diff -druNp linux-libre-3.1-gnu1/arch/alpha/include/asm/fcntl.h linux-libre-3.2-gnu1/arch/alpha/include/asm/fcntl.h
--- linux-libre-3.1-gnu1/arch/alpha/include/asm/fcntl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/include/asm/fcntl.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,8 +51,6 @@
 #define F_EXLCK		16	/* or 3 */
 #define F_SHLCK		32	/* or 4 */
 
-#define F_INPROGRESS	64
-
 #include <asm-generic/fcntl.h>
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/alpha/include/asm/unistd.h linux-libre-3.2-gnu1/arch/alpha/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/alpha/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -457,10 +457,12 @@
 #define __NR_clock_adjtime		499
 #define __NR_syncfs			500
 #define __NR_setns			501
+#define __NR_accept4			502
+#define __NR_sendmmsg			503
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS			502
+#define NR_SYSCALLS			504
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druNp linux-libre-3.1-gnu1/arch/alpha/Kconfig linux-libre-3.2-gnu1/arch/alpha/Kconfig
--- linux-libre-3.1-gnu1/arch/alpha/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -445,11 +445,6 @@ config ALPHA_EV67
 	  Is this a machine based on the EV67 core?  If in doubt, select N here
 	  and the machine will be treated as an EV6.
 
-config ALPHA_EV7
-	bool
-	depends on ALPHA_MARVEL
-	default y
-
 config ALPHA_MCPCIA
 	bool
 	depends on ALPHA_RAWHIDE
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/core_irongate.c linux-libre-3.2-gnu1/arch/alpha/kernel/core_irongate.c
--- linux-libre-3.1-gnu1/arch/alpha/kernel/core_irongate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/core_irongate.c	2012-01-04 18:55:44.000000000 -0500
@@ -303,6 +303,7 @@ irongate_init_arch(void)
 #include <linux/vmalloc.h>
 #include <linux/agp_backend.h>
 #include <linux/agpgart.h>
+#include <linux/export.h>
 #include <asm/pgalloc.h>
 
 #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/pci_iommu.c linux-libre-3.2-gnu1/arch/alpha/kernel/pci_iommu.c
--- linux-libre-3.1-gnu1/arch/alpha/kernel/pci_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/pci_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
 #include <linux/dma-mapping.h>
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/pci-sysfs.c linux-libre-3.2-gnu1/arch/alpha/kernel/pci-sysfs.c
--- linux-libre-3.1-gnu1/arch/alpha/kernel/pci-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/pci-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/stat.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/setup.c linux-libre-3.2-gnu1/arch/alpha/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/alpha/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <linux/log2.h>
+#include <linux/export.h>
 
 extern struct atomic_notifier_head panic_notifier_list;
 static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/srm_env.c linux-libre-3.2-gnu1/arch/alpha/kernel/srm_env.c
--- linux-libre-3.1-gnu1/arch/alpha/kernel/srm_env.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/srm_env.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,9 +4,8 @@
  *
  * (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
  *
- * This driver is at all a modified version of Erik Mouw's
- * Documentation/DocBook/procfs_example.c, so: thank
- * you, Erik! He can be reached via email at
+ * This driver is a modified version of Erik Mouw's example proc
+ * interface, so: thank you, Erik! He can be reached via email at
  * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
  * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
  * included a patch like this as well. Thanks for idea!
diff -druNp linux-libre-3.1-gnu1/arch/alpha/kernel/systbls.S linux-libre-3.2-gnu1/arch/alpha/kernel/systbls.S
--- linux-libre-3.1-gnu1/arch/alpha/kernel/systbls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/alpha/kernel/systbls.S	2012-01-04 18:55:44.000000000 -0500
@@ -520,6 +520,8 @@ sys_call_table:
 	.quad sys_clock_adjtime
 	.quad sys_syncfs			/* 500 */
 	.quad sys_setns
+	.quad sys_accept4
+	.quad sys_sendmmsg
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/atags_to_fdt.c linux-libre-3.2-gnu1/arch/arm/boot/compressed/atags_to_fdt.c
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/atags_to_fdt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/atags_to_fdt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+#include <asm/setup.h>
+#include <libfdt.h>
+
+static int node_offset(void *fdt, const char *node_path)
+{
+	int offset = fdt_path_offset(fdt, node_path);
+	if (offset == -FDT_ERR_NOTFOUND)
+		offset = fdt_add_subnode(fdt, 0, node_path);
+	return offset;
+}
+
+static int setprop(void *fdt, const char *node_path, const char *property,
+		   uint32_t *val_array, int size)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+static int setprop_string(void *fdt, const char *node_path,
+			  const char *property, const char *string)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop_string(fdt, offset, property, string);
+}
+
+static int setprop_cell(void *fdt, const char *node_path,
+			const char *property, uint32_t val)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+/*
+ * Convert and fold provided ATAGs into the provided FDT.
+ *
+ * REturn values:
+ *    = 0 -> pretend success
+ *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
+ *    < 0 -> error from libfdt
+ */
+int atags_to_fdt(void *atag_list, void *fdt, int total_space)
+{
+	struct tag *atag = atag_list;
+	uint32_t mem_reg_property[2 * NR_BANKS];
+	int memcount = 0;
+	int ret;
+
+	/* make sure we've got an aligned pointer */
+	if ((u32)atag_list & 0x3)
+		return 1;
+
+	/* if we get a DTB here we're done already */
+	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
+	       return 0;
+
+	/* validate the ATAG */
+	if (atag->hdr.tag != ATAG_CORE ||
+	    (atag->hdr.size != tag_size(tag_core) &&
+	     atag->hdr.size != 2))
+		return 1;
+
+	/* let's give it all the room it could need */
+	ret = fdt_open_into(fdt, fdt, total_space);
+	if (ret < 0)
+		return ret;
+
+	for_each_tag(atag, atag_list) {
+		if (atag->hdr.tag == ATAG_CMDLINE) {
+			setprop_string(fdt, "/chosen", "bootargs",
+					atag->u.cmdline.cmdline);
+		} else if (atag->hdr.tag == ATAG_MEM) {
+			if (memcount >= sizeof(mem_reg_property)/4)
+				continue;
+			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
+			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+		} else if (atag->hdr.tag == ATAG_INITRD2) {
+			uint32_t initrd_start, initrd_size;
+			initrd_start = atag->u.initrd.start;
+			initrd_size = atag->u.initrd.size;
+			setprop_cell(fdt, "/chosen", "linux,initrd-start",
+					initrd_start);
+			setprop_cell(fdt, "/chosen", "linux,initrd-end",
+					initrd_start + initrd_size);
+		}
+	}
+
+	if (memcount)
+		setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+
+	return fdt_pack(fdt);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/.gitignore linux-libre-3.2-gnu1/arch/arm/boot/compressed/.gitignore
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/.gitignore	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/.gitignore	2012-01-04 18:55:44.000000000 -0500
@@ -5,3 +5,12 @@ piggy.lzo
 piggy.lzma
 vmlinux
 vmlinux.lds
+
+# borrowed libfdt files
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/head.S linux-libre-3.2-gnu1/arch/arm/boot/compressed/head.S
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -216,6 +216,104 @@ restart:	adr	r0, LC0
 		mov	r10, r6
 #endif
 
+		mov	r5, #0			@ init dtb size to 0
+#ifdef CONFIG_ARM_APPENDED_DTB
+/*
+ *   r0  = delta
+ *   r2  = BSS start
+ *   r3  = BSS end
+ *   r4  = final kernel address
+ *   r5  = appended dtb size (still unknown)
+ *   r6  = _edata
+ *   r7  = architecture ID
+ *   r8  = atags/device tree pointer
+ *   r9  = size of decompressed image
+ *   r10 = end of this image, including  bss/stack/malloc space if non XIP
+ *   r11 = GOT start
+ *   r12 = GOT end
+ *   sp  = stack pointer
+ *
+ * if there are device trees (dtb) appended to zImage, advance r10 so that the
+ * dtb data will get relocated along with the kernel if necessary.
+ */
+
+		ldr	lr, [r6, #0]
+#ifndef __ARMEB__
+		ldr	r1, =0xedfe0dd0		@ sig is 0xd00dfeed big endian
+#else
+		ldr	r1, =0xd00dfeed
+#endif
+		cmp	lr, r1
+		bne	dtb_check_done		@ not found
+
+#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
+		/*
+		 * OK... Let's do some funky business here.
+		 * If we do have a DTB appended to zImage, and we do have
+		 * an ATAG list around, we want the later to be translated
+		 * and folded into the former here.  To be on the safe side,
+		 * let's temporarily move  the stack away into the malloc
+		 * area.  No GOT fixup has occurred yet, but none of the
+		 * code we're about to call uses any global variable.
+		*/
+		add	sp, sp, #0x10000
+		stmfd	sp!, {r0-r3, ip, lr}
+		mov	r0, r8
+		mov	r1, r6
+		sub	r2, sp, r6
+		bl	atags_to_fdt
+
+		/*
+		 * If returned value is 1, there is no ATAG at the location
+		 * pointed by r8.  Try the typical 0x100 offset from start
+		 * of RAM and hope for the best.
+		 */
+		cmp	r0, #1
+		sub	r0, r4, #TEXT_OFFSET
+		add	r0, r0, #0x100
+		mov	r1, r6
+		sub	r2, sp, r6
+		blne	atags_to_fdt
+
+		ldmfd	sp!, {r0-r3, ip, lr}
+		sub	sp, sp, #0x10000
+#endif
+
+		mov	r8, r6			@ use the appended device tree
+
+		/*
+		 * Make sure that the DTB doesn't end up in the final
+		 * kernel's .bss area. To do so, we adjust the decompressed
+		 * kernel size to compensate if that .bss size is larger
+		 * than the relocated code.
+		 */
+		ldr	r5, =_kernel_bss_size
+		adr	r1, wont_overwrite
+		sub	r1, r6, r1
+		subs	r1, r5, r1
+		addhi	r9, r9, r1
+
+		/* Get the dtb's size */
+		ldr	r5, [r6, #4]
+#ifndef __ARMEB__
+		/* convert r5 (dtb size) to little endian */
+		eor	r1, r5, r5, ror #16
+		bic	r1, r1, #0x00ff0000
+		mov	r5, r5, ror #8
+		eor	r5, r5, r1, lsr #8
+#endif
+
+		/* preserve 64-bit alignment */
+		add	r5, r5, #7
+		bic	r5, r5, #7
+
+		/* relocate some pointers past the appended dtb */
+		add	r6, r6, r5
+		add	r10, r10, r5
+		add	sp, sp, r5
+dtb_check_done:
+#endif
+
 /*
  * Check to see if we will overwrite ourselves.
  *   r4  = final kernel address
@@ -223,15 +321,14 @@ restart:	adr	r0, LC0
  *   r10 = end of this image, including  bss/stack/malloc space if non XIP
  * We basically want:
  *   r4 - 16k page directory >= r10 -> OK
- *   r4 + image length <= current position (pc) -> OK
+ *   r4 + image length <= address of wont_overwrite -> OK
  */
 		add	r10, r10, #16384
 		cmp	r4, r10
 		bhs	wont_overwrite
 		add	r10, r4, r9
-   ARM(		cmp	r10, pc		)
- THUMB(		mov	lr, pc		)
- THUMB(		cmp	r10, lr		)
+		adr	r9, wont_overwrite
+		cmp	r10, r9
 		bls	wont_overwrite
 
 /*
@@ -285,14 +382,16 @@ wont_overwrite:
  *   r2  = BSS start
  *   r3  = BSS end
  *   r4  = kernel execution address
+ *   r5  = appended dtb size (0 if not present)
  *   r7  = architecture ID
  *   r8  = atags pointer
  *   r11 = GOT start
  *   r12 = GOT end
  *   sp  = stack pointer
  */
-		teq	r0, #0
+		orrs	r1, r0, r5
 		beq	not_relocated
+
 		add	r11, r11, r0
 		add	r12, r12, r0
 
@@ -307,12 +406,21 @@ wont_overwrite:
 
 		/*
 		 * Relocate all entries in the GOT table.
+		 * Bump bss entries to _edata + dtb size
 		 */
 1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
-		add	r1, r1, r0		@ table.  This fixes up the
-		str	r1, [r11], #4		@ C references.
+		add	r1, r1, r0		@ This fixes up C references
+		cmp	r1, r2			@ if entry >= bss_start &&
+		cmphs	r3, r1			@       bss_end > entry
+		addhi	r1, r1, r5		@    entry += dtb size
+		str	r1, [r11], #4		@ next entry
 		cmp	r11, r12
 		blo	1b
+
+		/* bump our bss pointers too */
+		add	r2, r2, r5
+		add	r3, r3, r5
+
 #else
 
 		/*
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/libfdt_env.h linux-libre-3.2-gnu1/arch/arm/boot/compressed/libfdt_env.h
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/libfdt_env.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/libfdt_env.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+#ifndef _ARM_LIBFDT_ENV_H
+#define _ARM_LIBFDT_ENV_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#define fdt16_to_cpu(x)		be16_to_cpu(x)
+#define cpu_to_fdt16(x)		cpu_to_be16(x)
+#define fdt32_to_cpu(x)		be32_to_cpu(x)
+#define cpu_to_fdt32(x)		cpu_to_be32(x)
+#define fdt64_to_cpu(x)		be64_to_cpu(x)
+#define cpu_to_fdt64(x)		cpu_to_be64(x)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/Makefile linux-libre-3.2-gnu1/arch/arm/boot/compressed/Makefile
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,10 @@ HEAD	= head.o
 OBJS	+= misc.o decompress.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
+# string library code (-Os is enforced to keep it much smaller)
+OBJS		+= string.o
+CFLAGS_string.o	:= -Os
+
 #
 # Architecture dependencies
 #
@@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
 
+# Borrowed libfdt files for the ATAG compatibility mode
+
+libfdt		:= fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
+libfdt_hdrs	:= fdt.h libfdt.h libfdt_internal.h
+
+libfdt_objs	:= $(addsuffix .o, $(basename $(libfdt)))
+
+$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+	$(call cmd,shipped)
+
+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
+	$(addprefix $(obj)/,$(libfdt_hdrs))
+
+ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
+OBJS	+= $(libfdt_objs) atags_to_fdt.o
+endif
+
 targets       := vmlinux vmlinux.lds \
 		 piggy.$(suffix_y) piggy.$(suffix_y).o \
-		 font.o font.c head.o misc.o $(OBJS)
+		 lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
+extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-ccflags-y := -fpic -fno-builtin
+ccflags-y := -fpic -fno-builtin -I$(obj)
 asflags-y := -Wa,-march=all
 
+# Supply kernel BSS size to the decompressor via a linker symbol.
+KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
+LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
 LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
@@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T
 # For __aeabi_uidivmod
 lib1funcs = $(obj)/lib1funcs.o
 
-$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
 	$(call cmd,shipped)
 
 # We need to prevent any GOTOFF relocs being used with references
@@ -139,8 +163,16 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed
   ( echo "following symbols must have non local/private scope:" >&2; \
     echo "$$bad_syms" >&2; rm -f $@; false )
 
+check_for_multiple_zreladdr = \
+if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
+	echo 'multiple zreladdrs: $(ZRELADDR)'; \
+	echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \
+	false; \
+fi
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/misc.c linux-libre-3.2-gnu1/arch/arm/boot/compressed/misc.c
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,9 @@
 
 unsigned int __machine_arch_type;
 
-#define _LINUX_STRING_H_
-
 #include <linux/compiler.h>	/* for inline */
-#include <linux/types.h>	/* for size_t */
-#include <linux/stddef.h>	/* for NULL */
+#include <linux/types.h>
 #include <linux/linkage.h>
-#include <asm/string.h>
-
 
 static void putstr(const char *ptr);
 extern void error(char *x);
@@ -101,41 +96,6 @@ static void putstr(const char *ptr)
 	flush();
 }
 
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
-	int i = 0;
-	unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
-
-	for (i = __n >> 3; i > 0; i--) {
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-	}
-
-	if (__n & 1 << 2) {
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-		*d++ = *s++;
-	}
-
-	if (__n & 1 << 1) {
-		*d++ = *s++;
-		*d++ = *s++;
-	}
-
-	if (__n & 1)
-		*d++ = *s++;
-
-	return __dest;
-}
-
 /*
  * gzip declarations
  */
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/string.c linux-libre-3.2-gnu1/arch/arm/boot/compressed/string.c
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/string.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/string.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/boot/compressed/string.c
+ *
+ * Small subset of simple string routines
+ */
+
+#include <linux/string.h>
+
+void *memcpy(void *__dest, __const void *__src, size_t __n)
+{
+	int i = 0;
+	unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
+
+	for (i = __n >> 3; i > 0; i--) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (__n & 1 << 2) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (__n & 1 << 1) {
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (__n & 1)
+		*d++ = *s++;
+
+	return __dest;
+}
+
+void *memmove(void *__dest, __const void *__src, size_t count)
+{
+	unsigned char *d = __dest;
+	const unsigned char *s = __src;
+
+	if (__dest == __src)
+		return __dest;
+
+	if (__dest < __src)
+		return memcpy(__dest, __src, count);
+
+	while (count--)
+		d[count] = s[count];
+	return __dest;
+}
+
+size_t strlen(const char *s)
+{
+	const char *sc = s;
+
+	while (*sc != '\0')
+		sc++;
+	return sc - s;
+}
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+	const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
+	int res = 0;
+
+	while (su1 < end) {
+		res = *su1++ - *su2++;
+		if (res)
+			break;
+	}
+	return res;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+	unsigned char c1, c2;
+	int res = 0;
+
+	do {
+		c1 = *cs++;
+		c2 = *ct++;
+		res = c1 - c2;
+		if (res)
+			break;
+	} while (c1);
+	return res;
+}
+
+void *memchr(const void *s, int c, size_t count)
+{
+	const unsigned char *p = s;
+
+	while (count--)
+		if ((unsigned char)c == *p++)
+			return (void *)(p - 1);
+	return NULL;
+}
+
+char *strchr(const char *s, int c)
+{
+	while (*s != (char)c)
+		if (*s++ == '\0')
+			return NULL;
+	return (char *)s;
+}
+
+#undef memset
+
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+	while (count--)
+		*xs++ = c;
+	return s;
+}
+
+void __memzero(void *s, size_t count)
+{
+	memset(s, 0, count);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/compressed/vmlinux.lds.in linux-libre-3.2-gnu1/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-libre-3.1-gnu1/arch/arm/boot/compressed/vmlinux.lds.in	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/compressed/vmlinux.lds.in	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,10 @@ SECTIONS
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
+
+  /* ensure the zImage file size is always a multiple of 64 bits */
+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad			: { BYTE(0); . = ALIGN(8); }
   _edata = .;
 
   . = BSS_START;
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9g20.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9g20.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9g20.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9g20.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,119 @@
+/*
+ * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ *                2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G20 family SoC";
+	compatible = "atmel,at91sam9g20";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+		serial5 = &usart4;
+		serial6 = &usart5;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x08000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dbgu: serial@fffff200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffff200 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fffb0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb0000 0x200>;
+				interrupts = <6>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fffb4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb4000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fffb8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb8000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fffd0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd0000 0x200>;
+				interrupts = <23>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart4: serial@fffd4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd4000 0x200>;
+				interrupts = <24>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart5: serial@fffd8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd8000 0x200>;
+				interrupts = <25>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9g45.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9g45.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9g45.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/*
+ * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC
+ *                    applies to AT91SAM9G45, AT91SAM9M10,
+ *                    AT91SAM9G46, AT91SAM9M11 SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G45 family SoC";
+	compatible = "atmel,at91sam9g45";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x10000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dma: dma-controller@ffffec00 {
+				compatible = "atmel,at91sam9g45-dma";
+				reg = <0xffffec00 0x200>;
+				interrupts = <21>;
+			};
+
+			dbgu: serial@ffffee00 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xffffee00 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fff8c000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff8c000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fff90000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff90000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fff94000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff94000 0x200>;
+				interrupts = <9>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fff98000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff98000 0x200>;
+				interrupts = <10>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9m10g45ek.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9m10g45ek.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/at91sam9m10g45ek.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/at91sam9m10g45ek.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9M10G45-EK";
+	compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@ffffee00 {
+				status = "okay";
+			};
+
+			usart1: serial@fff90000 {
+				status = "okay";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/highbank.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/highbank.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/highbank.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/highbank.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+	model = "Calxeda Highbank";
+	compatible = "calxeda,highbank";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x00000000 0xff900000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyAMA0";
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@fff10600 {
+			compatible = "arm,smp-twd";
+			reg = <0xfff10600 0x20>;
+			interrupts = <1 13 0xf04>;
+		};
+
+		watchdog@fff10620 {
+			compatible = "arm,cortex-a9-wdt";
+			reg = <0xfff10620 0x20>;
+			interrupts = <1 14 0xf04>;
+		};
+
+		intc: interrupt-controller@fff11000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#size-cells = <0>;
+			#address-cells = <1>;
+			interrupt-controller;
+			interrupt-parent;
+			reg = <0xfff11000 0x1000>,
+			      <0xfff10100 0x100>;
+		};
+
+		L2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xfff12000 0x1000>;
+			interrupts = <0 70 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
+		};
+
+		sata@ffe08000 {
+			compatible = "calxeda,hb-ahci";
+			reg = <0xffe08000 0x10000>;
+			interrupts = <0 83 4>;
+		};
+
+		sdhci@ffe0e000 {
+			compatible = "calxeda,hb-sdhci";
+			reg = <0xffe0e000 0x1000>;
+			interrupts = <0 90 4>;
+		};
+
+		ipc@fff20000 {
+			compatible = "arm,pl320", "arm,primecell";
+			reg = <0xfff20000 0x1000>;
+			interrupts = <0 7 4>;
+		};
+
+		gpioe: gpio@fff30000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff30000 0x1000>;
+			interrupts = <0 14 4>;
+		};
+
+		gpiof: gpio@fff31000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff31000 0x1000>;
+			interrupts = <0 15 4>;
+		};
+
+		gpiog: gpio@fff32000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff32000 0x1000>;
+			interrupts = <0 16 4>;
+		};
+
+		gpioh: gpio@fff33000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff33000 0x1000>;
+			interrupts = <0 17 4>;
+		};
+
+		timer {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfff34000 0x1000>;
+			interrupts = <0 18 4>;
+		};
+
+		rtc@fff35000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0xfff35000 0x1000>;
+			interrupts = <0 19 4>;
+		};
+
+		serial@fff36000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfff36000 0x1000>;
+			interrupts = <0 20 4>;
+		};
+
+		smic@fff3a000 {
+			compatible = "ipmi-smic";
+			device_type = "ipmi";
+			reg = <0xfff3a000 0x1000>;
+			interrupts = <0 24 4>;
+			reg-size = <4>;
+			reg-spacing = <4>;
+		};
+
+		sregs@fff3c000 {
+			compatible = "calxeda,hb-sregs";
+			reg = <0xfff3c000 0x1000>;
+		};
+
+		dma@fff3d000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xfff3d000 0x1000>;
+			interrupts = <0 92 4>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx51-babbage.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx51-babbage.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx51-babbage.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx51-babbage.dts	2013-05-01 23:41:55.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx51.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage Board";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	soc {
+		aips@70000000 { /* aips-1 */
+			spba@70000000 {
+				esdhc@70004000 { /* ESDHC1 */
+					fsl,cd-internal;
+					fsl,wp-internal;
+					status = "okay";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+					wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+					status = "okay";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+						   <&gpio3 25 0>; /* GPIO4_25 */
+					status = "okay";
+
+					pmic: mc13892@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "fsl,mc13892";
+						spi-max-frequency = <6000000>;
+						reg = <0>;
+						mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
+						fsl,mc13xxx-uses-regulator;
+					};
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@73fa8000 {
+				compatible = "fsl,imx51-iomuxc-babbage";
+				reg = <0x73fa8000 0x4000>;
+			};
+
+			uart0: uart@73fbc000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			uart1: uart@73fc0000 {
+				status = "okay";
+			};
+		};
+
+		aips@80000000 {	/* aips-2 */
+			sdma@83fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@83fec000 {
+				phy-mode = "mii";
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 21 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx51.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/imx51.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx51.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx51.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@70000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x10000000>;
+			ranges;
+
+			spba@70000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x70000000 0x40000>;
+				ranges;
+
+				esdhc@70004000 { /* ESDHC1 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+					reg = <0x7000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx51-ecspi";
+					reg = <0x70010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@70020000 { /* ESDHC3 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@70024000 { /* ESDHC4 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@73f84000 { /* GPIO1 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@73f88000 { /* GPIO2 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@73f8c000 { /* GPIO3 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@73f90000 { /* GPIO4 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@73f9c000 { /* WDOG2 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@73fbc000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@73fc0000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+		};
+
+		aips@80000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x10000000>;
+			ranges;
+
+			ecspi@83fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-ecspi";
+				reg = <0x83fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@83fb0000 {
+				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+				reg = <0x83fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@83fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+				reg = <0x83fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@83fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@83fec000 {
+				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+				reg = <0x83fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-ard.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-ard.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-ard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-ard.dts	2013-05-01 23:41:57.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Automotive Reference Design Board";
+	compatible = "fsl,imx53-ard", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */
+					wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-ard";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+		};
+	};
+
+	eim-cs1@f4000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,eim-bus", "simple-bus";
+		reg = <0xf4000000 0x3ff0000>;
+		ranges;
+
+		lan9220@f4000000 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <0xf4000000 0x2000000>;
+			phy-mode = "mii";
+			interrupt-parent = <&gpio1>;
+			interrupts = <31>;
+			reg-io-width = <4>;
+			smsc,irq-push-pull;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "Home";
+			gpios = <&gpio4 10 0>; /* GPIO5_10 */
+			linux,code = <102>; /* KEY_HOME */
+			gpio-key,wakeup;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio4 11 0>; /* GPIO5_11 */
+			linux,code = <158>; /* KEY_BACK */
+			gpio-key,wakeup;
+		};
+
+		program {
+			label = "Program";
+			gpios = <&gpio4 12 0>; /* GPIO5_12 */
+			linux,code = <362>; /* KEY_PROGRAM */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio4 13 0>; /* GPIO5_13 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio3 0 0>; /* GPIO4_0 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	tzic: tz-interrupt-controller@0fffc000 {
+		compatible = "fsl,imx53-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x0fffc000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@50000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x10000000>;
+			ranges;
+
+			spba@50000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x50000000 0x40000>;
+				ranges;
+
+				esdhc@50004000 { /* ESDHC1 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+					reg = <0x5000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+					reg = <0x50010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@50024000 { /* ESDHC4 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@53f84000 { /* GPIO1 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@53f88000 { /* GPIO2 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@53f8c000 { /* GPIO3 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@53f90000 { /* GPIO4 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@53f9c000 { /* WDOG2 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+
+			gpio4: gpio@53fdc000 { /* GPIO5 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fdc000 0x4000>;
+				interrupts = <103 104>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@53fe0000 { /* GPIO6 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe0000 0x4000>;
+				interrupts = <105 106>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@53fe4000 { /* GPIO7 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe4000 0x4000>;
+				interrupts = <107 108>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			i2c@53fec000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x53fec000 0x4000>;
+				interrupts = <64>;
+				status = "disabled";
+			};
+
+			uart3: uart@53ff0000 { /* UART4 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <13>;
+				status = "disabled";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x60000000 0x10000000>;
+			ranges;
+
+			uart4: uart@63f90000 { /* UART5 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x63f90000 0x4000>;
+				interrupts = <86>;
+				status = "disabled";
+			};
+
+			ecspi@63fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+				reg = <0x63fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@63fb0000 {
+				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+				reg = <0x63fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@63fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+				reg = <0x63fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@63fec000 {
+				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+				reg = <0x63fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-evk.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-evk.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-evk.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-evk.dts	2013-05-01 23:41:59.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Evaluation Kit";
+	compatible = "fsl,imx53-evk", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x80000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-evk";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				pmic: mc13892@08 {
+					compatible = "fsl,mc13892", "fsl,mc13xxx";
+					reg = <0x08>;
+				};
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		green {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-qsb.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-qsb.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-qsb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-qsb.dts	2013-05-01 23:42:01.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Quick Start Board";
+	compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					status = "okay";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-qsb";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio0 8 0>; /* GPIO1_8 */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-smd.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-smd.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx53-smd.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx53-smd.dts	2013-05-01 23:42:03.000000000 -0400
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+	compatible = "fsl,imx53-smd", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */
+					status = "okay";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					fsl,card-wired;
+					status = "okay";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					zigbee: mc1323@0 {
+						compatible = "fsl,mc1323";
+						spi-max-frequency = <8000000>;
+						reg = <0>;
+					};
+
+					flash: m25p32@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "st,m25p32", "st,m25p";
+						spi-max-frequency = <20000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					fsl,card-wired;
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-smd";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+
+				magnetometer: mag3110@0e {
+					compatible = "fsl,mag3110";
+					reg = <0x0e>;
+				};
+
+				touchkey: mpr121@5a {
+					compatible = "fsl,mpr121";
+					reg = <0x5a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				camera: ov5642@3c {
+					compatible = "ovti,ov5642";
+					reg = <0x3c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx6q.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/imx6q.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx6q.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx6q.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	intc: interrupt-controller@00a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-controller;
+		reg = <0x00a01000 0x1000>,
+		      <0x00a00100 0x100>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@00a00600 {
+			compatible = "arm,smp-twd";
+			reg = <0x00a00600 0x100>;
+			interrupts = <1 13 0xf4>;
+		};
+
+		L2: l2-cache@00a02000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a02000 0x1000>;
+			interrupts = <0 92 0x04>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		aips-bus@02000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02000000 0x100000>;
+			ranges;
+
+			spba-bus@02000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02000000 0x40000>;
+				ranges;
+
+				spdif@02004000 {
+					reg = <0x02004000 0x4000>;
+					interrupts = <0 52 0x04>;
+				};
+
+				ecspi@02008000 { /* eCSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02008000 0x4000>;
+					interrupts = <0 31 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@0200c000 { /* eCSPI2 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x0200c000 0x4000>;
+					interrupts = <0 32 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02010000 { /* eCSPI3 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02010000 0x4000>;
+					interrupts = <0 33 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02014000 { /* eCSPI4 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02014000 0x4000>;
+					interrupts = <0 34 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02018000 { /* eCSPI5 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02018000 0x4000>;
+					interrupts = <0 35 0x04>;
+					status = "disabled";
+				};
+
+				uart0: uart@02020000 { /* UART1 */
+					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+					reg = <0x02020000 0x4000>;
+					interrupts = <0 26 0x04>;
+					status = "disabled";
+				};
+
+				esai@02024000 {
+					reg = <0x02024000 0x4000>;
+					interrupts = <0 51 0x04>;
+				};
+
+				ssi@02028000 { /* SSI1 */
+					reg = <0x02028000 0x4000>;
+					interrupts = <0 46 0x04>;
+				};
+
+				ssi@0202c000 { /* SSI2 */
+					reg = <0x0202c000 0x4000>;
+					interrupts = <0 47 0x04>;
+				};
+
+				ssi@02030000 { /* SSI3 */
+					reg = <0x02030000 0x4000>;
+					interrupts = <0 48 0x04>;
+				};
+
+				asrc@02034000 {
+					reg = <0x02034000 0x4000>;
+					interrupts = <0 50 0x04>;
+				};
+
+				spba@0203c000 {
+					reg = <0x0203c000 0x4000>;
+				};
+			};
+
+			vpu@02040000 {
+				reg = <0x02040000 0x3c000>;
+				interrupts = <0 3 0x04 0 12 0x04>;
+			};
+
+			aipstz@0207c000 { /* AIPSTZ1 */
+				reg = <0x0207c000 0x4000>;
+			};
+
+			pwm@02080000 { /* PWM1 */
+				reg = <0x02080000 0x4000>;
+				interrupts = <0 83 0x04>;
+			};
+
+			pwm@02084000 { /* PWM2 */
+				reg = <0x02084000 0x4000>;
+				interrupts = <0 84 0x04>;
+			};
+
+			pwm@02088000 { /* PWM3 */
+				reg = <0x02088000 0x4000>;
+				interrupts = <0 85 0x04>;
+			};
+
+			pwm@0208c000 { /* PWM4 */
+				reg = <0x0208c000 0x4000>;
+				interrupts = <0 86 0x04>;
+			};
+
+			flexcan@02090000 { /* CAN1 */
+				reg = <0x02090000 0x4000>;
+				interrupts = <0 110 0x04>;
+			};
+
+			flexcan@02094000 { /* CAN2 */
+				reg = <0x02094000 0x4000>;
+				interrupts = <0 111 0x04>;
+			};
+
+			gpt@02098000 {
+				compatible = "fsl,imx6q-gpt";
+				reg = <0x02098000 0x4000>;
+				interrupts = <0 55 0x04>;
+			};
+
+			gpio0: gpio@0209c000 { /* GPIO1 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x0209c000 0x4000>;
+				interrupts = <0 66 0x04 0 67 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@020a0000 { /* GPIO2 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a0000 0x4000>;
+				interrupts = <0 68 0x04 0 69 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@020a4000 { /* GPIO3 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a4000 0x4000>;
+				interrupts = <0 70 0x04 0 71 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@020a8000 { /* GPIO4 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a8000 0x4000>;
+				interrupts = <0 72 0x04 0 73 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio4: gpio@020ac000 { /* GPIO5 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020ac000 0x4000>;
+				interrupts = <0 74 0x04 0 75 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@020b0000 { /* GPIO6 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b0000 0x4000>;
+				interrupts = <0 76 0x04 0 77 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@020b4000 { /* GPIO7 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b4000 0x4000>;
+				interrupts = <0 78 0x04 0 79 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			kpp@020b8000 {
+				reg = <0x020b8000 0x4000>;
+				interrupts = <0 82 0x04>;
+			};
+
+			wdog@020bc000 { /* WDOG1 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020bc000 0x4000>;
+				interrupts = <0 80 0x04>;
+				status = "disabled";
+			};
+
+			wdog@020c0000 { /* WDOG2 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020c0000 0x4000>;
+				interrupts = <0 81 0x04>;
+				status = "disabled";
+			};
+
+			ccm@020c4000 {
+				compatible = "fsl,imx6q-ccm";
+				reg = <0x020c4000 0x4000>;
+				interrupts = <0 87 0x04 0 88 0x04>;
+			};
+
+			anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop";
+				reg = <0x020c8000 0x1000>;
+				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+			};
+
+			usbphy@020c9000 { /* USBPHY1 */
+				reg = <0x020c9000 0x1000>;
+				interrupts = <0 44 0x04>;
+			};
+
+			usbphy@020ca000 { /* USBPHY2 */
+				reg = <0x020ca000 0x1000>;
+				interrupts = <0 45 0x04>;
+			};
+
+			snvs@020cc000 {
+				reg = <0x020cc000 0x4000>;
+				interrupts = <0 19 0x04 0 20 0x04>;
+			};
+
+			epit@020d0000 { /* EPIT1 */
+				reg = <0x020d0000 0x4000>;
+				interrupts = <0 56 0x04>;
+			};
+
+			epit@020d4000 { /* EPIT2 */
+				reg = <0x020d4000 0x4000>;
+				interrupts = <0 57 0x04>;
+			};
+
+			src@020d8000 {
+				compatible = "fsl,imx6q-src";
+				reg = <0x020d8000 0x4000>;
+				interrupts = <0 91 0x04 0 96 0x04>;
+			};
+
+			gpc@020dc000 {
+				compatible = "fsl,imx6q-gpc";
+				reg = <0x020dc000 0x4000>;
+				interrupts = <0 89 0x04 0 90 0x04>;
+			};
+
+			iomuxc@020e0000 {
+				reg = <0x020e0000 0x4000>;
+			};
+
+			dcic@020e4000 { /* DCIC1 */
+				reg = <0x020e4000 0x4000>;
+				interrupts = <0 124 0x04>;
+			};
+
+			dcic@020e8000 { /* DCIC2 */
+				reg = <0x020e8000 0x4000>;
+				interrupts = <0 125 0x04>;
+			};
+
+			sdma@020ec000 {
+				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+				reg = <0x020ec000 0x4000>;
+				interrupts = <0 2 0x04>;
+			};
+		};
+
+		aips-bus@02100000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02100000 0x100000>;
+			ranges;
+
+			caam@02100000 {
+				reg = <0x02100000 0x40000>;
+				interrupts = <0 105 0x04 0 106 0x04>;
+			};
+
+			aipstz@0217c000 { /* AIPSTZ2 */
+				reg = <0x0217c000 0x4000>;
+			};
+
+			enet@02188000 {
+				compatible = "fsl,imx6q-fec";
+				reg = <0x02188000 0x4000>;
+				interrupts = <0 118 0x04 0 119 0x04>;
+				status = "disabled";
+			};
+
+			mlb@0218c000 {
+				reg = <0x0218c000 0x4000>;
+				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+			};
+
+			usdhc@02190000 { /* uSDHC1 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02190000 0x4000>;
+				interrupts = <0 22 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02194000 { /* uSDHC2 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02194000 0x4000>;
+				interrupts = <0 23 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02198000 0x4000>;
+				interrupts = <0 24 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x0219c000 0x4000>;
+				interrupts = <0 25 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a0000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a0000 0x4000>;
+				interrupts = <0 36 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a4000 0x4000>;
+				interrupts = <0 37 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a8000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a8000 0x4000>;
+				interrupts = <0 38 0x04>;
+				status = "disabled";
+			};
+
+			romcp@021ac000 {
+				reg = <0x021ac000 0x4000>;
+			};
+
+			mmdc@021b0000 { /* MMDC0 */
+				compatible = "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+
+			mmdc@021b4000 { /* MMDC1 */
+				reg = <0x021b4000 0x4000>;
+			};
+
+			weim@021b8000 {
+				reg = <0x021b8000 0x4000>;
+				interrupts = <0 14 0x04>;
+			};
+
+			ocotp@021bc000 {
+				reg = <0x021bc000 0x4000>;
+			};
+
+			ocotp@021c0000 {
+				reg = <0x021c0000 0x4000>;
+				interrupts = <0 21 0x04>;
+			};
+
+			tzasc@021d0000 { /* TZASC1 */
+				reg = <0x021d0000 0x4000>;
+				interrupts = <0 108 0x04>;
+			};
+
+			tzasc@021d4000 { /* TZASC2 */
+				reg = <0x021d4000 0x4000>;
+				interrupts = <0 109 0x04>;
+			};
+
+			audmux@021d8000 {
+				reg = <0x021d8000 0x4000>;
+			};
+
+			mipi@021dc000 { /* MIPI-CSI */
+				reg = <0x021dc000 0x4000>;
+			};
+
+			mipi@021e0000 { /* MIPI-DSI */
+				reg = <0x021e0000 0x4000>;
+			};
+
+			vdoa@021e4000 {
+				reg = <0x021e4000 0x4000>;
+				interrupts = <0 18 0x04>;
+			};
+
+			uart1: uart@021e8000 { /* UART2 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021e8000 0x4000>;
+				interrupts = <0 27 0x04>;
+				status = "disabled";
+			};
+
+			uart2: uart@021ec000 { /* UART3 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021ec000 0x4000>;
+				interrupts = <0 28 0x04>;
+				status = "disabled";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f0000 0x4000>;
+				interrupts = <0 29 0x04>;
+				status = "disabled";
+			};
+
+			uart4: uart@021f4000 { /* UART5 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f4000 0x4000>;
+				interrupts = <0 30 0x04>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/imx6q-sabreauto.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/imx6q-sabreauto.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/imx6q-sabreauto.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/imx6q-sabreauto.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Automotive Board";
+	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
+	};
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	soc {
+		aips-bus@02100000 { /* AIPS2 */
+			enet@02188000 {
+				phy-mode = "rgmii";
+				local-mac-address = [00 04 9F 01 1B 61];
+				status = "okay";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
+				wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
+				status = "okay";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				fsl,card-wired;
+				status = "okay";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		debug-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 25 0>; /* GPIO3_25 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/msm8660-surf.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/msm8660-surf.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/msm8660-surf.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/msm8660-surf.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM8660 SURF";
+	compatible = "qcom,msm8660-surf", "qcom,msm8660";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@02080000 {
+		compatible = "qcom,msm-8660-qgic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = < 0x02080000 0x1000 >,
+		      < 0x02081000 0x1000 >;
+	};
+
+	serial@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/omap3-beagle.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/omap3-beagle.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/omap3-beagle.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/omap3-beagle.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+	model = "TI OMAP3 BeagleBoard";
+	compatible = "ti,omap3-beagle", "ti,omap3";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/omap3.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/omap3.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/omap3.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/omap3.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap3430", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a8";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap3-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		iva {
+			compatible = "ti,iva2.2";
+			ti,hwmods = "iva";
+
+			dsp {
+				compatible = "ti,omap3-c64";
+			};
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP3 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main";
+
+		intc: interrupt-controller@1 {
+			compatible = "ti,omap3-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap4430", "ti,omap4";
+	interrupt-parent = <&gic>;
+
+	aliases {
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap4-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		dsp {
+			compatible = "ti,omap3-c64";
+			ti,hwmods = "dsp";
+		};
+
+		iva {
+			compatible = "ti,ivahd";
+			ti,hwmods = "iva";
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP4 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 *
+	 * MPU -+-- MPU_PRIVATE - GIC, L2
+	 *      |
+	 *      +----------------+----------+
+	 *      |                |          |
+	 *      +            +- EMIF - DDR  |
+	 *      |            |              |
+	 *      |            +     +--------+
+	 *      |            |     |
+	 *      |            +- L4_ABE - AESS, MCBSP, TIMERs...
+	 *      |            |
+	 *      +- L3_MAIN --+- L4_CORE - IPs...
+	 *                   |
+	 *                   +- L4_PER - IPs...
+	 *                   |
+	 *                   +- L4_CFG -+- L4_WKUP - IPs...
+	 *                   |          |
+	 *                   |          +- IPs...
+	 *                   +- IPU ----+
+	 *                   |          |
+	 *                   +- DSP ----+
+	 *                   |          |
+	 *                   +- DSS ----+
+	 *
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "ti,omap4-l3-noc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+		gic: interrupt-controller@48241000 {
+			compatible = "arm,cortex-a9-gic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x48241000 0x1000>,
+			      <0x48240100 0x0100>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4-panda.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4-panda.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4-panda.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4-panda.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 PandaBoard";
+	compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4-sdp.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4-sdp.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/omap4-sdp.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/omap4-sdp.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 SDP board";
+	compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc3x2.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc3x2.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc3x2.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X2";
+	compatible = "picochip,pc3x2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			clock-frequency = <400000000>;
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pclk: clock@0 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x2";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic1>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			timer2: timer@10028 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x10028 0x14>;
+			};
+
+			timer3: timer@1003c {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x1003c 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x2";
+			reg = <0xc0000000 0x10000>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc3x3.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc3x3.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc3x3.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,365 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X3";
+	compatible = "picochip,pc3x3";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			cpu-clock = <&arm_clk>, "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clkgate: clkgate@800a0048 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x800a0048 4>;
+			compatible = "picochip,pc3x3-clk-gate";
+
+			tzprot_clk: clock@0 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <0>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			spi_clk: clock@1 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <1>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac0_clk: clock@2 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <2>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac1_clk: clock@3 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <3>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ebi_clk: clock@4 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <4>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ipsec_clk: clock@5 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <5>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			l2_clk: clock@6 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <6>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			trng_clk: clock@7 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <7>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			fuse_clk: clock@8 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <8>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			otp_clk: clock@9 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <9>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+		};
+
+		arm_clk: clock@11 {
+			compatible = "picochip,pc3x3-pll";
+			reg = <0x800a0050 0x8>;
+			picochip,min-freq = <140000000>;
+			picochip,max-freq = <700000000>;
+			ref-clock = <&ref_clk>, "ref";
+			clock-outputs = "cpu";
+		};
+
+		pclk: clock@12 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x3";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&ipsec_clk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&l2_clk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic0>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <16>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+
+				bankd: gpio-controller@2 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <30>;
+
+					regoffset-dat = <0x5c>;
+					regoffset-set = <0x24>;
+					regoffset-dirout = <0x28>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+
+			timer2: timer@60000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x60000 0x14>;
+			};
+
+			timer3: timer@60014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x60014 0x14>;
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x3";
+			reg = <0xc0000000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+
+		otp@ffff8000 {
+			compatible = "picochip,otp-pc3x3";
+			reg = <0xffff8000 0x8000>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x2.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X2)";
+	compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@1 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&pclk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x3.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X3)";
+	compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@10 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+
+		clkgate: clkgate@800a0048 {
+			clock@4 {
+				picochip,clk-no-disable;
+			};
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&ebi_clk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/prima2-cb.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/prima2-cb.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/prima2-cb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/prima2-cb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -39,9 +39,12 @@
 		ranges = <0x40000000 0x40000000 0x80000000>;
 
 		l2-cache-controller@80040000 {
-			compatible = "arm,pl310-cache";
+			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
 			reg = <0x80040000 0x1000>;
 			interrupts = <59>;
+			arm,tag-latency = <1 1 1>;
+			arm,data-latency = <1 1 1>;
+			arm,filter-ranges = <0 0x40000000>;
 		};
 
 		intc: interrupt-controller@80020000 {
@@ -67,6 +70,11 @@
 				compatible = "sirf,prima2-rstc";
 				reg = <0x88010000 0x1000>;
 			};
+
+			rsc-controller@88020000 {
+				compatible = "sirf,prima2-rsc";
+				reg = <0x88020000 0x1000>;
+			};
 		};
 
 		mem-iobg {
@@ -274,7 +282,7 @@
 			gpio: gpio-controller@b0120000 {
 				#gpio-cells = <2>;
 				#interrupt-cells = <2>;
-				compatible = "sirf,prima2-gpio";
+				compatible = "sirf,prima2-gpio-pinmux";
 				reg = <0xb0120000 0x10000>;
 				gpio-controller;
 				interrupt-controller;
@@ -358,7 +366,7 @@
 		};
 
 		rtc-iobg {
-			compatible = "sirf,prima2-rtciobg", "simple-bus";
+			compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x80030000 0x10000>;
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra20.dtsi linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra20.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra20.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,14 @@
 		gpio-controller;
 	};
 
+	pinmux: pinmux@70000000 {
+		compatible = "nvidia,tegra20-pinmux";
+		reg = < 0x70000014 0x10    /* Tri-state registers */
+			0x70000080 0x20    /* Mux registers */
+			0x700000a0 0x14    /* Pull-up/down registers */
+			0x70000868 0xa8 >; /* Pad control registers */
+	};
+
 	serial@70006000 {
 		compatible = "nvidia,tegra20-uart";
 		reg = <0x70006000 0x40>;
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-harmony.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-harmony.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-harmony.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-harmony.dts	2012-01-04 18:55:44.000000000 -0500
@@ -66,5 +66,6 @@
 		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
 		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		support-8bit;
 	};
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-seaboard.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-seaboard.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-seaboard.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-seaboard.dts	2012-01-04 18:55:44.000000000 -0500
@@ -25,4 +25,8 @@
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 	};
+
+	sdhci@c8000600 {
+		support-8bit;
+	};
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-ventana.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-ventana.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/tegra-ventana.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/tegra-ventana.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Tegra2 Ventana evaluation board";
+	compatible = "nvidia,ventana", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+	};
+
+	memory {
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	serial@70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci@c8000400 {
+		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+	};
+
+	sdhci@c8000600 {
+		support-8bit;
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/dts/usb_a9g20.dts linux-libre-3.2-gnu1/arch/arm/boot/dts/usb_a9g20.dts
--- linux-libre-3.1-gnu1/arch/arm/boot/dts/usb_a9g20.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/boot/dts/usb_a9g20.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board
+ *
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+	model = "Calao USB A9G20";
+	compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/boot/Makefile linux-libre-3.2-gnu1/arch/arm/boot/Makefile
--- linux-libre-3.1-gnu1/arch/arm/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,8 @@ $(obj)/%.dtb: $(src)/dts/%.dts
 
 $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
 
+clean-files := *.dtb
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
 		   -C none -a $(LOADADDR) -e $(STARTADDR) \
@@ -78,7 +80,16 @@ endif
 
 $(obj)/uImage: STARTADDR=$(LOADADDR)
 
+check_for_multiple_loadaddr = \
+if [ $(words $(LOADADDR)) -gt 1 ]; then \
+	echo 'multiple load addresses: $(LOADADDR)'; \
+	echo 'This is incompatible with uImages'; \
+	echo 'Specify LOADADDR on the commandline to build an uImage'; \
+	false; \
+fi
+
 $(obj)/uImage:	$(obj)/zImage FORCE
+	@$(check_for_multiple_loadaddr)
 	$(call if_changed,uimage)
 	@echo '  Image $@ is ready'
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/gic.c linux-libre-3.2-gnu1/arch/arm/common/gic.c
--- linux-libre-3.1-gnu1/arch/arm/common/gic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/gic.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,16 +24,26 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/smp.h>
+#include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
-static DEFINE_SPINLOCK(irq_controller_lock);
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
@@ -71,8 +81,7 @@ static inline void __iomem *gic_cpu_base
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -80,32 +89,32 @@ static inline unsigned int gic_irq(struc
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
 	if (gic_arch_extn.irq_mask)
 		gic_arch_extn.irq_mask(d);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
 		gic_arch_extn.irq_unmask(d);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_eoi_irq(struct irq_data *d)
 {
 	if (gic_arch_extn.irq_eoi) {
-		spin_lock(&irq_controller_lock);
+		raw_spin_lock(&irq_controller_lock);
 		gic_arch_extn.irq_eoi(d);
-		spin_unlock(&irq_controller_lock);
+		raw_spin_unlock(&irq_controller_lock);
 	}
 
 	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
@@ -129,7 +138,7 @@ static int gic_set_type(struct irq_data
 	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
 		return -EINVAL;
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 
 	if (gic_arch_extn.irq_set_type)
 		gic_arch_extn.irq_set_type(d, type);
@@ -154,7 +163,7 @@ static int gic_set_type(struct irq_data
 	if (enabled)
 		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
 
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	return 0;
 }
@@ -172,7 +181,7 @@ static int gic_set_affinity(struct irq_d
 			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (d->irq % 4) * 8;
+	unsigned int shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -180,12 +189,12 @@ static int gic_set_affinity(struct irq_d
 		return -EINVAL;
 
 	mask = 0xff << shift;
-	bit = 1 << (cpu + shift);
+	bit = 1 << (cpu_logical_map(cpu) + shift);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	val = readl_relaxed(reg) & ~mask;
 	writel_relaxed(val | bit, reg);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	return IRQ_SET_MASK_OK;
 }
@@ -215,15 +224,15 @@ static void gic_handle_cascade_irq(unsig
 
 	chained_irq_enter(chip, desc);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	gic_irq = (status & 0x3ff);
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -255,28 +264,26 @@ void __init gic_cascade_irq(unsigned int
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int i, irq;
+	u32 cpumask;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
 	void __iomem *base = gic->dist_base;
-	u32 cpumask = 1 << smp_processor_id();
+	u32 cpu = 0;
+
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(smp_processor_id());
+#endif
 
+	cpumask = 1 << cpu;
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -302,19 +309,20 @@ static void __init gic_dist_init(struct
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		if (i < 32) {
+			irq_set_percpu_devid(irq);
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_percpu_devid_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+		} else {
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_fasteoi_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+		irq_set_chip_data(irq, gic);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -343,23 +351,274 @@ static void __cpuinit gic_cpu_init(struc
 	writel_relaxed(1, base + GIC_CPU_CTRL);
 }
 
-void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+#ifdef CONFIG_CPU_PM
+/*
+ * Saves the GIC distributor registers during suspend or idle.  Must be called
+ * with interrupts disabled but before powering down the GIC.  After calling
+ * this function, no interrupts will be delivered by the GIC, and another
+ * platform-specific wakeup source must be enabled.
+ */
+static void gic_dist_save(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	void __iomem *dist_base;
+	int i;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		gic_data[gic_nr].saved_spi_conf[i] =
+			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		gic_data[gic_nr].saved_spi_target[i] =
+			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		gic_data[gic_nr].saved_spi_enable[i] =
+			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+}
+
+/*
+ * Restores the GIC distributor registers during resume or when coming out of
+ * idle.  Must be called before enabling interrupts.  If a level interrupt
+ * that occured while the GIC was suspended is still present, it will be
+ * handled normally, but any edge interrupts that occured will not be seen by
+ * the GIC and need to be handled by the platform-specific wakeup source.
+ */
+static void gic_dist_restore(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	unsigned int i;
+	void __iomem *dist_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	writel_relaxed(0, dist_base + GIC_DIST_CTRL);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
+			dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(0xa0a0a0a0,
+			dist_base + GIC_DIST_PRI + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
+			dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
+			dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+}
+
+static void gic_cpu_save(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+}
+
+static void gic_cpu_restore(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+
+	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+}
+
+static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
+{
+	int i;
+
+	for (i = 0; i < MAX_GIC_NR; i++) {
+		switch (cmd) {
+		case CPU_PM_ENTER:
+			gic_cpu_save(i);
+			break;
+		case CPU_PM_ENTER_FAILED:
+		case CPU_PM_EXIT:
+			gic_cpu_restore(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER:
+			gic_dist_save(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER_FAILED:
+		case CPU_CLUSTER_PM_EXIT:
+			gic_dist_restore(i);
+			break;
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block gic_notifier_block = {
+	.notifier_call = gic_notifier,
+};
+
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+	gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_enable);
+
+	gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_conf);
+
+	if (gic == &gic_data[0])
+		cpu_pm_register_notifier(&gic_notifier_block);
+}
+#else
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+}
+#endif
+
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
+const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
+};
+
+void __init gic_init(unsigned int gic_nr, int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	domain->hwirq_base = 32;
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
 
-	gic_dist_init(gic, irq_start);
+		if ((irq_start & 31) > 0) {
+			domain->hwirq_base = 16;
+			if (irq_start != -1)
+				irq_start = (irq_start & ~31) + 16;
+		}
+	}
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
+					   numa_node_id());
+	if (IS_ERR_VALUE(domain->irq_base)) {
+		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+		     irq_start);
+		domain->irq_base = irq_start;
+	}
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
+
+	gic_chip.flags |= gic_arch_extn.flags;
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
+	gic_pm_init(gic);
 }
 
 void __cpuinit gic_secondary_init(unsigned int gic_nr)
@@ -369,20 +628,15 @@ void __cpuinit gic_secondary_init(unsign
 	gic_cpu_init(&gic_data[gic_nr]);
 }
 
-void __cpuinit gic_enable_ppi(unsigned int irq)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	irq_set_status_flags(irq, IRQ_NOPROBE);
-	gic_unmask_irq(irq_get_irq_data(irq));
-	local_irq_restore(flags);
-}
-
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
-	unsigned long map = *cpus_addr(*mask);
+	int cpu;
+	unsigned long map = 0;
+
+	/* Convert our logical CPU mask into a physical one. */
+	for_each_cpu(cpu, mask)
+		map |= 1 << cpu_logical_map(cpu);
 
 	/*
 	 * Ensure that stores to Normal memory are visible to the
@@ -394,3 +648,35 @@ void gic_raise_softirq(const struct cpum
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, -1, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/it8152.c linux-libre-3.2-gnu1/arch/arm/common/it8152.c
--- linux-libre-3.1-gnu1/arch/arm/common/it8152.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/it8152.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <asm/mach/pci.h>
 #include <asm/hardware/it8152.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/Kconfig linux-libre-3.2-gnu1/arch/arm/common/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/common/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/pl330.c linux-libre-3.2-gnu1/arch/arm/common/pl330.c
--- linux-libre-3.1-gnu1/arch/arm/common/pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/pl330.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,17 +221,6 @@
  */
 #define MCODE_BUFF_PER_REQ	256
 
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-#define MARK_FREE(req)	do { \
-				_emit_END(0, (req)->mc_cpu); \
-				(req)->mc_len = 0; \
-			} while (0)
-
 /* If the _pl330_req is available to the client */
 #define IS_FREE(req)	(*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
 
@@ -301,8 +290,10 @@ struct pl330_thread {
 	struct pl330_dmac *dmac;
 	/* Only two at a time */
 	struct _pl330_req req[2];
-	/* Index of the last submitted request */
+	/* Index of the last enqueued request */
 	unsigned lstenq;
+	/* Index of the last submitted request or -1 if the DMA is stopped */
+	int req_running;
 };
 
 enum pl330_dmac_state {
@@ -778,6 +769,22 @@ static inline void _execute_DBGINSN(stru
 	writel(0, regs + DBGCMD);
 }
 
+/*
+ * Mark a _pl330_req as free.
+ * We do it by writing DMAEND as the first instruction
+ * because no valid request is going to have DMAEND as
+ * its first instruction to execute.
+ */
+static void mark_free(struct pl330_thread *thrd, int idx)
+{
+	struct _pl330_req *req = &thrd->req[idx];
+
+	_emit_END(0, req->mc_cpu);
+	req->mc_len = 0;
+
+	thrd->req_running = -1;
+}
+
 static inline u32 _state(struct pl330_thread *thrd)
 {
 	void __iomem *regs = thrd->dmac->pinfo->base;
@@ -836,31 +843,6 @@ static inline u32 _state(struct pl330_th
 	}
 }
 
-/* If the request 'req' of thread 'thrd' is currently active */
-static inline bool _req_active(struct pl330_thread *thrd,
-		struct _pl330_req *req)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	u32 buf = req->mc_bus, pc = readl(regs + CPC(thrd->id));
-
-	if (IS_FREE(req))
-		return false;
-
-	return (pc >= buf && pc <= buf + req->mc_len) ? true : false;
-}
-
-/* Returns 0 if the thread is inactive, ID of active req + 1 otherwise */
-static inline unsigned _thrd_active(struct pl330_thread *thrd)
-{
-	if (_req_active(thrd, &thrd->req[0]))
-		return 1; /* First req active */
-
-	if (_req_active(thrd, &thrd->req[1]))
-		return 2; /* Second req active */
-
-	return 0;
-}
-
 static void _stop(struct pl330_thread *thrd)
 {
 	void __iomem *regs = thrd->dmac->pinfo->base;
@@ -892,17 +874,22 @@ static bool _trigger(struct pl330_thread
 	struct _arg_GO go;
 	unsigned ns;
 	u8 insn[6] = {0, 0, 0, 0, 0, 0};
+	int idx;
 
 	/* Return if already ACTIVE */
 	if (_state(thrd) != PL330_STATE_STOPPED)
 		return true;
 
-	if (!IS_FREE(&thrd->req[1 - thrd->lstenq]))
-		req = &thrd->req[1 - thrd->lstenq];
-	else if (!IS_FREE(&thrd->req[thrd->lstenq]))
-		req = &thrd->req[thrd->lstenq];
-	else
-		req = NULL;
+	idx = 1 - thrd->lstenq;
+	if (!IS_FREE(&thrd->req[idx]))
+		req = &thrd->req[idx];
+	else {
+		idx = thrd->lstenq;
+		if (!IS_FREE(&thrd->req[idx]))
+			req = &thrd->req[idx];
+		else
+			req = NULL;
+	}
 
 	/* Return if no request */
 	if (!req || !req->r)
@@ -933,6 +920,8 @@ static bool _trigger(struct pl330_thread
 	/* Only manager can execute GO */
 	_execute_DBGINSN(thrd, insn, true);
 
+	thrd->req_running = idx;
+
 	return true;
 }
 
@@ -1211,8 +1200,8 @@ static inline u32 _prepare_ccr(const str
 	ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
 	ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
 
-	ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT);
-	ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT);
+	ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
+	ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
 
 	ccr |= (rqc->swap << CC_SWAP_SHFT);
 
@@ -1382,8 +1371,8 @@ static void pl330_dotask(unsigned long d
 
 			thrd->req[0].r = NULL;
 			thrd->req[1].r = NULL;
-			MARK_FREE(&thrd->req[0]);
-			MARK_FREE(&thrd->req[1]);
+			mark_free(thrd, 0);
+			mark_free(thrd, 1);
 
 			/* Clear the reset flag */
 			pl330->dmac_tbd.reset_chan &= ~(1 << i);
@@ -1461,14 +1450,12 @@ int pl330_update(const struct pl330_info
 
 			thrd = &pl330->channels[id];
 
-			active = _thrd_active(thrd);
-			if (!active) /* Aborted */
+			active = thrd->req_running;
+			if (active == -1) /* Aborted */
 				continue;
 
-			active -= 1;
-
 			rqdone = &thrd->req[active];
-			MARK_FREE(rqdone);
+			mark_free(thrd, active);
 
 			/* Get going again ASAP */
 			_start(thrd);
@@ -1509,7 +1496,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl
 	struct pl330_thread *thrd = ch_id;
 	struct pl330_dmac *pl330;
 	unsigned long flags;
-	int ret = 0, active;
+	int ret = 0, active = thrd->req_running;
 
 	if (!thrd || thrd->free || thrd->dmac->state == DYING)
 		return -EINVAL;
@@ -1525,28 +1512,24 @@ int pl330_chan_ctrl(void *ch_id, enum pl
 
 		thrd->req[0].r = NULL;
 		thrd->req[1].r = NULL;
-		MARK_FREE(&thrd->req[0]);
-		MARK_FREE(&thrd->req[1]);
+		mark_free(thrd, 0);
+		mark_free(thrd, 1);
 		break;
 
 	case PL330_OP_ABORT:
-		active = _thrd_active(thrd);
-
 		/* Make sure the channel is stopped */
 		_stop(thrd);
 
 		/* ABORT is only for the active req */
-		if (!active)
+		if (active == -1)
 			break;
 
-		active--;
-
 		thrd->req[active].r = NULL;
-		MARK_FREE(&thrd->req[active]);
+		mark_free(thrd, active);
 
 		/* Start the next */
 	case PL330_OP_START:
-		if (!_start(thrd))
+		if ((active == -1) && !_start(thrd))
 			ret = -EIO;
 		break;
 
@@ -1587,14 +1570,13 @@ int pl330_chan_status(void *ch_id, struc
 	else
 		pstatus->faulting = false;
 
-	active = _thrd_active(thrd);
+	active = thrd->req_running;
 
-	if (!active) {
+	if (active == -1) {
 		/* Indicate that the thread is not running */
 		pstatus->top_req = NULL;
 		pstatus->wait_req = NULL;
 	} else {
-		active--;
 		pstatus->top_req = thrd->req[active].r;
 		pstatus->wait_req = !IS_FREE(&thrd->req[1 - active])
 					? thrd->req[1 - active].r : NULL;
@@ -1623,6 +1605,11 @@ static inline int _alloc_event(struct pl
 	return -1;
 }
 
+static bool _chan_ns(const struct pl330_info *pi, int i)
+{
+	return pi->pcfg.irq_ns & (1 << i);
+}
+
 /* Upon success, returns IdentityToken for the
  * allocated channel, NULL otherwise.
  */
@@ -1647,15 +1634,16 @@ void *pl330_request_channel(const struct
 
 	for (i = 0; i < chans; i++) {
 		thrd = &pl330->channels[i];
-		if (thrd->free) {
+		if ((thrd->free) && (!_manager_ns(thrd) ||
+					_chan_ns(pi, i))) {
 			thrd->ev = _alloc_event(thrd);
 			if (thrd->ev >= 0) {
 				thrd->free = false;
 				thrd->lstenq = 1;
 				thrd->req[0].r = NULL;
-				MARK_FREE(&thrd->req[0]);
+				mark_free(thrd, 0);
 				thrd->req[1].r = NULL;
-				MARK_FREE(&thrd->req[1]);
+				mark_free(thrd, 1);
 				break;
 			}
 		}
@@ -1761,14 +1749,14 @@ static inline void _reset_thread(struct
 	thrd->req[0].mc_bus = pl330->mcode_bus
 				+ (thrd->id * pi->mcbufsz);
 	thrd->req[0].r = NULL;
-	MARK_FREE(&thrd->req[0]);
+	mark_free(thrd, 0);
 
 	thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
 				+ pi->mcbufsz / 2;
 	thrd->req[1].mc_bus = thrd->req[0].mc_bus
 				+ pi->mcbufsz / 2;
 	thrd->req[1].r = NULL;
-	MARK_FREE(&thrd->req[1]);
+	mark_free(thrd, 1);
 }
 
 static int dmac_alloc_threads(struct pl330_dmac *pl330)
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/sa1111.c linux-libre-3.2-gnu1/arch/arm/common/sa1111.c
--- linux-libre-3.1-gnu1/arch/arm/common/sa1111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/sa1111.c	2012-01-04 18:55:44.000000000 -0500
@@ -718,6 +718,10 @@ __sa1111_probe(struct device *me, struct
 		goto err_free;
 	}
 
+	ret = clk_prepare(sachip->clk);
+	if (ret)
+		goto err_clkput;
+
 	spin_lock_init(&sachip->lock);
 
 	sachip->dev = me;
@@ -733,7 +737,7 @@ __sa1111_probe(struct device *me, struct
 	sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
 	if (!sachip->base) {
 		ret = -ENOMEM;
-		goto err_clkput;
+		goto err_clk_unprep;
 	}
 
 	/*
@@ -809,6 +813,8 @@ __sa1111_probe(struct device *me, struct
 
  err_unmap:
 	iounmap(sachip->base);
+ err_clk_unprep:
+	clk_unprepare(sachip->clk);
  err_clkput:
 	clk_put(sachip->clk);
  err_free:
@@ -835,6 +841,7 @@ static void __sa1111_remove(struct sa111
 	sa1111_writel(0, irqbase + SA1111_WAKEEN1);
 
 	clk_disable(sachip->clk);
+	clk_unprepare(sachip->clk);
 
 	if (sachip->irq != NO_IRQ) {
 		irq_set_chained_handler(sachip->irq, NULL);
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/scoop.c linux-libre-3.2-gnu1/arch/arm/common/scoop.c
--- linux-libre-3.1-gnu1/arch/arm/common/scoop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/scoop.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
  */
 
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <asm/hardware/scoop.h>
 
 /* PCMCIA to Scoop linkage
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/timer-sp.c linux-libre-3.2-gnu1/arch/arm/common/timer-sp.c
--- linux-libre-3.1-gnu1/arch/arm/common/timer-sp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/timer-sp.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,9 +41,17 @@ static long __init sp804_get_clock_rate(
 		return PTR_ERR(clk);
 	}
 
+	err = clk_prepare(clk);
+	if (err) {
+		pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
+		clk_put(clk);
+		return err;
+	}
+
 	err = clk_enable(clk);
 	if (err) {
 		pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+		clk_unprepare(clk);
 		clk_put(clk);
 		return err;
 	}
@@ -52,6 +60,7 @@ static long __init sp804_get_clock_rate(
 	if (rate < 0) {
 		pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
 		clk_disable(clk);
+		clk_unprepare(clk);
 		clk_put(clk);
 	}
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/common/vic.c linux-libre-3.2-gnu1/arch/arm/common/vic.c
--- linux-libre-3.1-gnu1/arch/arm/common/vic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/common/vic.c	2012-01-04 18:55:44.000000000 -0500
@@ -346,7 +346,8 @@ void __init vic_init(void __iomem *base,
 
 	/* Identify which VIC cell this one is, by reading the ID */
 	for (i = 0; i < 4; i++) {
-		u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
+		void __iomem *addr;
+		addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
 		cellid |= (readl(addr) & 0xff) << (8 * i);
 	}
 	vendor = (cellid >> 12) & 0xff;
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91cap9adk_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91cap9adk_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91cap9adk_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91cap9adk_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91CAP9=y
-CONFIG_MACH_AT91CAP9ADK=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91cap9_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91cap9_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91cap9_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91cap9_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,108 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91CAP9=y
+CONFIG_MACH_AT91CAP9ADK=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91rm9200_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91rm9200_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91rm9200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91rm9200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -56,7 +55,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -75,18 +73,8 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -108,8 +96,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_EEPROM_LEGACY=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -119,14 +105,23 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
+CONFIG_ARM_AT91_ETHER=y
 CONFIG_PHYLIB=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=y
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_CATC=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
@@ -139,18 +134,6 @@ CONFIG_USB_NET_RNDIS_HOST=m
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
@@ -158,9 +141,9 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -290,7 +273,6 @@ CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
@@ -335,7 +317,6 @@ CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_CRYPTO_PCBC=y
 CONFIG_CRYPTO_SHA1=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9260_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9260_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9260_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9260_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9260=y
+CONFIG_ARCH_AT91SAM9260_SAM9XE=y
+CONFIG_MACH_AT91SAM9260EK=y
+CONFIG_MACH_CAM60=y
+CONFIG_MACH_SAM9_L9260=y
+CONFIG_MACH_AFEB9260=y
+CONFIG_MACH_USB_A9260=y
+CONFIG_MACH_QIL_A9260=y
+CONFIG_MACH_CPU9260=y
+CONFIG_MACH_FLEXIBITY=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9260ek_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9260ek_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9260ek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9260ek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AT91SAM9260EK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g20_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g20_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g20_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g20_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,124 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
+CONFIG_MACH_CPU9G20=y
+CONFIG_MACH_ACMENETUSFOXG20=y
+CONFIG_MACH_PORTUXG20=y
+CONFIG_MACH_STAMP9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_MACH_GSIA18S=y
+CONFIG_MACH_USB_A9G20=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_HWMON is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g20ek_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g20ek_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g20ek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g20ek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_AT91SAM9G20EK=y
-CONFIG_MACH_AT91SAM9G20EK_2MMC=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_HW_RANDOM=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PROCFS is not set
-CONFIG_SND_AT73C213=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g45_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g45_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9g45_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9g45_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,211 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G45=y
+CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CFG80211=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_RTL8187=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43_PHY_N=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_FB_UDL=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_ATMEL_AC97C=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_SDIO_UART=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_MMC_ATMELMCI_DMA=y
+CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
+CONFIG_DMATEST=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9rl_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9rl_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9rl_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9rl_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,79 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9RL=y
+CONFIG_MACH_AT91SAM9RLEK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/at91sam9rlek_defconfig linux-libre-3.2-gnu1/arch/arm/configs/at91sam9rlek_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/at91sam9rlek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/at91sam9rlek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9RL=y
-CONFIG_MACH_AT91SAM9RLEK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=24576
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/exynos4_defconfig linux-libre-3.2-gnu1/arch/arm/configs/exynos4_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/exynos4_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/exynos4_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,18 +4,18 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_EXYNOS4=y
+CONFIG_ARCH_EXYNOS=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDKC210=y
-CONFIG_MACH_SMDKV310=y
 CONFIG_MACH_ARMLEX4210=y
 CONFIG_MACH_UNIVERSAL_C210=y
 CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
@@ -60,13 +60,9 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_DEBUG_S3C_UART=1
 CONFIG_CRC_CCITT=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/ezx_defconfig linux-libre-3.2-gnu1/arch/arm/configs/ezx_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/ezx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/ezx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -287,7 +287,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/imote2_defconfig linux-libre-3.2-gnu1/arch/arm/configs/imote2_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/imote2_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/imote2_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -263,7 +263,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/imx_v4_v5_defconfig linux-libre-3.2-gnu1/arch/arm/configs/imx_v4_v5_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/imx_v4_v5_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/imx_v4_v5_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,172 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MX1ADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MACH_APF9328=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX25_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX25SD=y
+CONFIG_MACH_MX27ADS=y
+CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
+CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
+CONFIG_MACH_IMX27IPCAM=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_NETDEVICES=y
+CONFIG_DM9000=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC_PHY=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_W1=y
+CONFIG_W1_MASTER_MXC=y
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_MX27VIS_AIC32X4=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ULPI=y
+CONFIG_MMC=y
+CONFIG_MMC_MXC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_MC13783=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/integrator_defconfig linux-libre-3.2-gnu1/arch/arm/configs/integrator_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/integrator_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/integrator_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_TINY_RCU=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -8,20 +9,29 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_INTEGRATOR=y
 CONFIG_ARCH_INTEGRATOR_AP=y
+CONFIG_ARCH_INTEGRATOR_CP=y
 CONFIG_CPU_ARM720T=y
 CONFIG_CPU_ARM920T=y
+CONFIG_CPU_ARM922T=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_ARM1020=y
+CONFIG_CPU_ARM1022=y
+CONFIG_CPU_ARM1026=y
 CONFIG_PCI=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
 CONFIG_LEDS=y
 CONFIG_LEDS_CPU=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M"
+CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -32,7 +42,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -40,6 +49,7 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -56,6 +66,8 @@ CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL030=y
 CONFIG_EXT2_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
@@ -68,4 +80,3 @@ CONFIG_NFSD_V3=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_ERRORS=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/magician_defconfig linux-libre-3.2-gnu1/arch/arm/configs/magician_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/magician_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/magician_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx1_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx1_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx1_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX1=y
-CONFIG_ARCH_MX1ADS=y
-CONFIG_MACH_SCB9328=y
-CONFIG_MACH_APF9328=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_DM9000=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_IMX=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx21_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx21_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx21_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx21_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX21ADS=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-# CONFIG_CONSOLE_TRANSLATIONS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_LOGO=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx27_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx27_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx27_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx27_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX27=y
-CONFIG_MACH_MX27ADS=y
-CONFIG_MACH_PCM038=y
-CONFIG_MACH_CPUIMX27=y
-CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
-CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
-CONFIG_MACH_MX27_3DS=y
-CONFIG_MACH_IMX27_VISSTRIM_M10=y
-CONFIG_MACH_IMX27LITE=y
-CONFIG_MACH_PCA100=y
-CONFIG_MACH_MXT_TD60=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# CONFIG_MTD_CFI_I2 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=m
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=m
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_PCF8563=y
-# CONFIG_DNOTIFY is not set
-# CONFIG_PROC_PAGE_MONITOR is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx3_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx3_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx3_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx3_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,20 +12,21 @@ CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_MX31ADS_WM1133_EV1=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
 CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_MX31_3DS=y
 CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_QONG=y
-CONFIG_MACH_PCM043=y
 CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX35=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
+CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
@@ -35,7 +35,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
 CONFIG_VFP=y
-CONFIG_PM=y
 CONFIG_PM_DEBUG=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -52,7 +51,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -62,24 +60,27 @@ CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MXC=y
 CONFIG_MTD_UBI=y
 # CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 CONFIG_DNET=y
-CONFIG_FEC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -89,12 +90,15 @@ CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
 CONFIG_MFD_WM8350_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_WM8350=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_MT9M001=y
 CONFIG_SOC_CAMERA_MT9M111=y
@@ -105,9 +109,26 @@ CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_MX3=y
 # CONFIG_RADIO_ADAPTERS is not set
 CONFIG_FB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_MXC_SOC_WM1133_EV1=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_GADGET=m
+CONFIG_USB_FSL_USB2=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_MXC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_MXC=y
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
@@ -119,6 +140,5 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx51_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx51_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx51_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx51_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,170 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX51=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=m
-CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MDIO_BITBANG=y
-CONFIG_MDIO_GPIO=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=m
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_LZO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mx5_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mx5_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mx5_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/configs/mx5_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MX5=y
+CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_MX53_EVK=y
+CONFIG_MACH_MX53_SMD=y
+CONFIG_MACH_MX53_LOCO=y
+CONFIG_MACH_MX53_ARD=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/mxs_defconfig linux-libre-3.2-gnu1/arch/arm/configs/mxs_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/mxs_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/mxs_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@ CONFIG_MACH_MX23EVK=y
 CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
+CONFIG_MACH_M28EVK=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/omap1_defconfig linux-libre-3.2-gnu1/arch/arm/configs/omap1_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/omap1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/omap1_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -48,13 +48,7 @@ CONFIG_MACH_SX1=y
 CONFIG_MACH_NOKIA770=y
 CONFIG_MACH_AMS_DELTA=y
 CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-CONFIG_OMAP_ARM_216MHZ=y
-CONFIG_OMAP_ARM_195MHZ=y
-CONFIG_OMAP_ARM_192MHZ=y
 CONFIG_OMAP_ARM_182MHZ=y
-CONFIG_OMAP_ARM_168MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
 # CONFIG_ARM_THUMB is not set
 CONFIG_PCCARD=y
 CONFIG_OMAP_CF=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/tegra_defconfig linux-libre-3.2-gnu1/arch/arm/configs/tegra_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/tegra_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/tegra_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@ CONFIG_MACH_KAEN=y
 CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
 CONFIG_MACH_WARIO=y
+CONFIG_MACH_VENTANA=y
 CONFIG_TEGRA_DEBUG_UARTD=y
 CONFIG_ARM_ERRATA_742230=y
 CONFIG_NO_HZ=y
@@ -38,7 +39,6 @@ CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_VFP=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -65,6 +65,7 @@ CONFIG_IPV6_TUNNEL=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 # CONFIG_WIRELESS is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_AD525X_DPOT=y
@@ -72,34 +73,61 @@ CONFIG_AD525X_DPOT_I2C=y
 CONFIG_ICS932S401=y
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
 CONFIG_R8169=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 # CONFIG_I2C_HELPER_AUTO is not set
 CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_TPS6586X=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TEGRA=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_IIO=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_AK8975=y
@@ -123,18 +151,15 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_SG=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CRYPTO_ECB=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/u300_defconfig linux-libre-3.2-gnu1/arch/arm/configs/u300_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/u300_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/u300_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U300=y
 CONFIG_MACH_U300=y
 CONFIG_MACH_U300_BS335=y
-CONFIG_MACH_U300_DUAL_RAM=y
-CONFIG_U300_DEBUG=y
 CONFIG_MACH_U300_SPIDUMMY=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -26,19 +24,21 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
 CONFIG_CPU_IDLE=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_HWMON is not set
@@ -51,6 +51,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
@@ -65,10 +66,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRC32 is not set
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/u8500_defconfig linux-libre-3.2-gnu1/arch/arm/configs/u8500_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/u8500_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/u8500_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
-CONFIG_MACH_U8500=y
+CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
@@ -24,6 +24,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -41,11 +42,8 @@ CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -72,15 +70,12 @@ CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
-# CONFIG_HWMON is not set
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
+CONFIG_AB5500_CORE=y
 CONFIG_AB8500_CORE=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_GADGET=y
 CONFIG_AB8500_USB=y
 CONFIG_MMC=y
@@ -97,6 +92,7 @@ CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_HSEM_U8500=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff -druNp linux-libre-3.1-gnu1/arch/arm/configs/zeus_defconfig linux-libre-3.2-gnu1/arch/arm/configs/zeus_defconfig
--- linux-libre-3.1-gnu1/arch/arm/configs/zeus_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/configs/zeus_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -140,7 +140,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/auxvec.h linux-libre-3.2-gnu1/arch/arm/include/asm/auxvec.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/auxvec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/auxvec.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef __ASMARM_AUXVEC_H
-#define __ASMARM_AUXVEC_H
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/bitsperlong.h linux-libre-3.2-gnu1/arch/arm/include/asm/bitsperlong.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/bitsperlong.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/bug.h linux-libre-3.2-gnu1/arch/arm/include/asm/bug.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/bug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/bug.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,21 +3,58 @@
 
 
 #ifdef CONFIG_BUG
+
+/*
+ * Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
+ * We need to be careful not to conflict with those used by other modules and
+ * the register_undef_hook() system.
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+#define BUG_INSTR_VALUE 0xde02
+#define BUG_INSTR_TYPE ".hword "
+#else
+#define BUG_INSTR_VALUE 0xe7f001f2
+#define BUG_INSTR_TYPE ".word "
+#endif
+
+
+#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE)
+#define _BUG(file, line, value) __BUG(file, line, value)
+
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line) __attribute__((noreturn));
 
-/* give file/line information */
-#define BUG()		__bug(__FILE__, __LINE__)
+/*
+ * The extra indirection is to ensure that the __FILE__ string comes through
+ * OK. Many version of gcc do not support the asm %c parameter which would be
+ * preferable to this unpleasantness. We use mergeable string sections to
+ * avoid multiple copies of the string appearing in the kernel image.
+ */
 
-#else
+#define __BUG(__file, __line, __value)				\
+do {								\
+	BUILD_BUG_ON(sizeof(struct bug_entry) != 12);		\
+	asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n"	\
+		".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
+		"2:\t.asciz " #__file "\n" 			\
+		".popsection\n" 				\
+		".pushsection __bug_table,\"a\"\n"		\
+		"3:\t.word 1b, 2b\n"				\
+		"\t.hword " #__line ", 0\n"			\
+		".popsection");					\
+	unreachable();						\
+} while (0)
 
-/* this just causes an oops */
-#define BUG()		do { *(int *)0 = 0; } while (1)
+#else  /* not CONFIG_DEBUG_BUGVERBOSE */
 
-#endif
+#define __BUG(__file, __line, __value)				\
+do {								\
+	asm volatile(BUG_INSTR_TYPE #__value);			\
+	unreachable();						\
+} while (0)
+#endif  /* CONFIG_DEBUG_BUGVERBOSE */
 
 #define HAVE_ARCH_BUG
-#endif
+#endif  /* CONFIG_BUG */
 
 #include <asm-generic/bug.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/cachetype.h linux-libre-3.2-gnu1/arch/arm/include/asm/cachetype.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/cachetype.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/cachetype.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #define CACHEID_VIPT			(CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
 #define CACHEID_ASID_TAGGED		(1 << 3)
 #define CACHEID_VIPT_I_ALIASING		(1 << 4)
+#define CACHEID_PIPT			(1 << 5)
 
 extern unsigned int cacheid;
 
@@ -16,6 +17,7 @@ extern unsigned int cacheid;
 #define cache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_ALIASING)
 #define icache_is_vivt_asid_tagged()	cacheid_is(CACHEID_ASID_TAGGED)
 #define icache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_I_ALIASING)
+#define icache_is_pipt()		cacheid_is(CACHEID_PIPT)
 
 /*
  * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@ extern unsigned int cacheid;
 #if __LINUX_ARM_ARCH__ >= 7
 #define __CACHEID_ARCH_MIN	(CACHEID_VIPT_NONALIASING |\
 				 CACHEID_ASID_TAGGED |\
-				 CACHEID_VIPT_I_ALIASING)
+				 CACHEID_VIPT_I_ALIASING |\
+				 CACHEID_PIPT)
 #elif __LINUX_ARM_ARCH__ >= 6
 #define	__CACHEID_ARCH_MIN	(~CACHEID_VIVT)
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/cputime.h linux-libre-3.2-gnu1/arch/arm/include/asm/cputime.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/cputime.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ARM_CPUTIME_H
-#define __ARM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __ARM_CPUTIME_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/cputype.h linux-libre-3.2-gnu1/arch/arm/include/asm/cputype.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/cputype.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/cputype.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #define CPUID_CACHETYPE	1
 #define CPUID_TCM	2
 #define CPUID_TLBTYPE	3
+#define CPUID_MPIDR	5
 
 #define CPUID_EXT_PFR0	"c1, 0"
 #define CPUID_EXT_PFR1	"c1, 1"
@@ -70,6 +71,11 @@ static inline unsigned int __attribute_c
 	return read_cpuid(CPUID_TCM);
 }
 
+static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
+{
+	return read_cpuid(CPUID_MPIDR);
+}
+
 /*
  * Intel's XScale3 core supports some v6 features (supersections, L2)
  * but advertises itself as v5 as it does not support the v6 ISA.  For
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/device.h linux-libre-3.2-gnu1/arch/arm/include/asm/device.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,17 @@ struct dev_archdata {
 #ifdef CONFIG_DMABOUNCE
 	struct dmabounce_device_info *dmabounce;
 #endif
+#ifdef CONFIG_IOMMU_API
+	void *iommu; /* private IOMMU data */
+#endif
 };
 
+struct omap_device;
+
 struct pdev_archdata {
+#ifdef CONFIG_ARCH_OMAP
+	struct omap_device *od;
+#endif
 };
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/dma.h linux-libre-3.2-gnu1/arch/arm/include/asm/dma.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,18 +34,18 @@
 #define DMA_MODE_CASCADE 0xc0
 #define DMA_AUTOINIT	 0x10
 
-extern spinlock_t  dma_spin_lock;
+extern raw_spinlock_t  dma_spin_lock;
 
 static inline unsigned long claim_dma_lock(void)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&dma_spin_lock, flags);
+	raw_spin_lock_irqsave(&dma_spin_lock, flags);
 	return flags;
 }
 
 static inline void release_dma_lock(unsigned long flags)
 {
-	spin_unlock_irqrestore(&dma_spin_lock, flags);
+	raw_spin_unlock_irqrestore(&dma_spin_lock, flags);
 }
 
 /* Clear the 'DMA Pointer Flip Flop'.
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/arm/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@ static inline unsigned long dma_to_pfn(s
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
 {
-	return (void *)__bus_to_virt(addr);
+	return (void *)__bus_to_virt((unsigned long)addr);
 }
 
 static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
@@ -205,6 +205,13 @@ extern void *dma_alloc_writecombine(stru
 int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
 		void *, dma_addr_t, size_t);
 
+/*
+ * This can be called during boot to increase the size of the consistent
+ * DMA region above it's default value of 2MB. It must be called before the
+ * memory allocator is initialised, i.e. before any core_initcall.
+ */
+extern void __init init_consistent_dma_size(unsigned long size);
+
 
 #ifdef CONFIG_DMABOUNCE
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/ecard.h linux-libre-3.2-gnu1/arch/arm/include/asm/ecard.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/ecard.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/ecard.h	2012-01-04 18:55:44.000000000 -0500
@@ -161,7 +161,6 @@ struct expansion_card {
 
 	/* Private internal data */
 	const char		*card_desc;	/* Card description		*/
-	CONST unsigned int	podaddr;	/* Base Linux address for card	*/
 	CONST loader_t		loader;		/* loader program */
 	u64			dma_mask;
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/emergency-restart.h linux-libre-3.2-gnu1/arch/arm/include/asm/emergency-restart.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/emergency-restart.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/emergency-restart.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/entry-macro-multi.S linux-libre-3.2-gnu1/arch/arm/include/asm/entry-macro-multi.S
--- linux-libre-3.1-gnu1/arch/arm/include/asm/entry-macro-multi.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/entry-macro-multi.S	2012-01-04 18:55:44.000000000 -0500
@@ -25,13 +25,6 @@
 	movne	r1, sp
 	adrne	lr, BSYM(1b)
 	bne	do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-	test_for_ltirq r0, r2, r6, lr
-	movne	r0, sp
-	adrne	lr, BSYM(1b)
-	bne	do_local_timer
-#endif
 #endif
 9997:
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/errno.h linux-libre-3.2-gnu1/arch/arm/include/asm/errno.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/errno.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/errno.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ARM_ERRNO_H
-#define _ARM_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/exception.h linux-libre-3.2-gnu1/arch/arm/include/asm/exception.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/exception.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/exception.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Annotations for marking C functions as exception handlers.
+ *
+ * These should only be used for C functions that are called from the low
+ * level exception entry code and not any intervening C code.
+ */
+#ifndef __ASM_ARM_EXCEPTION_H
+#define __ASM_ARM_EXCEPTION_H
+
+#include <linux/ftrace.h>
+
+#define __exception	__attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry	__irq_entry
+#else
+#define __exception_irq_entry	__exception
+#endif
+
+#endif /* __ASM_ARM_EXCEPTION_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/gpio.h linux-libre-3.2-gnu1/arch/arm/include/asm/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,4 +4,23 @@
 /* not all ARM platforms necessarily support this API ... */
 #include <mach/gpio.h>
 
+#ifndef __ARM_GPIOLIB_COMPLEX
+/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
+#include <asm-generic/gpio.h>
+
+/* The trivial gpiolib dispatchers */
+#define gpio_get_value  __gpio_get_value
+#define gpio_set_value  __gpio_set_value
+#define gpio_cansleep   __gpio_cansleep
+#endif
+
+/*
+ * Provide a default gpio_to_irq() which should satisfy every case.
+ * However, some platforms want to do this differently, so allow them
+ * to override it.
+ */
+#ifndef gpio_to_irq
+#define gpio_to_irq	__gpio_to_irq
+#endif
+
 #endif /* _ARCH_ARM_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardirq.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardirq.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardirq.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,6 @@
 
 typedef struct {
 	unsigned int __softirq_pending;
-#ifdef CONFIG_LOCAL_TIMERS
-	unsigned int local_timer_irqs;
-#endif
 #ifdef CONFIG_SMP
 	unsigned int ipi_irqs[NR_IPI];
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_HARDWARE_L2X0_H
 #define __ASM_ARM_HARDWARE_L2X0_H
 
+#include <linux/errno.h>
+
 #define L2X0_CACHE_ID			0x000
 #define L2X0_CACHE_TYPE			0x004
 #define L2X0_CTRL			0x100
@@ -52,6 +54,8 @@
 #define L2X0_LOCKDOWN_WAY_D_BASE	0x900
 #define L2X0_LOCKDOWN_WAY_I_BASE	0x904
 #define L2X0_LOCKDOWN_STRIDE		0x08
+#define L2X0_ADDR_FILTER_START		0xC00
+#define L2X0_ADDR_FILTER_END		0xC04
 #define L2X0_TEST_OPERATION		0xF00
 #define L2X0_LINE_DATA			0xF10
 #define L2X0_LINE_TAG			0xF30
@@ -65,8 +69,23 @@
 #define L2X0_CACHE_ID_PART_MASK		(0xf << 6)
 #define L2X0_CACHE_ID_PART_L210		(1 << 6)
 #define L2X0_CACHE_ID_PART_L310		(3 << 6)
+#define L2X0_CACHE_ID_RTL_MASK          0x3f
+#define L2X0_CACHE_ID_RTL_R0P0          0x0
+#define L2X0_CACHE_ID_RTL_R1P0          0x2
+#define L2X0_CACHE_ID_RTL_R2P0          0x4
+#define L2X0_CACHE_ID_RTL_R3P0          0x5
+#define L2X0_CACHE_ID_RTL_R3P1          0x6
+#define L2X0_CACHE_ID_RTL_R3P2          0x8
 
 #define L2X0_AUX_CTRL_MASK			0xc0000fff
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT	0
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK	0x7
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT	3
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK	(0x7 << 3)
+#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT		6
+#define L2X0_AUX_CTRL_TAG_LATENCY_MASK		(0x7 << 6)
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT	9
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK	(0x7 << 9)
 #define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT	16
 #define L2X0_AUX_CTRL_WAY_SIZE_SHIFT		17
 #define L2X0_AUX_CTRL_WAY_SIZE_MASK		(0x7 << 17)
@@ -77,8 +96,40 @@
 #define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT	29
 #define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT		30
 
+#define L2X0_LATENCY_CTRL_SETUP_SHIFT	0
+#define L2X0_LATENCY_CTRL_RD_SHIFT	4
+#define L2X0_LATENCY_CTRL_WR_SHIFT	8
+
+#define L2X0_ADDR_FILTER_EN		1
+
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
+extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+#else
+static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+	return -ENODEV;
+}
 #endif
 
+struct l2x0_regs {
+	unsigned long phy_base;
+	unsigned long aux_ctrl;
+	/*
+	 * Whether the following registers need to be saved/restored
+	 * depends on platform
+	 */
+	unsigned long tag_latency;
+	unsigned long data_latency;
+	unsigned long filter_start;
+	unsigned long filter_end;
+	unsigned long prefetch_ctrl;
+	unsigned long pwr_ctrl;
+};
+
+extern struct l2x0_regs l2x0_saved_regs;
+
+#endif /* __ASSEMBLY__ */
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,11 @@
  * interrupt controller spec.  To wit:
  *
  * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 16-31 are local.  We allow 30 to be used for the watchdog.
  * 32-1020 are global
  * 1021-1022 are reserved
  * 1023 is "spurious" (no interrupt)
  *
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
- *
  * A simple read from the controller will tell us the number of the highest
  * priority enabled interrupt.  We then just need to check whether it is in the
  * valid range for an IRQ (30-1020 inclusive).
@@ -43,7 +39,7 @@
 
 	ldr	\tmp, =1021
 	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
+	cmp     \irqnr, #15
 	cmpcc	\irqnr, \irqnr
 	cmpne	\irqnr, \tmp
 	cmpcs	\irqnr, \irqnr
@@ -62,14 +58,3 @@
 	strcc	\irqstat, [\base, #GIC_CPU_EOI]
 	cmpcs	\irqnr, \irqnr
 	.endm
-
-/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/gic.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/gic.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/gic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/gic.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,19 +33,32 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+struct device_node;
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
-void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_init(unsigned int, int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-void gic_enable_ppi(unsigned int);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+#ifdef CONFIG_IRQ_DOMAIN
+	struct irq_domain domain;
+#endif
+	unsigned int gic_irqs;
 };
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/iop3xx-gpio.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/iop3xx-gpio.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/iop3xx-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/iop3xx-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <mach/hardware.h>
 #include <asm-generic/gpio.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 #define IOP3XX_N_GPIOS	8
 
 static inline int gpio_get_value(unsigned gpio)
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/it8152.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/it8152.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/it8152.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/it8152.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #ifndef __ASM_HARDWARE_IT8152_H
 #define __ASM_HARDWARE_IT8152_H
-extern unsigned long it8152_base_address;
+extern void __iomem *it8152_base_address;
 
 #define IT8152_IO_BASE			(it8152_base_address + 0x03e00000)
 #define IT8152_CFGREG_BASE		(it8152_base_address + 0x03f00000)
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/pl080.h linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/pl080.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hardware/pl080.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hardware/pl080.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,9 @@
  * OneNAND features.
 */
 
+#ifndef ASM_PL080_H
+#define ASM_PL080_H
+
 #define PL080_INT_STATUS			(0x00)
 #define PL080_TC_STATUS				(0x04)
 #define PL080_TC_CLEAR				(0x08)
@@ -138,3 +141,4 @@ struct pl080s_lli {
 	u32	control1;
 };
 
+#endif /* ASM_PL080_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/hw_breakpoint.h linux-libre-3.2-gnu1/arch/arm/include/asm/hw_breakpoint.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/hw_breakpoint.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/hw_breakpoint.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@ static inline void decode_ctrl_reg(u32 r
 #define ARM_DEBUG_ARCH_V6_1	2
 #define ARM_DEBUG_ARCH_V7_ECP14	3
 #define ARM_DEBUG_ARCH_V7_MM	4
+#define ARM_DEBUG_ARCH_V7_1	5
 
 /* Breakpoint */
 #define ARM_BREAKPOINT_EXECUTE	0
@@ -57,6 +58,7 @@ static inline void decode_ctrl_reg(u32 r
 /* Watchpoints */
 #define ARM_BREAKPOINT_LOAD	1
 #define ARM_BREAKPOINT_STORE	2
+#define ARM_FSR_ACCESS_MASK	(1 << 11)
 
 /* Privilege Levels */
 #define ARM_BREAKPOINT_PRIV	1
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/ioctl.h linux-libre-3.2-gnu1/arch/arm/include/asm/ioctl.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/ioctl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/io.h linux-libre-3.2-gnu1/arch/arm/include/asm/io.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@ extern void __iomem *__arm_ioremap_calle
 
 extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
 extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
+extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
@@ -110,6 +111,27 @@ static inline void __iomem *__typesafe_i
 #include <mach/io.h>
 
 /*
+ * This is the limit of PC card/PCI/ISA IO space, which is by default
+ * 64K if we have PC card, PCI or ISA support.  Otherwise, default to
+ * zero to prevent ISA/PCI drivers claiming IO space (and potentially
+ * oopsing.)
+ *
+ * Only set this larger if you really need inb() et.al. to operate over
+ * a larger address space.  Note that SOC_COMMON ioremaps each sockets
+ * IO space area, and so inb() et.al. must be defined to operate as per
+ * readb() et.al. on such platforms.
+ */
+#ifndef IO_SPACE_LIMIT
+#if defined(CONFIG_PCMCIA_SOC_COMMON) || defined(CONFIG_PCMCIA_SOC_COMMON_MODULE)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffffffff)
+#elif defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(CONFIG_PCCARD)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffff)
+#else
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+#endif
+#endif
+
+/*
  *  IO port access primitives
  *  -------------------------
  *
@@ -189,11 +211,11 @@ extern void _memset_io(volatile void __i
  * IO port primitives for more information.
  */
 #ifdef __mem_pci
-#define readb_relaxed(c) ({ u8  __v = __raw_readb(__mem_pci(c)); __v; })
-#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16) \
-					__raw_readw(__mem_pci(c))); __v; })
-#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32) \
-					__raw_readl(__mem_pci(c))); __v; })
+#define readb_relaxed(c) ({ u8  __r = __raw_readb(__mem_pci(c)); __r; })
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+					__raw_readw(__mem_pci(c))); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl(__mem_pci(c))); __r; })
 
 #define writeb_relaxed(v,c)	((void)__raw_writeb(v,__mem_pci(c)))
 #define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
@@ -238,7 +260,7 @@ extern void _memset_io(volatile void __i
  * ioremap and friends.
  *
  * ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
  *
  */
 #ifndef __arch_ioremap
@@ -260,10 +282,16 @@ extern void _memset_io(volatile void __i
 #define ioread16(p)	({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32(p)	({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
 
+#define ioread16be(p)	({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p)	({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+
 #define iowrite8(v,p)	({ __iowmb(); (void)__raw_writeb(v, p); })
 #define iowrite16(v,p)	({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); })
 #define iowrite32(v,p)	({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); })
 
+#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); })
+
 #define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
 #define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
 #define ioread32_rep(p,d,c)	__raw_readsl(p,d,c)
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/irq_regs.h linux-libre-3.2-gnu1/arch/arm/include/asm/irq_regs.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/irq_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/irq_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/Kbuild linux-libre-3.2-gnu1/arch/arm/include/asm/Kbuild
--- linux-libre-3.1-gnu1/arch/arm/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,20 @@
 include include/asm-generic/Kbuild.asm
 
 header-y += hwcap.h
+
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += cputime.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += ioctl.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += resource.h
+generic-y += sections.h
+generic-y += siginfo.h
+generic-y += sizes.h
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/kdebug.h linux-libre-3.2-gnu1/arch/arm/include/asm/kdebug.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/kdebug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/kdebug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/local64.h linux-libre-3.2-gnu1/arch/arm/include/asm/local64.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/local64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/local64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/local.h linux-libre-3.2-gnu1/arch/arm/include/asm/local.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/local.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/local.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/localtimer.h linux-libre-3.2-gnu1/arch/arm/include/asm/localtimer.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/localtimer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/localtimer.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #define __ASM_ARM_LOCALTIMER_H
 
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 
 struct clock_event_device;
 
@@ -19,27 +20,20 @@ struct clock_event_device;
  */
 void percpu_timer_setup(void);
 
-/*
- * Called from assembly, this is the local timer IRQ handler
- */
-asmlinkage void do_local_timer(struct pt_regs *);
-
-
 #ifdef CONFIG_LOCAL_TIMERS
 
 #ifdef CONFIG_HAVE_ARM_TWD
 
 #include "smp_twd.h"
 
-#define local_timer_ack()	twd_timer_ack()
+#define local_timer_stop(c)	twd_timer_stop((c))
 
 #else
 
 /*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
+ * Stop the local timer
  */
-int local_timer_ack(void);
+void local_timer_stop(struct clock_event_device *);
 
 #endif
 
@@ -54,6 +48,10 @@ static inline int local_timer_setup(stru
 {
 	return -ENXIO;
 }
+
+static inline void local_timer_stop(struct clock_event_device *evt)
+{
+}
 #endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/mach/arch.h linux-libre-3.2-gnu1/arch/arm/include/asm/mach/arch.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/mach/arch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/mach/arch.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,12 @@
 struct tag;
 struct meminfo;
 struct sys_timer;
+struct pt_regs;
 
 struct machine_desc {
 	unsigned int		nr;		/* architecture number	*/
 	const char		*name;		/* architecture name	*/
-	unsigned long		boot_params;	/* tagged list		*/
+	unsigned long		atag_offset;	/* tagged list (relative) */
 	const char		**dt_compat;	/* array of device tree
 						 * 'compatible' strings	*/
 
@@ -34,8 +35,7 @@ struct machine_desc {
 	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
 	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
 	unsigned int		soft_reboot :1;	/* soft reboot		*/
-	void			(*fixup)(struct machine_desc *,
-					 struct tag *, char **,
+	void			(*fixup)(struct tag *, char **,
 					 struct meminfo *);
 	void			(*reserve)(void);/* reserve mem blocks	*/
 	void			(*map_io)(void);/* IO mapping function	*/
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/mach/map.h linux-libre-3.2-gnu1/arch/arm/include/asm/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@ struct map_desc {
 #define MT_MEMORY_NONCACHED	11
 #define MT_MEMORY_DTCM		12
 #define MT_MEMORY_ITCM		13
+#define MT_MEMORY_SO		14
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/memory.h linux-libre-3.2-gnu1/arch/arm/include/asm/memory.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,12 @@
 #include <linux/compiler.h>
 #include <linux/const.h>
 #include <linux/types.h>
-#include <mach/memory.h>
 #include <asm/sizes.h>
 
+#ifdef CONFIG_NEED_MACH_MEMORY_H
+#include <mach/memory.h>
+#endif
+
 /*
  * Allow for constants defined here to be used from assembly code
  * by prepending the UL suffix only with actual C code compilation.
@@ -77,16 +80,7 @@
  */
 #define IOREMAP_MAX_ORDER	24
 
-/*
- * Size of DMA-consistent memory region.  Must be multiple of 2M,
- * between 2MB and 14MB inclusive.
- */
-#ifndef CONSISTENT_DMA_SIZE
-#define CONSISTENT_DMA_SIZE 	SZ_2M
-#endif
-
 #define CONSISTENT_END		(0xffe00000UL)
-#define CONSISTENT_BASE		(CONSISTENT_END - CONSISTENT_DMA_SIZE)
 
 #else /* CONFIG_MMU */
 
@@ -160,7 +154,6 @@
  * so that all we need to do is modify the 8-bit constant field.
  */
 #define __PV_BITS_31_24	0x81000000
-#define __PV_BITS_23_16	0x00810000
 
 extern unsigned long __pv_phys_offset;
 #define PHYS_OFFSET __pv_phys_offset
@@ -178,9 +171,6 @@ static inline unsigned long __virt_to_ph
 {
 	unsigned long t;
 	__pv_stub(x, t, "add", __PV_BITS_31_24);
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-	__pv_stub(t, t, "add", __PV_BITS_23_16);
-#endif
 	return t;
 }
 
@@ -188,9 +178,6 @@ static inline unsigned long __phys_to_vi
 {
 	unsigned long t;
 	__pv_stub(x, t, "sub", __PV_BITS_31_24);
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-	__pv_stub(t, t, "sub", __PV_BITS_23_16);
-#endif
 	return t;
 }
 #else
@@ -200,7 +187,11 @@ static inline unsigned long __phys_to_vi
 #endif
 
 #ifndef PHYS_OFFSET
+#ifdef PLAT_PHYS_OFFSET
 #define PHYS_OFFSET	PLAT_PHYS_OFFSET
+#else
+#define PHYS_OFFSET	UL(CONFIG_PHYS_OFFSET)
+#endif
 #endif
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/mmu.h linux-libre-3.2-gnu1/arch/arm/include/asm/mmu.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
 	unsigned int id;
-	spinlock_t id_lock;
+	raw_spinlock_t id_lock;
 #endif
 	unsigned int kvm_seq;
 } mm_context_t;
@@ -16,7 +16,7 @@ typedef struct {
 
 /* init_mm.context.id_lock should be initialized. */
 #define INIT_MM_CONTEXT(name)                                                 \
-	.context.id_lock    = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
+	.context.id_lock    = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
 #else
 #define ASID(mm)	(0)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/module.h linux-libre-3.2-gnu1/arch/arm/include/asm/module.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,7 @@ struct mod_arch_specific {
 
 /* Add __virt_to_phys patching state as well */
 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-#define MODULE_ARCH_VERMAGIC_P2V "p2v16 "
-#else
 #define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
-#endif
 #else
 #define MODULE_ARCH_VERMAGIC_P2V ""
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/outercache.h linux-libre-3.2-gnu1/arch/arm/include/asm/outercache.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/outercache.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/outercache.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@ struct outer_cache_fns {
 	void (*sync)(void);
 #endif
 	void (*set_debug)(unsigned long);
+	void (*resume)(void);
 };
 
 #ifdef CONFIG_OUTER_CACHE
@@ -74,6 +75,12 @@ static inline void outer_disable(void)
 		outer_cache.disable();
 }
 
+static inline void outer_resume(void)
+{
+	if (outer_cache.resume)
+		outer_cache.resume();
+}
+
 #else
 
 static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/page.h linux-libre-3.2-gnu1/arch/arm/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -151,47 +151,7 @@ extern void __cpu_copy_user_highpage(str
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
-typedef unsigned long pteval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd[2]; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x)      ((x).pte)
-#define pmd_val(x)      ((x).pmd)
-#define pgd_val(x)	((x).pgd[0])
-#define pgprot_val(x)   ((x).pgprot)
-
-#define __pte(x)        ((pte_t) { (x) } )
-#define __pmd(x)        ((pmd_t) { (x) } )
-#define __pgprot(x)     ((pgprot_t) { (x) } )
-
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef pteval_t pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t[2];
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)      (x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)	((x)[0])
-#define pgprot_val(x)   (x)
-
-#define __pte(x)        (x)
-#define __pmd(x)        (x)
-#define __pgprot(x)     (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
+#include <asm/pgtable-2level-types.h>
 
 #endif /* CONFIG_MMU */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/percpu.h linux-libre-3.2-gnu1/arch/arm/include/asm/percpu.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/percpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/percpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ARM_PERCPU
-#define __ARM_PERCPU
-
-#include <asm-generic/percpu.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgalloc.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgalloc.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -105,9 +105,9 @@ static inline void pte_free(struct mm_st
 }
 
 static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
-	unsigned long prot)
+				  pmdval_t prot)
 {
-	unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot;
+	pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
 	pmdp[0] = __pmd(pmdval);
 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
 	flush_pmd_entry(pmdp);
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,143 @@
+/*
+ *  arch/arm/include/asm/pgtable-2level.h
+ *
+ *  Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_H
+#define _ASM_PGTABLE_2LEVEL_H
+
+/*
+ * Hardware-wise, we have a two level page table structure, where the first
+ * level has 4096 entries, and the second level has 256 entries.  Each entry
+ * is one 32-bit word.  Most of the bits in the second level entry are used
+ * by hardware, and there aren't any "accessed" and "dirty" bits.
+ *
+ * Linux on the other hand has a three level page table structure, which can
+ * be wrapped to fit a two level page table structure easily - using the PGD
+ * and PTE only.  However, Linux also expects one "PTE" table per page, and
+ * at least a "dirty" bit.
+ *
+ * Therefore, we tweak the implementation slightly - we tell Linux that we
+ * have 2048 entries in the first level, each of which is 8 bytes (iow, two
+ * hardware pointers to the second level.)  The second level contains two
+ * hardware PTE tables arranged contiguously, preceded by Linux versions
+ * which contain the state information Linux needs.  We, therefore, end up
+ * with 512 entries in the "PTE" level.
+ *
+ * This leads to the page tables having the following layout:
+ *
+ *    pgd             pte
+ * |        |
+ * +--------+
+ * |        |       +------------+ +0
+ * +- - - - +       | Linux pt 0 |
+ * |        |       +------------+ +1024
+ * +--------+ +0    | Linux pt 1 |
+ * |        |-----> +------------+ +2048
+ * +- - - - + +4    |  h/w pt 0  |
+ * |        |-----> +------------+ +3072
+ * +--------+ +8    |  h/w pt 1  |
+ * |        |       +------------+ +4096
+ *
+ * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
+ * PTE_xxx for definitions of bits appearing in the "h/w pt".
+ *
+ * PMD_xxx definitions refer to bits in the first level page table.
+ *
+ * The "dirty" bit is emulated by only granting hardware write permission
+ * iff the page is marked "writable" and "dirty" in the Linux PTE.  This
+ * means that a write to a clean page will cause a permission fault, and
+ * the Linux MM layer will mark the page dirty via handle_pte_fault().
+ * For the hardware to notice the permission change, the TLB entry must
+ * be flushed, and ptep_set_access_flags() does that for us.
+ *
+ * The "accessed" or "young" bit is emulated by a similar method; we only
+ * allow accesses to the page if the "young" bit is set.  Accesses to the
+ * page will cause a fault, and handle_pte_fault() will set the young bit
+ * for us as long as the page is marked present in the corresponding Linux
+ * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
+ *
+ * However, when the "young" bit is cleared, we deny access to the page
+ * by clearing the hardware PTE.  Currently Linux does not flush the TLB
+ * for us in this case, which means the TLB will retain the transation
+ * until either the TLB entry is evicted under pressure, or a context
+ * switch which changes the user space mapping occurs.
+ */
+#define PTRS_PER_PTE		512
+#define PTRS_PER_PMD		1
+#define PTRS_PER_PGD		2048
+
+#define PTE_HWTABLE_PTRS	(PTRS_PER_PTE)
+#define PTE_HWTABLE_OFF		(PTE_HWTABLE_PTRS * sizeof(pte_t))
+#define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u32))
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT		21
+#define PGDIR_SHIFT		21
+
+#define PMD_SIZE		(1UL << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		20
+#define SECTION_SIZE		(1UL << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+/*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT	24
+#define SUPERSECTION_SIZE	(1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK	(~(SUPERSECTION_SIZE-1))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT		(_AT(pteval_t, 1) << 0)
+#define L_PTE_YOUNG		(_AT(pteval_t, 1) << 1)
+#define L_PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !PRESENT */
+#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 6)
+#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)
+#define L_PTE_USER		(_AT(pteval_t, 1) << 8)
+#define L_PTE_XN		(_AT(pteval_t, 1) << 9)
+#define L_PTE_SHARED		(_AT(pteval_t, 1) << 10)	/* shared(v6), coherent(xsc3) */
+
+/*
+ * These are the memory types, defined to be compatible with
+ * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
+ */
+#define L_PTE_MT_UNCACHED	(_AT(pteval_t, 0x00) << 2)	/* 0000 */
+#define L_PTE_MT_BUFFERABLE	(_AT(pteval_t, 0x01) << 2)	/* 0001 */
+#define L_PTE_MT_WRITETHROUGH	(_AT(pteval_t, 0x02) << 2)	/* 0010 */
+#define L_PTE_MT_WRITEBACK	(_AT(pteval_t, 0x03) << 2)	/* 0011 */
+#define L_PTE_MT_MINICACHE	(_AT(pteval_t, 0x06) << 2)	/* 0110 (sa1100, xscale) */
+#define L_PTE_MT_WRITEALLOC	(_AT(pteval_t, 0x07) << 2)	/* 0111 */
+#define L_PTE_MT_DEV_SHARED	(_AT(pteval_t, 0x04) << 2)	/* 0100 */
+#define L_PTE_MT_DEV_NONSHARED	(_AT(pteval_t, 0x0c) << 2)	/* 1100 */
+#define L_PTE_MT_DEV_WC		(_AT(pteval_t, 0x09) << 2)	/* 1001 */
+#define L_PTE_MT_DEV_CACHED	(_AT(pteval_t, 0x0b) << 2)	/* 1011 */
+#define L_PTE_MT_MASK		(_AT(pteval_t, 0x0f) << 2)
+
+#endif /* _ASM_PGTABLE_2LEVEL_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level-hwdef.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level-hwdef.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level-hwdef.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level-hwdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ *  arch/arm/include/asm/pgtable-2level-hwdef.h
+ *
+ *  Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_HWDEF_H
+#define _ASM_PGTABLE_2LEVEL_HWDEF_H
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ *   - common
+ */
+#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT		(_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE		(_AT(pmdval_t, 1) << 0)
+#define PMD_TYPE_SECT		(_AT(pmdval_t, 2) << 0)
+#define PMD_BIT4		(_AT(pmdval_t, 1) << 4)
+#define PMD_DOMAIN(x)		(_AT(pmdval_t, (x)) << 5)
+#define PMD_PROTECTION		(_AT(pmdval_t, 1) << 9)		/* v5 */
+/*
+ *   - section
+ */
+#define PMD_SECT_BUFFERABLE	(_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_CACHEABLE	(_AT(pmdval_t, 1) << 3)
+#define PMD_SECT_XN		(_AT(pmdval_t, 1) << 4)		/* v6 */
+#define PMD_SECT_AP_WRITE	(_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_AP_READ	(_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_TEX(x)		(_AT(pmdval_t, (x)) << 12)	/* v5 */
+#define PMD_SECT_APX		(_AT(pmdval_t, 1) << 15)	/* v6 */
+#define PMD_SECT_S		(_AT(pmdval_t, 1) << 16)	/* v6 */
+#define PMD_SECT_nG		(_AT(pmdval_t, 1) << 17)	/* v6 */
+#define PMD_SECT_SUPER		(_AT(pmdval_t, 1) << 18)	/* v6 */
+#define PMD_SECT_AF		(_AT(pmdval_t, 0))
+
+#define PMD_SECT_UNCACHED	(_AT(pmdval_t, 0))
+#define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT		(PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA		(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV	(PMD_SECT_TEX(2))
+
+/*
+ *   - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ *   - common
+ */
+#define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_LARGE		(_AT(pteval_t, 1) << 0)
+#define PTE_TYPE_SMALL		(_AT(pteval_t, 2) << 0)
+#define PTE_TYPE_EXT		(_AT(pteval_t, 3) << 0)		/* v5 */
+#define PTE_BUFFERABLE		(_AT(pteval_t, 1) << 2)
+#define PTE_CACHEABLE		(_AT(pteval_t, 1) << 3)
+
+/*
+ *   - extended small page/tiny page
+ */
+#define PTE_EXT_XN		(_AT(pteval_t, 1) << 0)		/* v6 */
+#define PTE_EXT_AP_MASK		(_AT(pteval_t, 3) << 4)
+#define PTE_EXT_AP0		(_AT(pteval_t, 1) << 4)
+#define PTE_EXT_AP1		(_AT(pteval_t, 2) << 4)
+#define PTE_EXT_AP_UNO_SRO	(_AT(pteval_t, 0) << 4)
+#define PTE_EXT_AP_UNO_SRW	(PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW	(PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW	(PTE_EXT_AP1|PTE_EXT_AP0)
+#define PTE_EXT_TEX(x)		(_AT(pteval_t, (x)) << 6)	/* v5 */
+#define PTE_EXT_APX		(_AT(pteval_t, 1) << 9)		/* v6 */
+#define PTE_EXT_COHERENT	(_AT(pteval_t, 1) << 9)		/* XScale3 */
+#define PTE_EXT_SHARED		(_AT(pteval_t, 1) << 10)	/* v6 */
+#define PTE_EXT_NG		(_AT(pteval_t, 1) << 11)	/* v6 */
+
+/*
+ *   - small page
+ */
+#define PTE_SMALL_AP_MASK	(_AT(pteval_t, 0xff) << 4)
+#define PTE_SMALL_AP_UNO_SRO	(_AT(pteval_t, 0x00) << 4)
+#define PTE_SMALL_AP_UNO_SRW	(_AT(pteval_t, 0x55) << 4)
+#define PTE_SMALL_AP_URO_SRW	(_AT(pteval_t, 0xaa) << 4)
+#define PTE_SMALL_AP_URW_SRW	(_AT(pteval_t, 0xff) << 4)
+
+#define PHYS_MASK		(~0UL)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level-types.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level-types.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-2level-types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-2level-types.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-types.h
+ *
+ * Copyright (C) 1995-2003 Russell King
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_TYPES_H
+#define _ASM_PGTABLE_2LEVEL_TYPES_H
+
+#include <asm/types.h>
+
+typedef u32 pteval_t;
+typedef u32 pmdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pmdval_t pgd[2]; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)	((x).pgd[0])
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef pteval_t pte_t;
+typedef pmdval_t pmd_t;
+typedef pmdval_t pgd_t[2];
+typedef pteval_t pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)	((x)[0])
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgprot(x)     (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+#endif	/* _ASM_PGTABLE_2LEVEL_TYPES_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <mach/vmalloc.h>
 #include <asm/pgtable-hwdef.h>
 
+#include <asm/pgtable-2level.h>
+
 /*
  * Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -41,79 +43,6 @@
 #define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #endif
 
-/*
- * Hardware-wise, we have a two level page table structure, where the first
- * level has 4096 entries, and the second level has 256 entries.  Each entry
- * is one 32-bit word.  Most of the bits in the second level entry are used
- * by hardware, and there aren't any "accessed" and "dirty" bits.
- *
- * Linux on the other hand has a three level page table structure, which can
- * be wrapped to fit a two level page table structure easily - using the PGD
- * and PTE only.  However, Linux also expects one "PTE" table per page, and
- * at least a "dirty" bit.
- *
- * Therefore, we tweak the implementation slightly - we tell Linux that we
- * have 2048 entries in the first level, each of which is 8 bytes (iow, two
- * hardware pointers to the second level.)  The second level contains two
- * hardware PTE tables arranged contiguously, preceded by Linux versions
- * which contain the state information Linux needs.  We, therefore, end up
- * with 512 entries in the "PTE" level.
- *
- * This leads to the page tables having the following layout:
- *
- *    pgd             pte
- * |        |
- * +--------+
- * |        |       +------------+ +0
- * +- - - - +       | Linux pt 0 |
- * |        |       +------------+ +1024
- * +--------+ +0    | Linux pt 1 |
- * |        |-----> +------------+ +2048
- * +- - - - + +4    |  h/w pt 0  |
- * |        |-----> +------------+ +3072
- * +--------+ +8    |  h/w pt 1  |
- * |        |       +------------+ +4096
- *
- * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
- * PTE_xxx for definitions of bits appearing in the "h/w pt".
- *
- * PMD_xxx definitions refer to bits in the first level page table.
- *
- * The "dirty" bit is emulated by only granting hardware write permission
- * iff the page is marked "writable" and "dirty" in the Linux PTE.  This
- * means that a write to a clean page will cause a permission fault, and
- * the Linux MM layer will mark the page dirty via handle_pte_fault().
- * For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_set_access_flags() does that for us.
- *
- * The "accessed" or "young" bit is emulated by a similar method; we only
- * allow accesses to the page if the "young" bit is set.  Accesses to the
- * page will cause a fault, and handle_pte_fault() will set the young bit
- * for us as long as the page is marked present in the corresponding Linux
- * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
- * up to date.
- *
- * However, when the "young" bit is cleared, we deny access to the page
- * by clearing the hardware PTE.  Currently Linux does not flush the TLB
- * for us in this case, which means the TLB will retain the transation
- * until either the TLB entry is evicted under pressure, or a context
- * switch which changes the user space mapping occurs.
- */
-#define PTRS_PER_PTE		512
-#define PTRS_PER_PMD		1
-#define PTRS_PER_PGD		2048
-
-#define PTE_HWTABLE_PTRS	(PTRS_PER_PTE)
-#define PTE_HWTABLE_OFF		(PTE_HWTABLE_PTRS * sizeof(pte_t))
-#define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u32))
-
-/*
- * PMD_SHIFT determines the size of the area a second-level page table can map
- * PGDIR_SHIFT determines what a third-level page table entry can map
- */
-#define PMD_SHIFT		21
-#define PGDIR_SHIFT		21
-
 #define LIBRARY_TEXT_START	0x0c000000
 
 #ifndef __ASSEMBLY__
@@ -124,12 +53,6 @@ extern void __pgd_error(const char *file
 #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte)
 #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd)
 #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd)
-#endif /* !__ASSEMBLY__ */
-
-#define PMD_SIZE		(1UL << PMD_SHIFT)
-#define PMD_MASK		(~(PMD_SIZE-1))
-#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK		(~(PGDIR_SIZE-1))
 
 /*
  * This is the lowest virtual address we can permit any user space
@@ -138,60 +61,6 @@ extern void __pgd_error(const char *file
  */
 #define FIRST_USER_ADDRESS	PAGE_SIZE
 
-#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT		20
-#define SECTION_SIZE		(1UL << SECTION_SHIFT)
-#define SECTION_MASK		(~(SECTION_SIZE-1))
-
-/*
- * ARMv6 supersection address mask and size definitions.
- */
-#define SUPERSECTION_SHIFT	24
-#define SUPERSECTION_SIZE	(1UL << SUPERSECTION_SHIFT)
-#define SUPERSECTION_MASK	(~(SUPERSECTION_SIZE-1))
-
-/*
- * "Linux" PTE definitions.
- *
- * We keep two sets of PTEs - the hardware and the linux version.
- * This allows greater flexibility in the way we map the Linux bits
- * onto the hardware tables, and allows us to have YOUNG and DIRTY
- * bits.
- *
- * The PTE table pointer refers to the hardware entries; the "Linux"
- * entries are stored 1024 bytes below.
- */
-#define L_PTE_PRESENT		(_AT(pteval_t, 1) << 0)
-#define L_PTE_YOUNG		(_AT(pteval_t, 1) << 1)
-#define L_PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !PRESENT */
-#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 6)
-#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)
-#define L_PTE_USER		(_AT(pteval_t, 1) << 8)
-#define L_PTE_XN		(_AT(pteval_t, 1) << 9)
-#define L_PTE_SHARED		(_AT(pteval_t, 1) << 10)	/* shared(v6), coherent(xsc3) */
-
-/*
- * These are the memory types, defined to be compatible with
- * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
- */
-#define L_PTE_MT_UNCACHED	(_AT(pteval_t, 0x00) << 2)	/* 0000 */
-#define L_PTE_MT_BUFFERABLE	(_AT(pteval_t, 0x01) << 2)	/* 0001 */
-#define L_PTE_MT_WRITETHROUGH	(_AT(pteval_t, 0x02) << 2)	/* 0010 */
-#define L_PTE_MT_WRITEBACK	(_AT(pteval_t, 0x03) << 2)	/* 0011 */
-#define L_PTE_MT_MINICACHE	(_AT(pteval_t, 0x06) << 2)	/* 0110 (sa1100, xscale) */
-#define L_PTE_MT_WRITEALLOC	(_AT(pteval_t, 0x07) << 2)	/* 0111 */
-#define L_PTE_MT_DEV_SHARED	(_AT(pteval_t, 0x04) << 2)	/* 0100 */
-#define L_PTE_MT_DEV_NONSHARED	(_AT(pteval_t, 0x0c) << 2)	/* 1100 */
-#define L_PTE_MT_DEV_WC		(_AT(pteval_t, 0x09) << 2)	/* 1001 */
-#define L_PTE_MT_DEV_CACHED	(_AT(pteval_t, 0x0b) << 2)	/* 1011 */
-#define L_PTE_MT_MASK		(_AT(pteval_t, 0x0f) << 2)
-
-#ifndef __ASSEMBLY__
-
 /*
  * The pgprot_* and protection_map entries will be fixed up in runtime
  * to include the cachable and bufferable bits based on memory policy,
@@ -232,6 +101,9 @@ extern pgprot_t		pgprot_kernel;
 #define pgprot_writecombine(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
 
+#define pgprot_stronglyordered(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
 #define pgprot_dmacoherent(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
@@ -327,10 +199,10 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
-	return __va(pmd_val(pmd) & PAGE_MASK);
+	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
 }
 
-#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
 
 /* we don't need complex calculations here as the pmd is folded into the pgd */
 #define pmd_addr_end(addr,end)	(end)
@@ -351,7 +223,7 @@ static inline pte_t *pmd_page_vaddr(pmd_
 #define pte_offset_map(pmd,addr)	(__pte_map(pmd) + pte_index(addr))
 #define pte_unmap(pte)			__pte_unmap(pte)
 
-#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+#define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
 #define pfn_pte(pfn,prot)	__pte(__pfn_to_phys(pfn) | pgprot_val(prot))
 
 #define pte_page(pte)		pfn_to_page(pte_pfn(pte))
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-hwdef.h linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-hwdef.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pgtable-hwdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pgtable-hwdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,81 +10,6 @@
 #ifndef _ASMARM_PGTABLE_HWDEF_H
 #define _ASMARM_PGTABLE_HWDEF_H
 
-/*
- * Hardware page table definitions.
- *
- * + Level 1 descriptor (PMD)
- *   - common
- */
-#define PMD_TYPE_MASK		(3 << 0)
-#define PMD_TYPE_FAULT		(0 << 0)
-#define PMD_TYPE_TABLE		(1 << 0)
-#define PMD_TYPE_SECT		(2 << 0)
-#define PMD_BIT4		(1 << 4)
-#define PMD_DOMAIN(x)		((x) << 5)
-#define PMD_PROTECTION		(1 << 9)	/* v5 */
-/*
- *   - section
- */
-#define PMD_SECT_BUFFERABLE	(1 << 2)
-#define PMD_SECT_CACHEABLE	(1 << 3)
-#define PMD_SECT_XN		(1 << 4)	/* v6 */
-#define PMD_SECT_AP_WRITE	(1 << 10)
-#define PMD_SECT_AP_READ	(1 << 11)
-#define PMD_SECT_TEX(x)		((x) << 12)	/* v5 */
-#define PMD_SECT_APX		(1 << 15)	/* v6 */
-#define PMD_SECT_S		(1 << 16)	/* v6 */
-#define PMD_SECT_nG		(1 << 17)	/* v6 */
-#define PMD_SECT_SUPER		(1 << 18)	/* v6 */
-
-#define PMD_SECT_UNCACHED	(0)
-#define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
-#define PMD_SECT_WT		(PMD_SECT_CACHEABLE)
-#define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
-#define PMD_SECT_WBWA		(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_NONSHARED_DEV	(PMD_SECT_TEX(2))
-
-/*
- *   - coarse table (not used)
- */
-
-/*
- * + Level 2 descriptor (PTE)
- *   - common
- */
-#define PTE_TYPE_MASK		(3 << 0)
-#define PTE_TYPE_FAULT		(0 << 0)
-#define PTE_TYPE_LARGE		(1 << 0)
-#define PTE_TYPE_SMALL		(2 << 0)
-#define PTE_TYPE_EXT		(3 << 0)	/* v5 */
-#define PTE_BUFFERABLE		(1 << 2)
-#define PTE_CACHEABLE		(1 << 3)
-
-/*
- *   - extended small page/tiny page
- */
-#define PTE_EXT_XN		(1 << 0)	/* v6 */
-#define PTE_EXT_AP_MASK		(3 << 4)
-#define PTE_EXT_AP0		(1 << 4)
-#define PTE_EXT_AP1		(2 << 4)
-#define PTE_EXT_AP_UNO_SRO	(0 << 4)
-#define PTE_EXT_AP_UNO_SRW	(PTE_EXT_AP0)
-#define PTE_EXT_AP_URO_SRW	(PTE_EXT_AP1)
-#define PTE_EXT_AP_URW_SRW	(PTE_EXT_AP1|PTE_EXT_AP0)
-#define PTE_EXT_TEX(x)		((x) << 6)	/* v5 */
-#define PTE_EXT_APX		(1 << 9)	/* v6 */
-#define PTE_EXT_COHERENT	(1 << 9)	/* XScale3 */
-#define PTE_EXT_SHARED		(1 << 10)	/* v6 */
-#define PTE_EXT_NG		(1 << 11)	/* v6 */
-
-/*
- *   - small page
- */
-#define PTE_SMALL_AP_MASK	(0xff << 4)
-#define PTE_SMALL_AP_UNO_SRO	(0x00 << 4)
-#define PTE_SMALL_AP_UNO_SRW	(0x55 << 4)
-#define PTE_SMALL_AP_URO_SRW	(0xaa << 4)
-#define PTE_SMALL_AP_URW_SRW	(0xff << 4)
+#include <asm/pgtable-2level-hwdef.h>
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/pmu.h linux-libre-3.2-gnu1/arch/arm/include/asm/pmu.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,12 @@
 #define __ARM_PMU_H__
 
 #include <linux/interrupt.h>
+#include <linux/perf_event.h>
 
+/*
+ * Types of PMUs that can be accessed directly and require mutual
+ * exclusion between profiling tools.
+ */
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
 	ARM_NUM_PMU_DEVICES,
@@ -37,55 +42,95 @@ struct arm_pmu_platdata {
  * reserve_pmu() - reserve the hardware performance counters
  *
  * Reserve the hardware performance counters in the system for exclusive use.
- * The platform_device for the system is returned on success, ERR_PTR()
- * encoded error on failure.
+ * Returns 0 on success or -EBUSY if the lock is already held.
  */
-extern struct platform_device *
+extern int
 reserve_pmu(enum arm_pmu_type type);
 
 /**
  * release_pmu() - Relinquish control of the performance counters
  *
  * Release the performance counters and allow someone else to use them.
- * Callers must have disabled the counters and released IRQs before calling
- * this. The platform_device returned from reserve_pmu() must be passed as
- * a cookie.
  */
-extern int
+extern void
 release_pmu(enum arm_pmu_type type);
 
-/**
- * init_pmu() - Initialise the PMU.
- *
- * Initialise the system ready for PMU enabling. This should typically set the
- * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
- * the actual hardware initialisation.
- */
-extern int
-init_pmu(enum arm_pmu_type type);
-
 #else /* CONFIG_CPU_HAS_PMU */
 
 #include <linux/err.h>
 
-static inline struct platform_device *
-reserve_pmu(enum arm_pmu_type type)
-{
-	return ERR_PTR(-ENODEV);
-}
-
 static inline int
-release_pmu(enum arm_pmu_type type)
+reserve_pmu(enum arm_pmu_type type)
 {
 	return -ENODEV;
 }
 
-static inline int
-init_pmu(enum arm_pmu_type type)
-{
-	return -ENODEV;
-}
+static inline void
+release_pmu(enum arm_pmu_type type)	{ }
 
 #endif /* CONFIG_CPU_HAS_PMU */
 
+#ifdef CONFIG_HW_PERF_EVENTS
+
+/* The events for a given PMU register set. */
+struct pmu_hw_events {
+	/*
+	 * The events that are active on the PMU for the given index.
+	 */
+	struct perf_event	**events;
+
+	/*
+	 * A 1 bit for an index indicates that the counter is being used for
+	 * an event. A 0 means that the counter can be used.
+	 */
+	unsigned long           *used_mask;
+
+	/*
+	 * Hardware lock to serialize accesses to PMU registers. Needed for the
+	 * read/modify/write sequences.
+	 */
+	raw_spinlock_t		pmu_lock;
+};
+
+struct arm_pmu {
+	struct pmu	pmu;
+	enum arm_perf_pmu_ids id;
+	enum arm_pmu_type type;
+	cpumask_t	active_irqs;
+	const char	*name;
+	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
+	void		(*enable)(struct hw_perf_event *evt, int idx);
+	void		(*disable)(struct hw_perf_event *evt, int idx);
+	int		(*get_event_idx)(struct pmu_hw_events *hw_events,
+					 struct hw_perf_event *hwc);
+	int		(*set_event_filter)(struct hw_perf_event *evt,
+					    struct perf_event_attr *attr);
+	u32		(*read_counter)(int idx);
+	void		(*write_counter)(int idx, u32 val);
+	void		(*start)(void);
+	void		(*stop)(void);
+	void		(*reset)(void *);
+	int		(*map_event)(struct perf_event *event);
+	int		num_events;
+	atomic_t	active_events;
+	struct mutex	reserve_mutex;
+	u64		max_period;
+	struct platform_device	*plat_device;
+	struct pmu_hw_events	*(*get_hw_events)(void);
+};
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+
+u64 armpmu_event_update(struct perf_event *event,
+			struct hw_perf_event *hwc,
+			int idx, int overflow);
+
+int armpmu_event_set_period(struct perf_event *event,
+			    struct hw_perf_event *hwc,
+			    int idx);
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
 #endif /* __ARM_PMU_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/poll.h linux-libre-3.2-gnu1/arch/arm/include/asm/poll.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/poll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/poll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/proc-fns.h linux-libre-3.2-gnu1/arch/arm/include/asm/proc-fns.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/proc-fns.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/proc-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,6 +81,10 @@ extern void cpu_dcache_clean_area(void *
 extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
 extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
+
+/* These three are private to arch/arm/kernel/suspend.c */
+extern void cpu_do_suspend(void *);
+extern void cpu_do_resume(void *);
 #else
 #define cpu_proc_init			processor._proc_init
 #define cpu_proc_fin			processor._proc_fin
@@ -89,6 +93,10 @@ extern void cpu_reset(unsigned long addr
 #define cpu_dcache_clean_area		processor.dcache_clean_area
 #define cpu_set_pte_ext			processor.set_pte_ext
 #define cpu_do_switch_mm		processor.switch_mm
+
+/* These three are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend			processor.do_suspend
+#define cpu_do_resume			processor.do_resume
 #endif
 
 extern void cpu_resume(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/resource.h linux-libre-3.2-gnu1/arch/arm/include/asm/resource.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/resource.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/resource.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ARM_RESOURCE_H
-#define _ARM_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/sections.h linux-libre-3.2-gnu1/arch/arm/include/asm/sections.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/sections.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/sections.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/siginfo.h linux-libre-3.2-gnu1/arch/arm/include/asm/siginfo.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/siginfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/siginfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASMARM_SIGINFO_H
-#define _ASMARM_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/sizes.h linux-libre-3.2-gnu1/arch/arm/include/asm/sizes.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/sizes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/sizes.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*  Size definitions
- *  Copyright (C) ARM Limited 1998. All rights reserved.
- */
-#include <asm-generic/sizes.h>
-
-#define SZ_48M	(SZ_32M + SZ_16M)
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/smp.h linux-libre-3.2-gnu1/arch/arm/include/asm/smp.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,11 @@ extern void show_ipi_list(struct seq_fil
 asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
 
 /*
+ * Called from C code, this handles an IPI.
+ */
+void handle_IPI(int ipinr, struct pt_regs *regs);
+
+/*
  * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
@@ -66,6 +71,12 @@ extern void platform_secondary_init(unsi
 extern void platform_smp_prepare_cpus(unsigned int);
 
 /*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)	__cpu_logical_map[cpu]
+
+/*
  * Initial data for bringing up a secondary CPU.
  */
 struct secondary_data {
@@ -88,9 +99,4 @@ extern void platform_cpu_enable(unsigned
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
-/*
- * show local interrupt info
- */
-extern void show_local_irqs(struct seq_file *, int);
-
 #endif /* ifndef __ASM_ARM_SMP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/smp_twd.h linux-libre-3.2-gnu1/arch/arm/include/asm/smp_twd.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/smp_twd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/smp_twd.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@ struct clock_event_device;
 
 extern void __iomem *twd_base;
 
-int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
+void twd_timer_stop(struct clock_event_device *);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/suspend.h linux-libre-3.2-gnu1/arch/arm/include/asm/suspend.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/suspend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/suspend.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,22 +1,7 @@
 #ifndef __ASM_ARM_SUSPEND_H
 #define __ASM_ARM_SUSPEND_H
 
-#include <asm/memory.h>
-#include <asm/tlbflush.h>
-
 extern void cpu_resume(void);
-
-/*
- * Hide the first two arguments to __cpu_suspend - these are an implementation
- * detail which platform code shouldn't have to know about.
- */
-static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
-{
-	extern int __cpu_suspend(int, long, unsigned long,
-				 int (*)(unsigned long));
-	int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
-	flush_tlb_all();
-	return ret;
-}
+extern int cpu_suspend(unsigned long, int (*)(unsigned long));
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/system.h linux-libre-3.2-gnu1/arch/arm/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,18 +57,12 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
 
 #include <asm/outercache.h>
 
-#define __exception	__attribute__((section(".exception.text")))
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#define __exception_irq_entry	__irq_entry
-#else
-#define __exception_irq_entry	__exception
-#endif
-
 struct thread_info;
 struct task_struct;
 
@@ -97,14 +91,13 @@ void hook_ifault_code(int nr, int (*fn)(
 #define xchg(ptr,x) \
 	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-extern asmlinkage void __backtrace(void);
 extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
 
 struct mm_struct;
 extern void show_pte(struct mm_struct *mm, unsigned long addr);
 extern void __show_regs(struct pt_regs *);
 
-extern int cpu_architecture(void);
+extern int __pure cpu_architecture(void);
 extern void cpu_init(void);
 
 void arm_machine_restart(char mode, const char *cmd);
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/tlbflush.h linux-libre-3.2-gnu1/arch/arm/include/asm/tlbflush.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/tlbflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -471,7 +471,7 @@ static inline void local_flush_tlb_kerne
  *	these operations.  This is typically used when we are removing
  *	PMD entries.
  */
-static inline void flush_pmd_entry(pmd_t *pmd)
+static inline void flush_pmd_entry(void *pmd)
 {
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
@@ -487,7 +487,7 @@ static inline void flush_pmd_entry(pmd_t
 		dsb();
 }
 
-static inline void clean_pmd_entry(pmd_t *pmd)
+static inline void clean_pmd_entry(void *pmd)
 {
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/topology.h linux-libre-3.2-gnu1/arch/arm/include/asm/topology.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/topology.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,39 @@
 #ifndef _ASM_ARM_TOPOLOGY_H
 #define _ASM_ARM_TOPOLOGY_H
 
+#ifdef CONFIG_ARM_CPU_TOPOLOGY
+
+#include <linux/cpumask.h>
+
+struct cputopo_arm {
+	int thread_id;
+	int core_id;
+	int socket_id;
+	cpumask_t thread_sibling;
+	cpumask_t core_sibling;
+};
+
+extern struct cputopo_arm cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id)
+#define topology_core_id(cpu)		(cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)	(&cpu_topology[cpu].core_sibling)
+#define topology_thread_cpumask(cpu)	(&cpu_topology[cpu].thread_sibling)
+
+#define mc_capable()	(cpu_topology[0].socket_id != -1)
+#define smt_capable()	(cpu_topology[0].thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
+
+#else
+
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_ARM_TOPOLOGY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/unistd.h linux-libre-3.2-gnu1/arch/arm/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -402,6 +402,8 @@
 #define __NR_syncfs			(__NR_SYSCALL_BASE+373)
 #define __NR_sendmmsg			(__NR_SYSCALL_BASE+374)
 #define __NR_setns			(__NR_SYSCALL_BASE+375)
+#define __NR_process_vm_readv		(__NR_SYSCALL_BASE+376)
+#define __NR_process_vm_writev		(__NR_SYSCALL_BASE+377)
 
 /*
  * The following SWIs are ARM private.
diff -druNp linux-libre-3.1-gnu1/arch/arm/include/asm/unwind.h linux-libre-3.2-gnu1/arch/arm/include/asm/unwind.h
--- linux-libre-3.1-gnu1/arch/arm/include/asm/unwind.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/include/asm/unwind.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,14 +30,15 @@ enum unwind_reason_code {
 };
 
 struct unwind_idx {
-	unsigned long addr;
+	unsigned long addr_offset;
 	unsigned long insn;
 };
 
 struct unwind_table {
 	struct list_head list;
-	struct unwind_idx *start;
-	struct unwind_idx *stop;
+	const struct unwind_idx *start;
+	const struct unwind_idx *origin;
+	const struct unwind_idx *stop;
 	unsigned long begin_addr;
 	unsigned long end_addr;
 };
@@ -49,15 +50,6 @@ extern struct unwind_table *unwind_table
 extern void unwind_table_del(struct unwind_table *tab);
 extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk);
 
-#ifdef CONFIG_ARM_UNWIND
-extern int __init unwind_init(void);
-#else
-static inline int __init unwind_init(void)
-{
-	return 0;
-}
-#endif
-
 #endif	/* !__ASSEMBLY__ */
 
 #ifdef CONFIG_ARM_UNWIND
diff -druNp linux-libre-3.1-gnu1/arch/arm/Kconfig linux-libre-3.2-gnu1/arch/arm/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@ config ARM
 	default y
 	select HAVE_AOUT
 	select HAVE_DMA_API_DEBUG
-	select HAVE_IDE
+	select HAVE_IDE if PCI || ISA || PCMCIA
 	select HAVE_MEMBLOCK
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
@@ -29,6 +29,7 @@ config ARM
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
 	select GENERIC_IRQ_SHOW
+	select CPU_PM if (SUSPEND || CPU_IDLE)
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -195,7 +196,8 @@ config VECTORS_BASE
 	  The base address of exception vectors.
 
 config ARM_PATCH_PHYS_VIRT
-	bool "Patch physical to virtual translations at runtime"
+	bool "Patch physical to virtual translations at runtime" if EMBEDDED
+	default y
 	depends on !XIP_KERNEL && MMU
 	depends on !ARCH_REALVIEW || !SPARSEMEM
 	help
@@ -204,16 +206,30 @@ config ARM_PATCH_PHYS_VIRT
 	  kernel in system memory.
 
 	  This can only be used with non-XIP MMU kernels where the base
-	  of physical memory is at a 16MB boundary, or theoretically 64K
-	  for the MSM machine class.
+	  of physical memory is at a 16MB boundary.
 
-config ARM_PATCH_PHYS_VIRT_16BIT
-	def_bool y
-	depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM
+	  Only disable this option if you know that you do not require
+	  this feature (eg, building a kernel for a single machine) and
+	  you need to shrink the kernel to the minimal size.
+
+config NEED_MACH_MEMORY_H
+	bool
 	help
-	  This option extends the physical to virtual translation patching
-	  to allow physical memory down to a theoretical minimum of 64K
-	  boundaries.
+	  Select this when mach/memory.h is required to provide special
+	  definitions for this platform.  The need for mach/memory.h should
+	  be avoided when possible.
+
+config PHYS_OFFSET
+	hex "Physical address of main memory" if MMU
+	depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
+	default DRAM_BASE if !MMU
+	help
+	  Please provide the physical address corresponding to the
+	  location of main memory in your system.
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
 
 source "init/Kconfig"
 
@@ -246,6 +262,7 @@ config ARCH_INTEGRATOR
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_FPGA_IRQ
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for ARM's Integrator platform.
 
@@ -261,6 +278,7 @@ config ARCH_REALVIEW
 	select PLAT_VERSATILE_CLCD
 	select ARM_TIMER_SP804
 	select GPIO_PL061 if GPIOLIB
+	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for ARM Ltd RealView boards.
 
@@ -301,7 +319,6 @@ config ARCH_AT91
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
 	select CLKDEV_LOOKUP
-	select ARM_PATCH_PHYS_VIRT if MMU
 	help
 	  This enables support for systems based on the Atmel AT91RM9200,
 	  AT91SAM9 and AT91CAP9 processors.
@@ -318,10 +335,25 @@ config ARCH_BCMRING
 	help
 	  Support for Broadcom's BCMRing platform.
 
+config ARCH_HIGHBANK
+	bool "Calxeda Highbank-based"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select CLKDEV_LOOKUP
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU
+	select USE_OF
+	help
+	  Support for the Calxeda Highbank SoC based boards.
+
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x-based"
 	select CPU_ARM720T
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Cirrus Logic 711x/721x based boards.
 
@@ -346,7 +378,6 @@ config ARCH_GEMINI
 config ARCH_PRIMA2
 	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
 	select CPU_V7
-	select GENERIC_TIME
 	select NO_IOPORT
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
@@ -362,6 +393,7 @@ config ARCH_EBSA110
 	select ISA
 	select NO_IOPORT
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  This is an evaluation board for the StrongARM processor available
 	  from Digital. It has limited hardware on-board, including an
@@ -377,6 +409,7 @@ config ARCH_EP93XX
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
@@ -385,6 +418,8 @@ config ARCH_FOOTBRIDGE
 	select CPU_SA110
 	select FOOTBRIDGE
 	select GENERIC_CLOCKEVENTS
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -397,6 +432,7 @@ config ARCH_MXC
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
+	select MULTI_IRQ_HANDLER
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -434,6 +470,7 @@ config ARCH_IOP13XX
 	select PCI
 	select ARCH_SUPPORTS_MSI
 	select VMSPLIT_1G
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IOP13XX (XScale) family of processors.
 
@@ -464,6 +501,7 @@ config ARCH_IXP23XX
 	select CPU_XSC3
  	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IXP23xx (XScale) family of processors.
 
@@ -473,6 +511,7 @@ config ARCH_IXP2000
 	select CPU_XSCALE
 	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IXP2400/2800 (XScale) family of processors.
 
@@ -519,7 +558,6 @@ config ARCH_LPC32XX
 	select ARM_AMBA
 	select USB_ARCH_HAS_OHCI
 	select CLKDEV_LOOKUP
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	help
 	  Support for the NXP LPC32XX family of processors
@@ -558,6 +596,7 @@ config ARCH_MMP
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
+	select GENERIC_ALLOCATOR
 	help
 	  Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -566,6 +605,7 @@ config ARCH_KS8695
 	select CPU_ARM922T
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
 	  System-on-Chip devices.
@@ -586,19 +626,10 @@ config ARCH_W90X900
 	  <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
 		ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
 
-config ARCH_NUC93X
-	bool "Nuvoton NUC93X CPU"
-	select CPU_ARM926T
-	select CLKDEV_LOOKUP
-	help
-	  Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
-	  low-power and high performance MPEG-4/JPEG multimedia controller chip.
-
 config ARCH_TEGRA
 	bool "NVIDIA Tegra"
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
 	select HAVE_CLK
@@ -608,6 +639,24 @@ config ARCH_TEGRA
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
 	  Tegra 6xx and Tegra 2 series).
 
+config ARCH_PICOXCELL
+	bool "Picochip picoXcell"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_PATCH_PHYS_VIRT
+	select ARM_VIC
+	select CPU_V6K
+	select DW_APB_TIMER
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_SCHED_CLOCK
+	select HAVE_TCM
+	select NO_IOPORT
+	select USE_OF
+	help
+	  This enables support for systems based on the Picochip picoXcell
+	  family of Femtocell devices.  The picoxcell support requires device tree
+	  for all boards.
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -631,6 +680,8 @@ config ARCH_PXA
 	select SPARSE_IRQ
 	select AUTO_ZRELADDR
 	select MULTI_IRQ_HANDLER
+	select ARM_CPU_SUSPEND if PM
+	select HAVE_IDE
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -657,6 +708,7 @@ config ARCH_SHMOBILE
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
 	select PM_GENERIC_DOMAINS if PM
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
 
@@ -671,6 +723,8 @@ config ARCH_RPC
 	select NO_IOPORT
 	select ARCH_SPARSEMEM_ENABLE
 	select ARCH_USES_GETTIMEOFFSET
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  On the Acorn Risc-PC, Linux can support the internal IDE disk and
 	  CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -689,6 +743,8 @@ config ARCH_SA1100
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for StrongARM 11x0 based boards.
 
@@ -715,6 +771,7 @@ config ARCH_S3C64XX
 	select CPU_V6
 	select ARM_VIC
 	select HAVE_CLK
+	select HAVE_TCM
 	select CLKDEV_LOOKUP
 	select NO_IOPORT
 	select ARCH_USES_GETTIMEOFFSET
@@ -722,11 +779,7 @@ config ARCH_S3C64XX
 	select ARCH_REQUIRE_GPIOLIB
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_IRQ_VIC_TIMER
-	select SAMSUNG_IRQ_UART
 	select S3C_GPIO_TRACK
-	select S3C_GPIO_PULL_UPDOWN
-	select S3C_GPIO_CFG_S3C24XX
-	select S3C_GPIO_CFG_S3C64XX
 	select S3C_DEV_NAND
 	select USB_ARCH_HAS_OHCI
 	select SAMSUNG_GPIOLIB_4BIT
@@ -781,11 +834,12 @@ config ARCH_S5PV210
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_MEMORY_H
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_EXYNOS4
-	bool "Samsung EXYNOS4"
+config ARCH_EXYNOS
+	bool "SAMSUNG EXYNOS"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
 	select ARCH_HAS_HOLES_MEMORYMODEL
@@ -797,8 +851,9 @@ config ARCH_EXYNOS4
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_MEMORY_H
 	help
-	  Samsung EXYNOS4 series based systems
+	  Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
 
 config ARCH_SHARK
 	bool "Shark"
@@ -808,6 +863,7 @@ config ARCH_SHARK
 	select ZONE_DMA
 	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for the StrongARM based Digital DNARD machine, also known
 	  as "Shark" (<http://www.shark-linux.de/shark.html>).
@@ -830,11 +886,14 @@ config ARCH_U300
 	select HAVE_SCHED_CLOCK
 	select HAVE_TCM
 	select ARM_AMBA
+	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
 	select HAVE_MACH_CLKDEV
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
 
@@ -910,7 +969,6 @@ config ARCH_VT8500
 config ARCH_ZYNQ
 	bool "Xilinx Zynq ARM Cortex A9 Platform"
 	select CPU_V7
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
 	select ARM_GIC
@@ -979,8 +1037,6 @@ source "arch/arm/mach-netx/Kconfig"
 source "arch/arm/mach-nomadik/Kconfig"
 source "arch/arm/plat-nomadik/Kconfig"
 
-source "arch/arm/mach-nuc93x/Kconfig"
-
 source "arch/arm/plat-omap/Kconfig"
 
 source "arch/arm/mach-omap1/Kconfig"
@@ -1024,7 +1080,7 @@ source "arch/arm/mach-s5pc100/Kconfig"
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
-source "arch/arm/mach-exynos4/Kconfig"
+source "arch/arm/mach-exynos/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
@@ -1176,7 +1232,7 @@ config ARM_ERRATA_742231
 	  capabilities of the processor.
 
 config PL310_ERRATA_588369
-	bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+	bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
 	depends on CACHE_L2X0
 	help
 	   The PL310 L2 cache controller implements three types of Clean &
@@ -1190,7 +1246,7 @@ config PL310_ERRATA_588369
 
 config ARM_ERRATA_720789
 	bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
-	depends on CPU_V7 && SMP
+	depends on CPU_V7
 	help
 	  This option enables the workaround for the 720789 Cortex-A9 (prior to
 	  r2p0) erratum. A faulty ASID can be sent to the other CPUs for the
@@ -1201,7 +1257,7 @@ config ARM_ERRATA_720789
 	  entries regardless of the ASID.
 
 config PL310_ERRATA_727915
-	bool "Background Clean & Invalidate by Way operation can cause data corruption"
+	bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
 	depends on CACHE_L2X0
 	help
 	  PL310 implements the Clean & Invalidate by Way L2 cache maintenance
@@ -1226,7 +1282,7 @@ config ARM_ERRATA_743622
 
 config ARM_ERRATA_751472
 	bool "ARM errata: Interrupted ICIALLUIS may prevent completion of broadcasted operation"
-	depends on CPU_V7 && SMP
+	depends on CPU_V7
 	help
 	  This option enables the workaround for the 751472 Cortex-A9 (prior
 	  to r3p0) erratum. An interrupted ICIALLUIS operation may prevent the
@@ -1234,8 +1290,8 @@ config ARM_ERRATA_751472
 	  operation is received by a CPU before the ICIALLUIS has completed,
 	  potentially leading to corrupted entries in the cache or TLB.
 
-config ARM_ERRATA_753970
-	bool "ARM errata: cache sync operation may be faulty"
+config PL310_ERRATA_753970
+	bool "PL310 errata: cache sync operation may be faulty"
 	depends on CACHE_PL310
 	help
 	  This option enables the workaround for the 753970 PL310 (r3p0) erratum.
@@ -1297,6 +1353,18 @@ config ARM_ERRATA_764369
 	  relevant cache maintenance functions and sets a specific bit
 	  in the diagnostic control register of the SCU.
 
+config PL310_ERRATA_769419
+	bool "PL310 errata: no automatic Store Buffer drain"
+	depends on CACHE_L2X0
+	help
+	  On revisions of the PL310 prior to r3p2, the Store Buffer does
+	  not automatically drain. This can cause normal, non-cacheable
+	  writes to be retained when the memory system is idle, leading
+	  to suboptimal I/O performance for drivers using coherent DMA.
+	  This option adds a write barrier to the cpu_idle loop so that,
+	  on systems with an outer cache, the store buffer is drained
+	  explicitly.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1374,7 +1442,8 @@ config SMP
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
 		 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
-		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
+		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q
+	depends on MMU
 	select USE_GENERIC_SMP_HELPERS
 	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
 	help
@@ -1388,7 +1457,7 @@ config SMP
 	  processor machines. On a single processor machine, the kernel will
 	  run faster if you say N here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://tldp.org/HOWTO/SMP-HOWTO.html>.
 
@@ -1407,6 +1476,31 @@ config SMP_ON_UP
 
 	  If you don't know what to do here, say Y.
 
+config ARM_CPU_TOPOLOGY
+	bool "Support cpu topology definition"
+	depends on SMP && CPU_V7
+	default y
+	help
+	  Support ARM cpu topology definition. The MPIDR register defines
+	  affinity between processors which is then used to describe the cpu
+	  topology of an ARM System.
+
+config SCHED_MC
+	bool "Multi-core scheduler support"
+	depends on ARM_CPU_TOPOLOGY
+	help
+	  Multi-core scheduler support improves the CPU scheduler's decision
+	  making when dealing with multi-core CPU chips at a cost of slightly
+	  increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+	bool "SMT scheduler support"
+	depends on ARM_CPU_TOPOLOGY
+	help
+	  Improves the CPU scheduler's decision making when dealing with
+	  MultiThreading at a cost of slightly increased overhead in some
+	  places. If unsure say N here.
+
 config HAVE_ARM_SCU
 	bool
 	help
@@ -1482,6 +1576,7 @@ config THUMB2_KERNEL
 	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
+	select ARM_UNWIND
 	help
 	  By enabling this option, the kernel will be compiled in
 	  Thumb-2 mode. A compiler/assembler that understand the unified
@@ -1807,6 +1902,38 @@ config ZBOOT_ROM_SH_MOBILE_SDHI
 
 endchoice
 
+config ARM_APPENDED_DTB
+	bool "Use appended device tree blob to zImage (EXPERIMENTAL)"
+	depends on OF && !ZBOOT_ROM && EXPERIMENTAL
+	help
+	  With this option, the boot code will look for a device tree binary
+	  (DTB) appended to zImage
+	  (e.g. cat zImage <filename>.dtb > zImage_w_dtb).
+
+	  This is meant as a backward compatibility convenience for those
+	  systems with a bootloader that can't be upgraded to accommodate
+	  the documented boot protocol using a device tree.
+
+	  Beware that there is very little in terms of protection against
+	  this option being confused by leftover garbage in memory that might
+	  look like a DTB header after a reboot if no actual DTB is appended
+	  to zImage.  Do not leave this option active in a production kernel
+	  if you don't intend to always append a DTB.  Proper passing of the
+	  location into r2 of a bootloader provided DTB is always preferable
+	  to this option.
+
+config ARM_ATAG_DTB_COMPAT
+	bool "Supplement the appended DTB with traditional ATAG information"
+	depends on ARM_APPENDED_DTB
+	help
+	  Some old bootloaders can't be updated to a DTB capable one, yet
+	  they provide ATAGs with memory configuration, the ramdisk address,
+	  the kernel cmdline string, etc.  Such information is dynamically
+	  provided by the bootloader and can't always be stored in a static
+	  DTB.  To allow a device tree enabled kernel to be used with such
+	  bootloaders, this option allows zImage to extract the information
+	  from the ATAG list and store it at run time into the appended DTB.
+
 config CMDLINE
 	string "Default kernel command string"
 	default ""
@@ -1953,6 +2080,7 @@ config CPU_FREQ_PXA
 	bool
 	depends on CPU_FREQ && ARCH_PXA && PXA25x
 	default y
+	select CPU_FREQ_TABLE
 	select CPU_FREQ_DEFAULT_GOV_USERSPACE
 
 config CPU_FREQ_S3C
@@ -2096,11 +2224,14 @@ menu "Power management options"
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
-	depends on !ARCH_S5P64X0 && !ARCH_S5PC100
+	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
 		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
 	def_bool y
 
+config ARM_CPU_SUSPEND
+	def_bool PM_SLEEP
+
 endmenu
 
 source "net/Kconfig"
diff -druNp linux-libre-3.1-gnu1/arch/arm/Kconfig.debug linux-libre-3.2-gnu1/arch/arm/Kconfig.debug
--- linux-libre-3.1-gnu1/arch/arm/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -65,13 +65,190 @@ config DEBUG_USER
 
 # These options are only for real kernel hackers who want to get their hands dirty.
 config DEBUG_LL
-	bool "Kernel low-level debugging functions"
+	bool "Kernel low-level debugging functions (read help!)"
 	depends on DEBUG_KERNEL
 	help
 	  Say Y here to include definitions of printascii, printch, printhex
 	  in the kernel.  This is helpful if you are debugging code that
 	  executes before the console is initialized.
 
+	  Note that selecting this option will limit the kernel to a single
+	  UART definition, as specified below. Attempting to boot the kernel
+	  image on a different platform *will not work*, so this option should
+	  not be enabled for kernels that are intended to be portable.
+
+choice
+	prompt "Kernel low-level debugging port"
+	depends on DEBUG_LL
+
+	config DEBUG_LL_UART_NONE
+		bool "No low-level debugging UART"
+		help
+		  Say Y here if your platform doesn't provide a UART option
+		  below. This relies on your platform choosing the right UART
+		  definition internally in order for low-level debugging to
+		  work.
+
+	config DEBUG_ICEDCC
+		bool "Kernel low-level debugging via EmbeddedICE DCC channel"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the EmbeddedICE macrocell's DCC channel using
+		  co-processor 14. This is known to work on the ARM9 style ICE
+		  channel and on the XScale with the PEEDI.
+
+		  Note that the system will appear to hang during boot if there
+		  is nothing connected to read from the DCC.
+
+	config DEBUG_FOOTBRIDGE_COM1
+		bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1"
+		depends on FOOTBRIDGE
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the 8250 at PCI COM1.
+
+	config DEBUG_DC21285_PORT
+		bool "Kernel low-level debugging messages via footbridge serial port"
+		depends on FOOTBRIDGE
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port in the DC21285 (Footbridge).
+
+	config DEBUG_CLPS711X_UART1
+		bool "Kernel low-level debugging messages via UART1"
+		depends on ARCH_CLPS711X
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the first serial port on these devices.
+
+	config DEBUG_CLPS711X_UART2
+		bool "Kernel low-level debugging messages via UART2"
+		depends on ARCH_CLPS711X
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the second serial port on these devices.
+
+	config DEBUG_HIGHBANK_UART
+		bool "Kernel low-level debugging messages via Highbank UART"
+		depends on ARCH_HIGHBANK
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the UART on Highbank based devices.
+
+	config DEBUG_IMX1_UART
+		bool "i.MX1 Debug UART"
+		depends on SOC_IMX1
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX1.
+
+	config DEBUG_IMX23_UART
+		bool "i.MX23 Debug UART"
+		depends on SOC_IMX23
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX23.
+
+	config DEBUG_IMX25_UART
+		bool "i.MX25 Debug UART"
+		depends on SOC_IMX25
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX25.
+
+	config DEBUG_IMX21_IMX27_UART
+		bool "i.MX21 and i.MX27 Debug UART"
+		depends on SOC_IMX21 || SOC_IMX27
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX21 or i.MX27.
+
+	config DEBUG_IMX28_UART
+		bool "i.MX28 Debug UART"
+		depends on SOC_IMX28
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX28.
+
+	config DEBUG_IMX31_IMX35_UART
+		bool "i.MX31 and i.MX35 Debug UART"
+		depends on SOC_IMX31 || SOC_IMX35
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX31 or i.MX35.
+
+	config DEBUG_IMX51_UART
+		bool "i.MX51 Debug UART"
+		depends on SOC_IMX51
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX51.
+
+	config DEBUG_IMX50_IMX53_UART
+		bool "i.MX50 and i.MX53 Debug UART"
+		depends on SOC_IMX50 || SOC_IMX53
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX50 or i.MX53.
+
+	config DEBUG_IMX6Q_UART
+		bool "i.MX6Q Debug UART"
+		depends on SOC_IMX6Q
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX6Q.
+
+	config DEBUG_S3C_UART0
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 0 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 0. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART1
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 1 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 1. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART2
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 2 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 2. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_REALVIEW_STD_PORT
+		bool "RealView Default UART"
+		depends on ARCH_REALVIEW
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on RealView EB, PB11MP, PBA8
+		  and PBX platforms.
+
+	config DEBUG_REALVIEW_PB1176_PORT
+		bool "RealView PB1176 UART"
+		depends on MACH_REALVIEW_PB1176
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the standard serial port on the RealView
+		  PB1176 platform.
+
+endchoice
+
 config EARLY_PRINTK
 	bool "Early printk"
 	depends on DEBUG_LL
@@ -80,53 +257,18 @@ config EARLY_PRINTK
 	  kernel low-level debugging functions. Add earlyprintk to your
 	  kernel parameters to enable this console.
 
-config DEBUG_ICEDCC
-	bool "Kernel low-level debugging via EmbeddedICE DCC channel"
-	depends on DEBUG_LL
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the EmbeddedICE macrocell's DCC channel using
-	  co-processor 14. This is known to work on the ARM9 style ICE
-	  channel and on the XScale with the PEEDI.
-
-	  It does include a timeout to ensure that the system does not
-	  totally freeze when there is nothing connected to read.
-
 config OC_ETM
 	bool "On-chip ETM and ETB"
-	select ARM_AMBA
+	depends on ARM_AMBA
 	help
 	  Enables the on-chip embedded trace macrocell and embedded trace
 	  buffer driver that will allow you to collect traces of the
 	  kernel code.
 
-config DEBUG_DC21285_PORT
-	bool "Kernel low-level debugging messages via footbridge serial port"
-	depends on DEBUG_LL && FOOTBRIDGE
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the serial port in the DC21285 (Footbridge). Saying N
-	  will cause the debug messages to appear on the first 16550
-	  serial port.
-
-config DEBUG_CLPS711X_UART2
-	bool "Kernel low-level debugging messages via UART2"
-	depends on DEBUG_LL && ARCH_CLPS711X
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the second serial port on these devices.  Saying N will
-	  cause the debug messages to appear on the first serial port.
-
-config DEBUG_S3C_UART
-	depends on PLAT_SAMSUNG
-	int "S3C UART to use for low-level debug"
-	default "0"
+config ARM_KPROBES_TEST
+	tristate "Kprobes test module"
+	depends on KPROBES && MODULES
 	help
-	  Choice for UART for kernel low-level using S3C UARTS,
-	  should be between zero and two. The port must have been
-	  initialised by the boot-loader before use.
-
-	  The uncompressor code port configuration is now handled
-	  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+	  Perform tests of kprobes API and instruction set simulation.
 
 endmenu
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/armksyms.c linux-libre-3.2-gnu1/arch/arm/kernel/armksyms.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/armksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/armksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/cryptohash.h>
@@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void);
 
 extern void fpundefinstr(void);
 
-
-EXPORT_SYMBOL(__backtrace);
-
 	/* platform dependent support */
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__const_udelay);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/asm-offsets.c linux-libre-3.2-gnu1/arch/arm/kernel/asm-offsets.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/procinfo.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
 
 /*
@@ -92,6 +93,17 @@ int main(void)
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
+#ifdef CONFIG_CACHE_L2X0
+  DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
+  DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl));
+  DEFINE(L2X0_R_TAG_LATENCY,	offsetof(struct l2x0_regs, tag_latency));
+  DEFINE(L2X0_R_DATA_LATENCY,	offsetof(struct l2x0_regs, data_latency));
+  DEFINE(L2X0_R_FILTER_START,	offsetof(struct l2x0_regs, filter_start));
+  DEFINE(L2X0_R_FILTER_END,	offsetof(struct l2x0_regs, filter_end));
+  DEFINE(L2X0_R_PREFETCH_CTRL,	offsetof(struct l2x0_regs, prefetch_ctrl));
+  DEFINE(L2X0_R_PWR_CTRL,	offsetof(struct l2x0_regs, pwr_ctrl));
+  BLANK();
+#endif
 #ifdef CONFIG_CPU_HAS_ASID
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
   BLANK();
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/bios32.c linux-libre-3.2-gnu1/arch/arm/kernel/bios32.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/bios32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/bios32.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  *
  *  Bits taken from various places.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
@@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *b
 	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
 		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
 }
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+#endif
 
 /*
  * Convert from Linux-centric to bus-centric addresses for bridge devices.
@@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *
 	region->start = res->start - offset;
 	region->end   = res->end - offset;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 void __devinit
 pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
@@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *
 	res->start = region->start + offset;
 	res->end   = region->end + offset;
 }
-
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_fixup_bus);
-EXPORT_SYMBOL(pcibios_resource_to_bus);
 EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
 
 /*
  * Swizzle the device pin each time we cross a bridge.
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/calls.S linux-libre-3.2-gnu1/arch/arm/kernel/calls.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/calls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/calls.S	2012-01-04 18:55:44.000000000 -0500
@@ -385,6 +385,8 @@
 		CALL(sys_syncfs)
 		CALL(sys_sendmmsg)
 /* 375 */	CALL(sys_setns)
+		CALL(sys_process_vm_readv)
+		CALL(sys_process_vm_writev)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/debug.S linux-libre-3.2-gnu1/arch/arm/kernel/debug.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/debug.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/debug.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 		@@ debug using ARM EmbeddedICE DCC channel
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		.endm
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
@@ -106,7 +106,7 @@
 
 #ifdef CONFIG_MMU
 		.macro	addruart_current, rx, tmp1, tmp2
-		addruart	\tmp1, \tmp2
+		addruart	\tmp1, \tmp2, \rx
 		mrc		p15, 0, \rx, c1, c0
 		tst		\rx, #1
 		moveq		\rx, \tmp1
@@ -151,6 +151,8 @@ printhex:	adr	r2, hexbuf
 		b	printascii
 ENDPROC(printhex2)
 
+hexbuf:		.space 16
+
 		.ltorg
 
 ENTRY(printascii)
@@ -175,5 +177,3 @@ ENTRY(printch)
 		mov	r0, #0
 		b	1b
 ENDPROC(printch)
-
-hexbuf:		.space 16
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/devtree.c linux-libre-3.2-gnu1/arch/arm/kernel/devtree.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/devtree.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/devtree.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/dma.c linux-libre-3.2-gnu1/arch/arm/kernel/dma.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 
 #include <asm/mach/dma.h>
 
-DEFINE_SPINLOCK(dma_spin_lock);
+DEFINE_RAW_SPINLOCK(dma_spin_lock);
 EXPORT_SYMBOL(dma_spin_lock);
 
 static dma_t *dma_chan[MAX_DMA_CHANNELS];
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/ecard.c linux-libre-3.2-gnu1/arch/arm/kernel/ecard.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/ecard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/ecard.c	2012-01-04 18:55:44.000000000 -0500
@@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct m
 
 	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
 
-	src_pgd = pgd_offset(mm, EASI_BASE);
+	src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE);
 	dst_pgd = pgd_offset(mm, EASI_START);
 
 	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE));
@@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void)
 #define ecard_probeirqhw() (0)
 #endif
 
-#ifndef IO_EC_MEMC8_BASE
-#define IO_EC_MEMC8_BASE 0
-#endif
-
-static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
 {
-	unsigned long address = 0;
+	void __iomem *address = NULL;
 	int slot = ec->slot_no;
 
 	if (ec->slot_no == 8)
-		return IO_EC_MEMC8_BASE;
+		return ECARD_MEMC8_BASE;
 
 	ectcr &= ~(1 << slot);
 
 	switch (type) {
 	case ECARD_MEMC:
 		if (slot < 4)
-			address = IO_EC_MEMC_BASE + (slot << 12);
+			address = ECARD_MEMC_BASE + (slot << 14);
 		break;
 
 	case ECARD_IOC:
 		if (slot < 4)
-			address = IO_EC_IOC_BASE + (slot << 12);
-#ifdef IO_EC_IOC4_BASE
+			address = ECARD_IOC_BASE + (slot << 14);
 		else
-			address = IO_EC_IOC4_BASE + ((slot - 4) << 12);
-#endif
+			address = ECARD_IOC4_BASE + ((slot - 4) << 14);
 		if (address)
-			address +=  speed << 17;
+			address += speed << 19;
 		break;
 
-#ifdef IO_EC_EASI_BASE
 	case ECARD_EASI:
-		address = IO_EC_EASI_BASE + (slot << 22);
+		address = ECARD_EASI_BASE + (slot << 24);
 		if (speed == ECARD_FAST)
 			ectcr |= 1 << slot;
 		break;
-#endif
+
 	default:
 		break;
 	}
@@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type)
 	ecard_t **ecp;
 	ecard_t *ec;
 	struct ex_ecid cid;
+	void __iomem *addr;
 	int i, rc;
 
 	ec = ecard_alloc_card(type, slot);
@@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type)
 	}
 
 	rc = -ENODEV;
-	if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0)
+	if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL)
 		goto nodev;
 
 	cid.r_zero = 1;
@@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type)
 	ec->cid.fiqmask = cid.r_fiqmask;
 	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
 	ec->fiqaddr	=
-	ec->irqaddr	= (void __iomem *)ioaddr(ec->podaddr);
+	ec->irqaddr	= addr;
 
 	if (ec->cid.is) {
 		ec->irqmask = ec->cid.irqmask;
@@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type)
 		set_irq_flags(ec->irq, IRQF_VALID);
 	}
 
-#ifdef IO_EC_MEMC8_BASE
 	if (slot == 8)
 		ec->irq = 11;
-#endif
 #ifdef CONFIG_ARCH_RPC
 	/* On RiscPC, only first two slots have DMA capability */
 	if (slot < 2)
@@ -1097,9 +1089,7 @@ static int __init ecard_init(void)
 			ecard_probe(slot, ECARD_IOC);
 	}
 
-#ifdef IO_EC_MEMC8_BASE
 	ecard_probe(8, ECARD_IOC);
-#endif
 
 	irqhw = ecard_probeirqhw();
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/elf.c linux-libre-3.2-gnu1/arch/arm/kernel/elf.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/elf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/elf.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/entry-armv.S linux-libre-3.2-gnu1/arch/arm/kernel/entry-armv.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/entry-armv.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/entry-armv.S	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <asm/unwind.h>
 #include <asm/unistd.h>
 #include <asm/tls.h>
+#include <asm/system.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
@@ -262,8 +263,7 @@ __und_svc:
 	ldr	r0, [r4, #-4]
 #else
 	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2
-	and	r9, r0, #0xf800
-	cmp	r9, #0xe800			@ 32-bit instruction if xx >= 0
+	cmp	r0, #0xe800			@ 32-bit instruction if xx >= 0
 	ldrhhs	r9, [r4]			@ bottom 16 bits
 	orrhs	r0, r9, r0, lsl #16
 #endif
@@ -440,18 +440,46 @@ __und_usr:
 #endif
 	beq	call_fpe
 	@ Thumb instruction
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
+/*
+ * Thumb-2 instruction handling.  Note that because pre-v6 and >= v6 platforms
+ * can never be supported in a single kernel, this code is not applicable at
+ * all when __LINUX_ARM_ARCH__ < 6.  This allows simplifying assumptions to be
+ * made about .arch directives.
+ */
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */
+#define NEED_CPU_ARCHITECTURE
+	ldr	r5, .LCcpu_architecture
+	ldr	r5, [r5]
+	cmp	r5, #CPU_ARCH_ARMv7
+	blo	__und_usr_unknown
+/*
+ * The following code won't get run unless the running CPU really is v7, so
+ * coding round the lack of ldrht on older arches is pointless.  Temporarily
+ * override the assembler target arch with the minimum required instead:
+ */
+	.arch	armv6t2
+#endif
 2:
  ARM(	ldrht	r5, [r4], #2	)
  THUMB(	ldrht	r5, [r4]	)
  THUMB(	add	r4, r4, #2	)
-	and	r0, r5, #0xf800			@ mask bits 111x x... .... ....
-	cmp	r0, #0xe800			@ 32bit instruction if xx != 0
+	cmp	r5, #0xe800			@ 32bit instruction if xx != 0
 	blo	__und_usr_unknown
 3:	ldrht	r0, [r4]
 	add	r2, r2, #2			@ r2 is PC + 2, make it PC + 4
 	orr	r0, r0, r5, lsl #16
+
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target arch was overridden, change it back: */
+#ifdef CONFIG_CPU_32v6K
+	.arch	armv6k
 #else
+	.arch	armv6
+#endif
+#endif /* __LINUX_ARM_ARCH__ < 7 */
+#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */
 	b	__und_usr_unknown
 #endif
  UNWIND(.fnend		)
@@ -469,7 +497,7 @@ ENDPROC(__und_usr)
 	.popsection
 	.pushsection __ex_table,"a"
 	.long	1b, 4b
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
 	.long	2b, 4b
 	.long	3b, 4b
 #endif
@@ -578,6 +606,12 @@ call_fpe:
 	movw_pc	lr				@ CP#14 (Debug)
 	movw_pc	lr				@ CP#15 (Control)
 
+#ifdef NEED_CPU_ARCHITECTURE
+	.align	2
+.LCcpu_architecture:
+	.word	__cpu_architecture
+#endif
+
 #ifdef CONFIG_NEON
 	.align	6
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/etm.c linux-libre-3.2-gnu1/arch/arm/kernel/etm.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/etm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/etm.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/miscdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include <asm/hardware/coresight.h>
 #include <asm/sections.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/head.S linux-libre-3.2-gnu1/arch/arm/kernel/head.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <asm/memory.h>
 #include <asm/thread_info.h>
 #include <asm/system.h>
+#include <asm/pgtable.h>
 
 #ifdef CONFIG_DEBUG_LL
 #include <mach/debug-macro.S>
@@ -38,11 +39,14 @@
 #error KERNEL_RAM_VADDR must start at 0xXXXX8000
 #endif
 
+#define PG_DIR_SIZE	0x4000
+#define PMD_ORDER	2
+
 	.globl	swapper_pg_dir
-	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
+	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
 
 	.macro	pgtbl, rd, phys
-	add	\rd, \phys, #TEXT_OFFSET - 0x4000
+	add	\rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE
 	.endm
 
 #ifdef CONFIG_XIP_KERNEL
@@ -95,7 +99,7 @@ ENTRY(stext)
 	sub	r4, r3, r4			@ (PHYS_OFFSET - PAGE_OFFSET)
 	add	r8, r8, r4			@ PHYS_OFFSET
 #else
-	ldr	r8, =PLAT_PHYS_OFFSET
+	ldr	r8, =PHYS_OFFSET		@ always constant in this case
 #endif
 
 	/*
@@ -148,11 +152,11 @@ __create_page_tables:
 	pgtbl	r4, r8				@ page table address
 
 	/*
-	 * Clear the 16K level 1 swapper page table
+	 * Clear the swapper page table
 	 */
 	mov	r0, r4
 	mov	r3, #0
-	add	r6, r0, #0x4000
+	add	r6, r0, #PG_DIR_SIZE
 1:	str	r3, [r0], #4
 	str	r3, [r0], #4
 	str	r3, [r0], #4
@@ -171,30 +175,30 @@ __create_page_tables:
 	sub	r0, r0, r3			@ virt->phys offset
 	add	r5, r5, r0			@ phys __enable_mmu
 	add	r6, r6, r0			@ phys __enable_mmu_end
-	mov	r5, r5, lsr #20
-	mov	r6, r6, lsr #20
+	mov	r5, r5, lsr #SECTION_SHIFT
+	mov	r6, r6, lsr #SECTION_SHIFT
 
-1:	orr	r3, r7, r5, lsl #20		@ flags + kernel base
-	str	r3, [r4, r5, lsl #2]		@ identity mapping
-	teq	r5, r6
-	addne	r5, r5, #1			@ next section
-	bne	1b
+1:	orr	r3, r7, r5, lsl #SECTION_SHIFT	@ flags + kernel base
+	str	r3, [r4, r5, lsl #PMD_ORDER]	@ identity mapping
+	cmp	r5, r6
+	addlo	r5, r5, #1			@ next section
+	blo	1b
 
 	/*
 	 * Now setup the pagetables for our kernel direct
 	 * mapped region.
 	 */
 	mov	r3, pc
-	mov	r3, r3, lsr #20
-	orr	r3, r7, r3, lsl #20
-	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 18
-	str	r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
+	mov	r3, r3, lsr #SECTION_SHIFT
+	orr	r3, r7, r3, lsl #SECTION_SHIFT
+	add	r0, r4,  #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+	str	r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]!
 	ldr	r6, =(KERNEL_END - 1)
-	add	r0, r0, #4
-	add	r6, r4, r6, lsr #18
+	add	r0, r0, #1 << PMD_ORDER
+	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
 1:	cmp	r0, r6
-	add	r3, r3, #1 << 20
-	strls	r3, [r0], #4
+	add	r3, r3, #1 << SECTION_SHIFT
+	strls	r3, [r0], #1 << PMD_ORDER
 	bls	1b
 
 #ifdef CONFIG_XIP_KERNEL
@@ -203,11 +207,11 @@ __create_page_tables:
 	 */
 	add	r3, r8, #TEXT_OFFSET
 	orr	r3, r3, r7
-	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18
-	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
+	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]!
 	ldr	r6, =(_end - 1)
 	add	r0, r0, #4
-	add	r6, r4, r6, lsr #18
+	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
 1:	cmp	r0, r6
 	add	r3, r3, #1 << 20
 	strls	r3, [r0], #4
@@ -218,12 +222,12 @@ __create_page_tables:
 	 * Then map boot params address in r2 or
 	 * the first 1MB of ram if boot params address is not specified.
 	 */
-	mov	r0, r2, lsr #20
-	movs	r0, r0, lsl #20
+	mov	r0, r2, lsr #SECTION_SHIFT
+	movs	r0, r0, lsl #SECTION_SHIFT
 	moveq	r0, r8
 	sub	r3, r0, r8
 	add	r3, r3, #PAGE_OFFSET
-	add	r3, r4, r3, lsr #18
+	add	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
 	orr	r6, r7, r0
 	str	r6, [r3]
 
@@ -234,23 +238,23 @@ __create_page_tables:
 	 * This allows debug messages to be output
 	 * via a serial console before paging_init.
 	 */
-	addruart r7, r3
+	addruart r7, r3, r0
 
-	mov	r3, r3, lsr #20
-	mov	r3, r3, lsl #2
+	mov	r3, r3, lsr #SECTION_SHIFT
+	mov	r3, r3, lsl #PMD_ORDER
 
 	add	r0, r4, r3
 	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)
 	cmp	r3, #0x0800			@ limit to 512MB
 	movhi	r3, #0x0800
 	add	r6, r0, r3
-	mov	r3, r7, lsr #20
+	mov	r3, r7, lsr #SECTION_SHIFT
 	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
-	orr	r3, r7, r3, lsl #20
+	orr	r3, r7, r3, lsl #SECTION_SHIFT
 1:	str	r3, [r0], #4
-	add	r3, r3, #1 << 20
-	teq	r0, r6
-	bne	1b
+	add	r3, r3, #1 << SECTION_SHIFT
+	cmp	r0, r6
+	blo	1b
 
 #else /* CONFIG_DEBUG_ICEDCC */
 	/* we don't need any serial debugging mappings for ICEDCC */
@@ -262,7 +266,7 @@ __create_page_tables:
 	 * If we're using the NetWinder or CATS, we also need to map
 	 * in the 16550-type serial port for the debug messages
 	 */
-	add	r0, r4, #0xff000000 >> 18
+	add	r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER)
 	orr	r3, r7, #0x7c000000
 	str	r3, [r0]
 #endif
@@ -272,10 +276,10 @@ __create_page_tables:
 	 * Similar reasons here - for debug.  This is
 	 * only for Acorn RiscPC architectures.
 	 */
-	add	r0, r4, #0x02000000 >> 18
+	add	r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER)
 	orr	r3, r7, #0x02000000
 	str	r3, [r0]
-	add	r0, r4, #0xd8000000 >> 18
+	add	r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER)
 	str	r3, [r0]
 #endif
 #endif
@@ -356,7 +360,7 @@ __secondary_data:
  *  r13 = *virtual* address to jump to upon completion
  */
 __enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
+#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
 	orr	r0, r0, #CR_A
 #else
 	bic	r0, r0, #CR_A
@@ -488,13 +492,8 @@ __fixup_pv_table:
 	add	r5, r5, r3	@ adjust table end address
 	add	r7, r7, r3	@ adjust __pv_phys_offset address
 	str	r8, [r7]	@ save computed PHYS_OFFSET to __pv_phys_offset
-#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
 	mov	r6, r3, lsr #24	@ constant for add/sub instructions
 	teq	r3, r6, lsl #24 @ must be 16MiB aligned
-#else
-	mov	r6, r3, lsr #16	@ constant for add/sub instructions
-	teq	r3, r6, lsl #16	@ must be 64kiB aligned
-#endif
 THUMB(	it	ne		@ cross section branch )
 	bne	__error
 	str	r6, [r7, #4]	@ save to __pv_offset
@@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table)
 	.text
 __fixup_a_pv_table:
 #ifdef CONFIG_THUMB2_KERNEL
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-	lsls	r0, r6, #24
-	lsr	r6, #8
-	beq	1f
-	clz	r7, r0
-	lsr	r0, #24
-	lsl	r0, r7
-	bic	r0, 0x0080
-	lsrs	r7, #1
-	orrcs   r0, #0x0080
-	orr	r0, r0, r7, lsl #12
-#endif
-1:	lsls	r6, #24
-	beq	4f
+	lsls	r6, #24
+	beq	2f
 	clz	r7, r6
 	lsr	r6, #24
 	lsl	r6, r7
@@ -532,43 +519,25 @@ __fixup_a_pv_table:
 	orrcs	r6, #0x0080
 	orr	r6, r6, r7, lsl #12
 	orr	r6, #0x4000
-	b	4f
-2:	@ at this point the C flag is always clear
-	add     r7, r3
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-	ldrh	ip, [r7]
-	tst	ip, 0x0400	@ the i bit tells us LS or MS byte
-	beq	3f
-	cmp	r0, #0		@ set C flag, and ...
-	biceq	ip, 0x0400	@ immediate zero value has a special encoding
-	streqh	ip, [r7]	@ that requires the i bit cleared
-#endif
-3:	ldrh	ip, [r7, #2]
+	b	2f
+1:	add     r7, r3
+	ldrh	ip, [r7, #2]
 	and	ip, 0x8f00
-	orrcc	ip, r6	@ mask in offset bits 31-24
-	orrcs	ip, r0	@ mask in offset bits 23-16
+	orr	ip, r6	@ mask in offset bits 31-24
 	strh	ip, [r7, #2]
-4:	cmp	r4, r5
+2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
-	bcc	2b
+	bcc	1b
 	bx	lr
 #else
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-	and	r0, r6, #255	@ offset bits 23-16
-	mov	r6, r6, lsr #8	@ offset bits 31-24
-#else
-	mov	r0, #0		@ just in case...
-#endif
-	b	3f
-2:	ldr	ip, [r7, r3]
+	b	2f
+1:	ldr	ip, [r7, r3]
 	bic	ip, ip, #0x000000ff
-	tst	ip, #0x400	@ rotate shift tells us LS or MS byte
-	orrne	ip, ip, r6	@ mask in offset bits 31-24
-	orreq	ip, ip, r0	@ mask in offset bits 23-16
+	orr	ip, ip, r6	@ mask in offset bits 31-24
 	str	ip, [r7, r3]
-3:	cmp	r4, r5
+2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
-	bcc	2b
+	bcc	1b
 	mov	pc, lr
 #endif
 ENDPROC(__fixup_a_pv_table)
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/hw_breakpoint.c linux-libre-3.2-gnu1/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/hw_breakpoint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/hw_breakpoint.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,6 @@ static DEFINE_PER_CPU(struct perf_event
 
 /* Number of BRP/WRP registers on this CPU. */
 static int core_num_brps;
-static int core_num_reserved_brps;
 static int core_num_wrps;
 
 /* Debug architecture version. */
@@ -137,10 +136,11 @@ static u8 get_debug_arch(void)
 	u32 didr;
 
 	/* Do we implement the extended CPUID interface? */
-	if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf),
-	    "CPUID feature registers not supported. "
-	    "Assuming v6 debug is present.\n"))
+	if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+		pr_warning("CPUID feature registers not supported. "
+			   "Assuming v6 debug is present.\n");
 		return ARM_DEBUG_ARCH_V6;
+	}
 
 	ARM_DBG_READ(c0, 0, didr);
 	return (didr >> 16) & 0xf;
@@ -154,10 +154,21 @@ u8 arch_get_debug_arch(void)
 static int debug_arch_supported(void)
 {
 	u8 arch = get_debug_arch();
-	return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;
+
+	/* We don't support the memory-mapped interface. */
+	return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||
+		arch >= ARM_DEBUG_ARCH_V7_1;
 }
 
-/* Determine number of BRP register available. */
+/* Determine number of WRP registers available. */
+static int get_num_wrp_resources(void)
+{
+	u32 didr;
+	ARM_DBG_READ(c0, 0, didr);
+	return ((didr >> 28) & 0xf) + 1;
+}
+
+/* Determine number of BRP registers available. */
 static int get_num_brp_resources(void)
 {
 	u32 didr;
@@ -176,9 +187,10 @@ static int core_has_mismatch_brps(void)
 static int get_num_wrps(void)
 {
 	/*
-	 * FIXME: When a watchpoint fires, the only way to work out which
-	 * watchpoint it was is by disassembling the faulting instruction
-	 * and working out the address of the memory access.
+	 * On debug architectures prior to 7.1, when a watchpoint fires, the
+	 * only way to work out which watchpoint it was is by disassembling
+	 * the faulting instruction and working out the address of the memory
+	 * access.
 	 *
 	 * Furthermore, we can only do this if the watchpoint was precise
 	 * since imprecise watchpoints prevent us from calculating register
@@ -192,36 +204,17 @@ static int get_num_wrps(void)
 	 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
 	 * that it is set on some implementations].
 	 */
+	if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
+		return 1;
 
-#if 0
-	int wrps;
-	u32 didr;
-	ARM_DBG_READ(c0, 0, didr);
-	wrps = ((didr >> 28) & 0xf) + 1;
-#endif
-	int wrps = 1;
-
-	if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
-		wrps = get_num_brp_resources() - 1;
-
-	return wrps;
-}
-
-/* We reserve one breakpoint for each watchpoint. */
-static int get_num_reserved_brps(void)
-{
-	if (core_has_mismatch_brps())
-		return get_num_wrps();
-	return 0;
+	return get_num_wrp_resources();
 }
 
 /* Determine number of usable BRPs available. */
 static int get_num_brps(void)
 {
 	int brps = get_num_brp_resources();
-	if (core_has_mismatch_brps())
-		brps -= get_num_reserved_brps();
-	return brps;
+	return core_has_mismatch_brps() ? brps - 1 : brps;
 }
 
 /*
@@ -239,7 +232,7 @@ static int enable_monitor_mode(void)
 
 	/* Ensure that halting mode is disabled. */
 	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
-			"halting debug mode enabled. Unable to access hardware resources.\n")) {
+		"halting debug mode enabled. Unable to access hardware resources.\n")) {
 		ret = -EPERM;
 		goto out;
 	}
@@ -255,6 +248,7 @@ static int enable_monitor_mode(void)
 		ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
 		break;
 	case ARM_DEBUG_ARCH_V7_ECP14:
+	case ARM_DEBUG_ARCH_V7_1:
 		ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
 		break;
 	default:
@@ -346,24 +340,10 @@ int arch_install_hw_breakpoint(struct pe
 		val_base = ARM_BASE_BVR;
 		slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
 		max_slots = core_num_brps;
-		if (info->step_ctrl.enabled) {
-			/* Override the breakpoint data with the step data. */
-			addr = info->trigger & ~0x3;
-			ctrl = encode_ctrl_reg(info->step_ctrl);
-		}
 	} else {
 		/* Watchpoint */
-		if (info->step_ctrl.enabled) {
-			/* Install into the reserved breakpoint region. */
-			ctrl_base = ARM_BASE_BCR + core_num_brps;
-			val_base = ARM_BASE_BVR + core_num_brps;
-			/* Override the watchpoint data with the step data. */
-			addr = info->trigger & ~0x3;
-			ctrl = encode_ctrl_reg(info->step_ctrl);
-		} else {
-			ctrl_base = ARM_BASE_WCR;
-			val_base = ARM_BASE_WVR;
-		}
+		ctrl_base = ARM_BASE_WCR;
+		val_base = ARM_BASE_WVR;
 		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
@@ -382,6 +362,17 @@ int arch_install_hw_breakpoint(struct pe
 		goto out;
 	}
 
+	/* Override the breakpoint data with the step data. */
+	if (info->step_ctrl.enabled) {
+		addr = info->trigger & ~0x3;
+		ctrl = encode_ctrl_reg(info->step_ctrl);
+		if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {
+			i = 0;
+			ctrl_base = ARM_BASE_BCR + core_num_brps;
+			val_base = ARM_BASE_BVR + core_num_brps;
+		}
+	}
+
 	/* Setup the address register. */
 	write_wb_reg(val_base + i, addr);
 
@@ -405,10 +396,7 @@ void arch_uninstall_hw_breakpoint(struct
 		max_slots = core_num_brps;
 	} else {
 		/* Watchpoint */
-		if (info->step_ctrl.enabled)
-			base = ARM_BASE_BCR + core_num_brps;
-		else
-			base = ARM_BASE_WCR;
+		base = ARM_BASE_WCR;
 		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
@@ -426,6 +414,13 @@ void arch_uninstall_hw_breakpoint(struct
 	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
 		return;
 
+	/* Ensure that we disable the mismatch breakpoint. */
+	if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
+	    info->step_ctrl.enabled) {
+		i = 0;
+		base = ARM_BASE_BCR + core_num_brps;
+	}
+
 	/* Reset the control register. */
 	write_wb_reg(base + i, 0);
 }
@@ -632,10 +627,9 @@ int arch_validate_hwbkpt_settings(struct
 	 * we can use the mismatch feature as a poor-man's hardware
 	 * single-step, but this only works for per-task breakpoints.
 	 */
-	if (WARN_ONCE(!bp->overflow_handler &&
-		(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
-		 || !bp->hw.bp_target),
-			"overflow handler required but none found\n")) {
+	if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
+	    !core_has_mismatch_brps() || !bp->hw.bp_target)) {
+		pr_warning("overflow handler required but none found\n");
 		ret = -EINVAL;
 	}
 out:
@@ -666,34 +660,62 @@ static void disable_single_step(struct p
 	arch_install_hw_breakpoint(bp);
 }
 
-static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+			       struct pt_regs *regs)
 {
-	int i;
+	int i, access;
+	u32 val, ctrl_reg, alignment_mask;
 	struct perf_event *wp, **slots;
 	struct arch_hw_breakpoint *info;
+	struct arch_hw_breakpoint_ctrl ctrl;
 
 	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-	/* Without a disassembler, we can only handle 1 watchpoint. */
-	BUG_ON(core_num_wrps > 1);
-
 	for (i = 0; i < core_num_wrps; ++i) {
 		rcu_read_lock();
 
 		wp = slots[i];
 
-		if (wp == NULL) {
-			rcu_read_unlock();
-			continue;
-		}
+		if (wp == NULL)
+			goto unlock;
 
+		info = counter_arch_bp(wp);
 		/*
-		 * The DFAR is an unknown value. Since we only allow a
-		 * single watchpoint, we can set the trigger to the lowest
-		 * possible faulting address.
+		 * The DFAR is an unknown value on debug architectures prior
+		 * to 7.1. Since we only allow a single watchpoint on these
+		 * older CPUs, we can set the trigger to the lowest possible
+		 * faulting address.
 		 */
-		info = counter_arch_bp(wp);
-		info->trigger = wp->attr.bp_addr;
+		if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
+			BUG_ON(i > 0);
+			info->trigger = wp->attr.bp_addr;
+		} else {
+			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+				alignment_mask = 0x7;
+			else
+				alignment_mask = 0x3;
+
+			/* Check if the watchpoint value matches. */
+			val = read_wb_reg(ARM_BASE_WVR + i);
+			if (val != (addr & ~alignment_mask))
+				goto unlock;
+
+			/* Possible match, check the byte address select. */
+			ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+			decode_ctrl_reg(ctrl_reg, &ctrl);
+			if (!((1 << (addr & alignment_mask)) & ctrl.len))
+				goto unlock;
+
+			/* Check that the access type matches. */
+			access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
+				 HW_BREAKPOINT_R;
+			if (!(access & hw_breakpoint_type(wp)))
+				goto unlock;
+
+			/* We have a winner. */
+			info->trigger = addr;
+		}
+
 		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
 		perf_bp_event(wp, regs);
 
@@ -705,6 +727,7 @@ static void watchpoint_handler(unsigned
 		if (!wp->overflow_handler)
 			enable_single_step(wp, instruction_pointer(regs));
 
+unlock:
 		rcu_read_unlock();
 	}
 }
@@ -717,7 +740,7 @@ static void watchpoint_single_step_handl
 
 	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-	for (i = 0; i < core_num_reserved_brps; ++i) {
+	for (i = 0; i < core_num_wrps; ++i) {
 		rcu_read_lock();
 
 		wp = slots[i];
@@ -820,7 +843,7 @@ static int hw_breakpoint_pending(unsigne
 	case ARM_ENTRY_ASYNC_WATCHPOINT:
 		WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
 	case ARM_ENTRY_SYNC_WATCHPOINT:
-		watchpoint_handler(addr, regs);
+		watchpoint_handler(addr, fsr, regs);
 		break;
 	default:
 		ret = 1; /* Unhandled fault. */
@@ -834,11 +857,31 @@ static int hw_breakpoint_pending(unsigne
 /*
  * One-time initialisation.
  */
-static void reset_ctrl_regs(void *info)
+static cpumask_t debug_err_mask;
+
+static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
 {
-	int i, cpu = smp_processor_id();
+	int cpu = smp_processor_id();
+
+	pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
+		   instr, cpu);
+
+	/* Set the error flag for this CPU and skip the faulting instruction. */
+	cpumask_set_cpu(cpu, &debug_err_mask);
+	instruction_pointer(regs) += 4;
+	return 0;
+}
+
+static struct undef_hook debug_reg_hook = {
+	.instr_mask	= 0x0fe80f10,
+	.instr_val	= 0x0e000e10,
+	.fn		= debug_reg_trap,
+};
+
+static void reset_ctrl_regs(void *unused)
+{
+	int i, raw_num_brps, err = 0, cpu = smp_processor_id();
 	u32 dbg_power;
-	cpumask_t *cpumask = info;
 
 	/*
 	 * v7 debug contains save and restore registers so that debug state
@@ -848,38 +891,57 @@ static void reset_ctrl_regs(void *info)
 	 * Access Register to avoid taking undefined instruction exceptions
 	 * later on.
 	 */
-	if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+	switch (debug_arch) {
+	case ARM_DEBUG_ARCH_V6:
+	case ARM_DEBUG_ARCH_V6_1:
+		/* ARMv6 cores just need to reset the registers. */
+		goto reset_regs;
+	case ARM_DEBUG_ARCH_V7_ECP14:
 		/*
 		 * Ensure sticky power-down is clear (i.e. debug logic is
 		 * powered up).
 		 */
 		asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
-		if ((dbg_power & 0x1) == 0) {
-			pr_warning("CPU %d debug is powered down!\n", cpu);
-			cpumask_or(cpumask, cpumask, cpumask_of(cpu));
-			return;
-		}
-
+		if ((dbg_power & 0x1) == 0)
+			err = -EPERM;
+		break;
+	case ARM_DEBUG_ARCH_V7_1:
 		/*
-		 * Unconditionally clear the lock by writing a value
-		 * other than 0xC5ACCE55 to the access register.
+		 * Ensure the OS double lock is clear.
 		 */
-		asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
-		isb();
+		asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
+		if ((dbg_power & 0x1) == 1)
+			err = -EPERM;
+		break;
+	}
 
-		/*
-		 * Clear any configured vector-catch events before
-		 * enabling monitor mode.
-		 */
-		asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
-		isb();
+	if (err) {
+		pr_warning("CPU %d debug is powered down!\n", cpu);
+		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
+		return;
 	}
 
+	/*
+	 * Unconditionally clear the lock by writing a value
+	 * other than 0xC5ACCE55 to the access register.
+	 */
+	asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+	isb();
+
+	/*
+	 * Clear any configured vector-catch events before
+	 * enabling monitor mode.
+	 */
+	asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+	isb();
+
+reset_regs:
 	if (enable_monitor_mode())
 		return;
 
 	/* We must also reset any reserved registers. */
-	for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
+	raw_num_brps = get_num_brp_resources();
+	for (i = 0; i < raw_num_brps; ++i) {
 		write_wb_reg(ARM_BASE_BCR + i, 0UL);
 		write_wb_reg(ARM_BASE_BVR + i, 0UL);
 	}
@@ -895,6 +957,7 @@ static int __cpuinit dbg_reset_notify(st
 {
 	if (action == CPU_ONLINE)
 		smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+
 	return NOTIFY_OK;
 }
 
@@ -905,7 +968,6 @@ static struct notifier_block __cpuinitda
 static int __init arch_hw_breakpoint_init(void)
 {
 	u32 dscr;
-	cpumask_t cpumask = { CPU_BITS_NONE };
 
 	debug_arch = get_debug_arch();
 
@@ -916,28 +978,31 @@ static int __init arch_hw_breakpoint_ini
 
 	/* Determine how many BRPs/WRPs are available. */
 	core_num_brps = get_num_brps();
-	core_num_reserved_brps = get_num_reserved_brps();
 	core_num_wrps = get_num_wrps();
 
-	pr_info("found %d breakpoint and %d watchpoint registers.\n",
-		core_num_brps + core_num_reserved_brps, core_num_wrps);
-
-	if (core_num_reserved_brps)
-		pr_info("%d breakpoint(s) reserved for watchpoint "
-				"single-step.\n", core_num_reserved_brps);
+	/*
+	 * We need to tread carefully here because DBGSWENABLE may be
+	 * driven low on this core and there isn't an architected way to
+	 * determine that.
+	 */
+	register_undef_hook(&debug_reg_hook);
 
 	/*
 	 * Reset the breakpoint resources. We assume that a halting
 	 * debugger will leave the world in a nice state for us.
 	 */
-	on_each_cpu(reset_ctrl_regs, &cpumask, 1);
-	if (!cpumask_empty(&cpumask)) {
+	on_each_cpu(reset_ctrl_regs, NULL, 1);
+	unregister_undef_hook(&debug_reg_hook);
+	if (!cpumask_empty(&debug_err_mask)) {
 		core_num_brps = 0;
-		core_num_reserved_brps = 0;
 		core_num_wrps = 0;
 		return 0;
 	}
 
+	pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
+		core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
+		"", core_num_wrps);
+
 	ARM_DBG_READ(c1, 0, dscr);
 	if (dscr & ARM_DSCR_HDBGEN) {
 		max_watchpoint_len = 4;
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/io.c linux-libre-3.2-gnu1/arch/arm/kernel/io.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/io.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/irq.c linux-libre-3.2-gnu1/arch/arm/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
  *  Naturally it's not a 1:1 relation, but there are similarities.
  */
 #include <linux/kernel_stat.h>
-#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -35,8 +34,8 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
-#include <linux/ftrace.h>
 
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -59,9 +58,6 @@ int arch_show_interrupts(struct seq_file
 #ifdef CONFIG_SMP
 	show_ipi_list(p, prec);
 #endif
-#ifdef CONFIG_LOCAL_TIMERS
-	show_local_irqs(p, prec);
-#endif
 	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-arm.c linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-arm.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -518,10 +519,12 @@ static const union decode_item arm_cccc_
 static const union decode_item arm_cccc_0001_____1001_table[] = {
 	/* Synchronization primitives					*/
 
+#if __LINUX_ARM_ARCH__ < 6
+	/* Deprecated on ARMv6 and may be UNDEFINED on v7		*/
 	/* SMP/SWPB		cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
 	DECODE_EMULATEX	(0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
 						 REGS(NOPC, NOPC, 0, 0, NOPC)),
-
+#endif
 	/* LDREX/STREX{,D,B,H}	cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
 	/* And unallocated instructions...				*/
 	DECODE_END
@@ -971,6 +974,9 @@ const union decode_item kprobe_decode_ar
 
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+#endif
 
 static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes.h linux-libre-3.2-gnu1/arch/arm/kernel/kprobes.h
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes.h	2012-01-04 18:55:44.000000000 -0500
@@ -413,6 +413,14 @@ struct decode_reject {
 	DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
 
 
+#ifdef CONFIG_THUMB2_KERNEL
+extern const union decode_item kprobe_decode_thumb16_table[];
+extern const union decode_item kprobe_decode_thumb32_table[];
+#else
+extern const union decode_item kprobe_decode_arm_table[];
+#endif
+
+
 int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
 			const union decode_item *table, bool thumb16);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test-arm.c linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test-arm.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test-arm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test-arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1330 @@
+/*
+ * arch/arm/kernel/kprobes-test-arm.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "32"
+
+#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_REG(reg, val)					\
+	TEST_ARG_REG(14, 99f)					\
+	TEST_ARG_END("")					\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"3:	adr	lr, 2f		\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_PTR(reg, val)					\
+	TEST_ARG_REG(14, 99f)					\
+	TEST_ARG_MEM(15, 3f+1)					\
+	TEST_ARG_END("")					\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"3:	adr	lr, 2f		\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+
+void kprobe_arm_test_cases(void)
+{
+	kprobe_test_flags = 0;
+
+	TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
+
+#define _DATA_PROCESSING_DNM(op,s,val)						\
+	TEST_RR(  op "eq" s "	r0,  r",1, VAL1,", r",2, val, "")		\
+	TEST_RR(  op "ne" s "	r1,  r",1, VAL1,", r",2, val, ", lsl #3")	\
+	TEST_RR(  op "cs" s "	r2,  r",3, VAL1,", r",2, val, ", lsr #4")	\
+	TEST_RR(  op "cc" s "	r3,  r",3, VAL1,", r",2, val, ", asr #5")	\
+	TEST_RR(  op "mi" s "	r4,  r",5, VAL1,", r",2, N(val),", asr #6")	\
+	TEST_RR(  op "pl" s "	r5,  r",5, VAL1,", r",2, val, ", ror #7")	\
+	TEST_RR(  op "vs" s "	r6,  r",7, VAL1,", r",2, val, ", rrx")		\
+	TEST_R(   op "vc" s "	r6,  r",7, VAL1,", pc, lsl #3")			\
+	TEST_R(   op "vc" s "	r6,  r",7, VAL1,", sp, lsr #4")			\
+	TEST_R(   op "vc" s "	r6,  pc, r",7, VAL1,", asr #5")			\
+	TEST_R(   op "vc" s "	r6,  sp, r",7, VAL1,", ror #6")			\
+	TEST_RRR( op "hi" s "	r8,  r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
+	TEST_RRR( op "ls" s "	r9,  r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
+	TEST_RRR( op "ge" s "	r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
+	TEST_RRR( op "lt" s "	r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
+	TEST_RR(  op "gt" s "	r12, r13"       ", r",14,val, ", ror r",14,7,"")\
+	TEST_RR(  op "le" s "	r14, r",0, val, ", r13"       ", lsl r",14,8,"")\
+	TEST_RR(  op s "	r12, pc"        ", r",14,val, ", ror r",14,7,"")\
+	TEST_RR(  op s "	r14, r",0, val, ", pc"        ", lsl r",14,8,"")\
+	TEST_R(   op "eq" s "	r0,  r",11,VAL1,", #0xf5")			\
+	TEST_R(   op "ne" s "	r11, r",0, VAL1,", #0xf5000000")		\
+	TEST_R(   op s "	r7,  r",8, VAL2,", #0x000af000")		\
+	TEST(     op s "	r4,  pc"        ", #0x00005a00")
+
+#define DATA_PROCESSING_DNM(op,val)		\
+	_DATA_PROCESSING_DNM(op,"",val)		\
+	_DATA_PROCESSING_DNM(op,"s",val)
+
+#define DATA_PROCESSING_NM(op,val)						\
+	TEST_RR(  op "ne	r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(  op "eq	r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(  op "cc	r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(  op "cs	r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(  op "pl	r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(  op "mi	r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(  op "vc	r",7, VAL1,", r",2, val, ", rrx")		\
+	TEST_R (  op "vs	r",7, VAL1,", pc, lsl #3")			\
+	TEST_R (  op "vs	r",7, VAL1,", sp, lsr #4")			\
+	TEST_R(   op "vs	pc, r",7, VAL1,", asr #5")			\
+	TEST_R(   op "vs	sp, r",7, VAL1,", ror #6")			\
+	TEST_RRR( op "ls	r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")	\
+	TEST_RRR( op "hi	r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")	\
+	TEST_RRR( op "lt	r",11,VAL1,", r",14,val, ", asr r",7, 5,"")	\
+	TEST_RRR( op "ge	r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")	\
+	TEST_RR(  op "le	r13"       ", r",14,val, ", ror r",14,7,"")	\
+	TEST_RR(  op "gt	r",0, val, ", r13"       ", lsl r",14,8,"")	\
+	TEST_RR(  op "	pc"        ", r",14,val, ", ror r",14,7,"")		\
+	TEST_RR(  op "	r",0, val, ", pc"        ", lsl r",14,8,"")		\
+	TEST_R(   op "eq	r",11,VAL1,", #0xf5")				\
+	TEST_R(   op "ne	r",0, VAL1,", #0xf5000000")			\
+	TEST_R(   op "	r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING_DM(op,s,val)					\
+	TEST_R(   op "eq" s "	r0,  r",1, val, "")			\
+	TEST_R(   op "ne" s "	r1,  r",1, val, ", lsl #3")		\
+	TEST_R(   op "cs" s "	r2,  r",3, val, ", lsr #4")		\
+	TEST_R(   op "cc" s "	r3,  r",3, val, ", asr #5")		\
+	TEST_R(   op "mi" s "	r4,  r",5, N(val),", asr #6")		\
+	TEST_R(   op "pl" s "	r5,  r",5, val, ", ror #7")		\
+	TEST_R(   op "vs" s "	r6,  r",10,val, ", rrx")		\
+	TEST(     op "vs" s "	r7,  pc, lsl #3")			\
+	TEST(     op "vs" s "	r7,  sp, lsr #4")			\
+	TEST_RR(  op "vc" s "	r8,  r",7, val, ", lsl r",0, 3,"")	\
+	TEST_RR(  op "hi" s "	r9,  r",9, val, ", lsr r",7, 4,"")	\
+	TEST_RR(  op "ls" s "	r10, r",9, val, ", asr r",7, 5,"")	\
+	TEST_RR(  op "ge" s "	r11, r",11,N(val),", asr r",7, 6,"")	\
+	TEST_RR(  op "lt" s "	r12, r",11,val, ", ror r",14,7,"")	\
+	TEST_R(   op "gt" s "	r14, r13"       ", lsl r",14,8,"")	\
+	TEST_R(   op "le" s "	r14, pc"        ", lsl r",14,8,"")	\
+	TEST(     op "eq" s "	r0,  #0xf5")				\
+	TEST(     op "ne" s "	r11, #0xf5000000")			\
+	TEST(     op s "	r7,  #0x000af000")			\
+	TEST(     op s "	r4,  #0x00005a00")
+
+#define DATA_PROCESSING_DM(op,val)		\
+	_DATA_PROCESSING_DM(op,"",val)		\
+	_DATA_PROCESSING_DM(op,"s",val)
+
+	DATA_PROCESSING_DNM("and",0xf00f00ff)
+	DATA_PROCESSING_DNM("eor",0xf00f00ff)
+	DATA_PROCESSING_DNM("sub",VAL2)
+	DATA_PROCESSING_DNM("rsb",VAL2)
+	DATA_PROCESSING_DNM("add",VAL2)
+	DATA_PROCESSING_DNM("adc",VAL2)
+	DATA_PROCESSING_DNM("sbc",VAL2)
+	DATA_PROCESSING_DNM("rsc",VAL2)
+	DATA_PROCESSING_NM("tst",0xf00f00ff)
+	DATA_PROCESSING_NM("teq",0xf00f00ff)
+	DATA_PROCESSING_NM("cmp",VAL2)
+	DATA_PROCESSING_NM("cmn",VAL2)
+	DATA_PROCESSING_DNM("orr",0xf00f00ff)
+	DATA_PROCESSING_DM("mov",VAL2)
+	DATA_PROCESSING_DNM("bic",0xf00f00ff)
+	DATA_PROCESSING_DM("mvn",VAL2)
+
+	TEST("mov	ip, sp") /* This has special case emulation code */
+
+	TEST_SUPPORTED("mov	pc, #0x1000");
+	TEST_SUPPORTED("mov	sp, #0x1000");
+	TEST_SUPPORTED("cmp	pc, #0x1000");
+	TEST_SUPPORTED("cmp	sp, #0x1000");
+
+	/* Data-processing with PC as shift*/
+	TEST_UNSUPPORTED(".word 0xe15c0f1e	@ cmp	r12, r14, asl pc")
+	TEST_UNSUPPORTED(".word 0xe1a0cf1e	@ mov	r12, r14, asl pc")
+	TEST_UNSUPPORTED(".word 0xe08caf1e	@ add	r10, r12, r14, asl pc")
+
+	/* Data-processing with PC as shift*/
+	TEST_UNSUPPORTED("movs	pc, r1")
+	TEST_UNSUPPORTED("movs	pc, r1, lsl r2")
+	TEST_UNSUPPORTED("movs	pc, #0x10000")
+	TEST_UNSUPPORTED("adds	pc, lr, r1")
+	TEST_UNSUPPORTED("adds	pc, lr, r1, lsl r2")
+	TEST_UNSUPPORTED("adds	pc, lr, #4")
+
+	/* Data-processing with SP as target */
+	TEST("add	sp, sp, #16")
+	TEST("sub	sp, sp, #8")
+	TEST("bic	sp, sp, #0x20")
+	TEST("orr	sp, sp, #0x20")
+	TEST_PR( "add	sp, r",10,0,", r",11,4,"")
+	TEST_PRR("add	sp, r",10,0,", r",11,4,", asl r",12,1,"")
+	TEST_P(  "mov	sp, r",10,0,"")
+	TEST_PR( "mov	sp, r",10,0,", asl r",12,0,"")
+
+	/* Data-processing with PC as target */
+	TEST_BF(   "add	pc, pc, #2f-1b-8")
+	TEST_BF_R ("add	pc, pc, r",14,2f-1f-8,"")
+	TEST_BF_R ("add	pc, r",14,2f-1f-8,", pc")
+	TEST_BF_R ("mov	pc, r",0,2f,"")
+	TEST_BF_RR("mov	pc, r",0,2f,", asl r",1,0,"")
+	TEST_BB(   "sub	pc, pc, #1b-2b+8")
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_BB(   "sub	pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */
+#endif
+	TEST_BB_R( "sub	pc, pc, r",14, 1f-2f+8,"")
+	TEST_BB_R( "rsb	pc, r",14,1f-2f+8,", pc")
+	TEST_RR(   "add	pc, pc, r",10,-2,", asl r",11,1,"")
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_R("add	pc, pc, r",0,3f-1f-8+1,"")
+	TEST_ARM_TO_THUMB_INTERWORK_R("sub	pc, r",0,3f+8+1,", #8")
+#endif
+	TEST_GROUP("Miscellaneous instructions")
+
+	TEST("mrs	r0, cpsr")
+	TEST("mrspl	r7, cpsr")
+	TEST("mrs	r14, cpsr")
+	TEST_UNSUPPORTED(".word 0xe10ff000	@ mrs r15, cpsr")
+	TEST_UNSUPPORTED("mrs	r0, spsr")
+	TEST_UNSUPPORTED("mrs	lr, spsr")
+
+	TEST_UNSUPPORTED("msr	cpsr, r0")
+	TEST_UNSUPPORTED("msr	cpsr_f, lr")
+	TEST_UNSUPPORTED("msr	spsr, r0")
+
+	TEST_BF_R("bx	r",0,2f,"")
+	TEST_BB_R("bx	r",7,2f,"")
+	TEST_BF_R("bxeq	r",14,2f,"")
+
+	TEST_R("clz	r0, r",0, 0x0,"")
+	TEST_R("clzeq	r7, r",14,0x1,"")
+	TEST_R("clz	lr, r",7, 0xffffffff,"")
+	TEST(  "clz	r4, sp")
+	TEST_UNSUPPORTED(".word 0x016fff10	@ clz pc, r0")
+	TEST_UNSUPPORTED(".word 0x016f0f1f	@ clz r0, pc")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("bxj	r0")
+#endif
+
+	TEST_BF_R("blx	r",0,2f,"")
+	TEST_BB_R("blx	r",7,2f,"")
+	TEST_BF_R("blxeq	r",14,2f,"")
+	TEST_UNSUPPORTED(".word 0x0120003f	@ blx pc")
+
+	TEST_RR(   "qadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qaddvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qadd	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qsubvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qsub	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qdadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qdaddvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qdadd	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qdsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qdsubvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qdsub	lr, r",9, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe101f050	@ qadd pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe121f050	@ qsub pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe141f050	@ qdadd pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe161f050	@ qdsub pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe16f2050	@ qdsub r2, r0, pc")
+	TEST_UNSUPPORTED(".word 0xe161205f	@ qdsub r2, pc, r1")
+
+	TEST_UNSUPPORTED("bkpt	0xffff")
+	TEST_UNSUPPORTED("bkpt	0x0000")
+
+	TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0")
+
+	TEST_GROUP("Halfword multiply and multiply-accumulate")
+
+	TEST_RRR(    "smlabb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlabbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlabb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3")
+	TEST_RRR(    "smlatb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlatbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlatb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3")
+	TEST_RRR(    "smlabt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlabtge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlabt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3")
+	TEST_RRR(    "smlatt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlattge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlatt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3")
+
+	TEST_RRR(    "smlawb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlawbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlawb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3")
+	TEST_RRR(    "smlawt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlawtge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlawt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc")
+
+	TEST_RR(    "smulwb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulwb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2")
+	TEST_RR(    "smulwt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwtge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulwt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2")
+
+	TEST_RRRR(  "smlalbb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalbble	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlalbb	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3")
+	TEST_RRRR(  "smlaltb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlaltble	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlaltb	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3")
+	TEST_RRRR(  "smlalbt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalbtle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlalbt	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3")
+	TEST_RRRR(  "smlaltt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalttle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlaltt	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc")
+
+	TEST_RR(    "smulbb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulbb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2")
+	TEST_RR(    "smultb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smultb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2")
+	TEST_RR(    "smulbt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbtge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulbt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2")
+	TEST_RR(    "smultt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulttge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smultt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2")
+	TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2")
+	TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc")
+
+	TEST_GROUP("Multiply and multiply-accumulate")
+
+	TEST_RR(    "mul	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mulls	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_R(     "mul	lr, r",4, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2")
+	TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2")
+	TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc")
+	TEST_RR(    "muls	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mullss	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_R(     "muls	lr, r",4, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2")
+
+	TEST_RRR(    "mla	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "mlahi	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "mla	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3")
+	TEST_RRR(    "mlas	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "mlahis	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "mlas	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_RR(  "umaal	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umaalls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umaal	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
+	TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+
+	TEST_RRR(  "mls		r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(  "mlshi	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(   "mls		lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc")
+#endif
+
+	TEST_UNSUPPORTED(".word 0xe0700090 @ undef")
+	TEST_UNSUPPORTED(".word 0xe07fff9f @ undef")
+
+	TEST_RR(  "umull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umullls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umull	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3")
+	TEST_RR(  "umulls	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umulllss	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umulls	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3")
+
+	TEST_RRRR(  "umlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "umlalle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "umlal	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3")
+	TEST_RRRR(  "umlals	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "umlalles	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "umlals	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3")
+
+	TEST_RR(  "smull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "smullls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "smull	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3")
+	TEST_RR(  "smulls	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "smulllss	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "smulls	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3")
+
+	TEST_RRRR(  "smlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlal	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3")
+	TEST_RRRR(  "smlals	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalles	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlals	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc")
+
+	TEST_GROUP("Synchronization primitives")
+
+#if __LINUX_ARM_ARCH__ < 6
+	TEST_RP("swp	lr, r",7,VAL2,", [r",8,0,"]")
+	TEST_R( "swpvs	r0, r",1,VAL1,", [sp]")
+	TEST_RP("swp	sp, r",14,VAL2,", [r",12,13*4,"]")
+#else
+	TEST_UNSUPPORTED(".word 0xe108e097 @ swp	lr, r7, [r8]")
+	TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs	r0, r1, [sp]")
+	TEST_UNSUPPORTED(".word 0xe10cd09e @ swp	sp, r14 [r12]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
+	TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
+	TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
+#if __LINUX_ARM_ARCH__ < 6
+	TEST_RP("swpb	lr, r",7,VAL2,", [r",8,0,"]")
+	TEST_R( "swpvsb	r0, r",1,VAL1,", [sp]")
+#else
+	TEST_UNSUPPORTED(".word 0xe148e097 @ swpb	lr, r7, [r8]")
+	TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb	r0, r1, [sp]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
+
+	TEST_UNSUPPORTED(".word	0xe1100090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1200090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1300090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1500090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1600090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1700090") /* Unallocated space */
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("ldrex	r2, [sp]")
+	TEST_UNSUPPORTED("strexd	r0, r2, r3, [sp]")
+	TEST_UNSUPPORTED("ldrexd	r2, r3, [sp]")
+	TEST_UNSUPPORTED("strexb	r0, r2, [sp]")
+	TEST_UNSUPPORTED("ldrexb	r2, [sp]")
+	TEST_UNSUPPORTED("strexh	r0, r2, [sp]")
+	TEST_UNSUPPORTED("ldrexh	r2, [sp]")
+#endif
+	TEST_GROUP("Extra load/store instructions")
+
+	TEST_RPR(  "strh	r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
+	TEST_RPR(  "streqh	r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+	TEST_RPR(  "strh	r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")
+	TEST_RPR(  "strneh	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+	TEST_RPR(  "strh	r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
+	TEST_RPR(  "strh	r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0ba	@ strh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe089f0bb	@ strh pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089a0bf	@ strh r10, [r9], pc")
+
+	TEST_PR(   "ldrh	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrcsh	r14, [r",13,0, ", r",12, 48,"]")
+	TEST_PR(   "ldrh	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrcch	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrh	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrh	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0ba	@ ldrh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0bb	@ ldrh pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe099a0bf	@ ldrh r10, [r9], pc")
+
+	TEST_RP(   "strh	r",0, VAL1,", [r",1, 24,", #-2]")
+	TEST_RP(   "strmih	r",14,VAL2,", [r",13,0, ", #2]")
+	TEST_RP(   "strh	r",1, VAL1,", [r",2, 24,", #4]!")
+	TEST_RP(   "strplh	r",12,VAL2,", [r",11,24,", #-4]!")
+	TEST_RP(   "strh	r",2, VAL1,", [r",3, 24,"], #48")
+	TEST_RP(   "strh	r",10,VAL2,", [r",9, 64,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3b0	@ strh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0c9f3b0	@ strh pc, [r9], #48")
+
+	TEST_P(	   "ldrh	r0, [r",0,  24,", #-2]")
+	TEST_P(	   "ldrvsh	r14, [r",13,0, ", #2]")
+	TEST_P(	   "ldrh	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrvch	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrh	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrh	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrh	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3b0	@ ldrh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3b0	@ ldrh pc, [r9], #48")
+
+	TEST_PR(   "ldrsb	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrhisb	r14, [r",13,0,", r",12,  48,"]")
+	TEST_PR(   "ldrsb	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrlssb	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrsb	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrsb	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0da	@ ldrsb r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0db	@ ldrsb pc, [r9], r11")
+
+	TEST_P(	   "ldrsb	r0, [r",0,  24,", #-1]")
+	TEST_P(	   "ldrgesb	r14, [r",13,0, ", #1]")
+	TEST_P(	   "ldrsb	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrltsb	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrsb	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrsb	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrsb	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3d0	@ ldrsb r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3d0	@ ldrsb pc, [r9], #48")
+
+	TEST_PR(   "ldrsh	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrgtsh	r14, [r",13,0, ", r",12, 48,"]")
+	TEST_PR(   "ldrsh	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrlesh	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrsh	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrsh	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0fa	@ ldrsh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0fb	@ ldrsh pc, [r9], r11")
+
+	TEST_P(	   "ldrsh	r0, [r",0,  24,", #-1]")
+	TEST_P(	   "ldreqsh	r14, [r",13,0 ,", #1]")
+	TEST_P(	   "ldrsh	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrnesh	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrsh	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrsh	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrsh	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3f0	@ ldrsh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3f0	@ ldrsh pc, [r9], #48")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_UNSUPPORTED("strht	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrht	r1, [r2], r3")
+	TEST_UNSUPPORTED("strht	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrht	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrsbt	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrsbt	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrsht	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrsht	r1, [r2], #48")
+#endif
+
+	TEST_RPR(  "strd	r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
+	TEST_RPR(  "strccd	r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+	TEST_RPR(  "strd	r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
+	TEST_RPR(  "strcsd	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+	TEST_RPR(  "strd	r",2, VAL1,", [r",5, 24,"], r",4,48,"")
+	TEST_RPR(  "strd	r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0fa	@ strd r12, [pc, r10]!")
+
+	TEST_PR(   "ldrd	r0, [r",0, 48,", -r",2,24,"]")
+	TEST_PR(   "ldrmid	r8, [r",13,0, ", r",12,48,"]")
+	TEST_PR(   "ldrd	r4, [r",2, 24,", r",3, 48,"]!")
+	TEST_PR(   "ldrpld	r6, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrd	r2, [r",5, 24,"], r",4,48,"")
+	TEST_PR(   "ldrd	r10, [r",9,48,"], -r",7,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0da	@ ldrd r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe089f0db	@ ldrd pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089e0db	@ ldrd lr, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089c0df	@ ldrd r12, [r9], pc")
+
+	TEST_RP(   "strd	r",0, VAL1,", [r",1, 24,", #-8]")
+	TEST_RP(   "strvsd	r",8, VAL2,", [r",13,0, ", #8]")
+	TEST_RP(   "strd	r",4, VAL1,", [r",2, 24,", #16]!")
+	TEST_RP(   "strvcd	r",12,VAL2,", [r",11,24,", #-16]!")
+	TEST_RP(   "strd	r",2, VAL1,", [r",4, 24,"], #48")
+	TEST_RP(   "strd	r",10,VAL2,", [r",9, 64,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3f0	@ strd r12, [pc, #48]!")
+
+	TEST_P(	   "ldrd	r0, [r",0, 24,", #-8]")
+	TEST_P(	   "ldrhid	r8, [r",13,0, ", #8]")
+	TEST_P(	   "ldrd	r4, [r",2, 24,", #16]!")
+	TEST_P(	   "ldrlsd	r6, [r",11,24,", #-16]!")
+	TEST_P(	   "ldrd	r2, [r",5, 24,"], #48")
+	TEST_P(	   "ldrd	r10, [r",9,6,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3d0	@ ldrd r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0c9f3d0	@ ldrd pc, [r9], #48")
+	TEST_UNSUPPORTED(".word 0xe0c9e3d0	@ ldrd lr, [r9], #48")
+
+	TEST_GROUP("Miscellaneous")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST("movw	r0, #0")
+	TEST("movw	r0, #0xffff")
+	TEST("movw	lr, #0xffff")
+	TEST_UNSUPPORTED(".word 0xe300f000	@ movw pc, #0")
+	TEST_R("movt	r",0, VAL1,", #0")
+	TEST_R("movt	r",0, VAL2,", #0xffff")
+	TEST_R("movt	r",14,VAL1,", #0xffff")
+	TEST_UNSUPPORTED(".word 0xe340f000	@ movt pc, #0")
+#endif
+
+	TEST_UNSUPPORTED("msr	cpsr, 0x13")
+	TEST_UNSUPPORTED("msr	cpsr_f, 0xf0000000")
+	TEST_UNSUPPORTED("msr	spsr, 0x13")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_SUPPORTED("yield")
+	TEST("sev")
+	TEST("nop")
+	TEST("wfi")
+	TEST_SUPPORTED("wfe")
+	TEST_UNSUPPORTED("dbg #0")
+#endif
+
+	TEST_GROUP("Load/store word and unsigned byte")
+
+#define LOAD_STORE(byte)							\
+	TEST_RP( "str"byte"	r",0, VAL1,", [r",1, 24,", #-2]")		\
+	TEST_RP( "str"byte"	r",14,VAL2,", [r",13,0, ", #2]")		\
+	TEST_RP( "str"byte"	r",1, VAL1,", [r",2, 24,", #4]!")		\
+	TEST_RP( "str"byte"	r",12,VAL2,", [r",11,24,", #-4]!")		\
+	TEST_RP( "str"byte"	r",2, VAL1,", [r",3, 24,"], #48")		\
+	TEST_RP( "str"byte"	r",10,VAL2,", [r",9, 64,"], #-48")		\
+	TEST_RPR("str"byte"	r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")	\
+	TEST_RPR("str"byte"	r",14,VAL2,", [r",13,0, ", r",12, 48,"]")	\
+	TEST_RPR("str"byte"	r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")	\
+	TEST_RPR("str"byte"	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")	\
+	TEST_RPR("str"byte"	r",2, VAL1,", [r",3, 24,"], r",4, 48,"")	\
+	TEST_RPR("str"byte"	r",10,VAL2,", [r",9, 48,"], -r",11,24,"")	\
+	TEST_RPR("str"byte"	r",0, VAL1,", [r",1, 24,", r",2,  32,", asl #1]")\
+	TEST_RPR("str"byte"	r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+	TEST_RPR("str"byte"	r",1, VAL1,", [r",2, 24,", r",3,  32,", asr #3]!")\
+	TEST_RPR("str"byte"	r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
+	TEST_P(  "ldr"byte"	r0, [r",0,  24,", #-2]")			\
+	TEST_P(  "ldr"byte"	r14, [r",13,0, ", #2]")				\
+	TEST_P(  "ldr"byte"	r1, [r",2,  24,", #4]!")			\
+	TEST_P(  "ldr"byte"	r12, [r",11,24,", #-4]!")			\
+	TEST_P(  "ldr"byte"	r2, [r",3,  24,"], #48")			\
+	TEST_P(  "ldr"byte"	r10, [r",9, 64,"], #-48")			\
+	TEST_PR( "ldr"byte"	r0, [r",0,  48,", -r",2, 24,"]")		\
+	TEST_PR( "ldr"byte"	r14, [r",13,0, ", r",12, 48,"]")		\
+	TEST_PR( "ldr"byte"	r1, [r",2,  24,", r",3, 48,"]!")		\
+	TEST_PR( "ldr"byte"	r12, [r",11,48,", -r",10,24,"]!")		\
+	TEST_PR( "ldr"byte"	r2, [r",3,  24,"], r",4, 48,"")			\
+	TEST_PR( "ldr"byte"	r10, [r",9, 48,"], -r",11,24,"")		\
+	TEST_PR( "ldr"byte"	r0, [r",0,  24,", r",2,  32,", asl #1]")	\
+	TEST_PR( "ldr"byte"	r14, [r",13,0, ", r",12, 32,", lsr #2]")	\
+	TEST_PR( "ldr"byte"	r1, [r",2,  24,", r",3,  32,", asr #3]!")	\
+	TEST_PR( "ldr"byte"	r12, [r",11,24,", r",10, 4,", ror #31]!")	\
+	TEST(    "ldr"byte"	r0, [pc, #0]")					\
+	TEST_R(  "ldr"byte"	r12, [pc, r",14,0,"]")
+
+	LOAD_STORE("")
+	TEST_P(   "str	pc, [r",0,0,", #15*4]")
+	TEST_R(   "str	pc, [sp, r",2,15*4,"]")
+	TEST_BF(  "ldr	pc, [sp, #15*4]")
+	TEST_BF_R("ldr	pc, [sp, r",2,15*4,"]")
+
+	TEST_P(   "str	sp, [r",0,0,", #13*4]")
+	TEST_R(   "str	sp, [sp, r",2,13*4,"]")
+	TEST_BF(  "ldr	sp, [sp, #13*4]")
+	TEST_BF_R("ldr	sp, [sp, r",2,13*4,"]")
+
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldr	pc, [r",0,0,", #15*4]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe5af6008	@ str r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7af6008	@ str r6, [pc, r8]!")
+	TEST_UNSUPPORTED(".word 0xe5bf6008	@ ldr r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7bf6008	@ ldr r6, [pc, r8]!")
+	TEST_UNSUPPORTED(".word 0xe788600f	@ str r6, [r8, pc]")
+	TEST_UNSUPPORTED(".word 0xe798600f	@ ldr r6, [r8, pc]")
+
+	LOAD_STORE("b")
+	TEST_UNSUPPORTED(".word 0xe5f7f008	@ ldrb pc, [r7, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7f7f008	@ ldrb pc, [r7, r8]!")
+	TEST_UNSUPPORTED(".word 0xe5ef6008	@ strb r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7ef6008	@ strb r6, [pc, r3]!")
+	TEST_UNSUPPORTED(".word 0xe5ff6008	@ ldrb r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7ff6008	@ ldrb r6, [pc, r3]!")
+
+	TEST_UNSUPPORTED("ldrt	r0, [r1], #4")
+	TEST_UNSUPPORTED("ldrt	r1, [r2], r3")
+	TEST_UNSUPPORTED("strt	r2, [r3], #4")
+	TEST_UNSUPPORTED("strt	r3, [r4], r5")
+	TEST_UNSUPPORTED("ldrbt	r4, [r5], #4")
+	TEST_UNSUPPORTED("ldrbt	r5, [r6], r7")
+	TEST_UNSUPPORTED("strbt	r6, [r7], #4")
+	TEST_UNSUPPORTED("strbt	r7, [r8], r9")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_GROUP("Parallel addition and subtraction, signed")
+
+	TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */
+
+	TEST_RR(    "sadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff1a	@ sadd16	pc, r12, r10")
+	TEST_RR(    "sasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff3a	@ sasx	pc, r12, r10")
+	TEST_RR(    "ssax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff5a	@ ssax	pc, r12, r10")
+	TEST_RR(    "ssub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff7a	@ ssub16	pc, r12, r10")
+	TEST_RR(    "sadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff9a	@ sadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */
+	TEST_RR(    "ssub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cfffa	@ ssub8	pc, r12, r10")
+
+	TEST_RR(    "qadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff1a	@ qadd16	pc, r12, r10")
+	TEST_RR(    "qasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff3a	@ qasx	pc, r12, r10")
+	TEST_RR(    "qsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff5a	@ qsax	pc, r12, r10")
+	TEST_RR(    "qsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff7a	@ qsub16	pc, r12, r10")
+	TEST_RR(    "qadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff9a	@ qadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */
+	TEST_RR(    "qsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cfffa	@ qsub8	pc, r12, r10")
+
+	TEST_RR(    "shadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff1a	@ shadd16	pc, r12, r10")
+	TEST_RR(    "shasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff3a	@ shasx	pc, r12, r10")
+	TEST_RR(    "shsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff5a	@ shsax	pc, r12, r10")
+	TEST_RR(    "shsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff7a	@ shsub16	pc, r12, r10")
+	TEST_RR(    "shadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff9a	@ shadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */
+	TEST_RR(    "shsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cfffa	@ shsub8	pc, r12, r10")
+
+	TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+	TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */
+
+	TEST_RR(    "uadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff1a	@ uadd16	pc, r12, r10")
+	TEST_RR(    "uasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff3a	@ uasx	pc, r12, r10")
+	TEST_RR(    "usax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff5a	@ usax	pc, r12, r10")
+	TEST_RR(    "usub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff7a	@ usub16	pc, r12, r10")
+	TEST_RR(    "uadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff9a	@ uadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */
+	TEST_RR(    "usub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cfffa	@ usub8	pc, r12, r10")
+
+	TEST_RR(    "uqadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff1a	@ uqadd16	pc, r12, r10")
+	TEST_RR(    "uqasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff3a	@ uqasx	pc, r12, r10")
+	TEST_RR(    "uqsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff5a	@ uqsax	pc, r12, r10")
+	TEST_RR(    "uqsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff7a	@ uqsub16	pc, r12, r10")
+	TEST_RR(    "uqadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff9a	@ uqadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */
+	TEST_RR(    "uqsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cfffa	@ uqsub8	pc, r12, r10")
+
+	TEST_RR(    "uhadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff1a	@ uhadd16	pc, r12, r10")
+	TEST_RR(    "uhasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff3a	@ uhasx	pc, r12, r10")
+	TEST_RR(    "uhsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff5a	@ uhsax	pc, r12, r10")
+	TEST_RR(    "uhsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff7a	@ uhsub16	pc, r12, r10")
+	TEST_RR(    "uhadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff9a	@ uhadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */
+	TEST_RR(    "uhsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cfffa	@ uhsub8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe67feffa	@ uhsub8	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe67cefff	@ uhsub8	r14, r12, pc")
+#endif /* __LINUX_ARM_ARCH__ >= 7 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_GROUP("Packing, unpacking, saturation, and reversal")
+
+	TEST_RR(    "pkhbt	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "pkhbt	r14,r",12, HH1,", r",10,HH2,", lsl #2")
+	TEST_UNSUPPORTED(".word 0xe68cf11a	@ pkhbt	pc, r12, r10, lsl #2")
+	TEST_RR(    "pkhtb	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "pkhtb	r14,r",12, HH1,", r",10,HH2,", asr #2")
+	TEST_UNSUPPORTED(".word 0xe68cf15a	@ pkhtb	pc, r12, r10, asr #2")
+	TEST_UNSUPPORTED(".word 0xe68fe15a	@ pkhtb	r14, pc, r10, asr #2")
+	TEST_UNSUPPORTED(".word 0xe68ce15f	@ pkhtb	r14, r12, pc, asr #2")
+	TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */
+
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".word 0xe6b7f01c	@ ssat	pc, #24, r12")
+
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".word 0xe6f7f01c	@ usat	pc, #24, r12")
+
+	TEST_RR(    "sxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb16	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe68cf47a	@ sxtab16	pc,r12, r10, ror #8")
+
+	TEST_RR(    "sel	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "sel	r14, r",12,VAL1,", r",10, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe68cffba	@ sel	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe68fefba	@ sel	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe68cefbf	@ sel	r14, r12, pc")
+
+	TEST_R(     "ssat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "ssat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".word 0xe6abff3c	@ ssat16	pc, #12, r12")
+
+	TEST_RR(    "sxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6acf47a	@ sxtab	pc,r12, r10, ror #8")
+
+	TEST_R(     "rev	r0, r",0,   VAL1,"")
+	TEST_R(     "rev	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6bfff3c	@ rev	pc, r12")
+
+	TEST_RR(    "sxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxth	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6bcf47a	@ sxtah	pc,r12, r10, ror #8")
+
+	TEST_R(     "rev16	r0, r",0,   VAL1,"")
+	TEST_R(     "rev16	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6bfffbc	@ rev16	pc, r12")
+
+	TEST_RR(    "uxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb16	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6ccf47a	@ uxtab16	pc,r12, r10, ror #8")
+
+	TEST_R(     "usat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "usat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".word 0xe6ecff3c	@ usat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".word 0xe6ecef3f	@ usat16	r14, #12, pc")
+
+	TEST_RR(    "uxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6ecf47a	@ uxtab	pc,r12, r10, ror #8")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_R(     "rbit	r0, r",0,   VAL1,"")
+	TEST_R(     "rbit	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6ffff3c	@ rbit	pc, r12")
+#endif
+
+	TEST_RR(    "uxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxth	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6fff077	@ uxth	pc, r7")
+	TEST_UNSUPPORTED(".word 0xe6ff807f	@ uxth	r8, pc")
+	TEST_UNSUPPORTED(".word 0xe6fcf47a	@ uxtah	pc, r12, r10, ror #8")
+	TEST_UNSUPPORTED(".word 0xe6fce47f	@ uxtah	r14, r12, pc, ror #8")
+
+	TEST_R(     "revsh	r0, r",0,   VAL1,"")
+	TEST_R(     "revsh	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6ffff3c	@ revsh	pc, r12")
+	TEST_UNSUPPORTED(".word 0xe6ffef3f	@ revsh	r14, pc")
+
+	TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */
+
+	TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_GROUP("Signed multiplies")
+
+	TEST_RRR(   "smlad	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlad	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a1c	@ smlad	pc, r12, r10, r8")
+	TEST_RRR(   "smladx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smladx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a3c	@ smladx	pc, r12, r10, r8")
+
+	TEST_RR(   "smuad	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smuad	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa1c	@ smuad	pc, r12, r10")
+	TEST_RR(   "smuadx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smuadx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa3c	@ smuadx	pc, r12, r10")
+
+	TEST_RRR(   "smlsd	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsd	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a5c	@ smlsd	pc, r12, r10, r8")
+	TEST_RRR(   "smlsdx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsdx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a7c	@ smlsdx	pc, r12, r10, r8")
+
+	TEST_RR(   "smusd	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smusd	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa5c	@ smusd	pc, r12, r10")
+	TEST_RR(   "smusdx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smusdx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa7c	@ smusdx	pc, r12, r10")
+
+	TEST_RRRR( "smlald	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlald	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_UNSUPPORTED(".word 0xe74af819	@ smlald	pc, r10, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74fb819	@ smlald	r11, pc, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74ab81f	@ smlald	r11, r10, pc, r8")
+	TEST_UNSUPPORTED(".word 0xe74abf19	@ smlald	r11, r10, r9, pc")
+
+	TEST_RRRR( "smlaldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlaldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_UNSUPPORTED(".word 0xe74af839	@ smlaldx	pc, r10, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74fb839	@ smlaldx	r11, pc, r9, r8")
+
+	TEST_RRR(  "smmla	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmla	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8a1c	@ smmla	pc, r12, r10, r8")
+	TEST_RRR(  "smmlar	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmlar	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8a3c	@ smmlar	pc, r12, r10, r8")
+
+	TEST_RR(   "smmul	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "smmul	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa1c	@ smmul	pc, r12, r10")
+	TEST_RR(   "smmulr	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "smmulr	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa3c	@ smmulr	pc, r12, r10")
+
+	TEST_RRR(  "smmls	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmls	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8adc	@ smmls	pc, r12, r10, r8")
+	TEST_RRR(  "smmlsr	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmlsr	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8afc	@ smmlsr	pc, r12, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe75e8aff	@ smmlsr	r14, pc, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe75e8ffc	@ smmlsr	r14, r12, pc, r8")
+	TEST_UNSUPPORTED(".word 0xe75efafc	@ smmlsr	r14, r12, r10, pc")
+
+	TEST_RR(   "usad8	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "usad8	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa1c	@ usad8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe75efa1f	@ usad8	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe75eff1c	@ usad8	r14, r12, pc")
+
+	TEST_RRR(  "usada8	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+	TEST_RRR(  "usada8	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+	TEST_UNSUPPORTED(".word 0xe78f8a1c	@ usada8	pc, r12, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe78e8a1f	@ usada8	r14, pc, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe78e8f1c	@ usada8	r14, r12, pc, r8")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_GROUP("Bit Field")
+
+	TEST_R(     "sbfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "sbfxeq	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "sbfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".word 0xe7aff45c	@ sbfx	pc, r12, #8, #16")
+
+	TEST_R(     "ubfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "ubfxcs	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "ubfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".word 0xe7eff45c	@ ubfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".word 0xe7efc45f	@ ubfx	r12, pc, #8, #16")
+
+	TEST_R(     "bfc	r",0, VAL1,", #4, #20")
+	TEST_R(     "bfcvs	r",14,VAL2,", #4, #20")
+	TEST_R(     "bfc	r",7, VAL1,", #0, #31")
+	TEST_R(     "bfc	r",8, VAL2,", #0, #31")
+	TEST_UNSUPPORTED(".word 0xe7def01f	@ bfc	pc, #0, #31");
+
+	TEST_RR(    "bfi	r",0, VAL1,", r",0  , VAL2,", #0, #31")
+	TEST_RR(    "bfipl	r",12,VAL1,", r",14 , VAL2,", #4, #20")
+	TEST_UNSUPPORTED(".word 0xe7d7f21e	@ bfi	pc, r14, #4, #20")
+
+	TEST_UNSUPPORTED(".word 0x07f000f0")  /* Permanently UNDEFINED */
+	TEST_UNSUPPORTED(".word 0x07ffffff")  /* Permanently UNDEFINED */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+	TEST_GROUP("Branch, branch with link, and block data transfer")
+
+	TEST_P(   "stmda	r",0, 16*4,", {r0}")
+	TEST_P(   "stmeqda	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmneda	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmda	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmda	r",13,0,   "!, {pc}")
+
+	TEST_P(   "ldmda	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmcsda	r",4, 15*4,", {r0-r15}")
+	TEST_BF_P("ldmccda	r",7, 15*4,"!, {r8-r15}")
+	TEST_P(   "ldmda	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmda	r",14,15*4,"!, {pc}")
+
+	TEST_P(   "stmia	r",0, 16*4,", {r0}")
+	TEST_P(   "stmmiia	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmplia	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmia	r",14,0,   "!, {pc}")
+
+	TEST_P(   "ldmia	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmvsia	r",4, 0,   ", {r0-r15}")
+	TEST_BF_P("ldmvcia	r",7, 8*4, "!, {r8-r15}")
+	TEST_P(   "ldmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmia	r",14,15*4,"!, {pc}")
+
+	TEST_P(   "stmdb	r",0, 16*4,", {r0}")
+	TEST_P(   "stmhidb	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmlsdb	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmdb	r",13,4,   "!, {pc}")
+
+	TEST_P(   "ldmdb	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmgedb	r",4, 16*4,", {r0-r15}")
+	TEST_BF_P("ldmltdb	r",7, 16*4,"!, {r8-r15}")
+	TEST_P(   "ldmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmdb	r",14,16*4,"!, {pc}")
+
+	TEST_P(   "stmib	r",0, 16*4,", {r0}")
+	TEST_P(   "stmgtib	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmleib	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmib	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmib	r",13,-4,  "!, {pc}")
+
+	TEST_P(   "ldmib	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmeqib	r",4, -4,", {r0-r15}")
+	TEST_BF_P("ldmneib	r",7, 7*4,"!, {r8-r15}")
+	TEST_P(   "ldmib	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmib	r",14,14*4,"!, {pc}")
+
+	TEST_P(   "stmdb	r",13,16*4,"!, {r3-r12,lr}")
+	TEST_P(	  "stmeqdb	r",13,16*4,"!, {r3-r12}")
+	TEST_P(   "stmnedb	r",2, 16*4,", {r3-r12,lr}")
+	TEST_P(   "stmdb	r",13,16*4,"!, {r2-r12,lr}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_BF_P("ldmia	r",13,5*4, "!, {r3-r12,pc}")
+	TEST_P(	  "ldmccia	r",13,5*4, "!, {r3-r12}")
+	TEST_BF_P("ldmcsia	r",2, 5*4, "!, {r3-r12,pc}")
+	TEST_BF_P("ldmia	r",13,4*4, "!, {r2-r12,pc}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12,lr}")
+
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia	r",0,15*4,", {pc}")
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia	r",13,0,", {r0-r15}")
+#endif
+	TEST_BF("b	2f")
+	TEST_BF("bl	2f")
+	TEST_BB("b	2b")
+	TEST_BB("bl	2b")
+
+	TEST_BF("beq	2f")
+	TEST_BF("bleq	2f")
+	TEST_BB("bne	2b")
+	TEST_BB("blne	2b")
+
+	TEST_BF("bgt	2f")
+	TEST_BF("blgt	2f")
+	TEST_BB("blt	2b")
+	TEST_BB("bllt	2b")
+
+	TEST_GROUP("Supervisor Call, and coprocessor instructions")
+
+	/*
+	 * We can't really test these by executing them, so all
+	 * we can do is check that probes are, or are not allowed.
+	 * At the moment none are allowed...
+	 */
+#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
+
+#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc)					\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], {1}")			\
+										\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"daf0001	@ stc"two"	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d2f0001	@ stc"two"	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"caf0001	@ stc"two"	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c2f0001	@ stc"two"	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"def0001	@ stc"two"l	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d6f0001	@ stc"two"l	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cef0001	@ stc"two"l	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c6f0001	@ stc"two"l	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"dbf0001	@ ldc"two"	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d3f0001	@ ldc"two"	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cbf0001	@ ldc"two"	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c3f0001	@ ldc"two"	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"dff0001	@ ldc"two"l	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d7f0001	@ ldc"two"l	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cff0001	@ ldc"two"l	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c7f0001	@ ldc"two"l	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15], {1}")
+
+#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc)					\
+										\
+	TEST_COPROCESSOR( "mcrr"two"	0, 15, r0, r14, cr0")			\
+	TEST_COPROCESSOR( "mcrr"two"	15, 0, r14, r0, cr15")			\
+	TEST_UNSUPPORTED(".word 0x"cc"c4f00f0	@ mcrr"two"	0, 15, r0, r15, cr0")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c40ff0f	@ mcrr"two"	15, 0, r15, r0, cr15")	\
+	TEST_COPROCESSOR( "mrrc"two"	0, 15, r0, r14, cr0")			\
+	TEST_COPROCESSOR( "mrrc"two"	15, 0, r14, r0, cr15")			\
+	TEST_UNSUPPORTED(".word 0x"cc"c5f00f0	@ mrrc"two"	0, 15, r0, r15, cr0")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c50ff0f	@ mrrc"two"	15, 0, r15, r0, cr15")	\
+	TEST_COPROCESSOR( "cdp"two"	15, 15, cr15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "cdp"two"	0, 0, cr0, cr0, cr0, 0")		\
+	TEST_COPROCESSOR( "mcr"two"	15, 7, r15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "mcr"two"	0, 0, r0, cr0, cr0, 0")			\
+	TEST_COPROCESSOR( "mrc"two"	15, 7, r15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "mrc"two"	0, 0, r0, cr0, cr0, 0")
+
+	COPROCESSOR_INSTRUCTIONS_ST_LD("","e")
+	COPROCESSOR_INSTRUCTIONS_MC_MR("","e")
+	TEST_UNSUPPORTED("svc	0")
+	TEST_UNSUPPORTED("svc	0xffffff")
+
+	TEST_UNSUPPORTED("svc	0")
+
+	TEST_GROUP("Unconditional instruction")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("srsda	sp, 0x13")
+	TEST_UNSUPPORTED("srsdb	sp, 0x13")
+	TEST_UNSUPPORTED("srsia	sp, 0x13")
+	TEST_UNSUPPORTED("srsib	sp, 0x13")
+	TEST_UNSUPPORTED("srsda	sp!, 0x13")
+	TEST_UNSUPPORTED("srsdb	sp!, 0x13")
+	TEST_UNSUPPORTED("srsia	sp!, 0x13")
+	TEST_UNSUPPORTED("srsib	sp!, 0x13")
+
+	TEST_UNSUPPORTED("rfeda	sp")
+	TEST_UNSUPPORTED("rfedb	sp")
+	TEST_UNSUPPORTED("rfeia	sp")
+	TEST_UNSUPPORTED("rfeib	sp")
+	TEST_UNSUPPORTED("rfeda	sp!")
+	TEST_UNSUPPORTED("rfedb	sp!")
+	TEST_UNSUPPORTED("rfeia	sp!")
+	TEST_UNSUPPORTED("rfeib	sp!")
+	TEST_UNSUPPORTED(".word 0xf81d0a00	@ rfeda	pc")
+	TEST_UNSUPPORTED(".word 0xf91d0a00	@ rfedb	pc")
+	TEST_UNSUPPORTED(".word 0xf89d0a00	@ rfeia	pc")
+	TEST_UNSUPPORTED(".word 0xf99d0a00	@ rfeib	pc")
+	TEST_UNSUPPORTED(".word 0xf83d0a00	@ rfeda	pc!")
+	TEST_UNSUPPORTED(".word 0xf93d0a00	@ rfedb	pc!")
+	TEST_UNSUPPORTED(".word 0xf8bd0a00	@ rfeia	pc!")
+	TEST_UNSUPPORTED(".word 0xf9bd0a00	@ rfeib	pc!")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_X(	"blx	__dummy_thumb_subroutine_even",
+		".thumb				\n\t"
+		".space 4			\n\t"
+		".type __dummy_thumb_subroutine_even, %%function \n\t"
+		"__dummy_thumb_subroutine_even:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".arm				\n\t"
+	)
+	TEST(	"blx	__dummy_thumb_subroutine_even")
+
+	TEST_X(	"blx	__dummy_thumb_subroutine_odd",
+		".thumb				\n\t"
+		".space 2			\n\t"
+		".type __dummy_thumb_subroutine_odd, %%function	\n\t"
+		"__dummy_thumb_subroutine_odd:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".arm				\n\t"
+	)
+	TEST(	"blx	__dummy_thumb_subroutine_odd")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+	COPROCESSOR_INSTRUCTIONS_ST_LD("2","f")
+#if __LINUX_ARM_ARCH__ >= 6
+	COPROCESSOR_INSTRUCTIONS_MC_MR("2","f")
+#endif
+
+	TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("cps	0x13")
+	TEST_UNSUPPORTED("cpsie	i")
+	TEST_UNSUPPORTED("cpsid	i")
+	TEST_UNSUPPORTED("cpsie	i,0x13")
+	TEST_UNSUPPORTED("cpsid	i,0x13")
+	TEST_UNSUPPORTED("setend	le")
+	TEST_UNSUPPORTED("setend	be")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_P("pli	[r",0,0b,", #16]")
+	TEST(  "pli	[pc, #0]")
+	TEST_RR("pli	[r",12,0b,", r",0, 16,"]")
+	TEST_RR("pli	[r",0, 0b,", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 5
+	TEST_P("pld	[r",0,32,", #-16]")
+	TEST(  "pld	[pc, #0]")
+	TEST_PR("pld	[r",7, 24, ", r",0, 16,"]")
+	TEST_PR("pld	[r",8, 24, ", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_SUPPORTED(  ".word 0xf590f000	@ pldw [r0, #0]")
+	TEST_SUPPORTED(  ".word 0xf797f000	@ pldw	[r7, r0]")
+	TEST_SUPPORTED(  ".word 0xf798f18c	@ pldw	[r8, r12, lsl #3]");
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_UNSUPPORTED("clrex")
+	TEST_UNSUPPORTED("dsb")
+	TEST_UNSUPPORTED("dmb")
+	TEST_UNSUPPORTED("isb")
+#endif
+
+	verbose("\n");
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test.c linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1748 @@
+/*
+ * arch/arm/kernel/kprobes-test.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains test code for ARM kprobes.
+ *
+ * The top level function run_all_tests() executes tests for all of the
+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
+ * fall into two categories; run_api_tests() checks basic functionality of the
+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes
+ * instruction decoding and simulation.
+ *
+ * run_test_cases() first checks the kprobes decoding table for self consistency
+ * (using table_test()) then executes a series of test cases for each of the CPU
+ * instruction forms. coverage_start() and coverage_end() are used to verify
+ * that these test cases cover all of the possible combinations of instructions
+ * described by the kprobes decoding tables.
+ *
+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
+ * which use the macros defined in kprobes-test.h. The rest of this
+ * documentation will describe the operation of the framework used by these
+ * test cases.
+ */
+
+/*
+ * TESTING METHODOLOGY
+ * -------------------
+ *
+ * The methodology used to test an ARM instruction 'test_insn' is to use
+ * inline assembler like:
+ *
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ *
+ * When the test case is run a kprobe is placed of each nop. The
+ * post-handler of the test_before probe is used to modify the saved CPU
+ * register context to that which we require for the test case. The
+ * pre-handler of the of the test_after probe saves a copy of the CPU
+ * register context. In this way we can execute test_insn with a specific
+ * register context and see the results afterwards.
+ *
+ * To actually test the kprobes instruction emulation we perform the above
+ * step a second time but with an additional kprobe on the test_case
+ * instruction itself. If the emulation is accurate then the results seen
+ * by the test_after probe will be identical to the first run which didn't
+ * have a probe on test_case.
+ *
+ * Each test case is run several times with a variety of variations in the
+ * flags value of stored in CPSR, and for Thumb code, different ITState.
+ *
+ * For instructions which can modify PC, a second test_after probe is used
+ * like this:
+ *
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ *		b test_done
+ * test_after2: nop
+ * test_done:
+ *
+ * The test case is constructed such that test_insn branches to
+ * test_after2, or, if testing a conditional instruction, it may just
+ * continue to test_after. The probes inserted at both locations let us
+ * determine which happened. A similar approach is used for testing
+ * backwards branches...
+ *
+ *		b test_before
+ *		b test_done  @ helps to cope with off by 1 branches
+ * test_after2: nop
+ *		b test_done
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ * test_done:
+ *
+ * The macros used to generate the assembler instructions describe above
+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and
+ * 99 represent: test_before, test_case, test_after2 and test_done.
+ *
+ * FRAMEWORK
+ * ---------
+ *
+ * Each test case is wrapped between the pair of macros TESTCASE_START and
+ * TESTCASE_END. As well as performing the inline assembler boilerplate,
+ * these call out to the kprobes_test_case_start() and
+ * kprobes_test_case_end() functions which drive the execution of the test
+ * case. The specific arguments to use for each test case are stored as
+ * inline data constructed using the various TEST_ARG_* macros. Putting
+ * this all together, a simple test case may look like:
+ *
+ *	TESTCASE_START("Testing mov r0, r7")
+ *	TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
+ *	TEST_ARG_END("")
+ *	TEST_INSTRUCTION("mov r0, r7")
+ *	TESTCASE_END
+ *
+ * Note, in practice the single convenience macro TEST_R would be used for this
+ * instead.
+ *
+ * The above would expand to assembler looking something like:
+ *
+ *	@ TESTCASE_START
+ *	bl	__kprobes_test_case_start
+ *	@ start of inline data...
+ *	.ascii "mov r0, r7"	@ text title for test case
+ *	.byte	0
+ *	.align	2
+ *
+ *	@ TEST_ARG_REG
+ *	.byte	ARG_TYPE_REG
+ *	.byte	7
+ *	.short	0
+ *	.word	0x1234567
+ *
+ *	@ TEST_ARG_END
+ *	.byte	ARG_TYPE_END
+ *	.byte	TEST_ISA	@ flags, including ISA being tested
+ *	.short	50f-0f		@ offset of 'test_before'
+ *	.short	2f-0f		@ offset of 'test_after2' (if relevent)
+ *	.short	99f-0f		@ offset of 'test_done'
+ *	@ start of test case code...
+ *	0:
+ *	.code	TEST_ISA	@ switch to ISA being tested
+ *
+ *	@ TEST_INSTRUCTION
+ *	50:	nop		@ location for 'test_before' probe
+ *	1:	mov r0, r7	@ the test case instruction 'test_insn'
+ *		nop		@ location for 'test_after' probe
+ *
+ *	// TESTCASE_END
+ *	2:
+ *	99:	bl __kprobes_test_case_end_##TEST_ISA
+ *	.code	NONMAL_ISA
+ *
+ * When the above is execute the following happens...
+ *
+ * __kprobes_test_case_start() is an assembler wrapper which sets up space
+ * for a stack buffer and calls the C function kprobes_test_case_start().
+ * This C function will do some initial processing of the inline data and
+ * setup some global state. It then inserts the test_before and test_after
+ * kprobes and returns a value which causes the assembler wrapper to jump
+ * to the start of the test case code, (local label '0').
+ *
+ * When the test case code executes, the test_before probe will be hit and
+ * test_before_post_handler will call setup_test_context(). This fills the
+ * stack buffer and CPU registers with a test pattern and then processes
+ * the test case arguments. In our example there is one TEST_ARG_REG which
+ * indicates that R7 should be loaded with the value 0x12345678.
+ *
+ * When the test_before probe ends, the test case continues and executes
+ * the "mov r0, r7" instruction. It then hits the test_after probe and the
+ * pre-handler for this (test_after_pre_handler) will save a copy of the
+ * CPU register context. This should now have R0 holding the same value as
+ * R7.
+ *
+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
+ * an assembler wrapper which switches back to the ISA used by the test
+ * code and calls the C function kprobes_test_case_end().
+ *
+ * For each run through the test case, test_case_run_count is incremented
+ * by one. For even runs, kprobes_test_case_end() saves a copy of the
+ * register and stack buffer contents from the test case just run. It then
+ * inserts a kprobe on the test case instruction 'test_insn' and returns a
+ * value to cause the test case code to be re-run.
+ *
+ * For odd numbered runs, kprobes_test_case_end() compares the register and
+ * stack buffer contents to those that were saved on the previous even
+ * numbered run (the one without the kprobe on test_insn). These should be
+ * the same if the kprobe instruction simulation routine is correct.
+ *
+ * The pair of test case runs is repeated with different combinations of
+ * flag values in CPSR and, for Thumb, different ITState. This is
+ * controlled by test_context_cpsr().
+ *
+ * BUILDING TEST CASES
+ * -------------------
+ *
+ *
+ * As an aid to building test cases, the stack buffer is initialised with
+ * some special values:
+ *
+ *   [SP+13*4]	Contains SP+120. This can be used to test instructions
+ *		which load a value into SP.
+ *
+ *   [SP+15*4]	When testing branching instructions using TEST_BRANCH_{F,B},
+ *		this holds the target address of the branch, 'test_after2'.
+ *		This can be used to test instructions which load a PC value
+ *		from memory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+#include "kprobes-test.h"
+
+
+#define BENCHMARKING	1
+
+
+/*
+ * Test basic API
+ */
+
+static bool test_regs_ok;
+static int test_func_instance;
+static int pre_handler_called;
+static int post_handler_called;
+static int jprobe_func_called;
+static int kretprobe_handler_called;
+
+#define FUNC_ARG1 0x12345678
+#define FUNC_ARG2 0xabcdef
+
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+long arm_func(long r0, long r1);
+
+static void __used __naked __arm_kprobes_test_func(void)
+{
+	__asm__ __volatile__ (
+		".arm					\n\t"
+		".type arm_func, %%function		\n\t"
+		"arm_func:				\n\t"
+		"adds	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+		".code "NORMAL_ISA	 /* Back to Thumb if necessary */
+		: : : "r0", "r1", "cc"
+	);
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+long thumb16_func(long r0, long r1);
+long thumb32even_func(long r0, long r1);
+long thumb32odd_func(long r0, long r1);
+
+static void __used __naked __thumb_kprobes_test_funcs(void)
+{
+	__asm__ __volatile__ (
+		".type thumb16_func, %%function		\n\t"
+		"thumb16_func:				\n\t"
+		"adds.n	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		".align					\n\t"
+		".type thumb32even_func, %%function	\n\t"
+		"thumb32even_func:			\n\t"
+		"adds.w	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		".align					\n\t"
+		"nop.n					\n\t"
+		".type thumb32odd_func, %%function	\n\t"
+		"thumb32odd_func:			\n\t"
+		"adds.w	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		: : : "r0", "r1", "cc"
+	);
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+
+static int call_test_func(long (*func)(long, long), bool check_test_regs)
+{
+	long ret;
+
+	++test_func_instance;
+	test_regs_ok = false;
+
+	ret = (*func)(FUNC_ARG1, FUNC_ARG2);
+	if (ret != FUNC_ARG1 + FUNC_ARG2) {
+		pr_err("FAIL: call_test_func: func returned %lx\n", ret);
+		return false;
+	}
+
+	if (check_test_regs && !test_regs_ok) {
+		pr_err("FAIL: test regs not OK\n");
+		return false;
+	}
+
+	return true;
+}
+
+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	pre_handler_called = test_func_instance;
+	if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
+		test_regs_ok = true;
+	return 0;
+}
+
+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
+				unsigned long flags)
+{
+	post_handler_called = test_func_instance;
+	if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
+		test_regs_ok = false;
+}
+
+static struct kprobe the_kprobe = {
+	.addr		= 0,
+	.pre_handler	= pre_handler,
+	.post_handler	= post_handler
+};
+
+static int test_kprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_kprobe.addr = (kprobe_opcode_t *)func;
+	ret = register_kprobe(&the_kprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_kprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_kprobe(&the_kprobe);
+	the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (pre_handler_called != test_func_instance) {
+		pr_err("FAIL: kprobe pre_handler not called\n");
+		return -EINVAL;
+	}
+	if (post_handler_called != test_func_instance) {
+		pr_err("FAIL: kprobe post_handler not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (pre_handler_called == test_func_instance ||
+				post_handler_called == test_func_instance) {
+		pr_err("FAIL: probe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __kprobes jprobe_func(long r0, long r1)
+{
+	jprobe_func_called = test_func_instance;
+	if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
+		test_regs_ok = true;
+	jprobe_return();
+}
+
+static struct jprobe the_jprobe = {
+	.entry		= jprobe_func,
+};
+
+static int test_jprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_jprobe.kp.addr = (kprobe_opcode_t *)func;
+	ret = register_jprobe(&the_jprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_jprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_jprobe(&the_jprobe);
+	the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (jprobe_func_called != test_func_instance) {
+		pr_err("FAIL: jprobe handler function not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (jprobe_func_called == test_func_instance) {
+		pr_err("FAIL: probe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __kprobes
+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	kretprobe_handler_called = test_func_instance;
+	if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
+		test_regs_ok = true;
+	return 0;
+}
+
+static struct kretprobe the_kretprobe = {
+	.handler	= kretprobe_handler,
+};
+
+static int test_kretprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
+	ret = register_kretprobe(&the_kretprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_kretprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_kretprobe(&the_kretprobe);
+	the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (kretprobe_handler_called != test_func_instance) {
+		pr_err("FAIL: kretprobe handler not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (jprobe_func_called == test_func_instance) {
+		pr_err("FAIL: kretprobe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int run_api_tests(long (*func)(long, long))
+{
+	int ret;
+
+	pr_info("    kprobe\n");
+	ret = test_kprobe(func);
+	if (ret < 0)
+		return ret;
+
+	pr_info("    jprobe\n");
+	ret = test_jprobe(func);
+	if (ret < 0)
+		return ret;
+
+	pr_info("    kretprobe\n");
+	ret = test_kretprobe(func);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+
+/*
+ * Benchmarking
+ */
+
+#if BENCHMARKING
+
+static void __naked benchmark_nop(void)
+{
+	__asm__ __volatile__ (
+		"nop		\n\t"
+		"bx	lr"
+	);
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define wide ".w"
+#else
+#define wide
+#endif
+
+static void __naked benchmark_pushpop1(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r3-r11,lr}  \n\t"
+		"ldmia"wide"	sp!, {r3-r11,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop2(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r0-r8,lr}  \n\t"
+		"ldmia"wide"	sp!, {r0-r8,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop3(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r4,lr}  \n\t"
+		"ldmia"wide"	sp!, {r4,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop4(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r0,lr}  \n\t"
+		"ldmia"wide"	sp!, {r0,pc}"
+	);
+}
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static void __naked benchmark_pushpop_thumb(void)
+{
+	__asm__ __volatile__ (
+		"push.n	{r0-r7,lr}  \n\t"
+		"pop.n	{r0-r7,pc}"
+	);
+}
+
+#endif
+
+static int __kprobes
+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 0;
+}
+
+static int benchmark(void(*fn)(void))
+{
+	unsigned n, i, t, t0;
+
+	for (n = 1000; ; n *= 2) {
+		t0 = sched_clock();
+		for (i = n; i > 0; --i)
+			fn();
+		t = sched_clock() - t0;
+		if (t >= 250000000)
+			break; /* Stop once we took more than 0.25 seconds */
+	}
+	return t / n; /* Time for one iteration in nanoseconds */
+};
+
+static int kprobe_benchmark(void(*fn)(void), unsigned offset)
+{
+	struct kprobe k = {
+		.addr		= (kprobe_opcode_t *)((uintptr_t)fn + offset),
+		.pre_handler	= benchmark_pre_handler,
+	};
+
+	int ret = register_kprobe(&k);
+	if (ret < 0) {
+		pr_err("FAIL: register_kprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = benchmark(fn);
+
+	unregister_kprobe(&k);
+	return ret;
+};
+
+struct benchmarks {
+	void		(*fn)(void);
+	unsigned	offset;
+	const char	*title;
+};
+
+static int run_benchmarks(void)
+{
+	int ret;
+	struct benchmarks list[] = {
+		{&benchmark_nop, 0, "nop"},
+		/*
+		 * benchmark_pushpop{1,3} will have the optimised
+		 * instruction emulation, whilst benchmark_pushpop{2,4} will
+		 * be the equivalent unoptimised instructions.
+		 */
+		{&benchmark_pushpop1, 0, "stmdb	sp!, {r3-r11,lr}"},
+		{&benchmark_pushpop1, 4, "ldmia	sp!, {r3-r11,pc}"},
+		{&benchmark_pushpop2, 0, "stmdb	sp!, {r0-r8,lr}"},
+		{&benchmark_pushpop2, 4, "ldmia	sp!, {r0-r8,pc}"},
+		{&benchmark_pushpop3, 0, "stmdb	sp!, {r4,lr}"},
+		{&benchmark_pushpop3, 4, "ldmia	sp!, {r4,pc}"},
+		{&benchmark_pushpop4, 0, "stmdb	sp!, {r0,lr}"},
+		{&benchmark_pushpop4, 4, "ldmia	sp!, {r0,pc}"},
+#ifdef CONFIG_THUMB2_KERNEL
+		{&benchmark_pushpop_thumb, 0, "push.n	{r0-r7,lr}"},
+		{&benchmark_pushpop_thumb, 2, "pop.n	{r0-r7,pc}"},
+#endif
+		{0}
+	};
+
+	struct benchmarks *b;
+	for (b = list; b->fn; ++b) {
+		ret = kprobe_benchmark(b->fn, b->offset);
+		if (ret < 0)
+			return ret;
+		pr_info("    %dns for kprobe %s\n", ret, b->title);
+	}
+
+	pr_info("\n");
+	return 0;
+}
+
+#endif /* BENCHMARKING */
+
+
+/*
+ * Decoding table self-consistency tests
+ */
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+	[DECODE_TYPE_TABLE]	= sizeof(struct decode_table),
+	[DECODE_TYPE_CUSTOM]	= sizeof(struct decode_custom),
+	[DECODE_TYPE_SIMULATE]	= sizeof(struct decode_simulate),
+	[DECODE_TYPE_EMULATE]	= sizeof(struct decode_emulate),
+	[DECODE_TYPE_OR]	= sizeof(struct decode_or),
+	[DECODE_TYPE_REJECT]	= sizeof(struct decode_reject)
+};
+
+static int table_iter(const union decode_item *table,
+			int (*fn)(const struct decode_header *, void *),
+			void *args)
+{
+	const struct decode_header *h = (struct decode_header *)table;
+	int result;
+
+	for (;;) {
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+		if (type == DECODE_TYPE_END)
+			return 0;
+
+		result = fn(h, args);
+		if (result)
+			return result;
+
+		h = (struct decode_header *)
+			((uintptr_t)h + decode_struct_sizes[type]);
+
+	}
+}
+
+static int table_test_fail(const struct decode_header *h, const char* message)
+{
+
+	pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
+					message, h->mask.bits, h->value.bits);
+	return -EINVAL;
+}
+
+struct table_test_args {
+	const union decode_item *root_table;
+	u32			parent_mask;
+	u32			parent_value;
+};
+
+static int table_test_fn(const struct decode_header *h, void *args)
+{
+	struct table_test_args *a = (struct table_test_args *)args;
+	enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+	if (h->value.bits & ~h->mask.bits)
+		return table_test_fail(h, "Match value has bits not in mask");
+
+	if ((h->mask.bits & a->parent_mask) != a->parent_mask)
+		return table_test_fail(h, "Mask has bits not in parent mask");
+
+	if ((h->value.bits ^ a->parent_value) & a->parent_mask)
+		return table_test_fail(h, "Value is inconsistent with parent");
+
+	if (type == DECODE_TYPE_TABLE) {
+		struct decode_table *d = (struct decode_table *)h;
+		struct table_test_args args2 = *a;
+		args2.parent_mask = h->mask.bits;
+		args2.parent_value = h->value.bits;
+		return table_iter(d->table.table, table_test_fn, &args2);
+	}
+
+	return 0;
+}
+
+static int table_test(const union decode_item *table)
+{
+	struct table_test_args args = {
+		.root_table	= table,
+		.parent_mask	= 0,
+		.parent_value	= 0
+	};
+	return table_iter(args.root_table, table_test_fn, &args);
+}
+
+
+/*
+ * Decoding table test coverage analysis
+ *
+ * coverage_start() builds a coverage_table which contains a list of
+ * coverage_entry's to match each entry in the specified kprobes instruction
+ * decoding table.
+ *
+ * When test cases are run, coverage_add() is called to process each case.
+ * This looks up the corresponding entry in the coverage_table and sets it as
+ * being matched, as well as clearing the regs flag appropriate for the test.
+ *
+ * After all test cases have been run, coverage_end() is called to check that
+ * all entries in coverage_table have been matched and that all regs flags are
+ * cleared. I.e. that all possible combinations of instructions described by
+ * the kprobes decoding tables have had a test case executed for them.
+ */
+
+bool coverage_fail;
+
+#define MAX_COVERAGE_ENTRIES 256
+
+struct coverage_entry {
+	const struct decode_header	*header;
+	unsigned			regs;
+	unsigned			nesting;
+	char				matched;
+};
+
+struct coverage_table {
+	struct coverage_entry	*base;
+	unsigned		num_entries;
+	unsigned		nesting;
+};
+
+struct coverage_table coverage;
+
+#define COVERAGE_ANY_REG	(1<<0)
+#define COVERAGE_SP		(1<<1)
+#define COVERAGE_PC		(1<<2)
+#define COVERAGE_PCWB		(1<<3)
+
+static const char coverage_register_lookup[16] = {
+	[REG_TYPE_ANY]		= COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+	[REG_TYPE_SAMEAS16]	= COVERAGE_ANY_REG,
+	[REG_TYPE_SP]		= COVERAGE_SP,
+	[REG_TYPE_PC]		= COVERAGE_PC,
+	[REG_TYPE_NOSP]		= COVERAGE_ANY_REG | COVERAGE_SP,
+	[REG_TYPE_NOSPPC]	= COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+	[REG_TYPE_NOPC]		= COVERAGE_ANY_REG | COVERAGE_PC,
+	[REG_TYPE_NOPCWB]	= COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
+	[REG_TYPE_NOPCX]	= COVERAGE_ANY_REG,
+	[REG_TYPE_NOSPPCX]	= COVERAGE_ANY_REG | COVERAGE_SP,
+};
+
+unsigned coverage_start_registers(const struct decode_header *h)
+{
+	unsigned regs = 0;
+	int i;
+	for (i = 0; i < 20; i += 4) {
+		int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
+		regs |= coverage_register_lookup[r] << i;
+	}
+	return regs;
+}
+
+static int coverage_start_fn(const struct decode_header *h, void *args)
+{
+	struct coverage_table *coverage = (struct coverage_table *)args;
+	enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+	struct coverage_entry *entry = coverage->base + coverage->num_entries;
+
+	if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
+		pr_err("FAIL: Out of space for test coverage data");
+		return -ENOMEM;
+	}
+
+	++coverage->num_entries;
+
+	entry->header = h;
+	entry->regs = coverage_start_registers(h);
+	entry->nesting = coverage->nesting;
+	entry->matched = false;
+
+	if (type == DECODE_TYPE_TABLE) {
+		struct decode_table *d = (struct decode_table *)h;
+		int ret;
+		++coverage->nesting;
+		ret = table_iter(d->table.table, coverage_start_fn, coverage);
+		--coverage->nesting;
+		return ret;
+	}
+
+	return 0;
+}
+
+static int coverage_start(const union decode_item *table)
+{
+	coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
+				sizeof(struct coverage_entry), GFP_KERNEL);
+	coverage.num_entries = 0;
+	coverage.nesting = 0;
+	return table_iter(table, coverage_start_fn, &coverage);
+}
+
+static void
+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
+{
+	int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
+	int i;
+	for (i = 0; i < 20; i += 4) {
+		enum decode_reg_type reg_type = (regs >> i) & 0xf;
+		int reg = (insn >> i) & 0xf;
+		int flag;
+
+		if (!reg_type)
+			continue;
+
+		if (reg == 13)
+			flag = COVERAGE_SP;
+		else if (reg == 15)
+			flag = COVERAGE_PC;
+		else
+			flag = COVERAGE_ANY_REG;
+		entry->regs &= ~(flag << i);
+
+		switch (reg_type) {
+
+		case REG_TYPE_NONE:
+		case REG_TYPE_ANY:
+		case REG_TYPE_SAMEAS16:
+			break;
+
+		case REG_TYPE_SP:
+			if (reg != 13)
+				return;
+			break;
+
+		case REG_TYPE_PC:
+			if (reg != 15)
+				return;
+			break;
+
+		case REG_TYPE_NOSP:
+			if (reg == 13)
+				return;
+			break;
+
+		case REG_TYPE_NOSPPC:
+		case REG_TYPE_NOSPPCX:
+			if (reg == 13 || reg == 15)
+				return;
+			break;
+
+		case REG_TYPE_NOPCWB:
+			if (!is_writeback(insn))
+				break;
+			if (reg == 15) {
+				entry->regs &= ~(COVERAGE_PCWB << i);
+				return;
+			}
+			break;
+
+		case REG_TYPE_NOPC:
+		case REG_TYPE_NOPCX:
+			if (reg == 15)
+				return;
+			break;
+		}
+
+	}
+}
+
+static void coverage_add(kprobe_opcode_t insn)
+{
+	struct coverage_entry *entry = coverage.base;
+	struct coverage_entry *end = coverage.base + coverage.num_entries;
+	bool matched = false;
+	unsigned nesting = 0;
+
+	for (; entry < end; ++entry) {
+		const struct decode_header *h = entry->header;
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+		if (entry->nesting > nesting)
+			continue; /* Skip sub-table we didn't match */
+
+		if (entry->nesting < nesting)
+			break; /* End of sub-table we were scanning */
+
+		if (!matched) {
+			if ((insn & h->mask.bits) != h->value.bits)
+				continue;
+			entry->matched = true;
+		}
+
+		switch (type) {
+
+		case DECODE_TYPE_TABLE:
+			++nesting;
+			break;
+
+		case DECODE_TYPE_CUSTOM:
+		case DECODE_TYPE_SIMULATE:
+		case DECODE_TYPE_EMULATE:
+			coverage_add_registers(entry, insn);
+			return;
+
+		case DECODE_TYPE_OR:
+			matched = true;
+			break;
+
+		case DECODE_TYPE_REJECT:
+		default:
+			return;
+		}
+
+	}
+}
+
+static void coverage_end(void)
+{
+	struct coverage_entry *entry = coverage.base;
+	struct coverage_entry *end = coverage.base + coverage.num_entries;
+
+	for (; entry < end; ++entry) {
+		u32 mask = entry->header->mask.bits;
+		u32 value = entry->header->value.bits;
+
+		if (entry->regs) {
+			pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
+				mask, value, entry->regs);
+			coverage_fail = true;
+		}
+		if (!entry->matched) {
+			pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
+				mask, value);
+			coverage_fail = true;
+		}
+	}
+
+	kfree(coverage.base);
+}
+
+
+/*
+ * Framework for instruction set test cases
+ */
+
+void __naked __kprobes_test_case_start(void)
+{
+	__asm__ __volatile__ (
+		"stmdb	sp!, {r4-r11}				\n\t"
+		"sub	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"bic	r0, lr, #1  @ r0 = inline title string	\n\t"
+		"mov	r1, sp					\n\t"
+		"bl	kprobes_test_case_start			\n\t"
+		"bx	r0					\n\t"
+	);
+}
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+void __naked __kprobes_test_case_end_32(void)
+{
+	__asm__ __volatile__ (
+		"mov	r4, lr					\n\t"
+		"bl	kprobes_test_case_end			\n\t"
+		"cmp	r0, #0					\n\t"
+		"movne	pc, r0					\n\t"
+		"mov	r0, r4					\n\t"
+		"add	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"ldmia	sp!, {r4-r11}				\n\t"
+		"mov	pc, r0					\n\t"
+	);
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+void __naked __kprobes_test_case_end_16(void)
+{
+	__asm__ __volatile__ (
+		"mov	r4, lr					\n\t"
+		"bl	kprobes_test_case_end			\n\t"
+		"cmp	r0, #0					\n\t"
+		"bxne	r0					\n\t"
+		"mov	r0, r4					\n\t"
+		"add	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"ldmia	sp!, {r4-r11}				\n\t"
+		"bx	r0					\n\t"
+	);
+}
+
+void __naked __kprobes_test_case_end_32(void)
+{
+	__asm__ __volatile__ (
+		".arm						\n\t"
+		"orr	lr, lr, #1  @ will return to Thumb code	\n\t"
+		"ldr	pc, 1f					\n\t"
+		"1:						\n\t"
+		".word	__kprobes_test_case_end_16		\n\t"
+	);
+}
+
+#endif
+
+
+int kprobe_test_flags;
+int kprobe_test_cc_position;
+
+static int test_try_count;
+static int test_pass_count;
+static int test_fail_count;
+
+static struct pt_regs initial_regs;
+static struct pt_regs expected_regs;
+static struct pt_regs result_regs;
+
+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
+
+static const char *current_title;
+static struct test_arg *current_args;
+static u32 *current_stack;
+static uintptr_t current_branch_target;
+
+static uintptr_t current_code_start;
+static kprobe_opcode_t current_instruction;
+
+
+#define TEST_CASE_PASSED -1
+#define TEST_CASE_FAILED -2
+
+static int test_case_run_count;
+static bool test_case_is_thumb;
+static int test_instance;
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extentions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
+static unsigned long test_check_cc(int cc, unsigned long cpsr)
+{
+	unsigned long temp;
+
+	switch (cc) {
+	case 0x0: /* eq */
+		return cpsr & PSR_Z_BIT;
+
+	case 0x1: /* ne */
+		return (~cpsr) & PSR_Z_BIT;
+
+	case 0x2: /* cs */
+		return cpsr & PSR_C_BIT;
+
+	case 0x3: /* cc */
+		return (~cpsr) & PSR_C_BIT;
+
+	case 0x4: /* mi */
+		return cpsr & PSR_N_BIT;
+
+	case 0x5: /* pl */
+		return (~cpsr) & PSR_N_BIT;
+
+	case 0x6: /* vs */
+		return cpsr & PSR_V_BIT;
+
+	case 0x7: /* vc */
+		return (~cpsr) & PSR_V_BIT;
+
+	case 0x8: /* hi */
+		cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+		return cpsr & PSR_C_BIT;
+
+	case 0x9: /* ls */
+		cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+		return (~cpsr) & PSR_C_BIT;
+
+	case 0xa: /* ge */
+		cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		return (~cpsr) & PSR_N_BIT;
+
+	case 0xb: /* lt */
+		cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		return cpsr & PSR_N_BIT;
+
+	case 0xc: /* gt */
+		temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		temp |= (cpsr << 1);	   /* PSR_N_BIT |= PSR_Z_BIT */
+		return (~temp) & PSR_N_BIT;
+
+	case 0xd: /* le */
+		temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		temp |= (cpsr << 1);	   /* PSR_N_BIT |= PSR_Z_BIT */
+		return temp & PSR_N_BIT;
+
+	case 0xe: /* al */
+	case 0xf: /* unconditional */
+		return true;
+	}
+	BUG();
+	return false;
+}
+
+static int is_last_scenario;
+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
+static int memory_needs_checking;
+
+static unsigned long test_context_cpsr(int scenario)
+{
+	unsigned long cpsr;
+
+	probe_should_run = 1;
+
+	/* Default case is that we cycle through 16 combinations of flags */
+	cpsr  = (scenario & 0xf) << 28; /* N,Z,C,V flags */
+	cpsr |= (scenario & 0xf) << 16; /* GE flags */
+	cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
+
+	if (!test_case_is_thumb) {
+		/* Testing ARM code */
+		probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+		if (scenario == 15)
+			is_last_scenario = true;
+
+	} else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
+		/* Testing Thumb code without setting ITSTATE */
+		if (kprobe_test_cc_position) {
+			int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
+			probe_should_run = test_check_cc(cc, cpsr) != 0;
+		}
+
+		if (scenario == 15)
+			is_last_scenario = true;
+
+	} else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
+		/* Testing Thumb code with all combinations of ITSTATE */
+		unsigned x = (scenario >> 4);
+		unsigned cond_base = x % 7; /* ITSTATE<7:5> */
+		unsigned mask = x / 7 + 2;  /* ITSTATE<4:0>, bits reversed */
+
+		if (mask > 0x1f) {
+			/* Finish by testing state from instruction 'itt al' */
+			cond_base = 7;
+			mask = 0x4;
+			if ((scenario & 0xf) == 0xf)
+				is_last_scenario = true;
+		}
+
+		cpsr |= cond_base << 13;	/* ITSTATE<7:5> */
+		cpsr |= (mask & 0x1) << 12;	/* ITSTATE<4> */
+		cpsr |= (mask & 0x2) << 10;	/* ITSTATE<3> */
+		cpsr |= (mask & 0x4) << 8;	/* ITSTATE<2> */
+		cpsr |= (mask & 0x8) << 23;	/* ITSTATE<1> */
+		cpsr |= (mask & 0x10) << 21;	/* ITSTATE<0> */
+
+		probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
+
+	} else {
+		/* Testing Thumb code with several combinations of ITSTATE */
+		switch (scenario) {
+		case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
+			cpsr = 0x00000800;
+			probe_should_run = 0;
+			break;
+		case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
+			cpsr = 0xf0007800;
+			probe_should_run = 0;
+			break;
+		case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
+			cpsr = 0x00009800;
+			break;
+		case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
+			cpsr = 0xf0002800;
+			is_last_scenario = true;
+			break;
+		}
+	}
+
+	return cpsr;
+}
+
+static void setup_test_context(struct pt_regs *regs)
+{
+	int scenario = test_case_run_count>>1;
+	unsigned long val;
+	struct test_arg *args;
+	int i;
+
+	is_last_scenario = false;
+	memory_needs_checking = false;
+
+	/* Initialise test memory on stack */
+	val = (scenario & 1) ? VALM : ~VALM;
+	for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
+		current_stack[i] = val + (i << 8);
+	/* Put target of branch on stack for tests which load PC from memory */
+	if (current_branch_target)
+		current_stack[15] = current_branch_target;
+	/* Put a value for SP on stack for tests which load SP from memory */
+	current_stack[13] = (u32)current_stack + 120;
+
+	/* Initialise register values to their default state */
+	val = (scenario & 2) ? VALR : ~VALR;
+	for (i = 0; i < 13; ++i)
+		regs->uregs[i] = val ^ (i << 8);
+	regs->ARM_lr = val ^ (14 << 8);
+	regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
+	regs->ARM_cpsr |= test_context_cpsr(scenario);
+
+	/* Perform testcase specific register setup  */
+	args = current_args;
+	for (; args[0].type != ARG_TYPE_END; ++args)
+		switch (args[0].type) {
+		case ARG_TYPE_REG: {
+			struct test_arg_regptr *arg =
+				(struct test_arg_regptr *)args;
+			regs->uregs[arg->reg] = arg->val;
+			break;
+		}
+		case ARG_TYPE_PTR: {
+			struct test_arg_regptr *arg =
+				(struct test_arg_regptr *)args;
+			regs->uregs[arg->reg] =
+				(unsigned long)current_stack + arg->val;
+			memory_needs_checking = true;
+			break;
+		}
+		case ARG_TYPE_MEM: {
+			struct test_arg_mem *arg = (struct test_arg_mem *)args;
+			current_stack[arg->index] = arg->val;
+			break;
+		}
+		default:
+			break;
+		}
+}
+
+struct test_probe {
+	struct kprobe	kprobe;
+	bool		registered;
+	int		hit;
+};
+
+static void unregister_test_probe(struct test_probe *probe)
+{
+	if (probe->registered) {
+		unregister_kprobe(&probe->kprobe);
+		probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
+	}
+	probe->registered = false;
+}
+
+static int register_test_probe(struct test_probe *probe)
+{
+	int ret;
+
+	if (probe->registered)
+		BUG();
+
+	ret = register_kprobe(&probe->kprobe);
+	if (ret >= 0) {
+		probe->registered = true;
+		probe->hit = -1;
+	}
+	return ret;
+}
+
+static int __kprobes
+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static void __kprobes
+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
+							unsigned long flags)
+{
+	setup_test_context(regs);
+	initial_regs = *regs;
+	initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+}
+
+static int __kprobes
+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static int __kprobes
+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
+		return 0; /* Already run for this test instance */
+
+	result_regs = *regs;
+	result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+
+	/* Undo any changes done to SP by the test case */
+	regs->ARM_sp = (unsigned long)current_stack;
+
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static struct test_probe test_before_probe = {
+	.kprobe.pre_handler	= test_before_pre_handler,
+	.kprobe.post_handler	= test_before_post_handler,
+};
+
+static struct test_probe test_case_probe = {
+	.kprobe.pre_handler	= test_case_pre_handler,
+};
+
+static struct test_probe test_after_probe = {
+	.kprobe.pre_handler	= test_after_pre_handler,
+};
+
+static struct test_probe test_after2_probe = {
+	.kprobe.pre_handler	= test_after_pre_handler,
+};
+
+static void test_case_cleanup(void)
+{
+	unregister_test_probe(&test_before_probe);
+	unregister_test_probe(&test_case_probe);
+	unregister_test_probe(&test_after_probe);
+	unregister_test_probe(&test_after2_probe);
+}
+
+static void print_registers(struct pt_regs *regs)
+{
+	pr_err("r0  %08lx | r1  %08lx | r2  %08lx | r3  %08lx\n",
+		regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+	pr_err("r4  %08lx | r5  %08lx | r6  %08lx | r7  %08lx\n",
+		regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+	pr_err("r8  %08lx | r9  %08lx | r10 %08lx | r11 %08lx\n",
+		regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+	pr_err("r12 %08lx | sp  %08lx | lr  %08lx | pc  %08lx\n",
+		regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
+	pr_err("cpsr %08lx\n", regs->ARM_cpsr);
+}
+
+static void print_memory(u32 *mem, size_t size)
+{
+	int i;
+	for (i = 0; i < size / sizeof(u32); i += 4)
+		pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
+						mem[i+2], mem[i+3]);
+}
+
+static size_t expected_memory_size(u32 *sp)
+{
+	size_t size = sizeof(expected_memory);
+	int offset = (uintptr_t)sp - (uintptr_t)current_stack;
+	if (offset > 0)
+		size -= offset;
+	return size;
+}
+
+static void test_case_failed(const char *message)
+{
+	test_case_cleanup();
+
+	pr_err("FAIL: %s\n", message);
+	pr_err("FAIL: Test %s\n", current_title);
+	pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
+}
+
+static unsigned long next_instruction(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))
+		return pc + 2;
+	else
+#endif
+	return pc + 4;
+}
+
+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
+{
+	struct test_arg *args;
+	struct test_arg_end *end_arg;
+	unsigned long test_code;
+
+	args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
+
+	current_title = title;
+	current_args = args;
+	current_stack = stack;
+
+	++test_try_count;
+
+	while (args->type != ARG_TYPE_END)
+		++args;
+	end_arg = (struct test_arg_end *)args;
+
+	test_code = (unsigned long)(args + 1); /* Code starts after args */
+
+	test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
+	if (test_case_is_thumb)
+		test_code |= 1;
+
+	current_code_start = test_code;
+
+	current_branch_target = 0;
+	if (end_arg->branch_offset != end_arg->end_offset)
+		current_branch_target = test_code + end_arg->branch_offset;
+
+	test_code += end_arg->code_offset;
+	test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	test_code = next_instruction(test_code);
+	test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	if (test_case_is_thumb) {
+		u16 *p = (u16 *)(test_code & ~1);
+		current_instruction = p[0];
+		if (is_wide_instruction(current_instruction)) {
+			current_instruction <<= 16;
+			current_instruction |= p[1];
+		}
+	} else {
+		current_instruction = *(u32 *)test_code;
+	}
+
+	if (current_title[0] == '.')
+		verbose("%s\n", current_title);
+	else
+		verbose("%s\t@ %0*x\n", current_title,
+					test_case_is_thumb ? 4 : 8,
+					current_instruction);
+
+	test_code = next_instruction(test_code);
+	test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
+		if (!test_case_is_thumb ||
+			is_wide_instruction(current_instruction)) {
+				test_case_failed("expected 16-bit instruction");
+				goto fail;
+		}
+	} else {
+		if (test_case_is_thumb &&
+			!is_wide_instruction(current_instruction)) {
+				test_case_failed("expected 32-bit instruction");
+				goto fail;
+		}
+	}
+
+	coverage_add(current_instruction);
+
+	if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
+		if (register_test_probe(&test_case_probe) < 0)
+			goto pass;
+		test_case_failed("registered probe for unsupported instruction");
+		goto fail;
+	}
+
+	if (end_arg->flags & ARG_FLAG_SUPPORTED) {
+		if (register_test_probe(&test_case_probe) >= 0)
+			goto pass;
+		test_case_failed("couldn't register probe for supported instruction");
+		goto fail;
+	}
+
+	if (register_test_probe(&test_before_probe) < 0) {
+		test_case_failed("register test_before_probe failed");
+		goto fail;
+	}
+	if (register_test_probe(&test_after_probe) < 0) {
+		test_case_failed("register test_after_probe failed");
+		goto fail;
+	}
+	if (current_branch_target) {
+		test_after2_probe.kprobe.addr =
+				(kprobe_opcode_t *)current_branch_target;
+		if (register_test_probe(&test_after2_probe) < 0) {
+			test_case_failed("register test_after2_probe failed");
+			goto fail;
+		}
+	}
+
+	/* Start first run of test case */
+	test_case_run_count = 0;
+	++test_instance;
+	return current_code_start;
+pass:
+	test_case_run_count = TEST_CASE_PASSED;
+	return (uintptr_t)test_after_probe.kprobe.addr;
+fail:
+	test_case_run_count = TEST_CASE_FAILED;
+	return (uintptr_t)test_after_probe.kprobe.addr;
+}
+
+static bool check_test_results(void)
+{
+	size_t mem_size = 0;
+	u32 *mem = 0;
+
+	if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
+		test_case_failed("registers differ");
+		goto fail;
+	}
+
+	if (memory_needs_checking) {
+		mem = (u32 *)result_regs.ARM_sp;
+		mem_size = expected_memory_size(mem);
+		if (memcmp(expected_memory, mem, mem_size)) {
+			test_case_failed("test memory differs");
+			goto fail;
+		}
+	}
+
+	return true;
+
+fail:
+	pr_err("initial_regs:\n");
+	print_registers(&initial_regs);
+	pr_err("expected_regs:\n");
+	print_registers(&expected_regs);
+	pr_err("result_regs:\n");
+	print_registers(&result_regs);
+
+	if (mem) {
+		pr_err("current_stack=%p\n", current_stack);
+		pr_err("expected_memory:\n");
+		print_memory(expected_memory, mem_size);
+		pr_err("result_memory:\n");
+		print_memory(mem, mem_size);
+	}
+
+	return false;
+}
+
+static uintptr_t __used kprobes_test_case_end(void)
+{
+	if (test_case_run_count < 0) {
+		if (test_case_run_count == TEST_CASE_PASSED)
+			/* kprobes_test_case_start did all the needed testing */
+			goto pass;
+		else
+			/* kprobes_test_case_start failed */
+			goto fail;
+	}
+
+	if (test_before_probe.hit != test_instance) {
+		test_case_failed("test_before_handler not run");
+		goto fail;
+	}
+
+	if (test_after_probe.hit != test_instance &&
+				test_after2_probe.hit != test_instance) {
+		test_case_failed("test_after_handler not run");
+		goto fail;
+	}
+
+	/*
+	 * Even numbered test runs ran without a probe on the test case so
+	 * we can gather reference results. The subsequent odd numbered run
+	 * will have the probe inserted.
+	*/
+	if ((test_case_run_count & 1) == 0) {
+		/* Save results from run without probe */
+		u32 *mem = (u32 *)result_regs.ARM_sp;
+		expected_regs = result_regs;
+		memcpy(expected_memory, mem, expected_memory_size(mem));
+
+		/* Insert probe onto test case instruction */
+		if (register_test_probe(&test_case_probe) < 0) {
+			test_case_failed("register test_case_probe failed");
+			goto fail;
+		}
+	} else {
+		/* Check probe ran as expected */
+		if (probe_should_run == 1) {
+			if (test_case_probe.hit != test_instance) {
+				test_case_failed("test_case_handler not run");
+				goto fail;
+			}
+		} else if (probe_should_run == 0) {
+			if (test_case_probe.hit == test_instance) {
+				test_case_failed("test_case_handler ran");
+				goto fail;
+			}
+		}
+
+		/* Remove probe for any subsequent reference run */
+		unregister_test_probe(&test_case_probe);
+
+		if (!check_test_results())
+			goto fail;
+
+		if (is_last_scenario)
+			goto pass;
+	}
+
+	/* Do next test run */
+	++test_case_run_count;
+	++test_instance;
+	return current_code_start;
+fail:
+	++test_fail_count;
+	goto end;
+pass:
+	++test_pass_count;
+end:
+	test_case_cleanup();
+	return 0;
+}
+
+
+/*
+ * Top level test functions
+ */
+
+static int run_test_cases(void (*tests)(void), const union decode_item *table)
+{
+	int ret;
+
+	pr_info("    Check decoding tables\n");
+	ret = table_test(table);
+	if (ret)
+		return ret;
+
+	pr_info("    Run test cases\n");
+	ret = coverage_start(table);
+	if (ret)
+		return ret;
+
+	tests();
+
+	coverage_end();
+	return 0;
+}
+
+
+static int __init run_all_tests(void)
+{
+	int ret = 0;
+
+	pr_info("Begining kprobe tests...\n");
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+	pr_info("Probe ARM code\n");
+	ret = run_api_tests(arm_func);
+	if (ret)
+		goto out;
+
+	pr_info("ARM instruction simulation\n");
+	ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+	if (ret)
+		goto out;
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+	pr_info("Probe 16-bit Thumb code\n");
+	ret = run_api_tests(thumb16_func);
+	if (ret)
+		goto out;
+
+	pr_info("Probe 32-bit Thumb code, even halfword\n");
+	ret = run_api_tests(thumb32even_func);
+	if (ret)
+		goto out;
+
+	pr_info("Probe 32-bit Thumb code, odd halfword\n");
+	ret = run_api_tests(thumb32odd_func);
+	if (ret)
+		goto out;
+
+	pr_info("16-bit Thumb instruction simulation\n");
+	ret = run_test_cases(kprobe_thumb16_test_cases,
+				kprobe_decode_thumb16_table);
+	if (ret)
+		goto out;
+
+	pr_info("32-bit Thumb instruction simulation\n");
+	ret = run_test_cases(kprobe_thumb32_test_cases,
+				kprobe_decode_thumb32_table);
+	if (ret)
+		goto out;
+#endif
+
+	pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
+		test_try_count, test_pass_count, test_fail_count);
+	if (test_fail_count) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+#if BENCHMARKING
+	pr_info("Benchmarks\n");
+	ret = run_benchmarks();
+	if (ret)
+		goto out;
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	/* We are able to run all test cases so coverage should be complete */
+	if (coverage_fail) {
+		pr_err("FAIL: Test coverage checks failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+#endif
+
+out:
+	if (ret == 0)
+		pr_info("Finished kprobe tests OK\n");
+	else
+		pr_err("kprobe tests failed\n");
+
+	return ret;
+}
+
+
+/*
+ * Module setup
+ */
+
+#ifdef MODULE
+
+static void __exit kprobe_test_exit(void)
+{
+}
+
+module_init(run_all_tests)
+module_exit(kprobe_test_exit)
+MODULE_LICENSE("GPL");
+
+#else /* !MODULE */
+
+late_initcall(run_all_tests);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test.h linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test.h
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,432 @@
+/*
+ * arch/arm/kernel/kprobes-test.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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.
+ */
+
+#define VERBOSE 0 /* Set to '1' for more logging of test cases */
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define NORMAL_ISA "16"
+#else
+#define NORMAL_ISA "32"
+#endif
+
+
+/* Flags used in kprobe_test_flags */
+#define TEST_FLAG_NO_ITBLOCK	(1<<0)
+#define TEST_FLAG_FULL_ITBLOCK	(1<<1)
+#define TEST_FLAG_NARROW_INSTR	(1<<2)
+
+extern int kprobe_test_flags;
+extern int kprobe_test_cc_position;
+
+
+#define TEST_MEMORY_SIZE 256
+
+
+/*
+ * Test case structures.
+ *
+ * The arguments given to test cases can be one of three types.
+ *
+ *   ARG_TYPE_REG
+ *	Load a register with the given value.
+ *
+ *   ARG_TYPE_PTR
+ *	Load a register with a pointer into the stack buffer (SP + given value).
+ *
+ *   ARG_TYPE_MEM
+ *	Store the given value into the stack buffer at [SP+index].
+ *
+ */
+
+#define	ARG_TYPE_END	0
+#define	ARG_TYPE_REG	1
+#define	ARG_TYPE_PTR	2
+#define	ARG_TYPE_MEM	3
+
+#define ARG_FLAG_UNSUPPORTED	0x01
+#define ARG_FLAG_SUPPORTED	0x02
+#define ARG_FLAG_THUMB		0x10	/* Must be 16 so TEST_ISA can be used */
+#define ARG_FLAG_ARM		0x20	/* Must be 32 so TEST_ISA can be used */
+
+struct test_arg {
+	u8	type;		/* ARG_TYPE_x */
+	u8	_padding[7];
+};
+
+struct test_arg_regptr {
+	u8	type;		/* ARG_TYPE_REG or ARG_TYPE_PTR */
+	u8	reg;
+	u8	_padding[2];
+	u32	val;
+};
+
+struct test_arg_mem {
+	u8	type;		/* ARG_TYPE_MEM */
+	u8	index;
+	u8	_padding[2];
+	u32	val;
+};
+
+struct test_arg_end {
+	u8	type;		/* ARG_TYPE_END */
+	u8	flags;		/* ARG_FLAG_x */
+	u16	code_offset;
+	u16	branch_offset;
+	u16	end_offset;
+};
+
+
+/*
+ * Building blocks for test cases.
+ *
+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
+ *
+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
+ * used followed by a terminating TEST_ARG_END.
+ *
+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
+ *
+ * Some specific test cases may make use of other custom constructs.
+ */
+
+#if VERBOSE
+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
+#else
+#define verbose(fmt, ...)
+#endif
+
+#define TEST_GROUP(title)					\
+	verbose("\n");						\
+	verbose(title"\n");					\
+	verbose("---------------------------------------------------------\n");
+
+#define TESTCASE_START(title)					\
+	__asm__ __volatile__ (					\
+	"bl	__kprobes_test_case_start		\n\t"	\
+	/* don't use .asciz here as 'title' may be */		\
+	/* multiple strings to be concatenated.  */		\
+	".ascii "#title"				\n\t"	\
+	".byte	0					\n\t"	\
+	".align	2					\n\t"
+
+#define	TEST_ARG_REG(reg, val)					\
+	".byte	"__stringify(ARG_TYPE_REG)"		\n\t"	\
+	".byte	"#reg"					\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_PTR(reg, val)					\
+	".byte	"__stringify(ARG_TYPE_PTR)"		\n\t"	\
+	".byte	"#reg"					\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_MEM(index, val)				\
+	".byte	"__stringify(ARG_TYPE_MEM)"		\n\t"	\
+	".byte	"#index"				\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_END(flags)					\
+	".byte	"__stringify(ARG_TYPE_END)"		\n\t"	\
+	".byte	"TEST_ISA flags"			\n\t"	\
+	".short	50f-0f					\n\t"	\
+	".short	2f-0f					\n\t"	\
+	".short	99f-0f					\n\t"	\
+	".code "TEST_ISA"				\n\t"	\
+	"0:						\n\t"
+
+#define TEST_INSTRUCTION(instruction)				\
+	"50:	nop					\n\t"	\
+	"1:	"instruction"				\n\t"	\
+	"	nop					\n\t"
+
+#define TEST_BRANCH_F(instruction)				\
+	TEST_INSTRUCTION(instruction)				\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"
+
+#define TEST_BRANCH_B(instruction)				\
+	"	b	50f				\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"	\
+	"	b	99f				\n\t"	\
+	TEST_INSTRUCTION(instruction)
+
+#define TEST_BRANCH_FX(instruction, codex)			\
+	TEST_INSTRUCTION(instruction)				\
+	"	b	99f				\n\t"	\
+	codex"						\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"
+
+#define TEST_BRANCH_BX(instruction, codex)			\
+	"	b	50f				\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"	\
+	"	b	99f				\n\t"	\
+	codex"						\n\t"	\
+	TEST_INSTRUCTION(instruction)
+
+#define TESTCASE_END						\
+	"2:						\n\t"	\
+	"99:						\n\t"	\
+	"	bl __kprobes_test_case_end_"TEST_ISA"	\n\t"	\
+	".code "NORMAL_ISA"				\n\t"	\
+	: :							\
+	: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"	\
+	);
+
+
+/*
+ * Macros to define test cases.
+ *
+ * Those of the form TEST_{R,P,M}* can be used to define test cases
+ * which take combinations of the three basic types of arguments. E.g.
+ *
+ *   TEST_R	One register argument
+ *   TEST_RR	Two register arguments
+ *   TEST_RPR	A register, a pointer, then a register argument
+ *
+ * For testing instructions which may branch, there are macros TEST_BF_*
+ * and TEST_BB_* for branching forwards and backwards.
+ *
+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
+ * the just verify that a kprobe is or is not allowed on the given instruction.
+ */
+
+#define TEST(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code)			\
+	TESTCASE_END
+
+#define TEST_UNSUPPORTED(code)					\
+	TESTCASE_START(code)					\
+	TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED))	\
+	TEST_INSTRUCTION(code)					\
+	TESTCASE_END
+
+#define TEST_SUPPORTED(code)					\
+	TESTCASE_START(code)					\
+	TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED))	\
+	TEST_INSTRUCTION(code)					\
+	TESTCASE_END
+
+#define TEST_R(code1, reg, val, code2)			\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_INSTRUCTION(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_REG(reg4, val4)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)	\
+	TESTCASE_END
+
+#define TEST_P(code1, reg1, val1, code2)	\
+	TESTCASE_START(code1 #reg1 code2)	\
+	TEST_ARG_PTR(reg1, val1)		\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code1 #reg1 code2)	\
+	TESTCASE_END
+
+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_PTR(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_PTR(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_PTR(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_PTR(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_PTR(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_BF_P(code1, reg1, val1, code2)	\
+	TESTCASE_START(code1 #reg1 code2)	\
+	TEST_ARG_PTR(reg1, val1)		\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code1 #reg1 code2)	\
+	TESTCASE_END
+
+#define TEST_BF(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code)			\
+	TESTCASE_END
+
+#define TEST_BB(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_B(code)			\
+	TESTCASE_END
+
+#define TEST_BF_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)	\
+	TEST_ARG_REG(reg, val)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_BB_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)	\
+	TEST_ARG_REG(reg, val)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_B(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_BF_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_FX(code, codex)		\
+	TESTCASE_END
+
+#define TEST_BB_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_BX(code, codex)		\
+	TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, codex)	\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_BRANCH_FX(code1 #reg code2, codex)		\
+	TESTCASE_END
+
+#define TEST_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code)			\
+	"	b	99f		\n\t"	\
+	"	"codex"			\n\t"	\
+	TESTCASE_END
+
+#define TEST_RX(code1, reg, val, code2, codex)		\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_INSTRUCTION(code1 __stringify(reg) code2)	\
+	"	b	99f		\n\t"		\
+	"	"codex"			\n\t"		\
+	TESTCASE_END
+
+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex)		\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)				\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3)	\
+	"	b	99f		\n\t"					\
+	"	"codex"			\n\t"					\
+	TESTCASE_END
+
+
+/*
+ * Macros for defining space directives spread over multiple lines.
+ * These are required so the compiler guesses better the length of inline asm
+ * code and will spill the literal pool early enough to avoid generating PC
+ * relative loads with out of range offsets.
+ */
+#define TWICE(x)	x x
+#define SPACE_0x8	TWICE(".space 4\n\t")
+#define SPACE_0x10	TWICE(SPACE_0x8)
+#define SPACE_0x20	TWICE(SPACE_0x10)
+#define SPACE_0x40	TWICE(SPACE_0x20)
+#define SPACE_0x80	TWICE(SPACE_0x40)
+#define SPACE_0x100	TWICE(SPACE_0x80)
+#define SPACE_0x200	TWICE(SPACE_0x100)
+#define SPACE_0x400	TWICE(SPACE_0x200)
+#define SPACE_0x800	TWICE(SPACE_0x400)
+#define SPACE_0x1000	TWICE(SPACE_0x800)
+
+
+/* Various values used in test cases... */
+#define N(val)	(val ^ 0xffffffff)
+#define VAL1	0x12345678
+#define VAL2	N(VAL1)
+#define VAL3	0xa5f801
+#define VAL4	N(VAL3)
+#define VALM	0x456789ab
+#define VALR	0xdeaddead
+#define HH1	0x0123fecb
+#define HH2	0xa9874567
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+void kprobe_thumb16_test_cases(void);
+void kprobe_thumb32_test_cases(void);
+#else
+void kprobe_arm_test_cases(void);
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test-thumb.c linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test-thumb.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-test-thumb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-test-thumb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/kernel/kprobes-test-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "16"
+
+#define DONT_TEST_IN_ITBLOCK(tests)			\
+	kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK;	\
+	tests						\
+	kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
+
+#define CONDITION_INSTRUCTIONS(cc_pos, tests)		\
+	kprobe_test_cc_position = cc_pos;		\
+	DONT_TEST_IN_ITBLOCK(tests)			\
+	kprobe_test_cc_position = 0;
+
+#define TEST_ITBLOCK(code)				\
+	kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK;	\
+	TESTCASE_START(code)				\
+	TEST_ARG_END("")				\
+	"50:	nop			\n\t"		\
+	"1:	"code"			\n\t"		\
+	"	mov r1, #0x11		\n\t"		\
+	"	mov r2, #0x22		\n\t"		\
+	"	mov r3, #0x33		\n\t"		\
+	"2:	nop			\n\t"		\
+	TESTCASE_END					\
+	kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
+
+#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_PTR(reg, val)					\
+	TEST_ARG_REG(14, 99f+1)					\
+	TEST_ARG_MEM(15, 3f)					\
+	TEST_ARG_END("")					\
+	"	nop			\n\t" /* To align 1f */	\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"3:	adr	lr, 2f+1	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+
+void kprobe_thumb16_test_cases(void)
+{
+	kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
+
+	TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
+
+	TEST_R(    "lsls	r7, r",0,VAL1,", #5")
+	TEST_R(    "lsls	r0, r",7,VAL2,", #11")
+	TEST_R(    "lsrs	r7, r",0,VAL1,", #5")
+	TEST_R(    "lsrs	r0, r",7,VAL2,", #11")
+	TEST_R(    "asrs	r7, r",0,VAL1,", #5")
+	TEST_R(    "asrs	r0, r",7,VAL2,", #11")
+	TEST_RR(   "adds	r2, r",0,VAL1,", r",7,VAL2,"")
+	TEST_RR(   "adds	r5, r",7,VAL2,", r",0,VAL2,"")
+	TEST_RR(   "subs	r2, r",0,VAL1,", r",7,VAL2,"")
+	TEST_RR(   "subs	r5, r",7,VAL2,", r",0,VAL2,"")
+	TEST_R(    "adds	r7, r",0,VAL1,", #5")
+	TEST_R(    "adds	r0, r",7,VAL2,", #2")
+	TEST_R(    "subs	r7, r",0,VAL1,", #5")
+	TEST_R(    "subs	r0, r",7,VAL2,", #2")
+	TEST(      "movs.n	r0, #0x5f")
+	TEST(      "movs.n	r7, #0xa0")
+	TEST_R(    "cmp.n	r",0,0x5e, ", #0x5f")
+	TEST_R(    "cmp.n	r",5,0x15f,", #0x5f")
+	TEST_R(    "cmp.n	r",7,0xa0, ", #0xa0")
+	TEST_R(    "adds.n	r",0,VAL1,", #0x5f")
+	TEST_R(    "adds.n	r",7,VAL2,", #0xa0")
+	TEST_R(    "subs.n	r",0,VAL1,", #0x5f")
+	TEST_R(    "subs.n	r",7,VAL2,", #0xa0")
+
+	TEST_GROUP("16-bit Thumb data-processing instructions")
+
+#define DATA_PROCESSING16(op,val)			\
+	TEST_RR(   op"	r",0,VAL1,", r",7,val,"")	\
+	TEST_RR(   op"	r",7,VAL2,", r",0,val,"")
+
+	DATA_PROCESSING16("ands",0xf00f00ff)
+	DATA_PROCESSING16("eors",0xf00f00ff)
+	DATA_PROCESSING16("lsls",11)
+	DATA_PROCESSING16("lsrs",11)
+	DATA_PROCESSING16("asrs",11)
+	DATA_PROCESSING16("adcs",VAL2)
+	DATA_PROCESSING16("sbcs",VAL2)
+	DATA_PROCESSING16("rors",11)
+	DATA_PROCESSING16("tst",0xf00f00ff)
+	TEST_R("rsbs	r",0,VAL1,", #0")
+	TEST_R("rsbs	r",7,VAL2,", #0")
+	DATA_PROCESSING16("cmp",0xf00f00ff)
+	DATA_PROCESSING16("cmn",0xf00f00ff)
+	DATA_PROCESSING16("orrs",0xf00f00ff)
+	DATA_PROCESSING16("muls",VAL2)
+	DATA_PROCESSING16("bics",0xf00f00ff)
+	DATA_PROCESSING16("mvns",VAL2)
+
+	TEST_GROUP("Special data instructions and branch and exchange")
+
+	TEST_RR(  "add	r",0, VAL1,", r",7,VAL2,"")
+	TEST_RR(  "add	r",3, VAL2,", r",8,VAL3,"")
+	TEST_RR(  "add	r",8, VAL3,", r",0,VAL1,"")
+	TEST_R(   "add	sp"        ", r",8,-8,  "")
+	TEST_R(   "add	r",14,VAL1,", pc")
+	TEST_BF_R("add	pc"        ", r",0,2f-1f-8,"")
+	TEST_UNSUPPORTED(".short 0x44ff	@ add pc, pc")
+
+	TEST_RR(  "cmp	r",3,VAL1,", r",8,VAL2,"")
+	TEST_RR(  "cmp	r",8,VAL2,", r",0,VAL1,"")
+	TEST_R(   "cmp	sp"       ", r",8,-8,  "")
+
+	TEST_R(   "mov	r0, r",7,VAL2,"")
+	TEST_R(   "mov	r3, r",8,VAL3,"")
+	TEST_R(   "mov	r8, r",0,VAL1,"")
+	TEST_P(   "mov	sp, r",8,-8,  "")
+	TEST(     "mov	lr, pc")
+	TEST_BF_R("mov	pc, r",0,2f,  "")
+
+	TEST_BF_R("bx	r",0, 2f+1,"")
+	TEST_BF_R("bx	r",14,2f+1,"")
+	TESTCASE_START("bx	pc")
+		TEST_ARG_REG(14, 99f+1)
+		TEST_ARG_END("")
+		"	nop			\n\t" /* To align the bx pc*/
+		"50:	nop			\n\t"
+		"1:	bx	pc		\n\t"
+		"	bx	lr		\n\t"
+		".arm				\n\t"
+		"	adr	lr, 2f+1	\n\t"
+		"	bx	lr		\n\t"
+		".thumb				\n\t"
+		"2:	nop			\n\t"
+	TESTCASE_END
+
+	TEST_BF_R("blx	r",0, 2f+1,"")
+	TEST_BB_R("blx	r",14,2f+1,"")
+	TEST_UNSUPPORTED(".short 0x47f8	@ blx pc")
+
+	TEST_GROUP("Load from Literal Pool")
+
+	TEST_X( "ldr	r0, 3f",
+		".align					\n\t"
+		"3:	.word	"__stringify(VAL1))
+	TEST_X( "ldr	r7, 3f",
+		".space 128				\n\t"
+		".align					\n\t"
+		"3:	.word	"__stringify(VAL2))
+
+	TEST_GROUP("16-bit Thumb Load/store instructions")
+
+	TEST_RPR("str	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("str	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_RPR("strh	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("strh	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_RPR("strb	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("strb	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_PR( "ldrsb	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrsb	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldr	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldr	r7, [r",6, 24,", r",5,  48,"]")
+	TEST_PR( "ldrh	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrh	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldrb	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrb	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldrsh	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrsh	r7, [r",6, 24,", r",5,  50,"]")
+
+	TEST_RP("str	r",0, VAL1,", [r",1, 24,", #120]")
+	TEST_RP("str	r",7, VAL2,", [r",6, 24,", #120]")
+	TEST_P( "ldr	r0, [r",1, 24,", #120]")
+	TEST_P( "ldr	r7, [r",6, 24,", #120]")
+	TEST_RP("strb	r",0, VAL1,", [r",1, 24,", #30]")
+	TEST_RP("strb	r",7, VAL2,", [r",6, 24,", #30]")
+	TEST_P( "ldrb	r0, [r",1, 24,", #30]")
+	TEST_P( "ldrb	r7, [r",6, 24,", #30]")
+	TEST_RP("strh	r",0, VAL1,", [r",1, 24,", #60]")
+	TEST_RP("strh	r",7, VAL2,", [r",6, 24,", #60]")
+	TEST_P( "ldrh	r0, [r",1, 24,", #60]")
+	TEST_P( "ldrh	r7, [r",6, 24,", #60]")
+
+	TEST_R( "str	r",0, VAL1,", [sp, #0]")
+	TEST_R( "str	r",7, VAL2,", [sp, #160]")
+	TEST(   "ldr	r0, [sp, #0]")
+	TEST(   "ldr	r7, [sp, #160]")
+
+	TEST_RP("str	r",0, VAL1,", [r",0, 24,"]")
+	TEST_P( "ldr	r0, [r",0, 24,"]")
+
+	TEST_GROUP("Generate PC-/SP-relative address")
+
+	TEST("add	r0, pc, #4")
+	TEST("add	r7, pc, #1020")
+	TEST("add	r0, sp, #4")
+	TEST("add	r7, sp, #1020")
+
+	TEST_GROUP("Miscellaneous 16-bit instructions")
+
+	TEST_UNSUPPORTED( "cpsie	i")
+	TEST_UNSUPPORTED( "cpsid	i")
+	TEST_UNSUPPORTED( "setend	le")
+	TEST_UNSUPPORTED( "setend	be")
+
+	TEST("add	sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
+	TEST("sub	sp, #0x7f*4")
+
+DONT_TEST_IN_ITBLOCK(
+	TEST_BF_R(  "cbnz	r",0,0, ", 2f")
+	TEST_BF_R(  "cbz	r",2,-1,", 2f")
+	TEST_BF_RX( "cbnz	r",4,1, ", 2f", SPACE_0x20)
+	TEST_BF_RX( "cbz	r",7,0, ", 2f", SPACE_0x40)
+)
+	TEST_R("sxth	r0, r",7, HH1,"")
+	TEST_R("sxth	r7, r",0, HH2,"")
+	TEST_R("sxtb	r0, r",7, HH1,"")
+	TEST_R("sxtb	r7, r",0, HH2,"")
+	TEST_R("uxth	r0, r",7, HH1,"")
+	TEST_R("uxth	r7, r",0, HH2,"")
+	TEST_R("uxtb	r0, r",7, HH1,"")
+	TEST_R("uxtb	r7, r",0, HH2,"")
+	TEST_R("rev	r0, r",7, VAL1,"")
+	TEST_R("rev	r7, r",0, VAL2,"")
+	TEST_R("rev16	r0, r",7, VAL1,"")
+	TEST_R("rev16	r7, r",0, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xba80")
+	TEST_UNSUPPORTED(".short 0xbabf")
+	TEST_R("revsh	r0, r",7, VAL1,"")
+	TEST_R("revsh	r7, r",0, VAL2,"")
+
+#define TEST_POPPC(code, offset)	\
+	TESTCASE_START(code)		\
+	TEST_ARG_PTR(13, offset)	\
+	TEST_ARG_END("")		\
+	TEST_BRANCH_F(code)		\
+	TESTCASE_END
+
+	TEST("push	{r0}")
+	TEST("push	{r7}")
+	TEST("push	{r14}")
+	TEST("push	{r0-r7,r14}")
+	TEST("push	{r0,r2,r4,r6,r14}")
+	TEST("push	{r1,r3,r5,r7}")
+	TEST("pop	{r0}")
+	TEST("pop	{r7}")
+	TEST("pop	{r0,r2,r4,r6}")
+	TEST_POPPC("pop	{pc}",15*4)
+	TEST_POPPC("pop	{r0-r7,pc}",7*4)
+	TEST_POPPC("pop	{r1,r3,r5,r7,pc}",11*4)
+	TEST_THUMB_TO_ARM_INTERWORK_P("pop	{pc}	@ ",13,15*4,"")
+	TEST_THUMB_TO_ARM_INTERWORK_P("pop	{r0-r7,pc}	@ ",13,7*4,"")
+
+	TEST_UNSUPPORTED("bkpt.n	0")
+	TEST_UNSUPPORTED("bkpt.n	255")
+
+	TEST_SUPPORTED("yield")
+	TEST("sev")
+	TEST("nop")
+	TEST("wfi")
+	TEST_SUPPORTED("wfe")
+	TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */
+	TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */
+
+#define TEST_IT(code, code2)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	"50:	nop			\n\t"	\
+	"1:	"code"			\n\t"	\
+	"	"code2"			\n\t"	\
+	"2:	nop			\n\t"	\
+	TESTCASE_END
+
+DONT_TEST_IN_ITBLOCK(
+	TEST_IT("it	eq","moveq r0,#0")
+	TEST_IT("it	vc","movvc r0,#0")
+	TEST_IT("it	le","movle r0,#0")
+	TEST_IT("ite	eq","moveq r0,#0\n\t  movne r1,#1")
+	TEST_IT("itet	vc","movvc r0,#0\n\t  movvs r1,#1\n\t  movvc r2,#2")
+	TEST_IT("itete	le","movle r0,#0\n\t  movgt r1,#1\n\t  movle r2,#2\n\t  movgt r3,#3")
+	TEST_IT("itttt	le","movle r0,#0\n\t  movle r1,#1\n\t  movle r2,#2\n\t  movle r3,#3")
+	TEST_IT("iteee	le","movle r0,#0\n\t  movgt r1,#1\n\t  movgt r2,#2\n\t  movgt r3,#3")
+)
+
+	TEST_GROUP("Load and store multiple")
+
+	TEST_P("ldmia	r",4, 16*4,"!, {r0,r7}")
+	TEST_P("ldmia	r",7, 16*4,"!, {r0-r6}")
+	TEST_P("stmia	r",4, 16*4,"!, {r0,r7}")
+	TEST_P("stmia	r",0, 16*4,"!, {r0-r7}")
+
+	TEST_GROUP("Conditional branch and Supervisor Call instructions")
+
+CONDITION_INSTRUCTIONS(8,
+	TEST_BF("beq	2f")
+	TEST_BB("bne	2b")
+	TEST_BF("bgt	2f")
+	TEST_BB("blt	2b")
+)
+	TEST_UNSUPPORTED(".short 0xde00")
+	TEST_UNSUPPORTED(".short 0xdeff")
+	TEST_UNSUPPORTED("svc	#0x00")
+	TEST_UNSUPPORTED("svc	#0xff")
+
+	TEST_GROUP("Unconditional branch")
+
+	TEST_BF(  "b	2f")
+	TEST_BB(  "b	2b")
+	TEST_BF_X("b	2f", SPACE_0x400)
+	TEST_BB_X("b	2b", SPACE_0x400)
+
+	TEST_GROUP("Testing instructions in IT blocks")
+
+	TEST_ITBLOCK("subs.n r0, r0")
+
+	verbose("\n");
+}
+
+
+void kprobe_thumb32_test_cases(void)
+{
+	kprobe_test_flags = 0;
+
+	TEST_GROUP("Load/store multiple")
+
+	TEST_UNSUPPORTED("rfedb	sp")
+	TEST_UNSUPPORTED("rfeia	sp")
+	TEST_UNSUPPORTED("rfedb	sp!")
+	TEST_UNSUPPORTED("rfeia	sp!")
+
+	TEST_P(   "stmia	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "stmia	r",4, 16*4,", {r0-r12,r14}")
+	TEST_P(   "stmia	r",7, 16*4,"!, {r8-r12,r14}")
+	TEST_P(   "stmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+	TEST_P(   "ldmia	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "ldmia	r",4, 0,   ", {r0-r12,r14}")
+	TEST_BF_P("ldmia	r",5, 8*4, "!, {r6-r12,r15}")
+	TEST_P(   "ldmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmia	r",14,14*4,"!, {r4,pc}")
+
+	TEST_P(   "stmdb	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "stmdb	r",4, 16*4,", {r0-r12,r14}")
+	TEST_P(   "stmdb	r",5, 16*4,"!, {r8-r12,r14}")
+	TEST_P(   "stmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+	TEST_P(   "ldmdb	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "ldmdb	r",4, 16*4,", {r0-r12,r14}")
+	TEST_BF_P("ldmdb	r",5, 16*4,"!, {r6-r12,r15}")
+	TEST_P(   "ldmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmdb	r",14,16*4,"!, {r4,pc}")
+
+	TEST_P(   "stmdb	r",13,16*4,"!, {r3-r12,lr}")
+	TEST_P(	  "stmdb	r",13,16*4,"!, {r3-r12}")
+	TEST_P(   "stmdb	r",2, 16*4,", {r3-r12,lr}")
+	TEST_P(   "stmdb	r",13,16*4,"!, {r2-r12,lr}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_BF_P("ldmia	r",13,5*4, "!, {r3-r12,pc}")
+	TEST_P(	  "ldmia	r",13,5*4, "!, {r3-r12}")
+	TEST_BF_P("ldmia	r",2, 5*4, "!, {r3-r12,pc}")
+	TEST_BF_P("ldmia	r",13,4*4, "!, {r2-r12,pc}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldmia	r",0,14*4,", {r12,pc}")
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldmia	r",13,2*4,", {r0-r12,pc}")
+
+	TEST_UNSUPPORTED(".short 0xe88f,0x0101	@ stmia	pc, {r0,r8}")
+	TEST_UNSUPPORTED(".short 0xe92f,0x5f00	@ stmdb	pc!, {r8-r12,r14}")
+	TEST_UNSUPPORTED(".short 0xe8bd,0xc000	@ ldmia	r13!, {r14,pc}")
+	TEST_UNSUPPORTED(".short 0xe93e,0xc000	@ ldmdb	r14!, {r14,pc}")
+	TEST_UNSUPPORTED(".short 0xe8a7,0x3f00	@ stmia	r7!, {r8-r12,sp}")
+	TEST_UNSUPPORTED(".short 0xe8a7,0x9f00	@ stmia	r7!, {r8-r12,pc}")
+	TEST_UNSUPPORTED(".short 0xe93e,0x2010	@ ldmdb	r14!, {r4,sp}")
+
+	TEST_GROUP("Load/store double or exclusive, table branch")
+
+	TEST_P(  "ldrd	r0, r1, [r",1, 24,", #-16]")
+	TEST(    "ldrd	r12, r14, [sp, #16]")
+	TEST_P(  "ldrd	r1, r0, [r",7, 24,", #-16]!")
+	TEST(    "ldrd	r14, r12, [sp, #16]!")
+	TEST_P(  "ldrd	r1, r0, [r",7, 24,"], #16")
+	TEST(    "ldrd	r7, r8, [sp], #-16")
+
+	TEST_X( "ldrd	r12, r14, 3f",
+		".align 3				\n\t"
+		"3:	.word	"__stringify(VAL1)"	\n\t"
+		"	.word	"__stringify(VAL2))
+
+	TEST_UNSUPPORTED(".short 0xe9ff,0xec04	@ ldrd	r14, r12, [pc, #16]!")
+	TEST_UNSUPPORTED(".short 0xe8ff,0xec04	@ ldrd	r14, r12, [pc], #16")
+	TEST_UNSUPPORTED(".short 0xe9d4,0xd800	@ ldrd	sp, r8, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0xf800	@ ldrd	pc, r8, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0x7d00	@ ldrd	r7, sp, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0x7f00	@ ldrd	r7, pc, [r4]")
+
+	TEST_RRP("strd	r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
+	TEST_RR( "strd	r",12,VAL2,", r",14,VAL1,", [sp, #16]")
+	TEST_RRP("strd	r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
+	TEST_RR( "strd	r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
+	TEST_RRP("strd	r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
+	TEST_RR( "strd	r",7, VAL2,", r",8, VAL1,", [sp], #-16")
+	TEST_UNSUPPORTED(".short 0xe9ef,0xec04	@ strd	r14, r12, [pc, #16]!")
+	TEST_UNSUPPORTED(".short 0xe8ef,0xec04	@ strd	r14, r12, [pc], #16")
+
+	TEST_RX("tbb	[pc, r",0, (9f-(1f+4)),"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbb	[pc, r",4, (9f-(1f+4)+1),"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RRX("tbb	[r",1,9f,", r",2,0,"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbh	[pc, r",7, (9f-(1f+4))>>1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbh	[pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RRX("tbh	[r",1,9f, ", r",14,1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_UNSUPPORTED(".short 0xe8d1,0xf01f	@ tbh [r1, pc]")
+	TEST_UNSUPPORTED(".short 0xe8d1,0xf01d	@ tbh [r1, sp]")
+	TEST_UNSUPPORTED(".short 0xe8dd,0xf012	@ tbh [sp, r2]")
+
+	TEST_UNSUPPORTED("strexb	r0, r1, [r2]")
+	TEST_UNSUPPORTED("strexh	r0, r1, [r2]")
+	TEST_UNSUPPORTED("strexd	r0, r1, [r2]")
+	TEST_UNSUPPORTED("ldrexb	r0, [r1]")
+	TEST_UNSUPPORTED("ldrexh	r0, [r1]")
+	TEST_UNSUPPORTED("ldrexd	r0, [r1]")
+
+	TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
+
+#define _DATA_PROCESSING32_DNM(op,s,val)					\
+	TEST_RR(op s".w	r0,  r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(op s"	r1,  r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(op s"	r2,  r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(op s"	r3,  r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(op s"	r4,  r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(op s"	r5,  r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(op s"	r8,  r",9, VAL1,", r",10,val, ", rrx")			\
+	TEST_R( op s"	r0,  r",11,VAL1,", #0x00010001")			\
+	TEST_R( op s"	r11, r",0, VAL1,", #0xf5000000")			\
+	TEST_R( op s"	r7,  r",8, VAL2,", #0x000af000")
+
+#define DATA_PROCESSING32_DNM(op,val)		\
+	_DATA_PROCESSING32_DNM(op,"",val)	\
+	_DATA_PROCESSING32_DNM(op,"s",val)
+
+#define DATA_PROCESSING32_NM(op,val)					\
+	TEST_RR(op".w	r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(op"	r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(op"	r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(op"	r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(op"	r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(op"	r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(op"	r",9, VAL1,", r",10,val, ", rrx")		\
+	TEST_R( op"	r",11,VAL1,", #0x00010001")			\
+	TEST_R( op"	r",0, VAL1,", #0xf5000000")			\
+	TEST_R( op"	r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING32_DM(op,s,val)				\
+	TEST_R( op s".w	r0,  r",14, val, "")			\
+	TEST_R( op s"	r1,  r",12, val, ", lsl #3")		\
+	TEST_R( op s"	r2,  r",11, val, ", lsr #4")		\
+	TEST_R( op s"	r3,  r",10, val, ", asr #5")		\
+	TEST_R( op s"	r4,  r",9, N(val),", asr #6")		\
+	TEST_R( op s"	r5,  r",8, val, ", ror #7")		\
+	TEST_R( op s"	r8,  r",7,val, ", rrx")			\
+	TEST(   op s"	r0,  #0x00010001")			\
+	TEST(   op s"	r11, #0xf5000000")			\
+	TEST(   op s"	r7,  #0x000af000")			\
+	TEST(   op s"	r4,  #0x00005a00")
+
+#define DATA_PROCESSING32_DM(op,val)		\
+	_DATA_PROCESSING32_DM(op,"",val)	\
+	_DATA_PROCESSING32_DM(op,"s",val)
+
+	DATA_PROCESSING32_DNM("and",0xf00f00ff)
+	DATA_PROCESSING32_NM("tst",0xf00f00ff)
+	DATA_PROCESSING32_DNM("bic",0xf00f00ff)
+	DATA_PROCESSING32_DNM("orr",0xf00f00ff)
+	DATA_PROCESSING32_DM("mov",VAL2)
+	DATA_PROCESSING32_DNM("orn",0xf00f00ff)
+	DATA_PROCESSING32_DM("mvn",VAL2)
+	DATA_PROCESSING32_DNM("eor",0xf00f00ff)
+	DATA_PROCESSING32_NM("teq",0xf00f00ff)
+	DATA_PROCESSING32_DNM("add",VAL2)
+	DATA_PROCESSING32_NM("cmn",VAL2)
+	DATA_PROCESSING32_DNM("adc",VAL2)
+	DATA_PROCESSING32_DNM("sbc",VAL2)
+	DATA_PROCESSING32_DNM("sub",VAL2)
+	DATA_PROCESSING32_NM("cmp",VAL2)
+	DATA_PROCESSING32_DNM("rsb",VAL2)
+
+	TEST_RR("pkhbt	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR("pkhbt	r14,r",12, HH1,", r",10,HH2,", lsl #2")
+	TEST_RR("pkhtb	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR("pkhtb	r14,r",12, HH1,", r",10,HH2,", asr #2")
+
+	TEST_UNSUPPORTED(".short 0xea17,0x0f0d	@ tst.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea17,0x0f0f	@ tst.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea1d,0x0f07	@ tst.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea1f,0x0f07	@ tst.w pc, r7")
+	TEST_UNSUPPORTED(".short 0xf01d,0x1f08	@ tst sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf01f,0x1f08	@ tst pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xea97,0x0f0d	@ teq.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea97,0x0f0f	@ teq.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea9d,0x0f07	@ teq.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea9f,0x0f07	@ teq.w pc, r7")
+	TEST_UNSUPPORTED(".short 0xf09d,0x1f08	@ tst sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf09f,0x1f08	@ tst pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeb17,0x0f0d	@ cmn.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xeb17,0x0f0f	@ cmn.w r7, pc")
+	TEST_P("cmn.w	sp, r",7,0,"")
+	TEST_UNSUPPORTED(".short 0xeb1f,0x0f07	@ cmn.w pc, r7")
+	TEST(  "cmn	sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf11f,0x1f08	@ cmn pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xebb7,0x0f0d	@ cmp.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xebb7,0x0f0f	@ cmp.w r7, pc")
+	TEST_P("cmp.w	sp, r",7,0,"")
+	TEST_UNSUPPORTED(".short 0xebbf,0x0f07	@ cmp.w pc, r7")
+	TEST(  "cmp	sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf1bf,0x1f08	@ cmp pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xea5f,0x070d	@ movs.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea5f,0x070f	@ movs.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea5f,0x0d07	@ movs.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea4f,0x0f07	@ mov.w  pc, r7")
+	TEST_UNSUPPORTED(".short 0xf04f,0x1d08	@ mov sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf04f,0x1f08	@ mov pc, #0x00080008")
+
+	TEST_R("add.w	r0, sp, r",1, 4,"")
+	TEST_R("adds	r0, sp, r",1, 4,", asl #3")
+	TEST_R("add	r0, sp, r",1, 4,", asl #4")
+	TEST_R("add	r0, sp, r",1, 16,", ror #1")
+	TEST_R("add.w	sp, sp, r",1, 4,"")
+	TEST_R("add	sp, sp, r",1, 4,", asl #3")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x1d01	@ add sp, sp, r1, asl #4")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d71	@ add sp, sp, r1, ror #1")
+	TEST(  "add.w	r0, sp, #24")
+	TEST(  "add.w	sp, sp, #24")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0f01	@ add pc, sp, r1")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x000f	@ add r0, sp, pc")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x000d	@ add r0, sp, sp")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f	@ add sp, sp, pc")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d	@ add sp, sp, sp")
+
+	TEST_R("sub.w	r0, sp, r",1, 4,"")
+	TEST_R("subs	r0, sp, r",1, 4,", asl #3")
+	TEST_R("sub	r0, sp, r",1, 4,", asl #4")
+	TEST_R("sub	r0, sp, r",1, 16,", ror #1")
+	TEST_R("sub.w	sp, sp, r",1, 4,"")
+	TEST_R("sub	sp, sp, r",1, 4,", asl #3")
+	TEST_UNSUPPORTED(".short 0xebad,0x1d01	@ sub sp, sp, r1, asl #4")
+	TEST_UNSUPPORTED(".short 0xebad,0x0d71	@ sub sp, sp, r1, ror #1")
+	TEST_UNSUPPORTED(".short 0xebad,0x0f01	@ sub pc, sp, r1")
+	TEST(  "sub.w	r0, sp, #24")
+	TEST(  "sub.w	sp, sp, #24")
+
+	TEST_UNSUPPORTED(".short 0xea02,0x010f	@ and r1, r2, pc")
+	TEST_UNSUPPORTED(".short 0xea0f,0x0103	@ and r1, pc, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x0f03	@ and pc, r2, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x010d	@ and r1, r2, sp")
+	TEST_UNSUPPORTED(".short 0xea0d,0x0103	@ and r1, sp, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x0d03	@ and sp, r2, r3")
+	TEST_UNSUPPORTED(".short 0xf00d,0x1108	@ and r1, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf00f,0x1108	@ and r1, pc, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf002,0x1d08	@ and sp, r8, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf002,0x1f08	@ and pc, r8, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeb02,0x010f	@ add r1, r2, pc")
+	TEST_UNSUPPORTED(".short 0xeb0f,0x0103	@ add r1, pc, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x0f03	@ add pc, r2, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x010d	@ add r1, r2, sp")
+	TEST_SUPPORTED(  ".short 0xeb0d,0x0103	@ add r1, sp, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x0d03	@ add sp, r2, r3")
+	TEST_SUPPORTED(  ".short 0xf10d,0x1108	@ add r1, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf10d,0x1f08	@ add pc, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf10f,0x1108	@ add r1, pc, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf102,0x1d08	@ add sp, r8, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf102,0x1f08	@ add pc, r8, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeaa0,0x0000")
+	TEST_UNSUPPORTED(".short 0xeaf0,0x0000")
+	TEST_UNSUPPORTED(".short 0xeb20,0x0000")
+	TEST_UNSUPPORTED(".short 0xeb80,0x0000")
+	TEST_UNSUPPORTED(".short 0xebe0,0x0000")
+
+	TEST_UNSUPPORTED(".short 0xf0a0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf0c0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf0f0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf120,0x0000")
+	TEST_UNSUPPORTED(".short 0xf180,0x0000")
+	TEST_UNSUPPORTED(".short 0xf1e0,0x0000")
+
+	TEST_GROUP("Coprocessor instructions")
+
+	TEST_UNSUPPORTED(".short 0xec00,0x0000")
+	TEST_UNSUPPORTED(".short 0xeff0,0x0000")
+	TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+	TEST_UNSUPPORTED(".short 0xfff0,0x0000")
+
+	TEST_GROUP("Data-processing (plain binary immediate)")
+
+	TEST_R("addw	r0,  r",1, VAL1,", #0x123")
+	TEST(  "addw	r14, sp, #0xf5a")
+	TEST(  "addw	sp, sp, #0x20")
+	TEST(  "addw	r7,  pc, #0x888")
+	TEST_UNSUPPORTED(".short 0xf20f,0x1f20	@ addw pc, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf20d,0x1f20	@ addw pc, sp, #0x120")
+	TEST_UNSUPPORTED(".short 0xf20f,0x1d20	@ addw sp, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf200,0x1d20	@ addw sp, r0, #0x120")
+
+	TEST_R("subw	r0,  r",1, VAL1,", #0x123")
+	TEST(  "subw	r14, sp, #0xf5a")
+	TEST(  "subw	sp, sp, #0x20")
+	TEST(  "subw	r7,  pc, #0x888")
+	TEST_UNSUPPORTED(".short 0xf2af,0x1f20	@ subw pc, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2ad,0x1f20	@ subw pc, sp, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2af,0x1d20	@ subw sp, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2a0,0x1d20	@ subw sp, r0, #0x120")
+
+	TEST("movw	r0, #0")
+	TEST("movw	r0, #0xffff")
+	TEST("movw	lr, #0xffff")
+	TEST_UNSUPPORTED(".short 0xf240,0x0d00	@ movw sp, #0")
+	TEST_UNSUPPORTED(".short 0xf240,0x0f00	@ movw pc, #0")
+
+	TEST_R("movt	r",0, VAL1,", #0")
+	TEST_R("movt	r",0, VAL2,", #0xffff")
+	TEST_R("movt	r",14,VAL1,", #0xffff")
+	TEST_UNSUPPORTED(".short 0xf2c0,0x0d00	@ movt sp, #0")
+	TEST_UNSUPPORTED(".short 0xf2c0,0x0f00	@ movt pc, #0")
+
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".short 0xf30c,0x0d17	@ ssat	sp, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf30c,0x0f17	@ ssat	pc, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf30d,0x0c17	@ ssat	r12, #24, sp")
+	TEST_UNSUPPORTED(".short 0xf30f,0x0c17	@ ssat	r12, #24, pc")
+
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".short 0xf38c,0x0d17	@ usat	sp, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf38c,0x0f17	@ usat	pc, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf38d,0x0c17	@ usat	r12, #24, sp")
+	TEST_UNSUPPORTED(".short 0xf38f,0x0c17	@ usat	r12, #24, pc")
+
+	TEST_R(     "ssat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "ssat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".short 0xf32c,0x0d0b	@ ssat16	sp, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf32c,0x0f0b	@ ssat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf32d,0x0c0b	@ ssat16	r12, #12, sp")
+	TEST_UNSUPPORTED(".short 0xf32f,0x0c0b	@ ssat16	r12, #12, pc")
+
+	TEST_R(     "usat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "usat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b	@ usat16	sp, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b	@ usat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b	@ usat16	r12, #12, sp")
+	TEST_UNSUPPORTED(".short 0xf3af,0x0c0b	@ usat16	r12, #12, pc")
+
+	TEST_R(     "sbfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "sbfx	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "sbfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".short 0xf34c,0x2d0f	@ sbfx	sp, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34c,0x2f0f	@ sbfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34d,0x2c0f	@ sbfx	r12, sp, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34f,0x2c0f	@ sbfx	r12, pc, #8, #16")
+
+	TEST_R(     "ubfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "ubfx	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "ubfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f	@ ubfx	sp, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f	@ ubfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f	@ ubfx	r12, sp, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f	@ ubfx	r12, pc, #8, #16")
+
+	TEST_R(     "bfc	r",0, VAL1,", #4, #20")
+	TEST_R(     "bfc	r",14,VAL2,", #4, #20")
+	TEST_R(     "bfc	r",7, VAL1,", #0, #31")
+	TEST_R(     "bfc	r",8, VAL2,", #0, #31")
+	TEST_UNSUPPORTED(".short 0xf36f,0x0d1e	@ bfc	sp, #0, #31")
+	TEST_UNSUPPORTED(".short 0xf36f,0x0f1e	@ bfc	pc, #0, #31")
+
+	TEST_RR(    "bfi	r",0, VAL1,", r",0  , VAL2,", #0, #31")
+	TEST_RR(    "bfi	r",12,VAL1,", r",14 , VAL2,", #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36e,0x1d17	@ bfi	sp, r14, #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36e,0x1f17	@ bfi	pc, r14, #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36d,0x1e17	@ bfi	r14, sp, #4, #20")
+
+	TEST_GROUP("Branches and miscellaneous control")
+
+CONDITION_INSTRUCTIONS(22,
+	TEST_BF("beq.w	2f")
+	TEST_BB("bne.w	2b")
+	TEST_BF("bgt.w	2f")
+	TEST_BB("blt.w	2b")
+	TEST_BF_X("bpl.w	2f", SPACE_0x1000)
+)
+
+	TEST_UNSUPPORTED("msr	cpsr, r0")
+	TEST_UNSUPPORTED("msr	cpsr_f, r1")
+	TEST_UNSUPPORTED("msr	spsr, r2")
+
+	TEST_UNSUPPORTED("cpsie.w	i")
+	TEST_UNSUPPORTED("cpsid.w	i")
+	TEST_UNSUPPORTED("cps	0x13")
+
+	TEST_SUPPORTED("yield.w")
+	TEST("sev.w")
+	TEST("nop.w")
+	TEST("wfi.w")
+	TEST_SUPPORTED("wfe.w")
+	TEST_UNSUPPORTED("dbg.w	#0")
+
+	TEST_UNSUPPORTED("clrex")
+	TEST_UNSUPPORTED("dsb")
+	TEST_UNSUPPORTED("dmb")
+	TEST_UNSUPPORTED("isb")
+
+	TEST_UNSUPPORTED("bxj	r0")
+
+	TEST_UNSUPPORTED("subs	pc, lr, #4")
+
+	TEST("mrs	r0, cpsr")
+	TEST("mrs	r14, cpsr")
+	TEST_UNSUPPORTED(".short 0xf3ef,0x8d00	@ mrs	sp, spsr")
+	TEST_UNSUPPORTED(".short 0xf3ef,0x8f00	@ mrs	pc, spsr")
+	TEST_UNSUPPORTED("mrs	r0, spsr")
+	TEST_UNSUPPORTED("mrs	lr, spsr")
+
+	TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0")
+
+	TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined")
+
+	TEST_BF(  "b.w	2f")
+	TEST_BB(  "b.w	2b")
+	TEST_BF_X("b.w	2f", SPACE_0x1000)
+
+	TEST_BF(  "bl.w	2f")
+	TEST_BB(  "bl.w	2b")
+	TEST_BB_X("bl.w	2b", SPACE_0x1000)
+
+	TEST_X(	"blx	__dummy_arm_subroutine",
+		".arm				\n\t"
+		".align				\n\t"
+		".type __dummy_arm_subroutine, %%function \n\t"
+		"__dummy_arm_subroutine:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".thumb				\n\t"
+	)
+	TEST(	"blx	__dummy_arm_subroutine")
+
+	TEST_GROUP("Store single data item")
+
+#define SINGLE_STORE(size)							\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,-1024,", #1024]")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, -1024,", #1080]")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,256,  ", #-120]")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 256,  ", #-128]")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,  "], #120")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,  "], #128")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,  "], #-120")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,  "], #-128")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,   ", #120]!")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,   ", #128]!")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,256,  ", #-120]!")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 256,  ", #-128]!")		\
+	TEST_RPR("str"size".w	r",0, VAL1,", [r",1, 0,", r",2, 4,"]")		\
+	TEST_RPR("str"size"	r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]")	\
+	TEST_R(  "str"size".w	r",7, VAL1,", [sp, #24]")			\
+	TEST_RP( "str"size".w	r",0, VAL2,", [r",0,0, "]")			\
+	TEST_UNSUPPORTED("str"size"t	r0, [r1, #4]")
+
+	SINGLE_STORE("b")
+	SINGLE_STORE("h")
+	SINGLE_STORE("")
+
+	TEST("str	sp, [sp]")
+	TEST_UNSUPPORTED(".short 0xf8cf,0xe000	@ str	r14, [pc]")
+	TEST_UNSUPPORTED(".short 0xf8ce,0xf000	@ str	pc, [r14]")
+
+	TEST_GROUP("Advanced SIMD element or structure load/store instructions")
+
+	TEST_UNSUPPORTED(".short 0xf900,0x0000")
+	TEST_UNSUPPORTED(".short 0xf92f,0xffff")
+	TEST_UNSUPPORTED(".short 0xf980,0x0000")
+	TEST_UNSUPPORTED(".short 0xf9ef,0xffff")
+
+	TEST_GROUP("Load single data item and memory hints")
+
+#define SINGLE_LOAD(size)						\
+	TEST_P( "ldr"size"	r0, [r",11,-1024, ", #1024]")		\
+	TEST_P( "ldr"size"	r14, [r",1, -1024,", #1080]")		\
+	TEST_P( "ldr"size"	r0, [r",11,256,   ", #-120]")		\
+	TEST_P( "ldr"size"	r14, [r",1, 256,  ", #-128]")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,   "], #120")		\
+	TEST_P( "ldr"size"	r14, [r",1, 24,  "], #128")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,   "], #-120")		\
+	TEST_P( "ldr"size"	r14, [r",1,24,   "], #-128")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,    ", #120]!")		\
+	TEST_P( "ldr"size"	r14, [r",1, 24,   ", #128]!")		\
+	TEST_P( "ldr"size"	r0, [r",11,256,   ", #-120]!")		\
+	TEST_P( "ldr"size"	r14, [r",1, 256,  ", #-128]!")		\
+	TEST_PR("ldr"size".w	r0, [r",1, 0,", r",2, 4,"]")		\
+	TEST_PR("ldr"size"	r14, [r",10,0,", r",11,4,", lsl #1]")	\
+	TEST_X( "ldr"size".w	r0, 3f",				\
+		".align 3				\n\t"		\
+		"3:	.word	"__stringify(VAL1))			\
+	TEST_X( "ldr"size".w	r14, 3f",				\
+		".align 3				\n\t"		\
+		"3:	.word	"__stringify(VAL2))			\
+	TEST(   "ldr"size".w	r7, 3b")				\
+	TEST(   "ldr"size".w	r7, [sp, #24]")				\
+	TEST_P( "ldr"size".w	r0, [r",0,0, "]")			\
+	TEST_UNSUPPORTED("ldr"size"t	r0, [r1, #4]")
+
+	SINGLE_LOAD("b")
+	SINGLE_LOAD("sb")
+	SINGLE_LOAD("h")
+	SINGLE_LOAD("sh")
+	SINGLE_LOAD("")
+
+	TEST_BF_P("ldr	pc, [r",14, 15*4,"]")
+	TEST_P(   "ldr	sp, [r",14, 13*4,"]")
+	TEST_BF_R("ldr	pc, [sp, r",14, 15*4,"]")
+	TEST_R(   "ldr	sp, [sp, r",14, 13*4,"]")
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldr	pc, [r",0,0,", #15*4]")
+	TEST_SUPPORTED("ldr	sp, 99f")
+	TEST_SUPPORTED("ldr	pc, 99f")
+
+	TEST_UNSUPPORTED(".short 0xf854,0x700d	@ ldr	r7, [r4, sp]")
+	TEST_UNSUPPORTED(".short 0xf854,0x700f	@ ldr	r7, [r4, pc]")
+	TEST_UNSUPPORTED(".short 0xf814,0x700d	@ ldrb	r7, [r4, sp]")
+	TEST_UNSUPPORTED(".short 0xf814,0x700f	@ ldrb	r7, [r4, pc]")
+	TEST_UNSUPPORTED(".short 0xf89f,0xd004	@ ldrb	sp, 99f")
+	TEST_UNSUPPORTED(".short 0xf814,0xd008	@ ldrb	sp, [r4, r8]")
+	TEST_UNSUPPORTED(".short 0xf894,0xd000	@ ldrb	sp, [r4]")
+
+	TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */
+
+	TEST(   "pli	[pc, #4]")
+	TEST(   "pli	[pc, #-4]")
+	TEST(   "pld	[pc, #4]")
+	TEST(   "pld	[pc, #-4]")
+
+	TEST_P( "pld	[r",0,-1024,", #1024]")
+	TEST(   ".short 0xf8b0,0xf400	@ pldw	[r0, #1024]")
+	TEST_P( "pli	[r",4, 0b,", #1024]")
+	TEST_P( "pld	[r",7, 120,", #-120]")
+	TEST(   ".short 0xf837,0xfc78	@ pldw	[r7, #-120]")
+	TEST_P( "pli	[r",11,120,", #-120]")
+	TEST(   "pld	[sp, #0]")
+
+	TEST_PR("pld	[r",7, 24, ", r",0, 16,"]")
+	TEST_PR("pld	[r",8, 24, ", r",12,16,", lsl #3]")
+	TEST_SUPPORTED(".short 0xf837,0xf000	@ pldw	[r7, r0]")
+	TEST_SUPPORTED(".short 0xf838,0xf03c	@ pldw	[r8, r12, lsl #3]");
+	TEST_RR("pli	[r",12,0b,", r",0, 16,"]")
+	TEST_RR("pli	[r",0, 0b,", r",12,16,", lsl #3]")
+	TEST_R( "pld	[sp, r",1, 16,"]")
+	TEST_UNSUPPORTED(".short 0xf817,0xf00d  @pld	[r7, sp]")
+	TEST_UNSUPPORTED(".short 0xf817,0xf00f  @pld	[r7, pc]")
+
+	TEST_GROUP("Data-processing (register)")
+
+#define SHIFTS32(op)					\
+	TEST_RR(op"	r0,  r",1, VAL1,", r",2, 3, "")	\
+	TEST_RR(op"	r14, r",12,VAL2,", r",11,10,"")
+
+	SHIFTS32("lsl")
+	SHIFTS32("lsls")
+	SHIFTS32("lsr")
+	SHIFTS32("lsrs")
+	SHIFTS32("asr")
+	SHIFTS32("asrs")
+	SHIFTS32("ror")
+	SHIFTS32("rors")
+
+	TEST_UNSUPPORTED(".short 0xfa01,0xff02	@ lsl	pc, r1, r2")
+	TEST_UNSUPPORTED(".short 0xfa01,0xfd02	@ lsl	sp, r1, r2")
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf002	@ lsl	r0, pc, r2")
+	TEST_UNSUPPORTED(".short 0xfa0d,0xf002	@ lsl	r0, sp, r2")
+	TEST_UNSUPPORTED(".short 0xfa01,0xf00f	@ lsl	r0, r1, pc")
+	TEST_UNSUPPORTED(".short 0xfa01,0xf00d	@ lsl	r0, r1, sp")
+
+	TEST_RR(    "sxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxth	r8, r",7,  HH1,"")
+
+	TEST_UNSUPPORTED(".short 0xfa0f,0xff87	@ sxth	pc, r7");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xfd87	@ sxth	sp, r7");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf88f	@ sxth	r8, pc");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf88d	@ sxth	r8, sp");
+
+	TEST_RR(    "uxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxth	r8, r",7,  HH1,"")
+
+	TEST_RR(    "sxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb16	r8, r",7,  HH1,"")
+
+	TEST_RR(    "uxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb16	r8, r",7,  HH1,"")
+
+	TEST_RR(    "sxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb	r8, r",7,  HH1,"")
+
+	TEST_RR(    "uxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb	r8, r",7,  HH1,"")
+
+	TEST_UNSUPPORTED(".short 0xfa60,0x00f0")
+	TEST_UNSUPPORTED(".short 0xfa7f,0xffff")
+
+#define PARALLEL_ADD_SUB(op)					\
+	TEST_RR(  op"add16	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"add16	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"asx	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"asx	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sax	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sax	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sub16	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sub16	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"add8	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"add8	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sub8	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sub8	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_GROUP("Parallel addition and subtraction, signed")
+
+	PARALLEL_ADD_SUB("s")
+	PARALLEL_ADD_SUB("q")
+	PARALLEL_ADD_SUB("sh")
+
+	TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+	PARALLEL_ADD_SUB("u")
+	PARALLEL_ADD_SUB("uq")
+	PARALLEL_ADD_SUB("uh")
+
+	TEST_GROUP("Miscellaneous operations")
+
+	TEST_RR("qadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qadd	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qsub	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qdadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qdadd	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qdsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qdsub	lr, r",9, VAL2,", r",8, VAL1,"")
+
+	TEST_R("rev.w	r0, r",0,   VAL1,"")
+	TEST_R("rev	r14, r",12, VAL2,"")
+	TEST_R("rev16.w	r0, r",0,   VAL1,"")
+	TEST_R("rev16	r14, r",12, VAL2,"")
+	TEST_R("rbit	r0, r",0,   VAL1,"")
+	TEST_R("rbit	r14, r",12, VAL2,"")
+	TEST_R("revsh.w	r0, r",0,   VAL1,"")
+	TEST_R("revsh	r14, r",12, VAL2,"")
+
+	TEST_UNSUPPORTED(".short 0xfa9c,0xff8c	@ rev	pc, r12");
+	TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c	@ rev	sp, r12");
+	TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f	@ rev	r14, pc");
+	TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d	@ rev	r14, sp");
+
+	TEST_RR("sel	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR("sel	r14, r",12,VAL1,", r",10, VAL2,"")
+
+	TEST_R("clz	r0, r",0, 0x0,"")
+	TEST_R("clz	r7, r",14,0x1,"")
+	TEST_R("clz	lr, r",7, 0xffffffff,"")
+
+	TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+
+	TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
+
+	TEST_RR(    "mul	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mul	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xfb08,0xff09	@ mul	pc, r8, r9")
+	TEST_UNSUPPORTED(".short 0xfb08,0xfd09	@ mul	sp, r8, r9")
+	TEST_UNSUPPORTED(".short 0xfb0f,0xf709	@ mul	r7, pc, r9")
+	TEST_UNSUPPORTED(".short 0xfb0d,0xf709	@ mul	r7, sp, r9")
+	TEST_UNSUPPORTED(".short 0xfb08,0xf70f	@ mul	r7, r8, pc")
+	TEST_UNSUPPORTED(".short 0xfb08,0xf70d	@ mul	r7, r8, sp")
+
+	TEST_RRR(   "mla	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "mla	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xfb08,0xaf09	@ mla	pc, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xad09	@ mla	sp, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb0f,0xa709	@ mla	r7, pc, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb0d,0xa709	@ mla	r7, sp, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xa70f	@ mla	r7, r8, pc, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xa70d	@ mla	r7, r8, sp, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xd709	@ mla	r7, r8, r9, sp");
+
+	TEST_RRR(   "mls	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "mls	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+
+	TEST_RRR(   "smlabb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlabb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlatb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlatb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlabt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlabt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlatt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlatt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(    "smulbb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smultb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smulbt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbt	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smultt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultt	r7, r",8, VAL3,", r",9, VAL1,"")
+
+	TEST_RRR(   "smlad	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlad	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RRR(   "smladx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smladx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RR(    "smuad	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smuad	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_RR(    "smuadx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smuadx	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_RRR(   "smlawb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlawb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlawt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlawt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(    "smulwb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smulwt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwt	r7, r",8, VAL3,", r",9, VAL1,"")
+
+	TEST_RRR(   "smlsd	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsd	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RRR(   "smlsdx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsdx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RR(    "smusd	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smusd	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_RR(    "smusdx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smusdx	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_RRR(   "smmla	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmla	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RRR(   "smmlar	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmlar	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RR(    "smmul	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "smmul	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_RR(    "smmulr	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "smmulr	r14, r",12,VAL2,", r",10,VAL1,"")
+
+	TEST_RRR(   "smmls	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmls	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RRR(   "smmlsr	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmlsr	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+
+	TEST_RRR(   "usada8	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+	TEST_RRR(   "usada8	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+	TEST_RR(    "usad8	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "usad8	r14, r",12,VAL2,", r",10,VAL1,"")
+
+	TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+
+	TEST_GROUP("Long multiply, long multiply accumulate, and divide")
+
+	TEST_RR(   "smull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(   "smull	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_UNSUPPORTED(".short 0xfb89,0xf80a	@ smull	pc, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0xd80a	@ smull	sp, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x7f0a	@ smull	r7, pc, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x7d0a	@ smull	r7, sp, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb8f,0x780a	@ smull	r7, r8, pc, r10");
+	TEST_UNSUPPORTED(".short 0xfb8d,0x780a	@ smull	r7, r8, sp, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x780f	@ smull	r7, r8, r9, pc");
+	TEST_UNSUPPORTED(".short 0xfb89,0x780d	@ smull	r7, r8, r9, sp");
+
+	TEST_RR(   "umull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(   "umull	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+
+	TEST_RRRR( "smlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_RRRR( "smlalbb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlalbb	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlalbt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlalbt	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlaltb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlaltb	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlaltt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlaltt	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_RRRR( "smlald	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlald	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_RRRR( "smlaldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlaldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+	TEST_RRRR( "smlsld	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlsld	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_RRRR( "smlsldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlsldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+	TEST_RRRR( "umlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "umlal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "umaal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "umaal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_GROUP("Coprocessor instructions")
+
+	TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+	TEST_UNSUPPORTED(".short 0xffff,0xffff")
+
+	TEST_GROUP("Testing instructions in IT blocks")
+
+	TEST_ITBLOCK("sub.w	r0, r0")
+
+	verbose("\n");
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-thumb.c linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-thumb.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/kprobes-thumb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/kprobes-thumb.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -943,6 +944,9 @@ const union decode_item kprobe_decode_th
 	 */
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+#endif
 
 static void __kprobes
 t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
@@ -1423,6 +1427,9 @@ const union decode_item kprobe_decode_th
 
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
 
 static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/leds.c linux-libre-3.2-gnu1/arch/arm/kernel/leds.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
 #include <linux/syscore_ops.h>
+#include <linux/string.h>
 
 #include <asm/leds.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/Makefile linux-libre-3.2-gnu1/arch/arm/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/arm/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o mod
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
-obj-$(CONFIG_PM_SLEEP)		+= sleep.o
+obj-$(CONFIG_ARM_CPU_SUSPEND)	+= sleep.o suspend.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
@@ -43,6 +43,13 @@ obj-$(CONFIG_KPROBES)		+= kprobes-thumb.
 else
 obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
 endif
+obj-$(CONFIG_ARM_KPROBES_TEST)	+= test-kprobes.o
+test-kprobes-objs		:= kprobes-test.o
+ifdef CONFIG_THUMB2_KERNEL
+test-kprobes-objs		+= kprobes-test-thumb.o
+else
+test-kprobes-objs		+= kprobes-test-arm.o
+endif
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
@@ -66,6 +73,7 @@ obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
 obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
+obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/module.c linux-libre-3.2-gnu1/arch/arm/kernel/module.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
  * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
  */
 #undef MODULES_VADDR
-#define MODULES_VADDR	(((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK)
+#define MODULES_VADDR	(((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
 #endif
 
 #ifdef CONFIG_MMU
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/perf_event.c linux-libre-3.2-gnu1/arch/arm/kernel/perf_event.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,10 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
+#include <linux/bitmap.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
@@ -26,16 +27,8 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-static struct platform_device *pmu_device;
-
-/*
- * Hardware lock to serialize accesses to PMU registers. Needed for the
- * read/modify/write sequences.
- */
-static DEFINE_RAW_SPINLOCK(pmu_lock);
-
 /*
- * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
+ * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
  * another platform that supports more, we need to increase this to be the
  * largest of all platforms.
  *
@@ -43,62 +36,24 @@ static DEFINE_RAW_SPINLOCK(pmu_lock);
  *  cycle counter CCNT + 31 events counters CNT0..30.
  *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
  */
-#define ARMPMU_MAX_HWEVENTS		33
-
-/* The events for a given CPU. */
-struct cpu_hw_events {
-	/*
-	 * The events that are active on the CPU for the given index. Index 0
-	 * is reserved.
-	 */
-	struct perf_event	*events[ARMPMU_MAX_HWEVENTS];
-
-	/*
-	 * A 1 bit for an index indicates that the counter is being used for
-	 * an event. A 0 means that the counter can be used.
-	 */
-	unsigned long		used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+#define ARMPMU_MAX_HWEVENTS		32
 
-	/*
-	 * A 1 bit for an index indicates that the counter is actively being
-	 * used.
-	 */
-	unsigned long		active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
-};
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
 
-struct arm_pmu {
-	enum arm_perf_pmu_ids id;
-	const char	*name;
-	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
-	void		(*enable)(struct hw_perf_event *evt, int idx);
-	void		(*disable)(struct hw_perf_event *evt, int idx);
-	int		(*get_event_idx)(struct cpu_hw_events *cpuc,
-					 struct hw_perf_event *hwc);
-	u32		(*read_counter)(int idx);
-	void		(*write_counter)(int idx, u32 val);
-	void		(*start)(void);
-	void		(*stop)(void);
-	void		(*reset)(void *);
-	const unsigned	(*cache_map)[PERF_COUNT_HW_CACHE_MAX]
-				    [PERF_COUNT_HW_CACHE_OP_MAX]
-				    [PERF_COUNT_HW_CACHE_RESULT_MAX];
-	const unsigned	(*event_map)[PERF_COUNT_HW_MAX];
-	u32		raw_event_mask;
-	int		num_events;
-	u64		max_period;
-};
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
 /* Set at runtime when we know what CPU type we are. */
-static const struct arm_pmu *armpmu;
+static struct arm_pmu *cpu_pmu;
 
 enum arm_perf_pmu_ids
 armpmu_get_pmu_id(void)
 {
 	int id = -ENODEV;
 
-	if (armpmu != NULL)
-		id = armpmu->id;
+	if (cpu_pmu != NULL)
+		id = cpu_pmu->id;
 
 	return id;
 }
@@ -109,8 +64,8 @@ armpmu_get_max_events(void)
 {
 	int max_events = 0;
 
-	if (armpmu != NULL)
-		max_events = armpmu->num_events;
+	if (cpu_pmu != NULL)
+		max_events = cpu_pmu->num_events;
 
 	return max_events;
 }
@@ -130,7 +85,11 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
 #define CACHE_OP_UNSUPPORTED		0xFFFF
 
 static int
-armpmu_map_cache_event(u64 config)
+armpmu_map_cache_event(const unsigned (*cache_map)
+				      [PERF_COUNT_HW_CACHE_MAX]
+				      [PERF_COUNT_HW_CACHE_OP_MAX]
+				      [PERF_COUNT_HW_CACHE_RESULT_MAX],
+		       u64 config)
 {
 	unsigned int cache_type, cache_op, cache_result, ret;
 
@@ -146,7 +105,7 @@ armpmu_map_cache_event(u64 config)
 	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
 		return -EINVAL;
 
-	ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
+	ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
 
 	if (ret == CACHE_OP_UNSUPPORTED)
 		return -ENOENT;
@@ -155,23 +114,46 @@ armpmu_map_cache_event(u64 config)
 }
 
 static int
-armpmu_map_event(u64 config)
+armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-	int mapping = (*armpmu->event_map)[config];
-	return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+	int mapping = (*event_map)[config];
+	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
 static int
-armpmu_map_raw_event(u64 config)
+armpmu_map_raw_event(u32 raw_event_mask, u64 config)
 {
-	return (int)(config & armpmu->raw_event_mask);
+	return (int)(config & raw_event_mask);
 }
 
-static int
+static int map_cpu_event(struct perf_event *event,
+			 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+			 const unsigned (*cache_map)
+					[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX],
+			 u32 raw_event_mask)
+{
+	u64 config = event->attr.config;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_HARDWARE:
+		return armpmu_map_event(event_map, config);
+	case PERF_TYPE_HW_CACHE:
+		return armpmu_map_cache_event(cache_map, config);
+	case PERF_TYPE_RAW:
+		return armpmu_map_raw_event(raw_event_mask, config);
+	}
+
+	return -ENOENT;
+}
+
+int
 armpmu_event_set_period(struct perf_event *event,
 			struct hw_perf_event *hwc,
 			int idx)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	s64 left = local64_read(&hwc->period_left);
 	s64 period = hwc->sample_period;
 	int ret = 0;
@@ -202,11 +184,12 @@ armpmu_event_set_period(struct perf_even
 	return ret;
 }
 
-static u64
+u64
 armpmu_event_update(struct perf_event *event,
 		    struct hw_perf_event *hwc,
 		    int idx, int overflow)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	u64 delta, prev_raw_count, new_raw_count;
 
 again:
@@ -246,11 +229,9 @@ armpmu_read(struct perf_event *event)
 static void
 armpmu_stop(struct perf_event *event, int flags)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 
-	if (!armpmu)
-		return;
-
 	/*
 	 * ARM pmu always has to update the counter, so ignore
 	 * PERF_EF_UPDATE, see comments in armpmu_start().
@@ -266,11 +247,9 @@ armpmu_stop(struct perf_event *event, in
 static void
 armpmu_start(struct perf_event *event, int flags)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 
-	if (!armpmu)
-		return;
-
 	/*
 	 * ARM pmu always has to reprogram the period, so ignore
 	 * PERF_EF_RELOAD, see the comment below.
@@ -293,16 +272,16 @@ armpmu_start(struct perf_event *event, i
 static void
 armpmu_del(struct perf_event *event, int flags)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
 	WARN_ON(idx < 0);
 
-	clear_bit(idx, cpuc->active_mask);
 	armpmu_stop(event, PERF_EF_UPDATE);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
+	hw_events->events[idx] = NULL;
+	clear_bit(idx, hw_events->used_mask);
 
 	perf_event_update_userpage(event);
 }
@@ -310,7 +289,8 @@ armpmu_del(struct perf_event *event, int
 static int
 armpmu_add(struct perf_event *event, int flags)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
 	struct hw_perf_event *hwc = &event->hw;
 	int idx;
 	int err = 0;
@@ -318,7 +298,7 @@ armpmu_add(struct perf_event *event, int
 	perf_pmu_disable(event->pmu);
 
 	/* If we don't have a space for the counter then finish early. */
-	idx = armpmu->get_event_idx(cpuc, hwc);
+	idx = armpmu->get_event_idx(hw_events, hwc);
 	if (idx < 0) {
 		err = idx;
 		goto out;
@@ -330,8 +310,7 @@ armpmu_add(struct perf_event *event, int
 	 */
 	event->hw.idx = idx;
 	armpmu->disable(hwc, idx);
-	cpuc->events[idx] = event;
-	set_bit(idx, cpuc->active_mask);
+	hw_events->events[idx] = event;
 
 	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	if (flags & PERF_EF_START)
@@ -345,148 +324,166 @@ out:
 	return err;
 }
 
-static struct pmu pmu;
-
 static int
-validate_event(struct cpu_hw_events *cpuc,
+validate_event(struct pmu_hw_events *hw_events,
 	       struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event fake_event = event->hw;
+	struct pmu *leader_pmu = event->group_leader->pmu;
 
-	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
 		return 1;
 
-	return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
+	return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
 }
 
 static int
 validate_group(struct perf_event *event)
 {
 	struct perf_event *sibling, *leader = event->group_leader;
-	struct cpu_hw_events fake_pmu;
+	struct pmu_hw_events fake_pmu;
+	DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
 
-	memset(&fake_pmu, 0, sizeof(fake_pmu));
+	/*
+	 * Initialise the fake PMU. We only need to populate the
+	 * used_mask for the purposes of validation.
+	 */
+	memset(fake_used_mask, 0, sizeof(fake_used_mask));
+	fake_pmu.used_mask = fake_used_mask;
 
 	if (!validate_event(&fake_pmu, leader))
-		return -ENOSPC;
+		return -EINVAL;
 
 	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
 		if (!validate_event(&fake_pmu, sibling))
-			return -ENOSPC;
+			return -EINVAL;
 	}
 
 	if (!validate_event(&fake_pmu, event))
-		return -ENOSPC;
+		return -EINVAL;
 
 	return 0;
 }
 
 static irqreturn_t armpmu_platform_irq(int irq, void *dev)
 {
-	struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+	struct arm_pmu *armpmu = (struct arm_pmu *) dev;
+	struct platform_device *plat_device = armpmu->plat_device;
+	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
 
 	return plat->handle_irq(irq, dev, armpmu->handle_irq);
 }
 
+static void
+armpmu_release_hardware(struct arm_pmu *armpmu)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, armpmu);
+	}
+
+	release_pmu(armpmu->type);
+}
+
 static int
-armpmu_reserve_hardware(void)
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
 {
 	struct arm_pmu_platdata *plat;
 	irq_handler_t handle_irq;
-	int i, err = -ENODEV, irq;
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
 
-	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
-	if (IS_ERR(pmu_device)) {
+	if (!pmu_device)
+		return -ENODEV;
+
+	err = reserve_pmu(armpmu->type);
+	if (err) {
 		pr_warning("unable to reserve pmu\n");
-		return PTR_ERR(pmu_device);
+		return err;
 	}
 
-	init_pmu(ARM_PMU_DEVICE_CPU);
-
 	plat = dev_get_platdata(&pmu_device->dev);
 	if (plat && plat->handle_irq)
 		handle_irq = armpmu_platform_irq;
 	else
 		handle_irq = armpmu->handle_irq;
 
-	if (pmu_device->num_resources < 1) {
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
 		pr_err("no irqs for PMUs defined\n");
 		return -ENODEV;
 	}
 
-	for (i = 0; i < pmu_device->num_resources; ++i) {
+	for (i = 0; i < irqs; ++i) {
+		err = 0;
 		irq = platform_get_irq(pmu_device, i);
 		if (irq < 0)
 			continue;
 
+		/*
+		 * If we have a single PMU interrupt that we can't shift,
+		 * assume that we're running on a uniprocessor machine and
+		 * continue. Otherwise, continue without this interrupt.
+		 */
+		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+				    irq, i);
+			continue;
+		}
+
 		err = request_irq(irq, handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "armpmu", NULL);
+				  "arm-pmu", armpmu);
 		if (err) {
-			pr_warning("unable to request IRQ%d for ARM perf "
-				"counters\n", irq);
-			break;
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			armpmu_release_hardware(armpmu);
+			return err;
 		}
-	}
 
-	if (err) {
-		for (i = i - 1; i >= 0; --i) {
-			irq = platform_get_irq(pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
-		}
-		release_pmu(ARM_PMU_DEVICE_CPU);
-		pmu_device = NULL;
+		cpumask_set_cpu(i, &armpmu->active_irqs);
 	}
 
-	return err;
+	return 0;
 }
 
 static void
-armpmu_release_hardware(void)
+hw_perf_event_destroy(struct perf_event *event)
 {
-	int i, irq;
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	atomic_t *active_events	 = &armpmu->active_events;
+	struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
 
-	for (i = pmu_device->num_resources - 1; i >= 0; --i) {
-		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, NULL);
+	if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
+		armpmu_release_hardware(armpmu);
+		mutex_unlock(pmu_reserve_mutex);
 	}
-	armpmu->stop();
-
-	release_pmu(ARM_PMU_DEVICE_CPU);
-	pmu_device = NULL;
 }
 
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-
-static void
-hw_perf_event_destroy(struct perf_event *event)
+static int
+event_requires_mode_exclusion(struct perf_event_attr *attr)
 {
-	if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
-		armpmu_release_hardware();
-		mutex_unlock(&pmu_reserve_mutex);
-	}
+	return attr->exclude_idle || attr->exclude_user ||
+	       attr->exclude_kernel || attr->exclude_hv;
 }
 
 static int
 __hw_perf_event_init(struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 	int mapping, err;
 
-	/* Decode the generic type into an ARM event identifier. */
-	if (PERF_TYPE_HARDWARE == event->attr.type) {
-		mapping = armpmu_map_event(event->attr.config);
-	} else if (PERF_TYPE_HW_CACHE == event->attr.type) {
-		mapping = armpmu_map_cache_event(event->attr.config);
-	} else if (PERF_TYPE_RAW == event->attr.type) {
-		mapping = armpmu_map_raw_event(event->attr.config);
-	} else {
-		pr_debug("event type %x not supported\n", event->attr.type);
-		return -EOPNOTSUPP;
-	}
+	mapping = armpmu->map_event(event);
 
 	if (mapping < 0) {
 		pr_debug("event %x:%llx not supported\n", event->attr.type,
@@ -495,34 +492,31 @@ __hw_perf_event_init(struct perf_event *
 	}
 
 	/*
+	 * We don't assign an index until we actually place the event onto
+	 * hardware. Use -1 to signify that we haven't decided where to put it
+	 * yet. For SMP systems, each core has it's own PMU so we can't do any
+	 * clever allocation or constraints checking at this point.
+	 */
+	hwc->idx		= -1;
+	hwc->config_base	= 0;
+	hwc->config		= 0;
+	hwc->event_base		= 0;
+
+	/*
 	 * Check whether we need to exclude the counter from certain modes.
-	 * The ARM performance counters are on all of the time so if someone
-	 * has asked us for some excludes then we have to fail.
 	 */
-	if (event->attr.exclude_kernel || event->attr.exclude_user ||
-	    event->attr.exclude_hv || event->attr.exclude_idle) {
+	if ((!armpmu->set_event_filter ||
+	     armpmu->set_event_filter(hwc, &event->attr)) &&
+	     event_requires_mode_exclusion(&event->attr)) {
 		pr_debug("ARM performance counters do not support "
 			 "mode exclusion\n");
 		return -EPERM;
 	}
 
 	/*
-	 * We don't assign an index until we actually place the event onto
-	 * hardware. Use -1 to signify that we haven't decided where to put it
-	 * yet. For SMP systems, each core has it's own PMU so we can't do any
-	 * clever allocation or constraints checking at this point.
-	 */
-	hwc->idx = -1;
-
-	/*
-	 * Store the event encoding into the config_base field. config and
-	 * event_base are unused as the only 2 things we need to know are
-	 * the event mapping and the counter to use. The counter to use is
-	 * also the indx and the config_base is the event type.
+	 * Store the event encoding into the config_base field.
 	 */
-	hwc->config_base	    = (unsigned long)mapping;
-	hwc->config		    = 0;
-	hwc->event_base		    = 0;
+	hwc->config_base	    |= (unsigned long)mapping;
 
 	if (!hwc->sample_period) {
 		hwc->sample_period  = armpmu->max_period;
@@ -542,32 +536,23 @@ __hw_perf_event_init(struct perf_event *
 
 static int armpmu_event_init(struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	int err = 0;
+	atomic_t *active_events = &armpmu->active_events;
 
-	switch (event->attr.type) {
-	case PERF_TYPE_RAW:
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-		break;
-
-	default:
+	if (armpmu->map_event(event) == -ENOENT)
 		return -ENOENT;
-	}
-
-	if (!armpmu)
-		return -ENODEV;
 
 	event->destroy = hw_perf_event_destroy;
 
-	if (!atomic_inc_not_zero(&active_events)) {
-		mutex_lock(&pmu_reserve_mutex);
-		if (atomic_read(&active_events) == 0) {
-			err = armpmu_reserve_hardware();
-		}
+	if (!atomic_inc_not_zero(active_events)) {
+		mutex_lock(&armpmu->reserve_mutex);
+		if (atomic_read(active_events) == 0)
+			err = armpmu_reserve_hardware(armpmu);
 
 		if (!err)
-			atomic_inc(&active_events);
-		mutex_unlock(&pmu_reserve_mutex);
+			atomic_inc(active_events);
+		mutex_unlock(&armpmu->reserve_mutex);
 	}
 
 	if (err)
@@ -582,22 +567,9 @@ static int armpmu_event_init(struct perf
 
 static void armpmu_enable(struct pmu *pmu)
 {
-	/* Enable all of the perf events on hardware. */
-	int idx, enabled = 0;
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
-	if (!armpmu)
-		return;
-
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
-		struct perf_event *event = cpuc->events[idx];
-
-		if (!event)
-			continue;
-
-		armpmu->enable(&event->hw, idx);
-		enabled = 1;
-	}
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
 	if (enabled)
 		armpmu->start();
@@ -605,20 +577,32 @@ static void armpmu_enable(struct pmu *pm
 
 static void armpmu_disable(struct pmu *pmu)
 {
-	if (armpmu)
-		armpmu->stop();
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	armpmu->stop();
 }
 
-static struct pmu pmu = {
-	.pmu_enable	= armpmu_enable,
-	.pmu_disable	= armpmu_disable,
-	.event_init	= armpmu_event_init,
-	.add		= armpmu_add,
-	.del		= armpmu_del,
-	.start		= armpmu_start,
-	.stop		= armpmu_stop,
-	.read		= armpmu_read,
-};
+static void __init armpmu_init(struct arm_pmu *armpmu)
+{
+	atomic_set(&armpmu->active_events, 0);
+	mutex_init(&armpmu->reserve_mutex);
+
+	armpmu->pmu = (struct pmu) {
+		.pmu_enable	= armpmu_enable,
+		.pmu_disable	= armpmu_disable,
+		.event_init	= armpmu_event_init,
+		.add		= armpmu_add,
+		.del		= armpmu_del,
+		.start		= armpmu_start,
+		.stop		= armpmu_stop,
+		.read		= armpmu_read,
+	};
+}
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+	armpmu_init(armpmu);
+	return perf_pmu_register(&armpmu->pmu, name, type);
+}
 
 /* Include the PMU-specific implementations. */
 #include "perf_event_xscale.c"
@@ -630,14 +614,75 @@ static struct pmu pmu = {
  * This requires SMP to be available, so exists as a separate initcall.
  */
 static int __init
-armpmu_reset(void)
+cpu_pmu_reset(void)
 {
-	if (armpmu && armpmu->reset)
-		return on_each_cpu(armpmu->reset, NULL, 1);
+	if (cpu_pmu && cpu_pmu->reset)
+		return on_each_cpu(cpu_pmu->reset, NULL, 1);
 	return 0;
 }
-arch_initcall(armpmu_reset);
+arch_initcall(cpu_pmu_reset);
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id armpmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a9-pmu"},
+	{.compatible = "arm,cortex-a8-pmu"},
+	{.compatible = "arm,arm1136-pmu"},
+	{.compatible = "arm,arm1176-pmu"},
+	{},
+};
+
+static struct platform_device_id armpmu_plat_device_ids[] = {
+	{.name = "arm-pmu"},
+	{},
+};
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
+{
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	return 0;
+}
+
+static struct platform_driver armpmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.of_match_table = armpmu_of_device_ids,
+	},
+	.probe		= armpmu_device_probe,
+	.id_table	= armpmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&armpmu_driver);
+}
+device_initcall(register_pmu_driver);
+
+static struct pmu_hw_events *armpmu_get_cpu_events(void)
+{
+	return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+		events->events = per_cpu(hw_events, cpu);
+		events->used_mask = per_cpu(used_mask, cpu);
+		raw_spin_lock_init(&events->pmu_lock);
+	}
+	armpmu->get_hw_events = armpmu_get_cpu_events;
+	armpmu->type = ARM_PMU_DEVICE_CPU;
+}
 
+/*
+ * CPU PMU identification and registration.
+ */
 static int __init
 init_hw_perf_events(void)
 {
@@ -651,22 +696,22 @@ init_hw_perf_events(void)
 		case 0xB360:	/* ARM1136 */
 		case 0xB560:	/* ARM1156 */
 		case 0xB760:	/* ARM1176 */
-			armpmu = armv6pmu_init();
+			cpu_pmu = armv6pmu_init();
 			break;
 		case 0xB020:	/* ARM11mpcore */
-			armpmu = armv6mpcore_pmu_init();
+			cpu_pmu = armv6mpcore_pmu_init();
 			break;
 		case 0xC080:	/* Cortex-A8 */
-			armpmu = armv7_a8_pmu_init();
+			cpu_pmu = armv7_a8_pmu_init();
 			break;
 		case 0xC090:	/* Cortex-A9 */
-			armpmu = armv7_a9_pmu_init();
+			cpu_pmu = armv7_a9_pmu_init();
 			break;
 		case 0xC050:	/* Cortex-A5 */
-			armpmu = armv7_a5_pmu_init();
+			cpu_pmu = armv7_a5_pmu_init();
 			break;
 		case 0xC0F0:	/* Cortex-A15 */
-			armpmu = armv7_a15_pmu_init();
+			cpu_pmu = armv7_a15_pmu_init();
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -674,23 +719,23 @@ init_hw_perf_events(void)
 		part_number = (cpuid >> 13) & 0x7;
 		switch (part_number) {
 		case 1:
-			armpmu = xscale1pmu_init();
+			cpu_pmu = xscale1pmu_init();
 			break;
 		case 2:
-			armpmu = xscale2pmu_init();
+			cpu_pmu = xscale2pmu_init();
 			break;
 		}
 	}
 
-	if (armpmu) {
+	if (cpu_pmu) {
 		pr_info("enabled with %s PMU driver, %d counters available\n",
-			armpmu->name, armpmu->num_events);
+			cpu_pmu->name, cpu_pmu->num_events);
+		cpu_pmu_init(cpu_pmu);
+		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
 	} else {
 		pr_info("no hardware support available\n");
 	}
 
-	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
-
 	return 0;
 }
 early_initcall(init_hw_perf_events);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_v6.c linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_v6.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_v6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_v6.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,7 @@ enum armv6_perf_types {
 };
 
 enum armv6_counters {
-	ARMV6_CYCLE_COUNTER = 1,
+	ARMV6_CYCLE_COUNTER = 0,
 	ARMV6_COUNTER0,
 	ARMV6_COUNTER1,
 };
@@ -433,6 +433,7 @@ armv6pmu_enable_event(struct hw_perf_eve
 		      int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= 0;
@@ -454,12 +455,29 @@ armv6pmu_enable_event(struct hw_perf_eve
 	 * Mask out the current event and set the counter to count the event
 	 * that we're interested in.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int counter_is_active(unsigned long pmcr, int idx)
+{
+	unsigned long mask = 0;
+	if (idx == ARMV6_CYCLE_COUNTER)
+		mask = ARMV6_PMCR_CCOUNT_IEN;
+	else if (idx == ARMV6_COUNTER0)
+		mask = ARMV6_PMCR_COUNT0_IEN;
+	else if (idx == ARMV6_COUNTER1)
+		mask = ARMV6_PMCR_COUNT1_IEN;
+
+	if (mask)
+		return pmcr & mask;
+
+	WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+	return 0;
 }
 
 static irqreturn_t
@@ -468,7 +486,7 @@ armv6pmu_handle_irq(int irq_num,
 {
 	unsigned long pmcr = armv6_pmcr_read();
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -487,11 +505,11 @@ armv6pmu_handle_irq(int irq_num,
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
+		if (!counter_is_active(pmcr, idx))
 			continue;
 
 		/*
@@ -508,7 +526,7 @@ armv6pmu_handle_irq(int irq_num,
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	/*
@@ -527,28 +545,30 @@ static void
 armv6pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val |= ARMV6_PMCR_ENABLE;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 armv6pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~ARMV6_PMCR_ENABLE;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
 		       struct hw_perf_event *event)
 {
 	/* Always place a cycle counter into the cycle counter. */
@@ -578,6 +598,7 @@ armv6pmu_disable_event(struct hw_perf_ev
 		       int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -598,12 +619,12 @@ armv6pmu_disable_event(struct hw_perf_ev
 	 * of ETM bus signal assertion cycles. The external reporting should
 	 * be disabled and so this should never increment.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
@@ -611,6 +632,7 @@ armv6mpcore_pmu_disable_event(struct hw_
 			      int idx)
 {
 	unsigned long val, mask, flags, evt = 0;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -627,15 +649,21 @@ armv6mpcore_pmu_disable_event(struct hw_
 	 * Unlike UP ARMv6, we don't have a way of stopping the counters. We
 	 * simply disable the interrupt reporting.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static const struct arm_pmu armv6pmu = {
+static int armv6_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv6_perf_map,
+				&armv6_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6pmu = {
 	.id			= ARM_PERF_PMU_ID_V6,
 	.name			= "v6",
 	.handle_irq		= armv6pmu_handle_irq,
@@ -646,14 +674,12 @@ static const struct arm_pmu armv6pmu = {
 	.get_event_idx		= armv6pmu_get_event_idx,
 	.start			= armv6pmu_start,
 	.stop			= armv6pmu_stop,
-	.cache_map		= &armv6_perf_cache_map,
-	.event_map		= &armv6_perf_map,
-	.raw_event_mask		= 0xFF,
+	.map_event		= armv6_map_event,
 	.num_events		= 3,
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
 	return &armv6pmu;
 }
@@ -665,7 +691,14 @@ static const struct arm_pmu *__init armv
  * disable the interrupt reporting and update the event. When unthrottling we
  * reset the period and enable the interrupt reporting.
  */
-static const struct arm_pmu armv6mpcore_pmu = {
+
+static int armv6mpcore_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv6mpcore_perf_map,
+				&armv6mpcore_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6mpcore_pmu = {
 	.id			= ARM_PERF_PMU_ID_V6MP,
 	.name			= "v6mpcore",
 	.handle_irq		= armv6pmu_handle_irq,
@@ -676,24 +709,22 @@ static const struct arm_pmu armv6mpcore_
 	.get_event_idx		= armv6pmu_get_event_idx,
 	.start			= armv6pmu_start,
 	.stop			= armv6pmu_stop,
-	.cache_map		= &armv6mpcore_perf_cache_map,
-	.event_map		= &armv6mpcore_perf_map,
-	.raw_event_mask		= 0xFF,
+	.map_event		= armv6mpcore_map_event,
 	.num_events		= 3,
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
 	return &armv6mpcore_pmu;
 }
 #else
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
 	return NULL;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_v7.c linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_v7.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_v7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_v7.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,9 @@
  */
 
 #ifdef CONFIG_CPU_V7
+
+static struct arm_pmu armv7pmu;
+
 /*
  * Common ARMv7 event types
  *
@@ -676,23 +679,24 @@ static const unsigned armv7_a15_perf_cac
 };
 
 /*
- * Perf Events counters
+ * Perf Events' indices
  */
-enum armv7_counters {
-	ARMV7_CYCLE_COUNTER		= 1,	/* Cycle counter */
-	ARMV7_COUNTER0			= 2,	/* First event counter */
-};
+#define	ARMV7_IDX_CYCLE_COUNTER	0
+#define	ARMV7_IDX_COUNTER0	1
+#define	ARMV7_IDX_COUNTER_LAST	(ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+
+#define	ARMV7_MAX_COUNTERS	32
+#define	ARMV7_COUNTER_MASK	(ARMV7_MAX_COUNTERS - 1)
 
 /*
- * The cycle counter is ARMV7_CYCLE_COUNTER.
- * The first event counter is ARMV7_COUNTER0.
- * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ * ARMv7 low level PMNC access
  */
-#define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1)
 
 /*
- * ARMv7 low level PMNC access
+ * Perf Event to low level counters mapping
  */
+#define	ARMV7_IDX_TO_COUNTER(x)	\
+	(((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK)
 
 /*
  * Per-CPU PMNC: config reg
@@ -708,103 +712,76 @@ enum armv7_counters {
 #define	ARMV7_PMNC_MASK		0x3f	 /* Mask for writable bits */
 
 /*
- * Available counters
- */
-#define ARMV7_CNT0		0	/* First event counter */
-#define ARMV7_CCNT		31	/* Cycle counter */
-
-/* Perf Event to low level counters mapping */
-#define ARMV7_EVENT_CNT_TO_CNTx	(ARMV7_COUNTER0 - ARMV7_CNT0)
-
-/*
- * CNTENS: counters enable reg
- */
-#define ARMV7_CNTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENS_C		(1 << ARMV7_CCNT)
-
-/*
- * CNTENC: counters disable reg
- */
-#define ARMV7_CNTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENC_C		(1 << ARMV7_CCNT)
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define ARMV7_INTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENS_C		(1 << ARMV7_CCNT)
-
-/*
- * INTENC: counters overflow interrupt disable reg
- */
-#define ARMV7_INTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENC_C		(1 << ARMV7_CCNT)
-
-/*
- * EVTSEL: Event selection reg
+ * FLAG: counters overflow flag status reg
  */
-#define	ARMV7_EVTSEL_MASK	0xff		/* Mask for writable bits */
+#define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */
+#define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK
 
 /*
- * SELECT: Counter selection reg
+ * PMXEVTYPER: Event selection reg
  */
-#define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */
+#define	ARMV7_EVTYPE_MASK	0xc00000ff	/* Mask for writable bits */
+#define	ARMV7_EVTYPE_EVENT	0xff		/* Mask for EVENT bits */
 
 /*
- * FLAG: counters overflow flag status reg
+ * Event filters for PMUv2
  */
-#define ARMV7_FLAG_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_FLAG_C		(1 << ARMV7_CCNT)
-#define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */
-#define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK
+#define	ARMV7_EXCLUDE_PL1	(1 << 31)
+#define	ARMV7_EXCLUDE_USER	(1 << 30)
+#define	ARMV7_INCLUDE_HYP	(1 << 27)
 
-static inline unsigned long armv7_pmnc_read(void)
+static inline u32 armv7_pmnc_read(void)
 {
 	u32 val;
 	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
 	return val;
 }
 
-static inline void armv7_pmnc_write(unsigned long val)
+static inline void armv7_pmnc_write(u32 val)
 {
 	val &= ARMV7_PMNC_MASK;
 	isb();
 	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
 }
 
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+static inline int armv7_pmnc_has_overflowed(u32 pmnc)
 {
 	return pmnc & ARMV7_OVERFLOWED_MASK;
 }
 
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
-					enum armv7_counters counter)
+static inline int armv7_pmnc_counter_valid(int idx)
+{
+	return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
 {
 	int ret = 0;
+	u32 counter;
 
-	if (counter == ARMV7_CYCLE_COUNTER)
-		ret = pmnc & ARMV7_FLAG_C;
-	else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
-		ret = pmnc & ARMV7_FLAG_P(counter);
-	else
+	if (!armv7_pmnc_counter_valid(idx)) {
 		pr_err("CPU%u checking wrong counter %d overflow status\n",
-			smp_processor_id(), counter);
+			smp_processor_id(), idx);
+	} else {
+		counter = ARMV7_IDX_TO_COUNTER(idx);
+		ret = pmnc & BIT(counter);
+	}
 
 	return ret;
 }
 
-static inline int armv7_pmnc_select_counter(unsigned int idx)
+static inline int armv7_pmnc_select_counter(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
-		pr_err("CPU%u selecting wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u selecting wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
-	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
 	isb();
 
 	return idx;
@@ -812,124 +789,95 @@ static inline int armv7_pmnc_select_coun
 
 static inline u32 armv7pmu_read_counter(int idx)
 {
-	unsigned long value = 0;
+	u32 value = 0;
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
-	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-		if (armv7_pmnc_select_counter(idx) == idx)
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-				     : "=r" (value));
-	} else
+	if (!armv7_pmnc_counter_valid(idx))
 		pr_err("CPU%u reading wrong counter %d\n",
 			smp_processor_id(), idx);
+	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+	else if (armv7_pmnc_select_counter(idx) == idx)
+		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value));
 
 	return value;
 }
 
 static inline void armv7pmu_write_counter(int idx, u32 value)
 {
-	if (idx == ARMV7_CYCLE_COUNTER)
-		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
-	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-		if (armv7_pmnc_select_counter(idx) == idx)
-			asm volatile("mcr p15, 0, %0, c9, c13, 2"
-				     : : "r" (value));
-	} else
+	if (!armv7_pmnc_counter_valid(idx))
 		pr_err("CPU%u writing wrong counter %d\n",
 			smp_processor_id(), idx);
+	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+	else if (armv7_pmnc_select_counter(idx) == idx)
+		asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
 }
 
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 {
 	if (armv7_pmnc_select_counter(idx) == idx) {
-		val &= ARMV7_EVTSEL_MASK;
+		val &= ARMV7_EVTYPE_MASK;
 		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
 	}
 }
 
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+static inline int armv7_pmnc_enable_counter(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u enabling wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_CNTENS_C;
-	else
-		val = ARMV7_CNTENS_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+static inline int armv7_pmnc_disable_counter(int idx)
 {
-	u32 val;
-
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u disabling wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_CNTENC_C;
-	else
-		val = ARMV7_CNTENC_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+static inline int armv7_pmnc_enable_intens(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u enabling wrong PMNC counter"
-			" interrupt enable %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_INTENS_C;
-	else
-		val = ARMV7_INTENS_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+static inline int armv7_pmnc_disable_intens(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u disabling wrong PMNC counter"
-			" interrupt enable %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_INTENC_C;
-	else
-		val = ARMV7_INTENC_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
 	return idx;
 }
 
@@ -973,14 +921,14 @@ static void armv7_pmnc_dump_regs(void)
 	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
 	printk(KERN_INFO "CCNT  =0x%08x\n", val);
 
-	for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+	for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
 		armv7_pmnc_select_counter(cnt);
 		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
 		printk(KERN_INFO "CNT[%d] count =0x%08x\n",
-			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+			ARMV7_IDX_TO_COUNTER(cnt), val);
 		asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
 		printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
-			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+			ARMV7_IDX_TO_COUNTER(cnt), val);
 	}
 }
 #endif
@@ -988,12 +936,13 @@ static void armv7_pmnc_dump_regs(void)
 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
 	 * the event that we're interested in.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/*
 	 * Disable counter
@@ -1002,9 +951,10 @@ static void armv7pmu_enable_event(struct
 
 	/*
 	 * Set event (if destined for PMNx counters)
-	 * We don't need to set the event if it's a cycle count
+	 * We only need to set the event for the cycle counter if we
+	 * have the ability to perform event filtering.
 	 */
-	if (idx != ARMV7_CYCLE_COUNTER)
+	if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
 		armv7_pmnc_write_evtsel(idx, hwc->config_base);
 
 	/*
@@ -1017,17 +967,18 @@ static void armv7pmu_enable_event(struct
 	 */
 	armv7_pmnc_enable_counter(idx);
 
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
 	 * Disable counter and interrupt
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/*
 	 * Disable counter
@@ -1039,14 +990,14 @@ static void armv7pmu_disable_event(struc
 	 */
 	armv7_pmnc_disable_intens(idx);
 
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 {
-	unsigned long pmnc;
+	u32 pmnc;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -1069,13 +1020,10 @@ static irqreturn_t armv7pmu_handle_irq(i
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		/*
 		 * We have a single interrupt for all counters. Check that
 		 * each counter has overflowed before we process it.
@@ -1090,7 +1038,7 @@ static irqreturn_t armv7pmu_handle_irq(i
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	/*
@@ -1108,61 +1056,114 @@ static irqreturn_t armv7pmu_handle_irq(i
 static void armv7pmu_start(void)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	/* Enable all counters */
 	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_stop(void)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	/* Disable all counters */
 	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
 				  struct hw_perf_event *event)
 {
 	int idx;
+	unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
 
 	/* Always place a cycle counter into the cycle counter. */
-	if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
-		if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+	if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
+		if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask))
 			return -EAGAIN;
 
-		return ARMV7_CYCLE_COUNTER;
-	} else {
-		/*
-		 * For anything other than a cycle counter, try and use
-		 * the events counters
-		 */
-		for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
-			if (!test_and_set_bit(idx, cpuc->used_mask))
-				return idx;
-		}
+		return ARMV7_IDX_CYCLE_COUNTER;
+	}
 
-		/* The counters are all in use. */
-		return -EAGAIN;
+	/*
+	 * For anything other than a cycle counter, try and use
+	 * the events counters
+	 */
+	for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
+		if (!test_and_set_bit(idx, cpuc->used_mask))
+			return idx;
 	}
+
+	/* The counters are all in use. */
+	return -EAGAIN;
+}
+
+/*
+ * Add an event filter to a given event. This will only work for PMUv2 PMUs.
+ */
+static int armv7pmu_set_event_filter(struct hw_perf_event *event,
+				     struct perf_event_attr *attr)
+{
+	unsigned long config_base = 0;
+
+	if (attr->exclude_idle)
+		return -EPERM;
+	if (attr->exclude_user)
+		config_base |= ARMV7_EXCLUDE_USER;
+	if (attr->exclude_kernel)
+		config_base |= ARMV7_EXCLUDE_PL1;
+	if (!attr->exclude_hv)
+		config_base |= ARMV7_INCLUDE_HYP;
+
+	/*
+	 * Install the filter into config_base as this is used to
+	 * construct the event type.
+	 */
+	event->config_base = config_base;
+
+	return 0;
 }
 
 static void armv7pmu_reset(void *info)
 {
-	u32 idx, nb_cnt = armpmu->num_events;
+	u32 idx, nb_cnt = cpu_pmu->num_events;
 
 	/* The counter and interrupt enable registers are unknown at reset. */
-	for (idx = 1; idx < nb_cnt; ++idx)
+	for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
 		armv7pmu_disable_event(NULL, idx);
 
 	/* Initialize & Reset PMNC: C and P bits */
 	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
 }
 
+static int armv7_a8_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a8_perf_map,
+				&armv7_a8_perf_cache_map, 0xFF);
+}
+
+static int armv7_a9_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a9_perf_map,
+				&armv7_a9_perf_cache_map, 0xFF);
+}
+
+static int armv7_a5_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a5_perf_map,
+				&armv7_a5_perf_cache_map, 0xFF);
+}
+
+static int armv7_a15_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a15_perf_map,
+				&armv7_a15_perf_cache_map, 0xFF);
+}
+
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= armv7pmu_enable_event,
@@ -1173,7 +1174,6 @@ static struct arm_pmu armv7pmu = {
 	.start			= armv7pmu_start,
 	.stop			= armv7pmu_stop,
 	.reset			= armv7pmu_reset,
-	.raw_event_mask		= 0xFF,
 	.max_period		= (1LLU << 32) - 1,
 };
 
@@ -1188,62 +1188,59 @@ static u32 __init armv7_read_num_pmnc_ev
 	return nb_cnt + 1;
 }
 
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA8;
 	armv7pmu.name		= "ARMv7 Cortex-A8";
-	armv7pmu.cache_map	= &armv7_a8_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a8_perf_map;
+	armv7pmu.map_event	= armv7_a8_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA9;
 	armv7pmu.name		= "ARMv7 Cortex-A9";
-	armv7pmu.cache_map	= &armv7_a9_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a9_perf_map;
+	armv7pmu.map_event	= armv7_a9_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA5;
 	armv7pmu.name		= "ARMv7 Cortex-A5";
-	armv7pmu.cache_map	= &armv7_a5_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a5_perf_map;
+	armv7pmu.map_event	= armv7_a5_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA15;
 	armv7pmu.name		= "ARMv7 Cortex-A15";
-	armv7pmu.cache_map	= &armv7_a15_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a15_perf_map;
+	armv7pmu.map_event	= armv7_a15_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	armv7pmu.set_event_filter = armv7pmu_set_event_filter;
 	return &armv7pmu;
 }
 #else
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
 	return NULL;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_xscale.c linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_xscale.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/perf_event_xscale.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/perf_event_xscale.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,7 @@ enum xscale_perf_types {
 };
 
 enum xscale_counters {
-	XSCALE_CYCLE_COUNTER	= 1,
+	XSCALE_CYCLE_COUNTER	= 0,
 	XSCALE_COUNTER0,
 	XSCALE_COUNTER1,
 	XSCALE_COUNTER2,
@@ -222,7 +222,7 @@ xscale1pmu_handle_irq(int irq_num, void
 {
 	unsigned long pmnc;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -249,13 +249,10 @@ xscale1pmu_handle_irq(int irq_num, void
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
 			continue;
 
@@ -266,7 +263,7 @@ xscale1pmu_handle_irq(int irq_num, void
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	irq_work_run();
@@ -284,6 +281,7 @@ static void
 xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -305,18 +303,19 @@ xscale1pmu_enable_event(struct hw_perf_e
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~mask;
 	val |= evt;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -336,16 +335,16 @@ xscale1pmu_disable_event(struct hw_perf_
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~mask;
 	val |= evt;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
 			struct hw_perf_event *event)
 {
 	if (XSCALE_PERFCTR_CCNT == event->config_base) {
@@ -368,24 +367,26 @@ static void
 xscale1pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val |= XSCALE_PMU_ENABLE;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~XSCALE_PMU_ENABLE;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -424,7 +425,13 @@ xscale1pmu_write_counter(int counter, u3
 	}
 }
 
-static const struct arm_pmu xscale1pmu = {
+static int xscale_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &xscale_perf_map,
+				&xscale_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu xscale1pmu = {
 	.id		= ARM_PERF_PMU_ID_XSCALE1,
 	.name		= "xscale1",
 	.handle_irq	= xscale1pmu_handle_irq,
@@ -435,14 +442,12 @@ static const struct arm_pmu xscale1pmu =
 	.get_event_idx	= xscale1pmu_get_event_idx,
 	.start		= xscale1pmu_start,
 	.stop		= xscale1pmu_stop,
-	.cache_map	= &xscale_perf_cache_map,
-	.event_map	= &xscale_perf_map,
-	.raw_event_mask	= 0xFF,
+	.map_event	= xscale_map_event,
 	.num_events	= 3,
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
 	return &xscale1pmu;
 }
@@ -560,7 +565,7 @@ xscale2pmu_handle_irq(int irq_num, void
 {
 	unsigned long pmnc, of_flags;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -581,13 +586,10 @@ xscale2pmu_handle_irq(int irq_num, void
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
 			continue;
 
@@ -598,7 +600,7 @@ xscale2pmu_handle_irq(int irq_num, void
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	irq_work_run();
@@ -616,6 +618,7 @@ static void
 xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags, ien, evtsel;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -649,16 +652,17 @@ xscale2pmu_enable_event(struct hw_perf_e
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	xscale2pmu_write_event_select(evtsel);
 	xscale2pmu_write_int_enable(ien);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags, ien, evtsel;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -692,14 +696,14 @@ xscale2pmu_disable_event(struct hw_perf_
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	xscale2pmu_write_event_select(evtsel);
 	xscale2pmu_write_int_enable(ien);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
 			struct hw_perf_event *event)
 {
 	int idx = xscale1pmu_get_event_idx(cpuc, event);
@@ -718,24 +722,26 @@ static void
 xscale2pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
 	val |= XSCALE_PMU_ENABLE;
 	xscale2pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale2pmu_read_pmnc();
 	val &= ~XSCALE_PMU_ENABLE;
 	xscale2pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -786,7 +792,7 @@ xscale2pmu_write_counter(int counter, u3
 	}
 }
 
-static const struct arm_pmu xscale2pmu = {
+static struct arm_pmu xscale2pmu = {
 	.id		= ARM_PERF_PMU_ID_XSCALE2,
 	.name		= "xscale2",
 	.handle_irq	= xscale2pmu_handle_irq,
@@ -797,24 +803,22 @@ static const struct arm_pmu xscale2pmu =
 	.get_event_idx	= xscale2pmu_get_event_idx,
 	.start		= xscale2pmu_start,
 	.stop		= xscale2pmu_stop,
-	.cache_map	= &xscale_perf_cache_map,
-	.event_map	= &xscale_perf_map,
-	.raw_event_mask	= 0xFF,
+	.map_event	= xscale_map_event,
 	.num_events	= 5,
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
 	return &xscale2pmu;
 }
 #else
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
 	return NULL;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/pj4-cp0.c linux-libre-3.2-gnu1/arch/arm/kernel/pj4-cp0.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/pj4-cp0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/pj4-cp0.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/pmu.c linux-libre-3.2-gnu1/arch/arm/kernel/pmu.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,192 +10,27 @@
  *
  */
 
-#define pr_fmt(fmt) "PMU: " fmt
-
-#include <linux/cpumask.h>
 #include <linux/err.h>
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
 
 #include <asm/pmu.h>
 
-static volatile long pmu_lock;
-
-static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
-
-static int __devinit pmu_register(struct platform_device *pdev,
-					enum arm_pmu_type type)
-{
-	if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
-		pr_warning("received registration request for unknown "
-				"PMU device type %d\n", type);
-		return -EINVAL;
-	}
-
-	if (pmu_devices[type]) {
-		pr_warning("rejecting duplicate registration of PMU device "
-			"type %d.", type);
-		return -ENOSPC;
-	}
-
-	pr_info("registered new PMU device of type %d\n", type);
-	pmu_devices[type] = pdev;
-	return 0;
-}
-
-#define OF_MATCH_PMU(_name, _type) {	\
-	.compatible = _name,		\
-	.data = (void *)_type,		\
-}
-
-#define OF_MATCH_CPU(name)	OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)
-
-static struct of_device_id armpmu_of_device_ids[] = {
-	OF_MATCH_CPU("arm,cortex-a9-pmu"),
-	OF_MATCH_CPU("arm,cortex-a8-pmu"),
-	OF_MATCH_CPU("arm,arm1136-pmu"),
-	OF_MATCH_CPU("arm,arm1176-pmu"),
-	{},
-};
-
-#define PLAT_MATCH_PMU(_name, _type) {	\
-	.name		= _name,	\
-	.driver_data	= _type,	\
-}
-
-#define PLAT_MATCH_CPU(_name)	PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
-	PLAT_MATCH_CPU("arm-pmu"),
-	{},
-};
-
-enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)
-{
-	const struct of_device_id	*of_id;
-	const struct platform_device_id *pdev_id;
-
-	/* provided by of_device_id table */
-	if (pdev->dev.of_node) {
-		of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);
-		BUG_ON(!of_id);
-		return (enum arm_pmu_type)of_id->data;
-	}
-
-	/* Provided by platform_device_id table */
-	pdev_id = platform_get_device_id(pdev);
-	BUG_ON(!pdev_id);
-	return pdev_id->driver_data;
-}
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
-	return pmu_register(pdev, armpmu_device_type(pdev));
-}
-
-static struct platform_driver armpmu_driver = {
-	.driver		= {
-		.name	= "arm-pmu",
-		.of_match_table = armpmu_of_device_ids,
-	},
-	.probe		= armpmu_device_probe,
-	.id_table	= armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
+/*
+ * PMU locking to ensure mutual exclusion between different subsystems.
+ */
+static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
 
-struct platform_device *
+int
 reserve_pmu(enum arm_pmu_type type)
 {
-	struct platform_device *pdev;
-
-	if (test_and_set_bit_lock(type, &pmu_lock)) {
-		pdev = ERR_PTR(-EBUSY);
-	} else if (pmu_devices[type] == NULL) {
-		clear_bit_unlock(type, &pmu_lock);
-		pdev = ERR_PTR(-ENODEV);
-	} else {
-		pdev = pmu_devices[type];
-	}
-
-	return pdev;
+	return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
 }
 EXPORT_SYMBOL_GPL(reserve_pmu);
 
-int
+void
 release_pmu(enum arm_pmu_type type)
 {
-	if (WARN_ON(!pmu_devices[type]))
-		return -EINVAL;
-	clear_bit_unlock(type, &pmu_lock);
-	return 0;
+	clear_bit_unlock(type, pmu_lock);
 }
 EXPORT_SYMBOL_GPL(release_pmu);
-
-static int
-set_irq_affinity(int irq,
-		 unsigned int cpu)
-{
-#ifdef CONFIG_SMP
-	int err = irq_set_affinity(irq, cpumask_of(cpu));
-	if (err)
-		pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-			   irq, cpu);
-	return err;
-#else
-	return -EINVAL;
-#endif
-}
-
-static int
-init_cpu_pmu(void)
-{
-	int i, irqs, err = 0;
-	struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];
-
-	if (!pdev)
-		return -ENODEV;
-
-	irqs = pdev->num_resources;
-
-	/*
-	 * If we have a single PMU interrupt that we can't shift, assume that
-	 * we're running on a uniprocessor machine and continue.
-	 */
-	if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0)))
-		return 0;
-
-	for (i = 0; i < irqs; ++i) {
-		err = set_irq_affinity(platform_get_irq(pdev, i), i);
-		if (err)
-			break;
-	}
-
-	return err;
-}
-
-int
-init_pmu(enum arm_pmu_type type)
-{
-	int err = 0;
-
-	switch (type) {
-	case ARM_PMU_DEVICE_CPU:
-		err = init_cpu_pmu();
-		break;
-	default:
-		pr_warning("attempt to initialise PMU of unknown "
-			   "type %d\n", type);
-		err = -EINVAL;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(init_pmu);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/process.c linux-libre-3.2-gnu1/arch/arm/kernel/process.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  */
 #include <stdarg.h>
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -192,6 +192,9 @@ void cpu_idle(void)
 #endif
 
 			local_irq_disable();
+#ifdef CONFIG_PL310_ERRATA_769419
+			wmb();
+#endif
 			if (hlt_counter) {
 				local_irq_enable();
 				cpu_relax();
@@ -319,7 +322,7 @@ void show_regs(struct pt_regs * regs)
 	printk("\n");
 	printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
 	__show_regs(regs);
-	__backtrace();
+	dump_stack();
 }
 
 ATOMIC_NOTIFIER_HEAD(thread_notify_head);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/ptrace.c linux-libre-3.2-gnu1/arch/arm/kernel/ptrace.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/elf.h>
 #include <linux/smp.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/return_address.c linux-libre-3.2-gnu1/arch/arm/kernel/return_address.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/return_address.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/return_address.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/ftrace.h>
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/setup.c linux-libre-3.2-gnu1/arch/arm/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/ioport.h>
@@ -29,6 +29,8 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
+#include <linux/bug.h>
+#include <linux/compiler.h>
 
 #include <asm/unified.h>
 #include <asm/cpu.h>
@@ -42,6 +44,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/tlbflush.h>
+#include <asm/system.h>
 
 #include <asm/prom.h>
 #include <asm/mach/arch.h>
@@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __rea
 EXPORT_SYMBOL(outer_cache);
 #endif
 
+/*
+ * Cached cpu_architecture() result for use by assembler code.
+ * C code should use the cpu_architecture() function instead of accessing this
+ * variable directly.
+ */
+int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;
+
 struct stack {
 	u32 irq[3];
 	u32 abt[3];
@@ -210,7 +220,7 @@ static const char *proc_arch[] = {
 	"?(17)",
 };
 
-int cpu_architecture(void)
+static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
 
@@ -243,11 +253,22 @@ int cpu_architecture(void)
 	return cpu_arch;
 }
 
+int __pure cpu_architecture(void)
+{
+	BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN);
+
+	return __cpu_architecture;
+}
+
 static int cpu_has_aliasing_icache(unsigned int arch)
 {
 	int aliasing_icache;
 	unsigned int id_reg, num_sets, line_size;
 
+	/* PIPT caches never alias. */
+	if (icache_is_pipt())
+		return 0;
+
 	/* arch specifies the register format */
 	switch (arch) {
 	case CPU_ARCH_ARMv7:
@@ -282,8 +303,14 @@ static void __init cacheid_init(void)
 			/* ARMv7 register format */
 			arch = CPU_ARCH_ARMv7;
 			cacheid = CACHEID_VIPT_NONALIASING;
-			if ((cachetype & (3 << 14)) == 1 << 14)
+			switch (cachetype & (3 << 14)) {
+			case (1 << 14):
 				cacheid |= CACHEID_ASID_TAGGED;
+				break;
+			case (3 << 14):
+				cacheid |= CACHEID_PIPT;
+				break;
+			}
 		} else {
 			arch = CPU_ARCH_ARMv6;
 			if (cachetype & (1 << 23))
@@ -300,10 +327,11 @@ static void __init cacheid_init(void)
 	printk("CPU: %s data cache, %s instruction cache\n",
 		cache_is_vivt() ? "VIVT" :
 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
-		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
 		cache_is_vivt() ? "VIVT" :
 		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
 		icache_is_vipt_aliasing() ? "VIPT aliasing" :
+		icache_is_pipt() ? "PIPT" :
 		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 }
 
@@ -414,6 +442,7 @@ static void __init setup_processor(void)
 	}
 
 	cpu_name = list->cpu_name;
+	__cpu_architecture = __get_cpu_architecture();
 
 #ifdef MULTI_CPU
 	processor = *list->proc;
@@ -432,8 +461,10 @@ static void __init setup_processor(void)
 	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
 	       proc_arch[cpu_architecture()], cr_alignment);
 
-	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
+		 list->arch_name, ENDIANNESS);
+	snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
+		 list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
 #ifndef CONFIG_ARM_THUMB
 	elf_hwcap &= ~HWCAP_THUMB;
@@ -820,25 +851,8 @@ static struct machine_desc * __init setu
 
 	if (__atags_pointer)
 		tags = phys_to_virt(__atags_pointer);
-	else if (mdesc->boot_params) {
-#ifdef CONFIG_MMU
-		/*
-		 * We still are executing with a minimal MMU mapping created
-		 * with the presumption that the machine default for this
-		 * is located in the first MB of RAM.  Anything else will
-		 * fault and silently hang the kernel at this point.
-		 */
-		if (mdesc->boot_params < PHYS_OFFSET ||
-		    mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
-			printk(KERN_WARNING
-			       "Default boot params at physical 0x%08lx out of reach\n",
-			       mdesc->boot_params);
-		} else
-#endif
-		{
-			tags = phys_to_virt(mdesc->boot_params);
-		}
-	}
+	else if (mdesc->atag_offset)
+		tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
 
 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 	/*
@@ -861,7 +875,7 @@ static struct machine_desc * __init setu
 	}
 
 	if (mdesc->fixup)
-		mdesc->fixup(mdesc, tags, &from, &meminfo);
+		mdesc->fixup(tags, &from, &meminfo);
 
 	if (tags->hdr.tag == ATAG_CORE) {
 		if (meminfo.nr_banks != 0)
@@ -881,8 +895,6 @@ void __init setup_arch(char **cmdline_p)
 {
 	struct machine_desc *mdesc;
 
-	unwind_init();
-
 	setup_processor();
 	mdesc = setup_machine_fdt(__atags_pointer);
 	if (!mdesc)
@@ -890,6 +902,12 @@ void __init setup_arch(char **cmdline_p)
 	machine_desc = mdesc;
 	machine_name = mdesc->name;
 
+#ifdef CONFIG_ZONE_DMA
+	if (mdesc->dma_zone_size) {
+		extern unsigned long arm_dma_zone_size;
+		arm_dma_zone_size = mdesc->dma_zone_size;
+	}
+#endif
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
@@ -920,12 +938,6 @@ void __init setup_arch(char **cmdline_p)
 
 	tcm_init();
 
-#ifdef CONFIG_ZONE_DMA
-	if (mdesc->dma_zone_size) {
-		extern unsigned long arm_dma_zone_size;
-		arm_dma_zone_size = mdesc->dma_zone_size;
-	}
-#endif
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 	handle_arch_irq = mdesc->handle_irq;
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/sleep.S linux-libre-3.2-gnu1/arch/arm/kernel/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,92 +8,61 @@
 	.text
 
 /*
- * Save CPU state for a suspend
- *  r1 = v:p offset
- *  r2 = suspend function arg0
- *  r3 = suspend function
+ * Save CPU state for a suspend.  This saves the CPU general purpose
+ * registers, and allocates space on the kernel stack to save the CPU
+ * specific registers and some other data for resume.
+ *  r0 = suspend function arg0
+ *  r1 = suspend function
  */
 ENTRY(__cpu_suspend)
 	stmfd	sp!, {r4 - r11, lr}
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
-	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+	ldr	r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 #else
-	ldr	r5, =cpu_suspend_size
-	ldr	ip, =cpu_do_resume
+	ldr	r4, =cpu_suspend_size
 #endif
-	mov	r6, sp			@ current virtual SP
-	sub	sp, sp, r5		@ allocate CPU state on stack
-	mov	r0, sp			@ save pointer to CPU save block
-	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
-	ldr	r5, =sleep_save_sp
-	add	r6, sp, r1		@ convert SP to phys
-	stmfd	sp!, {r2, r3}		@ save suspend func arg and pointer
+	mov	r5, sp			@ current virtual SP
+	add	r4, r4, #12		@ Space for pgd, virt sp, phys resume fn
+	sub	sp, sp, r4		@ allocate CPU state on stack
+	stmfd	sp!, {r0, r1}		@ save suspend func arg and pointer
+	add	r0, sp, #8		@ save pointer to save block
+	mov	r1, r4			@ size of save block
+	mov	r2, r5			@ virtual SP
+	ldr	r3, =sleep_save_sp
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
 	and	lr, lr, #15
-	str	r6, [r5, lr, lsl #2]	@ save phys SP
-#else
-	str	r6, [r5]		@ save phys SP
-#endif
-#ifdef MULTI_CPU
-	mov	lr, pc
-	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
-#else
-	bl	cpu_do_suspend
-#endif
-
-	@ flush data cache
-#ifdef MULTI_CACHE
-	ldr	r10, =cpu_cache
-	mov	lr, pc
-	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
-	bl	__cpuc_flush_kern_all
+	add	r3, r3, lr, lsl #2
 #endif
+	bl	__cpu_suspend_save
 	adr	lr, BSYM(cpu_suspend_abort)
 	ldmfd	sp!, {r0, pc}		@ call suspend fn
 ENDPROC(__cpu_suspend)
 	.ltorg
 
 cpu_suspend_abort:
-	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn
+	ldmia	sp!, {r1 - r3}		@ pop phys pgd, virt SP, phys resume fn
+	teq	r0, #0
+	moveq	r0, #1			@ force non-zero value
 	mov	sp, r2
 	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_suspend_abort)
 
 /*
  * r0 = control register value
- * r1 = v:p offset (preserved by cpu_do_resume)
- * r2 = phys page table base
- * r3 = L1 section flags
  */
+	.align	5
 ENTRY(cpu_resume_mmu)
-	adr	r4, cpu_resume_turn_mmu_on
-	mov	r4, r4, lsr #20
-	orr	r3, r3, r4, lsl #20
-	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
-	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
-	sub	r2, r2, r1
 	ldr	r3, =cpu_resume_after_mmu
-	bic	r1, r0, #CR_C		@ ensure D-cache is disabled
-	b	cpu_resume_turn_mmu_on
-ENDPROC(cpu_resume_mmu)
-	.ltorg
-	.align	5
-cpu_resume_turn_mmu_on:
-	mcr	p15, 0, r1, c1, c0, 0	@ turn on MMU, I-cache, etc
-	mrc	p15, 0, r1, c0, c0, 0	@ read id reg
-	mov	r1, r1
-	mov	r1, r1
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, I-cache, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
 	mov	pc, r3			@ jump to virtual address
-ENDPROC(cpu_resume_turn_mmu_on)
+ENDPROC(cpu_resume_mmu)
 cpu_resume_after_mmu:
-	str	r5, [r2, r4, lsl #2]	@ restore old mapping
-	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
 	bl	cpu_init		@ restore the und/abt/irq banked regs
 	mov	r0, #0			@ return zero on success
 	ldmfd	sp!, {r4 - r11, pc}
@@ -119,7 +88,7 @@ ENTRY(cpu_resume)
 	ldr	r0, sleep_save_sp	@ stack phys addr
 #endif
 	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
-	@ load v:p, stack, resume fn
+	@ load phys pgd, stack, resume fn
   ARM(	ldmia	r0!, {r1, sp, pc}	)
 THUMB(	ldmia	r0!, {r1, r2, r3}	)
 THUMB(	mov	sp, r2			)
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/smp.c linux-libre-3.2-gnu1/arch/arm/kernel/smp.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <linux/cache.h>
 #include <linux/profile.h>
 #include <linux/errno.h>
-#include <linux/ftrace.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/cpu.h>
@@ -31,6 +30,8 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/exception.h>
+#include <asm/topology.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -39,6 +40,7 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
+#include <asm/smp_plat.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -259,6 +261,20 @@ void __ref cpu_die(void)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+	int i;
+	u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+	cpu_logical_map(0) = cpu;
+	for (i = 1; i < NR_CPUS; ++i)
+		cpu_logical_map(i) = i == cpu ? 0 : i;
+
+	printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
 /*
  * Called by both boot and secondaries to move global data into
  * per-processor storage.
@@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info
 	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
 
 	cpu_info->loops_per_jiffy = loops_per_jiffy;
+
+	store_cpu_topology(cpuid);
 }
 
 /*
@@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_star
 	 */
 	platform_secondary_init(cpu);
 
-	/*
-	 * Enable local interrupts.
-	 */
 	notify_cpu_starting(cpu);
-	local_irq_enable();
-	local_fiq_enable();
-
-	/*
-	 * Setup the percpu timer for this CPU.
-	 */
-	percpu_timer_setup();
 
 	calibrate_delay();
 
@@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_star
 	 * before we continue.
 	 */
 	set_cpu_online(cpu, true);
+
+	/*
+	 * Setup the percpu timer for this CPU.
+	 */
+	percpu_timer_setup();
+
 	while (!cpu_active(cpu))
 		cpu_relax();
 
 	/*
+	 * cpu_active bit is set, so it's safe to enalbe interrupts
+	 * now.
+	 */
+	local_irq_enable();
+	local_fiq_enable();
+
+	/*
 	 * OK, it's off to the idle thread for us
 	 */
 	cpu_idle();
@@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned in
 {
 	unsigned int ncores = num_possible_cpus();
 
+	init_cpu_topology();
+
 	smp_store_cpu_info(smp_processor_id());
 
 	/*
@@ -437,10 +460,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	for (i = 0; i < NR_IPI; i++)
 		sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-#ifdef CONFIG_LOCAL_TIMERS
-	sum += __get_irq_stat(cpu, local_timer_irqs);
-#endif
-
 	return sum;
 }
 
@@ -457,33 +476,6 @@ static void ipi_timer(void)
 	irq_exit();
 }
 
-#ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
-{
-	struct pt_regs *old_regs = set_irq_regs(regs);
-	int cpu = smp_processor_id();
-
-	if (local_timer_ack()) {
-		__inc_irq_stat(cpu, local_timer_irqs);
-		ipi_timer();
-	}
-
-	set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
-	unsigned int cpu;
-
-	seq_printf(p, "%*s: ", prec, "LOC");
-
-	for_each_present_cpu(cpu)
-		seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
-	seq_printf(p, " Local timer interrupts\n");
-}
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 static void smp_timer_broadcast(const struct cpumask *mask)
 {
@@ -534,11 +526,11 @@ static void percpu_timer_stop(void)
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
 
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	local_timer_stop(evt);
 }
 #endif
 
-static DEFINE_SPINLOCK(stop_lock);
+static DEFINE_RAW_SPINLOCK(stop_lock);
 
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
@@ -547,10 +539,10 @@ static void ipi_cpu_stop(unsigned int cp
 {
 	if (system_state == SYSTEM_BOOTING ||
 	    system_state == SYSTEM_RUNNING) {
-		spin_lock(&stop_lock);
+		raw_spin_lock(&stop_lock);
 		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
 		dump_stack();
-		spin_unlock(&stop_lock);
+		raw_spin_unlock(&stop_lock);
 	}
 
 	set_cpu_online(cpu, false);
@@ -567,6 +559,11 @@ static void ipi_cpu_stop(unsigned int cp
  */
 asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 {
+	handle_IPI(ipinr, regs);
+}
+
+void handle_IPI(int ipinr, struct pt_regs *regs)
+{
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/smp_scu.c linux-libre-3.2-gnu1/arch/arm/kernel/smp_scu.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/smp_scu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/smp_scu.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@ unsigned int __init scu_get_core_count(v
 /*
  * Enable the SCU
  */
-void __init scu_enable(void __iomem *scu_base)
+void scu_enable(void __iomem *scu_base)
 {
 	u32 scu_ctrl;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/smp_twd.c linux-libre-3.2-gnu1/arch/arm/kernel/smp_twd.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/smp_twd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/smp_twd.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <asm/smp_twd.h>
+#include <asm/localtimer.h>
 #include <asm/hardware/gic.h>
 
 /* set up by the platform code */
@@ -26,6 +27,8 @@ void __iomem *twd_base;
 
 static unsigned long twd_timer_rate;
 
+static struct clock_event_device __percpu **twd_evt;
+
 static void twd_set_mode(enum clock_event_mode mode,
 			struct clock_event_device *clk)
 {
@@ -80,6 +83,12 @@ int twd_timer_ack(void)
 	return 0;
 }
 
+void twd_timer_stop(struct clock_event_device *clk)
+{
+	twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+	disable_percpu_irq(clk->irq);
+}
+
 static void __cpuinit twd_calibrate_rate(void)
 {
 	unsigned long count;
@@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate
 	}
 }
 
+static irqreturn_t twd_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+	if (twd_timer_ack()) {
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
 /*
  * Setup the local clock events for a CPU.
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
+	struct clock_event_device **this_cpu_clk;
+
+	if (!twd_evt) {
+		int err;
+
+		twd_evt = alloc_percpu(struct clock_event_device *);
+		if (!twd_evt) {
+			pr_err("twd: can't allocate memory\n");
+			return;
+		}
+
+		err = request_percpu_irq(clk->irq, twd_handler,
+					 "twd", twd_evt);
+		if (err) {
+			pr_err("twd: can't register interrupt %d (%d)\n",
+			       clk->irq, err);
+			return;
+		}
+	}
+
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct cl
 	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
+	this_cpu_clk = __this_cpu_ptr(twd_evt);
+	*this_cpu_clk = clk;
+
 	clockevents_register_device(clk);
 
-	/* Make sure our local interrupt controller has this enabled */
-	gic_enable_ppi(clk->irq);
+	enable_percpu_irq(clk->irq, 0);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/stacktrace.c linux-libre-3.2-gnu1/arch/arm/kernel/stacktrace.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/suspend.c linux-libre-3.2-gnu1/arch/arm/kernel/suspend.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/suspend.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+#include <asm/tlbflush.h>
+
+static pgd_t *suspend_pgd;
+
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern void cpu_resume_mmu(void);
+
+/*
+ * This is called by __cpu_suspend() to save the state, and do whatever
+ * flushing is required to ensure that when the CPU goes to sleep we have
+ * the necessary data available when the caches are not searched.
+ */
+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
+{
+	*save_ptr = virt_to_phys(ptr);
+
+	/* This must correspond to the LDM in cpu_resume() assembly */
+	*ptr++ = virt_to_phys(suspend_pgd);
+	*ptr++ = sp;
+	*ptr++ = virt_to_phys(cpu_do_resume);
+
+	cpu_do_suspend(ptr);
+
+	flush_cache_all();
+	outer_clean_range(*save_ptr, *save_ptr + ptrsz);
+	outer_clean_range(virt_to_phys(save_ptr),
+			  virt_to_phys(save_ptr) + sizeof(*save_ptr));
+}
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+	struct mm_struct *mm = current->active_mm;
+	int ret;
+
+	if (!suspend_pgd)
+		return -EINVAL;
+
+	/*
+	 * Provide a temporary page table with an identity mapping for
+	 * the MMU-enable code, required for resuming.  On successful
+	 * resume (indicated by a zero return code), we need to switch
+	 * back to the correct page tables.
+	 */
+	ret = __cpu_suspend(arg, fn);
+	if (ret == 0) {
+		cpu_switch_mm(mm->pgd, mm);
+		local_flush_tlb_all();
+	}
+
+	return ret;
+}
+
+static int __init cpu_suspend_init(void)
+{
+	suspend_pgd = pgd_alloc(&init_mm);
+	if (suspend_pgd) {
+		unsigned long addr = virt_to_phys(cpu_resume_mmu);
+		identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
+	}
+	return suspend_pgd ? 0 : -ENOMEM;
+}
+core_initcall(cpu_suspend_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/sys_arm.c linux-libre-3.2-gnu1/arch/arm/kernel/sys_arm.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/sys_arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/sys_arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  *  have a non-standard calling sequence on the Linux/arm
  *  platform.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/time.c linux-libre-3.2-gnu1/arch/arm/kernel/time.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *  This file contains the ARM-specific time handling details:
  *  reading the RTC at bootup, etc...
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
@@ -39,13 +39,11 @@
  */
 static struct sys_timer *system_timer;
 
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
+    defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
-
-#ifdef CONFIG_RTC_DRV_CMOS_MODULE
 EXPORT_SYMBOL(rtc_lock);
-#endif
 #endif	/* pc-style 'CMOS' RTC support */
 
 /* change this if you have some constant time drift */
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/topology.c linux-libre-3.2-gnu1/arch/arm/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/kernel/topology.c
+ *
+ * Copyright (C) 2011 Linaro Limited.
+ * Written by: Vincent Guittot
+ *
+ * based on arch/sh/kernel/topology.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/cputype.h>
+#include <asm/topology.h>
+
+#define MPIDR_SMP_BITMASK (0x3 << 30)
+#define MPIDR_SMP_VALUE (0x2 << 30)
+
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+/*
+ * These masks reflect the current use of the affinity levels.
+ * The affinity level can be up to 16 bits according to ARM ARM
+ */
+
+#define MPIDR_LEVEL0_MASK 0x3
+#define MPIDR_LEVEL0_SHIFT 0
+
+#define MPIDR_LEVEL1_MASK 0xF
+#define MPIDR_LEVEL1_SHIFT 8
+
+#define MPIDR_LEVEL2_MASK 0xFF
+#define MPIDR_LEVEL2_SHIFT 16
+
+struct cputopo_arm cpu_topology[NR_CPUS];
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+	return &cpu_topology[cpu].core_sibling;
+}
+
+/*
+ * store_cpu_topology is called at boot when only one cpu is running
+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
+ * which prevents simultaneous write access to cpu_topology array
+ */
+void store_cpu_topology(unsigned int cpuid)
+{
+	struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];
+	unsigned int mpidr;
+	unsigned int cpu;
+
+	/* If the cpu topology has been already set, just return */
+	if (cpuid_topo->core_id != -1)
+		return;
+
+	mpidr = read_cpuid_mpidr();
+
+	/* create cpu topology mapping */
+	if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
+		/*
+		 * This is a multiprocessor system
+		 * multiprocessor format & multiprocessor mode field are set
+		 */
+
+		if (mpidr & MPIDR_MT_BITMASK) {
+			/* core performance interdependency */
+			cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+				& MPIDR_LEVEL0_MASK;
+			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+				& MPIDR_LEVEL1_MASK;
+			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)
+				& MPIDR_LEVEL2_MASK;
+		} else {
+			/* largely independent cores */
+			cpuid_topo->thread_id = -1;
+			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+				& MPIDR_LEVEL0_MASK;
+			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+				& MPIDR_LEVEL1_MASK;
+		}
+	} else {
+		/*
+		 * This is an uniprocessor system
+		 * we are in multiprocessor format but uniprocessor system
+		 * or in the old uniprocessor format
+		 */
+		cpuid_topo->thread_id = -1;
+		cpuid_topo->core_id = 0;
+		cpuid_topo->socket_id = -1;
+	}
+
+	/* update core and thread sibling masks */
+	for_each_possible_cpu(cpu) {
+		struct cputopo_arm *cpu_topo = &cpu_topology[cpu];
+
+		if (cpuid_topo->socket_id == cpu_topo->socket_id) {
+			cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+			if (cpu != cpuid)
+				cpumask_set_cpu(cpu,
+					&cpuid_topo->core_sibling);
+
+			if (cpuid_topo->core_id == cpu_topo->core_id) {
+				cpumask_set_cpu(cpuid,
+					&cpu_topo->thread_sibling);
+				if (cpu != cpuid)
+					cpumask_set_cpu(cpu,
+						&cpuid_topo->thread_sibling);
+			}
+		}
+	}
+	smp_wmb();
+
+	printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
+		cpuid, cpu_topology[cpuid].thread_id,
+		cpu_topology[cpuid].core_id,
+		cpu_topology[cpuid].socket_id, mpidr);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void init_cpu_topology(void)
+{
+	unsigned int cpu;
+
+	/* init core mask */
+	for_each_possible_cpu(cpu) {
+		struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
+
+		cpu_topo->thread_id = -1;
+		cpu_topo->core_id =  -1;
+		cpu_topo->socket_id = -1;
+		cpumask_clear(&cpu_topo->core_sibling);
+		cpumask_clear(&cpu_topo->thread_sibling);
+	}
+	smp_wmb();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/traps.c linux-libre-3.2-gnu1/arch/arm/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,14 @@
 #include <linux/kdebug.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
@@ -255,7 +257,7 @@ static int __die(const char *str, int er
 	return ret;
 }
 
-static DEFINE_SPINLOCK(die_lock);
+static DEFINE_RAW_SPINLOCK(die_lock);
 
 /*
  * This function is protected against re-entrancy.
@@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs
 
 	oops_enter();
 
-	spin_lock_irq(&die_lock);
+	raw_spin_lock_irq(&die_lock);
 	console_verbose();
 	bust_spinlocks(1);
+	if (!user_mode(regs))
+		report_bug(regs->ARM_pc, regs);
 	ret = __die(str, err, thread, regs);
 
 	if (regs && kexec_should_crash(thread->task))
@@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs
 
 	bust_spinlocks(0);
 	add_taint(TAINT_DIE);
-	spin_unlock_irq(&die_lock);
+	raw_spin_unlock_irq(&die_lock);
 	oops_exit();
 
 	if (in_interrupt())
@@ -301,25 +305,43 @@ void arm_notify_die(const char *str, str
 	}
 }
 
+#ifdef CONFIG_GENERIC_BUG
+
+int is_valid_bugaddr(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	unsigned short bkpt;
+#else
+	unsigned long bkpt;
+#endif
+
+	if (probe_kernel_address((unsigned *)pc, bkpt))
+		return 0;
+
+	return bkpt == BUG_INSTR_VALUE;
+}
+
+#endif
+
 static LIST_HEAD(undef_hook);
-static DEFINE_SPINLOCK(undef_lock);
+static DEFINE_RAW_SPINLOCK(undef_lock);
 
 void register_undef_hook(struct undef_hook *hook)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_add(&hook->node, &undef_hook);
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 void unregister_undef_hook(struct undef_hook *hook)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_del(&hook->node);
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
@@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_reg
 	unsigned long flags;
 	int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_for_each_entry(hook, &undef_hook, node)
 		if ((instr & hook->instr_mask) == hook->instr_val &&
 		    (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
 			fn = hook->fn;
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 
 	return fn ? fn(regs, instr) : 1;
 }
@@ -706,16 +728,6 @@ baddataabort(int code, unsigned long ins
 	arm_notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
-void __attribute__((noreturn)) __bug(const char *file, int line)
-{
-	printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
-	*(int *)0 = 0;
-
-	/* Avoid "noreturn function does return" */
-	for (;;);
-}
-EXPORT_SYMBOL(__bug);
-
 void __readwrite_bug(const char *fn)
 {
 	printk("%s called, but not implemented\n", fn);
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/unwind.c linux-libre-3.2-gnu1/arch/arm/kernel/unwind.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/unwind.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/unwind.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
 
 struct unwind_ctrl_block {
 	unsigned long vrs[16];		/* virtual register set */
-	unsigned long *insn;		/* pointer to the current instructions word */
+	const unsigned long *insn;	/* pointer to the current instructions word */
 	int entries;			/* number of entries left to interpret */
 	int byte;			/* current byte number in the instructions word */
 };
@@ -83,8 +83,9 @@ enum regs {
 	PC = 15
 };
 
-extern struct unwind_idx __start_unwind_idx[];
-extern struct unwind_idx __stop_unwind_idx[];
+extern const struct unwind_idx __start_unwind_idx[];
+static const struct unwind_idx *__origin_unwind_idx;
+extern const struct unwind_idx __stop_unwind_idx[];
 
 static DEFINE_SPINLOCK(unwind_lock);
 static LIST_HEAD(unwind_tables);
@@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables);
 })
 
 /*
- * Binary search in the unwind index. The entries entries are
+ * Binary search in the unwind index. The entries are
  * guaranteed to be sorted in ascending order by the linker.
+ *
+ * start = first entry
+ * origin = first entry with positive offset (or stop if there is no such entry)
+ * stop - 1 = last entry
  */
-static struct unwind_idx *search_index(unsigned long addr,
-				       struct unwind_idx *first,
-				       struct unwind_idx *last)
+static const struct unwind_idx *search_index(unsigned long addr,
+				       const struct unwind_idx *start,
+				       const struct unwind_idx *origin,
+				       const struct unwind_idx *stop)
 {
-	pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last);
+	unsigned long addr_prel31;
 
-	if (addr < first->addr) {
+	pr_debug("%s(%08lx, %p, %p, %p)\n",
+			__func__, addr, start, origin, stop);
+
+	/*
+	 * only search in the section with the matching sign. This way the
+	 * prel31 numbers can be compared as unsigned longs.
+	 */
+	if (addr < (unsigned long)start)
+		/* negative offsets: [start; origin) */
+		stop = origin;
+	else
+		/* positive offsets: [origin; stop) */
+		start = origin;
+
+	/* prel31 for address relavive to start */
+	addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
+
+	while (start < stop - 1) {
+		const struct unwind_idx *mid = start + ((stop - start) >> 1);
+
+		/*
+		 * As addr_prel31 is relative to start an offset is needed to
+		 * make it relative to mid.
+		 */
+		if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
+				mid->addr_offset)
+			stop = mid;
+		else {
+			/* keep addr_prel31 relative to start */
+			addr_prel31 -= ((unsigned long)mid -
+					(unsigned long)start);
+			start = mid;
+		}
+	}
+
+	if (likely(start->addr_offset <= addr_prel31))
+		return start;
+	else {
 		pr_warning("unwind: Unknown symbol address %08lx\n", addr);
 		return NULL;
-	} else if (addr >= last->addr)
-		return last;
+	}
+}
 
-	while (first < last - 1) {
-		struct unwind_idx *mid = first + ((last - first + 1) >> 1);
+static const struct unwind_idx *unwind_find_origin(
+		const struct unwind_idx *start, const struct unwind_idx *stop)
+{
+	pr_debug("%s(%p, %p)\n", __func__, start, stop);
+	while (start < stop) {
+		const struct unwind_idx *mid = start + ((stop - start) >> 1);
 
-		if (addr < mid->addr)
-			last = mid;
+		if (mid->addr_offset >= 0x40000000)
+			/* negative offset */
+			start = mid + 1;
 		else
-			first = mid;
+			/* positive offset */
+			stop = mid;
 	}
-
-	return first;
+	pr_debug("%s -> %p\n", __func__, stop);
+	return stop;
 }
 
-static struct unwind_idx *unwind_find_idx(unsigned long addr)
+static const struct unwind_idx *unwind_find_idx(unsigned long addr)
 {
-	struct unwind_idx *idx = NULL;
+	const struct unwind_idx *idx = NULL;
 	unsigned long flags;
 
 	pr_debug("%s(%08lx)\n", __func__, addr);
 
-	if (core_kernel_text(addr))
+	if (core_kernel_text(addr)) {
+		if (unlikely(!__origin_unwind_idx))
+			__origin_unwind_idx =
+				unwind_find_origin(__start_unwind_idx,
+						__stop_unwind_idx);
+
 		/* main unwind table */
 		idx = search_index(addr, __start_unwind_idx,
-				   __stop_unwind_idx - 1);
-	else {
+				   __origin_unwind_idx,
+				   __stop_unwind_idx);
+	} else {
 		/* module unwind tables */
 		struct unwind_table *table;
 
@@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_id
 			if (addr >= table->begin_addr &&
 			    addr < table->end_addr) {
 				idx = search_index(addr, table->start,
-						   table->stop - 1);
+						   table->origin,
+						   table->stop);
 				/* Move-to-front to exploit common traces */
 				list_move(&table->list, &unwind_tables);
 				break;
@@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwin
 int unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
-	struct unwind_idx *idx;
+	const struct unwind_idx *idx;
 	struct unwind_ctrl_block ctrl;
 
 	/* only go to a higher address on the stack */
@@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(un
 				      unsigned long text_size)
 {
 	unsigned long flags;
-	struct unwind_idx *idx;
 	struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
 
 	pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
@@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(un
 	if (!tab)
 		return tab;
 
-	tab->start = (struct unwind_idx *)start;
-	tab->stop = (struct unwind_idx *)(start + size);
+	tab->start = (const struct unwind_idx *)start;
+	tab->stop = (const struct unwind_idx *)(start + size);
+	tab->origin = unwind_find_origin(tab->start, tab->stop);
 	tab->begin_addr = text_addr;
 	tab->end_addr = text_addr + text_size;
 
-	/* Convert the symbol addresses to absolute values */
-	for (idx = tab->start; idx < tab->stop; idx++)
-		idx->addr = prel31_to_addr(&idx->addr);
-
 	spin_lock_irqsave(&unwind_lock, flags);
 	list_add_tail(&tab->list, &unwind_tables);
 	spin_unlock_irqrestore(&unwind_lock, flags);
@@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_tabl
 
 	kfree(tab);
 }
-
-int __init unwind_init(void)
-{
-	struct unwind_idx *idx;
-
-	/* Convert the symbol addresses to absolute values */
-	for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
-		idx->addr = prel31_to_addr(&idx->addr);
-
-	pr_debug("unwind: ARM stack unwinding initialised\n");
-
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/vmlinux.lds.S linux-libre-3.2-gnu1/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu1/arch/arm/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,8 @@
 #define ARM_CPU_KEEP(x)
 #endif
 
-#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
+#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
+	defined(CONFIG_GENERIC_BUG)
 #define ARM_EXIT_KEEP(x)	x
 #define ARM_EXIT_DISCARD(x)
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/kernel/xscale-cp0.c linux-libre-3.2-gnu1/arch/arm/kernel/xscale-cp0.c
--- linux-libre-3.1-gnu1/arch/arm/kernel/xscale-cp0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/kernel/xscale-cp0.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/backtrace.S linux-libre-3.2-gnu1/arch/arm/lib/backtrace.S
--- linux-libre-3.1-gnu1/arch/arm/lib/backtrace.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/backtrace.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,10 @@
 #define mask	r7
 #define offset	r8
 
-ENTRY(__backtrace)
-		mov	r1, #0x10
-		mov	r0, fp
-
 ENTRY(c_backtrace)
 
 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
 		mov	pc, lr
-ENDPROC(__backtrace)
 ENDPROC(c_backtrace)
 #else
 		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
@@ -107,7 +102,6 @@ for_each_frame:	tst	frame, mask		@ Check
 		mov	r1, frame
 		bl	printk
 no_frame:	ldmfd	sp!, {r4 - r8, pc}
-ENDPROC(__backtrace)
 ENDPROC(c_backtrace)
 		
 		.pushsection __ex_table,"a"
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/bitops.h linux-libre-3.2-gnu1/arch/arm/lib/bitops.h
--- linux-libre-3.1-gnu1/arch/arm/lib/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,9 @@
+#include <asm/unwind.h>
+
 #if __LINUX_ARM_ARCH__ >= 6
-	.macro	bitop, instr
+	.macro	bitop, name, instr
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
@@ -13,9 +17,13 @@
 	cmp	r0, #0
 	bne	1b
 	bx	lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 
-	.macro	testop, instr, store
+	.macro	testop, name, instr, store
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
@@ -34,9 +42,13 @@
 	cmp	r0, #0
 	movne	r0, #1
 2:	bx	lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 #else
-	.macro	bitop, instr
+	.macro	bitop, name, instr
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	and	r2, r0, #31
@@ -49,6 +61,8 @@
 	str	r2, [r1, r0, lsl #2]
 	restore_irqs ip
 	mov	pc, lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 
 /**
@@ -59,7 +73,9 @@
  * Note: we can trivially conditionalise the store instruction
  * to avoid dirtying the data cache.
  */
-	.macro	testop, instr, store
+	.macro	testop, name, instr, store
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	and	r3, r0, #31
@@ -73,5 +89,7 @@
 	moveq	r0, #0
 	restore_irqs ip
 	mov	pc, lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/changebit.S linux-libre-3.2-gnu1/arch/arm/lib/changebit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/changebit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/changebit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_change_bit)
-	bitop	eor
-ENDPROC(_change_bit)
+bitop	_change_bit, eor
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/clearbit.S linux-libre-3.2-gnu1/arch/arm/lib/clearbit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/clearbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/clearbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_clear_bit)
-	bitop	bic
-ENDPROC(_clear_bit)
+bitop	_clear_bit, bic
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/div64.S linux-libre-3.2-gnu1/arch/arm/lib/div64.S
--- linux-libre-3.1-gnu1/arch/arm/lib/div64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/div64.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/unwind.h>
 
 #ifdef __ARMEB__
 #define xh r0
@@ -44,6 +45,7 @@
  */
 
 ENTRY(__do_div64)
+UNWIND(.fnstart)
 
 	@ Test for easy paths first.
 	subs	ip, r4, #1
@@ -189,7 +191,12 @@ ENTRY(__do_div64)
 	moveq	yh, xh
 	moveq	xh, #0
 	moveq	pc, lr
+UNWIND(.fnend)
 
+UNWIND(.fnstart)
+UNWIND(.pad #4)
+UNWIND(.save {lr})
+Ldiv0_64:
 	@ Division by 0:
 	str	lr, [sp, #-8]!
 	bl	__div0
@@ -200,4 +207,5 @@ ENTRY(__do_div64)
 	mov	xh, #0
 	ldr	pc, [sp], #8
 
+UNWIND(.fnend)
 ENDPROC(__do_div64)
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/setbit.S linux-libre-3.2-gnu1/arch/arm/lib/setbit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/setbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/setbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
 		.text
 
-ENTRY(_set_bit)
-	bitop	orr
-ENDPROC(_set_bit)
+bitop	_set_bit, orr
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/testchangebit.S linux-libre-3.2-gnu1/arch/arm/lib/testchangebit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/testchangebit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/testchangebit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit)
-	testop	eor, str
-ENDPROC(_test_and_change_bit)
+testop	_test_and_change_bit, eor, str
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/testclearbit.S linux-libre-3.2-gnu1/arch/arm/lib/testclearbit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/testclearbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/testclearbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit)
-	testop	bicne, strne
-ENDPROC(_test_and_clear_bit)
+testop	_test_and_clear_bit, bicne, strne
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/testsetbit.S linux-libre-3.2-gnu1/arch/arm/lib/testsetbit.S
--- linux-libre-3.1-gnu1/arch/arm/lib/testsetbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/testsetbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit)
-	testop	orreq, streq
-ENDPROC(_test_and_set_bit)
+testop	_test_and_set_bit, orreq, streq
diff -druNp linux-libre-3.1-gnu1/arch/arm/lib/uaccess_with_memcpy.c linux-libre-3.2-gnu1/arch/arm/lib/uaccess_with_memcpy.c
--- linux-libre-3.1-gnu1/arch/arm/lib/uaccess_with_memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/lib/uaccess_with_memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/hardirq.h> /* for in_atomic() */
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 #include <asm/current.h>
 #include <asm/page.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91cap9.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91cap9.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91cap9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91cap9.c	2012-01-04 18:55:44.000000000 -0500
@@ -219,6 +219,8 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91cap9_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91cap9_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91cap9_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91cap9_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <asm/mach/irq.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -23,7 +24,6 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/gpio.h>
 #include <mach/at91cap9.h>
 #include <mach/at91cap9_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -80,6 +80,12 @@ void __init at91_add_device_usbh(struct
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -92,7 +98,7 @@ void __init at91_add_device_usbh(struct
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
 	[0] = {
@@ -1015,8 +1021,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1029,7 +1035,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91rm9200.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91rm9200.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91rm9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91rm9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,6 +193,8 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91rm9200_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91rm9200_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91rm9200_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91rm9200_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,11 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200.h>
 #include <mach/at91rm9200_mc.h>
 
@@ -60,9 +60,17 @@ static struct platform_device at91rm9200
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91rm9200_usbh_device);
 }
@@ -75,7 +83,7 @@ void __init at91_add_device_usbh(struct
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -869,8 +877,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -883,7 +891,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9260.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9260.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,10 +195,20 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-	CLKDEV_CON_DEV_ID("t3_clk", "atmel_tcb.1", &tc3_clk),
-	CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk),
-	CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk),
+	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
+	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
+	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9260_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9260_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9260_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9260_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,11 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9260.h>
 #include <mach/at91sam9260_matrix.h>
@@ -61,9 +61,17 @@ static struct platform_device at91_usbh_
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -76,7 +84,7 @@ void __init at91_add_device_usbh(struct
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -319,7 +327,7 @@ void __init at91_add_device_mci(short mm
 	if (!data)
 		return;
 
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		if (data->slot[i].bus_width) {
 			/* input/irq */
 			if (data->slot[i].detect_pin) {
@@ -829,8 +837,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -843,7 +851,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9261.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9261.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9261.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9261.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,6 +129,20 @@ static struct clk lcdc_clk = {
 	.type		= CLK_TYPE_PERIPHERAL,
 };
 
+/* HClocks */
+static struct clk hck0 = {
+	.name		= "hck0",
+	.pmc_mask	= AT91_PMC_HCK0,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 0,
+};
+static struct clk hck1 = {
+	.name		= "hck1",
+	.pmc_mask	= AT91_PMC_HCK1,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 1,
+};
+
 static struct clk *periph_clocks[] __initdata = {
 	&pioA_clk,
 	&pioB_clk,
@@ -161,6 +175,7 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -199,20 +214,6 @@ static struct clk pck3 = {
 	.id		= 3,
 };
 
-/* HClocks */
-static struct clk hck0 = {
-	.name		= "hck0",
-	.pmc_mask	= AT91_PMC_HCK0,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 0,
-};
-static struct clk hck1 = {
-	.name		= "hck1",
-	.pmc_mask	= AT91_PMC_HCK1,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 1,
-};
-
 static void __init at91sam9261_register_clocks(void)
 {
 	int i;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9261_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9261_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9261_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9261_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -21,7 +22,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9261.h>
 #include <mach/at91sam9261_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -64,9 +64,17 @@ static struct platform_device at91sam926
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91sam9261_usbh_device);
 }
@@ -79,7 +87,7 @@ void __init at91_add_device_usbh(struct
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -808,8 +816,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -822,7 +830,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9263.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9263.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9263.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9263.c	2012-01-04 18:55:44.000000000 -0500
@@ -189,6 +189,8 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9263_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9263_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9263_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9263_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -20,7 +21,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9263.h>
 #include <mach/at91sam9263_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -74,6 +74,12 @@ void __init at91_add_device_usbh(struct
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -86,7 +92,7 @@ void __init at91_add_device_usbh(struct
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -1190,8 +1196,8 @@ void __init at91_add_device_ssc(unsigned
 
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1204,7 +1210,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9g45.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9g45.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9g45.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9g45.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/pm.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
@@ -53,6 +54,11 @@ static struct clk pioDE_clk = {
 	.pmc_mask	= 1 << AT91SAM9G45_ID_PIODE,
 	.type		= CLK_TYPE_PERIPHERAL,
 };
+static struct clk trng_clk = {
+	.name		= "trng_clk",
+	.pmc_mask	= 1 << AT91SAM9G45_ID_TRNG,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
 static struct clk usart0_clk = {
 	.name		= "usart0_clk",
 	.pmc_mask	= 1 << AT91SAM9G45_ID_US0,
@@ -176,6 +182,7 @@ static struct clk *periph_clocks[] __ini
 	&pioB_clk,
 	&pioC_clk,
 	&pioDE_clk,
+	&trng_clk,
 	&usart0_clk,
 	&usart1_clk,
 	&usart2_clk,
@@ -215,6 +222,15 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -319,6 +335,7 @@ static void at91sam9g45_poweroff(void)
 static void __init at91sam9g45_map_io(void)
 {
 	at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
+	init_consistent_dma_size(SZ_4M);
 }
 
 static void __init at91sam9g45_initialize(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9g45_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9g45_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9g45_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9g45_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
@@ -21,7 +22,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -124,6 +124,12 @@ void __init at91_add_device_usbh_ohci(st
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_ohci_data = *data;
 	platform_device_register(&at91_usbh_ohci_device);
 }
@@ -191,7 +197,7 @@ void __init at91_add_device_usbh_ehci(st
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 static struct resource usba_udc_resources[] = {
 	[0] = {
 		.start	= AT91SAM9G45_UDPHS_FIFO,
@@ -1095,6 +1101,34 @@ static void __init at91_add_device_rtt(v
 
 
 /* --------------------------------------------------------------------
+ *  TRNG
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
+static struct resource trng_resources[] = {
+	{
+		.start	= AT91SAM9G45_BASE_TRNG,
+		.end	= AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device at91sam9g45_trng_device = {
+	.name		= "atmel-trng",
+	.id		= -1,
+	.resource	= trng_resources,
+	.num_resources	= ARRAY_SIZE(trng_resources),
+};
+
+static void __init at91_add_device_trng(void)
+{
+	platform_device_register(&at91sam9g45_trng_device);
+}
+#else
+static void __init at91_add_device_trng(void) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
 
@@ -1298,8 +1332,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1312,7 +1346,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1583,6 +1616,7 @@ static int __init at91_add_standard_devi
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
 	at91_add_device_rtt();
+	at91_add_device_trng();
 	at91_add_device_watchdog();
 	at91_add_device_tc();
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9rl_devices.c linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9rl_devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/at91sam9rl_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/at91sam9rl_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -17,7 +18,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9rl.h>
 #include <mach/at91sam9rl_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -75,7 +75,7 @@ void __init at91_add_device_hdmac(void)
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
 	[0] = {
@@ -908,8 +908,8 @@ void __init at91_add_device_ssc(unsigned
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -922,7 +922,6 @@ static struct resource dbgu_resources[]
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-1arm.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-1arm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-1arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-1arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-afeb-9260v1.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-afeb-9260v1.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-afeb-9260v1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-afeb-9260v1.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -43,7 +44,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
@@ -130,19 +130,14 @@ static struct mtd_partition __initdata a
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(afeb9260_nand_partition);
-	return afeb9260_nand_partition;
-}
-
 static struct atmel_nand_data __initdata afeb9260_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
 	.bus_width_16	= 0,
+	.parts		= afeb9260_nand_partition,
+	.num_parts	= ARRAY_SIZE(afeb9260_nand_partition),
 };
 
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cam60.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cam60.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cam60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cam60.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -132,19 +132,14 @@ static struct mtd_partition __initdata c
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(cam60_nand_partition);
-	return cam60_nand_partition;
-}
-
 static struct atmel_nand_data __initdata cam60_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PA9,
 	.enable_pin	= AT91_PIN_PA7,
-	.partition_info	= nand_partitions,
+	.parts		= cam60_nand_partition,
+	.num_parts	= ARRAY_SIZE(cam60_nand_partition),
 };
 
 static struct sam9_smc_config __initdata cam60_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cap9adk.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cap9adk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cap9adk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cap9adk.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91cap9_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
@@ -169,19 +169,14 @@ static struct mtd_partition __initdata c
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(cap9adk_nand_partitions);
-	return cap9adk_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata cap9adk_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.rdy_pin	= ... not connected
 	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
+	.parts		= cap9adk_nand_partitions,
+	.num_parts	= ARRAY_SIZE(cap9adk_nand_partitions),
 };
 
 static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-carmeva.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-carmeva.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-carmeva.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-carmeva.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cpu9krea.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cpu9krea.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cpu9krea.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cpu9krea.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -40,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91sam9260_matrix.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cpuat91.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cpuat91.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-cpuat91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-cpuat91.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -36,7 +37,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/cpu.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-csb337.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-csb337.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-csb337.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-csb337.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-csb637.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-csb637.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-csb637.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-csb637.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -35,7 +36,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-dt.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-dt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ *  Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ *  Covers: * AT91SAM9G45-EKES  board
+ *          * AT91SAM9M10-EKES  board
+ *          * AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/system_rev.h>
+#include <mach/at91sam9_smc.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.000 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DGBU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/* det_pin is not connected */
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+	.rdy_pin	= AT91_PIN_PC8,
+	.enable_pin	= AT91_PIN_PC14,
+};
+
+static struct sam9_smc_config __initdata ek_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	ek_nand_data.bus_width_16 = board_have_nand_16bit();
+	/* setup bus-width (8 or 16) */
+	if (ek_nand_data.bus_width_16)
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+	else
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+	/* configure chip-select 3 (NAND) */
+	sam9_smc_configure(3, &ek_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+static const struct of_device_id aic_of_match[] __initconst = {
+	{ .compatible = "atmel,at91rm9200-aic", },
+	{},
+};
+
+static void __init at91_dt_init_irq(void)
+{
+	irq_domain_generate_simple(aic_of_match, 0xfffff000, 0);
+	at91_init_irq_default();
+}
+
+static void __init at91_dt_device_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	/* NAND */
+	ek_add_device_nand();
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+	"atmel,at91sam9m10g45ek",
+	"calao,usb-a9g20",
+	NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+	/* Maintainer: Atmel */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_dt_init_irq,
+	.init_machine	= at91_dt_device_init,
+	.dt_compat	= at91_dt_board_compat,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-eb9200.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-eb9200.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-eb9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-eb9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-ecbat91.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-ecbat91.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-ecbat91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-ecbat91.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-kafa.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-kafa.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-kafa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-kafa.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-kb9202.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-kb9202.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-kb9202.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-kb9202.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 #include <mach/at91rm9200_mc.h>
 
@@ -97,19 +97,14 @@ static struct mtd_partition __initdata k
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
-	return kb9202_nand_partition;
-}
-
 static struct atmel_nand_data __initdata kb9202_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PC29,
 	.enable_pin	= AT91_PIN_PC28,
-	.partition_info	= nand_partitions,
+	.parts		= kb9202_nand_partition,
+	.num_parts	= ARRAY_SIZE(kb9202_nand_partition),
 };
 
 static void __init kb9202_board_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-neocore926.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-neocore926.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-neocore926.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-neocore926.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -44,7 +45,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -182,19 +182,14 @@ static struct mtd_partition __initdata n
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(neocore926_nand_partition);
-	return neocore926_nand_partition;
-}
-
 static struct atmel_nand_data __initdata neocore926_nand_data = {
 	.ale			= 21,
 	.cle			= 22,
 	.rdy_pin		= AT91_PIN_PB19,
 	.rdy_pin_active_low	= 1,
 	.enable_pin		= AT91_PIN_PD15,
-	.partition_info		= nand_partitions,
+	.parts			= neocore926_nand_partition,
+	.num_parts		= ARRAY_SIZE(neocore926_nand_partition),
 };
 
 static struct sam9_smc_config __initdata neocore926_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-picotux200.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-picotux200.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-picotux200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-picotux200.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-qil-a9260.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-qil-a9260.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-qil-a9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-qil-a9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -40,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -130,19 +130,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rm9200dk.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rm9200dk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rm9200dk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rm9200dk.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
@@ -138,19 +138,14 @@ static struct mtd_partition __initdata d
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(dk_nand_partition);
-	return dk_nand_partition;
-}
-
 static struct atmel_nand_data __initdata dk_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 	.det_pin	= AT91_PIN_PB1,
 	.rdy_pin	= AT91_PIN_PC2,
 	// .enable_pin	= ... not there
-	.partition_info	= nand_partitions,
+	.parts		= dk_nand_partition,
+	.num_parts	= ARRAY_SIZE(dk_nand_partition),
 };
 
 #define DK_FLASH_BASE	AT91_CHIPSELECT_0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rm9200ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rm9200ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rm9200ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rm9200ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rsi-ews.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rsi-ews.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-rsi-ews.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-rsi-ews.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,233 @@
+/*
+ * board-rsi-ews.c
+ *
+ *  Copyright (C)
+ *  2005 SAN People,
+ *  2008-2011 R-S-I Elektrotechnik GmbH & Co. KG
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include <linux/gpio.h>
+
+#include "generic.h"
+
+static void __init rsi_ews_init_early(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91_initialize(18432000);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	/* This one is for debugging */
+	at91_register_uart(0, 0, 0);
+
+	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+	/* Dialin/-out modem interface */
+	at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+			   | ATMEL_UART_RI);
+
+	/* USART3 on ttyS4. (Rx, Tx, RTS) */
+	/* RS485 communication */
+	at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * Ethernet
+ */
+static struct at91_eth_data rsi_ews_eth_data __initdata = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+/*
+ * USB Host
+ */
+static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
+	.ports		= 1,
+};
+
+/*
+ * SD/MC
+ */
+static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
+	.slot_b		= 0,
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PB27,
+	.wp_pin		= AT91_PIN_PB29,
+};
+
+/*
+ * I2C
+ */
+static struct i2c_board_info rsi_ews_i2c_devices[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+	{
+		I2C_BOARD_INFO("24c01", 0x50),
+	}
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led rsi_ews_leds[] = {
+	{
+		.name			= "led0",
+		.gpio			= AT91_PIN_PB6,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led1",
+		.gpio			= AT91_PIN_PB7,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led2",
+		.gpio			= AT91_PIN_PB8,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led3",
+		.gpio			= AT91_PIN_PB9,
+		.active_low		= 0,
+	},
+};
+
+/*
+ * DataFlash
+ */
+static struct spi_board_info rsi_ews_spi_devices[] = {
+	{	/* DataFlash chip 1*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+	{	/* DataFlash chip 2*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+};
+
+/*
+ * NOR flash
+ */
+static struct mtd_partition rsiews_nor_partitions[] = {
+	{
+		.name		= "boot",
+		.offset		= 0,
+		.size		= 3 * SZ_128K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_2M - (3 * SZ_128K)
+	},
+	{
+		.name		= "root",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_8M
+	},
+	{
+		.name		= "kernelupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 3 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "rootupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 9 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+};
+
+static struct physmap_flash_data rsiews_nor_data = {
+	.width		= 2,
+	.parts		= rsiews_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(rsiews_nor_partitions),
+};
+
+#define NOR_BASE	AT91_CHIPSELECT_0
+#define NOR_SIZE	SZ_16M
+
+static struct resource nor_flash_resources[] = {
+	{
+		.start	= NOR_BASE,
+		.end	= NOR_BASE + NOR_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device rsiews_nor_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &rsiews_nor_data,
+	},
+	.resource	= nor_flash_resources,
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+};
+
+/*
+ * Init Func
+ */
+static void __init rsi_ews_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	at91_set_gpio_output(AT91_PIN_PA21, 0);
+	/* Ethernet */
+	at91_add_device_eth(&rsi_ews_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&rsi_ews_usbh_data);
+	/* I2C */
+	at91_add_device_i2c(rsi_ews_i2c_devices,
+			ARRAY_SIZE(rsi_ews_i2c_devices));
+	/* SPI */
+	at91_add_device_spi(rsi_ews_spi_devices,
+			ARRAY_SIZE(rsi_ews_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(0, &rsi_ews_mmc_data);
+	/* NOR Flash */
+	platform_device_register(&rsiews_nor_flash);
+	/* LEDs */
+	at91_gpio_leds(rsi_ews_leds, ARRAY_SIZE(rsi_ews_leds));
+}
+
+MACHINE_START(RSI_EWS, "RSI EWS")
+	/* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
+	.timer		= &at91rm9200_timer,
+	.map_io		= at91_map_io,
+	.init_early	= rsi_ews_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= rsi_ews_board_init,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9260ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9260ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9260ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9260ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -173,19 +173,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9261ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9261ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9261ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9261ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -45,7 +46,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -179,19 +179,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC15,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9263ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9263ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9263ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9263ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -44,7 +45,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -180,19 +180,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PA22,
 	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9g20ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9g20ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9g20ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9g20ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
 
@@ -157,19 +157,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9-l9260.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9-l9260.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9-l9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9-l9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -131,19 +131,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -137,19 +137,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC8,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9rlek.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9rlek.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-sam9rlek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-sam9rlek.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -30,7 +31,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -88,19 +88,14 @@ static struct mtd_partition __initdata e
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PD17,
 	.enable_pin	= AT91_PIN_PB6,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-snapper9260.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-snapper9260.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-snapper9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-snapper9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,18 +97,12 @@ static struct mtd_partition __initdata s
 	},
 };
 
-static struct mtd_partition * __init
-snapper9260_nand_partition_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(snapper9260_nand_partitions);
-	return snapper9260_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata snapper9260_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
-	.partition_info	= snapper9260_nand_partition_info,
+	.parts		= snapper9260_nand_partitions,
+	.num_parts	= ARRAY_SIZE(snapper9260_nand_partitions),
 	.bus_width_16	= 0,
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a9260.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a9260.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a9260.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,230 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9260.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/clk.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.000 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PC5,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PA31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Uboot & Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PC13,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-/*
- * GPIO Buttons
- */
-
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 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_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 0,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9260, "CALAO USB_A9260")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a9263.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a9263.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a9263.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a9263.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9263.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Atmel Corporation.
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.00 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PB11,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	}
-#endif
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PE31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Linux Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PA22,
-	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 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_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 1,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9263, "CALAO USB_A9263")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a926x.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a926x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-usb-a926x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-usb-a926x.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,378 @@
+/*
+ * linux/arch/arm/mach-at91/board-usb-a926x.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Atmel Corporation.
+ *  Copyright (C) 2007 Calao-systems
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/spi/mmc_spi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91_shdwc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.00 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PB11,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+static void __init ek_add_device_udc(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+	at91_add_device_udc(&ek_udc_data);
+}
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT AT91_PIN_PC4
+static int at91_mmc_spi_init(struct device *dev,
+	irqreturn_t (*detect_int)(int, void *), void *data)
+{
+	/* Configure Interrupt pin as input, no pull-up */
+	at91_set_gpio_input(MMC_SPI_CARD_DETECT_INT, 0);
+	return request_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), detect_int,
+		IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+		"mmc-spi-detect", data);
+}
+
+static void at91_mmc_spi_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), data);
+}
+
+static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
+	.init = at91_mmc_spi_init,
+	.exit = at91_mmc_spi_exit,
+	.detect_delay = 100, /* msecs */
+};
+#endif
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info usb_a9263_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	}
+#endif
+};
+
+static struct spi_board_info usb_a9g20_spi_devices[] = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,	/* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 0,
+		.platform_data = &at91_mmc_spi_pdata,
+		.mode = SPI_MODE_3,
+	},
+#endif
+};
+
+static void __init ek_add_device_spi(void)
+{
+	if (machine_is_usb_a9263())
+		at91_add_device_spi(usb_a9263_spi_devices, ARRAY_SIZE(usb_a9263_spi_devices));
+	else if (machine_is_usb_a9g20())
+		at91_add_device_spi(usb_a9g20_spi_devices, ARRAY_SIZE(usb_a9g20_spi_devices));
+}
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata ek_macb_data = {
+	.phy_irq_pin	= AT91_PIN_PE31,
+	.is_rmii	= 1,
+};
+
+static void __init ek_add_device_eth(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_macb_data.phy_irq_pin = AT91_PIN_PA31;
+
+	at91_add_device_eth(&ek_macb_data);
+}
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "barebox",
+		.offset	= 0,
+		.size	= 3 * SZ_128K,
+	}, {
+		.name	= "bareboxenv",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "bareboxenv2",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "kernel",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 4 * SZ_1M,
+	}, {
+		.name	= "rootfs",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 120 * SZ_1M,
+	}, {
+		.name	= "data",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PA22,
+	.enable_pin	= AT91_PIN_PD15,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
+};
+
+static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 1,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 1,
+
+	.ncs_read_pulse		= 3,
+	.nrd_pulse		= 3,
+	.ncs_write_pulse	= 3,
+	.nwe_pulse		= 3,
+
+	.read_cycle		= 5,
+	.write_cycle		= 5,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 2,
+};
+
+static struct sam9_smc_config __initdata usb_a9g20_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20()) {
+		ek_nand_data.rdy_pin	= AT91_PIN_PC13;
+		ek_nand_data.enable_pin	= AT91_PIN_PC14;
+	}
+
+	/* configure chip-select 3 (NAND) */
+	if (machine_is_usb_a9g20())
+		sam9_smc_configure(3, &usb_a9g20_nand_smc_config);
+	else
+		sam9_smc_configure(3, &usb_a9260_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{	/* USER PUSH BUTTON */
+		.code		= KEY_ENTER,
+		.gpio		= AT91_PIN_PB10,
+		.active_low	= 1,
+		.desc		= "user_pb",
+		.wakeup		= 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_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
+	at91_set_deglitch(AT91_PIN_PB10, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+/*
+ * LEDs
+ */
+static struct gpio_led ek_leds[] = {
+	{	/* user_led (green) */
+		.name			= "user_led",
+		.gpio			= AT91_PIN_PB21,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	}
+};
+
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rv3029c2", 0x56),
+	},
+};
+
+static void __init ek_add_device_leds(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_leds[0].active_low = 0;
+
+	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	ek_add_device_udc();
+	/* SPI */
+	ek_add_device_spi();
+	/* Ethernet */
+	ek_add_device_eth();
+	/* NAND */
+	ek_add_device_nand();
+	/* Push Buttons */
+	ek_add_device_buttons();
+	/* LEDs */
+	ek_add_device_leds();
+
+	if (machine_is_usb_a9g20()) {
+		/* I2C */
+		at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	} else {
+		/* I2C */
+		at91_add_device_i2c(NULL, 0);
+		/* shutdown controller, wakeup button (5 msec low) */
+		at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10)
+				| AT91_SHDW_WKMODE0_LOW
+				| AT91_SHDW_RTTWKEN);
+	}
+}
+
+MACHINE_START(USB_A9263, "CALAO USB_A9263")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9260, "CALAO USB_A9260")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
+	/* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/board-yl-9200.c linux-libre-3.2-gnu1/arch/arm/mach-at91/board-yl-9200.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/board-yl-9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/board-yl-9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -43,7 +44,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/cpu.h>
 
@@ -172,19 +172,14 @@ static struct mtd_partition __initdata y
 	}
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(yl9200_nand_partition);
-	return yl9200_nand_partition;
-}
-
 static struct atmel_nand_data __initdata yl9200_nand_data = {
 	.ale		= 6,
 	.cle		= 7,
 	// .det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC14,	/* R/!B (Sheet10) */
 	.enable_pin	= AT91_PIN_PC15,	/* !CE  (Sheet10) */
-	.partition_info	= nand_partitions,
+	.parts		= yl9200_nand_partition,
+	.num_parts	= ARRAY_SIZE(yl9200_nand_partition),
 };
 
 /*
@@ -389,7 +384,7 @@ static struct spi_board_info yl9200_spi_
 #include <video/s1d13xxxfb.h>
 
 
-static void __init yl9200_init_video(void)
+static void yl9200_init_video(void)
 {
 	/* NWAIT Signal */
 	at91_set_A_periph(AT91_PIN_PC6, 0);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-at91/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/cpuidle.h>
 #include <asm/proc-fns.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include "pm.h"
 
@@ -33,7 +34,8 @@ static struct cpuidle_driver at91_idle_d
 
 /* Actual code that puts the SoC in different idle states */
 static int at91_enter_idle(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+			struct cpuidle_driver *drv,
+			       int index)
 {
 	struct timeval before, after;
 	int idle_time;
@@ -41,10 +43,10 @@ static int at91_enter_idle(struct cpuidl
 
 	local_irq_disable();
 	do_gettimeofday(&before);
-	if (state == &dev->states[0])
+	if (index == 0)
 		/* Wait for interrupt state */
 		cpu_do_idle();
-	else if (state == &dev->states[1]) {
+	else if (index == 1) {
 		asm("b 1f; .align 5; 1:");
 		asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
 		saved_lpr = sdram_selfrefresh_enable();
@@ -55,34 +57,38 @@ static int at91_enter_idle(struct cpuidl
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	dev->last_residency = idle_time;
+	return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int at91_init_cpuidle(void)
 {
 	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&at91_idle_driver);
+	struct cpuidle_driver *driver = &at91_idle_driver;
 
 	device = &per_cpu(at91_cpuidle_device, smp_processor_id());
 	device->state_count = AT91_MAX_STATES;
+	driver->state_count = AT91_MAX_STATES;
 
 	/* Wait for interrupt state */
-	device->states[0].enter = at91_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = at91_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and RAM self refresh state */
-	device->states[1].enter = at91_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "RAM_SR");
-	strcpy(device->states[1].desc, "WFI and RAM Self Refresh");
+	driver->states[1].enter = at91_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "RAM_SR");
+	strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
+
+	cpuidle_register_driver(&at91_idle_driver);
 
 	if (cpuidle_register_device(device)) {
 		printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-at91/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/errno.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/debugfs.h>
@@ -22,9 +23,6 @@
 
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
-#include <mach/gpio.h>
-
-#include <asm/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/at91sam9g45.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/at91sam9g45.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/at91sam9g45.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/at91sam9g45.h	2012-01-04 18:55:44.000000000 -0500
@@ -128,8 +128,6 @@
 #define AT91SAM9G45_EHCI_BASE	0x00800000	/* USB Host controller (EHCI) */
 #define AT91SAM9G45_VDEC_BASE	0x00900000	/* Video Decoder Controller */
 
-#define CONSISTENT_DMA_SIZE	SZ_4M
-
 /*
  * DMA peripheral identifiers
  * for hardware handshaking interface
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/board.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/board.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/board.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/board.h	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,11 @@ extern void __init at91_add_device_eth(s
 struct at91_usbh_data {
 	u8		ports;		/* number of ports on root hub */
 	u8		vbus_pin[2];	/* port power-control pin */
+	u8              vbus_pin_inverted;
+	u8              overcurrent_supported;
+	u8              overcurrent_pin[2];
+	u8              overcurrent_status[2];
+	u8              overcurrent_changed[2];
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
@@ -112,7 +117,8 @@ struct atmel_nand_data {
 	u8		ale;		/* address line number connected to ALE */
 	u8		cle;		/* address line number connected to CLE */
 	u8		bus_width_16;	/* buswidth is 16 bit */
-	struct mtd_partition* (*partition_info)(int, int*);
+	struct mtd_partition *parts;
+	unsigned int	num_parts;
 };
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/at91_dbgu.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =(AT91_BASE_SYS + AT91_DBGU)	@ System peripherals (phys address)
 	ldr	\rv, =(AT91_VA_BASE_SYS	+ AT91_DBGU)	@ System peripherals (virt address)
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -214,11 +214,6 @@ extern void at91_gpio_resume(void);
  */
 
 #include <asm/errno.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 #define gpio_to_irq(gpio) (gpio)
 #define irq_to_gpio(irq)  (irq)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/system_rev.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/system_rev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/system_rev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/system_rev.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #define BOARD_HAVE_NAND_16BIT	(1 << 31)
 static inline int board_have_nand_16bit(void)
 {
-	return system_rev & BOARD_HAVE_NAND_16BIT;
+	return (system_rev & BOARD_HAVE_NAND_16BIT) ? 1 : 0;
 }
 
 #endif /* __ARCH_SYSTEM_REV_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,12 @@
 
 #elif defined(CONFIG_ARCH_AT91SAM9G20)
 
+#if defined(CONFIG_MACH_USB_A9G20)
+#define AT91SAM9_MASTER_CLOCK	133000000
+#else
 #define AT91SAM9_MASTER_CLOCK	132096000
+#endif
+
 #define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
+#include <mach/hardware.h>
+
 #define VMALLOC_END		(AT91_VIRT_BASE & PGDIR_MASK)
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-at91/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,11 @@ config MACH_ECO920
 	help
 	  Select this if you are using the eco920 board
 
+config MACH_RSI_EWS
+	bool "RSI Embedded Webserver"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using RSIs EWS board.
 endif
 
 # ----------------------------------------------------------
@@ -190,12 +195,6 @@ if ARCH_AT91SAM9260
 
 comment "AT91SAM9260 Variants"
 
-config ARCH_AT91SAM9260_SAM9XE
-	bool "AT91SAM9XE"
-	help
-	  Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
-	  They are basically AT91SAM9260s with various sizes of embedded Flash.
-
 comment "AT91SAM9260 / AT91SAM9XE Board Type"
 
 config MACH_AT91SAM9260EK
@@ -381,6 +380,14 @@ config MACH_GSIA18S
 	  This enables support for the GS_IA18_S board
 	  produced by GeoSIG Ltd company. This is an internet accelerograph.
 	  <http://www.geosig.com>
+
+config MACH_USB_A9G20
+	bool "CALAO USB-A9G20"
+	depends on ARCH_AT91SAM9G20
+	help
+	  Select this if you are using a Calao Systems USB-A9G20.
+	  <http://www.calao-systems.com>
+
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
@@ -442,6 +449,17 @@ endif
 
 # ----------------------------------------------------------
 
+comment "Generic Board Type"
+
+config MACH_AT91SAM_DT
+	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+	select USE_OF
+	help
+	  Select this if you want to experiment device-tree with
+	  an Atmel Evaluation Kit.
+
+# ----------------------------------------------------------
+
 comment "AT91 Board Options"
 
 config MTD_AT91_DATAFLASH_CARD
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/leds.c linux-libre-3.2-gnu1/arch/arm/mach-at91/leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,13 +9,13 @@
  * 2 of the License, or (at your option) any later version.
 */
 
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 
 /* ------------------------------------------------------------------------- */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/Makefile linux-libre-3.2-gnu1/arch/arm/mach-at91/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -36,12 +36,13 @@ obj-$(CONFIG_MACH_ECBAT91)	+= board-ecba
 obj-$(CONFIG_MACH_YL9200)	+= board-yl-9200.o
 obj-$(CONFIG_MACH_CPUAT91)	+= board-cpuat91.o
 obj-$(CONFIG_MACH_ECO920)	+= board-eco920.o
+obj-$(CONFIG_MACH_RSI_EWS)	+= board-rsi-ews.o
 
 # AT91SAM9260 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
 obj-$(CONFIG_MACH_CAM60)	+= board-cam60.o
 obj-$(CONFIG_MACH_SAM9_L9260)	+= board-sam9-l9260.o
-obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a9260.o
+obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_QIL_A9260)	+= board-qil-a9260.o
 obj-$(CONFIG_MACH_AFEB9260)	+= board-afeb-9260v1.o
 obj-$(CONFIG_MACH_CPU9260)	+= board-cpu9krea.o
@@ -53,7 +54,7 @@ obj-$(CONFIG_MACH_AT91SAM9G10EK) += boar
 
 # AT91SAM9263 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
-obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a9263.o
+obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_NEOCORE926)	+= board-neocore926.o
 
 # AT91SAM9RL board-specific support
@@ -67,6 +68,7 @@ obj-$(CONFIG_MACH_STAMP9G20)	+= board-st
 obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o board-stamp9g20.o
 obj-$(CONFIG_MACH_GSIA18S)	+= board-gsia18s.o board-stamp9g20.o
+obj-$(CONFIG_MACH_USB_A9G20)	+= board-usb-a926x.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
@@ -74,6 +76,9 @@ obj-$(CONFIG_MACH_SNAPPER_9260)	+= board
 # AT91SAM9G45 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
+# AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
+
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK)	+= board-cap9adk.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-at91/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -4,15 +4,17 @@
 #   INITRD_PHYS must be in RAM
 
 ifeq ($(CONFIG_ARCH_AT91CAP9),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70410000
 else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70410000
 else
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
 initrd_phys-y	:= 0x20410000
 endif
+
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb usb_a9g20.dtb
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-at91/pm.c linux-libre-3.2-gnu1/arch/arm/mach-at91/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-at91/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-at91/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/gpio.h>
 #include <linux/suspend.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
@@ -25,7 +26,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/at91_pmc.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/arch.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/arch.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,8 +136,8 @@ static void __init bcmring_init_machine(
 *
 *****************************************************************************/
 
-static void __init bcmring_fixup(struct machine_desc *desc,
-     struct tag *t, char **cmdline, struct meminfo *mi) {
+static void __init bcmring_fixup(struct tag *t, char **cmdline,
+	struct meminfo *mi) {
 #ifdef CONFIG_BLK_DEV_INITRD
 	printk(KERN_NOTICE "bcmring_fixup\n");
 	t->hdr.tag = ATAG_CORE;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/core.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -235,7 +235,7 @@ void __init bcmring_init_timer(void)
 	 */
 	bcmring_clocksource_init();
 
-	sp804_clockevents_register(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
+	sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
 }
 
 struct sys_timer bcmring_timer = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/dma.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/irqreturn.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
@@ -35,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-bcmring/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <asm/sizes.h>
-#include <mach/memory.h>
 #include <cfg_global.h>
 #include <mach/csp/mm_io.h>
 
@@ -31,7 +30,7 @@
  *  *_SIZE  is the size of the region
  *  *_BASE  is the virtual address
  */
-#define RAM_START               PLAT_PHYS_OFFSET
+#define RAM_START               PHYS_OFFSET
 
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-bcmring/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*****************************************************************************
-* Copyright 2005 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <cfg_global.h>
-
-/*
- * Physical vs virtual RAM address space conversion.  These are
- * private definitions which should NOT be used outside memory.h
- * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
- */
-
-#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
-
-/*
- * Maximum DMA memory allowed is 14M
- */
-#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/irq.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/stddef.h>
 #include <linux/list.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-bcmring/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,3 @@ config BCM_ZRELADDR
 	hex "Compressed ZREL ADDR"
 
 endmenu
-
-# source "drivers/char/bcmring/Kconfig"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-bcmring/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 # Address where decompressor will be written and eventually executed.
 #
 # default to SDRAM
-zreladdr-y      := $(CONFIG_BCM_ZRELADDR)
+zreladdr-y      += $(CONFIG_BCM_ZRELADDR)
 params_phys-y   := 0x00000800
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/mm.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/mm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 *****************************************************************************/
 
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
@@ -53,4 +55,6 @@ void __init bcmring_map_io(void)
 {
 
 	iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc));
+	/* Maximum DMA memory allowed is 14M */
+	init_consistent_dma_size(14 << 20);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-bcmring/timer.c linux-libre-3.2-gnu1/arch/arm/mach-bcmring/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-bcmring/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-bcmring/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 * consent.
 *****************************************************************************/
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <csp/tmrHw.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/autcpu12.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/autcpu12.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/autcpu12.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/autcpu12.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@ void __init autcpu12_map_io(void)
 
 MACHINE_START(AUTCPU12, "autronix autcpu12")
 	/* Maintainer: Thomas Gleixner */
-	.boot_params	= 0xc0020000,
+	.atag_offset	= 0x20000,
 	.map_io		= autcpu12_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/cdb89712.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/cdb89712.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/cdb89712.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/cdb89712.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@ static void __init cdb89712_map_io(void)
 
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
 	/* Maintainer: Ray Lehtiniemi */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= cdb89712_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/ceiva.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/ceiva.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/ceiva.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/ceiva.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@ static void __init ceiva_map_io(void)
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
 	/* Maintainer: Rob Scott */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= ceiva_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/clep7312.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/clep7312.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/clep7312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/clep7312.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,8 +26,7 @@
 #include "common.h"
 
 static void __init
-fixup_clep7312(struct machine_desc *desc, struct tag *tags,
-	    char **cmdline, struct meminfo *mi)
+fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = 0xc0000000;
@@ -37,7 +36,7 @@ fixup_clep7312(struct machine_desc *desc
 
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
 	/* Maintainer: Nobody */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x0100,
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/edb7211-arch.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/edb7211-arch.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/edb7211-arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/edb7211-arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,7 @@ static void __init edb7211_reserve(void)
 }
 
 static void __init
-fixup_edb7211(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
+fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	/*
 	 * Bank start addresses are not present in the information
@@ -57,7 +56,7 @@ fixup_edb7211(struct machine_desc *desc,
 
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
 	/* Maintainer: Jon McClintock */
-	.boot_params	= 0xc0020100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
+	.atag_offset	= 0x20100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
 	.fixup		= fixup_edb7211,
 	.map_io		= edb7211_map_io,
 	.reserve	= edb7211_reserve,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/fortunet.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/fortunet.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/fortunet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/fortunet.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,8 +57,7 @@ typedef struct tag_IMAGE_PARAMS
 #define IMAGE_PARAMS_PHYS	0xC01F0000
 
 static void __init
-fortunet_fixup(struct machine_desc *desc, struct tag *tags,
-		 char **cmdline, struct meminfo *mi)
+fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS);
 	*cmdline = phys_to_virt(ip->command_line);
@@ -75,7 +74,6 @@ fortunet_fixup(struct machine_desc *desc
 
 MACHINE_START(FORTUNET, "ARM-FortuNet")
 	/* Maintainer: FortuNet Inc. */
-	.boot_params	= 0x00000000,
 	.fixup		= fortunet_fixup,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-clps711x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <asm/hardware/clps7111.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 #ifndef CONFIG_DEBUG_CLPS711X_UART2
 		mov	\rp, #0x0000	@ UART1
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-clps711x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 # The standard locations for stuff on CLPS711x type processors
-   zreladdr-y				:= 0xc0028000
+   zreladdr-y				+= 0xc0028000
 params_phys-y				:= 0xc0000100
 # Should probably have some agreement on these...
 initrd_phys-$(CONFIG_ARCH_P720T)	:= 0xc0400000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-clps711x/p720t.c linux-libre-3.2-gnu1/arch/arm/mach-clps711x/p720t.c
--- linux-libre-3.1-gnu1/arch/arm/mach-clps711x/p720t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-clps711x/p720t.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,8 +56,7 @@ static struct map_desc p720t_io_desc[] _
 };
 
 static void __init
-fixup_p720t(struct machine_desc *desc, struct tag *tag,
-	    char **cmdline, struct meminfo *mi)
+fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi)
 {
 	/*
 	 * Our bootloader doesn't setup any tags (yet).
@@ -89,7 +88,7 @@ static void __init p720t_map_io(void)
 
 MACHINE_START(P720T, "ARM-Prospector720T")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.fixup		= fixup_p720t,
 	.map_io		= p720t_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c	2012-01-04 18:55:44.000000000 -0500
@@ -197,7 +197,7 @@ static void __init cns3420_map_io(void)
 }
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= cns3420_map_io,
 	.init_irq	= cns3xxx_init_irq,
 	.timer		= &cns3xxx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart,rp,rv
+		.macro	addruart,rp,rv,tmp
 		mov	\rp, #0x00009000
 		orr	\rv, \rp, #0xf0000000	@ virtual base
 		orr	\rp, \rp, #0x10000000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright 2003 ARM Limited
- * Copyright 2008 Cavium Networks
- *
- * This file 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#define __phys_to_bus(x)	((x) + PHYS_OFFSET)
-#define __bus_to_phys(x)	((x) - PHYS_OFFSET)
-
-#define __virt_to_bus(v)	__phys_to_bus(__virt_to_phys(v))
-#define __bus_to_virt(b)	__phys_to_virt(__bus_to_phys(b))
-#define __pfn_to_bus(p)		__phys_to_bus(__pfn_to_phys(p))
-#define __bus_to_pfn(b)		__phys_to_pfn(__bus_to_phys(b))
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-cns3xxx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-cns3xxx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00C00000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-da830-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-da830-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-da830-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-da830-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -377,7 +377,7 @@ static struct davinci_nand_pdata da830_e
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
 	.timing         = &da830_evm_nandflash_timing,
@@ -676,7 +676,7 @@ static void __init da830_evm_map_io(void
 }
 
 MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= da830_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-da850-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-da850-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-da850-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-da850-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
 #include <linux/input/tps6507x-ts.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/delay.h>
+#include <linux/wl12xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -49,6 +51,9 @@
 #define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
 #define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
 
+#define DA850_WLAN_EN			GPIO_TO_PIN(6, 9)
+#define DA850_WLAN_IRQ			GPIO_TO_PIN(6, 10)
+
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
 static struct mtd_partition da850evm_spiflash_part[] = {
@@ -251,7 +256,7 @@ static struct davinci_nand_pdata da850_e
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &da850_evm_nandflash_timing,
 };
 
@@ -748,7 +753,7 @@ static struct snd_platform_data da850_ev
 	.num_serializer	= ARRAY_SIZE(da850_iis_serializer_direction),
 	.tdm_slots	= 2,
 	.serial_dir	= da850_iis_serializer_direction,
-	.asp_chan_q	= EVENTQ_1,
+	.asp_chan_q	= EVENTQ_0,
 	.version	= MCASP_VERSION_2,
 	.txnumevt	= 1,
 	.rxnumevt	= 1,
@@ -1143,6 +1148,110 @@ static __init int da850_evm_init_cpufreq
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DA850_WL12XX
+
+static void wl12xx_set_power(int index, bool power_on)
+{
+	static bool power_state;
+
+	pr_debug("Powering %s wl12xx", power_on ? "on" : "off");
+
+	if (power_on == power_state)
+		return;
+	power_state = power_on;
+
+	if (power_on) {
+		/* Power up sequence required for wl127x devices */
+		gpio_set_value(DA850_WLAN_EN, 1);
+		usleep_range(15000, 15000);
+		gpio_set_value(DA850_WLAN_EN, 0);
+		usleep_range(1000, 1000);
+		gpio_set_value(DA850_WLAN_EN, 1);
+		msleep(70);
+	} else {
+		gpio_set_value(DA850_WLAN_EN, 0);
+	}
+}
+
+static struct davinci_mmc_config da850_wl12xx_mmc_config = {
+	.set_power	= wl12xx_set_power,
+	.wires		= 4,
+	.max_freq	= 25000000,
+	.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE |
+			  MMC_CAP_POWER_OFF_CARD,
+	.version	= MMC_CTLR_VERSION_2,
+};
+
+static const short da850_wl12xx_pins[] __initconst = {
+	DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD,
+	DA850_GPIO6_9, DA850_GPIO6_10,
+	-1
+};
+
+static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
+	.irq			= -1,
+	.board_ref_clock	= WL12XX_REFCLOCK_38,
+	.platform_quirks	= WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
+};
+
+static __init int da850_wl12xx_init(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(da850_wl12xx_pins);
+	if (ret) {
+		pr_err("wl12xx/mmc mux setup failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = da850_register_mmcsd1(&da850_wl12xx_mmc_config);
+	if (ret) {
+		pr_err("wl12xx/mmc registration failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en");
+	if (ret) {
+		pr_err("Could not request wl12xx enable gpio: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq");
+	if (ret) {
+		pr_err("Could not request wl12xx irq gpio: %d\n", ret);
+		goto free_wlan_en;
+	}
+
+	da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);
+
+	ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
+	if (ret) {
+		pr_err("Could not set wl12xx data: %d\n", ret);
+		goto free_wlan_irq;
+	}
+
+	return 0;
+
+free_wlan_irq:
+	gpio_free(DA850_WLAN_IRQ);
+
+free_wlan_en:
+	gpio_free(DA850_WLAN_EN);
+
+exit:
+	return ret;
+}
+
+#else /* CONFIG_DA850_WL12XX */
+
+static __init int da850_wl12xx_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_DA850_WL12XX */
+
 #define DA850EVM_SATA_REFCLKPN_RATE	(100 * 1000 * 1000)
 
 static __init void da850_evm_init(void)
@@ -1197,6 +1306,11 @@ static __init void da850_evm_init(void)
 		if (ret)
 			pr_warning("da850_evm_init: mmcsd0 registration failed:"
 					" %d\n", ret);
+
+		ret = da850_wl12xx_init();
+		if (ret)
+			pr_warning("da850_evm_init: wl12xx initialization"
+				   " failed: %d\n", ret);
 	}
 
 	davinci_serial_init(&da850_evm_uart_config);
@@ -1291,7 +1405,7 @@ static void __init da850_evm_map_io(void
 }
 
 MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= da850_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm355-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm355-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm355-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm355-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ static struct davinci_nand_pdata davinci
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 };
 
@@ -351,7 +351,7 @@ static __init void dm355_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io	      = dm355_evm_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm355-leopard.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm355-leopard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm355-leopard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm355-leopard.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@ static struct davinci_nand_pdata davinci
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW_SYNDROME,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_nand_resources[] = {
@@ -270,7 +270,7 @@ static __init void dm355_leopard_init(vo
 }
 
 MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io	      = dm355_leopard_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm365-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm365-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm365-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm365-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,7 +107,7 @@ static struct mtd_partition davinci_nand
 		/* UBL (a few copies) plus U-Boot */
 		.name		= "bootloader",
 		.offset		= 0,
-		.size		= 28 * NAND_BLOCK_SIZE,
+		.size		= 30 * NAND_BLOCK_SIZE,
 		.mask_flags	= MTD_WRITEABLE, /* force read-only */
 	}, {
 		/* U-Boot environment */
@@ -139,7 +139,7 @@ static struct davinci_nand_pdata davinci
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 };
 
@@ -612,7 +612,7 @@ static __init void dm365_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
-	.boot_params	= (0x80000100),
+	.atag_offset	= 0x100,
 	.map_io		= dm365_evm_map_io,
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm644x-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm644x-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm644x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm644x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/phy.h>
 #include <linux/clk.h>
 #include <linux/videodev2.h>
+#include <linux/export.h>
 
 #include <media/tvp514x.h>
 
@@ -150,7 +151,7 @@ static struct davinci_nand_pdata davinci
 	.parts		= davinci_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &davinci_evm_nandflash_timing,
 };
 
@@ -712,7 +713,7 @@ static __init void davinci_evm_init(void
 
 MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
 	/* Maintainer: MontaVista Software <source@mvista.com> */
-	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset  = 0x100,
 	.map_io	      = davinci_evm_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm646x-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm646x-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-dm646x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-dm646x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
+#include <linux/export.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -563,7 +564,7 @@ static int setup_vpif_input_channel_mode
 	int val;
 	u32 value;
 
-	if (!vpif_vsclkdis_reg || !cpld_client)
+	if (!vpif_vidclkctl_reg || !cpld_client)
 		return -ENXIO;
 
 	val = i2c_smbus_read_byte(cpld_client);
@@ -571,7 +572,7 @@ static int setup_vpif_input_channel_mode
 		return val;
 
 	spin_lock_irqsave(&vpif_reg_lock, flags);
-	value = __raw_readl(vpif_vsclkdis_reg);
+	value = __raw_readl(vpif_vidclkctl_reg);
 	if (mux_mode) {
 		val &= VPIF_INPUT_TWO_CHANNEL;
 		value |= VIDCH1CLK;
@@ -579,7 +580,7 @@ static int setup_vpif_input_channel_mode
 		val |= VPIF_INPUT_ONE_CHANNEL;
 		value &= ~VIDCH1CLK;
 	}
-	__raw_writel(value, vpif_vsclkdis_reg);
+	__raw_writel(value, vpif_vidclkctl_reg);
 	spin_unlock_irqrestore(&vpif_reg_lock, flags);
 
 	err = i2c_smbus_write_byte(cpld_client, val);
@@ -792,7 +793,7 @@ static __init void evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
@@ -801,7 +802,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVin
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-mityomapl138.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-mityomapl138.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-mityomapl138.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-mityomapl138.c	2012-01-04 18:55:44.000000000 -0500
@@ -396,7 +396,8 @@ static struct davinci_nand_pdata mityoma
 	.parts		= mityomapl138_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(mityomapl138_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
+	.bbt_options	= NAND_BBT_USE_FLASH,
+	.options	= NAND_BUSWIDTH_16,
 	.ecc_bits	= 1, /* 4 bit mode is not supported with 16 bit NAND */
 };
 
@@ -566,7 +567,7 @@ static void __init mityomapl138_map_io(v
 }
 
 MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= mityomapl138_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-neuros-osd2.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-neuros-osd2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-neuros-osd2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-neuros-osd2.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,7 +87,7 @@ static struct davinci_nand_pdata davinci
 	.parts		= davinci_ntosd2_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_ntosd2_nandflash_resource[] = {
@@ -272,7 +272,7 @@ static __init void davinci_ntosd2_init(v
 
 MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
 	/* Maintainer: Neuros Technologies <neuros@groups.google.com> */
-	.boot_params	= (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		 = davinci_ntosd2_map_io,
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-omapl138-hawk.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-omapl138-hawk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-omapl138-hawk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-omapl138-hawk.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,7 +338,7 @@ static void __init omapl138_hawk_map_io(
 }
 
 MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= omapl138_hawk_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-sffsdr.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-sffsdr.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-sffsdr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-sffsdr.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,7 @@ static __init void davinci_sffsdr_init(v
 
 MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
 	/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
-	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset  = 0x100,
 	.map_io	      = davinci_sffsdr_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-tnetv107x-evm.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-tnetv107x-evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/board-tnetv107x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/board-tnetv107x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,7 +144,7 @@ static struct davinci_nand_pdata nand_co
 	.parts		= nand_partitions,
 	.nr_parts	= ARRAY_SIZE(nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.ecc_bits	= 1,
 };
 
@@ -277,7 +277,7 @@ console_initcall(tnetv107x_evm_console_i
 #endif
 
 MACHINE_START(TNETV107X, "TNETV107X EVM")
-	.boot_params	= (TNETV107X_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= tnetv107x_init,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/cdce949.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/cdce949.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/cdce949.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/cdce949.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 
 #include <mach/clock.h>
 #include <mach/cdce949.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/common.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 #include <linux/davinci_emac.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
@@ -86,6 +87,8 @@ void __init davinci_common_init(struct d
 		iotable_init(davinci_soc_info.io_desc,
 				davinci_soc_info.io_desc_num);
 
+	init_consistent_dma_size(14 << 20);
+
 	/*
 	 * Normally devicemaps_init() would flush caches and tlb after
 	 * mdesc->map_io(), but we must also do it here because of the CPU
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/cpufreq.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/cpufreq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/cpufreq.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,11 @@
 #include <linux/platform_device.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/proc-fns.h>
 
 #include <mach/cpuidle.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
 
 #define DAVINCI_CPUIDLE_MAX_STATES	2
 
@@ -78,9 +79,11 @@ static struct davinci_ops davinci_states
 
 /* Actual code that puts the SoC in different idle states */
 static int davinci_enter_idle(struct cpuidle_device *dev,
-						struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+						int index)
 {
-	struct davinci_ops *ops = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
 	struct timeval before, after;
 	int idle_time;
 
@@ -98,13 +101,17 @@ static int davinci_enter_idle(struct cpu
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct cpuidle_device *device;
+	struct cpuidle_driver *driver = &davinci_idle_driver;
 	struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
 
 	device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@@ -116,32 +123,33 @@ static int __init davinci_cpuidle_probe(
 
 	ddr2_reg_base = pdata->ddr2_ctlr_base;
 
-	ret = cpuidle_register_driver(&davinci_idle_driver);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register driver\n");
-		return ret;
-	}
-
 	/* Wait for interrupt state */
-	device->states[0].enter = davinci_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = davinci_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and DDR self refresh state */
-	device->states[1].enter = davinci_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "DDR SR");
-	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+	driver->states[1].enter = davinci_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "DDR SR");
+	strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
 	if (pdata->ddr2_pdown)
 		davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
-	cpuidle_set_statedata(&device->states[1], &davinci_states[1]);
+	cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
 
 	device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+	driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+
+	ret = cpuidle_register_driver(&davinci_idle_driver);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register driver\n");
+		return ret;
+	}
 
 	ret = cpuidle_register_device(device);
 	if (ret) {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/da830.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/da830.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/da830.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/da830.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
@@ -19,7 +20,7 @@
 #include <mach/common.h>
 #include <mach/time.h>
 #include <mach/da8xx.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/da850.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/da850.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/da850.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/da850.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
@@ -27,7 +28,7 @@
 #include <mach/da8xx.h>
 #include <mach/cpufreq.h>
 #include <mach/pm.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -535,6 +536,13 @@ static const struct mux_config da850_pin
 	MUX_CFG(DA850, MMCSD0_DAT_3,	10,	20,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CLK,	10,	0,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CMD,	10,	4,	15,	2,	false)
+	/* MMC/SD1 function */
+	MUX_CFG(DA850, MMCSD1_DAT_0,	18,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_1,	19,	16,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_2,	19,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_3,	19,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CLK,	18,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CMD,	18,	16,	15,	2,	false)
 	/* EMIF2.5/EMIFA function */
 	MUX_CFG(DA850, EMA_D_7,		9,	0,	15,	1,	false)
 	MUX_CFG(DA850, EMA_D_6,		9,	4,	15,	1,	false)
@@ -593,6 +601,8 @@ static const struct mux_config da850_pin
 	MUX_CFG(DA850, GPIO3_13,	7,	8,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_0,		10,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_1,		10,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_9,		13,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_10,	13,	20,	15,	8,	false)
 	MUX_CFG(DA850, GPIO6_13,	13,	8,	15,	8,	false)
 	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/devices-da8xx.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/devices-da8xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/devices-da8xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,6 +136,7 @@ static struct edma_soc_info da830_edma_c
 	.n_cc			= 1,
 	.queue_tc_mapping	= da8xx_queue_tc_mapping,
 	.queue_priority_mapping	= da8xx_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
@@ -151,6 +152,7 @@ static struct edma_soc_info da850_edma_c
 		.n_cc			= 1,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
+		.default_queue		= EVENTQ_1,
 	},
 	{
 		.n_channel		= 32,
@@ -160,6 +162,7 @@ static struct edma_soc_info da850_edma_c
 		.n_cc			= 1,
 		.queue_tc_mapping	= da850_queue_tc_mapping,
 		.queue_priority_mapping	= da850_queue_priority_mapping,
+		.default_queue		= EVENTQ_0,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@ static struct edma_soc_info edma_cc0_inf
 	.n_cc			= 1,
 	.queue_tc_mapping	= edma_tc_mapping,
 	.queue_priority_mapping	= edma_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *tnetv107x_edma_info[EDMA_MAX_CC] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm355.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm355.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm355.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm355.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/gpio.h>
 
 #include <linux/spi/spi.h>
 
@@ -30,6 +29,7 @@
 #include <mach/common.h>
 #include <mach/asp.h>
 #include <mach/spi.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -591,6 +591,7 @@ static struct edma_soc_info edma_cc0_inf
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm355_edma_info[EDMA_MAX_CC] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm365.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm365.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm365.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm365.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,6 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/gpio.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach/map.h>
@@ -34,7 +33,7 @@
 #include <mach/asp.h>
 #include <mach/keyscan.h>
 #include <mach/spi.h>
-
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm644x.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm644x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm644x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm644x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 
@@ -26,6 +25,7 @@
 #include <mach/serial.h>
 #include <mach/common.h>
 #include <mach/asp.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -514,6 +514,7 @@ static struct edma_soc_info edma_cc0_inf
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm644x_edma_info[EDMA_MAX_CC] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm646x.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm646x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/dm646x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/dm646x.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 
@@ -27,6 +26,7 @@
 #include <mach/serial.h>
 #include <mach/common.h>
 #include <mach/asp.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -161,7 +161,6 @@ static struct clk dsp_clk = {
 	.name = "dsp",
 	.parent = &pll1_sysclk1,
 	.lpsc = DM646X_LPSC_C64X_CPU,
-	.flags = PSC_DSP,
 	.usecount = 1,			/* REVISIT how to disable? */
 };
 
@@ -555,6 +554,7 @@ static struct edma_soc_info edma_cc0_inf
 	.n_cc			= 1,
 	.queue_tc_mapping	= dm646x_queue_tc_mapping,
 	.queue_priority_mapping	= dm646x_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm646x_edma_info[EDMA_MAX_CC] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/dma.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1435,12 +1435,11 @@ static int __init edma_probe(struct plat
 			goto fail1;
 		}
 
-		edma_cc[j] = kmalloc(sizeof(struct edma), GFP_KERNEL);
+		edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
 		if (!edma_cc[j]) {
 			status = -ENOMEM;
 			goto fail1;
 		}
-		memset(edma_cc[j], 0, sizeof(struct edma));
 
 		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
 							EDMA_MAX_DMACH);
@@ -1450,8 +1449,6 @@ static int __init edma_probe(struct plat
 							EDMA_MAX_CC);
 
 		edma_cc[j]->default_queue = info[j]->default_queue;
-		if (!edma_cc[j]->default_queue)
-			edma_cc[j]->default_queue = EVENTQ_1;
 
 		dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
 			edmacc_regs_base[j]);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,460 +0,0 @@
-/*
- * TI DaVinci GPIO Support
- *
- * Copyright (c) 2006-2007 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/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/gpio.h>
-
-#include <asm/mach/irq.h>
-
-struct davinci_gpio_regs {
-	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;
-};
-
-#define chip2controller(chip)	\
-	container_of(chip, struct davinci_gpio_controller, chip)
-
-static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
-static void __iomem *gpio_base;
-
-static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
-{
-	void __iomem *ptr;
-
-	if (gpio < 32 * 1)
-		ptr = gpio_base + 0x10;
-	else if (gpio < 32 * 2)
-		ptr = gpio_base + 0x38;
-	else if (gpio < 32 * 3)
-		ptr = gpio_base + 0x60;
-	else if (gpio < 32 * 4)
-		ptr = gpio_base + 0x88;
-	else if (gpio < 32 * 5)
-		ptr = gpio_base + 0xb0;
-	else
-		ptr = NULL;
-	return ptr;
-}
-
-static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
-{
-	struct davinci_gpio_regs __iomem *g;
-
-	g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
-
-	return g;
-}
-
-static int __init davinci_gpio_irq_setup(void);
-
-/*--------------------------------------------------------------------------*/
-
-/* board setup code *MUST* setup pinmux and enable the GPIO clock. */
-static inline int __davinci_direction(struct gpio_chip *chip,
-			unsigned offset, bool out, int value)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-	unsigned long flags;
-	u32 temp;
-	u32 mask = 1 << offset;
-
-	spin_lock_irqsave(&d->lock, flags);
-	temp = __raw_readl(&g->dir);
-	if (out) {
-		temp &= ~mask;
-		__raw_writel(mask, value ? &g->set_data : &g->clr_data);
-	} else {
-		temp |= mask;
-	}
-	__raw_writel(temp, &g->dir);
-	spin_unlock_irqrestore(&d->lock, flags);
-
-	return 0;
-}
-
-static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	return __davinci_direction(chip, offset, false, 0);
-}
-
-static int
-davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
-{
-	return __davinci_direction(chip, offset, true, value);
-}
-
-/*
- * 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.
- */
-static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-
-	return (1 << offset) & __raw_readl(&g->in_data);
-}
-
-/*
- * Assuming the pin is muxed as a gpio output, set its output value.
- */
-static void
-davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-
-	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
-}
-
-static int __init davinci_gpio_setup(void)
-{
-	int i, base;
-	unsigned ngpio;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs *regs;
-
-	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI)
-		return 0;
-
-	/*
-	 * The gpio banks conceptually expose a segmented bitmap,
-	 * and "ngpio" is one more than the largest zero-based
-	 * bit index that's valid.
-	 */
-	ngpio = soc_info->gpio_num;
-	if (ngpio == 0) {
-		pr_err("GPIO setup:  how many GPIOs?\n");
-		return -EINVAL;
-	}
-
-	if (WARN_ON(DAVINCI_N_GPIO < ngpio))
-		ngpio = DAVINCI_N_GPIO;
-
-	gpio_base = ioremap(soc_info->gpio_base, SZ_4K);
-	if (WARN_ON(!gpio_base))
-		return -ENOMEM;
-
-	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
-		chips[i].chip.label = "DaVinci";
-
-		chips[i].chip.direction_input = davinci_direction_in;
-		chips[i].chip.get = davinci_gpio_get;
-		chips[i].chip.direction_output = davinci_direction_out;
-		chips[i].chip.set = davinci_gpio_set;
-
-		chips[i].chip.base = base;
-		chips[i].chip.ngpio = ngpio - base;
-		if (chips[i].chip.ngpio > 32)
-			chips[i].chip.ngpio = 32;
-
-		spin_lock_init(&chips[i].lock);
-
-		regs = gpio2regs(base);
-		chips[i].regs = regs;
-		chips[i].set_data = &regs->set_data;
-		chips[i].clr_data = &regs->clr_data;
-		chips[i].in_data = &regs->in_data;
-
-		gpiochip_add(&chips[i].chip);
-	}
-
-	soc_info->gpio_ctlrs = chips;
-	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
-
-	davinci_gpio_irq_setup();
-	return 0;
-}
-pure_initcall(davinci_gpio_setup);
-
-/*--------------------------------------------------------------------------*/
-/*
- * 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:  The first few GPIOs also have direct INTC hookups in addition
- * to their GPIOBNK0 irq, with a bit less overhead.
- *
- * All those INTC hookups (direct, plus several IRQ banks) can also
- * serve as EDMA event triggers.
- */
-
-static void gpio_irq_disable(struct irq_data *d)
-{
-	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_handler_data(d);
-
-	__raw_writel(mask, &g->clr_falling);
-	__raw_writel(mask, &g->clr_rising);
-}
-
-static void gpio_irq_enable(struct irq_data *d)
-{
-	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_handler_data(d);
-	unsigned status = irqd_get_trigger_type(d);
-
-	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
-	if (!status)
-		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
-
-	if (status & IRQ_TYPE_EDGE_FALLING)
-		__raw_writel(mask, &g->set_falling);
-	if (status & IRQ_TYPE_EDGE_RISING)
-		__raw_writel(mask, &g->set_rising);
-}
-
-static int gpio_irq_type(struct irq_data *d, unsigned trigger)
-{
-	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_handler_data(d);
-
-	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		return -EINVAL;
-
-	return 0;
-}
-
-static struct irq_chip gpio_irqchip = {
-	.name		= "GPIO",
-	.irq_enable	= gpio_irq_enable,
-	.irq_disable	= gpio_irq_disable,
-	.irq_set_type	= gpio_irq_type,
-	.flags		= IRQCHIP_SET_TYPE_MASKED,
-};
-
-static void
-gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	struct davinci_gpio_regs __iomem *g;
-	u32 mask = 0xffff;
-	struct davinci_gpio_controller *d;
-
-	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
-	g = (struct davinci_gpio_regs __iomem *)d->regs;
-
-	/* we only care about one bank */
-	if (irq & 1)
-		mask <<= 16;
-
-	/* temporarily mask (level sensitive) parent IRQ */
-	desc->irq_data.chip->irq_mask(&desc->irq_data);
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-	while (1) {
-		u32		status;
-		int		n;
-		int		res;
-
-		/* ack any irqs */
-		status = __raw_readl(&g->intstat) & mask;
-		if (!status)
-			break;
-		__raw_writel(status, &g->intstat);
-
-		/* now demux them to the right lowlevel handler */
-		n = d->irq_base;
-		if (irq & 1) {
-			n += 16;
-			status >>= 16;
-		}
-
-		while (status) {
-			res = ffs(status);
-			n += res;
-			generic_handle_irq(n - 1);
-			status >>= res;
-		}
-	}
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-	/* now it may re-trigger */
-}
-
-static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-
-	if (d->irq_base >= 0)
-		return d->irq_base + offset;
-	else
-		return -ENODEV;
-}
-
-static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-
-	/* NOTE:  we assume for now that only irqs in the first gpio_chip
-	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
-	 */
-	if (offset < soc_info->gpio_unbanked)
-		return soc_info->gpio_irq + offset;
-	else
-		return -ENODEV;
-}
-
-static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
-{
-	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_handler_data(d);
-
-	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		return -EINVAL;
-
-	__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;
-}
-
-/*
- * NOTE:  for suspend/resume, probably best to make a platform_device with
- * suspend_late/resume_resume calls hooking into 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
- * (dm6446) can be set appropriately for GPIOV33 pins.
- */
-
-static int __init davinci_gpio_irq_setup(void)
-{
-	unsigned	gpio, irq, bank;
-	struct clk	*clk;
-	u32		binten = 0;
-	unsigned	ngpio, bank_irq;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs	__iomem *g;
-
-	ngpio = soc_info->gpio_num;
-
-	bank_irq = soc_info->gpio_irq;
-	if (bank_irq == 0) {
-		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
-		return -EINVAL;
-	}
-
-	clk = clk_get(NULL, "gpio");
-	if (IS_ERR(clk)) {
-		printk(KERN_ERR "Error %ld getting gpio clock?\n",
-		       PTR_ERR(clk));
-		return PTR_ERR(clk);
-	}
-	clk_enable(clk);
-
-	/* Arrange gpio_to_irq() support, handling either direct IRQs or
-	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
-	 * IRQs, while the others use banked IRQs, would need some setup
-	 * tweaks to recognize hardware which can do that.
-	 */
-	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
-		chips[bank].chip.to_irq = gpio_to_irq_banked;
-		chips[bank].irq_base = soc_info->gpio_unbanked
-			? -EINVAL
-			: (soc_info->intc_irq_num + gpio);
-	}
-
-	/*
-	 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
-	 * controller only handling trigger modes.  We currently assume no
-	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
-	 */
-	if (soc_info->gpio_unbanked) {
-		static struct irq_chip gpio_irqchip_unbanked;
-
-		/* pass "bank 0" GPIO IRQs to AINTC */
-		chips[0].chip.to_irq = gpio_to_irq_unbanked;
-		binten = BIT(0);
-
-		/* AINTC handles mask/unmask; GPIO handles triggering */
-		irq = bank_irq;
-		gpio_irqchip_unbanked = *irq_get_chip(irq);
-		gpio_irqchip_unbanked.name = "GPIO-AINTC";
-		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
-
-		/* default trigger: both edges */
-		g = gpio2regs(0);
-		__raw_writel(~0, &g->set_falling);
-		__raw_writel(~0, &g->set_rising);
-
-		/* set the direct IRQs up to use that irqchip */
-		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-			irq_set_chip(irq, &gpio_irqchip_unbanked);
-			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
-			irq_set_chip_data(irq, (__force void *)g);
-			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
-		}
-
-		goto done;
-	}
-
-	/*
-	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
-	 * then chain through our own handler.
-	 */
-	for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
-			gpio < ngpio;
-			bank++, bank_irq++) {
-		unsigned		i;
-
-		/* disabled by default, enabled only as needed */
-		g = gpio2regs(gpio);
-		__raw_writel(~0, &g->clr_falling);
-		__raw_writel(~0, &g->clr_rising);
-
-		/* set up all irqs in this bank */
-		irq_set_chained_handler(bank_irq, gpio_irq_handler);
-
-		/*
-		 * Each chip handles 32 gpios, and each irq bank consists of 16
-		 * gpio irqs. Pass the irq bank's corresponding controller to
-		 * the chained irq handler.
-		 */
-		irq_set_handler_data(bank_irq, &chips[gpio / 32]);
-
-		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
-			irq_set_chip(irq, &gpio_irqchip);
-			irq_set_chip_data(irq, (__force void *)g);
-			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
-			irq_set_handler(irq, handle_simple_irq);
-			set_irq_flags(irq, IRQF_VALID);
-		}
-
-		binten |= BIT(bank);
-	}
-
-done:
-	/* BINTEN -- per-bank interrupt enable. genirq would also let these
-	 * bits be set/cleared dynamically.
-	 */
-	__raw_writel(binten, gpio_base + 0x08);
-
-	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
-
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/*
- * Texas Instruments TNETV107X GPIO Controller
- *
- * Copyright (C) 2010 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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/tnetv107x.h>
-
-struct tnetv107x_gpio_regs {
-	u32	idver;
-	u32	data_in[3];
-	u32	data_out[3];
-	u32	direction[3];
-	u32	enable[3];
-};
-
-#define gpio_reg_index(gpio)	((gpio) >> 5)
-#define gpio_reg_bit(gpio)	BIT((gpio) & 0x1f)
-
-#define gpio_reg_rmw(reg, mask, val)	\
-	__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
-
-#define gpio_reg_set_bit(reg, gpio)	\
-	gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
-
-#define gpio_reg_clear_bit(reg, gpio)	\
-	gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
-
-#define gpio_reg_get_bit(reg, gpio)	\
-	(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
-
-#define chip2controller(chip)		\
-	container_of(chip, struct davinci_gpio_controller, chip)
-
-#define TNETV107X_GPIO_CTLRS	DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
-
-static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
-
-static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_set_bit(regs->enable, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_clear_bit(regs->enable, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-}
-
-static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_set_bit(regs->direction, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
-		unsigned offset, int value)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	if (value)
-		gpio_reg_set_bit(regs->data_out, gpio);
-	else
-		gpio_reg_clear_bit(regs->data_out, gpio);
-
-	gpio_reg_clear_bit(regs->direction, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	int ret;
-
-	ret = gpio_reg_get_bit(regs->data_in, gpio);
-
-	return ret ? 1 : 0;
-}
-
-static void tnetv107x_gpio_set(struct gpio_chip *chip,
-		unsigned offset, int value)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	if (value)
-		gpio_reg_set_bit(regs->data_out, gpio);
-	else
-		gpio_reg_clear_bit(regs->data_out, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-}
-
-static int __init tnetv107x_gpio_setup(void)
-{
-	int i, base;
-	unsigned ngpio;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct tnetv107x_gpio_regs *regs;
-	struct davinci_gpio_controller *ctlr;
-
-	if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
-		return 0;
-
-	ngpio = soc_info->gpio_num;
-	if (ngpio == 0) {
-		pr_err("GPIO setup:  how many GPIOs?\n");
-		return -EINVAL;
-	}
-
-	if (WARN_ON(TNETV107X_N_GPIO < ngpio))
-		ngpio = TNETV107X_N_GPIO;
-
-	regs = ioremap(soc_info->gpio_base, SZ_4K);
-	if (WARN_ON(!regs))
-		return -EINVAL;
-
-	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
-		ctlr = &chips[i];
-
-		ctlr->chip.label	= "tnetv107x";
-		ctlr->chip.can_sleep	= 0;
-		ctlr->chip.base		= base;
-		ctlr->chip.ngpio	= ngpio - base;
-		if (ctlr->chip.ngpio > 32)
-			ctlr->chip.ngpio = 32;
-
-		ctlr->chip.request		= tnetv107x_gpio_request;
-		ctlr->chip.free			= tnetv107x_gpio_free;
-		ctlr->chip.direction_input	= tnetv107x_gpio_dir_in;
-		ctlr->chip.get			= tnetv107x_gpio_get;
-		ctlr->chip.direction_output	= tnetv107x_gpio_dir_out;
-		ctlr->chip.set			= tnetv107x_gpio_set;
-
-		spin_lock_init(&ctlr->lock);
-
-		ctlr->regs	= regs;
-		ctlr->set_data	= &regs->data_out[i];
-		ctlr->clr_data	= &regs->data_out[i];
-		ctlr->in_data	= &regs->data_in[i];
-
-		gpiochip_add(&ctlr->chip);
-	}
-
-	soc_info->gpio_ctlrs = chips;
-	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
-	return 0;
-}
-pure_initcall(tnetv107x_gpio_setup);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/ddr2.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/ddr2.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/ddr2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/ddr2.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#define DDR2_SDRCR_OFFSET	0xc
+#define DDR2_SRPD_BIT		(1 << 23)
+#define DDR2_MCLKSTOPEN_BIT	(1 << 30)
+#define DDR2_LPMODEN_BIT	(1 << 31)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -18,56 +18,50 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #include <mach/serial.h>
 
 #define UART_SHIFT	2
 
-#define davinci_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define davinci_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
 		.pushsection .data
 davinci_uart_phys:	.word	0
 davinci_uart_virt:	.word	0
 		.popsection
 
-		.macro addruart, rp, rv
+		.macro addruart, rp, rv, tmp
 
 		/* Use davinci_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =davinci_uart_v2p(davinci_uart_phys)
-		ldrne	\rp, =davinci_uart_phys
-		add	\rv, \rp, #4		@ davinci_uart_virt
-		ldr	\rp, [\rp, #0]
-		ldr	\rv, [\rv, #0]
+10:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ davinci_uart_phys
+		ldr	\rv, [\tmp, #4]		@ davinci_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART address set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
+		and	\rp, pc, #0xff000000
+		ldr	\rv, =DAVINCI_UART_INFO_OFS
+		add	\rp, \rp, \rv
 
 		/* Copy uart phys address from decompressor uart info */
-		ldreq	\rv, =davinci_uart_v2p(davinci_uart_phys)
-		ldrne	\rv, =davinci_uart_phys
-		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
-		ldr	\rp, [\rp, #0]
-		str	\rp, [\rv]
+		ldr	\rv, [\rp, #0]
+		str	\rv, [\tmp, #0]
 
 		/* Copy uart virt address from decompressor uart info */
-		ldreq	\rv, =davinci_uart_v2p(davinci_uart_virt)
-		ldrne	\rv, =davinci_uart_virt
-		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
-		ldr	\rp, [\rp, #4]
-		str	\rp, [\rv]
+		ldr	\rv, [\rp, #4]
+		str	\rv, [\tmp, #4]
 
 		b	10b
-99:
+
+		.align
+99:		.word	.
+		.word	davinci_uart_phys
+		.ltorg
+
+100:
 		.endm
 
 		.macro	senduart,rd,rx
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/gpio-davinci.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/gpio-davinci.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/gpio-davinci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/gpio-davinci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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_DAVINCI_GPIO_H
+#define	__DAVINCI_DAVINCI_GPIO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/gpio.h>
+
+#include <mach/irqs.h>
+#include <mach/common.h>
+
+#define DAVINCI_GPIO_BASE 0x01C67000
+
+enum davinci_gpio_type {
+	GPIO_TYPE_DAVINCI = 0,
+	GPIO_TYPE_TNETV107X,
+};
+
+/*
+ * 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 PINMUX registers to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
+ * and maybe for later updates, code may write GPIO(N).  These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two.  A given chip
+ * may not support all the GPIOs in that range.
+ *
+ * GPIOs can also be on external chips, numbered after the ones built-in
+ * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
+ */
+#define	GPIO(X)		(X)		/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
+
+/* Convert GPIO signal to GPIO pin number */
+#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
+
+struct davinci_gpio_controller {
+	struct gpio_chip	chip;
+	int			irq_base;
+	spinlock_t		lock;
+	void __iomem		*regs;
+	void __iomem		*set_data;
+	void __iomem		*clr_data;
+	void __iomem		*in_data;
+};
+
+/* 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 davinci_gpio_controller *
+__gpio_to_controller(unsigned gpio)
+{
+	struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
+	int index = gpio / 32;
+
+	if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
+		return NULL;
+
+	return ctlrs + index;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+	return 1 << (gpio % 32);
+}
+
+#endif	/* __DAVINCI_DAVINCI_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,80 +13,12 @@
 #ifndef	__DAVINCI_GPIO_H
 #define	__DAVINCI_GPIO_H
 
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
 #include <asm-generic/gpio.h>
 
-#include <mach/irqs.h>
-#include <mach/common.h>
-
-#define DAVINCI_GPIO_BASE 0x01C67000
-
-enum davinci_gpio_type {
-	GPIO_TYPE_DAVINCI = 0,
-	GPIO_TYPE_TNETV107X,
-};
-
-/*
- * 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 PINMUX registers to be sure those pins are
- * used as gpios, not with other peripherals.
- *
- * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
- * and maybe for later updates, code may write GPIO(N).  These may be
- * all 1.8V signals, all 3.3V ones, or a mix of the two.  A given chip
- * may not support all the GPIOs in that range.
- *
- * GPIOs can also be on external chips, numbered after the ones built-in
- * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
- */
-#define	GPIO(X)		(X)		/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
-
-/* Convert GPIO signal to GPIO pin number */
-#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
-
-struct davinci_gpio_controller {
-	struct gpio_chip	chip;
-	int			irq_base;
-	spinlock_t		lock;
-	void __iomem		*regs;
-	void __iomem		*set_data;
-	void __iomem		*clr_data;
-	void __iomem		*in_data;
-};
-
-/* 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 davinci_gpio_controller *
-__gpio_to_controller(unsigned gpio)
-{
-	struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
-	int index = gpio / 32;
-
-	if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
-		return NULL;
-
-	return ctlrs + index;
-}
+#define __ARM_GPIOLIB_COMPLEX
 
-static inline u32 __gpio_mask(unsigned gpio)
-{
-	return 1 << (gpio % 32);
-}
+/* The inline versions use the static inlines in the driver header */
+#include "gpio-davinci.h"
 
 /*
  * The get/set/clear functions will inline when called with constant
@@ -147,11 +79,6 @@ static inline int gpio_cansleep(unsigned
 		return __gpio_cansleep(gpio);
 }
 
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned irq)
 {
 	/* don't support the reverse mapping */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * DaVinci memory space definitions
- *
- * Author: Kevin Hilman, 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/**************************************************************************
- * Included Files
- **************************************************************************/
-#include <asm/page.h>
-#include <asm/sizes.h>
-
-/**************************************************************************
- * Definitions
- **************************************************************************/
-#define DAVINCI_DDR_BASE	0x80000000
-#define DA8XX_DDR_BASE		0xc0000000
-
-#if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx)
-#error Cannot enable DaVinci and DA8XX platforms concurrently
-#elif defined(CONFIG_ARCH_DAVINCI_DA8XX)
-#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE
-#else
-#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE
-#endif
-
-#define DDR2_SDRCR_OFFSET	0xc
-#define DDR2_SRPD_BIT		BIT(23)
-#define DDR2_MCLKSTOPEN_BIT	BIT(30)
-#define DDR2_LPMODEN_BIT	BIT(31)
-
-/*
- * Increase size of DMA-consistent memory region
- */
-#define CONSISTENT_DMA_SIZE (14<<20)
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/mmc.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/mmc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,9 @@ struct davinci_mmc_config {
 	/* get_cd()/get_wp() may sleep */
 	int	(*get_cd)(int module);
 	int	(*get_ro)(int module);
+
+	void	(*set_power)(int module, bool on);
+
 	/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
 	u8	wires;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/mux.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/mux.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/mux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/mux.h	2012-01-04 18:55:44.000000000 -0500
@@ -857,6 +857,14 @@ enum davinci_da850_index {
 	DA850_MMCSD0_CLK,
 	DA850_MMCSD0_CMD,
 
+	/* MMC/SD1 function */
+	DA850_MMCSD1_DAT_0,
+	DA850_MMCSD1_DAT_1,
+	DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3,
+	DA850_MMCSD1_CLK,
+	DA850_MMCSD1_CMD,
+
 	/* EMIF2.5/EMIFA function */
 	DA850_EMA_D_7,
 	DA850_EMA_D_6,
@@ -916,6 +924,8 @@ enum davinci_da850_index {
 	DA850_GPIO3_13,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_GPIO6_9,
+	DA850_GPIO6_10,
 	DA850_GPIO6_13,
 	DA850_RTC_ALARM,
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/nand.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/nand.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/nand.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/nand.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,10 @@ struct davinci_nand_pdata {		/* platform
 	nand_ecc_modes_t	ecc_mode;
 	u8			ecc_bits;
 
-	/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
+	/* e.g. NAND_BUSWIDTH_16 */
 	unsigned		options;
+	/* e.g. NAND_BBT_USE_FLASH */
+	unsigned		bbt_options;
 
 	/* Main and mirror bbt descriptor overrides */
 	struct nand_bbt_descr	*bbt_td;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/psc.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/psc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/psc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/psc.h	2012-01-04 18:55:44.000000000 -0500
@@ -233,7 +233,7 @@
 #define PTCMD		0x120
 #define PTSTAT		0x128
 #define PDSTAT		0x200
-#define PDCTL1		0x304
+#define PDCTL		0x300
 #define MDSTAT		0x800
 #define MDCTL		0xA00
 
@@ -244,7 +244,10 @@
 #define PSC_STATE_ENABLE	3
 
 #define MDSTAT_STATE_MASK	0x3f
+#define PDSTAT_STATE_MASK	0x1f
 #define MDCTL_FORCE		BIT(31)
+#define PDCTL_NEXT		BIT(1)
+#define PDCTL_EPCGOOD		BIT(8)
 
 #ifndef __ASSEMBLER__
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/serial.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/serial.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,9 @@
  * macros in debug-macro.S.
  *
  * This area sits just below the page tables (see arch/arm/kernel/head.S).
+ * We define it as a relative offset from start of usable RAM.
  */
-#define DAVINCI_UART_INFO	(PLAT_PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO_OFS	0x3ff8
 
 #define DAVINCI_UART0_BASE	(IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE	(IO_PHYS + 0x20400)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,12 @@ static inline void flush(void)
 
 static inline void set_uart_info(u32 phys, void * __iomem virt)
 {
-	u32 *uart_info = (u32 *)(DAVINCI_UART_INFO);
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS);
 
 	uart = (u32 *)phys;
 	uart_info[0] = phys;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-davinci/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -192,6 +192,16 @@ config DA850_UI_RMII
 
 endchoice
 
+config DA850_WL12XX
+	bool "AM18x wl1271 daughter board"
+	depends on MACH_DAVINCI_DA850_EVM
+	help
+	  The wl1271 daughter card for AM18x EVMs is a combo wireless
+	  connectivity add-on card, based on the LS Research TiWi module with
+	  Texas Instruments' wl1271 solution.
+	  Say Y if you want to use a wl1271 expansion card connected to the
+	  AM18x EVM.
+
 config GPIO_PCA953X
 	default MACH_DAVINCI_DA850_EVM
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/Makefile linux-libre-3.2-gnu1/arch/arm/mach-davinci/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 
 # Common objects
 obj-y 			:= time.o clock.o serial.o io.o psc.o \
-			   gpio.o dma.o usb.o common.o sram.o aemif.o
+			   dma.o usb.o common.o sram.o aemif.o
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
@@ -17,7 +17,6 @@ obj-$(CONFIG_ARCH_DAVINCI_DM365)	+= dm36
 obj-$(CONFIG_ARCH_DAVINCI_DA830)        += da830.o devices-da8xx.o
 obj-$(CONFIG_ARCH_DAVINCI_DA850)        += da850.o devices-da8xx.o
 obj-$(CONFIG_ARCH_DAVINCI_TNETV107X)    += tnetv107x.o devices-tnetv107x.o
-obj-$(CONFIG_ARCH_DAVINCI_TNETV107X)    += gpio-tnetv107x.o
 
 obj-$(CONFIG_AINTC)			+= irq.o
 obj-$(CONFIG_CP_INTC)			+= cp_intc.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-davinci/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -2,12 +2,12 @@ ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y)
 ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)
 $(error Cannot enable DaVinci and DA8XX platforms concurrently)
 else
-   zreladdr-y	:= 0xc0008000
+   zreladdr-y	+= 0xc0008000
 params_phys-y	:= 0xc0000100
 initrd_phys-y	:= 0xc0800000
 endif
 else
-   zreladdr-y	:= 0x80008000
+   zreladdr-y	+= 0x80008000
 params_phys-y	:= 0x80000100
 initrd_phys-y	:= 0x80800000
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/psc.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/psc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/psc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/psc.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@ int __init davinci_psc_is_clk_active(uns
 void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, bool enable, u32 flags)
 {
-	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
+	u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl;
 	void __iomem *psc_base;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	u32 next_state = PSC_STATE_ENABLE;
@@ -79,11 +79,11 @@ void davinci_psc_config(unsigned int dom
 		mdctl |= MDCTL_FORCE;
 	__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
 
-	pdstat = __raw_readl(psc_base + PDSTAT);
-	if ((pdstat & 0x00000001) == 0) {
-		pdctl1 = __raw_readl(psc_base + PDCTL1);
-		pdctl1 |= 0x1;
-		__raw_writel(pdctl1, psc_base + PDCTL1);
+	pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain);
+	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
+		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
+		pdctl |= PDCTL_NEXT;
+		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
 
 		ptcmd = 1 << domain;
 		__raw_writel(ptcmd, psc_base + PTCMD);
@@ -92,9 +92,9 @@ void davinci_psc_config(unsigned int dom
 			epcpr = __raw_readl(psc_base + EPCPR);
 		} while ((((epcpr >> domain) & 1) == 0));
 
-		pdctl1 = __raw_readl(psc_base + PDCTL1);
-		pdctl1 |= 0x100;
-		__raw_writel(pdctl1, psc_base + PDCTL1);
+		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
+		pdctl |= PDCTL_EPCGOOD;
+		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
 	} else {
 		ptcmd = 1 << domain;
 		__raw_writel(ptcmd, psc_base + PTCMD);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/sleep.S linux-libre-3.2-gnu1/arch/arm/mach-davinci/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/psc.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
 
 #include "clock.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-davinci/tnetv107x.c linux-libre-3.2-gnu1/arch/arm/mach-davinci/tnetv107x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-davinci/tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-davinci/tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -27,9 +28,9 @@
 #include <mach/psc.h>
 #include <mach/cp_intc.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/hardware.h>
 #include <mach/tnetv107x.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-dove/cm-a510.c linux-libre-3.2-gnu1/arch/arm/mach-dove/cm-a510.c
--- linux-libre-3.1-gnu1/arch/arm/mach-dove/cm-a510.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-dove/cm-a510.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,7 +87,7 @@ static void __init cm_a510_init(void)
 }
 
 MACHINE_START(CM_A510, "Compulab CM-A510 Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= cm_a510_init,
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-dove/dove-db-setup.c linux-libre-3.2-gnu1/arch/arm/mach-dove/dove-db-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-dove/dove-db-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-dove/dove-db-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,7 +94,7 @@ static void __init dove_db_init(void)
 }
 
 MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dove_db_init,
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-dove/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-dove/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-dove/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-dove/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =DOVE_SB_REGS_PHYS_BASE
 	ldr	\rv, =DOVE_SB_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-dove/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-dove/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-dove/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-dove/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-dove/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-dove/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-dove/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-dove/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/core.c linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -280,7 +280,7 @@ arch_initcall(ebsa110_init);
 
 MACHINE_START(EBSA110, "EBSA110")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x00000400,
+	.atag_offset	= 0x400,
 	.reserve_lp0	= 1,
 	.reserve_lp2	= 1,
 	.soft_reboot	= 1,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 **/
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xf0000000
 		orr	\rp, \rp, #0x00000be0
 		mov	\rp, \rv
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
-
 u8 __inb8(unsigned int port);
 void __outb8(u8  val, unsigned int port);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ebsa110/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ebsa110/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000400
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/adssphere.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/adssphere.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/adssphere.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/adssphere.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@ static void __init adssphere_init_machin
 
 MACHINE_START(ADSSPHERE, "ADS Sphere board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/core.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,11 +33,13 @@
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
 #include <mach/ep93xx_keypad.h>
 #include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/edb93xx.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/edb93xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/edb93xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/edb93xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <mach/hardware.h>
 #include <mach/fb.h>
 #include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -159,6 +160,11 @@ static void __init edb93xx_register_spi(
 /*************************************************************************
  * EDB93xx I2S
  *************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+	.name		= "edb93xx-audio",
+	.id		= -1,
+};
+
 static int __init edb93xx_has_audio(void)
 {
 	return (machine_is_edb9301() || machine_is_edb9302() ||
@@ -170,6 +176,7 @@ static void __init edb93xx_register_i2s(
 {
 	if (edb93xx_has_audio()) {
 		ep93xx_register_i2s();
+		platform_device_register(&edb93xx_audio_device);
 	}
 }
 
@@ -240,7 +247,7 @@ static void __init edb93xx_init_machine(
 #ifdef CONFIG_MACH_EDB9301
 MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -251,7 +258,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302
 MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
 	/* Maintainer: George Kashperko <george@chas.com.ua> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -262,7 +269,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302A
 MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -273,7 +280,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307
 MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -284,7 +291,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307A
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -295,7 +302,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9312
 MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
 	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -306,7 +313,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315
 MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -317,7 +324,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315A
 MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/gesbc9312.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/gesbc9312.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/gesbc9312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/gesbc9312.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@ static void __init gesbc9312_init_machin
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  */
 #include <mach/ep93xx-regs.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =EP93XX_APB_PHYS_BASE	@ Physical base
 		ldr	\rv, =EP93XX_APB_VIRT_BASE	@ virtual base
 		orr	\rp, \rp, #0x000c0000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+/* GPIO port A.  */
+#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B.  */
+#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C.  */
+#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D.  */
+#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
+#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E.  */
+#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F.  */
+#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
+#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G.  */
+#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H.  */
+#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
+#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,120 +1 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/gpio.h
- */
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-/* GPIO port A.  */
-#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
-#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
-#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
-#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
-#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
-#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
-#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
-#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
-#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)
-
-/* GPIO port B.  */
-#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
-#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
-#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
-#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
-#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
-#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
-#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
-#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
-#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)
-
-/* GPIO port C.  */
-#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
-#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
-#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
-#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
-#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
-#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
-#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
-#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
-#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)
-
-/* GPIO port D.  */
-#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
-#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
-#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
-#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
-#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
-#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
-#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
-#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
-#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)
-
-/* GPIO port E.  */
-#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
-#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
-#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
-#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
-#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
-#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
-#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
-#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
-#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)
-
-/* GPIO port F.  */
-#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
-#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
-#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
-#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
-#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
-#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
-#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
-#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
-#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)
-
-/* GPIO port G.  */
-#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
-#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
-#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
-#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
-#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
-#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
-#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
-#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
-#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)
-
-/* GPIO port H.  */
-#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
-#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
-#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
-#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
-#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
-#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
-#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
-#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
-#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for gpio line identifiers */
-#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for irq capable line identifiers */
-#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
-
-/* new generic GPIO API - see Documentation/gpio.txt */
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-
-/*
- * Map GPIO A0..A7  (0..7)  to irq 64..71,
- *          B0..B7  (7..15) to irq 72..79, and
- *          F0..F7 (16..24) to irq 80..87.
- */
-#define gpio_to_irq(gpio)	\
-	(((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL)
-
-#define irq_to_gpio(irq)	((irq) - gpio_to_irq(0))
-
-#endif
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,13 @@ config MACH_TS72XX
 	  Say 'Y' here if you want your kernel to support the
 	  Technologic Systems TS-72xx board.
 
+config MACH_VISION_EP9307
+	bool "Support Vision Engraving Systems EP9307 SoM"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Vision Engraving Systems EP9307 SoM.
+
 choice
 	prompt "Select a UART for early kernel messages"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Makefile linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,3 +15,4 @@ obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
 obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o
 obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o
 obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,14 +1,14 @@
-   zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00008000
+   zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	+= 0x00008000
 params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		+= 0xc0008000
 params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		:= 0xd0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		+= 0xd0008000
 params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		:= 0xd0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		:= 0xe0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		+= 0xe0008000
 params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		:= 0xe0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	:= 0xf0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	+= 0xf0008000
 params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	:= 0xf0000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/micro9.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/micro9.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/micro9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/micro9.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ static void __init micro9_init_machine(v
 #ifdef CONFIG_MACH_MICRO9H
 MACHINE_START(MICRO9, "Contec Micro9-High")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -88,7 +88,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9M
 MACHINE_START(MICRO9M, "Contec Micro9-Mid")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -99,7 +99,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9L
 MACHINE_START(MICRO9L, "Contec Micro9-Lite")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -110,7 +110,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9S
 MACHINE_START(MICRO9S, "Contec Micro9-Slim")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/simone.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/simone.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/simone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/simone.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,12 +18,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -53,6 +53,17 @@ static struct i2c_board_info __initdata
 	},
 };
 
+static struct platform_device simone_audio_device = {
+	.name		= "simone-audio",
+	.id		= -1,
+};
+
+static void __init simone_register_audio(void)
+{
+	ep93xx_register_ac97();
+	platform_device_register(&simone_audio_device);
+}
+
 static void __init simone_init_machine(void)
 {
 	ep93xx_init_devices();
@@ -61,12 +72,12 @@ static void __init simone_init_machine(v
 	ep93xx_register_fb(&simone_fb_info);
 	ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
 			    ARRAY_SIZE(simone_i2c_board_info));
-	ep93xx_register_ac97();
+	simone_register_audio();
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	/* Maintainer: Ryan Mallon */
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/snappercl15.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/snappercl15.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/snappercl15.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/snappercl15.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/fb.h>
@@ -30,6 +29,7 @@
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -150,6 +150,17 @@ static struct ep93xxfb_mach_info __initd
 	.bpp			= 16,
 };
 
+static struct platform_device snappercl15_audio_device = {
+	.name		= "snappercl15-audio",
+	.id		= -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+	ep93xx_register_i2s();
+	platform_device_register(&snappercl15_audio_device);
+}
+
 static void __init snappercl15_init_machine(void)
 {
 	ep93xx_init_devices();
@@ -157,13 +168,13 @@ static void __init snappercl15_init_mach
 	ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
 			    ARRAY_SIZE(snappercl15_i2c_data));
 	ep93xx_register_fb(&snappercl15_fb_info);
-	ep93xx_register_i2s();
+	snappercl15_register_audio();
 	platform_device_register(&snappercl15_nand_device);
 }
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
 	/* Maintainer: Ryan Mallon */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer 		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/ts72xx.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/ts72xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/ts72xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/ts72xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,8 +116,9 @@ static struct mtd_partition ts72xx_nand_
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 	}, {
 		.name		= "Linux",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 0,			/* filled in later */
+		.offset		= MTDPART_OFS_RETAIN,
+		.size		= TS72XX_REDBOOT_PART_SIZE,
+				/* leave so much for last partition */
 	}, {
 		.name		= "RedBoot",
 		.offset		= MTDPART_OFS_APPEND,
@@ -126,28 +127,14 @@ static struct mtd_partition ts72xx_nand_
 	},
 };
 
-static void ts72xx_nand_set_parts(uint64_t size,
-				  struct platform_nand_chip *chip)
-{
-	/* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
-	if (size == SZ_32M || size == SZ_128M) {
-		/* Set the "Linux" partition size */
-		ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
-
-		chip->partitions = ts72xx_nand_parts;
-		chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
-	} else {
-		pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
-	}
-}
-
 static struct platform_nand_data ts72xx_nand_data = {
 	.chip = {
 		.nr_chips	= 1,
 		.chip_offset	= 0,
 		.chip_delay	= 15,
 		.part_probe_types = ts72xx_nand_part_probes,
-		.set_parts	= ts72xx_nand_set_parts,
+		.partitions	= ts72xx_nand_parts,
+		.nr_partitions	= ARRAY_SIZE(ts72xx_nand_parts),
 	},
 	.ctrl = {
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,
@@ -257,7 +244,7 @@ static void __init ts72xx_init_machine(v
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ts72xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/vision_ep9307.c linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/vision_ep9307.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ep93xx/vision_ep9307.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ep93xx/vision_ep9307.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,364 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE	EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE	0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+	{
+		.virtual	= VISION_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VISION_PHYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init vision_map_io(void)
+{
+	ep93xx_map_io();
+
+	iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+	.phy_id		= 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE	EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+	int err;
+
+	err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+				dev_name(&pdev->dev));
+	if (err)
+		return err;
+
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+				 EP93XX_SYSCON_DEVCFG_RASONP3 |
+				 EP93XX_SYSCON_DEVCFG_EXVC);
+
+	return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+	gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+	if (blank_mode)
+		gpio_set_value(VISION_LCD_ENABLE, 0);
+	else
+		gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+	.num_modes	= EP93XXFB_USE_MODEDB,
+	.bpp		= 16,
+	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+	.setup		= vision_lcd_setup,
+	.teardown	= vision_lcd_teardown,
+	.blank		= vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE	(EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE	(PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE	(PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE	(PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+	.gpio_base	= PCA9539_74_GPIO_BASE,
+	.irq_base	= EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+	.gpio_base	= PCA9539_75_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+	.gpio_base	= PCA9539_76_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+	.gpio_base	= PCA9539_77_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq		= IRQ_EP93XX_EXT1,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x74),
+		.platform_data	= &pca953x_74_gpio_data,
+		.irq		= gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x75),
+		.platform_data	= &pca953x_75_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x76),
+		.platform_data	= &pca953x_76_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x77),
+		.platform_data	= &pca953x_77_gpio_data,
+	},
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS	EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+	{
+		.name	= "SPI bootstrap",
+		.offset	= 0,
+		.size	= SZ_4K,
+	}, {
+		.name	= "Bootstrap config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= SZ_4K,
+	}, {
+		.name	= "System config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+	.name		= "SPI Flash",
+	.parts		= vision_spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+	.setup		= vision_spi_flash_hw_setup,
+	.cleanup	= vision_spi_flash_hw_cleanup,
+	.cs_control	= vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS	EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP	EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD	EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+	{ VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+	{ VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+			irqreturn_t (*func)(int, void *), void *pdata)
+{
+	int err;
+
+	err = gpio_request_array(vision_spi_mmc_gpios,
+				 ARRAY_SIZE(vision_spi_mmc_gpios));
+	if (err)
+		return err;
+
+	err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+	if (err)
+		goto exit_err;
+
+	err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+			IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+	if (err)
+		goto exit_err;
+
+	return 0;
+
+exit_err:
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+	return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+	free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+	return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+	return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+	.init		= vision_spi_mmc_init,
+	.exit		= vision_spi_mmc_exit,
+	.get_ro		= vision_spi_mmc_get_ro,
+	.get_cd		= vision_spi_mmc_get_cd,
+	.detect_delay	= 100,
+	.powerup_msecs	= 100,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+	.setup		= vision_spi_mmc_hw_setup,
+	.cleanup	= vision_spi_mmc_hw_cleanup,
+	.cs_control	= vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+	{
+		.modalias		= "sst25l",
+		.platform_data		= &vision_spi_flash_data,
+		.controller_data	= &vision_spi_flash_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	}, {
+		.modalias		= "mmc_spi",
+		.platform_data		= &vision_spi_mmc_data,
+		.controller_data	= &vision_spi_mmc_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 1,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+	.num_chipselect		= ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+	ep93xx_register_eth(&vision_eth_data, 1);
+	ep93xx_register_fb(&ep93xxfb_info);
+	ep93xx_register_pwm(1, 0);
+
+	/*
+	 * Request the gpio expander's interrupt gpio line now to prevent
+	 * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+	 */
+	if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+				"pca9539:74"))
+		pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+	ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+				ARRAY_SIZE(vision_i2c_info));
+	ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+				ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= vision_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= vision_init_machine,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1491 @@
+/* linux/arch/arm/mach-exynos4/clock.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Clock support
+ *
+ * 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/err.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4_clock_save[] = {
+	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKSRC_TOP0),
+	SAVE_ITEM(S5P_CLKSRC_TOP1),
+	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_TV),
+	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_G3D),
+	SAVE_ITEM(S5P_CLKSRC_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_CAM),
+	SAVE_ITEM(S5P_CLKDIV_TV),
+	SAVE_ITEM(S5P_CLKDIV_MFC),
+	SAVE_ITEM(S5P_CLKDIV_G3D),
+	SAVE_ITEM(S5P_CLKDIV_LCD0),
+	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+	SAVE_ITEM(S5P_CLKDIV_FSYS0),
+	SAVE_ITEM(S5P_CLKDIV_FSYS1),
+	SAVE_ITEM(S5P_CLKDIV_FSYS2),
+	SAVE_ITEM(S5P_CLKDIV_FSYS3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL0),
+	SAVE_ITEM(S5P_CLKDIV_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_PERIL2),
+	SAVE_ITEM(S5P_CLKDIV_PERIL3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL4),
+	SAVE_ITEM(S5P_CLKDIV_PERIL5),
+	SAVE_ITEM(S5P_CLKDIV_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV2_RATIO),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_TV),
+	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+	SAVE_ITEM(S5P_CLKGATE_BLOCK),
+	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+	SAVE_ITEM(S5P_CLKSRC_DMC),
+	SAVE_ITEM(S5P_CLKDIV_DMC0),
+	SAVE_ITEM(S5P_CLKDIV_DMC1),
+	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+	SAVE_ITEM(S5P_CLKSRC_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+};
+
+struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.rate		= 27000000,
+};
+
+struct clk clk_sclk_hdmiphy = {
+	.name		= "sclk_hdmiphy",
+};
+
+struct clk clk_sclk_usbphy0 = {
+	.name		= "sclk_usbphy0",
+	.rate		= 27000000,
+};
+
+struct clk clk_sclk_usbphy1 = {
+	.name		= "sclk_usbphy1",
+};
+
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
+static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
+}
+
+static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
+}
+
+int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
+}
+
+static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
+}
+
+static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
+}
+
+int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
+}
+
+int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
+}
+
+static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
+static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
+}
+
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_sclk_apll = {
+	.clk	= {
+		.name		= "sclk_apll",
+		.parent		= &clk_mout_apll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+	},
+	.sources	= &clk_src_mpll,
+
+	/* reg_src will be added in each SoCs' clock */
+};
+
+static struct clk *clkset_moutcore_list[] = {
+	[0] = &clk_mout_apll.clk,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_moutcore = {
+	.sources	= clkset_moutcore_list,
+	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
+};
+
+static struct clksrc_clk clk_moutcore = {
+	.clk	= {
+		.name		= "moutcore",
+	},
+	.sources	= &clkset_moutcore,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+	.clk	= {
+		.name		= "core_clk",
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.parent		= &clk_coreclk.clk,
+	},
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+	.clk	= {
+		.name		= "aclk_corem0",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cores = {
+	.clk	= {
+		.name		= "aclk_cores",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corem1 = {
+	.clk	= {
+		.name		= "aclk_corem1",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+	.clk	= {
+		.name		= "periphclk",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+struct clk *clkset_corebus_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+struct clksrc_sources clkset_mout_corebus = {
+	.sources	= clkset_corebus_list,
+	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
+};
+
+static struct clksrc_clk clk_mout_corebus = {
+	.clk	= {
+		.name		= "mout_corebus",
+	},
+	.sources	= &clkset_mout_corebus,
+	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_dmc = {
+	.clk	= {
+		.name		= "sclk_dmc",
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cored = {
+	.clk	= {
+		.name		= "aclk_cored",
+		.parent		= &clk_sclk_dmc.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corep = {
+	.clk	= {
+		.name		= "aclk_corep",
+		.parent		= &clk_aclk_cored.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_acp = {
+	.clk	= {
+		.name		= "aclk_acp",
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_acp = {
+	.clk	= {
+		.name		= "pclk_acp",
+		.parent		= &clk_aclk_acp.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+struct clk *clkset_aclk_top_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+struct clksrc_sources clkset_aclk = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_200 = {
+	.clk	= {
+		.name		= "aclk_200",
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_100 = {
+	.clk	= {
+		.name		= "aclk_100",
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_aclk_160 = {
+	.clk	= {
+		.name		= "aclk_160",
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+struct clksrc_clk clk_aclk_133 = {
+	.clk	= {
+		.name		= "aclk_133",
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+	[0] = &clk_fin_vpll,
+	[1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+	.sources	= clkset_vpllsrc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+	.clk	= {
+		.name		= "vpll_src",
+		.enable		= exynos4_clksrc_mask_top_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources	= &clkset_vpllsrc,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+	[0] = &clk_vpllsrc.clk,
+	[1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+	.sources	= clkset_sclk_vpll_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "timers",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "csis",
+		.devname	= "s5p-mipi-csis.0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "csis",
+		.devname	= "s5p-mipi-csis.1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.2",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.3",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "fimd",
+		.devname	= "exynos4-fb.0",
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.0",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.1",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.2",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.3",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "dwmmc",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "dac",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "mixer",
+		.devname	= "s5p-mixer",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "vp",
+		.devname	= "s5p-mixer",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "hdmi",
+		.devname	= "exynos4-hdmi",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "hdmiphy",
+		.devname	= "exynos4-hdmi",
+		.enable		= exynos4_clk_hdmiphy_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dacphy",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_dac_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "adc",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "keypad",
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "rtc",
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "watchdog",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "usbhost",
+		.enable		= exynos4_clk_ip_fsys_ctrl ,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "otg",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "ac97",
+		.devname	= "samsung-ac97",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "fimg2d",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "mfc",
+		.devname	= "s5p-mfc",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.0",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.1",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.2",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.3",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.4",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.5",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.6",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.7",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-hdmiphy-i2c",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "SYSMMU_MDMA",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "SYSMMU_FIMC0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "SYSMMU_FIMC1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "SYSMMU_FIMC2",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "SYSMMU_FIMC3",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "SYSMMU_JPEG",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "SYSMMU_FIMD0",
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_FIMD1",
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_PCIe",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "SYSMMU_G2D",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "SYSMMU_ROTATOR",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_TV",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_MFC_L",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "SYSMMU_MFC_R",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 2),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "uart",
+		.devname	= "s5pv210-uart.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.3",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.4",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.5",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 5),
+	}
+};
+
+struct clk *clkset_group_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_xusbxti,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+struct clksrc_sources clkset_group = {
+	.sources	= clkset_group_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group_list),
+};
+
+static struct clk *clkset_mout_g2d0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d0 = {
+	.sources	= clkset_mout_g2d0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
+};
+
+static struct clksrc_clk clk_mout_g2d0 = {
+	.clk	= {
+		.name		= "mout_g2d0",
+	},
+	.sources	= &clkset_mout_g2d0,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d1 = {
+	.sources	= clkset_mout_g2d1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
+};
+
+static struct clksrc_clk clk_mout_g2d1 = {
+	.clk	= {
+		.name		= "mout_g2d1",
+	},
+	.sources	= &clkset_mout_g2d1,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d_list[] = {
+	[0] = &clk_mout_g2d0.clk,
+	[1] = &clk_mout_g2d1.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d = {
+	.sources	= clkset_mout_g2d_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
+};
+
+static struct clk *clkset_mout_mfc0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+	.sources	= clkset_mout_mfc0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+	.clk	= {
+		.name		= "mout_mfc0",
+	},
+	.sources	= &clkset_mout_mfc0,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+	.sources	= clkset_mout_mfc1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+	.clk	= {
+		.name		= "mout_mfc1",
+	},
+	.sources	= &clkset_mout_mfc1,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+	[0] = &clk_mout_mfc0.clk,
+	[1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+	.sources	= clkset_mout_mfc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
+static struct clk *clkset_sclk_dac_list[] = {
+	[0] = &clk_sclk_vpll.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+	.sources	= clkset_sclk_dac_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+	.clk		= {
+		.name		= "sclk_dac",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 8),
+	},
+	.sources = &clkset_sclk_dac,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+	.clk		= {
+		.name		= "sclk_pixel",
+		.parent = &clk_sclk_vpll.clk,
+	},
+	.reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+	[0] = &clk_sclk_pixel.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+	.sources	= clkset_sclk_hdmi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+	.clk		= {
+		.name		= "sclk_hdmi",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &clkset_sclk_hdmi,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+	[0] = &clk_sclk_dac.clk,
+	[1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+	.sources	= clkset_sclk_mixer_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+};
+
+static struct clksrc_clk clk_dout_mmc0 = {
+	.clk		= {
+		.name		= "dout_mmc0",
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc1 = {
+	.clk		= {
+		.name		= "dout_mmc1",
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc2 = {
+	.clk		= {
+		.name		= "dout_mmc2",
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc3 = {
+	.clk		= {
+		.name		= "dout_mmc3",
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc4 = {
+	.clk		= {
+		.name		= "dout_mmc4",
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "uclk1",
+			.devname	= "s5pv210-uart.0",
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.devname	= "s5pv210-uart.1",
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.devname	= "s5pv210-uart.2",
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.devname	= "s5pv210-uart.3",
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwm",
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.devname	= "s5p-mipi-csis.0",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.devname	= "s5p-mipi-csis.1",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 28),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam0",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam1",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.devname	= "exynos4-fimc.0",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.devname	= "exynos4-fimc.1",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.devname	= "exynos4-fimc.2",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.devname	= "exynos4-fimc.3",
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.devname	= "exynos4-fb.0",
+			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.devname	= "s3c64xx-spi.0",
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.devname	= "s3c64xx-spi.1",
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.devname	= "s3c64xx-spi.2",
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimg2d",
+		},
+		.sources = &clkset_mout_g2d,
+		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mfc",
+			.devname	= "s5p-mfc",
+		},
+		.sources = &clkset_mout_mfc,
+		.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.devname	= "s3c-sdhci.0",
+			.parent		= &clk_dout_mmc0.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.devname	= "s3c-sdhci.1",
+			.parent         = &clk_dout_mmc1.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.devname	= "s3c-sdhci.2",
+			.parent         = &clk_dout_mmc2.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.devname	= "s3c-sdhci.3",
+			.parent         = &clk_dout_mmc3.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_dwmmc",
+			.parent         = &clk_dout_mmc4.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
+	}
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_sclk_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+	&clk_moutcore,
+	&clk_coreclk,
+	&clk_armclk,
+	&clk_aclk_corem0,
+	&clk_aclk_cores,
+	&clk_aclk_corem1,
+	&clk_periphclk,
+	&clk_mout_corebus,
+	&clk_sclk_dmc,
+	&clk_aclk_cored,
+	&clk_aclk_corep,
+	&clk_aclk_acp,
+	&clk_pclk_acp,
+	&clk_vpllsrc,
+	&clk_sclk_vpll,
+	&clk_aclk_200,
+	&clk_aclk_100,
+	&clk_aclk_160,
+	&clk_aclk_133,
+	&clk_dout_mmc0,
+	&clk_dout_mmc1,
+	&clk_dout_mmc2,
+	&clk_dout_mmc3,
+	&clk_dout_mmc4,
+	&clk_mout_mfc0,
+	&clk_mout_mfc1,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
+{
+	if (soc_is_exynos4210())
+		return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
+					pll_4508);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
+	else
+		return 0;
+}
+
+static struct clk_ops exynos4_fout_apll_ops = {
+	.get_rate = exynos4_fout_apll_get_rate,
+};
+
+static u32 vpll_div[][8] = {
+	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static unsigned long exynos4_vpll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int vpll_con0, vpll_con1 = 0;
+	unsigned int i;
+
+	/* Return if nothing changed */
+	if (clk->rate == rate)
+		return 0;
+
+	vpll_con0 = __raw_readl(S5P_VPLL_CON0);
+	vpll_con0 &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+	vpll_con1 = __raw_readl(S5P_VPLL_CON1);
+	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
+			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
+			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+		if (vpll_div[i][0] == rate) {
+			vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+			vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+			vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+			vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+			vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+			vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+			vpll_con0 |= vpll_div[i][7] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(vpll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con0, S5P_VPLL_CON0);
+	__raw_writel(vpll_con1, S5P_VPLL_CON1);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+		continue;
+
+	clk->rate = rate;
+	return 0;
+}
+
+static struct clk_ops exynos4_vpll_ops = {
+	.get_rate = exynos4_vpll_get_rate,
+	.set_rate = exynos4_vpll_set_rate,
+};
+
+void __init_or_cpufreq exynos4_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long apll = 0;
+	unsigned long mpll = 0;
+	unsigned long epll = 0;
+	unsigned long vpll = 0;
+	unsigned long vpllsrc;
+	unsigned long xtal;
+	unsigned long armclk;
+	unsigned long sclk_dmc;
+	unsigned long aclk_200;
+	unsigned long aclk_100;
+	unsigned long aclk_160;
+	unsigned long aclk_133;
+	unsigned int ptr;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	xtal_clk = clk_get(NULL, "xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+
+	xtal_rate = xtal;
+
+	clk_put(xtal_clk);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	if (soc_is_exynos4210()) {
+		apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0),
+					pll_4508);
+		mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0),
+					pll_4508);
+		epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+					__raw_readl(S5P_EPLL_CON1), pll_4600);
+
+		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+					__raw_readl(S5P_VPLL_CON1), pll_4650c);
+	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+		apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
+		mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
+		epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
+					__raw_readl(S5P_EPLL_CON1));
+
+		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+					__raw_readl(S5P_VPLL_CON1));
+	} else {
+		/* nothing */
+	}
+
+	clk_fout_apll.ops = &exynos4_fout_apll_ops;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_vpll.ops = &exynos4_vpll_ops;
+	clk_fout_vpll.rate = vpll;
+
+	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
+			apll, mpll, epll, vpll);
+
+	armclk = clk_get_rate(&clk_armclk.clk);
+	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
+
+	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
+	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
+	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
+	aclk_133 = clk_get_rate(&clk_aclk_133.clk);
+
+	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
+			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
+			armclk, sclk_dmc, aclk_200,
+			aclk_100, aclk_160, aclk_133);
+
+	clk_f.rate = armclk;
+	clk_h.rate = sclk_dmc;
+	clk_p.rate = aclk_100;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	&clk_sclk_hdmi27m,
+	&clk_sclk_hdmiphy,
+	&clk_sclk_usbphy0,
+	&clk_sclk_usbphy1,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+	return 0;
+}
+
+static void exynos4_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+}
+
+#else
+#define exynos4_clock_suspend NULL
+#define exynos4_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4_clock_syscore_ops = {
+	.suspend	= exynos4_clock_suspend,
+	.resume		= exynos4_clock_resume,
+};
+
+void __init exynos4_register_clocks(void)
+{
+	int ptr;
+
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+		s3c_register_clksrc(sclk_tv[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4_clock_syscore_ops);
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
+	s3c_pwmclk_init();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock-exynos4210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock-exynos4210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock-exynos4210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock-exynos4210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - Clock support
+ *
+ * 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/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4210_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKSRC_LCD1),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4210),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
+};
+
+static struct clksrc_clk *sysclks[] = {
+	/* nothing here yet */
+};
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk		= {
+			.name		= "sclk_sata",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_mout_corebus,
+		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.devname	= "exynos4-fb.1",
+			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
+	},
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "sataphy",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "sata",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "fimd",
+		.devname	= "exynos4-fb.1",
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4210_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+
+	return 0;
+}
+
+static void exynos4210_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+}
+
+#else
+#define exynos4210_clock_suspend NULL
+#define exynos4210_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4210_clock_syscore_ops = {
+	.suspend	= exynos4210_clock_suspend,
+	.resume		= exynos4210_clock_resume,
+};
+
+void __init exynos4210_register_clocks(void)
+{
+	int ptr;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_CPU;
+	clk_mout_mpll.reg_src.shift = 8;
+	clk_mout_mpll.reg_src.size = 1;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4210_clock_syscore_ops);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock-exynos4212.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock-exynos4212.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/clock-exynos4212.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/clock-exynos4212.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4212.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4212 - Clock support
+ *
+ * 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/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4212_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
+};
+
+static struct clk *clk_src_mpll_user_list[] = {
+	[0] = &clk_fin_mpll,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clk_src_mpll_user = {
+	.sources	= clk_src_mpll_user_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
+};
+
+static struct clksrc_clk clk_mout_mpll_user = {
+	.clk = {
+		.name		= "mout_mpll_user",
+	},
+	.sources	= &clk_src_mpll_user,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 24, .size = 1 },
+};
+
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_mpll_user,
+};
+
+static struct clksrc_clk clksrcs[] = {
+	/* nothing here yet */
+};
+
+static struct clk init_clocks_off[] = {
+	/* nothing here yet */
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4212_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+
+	return 0;
+}
+
+static void exynos4212_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+}
+
+#else
+#define exynos4212_clock_suspend NULL
+#define exynos4212_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4212_clock_syscore_ops = {
+	.suspend	= exynos4212_clock_suspend,
+	.resume		= exynos4212_clock_resume,
+};
+
+void __init exynos4212_register_clocks(void)
+{
+	int ptr;
+
+	/* usbphy1 is removed */
+	clkset_group_list[4] = NULL;
+
+	/* mout_mpll_user is used */
+	clkset_group_list[6] = &clk_mout_mpll_user.clk;
+	clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_DMC;
+	clk_mout_mpll.reg_src.shift = 12;
+	clk_mout_mpll.reg_src.size = 1;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4212_clock_syscore_ops);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,293 @@
+/* linux/arch/arm/mach-exynos/cpu.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/sysdev.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/adc-core.h>
+#include <plat/sdhci.h>
+#include <plat/fb-core.h>
+#include <plat/fimc-core.h>
+#include <plat/iic-core.h>
+#include <plat/reset.h>
+#include <plat/tv-core.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-pmu.h>
+
+unsigned int gic_bank_offset __read_mostly;
+
+extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
+			 unsigned int irq_start);
+extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+
+/* Initial IO mappings */
+static struct map_desc exynos_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_SYSTIMER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_PMU,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_PMU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_COMBINER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_GIC_CPU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_GIC_DIST),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_CMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
+		.length		= SZ_128K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_L2CC,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_L2CC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO1,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO2,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO2),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO3,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO3),
+		.length		= SZ_256,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC0,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_HSPHY),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc0[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc1[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void exynos_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+static void exynos4_sw_reset(void)
+{
+	__raw_writel(0x1, S5P_SWRESET);
+}
+
+/*
+ * exynos_map_io
+ *
+ * register the standard cpu IO areas
+ */
+void __init exynos4_map_io(void)
+{
+	iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
+	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+
+	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+		iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
+	else
+		iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
+
+	/* initialize device information early */
+	exynos4_default_sdhci0();
+	exynos4_default_sdhci1();
+	exynos4_default_sdhci2();
+	exynos4_default_sdhci3();
+
+	s3c_adc_setname("samsung-adc-v3");
+
+	s3c_fimc_setname(0, "exynos4-fimc");
+	s3c_fimc_setname(1, "exynos4-fimc");
+	s3c_fimc_setname(2, "exynos4-fimc");
+	s3c_fimc_setname(3, "exynos4-fimc");
+
+	/* The I2C bus controllers are directly compatible with s3c2440 */
+	s3c_i2c0_setname("s3c2440-i2c");
+	s3c_i2c1_setname("s3c2440-i2c");
+	s3c_i2c2_setname("s3c2440-i2c");
+
+	s5p_fb_setname(0, "exynos4-fb");
+	s5p_hdmi_setname("exynos4-hdmi");
+}
+
+void __init exynos4_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+
+	if (soc_is_exynos4210())
+		exynos4210_register_clocks();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4212_register_clocks();
+
+	exynos4_register_clocks();
+	exynos4_setup_clocks();
+}
+
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (gic_bank_offset * smp_processor_id());
+
+	gic_data->dist_base = S5P_VA_GIC_DIST +
+			    (gic_bank_offset * smp_processor_id());
+}
+
+void __init exynos4_init_irq(void)
+{
+	int irq;
+
+	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
+
+	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+				COMBINER_IRQ(irq, 0));
+		combiner_cascade_irq(irq, IRQ_SPI(irq));
+	}
+
+	/* The parameters of s5p_init_irq() are for VIC init.
+	 * Theses parameters should be NULL and 0 because EXYNOS4
+	 * uses GIC instead of VIC.
+	 */
+	s5p_init_irq(NULL, 0);
+}
+
+struct sysdev_class exynos4_sysclass = {
+	.name	= "exynos4-core",
+};
+
+static struct sys_device exynos4_sysdev = {
+	.cls	= &exynos4_sysclass,
+};
+
+static int __init exynos4_core_init(void)
+{
+	return sysdev_class_register(&exynos4_sysclass);
+}
+core_initcall(exynos4_core_init);
+
+#ifdef CONFIG_CACHE_L2X0
+static int __init exynos4_l2x0_cache_init(void)
+{
+	/* TAG, Data Latency Control: 2cycle */
+	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+
+	if (soc_is_exynos4210())
+		__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		__raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+	/* L2X0 Prefetch Control */
+	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+
+	/* L2X0 Power Control */
+	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
+		     S5P_VA_L2CC + L2X0_POWER_CTRL);
+
+	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
+
+	return 0;
+}
+
+early_initcall(exynos4_l2x0_cache_init);
+#endif
+
+int __init exynos_init(void)
+{
+	printk(KERN_INFO "EXYNOS: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = exynos_idle;
+
+	/* set sw_reset function */
+	if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
+		s5p_reset_hook = exynos4_sw_reset;
+
+	return sysdev_register(&exynos4_sysdev);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/cpuidle.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-exynos4/cpuidle.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
+
+#include <asm/proc-fns.h>
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv,
+			      int index);
+
+static struct cpuidle_state exynos4_cpuidle_set[] = {
+	[0] = {
+		.enter			= exynos4_enter_idle,
+		.exit_latency		= 1,
+		.target_residency	= 100000,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "IDLE",
+		.desc			= "ARM clock gating(WFI)",
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
+
+static struct cpuidle_driver exynos4_idle_driver = {
+	.name		= "exynos4_idle",
+	.owner		= THIS_MODULE,
+};
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv,
+			      int index)
+{
+	struct timeval before, after;
+	int idle_time;
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+
+	cpu_do_idle();
+
+	do_gettimeofday(&after);
+	local_irq_enable();
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+		    (after.tv_usec - before.tv_usec);
+
+	dev->last_residency = idle_time;
+	return index;
+}
+
+static int __init exynos4_init_cpuidle(void)
+{
+	int i, max_cpuidle_state, cpu_id;
+	struct cpuidle_device *device;
+	struct cpuidle_driver *drv = &exynos4_idle_driver;
+
+	/* Setup cpuidle driver */
+	drv->state_count = (sizeof(exynos4_cpuidle_set) /
+				       sizeof(struct cpuidle_state));
+	max_cpuidle_state = drv->state_count;
+	for (i = 0; i < max_cpuidle_state; i++) {
+		memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
+				sizeof(struct cpuidle_state));
+	}
+	cpuidle_register_driver(&exynos4_idle_driver);
+
+	for_each_cpu(cpu_id, cpu_online_mask) {
+		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
+		device->cpu = cpu_id;
+
+		device->state_count = drv->state_count;
+
+		if (cpuidle_register_device(device)) {
+			printk(KERN_ERR "CPUidle register device failed\n,");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+device_initcall(exynos4_init_cpuidle);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-ahci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-ahci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-ahci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-ahci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,263 @@
+/* linux/arch/arm/mach-exynos4/dev-ahci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - AHCI support
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/ahci_platform.h>
+
+#include <plat/cpu.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/regs-pmu.h>
+
+/* PHY Control Register */
+#define SATA_CTRL0		0x0
+/* PHY Link Control Register */
+#define SATA_CTRL1		0x4
+/* PHY Status Register */
+#define SATA_PHY_STATUS		0x8
+
+#define SATA_CTRL0_RX_DATA_VALID(x)	(x << 27)
+#define SATA_CTRL0_SPEED_MODE		(1 << 26)
+#define SATA_CTRL0_M_PHY_CAL		(1 << 19)
+#define SATA_CTRL0_PHY_CMU_RST_N	(1 << 10)
+#define SATA_CTRL0_M_PHY_LN_RST_N	(1 << 9)
+#define SATA_CTRL0_PHY_POR_N		(1 << 8)
+
+#define SATA_CTRL1_RST_PMALIVE_N	(1 << 8)
+#define SATA_CTRL1_RST_RXOOB_N		(1 << 7)
+#define SATA_CTRL1_RST_RX_N		(1 << 6)
+#define SATA_CTRL1_RST_TX_N		(1 << 5)
+
+#define SATA_PHY_STATUS_CMU_OK		(1 << 18)
+#define SATA_PHY_STATUS_LANE_OK		(1 << 16)
+
+#define LANE0		0x200
+#define COM_LANE	0xA00
+
+#define HOST_PORTS_IMPL	0xC
+#define SCLK_SATA_FREQ	(67 * MHZ)
+
+static void __iomem *phy_base, *phy_ctrl;
+
+struct phy_reg {
+	u8	reg;
+	u8	val;
+};
+
+/* SATA PHY setup */
+static const struct phy_reg exynos4_sataphy_cmu[] = {
+	{ 0x00, 0x06 }, { 0x02, 0x80 }, { 0x22, 0xa0 }, { 0x23, 0x42 },
+	{ 0x2e, 0x04 }, { 0x2f, 0x50 }, { 0x30, 0x70 }, { 0x31, 0x02 },
+	{ 0x32, 0x25 }, { 0x33, 0x40 }, { 0x34, 0x01 }, { 0x35, 0x40 },
+	{ 0x61, 0x2e }, { 0x63, 0x5e }, { 0x65, 0x42 }, { 0x66, 0xd1 },
+	{ 0x67, 0x20 }, { 0x68, 0x28 }, { 0x69, 0x78 }, { 0x6a, 0x04 },
+	{ 0x6b, 0xc8 }, { 0x6c, 0x06 },
+};
+
+static const struct phy_reg exynos4_sataphy_lane[] = {
+	{ 0x00, 0x02 }, { 0x05, 0x10 }, { 0x06, 0x84 }, { 0x07, 0x04 },
+	{ 0x08, 0xe0 }, { 0x10, 0x23 }, { 0x13, 0x05 }, { 0x14, 0x30 },
+	{ 0x15, 0x00 }, { 0x17, 0x70 }, { 0x18, 0xf2 }, { 0x19, 0x1e },
+	{ 0x1a, 0x18 }, { 0x1b, 0x0d }, { 0x1c, 0x08 }, { 0x50, 0x60 },
+	{ 0x51, 0x0f },
+};
+
+static const struct phy_reg exynos4_sataphy_comlane[] = {
+	{ 0x01, 0x20 }, { 0x03, 0x40 }, { 0x04, 0x3c }, { 0x05, 0x7d },
+	{ 0x06, 0x1d }, { 0x07, 0xcf }, { 0x08, 0x05 }, { 0x09, 0x63 },
+	{ 0x0a, 0x29 }, { 0x0b, 0xc4 }, { 0x0c, 0x01 }, { 0x0d, 0x03 },
+	{ 0x0e, 0x28 }, { 0x0f, 0x98 }, { 0x10, 0x19 }, { 0x13, 0x80 },
+	{ 0x14, 0xf0 }, { 0x15, 0xd0 }, { 0x39, 0xa0 }, { 0x3a, 0xa0 },
+	{ 0x3b, 0xa0 }, { 0x3c, 0xa0 }, { 0x3d, 0xa0 }, { 0x3e, 0xa0 },
+	{ 0x3f, 0xa0 }, { 0x40, 0x42 }, { 0x42, 0x80 }, { 0x43, 0x58 },
+	{ 0x45, 0x44 }, { 0x46, 0x5c }, { 0x47, 0x86 }, { 0x48, 0x8d },
+	{ 0x49, 0xd0 }, { 0x4a, 0x09 }, { 0x4b, 0x90 }, { 0x4c, 0x07 },
+	{ 0x4d, 0x40 }, { 0x51, 0x20 }, { 0x52, 0x32 }, { 0x7f, 0xd8 },
+	{ 0x80, 0x1a }, { 0x81, 0xff }, { 0x82, 0x11 }, { 0x83, 0x00 },
+	{ 0x87, 0xf0 }, { 0x87, 0xff }, { 0x87, 0xff }, { 0x87, 0xff },
+	{ 0x87, 0xff }, { 0x8c, 0x1c }, { 0x8d, 0xc2 }, { 0x8e, 0xc3 },
+	{ 0x8f, 0x3f }, { 0x90, 0x0a }, { 0x96, 0xf8 },
+};
+
+static int wait_for_phy_ready(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	/* wait for maximum of 3 sec */
+	timeout = jiffies + msecs_to_jiffies(3000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static int ahci_phy_init(void __iomem *mmio)
+{
+	int i, ctrl0;
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_cmu); i++)
+		__raw_writeb(exynos4_sataphy_cmu[i].val,
+		phy_base + (exynos4_sataphy_cmu[i].reg * 4));
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_lane); i++)
+		__raw_writeb(exynos4_sataphy_lane[i].val,
+		phy_base + (LANE0 + exynos4_sataphy_lane[i].reg) * 4);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_comlane); i++)
+		__raw_writeb(exynos4_sataphy_comlane[i].val,
+		phy_base + (COM_LANE + exynos4_sataphy_comlane[i].reg) * 4);
+
+	__raw_writeb(0x07, phy_base);
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_PHY_CMU_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_CMU_OK) < 0) {
+		printk(KERN_ERR "PHY CMU not ready\n");
+		return -EBUSY;
+	}
+
+	__raw_writeb(0x03, phy_base + (COM_LANE * 4));
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_LN_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_LANE_OK) < 0) {
+		printk(KERN_ERR "PHY LANE not ready\n");
+		return -EBUSY;
+	}
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_CAL;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	return 0;
+}
+
+static int exynos4_ahci_init(struct device *dev, void __iomem *mmio)
+{
+	struct clk *clk_sata, *clk_sataphy, *clk_sclk_sata;
+	int val, ret;
+
+	phy_base = ioremap(EXYNOS4_PA_SATAPHY, SZ_64K);
+	if (!phy_base) {
+		dev_err(dev, "failed to allocate memory for SATA PHY\n");
+		return -ENOMEM;
+	}
+
+	phy_ctrl = ioremap(EXYNOS4_PA_SATAPHY_CTRL, SZ_16);
+	if (!phy_ctrl) {
+		dev_err(dev, "failed to allocate memory for SATA PHY CTRL\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	clk_sata = clk_get(dev, "sata");
+	if (IS_ERR(clk_sata)) {
+		dev_err(dev, "failed to get sata clock\n");
+		ret = PTR_ERR(clk_sata);
+		clk_sata = NULL;
+		goto err2;
+
+	}
+	clk_enable(clk_sata);
+
+	clk_sataphy = clk_get(dev, "sataphy");
+	if (IS_ERR(clk_sataphy)) {
+		dev_err(dev, "failed to get sataphy clock\n");
+		ret = PTR_ERR(clk_sataphy);
+		clk_sataphy = NULL;
+		goto err3;
+	}
+	clk_enable(clk_sataphy);
+
+	clk_sclk_sata = clk_get(dev, "sclk_sata");
+	if (IS_ERR(clk_sclk_sata)) {
+		dev_err(dev, "failed to get sclk_sata\n");
+		ret = PTR_ERR(clk_sclk_sata);
+		clk_sclk_sata = NULL;
+		goto err4;
+	}
+	clk_enable(clk_sclk_sata);
+	clk_set_rate(clk_sclk_sata, SCLK_SATA_FREQ);
+
+	__raw_writel(S5P_PMU_SATA_PHY_CONTROL_EN, S5P_PMU_SATA_PHY_CONTROL);
+
+	/* Enable PHY link control */
+	val = SATA_CTRL1_RST_PMALIVE_N | SATA_CTRL1_RST_RXOOB_N |
+			SATA_CTRL1_RST_RX_N | SATA_CTRL1_RST_TX_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL1);
+
+	/* Set communication speed as 3Gbps and enable PHY power */
+	val = SATA_CTRL0_RX_DATA_VALID(3) | SATA_CTRL0_SPEED_MODE |
+			SATA_CTRL0_PHY_POR_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL0);
+
+	/* Port0 is available */
+	__raw_writel(0x1, mmio + HOST_PORTS_IMPL);
+
+	return ahci_phy_init(mmio);
+
+err4:
+	clk_disable(clk_sataphy);
+	clk_put(clk_sataphy);
+err3:
+	clk_disable(clk_sata);
+	clk_put(clk_sata);
+err2:
+	iounmap(phy_ctrl);
+err1:
+	iounmap(phy_base);
+
+	return ret;
+}
+
+static struct ahci_platform_data exynos4_ahci_pdata = {
+	.init = exynos4_ahci_init,
+};
+
+static struct resource exynos4_ahci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SATA,
+		.end	= EXYNOS4_PA_SATA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SATA,
+		.end	= IRQ_SATA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ahci = {
+	.name		= "ahci",
+	.id		= -1,
+	.resource	= exynos4_ahci_resource,
+	.num_resources	= ARRAY_SIZE(exynos4_ahci_resource),
+	.dev		= {
+		.platform_data		= &exynos4_ahci_pdata,
+		.dma_mask		= &exynos4_ahci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-audio.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-audio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,369 @@
+/* linux/arch/arm/mach-exynos4/dev-audio.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *	Jaswinder Singh <jassi.brar@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/regs-audss.h>
+
+static const char *rclksrc[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
+static int exynos4_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 7, S3C_GPIO_SFN(2));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(2));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(4));
+		break;
+	default:
+		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata i2sv5_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc,
+			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
+		},
+	},
+};
+
+static struct resource exynos4_i2s0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S0,
+		.end	= EXYNOS4_PA_I2S0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S0_TX,
+		.end	= DMACH_I2S0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S0_RX,
+		.end	= DMACH_I2S0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_I2S0S_TX,
+		.end	= DMACH_I2S0S_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s0 = {
+	.name = "samsung-i2s",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_i2s0_resource),
+	.resource = exynos4_i2s0_resource,
+	.dev = {
+		.platform_data = &i2sv5_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "sclk_i2s",
+	[1] = "no_such_clock",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_NO_MUXPSR,
+			.src_clk = rclksrc_v3,
+		},
+	},
+};
+
+static struct resource exynos4_i2s1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S1,
+		.end	= EXYNOS4_PA_I2S1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S1_TX,
+		.end	= DMACH_I2S1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S1_RX,
+		.end	= DMACH_I2S1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s1 = {
+	.name = "samsung-i2s",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_i2s1_resource),
+	.resource = exynos4_i2s1_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+static struct resource exynos4_i2s2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S2,
+		.end	= EXYNOS4_PA_I2S2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S2_TX,
+		.end	= DMACH_I2S2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S2_RX,
+		.end	= DMACH_I2S2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s2 = {
+	.name = "samsung-i2s",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_i2s2_resource),
+	.resource = exynos4_i2s2_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+/* PCM Controller platform_devices */
+
+static int exynos4_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(3));
+		break;
+	default:
+		printk(KERN_DEBUG "Invalid PCM Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata s3c_pcm_pdata = {
+	.cfg_gpio = exynos4_pcm_cfg_gpio,
+};
+
+static struct resource exynos4_pcm0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM0,
+		.end	= EXYNOS4_PA_PCM0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM0_TX,
+		.end	= DMACH_PCM0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM0_RX,
+		.end	= DMACH_PCM0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm0 = {
+	.name = "samsung-pcm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_pcm0_resource),
+	.resource = exynos4_pcm0_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM1,
+		.end	= EXYNOS4_PA_PCM1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM1_TX,
+		.end	= DMACH_PCM1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM1_RX,
+		.end	= DMACH_PCM1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm1 = {
+	.name = "samsung-pcm",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_pcm1_resource),
+	.resource = exynos4_pcm1_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM2,
+		.end	= EXYNOS4_PA_PCM2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM2_TX,
+		.end	= DMACH_PCM2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM2_RX,
+		.end	= DMACH_PCM2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm2 = {
+	.name = "samsung-pcm",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_pcm2_resource),
+	.resource = exynos4_pcm2_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+/* AC97 Controller platform devices */
+
+static int exynos4_ac97_cfg_gpio(struct platform_device *pdev)
+{
+	return s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(4));
+}
+
+static struct resource exynos4_ac97_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_AC97,
+		.end	= EXYNOS4_PA_AC97 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_AC97_PCMOUT,
+		.end	= DMACH_AC97_PCMOUT,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_AC97_PCMIN,
+		.end	= DMACH_AC97_PCMIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_AC97_MICIN,
+		.end	= DMACH_AC97_MICIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[4] = {
+		.start	= IRQ_AC97,
+		.end	= IRQ_AC97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_audio_pdata s3c_ac97_pdata = {
+	.cfg_gpio = exynos4_ac97_cfg_gpio,
+};
+
+static u64 exynos4_ac97_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ac97 = {
+	.name = "samsung-ac97",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_ac97_resource),
+	.resource = exynos4_ac97_resource,
+	.dev = {
+		.platform_data = &s3c_ac97_pdata,
+		.dma_mask = &exynos4_ac97_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+/* S/PDIF Controller platform_device */
+
+static int exynos4_spdif_cfg_gpio(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(4));
+
+	return 0;
+}
+
+static struct resource exynos4_spdif_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SPDIF,
+		.end	= EXYNOS4_PA_SPDIF + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_SPDIF,
+		.end	= DMACH_SPDIF,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata samsung_spdif_pdata = {
+	.cfg_gpio = exynos4_spdif_cfg_gpio,
+};
+
+static u64 exynos4_spdif_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_spdif = {
+	.name = "samsung-spdif",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_spdif_resource),
+	.resource = exynos4_spdif_resource,
+	.dev = {
+		.platform_data = &samsung_spdif_pdata,
+		.dma_mask = &exynos4_spdif_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-dwmci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-dwmci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-dwmci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-dwmci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/arm/mach-exynos4/dev-dwmci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Platform device for Synopsys DesignWare Mobile Storage IP
+ *
+ * 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/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/dw_mmc.h>
+
+#include <plat/devs.h>
+
+#include <mach/map.h>
+
+static int exynos4_dwmci_get_bus_wd(u32 slot_id)
+{
+	return 4;
+}
+
+static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
+{
+	return 0;
+}
+
+static struct resource exynos4_dwmci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_DWMCI,
+		.end	= EXYNOS4_PA_DWMCI + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DWMCI,
+		.end	= IRQ_DWMCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct dw_mci_board exynos4_dwci_pdata = {
+	.num_slots			= 1,
+	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+	.bus_hz				= 80 * 1000 * 1000,
+	.detect_delay_ms	= 200,
+	.init				= exynos4_dwmci_init,
+	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
+};
+
+static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_dwmci = {
+	.name		= "dw_mmc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
+	.resource	= exynos4_dwmci_resource,
+	.dev		= {
+		.dma_mask		= &exynos4_dwmci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data	= &exynos4_dwci_pdata,
+	},
+};
+
+void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
+{
+	struct dw_mci_board *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
+			&exynos4_device_dwmci);
+
+	if (!npd->init)
+		npd->init = exynos4_dwmci_init;
+	if (!npd->get_bus_wd)
+		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-pd.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-pd.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-pd.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-exynos4/dev-pd.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power Domain support
+ *
+ * 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/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/regs-pmu.h>
+
+#include <plat/pd.h>
+
+static int exynos4_pd_enable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
+		!= S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s enable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+static int exynos4_pd_disable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(0, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s disable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+struct platform_device exynos4_device_pd[] = {
+	{
+		.name		= "samsung-pd",
+		.id		= 0,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_MFC_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 1,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_G3D_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 2,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD0_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 3,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD1_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 4,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_TV_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 5,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_CAM_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 6,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_GPS_CONF,
+			},
+		},
+	},
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-sysmmu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-sysmmu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dev-sysmmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,233 @@
+/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU support
+ *
+ * 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/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/sysmmu.h>
+#include <plat/s5p-clock.h>
+
+/* These names must be equal to the clock names in mach-exynos4/clock.c */
+const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
+	"SYSMMU_MDMA"	,
+	"SYSMMU_SSS"	,
+	"SYSMMU_FIMC0"	,
+	"SYSMMU_FIMC1"	,
+	"SYSMMU_FIMC2"	,
+	"SYSMMU_FIMC3"	,
+	"SYSMMU_JPEG"	,
+	"SYSMMU_FIMD0"	,
+	"SYSMMU_FIMD1"	,
+	"SYSMMU_PCIe"	,
+	"SYSMMU_G2D"	,
+	"SYSMMU_ROTATOR",
+	"SYSMMU_MDMA2"	,
+	"SYSMMU_TV"	,
+	"SYSMMU_MFC_L"	,
+	"SYSMMU_MFC_R"	,
+};
+
+static struct resource exynos4_sysmmu_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SYSMMU_MDMA0_0,
+		.end	= IRQ_SYSMMU_MDMA0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= EXYNOS4_PA_SYSMMU_SSS,
+		.end	= EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start	= IRQ_SYSMMU_SSS_0,
+		.end	= IRQ_SYSMMU_SSS_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[5] = {
+		.start	= IRQ_SYSMMU_FIMC0_0,
+		.end	= IRQ_SYSMMU_FIMC0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[7] = {
+		.start	= IRQ_SYSMMU_FIMC1_0,
+		.end	= IRQ_SYSMMU_FIMC1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[8] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC2,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[9] = {
+		.start	= IRQ_SYSMMU_FIMC2_0,
+		.end	= IRQ_SYSMMU_FIMC2_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[10] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC3,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[11] = {
+		.start	= IRQ_SYSMMU_FIMC3_0,
+		.end	= IRQ_SYSMMU_FIMC3_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[12] = {
+		.start	= EXYNOS4_PA_SYSMMU_JPEG,
+		.end	= EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[13] = {
+		.start	= IRQ_SYSMMU_JPEG_0,
+		.end	= IRQ_SYSMMU_JPEG_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[14] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[15] = {
+		.start	= IRQ_SYSMMU_LCD0_M0_0,
+		.end	= IRQ_SYSMMU_LCD0_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[16] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[17] = {
+		.start	= IRQ_SYSMMU_LCD1_M1_0,
+		.end	= IRQ_SYSMMU_LCD1_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[18] = {
+		.start	= EXYNOS4_PA_SYSMMU_PCIe,
+		.end	= EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[19] = {
+		.start	= IRQ_SYSMMU_PCIE_0,
+		.end	= IRQ_SYSMMU_PCIE_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[20] = {
+		.start	= EXYNOS4_PA_SYSMMU_G2D,
+		.end	= EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[21] = {
+		.start	= IRQ_SYSMMU_2D_0,
+		.end	= IRQ_SYSMMU_2D_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[22] = {
+		.start	= EXYNOS4_PA_SYSMMU_ROTATOR,
+		.end	= EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[23] = {
+		.start	= IRQ_SYSMMU_ROTATOR_0,
+		.end	= IRQ_SYSMMU_ROTATOR_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[24] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA2,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[25] = {
+		.start	= IRQ_SYSMMU_MDMA1_0,
+		.end	= IRQ_SYSMMU_MDMA1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[26] = {
+		.start	= EXYNOS4_PA_SYSMMU_TV,
+		.end	= EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[27] = {
+		.start	= IRQ_SYSMMU_TV_M0_0,
+		.end	= IRQ_SYSMMU_TV_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[28] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_L,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[29] = {
+		.start	= IRQ_SYSMMU_MFC_M0_0,
+		.end	= IRQ_SYSMMU_MFC_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[30] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_R,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[31] = {
+		.start	= IRQ_SYSMMU_MFC_M1_0,
+		.end	= IRQ_SYSMMU_MFC_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device exynos4_device_sysmmu = {
+	.name		= "s5p-sysmmu",
+	.id		= 32,
+	.num_resources	= ARRAY_SIZE(exynos4_sysmmu_resource),
+	.resource	= exynos4_sysmmu_resource,
+};
+EXPORT_SYMBOL(exynos4_device_sysmmu);
+
+static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
+{
+	sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
+	if (IS_ERR(sysmmu_clk[ips]))
+		sysmmu_clk[ips] = NULL;
+	else
+		clk_put(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_enable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_enable(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_disable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_disable(sysmmu_clk[ips]);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/dma.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,250 @@
+/* linux/arch/arm/mach-exynos4/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/dma.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+struct dma_pl330_peri pdma0_peri[28] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	},
+};
+
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
+};
+
+struct amba_device exynos4_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma0_pdata,
+	},
+	.res = {
+		.start = EXYNOS4_PA_PDMA0,
+		.end = EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
+};
+
+struct dma_pl330_peri pdma1_peri[25] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_TX,
+		.rqtype = MEMTODEV,
+	},
+};
+
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device exynos4_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma1_pdata,
+	},
+	.res = {
+		.start = EXYNOS4_PA_PDMA1,
+		.end = EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
+};
+
+static int __init exynos4_dma_init(void)
+{
+	amba_device_register(&exynos4_device_pdma0, &iomem_resource);
+	amba_device_register(&exynos4_device_pdma1, &iomem_resource);
+
+	return 0;
+}
+arch_initcall(exynos4_dma_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/headsmp.S linux-libre-3.2-gnu1/arch/arm/mach-exynos/headsmp.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/headsmp.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/mach-exynos4/headsmp.S
+ *
+ *  Cloned from linux/arch/arm/mach-realview/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  All Rights Reserved
+ *
+ * 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/linkage.h>
+#include <linux/init.h>
+
+	__CPUINIT
+
+/*
+ * exynos4 specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(exynos4_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	pen_release
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/* linux arch/arm/mach-exynos4/hotplug.c
+ *
+ *  Cloned from linux/arch/arm/mach-realview/hotplug.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * 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/errno.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+
+#include <mach/regs-pmu.h>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, %3\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+	for (;;) {
+
+		/* make cpu1 to be turned off at next WFI command */
+		if (cpu == 1)
+			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		if (pen_release == cpu_logical_map(cpu)) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+
+		/*
+		 * Getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
+		 */
+		(*spurious)++;
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu, &spurious);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+
+	if (spurious)
+		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/* linux/arch/arm/mach-exynos4/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * 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.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rp, rv, tmp
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+#include <plat/debug-macro.S>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MACH_DMA_H
+#define __MACH_DMA_H
+
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
+
+#endif /* __MACH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/dwmci.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/dwmci.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/dwmci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/dwmci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Synopsys DesignWare Mobile Storage for EXYNOS4210
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_ARCH_DWMCI_H
+#define __ASM_ARM_ARCH_DWMCI_H __FILE__
+
+#include <linux/mmc/dw_mmc.h>
+
+extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
+
+#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/* arch/arm/mach-exynos4/include/mach/entry-macro.S
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for EXYNOS4 platforms
+ *
+ * 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 <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		mov	\tmp, #0
+
+		mrc	p15, 0, \base, c0, c0, 5
+		and	\base, \base, #3
+		cmp	\base, #0
+		beq	1f
+
+		ldr	\tmp, =gic_bank_offset
+		ldr	\tmp, [\tmp]
+		cmp	\base, #1
+		beq	1f
+
+		cmp	\base, #2
+		addeq	\tmp, \tmp, \tmp
+		addne	\tmp, \tmp, \tmp, LSL #1
+
+1:		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		add	\base, \base, \tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.  To wit:
+		 *
+		 * Interrupts 0-15 are IPI
+		 * 16-28 are reserved
+		 * 29-31 are local.  We allow 30 to be used for the watchdog.
+		 * 32-1020 are global
+		 * 1021-1022 are reserved
+		 * 1023 is "spurious" (no interrupt)
+		 *
+		 * For now, we ignore all local interrupts so only return an interrupt if it's
+		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+		 *
+		 * A simple read from the controller will tell us the number of the highest
+                 * priority enabled interrupt.  We then just need to check whether it is in the
+		 * valid range for an IRQ (30-1020 inclusive).
+		 */
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr	\tmp, =1021
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #15
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+		addne	\irqnr, \irqnr, #32
+
+		.endm
+
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt on the
+		 * controller, since this requires the original irqstat value which
+		 * we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		cmpcs	\irqnr, \irqnr
+		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/exynos4-clock.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/exynos4-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/exynos4-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/exynos4-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for exynos4 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clk clk_sclk_hdmi27m;
+extern struct clk clk_sclk_usbphy0;
+extern struct clk clk_sclk_usbphy1;
+extern struct clk clk_sclk_hdmiphy;
+
+extern struct clksrc_clk clk_sclk_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_aclk_133;
+extern struct clksrc_clk clk_mout_epll;
+extern struct clksrc_clk clk_sclk_vpll;
+
+extern struct clk *clkset_corebus_list[];
+extern struct clksrc_sources clkset_mout_corebus;
+
+extern struct clk *clkset_aclk_top_list[];
+extern struct clksrc_sources clkset_aclk;
+
+extern struct clk *clkset_group_list[];
+extern struct clksrc_sources clkset_group;
+
+extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,149 @@
+/* linux/arch/arm/mach-exynos4/include/mach/gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+/* Practically, GPIO banks up to GPZ are the configurable gpio banks */
+
+/* GPIO bank sizes */
+#define EXYNOS4_GPIO_A0_NR	(8)
+#define EXYNOS4_GPIO_A1_NR	(6)
+#define EXYNOS4_GPIO_B_NR	(8)
+#define EXYNOS4_GPIO_C0_NR	(5)
+#define EXYNOS4_GPIO_C1_NR	(5)
+#define EXYNOS4_GPIO_D0_NR	(4)
+#define EXYNOS4_GPIO_D1_NR	(4)
+#define EXYNOS4_GPIO_E0_NR	(5)
+#define EXYNOS4_GPIO_E1_NR	(8)
+#define EXYNOS4_GPIO_E2_NR	(6)
+#define EXYNOS4_GPIO_E3_NR	(8)
+#define EXYNOS4_GPIO_E4_NR	(8)
+#define EXYNOS4_GPIO_F0_NR	(8)
+#define EXYNOS4_GPIO_F1_NR	(8)
+#define EXYNOS4_GPIO_F2_NR	(8)
+#define EXYNOS4_GPIO_F3_NR	(6)
+#define EXYNOS4_GPIO_J0_NR	(8)
+#define EXYNOS4_GPIO_J1_NR	(5)
+#define EXYNOS4_GPIO_K0_NR	(7)
+#define EXYNOS4_GPIO_K1_NR	(7)
+#define EXYNOS4_GPIO_K2_NR	(7)
+#define EXYNOS4_GPIO_K3_NR	(7)
+#define EXYNOS4_GPIO_L0_NR	(8)
+#define EXYNOS4_GPIO_L1_NR	(3)
+#define EXYNOS4_GPIO_L2_NR	(8)
+#define EXYNOS4_GPIO_X0_NR	(8)
+#define EXYNOS4_GPIO_X1_NR	(8)
+#define EXYNOS4_GPIO_X2_NR	(8)
+#define EXYNOS4_GPIO_X3_NR	(8)
+#define EXYNOS4_GPIO_Y0_NR	(6)
+#define EXYNOS4_GPIO_Y1_NR	(4)
+#define EXYNOS4_GPIO_Y2_NR	(6)
+#define EXYNOS4_GPIO_Y3_NR	(8)
+#define EXYNOS4_GPIO_Y4_NR	(8)
+#define EXYNOS4_GPIO_Y5_NR	(8)
+#define EXYNOS4_GPIO_Y6_NR	(8)
+#define EXYNOS4_GPIO_Z_NR	(7)
+
+/* GPIO bank numbers */
+
+#define EXYNOS4_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	EXYNOS4_GPIO_A0_START	= 0,
+	EXYNOS4_GPIO_A1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A0),
+	EXYNOS4_GPIO_B_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A1),
+	EXYNOS4_GPIO_C0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_B),
+	EXYNOS4_GPIO_C1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C0),
+	EXYNOS4_GPIO_D0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C1),
+	EXYNOS4_GPIO_D1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D0),
+	EXYNOS4_GPIO_E0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D1),
+	EXYNOS4_GPIO_E1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E0),
+	EXYNOS4_GPIO_E2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E1),
+	EXYNOS4_GPIO_E3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E2),
+	EXYNOS4_GPIO_E4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E3),
+	EXYNOS4_GPIO_F0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E4),
+	EXYNOS4_GPIO_F1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F0),
+	EXYNOS4_GPIO_F2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F1),
+	EXYNOS4_GPIO_F3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F2),
+	EXYNOS4_GPIO_J0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F3),
+	EXYNOS4_GPIO_J1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J0),
+	EXYNOS4_GPIO_K0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J1),
+	EXYNOS4_GPIO_K1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K0),
+	EXYNOS4_GPIO_K2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K1),
+	EXYNOS4_GPIO_K3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K2),
+	EXYNOS4_GPIO_L0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K3),
+	EXYNOS4_GPIO_L1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L0),
+	EXYNOS4_GPIO_L2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L1),
+	EXYNOS4_GPIO_X0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L2),
+	EXYNOS4_GPIO_X1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X0),
+	EXYNOS4_GPIO_X2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X1),
+	EXYNOS4_GPIO_X3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X2),
+	EXYNOS4_GPIO_Y0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X3),
+	EXYNOS4_GPIO_Y1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y0),
+	EXYNOS4_GPIO_Y2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y1),
+	EXYNOS4_GPIO_Y3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y2),
+	EXYNOS4_GPIO_Y4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y3),
+	EXYNOS4_GPIO_Y5_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y4),
+	EXYNOS4_GPIO_Y6_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y5),
+	EXYNOS4_GPIO_Z_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y6),
+};
+
+/* EXYNOS4 GPIO number definitions */
+#define EXYNOS4_GPA0(_nr)	(EXYNOS4_GPIO_A0_START + (_nr))
+#define EXYNOS4_GPA1(_nr)	(EXYNOS4_GPIO_A1_START + (_nr))
+#define EXYNOS4_GPB(_nr)	(EXYNOS4_GPIO_B_START + (_nr))
+#define EXYNOS4_GPC0(_nr)	(EXYNOS4_GPIO_C0_START + (_nr))
+#define EXYNOS4_GPC1(_nr)	(EXYNOS4_GPIO_C1_START + (_nr))
+#define EXYNOS4_GPD0(_nr)	(EXYNOS4_GPIO_D0_START + (_nr))
+#define EXYNOS4_GPD1(_nr)	(EXYNOS4_GPIO_D1_START + (_nr))
+#define EXYNOS4_GPE0(_nr)	(EXYNOS4_GPIO_E0_START + (_nr))
+#define EXYNOS4_GPE1(_nr)	(EXYNOS4_GPIO_E1_START + (_nr))
+#define EXYNOS4_GPE2(_nr)	(EXYNOS4_GPIO_E2_START + (_nr))
+#define EXYNOS4_GPE3(_nr)	(EXYNOS4_GPIO_E3_START + (_nr))
+#define EXYNOS4_GPE4(_nr)	(EXYNOS4_GPIO_E4_START + (_nr))
+#define EXYNOS4_GPF0(_nr)	(EXYNOS4_GPIO_F0_START + (_nr))
+#define EXYNOS4_GPF1(_nr)	(EXYNOS4_GPIO_F1_START + (_nr))
+#define EXYNOS4_GPF2(_nr)	(EXYNOS4_GPIO_F2_START + (_nr))
+#define EXYNOS4_GPF3(_nr)	(EXYNOS4_GPIO_F3_START + (_nr))
+#define EXYNOS4_GPJ0(_nr)	(EXYNOS4_GPIO_J0_START + (_nr))
+#define EXYNOS4_GPJ1(_nr)	(EXYNOS4_GPIO_J1_START + (_nr))
+#define EXYNOS4_GPK0(_nr)	(EXYNOS4_GPIO_K0_START + (_nr))
+#define EXYNOS4_GPK1(_nr)	(EXYNOS4_GPIO_K1_START + (_nr))
+#define EXYNOS4_GPK2(_nr)	(EXYNOS4_GPIO_K2_START + (_nr))
+#define EXYNOS4_GPK3(_nr)	(EXYNOS4_GPIO_K3_START + (_nr))
+#define EXYNOS4_GPL0(_nr)	(EXYNOS4_GPIO_L0_START + (_nr))
+#define EXYNOS4_GPL1(_nr)	(EXYNOS4_GPIO_L1_START + (_nr))
+#define EXYNOS4_GPL2(_nr)	(EXYNOS4_GPIO_L2_START + (_nr))
+#define EXYNOS4_GPX0(_nr)	(EXYNOS4_GPIO_X0_START + (_nr))
+#define EXYNOS4_GPX1(_nr)	(EXYNOS4_GPIO_X1_START + (_nr))
+#define EXYNOS4_GPX2(_nr)	(EXYNOS4_GPIO_X2_START + (_nr))
+#define EXYNOS4_GPX3(_nr)	(EXYNOS4_GPIO_X3_START + (_nr))
+#define EXYNOS4_GPY0(_nr)	(EXYNOS4_GPIO_Y0_START + (_nr))
+#define EXYNOS4_GPY1(_nr)	(EXYNOS4_GPIO_Y1_START + (_nr))
+#define EXYNOS4_GPY2(_nr)	(EXYNOS4_GPIO_Y2_START + (_nr))
+#define EXYNOS4_GPY3(_nr)	(EXYNOS4_GPIO_Y3_START + (_nr))
+#define EXYNOS4_GPY4(_nr)	(EXYNOS4_GPIO_Y4_START + (_nr))
+#define EXYNOS4_GPY5(_nr)	(EXYNOS4_GPIO_Y5_START + (_nr))
+#define EXYNOS4_GPY6(_nr)	(EXYNOS4_GPIO_Y6_START + (_nr))
+#define EXYNOS4_GPZ(_nr)	(EXYNOS4_GPIO_Z_START + (_nr))
+
+/* the end of the EXYNOS4 specific gpios */
+#define EXYNOS4_GPIO_END	(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + 1)
+#define S3C_GPIO_END		EXYNOS4_GPIO_END
+
+/* define the number of gpios we need to the one after the GPZ() range */
+#define ARCH_NR_GPIOS		(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-exynos4/include/mach/hardware.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Hardware support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-exynos4/include/mach/io.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Default IO routines for EXYNOS4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H __FILE__
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,169 @@
+/* linux/arch/arm/mach-exynos4/include/mach/irqs.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* PPI: Private Peripheral Interrupt */
+
+#define IRQ_PPI(x)		S5P_IRQ(x+16)
+
+#define IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
+
+/* SPI: Shared Peripheral Interrupt */
+
+#define IRQ_SPI(x)		S5P_IRQ(x+32)
+
+#define IRQ_EINT0		IRQ_SPI(16)
+#define IRQ_EINT1		IRQ_SPI(17)
+#define IRQ_EINT2		IRQ_SPI(18)
+#define IRQ_EINT3		IRQ_SPI(19)
+#define IRQ_EINT4		IRQ_SPI(20)
+#define IRQ_EINT5		IRQ_SPI(21)
+#define IRQ_EINT6		IRQ_SPI(22)
+#define IRQ_EINT7		IRQ_SPI(23)
+#define IRQ_EINT8		IRQ_SPI(24)
+#define IRQ_EINT9		IRQ_SPI(25)
+#define IRQ_EINT10		IRQ_SPI(26)
+#define IRQ_EINT11		IRQ_SPI(27)
+#define IRQ_EINT12		IRQ_SPI(28)
+#define IRQ_EINT13		IRQ_SPI(29)
+#define IRQ_EINT14		IRQ_SPI(30)
+#define IRQ_EINT15		IRQ_SPI(31)
+#define IRQ_EINT16_31		IRQ_SPI(32)
+
+#define IRQ_PDMA0		IRQ_SPI(35)
+#define IRQ_PDMA1		IRQ_SPI(36)
+#define IRQ_TIMER0_VIC		IRQ_SPI(37)
+#define IRQ_TIMER1_VIC		IRQ_SPI(38)
+#define IRQ_TIMER2_VIC		IRQ_SPI(39)
+#define IRQ_TIMER3_VIC		IRQ_SPI(40)
+#define IRQ_TIMER4_VIC		IRQ_SPI(41)
+#define IRQ_MCT_L0		IRQ_SPI(42)
+#define IRQ_WDT			IRQ_SPI(43)
+#define IRQ_RTC_ALARM		IRQ_SPI(44)
+#define IRQ_RTC_TIC		IRQ_SPI(45)
+#define IRQ_GPIO_XB		IRQ_SPI(46)
+#define IRQ_GPIO_XA		IRQ_SPI(47)
+#define IRQ_MCT_L1		IRQ_SPI(48)
+
+#define IRQ_UART0		IRQ_SPI(52)
+#define IRQ_UART1		IRQ_SPI(53)
+#define IRQ_UART2		IRQ_SPI(54)
+#define IRQ_UART3		IRQ_SPI(55)
+#define IRQ_UART4		IRQ_SPI(56)
+#define IRQ_MCT_G0		IRQ_SPI(57)
+#define IRQ_IIC			IRQ_SPI(58)
+#define IRQ_IIC1		IRQ_SPI(59)
+#define IRQ_IIC2		IRQ_SPI(60)
+#define IRQ_IIC3		IRQ_SPI(61)
+#define IRQ_IIC4		IRQ_SPI(62)
+#define IRQ_IIC5		IRQ_SPI(63)
+#define IRQ_IIC6		IRQ_SPI(64)
+#define IRQ_IIC7		IRQ_SPI(65)
+
+#define IRQ_USB_HOST		IRQ_SPI(70)
+#define IRQ_USB_HSOTG		IRQ_SPI(71)
+#define IRQ_MODEM_IF		IRQ_SPI(72)
+#define IRQ_HSMMC0		IRQ_SPI(73)
+#define IRQ_HSMMC1		IRQ_SPI(74)
+#define IRQ_HSMMC2		IRQ_SPI(75)
+#define IRQ_HSMMC3		IRQ_SPI(76)
+#define IRQ_DWMCI		IRQ_SPI(77)
+
+#define IRQ_MIPI_CSIS0		IRQ_SPI(78)
+#define IRQ_MIPI_CSIS1		IRQ_SPI(80)
+
+#define IRQ_ONENAND_AUDI	IRQ_SPI(82)
+#define IRQ_ROTATOR		IRQ_SPI(83)
+#define IRQ_FIMC0		IRQ_SPI(84)
+#define IRQ_FIMC1		IRQ_SPI(85)
+#define IRQ_FIMC2		IRQ_SPI(86)
+#define IRQ_FIMC3		IRQ_SPI(87)
+#define IRQ_JPEG		IRQ_SPI(88)
+#define IRQ_2D			IRQ_SPI(89)
+#define IRQ_PCIE		IRQ_SPI(90)
+
+#define IRQ_MIXER		IRQ_SPI(91)
+#define IRQ_HDMI		IRQ_SPI(92)
+#define IRQ_IIC_HDMIPHY		IRQ_SPI(93)
+#define IRQ_MFC			IRQ_SPI(94)
+#define IRQ_SDO			IRQ_SPI(95)
+
+#define IRQ_AUDIO_SS		IRQ_SPI(96)
+#define IRQ_I2S0		IRQ_SPI(97)
+#define IRQ_I2S1		IRQ_SPI(98)
+#define IRQ_I2S2		IRQ_SPI(99)
+#define IRQ_AC97		IRQ_SPI(100)
+
+#define IRQ_SPDIF		IRQ_SPI(104)
+#define IRQ_ADC0		IRQ_SPI(105)
+#define IRQ_PEN0		IRQ_SPI(106)
+#define IRQ_ADC1		IRQ_SPI(107)
+#define IRQ_PEN1		IRQ_SPI(108)
+#define IRQ_KEYPAD		IRQ_SPI(109)
+#define IRQ_PMU			IRQ_SPI(110)
+#define IRQ_GPS			IRQ_SPI(111)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
+#define IRQ_SLIMBUS		IRQ_SPI(113)
+
+#define IRQ_TSI			IRQ_SPI(115)
+#define IRQ_SATA		IRQ_SPI(116)
+
+#define MAX_IRQ_IN_COMBINER	8
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
+#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
+
+#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
+#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
+#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
+#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
+#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
+#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
+#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
+#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
+
+#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
+#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
+#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
+#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
+#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
+#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
+#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
+#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
+
+#define IRQ_FIMD0_FIFO		COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
+
+#define MAX_COMBINER_NR		16
+
+#define IRQ_ADC			IRQ_ADC0
+#define IRQ_TC			IRQ_PEN0
+
+#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
+
+#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
+#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
+
+/* optional GPIO interrupts */
+#define S5P_GPIOINT_BASE	(S5P_IRQ_EINT_BASE + 32)
+#define IRQ_GPIO1_NR_GROUPS	16
+#define IRQ_GPIO2_NR_GROUPS	9
+#define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
+
+/* Set the default NR_IRQS */
+#define NR_IRQS			(IRQ_GPIO_END + 64)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,197 @@
+/* linux/arch/arm/mach-exynos/include/mach/map.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+
+/*
+ * EXYNOS4 UART offset is 0x10000 but the older S5P SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET			(0x10000)
+
+#include <plat/map-s5p.h>
+
+#define EXYNOS4_PA_SYSRAM0		0x02025000
+#define EXYNOS4_PA_SYSRAM1		0x02020000
+
+#define EXYNOS4_PA_FIMC0		0x11800000
+#define EXYNOS4_PA_FIMC1		0x11810000
+#define EXYNOS4_PA_FIMC2		0x11820000
+#define EXYNOS4_PA_FIMC3		0x11830000
+
+#define EXYNOS4_PA_I2S0			0x03830000
+#define EXYNOS4_PA_I2S1			0xE3100000
+#define EXYNOS4_PA_I2S2			0xE2A00000
+
+#define EXYNOS4_PA_PCM0			0x03840000
+#define EXYNOS4_PA_PCM1			0x13980000
+#define EXYNOS4_PA_PCM2			0x13990000
+
+#define EXYNOS4_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
+
+#define EXYNOS4_PA_ONENAND		0x0C000000
+#define EXYNOS4_PA_ONENAND_DMA		0x0C600000
+
+#define EXYNOS4_PA_CHIPID		0x10000000
+
+#define EXYNOS4_PA_SYSCON		0x10010000
+#define EXYNOS4_PA_PMU			0x10020000
+#define EXYNOS4_PA_CMU			0x10030000
+
+#define EXYNOS4_PA_SYSTIMER		0x10050000
+#define EXYNOS4_PA_WATCHDOG		0x10060000
+#define EXYNOS4_PA_RTC			0x10070000
+
+#define EXYNOS4_PA_KEYPAD		0x100A0000
+
+#define EXYNOS4_PA_DMC0			0x10400000
+
+#define EXYNOS4_PA_COMBINER		0x10440000
+
+#define EXYNOS4_PA_GIC_CPU		0x10480000
+#define EXYNOS4_PA_GIC_DIST		0x10490000
+
+#define EXYNOS4_PA_COREPERI		0x10500000
+#define EXYNOS4_PA_TWD			0x10500600
+#define EXYNOS4_PA_L2CC			0x10502000
+
+#define EXYNOS4_PA_MDMA			0x10810000
+#define EXYNOS4_PA_PDMA0		0x12680000
+#define EXYNOS4_PA_PDMA1		0x12690000
+
+#define EXYNOS4_PA_SYSMMU_MDMA		0x10A40000
+#define EXYNOS4_PA_SYSMMU_SSS		0x10A50000
+#define EXYNOS4_PA_SYSMMU_FIMC0		0x11A20000
+#define EXYNOS4_PA_SYSMMU_FIMC1		0x11A30000
+#define EXYNOS4_PA_SYSMMU_FIMC2		0x11A40000
+#define EXYNOS4_PA_SYSMMU_FIMC3		0x11A50000
+#define EXYNOS4_PA_SYSMMU_JPEG		0x11A60000
+#define EXYNOS4_PA_SYSMMU_FIMD0		0x11E20000
+#define EXYNOS4_PA_SYSMMU_FIMD1		0x12220000
+#define EXYNOS4_PA_SYSMMU_PCIe		0x12620000
+#define EXYNOS4_PA_SYSMMU_G2D		0x12A20000
+#define EXYNOS4_PA_SYSMMU_ROTATOR	0x12A30000
+#define EXYNOS4_PA_SYSMMU_MDMA2		0x12A40000
+#define EXYNOS4_PA_SYSMMU_TV		0x12E20000
+#define EXYNOS4_PA_SYSMMU_MFC_L		0x13620000
+#define EXYNOS4_PA_SYSMMU_MFC_R		0x13630000
+
+#define EXYNOS4_PA_GPIO1		0x11400000
+#define EXYNOS4_PA_GPIO2		0x11000000
+#define EXYNOS4_PA_GPIO3		0x03860000
+
+#define EXYNOS4_PA_MIPI_CSIS0		0x11880000
+#define EXYNOS4_PA_MIPI_CSIS1		0x11890000
+
+#define EXYNOS4_PA_FIMD0		0x11C00000
+
+#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+#define EXYNOS4_PA_DWMCI		0x12550000
+
+#define EXYNOS4_PA_SATA			0x12560000
+#define EXYNOS4_PA_SATAPHY		0x125D0000
+#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
+
+#define EXYNOS4_PA_SROMC		0x12570000
+
+#define EXYNOS4_PA_EHCI			0x12580000
+#define EXYNOS4_PA_HSPHY		0x125B0000
+#define EXYNOS4_PA_MFC			0x13400000
+
+#define EXYNOS4_PA_UART			0x13800000
+
+#define EXYNOS4_PA_VP			0x12C00000
+#define EXYNOS4_PA_MIXER		0x12C10000
+#define EXYNOS4_PA_SDO			0x12C20000
+#define EXYNOS4_PA_HDMI			0x12D00000
+#define EXYNOS4_PA_IIC_HDMIPHY		0x138E0000
+
+#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_ADC			0x13910000
+#define EXYNOS4_PA_ADC1			0x13911000
+
+#define EXYNOS4_PA_AC97			0x139A0000
+
+#define EXYNOS4_PA_SPDIF		0x139B0000
+
+#define EXYNOS4_PA_TIMER		0x139D0000
+
+#define EXYNOS4_PA_SDRAM		0x40000000
+
+/* Compatibiltiy Defines */
+
+#define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
+#define S3C_PA_HSMMC1			EXYNOS4_PA_HSMMC(1)
+#define S3C_PA_HSMMC2			EXYNOS4_PA_HSMMC(2)
+#define S3C_PA_HSMMC3			EXYNOS4_PA_HSMMC(3)
+#define S3C_PA_IIC			EXYNOS4_PA_IIC(0)
+#define S3C_PA_IIC1			EXYNOS4_PA_IIC(1)
+#define S3C_PA_IIC2			EXYNOS4_PA_IIC(2)
+#define S3C_PA_IIC3			EXYNOS4_PA_IIC(3)
+#define S3C_PA_IIC4			EXYNOS4_PA_IIC(4)
+#define S3C_PA_IIC5			EXYNOS4_PA_IIC(5)
+#define S3C_PA_IIC6			EXYNOS4_PA_IIC(6)
+#define S3C_PA_IIC7			EXYNOS4_PA_IIC(7)
+#define S3C_PA_RTC			EXYNOS4_PA_RTC
+#define S3C_PA_WDT			EXYNOS4_PA_WATCHDOG
+#define S3C_PA_UART			EXYNOS4_PA_UART
+
+#define S5P_PA_CHIPID			EXYNOS4_PA_CHIPID
+#define S5P_PA_EHCI			EXYNOS4_PA_EHCI
+#define S5P_PA_FIMC0			EXYNOS4_PA_FIMC0
+#define S5P_PA_FIMC1			EXYNOS4_PA_FIMC1
+#define S5P_PA_FIMC2			EXYNOS4_PA_FIMC2
+#define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
+#define S5P_PA_FIMD0			EXYNOS4_PA_FIMD0
+#define S5P_PA_HDMI			EXYNOS4_PA_HDMI
+#define S5P_PA_IIC_HDMIPHY		EXYNOS4_PA_IIC_HDMIPHY
+#define S5P_PA_MFC			EXYNOS4_PA_MFC
+#define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
+#define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_MIXER			EXYNOS4_PA_MIXER
+#define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
+#define S5P_PA_SDO			EXYNOS4_PA_SDO
+#define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
+#define S5P_PA_SROMC			EXYNOS4_PA_SROMC
+#define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
+#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
+#define S5P_PA_VP			EXYNOS4_PA_VP
+
+#define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
+#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+
+#define EXYNOS_PA_COMBINER		EXYNOS4_PA_COMBINER
+#define EXYNOS_PA_GIC_CPU		EXYNOS4_PA_GIC_CPU
+#define EXYNOS_PA_GIC_DIST		EXYNOS4_PA_GIC_DIST
+#define EXYNOS_PA_PMU			EXYNOS4_PA_PMU
+#define EXYNOS_PA_SYSTIMER		EXYNOS4_PA_SYSTIMER
+
+/* Compatibility UART */
+
+#define S3C_VA_UARTx(x)			(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+
+#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_PA_UART0			S5P_PA_UART(0)
+#define S5P_PA_UART1			S5P_PA_UART(1)
+#define S5P_PA_UART2			S5P_PA_UART(2)
+#define S5P_PA_UART3			S5P_PA_UART(3)
+#define S5P_PA_UART4			S5P_PA_UART(4)
+
+#define S5P_SZ_UART			SZ_256
+
+#endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/memory.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
+
+#define PLAT_PHYS_OFFSET		UL(0x40000000)
+
+/* Maximum of 256MiB in one bank */
+#define MAX_PHYSMEM_BITS	32
+#define SECTION_SIZE_BITS	28
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,65 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * EXYNOS4210 - PM core support for arch/arm/plat-s5p/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PM_CORE_H
+#define __ASM_ARCH_PM_CORE_H __FILE__
+
+#include <mach/regs-pmu.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	unsigned int tmp;
+	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp &= ~(1 << 31);
+	__raw_writel(tmp, S5P_WAKEUP_MASK);
+
+	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
+	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* nothing here yet */
+}
+
+static inline void samsung_pm_saved_gpios(void)
+{
+	/* nothing here yet */
+}
+
+#endif /* __ASM_ARCH_PM_CORE_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/pmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/pmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - PMU(Power Management Unit) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PMU_H
+#define __ASM_ARCH_PMU_H __FILE__
+
+#define PMU_TABLE_END	NULL
+
+enum sys_powerdown {
+	SYS_AFTR,
+	SYS_LPA,
+	SYS_SLEEP,
+	NUM_SYS_POWERDOWN,
+};
+
+struct exynos4_pmu_conf {
+	void __iomem *reg;
+	unsigned int val[NUM_SYS_POWERDOWN];
+};
+
+extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __ASM_ARCH_PMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-audss.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-audss.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-audss.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-audss.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+/* arch/arm/mach-exynos4/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *		http://www.samsung.com
+ *
+ * Exynos4 Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-clock.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,210 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <plat/cpu.h>
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
+
+#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
+#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
+#define S5P_CLKGATE_IP_LEFTBUS		S5P_CLKREG(0x04800)
+
+#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
+#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
+#define S5P_CLKGATE_IP_RIGHTBUS		S5P_CLKREG(0x08800)
+
+#define S5P_EPLL_LOCK			S5P_CLKREG(0x0C010)
+#define S5P_VPLL_LOCK			S5P_CLKREG(0x0C020)
+
+#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
+#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
+#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
+#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
+
+#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
+#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
+#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
+#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
+#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
+#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
+#define S5P_CLKSRC_MAUDIO		S5P_CLKREG(0x0C23C)
+#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
+#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
+#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
+
+#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
+#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
+#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
+#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
+#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
+#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
+#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
+
+#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
+#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
+#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
+#define S5P_CLKDIV_MFC			S5P_CLKREG(0x0C528)
+#define S5P_CLKDIV_G3D			S5P_CLKREG(0x0C52C)
+#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
+#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
+#define S5P_CLKDIV_MAUDIO		S5P_CLKREG(0x0C53C)
+#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
+#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
+#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
+#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
+#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
+#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
+#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
+#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
+#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
+#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
+#define S5P_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
+
+#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
+
+#define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
+#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
+#define S5P_CLKGATE_IP_MFC		S5P_CLKREG(0x0C928)
+#define S5P_CLKGATE_IP_G3D		S5P_CLKREG(0x0C92C)
+#define S5P_CLKGATE_IP_IMAGE		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C930) : \
+					S5P_CLKREG(0x04930))
+#define S5P_CLKGATE_IP_IMAGE_4210	S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE_4212	S5P_CLKREG(0x04930)
+#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
+#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
+#define S5P_CLKGATE_IP_GPS		S5P_CLKREG(0x0C94C)
+#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
+#define S5P_CLKGATE_IP_PERIR		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C960) : \
+					S5P_CLKREG(0x08960))
+#define S5P_CLKGATE_IP_PERIR_4210	S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR_4212	S5P_CLKREG(0x08960)
+#define S5P_CLKGATE_BLOCK		S5P_CLKREG(0x0C970)
+
+#define S5P_CLKSRC_MASK_DMC		S5P_CLKREG(0x10300)
+#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
+#define S5P_CLKDIV_DMC1			S5P_CLKREG(0x10504)
+#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
+#define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
+
+#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
+#define S5P_MPLL_LOCK			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14004) :  \
+					S5P_CLKREG(0x10008))
+#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
+#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
+#define S5P_MPLL_CON0			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14108) : \
+					S5P_CLKREG(0x10108))
+#define S5P_MPLL_CON1			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x1410C) : \
+					S5P_CLKREG(0x1010C))
+
+#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
+#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
+
+#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
+#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
+#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
+#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
+
+#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
+#define S5P_CLKGATE_IP_CPU		S5P_CLKREG(0x14900)
+
+#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
+
+#define S5P_APLLCON0_ENABLE_SHIFT	(31)
+#define S5P_APLLCON0_LOCKED_SHIFT	(29)
+#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
+#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
+
+#define S5P_EPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_EPLLCON0_LOCKED_SHIFT	(29)
+
+#define S5P_VPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_VPLLCON0_LOCKED_SHIFT	(29)
+
+#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
+#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+
+#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
+#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
+#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
+#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
+#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
+#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
+#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
+#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
+#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
+#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
+#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
+#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
+
+#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
+#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
+#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
+#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
+#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
+#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
+#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
+#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
+#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
+#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
+#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
+#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
+#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
+#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
+
+#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
+#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
+#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
+#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
+#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
+#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
+#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
+
+#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
+#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
+#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
+#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+
+/* Only for EXYNOS4210 */
+
+#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
+#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
+#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
+
+/* Compatibility defines and inclusion */
+
+#include <mach/regs-pmu.h>
+
+#define S5P_EPLL_CON			S5P_EPLL_CON0
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-gpio.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO (including EINT) register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_GPIO_H
+#define __ASM_ARCH_REGS_GPIO_H __FILE__
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#define EXYNOS4_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
+#define S5P_EINT_CON(x)			(EXYNOS4_EINT40CON + ((x) * 0x4))
+
+#define EXYNOS4_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
+#define S5P_EINT_FLTCON(x)		(EXYNOS4_EINT40FLTCON0 + ((x) * 0x4))
+
+#define EXYNOS4_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
+#define S5P_EINT_MASK(x)		(EXYNOS4_EINT40MASK + ((x) * 0x4))
+
+#define EXYNOS4_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
+#define S5P_EINT_PEND(x)		(EXYNOS4_EINT40PEND + ((x) * 0x4))
+
+#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
+
+#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
+
+#define EINT_MODE			S3C_GPIO_SFN(0xf)
+
+#define EINT_GPIO_0(x)			EXYNOS4_GPX0(x)
+#define EINT_GPIO_1(x)			EXYNOS4_GPX1(x)
+#define EINT_GPIO_2(x)			EXYNOS4_GPX2(x)
+#define EINT_GPIO_3(x)			EXYNOS4_GPX3(x)
+
+#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-irq.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-irq.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/gic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-mct.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-mct.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-mct.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-mct.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,53 @@
+/* arch/arm/mach-exynos4/include/mach/regs-mct.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 MCT configutation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_MCT_H
+#define __ASM_ARCH_REGS_MCT_H __FILE__
+
+#include <mach/map.h>
+
+#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
+
+#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
+
+#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
+
+#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
+
+#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
+
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
+
+#define MCT_L_TCNTB_OFFSET		(0x00)
+#define MCT_L_ICNTB_OFFSET		(0x08)
+#define MCT_L_TCON_OFFSET		(0x20)
+#define MCT_L_INT_CSTAT_OFFSET		(0x30)
+#define MCT_L_INT_ENB_OFFSET		(0x34)
+#define MCT_L_WSTAT_OFFSET		(0x40)
+
+#define MCT_G_TCON_START		(1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
+
+#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
+#define MCT_L_TCON_INT_START		(1 << 1)
+#define MCT_L_TCON_TIMER_START		(1 << 0)
+
+#endif /* __ASM_ARCH_REGS_MCT_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-mem.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-mem.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-mem.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - SROMC and DMC register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_MEM_H
+#define __ASM_ARCH_REGS_MEM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_DMC0_MEMCON_OFFSET		0x04
+
+#define S5P_DMC0_MEMTYPE_SHIFT		8
+#define S5P_DMC0_MEMTYPE_MASK		0xF
+
+#endif /* __ASM_ARCH_REGS_MEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-pmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-pmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power management unit definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_PMU_H
+#define __ASM_ARCH_REGS_PMU_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
+
+#define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
+
+#define S5P_CENTRAL_LOWPWR_CFG			(1 << 16)
+
+#define S5P_CENTRAL_SEQ_OPTION			S5P_PMUREG(0x0208)
+
+#define S5P_USE_STANDBY_WFI0			(1 << 16)
+#define S5P_USE_STANDBY_WFI1			(1 << 17)
+#define S5P_USE_STANDBYWFI_ISP_ARM		(1 << 18)
+#define S5P_USE_STANDBY_WFE0			(1 << 24)
+#define S5P_USE_STANDBY_WFE1			(1 << 25)
+#define S5P_USE_STANDBYWFE_ISP_ARM		(1 << 26)
+
+#define S5P_SWRESET				S5P_PMUREG(0x0400)
+
+#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
+#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
+#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
+
+#define S5P_HDMI_PHY_CONTROL			S5P_PMUREG(0x0700)
+#define S5P_HDMI_PHY_ENABLE			(1 << 0)
+
+#define S5P_DAC_PHY_CONTROL			S5P_PMUREG(0x070C)
+#define S5P_DAC_PHY_ENABLE			(1 << 0)
+
+#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
+#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
+#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
+#define S5P_MIPI_DPHY_MRESETN			(1 << 2)
+
+#define S5P_INFORM0				S5P_PMUREG(0x0800)
+#define S5P_INFORM1				S5P_PMUREG(0x0804)
+#define S5P_INFORM2				S5P_PMUREG(0x0808)
+#define S5P_INFORM3				S5P_PMUREG(0x080C)
+#define S5P_INFORM4				S5P_PMUREG(0x0810)
+#define S5P_INFORM5				S5P_PMUREG(0x0814)
+#define S5P_INFORM6				S5P_PMUREG(0x0818)
+#define S5P_INFORM7				S5P_PMUREG(0x081C)
+
+#define S5P_ARM_CORE0_LOWPWR			S5P_PMUREG(0x1000)
+#define S5P_DIS_IRQ_CORE0			S5P_PMUREG(0x1004)
+#define S5P_DIS_IRQ_CENTRAL0			S5P_PMUREG(0x1008)
+#define S5P_ARM_CORE1_LOWPWR			S5P_PMUREG(0x1010)
+#define S5P_DIS_IRQ_CORE1			S5P_PMUREG(0x1014)
+#define S5P_DIS_IRQ_CENTRAL1			S5P_PMUREG(0x1018)
+#define S5P_ARM_COMMON_LOWPWR			S5P_PMUREG(0x1080)
+#define S5P_L2_0_LOWPWR				S5P_PMUREG(0x10C0)
+#define S5P_L2_1_LOWPWR				S5P_PMUREG(0x10C4)
+#define S5P_CMU_ACLKSTOP_LOWPWR			S5P_PMUREG(0x1100)
+#define S5P_CMU_SCLKSTOP_LOWPWR			S5P_PMUREG(0x1104)
+#define S5P_CMU_RESET_LOWPWR			S5P_PMUREG(0x110C)
+#define S5P_APLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1120)
+#define S5P_MPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1124)
+#define S5P_VPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1128)
+#define S5P_EPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x112C)
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	S5P_PMUREG(0x1138)
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR		S5P_PMUREG(0x113C)
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR		S5P_PMUREG(0x1140)
+#define S5P_CMU_CLKSTOP_TV_LOWPWR		S5P_PMUREG(0x1144)
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR		S5P_PMUREG(0x1148)
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR		S5P_PMUREG(0x114C)
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		S5P_PMUREG(0x1150)
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		S5P_PMUREG(0x1158)
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR		S5P_PMUREG(0x115C)
+#define S5P_CMU_RESET_CAM_LOWPWR		S5P_PMUREG(0x1160)
+#define S5P_CMU_RESET_TV_LOWPWR			S5P_PMUREG(0x1164)
+#define S5P_CMU_RESET_MFC_LOWPWR		S5P_PMUREG(0x1168)
+#define S5P_CMU_RESET_G3D_LOWPWR		S5P_PMUREG(0x116C)
+#define S5P_CMU_RESET_LCD0_LOWPWR		S5P_PMUREG(0x1170)
+#define S5P_CMU_RESET_MAUDIO_LOWPWR		S5P_PMUREG(0x1178)
+#define S5P_CMU_RESET_GPS_LOWPWR		S5P_PMUREG(0x117C)
+#define S5P_TOP_BUS_LOWPWR			S5P_PMUREG(0x1180)
+#define S5P_TOP_RETENTION_LOWPWR		S5P_PMUREG(0x1184)
+#define S5P_TOP_PWR_LOWPWR			S5P_PMUREG(0x1188)
+#define S5P_LOGIC_RESET_LOWPWR			S5P_PMUREG(0x11A0)
+#define S5P_ONENAND_MEM_LOWPWR			S5P_PMUREG(0x11C0)
+#define S5P_G2D_ACP_MEM_LOWPWR			S5P_PMUREG(0x11C8)
+#define S5P_USBOTG_MEM_LOWPWR			S5P_PMUREG(0x11CC)
+#define S5P_HSMMC_MEM_LOWPWR			S5P_PMUREG(0x11D0)
+#define S5P_CSSYS_MEM_LOWPWR			S5P_PMUREG(0x11D4)
+#define S5P_SECSS_MEM_LOWPWR			S5P_PMUREG(0x11D8)
+#define S5P_PAD_RETENTION_DRAM_LOWPWR		S5P_PMUREG(0x1200)
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		S5P_PMUREG(0x1204)
+#define S5P_PAD_RETENTION_GPIO_LOWPWR		S5P_PMUREG(0x1220)
+#define S5P_PAD_RETENTION_UART_LOWPWR		S5P_PMUREG(0x1224)
+#define S5P_PAD_RETENTION_MMCA_LOWPWR		S5P_PMUREG(0x1228)
+#define S5P_PAD_RETENTION_MMCB_LOWPWR		S5P_PMUREG(0x122C)
+#define S5P_PAD_RETENTION_EBIA_LOWPWR		S5P_PMUREG(0x1230)
+#define S5P_PAD_RETENTION_EBIB_LOWPWR		S5P_PMUREG(0x1234)
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	S5P_PMUREG(0x1240)
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	S5P_PMUREG(0x1260)
+#define S5P_XUSBXTI_LOWPWR			S5P_PMUREG(0x1280)
+#define S5P_XXTI_LOWPWR				S5P_PMUREG(0x1284)
+#define S5P_EXT_REGULATOR_LOWPWR		S5P_PMUREG(0x12C0)
+#define S5P_GPIO_MODE_LOWPWR			S5P_PMUREG(0x1300)
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR		S5P_PMUREG(0x1340)
+#define S5P_CAM_LOWPWR				S5P_PMUREG(0x1380)
+#define S5P_TV_LOWPWR				S5P_PMUREG(0x1384)
+#define S5P_MFC_LOWPWR				S5P_PMUREG(0x1388)
+#define S5P_G3D_LOWPWR				S5P_PMUREG(0x138C)
+#define S5P_LCD0_LOWPWR				S5P_PMUREG(0x1390)
+#define S5P_MAUDIO_LOWPWR			S5P_PMUREG(0x1398)
+#define S5P_GPS_LOWPWR				S5P_PMUREG(0x139C)
+#define S5P_GPS_ALIVE_LOWPWR			S5P_PMUREG(0x13A0)
+
+#define S5P_ARM_CORE0_CONFIGURATION		S5P_PMUREG(0x2000)
+#define S5P_ARM_CORE0_OPTION			S5P_PMUREG(0x2008)
+#define S5P_ARM_CORE1_CONFIGURATION		S5P_PMUREG(0x2080)
+#define S5P_ARM_CORE1_STATUS			S5P_PMUREG(0x2084)
+#define S5P_ARM_CORE1_OPTION			S5P_PMUREG(0x2088)
+
+#define S5P_ARM_COMMON_OPTION			S5P_PMUREG(0x2408)
+#define S5P_TOP_PWR_OPTION			S5P_PMUREG(0x2C48)
+#define S5P_CAM_OPTION				S5P_PMUREG(0x3C08)
+#define S5P_TV_OPTION				S5P_PMUREG(0x3C28)
+#define S5P_MFC_OPTION				S5P_PMUREG(0x3C48)
+#define S5P_G3D_OPTION				S5P_PMUREG(0x3C68)
+#define S5P_LCD0_OPTION				S5P_PMUREG(0x3C88)
+#define S5P_LCD1_OPTION				S5P_PMUREG(0x3CA8)
+#define S5P_MAUDIO_OPTION			S5P_PMUREG(0x3CC8)
+#define S5P_GPS_OPTION				S5P_PMUREG(0x3CE8)
+#define S5P_GPS_ALIVE_OPTION			S5P_PMUREG(0x3D08)
+
+#define S5P_PAD_RET_MAUDIO_OPTION		S5P_PMUREG(0x3028)
+#define S5P_PAD_RET_GPIO_OPTION			S5P_PMUREG(0x3108)
+#define S5P_PAD_RET_UART_OPTION			S5P_PMUREG(0x3128)
+#define S5P_PAD_RET_MMCA_OPTION			S5P_PMUREG(0x3148)
+#define S5P_PAD_RET_MMCB_OPTION			S5P_PMUREG(0x3168)
+#define S5P_PAD_RET_EBIA_OPTION			S5P_PMUREG(0x3188)
+#define S5P_PAD_RET_EBIB_OPTION			S5P_PMUREG(0x31A8)
+
+#define S5P_PMU_CAM_CONF			S5P_PMUREG(0x3C00)
+#define S5P_PMU_TV_CONF				S5P_PMUREG(0x3C20)
+#define S5P_PMU_MFC_CONF			S5P_PMUREG(0x3C40)
+#define S5P_PMU_G3D_CONF			S5P_PMUREG(0x3C60)
+#define S5P_PMU_LCD0_CONF			S5P_PMUREG(0x3C80)
+#define S5P_PMU_GPS_CONF			S5P_PMUREG(0x3CE0)
+
+#define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
+#define S5P_CORE_LOCAL_PWR_EN			0x3
+#define S5P_INT_LOCAL_PWR_EN			0x7
+
+#define S5P_CHECK_SLEEP				0x00000BAD
+
+/* Only for EXYNOS4210 */
+#define S5P_USBHOST_PHY_CONTROL		S5P_PMUREG(0x0708)
+#define S5P_USBHOST_PHY_ENABLE		(1 << 0)
+
+#define S5P_PMU_SATA_PHY_CONTROL	S5P_PMUREG(0x0720)
+
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR	S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_LCD1_LOWPWR	S5P_PMUREG(0x1174)
+#define S5P_MODIMIF_MEM_LOWPWR		S5P_PMUREG(0x11C4)
+#define S5P_PCIE_MEM_LOWPWR		S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR		S5P_PMUREG(0x11E4)
+#define S5P_LCD1_LOWPWR			S5P_PMUREG(0x1394)
+
+#define S5P_PMU_LCD1_CONF		S5P_PMUREG(0x3CA0)
+
+/* Only for EXYNOS4212 */
+#define S5P_ISP_ARM_LOWPWR			S5P_PMUREG(0x1050)
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR	S5P_PMUREG(0x1054)
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR	S5P_PMUREG(0x1058)
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1110)
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1114)
+#define S5P_CMU_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x111C)
+#define S5P_MPLLUSER_SYSCLK_LOWPWR		S5P_PMUREG(0x1130)
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR		S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_ISP_LOWPWR		S5P_PMUREG(0x1174)
+#define S5P_TOP_BUS_COREBLK_LOWPWR		S5P_PMUREG(0x1190)
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR	S5P_PMUREG(0x1194)
+#define S5P_TOP_PWR_COREBLK_LOWPWR		S5P_PMUREG(0x1198)
+#define S5P_OSCCLK_GATE_LOWPWR			S5P_PMUREG(0x11A4)
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x11B0)
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR		S5P_PMUREG(0x11B4)
+#define S5P_HSI_MEM_LOWPWR			S5P_PMUREG(0x11C4)
+#define S5P_ROTATOR_MEM_LOWPWR			S5P_PMUREG(0x11DC)
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR	S5P_PMUREG(0x123C)
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR	S5P_PMUREG(0x1250)
+#define S5P_GPIO_MODE_COREBLK_LOWPWR		S5P_PMUREG(0x1320)
+#define S5P_TOP_ASB_RESET_LOWPWR		S5P_PMUREG(0x1344)
+#define S5P_TOP_ASB_ISOLATION_LOWPWR		S5P_PMUREG(0x1348)
+#define S5P_ISP_LOWPWR				S5P_PMUREG(0x1394)
+#define S5P_DRAM_FREQ_DOWN_LOWPWR		S5P_PMUREG(0x13B0)
+#define S5P_DDRPHY_DLLOFF_LOWPWR		S5P_PMUREG(0x13B4)
+#define S5P_CMU_SYSCLK_ISP_LOWPWR		S5P_PMUREG(0x13B8)
+#define S5P_CMU_SYSCLK_GPS_LOWPWR		S5P_PMUREG(0x13BC)
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR		S5P_PMUREG(0x13C0)
+
+#define S5P_ARM_L2_0_OPTION			S5P_PMUREG(0x2608)
+#define S5P_ARM_L2_1_OPTION			S5P_PMUREG(0x2628)
+#define S5P_ONENAND_MEM_OPTION			S5P_PMUREG(0x2E08)
+#define S5P_HSI_MEM_OPTION			S5P_PMUREG(0x2E28)
+#define S5P_G2D_ACP_MEM_OPTION			S5P_PMUREG(0x2E48)
+#define S5P_USBOTG_MEM_OPTION			S5P_PMUREG(0x2E68)
+#define S5P_HSMMC_MEM_OPTION			S5P_PMUREG(0x2E88)
+#define S5P_CSSYS_MEM_OPTION			S5P_PMUREG(0x2EA8)
+#define S5P_SECSS_MEM_OPTION			S5P_PMUREG(0x2EC8)
+#define S5P_ROTATOR_MEM_OPTION			S5P_PMUREG(0x2F48)
+
+#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-sysmmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU register
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SYSMMU_H
+#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
+
+#define S5P_MMU_CTRL			0x000
+#define S5P_MMU_CFG			0x004
+#define S5P_MMU_STATUS			0x008
+#define S5P_MMU_FLUSH			0x00C
+#define S5P_PT_BASE_ADDR		0x014
+#define S5P_INT_STATUS			0x018
+#define S5P_INT_CLEAR			0x01C
+#define S5P_PAGE_FAULT_ADDR		0x024
+#define S5P_AW_FAULT_ADDR		0x028
+#define S5P_AR_FAULT_ADDR		0x02C
+#define S5P_DEFAULT_SLAVE_ADDR		0x030
+
+#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-usb-phy.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-usb-phy.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/regs-usb-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/regs-usb-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_S5P_REGS_USB_PHY_H
+#define __PLAT_S5P_REGS_USB_PHY_H
+
+#define EXYNOS4_HSOTG_PHYREG(x)		((x) + S3C_VA_USB_HSPHY)
+
+#define EXYNOS4_PHYPWR			EXYNOS4_HSOTG_PHYREG(0x00)
+#define PHY1_HSIC_NORMAL_MASK		(0xf << 9)
+#define PHY1_HSIC1_SLEEP		(1 << 12)
+#define PHY1_HSIC1_FORCE_SUSPEND	(1 << 11)
+#define PHY1_HSIC0_SLEEP		(1 << 10)
+#define PHY1_HSIC0_FORCE_SUSPEND	(1 << 9)
+
+#define PHY1_STD_NORMAL_MASK		(0x7 << 6)
+#define PHY1_STD_SLEEP			(1 << 8)
+#define PHY1_STD_ANALOG_POWERDOWN	(1 << 7)
+#define PHY1_STD_FORCE_SUSPEND		(1 << 6)
+
+#define PHY0_NORMAL_MASK		(0x39 << 0)
+#define PHY0_SLEEP			(1 << 5)
+#define PHY0_OTG_DISABLE		(1 << 4)
+#define PHY0_ANALOG_POWERDOWN		(1 << 3)
+#define PHY0_FORCE_SUSPEND		(1 << 0)
+
+#define EXYNOS4_PHYCLK			EXYNOS4_HSOTG_PHYREG(0x04)
+#define PHY1_COMMON_ON_N		(1 << 7)
+#define PHY0_COMMON_ON_N		(1 << 4)
+#define PHY0_ID_PULLUP			(1 << 2)
+#define CLKSEL_MASK			(0x3 << 0)
+#define CLKSEL_SHIFT			(0)
+#define CLKSEL_48M			(0x0 << 0)
+#define CLKSEL_12M			(0x2 << 0)
+#define CLKSEL_24M			(0x3 << 0)
+
+#define EXYNOS4_RSTCON			EXYNOS4_HSOTG_PHYREG(0x08)
+#define HOST_LINK_PORT_SWRST_MASK	(0xf << 6)
+#define HOST_LINK_PORT2_SWRST		(1 << 9)
+#define HOST_LINK_PORT1_SWRST		(1 << 8)
+#define HOST_LINK_PORT0_SWRST		(1 << 7)
+#define HOST_LINK_ALL_SWRST		(1 << 6)
+
+#define PHY1_SWRST_MASK			(0x7 << 3)
+#define PHY1_HSIC_SWRST			(1 << 5)
+#define PHY1_STD_SWRST			(1 << 4)
+#define PHY1_ALL_SWRST			(1 << 3)
+
+#define PHY0_SWRST_MASK			(0x7 << 0)
+#define PHY0_PHYLINK_SWRST		(1 << 2)
+#define PHY0_HLINK_SWRST		(1 << 1)
+#define PHY0_SWRST			(1 << 0)
+
+#define EXYNOS4_PHY1CON			EXYNOS4_HSOTG_PHYREG(0x34)
+#define FPENABLEN			(1 << 0)
+
+#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/sysmmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung sysmmu driver for EXYNOS4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_SYSMMU_H
+#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
+
+enum exynos4_sysmmu_ips {
+	SYSMMU_MDMA,
+	SYSMMU_SSS,
+	SYSMMU_FIMC0,
+	SYSMMU_FIMC1,
+	SYSMMU_FIMC2,
+	SYSMMU_FIMC3,
+	SYSMMU_JPEG,
+	SYSMMU_FIMD0,
+	SYSMMU_FIMD1,
+	SYSMMU_PCIe,
+	SYSMMU_G2D,
+	SYSMMU_ROTATOR,
+	SYSMMU_MDMA2,
+	SYSMMU_TV,
+	SYSMMU_MFC_L,
+	SYSMMU_MFC_R,
+	EXYNOS4_SYSMMU_TOTAL_IPNUM,
+};
+
+#define S5P_SYSMMU_TOTAL_IPNUM		EXYNOS4_SYSMMU_TOTAL_IPNUM
+
+extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
+
+typedef enum exynos4_sysmmu_ips sysmmu_ips;
+
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
+void sysmmu_clk_enable(sysmmu_ips ips);
+void sysmmu_clk_disable(sysmmu_ips ips);
+
+#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/system.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - system support header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+#include <plat/system-reset.h>
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+#endif /* __ASM_ARCH_SYSTEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-exynos4/include/mach/timex.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * EXYNOS4 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H __FILE__
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H __FILE__
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+
+	/*
+	 * For preventing FIFO overrun or infinite loop of UART console,
+	 * fifo_max should be the minimum fifo size of all of the UART channels
+	 */
+	fifo_mask = S5PV210_UFSTAT_TXMASK;
+	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
+}
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
+ *
+ * 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.
+ *
+ * EXYNOS4 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H __FILE__
+
+#define VMALLOC_END	0xF6000000UL
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/init.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/init.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-exynos4/init.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->has_fracval = 1;
+			tcfg->clocks = exynos4_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
+		}
+		tcfg->flags |= NO_NEED_CHECK_CLKSRC;
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/irq-combiner.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/irq-combiner.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/irq-combiner.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,124 @@
+/* linux/arch/arm/mach-exynos4/irq-combiner.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/common/gic.c
+ *
+ * IRQ COMBINER support
+ *
+ * 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/io.h>
+
+#include <asm/mach/irq.h>
+
+#define COMBINER_ENABLE_SET	0x0
+#define COMBINER_ENABLE_CLEAR	0x4
+#define COMBINER_INT_STATUS	0xC
+
+static DEFINE_SPINLOCK(irq_controller_lock);
+
+struct combiner_chip_data {
+	unsigned int irq_offset;
+	unsigned int irq_mask;
+	void __iomem *base;
+};
+
+static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+
+static inline void __iomem *combiner_base(struct irq_data *data)
+{
+	struct combiner_chip_data *combiner_data =
+		irq_data_get_irq_chip_data(data);
+
+	return combiner_data->base;
+}
+
+static void combiner_mask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+}
+
+static void combiner_unmask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+}
+
+static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+	unsigned int cascade_irq, combiner_irq;
+	unsigned long status;
+
+	chained_irq_enter(chip, desc);
+
+	spin_lock(&irq_controller_lock);
+	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	spin_unlock(&irq_controller_lock);
+	status &= chip_data->irq_mask;
+
+	if (status == 0)
+		goto out;
+
+	combiner_irq = __ffs(status);
+
+	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
+	if (unlikely(cascade_irq >= NR_IRQS))
+		do_bad_IRQ(cascade_irq, desc);
+	else
+		generic_handle_irq(cascade_irq);
+
+ out:
+	chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip combiner_chip = {
+	.name		= "COMBINER",
+	.irq_mask	= combiner_mask_irq,
+	.irq_unmask	= combiner_unmask_irq,
+};
+
+void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+{
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+	if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
+		BUG();
+	irq_set_chained_handler(irq, combiner_handle_cascade_irq);
+}
+
+void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
+			  unsigned int irq_start)
+{
+	unsigned int i;
+
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+
+	combiner_data[combiner_nr].base = base;
+	combiner_data[combiner_nr].irq_offset = irq_start;
+	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+
+	/* Disable all interrupts */
+
+	__raw_writel(combiner_data[combiner_nr].irq_mask,
+		     base + COMBINER_ENABLE_CLEAR);
+
+	/* Setup the Linux IRQ subsystem */
+
+	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
+				+ MAX_IRQ_IN_COMBINER; i++) {
+		irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
+		irq_set_chip_data(i, &combiner_data[combiner_nr]);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/irq-eint.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/irq-eint.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/irq-eint.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,237 @@
+/* linux/arch/arm/mach-exynos4/irq-eint.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ EINT support
+ *
+ * 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+
+#include <plat/pm.h>
+#include <plat/cpu.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(eint_lock);
+
+static unsigned int eint0_15_data[16];
+
+static unsigned int exynos4_get_irq_nr(unsigned int number)
+{
+	u32 ret = 0;
+
+	switch (number) {
+	case 0 ... 3:
+		ret = (number + IRQ_EINT0);
+		break;
+	case 4 ... 7:
+		ret = (number + (IRQ_EINT4 - 4));
+		break;
+	case 8 ... 15:
+		ret = (number + (IRQ_EINT8 - 8));
+		break;
+	default:
+		printk(KERN_ERR "number available : %d\n", number);
+	}
+
+	return ret;
+}
+
+static inline void exynos4_irq_eint_mask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask |= eint_irq_to_bit(data->irq);
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static void exynos4_irq_eint_unmask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask &= ~(eint_irq_to_bit(data->irq));
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static inline void exynos4_irq_eint_ack(struct irq_data *data)
+{
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+}
+
+static void exynos4_irq_eint_maskack(struct irq_data *data)
+{
+	exynos4_irq_eint_mask(data);
+	exynos4_irq_eint_ack(data);
+}
+
+static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+	int offs = EINT_OFFSET(data->irq);
+	int shift;
+	u32 ctrl, mask;
+	u32 newvalue = 0;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
+		break;
+
+	default:
+		printk(KERN_ERR "No such irq type %d", type);
+		return -EINVAL;
+	}
+
+	shift = (offs & 0x7) * 4;
+	mask = 0x7 << shift;
+
+	spin_lock(&eint_lock);
+	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	ctrl &= ~mask;
+	ctrl |= newvalue << shift;
+	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+
+	switch (offs) {
+	case 0 ... 7:
+		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
+		break;
+	case 8 ... 15:
+		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
+		break;
+	case 16 ... 23:
+		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
+		break;
+	case 24 ... 31:
+		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
+		break;
+	default:
+		printk(KERN_ERR "No such irq number %d", offs);
+	}
+
+	return 0;
+}
+
+static struct irq_chip exynos4_irq_eint = {
+	.name		= "exynos4-eint",
+	.irq_mask	= exynos4_irq_eint_mask,
+	.irq_unmask	= exynos4_irq_eint_unmask,
+	.irq_mask_ack	= exynos4_irq_eint_maskack,
+	.irq_ack	= exynos4_irq_eint_ack,
+	.irq_set_type	= exynos4_irq_eint_set_type,
+#ifdef CONFIG_PM
+	.irq_set_wake	= s3c_irqext_wake,
+#endif
+};
+
+/* exynos4_irq_demux_eint
+ *
+ * This function demuxes the IRQ from from EINTs 16 to 31.
+ * It is designed to be inlined into the specific handler
+ * s5p_irq_demux_eintX_Y.
+ *
+ * Each EINT pend/mask registers handle eight of them.
+ */
+static inline void exynos4_irq_demux_eint(unsigned int start)
+{
+	unsigned int irq;
+
+	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
+	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
+
+	status &= ~mask;
+	status &= 0xff;
+
+	while (status) {
+		irq = fls(status) - 1;
+		generic_handle_irq(irq + start);
+		status &= ~(1 << irq);
+	}
+}
+
+static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	chained_irq_enter(chip, desc);
+	exynos4_irq_demux_eint(IRQ_EINT(16));
+	exynos4_irq_demux_eint(IRQ_EINT(24));
+	chained_irq_exit(chip, desc);
+}
+
+static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+{
+	u32 *irq_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chained_irq_enter(chip, desc);
+	chip->irq_mask(&desc->irq_data);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	generic_handle_irq(*irq_data);
+
+	chip->irq_unmask(&desc->irq_data);
+	chained_irq_exit(chip, desc);
+}
+
+int __init exynos4_init_irq_eint(void)
+{
+	int irq;
+
+	for (irq = 0 ; irq <= 31 ; irq++) {
+		irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
+					 handle_level_irq);
+		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+	}
+
+	irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+
+	for (irq = 0 ; irq <= 15 ; irq++) {
+		eint0_15_data[irq] = IRQ_EINT(irq);
+
+		irq_set_handler_data(exynos4_get_irq_nr(irq),
+				     &eint0_15_data[irq]);
+		irq_set_chained_handler(exynos4_get_irq_nr(irq),
+					exynos4_irq_eint0_15);
+	}
+
+	return 0;
+}
+
+arch_initcall(exynos4_init_irq_eint);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-exynos/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,349 @@
+# arch/arm/mach-exynos/Kconfig
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the EXYNOS4
+
+if ARCH_EXYNOS
+
+menu "SAMSUNG EXYNOS SoCs Support"
+
+choice
+	prompt "EXYNOS System Type"
+	default ARCH_EXYNOS4
+
+config ARCH_EXYNOS4
+	bool "SAMSUNG EXYNOS4"
+	help
+	  Samsung EXYNOS4 SoCs based systems
+
+endchoice
+
+comment "EXYNOS SoCs"
+
+config CPU_EXYNOS4210
+	bool "SAMSUNG EXYNOS4210"
+	default y
+	depends on ARCH_EXYNOS4
+	select SAMSUNG_DMADEV
+	select ARM_CPU_SUSPEND if PM
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
+	help
+	  Enable EXYNOS4210 CPU support
+
+config SOC_EXYNOS4212
+	bool "SAMSUNG EXYNOS4212"
+	default y
+	depends on ARCH_EXYNOS4
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
+	help
+	  Enable EXYNOS4212 SoC support
+
+config SOC_EXYNOS4412
+	bool "SAMSUNG EXYNOS4412"
+	default y
+	depends on ARCH_EXYNOS4
+	help
+	  Enable EXYNOS4412 SoC support
+
+config EXYNOS4_MCT
+	bool
+	default y
+	help
+	  Use MCT (Multi Core Timer) as kernel timers
+
+config EXYNOS4_DEV_AHCI
+	bool
+	help
+	  Compile in platform device definitions for AHCI
+
+config EXYNOS4_SETUP_FIMD0
+	bool
+	help
+	  Common setup code for FIMD0.
+
+config EXYNOS4_DEV_PD
+	bool
+	help
+	  Compile in platform device definitions for Power Domain
+
+config EXYNOS4_DEV_SYSMMU
+	bool
+	help
+	  Common setup code for SYSTEM MMU in EXYNOS4
+
+config EXYNOS4_DEV_DWMCI
+	bool
+	help
+	  Compile in platform device definitions for DWMCI
+
+config EXYNOS4_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+config EXYNOS4_SETUP_I2C2
+	bool
+	help
+	  Common setup code for i2c bus 2.
+
+config EXYNOS4_SETUP_I2C3
+	bool
+	help
+	  Common setup code for i2c bus 3.
+
+config EXYNOS4_SETUP_I2C4
+	bool
+	help
+	  Common setup code for i2c bus 4.
+
+config EXYNOS4_SETUP_I2C5
+	bool
+	help
+	  Common setup code for i2c bus 5.
+
+config EXYNOS4_SETUP_I2C6
+	bool
+	help
+	  Common setup code for i2c bus 6.
+
+config EXYNOS4_SETUP_I2C7
+	bool
+	help
+	  Common setup code for i2c bus 7.
+
+config EXYNOS4_SETUP_KEYPAD
+	bool
+	help
+	  Common setup code for keypad.
+
+config EXYNOS4_SETUP_SDHCI
+	bool
+	select EXYNOS4_SETUP_SDHCI_GPIO
+	help
+	  Internal helper functions for EXYNOS4 based SDHCI systems.
+
+config EXYNOS4_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for SDHCI gpio.
+
+config EXYNOS4_SETUP_FIMC
+	bool
+	help
+	  Common setup code for the camera interfaces.
+
+config EXYNOS4_SETUP_USB_PHY
+	bool
+	help
+	  Common setup code for USB PHY controller
+
+# machine support
+
+if ARCH_EXYNOS4
+
+comment "EXYNOS4210 Boards"
+
+config MACH_SMDKC210
+	bool "SMDKC210"
+	select MACH_SMDKV310
+	help
+	  Machine support for Samsung SMDKC210
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_TV
+	select S5P_DEV_USB_EHCI
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_BACKLIGHT
+	select EXYNOS4_DEV_AHCI
+	select SAMSUNG_DEV_KEYPAD
+	select EXYNOS4_DEV_PD
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	help
+	  Machine support for Samsung SMDKV310
+
+config MACH_ARMLEX4210
+	bool "ARMLEX4210"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select EXYNOS4_DEV_AHCI
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung ARMLEX4210 based on EXYNOS4210
+
+config MACH_UNIVERSAL_C210
+	bool "Mobile UNIVERSAL_C210 Board"
+	select CPU_EXYNOS4210
+	select S5P_GPIO_INT
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_CSIS0
+	select S5P_DEV_FIMD0
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C5
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_ONENAND
+	select S5P_DEV_TV
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_FIMC
+	select S5P_SETUP_MIPIPHY
+	help
+	  Machine support for Samsung Mobile Universal S5PC210 Reference
+	  Board.
+
+config MACH_NURI
+	bool "Mobile NURI Board"
+	select CPU_EXYNOS4210
+	select S5P_GPIO_INT
+	select S3C_DEV_WDT
+	select S3C_DEV_RTC
+	select S5P_DEV_FIMD0
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C5
+	select S5P_DEV_CSIS0
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_MFC
+	select S5P_DEV_USB_EHCI
+	select S5P_SETUP_MIPIPHY
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMC
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	select S5P_SETUP_MIPIPHY
+	select SAMSUNG_DEV_PWM
+	select SAMSUNG_DEV_ADC
+	help
+	  Machine support for Samsung Mobile NURI Board.
+
+config MACH_ORIGEN
+	bool "ORIGEN"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_FIMD0
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_TV
+	select S5P_DEV_USB_EHCI
+	select SAMSUNG_DEV_BACKLIGHT
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	help
+	  Machine support for ORIGEN based on Samsung EXYNOS4210
+
+comment "EXYNOS4212 Boards"
+
+config MACH_SMDK4212
+	bool "SMDK4212"
+	select SOC_EXYNOS4212
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C7
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select SAMSUNG_DEV_BACKLIGHT
+	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C7
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDK4212
+
+comment "EXYNOS4412 Boards"
+
+config MACH_SMDK4412
+	bool "SMDK4412"
+	select SOC_EXYNOS4412
+	select MACH_SMDK4212
+	help
+	  Machine support for Samsung SMDK4412
+endif
+
+if ARCH_EXYNOS4
+
+comment "Configuration for HSMMC 8-bit bus width"
+
+config EXYNOS4_SDHCI_CH0_8BIT
+	bool "Channel 0 with 8-bit bus"
+	help
+	  Support HSMMC Channel 0 8-bit bus.
+	  If selected, Channel 1 is disabled.
+
+config EXYNOS4_SDHCI_CH2_8BIT
+	bool "Channel 2 with 8-bit bus"
+	help
+	  Support HSMMC Channel 2 8-bit bus.
+	  If selected, Channel 3 is disabled.
+endif
+
+endmenu
+
+endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-armlex4210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-armlex4210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-armlex4210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-armlex4210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,215 @@
+/* linux/arch/arm/mach-exynos4/mach-armlex4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/smsc911x.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ARMLEX4210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ARMLEX4210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ARMLEX4210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPX2(5),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static void __init armlex4210_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&armlex4210_hsmmc0_pdata);
+	s3c_sdhci2_set_platdata(&armlex4210_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&armlex4210_hsmmc3_pdata);
+}
+
+static void __init armlex4210_wlan_init(void)
+{
+	/* enable */
+	s3c_gpio_cfgpin(EXYNOS4_GPX2(0), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX2(0), S3C_GPIO_PULL_UP);
+
+	/* reset */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(6), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(6), S3C_GPIO_PULL_UP);
+
+	/* wakeup */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(5), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(5), S3C_GPIO_PULL_UP);
+}
+
+static struct resource armlex4210_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(3),
+		.end	= EXYNOS4_PA_SROM_BANK(3) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(27),
+		.end	= IRQ_EINT(27),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device armlex4210_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(armlex4210_smsc911x_resources),
+	.resource	= armlex4210_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static struct platform_device *armlex4210_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&armlex4210_smsc911x,
+	&exynos4_device_ahci,
+};
+
+static void __init armlex4210_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(0 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__ADDRMODE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init armlex4210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(armlex4210_uartcfgs,
+			   ARRAY_SIZE(armlex4210_uartcfgs));
+}
+
+static void __init armlex4210_machine_init(void)
+{
+	armlex4210_smsc911x_init();
+
+	armlex4210_sdhci_init();
+
+	armlex4210_wlan_init();
+
+	platform_add_devices(armlex4210_devices,
+			     ARRAY_SIZE(armlex4210_devices));
+}
+
+MACHINE_START(ARMLEX4210, "ARMLEX4210")
+	/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= armlex4210_map_io,
+	.init_machine	= armlex4210_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-nuri.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-nuri.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-nuri.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-nuri.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1339 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-nuri.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * 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/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/i2c-gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/power/max8903_charger.h>
+#include <linux/power/max17042_battery.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+#include <linux/mmc/host.h>
+#include <linux/fb.h>
+#include <linux/pwm_backlight.h>
+
+#include <video/platform_lcd.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/adc.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/mfc.h>
+#include <plat/pd.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define NURI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define NURI_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define NURI_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC = 0,
+	FIXED_REG_ID_MAX8903,
+	FIXED_REG_ID_CAM_A28V,
+	FIXED_REG_ID_CAM_12V,
+};
+
+static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
+	{
+		.hwport		= 0,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 1,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 2,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 3,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE | MMC_CAP_ERASE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply emmc_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+	REGULATOR_SUPPLY("vmmc", "dw_mmc"),
+};
+
+static struct regulator_init_data emmc_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(emmc_supplies),
+	.consumer_supplies	= emmc_supplies,
+};
+
+static struct fixed_voltage_config emmc_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN (inverted)",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPL1(1),
+	.enable_high		= false,
+	.init_data		= &emmc_fixed_voltage_init_data,
+};
+
+static struct platform_device emmc_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_MMC,
+	.dev			= {
+		.platform_data	= &emmc_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(3),	/* XEINT_27 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WLAN */
+static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static void __init nuri_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&nuri_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&nuri_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&nuri_hsmmc3_data);
+}
+
+/* GPIO KEYS */
+static struct gpio_keys_button nuri_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_POWER,
+		.gpio			= EXYNOS4_GPX2(7),	/* XEINT23 */
+		.desc			= "gpio-keys: KEY_POWER",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data nuri_gpio_keys_data = {
+	.buttons		= nuri_gpio_keys_tables,
+	.nbuttons		= ARRAY_SIZE(nuri_gpio_keys_tables),
+};
+
+static struct platform_device nuri_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &nuri_gpio_keys_data,
+	},
+};
+
+/* Frame Buffer */
+static struct s3c_fb_pd_win nuri_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 64,
+		.right_margin	= 16,
+		.upper_margin	= 64,
+		.lower_margin	= 1,
+		.hsync_len	= 48,
+		.vsync_len	= 3,
+		.xres		= 1280,
+		.yres		= 800,
+		.refresh	= 60,
+	},
+	.max_bpp	= 24,
+	.default_bpp	= 16,
+	.virtual_x	= 1280,
+	.virtual_y	= 800,
+};
+
+static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
+	.win[0]		= &nuri_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+			  VIDCON0_CLKSEL_LCD,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
+{
+	int gpio = EXYNOS4_GPE1(5);
+
+	gpio_request(gpio, "LVDS_nSHDN");
+	gpio_direction_output(gpio, power);
+	gpio_free(gpio);
+}
+
+static int nuri_bl_init(struct device *dev)
+{
+	int ret, gpio = EXYNOS4_GPE2(3);
+
+	ret = gpio_request(gpio, "LCD_LDO_EN");
+	if (!ret)
+		gpio_direction_output(gpio, 0);
+
+	return ret;
+}
+
+static int nuri_bl_notify(struct device *dev, int brightness)
+{
+	if (brightness < 1)
+		brightness = 0;
+
+	gpio_set_value(EXYNOS4_GPE2(3), 1);
+
+	return brightness;
+}
+
+static void nuri_bl_exit(struct device *dev)
+{
+	gpio_free(EXYNOS4_GPE2(3));
+}
+
+/* nuri pwm backlight */
+static struct platform_pwm_backlight_data nuri_backlight_data = {
+	.pwm_id			= 0,
+	.pwm_period_ns		= 30000,
+	.max_brightness		= 100,
+	.dft_brightness		= 50,
+	.init			= nuri_bl_init,
+	.notify			= nuri_bl_notify,
+	.exit			= nuri_bl_exit,
+};
+
+static struct platform_device nuri_backlight_device = {
+	.name			= "pwm-backlight",
+	.id			= -1,
+	.dev			= {
+		.parent		= &s3c_device_timer[0].dev,
+		.platform_data	= &nuri_backlight_data,
+	},
+};
+
+static struct plat_lcd_data nuri_lcd_platform_data = {
+	.set_power		= nuri_lcd_power_on,
+};
+
+static struct platform_device nuri_lcd_device = {
+	.name			= "platform-lcd",
+	.id			= -1,
+	.dev			= {
+		.platform_data	= &nuri_lcd_platform_data,
+	},
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+/* TSP */
+static u8 mxt_init_vals[] = {
+	/* MXT_GEN_COMMAND(6) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_GEN_POWER(7) */
+	0x20, 0xff, 0x32,
+	/* MXT_GEN_ACQUIRE(8) */
+	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
+	/* MXT_TOUCH_MULTI(9) */
+	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00,
+	/* MXT_TOUCH_KEYARRAY(15) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00,
+	/* MXT_SPT_GPIOPWM(19) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_GRIPFACE(20) */
+	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
+	0x0f, 0x0a,
+	/* MXT_PROCG_NOISE(22) */
+	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
+	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
+	/* MXT_TOUCH_PROXIMITY(23) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_ONETOUCH(24) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_SPT_SELFTEST(25) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_TWOTOUCH(27) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_SPT_CTECONFIG(28) */
+	0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+	.config			= mxt_init_vals,
+	.config_length		= ARRAY_SIZE(mxt_init_vals),
+
+	.x_line			= 18,
+	.y_line			= 11,
+	.x_size			= 1024,
+	.y_size			= 600,
+	.blen			= 0x1,
+	.threshold		= 0x28,
+	.voltage		= 2800000,		/* 2.8V */
+	.orient			= MXT_DIAGONAL_COUNTER,
+	.irqflags		= IRQF_TRIGGER_FALLING,
+};
+
+static struct s3c2410_platform_i2c i2c3_data __initdata = {
+	.flags		= 0,
+	.bus_num	= 3,
+	.slave_addr	= 0x10,
+	.frequency	= 400 * 1000,
+	.sda_delay	= 100,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
+		.platform_data	= &mxt_platform_data,
+		.irq		= IRQ_EINT(4),
+	},
+};
+
+static void __init nuri_tsp_init(void)
+{
+	int gpio;
+
+	/* TOUCH_INT: XEINT_4 */
+	gpio = EXYNOS4_GPX0(4);
+	gpio_request(gpio, "TOUCH_INT");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+}
+
+static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
+	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
+	REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
+	REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
+	REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+	REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
+	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
+	REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
+	REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
+};
+static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
+	REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
+	REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
+	REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
+	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
+	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
+	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
+	REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
+	REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
+	REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
+	REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
+};
+
+static struct regulator_consumer_supply __initdata max8997_charger_[] = {
+	REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
+};
+static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
+	REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
+};
+
+static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
+	REGULATOR_SUPPLY("gps_clk", "bcm4751"),
+	REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
+	REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo1_),
+	.consumer_supplies	= max8997_ldo1_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo3_),
+	.consumer_supplies	= max8997_ldo3_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo4_),
+	.consumer_supplies	= max8997_ldo4_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo5_data = {
+	.constraints	= {
+		.name		= "VHSIC_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo5_),
+	.consumer_supplies	= max8997_ldo5_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V_PDA",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo7_),
+	.consumer_supplies	= max8997_ldo7_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB/VDAC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo8_),
+	.consumer_supplies	= max8997_ldo8_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V_PDA",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+	.constraints	= {
+		.name		= "LVDS_VDD3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo11_),
+	.consumer_supplies	= max8997_ldo11_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo12_data = {
+	.constraints	= {
+		.name		= "VT_CAM_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo12_),
+	.consumer_supplies	= max8997_ldo12_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo13_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo13_),
+	.consumer_supplies	= max8997_ldo13_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_MOTOR",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo14_),
+	.consumer_supplies	= max8997_ldo14_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo15_data = {
+	.constraints	= {
+		.name		= "VTOUCH_ADVV2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo15_),
+	.consumer_supplies	= max8997_ldo15_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_SENSOR_IO_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo16_),
+	.consumer_supplies	= max8997_ldo16_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo18_data = {
+	.constraints	= {
+		.name		= "VTOUCH_VDD2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo18_),
+	.consumer_supplies	= max8997_ldo18_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+	.constraints	= {
+		.name		= "VDDQ_M1M2_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VARM_1.2V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1350000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
+	.consumer_supplies = max8997_buck1_,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
+	.consumer_supplies = max8997_buck2_,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
+	.consumer_supplies = max8997_buck3_,
+};
+
+static struct regulator_init_data __initdata max8997_buck4_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
+	.consumer_supplies = max8997_buck4_,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck6_data = {
+	.constraints	= {
+		.name		= "CAM_AF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
+	.consumer_supplies = max8997_buck6_,
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+	.constraints	= {
+		.name		= "VCC_SUB_2.0V",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
+	.consumer_supplies = max8997_32khz_ap_,
+};
+
+static struct regulator_init_data __initdata max8997_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout1_),
+	.consumer_supplies	= max8997_esafeout1_,
+};
+
+static struct regulator_init_data __initdata max8997_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout2_),
+	.consumer_supplies	= max8997_esafeout2_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_cv_data = {
+	.constraints	= {
+		.name		= "CHARGER_CV",
+		.min_uV		= 4200000,
+		.max_uV		= 4200000,
+		.apply_uV	= 1,
+	},
+};
+
+static struct regulator_init_data __initdata max8997_charger_data = {
+	.constraints	= {
+		.name		= "CHARGER",
+		.min_uA		= 200000,
+		.max_uA		= 950000,
+		.boot_on	= 1,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+				REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_charger_),
+	.consumer_supplies	= max8997_charger_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_topoff_data = {
+	.constraints	= {
+		.name		= "CHARGER TOPOFF",
+		.min_uA		= 50000,
+		.max_uA		= 200000,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_chg_toff_),
+	.consumer_supplies	= max8997_chg_toff_,
+};
+
+static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
+	{ MAX8997_LDO1, &max8997_ldo1_data },
+	{ MAX8997_LDO2, &max8997_ldo2_data },
+	{ MAX8997_LDO3, &max8997_ldo3_data },
+	{ MAX8997_LDO4, &max8997_ldo4_data },
+	{ MAX8997_LDO5, &max8997_ldo5_data },
+	{ MAX8997_LDO6, &max8997_ldo6_data },
+	{ MAX8997_LDO7, &max8997_ldo7_data },
+	{ MAX8997_LDO8, &max8997_ldo8_data },
+	{ MAX8997_LDO9, &max8997_ldo9_data },
+	{ MAX8997_LDO10, &max8997_ldo10_data },
+	{ MAX8997_LDO11, &max8997_ldo11_data },
+	{ MAX8997_LDO12, &max8997_ldo12_data },
+	{ MAX8997_LDO13, &max8997_ldo13_data },
+	{ MAX8997_LDO14, &max8997_ldo14_data },
+	{ MAX8997_LDO15, &max8997_ldo15_data },
+	{ MAX8997_LDO16, &max8997_ldo16_data },
+
+	{ MAX8997_LDO18, &max8997_ldo18_data },
+	{ MAX8997_LDO21, &max8997_ldo21_data },
+
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+	{ MAX8997_BUCK4, &max8997_buck4_data },
+	{ MAX8997_BUCK5, &max8997_buck5_data },
+	{ MAX8997_BUCK6, &max8997_buck6_data },
+	{ MAX8997_BUCK7, &max8997_buck7_data },
+
+	{ MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
+	{ MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
+
+	{ MAX8997_ENVICHG, &max8997_vichg_data },
+	{ MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
+	{ MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
+	{ MAX8997_CHARGER_CV, &max8997_charger_cv_data },
+	{ MAX8997_CHARGER, &max8997_charger_data },
+	{ MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
+};
+
+static struct max8997_platform_data __initdata nuri_max8997_pdata = {
+	.wakeup			= 1,
+
+	.num_regulators		= ARRAY_SIZE(nuri_max8997_regulators),
+	.regulators		= nuri_max8997_regulators,
+
+	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
+	.buck2_gpiodvs = true,
+
+	.buck1_voltage[0] = 1350000, /* 1.35V */
+	.buck1_voltage[1] = 1300000, /* 1.3V */
+	.buck1_voltage[2] = 1250000, /* 1.25V */
+	.buck1_voltage[3] = 1200000, /* 1.2V */
+	.buck1_voltage[4] = 1150000, /* 1.15V */
+	.buck1_voltage[5] = 1100000, /* 1.1V */
+	.buck1_voltage[6] = 1000000, /* 1.0V */
+	.buck1_voltage[7] = 950000, /* 0.95V */
+
+	.buck2_voltage[0] = 1100000, /* 1.1V */
+	.buck2_voltage[1] = 1000000, /* 1.0V */
+	.buck2_voltage[2] = 950000, /* 0.95V */
+	.buck2_voltage[3] = 900000, /* 0.9V */
+	.buck2_voltage[4] = 1100000, /* 1.1V */
+	.buck2_voltage[5] = 1000000, /* 1.0V */
+	.buck2_voltage[6] = 950000, /* 0.95V */
+	.buck2_voltage[7] = 900000, /* 0.9V */
+
+	.buck5_voltage[0] = 1200000, /* 1.2V */
+	.buck5_voltage[1] = 1200000, /* 1.2V */
+	.buck5_voltage[2] = 1200000, /* 1.2V */
+	.buck5_voltage[3] = 1200000, /* 1.2V */
+	.buck5_voltage[4] = 1200000, /* 1.2V */
+	.buck5_voltage[5] = 1200000, /* 1.2V */
+	.buck5_voltage[6] = 1200000, /* 1.2V */
+	.buck5_voltage[7] = 1200000, /* 1.2V */
+};
+
+/* GPIO I2C 5 (PMIC) */
+enum { I2C5_MAX8997 };
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	[I2C5_MAX8997] = {
+		I2C_BOARD_INFO("max8997", 0xCC >> 1),
+		.platform_data	= &nuri_max8997_pdata,
+	},
+};
+
+static struct max17042_platform_data nuri_battery_platform_data = {
+};
+
+/* GPIO I2C 9 (Fuel Gauge) */
+static struct i2c_gpio_platform_data i2c9_gpio_data = {
+	.sda_pin		= EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
+	.scl_pin		= EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
+};
+static struct platform_device i2c9_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 9,
+	.dev			= {
+		.platform_data	= &i2c9_gpio_data,
+	},
+};
+enum { I2C9_MAX17042};
+static struct i2c_board_info i2c9_devs[] __initdata = {
+	[I2C9_MAX17042] = {
+		I2C_BOARD_INFO("max17042", 0x36),
+		.platform_data = &nuri_battery_platform_data,
+	},
+};
+
+/* MAX8903 Secondary Charger */
+static struct regulator_consumer_supply supplies_max8903[] = {
+	REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
+};
+
+static struct regulator_init_data max8903_charger_en_data = {
+	.constraints = {
+		.name		= "VOUT_CHARGER",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
+	.consumer_supplies = supplies_max8903,
+};
+
+static struct fixed_voltage_config max8903_charger_en = {
+	.supply_name = "VOUT_CHARGER",
+	.microvolts = 5000000, /* Assume 5VDC */
+	.gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
+	.enable_high = 0, /* Enable = Low */
+	.enabled_at_boot = 1,
+	.init_data = &max8903_charger_en_data,
+};
+
+static struct platform_device max8903_fixed_reg_dev = {
+	.name = "reg-fixed-voltage",
+	.id = FIXED_REG_ID_MAX8903,
+	.dev = { .platform_data	= &max8903_charger_en },
+};
+
+static struct max8903_pdata nuri_max8903 = {
+	/*
+	 * cen: don't control with the driver, let it be
+	 * controlled by regulator above
+	 */
+	.dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
+	/* uok, usus: not connected */
+	.chg = EXYNOS4_GPE2(0), /* TA_nCHG */
+	/* flt: vcc_1.8V_pda */
+	.dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
+
+	.dc_valid = true,
+	.usb_valid = false, /* USB is not wired to MAX8903 */
+};
+
+static struct platform_device nuri_max8903_device = {
+	.name			= "max8903-charger",
+	.dev			= {
+		.platform_data	= &nuri_max8903,
+	},
+};
+
+static void __init nuri_power_init(void)
+{
+	int gpio;
+	int irq_base = IRQ_GPIO_END + 1;
+	int ta_en = 0;
+
+	nuri_max8997_pdata.irq_base = irq_base;
+	irq_base += MAX8997_IRQ_NR;
+
+	gpio = EXYNOS4_GPX0(7);
+	gpio_request(gpio, "AP_PMIC_IRQ");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = EXYNOS4_GPX2(3);
+	gpio_request(gpio, "FUEL_ALERT");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = nuri_max8903.dok;
+	gpio_request(gpio, "TA_nCONNECTED");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	ta_en = gpio_get_value(gpio) ? 0 : 1;
+
+	gpio = nuri_max8903.chg;
+	gpio_request(gpio, "TA_nCHG");
+	gpio_direction_input(gpio);
+
+	gpio = nuri_max8903.dcm;
+	gpio_request(gpio, "CURR_ADJ");
+	gpio_direction_output(gpio, ta_en);
+}
+
+/* USB EHCI */
+static struct s5p_ehci_platdata nuri_ehci_pdata;
+
+static void __init nuri_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+/* CAMERA */
+static struct regulator_consumer_supply cam_vdda_supply[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data cam_vdda_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = ARRAY_SIZE(cam_vdda_supply),
+	.consumer_supplies = cam_vdda_supply,
+};
+
+static struct fixed_voltage_config cam_vdda_fixed_voltage_cfg = {
+	.supply_name	= "CAM_IO_EN",
+	.microvolts	= 2800000,
+	.gpio		= EXYNOS4_GPE2(1), /* CAM_IO_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_vdda_reg_init_data,
+};
+
+static struct platform_device cam_vdda_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_A28V,
+	.dev = { .platform_data	= &cam_vdda_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply camera_8m_12v_supply =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data cam_8m_12v_reg_init_data = {
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &camera_8m_12v_supply,
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS
+	},
+};
+
+static struct fixed_voltage_config cam_8m_12v_fixed_voltage_cfg = {
+	.supply_name	= "8M_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(5), /* 8M_1.2V_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_8m_12v_reg_init_data,
+};
+
+static struct platform_device cam_8m_12v_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_12V,
+	.dev = { .platform_data = &cam_8m_12v_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+	.clk_rate	= 166000000UL,
+	.lanes		= 2,
+	.alignment	= 32,
+	.hs_settle	= 12,
+	.phy_enable	= s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_MEGA_RST	EXYNOS4_GPY3(7) /* ISP_RESET */
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPL2(5)
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset = GPIO_CAM_MEGA_RST,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data	= &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
+	{
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.clk_frequency	= 24000000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= nuri_camera_sensors,
+	.num_clients	= ARRAY_SIZE(nuri_camera_sensors),
+};
+
+static struct gpio nuri_camera_gpios[] = {
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,           "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_RST,	GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
+};
+
+static void nuri_camera_init(void)
+{
+	s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+			 &s5p_device_mipi_csis0);
+	s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	if (gpio_request_array(nuri_camera_gpios,
+			       ARRAY_SIZE(nuri_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
+	if (!IS_ERR_VALUE(m5mols_board_info.irq))
+		s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
+	else
+		pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_RST);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+		pr_err("%s: Camera port A setup failed\n", __func__);
+		return;
+	}
+	/* Increase drive strength of the sensor clock output */
+	s5p_gpio_set_drvstr(EXYNOS4_GPJ1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
+static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
+	.frequency	= 400000U,
+	.sda_delay	= 200,
+};
+
+static struct platform_device *nuri_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&s3c_device_i2c5, /* PMIC should initialize first */
+	&s3c_device_i2c0,
+	&emmc_fixed_voltage,
+	&s5p_device_mipi_csis0,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&s5p_device_fimd0,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_wdt,
+	&s3c_device_timer[0],
+	&s5p_device_ehci,
+	&s3c_device_i2c3,
+	&i2c9_gpio,
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&s5p_device_fimc_md,
+
+	/* NURI Devices */
+	&nuri_gpio_keys,
+	&nuri_lcd_device,
+	&nuri_backlight_device,
+	&max8903_fixed_reg_dev,
+	&nuri_max8903_device,
+	&cam_vdda_fixed_rdev,
+	&cam_8m_12v_fixed_rdev,
+};
+
+static void __init nuri_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
+}
+
+static void __init nuri_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init nuri_machine_init(void)
+{
+	nuri_sdhci_init();
+	nuri_tsp_init();
+	nuri_power_init();
+
+	s3c_i2c0_set_platdata(&nuri_i2c0_platdata);
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+	s3c_i2c3_set_platdata(&i2c3_data);
+	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+	s3c_i2c5_set_platdata(NULL);
+	i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+	i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
+	i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
+
+	s5p_fimd0_set_platdata(&nuri_fb_pdata);
+
+	nuri_camera_init();
+
+	nuri_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	/* Last */
+	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+}
+
+MACHINE_START(NURI, "NURI")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= nuri_map_io,
+	.init_machine	= nuri_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve        = &nuri_reserve,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-origen.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-origen.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-origen.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-origen.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,700 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ *		http://www.insignal.co.kr/
+ *
+ * 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/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/pd.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+};
+
+static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
+	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
+	REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
+	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
+	REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
+	REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
+	REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
+	REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
+	REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata buck1_consumer[] = {
+	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck2_consumer[] = {
+	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck3_consumer[] = {
+	REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
+};
+static struct regulator_consumer_supply __initdata buck7_consumer[] = {
+	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+	.constraints	= {
+		.name		= "VDD_ABB_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data	= {
+	.constraints	= {
+		.name		= "VDD_ALIVE_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo3_consumer),
+	.consumer_supplies	= ldo3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+	.constraints	= {
+		.name		= "VDD_RTC_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo6_consumer),
+	.consumer_supplies	= ldo6_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+	.constraints	= {
+		.name		= "VDD_AUD_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo7_consumer),
+	.consumer_supplies	= ldo7_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo8_consumer),
+	.consumer_supplies	= ldo8_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+	.constraints	= {
+		.name		= "DVDD_SWB_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo9_consumer),
+	.consumer_supplies	= ldo9_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+	.constraints	= {
+		.name		= "VDD_PLL_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+	.constraints	= {
+		.name		= "VDD_AUD_3V",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo11_consumer),
+	.consumer_supplies	= ldo11_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+	.constraints	= {
+		.name		= "AVDD18_SWB_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo14_consumer),
+	.consumer_supplies	= ldo14_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo17_data = {
+	.constraints	= {
+		.name		= "VDD_SWB_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo17_consumer),
+	.consumer_supplies	= ldo17_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+	.constraints	= {
+		.name		= "VDD_MIF_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VDD_ARM_1.2V",
+		.min_uV		= 950000,
+		.max_uV		= 1350000,
+		.always_on	= 1,
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
+	.consumer_supplies	= buck1_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VDD_INT_1.1V",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.always_on	= 1,
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
+	.consumer_supplies	= buck2_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VDD_G3D_1.1V",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+					REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck3_consumer),
+	.consumer_supplies	= buck3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+	.constraints	= {
+		.name		= "VDDQ_M1M2_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+	.constraints	= {
+		.name		= "VDD_LCD_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.boot_on	= 1,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck7_consumer),
+	.consumer_supplies	= buck7_consumer,
+};
+
+static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
+	{ MAX8997_LDO1,		&max8997_ldo1_data },
+	{ MAX8997_LDO2,		&max8997_ldo2_data },
+	{ MAX8997_LDO3,		&max8997_ldo3_data },
+	{ MAX8997_LDO4,		&max8997_ldo4_data },
+	{ MAX8997_LDO6,		&max8997_ldo6_data },
+	{ MAX8997_LDO7,		&max8997_ldo7_data },
+	{ MAX8997_LDO8,		&max8997_ldo8_data },
+	{ MAX8997_LDO9,		&max8997_ldo9_data },
+	{ MAX8997_LDO10,	&max8997_ldo10_data },
+	{ MAX8997_LDO11,	&max8997_ldo11_data },
+	{ MAX8997_LDO14,	&max8997_ldo14_data },
+	{ MAX8997_LDO17,	&max8997_ldo17_data },
+	{ MAX8997_LDO21,	&max8997_ldo21_data },
+	{ MAX8997_BUCK1,	&max8997_buck1_data },
+	{ MAX8997_BUCK2,	&max8997_buck2_data },
+	{ MAX8997_BUCK3,	&max8997_buck3_data },
+	{ MAX8997_BUCK5,	&max8997_buck5_data },
+	{ MAX8997_BUCK7,	&max8997_buck7_data },
+};
+
+struct max8997_platform_data __initdata origen_max8997_pdata = {
+	.num_regulators = ARRAY_SIZE(origen_max8997_regulators),
+	.regulators	= origen_max8997_regulators,
+
+	.wakeup	= true,
+	.buck1_gpiodvs	= false,
+	.buck2_gpiodvs	= false,
+	.buck5_gpiodvs	= false,
+	.irq_base	= IRQ_GPIO_END + 1,
+
+	.ignore_gpiodvs_side_effect = true,
+	.buck125_default_idx = 0x0,
+
+	.buck125_gpios[0]	= EXYNOS4_GPX0(0),
+	.buck125_gpios[1]	= EXYNOS4_GPX0(1),
+	.buck125_gpios[2]	= EXYNOS4_GPX0(2),
+
+	.buck1_voltage[0]	= 1350000,
+	.buck1_voltage[1]	= 1300000,
+	.buck1_voltage[2]	= 1250000,
+	.buck1_voltage[3]	= 1200000,
+	.buck1_voltage[4]	= 1150000,
+	.buck1_voltage[5]	= 1100000,
+	.buck1_voltage[6]	= 1000000,
+	.buck1_voltage[7]	= 950000,
+
+	.buck2_voltage[0]	= 1100000,
+	.buck2_voltage[1]	= 1100000,
+	.buck2_voltage[2]	= 1100000,
+	.buck2_voltage[3]	= 1100000,
+	.buck2_voltage[4]	= 1000000,
+	.buck2_voltage[5]	= 1000000,
+	.buck2_voltage[6]	= 1000000,
+	.buck2_voltage[7]	= 1000000,
+
+	.buck5_voltage[0]	= 1200000,
+	.buck5_voltage[1]	= 1200000,
+	.buck5_voltage[2]	= 1200000,
+	.buck5_voltage[3]	= 1200000,
+	.buck5_voltage[4]	= 1200000,
+	.buck5_voltage[5]	= 1200000,
+	.buck5_voltage[6]	= 1200000,
+	.buck5_voltage[7]	= 1200000,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8997", (0xCC >> 1)),
+		.platform_data	= &origen_max8997_pdata,
+		.irq		= IRQ_EINT(4),
+	},
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata origen_ehci_pdata;
+
+static void __init origen_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+static struct gpio_keys_button origen_gpio_keys_table[] = {
+	{
+		.code			= KEY_MENU,
+		.gpio			= EXYNOS4_GPX1(5),
+		.desc			= "gpio-keys: KEY_MENU",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_HOME,
+		.gpio			= EXYNOS4_GPX1(6),
+		.desc			= "gpio-keys: KEY_HOME",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_BACK,
+		.gpio			= EXYNOS4_GPX1(7),
+		.desc			= "gpio-keys: KEY_BACK",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_UP,
+		.gpio			= EXYNOS4_GPX2(0),
+		.desc			= "gpio-keys: KEY_UP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_DOWN,
+		.gpio			= EXYNOS4_GPX2(1),
+		.desc			= "gpio-keys: KEY_DOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data origen_gpio_keys_data = {
+	.buttons	= origen_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(origen_gpio_keys_table),
+};
+
+static struct platform_device origen_device_gpiokeys = {
+	.name		= "gpio-keys",
+	.dev		= {
+		.platform_data	= &origen_gpio_keys_data,
+	},
+};
+
+static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
+{
+	int ret;
+
+	if (power)
+		ret = gpio_request_one(EXYNOS4_GPE3(4),
+					GPIOF_OUT_INIT_HIGH, "GPE3_4");
+	else
+		ret = gpio_request_one(EXYNOS4_GPE3(4),
+					GPIOF_OUT_INIT_LOW, "GPE3_4");
+
+	gpio_free(EXYNOS4_GPE3(4));
+
+	if (ret)
+		pr_err("failed to request gpio for LCD power: %d\n", ret);
+}
+
+static struct plat_lcd_data origen_lcd_hv070wsa_data = {
+	.set_power = lcd_hv070wsa_set_power,
+};
+
+static struct platform_device origen_lcd_hv070wsa = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &origen_lcd_hv070wsa_data,
+};
+
+static struct s3c_fb_pd_win origen_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 64,
+		.right_margin	= 16,
+		.upper_margin	= 64,
+		.lower_margin	= 16,
+		.hsync_len	= 48,
+		.vsync_len	= 3,
+		.xres		= 1024,
+		.yres		= 600,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
+	.win[0]		= &origen_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct platform_device *origen_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc0,
+	&s3c_device_i2c0,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&s5p_device_ehci,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&s5p_device_fimd0,
+	&s5p_device_hdmi,
+	&s5p_device_i2c_hdmiphy,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&s5p_device_mixer,
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_pd[PD_MFC],
+	&origen_device_gpiokeys,
+	&origen_lcd_hv070wsa,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+	.no		= EXYNOS4_GPD0(0),
+	.func		= S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+	.pwm_id		= 0,
+	.pwm_period_ns	= 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+	/* Direct HPD to HDMI chip */
+	gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_power_init(void)
+{
+	gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
+	s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init origen_machine_init(void)
+{
+	origen_power_init();
+
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+
+	/*
+	 * Since sdhci instance 2 can contain a bootable media,
+	 * sdhci instance 0 is registered after instance 2.
+	 */
+	s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+	s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+
+	origen_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	s5p_tv_setup();
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+
+	s5p_fimd0_set_platdata(&origen_lcd_pdata);
+
+	platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+
+	samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+	/* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= origen_map_io,
+	.init_machine	= origen_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve	= &origen_reserve,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-smdk4x12.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-smdk4x12.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-smdk4x12.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-smdk4x12.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,302 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-smdk4x12.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/machine.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/backlight.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/regs-serial.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDK4X12_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK4X12_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDK4X12_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply max8997_buck1 =
+	REGULATOR_SUPPLY("vdd_arm", NULL);
+
+static struct regulator_consumer_supply max8997_buck2 =
+	REGULATOR_SUPPLY("vdd_int", NULL);
+
+static struct regulator_consumer_supply max8997_buck3 =
+	REGULATOR_SUPPLY("vdd_g3d", NULL);
+
+static struct regulator_init_data max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VDD_ARM_SMDK4X12",
+		.min_uV		= 925000,
+		.max_uV		= 1350000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck1,
+};
+
+static struct regulator_init_data max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VDD_INT_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck2,
+};
+
+static struct regulator_init_data max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VDD_G3D_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck3,
+};
+
+static struct max8997_regulator_data smdk4x12_max8997_regulators[] = {
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+};
+
+static struct max8997_platform_data smdk4x12_max8997_pdata = {
+	.num_regulators	= ARRAY_SIZE(smdk4x12_max8997_regulators),
+	.regulators	= smdk4x12_max8997_regulators,
+
+	.buck1_voltage[0] = 1100000,	/* 1.1V */
+	.buck1_voltage[1] = 1100000,	/* 1.1V */
+	.buck1_voltage[2] = 1100000,	/* 1.1V */
+	.buck1_voltage[3] = 1100000,	/* 1.1V */
+	.buck1_voltage[4] = 1100000,	/* 1.1V */
+	.buck1_voltage[5] = 1100000,	/* 1.1V */
+	.buck1_voltage[6] = 1000000,	/* 1.0V */
+	.buck1_voltage[7] = 950000,	/* 0.95V */
+
+	.buck2_voltage[0] = 1100000,	/* 1.1V */
+	.buck2_voltage[1] = 1000000,	/* 1.0V */
+	.buck2_voltage[2] = 950000,	/* 0.95V */
+	.buck2_voltage[3] = 900000,	/* 0.9V */
+	.buck2_voltage[4] = 1100000,	/* 1.1V */
+	.buck2_voltage[5] = 1000000,	/* 1.0V */
+	.buck2_voltage[6] = 950000,	/* 0.95V */
+	.buck2_voltage[7] = 900000,	/* 0.9V */
+
+	.buck5_voltage[0] = 1100000,	/* 1.1V */
+	.buck5_voltage[1] = 1100000,	/* 1.1V */
+	.buck5_voltage[2] = 1100000,	/* 1.1V */
+	.buck5_voltage[3] = 1100000,	/* 1.1V */
+	.buck5_voltage[4] = 1100000,	/* 1.1V */
+	.buck5_voltage[5] = 1100000,	/* 1.1V */
+	.buck5_voltage[6] = 1100000,	/* 1.1V */
+	.buck5_voltage[7] = 1100000,	/* 1.1V */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs0[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8997", 0x66),
+		.platform_data	= &smdk4x12_max8997_pdata,
+	}
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("wm8994", 0x1a), }
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs7[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk4x12_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
+static uint32_t smdk4x12_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
+	KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+};
+
+static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
+	.keymap		= smdk4x12_keymap,
+	.keymap_size	= ARRAY_SIZE(smdk4x12_keymap),
+};
+
+static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
+	.keymap_data	= &smdk4x12_keymap_data,
+	.rows		= 2,
+	.cols		= 5,
+};
+
+static struct platform_device *smdk4x12_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_i2c3,
+	&s3c_device_i2c7,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&samsung_device_keypad,
+};
+
+static void __init smdk4x12_map_io(void)
+{
+	clk_xusbxti.rate = 24000000;
+
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(clk_xusbxti.rate);
+	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
+}
+
+static void __init smdk4x12_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, smdk4x12_i2c_devs0,
+				ARRAY_SIZE(smdk4x12_i2c_devs0));
+
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, smdk4x12_i2c_devs1,
+				ARRAY_SIZE(smdk4x12_i2c_devs1));
+
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, smdk4x12_i2c_devs3,
+				ARRAY_SIZE(smdk4x12_i2c_devs3));
+
+	s3c_i2c7_set_platdata(NULL);
+	i2c_register_board_info(7, smdk4x12_i2c_devs7,
+				ARRAY_SIZE(smdk4x12_i2c_devs7));
+
+	samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
+
+	samsung_keypad_set_platdata(&smdk4x12_keypad_data);
+
+	s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
+
+	platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
+}
+
+MACHINE_START(SMDK4212, "SMDK4212")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDK4412, "SMDK4412")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-smdkv310.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-smdkv310.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-smdkv310.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,390 @@
+/* linux/arch/arm/mach-exynos4/mach-smdkv310.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/lcd.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/fb.h>
+#include <plat/keypad.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/mfc.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+		/* fire nRESET on power up */
+		gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+		gpio_direction_output(EXYNOS4_GPX0(6), 1);
+		mdelay(100);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 1);
+		mdelay(10);
+
+		gpio_free(EXYNOS4_GPX0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkv310_lcd_lte480wv_data = {
+	.set_power		= lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkv310_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &smdkv310_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkv310_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 13,
+		.right_margin	= 8,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
+	.win[0]		= &smdkv310_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct resource smdkv310_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(1),
+		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(5),
+		.end	= IRQ_EINT(5),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device smdkv310_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
+	.resource	= smdkv310_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static uint32_t smdkv310_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
+	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
+	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
+	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
+};
+
+static struct matrix_keymap_data smdkv310_keymap_data __initdata = {
+	.keymap		= smdkv310_keymap,
+	.keymap_size	= ARRAY_SIZE(smdkv310_keymap),
+};
+
+static struct samsung_keypad_platdata smdkv310_keypad_data __initdata = {
+	.keymap_data	= &smdkv310_keymap_data,
+	.rows		= 2,
+	.cols		= 8,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{I2C_BOARD_INFO("wm8994", 0x1a),},
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata smdkv310_ehci_pdata;
+
+static void __init smdkv310_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &smdkv310_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+static struct platform_device *smdkv310_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s5p_device_i2c_hdmiphy,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&s5p_device_ehci,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&samsung_device_keypad,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_spdif,
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&samsung_asoc_idma,
+	&s5p_device_fimd0,
+	&smdkv310_lcd_lte480wv,
+	&smdkv310_smsc911x,
+	&exynos4_device_ahci,
+	&s5p_device_hdmi,
+	&s5p_device_mixer,
+};
+
+static void __init smdkv310_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv310_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+	/* direct HPD to HDMI chip */
+	WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* setup dependencies between TV devices */
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
+static void __init smdkv310_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+}
+
+static void __init smdkv310_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init smdkv310_machine_init(void)
+{
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	smdkv310_smsc911x_init();
+
+	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
+
+	s5p_tv_setup();
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+
+	samsung_keypad_set_platdata(&smdkv310_keypad_data);
+
+	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+	s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
+
+	smdkv310_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+}
+
+MACHINE_START(SMDKV310, "SMDKV310")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve	= &smdkv310_reserve,
+MACHINE_END
+
+MACHINE_START(SMDKC210, "SMDKC210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-universal_c210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-universal_c210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mach-universal_c210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1064 @@
+/* linux/arch/arm/mach-exynos4/mach-universal_c210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * 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/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/mfd/max8998.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/max8952.h>
+#include <linux/mmc/host.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/mcs.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+#include <plat/sdhci.h>
+#include <plat/pd.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
+
+#include <mach/map.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/m5mols.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+};
+
+static struct regulator_consumer_supply max8952_consumer =
+	REGULATOR_SUPPLY("vdd_arm", NULL);
+
+static struct max8952_platform_data universal_max8952_pdata __initdata = {
+	.gpio_vid0	= EXYNOS4_GPX0(3),
+	.gpio_vid1	= EXYNOS4_GPX0(4),
+	.gpio_en	= -1, /* Not controllable, set "Always High" */
+	.default_mode	= 0, /* vid0 = 0, vid1 = 0 */
+	.dvs_mode	= { 48, 32, 28, 18 }, /* 1.25, 1.20, 1.05, 0.95V */
+	.sync_freq	= 0, /* default: fastest */
+	.ramp_speed	= 0, /* default: fastest */
+
+	.reg_data	= {
+		.constraints	= {
+			.name		= "VARM_1.2V",
+			.min_uV		= 770000,
+			.max_uV		= 1400000,
+			.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+			.always_on	= 1,
+			.boot_on	= 1,
+		},
+		.num_consumer_supplies	= 1,
+		.consumer_supplies	= &max8952_consumer,
+	},
+};
+
+static struct regulator_consumer_supply lp3974_buck1_consumer =
+	REGULATOR_SUPPLY("vdd_int", NULL);
+
+static struct regulator_consumer_supply lp3974_buck2_consumer =
+	REGULATOR_SUPPLY("vddg3d", NULL);
+
+static struct regulator_consumer_supply lp3974_buck3_consumer =
+	REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+static struct regulator_init_data lp3974_buck1_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck1_consumer,
+};
+
+static struct regulator_init_data lp3974_buck2_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck2_consumer,
+};
+
+static struct regulator_init_data lp3974_buck3_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck3_consumer,
+};
+
+static struct regulator_init_data lp3974_buck4_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
+	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
+	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+};
+
+static struct regulator_init_data lp3974_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB+MIPI_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo3_consumer),
+	.consumer_supplies = lp3974_ldo3_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo4_consumer[] = {
+	REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"),
+};
+
+static struct regulator_init_data lp3974_ldo4_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo4_consumer),
+	.consumer_supplies = lp3974_ldo4_consumer,
+};
+
+static struct regulator_init_data lp3974_ldo5_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo6_data = {
+	.constraints	= {
+		.name		= "LDO6",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+};
+
+static struct regulator_init_data lp3974_ldo7_data = {
+	.constraints	= {
+		.name		= "VLCD+VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo7_consumer),
+	.consumer_supplies	= lp3974_ldo7_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
+	REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
+};
+
+static struct regulator_init_data lp3974_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB+VDAC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo8_consumer),
+	.consumer_supplies = lp3974_ldo8_consumer,
+};
+
+static struct regulator_init_data lp3974_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.boot_on	= 1,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_consumer_supply lp3974_ldo11_consumer =
+	REGULATOR_SUPPLY("dig_28", "0-001f");
+
+static struct regulator_init_data lp3974_ldo11_data = {
+	.constraints	= {
+		.name		= "CAM_AF_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo11_consumer,
+};
+
+static struct regulator_init_data lp3974_ldo12_data = {
+	.constraints	= {
+		.name		= "PS_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo13_data = {
+	.constraints	= {
+		.name		= "VHIC_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_consumer_supply lp3974_ldo14_consumer =
+	REGULATOR_SUPPLY("dig_18", "0-001f");
+
+static struct regulator_init_data lp3974_ldo14_data = {
+	.constraints	= {
+		.name		= "CAM_I_HOST_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo14_consumer,
+};
+
+
+static struct regulator_consumer_supply lp3974_ldo15_consumer =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data lp3974_ldo15_data = {
+	.constraints	= {
+		.name		= "CAM_S_DIG+FM33_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo15_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data lp3974_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_S_ANA_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo16_consumer),
+	.consumer_supplies	= lp3974_ldo16_consumer,
+};
+
+static struct regulator_init_data lp3974_ldo17_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_LCD",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct max8998_regulator_data lp3974_regulators[] = {
+	{ MAX8998_LDO2,  &lp3974_ldo2_data },
+	{ MAX8998_LDO3,  &lp3974_ldo3_data },
+	{ MAX8998_LDO4,  &lp3974_ldo4_data },
+	{ MAX8998_LDO5,  &lp3974_ldo5_data },
+	{ MAX8998_LDO6,  &lp3974_ldo6_data },
+	{ MAX8998_LDO7,  &lp3974_ldo7_data },
+	{ MAX8998_LDO8,  &lp3974_ldo8_data },
+	{ MAX8998_LDO9,  &lp3974_ldo9_data },
+	{ MAX8998_LDO10, &lp3974_ldo10_data },
+	{ MAX8998_LDO11, &lp3974_ldo11_data },
+	{ MAX8998_LDO12, &lp3974_ldo12_data },
+	{ MAX8998_LDO13, &lp3974_ldo13_data },
+	{ MAX8998_LDO14, &lp3974_ldo14_data },
+	{ MAX8998_LDO15, &lp3974_ldo15_data },
+	{ MAX8998_LDO16, &lp3974_ldo16_data },
+	{ MAX8998_LDO17, &lp3974_ldo17_data },
+	{ MAX8998_BUCK1, &lp3974_buck1_data },
+	{ MAX8998_BUCK2, &lp3974_buck2_data },
+	{ MAX8998_BUCK3, &lp3974_buck3_data },
+	{ MAX8998_BUCK4, &lp3974_buck4_data },
+	{ MAX8998_EN32KHZ_AP, &lp3974_32khz_ap_data },
+	{ MAX8998_EN32KHZ_CP, &lp3974_32khz_cp_data },
+	{ MAX8998_ENVICHG, &lp3974_vichg_data },
+	{ MAX8998_ESAFEOUT1, &lp3974_esafeout1_data },
+	{ MAX8998_ESAFEOUT2, &lp3974_esafeout2_data },
+};
+
+static struct max8998_platform_data universal_lp3974_pdata = {
+	.num_regulators		= ARRAY_SIZE(lp3974_regulators),
+	.regulators		= lp3974_regulators,
+	.buck1_voltage1		= 1100000,	/* INT */
+	.buck1_voltage2		= 1000000,
+	.buck1_voltage3		= 1100000,
+	.buck1_voltage4		= 1000000,
+	.buck1_set1		= EXYNOS4_GPX0(5),
+	.buck1_set2		= EXYNOS4_GPX0(6),
+	.buck2_voltage1		= 1200000,	/* G3D */
+	.buck2_voltage2		= 1100000,
+	.buck1_default_idx	= 0,
+	.buck2_set3		= EXYNOS4_GPE2(0),
+	.buck2_default_idx	= 0,
+	.wakeup			= true,
+};
+
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC0,
+	FIXED_REG_ID_HDMI_5V,
+	FIXED_REG_ID_CAM_S_IF,
+	FIXED_REG_ID_CAM_I_CORE,
+	FIXED_REG_ID_CAM_VT_DIO,
+};
+
+static struct regulator_consumer_supply hdmi_fixed_consumer =
+	REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
+
+static struct regulator_init_data hdmi_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "HDMI_5V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &hdmi_fixed_consumer,
+};
+
+static struct fixed_voltage_config hdmi_fixed_voltage_config = {
+	.supply_name		= "HDMI_EN1",
+	.microvolts		= 5000000,
+	.gpio			= EXYNOS4_GPE0(1),
+	.enable_high		= true,
+	.init_data		= &hdmi_fixed_voltage_init_data,
+};
+
+static struct platform_device hdmi_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_HDMI_5V,
+	.dev			= {
+		.platform_data	= &hdmi_fixed_voltage_config,
+	},
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8952", 0xC0 >> 1),
+		.platform_data	= &universal_max8952_pdata,
+	}, {
+		I2C_BOARD_INFO("lp3974", 0xCC >> 1),
+		.platform_data	= &universal_lp3974_pdata,
+	},
+};
+
+/* I2C3 (TSP) */
+static struct mxt_platform_data qt602240_platform_data = {
+	.x_line		= 19,
+	.y_line		= 11,
+	.x_size		= 800,
+	.y_size		= 480,
+	.blen		= 0x11,
+	.threshold	= 0x28,
+	.voltage	= 2800000,		/* 2.8V */
+	.orient		= MXT_DIAGONAL,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("qt602240_ts", 0x4a),
+		.platform_data = &qt602240_platform_data,
+	},
+};
+
+static void __init universal_tsp_init(void)
+{
+	int gpio;
+
+	/* TSP_LDO_ON: XMDMADDR_11 */
+	gpio = EXYNOS4_GPE2(3);
+	gpio_request(gpio, "TSP_LDO_ON");
+	gpio_direction_output(gpio, 1);
+	gpio_export(gpio, 0);
+
+	/* TSP_INT: XMDMADDR_7 */
+	gpio = EXYNOS4_GPE1(7);
+	gpio_request(gpio, "TSP_INT");
+
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+	i2c3_devs[0].irq = gpio_to_irq(gpio);
+}
+
+
+/* GPIO I2C 12 (3 Touchkey) */
+static uint32_t touchkey_keymap[] = {
+	/* MCS_KEY_MAP(value, keycode) */
+	MCS_KEY_MAP(0, KEY_MENU),		/* KEY_SEND */
+	MCS_KEY_MAP(1, KEY_BACK),		/* KEY_END */
+};
+
+static struct mcs_platform_data touchkey_data = {
+	.keymap		= touchkey_keymap,
+	.keymap_size	= ARRAY_SIZE(touchkey_keymap),
+	.key_maxval	= 2,
+};
+
+/* GPIO I2C 3_TOUCH 2.8V */
+#define I2C_GPIO_BUS_12		12
+static struct i2c_gpio_platform_data i2c_gpio12_data = {
+	.sda_pin	= EXYNOS4_GPE4(0),	/* XMDMDATA_8 */
+	.scl_pin	= EXYNOS4_GPE4(1),	/* XMDMDATA_9 */
+};
+
+static struct platform_device i2c_gpio12 = {
+	.name		= "i2c-gpio",
+	.id		= I2C_GPIO_BUS_12,
+	.dev		= {
+		.platform_data	= &i2c_gpio12_data,
+	},
+};
+
+static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
+		.platform_data = &touchkey_data,
+	},
+};
+
+static void __init universal_touchkey_init(void)
+{
+	int gpio;
+
+	gpio = EXYNOS4_GPE3(7);			/* XMDMDATA_7 */
+	gpio_request(gpio, "3_TOUCH_INT");
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
+
+	gpio = EXYNOS4_GPE3(3);			/* XMDMDATA_3 */
+	gpio_request(gpio, "3_TOUCH_EN");
+	gpio_direction_output(gpio, 1);
+}
+
+static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
+	.frequency	= 300 * 1000,
+	.sda_delay	= 200,
+};
+
+/* GPIO KEYS */
+static struct gpio_keys_button universal_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CONFIG,
+		.gpio			= EXYNOS4_GPX2(2),	/* XEINT18 */
+		.desc			= "gpio-keys: KEY_CONFIG",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CAMERA,
+		.gpio			= EXYNOS4_GPX2(3),	/* XEINT19 */
+		.desc			= "gpio-keys: KEY_CAMERA",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_OK,
+		.gpio			= EXYNOS4_GPX3(5),	/* XEINT29 */
+		.desc			= "gpio-keys: KEY_OK",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data universal_gpio_keys_data = {
+	.buttons	= universal_gpio_keys_tables,
+	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
+};
+
+static struct platform_device universal_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &universal_gpio_keys_data,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply mmc0_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+};
+
+static struct regulator_init_data mmc0_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
+	.consumer_supplies	= mmc0_supplies,
+};
+
+static struct fixed_voltage_config mmc0_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPE1(3),
+	.enable_high		= true,
+	.init_data		= &mmc0_fixed_voltage_init_data,
+};
+
+static struct platform_device mmc0_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_MMC0,
+	.dev			= {
+		.platform_data	= &mmc0_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(4),      /* XEINT_28 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WiFi */
+static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+};
+
+static void __init universal_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
+}
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+/* Frame Buffer */
+static struct s3c_fb_pd_win universal_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 16,
+		.right_margin	= 16,
+		.upper_margin	= 2,
+		.lower_margin	= 28,
+		.hsync_len	= 2,
+		.vsync_len	= 1,
+		.xres		= 480,
+		.yres		= 800,
+		.refresh	= 55,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
+	.win[0]		= &universal_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+			  VIDCON0_CLKSEL_LCD,
+	.vidcon1	= VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
+			  | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct regulator_consumer_supply cam_i_core_supply =
+	REGULATOR_SUPPLY("core", "0-001f");
+
+static struct regulator_init_data cam_i_core_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_i_core_supply,
+};
+
+static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
+	.supply_name	= "CAM_I_CORE_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(2),	/* CAM_8M_CORE_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_i_core_reg_init_data,
+};
+
+static struct platform_device cam_i_core_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
+	.dev = { .platform_data	= &cam_i_core_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply cam_s_if_supply =
+	REGULATOR_SUPPLY("d_sensor", "0-001f");
+
+static struct regulator_init_data cam_s_if_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_s_if_supply,
+};
+
+static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
+	.supply_name	= "CAM_S_IF_1.8V",
+	.microvolts	= 1800000,
+	.gpio		= EXYNOS4_GPE3(0),	/* CAM_PWR_EN1 */
+	.enable_high	= 1,
+	.init_data	= &cam_s_if_reg_init_data,
+};
+
+static struct platform_device cam_s_if_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
+	.dev = { .platform_data	= &cam_s_if_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+	.clk_rate	= 166000000UL,
+	.lanes		= 2,
+	.alignment	= 32,
+	.hs_settle	= 12,
+	.phy_enable	= s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_LEVEL_EN(n)	EXYNOS4_GPE4(n + 3)
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPX1(5)	/* XEINT_13 */
+#define GPIO_CAM_MEGA_nRST	EXYNOS4_GPE2(5)
+
+static int m5mols_set_power(struct device *dev, int on)
+{
+	gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
+	gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
+	return 0;
+}
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset	= GPIO_CAM_MEGA_nRST,
+	.reset_polarity	= 0,
+	.set_power	= m5mols_set_power,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info universal_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 21600000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= universal_camera_sensors,
+	.num_clients	= ARRAY_SIZE(universal_camera_sensors),
+};
+
+static struct gpio universal_camera_gpios[] = {
+	{ GPIO_CAM_LEVEL_EN(1),	GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
+	{ GPIO_CAM_LEVEL_EN(2),	GPIOF_OUT_INIT_LOW,  "CAM_LVL_EN2" },
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,            "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_nRST,	GPIOF_OUT_INIT_LOW,  "CAM_8M_NRST" },
+};
+
+static void universal_camera_init(void)
+{
+	s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+			 &s5p_device_mipi_csis0);
+	s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	if (gpio_request_array(universal_camera_gpios,
+			       ARRAY_SIZE(universal_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
+		m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
+	else
+		pr_err("Failed to configure 8M_ISP_INT GPIO\n");
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_nRST);
+	gpio_free(GPIO_CAM_8M_ISP_INT);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
+		pr_err("Camera port A setup failed\n");
+}
+
+static struct platform_device *universal_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&s5p_device_mipi_csis0,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&mmc0_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
+	&s3c_device_i2c3,
+	&s3c_device_i2c5,
+	&s5p_device_i2c_hdmiphy,
+	&hdmi_fixed_voltage,
+	&exynos4_device_pd[PD_TV],
+	&s5p_device_hdmi,
+	&s5p_device_sdo,
+	&s5p_device_mixer,
+
+	/* Universal Devices */
+	&i2c_gpio12,
+	&universal_gpio_keys,
+	&s5p_device_onenand,
+	&s5p_device_fimd0,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&cam_i_core_fixed_reg_dev,
+	&cam_s_if_fixed_reg_dev,
+	&s5p_device_fimc_md,
+};
+
+static void __init universal_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
+}
+
+void s5p_tv_setup(void)
+{
+	/* direct HPD to HDMI chip */
+	gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
+
+	gpio_direction_input(EXYNOS4_GPX3(7));
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* setup dependencies between TV devices */
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
+static void __init universal_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init universal_machine_init(void)
+{
+	universal_sdhci_init();
+	s5p_tv_setup();
+
+	s3c_i2c0_set_platdata(&universal_i2c0_platdata);
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
+	universal_tsp_init();
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+
+	s3c_i2c5_set_platdata(NULL);
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	s5p_fimd0_set_platdata(&universal_lcd_pdata);
+
+	universal_touchkey_init();
+	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
+			ARRAY_SIZE(i2c_gpio12_devs));
+
+	universal_camera_init();
+
+	/* Last */
+	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+}
+
+MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= universal_map_io,
+	.init_machine	= universal_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve        = &universal_reserve,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/Makefile linux-libre-3.2-gnu1/arch/arm/mach-exynos/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+# arch/arm/mach-exynos/Makefile
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for EXYNOS4 system
+
+obj-$(CONFIG_ARCH_EXYNOS4)	+= cpu.o init.o clock.o irq-combiner.o setup-i2c0.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= irq-eint.o dma.o pmu.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
+obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
+
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+
+obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
+
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkv310.o
+obj-$(CONFIG_MACH_SMDKV310)		+= mach-smdkv310.o
+obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
+obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
+obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
+obj-$(CONFIG_MACH_ORIGEN)		+= mach-origen.o
+
+obj-$(CONFIG_MACH_SMDK4212)		+= mach-smdk4x12.o
+obj-$(CONFIG_MACH_SMDK4412)		+= mach-smdk4x12.o
+
+# device support
+
+obj-$(CONFIG_ARCH_EXYNOS4)		+= dev-audio.o
+obj-$(CONFIG_EXYNOS4_DEV_AHCI)		+= dev-ahci.o
+obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
+obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
+obj-$(CONFIG_EXYNOS4_DEV_DWMCI)		+= dev-dwmci.o
+
+obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C4)	+= setup-i2c4.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C5)	+= setup-i2c5.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C6)	+= setup-i2c6.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C7)	+= setup-i2c7.o
+obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)	+= setup-keypad.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)	+= setup-sdhci.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
+obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY)	+= setup-usb-phy.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-exynos/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2 @@
+   zreladdr-y	+= 0x40008000
+params_phys-y	:= 0x40000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/mct.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/mct.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/mct.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/mct.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,478 @@
+/* linux/arch/arm/mach-exynos4/mct.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 MCT(Multi-Core Timer) support
+ *
+ * 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/percpu.h>
+
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-mct.h>
+#include <asm/mach/time.h>
+
+enum {
+	MCT_INT_SPI,
+	MCT_INT_PPI
+};
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+static unsigned int mct_int_type;
+
+struct mct_clock_event_device {
+	struct clock_event_device *evt;
+	void __iomem *base;
+	char name[10];
+};
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+	void __iomem *stat_addr;
+	u32 mask;
+	u32 i;
+
+	__raw_writel(value, addr);
+
+	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
+		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
+		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
+		case (u32) MCT_L_TCON_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 3;		/* L_TCON write status */
+			break;
+		case (u32) MCT_L_ICNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 1;		/* L_ICNTB write status */
+			break;
+		case (u32) MCT_L_TCNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 0;		/* L_TCNTB write status */
+			break;
+		default:
+			return;
+		}
+	} else {
+		switch ((u32) addr) {
+		case (u32) EXYNOS4_MCT_G_TCON:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 16;		/* G_TCON write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_L:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 0;		/* G_COMP0_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_U:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 1;		/* G_COMP0_U write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_L:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 0;		/* G_CNT_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_U:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 1;		/* G_CNT_U write status */
+			break;
+		default:
+			return;
+		}
+	}
+
+	/* Wait maximum 1 ms until written values are applied */
+	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
+		if (__raw_readl(stat_addr) & mask) {
+			__raw_writel(mask, stat_addr);
+			return;
+		}
+
+	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+}
+
+/* Clocksource handling */
+static void exynos4_mct_frc_start(u32 hi, u32 lo)
+{
+	u32 reg;
+
+	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
+	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
+
+	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+	reg |= MCT_G_TCON_START;
+	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
+}
+
+static cycle_t exynos4_frc_read(struct clocksource *cs)
+{
+	unsigned int lo, hi;
+	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+
+	do {
+		hi = hi2;
+		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
+		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+	} while (hi != hi2);
+
+	return ((cycle_t)hi << 32) | lo;
+}
+
+static void exynos4_frc_resume(struct clocksource *cs)
+{
+	exynos4_mct_frc_start(0, 0);
+}
+
+struct clocksource mct_frc = {
+	.name		= "mct-frc",
+	.rating		= 400,
+	.read		= exynos4_frc_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume		= exynos4_frc_resume,
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+	exynos4_mct_frc_start(0, 0);
+
+	if (clocksource_register_hz(&mct_frc, clk_rate))
+		panic("%s: can't register clocksource\n", mct_frc.name);
+}
+
+static void exynos4_mct_comp0_stop(void)
+{
+	unsigned int tcon;
+
+	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
+
+	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
+	exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
+}
+
+static void exynos4_mct_comp0_start(enum clock_event_mode mode,
+				    unsigned long cycles)
+{
+	unsigned int tcon;
+	cycle_t comp_cycle;
+
+	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+
+	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
+		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
+	}
+
+	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
+	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
+
+	tcon |= MCT_G_TCON_COMP0_ENABLE;
+	exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
+}
+
+static int exynos4_comp_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	exynos4_mct_comp0_start(evt->mode, cycles);
+
+	return 0;
+}
+
+static void exynos4_comp_set_mode(enum clock_event_mode mode,
+				  struct clock_event_device *evt)
+{
+	exynos4_mct_comp0_stop();
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_comp0_start(mode, clk_cnt_per_tick);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device mct_comp_device = {
+	.name		= "mct-comp",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 250,
+	.set_next_event	= exynos4_comp_set_next_event,
+	.set_mode	= exynos4_comp_set_mode,
+};
+
+static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_comp_event_irq = {
+	.name		= "mct_comp_irq",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= exynos4_mct_comp_isr,
+	.dev_id		= &mct_comp_device,
+};
+
+static void exynos4_clockevent_init(void)
+{
+	clk_cnt_per_tick = clk_rate / 2	/ HZ;
+
+	clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5);
+	mct_comp_device.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &mct_comp_device);
+	mct_comp_device.min_delta_ns =
+		clockevent_delta2ns(0xf, &mct_comp_device);
+	mct_comp_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&mct_comp_device);
+
+	setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
+
+/* Clock event handling */
+static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+
+	tmp = __raw_readl(addr);
+	if (tmp & mask) {
+		tmp &= ~mask;
+		exynos4_mct_write(tmp, addr);
+	}
+}
+
+static void exynos4_mct_tick_start(unsigned long cycles,
+				   struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+
+	exynos4_mct_tick_stop(mevt);
+
+	tmp = (1 << 31) | cycles;	/* MCT_L_UPDATE_ICNTB */
+
+	/* update interrupt count buffer */
+	exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
+
+	/* enable MCT tick interrupt */
+	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
+
+	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
+	       MCT_L_TCON_INTERVAL_MODE;
+	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
+}
+
+static int exynos4_tick_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+
+	exynos4_mct_tick_start(cycles, mevt);
+
+	return 0;
+}
+
+static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
+					 struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+
+	exynos4_mct_tick_stop(mevt);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
+{
+	struct clock_event_device *evt = mevt->evt;
+
+	/*
+	 * This is for supporting oneshot mode.
+	 * Mct would generate interrupt periodically
+	 * without explicit stopping.
+	 */
+	if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
+		exynos4_mct_tick_stop(mevt);
+
+	/* Clear the MCT tick interrupt */
+	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+	struct mct_clock_event_device *mevt = dev_id;
+	struct clock_event_device *evt = mevt->evt;
+
+	exynos4_mct_tick_clear(mevt);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_tick0_event_irq = {
+	.name		= "mct_tick0_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static struct irqaction mct_tick1_event_irq = {
+	.name		= "mct_tick1_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static void exynos4_mct_tick_init(struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt;
+	unsigned int cpu = smp_processor_id();
+
+	mevt = this_cpu_ptr(&percpu_mct_tick);
+	mevt->evt = evt;
+
+	mevt->base = EXYNOS4_MCT_L_BASE(cpu);
+	sprintf(mevt->name, "mct_tick%d", cpu);
+
+	evt->name = mevt->name;
+	evt->cpumask = cpumask_of(cpu);
+	evt->set_next_event = exynos4_tick_set_next_event;
+	evt->set_mode = exynos4_tick_set_mode;
+	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = 450;
+
+	clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
+	evt->max_delta_ns =
+		clockevent_delta2ns(0x7fffffff, evt);
+	evt->min_delta_ns =
+		clockevent_delta2ns(0xf, evt);
+
+	clockevents_register_device(evt);
+
+	exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET);
+
+	if (mct_int_type == MCT_INT_SPI) {
+		if (cpu == 0) {
+			mct_tick0_event_irq.dev_id = mevt;
+			evt->irq = IRQ_MCT_L0;
+			setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+		} else {
+			mct_tick1_event_irq.dev_id = mevt;
+			evt->irq = IRQ_MCT_L1;
+			setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+			irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		}
+	} else {
+		enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
+	}
+}
+
+/* Setup the local clock events for a CPU */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	exynos4_mct_tick_init(evt);
+
+	return 0;
+}
+
+void local_timer_stop(struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	if (mct_int_type == MCT_INT_SPI)
+		if (cpu == 0)
+			remove_irq(evt->irq, &mct_tick0_event_irq);
+		else
+			remove_irq(evt->irq, &mct_tick1_event_irq);
+	else
+		disable_percpu_irq(IRQ_MCT_LOCALTIMER);
+}
+#endif /* CONFIG_LOCAL_TIMERS */
+
+static void __init exynos4_timer_resources(void)
+{
+	struct clk *mct_clk;
+	mct_clk = clk_get(NULL, "xtal");
+
+	clk_rate = clk_get_rate(mct_clk);
+
+#ifdef CONFIG_LOCAL_TIMERS
+	if (mct_int_type == MCT_INT_PPI) {
+		int err;
+
+		err = request_percpu_irq(IRQ_MCT_LOCALTIMER,
+					 exynos4_mct_tick_isr, "MCT",
+					 &percpu_mct_tick);
+		WARN(err, "MCT: can't request IRQ %d (%d)\n",
+		     IRQ_MCT_LOCALTIMER, err);
+	}
+#endif /* CONFIG_LOCAL_TIMERS */
+}
+
+static void __init exynos4_timer_init(void)
+{
+	if (soc_is_exynos4210())
+		mct_int_type = MCT_INT_SPI;
+	else
+		mct_int_type = MCT_INT_PPI;
+
+	exynos4_timer_resources();
+	exynos4_clocksource_init();
+	exynos4_clockevent_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,223 @@
+/* linux/arch/arm/mach-exynos4/platsmp.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+
+#include <plat/cpu.h>
+
+extern unsigned int gic_bank_offset;
+extern void exynos4_secondary_startup(void);
+
+#define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
+				S5P_INFORM5 : S5P_VA_SYSRAM)
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+
+volatile int __cpuinitdata pen_release = -1;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)(S5P_VA_SCU);
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+	void __iomem *dist_base = S5P_VA_GIC_DIST +
+				(gic_bank_offset * smp_processor_id());
+	void __iomem *cpu_base = S5P_VA_GIC_CPU +
+				(gic_bank_offset * smp_processor_id());
+	int i;
+
+	/*
+	 * Deal with the banked PPI and SGI interrupts - disable all
+	 * PPI interrupts, ensure all SGI interrupts are enabled.
+	 */
+	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+	/*
+	 * Set priority on PPI and SGI interrupts
+	 */
+	for (i = 0; i < 32; i += 4)
+		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	exynos4_gic_secondary_init();
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	write_pen_release(cpu_logical_map(cpu));
+
+	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
+			     S5P_ARM_CORE1_CONFIGURATION);
+
+		timeout = 10;
+
+		/* wait max 10 ms until cpu1 is on */
+		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+			if (timeout-- == 0)
+				break;
+
+			mdelay(1);
+		}
+
+		if (timeout == 0) {
+			printk(KERN_ERR "cpu1 power enable failed");
+			spin_unlock(&boot_lock);
+			return -ETIMEDOUT;
+		}
+	}
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+
+		__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+			CPU1_BOOT_REG);
+		gic_raise_softirq(cpumask_of(cpu), 1);
+
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+
+void __init smp_init_cpus(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	/* sanity check */
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+
+	scu_enable(scu_base_addr());
+
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The boot monitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+			CPU1_BOOT_REG);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/pm.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,428 @@
+/* linux/arch/arm/mach-exynos4/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+#include <mach/pm-core.h>
+#include <mach/pmu.h>
+
+static struct sleep_save exynos4_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_TOP			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_CAM			, .val = 0x11111111, },
+	{ .reg = S5P_CLKSRC_MASK_TV			, .val = 0x00000111, },
+	{ .reg = S5P_CLKSRC_MASK_LCD0			, .val = 0x00001111, },
+	{ .reg = S5P_CLKSRC_MASK_MAUDIO			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_FSYS			, .val = 0x01011111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL0			, .val = 0x01111111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL1			, .val = 0x01110111, },
+	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
+};
+
+static struct sleep_save exynos4210_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
+};
+
+static struct sleep_save exynos4_epll_save[] = {
+	SAVE_ITEM(S5P_EPLL_CON0),
+	SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+	SAVE_ITEM(S5P_VPLL_CON0),
+	SAVE_ITEM(S5P_VPLL_CON1),
+};
+
+static struct sleep_save exynos4_core_save[] = {
+	/* GIC side */
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
+
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+
+	/* SROM side */
+	SAVE_ITEM(S5P_SROM_BW),
+	SAVE_ITEM(S5P_SROM_BC0),
+	SAVE_ITEM(S5P_SROM_BC1),
+	SAVE_ITEM(S5P_SROM_BC2),
+	SAVE_ITEM(S5P_SROM_BC3),
+};
+
+static struct sleep_save exynos4_l2cc_save[] = {
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
+};
+
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
+
+static int exynos4_cpu_suspend(unsigned long arg)
+{
+	outer_flush_all();
+
+	/* issue the standby signal into the pm unit. */
+	cpu_do_idle();
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+static void exynos4_pm_prepare(void)
+{
+	u32 tmp;
+
+	s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+	s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+	s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+	s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
+
+	tmp = __raw_readl(S5P_INFORM1);
+
+	/* Set value of power down register for sleep mode */
+
+	exynos4_sys_powerdown_conf(SYS_SLEEP);
+	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+
+	/* ensure at least INFORM0 has the resume address */
+
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+	/* Before enter central sequence mode, clock src register have to set */
+
+	s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
+
+	if (soc_is_exynos4210())
+		s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
+
+}
+
+static int exynos4_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = exynos4_pm_prepare;
+	pm_cpu_sleep = exynos4_cpu_suspend;
+
+	return 0;
+}
+
+/* This function copy from linux/arch/arm/kernel/smp_scu.c */
+
+void exynos4_scu_enable(void __iomem *scu_base)
+{
+	u32 scu_ctrl;
+
+	scu_ctrl = __raw_readl(scu_base);
+	/* already enabled? */
+	if (scu_ctrl & 1)
+		return;
+
+	scu_ctrl |= 1;
+	__raw_writel(scu_ctrl, scu_base);
+
+	/*
+	 * Ensure that the data accessed by CPU0 before the SCU was
+	 * initialised is visible to the other CPUs.
+	 */
+	flush_cache_all();
+}
+
+static unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+	unsigned long pll_con, locktime, lockcnt;
+	unsigned long pll_in_rate;
+	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+	if (pll_base_rate == 0)
+		return;
+
+	pll_in_rate = pll_base_rate;
+
+	/* EPLL */
+	pll_con = exynos4_epll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+		pll_in_rate /= 1000000;
+
+		locktime = (3000 / pll_in_rate) * p_div;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_epll_save,
+					ARRAY_SIZE(exynos4_epll_save));
+		epll_wait = 1;
+	}
+
+	pll_in_rate = pll_base_rate;
+
+	/* VPLL */
+	pll_con = exynos4_vpll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_in_rate /= 1000000;
+		/* 750us */
+		locktime = 750;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_vpll_save,
+					ARRAY_SIZE(exynos4_vpll_save));
+		vpll_wait = 1;
+	}
+
+	/* Wait PLL locking */
+
+	do {
+		if (epll_wait) {
+			pll_con = __raw_readl(S5P_EPLL_CON0);
+			if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+				epll_wait = 0;
+		}
+
+		if (vpll_wait) {
+			pll_con = __raw_readl(S5P_VPLL_CON0);
+			if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+				vpll_wait = 0;
+		}
+	} while (epll_wait || vpll_wait);
+}
+
+static struct sysdev_driver exynos4_pm_driver = {
+	.add		= exynos4_pm_add,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+	struct clk *pll_base;
+	unsigned int tmp;
+
+	s3c_pm_init();
+
+	/* All wakeup disable */
+
+	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp |= ((0xFF << 8) | (0x1F << 1));
+	__raw_writel(tmp, S5P_WAKEUP_MASK);
+
+	pll_base = clk_get(NULL, "xtal");
+
+	if (!IS_ERR(pll_base)) {
+		pll_base_rate = clk_get_rate(pll_base);
+		clk_put(pll_base);
+	}
+
+	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
+
+static int exynos4_pm_suspend(void)
+{
+	unsigned long tmp;
+
+	/* Setting Central Sequence Register for power down mode */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+	if (soc_is_exynos4212()) {
+		tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+		tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
+			 S5P_USE_STANDBYWFE_ISP_ARM);
+		__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+	}
+
+	/* Save Power control register */
+	asm ("mrc p15, 0, %0, c15, c0, 0"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[0] = tmp;
+
+	/* Save Diagnostic register */
+	asm ("mrc p15, 0, %0, c15, c0, 1"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[1] = tmp;
+
+	return 0;
+}
+
+static void exynos4_pm_resume(void)
+{
+	unsigned long tmp;
+
+	/*
+	 * If PMU failed while entering sleep mode, WFI will be
+	 * ignored by PMU and then exiting cpu_do_idle().
+	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+	 * in this situation.
+	 */
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+		tmp |= S5P_CENTRAL_LOWPWR_CFG;
+		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+		/* No need to perform below restore code */
+		goto early_wakeup;
+	}
+	/* Restore Power control register */
+	tmp = save_arm_register[0];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+		      : : "r" (tmp)
+		      : "cc");
+
+	/* Restore Diagnostic register */
+	tmp = save_arm_register[1];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+		      : : "r" (tmp)
+		      : "cc");
+
+	/* For release retention */
+
+	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+
+	s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+
+	exynos4_restore_pll();
+
+	exynos4_scu_enable(S5P_VA_SCU);
+
+#ifdef CONFIG_CACHE_L2X0
+	s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+	outer_inv_all();
+	/* enable L2X0*/
+	writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
+#endif
+
+early_wakeup:
+	return;
+}
+
+static struct syscore_ops exynos4_pm_syscore_ops = {
+	.suspend	= exynos4_pm_suspend,
+	.resume		= exynos4_pm_resume,
+};
+
+static __init int exynos4_pm_syscore_init(void)
+{
+	register_syscore_ops(&exynos4_pm_syscore_ops);
+	return 0;
+}
+arch_initcall(exynos4_pm_syscore_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/pmu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/pmu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,230 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) support
+ *
+ * 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/io.h>
+#include <linux/kernel.h>
+
+#include <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static struct exynos4_pmu_conf *exynos4_pmu_config;
+
+static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
+	/* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_CORE1_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_COMMON_LOWPWR,		{ 0x0, 0x0, 0x2 } },
+	{ S5P_L2_0_LOWPWR,			{ 0x2, 0x2, 0x3 } },
+	{ S5P_L2_1_LOWPWR,			{ 0x2, 0x2, 0x3 } },
+	{ S5P_CMU_ACLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_APLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_MPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_VPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_EPLL_SYSCLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPSALIVE_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_CAM_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_TV_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MFC_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_G3D_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD0_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD1_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_CAM_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_TV_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_MFC_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_G3D_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_LCD0_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_LCD1_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPS_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_TOP_BUS_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_LOWPWR,			{ 0x3, 0x0, 0x3 } },
+	{ S5P_LOGIC_RESET_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_ONENAND_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_MODIMIF_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_G2D_ACP_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_USBOTG_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSMMC_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_CSSYS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SECSS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_PCIE_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SATA_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_DRAM_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_UART_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ISOLATION_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_XUSBXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_XXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_EXT_REGULATOR_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_GPIO_MODE_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CAM_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_TV_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MFC_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_G3D_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD0_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD1_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MAUDIO_LOWPWR,			{ 0x7, 0x7, 0x0 } },
+	{ S5P_GPS_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_GPS_ALIVE_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ PMU_TABLE_END,},
+};
+
+static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
+	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_CORE1_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ISP_ARM_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR,	{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR,	{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_COMMON_LOWPWR,		{ 0x0, 0x0, 0x2 } },
+	{ S5P_L2_0_LOWPWR,			{ 0x0, 0x0, 0x3 } },
+	/* XXX_OPTION register should be set other field */
+	{ S5P_ARM_L2_0_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_L2_1_LOWPWR,			{ 0x0, 0x0, 0x3 } },
+	{ S5P_ARM_L2_1_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_CMU_ACLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_DRAM_FREQ_DOWN_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_DDRPHY_DLLOFF_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_LPDDR_PHY_DLL_LOCK_LOWPWR,	{ 0x1, 0x1, 0x1 } },
+	{ S5P_CMU_ACLKSTOP_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_COREBLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_APLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_MPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_VPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_EPLL_SYSCLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_MPLLUSER_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_GPSALIVE_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_CAM_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_TV_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MFC_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_G3D_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD0_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_CAM_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_TV_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_MFC_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_G3D_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LCD0_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_TOP_BUS_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_LOWPWR,			{ 0x3, 0x0, 0x3 } },
+	{ S5P_TOP_BUS_COREBLK_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_COREBLK_LOWPWR,		{ 0x3, 0x0, 0x3 } },
+	{ S5P_LOGIC_RESET_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_OSCCLK_GATE_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_LOGIC_RESET_COREBLK_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_OSCCLK_GATE_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x1 } },
+	{ S5P_ONENAND_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_ONENAND_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_HSI_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSI_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_G2D_ACP_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_G2D_ACP_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_USBOTG_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_USBOTG_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_HSMMC_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSMMC_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_CSSYS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_CSSYS_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_SECSS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SECSS_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_ROTATOR_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_ROTATOR_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_PAD_RETENTION_DRAM_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_UART_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ISOLATION_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_ISOLATION_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_XUSBXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_XXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_EXT_REGULATOR_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_GPIO_MODE_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_COREBLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_TOP_ASB_RESET_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_TOP_ASB_ISOLATION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_CAM_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_TV_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MFC_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_G3D_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD0_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_ISP_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MAUDIO_LOWPWR,			{ 0x7, 0x7, 0x0 } },
+	{ S5P_GPS_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_GPS_ALIVE_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_CMU_SYSCLK_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SYSCLK_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ PMU_TABLE_END,},
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+	unsigned int i;
+
+	for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
+		__raw_writel(exynos4_pmu_config[i].val[mode],
+				exynos4_pmu_config[i].reg);
+}
+
+static int __init exynos4_pmu_init(void)
+{
+	exynos4_pmu_config = exynos4210_pmu_config;
+
+	if (soc_is_exynos4210()) {
+		exynos4_pmu_config = exynos4210_pmu_config;
+		pr_info("EXYNOS4210 PMU Initialize\n");
+	} else if (soc_is_exynos4212()) {
+		exynos4_pmu_config = exynos4212_pmu_config;
+		pr_info("EXYNOS4212 PMU Initialize\n");
+	} else {
+		pr_info("EXYNOS4: PMU not supported\n");
+	}
+
+	return 0;
+}
+arch_initcall(exynos4_pmu_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-fimc.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-fimc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-fimc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Exynos4 camera interface GPIO configuration.
+ *
+ * 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/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <plat/camport.h>
+
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id)
+{
+	u32 gpio8, gpio5;
+	u32 sfn;
+	int ret;
+
+	switch (id) {
+	case S5P_CAMPORT_A:
+		gpio8 = EXYNOS4_GPJ0(0); /* PCLK, VSYNC, HREF, DATA[0:4] */
+		gpio5 = EXYNOS4_GPJ1(0); /* DATA[5:7], CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(2);
+		break;
+
+	case S5P_CAMPORT_B:
+		gpio8 = EXYNOS4_GPE0(0); /* DATA[0:7] */
+		gpio5 = EXYNOS4_GPE1(0); /* PCLK, VSYNC, HREF, CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(3);
+		break;
+
+	default:
+		WARN(1, "Wrong camport id: %d\n", id);
+		return -EINVAL;
+	}
+
+	ret = s3c_gpio_cfgall_range(gpio8, 8, sfn, S3C_GPIO_PULL_UP);
+	if (ret)
+		return ret;
+
+	return s3c_gpio_cfgall_range(gpio5, 5, sfn, S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-fimd0.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-fimd0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-fimd0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-fimd0.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+	unsigned int reg;
+
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+	/*
+	 * Set DISPLAY_CONTROL register for Display path selection.
+	 *
+	 * DISPLAY_CONTROL[1:0]
+	 * ---------------------
+	 *  00 | MIE
+	 *  01 | MDINE
+	 *  10 | FIMD : selected
+	 *  11 | FIMD
+	 */
+	reg = __raw_readl(S3C_VA_SYS + 0x0210);
+	reg |= (1 << 1);
+	__raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c0.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c0.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c0.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64xx/setup-i2c0.c
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c1.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c1.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c1.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c1.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C1 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(2), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c2.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c2.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C2 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c2_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA0(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c3.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c3.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C3 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c3_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA1(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c4.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c4.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c4.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C4 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c4_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c5.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c5.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c5.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c5.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C5 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c5_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c6.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c6.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c6.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c6.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C6 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c6_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
+			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c7.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c7.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-i2c7.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c7.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C7 GPIO configuration.
+ *
+ * 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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c7_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD0(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-keypad.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-keypad.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/mach-exynos4/setup-keypad.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * GPIO configuration for Exynos4 KeyPad device
+ *
+ * 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/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
+{
+	/* Keypads can be of various combinations, Just making sure */
+
+	if (rows > 8) {
+		/* Set all the necessary GPX2 pins: KP_ROW[0~7] */
+		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3),
+					S3C_GPIO_PULL_UP);
+
+		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
+		s3c_gpio_cfgall_range(EXYNOS4_GPX3(0), (rows - 8),
+					 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+	} else {
+		/* Set all the necessary GPX2 pins: KP_ROW[x] */
+		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), rows, S3C_GPIO_SFN(3),
+					S3C_GPIO_PULL_UP);
+	}
+
+	/* Set all the necessary GPX1 pins to special-function 3: KP_COL[x] */
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPX1(0), cols, S3C_GPIO_SFN(3));
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * 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/types.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *exynos4_hsmmc_clksrcs[4] = {
+	[0] = NULL,
+	[1] = NULL,
+	[2] = "sclk_mmc",	/* mmc_bus */
+	[3] = NULL,
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-sdhci-gpio.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-sdhci-gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-sdhci-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,152 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci-gpio.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+			/* Data pin GPK1[3:6] to special-function 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) {
+			/* Data pin GPK0[3:6] to special-function 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK0(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK0(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK1(0); gpio < EXYNOS4_GPK1(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+		/* Data pin GPK1[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK1(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK1(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK2(0); gpio < EXYNOS4_GPK2(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+			/* Data pin GPK3[3:6] to special-function 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK2(3); gpio <= EXYNOS4_GPK2(6); gpio++) {
+			/* Data pin GPK2[3:6] to special-function 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK2(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK2(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK3(0); gpio < EXYNOS4_GPK3(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+		/* Data pin GPK3[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK3(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK3(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-usb-phy.c linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-usb-phy.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos/setup-usb-phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos/setup-usb-phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <mach/regs-pmu.h>
+#include <mach/regs-usb-phy.h>
+#include <plat/cpu.h>
+#include <plat/usb-phy.h>
+
+static int exynos4_usb_phy1_init(struct platform_device *pdev)
+{
+	struct clk *otg_clk;
+	struct clk *xusbxti_clk;
+	u32 phyclk;
+	u32 rstcon;
+	int err;
+
+	otg_clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(otg_clk)) {
+		dev_err(&pdev->dev, "Failed to get otg clock\n");
+		return PTR_ERR(otg_clk);
+	}
+
+	err = clk_enable(otg_clk);
+	if (err) {
+		clk_put(otg_clk);
+		return err;
+	}
+
+	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
+			S5P_USBHOST_PHY_CONTROL);
+
+	/* set clock frequency for PLL */
+	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
+
+	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
+		switch (clk_get_rate(xusbxti_clk)) {
+		case 12 * MHZ:
+			phyclk |= CLKSEL_12M;
+			break;
+		case 24 * MHZ:
+			phyclk |= CLKSEL_24M;
+			break;
+		default:
+		case 48 * MHZ:
+			/* default reference clock */
+			break;
+		}
+		clk_put(xusbxti_clk);
+	}
+
+	writel(phyclk, EXYNOS4_PHYCLK);
+
+	/* floating prevention logic: disable */
+	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
+
+	/* set to normal HSIC 0 and 1 of PHY1 */
+	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
+			EXYNOS4_PHYPWR);
+
+	/* set to normal standard USB of PHY1 */
+	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
+
+	/* reset all ports of both PHY and Link */
+	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
+		PHY1_SWRST_MASK;
+	writel(rstcon, EXYNOS4_RSTCON);
+	udelay(10);
+
+	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
+	writel(rstcon, EXYNOS4_RSTCON);
+	udelay(80);
+
+	clk_disable(otg_clk);
+	clk_put(otg_clk);
+
+	return 0;
+}
+
+static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+{
+	struct clk *otg_clk;
+	int err;
+
+	otg_clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(otg_clk)) {
+		dev_err(&pdev->dev, "Failed to get otg clock\n");
+		return PTR_ERR(otg_clk);
+	}
+
+	err = clk_enable(otg_clk);
+	if (err) {
+		clk_put(otg_clk);
+		return err;
+	}
+
+	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
+			EXYNOS4_PHYPWR);
+
+	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
+			S5P_USBHOST_PHY_CONTROL);
+
+	clk_disable(otg_clk);
+	clk_put(otg_clk);
+
+	return 0;
+}
+
+int s5p_usb_phy_init(struct platform_device *pdev, int type)
+{
+	if (type == S5P_USB_PHY_HOST)
+		return exynos4_usb_phy1_init(pdev);
+
+	return -EINVAL;
+}
+
+int s5p_usb_phy_exit(struct platform_device *pdev, int type)
+{
+	if (type == S5P_USB_PHY_HOST)
+		return exynos4_usb_phy1_exit(pdev);
+
+	return -EINVAL;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/clock.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1212 +0,0 @@
-/* linux/arch/arm/mach-exynos4/clock.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock support
- *
- * 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/err.h>
-#include <linux/io.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-static struct clk clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
-}
-
-static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources	= &clk_src_apll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &clk_mout_apll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources	= &clk_src_epll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-	},
-	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
-};
-
-static struct clk *clkset_moutcore_list[] = {
-	[0] = &clk_mout_apll.clk,
-	[1] = &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_moutcore = {
-	.sources	= clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
-};
-
-static struct clksrc_clk clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-	},
-	.sources	= &clkset_moutcore,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &clk_moutcore.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *clkset_corebus_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_corebus = {
-	.sources	= clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
-};
-
-static struct clksrc_clk clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-	},
-	.sources	= &clkset_mout_corebus,
-	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.parent		= &clk_sclk_dmc.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.parent		= &clk_aclk_cored.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &clk_aclk_acp.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-static struct clk *clkset_aclk_top_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_aclk = {
-	.sources	= clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
-};
-
-static struct clksrc_clk clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources clkset_vpllsrc = {
-	.sources	= clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos4_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources	= &clkset_vpllsrc,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_sclk_vpll_list[] = {
-	[0] = &clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources clkset_sclk_vpll = {
-	.sources	= clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources	= &clkset_sclk_vpll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.0",
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "sataphy",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.3",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dwmmc",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sata",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "SYSMMU_MDMA",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "SYSMMU_FIMC0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "SYSMMU_FIMC1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "SYSMMU_FIMC2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "SYSMMU_FIMC3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "SYSMMU_JPEG",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "SYSMMU_FIMD0",
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_FIMD1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_PCIe",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "SYSMMU_G2D",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "SYSMMU_ROTATOR",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_TV",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_MFC_L",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "SYSMMU_MFC_R",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk *clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group = {
-	.sources	= clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group_list),
-};
-
-static struct clk *clkset_mout_g2d0_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d0 = {
-	.sources	= clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
-};
-
-static struct clksrc_clk clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources	= &clkset_mout_g2d0,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d1 = {
-	.sources	= clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
-};
-
-static struct clksrc_clk clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources	= &clkset_mout_g2d1,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d_list[] = {
-	[0] = &clk_mout_g2d0.clk,
-	[1] = &clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d = {
-	.sources	= clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
-};
-
-static struct clk *clkset_mout_mfc0_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc0 = {
-	.sources	= clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources	= &clkset_mout_mfc0,
-	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_mout_mfc1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc1 = {
-	.sources	= clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources	= &clkset_mout_mfc1,
-	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_mout_mfc_list[] = {
-	[0] = &clk_mout_mfc0.clk,
-	[1] = &clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc = {
-	.sources	= clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
-};
-
-static struct clksrc_clk clk_dout_mmc0 = {
-	.clk		= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc1 = {
-	.clk		= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc2 = {
-	.clk		= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc3 = {
-	.clk		= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "uclk1",
-			.devname	= "s5pv210-uart.0",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.devname	= "s5pv210-uart.1",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.devname	= "s5pv210-uart.2",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.devname	= "s5pv210-uart.3",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_pwm",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.2",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.3",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.0",
-			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_sata",
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_mout_corebus,
-		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.devname	= "s3c64xx-spi.0",
-			.enable		= exynos4_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.devname	= "s3c64xx-spi.1",
-			.enable		= exynos4_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.devname	= "s3c64xx-spi.2",
-			.enable		= exynos4_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &clkset_mout_g2d,
-		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &clkset_mout_mfc,
-		.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.0",
-			.parent		= &clk_dout_mmc0.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.1",
-			.parent         = &clk_dout_mmc1.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.2",
-			.parent         = &clk_dout_mmc2.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.3",
-			.parent         = &clk_dout_mmc3.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_dwmmc",
-			.parent         = &clk_dout_mmc4.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_sclk_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_moutcore,
-	&clk_coreclk,
-	&clk_armclk,
-	&clk_aclk_corem0,
-	&clk_aclk_cores,
-	&clk_aclk_corem1,
-	&clk_periphclk,
-	&clk_mout_corebus,
-	&clk_sclk_dmc,
-	&clk_aclk_cored,
-	&clk_aclk_corep,
-	&clk_aclk_acp,
-	&clk_pclk_acp,
-	&clk_vpllsrc,
-	&clk_sclk_vpll,
-	&clk_aclk_200,
-	&clk_aclk_100,
-	&clk_aclk_160,
-	&clk_aclk_133,
-	&clk_dout_mmc0,
-	&clk_dout_mmc1,
-	&clk_dout_mmc2,
-	&clk_dout_mmc3,
-	&clk_dout_mmc4,
-	&clk_mout_mfc0,
-	&clk_mout_mfc1,
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
-	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-	.get_rate = exynos4_fout_apll_get_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
-	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
-				__raw_readl(S5P_EPLL_CON1), pll_4600);
-
-	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
-	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
-				__raw_readl(S5P_VPLL_CON1), pll_4650c);
-
-	clk_fout_apll.ops = &exynos4_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&clk_aclk_133.clk);
-
-	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	/* Nothing here yet */
-};
-
-void __init exynos4_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	s3c_pwmclk_init();
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,254 +0,0 @@
-/* linux/arch/arm/mach-exynos4/cpu.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/sched.h>
-#include <linux/sysdev.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/exynos4.h>
-#include <plat/adc-core.h>
-#include <plat/sdhci.h>
-#include <plat/fb-core.h>
-#include <plat/fimc-core.h>
-#include <plat/iic-core.h>
-#include <plat/reset.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-pmu.h>
-
-extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
-			 unsigned int irq_start);
-extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
-
-/* Initial IO mappings */
-static struct map_desc exynos4_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
-		.length		= SZ_4K,
-		.type	 	= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSRAM,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_CMU,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
-		.length		= SZ_128K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_PMU,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_PMU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_COMBINER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_L2CC,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_L2CC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO1,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO1),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO2,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO2),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO3,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO3),
-		.length		= SZ_256,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_DMC0,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC0),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_HSPHY),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void exynos4_idle(void)
-{
-	if (!need_resched())
-		cpu_do_idle();
-
-	local_irq_enable();
-}
-
-static void exynos4_sw_reset(void)
-{
-	__raw_writel(0x1, S5P_SWRESET);
-}
-
-/*
- * exynos4_map_io
- *
- * register the standard cpu IO areas
- */
-void __init exynos4_map_io(void)
-{
-	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-
-	/* initialize device information early */
-	exynos4_default_sdhci0();
-	exynos4_default_sdhci1();
-	exynos4_default_sdhci2();
-	exynos4_default_sdhci3();
-
-	s3c_adc_setname("samsung-adc-v3");
-
-	s3c_fimc_setname(0, "exynos4-fimc");
-	s3c_fimc_setname(1, "exynos4-fimc");
-	s3c_fimc_setname(2, "exynos4-fimc");
-	s3c_fimc_setname(3, "exynos4-fimc");
-
-	/* The I2C bus controllers are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-	s3c_i2c2_setname("s3c2440-i2c");
-
-	s5p_fb_setname(0, "exynos4-fb");
-}
-
-void __init exynos4_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	exynos4_register_clocks();
-	exynos4_setup_clocks();
-}
-
-static void exynos4_gic_irq_eoi(struct irq_data *d)
-{
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-
-	gic_data->cpu_base = S5P_VA_GIC_CPU +
-			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-}
-
-void __init exynos4_init_irq(void)
-{
-	int irq;
-
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
-
-	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
-
-		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-				COMBINER_IRQ(irq, 0));
-		combiner_cascade_irq(irq, IRQ_SPI(irq));
-	}
-
-	/* The parameters of s5p_init_irq() are for VIC init.
-	 * Theses parameters should be NULL and 0 because EXYNOS4
-	 * uses GIC instead of VIC.
-	 */
-	s5p_init_irq(NULL, 0);
-}
-
-struct sysdev_class exynos4_sysclass = {
-	.name	= "exynos4-core",
-};
-
-static struct sys_device exynos4_sysdev = {
-	.cls	= &exynos4_sysclass,
-};
-
-static int __init exynos4_core_init(void)
-{
-	return sysdev_class_register(&exynos4_sysclass);
-}
-
-core_initcall(exynos4_core_init);
-
-#ifdef CONFIG_CACHE_L2X0
-static int __init exynos4_l2x0_cache_init(void)
-{
-	/* TAG, Data Latency Control: 2cycle */
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
-
-	/* L2X0 Prefetch Control */
-	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
-
-	/* L2X0 Power Control */
-	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
-		     S5P_VA_L2CC + L2X0_POWER_CTRL);
-
-	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
-
-	return 0;
-}
-
-early_initcall(exynos4_l2x0_cache_init);
-#endif
-
-int __init exynos4_init(void)
-{
-	printk(KERN_INFO "EXYNOS4: Initializing architecture\n");
-
-	/* set idle function */
-	pm_idle = exynos4_idle;
-
-	/* set sw_reset function */
-	s5p_reset_hook = exynos4_sw_reset;
-
-	return sysdev_register(&exynos4_sysdev);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/cpuidle.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-exynos4/cpuidle.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/cpuidle.h>
-#include <linux/io.h>
-
-#include <asm/proc-fns.h>
-
-static int exynos4_enter_idle(struct cpuidle_device *dev,
-			      struct cpuidle_state *state);
-
-static struct cpuidle_state exynos4_cpuidle_set[] = {
-	[0] = {
-		.enter			= exynos4_enter_idle,
-		.exit_latency		= 1,
-		.target_residency	= 100000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID,
-		.name			= "IDLE",
-		.desc			= "ARM clock gating(WFI)",
-	},
-};
-
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
-static struct cpuidle_driver exynos4_idle_driver = {
-	.name		= "exynos4_idle",
-	.owner		= THIS_MODULE,
-};
-
-static int exynos4_enter_idle(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
-{
-	struct timeval before, after;
-	int idle_time;
-
-	local_irq_disable();
-	do_gettimeofday(&before);
-
-	cpu_do_idle();
-
-	do_gettimeofday(&after);
-	local_irq_enable();
-	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
-		    (after.tv_usec - before.tv_usec);
-
-	return idle_time;
-}
-
-static int __init exynos4_init_cpuidle(void)
-{
-	int i, max_cpuidle_state, cpu_id;
-	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&exynos4_idle_driver);
-
-	for_each_cpu(cpu_id, cpu_online_mask) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		device->state_count = (sizeof(exynos4_cpuidle_set) /
-					       sizeof(struct cpuidle_state));
-
-		max_cpuidle_state = device->state_count;
-
-		for (i = 0; i < max_cpuidle_state; i++) {
-			memcpy(&device->states[i], &exynos4_cpuidle_set[i],
-					sizeof(struct cpuidle_state));
-		}
-
-		if (cpuidle_register_device(device)) {
-			printk(KERN_ERR "CPUidle register device failed\n,");
-			return -EIO;
-		}
-	}
-	return 0;
-}
-device_initcall(exynos4_init_cpuidle);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-ahci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-ahci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-ahci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-ahci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dev-ahci.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - AHCI support
- *
- * 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/clk.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/ahci_platform.h>
-
-#include <plat/cpu.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <mach/regs-pmu.h>
-
-/* PHY Control Register */
-#define SATA_CTRL0		0x0
-/* PHY Link Control Register */
-#define SATA_CTRL1		0x4
-/* PHY Status Register */
-#define SATA_PHY_STATUS		0x8
-
-#define SATA_CTRL0_RX_DATA_VALID(x)	(x << 27)
-#define SATA_CTRL0_SPEED_MODE		(1 << 26)
-#define SATA_CTRL0_M_PHY_CAL		(1 << 19)
-#define SATA_CTRL0_PHY_CMU_RST_N	(1 << 10)
-#define SATA_CTRL0_M_PHY_LN_RST_N	(1 << 9)
-#define SATA_CTRL0_PHY_POR_N		(1 << 8)
-
-#define SATA_CTRL1_RST_PMALIVE_N	(1 << 8)
-#define SATA_CTRL1_RST_RXOOB_N		(1 << 7)
-#define SATA_CTRL1_RST_RX_N		(1 << 6)
-#define SATA_CTRL1_RST_TX_N		(1 << 5)
-
-#define SATA_PHY_STATUS_CMU_OK		(1 << 18)
-#define SATA_PHY_STATUS_LANE_OK		(1 << 16)
-
-#define LANE0		0x200
-#define COM_LANE	0xA00
-
-#define HOST_PORTS_IMPL	0xC
-#define SCLK_SATA_FREQ	(67 * MHZ)
-
-static void __iomem *phy_base, *phy_ctrl;
-
-struct phy_reg {
-	u8	reg;
-	u8	val;
-};
-
-/* SATA PHY setup */
-static const struct phy_reg exynos4_sataphy_cmu[] = {
-	{ 0x00, 0x06 }, { 0x02, 0x80 }, { 0x22, 0xa0 }, { 0x23, 0x42 },
-	{ 0x2e, 0x04 }, { 0x2f, 0x50 }, { 0x30, 0x70 }, { 0x31, 0x02 },
-	{ 0x32, 0x25 }, { 0x33, 0x40 }, { 0x34, 0x01 }, { 0x35, 0x40 },
-	{ 0x61, 0x2e }, { 0x63, 0x5e }, { 0x65, 0x42 }, { 0x66, 0xd1 },
-	{ 0x67, 0x20 }, { 0x68, 0x28 }, { 0x69, 0x78 }, { 0x6a, 0x04 },
-	{ 0x6b, 0xc8 }, { 0x6c, 0x06 },
-};
-
-static const struct phy_reg exynos4_sataphy_lane[] = {
-	{ 0x00, 0x02 }, { 0x05, 0x10 }, { 0x06, 0x84 }, { 0x07, 0x04 },
-	{ 0x08, 0xe0 }, { 0x10, 0x23 }, { 0x13, 0x05 }, { 0x14, 0x30 },
-	{ 0x15, 0x00 }, { 0x17, 0x70 }, { 0x18, 0xf2 }, { 0x19, 0x1e },
-	{ 0x1a, 0x18 }, { 0x1b, 0x0d }, { 0x1c, 0x08 }, { 0x50, 0x60 },
-	{ 0x51, 0x0f },
-};
-
-static const struct phy_reg exynos4_sataphy_comlane[] = {
-	{ 0x01, 0x20 }, { 0x03, 0x40 }, { 0x04, 0x3c }, { 0x05, 0x7d },
-	{ 0x06, 0x1d }, { 0x07, 0xcf }, { 0x08, 0x05 }, { 0x09, 0x63 },
-	{ 0x0a, 0x29 }, { 0x0b, 0xc4 }, { 0x0c, 0x01 }, { 0x0d, 0x03 },
-	{ 0x0e, 0x28 }, { 0x0f, 0x98 }, { 0x10, 0x19 }, { 0x13, 0x80 },
-	{ 0x14, 0xf0 }, { 0x15, 0xd0 }, { 0x39, 0xa0 }, { 0x3a, 0xa0 },
-	{ 0x3b, 0xa0 }, { 0x3c, 0xa0 }, { 0x3d, 0xa0 }, { 0x3e, 0xa0 },
-	{ 0x3f, 0xa0 }, { 0x40, 0x42 }, { 0x42, 0x80 }, { 0x43, 0x58 },
-	{ 0x45, 0x44 }, { 0x46, 0x5c }, { 0x47, 0x86 }, { 0x48, 0x8d },
-	{ 0x49, 0xd0 }, { 0x4a, 0x09 }, { 0x4b, 0x90 }, { 0x4c, 0x07 },
-	{ 0x4d, 0x40 }, { 0x51, 0x20 }, { 0x52, 0x32 }, { 0x7f, 0xd8 },
-	{ 0x80, 0x1a }, { 0x81, 0xff }, { 0x82, 0x11 }, { 0x83, 0x00 },
-	{ 0x87, 0xf0 }, { 0x87, 0xff }, { 0x87, 0xff }, { 0x87, 0xff },
-	{ 0x87, 0xff }, { 0x8c, 0x1c }, { 0x8d, 0xc2 }, { 0x8e, 0xc3 },
-	{ 0x8f, 0x3f }, { 0x90, 0x0a }, { 0x96, 0xf8 },
-};
-
-static int wait_for_phy_ready(void __iomem *reg, unsigned long bit)
-{
-	unsigned long timeout;
-
-	/* wait for maximum of 3 sec */
-	timeout = jiffies + msecs_to_jiffies(3000);
-	while (!(__raw_readl(reg) & bit)) {
-		if (time_after(jiffies, timeout))
-			return -1;
-		cpu_relax();
-	}
-	return 0;
-}
-
-static int ahci_phy_init(void __iomem *mmio)
-{
-	int i, ctrl0;
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_cmu); i++)
-		__raw_writeb(exynos4_sataphy_cmu[i].val,
-		phy_base + (exynos4_sataphy_cmu[i].reg * 4));
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_lane); i++)
-		__raw_writeb(exynos4_sataphy_lane[i].val,
-		phy_base + (LANE0 + exynos4_sataphy_lane[i].reg) * 4);
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_comlane); i++)
-		__raw_writeb(exynos4_sataphy_comlane[i].val,
-		phy_base + (COM_LANE + exynos4_sataphy_comlane[i].reg) * 4);
-
-	__raw_writeb(0x07, phy_base);
-
-	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
-	ctrl0 |= SATA_CTRL0_PHY_CMU_RST_N;
-	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
-
-	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
-				SATA_PHY_STATUS_CMU_OK) < 0) {
-		printk(KERN_ERR "PHY CMU not ready\n");
-		return -EBUSY;
-	}
-
-	__raw_writeb(0x03, phy_base + (COM_LANE * 4));
-
-	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
-	ctrl0 |= SATA_CTRL0_M_PHY_LN_RST_N;
-	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
-
-	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
-				SATA_PHY_STATUS_LANE_OK) < 0) {
-		printk(KERN_ERR "PHY LANE not ready\n");
-		return -EBUSY;
-	}
-
-	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
-	ctrl0 |= SATA_CTRL0_M_PHY_CAL;
-	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
-
-	return 0;
-}
-
-static int exynos4_ahci_init(struct device *dev, void __iomem *mmio)
-{
-	struct clk *clk_sata, *clk_sataphy, *clk_sclk_sata;
-	int val, ret;
-
-	phy_base = ioremap(EXYNOS4_PA_SATAPHY, SZ_64K);
-	if (!phy_base) {
-		dev_err(dev, "failed to allocate memory for SATA PHY\n");
-		return -ENOMEM;
-	}
-
-	phy_ctrl = ioremap(EXYNOS4_PA_SATAPHY_CTRL, SZ_16);
-	if (!phy_ctrl) {
-		dev_err(dev, "failed to allocate memory for SATA PHY CTRL\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	clk_sata = clk_get(dev, "sata");
-	if (IS_ERR(clk_sata)) {
-		dev_err(dev, "failed to get sata clock\n");
-		ret = PTR_ERR(clk_sata);
-		clk_sata = NULL;
-		goto err2;
-
-	}
-	clk_enable(clk_sata);
-
-	clk_sataphy = clk_get(dev, "sataphy");
-	if (IS_ERR(clk_sataphy)) {
-		dev_err(dev, "failed to get sataphy clock\n");
-		ret = PTR_ERR(clk_sataphy);
-		clk_sataphy = NULL;
-		goto err3;
-	}
-	clk_enable(clk_sataphy);
-
-	clk_sclk_sata = clk_get(dev, "sclk_sata");
-	if (IS_ERR(clk_sclk_sata)) {
-		dev_err(dev, "failed to get sclk_sata\n");
-		ret = PTR_ERR(clk_sclk_sata);
-		clk_sclk_sata = NULL;
-		goto err4;
-	}
-	clk_enable(clk_sclk_sata);
-	clk_set_rate(clk_sclk_sata, SCLK_SATA_FREQ);
-
-	__raw_writel(S5P_PMU_SATA_PHY_CONTROL_EN, S5P_PMU_SATA_PHY_CONTROL);
-
-	/* Enable PHY link control */
-	val = SATA_CTRL1_RST_PMALIVE_N | SATA_CTRL1_RST_RXOOB_N |
-			SATA_CTRL1_RST_RX_N | SATA_CTRL1_RST_TX_N;
-	__raw_writel(val, phy_ctrl + SATA_CTRL1);
-
-	/* Set communication speed as 3Gbps and enable PHY power */
-	val = SATA_CTRL0_RX_DATA_VALID(3) | SATA_CTRL0_SPEED_MODE |
-			SATA_CTRL0_PHY_POR_N;
-	__raw_writel(val, phy_ctrl + SATA_CTRL0);
-
-	/* Port0 is available */
-	__raw_writel(0x1, mmio + HOST_PORTS_IMPL);
-
-	return ahci_phy_init(mmio);
-
-err4:
-	clk_disable(clk_sataphy);
-	clk_put(clk_sataphy);
-err3:
-	clk_disable(clk_sata);
-	clk_put(clk_sata);
-err2:
-	iounmap(phy_ctrl);
-err1:
-	iounmap(phy_base);
-
-	return ret;
-}
-
-static struct ahci_platform_data exynos4_ahci_pdata = {
-	.init = exynos4_ahci_init,
-};
-
-static struct resource exynos4_ahci_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SATA,
-		.end	= EXYNOS4_PA_SATA + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_SATA,
-		.end	= IRQ_SATA,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_ahci = {
-	.name		= "ahci",
-	.id		= -1,
-	.resource	= exynos4_ahci_resource,
-	.num_resources	= ARRAY_SIZE(exynos4_ahci_resource),
-	.dev		= {
-		.platform_data		= &exynos4_ahci_pdata,
-		.dma_mask		= &exynos4_ahci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-audio.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-audio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,369 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dev-audio.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-#include <mach/regs-audss.h>
-
-static const char *rclksrc[] = {
-	[0] = "busclk",
-	[1] = "i2sclk",
-};
-
-static int exynos4_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 7, S3C_GPIO_SFN(2));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(2));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(4));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
-	.cfg_gpio = exynos4_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
-					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc,
-			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
-		},
-	},
-};
-
-static struct resource exynos4_i2s0_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_I2S0,
-		.end	= EXYNOS4_PA_I2S0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S0_TX,
-		.end	= DMACH_I2S0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S0_RX,
-		.end	= DMACH_I2S0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_I2S0S_TX,
-		.end	= DMACH_I2S0S_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_i2s0 = {
-	.name = "samsung-i2s",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(exynos4_i2s0_resource),
-	.resource = exynos4_i2s0_resource,
-	.dev = {
-		.platform_data = &i2sv5_pdata,
-	},
-};
-
-static const char *rclksrc_v3[] = {
-	[0] = "sclk_i2s",
-	[1] = "no_such_clock",
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
-	.cfg_gpio = exynos4_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_NO_MUXPSR,
-			.src_clk = rclksrc_v3,
-		},
-	},
-};
-
-static struct resource exynos4_i2s1_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_I2S1,
-		.end	= EXYNOS4_PA_I2S1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S1_TX,
-		.end	= DMACH_I2S1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S1_RX,
-		.end	= DMACH_I2S1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_i2s1 = {
-	.name = "samsung-i2s",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(exynos4_i2s1_resource),
-	.resource = exynos4_i2s1_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-static struct resource exynos4_i2s2_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_I2S2,
-		.end	= EXYNOS4_PA_I2S2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S2_TX,
-		.end	= DMACH_I2S2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S2_RX,
-		.end	= DMACH_I2S2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_i2s2 = {
-	.name = "samsung-i2s",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(exynos4_i2s2_resource),
-	.resource = exynos4_i2s2_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int exynos4_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(3));
-		break;
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = exynos4_pcm_cfg_gpio,
-};
-
-static struct resource exynos4_pcm0_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PCM0,
-		.end	= EXYNOS4_PA_PCM0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM0_TX,
-		.end	= DMACH_PCM0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM0_RX,
-		.end	= DMACH_PCM0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_pcm0 = {
-	.name = "samsung-pcm",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(exynos4_pcm0_resource),
-	.resource = exynos4_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource exynos4_pcm1_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PCM1,
-		.end	= EXYNOS4_PA_PCM1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM1_TX,
-		.end	= DMACH_PCM1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM1_RX,
-		.end	= DMACH_PCM1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_pcm1 = {
-	.name = "samsung-pcm",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(exynos4_pcm1_resource),
-	.resource = exynos4_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource exynos4_pcm2_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PCM2,
-		.end	= EXYNOS4_PA_PCM2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM2_TX,
-		.end	= DMACH_PCM2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM2_RX,
-		.end	= DMACH_PCM2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device exynos4_device_pcm2 = {
-	.name = "samsung-pcm",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(exynos4_pcm2_resource),
-	.resource = exynos4_pcm2_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-/* AC97 Controller platform devices */
-
-static int exynos4_ac97_cfg_gpio(struct platform_device *pdev)
-{
-	return s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource exynos4_ac97_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_AC97,
-		.end	= EXYNOS4_PA_AC97 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_AC97_PCMOUT,
-		.end	= DMACH_AC97_PCMOUT,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_AC97_PCMIN,
-		.end	= DMACH_AC97_PCMIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_AC97_MICIN,
-		.end	= DMACH_AC97_MICIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[4] = {
-		.start	= IRQ_AC97,
-		.end	= IRQ_AC97,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
-	.cfg_gpio = exynos4_ac97_cfg_gpio,
-};
-
-static u64 exynos4_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_ac97 = {
-	.name = "samsung-ac97",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(exynos4_ac97_resource),
-	.resource = exynos4_ac97_resource,
-	.dev = {
-		.platform_data = &s3c_ac97_pdata,
-		.dma_mask = &exynos4_ac97_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-/* S/PDIF Controller platform_device */
-
-static int exynos4_spdif_cfg_gpio(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(4));
-
-	return 0;
-}
-
-static struct resource exynos4_spdif_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SPDIF,
-		.end	= EXYNOS4_PA_SPDIF + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_SPDIF,
-		.end	= DMACH_SPDIF,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-static struct s3c_audio_pdata samsung_spdif_pdata = {
-	.cfg_gpio = exynos4_spdif_cfg_gpio,
-};
-
-static u64 exynos4_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_spdif = {
-	.name = "samsung-spdif",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(exynos4_spdif_resource),
-	.resource = exynos4_spdif_resource,
-	.dev = {
-		.platform_data = &samsung_spdif_pdata,
-		.dma_mask = &exynos4_spdif_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-dwmci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-dwmci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-dwmci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-dwmci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/dev-dwmci.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Platform device for Synopsys DesignWare Mobile Storage IP
- *
- * 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/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/mmc/dw_mmc.h>
-
-#include <plat/devs.h>
-
-#include <mach/map.h>
-
-static int exynos4_dwmci_get_bus_wd(u32 slot_id)
-{
-	return 4;
-}
-
-static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
-{
-	return 0;
-}
-
-static struct resource exynos4_dwmci_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_DWMCI,
-		.end	= EXYNOS4_PA_DWMCI + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DWMCI,
-		.end	= IRQ_DWMCI,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct dw_mci_board exynos4_dwci_pdata = {
-	.num_slots			= 1,
-	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
-	.bus_hz				= 80 * 1000 * 1000,
-	.detect_delay_ms	= 200,
-	.init				= exynos4_dwmci_init,
-	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
-};
-
-static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_dwmci = {
-	.name		= "dw_mmc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
-	.resource	= exynos4_dwmci_resource,
-	.dev		= {
-		.dma_mask		= &exynos4_dwmci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data	= &exynos4_dwci_pdata,
-	},
-};
-
-void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
-{
-	struct dw_mci_board *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
-			&exynos4_device_dwmci);
-
-	if (!npd->init)
-		npd->init = exynos4_dwmci_init;
-	if (!npd->get_bus_wd)
-		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-pd.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-pd.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-pd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dev-pd.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Power Domain support
- *
- * 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/io.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-
-#include <mach/regs-pmu.h>
-
-#include <plat/pd.h>
-
-static int exynos4_pd_enable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
-		!= S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s enable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-static int exynos4_pd_disable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(0, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s disable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-struct platform_device exynos4_device_pd[] = {
-	{
-		.name		= "samsung-pd",
-		.id		= 0,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_MFC_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 1,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_G3D_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 2,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_LCD0_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 3,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_LCD1_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 4,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_TV_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 5,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_CAM_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 6,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= exynos4_pd_enable,
-				.disable	= exynos4_pd_disable,
-				.base		= S5P_PMU_GPS_CONF,
-			},
-		},
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-sysmmu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-sysmmu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dev-sysmmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - System MMU support
- *
- * 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/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/sysmmu.h>
-#include <plat/s5p-clock.h>
-
-/* These names must be equal to the clock names in mach-exynos4/clock.c */
-const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
-	"SYSMMU_MDMA"	,
-	"SYSMMU_SSS"	,
-	"SYSMMU_FIMC0"	,
-	"SYSMMU_FIMC1"	,
-	"SYSMMU_FIMC2"	,
-	"SYSMMU_FIMC3"	,
-	"SYSMMU_JPEG"	,
-	"SYSMMU_FIMD0"	,
-	"SYSMMU_FIMD1"	,
-	"SYSMMU_PCIe"	,
-	"SYSMMU_G2D"	,
-	"SYSMMU_ROTATOR",
-	"SYSMMU_MDMA2"	,
-	"SYSMMU_TV"	,
-	"SYSMMU_MFC_L"	,
-	"SYSMMU_MFC_R"	,
-};
-
-static struct resource exynos4_sysmmu_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SYSMMU_MDMA,
-		.end	= EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_SYSMMU_MDMA0_0,
-		.end	= IRQ_SYSMMU_MDMA0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= EXYNOS4_PA_SYSMMU_SSS,
-		.end	= EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[3] = {
-		.start	= IRQ_SYSMMU_SSS_0,
-		.end	= IRQ_SYSMMU_SSS_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[4] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMC0,
-		.end	= EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[5] = {
-		.start	= IRQ_SYSMMU_FIMC0_0,
-		.end	= IRQ_SYSMMU_FIMC0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[6] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMC1,
-		.end	= EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[7] = {
-		.start	= IRQ_SYSMMU_FIMC1_0,
-		.end	= IRQ_SYSMMU_FIMC1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[8] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMC2,
-		.end	= EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[9] = {
-		.start	= IRQ_SYSMMU_FIMC2_0,
-		.end	= IRQ_SYSMMU_FIMC2_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[10] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMC3,
-		.end	= EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[11] = {
-		.start	= IRQ_SYSMMU_FIMC3_0,
-		.end	= IRQ_SYSMMU_FIMC3_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[12] = {
-		.start	= EXYNOS4_PA_SYSMMU_JPEG,
-		.end	= EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[13] = {
-		.start	= IRQ_SYSMMU_JPEG_0,
-		.end	= IRQ_SYSMMU_JPEG_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[14] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMD0,
-		.end	= EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[15] = {
-		.start	= IRQ_SYSMMU_LCD0_M0_0,
-		.end	= IRQ_SYSMMU_LCD0_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[16] = {
-		.start	= EXYNOS4_PA_SYSMMU_FIMD1,
-		.end	= EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[17] = {
-		.start	= IRQ_SYSMMU_LCD1_M1_0,
-		.end	= IRQ_SYSMMU_LCD1_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[18] = {
-		.start	= EXYNOS4_PA_SYSMMU_PCIe,
-		.end	= EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[19] = {
-		.start	= IRQ_SYSMMU_PCIE_0,
-		.end	= IRQ_SYSMMU_PCIE_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[20] = {
-		.start	= EXYNOS4_PA_SYSMMU_G2D,
-		.end	= EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[21] = {
-		.start	= IRQ_SYSMMU_2D_0,
-		.end	= IRQ_SYSMMU_2D_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[22] = {
-		.start	= EXYNOS4_PA_SYSMMU_ROTATOR,
-		.end	= EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[23] = {
-		.start	= IRQ_SYSMMU_ROTATOR_0,
-		.end	= IRQ_SYSMMU_ROTATOR_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[24] = {
-		.start	= EXYNOS4_PA_SYSMMU_MDMA2,
-		.end	= EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[25] = {
-		.start	= IRQ_SYSMMU_MDMA1_0,
-		.end	= IRQ_SYSMMU_MDMA1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[26] = {
-		.start	= EXYNOS4_PA_SYSMMU_TV,
-		.end	= EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[27] = {
-		.start	= IRQ_SYSMMU_TV_M0_0,
-		.end	= IRQ_SYSMMU_TV_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[28] = {
-		.start	= EXYNOS4_PA_SYSMMU_MFC_L,
-		.end	= EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[29] = {
-		.start	= IRQ_SYSMMU_MFC_M0_0,
-		.end	= IRQ_SYSMMU_MFC_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[30] = {
-		.start	= EXYNOS4_PA_SYSMMU_MFC_R,
-		.end	= EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[31] = {
-		.start	= IRQ_SYSMMU_MFC_M1_0,
-		.end	= IRQ_SYSMMU_MFC_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device exynos4_device_sysmmu = {
-	.name		= "s5p-sysmmu",
-	.id		= 32,
-	.num_resources	= ARRAY_SIZE(exynos4_sysmmu_resource),
-	.resource	= exynos4_sysmmu_resource,
-};
-EXPORT_SYMBOL(exynos4_device_sysmmu);
-
-static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
-{
-	sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
-	if (IS_ERR(sysmmu_clk[ips]))
-		sysmmu_clk[ips] = NULL;
-	else
-		clk_put(sysmmu_clk[ips]);
-}
-
-void sysmmu_clk_enable(sysmmu_ips ips)
-{
-	if (sysmmu_clk[ips])
-		clk_enable(sysmmu_clk[ips]);
-}
-
-void sysmmu_clk_disable(sysmmu_ips ips)
-{
-	if (sysmmu_clk[ips])
-		clk_disable(sysmmu_clk[ips]);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dma.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,172 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
-static struct resource exynos4_pdma0_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA0,
-		.end	= EXYNOS4_PA_PDMA0 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM2_RX,
-		[3] = DMACH_PCM2_TX,
-		[4] = DMACH_MSM_REQ0,
-		[5] = DMACH_MSM_REQ2,
-		[6] = DMACH_SPI0_RX,
-		[7] = DMACH_SPI0_TX,
-		[8] = DMACH_SPI2_RX,
-		[9] = DMACH_SPI2_TX,
-		[10] = DMACH_I2S0S_TX,
-		[11] = DMACH_I2S0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S2_RX,
-		[14] = DMACH_I2S2_TX,
-		[15] = DMACH_UART0_RX,
-		[16] = DMACH_UART0_TX,
-		[17] = DMACH_UART2_RX,
-		[18] = DMACH_UART2_TX,
-		[19] = DMACH_UART4_RX,
-		[20] = DMACH_UART4_TX,
-		[21] = DMACH_SLIMBUS0_RX,
-		[22] = DMACH_SLIMBUS0_TX,
-		[23] = DMACH_SLIMBUS2_RX,
-		[24] = DMACH_SLIMBUS2_TX,
-		[25] = DMACH_SLIMBUS4_RX,
-		[26] = DMACH_SLIMBUS4_TX,
-		[27] = DMACH_AC97_MICIN,
-		[28] = DMACH_AC97_PCMIN,
-		[29] = DMACH_AC97_PCMOUT,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device exynos4_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma0_resource),
-	.resource	= exynos4_pdma0_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &exynos4_pdma0_pdata,
-	},
-};
-
-static struct resource exynos4_pdma1_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA1,
-		.end	= EXYNOS4_PA_PDMA1 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM1_RX,
-		[3] = DMACH_PCM1_TX,
-		[4] = DMACH_MSM_REQ1,
-		[5] = DMACH_MSM_REQ3,
-		[6] = DMACH_SPI1_RX,
-		[7] = DMACH_SPI1_TX,
-		[8] = DMACH_I2S0S_TX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S1_RX,
-		[12] = DMACH_I2S1_TX,
-		[13] = DMACH_UART0_RX,
-		[14] = DMACH_UART0_TX,
-		[15] = DMACH_UART1_RX,
-		[16] = DMACH_UART1_TX,
-		[17] = DMACH_UART3_RX,
-		[18] = DMACH_UART3_TX,
-		[19] = DMACH_SLIMBUS1_RX,
-		[20] = DMACH_SLIMBUS1_TX,
-		[21] = DMACH_SLIMBUS3_RX,
-		[22] = DMACH_SLIMBUS3_TX,
-		[23] = DMACH_SLIMBUS5_RX,
-		[24] = DMACH_SLIMBUS5_TX,
-		[25] = DMACH_SLIMBUS0AUX_RX,
-		[26] = DMACH_SLIMBUS0AUX_TX,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device exynos4_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma1_resource),
-	.resource	= exynos4_pdma1_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &exynos4_pdma1_pdata,
-	},
-};
-
-static struct platform_device *exynos4_dmacs[] __initdata = {
-	&exynos4_device_pdma0,
-	&exynos4_device_pdma1,
-};
-
-static int __init exynos4_dma_init(void)
-{
-	platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
-
-	return 0;
-}
-arch_initcall(exynos4_dma_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/headsmp.S linux-libre-3.2-gnu1/arch/arm/mach-exynos4/headsmp.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/headsmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/headsmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- *  linux/arch/arm/mach-exynos4/headsmp.S
- *
- *  Cloned from linux/arch/arm/mach-realview/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  All Rights Reserved
- *
- * 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/linkage.h>
-#include <linux/init.h>
-
-	__CPUINIT
-
-/*
- * exynos4 specific entry point for secondary CPUs.  This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(exynos4_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-1:	.long	.
-	.long	pen_release
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/hotplug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/* linux arch/arm/mach-exynos4/hotplug.c
- *
- *  Cloned from linux/arch/arm/mach-realview/hotplug.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * 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/errno.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-
-#include <mach/regs-pmu.h>
-
-extern volatile int pen_release;
-
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
-
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, %3\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	  : "=&r" (v)
-	  : "r" (0), "Ir" (CR_C), "Ir" (0x40)
-	  : "cc");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
-
-	asm volatile(
-	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	  : "=&r" (v)
-	  : "Ir" (CR_C), "Ir" (0x40)
-	  : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-	for (;;) {
-
-		/* make cpu1 to be turned off at next WFI command */
-		if (cpu == 1)
-			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
-
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		if (pen_release == cpu) {
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		}
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void platform_cpu_die(unsigned int cpu)
-{
-	int spurious = 0;
-
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
-
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
-
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-}
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/debug-macro.S
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
- * 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.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rp, rv
-		ldr	\rp, = S3C_PA_UART
-		ldr	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-#define fifo_full fifo_full_s5pv210
-#define fifo_level fifo_level_s5pv210
-
-#include <plat/debug-macro.S>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/dwmci.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/dwmci.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/dwmci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/dwmci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Synopsys DesignWare Mobile Storage for EXYNOS4210
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_ARCH_DWMCI_H
-#define __ASM_ARM_ARCH_DWMCI_H __FILE__
-
-#include <linux/mmc/dw_mmc.h>
-
-extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
-
-#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/entry-macro.S
- *
- * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for EXYNOS4 platforms
- *
- * 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 <mach/hardware.h>
-#include <mach/map.h>
-#include <asm/hardware/gic.h>
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		mrc     p15, 0, \tmp, c0, c0, 5
-		and     \tmp, \tmp, #3
-		cmp     \tmp, #1
-		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-		addne	\irqnr, \irqnr, #32
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,156 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/gpio.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-/* Practically, GPIO banks up to GPZ are the configurable gpio banks */
-
-/* GPIO bank sizes */
-#define EXYNOS4_GPIO_A0_NR	(8)
-#define EXYNOS4_GPIO_A1_NR	(6)
-#define EXYNOS4_GPIO_B_NR	(8)
-#define EXYNOS4_GPIO_C0_NR	(5)
-#define EXYNOS4_GPIO_C1_NR	(5)
-#define EXYNOS4_GPIO_D0_NR	(4)
-#define EXYNOS4_GPIO_D1_NR	(4)
-#define EXYNOS4_GPIO_E0_NR	(5)
-#define EXYNOS4_GPIO_E1_NR	(8)
-#define EXYNOS4_GPIO_E2_NR	(6)
-#define EXYNOS4_GPIO_E3_NR	(8)
-#define EXYNOS4_GPIO_E4_NR	(8)
-#define EXYNOS4_GPIO_F0_NR	(8)
-#define EXYNOS4_GPIO_F1_NR	(8)
-#define EXYNOS4_GPIO_F2_NR	(8)
-#define EXYNOS4_GPIO_F3_NR	(6)
-#define EXYNOS4_GPIO_J0_NR	(8)
-#define EXYNOS4_GPIO_J1_NR	(5)
-#define EXYNOS4_GPIO_K0_NR	(7)
-#define EXYNOS4_GPIO_K1_NR	(7)
-#define EXYNOS4_GPIO_K2_NR	(7)
-#define EXYNOS4_GPIO_K3_NR	(7)
-#define EXYNOS4_GPIO_L0_NR	(8)
-#define EXYNOS4_GPIO_L1_NR	(3)
-#define EXYNOS4_GPIO_L2_NR	(8)
-#define EXYNOS4_GPIO_X0_NR	(8)
-#define EXYNOS4_GPIO_X1_NR	(8)
-#define EXYNOS4_GPIO_X2_NR	(8)
-#define EXYNOS4_GPIO_X3_NR	(8)
-#define EXYNOS4_GPIO_Y0_NR	(6)
-#define EXYNOS4_GPIO_Y1_NR	(4)
-#define EXYNOS4_GPIO_Y2_NR	(6)
-#define EXYNOS4_GPIO_Y3_NR	(8)
-#define EXYNOS4_GPIO_Y4_NR	(8)
-#define EXYNOS4_GPIO_Y5_NR	(8)
-#define EXYNOS4_GPIO_Y6_NR	(8)
-#define EXYNOS4_GPIO_Z_NR	(7)
-
-/* GPIO bank numbers */
-
-#define EXYNOS4_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	EXYNOS4_GPIO_A0_START	= 0,
-	EXYNOS4_GPIO_A1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A0),
-	EXYNOS4_GPIO_B_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A1),
-	EXYNOS4_GPIO_C0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_B),
-	EXYNOS4_GPIO_C1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C0),
-	EXYNOS4_GPIO_D0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C1),
-	EXYNOS4_GPIO_D1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D0),
-	EXYNOS4_GPIO_E0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D1),
-	EXYNOS4_GPIO_E1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E0),
-	EXYNOS4_GPIO_E2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E1),
-	EXYNOS4_GPIO_E3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E2),
-	EXYNOS4_GPIO_E4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E3),
-	EXYNOS4_GPIO_F0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E4),
-	EXYNOS4_GPIO_F1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F0),
-	EXYNOS4_GPIO_F2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F1),
-	EXYNOS4_GPIO_F3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F2),
-	EXYNOS4_GPIO_J0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F3),
-	EXYNOS4_GPIO_J1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J0),
-	EXYNOS4_GPIO_K0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J1),
-	EXYNOS4_GPIO_K1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K0),
-	EXYNOS4_GPIO_K2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K1),
-	EXYNOS4_GPIO_K3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K2),
-	EXYNOS4_GPIO_L0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K3),
-	EXYNOS4_GPIO_L1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L0),
-	EXYNOS4_GPIO_L2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L1),
-	EXYNOS4_GPIO_X0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L2),
-	EXYNOS4_GPIO_X1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X0),
-	EXYNOS4_GPIO_X2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X1),
-	EXYNOS4_GPIO_X3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X2),
-	EXYNOS4_GPIO_Y0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X3),
-	EXYNOS4_GPIO_Y1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y0),
-	EXYNOS4_GPIO_Y2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y1),
-	EXYNOS4_GPIO_Y3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y2),
-	EXYNOS4_GPIO_Y4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y3),
-	EXYNOS4_GPIO_Y5_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y4),
-	EXYNOS4_GPIO_Y6_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y5),
-	EXYNOS4_GPIO_Z_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y6),
-};
-
-/* EXYNOS4 GPIO number definitions */
-#define EXYNOS4_GPA0(_nr)	(EXYNOS4_GPIO_A0_START + (_nr))
-#define EXYNOS4_GPA1(_nr)	(EXYNOS4_GPIO_A1_START + (_nr))
-#define EXYNOS4_GPB(_nr)	(EXYNOS4_GPIO_B_START + (_nr))
-#define EXYNOS4_GPC0(_nr)	(EXYNOS4_GPIO_C0_START + (_nr))
-#define EXYNOS4_GPC1(_nr)	(EXYNOS4_GPIO_C1_START + (_nr))
-#define EXYNOS4_GPD0(_nr)	(EXYNOS4_GPIO_D0_START + (_nr))
-#define EXYNOS4_GPD1(_nr)	(EXYNOS4_GPIO_D1_START + (_nr))
-#define EXYNOS4_GPE0(_nr)	(EXYNOS4_GPIO_E0_START + (_nr))
-#define EXYNOS4_GPE1(_nr)	(EXYNOS4_GPIO_E1_START + (_nr))
-#define EXYNOS4_GPE2(_nr)	(EXYNOS4_GPIO_E2_START + (_nr))
-#define EXYNOS4_GPE3(_nr)	(EXYNOS4_GPIO_E3_START + (_nr))
-#define EXYNOS4_GPE4(_nr)	(EXYNOS4_GPIO_E4_START + (_nr))
-#define EXYNOS4_GPF0(_nr)	(EXYNOS4_GPIO_F0_START + (_nr))
-#define EXYNOS4_GPF1(_nr)	(EXYNOS4_GPIO_F1_START + (_nr))
-#define EXYNOS4_GPF2(_nr)	(EXYNOS4_GPIO_F2_START + (_nr))
-#define EXYNOS4_GPF3(_nr)	(EXYNOS4_GPIO_F3_START + (_nr))
-#define EXYNOS4_GPJ0(_nr)	(EXYNOS4_GPIO_J0_START + (_nr))
-#define EXYNOS4_GPJ1(_nr)	(EXYNOS4_GPIO_J1_START + (_nr))
-#define EXYNOS4_GPK0(_nr)	(EXYNOS4_GPIO_K0_START + (_nr))
-#define EXYNOS4_GPK1(_nr)	(EXYNOS4_GPIO_K1_START + (_nr))
-#define EXYNOS4_GPK2(_nr)	(EXYNOS4_GPIO_K2_START + (_nr))
-#define EXYNOS4_GPK3(_nr)	(EXYNOS4_GPIO_K3_START + (_nr))
-#define EXYNOS4_GPL0(_nr)	(EXYNOS4_GPIO_L0_START + (_nr))
-#define EXYNOS4_GPL1(_nr)	(EXYNOS4_GPIO_L1_START + (_nr))
-#define EXYNOS4_GPL2(_nr)	(EXYNOS4_GPIO_L2_START + (_nr))
-#define EXYNOS4_GPX0(_nr)	(EXYNOS4_GPIO_X0_START + (_nr))
-#define EXYNOS4_GPX1(_nr)	(EXYNOS4_GPIO_X1_START + (_nr))
-#define EXYNOS4_GPX2(_nr)	(EXYNOS4_GPIO_X2_START + (_nr))
-#define EXYNOS4_GPX3(_nr)	(EXYNOS4_GPIO_X3_START + (_nr))
-#define EXYNOS4_GPY0(_nr)	(EXYNOS4_GPIO_Y0_START + (_nr))
-#define EXYNOS4_GPY1(_nr)	(EXYNOS4_GPIO_Y1_START + (_nr))
-#define EXYNOS4_GPY2(_nr)	(EXYNOS4_GPIO_Y2_START + (_nr))
-#define EXYNOS4_GPY3(_nr)	(EXYNOS4_GPIO_Y3_START + (_nr))
-#define EXYNOS4_GPY4(_nr)	(EXYNOS4_GPIO_Y4_START + (_nr))
-#define EXYNOS4_GPY5(_nr)	(EXYNOS4_GPIO_Y5_START + (_nr))
-#define EXYNOS4_GPY6(_nr)	(EXYNOS4_GPIO_Y6_START + (_nr))
-#define EXYNOS4_GPZ(_nr)	(EXYNOS4_GPIO_Z_START + (_nr))
-
-/* the end of the EXYNOS4 specific gpios */
-#define EXYNOS4_GPIO_END	(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + 1)
-#define S3C_GPIO_END		EXYNOS4_GPIO_END
-
-/* define the number of gpios we need to the one after the GPZ() range */
-#define ARCH_NR_GPIOS		(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) +	\
-				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/hardware.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Hardware support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/io.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/io.h
- *
- * Default IO routines for EXYNOS4
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H __FILE__
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/irqs.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* PPI: Private Peripheral Interrupt */
-
-#define IRQ_PPI(x)		S5P_IRQ(x+16)
-
-/* SPI: Shared Peripheral Interrupt */
-
-#define IRQ_SPI(x)		S5P_IRQ(x+32)
-
-#define IRQ_EINT0		IRQ_SPI(16)
-#define IRQ_EINT1		IRQ_SPI(17)
-#define IRQ_EINT2		IRQ_SPI(18)
-#define IRQ_EINT3		IRQ_SPI(19)
-#define IRQ_EINT4		IRQ_SPI(20)
-#define IRQ_EINT5		IRQ_SPI(21)
-#define IRQ_EINT6		IRQ_SPI(22)
-#define IRQ_EINT7		IRQ_SPI(23)
-#define IRQ_EINT8		IRQ_SPI(24)
-#define IRQ_EINT9		IRQ_SPI(25)
-#define IRQ_EINT10		IRQ_SPI(26)
-#define IRQ_EINT11		IRQ_SPI(27)
-#define IRQ_EINT12		IRQ_SPI(28)
-#define IRQ_EINT13		IRQ_SPI(29)
-#define IRQ_EINT14		IRQ_SPI(30)
-#define IRQ_EINT15		IRQ_SPI(31)
-#define IRQ_EINT16_31		IRQ_SPI(32)
-
-#define IRQ_PDMA0		IRQ_SPI(35)
-#define IRQ_PDMA1		IRQ_SPI(36)
-#define IRQ_TIMER0_VIC		IRQ_SPI(37)
-#define IRQ_TIMER1_VIC		IRQ_SPI(38)
-#define IRQ_TIMER2_VIC		IRQ_SPI(39)
-#define IRQ_TIMER3_VIC		IRQ_SPI(40)
-#define IRQ_TIMER4_VIC		IRQ_SPI(41)
-#define IRQ_MCT_L0		IRQ_SPI(42)
-#define IRQ_WDT			IRQ_SPI(43)
-#define IRQ_RTC_ALARM		IRQ_SPI(44)
-#define IRQ_RTC_TIC		IRQ_SPI(45)
-#define IRQ_GPIO_XB		IRQ_SPI(46)
-#define IRQ_GPIO_XA		IRQ_SPI(47)
-#define IRQ_MCT_L1		IRQ_SPI(48)
-
-#define IRQ_UART0		IRQ_SPI(52)
-#define IRQ_UART1		IRQ_SPI(53)
-#define IRQ_UART2		IRQ_SPI(54)
-#define IRQ_UART3		IRQ_SPI(55)
-#define IRQ_UART4		IRQ_SPI(56)
-#define IRQ_MCT_G0		IRQ_SPI(57)
-#define IRQ_IIC			IRQ_SPI(58)
-#define IRQ_IIC1		IRQ_SPI(59)
-#define IRQ_IIC2		IRQ_SPI(60)
-#define IRQ_IIC3		IRQ_SPI(61)
-#define IRQ_IIC4		IRQ_SPI(62)
-#define IRQ_IIC5		IRQ_SPI(63)
-#define IRQ_IIC6		IRQ_SPI(64)
-#define IRQ_IIC7		IRQ_SPI(65)
-
-#define IRQ_USB_HOST		IRQ_SPI(70)
-#define IRQ_USB_HSOTG		IRQ_SPI(71)
-#define IRQ_MODEM_IF		IRQ_SPI(72)
-#define IRQ_HSMMC0		IRQ_SPI(73)
-#define IRQ_HSMMC1		IRQ_SPI(74)
-#define IRQ_HSMMC2		IRQ_SPI(75)
-#define IRQ_HSMMC3		IRQ_SPI(76)
-#define IRQ_DWMCI		IRQ_SPI(77)
-
-#define IRQ_MIPI_CSIS0		IRQ_SPI(78)
-#define IRQ_MIPI_CSIS1		IRQ_SPI(80)
-
-#define IRQ_ONENAND_AUDI	IRQ_SPI(82)
-#define IRQ_ROTATOR		IRQ_SPI(83)
-#define IRQ_FIMC0		IRQ_SPI(84)
-#define IRQ_FIMC1		IRQ_SPI(85)
-#define IRQ_FIMC2		IRQ_SPI(86)
-#define IRQ_FIMC3		IRQ_SPI(87)
-#define IRQ_JPEG		IRQ_SPI(88)
-#define IRQ_2D			IRQ_SPI(89)
-#define IRQ_PCIE		IRQ_SPI(90)
-
-#define IRQ_MFC			IRQ_SPI(94)
-
-#define IRQ_AUDIO_SS		IRQ_SPI(96)
-#define IRQ_I2S0		IRQ_SPI(97)
-#define IRQ_I2S1		IRQ_SPI(98)
-#define IRQ_I2S2		IRQ_SPI(99)
-#define IRQ_AC97		IRQ_SPI(100)
-
-#define IRQ_SPDIF		IRQ_SPI(104)
-#define IRQ_ADC0		IRQ_SPI(105)
-#define IRQ_PEN0		IRQ_SPI(106)
-#define IRQ_ADC1		IRQ_SPI(107)
-#define IRQ_PEN1		IRQ_SPI(108)
-#define IRQ_KEYPAD		IRQ_SPI(109)
-#define IRQ_PMU			IRQ_SPI(110)
-#define IRQ_GPS			IRQ_SPI(111)
-#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
-#define IRQ_SLIMBUS		IRQ_SPI(113)
-
-#define IRQ_TSI			IRQ_SPI(115)
-#define IRQ_SATA		IRQ_SPI(116)
-
-#define MAX_IRQ_IN_COMBINER	8
-#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
-#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
-
-#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
-
-#define IRQ_FIMD0_FIFO		COMBINER_IRQ(11, 0)
-#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
-#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
-
-#define MAX_COMBINER_NR		16
-
-#define IRQ_ADC			IRQ_ADC0
-#define IRQ_TC			IRQ_PEN0
-
-#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
-#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
-
-/* optional GPIO interrupts */
-#define S5P_GPIOINT_BASE	(S5P_IRQ_EINT_BASE + 32)
-#define IRQ_GPIO1_NR_GROUPS	16
-#define IRQ_GPIO2_NR_GROUPS	9
-#define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
-
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_GPIO_END + 64)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/map.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-
-/*
- * EXYNOS4 UART offset is 0x10000 but the older S5P SoCs are 0x400.
- * So need to define it, and here is to avoid redefinition warning.
- */
-#define S3C_UART_OFFSET			(0x10000)
-
-#include <plat/map-s5p.h>
-
-#define EXYNOS4_PA_SYSRAM		0x02020000
-
-#define EXYNOS4_PA_FIMC0		0x11800000
-#define EXYNOS4_PA_FIMC1		0x11810000
-#define EXYNOS4_PA_FIMC2		0x11820000
-#define EXYNOS4_PA_FIMC3		0x11830000
-
-#define EXYNOS4_PA_I2S0			0x03830000
-#define EXYNOS4_PA_I2S1			0xE3100000
-#define EXYNOS4_PA_I2S2			0xE2A00000
-
-#define EXYNOS4_PA_PCM0			0x03840000
-#define EXYNOS4_PA_PCM1			0x13980000
-#define EXYNOS4_PA_PCM2			0x13990000
-
-#define EXYNOS4_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
-
-#define EXYNOS4_PA_ONENAND		0x0C000000
-#define EXYNOS4_PA_ONENAND_DMA		0x0C600000
-
-#define EXYNOS4_PA_CHIPID		0x10000000
-
-#define EXYNOS4_PA_SYSCON		0x10010000
-#define EXYNOS4_PA_PMU			0x10020000
-#define EXYNOS4_PA_CMU			0x10030000
-
-#define EXYNOS4_PA_SYSTIMER		0x10050000
-#define EXYNOS4_PA_WATCHDOG		0x10060000
-#define EXYNOS4_PA_RTC			0x10070000
-
-#define EXYNOS4_PA_KEYPAD		0x100A0000
-
-#define EXYNOS4_PA_DMC0			0x10400000
-
-#define EXYNOS4_PA_COMBINER		0x10440000
-
-#define EXYNOS4_PA_GIC_CPU		0x10480000
-#define EXYNOS4_PA_GIC_DIST		0x10490000
-#define EXYNOS4_GIC_BANK_OFFSET		0x8000
-
-#define EXYNOS4_PA_COREPERI		0x10500000
-#define EXYNOS4_PA_TWD			0x10500600
-#define EXYNOS4_PA_L2CC			0x10502000
-
-#define EXYNOS4_PA_MDMA			0x10810000
-#define EXYNOS4_PA_PDMA0		0x12680000
-#define EXYNOS4_PA_PDMA1		0x12690000
-
-#define EXYNOS4_PA_SYSMMU_MDMA		0x10A40000
-#define EXYNOS4_PA_SYSMMU_SSS		0x10A50000
-#define EXYNOS4_PA_SYSMMU_FIMC0		0x11A20000
-#define EXYNOS4_PA_SYSMMU_FIMC1		0x11A30000
-#define EXYNOS4_PA_SYSMMU_FIMC2		0x11A40000
-#define EXYNOS4_PA_SYSMMU_FIMC3		0x11A50000
-#define EXYNOS4_PA_SYSMMU_JPEG		0x11A60000
-#define EXYNOS4_PA_SYSMMU_FIMD0		0x11E20000
-#define EXYNOS4_PA_SYSMMU_FIMD1		0x12220000
-#define EXYNOS4_PA_SYSMMU_PCIe		0x12620000
-#define EXYNOS4_PA_SYSMMU_G2D		0x12A20000
-#define EXYNOS4_PA_SYSMMU_ROTATOR	0x12A30000
-#define EXYNOS4_PA_SYSMMU_MDMA2		0x12A40000
-#define EXYNOS4_PA_SYSMMU_TV		0x12E20000
-#define EXYNOS4_PA_SYSMMU_MFC_L		0x13620000
-#define EXYNOS4_PA_SYSMMU_MFC_R		0x13630000
-
-#define EXYNOS4_PA_GPIO1		0x11400000
-#define EXYNOS4_PA_GPIO2		0x11000000
-#define EXYNOS4_PA_GPIO3		0x03860000
-
-#define EXYNOS4_PA_MIPI_CSIS0		0x11880000
-#define EXYNOS4_PA_MIPI_CSIS1		0x11890000
-
-#define EXYNOS4_PA_FIMD0		0x11C00000
-
-#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
-#define EXYNOS4_PA_DWMCI		0x12550000
-
-#define EXYNOS4_PA_SATA			0x12560000
-#define EXYNOS4_PA_SATAPHY		0x125D0000
-#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
-
-#define EXYNOS4_PA_SROMC		0x12570000
-
-#define EXYNOS4_PA_EHCI			0x12580000
-#define EXYNOS4_PA_HSPHY		0x125B0000
-#define EXYNOS4_PA_MFC			0x13400000
-
-#define EXYNOS4_PA_UART			0x13800000
-
-#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
-
-#define EXYNOS4_PA_ADC			0x13910000
-#define EXYNOS4_PA_ADC1			0x13911000
-
-#define EXYNOS4_PA_AC97			0x139A0000
-
-#define EXYNOS4_PA_SPDIF		0x139B0000
-
-#define EXYNOS4_PA_TIMER		0x139D0000
-
-#define EXYNOS4_PA_SDRAM		0x40000000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
-#define S3C_PA_HSMMC1			EXYNOS4_PA_HSMMC(1)
-#define S3C_PA_HSMMC2			EXYNOS4_PA_HSMMC(2)
-#define S3C_PA_HSMMC3			EXYNOS4_PA_HSMMC(3)
-#define S3C_PA_IIC			EXYNOS4_PA_IIC(0)
-#define S3C_PA_IIC1			EXYNOS4_PA_IIC(1)
-#define S3C_PA_IIC2			EXYNOS4_PA_IIC(2)
-#define S3C_PA_IIC3			EXYNOS4_PA_IIC(3)
-#define S3C_PA_IIC4			EXYNOS4_PA_IIC(4)
-#define S3C_PA_IIC5			EXYNOS4_PA_IIC(5)
-#define S3C_PA_IIC6			EXYNOS4_PA_IIC(6)
-#define S3C_PA_IIC7			EXYNOS4_PA_IIC(7)
-#define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
-#define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
-#define S3C_PA_RTC			EXYNOS4_PA_RTC
-#define S3C_PA_WDT			EXYNOS4_PA_WATCHDOG
-
-#define S5P_PA_CHIPID			EXYNOS4_PA_CHIPID
-#define S5P_PA_FIMC0			EXYNOS4_PA_FIMC0
-#define S5P_PA_FIMC1			EXYNOS4_PA_FIMC1
-#define S5P_PA_FIMC2			EXYNOS4_PA_FIMC2
-#define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
-#define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
-#define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
-#define S5P_PA_FIMD0			EXYNOS4_PA_FIMD0
-#define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
-#define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
-#define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
-#define S5P_PA_SROMC			EXYNOS4_PA_SROMC
-#define S5P_PA_MFC			EXYNOS4_PA_MFC
-#define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
-#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
-#define S5P_PA_EHCI			EXYNOS4_PA_EHCI
-
-#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
-
-/* UART */
-
-#define S3C_PA_UART			EXYNOS4_PA_UART
-
-#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0			S5P_PA_UART(0)
-#define S5P_PA_UART1			S5P_PA_UART(1)
-#define S5P_PA_UART2			S5P_PA_UART(2)
-#define S5P_PA_UART3			S5P_PA_UART(3)
-#define S5P_PA_UART4			S5P_PA_UART(4)
-
-#define S5P_SZ_UART			SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/memory.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H __FILE__
-
-#define PLAT_PHYS_OFFSET		UL(0x40000000)
-
-/* Maximum of 256MiB in one bank */
-#define MAX_PHYSMEM_BITS	32
-#define SECTION_SIZE_BITS	28
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,59 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/pm-core.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * EXYNOS4210 - PM core support for arch/arm/plat-s5p/pm.c
- *
- * 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 <mach/regs-pmu.h>
-
-static inline void s3c_pm_debug_init_uart(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
-	unsigned int tmp;
-	tmp = __raw_readl(S5P_WAKEUP_MASK);
-	tmp &= ~(1 << 31);
-	__raw_writel(tmp, S5P_WAKEUP_MASK);
-
-	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
-	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_show_resume_irqs(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-					   struct pm_uart_save *save)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_restored_gpios(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_saved_gpios(void)
-{
-	/* nothing here yet */
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4210 - PMU(Power Management Unit) support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_PMU_H
-#define __ASM_ARCH_PMU_H __FILE__
-
-enum sys_powerdown {
-	SYS_AFTR,
-	SYS_LPA,
-	SYS_SLEEP,
-	NUM_SYS_POWERDOWN,
-};
-
-extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
-
-#endif /* __ASM_ARCH_PMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/pwm-clock.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * EXYNOS4 - pwm clock and timer support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-audss.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-audss.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-audss.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-audss.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-audss.h
- *
- * Copyright (c) 2011 Samsung Electronics
- *		http://www.samsung.com
- *
- * Exynos4 Audio SubSystem clock register definitions
- *
- * 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 __PLAT_REGS_AUDSS_H
-#define __PLAT_REGS_AUDSS_H __FILE__
-
-#define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
-
-#endif /* _PLAT_REGS_AUDSS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-clock.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-clock.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
-
-#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
-#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
-#define S5P_CLKGATE_IP_LEFTBUS		S5P_CLKREG(0x04800)
-
-#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
-#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
-#define S5P_CLKGATE_IP_RIGHTBUS		S5P_CLKREG(0x08800)
-
-#define S5P_EPLL_LOCK			S5P_CLKREG(0x0C010)
-#define S5P_VPLL_LOCK			S5P_CLKREG(0x0C020)
-
-#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
-#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
-#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
-#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
-
-#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
-#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
-#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
-#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
-#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
-#define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
-#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
-#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
-#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
-#define S5P_CLKSRC_MAUDIO		S5P_CLKREG(0x0C23C)
-#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
-#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
-#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
-
-#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
-#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
-#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
-#define S5P_CLKDIV_MFC			S5P_CLKREG(0x0C528)
-#define S5P_CLKDIV_G3D			S5P_CLKREG(0x0C52C)
-#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
-#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
-#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
-#define S5P_CLKDIV_MAUDIO		S5P_CLKREG(0x0C53C)
-#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
-#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
-#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
-#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
-#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
-#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
-#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
-#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
-#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
-#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
-#define S5P_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
-
-#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
-#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
-#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
-#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
-#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
-#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
-#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
-#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
-#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
-
-#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
-
-#define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
-#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
-#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
-#define S5P_CLKGATE_IP_MFC		S5P_CLKREG(0x0C928)
-#define S5P_CLKGATE_IP_G3D		S5P_CLKREG(0x0C92C)
-#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
-#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
-#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
-#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
-#define S5P_CLKGATE_IP_GPS		S5P_CLKREG(0x0C94C)
-#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
-#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
-#define S5P_CLKGATE_BLOCK		S5P_CLKREG(0x0C970)
-
-#define S5P_CLKSRC_MASK_DMC		S5P_CLKREG(0x10300)
-#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
-#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
-#define S5P_CLKDIV_DMC1			S5P_CLKREG(0x10504)
-#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
-#define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
-
-#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
-#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
-#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
-#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
-#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
-#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
-
-#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
-#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
-
-#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
-#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
-#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
-#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
-
-#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
-#define S5P_CLKGATE_IP_CPU		S5P_CLKREG(0x14900)
-
-#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
-
-#define S5P_APLLCON0_ENABLE_SHIFT	(31)
-#define S5P_APLLCON0_LOCKED_SHIFT	(29)
-#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
-#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
-
-#define S5P_EPLLCON0_ENABLE_SHIFT	(31)
-#define S5P_EPLLCON0_LOCKED_SHIFT	(29)
-
-#define S5P_VPLLCON0_ENABLE_SHIFT	(31)
-#define S5P_VPLLCON0_LOCKED_SHIFT	(29)
-
-#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
-#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
-
-#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
-#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
-#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
-#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
-#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
-#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
-#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
-#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
-#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
-#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
-#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
-#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
-
-#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
-#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
-#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
-#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
-#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
-#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
-#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
-#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
-#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
-#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
-#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
-#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
-#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
-#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
-
-#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
-#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
-#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
-#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
-#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
-#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
-#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
-
-#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
-#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
-#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
-#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
-
-/* Compatibility defines and inclusion */
-
-#include <mach/regs-pmu.h>
-
-#define S5P_EPLL_CON			S5P_EPLL_CON0
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-gpio.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-gpio.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - GPIO (including EINT) register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#define EXYNOS4_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
-#define S5P_EINT_CON(x)			(EXYNOS4_EINT40CON + ((x) * 0x4))
-
-#define EXYNOS4_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
-#define S5P_EINT_FLTCON(x)		(EXYNOS4_EINT40FLTCON0 + ((x) * 0x4))
-
-#define EXYNOS4_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
-#define S5P_EINT_MASK(x)		(EXYNOS4_EINT40MASK + ((x) * 0x4))
-
-#define EXYNOS4_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
-#define S5P_EINT_PEND(x)		(EXYNOS4_EINT40PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE			S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x)			EXYNOS4_GPX0(x)
-#define EINT_GPIO_1(x)			EXYNOS4_GPX1(x)
-#define EINT_GPIO_2(x)			EXYNOS4_GPX2(x)
-#define EINT_GPIO_3(x)			EXYNOS4_GPX3(x)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-irq.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-irq.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-irq.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <asm/hardware/gic.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-mct.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-mct.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-mct.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-mct.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-mct.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT configutation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_MCT_H
-#define __ASM_ARCH_REGS_MCT_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
-
-#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
-#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
-#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
-
-#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
-#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
-#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
-
-#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
-
-#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
-#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
-#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
-
-#define EXYNOS4_MCT_L0_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L1_BASE		EXYNOS4_MCTREG(0x400)
-
-#define MCT_L_TCNTB_OFFSET		(0x00)
-#define MCT_L_ICNTB_OFFSET		(0x08)
-#define MCT_L_TCON_OFFSET		(0x20)
-#define MCT_L_INT_CSTAT_OFFSET		(0x30)
-#define MCT_L_INT_ENB_OFFSET		(0x34)
-#define MCT_L_WSTAT_OFFSET		(0x40)
-
-#define MCT_G_TCON_START		(1 << 8)
-#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
-#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
-
-#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
-#define MCT_L_TCON_INT_START		(1 << 1)
-#define MCT_L_TCON_TIMER_START		(1 << 0)
-
-#endif /* __ASM_ARCH_REGS_MCT_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-mem.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-mem.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-mem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-mem.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - SROMC and DMC register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_MEM_H
-#define __ASM_ARCH_REGS_MEM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_DMC0_MEMCON_OFFSET		0x04
-
-#define S5P_DMC0_MEMTYPE_SHIFT		8
-#define S5P_DMC0_MEMTYPE_MASK		0xF
-
-#endif /* __ASM_ARCH_REGS_MEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-pmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-pmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-pmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Power management unit definition
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_PMU_H
-#define __ASM_ARCH_REGS_PMU_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
-
-#define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
-
-#define S5P_CENTRAL_LOWPWR_CFG			(1 << 16)
-
-#define S5P_CENTRAL_SEQ_OPTION			S5P_PMUREG(0x0208)
-
-#define S5P_USE_STANDBY_WFI0			(1 << 16)
-#define S5P_USE_STANDBY_WFI1			(1 << 17)
-#define S5P_USE_STANDBY_WFE0			(1 << 24)
-#define S5P_USE_STANDBY_WFE1			(1 << 25)
-#define S5P_USE_MASK				((0x3 << 16) | (0x3 << 24))
-
-#define S5P_SWRESET				S5P_PMUREG(0x0400)
-
-#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
-#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
-#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
-
-#define S5P_USBHOST_PHY_CONTROL			S5P_PMUREG(0x0708)
-#define S5P_USBHOST_PHY_ENABLE			(1 << 0)
-
-#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
-#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
-#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
-#define S5P_MIPI_DPHY_MRESETN			(1 << 2)
-
-#define S5P_PMU_SATA_PHY_CONTROL		S5P_PMUREG(0x0720)
-#define S5P_INFORM0				S5P_PMUREG(0x0800)
-#define S5P_INFORM1				S5P_PMUREG(0x0804)
-#define S5P_INFORM2				S5P_PMUREG(0x0808)
-#define S5P_INFORM3				S5P_PMUREG(0x080C)
-#define S5P_INFORM4				S5P_PMUREG(0x0810)
-#define S5P_INFORM5				S5P_PMUREG(0x0814)
-#define S5P_INFORM6				S5P_PMUREG(0x0818)
-#define S5P_INFORM7				S5P_PMUREG(0x081C)
-
-#define S5P_ARM_CORE0_LOWPWR			S5P_PMUREG(0x1000)
-#define S5P_DIS_IRQ_CORE0			S5P_PMUREG(0x1004)
-#define S5P_DIS_IRQ_CENTRAL0			S5P_PMUREG(0x1008)
-#define S5P_ARM_CORE1_LOWPWR			S5P_PMUREG(0x1010)
-#define S5P_DIS_IRQ_CORE1			S5P_PMUREG(0x1014)
-#define S5P_DIS_IRQ_CENTRAL1			S5P_PMUREG(0x1018)
-#define S5P_ARM_COMMON_LOWPWR			S5P_PMUREG(0x1080)
-#define S5P_L2_0_LOWPWR				S5P_PMUREG(0x10C0)
-#define S5P_L2_1_LOWPWR				S5P_PMUREG(0x10C4)
-#define S5P_CMU_ACLKSTOP_LOWPWR			S5P_PMUREG(0x1100)
-#define S5P_CMU_SCLKSTOP_LOWPWR			S5P_PMUREG(0x1104)
-#define S5P_CMU_RESET_LOWPWR			S5P_PMUREG(0x110C)
-#define S5P_APLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1120)
-#define S5P_MPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1124)
-#define S5P_VPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1128)
-#define S5P_EPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x112C)
-#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	S5P_PMUREG(0x1138)
-#define S5P_CMU_RESET_GPSALIVE_LOWPWR		S5P_PMUREG(0x113C)
-#define S5P_CMU_CLKSTOP_CAM_LOWPWR		S5P_PMUREG(0x1140)
-#define S5P_CMU_CLKSTOP_TV_LOWPWR		S5P_PMUREG(0x1144)
-#define S5P_CMU_CLKSTOP_MFC_LOWPWR		S5P_PMUREG(0x1148)
-#define S5P_CMU_CLKSTOP_G3D_LOWPWR		S5P_PMUREG(0x114C)
-#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR		S5P_PMUREG(0x1154)
-#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		S5P_PMUREG(0x1158)
-#define S5P_CMU_CLKSTOP_GPS_LOWPWR		S5P_PMUREG(0x115C)
-#define S5P_CMU_RESET_CAM_LOWPWR		S5P_PMUREG(0x1160)
-#define S5P_CMU_RESET_TV_LOWPWR			S5P_PMUREG(0x1164)
-#define S5P_CMU_RESET_MFC_LOWPWR		S5P_PMUREG(0x1168)
-#define S5P_CMU_RESET_G3D_LOWPWR		S5P_PMUREG(0x116C)
-#define S5P_CMU_RESET_LCD0_LOWPWR		S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_LCD1_LOWPWR		S5P_PMUREG(0x1174)
-#define S5P_CMU_RESET_MAUDIO_LOWPWR		S5P_PMUREG(0x1178)
-#define S5P_CMU_RESET_GPS_LOWPWR		S5P_PMUREG(0x117C)
-#define S5P_TOP_BUS_LOWPWR			S5P_PMUREG(0x1180)
-#define S5P_TOP_RETENTION_LOWPWR		S5P_PMUREG(0x1184)
-#define S5P_TOP_PWR_LOWPWR			S5P_PMUREG(0x1188)
-#define S5P_LOGIC_RESET_LOWPWR			S5P_PMUREG(0x11A0)
-#define S5P_ONENAND_MEM_LOWPWR			S5P_PMUREG(0x11C0)
-#define S5P_MODIMIF_MEM_LOWPWR			S5P_PMUREG(0x11C4)
-#define S5P_G2D_ACP_MEM_LOWPWR			S5P_PMUREG(0x11C8)
-#define S5P_USBOTG_MEM_LOWPWR			S5P_PMUREG(0x11CC)
-#define S5P_HSMMC_MEM_LOWPWR			S5P_PMUREG(0x11D0)
-#define S5P_CSSYS_MEM_LOWPWR			S5P_PMUREG(0x11D4)
-#define S5P_SECSS_MEM_LOWPWR			S5P_PMUREG(0x11D8)
-#define S5P_PCIE_MEM_LOWPWR			S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR			S5P_PMUREG(0x11E4)
-#define S5P_PAD_RETENTION_DRAM_LOWPWR		S5P_PMUREG(0x1200)
-#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		S5P_PMUREG(0x1204)
-#define S5P_PAD_RETENTION_GPIO_LOWPWR		S5P_PMUREG(0x1220)
-#define S5P_PAD_RETENTION_UART_LOWPWR		S5P_PMUREG(0x1224)
-#define S5P_PAD_RETENTION_MMCA_LOWPWR		S5P_PMUREG(0x1228)
-#define S5P_PAD_RETENTION_MMCB_LOWPWR		S5P_PMUREG(0x122C)
-#define S5P_PAD_RETENTION_EBIA_LOWPWR		S5P_PMUREG(0x1230)
-#define S5P_PAD_RETENTION_EBIB_LOWPWR		S5P_PMUREG(0x1234)
-#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	S5P_PMUREG(0x1240)
-#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	S5P_PMUREG(0x1260)
-#define S5P_XUSBXTI_LOWPWR			S5P_PMUREG(0x1280)
-#define S5P_XXTI_LOWPWR				S5P_PMUREG(0x1284)
-#define S5P_EXT_REGULATOR_LOWPWR		S5P_PMUREG(0x12C0)
-#define S5P_GPIO_MODE_LOWPWR			S5P_PMUREG(0x1300)
-#define S5P_GPIO_MODE_MAUDIO_LOWPWR		S5P_PMUREG(0x1340)
-#define S5P_CAM_LOWPWR				S5P_PMUREG(0x1380)
-#define S5P_TV_LOWPWR				S5P_PMUREG(0x1384)
-#define S5P_MFC_LOWPWR				S5P_PMUREG(0x1388)
-#define S5P_G3D_LOWPWR				S5P_PMUREG(0x138C)
-#define S5P_LCD0_LOWPWR				S5P_PMUREG(0x1390)
-#define S5P_LCD1_LOWPWR				S5P_PMUREG(0x1394)
-#define S5P_MAUDIO_LOWPWR			S5P_PMUREG(0x1398)
-#define S5P_GPS_LOWPWR				S5P_PMUREG(0x139C)
-#define S5P_GPS_ALIVE_LOWPWR			S5P_PMUREG(0x13A0)
-
-#define S5P_ARM_CORE0_CONFIGURATION		S5P_PMUREG(0x2000)
-#define S5P_ARM_CORE0_OPTION			S5P_PMUREG(0x2008)
-#define S5P_ARM_CORE1_CONFIGURATION		S5P_PMUREG(0x2080)
-#define S5P_ARM_CORE1_STATUS			S5P_PMUREG(0x2084)
-#define S5P_ARM_CORE1_OPTION			S5P_PMUREG(0x2088)
-
-#define S5P_ARM_COMMON_OPTION			S5P_PMUREG(0x2408)
-#define S5P_TOP_PWR_OPTION			S5P_PMUREG(0x2C48)
-#define S5P_CAM_OPTION				S5P_PMUREG(0x3C08)
-#define S5P_TV_OPTION				S5P_PMUREG(0x3C28)
-#define S5P_MFC_OPTION				S5P_PMUREG(0x3C48)
-#define S5P_G3D_OPTION				S5P_PMUREG(0x3C68)
-#define S5P_LCD0_OPTION				S5P_PMUREG(0x3C88)
-#define S5P_LCD1_OPTION				S5P_PMUREG(0x3CA8)
-#define S5P_MAUDIO_OPTION			S5P_PMUREG(0x3CC8)
-#define S5P_GPS_OPTION				S5P_PMUREG(0x3CE8)
-#define S5P_GPS_ALIVE_OPTION			S5P_PMUREG(0x3D08)
-
-#define S5P_PAD_RET_MAUDIO_OPTION		S5P_PMUREG(0x3028)
-#define S5P_PAD_RET_GPIO_OPTION			S5P_PMUREG(0x3108)
-#define S5P_PAD_RET_UART_OPTION			S5P_PMUREG(0x3128)
-#define S5P_PAD_RET_MMCA_OPTION			S5P_PMUREG(0x3148)
-#define S5P_PAD_RET_MMCB_OPTION			S5P_PMUREG(0x3168)
-#define S5P_PAD_RET_EBIA_OPTION			S5P_PMUREG(0x3188)
-#define S5P_PAD_RET_EBIB_OPTION			S5P_PMUREG(0x31A8)
-
-#define S5P_PMU_CAM_CONF			S5P_PMUREG(0x3C00)
-#define S5P_PMU_TV_CONF				S5P_PMUREG(0x3C20)
-#define S5P_PMU_MFC_CONF			S5P_PMUREG(0x3C40)
-#define S5P_PMU_G3D_CONF			S5P_PMUREG(0x3C60)
-#define S5P_PMU_LCD0_CONF			S5P_PMUREG(0x3C80)
-#define S5P_PMU_LCD1_CONF			S5P_PMUREG(0x3CA0)
-#define S5P_PMU_GPS_CONF			S5P_PMUREG(0x3CE0)
-
-#define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
-#define S5P_CORE_LOCAL_PWR_EN			0x3
-#define S5P_INT_LOCAL_PWR_EN			0x7
-
-#define S5P_CHECK_SLEEP				0x00000BAD
-
-#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - System MMU register
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_SYSMMU_H
-#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-
-#define S5P_MMU_CTRL			0x000
-#define S5P_MMU_CFG			0x004
-#define S5P_MMU_STATUS			0x008
-#define S5P_MMU_FLUSH			0x00C
-#define S5P_PT_BASE_ADDR		0x014
-#define S5P_INT_STATUS			0x018
-#define S5P_INT_CLEAR			0x01C
-#define S5P_PAGE_FAULT_ADDR		0x024
-#define S5P_AW_FAULT_ADDR		0x028
-#define S5P_AR_FAULT_ADDR		0x02C
-#define S5P_DEFAULT_SLAVE_ADDR		0x030
-
-#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_S5P_REGS_USB_PHY_H
-#define __PLAT_S5P_REGS_USB_PHY_H
-
-#define EXYNOS4_HSOTG_PHYREG(x)		((x) + S3C_VA_USB_HSPHY)
-
-#define EXYNOS4_PHYPWR			EXYNOS4_HSOTG_PHYREG(0x00)
-#define PHY1_HSIC_NORMAL_MASK		(0xf << 9)
-#define PHY1_HSIC1_SLEEP		(1 << 12)
-#define PHY1_HSIC1_FORCE_SUSPEND	(1 << 11)
-#define PHY1_HSIC0_SLEEP		(1 << 10)
-#define PHY1_HSIC0_FORCE_SUSPEND	(1 << 9)
-
-#define PHY1_STD_NORMAL_MASK		(0x7 << 6)
-#define PHY1_STD_SLEEP			(1 << 8)
-#define PHY1_STD_ANALOG_POWERDOWN	(1 << 7)
-#define PHY1_STD_FORCE_SUSPEND		(1 << 6)
-
-#define PHY0_NORMAL_MASK		(0x39 << 0)
-#define PHY0_SLEEP			(1 << 5)
-#define PHY0_OTG_DISABLE		(1 << 4)
-#define PHY0_ANALOG_POWERDOWN		(1 << 3)
-#define PHY0_FORCE_SUSPEND		(1 << 0)
-
-#define EXYNOS4_PHYCLK			EXYNOS4_HSOTG_PHYREG(0x04)
-#define PHY1_COMMON_ON_N		(1 << 7)
-#define PHY0_COMMON_ON_N		(1 << 4)
-#define PHY0_ID_PULLUP			(1 << 2)
-#define CLKSEL_MASK			(0x3 << 0)
-#define CLKSEL_SHIFT			(0)
-#define CLKSEL_48M			(0x0 << 0)
-#define CLKSEL_12M			(0x2 << 0)
-#define CLKSEL_24M			(0x3 << 0)
-
-#define EXYNOS4_RSTCON			EXYNOS4_HSOTG_PHYREG(0x08)
-#define HOST_LINK_PORT_SWRST_MASK	(0xf << 6)
-#define HOST_LINK_PORT2_SWRST		(1 << 9)
-#define HOST_LINK_PORT1_SWRST		(1 << 8)
-#define HOST_LINK_PORT0_SWRST		(1 << 7)
-#define HOST_LINK_ALL_SWRST		(1 << 6)
-
-#define PHY1_SWRST_MASK			(0x7 << 3)
-#define PHY1_HSIC_SWRST			(1 << 5)
-#define PHY1_STD_SWRST			(1 << 4)
-#define PHY1_ALL_SWRST			(1 << 3)
-
-#define PHY0_SWRST_MASK			(0x7 << 0)
-#define PHY0_PHYLINK_SWRST		(1 << 2)
-#define PHY0_HLINK_SWRST		(1 << 1)
-#define PHY0_SWRST			(1 << 0)
-
-#define EXYNOS4_PHY1CON			EXYNOS4_HSOTG_PHYREG(0x34)
-#define FPENABLEN			(1 << 0)
-
-#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/sysmmu.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Samsung sysmmu driver for EXYNOS4
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-enum exynos4_sysmmu_ips {
-	SYSMMU_MDMA,
-	SYSMMU_SSS,
-	SYSMMU_FIMC0,
-	SYSMMU_FIMC1,
-	SYSMMU_FIMC2,
-	SYSMMU_FIMC3,
-	SYSMMU_JPEG,
-	SYSMMU_FIMD0,
-	SYSMMU_FIMD1,
-	SYSMMU_PCIe,
-	SYSMMU_G2D,
-	SYSMMU_ROTATOR,
-	SYSMMU_MDMA2,
-	SYSMMU_TV,
-	SYSMMU_MFC_L,
-	SYSMMU_MFC_R,
-	EXYNOS4_SYSMMU_TOTAL_IPNUM,
-};
-
-#define S5P_SYSMMU_TOTAL_IPNUM		EXYNOS4_SYSMMU_TOTAL_IPNUM
-
-extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
-
-typedef enum exynos4_sysmmu_ips sysmmu_ips;
-
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
-void sysmmu_clk_enable(sysmmu_ips ips);
-void sysmmu_clk_disable(sysmmu_ips ips);
-
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/system.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - system support header
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H __FILE__
-
-#include <plat/system-reset.h>
-
-static void arch_idle(void)
-{
-	/* nothing here yet */
-}
-#endif /* __ASM_ARCH_SYSTEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/timex.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2003-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/timex.h
- *
- * EXYNOS4 - time parameters
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H __FILE__
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - uncompress code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H __FILE__
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static void arch_detect_cpu(void)
-{
-	/* we do not need to do any cpu detection here at the moment. */
-
-	/*
-	 * For preventing FIFO overrun or infinite loop of UART console,
-	 * fifo_max should be the minimum fifo size of all of the UART channels
-	 */
-	fifo_mask = S5PV210_UFSTAT_TXMASK;
-	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
-}
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/vmalloc.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
- *
- * 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.
- *
- * EXYNOS4 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H __FILE__
-
-#define VMALLOC_END	0xF6000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/init.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/init.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-exynos4/init.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
-	[0] = {
-		.name		= "uclk1",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-};
-
-/* uart registration process */
-void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	struct s3c2410_uartcfg *tcfg = cfg;
-	u32 ucnt;
-
-	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
-		if (!tcfg->clocks) {
-			tcfg->has_fracval = 1;
-			tcfg->clocks = exynos4_serial_clocks;
-			tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
-		}
-		tcfg->flags |= NO_NEED_CHECK_CLKSRC;
-	}
-
-	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/irq-combiner.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/irq-combiner.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/irq-combiner.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/* linux/arch/arm/mach-exynos4/irq-combiner.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/common/gic.c
- *
- * IRQ COMBINER support
- *
- * 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/io.h>
-
-#include <asm/mach/irq.h>
-
-#define COMBINER_ENABLE_SET	0x0
-#define COMBINER_ENABLE_CLEAR	0x4
-#define COMBINER_INT_STATUS	0xC
-
-static DEFINE_SPINLOCK(irq_controller_lock);
-
-struct combiner_chip_data {
-	unsigned int irq_offset;
-	unsigned int irq_mask;
-	void __iomem *base;
-};
-
-static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
-
-static inline void __iomem *combiner_base(struct irq_data *data)
-{
-	struct combiner_chip_data *combiner_data =
-		irq_data_get_irq_chip_data(data);
-
-	return combiner_data->base;
-}
-
-static void combiner_mask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
-}
-
-static void combiner_unmask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
-}
-
-static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
-	struct irq_chip *chip = irq_get_chip(irq);
-	unsigned int cascade_irq, combiner_irq;
-	unsigned long status;
-
-	chained_irq_enter(chip, desc);
-
-	spin_lock(&irq_controller_lock);
-	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
-	spin_unlock(&irq_controller_lock);
-	status &= chip_data->irq_mask;
-
-	if (status == 0)
-		goto out;
-
-	combiner_irq = __ffs(status);
-
-	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
-	if (unlikely(cascade_irq >= NR_IRQS))
-		do_bad_IRQ(cascade_irq, desc);
-	else
-		generic_handle_irq(cascade_irq);
-
- out:
-	chained_irq_exit(chip, desc);
-}
-
-static struct irq_chip combiner_chip = {
-	.name		= "COMBINER",
-	.irq_mask	= combiner_mask_irq,
-	.irq_unmask	= combiner_unmask_irq,
-};
-
-void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
-{
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-	if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
-		BUG();
-	irq_set_chained_handler(irq, combiner_handle_cascade_irq);
-}
-
-void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
-			  unsigned int irq_start)
-{
-	unsigned int i;
-
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-
-	combiner_data[combiner_nr].base = base;
-	combiner_data[combiner_nr].irq_offset = irq_start;
-	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
-
-	/* Disable all interrupts */
-
-	__raw_writel(combiner_data[combiner_nr].irq_mask,
-		     base + COMBINER_ENABLE_CLEAR);
-
-	/* Setup the Linux IRQ subsystem */
-
-	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
-				+ MAX_IRQ_IN_COMBINER; i++) {
-		irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
-		irq_set_chip_data(i, &combiner_data[combiner_nr]);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/irq-eint.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/irq-eint.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/irq-eint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-/* linux/arch/arm/mach-exynos4/irq-eint.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - IRQ EINT support
- *
- * 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/gpio.h>
-
-#include <plat/pm.h>
-#include <plat/cpu.h>
-#include <plat/gpio-cfg.h>
-
-#include <mach/regs-gpio.h>
-
-#include <asm/mach/irq.h>
-
-static DEFINE_SPINLOCK(eint_lock);
-
-static unsigned int eint0_15_data[16];
-
-static unsigned int exynos4_get_irq_nr(unsigned int number)
-{
-	u32 ret = 0;
-
-	switch (number) {
-	case 0 ... 3:
-		ret = (number + IRQ_EINT0);
-		break;
-	case 4 ... 7:
-		ret = (number + (IRQ_EINT4 - 4));
-		break;
-	case 8 ... 15:
-		ret = (number + (IRQ_EINT8 - 8));
-		break;
-	default:
-		printk(KERN_ERR "number available : %d\n", number);
-	}
-
-	return ret;
-}
-
-static inline void exynos4_irq_eint_mask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask |= eint_irq_to_bit(data->irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static void exynos4_irq_eint_unmask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask &= ~(eint_irq_to_bit(data->irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static inline void exynos4_irq_eint_ack(struct irq_data *data)
-{
-	__raw_writel(eint_irq_to_bit(data->irq),
-		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void exynos4_irq_eint_maskack(struct irq_data *data)
-{
-	exynos4_irq_eint_mask(data);
-	exynos4_irq_eint_ack(data);
-}
-
-static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
-	int offs = EINT_OFFSET(data->irq);
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
-		break;
-
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -EINVAL;
-	}
-
-	shift = (offs & 0x7) * 4;
-	mask = 0x7 << shift;
-
-	spin_lock(&eint_lock);
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	ctrl &= ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-
-	switch (offs) {
-	case 0 ... 7:
-		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-		break;
-	case 8 ... 15:
-		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-		break;
-	case 16 ... 23:
-		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-		break;
-	case 24 ... 31:
-		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-		break;
-	default:
-		printk(KERN_ERR "No such irq number %d", offs);
-	}
-
-	return 0;
-}
-
-static struct irq_chip exynos4_irq_eint = {
-	.name		= "exynos4-eint",
-	.irq_mask	= exynos4_irq_eint_mask,
-	.irq_unmask	= exynos4_irq_eint_unmask,
-	.irq_mask_ack	= exynos4_irq_eint_maskack,
-	.irq_ack	= exynos4_irq_eint_ack,
-	.irq_set_type	= exynos4_irq_eint_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= s3c_irqext_wake,
-#endif
-};
-
-/* exynos4_irq_demux_eint
- *
- * This function demuxes the IRQ from from EINTs 16 to 31.
- * It is designed to be inlined into the specific handler
- * s5p_irq_demux_eintX_Y.
- *
- * Each EINT pend/mask registers handle eight of them.
- */
-static inline void exynos4_irq_demux_eint(unsigned int start)
-{
-	unsigned int irq;
-
-	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
-	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
-
-	status &= ~mask;
-	status &= 0xff;
-
-	while (status) {
-		irq = fls(status) - 1;
-		generic_handle_irq(irq + start);
-		status &= ~(1 << irq);
-	}
-}
-
-static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	chained_irq_enter(chip, desc);
-	exynos4_irq_demux_eint(IRQ_EINT(16));
-	exynos4_irq_demux_eint(IRQ_EINT(24));
-	chained_irq_exit(chip, desc);
-}
-
-static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
-{
-	u32 *irq_data = irq_get_handler_data(irq);
-	struct irq_chip *chip = irq_get_chip(irq);
-
-	chained_irq_enter(chip, desc);
-	chip->irq_mask(&desc->irq_data);
-
-	if (chip->irq_ack)
-		chip->irq_ack(&desc->irq_data);
-
-	generic_handle_irq(*irq_data);
-
-	chip->irq_unmask(&desc->irq_data);
-	chained_irq_exit(chip, desc);
-}
-
-int __init exynos4_init_irq_eint(void)
-{
-	int irq;
-
-	for (irq = 0 ; irq <= 31 ; irq++) {
-		irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
-					 handle_level_irq);
-		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
-	}
-
-	irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
-
-	for (irq = 0 ; irq <= 15 ; irq++) {
-		eint0_15_data[irq] = IRQ_EINT(irq);
-
-		irq_set_handler_data(exynos4_get_irq_nr(irq),
-				     &eint0_15_data[irq]);
-		irq_set_chained_handler(exynos4_get_irq_nr(irq),
-					exynos4_irq_eint0_15);
-	}
-
-	return 0;
-}
-
-arch_initcall(exynos4_init_irq_eint);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-# arch/arm/mach-exynos4/Kconfig
-#
-# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-# Configuration options for the EXYNOS4
-
-if ARCH_EXYNOS4
-
-config CPU_EXYNOS4210
-	bool
-	select S3C_PL330_DMA
-	help
-	  Enable EXYNOS4210 CPU support
-
-config EXYNOS4_MCT
-	bool
-	default y
-	help
-	  Use MCT (Multi Core Timer) as kernel timers
-
-config EXYNOS4_DEV_AHCI
-	bool
-	help
-	  Compile in platform device definitions for AHCI
-
-config EXYNOS4_SETUP_FIMD0
-	bool
-	help
-	  Common setup code for FIMD0.
-
-config EXYNOS4_DEV_PD
-	bool
-	help
-	  Compile in platform device definitions for Power Domain
-
-config EXYNOS4_DEV_SYSMMU
-	bool
-	help
-	  Common setup code for SYSTEM MMU in EXYNOS4
-
-config EXYNOS4_DEV_DWMCI
-	bool
-	help
-	  Compile in platform device definitions for DWMCI
-
-config EXYNOS4_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config EXYNOS4_SETUP_I2C2
-	bool
-	help
-	  Common setup code for i2c bus 2.
-
-config EXYNOS4_SETUP_I2C3
-	bool
-	help
-	  Common setup code for i2c bus 3.
-
-config EXYNOS4_SETUP_I2C4
-	bool
-	help
-	  Common setup code for i2c bus 4.
-
-config EXYNOS4_SETUP_I2C5
-	bool
-	help
-	  Common setup code for i2c bus 5.
-
-config EXYNOS4_SETUP_I2C6
-	bool
-	help
-	  Common setup code for i2c bus 6.
-
-config EXYNOS4_SETUP_I2C7
-	bool
-	help
-	  Common setup code for i2c bus 7.
-
-config EXYNOS4_SETUP_KEYPAD
-	bool
-	help
-	  Common setup code for keypad.
-
-config EXYNOS4_SETUP_SDHCI
-	bool
-	select EXYNOS4_SETUP_SDHCI_GPIO
-	help
-	  Internal helper functions for EXYNOS4 based SDHCI systems.
-
-config EXYNOS4_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-config EXYNOS4_SETUP_FIMC
-	bool
-	help
-	  Common setup code for the camera interfaces.
-
-config EXYNOS4_SETUP_USB_PHY
-	bool
-	help
-	  Common setup code for USB PHY controller
-
-# machine support
-
-menu "EXYNOS4 Machines"
-
-config MACH_SMDKC210
-	bool "SMDKC210"
-	select CPU_EXYNOS4210
-	select S5P_DEV_FIMD0
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_BACKLIGHT
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_FIMD0
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_SDHCI
-	help
-	  Machine support for Samsung SMDKC210
-
-config MACH_SMDKV310
-	bool "SMDKV310"
-	select CPU_EXYNOS4210
-	select S5P_DEV_FIMD0
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select SAMSUNG_DEV_BACKLIGHT
-	select EXYNOS4_DEV_AHCI
-	select SAMSUNG_DEV_KEYPAD
-	select EXYNOS4_DEV_PD
-	select SAMSUNG_DEV_PWM
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_FIMD0
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_KEYPAD
-	select EXYNOS4_SETUP_SDHCI
-	help
-	  Machine support for Samsung SMDKV310
-
-config MACH_ARMLEX4210
-	bool "ARMLEX4210"
-	select CPU_EXYNOS4210
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select EXYNOS4_DEV_AHCI
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_SDHCI
-	help
-	  Machine support for Samsung ARMLEX4210 based on EXYNOS4210
-
-config MACH_UNIVERSAL_C210
-	bool "Mobile UNIVERSAL_C210 Board"
-	select CPU_EXYNOS4210
-	select S5P_GPIO_INT
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_FIMC3
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C3
-	select S3C_DEV_I2C5
-	select S5P_DEV_MFC
-	select S5P_DEV_ONENAND
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_I2C3
-	select EXYNOS4_SETUP_I2C5
-	select EXYNOS4_SETUP_SDHCI
-	help
-	  Machine support for Samsung Mobile Universal S5PC210 Reference
-	  Board.
-
-config MACH_NURI
-	bool "Mobile NURI Board"
-	select CPU_EXYNOS4210
-	select S3C_DEV_WDT
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C3
-	select S3C_DEV_I2C5
-	select S5P_DEV_MFC
-	select S5P_DEV_USB_EHCI
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_I2C3
-	select EXYNOS4_SETUP_I2C5
-	select EXYNOS4_SETUP_SDHCI
-	select EXYNOS4_SETUP_USB_PHY
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_ADC
-	help
-	  Machine support for Samsung Mobile NURI Board.
-
-endmenu
-
-comment "Configuration for HSMMC bus width"
-
-menu "Use 8-bit bus width"
-
-config EXYNOS4_SDHCI_CH0_8BIT
-	bool "Channel 0 with 8-bit bus"
-	help
-	  Support HSMMC Channel 0 8-bit bus.
-	  If selected, Channel 1 is disabled.
-
-config EXYNOS4_SDHCI_CH2_8BIT
-	bool "Channel 2 with 8-bit bus"
-	help
-	  Support HSMMC Channel 2 8-bit bus.
-	  If selected, Channel 3 is disabled.
-
-endmenu
-
-endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-armlex4210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-armlex4210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-armlex4210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-armlex4210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,215 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-armlex4210.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/smsc911x.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/exynos4.h>
-#include <plat/gpio-cfg.h>
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/sdhci.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define ARMLEX4210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define ARMLEX4210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define ARMLEX4210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= ARMLEX4210_UCON_DEFAULT,
-		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
-		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= ARMLEX4210_UCON_DEFAULT,
-		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
-		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= ARMLEX4210_UCON_DEFAULT,
-		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
-		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= ARMLEX4210_UCON_DEFAULT,
-		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
-		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPX2(5),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-	.max_width		= 4,
-};
-
-static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-	.max_width		= 4,
-};
-
-static void __init armlex4210_sdhci_init(void)
-{
-	s3c_sdhci0_set_platdata(&armlex4210_hsmmc0_pdata);
-	s3c_sdhci2_set_platdata(&armlex4210_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&armlex4210_hsmmc3_pdata);
-}
-
-static void __init armlex4210_wlan_init(void)
-{
-	/* enable */
-	s3c_gpio_cfgpin(EXYNOS4_GPX2(0), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(EXYNOS4_GPX2(0), S3C_GPIO_PULL_UP);
-
-	/* reset */
-	s3c_gpio_cfgpin(EXYNOS4_GPX1(6), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(EXYNOS4_GPX1(6), S3C_GPIO_PULL_UP);
-
-	/* wakeup */
-	s3c_gpio_cfgpin(EXYNOS4_GPX1(5), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(EXYNOS4_GPX1(5), S3C_GPIO_PULL_UP);
-}
-
-static struct resource armlex4210_smsc911x_resources[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SROM_BANK(3),
-		.end	= EXYNOS4_PA_SROM_BANK(3) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(27),
-		.end	= IRQ_EINT(27),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device armlex4210_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(armlex4210_smsc911x_resources),
-	.resource	= armlex4210_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct platform_device *armlex4210_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&exynos4_device_sysmmu,
-	&samsung_asoc_dma,
-	&armlex4210_smsc911x,
-	&exynos4_device_ahci,
-};
-
-static void __init armlex4210_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(0 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__ADDRMODE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-static void __init armlex4210_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(armlex4210_uartcfgs,
-			   ARRAY_SIZE(armlex4210_uartcfgs));
-}
-
-static void __init armlex4210_machine_init(void)
-{
-	armlex4210_smsc911x_init();
-
-	armlex4210_sdhci_init();
-
-	armlex4210_wlan_init();
-
-	platform_add_devices(armlex4210_devices,
-			     ARRAY_SIZE(armlex4210_devices));
-}
-
-MACHINE_START(ARMLEX4210, "ARMLEX4210")
-	/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= armlex4210_map_io,
-	.init_machine	= armlex4210_machine_init,
-	.timer		= &exynos4_timer,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-nuri.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-nuri.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-nuri.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-nuri.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1161 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/mach-nuri.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * 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/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/i2c-gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio.h>
-#include <linux/power/max8903_charger.h>
-#include <linux/power/max17042_battery.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/mfd/max8997.h>
-#include <linux/mfd/max8997-private.h>
-#include <linux/mmc/host.h>
-#include <linux/fb.h>
-#include <linux/pwm_backlight.h>
-
-#include <video/platform_lcd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/adc.h>
-#include <plat/regs-serial.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/ehci.h>
-#include <plat/clock.h>
-#include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-#include <plat/mfc.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define NURI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define NURI_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define NURI_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG256 |	\
-				 S5PV210_UFCON_RXTRIG256)
-
-enum fixed_regulator_id {
-	FIXED_REG_ID_MMC = 0,
-	FIXED_REG_ID_MAX8903,
-};
-
-static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
-	{
-		.hwport		= 0,
-		.ucon		= NURI_UCON_DEFAULT,
-		.ulcon		= NURI_ULCON_DEFAULT,
-		.ufcon		= NURI_UFCON_DEFAULT,
-	},
-	{
-		.hwport		= 1,
-		.ucon		= NURI_UCON_DEFAULT,
-		.ulcon		= NURI_ULCON_DEFAULT,
-		.ufcon		= NURI_UFCON_DEFAULT,
-	},
-	{
-		.hwport		= 2,
-		.ucon		= NURI_UCON_DEFAULT,
-		.ulcon		= NURI_ULCON_DEFAULT,
-		.ufcon		= NURI_UFCON_DEFAULT,
-	},
-	{
-		.hwport		= 3,
-		.ucon		= NURI_UCON_DEFAULT,
-		.ulcon		= NURI_ULCON_DEFAULT,
-		.ufcon		= NURI_UFCON_DEFAULT,
-	},
-};
-
-/* eMMC */
-static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
-	.max_width		= 8,
-	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE | MMC_CAP_ERASE),
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct regulator_consumer_supply emmc_supplies[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-	REGULATOR_SUPPLY("vmmc", "dw_mmc"),
-};
-
-static struct regulator_init_data emmc_fixed_voltage_init_data = {
-	.constraints		= {
-		.name		= "VMEM_VDD_2.8V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(emmc_supplies),
-	.consumer_supplies	= emmc_supplies,
-};
-
-static struct fixed_voltage_config emmc_fixed_voltage_config = {
-	.supply_name		= "MASSMEMORY_EN (inverted)",
-	.microvolts		= 2800000,
-	.gpio			= EXYNOS4_GPL1(1),
-	.enable_high		= false,
-	.init_data		= &emmc_fixed_voltage_init_data,
-};
-
-static struct platform_device emmc_fixed_voltage = {
-	.name			= "reg-fixed-voltage",
-	.id			= FIXED_REG_ID_MMC,
-	.dev			= {
-		.platform_data	= &emmc_fixed_voltage_config,
-	},
-};
-
-/* SD */
-static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.ext_cd_gpio		= EXYNOS4_GPX3(3),	/* XEINT_27 */
-	.ext_cd_gpio_invert	= 1,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-/* WLAN */
-static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static void __init nuri_sdhci_init(void)
-{
-	s3c_sdhci0_set_platdata(&nuri_hsmmc0_data);
-	s3c_sdhci2_set_platdata(&nuri_hsmmc2_data);
-	s3c_sdhci3_set_platdata(&nuri_hsmmc3_data);
-}
-
-/* GPIO KEYS */
-static struct gpio_keys_button nuri_gpio_keys_tables[] = {
-	{
-		.code			= KEY_VOLUMEUP,
-		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
-		.desc			= "gpio-keys: KEY_VOLUMEUP",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_VOLUMEDOWN,
-		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
-		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_POWER,
-		.gpio			= EXYNOS4_GPX2(7),	/* XEINT23 */
-		.desc			= "gpio-keys: KEY_POWER",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.wakeup			= 1,
-		.debounce_interval	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data nuri_gpio_keys_data = {
-	.buttons		= nuri_gpio_keys_tables,
-	.nbuttons		= ARRAY_SIZE(nuri_gpio_keys_tables),
-};
-
-static struct platform_device nuri_gpio_keys = {
-	.name			= "gpio-keys",
-	.dev			= {
-		.platform_data	= &nuri_gpio_keys_data,
-	},
-};
-
-static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
-{
-	int gpio = EXYNOS4_GPE1(5);
-
-	gpio_request(gpio, "LVDS_nSHDN");
-	gpio_direction_output(gpio, power);
-	gpio_free(gpio);
-}
-
-static int nuri_bl_init(struct device *dev)
-{
-	int ret, gpio = EXYNOS4_GPE2(3);
-
-	ret = gpio_request(gpio, "LCD_LDO_EN");
-	if (!ret)
-		gpio_direction_output(gpio, 0);
-
-	return ret;
-}
-
-static int nuri_bl_notify(struct device *dev, int brightness)
-{
-	if (brightness < 1)
-		brightness = 0;
-
-	gpio_set_value(EXYNOS4_GPE2(3), 1);
-
-	return brightness;
-}
-
-static void nuri_bl_exit(struct device *dev)
-{
-	gpio_free(EXYNOS4_GPE2(3));
-}
-
-/* nuri pwm backlight */
-static struct platform_pwm_backlight_data nuri_backlight_data = {
-	.pwm_id			= 0,
-	.pwm_period_ns		= 30000,
-	.max_brightness		= 100,
-	.dft_brightness		= 50,
-	.init			= nuri_bl_init,
-	.notify			= nuri_bl_notify,
-	.exit			= nuri_bl_exit,
-};
-
-static struct platform_device nuri_backlight_device = {
-	.name			= "pwm-backlight",
-	.id			= -1,
-	.dev			= {
-		.parent		= &s3c_device_timer[0].dev,
-		.platform_data	= &nuri_backlight_data,
-	},
-};
-
-static struct plat_lcd_data nuri_lcd_platform_data = {
-	.set_power		= nuri_lcd_power_on,
-};
-
-static struct platform_device nuri_lcd_device = {
-	.name			= "platform-lcd",
-	.id			= -1,
-	.dev			= {
-		.platform_data	= &nuri_lcd_platform_data,
-	},
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c1_devs[] __initdata = {
-	/* Gyro, To be updated */
-};
-
-/* TSP */
-static u8 mxt_init_vals[] = {
-	/* MXT_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* MXT_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* MXT_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* MXT_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00,
-	/* MXT_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* MXT_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* MXT_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
-};
-
-static struct mxt_platform_data mxt_platform_data = {
-	.config			= mxt_init_vals,
-	.config_length		= ARRAY_SIZE(mxt_init_vals),
-
-	.x_line			= 18,
-	.y_line			= 11,
-	.x_size			= 1024,
-	.y_size			= 600,
-	.blen			= 0x1,
-	.threshold		= 0x28,
-	.voltage		= 2800000,		/* 2.8V */
-	.orient			= MXT_DIAGONAL_COUNTER,
-	.irqflags		= IRQF_TRIGGER_FALLING,
-};
-
-static struct s3c2410_platform_i2c i2c3_data __initdata = {
-	.flags		= 0,
-	.bus_num	= 3,
-	.slave_addr	= 0x10,
-	.frequency	= 400 * 1000,
-	.sda_delay	= 100,
-};
-
-static struct i2c_board_info i2c3_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
-		.platform_data	= &mxt_platform_data,
-		.irq		= IRQ_EINT(4),
-	},
-};
-
-static void __init nuri_tsp_init(void)
-{
-	int gpio;
-
-	/* TOUCH_INT: XEINT_4 */
-	gpio = EXYNOS4_GPX0(4);
-	gpio_request(gpio, "TOUCH_INT");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-}
-
-static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
-	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
-	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
-	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
-	REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
-	REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
-	REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
-	REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
-	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
-	REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
-	REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
-};
-static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
-	REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
-	REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
-	REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
-};
-static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
-	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
-};
-static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
-	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
-};
-static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
-	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
-};
-static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
-	REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
-	REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
-	REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
-};
-static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
-	REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
-};
-
-static struct regulator_consumer_supply __initdata max8997_charger_[] = {
-	REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
-};
-static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
-	REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
-};
-
-static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
-	REGULATOR_SUPPLY("gps_clk", "bcm4751"),
-	REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
-	REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
-};
-
-static struct regulator_init_data __initdata max8997_ldo1_data = {
-	.constraints	= {
-		.name		= "VADC_3.3V_C210",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo1_),
-	.consumer_supplies	= max8997_ldo1_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo2_data = {
-	.constraints	= {
-		.name		= "VALIVE_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo3_data = {
-	.constraints	= {
-		.name		= "VUSB_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo3_),
-	.consumer_supplies	= max8997_ldo3_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo4_data = {
-	.constraints	= {
-		.name		= "VMIPI_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo4_),
-	.consumer_supplies	= max8997_ldo4_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo5_data = {
-	.constraints	= {
-		.name		= "VHSIC_1.2V_C210",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo5_),
-	.consumer_supplies	= max8997_ldo5_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo6_data = {
-	.constraints	= {
-		.name		= "VCC_1.8V_PDA",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo7_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo7_),
-	.consumer_supplies	= max8997_ldo7_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo8_data = {
-	.constraints	= {
-		.name		= "VUSB/VDAC_3.3V_C210",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo8_),
-	.consumer_supplies	= max8997_ldo8_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo9_data = {
-	.constraints	= {
-		.name		= "VCC_2.8V_PDA",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo10_data = {
-	.constraints	= {
-		.name		= "VPLL_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo11_data = {
-	.constraints	= {
-		.name		= "LVDS_VDD3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.boot_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo11_),
-	.consumer_supplies	= max8997_ldo11_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo12_data = {
-	.constraints	= {
-		.name		= "VT_CAM_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo12_),
-	.consumer_supplies	= max8997_ldo12_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo13_data = {
-	.constraints	= {
-		.name		= "VTF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo13_),
-	.consumer_supplies	= max8997_ldo13_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo14_data = {
-	.constraints	= {
-		.name		= "VCC_3.0V_MOTOR",
-		.min_uV		= 3000000,
-		.max_uV		= 3000000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo14_),
-	.consumer_supplies	= max8997_ldo14_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo15_data = {
-	.constraints	= {
-		.name		= "VTOUCH_ADVV2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo15_),
-	.consumer_supplies	= max8997_ldo15_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo16_data = {
-	.constraints	= {
-		.name		= "CAM_SENSOR_IO_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo16_),
-	.consumer_supplies	= max8997_ldo16_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo18_data = {
-	.constraints	= {
-		.name		= "VTOUCH_VDD2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo18_),
-	.consumer_supplies	= max8997_ldo18_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo21_data = {
-	.constraints	= {
-		.name		= "VDDQ_M1M2_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_buck1_data = {
-	.constraints	= {
-		.name		= "VARM_1.2V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1350000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
-	.consumer_supplies = max8997_buck1_,
-};
-
-static struct regulator_init_data __initdata max8997_buck2_data = {
-	.constraints	= {
-		.name		= "VINT_1.1V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
-	.consumer_supplies = max8997_buck2_,
-};
-
-static struct regulator_init_data __initdata max8997_buck3_data = {
-	.constraints	= {
-		.name		= "VG3D_1.1V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
-	.consumer_supplies = max8997_buck3_,
-};
-
-static struct regulator_init_data __initdata max8997_buck4_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_CORE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
-	.consumer_supplies = max8997_buck4_,
-};
-
-static struct regulator_init_data __initdata max8997_buck5_data = {
-	.constraints	= {
-		.name		= "VMEM_1.2V_C210",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_buck6_data = {
-	.constraints	= {
-		.name		= "CAM_AF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
-	.consumer_supplies = max8997_buck6_,
-};
-
-static struct regulator_init_data __initdata max8997_buck7_data = {
-	.constraints	= {
-		.name		= "VCC_SUB_2.0V",
-		.min_uV		= 2000000,
-		.max_uV		= 2000000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_32khz_ap_data = {
-	.constraints	= {
-		.name		= "32KHz AP",
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
-	.consumer_supplies = max8997_32khz_ap_,
-};
-
-static struct regulator_init_data __initdata max8997_32khz_cp_data = {
-	.constraints	= {
-		.name		= "32KHz CP",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_vichg_data = {
-	.constraints	= {
-		.name		= "VICHG",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_esafeout1_data = {
-	.constraints	= {
-		.name		= "SAFEOUT1",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout1_),
-	.consumer_supplies	= max8997_esafeout1_,
-};
-
-static struct regulator_init_data __initdata max8997_esafeout2_data = {
-	.constraints	= {
-		.name		= "SAFEOUT2",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout2_),
-	.consumer_supplies	= max8997_esafeout2_,
-};
-
-static struct regulator_init_data __initdata max8997_charger_cv_data = {
-	.constraints	= {
-		.name		= "CHARGER_CV",
-		.min_uV		= 4200000,
-		.max_uV		= 4200000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data __initdata max8997_charger_data = {
-	.constraints	= {
-		.name		= "CHARGER",
-		.min_uA		= 200000,
-		.max_uA		= 950000,
-		.boot_on	= 1,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
-				REGULATOR_CHANGE_CURRENT,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_charger_),
-	.consumer_supplies	= max8997_charger_,
-};
-
-static struct regulator_init_data __initdata max8997_charger_topoff_data = {
-	.constraints	= {
-		.name		= "CHARGER TOPOFF",
-		.min_uA		= 50000,
-		.max_uA		= 200000,
-		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_chg_toff_),
-	.consumer_supplies	= max8997_chg_toff_,
-};
-
-static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
-	{ MAX8997_LDO1, &max8997_ldo1_data },
-	{ MAX8997_LDO2, &max8997_ldo2_data },
-	{ MAX8997_LDO3, &max8997_ldo3_data },
-	{ MAX8997_LDO4, &max8997_ldo4_data },
-	{ MAX8997_LDO5, &max8997_ldo5_data },
-	{ MAX8997_LDO6, &max8997_ldo6_data },
-	{ MAX8997_LDO7, &max8997_ldo7_data },
-	{ MAX8997_LDO8, &max8997_ldo8_data },
-	{ MAX8997_LDO9, &max8997_ldo9_data },
-	{ MAX8997_LDO10, &max8997_ldo10_data },
-	{ MAX8997_LDO11, &max8997_ldo11_data },
-	{ MAX8997_LDO12, &max8997_ldo12_data },
-	{ MAX8997_LDO13, &max8997_ldo13_data },
-	{ MAX8997_LDO14, &max8997_ldo14_data },
-	{ MAX8997_LDO15, &max8997_ldo15_data },
-	{ MAX8997_LDO16, &max8997_ldo16_data },
-
-	{ MAX8997_LDO18, &max8997_ldo18_data },
-	{ MAX8997_LDO21, &max8997_ldo21_data },
-
-	{ MAX8997_BUCK1, &max8997_buck1_data },
-	{ MAX8997_BUCK2, &max8997_buck2_data },
-	{ MAX8997_BUCK3, &max8997_buck3_data },
-	{ MAX8997_BUCK4, &max8997_buck4_data },
-	{ MAX8997_BUCK5, &max8997_buck5_data },
-	{ MAX8997_BUCK6, &max8997_buck6_data },
-	{ MAX8997_BUCK7, &max8997_buck7_data },
-
-	{ MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
-	{ MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
-
-	{ MAX8997_ENVICHG, &max8997_vichg_data },
-	{ MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
-	{ MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
-	{ MAX8997_CHARGER_CV, &max8997_charger_cv_data },
-	{ MAX8997_CHARGER, &max8997_charger_data },
-	{ MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
-};
-
-static struct max8997_platform_data __initdata nuri_max8997_pdata = {
-	.wakeup			= 1,
-
-	.num_regulators		= ARRAY_SIZE(nuri_max8997_regulators),
-	.regulators		= nuri_max8997_regulators,
-
-	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
-	.buck2_gpiodvs = true,
-
-	.buck1_voltage[0] = 1350000, /* 1.35V */
-	.buck1_voltage[1] = 1300000, /* 1.3V */
-	.buck1_voltage[2] = 1250000, /* 1.25V */
-	.buck1_voltage[3] = 1200000, /* 1.2V */
-	.buck1_voltage[4] = 1150000, /* 1.15V */
-	.buck1_voltage[5] = 1100000, /* 1.1V */
-	.buck1_voltage[6] = 1000000, /* 1.0V */
-	.buck1_voltage[7] = 950000, /* 0.95V */
-
-	.buck2_voltage[0] = 1100000, /* 1.1V */
-	.buck2_voltage[1] = 1000000, /* 1.0V */
-	.buck2_voltage[2] = 950000, /* 0.95V */
-	.buck2_voltage[3] = 900000, /* 0.9V */
-	.buck2_voltage[4] = 1100000, /* 1.1V */
-	.buck2_voltage[5] = 1000000, /* 1.0V */
-	.buck2_voltage[6] = 950000, /* 0.95V */
-	.buck2_voltage[7] = 900000, /* 0.9V */
-
-	.buck5_voltage[0] = 1200000, /* 1.2V */
-	.buck5_voltage[1] = 1200000, /* 1.2V */
-	.buck5_voltage[2] = 1200000, /* 1.2V */
-	.buck5_voltage[3] = 1200000, /* 1.2V */
-	.buck5_voltage[4] = 1200000, /* 1.2V */
-	.buck5_voltage[5] = 1200000, /* 1.2V */
-	.buck5_voltage[6] = 1200000, /* 1.2V */
-	.buck5_voltage[7] = 1200000, /* 1.2V */
-};
-
-/* GPIO I2C 5 (PMIC) */
-enum { I2C5_MAX8997 };
-static struct i2c_board_info i2c5_devs[] __initdata = {
-	[I2C5_MAX8997] = {
-		I2C_BOARD_INFO("max8997", 0xCC >> 1),
-		.platform_data	= &nuri_max8997_pdata,
-	},
-};
-
-static struct max17042_platform_data nuri_battery_platform_data = {
-};
-
-/* GPIO I2C 9 (Fuel Gauge) */
-static struct i2c_gpio_platform_data i2c9_gpio_data = {
-	.sda_pin		= EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
-	.scl_pin		= EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
-};
-static struct platform_device i2c9_gpio = {
-	.name			= "i2c-gpio",
-	.id			= 9,
-	.dev			= {
-		.platform_data	= &i2c9_gpio_data,
-	},
-};
-enum { I2C9_MAX17042};
-static struct i2c_board_info i2c9_devs[] __initdata = {
-	[I2C9_MAX17042] = {
-		I2C_BOARD_INFO("max17042", 0x36),
-		.platform_data = &nuri_battery_platform_data,
-	},
-};
-
-/* MAX8903 Secondary Charger */
-static struct regulator_consumer_supply supplies_max8903[] = {
-	REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
-};
-
-static struct regulator_init_data max8903_charger_en_data = {
-	.constraints = {
-		.name		= "VOUT_CHARGER",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on	= 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
-	.consumer_supplies = supplies_max8903,
-};
-
-static struct fixed_voltage_config max8903_charger_en = {
-	.supply_name = "VOUT_CHARGER",
-	.microvolts = 5000000, /* Assume 5VDC */
-	.gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
-	.enable_high = 0, /* Enable = Low */
-	.enabled_at_boot = 1,
-	.init_data = &max8903_charger_en_data,
-};
-
-static struct platform_device max8903_fixed_reg_dev = {
-	.name = "reg-fixed-voltage",
-	.id = FIXED_REG_ID_MAX8903,
-	.dev = { .platform_data	= &max8903_charger_en },
-};
-
-static struct max8903_pdata nuri_max8903 = {
-	/*
-	 * cen: don't control with the driver, let it be
-	 * controlled by regulator above
-	 */
-	.dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
-	/* uok, usus: not connected */
-	.chg = EXYNOS4_GPE2(0), /* TA_nCHG */
-	/* flt: vcc_1.8V_pda */
-	.dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
-
-	.dc_valid = true,
-	.usb_valid = false, /* USB is not wired to MAX8903 */
-};
-
-static struct platform_device nuri_max8903_device = {
-	.name			= "max8903-charger",
-	.dev			= {
-		.platform_data	= &nuri_max8903,
-	},
-};
-
-static struct device *nuri_cm_devices[] = {
-	&s3c_device_i2c5.dev,
-	&s3c_device_adc.dev,
-	NULL, /* Reserved for UART */
-	NULL,
-};
-
-static void __init nuri_power_init(void)
-{
-	int gpio;
-	int irq_base = IRQ_GPIO_END + 1;
-	int ta_en = 0;
-
-	nuri_max8997_pdata.irq_base = irq_base;
-	irq_base += MAX8997_IRQ_NR;
-
-	gpio = EXYNOS4_GPX0(7);
-	gpio_request(gpio, "AP_PMIC_IRQ");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
-	gpio = EXYNOS4_GPX2(3);
-	gpio_request(gpio, "FUEL_ALERT");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
-	gpio = nuri_max8903.dok;
-	gpio_request(gpio, "TA_nCONNECTED");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-	ta_en = gpio_get_value(gpio) ? 0 : 1;
-
-	gpio = nuri_max8903.chg;
-	gpio_request(gpio, "TA_nCHG");
-	gpio_direction_input(gpio);
-
-	gpio = nuri_max8903.dcm;
-	gpio_request(gpio, "CURR_ADJ");
-	gpio_direction_output(gpio, ta_en);
-}
-
-/* USB EHCI */
-static struct s5p_ehci_platdata nuri_ehci_pdata;
-
-static void __init nuri_ehci_init(void)
-{
-	struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
-
-	s5p_ehci_set_platdata(pdata);
-}
-
-static struct platform_device *nuri_devices[] __initdata = {
-	/* Samsung Platform Devices */
-	&s3c_device_i2c5, /* PMIC should initialize first */
-	&emmc_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_wdt,
-	&s3c_device_timer[0],
-	&s5p_device_ehci,
-	&s3c_device_i2c3,
-	&i2c9_gpio,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&exynos4_device_pd[PD_MFC],
-
-	/* NURI Devices */
-	&nuri_gpio_keys,
-	&nuri_lcd_device,
-	&nuri_backlight_device,
-	&max8903_fixed_reg_dev,
-	&nuri_max8903_device,
-};
-
-static void __init nuri_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
-}
-
-static void __init nuri_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init nuri_machine_init(void)
-{
-	nuri_sdhci_init();
-	nuri_tsp_init();
-	nuri_power_init();
-
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-	s3c_i2c3_set_platdata(&i2c3_data);
-	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
-	s3c_i2c5_set_platdata(NULL);
-	i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
-	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
-	i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
-	i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
-
-	nuri_ehci_init();
-	clk_xusbxti.rate = 24000000;
-
-	/* Last */
-	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
-	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
-}
-
-MACHINE_START(NURI, "NURI")
-	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= nuri_map_io,
-	.init_machine	= nuri_machine_init,
-	.timer		= &exynos4_timer,
-	.reserve        = &nuri_reserve,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-smdkc210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-smdkc210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-smdkc210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-smdkc210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,309 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-smdkc210.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/lcd.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-#include <plat/gpio-cfg.h>
-#include <plat/backlight.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-		/* fire nRESET on power up */
-		gpio_request(EXYNOS4_GPX0(6), "GPX0");
-
-		gpio_direction_output(EXYNOS4_GPX0(6), 1);
-		mdelay(100);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 0);
-		mdelay(10);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 1);
-		mdelay(10);
-
-		gpio_free(EXYNOS4_GPX0(6));
-	} else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-	}
-}
-
-static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
-	.set_power		= lcd_lte480wv_set_power,
-};
-
-static struct platform_device smdkc210_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s5p_device_fimd0.dev,
-	.dev.platform_data	= &smdkc210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkc210_fb_win0 = {
-	.win_mode = {
-		.left_margin	= 13,
-		.right_margin	= 8,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp		= 32,
-	.default_bpp		= 24,
-};
-
-static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
-	.win[0]		= &smdkc210_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
-};
-
-static struct resource smdkc210_smsc911x_resources[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SROM_BANK(1),
-		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkc210_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
-	.resource	= smdkc210_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkc210_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&exynos4_device_ac97,
-	&exynos4_device_i2s0,
-	&exynos4_device_pd[PD_MFC],
-	&exynos4_device_pd[PD_G3D],
-	&exynos4_device_pd[PD_LCD0],
-	&exynos4_device_pd[PD_LCD1],
-	&exynos4_device_pd[PD_CAM],
-	&exynos4_device_pd[PD_TV],
-	&exynos4_device_pd[PD_GPS],
-	&exynos4_device_sysmmu,
-	&samsung_asoc_dma,
-	&s5p_device_fimd0,
-	&smdkc210_lcd_lte480wv,
-	&smdkc210_smsc911x,
-};
-
-static void __init smdkc210_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc210_bl_gpio_info = {
-	.no = EXYNOS4_GPD0(1),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc210_bl_data = {
-	.pwm_id = 1,
-	.pwm_period_ns  = 1000,
-};
-
-static void __init smdkc210_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
-}
-
-static void __init smdkc210_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkc210_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
-
-	samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
-	s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
-
-	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
-}
-
-MACHINE_START(SMDKC210, "SMDKC210")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= smdkc210_map_io,
-	.init_machine	= smdkc210_machine_init,
-	.timer		= &exynos4_timer,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-smdkv310.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-smdkv310.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-smdkv310.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-smdkv310.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/input.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/keypad.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-#include <plat/gpio-cfg.h>
-#include <plat/backlight.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct resource smdkv310_smsc911x_resources[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SROM_BANK(1),
-		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkv310_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
-	.resource	= smdkv310_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static uint32_t smdkv310_keymap[] __initdata = {
-	/* KEY(row, col, keycode) */
-	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
-	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
-	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
-	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
-};
-
-static struct matrix_keymap_data smdkv310_keymap_data __initdata = {
-	.keymap		= smdkv310_keymap,
-	.keymap_size	= ARRAY_SIZE(smdkv310_keymap),
-};
-
-static struct samsung_keypad_platdata smdkv310_keypad_data __initdata = {
-	.keymap_data	= &smdkv310_keymap_data,
-	.rows		= 2,
-	.cols		= 8,
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkv310_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&exynos4_device_ac97,
-	&exynos4_device_i2s0,
-	&samsung_device_keypad,
-	&exynos4_device_pd[PD_MFC],
-	&exynos4_device_pd[PD_G3D],
-	&exynos4_device_pd[PD_LCD0],
-	&exynos4_device_pd[PD_LCD1],
-	&exynos4_device_pd[PD_CAM],
-	&exynos4_device_pd[PD_TV],
-	&exynos4_device_pd[PD_GPS],
-	&exynos4_device_spdif,
-	&exynos4_device_sysmmu,
-	&samsung_asoc_dma,
-	&samsung_asoc_idma,
-	&smdkv310_smsc911x,
-	&exynos4_device_ahci,
-};
-
-static void __init smdkv310_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
-	.no = EXYNOS4_GPD0(1),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkv310_bl_data = {
-	.pwm_id = 1,
-	.pwm_period_ns  = 1000,
-};
-
-static void __init smdkv310_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
-}
-
-static void __init smdkv310_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkv310_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
-
-	samsung_keypad_set_platdata(&smdkv310_keypad_data);
-
-	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
-
-	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
-}
-
-MACHINE_START(SMDKV310, "SMDKV310")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= smdkv310_map_io,
-	.init_machine	= smdkv310_machine_init,
-	.timer		= &exynos4_timer,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-universal_c210.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-universal_c210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mach-universal_c210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,771 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-universal_c210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * 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/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio.h>
-#include <linux/mfd/max8998.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/max8952.h>
-#include <linux/mmc/host.h>
-#include <linux/i2c-gpio.h>
-#include <linux/i2c/mcs.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-#include <plat/mfc.h>
-#include <plat/sdhci.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG256 |	\
-				 S5PV210_UFCON_RXTRIG256)
-
-static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-};
-
-static struct regulator_consumer_supply max8952_consumer =
-	REGULATOR_SUPPLY("vdd_arm", NULL);
-
-static struct max8952_platform_data universal_max8952_pdata __initdata = {
-	.gpio_vid0	= EXYNOS4_GPX0(3),
-	.gpio_vid1	= EXYNOS4_GPX0(4),
-	.gpio_en	= -1, /* Not controllable, set "Always High" */
-	.default_mode	= 0, /* vid0 = 0, vid1 = 0 */
-	.dvs_mode	= { 48, 32, 28, 18 }, /* 1.25, 1.20, 1.05, 0.95V */
-	.sync_freq	= 0, /* default: fastest */
-	.ramp_speed	= 0, /* default: fastest */
-
-	.reg_data	= {
-		.constraints	= {
-			.name		= "VARM_1.2V",
-			.min_uV		= 770000,
-			.max_uV		= 1400000,
-			.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
-			.always_on	= 1,
-			.boot_on	= 1,
-		},
-		.num_consumer_supplies	= 1,
-		.consumer_supplies	= &max8952_consumer,
-	},
-};
-
-static struct regulator_consumer_supply lp3974_buck1_consumer =
-	REGULATOR_SUPPLY("vdd_int", NULL);
-
-static struct regulator_consumer_supply lp3974_buck2_consumer =
-	REGULATOR_SUPPLY("vddg3d", NULL);
-
-static struct regulator_init_data lp3974_buck1_data = {
-	.constraints	= {
-		.name		= "VINT_1.1V",
-		.min_uV		= 750000,
-		.max_uV		= 1500000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_STATUS,
-		.boot_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = 1,
-	.consumer_supplies = &lp3974_buck1_consumer,
-};
-
-static struct regulator_init_data lp3974_buck2_data = {
-	.constraints	= {
-		.name		= "VG3D_1.1V",
-		.min_uV		= 750000,
-		.max_uV		= 1500000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_STATUS,
-		.boot_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = 1,
-	.consumer_supplies = &lp3974_buck2_consumer,
-};
-
-static struct regulator_init_data lp3974_buck3_data = {
-	.constraints	= {
-		.name		= "VCC_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_buck4_data = {
-	.constraints	= {
-		.name		= "VMEM_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo2_data = {
-	.constraints	= {
-		.name		= "VALIVE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo3_data = {
-	.constraints	= {
-		.name		= "VUSB+MIPI_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo4_data = {
-	.constraints	= {
-		.name		= "VADC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo5_data = {
-	.constraints	= {
-		.name		= "VTF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo6_data = {
-	.constraints	= {
-		.name		= "LDO6",
-		.min_uV		= 2000000,
-		.max_uV		= 2000000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo7_data = {
-	.constraints	= {
-		.name		= "VLCD+VMIPI_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo8_data = {
-	.constraints	= {
-		.name		= "VUSB+VDAC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo9_data = {
-	.constraints	= {
-		.name		= "VCC_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo10_data = {
-	.constraints	= {
-		.name		= "VPLL_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.boot_on	= 1,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo11_data = {
-	.constraints	= {
-		.name		= "CAM_AF_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo12_data = {
-	.constraints	= {
-		.name		= "PS_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo13_data = {
-	.constraints	= {
-		.name		= "VHIC_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo14_data = {
-	.constraints	= {
-		.name		= "CAM_I_HOST_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo15_data = {
-	.constraints	= {
-		.name		= "CAM_S_DIG+FM33_CORE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo16_data = {
-	.constraints	= {
-		.name		= "CAM_S_ANA_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_ldo17_data = {
-	.constraints	= {
-		.name		= "VCC_3.0V_LCD",
-		.min_uV		= 3000000,
-		.max_uV		= 3000000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.boot_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_32khz_ap_data = {
-	.constraints	= {
-		.name		= "32KHz AP",
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_32khz_cp_data = {
-	.constraints	= {
-		.name		= "32KHz CP",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_vichg_data = {
-	.constraints	= {
-		.name		= "VICHG",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_esafeout1_data = {
-	.constraints	= {
-		.name		= "SAFEOUT1",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data lp3974_esafeout2_data = {
-	.constraints	= {
-		.name		= "SAFEOUT2",
-		.boot_on	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct max8998_regulator_data lp3974_regulators[] = {
-	{ MAX8998_LDO2,  &lp3974_ldo2_data },
-	{ MAX8998_LDO3,  &lp3974_ldo3_data },
-	{ MAX8998_LDO4,  &lp3974_ldo4_data },
-	{ MAX8998_LDO5,  &lp3974_ldo5_data },
-	{ MAX8998_LDO6,  &lp3974_ldo6_data },
-	{ MAX8998_LDO7,  &lp3974_ldo7_data },
-	{ MAX8998_LDO8,  &lp3974_ldo8_data },
-	{ MAX8998_LDO9,  &lp3974_ldo9_data },
-	{ MAX8998_LDO10, &lp3974_ldo10_data },
-	{ MAX8998_LDO11, &lp3974_ldo11_data },
-	{ MAX8998_LDO12, &lp3974_ldo12_data },
-	{ MAX8998_LDO13, &lp3974_ldo13_data },
-	{ MAX8998_LDO14, &lp3974_ldo14_data },
-	{ MAX8998_LDO15, &lp3974_ldo15_data },
-	{ MAX8998_LDO16, &lp3974_ldo16_data },
-	{ MAX8998_LDO17, &lp3974_ldo17_data },
-	{ MAX8998_BUCK1, &lp3974_buck1_data },
-	{ MAX8998_BUCK2, &lp3974_buck2_data },
-	{ MAX8998_BUCK3, &lp3974_buck3_data },
-	{ MAX8998_BUCK4, &lp3974_buck4_data },
-	{ MAX8998_EN32KHZ_AP, &lp3974_32khz_ap_data },
-	{ MAX8998_EN32KHZ_CP, &lp3974_32khz_cp_data },
-	{ MAX8998_ENVICHG, &lp3974_vichg_data },
-	{ MAX8998_ESAFEOUT1, &lp3974_esafeout1_data },
-	{ MAX8998_ESAFEOUT2, &lp3974_esafeout2_data },
-};
-
-static struct max8998_platform_data universal_lp3974_pdata = {
-	.num_regulators		= ARRAY_SIZE(lp3974_regulators),
-	.regulators		= lp3974_regulators,
-	.buck1_voltage1		= 1100000,	/* INT */
-	.buck1_voltage2		= 1000000,
-	.buck1_voltage3		= 1100000,
-	.buck1_voltage4		= 1000000,
-	.buck1_set1		= EXYNOS4_GPX0(5),
-	.buck1_set2		= EXYNOS4_GPX0(6),
-	.buck2_voltage1		= 1200000,	/* G3D */
-	.buck2_voltage2		= 1100000,
-	.buck1_default_idx	= 0,
-	.buck2_set3		= EXYNOS4_GPE2(0),
-	.buck2_default_idx	= 0,
-	.wakeup			= true,
-};
-
-/* GPIO I2C 5 (PMIC) */
-static struct i2c_board_info i2c5_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("max8952", 0xC0 >> 1),
-		.platform_data	= &universal_max8952_pdata,
-	}, {
-		I2C_BOARD_INFO("lp3974", 0xCC >> 1),
-		.platform_data	= &universal_lp3974_pdata,
-	},
-};
-
-/* I2C3 (TSP) */
-static struct mxt_platform_data qt602240_platform_data = {
-	.x_line		= 19,
-	.y_line		= 11,
-	.x_size		= 800,
-	.y_size		= 480,
-	.blen		= 0x11,
-	.threshold	= 0x28,
-	.voltage	= 2800000,		/* 2.8V */
-	.orient		= MXT_DIAGONAL,
-};
-
-static struct i2c_board_info i2c3_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("qt602240_ts", 0x4a),
-		.platform_data = &qt602240_platform_data,
-	},
-};
-
-static void __init universal_tsp_init(void)
-{
-	int gpio;
-
-	/* TSP_LDO_ON: XMDMADDR_11 */
-	gpio = EXYNOS4_GPE2(3);
-	gpio_request(gpio, "TSP_LDO_ON");
-	gpio_direction_output(gpio, 1);
-	gpio_export(gpio, 0);
-
-	/* TSP_INT: XMDMADDR_7 */
-	gpio = EXYNOS4_GPE1(7);
-	gpio_request(gpio, "TSP_INT");
-
-	s5p_register_gpio_interrupt(gpio);
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-	i2c3_devs[0].irq = gpio_to_irq(gpio);
-}
-
-
-/* GPIO I2C 12 (3 Touchkey) */
-static uint32_t touchkey_keymap[] = {
-	/* MCS_KEY_MAP(value, keycode) */
-	MCS_KEY_MAP(0, KEY_MENU),		/* KEY_SEND */
-	MCS_KEY_MAP(1, KEY_BACK),		/* KEY_END */
-};
-
-static struct mcs_platform_data touchkey_data = {
-	.keymap		= touchkey_keymap,
-	.keymap_size	= ARRAY_SIZE(touchkey_keymap),
-	.key_maxval	= 2,
-};
-
-/* GPIO I2C 3_TOUCH 2.8V */
-#define I2C_GPIO_BUS_12		12
-static struct i2c_gpio_platform_data i2c_gpio12_data = {
-	.sda_pin	= EXYNOS4_GPE4(0),	/* XMDMDATA_8 */
-	.scl_pin	= EXYNOS4_GPE4(1),	/* XMDMDATA_9 */
-};
-
-static struct platform_device i2c_gpio12 = {
-	.name		= "i2c-gpio",
-	.id		= I2C_GPIO_BUS_12,
-	.dev		= {
-		.platform_data	= &i2c_gpio12_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
-		.platform_data = &touchkey_data,
-	},
-};
-
-static void __init universal_touchkey_init(void)
-{
-	int gpio;
-
-	gpio = EXYNOS4_GPE3(7);			/* XMDMDATA_7 */
-	gpio_request(gpio, "3_TOUCH_INT");
-	s5p_register_gpio_interrupt(gpio);
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
-
-	gpio = EXYNOS4_GPE3(3);			/* XMDMDATA_3 */
-	gpio_request(gpio, "3_TOUCH_EN");
-	gpio_direction_output(gpio, 1);
-}
-
-/* GPIO KEYS */
-static struct gpio_keys_button universal_gpio_keys_tables[] = {
-	{
-		.code			= KEY_VOLUMEUP,
-		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
-		.desc			= "gpio-keys: KEY_VOLUMEUP",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_VOLUMEDOWN,
-		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
-		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CONFIG,
-		.gpio			= EXYNOS4_GPX2(2),	/* XEINT18 */
-		.desc			= "gpio-keys: KEY_CONFIG",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CAMERA,
-		.gpio			= EXYNOS4_GPX2(3),	/* XEINT19 */
-		.desc			= "gpio-keys: KEY_CAMERA",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_OK,
-		.gpio			= EXYNOS4_GPX3(5),	/* XEINT29 */
-		.desc			= "gpio-keys: KEY_OK",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data universal_gpio_keys_data = {
-	.buttons	= universal_gpio_keys_tables,
-	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
-};
-
-static struct platform_device universal_gpio_keys = {
-	.name			= "gpio-keys",
-	.dev			= {
-		.platform_data	= &universal_gpio_keys_data,
-	},
-};
-
-/* eMMC */
-static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
-	.max_width		= 8,
-	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE),
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct regulator_consumer_supply mmc0_supplies[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-};
-
-static struct regulator_init_data mmc0_fixed_voltage_init_data = {
-	.constraints		= {
-		.name		= "VMEM_VDD_2.8V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
-	.consumer_supplies	= mmc0_supplies,
-};
-
-static struct fixed_voltage_config mmc0_fixed_voltage_config = {
-	.supply_name		= "MASSMEMORY_EN",
-	.microvolts		= 2800000,
-	.gpio			= EXYNOS4_GPE1(3),
-	.enable_high		= true,
-	.init_data		= &mmc0_fixed_voltage_init_data,
-};
-
-static struct platform_device mmc0_fixed_voltage = {
-	.name			= "reg-fixed-voltage",
-	.id			= 0,
-	.dev			= {
-		.platform_data	= &mmc0_fixed_voltage_config,
-	},
-};
-
-/* SD */
-static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.ext_cd_gpio		= EXYNOS4_GPX3(4),      /* XEINT_28 */
-	.ext_cd_gpio_invert	= 1,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-/* WiFi */
-static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-};
-
-static void __init universal_sdhci_init(void)
-{
-	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
-	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
-	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
-}
-
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-	/* Camera, To be updated */
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c1_devs[] __initdata = {
-	/* Gyro, To be updated */
-};
-
-static struct platform_device *universal_devices[] __initdata = {
-	/* Samsung Platform Devices */
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5p_device_fimc3,
-	&mmc0_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c3,
-	&s3c_device_i2c5,
-
-	/* Universal Devices */
-	&i2c_gpio12,
-	&universal_gpio_keys,
-	&s5p_device_onenand,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&exynos4_device_pd[PD_MFC],
-};
-
-static void __init universal_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-}
-
-static void __init universal_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init universal_machine_init(void)
-{
-	universal_sdhci_init();
-
-	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-
-	universal_tsp_init();
-	s3c_i2c3_set_platdata(NULL);
-	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
-
-	s3c_i2c5_set_platdata(NULL);
-	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
-
-	universal_touchkey_init();
-	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
-			ARRAY_SIZE(i2c_gpio12_devs));
-
-	/* Last */
-	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
-	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
-}
-
-MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
-	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= universal_map_io,
-	.init_machine	= universal_machine_init,
-	.timer		= &exynos4_timer,
-	.reserve        = &universal_reserve,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Makefile linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-# arch/arm/mach-exynos4/Makefile
-#
-# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for EXYNOS4 system
-
-obj-$(CONFIG_CPU_EXYNOS4210)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o irq-eint.o dma.o pmu.o
-obj-$(CONFIG_PM)		+= pm.o sleep.o
-obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
-
-obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
-
-obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
-
-obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkc210.o
-obj-$(CONFIG_MACH_SMDKV310)		+= mach-smdkv310.o
-obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
-obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
-obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
-
-# device support
-
-obj-y					+= dev-audio.o
-obj-$(CONFIG_EXYNOS4_DEV_AHCI)		+= dev-ahci.o
-obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
-obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
-obj-$(CONFIG_EXYNOS4_DEV_DWMCI)	+= dev-dwmci.o
-
-obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
-obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C4)	+= setup-i2c4.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C5)	+= setup-i2c5.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C6)	+= setup-i2c6.o
-obj-$(CONFIG_EXYNOS4_SETUP_I2C7)	+= setup-i2c7.o
-obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)	+= setup-keypad.o
-obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)	+= setup-sdhci.o
-obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
-
-obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY)	+= setup-usb-phy.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-   zreladdr-y	:= 0x40008000
-params_phys-y	:= 0x40000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mct.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mct.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/mct.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/mct.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,429 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mct.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT(Multi-Core Timer) support
- *
- * 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/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/percpu.h>
-
-#include <mach/map.h>
-#include <mach/regs-mct.h>
-#include <asm/mach/time.h>
-
-static unsigned long clk_cnt_per_tick;
-static unsigned long clk_rate;
-
-struct mct_clock_event_device {
-	struct clock_event_device *evt;
-	void __iomem *base;
-};
-
-struct mct_clock_event_device mct_tick[2];
-
-static void exynos4_mct_write(unsigned int value, void *addr)
-{
-	void __iomem *stat_addr;
-	u32 mask;
-	u32 i;
-
-	__raw_writel(value, addr);
-
-	switch ((u32) addr) {
-	case (u32) EXYNOS4_MCT_G_TCON:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 16;		/* G_TCON write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_L:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 0;		/* G_COMP0_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_U:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 1;		/* G_COMP0_U write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 2;		/* G_COMP0_ADD_INCR write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_L:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 0;		/* G_CNT_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_U:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 1;		/* G_CNT_U write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L0_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L1_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L0_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L1_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L0_ICNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L1_ICNTB write status */
-		break;
-	default:
-		return;
-	}
-
-	/* Wait maximum 1 ms until written values are applied */
-	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-		if (__raw_readl(stat_addr) & mask) {
-			__raw_writel(mask, stat_addr);
-			return;
-		}
-
-	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
-}
-
-/* Clocksource handling */
-static void exynos4_mct_frc_start(u32 hi, u32 lo)
-{
-	u32 reg;
-
-	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
-	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
-
-	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
-	reg |= MCT_G_TCON_START;
-	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
-}
-
-static cycle_t exynos4_frc_read(struct clocksource *cs)
-{
-	unsigned int lo, hi;
-	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
-
-	do {
-		hi = hi2;
-		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
-		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
-	} while (hi != hi2);
-
-	return ((cycle_t)hi << 32) | lo;
-}
-
-static void exynos4_frc_resume(struct clocksource *cs)
-{
-	exynos4_mct_frc_start(0, 0);
-}
-
-struct clocksource mct_frc = {
-	.name		= "mct-frc",
-	.rating		= 400,
-	.read		= exynos4_frc_read,
-	.mask		= CLOCKSOURCE_MASK(64),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.resume		= exynos4_frc_resume,
-};
-
-static void __init exynos4_clocksource_init(void)
-{
-	exynos4_mct_frc_start(0, 0);
-
-	if (clocksource_register_hz(&mct_frc, clk_rate))
-		panic("%s: can't register clocksource\n", mct_frc.name);
-}
-
-static void exynos4_mct_comp0_stop(void)
-{
-	unsigned int tcon;
-
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
-	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
-
-	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
-	exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
-}
-
-static void exynos4_mct_comp0_start(enum clock_event_mode mode,
-				    unsigned long cycles)
-{
-	unsigned int tcon;
-	cycle_t comp_cycle;
-
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
-
-	if (mode == CLOCK_EVT_MODE_PERIODIC) {
-		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
-		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
-	}
-
-	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
-	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
-	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
-
-	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
-
-	tcon |= MCT_G_TCON_COMP0_ENABLE;
-	exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
-}
-
-static int exynos4_comp_set_next_event(unsigned long cycles,
-				       struct clock_event_device *evt)
-{
-	exynos4_mct_comp0_start(evt->mode, cycles);
-
-	return 0;
-}
-
-static void exynos4_comp_set_mode(enum clock_event_mode mode,
-				  struct clock_event_device *evt)
-{
-	exynos4_mct_comp0_stop();
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		exynos4_mct_comp0_start(mode, clk_cnt_per_tick);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device mct_comp_device = {
-	.name		= "mct-comp",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 250,
-	.set_next_event	= exynos4_comp_set_next_event,
-	.set_mode	= exynos4_comp_set_mode,
-};
-
-static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mct_comp_event_irq = {
-	.name		= "mct_comp_irq",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= exynos4_mct_comp_isr,
-	.dev_id		= &mct_comp_device,
-};
-
-static void exynos4_clockevent_init(void)
-{
-	clk_cnt_per_tick = clk_rate / 2	/ HZ;
-
-	clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5);
-	mct_comp_device.max_delta_ns =
-		clockevent_delta2ns(0xffffffff, &mct_comp_device);
-	mct_comp_device.min_delta_ns =
-		clockevent_delta2ns(0xf, &mct_comp_device);
-	mct_comp_device.cpumask = cpumask_of(0);
-	clockevents_register_device(&mct_comp_device);
-
-	setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
-}
-
-#ifdef CONFIG_LOCAL_TIMERS
-/* Clock event handling */
-static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
-{
-	unsigned long tmp;
-	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
-
-	tmp = __raw_readl(addr);
-	if (tmp & mask) {
-		tmp &= ~mask;
-		exynos4_mct_write(tmp, addr);
-	}
-}
-
-static void exynos4_mct_tick_start(unsigned long cycles,
-				   struct mct_clock_event_device *mevt)
-{
-	unsigned long tmp;
-
-	exynos4_mct_tick_stop(mevt);
-
-	tmp = (1 << 31) | cycles;	/* MCT_L_UPDATE_ICNTB */
-
-	/* update interrupt count buffer */
-	exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
-
-	/* enable MCT tick interrupt */
-	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
-
-	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
-	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
-	       MCT_L_TCON_INTERVAL_MODE;
-	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
-}
-
-static int exynos4_tick_set_next_event(unsigned long cycles,
-				       struct clock_event_device *evt)
-{
-	struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
-
-	exynos4_mct_tick_start(cycles, mevt);
-
-	return 0;
-}
-
-static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
-					 struct clock_event_device *evt)
-{
-	struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
-
-	exynos4_mct_tick_stop(mevt);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
-{
-	struct mct_clock_event_device *mevt = dev_id;
-	struct clock_event_device *evt = mevt->evt;
-
-	/*
-	 * This is for supporting oneshot mode.
-	 * Mct would generate interrupt periodically
-	 * without explicit stopping.
-	 */
-	if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
-		exynos4_mct_tick_stop(mevt);
-
-	/* Clear the MCT tick interrupt */
-	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mct_tick0_event_irq = {
-	.name		= "mct_tick0_irq",
-	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
-	.handler	= exynos4_mct_tick_isr,
-};
-
-static struct irqaction mct_tick1_event_irq = {
-	.name		= "mct_tick1_irq",
-	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
-	.handler	= exynos4_mct_tick_isr,
-};
-
-static void exynos4_mct_tick_init(struct clock_event_device *evt)
-{
-	unsigned int cpu = smp_processor_id();
-
-	mct_tick[cpu].evt = evt;
-
-	if (cpu == 0) {
-		mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
-		evt->name = "mct_tick0";
-	} else {
-		mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
-		evt->name = "mct_tick1";
-	}
-
-	evt->cpumask = cpumask_of(cpu);
-	evt->set_next_event = exynos4_tick_set_next_event;
-	evt->set_mode = exynos4_tick_set_mode;
-	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-	evt->rating = 450;
-
-	clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
-	evt->max_delta_ns =
-		clockevent_delta2ns(0x7fffffff, evt);
-	evt->min_delta_ns =
-		clockevent_delta2ns(0xf, evt);
-
-	clockevents_register_device(evt);
-
-	exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
-
-	if (cpu == 0) {
-		mct_tick0_event_irq.dev_id = &mct_tick[cpu];
-		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
-	} else {
-		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
-		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
-	}
-}
-
-/* Setup the local clock events for a CPU */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	exynos4_mct_tick_init(evt);
-
-	return 0;
-}
-
-int local_timer_ack(void)
-{
-	return 0;
-}
-
-#endif /* CONFIG_LOCAL_TIMERS */
-
-static void __init exynos4_timer_resources(void)
-{
-	struct clk *mct_clk;
-	mct_clk = clk_get(NULL, "xtal");
-
-	clk_rate = clk_get_rate(mct_clk);
-}
-
-static void __init exynos4_timer_init(void)
-{
-	exynos4_timer_resources();
-	exynos4_clocksource_init();
-	exynos4_clockevent_init();
-}
-
-struct sys_timer exynos4_timer = {
-	.init		= exynos4_timer_init,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/platsmp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/* linux/arch/arm/mach-exynos4/platsmp.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
-#include <asm/smp_scu.h>
-#include <asm/unified.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-pmu.h>
-
-extern void exynos4_secondary_startup(void);
-
-#define CPU1_BOOT_REG S5P_VA_SYSRAM
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-
-volatile int __cpuinitdata pen_release = -1;
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void write_pen_release(int val)
-{
-	pen_release = val;
-	smp_wmb();
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-}
-
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)(S5P_VA_SCU);
-}
-
-static DEFINE_SPINLOCK(boot_lock);
-
-static void __cpuinit exynos4_gic_secondary_init(void)
-{
-	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-	void __iomem *cpu_base = S5P_VA_GIC_CPU +
-				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-	int i;
-
-	/*
-	 * Deal with the banked PPI and SGI interrupts - disable all
-	 * PPI interrupts, ensure all SGI interrupts are enabled.
-	 */
-	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
-	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
-
-	/*
-	 * Set priority on PPI and SGI interrupts
-	 */
-	for (i = 0; i < 32; i += 4)
-		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
-
-	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
-}
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
-{
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	exynos4_gic_secondary_init();
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	write_pen_release(-1);
-
-	/*
-	 * Synchronise with the boot thread.
-	 */
-	spin_lock(&boot_lock);
-	spin_unlock(&boot_lock);
-
-	set_cpu_online(cpu, true);
-}
-
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	unsigned long timeout;
-
-	/*
-	 * Set synchronisation state between this boot processor
-	 * and the secondary one
-	 */
-	spin_lock(&boot_lock);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	write_pen_release(cpu);
-
-	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
-		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
-			     S5P_ARM_CORE1_CONFIGURATION);
-
-		timeout = 10;
-
-		/* wait max 10 ms until cpu1 is on */
-		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
-			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
-			if (timeout-- == 0)
-				break;
-
-			mdelay(1);
-		}
-
-		if (timeout == 0) {
-			printk(KERN_ERR "cpu1 power enable failed");
-			spin_unlock(&boot_lock);
-			return -ETIMEDOUT;
-		}
-	}
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-
-		__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
-			CPU1_BOOT_REG);
-		gic_raise_softirq(cpumask_of(cpu), 1);
-
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-
-void __init smp_init_cpus(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-	unsigned int i, ncores;
-
-	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "EXYNOS4: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
-}
-
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-
-	scu_enable(scu_base_addr());
-
-	/*
-	 * Write the address of secondary startup into the
-	 * system-wide flags register. The boot monitor waits
-	 * until it receives a soft interrupt, and then the
-	 * secondary CPU branches to this address.
-	 */
-	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/pm.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,486 +0,0 @@
-/* linux/arch/arm/mach-exynos4/pm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - Power Management support
- *
- * Based on arch/arm/mach-s3c2410/pm.c
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/syscore_ops.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/pll.h>
-#include <plat/regs-srom.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-pmu.h>
-#include <mach/pm-core.h>
-#include <mach/pmu.h>
-
-static struct sleep_save exynos4_set_clksrc[] = {
-	{ .reg = S5P_CLKSRC_MASK_TOP			, .val = 0x00000001, },
-	{ .reg = S5P_CLKSRC_MASK_CAM			, .val = 0x11111111, },
-	{ .reg = S5P_CLKSRC_MASK_TV			, .val = 0x00000111, },
-	{ .reg = S5P_CLKSRC_MASK_LCD0			, .val = 0x00001111, },
-	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
-	{ .reg = S5P_CLKSRC_MASK_MAUDIO			, .val = 0x00000001, },
-	{ .reg = S5P_CLKSRC_MASK_FSYS			, .val = 0x01011111, },
-	{ .reg = S5P_CLKSRC_MASK_PERIL0			, .val = 0x01111111, },
-	{ .reg = S5P_CLKSRC_MASK_PERIL1			, .val = 0x01110111, },
-	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
-};
-
-static struct sleep_save exynos4_epll_save[] = {
-	SAVE_ITEM(S5P_EPLL_CON0),
-	SAVE_ITEM(S5P_EPLL_CON1),
-};
-
-static struct sleep_save exynos4_vpll_save[] = {
-	SAVE_ITEM(S5P_VPLL_CON0),
-	SAVE_ITEM(S5P_VPLL_CON1),
-};
-
-static struct sleep_save exynos4_core_save[] = {
-	/* CMU side */
-	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
-	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(S5P_CLKSRC_TOP0),
-	SAVE_ITEM(S5P_CLKSRC_TOP1),
-	SAVE_ITEM(S5P_CLKSRC_CAM),
-	SAVE_ITEM(S5P_CLKSRC_TV),
-	SAVE_ITEM(S5P_CLKSRC_MFC),
-	SAVE_ITEM(S5P_CLKSRC_G3D),
-	SAVE_ITEM(S5P_CLKSRC_IMAGE),
-	SAVE_ITEM(S5P_CLKSRC_LCD0),
-	SAVE_ITEM(S5P_CLKSRC_LCD1),
-	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
-	SAVE_ITEM(S5P_CLKSRC_FSYS),
-	SAVE_ITEM(S5P_CLKSRC_PERIL0),
-	SAVE_ITEM(S5P_CLKSRC_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV_CAM),
-	SAVE_ITEM(S5P_CLKDIV_TV),
-	SAVE_ITEM(S5P_CLKDIV_MFC),
-	SAVE_ITEM(S5P_CLKDIV_G3D),
-	SAVE_ITEM(S5P_CLKDIV_IMAGE),
-	SAVE_ITEM(S5P_CLKDIV_LCD0),
-	SAVE_ITEM(S5P_CLKDIV_LCD1),
-	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
-	SAVE_ITEM(S5P_CLKDIV_FSYS0),
-	SAVE_ITEM(S5P_CLKDIV_FSYS1),
-	SAVE_ITEM(S5P_CLKDIV_FSYS2),
-	SAVE_ITEM(S5P_CLKDIV_FSYS3),
-	SAVE_ITEM(S5P_CLKDIV_PERIL0),
-	SAVE_ITEM(S5P_CLKDIV_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV_PERIL2),
-	SAVE_ITEM(S5P_CLKDIV_PERIL3),
-	SAVE_ITEM(S5P_CLKDIV_PERIL4),
-	SAVE_ITEM(S5P_CLKDIV_PERIL5),
-	SAVE_ITEM(S5P_CLKDIV_TOP),
-	SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
-	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
-	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
-	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV2_RATIO),
-	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
-	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
-	SAVE_ITEM(S5P_CLKGATE_IP_TV),
-	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
-	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
-	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
-	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
-	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
-	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
-	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
-	SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
-	SAVE_ITEM(S5P_CLKGATE_BLOCK),
-	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
-	SAVE_ITEM(S5P_CLKSRC_DMC),
-	SAVE_ITEM(S5P_CLKDIV_DMC0),
-	SAVE_ITEM(S5P_CLKDIV_DMC1),
-	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
-	SAVE_ITEM(S5P_CLKSRC_CPU),
-	SAVE_ITEM(S5P_CLKDIV_CPU),
-	SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
-	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
-
-	/* GIC side */
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
-	SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
-
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
-
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
-	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
-
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
-	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
-
-	/* SROM side */
-	SAVE_ITEM(S5P_SROM_BW),
-	SAVE_ITEM(S5P_SROM_BC0),
-	SAVE_ITEM(S5P_SROM_BC1),
-	SAVE_ITEM(S5P_SROM_BC2),
-	SAVE_ITEM(S5P_SROM_BC3),
-};
-
-static struct sleep_save exynos4_l2cc_save[] = {
-	SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
-	SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
-	SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
-	SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
-	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
-};
-
-/* For Cortex-A9 Diagnostic and Power control register */
-static unsigned int save_arm_register[2];
-
-static int exynos4_cpu_suspend(unsigned long arg)
-{
-	outer_flush_all();
-
-	/* issue the standby signal into the pm unit. */
-	cpu_do_idle();
-
-	/* we should never get past here */
-	panic("sleep resumed to originator?");
-}
-
-static void exynos4_pm_prepare(void)
-{
-	u32 tmp;
-
-	s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
-	s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
-	s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
-	s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
-
-	tmp = __raw_readl(S5P_INFORM1);
-
-	/* Set value of power down register for sleep mode */
-
-	exynos4_sys_powerdown_conf(SYS_SLEEP);
-	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
-
-	/* ensure at least INFORM0 has the resume address */
-
-	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
-
-	/* Before enter central sequence mode, clock src register have to set */
-
-	s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
-
-}
-
-static int exynos4_pm_add(struct sys_device *sysdev)
-{
-	pm_cpu_prep = exynos4_pm_prepare;
-	pm_cpu_sleep = exynos4_cpu_suspend;
-
-	return 0;
-}
-
-/* This function copy from linux/arch/arm/kernel/smp_scu.c */
-
-void exynos4_scu_enable(void __iomem *scu_base)
-{
-	u32 scu_ctrl;
-
-	scu_ctrl = __raw_readl(scu_base);
-	/* already enabled? */
-	if (scu_ctrl & 1)
-		return;
-
-	scu_ctrl |= 1;
-	__raw_writel(scu_ctrl, scu_base);
-
-	/*
-	 * Ensure that the data accessed by CPU0 before the SCU was
-	 * initialised is visible to the other CPUs.
-	 */
-	flush_cache_all();
-}
-
-static unsigned long pll_base_rate;
-
-static void exynos4_restore_pll(void)
-{
-	unsigned long pll_con, locktime, lockcnt;
-	unsigned long pll_in_rate;
-	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
-
-	if (pll_base_rate == 0)
-		return;
-
-	pll_in_rate = pll_base_rate;
-
-	/* EPLL */
-	pll_con = exynos4_epll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
-		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
-
-		pll_in_rate /= 1000000;
-
-		locktime = (3000 / pll_in_rate) * p_div;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, S5P_EPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_epll_save,
-					ARRAY_SIZE(exynos4_epll_save));
-		epll_wait = 1;
-	}
-
-	pll_in_rate = pll_base_rate;
-
-	/* VPLL */
-	pll_con = exynos4_vpll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_in_rate /= 1000000;
-		/* 750us */
-		locktime = 750;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, S5P_VPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_vpll_save,
-					ARRAY_SIZE(exynos4_vpll_save));
-		vpll_wait = 1;
-	}
-
-	/* Wait PLL locking */
-
-	do {
-		if (epll_wait) {
-			pll_con = __raw_readl(S5P_EPLL_CON0);
-			if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
-				epll_wait = 0;
-		}
-
-		if (vpll_wait) {
-			pll_con = __raw_readl(S5P_VPLL_CON0);
-			if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
-				vpll_wait = 0;
-		}
-	} while (epll_wait || vpll_wait);
-}
-
-static struct sysdev_driver exynos4_pm_driver = {
-	.add		= exynos4_pm_add,
-};
-
-static __init int exynos4_pm_drvinit(void)
-{
-	struct clk *pll_base;
-	unsigned int tmp;
-
-	s3c_pm_init();
-
-	/* All wakeup disable */
-
-	tmp = __raw_readl(S5P_WAKEUP_MASK);
-	tmp |= ((0xFF << 8) | (0x1F << 1));
-	__raw_writel(tmp, S5P_WAKEUP_MASK);
-
-	pll_base = clk_get(NULL, "xtal");
-
-	if (!IS_ERR(pll_base)) {
-		pll_base_rate = clk_get_rate(pll_base);
-		clk_put(pll_base);
-	}
-
-	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
-}
-arch_initcall(exynos4_pm_drvinit);
-
-static int exynos4_pm_suspend(void)
-{
-	unsigned long tmp;
-
-	/* Setting Central Sequence Register for power down mode */
-
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
-	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-
-	/* Save Power control register */
-	asm ("mrc p15, 0, %0, c15, c0, 0"
-	     : "=r" (tmp) : : "cc");
-	save_arm_register[0] = tmp;
-
-	/* Save Diagnostic register */
-	asm ("mrc p15, 0, %0, c15, c0, 1"
-	     : "=r" (tmp) : : "cc");
-	save_arm_register[1] = tmp;
-
-	return 0;
-}
-
-static void exynos4_pm_resume(void)
-{
-	unsigned long tmp;
-
-	/*
-	 * If PMU failed while entering sleep mode, WFI will be
-	 * ignored by PMU and then exiting cpu_do_idle().
-	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
-	 * in this situation.
-	 */
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
-		tmp |= S5P_CENTRAL_LOWPWR_CFG;
-		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-		/* No need to perform below restore code */
-		goto early_wakeup;
-	}
-	/* Restore Power control register */
-	tmp = save_arm_register[0];
-	asm volatile ("mcr p15, 0, %0, c15, c0, 0"
-		      : : "r" (tmp)
-		      : "cc");
-
-	/* Restore Diagnostic register */
-	tmp = save_arm_register[1];
-	asm volatile ("mcr p15, 0, %0, c15, c0, 1"
-		      : : "r" (tmp)
-		      : "cc");
-
-	/* For release retention */
-
-	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
-
-	s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
-
-	exynos4_restore_pll();
-
-	exynos4_scu_enable(S5P_VA_SCU);
-
-#ifdef CONFIG_CACHE_L2X0
-	s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
-	outer_inv_all();
-	/* enable L2X0*/
-	writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
-#endif
-
-early_wakeup:
-	return;
-}
-
-static struct syscore_ops exynos4_pm_syscore_ops = {
-	.suspend	= exynos4_pm_suspend,
-	.resume		= exynos4_pm_resume,
-};
-
-static __init int exynos4_pm_syscore_init(void)
-{
-	register_syscore_ops(&exynos4_pm_syscore_ops);
-	return 0;
-}
-arch_initcall(exynos4_pm_syscore_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/pmu.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/pmu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/pmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/* linux/arch/arm/mach-exynos4/pmu.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4210 - CPU PMU(Power Management Unit) support
- *
- * 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/io.h>
-#include <linux/kernel.h>
-
-#include <mach/regs-clock.h>
-#include <mach/pmu.h>
-
-static void __iomem *sys_powerdown_reg[] = {
-	S5P_ARM_CORE0_LOWPWR,
-	S5P_DIS_IRQ_CORE0,
-	S5P_DIS_IRQ_CENTRAL0,
-	S5P_ARM_CORE1_LOWPWR,
-	S5P_DIS_IRQ_CORE1,
-	S5P_DIS_IRQ_CENTRAL1,
-	S5P_ARM_COMMON_LOWPWR,
-	S5P_L2_0_LOWPWR,
-	S5P_L2_1_LOWPWR,
-	S5P_CMU_ACLKSTOP_LOWPWR,
-	S5P_CMU_SCLKSTOP_LOWPWR,
-	S5P_CMU_RESET_LOWPWR,
-	S5P_APLL_SYSCLK_LOWPWR,
-	S5P_MPLL_SYSCLK_LOWPWR,
-	S5P_VPLL_SYSCLK_LOWPWR,
-	S5P_EPLL_SYSCLK_LOWPWR,
-	S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
-	S5P_CMU_RESET_GPSALIVE_LOWPWR,
-	S5P_CMU_CLKSTOP_CAM_LOWPWR,
-	S5P_CMU_CLKSTOP_TV_LOWPWR,
-	S5P_CMU_CLKSTOP_MFC_LOWPWR,
-	S5P_CMU_CLKSTOP_G3D_LOWPWR,
-	S5P_CMU_CLKSTOP_LCD0_LOWPWR,
-	S5P_CMU_CLKSTOP_LCD1_LOWPWR,
-	S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
-	S5P_CMU_CLKSTOP_GPS_LOWPWR,
-	S5P_CMU_RESET_CAM_LOWPWR,
-	S5P_CMU_RESET_TV_LOWPWR,
-	S5P_CMU_RESET_MFC_LOWPWR,
-	S5P_CMU_RESET_G3D_LOWPWR,
-	S5P_CMU_RESET_LCD0_LOWPWR,
-	S5P_CMU_RESET_LCD1_LOWPWR,
-	S5P_CMU_RESET_MAUDIO_LOWPWR,
-	S5P_CMU_RESET_GPS_LOWPWR,
-	S5P_TOP_BUS_LOWPWR,
-	S5P_TOP_RETENTION_LOWPWR,
-	S5P_TOP_PWR_LOWPWR,
-	S5P_LOGIC_RESET_LOWPWR,
-	S5P_ONENAND_MEM_LOWPWR,
-	S5P_MODIMIF_MEM_LOWPWR,
-	S5P_G2D_ACP_MEM_LOWPWR,
-	S5P_USBOTG_MEM_LOWPWR,
-	S5P_HSMMC_MEM_LOWPWR,
-	S5P_CSSYS_MEM_LOWPWR,
-	S5P_SECSS_MEM_LOWPWR,
-	S5P_PCIE_MEM_LOWPWR,
-	S5P_SATA_MEM_LOWPWR,
-	S5P_PAD_RETENTION_DRAM_LOWPWR,
-	S5P_PAD_RETENTION_MAUDIO_LOWPWR,
-	S5P_PAD_RETENTION_GPIO_LOWPWR,
-	S5P_PAD_RETENTION_UART_LOWPWR,
-	S5P_PAD_RETENTION_MMCA_LOWPWR,
-	S5P_PAD_RETENTION_MMCB_LOWPWR,
-	S5P_PAD_RETENTION_EBIA_LOWPWR,
-	S5P_PAD_RETENTION_EBIB_LOWPWR,
-	S5P_PAD_RETENTION_ISOLATION_LOWPWR,
-	S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
-	S5P_XUSBXTI_LOWPWR,
-	S5P_XXTI_LOWPWR,
-	S5P_EXT_REGULATOR_LOWPWR,
-	S5P_GPIO_MODE_LOWPWR,
-	S5P_GPIO_MODE_MAUDIO_LOWPWR,
-	S5P_CAM_LOWPWR,
-	S5P_TV_LOWPWR,
-	S5P_MFC_LOWPWR,
-	S5P_G3D_LOWPWR,
-	S5P_LCD0_LOWPWR,
-	S5P_LCD1_LOWPWR,
-	S5P_MAUDIO_LOWPWR,
-	S5P_GPS_LOWPWR,
-	S5P_GPS_ALIVE_LOWPWR,
-};
-
-static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
-	/* { AFTR, LPA, SLEEP }*/
-	{ 0, 0, 2 },	/* ARM_CORE0 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE0 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL0 */
-	{ 0, 0, 2 },	/* ARM_CORE1 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE1 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL1 */
-	{ 0, 0, 2 },	/* ARM_COMMON */
-	{ 2, 2, 3 },	/* ARM_CPU_L2_0 */
-	{ 2, 2, 3 },	/* ARM_CPU_L2_1 */
-	{ 1, 0, 0 },	/* CMU_ACLKSTOP */
-	{ 1, 0, 0 },	/* CMU_SCLKSTOP */
-	{ 1, 1, 0 },	/* CMU_RESET */
-	{ 1, 0, 0 },	/* APLL_SYSCLK */
-	{ 1, 0, 0 },	/* MPLL_SYSCLK */
-	{ 1, 0, 0 },	/* VPLL_SYSCLK */
-	{ 1, 1, 0 },	/* EPLL_SYSCLK */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS_ALIVE */
-	{ 1, 1, 0 },	/* CMU_RESET_GPS_ALIVE */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_CAM */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_TV */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_MFC */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_G3D */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD0 */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD1 */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_MAUDIO */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS */
-	{ 1, 1, 0 },	/* CMU_RESET_CAM */
-	{ 1, 1, 0 },	/* CMU_RESET_TV */
-	{ 1, 1, 0 },	/* CMU_RESET_MFC */
-	{ 1, 1, 0 },	/* CMU_RESET_G3D */
-	{ 1, 1, 0 },	/* CMU_RESET_LCD0 */
-	{ 1, 1, 0 },	/* CMU_RESET_LCD1 */
-	{ 1, 1, 0 },	/* CMU_RESET_MAUDIO */
-	{ 1, 1, 0 },	/* CMU_RESET_GPS */
-	{ 3, 0, 0 },	/* TOP_BUS */
-	{ 1, 0, 1 },	/* TOP_RETENTION */
-	{ 3, 0, 3 },	/* TOP_PWR */
-	{ 1, 1, 0 },	/* LOGIC_RESET */
-	{ 3, 0, 0 },	/* ONENAND_MEM */
-	{ 3, 0, 0 },	/* MODIMIF_MEM */
-	{ 3, 0, 0 },	/* G2D_ACP_MEM */
-	{ 3, 0, 0 },	/* USBOTG_MEM */
-	{ 3, 0, 0 },	/* HSMMC_MEM */
-	{ 3, 0, 0 },	/* CSSYS_MEM */
-	{ 3, 0, 0 },	/* SECSS_MEM */
-	{ 3, 0, 0 },	/* PCIE_MEM */
-	{ 3, 0, 0 },	/* SATA_MEM */
-	{ 1, 0, 0 },	/* PAD_RETENTION_DRAM */
-	{ 1, 1, 0 },	/* PAD_RETENTION_MAUDIO */
-	{ 1, 0, 0 },	/* PAD_RETENTION_GPIO */
-	{ 1, 0, 0 },	/* PAD_RETENTION_UART */
-	{ 1, 0, 0 },	/* PAD_RETENTION_MMCA */
-	{ 1, 0, 0 },	/* PAD_RETENTION_MMCB */
-	{ 1, 0, 0 },	/* PAD_RETENTION_EBIA */
-	{ 1, 0, 0 },	/* PAD_RETENTION_EBIB */
-	{ 1, 0, 0 },	/* PAD_RETENTION_ISOLATION */
-	{ 1, 0, 0 },	/* PAD_RETENTION_ALV_SEL */
-	{ 1, 1, 0 },	/* XUSBXTI */
-	{ 1, 1, 0 },	/* XXTI */
-	{ 1, 1, 0 },	/* EXT_REGULATOR */
-	{ 1, 0, 0 },	/* GPIO_MODE */
-	{ 1, 1, 0 },	/* GPIO_MODE_MAUDIO */
-	{ 7, 0, 0 },	/* CAM */
-	{ 7, 0, 0 },	/* TV */
-	{ 7, 0, 0 },	/* MFC */
-	{ 7, 0, 0 },	/* G3D */
-	{ 7, 0, 0 },	/* LCD0 */
-	{ 7, 0, 0 },	/* LCD1 */
-	{ 7, 7, 0 },	/* MAUDIO */
-	{ 7, 0, 0 },	/* GPS */
-	{ 7, 0, 0 },	/* GPS_ALIVE */
-};
-
-void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
-{
-	unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
-
-	for (; count > 0; count--)
-		__raw_writel(sys_powerdown_val[count - 1][mode],
-				sys_powerdown_reg[count - 1]);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-fimc.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-fimc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-fimc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * Exynos4 camera interface GPIO configuration.
- *
- * 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/gpio.h>
-#include <plat/gpio-cfg.h>
-#include <plat/camport.h>
-
-int exynos4_fimc_setup_gpio(enum s5p_camport_id id)
-{
-	u32 gpio8, gpio5;
-	u32 sfn;
-	int ret;
-
-	switch (id) {
-	case S5P_CAMPORT_A:
-		gpio8 = EXYNOS4_GPJ0(0); /* PCLK, VSYNC, HREF, DATA[0:4] */
-		gpio5 = EXYNOS4_GPJ1(0); /* DATA[5:7], CLKOUT, FIELD */
-		sfn = S3C_GPIO_SFN(2);
-		break;
-
-	case S5P_CAMPORT_B:
-		gpio8 = EXYNOS4_GPE0(0); /* DATA[0:7] */
-		gpio5 = EXYNOS4_GPE1(0); /* PCLK, VSYNC, HREF, CLKOUT, FIELD */
-		sfn = S3C_GPIO_SFN(3);
-		break;
-
-	default:
-		WARN(1, "Wrong camport id: %d\n", id);
-		return -EINVAL;
-	}
-
-	ret = s3c_gpio_cfgall_range(gpio8, 8, sfn, S3C_GPIO_PULL_UP);
-	if (ret)
-		return ret;
-
-	return s3c_gpio_cfgall_range(gpio5, 5, sfn, S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-fimd0.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-fimd0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-fimd0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-fimd0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-fimd0.c
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Base Exynos4 FIMD 0 configuration
- *
- * 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/fb.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
-
-#include <mach/map.h>
-
-void exynos4_fimd0_gpio_setup_24bpp(void)
-{
-	unsigned int reg;
-
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
-
-	/*
-	 * Set DISPLAY_CONTROL register for Display path selection.
-	 *
-	 * DISPLAY_CONTROL[1:0]
-	 * ---------------------
-	 *  00 | MIE
-	 *  01 | MDINE
-	 *  10 | FIMD : selected
-	 *  11 | FIMD
-	 */
-	reg = __raw_readl(S3C_VA_SYS + 0x0210);
-	reg |= (1 << 1);
-	__raw_writel(reg, S3C_VA_SYS + 0x0210);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c0.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c1.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c1.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c1.c
- *
- * Copyright (C) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C1 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPD1(2), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c2.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c2.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *
- * I2C2 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c2_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPA0(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c3.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C3 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c3_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPA1(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c4.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C4 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c4_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c5.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c5.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c5.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C5 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c5_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c6.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c6.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C6 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c6_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
-			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c7.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c7.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-i2c7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/setup-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C7 GPIO configuration.
- *
- * 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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c7_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(EXYNOS4_GPD0(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-keypad.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-keypad.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-keypad.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * GPIO configuration for Exynos4 KeyPad device
- *
- * 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/gpio.h>
-#include <plat/gpio-cfg.h>
-
-void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
-{
-	/* Keypads can be of various combinations, Just making sure */
-
-	if (rows > 8) {
-		/* Set all the necessary GPX2 pins: KP_ROW[0~7] */
-		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3),
-					S3C_GPIO_PULL_UP);
-
-		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
-		s3c_gpio_cfgall_range(EXYNOS4_GPX3(0), (rows - 8),
-					 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-	} else {
-		/* Set all the necessary GPX2 pins: KP_ROW[x] */
-		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), rows, S3C_GPIO_SFN(3),
-					S3C_GPIO_PULL_UP);
-	}
-
-	/* Set all the necessary GPX1 pins to special-function 3: KP_COL[x] */
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPX1(0), cols, S3C_GPIO_SFN(3));
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-sdhci.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
- *
- * 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *exynos4_hsmmc_clksrcs[4] = {
-	[0] = NULL,
-	[1] = NULL,
-	[2] = "sclk_mmc",	/* mmc_bus */
-	[3] = NULL,
-};
-
-void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
-				  struct mmc_ios *ios, struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything according to card-type */
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-
-	/* select base clock source to HCLK */
-
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-
-	/*
-	 * clear async mode, enable conflict mask, rx feedback ctrl, SD
-	 * clk hold and no use debounce count
-	 */
-
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	/* Tx and Rx feedback clock delay control */
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-sdhci-gpio.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-sdhci-gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-sdhci-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-sdhci-gpio.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
-
-void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
-	for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
-			/* Data pin GPK1[3:6] to special-function 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) {
-			/* Data pin GPK0[3:6] to special-function 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(EXYNOS4_GPK0(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(EXYNOS4_GPK0(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
-	for (gpio = EXYNOS4_GPK1(0); gpio < EXYNOS4_GPK1(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
-		/* Data pin GPK1[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(EXYNOS4_GPK1(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(EXYNOS4_GPK1(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
-	for (gpio = EXYNOS4_GPK2(0); gpio < EXYNOS4_GPK2(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
-			/* Data pin GPK3[3:6] to special-function 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = EXYNOS4_GPK2(3); gpio <= EXYNOS4_GPK2(6); gpio++) {
-			/* Data pin GPK2[3:6] to special-function 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(EXYNOS4_GPK2(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(EXYNOS4_GPK2(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
-	for (gpio = EXYNOS4_GPK3(0); gpio < EXYNOS4_GPK3(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
-		/* Data pin GPK3[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(EXYNOS4_GPK3(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(EXYNOS4_GPK3(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-usb-phy.c linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-usb-phy.c
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/setup-usb-phy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/setup-usb-phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <mach/regs-pmu.h>
-#include <mach/regs-usb-phy.h>
-#include <plat/cpu.h>
-#include <plat/usb-phy.h>
-
-static int exynos4_usb_phy1_init(struct platform_device *pdev)
-{
-	struct clk *otg_clk;
-	struct clk *xusbxti_clk;
-	u32 phyclk;
-	u32 rstcon;
-	int err;
-
-	otg_clk = clk_get(&pdev->dev, "otg");
-	if (IS_ERR(otg_clk)) {
-		dev_err(&pdev->dev, "Failed to get otg clock\n");
-		return PTR_ERR(otg_clk);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
-
-	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
-			S5P_USBHOST_PHY_CONTROL);
-
-	/* set clock frequency for PLL */
-	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
-	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
-	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
-		switch (clk_get_rate(xusbxti_clk)) {
-		case 12 * MHZ:
-			phyclk |= CLKSEL_12M;
-			break;
-		case 24 * MHZ:
-			phyclk |= CLKSEL_24M;
-			break;
-		default:
-		case 48 * MHZ:
-			/* default reference clock */
-			break;
-		}
-		clk_put(xusbxti_clk);
-	}
-
-	writel(phyclk, EXYNOS4_PHYCLK);
-
-	/* floating prevention logic: disable */
-	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
-
-	/* set to normal HSIC 0 and 1 of PHY1 */
-	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
-			EXYNOS4_PHYPWR);
-
-	/* set to normal standard USB of PHY1 */
-	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
-
-	/* reset all ports of both PHY and Link */
-	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
-		PHY1_SWRST_MASK;
-	writel(rstcon, EXYNOS4_RSTCON);
-	udelay(10);
-
-	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
-	writel(rstcon, EXYNOS4_RSTCON);
-	udelay(80);
-
-	clk_disable(otg_clk);
-	clk_put(otg_clk);
-
-	return 0;
-}
-
-static int exynos4_usb_phy1_exit(struct platform_device *pdev)
-{
-	struct clk *otg_clk;
-	int err;
-
-	otg_clk = clk_get(&pdev->dev, "otg");
-	if (IS_ERR(otg_clk)) {
-		dev_err(&pdev->dev, "Failed to get otg clock\n");
-		return PTR_ERR(otg_clk);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
-
-	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
-			EXYNOS4_PHYPWR);
-
-	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
-			S5P_USBHOST_PHY_CONTROL);
-
-	clk_disable(otg_clk);
-	clk_put(otg_clk);
-
-	return 0;
-}
-
-int s5p_usb_phy_init(struct platform_device *pdev, int type)
-{
-	if (type == S5P_USB_PHY_HOST)
-		return exynos4_usb_phy1_init(pdev);
-
-	return -EINVAL;
-}
-
-int s5p_usb_phy_exit(struct platform_device *pdev, int type)
-{
-	if (type == S5P_USB_PHY_HOST)
-		return exynos4_usb_phy1_exit(pdev);
-
-	return -EINVAL;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-exynos4/sleep.S linux-libre-3.2-gnu1/arch/arm/mach-exynos4/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/mach-exynos4/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-exynos4/sleep.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/* linux/arch/arm/mach-exynos4/sleep.S
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 power Manager (Suspend-To-RAM) support
- * Based on S3C2410 sleep code by:
- *	Ben Dooks, (c) 2004 Simtec Electronics
- *
- * Based on PXA/SA1100 sleep code by:
- *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *	Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/memory.h>
-
-	.text
-
-	/*
-	 * sleep magic, to allow the bootloader to check for an valid
-	 * image to resume to. Must be the first word before the
-	 * s3c_cpu_resume entry.
-	 */
-
-	.word	0x2bedf00d
-
-	/*
-	 * s3c_cpu_resume
-	 *
-	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
-	 */
-
-ENTRY(s3c_cpu_resume)
-	b	cpu_resume
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/cats-hw.c linux-libre-3.2-gnu1/arch/arm/mach-footbridge/cats-hw.c
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/cats-hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/cats-hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,8 +76,7 @@ __initcall(cats_hw_init);
  * hard reboots fail on early boards.
  */
 static void __init
-fixup_cats(struct machine_desc *desc, struct tag *tags,
-	   char **cmdline, struct meminfo *mi)
+fixup_cats(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	screen_info.orig_video_lines  = 25;
 	screen_info.orig_video_points = 16;
@@ -86,7 +85,7 @@ fixup_cats(struct machine_desc *desc, st
 
 MACHINE_START(CATS, "Chalice-CATS")
 	/* Maintainer: Philip Blundell */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.soft_reboot	= 1,
 	.fixup		= fixup_cats,
 	.map_io		= footbridge_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/ebsa285.c linux-libre-3.2-gnu1/arch/arm/mach-footbridge/ebsa285.c
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/ebsa285.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/ebsa285.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 MACHINE_START(EBSA285, "EBSA285")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
 	.map_io		= footbridge_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 #ifndef CONFIG_DEBUG_DC21285_PORT
 	/* For NetWinder debugging */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x000003f8
 		orr	\rv, \rp, #0xff000000	@ virtual
 		orr	\rp, \rp, #0x7c000000	@ physical
@@ -31,7 +31,7 @@
 		.equ	dc21285_high, ARMCSR_BASE & 0xff000000
 		.equ	dc21285_low,  ARMCSR_BASE & 0x00ffffff
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		.if	dc21285_low
 		mov	\rp, #dc21285_low
 		.else
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 #define CPLD_FLASH_WR_ENABLE	1
 
 #ifndef __ASSEMBLY__
-extern spinlock_t nw_gpio_lock;
+extern raw_spinlock_t nw_gpio_lock;
 extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
 extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
 extern unsigned int nw_gpio_read(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,8 +23,6 @@
 #define PCIO_SIZE       0x00100000
 #define PCIO_BASE       MMU_IO(0xff000000, 0x7c000000)
 
-#define IO_SPACE_LIMIT 0xffff
-
 /*
  * Translation of various region addresses to virtual addresses
  */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-footbridge/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@ menu "Footbridge Implementations"
 
 config ARCH_CATS
 	bool "CATS"
-	select CLKSRC_I8253
 	select CLKEVT_I8253
+	select CLKSRC_I8253
 	select FOOTBRIDGE_HOST
 	select ISA
 	select ISA_DMA
@@ -61,8 +61,8 @@ config ARCH_EBSA285_HOST
 
 config ARCH_NETWINDER
 	bool "NetWinder"
-	select CLKSRC_I8253
 	select CLKEVT_I8253
+	select CLKSRC_I8253
 	select FOOTBRIDGE_HOST
 	select ISA
 	select ISA_DMA
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-footbridge/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/netwinder-hw.c linux-libre-3.2-gnu1/arch/arm/mach-footbridge/netwinder-hw.c
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/netwinder-hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/netwinder-hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ static inline void wb977_ww(int reg, int
 /*
  * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
  */
-DEFINE_SPINLOCK(nw_gpio_lock);
+DEFINE_RAW_SPINLOCK(nw_gpio_lock);
 EXPORT_SYMBOL(nw_gpio_lock);
 
 static unsigned int current_gpio_op;
@@ -327,9 +327,9 @@ static inline void wb977_init_gpio(void)
 	/*
 	 * Set Group1/Group2 outputs
 	 */
-	spin_lock_irqsave(&nw_gpio_lock, flags);
+	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 	nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
-	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 /*
@@ -390,9 +390,9 @@ static void __init cpld_init(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&nw_gpio_lock, flags);
+	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 	nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
-	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 static unsigned char rwa_unlock[] __initdata =
@@ -616,9 +616,9 @@ static int __init nw_hw_init(void)
 		cpld_init();
 		rwa010_init();
 
-		spin_lock_irqsave(&nw_gpio_lock, flags);
+		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 		nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
-		spin_unlock_irqrestore(&nw_gpio_lock, flags);
+		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 	}
 	return 0;
 }
@@ -631,8 +631,7 @@ __initcall(nw_hw_init);
  * the parameter page.
  */
 static void __init
-fixup_netwinder(struct machine_desc *desc, struct tag *tags,
-		char **cmdline, struct meminfo *mi)
+fixup_netwinder(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 #ifdef CONFIG_ISAPNP
 	extern int isapnp_disable;
@@ -648,7 +647,7 @@ fixup_netwinder(struct machine_desc *des
 
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
 	/* Maintainer: Russell King/Rebel.com */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
 	.reserve_lp0	= 1,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/netwinder-leds.c linux-libre-3.2-gnu1/arch/arm/mach-footbridge/netwinder-leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/netwinder-leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/netwinder-leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,13 +31,13 @@
 static char led_state;
 static char hw_led_state;
 
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
 
 static void netwinder_leds_event(led_event_t evt)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&leds_lock, flags);
+	raw_spin_lock_irqsave(&leds_lock, flags);
 
 	switch (evt) {
 	case led_start:
@@ -117,12 +117,12 @@ static void netwinder_leds_event(led_eve
 		break;
 	}
 
-	spin_unlock_irqrestore(&leds_lock, flags);
+	raw_spin_unlock_irqrestore(&leds_lock, flags);
 
 	if  (led_state & LED_STATE_ENABLED) {
-		spin_lock_irqsave(&nw_gpio_lock, flags);
+		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 		nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
-		spin_unlock_irqrestore(&nw_gpio_lock, flags);
+		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 	}
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-footbridge/personal.c linux-libre-3.2-gnu1/arch/arm/mach-footbridge/personal.c
--- linux-libre-3.1-gnu1/arch/arm/mach-footbridge/personal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-footbridge/personal.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
 	/* Maintainer: Jamey Hicks / George France */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
 	.timer		= &footbridge_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-nas4220b.c linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-nas4220b.c
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-nas4220b.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-nas4220b.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@ static void __init ib4220b_init(void)
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &ib4220b_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-rut1xx.c linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-rut1xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-rut1xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-rut1xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@ static void __init rut1xx_init(void)
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &rut1xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-wbd111.c linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-wbd111.c
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-wbd111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-wbd111.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@ static void __init wbd111_init(void)
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &wbd111_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-wbd222.c linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-wbd222.c
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/board-wbd222.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/board-wbd222.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@ static void __init wbd222_init(void)
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &wbd222_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =GEMINI_UART_BASE			@ physical
 	ldr	\rv, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #define __MACH_GPIO_H__
 
 #include <mach/irqs.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 #define gpio_to_irq(x)	((x) + GPIO_IRQ_BASE)
 #define irq_to_gpio(x)	((x) - GPIO_IRQ_BASE)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#ifdef CONFIG_GEMINI_MEM_SWAP
-# define PLAT_PHYS_OFFSET	UL(0x00000000)
-#else
-# define PLAT_PHYS_OFFSET	UL(0x10000000)
-#endif
-
-#endif /* __MACH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-gemini/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-gemini/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-gemini/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-gemini/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 else
-   zreladdr-y	:= 0x10008000
+   zreladdr-y	+= 0x10008000
 params_phys-y	:= 0x10000100
 initrd_phys-y	:= 0x10800000
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-h720x/h7201-eval.c linux-libre-3.2-gnu1/arch/arm/mach-h720x/h7201-eval.c
--- linux-libre-3.1-gnu1/arch/arm/mach-h720x/h7201-eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-h720x/h7201-eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 
 MACHINE_START(H7201, "Hynix GMS30C7201")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.boot_params	= 0xc0001000,
+	.atag_offset	= 0x1000,
 	.map_io		= h720x_map_io,
 	.init_irq	= h720x_init_irq,
 	.timer		= &h7201_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-h720x/h7202-eval.c linux-libre-3.2-gnu1/arch/arm/mach-h720x/h7202-eval.c
--- linux-libre-3.1-gnu1/arch/arm/mach-h720x/h7202-eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-h720x/h7202-eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@ static void __init init_eval_h7202(void)
 
 MACHINE_START(H7202, "Hynix HMS30C7202")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.boot_params	= 0x40000100,
+	.atag_offset	= 0x100,
 	.map_io		= h720x_map_io,
 	.init_irq	= h7202_init_irq,
 	.timer		= &h7202_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-h720x/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-h720x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-h720x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-h720x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 		.equ    io_virt, IO_VIRT
 		.equ    io_phys, IO_PHYS
 
-		.macro  addruart, rp, rv
+		.macro  addruart, rp, rv, tmp
 		mov     \rp, #0x00020000	@ UART1
 		add     \rv, \rp, #io_virt	@ virtual address
 		add     \rp, \rp, #io_phys	@ physical base address
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-h720x/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-h720x/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-h720x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-h720x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/memory.h
- *
- * Copyright (c) 2000 Jungjun Kim
- *
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x40000000)
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-h720x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-h720x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-h720x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-h720x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-$(CONFIG_ARCH_H720X)	:= 0x40008000
+   zreladdr-$(CONFIG_ARCH_H720X)	+= 0x40008000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/clock.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+struct clk {
+	unsigned long rate;
+};
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
+static struct clk eclk = { .rate = 200000000 };
+static struct clk pclk = { .rate = 150000000 };
+
+static struct clk_lookup lookups[] = {
+	{ .clk = &pclk, .con_id = "apb_pclk", },
+	{ .clk = &pclk, .dev_id = "sp804", },
+	{ .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
+	{ .clk = &pclk, .dev_id = "fff36000.serial", },
+};
+
+void __init highbank_clocks_init(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/core.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
+extern void highbank_clocks_init(void);
+extern void __iomem *scu_base_addr;
+#ifdef CONFIG_DEBUG_HIGHBANK_UART
+extern void highbank_lluart_map_io(void);
+#else
+static inline void highbank_lluart_map_io(void) {}
+#endif
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/highbank.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/highbank.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/highbank.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/highbank.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unified.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void __iomem *sregs_base;
+
+#define HB_SCU_VIRT_BASE	0xfee00000
+void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+	.virtual	= HB_SCU_VIRT_BASE,
+	.pfn		= 0, /* run-time */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+static void __init highbank_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+}
+
+static void __init highbank_map_io(void)
+{
+	highbank_scu_map_io();
+	highbank_lluart_map_io();
+}
+
+#define HB_JUMP_TABLE_PHYS(cpu)		(0x40 + (0x10 * (cpu)))
+#define HB_JUMP_TABLE_VIRT(cpu)		phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
+
+void highbank_set_cpu_jump(int cpu, void *jump_addr)
+{
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(cpu);
+#endif
+	writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
+	__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
+	outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
+			  HB_JUMP_TABLE_PHYS(cpu) + 15);
+}
+
+const static struct of_device_id irq_match[] = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{}
+};
+
+static void __init highbank_init_irq(void)
+{
+	of_irq_init(irq_match);
+	l2x0_of_init(0, ~0UL);
+}
+
+static void __init highbank_timer_init(void)
+{
+	int irq;
+	struct device_node *np;
+	void __iomem *timer_base;
+
+	/* Map system registers */
+	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+	sregs_base = of_iomap(np, 0);
+	WARN_ON(!sregs_base);
+
+	np = of_find_compatible_node(NULL, NULL, "arm,sp804");
+	timer_base = of_iomap(np, 0);
+	WARN_ON(!timer_base);
+	irq = irq_of_parse_and_map(np, 0);
+
+	highbank_clocks_init();
+
+	sp804_clocksource_init(timer_base + 0x20, "timer1");
+	sp804_clockevents_init(timer_base, irq, "timer0");
+}
+
+static struct sys_timer highbank_timer = {
+	.init = highbank_timer_init,
+};
+
+static void highbank_power_off(void)
+{
+	hignbank_set_pwr_shutdown();
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	while (1)
+		cpu_do_idle();
+}
+
+static void __init highbank_init(void)
+{
+	pm_power_off = highbank_power_off;
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *highbank_match[] __initconst = {
+	"calxeda,highbank",
+	NULL,
+};
+
+DT_MACHINE_START(HIGHBANK, "Highbank")
+	.map_io		= highbank_map_io,
+	.init_irq	= highbank_init_irq,
+	.timer		= &highbank_timer,
+	.init_machine	= highbank_init,
+	.dt_compat	= highbank_match,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+
+	highbank_set_cpu_jump(cpu, secondary_startup);
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * CPU0 should not be shut down via hotplug.  cpu_idle can WFI
+	 * or a proper shutdown or hibernate should be used.
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+		.macro	addruart,rp,rv,tmp
+		movw	\rv, #0x6000
+		movt	\rv, #0xfee3
+		movw	\rp, #0x6000
+		movt	\rp, #0xfff3
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#include <asm/hardware/entry-macro-gic.S>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define __io(a)		({ (void)(a); __typesafe_io(0); })
+#define __mem_pci(a)	(a)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define NR_IRQS			192
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+extern void arch_reset(char mode, const char *cmd);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		1000000
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+#define VMALLOC_END		0xFEE00000UL
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/lluart.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/lluart.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/lluart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/lluart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#define HB_DEBUG_LL_PHYS_BASE	0xfff36000
+#define HB_DEBUG_LL_VIRT_BASE	0xfee36000
+
+static struct map_desc lluart_io_desc __initdata = {
+	.virtual	= HB_DEBUG_LL_VIRT_BASE,
+	.pfn		= __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init highbank_lluart_map_io(void)
+{
+	iotable_init(&lluart_io_desc, 1);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/localtimer.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/localtimer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/localtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on localtimer.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/Makefile linux-libre-3.2-gnu1/arch/arm/mach-highbank/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+obj-y					:= clock.o highbank.o system.o
+obj-$(CONFIG_DEBUG_HIGHBANK_UART)	+= lluart.o
+obj-$(CONFIG_SMP)			+= platsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+obj-$(CONFIG_PM_SLEEP)			+= pm.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-highbank/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+zreladdr-y	:= 0x00008000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	gic_raise_softirq(cpumask_of(cpu), 0);
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i, ncores;
+
+	ncores = scu_get_core_count(scu_base_addr);
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "highbank: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	scu_enable(scu_base_addr);
+
+	/*
+	 * Write the address of secondary startup into the jump table
+	 * The cores are in wfi and wait until they receive a soft interrupt
+	 * and a non-zero value to jump to. Then the secondary CPU branches
+	 * to this address.
+	 */
+	for (i = 1; i < max_cpus; i++)
+		highbank_set_cpu_jump(i, secondary_startup);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/pm.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+static int highbank_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int highbank_pm_enter(suspend_state_t state)
+{
+	hignbank_set_pwr_suspend();
+	highbank_set_cpu_jump(0, cpu_resume);
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_suspend(0, highbank_suspend_finish);
+
+	return 0;
+}
+
+static const struct platform_suspend_ops highbank_pm_ops = {
+	.enter = highbank_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init highbank_pm_init(void)
+{
+	suspend_set_ops(&highbank_pm_ops);
+	return 0;
+}
+module_init(highbank_pm_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/sysregs.h linux-libre-3.2-gnu1/arch/arm/mach-highbank/sysregs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/sysregs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/sysregs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _MACH_HIGHBANK__SYSREGS_H_
+#define _MACH_HIGHBANK__SYSREGS_H_
+
+#include <linux/io.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_SREG_A9_PWR_REQ		0xf00
+#define HB_SREG_A9_BOOT_STAT		0xf04
+#define HB_SREG_A9_BOOT_DATA		0xf08
+
+#define HB_PWR_SUSPEND			0
+#define HB_PWR_SOFT_RESET		1
+#define HB_PWR_HARD_RESET		2
+#define HB_PWR_SHUTDOWN			3
+
+static inline void hignbank_set_pwr_suspend(void)
+{
+	writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_shutdown(void)
+{
+	writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_soft_reset(void)
+{
+	writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_hard_reset(void)
+{
+	writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-highbank/system.c linux-libre-3.2-gnu1/arch/arm/mach-highbank/system.c
--- linux-libre-3.1-gnu1/arch/arm/mach-highbank/system.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-highbank/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+#include <asm/proc-fns.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void arch_reset(char mode, const char *cmd)
+{
+	if (mode == 'h')
+		hignbank_set_pwr_hard_reset();
+	else
+		hignbank_set_pwr_soft_reset();
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_do_idle();
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/cache-l2x0.c linux-libre-3.2-gnu1/arch/arm/mach-imx/cache-l2x0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/cache-l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/cache-l2x0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- * Juergen Beisert <j.beisert@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/hardware.h>
-
-static int mxc_init_l2x0(void)
-{
-	void __iomem *l2x0_base;
-	void __iomem *clkctl_base;
-
-	if (!cpu_is_mx31() && !cpu_is_mx35())
-		return 0;
-
-/*
- * First of all, we must repair broken chip settings. There are some
- * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
- * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
- * Workaraound is to setup the correct register setting prior enabling the
- * L2 cache. This should not hurt already working CPUs, as they are using the
- * same value.
- */
-#define L2_MEM_VAL 0x10
-
-	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
-	if (clkctl_base != NULL) {
-		writel(0x00000515, clkctl_base + L2_MEM_VAL);
-		iounmap(clkctl_base);
-	} else {
-		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
-	}
-
-	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-	if (IS_ERR(l2x0_base)) {
-		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-				PTR_ERR(l2x0_base));
-		return 0;
-	}
-
-	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
-
-	return 0;
-}
-arch_initcall(mxc_init_l2x0);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx25.c linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx25.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx25.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -263,6 +263,7 @@ DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0
 DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
 DEFINE_CLOCK(can1_clk,	 0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(can2_clk,	 1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(iim_clk,    0, CCM_CGCR1, 26, NULL, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -310,6 +311,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	/* i.mx25 has the i.mx35 type sdma */
 	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
 };
 
 int __init mx25_clocks_init(void)
@@ -334,6 +336,10 @@ int __init mx25_clocks_init(void)
 	/* Clock source for gpt is ahb_div */
 	__raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
 
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX25", mx25_revision());
+	clk_disable(&iim_clk);
+
 	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx27.c linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx27.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -583,7 +583,7 @@ DEFINE_CLOCK(emi_clk,      0, PCCR1, 19,
 DEFINE_CLOCK(dma_clk1,     0, PCCR1, 20, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(csi_clk1,     0, PCCR1, 21, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(brom_clk,     0, PCCR1, 22, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(ata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(pata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(wdog_clk,     0, PCCR1, 24, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(usb_clk,      0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
 DEFINE_CLOCK(uart6_clk1,   0, PCCR1, 26, NULL, NULL, &ipg_clk);
@@ -666,7 +666,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
 	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
@@ -751,6 +751,8 @@ int __init mx27_clocks_init(unsigned lon
 	clk_enable(&gpio_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX27", mx27_revision());
+	clk_disable(&iim_clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
 	clk_enable(&uart1_clk);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx31.c linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx31.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -476,7 +476,7 @@ DEFINE_CLOCK(gpt_clk,     0, MXC_CCM_CGR
 DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
@@ -562,7 +562,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK(NULL, "firi", firi_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
 	_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
@@ -611,11 +611,11 @@ int __init mx31_clocks_init(unsigned lon
 	clk_enable(&gpt_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	mx31_revision();
+	clk_disable(&iim_clk);
 
 	clk_enable(&serial_pll_clk);
 
-	mx31_read_cpu_rev();
-
 	if (mx31_revision() >= IMX_CHIP_REVISION_2_0) {
 		reg = __raw_readl(MXC_CCM_PMCR1);
 		/* No PLL restart on DVFS switch; enable auto EMI handshake */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx35.c linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx35.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -354,7 +354,7 @@ static void clk_cgr_disable(struct clk *
 	}
 
 DEFINE_CLOCK(asrc_clk,   0, CCM_CGR0,  0, NULL, NULL);
-DEFINE_CLOCK(ata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
+DEFINE_CLOCK(pata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
 /* DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0,  4, NULL, NULL); */
 DEFINE_CLOCK(can1_clk,   0, CCM_CGR0,  6, get_rate_ipg, NULL);
 DEFINE_CLOCK(can2_clk,   1, CCM_CGR0,  8, get_rate_ipg, NULL);
@@ -447,7 +447,7 @@ static struct clk nfc_clk = {
 
 static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
@@ -507,7 +507,7 @@ static struct clk_lookup lookups[] = {
 
 int __init mx35_clocks_init()
 {
-	unsigned int cgr2 = 3 << 26, cgr3 = 0;
+	unsigned int cgr2 = 3 << 26;
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
 	cgr2 |= 3 << 16;
@@ -521,6 +521,12 @@ int __init mx35_clocks_init()
 	__raw_writel((3 << 18), CCM_BASE + CCM_CGR0);
 	__raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
 			CCM_BASE + CCM_CGR1);
+	__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
+	__raw_writel(0, CCM_BASE + CCM_CGR3);
+
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX35", mx35_revision());
+	clk_disable(&iim_clk);
 
 	/*
 	 * Check if we came up in internal boot mode. If yes, we need some
@@ -529,16 +535,11 @@ int __init mx35_clocks_init()
 	 */
 	if (!(__raw_readl(CCM_BASE + CCM_RCSR) & (3 << 10))) {
 		/* Additionally turn on UART1, SCC, and IIM clocks */
-		cgr2 |= 3 << 16 | 3 << 4;
-		cgr3 |= 3 << 2;
+		clk_enable(&iim_clk);
+		clk_enable(&uart1_clk);
+		clk_enable(&scc_clk);
 	}
 
-	__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
-	__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
-
-	clk_enable(&iim_clk);
-	mx35_read_cpu_rev();
-
 #ifdef CONFIG_MXC_USE_EPIT
 	epit_timer_init(&epit1_clk,
 			MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx6q.c linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx6q.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/clock-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/clock-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2030 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/div64.h>
+#include <asm/mach/map.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#define PLL_BASE		IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
+#define PLL1_SYS		(PLL_BASE + 0x000)
+#define PLL2_BUS		(PLL_BASE + 0x030)
+#define PLL3_USB_OTG		(PLL_BASE + 0x010)
+#define PLL4_AUDIO		(PLL_BASE + 0x070)
+#define PLL5_VIDEO		(PLL_BASE + 0x0a0)
+#define PLL6_MLB		(PLL_BASE + 0x0d0)
+#define PLL7_USB_HOST		(PLL_BASE + 0x020)
+#define PLL8_ENET		(PLL_BASE + 0x0e0)
+#define PFD_480			(PLL_BASE + 0x0f0)
+#define PFD_528			(PLL_BASE + 0x100)
+#define PLL_NUM_OFFSET		0x010
+#define PLL_DENOM_OFFSET	0x020
+
+#define PFD0			7
+#define PFD1			15
+#define PFD2			23
+#define PFD3			31
+#define PFD_FRAC_MASK		0x3f
+
+#define BM_PLL_BYPASS			(0x1 << 16)
+#define BM_PLL_ENABLE			(0x1 << 13)
+#define BM_PLL_POWER_DOWN		(0x1 << 12)
+#define BM_PLL_LOCK			(0x1 << 31)
+#define BP_PLL_SYS_DIV_SELECT		0
+#define BM_PLL_SYS_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_BUS_DIV_SELECT		0
+#define BM_PLL_BUS_DIV_SELECT		(0x1 << 0)
+#define BP_PLL_USB_DIV_SELECT		0
+#define BM_PLL_USB_DIV_SELECT		(0x3 << 0)
+#define BP_PLL_AV_DIV_SELECT		0
+#define BM_PLL_AV_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_ENET_DIV_SELECT		0
+#define BM_PLL_ENET_DIV_SELECT		(0x3 << 0)
+#define BM_PLL_ENET_EN_PCIE		(0x1 << 19)
+#define BM_PLL_ENET_EN_SATA		(0x1 << 20)
+
+#define CCM_BASE	IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
+#define CCR		(CCM_BASE + 0x00)
+#define CCDR		(CCM_BASE + 0x04)
+#define CSR		(CCM_BASE + 0x08)
+#define CCSR		(CCM_BASE + 0x0c)
+#define CACRR		(CCM_BASE + 0x10)
+#define CBCDR		(CCM_BASE + 0x14)
+#define CBCMR		(CCM_BASE + 0x18)
+#define CSCMR1		(CCM_BASE + 0x1c)
+#define CSCMR2		(CCM_BASE + 0x20)
+#define CSCDR1		(CCM_BASE + 0x24)
+#define CS1CDR		(CCM_BASE + 0x28)
+#define CS2CDR		(CCM_BASE + 0x2c)
+#define CDCDR		(CCM_BASE + 0x30)
+#define CHSCCDR		(CCM_BASE + 0x34)
+#define CSCDR2		(CCM_BASE + 0x38)
+#define CSCDR3		(CCM_BASE + 0x3c)
+#define CSCDR4		(CCM_BASE + 0x40)
+#define CWDR		(CCM_BASE + 0x44)
+#define CDHIPR		(CCM_BASE + 0x48)
+#define CDCR		(CCM_BASE + 0x4c)
+#define CTOR		(CCM_BASE + 0x50)
+#define CLPCR		(CCM_BASE + 0x54)
+#define CISR		(CCM_BASE + 0x58)
+#define CIMR		(CCM_BASE + 0x5c)
+#define CCOSR		(CCM_BASE + 0x60)
+#define CGPR		(CCM_BASE + 0x64)
+#define CCGR0		(CCM_BASE + 0x68)
+#define CCGR1		(CCM_BASE + 0x6c)
+#define CCGR2		(CCM_BASE + 0x70)
+#define CCGR3		(CCM_BASE + 0x74)
+#define CCGR4		(CCM_BASE + 0x78)
+#define CCGR5		(CCM_BASE + 0x7c)
+#define CCGR6		(CCM_BASE + 0x80)
+#define CCGR7		(CCM_BASE + 0x84)
+#define CMEOR		(CCM_BASE + 0x88)
+
+#define CG0		0
+#define CG1		2
+#define CG2		4
+#define CG3		6
+#define CG4		8
+#define CG5		10
+#define CG6		12
+#define CG7		14
+#define CG8		16
+#define CG9		18
+#define CG10		20
+#define CG11		22
+#define CG12		24
+#define CG13		26
+#define CG14		28
+#define CG15		30
+
+#define BM_CCSR_PLL1_SW_SEL		(0x1 << 2)
+#define BM_CCSR_STEP_SEL		(0x1 << 8)
+
+#define BP_CACRR_ARM_PODF		0
+#define BM_CACRR_ARM_PODF		(0x7 << 0)
+
+#define BP_CBCDR_PERIPH2_CLK2_PODF	0
+#define BM_CBCDR_PERIPH2_CLK2_PODF	(0x7 << 0)
+#define BP_CBCDR_MMDC_CH1_AXI_PODF	3
+#define BM_CBCDR_MMDC_CH1_AXI_PODF	(0x7 << 3)
+#define BP_CBCDR_AXI_SEL		6
+#define BM_CBCDR_AXI_SEL		(0x3 << 6)
+#define BP_CBCDR_IPG_PODF		8
+#define BM_CBCDR_IPG_PODF		(0x3 << 8)
+#define BP_CBCDR_AHB_PODF		10
+#define BM_CBCDR_AHB_PODF		(0x7 << 10)
+#define BP_CBCDR_AXI_PODF		16
+#define BM_CBCDR_AXI_PODF		(0x7 << 16)
+#define BP_CBCDR_MMDC_CH0_AXI_PODF	19
+#define BM_CBCDR_MMDC_CH0_AXI_PODF	(0x7 << 19)
+#define BP_CBCDR_PERIPH_CLK_SEL		25
+#define BM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
+#define BP_CBCDR_PERIPH2_CLK_SEL	26
+#define BM_CBCDR_PERIPH2_CLK_SEL	(0x1 << 26)
+#define BP_CBCDR_PERIPH_CLK2_PODF	27
+#define BM_CBCDR_PERIPH_CLK2_PODF	(0x7 << 27)
+
+#define BP_CBCMR_GPU2D_AXI_SEL		0
+#define BM_CBCMR_GPU2D_AXI_SEL		(0x1 << 0)
+#define BP_CBCMR_GPU3D_AXI_SEL		1
+#define BM_CBCMR_GPU3D_AXI_SEL		(0x1 << 1)
+#define BP_CBCMR_GPU3D_CORE_SEL		4
+#define BM_CBCMR_GPU3D_CORE_SEL		(0x3 << 4)
+#define BP_CBCMR_GPU3D_SHADER_SEL	8
+#define BM_CBCMR_GPU3D_SHADER_SEL	(0x3 << 8)
+#define BP_CBCMR_PCIE_AXI_SEL		10
+#define BM_CBCMR_PCIE_AXI_SEL		(0x1 << 10)
+#define BP_CBCMR_VDO_AXI_SEL		11
+#define BM_CBCMR_VDO_AXI_SEL		(0x1 << 11)
+#define BP_CBCMR_PERIPH_CLK2_SEL	12
+#define BM_CBCMR_PERIPH_CLK2_SEL	(0x3 << 12)
+#define BP_CBCMR_VPU_AXI_SEL		14
+#define BM_CBCMR_VPU_AXI_SEL		(0x3 << 14)
+#define BP_CBCMR_GPU2D_CORE_SEL		16
+#define BM_CBCMR_GPU2D_CORE_SEL		(0x3 << 16)
+#define BP_CBCMR_PRE_PERIPH_CLK_SEL	18
+#define BM_CBCMR_PRE_PERIPH_CLK_SEL	(0x3 << 18)
+#define BP_CBCMR_PERIPH2_CLK2_SEL	20
+#define BM_CBCMR_PERIPH2_CLK2_SEL	(0x1 << 20)
+#define BP_CBCMR_PRE_PERIPH2_CLK_SEL	21
+#define BM_CBCMR_PRE_PERIPH2_CLK_SEL	(0x3 << 21)
+#define BP_CBCMR_GPU2D_CORE_PODF	23
+#define BM_CBCMR_GPU2D_CORE_PODF	(0x7 << 23)
+#define BP_CBCMR_GPU3D_CORE_PODF	26
+#define BM_CBCMR_GPU3D_CORE_PODF	(0x7 << 26)
+#define BP_CBCMR_GPU3D_SHADER_PODF	29
+#define BM_CBCMR_GPU3D_SHADER_PODF	(0x7 << 29)
+
+#define BP_CSCMR1_PERCLK_PODF		0
+#define BM_CSCMR1_PERCLK_PODF		(0x3f << 0)
+#define BP_CSCMR1_SSI1_SEL		10
+#define BM_CSCMR1_SSI1_SEL		(0x3 << 10)
+#define BP_CSCMR1_SSI2_SEL		12
+#define BM_CSCMR1_SSI2_SEL		(0x3 << 12)
+#define BP_CSCMR1_SSI3_SEL		14
+#define BM_CSCMR1_SSI3_SEL		(0x3 << 14)
+#define BP_CSCMR1_USDHC1_SEL		16
+#define BM_CSCMR1_USDHC1_SEL		(0x1 << 16)
+#define BP_CSCMR1_USDHC2_SEL		17
+#define BM_CSCMR1_USDHC2_SEL		(0x1 << 17)
+#define BP_CSCMR1_USDHC3_SEL		18
+#define BM_CSCMR1_USDHC3_SEL		(0x1 << 18)
+#define BP_CSCMR1_USDHC4_SEL		19
+#define BM_CSCMR1_USDHC4_SEL		(0x1 << 19)
+#define BP_CSCMR1_EMI_PODF		20
+#define BM_CSCMR1_EMI_PODF		(0x7 << 20)
+#define BP_CSCMR1_EMI_SLOW_PODF		23
+#define BM_CSCMR1_EMI_SLOW_PODF		(0x7 << 23)
+#define BP_CSCMR1_EMI_SEL		27
+#define BM_CSCMR1_EMI_SEL		(0x3 << 27)
+#define BP_CSCMR1_EMI_SLOW_SEL		29
+#define BM_CSCMR1_EMI_SLOW_SEL		(0x3 << 29)
+
+#define BP_CSCMR2_CAN_PODF		2
+#define BM_CSCMR2_CAN_PODF		(0x3f << 2)
+#define BM_CSCMR2_LDB_DI0_IPU_DIV	(0x1 << 10)
+#define BM_CSCMR2_LDB_DI1_IPU_DIV	(0x1 << 11)
+#define BP_CSCMR2_ESAI_SEL		19
+#define BM_CSCMR2_ESAI_SEL		(0x3 << 19)
+
+#define BP_CSCDR1_UART_PODF		0
+#define BM_CSCDR1_UART_PODF		(0x3f << 0)
+#define BP_CSCDR1_USDHC1_PODF		11
+#define BM_CSCDR1_USDHC1_PODF		(0x7 << 11)
+#define BP_CSCDR1_USDHC2_PODF		16
+#define BM_CSCDR1_USDHC2_PODF		(0x7 << 16)
+#define BP_CSCDR1_USDHC3_PODF		19
+#define BM_CSCDR1_USDHC3_PODF		(0x7 << 19)
+#define BP_CSCDR1_USDHC4_PODF		22
+#define BM_CSCDR1_USDHC4_PODF		(0x7 << 22)
+#define BP_CSCDR1_VPU_AXI_PODF		25
+#define BM_CSCDR1_VPU_AXI_PODF		(0x7 << 25)
+
+#define BP_CS1CDR_SSI1_PODF		0
+#define BM_CS1CDR_SSI1_PODF		(0x3f << 0)
+#define BP_CS1CDR_SSI1_PRED		6
+#define BM_CS1CDR_SSI1_PRED		(0x7 << 6)
+#define BP_CS1CDR_ESAI_PRED		9
+#define BM_CS1CDR_ESAI_PRED		(0x7 << 9)
+#define BP_CS1CDR_SSI3_PODF		16
+#define BM_CS1CDR_SSI3_PODF		(0x3f << 16)
+#define BP_CS1CDR_SSI3_PRED		22
+#define BM_CS1CDR_SSI3_PRED		(0x7 << 22)
+#define BP_CS1CDR_ESAI_PODF		25
+#define BM_CS1CDR_ESAI_PODF		(0x7 << 25)
+
+#define BP_CS2CDR_SSI2_PODF		0
+#define BM_CS2CDR_SSI2_PODF		(0x3f << 0)
+#define BP_CS2CDR_SSI2_PRED		6
+#define BM_CS2CDR_SSI2_PRED		(0x7 << 6)
+#define BP_CS2CDR_LDB_DI0_SEL		9
+#define BM_CS2CDR_LDB_DI0_SEL		(0x7 << 9)
+#define BP_CS2CDR_LDB_DI1_SEL		12
+#define BM_CS2CDR_LDB_DI1_SEL		(0x7 << 12)
+#define BP_CS2CDR_ENFC_SEL		16
+#define BM_CS2CDR_ENFC_SEL		(0x3 << 16)
+#define BP_CS2CDR_ENFC_PRED		18
+#define BM_CS2CDR_ENFC_PRED		(0x7 << 18)
+#define BP_CS2CDR_ENFC_PODF		21
+#define BM_CS2CDR_ENFC_PODF		(0x3f << 21)
+
+#define BP_CDCDR_ASRC_SERIAL_SEL	7
+#define BM_CDCDR_ASRC_SERIAL_SEL	(0x3 << 7)
+#define BP_CDCDR_ASRC_SERIAL_PODF	9
+#define BM_CDCDR_ASRC_SERIAL_PODF	(0x7 << 9)
+#define BP_CDCDR_ASRC_SERIAL_PRED	12
+#define BM_CDCDR_ASRC_SERIAL_PRED	(0x7 << 12)
+#define BP_CDCDR_SPDIF_SEL		20
+#define BM_CDCDR_SPDIF_SEL		(0x3 << 20)
+#define BP_CDCDR_SPDIF_PODF		22
+#define BM_CDCDR_SPDIF_PODF		(0x7 << 22)
+#define BP_CDCDR_SPDIF_PRED		25
+#define BM_CDCDR_SPDIF_PRED		(0x7 << 25)
+#define BP_CDCDR_HSI_TX_PODF		29
+#define BM_CDCDR_HSI_TX_PODF		(0x7 << 29)
+#define BP_CDCDR_HSI_TX_SEL		28
+#define BM_CDCDR_HSI_TX_SEL		(0x1 << 28)
+
+#define BP_CHSCCDR_IPU1_DI0_SEL		0
+#define BM_CHSCCDR_IPU1_DI0_SEL		(0x7 << 0)
+#define BP_CHSCCDR_IPU1_DI0_PRE_PODF	3
+#define BM_CHSCCDR_IPU1_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CHSCCDR_IPU1_DI0_PRE_SEL	6
+#define BM_CHSCCDR_IPU1_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CHSCCDR_IPU1_DI1_SEL		9
+#define BM_CHSCCDR_IPU1_DI1_SEL		(0x7 << 9)
+#define BP_CHSCCDR_IPU1_DI1_PRE_PODF	12
+#define BM_CHSCCDR_IPU1_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CHSCCDR_IPU1_DI1_PRE_SEL	15
+#define BM_CHSCCDR_IPU1_DI1_PRE_SEL	(0x7 << 15)
+
+#define BP_CSCDR2_IPU2_DI0_SEL		0
+#define BM_CSCDR2_IPU2_DI0_SEL		(0x7)
+#define BP_CSCDR2_IPU2_DI0_PRE_PODF	3
+#define BM_CSCDR2_IPU2_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CSCDR2_IPU2_DI0_PRE_SEL	6
+#define BM_CSCDR2_IPU2_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CSCDR2_IPU2_DI1_SEL		9
+#define BM_CSCDR2_IPU2_DI1_SEL		(0x7 << 9)
+#define BP_CSCDR2_IPU2_DI1_PRE_PODF	12
+#define BM_CSCDR2_IPU2_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CSCDR2_IPU2_DI1_PRE_SEL	15
+#define BM_CSCDR2_IPU2_DI1_PRE_SEL	(0x7 << 15)
+#define BP_CSCDR2_ECSPI_CLK_PODF	19
+#define BM_CSCDR2_ECSPI_CLK_PODF	(0x3f << 19)
+
+#define BP_CSCDR3_IPU1_HSP_SEL		9
+#define BM_CSCDR3_IPU1_HSP_SEL		(0x3 << 9)
+#define BP_CSCDR3_IPU1_HSP_PODF		11
+#define BM_CSCDR3_IPU1_HSP_PODF		(0x7 << 11)
+#define BP_CSCDR3_IPU2_HSP_SEL		14
+#define BM_CSCDR3_IPU2_HSP_SEL		(0x3 << 14)
+#define BP_CSCDR3_IPU2_HSP_PODF		16
+#define BM_CSCDR3_IPU2_HSP_PODF		(0x7 << 16)
+
+#define BM_CDHIPR_AXI_PODF_BUSY		(0x1 << 0)
+#define BM_CDHIPR_AHB_PODF_BUSY		(0x1 << 1)
+#define BM_CDHIPR_MMDC_CH1_PODF_BUSY	(0x1 << 2)
+#define BM_CDHIPR_PERIPH2_SEL_BUSY	(0x1 << 3)
+#define BM_CDHIPR_MMDC_CH0_PODF_BUSY	(0x1 << 4)
+#define BM_CDHIPR_PERIPH_SEL_BUSY	(0x1 << 5)
+#define BM_CDHIPR_ARM_PODF_BUSY		(0x1 << 16)
+
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define FREQ_480M	480000000
+#define FREQ_528M	528000000
+#define FREQ_594M	594000000
+#define FREQ_650M	650000000
+#define FREQ_1300M	1300000000
+
+static struct clk pll1_sys;
+static struct clk pll2_bus;
+static struct clk pll3_usb_otg;
+static struct clk pll4_audio;
+static struct clk pll5_video;
+static struct clk pll6_mlb;
+static struct clk pll7_usb_host;
+static struct clk pll8_enet;
+static struct clk apbh_dma_clk;
+static struct clk arm_clk;
+static struct clk ipg_clk;
+static struct clk ahb_clk;
+static struct clk axi_clk;
+static struct clk mmdc_ch0_axi_clk;
+static struct clk mmdc_ch1_axi_clk;
+static struct clk periph_clk;
+static struct clk periph_pre_clk;
+static struct clk periph_clk2_clk;
+static struct clk periph2_clk;
+static struct clk periph2_pre_clk;
+static struct clk periph2_clk2_clk;
+static struct clk gpu2d_core_clk;
+static struct clk gpu3d_core_clk;
+static struct clk gpu3d_shader_clk;
+static struct clk ipg_perclk;
+static struct clk emi_clk;
+static struct clk emi_slow_clk;
+static struct clk can1_clk;
+static struct clk uart_clk;
+static struct clk usdhc1_clk;
+static struct clk usdhc2_clk;
+static struct clk usdhc3_clk;
+static struct clk usdhc4_clk;
+static struct clk vpu_clk;
+static struct clk hsi_tx_clk;
+static struct clk ipu1_di0_pre_clk;
+static struct clk ipu1_di1_pre_clk;
+static struct clk ipu2_di0_pre_clk;
+static struct clk ipu2_di1_pre_clk;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk ssi1_clk;
+static struct clk ssi3_clk;
+static struct clk esai_clk;
+static struct clk ssi2_clk;
+static struct clk spdif_clk;
+static struct clk asrc_serial_clk;
+static struct clk gpu2d_axi_clk;
+static struct clk gpu3d_axi_clk;
+static struct clk pcie_clk;
+static struct clk vdo_axi_clk;
+static struct clk ldb_di0_clk;
+static struct clk ldb_di1_clk;
+static struct clk ipu1_di0_clk;
+static struct clk ipu1_di1_clk;
+static struct clk ipu2_di0_clk;
+static struct clk ipu2_di1_clk;
+static struct clk enfc_clk;
+static struct clk dummy_clk = {};
+
+static unsigned long external_high_reference;
+static unsigned long external_low_reference;
+static unsigned long oscillator_reference;
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+	return oscillator_reference;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+	return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+	.get_rate = get_oscillator_reference_clock_rate,
+};
+
+static inline void __iomem *pll_get_reg_addr(struct clk *pll)
+{
+	if (pll == &pll1_sys)
+		return PLL1_SYS;
+	else if (pll == &pll2_bus)
+		return PLL2_BUS;
+	else if (pll == &pll3_usb_otg)
+		return PLL3_USB_OTG;
+	else if (pll == &pll4_audio)
+		return PLL4_AUDIO;
+	else if (pll == &pll5_video)
+		return PLL5_VIDEO;
+	else if (pll == &pll6_mlb)
+		return PLL6_MLB;
+	else if (pll == &pll7_usb_host)
+		return PLL7_USB_HOST;
+	else if (pll == &pll8_enet)
+		return PLL8_ENET;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static int pll_enable(struct clk *clk)
+{
+	int timeout = 0x100000;
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_BYPASS;
+	val &= ~BM_PLL_POWER_DOWN;
+	/* 480MHz PLLs have the opposite definition for power bit */
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val |= BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+
+	/* Wait for PLL to lock */
+	while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	/* Enable the PLL output now */
+	val = readl_relaxed(reg);
+	val |= BM_PLL_ENABLE;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+static void pll_disable(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_ENABLE;
+	val |= BM_PLL_BYPASS;
+	val |= BM_PLL_POWER_DOWN;
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val &= ~BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+}
+
+static unsigned long pll1_sys_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
+		  BP_PLL_SYS_DIV_SELECT;
+
+	return clk_get_rate(clk->parent) * div / 2;
+}
+
+static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate * 2 / clk_get_rate(clk->parent);
+	val = readl_relaxed(PLL1_SYS);
+	val &= ~BM_PLL_SYS_DIV_SELECT;
+	val |= div << BP_PLL_SYS_DIV_SELECT;
+	writel_relaxed(val, PLL1_SYS);
+
+	return 0;
+}
+
+static unsigned long pll8_enet_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
+		  BP_PLL_ENET_DIV_SELECT;
+
+	switch (div) {
+	case 0:
+		return 25000000;
+	case 1:
+		return 50000000;
+	case 2:
+		return 100000000;
+	case 3:
+		return 125000000;
+	}
+
+	return 0;
+}
+
+static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	switch (rate) {
+	case 25000000:
+		div = 0;
+		break;
+	case 50000000:
+		div = 1;
+		break;
+	case 100000000:
+		div = 2;
+		break;
+	case 125000000:
+		div = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= ~BM_PLL_ENET_DIV_SELECT;
+	val |= div << BP_PLL_ENET_DIV_SELECT;
+	writel_relaxed(val, PLL8_ENET);
+
+	return 0;
+}
+
+static unsigned long pll_av_get_rate(struct clk *clk)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
+	u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
+	u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
+		  BP_PLL_AV_DIV_SELECT;
+
+	return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static int pll_av_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned int parent_rate = clk_get_rate(clk->parent);
+	u32 val, div;
+	u32 mfn, mfd = 1000000;
+	s64 temp64;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate / parent_rate;
+	temp64 = (u64) (rate - div * parent_rate);
+	temp64 *= mfd;
+	do_div(temp64, parent_rate);
+	mfn = temp64;
+
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_AV_DIV_SELECT;
+	val |= div << BP_PLL_AV_DIV_SELECT;
+	writel_relaxed(val, reg);
+	writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
+	writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
+
+	return 0;
+}
+
+static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
+{
+	void __iomem *reg;
+
+	if (clk == &pll2_bus) {
+		reg = PLL2_BUS;
+		*bp = BP_PLL_BUS_DIV_SELECT;
+		*bm = BM_PLL_BUS_DIV_SELECT;
+	} else if (clk == &pll3_usb_otg) {
+		reg = PLL3_USB_OTG;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else if (clk == &pll7_usb_host) {
+		reg = PLL7_USB_HOST;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else {
+		BUG();
+	}
+
+	return reg;
+}
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 div, bp, bm;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	div = (readl_relaxed(reg) & bm) >> bp;
+
+	return (div == 1) ? clk_get_rate(clk->parent) * 22 :
+			    clk_get_rate(clk->parent) * 20;
+}
+
+static int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg;
+	u32 val, div, bp, bm;
+
+	if (rate == FREQ_528M)
+		div = 1;
+	else if (rate == FREQ_480M)
+		div = 0;
+	else
+		return -EINVAL;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	val = readl_relaxed(reg);
+	val &= ~bm;
+	val |= div << bp;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+#define pll2_bus_get_rate	pll_get_rate
+#define pll2_bus_set_rate	pll_set_rate
+#define pll3_usb_otg_get_rate	pll_get_rate
+#define pll3_usb_otg_set_rate	pll_set_rate
+#define pll7_usb_host_get_rate	pll_get_rate
+#define pll7_usb_host_set_rate	pll_set_rate
+#define pll4_audio_get_rate	pll_av_get_rate
+#define pll4_audio_set_rate	pll_av_set_rate
+#define pll5_video_get_rate	pll_av_get_rate
+#define pll5_video_set_rate	pll_av_set_rate
+#define pll6_mlb_get_rate	NULL
+#define pll6_mlb_set_rate	NULL
+
+#define DEF_PLL(name)					\
+	static struct clk name = {			\
+		.enable		= pll_enable,		\
+		.disable	= pll_disable,		\
+		.get_rate	= name##_get_rate,	\
+		.set_rate	= name##_set_rate,	\
+		.parent		= &osc_clk,		\
+	}
+
+DEF_PLL(pll1_sys);
+DEF_PLL(pll2_bus);
+DEF_PLL(pll3_usb_otg);
+DEF_PLL(pll4_audio);
+DEF_PLL(pll5_video);
+DEF_PLL(pll6_mlb);
+DEF_PLL(pll7_usb_host);
+DEF_PLL(pll8_enet);
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+	u32 frac, bp_frac;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	bp_frac = clk->enable_shift - 7;
+	frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, frac, bp_frac;
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	/*
+	 * Round up the divider so that we don't set a rate
+	 * higher than what is requested
+	 */
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+
+	/*
+	 * The frac field always starts from 7 bits lower
+	 * position of enable bit
+	 */
+	bp_frac = clk->enable_shift - 7;
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(PFD_FRAC_MASK << bp_frac);
+	val |= frac << bp_frac;
+	writel_relaxed(val, clk->enable_reg);
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 frac;
+	u64 tmp;
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(1 << clk->enable_shift);
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val |= 1 << clk->enable_shift;
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+#define DEF_PFD(name, er, es, p)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= pfd_enable,		\
+		.disable	= pfd_disable,		\
+		.get_rate	= pfd_get_rate,		\
+		.set_rate	= pfd_set_rate,		\
+		.round_rate	= pfd_round_rate,	\
+		.parent		= p,			\
+	}
+
+DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
+DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
+DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
+DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+
+static unsigned long pll2_200m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200m = {
+	.parent = &pll2_pfd_400m,
+	.get_rate = pll2_200m_get_rate,
+};
+
+static unsigned long pll3_120m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_120m_get_rate,
+};
+
+static unsigned long pll3_80m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_80m_get_rate,
+};
+
+static unsigned long pll3_60m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_60m_get_rate,
+};
+
+static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val = readl_relaxed(CCSR);
+
+	if (parent == &pll1_sys) {
+		val &= ~BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &osc_clk) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &pll2_pfd_400m) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val |= BM_CCSR_STEP_SEL;
+	} else {
+		return -EINVAL;
+	}
+
+	writel_relaxed(val, CCSR);
+
+	return 0;
+}
+
+static struct clk pll1_sw_clk = {
+	.parent = &pll1_sys,
+	.set_parent = pll1_sw_clk_set_parent,
+};
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+	u32 min_pred, temp_pred, old_err, err;
+
+	if (div >= 512) {
+		*pred = 8;
+		*podf = 64;
+	} else if (div >= 8) {
+		min_pred = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+			err = div % temp_pred;
+			if (err == 0) {
+				*pred = temp_pred;
+				break;
+			}
+			err = temp_pred - err;
+			if (err < old_err) {
+				old_err = err;
+				*pred = temp_pred;
+			}
+		}
+		*podf = (div + *pred - 1) / *pred;
+	} else if (div < 8) {
+		*pred = div;
+		*podf = 1;
+	}
+}
+
+static int _clk_enable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg |= 0x3 << clk->enable_shift;
+	writel_relaxed(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg &= ~(0x3 << clk->enable_shift);
+	writel_relaxed(reg, clk->enable_reg);
+}
+
+struct divider {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp_pred;
+	u32 bm_pred;
+	u32 bp_podf;
+	u32 bm_podf;
+};
+
+#define DEF_CLK_DIV1(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV1(arm_div,		&arm_clk,		CACRR,	ARM);
+DEF_CLK_DIV1(ipg_div,		&ipg_clk,		CBCDR,	IPG);
+DEF_CLK_DIV1(ahb_div,		&ahb_clk,		CBCDR,	AHB);
+DEF_CLK_DIV1(axi_div,		&axi_clk,		CBCDR,	AXI);
+DEF_CLK_DIV1(mmdc_ch0_axi_div,	&mmdc_ch0_axi_clk,	CBCDR,	MMDC_CH0_AXI);
+DEF_CLK_DIV1(mmdc_ch1_axi_div,	&mmdc_ch1_axi_clk,	CBCDR,	MMDC_CH1_AXI);
+DEF_CLK_DIV1(periph_clk2_div,	&periph_clk2_clk,	CBCDR,	PERIPH_CLK2);
+DEF_CLK_DIV1(periph2_clk2_div,	&periph2_clk2_clk,	CBCDR,	PERIPH2_CLK2);
+DEF_CLK_DIV1(gpu2d_core_div,	&gpu2d_core_clk,	CBCMR,	GPU2D_CORE);
+DEF_CLK_DIV1(gpu3d_core_div,	&gpu3d_core_clk,	CBCMR,	GPU3D_CORE);
+DEF_CLK_DIV1(gpu3d_shader_div,	&gpu3d_shader_clk,	CBCMR,	GPU3D_SHADER);
+DEF_CLK_DIV1(ipg_perclk_div,	&ipg_perclk,		CSCMR1,	PERCLK);
+DEF_CLK_DIV1(emi_div,		&emi_clk,		CSCMR1,	EMI);
+DEF_CLK_DIV1(emi_slow_div,	&emi_slow_clk,		CSCMR1,	EMI_SLOW);
+DEF_CLK_DIV1(can_div,		&can1_clk,		CSCMR2,	CAN);
+DEF_CLK_DIV1(uart_div,		&uart_clk,		CSCDR1,	UART);
+DEF_CLK_DIV1(usdhc1_div,	&usdhc1_clk,		CSCDR1,	USDHC1);
+DEF_CLK_DIV1(usdhc2_div,	&usdhc2_clk,		CSCDR1,	USDHC2);
+DEF_CLK_DIV1(usdhc3_div,	&usdhc3_clk,		CSCDR1,	USDHC3);
+DEF_CLK_DIV1(usdhc4_div,	&usdhc4_clk,		CSCDR1,	USDHC4);
+DEF_CLK_DIV1(vpu_div,		&vpu_clk,		CSCDR1,	VPU_AXI);
+DEF_CLK_DIV1(hsi_tx_div,	&hsi_tx_clk,		CDCDR,	HSI_TX);
+DEF_CLK_DIV1(ipu1_di0_pre_div,	&ipu1_di0_pre_clk,	CHSCCDR, IPU1_DI0_PRE);
+DEF_CLK_DIV1(ipu1_di1_pre_div,	&ipu1_di1_pre_clk,	CHSCCDR, IPU1_DI1_PRE);
+DEF_CLK_DIV1(ipu2_di0_pre_div,	&ipu2_di0_pre_clk,	CSCDR2,	IPU2_DI0_PRE);
+DEF_CLK_DIV1(ipu2_di1_pre_div,	&ipu2_di1_pre_clk,	CSCDR2,	IPU2_DI1_PRE);
+DEF_CLK_DIV1(ipu1_div,		&ipu1_clk,		CSCDR3,	IPU1_HSP);
+DEF_CLK_DIV1(ipu2_div,		&ipu2_clk,		CSCDR3,	IPU2_HSP);
+
+#define DEF_CLK_DIV2(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_pred = BP_##r##_##b##_PRED,			\
+		.bm_pred = BM_##r##_##b##_PRED,			\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV2(ssi1_div,		&ssi1_clk,		CS1CDR,	SSI1);
+DEF_CLK_DIV2(ssi3_div,		&ssi3_clk,		CS1CDR,	SSI3);
+DEF_CLK_DIV2(esai_div,		&esai_clk,		CS1CDR,	ESAI);
+DEF_CLK_DIV2(ssi2_div,		&ssi2_clk,		CS2CDR,	SSI2);
+DEF_CLK_DIV2(enfc_div,		&enfc_clk,		CS2CDR,	ENFC);
+DEF_CLK_DIV2(spdif_div,		&spdif_clk,		CDCDR,	SPDIF);
+DEF_CLK_DIV2(asrc_serial_div,	&asrc_serial_clk,	CDCDR,	ASRC_SERIAL);
+
+static struct divider *dividers[] = {
+	&arm_div,
+	&ipg_div,
+	&ahb_div,
+	&axi_div,
+	&mmdc_ch0_axi_div,
+	&mmdc_ch1_axi_div,
+	&periph_clk2_div,
+	&periph2_clk2_div,
+	&gpu2d_core_div,
+	&gpu3d_core_div,
+	&gpu3d_shader_div,
+	&ipg_perclk_div,
+	&emi_div,
+	&emi_slow_div,
+	&can_div,
+	&uart_div,
+	&usdhc1_div,
+	&usdhc2_div,
+	&usdhc3_div,
+	&usdhc4_div,
+	&vpu_div,
+	&hsi_tx_div,
+	&ipu1_di0_pre_div,
+	&ipu1_di1_pre_div,
+	&ipu2_di0_pre_div,
+	&ipu2_di1_pre_div,
+	&ipu1_div,
+	&ipu2_div,
+	&ssi1_div,
+	&ssi3_div,
+	&esai_div,
+	&ssi2_div,
+	&enfc_div,
+	&spdif_div,
+	&asrc_serial_div,
+};
+
+static unsigned long ldb_di_clk_get_rate(struct clk *clk)
+{
+	u32 val = readl_relaxed(CSCMR2);
+
+	val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
+				       BM_CSCMR2_LDB_DI1_IPU_DIV;
+	if (val)
+		return clk_get_rate(clk->parent) / 7;
+	else
+		return clk_get_rate(clk->parent) * 2 / 7;
+}
+
+static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 val = readl_relaxed(CSCMR2);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+	else
+		val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+
+	writel_relaxed(val, CSCMR2);
+
+	return 0;
+}
+
+static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		return parent_rate / 7;
+	else
+		return 2 * parent_rate / 7;
+}
+
+static unsigned long _clk_get_rate(struct clk *clk)
+{
+	struct divider *d;
+	u32 val, pred, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_get_rate(clk);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return clk_get_rate(clk->parent);
+
+	val = readl_relaxed(d->reg);
+	pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
+	podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
+
+	return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int clk_busy_wait(struct clk *clk)
+{
+	int timeout = 0x100000;
+	u32 bm;
+
+	if (clk == &axi_clk)
+		bm = BM_CDHIPR_AXI_PODF_BUSY;
+	else if (clk == &ahb_clk)
+		bm = BM_CDHIPR_AHB_PODF_BUSY;
+	else if (clk == &mmdc_ch0_axi_clk)
+		bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
+	else if (clk == &periph_clk)
+		bm = BM_CDHIPR_PERIPH_SEL_BUSY;
+	else if (clk == &arm_clk)
+		bm = BM_CDHIPR_ARM_PODF_BUSY;
+	else
+		return -EINVAL;
+
+	while ((readl_relaxed(CDHIPR) & bm) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int _clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	struct divider *d;
+	u32 val, div, max_div, pred = 0, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_set_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	max_div = ((d->bm_pred >> d->bp_pred) + 1) *
+		  ((d->bm_podf >> d->bp_podf) + 1);
+
+	div = parent_rate / rate;
+	if (div == 0)
+		div++;
+
+	if ((parent_rate / div != rate) || div > max_div)
+		return -EINVAL;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+	} else {
+		pred = 1;
+		podf = div;
+	}
+
+	val = readl_relaxed(d->reg);
+	val &= ~(d->bm_pred | d->bm_podf);
+	val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
+	writel_relaxed(val, d->reg);
+
+	if (clk == &axi_clk || clk == &ahb_clk ||
+	    clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 div = parent_rate / rate;
+	u32 div_max, pred = 0, podf;
+	struct divider *d;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_round_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	if (div == 0 || parent_rate % rate)
+		div++;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+		div = pred * podf;
+	} else {
+		div_max = (d->bm_podf >> d->bp_podf) + 1;
+		if (div > div_max)
+			div = div_max;
+	}
+
+	return parent_rate / div;
+}
+
+struct multiplexer {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp;
+	u32 bm;
+	int pnum;
+	struct clk *parents[];
+};
+
+static struct multiplexer axi_mux = {
+	.clk = &axi_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_AXI_SEL,
+	.bm = BM_CBCDR_AXI_SEL,
+	.parents = {
+		&periph_clk,
+		&pll2_pfd_400m,
+		&pll3_pfd_540m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_mux = {
+	.clk = &periph_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH_CLK_SEL,
+	.parents = {
+		&periph_pre_clk,
+		&periph_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph_pre_mux = {
+	.clk = &periph_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_clk2_mux = {
+	.clk = &periph_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_mux = {
+	.clk = &periph2_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH2_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH2_CLK_SEL,
+	.parents = {
+		&periph2_pre_clk,
+		&periph2_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_pre_mux = {
+	.clk = &periph2_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_clk2_mux = {
+	.clk = &periph2_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH2_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH2_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_axi_mux = {
+	.clk = &gpu2d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_AXI_SEL,
+	.bm = BM_CBCMR_GPU2D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_axi_mux = {
+	.clk = &gpu3d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_AXI_SEL,
+	.bm = BM_CBCMR_GPU3D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_core_mux = {
+	.clk = &gpu3d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_CORE_SEL,
+	.bm = BM_CBCMR_GPU3D_CORE_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_shader_mux = {
+	.clk = &gpu3d_shader_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_SHADER_SEL,
+	.bm = BM_CBCMR_GPU3D_SHADER_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll3_pfd_720m,
+		NULL
+	},
+};
+
+static struct multiplexer pcie_axi_mux = {
+	.clk = &pcie_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PCIE_AXI_SEL,
+	.bm = BM_CBCMR_PCIE_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vdo_axi_mux = {
+	.clk = &vdo_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VDO_AXI_SEL,
+	.bm = BM_CBCMR_VDO_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vpu_axi_mux = {
+	.clk = &vpu_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VPU_AXI_SEL,
+	.bm = BM_CBCMR_VPU_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_core_mux = {
+	.clk = &gpu2d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_CORE_SEL,
+	.bm = BM_CBCMR_GPU2D_CORE_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_352m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_SSI_MUX(id)							\
+	static struct multiplexer ssi##id##_mux = {			\
+		.clk = &ssi##id##_clk,					\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_SSI##id##_SEL,				\
+		.bm = BM_CSCMR1_SSI##id##_SEL,				\
+		.parents = {						\
+			&pll3_pfd_508m,					\
+			&pll3_pfd_454m,					\
+			&pll4_audio,					\
+			NULL						\
+		},							\
+	}
+
+DEF_SSI_MUX(1);
+DEF_SSI_MUX(2);
+DEF_SSI_MUX(3);
+
+#define DEF_USDHC_MUX(id)						\
+	static struct multiplexer usdhc##id##_mux = {			\
+		.clk = &usdhc##id##_clk,				\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_USDHC##id##_SEL,			\
+		.bm = BM_CSCMR1_USDHC##id##_SEL,			\
+		.parents = {						\
+			&pll2_pfd_400m,					\
+			&pll2_pfd_352m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_USDHC_MUX(1);
+DEF_USDHC_MUX(2);
+DEF_USDHC_MUX(3);
+DEF_USDHC_MUX(4);
+
+static struct multiplexer emi_mux = {
+	.clk = &emi_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SEL,
+	.bm = BM_CSCMR1_EMI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer emi_slow_mux = {
+	.clk = &emi_slow_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SLOW_SEL,
+	.bm = BM_CSCMR1_EMI_SLOW_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer esai_mux = {
+	.clk = &esai_clk,
+	.reg = CSCMR2,
+	.bp = BP_CSCMR2_ESAI_SEL,
+	.bm = BM_CSCMR2_ESAI_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+#define DEF_LDB_DI_MUX(id)						\
+	static struct multiplexer ldb_di##id##_mux = {			\
+		.clk = &ldb_di##id##_clk,				\
+		.reg = CS2CDR,						\
+		.bp = BP_CS2CDR_LDB_DI##id##_SEL,			\
+		.bm = BM_CS2CDR_LDB_DI##id##_SEL,			\
+		.parents = {						\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			&pll3_usb_otg,					\
+			NULL						\
+		},							\
+	}
+
+DEF_LDB_DI_MUX(0);
+DEF_LDB_DI_MUX(1);
+
+static struct multiplexer enfc_mux = {
+	.clk = &enfc_clk,
+	.reg = CS2CDR,
+	.bp = BP_CS2CDR_ENFC_SEL,
+	.bm = BM_CS2CDR_ENFC_SEL,
+	.parents = {
+		&pll2_pfd_352m,
+		&pll2_bus,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer spdif_mux = {
+	.clk = &spdif_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_SPDIF_SEL,
+	.bm = BM_CDCDR_SPDIF_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer asrc_serial_mux = {
+	.clk = &asrc_serial_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_ASRC_SERIAL_SEL,
+	.bm = BM_CDCDR_ASRC_SERIAL_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer hsi_tx_mux = {
+	.clk = &hsi_tx_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_HSI_TX_SEL,
+	.bm = BM_CDCDR_HSI_TX_SEL,
+	.parents = {
+		&pll3_120m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_IPU_DI_PRE_MUX(r, i, d)					\
+	static struct multiplexer ipu##i##_di##d##_pre_mux = {		\
+		.clk = &ipu##i##_di##d##_pre_clk,			\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll3_usb_otg,					\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_DI_MUX(r, i, d)						\
+	static struct multiplexer ipu##i##_di##d##_mux = {		\
+		.clk = &ipu##i##_di##d##_clk,				\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_SEL,			\
+		.bm = BM_##r##_IPU##i##_DI##d##_SEL,			\
+		.parents = {						\
+			&ipu##i##_di##d##_pre_clk,			\
+			&dummy_clk,					\
+			&dummy_clk,					\
+			&ldb_di0_clk,					\
+			&ldb_di1_clk,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_MUX(id)							\
+	static struct multiplexer ipu##id##_mux = {			\
+		.clk = &ipu##id##_clk,					\
+		.reg = CSCDR3,						\
+		.bp = BP_CSCDR3_IPU##id##_HSP_SEL,			\
+		.bm = BM_CSCDR3_IPU##id##_HSP_SEL,			\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll2_pfd_400m,					\
+			&pll3_120m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_MUX(1);
+DEF_IPU_MUX(2);
+
+static struct multiplexer *multiplexers[] = {
+	&axi_mux,
+	&periph_mux,
+	&periph_pre_mux,
+	&periph_clk2_mux,
+	&periph2_mux,
+	&periph2_pre_mux,
+	&periph2_clk2_mux,
+	&gpu2d_axi_mux,
+	&gpu3d_axi_mux,
+	&gpu3d_core_mux,
+	&gpu3d_shader_mux,
+	&pcie_axi_mux,
+	&vdo_axi_mux,
+	&vpu_axi_mux,
+	&gpu2d_core_mux,
+	&ssi1_mux,
+	&ssi2_mux,
+	&ssi3_mux,
+	&usdhc1_mux,
+	&usdhc2_mux,
+	&usdhc3_mux,
+	&usdhc4_mux,
+	&emi_mux,
+	&emi_slow_mux,
+	&esai_mux,
+	&ldb_di0_mux,
+	&ldb_di1_mux,
+	&enfc_mux,
+	&spdif_mux,
+	&asrc_serial_mux,
+	&hsi_tx_mux,
+	&ipu1_di0_pre_mux,
+	&ipu1_di0_mux,
+	&ipu1_di1_pre_mux,
+	&ipu1_di1_mux,
+	&ipu2_di0_pre_mux,
+	&ipu2_di0_mux,
+	&ipu2_di1_pre_mux,
+	&ipu2_di1_mux,
+	&ipu1_mux,
+	&ipu2_mux,
+};
+
+static int _clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct multiplexer *m;
+	int i, num;
+	u32 val;
+
+	num = ARRAY_SIZE(multiplexers);
+	for (i = 0; i < num; i++)
+		if (multiplexers[i]->clk == clk) {
+			m = multiplexers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	i = 0;
+	while (m->parents[i]) {
+		if (parent == m->parents[i])
+			break;
+		i++;
+	}
+	if (!m->parents[i])
+		return -EINVAL;
+
+	val = readl_relaxed(m->reg);
+	val &= ~m->bm;
+	val |= i << m->bp;
+	writel_relaxed(val, m->reg);
+
+	if (clk == &periph_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+#define DEF_NG_CLK(name, p)				\
+	static struct clk name = {			\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+	}
+
+DEF_NG_CLK(periph_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph_clk,		&periph_pre_clk);
+DEF_NG_CLK(periph2_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph2_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph2_clk,		&periph2_pre_clk);
+DEF_NG_CLK(axi_clk,		&periph_clk);
+DEF_NG_CLK(emi_clk,		&axi_clk);
+DEF_NG_CLK(arm_clk,		&pll1_sw_clk);
+DEF_NG_CLK(ahb_clk,		&periph_clk);
+DEF_NG_CLK(ipg_clk,		&ahb_clk);
+DEF_NG_CLK(ipg_perclk,		&ipg_clk);
+DEF_NG_CLK(ipu1_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu1_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(asrc_serial_clk,	&pll3_usb_otg);
+
+#define DEF_CLK(name, er, es, p, s)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= _clk_enable,		\
+		.disable	= _clk_disable,		\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+DEF_CLK(aips_tz1_clk,	  CCGR0, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(aips_tz2_clk,	  CCGR0, CG1,  &ahb_clk,	  NULL);
+DEF_CLK(apbh_dma_clk,	  CCGR0, CG2,  &ahb_clk,	  NULL);
+DEF_CLK(asrc_clk,	  CCGR0, CG3,  &pll4_audio,	  NULL);
+DEF_CLK(can1_serial_clk,  CCGR0, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(can1_clk,	  CCGR0, CG7,  &pll3_usb_otg,	  &can1_serial_clk);
+DEF_CLK(can2_serial_clk,  CCGR0, CG10, &pll3_usb_otg,	  NULL);
+DEF_CLK(can2_clk,	  CCGR0, CG9,  &pll3_usb_otg,	  &can2_serial_clk);
+DEF_CLK(ecspi1_clk,	  CCGR1, CG0,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi2_clk,	  CCGR1, CG1,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi3_clk,	  CCGR1, CG2,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi4_clk,	  CCGR1, CG3,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi5_clk,	  CCGR1, CG4,  &pll3_60m,	  NULL);
+DEF_CLK(enet_clk,	  CCGR1, CG5,  &ipg_clk,	  NULL);
+DEF_CLK(esai_clk,	  CCGR1, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(gpt_serial_clk,	  CCGR1, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpt_clk,	  CCGR1, CG10, &ipg_perclk,	  &gpt_serial_clk);
+DEF_CLK(gpu2d_core_clk,	  CCGR1, CG12, &pll2_pfd_352m,	  &gpu2d_axi_clk);
+DEF_CLK(gpu3d_core_clk,	  CCGR1, CG13, &pll2_pfd_594m,	  &gpu3d_axi_clk);
+DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m,	  &gpu3d_axi_clk);
+DEF_CLK(hdmi_iahb_clk,	  CCGR2, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(hdmi_isfr_clk,	  CCGR2, CG2,  &pll3_pfd_540m,	  &hdmi_iahb_clk);
+DEF_CLK(i2c1_clk,	  CCGR2, CG3,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c2_clk,	  CCGR2, CG4,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c3_clk,	  CCGR2, CG5,  &ipg_perclk,	  NULL);
+DEF_CLK(iim_clk,	  CCGR2, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(enfc_clk,	  CCGR2, CG7,  &pll2_pfd_352m,	  NULL);
+DEF_CLK(ipu1_clk,	  CCGR3, CG0,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu1_di0_clk,	  CCGR3, CG1,  &ipu1_di0_pre_clk, NULL);
+DEF_CLK(ipu1_di1_clk,	  CCGR3, CG2,  &ipu1_di1_pre_clk, NULL);
+DEF_CLK(ipu2_clk,	  CCGR3, CG3,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu2_di0_clk,	  CCGR3, CG4,  &ipu2_di0_pre_clk, NULL);
+DEF_CLK(ipu2_di1_clk,	  CCGR3, CG5,  &ipu2_di1_pre_clk, NULL);
+DEF_CLK(ldb_di0_clk,	  CCGR3, CG6,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(ldb_di1_clk,	  CCGR3, CG7,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(hsi_tx_clk,	  CCGR3, CG8,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(mlb_clk,	  CCGR3, CG9,  &pll6_mlb,	  NULL);
+DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk,	  &mmdc_ch0_ipg_clk);
+DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk,	  &mmdc_ch1_ipg_clk);
+DEF_CLK(openvg_axi_clk,   CCGR3, CG13, &axi_clk,	  NULL);
+DEF_CLK(pwm1_clk,	  CCGR4, CG8,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm2_clk,	  CCGR4, CG9,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm3_clk,	  CCGR4, CG10, &ipg_perclk,	  NULL);
+DEF_CLK(pwm4_clk,	  CCGR4, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk,	  NULL);
+DEF_CLK(gpmi_bch_clk,	  CCGR4, CG13, &usdhc4_clk,	  &gpmi_bch_apb_clk);
+DEF_CLK(gpmi_apb_clk,	  CCGR4, CG15, &usdhc3_clk,	  &gpmi_bch_clk);
+DEF_CLK(gpmi_io_clk,	  CCGR4, CG14, &enfc_clk,	  &gpmi_apb_clk);
+DEF_CLK(sdma_clk,	  CCGR5, CG3,  &ahb_clk,	  NULL);
+DEF_CLK(spba_clk,	  CCGR5, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(spdif_clk,	  CCGR5, CG7,  &pll3_usb_otg,	  &spba_clk);
+DEF_CLK(ssi1_clk,	  CCGR5, CG9,  &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi2_clk,	  CCGR5, CG10, &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi3_clk,	  CCGR5, CG11, &pll3_pfd_508m,	  NULL);
+DEF_CLK(uart_serial_clk,  CCGR5, CG13, &pll3_usb_otg,	  NULL);
+DEF_CLK(uart_clk,	  CCGR5, CG12, &pll3_80m,	  &uart_serial_clk);
+DEF_CLK(usboh3_clk,	  CCGR6, CG0,  &ipg_clk,	  NULL);
+DEF_CLK(usdhc1_clk,	  CCGR6, CG1,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc2_clk,	  CCGR6, CG2,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc3_clk,	  CCGR6, CG3,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc4_clk,	  CCGR6, CG4,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(emi_slow_clk,	  CCGR6, CG5,  &axi_clk,	  NULL);
+DEF_CLK(vdo_axi_clk,	  CCGR6, CG6,  &axi_clk,	  NULL);
+DEF_CLK(vpu_clk,	  CCGR6, CG7,  &axi_clk,	  NULL);
+
+static int pcie_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void pcie_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk pcie_clk = {
+	.enable_reg = CCGR4,
+	.enable_shift = CG0,
+	.enable = pcie_clk_enable,
+	.disable = pcie_clk_disable,
+	.set_parent = _clk_set_parent,
+	.parent = &axi_clk,
+	.secondary = &pll8_enet,
+};
+
+static int sata_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void sata_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk sata_clk = {
+	.enable_reg = CCGR5,
+	.enable_shift = CG2,
+	.enable = sata_clk_enable,
+	.disable = sata_clk_disable,
+	.parent = &ipg_clk,
+	.secondary = &pll8_enet,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	}
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
+	_REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
+	_REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
+	_REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
+	_REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
+	_REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
+	_REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
+	_REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
+	_REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
+	_REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
+	_REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
+	_REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
+	_REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
+	_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
+	_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+	_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
+	_REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
+	_REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
+	_REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+	_REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
+	_REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+	_REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
+	_REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
+	_REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
+	_REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
+	_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
+	_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
+	_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+};
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	u32 val = readl_relaxed(CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel_relaxed(val, CLPCR);
+
+	return 0;
+}
+
+static struct map_desc imx6q_clock_desc[] = {
+	imx_map_entry(MX6Q, CCM, MT_DEVICE),
+	imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+};
+
+void __init imx6q_clock_map_io(void)
+{
+	iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+}
+
+int __init mx6q_clocks_init(void)
+{
+	struct device_node *np;
+	void __iomem *base;
+	int i, irq;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			external_low_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			external_high_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			oscillator_reference = rate;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/* only keep necessary clocks on */
+	writel_relaxed(0x3 << CG0  | 0x3 << CG1  | 0x3 << CG2,	CCGR0);
+	writel_relaxed(0x3 << CG8  | 0x3 << CG9  | 0x3 << CG10,	CCGR2);
+	writel_relaxed(0x3 << CG10 | 0x3 << CG12,		CCGR3);
+	writel_relaxed(0x3 << CG4  | 0x3 << CG6  | 0x3 << CG7,	CCGR4);
+	writel_relaxed(0x3 << CG0,				CCGR5);
+	writel_relaxed(0,					CCGR6);
+	writel_relaxed(0,					CCGR7);
+
+	clk_enable(&uart_clk);
+	clk_enable(&mmdc_ch0_axi_clk);
+
+	clk_set_rate(&pll4_audio, FREQ_650M);
+	clk_set_rate(&pll5_video, FREQ_650M);
+	clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
+	clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
+	clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
+	clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
+	clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
+	clk_set_rate(&gpu3d_core_clk, FREQ_528M);
+	clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
+	clk_set_rate(&asrc_serial_clk, 1500000);
+	clk_set_rate(&enfc_clk, 11000000);
+
+	/*
+	 * Before pinctrl API is available, we have to rely on the pad
+	 * configuration set up by bootloader.  For usdhc example here,
+	 * u-boot sets up the pads for 49.5 MHz case, and we have to lower
+	 * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
+	 *
+	 * FIXME: This is should be removed after pinctrl API is available.
+	 * At that time, usdhc driver can call pinctrl API to change pad
+	 * configuration dynamically per different usdhc clock settings.
+	 */
+	clk_set_rate(&usdhc1_clk, 49500000);
+	clk_set_rate(&usdhc2_clk, 49500000);
+	clk_set_rate(&usdhc3_clk, 49500000);
+	clk_set_rate(&usdhc4_clk, 49500000);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+	mxc_timer_init(&gpt_clk, base, irq);
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx25.c linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx25.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * MX25 CPU type detection
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * 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/io.h>
+#include <mach/hardware.h>
+#include <mach/iim.h>
+
+static int mx25_cpu_rev = -1;
+
+static int mx25_read_cpu_rev(void)
+{
+	u32 rev;
+
+	rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
+	switch (rev) {
+	case 0x00:
+		return IMX_CHIP_REVISION_1_0;
+	case 0x01:
+		return IMX_CHIP_REVISION_1_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
+
+int mx25_revision(void)
+{
+	if (mx25_cpu_rev == -1)
+		mx25_cpu_rev = mx25_read_cpu_rev();
+
+	return mx25_cpu_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx27.c linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx27.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,12 +26,12 @@
 
 #include <mach/hardware.h>
 
-static int cpu_silicon_rev = -1;
-static int cpu_partnumber;
+static int mx27_cpu_rev = -1;
+static int mx27_cpu_partnumber;
 
 #define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
 
-static void query_silicon_parameter(void)
+static int mx27_read_cpu_rev(void)
 {
 	u32 val;
 	/*
@@ -42,20 +42,18 @@ static void query_silicon_parameter(void
 	val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
 				+ SYS_CHIP_ID));
 
+	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
+
 	switch (val >> 28) {
 	case 0:
-		cpu_silicon_rev = IMX_CHIP_REVISION_1_0;
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 1:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_0;
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 2:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_1;
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		cpu_silicon_rev = IMX_CHIP_REVISION_UNKNOWN;
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
-	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
 }
 
 /*
@@ -65,12 +63,12 @@ static void query_silicon_parameter(void
  */
 int mx27_revision(void)
 {
-	if (cpu_silicon_rev == -1)
-		query_silicon_parameter();
+	if (mx27_cpu_rev == -1)
+		mx27_cpu_rev = mx27_read_cpu_rev();
 
-	if (cpu_partnumber != 0x8821)
+	if (mx27_cpu_partnumber != 0x8821)
 		return -EINVAL;
 
-	return cpu_silicon_rev;
+	return mx27_cpu_rev;
 }
 EXPORT_SYMBOL(mx27_revision);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx31.c linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx31.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,45 +13,50 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/iim.h>
+#include <mach/common.h>
 
-unsigned int mx31_cpu_rev;
-EXPORT_SYMBOL(mx31_cpu_rev);
+static int mx31_cpu_rev = -1;
 
 static struct {
 	u8 srev;
 	const char *name;
-	const char *v;
 	unsigned int rev;
-} mx31_cpu_type[] __initdata = {
-	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = IMX_CHIP_REVISION_1_0	},
-	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
-	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
+} mx31_cpu_type[] = {
+	{ .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 },
+	{ .srev = 0x10, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x11, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x12, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x13, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x14, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x15, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x28, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_2_0 },
+	{ .srev = 0x29, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_2_0 },
 };
 
-void __init mx31_read_cpu_rev(void)
+static int mx31_read_cpu_rev(void)
 {
 	u32 i, srev;
 
 	/* read SREV register from IIM module */
 	srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
+	srev &= 0xff;
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
 		if (srev == mx31_cpu_type[i].srev) {
-			printk(KERN_INFO
-				"CPU identified as %s, silicon rev %s\n",
-				mx31_cpu_type[i].name, mx31_cpu_type[i].v);
-
-			mx31_cpu_rev = mx31_cpu_type[i].rev;
-			return;
+			imx_print_silicon_rev(mx31_cpu_type[i].name,
+						mx31_cpu_type[i].rev);
+			return mx31_cpu_type[i].rev;
 		}
 
-	mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+	imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN);
+	return IMX_CHIP_REVISION_UNKNOWN;
+}
 
-	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
+int mx31_revision(void)
+{
+	if (mx31_cpu_rev == -1)
+		mx31_cpu_rev = mx31_read_cpu_rev();
+
+	return mx31_cpu_rev;
 }
+EXPORT_SYMBOL(mx31_revision);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx35.c linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx35.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/cpu-imx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/cpu-imx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,32 +13,30 @@
 #include <mach/hardware.h>
 #include <mach/iim.h>
 
-unsigned int mx35_cpu_rev;
-EXPORT_SYMBOL(mx35_cpu_rev);
+static int mx35_cpu_rev = -1;
 
-void __init mx35_read_cpu_rev(void)
+static int mx35_read_cpu_rev(void)
 {
 	u32 rev;
-	char *srev;
 
 	rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
 	switch (rev) {
 	case 0x00:
-		mx35_cpu_rev = IMX_CHIP_REVISION_1_0;
-		srev = "1.0";
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 0x10:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_0;
-		srev = "2.0";
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 0x11:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_1;
-		srev = "2.1";
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		mx35_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
-		srev = "unknown";
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
+}
 
-	printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+int mx35_revision(void)
+{
+	if (mx35_cpu_rev == -1)
+		mx35_cpu_rev = mx35_read_cpu_rev();
+
+	return mx35_cpu_rev;
 }
+EXPORT_SYMBOL(mx35_revision);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx27.h linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx27.h
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx27.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx27.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,3 +76,7 @@ extern const struct imx_spi_imx_data imx
 #define imx27_add_spi_imx0(pdata)	imx27_add_cspi(0, pdata)
 #define imx27_add_spi_imx1(pdata)	imx27_add_cspi(1, pdata)
 #define imx27_add_spi_imx2(pdata)	imx27_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx27_pata_imx_data;
+#define imx27_add_pata_imx() \
+	imx_add_pata_imx(&imx27_pata_imx_data)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx31.h linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx31.h
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx31.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx31.h	2012-01-04 18:55:44.000000000 -0500
@@ -78,3 +78,7 @@ extern const struct imx_spi_imx_data imx
 #define imx31_add_spi_imx0(pdata)	imx31_add_cspi(0, pdata)
 #define imx31_add_spi_imx1(pdata)	imx31_add_cspi(1, pdata)
 #define imx31_add_spi_imx2(pdata)	imx31_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx31_pata_imx_data;
+#define imx31_add_pata_imx() \
+	imx_add_pata_imx(&imx31_pata_imx_data)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx35.h linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx35.h
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/devices-imx35.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/devices-imx35.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,3 +81,7 @@ extern const struct imx_spi_imx_data imx
 	imx_add_spi_imx(&imx35_cspi_data[id], pdata)
 #define imx35_add_spi_imx0(pdata)	imx35_add_cspi(0, pdata)
 #define imx35_add_spi_imx1(pdata)	imx35_add_cspi(1, pdata)
+
+extern const struct imx_pata_imx_data imx35_pata_imx_data;
+#define imx35_add_pata_imx() \
+	imx_add_pata_imx(&imx35_pata_imx_data)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/gpc.c linux-libre-3.2-gnu1/arch/arm/mach-imx/gpc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/gpc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/gpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+
+#define GPC_IMR1		0x008
+#define GPC_PGC_CPU_PDN		0x2a0
+
+#define IMR_NUM			4
+
+static void __iomem *gpc_base;
+static u32 gpc_wake_irqs[IMR_NUM];
+static u32 gpc_saved_imrs[IMR_NUM];
+
+void imx_gpc_pre_suspend(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Tell GPC to power off ARM core when suspend */
+	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++) {
+		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+		writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+	}
+}
+
+void imx_gpc_post_resume(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Keep ARM core powered on for other low-power modes */
+	writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++)
+		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	unsigned int idx = d->irq / 32 - 1;
+	u32 mask;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return -EINVAL;
+
+	mask = 1 << d->irq % 32;
+	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+				  gpc_wake_irqs[idx] & ~mask;
+
+	return 0;
+}
+
+static void imx_gpc_irq_unmask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val &= ~(1 << d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val |= 1 << (d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+void __init imx_gpc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+	gpc_base = of_iomap(np, 0);
+	WARN_ON(!gpc_base);
+
+	/* Register GPC as the secondary interrupt controller behind GIC */
+	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
+	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
+	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/head-v7.S linux-libre-3.2-gnu1/arch/arm/mach-imx/head-v7.S
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/head-v7.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/head-v7.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+	.section ".text.head", "ax"
+	__CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor.  We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures.  Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+	mov	r0, #0
+	mcr	p15, 2, r0, c0, c0, 0
+	mrc	p15, 1, r0, c0, c0, 0
+
+	ldr	r1, =0x7fff
+	and	r2, r1, r0, lsr #13
+
+	ldr	r1, =0x3ff
+
+	and	r3, r1, r0, lsr #3	@ NumWays - 1
+	add	r2, r2, #1		@ NumSets
+
+	and	r0, r0, #0x7
+	add	r0, r0, #4	@ SetShift
+
+	clz	r1, r3		@ WayShift
+	add	r4, r3, #1	@ NumWays
+1:	sub	r2, r2, #1	@ NumSets--
+	mov	r3, r4		@ Temp = NumWays
+2:	subs	r3, r3, #1	@ Temp--
+	mov	r5, r3, lsl r1
+	mov	r6, r2, lsl r0
+	orr	r5, r5, r6	@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+	mcr	p15, 0, r5, c7, c6, 2
+	bgt	2b
+	cmp	r2, #0
+	bgt	1b
+	dsb
+	isb
+	mov	pc, lr
+ENDPROC(v7_invalidate_l1)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
+
+/*
+ * The following code is located into the .data section.  This is to
+ * allow phys_l2x0_saved_regs to be accessed with a relative load
+ * as we are running on physical address here.
+ */
+	.data
+	.align
+
+	.macro	pl310_resume
+	ldr	r2, phys_l2x0_saved_regs
+	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
+	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
+	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
+	mov	r1, #0x1
+	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
+	.endm
+
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+	pl310_resume
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
+
+	.globl	phys_l2x0_saved_regs
+phys_l2x0_saved_regs:
+        .long   0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-imx/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <mach/common.h>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+	imx_enable_cpu(cpu, false);
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/iomux-imx31.c linux-libre-3.2-gnu1/arch/arm/mach-imx/iomux-imx31.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/iomux-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/iomux-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,13 +17,12 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
 #include <mach/iomux-mx3.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-imx/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,18 +1,30 @@
 config IMX_HAVE_DMA_V1
 	bool
-#
-# ARCH_MX31 and ARCH_MX35 are left for compatibility
-# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
-# To easily distinguish good and reviewed from unreviewed usages new (and IMHO
-# more sensible) names are used: SOC_IMX31 and SOC_IMX35
-config ARCH_MX31
+
+config HAVE_IMX_GPC
 	bool
 
-config ARCH_MX35
+config HAVE_IMX_MMDC
+	bool
+
+config HAVE_IMX_SRC
+	bool
+
+config ARCH_MX1
+	bool
+
+config MACH_MX21
+	bool
+
+config ARCH_MX25
+	bool
+
+config MACH_MX27
 	bool
 
 config SOC_IMX1
 	bool
+	select ARCH_MX1
 	select CPU_ARM920T
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
@@ -20,6 +32,7 @@ config SOC_IMX1
 
 config SOC_IMX21
 	bool
+	select MACH_MX21
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -28,6 +41,7 @@ config SOC_IMX21
 
 config SOC_IMX25
 	bool
+	select ARCH_MX25
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MXC_IOMUX_V3
@@ -35,6 +49,7 @@ config SOC_IMX25
 
 config SOC_IMX27
 	bool
+	select MACH_MX27
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -46,8 +61,8 @@ config SOC_IMX31
 	select CPU_V6
 	select IMX_HAVE_PLATFORM_MXC_RNGA
 	select ARCH_MXC_AUDMUX_V2
-	select ARCH_MX31
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 config SOC_IMX35
 	bool
@@ -55,11 +70,11 @@ config SOC_IMX35
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select HAVE_EPIT
-	select ARCH_MX35
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 
-if ARCH_MX1
+if ARCH_IMX_V4_V5
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -87,30 +102,6 @@ config MACH_APF9328
 	help
 	  Say Yes here if you are using the Armadeus APF9328 development board
 
-endif
-
-if ARCH_MX2
-
-choice
-	prompt "CPUs:"
-	default MACH_MX21
-
-config MACH_MX21
-	bool "i.MX21 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX21 processor.
-
-config MACH_MX27
-	bool "i.MX27 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX27 processor.
-
-endchoice
-
-endif
-
-if MACH_MX21
-
 comment "MX21 platforms:"
 
 config MACH_MX21ADS
@@ -124,15 +115,12 @@ config MACH_MX21ADS
 	  Include support for MX21ADS platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif
-
-if ARCH_MX25
-
 comment "MX25 platforms:"
 
 config MACH_MX25_3DS
 	bool "Support MX25PDK (3DS) Platform"
 	select SOC_IMX25
+	select IMX_HAVE_PLATFORM_FLEXCAN
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMXDI_RTC
@@ -144,7 +132,7 @@ config MACH_MX25_3DS
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 
-config MACH_EUKREA_CPUIMX25
+config MACH_EUKREA_CPUIMX25SD
 	bool "Support Eukrea CPUIMX25 Platform"
 	select SOC_IMX25
 	select IMX_HAVE_PLATFORM_FLEXCAN
@@ -160,7 +148,7 @@ config MACH_EUKREA_CPUIMX25
 
 choice
 	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX25
+	depends on MACH_EUKREA_CPUIMX25SD
 	default MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD25_BASEBOARD
@@ -174,10 +162,6 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 endchoice
 
-endif
-
-if MACH_MX27
-
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
@@ -356,7 +340,7 @@ config MACH_IMX27IPCAM
 
 endif
 
-if ARCH_MX3
+if ARCH_IMX_V6_V7
 
 comment "MX31 platforms:"
 
@@ -449,6 +433,7 @@ config MACH_MX31_3DS
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IPU_CORE
 	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -485,6 +470,7 @@ config MACH_QONG
 	bool "Support Dave/DENX QongEVB-LITE platform"
 	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	help
 	  Include support for Dave/DENX QongEVB-LITE platform. This includes
 	  specific configurations for the board and its peripherals.
@@ -556,7 +542,7 @@ config MACH_MX35_3DS
 	  Include support for MX35PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
-config MACH_EUKREA_CPUIMX35
+config MACH_EUKREA_CPUIMX35SD
 	bool "Support Eukrea CPUIMX35 Platform"
 	select SOC_IMX35
 	select IMX_HAVE_PLATFORM_FLEXCAN
@@ -574,7 +560,7 @@ config MACH_EUKREA_CPUIMX35
 
 choice
 	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX35
+	depends on MACH_EUKREA_CPUIMX35SD
 	default MACH_EUKREA_MBIMXSD35_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD35_BASEBOARD
@@ -605,4 +591,20 @@ config MACH_VPR200
 	  Include support for VPR200 platform. This includes specific
 	  configurations for the board and its peripherals.
 
+comment "i.MX6 family:"
+
+config SOC_IMX6Q
+	bool "i.MX6 Quad support"
+	select ARM_GIC
+	select CACHE_L2X0
+	select CPU_V7
+	select HAVE_ARM_SCU
+	select HAVE_IMX_GPC
+	select HAVE_IMX_MMDC
+	select HAVE_IMX_SRC
+	select USE_OF
+
+	help
+	  This enables support for Freescale i.MX6 Quad processor.
+
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/lluart.c linux-libre-3.2-gnu1/arch/arm/mach-imx/lluart.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/lluart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/lluart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+
+static struct map_desc imx_lluart_desc = {
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+	.virtual	= MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
+	.pfn		= __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
+	.length		= MX6Q_UART4_SIZE,
+	.type		= MT_DEVICE,
+#endif
+};
+
+void __init imx_lluart_map_io(void)
+{
+	if (imx_lluart_desc.virtual)
+		iotable_init(&imx_lluart_desc, 1);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/localtimer.c linux-libre-3.2-gnu1/arch/arm/mach-imx/localtimer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/localtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-apf9328.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-apf9328.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-apf9328.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-apf9328.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,6 +136,7 @@ MACHINE_START(APF9328, "Armadeus APF9328
 	.map_io       = mx1_map_io,
 	.init_early   = imx1_init_early,
 	.init_irq     = mx1_init_irq,
+	.handle_irq   = imx1_handle_irq,
 	.timer        = &apf9328_timer,
 	.init_machine = apf9328_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-armadillo5x0.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-armadillo5x0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-armadillo5x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-armadillo5x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -314,25 +314,19 @@ static struct mtd_partition armadillo5x0
 	},
 };
 
-static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+static const struct physmap_flash_data
+		armadillo5x0_nor_flash_pdata __initconst = {
 	.width		= 2,
 	.parts		= armadillo5x0_nor_flash_partitions,
 	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
 };
 
-static struct resource armadillo5x0_nor_flash_resource = {
+static const struct resource armadillo5x0_nor_flash_resource __initconst = {
 	.flags		= IORESOURCE_MEM,
 	.start		= MX31_CS0_BASE_ADDR,
 	.end		= MX31_CS0_BASE_ADDR + SZ_64M - 1,
 };
 
-static struct platform_device armadillo5x0_nor_flash = {
-	.name			= "physmap-flash",
-	.id			= -1,
-	.num_resources		= 1,
-	.resource		= &armadillo5x0_nor_flash_resource,
-};
-
 /*
  * FB support
  */
@@ -514,8 +508,10 @@ static void __init armadillo5x0_init(voi
 	imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
 	/* Register NOR Flash */
-	mxc_register_device(&armadillo5x0_nor_flash,
-			    &armadillo5x0_nor_flash_pdata);
+	platform_device_register_resndata(NULL, "physmap-flash", -1,
+			&armadillo5x0_nor_flash_resource, 1,
+			&armadillo5x0_nor_flash_pdata,
+			sizeof(armadillo5x0_nor_flash_pdata));
 
 	/* Register NAND Flash */
 	imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
@@ -558,10 +554,11 @@ static struct sys_timer armadillo5x0_tim
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &armadillo5x0_timer,
 	.init_machine = armadillo5x0_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-bug.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-bug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-bug.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,7 @@ MACHINE_START(BUG, "BugLabs BUGBase")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &bug_timer,
 	.init_machine = bug_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-cpuimx27.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-cpuimx27.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-cpuimx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-cpuimx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -311,10 +311,11 @@ static struct sys_timer eukrea_cpuimx27_
 };
 
 MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &eukrea_cpuimx27_timer,
 	.init_machine = eukrea_cpuimx27_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-cpuimx35.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-cpuimx35.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-cpuimx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-cpuimx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,12 +53,18 @@ static const struct imxi2c_platform_data
 	.bitrate =		100000,
 };
 
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
+static int tsc2007_get_pendown_state(void)
+{
+	return !gpio_get_value(TSC2007_IRQGPIO);
+}
+
 static struct tsc2007_platform_data tsc2007_info = {
 	.model			= 2007,
 	.x_plate_ohms		= 180,
+	.get_pendown_state = tsc2007_get_pendown_state,
 };
 
-#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
@@ -66,7 +72,7 @@ static struct i2c_board_info eukrea_cpui
 		I2C_BOARD_INFO("tsc2007", 0x48),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -194,10 +200,11 @@ struct sys_timer eukrea_cpuimx35_timer =
 
 MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &eukrea_cpuimx35_timer,
 	.init_machine = eukrea_cpuimx35_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,10 +163,11 @@ static struct sys_timer eukrea_cpuimx25_
 
 MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &eukrea_cpuimx25_timer,
 	.init_machine = eukrea_cpuimx25_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27ipcam.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27ipcam.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27ipcam.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27ipcam.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,10 +71,11 @@ static struct sys_timer mx27ipcam_timer
 
 MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ipcam_timer,
 	.init_machine = mx27ipcam_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27lite.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27lite.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27lite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27lite.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,10 +77,11 @@ static struct sys_timer mx27lite_timer =
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27lite_timer,
 	.init_machine = mx27lite_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2012-01-04 18:55:44.000000000 -0500
@@ -275,10 +275,11 @@ static struct sys_timer visstrim_m10_tim
 };
 
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &visstrim_m10_timer,
 	.init_machine = visstrim_m10_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx6q.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx6q.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __init imx6q_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	imx6q_pm_init();
+}
+
+static void __init imx6q_map_io(void)
+{
+	imx_lluart_map_io();
+	imx_scu_map_io();
+	imx6q_clock_map_io();
+}
+
+static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx6q_irq_match[] __initconst = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static void __init imx6q_init_irq(void)
+{
+	l2x0_of_init(0, ~0UL);
+	imx_src_init();
+	imx_gpc_init();
+	of_irq_init(imx6q_irq_match);
+}
+
+static void __init imx6q_timer_init(void)
+{
+	mx6q_clocks_init();
+}
+
+static struct sys_timer imx6q_timer = {
+	.init = imx6q_timer_init,
+};
+
+static const char *imx6q_dt_compat[] __initdata = {
+	"fsl,imx6q-sabreauto",
+	NULL,
+};
+
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+	.map_io		= imx6q_map_io,
+	.init_irq	= imx6q_init_irq,
+	.handle_irq	= imx6q_handle_irq,
+	.timer		= &imx6q_timer,
+	.init_machine	= imx6q_init_machine,
+	.dt_compat	= imx6q_dt_compat,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-kzm_arm11_01.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-kzm_arm11_01.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-kzm_arm11_01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-kzm_arm11_01.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 
 #include "devices-imx31.h"
@@ -271,10 +272,11 @@ static struct sys_timer kzm_timer = {
 };
 
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = kzm_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &kzm_timer,
 	.init_machine = kzm_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx1ads.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx1ads.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx1ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx1ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,23 +68,16 @@ static const struct imxuart_platform_dat
  * Physmap flash
  */
 
-static struct physmap_flash_data mx1ads_flash_data = {
+static const struct physmap_flash_data mx1ads_flash_data __initconst = {
 	.width		= 4,		/* bankwidth in bytes */
 };
 
-static struct resource flash_resource = {
+static const struct resource flash_resource __initconst = {
 	.start	= MX1_CS0_PHYS,
 	.end	= MX1_CS0_PHYS + SZ_32M - 1,
 	.flags	= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.resource = &flash_resource,
-	.num_resources = 1,
-};
-
 /*
  * I2C
  */
@@ -125,7 +118,9 @@ static void __init mx1ads_init(void)
 	imx1_add_imx_uart1(&uart1_pdata);
 
 	/* Physmap flash */
-	mxc_register_device(&flash_device, &mx1ads_flash_data);
+	platform_device_register_resndata(NULL, "physmap-flash", 0,
+			&flash_resource, 1,
+			&mx1ads_flash_data, sizeof(mx1ads_flash_data));
 
 	/* I2C */
 	i2c_register_board_info(0, mx1ads_i2c_devices,
@@ -145,19 +140,21 @@ struct sys_timer mx1ads_timer = {
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
-	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx21ads.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx21ads.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx21ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx21ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -305,10 +305,11 @@ static struct sys_timer mx21ads_timer =
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX21_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx21ads_map_io,
 	.init_early = imx21_init_early,
 	.init_irq = mx21_init_irq,
+	.handle_irq = imx21_handle_irq,
 	.timer = &mx21ads_timer,
 	.init_machine = mx21ads_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,8 @@
 
 #include "devices-imx25.h"
 
+#define MX25PDK_CAN_PWDN	IMX_GPIO_NR(4, 6)
+
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -108,6 +110,11 @@ static iomux_v3_cfg_t mx25pdk_pads[] = {
 	/* I2C1 */
 	MX25_PAD_I2C1_CLK__I2C1_CLK,
 	MX25_PAD_I2C1_DAT__I2C1_DAT,
+
+	/* CAN1 */
+	MX25_PAD_GPIO_A__CAN1_TX,
+	MX25_PAD_GPIO_B__CAN1_RX,
+	MX25_PAD_D14__GPIO_4_6,	/* CAN_PWDN */
 };
 
 static const struct fec_platform_data mx25_fec_pdata __initconst = {
@@ -240,6 +247,9 @@ static void __init mx25pdk_init(void)
 
 	imx25_add_sdhci_esdhc_imx(0, &mx25pdk_esdhc_pdata);
 	imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
+
+	gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn");
+	imx25_add_flexcan0(NULL);
 }
 
 static void __init mx25pdk_timer_init(void)
@@ -253,10 +263,11 @@ static struct sys_timer mx25pdk_timer =
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &mx25pdk_timer,
 	.init_machine = mx25pdk_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -241,7 +241,7 @@ static struct regulator_init_data gpo_in
 };
 
 static struct regulator_consumer_supply vmmc1_consumers[] = {
-	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("vcore", "spi0.0"),
 };
 
 static struct regulator_init_data vmmc1_init = {
@@ -257,7 +257,7 @@ static struct regulator_init_data vmmc1_
 };
 
 static struct regulator_consumer_supply vgen_consumers[] = {
-	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+	REGULATOR_SUPPLY("vdd", "spi0.0"),
 };
 
 static struct regulator_init_data vgen_init = {
@@ -293,8 +293,7 @@ static struct mc13xxx_platform_data mc13
 		.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
 	},
-	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
-	MC13783_USE_RTC,
+	.flags  = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
 };
 
 /* SPI */
@@ -348,8 +347,6 @@ static const struct imx_fb_platform_data
 static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
 	.reset_gpio		= LCD_RESET,
 	.data_enable_gpio	= LCD_ENABLE,
-	.core_supply		= "lcd_2v8",
-	.io_supply		= "vdd_lcdio",
 };
 
 static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
@@ -359,7 +356,7 @@ static struct spi_board_info mx27_3ds_sp
 		.bus_num	= 1,
 		.chip_select	= 0, /* SS0 */
 		.platform_data	= &mc13783_pdata,
-		.irq = gpio_to_irq(PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(PMIC_INT),
 		.mode = SPI_CS_HIGH,
 	}, {
 		.modalias	= "l4f00242t03",
@@ -421,10 +418,11 @@ static struct sys_timer mx27pdk_timer =
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27pdk_timer,
 	.init_machine = mx27pdk_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx27ads.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx27ads.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx27ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx27ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
@@ -345,10 +344,11 @@ static void __init mx27ads_map_io(void)
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27ads_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ads_timer,
 	.init_machine = mx27ads_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31_3ds.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31_3ds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -285,8 +285,6 @@ static struct mx3fb_platform_data mx3fb_
 static struct l4f00242t03_pdata mx31_3ds_l4f00242t03_pdata = {
 	.reset_gpio		= IOMUX_TO_GPIO(MX31_PIN_LCS1),
 	.data_enable_gpio	= IOMUX_TO_GPIO(MX31_PIN_SER_RS),
-	.core_supply		= "lcd_2v8",
-	.io_supply		= "vdd_lcdio",
 };
 
 /*
@@ -411,7 +409,7 @@ static struct regulator_init_data vmmc2_
 };
 
 static struct regulator_consumer_supply vmmc1_consumers[] = {
-	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("vcore", "spi0.0"),
 	REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
 };
 
@@ -428,7 +426,7 @@ static struct regulator_init_data vmmc1_
 };
 
 static struct regulator_consumer_supply vgen_consumers[] = {
-	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+	REGULATOR_SUPPLY("vdd", "spi0.0"),
 };
 
 static struct regulator_init_data vgen_init = {
@@ -494,7 +492,7 @@ static struct mc13xxx_platform_data mc13
 		.regulators = mx31_3ds_regulators,
 		.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
 	},
-	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
+	.flags  = MC13XXX_USE_TOUCHSCREEN,
 };
 
 /* SPI */
@@ -542,7 +540,7 @@ static const struct mxc_nand_platform_da
 mx31_3ds_nand_board_info __initconst = {
 	.width		= 1,
 	.hw_ecc		= 1,
-#ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT
+#ifdef CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT
 	.flash_bbt	= 1,
 #endif
 };
@@ -764,10 +762,11 @@ static void __init mx31_3ds_reserve(void
 
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31_3ds_timer,
 	.init_machine = mx31_3ds_init,
 	.reserve = mx31_3ds_reserve,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31ads.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31ads.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -535,10 +535,11 @@ static struct sys_timer mx31ads_timer =
 
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31ads_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31ads_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31ads_timer,
 	.init_machine = mx31ads_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31lilly.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31lilly.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31lilly.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31lilly.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/smsc911x.h>
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
@@ -295,10 +296,11 @@ static struct sys_timer mx31lilly_timer
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lilly_timer,
 	.init_machine = mx31lilly_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31lite.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31lite.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31lite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31lite.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/memory.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/moduleparam.h>
 #include <linux/smsc911x.h>
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
@@ -112,8 +113,7 @@ static const struct spi_imx_master spi1_
 };
 
 static struct mc13xxx_platform_data mc13783_pdata __initdata = {
-	.flags  = MC13XXX_USE_RTC |
-		  MC13XXX_USE_REGULATOR,
+	.flags = MC13XXX_USE_RTC,
 };
 
 static struct spi_board_info mc13783_spi_dev __initdata = {
@@ -280,10 +280,11 @@ struct sys_timer mx31lite_timer = {
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31lite_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lite_timer,
 	.init_machine = mx31lite_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31moboard.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31moboard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx31moboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx31moboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/leds.h>
 #include <linux/memory.h>
 #include <linux/mtd/physmap.h>
@@ -28,6 +29,10 @@
 #include <linux/spi/spi.h>
 #include <linux/types.h>
 #include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/input.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -222,7 +227,7 @@ static struct mc13xxx_regulator_init_dat
 	},
 };
 
-static struct mc13783_led_platform_data moboard_led[] = {
+static struct mc13xxx_led_platform_data moboard_led[] = {
 	{
 		.id = MC13783_LED_R1,
 		.name = "coreboard-led-4:red",
@@ -255,7 +260,7 @@ static struct mc13783_led_platform_data
 	},
 };
 
-static struct mc13783_leds_platform_data moboard_leds = {
+static struct mc13xxx_leds_platform_data moboard_leds = {
 	.num_leds = ARRAY_SIZE(moboard_led),
 	.led = moboard_led,
 	.flags = MC13783_LED_SLEWLIMTC,
@@ -264,14 +269,20 @@ static struct mc13783_leds_platform_data
 	.tc2_period = MC13783_LED_PERIOD_10MS,
 };
 
+static struct mc13xxx_buttons_platform_data moboard_buttons = {
+	.b1on_flags = MC13783_BUTTON_DBNC_750MS | MC13783_BUTTON_ENABLE |
+			MC13783_BUTTON_POL_INVERT,
+	.b1on_key = KEY_POWER,
+};
+
 static struct mc13xxx_platform_data moboard_pmic = {
 	.regulators = {
 		.regulators = moboard_regulators,
 		.num_regulators = ARRAY_SIZE(moboard_regulators),
 	},
 	.leds = &moboard_leds,
-	.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
-		MC13XXX_USE_ADC | MC13XXX_USE_LED,
+	.buttons = &moboard_buttons,
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC,
 };
 
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
@@ -490,6 +501,18 @@ err:
 
 }
 
+static void mx31moboard_poweroff(void)
+{
+	struct clk *clk = clk_get_sys("imx2-wdt.0", NULL);
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	mxc_iomux_mode(MX31_PIN_WATCHDOG_RST__WATCHDOG_RST);
+
+	__raw_writew(1 << 6 | 1 << 2, MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+}
+
 static int mx31moboard_baseboard;
 core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
 
@@ -528,6 +551,8 @@ static void __init mx31moboard_init(void
 
 	moboard_usbh2_init();
 
+	pm_power_off = mx31moboard_poweroff;
+
 	switch (mx31moboard_baseboard) {
 	case MX31NOBOARD:
 		break;
@@ -567,11 +592,12 @@ static void __init mx31moboard_reserve(v
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.reserve = mx31moboard_reserve,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31moboard_timer,
 	.init_machine = mx31moboard_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx35_3ds.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx35_3ds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mx35_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mx35_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -217,10 +217,11 @@ struct sys_timer mx35pdk_timer = {
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	/* Maintainer: Freescale Semiconductor, Inc */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &mx35pdk_timer,
 	.init_machine = mx35_3ds_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mxt_td60.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mxt_td60.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-mxt_td60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-mxt_td60.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,10 +267,11 @@ static struct sys_timer mxt_td60_timer =
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mxt_td60_timer,
 	.init_machine = mxt_td60_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pca100.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pca100.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pca100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pca100.c	2012-01-04 18:55:44.000000000 -0500
@@ -435,10 +435,11 @@ static struct sys_timer pca100_timer = {
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.init_machine = pca100_init,
 	.timer = &pca100_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm037.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm037.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm037.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm037.c	2012-01-04 18:55:44.000000000 -0500
@@ -688,11 +688,12 @@ static void __init pcm037_reserve(void)
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	/* Maintainer: Pengutronix */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.reserve = pcm037_reserve,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &pcm037_timer,
 	.init_machine = pcm037_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm038.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm038.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm038.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm038.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,9 @@ static struct platform_device *platform_
  * setup other stuffs to access the sram. */
 static void __init pcm038_init_sram(void)
 {
-	mx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00);
+	__raw_writel(0x0000d843, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(1)));
+	__raw_writel(0x22252521, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(1)));
+	__raw_writel(0x22220a00, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(1)));
 }
 
 static const struct imxi2c_platform_data pcm038_i2c1_data __initconst = {
@@ -266,8 +268,7 @@ static struct mc13xxx_platform_data pcm0
 		.regulators = pcm038_regulators,
 		.num_regulators = ARRAY_SIZE(pcm038_regulators),
 	},
-	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
-		 MC13783_USE_TOUCHSCREEN,
+	.flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
@@ -349,10 +350,11 @@ static struct sys_timer pcm038_timer = {
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &pcm038_timer,
 	.init_machine = pcm038_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm043.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm043.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-pcm043.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-pcm043.c	2012-01-04 18:55:44.000000000 -0500
@@ -418,10 +418,11 @@ struct sys_timer pcm043_timer = {
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &pcm043_timer,
 	.init_machine = pcm043_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-qong.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-qong.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-qong.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-qong.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,7 +190,10 @@ static struct platform_device qong_nand_
 static void __init qong_init_nand_mtd(void)
 {
 	/* init CS */
-	mx31_setup_weimcs(3, 0x00004f00, 0x20013b31, 0x00020800);
+	__raw_writel(0x00004f00, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(3)));
+	__raw_writel(0x20013b31, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(3)));
+	__raw_writel(0x00020800, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(3)));
+
 	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
 
 	/* enable pin */
@@ -249,6 +252,7 @@ static void __init qong_init(void)
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
 	qong_init_fpga();
+	imx31_add_imx2_wdt(NULL);
 }
 
 static void __init qong_timer_init(void)
@@ -262,10 +266,11 @@ static struct sys_timer qong_timer = {
 
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &qong_timer,
 	.init_machine = qong_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-scb9328.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-scb9328.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-scb9328.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-scb9328.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,10 +137,11 @@ static struct sys_timer scb9328_timer =
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
 	/* Sascha Hauer */
-	.boot_params = 0x08000100,
+	.atag_offset = 100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &scb9328_timer,
 	.init_machine = scb9328_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-vpr200.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-vpr200.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mach-vpr200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mach-vpr200.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,7 @@ static struct i2c_board_info vpr200_i2c_
 	}, {
 		I2C_BOARD_INFO("mc13892", 0x08),
 		.platform_data = &vpr200_pmic,
-		.irq = gpio_to_irq(GPIO_PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
 	}
 };
 
@@ -319,6 +319,7 @@ MACHINE_START(VPR200, "VPR200")
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &vpr200_timer,
 	.init_machine = vpr200_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/Makefile linux-libre-3.2-gnu1/arch/arm/mach-imx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,16 +1,15 @@
 obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 
-obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
-obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
-obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
-obj-$(CONFIG_SOC_IMX31) += mm-imx31.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
-obj-$(CONFIG_SOC_IMX35) += mm-imx35.o cpu-imx35.o clock-imx35.o ehci-imx35.o
-obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
+obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -25,7 +24,7 @@ obj-$(CONFIG_MACH_MX21ADS) += mach-mx21a
 
 # i.MX25 based machines
 obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += mach-eukrea_cpuimx25.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
 
 # i.MX27 based machines
@@ -58,6 +57,17 @@ obj-$(CONFIG_MACH_BUG) += mach-bug.o
 # i.MX35 based machines
 obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o
 obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
 obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
+
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
+obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+obj-$(CONFIG_CPU_V7) += head-v7.o
+AFLAGS_head-v7.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-imx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,19 +1,27 @@
-zreladdr-$(CONFIG_ARCH_MX1)	:= 0x08008000
-params_phys-$(CONFIG_ARCH_MX1)	:= 0x08000100
-initrd_phys-$(CONFIG_ARCH_MX1)	:= 0x08800000
+zreladdr-$(CONFIG_SOC_IMX1)	+= 0x08008000
+params_phys-$(CONFIG_SOC_IMX1)	:= 0x08000100
+initrd_phys-$(CONFIG_SOC_IMX1)	:= 0x08800000
 
-zreladdr-$(CONFIG_MACH_MX21)	:= 0xC0008000
-params_phys-$(CONFIG_MACH_MX21)	:= 0xC0000100
-initrd_phys-$(CONFIG_MACH_MX21)	:= 0xC0800000
+zreladdr-$(CONFIG_SOC_IMX21)	+= 0xC0008000
+params_phys-$(CONFIG_SOC_IMX21)	:= 0xC0000100
+initrd_phys-$(CONFIG_SOC_IMX21)	:= 0xC0800000
 
-zreladdr-$(CONFIG_ARCH_MX25)	:= 0x80008000
-params_phys-$(CONFIG_ARCH_MX25)	:= 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX25)	:= 0x80800000
+zreladdr-$(CONFIG_SOC_IMX25)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX25)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX25)	:= 0x80800000
 
-zreladdr-$(CONFIG_MACH_MX27)	:= 0xA0008000
-params_phys-$(CONFIG_MACH_MX27)	:= 0xA0000100
-initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
+zreladdr-$(CONFIG_SOC_IMX27)	+= 0xA0008000
+params_phys-$(CONFIG_SOC_IMX27)	:= 0xA0000100
+initrd_phys-$(CONFIG_SOC_IMX27)	:= 0xA0800000
 
-zreladdr-$(CONFIG_ARCH_MX3)	:= 0x80008000
-params_phys-$(CONFIG_ARCH_MX3)	:= 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX3)	:= 0x80800000
+zreladdr-$(CONFIG_SOC_IMX31)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX31)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX31)	:= 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX35)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX35)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX35)	:= 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
+params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
+initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mmdc.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mmdc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mmdc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mmdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#define MMDC_MAPSR		0x404
+#define BP_MMDC_MAPSR_PSD	0
+#define BP_MMDC_MAPSR_PSS	4
+
+static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	void __iomem *mmdc_base, *reg;
+	u32 val;
+	int timeout = 0x400;
+
+	mmdc_base = of_iomap(np, 0);
+	WARN_ON(!mmdc_base);
+
+	reg = mmdc_base + MMDC_MAPSR;
+
+	/* Enable automatic power saving */
+	val = readl_relaxed(reg);
+	val &= ~(1 << BP_MMDC_MAPSR_PSD);
+	writel_relaxed(val, reg);
+
+	/* Ensure it's successfully enabled */
+	while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout)) {
+		pr_warn("%s: failed to enable automatic power saving\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static struct of_device_id imx_mmdc_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-mmdc", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx_mmdc_driver = {
+	.driver		= {
+		.name	= "imx-mmdc",
+		.owner	= THIS_MODULE,
+		.of_match_table = imx_mmdc_dt_ids,
+	},
+	.probe		= imx_mmdc_probe,
+};
+
+static int __init imx_mmdc_init(void)
+{
+	return platform_driver_register(&imx_mmdc_driver);
+}
+postcore_initcall(imx_mmdc_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx31.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx31.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx31.c	2013-05-02 01:33:50.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx31.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx31_io_desc[] __initdata = {
-	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx31_map_io(void)
-{
-	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
-}
-
-void __init imx31_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX31);
-	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-}
-
-void __init mx31_init_irq(void)
-{
-	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
-	.per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 423,
-	.ap_2_bp_addr = 829,
-	.bp_2_ap_addr = 1029,
-};
-
-static struct sdma_platform_data imx31_sdma_pdata __initdata = {
-	.fw_name = "/*(DEBLOBBED)*/",
-	.script_addrs = &imx31_to2_sdma_script,
-};
-
-void __init imx31_soc_init(void)
-{
-	int to_version = mx31_revision() >> 4;
-
-	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx31_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
-			strlen(imx31_sdma_pdata.fw_name));
-		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx35.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx35.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx35.c	2013-05-02 01:33:52.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx35.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx35_io_desc[] __initdata = {
-	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-void __init mx35_map_io(void)
-{
-	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
-}
-
-void __init imx35_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX35);
-	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-}
-
-void __init mx35_init_irq(void)
-{
-	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.uartsh_2_mcu_addr = 1183,
-	.per_2_shp_addr = 1033,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1333,
-	.mcu_2_ata_addr = 1252,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1111,
-	.shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 729,
-	.uart_2_mcu_addr = 904,
-	.per_2_app_addr = 1597,
-	.mcu_2_app_addr = 834,
-	.uartsh_2_mcu_addr = 1270,
-	.per_2_shp_addr = 1120,
-	.mcu_2_shp_addr = 1048,
-	.ata_2_mcu_addr = 1429,
-	.mcu_2_ata_addr = 1339,
-	.app_2_per_addr = 1531,
-	.app_2_mcu_addr = 770,
-	.shp_2_per_addr = 1198,
-	.shp_2_mcu_addr = 979,
-};
-
-static struct sdma_platform_data imx35_sdma_pdata __initdata = {
-	.fw_name = "/*(DEBLOBBED)*/",
-	.script_addrs = &imx35_to2_sdma_script,
-};
-
-void __init imx35_soc_init(void)
-{
-	int to_version = mx35_revision() >> 4;
-
-	/* i.mx35 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx35_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
-			strlen(imx35_sdma_pdata.fw_name));
-		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx3.c linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/mm-imx3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/mm-imx3.c	2013-05-01 23:41:52.000000000 -0400
@@ -0,0 +1,263 @@
+/*
+ *  Copyright (C) 1999,2000 Arm Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *    - add MX31 specific definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-v3.h>
+#include <mach/irqs.h>
+
+static void imx3_idle(void)
+{
+	unsigned long reg = 0;
+
+	if (!need_resched())
+		__asm__ __volatile__(
+			/* disable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"bic %0, %0, #0x00001000\n"
+			"bic %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			/* invalidate I cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c5, 0\n"
+			/* clear and invalidate D cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c14, 0\n"
+			/* WFI */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c0, 4\n"
+			"nop\n" "nop\n" "nop\n" "nop\n"
+			"nop\n" "nop\n" "nop\n"
+			/* enable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"orr %0, %0, #0x00001000\n"
+			"orr %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			: "=r" (reg));
+	local_irq_enable();
+}
+
+static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
+				  unsigned int mtype)
+{
+	if (mtype == MT_DEVICE) {
+		/*
+		 * Access all peripherals below 0x80000000 as nonshared device
+		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
+		 * can occur.
+		 */
+		if (phys_addr < 0x80000000 &&
+				!addr_in_module(phys_addr, MX3x_L2CC))
+			mtype = MT_DEVICE_NONSHARED;
+	}
+
+	return __arm_ioremap(phys_addr, size, mtype);
+}
+
+void imx3_init_l2x0(void)
+{
+	void __iomem *l2x0_base;
+	void __iomem *clkctl_base;
+
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value.
+ */
+#define L2_MEM_VAL 0x10
+
+	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+	if (clkctl_base != NULL) {
+		writel(0x00000515, clkctl_base + L2_MEM_VAL);
+		iounmap(clkctl_base);
+	} else {
+		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+	}
+
+	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
+	if (IS_ERR(l2x0_base)) {
+		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+				PTR_ERR(l2x0_base));
+		return;
+	}
+
+	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+}
+
+#ifdef CONFIG_SOC_IMX31
+static struct map_desc mx31_io_desc[] __initdata = {
+	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx31_map_io(void)
+{
+	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX31);
+	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+	pm_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init mx31_init_irq(void)
+{
+	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+	.per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 423,
+	.ap_2_bp_addr = 829,
+	.bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+	.fw_name = "/*(DEBLOBBED)*/",
+	.script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+	int to_version = mx31_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx31_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
+			strlen(imx31_sdma_pdata.fw_name));
+		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX35);
+	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+	pm_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init mx35_init_irq(void)
+{
+	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.uartsh_2_mcu_addr = 1183,
+	.per_2_shp_addr = 1033,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1333,
+	.mcu_2_ata_addr = 1252,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1111,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1597,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1270,
+	.per_2_shp_addr = 1120,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1429,
+	.mcu_2_ata_addr = 1339,
+	.app_2_per_addr = 1531,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1198,
+	.shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+	.fw_name = "/*(DEBLOBBED)*/",
+	.script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+	int to_version = mx35_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	/* i.mx35 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx35_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
+			strlen(imx35_sdma_pdata.fw_name));
+		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX35 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-imx/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __iomem *scu_base;
+
+static struct map_desc scu_io_desc __initdata = {
+	/* .virtual and .pfn are run-time assigned */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.virtual = IMX_IO_P2V(base);
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+
+	scu_base = IMX_IO_ADDRESS(base);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	imx_set_cpu_jump(cpu, v7_secondary_startup);
+	imx_enable_cpu(cpu, true);
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	int i, ncores;
+
+	ncores = scu_get_core_count(scu_base);
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+	scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	imx_smp_prepare();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/pm-imx27.c linux-libre-3.2-gnu1/arch/arm/mach-imx/pm-imx27.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/pm-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/pm-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/io.h>
 #include <mach/system.h>
-#include <mach/mx27.h>
+#include <mach/hardware.h>
 
 static int mx27_suspend_enter(suspend_state_t state)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/pm-imx6q.c linux-libre-3.2-gnu1/arch/arm/mach-imx/pm-imx6q.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/pm-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/pm-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern unsigned long phys_l2x0_saved_regs;
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		imx6q_set_lpm(STOP_POWER_OFF);
+		imx_gpc_pre_suspend();
+		imx_set_cpu_jump(0, v7_cpu_resume);
+		/* Zzz ... */
+		cpu_suspend(0, imx6q_suspend_finish);
+		imx_smp_prepare();
+		imx_gpc_post_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+	.enter = imx6q_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_init(void)
+{
+	/*
+	 * The l2x0 core code provides an infrastucture to save and restore
+	 * l2x0 registers across suspend/resume cycle.  But because imx6q
+	 * retains L2 content during suspend and needs to resume L2 before
+	 * MMU is enabled, it can only utilize register saving support and
+	 * have to take care of restoring on its own.  So we save physical
+	 * address of the data structure used by l2x0 core to save registers,
+	 * and later restore the necessary ones in imx6q resume entry.
+	 */
+	phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
+
+	suspend_set_ops(&imx6q_pm_ops);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-imx/src.c linux-libre-3.2-gnu1/arch/arm/mach-imx/src.c
--- linux-libre-3.1-gnu1/arch/arm/mach-imx/src.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-imx/src.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/unified.h>
+
+#define SRC_SCR				0x000
+#define SRC_GPR1			0x020
+#define BP_SRC_SCR_CORE1_RST		14
+#define BP_SRC_SCR_CORE1_ENABLE		22
+
+static void __iomem *src_base;
+
+#ifndef CONFIG_SMP
+#define cpu_logical_map(cpu)		0
+#endif
+
+void imx_enable_cpu(int cpu, bool enable)
+{
+	u32 mask, val;
+
+	cpu = cpu_logical_map(cpu);
+	mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+	val = readl_relaxed(src_base + SRC_SCR);
+	val = enable ? val | mask : val & ~mask;
+	writel_relaxed(val, src_base + SRC_SCR);
+}
+
+void imx_set_cpu_jump(int cpu, void *jump_addr)
+{
+	cpu = cpu_logical_map(cpu);
+	writel_relaxed(BSYM(virt_to_phys(jump_addr)),
+		       src_base + SRC_GPR1 + cpu * 8);
+}
+
+void __init imx_src_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+	src_base = of_iomap(np, 0);
+	WARN_ON(!src_base);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/core.c linux-libre-3.2-gnu1/arch/arm/mach-integrator/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -126,6 +126,10 @@ static struct clk_lookup lookups[] = {
 	{	/* Bus clock */
 		.con_id		= "apb_pclk",
 		.clk		= &dummy_apb_pclk,
+	}, {
+		/* Integrator/AP timer frequency */
+		.dev_id		= "ap_timer",
+		.clk		= &clk24mhz,
 	}, {	/* UART0 */
 		.dev_id		= "mb:16",
 		.clk		= &uartclk,
@@ -205,7 +209,7 @@ static struct amba_pl010_data integrator
 
 #define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL)
 
-static DEFINE_SPINLOCK(cm_lock);
+static DEFINE_RAW_SPINLOCK(cm_lock);
 
 /**
  * cm_control - update the CM_CTRL register.
@@ -217,10 +221,10 @@ void cm_control(u32 mask, u32 set)
 	unsigned long flags;
 	u32 val;
 
-	spin_lock_irqsave(&cm_lock, flags);
+	raw_spin_lock_irqsave(&cm_lock, flags);
 	val = readl(CM_CTRL) & ~mask;
 	writel(val | set, CM_CTRL);
-	spin_unlock_irqrestore(&cm_lock, flags);
+	raw_spin_unlock_irqrestore(&cm_lock, flags);
 }
 
 EXPORT_SYMBOL(cm_control);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x16000000	@ physical base address
 		mov	\rv, #0xf0000000	@ virtual base
 		add	\rv, \rv, #0x16000000 >> 4
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
-
 /*
  * WARNING: this has to mirror definitions in platform.h
  */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/platform.h linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/platform.h
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/include/mach/platform.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/include/mach/platform.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-/* DO NOT EDIT!! - this file automatically generated
- *                 from .s file by awk -f s2h.awk
- */
 /**************************************************************************
  * * Copyright Â© ARM Limited 1998.  All rights reserved.
  * ***********************************************************************/
@@ -399,15 +396,6 @@
 #define INTEGRATOR_TIMER1_BASE          (INTEGRATOR_CT_BASE + 0x100)
 #define INTEGRATOR_TIMER2_BASE          (INTEGRATOR_CT_BASE + 0x200)
 
-#define TICKS_PER_uSEC                  24
-
-/*
- *  These are useconds NOT ticks.
- *
- */
-#define mSEC_1                          1000
-#define mSEC_10                         (mSEC_1 * 10)
-
 #define INTEGRATOR_CSR_BASE             0x10000000
 #define INTEGRATOR_CSR_SIZE             0x10000000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/integrator_ap.c linux-libre-3.2-gnu1/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/integrator_ap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/integrator_ap.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mtd/physmap.h>
+#include <linux/clk.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -322,27 +323,16 @@ static void __init ap_init(void)
 #define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
 #define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
 
-/*
- * How long is the timer interval?
- */
-#define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
-#if TIMER_INTERVAL >= 0x100000
-#define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
-#elif TIMER_INTERVAL >= 0x10000
-#define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
-#else
-#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
-#endif
-
 static unsigned long timer_reload;
 
-static void integrator_clocksource_init(u32 khz)
+static void integrator_clocksource_init(unsigned long inrate)
 {
 	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
 	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
+	unsigned long rate = inrate;
 
-	if (khz >= 1500) {
-		khz /= 16;
+	if (rate >= 1500000) {
+		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}
 
@@ -350,7 +340,7 @@ static void integrator_clocksource_init(
 	writel(ctrl, base + TIMER_CTRL);
 
 	clocksource_mmio_init(base + TIMER_VALUE, "timer2",
-		khz * 1000, 200, 16, clocksource_mmio_readl_down);
+			rate, 200, 16, clocksource_mmio_readl_down);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
@@ -374,15 +364,29 @@ static void clkevt_set_mode(enum clock_e
 {
 	u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
 
-	BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT);
+	/* Disable timer */
+	writel(ctrl, clkevt_base + TIMER_CTRL);
 
-	if (mode == CLOCK_EVT_MODE_PERIODIC) {
-		writel(ctrl, clkevt_base + TIMER_CTRL);
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* Enable the timer and start the periodic tick */
 		writel(timer_reload, clkevt_base + TIMER_LOAD);
 		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+		writel(ctrl, clkevt_base + TIMER_CTRL);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* Leave the timer disabled, .set_next_event will enable it */
+		ctrl &= ~TIMER_CTRL_PERIODIC;
+		writel(ctrl, clkevt_base + TIMER_CTRL);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+	default:
+		/* Just leave in disabled state */
+		break;
 	}
 
-	writel(ctrl, clkevt_base + TIMER_CTRL);
 }
 
 static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
@@ -398,12 +402,10 @@ static int clkevt_set_next_event(unsigne
 
 static struct clock_event_device integrator_clockevent = {
 	.name		= "timer1",
-	.shift		= 34,
-	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.set_mode	= clkevt_set_mode,
 	.set_next_event	= clkevt_set_next_event,
 	.rating		= 300,
-	.cpumask	= cpu_all_mask,
 };
 
 static struct irqaction integrator_timer_irq = {
@@ -413,29 +415,27 @@ static struct irqaction integrator_timer
 	.dev_id		= &integrator_clockevent,
 };
 
-static void integrator_clockevent_init(u32 khz)
+static void integrator_clockevent_init(unsigned long inrate)
 {
-	struct clock_event_device *evt = &integrator_clockevent;
+	unsigned long rate = inrate;
 	unsigned int ctrl = 0;
 
-	if (khz * 1000 > 0x100000 * HZ) {
-		khz /= 256;
+	/* Calculate and program a divisor */
+	if (rate > 0x100000 * HZ) {
+		rate /= 256;
 		ctrl |= TIMER_CTRL_DIV256;
-	} else if (khz * 1000 > 0x10000 * HZ) {
-		khz /= 16;
+	} else if (rate > 0x10000 * HZ) {
+		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}
-
-	timer_reload = khz * 1000 / HZ;
+	timer_reload = rate / HZ;
 	writel(ctrl, clkevt_base + TIMER_CTRL);
 
-	evt->irq = IRQ_TIMERINT1;
-	evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift);
-	evt->max_delta_ns = clockevent_delta2ns(0xffff, evt);
-	evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
-
 	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
-	clockevents_register_device(evt);
+	clockevents_config_and_register(&integrator_clockevent,
+					rate,
+					1,
+					0xffffU);
 }
 
 /*
@@ -443,14 +443,20 @@ static void integrator_clockevent_init(u
  */
 static void __init ap_init_timer(void)
 {
-	u32 khz = TICKS_PER_uSEC * 1000;
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get_sys("ap_timer", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+	rate = clk_get_rate(clk);
 
 	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
-	integrator_clocksource_init(khz);
-	integrator_clockevent_init(khz);
+	integrator_clocksource_init(rate);
+	integrator_clockevent_init(rate);
 }
 
 static struct sys_timer ap_timer = {
@@ -459,7 +465,7 @@ static struct sys_timer ap_timer = {
 
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
 	.map_io		= ap_map_io,
 	.init_early	= integrator_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/integrator_cp.c linux-libre-3.2-gnu1/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/integrator_cp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/integrator_cp.c	2012-01-04 18:55:44.000000000 -0500
@@ -492,7 +492,7 @@ static struct sys_timer cp_timer = {
 
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
 	.map_io		= intcp_map_io,
 	.init_early	= intcp_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-integrator/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-integrator/pci_v3.c linux-libre-3.2-gnu1/arch/arm/mach-integrator/pci_v3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-integrator/pci_v3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-integrator/pci_v3.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@
  *	 7:2	register number
  *  
  */
-static DEFINE_SPINLOCK(v3_lock);
+static DEFINE_RAW_SPINLOCK(v3_lock);
 
 #define PCI_BUS_NONMEM_START	0x00000000
 #define PCI_BUS_NONMEM_SIZE	SZ_256M
@@ -284,7 +284,7 @@ static int v3_read_config(struct pci_bus
 	unsigned long flags;
 	u32 v;
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 	addr = v3_open_config_window(bus, devfn, where);
 
 	switch (size) {
@@ -302,7 +302,7 @@ static int v3_read_config(struct pci_bus
 	}
 
 	v3_close_config_window();
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 
 	*val = v;
 	return PCIBIOS_SUCCESSFUL;
@@ -314,7 +314,7 @@ static int v3_write_config(struct pci_bu
 	unsigned long addr;
 	unsigned long flags;
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 	addr = v3_open_config_window(bus, devfn, where);
 
 	switch (size) {
@@ -335,7 +335,7 @@ static int v3_write_config(struct pci_bu
 	}
 
 	v3_close_config_window();
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -513,7 +513,7 @@ void __init pci_v3_preinit(void)
 	hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
 	hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 
 	/*
 	 * Unlock V3 registers, but only if they were previously locked.
@@ -586,7 +586,7 @@ void __init pci_v3_preinit(void)
 		printk(KERN_ERR "PCI: unable to grab PCI error "
 		       "interrupt: %d\n", ret);
 
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 }
 
 void __init pci_v3_postinit(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	mov	\rp, #0x00002300
 	orr	\rp, \rp, #0x00000040
 	orr	\rv, \rp, #0xfe000000	@ virtual
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/iq81340mc.c linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/iq81340mc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/iq81340mc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/iq81340mc.c	2012-01-04 18:55:44.000000000 -0500
@@ -91,7 +91,7 @@ static struct sys_timer iq81340mc_timer
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
 	.timer          = &iq81340mc_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/iq81340sc.c linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/iq81340sc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/iq81340sc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/iq81340sc.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ static struct sys_timer iq81340sc_timer
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
 	.timer          = &iq81340sc_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y   := 0x00008000
+   zreladdr-y   += 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y 	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/pci.c linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/pci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop13xx/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop13xx/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
+#include <linux/export.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/sizes.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/em7210.c linux-libre-3.2-gnu1/arch/arm/mach-iop32x/em7210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/em7210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/em7210.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@ static void __init em7210_init_machine(v
 }
 
 MACHINE_START(EM7210, "Lanner EM7210")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= em7210_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &em7210_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/glantank.c linux-libre-3.2-gnu1/arch/arm/mach-iop32x/glantank.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/glantank.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/glantank.c	2012-01-04 18:55:44.000000000 -0500
@@ -207,7 +207,7 @@ static void __init glantank_init_machine
 
 MACHINE_START(GLANTANK, "GLAN Tank")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= glantank_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &glantank_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-iop32x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xfe000000	@ physical as well as virtual
 		orr	\rp, \rp, #0x00800000	@ location of the UART
 		mov	\rv, \rp
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-iop32x/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0xa0000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/iq31244.c linux-libre-3.2-gnu1/arch/arm/mach-iop32x/iq31244.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/iq31244.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/iq31244.c	2012-01-04 18:55:44.000000000 -0500
@@ -313,7 +313,7 @@ __setup("force_ep80219", force_ep80219_s
 
 MACHINE_START(IQ31244, "Intel IQ31244")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq31244_timer,
@@ -327,7 +327,7 @@ MACHINE_END
  */
 MACHINE_START(EP80219, "Intel EP80219")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq31244_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/iq80321.c linux-libre-3.2-gnu1/arch/arm/mach-iop32x/iq80321.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/iq80321.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/iq80321.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@ static void __init iq80321_init_machine(
 
 MACHINE_START(IQ80321, "Intel IQ80321")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq80321_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq80321_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-iop32x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0xa0008000
+   zreladdr-y	+= 0xa0008000
 params_phys-y	:= 0xa0000100
 initrd_phys-y	:= 0xa0800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop32x/n2100.c linux-libre-3.2-gnu1/arch/arm/mach-iop32x/n2100.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop32x/n2100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop32x/n2100.c	2012-01-04 18:55:44.000000000 -0500
@@ -327,7 +327,7 @@ static void __init n2100_init_machine(vo
 
 MACHINE_START(N2100, "Thecus N2100")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= n2100_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &n2100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop33x/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-iop33x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-iop33x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop33x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00ff0000
 		orr	\rp, \rp, #0x0000f700
 		orr	\rv, #0xfe000000	@ virtual
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop33x/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-iop33x/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-iop33x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop33x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop33x/iq80331.c linux-libre-3.2-gnu1/arch/arm/mach-iop33x/iq80331.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop33x/iq80331.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop33x/iq80331.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@ static void __init iq80331_init_machine(
 
 MACHINE_START(IQ80331, "Intel IQ80331")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
 	.timer		= &iq80331_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop33x/iq80332.c linux-libre-3.2-gnu1/arch/arm/mach-iop33x/iq80332.c
--- linux-libre-3.1-gnu1/arch/arm/mach-iop33x/iq80332.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop33x/iq80332.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@ static void __init iq80332_init_machine(
 
 MACHINE_START(IQ80332, "Intel IQ80332")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
 	.timer		= &iq80332_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-iop33x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-iop33x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-iop33x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-iop33x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/core.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * License version 2. This program is licensed "as is" without any 
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
@@ -25,6 +25,7 @@
 #include <linux/bitops.h>
 #include <linux/serial_8250.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -39,7 +40,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
 
 static DEFINE_SPINLOCK(ixp2000_slowport_lock);
 static unsigned long ixp2000_slowport_irq_flags;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/enp2611.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/enp2611.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/enp2611.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/enp2611.c	2012-01-04 18:55:44.000000000 -0500
@@ -254,7 +254,7 @@ static void __init enp2611_init_machine(
 
 MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= enp2611_map_io,
 	.init_irq	= ixp2000_init_irq,
 	.timer		= &enp2611_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro  addruart, rp, rv
+		.macro  addruart, rp, rv, tmp
 		mov	\rp, #0x00030000
 #ifdef	__ARMEB__
 		orr	\rp, \rp, #0x00000003
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/gpio.h
- *
- * Copyright (C) 2002 Intel Corporation.
- *
- * 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.
- */
-
-/*
- * IXP2000 GPIO in/out, edge/level detection for IRQs:
- * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
- * or both Falling-edge and Rising-edge.  
- * This must be called *before* the corresponding IRQ is registerd.
- * Use this instead of directly setting the GPIO registers.
- * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
- */
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#ifndef __ASSEMBLY__
-
-#define GPIO_IN				0
-#define GPIO_OUT			1
-
-#define IXP2000_GPIO_LOW		0
-#define IXP2000_GPIO_HIGH		1
-
-extern void gpio_line_config(int line, int direction);
-
-static inline int gpio_line_get(int line)
-{
-	return (((*IXP2000_GPIO_PLR) >> line) & 1);
-}
-
-static inline void gpio_line_set(int line, int value)
-{
-	if (value == IXP2000_GPIO_HIGH) {
-		ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
-	} else if (value == IXP2000_GPIO_LOW) {
-		ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
-	}
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/mach-ixp2000/include/mach/gpio.h
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ *
+ * 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.
+ */
+
+/*
+ * IXP2000 GPIO in/out, edge/level detection for IRQs:
+ * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
+ * or both Falling-edge and Rising-edge.
+ * This must be called *before* the corresponding IRQ is registerd.
+ * Use this instead of directly setting the GPIO registers.
+ * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#ifndef __ASSEMBLY__
+
+#define GPIO_IN				0
+#define GPIO_OUT			1
+
+#define IXP2000_GPIO_LOW		0
+#define IXP2000_GPIO_HIGH		1
+
+extern void gpio_line_config(int line, int direction);
+
+static inline int gpio_line_get(int line)
+{
+	return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+	if (value == IXP2000_GPIO_HIGH) {
+		ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
+	} else if (value == IXP2000_GPIO_LOW) {
+		ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
+	}
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2400.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2400.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2400.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,7 @@ void __init ixdp2400_init_irq(void)
 
 MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2400_init_irq,
 	.timer		= &ixdp2400_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2800.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2800.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2800.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2800.c	2012-01-04 18:55:44.000000000 -0500
@@ -286,7 +286,7 @@ void __init ixdp2800_init_irq(void)
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2800_init_irq,
 	.timer		= &ixdp2800_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -40,8 +41,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/arch.h>
 
-#include <mach/gpio.h>
-
+#include <mach/gpio-ixp2000.h>
 
 /*************************************************************************
  * IXDP2x00 IRQ Initialization
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c	2012-01-04 18:55:44.000000000 -0500
@@ -417,7 +417,7 @@ static void __init ixdp2x01_init_machine
 #ifdef CONFIG_ARCH_IXDP2401
 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
@@ -428,7 +428,7 @@ MACHINE_END
 #ifdef CONFIG_ARCH_IXDP2801
 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
@@ -441,7 +441,7 @@ MACHINE_END
  */
 MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp2000/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp2000/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/espresso.c linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/espresso.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/espresso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/espresso.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,6 @@ MACHINE_START(ESPRESSO, "IP Fabrics Doub
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= espresso_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <mach/ixp23xx.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =IXP23XX_PERIPHERAL_PHYS 	@ physical
 		ldr	\rv, =IXP23XX_PERIPHERAL_VIRT	@ virtual
 #ifdef __ARMEB__
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c	2012-01-04 18:55:44.000000000 -0500
@@ -331,6 +331,6 @@ MACHINE_START(IXDP2351, "Intel IXDP2351
 	.map_io		= ixdp2351_map_io,
 	.init_irq	= ixdp2351_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp2351_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/roadrunner.c linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/roadrunner.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp23xx/roadrunner.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp23xx/roadrunner.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,6 +175,6 @@ MACHINE_START(ROADRUNNER, "ADI Engineeri
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= roadrunner_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/avila-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/avila-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/avila-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/avila-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@ MACHINE_START(AVILA, "Gateworks Avila Ne
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -185,7 +185,7 @@ MACHINE_START(LOFT, "Giant Shoulder Inc
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/common.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/udc.h>
 #include <mach/hardware.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/common-pci.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/common-pci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/common-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/common-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/dma-mapping.h>
 
 #include <asm/cputype.h>
@@ -54,7 +55,7 @@ unsigned long ixp4xx_pci_reg_base = 0;
  * these transactions are atomic or we will end up
  * with corrupt data on the bus or in a driver.
  */
-static DEFINE_SPINLOCK(ixp4xx_pci_lock);
+static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock);
 
 /*
  * Read from PCI config space
@@ -62,10 +63,10 @@ static DEFINE_SPINLOCK(ixp4xx_pci_lock);
 static void crp_read(u32 ad_cbe, u32 *data)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 	*PCI_CRP_AD_CBE = ad_cbe;
 	*data = *PCI_CRP_RDATA;
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 }
 
 /*
@@ -74,10 +75,10 @@ static void crp_read(u32 ad_cbe, u32 *da
 static void crp_write(u32 ad_cbe, u32 data)
 { 
 	unsigned long flags;
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 	*PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe;
 	*PCI_CRP_WDATA = data;
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 }
 
 static inline int check_master_abort(void)
@@ -101,7 +102,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32
 	int retval = 0;
 	int i;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -118,7 +119,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -127,7 +128,7 @@ int ixp4xx_pci_read_no_errata(u32 addr,
 	unsigned long flags;
 	int retval = 0;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -140,7 +141,7 @@ int ixp4xx_pci_read_no_errata(u32 addr,
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -149,7 +150,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd,
 	unsigned long flags;
 	int retval = 0;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -162,7 +163,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd,
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -397,7 +398,8 @@ void __init ixp4xx_pci_preinit(void)
 		local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET);
 		local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M);
 		local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M);
-		local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M);
+		local_write_config(PCI_BASE_ADDRESS_3, 4,
+					PHYS_OFFSET + SZ_32M + SZ_16M);
 
 		/*
 		 * Enable CSR window at 64 MiB to allow PCI masters
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/coyote-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/coyote-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/coyote-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/coyote-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -112,7 +112,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineeri
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -130,7 +130,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425"
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 MACHINE_END
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/dsmg600-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/dsmg600-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/dsmg600-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/dsmg600-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Author: Rod Whitby <rod@whitby.id.au>
  * Maintainers: http://www.nslu2-linux.org/
  */
-
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
@@ -31,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
-#include <asm/gpio.h>
 
 #define DSMG600_SDA_PIN		5
 #define DSMG600_SCL_PIN		4
@@ -279,7 +278,7 @@ static void __init dsmg600_init(void)
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &dsmg600_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/fsg-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/fsg-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/fsg-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/fsg-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/serial.h>
@@ -27,7 +27,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
-#include <asm/gpio.h>
 
 #define FSG_SDA_PIN		12
 #define FSG_SCL_PIN		13
@@ -273,7 +272,7 @@ MACHINE_START(FSG, "Freecom FSG-3")
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= fsg_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/gateway7001-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/gateway7001-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/gateway7001-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/gateway7001-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -99,7 +99,7 @@ MACHINE_START(GATEWAY7001, "Gateway 7001
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gateway7001_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/goramo_mlr.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/goramo_mlr.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/goramo_mlr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/goramo_mlr.c	2012-01-04 18:55:44.000000000 -0500
@@ -499,7 +499,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gmlr_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/gtwx5715-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/gtwx5715-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/gtwx5715-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/gtwx5715-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gtwx5715_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
 */
 
-                .macro  addruart, rp, rv
+                .macro  addruart, rp, rv, tmp
 #ifdef __ARMEB__
                 mov     \rp, #3         @ Uart regs are at off set of 3 if
 					@ byte writes used - Big Endian.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <linux/kernel.h>
 #include <mach/hardware.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 static inline int gpio_request(unsigned gpio, const char *label)
 {
 	return 0;
@@ -70,6 +72,7 @@ static inline void gpio_set_value(unsign
 #include <asm-generic/gpio.h>			/* cansleep wrappers */
 
 extern int gpio_to_irq(int gpio);
+#define gpio_to_irq gpio_to_irq
 extern int irq_to_gpio(unsigned int irq);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0x0000ffff
-
 extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
 extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/memory.h
- *
- * Copyright (c) 2001-2004 MontaVista Software, Inc.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/sizes.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,8 @@ static __inline__ void __arch_decomp_set
 	 * Some boards are using UART2 as console
 	 */
 	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
-			 machine_is_gateway7001() || machine_is_wg302v2())
+	    machine_is_gateway7001() || machine_is_wg302v2() ||
+	    machine_is_devixp() || machine_is_miccpt() || machine_is_mic256())
 		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
 	else
 		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/ixdp425-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/ixdp425-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/ixdp425-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,7 +256,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 De
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -270,7 +270,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 De
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -284,7 +284,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP110
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -298,7 +298,7 @@ MACHINE_START(KIXRP435, "Intel KIXRP435
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -179,6 +179,25 @@ config MACH_GTWX5715
 		"High Speed" UART is n/c (as far as I can tell)
 		20 Pin ARM/Xscale JTAG interface on J2
 
+config MACH_DEVIXP
+	bool "Omicron DEVIXP"
+	help
+	  Say 'Y' here if you want your kernel to support the DEVIXP
+	  board from OMICRON electronics GmbH.
+
+config MACH_MICCPT
+	bool "Omicron MICCPT"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the MICCPT
+	  board from OMICRON electronics GmbH.
+
+config MACH_MIC256
+	bool "Omicron MIC256"
+	help
+	  Say 'Y' here if you want your kernel to support the MIC256
+	  board from OMICRON electronics GmbH.
+
 comment "IXP4xx Options"
 
 config IXP4XX_INDIRECT_PCI
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Makefile linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@ obj-pci-$(CONFIG_MACH_AVILA)		+= avila-p
 obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
 obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_MICCPT)		+= miccpt-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
@@ -25,6 +26,9 @@ obj-$(CONFIG_MACH_AVILA)	+= avila-setup.
 obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+obj-$(CONFIG_MACH_DEVIXP)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MICCPT)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MIC256)	+= omixp-setup.o
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/miccpt-pci.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/miccpt-pci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/miccpt-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/miccpt-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * 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/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		1
+#define INTB		2
+#define INTC		3
+#define INTD		4
+
+
+void __init miccpt_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit	= miccpt_pci_preinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= ixp4xx_setup,
+	.scan		= ixp4xx_scan_bus,
+	.map_irq	= miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+	if (machine_is_miccpt())
+		pci_common_init(&miccpt_pci);
+	return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/nas100d-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/nas100d-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/nas100d-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/nas100d-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/jiffies.h>
@@ -32,7 +32,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
-#include <asm/gpio.h>
 
 #define NAS100D_SDA_PIN		5
 #define NAS100D_SCL_PIN		6
@@ -314,7 +313,7 @@ static void __init nas100d_init(void)
 
 MACHINE_START(NAS100D, "Iomega NAS 100d")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &ixp4xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/nslu2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/nslu2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/nslu2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/nslu2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/serial.h>
@@ -30,7 +30,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
-#include <asm/gpio.h>
 
 #define NSLU2_SDA_PIN		7
 #define NSLU2_SCL_PIN		6
@@ -300,7 +299,7 @@ static void __init nslu2_init(void)
 
 MACHINE_START(NSLU2, "Linksys NSLU2")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &nslu2_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/omixp-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/omixp-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/omixp-setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/omixp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ *      Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct resource omixp_flash_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition omixp_partitions[] = {
+	{
+		.name =		"Recovery Bootloader",
+		.size =		0x00020000,
+		.offset =	0,
+	}, {
+		.name =		"Calibration Data",
+		.size =		0x00020000,
+		.offset =	0x00020000,
+	}, {
+		.name =		"Recovery FPGA",
+		.size =		0x00020000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Release Bootloader",
+		.size =		0x00020000,
+		.offset =	0x00060000,
+	}, {
+		.name =		"Release FPGA",
+		.size =		0x00020000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00160000,
+		.offset =	0x000a0000,
+	}, {
+		.name =		"Filesystem",
+		.size =		0x00C00000,
+		.offset =	0x00200000,
+	}, {
+		.name =		"Persistent Storage",
+		.size =		0x00200000,
+		.offset =	0x00E00000,
+	},
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= omixp_partitions,
+		.nr_parts	= ARRAY_SIZE(omixp_partitions),
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+	},
+};
+
+static struct platform_device omixp_flash_device[] = {
+	{
+		.name		= "IXP4XX-Flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &omixp_flash_data[0],
+		},
+		.resource = &omixp_flash_resources[0],
+		.num_resources = 1,
+	}, {
+		.name		= "IXP4XX-Flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &omixp_flash_data[1],
+		},
+		.resource = &omixp_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ *      ttyS0 .. UART2
+ *      ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct plat_serial8250_port omixp_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,
+	}, {
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		/* list termination */
+	}
+};
+
+static struct platform_device omixp_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= omixp_uart_data,
+	.num_resources		= 2,
+	.resource		= omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+	{
+		.name		= "LED-A",
+		.gpio		= 7,
+	},
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+	.num_leds		= ARRAY_SIZE(mic256_led_pins),
+	.leds			= mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	},
+};
+
+static struct platform_device ixdp425_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= ixdp425_plat_eth,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= ixdp425_plat_eth + 1,
+	},
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&mic256_leds,
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&omixp_flash_device[1],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* 16MiB Boot Flash */
+	omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+	omixp_flash_resources[0].end   = IXP4XX_EXP_BUS_END(0);
+
+	/* 32 MiB Data Flash */
+	omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	omixp_flash_resources[1].end   = IXP4XX_EXP_BUS_END(2);
+
+	if (machine_is_devixp())
+		platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+	else if (machine_is_miccpt())
+		platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+	else if (machine_is_mic256())
+		platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -239,7 +239,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurot
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= vulcan_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/wg302v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/wg302v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ixp4xx/wg302v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ixp4xx/wg302v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,7 @@ MACHINE_START(WG302V2, "Netgear WG302 v2
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= wg302v2_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/proc-fns.h>
 #include <mach/kirkwood.h>
 
@@ -32,17 +33,18 @@ static DEFINE_PER_CPU(struct cpuidle_dev
 
 /* Actual code that puts the SoC in different idle states */
 static int kirkwood_enter_idle(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+			       int index)
 {
 	struct timeval before, after;
 	int idle_time;
 
 	local_irq_disable();
 	do_gettimeofday(&before);
-	if (state == &dev->states[0])
+	if (index == 0)
 		/* Wait for interrupt state */
 		cpu_do_idle();
-	else if (state == &dev->states[1]) {
+	else if (index == 1) {
 		/*
 		 * Following write will put DDR in self refresh.
 		 * Note that we have 256 cycles before DDR puts it
@@ -57,35 +59,40 @@ static int kirkwood_enter_idle(struct cp
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	/* Update last residency */
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int kirkwood_init_cpuidle(void)
 {
 	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&kirkwood_idle_driver);
+	struct cpuidle_driver *driver = &kirkwood_idle_driver;
 
 	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
 	device->state_count = KIRKWOOD_MAX_STATES;
+	driver->state_count = KIRKWOOD_MAX_STATES;
 
 	/* Wait for interrupt state */
-	device->states[0].enter = kirkwood_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = kirkwood_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and DDR self refresh state */
-	device->states[1].enter = kirkwood_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "DDR SR");
-	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+	driver->states[1].enter = kirkwood_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "DDR SR");
+	strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
 
+	cpuidle_register_driver(&kirkwood_idle_driver);
 	if (cpuidle_register_device(device)) {
 		printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
 		return -EIO;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/d2net_v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/d2net_v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/d2net_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/d2net_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,7 +221,7 @@ static void __init d2net_v2_init(void)
 }
 
 MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/db88f6281-bp-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,7 +97,7 @@ subsys_initcall(db88f6281_pci_init);
 
 MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db88f6281_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/dockstar-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/dockstar-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/dockstar-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/dockstar-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@ static void __init dockstar_init(void)
 }
 
 MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dockstar_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/guruplug-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/guruplug-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/guruplug-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/guruplug-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,7 +121,7 @@ static void __init guruplug_init(void)
 
 MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
 	/* Maintainer: Siddarth Gore <gores@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= guruplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =KIRKWOOD_REGS_PHYS_BASE
 	ldr	\rv, =KIRKWOOD_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/irq.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,14 +7,13 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
-#include <asm/gpio.h>
 #include "common.h"
 
 static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/mpp.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/mpp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/mpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/mpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include <plat/mpp.h>
 #include "common.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@ subsys_initcall(mv88f6281gtw_ge_pci_init
 
 MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mv88f6281gtw_ge_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/netspace_v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/netspace_v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/netspace_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/netspace_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,7 +258,7 @@ static void __init netspace_v2_init(void
 
 #ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -269,7 +269,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_INETSPACE_V2
 MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -280,7 +280,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_NETSPACE_MAX_V2
 MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/netxbig_v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/netxbig_v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -399,7 +399,7 @@ static void __init netxbig_v2_init(void)
 
 #ifdef CONFIG_MACH_NET2BIG_V2
 MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -410,7 +410,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_NET5BIG_V2
 MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/openrd-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/openrd-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/openrd-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/openrd-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -214,7 +214,7 @@ subsys_initcall(openrd_pci_init);
 #ifdef CONFIG_MACH_OPENRD_BASE
 MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -226,7 +226,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_CLIENT
 MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -238,7 +238,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_ULTIMATE
 MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@ subsys_initcall(rd88f6192_pci_init);
 
 MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6192_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/rd88f6281-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/rd88f6281-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/rd88f6281-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/rd88f6281-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,7 +115,7 @@ subsys_initcall(rd88f6281_pci_init);
 
 MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6281_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/sheevaplug-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/sheevaplug-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/sheevaplug-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/sheevaplug-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -138,7 +138,7 @@ static void __init sheevaplug_init(void)
 #ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
 	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -149,7 +149,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
 MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/t5325-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/t5325-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/t5325-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/t5325-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,7 +201,7 @@ subsys_initcall(hp_t5325_pci_init);
 
 MACHINE_START(T5325, "HP t5325 Thin Client")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= hp_t5325_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/ts219-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/ts219-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@ subsys_initcall(ts219_pci_init);
 
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts219_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,7 @@ subsys_initcall(ts41x_pci_init);
 
 MACHINE_START(TS41X, "QNAP TS-41x")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts41x_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-acs5k.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-acs5k.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-acs5k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-acs5k.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -34,7 +34,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 
 #include "generic.h"
 
@@ -223,7 +223,7 @@ static void __init acs5k_init(void)
 
 MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
 	/* Maintainer: Simtec Electronics. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= acs5k_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-dsm320.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-dsm320.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-dsm320.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-dsm320.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -29,7 +29,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 
 #include "generic.h"
 
@@ -121,7 +121,7 @@ static void __init dsm320_init(void)
 
 MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
 	/* Maintainer: Simtec Electronics. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= dsm320_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-micrel.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-micrel.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/board-micrel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/board-micrel.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -18,7 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 #include <mach/devices.h>
 
 #include "generic.h"
@@ -53,7 +53,7 @@ static void __init micrel_init(void)
 
 MACHINE_START(KS8695, "KS8695 Centaur Development Board")
 	/* Maintainer: Micrel Semiconductor Inc. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= micrel_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/devices.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <mach/irqs.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-/*
- * arch/arm/mach-ks8695/gpio.c
- *
- * Copyright (C) 2006 Andrew Victor
- * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
- *                     Daniel Silverstone <dsilvers@simtec.co.uk>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/irq.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/gpio.h>
-
-/*
- * Configure a GPIO line for either GPIO function, or its internal
- * function (Interrupt, Timer, etc).
- */
-static void ks8695_gpio_mode(unsigned int pin, short gpio)
-{
-	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
-		return;
-
-	local_irq_save(flags);
-
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-	if (gpio)			/* GPIO: set bit to 0 */
-		x &= ~enable[pin];
-	else				/* Internal function: set bit to 1 */
-		x |= enable[pin];
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
-
-	local_irq_restore(flags);
-}
-
-
-static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	/* set pin as input */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x &= ~IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	/* Set IRQ triggering type */
-	irq_set_irq_type(gpio_irq[pin], type);
-
-	/* enable interrupt mode */
-	ks8695_gpio_mode(pin, 0);
-
-	return 0;
-}
-EXPORT_SYMBOL(ks8695_gpio_interrupt);
-
-
-
-/* .... Generic GPIO interface .............................................. */
-
-/*
- * Configure the GPIO line as an input.
- */
-static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	/* set pin to GPIO mode */
-	ks8695_gpio_mode(pin, 1);
-
-	local_irq_save(flags);
-
-	/* set pin as input */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x &= ~IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-/*
- * Configure the GPIO line as an output, with default state.
- */
-static int ks8695_gpio_direction_output(struct gpio_chip *gc,
-					unsigned int pin, int state)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	/* set pin to GPIO mode */
-	ks8695_gpio_mode(pin, 1);
-
-	local_irq_save(flags);
-
-	/* set line state */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	if (state)
-		x |= IOPD(pin);
-	else
-		x &= ~IOPD(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
-	/* set pin as output */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x |= IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-/*
- * Set the state of an output GPIO line.
- */
-static void ks8695_gpio_set_value(struct gpio_chip *gc,
-				  unsigned int pin, int state)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return;
-
-	local_irq_save(flags);
-
-	/* set output line state */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	if (state)
-		x |= IOPD(pin);
-	else
-		x &= ~IOPD(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
-	local_irq_restore(flags);
-}
-
-
-/*
- * Read the state of a GPIO line.
- */
-static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
-{
-	unsigned long x;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	return (x & IOPD(pin)) != 0;
-}
-
-
-/*
- * Map GPIO line to IRQ number.
- */
-static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
-{
-	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
-		return -EINVAL;
-
-	return gpio_irq[pin];
-}
-
-/*
- * Map IRQ number to GPIO line.
- */
-int irq_to_gpio(unsigned int irq)
-{
-	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
-		return -EINVAL;
-
-	return (irq - KS8695_IRQ_EXTERN0);
-}
-EXPORT_SYMBOL(irq_to_gpio);
-
-/* GPIOLIB interface */
-
-static struct gpio_chip ks8695_gpio_chip = {
-	.label			= "KS8695",
-	.direction_input	= ks8695_gpio_direction_input,
-	.direction_output	= ks8695_gpio_direction_output,
-	.get			= ks8695_gpio_get_value,
-	.set			= ks8695_gpio_set_value,
-	.to_irq			= ks8695_gpio_to_irq,
-	.base			= 0,
-	.ngpio			= 16,
-	.can_sleep		= 0,
-};
-
-/* Register the GPIOs */
-void ks8695_register_gpios(void)
-{
-	if (gpiochip_add(&ks8695_gpio_chip))
-		printk(KERN_ERR "Unable to register core GPIOs\n");
-}
-
-/* .... Debug interface ..................................................... */
-
-#ifdef CONFIG_DEBUG_FS
-
-static int ks8695_gpio_show(struct seq_file *s, void *unused)
-{
-	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
-	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
-	unsigned long mode, ctrl, data;
-	int i;
-
-	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-
-	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
-
-	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
-		seq_printf(s, "%i:\t", i);
-
-		seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
-
-		if (i <= KS8695_GPIO_3) {
-			if (ctrl & enable[i]) {
-				seq_printf(s, "EXT%i ", i);
-
-				switch ((ctrl & intmask[i]) >> (4 * i)) {
-					case IOPC_TM_LOW:
-						seq_printf(s, "(Low)");		break;
-					case IOPC_TM_HIGH:
-						seq_printf(s, "(High)");	break;
-					case IOPC_TM_RISING:
-						seq_printf(s, "(Rising)");	break;
-					case IOPC_TM_FALLING:
-						seq_printf(s, "(Falling)");	break;
-					case IOPC_TM_EDGE:
-						seq_printf(s, "(Edges)");	break;
-				}
-			}
-			else
-				seq_printf(s, "GPIO\t");
-		}
-		else if (i <= KS8695_GPIO_5) {
-			if (ctrl & enable[i])
-				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
-			else
-				seq_printf(s, "GPIO\t");
-		}
-		else
-			seq_printf(s, "GPIO\t");
-
-		seq_printf(s, "\t");
-
-		seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
-	}
-	return 0;
-}
-
-static int ks8695_gpio_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ks8695_gpio_show, NULL);
-}
-
-static const struct file_operations ks8695_gpio_operations = {
-	.open		= ks8695_gpio_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init ks8695_gpio_debugfs_init(void)
-{
-	/* /sys/kernel/debug/ks8695_gpio */
-	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
-	return 0;
-}
-postcore_initcall(ks8695_gpio_debugfs_init);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-uart.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 		ldr	\rp, =KS8695_UART_PA		@ physical base address
 		ldr	\rv, =KS8695_UART_VA		@ virtual base address
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,47 +11,9 @@
 #ifndef __ASM_ARCH_GPIO_H_
 #define __ASM_ARCH_GPIO_H_
 
-#include <linux/kernel.h>
-
-#define KS8695_GPIO_0		0
-#define KS8695_GPIO_1		1
-#define KS8695_GPIO_2		2
-#define KS8695_GPIO_3		3
-#define KS8695_GPIO_4		4
-#define KS8695_GPIO_5		5
-#define KS8695_GPIO_6		6
-#define KS8695_GPIO_7		7
-#define KS8695_GPIO_8		8
-#define KS8695_GPIO_9		9
-#define KS8695_GPIO_10		10
-#define KS8695_GPIO_11		11
-#define KS8695_GPIO_12		12
-#define KS8695_GPIO_13		13
-#define KS8695_GPIO_14		14
-#define KS8695_GPIO_15		15
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
-
 /*
  * Map IRQ number to GPIO line.
  */
 extern int irq_to_gpio(unsigned int irq);
 
-#include <asm-generic/gpio.h>
-
-/* If it turns out that we need to optimise GPIO access for the
- * Micrel's GPIOs, then these can be changed to check their argument
- * directly as static inlines. However for now it's probably not
- * worthwhile.
- */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_to_irq __gpio_to_irq
-
-/* Register the GPIOs */
-extern void ks8695_register_gpios(void);
-
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * 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 __MACH_KS8659_GPIO_H
+#define __MACH_KS8659_GPIO_H
+
+#include <linux/kernel.h>
+
+#define KS8695_GPIO_0		0
+#define KS8695_GPIO_1		1
+#define KS8695_GPIO_2		2
+#define KS8695_GPIO_3		3
+#define KS8695_GPIO_4		4
+#define KS8695_GPIO_5		5
+#define KS8695_GPIO_6		6
+#define KS8695_GPIO_7		7
+#define KS8695_GPIO_8		8
+#define KS8695_GPIO_9		9
+#define KS8695_GPIO_10		10
+#define KS8695_GPIO_11		11
+#define KS8695_GPIO_12		12
+#define KS8695_GPIO_13		13
+#define KS8695_GPIO_14		14
+#define KS8695_GPIO_15		15
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/* Register the GPIOs */
+extern void ks8695_register_gpios(void);
+
+#endif /* __MACH_KS8659_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/leds.c linux-libre-3.2-gnu1/arch/arm/mach-ks8695/leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,14 +7,14 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/leds.h>
 #include <mach/devices.h>
-#include <mach/gpio.h>
 
 
 static inline void ks8695_led_on(unsigned int led)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/Makefile linux-libre-3.2-gnu1/arch/arm/mach-ks8695/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 # Makefile for KS8695 architecture support
 #
 
-obj-y				:= cpu.o irq.o time.o gpio.o devices.o
+obj-y				:= cpu.o irq.o time.o devices.o
 obj-m				:=
 obj-n				:=
 obj-				:=
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ks8695/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ks8695/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ks8695/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ks8695/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,6 @@
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
 #   INITRD_PHYS must be in RAM
 
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-l7200/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-l7200/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-l7200/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-l7200/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 		.equ	io_virt, IO_BASE
 		.equ	io_phys, IO_START
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00044000	@ UART1
 @		mov	\rp, #0x00045000	@ UART2
 		add	\rv, \rp, #io_virt	@ virtual address
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/gpiolib.c linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/gpiolib.c
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,446 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/gpiolib.c
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include "common.h"
-
-#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
-#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
-#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
-#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
-#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
-#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
-#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
-#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
-#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
-#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
-#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
-#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
-#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
-#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
-#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
-#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
-#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
-#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
-#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
-#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
-#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
-#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
-#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
-#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
-#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
-#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
-#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
-
-#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
-#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
-#define GPO3_PIN_TO_BIT(x)			(1 << (x))
-#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
-#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
-#define GPIO3_PIN_IN_SEL(x, y)			((x) >> GPIO3_PIN_IN_SHIFT(y))
-#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
-#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
-
-struct gpio_regs {
-	void __iomem *inp_state;
-	void __iomem *outp_set;
-	void __iomem *outp_clr;
-	void __iomem *dir_set;
-	void __iomem *dir_clr;
-};
-
-/*
- * GPIO names
- */
-static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
-	"p0.0", "p0.1", "p0.2", "p0.3",
-	"p0.4", "p0.5", "p0.6", "p0.7"
-};
-
-static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
-	"p1.0", "p1.1", "p1.2", "p1.3",
-	"p1.4", "p1.5", "p1.6", "p1.7",
-	"p1.8", "p1.9", "p1.10", "p1.11",
-	"p1.12", "p1.13", "p1.14", "p1.15",
-	"p1.16", "p1.17", "p1.18", "p1.19",
-	"p1.20", "p1.21", "p1.22", "p1.23",
-};
-
-static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
-	"p2.0", "p2.1", "p2.2", "p2.3",
-	"p2.4", "p2.5", "p2.6", "p2.7",
-	"p2.8", "p2.9", "p2.10", "p2.11",
-	"p2.12"
-};
-
-static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
-	"gpi000", "gpio01", "gpio02", "gpio03",
-	"gpio04", "gpio05"
-};
-
-static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
-	"gpi00", "gpi01", "gpi02", "gpi03",
-	"gpi04", "gpi05", "gpi06", "gpi07",
-	"gpi08", "gpi09",  NULL,    NULL,
-	 NULL,    NULL,    NULL,   "gpi15",
-	"gpi16", "gpi17", "gpi18", "gpi19",
-	"gpi20", "gpi21", "gpi22", "gpi23",
-	"gpi24", "gpi25", "gpi26", "gpi27"
-};
-
-static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
-	"gpo00", "gpo01", "gpo02", "gpo03",
-	"gpo04", "gpo05", "gpo06", "gpo07",
-	"gpo08", "gpo09", "gpo10", "gpo11",
-	"gpo12", "gpo13", "gpo14", "gpo15",
-	"gpo16", "gpo17", "gpo18", "gpo19",
-	"gpo20", "gpo21", "gpo22", "gpo23"
-};
-
-static struct gpio_regs gpio_grp_regs_p0 = {
-	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p1 = {
-	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p2 = {
-	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p3 = {
-	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
-};
-
-struct lpc32xx_gpio_chip {
-	struct gpio_chip	chip;
-	struct gpio_regs	*gpio_grp;
-};
-
-static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
-	struct gpio_chip *gpc)
-{
-	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
-}
-
-static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int input)
-{
-	if (input)
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->dir_clr);
-	else
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->dir_set);
-}
-
-static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int input)
-{
-	u32 u = GPIO3_PIN_TO_BIT(pin);
-
-	if (input)
-		__raw_writel(u, group->gpio_grp->dir_clr);
-	else
-		__raw_writel(u, group->gpio_grp->dir_set);
-}
-
-static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	if (high)
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->outp_set);
-	else
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->outp_clr);
-}
-
-static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	u32 u = GPIO3_PIN_TO_BIT(pin);
-
-	if (high)
-		__raw_writel(u, group->gpio_grp->outp_set);
-	else
-		__raw_writel(u, group->gpio_grp->outp_clr);
-}
-
-static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	if (high)
-		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
-	else
-		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
-}
-
-static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
-		pin);
-}
-
-static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	int state = __raw_readl(group->gpio_grp->inp_state);
-
-	/*
-	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
-	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
-	 */
-	return GPIO3_PIN_IN_SEL(state, pin);
-}
-
-static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
-}
-
-/*
- * GENERIC_GPIO primitives.
- */
-static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
-	unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p012(group, pin, 1);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
-	unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p3(group, pin, 1);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
-	unsigned pin)
-{
-	return 0;
-}
-
-static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpio_state_p012(group, pin);
-}
-
-static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpio_state_p3(group, pin);
-}
-
-static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpi_state_p3(group, pin);
-}
-
-static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p012(group, pin, 0);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p3(group, pin, 0);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	return 0;
-}
-
-static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_level_p012(group, pin, value);
-}
-
-static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_level_p3(group, pin, value);
-}
-
-static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpo_level_p3(group, pin, value);
-}
-
-static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
-{
-	if (pin < chip->ngpio)
-		return 0;
-
-	return -EINVAL;
-}
-
-static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
-	{
-		.chip = {
-			.label			= "gpio_p0",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P0_GRP,
-			.ngpio			= LPC32XX_GPIO_P0_MAX,
-			.names			= gpio_p0_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p0,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p1",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P1_GRP,
-			.ngpio			= LPC32XX_GPIO_P1_MAX,
-			.names			= gpio_p1_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p1,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p2",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P2_GRP,
-			.ngpio			= LPC32XX_GPIO_P2_MAX,
-			.names			= gpio_p2_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p2,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p3",
-			.direction_input	= lpc32xx_gpio_dir_input_p3,
-			.get			= lpc32xx_gpio_get_value_p3,
-			.direction_output	= lpc32xx_gpio_dir_output_p3,
-			.set			= lpc32xx_gpio_set_value_p3,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P3_GRP,
-			.ngpio			= LPC32XX_GPIO_P3_MAX,
-			.names			= gpio_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-	{
-		.chip = {
-			.label			= "gpi_p3",
-			.direction_input	= lpc32xx_gpio_dir_in_always,
-			.get			= lpc32xx_gpi_get_value,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPI_P3_GRP,
-			.ngpio			= LPC32XX_GPI_P3_MAX,
-			.names			= gpi_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-	{
-		.chip = {
-			.label			= "gpo_p3",
-			.direction_output	= lpc32xx_gpio_dir_out_always,
-			.set			= lpc32xx_gpo_set_value,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPO_P3_GRP,
-			.ngpio			= LPC32XX_GPO_P3_MAX,
-			.names			= gpo_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-};
-
-void __init lpc32xx_gpio_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
-		gpiochip_add(&lpc32xx_gpiochip[i].chip);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
  * Debug output is hardcoded to standard UART 5
 */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldreq	\rp, =0x40090000
 	ldrne	\rv, =0xF4090000
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,74 +1 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/gpio.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-/*
- * Note!
- * Muxed GP pins need to be setup to the GP state in the board level
- * code prior to using this driver.
- * GPI pins : 28xP3 group
- * GPO pins : 24xP3 group
- * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
- */
-
-#define LPC32XX_GPIO_P0_MAX 8
-#define LPC32XX_GPIO_P1_MAX 24
-#define LPC32XX_GPIO_P2_MAX 13
-#define LPC32XX_GPIO_P3_MAX 6
-#define LPC32XX_GPI_P3_MAX 28
-#define LPC32XX_GPO_P3_MAX 24
-
-#define LPC32XX_GPIO_P0_GRP 0
-#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
-#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
-#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
-#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
-#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
-
-/*
- * A specific GPIO can be selected with this macro
- * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
- * See the LPC32x0 User's guide for GPIO group numbers
- */
-#define LPC32XX_GPIO(x, y) ((x) + (y))
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
-#endif
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_GPIO_LPC32XX_H
+#define __MACH_GPIO_LPC32XX_H
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+#endif /* __MACH_GPIO_LPC32XX_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/memory.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset of bank 0
- */
-#define PLAT_PHYS_OFFSET	UL(0x80000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/Makefile linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,6 @@
 #
 
 obj-y	:= timer.o irq.o common.o serial.o clock.o
-obj-y	+= gpiolib.o pm.o suspend.o
+obj-y	+= pm.o suspend.o
 obj-y	+= phy3250.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x80008000
+   zreladdr-y	+= 0x80008000
 params_phys-y	:= 0x80000100
 initrd_phys-y	:= 0x82000000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/phy3250.c linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/phy3250.c
--- linux-libre-3.1-gnu1/arch/arm/mach-lpc32xx/phy3250.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-lpc32xx/phy3250.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
+#include <mach/gpio-lpc32xx.h>
 #include "common.h"
 
 /*
@@ -382,7 +383,7 @@ arch_initcall(lpc32xx_display_uid);
 
 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
 	/* Maintainer: Kevin Wells, NXP Semiconductors */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= lpc32xx_map_io,
 	.init_irq	= lpc32xx_init_irq,
 	.timer		= &lpc32xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/aspenite.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/aspenite.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/aspenite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/aspenite.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -17,13 +17,13 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
-#include <mach/gpio.h>
 #include <video/pxa168fb.h>
 #include <linux/input.h>
 #include <plat/pxa27x_keypad.h>
@@ -160,15 +160,16 @@ static struct mtd_partition aspenite_nan
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
 
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= aspenite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(aspenite_nand_partitions),
+	.num_cs = 1,
+	.parts[0]	= aspenite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };
 
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/brownstone.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/brownstone.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/brownstone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/brownstone.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
@@ -186,6 +185,15 @@ static struct sdhci_pxa_platdata mmp2_sd
 		| PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
 };
 
+static struct sram_platdata mmp2_asram_platdata = {
+	.pool_name	= "asram",
+	.granularity	= SRAM_GRANULARITY,
+};
+
+static struct sram_platdata mmp2_isram_platdata = {
+	.pool_name	= "isram",
+	.granularity	= SRAM_GRANULARITY,
+};
 
 static void __init brownstone_init(void)
 {
@@ -197,6 +205,8 @@ static void __init brownstone_init(void)
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
 	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
 	mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */
+	mmp2_add_asram(&mmp2_asram_platdata);
+	mmp2_add_isram(&mmp2_isram_platdata);
 
 	/* enable 5v regulator */
 	platform_device_register(&brownstone_v_5vp_device);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/clock.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@ extern struct clkops apmu_clk_ops;
 
 #define APBC_CLK(_name, _reg, _fnclksel, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= &apbc_clk_ops,		\
@@ -38,7 +38,7 @@ struct clk clk_##_name = {					\
 
 #define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops)	\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
@@ -46,7 +46,7 @@ struct clk clk_##_name = {					\
 
 #define APMU_CLK(_name, _reg, _eval, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= &apmu_clk_ops,		\
@@ -54,7 +54,7 @@ struct clk clk_##_name = {					\
 
 #define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops)		\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/common.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,12 +27,12 @@ EXPORT_SYMBOL(mmp_chip_id);
 static struct map_desc standard_io_desc[] __initdata = {
 	{
 		.pfn		= __phys_to_pfn(APB_PHYS_BASE),
-		.virtual	= APB_VIRT_BASE,
+		.virtual	= (unsigned long)APB_VIRT_BASE,
 		.length		= APB_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
 		.pfn		= __phys_to_pfn(AXI_PHYS_BASE),
-		.virtual	= AXI_VIRT_BASE,
+		.virtual	= (unsigned long)AXI_VIRT_BASE,
 		.length		= AXI_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	},
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/gplugd.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/gplugd.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/gplugd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/gplugd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,11 +9,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
 
@@ -182,13 +182,13 @@ static void __init gplugd_init(void)
 
 	/* on-chip devices */
 	pxa168_add_uart(3);
-	pxa168_add_ssp(0);
+	pxa168_add_ssp(1);
 	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
 
 	pxa168_add_eth(&gplugd_eth_platform_data);
 }
 
-MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
 	.map_io		= mmp_map_io,
 	.nr_irqs	= IRQ_BOARD_START,
 	.init_irq       = pxa168_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/addr-map.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/addr-map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/addr-map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/addr-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,12 @@
 #ifndef __ASM_MACH_ADDR_MAP_H
 #define __ASM_MACH_ADDR_MAP_H
 
+#ifndef __ASSEMBLER__
+#define IOMEM(x)	((void __iomem *)(x))
+#else
+#define IOMEM(x)	(x)
+#endif
+
 /* APB - Application Subsystem Peripheral Bus
  *
  * NOTE: the DMA controller registers are actually on the AXI fabric #1
@@ -18,11 +24,11 @@
  * peripherals on APB, let's count it into the ABP mapping area.
  */
 #define APB_PHYS_BASE		0xd4000000
-#define APB_VIRT_BASE		0xfe000000
+#define APB_VIRT_BASE		IOMEM(0xfe000000)
 #define APB_PHYS_SIZE		0x00200000
 
 #define AXI_PHYS_BASE		0xd4200000
-#define AXI_VIRT_BASE		0xfe200000
+#define AXI_VIRT_BASE		IOMEM(0xfe200000)
 #define AXI_PHYS_SIZE		0x00200000
 
 /* Static Memory Controller - Chip Select 0 and 1 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 
 #include <mach/addr-map.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =APB_PHYS_BASE		@ physical
 		ldr	\rv, =APB_VIRT_BASE		@ virtual
 		orr	\rp, \rp, #0x00017000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,36 +1,13 @@
 #ifndef __ASM_MACH_GPIO_H
 #define __ASM_MACH_GPIO_H
 
-#include <mach/addr-map.h>
-#include <mach/irqs.h>
 #include <asm-generic/gpio.h>
 
-#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
-
-#define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	(IRQ_GPIO_START + (gpio))
 #define irq_to_gpio(irq)	((irq) - IRQ_GPIO_START)
 
-
 #define __gpio_is_inverted(gpio)	(0)
 #define __gpio_is_occupied(gpio)	(0)
 
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
 #include <plat/gpio.h>
 #endif /* __ASM_MACH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/gpio-pxa.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/gpio-pxa.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_GPIO_PXA_H
+#define __ASM_MACH_GPIO_PXA_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+#define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio-pxa.h>
+
+#endif /* __ASM_MACH_GPIO_PXA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_MACH_MEMORY_H
-#define __ASM_MACH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif /* __ASM_MACH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@ extern void mmp2_clear_pmic_int(void);
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
+#include <mach/sram.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
@@ -28,6 +29,8 @@ extern struct pxa_device_desc mmp2_devic
 extern struct pxa_device_desc mmp2_device_sdh1;
 extern struct pxa_device_desc mmp2_device_sdh2;
 extern struct pxa_device_desc mmp2_device_sdh3;
+extern struct pxa_device_desc mmp2_device_asram;
+extern struct pxa_device_desc mmp2_device_isram;
 
 static inline int mmp2_add_uart(int id)
 {
@@ -85,5 +88,15 @@ static inline int mmp2_add_sdhost(int id
 	return pxa_register_device(d, data, sizeof(*data));
 }
 
+static inline int mmp2_add_asram(struct sram_platdata *data)
+{
+	return pxa_register_device(&mmp2_device_asram, data, sizeof(*data));
+}
+
+static inline int mmp2_add_isram(struct sram_platdata *data)
+{
+	return pxa_register_device(&mmp2_device_isram, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_MMP2_H */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/pxa168.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/pxa168.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/pxa168.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/pxa168.h	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,13 @@ extern struct pxa_device_desc pxa168_dev
 extern struct pxa_device_desc pxa168_device_keypad;
 extern struct pxa_device_desc pxa168_device_eth;
 
+struct pxa168_usb_pdata {
+	/* If NULL, default phy init routine for PXA168 would be called */
+	int (*phy_init)(void __iomem *usb_phy_reg_base);
+};
+/* pdata can be NULL */
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata);
+
 static inline int pxa168_add_uart(int id)
 {
 	struct pxa_device_desc *d = NULL;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/sram.h linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/sram.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/include/mach/sram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/include/mach/sram.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ *  linux/arch/arm/mach-mmp/include/mach/sram.h
+ *
+ *  SRAM Memory Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_ARCH_SRAM_H
+#define __ASM_ARCH_SRAM_H
+
+#include <linux/genalloc.h>
+
+/* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
+#define SRAM_GRANULARITY	512
+
+enum sram_type {
+	MMP_SRAM_UNDEFINED = 0,
+	MMP_ASRAM,
+	MMP_ISRAM,
+};
+
+struct sram_platdata {
+	char *pool_name;
+	int granularity;
+};
+
+extern struct gen_pool *sram_get_gpool(char *pool_name);
+
+#endif /* __ASM_ARCH_SRAM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/jasper.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/jasper.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/jasper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/jasper.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/mfd/max8925.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-mmp/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ config MACH_TETON_BGA
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Teton BGA Development Board.
 
-config MACH_SHEEVAD
+config MACH_GPLUGD
 	bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
 	select CPU_PXA168
 	help
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/Makefile linux-libre-3.2-gnu1/arch/arm/mach-mmp/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@ obj-y				+= common.o clock.o devices.o t
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
-obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o
+obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o sram.o
 
 # board support
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
@@ -19,4 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE)	+= brownst
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
-obj-$(CONFIG_MACH_SHEEVAD)	+= gplugd.o
+obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-mmp/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1 +1 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/mmp2.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/mmp2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/mmp2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/mmp2.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -25,7 +24,7 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/devices.h>
 #include <mach/mmp2.h>
 
@@ -87,7 +86,8 @@ static struct mfp_addr_map mmp2_addr_map
 
 void mmp2_clear_pmic_int(void)
 {
-	unsigned long mfpr_pmic, data;
+	void __iomem *mfpr_pmic;
+	unsigned long data;
 
 	mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
 	data = __raw_readl(mfpr_pmic);
@@ -226,4 +226,7 @@ MMP2_DEVICE(sdh0, "sdhci-pxav3", 0, MMC,
 MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
 MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
 MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
+MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000);
+/* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */
+MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/pxa168.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/pxa168.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/pxa168.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/pxa168.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,10 +20,13 @@
 #include <mach/regs-apbc.h>
 #include <mach/regs-apmu.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/devices.h>
 #include <mach/mfp.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <mach/pxa168.h>
 
 #include "common.h"
 #include "clock.h"
@@ -83,6 +85,7 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 3
 static APMU_CLK(nand, NAND, 0x19b, 156000000);
 static APMU_CLK(lcd, LCD, 0x7f, 312000000);
 static APMU_CLK(eth, ETH, 0x09, 0);
+static APMU_CLK(usb, USB, 0x12, 0);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
@@ -104,6 +107,7 @@ static struct clk_lookup pxa168_clkregs[
 	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
 	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
 	INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
+	INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"),
 };
 
 static int __init pxa168_init(void)
@@ -169,3 +173,44 @@ PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP
 PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
 PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
 PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
+
+struct resource pxa168_usb_host_resources[] = {
+	/* USB Host conroller register base */
+	[0] = {
+		.start	= 0xd4209000,
+		.end	= 0xd4209000 + 0x200,
+		.flags	= IORESOURCE_MEM,
+		.name	= "pxa168-usb-host",
+	},
+	/* USB PHY register base */
+	[1] = {
+		.start	= 0xd4206000,
+		.end	= 0xd4206000 + 0xff,
+		.flags	= IORESOURCE_MEM,
+		.name	= "pxa168-usb-phy",
+	},
+	[2] = {
+		.start	= IRQ_PXA168_USB2,
+		.end	= IRQ_PXA168_USB2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
+struct platform_device pxa168_device_usb_host = {
+	.name = "pxa168-ehci",
+	.id   = -1,
+	.dev  = {
+		.dma_mask = &pxa168_usb_host_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+
+	.num_resources = ARRAY_SIZE(pxa168_usb_host_resources),
+	.resource      = pxa168_usb_host_resources,
+};
+
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata)
+{
+	pxa168_device_usb_host.dev.platform_data = pdata;
+	return platform_device_register(&pxa168_device_usb_host);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/pxa910.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/pxa910.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/pxa910.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/pxa910.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -20,7 +19,7 @@
 #include <mach/regs-apmu.h>
 #include <mach/cputype.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
 #include <mach/devices.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/sram.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/sram.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/sram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,168 @@
+/*
+ *  linux/arch/arm/mach-mmp/sram.c
+ *
+ *  based on mach-davinci/sram.c - DaVinci simple SRAM allocator
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *  All Rights Reserved
+ *
+ *  Add for mmp sram support - Leo Yan <leoy@marvell.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
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+#include <mach/sram.h>
+
+struct sram_bank_info {
+	char *pool_name;
+	struct gen_pool *gpool;
+	int granularity;
+
+	phys_addr_t sram_phys;
+	void __iomem *sram_virt;
+	u32 sram_size;
+
+	struct list_head node;
+};
+
+static DEFINE_MUTEX(sram_lock);
+static LIST_HEAD(sram_bank_list);
+
+struct gen_pool *sram_get_gpool(char *pool_name)
+{
+	struct sram_bank_info *info = NULL;
+
+	if (!pool_name)
+		return NULL;
+
+	mutex_lock(&sram_lock);
+
+	list_for_each_entry(info, &sram_bank_list, node)
+		if (!strcmp(pool_name, info->pool_name))
+			break;
+
+	mutex_unlock(&sram_lock);
+
+	if (&info->node == &sram_bank_list)
+		return NULL;
+
+	return info->gpool;
+}
+EXPORT_SYMBOL(sram_get_gpool);
+
+static int __devinit sram_probe(struct platform_device *pdev)
+{
+	struct sram_platdata *pdata = pdev->dev.platform_data;
+	struct sram_bank_info *info;
+	struct resource *res;
+	int ret = 0;
+
+	if (!pdata && !pdata->pool_name)
+		return -ENODEV;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!resource_size(res))
+		return 0;
+
+	info->sram_phys   = (phys_addr_t)res->start;
+	info->sram_size   = resource_size(res);
+	info->sram_virt   = ioremap(info->sram_phys, info->sram_size);
+	info->pool_name	  = kstrdup(pdata->pool_name, GFP_KERNEL);
+	info->granularity = pdata->granularity;
+
+	info->gpool = gen_pool_create(ilog2(info->granularity), -1);
+	if (!info->gpool) {
+		dev_err(&pdev->dev, "create pool failed\n");
+		ret = -ENOMEM;
+		goto create_pool_err;
+	}
+
+	ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt,
+				info->sram_phys, info->sram_size, -1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "add new chunk failed\n");
+		ret = -ENOMEM;
+		goto add_chunk_err;
+	}
+
+	mutex_lock(&sram_lock);
+	list_add(&info->node, &sram_bank_list);
+	mutex_unlock(&sram_lock);
+
+	platform_set_drvdata(pdev, info);
+
+	dev_info(&pdev->dev, "initialized\n");
+	return 0;
+
+add_chunk_err:
+	gen_pool_destroy(info->gpool);
+create_pool_err:
+	iounmap(info->sram_virt);
+	kfree(info->pool_name);
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit sram_remove(struct platform_device *pdev)
+{
+	struct sram_bank_info *info;
+
+	info = platform_get_drvdata(pdev);
+	if (info == NULL)
+		return -ENODEV;
+
+	mutex_lock(&sram_lock);
+	list_del(&info->node);
+	mutex_unlock(&sram_lock);
+
+	gen_pool_destroy(info->gpool);
+	iounmap(info->sram_virt);
+	kfree(info->pool_name);
+	kfree(info);
+	return 0;
+}
+
+static const struct platform_device_id sram_id_table[] = {
+	{ "asram", MMP_ASRAM },
+	{ "isram", MMP_ISRAM },
+	{ }
+};
+
+static struct platform_driver sram_driver = {
+	.probe		= sram_probe,
+	.remove		= sram_remove,
+	.driver		= {
+		.name	= "mmp-sram",
+	},
+	.id_table	= sram_id_table,
+};
+
+static int __init sram_init(void)
+{
+	return platform_driver_register(&sram_driver);
+}
+core_initcall(sram_init);
+
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/tavorevb.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/tavorevb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/tavorevb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/tavorevb.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,18 +7,18 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/smc91x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa910.h>
 #include <mach/pxa910.h>
-#include <mach/gpio.h>
 
 #include "common.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mmp/ttc_dkb.c linux-libre-3.2-gnu1/arch/arm/mach-mmp/ttc_dkb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mmp/ttc_dkb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mmp/ttc_dkb.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ static struct mtd_partition ttc_dkb_onen
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-halibut.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-halibut.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-halibut.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-halibut.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,8 +78,8 @@ static void __init halibut_init(void)
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init halibut_fixup(struct machine_desc *desc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init halibut_fixup(struct tag *tags, char **cmdline,
+				 struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@ static void __init halibut_map_io(void)
 }
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.fixup		= halibut_fixup,
 	.map_io		= halibut_map_io,
 	.init_irq	= halibut_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-mahimahi.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-mahimahi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-mahimahi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-mahimahi.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,8 +53,8 @@ static void __init mahimahi_init(void)
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init mahimahi_fixup(struct machine_desc *desc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init mahimahi_fixup(struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -74,7 +74,7 @@ static void __init mahimahi_map_io(void)
 extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
-	.boot_params	= 0x20000100,
+	.atag_offset	= 0x100,
 	.fixup		= mahimahi_fixup,
 	.map_io		= mahimahi_map_io,
 	.init_irq	= msm_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm7x27.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm7x27.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm7x27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm7x27.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -34,7 +34,6 @@
 
 #include <mach/vreg.h>
 #include <mach/mpp.h>
-#include <mach/gpio.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
@@ -130,7 +129,7 @@ static void __init msm7x2x_map_io(void)
 }
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -138,7 +137,7 @@ MACHINE_START(MSM7X27_SURF, "QCT MSM7x27
 MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -146,7 +145,7 @@ MACHINE_START(MSM7X27_FFA, "QCT MSM7x27
 MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -154,7 +153,7 @@ MACHINE_START(MSM7X25_SURF, "QCT MSM7x25
 MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm7x30.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm7x30.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm7x30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm7x30.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -24,13 +24,13 @@
 #include <linux/smsc911x.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/clkdev.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/memory.h>
 #include <asm/setup.h>
 
-#include <mach/gpio.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
@@ -42,6 +42,21 @@
 
 extern struct sys_timer msm_timer;
 
+static void __init msm7x30_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
+			tag->u.mem.start = 0;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm7x30_reserve(void)
+{
+	memblock_remove(0x0, SZ_2M);
+}
+
 static int hsusb_phy_init_seq[] = {
 	0x30, 0x32,	/* Enable and set Pre-Emphasis Depth to 20% */
 	0x02, 0x36,	/* Disable CDR Auto Reset feature */
@@ -106,7 +121,9 @@ static void __init msm7x30_map_io(void)
 }
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -114,7 +131,9 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -122,7 +141,9 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm8960.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm8960.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm8960.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm8960.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,16 +20,34 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/clkdev.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
+#include <asm/setup.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
 #include "devices.h"
 
+static void __init msm8960_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM &&
+				tag->u.mem.start == 0x40200000) {
+			tag->u.mem.start = 0x40000000;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm8960_reserve(void)
+{
+	memblock_remove(0x40000000, SZ_2M);
+}
+
 static void __init msm8960_map_io(void)
 {
 	msm_map_msm8960_io();
@@ -76,6 +94,8 @@ static void __init msm8960_rumi3_init(vo
 }
 
 MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+	.fixup = msm8960_fixup,
+	.reserve = msm8960_reserve,
 	.map_io = msm8960_map_io,
 	.init_irq = msm8960_init_irq,
 	.timer = &msm_timer,
@@ -83,6 +103,8 @@ MACHINE_START(MSM8960_SIM, "QCT MSM8960
 MACHINE_END
 
 MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+	.fixup = msm8960_fixup,
+	.reserve = msm8960_reserve,
 	.map_io = msm8960_map_io,
 	.init_irq = msm8960_init_irq,
 	.timer = &msm_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm8x60.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm8x60.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-msm8x60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-msm8x60.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -8,26 +8,41 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
  */
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
+#include <asm/setup.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
+static void __init msm8x60_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM &&
+				tag->u.mem.start == 0x40200000) {
+			tag->u.mem.start = 0x40000000;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm8x60_reserve(void)
+{
+	memblock_remove(0x40000000, SZ_2M);
+}
 
 static void __init msm8x60_map_io(void)
 {
@@ -36,8 +51,6 @@ static void __init msm8x60_map_io(void)
 
 static void __init msm8x60_init_irq(void)
 {
-	unsigned int i;
-
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 		 (void *)MSM_QGIC_CPU_BASE);
 
@@ -49,22 +62,50 @@ static void __init msm8x60_init_irq(void
 	 */
 	if (!machine_is_msm8x60_sim())
 		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
-	/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
-	 * as they are configured as level, which does not play nice with
-	 * handle_percpu_irq.
-	 */
-	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
-		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-			irq_set_handler(i, handle_percpu_irq);
-	}
 }
 
 static void __init msm8x60_init(void)
 {
 }
 
+#ifdef CONFIG_OF
+static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
+	{}
+};
+
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+	{ .compatible = "qcom,msm-8660-qgic", },
+	{}
+};
+
+static void __init msm8x60_dt_init(void)
+{
+	struct device_node *node;
+
+	node = of_find_matching_node_by_address(NULL, msm_dt_gic_match,
+			MSM8X60_QGIC_DIST_PHYS);
+	if (node)
+		irq_domain_add_simple(node, GIC_SPI_START);
+
+	if (of_machine_is_compatible("qcom,msm8660-surf")) {
+		printk(KERN_INFO "Init surf UART registers\n");
+		msm8x60_init_uart12dm();
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			msm_auxdata_lookup, NULL);
+}
+
+static const char *msm8x60_fluid_match[] __initdata = {
+	"qcom,msm8660-fluid",
+	"qcom,msm8660-surf",
+	NULL
+};
+#endif /* CONFIG_OF */
+
 MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -72,6 +113,8 @@ MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X6
 MACHINE_END
 
 MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -79,6 +122,8 @@ MACHINE_START(MSM8X60_SURF, "QCT MSM8X60
 MACHINE_END
 
 MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -86,8 +131,21 @@ MACHINE_START(MSM8X60_SIM, "QCT MSM8X60
 MACHINE_END
 
 MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
 	.timer = &msm_timer,
 MACHINE_END
+
+#ifdef CONFIG_OF
+/* TODO: General device tree support for all MSM. */
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_dt_init,
+	.timer = &msm_timer,
+	.dt_compat = msm8x60_fluid_match,
+MACHINE_END
+#endif /* CONFIG_OF */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-qsd8x50.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-qsd8x50.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-qsd8x50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-qsd8x50.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -32,7 +32,6 @@
 #include <mach/board.h>
 #include <mach/irqs.h>
 #include <mach/sirc.h>
-#include <mach/gpio.h>
 #include <mach/vreg.h>
 #include <mach/mmc.h>
 
@@ -193,7 +192,7 @@ static void __init qsd8x50_init(void)
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
@@ -201,7 +200,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-sapphire.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-sapphire.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-sapphire.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-sapphire.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -22,7 +22,6 @@
 
 #include <linux/delay.h>
 
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -77,8 +76,8 @@ static struct map_desc sapphire_io_desc[
 	}
 };
 
-static void __init sapphire_fixup(struct machine_desc *desc, struct tag *tags,
-				  char **cmdline, struct meminfo *mi)
+static void __init sapphire_fixup(struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
 {
 	int smi_sz = parse_tag_smi((const struct tag *)tags);
 
@@ -105,7 +104,7 @@ static void __init sapphire_map_io(void)
 
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-	.boot_params    = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset    = 0x100,
 	.fixup          = sapphire_fixup,
 	.map_io         = sapphire_map_io,
 	.init_irq       = sapphire_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,8 +48,8 @@ static void __init trout_init_irq(void)
 	msm_init_irq();
 }
 
-static void __init trout_fixup(struct machine_desc *desc, struct tag *tags,
-				char **cmdline, struct meminfo *mi)
+static void __init trout_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	mi->nr_banks = 1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@ static void __init trout_map_io(void)
 }
 
 MACHINE_START(TROUT, "HTC Dream")
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.fixup		= trout_fixup,
 	.map_io		= trout_map_io,
 	.init_irq	= trout_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout-mmc.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout-mmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/board-trout-mmc.c
 ** Author: Brian Swetland <swetland@google.com>
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -11,7 +11,6 @@
 #include <linux/err.h>
 #include <linux/debugfs.h>
 
-#include <asm/gpio.h>
 #include <asm/io.h>
 
 #include <mach/vreg.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout-panel.c linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout-panel.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/board-trout-panel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/board-trout-panel.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/board-trout-mddi.c
 ** Author: Brian Swetland <swetland@google.com>
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -11,7 +11,6 @@
 #include <linux/err.h>
 
 #include <asm/io.h>
-#include <asm/gpio.h>
 #include <asm/mach-types.h>
 
 #include <mach/msm_fb.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/clock.c linux-libre-3.2-gnu1/arch/arm/mach-msm/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/string.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-iommu.c linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-iommu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
+#include <linux/module.h>
 #include <mach/irqs.h>
 #include <mach/iommu.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-msm7x00.c linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-msm7x00.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-msm7x00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-msm7x00.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,12 +176,6 @@ static struct resource resources_sdc1[]
 		.name	= "cmd_irq",
 	},
 	{
-		.start	= INT_SDC1_1,
-		.end	= INT_SDC1_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
-	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
 	},
@@ -204,12 +198,6 @@ static struct resource resources_sdc2[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC2_1,
-		.end	= INT_SDC2_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
@@ -233,12 +221,6 @@ static struct resource resources_sdc3[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC3_1,
-		.end	= INT_SDC3_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
@@ -262,12 +244,6 @@ static struct resource resources_sdc4[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC4_1,
-		.end	= INT_SDC4_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-qsd8x50.c linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-qsd8x50.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/devices-qsd8x50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/devices-qsd8x50.c	2012-01-04 18:55:44.000000000 -0500
@@ -140,12 +140,6 @@ static struct resource resources_sdc1[]
 		.name	= "cmd_irq",
 	},
 	{
-		.start	= INT_SDC1_1,
-		.end	= INT_SDC1_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
-	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
 	},
@@ -168,12 +162,6 @@ static struct resource resources_sdc2[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC2_1,
-		.end	= INT_SDC2_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
@@ -197,12 +185,6 @@ static struct resource resources_sdc3[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC3_1,
-		.end	= INT_SDC3_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
@@ -226,12 +208,6 @@ static struct resource resources_sdc4[]
 		.flags	= IORESOURCE_IRQ,
 		.name	= "cmd_irq",
 	},
-		{
-		.start	= INT_SDC4_1,
-		.end	= INT_SDC4_1,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "pio_irq",
-	},
 	{
 		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
 		.name	= "status_irq"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-msm/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@ static inline void platform_do_lowpower(
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #include <mach/msm_iomap.h>
 
 #if defined(CONFIG_HAS_MSM_DEBUG_UART_PHYS) && !defined(CONFIG_MSM_DEBUG_UART_NONE)
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =MSM_DEBUG_UART_PHYS
 	ldr	\rv, =MSM_DEBUG_UART_BASE
 	.endm
@@ -37,7 +37,7 @@
 	beq	1001b
 	.endm
 #else
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
 	mov	\rv, #0xff000000
 	orr	\rv, \rv, #0x00f00000
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,81 +8,10 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 	.macro	disable_fiq
 	.endm
 
-	.macro  get_irqnr_preamble, base, tmp
-	ldr	\base, =gic_cpu_base_addr
-	ldr	\base, [\base]
-	.endm
-
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Migrated the code from ARM MP port to be more consistent
-	 * with interrupt processing , the following still holds true
-	 * however, all interrupts are treated the same regardless of
-	 * if they are local IPI or PPI
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-31 are PPI
-	 *   (16-18 are the timers)
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * A simple read from the controller will tell us the number of the
-	 * highest priority enabled interrupt.  We then just need to check
-	 * whether it is in the valid range for an IRQ (0-1020 inclusive).
-	 *
-	 * Base ARM code assumes that the local (private) peripheral interrupts
-	 * are not valid, we treat them differently, in that the privates are
-	 * handled like normal shared interrupts with the exception that only
-	 * one processor can register the interrupt and the handler must be
-	 * the same for all processors.
-	 */
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	ldr  \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
-						   9-0 =int # */
-
-	bic     \irqnr, \irqstat, #0x1c00	@mask src
-	cmp     \irqnr, #15
-	ldr		\tmp, =1021
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-    bic \irqnr, \irqstat, #0x1c00
-    cmp \irqnr, #16
-    strcc   \irqstat, [\base, #GIC_CPU_EOI]
-    cmpcs   \irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-    bic \irqnr, \irqstat, #0x1c00
-    mov     \tmp, #0
-    cmp \irqnr, #16
-    moveq   \tmp, #1
-    streq   \irqstat, [\base, #GIC_CPU_EOI]
-    cmp \tmp, #0
-	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef __ASM_ARCH_MSM_GPIO_H
-#define __ASM_ARCH_MSM_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value  __gpio_get_value
-#define gpio_set_value  __gpio_set_value
-#define gpio_cansleep   __gpio_cansleep
-#define gpio_to_irq     __gpio_to_irq
-
-#endif /* __ASM_ARCH_MSM_GPIO_H */
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* arch/arm/mach-msm/include/mach/memory.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/* physical offset of RAM */
-#if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-#elif defined(CONFIG_ARCH_MSM7X30)
-#define PLAT_PHYS_OFFSET		UL(0x00200000)
-#elif defined(CONFIG_ARCH_MSM8X60)
-#define PLAT_PHYS_OFFSET		UL(0x40200000)
-#elif defined(CONFIG_ARCH_MSM8960)
-#define PLAT_PHYS_OFFSET		UL(0x40200000)
-#else
-#define PLAT_PHYS_OFFSET		UL(0x10000000)
-#endif
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/mmc.h linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/mmc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/include/mach/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/include/mach/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,13 +8,6 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 
-struct embedded_sdio_data {
-	struct sdio_cis cis;
-	struct sdio_cccr cccr;
-	struct sdio_embedded_func *funcs;
-	int num_funcs;
-};
-
 struct msm_mmc_gpio {
 	unsigned no;
 	const char *name;
@@ -29,9 +22,9 @@ struct msm_mmc_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
 	u32 (*translate_vdd)(struct device *, unsigned int);
 	unsigned int (*status)(struct device *);
-	struct embedded_sdio_data *embedded_sdio;
 	int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
 	struct msm_mmc_gpio_data *gpio_data;
+	void (*init_card)(struct mmc_card *card);
 };
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/io.c linux-libre-3.2-gnu1/arch/arm/mach-msm/io.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/page.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/Makefile linux-libre-3.2-gnu1/arch/arm/mach-msm/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,8 @@ obj-$(CONFIG_MSM_SMD) += smd.o smd_debug
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
 
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-msm/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-  zreladdr-y		:= 0x10008000
+  zreladdr-y		+= 0x10008000
 params_phys-y		:= 0x10000100
 initrd_phys-y		:= 0x10800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-msm/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@ int __cpuinit boot_secondary(unsigned in
 	 * Note that "pen_release" is the hardware CPU ID, whereas
 	 * "cpu" is Linux's internal ID.
 	 */
-	pen_release = cpu;
+	pen_release = cpu_logical_map(cpu);
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 
@@ -156,6 +156,12 @@ void __init smp_init_cpus(void)
 {
 	unsigned int i, ncores = get_core_count();
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/scm.c linux-libre-3.2-gnu1/arch/arm/mach-msm/scm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/scm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/scm.c	2012-01-04 18:55:44.000000000 -0500
@@ -180,6 +180,9 @@ static u32 smc(u32 cmd_addr)
 			__asmeq("%1", "r0")
 			__asmeq("%2", "r1")
 			__asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
 			"smc	#0	@ switch to secure world\n"
 			: "=r" (r0)
 			: "r" (r0), "r" (r1), "r" (r2)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-msm/timer.c linux-libre-3.2-gnu1/arch/arm/mach-msm/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-msm/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-msm/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,12 +71,16 @@ enum timer_location {
 struct msm_clock {
 	struct clock_event_device   clockevent;
 	struct clocksource          clocksource;
-	struct irqaction            irq;
+	unsigned int		    irq;
 	void __iomem                *regbase;
 	uint32_t                    freq;
 	uint32_t                    shift;
 	void __iomem                *global_counter;
 	void __iomem                *local_counter;
+	union {
+		struct clock_event_device		*evt;
+		struct clock_event_device __percpu	**percpu_evt;
+	};		
 };
 
 enum {
@@ -87,13 +91,10 @@ enum {
 
 
 static struct msm_clock msm_clocks[];
-static struct clock_event_device *local_clock_event;
 
 static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = dev_id;
-	if (smp_processor_id() != 0)
-		evt = local_clock_event;
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
 	if (evt->event_handler == NULL)
 		return IRQ_HANDLED;
 	evt->event_handler(evt);
@@ -171,13 +172,7 @@ static struct msm_clock msm_clocks[] = {
 			.mask           = CLOCKSOURCE_MASK(32),
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
-		.irq = {
-			.name    = "gp_timer",
-			.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
-			.handler = msm_timer_interrupt,
-			.dev_id  = &msm_clocks[0].clockevent,
-			.irq     = INT_GP_TIMER_EXP
-		},
+		.irq = INT_GP_TIMER_EXP,
 		.freq = GPT_HZ,
 	},
 	[MSM_CLOCK_DGT] = {
@@ -196,13 +191,7 @@ static struct msm_clock msm_clocks[] = {
 			.mask           = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
-		.irq = {
-			.name    = "dg_timer",
-			.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
-			.handler = msm_timer_interrupt,
-			.dev_id  = &msm_clocks[1].clockevent,
-			.irq     = INT_DEBUG_TIMER_EXP
-		},
+		.irq = INT_DEBUG_TIMER_EXP,
 		.freq = DGT_HZ >> MSM_DGT_SHIFT,
 		.shift = MSM_DGT_SHIFT,
 	}
@@ -261,10 +250,30 @@ static void __init msm_timer_init(void)
 			printk(KERN_ERR "msm_timer_init: clocksource_register "
 			       "failed for %s\n", cs->name);
 
-		res = setup_irq(clock->irq.irq, &clock->irq);
+		ce->irq = clock->irq;
+		if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+			clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+			if (!clock->percpu_evt) {
+				pr_err("msm_timer_init: memory allocation "
+				       "failed for %s\n", ce->name);
+				continue;
+			}
+
+			*__this_cpu_ptr(clock->percpu_evt) = ce;
+			res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+						 ce->name, clock->percpu_evt);
+			if (!res)
+				enable_percpu_irq(ce->irq, 0);
+		} else {
+			clock->evt = ce;
+			res = request_irq(ce->irq, msm_timer_interrupt,
+					  IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+					  ce->name, &clock->evt);
+		}
+
 		if (res)
-			printk(KERN_ERR "msm_timer_init: setup_irq "
-			       "failed for %s\n", cs->name);
+			pr_err("msm_timer_init: request_irq failed for %s\n",
+			       ce->name);
 
 		clockevents_register_device(ce);
 	}
@@ -273,6 +282,7 @@ static void __init msm_timer_init(void)
 #ifdef CONFIG_SMP
 int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
+	static bool local_timer_inited;
 	struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
 
 	/* Use existing clock_event for cpu 0 */
@@ -281,12 +291,13 @@ int __cpuinit local_timer_setup(struct c
 
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
-	if (!local_clock_event) {
+	if (!local_timer_inited) {
 		writel(0, clock->regbase  + TIMER_ENABLE);
 		writel(0, clock->regbase + TIMER_CLEAR);
 		writel(~0, clock->regbase + TIMER_MATCH_VAL);
+		local_timer_inited = true;
 	}
-	evt->irq = clock->irq.irq;
+	evt->irq = clock->irq;
 	evt->name = "local_timer";
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
 	evt->rating = clock->clockevent.rating;
@@ -298,17 +309,17 @@ int __cpuinit local_timer_setup(struct c
 		clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
 	evt->min_delta_ns = clockevent_delta2ns(4, evt);
 
-	local_clock_event = evt;
-
-	gic_enable_ppi(clock->irq.irq);
+	*__this_cpu_ptr(clock->percpu_evt) = evt;
+	enable_percpu_irq(evt->irq, 0);
 
 	clockevents_register_device(evt);
 	return 0;
 }
 
-inline int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
 {
-	return 1;
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	disable_percpu_irq(evt->irq);
 }
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -145,7 +145,7 @@ subsys_initcall(wxl_pci_init);
 
 MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
 	/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wxl_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/db78x00-bp-setup.c linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ subsys_initcall(db78x00_pci_init);
 
 MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db78x00_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/mv78xx0.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =MV78XX0_REGS_PHYS_BASE
 	ldr	\rv, =MV78XX0_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/irq.c linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
-#include <asm/gpio.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
 #include "common.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/mpp.c linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/mpp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/mpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/mpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,13 +7,12 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
 #include <plat/mpp.h>
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include "common.h"
 #include "mpp.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,7 +78,7 @@ subsys_initcall(rd78x00_pci_init);
 
 MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd78x00_masa_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-cpuimx51.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-cpuimx51.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-cpuimx51.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-cpuimx51.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,21 +22,18 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 
 #include <mach/eukrea-baseboards.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
 #define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
@@ -57,7 +54,7 @@
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -65,7 +62,7 @@ static struct plat_serial8250_port seria
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -73,7 +70,7 @@ static struct plat_serial8250_port seria
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -81,7 +78,7 @@ static struct plat_serial8250_port seria
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTD_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -167,7 +164,7 @@ static int initialize_otg_port(struct pl
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -190,7 +187,7 @@ static int initialize_usbh1_port(struct
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -206,17 +203,17 @@ static int initialize_usbh1_port(struct
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -270,12 +267,12 @@ static void __init eukrea_cpuimx51_init(
 				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
 	eukrea_mbimx51_baseboard_init();
@@ -293,10 +290,11 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/can/platform/mcp251x.h>
@@ -32,14 +31,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "cpu_op-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
@@ -108,7 +105,7 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_
 
 	/* Touchscreen */
 	/* IRQ */
-	_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
@@ -129,7 +126,7 @@ static struct i2c_board_info eukrea_cpui
 		I2C_BOARD_INFO("tsc2007", 0x49),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -149,7 +146,7 @@ static int initialize_otg_port(struct pl
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -172,7 +169,7 @@ static int initialize_usbh1_port(struct
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -189,17 +186,17 @@ static int initialize_usbh1_port(struct
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -245,7 +242,7 @@ static struct spi_board_info cpuimx51sd_
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
 		.platform_data   = &mcp251x_info,
-		.irq             = gpio_to_irq(CAN_IRQGPIO)
+		.irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
 	},
 };
 
@@ -303,17 +300,17 @@ static void __init eukrea_cpuimx51sd_ini
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_request(USBH1_RST, "usb_rst");
 	gpio_direction_output(USBH1_RST, 0);
 	msleep(20);
 	gpio_set_value(USBH1_RST, 1);
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
 	eukrea_mbimxsd51_baseboard_init();
@@ -331,10 +328,11 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51sd_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -219,6 +219,7 @@ MACHINE_START(MX50_RDP, "Freescale MX50
 	.map_io = mx50_map_io,
 	.init_early = imx50_init_early,
 	.init_irq = mx50_init_irq,
+	.handle_irq = imx50_handle_irq,
 	.timer = &mx50_rdp_timer,
 	.init_machine = mx50_rdp_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,6 @@
 #include <mach/3ds_debugboard.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
@@ -169,10 +168,11 @@ static struct sys_timer mx51_3ds_timer =
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_3ds_timer,
 	.init_machine = mx51_3ds_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,14 +24,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "cpu_op-mx51.h"
 
 #define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
@@ -176,7 +174,7 @@ static const struct imxi2c_platform_data
 	.bitrate = 100000,
 };
 
-static struct imxi2c_platform_data babbage_hsi2c_data = {
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
 	.bitrate = 400000,
 };
 
@@ -249,7 +247,7 @@ static int initialize_otg_port(struct pl
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -272,7 +270,7 @@ static int initialize_usbh1_port(struct
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -288,17 +286,17 @@ static int initialize_usbh1_port(struct
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -351,22 +349,27 @@ static const struct esdhc_platform_data
 	.wp_type = ESDHC_WP_GPIO,
 };
 
+void __init imx51_babbage_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+					 ARRAY_SIZE(mx51babbage_pads));
+}
+
 /*
  * Board specific initialization.
  */
 static void __init mx51_babbage_init(void)
 {
 	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
-		MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
+	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
 
 	imx51_soc_init();
 
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
-	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-					ARRAY_SIZE(mx51babbage_pads));
+	imx51_babbage_common_init();
 
 	imx51_add_imx_uart(0, &uart_pdata);
 	imx51_add_imx_uart(1, NULL);
@@ -381,17 +384,17 @@ static void __init mx51_babbage_init(voi
 
 	imx51_add_imx_i2c(0, &babbage_i2c_data);
 	imx51_add_imx_i2c(1, &babbage_i2c_data);
-	mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
+	imx51_add_hsi2c(&babbage_hsi2c_data);
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_usbh1_active();
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 	/* setback USBH1_STP to be function */
 	mxc_iomux_v3_setup_pad(usbh1stp);
 	babbage_usbhub_reset();
@@ -416,10 +419,11 @@ static struct sys_timer mx51_babbage_tim
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_babbage_timer,
 	.init_machine = mx51_babbage_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,14 +32,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 
 #define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
@@ -163,6 +161,11 @@ static const struct gpio_led_platform_da
 	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
 };
 
+static struct esdhc_platform_data sd_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct gpio_keys_button mx51_efikamx_powerkey[] = {
 	{
 		.code = KEY_POWER,
@@ -239,9 +242,11 @@ static void __init mx51_efikamx_init(voi
 
 	/* on < 1.2 boards both SD controllers are used */
 	if (system_rev < 0x12) {
-		imx51_add_sdhci_esdhc_imx(1, NULL);
+		imx51_add_sdhci_esdhc_imx(0, NULL);
+		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
 		mx51_efikamx_leds[2].default_trigger = "mmc1";
-	}
+	} else
+		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
 	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
@@ -280,10 +285,11 @@ static struct sys_timer mx51_efikamx_tim
 
 MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
 	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_efikamx_timer,
 	.init_machine = mx51_efikamx_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_efikasb.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_efikasb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx51_efikasb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx51_efikasb.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,14 +35,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 
 #define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
@@ -56,6 +54,7 @@
 #define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
 
 #define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 
 static iomux_v3_cfg_t mx51efikasb_pads[] = {
 	/* USB HOST2 */
@@ -97,6 +96,8 @@ static iomux_v3_cfg_t mx51efikasb_pads[]
 
 	/* BT */
 	MX51_PAD_EIM_A17__GPIO2_11,
+
+	MX51_PAD_SD1_CD,
 };
 
 static int initialize_usbh2_port(struct platform_device *pdev)
@@ -119,7 +120,7 @@ static int initialize_usbh2_port(struct
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh2_config = {
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
 	.init   = initialize_usbh2_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -129,7 +130,7 @@ static void __init mx51_efikasb_usb(void
 	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
 			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
 	if (usbh2_config.otg)
-		mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+		imx51_add_mxc_ehci_hs(2, &usbh2_config);
 }
 
 static const struct gpio_led mx51_efikasb_leds[] __initconst = {
@@ -182,6 +183,18 @@ static const struct gpio_keys_platform_d
 	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
 };
 
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
+	.cd_gpio = EFIKASB_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct regulator *pwgt1, *pwgt2;
 
 static void mx51_efikasb_power_off(void)
@@ -250,7 +263,8 @@ static void __init efikasb_board_init(vo
 
 	mx51_efikasb_board_id();
 	mx51_efikasb_usb();
-	imx51_add_sdhci_esdhc_imx(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
 	imx_add_gpio_keys(&mx51_efikasb_keys_data);
@@ -266,10 +280,11 @@ static struct sys_timer mx51_efikasb_tim
 };
 
 MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.init_machine =  efikasb_board_init,
 	.timer = &mx51_efikasb_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_ard.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_ard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_ard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_ard.c	2012-01-04 18:55:44.000000000 -0500
@@ -134,8 +134,8 @@ static struct resource ard_smsc911x_reso
 		.flags = IORESOURCE_MEM,
 	},
 	{
-		.start =  gpio_to_irq(ARD_ETHERNET_INT_B),
-		.end =  gpio_to_irq(ARD_ETHERNET_INT_B),
+		.start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+		.end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -171,9 +171,6 @@ static struct imxi2c_platform_data mx53_
 
 static void __init mx53_ard_io_init(void)
 {
-	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-				ARRAY_SIZE(mx53_ard_pads));
-
 	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
 	gpio_direction_input(ARD_ETHERNET_INT_B);
 
@@ -216,6 +213,13 @@ static int weim_cs_config(void)
 	return 0;
 }
 
+void __init imx53_ard_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+					 ARRAY_SIZE(mx53_ard_pads));
+	weim_cs_config();
+}
+
 static struct platform_device *devices[] __initdata = {
 	&ard_smsc_lan9220_device,
 };
@@ -225,8 +229,8 @@ static void __init mx53_ard_board_init(v
 	imx53_soc_init();
 	imx53_add_imx_uart(0, NULL);
 
+	imx53_ard_common_init();
 	mx53_ard_io_init();
-	weim_cs_config();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
@@ -234,6 +238,7 @@ static void __init mx53_ard_board_init(v
 	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
 	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
 	imx_add_gpio_keys(&ard_button_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_ard_timer_init(void)
@@ -249,6 +254,7 @@ MACHINE_START(MX53_ARD, "Freescale MX53
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_ard_timer,
 	.init_machine = mx53_ard_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_evk.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_evk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -106,7 +106,7 @@ static inline void mx53_evk_fec_reset(vo
 	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_evk_fec_pdata = {
+static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -131,12 +131,17 @@ static const struct spi_imx_master mx53_
 	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
 };
 
+void __init imx53_evk_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+					 ARRAY_SIZE(mx53_evk_pads));
+}
+
 static void __init mx53_evk_board_init(void)
 {
 	imx53_soc_init();
+	imx53_evk_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-					ARRAY_SIZE(mx53_evk_pads));
 	mx53_evk_init_uart();
 	mx53_evk_fec_reset();
 	imx53_add_fec(&mx53_evk_fec_pdata);
@@ -167,6 +172,7 @@ MACHINE_START(MX53_EVK, "Freescale MX53
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_evk_timer,
 	.init_machine = mx53_evk_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_loco.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_loco.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_loco.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_loco.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -42,6 +43,7 @@
 #define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
 #define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
 #define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
 	/* FEC */
@@ -64,6 +66,10 @@ static iomux_v3_cfg_t mx53_loco_pads[] =
 	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
 	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
 	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
 	/* I2C2 */
 	MX53_PAD_KEY_COL3__I2C2_SCL,
 	MX53_PAD_KEY_ROW3__I2C2_SDA,
@@ -236,7 +242,7 @@ static inline void mx53_loco_fec_reset(v
 	gpio_set_value(LOCO_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_loco_fec_data = {
+static const struct fec_platform_data mx53_loco_fec_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -257,22 +263,42 @@ static const struct gpio_led_platform_da
 	.num_leds	= ARRAY_SIZE(mx53loco_leds),
 };
 
+void __init imx53_qsb_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+					 ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mma8450", 0x1C),
+	},
+};
+
 static void __init mx53_loco_board_init(void)
 {
+	int ret;
 	imx53_soc_init();
+	imx53_qsb_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-					ARRAY_SIZE(mx53_loco_pads));
 	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
 	imx53_add_imx2_wdt(0, NULL);
+
+	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+	if (ret)
+		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+	i2c_register_board_info(0, mx53loco_i2c_devices,
+				ARRAY_SIZE(mx53loco_i2c_devices));
 	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
 	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
 	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
 	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
 	imx_add_gpio_keys(&loco_button_data);
 	gpio_led_register_device(-1, &mx53loco_leds_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_loco_timer_init(void)
@@ -288,6 +314,7 @@ MACHINE_START(MX53_LOCO, "Freescale MX53
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_loco_timer,
 	.init_machine = mx53_loco_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_smd.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_smd.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/board-mx53_smd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/board-mx53_smd.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "devices-imx53.h"
 
 #define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
 
 static iomux_v3_cfg_t mx53_smd_pads[] = {
 	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
@@ -103,7 +104,7 @@ static inline void mx53_smd_fec_reset(vo
 	gpio_set_value(SMD_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_smd_fec_data = {
+static const struct fec_platform_data mx53_smd_fec_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -111,12 +112,30 @@ static const struct imxi2c_platform_data
 	.bitrate = 100000,
 };
 
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+	int ret;
+
+	/* Enable SATA PWR */
+	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+	if (ret) {
+		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+		return;
+	}
+}
+
+void __init imx53_smd_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+					 ARRAY_SIZE(mx53_smd_pads));
+}
+
 static void __init mx53_smd_board_init(void)
 {
 	imx53_soc_init();
+	imx53_smd_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-					ARRAY_SIZE(mx53_smd_pads));
 	mx53_smd_init_uart();
 	mx53_smd_fec_reset();
 	imx53_add_fec(&mx53_smd_fec_data);
@@ -125,6 +144,8 @@ static void __init mx53_smd_board_init(v
 	imx53_add_sdhci_esdhc_imx(0, NULL);
 	imx53_add_sdhci_esdhc_imx(1, NULL);
 	imx53_add_sdhci_esdhc_imx(2, NULL);
+	mx53_smd_ahci_pwr_on();
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_smd_timer_init(void)
@@ -140,6 +161,7 @@ MACHINE_START(MX53_SMD, "Freescale MX53
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_smd_timer,
 	.init_machine = mx53_smd_board_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/of.h>
 
 #include <asm/div64.h>
 
@@ -1280,9 +1281,9 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2,
 	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1401,6 +1402,22 @@ static struct clk esdhc4_mx53_clk = {
 	.secondary = &esdhc4_ipg_clk,
 };
 
+static struct clk sata_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_max_enable,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+	.disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+	.parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+	.parent = &ahb_clk,
+};
+
 DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
@@ -1418,6 +1435,10 @@ DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCG
 DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
 		NULL, NULL, &pll3_sw_clk, NULL);
 
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+		NULL, NULL, &ipg_clk, &spba_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
 		.dev_id = d, \
@@ -1474,6 +1495,7 @@ static struct clk_lookup mx51_lookups[]
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
 	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 };
 
 static struct clk_lookup mx53_lookups[] = {
@@ -1507,6 +1529,10 @@ static struct clk_lookup mx53_lookups[]
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
 	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
 };
 
 static void clk_tree_init(void)
@@ -1548,9 +1574,8 @@ int __init mx51_clocks_init(unsigned lon
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx51_revision();
+	imx_print_silicon_rev("i.MX51", mx51_revision());
 	clk_disable(&iim_clk);
-	mx51_display_revision();
 
 	/* move usb_phy_clk to 24MHz */
 	clk_set_parent(&usb_phy1_clk, &osc_clk);
@@ -1568,7 +1593,7 @@ int __init mx51_clocks_init(unsigned lon
 
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_MXC_INT_GPT);
+		MX51_INT_GPT);
 	return 0;
 }
 
@@ -1592,9 +1617,8 @@ int __init mx53_clocks_init(unsigned lon
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx53_revision();
+	imx_print_silicon_rev("i.MX53", mx53_revision());
 	clk_disable(&iim_clk);
-	mx53_display_revision();
 
 	/* Set SDHC parents to be PLL2 */
 	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
@@ -1609,3 +1633,43 @@ int __init mx53_clocks_init(unsigned lon
 		MX53_INT_GPT);
 	return 0;
 }
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+				   unsigned long *ckih1, unsigned long *ckih2)
+{
+	struct device_node *np;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			*ckil = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			*osc = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			*ckih1 = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+			*ckih2 = rate;
+	}
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,9 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
-static int cpu_silicon_rev = -1;
+static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
 #define MX50_HW_ADADIG_DIGPROG	0xB0
@@ -28,11 +28,14 @@ static int get_mx51_srev(void)
 	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	if (rev == 0x0)
+	switch (rev) {
+	case 0x0:
 		return IMX_CHIP_REVISION_2_0;
-	else if (rev == 0x10)
+	case 0x10:
 		return IMX_CHIP_REVISION_3_0;
-	return 0;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
 }
 
 /*
@@ -45,33 +48,13 @@ int mx51_revision(void)
 	if (!cpu_is_mx51())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx51_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx51_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx51_revision);
 
-void mx51_display_revision(void)
-{
-	int rev;
-	char *srev;
-	rev = mx51_revision();
-
-	switch (rev) {
-	case IMX_CHIP_REVISION_2_0:
-		srev = IMX_CHIP_REVISION_2_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_3_0:
-		srev = IMX_CHIP_REVISION_3_0_STRING;
-		break;
-	default:
-		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
-	}
-	printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx51_display_revision);
-
 #ifdef CONFIG_NEON
 
 /*
@@ -84,7 +67,8 @@ static int __init mx51_neon_fixup(void)
 	if (!cpu_is_mx51())
 		return 0;
 
-	if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
+	if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+			(elf_hwcap & HWCAP_NEON)) {
 		elf_hwcap &= ~HWCAP_NEON;
 		pr_info("Turning off NEON support, detected broken NEON implementation\n");
 	}
@@ -121,10 +105,10 @@ int mx53_revision(void)
 	if (!cpu_is_mx53())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx53_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx53_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx53_revision);
 
@@ -134,7 +118,7 @@ static int get_mx50_srev(void)
 	u32 rev;
 
 	if (!anatop) {
-		cpu_silicon_rev = -EINVAL;
+		mx5_cpu_rev = -EINVAL;
 		return 0;
 	}
 
@@ -159,36 +143,13 @@ int mx50_revision(void)
 	if (!cpu_is_mx50())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx50_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx50_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx50_revision);
 
-void mx53_display_revision(void)
-{
-	int rev;
-	char *srev;
-	rev = mx53_revision();
-
-	switch (rev) {
-	case IMX_CHIP_REVISION_1_0:
-		srev = IMX_CHIP_REVISION_1_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_0:
-		srev = IMX_CHIP_REVISION_2_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_1:
-		srev = IMX_CHIP_REVISION_2_1_STRING;
-		break;
-	default:
-		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
-	}
-	printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx53_display_revision);
-
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,120 +0,0 @@
-/*
- * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
-
-static struct resource mxc_hsi2c_resources[] = {
-	{
-		.start = MX51_HSI2C_DMA_BASE_ADDR,
-		.end = MX51_HSI2C_DMA_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_HS_I2C,
-		.end = MX51_MXC_INT_HS_I2C,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_hsi2c_device = {
-	.name = "imx-i2c",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(mxc_hsi2c_resources),
-	.resource = mxc_hsi2c_resources
-};
-
-static u64 usb_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource usbotg_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR,
-		.end = MX51_OTG_BASE_ADDR + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_OTG,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-/* OTG gadget device */
-struct platform_device mxc_usbdr_udc_device = {
-	.name		= "fsl-usb2-udc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(usbotg_resources),
-	.resource	= usbotg_resources,
-	.dev		= {
-		.dma_mask		= &usb_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device mxc_usbdr_host_device = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(usbotg_resources),
-	.resource = usbotg_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh1_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x200,
-		.end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh1_device = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(usbh1_resources),
-	.resource = usbh1_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh2_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x400,
-		.end = MX51_OTG_BASE_ADDR + 0x400 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2_device = {
-	.name = "mxc-ehci",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(usbh2_resources),
-	.resource = usbh2_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices.h linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-extern struct platform_device mxc_usbdr_host_device;
-extern struct platform_device mxc_usbh1_device;
-extern struct platform_device mxc_usbh2_device;
-extern struct platform_device mxc_usbdr_udc_device;
-extern struct platform_device mxc_hsi2c_device;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices-imx51.h linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices-imx51.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices-imx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices-imx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,15 @@ extern const struct imx_fec_data imx51_f
 #define imx51_add_fec(pdata)	\
 	imx_add_fec(&imx51_fec_data, pdata)
 
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
 extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
 #define imx51_add_imx_i2c(id, pdata)	\
 	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata)	\
+	imx51_add_imx_i2c(2, pdata)
 
 extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
 #define imx51_add_imx_ssi(id, pdata)	\
@@ -25,6 +31,13 @@ extern const struct imx_imx_uart_1irq_da
 #define imx51_add_imx_uart(id, pdata)	\
 	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
 
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
 extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
 #define imx51_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
@@ -52,3 +65,7 @@ extern const struct imx_mxc_pwm_data imx
 extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
 #define imx51_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+	imx_add_pata_imx(&imx51_pata_imx_data)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices-imx53.h linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices-imx53.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/devices-imx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/devices-imx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,3 +40,9 @@ extern const struct imx_imx_ssi_data imx
 extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
 #define imx53_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+	imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/ehci.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/ehci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/ehci.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@ int mx51_initialize_usb_hw(int port, uns
 	void __iomem *usbother_base;
 	int ret = 0;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base) {
 		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
 		return -ENOMEM;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <asm/mach/arch.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
 #define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
@@ -160,7 +159,7 @@ struct tsc2007_platform_data tsc2007_dat
 static struct i2c_board_info mbimx51_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("tsc2007", 0x49),
-		.irq  = gpio_to_irq(MBIMX51_TSC2007_GPIO),
+		.irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
 		.platform_data = &tsc2007_data,
 	}, {
 		I2C_BOARD_INFO("tlv320aic23", 0x1a),
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,6 @@
 
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
@@ -41,13 +40,12 @@
 #include <mach/audmux.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LED */
 	MX51_PAD_NANDF_D10__GPIO3_30,
 	/* SWITCH */
-	_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 	/* UART2 */
@@ -66,7 +64,7 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pad
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
 	/* SD1 CD */
-	_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/imx51-dt.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/imx51-dt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/imx51-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/imx51-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx51_irq_match);
+
+	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx51_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.handle_irq	= imx51_handle_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/imx53-dt.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/imx53-dt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/imx53-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/imx53-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx53_irq_match);
+
+	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx53_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+	.init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+	"fsl,imx53-ard",
+	"fsl,imx53-evk",
+	"fsl,imx53-qsb",
+	"fsl,imx53-smd",
+	NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+	.map_io		= mx53_map_io,
+	.init_early	= imx53_init_early,
+	.init_irq	= mx53_init_irq,
+	.handle_irq	= imx53_handle_irq,
+	.timer		= &imx53_timer,
+	.init_machine	= imx53_dt_init,
+	.dt_compat	= imx53_dt_board_compat,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-mx5/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,8 +1,9 @@
-if ARCH_MX503 || ARCH_MX51
+if ARCH_MX5
+
 # ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
 # image. So for most time, SOC_IMX50/51/53 should be used.
 
-config ARCH_MX5
+config ARCH_MX51
 	bool
 
 config ARCH_MX50
@@ -19,7 +20,6 @@ config SOC_IMX50
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
 	select ARCH_MX50
 
 config	SOC_IMX51
@@ -30,7 +30,7 @@ config	SOC_IMX51
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
+	select ARCH_MX51
 
 config	SOC_IMX53
 	bool
@@ -38,10 +38,8 @@ config	SOC_IMX53
 	select ARM_L1_CACHE_SHIFT_6
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
-	select ARCH_MX5
 	select ARCH_MX53
 
-if ARCH_MX50_SUPPORTED
 #comment "i.MX50 machines:"
 
 config MACH_MX50_RDP
@@ -52,22 +50,29 @@ config MACH_MX50_RDP
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
-	select IMX_HAVE_PLATFORM_FEC
 	help
 	  Include support for MX50 reference design platform (RDP) board. This
 	  includes specific configurations for the board and its peripherals.
 
-endif # ARCH_MX50_SUPPORTED
-
-if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	select MACH_MX51_BABBAGE
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -91,8 +96,10 @@ config MACH_MX51_3DS
 config MACH_EUKREA_CPUIMX51
 	bool "Support Eukrea CPUIMX51 module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -119,10 +126,12 @@ endchoice
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_SPI_IMX
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for Eukrea CPUIMX51SD platform. This includes
 	  specific configurations for the module and its peripherals.
@@ -147,6 +156,8 @@ config MX51_EFIKA_COMMON
 	bool
 	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_PATA_IMX
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -167,11 +178,20 @@ config MACH_MX51_EFIKASB
 	  Include support for Genesi Efika Smartbook. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX51
-
-if ARCH_MX53_SUPPORTED
 comment "i.MX53 machines:"
 
+config MACH_IMX53_DT
+	bool "Support i.MX53 platforms from device tree"
+	select SOC_IMX53
+	select USE_OF
+	select MACH_MX53_ARD
+	select MACH_MX53_EVK
+	select MACH_MX53_LOCO
+	select MACH_MX53_SMD
+	help
+	  Include support for Freescale i.MX53 based platforms
+	  using the device tree for discovery
+
 config MACH_MX53_EVK
 	bool "Support MX53 EVK platforms"
 	select SOC_IMX53
@@ -221,6 +241,4 @@ config MACH_MX53_ARD
 	  Include support for MX53 ARD platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX53_SUPPORTED
-
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/Makefile linux-libre-3.2-gnu1/arch/arm/mach-mx5/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,8 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
-obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
 
 obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
@@ -22,3 +21,6 @@ obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
 obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-mx5/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
-   zreladdr-$(CONFIG_ARCH_MX50)	:= 0x70008000
+   zreladdr-$(CONFIG_ARCH_MX50)	+= 0x70008000
 params_phys-$(CONFIG_ARCH_MX50)	:= 0x70000100
 initrd_phys-$(CONFIG_ARCH_MX50)	:= 0x70800000
-   zreladdr-$(CONFIG_ARCH_MX51)	:= 0x90008000
+   zreladdr-$(CONFIG_ARCH_MX51)	+= 0x90008000
 params_phys-$(CONFIG_ARCH_MX51)	:= 0x90000100
 initrd_phys-$(CONFIG_ARCH_MX51)	:= 0x90800000
-   zreladdr-$(CONFIG_ARCH_MX53)	:= 0x70008000
+   zreladdr-$(CONFIG_ARCH_MX53)	+= 0x70008000
 params_phys-$(CONFIG_ARCH_MX53)	:= 0x70000100
 initrd_phys-$(CONFIG_ARCH_MX53)	:= 0x70800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/mm.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/mm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/mm.c	2013-05-02 01:33:54.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/mm.c	2013-05-01 23:41:54.000000000 -0400
@@ -21,12 +21,29 @@
 #include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
+static void imx5_idle(void)
+{
+	if (!need_resched())
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+	local_irq_enable();
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+	imx_map_entry(MX50, TZIC, MT_DEVICE),
+	imx_map_entry(MX50, SPBA0, MT_DEVICE),
+	imx_map_entry(MX50, AIPS1, MT_DEVICE),
+	imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
 /*
  * Define the MX51 memory map.
  */
 static struct map_desc mx51_io_desc[] __initdata = {
+	imx_map_entry(MX51, TZIC, MT_DEVICE),
 	imx_map_entry(MX51, IRAM, MT_DEVICE),
-	imx_map_entry(MX51, DEBUG, MT_DEVICE),
 	imx_map_entry(MX51, AIPS1, MT_DEVICE),
 	imx_map_entry(MX51, SPBA0, MT_DEVICE),
 	imx_map_entry(MX51, AIPS2, MT_DEVICE),
@@ -36,6 +53,7 @@ static struct map_desc mx51_io_desc[] __
  * Define the MX53 memory map.
  */
 static struct map_desc mx53_io_desc[] __initdata = {
+	imx_map_entry(MX53, TZIC, MT_DEVICE),
 	imx_map_entry(MX53, AIPS1, MT_DEVICE),
 	imx_map_entry(MX53, SPBA0, MT_DEVICE),
 	imx_map_entry(MX53, AIPS2, MT_DEVICE),
@@ -46,21 +64,34 @@ static struct map_desc mx53_io_desc[] __
  * system startup to create static physical to virtual memory mappings
  * for the IO modules.
  */
+void __init mx50_map_io(void)
+{
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
 void __init mx51_map_io(void)
 {
 	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
 }
 
+void __init mx53_map_io(void)
+{
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX50);
+	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
 void __init imx51_init_early(void)
 {
 	mxc_set_cpu_type(MXC_CPU_MX51);
 	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-}
-
-void __init mx53_map_io(void)
-{
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+	pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
@@ -70,35 +101,19 @@ void __init imx53_init_early(void)
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
-void __init mx51_init_irq(void)
+void __init mx50_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-		tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
-	else
-		tzic_addr = MX51_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
 
-	tzic_init_irq(tzic_virt);
+void __init mx51_init_irq(void)
+{
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
 }
 
 void __init mx53_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	tzic_addr = MX53_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
-
-	tzic_init_irq(tzic_virt);
+	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
 }
 
 static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
@@ -138,13 +153,24 @@ static struct sdma_platform_data imx53_s
 	.script_addrs = &imx53_sdma_script,
 };
 
+void __init imx50_soc_init(void)
+{
+	/* i.mx50 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
 void __init imx51_soc_init(void)
 {
 	/* i.mx51 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
 
 	/* i.mx51 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/mm-mx50.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/mm-mx50.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/mm-mx50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/mm-mx50.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-	imx_map_entry(MX50, TZIC, MT_DEVICE),
-	imx_map_entry(MX50, SPBA0, MT_DEVICE),
-	imx_map_entry(MX50, AIPS1, MT_DEVICE),
-	imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX50);
-	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init imx50_soc_init(void)
-{
-	/* i.mx50 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/mx51_efika.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/mx51_efika.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/mx51_efika.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/mx51_efika.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,14 +34,12 @@
 #include <linux/usb/ulpi.h>
 #include <mach/ulpi.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 #include "cpu_op-mx51.h"
 
@@ -133,7 +131,7 @@ static int initialize_otg_port(struct pl
 	u32 v;
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
@@ -150,7 +148,7 @@ static int initialize_otg_port(struct pl
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init   = initialize_otg_port,
 	.portsc = MXC_EHCI_UTMI_16BIT,
 };
@@ -170,7 +168,7 @@ static int initialize_usbh1_port(struct
 	gpio_set_value(EFIKAMX_USBH1_STP, 1);
 	msleep(1);
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
 
 	/* The clock for the USBH1 ULPI port will come externally */
@@ -189,7 +187,7 @@ static int initialize_usbh1_port(struct
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
 	.init   = initialize_usbh1_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -217,9 +215,9 @@ static void __init mx51_efika_usb(void)
 	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
 			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
 
-	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	if (usbh1_config.otg)
-		mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+		imx51_add_mxc_ehci_hs(1, &usbh1_config);
 }
 
 static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
@@ -567,7 +565,7 @@ static struct mc13xxx_regulator_init_dat
 };
 
 static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-	.flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR,
+	.flags = MC13XXX_USE_RTC,
 	.regulators = {
 		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
 		.regulators = mx51_efika_regulators,
@@ -589,7 +587,7 @@ static struct spi_board_info mx51_efika_
 		.bus_num = 0,
 		.chip_select = 0,
 		.platform_data = &mx51_efika_mc13892_data,
-		.irq = gpio_to_irq(EFIKAMX_PMIC),
+		.irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
 	},
 };
 
@@ -609,7 +607,6 @@ void __init efika_board_common_init(void
 					ARRAY_SIZE(mx51efika_pads));
 	imx51_add_imx_uart(0, &uart_pdata);
 	mx51_efika_usb();
-	imx51_add_sdhci_esdhc_imx(0, NULL);
 
 	/* FIXME: comes from original code. check this. */
 	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
@@ -627,8 +624,9 @@ void __init efika_board_common_init(void
 		ARRAY_SIZE(mx51_efika_spi_board_info));
 	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
 
+	imx51_add_pata_imx();
+
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
 }
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/pm-imx5.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/pm-imx5.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/pm-imx5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/pm-imx5.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,14 +14,19 @@
 #include <linux/err.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <mach/system.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
 #include "crm_regs.h"
 
 static struct clk *gpc_dvfs_clk;
 
+static int mx5_suspend_prepare(void)
+{
+	return clk_enable(gpc_dvfs_clk);
+}
+
 static int mx5_suspend_enter(suspend_state_t state)
 {
-	clk_enable(gpc_dvfs_clk);
 	switch (state) {
 	case PM_SUSPEND_MEM:
 		mx5_cpu_lp_set(STOP_POWER_OFF);
@@ -42,11 +47,14 @@ static int mx5_suspend_enter(suspend_sta
 		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
 	}
 	cpu_do_idle();
-	clk_disable(gpc_dvfs_clk);
-
 	return 0;
 }
 
+static void mx5_suspend_finish(void)
+{
+	clk_disable(gpc_dvfs_clk);
+}
+
 static int mx5_pm_valid(suspend_state_t state)
 {
 	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
@@ -54,7 +62,9 @@ static int mx5_pm_valid(suspend_state_t
 
 static const struct platform_suspend_ops mx5_suspend_ops = {
 	.valid = mx5_pm_valid,
+	.prepare = mx5_suspend_prepare,
 	.enter = mx5_suspend_enter,
+	.finish = mx5_suspend_finish,
 };
 
 static int __init mx5_pm_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mx5/system.c linux-libre-3.2-gnu1/arch/arm/mach-mx5/system.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mx5/system.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mx5/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include "crm_regs.h"
 
 /* set cpu low power mode before WFI instruction. This function is called
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/clock-mx28.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/clock-mx28.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/clock-mx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/clock-mx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -349,7 +349,7 @@ static int name##_set_rate(struct clk *c
 									\
 		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 		reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC;			\
-		reg |= frac;						\
+		reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC;		\
 		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 	}								\
 									\
@@ -404,7 +404,7 @@ static int name##_set_rate(struct clk *c
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
 	reg &= ~BM_CLKCTRL_##dr##_DIV;					\
 	reg |= div << BP_CLKCTRL_##dr##_DIV;				\
-	if (reg | (1 << clk->enable_shift)) {				\
+	if (reg & (1 << clk->enable_shift)) {				\
 		pr_err("%s: clock is gated\n", __func__);		\
 		return -EINVAL;						\
 	}								\
@@ -640,6 +640,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
+	_REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk)
+	_REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk)
 };
 
 static int clk_misc_init(void)
@@ -708,11 +710,11 @@ static int clk_misc_init(void)
 
 	/* SAIF has to use frac div for functional operation */
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
-	reg &= ~BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
 
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
-	reg &= ~BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
 
 	/*
@@ -738,11 +740,17 @@ static int clk_misc_init(void)
 	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
 			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
 
-	/* Extra fec clock setting */
-	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
-	reg &= ~BM_CLKCTRL_ENET_SLEEP;
-	reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
-	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+	/*
+	 * Extra fec clock setting
+	 * The DENX M28 uses an external clock source
+	 * and the clock output must not be enabled
+	 */
+	if (!machine_is_m28evk()) {
+		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+		reg &= ~BM_CLKCTRL_ENET_SLEEP;
+		reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
+		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+	}
 
 	/*
 	 * 480 MHz seems too high to be ssp clock source directly,
@@ -774,6 +782,8 @@ int __init mx28_clocks_init(void)
 	clk_enable(&uart_clk);
 
 	clk_set_parent(&lcdif_clk, &ref_pix_clk);
+	clk_set_parent(&saif0_clk, &pll0_clk);
+	clk_set_parent(&saif1_clk, &pll0_clk);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,3 +23,9 @@ config MXS_HAVE_PLATFORM_MXS_PWM
 
 config MXS_HAVE_PLATFORM_MXSFB
 	bool
+
+config MXS_HAVE_PLATFORM_MXS_SAIF
+	bool
+
+config MXS_HAVE_PLATFORM_RTC_STMP3XXX
+	bool
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/Makefile linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,3 +8,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC)
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
 obj-y += platform-gpio-mxs.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/platform-mxs-saif.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/platform-mxs-saif.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/platform-mxs-saif.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/platform-mxs-saif.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_saif_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SAIF ## _id ## _BASE_ADDR,		\
+		.irq = soc ## _INT_SAIF ## _id,				\
+		.dma = soc ## _DMA_SAIF ## _id,				\
+		.dmairq = soc ## _INT_SAIF ## _id ##_DMA,		\
+	}
+
+#define mxs_saif_data_entry(soc, _id)					\
+	[_id] = mxs_saif_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_saif_data mx28_saif_data[] __initconst = {
+	mxs_saif_data_entry(MX28, 0),
+	mxs_saif_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dma,
+			.end = data->dma,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.start = data->dmairq,
+			.end = data->dmairq,
+			.flags = IORESOURCE_IRQ,
+		},
+
+	};
+
+	return mxs_add_platform_device("mxs-saif", data->id, res,
+					ARRAY_SIZE(res), NULL, 0);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * 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 <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX23_RTC_BASE_ADDR,
+			.end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX23_INT_RTC_ALARM,
+			.end = MX23_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_RTC_BASE_ADDR,
+			.end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX28_INT_RTC_ALARM,
+			.end = MX28_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX28 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices-mx23.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices-mx23.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices-mx23.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices-mx23.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,3 +29,5 @@ extern const struct mxs_mxs_mmc_data mx2
 
 struct platform_device *__init mx23_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices-mx28.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices-mx28.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/devices-mx28.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/devices-mx28.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,3 +45,8 @@ extern const struct mxs_mxs_mmc_data mx2
 
 struct platform_device *__init mx28_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+extern const struct mxs_saif_data mx28_saif_data[] __initconst;
+#define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
+
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,23 +14,15 @@
 #include <mach/mx23.h>
 #include <mach/mx28.h>
 
-#ifdef CONFIG_SOC_IMX23
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#ifdef CONFIG_DEBUG_IMX23_UART
 #define UART_PADDR	MX23_DUART_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX28_UART)
 #define UART_PADDR	MX28_DUART_BASE_ADDR
 #endif
 
 #define UART_VADDR	MXS_IO_ADDRESS(UART_PADDR)
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =UART_PADDR	@ physical
 		ldr	\rv, =UART_VADDR	@ virtual
 		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,3 +92,15 @@ struct platform_device *__init mxs_add_m
 /* pwm */
 struct platform_device *__init mxs_add_mxs_pwm(
 		resource_size_t iobase, int id);
+
+/* saif */
+struct mxs_saif_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+	resource_size_t dma;
+	resource_size_t dmairq;
+};
+
+struct platform_device *__init mxs_add_saif(
+		const struct mxs_saif_data *data);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,35 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __MACH_MXS_GPIO_H__
-#define __MACH_MXS_GPIO_H__
-
-#include <asm-generic/gpio.h>
-
-#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#define gpio_get_value		__gpio_get_value
-#define gpio_set_value		__gpio_set_value
-#define gpio_cansleep		__gpio_cansleep
-#define gpio_to_irq		__gpio_to_irq
-
-#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
-
-#endif /* __MACH_MXS_GPIO_H__ */
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __MACH_MXS_MEMORY_H__
-#define __MACH_MXS_MEMORY_H__
-
-#define PHYS_OFFSET		UL(0x40000000)
-
-#endif /* __MACH_MXS_MEMORY_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/mx28.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/mx28.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/mx28.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/mx28.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,8 +104,8 @@
 #define MX28_INT_CAN1			9
 #define MX28_INT_LRADC_TOUCH		10
 #define MX28_INT_HSADC			13
-#define MX28_INT_IRADC_THRESH0		14
-#define MX28_INT_IRADC_THRESH1		15
+#define MX28_INT_LRADC_THRESH0		14
+#define MX28_INT_LRADC_THRESH1		15
 #define MX28_INT_LRADC_CH0		16
 #define MX28_INT_LRADC_CH1		17
 #define MX28_INT_LRADC_CH2		18
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/mxs.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/mxs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/mxs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/mxs.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,11 @@
  */
 #define cpu_is_mx23()		(					\
 		machine_is_mx23evk() ||					\
+		machine_is_stmp378x() ||				\
 		0)
 #define cpu_is_mx28()		(					\
 		machine_is_mx28evk() ||					\
+		machine_is_m28evk() ||					\
 		machine_is_tx28() ||					\
 		0)
 
@@ -86,6 +88,8 @@
 	.type = _type,							\
 }
 
+#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
+
 #define MXS_SET_ADDR		0x4
 #define MXS_CLR_ADDR		0x8
 #define MXS_TOG_ADDR		0xc
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@ static inline void __arch_decomp_setup(u
 		mxs_duart_base = MX23_DUART_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX28EVK:
+	case MACH_TYPE_M28EVK:
 	case MACH_TYPE_TX28:
 		mxs_duart_base = MX28_DUART_BASE_ADDR;
 		break;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-mxs/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@ config MACH_STMP378X_DEVB
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for STMP378x-devb platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -34,6 +35,7 @@ config MACH_MX23EVK
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for MX23EVK platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -48,6 +50,9 @@ config MACH_MX28EVK
 	select MXS_HAVE_PLATFORM_FLEXCAN
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_MXS_SAIF
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	select MXS_OCOTP
 	help
 	  Include support for MX28EVK platform. This includes specific
@@ -63,9 +68,27 @@ config MODULE_TX28
 	select MXS_HAVE_PLATFORM_MXS_I2C
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXS_PWM
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
+
+config MODULE_M28
+	bool
+	select SOC_IMX28
+	select LEDS_GPIO_REGISTER
+	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_OCOTP
 
 config MACH_TX28
 	bool "Ka-Ro TX28 module"
 	select MODULE_TX28
 
+config MACH_M28EVK
+	bool "Support DENX M28EVK Platform"
+	select MODULE_M28
+
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-m28evk.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-m28evk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-m28evk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-m28evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
+ *
+ * based on: mach-mx28_evk.c
+ * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+
+#define M28EVK_GPIO_USERLED1	MXS_GPIO_NR(3, 16)
+#define M28EVK_GPIO_USERLED2	MXS_GPIO_NR(3, 17)
+
+#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
+#define M28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 28)
+
+#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
+
+static const iomux_cfg_t m28evk_pads[] __initconst = {
+	/* duart */
+	MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart0 */
+	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+
+	/* auart3 */
+	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
+
+#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
+	/* fec0 */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
+	/* fec1 */
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
+
+	/* flexcan0 */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* flexcan1 */
+	MX28_PAD_GPMI_CE2N__CAN1_TX,
+	MX28_PAD_GPMI_CE3N__CAN1_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* mxsfb (lcdif) */
+	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+
+	MX28_PAD_LCD_ENABLE__LCD_ENABLE	| MXS_PAD_CTRL,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
+
+	/* mmc0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* mmc1 */
+	MX28_PAD_GPMI_D00__SSP1_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D01__SSP1_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D02__SSP1_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D03__SSP1_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D04__SSP1_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D05__SSP1_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D06__SSP1_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D07__SSP1_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY1__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_WRN__SSP1_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* led */
+	MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+	MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
+
+	/* nand */
+	MX28_PAD_GPMI_D00__GPMI_D0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D01__GPMI_D1 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D02__GPMI_D2 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D03__GPMI_D3 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D04__GPMI_D4 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D05__GPMI_D5 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D06__GPMI_D6 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D07__GPMI_D7 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_ALE__GPMI_ALE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_CLE__GPMI_CLE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+
+	/* Backlight */
+	MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led m28evk_leds[] __initconst = {
+	{
+		.name = "user-led1",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED1,
+	},
+	{
+		.name = "user-led2",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED2,
+	},
+};
+
+static const struct gpio_led_platform_data m28evk_led_data __initconst = {
+	.leds = m28evk_leds,
+	.num_leds = ARRAY_SIZE(m28evk_leds),
+};
+
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
+	{
+		/* fec0 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	}, {
+		/* fec1 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	},
+};
+
+static int __init m28evk_fec_get_mac(void)
+{
+	int i;
+	u32 val;
+	const u32 *ocotp = mxs_get_ocotp();
+
+	if (!ocotp) {
+		pr_err("%s: timeout when reading fec mac from OCOTP\n",
+			__func__);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * OCOTP only stores the last 4 octets for each mac address,
+	 * so hard-code DENX OUI (C0:E5:4E) here.
+	 */
+	for (i = 0; i < 2; i++) {
+		val = ocotp[i * 4];
+		mx28_fec_pdata[i].mac[0] = 0xC0;
+		mx28_fec_pdata[i].mac[1] = 0xE5;
+		mx28_fec_pdata[i].mac[2] = 0x4E;
+		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+	}
+
+	return 0;
+}
+
+/* mxsfb (lcdif) */
+static struct fb_videomode m28evk_video_modes[] = {
+	{
+		.name		= "Ampire AM-800480R2TMQW-T01H",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 30066, /* picosecond (33.26 MHz) */
+		.left_margin	= 0,
+		.right_margin	= 256,
+		.upper_margin	= 0,
+		.lower_margin	= 45,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
+	.mode_list	= m28evk_video_modes,
+	.mode_count	= ARRAY_SIZE(m28evk_video_modes),
+	.default_bpp	= 16,
+	.ld_intf_width	= STMLCDIF_18BIT,
+};
+
+static struct at24_platform_data m28evk_eeprom = {
+	.byte_len = 16384,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("at24", 0x51),	/* E0=1, E1=0, E2=0 */
+		.platform_data = &m28evk_eeprom,
+	},
+};
+
+static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
+	{
+		/* mmc0 */
+		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	}, {
+		/* mmc1 */
+		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	},
+};
+
+static void __init m28evk_init(void)
+{
+	mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
+
+	mx28_add_duart();
+	mx28_add_auart0();
+	mx28_add_auart3();
+
+	if (!m28evk_fec_get_mac()) {
+		mx28_add_fec(0, &mx28_fec_pdata[0]);
+		mx28_add_fec(1, &mx28_fec_pdata[1]);
+	}
+
+	mx28_add_flexcan(0, NULL);
+	mx28_add_flexcan(1, NULL);
+
+	mx28_add_mxsfb(&m28evk_mxsfb_pdata);
+
+	mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
+	mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
+
+	gpio_led_register_device(0, &m28evk_led_data);
+
+	/* I2C */
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
+			ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
+}
+
+static void __init m28evk_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer m28evk_timer = {
+	.init	= m28evk_timer_init,
+};
+
+MACHINE_START(M28EVK, "DENX M28 EVK")
+	.map_io		= mx28_map_io,
+	.init_irq	= mx28_init_irq,
+	.timer		= &m28evk_timer,
+	.init_machine	= m28evk_init,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-mx23evk.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-mx23evk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-mx23evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-mx23evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -167,6 +166,7 @@ static void __init mx23evk_init(void)
 		gpio_set_value(MX23EVK_BL_ENABLE, 1);
 
 	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
+	mx23_add_rtc_stmp3xxx();
 }
 
 static void __init mx23evk_timer_init(void)
@@ -182,6 +182,6 @@ MACHINE_START(MX23EVK, "Freescale MX23 E
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx23_map_io,
 	.init_irq	= mx23_init_irq,
-	.init_machine	= mx23evk_init,
 	.timer		= &mx23evk_timer,
+	.init_machine	= mx23evk_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-mx28evk.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-mx28evk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-mx28evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-mx28evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,8 +16,10 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <linux/irq.h>
 #include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -183,6 +185,24 @@ static const iomux_cfg_t mx28evk_pads[]
 
 	/* led */
 	MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_I2C0_SDA__I2C0_SDA |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+
+	/* saif0 & saif1 */
+	MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 };
 
 /* led */
@@ -352,6 +372,55 @@ static struct mxs_mmc_platform_data mx28
 	},
 };
 
+static struct i2c_board_info mxs_i2c0_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("sgtl5000", 0x0a),
+	},
+};
+
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+static struct regulator_consumer_supply mx28evk_audio_consumer_supplies[] = {
+	REGULATOR_SUPPLY("VDDA", "0-000a"),
+	REGULATOR_SUPPLY("VDDIO", "0-000a"),
+};
+
+static struct regulator_init_data mx28evk_vdd_reg_init_data = {
+	.constraints	= {
+		.name	= "3V3",
+		.always_on = 1,
+	},
+	.consumer_supplies = mx28evk_audio_consumer_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(mx28evk_audio_consumer_supplies),
+};
+
+static struct fixed_voltage_config mx28evk_vdd_pdata = {
+	.supply_name	= "board-3V3",
+	.microvolts	= 3300000,
+	.gpio		= -EINVAL,
+	.enabled_at_boot = 1,
+	.init_data	= &mx28evk_vdd_reg_init_data,
+};
+static struct platform_device mx28evk_voltage_regulator = {
+	.name		= "reg-fixed-voltage",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &mx28evk_vdd_pdata,
+	},
+};
+static void __init mx28evk_add_regulators(void)
+{
+	platform_device_register(&mx28evk_voltage_regulator);
+}
+#else
+static void __init mx28evk_add_regulators(void) {}
+#endif
+
+static struct gpio mx28evk_lcd_gpios[] = {
+	{ MX28EVK_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, "lcd-enable" },
+	{ MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
+};
+
 static void __init mx28evk_init(void)
 {
 	int ret;
@@ -378,32 +447,41 @@ static void __init mx28evk_init(void)
 		mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
 	}
 
-	ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	ret = gpio_request_array(mx28evk_lcd_gpios,
+				 ARRAY_SIZE(mx28evk_lcd_gpios));
 	if (ret)
-		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+		pr_warn("failed to request gpio pins for lcd: %d\n", ret);
 	else
-		gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+		mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
-	ret = gpio_request_one(MX28EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
-	if (ret)
-		pr_warn("failed to request gpio bl-enable: %d\n", ret);
-	else
-		gpio_set_value(MX28EVK_BL_ENABLE, 1);
+	mx28_add_saif(0);
+	mx28_add_saif(1);
 
-	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, mxs_i2c0_board_info,
+				ARRAY_SIZE(mxs_i2c0_board_info));
+
+	mx28evk_add_regulators();
+
+	mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0,
+			NULL, 0);
 
 	/* power on mmc slot by writing 0 to the gpio */
 	ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW,
 			       "mmc0-slot-power");
 	if (ret)
 		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
-	mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
+	else
+		mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
 
 	ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW,
 			       "mmc1-slot-power");
 	if (ret)
 		pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
-	mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+	else
+		mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
+	mx28_add_rtc_stmp3xxx();
 
 	gpio_led_register_device(0, &mx28evk_led_data);
 }
@@ -421,6 +499,6 @@ MACHINE_START(MX28EVK, "Freescale MX28 E
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx28_map_io,
 	.init_irq	= mx28_init_irq,
-	.init_machine	= mx28evk_init,
 	.timer		= &mx28evk_timer,
+	.init_machine	= mx28evk_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-stmp378x_devb.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-stmp378x_devb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-stmp378x_devb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-stmp378x_devb.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
@@ -91,6 +90,7 @@ static void __init stmp378x_dvb_init(voi
 
 	mx23_add_duart();
 	mx23_add_auart0();
+	mx23_add_rtc_stmp3xxx();
 
 	/* power on mmc slot */
 	ret = gpio_request_one(STMP378X_DEVB_MMC0_SLOT_POWER,
@@ -115,6 +115,6 @@ static struct sys_timer stmp378x_dvb_tim
 MACHINE_START(STMP378X, "STMP378X")
 	.map_io		= mx23_map_io,
 	.init_irq	= mx23_init_irq,
-	.init_machine	= stmp378x_dvb_init,
 	.timer		= &stmp378x_dvb_timer,
+	.init_machine	= stmp378x_dvb_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-tx28.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-tx28.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mach-tx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mach-tx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -161,6 +161,7 @@ static void __init tx28_stk5v3_init(void
 	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
 			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
 	mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
+	mx28_add_rtc_stmp3xxx();
 }
 
 static void __init tx28_timer_init(void)
@@ -175,6 +176,6 @@ static struct sys_timer tx28_timer = {
 MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
 	.map_io = mx28_map_io,
 	.init_irq = mx28_init_irq,
-	.init_machine = tx28_stk5v3_init,
 	.timer = &tx28_timer,
+	.init_machine = tx28_stk5v3_init,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/Makefile linux-libre-3.2-gnu1/arch/arm/mach-mxs/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,16 @@
 # Common support
-obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.o
 
 obj-$(CONFIG_MXS_OCOTP) += ocotp.o
 obj-$(CONFIG_PM) += pm.o
 
-obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
-obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
+obj-$(CONFIG_SOC_IMX23) += clock-mx23.o
+obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
 
 obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
 obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
 obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MACH_M28EVK)    += mach-m28evk.o
 obj-$(CONFIG_MODULE_TX28) += module-tx28.o
 obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-mxs/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1 +1 @@
-zreladdr-y := 0x40008000
+zreladdr-y += 0x40008000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License.  You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/common.h>
+#include <mach/iomux.h>
+
+/*
+ * Define the MX23 memory map.
+ */
+static struct map_desc mx23_io_desc[] __initdata = {
+	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX23, IO, MT_DEVICE),
+};
+
+/*
+ * Define the MX28 memory map.
+ */
+static struct map_desc mx28_io_desc[] __initdata = {
+	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX28, IO, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx23_map_io(void)
+{
+	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
+}
+
+void __init mx23_init_irq(void)
+{
+	icoll_init_irq();
+}
+
+void __init mx28_map_io(void)
+{
+	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
+}
+
+void __init mx28_init_irq(void)
+{
+	icoll_init_irq();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm-mx23.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm-mx23.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm-mx23.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm-mx23.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx23.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX23 memory map.
- */
-static struct map_desc mx23_io_desc[] __initdata = {
-	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX23, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx23_map_io(void)
-{
-	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
-}
-
-void __init mx23_init_irq(void)
-{
-	icoll_init_irq();
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm-mx28.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm-mx28.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/mm-mx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/mm-mx28.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx28.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX28 memory map.
- */
-static struct map_desc mx28_io_desc[] __initdata = {
-	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX28, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx28_map_io(void)
-{
-	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
-}
-
-void __init mx28_init_irq(void)
-{
-	icoll_init_irq();
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-mxs/module-tx28.c linux-libre-3.2-gnu1/arch/arm/mach-mxs/module-tx28.c
--- linux-libre-3.1-gnu1/arch/arm/mach-mxs/module-tx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-mxs/module-tx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,11 +66,11 @@ static const iomux_cfg_t tx28_fec1_pads[
 	MX28_PAD_ENET0_CRS__ENET1_RX_EN,
 };
 
-static struct fec_platform_data tx28_fec0_data = {
+static const struct fec_platform_data tx28_fec0_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
-static struct fec_platform_data tx28_fec1_data = {
+static const struct fec_platform_data tx28_fec1_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-netx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00000a00
 		orr	\rv, \rp, #io_p2v(0x00100000)	@ virtual
 		orr	\rp, \rp, #0x00100000		@ physical
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-netx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-netx/include/mach/memory.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x80000000)
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-netx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-    zreladdr-y			:= 0x80008000
+    zreladdr-y			+= 0x80008000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/nxdb500.c linux-libre-3.2-gnu1/arch/arm/mach-netx/nxdb500.c
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/nxdb500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/nxdb500.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@ static void __init nxdb500_init(void)
 }
 
 MACHINE_START(NXDB500, "Hilscher nxdb500")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/nxdkn.c linux-libre-3.2-gnu1/arch/arm/mach-netx/nxdkn.c
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/nxdkn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/nxdkn.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ static void __init nxdkn_init(void)
 }
 
 MACHINE_START(NXDKN, "Hilscher nxdkn")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/nxeb500hmi.c linux-libre-3.2-gnu1/arch/arm/mach-netx/nxeb500hmi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/nxeb500hmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/nxeb500hmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -177,7 +177,7 @@ static void __init nxeb500hmi_init(void)
 }
 
 MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-netx/xc.c linux-libre-3.2-gnu1/arch/arm/mach-netx/xc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-netx/xc.c	2013-05-02 01:32:52.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-netx/xc.c	2013-05-01 23:40:54.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/board-nhk8815.c linux-libre-3.2-gnu1/arch/arm/mach-nomadik/board-nhk8815.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/board-nhk8815.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/board-nhk8815.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 
+#include <plat/gpio-nomadik.h>
 #include <plat/mtu.h>
 
 #include <mach/setup.h>
@@ -276,7 +277,7 @@ static void __init nhk8815_platform_init
 
 MACHINE_START(NOMADIK, "NHK8815")
 	/* Maintainer: ST MicroElectronics */
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= cpu8815_map_io,
 	.init_irq	= cpu8815_init_irq,
 	.timer		= &nomadik_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/cpu-8815.c linux-libre-3.2-gnu1/arch/arm/mach-nomadik/cpu-8815.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/cpu-8815.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/cpu-8815.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,8 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/i2c-8815nhk.c linux-libre-3.2-gnu1/arch/arm/mach-nomadik/i2c-8815nhk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/i2c-8815nhk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/i2c-8815nhk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,8 +3,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
-#include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <plat/gpio-nomadik.h>
 
 /*
  * There are two busses in the 8815NHK.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00100000
 		add	\rp, \rp, #0x000fb000
 		add	\rv, \rp, #0xf0000000	@ virtual base
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,4 @@
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H
 
-#include <plat/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  mach-nomadik/include/mach/memory.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nomadik/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-nomadik/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-nomadik/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nomadik/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/clock.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "clock.h"
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->enabled++ == 0)
-		(clk->enable)(clk, 1);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	WARN_ON(clk->enabled == 0);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->enabled == 0)
-		(clk->enable)(clk, 0);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return 27000000;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void nuc93x_clk_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->cken;
-	unsigned long clken;
-
-	clken = __raw_readl(NUC93X_VA_CLKPWR);
-
-	if (enable)
-		clken |= clocks;
-	else
-		clken &= ~clocks;
-
-	__raw_writel(clken, NUC93X_VA_CLKPWR);
-}
-
-void clks_register(struct clk_lookup *clks, size_t num)
-{
-	int i;
-
-	for (i = 0; i < num; i++)
-		clkdev_add(&clks[i]);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/clock.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.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.
- */
-
-#include <linux/clkdev.h>
-
-void nuc93x_clk_enable(struct clk *clk, int enable);
-void clks_register(struct clk_lookup *clks, size_t num);
-
-struct clk {
-	unsigned long		cken;
-	unsigned int		enabled;
-	void			(*enable)(struct clk *, int enable);
-};
-
-#define DEFINE_CLK(_name, _ctrlbit)			\
-struct clk clk_##_name = {				\
-		.enable	= nuc93x_clk_enable,		\
-		.cken	= (1 << _ctrlbit),		\
-	}
-
-#define DEF_CLKLOOK(_clk, _devname, _conname)		\
-	{						\
-		.clk		= _clk,			\
-		.dev_id		= _devname,		\
-		.con_id		= _conname,		\
-	}
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/cpu.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC93x series cpu common support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ebi.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* Initial IO mappings */
-
-static struct map_desc nuc93x_iodesc[] __initdata = {
-	IODESC_ENT(IRQ),
-	IODESC_ENT(GCR),
-	IODESC_ENT(UART),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(EBI),
-};
-
-/* Initial nuc932 clock declarations. */
-static DEFINE_CLK(audio, 2);
-static DEFINE_CLK(sd, 3);
-static DEFINE_CLK(jpg, 4);
-static DEFINE_CLK(video, 5);
-static DEFINE_CLK(vpost, 6);
-static DEFINE_CLK(2d, 7);
-static DEFINE_CLK(gpu, 8);
-static DEFINE_CLK(gdma, 9);
-static DEFINE_CLK(adc, 10);
-static DEFINE_CLK(uart, 11);
-static DEFINE_CLK(spi, 12);
-static DEFINE_CLK(pwm, 13);
-static DEFINE_CLK(timer, 14);
-static DEFINE_CLK(wdt, 15);
-static DEFINE_CLK(ac97, 16);
-static DEFINE_CLK(i2s, 16);
-static DEFINE_CLK(usbck, 17);
-static DEFINE_CLK(usb48, 18);
-static DEFINE_CLK(usbh, 19);
-static DEFINE_CLK(i2c, 20);
-static DEFINE_CLK(ext, 0);
-
-static struct clk_lookup nuc932_clkregs[] = {
-       DEF_CLKLOOK(&clk_audio, "nuc932-audio", NULL),
-       DEF_CLKLOOK(&clk_sd, "nuc932-sd", NULL),
-       DEF_CLKLOOK(&clk_jpg, "nuc932-jpg", "NULL"),
-       DEF_CLKLOOK(&clk_video, "nuc932-video", "NULL"),
-       DEF_CLKLOOK(&clk_vpost, "nuc932-vpost", NULL),
-       DEF_CLKLOOK(&clk_2d, "nuc932-2d", NULL),
-       DEF_CLKLOOK(&clk_gpu, "nuc932-gpu", NULL),
-       DEF_CLKLOOK(&clk_gdma, "nuc932-gdma", "NULL"),
-       DEF_CLKLOOK(&clk_adc, "nuc932-adc", NULL),
-       DEF_CLKLOOK(&clk_uart, NULL, "uart"),
-       DEF_CLKLOOK(&clk_spi, "nuc932-spi", NULL),
-       DEF_CLKLOOK(&clk_pwm, "nuc932-pwm", NULL),
-       DEF_CLKLOOK(&clk_timer, NULL, "timer"),
-       DEF_CLKLOOK(&clk_wdt, "nuc932-wdt", NULL),
-       DEF_CLKLOOK(&clk_ac97, "nuc932-ac97", NULL),
-       DEF_CLKLOOK(&clk_i2s, "nuc932-i2s", NULL),
-       DEF_CLKLOOK(&clk_usbck, "nuc932-usbck", NULL),
-       DEF_CLKLOOK(&clk_usb48, "nuc932-usb48", NULL),
-       DEF_CLKLOOK(&clk_usbh, "nuc932-usbh", NULL),
-       DEF_CLKLOOK(&clk_i2c, "nuc932-i2c", NULL),
-       DEF_CLKLOOK(&clk_ext, NULL, "ext"),
-};
-
-/* Initial serial platform data */
-
-struct plat_serial8250_port nuc93x_uart_data[] = {
-	NUC93X_8250PORT(UART0),
-	{},
-};
-
-struct platform_device nuc93x_serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= nuc93x_uart_data,
-	},
-};
-
-/*Init NUC93x evb io*/
-
-void __init nuc93x_map_io(struct map_desc *mach_desc, int mach_size)
-{
-	unsigned long idcode = 0x0;
-
-	iotable_init(mach_desc, mach_size);
-	iotable_init(nuc93x_iodesc, ARRAY_SIZE(nuc93x_iodesc));
-
-	idcode = __raw_readl(NUC93XPDID);
-	if (idcode == NUC932_CPUID)
-		printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode);
-	else
-		printk(KERN_ERR "CPU type detect error!\n");
-
-}
-
-/*Init NUC93x clock*/
-
-void __init nuc93x_init_clocks(void)
-{
-	clks_register(nuc932_clkregs, ARRAY_SIZE(nuc932_clkregs));
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/cpu.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/cpu.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/cpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/cpu.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Header file for NUC93X CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.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
- * published by the Free Software Foundation.
- *
- */
-
-#define IODESC_ENT(y)					\
-{							\
-	.virtual = (unsigned long)NUC93X_VA_##y,	\
-	.pfn     = __phys_to_pfn(NUC93X_PA_##y),	\
-	.length  = NUC93X_SZ_##y,			\
-	.type    = MT_DEVICE,				\
-}
-
-#define NUC93X_8250PORT(name)					\
-{								\
-	.membase	= name##_BA,				\
-	.mapbase	= name##_PA,				\
-	.irq		= IRQ_##name,				\
-	.uartclk	= 57139200,				\
-	.regshift	= 2,					\
-	.iotype		= UPIO_MEM,				\
-	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
-}
-
-/*Cpu identifier register*/
-
-#define NUC93XPDID	NUC93X_VA_GCR
-#define NUC932_CPUID	0x29550091
-
-/* extern file from cpu.c */
-
-extern void nuc93x_clock_source(struct device *dev, unsigned char *src);
-extern void nuc93x_init_clocks(void);
-extern void nuc93x_map_io(struct map_desc *mach_desc, int mach_size);
-extern void nuc93x_board_init(struct platform_device **device, int size);
-extern struct platform_device nuc93x_serial_device;
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/dev.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/dev.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/dev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/dev.c
- *
- * Copyright (C) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach-types.h>
-
-#include "cpu.h"
-
-/*Here should be your evb resourse,such as LCD*/
-
-static struct platform_device *nuc93x_public_dev[] __initdata = {
-	&nuc93x_serial_device,
-};
-
-/* Provide adding specific CPU platform devices API */
-
-void __init nuc93x_board_init(struct platform_device **device, int size)
-{
-	platform_add_devices(device, size);
-	platform_add_devices(nuc93x_public_dev, ARRAY_SIZE(nuc93x_public_dev));
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/entry-macro.S
- *
- * 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 <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-	.macro  get_irqnr_preamble, base, tmp
-	.endm
-
-	.macro  arch_ret_to_user, tmp1, tmp2
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		mov	\base, #AIC_BA
-
-		ldr	\irqnr, [ \base, #AIC_IPER]
-		ldr	\irqnr, [ \base, #AIC_ISNR]
-		cmp	\irqnr, #0
-
-	.endm
-
-	/* currently don't need an disable_fiq macro */
-
-	.macro	disable_fiq
-	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/hardware.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/io.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT	0xffffffff
-
-/*
- * 1:1 mapping for ioremapped regions.
- */
-
-#define __mem_pci(a)	(a)
-#define __io(a)		__typesafe_io(a)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,59 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/irqs.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define NUC93X_IRQ(x)	(x)
-
-/* Main cpu interrupts */
-
-#define IRQ_WDT		NUC93X_IRQ(1)
-#define IRQ_IRQ0	NUC93X_IRQ(2)
-#define IRQ_IRQ1	NUC93X_IRQ(3)
-#define IRQ_IRQ2	NUC93X_IRQ(4)
-#define IRQ_IRQ3	NUC93X_IRQ(5)
-#define IRQ_USBH	NUC93X_IRQ(6)
-#define IRQ_APU		NUC93X_IRQ(7)
-#define IRQ_VPOST	NUC93X_IRQ(8)
-#define IRQ_ADC		NUC93X_IRQ(9)
-#define IRQ_UART0	NUC93X_IRQ(10)
-#define IRQ_TIMER0	NUC93X_IRQ(11)
-#define IRQ_GPU0	NUC93X_IRQ(12)
-#define IRQ_GPU1	NUC93X_IRQ(13)
-#define IRQ_GPU2	NUC93X_IRQ(14)
-#define IRQ_GPU3	NUC93X_IRQ(15)
-#define IRQ_GPU4	NUC93X_IRQ(16)
-#define IRQ_VIN		NUC93X_IRQ(17)
-#define IRQ_USBD	NUC93X_IRQ(18)
-#define IRQ_VRAMLD	NUC93X_IRQ(19)
-#define IRQ_GDMA0	NUC93X_IRQ(20)
-#define IRQ_GDMA1	NUC93X_IRQ(21)
-#define IRQ_SDIO	NUC93X_IRQ(22)
-#define IRQ_FMI		NUC93X_IRQ(22)
-#define IRQ_JPEG	NUC93X_IRQ(23)
-#define IRQ_SPI0	NUC93X_IRQ(24)
-#define IRQ_SPI1	NUC93X_IRQ(25)
-#define IRQ_RTC		NUC93X_IRQ(26)
-#define IRQ_PWM0	NUC93X_IRQ(27)
-#define IRQ_PWM1	NUC93X_IRQ(28)
-#define IRQ_PWM2	NUC93X_IRQ(29)
-#define IRQ_PWM3	NUC93X_IRQ(30)
-#define IRQ_I2SAC97	NUC93X_IRQ(31)
-#define IRQ_CAP0	IRQ_PWM0
-#define IRQ_CAP1	IRQ_PWM1
-#define IRQ_CAP2	IRQ_PWM2
-#define IRQ_CAP3	IRQ_PWM3
-#define NR_IRQS		(IRQ_I2SAC97 + 1)
-
-#endif /* __ASM_ARCH_IRQ_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/map.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H
-
-#define MAP_OFFSET	(0xfff00000)
-#define CLK_OFFSET	(0x10)
-
-#ifndef __ASSEMBLY__
-#define NUC93X_ADDR(x)	((void __iomem *)(0xF0000000 + ((x)&(~MAP_OFFSET))))
-#else
-#define NUC93X_ADDR(x)	(0xF0000000 + ((x)&(~MAP_OFFSET)))
-#endif
-
- /*
-  * nuc932 hardware register definition
-  */
-
-#define NUC93X_PA_IRQ		(0xFFF83000)
-#define NUC93X_PA_GCR		(0xFFF00000)
-#define NUC93X_PA_EBI		(0xFFF01000)
-#define NUC93X_PA_UART		(0xFFF80000)
-#define NUC93X_PA_TIMER		(0xFFF81000)
-#define NUC93X_PA_GPIO		(0xFFF84000)
-#define NUC93X_PA_GDMA		(0xFFF03000)
-#define NUC93X_PA_USBHOST	(0xFFF0d000)
-#define NUC93X_PA_I2C		(0xFFF89000)
-#define NUC93X_PA_LCD		(0xFFF06000)
-#define NUC93X_PA_GE		(0xFFF05000)
-#define NUC93X_PA_ADC		(0xFFF85000)
-#define NUC93X_PA_RTC		(0xFFF87000)
-#define NUC93X_PA_PWM		(0xFFF82000)
-#define NUC93X_PA_ACTL		(0xFFF0a000)
-#define NUC93X_PA_USBDEV	(0xFFF0C000)
-#define NUC93X_PA_JEPEG		(0xFFF0e000)
-#define NUC93X_PA_CACHE_T	(0xFFF60000)
-#define NUC93X_PA_VRAM		(0xFFF0b000)
-#define NUC93X_PA_DMAC		(0xFFF09000)
-#define NUC93X_PA_I2SM		(0xFFF08000)
-#define NUC93X_PA_CACHE		(0xFFF02000)
-#define NUC93X_PA_GPU		(0xFFF04000)
-#define NUC93X_PA_VIDEOIN	(0xFFF07000)
-#define NUC93X_PA_SPI0		(0xFFF86000)
-#define NUC93X_PA_SPI1		(0xFFF88000)
-
- /*
-  * nuc932 virtual address mapping.
-  * interrupt controller is the first thing we put in, to make
-  * the assembly code for the irq detection easier
-  */
-
-#define NUC93X_VA_IRQ		NUC93X_ADDR(0x00000000)
-#define NUC93X_SZ_IRQ		SZ_4K
-
-#define NUC93X_VA_GCR		NUC93X_ADDR(NUC93X_PA_IRQ)
-#define NUC93X_VA_CLKPWR	(NUC93X_VA_GCR+CLK_OFFSET)
-#define NUC93X_SZ_GCR		SZ_4K
-
-/* EBI management */
-
-#define NUC93X_VA_EBI		NUC93X_ADDR(NUC93X_PA_EBI)
-#define NUC93X_SZ_EBI		SZ_4K
-
-/* UARTs */
-
-#define NUC93X_VA_UART		NUC93X_ADDR(NUC93X_PA_UART)
-#define NUC93X_SZ_UART		SZ_4K
-
-/* Timers */
-
-#define NUC93X_VA_TIMER	NUC93X_ADDR(NUC93X_PA_TIMER)
-#define NUC93X_SZ_TIMER	SZ_4K
-
-/* GPIO ports */
-
-#define NUC93X_VA_GPIO		NUC93X_ADDR(NUC93X_PA_GPIO)
-#define NUC93X_SZ_GPIO		SZ_4K
-
-/* GDMA control */
-
-#define NUC93X_VA_GDMA		NUC93X_ADDR(NUC93X_PA_GDMA)
-#define NUC93X_SZ_GDMA		SZ_4K
-
-/* I2C hardware controller */
-
-#define NUC93X_VA_I2C		NUC93X_ADDR(NUC93X_PA_I2C)
-#define NUC93X_SZ_I2C		SZ_4K
-
-/* LCD controller*/
-
-#define NUC93X_VA_LCD		NUC93X_ADDR(NUC93X_PA_LCD)
-#define NUC93X_SZ_LCD		SZ_4K
-
-/* 2D controller*/
-
-#define NUC93X_VA_GE		NUC93X_ADDR(NUC93X_PA_GE)
-#define NUC93X_SZ_GE		SZ_4K
-
-/* ADC */
-
-#define NUC93X_VA_ADC		NUC93X_ADDR(NUC93X_PA_ADC)
-#define NUC93X_SZ_ADC		SZ_4K
-
-/* RTC */
-
-#define NUC93X_VA_RTC		NUC93X_ADDR(NUC93X_PA_RTC)
-#define NUC93X_SZ_RTC		SZ_4K
-
-/* Pulse Width Modulation(PWM) Registers */
-
-#define NUC93X_VA_PWM		NUC93X_ADDR(NUC93X_PA_PWM)
-#define NUC93X_SZ_PWM		SZ_4K
-
-/* Audio Controller controller */
-
-#define NUC93X_VA_ACTL		NUC93X_ADDR(NUC93X_PA_ACTL)
-#define NUC93X_SZ_ACTL		SZ_4K
-
-/* USB Device port */
-
-#define NUC93X_VA_USBDEV	NUC93X_ADDR(NUC93X_PA_USBDEV)
-#define NUC93X_SZ_USBDEV	SZ_4K
-
-/* USB host controller*/
-#define NUC93X_VA_USBHOST	NUC93X_ADDR(NUC93X_PA_USBHOST)
-#define NUC93X_SZ_USBHOST	SZ_4K
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-clock.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H
-
-/* Clock Control Registers  */
-#define CLK_BA		NUC93X_VA_CLKPWR
-#define REG_CLKEN	(CLK_BA + 0x00)
-#define REG_CLKSEL	(CLK_BA + 0x04)
-#define REG_CLKDIV	(CLK_BA + 0x08)
-#define REG_PLLCON0	(CLK_BA + 0x0C)
-#define REG_PLLCON1	(CLK_BA + 0x10)
-#define REG_PMCON	(CLK_BA + 0x14)
-#define REG_IRQWAKECON	(CLK_BA + 0x18)
-#define REG_IRQWAKEFLAG	(CLK_BA + 0x1C)
-#define REG_IPSRST	(CLK_BA + 0x20)
-#define REG_CLKEN1	(CLK_BA + 0x24)
-#define REG_CLKDIV1	(CLK_BA + 0x28)
-
-/* Define PLL freq setting */
-#define PLL_DISABLE		0x12B63
-#define	PLL_66MHZ		0x2B63
-#define	PLL_100MHZ		0x4F64
-#define PLL_120MHZ		0x4F63
-#define	PLL_166MHZ		0x4124
-#define	PLL_200MHZ		0x4F24
-
-/* Define AHB:CPUFREQ ratio */
-#define	AHB_CPUCLK_1_1		0x00
-#define	AHB_CPUCLK_1_2		0x01
-#define	AHB_CPUCLK_1_4		0x02
-#define	AHB_CPUCLK_1_8		0x03
-
-/* Define APB:AHB ratio */
-#define APB_AHB_1_2		0x01
-#define APB_AHB_1_4		0x02
-#define APB_AHB_1_8		0x03
-
-/* Define clock skew */
-#define DEFAULTSKEW		0x48
-
-#endif /*  __ASM_ARCH_REGS_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-ebi.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-ebi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-ebi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-ebi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_EBI_H
-#define __ASM_ARCH_REGS_EBI_H
-
-/* EBI Control Registers */
-
-#define EBI_BA		NUC93X_VA_EBI
-#define REG_EBICON	(EBI_BA + 0x00)
-#define REG_ROMCON	(EBI_BA + 0x04)
-#define REG_SDCONF0	(EBI_BA + 0x08)
-#define REG_SDCONF1	(EBI_BA + 0x0C)
-#define REG_SDTIME0	(EBI_BA + 0x10)
-#define REG_SDTIME1	(EBI_BA + 0x14)
-#define REG_EXT0CON	(EBI_BA + 0x18)
-#define REG_EXT1CON	(EBI_BA + 0x1C)
-#define REG_EXT2CON	(EBI_BA + 0x20)
-#define REG_EXT3CON	(EBI_BA + 0x24)
-#define REG_EXT4CON	(EBI_BA + 0x28)
-#define REG_CKSKEW	(EBI_BA + 0x2C)
-
-#endif /*  __ASM_ARCH_REGS_EBI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-irq.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-irq.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-irq.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 ___ASM_ARCH_REGS_IRQ_H
-#define ___ASM_ARCH_REGS_IRQ_H
-
-/* Advance Interrupt Controller (AIC) Registers */
-
-#define AIC_BA    		NUC93X_VA_IRQ
-
-#define REG_AIC_IRQSC		(AIC_BA+0x80)
-#define REG_AIC_GEN		(AIC_BA+0x84)
-#define REG_AIC_GASR		(AIC_BA+0x88)
-#define REG_AIC_GSCR		(AIC_BA+0x8C)
-#define REG_AIC_IRSR		(AIC_BA+0x100)
-#define REG_AIC_IASR		(AIC_BA+0x104)
-#define REG_AIC_ISR		(AIC_BA+0x108)
-#define REG_AIC_IPER		(AIC_BA+0x10C)
-#define REG_AIC_ISNR		(AIC_BA+0x110)
-#define REG_AIC_IMR		(AIC_BA+0x114)
-#define REG_AIC_OISR		(AIC_BA+0x118)
-#define REG_AIC_MECR		(AIC_BA+0x120)
-#define REG_AIC_MDCR		(AIC_BA+0x124)
-#define REG_AIC_SSCR		(AIC_BA+0x128)
-#define REG_AIC_SCCR		(AIC_BA+0x12C)
-#define REG_AIC_EOSCR		(AIC_BA+0x130)
-#define AIC_IPER		(0x10C)
-#define AIC_ISNR		(0x110)
-
-#endif /* ___ASM_ARCH_REGS_IRQ_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-serial.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-serial.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-serial.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-serial.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define UART0_BA	NUC93X_VA_UART
-#define UART1_BA	(NUC93X_VA_UART+0x100)
-
-#define UART0_PA	NUC93X_PA_UART
-#define UART1_PA	(NUC93X_PA_UART+0x100)
-
-
-#ifndef __ASSEMBLY__
-
-struct nuc93x_uart_clksrc {
-	const char	*name;
-	unsigned int	divisor;
-	unsigned int	min_baud;
-	unsigned int	max_baud;
-};
-
-struct nuc93x_uartcfg {
-	unsigned char	hwport;
-	unsigned char	unused;
-	unsigned short	flags;
-	unsigned long	uart_flags;
-
-	unsigned long	ucon;
-	unsigned long	ulcon;
-	unsigned long	ufcon;
-
-	struct nuc93x_uart_clksrc *clocks;
-	unsigned int	clocks_size;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-timer.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-timer.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/regs-timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/regs-timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-timer.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.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 __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-/* Timer Registers */
-
-#define TMR_BA			NUC93X_VA_TIMER
-#define REG_TCSR0		(TMR_BA+0x00)
-#define REG_TICR0		(TMR_BA+0x08)
-#define REG_TDR0		(TMR_BA+0x10)
-#define REG_TISR		(TMR_BA+0x18)
-#define REG_WTCR		(TMR_BA+0x1C)
-
-#endif /*  __ASM_ARCH_REGS_TIMER_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/machnuc93x/include/mach/system.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system.h
- *
- * 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 <asm/proc-fns.h>
-
-static void arch_idle(void)
-{
-}
-
-static void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/timex.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE Now, I don't use it. */
-
-#define CLOCK_TICK_RATE 27000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/uncompress.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h
- *
- * 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 __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-/* Defines for UART registers */
-
-#include <mach/regs-serial.h>
-#include <mach/map.h>
-#include <linux/serial_reg.h>
-
-#define arch_decomp_wdog()
-
-#define TX_DONE	(UART_LSR_TEMT | UART_LSR_THRE)
-static u32 * const uart_base = (u32 *)UART0_PA;
-
-static void putc(int ch)
-{
-	/* Check THRE and TEMT bits before we transmit the character.
-	 */
-	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
-		barrier();
-
-	*uart_base = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif/* __ASM_NUC93X_UNCOMPRESS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/vmalloc.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/vmalloc.h
- *
- * 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 __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	  0xE0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/irq.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/irq.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-static void nuc93x_irq_mask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MDCR);
-}
-
-/*
- * By the w90p910 spec,any irq,only write 1
- * to REG_AIC_EOSCR for ACK
- */
-
-static void nuc93x_irq_ack(struct irq_data *d)
-{
-	__raw_writel(0x01, REG_AIC_EOSCR);
-}
-
-static void nuc93x_irq_unmask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MECR);
-
-}
-
-static struct irq_chip nuc93x_irq_chip = {
-	.irq_ack	= nuc93x_irq_ack,
-	.irq_mask	= nuc93x_irq_mask,
-	.irq_unmask	= nuc93x_irq_unmask,
-};
-
-void __init nuc93x_init_irq(void)
-{
-	int irqno;
-
-	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
-
-	for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
-		irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-if ARCH_NUC93X
-
-config CPU_NUC932
-	bool
-	help
-	  Support for NUC932 of Nuvoton NUC93X CPUs.
-
-menu "NUC932 Machines"
-
-config MACH_NUC932EVB
-	bool "Nuvoton NUC932 Evaluation Board"
-	default y
-	select CPU_NUC932
-	help
-	   Say Y here if you are using the Nuvoton NUC932EVB
-
-endmenu
-
-endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/mach-nuc932evb.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/mach-nuc932evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/mach-nuc932evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/mach-nuc932evb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc910evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc932.h"
-
-static void __init nuc932evb_map_io(void)
-{
-	nuc932_map_io();
-	nuc932_init_clocks();
-	nuc932_init_uartclk();
-}
-
-static void __init nuc932evb_init(void)
-{
-	nuc932_board_init();
-}
-
-MACHINE_START(NUC932EVB, "NUC932EVB")
-	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
-	.map_io		= nuc932evb_map_io,
-	.init_irq	= nuc93x_init_irq,
-	.init_machine	= nuc932evb_init,
-	.timer		= &nuc93x_timer,
-MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Makefile linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y				:= irq.o time.o dev.o cpu.o clock.o
-# NUC932 CPU support files
-
-obj-$(CONFIG_CPU_NUC932)	+= nuc932.o
-
-# machine support
-
-obj-$(CONFIG_MACH_NUC932EVB)	+= mach-nuc932evb.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/nuc932.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/nuc932.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/nuc932.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/nuc932.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/nuc932.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC932 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc932_dev[] __initdata = {
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc932evb_iodesc[] __initdata = {
-};
-
-/*Init NUC932 evb io*/
-
-void __init nuc932_map_io(void)
-{
-	nuc93x_map_io(nuc932evb_iodesc, ARRAY_SIZE(nuc932evb_iodesc));
-}
-
-/*Init NUC932 clock*/
-
-void __init nuc932_init_clocks(void)
-{
-	nuc93x_init_clocks();
-}
-
-/*enable NUC932 uart clock*/
-
-void __init nuc932_init_uartclk(void)
-{
-	struct clk *ck_uart = clk_get(NULL, "uart");
-	BUG_ON(IS_ERR(ck_uart));
-
-	clk_enable(ck_uart);
-}
-
-/*Init NUC932 board info*/
-
-void __init nuc932_board_init(void)
-{
-	nuc93x_board_init(nuc932_dev, ARRAY_SIZE(nuc932_dev));
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/nuc932.h linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/nuc932.h
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/nuc932.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/nuc932.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/nuc932.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC93x CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.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
- * published by the Free Software Foundation.
- *
- */
-
-struct map_desc;
-struct sys_timer;
-
-/* core initialisation functions */
-
-extern void nuc93x_init_irq(void);
-extern struct sys_timer nuc93x_timer;
-
-/* extern file from nuc932.c */
-
-extern void nuc932_board_init(void);
-extern void nuc932_init_clocks(void);
-extern void nuc932_map_io(void);
-extern void nuc932_init_uartclk(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/time.c linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/time.c
--- linux-libre-3.1-gnu1/arch/arm/mach-nuc93x/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-nuc93x/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/time.c
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.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/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#include <mach/system.h>
-#include <mach/map.h>
-#include <mach/regs-timer.h>
-
-#define RESETINT	0x01
-#define PERIOD		(0x01 << 27)
-#define ONESHOT		(0x00 << 27)
-#define COUNTEN		(0x01 << 30)
-#define INTEN		(0x01 << 29)
-
-#define TICKS_PER_SEC	100
-#define PRESCALE	0x63 /* Divider = prescale + 1 */
-
-unsigned int timer0_load;
-
-static unsigned long nuc93x_gettimeoffset(void)
-{
-	return 0;
-}
-
-/*IRQ handler for the timer*/
-
-static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	__raw_writel(0x01, REG_TISR); /* clear TIF0 */
-	return IRQ_HANDLED;
-}
-
-static struct irqaction nuc93x_timer_irq = {
-	.name		= "nuc93x Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= nuc93x_timer_interrupt,
-};
-
-/*Set up timer reg.*/
-
-static void nuc93x_timer_setup(void)
-{
-	struct clk *ck_ext = clk_get(NULL, "ext");
-	struct clk *ck_timer = clk_get(NULL, "timer");
-	unsigned int rate, val = 0;
-
-	BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer));
-
-	clk_enable(ck_timer);
-	rate = clk_get_rate(ck_ext);
-	clk_put(ck_ext);
-	rate = rate / (PRESCALE + 0x01);
-
-	 /* set a known state */
-	__raw_writel(0x00, REG_TCSR0);
-	__raw_writel(RESETINT, REG_TISR);
-
-	timer0_load = (rate / TICKS_PER_SEC);
-	__raw_writel(timer0_load, REG_TICR0);
-
-	val |= (PERIOD | COUNTEN | INTEN | PRESCALE);;
-	__raw_writel(val, REG_TCSR0);
-
-}
-
-static void __init nuc93x_timer_init(void)
-{
-	nuc93x_timer_setup();
-	setup_irq(IRQ_TIMER0, &nuc93x_timer_irq);
-}
-
-struct sys_timer nuc93x_timer = {
-	.init		= nuc93x_timer_init,
-	.offset		= nuc93x_gettimeoffset,
-	.resume		= nuc93x_timer_setup
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-ams-delta.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-ams-delta.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-ams-delta.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-ams-delta.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -19,6 +19,7 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/export.h>
 
 #include <media/soc_camera.h>
 
@@ -30,7 +31,6 @@
 
 #include <plat/io.h>
 #include <plat/board-ams-delta.h>
-#include <mach/gpio.h>
 #include <plat/keypad.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -135,12 +135,6 @@ void ams_delta_latch2_write(u16 mask, u1
 	*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
 }
 
-static void __init ams_delta_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct map_desc ams_delta_io_desc[] __initdata = {
 	/* AMS_DELTA_LATCH1 */
 	{
@@ -308,8 +302,6 @@ static void __init ams_delta_init(void)
 	omap_cfg_reg(J19_1610_CAM_D6);
 	omap_cfg_reg(J18_1610_CAM_D7);
 
-	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
-
 	omap_board_config = ams_delta_config;
 	omap_board_config_size = ARRAY_SIZE(ams_delta_config);
 	omap_serial_init();
@@ -381,15 +373,17 @@ arch_initcall(ams_delta_modem_init);
 
 static void __init ams_delta_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
+	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 }
 
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= ams_delta_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= ams_delta_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= ams_delta_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-fsample.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-fsample.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-fsample.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-fsample.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -28,7 +28,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/flash.h>
 #include <plat/fpga.h>
@@ -297,6 +296,39 @@ static struct omap_board_config_kernel f
 
 static void __init omap_fsample_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+			OMAP7XX_IO_CONF_9);
+
 	fsample_init_smc91x();
 
 	if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -326,12 +358,6 @@ static void __init omap_fsample_init(voi
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_fsample_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_fsample_io_desc[] __initdata = {
 	{
@@ -350,49 +376,18 @@ static struct map_desc omap_fsample_io_d
 
 static void __init omap_fsample_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 	iotable_init(omap_fsample_io_desc,
 		     ARRAY_SIZE(omap_fsample_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap_fsample_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_fsample_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_fsample_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-generic.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-generic.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -22,18 +22,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
 
-static void __init omap_generic_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* assume no Mini-AB port */
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -87,17 +80,13 @@ static void __init omap_generic_init(voi
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_generic_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	/* Maintainer: Tony Lindgren <tony@atomide.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= omap_generic_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_generic_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h2.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h2.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -32,7 +32,6 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -373,12 +372,6 @@ static struct i2c_board_info __initdata
 	},
 };
 
-static void __init h2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config h2_usb_config __initdata = {
 	/* usb1 has a Mini-AB port and external isp1301 transceiver */
 	.otg		= 2,
@@ -454,17 +447,13 @@ static void __init h2_init(void)
 	h2_mmc_init();
 }
 
-static void __init h2_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H2, "TI-H2")
 	/* Maintainer: Imre Deak <imre.deak@nokia.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= h2_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h2-mmc.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h2-mmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h2-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h2-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,13 +11,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <linux/i2c/tps65010.h>
 
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 
 #include "board-h2.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h3.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h3.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/major.h>
@@ -34,7 +34,6 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -436,23 +435,13 @@ static void __init h3_init(void)
 	h3_mmc_init();
 }
 
-static void __init h3_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init h3_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	/* Maintainer: Texas Instruments, Inc. */
-	.boot_params	= 0x10000100,
-	.map_io		= h3_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h3_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h3_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h3-mmc.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h3-mmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-h3-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-h3-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,13 +11,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <linux/i2c/tps65010.h>
 
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 
 #include "board-h3.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-htcherald.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-htcherald.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-htcherald.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-htcherald.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
  * 02110-1301, USA.
  *
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -500,7 +499,7 @@ static void __init htcherald_lcd_init(vo
 
 static void __init htcherald_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 
 	/*
 	 * The LCD panel must be disabled and DMA turned off here, as doing
@@ -601,20 +600,14 @@ static void __init htcherald_init(void)
 #endif
 }
 
-static void __init htcherald_init_irq(void)
-{
-	printk(KERN_INFO "htcherald_init_irq.\n");
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 MACHINE_START(HERALD, "HTC Herald")
 	/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
 	/* Maintainer: wing-linux.sourceforge.net */
-	.boot_params    = 0x10000100,
+	.atag_offset    = 0x100,
 	.map_io         = htcherald_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq       = htcherald_init_irq,
+	.init_irq       = omap1_init_irq,
 	.init_machine   = htcherald_init,
 	.timer          = &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-innovator.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-innovator.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-innovator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-innovator.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -34,7 +34,6 @@
 #include <plat/mux.h>
 #include <plat/flash.h>
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 #include <plat/tc.h>
 #include <plat/usb.h>
 #include <plat/keypad.h>
@@ -289,12 +288,6 @@ static void __init innovator_init_smc91x
 	}
 }
 
-static void __init innovator_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_usb_config innovator1510_usb_config __initdata = {
 	/* for bundled non-standard host and peripheral cables */
@@ -439,30 +432,32 @@ static void __init innovator_init(void)
 	innovator_mmc_init();
 }
 
+/*
+ * REVISIT: Assume 15xx for now, we don't want to do revision check
+ * until later on. The right way to fix this is to set up a different
+ * machine_id for 16xx Innovator, or use device tree.
+ */
 static void __init innovator_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
-		iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
-		udelay(10);	/* Delay needed for FPGA */
+	iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
+	udelay(10);	/* Delay needed for FPGA */
 
-		/* Dump the Innovator FPGA rev early - useful info for support. */
-		printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
-		       fpga_read(OMAP1510_FPGA_REV_HIGH),
-		       fpga_read(OMAP1510_FPGA_REV_LOW),
-		       fpga_read(OMAP1510_FPGA_BOARD_REV));
-	}
-#endif
+	/* Dump the Innovator FPGA rev early - useful info for support. */
+	pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
+			fpga_read(OMAP1510_FPGA_REV_HIGH),
+			fpga_read(OMAP1510_FPGA_REV_LOW),
+			fpga_read(OMAP1510_FPGA_BOARD_REV));
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= innovator_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= innovator_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= innovator_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-nokia770.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-nokia770.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-nokia770.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-nokia770.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -26,7 +26,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
 #include <plat/board.h>
@@ -39,21 +38,6 @@
 
 #define ADS7846_PENDOWN_GPIO	15
 
-static void __init omap_nokia770_init_irq(void)
-{
-	/* On Nokia 770, the SleepX signal is masked with an
-	 * MPUIO line by default.  It has to be unmasked for it
-	 * to become functional */
-
-	/* SleepX mask direction */
-	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
-	/* Unmask SleepX signal */
-	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int nokia770_keymap[] = {
 	KEY(1, 0, GROUP_0 | KEY_UP),
 	KEY(2, 0, GROUP_1 | KEY_F5),
@@ -246,6 +230,15 @@ static inline void nokia770_mmc_init(voi
 
 static void __init omap_nokia770_init(void)
 {
+	/* On Nokia 770, the SleepX signal is masked with an
+	 * MPUIO line by default.  It has to be unmasked for it
+	 * to become functional */
+
+	/* SleepX mask direction */
+	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+	/* Unmask SleepX signal */
+	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
 	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
 	spi_register_board_info(nokia770_spi_board_info,
 				ARRAY_SIZE(nokia770_spi_board_info));
@@ -258,16 +251,12 @@ static void __init omap_nokia770_init(vo
 	nokia770_mmc_init();
 }
 
-static void __init omap_nokia770_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(NOKIA770, "Nokia 770")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_nokia770_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_nokia770_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_nokia770_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-osk.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-osk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-osk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-osk.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -42,7 +42,6 @@
 #include <linux/i2c/tps65010.h>
 
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -279,12 +278,6 @@ static void __init osk_init_cf(void)
 	irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
 }
 
-static void __init osk_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config osk_usb_config __initdata = {
 	/* has usb host connector (A) ... for development it can also
 	 * be used, with a NONSTANDARD gender-bending cable/dongle, as
@@ -576,17 +569,13 @@ static void __init osk_init(void)
 	osk_mistral_init();
 }
 
-static void __init osk_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_OSK, "TI-OSK")
 	/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= osk_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= osk_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= osk_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmte.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmte.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmte.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmte.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -33,7 +33,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -59,12 +58,6 @@
 #define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
 #define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
 
-static void __init omap_palmte_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmte_keymap[] = {
 	KEY(0, 0, KEY_F1),		/* Calendar */
 	KEY(1, 0, KEY_F2),		/* Contacts */
@@ -269,16 +262,12 @@ static void __init omap_palmte_init(void
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmte_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmte_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmte_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmte_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmtt.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmtt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -30,7 +31,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/led.h>
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -263,12 +263,6 @@ static struct spi_board_info __initdata
 	}
 };
 
-static void __init omap_palmtt_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config palmtt_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0,
@@ -315,16 +309,12 @@ static void __init omap_palmtt_init(void
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmtt_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmtt_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmtt_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmtt_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmz71.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmz71.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-palmz71.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-palmz71.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -32,7 +33,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -42,7 +42,6 @@
 #include <plat/irda.h>
 #include <plat/keypad.h>
 #include <plat/common.h>
-#include <plat/omap-alsa.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -57,13 +56,6 @@
 #define PALMZ71_SLIDER_GPIO	OMAP_MPUIO(3)
 #define PALMZ71_MMC_IN_GPIO	OMAP_MPUIO(4)
 
-static void __init
-omap_palmz71_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmz71_keymap[] = {
 	KEY(0, 0, KEY_F1),
 	KEY(1, 0, KEY_F2),
@@ -334,17 +326,12 @@ omap_palmz71_init(void)
 	palmz71_gpio_setup(0);
 }
 
-static void __init
-omap_palmz71_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmz71_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmz71_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmz71_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-perseus2.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-perseus2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-perseus2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-perseus2.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -28,7 +28,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/fpga.h>
 #include <plat/flash.h>
@@ -265,6 +264,39 @@ static void __init perseus2_init_smc91x(
 
 static void __init omap_perseus2_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+				OMAP7XX_IO_CONF_9);
+
 	perseus2_init_smc91x();
 
 	if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -294,11 +326,6 @@ static void __init omap_perseus2_init(vo
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_perseus2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
 	{
@@ -311,49 +338,18 @@ static struct map_desc omap_perseus2_io_
 
 static void __init omap_perseus2_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 	iotable_init(omap_perseus2_io_desc,
 		     ARRAY_SIZE(omap_perseus2_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	/* Maintainer: Kevin Hilman <kjh@hilman.org> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap_perseus2_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_perseus2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_perseus2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-sx1.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-sx1.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-sx1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-sx1.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -26,13 +26,13 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/dma.h>
@@ -407,24 +407,13 @@ static void __init omap_sx1_init(void)
 	gpio_direction_output(11, 0);	/*A_SWITCH = 0 */
 	gpio_direction_output(15, 0);	/*A_USB_ON = 0 */
 }
-/*----------------------------------------*/
-static void __init omap_sx1_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-/*----------------------------------------*/
-
-static void __init omap_sx1_map_io(void)
-{
-	omap1_map_common_io();
-}
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_sx1_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_sx1_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_sx1_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-sx1-mmc.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-sx1-mmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-sx1-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-sx1-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,11 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 #include <plat/board-sx1.h>
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-voiceblue.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-voiceblue.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/board-voiceblue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/board-voiceblue.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -24,6 +25,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/smc91x.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/system.h>
@@ -33,7 +35,6 @@
 
 #include <plat/board-voiceblue.h>
 #include <plat/common.h>
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/tc.h>
@@ -159,17 +160,6 @@ static struct omap_usb_config voiceblue_
 static struct omap_board_config_kernel voiceblue_config[] = {
 };
 
-static void __init voiceblue_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init voiceblue_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 #define MACHINE_PANICED		1
 #define MACHINE_REBOOTING	2
 #define MACHINE_REBOOT		4
@@ -301,10 +291,11 @@ static void __init voiceblue_init(void)
 
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
-	.boot_params	= 0x10000100,
-	.map_io		= voiceblue_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= voiceblue_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= voiceblue_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/clock_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/clock_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/clock_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/clock_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 
 #include <asm/mach-types.h>  /* for machine_is_* */
@@ -767,6 +769,15 @@ static struct clk_functions omap1_clk_fu
 	.clk_disable_unused	= omap1_clk_disable_unused,
 };
 
+static void __init omap1_show_rates(void)
+{
+	pr_notice("Clocking rate (xtal/DPLL1/MPU): "
+			"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+		ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+		ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+		arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+}
+
 int __init omap1_clk_init(void)
 {
 	struct omap_clk *c;
@@ -835,9 +846,12 @@ int __init omap1_clk_init(void)
 	/* We want to be in syncronous scalable mode */
 	omap_writew(0x1000, ARM_SYSST);
 
-#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
-	/* Use values set by bootloader. Determine PLL rate and recalculate
-	 * dependent clocks as if kernel had changed PLL or divisors.
+
+	/*
+	 * Initially use the values set by bootloader. Determine PLL rate and
+	 * recalculate dependent clocks as if kernel had changed PLL or
+	 * divisors. See also omap1_clk_late_init() that can reprogram dpll1
+	 * after the SRAM is initialized.
 	 */
 	{
 		unsigned pll_ctl_val = omap_readw(DPLL_CTL);
@@ -862,25 +876,10 @@ int __init omap1_clk_init(void)
 			}
 		}
 	}
-#else
-	/* Find the highest supported frequency and enable it */
-	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
-		printk(KERN_ERR "System frequencies not set. Check your config.\n");
-		/* Guess sane values (60MHz) */
-		omap_writew(0x2290, DPLL_CTL);
-		omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
-		ck_dpll1.rate = 60000000;
-	}
-#endif
 	propagate_rate(&ck_dpll1);
 	/* Cache rates for clocks connected to ck_ref (not dpll1) */
 	propagate_rate(&ck_ref);
-	printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
-		"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-	       ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-	       ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-	       arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
-
+	omap1_show_rates();
 	if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
 		/* Select slicer output as OMAP input clock */
 		omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
@@ -925,3 +924,27 @@ int __init omap1_clk_init(void)
 
 	return 0;
 }
+
+#define OMAP1_DPLL1_SANE_VALUE	60000000
+
+void __init omap1_clk_late_init(void)
+{
+	unsigned long rate = ck_dpll1.rate;
+
+	if (rate >= OMAP1_DPLL1_SANE_VALUE)
+		return;
+
+	/* System booting at unusable rate, force reprogramming of DPLL1 */
+	ck_dpll1_p->rate = 0;
+
+	/* Find the highest supported frequency and enable it */
+	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+		pr_err("System frequencies not set, using default. Check your config.\n");
+		omap_writew(0x2290, DPLL_CTL);
+		omap_writew(cpu_is_omap7xx() ? 0x2005 : 0x0005, ARM_CKCTL);
+		ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE;
+	}
+	propagate_rate(&ck_dpll1);
+	omap1_show_rates();
+	loops_per_jiffy = cpufreq_scale(loops_per_jiffy, rate, ck_dpll1.rate);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/clock.h linux-libre-3.2-gnu1/arch/arm/mach-omap1/clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,8 @@
 
 #include <plat/clock.h>
 
-extern int __init omap1_clk_init(void);
+int omap1_clk_init(void);
+void omap1_clk_late_init(void);
 extern int omap1_clk_enable(struct clk *clk);
 extern void omap1_clk_disable(struct clk *clk);
 extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/devices.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,14 +22,16 @@
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 
+#include <plat/common.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mux.h>
-#include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/omap7xx.h>
 #include <plat/mcbsp.h>
 
+#include "clock.h"
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -291,6 +294,9 @@ static int __init omap1_init_devices(voi
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
+	omap_sram_init();
+	omap1_clk_late_init();
+
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/fpga.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/fpga.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/fpga.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/fpga.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -28,7 +29,6 @@
 #include <asm/mach/irq.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 static void fpga_mask_irq(struct irq_data *d)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-omap1/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,13 +13,8 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #include <plat/serial.h>
 
-#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
 		.pushsection .data
 omap_uart_phys:	.word	0x0
 omap_uart_virt:	.word	0x0
@@ -31,26 +26,24 @@ omap_uart_virt:	.word	0x0
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 
 		/* Use omap_uart_phys/virt if already configured */
-9:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rp, =omap_uart_phys	@ MMU enabled
-		add	\rv, \rp, #4		@ omap_uart_virt
-		ldr	\rp, [\rp, #0]
-		ldr	\rv, [\rv, #0]
+9:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ omap_uart_phys
+		ldr	\rv, [\tmp, #4]		@ omap_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
-		ldr	\rp, [\rp, #0]
+		and	\rp, pc, #0xff000000
+		ldr	\rv, =OMAP_UART_INFO_OFS
+		ldr	\rp, [\rp, \rv]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 10:		cmp	\rp, #0			@ no port configured?
@@ -74,17 +67,18 @@ omap_uart_virt:	.word	0x0
 
 		/* Store both phys and virt address for the uart */
 98:		add	\rp, \rp, #0xff000000	@ phys base
-		mrc	p15, 0, \rv, c1, c0
-		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		sub	\rp, \rp, #0xff000000	@ phys base
 		add	\rp, \rp, #0xfe000000	@ virt base
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		b	9b
-99:
+
+		.align
+99:		.word	.
+		.word	omap_uart_phys
+		.ltorg
+
+100:
 		.endm
 
 		.macro	senduart,rd,rx
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-omap1/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,4 +2,55 @@
  * arch/arm/mach-omap1/include/mach/memory.h
  */
 
-#include <plat/memory.h>
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
+
+/*
+ * Bus address is physical address, except for OMAP-1510 Local Bus.
+ * OMAP-1510 bus address is translated into a Local Bus address if the
+ * OMAP bus type is lbus. We do the address translation based on the
+ * device overriding the defaults used in the dma-mapping API.
+ * Note that the is_lbus_device() test is not very efficient on 1510
+ * because of the strncmp().
+ */
+#ifdef CONFIG_ARCH_OMAP15XX
+
+/*
+ * OMAP-1510 Local Bus address offset
+ */
+#define OMAP1510_LB_OFFSET	UL(0x30000000)
+
+#define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
+#define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
+#define is_lbus_device(dev)	(cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
+
+#define __arch_pfn_to_dma(dev, pfn)	\
+	({ dma_addr_t __dma = __pfn_to_phys(pfn); \
+	   if (is_lbus_device(dev)) \
+		__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
+	   __dma; })
+
+#define __arch_dma_to_pfn(dev, addr)	\
+	({ dma_addr_t __dma = addr;				\
+	   if (is_lbus_device(dev))				\
+		__dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;	\
+	   __phys_to_pfn(__dma);				\
+	})
+
+#define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
+						lbus_to_virt(addr) : \
+						__phys_to_virt(addr)); })
+
+#define __arch_virt_to_dma(dev, addr)	({ unsigned long __addr = (unsigned long)(addr); \
+					   (dma_addr_t) (is_lbus_device(dev) ? \
+						virt_to_lbus(__addr) : \
+						__virt_to_phys(__addr)); })
+
+#endif	/* CONFIG_ARCH_OMAP15XX */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/io.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/io.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include "clock.h"
 
 extern void omap_check_revision(void);
-extern void omap_sram_init(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -85,50 +84,45 @@ static struct map_desc omap16xx_io_desc[
 #endif
 
 /*
- * Maps common IO regions for omap1. This should only get called from
- * board specific init.
+ * Maps common IO regions for omap1
  */
-void __init omap1_map_common_io(void)
+static void __init omap1_map_common_io(void)
 {
 	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	/* We want to check CPU revision early for cpu_is_omapxxxx() macros.
-	 * IO space mapping must be initialized before we can do that.
-	 */
-	omap_check_revision();
+}
 
 #if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
-	if (cpu_is_omap7xx()) {
-		iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
-	}
+void __init omap7xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
+}
 #endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap15xx()) {
-		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-	if (cpu_is_omap16xx()) {
-		iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
-	}
+void __init omap15xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
+}
 #endif
 
-	omap_sram_init();
+#if defined(CONFIG_ARCH_OMAP16XX)
+void __init omap16xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
 }
+#endif
 
 /*
- * Common low-level hardware init for omap1. This should only get called from
- * board specific init.
+ * Common low-level hardware init for omap1.
  */
-void __init omap1_init_common_hw(void)
+void omap1_init_early(void)
 {
+	omap_check_revision();
+	omap_ioremap_init();
+
 	/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
 	 * on a Posted Write in the TIPB Bridge".
 	 */
@@ -138,8 +132,8 @@ void __init omap1_init_common_hw(void)
 	/* Must init clocks early to assure that timer interrupt works
 	 */
 	omap1_clk_init();
-
 	omap1_mux_init();
+	omap_init_consistent_dma_size();
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/irq.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -45,7 +45,6 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
-#include <mach/gpio.h>
 #include <plat/cpu.h>
 
 #define IRQ_BANK(irq) ((irq) >> 5)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-omap1/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -171,14 +171,6 @@ config MACH_OMAP_GENERIC
 comment "OMAP CPU Speed"
 	depends on ARCH_OMAP1
 
-config OMAP_CLOCKS_SET_BY_BOOTLOADER
-	bool "OMAP clocks set by bootloader"
-	depends on ARCH_OMAP1
-	help
-	  Enable this option to prevent the kernel from overriding the clock
-	  frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
-	  internal LCD controller and MPU peripherals.
-
 config OMAP_ARM_216MHZ
 	bool "OMAP ARM 216 MHz CPU (1710 only)"
         depends on ARCH_OMAP1 && ARCH_OMAP16XX
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,13 +3,13 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 
 #include "leds.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds-h2p2-debug.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds-h2p2-debug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds-h2p2-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds-h2p2-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * The "surfer" expansion board and H2 sample board also have two-color
  * green+red LEDs (in parallel), used here for timer and idle indicators.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
@@ -20,7 +21,6 @@
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 #include "leds.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds-osk.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds-osk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/leds-osk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/leds-osk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,14 +3,13 @@
  *
  * LED driver for OSK with optional Mistral QVGA board
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
 
-#include <mach/gpio.h>
-
 #include "leds.h"
 
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/mailbox.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/mailbox.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/Makefile linux-libre-3.2-gnu1/arch/arm/mach-omap1/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-omap1/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y		:= 0x10008000
+   zreladdr-y		+= 0x10008000
 params_phys-y		:= 0x10000100
 initrd_phys-y		:= 0x10800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/mcbsp.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/mcbsp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 static int dsp_use;
 static struct clk *api_clk;
 static struct clk *dsp_clk;
+static struct platform_device **omap_mcbsp_devices;
 
 static void omap1_mcbsp_request(unsigned int id)
 {
@@ -78,6 +79,17 @@ static struct omap_mcbsp_ops omap1_mcbsp
 	.free		= omap1_mcbsp_free,
 };
 
+#define OMAP7XX_MCBSP1_BASE	0xfffb1000
+#define OMAP7XX_MCBSP2_BASE	0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE	0xe1011800
+#define OMAP1510_MCBSP2_BASE	0xfffb1000
+#define OMAP1510_MCBSP3_BASE	0xe1017000
+
+#define OMAP1610_MCBSP1_BASE	0xe1011800
+#define OMAP1610_MCBSP2_BASE	0xfffb1000
+#define OMAP1610_MCBSP3_BASE	0xe1017000
+
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 struct resource omap7xx_mcbsp_res[][6] = {
 	{
@@ -369,6 +381,39 @@ static struct omap_mcbsp_platform_data o
 #define OMAP16XX_MCBSP_COUNT		0
 #endif
 
+static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
+{
+	int i;
+
+	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
+				     GFP_KERNEL);
+	if (!omap_mcbsp_devices) {
+		printk(KERN_ERR "Could not register McBSP devices\n");
+		return;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct platform_device *new_mcbsp;
+		int ret;
+
+		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
+		if (!new_mcbsp)
+			continue;
+		platform_device_add_resources(new_mcbsp, &res[i * res_count],
+					res_count);
+		config[i].reg_size = 2;
+		config[i].reg_step = 2;
+		new_mcbsp->dev.platform_data = &config[i];
+		ret = platform_device_add(new_mcbsp);
+		if (ret) {
+			platform_device_put(new_mcbsp);
+			continue;
+		}
+		omap_mcbsp_devices[i] = new_mcbsp;
+	}
+}
+
 static int __init omap1_mcbsp_init(void)
 {
 	if (!cpu_class_is_omap1())
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/pm_bus.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/pm_bus.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/pm_bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/pm_bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/pm.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@ void omap1_pm_idle(void)
 		return;
 	}
 
-#ifdef CONFIG_OMAP_MPU_TIMER
+#if defined(CONFIG_OMAP_MPU_TIMER) && !defined(CONFIG_OMAP_DM_TIMER)
 #warning Enable 32kHz OS timer in order to allow sleep states in idle
 	use_idlect1 = use_idlect1 & ~(1 << 9);
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/serial.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/serial.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,7 +24,6 @@
 
 #include <plat/board.h>
 #include <plat/mux.h>
-#include <mach/gpio.h>
 #include <plat/fpga.h>
 
 #include "pm.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap1/timer.c linux-libre-3.2-gnu1/arch/arm/mach-omap1/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap1/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap1/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,173 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE		0xfffb1400
+#define OMAP1610_GPTIMER2_BASE		0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE		0xfffb2400
+#define OMAP1610_GPTIMER4_BASE		0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE		0xfffb3400
+#define OMAP1610_GPTIMER6_BASE		0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE		0xfffb7400
+#define OMAP1610_GPTIMER8_BASE		0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT		8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+				int source)
+{
+	int n = (pdev->id - 1) << 1;
+	u32 l;
+
+	l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+	l |= source << n;
+	__raw_writel(l, MOD_CONF_CTRL_1);
+
+	return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+	int i;
+	int ret;
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+
+	if (!cpu_is_omap16xx())
+		return 0;
+
+	for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+		struct resource res[2];
+		u32 base, irq;
+
+		switch (i) {
+		case 1:
+			base = OMAP1610_GPTIMER1_BASE;
+			irq = INT_1610_GPTIMER1;
+			break;
+		case 2:
+			base = OMAP1610_GPTIMER2_BASE;
+			irq = INT_1610_GPTIMER2;
+			break;
+		case 3:
+			base = OMAP1610_GPTIMER3_BASE;
+			irq = INT_1610_GPTIMER3;
+			break;
+		case 4:
+			base = OMAP1610_GPTIMER4_BASE;
+			irq = INT_1610_GPTIMER4;
+			break;
+		case 5:
+			base = OMAP1610_GPTIMER5_BASE;
+			irq = INT_1610_GPTIMER5;
+			break;
+		case 6:
+			base = OMAP1610_GPTIMER6_BASE;
+			irq = INT_1610_GPTIMER6;
+			break;
+		case 7:
+			base = OMAP1610_GPTIMER7_BASE;
+			irq = INT_1610_GPTIMER7;
+			break;
+		case 8:
+			base = OMAP1610_GPTIMER8_BASE;
+			irq = INT_1610_GPTIMER8;
+			break;
+		default:
+			/*
+			 * not supposed to reach here.
+			 * this is to remove warning.
+			 */
+			return -EINVAL;
+		}
+
+		pdev = platform_device_alloc("omap_timer", i);
+		if (!pdev) {
+			pr_err("%s: Failed to device alloc for dmtimer%d\n",
+				__func__, i);
+			return -ENOMEM;
+		}
+
+		memset(res, 0, 2 * sizeof(struct resource));
+		res[0].start = base;
+		res[0].end = base + 0x46;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = irq;
+		res[1].end = irq;
+		res[1].flags = IORESOURCE_IRQ;
+		ret = platform_device_add_resources(pdev, res,
+				ARRAY_SIZE(res));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+				__func__);
+			goto err_free_pdev;
+		}
+
+		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err_free_pdata;
+		}
+
+		pdata->set_timer_src = omap1_dm_timer_set_src;
+		pdata->needs_manual_reset = 1;
+
+		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		dev_dbg(&pdev->dev, " Registered.\n");
+	}
+
+	return 0;
+
+err_free_pdata:
+	kfree(pdata);
+
+err_free_pdev:
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-2430sdp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-2430sdp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-2430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-2430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -99,20 +102,72 @@ static struct platform_device sdp2430_fl
 	.resource	= &sdp2430_flash_resource,
 };
 
-static struct platform_device sdp2430_lcd_device = {
-	.name		= "sdp2430_lcd",
-	.id		= -1,
-};
-
 static struct platform_device *sdp2430_devices[] __initdata = {
 	&sdp2430_flash_device,
+};
+
+/* LCD */
+#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91
+#define SDP2430_LCD_PANEL_ENABLE_GPIO		154
+
+static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1);
+	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1);
+
+	return 0;
+}
+
+static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0);
+	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0);
+}
+
+static struct panel_generic_dpi_data sdp2430_panel_data = {
+	.name			= "nec_nl2432dr22-11b",
+	.platform_enable	= sdp2430_panel_enable_lcd,
+	.platform_disable	= sdp2430_panel_disable_lcd,
+};
+
+static struct omap_dss_device sdp2430_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 16,
+	.data			= &sdp2430_panel_data,
+};
+
+static struct omap_dss_device *sdp2430_dss_devices[] = {
 	&sdp2430_lcd_device,
 };
 
-static struct omap_lcd_config sdp2430_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct omap_dss_board_info sdp2430_dss_data = {
+	.num_devices	= ARRAY_SIZE(sdp2430_dss_devices),
+	.devices	= sdp2430_dss_devices,
+	.default_device	= &sdp2430_lcd_device,
 };
 
+static void __init sdp2430_display_init(void)
+{
+	int r;
+
+	static struct gpio gpios[] __initdata = {
+		{ SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
+			"LCD reset" },
+		{ SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW,
+			"LCD Backlight" },
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		return;
+	}
+
+	omap_display_init(&sdp2430_dss_data);
+}
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -137,16 +192,6 @@ static inline void board_smc91x_init(voi
 
 #endif
 
-static struct omap_board_config_kernel sdp2430_config[] __initdata = {
-	{OMAP_TAG_LCD, &sdp2430_lcd_config},
-};
-
-static void __init omap_2430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -229,13 +274,11 @@ static void __init omap_2430sdp_init(voi
 {
 	omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-	omap_board_config = sdp2430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
-
 	omap2430_i2c_init();
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap2_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
@@ -247,20 +290,16 @@ static void __init omap_2430sdp_init(voi
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
 			 "Secondary LCD backlight");
-}
 
-static void __init omap_2430sdp_map_io(void)
-{
-	omap2_set_globals_243x();
-	omap243x_map_common_io();
+	sdp2430_display_init();
 }
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_2430sdp_map_io,
-	.init_early	= omap_2430sdp_init_early,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_2430sdp_init,
 	.timer		= &omap2_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-3430sdp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-3430sdp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-3430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-3430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/gpmc-smc91x.h>
 
@@ -186,8 +186,7 @@ static struct omap_dss_device sdp3430_lc
 	.platform_disable	= sdp3430_panel_disable_lcd,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= sdp3430_panel_enable_dvi,
 	.platform_disable	= sdp3430_panel_disable_dvi,
 };
@@ -195,7 +194,7 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device sdp3430_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -225,12 +224,6 @@ static struct omap_dss_board_info sdp343
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
-static void __init omap_3430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-}
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -719,6 +712,7 @@ static void __init omap_3430sdp_init(voi
 		gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
 	board_serial_init();
+	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
@@ -729,10 +723,10 @@ static void __init omap_3430sdp_init(voi
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_3430sdp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_3430sdp_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-3630sdp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-3630sdp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-3630sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-3630sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,13 +70,6 @@ static const struct usbhs_omap_board_dat
 static struct omap_board_config_kernel sdp_config[] __initdata = {
 };
 
-static void __init omap_sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-				  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -207,6 +200,8 @@ static void __init omap_sdp_init(void)
 	omap_board_config = sdp_config;
 	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
+	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
@@ -215,10 +210,10 @@ static void __init omap_sdp_init(void)
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_sdp_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_sdp_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-4430sdp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-4430sdp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-4430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-4430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,8 @@
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
 #include <video/omapdss.h>
+#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
 
 #include "mux.h"
@@ -52,6 +54,8 @@
 #define OMAP4_SFH7741_ENABLE_GPIO		188
 #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */
+#define DLP_POWER_ON_GPIO	40
 
 #define GPIO_WIFI_PMENA		54
 #define GPIO_WIFI_IRQ		53
@@ -129,7 +133,7 @@ static const int sdp4430_keymap[] = {
 	KEY(7, 6, KEY_OK),
 	KEY(7, 7, KEY_DOWN),
 };
-static struct omap_device_pad keypad_pads[] __initdata = {
+static struct omap_device_pad keypad_pads[] = {
 	{	.name   = "kpd_col1.kpd_col1",
 		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
 	},
@@ -340,11 +344,6 @@ static int __init omap_ethernet_init(voi
 	return status;
 }
 
-static struct platform_device sdp4430_lcd_device = {
-	.name		= "sdp4430_lcd",
-	.id		= -1,
-};
-
 static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
 	REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
 	REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
@@ -374,27 +373,12 @@ static struct platform_device sdp4430_vb
 };
 
 static struct platform_device *sdp4430_devices[] __initdata = {
-	&sdp4430_lcd_device,
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 	&sdp4430_leds_pwm,
 	&sdp4430_vbat,
 };
 
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
-static struct omap_board_config_kernel sdp4430_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },
-};
-
-static void __init omap_4430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_OTG,
@@ -648,37 +632,202 @@ static void sdp4430_panel_disable_hdmi(s
 	gpio_free(HDMI_GPIO_HPD);
 }
 
-static struct omap_dss_device sdp4430_hdmi_device = {
-	.name = "hdmi",
-	.driver_name = "hdmi_panel",
-	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.clocks	= {
-		.dispc	= {
+static struct nokia_dsi_panel_data dsi1_panel = {
+		.name		= "taal",
+		.reset_gpio	= 102,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 101,
+		.esd_interval	= 0,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi1_panel,
+	.phy.dsi		= {
+		.clk_lane	= 1,
+		.clk_pol	= 0,
+		.data1_lane	= 2,
+		.data1_pol	= 0,
+		.data2_lane	= 3,
+		.data2_pol	= 0,
+
+		.module		= 0,
+	},
+
+	.clocks = {
+		.dispc = {
+			.channel = {
+				/* Logic Clock = 172.8 MHz */
+				.lck_div	= 1,
+				/* Pixel Clock = 34.56 MHz */
+				.pck_div	= 5,
+				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+			},
 			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
 		},
-		.hdmi	= {
-			.regn	= 15,
-			.regm2	= 1,
+
+		.dsi = {
+			.regn		= 16,	/* Fint = 2.4 MHz */
+			.regm		= 180,	/* DDR Clock = 216 MHz */
+			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
+			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
+
+			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
+			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
 		},
 	},
+	.channel		= OMAP_DSS_CHANNEL_LCD,
+};
+
+static struct nokia_dsi_panel_data dsi2_panel = {
+		.name		= "taal",
+		.reset_gpio	= 104,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 103,
+		.esd_interval	= 0,
+};
+
+static struct omap_dss_device sdp4430_lcd2_device = {
+	.name			= "lcd2",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi2_panel,
+	.phy.dsi		= {
+		.clk_lane	= 1,
+		.clk_pol	= 0,
+		.data1_lane	= 2,
+		.data1_pol	= 0,
+		.data2_lane	= 3,
+		.data2_pol	= 0,
+
+		.module		= 1,
+	},
+
+	.clocks = {
+		.dispc = {
+			.channel = {
+				/* Logic Clock = 172.8 MHz */
+				.lck_div	= 1,
+				/* Pixel Clock = 34.56 MHz */
+				.pck_div	= 5,
+				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
+			},
+			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
+		},
+
+		.dsi = {
+			.regn		= 16,	/* Fint = 2.4 MHz */
+			.regm		= 180,	/* DDR Clock = 216 MHz */
+			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
+			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
+
+			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
+			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
+		},
+	},
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+static void sdp4430_lcd_init(void)
+{
+	int r;
+
+	r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+		"lcd1_reset_gpio");
+	if (r)
+		pr_err("%s: Could not get lcd1_reset_gpio\n", __func__);
+
+	r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT,
+		"lcd2_reset_gpio");
+	if (r)
+		pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
+}
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
 	.platform_enable = sdp4430_panel_enable_hdmi,
 	.platform_disable = sdp4430_panel_disable_hdmi,
 	.channel = OMAP_DSS_CHANNEL_DIGIT,
 };
 
+static struct picodlp_panel_data sdp4430_picodlp_pdata = {
+	.picodlp_adapter_id	= 2,
+	.emu_done_gpio		= 44,
+	.pwrgood_gpio		= 45,
+};
+
+static void sdp4430_picodlp_init(void)
+{
+	int r;
+	const struct gpio picodlp_gpios[] = {
+		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+			"DLP POWER ON"},
+		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
+			"DLP EMU DONE"},
+		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
+			"DLP PWRGOOD"},
+	};
+
+	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
+	if (r)
+		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
+}
+
+static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DISPLAY_SEL_GPIO, 0);
+	gpio_set_value(DLP_POWER_ON_GPIO, 1);
+
+	return 0;
+}
+
+static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DLP_POWER_ON_GPIO, 0);
+	gpio_set_value(DISPLAY_SEL_GPIO, 1);
+}
+
+static struct omap_dss_device sdp4430_picodlp_device = {
+	.name			= "picodlp",
+	.driver_name		= "picodlp_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 24,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+	.platform_enable	= sdp4430_panel_enable_picodlp,
+	.platform_disable	= sdp4430_panel_disable_picodlp,
+	.data			= &sdp4430_picodlp_pdata,
+};
+
 static struct omap_dss_device *sdp4430_dss_devices[] = {
+	&sdp4430_lcd_device,
+	&sdp4430_lcd2_device,
 	&sdp4430_hdmi_device,
+	&sdp4430_picodlp_device,
 };
 
 static struct omap_dss_board_info sdp4430_dss_data = {
 	.num_devices	= ARRAY_SIZE(sdp4430_dss_devices),
 	.devices	= sdp4430_dss_devices,
-	.default_device	= &sdp4430_hdmi_device,
+	.default_device	= &sdp4430_lcd_device,
 };
 
-void omap_4430sdp_display_init(void)
+static void omap_4430sdp_display_init(void)
 {
+	int r;
+
+	/* Enable LCD2 by default (instead of Pico DLP) */
+	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+			"display_sel");
+	if (r)
+		pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+	sdp4430_lcd_init();
 	sdp4430_hdmi_mux_init();
+	sdp4430_picodlp_init();
 	omap_display_init(&sdp4430_dss_data);
 }
 
@@ -802,13 +951,11 @@ static void __init omap_4430sdp_init(voi
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, NULL, package);
 
-	omap_board_config = sdp4430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
-
 	omap4_i2c_init();
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
@@ -830,18 +977,12 @@ static void __init omap_4430sdp_init(voi
 	omap_4430sdp_display_init();
 }
 
-static void __init omap_4430sdp_map_io(void)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_4430sdp_map_io,
-	.init_early	= omap_4430sdp_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
 	.timer		= &omap4_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-am3517crane.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-am3517crane.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-am3517crane.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-am3517crane.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,12 +47,6 @@ static struct omap_board_mux board_mux[]
 };
 #endif
 
-static void __init am3517_crane_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -70,6 +64,7 @@ static void __init am3517_crane_init(voi
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	omap_board_config = am3517_crane_config;
 	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
@@ -98,10 +93,10 @@ static void __init am3517_crane_init(voi
 }
 
 MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_crane_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_crane_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-am3517evm.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-am3517evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-am3517evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-am3517evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "control.h"
@@ -333,8 +334,7 @@ static void am3517_evm_panel_disable_dvi
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= am3517_evm_panel_enable_dvi,
 	.platform_disable	= am3517_evm_panel_disable_dvi,
 };
@@ -342,7 +342,7 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device am3517_evm_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -362,11 +362,6 @@ static struct omap_dss_board_info am3517
 /*
  * Board initialization
  */
-static void __init am3517_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type         = MUSB_INTERFACE_ULPI,
@@ -469,6 +464,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_i2c_init();
 	omap_display_init(&am3517_evm_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
@@ -490,10 +486,10 @@ static void __init am3517_evm_init(void)
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_evm_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_evm_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-apollon.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-apollon.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-apollon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-apollon.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,9 @@
 #include <plat/common.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -149,11 +152,6 @@ static struct platform_device apollon_sm
 	.resource	= apollon_smc91x_resources,
 };
 
-static struct platform_device apollon_lcd_device = {
-	.name		= "apollon_lcd",
-	.id		= -1,
-};
-
 static struct omap_led_config apollon_led_config[] = {
 	{
 		.cdev	= {
@@ -191,7 +189,6 @@ static struct platform_device apollon_le
 static struct platform_device *apollon_devices[] __initdata = {
 	&apollon_onenand_device,
 	&apollon_smc91x_device,
-	&apollon_lcd_device,
 	&apollon_led_device,
 };
 
@@ -265,19 +262,27 @@ static struct omap_usb_config apollon_us
 	.pins[0]	= 6,
 };
 
-static struct omap_lcd_config apollon_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct panel_generic_dpi_data apollon_panel_data = {
+	.name			= "apollon",
 };
 
-static struct omap_board_config_kernel apollon_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&apollon_lcd_config },
+static struct omap_dss_device apollon_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 18,
+	.data			= &apollon_panel_data,
 };
 
-static void __init omap_apollon_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
+static struct omap_dss_device *apollon_dss_devices[] = {
+	&apollon_lcd_device,
+};
+
+static struct omap_dss_board_info apollon_dss_data = {
+	.num_devices	= ARRAY_SIZE(apollon_dss_devices),
+	.devices	= apollon_dss_devices,
+	.default_device	= &apollon_lcd_device,
+};
 
 static struct gpio apollon_gpio_leds[] __initdata = {
 	{ LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */
@@ -314,8 +319,6 @@ static void __init omap_apollon_init(voi
 	u32 v;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
-	omap_board_config = apollon_config;
-	omap_board_config_size = ARRAY_SIZE(apollon_config);
 
 	apollon_init_smc91x();
 	apollon_led_init();
@@ -340,20 +343,16 @@ static void __init omap_apollon_init(voi
 	 */
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
-}
-
-static void __init omap_apollon_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
+	omap_sdrc_init(NULL, NULL);
+	omap_display_init(&apollon_dss_data);
 }
 
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_apollon_map_io,
-	.init_early	= omap_apollon_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_apollon_init,
 	.timer		= &omap2_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-cm-t3517.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-cm-t3517.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-cm-t3517.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-cm-t3517.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,12 +251,6 @@ static inline void cm_t3517_init_nand(vo
 static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
 };
 
-static void __init cm_t3517_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
@@ -289,6 +283,7 @@ static void __init cm_t3517_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap_board_config = cm_t3517_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
@@ -299,10 +294,10 @@ static void __init cm_t3517_init(void)
 }
 
 MACHINE_START(CM_T3517, "Compulab CM-T3517")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve        = omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t3517_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t3517_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-cm-t35.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-cm-t35.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-cm-t35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-cm-t35.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/mcspi.h>
 
 #include <mach/hardware.h>
@@ -242,8 +243,7 @@ static struct omap_dss_device cm_t35_lcd
 	.phy.dpi.data_lines	= 18,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= cm_t35_panel_enable_dvi,
 	.platform_disable	= cm_t35_panel_disable_dvi,
 };
@@ -251,7 +251,7 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device cm_t35_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -471,13 +471,6 @@ static void __init cm_t35_init_i2c(void)
 	omap3_pmic_init("tps65930", &cm_t35_twldata);
 }
 
-static void __init cm_t35_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for CM-T35 ethernet */
@@ -610,6 +603,8 @@ static void __init cm_t3x_common_init(vo
 	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
@@ -634,20 +629,20 @@ static void __init cm_t3730_init(void)
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t35_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t35_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(CM_T3730, "Compulab CM-T3730")
-	.boot_params    = 0x80000100,
+	.atag_offset    = 0x100,
 	.reserve        = omap_reserve,
 	.map_io         = omap3_map_io,
-	.init_early     = cm_t35_init_early,
+	.init_early     = omap3630_init_early,
 	.init_irq       = omap3_init_irq,
 	.init_machine   = cm_t3730_init,
 	.timer          = &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-devkit8000.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-devkit8000.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-devkit8000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-devkit8000.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -139,7 +140,7 @@ static struct regulator_consumer_supply
 };
 
 static struct panel_generic_dpi_data lcd_panel = {
-	.name			= "generic",
+	.name			= "innolux_at070tn83",
 	.platform_enable        = devkit8000_panel_enable_lcd,
 	.platform_disable       = devkit8000_panel_disable_lcd,
 };
@@ -152,8 +153,7 @@ static struct omap_dss_device devkit8000
 	.phy.dpi.data_lines     = 24,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable        = devkit8000_panel_enable_dvi,
 	.platform_disable       = devkit8000_panel_disable_dvi,
 };
@@ -161,7 +161,7 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device devkit8000_dvi_device = {
 	.name                   = "dvi",
 	.type                   = OMAP_DISPLAY_TYPE_DPI,
-	.driver_name            = "generic_dpi_panel",
+	.driver_name            = "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines     = 24,
 };
@@ -226,7 +226,6 @@ static int devkit8000_twl_gpio_setup(str
 {
 	int ret;
 
-	omap_mux_init_gpio(29, OMAP_PIN_INPUT);
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
@@ -267,7 +266,7 @@ static struct twl4030_gpio_platform_data
 
 static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -397,19 +396,6 @@ static struct platform_device keys_gpio
 	},
 };
 
-
-static void __init devkit8000_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init devkit8000_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 #define OMAP_DM9000_BASE	0x2c000000
 
 static struct resource omap_dm9000_resources[] = {
@@ -645,6 +631,8 @@ static void __init devkit8000_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_dm9000_init();
 
@@ -667,11 +655,11 @@ static void __init devkit8000_init(void)
 }
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= devkit8000_init_early,
-	.init_irq	= devkit8000_init_irq,
+	.init_early	= omap35xx_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= devkit8000_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-flash.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-flash.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,11 +148,6 @@ __init board_nand_init(struct mtd_partit
 	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
-#else
-void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, int nand_type)
-{
-}
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-flash.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-flash.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-flash.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-flash.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,26 @@ struct flash_partitions {
 	int nr_parts;
 };
 
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 extern void board_flash_init(struct flash_partitions [],
 				char chip_sel[][GPMC_CS_NUM], int nand_type);
+#else
+static inline void board_flash_init(struct flash_partitions part[],
+				char chip_sel[][GPMC_CS_NUM], int nand_type)
+{
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern void board_nand_init(struct mtd_partition *nand_parts,
 					u8 nr_parts, u8 cs, int nand_type);
+#else
+static inline void board_nand_init(struct mtd_partition *nand_parts,
+					u8 nr_parts, u8 cs, int nand_type)
+{
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-generic.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-generic.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,76 +1,165 @@
 /*
- * linux/arch/arm/mach-omap2/board-generic.c
- *
  * Copyright (C) 2005 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
- * Modified from mach-omap/omap1/board-generic.c
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  *
- * Code for generic OMAP2 board. Should work on many OMAP2 systems where
- * the bootloader passes the board-specific data to the kernel.
- * Do not put any board specific code to this file; create a new machine
- * type if you need custom low-level initializations.
+ * Modified from the original mach-omap/omap2/board-generic.c did by Paul
+ * to support the OMAP2+ device tree boards with an unique board file.
  *
  * 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/init.h>
-#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 
-#include <mach/gpio.h>
-#include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/omap4-common.h>
+#include "common-board-devices.h"
 
-static struct omap_board_config_kernel generic_config[] = {
+/*
+ * XXX: Still needed to boot until the i2c & twl driver is adapted to
+ * device-tree
+ */
+#ifdef CONFIG_ARCH_OMAP4
+static struct twl4030_platform_data sdp4430_twldata = {
+	.irq_base	= TWL6030_IRQ_BASE,
+	.irq_end	= TWL6030_IRQ_END,
 };
 
-static void __init omap_generic_init_early(void)
+static void __init omap4_i2c_init(void)
 {
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
+	omap4_pmic_init("twl6030", &sdp4430_twldata);
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct twl4030_platform_data beagle_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+};
+
+static void __init omap3_i2c_init(void)
+{
+	omap3_pmic_init("twl4030", &beagle_twldata);
 }
+#endif
+
+static struct of_device_id omap_dt_match_table[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "ti,omap-infra", },
+	{ }
+};
+
+static struct of_device_id intc_match[] __initdata = {
+	{ .compatible = "ti,omap3-intc", },
+	{ .compatible = "arm,cortex-a9-gic", },
+	{ }
+};
 
 static void __init omap_generic_init(void)
 {
+	struct device_node *node = of_find_matching_node(NULL, intc_match);
+	if (node)
+		irq_domain_add_simple(node, 0);
+
 	omap_serial_init();
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
+	omap_sdrc_init(NULL, NULL);
+
+	of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
 }
 
-static void __init omap_generic_map_io(void)
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_init(void)
 {
-	if (cpu_is_omap242x()) {
-		omap2_set_globals_242x();
-		omap242x_map_common_io();
-	} else if (cpu_is_omap243x()) {
-		omap2_set_globals_243x();
-		omap243x_map_common_io();
-	} else if (cpu_is_omap34xx()) {
-		omap2_set_globals_3xxx();
-		omap34xx_map_common_io();
-	} else if (cpu_is_omap44xx()) {
-		omap2_set_globals_443x();
-		omap44xx_map_common_io();
-	}
+	omap4_i2c_init();
+	omap_generic_init();
 }
+#endif
 
-/* XXX This machine entry name should be updated */
-MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
-	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.boot_params	= 0x80000100,
+#ifdef CONFIG_ARCH_OMAP3
+static void __init omap3_init(void)
+{
+	omap3_i2c_init();
+	omap_generic_init();
+}
+#endif
+
+#if defined(CONFIG_SOC_OMAP2420)
+static const char *omap242x_boards_compat[] __initdata = {
+	"ti,omap2420",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_generic_map_io,
-	.init_early	= omap_generic_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap2_timer,
+	.dt_compat	= omap242x_boards_compat,
 MACHINE_END
+#endif
+
+#if defined(CONFIG_SOC_OMAP2430)
+static const char *omap243x_boards_compat[] __initdata = {
+	"ti,omap2430",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
+	.init_irq	= omap2_init_irq,
+	.init_machine	= omap_generic_init,
+	.timer		= &omap2_timer,
+	.dt_compat	= omap243x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+static const char *omap3_boards_compat[] __initdata = {
+	"ti,omap3",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
+	.init_machine	= omap3_init,
+	.timer		= &omap3_timer,
+	.dt_compat	= omap3_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static const char *omap4_boards_compat[] __initdata = {
+	"ti,omap4",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
+	.init_irq	= gic_init_irq,
+	.init_machine	= omap4_init,
+	.timer		= &omap4_timer,
+	.dt_compat	= omap4_boards_compat,
+MACHINE_END
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-h4.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-h4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-h4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-h4.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -25,21 +25,23 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -48,10 +50,8 @@
 
 #define H4_ETHR_GPIO_IRQ		92
 
-static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
-static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
-
-static const unsigned int h4_keymap[] = {
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
+static const uint32_t board_matrix_keys[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(1, 0, KEY_RIGHT),
 	KEY(2, 0, KEY_A),
@@ -84,6 +84,71 @@ static const unsigned int h4_keymap[] =
 	KEY(4, 5, KEY_ENTER),
 };
 
+static const struct matrix_keymap_data board_keymap_data = {
+	.keymap			= board_matrix_keys,
+	.keymap_size		= ARRAY_SIZE(board_matrix_keys),
+};
+
+static unsigned int board_keypad_row_gpios[] = {
+	88, 89, 124, 11, 6, 96
+};
+
+static unsigned int board_keypad_col_gpios[] = {
+	90, 91, 100, 36, 12, 97, 98
+};
+
+static struct matrix_keypad_platform_data board_keypad_platform_data = {
+	.keymap_data	= &board_keymap_data,
+	.row_gpios	= board_keypad_row_gpios,
+	.num_row_gpios	= ARRAY_SIZE(board_keypad_row_gpios),
+	.col_gpios	= board_keypad_col_gpios,
+	.num_col_gpios	= ARRAY_SIZE(board_keypad_col_gpios),
+	.active_low	= 1,
+
+	.debounce_ms		= 20,
+	.col_scan_delay_us	= 5,
+};
+
+static struct platform_device board_keyboard = {
+	.name	= "matrix-keypad",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &board_keypad_platform_data,
+	},
+};
+static void __init board_mkp_init(void)
+{
+	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
+	if (omap_has_menelaus()) {
+		omap_mux_init_signal("sdrc_a14.gpio0",
+			OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
+		omap_mux_init_signal("gpio_98", 0);
+		board_keypad_row_gpios[5] = 0;
+		board_keypad_col_gpios[2] = 15;
+		board_keypad_col_gpios[6] = 18;
+	} else {
+		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("gpio_100", 0);
+		omap_mux_init_signal("gpio_98", 0);
+	}
+	omap_mux_init_signal("gpio_90", 0);
+	omap_mux_init_signal("gpio_91", 0);
+	omap_mux_init_signal("gpio_36", 0);
+	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
+	omap_mux_init_signal("gpio_97", 0);
+
+	platform_device_register(&board_keyboard);
+}
+#else
+static inline void board_mkp_init(void)
+{
+}
+#endif
+
 static struct mtd_partition h4_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -135,37 +200,30 @@ static struct platform_device h4_flash_d
 	.resource	= &h4_flash_resource,
 };
 
-static const struct matrix_keymap_data h4_keymap_data = {
-	.keymap		= h4_keymap,
-	.keymap_size	= ARRAY_SIZE(h4_keymap),
+static struct platform_device *h4_devices[] __initdata = {
+	&h4_flash_device,
 };
 
-static struct omap_kp_platform_data h4_kp_data = {
-	.rows		= 6,
-	.cols		= 7,
-	.keymap_data	= &h4_keymap_data,
-	.rep		= true,
-	.row_gpios 	= row_gpios,
-	.col_gpios 	= col_gpios,
+static struct panel_generic_dpi_data h4_panel_data = {
+	.name			= "h4",
 };
 
-static struct platform_device h4_kp_device = {
-	.name		= "omap-keypad",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &h4_kp_data,
-	},
+static struct omap_dss_device h4_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 16,
+	.data			= &h4_panel_data,
 };
 
-static struct platform_device h4_lcd_device = {
-	.name		= "lcd_h4",
-	.id		= -1,
+static struct omap_dss_device *h4_dss_devices[] = {
+	&h4_lcd_device,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
-	&h4_kp_device,
-	&h4_lcd_device,
+static struct omap_dss_board_info h4_dss_data = {
+	.num_devices	= ARRAY_SIZE(h4_dss_devices),
+	.devices	= h4_dss_devices,
+	.default_device	= &h4_lcd_device,
 };
 
 /* 2420 Sysboot setup (2430 is different) */
@@ -271,10 +329,6 @@ static void __init h4_init_flash(void)
 	h4_flash_resource.end	= base + SZ_64M - 1;
 }
 
-static struct omap_lcd_config h4_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct omap_usb_config h4_usb_config __initdata = {
 	/* S1.10 OFF -- usb "download port"
 	 * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -286,21 +340,6 @@ static struct omap_usb_config h4_usb_con
 	.hmc_mode	= 0x00,		/* 0:dev|otg 1:disable 2:disable */
 };
 
-static struct omap_board_config_kernel h4_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&h4_lcd_config },
-};
-
-static void __init omap_h4_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
-static void __init omap_h4_init_irq(void)
-{
-	omap2_init_irq();
-}
-
 static struct at24_platform_data m24c01 = {
 	.byte_len	= SZ_1K / 8,
 	.page_size	= 16,
@@ -331,62 +370,32 @@ static void __init omap_h4_init(void)
 {
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF);
 
-	omap_board_config = h4_config;
-	omap_board_config_size = ARRAY_SIZE(h4_config);
-
 	/*
 	 * Make sure the serial ports are muxed on at this point.
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
 
-#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
-	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
-	if (omap_has_menelaus()) {
-		omap_mux_init_signal("sdrc_a14.gpio0",
-			OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
-		omap_mux_init_signal("gpio_98", 0);
-		row_gpios[5] = 0;
-		col_gpios[2] = 15;
-		col_gpios[6] = 18;
-	} else {
-		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("gpio_100", 0);
-		omap_mux_init_signal("gpio_98", 0);
-	}
-	omap_mux_init_signal("gpio_90", 0);
-	omap_mux_init_signal("gpio_91", 0);
-	omap_mux_init_signal("gpio_36", 0);
-	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
-	omap_mux_init_signal("gpio_97", 0);
-#endif
-
+	board_mkp_init();
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	h4_init_flash();
-}
 
-static void __init omap_h4_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
+	omap_display_init(&h4_dss_data);
 }
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_h4_map_io,
-	.init_early	= omap_h4_init_early,
-	.init_irq	= omap_h4_init_irq,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_h4_init,
 	.timer		= &omap2_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-igep0020.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-igep0020.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-igep0020.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-igep0020.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
 
 #include "mux.h"
@@ -455,16 +455,16 @@ static void igep2_disable_dvi(struct oma
 	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= igep2_enable_dvi,
 	.platform_disable	= igep2_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device igep2_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -491,13 +491,6 @@ static struct platform_device *igep_devi
 	&igep_vwlan_device,
 };
 
-static void __init igep_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(m65kxxxxam_sdrc_params,
-				  m65kxxxxam_sdrc_params);
-}
-
 static int igep2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -650,6 +643,8 @@ static void __init igep_init(void)
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
 	omap_serial_init();
+	omap_sdrc_init(m65kxxxxam_sdrc_params,
+				  m65kxxxxam_sdrc_params);
 	usb_musb_init(NULL);
 
 	igep_flash_init();
@@ -672,20 +667,20 @@ static void __init igep_init(void)
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-ldp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-ldp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-ldp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-ldp.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/mcspi.h>
-#include <mach/gpio.h>
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
@@ -44,6 +44,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
@@ -180,29 +183,102 @@ static inline void __init ldp_init_smsc9
 	gpmc_smsc911x_init(&smsc911x_cfg);
 }
 
-static struct platform_device ldp_lcd_device = {
-	.name		= "ldp_lcd",
-	.id		= -1,
+/* LCD */
+
+static int ldp_backlight_gpio;
+static int ldp_lcd_enable_gpio;
+
+#define LCD_PANEL_RESET_GPIO		55
+#define LCD_PANEL_QVGA_GPIO		56
+
+static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(ldp_lcd_enable_gpio))
+		gpio_direction_output(ldp_lcd_enable_gpio, 1);
+	if (gpio_is_valid(ldp_backlight_gpio))
+		gpio_direction_output(ldp_backlight_gpio, 1);
+
+	return 0;
+}
+
+static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(ldp_lcd_enable_gpio))
+		gpio_direction_output(ldp_lcd_enable_gpio, 0);
+	if (gpio_is_valid(ldp_backlight_gpio))
+		gpio_direction_output(ldp_backlight_gpio, 0);
+}
+
+static struct panel_generic_dpi_data ldp_panel_data = {
+	.name			= "nec_nl2432dr22-11b",
+	.platform_enable	= ldp_panel_enable_lcd,
+	.platform_disable	= ldp_panel_disable_lcd,
 };
 
-static struct omap_lcd_config ldp_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct omap_dss_device ldp_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 18,
+	.data			= &ldp_panel_data,
 };
 
-static struct omap_board_config_kernel ldp_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&ldp_lcd_config },
+static struct omap_dss_device *ldp_dss_devices[] = {
+	&ldp_lcd_device,
 };
 
-static void __init omap_ldp_init_early(void)
+static struct omap_dss_board_info ldp_dss_data = {
+	.num_devices	= ARRAY_SIZE(ldp_dss_devices),
+	.devices	= ldp_dss_devices,
+	.default_device	= &ldp_lcd_device,
+};
+
+static void __init ldp_display_init(void)
 {
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
+	int r;
+
+	static struct gpio gpios[] __initdata = {
+		{LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"},
+		{LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"},
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		return;
+	}
+
+	omap_display_init(&ldp_dss_data);
+}
+
+static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
+{
+	int r;
+
+	struct gpio gpios[] = {
+		{gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
+		{gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		ldp_backlight_gpio = -EINVAL;
+		ldp_lcd_enable_gpio = -EINVAL;
+		return r;
+	}
+
+	ldp_backlight_gpio = gpio + 15;
+	ldp_lcd_enable_gpio = gpio + 7;
+
+	return 0;
 }
 
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.setup		= ldp_twl_gpio_setup,
 };
 
 static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
@@ -244,10 +320,31 @@ static struct regulator_init_data ldp_va
 	.consumer_supplies		= ldp_vaux1_supplies,
 };
 
+static struct regulator_consumer_supply ldp_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data ldp_vpll2 = {
+	.constraints = {
+		.name			= "VDVI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldp_vpll2_supplies),
+	.consumer_supplies	= ldp_vpll2_supplies,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
 	/* platform_data for children goes here */
 	.vmmc1		= &ldp_vmmc1,
 	.vaux1		= &ldp_vaux1,
+	.vpll2		= &ldp_vpll2,
 	.gpio		= &ldp_gpio_data,
 	.keypad		= &ldp_kp_twl4030_data,
 };
@@ -273,7 +370,6 @@ static struct omap2_hsmmc_info mmc[] __i
 };
 
 static struct platform_device *ldp_devices[] __initdata = {
-	&ldp_lcd_device,
 	&ldp_gpio_keys_device,
 };
 
@@ -318,25 +414,25 @@ static struct mtd_partition ldp_nand_par
 static void __init omap_ldp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = ldp_config;
-	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	ldp_init_smsc911x();
 	omap_i2c_init();
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
 	omap_ads7846_init(1, 54, 310, NULL);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
 	omap2_hsmmc_init(mmc);
+	ldp_display_init();
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_ldp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_ldp_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-n8x0.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-n8x0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-n8x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-n8x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -616,18 +616,6 @@ static struct i2c_board_info n810_i2c_bo
 	},
 };
 
-static void __init n8x0_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
-}
-
-static void __init n8x0_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* I2S codec port pins for McBSP block */
@@ -689,36 +677,37 @@ static void __init n8x0_init_machine(voi
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3beagle.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3beagle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3beagle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3beagle.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,7 +42,7 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
@@ -203,16 +203,16 @@ static void beagle_disable_dvi(struct om
 		gpio_set_value(dssdev->reset_gpio, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
 	.type = OMAP_DISPLAY_TYPE_DPI,
 	.name = "dvi",
-	.driver_name = "generic_dpi_panel",
+	.driver_name = "dvi",
 	.data = &dvi_panel,
 	.phy.dpi.data_lines = 24,
 	.reset_gpio = -EINVAL,
@@ -378,7 +378,8 @@ static struct i2c_board_info __initdata
 static int __init omap3_beagle_i2c_init(void)
 {
 	omap3_pmic_get_config(&beagle_twldata,
-			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+			TWL_COMMON_PDATA_AUDIO,
 			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
 
 	beagle_twldata.vpll2->constraints.name = "VDVI";
@@ -444,21 +445,15 @@ static struct platform_device keys_gpio
 	},
 };
 
-static void __init omap3_beagle_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_beagle_init_irq(void)
-{
-	omap3_init_irq();
-}
+static struct platform_device madc_hwmon = {
+	.name	= "twl4030_madc_hwmon",
+	.id	= -1,
+};
 
 static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
+	&madc_hwmon,
 };
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
@@ -493,8 +488,8 @@ static void __init beagle_opp_init(void)
 	if (cpu_is_omap3630()) {
 		struct device *mpu_dev, *iva_dev;
 
-		mpu_dev = omap2_get_mpuss_device();
-		iva_dev = omap2_get_iva_device();
+		mpu_dev = omap_device_get_by_hwmod_name("mpu");
+		iva_dev = omap_device_get_by_hwmod_name("iva");
 
 		if (!mpu_dev || !iva_dev) {
 			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
@@ -534,6 +529,8 @@ static void __init omap3_beagle_init(voi
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_display_init(&beagle_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -557,11 +554,11 @@ static void __init omap3_beagle_init(voi
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_beagle_init_early,
-	.init_irq	= omap3_beagle_init_irq,
+	.init_early	= omap3_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_beagle_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3evm.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -45,7 +46,7 @@
 #include <plat/common.h>
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -247,8 +248,7 @@ static void omap3_evm_disable_dvi(struct
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= omap3_evm_enable_dvi,
 	.platform_disable	= omap3_evm_disable_dvi,
 };
@@ -256,7 +256,7 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device omap3_evm_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -520,12 +520,6 @@ static int __init omap3_evm_i2c_init(voi
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 };
 
-static void __init omap3_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -640,6 +634,7 @@ static void __init omap3_evm_init(void)
 	omap_display_init(&omap3_evm_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 
 	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
 	usb_nop_xceiv_register();
@@ -681,10 +676,10 @@ static void __init omap3_evm_init(void)
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_evm_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_evm_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3logic.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3logic.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3logic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3logic.c	2012-01-04 18:55:44.000000000 -0500
@@ -182,12 +182,6 @@ static inline void __init board_smsc911x
 	gpmc_smsc911x_init(&board_smsc911x_data);
 }
 
-static void __init omap3logic_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -200,6 +194,7 @@ static void __init omap3logic_init(void)
 	omap3torpedo_fix_pbias_voltage();
 	omap3logic_i2c_init();
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
 
@@ -209,18 +204,18 @@ static void __init omap3logic_init(void)
 }
 
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3pandora.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3pandora.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3pandora.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3pandora.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,7 +335,7 @@ static struct regulator_consumer_supply
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
@@ -525,13 +525,6 @@ static struct spi_board_info omap3pandor
 	}
 };
 
-static void __init omap3pandora_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 static void __init pandora_wl1251_init(void)
 {
 	struct wl12xx_platform_data pandora_wl1251_pdata;
@@ -593,6 +586,8 @@ static void __init omap3pandora_init(voi
 			ARRAY_SIZE(omap3pandora_devices));
 	omap_display_init(&pandora_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
@@ -606,10 +601,10 @@ static void __init omap3pandora_init(voi
 }
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3pandora_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3pandora_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3stalker.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3stalker.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3stalker.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3stalker.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -107,39 +108,6 @@ static void __init omap3_stalker_display
 	return;
 }
 
-static int omap3_stalker_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (dvi_enabled) {
-		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-		return -EINVAL;
-	}
-	gpio_set_value(DSS_ENABLE_GPIO, 1);
-	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1);
-	lcd_enabled = 1;
-	return 0;
-}
-
-static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DSS_ENABLE_GPIO, 0);
-	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0);
-	lcd_enabled = 0;
-}
-
-static struct panel_generic_dpi_data lcd_panel = {
-	.name			= "generic",
-	.platform_enable	= omap3_stalker_enable_lcd,
-	.platform_disable	= omap3_stalker_disable_lcd,
-};
-
-static struct omap_dss_device omap3_stalker_lcd_device = {
-	.name			= "lcd",
-	.driver_name		= "generic_dpi_panel",
-	.data			= &lcd_panel,
-	.phy.dpi.data_lines	= 24,
-	.type			= OMAP_DISPLAY_TYPE_DPI,
-};
-
 static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
 {
 	return 0;
@@ -179,8 +147,7 @@ static void omap3_stalker_disable_dvi(st
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= omap3_stalker_enable_dvi,
 	.platform_disable	= omap3_stalker_disable_dvi,
 };
@@ -188,13 +155,12 @@ static struct panel_generic_dpi_data dvi
 static struct omap_dss_device omap3_stalker_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
 
 static struct omap_dss_device *omap3_stalker_dss_devices[] = {
-	&omap3_stalker_lcd_device,
 	&omap3_stalker_tv_device,
 	&omap3_stalker_dvi_device,
 };
@@ -428,17 +394,6 @@ static int __init omap3_stalker_i2c_init
 static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
 };
 
-static void __init omap3_stalker_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
-static void __init omap3_stalker_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_stalker_devices[] __initdata = {
 	&keys_gpio,
 };
@@ -478,6 +433,7 @@ static void __init omap3_stalker_init(vo
 	omap_display_init(&omap3_stalker_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
@@ -494,10 +450,10 @@ static void __init omap3_stalker_init(vo
 
 MACHINE_START(SBC3530, "OMAP3 STALKER")
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
-	.boot_params		= 0x80000100,
+	.atag_offset		= 0x100,
 	.map_io			= omap3_map_io,
-	.init_early		= omap3_stalker_init_early,
-	.init_irq		= omap3_stalker_init_irq,
+	.init_early		= omap35xx_init_early,
+	.init_irq		= omap3_init_irq,
 	.init_machine		= omap3_stalker_init,
 	.timer			= &omap3_secure_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,15 +104,6 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct platform_device omap3_touchbook_lcd_device = {
-	.name		= "omap3touchbook_lcd",
-	.id		= -1,
-};
-
-static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -165,14 +156,12 @@ static struct twl4030_gpio_platform_data
 static struct regulator_consumer_supply touchbook_vdac_supply[] = {
 {
 	.supply		= "vdac",
-	.dev		= &omap3_touchbook_lcd_device.dev,
 },
 };
 
 static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
 {
 	.supply		= "vdvi",
-	.dev		= &omap3_touchbook_lcd_device.dev,
 },
 };
 
@@ -316,30 +305,13 @@ static struct platform_device keys_gpio
 	},
 };
 
-static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&omap3_touchbook_lcd_config },
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #endif
 
-static void __init omap3_touchbook_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_touchbook_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
-	&omap3_touchbook_lcd_device,
 	&leds_gpio,
 	&keys_gpio,
 };
@@ -376,8 +348,6 @@ early_param("tbr", early_touchbook_revis
 static void __init omap3_touchbook_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = omap3_touchbook_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
 
 	pm_power_off = omap3_touchbook_poweroff;
 
@@ -385,6 +355,8 @@ static void __init omap3_touchbook_init(
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -404,11 +376,11 @@ static void __init omap3_touchbook_init(
 
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_touchbook_init_early,
-	.init_irq	= omap3_touchbook_init_irq,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_touchbook_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap4panda.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap4panda.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-omap4panda.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-omap4panda.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "hsmmc.h"
 #include "control.h"
@@ -95,12 +95,6 @@ static struct platform_device *panda_dev
 	&wl1271_device,
 };
 
-static void __init omap4_panda_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -455,16 +449,16 @@ static void omap4_panda_disable_dvi(stru
 }
 
 /* Using generic display panel */
-static struct panel_generic_dpi_data omap4_dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data omap4_dvi_panel = {
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &omap4_dvi_panel,
 	.phy.dpi.data_lines	= 24,
 	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
@@ -569,24 +563,19 @@ static void __init omap4_panda_init(void
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	platform_device_register(&omap_vwlan_device);
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
 	usb_musb_init(&musb_board_data);
 	omap4_panda_display_init();
 }
 
-static void __init omap4_panda_map_io(void)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap4_panda_map_io,
-	.init_early	= omap4_panda_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
 	.timer		= &omap4_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-overo.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-overo.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-overo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-overo.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include <plat/common.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
@@ -182,16 +183,16 @@ static void overo_panel_disable_dvi(stru
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= overo_panel_enable_dvi,
 	.platform_disable	= overo_panel_disable_dvi,
+	.i2c_bus_num		= 3,
 };
 
 static struct omap_dss_device overo_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -478,13 +479,6 @@ static int __init overo_spi_init(void)
 	return 0;
 }
 
-static void __init overo_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
@@ -514,6 +508,8 @@ static void __init overo_init(void)
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_nand_flash_init(0, overo_nand_partitions,
 			     ARRAY_SIZE(overo_nand_partitions));
 	usb_musb_init(NULL);
@@ -561,10 +557,10 @@ static void __init overo_init(void)
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= overo_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= overo_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rm680.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rm680.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rm680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rm680.c	2012-01-04 18:55:44.000000000 -0500
@@ -123,15 +123,6 @@ static void __init rm680_peripherals_ini
 	omap2_hsmmc_init(mmc);
 }
 
-static void __init rm680_init_early(void)
-{
-	struct omap_sdrc_params *sdrc_params;
-
-	omap2_init_common_infrastructure();
-	sdrc_params = nokia_get_sdram_timings();
-	omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -140,23 +131,23 @@ static struct omap_board_mux board_mux[]
 
 static void __init rm680_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
 }
 
-static void __init rm680_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= rm680_map_io,
-	.init_early	= rm680_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rm680_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rx51.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rx51.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rx51.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rx51.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,38 +79,6 @@ static struct cpuidle_params rx51_cpuidl
 	{7505 + 15274, 484329, 1},
 };
 
-static struct omap_lcd_config rx51_lcd_config = {
-	.ctrl_name	= "internal",
-};
-
-static struct omap_fbmem_config rx51_fbmem0_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem1_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem2_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_board_config_kernel rx51_config[] = {
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem0_config },
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem1_config },
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem2_config },
-	{ OMAP_TAG_LCD,		&rx51_lcd_config },
-};
-
-static void __init rx51_init_early(void)
-{
-	struct omap_sdrc_params *sdrc_params;
-
-	omap2_init_common_infrastructure();
-	sdrc_params = nokia_get_sdram_timings();
-	omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
 extern void __init rx51_peripherals_init(void);
 
 #ifdef CONFIG_OMAP_MUX
@@ -127,11 +95,15 @@ static struct omap_musb_board_data musb_
 
 static void __init rx51_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = rx51_config;
-	omap_board_config_size = ARRAY_SIZE(rx51_config);
 	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap_serial_init();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
 
@@ -142,12 +114,6 @@ static void __init rx51_init(void)
 	platform_device_register(&leds_gpio);
 }
 
-static void __init rx51_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 static void __init rx51_reserve(void)
 {
 	rx51_video_mem_init();
@@ -156,10 +122,10 @@ static void __init rx51_reserve(void)
 
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= rx51_reserve,
-	.map_io		= rx51_map_io,
-	.init_early	= rx51_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rx51_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,7 +193,7 @@ static struct platform_device rx51_charg
 static void __init rx51_charger_init(void)
 {
 	WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO,
-		GPIOF_OUT_INIT_LOW, "isp1704_reset"));
+		GPIOF_OUT_INIT_HIGH, "isp1704_reset"));
 
 	platform_device_register(&rx51_charger_device);
 }
@@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51
 };
 
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
-	.id			= TPA6130A2,
 	.power_gpio		= 98,
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-ti8168evm.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-ti8168evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-ti8168evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-ti8168evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,30 +27,24 @@
 static struct omap_board_config_kernel ti8168_evm_config[] __initdata = {
 };
 
-static void __init ti8168_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static void __init ti8168_evm_init(void)
 {
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap_board_config = ti8168_evm_config;
 	omap_board_config_size = ARRAY_SIZE(ti8168_evm_config);
 }
 
 static void __init ti8168_evm_map_io(void)
 {
-	omap2_set_globals_ti816x();
 	omapti816x_map_common_io();
 }
 
 MACHINE_START(TI8168EVM, "ti8168evm")
 	/* Maintainer: Texas Instruments */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= ti8168_evm_map_io,
-	.init_early	= ti8168_init_early,
+	.init_early	= ti816x_init_early,
 	.init_irq	= ti816x_init_irq,
 	.timer		= &omap3_timer,
 	.init_machine	= ti8168_evm_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-zoom.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-zoom.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/board-zoom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/board-zoom.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,17 +34,6 @@
 
 #define ZOOM3_EHCI_RESET_GPIO		64
 
-static void __init omap_zoom_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	if (machine_is_omap_zoom2())
-		omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-					  mt46h32m32lf6_sdrc_params);
-	else if (machine_is_omap_zoom3())
-		omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-					  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* WLAN IRQ - GPIO 162 */
@@ -129,24 +118,32 @@ static void __init omap_zoom_init(void)
 						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
+
+	if (machine_is_omap_zoom2())
+		omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+					  mt46h32m32lf6_sdrc_params);
+	else if (machine_is_omap_zoom3())
+		omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+					  h8mbx00u0mer0em_sdrc_params);
+
 	zoom_display_init();
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clkt_dpll.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clkt_dpll.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clkt_dpll.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clkt_dpll.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,10 +46,19 @@
 					 (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define DPLL_FINT_BAND1_MIN		750000
-#define DPLL_FINT_BAND1_MAX		2100000
-#define DPLL_FINT_BAND2_MIN		7500000
-#define DPLL_FINT_BAND2_MAX		21000000
+#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN	500000
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX	2500000
+#define OMAP3PLUS_DPLL_FINT_MIN		32000
+#define OMAP3PLUS_DPLL_FINT_MAX		52000000
 
 /* _dpll_test_fint() return codes */
 #define DPLL_FINT_UNDERFLOW		-1
@@ -71,33 +80,43 @@
 static int _dpll_test_fint(struct clk *clk, u8 n)
 {
 	struct dpll_data *dd;
-	long fint;
+	long fint, fint_min, fint_max;
 	int ret = 0;
 
 	dd = clk->dpll_data;
 
 	/* DPLL divider must result in a valid jitter correction val */
 	fint = clk->parent->rate / n;
-	if (fint < DPLL_FINT_BAND1_MIN) {
 
+	if (cpu_is_omap24xx()) {
+		/* Should not be called for OMAP2, so warn if it is called */
+		WARN(1, "No fint limits available for OMAP2!\n");
+		return DPLL_FINT_INVALID;
+	} else if (cpu_is_omap3430()) {
+		fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+		fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+	} else if (dd->flags & DPLL_J_TYPE) {
+		fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
+		fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
+	} else {
+		fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+		fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+	}
+
+	if (fint < fint_min) {
 		pr_debug("rejecting n=%d due to Fint failure, "
 			 "lowering max_divider\n", n);
 		dd->max_divider = n;
 		ret = DPLL_FINT_UNDERFLOW;
-
-	} else if (fint > DPLL_FINT_BAND1_MAX &&
-		   fint < DPLL_FINT_BAND2_MIN) {
-
-		pr_debug("rejecting n=%d due to Fint failure\n", n);
-		ret = DPLL_FINT_INVALID;
-
-	} else if (fint > DPLL_FINT_BAND2_MAX) {
-
+	} else if (fint > fint_max) {
 		pr_debug("rejecting n=%d due to Fint failure, "
 			 "boosting min_divider\n", n);
 		dd->min_divider = n;
 		ret = DPLL_FINT_INVALID;
-
+	} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
+		   fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+		pr_debug("rejecting n=%d due to Fint failure\n", n);
+		ret = DPLL_FINT_INVALID;
 	}
 
 	return ret;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock2420_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock2420_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock2420_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1898,6 +1898,42 @@ static struct omap_clk omap2420_clks[] =
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
 	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK("omap_timer.1",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.2",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.3",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.4",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.5",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.6",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.7",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.8",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.9",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.10",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.11",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.12",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock2430_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock2430_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock2430_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1998,6 +1998,42 @@ static struct omap_clk omap2430_clks[] =
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
 	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
 	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_timer.1",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.2",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.3",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.4",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.5",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.6",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.7",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.8",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.9",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.10",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.11",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.12",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -3464,6 +3464,30 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK("musb-am35x",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
 	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
+	CLK("omap_timer.1",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.2",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.3",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.4",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.5",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.6",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.7",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.8",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.9",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.10",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.11",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.12",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_3XXX),
 };
 
 
@@ -3472,7 +3496,16 @@ int __init omap3xxx_clk_init(void)
 	struct omap_clk *c;
 	u32 cpu_clkflg = 0;
 
-	if (cpu_is_omap3517()) {
+	/*
+	 * 3505 must be tested before 3517, since 3517 returns true
+	 * for both AM3517 chips and AM3517 family chips, which
+	 * includes 3505.  Unfortunately there's no obvious family
+	 * test for 3517/3505 :-(
+	 */
+	if (cpu_is_omap3505()) {
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_3505;
+	} else if (cpu_is_omap3517()) {
 		cpu_mask = RATE_IN_34XX;
 		cpu_clkflg = CK_3517;
 	} else if (cpu_is_omap3505()) {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -270,8 +270,8 @@ static struct clk dpll_abe_ck = {
 	.dpll_data	= &dpll_abe_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
+	.recalc		= &omap4_dpll_regm4xen_recalc,
+	.round_rate	= &omap4_dpll_regm4xen_round_rate,
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
@@ -1195,11 +1195,25 @@ static struct clk l4_wkup_clk_mux_ck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate div2_2to1_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
+static const struct clksel ocp_abe_iclk_div[] = {
+	{ .parent = &aess_fclk, .rates = div2_2to1_rates },
+	{ .parent = NULL },
+};
+
 static struct clk ocp_abe_iclk = {
 	.name		= "ocp_abe_iclk",
 	.parent		= &aess_fclk,
+	.clksel		= ocp_abe_iclk_div,
+	.clksel_reg	= OMAP4430_CM1_ABE_AESS_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_AESS_FCLK_MASK,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk per_abe_24m_fclk = {
@@ -1398,9 +1412,9 @@ static struct clk dss_dss_clk = {
 };
 
 static const struct clksel_rate div3_8to32_rates[] = {
-	{ .div = 8, .val = 0, .flags = RATE_IN_44XX },
-	{ .div = 16, .val = 1, .flags = RATE_IN_44XX },
-	{ .div = 32, .val = 2, .flags = RATE_IN_44XX },
+	{ .div = 8, .val = 0, .flags = RATE_IN_4460 },
+	{ .div = 16, .val = 1, .flags = RATE_IN_4460 },
+	{ .div = 32, .val = 2, .flags = RATE_IN_4460 },
 	{ .div = 0 },
 };
 
@@ -3363,6 +3377,28 @@ static struct omap_clk omap44xx_clks[] =
 	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_timer.1",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.2",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.3",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.4",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.5",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.6",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.7",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.8",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.9",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.10",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.11",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.5",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.6",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.7",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.8",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
@@ -3370,12 +3406,12 @@ int __init omap4xxx_clk_init(void)
 	struct omap_clk *c;
 	u32 cpu_clkflg;
 
-	if (cpu_is_omap44xx()) {
+	if (cpu_is_omap443x()) {
 		cpu_mask = RATE_IN_4430;
 		cpu_clkflg = CK_443X;
 	} else if (cpu_is_omap446x()) {
-		cpu_mask = RATE_IN_4460;
-		cpu_clkflg = CK_446X;
+		cpu_mask = RATE_IN_4460 | RATE_IN_4430;
+		cpu_clkflg = CK_446X | CK_443X;
 	} else {
 		return 0;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock44xx.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock44xx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,13 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 
+/*
+ * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
+ *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
+ *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
+ */
+#define OMAP4430_REGM4XEN_MULT	4
+
 int omap4xxx_clk_init(void);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@ static int omap2_clkdm_clear_all_wkdeps(
 	u32 mask = 0;
 
 	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
@@ -98,8 +96,6 @@ static int omap3_clkdm_clear_all_sleepde
 	u32 mask = 0;
 
 	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain44xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain44xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@ static int omap4_clkdm_clear_all_wkup_sl
 	u32 mask = 0;
 
 	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/limits.h>
@@ -73,9 +74,6 @@ static int _clkdm_register(struct clockd
 	if (!clkdm || !clkdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(clkdm->omap_chip))
-		return -EINVAL;
-
 	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
 	if (!pwrdm) {
 		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
@@ -105,13 +103,10 @@ static struct clkdm_dep *_clkdm_deps_loo
 {
 	struct clkdm_dep *cd;
 
-	if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip))
+	if (!clkdm || !deps)
 		return ERR_PTR(-EINVAL);
 
 	for (cd = deps; cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
 		if (!cd->clkdm && cd->clkdm_name)
 			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
 
@@ -148,9 +143,6 @@ static void _autodep_lookup(struct clkdm
 	if (!autodep)
 		return;
 
-	if (!omap_chip_is(autodep->omap_chip))
-		return;
-
 	clkdm = clkdm_lookup(autodep->clkdm.name);
 	if (!clkdm) {
 		pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
@@ -182,9 +174,6 @@ void _clkdm_add_autodeps(struct clockdom
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -216,9 +205,6 @@ void _clkdm_del_autodeps(struct clockdom
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -243,8 +229,6 @@ static void _resolve_clkdm_deps(struct c
 	struct clkdm_dep *cd;
 
 	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (cd->clkdm)
 			continue;
 		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
@@ -257,43 +241,113 @@ static void _resolve_clkdm_deps(struct c
 /* Public functions */
 
 /**
- * clkdm_init - set up the clockdomain layer
- * @clkdms: optional pointer to an array of clockdomains to register
- * @init_autodeps: optional pointer to an array of autodeps to register
- * @custom_funcs: func pointers for arch specific implementations
+ * clkdm_register_platform_funcs - register clockdomain implementation fns
+ * @co: func pointers for arch specific implementations
  *
- * Set up internal state.  If a pointer to an array of clockdomains
- * @clkdms was supplied, loop through the list of clockdomains,
- * register all that are available on the current platform. Similarly,
- * if a pointer to an array of clockdomain autodependencies
- * @init_autodeps was provided, register those.  No return value.
+ * Register the list of function pointers used to implement the
+ * clockdomain functions on different OMAP SoCs.  Should be called
+ * before any other clkdm_register*() function.  Returns -EINVAL if
+ * @co is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
  */
-void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps,
-		struct clkdm_ops *custom_funcs)
+int clkdm_register_platform_funcs(struct clkdm_ops *co)
+{
+	if (!co)
+		return -EINVAL;
+
+	if (arch_clkdm)
+		return -EEXIST;
+
+	arch_clkdm = co;
+
+	return 0;
+};
+
+/**
+ * clkdm_register_clkdms - register SoC clockdomains
+ * @cs: pointer to an array of struct clockdomain to register
+ *
+ * Register the clockdomains available on a particular OMAP SoC.  Must
+ * be called after clkdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
+ * null; or 0 upon success.
+ */
+int clkdm_register_clkdms(struct clockdomain **cs)
 {
 	struct clockdomain **c = NULL;
-	struct clockdomain *clkdm;
-	struct clkdm_autodep *autodep = NULL;
 
-	if (!custom_funcs)
-		WARN(1, "No custom clkdm functions registered\n");
-	else
-		arch_clkdm = custom_funcs;
+	if (!arch_clkdm)
+		return -EACCES;
 
-	if (clkdms)
-		for (c = clkdms; *c; c++)
-			_clkdm_register(*c);
+	if (!cs)
+		return -EINVAL;
+
+	for (c = cs; *c; c++)
+		_clkdm_register(*c);
+
+	return 0;
+}
+
+/**
+ * clkdm_register_autodeps - register autodeps (if required)
+ * @ia: pointer to a static array of struct clkdm_autodep to register
+ *
+ * Register clockdomain "automatic dependencies."  These are
+ * clockdomain wakeup and sleep dependencies that are automatically
+ * added whenever the first clock inside a clockdomain is enabled, and
+ * removed whenever the last clock inside a clockdomain is disabled.
+ * These are currently only used on OMAP3 devices, and are deprecated,
+ * since they waste energy.  However, until the OMAP2/3 IP block
+ * enable/disable sequence can be converted to match the OMAP4
+ * sequence, they are needed.
+ *
+ * Must be called only after all of the SoC clockdomains are
+ * registered, since the function will resolve autodep clockdomain
+ * names into clockdomain pointers.
+ *
+ * The struct clkdm_autodep @ia array must be static, as this function
+ * does not copy the array elements.
+ *
+ * Returns -EACCES if called before any clockdomains have been
+ * registered, -EINVAL if called with a null @ia argument, -EEXIST if
+ * autodeps have already been registered, or 0 upon success.
+ */
+int clkdm_register_autodeps(struct clkdm_autodep *ia)
+{
+	struct clkdm_autodep *a = NULL;
+
+	if (list_empty(&clkdm_list))
+		return -EACCES;
+
+	if (!ia)
+		return -EINVAL;
 
-	autodeps = init_autodeps;
 	if (autodeps)
-		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
-			_autodep_lookup(autodep);
+		return -EEXIST;
+
+	autodeps = ia;
+	for (a = autodeps; a->clkdm.ptr; a++)
+		_autodep_lookup(a);
+
+	return 0;
+}
+
+/**
+ * clkdm_complete_init - set up the clockdomain layer
+ *
+ * Put all clockdomains into software-supervised mode; PM code should
+ * later enable hardware-supervised mode as appropriate.  Must be
+ * called after clkdm_register_clkdms().  Returns -EACCES if called
+ * before clkdm_register_clkdms(), or 0 upon success.
+ */
+int clkdm_complete_init(void)
+{
+	struct clockdomain *clkdm;
+
+	if (list_empty(&clkdm_list))
+		return -EACCES;
 
-	/*
-	 * Put all clockdomains into software-supervised mode; PM code
-	 * should later enable hardware-supervised mode as appropriate
-	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
 			clkdm_wakeup(clkdm);
@@ -306,6 +360,8 @@ void clkdm_init(struct clockdomain **clk
 		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
+
+	return 0;
 }
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomain.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomain.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,6 @@
 /**
  * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
  * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
- * @omap_chip: OMAP chip types that this autodep is valid on
  *
  * A clockdomain that should have wkdeps and sleepdeps added when a
  * clockdomain should stay active in hwsup mode; and conversely,
@@ -60,14 +59,12 @@ struct clkdm_autodep {
 		const char *name;
 		struct clockdomain *ptr;
 	} clkdm;
-	const struct omap_chip_id omap_chip;
 };
 
 /**
  * struct clkdm_dep - encode dependencies between clockdomains
  * @clkdm_name: clockdomain name
  * @clkdm: pointer to the struct clockdomain of @clkdm_name
- * @omap_chip: OMAP chip types that this dependency is valid on
  * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
  * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
  *
@@ -81,7 +78,6 @@ struct clkdm_dep {
 	struct clockdomain *clkdm;
 	atomic_t wkdep_usecount;
 	atomic_t sleepdep_usecount;
-	const struct omap_chip_id omap_chip;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -101,7 +97,6 @@ struct clkdm_dep {
  * @clkdm_offs: (OMAP4 only) CM clockdomain register offset
  * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
  * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
- * @omap_chip: OMAP chip types that this clockdomain is valid on
  * @usecount: Usecount tracking
  * @node: list_head to link all clockdomains together
  *
@@ -126,7 +121,6 @@ struct clockdomain {
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	const struct omap_chip_id omap_chip;
 	atomic_t usecount;
 	struct list_head node;
 	spinlock_t lock;
@@ -166,8 +160,11 @@ struct clkdm_ops {
 	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
-			struct clkdm_ops *custom_funcs);
+int clkdm_register_platform_funcs(struct clkdm_ops *co);
+int clkdm_register_autodeps(struct clkdm_autodep *ia);
+int clkdm_register_clkdms(struct clockdomain **c);
+int clkdm_complete_init(void);
+
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -195,7 +192,8 @@ int clkdm_clk_disable(struct clockdomain
 int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
-extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap242x_clockdomains_init(void);
+extern void __init omap243x_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
 extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
@@ -205,4 +203,10 @@ extern struct clkdm_ops omap2_clkdm_oper
 extern struct clkdm_ops omap3_clkdm_operations;
 extern struct clkdm_ops omap4_clkdm_operations;
 
+extern struct clkdm_dep gfx_24xx_wkdeps[];
+extern struct clkdm_dep dsp_24xx_wkdeps[];
+extern struct clockdomain wkup_common_clkdm;
+extern struct clockdomain prm_common_clkdm;
+extern struct clockdomain cm_common_clkdm;
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2420_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2420_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2420_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+/*
+ * OMAP2420 clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2420 chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2420-specific possible wakeup dependencies */
+
+/* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP */
+static struct clkdm_dep mpu_2420_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP */
+static struct clkdm_dep core_2420_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+static struct clockdomain mpu_2420_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= mpu_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+	.name		= "iva1_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+};
+
+static struct clockdomain dsp_2420_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2420_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+static struct clockdomain core_l3_2420_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+static struct clockdomain core_l4_2420_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2420_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap242x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2420_clkdm,
+	&iva1_2420_clkdm,
+	&dsp_2420_clkdm,
+	&gfx_2420_clkdm,
+	&core_l3_2420_clkdm,
+	&core_l4_2420_clkdm,
+	&dss_2420_clkdm,
+	NULL,
+};
+
+void __init omap242x_clockdomains_init(void)
+{
+	if (!cpu_is_omap242x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap242x);
+	clkdm_complete_init();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2430_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2430_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2430_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,181 @@
+/*
+ * OMAP2xxx clockdomains
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2430-specific possible wakeup dependencies */
+
+/* 2430 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP, MDM */
+static struct clkdm_dep core_2430_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MPU: CORE, DSP, WKUP, MDM */
+static struct clkdm_dep mpu_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2430-only clockdomains
+ */
+
+static struct clockdomain mpu_2430_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= mpu_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct clockdomain mdm_clkdm = {
+	.name		= "mdm_clkdm",
+	.pwrdm		= { .name = "mdm_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+	.wkdep_srcs	= mdm_2430_wkdeps,
+	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+};
+
+static struct clockdomain dsp_2430_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2430_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_2430_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_2430_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2430_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap243x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2430_clkdm,
+	&mdm_clkdm,
+	&dsp_2430_clkdm,
+	&gfx_2430_clkdm,
+	&core_l3_2430_clkdm,
+	&core_l4_2430_clkdm,
+	&dss_2430_clkdm,
+	NULL,
+};
+
+void __init omap243x_clockdomains_init(void)
+{
+	if (!cpu_is_omap243x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap243x);
+	clkdm_complete_init();
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * OMAP2/3 clockdomains
+ * OMAP2/3 clockdomain common data
  *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
  * Copyright (C) 2008-2010 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -51,374 +51,28 @@
  * changed in software) are not included here yet, but should be.
  */
 
-/* OMAP2/3-common wakeup dependencies */
-
-/*
- * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
- * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
- * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 24XX-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP2
-
 /* Wakeup dependency source arrays */
 
-/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
-static struct clkdm_dep dsp_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep mpu_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep core_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "gfx_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
-/* 2430-specific possible wakeup dependencies */
-
-#ifdef CONFIG_SOC_OMAP2430
-
-/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
-static struct clkdm_dep mdm_2430_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_SOC_OMAP2430 */
-
-
-/* OMAP3-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep per_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep usbhost_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
-static struct clkdm_dep mpu_3xxx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
-static struct clkdm_dep iva2_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
-static struct clkdm_dep cam_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
-static struct clkdm_dep dss_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: PM_WKDEP_NEON: MPU */
-static struct clkdm_dep neon_wkdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* Sleep dependency source arrays for OMAP3-specific clkdms */
-
-/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
-static struct clkdm_dep dss_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
-static struct clkdm_dep per_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
-static struct clkdm_dep usbhost_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
+/* 2xxx-specific possible dependencies */
 
-/* 3430: CM_SLEEPDEP_CAM: MPU */
-static struct clkdm_dep cam_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_GFX: CORE, MPU, WKUP */
+struct clkdm_dep gfx_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-/*
- * 3430ES1: CM_SLEEPDEP_GFX: MPU
- * 3430ES2: CM_SLEEPDEP_SGX: MPU
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_DSP: CORE, MPU, WKUP */
+struct clkdm_dep dsp_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-#endif /* CONFIG_ARCH_OMAP3 */
-
 
 /*
  * OMAP2/3-common clockdomains
@@ -430,439 +84,18 @@ static struct clkdm_dep gfx_sgx_sleepdep
  */
 
 /* This is an implicit clockdomain - it is never defined as such in TRM */
-static struct clockdomain wkup_clkdm = {
+struct clockdomain wkup_common_clkdm = {
 	.name		= "wkup_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
 	.dep_bit	= OMAP_EN_WKUP_SHIFT,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain prm_clkdm = {
+struct clockdomain prm_common_clkdm = {
 	.name		= "prm_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain cm_clkdm = {
+struct clockdomain cm_common_clkdm = {
 	.name		= "cm_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
-
-/*
- * 2420-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2420)
-
-static struct clockdomain mpu_2420_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain iva1_2420_clkdm = {
-	.name		= "iva1_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dsp_2420_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain gfx_2420_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l3_2420_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l4_2420_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dss_2420_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-#endif   /* CONFIG_SOC_OMAP2420 */
-
-
-/*
- * 2430-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2430)
-
-static struct clockdomain mpu_2430_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/* Another case of bit name collisions between several registers: EN_MDM */
-static struct clockdomain mdm_clkdm = {
-	.name		= "mdm_clkdm",
-	.pwrdm		= { .name = "mdm_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	= mdm_2430_wkdeps,
-	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dsp_2430_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain gfx_2430_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_2430_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_2430_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dss_2430_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-#endif    /* CONFIG_SOC_OMAP2430 */
-
-
-/*
- * OMAP3 clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct clockdomain mpu_3xxx_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
-	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
-	.wkdep_srcs	= mpu_3xxx_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain neon_clkdm = {
-	.name		= "neon_clkdm",
-	.pwrdm		= { .name = "neon_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= neon_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain iva2_clkdm = {
-	.name		= "iva2_clkdm",
-	.pwrdm		= { .name = "iva2_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
-	.wkdep_srcs	= iva2_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain gfx_3430es1_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
-};
-
-static struct clockdomain sgx_clkdm = {
-	.name		= "sgx_clkdm",
-	.pwrdm		= { .name = "sgx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-/*
- * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
- * then that information was removed from the 34xx ES2+ TRM.  It is
- * unclear whether the core is still there, but the clockdomain logic
- * is there, and must be programmed to an appropriate state if the
- * CORE clockdomain is to become inactive.
- */
-static struct clockdomain d2d_clkdm = {
-	.name		= "d2d_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_3xxx_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_3xxx_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/* Another case of bit name collisions between several registers: EN_DSS */
-static struct clockdomain dss_3xxx_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "dss_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
-	.wkdep_srcs	= dss_wkdeps,
-	.sleepdep_srcs	= dss_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cam_clkdm = {
-	.name		= "cam_clkdm",
-	.pwrdm		= { .name = "cam_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= cam_wkdeps,
-	.sleepdep_srcs	= cam_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain usbhost_clkdm = {
-	.name		= "usbhost_clkdm",
-	.pwrdm		= { .name = "usbhost_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= usbhost_wkdeps,
-	.sleepdep_srcs	= usbhost_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-static struct clockdomain per_clkdm = {
-	.name		= "per_clkdm",
-	.pwrdm		= { .name = "per_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_EN_PER_SHIFT,
-	.wkdep_srcs	= per_wkdeps,
-	.sleepdep_srcs	= per_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
- * switched of even if sdti is in use
- */
-static struct clockdomain emu_clkdm = {
-	.name		= "emu_clkdm",
-	.pwrdm		= { .name = "emu_pwrdm" },
-	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll1_clkdm = {
-	.name		= "dpll1_clkdm",
-	.pwrdm		= { .name = "dpll1_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll2_clkdm = {
-	.name		= "dpll2_clkdm",
-	.pwrdm		= { .name = "dpll2_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll3_clkdm = {
-	.name		= "dpll3_clkdm",
-	.pwrdm		= { .name = "dpll3_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll4_clkdm = {
-	.name		= "dpll4_clkdm",
-	.pwrdm		= { .name = "dpll4_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll5_clkdm = {
-	.name		= "dpll5_clkdm",
-	.pwrdm		= { .name = "dpll5_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-#endif   /* CONFIG_ARCH_OMAP3 */
-
-/*
- * Clockdomain hwsup dependencies (OMAP3 only)
- */
-
-static struct clkdm_autodep clkdm_autodeps[] = {
-	{
-		.clkdm	   = { .name = "mpu_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = "iva2_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = NULL },
-	}
-};
-
-static struct clockdomain *clockdomains_omap2[] __initdata = {
-	&wkup_clkdm,
-	&cm_clkdm,
-	&prm_clkdm,
-
-#ifdef CONFIG_SOC_OMAP2420
-	&mpu_2420_clkdm,
-	&iva1_2420_clkdm,
-	&dsp_2420_clkdm,
-	&gfx_2420_clkdm,
-	&core_l3_2420_clkdm,
-	&core_l4_2420_clkdm,
-	&dss_2420_clkdm,
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-	&mpu_2430_clkdm,
-	&mdm_clkdm,
-	&dsp_2430_clkdm,
-	&gfx_2430_clkdm,
-	&core_l3_2430_clkdm,
-	&core_l4_2430_clkdm,
-	&dss_2430_clkdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-	&mpu_3xxx_clkdm,
-	&neon_clkdm,
-	&iva2_clkdm,
-	&gfx_3430es1_clkdm,
-	&sgx_clkdm,
-	&d2d_clkdm,
-	&core_l3_3xxx_clkdm,
-	&core_l4_3xxx_clkdm,
-	&dss_3xxx_clkdm,
-	&cam_clkdm,
-	&usbhost_clkdm,
-	&per_clkdm,
-	&emu_clkdm,
-	&dpll1_clkdm,
-	&dpll2_clkdm,
-	&dpll3_clkdm,
-	&dpll4_clkdm,
-	&dpll5_clkdm,
-#endif
-	NULL,
-};
-
-void __init omap2xxx_clockdomains_init(void)
-{
-	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
-}
-
-void __init omap3xxx_clockdomains_init(void)
-{
-	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,398 @@
+/*
+ * OMAP3xxx clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP3xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies.  Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP3-specific possible dependencies */
+
+/*
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm", },
+	{ .clkdm_name = "mpu_clkdm", },
+	{ .clkdm_name = "wkup_clkdm", },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
+static struct clkdm_dep mpu_3xxx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
+static struct clkdm_dep iva2_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/* Sleep dependency source arrays for OMAP3-specific clkdms */
+
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
+ */
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * OMAP3 clockdomains
+ */
+
+static struct clockdomain mpu_3xxx_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
+	.wkdep_srcs	= mpu_3xxx_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
+static struct clockdomain neon_clkdm = {
+	.name		= "neon_clkdm",
+	.pwrdm		= { .name = "neon_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= neon_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+};
+
+static struct clockdomain iva2_clkdm = {
+	.name		= "iva2_clkdm",
+	.pwrdm		= { .name = "iva2_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+	.wkdep_srcs	= iva2_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+};
+
+static struct clockdomain sgx_clkdm = {
+	.name		= "sgx_clkdm",
+	.pwrdm		= { .name = "sgx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM.  It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+	.name		= "d2d_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_3xxx_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_3xxx_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct clockdomain dss_3xxx_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "dss_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+	.wkdep_srcs	= dss_wkdeps,
+	.sleepdep_srcs	= dss_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
+static struct clockdomain cam_clkdm = {
+	.name		= "cam_clkdm",
+	.pwrdm		= { .name = "cam_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= cam_wkdeps,
+	.sleepdep_srcs	= cam_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+};
+
+static struct clockdomain usbhost_clkdm = {
+	.name		= "usbhost_clkdm",
+	.pwrdm		= { .name = "usbhost_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= usbhost_wkdeps,
+	.sleepdep_srcs	= usbhost_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
+static struct clockdomain per_clkdm = {
+	.name		= "per_clkdm",
+	.pwrdm		= { .name = "per_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_EN_PER_SHIFT,
+	.wkdep_srcs	= per_wkdeps,
+	.sleepdep_srcs	= per_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
+static struct clockdomain emu_clkdm = {
+	.name		= "emu_clkdm",
+	.pwrdm		= { .name = "emu_pwrdm" },
+	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+};
+
+static struct clockdomain dpll1_clkdm = {
+	.name		= "dpll1_clkdm",
+	.pwrdm		= { .name = "dpll1_pwrdm" },
+};
+
+static struct clockdomain dpll2_clkdm = {
+	.name		= "dpll2_clkdm",
+	.pwrdm		= { .name = "dpll2_pwrdm" },
+};
+
+static struct clockdomain dpll3_clkdm = {
+	.name		= "dpll3_clkdm",
+	.pwrdm		= { .name = "dpll3_pwrdm" },
+};
+
+static struct clockdomain dpll4_clkdm = {
+	.name		= "dpll4_clkdm",
+	.pwrdm		= { .name = "dpll4_pwrdm" },
+};
+
+static struct clockdomain dpll5_clkdm = {
+	.name		= "dpll5_clkdm",
+	.pwrdm		= { .name = "dpll5_pwrdm" },
+};
+
+/*
+ * Clockdomain hwsup dependencies
+ */
+
+static struct clkdm_autodep clkdm_autodeps[] = {
+	{
+		.clkdm = { .name = "mpu_clkdm" },
+	},
+	{
+		.clkdm = { .name = "iva2_clkdm" },
+	},
+	{
+		.clkdm = { .name = NULL },
+	}
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_3xxx_clkdm,
+	&neon_clkdm,
+	&iva2_clkdm,
+	&d2d_clkdm,
+	&core_l3_3xxx_clkdm,
+	&core_l4_3xxx_clkdm,
+	&dss_3xxx_clkdm,
+	&cam_clkdm,
+	&per_clkdm,
+	&emu_clkdm,
+	&dpll1_clkdm,
+	&dpll2_clkdm,
+	&dpll3_clkdm,
+	&dpll4_clkdm,
+	NULL
+};
+
+static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
+	&gfx_3430es1_clkdm,
+	NULL,
+};
+
+static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
+	&sgx_clkdm,
+	&dpll5_clkdm,
+	&usbhost_clkdm,
+	NULL,
+};
+
+void __init omap3xxx_clockdomains_init(void)
+{
+	struct clockdomain **sc;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	clkdm_register_platform_funcs(&omap3_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap3430_common);
+
+	sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
+		clockdomains_omap3430es2plus;
+
+	clkdm_register_clkdms(sc);
+
+	clkdm_register_autodeps(clkdm_autodeps);
+	clkdm_complete_init();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,350 +34,122 @@
 /* Static Dependencies for OMAP4 Clock Domains */
 
 static struct clkdm_dep d2d_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep ducati_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_gfx_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "tesla_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep iss_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ducati_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep mpu_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ducati_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_gfx_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "tesla_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep tesla_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
@@ -388,7 +160,6 @@ static struct clockdomain l4_cefuse_44xx
 	.cm_inst	  = OMAP4430_CM2_CEFUSE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_cfg_44xx_clkdm = {
@@ -399,7 +170,6 @@ static struct clockdomain l4_cfg_44xx_cl
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
 	.dep_bit	  = OMAP4430_L4CFG_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain tesla_44xx_clkdm = {
@@ -412,7 +182,6 @@ static struct clockdomain tesla_44xx_clk
 	.wkdep_srcs	  = tesla_wkup_sleep_deps,
 	.sleepdep_srcs	  = tesla_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_gfx_44xx_clkdm = {
@@ -425,7 +194,6 @@ static struct clockdomain l3_gfx_44xx_cl
 	.wkdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain ivahd_44xx_clkdm = {
@@ -438,7 +206,6 @@ static struct clockdomain ivahd_44xx_clk
 	.wkdep_srcs	  = ivahd_wkup_sleep_deps,
 	.sleepdep_srcs	  = ivahd_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_secure_44xx_clkdm = {
@@ -451,7 +218,6 @@ static struct clockdomain l4_secure_44xx
 	.wkdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.sleepdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_per_44xx_clkdm = {
@@ -462,7 +228,6 @@ static struct clockdomain l4_per_44xx_cl
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
 	.dep_bit	  = OMAP4430_L4PER_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain abe_44xx_clkdm = {
@@ -473,7 +238,6 @@ static struct clockdomain abe_44xx_clkdm
 	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
 	.dep_bit	  = OMAP4430_ABE_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_instr_44xx_clkdm = {
@@ -482,7 +246,6 @@ static struct clockdomain l3_instr_44xx_
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3INSTR_CDOFFS,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_init_44xx_clkdm = {
@@ -495,7 +258,6 @@ static struct clockdomain l3_init_44xx_c
 	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain d2d_44xx_clkdm = {
@@ -507,7 +269,6 @@ static struct clockdomain d2d_44xx_clkdm
 	.wkdep_srcs	  = d2d_wkup_sleep_deps,
 	.sleepdep_srcs	  = d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu0_44xx_clkdm = {
@@ -517,7 +278,6 @@ static struct clockdomain mpu0_44xx_clkd
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu1_44xx_clkdm = {
@@ -527,7 +287,6 @@ static struct clockdomain mpu1_44xx_clkd
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_emif_44xx_clkdm = {
@@ -538,7 +297,6 @@ static struct clockdomain l3_emif_44xx_c
 	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
 	.dep_bit	  = OMAP4430_MEMIF_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_ao_44xx_clkdm = {
@@ -548,7 +306,6 @@ static struct clockdomain l4_ao_44xx_clk
 	.cm_inst	  = OMAP4430_CM2_ALWAYS_ON_INST,
 	.clkdm_offs	  = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain ducati_44xx_clkdm = {
@@ -561,7 +318,6 @@ static struct clockdomain ducati_44xx_cl
 	.wkdep_srcs	  = ducati_wkup_sleep_deps,
 	.sleepdep_srcs	  = ducati_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu_44xx_clkdm = {
@@ -573,7 +329,6 @@ static struct clockdomain mpu_44xx_clkdm
 	.wkdep_srcs	  = mpu_wkup_sleep_deps,
 	.sleepdep_srcs	  = mpu_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_2_44xx_clkdm = {
@@ -584,7 +339,6 @@ static struct clockdomain l3_2_44xx_clkd
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
 	.dep_bit	  = OMAP4430_L3_2_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_1_44xx_clkdm = {
@@ -595,7 +349,6 @@ static struct clockdomain l3_1_44xx_clkd
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
 	.dep_bit	  = OMAP4430_L3_1_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain iss_44xx_clkdm = {
@@ -607,7 +360,6 @@ static struct clockdomain iss_44xx_clkdm
 	.wkdep_srcs	  = iss_wkup_sleep_deps,
 	.sleepdep_srcs	  = iss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
@@ -620,7 +372,6 @@ static struct clockdomain l3_dss_44xx_cl
 	.wkdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_wkup_44xx_clkdm = {
@@ -631,7 +382,6 @@ static struct clockdomain l4_wkup_44xx_c
 	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
 	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain emu_sys_44xx_clkdm = {
@@ -641,7 +391,6 @@ static struct clockdomain emu_sys_44xx_c
 	.cm_inst	  = OMAP4430_PRM_EMU_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_dma_44xx_clkdm = {
@@ -653,7 +402,6 @@ static struct clockdomain l3_dma_44xx_cl
 	.wkdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* As clockdomains are added or removed above, this list must also be changed */
@@ -685,7 +433,10 @@ static struct clockdomain *clockdomains_
 	NULL
 };
 
+
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
+	clkdm_register_platform_funcs(&omap4_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap44xx);
+	clkdm_complete_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,8 @@ void omap3_noncore_dpll_disable(struct c
 int omap4_dpllmx_gatectrl_read(struct clk *clk);
 void omap4_dpllmx_allow_gatectrl(struct clk *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk *clk);
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/common.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,17 +45,22 @@ static void __init __omap2_set_globals(s
 static struct omap_globals omap242x_globals = {
 	.class	= OMAP242X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x48014000),
-	.sdrc	= OMAP2420_SDRC_BASE,
-	.sms	= OMAP2420_SMS_BASE,
-	.ctrl	= OMAP242X_CTRL_BASE,
-	.prm	= OMAP2420_PRM_BASE,
-	.cm	= OMAP2420_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
 };
 
 void __init omap2_set_globals_242x(void)
 {
 	__omap2_set_globals(&omap242x_globals);
 }
+
+void __init omap242x_map_io(void)
+{
+	omap242x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_SOC_OMAP2430)
@@ -63,17 +68,22 @@ void __init omap2_set_globals_242x(void)
 static struct omap_globals omap243x_globals = {
 	.class	= OMAP243X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4900a000),
-	.sdrc	= OMAP243X_SDRC_BASE,
-	.sms	= OMAP243X_SMS_BASE,
-	.ctrl	= OMAP243X_CTRL_BASE,
-	.prm	= OMAP2430_PRM_BASE,
-	.cm	= OMAP2430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
 };
 
 void __init omap2_set_globals_243x(void)
 {
 	__omap2_set_globals(&omap243x_globals);
 }
+
+void __init omap243x_map_io(void)
+{
+	omap243x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_ARCH_OMAP3)
@@ -81,11 +91,11 @@ void __init omap2_set_globals_243x(void)
 static struct omap_globals omap3_globals = {
 	.class	= OMAP343X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4830A000),
-	.sdrc	= OMAP343X_SDRC_BASE,
-	.sms	= OMAP343X_SMS_BASE,
-	.ctrl	= OMAP343X_CTRL_BASE,
-	.prm	= OMAP3430_PRM_BASE,
-	.cm	= OMAP3430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
 };
 
 void __init omap2_set_globals_3xxx(void)
@@ -95,7 +105,6 @@ void __init omap2_set_globals_3xxx(void)
 
 void __init omap3_map_io(void)
 {
-	omap2_set_globals_3xxx();
 	omap34xx_map_common_io();
 }
 
@@ -110,9 +119,9 @@ void __init omap3_map_io(void)
 static struct omap_globals ti816x_globals = {
 	.class  = OMAP343X_CLASS,
 	.tap    = OMAP2_L4_IO_ADDRESS(TI816X_TAP_BASE),
-	.ctrl   = TI816X_CTRL_BASE,
-	.prm    = TI816X_PRCM_BASE,
-	.cm     = TI816X_PRCM_BASE,
+	.ctrl   = OMAP2_L4_IO_ADDRESS(TI816X_CTRL_BASE),
+	.prm    = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
+	.cm     = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
 };
 
 void __init omap2_set_globals_ti816x(void)
@@ -125,11 +134,11 @@ void __init omap2_set_globals_ti816x(voi
 static struct omap_globals omap4_globals = {
 	.class	= OMAP443X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl	= OMAP443X_SCM_BASE,
-	.ctrl_pad	= OMAP443X_CTRL_BASE,
-	.prm	= OMAP4430_PRM_BASE,
-	.cm	= OMAP4430_CM_BASE,
-	.cm2	= OMAP4430_CM2_BASE,
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
+	.cm2	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
 };
 
 void __init omap2_set_globals_443x(void)
@@ -138,5 +147,10 @@ void __init omap2_set_globals_443x(void)
 	omap2_set_globals_control(&omap4_globals);
 	omap2_set_globals_prcm(&omap4_globals);
 }
+
+void __init omap4_map_io(void)
+{
+	omap44xx_map_common_io();
+}
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/control.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/control.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/control.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/control.c	2012-01-04 18:55:44.000000000 -0500
@@ -149,17 +149,11 @@ static struct omap3_control_regs control
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl) {
-		omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
-		WARN_ON(!omap2_ctrl_base);
-	}
+	if (omap2_globals->ctrl)
+		omap2_ctrl_base = omap2_globals->ctrl;
 
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl_pad) {
-		omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
-		WARN_ON(!omap4_ctrl_pad_base);
-	}
+	if (omap2_globals->ctrl_pad)
+		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
 }
 
 void __iomem *omap_ctrl_base_get(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/cpuidle34xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/cpuidle34xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 
 #include <plat/prcm.h>
 #include <plat/irqs.h>
@@ -88,17 +89,21 @@ static int _cpuidle_deny_idle(struct pow
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: the index of state to be entered
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
  */
 static int omap3_enter_idle(struct cpuidle_device *dev,
-			struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+				int index)
 {
-	struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
+	struct omap3_idle_statedata *cx =
+			cpuidle_get_statedata(&dev->states_usage[index]);
 	struct timespec ts_preidle, ts_postidle, ts_idle;
 	u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
+	int idle_time;
 
 	/* Used to keep track of the total time in idle */
 	getnstimeofday(&ts_preidle);
@@ -113,7 +118,7 @@ static int omap3_enter_idle(struct cpuid
 		goto return_sleep_time;
 
 	/* Deny idle for C1 */
-	if (state == &dev->states[0]) {
+	if (index == 0) {
 		pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
 		pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
 	}
@@ -122,7 +127,7 @@ static int omap3_enter_idle(struct cpuid
 	omap_sram_idle();
 
 	/* Re-allow idle for C1 */
-	if (state == &dev->states[0]) {
+	if (index == 0) {
 		pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
 		pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
 	}
@@ -134,28 +139,38 @@ return_sleep_time:
 	local_irq_enable();
 	local_fiq_enable();
 
-	return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
+	idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
+								USEC_PER_SEC;
+
+	/* Update cpuidle counters */
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 /**
  * next_valid_state - Find next valid C-state
  * @dev: cpuidle device
- * @state: Currently selected C-state
+ * @drv: cpuidle driver
+ * @index: Index of currently selected c-state
  *
- * If the current state is valid, it is returned back to the caller.
- * Else, this function searches for a lower c-state which is still
- * valid.
+ * If the state corresponding to index is valid, index is returned back
+ * to the caller. Else, this function searches for a lower c-state which is
+ * still valid (as defined in omap3_power_states[]) and returns its index.
  *
  * A state is valid if the 'valid' field is enabled and
  * if it satisfies the enable_off_mode condition.
  */
-static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
-					      struct cpuidle_state *curr)
+static int next_valid_state(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv,
+				int index)
 {
-	struct cpuidle_state *next = NULL;
-	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
+	struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
+	struct cpuidle_state *curr = &drv->states[index];
+	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
 	u32 mpu_deepest_state = PWRDM_POWER_RET;
 	u32 core_deepest_state = PWRDM_POWER_RET;
+	int next_index = -1;
 
 	if (enable_off_mode) {
 		mpu_deepest_state = PWRDM_POWER_OFF;
@@ -172,20 +187,20 @@ static struct cpuidle_state *next_valid_
 	if ((cx->valid) &&
 	    (cx->mpu_state >= mpu_deepest_state) &&
 	    (cx->core_state >= core_deepest_state)) {
-		return curr;
+		return index;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
 
 		/* Reach the current state starting at highest C-state */
 		for (; idx >= 0; idx--) {
-			if (&dev->states[idx] == curr) {
-				next = &dev->states[idx];
+			if (&drv->states[idx] == curr) {
+				next_index = idx;
 				break;
 			}
 		}
 
 		/* Should never hit this condition */
-		WARN_ON(next == NULL);
+		WARN_ON(next_index == -1);
 
 		/*
 		 * Drop to next valid state.
@@ -193,41 +208,44 @@ static struct cpuidle_state *next_valid_
 		 */
 		idx--;
 		for (; idx >= 0; idx--) {
-			cx = cpuidle_get_statedata(&dev->states[idx]);
+			cx = cpuidle_get_statedata(&dev->states_usage[idx]);
 			if ((cx->valid) &&
 			    (cx->mpu_state >= mpu_deepest_state) &&
 			    (cx->core_state >= core_deepest_state)) {
-				next = &dev->states[idx];
+				next_index = idx;
 				break;
 			}
 		}
 		/*
 		 * C1 is always valid.
-		 * So, no need to check for 'next==NULL' outside this loop.
+		 * So, no need to check for 'next_index == -1' outside
+		 * this loop.
 		 */
 	}
 
-	return next;
+	return next_index;
 }
 
 /**
  * omap3_enter_idle_bm - Checks for any bus activity
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: array index of target state to be programmed
  *
  * This function checks for any pending activity and then programs
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+			       int index)
 {
-	struct cpuidle_state *new_state;
+	int new_state_idx;
 	u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
 	struct omap3_idle_statedata *cx;
 	int ret;
 
 	if (!omap3_can_sleep()) {
-		new_state = dev->safe_state;
+		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
 
@@ -237,7 +255,7 @@ static int omap3_enter_idle_bm(struct cp
 	 */
 	cam_state = pwrdm_read_pwrst(cam_pd);
 	if (cam_state == PWRDM_POWER_ON) {
-		new_state = dev->safe_state;
+		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
 
@@ -253,7 +271,7 @@ static int omap3_enter_idle_bm(struct cp
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(state);
+	cx = cpuidle_get_statedata(&dev->states_usage[index]);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
 	if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -264,11 +282,10 @@ static int omap3_enter_idle_bm(struct cp
 	if (per_next_state != per_saved_state)
 		pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-	new_state = next_valid_state(dev, state);
+	new_state_idx = next_valid_state(dev, drv, index);
 
 select_state:
-	dev->last_state = new_state;
-	ret = omap3_enter_idle(dev, new_state);
+	ret = omap3_enter_idle(dev, drv, new_state_idx);
 
 	/* Restore original PER state if it was modified */
 	if (per_next_state != per_saved_state)
@@ -301,22 +318,31 @@ struct cpuidle_driver omap3_idle_driver
 	.owner = 	THIS_MODULE,
 };
 
-/* Helper to fill the C-state common data and register the driver_data */
-static inline struct omap3_idle_statedata *_fill_cstate(
-					struct cpuidle_device *dev,
+/* Helper to fill the C-state common data*/
+static inline void _fill_cstate(struct cpuidle_driver *drv,
 					int idx, const char *descr)
 {
-	struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
-	struct cpuidle_state *state = &dev->states[idx];
+	struct cpuidle_state *state = &drv->states[idx];
 
 	state->exit_latency	= cpuidle_params_table[idx].exit_latency;
 	state->target_residency	= cpuidle_params_table[idx].target_residency;
 	state->flags		= CPUIDLE_FLAG_TIME_VALID;
 	state->enter		= omap3_enter_idle_bm;
-	cx->valid		= cpuidle_params_table[idx].valid;
 	sprintf(state->name, "C%d", idx + 1);
 	strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
-	cpuidle_set_statedata(state, cx);
+
+}
+
+/* Helper to register the driver_data */
+static inline struct omap3_idle_statedata *_fill_cstate_usage(
+					struct cpuidle_device *dev,
+					int idx)
+{
+	struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
+
+	cx->valid		= cpuidle_params_table[idx].valid;
+	cpuidle_set_statedata(state_usage, cx);
 
 	return cx;
 }
@@ -330,6 +356,7 @@ static inline struct omap3_idle_statedat
 int __init omap3_idle_init(void)
 {
 	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &omap3_idle_driver;
 	struct omap3_idle_statedata *cx;
 
 	mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -337,44 +364,52 @@ int __init omap3_idle_init(void)
 	per_pd = pwrdm_lookup("per_pwrdm");
 	cam_pd = pwrdm_lookup("cam_pwrdm");
 
-	cpuidle_register_driver(&omap3_idle_driver);
+
+	drv->safe_state_index = -1;
 	dev = &per_cpu(omap3_idle_dev, smp_processor_id());
 
 	/* C1 . MPU WFI + Core active */
-	cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
-	(&dev->states[0])->enter = omap3_enter_idle;
-	dev->safe_state = &dev->states[0];
+	_fill_cstate(drv, 0, "MPU ON + CORE ON");
+	(&drv->states[0])->enter = omap3_enter_idle;
+	drv->safe_state_index = 0;
+	cx = _fill_cstate_usage(dev, 0);
 	cx->valid = 1;	/* C1 is always valid */
 	cx->mpu_state = PWRDM_POWER_ON;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C2 . MPU WFI + Core inactive */
-	cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
+	_fill_cstate(drv, 1, "MPU ON + CORE ON");
+	cx = _fill_cstate_usage(dev, 1);
 	cx->mpu_state = PWRDM_POWER_ON;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C3 . MPU CSWR + Core inactive */
-	cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
+	_fill_cstate(drv, 2, "MPU RET + CORE ON");
+	cx = _fill_cstate_usage(dev, 2);
 	cx->mpu_state = PWRDM_POWER_RET;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C4 . MPU OFF + Core inactive */
-	cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
+	_fill_cstate(drv, 3, "MPU OFF + CORE ON");
+	cx = _fill_cstate_usage(dev, 3);
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C5 . MPU RET + Core RET */
-	cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
+	_fill_cstate(drv, 4, "MPU RET + CORE RET");
+	cx = _fill_cstate_usage(dev, 4);
 	cx->mpu_state = PWRDM_POWER_RET;
 	cx->core_state = PWRDM_POWER_RET;
 
 	/* C6 . MPU OFF + Core RET */
-	cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
+	_fill_cstate(drv, 5, "MPU OFF + CORE RET");
+	cx = _fill_cstate_usage(dev, 5);
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_RET;
 
 	/* C7 . MPU OFF + Core OFF */
-	cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
+	_fill_cstate(drv, 6, "MPU OFF + CORE OFF");
+	cx = _fill_cstate_usage(dev, 6);
 	/*
 	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
 	 * enable OFF mode in a stable form for previous revisions.
@@ -388,6 +423,9 @@ int __init omap3_idle_init(void)
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_OFF;
 
+	drv->state_count = OMAP3_NUM_STATES;
+	cpuidle_register_driver(&omap3_idle_driver);
+
 	dev->state_count = OMAP3_NUM_STATES;
 	if (cpuidle_register_device(dev)) {
 		printk(KERN_ERR "%s: CPUidle register device failed\n",
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/devices.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -26,7 +27,6 @@
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mcbsp.h>
-#include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
@@ -44,7 +44,7 @@ static int __init omap3_l3_init(void)
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
 	/*
@@ -61,12 +61,12 @@ static int __init omap3_l3_init(void)
 	if (!oh)
 		pr_err("could not look up %s\n", oh_name);
 
-	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+	pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
 							   NULL, 0, 0);
 
-	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap3_l3_init);
 
@@ -74,9 +74,13 @@ static int __init omap4_l3_init(void)
 {
 	int l, i;
 	struct omap_hwmod *oh[3];
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
+	/* If dtb is there, the devices will be created dynamically */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	/*
 	 * To avoid code running on other OMAPs in
 	 * multi-omap builds
@@ -92,12 +96,12 @@ static int __init omap4_l3_init(void)
 			pr_err("could not look up %s\n", oh_name);
 	}
 
-	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+	pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
 						     0, NULL, 0, 0);
 
-	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap4_l3_init);
 
@@ -221,18 +225,10 @@ static inline void omap_init_camera(void
 #endif
 }
 
-struct omap_device_pm_latency omap_keyboard_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	struct omap4_keypad_platform_data *keypad_data;
 	unsigned int id = -1;
@@ -247,15 +243,13 @@ int __init omap4_keyboard_init(struct om
 
 	keypad_data = sdp4430_keypad_data;
 
-	od = omap_device_build(name, id, oh, keypad_data,
-			sizeof(struct omap4_keypad_platform_data),
-			omap_keyboard_latency,
-			ARRAY_SIZE(omap_keyboard_latency), 0);
+	pdev = omap_device_build(name, id, oh, keypad_data,
+			sizeof(struct omap4_keypad_platform_data), NULL, 0, 0);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 						name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
@@ -263,18 +257,10 @@ int __init omap4_keyboard_init(struct om
 }
 
 #if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-static struct omap_device_pm_latency mbox_latencies[] = {
-	[0] = {
-		.activate_func = omap_device_enable_hwmods,
-		.deactivate_func = omap_device_idle_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline void omap_init_mbox(void)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup("mailbox");
 	if (!oh) {
@@ -282,10 +268,9 @@ static inline void omap_init_mbox(void)
 		return;
 	}
 
-	od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
-				mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
-	WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
-						__func__, PTR_ERR(od));
+	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
+						__func__, PTR_ERR(pdev));
 }
 #else
 static inline void omap_init_mbox(void) { }
@@ -330,21 +315,34 @@ static void omap_init_audio(void)
 static inline void omap_init_audio(void) {}
 #endif
 
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static void omap_init_mcpdm(void)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+
+	oh = omap_hwmod_lookup("mcpdm");
+	if (!oh) {
+		printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+		return;
+	}
+
+	pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
 
-struct omap_device_pm_latency omap_mcspi_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char *name = "omap2_mcspi";
 	struct omap2_mcspi_platform_config *pdata;
 	static int spi_num;
@@ -371,10 +369,9 @@ static int omap_mcspi_init(struct omap_h
 	}
 
 	spi_num++;
-	od = omap_device_build(name, spi_num, oh, pdata,
-				sizeof(*pdata),	omap_mcspi_latency,
-				ARRAY_SIZE(omap_mcspi_latency), 0);
-	WARN(IS_ERR(od), "Can't build omap_device for %s:%s\n",
+	pdev = omap_device_build(name, spi_num, oh, pdata,
+				sizeof(*pdata),	NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
 				name, oh->name);
 	kfree(pdata);
 	return 0;
@@ -683,6 +680,7 @@ static int __init omap2_init_devices(voi
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_audio();
+	omap_init_mcpdm();
 	omap_init_camera();
 	omap_init_mbox();
 	omap_init_mcspi();
@@ -698,18 +696,10 @@ static int __init omap2_init_devices(voi
 arch_initcall(omap2_init_devices);
 
 #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static struct omap_device_pm_latency omap_wdt_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int __init omap_init_wdt(void)
 {
 	int id = -1;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	char *oh_name = "wd_timer2";
 	char *dev_name = "omap_wdt";
@@ -723,10 +713,8 @@ static int __init omap_init_wdt(void)
 		return -EINVAL;
 	}
 
-	od = omap_device_build(dev_name, id, oh, NULL, 0,
-				omap_wdt_latency,
-				ARRAY_SIZE(omap_wdt_latency), 0);
-	WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+	pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 				dev_name, oh->name);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/display.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/display.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/display.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -26,6 +27,35 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
+#include <plat/common.h>
+
+#include "control.h"
+#include "display.h"
+
+#define DISPC_CONTROL		0x0040
+#define DISPC_CONTROL2		0x0238
+#define DISPC_IRQSTATUS		0x0018
+
+#define DSS_SYSCONFIG		0x10
+#define DSS_SYSSTATUS		0x14
+#define DSS_CONTROL		0x40
+#define DSS_SDI_CONTROL		0x44
+#define DSS_PLL_CONTROL		0x48
+
+#define LCD_EN_MASK		(0x1 << 0)
+#define DIGIT_EN_MASK		(0x1 << 1)
+
+#define FRAMEDONE_IRQ_SHIFT	0
+#define EVSYNC_EVEN_IRQ_SHIFT	2
+#define EVSYNC_ODD_IRQ_SHIFT	3
+#define FRAMEDONE2_IRQ_SHIFT	22
+#define FRAMEDONETV_IRQ_SHIFT	24
+
+/*
+ * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
+ *     reset before deciding that something has gone wrong
+ */
+#define FRAMEDONE_IRQ_TIMEOUT		100
 
 static struct platform_device omap_display_device = {
 	.name          = "omapdss",
@@ -35,14 +65,6 @@ static struct platform_device omap_displ
 	},
 };
 
-static struct omap_device_pm_latency omap_dss_latency[] = {
-	[0] = {
-		.deactivate_func        = omap_device_idle_hwmods,
-		.activate_func          = omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -61,7 +83,7 @@ static const struct omap_dss_hwmod_data
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
 	{ "dss_venc", "omapdss_venc", -1 },
-	{ "dss_dsi1", "omapdss_dsi1", -1 },
+	{ "dss_dsi1", "omapdss_dsi", 0 },
 };
 
 static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
@@ -69,16 +91,63 @@ static const struct omap_dss_hwmod_data
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
 	{ "dss_venc", "omapdss_venc", -1 },
-	{ "dss_dsi1", "omapdss_dsi1", -1 },
-	{ "dss_dsi2", "omapdss_dsi2", -1 },
+	{ "dss_dsi1", "omapdss_dsi", 0 },
+	{ "dss_dsi2", "omapdss_dsi", 1 },
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+	u32 enable_mask, enable_shift;
+	u32 pipd_mask, pipd_shift;
+	u32 reg;
+
+	if (dsi_id == 0) {
+		enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+		enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+		pipd_mask = OMAP4_DSI1_PIPD_MASK;
+		pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+	} else if (dsi_id == 1) {
+		enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+		enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+		pipd_mask = OMAP4_DSI2_PIPD_MASK;
+		pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+	} else {
+		return -ENODEV;
+	}
+
+	reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+	reg &= ~enable_mask;
+	reg &= ~pipd_mask;
+
+	reg |= (lanes << enable_shift) & enable_mask;
+	reg |= (lanes << pipd_shift) & pipd_mask;
+
+	omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+	return 0;
+}
+
+static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+{
+	if (cpu_is_omap44xx())
+		return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
+	return 0;
+}
+
+static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+{
+	if (cpu_is_omap44xx())
+		omap4_dsi_mux_pads(dsi_id, 0);
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
 	int r = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	int i, oh_count;
 	struct omap_display_platform_data pdata;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
@@ -96,6 +165,11 @@ int __init omap_display_init(struct omap
 		oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
 	}
 
+	if (board_data->dsi_enable_pads == NULL)
+		board_data->dsi_enable_pads = omap_dsi_enable_pads;
+	if (board_data->dsi_disable_pads == NULL)
+		board_data->dsi_disable_pads = omap_dsi_disable_pads;
+
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count =
 		omap_pm_get_dev_context_loss_count;
@@ -108,13 +182,12 @@ int __init omap_display_init(struct omap
 			return -ENODEV;
 		}
 
-		od = omap_device_build(curr_dss_hwmod[i].dev_name,
+		pdev = omap_device_build(curr_dss_hwmod[i].dev_name,
 				curr_dss_hwmod[i].id, oh, &pdata,
 				sizeof(struct omap_display_platform_data),
-				omap_dss_latency,
-				ARRAY_SIZE(omap_dss_latency), 0);
+				NULL, 0, 0);
 
-		if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+		if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n",
 				curr_dss_hwmod[i].oh_name))
 			return -ENODEV;
 	}
@@ -126,3 +199,135 @@ int __init omap_display_init(struct omap
 
 	return r;
 }
+
+static void dispc_disable_outputs(void)
+{
+	u32 v, irq_mask = 0;
+	bool lcd_en, digit_en, lcd2_en = false;
+	int i;
+	struct omap_dss_dispc_dev_attr *da;
+	struct omap_hwmod *oh;
+
+	oh = omap_hwmod_lookup("dss_dispc");
+	if (!oh) {
+		WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
+		return;
+	}
+
+	if (!oh->dev_attr) {
+		pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
+		return;
+	}
+
+	da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
+
+	/* store value of LCDENABLE and DIGITENABLE bits */
+	v = omap_hwmod_read(oh, DISPC_CONTROL);
+	lcd_en = v & LCD_EN_MASK;
+	digit_en = v & DIGIT_EN_MASK;
+
+	/* store value of LCDENABLE for LCD2 */
+	if (da->manager_count > 2) {
+		v = omap_hwmod_read(oh, DISPC_CONTROL2);
+		lcd2_en = v & LCD_EN_MASK;
+	}
+
+	if (!(lcd_en | digit_en | lcd2_en))
+		return; /* no managers currently enabled */
+
+	/*
+	 * If any manager was enabled, we need to disable it before
+	 * DSS clocks are disabled or DISPC module is reset
+	 */
+	if (lcd_en)
+		irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
+
+	if (digit_en) {
+		if (da->has_framedonetv_irq) {
+			irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
+		} else {
+			irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
+				1 << EVSYNC_ODD_IRQ_SHIFT;
+		}
+	}
+
+	if (lcd2_en)
+		irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
+
+	/*
+	 * clear any previous FRAMEDONE, FRAMEDONETV,
+	 * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts
+	 */
+	omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
+
+	/* disable LCD and TV managers */
+	v = omap_hwmod_read(oh, DISPC_CONTROL);
+	v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
+	omap_hwmod_write(v, oh, DISPC_CONTROL);
+
+	/* disable LCD2 manager */
+	if (da->manager_count > 2) {
+		v = omap_hwmod_read(oh, DISPC_CONTROL2);
+		v &= ~LCD_EN_MASK;
+		omap_hwmod_write(v, oh, DISPC_CONTROL2);
+	}
+
+	i = 0;
+	while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
+	       irq_mask) {
+		i++;
+		if (i > FRAMEDONE_IRQ_TIMEOUT) {
+			pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n");
+			break;
+		}
+		mdelay(1);
+	}
+}
+
+#define MAX_MODULE_SOFTRESET_WAIT	10000
+int omap_dss_reset(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_opt_clk *oc;
+	int c = 0;
+	int i, r;
+
+	if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
+		pr_err("dss_core: hwmod data doesn't contain reset data\n");
+		return -EINVAL;
+	}
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk)
+			clk_enable(oc->_clk);
+
+	dispc_disable_outputs();
+
+	/* clear SDI registers */
+	if (cpu_is_omap3430()) {
+		omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
+		omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
+	}
+
+	/*
+	 * clear DSS_CONTROL register to switch DSS clock sources to
+	 * PRCM clock, if any
+	 */
+	omap_hwmod_write(0x0, oh, DSS_CONTROL);
+
+	omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
+				& SYSS_RESETDONE_MASK),
+			MAX_MODULE_SOFTRESET_WAIT, c);
+
+	if (c == MAX_MODULE_SOFTRESET_WAIT)
+		pr_warning("dss_core: waiting for reset to finish failed\n");
+	else
+		pr_debug("dss_core: softreset done\n");
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk)
+			clk_disable(oc->_clk);
+
+	r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+	return r;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/display.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/display.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/display.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/display.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * display.h - OMAP2+ integration-specific DSS header
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+
+#include <linux/kernel.h>
+
+struct omap_dss_dispc_dev_attr {
+	u8	manager_count;
+	bool	has_framedonetv_irq;
+};
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/dma.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,14 +87,6 @@ static u16 reg_map[] = {
 	[CCDN]			= 0xd8,
 };
 
-static struct omap_device_pm_latency omap2_dma_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static void __iomem *dma_base;
 static inline void dma_write(u32 val, int reg, int lch)
 {
@@ -228,7 +220,7 @@ static u32 configure_dma_errata(void)
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device			*od;
+	struct platform_device			*pdev;
 	struct omap_system_dma_plat_info	*p;
 	struct resource				*mem;
 	char					*name = "omap_dma_system";
@@ -258,23 +250,22 @@ static int __init omap2_system_dma_init_
 
 	p->errata		= configure_dma_errata();
 
-	od = omap_device_build(name, 0, oh, p, sizeof(*p),
-			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+	pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0);
 	kfree(p);
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
-		dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
 		return -EINVAL;
 	}
 	dma_base = ioremap(mem->start, resource_size(mem));
 	if (!dma_base) {
-		dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -283,7 +274,7 @@ static int __init omap2_system_dma_init_
 					(d->lch_count), GFP_KERNEL);
 
 	if (!d->chan) {
-		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
 		return -ENOMEM;
 	}
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/dpll3xxx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/dpll3xxx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/dpll3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/dpll3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk
 	 * propagating?
 	 */
 	if (!r)
-		clk->rate = omap2_get_dpll_rate(clk);
+		clk->rate = (clk->recalc) ? clk->recalc(clk) :
+			omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -424,6 +425,7 @@ void omap3_noncore_dpll_disable(struct c
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk *new_parent = NULL;
+	unsigned long hw_rate;
 	u16 freqsel = 0;
 	struct dpll_data *dd;
 	int ret;
@@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct c
 	if (!dd)
 		return -EINVAL;
 
-	if (rate == omap2_get_dpll_rate(clk))
+	hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
+	if (rate == hw_rate)
 		return 0;
 
 	/*
@@ -455,7 +458,7 @@ int omap3_noncore_dpll_set_rate(struct c
 			new_parent = dd->clk_bypass;
 	} else {
 		if (dd->last_rounded_rate != rate)
-			omap2_dpll_round_rate(clk, rate);
+			rate = clk->round_rate(clk, rate);
 
 		if (dd->last_rounded_rate == 0)
 			return -EINVAL;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/dpll44xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/dpll44xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/dpll44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/dpll44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <plat/clock.h>
 
 #include "clock.h"
+#include "clock44xx.h"
 #include "cm-regbits-44xx.h"
 
 /* Supported only on OMAP4 */
@@ -82,3 +83,71 @@ const struct clkops clkops_omap4_dpllmx_
 	.deny_idle	= omap4_dpllmx_deny_gatectrl,
 };
 
+/**
+ * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to compute the rate for
+ *
+ * Compute the output rate for the OMAP4 DPLL represented by @clk.
+ * Takes the REGM4XEN bit into consideration, which is needed for the
+ * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
+ * upon success, or 0 upon error.
+ */
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+{
+	u32 v;
+	unsigned long rate;
+	struct dpll_data *dd;
+
+	if (!clk || !clk->dpll_data)
+		return 0;
+
+	dd = clk->dpll_data;
+
+	rate = omap2_get_dpll_rate(clk);
+
+	/* regm4xen adds a multiplier of 4 to DPLL calculations */
+	v = __raw_readl(dd->control_reg);
+	if (v & OMAP4430_DPLL_REGM4XEN_MASK)
+		rate *= OMAP4430_REGM4XEN_MULT;
+
+	return rate;
+}
+
+/**
+ * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to round a rate for
+ * @target_rate: the desired rate of the DPLL
+ *
+ * Compute the rate that would be programmed into the DPLL hardware
+ * for @clk if set_rate() were to be provided with the rate
+ * @target_rate.  Takes the REGM4XEN bit into consideration, which is
+ * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before
+ * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
+ * ~0 if an error occurred in omap2_dpll_round_rate().
+ */
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+{
+	u32 v;
+	struct dpll_data *dd;
+	long r;
+
+	if (!clk || !clk->dpll_data)
+		return -EINVAL;
+
+	dd = clk->dpll_data;
+
+	/* regm4xen adds a multiplier of 4 to DPLL calculations */
+	v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
+
+	if (v)
+		target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
+
+	r = omap2_dpll_round_rate(clk, target_rate);
+	if (r == ~0)
+		return r;
+
+	if (v)
+		clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
+
+	return clk->dpll_data->last_rounded_rate;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/dsp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/dsp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/dsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/dsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  * of the OMAP PM core code.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,17 +24,9 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-static struct omap_device_pm_latency omap_gpio_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_gpio_platform_data *pdata;
 	struct omap_gpio_dev_attr *dev_attr;
 	char *name = "omap_gpio";
@@ -107,19 +99,17 @@ static int omap2_gpio_dev_init(struct om
 		return -EINVAL;
 	}
 
-	od = omap_device_build(name, id - 1, oh, pdata,
-				sizeof(*pdata),	omap_gpio_latency,
-				ARRAY_SIZE(omap_gpio_latency),
-				false);
+	pdev = omap_device_build(name, id - 1, oh, pdata,
+				sizeof(*pdata),	NULL, 0, false);
 	kfree(pdata);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 
 	gpio_bank_count++;
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/gpmc-onenand.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/gpmc-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/gpmc-onenand.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/onenand_regs.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/hsmmc.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/hsmmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/hsmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/hsmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,15 +129,11 @@ static void omap4_hsmmc1_before_set_reg(
 	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
 	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
 	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
-	 *
-	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
-	 * is most naturally TWL VSIM; those pins also use PBIAS.
-	 *
-	 * FIXME handle VMMC1A as needed ...
 	 */
 	reg = omap4_ctrl_pad_readl(control_pbias_offset);
 	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-		OMAP4_MMC1_PWRDNZ_MASK);
+		OMAP4_MMC1_PWRDNZ_MASK |
+		OMAP4_MMC1_PBIASLITE_VMODE_MASK);
 	omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
@@ -172,12 +168,6 @@ static void omap4_hsmmc1_after_set_reg(s
 			reg &= ~(OMAP4_MMC1_PWRDNZ_MASK);
 			omap4_ctrl_pad_writel(reg, control_pbias_offset);
 		}
-	} else {
-		reg = omap4_ctrl_pad_readl(control_pbias_offset);
-		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-			OMAP4_MMC1_PWRDNZ_MASK |
-			OMAP4_MMC1_PBIASLITE_VMODE_MASK);
-		omap4_ctrl_pad_writel(reg, control_pbias_offset);
 	}
 }
 
@@ -409,31 +399,17 @@ static int __init omap_hsmmc_pdata_init(
 	return 0;
 }
 
-static struct omap_device_pm_latency omap_hsmmc_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-	/*
-	 * XXX There should also be an entry here to power off/on the
-	 * MMC regulators/PBIAS cells, etc.
-	 */
-};
-
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
-	struct omap_device_pm_latency *ohl;
+	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
 	int l;
-	int ohl_cnt = 0;
 
 	mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
 	if (!mmc_data) {
@@ -448,8 +424,6 @@ void __init omap_init_hsmmc(struct omap2
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-	ohl = omap_hsmmc_latency;
-	ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency);
 
 	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
@@ -467,9 +441,9 @@ void __init omap_init_hsmmc(struct omap2
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
 		kfree(mmc_data->slots[0].name);
 		goto done;
@@ -478,7 +452,7 @@ void __init omap_init_hsmmc(struct omap2
 	 * return device handle to board setup code
 	 * required to populate for regulator framework structure
 	 */
-	hsmmcinfo->dev = &od->pdev.dev;
+	hsmmcinfo->dev = &pdev->dev;
 
 done:
 	kfree(mmc_data);
@@ -505,7 +479,7 @@ void __init omap2_hsmmc_init(struct omap
 			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
 		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
 			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
-		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+		reg |= (OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK |
 			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
 			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
 		omap4_ctrl_pad_writel(reg, control_mmc1);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/hwspinlock.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/hwspinlock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/hwspinlock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/hwspinlock.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,23 +19,20 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/hwspinlock.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-struct omap_device_pm_latency omap_spinlock_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	}
+static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
+	.base_id = 0,
 };
 
 int __init hwspinlocks_init(void)
 {
 	int retval = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	const char *oh_name = "spinlock";
 	const char *dev_name = "omap_hwspinlock";
 
@@ -48,13 +45,13 @@ int __init hwspinlocks_init(void)
 	if (oh == NULL)
 		return -EINVAL;
 
-	od = omap_device_build(dev_name, 0, oh, NULL, 0,
-				omap_spinlock_latency,
-				ARRAY_SIZE(omap_spinlock_latency), false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
+				sizeof(struct hwspinlock_pdata),
+				NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		pr_err("Can't build omap_device for %s:%s\n", dev_name,
 								oh_name);
-		retval = PTR_ERR(od);
+		retval = PTR_ERR(pdev);
 	}
 
 	return retval;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/id.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/id.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/id.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/id.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 
 #include "control.h"
 
-static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
 u32 omap_features;
@@ -39,19 +38,6 @@ unsigned int omap_rev(void)
 }
 EXPORT_SYMBOL(omap_rev);
 
-/**
- * omap_chip_is - test whether currently running OMAP matches a chip type
- * @oc: omap_chip_t to test against
- *
- * Test whether the currently-running OMAP chip matches the supplied
- * chip type 'oc'.  Returns 1 upon a match; 0 upon failure.
- */
-int omap_chip_is(struct omap_chip_id oci)
-{
-	return (oci.oc & omap_chip.oc) ? 1 : 0;
-}
-EXPORT_SYMBOL(omap_chip_is);
-
 int omap_type(void)
 {
 	u32 val = 0;
@@ -201,8 +187,11 @@ static void __init omap3_check_features(
 	OMAP3_CHECK_FEATURE(status, ISP);
 	if (cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_192MHZ_CLK;
-	if (!cpu_is_omap3505() && !cpu_is_omap3517())
+	if (cpu_is_omap3430() || cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_IO_WAKEUP;
+	if (cpu_is_omap3630() || omap_rev() == OMAP3430_REV_ES3_1 ||
+	    omap_rev() == OMAP3430_REV_ES3_1_2)
+		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
 
 	omap_features |= OMAP3_HAS_SDRC;
 
@@ -242,14 +231,12 @@ static void __init ti816x_check_features
 	omap_features = OMAP3_HAS_NEON;
 }
 
-static void __init omap3_check_revision(void)
+static void __init omap3_check_revision(const char **cpu_rev)
 {
 	u32 cpuid, idcode;
 	u16 hawkeye;
 	u8 rev;
 
-	omap_chip.oc = CHIP_IS_OMAP3430;
-
 	/*
 	 * We cannot access revision registers on ES1.0.
 	 * If the processor type is Cortex-A8 and the revision is 0x0
@@ -258,7 +245,7 @@ static void __init omap3_check_revision(
 	cpuid = read_cpuid(CPUID_ID);
 	if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
 		omap_revision = OMAP3430_REV_ES1_0;
-		omap_chip.oc |= CHIP_IS_OMAP3430ES1;
+		*cpu_rev = "1.0";
 		return;
 	}
 
@@ -279,77 +266,85 @@ static void __init omap3_check_revision(
 		case 0: /* Take care of early samples */
 		case 1:
 			omap_revision = OMAP3430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.0";
 			break;
 		case 2:
 			omap_revision = OMAP3430_REV_ES2_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.1";
 			break;
 		case 3:
 			omap_revision = OMAP3430_REV_ES3_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
+			*cpu_rev = "3.0";
 			break;
 		case 4:
 			omap_revision = OMAP3430_REV_ES3_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1";
 			break;
 		case 7:
 		/* FALLTHROUGH */
 		default:
 			/* Use the latest known revision as default */
 			omap_revision = OMAP3430_REV_ES3_1_2;
-
-			/* REVISIT: Add CHIP_IS_OMAP3430ES3_1_2? */
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1.2";
 		}
 		break;
 	case 0xb868:
-		/* Handle OMAP35xx/AM35xx devices
+		/*
+		 * Handle OMAP/AM 3505/3517 devices
 		 *
-		 * Set the device to be OMAP3505 here. Actual device
+		 * Set the device to be OMAP3517 here. Actual device
 		 * is identified later based on the features.
-		 *
-		 * REVISIT: AM3505/AM3517 should have their own CHIP_IS
 		 */
-		omap_revision = OMAP3505_REV(rev);
-		omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+		switch (rev) {
+		case 0:
+			omap_revision = OMAP3517_REV_ES1_0;
+			*cpu_rev = "1.0";
+			break;
+		case 1:
+		/* FALLTHROUGH */
+		default:
+			omap_revision = OMAP3517_REV_ES1_1;
+			*cpu_rev = "1.1";
+		}
 		break;
 	case 0xb891:
 		/* Handle 36xx devices */
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1;
 
 		switch(rev) {
 		case 0: /* Take care of early samples */
 			omap_revision = OMAP3630_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
 			omap_revision = OMAP3630_REV_ES1_1;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_1;
+			*cpu_rev = "1.1";
 			break;
 		case 2:
+		/* FALLTHROUGH */
 		default:
-			omap_revision =  OMAP3630_REV_ES1_2;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+			omap_revision = OMAP3630_REV_ES1_2;
+			*cpu_rev = "1.2";
 		}
 		break;
 	case 0xb81e:
-		omap_chip.oc = CHIP_IS_TI816X;
-
 		switch (rev) {
 		case 0:
 			omap_revision = TI8168_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
+		/* FALLTHROUGH */
+		default:
 			omap_revision = TI8168_REV_ES1_1;
+			*cpu_rev = "1.1";
 			break;
-		default:
-			omap_revision =  TI8168_REV_ES1_1;
 		}
 		break;
 	default:
-		/* Unknown default to latest silicon rev as default*/
-		omap_revision =  OMAP3630_REV_ES1_2;
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+		/* Unknown default to latest silicon rev as default */
+		omap_revision = OMAP3630_REV_ES1_2;
+		*cpu_rev = "1.2";
+		pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n");
 	}
 }
 
@@ -382,24 +377,20 @@ static void __init omap4_check_revision(
 		switch (rev) {
 		case 0:
 			omap_revision = OMAP4430_REV_ES1_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES1;
 			break;
 		case 1:
 		default:
 			omap_revision = OMAP4430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
 		}
 		break;
 	case 0xb95c:
 		switch (rev) {
 		case 3:
 			omap_revision = OMAP4430_REV_ES2_1;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2_1;
 			break;
 		case 4:
 		default:
 			omap_revision = OMAP4430_REV_ES2_2;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 		}
 		break;
 	case 0xb94e:
@@ -407,14 +398,12 @@ static void __init omap4_check_revision(
 		case 0:
 		default:
 			omap_revision = OMAP4460_REV_ES1_0;
-			omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
 			break;
 		}
 		break;
 	default:
 		/* Unknown default to latest silicon rev as default */
 		omap_revision = OMAP4430_REV_ES2_2;
-		omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 	}
 
 	pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
@@ -425,94 +414,33 @@ static void __init omap4_check_revision(
 	if (omap3_has_ ##feat())		\
 		printk(#feat" ");
 
-static void __init omap3_cpuinfo(void)
+static void __init omap3_cpuinfo(const char *cpu_rev)
 {
-	u8 rev = GET_OMAP_REVISION();
-	char cpu_name[16], cpu_rev[16];
+	const char *cpu_name;
 
-	/* OMAP3430 and OMAP3530 are assumed to be same.
+	/*
+	 * OMAP3430 and OMAP3530 are assumed to be same.
 	 *
 	 * OMAP3525, OMAP3515 and OMAP3503 can be detected only based
 	 * on available features. Upon detection, update the CPU id
 	 * and CPU class bits.
 	 */
 	if (cpu_is_omap3630()) {
-		strcpy(cpu_name, "OMAP3630");
-	} else if (cpu_is_omap3505()) {
-		/*
-		 * AM35xx devices
-		 */
-		if (omap3_has_sgx()) {
-			omap_revision = OMAP3517_REV(rev);
-			strcpy(cpu_name, "AM3517");
-		} else {
-			/* Already set in omap3_check_revision() */
-			strcpy(cpu_name, "AM3505");
-		}
+		cpu_name = "OMAP3630";
+	} else if (cpu_is_omap3517()) {
+		/* AM35xx devices */
+		cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
 	} else if (cpu_is_ti816x()) {
-		strcpy(cpu_name, "TI816X");
+		cpu_name = "TI816X";
 	} else if (omap3_has_iva() && omap3_has_sgx()) {
 		/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
-		strcpy(cpu_name, "OMAP3430/3530");
+		cpu_name = "OMAP3430/3530";
 	} else if (omap3_has_iva()) {
-		omap_revision = OMAP3525_REV(rev);
-		strcpy(cpu_name, "OMAP3525");
+		cpu_name = "OMAP3525";
 	} else if (omap3_has_sgx()) {
-		omap_revision = OMAP3515_REV(rev);
-		strcpy(cpu_name, "OMAP3515");
-	} else {
-		omap_revision = OMAP3503_REV(rev);
-		strcpy(cpu_name, "OMAP3503");
-	}
-
-	if (cpu_is_omap3630() || cpu_is_ti816x()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "1.1");
-			break;
-		case OMAP_REVBITS_02:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.2");
-		}
-	} else if (cpu_is_omap3505() || cpu_is_omap3517()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.1");
-		}
+		cpu_name = "OMAP3515";
 	} else {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "2.0");
-			break;
-		case OMAP_REVBITS_02:
-			strcpy(cpu_rev, "2.1");
-			break;
-		case OMAP_REVBITS_03:
-			strcpy(cpu_rev, "3.0");
-			break;
-		case OMAP_REVBITS_04:
-			strcpy(cpu_rev, "3.1");
-			break;
-		case OMAP_REVBITS_05:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "3.1.2");
-		}
+		cpu_name = "OMAP3503";
 	}
 
 	/* Print verbose information */
@@ -533,6 +461,8 @@ static void __init omap3_cpuinfo(void)
  */
 void __init omap2_check_revision(void)
 {
+	const char *cpu_rev;
+
 	/*
 	 * At this point we have an idea about the processor revision set
 	 * earlier with omap2_set_globals_tap().
@@ -540,7 +470,7 @@ void __init omap2_check_revision(void)
 	if (cpu_is_omap24xx()) {
 		omap24xx_check_revision();
 	} else if (cpu_is_omap34xx()) {
-		omap3_check_revision();
+		omap3_check_revision(&cpu_rev);
 
 		/* TI816X doesn't have feature register */
 		if (!cpu_is_ti816x())
@@ -548,7 +478,7 @@ void __init omap2_check_revision(void)
 		else
 			ti816x_check_features();
 
-		omap3_cpuinfo();
+		omap3_cpuinfo(cpu_rev);
 		return;
 	} else if (cpu_is_omap44xx()) {
 		omap4_check_revision();
@@ -557,22 +487,6 @@ void __init omap2_check_revision(void)
 	} else {
 		pr_err("OMAP revision unknown, please fix!\n");
 	}
-
-	/*
-	 * OK, now we know the exact revision. Initialize omap_chip bits
-	 * for powerdowmain and clockdomain code.
-	 */
-	if (cpu_is_omap243x()) {
-		/* Currently only supports 2430ES2.1 and 2430-all */
-		omap_chip.oc |= CHIP_IS_OMAP2430;
-		return;
-	} else if (cpu_is_omap242x()) {
-		/* Currently only supports 2420ES2.1.1 and 2420-all */
-		omap_chip.oc |= CHIP_IS_OMAP2420;
-		return;
-	}
-
-	pr_err("Uninitialized omap_chip, please fix!\n");
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -941,10 +941,10 @@
 #define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
 #define OMAP4_DSI1_LANEENABLE_SHIFT				24
 #define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT					19
-#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT					14
-#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+#define OMAP4_DSI2_PIPD_SHIFT					19
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI1_PIPD_SHIFT					14
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 14)
 
 /* CONTROL_MCBSPLP */
 #define OMAP4_ALBCTRLRX_FSX_SHIFT				31
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,10 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #include <plat/serial.h>
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
 
-#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
 		.pushsection .data
 omap_uart_phys:	.word	0
 omap_uart_virt:	.word	0
@@ -34,26 +29,25 @@ omap_uart_lsr:	.word	0
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 
 		/* Use omap_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rp, =omap_uart_phys	@ MMU enabled
-		add	\rv, \rp, #4		@ omap_uart_virt
-		ldr	\rp, [\rp, #0]
-		ldr	\rv, [\rv, #0]
+10:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ omap_uart_phys
+		ldr	\rv, [\tmp, #4]		@ omap_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
-		ldr	\rp, [\rp, #0]
+		mov	\rp, pc
+		ldr	\rv, =OMAP_UART_INFO_OFS
+		and	\rp, \rp, #0xff000000
+		ldr	\rp, [\rp, \rv]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 		cmp	\rp, #0			@ no port configured?
@@ -106,50 +100,47 @@ omap_uart_lsr:	.word	0
 		b	98f
 83:		mov	\rp, #UART_OFFSET(TI816X_UART3_BASE)
 		b	98f
+
 95:		ldr	\rp, =ZOOM_UART_BASE
-		mrc	p15, 0, \rv, c1, c0
-		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		ldr	\rp, =ZOOM_UART_VIRT
-		add	\rv, \rv, #4		@ omap_uart_virt
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		mov	\rp, #(UART_LSR << ZOOM_PORT_SHIFT)
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #8]		@ omap_uart_lsr
 		b	10b
 
 		/* Store both phys and virt address for the uart */
 98:		add	\rp, \rp, #0x48000000	@ phys base
-		mrc	p15, 0, \rv, c1, c0
-		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		sub	\rp, \rp, #0x48000000	@ phys base
 		add	\rp, \rp, #0xfa000000	@ virt base
-		add	\rv, \rv, #4		@ omap_uart_virt
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		mov	\rp, #(UART_LSR << OMAP_PORT_SHIFT)
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #8]		@ omap_uart_lsr
 
 		b	10b
-99:
+
+		.align
+99:		.word	.
+		.word	omap_uart_phys
+		.ltorg
+
+100:		/* Pass the UART_LSR reg address */
+		ldr	\tmp, [\tmp, #8]	@ omap_uart_lsr
+		add	\rp, \rp, \tmp
+		add	\rv, \rv, \tmp
 		.endm
 
 		.macro	senduart,rd,rx
-		strb	\rd, [\rx]
+		orr	\rd, \rd, \rx, lsl #24	@ preserve LSR reg offset
+		bic	\rx, \rx, #0xff		@ get base (THR) reg address
+		strb	\rd, [\rx]		@ send lower byte of rd
+		orr	\rx, \rx, \rd, lsr #24	@ restore original rx (LSR)
+		bic	\rd, \rd, #(0xff << 24)	@ restore original rd
 		.endm
 
 		.macro	busyuart,rd,rx
-1001:		mrc	p15, 0, \rd, c1, c0
-		tst	\rd, #1			@ MMU enabled?
-		ldreq	\rd, =omap_uart_v2p(omap_uart_lsr)	@ MMU disabled
-		ldrne	\rd, =omap_uart_lsr	@ MMU enabled
-		ldr	\rd, [\rd, #0]
-		ldrb	\rd, [\rx, \rd]
+1001:		ldrb	\rd, [\rx]		@ rx contains UART_LSR address
 		and	\rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
 		teq	\rd, #(UART_LSR_TEMT | UART_LSR_THRE)
 		bne	1001b
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -78,7 +78,7 @@
 4401:		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
 		ldr     \tmp, =1021
 		bic     \irqnr, \irqstat, #0x1c00
-		cmp     \irqnr, #29
+		cmp     \irqnr, #15
 		cmpcc   \irqnr, \irqnr
 		cmpne   \irqnr, \tmp
 		cmpcs   \irqnr, \irqnr
@@ -101,18 +101,6 @@
 		it	cs
 		cmpcs	\irqnr, \irqnr
 		.endm
-
-		/* As above, this assumes that irqstat and base are preserved */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
 #endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/memory.h
- */
-
-#include <plat/memory.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/io.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/io.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -35,14 +34,16 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
-#include "io.h"
 
+#include <plat/common.h>
 #include <plat/omap-pm.h>
+#include "voltage.h"
 #include "powerdomain.h"
 
 #include "clockdomain.h"
 #include <plat/omap_hwmod.h>
 #include <plat/multi.h>
+#include <plat/common.h>
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -239,25 +240,11 @@ static struct map_desc omap44xx_io_desc[
 };
 #endif
 
-static void __init _omap2_map_common_io(void)
-{
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	omap2_check_revision();
-	omap_sram_init();
-}
-
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -266,7 +253,6 @@ void __init omap243x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -274,7 +260,6 @@ void __init omap243x_map_common_io(void)
 void __init omap34xx_map_common_io(void)
 {
 	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -282,7 +267,6 @@ void __init omap34xx_map_common_io(void)
 void __init omapti816x_map_common_io(void)
 {
 	iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -290,7 +274,6 @@ void __init omapti816x_map_common_io(voi
 void __init omap44xx_map_common_io(void)
 {
 	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -336,29 +319,16 @@ static int _set_hwmod_postsetup_state(st
 /* See irq.c, omap4-common.c and entry-macro.S */
 void __iomem *omap_irq_base;
 
-void __init omap2_init_common_infrastructure(void)
+static void __init omap_common_init_early(void)
 {
-	u8 postsetup_state;
+	omap2_check_revision();
+	omap_ioremap_init();
+	omap_init_consistent_dma_size();
+}
 
-	if (cpu_is_omap242x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2420_hwmod_init();
-	} else if (cpu_is_omap243x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2430_hwmod_init();
-	} else if (cpu_is_omap34xx()) {
-		omap3xxx_powerdomains_init();
-		omap3xxx_clockdomains_init();
-		omap3xxx_hwmod_init();
-	} else if (cpu_is_omap44xx()) {
-		omap44xx_powerdomains_init();
-		omap44xx_clockdomains_init();
-		omap44xx_hwmod_init();
-	} else {
-		pr_err("Could not init hwmod data - unknown SoC\n");
-        }
+static void __init omap_hwmod_init_postsetup(void)
+{
+	u8 postsetup_state;
 
 	/* Set the default postsetup state for all hwmods */
 #ifdef CONFIG_PM_RUNTIME
@@ -376,7 +346,7 @@ void __init omap2_init_common_infrastruc
 	 * omap_hwmod_late_init(), so boards that desire full watchdog
 	 * coverage of kernel initialization can reprogram the
 	 * postsetup_state between the calls to
-	 * omap2_init_common_infra() and omap2_init_common_devices().
+	 * omap2_init_common_infra() and omap_sdrc_init().
 	 *
 	 * XXX ideally we could detect whether the MPU WDT was currently
 	 * enabled here and make this conditional
@@ -387,27 +357,107 @@ void __init omap2_init_common_infrastruc
 				     &postsetup_state);
 
 	omap_pm_if_early_init();
+}
 
-	if (cpu_is_omap2420())
-		omap2420_clk_init();
-	else if (cpu_is_omap2430())
-		omap2430_clk_init();
-	else if (cpu_is_omap34xx())
-		omap3xxx_clk_init();
-	else if (cpu_is_omap44xx())
-		omap4xxx_clk_init();
-	else
-		pr_err("Could not init clock framework - unknown SoC\n");
+#ifdef CONFIG_ARCH_OMAP2
+void __init omap2420_init_early(void)
+{
+	omap2_set_globals_242x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap242x_powerdomains_init();
+	omap242x_clockdomains_init();
+	omap2420_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2420_clk_init();
 }
 
-void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+void __init omap2430_init_early(void)
+{
+	omap2_set_globals_243x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap243x_powerdomains_init();
+	omap243x_clockdomains_init();
+	omap2430_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2430_clk_init();
+}
+#endif
+
+/*
+ * Currently only board-omap3beagle.c should call this because of the
+ * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
+ */
+#ifdef CONFIG_ARCH_OMAP3
+void __init omap3_init_early(void)
+{
+	omap2_set_globals_3xxx();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+
+void __init omap3430_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap3630_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init am35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init ti816x_init_early(void)
+{
+	omap2_set_globals_ti816x();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+void __init omap4430_init_early(void)
+{
+	omap2_set_globals_443x();
+	omap_common_init_early();
+	omap44xx_voltagedomains_init();
+	omap44xx_powerdomains_init();
+	omap44xx_clockdomains_init();
+	omap44xx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap4xxx_clk_init();
+}
+#endif
+
+void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1)
 {
+	omap_sram_init();
+
 	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
-
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/io.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-
-#ifndef __MACH_OMAP2_IO_H__
-#define __MACH_OMAP2_IO_H__
-
-extern int __init omap_sram_init(void);
-
-#endif /*  __MACH_OMAP2_IO_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/iommu2.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/iommu2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/iommu2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/iommu2.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,7 @@
 	 ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xfffff000 : 0)
 
 
-static void __iommu_set_twl(struct iommu *obj, bool on)
+static void __iommu_set_twl(struct omap_iommu *obj, bool on)
 {
 	u32 l = iommu_read_reg(obj, MMU_CNTL);
 
@@ -85,7 +85,7 @@ static void __iommu_set_twl(struct iommu
 }
 
 
-static int omap2_iommu_enable(struct iommu *obj)
+static int omap2_iommu_enable(struct omap_iommu *obj)
 {
 	u32 l, pa;
 	unsigned long timeout;
@@ -127,7 +127,7 @@ static int omap2_iommu_enable(struct iom
 	return 0;
 }
 
-static void omap2_iommu_disable(struct iommu *obj)
+static void omap2_iommu_disable(struct omap_iommu *obj)
 {
 	u32 l = iommu_read_reg(obj, MMU_CNTL);
 
@@ -138,12 +138,12 @@ static void omap2_iommu_disable(struct i
 	dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
 }
 
-static void omap2_iommu_set_twl(struct iommu *obj, bool on)
+static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
 {
 	__iommu_set_twl(obj, false);
 }
 
-static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
+static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
 {
 	u32 stat, da;
 	u32 errs = 0;
@@ -173,13 +173,13 @@ static u32 omap2_iommu_fault_isr(struct
 	return errs;
 }
 
-static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
 {
 	cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
 	cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
 }
 
-static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
 {
 	iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
 	iommu_write_reg(obj, cr->ram, MMU_RAM);
@@ -193,7 +193,8 @@ static u32 omap2_cr_to_virt(struct cr_re
 	return cr->cam & mask;
 }
 
-static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
+static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
+						struct iotlb_entry *e)
 {
 	struct cr_regs *cr;
 
@@ -230,7 +231,8 @@ static u32 omap2_get_pte_attr(struct iot
 	return attr;
 }
 
-static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
+static ssize_t
+omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
 {
 	char *p = buf;
 
@@ -254,7 +256,8 @@ static ssize_t omap2_dump_cr(struct iomm
 			goto out;					\
 	} while (0)
 
-static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len)
+static ssize_t
+omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
 {
 	char *p = buf;
 
@@ -280,7 +283,7 @@ out:
 	return p - buf;
 }
 
-static void omap2_iommu_save_ctx(struct iommu *obj)
+static void omap2_iommu_save_ctx(struct omap_iommu *obj)
 {
 	int i;
 	u32 *p = obj->ctx;
@@ -293,7 +296,7 @@ static void omap2_iommu_save_ctx(struct
 	BUG_ON(p[0] != IOMMU_ARCH_VERSION);
 }
 
-static void omap2_iommu_restore_ctx(struct iommu *obj)
+static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
 {
 	int i;
 	u32 *p = obj->ctx;
@@ -343,13 +346,13 @@ static const struct iommu_functions omap
 
 static int __init omap2_iommu_init(void)
 {
-	return install_iommu_arch(&omap2_iommu_ops);
+	return omap_install_iommu_arch(&omap2_iommu_ops);
 }
 module_init(omap2_iommu_init);
 
 static void __exit omap2_iommu_exit(void)
 {
-	uninstall_iommu_arch(&omap2_iommu_ops);
+	omap_uninstall_iommu_arch(&omap2_iommu_ops);
 }
 module_exit(omap2_iommu_exit);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/irq.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -165,8 +165,8 @@ static void __init omap_init_irq(u32 bas
 
 		omap_irq_bank_init_one(bank);
 
-		for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20)
-			omap_alloc_gc(bank->base_reg + j, i, 32);
+		for (j = 0; j < bank->nr_irqs; j += 32)
+			omap_alloc_gc(bank->base_reg + j, j, 32);
 
 		nr_of_irqs += bank->nr_irqs;
 		nr_banks++;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-omap2/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@ config ARCH_OMAP2PLUS_TYPICAL
 	select SERIAL_OMAP_CONSOLE
 	select I2C
 	select I2C_OMAP
-	select MFD_SUPPORT
 	select MENELAUS if ARCH_OMAP2
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
@@ -36,6 +35,7 @@ config ARCH_OMAP3
 	select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
+	select ARM_CPU_SUSPEND if PM
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -50,6 +50,7 @@ config ARCH_OMAP4
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
 	select USB_ARCH_HAS_EHCI
+	select ARM_CPU_SUSPEND if PM
 
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
@@ -106,9 +107,13 @@ comment "OMAP Board Type"
 	depends on ARCH_OMAP2PLUS
 
 config MACH_OMAP_GENERIC
-	bool "Generic OMAP board"
-	depends on ARCH_OMAP2
+	bool "Generic OMAP2+ board"
+	depends on ARCH_OMAP2PLUS
+	select USE_OF
 	default y
+	help
+	  Support for generic TI OMAP2+ boards using Flattened Device Tree.
+	  More information at Documentation/devicetree
 
 config MACH_OMAP2_TUSB6010
 	bool
@@ -329,6 +334,7 @@ config MACH_OMAP4_PANDA
 config OMAP3_EMU
 	bool "OMAP3 debugging peripherals"
 	depends on ARCH_OMAP3
+	select ARM_AMBA
 	select OC_ETM
 	help
 	  Say Y here to enable debugging hardware of omap3
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/mailbox.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/mailbox.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/Makefile linux-libre-3.2-gnu1/arch/arm/mach-omap2/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
-	 common.o gpio.o dma.o wd_timer.o
+	 common.o gpio.o dma.o wd_timer.o display.o
 
 omap-2-3-common				= irq.o sdrc.o
 hwmod-common				= omap_hwmod.o \
@@ -89,14 +89,13 @@ obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2x
 					   vp44xx_data.o
 
 # OMAP voltage domains
-ifeq ($(CONFIG_PM),y)
-voltagedomain-common			:= voltage.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+voltagedomain-common			:= voltage.o vc.o vp.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common) \
+					   voltagedomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common) \
 					   voltagedomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common) \
 					   voltagedomains44xx_data.o
-endif
 
 # OMAP powerdomain framework
 powerdomain-common			+= powerdomain.o powerdomain-common.o
@@ -116,9 +115,12 @@ obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdoma
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
-					   clockdomains2xxx_3xxx_data.o
+					   clockdomains2xxx_3xxx_data.o \
+					   clockdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
 					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
@@ -185,81 +187,67 @@ endif
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
-obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
-obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o \
-                                           hsmmc.o
-obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OVERO)		+= board-overo.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o \
-					   hsmmc.o \
-					   board-flash.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
+obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o
+obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
+obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o
+obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
+obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
+obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o
+obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-n8x0.o
 obj-$(CONFIG_MACH_NOKIA_RM680)		+= board-rm680.o \
-					   sdram-nokia.o \
-					   hsmmc.o
+					   sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
 					   sdram-nokia.o \
 					   board-rx51-peripherals.o \
-					   board-rx51-video.o \
-					   hsmmc.o
+					   board-rx51-video.o
 obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-3630sdp.o \
 					   board-zoom-peripherals.o \
-					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o \
-					   hsmmc.o
+					   board-zoom-display.o
+obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)		+= board-cm-t3517.o
-obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
-					   hsmmc.o \
-					   omap_phy_internal.o
-obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
-					   hsmmc.o \
-					   omap_phy_internal.o
+obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o
+obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o
+obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o
+obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o
 
-obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o \
-					   omap_phy_internal.o \
+obj-$(CONFIG_MACH_PCM049)		+= board-omap4pcm049.o
+
+obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
 
 obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
 
-obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o
 obj-$(CONFIG_MACH_TI8168EVM)		+= board-ti8168evm.o
+
 # Platform specific device init code
+
+omap-flash-$(CONFIG_MTD_NAND_OMAP2)	:= board-flash.o
+omap-flash-$(CONFIG_MTD_ONENAND_OMAP2)	:= board-flash.o
+obj-y					+= $(omap-flash-y) $(omap-flash-m)
+
+omap-hsmmc-$(CONFIG_MMC_OMAP_HS)	:= hsmmc.o
+obj-y					+= $(omap-hsmmc-m) $(omap-hsmmc-y)
+
+
 usbfs-$(CONFIG_ARCH_OMAP_OTG)		:= usb-fs.o
 obj-y					+= $(usbfs-m) $(usbfs-y)
 obj-y					+= usb-musb.o
+obj-y					+= omap_phy_internal.o
+
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)	+= usb-tusb6010.o
 obj-y					+= usb-host.o
 
@@ -276,7 +264,4 @@ smsc911x-$(CONFIG_SMSC911X)		:= gpmc-sms
 obj-y					+= $(smsc911x-m) $(smsc911x-y)
 obj-$(CONFIG_ARCH_OMAP4)		+= hwspinlock.o
 
-disp-$(CONFIG_OMAP2_DSS)		:= display.o
-obj-y					+= $(disp-m) $(disp-y)
-
 obj-y					+= common-board-devices.o twl-common.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-omap2/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-  zreladdr-y		:= 0x80008000
+  zreladdr-y		+= 0x80008000
 params_phys-y		:= 0x80000100
 initrd_phys-y		:= 0x80800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/mcbsp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/mcbsp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,66 +27,69 @@
 
 #include "control.h"
 
-/* McBSP internal signal muxing functions */
+/*
+ * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
+ * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
+ */
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
 
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+/* McBSP internal signal muxing function */
+static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
+				   const char *src)
 {
 	u32 v;
 
 	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == CLKR_SRC_CLKR)
-		v &= ~OMAP2_MCBSP1_CLKR_MASK;
-	else if (mux == CLKR_SRC_CLKX)
-		v |= OMAP2_MCBSP1_CLKR_MASK;
-	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
-	u32 v;
+	if (!strcmp(signal, "clkr")) {
+		if (!strcmp(src, "clkr"))
+			v &= ~OMAP2_MCBSP1_CLKR_MASK;
+		else if (!strcmp(src, "clkx"))
+			v |= OMAP2_MCBSP1_CLKR_MASK;
+		else
+			return -EINVAL;
+	} else if (!strcmp(signal, "fsr")) {
+		if (!strcmp(src, "fsr"))
+			v &= ~OMAP2_MCBSP1_FSR_MASK;
+		else if (!strcmp(src, "fsx"))
+			v |= OMAP2_MCBSP1_FSR_MASK;
+		else
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
 
-	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == FSR_SRC_FSR)
-		v &= ~OMAP2_MCBSP1_FSR_MASK;
-	else if (mux == FSR_SRC_FSX)
-		v |= OMAP2_MCBSP1_FSR_MASK;
 	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+
+	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
 /* McBSP CLKS source switching function */
-
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
+				   const char *src)
 {
-	struct omap_mcbsp *mcbsp;
 	struct clk *fck_src;
 	char *fck_src_name;
 	int r;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
-		return -EINVAL;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+	if (!strcmp(src, "clks_ext"))
 		fck_src_name = "pad_fck";
-	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+	else if (!strcmp(src, "clks_fclk"))
 		fck_src_name = "prcm_fck";
 	else
 		return -EINVAL;
 
-	fck_src = clk_get(mcbsp->dev, fck_src_name);
+	fck_src = clk_get(dev, fck_src_name);
 	if (IS_ERR_OR_NULL(fck_src)) {
 		pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
 		       fck_src_name);
 		return -EINVAL;
 	}
 
-	pm_runtime_put_sync(mcbsp->dev);
+	pm_runtime_put_sync(dev);
 
-	r = clk_set_parent(mcbsp->fclk, fck_src);
+	r = clk_set_parent(clk, fck_src);
 	if (IS_ERR_VALUE(r)) {
 		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
 		       "clks", fck_src_name);
@@ -94,21 +97,30 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 f
 		return -EINVAL;
 	}
 
-	pm_runtime_get_sync(mcbsp->dev);
+	pm_runtime_get_sync(dev);
 
 	clk_put(fck_src);
 
 	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-struct omap_device_pm_latency omap2_mcbsp_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
+static int omap3_enable_st_clock(unsigned int id, bool enable)
+{
+	unsigned int w;
+
+	/*
+	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
+	 * are enabled or sidetones start sounding ugly.
+	 */
+	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (enable)
+		w &= ~(1 << (id - 2));
+	else
+		w |= 1 << (id - 2);
+	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+
+	return 0;
+}
 
 static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
@@ -116,7 +128,7 @@ static int omap_init_mcbsp(struct omap_h
 	char *name = "omap-mcbsp";
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -126,7 +138,16 @@ static int omap_init_mcbsp(struct omap_h
 		return -ENOMEM;
 	}
 
-	pdata->mcbsp_config_type = oh->class->rev;
+	pdata->reg_step = 4;
+	if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
+		pdata->reg_size = 2;
+	} else {
+		pdata->reg_size = 4;
+		pdata->has_ccr = true;
+	}
+	pdata->set_clk_src = omap2_mcbsp_set_clk_src;
+	if (id == 1)
+		pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
 
 	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
 		if (id == 2)
@@ -137,21 +158,24 @@ static int omap_init_mcbsp(struct omap_h
 			pdata->buffer_size = 0x80;
 	}
 
+	if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
+		pdata->has_wakeup = true;
+
 	oh_device[0] = oh;
 
 	if (oh->dev_attr) {
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+		pdata->enable_st_clock = omap3_enable_st_clock;
 		count++;
 	}
-	od = omap_device_build_ss(name, id, oh_device, count, pdata,
-				sizeof(*pdata), omap2_mcbsp_latency,
-				ARRAY_SIZE(omap2_mcbsp_latency), false);
+	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
+				sizeof(*pdata), NULL, 0, false);
 	kfree(pdata);
-	if (IS_ERR(od))  {
+	if (IS_ERR(pdev))  {
 		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 	omap_mcbsp_count++;
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,6 @@ static struct omap_hwmod omap2420_l3_mai
 	.masters_cnt	= ARRAY_SIZE(omap2420_l3_main_masters),
 	.slaves		= omap2420_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -206,7 +205,6 @@ static struct omap_hwmod omap2420_l4_cor
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_core_masters),
 	.slaves		= omap2420_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -227,7 +225,6 @@ static struct omap_hwmod omap2420_l4_wku
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_wkup_masters),
 	.slaves		= omap2420_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -243,7 +240,6 @@ static struct omap_hwmod omap2420_mpu_hw
 	.main_clk	= "mpu_ck",
 	.masters	= omap2420_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -271,7 +267,16 @@ static struct omap_hwmod omap2420_iva_hw
 	.class		= &iva_hwmod_class,
 	.masters	= omap2420_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -314,10 +319,10 @@ static struct omap_hwmod omap2420_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer2 */
@@ -351,10 +356,10 @@ static struct omap_hwmod omap2420_timer2
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer3 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2420_timer3
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer4 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2420_timer4
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer5 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2420_timer5
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 
@@ -500,10 +505,10 @@ static struct omap_hwmod omap2420_timer6
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer7 */
@@ -537,10 +542,10 @@ static struct omap_hwmod omap2420_timer7
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer8 */
@@ -574,10 +579,10 @@ static struct omap_hwmod omap2420_timer8
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer9 */
@@ -611,10 +616,10 @@ static struct omap_hwmod omap2420_timer9
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer10 */
@@ -648,10 +653,10 @@ static struct omap_hwmod omap2420_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer11 */
@@ -685,10 +690,10 @@ static struct omap_hwmod omap2420_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer12 */
@@ -722,10 +727,10 @@ static struct omap_hwmod omap2420_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -766,7 +771,6 @@ static struct omap_hwmod omap2420_wd_tim
 	},
 	.slaves		= omap2420_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART1 */
@@ -792,7 +796,6 @@ static struct omap_hwmod omap2420_uart1_
 	.slaves		= omap2420_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART2 */
@@ -818,7 +821,6 @@ static struct omap_hwmod omap2420_uart2_
 	.slaves		= omap2420_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART3 */
@@ -844,7 +846,6 @@ static struct omap_hwmod omap2420_uart3_
 	.slaves		= omap2420_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dss */
@@ -874,6 +875,10 @@ static struct omap_hwmod_ocp_if *omap242
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -898,8 +903,7 @@ static struct omap_hwmod omap2420_dss_co
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_slaves),
 	.masters	= omap2420_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-	.flags		= HWMOD_NO_IDLEST,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -938,8 +942,8 @@ static struct omap_hwmod omap2420_dss_di
 	},
 	.slaves		= omap2420_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -962,6 +966,10 @@ static struct omap_hwmod_ocp_if *omap242
 	&omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -973,9 +981,10 @@ static struct omap_hwmod omap2420_dss_rf
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap2420_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -983,7 +992,7 @@ static struct omap_hwmod omap2420_dss_rf
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dss_venc_hwmod,
-	.clk		= "dss_54m_fck",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
@@ -1003,7 +1012,7 @@ static struct omap_hwmod_ocp_if *omap242
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_fck",
+	.main_clk	= "dss_54m_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1013,7 +1022,6 @@ static struct omap_hwmod omap2420_dss_ve
 	},
 	.slaves		= omap2420_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1064,7 +1072,6 @@ static struct omap_hwmod omap2420_i2c1_h
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1092,7 +1099,6 @@ static struct omap_hwmod omap2420_i2c2_h
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1197,7 +1203,6 @@ static struct omap_hwmod omap2420_gpio1_
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio2 */
@@ -1223,7 +1228,6 @@ static struct omap_hwmod omap2420_gpio2_
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio3 */
@@ -1249,7 +1253,6 @@ static struct omap_hwmod omap2420_gpio3_
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio4 */
@@ -1275,7 +1278,6 @@ static struct omap_hwmod omap2420_gpio4_
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dma attributes */
@@ -1322,7 +1324,6 @@ static struct omap_hwmod omap2420_dma_sy
 	.masters	= omap2420_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1363,7 +1364,6 @@ static struct omap_hwmod omap2420_mailbo
 	},
 	.slaves		= omap2420_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi1 */
@@ -1393,7 +1393,6 @@ static struct omap_hwmod omap2420_mcspi1
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi2 */
@@ -1423,7 +1422,6 @@ static struct omap_hwmod omap2420_mcspi2
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -1473,7 +1471,6 @@ static struct omap_hwmod omap2420_mcbsp1
 	},
 	.slaves		= omap2420_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcbsp2 */
@@ -1514,7 +1511,6 @@ static struct omap_hwmod omap2420_mcbsp2
 	},
 	.slaves		= omap2420_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,6 @@ static struct omap_hwmod omap2430_l3_mai
 	.masters_cnt	= ARRAY_SIZE(omap2430_l3_main_masters),
 	.slaves		= omap2430_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -250,7 +249,6 @@ static struct omap_hwmod omap2430_l4_cor
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_core_masters),
 	.slaves		= omap2430_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -301,7 +299,6 @@ static struct omap_hwmod omap2430_l4_wku
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_wkup_masters),
 	.slaves		= omap2430_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -317,7 +314,6 @@ static struct omap_hwmod omap2430_mpu_hw
 	.main_clk	= "mpu_ck",
 	.masters	= omap2430_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -345,7 +341,16 @@ static struct omap_hwmod omap2430_iva_hw
 	.class		= &iva_hwmod_class,
 	.masters	= omap2430_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2430_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer2 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2430_timer2
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer3 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2430_timer3
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer4 */
@@ -499,10 +504,10 @@ static struct omap_hwmod omap2430_timer4
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer5 */
@@ -536,10 +541,10 @@ static struct omap_hwmod omap2430_timer5
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer6 */
@@ -573,10 +578,10 @@ static struct omap_hwmod omap2430_timer6
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer7 */
@@ -610,10 +615,10 @@ static struct omap_hwmod omap2430_timer7
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer8 */
@@ -647,10 +652,10 @@ static struct omap_hwmod omap2430_timer8
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer9 */
@@ -684,10 +689,10 @@ static struct omap_hwmod omap2430_timer9
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer10 */
@@ -721,10 +726,10 @@ static struct omap_hwmod omap2430_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer11 */
@@ -758,10 +763,10 @@ static struct omap_hwmod omap2430_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer12 */
@@ -795,10 +800,10 @@ static struct omap_hwmod omap2430_timer1
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -839,7 +844,6 @@ static struct omap_hwmod omap2430_wd_tim
 	},
 	.slaves		= omap2430_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART1 */
@@ -865,7 +869,6 @@ static struct omap_hwmod omap2430_uart1_
 	.slaves		= omap2430_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART2 */
@@ -891,7 +894,6 @@ static struct omap_hwmod omap2430_uart2_
 	.slaves		= omap2430_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART3 */
@@ -917,7 +919,6 @@ static struct omap_hwmod omap2430_uart3_
 	.slaves		= omap2430_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dss */
@@ -941,6 +942,10 @@ static struct omap_hwmod_ocp_if *omap243
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -965,8 +970,7 @@ static struct omap_hwmod omap2430_dss_co
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_slaves),
 	.masters	= omap2430_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-	.flags		= HWMOD_NO_IDLEST,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -999,8 +1003,8 @@ static struct omap_hwmod omap2430_dss_di
 	},
 	.slaves		= omap2430_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -1017,6 +1021,10 @@ static struct omap_hwmod_ocp_if *omap243
 	&omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -1028,9 +1036,10 @@ static struct omap_hwmod omap2430_dss_rf
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap2430_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1038,7 +1047,7 @@ static struct omap_hwmod omap2430_dss_rf
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dss_venc_hwmod,
-	.clk		= "dss_54m_fck",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
@@ -1052,7 +1061,7 @@ static struct omap_hwmod_ocp_if *omap243
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_fck",
+	.main_clk	= "dss_54m_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1062,7 +1071,6 @@ static struct omap_hwmod omap2430_dss_ve
 	},
 	.slaves		= omap2430_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1123,7 +1131,6 @@ static struct omap_hwmod omap2430_i2c1_h
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* I2C2 */
@@ -1151,7 +1158,6 @@ static struct omap_hwmod omap2430_i2c2_h
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1273,7 +1279,6 @@ static struct omap_hwmod omap2430_gpio1_
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio2 */
@@ -1299,7 +1304,6 @@ static struct omap_hwmod omap2430_gpio2_
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio3 */
@@ -1325,7 +1329,6 @@ static struct omap_hwmod omap2430_gpio3_
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio4 */
@@ -1351,7 +1354,6 @@ static struct omap_hwmod omap2430_gpio4_
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio5 */
@@ -1382,7 +1384,6 @@ static struct omap_hwmod omap2430_gpio5_
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dma attributes */
@@ -1429,7 +1430,6 @@ static struct omap_hwmod omap2430_dma_sy
 	.masters	= omap2430_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1469,7 +1469,6 @@ static struct omap_hwmod omap2430_mailbo
 	},
 	.slaves		= omap2430_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi1 */
@@ -1499,7 +1498,6 @@ static struct omap_hwmod omap2430_mcspi1
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi2 */
@@ -1529,7 +1527,6 @@ static struct omap_hwmod omap2430_mcspi2
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi3 */
@@ -1572,7 +1569,6 @@ static struct omap_hwmod omap2430_mcspi3
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -1628,7 +1624,6 @@ static struct omap_hwmod omap2430_usbhso
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /*
@@ -1689,7 +1684,6 @@ static struct omap_hwmod omap2430_mcbsp1
 	},
 	.slaves		= omap2430_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp2 */
@@ -1731,7 +1725,6 @@ static struct omap_hwmod omap2430_mcbsp2
 	},
 	.slaves		= omap2430_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp3 */
@@ -1783,7 +1776,6 @@ static struct omap_hwmod omap2430_mcbsp3
 	},
 	.slaves		= omap2430_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp4 */
@@ -1841,7 +1833,6 @@ static struct omap_hwmod omap2430_mcbsp4
 	},
 	.slaves		= omap2430_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp5 */
@@ -1899,7 +1890,6 @@ static struct omap_hwmod omap2430_mcbsp5
 	},
 	.slaves		= omap2430_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* MMC/SD/SDIO common */
@@ -1966,7 +1956,6 @@ static struct omap_hwmod omap2430_mmc1_h
 	.slaves		= omap2430_mmc1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc1_slaves),
 	.class		= &omap2430_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* MMC/SD/SDIO2 */
@@ -2010,7 +1999,6 @@ static struct omap_hwmod omap2430_mmc2_h
 	.slaves		= omap2430_mmc2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc2_slaves),
 	.class		= &omap2430_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
 #include <plat/dma.h>
+#include <plat/common.h>
 
 #include <mach/irqs.h>
 
@@ -43,13 +44,15 @@ static struct omap_hwmod_class_sysconfig
 	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
 struct omap_hwmod_class omap2_dss_hwmod_class = {
 	.name	= "dss",
 	.sysc	= &omap2_dss_sysc,
+	.reset	= omap_dss_reset,
 };
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -156,7 +156,6 @@ static struct omap_hwmod omap3xxx_l3_mai
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -459,7 +458,6 @@ static struct omap_hwmod omap3xxx_l4_cor
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -474,7 +472,6 @@ static struct omap_hwmod omap3xxx_l4_per
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -489,7 +486,6 @@ static struct omap_hwmod omap3xxx_l4_wku
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -505,7 +501,6 @@ static struct omap_hwmod omap3xxx_mpu_hw
 	.main_clk	= "arm_fck",
 	.masters	= omap3xxx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /*
@@ -533,7 +528,6 @@ static struct omap_hwmod omap3xxx_iva_hw
 	.class		= &iva_hwmod_class,
 	.masters	= omap3xxx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer class */
@@ -570,6 +564,21 @@ static struct omap_hwmod_class omap3xxx_
 	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 
@@ -610,10 +619,10 @@ static struct omap_hwmod omap3xxx_timer1
 			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer2 */
@@ -656,10 +665,10 @@ static struct omap_hwmod omap3xxx_timer2
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer3 */
@@ -702,10 +711,10 @@ static struct omap_hwmod omap3xxx_timer3
 			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer4 */
@@ -748,10 +757,10 @@ static struct omap_hwmod omap3xxx_timer4
 			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer5 */
@@ -794,10 +803,10 @@ static struct omap_hwmod omap3xxx_timer5
 			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer6 */
@@ -840,10 +849,10 @@ static struct omap_hwmod omap3xxx_timer6
 			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer7 */
@@ -886,10 +895,10 @@ static struct omap_hwmod omap3xxx_timer7
 			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer8 */
@@ -932,10 +941,10 @@ static struct omap_hwmod omap3xxx_timer8
 			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer9 */
@@ -978,10 +987,10 @@ static struct omap_hwmod omap3xxx_timer9
 			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer10 */
@@ -1015,10 +1024,10 @@ static struct omap_hwmod omap3xxx_timer1
 			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer11 */
@@ -1052,10 +1061,10 @@ static struct omap_hwmod omap3xxx_timer1
 			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer12*/
@@ -1102,10 +1111,10 @@ static struct omap_hwmod omap3xxx_timer1
 			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_secure_dev_attr,
 	.slaves		= omap3xxx_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -1182,7 +1191,6 @@ static struct omap_hwmod omap3xxx_wd_tim
 	},
 	.slaves		= omap3xxx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	/*
 	 * XXX: Use software supervised mode, HW supervised smartidle seems to
 	 * block CORE power domain idle transitions. Maybe a HW bug in wdt2?
@@ -1213,7 +1221,6 @@ static struct omap_hwmod omap3xxx_uart1_
 	.slaves		= omap3xxx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART2 */
@@ -1239,7 +1246,6 @@ static struct omap_hwmod omap3xxx_uart2_
 	.slaves		= omap3xxx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART3 */
@@ -1265,7 +1271,6 @@ static struct omap_hwmod omap3xxx_uart3_
 	.slaves		= omap3xxx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART4 */
@@ -1302,7 +1307,6 @@ static struct omap_hwmod omap3xxx_uart4_
 	.slaves		= omap3xxx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 static struct omap_hwmod_class i2c_class = {
@@ -1365,9 +1369,14 @@ static struct omap_hwmod_ocp_if *omap3xx
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "tv_clk", .clk = "dss_tv_fck" },
-	{ .role = "video_clk", .clk = "dss_96m_fck" },
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1390,12 +1399,12 @@ static struct omap_hwmod omap3430es1_dss
 	.slaves_cnt	= ARRAY_SIZE(omap3430es1_dss_slaves),
 	.masters	= omap3xxx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
-	.flags		= HWMOD_NO_IDLEST,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.name		= "dss_core",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
@@ -1415,8 +1424,6 @@ static struct omap_hwmod omap3xxx_dss_co
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_slaves),
 	.masters	= omap3xxx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 |
-				CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
 };
 
 /* l4_core -> dss_dispc */
@@ -1454,10 +1461,8 @@ static struct omap_hwmod omap3xxx_dss_di
 	},
 	.slaves		= omap3xxx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /*
@@ -1488,6 +1493,7 @@ static struct omap_hwmod_addr_space omap
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dsi1_hwmod,
+	.clk		= "dss_ick",
 	.addr		= omap3xxx_dss_dsi1_addrs,
 	.fw = {
 		.omap2 = {
@@ -1504,6 +1510,10 @@ static struct omap_hwmod_ocp_if *omap3xx
 	&omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
@@ -1516,11 +1526,10 @@ static struct omap_hwmod omap3xxx_dss_ds
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.slaves		= omap3xxx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1545,6 +1554,10 @@ static struct omap_hwmod_ocp_if *omap3xx
 	&omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -1556,11 +1569,10 @@ static struct omap_hwmod omap3xxx_dss_rf
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap3xxx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1568,7 +1580,7 @@ static struct omap_hwmod omap3xxx_dss_rf
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_venc_hwmod,
-	.clk		= "dss_tv_fck",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
@@ -1586,10 +1598,15 @@ static struct omap_hwmod_ocp_if *omap3xx
 	&omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_alwon_fck",
+	.main_clk	= "dss_tv_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1597,11 +1614,10 @@ static struct omap_hwmod omap3xxx_dss_ve
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_venc_opt_clks),
 	.slaves		= omap3xxx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1637,7 +1653,6 @@ static struct omap_hwmod omap3xxx_i2c1_h
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C2 */
@@ -1672,7 +1687,6 @@ static struct omap_hwmod omap3xxx_i2c2_h
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C3 */
@@ -1718,7 +1732,6 @@ static struct omap_hwmod omap3xxx_i2c3_h
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c3_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1880,7 +1893,6 @@ static struct omap_hwmod omap3xxx_gpio1_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio1_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio2 */
@@ -1912,7 +1924,6 @@ static struct omap_hwmod omap3xxx_gpio2_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio2_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio3 */
@@ -1944,7 +1955,6 @@ static struct omap_hwmod omap3xxx_gpio3_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio3_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio4 */
@@ -1976,7 +1986,6 @@ static struct omap_hwmod omap3xxx_gpio4_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio4_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio5 */
@@ -2013,7 +2022,6 @@ static struct omap_hwmod omap3xxx_gpio5_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio5_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio6 */
@@ -2050,7 +2058,6 @@ static struct omap_hwmod omap3xxx_gpio6_
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio6_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* dma_system -> L3 */
@@ -2134,7 +2141,6 @@ static struct omap_hwmod omap3xxx_dma_sy
 	.masters	= omap3xxx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -2207,7 +2213,6 @@ static struct omap_hwmod omap3xxx_mcbsp1
 	},
 	.slaves		= omap3xxx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp2 */
@@ -2264,7 +2269,6 @@ static struct omap_hwmod omap3xxx_mcbsp2
 	.slaves		= omap3xxx_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
 	.dev_attr	= &omap34xx_mcbsp2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp3 */
@@ -2321,7 +2325,6 @@ static struct omap_hwmod omap3xxx_mcbsp3
 	.slaves		= omap3xxx_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
 	.dev_attr	= &omap34xx_mcbsp3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp4 */
@@ -2379,7 +2382,6 @@ static struct omap_hwmod omap3xxx_mcbsp4
 	},
 	.slaves		= omap3xxx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp5 */
@@ -2437,7 +2439,6 @@ static struct omap_hwmod omap3xxx_mcbsp5
 	},
 	.slaves		= omap3xxx_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 /* 'mcbsp sidetone' class */
 
@@ -2498,7 +2499,6 @@ static struct omap_hwmod omap3xxx_mcbsp2
 	},
 	.slaves		= omap3xxx_mcbsp2_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp3_sidetone */
@@ -2547,7 +2547,6 @@ static struct omap_hwmod omap3xxx_mcbsp3
 	},
 	.slaves		= omap3xxx_mcbsp3_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 
@@ -2597,7 +2596,7 @@ static struct omap_hwmod omap34xx_sr1_hw
 	.name		= "sr1_hwmod",
 	.class		= &omap34xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2609,9 +2608,6 @@ static struct omap_hwmod omap34xx_sr1_hw
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2619,7 +2615,7 @@ static struct omap_hwmod omap36xx_sr1_hw
 	.name		= "sr1_hwmod",
 	.class		= &omap36xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2631,7 +2627,6 @@ static struct omap_hwmod omap36xx_sr1_hw
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /* SR2 */
@@ -2655,9 +2650,6 @@ static struct omap_hwmod omap34xx_sr2_hw
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2677,7 +2669,6 @@ static struct omap_hwmod omap36xx_sr2_hw
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /*
@@ -2745,7 +2736,6 @@ static struct omap_hwmod omap3xxx_mailbo
 	},
 	.slaves		= omap3xxx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4 core -> mcspi1 interface */
@@ -2843,7 +2833,6 @@ static struct omap_hwmod omap34xx_mcspi1
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi1_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcspi2 */
@@ -2873,7 +2862,6 @@ static struct omap_hwmod omap34xx_mcspi2
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi2_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcspi3 */
@@ -2916,7 +2904,6 @@ static struct omap_hwmod omap34xx_mcspi3
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi3_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* SPI4 */
@@ -2957,7 +2944,6 @@ static struct omap_hwmod omap34xx_mcspi4
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi4_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi4_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /*
@@ -3014,7 +3000,6 @@ static struct omap_hwmod omap3xxx_usbhso
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* usb_otg_hs */
@@ -3042,7 +3027,6 @@ static struct omap_hwmod am35xx_usbhsotg
 	.slaves		= am35xx_usbhsotg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(am35xx_usbhsotg_slaves),
 	.class		= &am35xx_usbotg_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1)
 };
 
 /* MMC/SD/SDIO common */
@@ -3108,7 +3092,6 @@ static struct omap_hwmod omap3xxx_mmc1_h
 	.slaves		= omap3xxx_mmc1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc1_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* MMC/SD/SDIO2 */
@@ -3151,7 +3134,6 @@ static struct omap_hwmod omap3xxx_mmc2_h
 	.slaves		= omap3xxx_mmc2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc2_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* MMC/SD/SDIO3 */
@@ -3193,7 +3175,6 @@ static struct omap_hwmod omap3xxx_mmc3_h
 	.slaves		= omap3xxx_mmc3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc3_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
@@ -3205,7 +3186,6 @@ static __initdata struct omap_hwmod *oma
 	&omap3xxx_mmc2_hwmod,
 	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
-	&omap3xxx_iva_hwmod,
 
 	&omap3xxx_timer1_hwmod,
 	&omap3xxx_timer2_hwmod,
@@ -3224,10 +3204,7 @@ static __initdata struct omap_hwmod *oma
 	&omap3xxx_uart1_hwmod,
 	&omap3xxx_uart2_hwmod,
 	&omap3xxx_uart3_hwmod,
-	&omap3xxx_uart4_hwmod,
 	/* dss class */
-	&omap3430es1_dss_core_hwmod,
-	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_dss_dispc_hwmod,
 	&omap3xxx_dss_dsi1_hwmod,
 	&omap3xxx_dss_rfbi_hwmod,
@@ -3237,11 +3214,6 @@ static __initdata struct omap_hwmod *oma
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
-	&omap34xx_sr1_hwmod,
-	&omap34xx_sr2_hwmod,
-	&omap36xx_sr1_hwmod,
-	&omap36xx_sr2_hwmod,
-
 
 	/* gpio class */
 	&omap3xxx_gpio1_hwmod,
@@ -3263,8 +3235,6 @@ static __initdata struct omap_hwmod *oma
 	&omap3xxx_mcbsp2_sidetone_hwmod,
 	&omap3xxx_mcbsp3_sidetone_hwmod,
 
-	/* mailbox class */
-	&omap3xxx_mailbox_hwmod,
 
 	/* mcspi class */
 	&omap34xx_mcspi1,
@@ -3272,16 +3242,100 @@ static __initdata struct omap_hwmod *oma
 	&omap34xx_mcspi3,
 	&omap34xx_mcspi4,
 
-	/* usbotg class */
+	NULL,
+};
+
+/* 3430ES1-only hwmods */
+static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+	&omap3430es1_dss_core_hwmod,
+	NULL
+};
+
+/* 3430ES2+-only hwmods */
+static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_usbhsotg_hwmod,
+	NULL
+};
 
-	/* usbotg for am35x */
-	&am35xx_usbhsotg_hwmod,
+/* 34xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
+	&omap3xxx_mailbox_hwmod,
+	NULL
+};
 
-	NULL,
+/* 36xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
+	&omap3xxx_uart4_hwmod,
+	&omap3xxx_dss_core_hwmod,
+	&omap36xx_sr1_hwmod,
+	&omap36xx_sr2_hwmod,
+	&omap3xxx_usbhsotg_hwmod,
+	&omap3xxx_mailbox_hwmod,
+	NULL
+};
+
+static __initdata struct omap_hwmod *am35xx_hwmods[] = {
+	&omap3xxx_dss_core_hwmod, /* XXX ??? */
+	&am35xx_usbhsotg_hwmod,
+	NULL
 };
 
 int __init omap3xxx_hwmod_init(void)
 {
-	return omap_hwmod_register(omap3xxx_hwmods);
+	int r;
+	struct omap_hwmod **h = NULL;
+	unsigned int rev;
+
+	/* Register hwmods common to all OMAP3 */
+	r = omap_hwmod_register(omap3xxx_hwmods);
+	if (r < 0)
+		return r;
+
+	rev = omap_rev();
+
+	/*
+	 * Register hwmods common to individual OMAP3 families, all
+	 * silicon revisions (e.g., 34xx, or AM3505/3517, or 36xx)
+	 * All possible revisions should be included in this conditional.
+	 */
+	if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
+	    rev == OMAP3430_REV_ES2_1 || rev == OMAP3430_REV_ES3_0 ||
+	    rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) {
+		h = omap34xx_hwmods;
+	} else if (rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1) {
+		h = am35xx_hwmods;
+	} else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
+		   rev == OMAP3630_REV_ES1_2) {
+		h = omap36xx_hwmods;
+	} else {
+		WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
+		return -EINVAL;
+	};
+
+	r = omap_hwmod_register(h);
+	if (r < 0)
+		return r;
+
+	/*
+	 * Register hwmods specific to certain ES levels of a
+	 * particular family of silicon (e.g., 34xx ES1.0)
+	 */
+	h = NULL;
+	if (rev == OMAP3430_REV_ES1_0) {
+		h = omap3430es1_hwmods;
+	} else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		   rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
+		   rev == OMAP3430_REV_ES3_1_2) {
+		h = omap3430es2plus_hwmods;
+	};
+
+	if (h)
+		r = omap_hwmod_register(h);
+
+	return r;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/i2c.h>
+#include <plat/dmtimer.h>
+#include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -133,7 +135,6 @@ static struct omap_hwmod omap44xx_dmm_hw
 	.slaves		= omap44xx_dmm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmm_slaves),
 	.mpu_irqs	= omap44xx_dmm_irqs,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -189,7 +190,6 @@ static struct omap_hwmod omap44xx_emif_f
 	},
 	.slaves		= omap44xx_emif_fw_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_emif_fw_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -236,7 +236,6 @@ static struct omap_hwmod omap44xx_l3_ins
 	},
 	.slaves		= omap44xx_l3_instr_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_instr_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_1 */
@@ -336,7 +335,6 @@ static struct omap_hwmod omap44xx_l3_mai
 	},
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_2 */
@@ -438,7 +436,6 @@ static struct omap_hwmod omap44xx_l3_mai
 	},
 	.slaves		= omap44xx_l3_main_2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_3 */
@@ -496,7 +493,6 @@ static struct omap_hwmod omap44xx_l3_mai
 	},
 	.slaves		= omap44xx_l3_main_3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -559,7 +555,6 @@ static struct omap_hwmod omap44xx_l4_abe
 	},
 	.slaves		= omap44xx_l4_abe_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_abe_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_cfg */
@@ -588,7 +583,6 @@ static struct omap_hwmod omap44xx_l4_cfg
 	},
 	.slaves		= omap44xx_l4_cfg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_cfg_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_per */
@@ -617,7 +611,6 @@ static struct omap_hwmod omap44xx_l4_per
 	},
 	.slaves		= omap44xx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_wkup */
@@ -646,7 +639,6 @@ static struct omap_hwmod omap44xx_l4_wku
 	},
 	.slaves		= omap44xx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -677,7 +669,6 @@ static struct omap_hwmod omap44xx_mpu_pr
 	.clkdm_name	= "mpuss_clkdm",
 	.slaves		= omap44xx_mpu_private_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mpu_private_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -828,7 +819,6 @@ static struct omap_hwmod omap44xx_aess_h
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_aess_slaves),
 	.masters	= omap44xx_aess_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_aess_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -856,7 +846,6 @@ static struct omap_hwmod omap44xx_bandga
 	},
 	.opt_clks	= bandgap_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(bandgap_opt_clks),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -917,7 +906,6 @@ static struct omap_hwmod omap44xx_counte
 	},
 	.slaves		= omap44xx_counter_32k_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_counter_32k_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1005,7 +993,6 @@ static struct omap_hwmod omap44xx_dma_sy
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dma_system_slaves),
 	.masters	= omap44xx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dma_system_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1098,7 +1085,6 @@ static struct omap_hwmod omap44xx_dmic_h
 	},
 	.slaves		= omap44xx_dmic_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmic_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1164,7 +1150,6 @@ static struct omap_hwmod omap44xx_dsp_c0
 			.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1187,7 +1172,6 @@ static struct omap_hwmod omap44xx_dsp_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dsp_slaves),
 	.masters	= omap44xx_dsp_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dsp_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1204,6 +1188,7 @@ static struct omap_hwmod_class_sysconfig
 static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
 	.name	= "dss",
 	.sysc	= &omap44xx_dss_sysc,
+	.reset	= omap_dss_reset,
 };
 
 /* dss */
@@ -1257,12 +1242,12 @@ static struct omap_hwmod_ocp_if *omap44x
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 	{ .role = "sys_clk", .clk = "dss_sys_clk" },
 	{ .role = "tv_clk", .clk = "dss_tv_clk" },
-	{ .role = "dss_clk", .clk = "dss_dss_clk" },
-	{ .role = "video_clk", .clk = "dss_48mhz_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap44xx_dss_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
 	.main_clk	= "dss_dss_clk",
@@ -1278,7 +1263,6 @@ static struct omap_hwmod omap44xx_dss_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_slaves),
 	.masters	= omap44xx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1343,6 +1327,11 @@ static struct omap_hwmod_addr_space omap
 	{ }
 };
 
+static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = {
+	.manager_count		= 3,
+	.has_framedonetv_irq	= 1
+};
+
 /* l4_per -> dss_dispc */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
 	.master		= &omap44xx_l4_per_hwmod,
@@ -1358,12 +1347,6 @@ static struct omap_hwmod_ocp_if *omap44x
 	&omap44xx_l4_per__dss_dispc,
 };
 
-static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
-	{ .role = "sys_clk", .clk = "dss_sys_clk" },
-	{ .role = "tv_clk", .clk = "dss_tv_clk" },
-	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
-};
-
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
@@ -1377,11 +1360,9 @@ static struct omap_hwmod omap44xx_dss_di
 			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
-	.opt_clks	= dss_dispc_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(dss_dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+	.dev_attr	= &omap44xx_dss_dispc_dev_attr
 };
 
 /*
@@ -1480,7 +1461,6 @@ static struct omap_hwmod omap44xx_dss_ds
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* dss_dsi2 */
@@ -1558,7 +1538,6 @@ static struct omap_hwmod omap44xx_dss_ds
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi2_opt_clks),
 	.slaves		= omap44xx_dss_dsi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1645,7 +1624,7 @@ static struct omap_hwmod omap44xx_dss_hd
 	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
-	.main_clk	= "dss_dss_clk",
+	.main_clk	= "dss_48mhz_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1656,7 +1635,6 @@ static struct omap_hwmod omap44xx_dss_hd
 	.opt_clks_cnt	= ARRAY_SIZE(dss_hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1748,7 +1726,6 @@ static struct omap_hwmod omap44xx_dss_rf
 	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1808,7 +1785,7 @@ static struct omap_hwmod omap44xx_dss_ve
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
-	.main_clk	= "dss_dss_clk",
+	.main_clk	= "dss_tv_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1817,7 +1794,6 @@ static struct omap_hwmod omap44xx_dss_ve
 	},
 	.slaves		= omap44xx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1901,7 +1877,6 @@ static struct omap_hwmod omap44xx_gpio1_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio2 */
@@ -1957,7 +1932,6 @@ static struct omap_hwmod omap44xx_gpio2_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio3 */
@@ -2013,7 +1987,6 @@ static struct omap_hwmod omap44xx_gpio3_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio4 */
@@ -2069,7 +2042,6 @@ static struct omap_hwmod omap44xx_gpio4_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio5 */
@@ -2125,7 +2097,6 @@ static struct omap_hwmod omap44xx_gpio5_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio6 */
@@ -2181,7 +2152,6 @@ static struct omap_hwmod omap44xx_gpio6_
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2261,7 +2231,6 @@ static struct omap_hwmod omap44xx_hsi_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_hsi_slaves),
 	.masters	= omap44xx_hsi_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_hsi_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2345,7 +2314,6 @@ static struct omap_hwmod omap44xx_i2c1_h
 	.slaves		= omap44xx_i2c1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c2 */
@@ -2402,7 +2370,6 @@ static struct omap_hwmod omap44xx_i2c2_h
 	.slaves		= omap44xx_i2c2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c3 */
@@ -2459,7 +2426,6 @@ static struct omap_hwmod omap44xx_i2c3_h
 	.slaves		= omap44xx_i2c3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c4 */
@@ -2516,7 +2482,6 @@ static struct omap_hwmod omap44xx_i2c4_h
 	.slaves		= omap44xx_i2c4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2577,7 +2542,6 @@ static struct omap_hwmod omap44xx_ipu_c0
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2593,7 +2557,6 @@ static struct omap_hwmod omap44xx_ipu_c1
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_ipu_hwmod = {
@@ -2616,7 +2579,6 @@ static struct omap_hwmod omap44xx_ipu_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_ipu_slaves),
 	.masters	= omap44xx_ipu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_ipu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2706,7 +2668,6 @@ static struct omap_hwmod omap44xx_iss_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_iss_slaves),
 	.masters	= omap44xx_iss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_iss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2781,7 +2742,6 @@ static struct omap_hwmod omap44xx_iva_se
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2797,7 +2757,6 @@ static struct omap_hwmod omap44xx_iva_se
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_iva_hwmod = {
@@ -2820,7 +2779,6 @@ static struct omap_hwmod omap44xx_iva_hw
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_iva_slaves),
 	.masters	= omap44xx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2890,7 +2848,6 @@ static struct omap_hwmod omap44xx_kbd_hw
 	},
 	.slaves		= omap44xx_kbd_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_kbd_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2956,7 +2913,6 @@ static struct omap_hwmod omap44xx_mailbo
 	},
 	.slaves		= omap44xx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3051,7 +3007,6 @@ static struct omap_hwmod omap44xx_mcbsp1
 	},
 	.slaves		= omap44xx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp2 */
@@ -3127,7 +3082,6 @@ static struct omap_hwmod omap44xx_mcbsp2
 	},
 	.slaves		= omap44xx_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp3 */
@@ -3203,7 +3157,6 @@ static struct omap_hwmod omap44xx_mcbsp3
 	},
 	.slaves		= omap44xx_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp4 */
@@ -3258,7 +3211,6 @@ static struct omap_hwmod omap44xx_mcbsp4
 	},
 	.slaves		= omap44xx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3353,7 +3305,6 @@ static struct omap_hwmod omap44xx_mcpdm_
 	},
 	.slaves		= omap44xx_mcpdm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcpdm_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3442,7 +3393,6 @@ static struct omap_hwmod omap44xx_mcspi1
 	.dev_attr	= &mcspi1_dev_attr,
 	.slaves		= omap44xx_mcspi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi2 */
@@ -3505,7 +3455,6 @@ static struct omap_hwmod omap44xx_mcspi2
 	.dev_attr	= &mcspi2_dev_attr,
 	.slaves		= omap44xx_mcspi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi3 */
@@ -3568,7 +3517,6 @@ static struct omap_hwmod omap44xx_mcspi3
 	.dev_attr	= &mcspi3_dev_attr,
 	.slaves		= omap44xx_mcspi3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi4 */
@@ -3629,7 +3577,6 @@ static struct omap_hwmod omap44xx_mcspi4
 	.dev_attr	= &mcspi4_dev_attr,
 	.slaves		= omap44xx_mcspi4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3718,7 +3665,6 @@ static struct omap_hwmod omap44xx_mmc1_h
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc1_slaves),
 	.masters	= omap44xx_mmc1_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc1_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc2 */
@@ -3779,7 +3725,6 @@ static struct omap_hwmod omap44xx_mmc2_h
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc2_slaves),
 	.masters	= omap44xx_mmc2_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc2_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc3 */
@@ -3834,7 +3779,6 @@ static struct omap_hwmod omap44xx_mmc3_h
 	},
 	.slaves		= omap44xx_mmc3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc4 */
@@ -3890,7 +3834,6 @@ static struct omap_hwmod omap44xx_mmc4_h
 	},
 	.slaves		= omap44xx_mmc4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc5 */
@@ -3945,7 +3888,6 @@ static struct omap_hwmod omap44xx_mmc5_h
 	},
 	.slaves		= omap44xx_mmc5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3987,7 +3929,6 @@ static struct omap_hwmod omap44xx_mpu_hw
 	},
 	.masters	= omap44xx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4063,7 +4004,6 @@ static struct omap_hwmod omap44xx_smartr
 	},
 	.slaves		= omap44xx_smartreflex_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_iva */
@@ -4112,7 +4052,6 @@ static struct omap_hwmod omap44xx_smartr
 	},
 	.slaves		= omap44xx_smartreflex_iva_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_mpu */
@@ -4161,7 +4100,6 @@ static struct omap_hwmod omap44xx_smartr
 	},
 	.slaves		= omap44xx_smartreflex_mpu_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4224,7 +4162,6 @@ static struct omap_hwmod omap44xx_spinlo
 	},
 	.slaves		= omap44xx_spinlock_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_spinlock_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4265,6 +4202,16 @@ static struct omap_hwmod_class omap44xx_
 	.sysc	= &omap44xx_timer_sysc,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability	= OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability	= OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4308,9 +4255,9 @@ static struct omap_hwmod omap44xx_timer1
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer2 */
@@ -4356,9 +4303,9 @@ static struct omap_hwmod omap44xx_timer2
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer3 */
@@ -4404,9 +4351,9 @@ static struct omap_hwmod omap44xx_timer3
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer4 */
@@ -4452,9 +4399,9 @@ static struct omap_hwmod omap44xx_timer4
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer5 */
@@ -4519,9 +4466,9 @@ static struct omap_hwmod omap44xx_timer5
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer6 */
@@ -4587,9 +4534,9 @@ static struct omap_hwmod omap44xx_timer6
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer7 */
@@ -4654,9 +4601,9 @@ static struct omap_hwmod omap44xx_timer7
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer8 */
@@ -4721,9 +4668,9 @@ static struct omap_hwmod omap44xx_timer8
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer9 */
@@ -4769,9 +4716,9 @@ static struct omap_hwmod omap44xx_timer9
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer10 */
@@ -4817,9 +4764,9 @@ static struct omap_hwmod omap44xx_timer1
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer11 */
@@ -4865,9 +4812,9 @@ static struct omap_hwmod omap44xx_timer1
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4944,7 +4891,6 @@ static struct omap_hwmod omap44xx_uart1_
 	},
 	.slaves		= omap44xx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart2 */
@@ -4999,7 +4945,6 @@ static struct omap_hwmod omap44xx_uart2_
 	},
 	.slaves		= omap44xx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart3 */
@@ -5055,7 +5000,6 @@ static struct omap_hwmod omap44xx_uart3_
 	},
 	.slaves		= omap44xx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart4 */
@@ -5110,7 +5054,6 @@ static struct omap_hwmod omap44xx_uart4_
 	},
 	.slaves		= omap44xx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -5195,7 +5138,6 @@ static struct omap_hwmod omap44xx_usb_ot
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
 	.masters	= omap44xx_usb_otg_hs_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -5266,7 +5208,6 @@ static struct omap_hwmod omap44xx_wd_tim
 	},
 	.slaves		= omap44xx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* wd_timer3 */
@@ -5333,7 +5274,6 @@ static struct omap_hwmod omap44xx_wd_tim
 	},
 	.slaves		= omap44xx_wd_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
@@ -5430,7 +5370,7 @@ static __initdata struct omap_hwmod *oma
 	&omap44xx_mcbsp4_hwmod,
 
 	/* mcpdm class */
-/*	&omap44xx_mcpdm_hwmod, */
+	&omap44xx_mcpdm_hwmod,
 
 	/* mcspi class */
 	&omap44xx_mcspi1_hwmod,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod.c	2012-01-04 18:55:44.000000000 -0500
@@ -749,7 +749,7 @@ static int _count_mpu_irqs(struct omap_h
 		ohii = &oh->mpu_irqs[i++];
 	} while (ohii->irq != -1);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -772,7 +772,7 @@ static int _count_sdma_reqs(struct omap_
 		ohdi = &oh->sdma_reqs[i++];
 	} while (ohdi->dma_req != -1);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -795,7 +795,7 @@ static int _count_ocp_if_addr_spaces(str
 		mem = &os->addr[i++];
 	} while (mem->pa_start != mem->pa_end);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -1954,9 +1954,6 @@ int __init omap_hwmod_register(struct om
 
 	i = 0;
 	do {
-		if (!omap_chip_is(ohs[i]->omap_chip))
-			continue;
-
 		r = _register(ohs[i]);
 		WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
 		     r);
@@ -2628,7 +2625,7 @@ ohsps_unlock:
  * Returns the context loss count of the powerdomain assocated with @oh
  * upon success, or zero if no powerdomain exists for @oh.
  */
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,3 +49,7 @@ struct omap_hwmod_sysc_fields omap_hwmod
 	.srst_shift	= SYSC_TYPE2_SOFTRESET_SHIFT,
 };
 
+struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
+	.manager_count		= 2,
+	.has_framedonetv_irq	= 0
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_hwmod_common_data.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "display.h"
+
 /* Common address space across OMAP2xxx */
 extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
 extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
@@ -111,4 +113,6 @@ extern struct omap_hwmod_class omap2xxx_
 extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mcspi_class;
 
+extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr;
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap-iommu.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap-iommu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 
 #include <plat/iommu.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_noc.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_noc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_noc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_noc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,25 +1,26 @@
 /*
-  * OMAP4XXX L3 Interconnect error handling driver
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	Sricharan <r.sricharan@ti.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.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+ * OMAP4XXX L3 Interconnect error handling driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -55,12 +56,12 @@
 static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 {
 
-	struct omap4_l3		*l3 = _l3;
-	int inttype, i, j;
+	struct omap4_l3 *l3 = _l3;
+	int inttype, i, k;
 	int err_src = 0;
-	u32 std_err_main_addr, std_err_main, err_reg;
-	u32 base, slave_addr, clear;
-	char *source_name;
+	u32 std_err_main, err_reg, clear, masterid;
+	void __iomem *base, *l3_targ_base;
+	char *target_name, *master_name = "UN IDENTIFIED";
 
 	/* Get the Type of interrupt */
 	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -70,43 +71,50 @@ static irqreturn_t l3_interrupt_handler(
 		 * Read the regerr register of the clock domain
 		 * to determine the source
 		 */
-		base = (u32)l3->l3_base[i];
-		err_reg =  readl(base + l3_flagmux[i] + (inttype << 3));
+		base = l3->l3_base[i];
+		err_reg = __raw_readl(base + l3_flagmux[i] +
+					+ L3_FLAGMUX_REGERR0 + (inttype << 3));
 
 		/* Get the corresponding error and analyse */
 		if (err_reg) {
 			/* Identify the source from control status register */
-			for (j = 0; !(err_reg & (1 << j)); j++)
-									;
+			err_src = __ffs(err_reg);
 
-			err_src = j;
 			/* Read the stderrlog_main_source from clk domain */
-			std_err_main_addr = base + *(l3_targ[i] + err_src);
-			std_err_main = readl(std_err_main_addr);
+			l3_targ_base = base + *(l3_targ[i] + err_src);
+			std_err_main =  __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+			masterid = __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MSTADDR);
 
 			switch (std_err_main & CUSTOM_ERROR) {
 			case STANDARD_ERROR:
-				source_name =
-				l3_targ_stderrlog_main_name[i][err_src];
-
-				slave_addr = std_err_main_addr +
-						L3_SLAVE_ADDRESS_OFFSET;
-				WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
-					source_name, readl(slave_addr));
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
+					target_name,
+					__raw_readl(l3_targ_base +
+						L3_TARG_STDERRLOG_SLVOFSLSB));
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				break;
 
 			case CUSTOM_ERROR:
-				source_name =
-				l3_targ_stderrlog_main_name[i][err_src];
-
-				WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
-							source_name);
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+					if (masterid == l3_masters[k].id)
+						master_name =
+							l3_masters[k].name;
+				}
+				WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
+					master_name, target_name);
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				break;
 
 			default:
@@ -120,12 +128,11 @@ static irqreturn_t l3_interrupt_handler(
 	return IRQ_HANDLED;
 }
 
-static int __init omap4_l3_probe(struct platform_device *pdev)
+static int __devinit omap4_l3_probe(struct platform_device *pdev)
 {
-	static struct omap4_l3		*l3;
-	struct resource		*res;
-	int			ret;
-	int			irq;
+	static struct omap4_l3 *l3;
+	struct resource	*res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
@@ -177,27 +184,25 @@ static int __init omap4_l3_probe(struct
 	/*
 	 * Setup interrupt Handlers
 	 */
-	irq = platform_get_irq(pdev, 0);
-	ret = request_irq(irq,
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_irq,
 			l3_interrupt_handler,
 			IRQF_DISABLED, "l3-dbg-irq", l3);
 	if (ret) {
 		pr_crit("L3: request_irq failed to register for 0x%x\n",
-					 OMAP44XX_IRQ_L3_DBG);
+						OMAP44XX_IRQ_L3_DBG);
 		goto err3;
 	}
-	l3->debug_irq = irq;
 
-	irq = platform_get_irq(pdev, 1);
-	ret = request_irq(irq,
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_irq,
 			l3_interrupt_handler,
 			IRQF_DISABLED, "l3-app-irq", l3);
 	if (ret) {
 		pr_crit("L3: request_irq failed to register for 0x%x\n",
-					 OMAP44XX_IRQ_L3_APP);
+						OMAP44XX_IRQ_L3_APP);
 		goto err4;
 	}
-	l3->app_irq = irq;
 
 	return 0;
 
@@ -214,9 +219,9 @@ err0:
 	return ret;
 }
 
-static int __exit omap4_l3_remove(struct platform_device *pdev)
+static int __devexit omap4_l3_remove(struct platform_device *pdev)
 {
-	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+	struct omap4_l3 *l3 = platform_get_drvdata(pdev);
 
 	free_irq(l3->app_irq, l3);
 	free_irq(l3->debug_irq, l3);
@@ -228,16 +233,29 @@ static int __exit omap4_l3_remove(struct
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id l3_noc_match[] = {
+	{.compatible = "ti,omap4-l3-noc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+#else
+#define l3_noc_match NULL
+#endif
+
 static struct platform_driver omap4_l3_driver = {
-	.remove		= __exit_p(omap4_l3_remove),
+	.probe		= omap4_l3_probe,
+	.remove		= __devexit_p(omap4_l3_remove),
 	.driver		= {
-	.name		= "omap_l3_noc",
+		.name		= "omap_l3_noc",
+		.owner		= THIS_MODULE,
+		.of_match_table = l3_noc_match,
 	},
 };
 
 static int __init omap4_l3_init(void)
 {
-	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+	return platform_driver_register(&omap4_l3_driver);
 }
 postcore_initcall_sync(omap4_l3_init);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_noc.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_noc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_noc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_noc.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,132 +1,162 @@
- /*
-  * OMAP4XXX L3 Interconnect  error handling driver header
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	sricharan <r.sricharan@ti.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.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP4XXX L3 Interconnect  error handling driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 #ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 #define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 
-/*
- * L3 register offsets
- */
 #define L3_MODULES			3
 #define CLEAR_STDERR_LOG		(1 << 31)
 #define CUSTOM_ERROR			0x2
 #define STANDARD_ERROR			0x0
 #define INBAND_ERROR			0x0
-#define EMIF_KERRLOG_OFFSET		0x10
-#define L3_SLAVE_ADDRESS_OFFSET		0x14
-#define LOGICAL_ADDR_ERRORLOG		0x4
 #define L3_APPLICATION_ERROR		0x0
 #define L3_DEBUG_ERROR			0x1
 
-u32 l3_flagmux[L3_MODULES] = {
-	0x50C,
-	0x100C,
-	0X020C
+/* L3 TARG register offsets */
+#define L3_TARG_STDERRLOG_MAIN		0x48
+#define L3_TARG_STDERRLOG_SLVOFSLSB	0x5c
+#define L3_TARG_STDERRLOG_MSTADDR	0x68
+#define L3_FLAGMUX_REGERR0		0xc
+
+#define NUM_OF_L3_MASTERS	(sizeof(l3_masters)/sizeof(l3_masters[0]))
+
+static u32 l3_flagmux[L3_MODULES] = {
+	0x500,
+	0x1000,
+	0X0200
 };
 
-/*
- * L3 Target standard Error register offsets
- */
-u32 l3_targ_stderrlog_main_clk1[] = {
-	0x148, /* DMM1 */
-	0x248, /* DMM2 */
-	0x348, /* ABE */
-	0x448, /* L4CFG */
-	0x648  /* CLK2 PWR DISC */
+/* L3 Target standard Error register offsets */
+static u32 l3_targ_inst_clk1[] = {
+	0x100, /* DMM1 */
+	0x200, /* DMM2 */
+	0x300, /* ABE */
+	0x400, /* L4CFG */
+	0x600  /* CLK2 PWR DISC */
 };
 
-u32 l3_targ_stderrlog_main_clk2[] = {
-	0x548,		/* CORTEX M3 */
-	0x348,		/* DSS */
-	0x148,		/* GPMC */
-	0x448,		/* ISS */
-	0x748,		/* IVAHD */
-	0xD48,		/* missing in TRM  corresponds to AES1*/
-	0x948,		/* L4 PER0*/
-	0x248,		/* OCMRAM */
-	0x148,		/* missing in TRM corresponds to GPMC sERROR*/
-	0x648,		/* SGX */
-	0x848,		/* SL2 */
-	0x1648,		/* C2C */
-	0x1148,		/* missing in TRM corresponds PWR DISC CLK1*/
-	0xF48,		/* missing in TRM corrsponds to SHA1*/
-	0xE48,		/* missing in TRM corresponds to AES2*/
-	0xC48,		/* L4 PER3 */
-	0xA48,		/* L4 PER1*/
-	0xB48		/* L4 PER2*/
+static u32 l3_targ_inst_clk2[] = {
+	0x500, /* CORTEX M3 */
+	0x300, /* DSS */
+	0x100, /* GPMC */
+	0x400, /* ISS */
+	0x700, /* IVAHD */
+	0xD00, /* missing in TRM  corresponds to AES1*/
+	0x900, /* L4 PER0*/
+	0x200, /* OCMRAM */
+	0x100, /* missing in TRM corresponds to GPMC sERROR*/
+	0x600, /* SGX */
+	0x800, /* SL2 */
+	0x1600, /* C2C */
+	0x1100,	/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF00, /* missing in TRM corrsponds to SHA1*/
+	0xE00, /* missing in TRM corresponds to AES2*/
+	0xC00, /* L4 PER3 */
+	0xA00, /* L4 PER1*/
+	0xB00 /* L4 PER2*/
 };
 
-u32 l3_targ_stderrlog_main_clk3[] = {
-	0x0148	/* EMUSS */
+static u32 l3_targ_inst_clk3[] = {
+	0x0100	/* EMUSS */
 };
 
-char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+static struct l3_masters_data {
+	u32 id;
+	char name[10];
+} l3_masters[] = {
+	{ 0x0 , "MPU"},
+	{ 0x10, "CS_ADP"},
+	{ 0x14, "xxx"},
+	{ 0x20, "DSP"},
+	{ 0x30, "IVAHD"},
+	{ 0x40, "ISS"},
+	{ 0x44, "DucatiM3"},
+	{ 0x48, "FaceDetect"},
+	{ 0x50, "SDMA_Rd"},
+	{ 0x54, "SDMA_Wr"},
+	{ 0x58, "xxx"},
+	{ 0x5C, "xxx"},
+	{ 0x60, "SGX"},
+	{ 0x70, "DSS"},
+	{ 0x80, "C2C"},
+	{ 0x88, "xxx"},
+	{ 0x8C, "xxx"},
+	{ 0x90, "HSI"},
+	{ 0xA0, "MMC1"},
+	{ 0xA4, "MMC2"},
+	{ 0xA8, "MMC6"},
+	{ 0xB0, "UNIPRO1"},
+	{ 0xC0, "USBHOSTHS"},
+	{ 0xC4, "USBOTGHS"},
+	{ 0xC8, "USBHOSTFS"}
+};
+
+static char *l3_targ_inst_name[L3_MODULES][18] = {
 	{
-	"DMM1",
-	"DMM2",
-	"ABE",
-	"L4CFG",
-	"CLK2 PWR DISC",
+		"DMM1",
+		"DMM2",
+		"ABE",
+		"L4CFG",
+		"CLK2 PWR DISC",
 	},
 	{
-	"CORTEX M3" ,
-	"DSS ",
-	"GPMC ",
-	"ISS ",
-	"IVAHD ",
-	"AES1",
-	"L4 PER0",
-	"OCMRAM ",
-	"GPMC sERROR",
-	"SGX ",
-	"SL2 ",
-	"C2C ",
-	"PWR DISC CLK1",
-	"SHA1",
-	"AES2",
-	"L4 PER3",
-	"L4 PER1",
-	"L4 PER2",
+		"CORTEX M3" ,
+		"DSS ",
+		"GPMC ",
+		"ISS ",
+		"IVAHD ",
+		"AES1",
+		"L4 PER0",
+		"OCMRAM ",
+		"GPMC sERROR",
+		"SGX ",
+		"SL2 ",
+		"C2C ",
+		"PWR DISC CLK1",
+		"SHA1",
+		"AES2",
+		"L4 PER3",
+		"L4 PER1",
+		"L4 PER2",
 	},
 	{
-	"EMUSS",
+		"EMUSS",
 	},
 };
 
-u32 *l3_targ[L3_MODULES] = {
-	l3_targ_stderrlog_main_clk1,
-	l3_targ_stderrlog_main_clk2,
-	l3_targ_stderrlog_main_clk3,
+static u32 *l3_targ[L3_MODULES] = {
+	l3_targ_inst_clk1,
+	l3_targ_inst_clk2,
+	l3_targ_inst_clk3,
 };
 
 struct omap4_l3 {
-	struct device	*dev;
-	struct clk	*ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base */
-	void __iomem *l3_base[4];
+	void __iomem *l3_base[L3_MODULES];
 
-	int		debug_irq;
-	int		app_irq;
+	int debug_irq;
+	int app_irq;
 };
-
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_smx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_smx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_smx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_smx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1,26 @@
- /*
-  * OMAP3XXX L3 Interconnect Driver
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Felipe Balbi <balbi@ti.com>
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	Sricharan <r.sricharan@ti.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.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP3XXX L3 Interconnect Driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -135,7 +135,7 @@ static char *omap3_l3_initiator_string(u
 	}
 }
 
-/**
+/*
  * omap3_l3_block_irq - handles a register block's irq
  * @l3: struct omap3_l3 *
  * @base: register block base address
@@ -150,30 +150,29 @@ static char *omap3_l3_initiator_string(u
 static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
 					u64 error, int error_addr)
 {
-	u8                      code = omap3_l3_decode_error_code(error);
-	u8                      initid = omap3_l3_decode_initid(error);
-	u8                      multi = error & L3_ERROR_LOG_MULTI;
-	u32			address = omap3_l3_decode_addr(error_addr);
+	u8 code = omap3_l3_decode_error_code(error);
+	u8 initid = omap3_l3_decode_initid(error);
+	u8 multi = error & L3_ERROR_LOG_MULTI;
+	u32 address = omap3_l3_decode_addr(error_addr);
 
 	WARN(true, "%s seen by %s %s at address %x\n",
-				 omap3_l3_code_string(code),
-			  omap3_l3_initiator_string(initid),
-			     multi ? "Multiple Errors" : "",
-						   address);
+			omap3_l3_code_string(code),
+			omap3_l3_initiator_string(initid),
+			multi ? "Multiple Errors" : "", address);
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
 {
-	struct omap3_l3         *l3 = _l3;
-	u64                     status, clear;
-	u64                     error;
-	u64			error_addr;
-	u64			err_source = 0;
-	void			__iomem *base;
-	int			int_type;
-	irqreturn_t             ret = IRQ_NONE;
+	struct omap3_l3 *l3 = _l3;
+	u64 status, clear;
+	u64 error;
+	u64 error_addr;
+	u64 err_source = 0;
+	void __iomem *base;
+	int int_type;
+	irqreturn_t ret = IRQ_NONE;
 
 	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
 	if (!int_type) {
@@ -191,14 +190,12 @@ static irqreturn_t omap3_l3_app_irq(int
 	}
 
 	/* identify the error source */
-	for (err_source = 0; !(status & (1 << err_source)); err_source++)
-									;
+	err_source = __ffs(status);
 
-	base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
+	base = l3->rt + omap3_l3_bases[int_type][err_source];
 	error = omap3_l3_readll(base, L3_ERROR_LOG);
 	if (error) {
 		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
-
 		ret |= omap3_l3_block_irq(l3, error, error_addr);
 	}
 
@@ -215,9 +212,9 @@ static irqreturn_t omap3_l3_app_irq(int
 
 static int __init omap3_l3_probe(struct platform_device *pdev)
 {
-	struct omap3_l3         *l3;
-	struct resource         *res;
-	int                     ret;
+	struct omap3_l3 *l3;
+	struct resource *res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_smx.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_smx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_l3_smx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_l3_smx.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1,26 @@
- /*
-  * OMAP3XXX L3 Interconnect Driver header
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Felipe Balbi <balbi@ti.com>
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	sricharan <r.sricharan@ti.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.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP3XXX L3 Interconnect Driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 #ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 #define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 
@@ -40,7 +40,7 @@
 #define L3_SI_CONTROL			0x020
 #define L3_SI_FLAG_STATUS_0		0x510
 
-const u64 shift = 1;
+static const u64 shift = 1;
 
 #define L3_STATUS_0_MPUIA_BRST		(shift << 0)
 #define L3_STATUS_0_MPUIA_RSP		(shift << 1)
@@ -78,32 +78,32 @@ const u64 shift = 1;
 #define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
 #define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
 
-#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST         \
-					| L3_STATUS_0_MPUIA_RSP         \
-					| L3_STATUS_0_IVAIA_BRST        \
-					| L3_STATUS_0_IVAIA_RSP         \
-					| L3_STATUS_0_SGXIA_BRST        \
-					| L3_STATUS_0_SGXIA_RSP         \
-					| L3_STATUS_0_CAMIA_BRST        \
-					| L3_STATUS_0_CAMIA_RSP         \
-					| L3_STATUS_0_DISPIA_BRST       \
-					| L3_STATUS_0_DISPIA_RSP        \
-					| L3_STATUS_0_DMARDIA_BRST      \
-					| L3_STATUS_0_DMARDIA_RSP       \
-					| L3_STATUS_0_DMAWRIA_BRST      \
-					| L3_STATUS_0_DMAWRIA_RSP       \
-					| L3_STATUS_0_USBOTGIA_BRST     \
-					| L3_STATUS_0_USBOTGIA_RSP      \
-					| L3_STATUS_0_USBHOSTIA_BRST    \
-					| L3_STATUS_0_SMSTA_REQ         \
-					| L3_STATUS_0_GPMCTA_REQ        \
-					| L3_STATUS_0_OCMRAMTA_REQ      \
-					| L3_STATUS_0_OCMROMTA_REQ      \
-					| L3_STATUS_0_IVATA_REQ         \
-					| L3_STATUS_0_SGXTA_REQ         \
-					| L3_STATUS_0_L4CORETA_REQ      \
-					| L3_STATUS_0_L4PERTA_REQ       \
-					| L3_STATUS_0_L4EMUTA_REQ       \
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST		\
+					| L3_STATUS_0_MPUIA_RSP		\
+					| L3_STATUS_0_IVAIA_BRST	\
+					| L3_STATUS_0_IVAIA_RSP		\
+					| L3_STATUS_0_SGXIA_BRST	\
+					| L3_STATUS_0_SGXIA_RSP		\
+					| L3_STATUS_0_CAMIA_BRST	\
+					| L3_STATUS_0_CAMIA_RSP		\
+					| L3_STATUS_0_DISPIA_BRST	\
+					| L3_STATUS_0_DISPIA_RSP	\
+					| L3_STATUS_0_DMARDIA_BRST	\
+					| L3_STATUS_0_DMARDIA_RSP	\
+					| L3_STATUS_0_DMAWRIA_BRST	\
+					| L3_STATUS_0_DMAWRIA_RSP	\
+					| L3_STATUS_0_USBOTGIA_BRST	\
+					| L3_STATUS_0_USBOTGIA_RSP	\
+					| L3_STATUS_0_USBHOSTIA_BRST	\
+					| L3_STATUS_0_SMSTA_REQ		\
+					| L3_STATUS_0_GPMCTA_REQ	\
+					| L3_STATUS_0_OCMRAMTA_REQ	\
+					| L3_STATUS_0_OCMROMTA_REQ	\
+					| L3_STATUS_0_IVATA_REQ		\
+					| L3_STATUS_0_SGXTA_REQ		\
+					| L3_STATUS_0_L4CORETA_REQ	\
+					| L3_STATUS_0_L4PERTA_REQ	\
+					| L3_STATUS_0_L4EMUTA_REQ	\
 					| L3_STATUS_0_MAD2DTA_REQ)
 
 #define L3_SI_FLAG_STATUS_1		0x530
@@ -137,19 +137,19 @@ const u64 shift = 1;
 
 enum omap3_l3_initiator_id {
 	/* LCD has 1 ID */
-	OMAP_L3_LCD	        = 29,
+	OMAP_L3_LCD = 29,
 	/* SAD2D has 1 ID */
-	OMAP_L3_SAD2D		= 28,
+	OMAP_L3_SAD2D = 28,
 	/* MPU has 5 IDs */
-	OMAP_L3_IA_MPU_SS_1     = 27,
-	OMAP_L3_IA_MPU_SS_2     = 26,
-	OMAP_L3_IA_MPU_SS_3     = 25,
-	OMAP_L3_IA_MPU_SS_4     = 24,
-	OMAP_L3_IA_MPU_SS_5     = 23,
+	OMAP_L3_IA_MPU_SS_1 = 27,
+	OMAP_L3_IA_MPU_SS_2 = 26,
+	OMAP_L3_IA_MPU_SS_3 = 25,
+	OMAP_L3_IA_MPU_SS_4 = 24,
+	OMAP_L3_IA_MPU_SS_5 = 23,
 	/* IVA2.2 SS has 3 IDs*/
-	OMAP_L3_IA_IVA_SS_1     = 22,
-	OMAP_L3_IA_IVA_SS_2     = 21,
-	OMAP_L3_IA_IVA_SS_3     = 20,
+	OMAP_L3_IA_IVA_SS_1 = 22,
+	OMAP_L3_IA_IVA_SS_2 = 21,
+	OMAP_L3_IA_IVA_SS_3 = 20,
 	/* IVA 2.2 SS DMA has 6 IDS */
 	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
 	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
@@ -158,25 +158,25 @@ enum omap3_l3_initiator_id {
 	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
 	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
 	/* SGX has 1 ID */
-	OMAP_L3_IA_SGX		= 13,
+	OMAP_L3_IA_SGX = 13,
 	/* CAM has 3 ID */
-	OMAP_L3_IA_CAM_1	= 12,
-	OMAP_L3_IA_CAM_2	= 11,
-	OMAP_L3_IA_CAM_3	= 10,
+	OMAP_L3_IA_CAM_1 = 12,
+	OMAP_L3_IA_CAM_2 = 11,
+	OMAP_L3_IA_CAM_3 = 10,
 	/* DAP has 1 ID */
-	OMAP_L3_IA_DAP		= 9,
+	OMAP_L3_IA_DAP = 9,
 	/* SDMA WR has 2 IDs */
-	OMAP_L3_SDMA_WR_1	= 8,
-	OMAP_L3_SDMA_WR_2	= 7,
+	OMAP_L3_SDMA_WR_1 = 8,
+	OMAP_L3_SDMA_WR_2 = 7,
 	/* SDMA RD has 4 IDs */
-	OMAP_L3_SDMA_RD_1	= 6,
-	OMAP_L3_SDMA_RD_2	= 5,
-	OMAP_L3_SDMA_RD_3	= 4,
-	OMAP_L3_SDMA_RD_4	= 3,
+	OMAP_L3_SDMA_RD_1 = 6,
+	OMAP_L3_SDMA_RD_2 = 5,
+	OMAP_L3_SDMA_RD_3 = 4,
+	OMAP_L3_SDMA_RD_4 = 3,
 	/* HSUSB OTG has 1 ID */
-	OMAP_L3_USBOTG		= 2,
+	OMAP_L3_USBOTG = 2,
 	/* HSUSB HOST has 1 ID */
-	OMAP_L3_USBHOST		= 1,
+	OMAP_L3_USBHOST = 1,
 };
 
 enum omap3_l3_code {
@@ -192,21 +192,21 @@ enum omap3_l3_code {
 };
 
 struct omap3_l3 {
-	struct device   *dev;
-	struct clk      *ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base*/
-	void __iomem    *rt;
+	void __iomem *rt;
 
-	int             debug_irq;
-	int             app_irq;
+	int debug_irq;
+	int app_irq;
 
 	/* true when and inband functional error occurs */
-	unsigned        inband:1;
+	unsigned inband:1;
 };
 
 /* offsets for l3 agents in order with the Flag status register */
-unsigned int __iomem omap3_l3_app_bases[] = {
+static unsigned int omap3_l3_app_bases[] = {
 	/* MPU IA */
 	0x1400,
 	0x1400,
@@ -305,7 +305,7 @@ unsigned int __iomem omap3_l3_app_bases[
 	0,
 };
 
-unsigned int __iomem omap3_l3_debug_bases[] = {
+static unsigned int omap3_l3_debug_bases[] = {
 	/* MPU DATA IA */
 	0x1400,
 	/* RESERVED */
@@ -321,7 +321,7 @@ unsigned int __iomem omap3_l3_debug_base
 	/* REST RESERVED */
 };
 
-u32 *omap3_l3_bases[] = {
+static u32 *omap3_l3_bases[] = {
 	omap3_l3_app_bases,
 	omap3_l3_debug_bases,
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap-smp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap-smp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap-smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap-smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,19 +102,20 @@ void __init smp_init_cpus(void)
 {
 	unsigned int i, ncores;
 
-	/* Never released */
-	scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
+	/*
+	 * Currently we can't call ioremap here because
+	 * SoC detection won't work until after init_early.
+	 */
+	scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
 	BUG_ON(!scu_base);
 
 	ncores = scu_get_core_count(scu_base);
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "OMAP4: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_twl.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_twl.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/omap_twl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/omap_twl.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,11 @@
 
 #define OMAP4_SRI2C_SLAVE_ADDR		0x12
 #define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
+#define OMAP4_VDD_MPU_SR_CMD_REG	0x56
 #define OMAP4_VDD_IVA_SR_VOLT_REG	0x5B
+#define OMAP4_VDD_IVA_SR_CMD_REG	0x5C
 #define OMAP4_VDD_CORE_SR_VOLT_REG	0x61
+#define OMAP4_VDD_CORE_SR_CMD_REG	0x62
 
 #define OMAP4_VP_CONFIG_ERROROFFSET	0x00
 #define OMAP4_VP_VSTEPMIN_VSTEPMIN	0x01
@@ -95,6 +98,8 @@ static unsigned long twl6030_vsel_to_uv(
 		is_offset_valid = true;
 	}
 
+	if (!vsel)
+		return 0;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -106,9 +111,9 @@ static unsigned long twl6030_vsel_to_uv(
 		return 1350000;
 
 	if (smps_offset & 0x8)
-		return ((((vsel - 1) * 125) + 7000)) * 100;
+		return ((((vsel - 1) * 1266) + 70900)) * 10;
 	else
-		return ((((vsel - 1) * 125) + 6000)) * 100;
+		return ((((vsel - 1) * 1266) + 60770)) * 10;
 }
 
 static u8 twl6030_uv_to_vsel(unsigned long uv)
@@ -127,6 +132,8 @@ static u8 twl6030_uv_to_vsel(unsigned lo
 		is_offset_valid = true;
 	}
 
+	if (!uv)
+		return 0x00;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -134,16 +141,21 @@ static u8 twl6030_uv_to_vsel(unsigned lo
 	 * hardcoding only for 1.35 V which is used for 1GH OPP for
 	 * OMAP4430.
 	 */
-	if (uv == 1350000)
+	if (uv > twl6030_vsel_to_uv(0x39)) {
+		if (uv == 1350000)
+			return 0x3A;
+		pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
+			__func__, uv, twl6030_vsel_to_uv(0x39));
 		return 0x3A;
+	}
 
 	if (smps_offset & 0x8)
-		return DIV_ROUND_UP(uv - 700000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 709000, 12660) + 1;
 	else
-		return DIV_ROUND_UP(uv - 600000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 607700, 12660) + 1;
 }
 
-static struct omap_volt_pmic_info omap3_mpu_volt_info = {
+static struct omap_voltdm_pmic omap3_mpu_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt		= 1200000,
@@ -158,12 +170,13 @@ static struct omap_volt_pmic_info omap3_
 	.vp_vddmax		= OMAP3430_VP1_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap3_core_volt_info = {
+static struct omap_voltdm_pmic omap3_core_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt                = 1200000,
@@ -178,18 +191,19 @@ static struct omap_volt_pmic_info omap3_
 	.vp_vddmax		= OMAP3430_VP2_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_mpu_volt_info = {
+static struct omap_voltdm_pmic omap4_mpu_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1350000,
-	.onlp_volt		= 1350000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1375000,
+	.onlp_volt		= 1375000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -198,18 +212,20 @@ static struct omap_volt_pmic_info omap4_
 	.vp_vddmax		= OMAP4_VP_MPU_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_MPU_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_iva_volt_info = {
+static struct omap_voltdm_pmic omap4_iva_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1188000,
+	.onlp_volt		= 1188000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -218,18 +234,20 @@ static struct omap_volt_pmic_info omap4_
 	.vp_vddmax		= OMAP4_VP_IVA_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_IVA_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_core_volt_info = {
+static struct omap_voltdm_pmic omap4_core_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1200000,
+	.onlp_volt		= 1200000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -238,7 +256,8 @@ static struct omap_volt_pmic_info omap4_
 	.vp_vddmax		= OMAP4_VP_CORE_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_CORE_SR_CMD_REG,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -250,14 +269,14 @@ int __init omap4_twl_init(void)
 	if (!cpu_is_omap44xx())
 		return -ENODEV;
 
-	voltdm = omap_voltage_domain_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info);
+	voltdm = voltdm_lookup("mpu");
+	omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("iva");
-	omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info);
+	voltdm = voltdm_lookup("iva");
+	omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap4_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
 
 	return 0;
 }
@@ -270,10 +289,10 @@ int __init omap3_twl_init(void)
 		return -ENODEV;
 
 	if (cpu_is_omap3630()) {
-		omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
-		omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
-		omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
-		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
+		omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
+		omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
+		omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
+		omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
 	/*
@@ -288,11 +307,11 @@ int __init omap3_twl_init(void)
 	if (!twl_sr_enable_autoinit)
 		omap3_twl_set_sr_bit(true);
 
-	voltdm = omap_voltage_domain_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
+	voltdm = voltdm_lookup("mpu_iva");
+	omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/opp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/opp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/opp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/opp.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ int __init omap_init_opp_table(struct om
 				opp_def->hwmod_name, i);
 			return -EINVAL;
 		}
-		dev = &oh->od->pdev.dev;
+		dev = &oh->od->pdev->dev;
 
 		r = opp_add(dev, opp_def->freq, opp_def->u_volt);
 		if (r) {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm24xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm24xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm24xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,8 +53,6 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 
-static int omap2_pm_debug;
-
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
@@ -96,7 +94,6 @@ static int omap2_fclks_active(void)
 static void omap2_enter_full_retention(void)
 {
 	u32 l;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* There is 1 reference hold for all children of the oscillator
 	 * clock, the following will remove it. If no one else uses the
@@ -124,10 +121,6 @@ static void omap2_enter_full_retention(v
 
 	omap2_gpio_prepare_for_idle(0);
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	/* One last check for pending IRQs to avoid extra latency due
 	 * to sleeping unnecessarily. */
 	if (omap_irq_pending())
@@ -155,13 +148,6 @@ static void omap2_enter_full_retention(v
 		console_unlock();
 
 no_sleep:
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 	omap2_gpio_resume_after_idle();
 
 	clk_enable(osc_ck);
@@ -219,7 +205,6 @@ static int omap2_allow_mpu_retention(voi
 static void omap2_enter_mpu_retention(void)
 {
 	int only_idle = 0;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* Putting MPU into the WFI state while a transfer is active
 	 * seems to cause the I2C block to timeout. Why? Good question. */
@@ -246,19 +231,7 @@ static void omap2_enter_mpu_retention(vo
 		only_idle = 1;
 	}
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	omap2_sram_idle();
-
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 }
 
 static int omap2_can_sleep(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm34xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm34xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm34xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
 {
-	return (suspend_state != PM_SUSPEND_ON);
+	return (suspend_state != PM_SUSPEND_ON) && console_suspend_enabled;
 }
 #else
 static inline bool is_suspending(void)
@@ -99,31 +99,27 @@ static void omap3_enable_io_chain(void)
 {
 	int timeout = 0;
 
-	if (omap_rev() >= OMAP3430_REV_ES3_1) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				     PM_WKEN);
-		/* Do a readback to assure write has been done */
-		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKEN);
+	/* Do a readback to assure write has been done */
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 
-		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-			 OMAP3430_ST_IO_CHAIN_MASK)) {
-			timeout++;
-			if (timeout > 1000) {
-				printk(KERN_ERR "Wake up daisy chain "
-				       "activation failed.\n");
-				return;
-			}
-			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-					     WKUP_MOD, PM_WKEN);
+	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
+		 OMAP3430_ST_IO_CHAIN_MASK)) {
+		timeout++;
+		if (timeout > 1000) {
+			pr_err("Wake up daisy chain activation failed.\n");
+			return;
 		}
+		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+					   WKUP_MOD, PM_WKEN);
 	}
 }
 
 static void omap3_disable_io_chain(void)
 {
-	if (omap_rev() >= OMAP3430_REV_ES3_1)
-		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				       PM_WKEN);
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				     PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
@@ -363,7 +359,6 @@ void omap_sram_idle(void)
 		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
 		return;
 	}
-	pwrdm_pre_transition();
 
 	/* NEON control */
 	if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
@@ -376,7 +371,8 @@ void omap_sram_idle(void)
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-		omap3_enable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_enable_io_chain();
 	}
 
 	/* Block console output in case it is on one of the OMAP UARTs */
@@ -386,6 +382,8 @@ void omap_sram_idle(void)
 			if (!console_trylock())
 				goto console_still_active;
 
+	pwrdm_pre_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
@@ -409,13 +407,14 @@ void omap_sram_idle(void)
 	omap3_intc_prepare_idle();
 
 	/*
-	* On EMU/HS devices ROM code restores a SRDC value
-	* from scratchpad which has automatic self refresh on timeout
-	* of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
-	* Hence store/restore the SDRC_POWER register here.
-	*/
-	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-	    omap_type() != OMAP2_DEVICE_TYPE_GP &&
+	 * On EMU/HS devices ROM code restores a SRDC value
+	 * from scratchpad which has automatic self refresh on timeout
+	 * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
+	 * Hence store/restore the SDRC_POWER register here.
+	 */
+	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
@@ -432,8 +431,9 @@ void omap_sram_idle(void)
 		omap34xx_do_sram_idle(save_state);
 
 	/* Restore normal SDRC POWER settings */
-	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-	    omap_type() != OMAP2_DEVICE_TYPE_GP &&
+	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
@@ -455,6 +455,8 @@ void omap_sram_idle(void)
 	}
 	omap3_intc_resume_idle();
 
+	pwrdm_post_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
@@ -475,11 +477,10 @@ console_still_active:
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
-		omap3_disable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_disable_io_chain();
 	}
 
-	pwrdm_post_transition();
-
 	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
@@ -870,6 +871,9 @@ static int __init omap3_pm_init(void)
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
+	if (!omap3_has_io_chain_ctrl())
+		pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
+
 	pm_errata_configure();
 
 	/* XXX prcm_setup_regs needs to be before enabling hw
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/opp.h>
+#include <linux/export.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -23,57 +24,25 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
+#include "twl-common.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
-static struct device *mpu_dev;
-static struct device *iva_dev;
-static struct device *l3_dev;
-static struct device *dsp_dev;
-
-struct device *omap2_get_mpuss_device(void)
-{
-	WARN_ON_ONCE(!mpu_dev);
-	return mpu_dev;
-}
-
-struct device *omap2_get_iva_device(void)
-{
-	WARN_ON_ONCE(!iva_dev);
-	return iva_dev;
-}
-
-struct device *omap2_get_l3_device(void)
-{
-	WARN_ON_ONCE(!l3_dev);
-	return l3_dev;
-}
-
-struct device *omap4_get_dsp_device(void)
-{
-	WARN_ON_ONCE(!dsp_dev);
-	return dsp_dev;
-}
-EXPORT_SYMBOL(omap4_get_dsp_device);
-
-/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
-static int _init_omap_device(char *name, struct device **new_dev)
+static int _init_omap_device(char *name)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup(name);
 	if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	od = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
-	if (WARN(IS_ERR(od), "%s: could not build omap_device for %s\n",
+	pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+	if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	*new_dev = &od->pdev.dev;
-
 	return 0;
 }
 
@@ -82,16 +51,16 @@ static int _init_omap_device(char *name,
  */
 static void omap2_init_processor_devices(void)
 {
-	_init_omap_device("mpu", &mpu_dev);
+	_init_omap_device("mpu");
 	if (omap3_has_iva())
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("iva");
 
 	if (cpu_is_omap44xx()) {
-		_init_omap_device("l3_main_1", &l3_dev);
-		_init_omap_device("dsp", &dsp_dev);
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("l3_main_1");
+		_init_omap_device("dsp");
+		_init_omap_device("iva");
 	} else {
-		_init_omap_device("l3_main", &l3_dev);
+		_init_omap_device("l3_main");
 	}
 }
 
@@ -136,8 +105,8 @@ int omap_set_pwrdm_state(struct powerdom
 
 	ret = pwrdm_set_next_pwrst(pwrdm, state);
 	if (ret) {
-		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-		       pwrdm->name);
+		pr_err("%s: unable to set state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
 		goto err;
 	}
 
@@ -161,37 +130,44 @@ err:
 }
 
 /*
- * This API is to be called during init to put the various voltage
+ * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
  * the clock associated with the voltage domain, finds out the correct
- * opp entry and puts the voltage domain to the voltage specifies
+ * opp entry and sets the voltage domain to the voltage specified
  * in the opp entry
  */
 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
-						struct device *dev)
+					 const char *oh_name)
 {
 	struct voltagedomain *voltdm;
 	struct clk *clk;
 	struct opp *opp;
 	unsigned long freq, bootup_volt;
+	struct device *dev;
 
-	if (!vdd_name || !clk_name || !dev) {
-		printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+	if (!vdd_name || !clk_name || !oh_name) {
+		pr_err("%s: invalid parameters\n", __func__);
 		goto exit;
 	}
 
-	voltdm = omap_voltage_domain_lookup(vdd_name);
+	dev = omap_device_get_by_hwmod_name(oh_name);
+	if (IS_ERR(dev)) {
+		pr_err("%s: Unable to get dev pointer for hwmod %s\n",
+			__func__, oh_name);
+		goto exit;
+	}
+
+	voltdm = voltdm_lookup(vdd_name);
 	if (IS_ERR(voltdm)) {
-		printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
+		pr_err("%s: unable to get vdd pointer for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	clk =  clk_get(NULL, clk_name);
 	if (IS_ERR(clk)) {
-		printk(KERN_ERR "%s: unable to get clk %s\n",
-			__func__, clk_name);
+		pr_err("%s: unable to get clk %s\n", __func__, clk_name);
 		goto exit;
 	}
 
@@ -200,24 +176,23 @@ static int __init omap2_set_init_voltage
 
 	opp = opp_find_freq_ceil(dev, &freq);
 	if (IS_ERR(opp)) {
-		printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
+		pr_err("%s: unable to find boot up OPP for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	bootup_volt = opp_get_voltage(opp);
 	if (!bootup_volt) {
-		printk(KERN_ERR "%s: unable to find voltage corresponding"
+		pr_err("%s: unable to find voltage corresponding "
 			"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
 		goto exit;
 	}
 
-	omap_voltage_scale_vdd(voltdm, bootup_volt);
+	voltdm_scale(voltdm, bootup_volt);
 	return 0;
 
 exit:
-	printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
-		__func__, vdd_name);
+	pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
 	return -EINVAL;
 }
 
@@ -226,8 +201,8 @@ static void __init omap3_init_voltages(v
 	if (!cpu_is_omap34xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_ick", "l3_main");
 }
 
 static void __init omap4_init_voltages(void)
@@ -235,14 +210,15 @@ static void __init omap4_init_voltages(v
 	if (!cpu_is_omap44xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_div_ck", l3_dev);
-	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
+	omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
+	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
 }
 
 static int __init omap2_common_pm_init(void)
 {
-	omap2_init_processor_devices();
+	if (!of_have_populated_dt())
+		omap2_init_processor_devices();
 	omap_pm_if_init();
 
 	return 0;
@@ -251,11 +227,8 @@ postcore_initcall(omap2_common_pm_init);
 
 static int __init omap2_common_pm_late_init(void)
 {
-	/* Init the OMAP TWL parameters */
-	omap3_twl_init();
-	omap4_twl_init();
-
 	/* Init the voltage layer */
+	omap_pmic_late_init();
 	omap_voltage_late_init();
 
 	/* Initialize the voltages */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2 and OMAP3 powerdomain control
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP powerdomain control
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -77,13 +77,11 @@ static struct powerdomain *_pwrdm_lookup
 static int _pwrdm_register(struct powerdomain *pwrdm)
 {
 	int i;
+	struct voltagedomain *voltdm;
 
 	if (!pwrdm || !pwrdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(pwrdm->omap_chip))
-		return -EINVAL;
-
 	if (cpu_is_omap44xx() &&
 	    pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
 		pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
@@ -94,6 +92,16 @@ static int _pwrdm_register(struct powerd
 	if (_pwrdm_lookup(pwrdm->name))
 		return -EEXIST;
 
+	voltdm = voltdm_lookup(pwrdm->voltdm.name);
+	if (!voltdm) {
+		pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
+		       pwrdm->name, pwrdm->voltdm.name);
+		return -EINVAL;
+	}
+	pwrdm->voltdm.ptr = voltdm;
+	INIT_LIST_HEAD(&pwrdm->voltdm_node);
+	voltdm_add_pwrdm(voltdm, pwrdm);
+
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
@@ -194,36 +202,76 @@ static int _pwrdm_post_transition_cb(str
 /* Public functions */
 
 /**
- * pwrdm_init - set up the powerdomain layer
- * @pwrdms: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specific implementations
+ * pwrdm_register_platform_funcs - register powerdomain implementation fns
+ * @po: func pointers for arch specific implementations
  *
- * Loop through the array of powerdomains @pwrdms, registering all
- * that are available on the current CPU.  Also, program all
- * powerdomain target state as ON; this is to prevent domains from
- * hitting low power states (if bootloader has target states set to
- * something other than ON) and potentially even losing context while
- * PM is not fully initialized.  The PM late init code can then program
- * the desired target state for all the power domains.  No return
- * value.
+ * Register the list of function pointers used to implement the
+ * powerdomain functions on different OMAP SoCs.  Should be called
+ * before any other pwrdm_register*() function.  Returns -EINVAL if
+ * @po is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
  */
-void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs)
+int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
+{
+	if (!po)
+		return -EINVAL;
+
+	if (arch_pwrdm)
+		return -EEXIST;
+
+	arch_pwrdm = po;
+
+	return 0;
+}
+
+/**
+ * pwrdm_register_pwrdms - register SoC powerdomains
+ * @ps: pointer to an array of struct powerdomain to register
+ *
+ * Register the powerdomains available on a particular OMAP SoC.  Must
+ * be called after pwrdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
+ * null; or 0 upon success.
+ */
+int pwrdm_register_pwrdms(struct powerdomain **ps)
 {
 	struct powerdomain **p = NULL;
-	struct powerdomain *temp_p;
 
-	if (!custom_funcs)
-		WARN(1, "powerdomain: No custom pwrdm functions registered\n");
-	else
-		arch_pwrdm = custom_funcs;
+	if (!arch_pwrdm)
+		return -EEXIST;
 
-	if (pwrdms) {
-		for (p = pwrdms; *p; p++)
-			_pwrdm_register(*p);
-	}
+	if (!ps)
+		return -EINVAL;
+
+	for (p = ps; *p; p++)
+		_pwrdm_register(*p);
+
+	return 0;
+}
+
+/**
+ * pwrdm_complete_init - set up the powerdomain layer
+ *
+ * Do whatever is necessary to initialize registered powerdomains and
+ * powerdomain code.  Currently, this programs the next power state
+ * for each powerdomain to ON.  This prevents powerdomains from
+ * unexpectedly losing context or entering high wakeup latency modes
+ * with non-power-management-enabled kernels.  Must be called after
+ * pwrdm_register_pwrdms().  Returns -EACCES if called before
+ * pwrdm_register_pwrdms(), or 0 upon success.
+ */
+int pwrdm_complete_init(void)
+{
+	struct powerdomain *temp_p;
+
+	if (list_empty(&pwrdm_list))
+		return -EACCES;
 
 	list_for_each_entry(temp_p, &pwrdm_list, node)
 		pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+
+	return 0;
 }
 
 /**
@@ -390,6 +438,18 @@ int pwrdm_for_each_clkdm(struct powerdom
 }
 
 /**
+ * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
+ * @pwrdm: struct powerdomain *
+ *
+ * Return a pointer to the struct voltageomain that the specified powerdomain
+ * @pwrdm exists in.
+ */
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
+{
+	return pwrdm->voltdm.ptr;
+}
+
+/**
  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  * @pwrdm: struct powerdomain *
  *
@@ -942,16 +1002,16 @@ int pwrdm_post_transition(void)
  * @pwrdm: struct powerdomain * to wait for
  *
  * Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter.  Returns 0
+ * logic off counter and the per-bank memory off counter.  Returns negative
  * (and WARNs) upon error, otherwise, returns the context loss count.
  */
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 {
 	int i, count;
 
 	if (!pwrdm) {
 		WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
-		return 0;
+		return -ENODEV;
 	}
 
 	count = pwrdm->state_counter[PWRDM_POWER_OFF];
@@ -960,7 +1020,13 @@ u32 pwrdm_get_context_loss_count(struct
 	for (i = 0; i < pwrdm->banks; i++)
 		count += pwrdm->ret_mem_off_counter[i];
 
-	pr_debug("powerdomain: %s: context loss count = %u\n",
+	/*
+	 * Context loss count has to be a non-negative value. Clear the sign
+	 * bit to get a value range from 0 to INT_MAX.
+	 */
+	count &= INT_MAX;
+
+	pr_debug("powerdomain: %s: context loss count = %d\n",
 		 pwrdm->name, count);
 
 	return count;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain-common.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain-common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,8 @@
 /*
- *  linux/arch/arm/mach-omap2/powerdomain-common.c
- *  Contains common powerdomain framework functions
+ * Common powerdomain framework functions
  *
- *  Copyright (C) 2010 Texas Instruments, Inc.
- *  Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
  *
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomain.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomain.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 
 #include <plat/cpu.h>
 
+#include "voltage.h"
+
 /* Powerdomain basic power states */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
@@ -78,7 +80,7 @@ struct powerdomain;
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
- * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @voltdm: voltagedomain containing this powerdomain
  * @prcm_offs: the address offset from CM_BASE/PRM_BASE
  * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
  * @pwrsts: Possible powerdomain power states
@@ -89,6 +91,7 @@ struct powerdomain;
  * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
  * @pwrdm_clkdms: Clockdomains in this powerdomain
  * @node: list_head linking all powerdomains
+ * @voltdm_node: list_head linking all powerdomains in a voltagedomain
  * @state:
  * @state_counter:
  * @timer:
@@ -98,7 +101,10 @@ struct powerdomain;
  */
 struct powerdomain {
 	const char *name;
-	const struct omap_chip_id omap_chip;
+	union {
+		const char *name;
+		struct voltagedomain *ptr;
+	} voltdm;
 	const s16 prcm_offs;
 	const u8 pwrsts;
 	const u8 pwrsts_logic_ret;
@@ -109,6 +115,7 @@ struct powerdomain {
 	const u8 prcm_partition;
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 	struct list_head node;
+	struct list_head voltdm_node;
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
@@ -162,7 +169,9 @@ struct pwrdm_ops {
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
+int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
+int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
+int pwrdm_complete_init(void);
 
 struct powerdomain *pwrdm_lookup(const char *name);
 
@@ -176,6 +185,7 @@ int pwrdm_del_clkdm(struct powerdomain *
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
 
 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
@@ -207,10 +217,11 @@ int pwrdm_clkdm_state_switch(struct cloc
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-extern void omap2xxx_powerdomains_init(void);
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
 extern void omap44xx_powerdomains_init(void);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3 common powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -12,20 +12,6 @@
  */
 
 /*
- * To Do List
- * -> Move the Sleep/Wakeup dependencies from Power Domain framework to
- *    Clock Domain Framework
- */
-
-/*
- * This file contains all of the powerdomains that have some element
- * of software control for the OMAP24xx and OMAP34xx chips.
- *
- * This is not an exhaustive listing of powerdomains on the chips; only
- * powerdomains that can be controlled in software.
- */
-
-/*
  * The names for the DSP/IVA2 powerdomains are confusing.
  *
  * Most OMAP chips have an on-board DSP.
@@ -59,8 +45,6 @@
 struct powerdomain gfx_omap2_pwrdm = {
 	.name		  = "gfx_pwrdm",
 	.prcm_offs	  = GFX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -70,11 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 	.pwrsts		= PWRSTS_ON,
+	.voltdm         = { .name = "wakeup" },
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2XXX powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -28,7 +28,6 @@
 static struct powerdomain dsp_pwrdm = {
 	.name		  = "dsp_pwrdm",
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -38,12 +37,12 @@ static struct powerdomain dsp_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain mpu_24xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -53,12 +52,12 @@ static struct powerdomain mpu_24xx_pwrdm
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_24xx_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.banks		  = 3,
 	.pwrsts_mem_ret	  = {
@@ -71,6 +70,7 @@ static struct powerdomain core_24xx_pwrd
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 
@@ -78,14 +78,11 @@ static struct powerdomain core_24xx_pwrd
  * 2430-specific powerdomains
  */
 
-#ifdef CONFIG_SOC_OMAP2430
-
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
 static struct powerdomain mdm_pwrdm = {
 	.name		  = "mdm_pwrdm",
 	.prcm_offs	  = OMAP2430_MDM_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -95,29 +92,44 @@ static struct powerdomain mdm_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
-#endif     /* CONFIG_SOC_OMAP2430 */
-
-/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
+/*
+ *
+ */
 
+static struct powerdomain *powerdomains_omap24xx[] __initdata = {
 	&wkup_omap2_pwrdm,
 	&gfx_omap2_pwrdm,
-
-#ifdef CONFIG_ARCH_OMAP2
 	&dsp_pwrdm,
 	&mpu_24xx_pwrdm,
 	&core_24xx_pwrdm,
-#endif
+	NULL
+};
 
-#ifdef CONFIG_SOC_OMAP2430
+static struct powerdomain *powerdomains_omap2430[] __initdata = {
 	&mdm_pwrdm,
-#endif
 	NULL
 };
 
-void __init omap2xxx_powerdomains_init(void)
+void __init omap242x_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap2xxx, &omap2_pwrdm_operations);
+	if (!cpu_is_omap2420())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_complete_init();
+}
+
+void __init omap243x_powerdomains_init(void)
+{
+	if (!cpu_is_omap2430())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_register_pwrdms(powerdomains_omap2430);
+	pwrdm_complete_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP3 powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <plat/cpu.h>
+
 #include "powerdomain.h"
 #include "powerdomains2xxx_3xxx_data.h"
 
@@ -27,8 +29,6 @@
  * 34XX-specific powerdomains, dependencies
  */
 
-#ifdef CONFIG_ARCH_OMAP3
-
 /*
  * Powerdomains
  */
@@ -36,7 +36,6 @@
 static struct powerdomain iva2_pwrdm = {
 	.name		  = "iva2_pwrdm",
 	.prcm_offs	  = OMAP3430_IVA2_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 4,
@@ -52,12 +51,12 @@ static struct powerdomain iva2_pwrdm = {
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.flags		  = PWRDM_HAS_MPU_QUIRK,
@@ -68,6 +67,7 @@ static struct powerdomain mpu_3xxx_pwrdm
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 /*
@@ -83,10 +83,6 @@ static struct powerdomain mpu_3xxx_pwrdm
 static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-					   CHIP_IS_OMAP3430ES2 |
-					   CHIP_IS_OMAP3430ES3_0 |
-					   CHIP_IS_OMAP3630ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -98,13 +94,12 @@ static struct powerdomain core_3xxx_pre_
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1 |
-					  CHIP_GE_OMAP3630ES1_1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	/*
@@ -121,11 +116,11 @@ static struct powerdomain core_3xxx_es3_
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dss_pwrdm = {
 	.name		  = "dss_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -136,6 +131,7 @@ static struct powerdomain dss_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 /*
@@ -146,7 +142,6 @@ static struct powerdomain dss_pwrdm = {
 static struct powerdomain sgx_pwrdm = {
 	.name		  = "sgx_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_SGX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -157,11 +152,11 @@ static struct powerdomain sgx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain cam_pwrdm = {
 	.name		  = "cam_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -172,12 +167,12 @@ static struct powerdomain cam_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain per_pwrdm = {
 	.name		  = "per_pwrdm",
 	.prcm_offs	  = OMAP3430_PER_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -187,26 +182,26 @@ static struct powerdomain per_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain emu_pwrdm = {
 	.name		= "emu_pwrdm",
 	.prcm_offs	= OMAP3430_EMU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain neon_pwrdm = {
 	.name		  = "neon_pwrdm",
 	.prcm_offs	  = OMAP3430_NEON_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain usbhost_pwrdm = {
 	.name		  = "usbhost_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
@@ -223,65 +218,103 @@ static struct powerdomain usbhost_pwrdm
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll1_pwrdm = {
 	.name		= "dpll1_pwrdm",
 	.prcm_offs	= MPU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll2_pwrdm = {
 	.name		= "dpll2_pwrdm",
 	.prcm_offs	= OMAP3430_IVA2_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll3_pwrdm = {
 	.name		= "dpll3_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll4_pwrdm = {
 	.name		= "dpll4_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll5_pwrdm = {
 	.name		= "dpll5_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+	.voltdm           = { .name = "core" },
 };
 
 /* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap3xxx[] __initdata = {
-
+static struct powerdomain *powerdomains_omap3430_common[] __initdata = {
 	&wkup_omap2_pwrdm,
-	&gfx_omap2_pwrdm,
 	&iva2_pwrdm,
 	&mpu_3xxx_pwrdm,
 	&neon_pwrdm,
-	&core_3xxx_pre_es3_1_pwrdm,
-	&core_3xxx_es3_1_pwrdm,
 	&cam_pwrdm,
 	&dss_pwrdm,
 	&per_pwrdm,
 	&emu_pwrdm,
-	&sgx_pwrdm,
-	&usbhost_pwrdm,
 	&dpll1_pwrdm,
 	&dpll2_pwrdm,
 	&dpll3_pwrdm,
 	&dpll4_pwrdm,
+	NULL
+};
+
+static struct powerdomain *powerdomains_omap3430es1[] __initdata = {
+	&gfx_omap2_pwrdm,
+	&core_3xxx_pre_es3_1_pwrdm,
+	NULL
+};
+
+/* also includes 3630ES1.0 */
+static struct powerdomain *powerdomains_omap3430es2_es3_0[] __initdata = {
+	&core_3xxx_pre_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
 	&dpll5_pwrdm,
-#endif
 	NULL
 };
 
+/* also includes 3630ES1.1+ */
+static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
+	&core_3xxx_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
+	&dpll5_pwrdm,
+	NULL
+};
 
 void __init omap3xxx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap3xxx, &omap3_pwrdm_operations);
+	unsigned int rev;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+	rev = omap_rev();
+
+	if (rev == OMAP3430_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es1);
+	else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		 rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+	else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
+		 rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1 ||
+		 rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
+		pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+	else
+		WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+
+	pwrdm_complete_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,9 +33,9 @@
 /* core_44xx_pwrdm: CORE power domain */
 static struct powerdomain core_44xx_pwrdm = {
 	.name		  = "core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CORE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
@@ -59,9 +59,9 @@ static struct powerdomain core_44xx_pwrd
 /* gfx_44xx_pwrdm: 3D accelerator power domain */
 static struct powerdomain gfx_44xx_pwrdm = {
 	.name		  = "gfx_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_GFX_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -76,9 +76,9 @@ static struct powerdomain gfx_44xx_pwrdm
 /* abe_44xx_pwrdm: Audio back end power domain */
 static struct powerdomain abe_44xx_pwrdm = {
 	.name		  = "abe_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_ABE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
@@ -96,9 +96,9 @@ static struct powerdomain abe_44xx_pwrdm
 /* dss_44xx_pwrdm: Display subsystem power domain */
 static struct powerdomain dss_44xx_pwrdm = {
 	.name		  = "dss_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_DSS_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
@@ -114,9 +114,9 @@ static struct powerdomain dss_44xx_pwrdm
 /* tesla_44xx_pwrdm: Tesla processor power domain */
 static struct powerdomain tesla_44xx_pwrdm = {
 	.name		  = "tesla_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_TESLA_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -136,9 +136,9 @@ static struct powerdomain tesla_44xx_pwr
 /* wkup_44xx_pwrdm: Wake-up power domain */
 static struct powerdomain wkup_44xx_pwrdm = {
 	.name		  = "wkup_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_WKUP_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -152,9 +152,9 @@ static struct powerdomain wkup_44xx_pwrd
 /* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
 static struct powerdomain cpu0_44xx_pwrdm = {
 	.name		  = "cpu0_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -169,9 +169,9 @@ static struct powerdomain cpu0_44xx_pwrd
 /* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
 static struct powerdomain cpu1_44xx_pwrdm = {
 	.name		  = "cpu1_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -186,9 +186,9 @@ static struct powerdomain cpu1_44xx_pwrd
 /* emu_44xx_pwrdm: Emulation power domain */
 static struct powerdomain emu_44xx_pwrdm = {
 	.name		  = "emu_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_EMU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -202,9 +202,9 @@ static struct powerdomain emu_44xx_pwrdm
 /* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
 static struct powerdomain mpu_44xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRM_MPU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -223,9 +223,9 @@ static struct powerdomain mpu_44xx_pwrdm
 /* ivahd_44xx_pwrdm: IVA-HD power domain */
 static struct powerdomain ivahd_44xx_pwrdm = {
 	.name		  = "ivahd_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_IVAHD_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
@@ -247,9 +247,9 @@ static struct powerdomain ivahd_44xx_pwr
 /* cam_44xx_pwrdm: Camera subsystem power domain */
 static struct powerdomain cam_44xx_pwrdm = {
 	.name		  = "cam_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CAM_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -264,9 +264,9 @@ static struct powerdomain cam_44xx_pwrdm
 /* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
 static struct powerdomain l3init_44xx_pwrdm = {
 	.name		  = "l3init_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L3INIT_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -282,9 +282,9 @@ static struct powerdomain l3init_44xx_pw
 /* l4per_44xx_pwrdm: Target peripherals power domain */
 static struct powerdomain l4per_44xx_pwrdm = {
 	.name		  = "l4per_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L4PER_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -305,18 +305,18 @@ static struct powerdomain l4per_44xx_pwr
  */
 static struct powerdomain always_on_core_44xx_pwrdm = {
 	.name		  = "always_on_core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_ALWAYS_ON_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 };
 
 /* cefuse_44xx_pwrdm: Customer efuse controller power domain */
 static struct powerdomain cefuse_44xx_pwrdm = {
 	.name		  = "cefuse_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CEFUSE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -352,5 +352,7 @@ static struct powerdomain *powerdomains_
 
 void __init omap44xx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap44xx, &omap4_pwrdm_operations);
+	pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap44xx);
+	pwrdm_complete_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/prcm.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/prcm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/prcm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/prcm.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <mach/system.h>
 #include <plat/common.h>
@@ -151,17 +152,10 @@ int omap2_cm_wait_idlest(void __iomem *r
 
 void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->prm) {
-		prm_base = ioremap(omap2_globals->prm, SZ_8K);
-		WARN_ON(!prm_base);
-	}
-	if (omap2_globals->cm) {
-		cm_base = ioremap(omap2_globals->cm, SZ_8K);
-		WARN_ON(!cm_base);
-	}
-	if (omap2_globals->cm2) {
-		cm2_base = ioremap(omap2_globals->cm2, SZ_8K);
-		WARN_ON(!cm2_base);
-	}
+	if (omap2_globals->prm)
+		prm_base = omap2_globals->prm;
+	if (omap2_globals->cm)
+		cm_base = omap2_globals->cm;
+	if (omap2_globals->cm2)
+		cm2_base = omap2_globals->cm2;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
+
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
@@ -156,3 +158,57 @@ int omap2_prm_deassert_hardreset(s16 prm
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap3_vp - OMAP3 VP register access description.
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap3_vp {
+	u32 tranxdone_status;
+};
+
+static struct omap3_vp omap3_vp[] = {
+	[OMAP3_VP_VDD_MPU_ID] = {
+		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	},
+	[OMAP3_VP_VDD_CORE_ID] = {
+		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+	},
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+
+	omap2_prm_write_mod_reg(vp->tranxdone_status,
+				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap3_prm_vcvp_read(u8 offset)
+{
+	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+}
+
+void omap3_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+}
+
+u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h	2012-01-04 18:55:44.000000000 -0500
@@ -303,7 +303,19 @@ extern int omap2_prm_is_hardreset_assert
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
 extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 vp_id);
+void omap3_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP3 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap3_prm_vcvp_read(u8 offset);
+extern void omap3_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 #endif	/* CONFIG_ARCH_OMAP4 */
+
 #endif
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm44xx.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm44xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,11 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
 
 /* PRM low-level functions */
 
@@ -50,3 +53,71 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask
 
 	return v;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap4_vp - OMAP4 VP register access description.
+ * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap4_vp {
+	u32 irqstatus_mpu;
+	u32 tranxdone_status;
+};
+
+static struct omap4_vp omap4_vp[] = {
+	[OMAP4_VP_VDD_MPU_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+		.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_IVA_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_CORE_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+	},
+};
+
+u32 omap4_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+						OMAP4430_PRM_OCP_SOCKET_INST,
+						vp->irqstatus_mpu);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap4_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+
+	omap4_prminst_write_inst_reg(vp->tranxdone_status,
+				     OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_OCP_SOCKET_INST,
+				     vp->irqstatus_mpu);
+};
+
+u32 omap4_prm_vcvp_read(u8 offset)
+{
+	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+					   OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+void omap4_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap4_prminst_rmw_inst_reg_bits(mask, bits,
+					       OMAP4430_PRM_PARTITION,
+					       OMAP4430_PRM_DEVICE_INST,
+					       offset);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm44xx.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm44xx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/prm44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/prm44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -751,6 +751,18 @@ extern u32 omap4_prm_read_inst_reg(s16 i
 extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
 
+/* OMAP4-specific VP functions */
+u32 omap4_prm_vp_check_txdone(u8 vp_id);
+void omap4_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP4 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap4_prm_vcvp_read(u8 offset);
+extern void omap4_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
+
 # endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/sdrc.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/sdrc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/sdrc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/sdrc.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,15 +117,10 @@ int omap2_sdrc_get_params(unsigned long
 
 void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->sdrc) {
-		omap2_sdrc_base = ioremap(omap2_globals->sdrc, SZ_64K);
-		WARN_ON(!omap2_sdrc_base);
-	}
-	if (omap2_globals->sms) {
-		omap2_sms_base = ioremap(omap2_globals->sms, SZ_64K);
-		WARN_ON(!omap2_sms_base);
-	}
+	if (omap2_globals->sdrc)
+		omap2_sdrc_base = omap2_globals->sdrc;
+	if (omap2_globals->sms)
+		omap2_sms_base = omap2_globals->sms;
 }
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/serial.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/serial.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,28 +107,6 @@ struct omap_uart_state {
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-static int uart_idle_hwmod(struct omap_device *od)
-{
-	omap_hwmod_idle(od->hwmods[0]);
-
-	return 0;
-}
-
-static int uart_enable_hwmod(struct omap_device *od)
-{
-	omap_hwmod_enable(od->hwmods[0]);
-
-	return 0;
-}
-
-static struct omap_device_pm_latency omap_uart_latency[] = {
-	{
-		.deactivate_func = uart_idle_hwmod,
-		.activate_func	 = uart_enable_hwmod,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline unsigned int __serial_read_reg(struct uart_port *up,
 					     int offset)
 {
@@ -711,7 +689,7 @@ void __init omap_serial_init_port(struct
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	void *pdata = NULL;
 	u32 pdata_size = 0;
 	char *name;
@@ -799,20 +777,19 @@ void __init omap_serial_init_port(struct
 	if (WARN_ON(!oh))
 		return;
 
-	od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
-	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+				 NULL, 0, false);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
 	uart->irq = oh->mpu_irqs[0].irq;
 	uart->regshift = 2;
 	uart->mapbase = oh->slaves[0]->addr->pa_start;
 	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = &od->pdev;
+	uart->pdev = pdev;
 
 	oh->dev_attr = uart;
 
@@ -846,8 +823,8 @@ void __init omap_serial_init_port(struct
 
 	if ((cpu_is_omap34xx() && uart->padconf) ||
 	    (uart->wk_en && uart->wk_mask)) {
-		device_init_wakeup(&od->pdev.dev, true);
-		DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
+		device_init_wakeup(&pdev->dev, true);
+		DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/smartreflex.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/smartreflex.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/smartreflex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/smartreflex.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -62,6 +63,7 @@ static LIST_HEAD(sr_list);
 
 static struct omap_sr_class_data *sr_class;
 static struct omap_sr_pmic_data *sr_pmic_data;
+static struct dentry		*sr_dbg_dir;
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
 {
@@ -137,7 +139,7 @@ static irqreturn_t sr_interrupt(int irq,
 		sr_write_reg(sr_info, ERRCONFIG_V1, status);
 	} else if (sr_info->ip_type == SR_TYPE_V2) {
 		/* Read the status bits */
-		sr_read_reg(sr_info, IRQSTATUS);
+		status = sr_read_reg(sr_info, IRQSTATUS);
 
 		/* Clear them by writing back */
 		sr_write_reg(sr_info, IRQSTATUS, status);
@@ -247,7 +249,7 @@ static void sr_stop_vddautocomp(struct o
  * driver register and sr device intializtion API's. Only one call
  * will ultimately succeed.
  *
- * Currently this function registers interrrupt handler for a particular SR
+ * Currently this function registers interrupt handler for a particular SR
  * if smartreflex class driver is already registered and has
  * requested for interrupts and the SR interrupt line in present.
  */
@@ -826,9 +828,10 @@ static int __init omap_sr_probe(struct p
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *nvalue_dir;
+	struct dentry *nvalue_dir;
 	struct omap_volt_data *volt_data;
 	int i, ret = 0;
+	char *name;
 
 	if (!sr_info) {
 		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -899,18 +902,25 @@ static int __init omap_sr_probe(struct p
 	}
 
 	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+	if (!sr_dbg_dir) {
+		sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
+		if (!sr_dbg_dir) {
+			ret = PTR_ERR(sr_dbg_dir);
+			pr_err("%s:sr debugfs dir creation failed(%d)\n",
+				__func__, ret);
+			goto err_iounmap;
+		}
+	}
 
-	/*
-	 * If the voltage domain debugfs directory is not created, do
-	 * not try to create rest of the debugfs entries.
-	 */
-	vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
-	if (!vdd_dbg_dir) {
-		ret = -EINVAL;
+	name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+	if (!name) {
+		dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
+			__func__);
+		ret = -ENOMEM;
 		goto err_iounmap;
 	}
-
-	sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+	kfree(name);
 	if (IS_ERR(sr_info->dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/smartreflex-class3.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/smartreflex-class3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/smartreflex-class3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/smartreflex-class3.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 static int sr_class3_enable(struct voltagedomain *voltdm)
 {
-	unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+	unsigned long volt = voltdm_get_voltage(voltdm);
 
 	if (!volt) {
 		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
@@ -32,7 +32,7 @@ static int sr_class3_disable(struct volt
 	omap_vp_disable(voltdm);
 	sr_disable(voltdm);
 	if (is_volt_reset)
-		omap_voltage_reset(voltdm);
+		voltdm_reset(voltdm);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/sr_device.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/sr_device.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/sr_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/sr_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,14 +31,6 @@
 
 static bool sr_enable_on_init;
 
-static struct omap_device_pm_latency omap_sr_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
-	},
-};
-
 /* Read EFUSE values from control registers for OMAP3430 */
 static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
 				struct omap_sr_data *sr_data)
@@ -80,7 +72,7 @@ static void __init sr_set_nvalues(struct
 static int sr_dev_init(struct omap_hwmod *oh, void *user)
 {
 	struct omap_sr_data *sr_data;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_volt_data *volt_data;
 	char *name = "smartreflex";
 	static int i;
@@ -102,7 +94,7 @@ static int sr_dev_init(struct omap_hwmod
 	sr_data->senn_mod = 0x1;
 	sr_data->senp_mod = 0x1;
 
-	sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name);
+	sr_data->voltdm = voltdm_lookup(oh->vdd_name);
 	if (IS_ERR(sr_data->voltdm)) {
 		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
 			__func__, oh->vdd_name);
@@ -120,10 +112,9 @@ static int sr_dev_init(struct omap_hwmod
 
 	sr_data->enable_on_init = sr_enable_on_init;
 
-	od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
-			       omap_sr_latency,
-			       ARRAY_SIZE(omap_sr_latency), 0);
-	if (IS_ERR(od))
+	pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+				 NULL, 0, 0);
+	if (IS_ERR(pdev))
 		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
 			__func__, name, oh->name);
 exit:
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/timer.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,10 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
 
 /* Parent clocks, eventually these will come from the clock framework */
 
@@ -67,7 +72,7 @@
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
 
-u32 sys_timer_reserved;
+static u32 sys_timer_reserved;
 
 /* Clockevent code */
 
@@ -78,7 +83,7 @@ static irqreturn_t omap2_gp_timer_interr
 {
 	struct clock_event_device *evt = &clockevent_gpt;
 
-	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
@@ -93,7 +98,7 @@ static struct irqaction omap2_gp_timer_i
 static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
-	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
+	__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
 						0xffffffff - cycles, 1);
 
 	return 0;
@@ -104,16 +109,16 @@ static void omap2_gp_timer_set_mode(enum
 {
 	u32 period;
 
-	__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		period = clkev.rate / HZ;
 		period -= 1;
 		/* Looks like we need to first set the load value separately */
-		__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
+		__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
 					0xffffffff - period, 1);
-		__omap_dm_timer_load_start(clkev.io_base,
+		__omap_dm_timer_load_start(&clkev,
 					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
 						0xffffffff - period, 1);
 		break;
@@ -189,7 +194,8 @@ static int __init omap_dm_timer_init_one
 			clk_put(src);
 		}
 	}
-	__omap_dm_timer_reset(timer->io_base, 1, 1);
+	__omap_dm_timer_init_regs(timer);
+	__omap_dm_timer_reset(timer, 1, 1);
 	timer->posted = 1;
 
 	timer->rate = clk_get_rate(timer->fclk);
@@ -210,7 +216,7 @@ static void __init omap2_gp_clockevent_i
 	omap2_gp_timer_irq.dev_id = (void *)&clkev;
 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
 
-	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
 				     clockevent_gpt.shift);
@@ -251,7 +257,7 @@ static struct omap_dm_timer clksrc;
 static DEFINE_CLOCK_DATA(cd);
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+	return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
 }
 
 static struct clocksource clocksource_gpt = {
@@ -266,7 +272,7 @@ static void notrace dmtimer_update_sched
 {
 	u32 cyc;
 
-	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+	cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -276,7 +282,7 @@ unsigned long long notrace sched_clock(v
 	u32 cyc = 0;
 
 	if (clksrc.reserved)
-		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+		cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -293,7 +299,7 @@ static void __init omap2_gp_clocksource_
 	pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
 		gptimer_id, clksrc.rate);
 
-	__omap_dm_timer_load_start(clksrc.io_base,
+	__omap_dm_timer_load_start(&clksrc,
 			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
 	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
 
@@ -341,3 +347,157 @@ static void __init omap4_timer_init(void
 }
 OMAP_SYS_TIMER(4)
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @source:	array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+	int ret;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *fclk, *parent;
+	char *parent_name = NULL;
+
+	fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		parent_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		parent_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
+			parent_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	parent = clk_get(&pdev->dev, parent_name);
+	if (IS_ERR_OR_NULL(parent)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, parent_name);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(fclk, parent);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+			__func__, parent_name);
+		ret = -EINVAL;
+	}
+
+	clk_put(parent);
+	clk_put(fclk);
+
+	return ret;
+}
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:	timer hwmod pointer to be used to build timer device
+ * @user:	parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+	int id;
+	int ret = 0;
+	char *name = "omap_timer";
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+	struct omap_timer_capability_dev_attr *timer_dev_attr;
+	struct powerdomain *pwrdm;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	/* on secure device, do not register secure timer */
+	timer_dev_attr = oh->dev_attr;
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+		if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+			return ret;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Extract the IDs from name field in hwmod database
+	 * and use the same for constructing ids' for the
+	 * timer devices. In a way, we are avoiding usage of
+	 * static variable witin the function to do the same.
+	 * CAUTION: We have to be careful and make sure the
+	 * name in hwmod database does not change in which case
+	 * we might either make corresponding change here or
+	 * switch back static variable mechanism.
+	 */
+	sscanf(oh->name, "timer%2d", &id);
+
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+	pdata->timer_ip_version = oh->class->rev;
+
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (id - 1)) & 0x1)
+		pdata->reserved = 1;
+
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+#ifdef CONFIG_PM
+	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+#endif
+	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+				 NULL, 0, 0);
+
+	if (IS_ERR(pdev)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	}
+
+	kfree(pdata);
+
+	return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+	int ret;
+
+	ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+	if (unlikely(ret)) {
+		pr_err("%s: device registration failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/twl-common.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/twl-common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/twl-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/twl-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <plat/usb.h>
 
 #include "twl-common.h"
+#include "pm.h"
 
 static struct i2c_board_info __initdata pmic_i2c_board_info = {
 	.addr		= 0x48,
@@ -48,6 +49,16 @@ void __init omap_pmic_init(int bus, u32
 	omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
+void __init omap_pmic_late_init(void)
+{
+	/* Init the OMAP TWL parameters (if PMIC has been registerd) */
+	if (!pmic_i2c_board_info.irq)
+		return;
+
+	omap3_twl_init();
+	omap4_twl_init();
+}
+
 #if defined(CONFIG_ARCH_OMAP3)
 static struct twl4030_usb_data omap3_usb_pdata = {
 	.usb_mode	= T2_USB_MODE_ULPI,
@@ -99,7 +110,7 @@ static struct regulator_init_data omap3_
 
 static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_init_data omap3_vpll2_idata = {
@@ -235,6 +246,12 @@ static struct regulator_init_data omap4_
 	},
 };
 
+static struct regulator_consumer_supply omap4_vcxio_supply[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
+};
+
 static struct regulator_init_data omap4_vcxio_idata = {
 	.constraints = {
 		.min_uV			= 1800000,
@@ -243,7 +260,10 @@ static struct regulator_init_data omap4_
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
+		.always_on		= true,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap4_vcxio_supply),
+	.consumer_supplies	= omap4_vcxio_supply,
 };
 
 static struct regulator_init_data omap4_vusb_idata = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/twl-common.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/twl-common.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/twl-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/twl-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,8 @@
 #ifndef __OMAP_PMIC_COMMON__
 #define __OMAP_PMIC_COMMON__
 
+#include <plat/irqs.h>
+
 #define TWL_COMMON_PDATA_USB		(1 << 0)
 #define TWL_COMMON_PDATA_BCI		(1 << 1)
 #define TWL_COMMON_PDATA_MADC		(1 << 2)
@@ -30,6 +32,7 @@ struct twl4030_platform_data;
 
 void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
 		    struct twl4030_platform_data *pmic_data);
+void omap_pmic_late_init(void);
 
 static inline void omap2_pmic_init(const char *pmic_type,
 				   struct twl4030_platform_data *pmic_data)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/usb-musb.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/usb-musb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/usb-musb.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,52 +60,6 @@ static struct musb_hdrc_platform_data mu
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static struct omap_device_pm_latency omap_musb_latency[] = {
-	{
-		.deactivate_func	= omap_device_idle_hwmods,
-		.activate_func		= omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
-static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
-{
-	switch (board_data->interface_type) {
-	case MUSB_INTERFACE_UTMI:
-		omap_mux_init_signal("usba0_otg_dp", OMAP_PIN_INPUT);
-		omap_mux_init_signal("usba0_otg_dm", OMAP_PIN_INPUT);
-		break;
-	case MUSB_INTERFACE_ULPI:
-		omap_mux_init_signal("usba0_ulpiphy_clk",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_stp",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dir",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_nxt",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat0",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat1",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat2",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat3",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat4",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat5",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat6",
-						OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usba0_ulpiphy_dat7",
-						OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	default:
-		break;
-	}
-}
-
 static struct omap_musb_board_data musb_default_board_data = {
 	.interface_type		= MUSB_INTERFACE_ULPI,
 	.mode			= MUSB_OTG,
@@ -115,7 +69,6 @@ static struct omap_musb_board_data musb_
 void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 {
 	struct omap_hwmod		*oh;
-	struct omap_device		*od;
 	struct platform_device		*pdev;
 	struct device			*dev;
 	int				bus_id = -1;
@@ -145,22 +98,19 @@ void __init usb_musb_init(struct omap_mu
 		name = "musb-omap2430";
 	}
 
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-		pr_err("Could not look up %s\n", oh_name);
-		return;
-	}
+        oh = omap_hwmod_lookup(oh_name);
+        if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
+                 __func__, oh_name))
+                return;
 
-	od = omap_device_build(name, bus_id, oh, &musb_plat,
-			       sizeof(musb_plat), omap_musb_latency,
-			       ARRAY_SIZE(omap_musb_latency), false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(name, bus_id, oh, &musb_plat,
+			       sizeof(musb_plat), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		pr_err("Could not build omap_device for %s %s\n",
 						name, oh_name);
 		return;
 	}
 
-	pdev = &od->pdev;
 	dev = &pdev->dev;
 	get_device(dev);
 	dev->dma_mask = &musb_dmamask;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/usb-tusb6010.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/usb-tusb6010.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/usb-tusb6010.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/usb-tusb6010.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,13 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/string.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 
 #include <linux/usb/musb.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,9 +29,7 @@
  * VC data common to 34xx/36xx chips
  * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
  */
-static struct omap_vc_common_data omap3_vc_common = {
-	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
-	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+static struct omap_vc_common omap3_vc_common = {
 	.bypass_val_reg	 = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
 	.data_shift	 = OMAP3430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
@@ -42,22 +40,33 @@ static struct omap_vc_common_data omap3_
 	.cmd_onlp_shift	 = OMAP3430_VC_CMD_ONLP_SHIFT,
 	.cmd_ret_shift	 = OMAP3430_VC_CMD_RET_SHIFT,
 	.cmd_off_shift	 = OMAP3430_VC_CMD_OFF_SHIFT,
+	.i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
+	.i2c_cfg_reg	 = OMAP3_PRM_VC_I2C_CFG_OFFSET,
+	.i2c_mcode_mask	 = OMAP3430_MCODE_MASK,
 };
 
-struct omap_vc_instance_data omap3_vc1_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_mpu = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
-	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
 	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
-	.smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
 	.smps_volra_mask = OMAP3430_VOLRA0_MASK,
+	.smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
 };
 
-struct omap_vc_instance_data omap3_vc2_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_core = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
-	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
-	.smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
 	.smps_volra_mask = OMAP3430_VOLRA1_MASK,
+	.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,7 @@
  * VC data common to 44xx chips
  * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
  */
-static const struct omap_vc_common_data omap4_vc_common = {
-	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
-	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+static const struct omap_vc_common omap4_vc_common = {
 	.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
 	.data_shift = OMAP4430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
@@ -43,33 +41,49 @@ static const struct omap_vc_common_data
 	.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
 	.cmd_ret_shift = OMAP4430_RET_SHIFT,
 	.cmd_off_shift = OMAP4430_OFF_SHIFT,
+	.i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
+	.i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
+	.i2c_mcode_mask	 = OMAP4430_HSMCODE_MASK,
 };
 
 /* VC instance data for each controllable voltage line */
-struct omap_vc_instance_data omap4_vc_mpu_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_mpu = {
+	.flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_iva_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_iva = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_core_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_core = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,367 @@
+/*
+ * OMAP Voltage Controller (VC) interface
+ *
+ * Copyright (C) 2011 Texas Instruments, 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/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+/**
+ * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
+ * @sa: bit for slave address
+ * @rav: bit for voltage configuration register
+ * @rac: bit for command configuration register
+ * @racen: enable bit for RAC
+ * @cmd: bit for command value set selection
+ *
+ * Channel configuration bits, common for OMAP3+
+ * OMAP3 register: PRM_VC_CH_CONF
+ * OMAP4 register: PRM_VC_CFG_CHANNEL
+ * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
+ */
+struct omap_vc_channel_cfg {
+	u8 sa;
+	u8 rav;
+	u8 rac;
+	u8 racen;
+	u8 cmd;
+};
+
+static struct omap_vc_channel_cfg vc_default_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(1),
+	.rac   = BIT(2),
+	.racen = BIT(3),
+	.cmd   = BIT(4),
+};
+
+/*
+ * On OMAP3+, all VC channels have the above default bitfield
+ * configuration, except the OMAP4 MPU channel.  This appears
+ * to be a freak accident as every other VC channel has the
+ * default configuration, thus creating a mutant channel config.
+ */
+static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(2),
+	.rac   = BIT(3),
+	.racen = BIT(4),
+	.cmd   = BIT(1),
+};
+
+static struct omap_vc_channel_cfg *vc_cfg_bits;
+#define CFG_CHANNEL_MASK 0x1f
+
+/**
+ * omap_vc_config_channel - configure VC channel to PMIC mappings
+ * @voltdm: pointer to voltagdomain defining the desired VC channel
+ *
+ * Configures the VC channel to PMIC mappings for the following
+ * PMIC settings
+ * - i2c slave address (SA)
+ * - voltage configuration address (RAV)
+ * - command configuration address (RAC) and enable bit (RACEN)
+ * - command values for ON, ONLP, RET and OFF (CMD)
+ *
+ * This function currently only allows flexible configuration of the
+ * non-default channel.  Starting with OMAP4, there are more than 2
+ * channels, with one defined as the default (on OMAP4, it's MPU.)
+ * Only the non-default channel can be configured.
+ */
+static int omap_vc_config_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+
+	/*
+	 * For default channel, the only configurable bit is RACEN.
+	 * All others must stay at zero (see function comment above.)
+	 */
+	if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
+		vc->cfg_channel &= vc_cfg_bits->racen;
+
+	voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel_reg);
+
+	return 0;
+}
+
+/* Voltage scale and accessory APIs */
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 vc_cmdval;
+
+	/* Check if sufficient pmic info is available for this vdd */
+	if (!voltdm->pmic) {
+		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	if (!voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC function to convert voltage in uV to"
+			"vsel not registered. Hence unable to scale voltage"
+			"for vdd_%s\n", __func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	*target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+	*current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
+
+	/* Setting the ON voltage to the new target voltage */
+	vc_cmdval = voltdm->read(vc->cmdval_reg);
+	vc_cmdval &= ~vc->common->cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
+	voltdm->write(vc_cmdval, vc->cmdval_reg);
+
+	omap_vp_update_errorgain(voltdm, target_volt);
+
+	return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel)
+{
+	u32 smps_steps = 0, smps_delay = 0;
+
+	smps_steps = abs(target_vsel - current_vsel);
+	/* SMPS slew rate / step size. 2us added as buffer. */
+	smps_delay = ((smps_steps * voltdm->pmic->step_size) /
+			voltdm->pmic->slew_rate) + 2;
+	udelay(smps_delay);
+}
+
+/* vc_bypass_scale - VC bypass method of voltage scaling */
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 loop_cnt = 0, retries_cnt = 0;
+	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+	u8 target_vsel, current_vsel;
+	int ret;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	vc_valid = vc->common->valid;
+	vc_bypass_val_reg = vc->common->bypass_val_reg;
+	vc_bypass_value = (target_vsel << vc->common->data_shift) |
+		(vc->volt_reg_addr << vc->common->regaddr_shift) |
+		(vc->i2c_slave_addr << vc->common->slaveaddr_shift);
+
+	voltdm->write(vc_bypass_value, vc_bypass_val_reg);
+	voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
+
+	vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+	/*
+	 * Loop till the bypass command is acknowledged from the SMPS.
+	 * NOTE: This is legacy code. The loop count and retry count needs
+	 * to be revisited.
+	 */
+	while (!(vc_bypass_value & vc_valid)) {
+		loop_cnt++;
+
+		if (retries_cnt > 10) {
+			pr_warning("%s: Retry count exceeded\n", __func__);
+			return -ETIMEDOUT;
+		}
+
+		if (loop_cnt > 50) {
+			retries_cnt++;
+			loop_cnt = 0;
+			udelay(10);
+		}
+		vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+	}
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+	return 0;
+}
+
+static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+{
+	/*
+	 * Voltage Manager FSM parameters init
+	 * XXX This data should be passed in from the board file
+	 */
+	voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
+	voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
+	voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+
+	if (is_initialized)
+		return;
+
+	omap3_vfsm_init(voltdm);
+
+	is_initialized = true;
+}
+
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+	u32 vc_val;
+
+	if (is_initialized)
+		return;
+
+	/* XXX These are magic numbers and do not belong! */
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+
+	is_initialized = true;
+}
+
+/**
+ * omap_vc_i2c_init - initialize I2C interface to PMIC
+ * @voltdm: voltage domain containing VC data
+ *
+ * Use PMIC supplied seetings for I2C high-speed mode and
+ * master code (if set) and program the VC I2C configuration
+ * register.
+ *
+ * The VC I2C configuration is common to all VC channels,
+ * so this function only configures I2C for the first VC
+ * channel registers.  All other VC channels will use the
+ * same configuration.
+ */
+static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	static bool initialized;
+	static bool i2c_high_speed;
+	u8 mcode;
+
+	if (initialized) {
+		if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
+			pr_warn("%s: I2C config for all channels must match.",
+				__func__);
+		return;
+	}
+
+	i2c_high_speed = voltdm->pmic->i2c_high_speed;
+	if (i2c_high_speed)
+		voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_reg);
+
+	mcode = voltdm->pmic->i2c_mcode;
+	if (mcode)
+		voltdm->rmw(vc->common->i2c_mcode_mask,
+			    mcode << __ffs(vc->common->i2c_mcode_mask),
+			    vc->common->i2c_cfg_reg);
+
+	initialized = true;
+}
+
+void __init omap_vc_init_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	u32 val;
+
+	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC info requried to configure vc for"
+			"vdd_%s not populated.Hence cannot initialize vc\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vc->cfg_channel = 0;
+	if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
+		vc_cfg_bits = &vc_mutant_channel_cfg;
+	else
+		vc_cfg_bits = &vc_default_channel_cfg;
+
+	/* get PMIC/board specific settings */
+	vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
+	vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
+	vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
+	vc->setup_time = voltdm->pmic->volt_setup_time;
+
+	/* Configure the i2c slave address for this VC */
+	voltdm->rmw(vc->smps_sa_mask,
+		    vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
+		    vc->smps_sa_reg);
+	vc->cfg_channel |= vc_cfg_bits->sa;
+
+	/*
+	 * Configure the PMIC register addresses.
+	 */
+	voltdm->rmw(vc->smps_volra_mask,
+		    vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
+		    vc->smps_volra_reg);
+	vc->cfg_channel |= vc_cfg_bits->rav;
+
+	if (vc->cmd_reg_addr) {
+		voltdm->rmw(vc->smps_cmdra_mask,
+			    vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
+			    vc->smps_cmdra_reg);
+		vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+	}
+
+	/* Set up the on, inactive, retention and off voltage */
+	on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
+	onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
+	ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
+	off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+	val = ((on_vsel << vc->common->cmd_on_shift) |
+	       (onlp_vsel << vc->common->cmd_onlp_shift) |
+	       (ret_vsel << vc->common->cmd_ret_shift) |
+	       (off_vsel << vc->common->cmd_off_shift));
+	voltdm->write(val, vc->cmdval_reg);
+	vc->cfg_channel |= vc_cfg_bits->cmd;
+
+	/* Channel configuration */
+	omap_vc_config_channel(voltdm);
+
+	/* Configure the setup times */
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+		    vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
+		    voltdm->vfsm->voltsetup_reg);
+
+	omap_vc_i2c_init(voltdm);
+
+	if (cpu_is_omap34xx())
+		omap3_vc_init_channel(voltdm);
+	else if (cpu_is_omap44xx())
+		omap4_vc_init_channel(voltdm);
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vc.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,12 +19,12 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
 /**
- * struct omap_vc_common_data - per-VC register/bitfield data
+ * struct omap_vc_common - per-VC register/bitfield data
  * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
  * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
- * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
- * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
  * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
  * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
  * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
@@ -33,15 +33,16 @@
  * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
  * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
  * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ * @i2c_cfg_reg: I2C configuration register offset
+ * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
+ * @i2c_mcode_mask: MCODE field mask for I2C config register
  *
  * XXX One of cmd_on_mask and cmd_on_shift are not needed
  * XXX VALID should probably be a shift, not a mask
  */
-struct omap_vc_common_data {
+struct omap_vc_common {
 	u32 cmd_on_mask;
 	u32 valid;
-	u8 smps_sa_reg;
-	u8 smps_volra_reg;
 	u8 bypass_val_reg;
 	u8 data_shift;
 	u8 slaveaddr_shift;
@@ -50,34 +51,75 @@ struct omap_vc_common_data {
 	u8 cmd_onlp_shift;
 	u8 cmd_ret_shift;
 	u8 cmd_off_shift;
+	u8 i2c_cfg_reg;
+	u8 i2c_cfg_hsen_mask;
+	u8 i2c_mcode_mask;
 };
 
+/* omap_vc_channel.flags values */
+#define OMAP_VC_CHANNEL_DEFAULT BIT(0)
+#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
+
 /**
- * struct omap_vc_instance_data - VC per-instance data
- * @vc_common: pointer to VC common data for this platform
- * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
- * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
- * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
- * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ * struct omap_vc_channel - VC per-instance data
+ * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command configuration register address
+ * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
+ * @cfg_channel: current value of VC channel configuration register
+ * @i2c_high_speed: whether or not to use I2C high-speed mode
  *
- * XXX It is not necessary to have both a *_mask and a *_shift -
- *     remove one
+ * @common: pointer to VC common data for this platform
+ * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
+ * @cmdval_reg: register for on/ret/off voltage level values for this channel
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
+ * @cfg_channel_reg: VC channel configuration register
+ * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
+ * @flags: VC channel-specific flags (optional)
  */
-struct omap_vc_instance_data {
-	const struct omap_vc_common_data *vc_common;
+struct omap_vc_channel {
+	/* channel state */
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
+	u16 setup_time;
+	u8 cfg_channel;
+	bool i2c_high_speed;
+
+	/* register access data */
+	const struct omap_vc_common *common;
 	u32 smps_sa_mask;
 	u32 smps_volra_mask;
+	u32 smps_cmdra_mask;
 	u8 cmdval_reg;
-	u8 smps_sa_shift;
-	u8 smps_volra_shift;
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 smps_cmdra_reg;
+	u8 cfg_channel_reg;
+	u8 cfg_channel_sa_shift;
+	u8 flags;
 };
 
-extern struct omap_vc_instance_data omap3_vc1_data;
-extern struct omap_vc_instance_data omap3_vc2_data;
+extern struct omap_vc_channel omap3_vc_mpu;
+extern struct omap_vc_channel omap3_vc_core;
 
-extern struct omap_vc_instance_data omap4_vc_mpu_data;
-extern struct omap_vc_instance_data omap4_vc_iva_data;
-extern struct omap_vc_instance_data omap4_vc_core_data;
+extern struct omap_vc_channel omap4_vc_mpu;
+extern struct omap_vc_channel omap4_vc_iva;
+extern struct omap_vc_channel omap4_vc_core;
+
+void omap_vc_init_channel(struct voltagedomain *voltdm);
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel);
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel);
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt);
 
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltage.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltage.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltage.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,10 +21,11 @@
 
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <plat/common.h>
 
@@ -36,839 +37,88 @@
 #include "control.h"
 
 #include "voltage.h"
+#include "powerdomain.h"
 
 #include "vc.h"
 #include "vp.h"
 
-#define VOLTAGE_DIR_SIZE	16
-
-
-static struct omap_vdd_info **vdd_info;
-
-/*
- * Number of scalable voltage domains.
- */
-static int nr_scalable_vdd;
-
-/* XXX document */
-static s16 prm_mod_offs;
-static s16 prm_irqst_ocp_mod_offs;
-
-static struct dentry *voltage_dir;
-
-/* Init function pointers */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
-					unsigned long target_volt);
-
-static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
-{
-	return omap2_prm_read_mod_reg(mod, offset);
-}
-
-static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	omap2_prm_write_mod_reg(val, mod, offset);
-}
-
-static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
-{
-	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-					mod, offset);
-}
-
-static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
-}
-
-static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
-{
-	char *sys_ck_name;
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
-
-	/*
-	 * XXX Clockfw should handle this, or this should be in a
-	 * struct record
-	 */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		sys_ck_name = "sys_ck";
-	else if (cpu_is_omap44xx())
-		sys_ck_name = "sys_clkin_ck";
-	else
-		return -EINVAL;
-
-	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
-	 */
-	sys_ck = clk_get(NULL, sys_ck_name);
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
-
-	vdd->vp_rt_data.vpconfig_erroroffset =
-		(vdd->pmic_info->vp_erroroffset <<
-		 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
-
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_rt_data.vlimitto_timeout = timeout_val;
-	vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-
-	return 0;
-}
-
-/* Voltage debugfs support */
-static int vp_volt_debug_get(void *data, u64 *val)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-	u8 vsel;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info->vsel_to_uv) {
-		pr_warning("PMIC function to convert vsel to voltage"
-			"in uV not registerd\n");
-		return -EINVAL;
-	}
-
-	*val = vdd->pmic_info->vsel_to_uv(vsel);
-	return 0;
-}
-
-static int nom_volt_debug_get(void *data, u64 *val)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
-								"%llu\n");
-static void vp_latch_vsel(struct omap_vdd_info *vdd)
-{
-	u32 vpconfig;
-	unsigned long uvdc;
-	char vsel;
-
-	uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
-	if (!uvdc) {
-		pr_warning("%s: unable to find current voltage for vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_warning("%s: PMIC function to convert voltage in uV to"
-			" vsel not registered\n", __func__);
-		return;
-	}
-
-	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
-
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
-			vdd->vp_data->vp_common->vpconfig_initvdd);
-	vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
-
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
-		       prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Clear initVDD copy trigger bit */
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-}
-
-/* Generic voltage init functions */
-static void __init vp_init(struct omap_vdd_info *vdd)
-{
-	u32 vp_val;
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
-		(vdd->vp_rt_data.vpconfig_errorgain <<
-		vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
-		vdd->vp_data->vp_common->vpconfig_timeouten;
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
-		vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
-		(vdd->vp_rt_data.vstepmin_stepmin <<
-		vdd->vp_data->vp_common->vstepmin_stepmin_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
-
-	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
-		vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
-		(vdd->vp_rt_data.vstepmax_stepmax <<
-		vdd->vp_data->vp_common->vstepmax_stepmax_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
-
-	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
-		vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
-		(vdd->vp_rt_data.vlimitto_vddmin <<
-		vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
-		(vdd->vp_rt_data.vlimitto_timeout <<
-		vdd->vp_data->vp_common->vlimitto_timeout_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
-}
-
-static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
-{
-	char *name;
-
-	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
-	if (!name) {
-		pr_warning("%s: Unable to allocate memory for debugfs"
-			" directory name for vdd_%s",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-	strcpy(name, "vdd_");
-	strcat(name, vdd->voltdm.name);
-
-	vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
-	kfree(name);
-	if (IS_ERR(vdd->debug_dir)) {
-		pr_warning("%s: Unable to create debugfs directory for"
-			" vdd_%s\n", __func__, vdd->voltdm.name);
-		vdd->debug_dir = NULL;
-		return;
-	}
-
-	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vpconfig_errorgain));
-	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
-	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_stepmin));
-	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
-	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_stepmax));
-	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmax));
-	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmin));
-	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_timeout));
-	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
-				(void *) vdd, &vp_volt_debug_fops);
-	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
-				vdd->debug_dir, (void *) vdd,
-				&nom_volt_debug_fops);
-}
-
-/* Voltage scale and accessory APIs */
-static int _pre_volt_scale(struct omap_vdd_info *vdd,
-		unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
-{
-	struct omap_volt_data *volt_data;
-	const struct omap_vc_common_data *vc_common;
-	const struct omap_vp_common_data *vp_common;
-	u32 vc_cmdval, vp_errgain_val;
-
-	vc_common = vdd->vc_data->vc_common;
-	vp_common = vdd->vp_data->vp_common;
-
-	/* Check if suffiecient pmic info is available for this vdd */
-	if (!vdd->pmic_info) {
-		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	if (!vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC function to convert voltage in uV to"
-			"vsel not registered. Hence unable to scale voltage"
-			"for vdd_%s\n", __func__, vdd->voltdm.name);
-		return -ENODATA;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	/* Get volt_data corresponding to target_volt */
-	volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
-	if (IS_ERR(volt_data))
-		volt_data = NULL;
-
-	*target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
-	*current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	/* Setting the ON voltage to the new target voltage */
-	vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
-	vc_cmdval &= ~vc_common->cmd_on_mask;
-	vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
-	vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
-	/* Setting vp errorgain based on the voltage */
-	if (volt_data) {
-		vp_errgain_val = vdd->read_reg(prm_mod_offs,
-					       vdd->vp_data->vpconfig);
-		vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
-		vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
-		vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
-			vp_common->vpconfig_errorgain_shift;
-		vdd->write_reg(vp_errgain_val, prm_mod_offs,
-			       vdd->vp_data->vpconfig);
-	}
-
-	return 0;
-}
-
-static void _post_volt_scale(struct omap_vdd_info *vdd,
-		unsigned long target_volt, u8 target_vsel, u8 current_vsel)
-{
-	u32 smps_steps = 0, smps_delay = 0;
-
-	smps_steps = abs(target_vsel - current_vsel);
-	/* SMPS slew rate / step size. 2us added as buffer. */
-	smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
-			vdd->pmic_info->slew_rate) + 2;
-	udelay(smps_delay);
-
-	vdd->curr_volt = target_volt;
-}
-
-/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
-static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 loop_cnt = 0, retries_cnt = 0;
-	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
-	u8 target_vsel, current_vsel;
-	int ret;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	vc_valid = vdd->vc_data->vc_common->valid;
-	vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
-	vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
-			(vdd->pmic_info->pmic_reg <<
-			vdd->vc_data->vc_common->regaddr_shift) |
-			(vdd->pmic_info->i2c_slave_addr <<
-			vdd->vc_data->vc_common->slaveaddr_shift);
-
-	vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
-	vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
-		       vc_bypass_val_reg);
-
-	vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
-	/*
-	 * Loop till the bypass command is acknowledged from the SMPS.
-	 * NOTE: This is legacy code. The loop count and retry count needs
-	 * to be revisited.
-	 */
-	while (!(vc_bypass_value & vc_valid)) {
-		loop_cnt++;
-
-		if (retries_cnt > 10) {
-			pr_warning("%s: Retry count exceeded\n", __func__);
-			return -ETIMEDOUT;
-		}
-
-		if (loop_cnt > 50) {
-			retries_cnt++;
-			loop_cnt = 0;
-			udelay(10);
-		}
-		vc_bypass_value = vdd->read_reg(prm_mod_offs,
-						vc_bypass_val_reg);
-	}
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-	return 0;
-}
-
-/* VP force update method of voltage scaling */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 vpconfig;
-	u8 target_vsel, current_vsel, prm_irqst_reg;
-	int ret, timeout = 0;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
-
-	/*
-	 * Clear all pending TransactionDone interrupt/status. Typical latency
-	 * is <3us
-	 */
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
-		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-	if (timeout >= VP_TRANXDONE_TIMEOUT) {
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
-			"Voltage change aborted", __func__, vdd->voltdm.name);
-		return -ETIMEDOUT;
-	}
-
-	/* Configure for VP-Force Update */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
-			vdd->vp_data->vp_common->vpconfig_forceupdate |
-			vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
-	vpconfig |= ((target_vsel <<
-			vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Force update of voltage */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for TransactionDone. Typical latency is <200us.
-	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
-	 */
-	timeout = 0;
-	omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-			   vdd->vp_data->prm_irqst_data->tranxdone_status),
-			  VP_TRANXDONE_TIMEOUT, timeout);
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
-			"TRANXDONE never got set after the voltage update\n",
-			__func__, vdd->voltdm.name);
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-
-	/*
-	 * Disable TransactionDone interrupt , clear all status, clear
-	 * control registers
-	 */
-	timeout = 0;
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
-		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
-			"to clear the TRANXDONE status\n",
-			__func__, vdd->voltdm.name);
-
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	/* Clear initVDD copy trigger bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-	/* Clear force bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	return 0;
-}
-
-static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
-{
-	/*
-	 * Voltage Manager FSM parameters init
-	 * XXX This data should be passed in from the board file
-	 */
-	vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
-	vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
-		       OMAP3_PRM_VOLTOFFSET_OFFSET);
-	vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
-		       OMAP3_PRM_VOLTSETUP2_OFFSET);
-}
-
-static void __init omap3_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* Set up the on, inactive, retention and off voltage */
-	on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
-	onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
-	ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
-	off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
-	vc_val	= ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
-		(onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
-		(ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
-		(off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
-	vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
-	/*
-	 * Generic VC parameters init
-	 * XXX This data should be abstracted out
-	 */
-	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
-			OMAP3_PRM_VC_CH_CONF_OFFSET);
-	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
-			OMAP3_PRM_VC_I2C_CFG_OFFSET);
-
-	omap3_vfsm_init(vdd);
-
-	is_initialized = true;
-}
-
-
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* TODO: Configure setup times and CMD_VAL values*/
-
-	/*
-	 * Generic VC parameters init
-	 * XXX This data should be abstracted out
-	 */
-	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
-		  OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
-		  OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
-	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
-
-	/* XXX These are magic numbers and do not belong! */
-	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
-	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
-
-	is_initialized = true;
-}
-
-static void __init omap_vc_init(struct omap_vdd_info *vdd)
-{
-	u32 vc_val;
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC info requried to configure vc for"
-			"vdd_%s not populated.Hence cannot initialize vc\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(prm_mod_offs,
-			       vdd->vc_data->vc_common->smps_sa_reg);
-	vc_val &= ~vdd->vc_data->smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
-	vdd->write_reg(vc_val, prm_mod_offs,
-		       vdd->vc_data->vc_common->smps_sa_reg);
-
-	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(prm_mod_offs,
-			       vdd->vc_data->vc_common->smps_volra_reg);
-	vc_val &= ~vdd->vc_data->smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
-	vdd->write_reg(vc_val, prm_mod_offs,
-		       vdd->vc_data->vc_common->smps_volra_reg);
-
-	/* Configure the setup times */
-	vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
-	vc_val &= ~vdd->vfsm->voltsetup_mask;
-	vc_val |= vdd->pmic_info->volt_setup_time <<
-			vdd->vfsm->voltsetup_shift;
-	vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
-
-	if (cpu_is_omap34xx())
-		omap3_vc_init(vdd);
-	else if (cpu_is_omap44xx())
-		omap4_vc_init(vdd);
-}
-
-static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
-{
-	int ret = -EINVAL;
-
-	if (!vdd->pmic_info) {
-		pr_err("%s: PMIC info requried to configure vdd_%s not"
-			"populated.Hence cannot initialize vdd_%s\n",
-			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		goto ovdc_out;
-	}
-
-	if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
-		goto ovdc_out;
-
-	if (cpu_is_omap34xx()) {
-		vdd->read_reg = omap3_voltage_read_reg;
-		vdd->write_reg = omap3_voltage_write_reg;
-		ret = 0;
-	} else if (cpu_is_omap44xx()) {
-		vdd->read_reg = omap4_voltage_read_reg;
-		vdd->write_reg = omap4_voltage_write_reg;
-		ret = 0;
-	}
-
-ovdc_out:
-	return ret;
-}
+static LIST_HEAD(voltdm_list);
 
 /* Public functions */
 /**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
- * @voltdm:	pointer to the VDD for which current voltage info is needed
- *
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
- */
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return 0;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->curr_volt;
-}
-
-/**
- * omap_vp_get_curr_volt() - API to get the current vp voltage.
- * @voltdm:	pointer to the VDD.
+ * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
+ * @voltdm:	pointer to the voltdm for which current voltage info is needed
  *
- * This API returns the current voltage for the specified voltage processor
+ * API to get the current non-auto-compensated voltage for a voltage domain.
+ * Returns 0 in case of error else returns the current voltage.
  */
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
 {
-	struct omap_vdd_info *vdd;
-	u8 curr_vsel;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return 0;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg) {
-		pr_err("%s: No read API for reading vdd_%s regs\n",
-			__func__, voltdm->name);
-		return 0;
-	}
-
-	curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
-		pr_warning("%s: PMIC function to convert vsel to voltage"
-			"in uV not registerd\n", __func__);
-		return 0;
-	}
-
-	return vdd->pmic_info->vsel_to_uv(curr_vsel);
-}
-
-/**
- * omap_vp_enable() - API to enable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be enabled.
- *
- * This API enables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_enable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already enabled, do nothing. Return */
-	if (vdd->vp_enabled)
-		return;
-
-	vp_latch_vsel(vdd);
-
-	/* Enable VP */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-	vdd->vp_enabled = true;
-}
-
-/**
- * omap_vp_disable() - API to disable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be disabled.
- *
- * This API disables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_disable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-	int timeout;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already disabled, do nothing. Return */
-	if (!vdd->vp_enabled) {
-		pr_warning("%s: Trying to disable VP for vdd_%s when"
-			"it is already disabled\n", __func__, voltdm->name);
-		return;
-	}
-
-	/* Disable VP */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
-	 */
-	omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
-				VP_IDLE_TIMEOUT, timeout);
-
-	if (timeout >= VP_IDLE_TIMEOUT)
-		pr_warning("%s: vdd_%s idle timedout\n",
-			__func__, voltdm->name);
-
-	vdd->vp_enabled = false;
-
-	return;
+	return voltdm->nominal_volt;
 }
 
 /**
- * omap_voltage_scale_vdd() - API to scale voltage of a particular
- *				voltage domain.
- * @voltdm:	pointer to the VDD which is to be scaled.
- * @target_volt:	The target voltage of the voltage domain
+ * voltdm_scale() - API to scale voltage of a particular voltage domain.
+ * @voltdm: pointer to the voltage domain which is to be scaled.
+ * @target_volt: The target voltage of the voltage domain
  *
  * This API should be called by the kernel to do the voltage scaling
- * for a particular voltage domain during dvfs or any other situation.
+ * for a particular voltage domain during DVFS.
  */
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt)
+int voltdm_scale(struct voltagedomain *voltdm,
+		 unsigned long target_volt)
 {
-	struct omap_vdd_info *vdd;
+	int ret;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_scale) {
+	if (!voltdm->scale) {
 		pr_err("%s: No voltage scale API registered for vdd_%s\n",
 			__func__, voltdm->name);
 		return -ENODATA;
 	}
 
-	return vdd->volt_scale(vdd, target_volt);
+	ret = voltdm->scale(voltdm, target_volt);
+	if (!ret)
+		voltdm->nominal_volt = target_volt;
+
+	return ret;
 }
 
 /**
- * omap_voltage_reset() - Resets the voltage of a particular voltage domain
- *			to that of the current OPP.
- * @voltdm:	pointer to the VDD whose voltage is to be reset.
+ * voltdm_reset() - Resets the voltage of a particular voltage domain
+ *		    to that of the current OPP.
+ * @voltdm: pointer to the voltage domain whose voltage is to be reset.
  *
  * This API finds out the correct voltage the voltage domain is supposed
  * to be at and resets the voltage to that level. Should be used especially
  * while disabling any voltage compensation modules.
  */
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
 {
-	unsigned long target_uvdc;
+	unsigned long target_volt;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	target_uvdc = omap_voltage_get_nom_volt(voltdm);
-	if (!target_uvdc) {
+	target_volt = voltdm_get_voltage(voltdm);
+	if (!target_volt) {
 		pr_err("%s: unable to find current voltage for vdd_%s\n",
 			__func__, voltdm->name);
 		return;
 	}
 
-	omap_voltage_scale_vdd(voltdm, target_uvdc);
+	voltdm_scale(voltdm, target_volt);
 }
 
 /**
@@ -884,18 +134,14 @@ void omap_voltage_reset(struct voltagedo
  *
  */
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
-		struct omap_volt_data **volt_data)
+				struct omap_volt_data **volt_data)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	*volt_data = vdd->volt_data;
+	*volt_data = voltdm->volt_data;
 }
 
 /**
@@ -914,9 +160,8 @@ void omap_voltage_get_volttable(struct v
  * domain or if there is no matching entry.
  */
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt)
+						 unsigned long volt)
 {
-	struct omap_vdd_info *vdd;
 	int i;
 
 	if (!voltdm || IS_ERR(voltdm)) {
@@ -924,17 +169,15 @@ struct omap_volt_data *omap_voltage_get_
 		return ERR_PTR(-EINVAL);
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_data) {
+	if (!voltdm->volt_data) {
 		pr_warning("%s: voltage table does not exist for vdd_%s\n",
 			__func__, voltdm->name);
 		return ERR_PTR(-ENODATA);
 	}
 
-	for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
-		if (vdd->volt_data[i].volt_nominal == volt)
-			return &vdd->volt_data[i];
+	for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+		if (voltdm->volt_data[i].volt_nominal == volt)
+			return &voltdm->volt_data[i];
 	}
 
 	pr_notice("%s: Unable to match the current voltage with the voltage"
@@ -947,54 +190,25 @@ struct omap_volt_data *omap_voltage_get_
  * omap_voltage_register_pmic() - API to register PMIC specific data
  * @voltdm:	pointer to the VDD for which the PMIC specific data is
  *		to be registered
- * @pmic_info:	the structure containing pmic info
+ * @pmic:	the structure containing pmic info
  *
  * This API is to be called by the SOC/PMIC file to specify the
- * pmic specific info as present in omap_volt_pmic_info structure.
+ * pmic specific info as present in omap_voltdm_pmic structure.
  */
 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
+			       struct omap_voltdm_pmic *pmic)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	vdd->pmic_info = pmic_info;
+	voltdm->pmic = pmic;
 
 	return 0;
 }
 
 /**
- * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
- *				corresponding to a voltage domain.
- *
- * @voltdm:	pointer to the VDD whose debug directory is required.
- *
- * This API returns pointer to the debugfs directory corresponding
- * to the voltage domain. Should be used by drivers requiring to
- * add any debug entry for a particular voltage domain. Returns NULL
- * in case of error.
- */
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return NULL;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->debug_dir;
-}
-
-/**
  * omap_change_voltscale_method() - API to change the voltage scaling method.
  * @voltdm:	pointer to the VDD whose voltage scaling method
  *		has to be changed.
@@ -1005,23 +219,19 @@ struct dentry *omap_voltage_get_dbgdir(s
  * defined in voltage.h
  */
 void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method)
+				  int voltscale_method)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
 	switch (voltscale_method) {
 	case VOLTSCALE_VPFORCEUPDATE:
-		vdd->volt_scale = vp_forceupdate_scale_voltage;
+		voltdm->scale = omap_vp_forceupdate_scale;
 		return;
 	case VOLTSCALE_VCBYPASS:
-		vdd->volt_scale = vc_bypass_scale_voltage;
+		voltdm->scale = omap_vc_bypass_scale;
 		return;
 	default:
 		pr_warning("%s: Trying to change the method of voltage scaling"
@@ -1030,77 +240,192 @@ void omap_change_voltscale_method(struct
 }
 
 /**
- * omap_voltage_domain_lookup() - API to get the voltage domain pointer
- * @name:	Name of the voltage domain
+ * omap_voltage_late_init() - Init the various voltage parameters
  *
- * This API looks up in the global vdd_info struct for the
- * existence of voltage domain <name>. If it exists, the API returns
- * a pointer to the voltage domain structure corresponding to the
- * VDD<name>. Else retuns error pointer.
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
  */
-struct voltagedomain *omap_voltage_domain_lookup(char *name)
+int __init omap_voltage_late_init(void)
 {
-	int i;
+	struct voltagedomain *voltdm;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver init not yet happened.Faulting!\n",
+	if (list_empty(&voltdm_list)) {
+		pr_err("%s: Voltage driver support not added\n",
 			__func__);
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
-	if (!name) {
-		pr_err("%s: No name to get the votage domain!\n", __func__);
-		return ERR_PTR(-EINVAL);
+	list_for_each_entry(voltdm, &voltdm_list, node) {
+		struct clk *sys_ck;
+
+		if (!voltdm->scalable)
+			continue;
+
+		sys_ck = clk_get(NULL, voltdm->sys_clk.name);
+		if (IS_ERR(sys_ck)) {
+			pr_warning("%s: Could not get sys clk.\n", __func__);
+			return -EINVAL;
+		}
+		voltdm->sys_clk.rate = clk_get_rate(sys_ck);
+		WARN_ON(!voltdm->sys_clk.rate);
+		clk_put(sys_ck);
+
+		if (voltdm->vc) {
+			voltdm->scale = omap_vc_bypass_scale;
+			omap_vc_init_channel(voltdm);
+		}
+
+		if (voltdm->vp) {
+			voltdm->scale = omap_vp_forceupdate_scale;
+			omap_vp_init(voltdm);
+		}
 	}
 
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (!(strcmp(name, vdd_info[i]->voltdm.name)))
-			return &vdd_info[i]->voltdm;
+	return 0;
+}
+
+static struct voltagedomain *_voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm, *temp_voltdm;
+
+	voltdm = NULL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		if (!strcmp(name, temp_voltdm->name)) {
+			voltdm = temp_voltdm;
+			break;
+		}
 	}
 
-	return ERR_PTR(-EINVAL);
+	return voltdm;
 }
 
 /**
- * omap_voltage_late_init() - Init the various voltage parameters
+ * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
+ * @voltdm: struct voltagedomain * to add the powerdomain to
+ * @pwrdm: struct powerdomain * to associate with a voltagedomain
  *
- * This API is to be called in the later stages of the
- * system boot to init the voltage controller and
- * voltage processors.
+ * Associate the powerdomain @pwrdm with a voltagedomain @voltdm.  This
+ * enables the use of voltdm_for_each_pwrdm().  Returns -EINVAL if
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
+ * or 0 upon success.
  */
-int __init omap_voltage_late_init(void)
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 {
-	int i;
+	if (!voltdm || !pwrdm)
+		return -EINVAL;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver support not added\n",
-			__func__);
+	pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
+		 "%s\n", pwrdm->name, voltdm->name);
+
+	list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
+
+	return 0;
+}
+
+/**
+ * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
+ * @voltdm: struct voltagedomain * to iterate over
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each powerdomain in the
+ * voltagedomain @voltdm.  Returns -EINVAL if presented with invalid
+ * pointers; or passes along the last return value of the callback
+ * function, which should be 0 for success or anything else to
+ * indicate failure.
+ */
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm))
+{
+	struct powerdomain *pwrdm;
+	int ret = 0;
+
+	if (!fn)
 		return -EINVAL;
-	}
 
-	voltage_dir = debugfs_create_dir("voltage", NULL);
-	if (IS_ERR(voltage_dir))
-		pr_err("%s: Unable to create voltage debugfs main dir\n",
-			__func__);
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (omap_vdd_data_configure(vdd_info[i]))
-			continue;
-		omap_vc_init(vdd_info[i]);
-		vp_init(vdd_info[i]);
-		vdd_debugfs_init(vdd_info[i]);
+	list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
+		ret = (*fn)(voltdm, pwrdm);
+
+	return ret;
+}
+
+/**
+ * voltdm_for_each - call function on each registered voltagedomain
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each registered voltagedomain.
+ * The callback function @fn can return anything but 0 to bail out
+ * early from the iterator.  Returns the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure; or -EINVAL if the function pointer is null.
+ */
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user)
+{
+	struct voltagedomain *temp_voltdm;
+	int ret = 0;
+
+	if (!fn)
+		return -EINVAL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		ret = (*fn)(temp_voltdm, user);
+		if (ret)
+			break;
 	}
 
-	return 0;
+	return ret;
 }
 
-/* XXX document */
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
-				   struct omap_vdd_info *omap_vdd_array[],
-				   u8 omap_vdd_count)
+static int _voltdm_register(struct voltagedomain *voltdm)
 {
-	prm_mod_offs = prm_mod;
-	prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
-	vdd_info = omap_vdd_array;
-	nr_scalable_vdd = omap_vdd_count;
+	if (!voltdm || !voltdm->name)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&voltdm->pwrdm_list);
+	list_add(&voltdm->node, &voltdm_list);
+
+	pr_debug("voltagedomain: registered %s\n", voltdm->name);
+
 	return 0;
 }
+
+/**
+ * voltdm_lookup - look up a voltagedomain by name, return a pointer
+ * @name: name of voltagedomain
+ *
+ * Find a registered voltagedomain by its name @name.  Returns a pointer
+ * to the struct voltagedomain if found, or NULL otherwise.
+ */
+struct voltagedomain *voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm ;
+
+	if (!name)
+		return NULL;
+
+	voltdm = _voltdm_lookup(name);
+
+	return voltdm;
+}
+
+/**
+ * voltdm_init - set up the voltagedomain layer
+ * @voltdm_list: array of struct voltagedomain pointers to register
+ *
+ * Loop through the array of voltagedomains @voltdm_list, registering all
+ * that are available on the current CPU. If voltdm_list is supplied
+ * and not null, all of the referenced voltagedomains will be
+ * registered.  No return value.
+ */
+void voltdm_init(struct voltagedomain **voltdms)
+{
+	struct voltagedomain **v;
+
+	if (voltdms) {
+		for (v = voltdms; *v; v++)
+			_voltdm_register(*v);
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains2xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains2xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains2xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains2xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * 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/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain omap2_voltdm_core = {
+	.name = "core",
+};
+
+static struct voltagedomain omap2_voltdm_wkup = {
+	.name = "wakeup",
+};
+
+static struct voltagedomain *voltagedomains_omap2[] __initdata = {
+	&omap2_voltdm_core,
+	&omap2_voltdm_wkup,
+	NULL,
+};
+
+void __init omap2xxx_voltagedomains_init(void)
+{
+	voltdm_init(voltagedomains_omap2);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,65 +31,70 @@
  * VDD data
  */
 
-static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
 	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
-	.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
 	.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
 };
 
-static struct omap_vdd_info omap3_vdd1_info = {
-	.vp_data = &omap3_vp1_data,
-	.vc_data = &omap3_vc1_data,
-	.vfsm = &omap3_vdd1_vfsm_data,
-	.voltdm = {
-		.name = "mpu",
-	},
-};
-
-static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
 	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
-	.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
 	.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
 };
 
-static struct omap_vdd_info omap3_vdd2_info = {
-	.vp_data = &omap3_vp2_data,
-	.vc_data = &omap3_vc2_data,
-	.vfsm = &omap3_vdd2_vfsm_data,
-	.voltdm = {
-		.name = "core",
-	},
+static struct voltagedomain omap3_voltdm_mpu = {
+	.name = "mpu_iva",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_mpu,
+	.vfsm = &omap3_vdd1_vfsm,
+	.vp = &omap3_vp_mpu,
 };
 
-/* OMAP3 VDD structures */
-static struct omap_vdd_info *omap3_vdd_info[] = {
-	&omap3_vdd1_info,
-	&omap3_vdd2_info,
+static struct voltagedomain omap3_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_core,
+	.vfsm = &omap3_vdd2_vfsm,
+	.vp = &omap3_vp_core,
 };
 
-/* OMAP3 specific voltage init functions */
-static int __init omap3xxx_voltage_early_init(void)
-{
-	s16 prm_mod = OMAP3430_GR_MOD;
-	s16 prm_irqst_ocp_mod = OCP_MOD;
+static struct voltagedomain omap3_voltdm_wkup = {
+	.name = "wakeup",
+};
 
-	if (!cpu_is_omap34xx())
-		return 0;
+static struct voltagedomain *voltagedomains_omap3[] __initdata = {
+	&omap3_voltdm_mpu,
+	&omap3_voltdm_core,
+	&omap3_voltdm_wkup,
+	NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_ck";
+
+void __init omap3xxx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * XXX Will depend on the process, validation, and binning
 	 * for the currently-running IC
 	 */
 	if (cpu_is_omap3630()) {
-		omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
-		omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+		omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
+		omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
 	} else {
-		omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
-		omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+		omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
+		omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
 	}
 
-	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
-				       omap3_vdd_info,
-				       ARRAY_SIZE(omap3_vdd_info));
+	for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
+
+	voltdm_init(voltagedomains_omap3);
 };
-core_initcall(omap3xxx_voltage_early_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltagedomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltagedomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,71 +32,80 @@
 #include "vc.h"
 #include "vp.h"
 
-static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
 };
 
-static struct omap_vdd_info omap4_vdd_mpu_info = {
-	.vp_data = &omap4_vp_mpu_data,
-	.vc_data = &omap4_vc_mpu_data,
-	.vfsm = &omap4_vdd_mpu_vfsm_data,
-	.voltdm = {
-		.name = "mpu",
-	},
+static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
 };
 
-static struct omap_vdd_info omap4_vdd_iva_info = {
-	.vp_data = &omap4_vp_iva_data,
-	.vc_data = &omap4_vc_iva_data,
-	.vfsm = &omap4_vdd_iva_vfsm_data,
-	.voltdm = {
-		.name = "iva",
-	},
+static struct voltagedomain omap4_voltdm_mpu = {
+	.name = "mpu",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_mpu,
+	.vfsm = &omap4_vdd_mpu_vfsm,
+	.vp = &omap4_vp_mpu,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+static struct voltagedomain omap4_voltdm_iva = {
+	.name = "iva",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_iva,
+	.vfsm = &omap4_vdd_iva_vfsm,
+	.vp = &omap4_vp_iva,
 };
 
-static struct omap_vdd_info omap4_vdd_core_info = {
-	.vp_data = &omap4_vp_core_data,
-	.vc_data = &omap4_vc_core_data,
-	.vfsm = &omap4_vdd_core_vfsm_data,
-	.voltdm = {
-		.name = "core",
-	},
+static struct voltagedomain omap4_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_core,
+	.vfsm = &omap4_vdd_core_vfsm,
+	.vp = &omap4_vp_core,
 };
 
-/* OMAP4 VDD structures */
-static struct omap_vdd_info *omap4_vdd_info[] = {
-	&omap4_vdd_mpu_info,
-	&omap4_vdd_iva_info,
-	&omap4_vdd_core_info,
+static struct voltagedomain omap4_voltdm_wkup = {
+	.name = "wakeup",
 };
 
-/* OMAP4 specific voltage init functions */
-static int __init omap44xx_voltage_early_init(void)
-{
-	s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
-	s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+static struct voltagedomain *voltagedomains_omap4[] __initdata = {
+	&omap4_voltdm_mpu,
+	&omap4_voltdm_iva,
+	&omap4_voltdm_core,
+	&omap4_voltdm_wkup,
+	NULL,
+};
 
-	if (!cpu_is_omap44xx())
-		return 0;
+static const char *sys_clk_name __initdata = "sys_clkin_ck";
+
+void __init omap44xx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * XXX Will depend on the process, validation, and binning
 	 * for the currently-running IC
 	 */
-	omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
-	omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
-	omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+	omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
+	omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
+	omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
 
-	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
-				       omap4_vdd_info,
-				       ARRAY_SIZE(omap4_vdd_info));
+	for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
+
+	voltdm_init(voltagedomains_omap4);
 };
-core_initcall(omap44xx_voltage_early_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltage.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltage.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/voltage.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/voltage.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
 #include "vc.h"
 #include "vp.h"
 
+struct powerdomain;
+
 /* XXX document */
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2
@@ -32,29 +34,60 @@
 #define OMAP3_VOLTSETUP2	0xff
 
 /**
- * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
  * data
  * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
  * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
- * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
  *
  * XXX What about VOLTOFFSET/VOLTCTRL?
- * XXX It is not necessary to have both a _mask and a _shift for the same
- *     bitfield - remove one!
  */
-struct omap_vfsm_instance_data {
+struct omap_vfsm_instance {
 	u32 voltsetup_mask;
 	u8 voltsetup_reg;
-	u8 voltsetup_shift;
 };
 
 /**
  * struct voltagedomain - omap voltage domain global structure.
- * @name:	Name of the voltage domain which can be used as a unique
- *		identifier.
+ * @name: Name of the voltage domain which can be used as a unique identifier.
+ * @scalable: Whether or not this voltage domain is scalable
+ * @node: list_head linking all voltage domains
+ * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
+ * @vc: pointer to VC channel associated with this voltagedomain
+ * @vp: pointer to VP associated with this voltagedomain
+ * @read: read a VC/VP register
+ * @write: write a VC/VP register
+ * @read: read-modify-write a VC/VP register
+ * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @scale: function used to scale the voltage of the voltagedomain
+ * @nominal_volt: current nominal voltage for this voltage domain
+ * @volt_data: voltage table having the distinct voltages supported
+ *             by the domain and other associated per voltage data.
  */
 struct voltagedomain {
 	char *name;
+	bool scalable;
+	struct list_head node;
+	struct list_head pwrdm_list;
+	struct omap_vc_channel *vc;
+	const struct omap_vfsm_instance *vfsm;
+	struct omap_vp_instance *vp;
+	struct omap_voltdm_pmic *pmic;
+
+	/* VC/VP register access functions: SoC specific */
+	u32 (*read) (u8 offset);
+	void (*write) (u32 val, u8 offset);
+	u32 (*rmw)(u32 mask, u32 bits, u8 offset);
+
+	union {
+		const char *name;
+		u32 rate;
+	} sys_clk;
+
+	int (*scale) (struct voltagedomain *voltdm,
+		      unsigned long target_volt);
+
+	u32 nominal_volt;
+	struct omap_volt_data *volt_data;
 };
 
 /**
@@ -77,13 +110,18 @@ struct omap_volt_data {
 };
 
 /**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate:	PMIC slew rate (in uv/us)
  * @step_size:	PMIC voltage step size (in uv)
+ * @i2c_slave_addr: I2C slave address of PMIC
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
+ * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
+ * @i2c_mcode: master code value for I2C high-speed preamble transmission
  * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
  * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
  */
-struct omap_volt_pmic_info {
+struct omap_voltdm_pmic {
 	int slew_rate;
 	int step_size;
 	u32 on_volt;
@@ -91,94 +129,44 @@ struct omap_volt_pmic_info {
 	u32 ret_volt;
 	u32 off_volt;
 	u16 volt_setup_time;
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
 	u8 vp_erroroffset;
 	u8 vp_vstepmin;
 	u8 vp_vstepmax;
 	u8 vp_vddmin;
 	u8 vp_vddmax;
 	u8 vp_timeout_us;
-	u8 i2c_slave_addr;
-	u8 pmic_reg;
+	bool i2c_high_speed;
+	u8 i2c_mcode;
 	unsigned long (*vsel_to_uv) (const u8 vsel);
 	u8 (*uv_to_vsel) (unsigned long uV);
 };
 
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data		: voltage table having the distinct voltages supported
- *			  by the domain and other associated per voltage data.
- * @pmic_info		: pmic specific parameters which should be populted by
- *			  the pmic drivers.
- * @vp_data		: the register values, shifts, masks for various
- *			  vp registers
- * @vp_rt_data          : VP data derived at runtime, not predefined
- * @vc_data		: structure containing various various vc registers,
- *			  shifts, masks etc.
- * @vfsm                : voltage manager FSM data
- * @voltdm		: pointer to the voltage domain structure
- * @debug_dir		: debug directory for this voltage domain.
- * @curr_volt		: current voltage for this vdd.
- * @vp_enabled		: flag to keep track of whether vp is enabled or not
- * @volt_scale		: API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
-	struct omap_volt_data *volt_data;
-	struct omap_volt_pmic_info *pmic_info;
-	struct omap_vp_instance_data *vp_data;
-	struct omap_vp_runtime_data vp_rt_data;
-	struct omap_vc_instance_data *vc_data;
-	const struct omap_vfsm_instance_data *vfsm;
-	struct voltagedomain voltdm;
-	struct dentry *debug_dir;
-	u32 curr_volt;
-	bool vp_enabled;
-	u32 (*read_reg) (u16 mod, u8 offset);
-	void (*write_reg) (u32 val, u16 mod, u8 offset);
-	int (*volt_scale) (struct omap_vdd_info *vdd,
-		unsigned long target_volt);
-};
-
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt);
-void omap_voltage_reset(struct voltagedomain *voltdm);
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
 		struct omap_volt_data **volt_data);
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
 		unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
-				   struct omap_vdd_info *omap_vdd_array[],
-				   u8 omap_vdd_count);
-#ifdef CONFIG_PM
 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info);
+			       struct omap_voltdm_pmic *pmic);
 void omap_change_voltscale_method(struct voltagedomain *voltdm,
 		int voltscale_method);
-/* API to get the voltagedomain pointer */
-struct voltagedomain *omap_voltage_domain_lookup(char *name);
-
 int omap_voltage_late_init(void);
-#else
-static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
-{
-	return -EINVAL;
-}
-static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method) {}
-static inline int omap_voltage_late_init(void)
-{
-	return -EINVAL;
-}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
-{
-	return ERR_PTR(-EINVAL);
-}
-#endif
 
+extern void omap2xxx_voltagedomains_init(void);
+extern void omap3xxx_voltagedomains_init(void);
+extern void omap44xx_voltagedomains_init(void);
+
+struct voltagedomain *voltdm_lookup(const char *name);
+void voltdm_init(struct voltagedomain **voltdm_list);
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user);
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm));
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+void voltdm_reset(struct voltagedomain *voltdm);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp3xxx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp3xxx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,16 +25,20 @@
 #include "voltage.h"
 
 #include "vp.h"
+#include "prm2xxx_3xxx.h"
+
+static const struct omap_vp_ops omap3_vp_ops = {
+	.check_txdone = omap3_prm_vp_check_txdone,
+	.clear_txdone = omap3_prm_vp_clear_txdone,
+};
 
 /*
  * VP data common to 34xx/36xx chips
  * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
  */
-static const struct omap_vp_common_data omap3_vp_common = {
-	.vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap3_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
 	.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
-	.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
-	.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
 	.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
 	.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
 	.vpconfig_initvdd = OMAP3430_INITVDD_MASK,
@@ -47,36 +51,29 @@ static const struct omap_vp_common_data
 	.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
-};
+	.vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
 
-static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
-	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	.ops = &omap3_vp_ops,
 };
 
-struct omap_vp_instance_data omap3_vp1_data = {
-	.vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_mpu = {
+	.id = OMAP3_VP_VDD_MPU_ID,
+	.common = &omap3_vp_common,
 	.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
 	.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
 	.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
 	.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap3_vp1_prm_irqst_data,
 };
 
-static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
-	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap3_vp2_data = {
-	.vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_core = {
+	.id = OMAP3_VP_VDD_CORE_ID,
+	.common = &omap3_vp_common,
 	.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
 	.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
 	.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
 	.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap3_vp2_prm_irqst_data,
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp44xx_data.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp44xx_data.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,15 +27,18 @@
 
 #include "vp.h"
 
+static const struct omap_vp_ops omap4_vp_ops = {
+	.check_txdone = omap4_prm_vp_check_txdone,
+	.clear_txdone = omap4_prm_vp_clear_txdone,
+};
+
 /*
  * VP data common to 44xx chips
  * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
  */
-static const struct omap_vp_common_data omap4_vp_common = {
-	.vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap4_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
 	.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
-	.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
-	.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
 	.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
 	.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
 	.vpconfig_initvdd = OMAP4430_INITVDD_MASK,
@@ -48,53 +51,39 @@ static const struct omap_vp_common_data
 	.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+	.vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
+	.ops = &omap4_vp_ops,
 };
 
-static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
-	.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_mpu_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_mpu = {
+	.id = OMAP4_VP_VDD_MPU_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
 };
 
-static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_iva_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_iva = {
+	.id = OMAP4_VP_VDD_IVA_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
 };
 
-static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_core_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_core = {
+	.id = OMAP4_VP_VDD_CORE_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_core_prm_irqst_data,
 };
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp.c linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,278 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	char vsel;
+
+	vsel = voltdm->pmic->uv_to_vsel(volt);
+
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
+		      vp->common->vpconfig_forceupdate |
+		      vp->common->vpconfig_initvdd);
+	vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
+		       vp->vpconfig);
+
+	/* Clear initVDD copy trigger bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return vpconfig;
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 val, sys_clk_rate, timeout, waittime;
+	u32 vddmin, vddmax, vstepmin, vstepmax;
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vp->enabled = false;
+
+	/* Divide to avoid overflow */
+	sys_clk_rate = voltdm->sys_clk.rate / 1000;
+
+	timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
+	vddmin = voltdm->pmic->vp_vddmin;
+	vddmax = voltdm->pmic->vp_vddmax;
+
+	waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
+		    sys_clk_rate) / 1000;
+	vstepmin = voltdm->pmic->vp_vstepmin;
+	vstepmax = voltdm->pmic->vp_vstepmax;
+
+	/*
+	 * VP_CONFIG: error gain is not set here, it will be updated
+	 * on each scale, based on OPP.
+	 */
+	val = (voltdm->pmic->vp_erroroffset <<
+	       __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
+		vp->common->vpconfig_timeouten;
+	voltdm->write(val, vp->vpconfig);
+
+	/* VSTEPMIN */
+	val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
+		(vstepmin <<  vp->common->vstepmin_stepmin_shift);
+	voltdm->write(val, vp->vstepmin);
+
+	/* VSTEPMAX */
+	val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
+		(waittime << vp->common->vstepmax_smpswaittimemax_shift);
+	voltdm->write(val, vp->vstepmax);
+
+	/* VLIMITTO */
+	val = (vddmax << vp->common->vlimitto_vddmax_shift) |
+		(vddmin << vp->common->vlimitto_vddmin_shift) |
+		(timeout <<  vp->common->vlimitto_timeout_shift);
+	voltdm->write(val, vp->vlimitto);
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt)
+{
+	struct omap_volt_data *volt_data;
+
+	if (!voltdm->vp)
+		return -EINVAL;
+
+	/* Get volt_data corresponding to target_volt */
+	volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+	if (IS_ERR(volt_data))
+		return -EINVAL;
+
+	/* Setting vp errorgain based on the voltage */
+	voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
+		    volt_data->vp_errgain <<
+		    __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
+		    voltdm->vp->vpconfig);
+
+	return 0;
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	u8 target_vsel, current_vsel;
+	int ret, timeout = 0;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+			"Voltage change aborted", __func__, voltdm->name);
+		return -ETIMEDOUT;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, target_volt);
+
+	/* Force update of voltage */
+	voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
+		      voltdm->vp->vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout(vp->common->ops->check_txdone(vp->id),
+			  VP_TRANXDONE_TIMEOUT, timeout);
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+			"TRANXDONE never got set after the voltage update\n",
+			__func__, voltdm->name);
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+	/*
+	 * Disable TransactionDone interrupt , clear all status, clear
+	 * control registers
+	 */
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+			"to clear the TRANXDONE status\n",
+			__func__, voltdm->name);
+
+	/* Clear force bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return 0;
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig, volt;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already enabled, do nothing. Return */
+	if (vp->enabled)
+		return;
+
+	volt = voltdm_get_voltage(voltdm);
+	if (!volt) {
+		pr_warning("%s: unable to find current voltage for %s\n",
+			   __func__, voltdm->name);
+		return;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, volt);
+
+	/* Enable VP */
+	vpconfig |= vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	vp->enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig;
+	int timeout;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already disabled, do nothing. Return */
+	if (!vp->enabled) {
+		pr_warning("%s: Trying to disable VP for vdd_%s when"
+			"it is already disabled\n", __func__, voltdm->name);
+		return;
+	}
+
+	/* Disable VP */
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	omap_test_timeout((voltdm->read(vp->vstatus)),
+			  VP_IDLE_TIMEOUT, timeout);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("%s: vdd_%s idle timedout\n",
+			__func__, voltdm->name);
+
+	vp->enabled = false;
+
+	return;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp.h linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp.h
--- linux-libre-3.1-gnu1/arch/arm/mach-omap2/vp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-omap2/vp.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,44 +19,60 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
+/*
+ * Voltage Processor (VP) identifiers
+ */
+#define OMAP3_VP_VDD_MPU_ID 0
+#define OMAP3_VP_VDD_CORE_ID 1
+#define OMAP4_VP_VDD_CORE_ID 0
+#define OMAP4_VP_VDD_IVA_ID 1
+#define OMAP4_VP_VDD_MPU_ID 2
+
 /* XXX document */
 #define VP_IDLE_TIMEOUT		200
 #define VP_TRANXDONE_TIMEOUT	300
 
+/**
+ * struct omap_vp_ops - per-VP operations
+ * @check_txdone: check for VP transaction done
+ * @clear_txdone: clear VP transaction done status
+ */
+struct omap_vp_ops {
+	u32 (*check_txdone)(u8 vp_id);
+	void (*clear_txdone)(u8 vp_id);
+};
 
 /**
- * struct omap_vp_common_data - register data common to all VDDs
+ * struct omap_vp_common - register data common to all VDDs
+ * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
- * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
  * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
  * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
- * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
- * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
- * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
- * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
- * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
- *
- * XXX It it not necessary to have both a mask and a shift for the same
- *     bitfield - remove one
- * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
  */
-struct omap_vp_common_data {
+struct omap_vp_common {
+	u32 vpconfig_erroroffset_mask;
 	u32 vpconfig_errorgain_mask;
 	u32 vpconfig_initvoltage_mask;
-	u32 vpconfig_timeouten;
-	u32 vpconfig_initvdd;
-	u32 vpconfig_forceupdate;
-	u32 vpconfig_vpenable;
-	u8 vpconfig_erroroffset_shift;
-	u8 vpconfig_errorgain_shift;
-	u8 vpconfig_initvoltage_shift;
+	u8 vpconfig_timeouten;
+	u8 vpconfig_initvdd;
+	u8 vpconfig_forceupdate;
+	u8 vpconfig_vpenable;
 	u8 vstepmin_stepmin_shift;
 	u8 vstepmin_smpswaittimemin_shift;
 	u8 vstepmax_stepmax_shift;
@@ -64,80 +80,49 @@ struct omap_vp_common_data {
 	u8 vlimitto_vddmin_shift;
 	u8 vlimitto_vddmax_shift;
 	u8 vlimitto_timeout_shift;
-};
+	u8 vpvoltage_mask;
 
-/**
- * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
- * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
- * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
- *
- * XXX prm_irqst_reg does not belong here
- * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
- *     hardware bug
- * XXX This structure is probably not needed
- */
-struct omap_vp_prm_irqst_data {
-	u8 prm_irqst_reg;
-	u32 tranxdone_status;
+	const struct omap_vp_ops *ops;
 };
 
 /**
- * struct omap_vp_instance_data - VP register offsets (per-VDD)
- * @vp_common: pointer to struct omap_vp_common_data * for this SoC
- * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * struct omap_vp_instance - VP register offsets (per-VDD)
+ * @common: pointer to struct omap_vp_common * for this SoC
  * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
  * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
  * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
  * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
  * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ * @id: Unique identifier for VP instance.
+ * @enabled: flag to keep track of whether vp is enabled or not
  *
  * XXX vp_common is probably not needed since it is per-SoC
  */
-struct omap_vp_instance_data {
-	const struct omap_vp_common_data *vp_common;
-	const struct omap_vp_prm_irqst_data *prm_irqst_data;
+struct omap_vp_instance {
+	const struct omap_vp_common *common;
 	u8 vpconfig;
 	u8 vstepmin;
 	u8 vstepmax;
 	u8 vlimitto;
 	u8 vstatus;
 	u8 voltage;
+	u8 id;
+	bool enabled;
 };
 
-/**
- * struct omap_vp_runtime_data - VP data populated at runtime by code
- * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
- * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
- * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
- * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
- * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
- *
- * XXX Is this structure really needed?  Why not just program the
- * device directly?  They are in PRM space, therefore in the WKUP
- * powerdomain, so register contents should not be lost in off-mode.
- * XXX Some of these fields are incorrectly named, e.g., vstep*
- */
-struct omap_vp_runtime_data {
-	u32 vpconfig_erroroffset;
-	u16 vpconfig_errorgain;
-	u16 vstepmin_smpswaittimemin;
-	u16 vstepmax_smpswaittimemax;
-	u16 vlimitto_timeout;
-	u8 vstepmin_stepmin;
-	u8 vstepmax_stepmax;
-	u8 vlimitto_vddmin;
-	u8 vlimitto_vddmax;
-};
+extern struct omap_vp_instance omap3_vp_mpu;
+extern struct omap_vp_instance omap3_vp_core;
 
-extern struct omap_vp_instance_data omap3_vp1_data;
-extern struct omap_vp_instance_data omap3_vp2_data;
+extern struct omap_vp_instance omap4_vp_mpu;
+extern struct omap_vp_instance omap4_vp_iva;
+extern struct omap_vp_instance omap4_vp_core;
 
-extern struct omap_vp_instance_data omap4_vp_mpu_data;
-extern struct omap_vp_instance_data omap4_vp_iva_data;
-extern struct omap_vp_instance_data omap4_vp_core_data;
+void omap_vp_init(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt);
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/common.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -308,8 +308,8 @@ void __init orion5x_init(void)
  * Many orion-based systems have buggy bootloader implementations.
  * This is a common fixup for bogus memory tags.
  */
-void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
-			    char **from, struct meminfo *meminfo)
+void __init tag_fixup_mem32(struct tag *t, char **from,
+			    struct meminfo *meminfo)
 {
 	for (; t->hdr.size; t = tag_next(t))
 		if (t->hdr.tag == ATAG_MEM &&
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/common.h linux-libre-3.2-gnu1/arch/arm/mach-orion5x/common.h
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,9 @@ int orion5x_pci_sys_setup(int nr, struct
 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
 int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
-struct machine_desc;
 struct meminfo;
 struct tag;
-extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
-				   char **, struct meminfo *);
+extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
 
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/d2net-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/d2net-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/d2net-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/d2net-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,7 +336,7 @@ static void __init d2net_init(void)
 
 #ifdef CONFIG_MACH_D2NET
 MACHINE_START(D2NET, "LaCie d2 Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
@@ -348,7 +348,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_BIGDISK
 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/db88f5281-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/db88f5281-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/db88f5281-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/db88f5281-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -359,7 +358,7 @@ static void __init db88f5281_init(void)
 
 MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
 	/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db88f5281_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/dns323-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/dns323-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/dns323-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/dns323-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * License, or (at your option) any later version.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -30,7 +30,6 @@
 #include <linux/phy.h>
 #include <linux/marvell_phy.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -730,7 +729,7 @@ static void __init dns323_init(void)
 /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(DNS323, "D-Link DNS-323")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dns323_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/edmini_v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/edmini_v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/edmini_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/edmini_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,7 +251,7 @@ static void __init edmini_v2_init(void)
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
 	/* Maintainer: Christopher Moore <moore@free.fr> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= edmini_v2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-orion5x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 
 #include <mach/orion5x.h>
 
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
 	ldr	\rp, =ORION5X_REGS_PHYS_BASE
 	ldr	\rv, =ORION5X_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-orion5x/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/memory.h
- *
- * Marvell Orion memory definitions
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/irq.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,12 +9,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
 #include "common.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/kurobox_pro-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/kurobox_pro-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/kurobox_pro-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/kurobox_pro-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/serial_reg.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -380,7 +379,7 @@ static void __init kurobox_pro_init(void
 #ifdef CONFIG_MACH_KUROBOX_PRO
 MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
@@ -393,7 +392,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_LINKSTATION_PRO
 MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -318,7 +318,7 @@ static void __init lschl_init(void)
 
 MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
 	/* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= lschl_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ls_hgl-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ls_hgl-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ls_hgl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ls_hgl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,7 +265,7 @@ static void __init ls_hgl_init(void)
 
 MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
 	/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ls_hgl_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/lsmini-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/lsmini-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/lsmini-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/lsmini-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,7 +267,7 @@ static void __init lsmini_init(void)
 #ifdef CONFIG_MACH_LINKSTATION_MINI
 MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
 	/* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= lsmini_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-orion5x/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/mss2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/mss2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/mss2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/mss2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -261,7 +261,7 @@ static void __init mss2_init(void)
 
 MACHINE_START(MSS2, "Maxtor Shared Storage II")
 	/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mss2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/mv2120-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/mv2120-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/mv2120-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/mv2120-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/i2c.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <mach/orion5x.h>
 #include "common.h"
@@ -229,7 +228,7 @@ static void __init mv2120_init(void)
 /* Warning: HP uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(MV2120, "HP Media Vault mv2120")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mv2120_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/net2big-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/net2big-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/net2big-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/net2big-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -419,7 +419,7 @@ static void __init net2big_init(void)
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(NET2BIG, "LaCie 2Big Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= net2big_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -18,7 +18,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -169,7 +168,7 @@ subsys_initcall(rd88f5181l_fxo_pci_init)
 
 MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
 	/* Maintainer: Nicolas Pitre <nico@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5181l_fxo_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -19,7 +19,6 @@
 #include <linux/i2c.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -181,7 +180,7 @@ subsys_initcall(rd88f5181l_ge_pci_init);
 
 MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5181l_ge_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5182-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5182-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f5182-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f5182-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/ata_platform.h>
 #include <linux/i2c.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -306,7 +305,7 @@ static void __init rd88f5182_init(void)
 
 MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5182_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -122,7 +121,7 @@ subsys_initcall(rd88f6183ap_ge_pci_init)
 
 MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6183ap_ge_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/terastation_pro2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/terastation_pro2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/terastation_pro2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/terastation_pro2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/i2c.h>
 #include <linux/serial_reg.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -358,7 +357,7 @@ static void __init tsp2_init(void)
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= tsp2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts209-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts209-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts209-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts209-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -23,7 +23,6 @@
 #include <linux/serial_reg.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -323,7 +322,7 @@ static void __init qnap_ts209_init(void)
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts209_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts409-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts409-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts409-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts409-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -25,7 +25,6 @@
 #include <linux/i2c.h>
 #include <linux/serial_reg.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -312,7 +311,7 @@ static void __init qnap_ts409_init(void)
 
 MACHINE_START(TS409, "QNAP TS-409")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts409_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts78xx-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts78xx-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/ts78xx-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/ts78xx-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -275,7 +275,7 @@ static struct platform_nand_data ts78xx_
 		.partitions		= ts78xx_ts_nand_parts,
 		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
 		.chip_delay		= 15,
-		.options		= NAND_USE_FLASH_BBT,
+		.bbt_options		= NAND_BBT_USE_FLASH,
 	},
 	.ctrl	= {
 		/*
@@ -621,7 +621,7 @@ static void __init ts78xx_init(void)
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
 	/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ts78xx_init,
 	.map_io		= ts78xx_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/wnr854t-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/wnr854t-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/wnr854t-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/wnr854t-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -17,7 +17,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -173,7 +172,7 @@ subsys_initcall(wnr854t_pci_init);
 
 MACHINE_START(WNR854T, "Netgear WNR854T")
 	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wnr854t_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-orion5x/wrt350n-v2-setup.c linux-libre-3.2-gnu1/arch/arm/mach-orion5x/wrt350n-v2-setup.c
--- linux-libre-3.1-gnu1/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/input.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -261,7 +260,7 @@ subsys_initcall(wrt350n_v2_pci_init);
 
 MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wrt350n_v2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/common.c linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+static void __init picoxcell_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *picoxcell_dt_match[] = {
+	"picochip,pc3x2",
+	"picochip,pc3x3",
+	NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+	{ .compatible = "arm,pl192-vic" },
+	{ /* Sentinel */ }
+};
+
+static void __init picoxcell_init_irq(void)
+{
+	vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
+	vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
+}
+
+DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
+	.map_io		= picoxcell_map_io,
+	.nr_irqs	= ARCH_NR_IRQS,
+	.init_irq	= picoxcell_init_irq,
+	.timer		= &picoxcell_timer,
+	.init_machine	= picoxcell_init_machine,
+	.dt_compat	= picoxcell_dt_match,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/common.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/common.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#ifndef __PICOXCELL_COMMON_H__
+#define __PICOXCELL_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer picoxcell_timer;
+extern void picoxcell_map_io(void);
+
+#endif /* __PICOXCELL_COMMON_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#define UART_SHIFT 2
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+		ldr	\rp, =PICOXCELL_UART1_BASE
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		/* The UART's don't have any flow control IO's wired up. */
+		.macro	waituart,rd,rx
+		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * entry-macro.S
+ *
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Low-level IRQ helper macros for picoXcell platforms
+ *
+ * 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 <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#define VA_VIC0		IO_ADDRESS(PICOXCELL_VIC0_BASE)
+#define VA_VIC1		IO_ADDRESS(PICOXCELL_VIC1_BASE)
+
+#include <asm/entry-macro-vic2.S>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/picoxcell_soc.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No ioports, but needed for driver compatibility. */
+#define __io(a)			__typesafe_io(a)
+/* No PCI possible on picoxcell. */
+#define __mem_pci(a)		(a)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_IRQS			64
+#define NR_IRQS				(128 + ARCH_NR_IRQS)
+
+#define IRQ_VIC0_BASE			0
+#define IRQ_VIC1_BASE			32
+
+#endif /* __MACH_IRQS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_MAP_H__
+#define __PICOXCELL_MAP_H__
+
+#define PHYS_TO_IO(x)		(((x) & 0x00ffffff) | 0xfe000000)
+
+#ifdef __ASSEMBLY__
+#define IO_ADDRESS(x)		PHYS_TO_IO((x))
+#else
+#define IO_ADDRESS(x)		(void __iomem __force *)(PHYS_TO_IO((x)))
+#endif
+
+#endif /* __PICOXCELL_MAP_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_SOC_H__
+#define __PICOXCELL_SOC_H__
+
+#define PICOXCELL_UART1_BASE		0x80230000
+#define PICOXCELL_PERIPH_BASE		0x80000000
+#define PICOXCELL_PERIPH_LENGTH		SZ_4M
+#define PICOXCELL_VIC0_BASE		0x80060000
+#define PICOXCELL_VIC1_BASE		0x80064000
+
+#endif /* __PICOXCELL_SOC_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching and wait for interrupt
+	 * tricks.
+	 */
+	cpu_do_idle();
+}
+
+static inline void arch_reset(int mode, const char *cmd)
+{
+	/* Watchdog reset to go here. */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/timex.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/timex.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __TIMEX_H__
+#define __TIMEX_H__
+
+/* Bogus value to allow the kernel to compile. */
+#define CLOCK_TICK_RATE		1000000
+
+#endif /* __TIMEX_H__ */
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/vmalloc.h linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/vmalloc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#define VMALLOC_END	0xfe000000UL
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/io.c linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/io.c
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/io.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+void __init picoxcell_map_io(void)
+{
+	struct map_desc io_map = {
+		.virtual	= PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
+		.pfn		= __phys_to_pfn(PICOXCELL_PERIPH_BASE),
+		.length		= PICOXCELL_PERIPH_LENGTH,
+		.type		= MT_DEVICE,
+	};
+
+	iotable_init(&io_map, 1);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/Makefile linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3 @@
+obj-y	:= common.o
+obj-y	+= time.o
+obj-y	+= io.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/time.c linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/time.c
--- linux-libre-3.1-gnu1/arch/arm/mach-picoxcell/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-picoxcell/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+#include "common.h"
+
+static void timer_get_base_and_rate(struct device_node *np,
+				    void __iomem **base, u32 *rate)
+{
+	*base = of_iomap(np, 0);
+
+	if (!*base)
+		panic("Unable to map regs for %s", np->name);
+
+	if (of_property_read_u32(np, "clock-freq", rate))
+		panic("No clock-freq property for %s", np->name);
+}
+
+static void picoxcell_add_clockevent(struct device_node *event_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clock_event_device *ced;
+	u32 irq, rate;
+
+	irq = irq_of_parse_and_map(event_timer, 0);
+	if (irq == NO_IRQ)
+		panic("No IRQ for clock event timer");
+
+	timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+	ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+				     rate);
+	if (!ced)
+		panic("Unable to initialise clockevent device");
+
+	dw_apb_clockevent_register(ced);
+}
+
+static void picoxcell_add_clocksource(struct device_node *source_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clocksource *cs;
+	u32 rate;
+
+	timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+	cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+	if (!cs)
+		panic("Unable to initialise clocksource device");
+
+	dw_apb_clocksource_start(cs);
+	dw_apb_clocksource_register(cs);
+}
+
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *sched_io_base;
+
+unsigned long long notrace sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace picoxcell_update_sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-rtc" },
+	{ /* Sentinel */ },
+};
+
+static void picoxcell_init_sched_clock(void)
+{
+	struct device_node *sched_timer;
+	u32 rate;
+
+	sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+	if (!sched_timer)
+		panic("No RTC for sched clock to use");
+
+	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+	of_node_put(sched_timer);
+
+	init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
+}
+
+static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-timer" },
+	{},
+};
+
+static void __init picoxcell_timer_init(void)
+{
+	struct device_node *event_timer, *source_timer;
+
+	event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+	if (!event_timer)
+		panic("No timer for clockevent");
+	picoxcell_add_clockevent(event_timer);
+
+	source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+	if (!source_timer)
+		panic("No timer for clocksource");
+	picoxcell_add_clocksource(source_timer);
+
+	of_node_put(source_timer);
+
+	picoxcell_init_sched_clock();
+}
+
+struct sys_timer picoxcell_timer = {
+	.init = picoxcell_timer_init,
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/core.c linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -264,7 +264,7 @@ extern struct sys_timer pnx4008_timer;
 
 MACHINE_START(PNX4008, "Philips PNX4008")
 	/* Maintainer: MontaVista Software Inc. */
-	.boot_params		= 0x80000100,
+	.atag_offset		= 0x100,
 	.map_io 		= pnx4008_map_io,
 	.init_irq 		= pnx4008_init_irq,
 	.init_machine 		= pnx4008_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,14 +13,13 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pnx4008.h>
 
 /* register definitions */
 #define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00090000
 		add	\rv, \rp, #0xf4000000	@ virtual
 		add	\rp, \rp, #0x40000000	@ physical
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/gpio.h
- *
- * PNX4008 GPIO driver - header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
- * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
- *
- * 2005 (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 _PNX4008_GPIO_H_
-#define _PNX4008_GPIO_H_
-
-
-/* Block numbers */
-#define GPIO_IN		(0)
-#define GPIO_OUT		(0x100)
-#define GPIO_BID		(0x200)
-#define GPIO_RAM		(0x300)
-#define GPIO_MUX		(0x400)
-
-#define GPIO_TYPE_MASK(K) ((K) & 0x700)
-
-/* INPUT GPIOs */
-/* GPI */
-#define GPI_00		(GPIO_IN | 0)
-#define GPI_01		(GPIO_IN | 1)
-#define GPI_02   	(GPIO_IN | 2)
-#define GPI_03 	 	(GPIO_IN | 3)
-#define GPI_04   	(GPIO_IN | 4)
-#define GPI_05   	(GPIO_IN | 5)
-#define GPI_06   	(GPIO_IN | 6)
-#define GPI_07   	(GPIO_IN | 7)
-#define GPI_08   	(GPIO_IN | 8)
-#define GPI_09   	(GPIO_IN | 9)
-#define U1_RX 		(GPIO_IN | 15)
-#define U2_HTCS 	(GPIO_IN | 16)
-#define U2_RX	 	(GPIO_IN | 17)
-#define U3_RX		(GPIO_IN | 18)
-#define U4_RX		(GPIO_IN | 19)
-#define U5_RX		(GPIO_IN | 20)
-#define U6_IRRX 	(GPIO_IN | 21)
-#define U7_HCTS 	(GPIO_IN | 22)
-#define U7_RX		(GPIO_IN | 23)
-/* MISC IN */
-#define SPI1_DATIN	(GPIO_IN | 25)
-#define DISP_SYNC	(GPIO_IN | 26)
-#define SPI2_DATIN	(GPIO_IN | 27)
-#define GPI_11  	(GPIO_IN | 28)
-
-#define GPIO_IN_MASK   0x1eff83ff
-
-/* OUTPUT GPIOs */
-/* GPO */
-#define GPO_00		(GPIO_OUT | 0)
-#define GPO_01   	(GPIO_OUT | 1)
-#define GPO_02   	(GPIO_OUT | 2)
-#define GPO_03 	 	(GPIO_OUT | 3)
-#define GPO_04   	(GPIO_OUT | 4)
-#define GPO_05   	(GPIO_OUT | 5)
-#define GPO_06   	(GPIO_OUT | 6)
-#define GPO_07   	(GPIO_OUT | 7)
-#define GPO_08		(GPIO_OUT | 8)
-#define GPO_09   	(GPIO_OUT | 9)
-#define GPO_10   	(GPIO_OUT | 10)
-#define GPO_11 	 	(GPIO_OUT | 11)
-#define GPO_12   	(GPIO_OUT | 12)
-#define GPO_13   	(GPIO_OUT | 13)
-#define GPO_14   	(GPIO_OUT | 14)
-#define GPO_15   	(GPIO_OUT | 15)
-#define GPO_16  	(GPIO_OUT | 16)
-#define GPO_17 	 	(GPIO_OUT | 17)
-#define GPO_18   	(GPIO_OUT | 18)
-#define GPO_19   	(GPIO_OUT | 19)
-#define GPO_20   	(GPIO_OUT | 20)
-#define GPO_21   	(GPIO_OUT | 21)
-#define GPO_22   	(GPIO_OUT | 22)
-#define GPO_23   	(GPIO_OUT | 23)
-
-#define GPIO_OUT_MASK   0xffffff
-
-/* BIDIRECTIONAL GPIOs */
-/* RAM pins */
-#define RAM_D19		(GPIO_RAM | 0)
-#define RAM_D20  	(GPIO_RAM | 1)
-#define RAM_D21  	(GPIO_RAM | 2)
-#define RAM_D22 	(GPIO_RAM | 3)
-#define RAM_D23  	(GPIO_RAM | 4)
-#define RAM_D24  	(GPIO_RAM | 5)
-#define RAM_D25  	(GPIO_RAM | 6)
-#define RAM_D26  	(GPIO_RAM | 7)
-#define RAM_D27		(GPIO_RAM | 8)
-#define RAM_D28  	(GPIO_RAM | 9)
-#define RAM_D29  	(GPIO_RAM | 10)
-#define RAM_D30 	(GPIO_RAM | 11)
-#define RAM_D31  	(GPIO_RAM | 12)
-
-#define GPIO_RAM_MASK   0x1fff
-
-/* I/O pins */
-#define GPIO_00  	(GPIO_BID | 25)
-#define GPIO_01 	(GPIO_BID | 26)
-#define GPIO_02  	(GPIO_BID | 27)
-#define GPIO_03  	(GPIO_BID | 28)
-#define GPIO_04 	(GPIO_BID | 29)
-#define GPIO_05  	(GPIO_BID | 30)
-
-#define GPIO_BID_MASK   0x7e000000
-
-/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
-#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
-
-#define GPIO_MUX_MASK   0x8
-
-/* Extraction/assembly macros */
-#define GPIO_BIT_MASK(K) ((K) & 0x1F)
-#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
-#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
-#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
-#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
-#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
-#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
-
-/* Start Enable Pin Interrupts - table 58 page 66 */
-
-#define SE_PIN_BASE_INT   32
-
-#define SE_U7_RX_INT            63
-#define SE_U7_HCTS_INT          62
-#define SE_BT_CLKREQ_INT        61
-#define SE_U6_IRRX_INT          60
-/*59 unused*/
-#define SE_U5_RX_INT            58
-#define SE_GPI_11_INT           57
-#define SE_U3_RX_INT            56
-#define SE_U2_HCTS_INT          55
-#define SE_U2_RX_INT            54
-#define SE_U1_RX_INT            53
-#define SE_DISP_SYNC_INT        52
-/*51 unused*/
-#define SE_SDIO_INT_N           50
-#define SE_MSDIO_START_INT      49
-#define SE_GPI_06_INT           48
-#define SE_GPI_05_INT           47
-#define SE_GPI_04_INT           46
-#define SE_GPI_03_INT           45
-#define SE_GPI_02_INT           44
-#define SE_GPI_01_INT           43
-#define SE_GPI_00_INT           42
-#define SE_SYSCLKEN_PIN_INT     41
-#define SE_SPI1_DATAIN_INT      40
-#define SE_GPI_07_INT           39
-#define SE_SPI2_DATAIN_INT      38
-#define SE_GPI_10_INT           37
-#define SE_GPI_09_INT           36
-#define SE_GPI_08_INT           35
-/*34-32 unused*/
-
-/* Start Enable Internal Interrupts - table 57 page 65 */
-
-#define SE_INT_BASE_INT   0
-
-#define SE_TS_IRQ               31
-#define SE_TS_P_INT             30
-#define SE_TS_AUX_INT           29
-/*27-28 unused*/
-#define SE_USB_AHB_NEED_CLK_INT 26
-#define SE_MSTIMER_INT          25
-#define SE_RTC_INT              24
-#define SE_USB_NEED_CLK_INT     23
-#define SE_USB_INT              22
-#define SE_USB_I2C_INT          21
-#define SE_USB_OTG_TIMER_INT    20
-#define SE_USB_OTG_ATX_INT_N    19
-/*18 unused*/
-#define SE_DSP_GPIO4_INT        17
-#define SE_KEY_IRQ              16
-#define SE_DSP_SLAVEPORT_INT    15
-#define SE_DSP_GPIO1_INT        14
-#define SE_DSP_GPIO0_INT        13
-#define SE_DSP_AHB_INT          12
-/*11-6 unused*/
-#define SE_GPIO_05_INT          5
-#define SE_GPIO_04_INT          4
-#define SE_GPIO_03_INT          3
-#define SE_GPIO_02_INT          2
-#define SE_GPIO_01_INT          1
-#define SE_GPIO_00_INT          0
-
-#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
-
-#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
-
-extern int pnx4008_gpio_register_pin(unsigned short pin);
-extern int pnx4008_gpio_unregister_pin(unsigned short pin);
-extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
-extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
-extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
-extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
-
-static inline void start_int_umask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_mask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_ack(u8 irq)
-{
-	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
-}
-
-static inline void start_int_set_falling_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-static inline void start_int_set_rising_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-#endif				/* _PNX4008_GPIO_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,241 @@
+/*
+ * arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (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 _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN		(0)
+#define GPIO_OUT		(0x100)
+#define GPIO_BID		(0x200)
+#define GPIO_RAM		(0x300)
+#define GPIO_MUX		(0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00		(GPIO_IN | 0)
+#define GPI_01		(GPIO_IN | 1)
+#define GPI_02   	(GPIO_IN | 2)
+#define GPI_03 	 	(GPIO_IN | 3)
+#define GPI_04   	(GPIO_IN | 4)
+#define GPI_05   	(GPIO_IN | 5)
+#define GPI_06   	(GPIO_IN | 6)
+#define GPI_07   	(GPIO_IN | 7)
+#define GPI_08   	(GPIO_IN | 8)
+#define GPI_09   	(GPIO_IN | 9)
+#define U1_RX 		(GPIO_IN | 15)
+#define U2_HTCS 	(GPIO_IN | 16)
+#define U2_RX	 	(GPIO_IN | 17)
+#define U3_RX		(GPIO_IN | 18)
+#define U4_RX		(GPIO_IN | 19)
+#define U5_RX		(GPIO_IN | 20)
+#define U6_IRRX 	(GPIO_IN | 21)
+#define U7_HCTS 	(GPIO_IN | 22)
+#define U7_RX		(GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN	(GPIO_IN | 25)
+#define DISP_SYNC	(GPIO_IN | 26)
+#define SPI2_DATIN	(GPIO_IN | 27)
+#define GPI_11  	(GPIO_IN | 28)
+
+#define GPIO_IN_MASK   0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00		(GPIO_OUT | 0)
+#define GPO_01   	(GPIO_OUT | 1)
+#define GPO_02   	(GPIO_OUT | 2)
+#define GPO_03 	 	(GPIO_OUT | 3)
+#define GPO_04   	(GPIO_OUT | 4)
+#define GPO_05   	(GPIO_OUT | 5)
+#define GPO_06   	(GPIO_OUT | 6)
+#define GPO_07   	(GPIO_OUT | 7)
+#define GPO_08		(GPIO_OUT | 8)
+#define GPO_09   	(GPIO_OUT | 9)
+#define GPO_10   	(GPIO_OUT | 10)
+#define GPO_11 	 	(GPIO_OUT | 11)
+#define GPO_12   	(GPIO_OUT | 12)
+#define GPO_13   	(GPIO_OUT | 13)
+#define GPO_14   	(GPIO_OUT | 14)
+#define GPO_15   	(GPIO_OUT | 15)
+#define GPO_16  	(GPIO_OUT | 16)
+#define GPO_17 	 	(GPIO_OUT | 17)
+#define GPO_18   	(GPIO_OUT | 18)
+#define GPO_19   	(GPIO_OUT | 19)
+#define GPO_20   	(GPIO_OUT | 20)
+#define GPO_21   	(GPIO_OUT | 21)
+#define GPO_22   	(GPIO_OUT | 22)
+#define GPO_23   	(GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK   0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19		(GPIO_RAM | 0)
+#define RAM_D20  	(GPIO_RAM | 1)
+#define RAM_D21  	(GPIO_RAM | 2)
+#define RAM_D22 	(GPIO_RAM | 3)
+#define RAM_D23  	(GPIO_RAM | 4)
+#define RAM_D24  	(GPIO_RAM | 5)
+#define RAM_D25  	(GPIO_RAM | 6)
+#define RAM_D26  	(GPIO_RAM | 7)
+#define RAM_D27		(GPIO_RAM | 8)
+#define RAM_D28  	(GPIO_RAM | 9)
+#define RAM_D29  	(GPIO_RAM | 10)
+#define RAM_D30 	(GPIO_RAM | 11)
+#define RAM_D31  	(GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK   0x1fff
+
+/* I/O pins */
+#define GPIO_00  	(GPIO_BID | 25)
+#define GPIO_01 	(GPIO_BID | 26)
+#define GPIO_02  	(GPIO_BID | 27)
+#define GPIO_03  	(GPIO_BID | 28)
+#define GPIO_04 	(GPIO_BID | 29)
+#define GPIO_05  	(GPIO_BID | 30)
+
+#define GPIO_BID_MASK   0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK   0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+#define SE_USB_OTG_ATX_INT_N    19
+/*18 unused*/
+#define SE_DSP_GPIO4_INT        17
+#define SE_KEY_IRQ              16
+#define SE_DSP_SLAVEPORT_INT    15
+#define SE_DSP_GPIO1_INT        14
+#define SE_DSP_GPIO0_INT        13
+#define SE_DSP_AHB_INT          12
+/*11-6 unused*/
+#define SE_GPIO_05_INT          5
+#define SE_GPIO_04_INT          4
+#define SE_GPIO_03_INT          3
+#define SE_GPIO_02_INT          2
+#define SE_GPIO_01_INT          1
+#define SE_GPIO_00_INT          0
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+static inline void start_int_umask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif				/* _PNX4008_GPIO_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/memory.h
- *
- * Copyright (c) 2005 Philips Semiconductors
- * Copyright (c) 2005 MontaVista Software, Inc.
- *
- *  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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x80000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y		:= 0x80008000
+   zreladdr-y		+= 0x80008000
 params_phys-y		:= 0x80000100
 initrd_phys-y		:= 0x80800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/serial.c linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/serial.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pnx4008/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pnx4008/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *  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/types.h>
 #include <linux/io.h>
@@ -19,8 +18,8 @@
 
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <mach/gpio.h>
 
+#include <mach/gpio-pnx4008.h>
 #include <mach/clock.h>
 
 #define UART_3		0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/clock.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -350,10 +350,10 @@ static struct clk_lookup onchip_clks[] =
 		.clk = &clk_mem,
 	}, {
 		.dev_id = "sys",
-			.clk = &clk_sys,
+		.clk = &clk_sys,
 	}, {
 		.dev_id = "io",
-			.clk = &clk_io,
+		.clk = &clk_io,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-prima2/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 #include <mach/hardware.h>
 #include <mach/uart.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =SIRFSOC_UART1_PA_BASE		@ physical
 	ldr	\rv, =SIRFSOC_UART1_VA_BASE		@ virtual
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-prima2/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-prima2/include/mach/memory.h
- *
- * Copyright (c) 2010 â€“ 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET        UL(0x00000000)
-
-/*
- * Restrict DMA-able region to workaround silicon limitation.
- * The limitation restricts buffers available for DMA to SD/MMC
- * hardware to be below 256MB
- */
-#define ARM_DMA_ZONE_SIZE	(SZ_256M)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/irq.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 #include <asm/mach/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
 
 #define SIRFSOC_INT_RISC_MASK0          0x0018
 #define SIRFSOC_INT_RISC_MASK1          0x001C
@@ -66,7 +68,48 @@ void __init sirfsoc_of_irq_init(void)
 	if (!sirfsoc_intc_base)
 		panic("unable to map intc cpu registers\n");
 
+	irq_domain_add_simple(np, 0);
+
 	of_node_put(np);
 
 	sirfsoc_irq_init();
 }
+
+struct sirfsoc_irq_status {
+	u32 mask0;
+	u32 mask1;
+	u32 level0;
+	u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+	sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+	return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+	writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+	.suspend	= sirfsoc_irq_suspend,
+	.resume		= sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+	register_syscore_ops(&sirfsoc_irq_syscore_ops);
+	return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/l2x0.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/l2x0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,52 +8,24 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <mach/memory.h>
-
-#define L2X0_ADDR_FILTERING_START       0xC00
-#define L2X0_ADDR_FILTERING_END         0xC04
 
-static struct of_device_id l2x_ids[]  = {
-	{ .compatible = "arm,pl310-cache" },
+static struct of_device_id prima2_l2x0_ids[]  = {
+	{ .compatible = "sirf,prima2-pl310-cache" },
+	{},
 };
 
-static int __init sirfsoc_of_l2x_init(void)
+static int __init sirfsoc_l2x0_init(void)
 {
 	struct device_node *np;
-	void __iomem *sirfsoc_l2x_base;
-
-	np = of_find_matching_node(NULL, l2x_ids);
-	if (!np)
-		panic("unable to find compatible l2x node in dtb\n");
-
-	sirfsoc_l2x_base = of_iomap(np, 0);
-	if (!sirfsoc_l2x_base)
-		panic("unable to map l2x cpu registers\n");
 
-	of_node_put(np);
-
-	if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
-		/*
-		 * set the physical memory windows L2 cache will cover
-		 */
-		writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
-		writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
-
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+	np = of_find_matching_node(NULL, prima2_l2x0_ids);
+	if (np) {
+		pr_info("Initializing prima2 L2 cache\n");
+		return l2x0_of_init(0x40000, 0);
 	}
-	l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
-		0x00000000);
 
 	return 0;
 }
-early_initcall(sirfsoc_of_l2x_init);
+early_initcall(sirfsoc_l2x0_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/Makefile linux-libre-3.2-gnu1/arch/arm/mach-prima2/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,5 +3,7 @@ obj-y += irq.o
 obj-y += clock.o
 obj-y += rstc.o
 obj-y += prima2.o
+obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
+obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-prima2/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y		:= 0x00008000
+zreladdr-y		+= 0x00008000
 params_phys-y		:= 0x00000100
 initrd_phys-y		:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/pm.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/*
+ * power management entry for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "pm.h"
+
+/*
+ * suspend asm codes will access these to make DRAM become self-refresh and
+ * system sleep
+ */
+u32 sirfsoc_pwrc_base;
+void __iomem *sirfsoc_memc_base;
+
+static void sirfsoc_set_wakeup_source(void)
+{
+	u32 pwr_trigger_en_reg;
+	pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_TRIGGER_EN);
+#define X_ON_KEY_B (1 << 0)
+	sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B,
+		sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN);
+}
+
+static void sirfsoc_set_sleep_mode(u32 mode)
+{
+	u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+	sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1);
+	sleep_mode |= mode << 1;
+	sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+}
+
+static int sirfsoc_pre_suspend_power_off(void)
+{
+	u32 wakeup_entry = virt_to_phys(cpu_resume);
+
+	sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_SCRATCH_PAD1);
+
+	sirfsoc_set_wakeup_source();
+
+	sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE);
+
+	return 0;
+}
+
+static int sirfsoc_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		sirfsoc_pre_suspend_power_off();
+
+		outer_flush_all();
+		outer_disable();
+		/* go zzz */
+		cpu_suspend(0, sirfsoc_finish_suspend);
+		outer_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct platform_suspend_ops sirfsoc_pm_ops = {
+	.enter = sirfsoc_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init sirfsoc_pm_init(void)
+{
+	suspend_set_ops(&sirfsoc_pm_ops);
+	return 0;
+}
+late_initcall(sirfsoc_pm_init);
+
+static const struct of_device_id pwrc_ids[] = {
+	{ .compatible = "sirf,prima2-pwrc" },
+	{}
+};
+
+static int __init sirfsoc_of_pwrc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, pwrc_ids);
+	if (!np)
+		panic("unable to find compatible pwrc node in dtb\n");
+
+	/*
+	 * pwrc behind rtciobrg is not located in memory space
+	 * though the property is named reg. reg only means base
+	 * offset for pwrc. then of_iomap is not suitable here.
+	 */
+	if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base))
+		panic("unable to find base address of pwrc node in dtb\n");
+
+	of_node_put(np);
+
+	return 0;
+}
+postcore_initcall(sirfsoc_of_pwrc_init);
+
+static const struct of_device_id memc_ids[] = {
+	{ .compatible = "sirf,prima2-memc" },
+	{}
+};
+
+static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_memc_base = of_iomap(np, 0);
+	if (!sirfsoc_memc_base)
+		panic("unable to map memc registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_memc_driver = {
+	.probe		= sirfsoc_memc_probe,
+	.driver = {
+		.name = "sirfsoc-memc",
+		.owner = THIS_MODULE,
+		.of_match_table	= memc_ids,
+	},
+};
+
+static int __init sirfsoc_memc_init(void)
+{
+	return platform_driver_register(&sirfsoc_memc_driver);
+}
+postcore_initcall(sirfsoc_memc_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/pm.h linux-libre-3.2-gnu1/arch/arm/mach-prima2/pm.h
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/pm.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _MACH_PRIMA2_PM_H_
+#define _MACH_PRIMA2_PM_H_
+
+#define SIRFSOC_PWR_SLEEPFORCE		0x01
+
+#define SIRFSOC_SLEEP_MODE_MASK         0x3
+#define SIRFSOC_DEEP_SLEEP_MODE         0x1
+
+#define SIRFSOC_PWRC_PDN_CTRL           0x0
+#define SIRFSOC_PWRC_PON_OFF            0x4
+#define SIRFSOC_PWRC_TRIGGER_EN         0x8
+#define SIRFSOC_PWRC_PIN_STATUS         0x14
+#define SIRFSOC_PWRC_SCRATCH_PAD1       0x18
+#define SIRFSOC_PWRC_SCRATCH_PAD2       0x1C
+
+#ifndef __ASSEMBLY__
+extern int sirfsoc_finish_suspend(unsigned long);
+#endif
+
+#endif
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/prima2.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/prima2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/prima2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/prima2.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Defines machines for CSR SiRFprimaII 
+ * Defines machines for CSR SiRFprimaII
  *
  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  *
@@ -8,6 +8,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <linux/of.h>
@@ -31,11 +32,12 @@ static const char *prima2cb_dt_match[] _
 
 MACHINE_START(PRIMA2_EVB, "prima2cb")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_early     = sirfsoc_of_clk_init,
 	.map_io         = sirfsoc_map_lluart,
 	.init_irq	= sirfsoc_of_irq_init,
 	.timer		= &sirfsoc_timer,
+	.dma_zone_size	= SZ_256M,
 	.init_machine	= sirfsoc_mach_init,
 	.dt_compat      = prima2cb_dt_match,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/rtciobrg.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/rtciobrg.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/rtciobrg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/rtciobrg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SIRFSOC_CPUIOBRG_CTRL           0x00
+#define SIRFSOC_CPUIOBRG_WRBE           0x04
+#define SIRFSOC_CPUIOBRG_ADDR           0x08
+#define SIRFSOC_CPUIOBRG_DATA           0x0c
+
+/*
+ * suspend asm codes will access this address to make system deepsleep
+ * after DRAM becomes self-refresh
+ */
+void __iomem *sirfsoc_rtciobrg_base;
+static DEFINE_SPINLOCK(rtciobrg_lock);
+
+/*
+ * symbols without lock are only used by suspend asm codes
+ * and these symbols are not exported too
+ */
+void sirfsoc_rtc_iobrg_wait_sync(void)
+{
+	while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
+		cpu_relax();
+}
+
+void sirfsoc_rtc_iobrg_besyncing(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
+
+u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+u32 sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	unsigned long flags, val;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	val = __sirfsoc_rtc_iobrg_readl(addr);
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
+
+void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+
+	writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_pre_writel(val, addr);
+
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
+
+static const struct of_device_id rtciobrg_ids[] = {
+	{ .compatible = "sirf,prima2-rtciobg" },
+	{}
+};
+
+static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_rtciobrg_base = of_iomap(np, 0);
+	if (!sirfsoc_rtciobrg_base)
+		panic("unable to map rtc iobrg registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_rtciobrg_driver = {
+	.probe		= sirfsoc_rtciobrg_probe,
+	.driver = {
+		.name = "sirfsoc-rtciobrg",
+		.owner = THIS_MODULE,
+		.of_match_table	= rtciobrg_ids,
+	},
+};
+
+static int __init sirfsoc_rtciobrg_init(void)
+{
+	return platform_driver_register(&sirfsoc_rtciobrg_driver);
+}
+postcore_initcall(sirfsoc_rtciobrg_init);
+
+MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, "
+		"Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/sleep.S linux-libre-3.2-gnu1/arch/arm/mach-prima2/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * sleep mode for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+
+#include "pm.h"
+
+#define DENALI_CTL_22_OFF	0x58
+#define DENALI_CTL_112_OFF	0x1c0
+
+	.text
+
+ENTRY(sirfsoc_finish_suspend)
+	@ r5: 	mem controller
+	ldr     r0, =sirfsoc_memc_base
+	ldr	r5, [r0]
+	@ r6: 	pwrc base offset
+	ldr     r0, =sirfsoc_pwrc_base
+	ldr	r6, [r0]
+	@ r7: 	rtc iobrg controller
+	ldr     r0, =sirfsoc_rtciobrg_base
+	ldr	r7, [r0]
+
+	@ Read the power control register and set the
+	@ sleep force bit.
+	add	r0, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	__sirfsoc_rtc_iobrg_readl
+	orr	r0,r0,#SIRFSOC_PWR_SLEEPFORCE
+	add	r1, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	sirfsoc_rtc_iobrg_pre_writel
+	mov	r1, #0x1
+
+	@ read the MEM ctl register and set the self
+	@ refresh bit
+
+	ldr	r2, [r5, #DENALI_CTL_22_OFF]
+	orr	r2, r2, #0x1
+
+	@ Following code has to run from cache since
+	@ the RAM is going to self refresh mode
+	.align 5
+	str	r2, [r5, #DENALI_CTL_22_OFF]
+
+1:
+	ldr	r4, [r5, #DENALI_CTL_112_OFF]
+	tst	r4, #0x1
+	bne	1b
+
+	@ write SLEEPFORCE through rtc iobridge
+
+	str	r1, [r7]
+	@ wait rtc io bridge sync
+1:
+	ldr	r3, [r7]
+	tst	r3, #0x01
+	bne	1b
+	b .
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-prima2/timer.c linux-libre-3.2-gnu1/arch/arm/mach-prima2/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-prima2/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-prima2/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,17 @@
 
 #define SIRFSOC_TIMER_LATCH_BIT	 BIT(0)
 
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+	SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+	SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+	SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
 static void __iomem *sirfsoc_timer_base;
 static void __init sirfsoc_of_timer_map(void);
 
@@ -106,6 +117,27 @@ static void sirfsoc_timer_set_mode(enum
 	}
 }
 
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
 static struct clock_event_device sirfsoc_clockevent = {
 	.name = "sirfsoc_clockevent",
 	.rating = 200,
@@ -120,6 +152,8 @@ static struct clocksource sirfsoc_clocks
 	.mask = CLOCKSOURCE_MASK(64),
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 	.read = sirfsoc_timer_read,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
 };
 
 static struct irqaction sirfsoc_timer_irq = {
@@ -133,14 +167,14 @@ static struct irqaction sirfsoc_timer_ir
 /* Overwrite weak default sched_clock with more precise one */
 unsigned long long notrace sched_clock(void)
 {
-	static int is_mapped = 0;
+	static int is_mapped;
 
 	/*
 	 * sched_clock is called earlier than .init of sys_timer
 	 * if we map timer memory in .init of sys_timer, system
 	 * will panic due to illegal memory access
 	 */
-	if(!is_mapped) {
+	if (!is_mapped) {
 		sirfsoc_of_timer_map();
 		is_mapped = 1;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/balloon3.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/balloon3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/balloon3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/balloon3.c	2012-01-04 18:55:44.000000000 -0500
@@ -307,7 +307,7 @@ static inline void balloon3_mmc_init(voi
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static void balloon3_udc_command(int cmd)
 {
 	if (cmd == PXA2XX_UDC_CMD_CONNECT)
@@ -591,7 +591,7 @@ static void balloon3_nand_cmd_ctl(struct
 				BALLOON3_NAND_CONTROL_REG);
 		if (balloon3_ctl_set)
 			__raw_writel(balloon3_ctl_set,
-				BALLOON3_NAND_CONTROL_REG |
+				BALLOON3_NAND_CONTROL_REG +
 				BALLOON3_FPGA_SETnCLR);
 	}
 
@@ -608,7 +608,7 @@ static void balloon3_nand_select_chip(st
 	__raw_writew(
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 
 	/* Deassert correct nCE line */
 	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
@@ -626,7 +626,7 @@ static int balloon3_nand_probe(struct pl
 	int ret;
 
 	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
-		BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);
 
 	ver = __raw_readw(BALLOON3_FPGA_VER);
 	if (ver < 0x4f08)
@@ -649,7 +649,7 @@ static int balloon3_nand_probe(struct pl
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
 		BALLOON3_NAND_CONTROL_FLWP,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 	return 0;
 
 err2:
@@ -807,7 +807,7 @@ static void __init balloon3_init(void)
 
 static struct map_desc balloon3_io_desc[] __initdata = {
 	{	/* CPLD/FPGA */
-		.virtual	=  BALLOON3_FPGA_VIRT,
+		.virtual	= (unsigned long)BALLOON3_FPGA_VIRT,
 		.pfn		= __phys_to_pfn(BALLOON3_FPGA_PHYS),
 		.length		= BALLOON3_FPGA_LENGTH,
 		.type		= MT_DEVICE,
@@ -828,5 +828,5 @@ MACHINE_START(BALLOON3, "Balloon3")
 	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/capc7117.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/capc7117.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/capc7117.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/capc7117.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@ static void __init capc7117_init(void)
 
 MACHINE_START(CAPC7117,
 	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa3xx_map_io,
 	.init_irq = pxa3xx_init_irq,
 	.handle_irq = pxa3xx_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x255.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x255.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x255.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x255.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand-gpio.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x2xx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x2xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x2xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x2xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@ extern void cmx270_init(void);
 #define CMX2XX_NR_IRQS		(IRQ_BOARD_START + 40)
 
 /* virtual addresses for statically mapped regions */
-#define CMX2XX_VIRT_BASE	(0xe8000000)
+#define CMX2XX_VIRT_BASE	(void __iomem *)(0xe8000000)
 #define CMX2XX_IT8152_VIRT	(CMX2XX_VIRT_BASE)
 
 /* physical address if local-bus attached devices */
@@ -482,7 +482,7 @@ static void __init cmx2xx_init_irq(void)
 /* Map PCI companion statically */
 static struct map_desc cmx2xx_io_desc[] __initdata = {
 	[0] = { /* PCI bridge */
-		.virtual	= CMX2XX_IT8152_VIRT,
+		.virtual	= (unsigned long)CMX2XX_IT8152_VIRT,
 		.pfn		= __phys_to_pfn(PXA_CS4_PHYS),
 		.length		= SZ_64M,
 		.type		= MT_DEVICE
@@ -513,7 +513,7 @@ static void __init cmx2xx_map_io(void)
 #endif
 
 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= cmx2xx_map_io,
 	.nr_irqs	= CMX2XX_NR_IRQS,
 	.init_irq	= cmx2xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <asm/hardware/it8152.h>
 
-unsigned long it8152_base_address;
+void __iomem *it8152_base_address;
 static int cmx2xx_it8152_irq_gpio;
 
 static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x300.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x300.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/cm-x300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/cm-x300.c	2012-01-04 18:55:44.000000000 -0500
@@ -424,8 +424,9 @@ static struct mtd_partition cm_x300_nand
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= cm_x300_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= cm_x300_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
 
 static void __init cm_x300_init_nand(void)
@@ -775,7 +776,6 @@ static struct gpio cm_x300_wi2wi_gpios[]
 
 static void __init cm_x300_init_wi2wi(void)
 {
-	int bt_reset, wlan_en;
 	int err;
 
 	if (system_rev < 130) {
@@ -791,12 +791,11 @@ static void __init cm_x300_init_wi2wi(vo
 	}
 
 	udelay(10);
-	gpio_set_value(bt_reset, 0);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
 	udelay(10);
-	gpio_set_value(bt_reset, 1);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
 
-	gpio_free(wlan_en);
-	gpio_free(bt_reset);
+	gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
 }
 
 /* MFP */
@@ -839,8 +838,8 @@ static void __init cm_x300_init(void)
 	cm_x300_init_bl();
 }
 
-static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init cm_x300_fixup(struct tag *tags, char **cmdline,
+				 struct meminfo *mi)
 {
 	/* Make sure that mi->bank[0].start = PHYS_ADDR */
 	for (; tags->hdr.size; tags = tag_next(tags))
@@ -852,7 +851,7 @@ static void __init cm_x300_fixup(struct
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa270.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa270.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa270.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,7 +307,7 @@ static void __init colibri_pxa270_income
 }
 
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa270_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -315,7 +316,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri
 MACHINE_END
 
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa270_income_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa300.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa300.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa300.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,7 +183,7 @@ void __init colibri_pxa300_init(void)
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa300_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa320.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa320.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa320.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa320.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@ static void __init colibri_pxa320_init_e
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
 	.gpio_vbus		= mfp_to_gpio(MFP_PIN_GPIO96),
 	.gpio_pullup		= -1,
@@ -253,7 +253,7 @@ void __init colibri_pxa320_init(void)
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa320_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -139,8 +139,9 @@ static struct mtd_partition colibri_nand
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= colibri_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(colibri_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= colibri_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };
 
 void __init colibri_pxa3xx_init_nand(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/corgi.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/corgi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/corgi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/corgi.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/module.h>
 #include <video/w100fb.h>
 
 #include <asm/setup.h>
@@ -705,8 +706,8 @@ static void __init corgi_init(void)
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init fixup_corgi(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_corgi(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/csb726.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/csb726.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/csb726.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/csb726.c	2012-01-04 18:55:44.000000000 -0500
@@ -272,7 +272,7 @@ static void __init csb726_init(void)
 }
 
 MACHINE_START(CSB726, "Cogent CSB726")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io         = pxa27x_map_io,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/em-x270.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/em-x270.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/em-x270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/em-x270.c	2012-01-04 18:55:44.000000000 -0500
@@ -1299,7 +1299,7 @@ static void __init em_x270_init(void)
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
@@ -1308,7 +1308,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270
 MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/eseries.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/eseries.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/eseries.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/eseries.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,7 @@
 #include "clock.h"
 
 /* Only e800 has 128MB RAM */
-void __init eseries_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = 0xa0000000;
@@ -145,7 +144,7 @@ static struct clk_lookup eseries_clkregs
 	INIT_CLKREG(&tmio_dummy_clk, NULL, "CLK_CK32K"),
 };
 
-void eseries_register_clks(void)
+static void __init eseries_register_clks(void)
 {
 	clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));
 }
@@ -189,7 +188,7 @@ static void __init e330_init(void)
 
 MACHINE_START(E330, "Toshiba e330")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -239,7 +238,7 @@ static void __init e350_init(void)
 
 MACHINE_START(E350, "Toshiba e350")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -362,7 +361,7 @@ static void __init e400_init(void)
 
 MACHINE_START(E400, "Toshiba e400")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -551,7 +550,7 @@ static void __init e740_init(void)
 
 MACHINE_START(E740, "Toshiba e740")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -743,7 +742,7 @@ static void __init e750_init(void)
 
 MACHINE_START(E750, "Toshiba e750")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -948,7 +947,7 @@ static void __init e800_init(void)
 
 MACHINE_START(E800, "Toshiba e800")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/eseries.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/eseries.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/eseries.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/eseries.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
-void __init eseries_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi);
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi);
 
 extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info;
 extern struct pxaficp_platform_data e7xx_ficp_platform_data;
@@ -12,5 +11,4 @@ extern int eseries_tmio_resume(struct pl
 extern void eseries_get_tmio_gpios(void);
 extern struct resource eseries_tmio_resources[];
 extern struct platform_device e300_tc6387xb_device;
-extern void eseries_register_clks(void);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/ezx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/ezx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/ezx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/ezx.c	2012-01-04 18:55:44.000000000 -0500
@@ -797,7 +797,7 @@ static void __init a780_init(void)
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -863,7 +863,7 @@ static void __init e680_init(void)
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -929,7 +929,7 @@ static void __init a1200_init(void)
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1120,7 +1120,7 @@ static void __init a910_init(void)
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1186,7 +1186,7 @@ static void __init e6_init(void)
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1226,7 +1226,7 @@ static void __init e2_init(void)
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/generic.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/generic.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  * initialization stuff for PXA machines which can be overridden later if
  * need be.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,7 +27,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/reset.h>
-#include <mach/gpio.h>
 #include <mach/smemc.h>
 #include <mach/pxa3xx-regs.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/gumstix.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/gumstix.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/gumstix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/gumstix.c	2012-01-04 18:55:44.000000000 -0500
@@ -106,7 +106,7 @@ static void __init gumstix_mmc_init(void
 }
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA25X
+#ifdef CONFIG_USB_PXA25X
 static struct gpio_vbus_mach_info gumstix_udc_info = {
 	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
 	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
@@ -233,7 +233,7 @@ static void __init gumstix_init(void)
 }
 
 MACHINE_START(GUMSTIX, "Gumstix")
-	.boot_params	= 0xa0000100, /* match u-boot bi_boot_params */
+	.atag_offset	= 0x100, /* match u-boot bi_boot_params */
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/h5000.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/h5000.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/h5000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/h5000.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@ static void __init h5000_init(void)
 }
 
 MACHINE_START(H5400, "HP iPAQ H5000")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/himalaya.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/himalaya.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/himalaya.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/himalaya.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,7 +158,7 @@ static void __init himalaya_init(void)
 
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/hx4700.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/hx4700.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/hx4700.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/hx4700.c	2012-01-04 18:55:44.000000000 -0500
@@ -838,7 +838,7 @@ static void __init hx4700_init(void)
 }
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
-	.boot_params  = 0xa0000100,
+	.atag_offset  = 0x100,
 	.map_io       = pxa27x_map_io,
 	.nr_irqs      = HX4700_NR_IRQS,
 	.init_irq     = pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/icontrol.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/icontrol.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/icontrol.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/icontrol.c	2012-01-04 18:55:44.000000000 -0500
@@ -191,7 +191,7 @@ static void __init icontrol_init(void)
 }
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
  * Peripheral Bus
  */
 #define PERIPH_PHYS		0x40000000
-#define PERIPH_VIRT		0xf2000000
+#define PERIPH_VIRT		IOMEM(0xf2000000)
 #define PERIPH_SIZE		0x02000000
 
 /*
@@ -28,21 +28,21 @@
  */
 #define PXA2XX_SMEMC_PHYS	0x48000000
 #define PXA3XX_SMEMC_PHYS	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 #define SMEMC_SIZE		0x00100000
 
 /*
  * Dynamic Memory Controller (only on PXA3xx)
  */
 #define DMEMC_PHYS		0x48100000
-#define DMEMC_VIRT		0xf6100000
+#define DMEMC_VIRT		IOMEM(0xf6100000)
 #define DMEMC_SIZE		0x00100000
 
 /*
  * Internal Memory Controller (PXA27x and later)
  */
 #define IMEMC_PHYS		0x58000000
-#define IMEMC_VIRT		0xfe000000
+#define IMEMC_VIRT		IOMEM(0xfe000000)
 #define IMEMC_SIZE		0x00100000
 
 #endif /* __ASM_MACH_ADDR_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@ enum balloon3_features {
 };
 
 #define BALLOON3_FPGA_PHYS	PXA_CS4_PHYS
-#define BALLOON3_FPGA_VIRT	(0xf1000000)	/* as per balloon2 */
+#define BALLOON3_FPGA_VIRT	IOMEM(0xf1000000)	/* as per balloon2 */
 #define BALLOON3_FPGA_LENGTH	0x01000000
 
 #define	BALLOON3_FPGA_SETnCLR		(0x1000)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00100000
 		orr	\rv, \rp, #io_p2v(0x40000000)	@ virtual
 		orr	\rp, \rp, #0x40000000		@ physical
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,84 +24,10 @@
 #ifndef __ASM_ARCH_PXA_GPIO_H
 #define __ASM_ARCH_PXA_GPIO_H
 
-#include <mach/irqs.h>
-#include <mach/hardware.h>
 #include <asm-generic/gpio.h>
+/* The defines for the driver are needed for the accelerated accessors */
+#include "gpio-pxa.h"
 
-#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* GPIO Pin Level Registers */
-#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
-#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
-#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
-#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
-
-/* GPIO Pin Direction Registers */
-#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
-#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
-#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
-#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
-
-/* GPIO Pin Output Set Registers */
-#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
-#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
-#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
-#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
-
-/* GPIO Pin Output Clear Registers */
-#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
-#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
-#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
-#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
-
-/* GPIO Rising Edge Detect Registers */
-#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
-#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
-#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
-#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
-
-/* GPIO Falling Edge Detect Registers */
-#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
-#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
-#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
-#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
-
-/* GPIO Edge Detect Status Registers */
-#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
-#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
-#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
-#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
-
-/* GPIO Alternate Function Select Registers */
-#define GAFR0_L		GPIO_REG(0x0054)
-#define GAFR0_U		GPIO_REG(0x0058)
-#define GAFR1_L		GPIO_REG(0x005C)
-#define GAFR1_U		GPIO_REG(0x0060)
-#define GAFR2_L		GPIO_REG(0x0064)
-#define GAFR2_U		GPIO_REG(0x0068)
-#define GAFR3_L		GPIO_REG(0x006C)
-#define GAFR3_U		GPIO_REG(0x0070)
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
-
-#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
 
 static inline int irq_to_gpio(unsigned int irq)
@@ -118,37 +44,5 @@ static inline int irq_to_gpio(unsigned i
 	return -1;
 }
 
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
-	return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-		int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-		if (__gpio_is_inverted(gpio))
-			return af != 1 || dir == 0;
-		else
-			return af != 0 || dir != 0;
-	} else
-		return GPDR(gpio) & GPIO_bit(gpio);
-}
-
 #include <plat/gpio.h>
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/gpio-pxa.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/gpio-pxa.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ * Written by Philipp Zabel <philipp.zabel@gmail.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __MACH_PXA_GPIO_PXA_H
+#define __MACH_PXA_GPIO_PXA_H
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+/* GPIO Pin Level Registers */
+#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L		GPIO_REG(0x0054)
+#define GAFR0_U		GPIO_REG(0x0058)
+#define GAFR1_L		GPIO_REG(0x005C)
+#define GAFR1_U		GPIO_REG(0x0060)
+#define GAFR2_L		GPIO_REG(0x0064)
+#define GAFR2_U		GPIO_REG(0x0068)
+#define GAFR3_L		GPIO_REG(0x006C)
+#define GAFR3_U		GPIO_REG(0x0070)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
+#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+	return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+		if (__gpio_is_inverted(gpio))
+			return af != 1 || dir == 0;
+		else
+			return af != 0 || dir != 0;
+	} else
+		return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio-pxa.h>
+#endif /* __MACH_PXA_GPIO_PXA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,22 +36,23 @@
  * Note that not all PXA2xx chips implement all those addresses, and the
  * kernel only maps the minimum needed range of this mapping.
  */
-#define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 #define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))
+#define io_p2v(x) IOMEM(0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 
 #ifndef __ASSEMBLY__
-
-# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+# define IOMEM(x) ((void __iomem *)(x))
+# define __REG(x)	(*((volatile u32 __iomem *)io_p2v(x)))
 
 /* With indexed regs we don't want to feed the index through io_p2v()
    especially if it is a variable, otherwise horrible code will result. */
 # define __REG2(x,y)	\
-	(*(volatile u32 *)((u32)&__REG(x) + (y)))
+	(*(volatile u32 __iomem*)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
 #else
 
+# define IOMEM(x)	x 
 # define __REG(x)	io_p2v(x)
 # define __PREG(x)	io_v2p(x)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/littleton.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/littleton.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/littleton.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/littleton.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARCH_LITTLETON_H
 #define __ASM_ARCH_LITTLETON_H
 
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 
 #define LITTLETON_ETH_PHYS	0x30000000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/lpd270.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/lpd270.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/lpd270.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/lpd270.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,13 +13,13 @@
 #define __ASM_ARCH_LPD270_H
 
 #define LPD270_CPLD_PHYS	PXA_CS2_PHYS
-#define LPD270_CPLD_VIRT	0xf0000000
+#define LPD270_CPLD_VIRT	IOMEM(0xf0000000)
 #define LPD270_CPLD_SIZE	0x00100000
 
 #define LPD270_ETH_PHYS		(PXA_CS2_PHYS + 0x01000000)
 
 /* CPLD registers  */
-#define LPD270_CPLD_REG(x)	((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CPLD_REG(x)	(LPD270_CPLD_VIRT + (x))
 #define LPD270_CONTROL		LPD270_CPLD_REG(0x00)
 #define LPD270_PERIPHERAL0	LPD270_CPLD_REG(0x04)
 #define LPD270_PERIPHERAL1	LPD270_CPLD_REG(0x08)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- *  arch/arm/mach-pxa/include/mach/memory.h
- *
- * Author:	Nicolas Pitre
- * Copyright:	(C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0xa0000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/mtd-xip.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/mtd-xip.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/mtd-xip.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/mtd-xip.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #define __ARCH_PXA_MTD_XIP_H__
 
 #include <mach/regs-ost.h>
-#include <mach/regs-intc.h>
 
 #define xip_irqpending()	(ICIP & ICMR)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/palm27x.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/palm27x.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/palm27x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/palm27x.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,11 +34,11 @@ extern struct pxafb_mode_info palm_320x3
 extern void __init palm27x_lcd_init(int power,
 					struct pxafb_mode_info *mode);
 #else
-static inline void palm27x_lcd_init(int power, struct pxafb_mode_info *mode) {}
+#define palm27x_lcd_init(power, mode)	do {} while (0)
 #endif
 
-#if	defined(CONFIG_USB_GADGET_PXA27X) || \
-	defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if	defined(CONFIG_USB_PXA27X) || \
+	defined(CONFIG_USB_PXA27X_MODULE)
 extern void __init palm27x_udc_init(int vbus, int pullup,
 					int vbus_inverted);
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/palmtx.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/palmtx.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/palmtx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/palmtx.h	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@
 
 /* Various addresses  */
 #define PALMTX_PCMCIA_PHYS	0x28000000
-#define PALMTX_PCMCIA_VIRT	0xf0000000
+#define PALMTX_PCMCIA_VIRT	IOMEM(0xf0000000)
 #define PALMTX_PCMCIA_SIZE	0x100000
 
 #define PALMTX_PHYS_RAM_START	0xa0000000
@@ -84,8 +84,8 @@
 
 #define PALMTX_NAND_ALE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 24))
 #define PALMTX_NAND_CLE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 25))
-#define PALMTX_NAND_ALE_VIRT	0xff100000
-#define PALMTX_NAND_CLE_VIRT	0xff200000
+#define PALMTX_NAND_ALE_VIRT	IOMEM(0xff100000)
+#define PALMTX_NAND_CLE_VIRT	IOMEM(0xff200000)
 
 /* TOUCHSCREEN */
 #define AC97_LINK_FRAME			21
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxa27x.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxa27x.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxa27x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxa27x.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #ifndef __MACH_PXA27x_H
 #define __MACH_PXA27x_H
 
+#include <linux/suspend.h>
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa27x.h>
@@ -21,6 +22,7 @@
 extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxa95x.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxa95x.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxa95x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxa95x.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef __MACH_PXA95X_H
+#define __MACH_PXA95X_H
+
+#include <mach/pxa3xx.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA95X_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxafb.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxafb.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/pxafb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/pxafb.h	2012-01-04 18:55:44.000000000 -0500
@@ -158,5 +158,18 @@ struct pxafb_mach_info {
 void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
 unsigned long pxafb_get_hsync_time(struct device *dev);
 
+#ifdef CONFIG_FB_PXA_SMARTPANEL
 extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
 extern int pxafb_smart_flush(struct fb_info *info);
+#else
+static inline int pxafb_smart_queue(struct fb_info *info,
+				    uint16_t *cmds, int n)
+{
+	return 0;
+}
+
+static inline int pxafb_smart_flush(struct fb_info *info)
+{
+	return 0;
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/smemc.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/smemc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #define PXA2XX_SMEMC_BASE	0x48000000
 #define PXA3XX_SMEMC_BASE	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 
 #define MDCNFG		(SMEMC_VIRT + 0x00)  /* SDRAM Configuration Register 0 */
 #define MDREFR		(SMEMC_VIRT + 0x04)  /* SDRAM Refresh Control Register */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/zeus.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/zeus.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/zeus.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/zeus.h	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
  * Be gentle, and remap that over 32kB...
  */
 
-#define ZEUS_CPLD		(0xf0000000)
+#define ZEUS_CPLD		IOMEM(0xf0000000)
 #define ZEUS_CPLD_VERSION	(ZEUS_CPLD + 0x0000)
 #define ZEUS_CPLD_ISA_IRQ	(ZEUS_CPLD + 0x1000)
 #define ZEUS_CPLD_CONTROL	(ZEUS_CPLD + 0x2000)
@@ -76,7 +76,7 @@
 /* CPLD register bits */
 #define ZEUS_CPLD_CONTROL_CF_RST        0x01
 
-#define ZEUS_PC104IO		(0xf1000000)
+#define ZEUS_PC104IO		IOMEM(0xf1000000)
 
 #define ZEUS_SRAM_SIZE		(256 * 1024)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/zylonite.h linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/zylonite.h
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/include/mach/zylonite.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/include/mach/zylonite.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@ extern int wm9713_irq;
 extern int lcd_id;
 extern int lcd_orientation;
 
-#ifdef CONFIG_CPU_PXA300
+#ifdef CONFIG_MACH_ZYLONITE300
 extern void zylonite_pxa300_init(void);
 #else
 static inline void zylonite_pxa300_init(void)
@@ -29,7 +29,7 @@ static inline void zylonite_pxa300_init(
 }
 #endif
 
-#ifdef CONFIG_CPU_PXA320
+#ifdef CONFIG_MACH_ZYLONITE320
 extern void zylonite_pxa320_init(void);
 #else
 static inline void zylonite_pxa320_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/irq.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -19,13 +18,15 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include <asm/exception.h>
+
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
-#define IRQ_BASE		(void __iomem *)io_p2v(0x40d00000)
+#define IRQ_BASE		io_p2v(0x40d00000)
 
 #define ICIP			(0x000)
 #define ICMR			(0x004)
@@ -63,7 +64,7 @@ static inline void __iomem *irq_base(int
 		0x40d00130,
 	};
 
-	return (void __iomem *)io_p2v(phys_base[i]);
+	return io_p2v(phys_base[i]);
 }
 
 void pxa_mask_irq(struct irq_data *d)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-pxa/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,27 @@ if ARCH_PXA
 
 menu "Intel PXA2xx/PXA3xx Implementations"
 
+config ARCH_PXA_V7
+	bool "ARMv7 (PXA95x) based systems"
+
+if ARCH_PXA_V7
+comment "Marvell Dev Platforms (sorted by hardware release time)"
+config MACH_TAVOREVB3
+	bool "PXA95x Development Platform (aka TavorEVB III)"
+	select CPU_PXA955
+
+config MACH_SAARB
+	bool "PXA955 Handheld Platform (aka SAARB)"
+	select CPU_PXA955
+endif
+
+config PXA_V7_MACH_AUTO
+	def_bool y
+	depends on ARCH_PXA_V7
+	depends on !MACH_SAARB
+	select MACH_TAVOREVB3
+
+if !ARCH_PXA_V7
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
 config ARCH_LUBBOCK
@@ -41,19 +62,11 @@ config MACH_TAVOREVB
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_TAVOREVB3
-	bool "PXA95x Development Platform (aka TavorEVB III)"
-	select CPU_PXA950
-
 config MACH_SAAR
 	bool "PXA930 Handheld Platform (aka SAAR)"
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_SAARB
-	bool "PXA955 Handheld Platform (aka SAARB)"
-	select CPU_PXA955
-
 comment "Third Party Dev Platforms (sorted by vendor name)"
 
 config ARCH_PXA_IDP
@@ -414,6 +427,7 @@ config MACH_CENTRO
 	bool "Palm Centro 685 (GSM)"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -425,6 +439,7 @@ config MACH_TREO680
 	bool "Palm Treo 680"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -436,15 +451,18 @@ config MACH_RAUMFELD_RC
 	bool "Raumfeld Controller"
 	select PXA3xx
 	select CPU_PXA300
+	select POWER_SUPPLY
 	select HAVE_PWM
 
 config MACH_RAUMFELD_CONNECTOR
 	bool "Raumfeld Connector"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
 config MACH_RAUMFELD_SPEAKER
 	bool "Raumfeld Speaker"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
@@ -598,7 +616,7 @@ config MACH_ZIPIT2
 	bool "Zipit Z2 Handheld"
 	select PXA27x
 	select HAVE_PWM
-
+endif
 endmenu
 
 config PXA25x
@@ -688,6 +706,8 @@ config SHARPSL_PM
 config SHARPSL_PM_MAX1111
 	bool
 	select HWMON
+	select SPI
+	select SPI_MASTER
 	select SENSORS_MAX1111
 
 config PXA_HAVE_ISA_IRQS
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/littleton.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/littleton.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/littleton.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/littleton.c	2012-01-04 18:55:44.000000000 -0500
@@ -325,8 +325,9 @@ static struct mtd_partition littleton_na
 
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= littleton_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(littleton_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= littleton_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };
 
 static void __init littleton_init_nand(void)
@@ -437,7 +438,7 @@ static void __init littleton_init(void)
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/lpd270.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/lpd270.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/lpd270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/lpd270.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
@@ -39,7 +39,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/gpio.h>
 #include <mach/lpd270.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
@@ -480,7 +479,7 @@ static void __init lpd270_init(void)
 
 static struct map_desc lpd270_io_desc[] __initdata = {
 	{
-		.virtual	= LPD270_CPLD_VIRT,
+		.virtual	= (unsigned long)LPD270_CPLD_VIRT,
 		.pfn		= __phys_to_pfn(LPD270_CPLD_PHYS),
 		.length		= LPD270_CPLD_SIZE,
 		.type		= MT_DEVICE,
@@ -499,7 +498,7 @@ static void __init lpd270_map_io(void)
 
 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
 	/* Maintainer: Peter Barada */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= lpd270_map_io,
 	.nr_irqs	= LPD270_NR_IRQS,
 	.init_irq	= lpd270_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/lubbock.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/lubbock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/lubbock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/lubbock.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -42,7 +43,6 @@
 #include <asm/hardware/sa1111.h>
 
 #include <mach/pxa25x.h>
-#include <mach/gpio.h>
 #include <mach/audio.h>
 #include <mach/lubbock.h>
 #include <mach/udc.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/magician.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/magician.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/magician.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/magician.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,7 +753,7 @@ static void __init magician_init(void)
 
 
 MACHINE_START(MAGICIAN, "HTC Magician")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa27x_map_io,
 	.nr_irqs = MAGICIAN_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/mainstone.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/mainstone.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/mainstone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/mainstone.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
@@ -43,7 +43,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/gpio.h>
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
@@ -616,7 +615,7 @@ static void __init mainstone_map_io(void
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
 	/* Maintainer: MontaVista Software Inc. */
-	.boot_params	= 0xa0000100,	/* BLOB boot parameter setting */
+	.atag_offset	= 0x100,	/* BLOB boot parameter setting */
 	.map_io		= mainstone_map_io,
 	.nr_irqs	= MAINSTONE_NR_IRQS,
 	.init_irq	= mainstone_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/Makefile linux-libre-3.2-gnu1/arch/arm/mach-pxa/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@ endif
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
 obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
-obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa95x.o smemc.o
+obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o pxa95x.o smemc.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-pxa/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0xa0008000
+   zreladdr-y	+= 0xa0008000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/mfp-pxa2xx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/mfp-pxa2xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/mfp-pxa2xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/mfp-pxa2xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,15 +12,15 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/syscore_ops.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa2xx.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/mioa701.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/mioa701.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/mioa701.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/mioa701.c	2012-01-04 18:55:44.000000000 -0500
@@ -751,7 +751,7 @@ static void mioa701_machine_exit(void)
 }
 
 MACHINE_START(MIOA701, "MIO A701")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= &pxa27x_map_io,
 	.init_irq	= &pxa27x_init_irq,
 	.handle_irq	= &pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/mp900.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/mp900.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/mp900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/mp900.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@ static void __init mp900c_init(void)
 
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
-	.boot_params	= 0xa0220100,
+	.atag_offset	= 0x220100,
 	.timer		= &pxa_timer,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/mxm8x10.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/mxm8x10.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/mxm8x10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/mxm8x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -389,10 +389,11 @@ static struct mtd_partition mxm_8x10_nan
 };
 
 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter = 1,
-	.keep_config = 1,
-	.parts = mxm_8x10_nand_partitions,
-	.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+	.enable_arbiter	= 1,
+	.keep_config	= 1,
+	.num_cs		= 1,
+	.parts[0]	= mxm_8x10_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
 
 static void __init mxm_8x10_nand_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palm27x.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palm27x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palm27x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palm27x.c	2012-01-04 18:55:44.000000000 -0500
@@ -164,8 +164,8 @@ void __init palm27x_lcd_init(int power,
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if	defined(CONFIG_USB_GADGET_PXA27X) || \
-	defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if	defined(CONFIG_USB_PXA27X) || \
+	defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info palm27x_udc_info = {
 	.gpio_vbus_inverted	= 1,
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmld.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmld.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmld.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmld.c	2012-01-04 18:55:44.000000000 -0500
@@ -342,7 +342,7 @@ static void __init palmld_init(void)
 }
 
 MACHINE_START(PALMLD, "Palm LifeDrive")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= palmld_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmt5.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmt5.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmt5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmt5.c	2012-01-04 18:55:44.000000000 -0500
@@ -202,7 +202,7 @@ static void __init palmt5_init(void)
 }
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.reserve	= palmt5_reserve,
 	.init_irq	= pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtc.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,7 +338,7 @@ static inline void palmtc_mkp_init(void)
 /******************************************************************************
  * UDC
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+#if defined(CONFIG_USB_PXA25X)||defined(CONFIG_USB_PXA25X_MODULE)
 static struct gpio_vbus_mach_info palmtc_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTC_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
@@ -537,7 +537,7 @@ static void __init palmtc_init(void)
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
-	.boot_params 	= 0xa0000100,
+	.atag_offset 	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmte2.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmte2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmte2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmte2.c	2012-01-04 18:55:44.000000000 -0500
@@ -356,7 +356,7 @@ static void __init palmte2_init(void)
 }
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtreo.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtreo.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtreo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtreo.c	2012-01-04 18:55:44.000000000 -0500
@@ -423,6 +423,7 @@ static void __init palmphone_common_init
 	palmtreo_leds_init();
 }
 
+#ifdef CONFIG_MACH_TREO680
 static void __init treo680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
@@ -430,7 +431,9 @@ static void __init treo680_init(void)
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
 			GPIO_NR_TREO680_SD_POWER, 0);
 }
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 static void __init centro_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(centro685_pin_config));
@@ -438,9 +441,11 @@ static void __init centro_init(void)
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, -1,
 			GPIO_NR_CENTRO_SD_POWER, 1);
 }
+#endif
 
+#ifdef CONFIG_MACH_TREO680
 MACHINE_START(TREO680, "Palm Treo 680")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
@@ -448,9 +453,11 @@ MACHINE_START(TREO680, "Palm Treo 680")
 	.timer          = &pxa_timer,
 	.init_machine   = treo680_init,
 MACHINE_END
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 MACHINE_START(CENTRO, "Palm Centro 685")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
@@ -458,3 +465,4 @@ MACHINE_START(CENTRO, "Palm Centro 685")
 	.timer          = &pxa_timer,
 	.init_machine	= centro_init,
 MACHINE_END
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmtx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmtx.c	2012-01-04 18:55:44.000000000 -0500
@@ -247,7 +247,7 @@ static void palmtx_nand_cmd_ctl(struct m
 				 unsigned int ctrl)
 {
 	struct nand_chip *this = mtd->priv;
-	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+	char __iomem *nandaddr = this->IO_ADDR_W;
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -315,17 +315,17 @@ static inline void palmtx_nand_init(void
  ******************************************************************************/
 static struct map_desc palmtx_io_desc[] __initdata = {
 {
-	.virtual	= PALMTX_PCMCIA_VIRT,
+	.virtual	= (unsigned long)PALMTX_PCMCIA_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_PCMCIA_PHYS),
 	.length		= PALMTX_PCMCIA_SIZE,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_ALE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_ALE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_ALE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_CLE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_CLE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_CLE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
@@ -364,7 +364,7 @@ static void __init palmtx_init(void)
 }
 
 MACHINE_START(PALMTX, "Palm T|X")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= palmtx_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmz72.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmz72.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/palmz72.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/palmz72.c	2012-01-04 18:55:44.000000000 -0500
@@ -399,7 +399,7 @@ static void __init palmz72_init(void)
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pcm027.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pcm027.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pcm027.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pcm027.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,7 +258,7 @@ static void __init pcm027_map_io(void)
 
 MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
 	/* Maintainer: Pengutronix */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pcm027_map_io,
 	.nr_irqs	= PCM027_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
@@ -28,7 +28,6 @@
 
 #include <media/soc_camera.h>
 
-#include <asm/gpio.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
@@ -395,9 +394,9 @@ static int pcm990_camera_set_bus_param(s
 	}
 
 	if (flags & SOCAM_DATAWIDTH_8)
-		gpio_set_value(gpio_bus_switch, 1);
+		gpio_set_value_cansleep(gpio_bus_switch, 1);
 	else
-		gpio_set_value(gpio_bus_switch, 0);
+		gpio_set_value_cansleep(gpio_bus_switch, 0);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/poodle.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/poodle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/poodle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/poodle.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
 #include <linux/pm.h>
@@ -454,8 +455,8 @@ static void __init poodle_init(void)
 	poodle_init_spi();
 }
 
-static void __init fixup_poodle(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_poodle(struct tag *tags, char **cmdline,
+				struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa25x.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa25x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa25x.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  * initialization stuff for PXA machines which can be overridden later if
  * need be.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -23,12 +24,12 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/pm.h>
@@ -324,7 +325,7 @@ void __init pxa26x_init_irq(void)
 
 static struct map_desc pxa25x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa27x.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa27x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa27x.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -20,13 +21,13 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/i2c/pxa-i2c.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/suspend.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/pxa27x.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -390,7 +391,7 @@ void __init pxa27x_init_irq(void)
 
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa3xx.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,7 +25,7 @@
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -394,7 +393,7 @@ void __init pxa3xx_init_irq(void)
 
 static struct map_desc pxa3xx_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA3XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa3xx-ulpi.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa3xx-ulpi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa3xx-ulpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa3xx-ulpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,6 +265,7 @@ int pxa3xx_u2d_start_hc(struct usb_bus *
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc);
 
 void pxa3xx_u2d_stop_hc(struct usb_bus *host)
 {
@@ -277,6 +278,7 @@ void pxa3xx_u2d_stop_hc(struct usb_bus *
 
 	clk_disable(u2d->clk);
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc);
 
 static int pxa3xx_u2d_probe(struct platform_device *pdev)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa95x.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa95x.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/pxa95x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/pxa95x.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,7 +20,7 @@
 #include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/pxa930.h>
 #include <mach/reset.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/raumfeld.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/raumfeld.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/raumfeld.c	2012-01-04 18:55:44.000000000 -0500
@@ -346,8 +346,9 @@ static struct mtd_partition raumfeld_nan
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= raumfeld_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(raumfeld_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= raumfeld_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };
 
 /**
@@ -1086,7 +1087,7 @@ static void __init raumfeld_speaker_init
 
 #ifdef CONFIG_MACH_RAUMFELD_RC
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_controller_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
@@ -1097,7 +1098,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_connector_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
@@ -1108,7 +1109,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_SPEAKER
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_speaker_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/saarb.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/saarb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/saarb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/saarb.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,12 +9,13 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -23,7 +24,7 @@
 #include <mach/hardware.h>
 #include <mach/mfp.h>
 #include <mach/mfp-pxa930.h>
-#include <mach/gpio.h>
+#include <mach/pxa95x.h>
 
 #include "generic.h"
 
@@ -103,7 +104,7 @@ static void __init saarb_init(void)
 }
 
 MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= SAARB_NR_IRQS,
 	.init_irq       = pxa95x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/saar.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/saar.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/saar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/saar.c	2012-01-04 18:55:44.000000000 -0500
@@ -540,7 +540,7 @@ static struct mtd_partition saar_onenand
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
@@ -596,7 +596,7 @@ static void __init saar_init(void)
 
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/spitz.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/spitz.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/spitz.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/spitz.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -970,8 +971,8 @@ static void __init spitz_init(void)
 	spitz_i2c_init();
 }
 
-static void __init spitz_fixup(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init spitz_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks = 1;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/stargate2.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/stargate2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/stargate2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/stargate2.c	2012-01-04 18:55:44.000000000 -0500
@@ -1004,7 +1004,7 @@ MACHINE_START(INTELMOTE2, "IMOTE 2")
 	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= imote2_init,
-	.boot_params	= 0xA0000100,
+	.atag_offset	= 0x100,
 MACHINE_END
 #endif
 
@@ -1016,6 +1016,6 @@ MACHINE_START(STARGATE2, "Stargate 2")
 	.handle_irq = pxa27x_handle_irq,
 	.timer = &pxa_timer,
 	.init_machine = stargate2_init,
-	.boot_params = 0xA0000100,
+	.atag_offset = 0x100,
 MACHINE_END
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/tavorevb3.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/tavorevb3.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/tavorevb3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/tavorevb3.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@ static void __init evb3_init(void)
 }
 
 MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= TAVOREVB3_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/tavorevb.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/tavorevb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/tavorevb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/tavorevb.c	2012-01-04 18:55:44.000000000 -0500
@@ -489,7 +489,7 @@ static void __init tavorevb_init(void)
 
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/tosa.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/tosa.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/tosa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/tosa.c	2012-01-04 18:55:44.000000000 -0500
@@ -960,8 +960,8 @@ static void __init tosa_init(void)
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init fixup_tosa(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_tosa(struct tag *tags, char **cmdline,
+			      struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/trizeps4.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/trizeps4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/trizeps4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/trizeps4.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
 #include <linux/fb.h>
@@ -554,7 +555,7 @@ static void __init trizeps4_map_io(void)
 
 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
 	/* MAINTAINER("JÃ¼rgen Schindele") */
-	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -564,7 +565,7 @@ MACHINE_END
 
 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
 	/* MAINTAINER("JÃ¼rgen Schindele") */
-	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/viper.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/viper.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/viper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/viper.c	2012-01-04 18:55:44.000000000 -0500
@@ -992,7 +992,7 @@ static void __init viper_map_io(void)
 
 MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= viper_map_io,
 	.init_irq	= viper_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/vpac270.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/vpac270.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/vpac270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/vpac270.c	2012-01-04 18:55:44.000000000 -0500
@@ -343,7 +343,7 @@ static inline void vpac270_uhc_init(void
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = {
 	.gpio_vbus		= GPIO41_VPAC270_UDC_DETECT,
 	.gpio_pullup		= -1,
@@ -716,7 +716,7 @@ static void __init vpac270_init(void)
 }
 
 MACHINE_START(VPAC270, "Voipac PXA270")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/xcep.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/xcep.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/xcep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/xcep.c	2012-01-04 18:55:44.000000000 -0500
@@ -142,8 +142,7 @@ static struct platform_device *devices[]
 
 /* We have to state that there are HWMON devices on the I2C bus on XCEP.
  * Drivers for HWMON verify capabilities of the adapter when loading and
- * refuse to attach if the adapter doesn't support HWMON class of devices.
- * See also Documentation/i2c/porting-clients. */
+ * refuse to attach if the adapter doesn't support HWMON class of devices. */
 static struct i2c_pxa_platform_data xcep_i2c_platform_data  = {
 	.class = I2C_CLASS_HWMON
 };
@@ -180,7 +179,7 @@ static void __init xcep_init(void)
 }
 
 MACHINE_START(XCEP, "Iskratel XCEP")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.init_machine	= xcep_init,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/z2.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/z2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/z2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/z2.c	2012-01-04 18:55:44.000000000 -0500
@@ -686,7 +686,8 @@ static void z2_power_off(void)
 	 */
 	PSPR = 0x0;
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_pm_enter(PM_SUSPEND_MEM);
 }
 #else
 #define z2_power_off   NULL
@@ -718,7 +719,7 @@ static void __init z2_init(void)
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/zeus.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/zeus.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/zeus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/zeus.c	2012-01-04 18:55:44.000000000 -0500
@@ -860,25 +860,25 @@ static void __init zeus_init(void)
 
 static struct map_desc zeus_io_desc[] __initdata = {
 	{
-		.virtual = ZEUS_CPLD_VERSION,
+		.virtual = (unsigned long)ZEUS_CPLD_VERSION,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_ISA_IRQ,
+		.virtual = (unsigned long)ZEUS_CPLD_ISA_IRQ,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_CONTROL,
+		.virtual = (unsigned long)ZEUS_CPLD_CONTROL,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_PC104IO,
+		.virtual = (unsigned long)ZEUS_PC104IO,
 		.pfn     = __phys_to_pfn(ZEUS_PC104IO_PHYS),
 		.length  = 0x00800000,
 		.type    = MT_DEVICE,
@@ -904,7 +904,7 @@ static void __init zeus_map_io(void)
 
 MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= zeus_map_io,
 	.nr_irqs	= ZEUS_NR_IRQS,
 	.init_irq	= zeus_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-pxa/zylonite.c linux-libre-3.2-gnu1/arch/arm/mach-pxa/zylonite.c
--- linux-libre-3.1-gnu1/arch/arm/mach-pxa/zylonite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-pxa/zylonite.c	2012-01-04 18:55:44.000000000 -0500
@@ -366,8 +366,9 @@ static struct mtd_partition zylonite_nan
 
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= zylonite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(zylonite_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= zylonite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };
 
 static void __init zylonite_init_nand(void)
@@ -422,7 +423,7 @@ static void __init zylonite_init(void)
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/core.c linux-libre-3.2-gnu1/arch/arm/mach-realview/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -517,8 +517,7 @@ void __init realview_timer_init(unsigned
 /*
  * Setup the memory banks.
  */
-void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from,
-		    struct meminfo *meminfo)
+void realview_fixup(struct tag *tags, char **from, struct meminfo *meminfo)
 {
 	/*
 	 * Most RealView platforms have 512MB contiguous RAM at 0x70000000.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/core.h linux-libre-3.2-gnu1/arch/arm/mach-realview/core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/core.h	2012-01-04 18:55:44.000000000 -0500
@@ -63,8 +63,8 @@ extern int realview_flash_register(struc
 extern int realview_eth_register(const char *name, struct resource *res);
 extern int realview_usb_register(struct resource *res);
 extern void realview_init_early(void);
-extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags,
-			   char **from, struct meminfo *meminfo);
+extern void realview_fixup(struct tag *tags, char **from,
+			   struct meminfo *meminfo);
 extern void (*realview_reset)(char);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-realview/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ static inline void platform_do_lowpower(
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/board-pb1176.h linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/board-pb1176.h
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/board-pb1176.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/board-pb1176.h	2012-01-04 18:55:44.000000000 -0500
@@ -70,6 +70,7 @@
 
 #define REALVIEW_DC1176_GIC_CPU_BASE		0x10120000 /* GIC CPU interface, on devchip */
 #define REALVIEW_DC1176_GIC_DIST_BASE		0x10121000 /* GIC distributor, on devchip */
+#define REALVIEW_DC1176_ROM_BASE		0x10200000 /* 16KiB NRAM preudo-ROM, on devchip */
 #define REALVIEW_PB1176_GIC_CPU_BASE		0x10040000 /* GIC CPU interface, on FPGA */
 #define REALVIEW_PB1176_GIC_DIST_BASE		0x10041000 /* GIC distributor, on FPGA */
 #define REALVIEW_PB1176_L220_BASE		0x10110000 /* L220 registers */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,30 +10,17 @@
  * published by the Free Software Foundation.
  */
 
-#if defined(CONFIG_MACH_REALVIEW_EB) || \
-    defined(CONFIG_MACH_REALVIEW_PB11MP) || \
-    defined(CONFIG_MACH_REALVIEW_PBA8) || \
-    defined(CONFIG_MACH_REALVIEW_PBX)
-#ifndef DEBUG_LL_UART_OFFSET
+#ifdef CONFIG_DEBUG_REALVIEW_STD_PORT
 #define DEBUG_LL_UART_OFFSET	0x00009000
-#elif DEBUG_LL_UART_OFFSET != 0x00009000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
-#endif
-
-#ifdef CONFIG_MACH_REALVIEW_PB1176
-#ifndef DEBUG_LL_UART_OFFSET
+#elif defined(CONFIG_DEBUG_REALVIEW_PB1176_PORT)
 #define DEBUG_LL_UART_OFFSET	0x0010c000
-#elif DEBUG_LL_UART_OFFSET != 0x0010c000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
 #endif
 
 #ifndef DEBUG_LL_UART_OFFSET
 #error "Unknown RealView platform"
 #endif
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #DEBUG_LL_UART_OFFSET
 		orr	\rv, \rp, #0xfb000000	@ virtual base
 		orr	\rp, \rp, #0x10000000	@ physical base
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-realview/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 ifeq ($(CONFIG_REALVIEW_HIGH_PHYS_OFFSET),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70800000
 else
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-realview/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,12 +52,10 @@ void __init smp_init_cpus(void)
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "Realview: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_eb.c linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_eb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_eb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_eb.c	2012-01-04 18:55:44.000000000 -0500
@@ -463,7 +463,7 @@ static void __init realview_eb_init(void
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_eb_map_io,
 	.init_early	= realview_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pb1176.c linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pb1176.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pb1176.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pb1176.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 #include <linux/amba/pl061.h>
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
@@ -204,22 +206,48 @@ static struct amba_device *amba_devs[] _
  * RealView PB1176 platform devices
  */
 static struct resource realview_pb1176_flash_resources[] = {
-	[0] = {
+	{
 		.start		= REALVIEW_PB1176_FLASH_BASE,
 		.end		= REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
-	[1] = {
+#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
+	{
 		.start		= REALVIEW_PB1176_SEC_FLASH_BASE,
 		.end		= REALVIEW_PB1176_SEC_FLASH_BASE + REALVIEW_PB1176_SEC_FLASH_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
-};
-#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
-#define PB1176_FLASH_BLOCKS	2
-#else
-#define PB1176_FLASH_BLOCKS	1
 #endif
+};
+
+static struct physmap_flash_data pb1176_rom_pdata = {
+	.probe_type	= "map_rom",
+	.width		= 4,
+	.nr_parts	= 0,
+};
+
+static struct resource pb1176_rom_resources[] = {
+	/*
+	 * This exposes the PB1176 DevChip ROM as an MTD ROM mapping.
+	 * The reference manual states that this is actually a pseudo-ROM
+	 * programmed in NVRAM.
+	 */
+	{
+		.start		= REALVIEW_DC1176_ROM_BASE,
+		.end		= REALVIEW_DC1176_ROM_BASE + SZ_16K - 1,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device pb1176_rom_device = {
+	.name		= "physmap-flash",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pb1176_rom_resources),
+	.resource	= pb1176_rom_resources,
+	.dev = {
+		.platform_data = &pb1176_rom_pdata,
+	},
+};
 
 static struct resource realview_pb1176_smsc911x_resources[] = {
 	[0] = {
@@ -316,8 +344,7 @@ static void realview_pb1176_reset(char m
 	__raw_writel(REALVIEW_PB1176_SYS_SOFT_RESET, reset_ctrl);
 }
 
-static void realview_pb1176_fixup(struct machine_desc *mdesc,
-				  struct tag *tags, char **from,
+static void realview_pb1176_fixup(struct tag *tags, char **from,
 				  struct meminfo *meminfo)
 {
 	/*
@@ -338,7 +365,8 @@ static void __init realview_pb1176_init(
 #endif
 
 	realview_flash_register(realview_pb1176_flash_resources,
-				PB1176_FLASH_BLOCKS);
+				ARRAY_SIZE(realview_pb1176_flash_resources));
+	platform_device_register(&pb1176_rom_device);
 	realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
 	realview_usb_register(realview_pb1176_isp1761_resources);
@@ -358,7 +386,7 @@ static void __init realview_pb1176_init(
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_pb1176_fixup,
 	.map_io		= realview_pb1176_map_io,
 	.init_early	= realview_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pb11mp.c linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pb11mp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pb11mp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pb11mp.c	2012-01-04 18:55:44.000000000 -0500
@@ -360,7 +360,7 @@ static void __init realview_pb11mp_init(
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
 	.init_early	= realview_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pba8.c linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pba8.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pba8.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pba8.c	2012-01-04 18:55:44.000000000 -0500
@@ -310,7 +310,7 @@ static void __init realview_pba8_init(vo
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pba8_map_io,
 	.init_early	= realview_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pbx.c linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-3.1-gnu1/arch/arm/mach-realview/realview_pbx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-realview/realview_pbx.c	2012-01-04 18:55:44.000000000 -0500
@@ -319,8 +319,8 @@ static struct sys_timer realview_pbx_tim
 	.init		= realview_pbx_timer_init,
 };
 
-static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags,
-			       char **from, struct meminfo *meminfo)
+static void realview_pbx_fixup(struct tag *tags, char **from,
+			       struct meminfo *meminfo)
 {
 #ifdef CONFIG_SPARSEMEM
 	/*
@@ -335,7 +335,7 @@ static void realview_pbx_fixup(struct ma
 	meminfo->bank[2].size = SZ_256M;
 	meminfo->nr_banks = 3;
 #else
-	realview_fixup(mdesc, tags, from, meminfo);
+	realview_fixup(tags, from, meminfo);
 #endif
 }
 
@@ -393,7 +393,7 @@ static void __init realview_pbx_init(voi
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
 	.init_early	= realview_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00010000
 		orr	\rp, \rp, #0x00000fe0
 		orr	\rv, \rp, #0xe0000000	@ virtual
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 
 #define EASI_SIZE		0x08000000	/* EASI I/O */
 #define EASI_START		0x08000000
-#define EASI_BASE		0xe5000000
+#define EASI_BASE		IOMEM(0xe5000000)
 
 #define IO_START		0x03000000	/* I/O */
 #define IO_SIZE			0x01000000
@@ -51,21 +51,20 @@
 /*
  * IO Addresses
  */
-#define VIDC_BASE		IOMEM(0xe0400000)
-#define EXPMASK_BASE		0xe0360000
-#define IOMD_BASE		IOMEM(0xe0200000)
-#define IOC_BASE		IOMEM(0xe0200000)
-#define PCIO_BASE		IOMEM(0xe0010000)
-#define FLOPPYDMA_BASE		IOMEM(0xe002a000)
+#define ECARD_EASI_BASE		(EASI_BASE)
+#define VIDC_BASE		(IO_BASE + 0x00400000)
+#define EXPMASK_BASE		(IO_BASE + 0x00360000)
+#define ECARD_IOC4_BASE		(IO_BASE + 0x00270000)
+#define ECARD_IOC_BASE		(IO_BASE + 0x00240000)
+#define IOMD_BASE		(IO_BASE + 0x00200000)
+#define IOC_BASE		(IO_BASE + 0x00200000)
+#define ECARD_MEMC8_BASE	(IO_BASE + 0x0002b000)
+#define FLOPPYDMA_BASE		(IO_BASE + 0x0002a000)
+#define PCIO_BASE		(IO_BASE + 0x00010000)
+#define ECARD_MEMC_BASE		(IO_BASE + 0x00000000)
 
 #define vidc_writel(val)	__raw_writel(val, VIDC_BASE)
 
-#define IO_EC_EASI_BASE		0x81400000
-#define IO_EC_IOC4_BASE		0x8009c000
-#define IO_EC_IOC_BASE		0x80090000
-#define IO_EC_MEMC8_BASE	0x8000ac00
-#define IO_EC_MEMC_BASE		0x80000000
-
 #define NETSLOT_BASE		0x0302b000
 #define NETSLOT_SIZE		0x00001000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-rpc/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-rpc/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,195 +15,18 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We use two different types of addressing - PC style addresses, and ARM
- * addresses.  PC style accesses the PC hardware with the normal PC IO
- * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
- * and are translated to the start of IO.  Note that all addresses are
- * shifted left!
- */
-#define __PORT_PCIO(x)	(!((x) & 0x80000000))
-
-/*
- * Dynamic IO functions.
- */
-static inline void __outb (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"strb	%1, [%0, %2, lsl #2]	@ outb"
-	: "=&r" (temp)
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-static inline void __outw (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]	@ outw"
-	: "=&r" (temp)
-	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-static inline void __outl (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]	@ outl"
-	: "=&r" (temp)
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
-static inline unsigned sz __in##fnsuffix (unsigned int port)		\
-{										\
-	unsigned long temp, value;						\
-	__asm__ __volatile__(							\
-	"tst	%2, #0x80000000\n\t"						\
-	"mov	%0, %4\n\t"							\
-	"addeq	%0, %0, %3\n\t"							\
-	"ldr" instr "	%1, [%0, %2, lsl #2]	@ in" #fnsuffix			\
-	: "=&r" (temp), "=r" (value)						\
-	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
-	: "cc");								\
-	return (unsigned sz)value;						\
-}
-
-static inline void __iomem *__deprecated __ioaddr(unsigned int port)
-{
-	void __iomem *ret;
-	if (__PORT_PCIO(port))
-		ret = PCIO_BASE;
-	else
-		ret = IO_BASE;
-	return ret + (port << 2);
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr)	\
-	DECLARE_DYN_IN(sz,fnsuffix,instr)
-
-DECLARE_IO(char,b,"b")
-DECLARE_IO(short,w,"")
-DECLARE_IO(int,l,"")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_IN
+#define IO_SPACE_LIMIT 0xffff
 
 /*
- * Constant address IO functions
+ * We need PC style IO addressing for:
+ *  - floppy (at 0x3f2,0x3f4,0x3f5,0x3f7)
+ *  - parport (at 0x278-0x27a, 0x27b-0x27f, 0x778-0x77a)
+ *  - 8250 serial (only for compile)
  *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
+ * These peripherals are found in an area of MMIO which looks very much
+ * like an ISA bus, but with registers at the low byte of each word.
  */
-#define __outbc(value,port)							\
-({										\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]	@ outbc"				\
-		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]	@ outbc"				\
-		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inbc(port)								\
-({										\
-	unsigned char result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]	@ inbc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]	@ inbc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define __outwc(value,port)							\
-({										\
-	unsigned long __v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inwc(port)								\
-({										\
-	unsigned short result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inwc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inwc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result & 0xffff;							\
-})
-
-#define __outlc(value,port)							\
-({										\
-	unsigned long __v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inlc(port)								\
-({										\
-	unsigned long result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inlc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inlc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define inb(p)	 	(__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
-#define inw(p)	 	(__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
-#define inl(p)	 	(__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
-#define outb(v,p)	(__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
-#define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
-#define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-
-/* the following macro is deprecated */
-#define ioaddr(port)	((unsigned long)__ioaddr((port)))
-
-#define insb(p,d,l)	__raw_readsb(__ioaddr(p),d,l)
-#define insw(p,d,l)	__raw_readsw(__ioaddr(p),d,l)
-
-#define outsb(p,d,l)	__raw_writesb(__ioaddr(p),d,l)
-#define outsw(p,d,l)	__raw_writesw(__ioaddr(p),d,l)
+#define __io(a)		(PCIO_BASE + ((a) << 2))
 
 /*
  * 1:1 mapping for ioremapped regions.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-rpc/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-rpc/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-rpc/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-rpc/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x10008000
+   zreladdr-y	+= 0x10008000
 params_phys-y	:= 0x10000100
 initrd_phys-y	:= 0x18000000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-rpc/riscpc.c linux-libre-3.2-gnu1/arch/arm/mach-rpc/riscpc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-rpc/riscpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-rpc/riscpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@ static struct map_desc rpc_io_desc[] __i
 		.length		= 	IO_SIZE	 ,
 		.type		= MT_DEVICE
 	}, {	/* EASI space	*/
-		.virtual	= EASI_BASE,
+		.virtual	= (unsigned long)EASI_BASE,
 		.pfn		= __phys_to_pfn(EASI_START),
 		.length		= EASI_SIZE,
 		.type		= MT_DEVICE
@@ -218,7 +218,7 @@ extern struct sys_timer ioc_timer;
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.reserve_lp0	= 1,
 	.reserve_lp1	= 1,
 	.map_io		= rpc_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2400/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2400/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2400/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2400/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c2400/include/mach/memory.h
- *  from arch/arm/mach-rpc/include/mach/memory.h
- *
- *  Copyright 2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- *  Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x0C000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,38 +47,26 @@ static struct s3c24xx_dma_map __initdata
 		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -90,12 +78,10 @@ static struct s3c24xx_dma_map __initdata
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C24XX_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG(8) || pin > S3C2410_GPG(15))
-		return -EINVAL;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG(8);
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C24XX_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C24XX_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C24XX_PA_UART
 		ldr	\rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,18 @@ enum dma_ch {
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+	return false;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
@@ -163,7 +174,7 @@ struct s3c2410_dma_chan {
 	struct s3c2410_dma_client *client;
 
 	/* channel configuration */
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 	enum dma_ch		 req_ch;
 	unsigned long		 dev_addr;
 	unsigned long		 load_timeout;
@@ -196,9 +207,4 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-	return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/fb.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/fb.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/fb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,74 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/fb.h
- *
- * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * Inspired by pxafb.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_FB_H
-#define __ASM_ARM_FB_H
-
-#include <mach/regs-lcd.h>
-
-struct s3c2410fb_hw {
-	unsigned long	lcdcon1;
-	unsigned long	lcdcon2;
-	unsigned long	lcdcon3;
-	unsigned long	lcdcon4;
-	unsigned long	lcdcon5;
-};
-
-/* LCD description */
-struct s3c2410fb_display {
-	/* LCD type */
-	unsigned type;
-
-	/* Screen size */
-	unsigned short width;
-	unsigned short height;
-
-	/* Screen info */
-	unsigned short xres;
-	unsigned short yres;
-	unsigned short bpp;
-
-	unsigned pixclock;		/* pixclock in picoseconds */
-	unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short upper_margin;	/* value in lines (TFT) or 0 (STN) */
-	unsigned short lower_margin;	/* value in lines (TFT) or 0 (STN) */
-	unsigned short vsync_len;	/* value in lines (TFT) or 0 (STN) */
-
-	/* lcd configuration registers */
-	unsigned long	lcdcon5;
-};
-
-struct s3c2410fb_mach_info {
-
-	struct s3c2410fb_display *displays;	/* attached diplays info */
-	unsigned num_displays;			/* number of defined displays */
-	unsigned default_display;
-
-	/* GPIOs */
-
-	unsigned long	gpcup;
-	unsigned long	gpcup_mask;
-	unsigned long	gpccon;
-	unsigned long	gpccon_mask;
-	unsigned long	gpdup;
-	unsigned long	gpdup_mask;
-	unsigned long	gpdcon;
-	unsigned long	gpdcon_mask;
-
-	/* lpc3600 control register */
-	unsigned long	lpcsel;
-};
-
-extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
-
-#endif /* __ASM_ARM_FB_H */
+#include <plat/fb-s3c2410.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-fns.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,98 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - hardware
- *
- * 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 __MACH_GPIO_FNS_H
-#define __MACH_GPIO_FNS_H __FILE__
-
-/* These functions are in the to-be-removed category and it is strongly
- * encouraged not to use these in new code. They will be marked deprecated
- * very soon.
- *
- * Most of the functionality can be either replaced by the gpiocfg calls
- * for the s3c platform or by the generic GPIOlib API.
- *
- * As of 2.6.35-rc, these will be removed, with the few drivers using them
- * either replaced or given a wrapper until the calls can be removed.
-*/
-
-#include <plat/gpio-cfg.h>
-
-static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
-{
-	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
-	s3c_gpio_cfgpin(pin, cfg);
-}
-
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *	< 0 = no interrupt for this pin
- *	>=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-				  unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * This call should be replaced with s3c_gpio_setpull().
- *
- * As a note, there is currently no distinction between pull-up and pull-down
- * in the s3c24xx series devices with only an on/off configuration.
- */
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
-#endif /* __MACH_GPIO_FNS_H */
+#include <plat/gpio-fns.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,11 +11,6 @@
  * published by the Free Software Foundation.
 */
 
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
 /* some boards require extra gpio capacity to support external
  * devices that need GPIO.
  */
@@ -28,7 +23,6 @@
 #define ARCH_NR_GPIOS	(256 + CONFIG_S3C24XX_GPIO_EXTRA)
 #endif
 
-#include <asm-generic/gpio.h>
 #include <mach/gpio-nrs.h>
 #include <mach/gpio-fns.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@
 #define S3C2410_GPIO_M_NR	(32)	/* technically 2. */
 
 #if CONFIG_S3C_GPIO_SPACE != 0
-#error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment
+#error CONFIG_S3C_GPIO_SPACE cannot be nonzero at the moment
 #endif
 
 #define S3C2410_GPIO_NEXT(__gpio) \
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-track.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-track.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-track.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/gpio-track.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,11 @@
 
 #include <mach/regs-gpio.h>
 
-extern struct s3c_gpio_chip s3c24xx_gpios[];
+extern struct samsung_gpio_chip s3c24xx_gpios[];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
 {
-	struct s3c_gpio_chip *chip;
+	struct samsung_gpio_chip *chip;
 
 	if (pin > S3C_GPIO_END)
 		return NULL;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/h1940-latch.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/h1940-latch.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/h1940-latch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/h1940-latch.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_H1940_LATCH_H
 #define __ASM_ARCH_H1940_LATCH_H
 
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 #define H1940_LATCH_GPIO(x)		(S3C_GPIO_END + (x))
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -199,8 +199,6 @@ DECLARE_IO(int,l,"")
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 #define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-/* the following macro is deprecated */
-#define ioaddr(port)	__ioaddr((port))
 
 #define insb(p,d,l)	__raw_readsb(__ioaddr(p),d,l)
 #define insw(p,d,l)	__raw_readsw(__ioaddr(p),d,l)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -191,9 +191,9 @@
 #define IRQ_LCD_SYSTEM		IRQ_S3C2443_LCD2
 
 #ifdef CONFIG_CPU_S3C2440
-#define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2440_AC97
 #else
-#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2443_AC97
 #endif
 
 /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,53 @@
 #define __ASM_ARCH_MAP_H
 
 #include <plat/map-base.h>
-#include <plat/map.h>
 
-#define S3C2410_ADDR(x)		S3C_ADDR(x)
+/*
+ * S3C2410 UART offset is 0x4000 but the other SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET		(0x4000)
+
+#include <plat/map-s3c.h>
+
+/*
+ * interrupt controller is the first thing we put in, to make
+ * the assembly code for the irq detection easier
+ */
+#define S3C2410_PA_IRQ		(0x4A000000)
+#define S3C24XX_SZ_IRQ		SZ_1M
+
+/* memory controller registers */
+#define S3C2410_PA_MEMCTRL	(0x48000000)
+#define S3C24XX_SZ_MEMCTRL	SZ_1M
+
+/* UARTs */
+#define S3C_VA_UARTx(uart)	(S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
+
+/* Timers */
+#define S3C2410_PA_TIMER	(0x51000000)
+#define S3C24XX_SZ_TIMER	SZ_1M
+
+/* Clock and Power management */
+#define S3C24XX_SZ_CLKPWR	SZ_1M
+
+/* USB Device port */
+#define S3C2410_PA_USBDEV	(0x52000000)
+#define S3C24XX_SZ_USBDEV	SZ_1M
+
+/* Watchdog */
+#define S3C2410_PA_WATCHDOG	(0x53000000)
+#define S3C24XX_SZ_WATCHDOG	SZ_1M
+
+/* Standard size definitions for peripheral blocks. */
+
+#define S3C24XX_SZ_UART		SZ_1M
+#define S3C24XX_SZ_IIS		SZ_1M
+#define S3C24XX_SZ_ADC		SZ_1M
+#define S3C24XX_SZ_SPI		SZ_1M
+#define S3C24XX_SZ_SDI		SZ_1M
+#define S3C24XX_SZ_NAND		SZ_1M
+#define S3C24XX_SZ_GPIO		SZ_1M
 
 /* USB host controller */
 #define S3C2410_PA_USBHOST (0x49000000)
@@ -75,10 +119,8 @@
 
 /* S3C2412 memory and IO controls */
 #define S3C2412_PA_SSMC	(0x4F000000)
-#define S3C2412_VA_SSMC	S3C_ADDR_CPU(0x00000000)
 
 #define S3C2412_PA_EBI	(0x48800000)
-#define S3C2412_VA_EBI	S3C_ADDR_CPU(0x00010000)
 
 /* physical addresses of all the chip-select areas */
 
@@ -100,15 +142,14 @@
 #define S3C24XX_PA_DMA      S3C2410_PA_DMA
 #define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
 #define S3C24XX_PA_LCD      S3C2410_PA_LCD
-#define S3C24XX_PA_UART     S3C2410_PA_UART
 #define S3C24XX_PA_TIMER    S3C2410_PA_TIMER
 #define S3C24XX_PA_USBDEV   S3C2410_PA_USBDEV
 #define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
 #define S3C24XX_PA_IIS      S3C2410_PA_IIS
-#define S3C24XX_PA_GPIO     S3C2410_PA_GPIO
 #define S3C24XX_PA_RTC      S3C2410_PA_RTC
 #define S3C24XX_PA_ADC      S3C2410_PA_ADC
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
+#define S3C24XX_PA_SPI1		(S3C2410_PA_SPI + S3C2410_SPI1)
 #define S3C24XX_PA_SDI      S3C2410_PA_SDI
 #define S3C24XX_PA_NAND	    S3C2410_PA_NAND
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/memory.h
- *  from arch/arm/mach-rpc/include/mach/memory.h
- *
- *  Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x30000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,4 +64,4 @@ static inline void s3c_pm_arch_update_ua
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@
 #define S3C2443_CLKDIV0_PREDIV_MASK	(3<<4)
 #define S3C2443_CLKDIV0_PREDIV_SHIFT	(4)
 
+#define S3C2416_CLKDIV0_ARMDIV_MASK	(7 << 9)
 #define S3C2443_CLKDIV0_ARMDIV_MASK	(15<<9)
 #define S3C2443_CLKDIV0_ARMDIV_SHIFT	(9)
 #define S3C2443_CLKDIV0_ARMDIV_1	(0<<9)
@@ -102,6 +103,7 @@
 #define S3C2443_PCLKCON_UART3		(1<<3)
 #define S3C2443_PCLKCON_IIC		(1<<4)
 #define S3C2443_PCLKCON_SDI		(1<<5)
+#define S3C2443_PCLKCON_HSSPI		(1<<6)
 #define S3C2443_PCLKCON_ADC		(1<<7)
 #define S3C2443_PCLKCON_AC97		(1<<8)
 #define S3C2443_PCLKCON_IIS		(1<<9)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,7 @@ config CPU_S3C2410
 	bool
 	depends on ARCH_S3C2410
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select CPU_LLSERIAL_S3C2410
 	select S3C2410_PM if PM
 	select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
@@ -28,11 +26,6 @@ config S3C2410_PM
 	help
 	  Power Management code common to S3C2410 and better
 
-config S3C2410_GPIO
-	bool
-	help
-	  GPIO code for S3C2410 and similar processors
-
 config SIMTEC_NOR
 	bool
 	help
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-amlm5900.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-amlm5900.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-amlm5900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-amlm5900.c	2012-01-04 18:55:44.000000000 -0500
@@ -236,7 +236,7 @@ static void __init amlm5900_init(void)
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= amlm5900_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= amlm5900_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-bast.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-bast.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-bast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-bast.c	2012-01-04 18:55:44.000000000 -0500
@@ -657,7 +657,7 @@ static void __init bast_init(void)
 
 MACHINE_START(BAST, "Simtec-BAST")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= bast_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= bast_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-h1940.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-h1940.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-h1940.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <video/platform_lcd.h>
 
 #include <linux/mmc/host.h>
+#include <linux/export.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -696,9 +697,9 @@ static void __init h1940_init(void)
 			      S3C2410_MISCCR_USBSUSPND0 |
 			      S3C2410_MISCCR_USBSUSPND1, 0x0);
 
-	tmp =   (0x78 << S3C24XX_PLLCON_MDIVSHIFT)
-	      | (0x02 << S3C24XX_PLLCON_PDIVSHIFT)
-	      | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
+	tmp =   (0x78 << S3C24XX_PLL_MDIV_SHIFT)
+	      | (0x02 << S3C24XX_PLL_PDIV_SHIFT)
+	      | (0x03 << S3C24XX_PLL_SDIV_SHIFT);
 	writel(tmp, S3C2410_UPLLCON);
 
 	gpio_request(S3C2410_GPC(0), "LCD power");
@@ -744,7 +745,7 @@ static void __init h1940_init(void)
 
 MACHINE_START(H1940, "IPAQ-H1940")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= h1940_map_io,
 	.reserve	= h1940_reserve,
 	.init_irq	= h1940_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-n30.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-n30.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-n30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-n30.c	2012-01-04 18:55:44.000000000 -0500
@@ -586,7 +586,7 @@ MACHINE_START(N30, "Acer-N30")
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>,
 				Ben Dooks <ben-linux@fluff.org>
 	*/
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
@@ -596,7 +596,7 @@ MACHINE_END
 MACHINE_START(N35, "Acer-N35")
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>
 	*/
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-otom.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-otom.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-otom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-otom.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@ static void __init otom11_init(void)
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= otom11_map_io,
 	.init_machine	= otom11_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-qt2410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-qt2410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-qt2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-qt2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
+#include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
 #include <mach/fb.h>
 #include <plat/nand.h>
@@ -344,7 +345,7 @@ static void __init qt2410_machine_init(v
 }
 
 MACHINE_START(QT2410, "QT2410")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= qt2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= qt2410_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-smdk2410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-smdk2410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-smdk2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-smdk2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@ static void __init smdk2410_init(void)
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
 	/* Maintainer: Jonas Dietsche */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= smdk2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= smdk2410_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-tct_hammer.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-tct_hammer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-tct_hammer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-tct_hammer.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@ static void __init tct_hammer_init(void)
 }
 
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= tct_hammer_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= tct_hammer_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-vr1000.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-vr1000.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/mach-vr1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/mach-vr1000.c	2012-01-04 18:55:44.000000000 -0500
@@ -400,7 +400,7 @@ static void __init vr1000_init(void)
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= vr1000_map_io,
 	.init_machine	= vr1000_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Makefile linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@ obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_S3C2410_PM)	+= pm.o sleep.o
-obj-$(CONFIG_S3C2410_GPIO)	+= gpio.o
 obj-$(CONFIG_S3C2410_CPUFREQ)	+= cpu-freq.o
 obj-$(CONFIG_S3C2410_PLLTABLE)	+= pll.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 ifeq ($(CONFIG_PM_H1940),y)
-	zreladdr-y		:= 0x30108000
+	zreladdr-y	+= 0x30108000
 	params_phys-y	:= 0x30100100
 else
-	zreladdr-y		:= 0x30008000
+	zreladdr-y	+= 0x30008000
 	params_phys-y	:= 0x30000100
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/s3c2410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/s3c2410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2410/s3c2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2410/s3c2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,8 +72,8 @@ void __init s3c2410_init_uarts(struct s3
 
 void __init s3c2410_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,64 +50,46 @@ static struct s3c24xx_dma_map __initdata
 		.name		= "sdi",
 		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_SDI + S3C2410_SDIDATA,
-		.hw_addr.from	= S3C2410_PA_SDI + S3C2410_SDIDATA,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI0RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI1RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2412_SPI1  + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -148,11 +130,11 @@ static struct s3c24xx_dma_map __initdata
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
 				  struct s3c24xx_dma_map *map,
-				  enum s3c2410_dmasrc dir)
+				  enum dma_data_direction dir)
 {
 	unsigned long chsel;
 
-	if (dir == S3C2410_DMASRC_HW)
+	if (dir == DMA_FROM_DEVICE)
 		chsel = map->channels_rx[0];
 	else
 		chsel = map->channels[0];
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 
 int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
 {
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
 	unsigned long offs = pin - chip->chip.base;
 	unsigned long flags;
 	unsigned long slpcon;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@ config CPU_S3C2412
 	select CPU_LLSERIAL_S3C2440
 	select S3C2412_PM if PM
 	select S3C2412_DMA if S3C2410_DMA
-	select S3C2410_GPIO
 	help
 	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-jive.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-jive.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-jive.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-jive.c	2012-01-04 18:55:44.000000000 -0500
@@ -655,7 +655,7 @@ static void __init jive_machine_init(voi
 
 MACHINE_START(JIVE, "JIVE")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= jive_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-smdk2413.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-smdk2413.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-smdk2413.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-smdk2413.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,8 +92,7 @@ static struct platform_device *smdk2413_
 	&s3c_device_usbgadget,
 };
 
-static void __init smdk2413_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
+static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
 				  struct meminfo *mi)
 {
 	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
@@ -128,7 +127,7 @@ static void __init smdk2413_machine_init
 
 MACHINE_START(S3C2413, "S3C2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
@@ -139,7 +138,7 @@ MACHINE_END
 
 MACHINE_START(SMDK2412, "SMDK2412")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
@@ -150,7 +149,7 @@ MACHINE_END
 
 MACHINE_START(SMDK2413, "SMDK2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-vstms.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-vstms.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/mach-vstms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/mach-vstms.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,9 +129,8 @@ static struct platform_device *vstms_dev
 	&s3c_device_nand,
 };
 
-static void __init vstms_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
-				  struct meminfo *mi)
+static void __init vstms_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
 		mi->nr_banks=1;
@@ -156,7 +155,7 @@ static void __init vstms_init(void)
 }
 
 MACHINE_START(VSTMS, "VSTMS")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= vstms_fixup,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/Makefile linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2412/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2412/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@ obj-				:=
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
 obj-$(CONFIG_CPU_S3C2412)	+= irq.o
 obj-$(CONFIG_CPU_S3C2412)	+= clock.o
-obj-$(CONFIG_CPU_S3C2412)	+= gpio.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma.o
 obj-$(CONFIG_S3C2412_PM)	+= pm.o
 obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/clock.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include <plat/cpu.h>
 
 #include <plat/cpu-freq.h>
-#include <plat/pll6553x.h>
 #include <plat/pll.h>
 
 #include <asm/mach/map.h>
@@ -29,6 +28,14 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-s3c2443-clock.h>
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
+*/
+
 static unsigned int armdiv[8] = {
 	[0] = 1,
 	[1] = 2,
@@ -38,6 +45,32 @@ static unsigned int armdiv[8] = {
 	[7] = 8,
 };
 
+static struct clksrc_clk hsspi_eplldiv = {
+	.clk = {
+		.name	= "hsspi-eplldiv",
+		.parent	= &clk_esysclk.clk,
+		.ctrlbit = (1 << 14),
+		.enable = s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
+};
+
+static struct clk *hsspi_sources[] = {
+	[0] = &hsspi_eplldiv.clk,
+	[1] = NULL, /* to fix */
+};
+
+static struct clksrc_clk hsspi_mux = {
+	.clk	= {
+		.name	= "hsspi-if",
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = hsspi_sources,
+		.nr_sources = ARRAY_SIZE(hsspi_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
+};
+
 static struct clksrc_clk hsmmc_div[] = {
 	[0] = {
 		.clk = {
@@ -100,20 +133,15 @@ static struct clk hsmmc0_clk = {
 	.ctrlbit	= S3C2416_HCLKCON_HSMMC0,
 };
 
-static inline unsigned int s3c2416_fclk_div(unsigned long clkcon0)
-{
-	clkcon0 &= 7 << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-
-	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
 void __init_or_cpufreq s3c2416_setup_clocks(void)
 {
-	s3c2443_common_setup_clocks(s3c2416_get_pll, s3c2416_fclk_div);
+	s3c2443_common_setup_clocks(s3c2416_get_pll);
 }
 
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+	&hsspi_eplldiv,
+	&hsspi_mux,
 	&hsmmc_div[0],
 	&hsmmc_div[1],
 	&hsmmc_mux[0],
@@ -131,7 +159,9 @@ void __init s3c2416_init_clocks(int xtal
 
 	clk_epll.parent = &clk_epllref.clk;
 
-	s3c2443_common_init_clocks(xtal, s3c2416_get_pll, s3c2416_fclk_div);
+	s3c2443_common_init_clocks(xtal, s3c2416_get_pll,
+				   armdiv, ARRAY_SIZE(armdiv),
+				   S3C2416_CLKDIV0_ARMDIV_MASK);
 
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_register_clksrc(clksrcs[ptr], 1);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@ config CPU_S3C2416
 	select CPU_ARM926T
 	select S3C2416_DMA if S3C2410_DMA
 	select CPU_LLSERIAL_S3C2440
-	select S3C_GPIO_PULL_UPDOWN
 	select SAMSUNG_CLKSRC
 	select S3C2443_CLOCK
 	help
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c	2012-01-04 18:55:44.000000000 -0500
@@ -245,7 +245,7 @@ static void __init smdk2416_machine_init
 
 MACHINE_START(SMDK2416, "SMDK2416")
 	/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2416_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/s3c2416.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/s3c2416.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/s3c2416.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/s3c2416.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 #include <plat/iic-core.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -97,6 +98,8 @@ int __init s3c2416_init(void)
 
 	s3c_fb_setname("s3c2443-fb");
 
+	s3c_adc_setname("s3c2416-adc");
+
 #ifdef CONFIG_PM
 	register_syscore_ops(&s3c2416_pm_syscore_ops);
 #endif
@@ -120,8 +123,8 @@ void __init s3c2416_init_uarts(struct s3
 
 void __init s3c2416_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown;
+	s3c24xx_gpiocfg_default.set_pull = samsung_gpio_setpull_updown;
+	s3c24xx_gpiocfg_default.get_pull = samsung_gpio_getpull_updown;
 
 	/* initialize device information early */
 	s3c2416_default_sdhci0();
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,17 +12,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,30 +22,3 @@ char *s3c2416_hsmmc_clksrcs[4] = {
 	[2] = "hsmmc-if",
 	/* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	ctrl2 = __raw_readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	__raw_writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	__raw_writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,38 +48,26 @@ static struct s3c24xx_dma_map __initdata
 		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -91,31 +79,26 @@ static struct s3c24xx_dma_map __initdata
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
 		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,10 +5,8 @@
 config CPU_S3C2440
 	bool
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
-	select S3C2410_GPIO
 	select S3C2440_DMA if S3C2410_DMA
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
@@ -18,9 +16,7 @@ config CPU_S3C2440
 config CPU_S3C2442
 	bool
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_DOWN
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select S3C2410_PM if PM
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-anubis.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-anubis.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-anubis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-anubis.c	2012-01-04 18:55:44.000000000 -0500
@@ -498,7 +498,7 @@ static void __init anubis_init(void)
 
 MACHINE_START(ANUBIS, "Simtec-Anubis")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= anubis_map_io,
 	.init_machine	= anubis_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-at2440evb.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-at2440evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-at2440evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-at2440evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -233,7 +233,7 @@ static void __init at2440evb_init(void)
 
 
 MACHINE_START(AT2440EVB, "AT2440EVB")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= at2440evb_map_io,
 	.init_machine	= at2440evb_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-gta02.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-gta02.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-gta02.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-gta02.c	2012-01-04 18:55:44.000000000 -0500
@@ -595,7 +595,7 @@ static void __init gta02_machine_init(vo
 
 MACHINE_START(NEO1973_GTA02, "GTA02")
 	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gta02_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= gta02_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-mini2440.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-mini2440.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-mini2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-mini2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -676,7 +676,7 @@ static void __init mini2440_init(void)
 
 MACHINE_START(MINI2440, "MINI2440")
 	/* Maintainer: Michel Pollet <buserror@gmail.com> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= mini2440_map_io,
 	.init_machine	= mini2440_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-nexcoder.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-nexcoder.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-nexcoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-nexcoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,7 @@ static void __init nexcoder_init(void)
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= nexcoder_map_io,
 	.init_machine	= nexcoder_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-osiris.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-osiris.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-osiris.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-osiris.c	2012-01-04 18:55:44.000000000 -0500
@@ -447,7 +447,7 @@ static void __init osiris_init(void)
 
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= osiris_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= osiris_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpioj.h>
+#include <mach/regs-lcd.h>
 #include <mach/h1940.h>
 #include <mach/fb.h>
 
@@ -825,7 +826,7 @@ static void __init rx1950_reserve(void)
 
 MACHINE_START(RX1950, "HP iPAQ RX1950")
     /* Maintainers: Vasily Khoruzhick */
-	.boot_params = S3C2410_SDRAM_PA + 0x100,
+	.atag_offset = 0x100,
 	.map_io = rx1950_map_io,
 	.reserve	= rx1950_reserve,
 	.init_irq = s3c24xx_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-rx3715.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-rx3715.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-rx3715.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-rx3715.c	2012-01-04 18:55:44.000000000 -0500
@@ -218,7 +218,7 @@ static void __init rx3715_init_machine(v
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= rx3715_map_io,
 	.reserve	= rx3715_reserve,
 	.init_irq	= rx3715_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-smdk2440.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-smdk2440.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/mach-smdk2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/mach-smdk2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,7 +175,7 @@ static void __init smdk2440_machine_init
 
 MACHINE_START(S3C2440, "SMDK2440")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2440_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/s3c2440.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/s3c2440.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/s3c2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/s3c2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,6 +70,6 @@ void __init s3c2440_map_io(void)
 {
 	s3c244x_map_io();
 
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/s3c2442.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/s3c2442.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2440/s3c2442.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2440/s3c2442.c	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,6 @@ void __init s3c2442_map_io(void)
 {
 	s3c244x_map_io();
 
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/clock.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,18 +57,14 @@
 
 /* clock selections */
 
-static struct clk clk_i2s_ext = {
-	.name		= "i2s-ext",
-};
-
 /* armdiv
  *
  * this clock is sourced from msysclk and can have a number of
  * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
 */
 
-/* armdiv divisor table */
-
 static unsigned int armdiv[16] = {
 	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
 	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
@@ -80,92 +76,6 @@ static unsigned int armdiv[16] = {
 	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
 };
 
-static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
-{
-	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
-
-	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
-static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned best = 256; /* bigger than any value */
-	unsigned div;
-	int ptr;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-		div = armdiv[ptr];
-		calc = parent / div;
-		if (calc <= rate && div < best)
-			best = div;
-	}
-
-	return parent / best;
-}
-
-static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned div;
-	unsigned best = 256; /* bigger than any value */
-	int ptr;
-	int val = -1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-		div = armdiv[ptr];
-		calc = parent / div;
-		if (calc <= rate && div < best) {
-			best = div;
-			val = ptr;
-		}
-	}
-
-	if (val >= 0) {
-		unsigned long clkcon0;
-
-		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
-		clkcon0 &= ~S3C2443_CLKDIV0_ARMDIV_MASK;
-		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-		__raw_writel(clkcon0, S3C2443_CLKDIV0);
-	}
-
-	return (val == -1) ? -EINVAL : 0;
-}
-
-static struct clk clk_armdiv = {
-	.name		= "armdiv",
-	.parent		= &clk_msysclk.clk,
-	.ops		= &(struct clk_ops) {
-		.round_rate = s3c2443_armclk_roundrate,
-		.set_rate = s3c2443_armclk_setrate,
-	},
-};
-
-/* armclk
- *
- * this is the clock fed into the ARM core itself, from armdiv or from hclk.
- */
-
-static struct clk *clk_arm_sources[] = {
-	[0] = &clk_armdiv,
-	[1] = &clk_h,
-};
-
-static struct clksrc_clk clk_arm = {
-	.clk	= {
-		.name		= "armclk",
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_arm_sources,
-		.nr_sources = ARRAY_SIZE(clk_arm_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
-};
-
 /* hsspi
  *
  * high-speed spi clock, sourced from esysclk
@@ -173,7 +83,7 @@ static struct clksrc_clk clk_arm = {
 
 static struct clksrc_clk clk_hsspi = {
 	.clk	= {
-		.name		= "hsspi",
+		.name		= "hsspi-if",
 		.parent		= &clk_esysclk.clk,
 		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
 		.enable		= s3c2443_clkcon_enable_s,
@@ -235,48 +145,6 @@ static struct clk clk_hsmmc = {
 	},
 };
 
-/* i2s_eplldiv
- *
- * This clock is the output from the I2S divisor of ESYSCLK, and is separate
- * from the mux that comes after it (cannot merge into one single clock)
-*/
-
-static struct clksrc_clk clk_i2s_eplldiv = {
-	.clk	= {
-		.name		= "i2s-eplldiv",
-		.parent		= &clk_esysclk.clk,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
-};
-
-/* i2s-ref
- *
- * i2s bus reference clock, selectable from external, esysclk or epllref
- *
- * Note, this used to be two clocks, but was compressed into one.
-*/
-
-struct clk *clk_i2s_srclist[] = {
-	[0] = &clk_i2s_eplldiv.clk,
-	[1] = &clk_i2s_ext,
-	[2] = &clk_epllref.clk,
-	[3] = &clk_epllref.clk,
-};
-
-static struct clksrc_clk clk_i2s = {
-	.clk	= {
-		.name		= "i2s-if",
-		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
-		.enable		= s3c2443_clkcon_enable_s,
-
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_i2s_srclist,
-		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
-};
-
 /* standard clock definitions */
 
 static struct clk init_clocks_off[] = {
@@ -286,11 +154,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SDI,
 	}, {
-		.name		= "iis",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_IIS,
-	}, {
 		.name		= "spi",
 		.devname	= "s3c2410-spi.0",
 		.parent		= &clk_p,
@@ -305,27 +168,20 @@ static struct clk init_clocks_off[] = {
 	}
 };
 
-static struct clk init_clocks[] = {
-};
-
 /* clocks to add straight away */
 
 static struct clksrc_clk *clksrcs[] __initdata = {
-	&clk_arm,
-	&clk_i2s_eplldiv,
-	&clk_i2s,
 	&clk_hsspi,
 	&clk_hsmmc_div,
 };
 
 static struct clk *clks[] __initdata = {
 	&clk_hsmmc,
-	&clk_armdiv,
 };
 
 void __init_or_cpufreq s3c2443_setup_clocks(void)
 {
-	s3c2443_common_setup_clocks(s3c2443_get_mpll, s3c2443_fclk_div);
+	s3c2443_common_setup_clocks(s3c2443_get_mpll);
 }
 
 void __init s3c2443_init_clocks(int xtal)
@@ -336,7 +192,9 @@ void __init s3c2443_init_clocks(int xtal
 	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
 	clk_epll.parent = &clk_epllref.clk;
 
-	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, s3c2443_fclk_div);
+	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll,
+				   armdiv, ARRAY_SIZE(armdiv),
+				   S3C2443_CLKDIV0_ARMDIV_MASK);
 
 	s3c2443_setup_clocks();
 
@@ -345,10 +203,6 @@ void __init s3c2443_init_clocks(int xtal
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_register_clksrc(clksrcs[ptr], 1);
 
-	/* register clocks from clock array */
-
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
 	/* We must be careful disabling the clocks we are not intending to
 	 * be using at boot time, as subsystems such as the LCD which do
 	 * their own DMA requests to the bus can cause the system to lockup
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,68 +54,46 @@ static struct s3c24xx_dma_map __initdata
 	[DMACH_SDI] = {
 		.name		= "sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI0TX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI1TX),
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_0),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3_SRC2] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_1),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -124,27 +102,22 @@ static struct s3c24xx_dma_map __initdata
 	[DMACH_I2S_IN] = {
 		.name		= "i2s-sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2SRX),
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2STX),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMOUT),
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_MICIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@ config CPU_S3C2443
 	select CPU_LLSERIAL_S3C2440
 	select SAMSUNG_CLKSRC
 	select S3C2443_CLOCK
-	select S3C_GPIO_PULL_S3C2443
 	help
 	  Support for the S3C2443 SoC from the S3C24XX line
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@ static void __init smdk2443_machine_init
 
 MACHINE_START(SMDK2443, "SMDK2443")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2443_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/s3c2443.c linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/s3c2443.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c2443/s3c2443.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c2443/s3c2443.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <plat/cpu.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -70,6 +71,8 @@ int __init s3c2443_init(void)
 	s3c_nand_setname("s3c2412-nand");
 	s3c_fb_setname("s3c2443-fb");
 
+	s3c_adc_setname("s3c2443-adc");
+
 	/* change WDT IRQ number */
 	s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
 	s3c_device_wdt.resource[1].end   = IRQ_S3C2443_WDT;
@@ -90,8 +93,8 @@ void __init s3c2443_init_uarts(struct s3
 
 void __init s3c2443_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_s3c2443;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_s3c2443;
+	s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
+	s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
 	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/clock.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,13 +25,13 @@
 
 #include <mach/regs-sys.h>
 #include <mach/regs-clock.h>
-#include <mach/pll.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/cpu-freq.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
+#include <plat/pll.h>
 
 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  * ext_xtal_mux for want of an actual name from the manual.
@@ -735,7 +735,8 @@ void __init_or_cpufreq s3c6400_setup_clo
 	/* For now assume the mux always selects the crystal */
 	clk_ext_xtal_mux.parent = xtal_clk;
 
-	epll = s3c6400_get_epll(xtal);
+	epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
+				__raw_readl(S3C_EPLL_CON1));
 	mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
 	apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
 
@@ -744,7 +745,13 @@ void __init_or_cpufreq s3c6400_setup_clo
 	printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
 	       apll, mpll, epll);
 
-	hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+	if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
+		/* Synchronous mode */
+		hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+	else
+		/* Asynchronous mode */
+		hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+
 	hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
 	pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/map.h>
@@ -33,8 +34,8 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 /* table of supported CPUs */
 
@@ -43,16 +44,16 @@ static const char name_s3c6410[] = "S3C6
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x36400000,
-		.idmask		= 0xfffff000,
+		.idcode		= S3C6400_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6400_map_io,
 		.init_clocks	= s3c6400_init_clocks,
 		.init_uarts	= s3c6400_init_uarts,
 		.init		= s3c6400_init,
 		.name		= name_s3c6400,
 	}, {
-		.idcode		= 0x36410100,
-		.idmask		= 0xffffff00,
+		.idcode		= S3C6410_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6410_map_io,
 		.init_clocks	= s3c6410_init_clocks,
 		.init_uarts	= s3c6410_init_uarts,
@@ -140,22 +141,15 @@ void __init s3c6400_common_init_uarts(st
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 	iotable_init(mach_desc, size);
+	init_consistent_dma_size(SZ_8M);
 
-	idcode = __raw_readl(S3C_VA_SYS + 0x118);
-	if (!idcode) {
-		/* S3C6400 has the ID register in a different place,
-		 * and needs a write before it can be read. */
-
-		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
-		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
-	}
+	/* detect cpu id */
+	s3c64xx_init_cpu();
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
 static __init int s3c64xx_sysdev_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-audio.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-audio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 
 #include <mach/irqs.h>
 #include <mach/map.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-onenand1.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-onenand1.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-onenand1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-onenand1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c64xx/dev-onenand1.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX series device definition for OneNAND devices
- *
- * 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/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c64xx_onenand1_resources[] = {
-	[0] = {
-		.start	= S3C64XX_PA_ONENAND1,
-		.end	= S3C64XX_PA_ONENAND1 + 0x400 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S3C64XX_PA_ONENAND1_BUF,
-		.end	= S3C64XX_PA_ONENAND1_BUF + S3C64XX_SZ_ONENAND1_BUF - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND1,
-		.end	= IRQ_ONENAND1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c64xx_device_onenand1 = {
-	.name		= "samsung-onenand",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s3c64xx_onenand1_resources),
-	.resource	= s3c64xx_onenand1_resources,
-};
-
-void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
-			 &s3c64xx_device_onenand1);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-spi.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-spi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-uart.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-uart.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dev-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_res
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX0,
-		.end	= IRQ_S3CUART_RX0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX0,
-		.end	= IRQ_S3CUART_TX0,
+		.start	= IRQ_UART0,
+		.end	= IRQ_UART0,
 		.flags	= IORESOURCE_IRQ,
-
 	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR0,
-		.end	= IRQ_S3CUART_ERR0,
-		.flags	= IORESOURCE_IRQ,
-	}
 };
 
 static struct resource s3c64xx_uart1_resource[] = {
@@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_res
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX1,
-		.end	= IRQ_S3CUART_RX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX1,
-		.end	= IRQ_S3CUART_TX1,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR1,
-		.end	= IRQ_S3CUART_ERR1,
+		.start	= IRQ_UART1,
+		.end	= IRQ_UART1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_reso
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX2,
-		.end	= IRQ_S3CUART_RX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX2,
-		.end	= IRQ_S3CUART_TX2,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR2,
-		.end	= IRQ_S3CUART_ERR2,
+		.start	= IRQ_UART2,
+		.end	= IRQ_UART2,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_res
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX3,
-		.end	= IRQ_S3CUART_RX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX3,
-		.end	= IRQ_S3CUART_TX3,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR3,
-		.end	= IRQ_S3CUART_ERR3,
+		.start	= IRQ_UART3,
+		.end	= IRQ_UART3,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct
 	u32 control0, control1;
 
 	switch (chan->source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		src = chan->dev_addr;
 		dst = data;
 		control0 = PL080_CONTROL_SRC_AHB2;
 		control0 |= PL080_CONTROL_DST_INCR;
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		src = data;
 		dst = chan->dev_addr;
 		control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(enum dma_ch ch
 	pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
 		break;
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
 		break;
@@ -740,7 +740,7 @@ static int __init s3c64xx_dma_init(void)
 	}
 
 	/* Set all DMA configuration to be DMA, not SDMA */
-	writel(0xffffff, S3C_SYSREG(0x110));
+	writel(0xffffff, S3C64XX_SDMA_SEL);
 
 	/* Register standard DMA controllers */
 	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/gpiolib.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/gpiolib.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,290 +0,0 @@
-/* arch/arm/plat-s3c64xx/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - GPIOlib support 
- *
- * 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/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/regs-gpio.h>
-
-/* GPIO bank summary:
- *
- * Bank	GPIOs	Style	SlpCon	ExtInt Group
- * A	8	4Bit	Yes	1
- * B	7	4Bit	Yes	1
- * C	8	4Bit	Yes	2
- * D	5	4Bit	Yes	3
- * E	5	4Bit	Yes	None
- * F	16	2Bit	Yes	4 [1]
- * G	7	4Bit	Yes	5
- * H	10	4Bit[2]	Yes	6
- * I	16	2Bit	Yes	None
- * J	12	2Bit	Yes	None
- * K	16	4Bit[2]	No	None
- * L	15	4Bit[2] No	None
- * M	6	4Bit	No	IRQ_EINT
- * N	16	2Bit	No	IRQ_EINT
- * O	16	2Bit	Yes	7
- * P	15	2Bit	Yes	8
- * Q	9	2Bit	Yes	9
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
-	.cfg_eint	= 7,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
-	.cfg_eint	= 3,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
-{
-	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit[] = {
-	{
-		.base	= S3C64XX_GPA_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPA(0),
-			.ngpio	= S3C64XX_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.base	= S3C64XX_GPB_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPB(0),
-			.ngpio	= S3C64XX_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S3C64XX_GPC_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPC(0),
-			.ngpio	= S3C64XX_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S3C64XX_GPD_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPD(0),
-			.ngpio	= S3C64XX_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.base	= S3C64XX_GPE_BASE,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPE(0),
-			.ngpio	= S3C64XX_GPIO_E_NR,
-			.label	= "GPE",
-		},
-	}, {
-		.base	= S3C64XX_GPG_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPG(0),
-			.ngpio	= S3C64XX_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	}, {
-		.base	= S3C64XX_GPM_BASE,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPM(0),
-			.ngpio	= S3C64XX_GPIO_M_NR,
-			.label	= "GPM",
-			.to_irq = s3c64xx_gpio2int_gpm,
-		},
-	},
-};
-
-static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
-{
-	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit2[] = {
-	{
-		.base	= S3C64XX_GPH_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPH(0),
-			.ngpio	= S3C64XX_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	}, {
-		.base	= S3C64XX_GPK_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPK(0),
-			.ngpio	= S3C64XX_GPIO_K_NR,
-			.label	= "GPK",
-		},
-	}, {
-		.base	= S3C64XX_GPL_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPL(0),
-			.ngpio	= S3C64XX_GPIO_L_NR,
-			.label	= "GPL",
-			.to_irq = s3c64xx_gpio2int_gpl,
-		},
-	},
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
-	.cfg_eint	= 2,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
-	.cfg_eint	= 3,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_chip gpio_2bit[] = {
-	{
-		.base	= S3C64XX_GPF_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPF(0),
-			.ngpio	= S3C64XX_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S3C64XX_GPI_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPI(0),
-			.ngpio	= S3C64XX_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S3C64XX_GPJ_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPJ(0),
-			.ngpio	= S3C64XX_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S3C64XX_GPN_BASE,
-		.irq_base = IRQ_EINT(0),
-		.config	= &gpio_2bit_cfg_eint10,
-		.chip	= {
-			.base	= S3C64XX_GPN(0),
-			.ngpio	= S3C64XX_GPIO_N_NR,
-			.label	= "GPN",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= S3C64XX_GPO_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPO(0),
-			.ngpio	= S3C64XX_GPIO_O_NR,
-			.label	= "GPO",
-		},
-	}, {
-		.base	= S3C64XX_GPP_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPP(0),
-			.ngpio	= S3C64XX_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	}, {
-		.base	= S3C64XX_GPQ_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPQ(0),
-			.ngpio	= S3C64XX_GPIO_Q_NR,
-			.label	= "GPQ",
-		},
-	},
-};
-
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-				       int nr_chips,
-				       void (*fn)(struct s3c_gpio_chip *))
-{
-	for (; nr_chips > 0; nr_chips--, chips++) {
-		if (fn)
-			(fn)(chips);
-		s3c_gpiolib_add(chips);
-	}
-}
-
-static __init int s3c64xx_gpiolib_init(void)
-{
-	s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-			    samsung_gpiolib_add_4bit);
-
-	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-			    samsung_gpiolib_add_4bit2);
-
-	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-			    s3c64xx_gpiolib_add_2bit);
-
-	return 0;
-}
-
-core_initcall(s3c64xx_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/crag6410.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/crag6410.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/crag6410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/crag6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/* Cragganmore 6410 shared definitions
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *	Mark Brown <broonie@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_CRAG6410_H
+#define MACH_CRAG6410_H
+
+#include <linux/gpio.h>
+
+#define BANFF_PMIC_IRQ_BASE		IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE	(IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE		GPIO_BOARD_START
+#define CODEC_GPIO_BASE		(GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE	(GPIO_BOARD_START + 16)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -58,11 +58,15 @@ enum dma_ch {
 	DMACH_MAX		/* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
 #define S3C2410_DMAF_CIRCULAR		(1 << 0)
 
 #include <plat/dma.h>
@@ -95,7 +99,7 @@ struct s3c2410_dma_chan {
 	unsigned char		 peripheral;
 
 	unsigned int		 flags;
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 
 
 	dma_addr_t		dev_addr;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,6 @@
  * published by the Free Software Foundation.
 */
 
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
 /* GPIO bank sizes */
 #define S3C64XX_GPIO_A_NR	(8)
 #define S3C64XX_GPIO_B_NR	(7)
@@ -96,5 +91,3 @@ enum s3c_gpio_number {
 #define BOARD_NR_GPIOS 16
 
 #define ARCH_NR_GPIOS	(GPIO_BOARD_START + BOARD_NR_GPIOS)
-
-#include <asm-generic/gpio.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,36 +27,6 @@
 #define IRQ_VIC0_BASE	S3C_IRQ(0)
 #define IRQ_VIC1_BASE	S3C_IRQ(32)
 
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0	(16)
-#define IRQ_S3CUART_BASE1	(20)
-#define IRQ_S3CUART_BASE2	(24)
-#define IRQ_S3CUART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-#define UART_IRQ_MODEM		(3)
-
-#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
 /* VIC based IRQs */
 
 #define S3C64XX_IRQ_VIC0(x)	(IRQ_VIC0_BASE + (x))
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #define __ASM_ARCH_MAP_H __FILE__
 
 #include <plat/map-base.h>
+#include <plat/map-s3c.h>
 
 /*
  * Post-mux Chip Select Regions Xm0CSn_
@@ -83,7 +84,6 @@
 #define S3C64XX_PA_IIC1		(0x7F00F000)
 
 #define S3C64XX_PA_GPIO		(0x7F008000)
-#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
 #define S3C64XX_SZ_GPIO		SZ_4K
 
 #define S3C64XX_PA_SDRAM	(0x50000000)
@@ -94,16 +94,10 @@
 #define S3C64XX_PA_VIC1		(0x71300000)
 
 #define S3C64XX_PA_MODEM	(0x74108000)
-#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
 
 #define S3C64XX_PA_USBHOST	(0x74300000)
 
 #define S3C64XX_PA_USB_HSPHY	(0x7C100000)
-#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
-
-/* place VICs close together */
-#define VA_VIC0			(S3C_VA_IRQ + 0x00)
-#define VA_VIC1			(S3C_VA_IRQ + 0x10000)
 
 /* compatibiltiy defines. */
 #define S3C_PA_TIMER		S3C64XX_PA_TIMER
@@ -119,7 +113,6 @@
 #define S3C_PA_FB		S3C64XX_PA_FB
 #define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
 #define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
-#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
 #define S3C_PA_RTC		S3C64XX_PA_RTC
 #define S3C_PA_WDT		S3C64XX_PA_WATCHDOG
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/memory.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET     UL(0x50000000)
-
-#define CONSISTENT_DMA_SIZE	SZ_8M
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pll.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pll.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX PLL code
- *
- * 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.
-*/
-
-#define S3C6400_PLL_MDIV_MASK	((1 << (25-16+1)) - 1)
-#define S3C6400_PLL_PDIV_MASK	((1 << (13-8+1)) - 1)
-#define S3C6400_PLL_SDIV_MASK	((1 << (2-0+1)) - 1)
-#define S3C6400_PLL_MDIV_SHIFT	(16)
-#define S3C6400_PLL_PDIV_SHIFT	(8)
-#define S3C6400_PLL_SDIV_SHIFT	(0)
-
-#include <asm/div64.h>
-#include <plat/pll6553x.h>
-
-static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
-					    u32 pllcon)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
-	pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
-	sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-static inline unsigned long s3c6400_get_epll(unsigned long baseclk)
-{
-	return s3c_get_pll6553x(baseclk, __raw_readl(S3C_EPLL_CON0),
-				__raw_readl(S3C_EPLL_CON1));
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@ static inline void s3c_pm_restored_gpios
 	__raw_writel(0, S3C64XX_SLPEN);
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_pm_saved_gpios(void)
 {
 	/* turn on the sleep mode and keep it there, as it seems that during
 	 * suspend the xCON registers get re-set and thus you can end up with
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64xx - pwm clock and timer support
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/regs-sys.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/regs-sys.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/regs-sys.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,11 @@
 #define S3C64XX_AHB_CON1	S3C_SYSREG(0x104)
 #define S3C64XX_AHB_CON2	S3C_SYSREG(0x108)
 
+#define S3C64XX_SDMA_SEL	S3C_SYSREG(0x110)
+
 #define S3C64XX_OTHERS		S3C_SYSREG(0x900)
 
 #define S3C64XX_OTHERS_USBMASK	(1 << 16)
+#define S3C64XX_OTHERS_SYNCMUXSEL	(1 << 6)
 
 #endif /* _PLAT_REGS_SYS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6400.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6400.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6400.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6400.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/macht/s3c6400.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6400 cpu support
- *
- * 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.
-*/
-
-/* Common init code for S3C6400 related SoCs */
-
-extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s3c6400_setup_clocks(void);
-
-extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
-
-#ifdef CONFIG_CPU_S3C6400
-
-extern  int s3c6400_init(void);
-extern void s3c6400_init_irq(void);
-extern void s3c6400_map_io(void);
-extern void s3c6400_init_clocks(int xtal);
-
-#define s3c6400_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6400_init_clocks NULL
-#define s3c6400_init_uarts NULL
-#define s3c6400_map_io NULL
-#define s3c6400_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6410.h linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6410.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/include/mach/s3c6410.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/mach/s3c6410.h
- *
- * Copyright 2008 Openmoko,  Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6410 cpu support
- *
- * 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.
-*/
-
-#ifdef CONFIG_CPU_S3C6410
-
-extern  int s3c6410_init(void);
-extern void s3c6410_init_irq(void);
-extern void s3c6410_map_io(void);
-extern void s3c6410_init_clocks(int xtal);
-
-#define s3c6410_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6410_init_clocks NULL
-#define s3c6410_init_uarts NULL
-#define s3c6410_map_io NULL
-#define s3c6410_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/irq.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/irq.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,29 +25,6 @@
 #include <plat/irq-uart.h>
 #include <plat/cpu.h>
 
-static struct s3c_uart_irq uart_irqs[] = {
-	[0] = {
-		.regs		= S3C_VA_UART0,
-		.base_irq	= IRQ_S3CUART_BASE0,
-		.parent_irq	= IRQ_UART0,
-	},
-	[1] = {
-		.regs		= S3C_VA_UART1,
-		.base_irq	= IRQ_S3CUART_BASE1,
-		.parent_irq	= IRQ_UART1,
-	},
-	[2] = {
-		.regs		= S3C_VA_UART2,
-		.base_irq	= IRQ_S3CUART_BASE2,
-		.parent_irq	= IRQ_UART2,
-	},
-	[3] = {
-		.regs		= S3C_VA_UART3,
-		.base_irq	= IRQ_S3CUART_BASE3,
-		.parent_irq	= IRQ_UART3,
-	},
-};
-
 /* setup the sources the vic should advertise resume for, even though it
  * is not doing the wake (set_irq_wake needs to be valid) */
 #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
@@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_va
 
 	/* add the timer sub-irqs */
 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
-	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -288,5 +288,6 @@ config MACH_WLF_CRAGG_6410
 	select S3C_DEV_RTC
 	select S3C64XX_DEV_SPI
 	select S3C24XX_GPIO_EXTRA128
+	select I2C
 	help
 	  Machine support for the Wolfson Cragganmore S3C6410 variant.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-anw6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-anw6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-anw6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-anw6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,7 @@
 #include <plat/fb.h>
 #include <plat/regs-fb-v4.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -233,7 +233,7 @@ static void __init anw6410_machine_init(
 
 MACHINE_START(ANW6410, "A&W6410")
 	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= anw6410_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-crag6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-crag6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-crag6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-crag6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,13 +43,14 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 
-#include <mach/s3c6410.h>
 #include <mach/regs-sys.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
+#include <mach/crag6410.h>
 
 #include <mach/regs-gpio-memport.h>
 
+#include <plat/s3c6410.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
@@ -65,17 +66,6 @@
 #include <plat/iic.h>
 #include <plat/pm.h>
 
-#include <sound/wm8996.h>
-#include <sound/wm8962.h>
-#include <sound/wm9081.h>
-
-#define BANFF_PMIC_IRQ_BASE		IRQ_BOARD_START
-#define GLENFARCLAS_PMIC_IRQ_BASE	(IRQ_BOARD_START + 64)
-
-#define PCA935X_GPIO_BASE		GPIO_BOARD_START
-#define CODEC_GPIO_BASE		(GPIO_BOARD_START + 8)
-#define GLENFARCLAS_PMIC_GPIO_BASE	(GPIO_BOARD_START + 16)
-
 /* serial port setup */
 
 #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
@@ -287,6 +277,11 @@ static struct platform_device speyside_d
 	.id		= -1,
 };
 
+static struct platform_device lowland_device = {
+	.name		= "lowland",
+	.id		= -1,
+};
+
 static struct platform_device speyside_wm8962_device = {
 	.name		= "speyside-wm8962",
 	.id		= -1,
@@ -295,6 +290,8 @@ static struct platform_device speyside_w
 static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
 	REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+	REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
+	REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 };
 
 static struct regulator_init_data wallvdd_data = {
@@ -329,9 +326,6 @@ static struct platform_device *crag6410_
 	&s3c_device_fb,
 	&s3c_device_ohci,
 	&s3c_device_usb_hsotg,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_ts,
 	&s3c_device_timer[0],
 	&s3c64xx_device_iis0,
 	&s3c64xx_device_iis1,
@@ -345,6 +339,7 @@ static struct platform_device *crag6410_
 	&crag6410_backlight_device,
 	&speyside_device,
 	&speyside_wm8962_device,
+	&lowland_device,
 	&wallvdd_device,
 };
 
@@ -353,6 +348,12 @@ static struct pca953x_platform_data crag
 	.irq_base	= 0,
 };
 
+/* VDDARM is controlled by DVS1 connected to GPK(0) */
+static struct wm831x_buckv_pdata vddarm_pdata = {
+	.dvs_control_src = 1,
+	.dvs_gpio = S3C64XX_GPK(0),
+};
+
 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
 	REGULATOR_SUPPLY("vddarm", NULL),
 };
@@ -368,6 +369,7 @@ static struct regulator_init_data vddarm
 	.num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
 	.consumer_supplies = vddarm_consumers,
 	.supply_regulator = "WALLVDD",
+	.driver_data = &vddarm_pdata,
 };
 
 static struct regulator_init_data vddint __initdata = {
@@ -503,6 +505,8 @@ static struct wm831x_pdata crag_pmic_pda
 	.backup = &banff_backup_pdata,
 
 	.gpio_defaults = {
+		/* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
+		[4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
 		/* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
 		[10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
 		/* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
@@ -560,8 +564,12 @@ static struct regulator_init_data pvdd_1
 };
 
 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+	REGULATOR_SUPPLY("LDOVDD", "1-001a"),
 	REGULATOR_SUPPLY("PLLVDD", "1-001a"),
 	REGULATOR_SUPPLY("DBVDD", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD1", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD2", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD3", "1-001a"),
 	REGULATOR_SUPPLY("CPVDD", "1-001a"),
 	REGULATOR_SUPPLY("AVDD2", "1-001a"),
 	REGULATOR_SUPPLY("DCVDD", "1-001a"),
@@ -614,81 +622,16 @@ static struct wm831x_pdata glenfarclas_p
 	.disable_touch = true,
 };
 
-static struct wm8996_retune_mobile_config wm8996_retune[] = {
-	{
-		.name = "Sub LPF",
-		.rate = 48000,
-		.regs = {
-			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-		},
-	},
-	{
-		.name = "Sub HPF",
-		.rate = 48000,
-		.regs = {
-			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-		},
-	},
-};
-
-static struct wm8996_pdata wm8996_pdata __initdata = {
-	.ldo_ena = S3C64XX_GPN(7),
-	.gpio_base = CODEC_GPIO_BASE,
-	.micdet_def = 1,
-	.inl_mode = WM8996_DIFFERRENTIAL_1,
-	.inr_mode = WM8996_DIFFERRENTIAL_1,
-
-	.irq_flags = IRQF_TRIGGER_RISING,
-
-	.gpio_default = {
-		0x8001, /* GPIO1 == ADCLRCLK1 */
-		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
-		0x0141, /* GPIO3 == HP_SEL */
-		0x0002, /* GPIO4 == IRQ */
-		0x020e, /* GPIO5 == CLKOUT */
-	},
-
-	.retune_mobile_cfgs = wm8996_retune,
-	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
-};
-
-static struct wm8962_pdata wm8962_pdata __initdata = {
-	.gpio_init = {
-		0,
-		WM8962_GPIO_FN_OPCLK,
-		WM8962_GPIO_FN_DMICCLK,
-		0,
-		0x8000 | WM8962_GPIO_FN_DMICDAT,
-		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
-	},
-	.irq_active_low = true,
-};
-
-static struct wm9081_pdata wm9081_pdata __initdata = {
-	.irq_high = false,
-	.irq_cmos = false,
-};
-
 static struct i2c_board_info i2c_devs1[] __initdata = {
 	{ I2C_BOARD_INFO("wm8311", 0x34),
 	  .irq = S3C_EINT(0),
 	  .platform_data = &glenfarclas_pmic_pdata },
 
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x24) },
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x25) },
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x26) },
+
 	{ I2C_BOARD_INFO("wm1250-ev1", 0x27) },
-	{ I2C_BOARD_INFO("wm8996", 0x1a),
-	  .platform_data = &wm8996_pdata,
-	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-	},
-	{ I2C_BOARD_INFO("wm9081", 0x6c),
-	  .platform_data = &wm9081_pdata, },
-	{ I2C_BOARD_INFO("wm8962", 0x1a),
-	  .platform_data = &wm8962_pdata,
-	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-	},
 };
 
 static void __init crag6410_map_io(void)
@@ -766,7 +709,7 @@ static void __init crag6410_machine_init
 
 MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
 	/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= crag6410_map_io,
 	.init_machine	= crag6410_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-crag6410-module.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-crag6410-module.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-crag6410-module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-crag6410-module.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,182 @@
+/* Speyside modules for Cragganmore - board data probing
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *	Mark Brown <broonie@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <sound/wm8996.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#include <mach/crag6410.h>
+
+static struct wm8996_retune_mobile_config wm8996_retune[] = {
+	{
+		.name = "Sub LPF",
+		.rate = 48000,
+		.regs = {
+			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+	{
+		.name = "Sub HPF",
+		.rate = 48000,
+		.regs = {
+			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+};
+
+static struct wm8996_pdata wm8996_pdata __initdata = {
+	.ldo_ena = S3C64XX_GPN(7),
+	.gpio_base = CODEC_GPIO_BASE,
+	.micdet_def = 1,
+	.inl_mode = WM8996_DIFFERRENTIAL_1,
+	.inr_mode = WM8996_DIFFERRENTIAL_1,
+
+	.irq_flags = IRQF_TRIGGER_RISING,
+
+	.gpio_default = {
+		0x8001, /* GPIO1 == ADCLRCLK1 */
+		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+		0x0141, /* GPIO3 == HP_SEL */
+		0x0002, /* GPIO4 == IRQ */
+		0x020e, /* GPIO5 == CLKOUT */
+	},
+
+	.retune_mobile_cfgs = wm8996_retune,
+	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+	.gpio_init = {
+		0,
+		WM8962_GPIO_FN_OPCLK,
+		WM8962_GPIO_FN_DMICCLK,
+		0,
+		0x8000 | WM8962_GPIO_FN_DMICDAT,
+		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
+	},
+	.irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+	.irq_high = false,
+	.irq_cmos = false,
+};
+
+static const struct i2c_board_info wm1254_devs[] = {
+	{ I2C_BOARD_INFO("wm8996", 0x1a),
+	  .platform_data = &wm8996_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+	{ I2C_BOARD_INFO("wm9081", 0x6c),
+	  .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1255_devs[] = {
+	{ I2C_BOARD_INFO("wm5100", 0x1a),
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+	{ I2C_BOARD_INFO("wm9081", 0x6c),
+	  .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1259_devs[] = {
+	{ I2C_BOARD_INFO("wm8962", 0x1a),
+	  .platform_data = &wm8962_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+};
+
+
+static __devinitdata const struct {
+	u8 id;
+	const char *name;
+	const struct i2c_board_info *i2c_devs;
+	int num_i2c_devs;
+} gf_mods[] = {
+	{ .id = 0x01, .name = "1250-EV1 Springbank" },
+	{ .id = 0x02, .name = "1251-EV1 Jura" },
+	{ .id = 0x03, .name = "1252-EV1 Glenlivet" },
+	{ .id = 0x11, .name = "6249-EV2 Glenfarclas", },
+	{ .id = 0x21, .name = "1275-EV1 Mortlach" },
+	{ .id = 0x25, .name = "1274-EV1 Glencadam" },
+	{ .id = 0x31, .name = "1253-EV1 Tomatin", },
+	{ .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+	  .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
+	{ .id = 0x3a, .name = "1259-EV1 Tobermory",
+	  .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
+	{ .id = 0x3b, .name = "1255-EV1 Kilchoman",
+	  .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
+	{ .id = 0x3c, .name = "1273-EV1 Longmorn" },
+};
+
+static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
+					 const struct i2c_device_id *i2c_id)
+{
+	int ret, i, j, id, rev;
+
+	ret = i2c_smbus_read_byte_data(i2c, 0);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
+		return ret;
+	}
+
+	id = (ret & 0xfe) >> 2;
+	rev = ret & 0x3;
+	for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
+		if (id == gf_mods[i].id)
+			break;
+
+	if (i < ARRAY_SIZE(gf_mods)) {
+		dev_info(&i2c->dev, "%s revision %d\n",
+			 gf_mods[i].name, rev + 1);
+		for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
+			if (!i2c_new_device(i2c->adapter,
+					    &(gf_mods[i].i2c_devs[j])))
+				dev_err(&i2c->dev,
+					"Failed to register dev: %d\n", ret);
+		}
+	} else {
+		dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
+			 id, rev);
+	}
+
+	return 0;
+}
+
+static const struct i2c_device_id wlf_gf_module_id[] = {
+	{ "wlf-gf-module", 0 },
+	{ }
+};
+
+static struct i2c_driver wlf_gf_module_driver = {
+	.driver = {
+		.name = "wlf-gf-module",
+		.owner = THIS_MODULE,
+	},
+	.probe = wlf_gf_module_probe,
+	.id_table = wlf_gf_module_id,
+};
+
+static int __init wlf_gf_module_register(void)
+{
+	return i2c_add_driver(&wlf_gf_module_driver);
+}
+module_init(wlf_gf_module_register);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-hmt.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-hmt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-hmt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-hmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <plat/fb.h>
 #include <plat/nand.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -265,7 +265,7 @@ static void __init hmt_machine_init(void
 
 MACHINE_START(HMT, "Airgoo-HMT")
 	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= hmt_map_io,
 	.init_machine	= hmt_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-mini6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-mini6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-mini6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-mini6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -205,12 +205,6 @@ static struct platform_device mini6410_l
 	.dev.platform_data	= &mini6410_lcd_power_data,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static struct platform_device *mini6410_devices[] __initdata = {
 	&mini6410_device_eth,
 	&s3c_device_hsmmc0,
@@ -319,7 +313,7 @@ static void __init mini6410_machine_init
 
 	s3c_nand_set_platdata(&mini6410_nand_info);
 	s3c_fb_set_platdata(&mini6410_lcd_pdata);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -349,7 +343,7 @@ static void __init mini6410_machine_init
 
 MACHINE_START(MINI6410, "MINI6410")
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= mini6410_map_io,
 	.init_machine	= mini6410_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-ncp.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-ncp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-ncp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-ncp.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 #include <plat/iic.h>
 #include <plat/fb.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -97,7 +97,7 @@ static void __init ncp_machine_init(void
 
 MACHINE_START(NCP, "NCP")
 	/* Maintainer: Samsung Electronics */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= ncp_map_io,
 	.init_machine	= ncp_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-real6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-real6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-real6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-real6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -198,12 +198,6 @@ static struct platform_device *real6410_
 	&s3c_device_ohci,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static void __init real6410_map_io(void)
 {
 	u32 tmp;
@@ -300,7 +294,7 @@ static void __init real6410_machine_init
 
 	s3c_fb_set_platdata(&real6410_lcd_pdata);
 	s3c_nand_set_platdata(&real6410_nand_info);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -329,7 +323,7 @@ static void __init real6410_machine_init
 
 MACHINE_START(REAL6410, "REAL6410")
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= real6410_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smartq5.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smartq5.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smartq5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smartq5.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
@@ -146,7 +146,7 @@ static void __init smartq5_machine_init(
 
 MACHINE_START(SMARTQ5, "SmartQ 5")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq5_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smartq7.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smartq7.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smartq7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smartq7.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
@@ -162,7 +162,7 @@ static void __init smartq7_machine_init(
 
 MACHINE_START(SMARTQ7, "SmartQ 7")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq7_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smdk6400.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smdk6400.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smdk6400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smdk6400.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <plat/regs-serial.h>
 
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -85,7 +85,7 @@ static void __init smdk6400_machine_init
 
 MACHINE_START(SMDK6400, "SMDK6400")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6400_init_irq,
 	.map_io		= smdk6400_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -619,12 +619,6 @@ static struct i2c_board_info i2c_devs1[]
 	{ I2C_BOARD_INFO("24c128", 0x57), },	/* Samsung S524AD0XD1 */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
 	.no = S3C64XX_GPF(15),
@@ -666,7 +660,7 @@ static void __init smdk6410_machine_init
 
 	samsung_keypad_set_platdata(&smdk6410_keypad_data);
 
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -703,7 +697,7 @@ static void __init smdk6410_machine_init
 
 MACHINE_START(SMDK6410, "SMDK6410")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smdk6410_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Makefile linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@ obj-				:=
 # Core files
 obj-y				+= cpu.o
 obj-y				+= clock.o
-obj-y				+= gpiolib.o
 
 # Core support for S3C6400 system
 
@@ -55,12 +54,10 @@ obj-$(CONFIG_MACH_HMT)		+= mach-hmt.o
 obj-$(CONFIG_MACH_SMARTQ)	+= mach-smartq.o
 obj-$(CONFIG_MACH_SMARTQ5)	+= mach-smartq5.o
 obj-$(CONFIG_MACH_SMARTQ7)	+= mach-smartq7.o
-obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
 
 # device support
 
 obj-y				+= dev-uart.o
 obj-y				+= dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
-obj-$(CONFIG_S3C64XX_DEV_TS)	+= dev-ts.o
-obj-$(CONFIG_S3C64XX_DEV_ONENAND1)	+= dev-onenand1.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x50008000
+   zreladdr-y	+= 0x50008000
 params_phys-y	:= 0x50000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/pm.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-syscon-power.h>
 #include <mach/regs-gpio-memport.h>
+#include <mach/regs-modem.h>
 
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
 void s3c_pm_debug_smdkled(u32 set, u32 clear)
@@ -85,6 +86,9 @@ static struct sleep_save misc_save[] = {
 	SAVE_ITEM(S3C64XX_MEM0CONSLP0),
 	SAVE_ITEM(S3C64XX_MEM0CONSLP1),
 	SAVE_ITEM(S3C64XX_MEM1CONSLP),
+
+	SAVE_ITEM(S3C64XX_SDMA_SEL),
+	SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
 };
 
 void s3c_pm_configure_extint(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/s3c6400.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/s3c6400.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/s3c6400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/s3c6400.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <plat/sdhci.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 
 void __init s3c6400_map_io(void)
 {
@@ -70,7 +70,7 @@ void __init s3c6400_init_irq(void)
 	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
 }
 
-struct sysdev_class s3c6400_sysclass = {
+static struct sysdev_class s3c6400_sysclass = {
 	.name	= "s3c6400-core",
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/s3c6410.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/s3c6410.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/s3c6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/s3c6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,8 @@
 #include <plat/adc-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 void __init s3c6410_map_io(void)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/setup-fb-24bpp.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/setup-fb-24bpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/setup-fb-24bpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-extern void s3c64xx_fb_gpio_setup_24bpp(void)
+void s3c64xx_fb_gpio_setup_24bpp(void)
 {
 	s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));
 	s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,17 +12,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,41 +22,3 @@ char *s3c64xx_hsmmc_clksrcs[4] = {
 	[2] = "mmc_bus",
 	/* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	pr_debug("%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
-
-void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	s3c6400_setup_sdhci_cfg_card(dev, r, ios, card);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,8 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
+		.devname	= "dma-pl330",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
@@ -499,6 +500,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -581,5 +587,7 @@ void __init s5p6440_register_clocks(void
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,7 +179,8 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
+		.devname	= "dma-pl330",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
@@ -553,6 +554,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -632,5 +638,7 @@ void __init s5p6450_register_clocks(void
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -38,6 +39,7 @@
 #include <plat/s5p6440.h>
 #include <plat/s5p6450.h>
 #include <plat/adc-core.h>
+#include <plat/fb-core.h>
 
 /* Initial IO mappings */
 
@@ -108,18 +110,22 @@ void __init s5p6440_map_io(void)
 {
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
+	s3c_fb_setname("s5p64x0-fb");
 
 	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
 	iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+	init_consistent_dma_size(SZ_8M);
 }
 
 void __init s5p6450_map_io(void)
 {
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
+	s3c_fb_setname("s5p64x0-fb");
 
 	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
 	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
+	init_consistent_dma_size(SZ_8M);
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/dev-spi.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/dev-spi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/dev-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/dev-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <mach/regs-clock.h>
 #include <mach/spi-clocks.h>
 
+#include <plat/cpu.h>
 #include <plat/s3c64xx-spi.h>
 #include <plat/gpio-cfg.h>
 
@@ -185,11 +186,8 @@ struct platform_device s5p64x0_device_sp
 
 void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 {
-	unsigned int id;
 	struct s3c64xx_spi_info *pd;
 
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
 	/* Reject invalid configuration */
 	if (!num_cs || src_clk_nr < 0
 			|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
@@ -199,7 +197,7 @@ void __init s5p64x0_spi_set_info(int cnt
 
 	switch (cntrlr) {
 	case 0:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi0_pdata;
 		else
 			pd = &s5p6440_spi0_pdata;
@@ -207,7 +205,7 @@ void __init s5p64x0_spi_set_info(int cnt
 		s5p64x0_device_spi0.dev.platform_data = pd;
 		break;
 	case 1:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi1_pdata;
 		else
 			pd = &s5p6440_spi1_pdata;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,128 +21,218 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
+#include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-	[0] = {
-		.start	= S5P64X0_PA_PDMA,
-		.end	= S5P64X0_PA_PDMA + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DMA0,
-		.end	= IRQ_DMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[22] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
 	},
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_MAX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_MAX,
-		[17] = DMACH_MAX,
-		[18] = DMACH_MAX,
-		[19] = DMACH_MAX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_MAX,
-		[23] = DMACH_MAX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_MAX,
-		[26] = DMACH_MAX,
-		[27] = DMACH_MAX,
-		[28] = DMACH_MAX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
+	.peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_UART4_RX,
-		[9] = DMACH_UART4_TX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_PCM1_TX,
-		[17] = DMACH_PCM1_RX,
-		[18] = DMACH_PCM2_TX,
-		[19] = DMACH_PCM2_RX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_USI_TX,
-		[23] = DMACH_USI_RX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_I2S1_TX,
-		[26] = DMACH_I2S1_RX,
-		[27] = DMACH_I2S2_TX,
-		[28] = DMACH_I2S2_RX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_UART5_RX,
-		[31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_USI_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_USI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-	.name		= "s3c-pl330",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_pdma_resource),
-	.resource	= s5p64x0_pdma_resource,
-	.dev		= {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
+	.peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+	.dev = {
+		.init_name = "dma-pl330",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
+	.res = {
+		.start = S5P64X0_PA_PDMA,
+		.end = S5P64X0_PA_PDMA + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_DMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
 {
-	unsigned int id;
-
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
-	if (id == 0x50000)
+	if (soc_is_s5p6450())
 		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
 	else
 		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-	platform_device_register(&s5p64x0_device_pdma);
+	amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/gpiolib.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/gpiolib.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/gpiolib.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 
+#include <plat/cpu.h>
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
@@ -473,14 +474,10 @@ static void __init s5p64x0_gpio_add_rban
 
 static int __init s5p64x0_gpiolib_init(void)
 {
-	unsigned int chipid;
-
-	chipid = __raw_readl(S5P64X0_SYS_ID);
-
 	s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
 				ARRAY_SIZE(s5p64x0_gpio_cfgs));
 
-	if ((chipid & 0xff000) == 0x50000) {
+	if (soc_is_s5p6450()) {
 		samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
 					ARRAY_SIZE(s5p6450_gpio_2bit));
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 #include <plat/regs-serial.h>
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		mov	\rp, #0xE0000000
 		orr	\rp, \rp, #0x00100000
 		ldr	\rp, [\rp, #0x118 ]
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H __FILE__
 
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
 /* GPIO bank sizes */
 
 #define S5P6440_GPIO_A_NR	(6)
@@ -134,6 +129,4 @@ enum s5p6450_gpio_number {
 
 #define ARCH_NR_GPIOS		(S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,10 @@
 
 #define IRQ_I2S0		IRQ_I2SV40
 
+#define IRQ_LCD_FIFO		IRQ_DISPCON0
+#define IRQ_LCD_VSYNC		IRQ_DISPCON1
+#define IRQ_LCD_SYSTEM		IRQ_DISPCON2
+
 /* S5P6450 EINT feature will be added */
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,8 @@
 
 #define S5P64X0_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
 
+#define S5P64X0_PA_FB		0xEE000000
+
 #define S5P64X0_PA_I2S		0xF2000000
 #define S5P6450_PA_I2S1		0xF2800000
 #define S5P6450_PA_I2S2		0xF2900000
@@ -64,6 +66,7 @@
 #define S3C_PA_IIC1		S5P6440_PA_IIC1
 #define S3C_PA_RTC		S5P64X0_PA_RTC
 #define S3C_PA_WDT		S5P64X0_PA_WDT
+#define S3C_PA_FB		S5P64X0_PA_FB
 
 #define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
 #define S5P_PA_SROMC		S5P64X0_PA_SROMC
@@ -85,5 +88,6 @@
 #define S5P_PA_UART5		S5P6450_PA_UART(5)
 
 #define S5P_SZ_UART		SZ_256
+#define S3C_VA_UARTx(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
 #endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H __FILE__
-
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-#define CONSISTENT_DMA_SIZE	SZ_8M
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
+ *
+ * Based on PM core support for S3C64XX by Ben Dooks
+ *
+ * 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 <mach/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
+
+	/*
+	 * As a note, since the S5P64X0 UARTs generally have multiple
+	 * clock sources, we simply enable PCLK at the moment and hope
+	 * that the resume settings for the UART are suitable for the
+	 * use with PCLK.
+	 */
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
+
+	__raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	/* VIC should have already been taken care of */
+
+	/* clear any pending EINT0 interrupts */
+	__raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void) { }
+static inline void s3c_pm_arch_show_resume_irqs(void) { }
+
+/*
+ * make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on
+ */
+#define s3c_irqwake_eintallow	((1 << 16) - 1)
+#define s3c_irqwake_intallow	(~0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					struct pm_uart_save *save)
+{
+	u32 ucon = __raw_readl(regs + S3C2410_UCON);
+	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+	u32 new_ucon;
+	u32 delta;
+
+	/*
+	 * S5P64X0 UART blocks only support level interrupts, so ensure that
+	 * when we restore unused UART blocks we force the level interrupt
+	 * settings.
+	 */
+	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+	/*
+	 * We have a constraint on changing the clock type of the UART
+	 * between UCLKx and PCLK, so ensure that when we restore UCON
+	 * that the CLK field is correctly modified if the bootloader
+	 * has changed anything.
+	 */
+	if (ucon_clk != save_clk) {
+		new_ucon = save->ucon;
+		delta = ucon_clk ^ save_clk;
+
+		/*
+		 * change from UCLKx => wrong PCLK,
+		 * either UCLK can be tested for by a bit-test
+		 * with UCLK0
+		 */
+		if (ucon_clk & S3C6400_UCON_UCLK0 &&
+		!(save_clk & S3C6400_UCON_UCLK0) &&
+		delta & S3C6400_UCON_PCLK2) {
+			new_ucon &= ~S3C6400_UCON_UCLK0;
+		} else if (delta == S3C6400_UCON_PCLK2) {
+			/*
+			 * as a precaution, don't change from
+			 * PCLK2 => PCLK or vice-versa
+			 */
+			new_ucon ^= S3C6400_UCON_PCLK2;
+		}
+
+		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+			ucon, new_ucon, save->ucon);
+		save->ucon = new_ucon;
+	}
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* ensure sleep mode has been cleared from the system */
+	__raw_writel(0, S5P64X0_SLPEN);
+}
+
+static inline void samsung_pm_saved_gpios(void)
+{
+	/*
+	 * turn on the sleep mode and keep it there, as it seems that during
+	 * suspend the xCON registers get re-set and thus you can end up with
+	 * problems between going to sleep and resuming.
+	 */
+	__raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S5P64X0 - pwm clock and timer support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return 0;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK 0
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,17 +41,50 @@
 #define S5P6450_DPLL_CON		S5P_CLKREG(0x50)
 #define S5P6450_DPLL_CON_K		S5P_CLKREG(0x54)
 
+#define S5P64X0_AHB_CON0		S5P_CLKREG(0x100)
 #define S5P64X0_CLK_SRC1		S5P_CLKREG(0x10C)
 
 #define S5P64X0_SYS_ID			S5P_CLKREG(0x118)
 #define S5P64X0_SYS_OTHERS		S5P_CLKREG(0x11C)
 
 #define S5P64X0_PWR_CFG			S5P_CLKREG(0x804)
+#define S5P64X0_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
+#define S5P64X0_SLEEP_CFG		S5P_CLKREG(0x818)
+#define S5P64X0_PWR_STABLE		S5P_CLKREG(0x828)
+
 #define S5P64X0_OTHERS			S5P_CLKREG(0x900)
+#define S5P64X0_WAKEUP_STAT		S5P_CLKREG(0x908)
+
+#define S5P64X0_INFORM0			S5P_CLKREG(0xA00)
 
 #define S5P64X0_CLKDIV0_HCLK_SHIFT	(8)
 #define S5P64X0_CLKDIV0_HCLK_MASK	(0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
 
+/* HCLK GATE Registers */
+#define S5P64X0_CLK_GATE_HCLK1_FIMGVG	(1 << 2)
+#define S5P64X0_CLK_GATE_SCLK1_FIMGVG	(1 << 2)
+
+/* PCLK GATE Registers */
+#define S5P64X0_CLK_GATE_PCLK_UART3	(1 << 4)
+#define S5P64X0_CLK_GATE_PCLK_UART2	(1 << 3)
+#define S5P64X0_CLK_GATE_PCLK_UART1	(1 << 2)
+#define S5P64X0_CLK_GATE_PCLK_UART0	(1 << 1)
+
+#define S5P64X0_PWR_CFG_MMC1_DISABLE		(1 << 15)
+#define S5P64X0_PWR_CFG_MMC0_DISABLE		(1 << 14)
+#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE	(1 << 11)
+#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE	(1 << 10)
+#define S5P64X0_PWR_CFG_WFI_MASK		(3 << 5)
+#define S5P64X0_PWR_CFG_WFI_SLEEP		(3 << 5)
+
+#define S5P64X0_SLEEP_CFG_OSC_EN	(1 << 0)
+
+#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4	(4 << 0)
+
+#define S5P6450_OTHERS_DISABLE_INT	(1 << 31)
+#define S5P64X0_OTHERS_RET_UART		(1 << 26)
+#define S5P64X0_OTHERS_RET_MMC1		(1 << 25)
+#define S5P64X0_OTHERS_RET_MMC0		(1 << 24)
 #define S5P64X0_OTHERS_USB_SIG_MASK	(1 << 16)
 
 /* Compatibility defines */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,14 +34,35 @@
 #define S5P6450_GPQ_BASE		(S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE		(S5P_VA_GPIO + 0x0300)
 
+#define S5P64X0_SPCON0			(S5P_VA_GPIO + 0x1A0)
+#define S5P64X0_SPCON0_LCD_SEL_MASK	(0x3 << 0)
+#define S5P64X0_SPCON0_LCD_SEL_RGB	(0x1 << 0)
+#define S5P64X0_SPCON1			(S5P_VA_GPIO + 0x2B0)
+
+#define S5P64X0_MEM0CONSLP0		(S5P_VA_GPIO + 0x1C0)
+#define S5P64X0_MEM0CONSLP1		(S5P_VA_GPIO + 0x1C4)
+#define S5P64X0_MEM0DRVCON		(S5P_VA_GPIO + 0x1D0)
+#define S5P64X0_MEM1DRVCON		(S5P_VA_GPIO + 0x1D4)
+
+#define S5P64X0_EINT12CON		(S5P_VA_GPIO + 0x200)
+#define S5P64X0_EINT12FLTCON		(S5P_VA_GPIO + 0x220)
+#define S5P64X0_EINT12MASK		(S5P_VA_GPIO + 0x240)
+
 /* External interrupt control registers for group0 */
 
 #define EINT0CON0_OFFSET		(0x900)
+#define EINT0FLTCON0_OFFSET		(0x910)
+#define EINT0FLTCON1_OFFSET		(0x914)
 #define EINT0MASK_OFFSET		(0x920)
 #define EINT0PEND_OFFSET		(0x924)
 
 #define S5P64X0_EINT0CON0		(S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0FLTCON0		(S5P_VA_GPIO + EINT0FLTCON0_OFFSET)
+#define S5P64X0_EINT0FLTCON1		(S5P_VA_GPIO + EINT0FLTCON1_OFFSET)
 #define S5P64X0_EINT0MASK		(S5P_VA_GPIO + EINT0MASK_OFFSET)
 #define S5P64X0_EINT0PEND		(S5P_VA_GPIO + EINT0PEND_OFFSET)
 
+#define S5P64X0_SLPEN			(S5P_VA_GPIO + 0x930)
+#define S5P64X0_SLPEN_USE_xSLP		(1 << 0)
+
 #endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/irq-eint.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/irq-eint.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/irq-eint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/irq-eint.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,10 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <plat/cpu.h>
 #include <plat/regs-irqtype.h>
 #include <plat/gpio-cfg.h>
+#include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
@@ -67,7 +69,7 @@ static int s5p64x0_irq_eint_set_type(str
 	__raw_writel(ctrl, S5P64X0_EINT0CON0);
 
 	/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
-	if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+	if (soc_is_s5p6450())
 		s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
 	else
 		s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
@@ -133,6 +135,7 @@ static int s5p64x0_alloc_gc(void)
 	ct->chip.irq_mask = irq_gc_mask_set_bit;
 	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 	ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+	ct->chip.irq_set_wake = s3c_irqext_wake;
 	ct->regs.ack = EINT0PEND_OFFSET;
 	ct->regs.mask = EINT0MASK_OFFSET;
 	irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/irq-pm.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/irq-pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/irq-pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/irq-pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-s5p64x0/irq-pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - Interrupt handling Power Management
+ *
+ * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks
+ *
+ * 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/syscore_ops.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <plat/regs-serial.h>
+#include <plat/pm.h>
+
+#include <mach/regs-gpio.h>
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S5P64X0_EINT0CON0),
+	SAVE_ITEM(S5P64X0_EINT0FLTCON0),
+	SAVE_ITEM(S5P64X0_EINT0FLTCON1),
+	SAVE_ITEM(S5P64X0_EINT0MASK),
+};
+
+static struct irq_grp_save {
+	u32	con;
+	u32	fltcon;
+	u32	mask;
+} eint_grp_save[4];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s5p64x0_irq_pm_suspend(void)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
+		grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
+		grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
+	}
+
+	return 0;
+}
+
+static void s5p64x0_irq_pm_resume(void)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		__raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
+		__raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
+		__raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
+	}
+
+	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+}
+
+static struct syscore_ops s5p64x0_irq_syscore_ops = {
+	.suspend = s5p64x0_irq_pm_suspend,
+	.resume  = s5p64x0_irq_pm_resume,
+};
+
+static int __init s5p64x0_syscore_init(void)
+{
+	register_syscore_ops(&s5p64x0_irq_syscore_ops);
+
+	return 0;
+}
+core_initcall(s5p64x0_syscore_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,18 +9,28 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_HRT
+	select S5P_SLEEP if PM
+	select SAMSUNG_WAKEMASK if PM
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_HRT
+	select S5P_SLEEP if PM
+	select SAMSUNG_WAKEMASK if PM
 	help
 	  Enable S5P6450 CPU support
 
+config S5P64X0_SETUP_FB_24BPP
+	bool
+	help
+	  Common setup code for S5P64X0 based boards with a LCD display
+	  through RGB interface.
+
 config S5P64X0_SETUP_I2C1
 	bool
 	help
@@ -31,6 +41,7 @@ config S5P64X0_SETUP_I2C1
 config MACH_SMDK6440
 	bool "SMDK6440"
 	select CPU_S5P6440
+	select S3C_DEV_FB
 	select S3C_DEV_I2C1
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
@@ -39,6 +50,7 @@ config MACH_SMDK6440
 	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_FB_24BPP
 	select S5P64X0_SETUP_I2C1
 	help
 	  Machine support for the Samsung SMDK6440
@@ -46,6 +58,7 @@ config MACH_SMDK6440
 config MACH_SMDK6450
 	bool "SMDK6450"
 	select CPU_S5P6450
+	select S3C_DEV_FB
 	select S3C_DEV_I2C1
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
@@ -54,6 +67,7 @@ config MACH_SMDK6450
 	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_FB_24BPP
 	select S5P64X0_SETUP_I2C1
 	help
 	  Machine support for the Samsung SMDK6450
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -92,6 +97,59 @@ static struct s3c2410_uartcfg smdk6440_u
 	},
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6440_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 24,
+};
+
+static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
+	.win[0]		= &smdk6440_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
+					 unsigned int power)
+{
+	int err;
+
+	if (power) {
+		err = gpio_request(S5P6440_GPN(5), "GPN");
+		if (err) {
+			printk(KERN_ERR "failed to request GPN for lcd reset\n");
+			return;
+		}
+
+		gpio_direction_output(S5P6440_GPN(5), 1);
+		gpio_set_value(S5P6440_GPN(5), 0);
+		gpio_set_value(S5P6440_GPN(5), 1);
+		gpio_free(S5P6440_GPN(5));
+	}
+}
+
+static struct plat_lcd_data smdk6440_lcd_power_data = {
+	.set_power	= smdk6440_lte480_reset_power,
+};
+
+static struct platform_device smdk6440_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdk6440_lcd_power_data,
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -101,6 +159,8 @@ static struct platform_device *smdk6440_
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6440_device_iis,
+	&s3c_device_fb,
+	&smdk6440_lcd_lte480wv,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -129,12 +189,6 @@ static struct i2c_board_info smdk6440_i2
 	/* To be populated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
 	.no = S5P6440_GPF(15),
@@ -153,9 +207,20 @@ static void __init smdk6440_map_io(void)
 	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6440_set_lcd_interface(void)
+{
+	unsigned int cfg;
+
+	/* select TFT LCD type (RGB I/F) */
+	cfg = __raw_readl(S5P64X0_SPCON0);
+	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+	__raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6440_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
@@ -166,12 +231,15 @@ static void __init smdk6440_machine_init
 
 	samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
 
+	s5p6440_set_lcd_interface();
+	s3c_fb_set_platdata(&smdk6440_lcd_pdata);
+
 	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
 }
 
 MACHINE_START(SMDK6440, "SMDK6440")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6440_init_irq,
 	.map_io		= smdk6440_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -110,6 +115,59 @@ static struct s3c2410_uartcfg smdk6450_u
 #endif
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6450_fb_win0 = {
+	.win_mode	= {
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 24,
+};
+
+static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
+	.win[0]		= &smdk6450_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
+					 unsigned int power)
+{
+	int err;
+
+	if (power) {
+		err = gpio_request(S5P6450_GPN(5), "GPN");
+		if (err) {
+			printk(KERN_ERR "failed to request GPN for lcd reset\n");
+			return;
+		}
+
+		gpio_direction_output(S5P6450_GPN(5), 1);
+		gpio_set_value(S5P6450_GPN(5), 0);
+		gpio_set_value(S5P6450_GPN(5), 1);
+		gpio_free(S5P6450_GPN(5));
+	}
+}
+
+static struct plat_lcd_data smdk6450_lcd_power_data = {
+	.set_power	= smdk6450_lte480_reset_power,
+};
+
+static struct platform_device smdk6450_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdk6450_lcd_power_data,
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -119,6 +177,9 @@ static struct platform_device *smdk6450_
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
+	&s3c_device_fb,
+	&smdk6450_lcd_lte480wv,
+
 	/* s5p6450_device_spi0 will be added */
 };
 
@@ -148,12 +209,6 @@ static struct i2c_board_info smdk6450_i2
 	{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
 	.no = S5P6450_GPF(15),
@@ -172,9 +227,20 @@ static void __init smdk6450_map_io(void)
 	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6450_set_lcd_interface(void)
+{
+	unsigned int cfg;
+
+	/* select TFT LCD type (RGB I/F) */
+	cfg = __raw_readl(S5P64X0_SPCON0);
+	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+	__raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6450_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
@@ -185,12 +251,15 @@ static void __init smdk6450_machine_init
 
 	samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
 
+	s5p6450_set_lcd_interface();
+	s3c_fb_set_platdata(&smdk6450_lcd_pdata);
+
 	platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
 }
 
 MACHINE_START(SMDK6450, "SMDK6450")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6450_init_irq,
 	.map_io		= smdk6450_map_io,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Makefile linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,11 @@ obj-				:=
 
 # Core support for S5P64X0 system
 
-obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o gpiolib.o
+obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o irq-eint.o
 obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
+obj-$(CONFIG_PM)		+= pm.o irq-pm.o
 
 # machine support
 
@@ -28,3 +29,4 @@ obj-y				+= dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
 
 obj-$(CONFIG_S5P64X0_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/pm.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/pm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,204 @@
+/* linux/arch/arm/mach-s5p64x0/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 Power Management Support
+ *
+ * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
+ *
+ * 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/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/regs-timer.h>
+#include <plat/wakeup-mask.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+static struct sleep_save s5p64x0_core_save[] = {
+	SAVE_ITEM(S5P64X0_APLL_CON),
+	SAVE_ITEM(S5P64X0_MPLL_CON),
+	SAVE_ITEM(S5P64X0_EPLL_CON),
+	SAVE_ITEM(S5P64X0_EPLL_CON_K),
+	SAVE_ITEM(S5P64X0_CLK_SRC0),
+	SAVE_ITEM(S5P64X0_CLK_SRC1),
+	SAVE_ITEM(S5P64X0_CLK_DIV0),
+	SAVE_ITEM(S5P64X0_CLK_DIV1),
+	SAVE_ITEM(S5P64X0_CLK_DIV2),
+	SAVE_ITEM(S5P64X0_CLK_DIV3),
+	SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
+	SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
+	SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
+};
+
+static struct sleep_save s5p64x0_misc_save[] = {
+	SAVE_ITEM(S5P64X0_AHB_CON0),
+	SAVE_ITEM(S5P64X0_SPCON0),
+	SAVE_ITEM(S5P64X0_SPCON1),
+	SAVE_ITEM(S5P64X0_MEM0CONSLP0),
+	SAVE_ITEM(S5P64X0_MEM0CONSLP1),
+	SAVE_ITEM(S5P64X0_MEM0DRVCON),
+	SAVE_ITEM(S5P64X0_MEM1DRVCON),
+
+	SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+/* DPLL is present only in S5P6450 */
+static struct sleep_save s5p6450_core_save[] = {
+	SAVE_ITEM(S5P6450_DPLL_CON),
+	SAVE_ITEM(S5P6450_DPLL_CON_K),
+};
+
+void s3c_pm_configure_extint(void)
+{
+	__raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+	__raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
+
+	s3c_pm_do_restore_core(s5p64x0_core_save,
+				ARRAY_SIZE(s5p64x0_core_save));
+
+	if (soc_is_s5p6450())
+		s3c_pm_do_restore_core(s5p6450_core_save,
+				ARRAY_SIZE(s5p6450_core_save));
+
+	s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+	s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+
+	if (soc_is_s5p6450())
+		s3c_pm_do_save(s5p6450_core_save,
+				ARRAY_SIZE(s5p6450_core_save));
+
+	s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
+}
+
+static int s5p64x0_cpu_suspend(unsigned long arg)
+{
+	unsigned long tmp = 0;
+
+	/*
+	 * Issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case.
+	 */
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 5\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
+	{ .irq = IRQ_RTC_ALARM,	.bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
+	{ .irq = IRQ_RTC_TIC,	.bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
+	{ .irq = IRQ_HSMMC0,	.bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
+	{ .irq = IRQ_HSMMC1,	.bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
+};
+
+static void s5p64x0_pm_prepare(void)
+{
+	u32 tmp;
+
+	samsung_sync_wakemask(S5P64X0_PWR_CFG,
+			s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
+
+	/* store the resume address in INFORM0 register */
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
+
+	/* setup clock gating for FIMGVG block */
+	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
+		(S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
+	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
+		(S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
+
+	/* Configure the stabilization counter with wait time required */
+	__raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
+
+	/* set WFI to SLEEP mode configuration */
+	tmp = __raw_readl(S5P64X0_SLEEP_CFG);
+	tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
+	__raw_writel(tmp, S5P64X0_SLEEP_CFG);
+
+	tmp = __raw_readl(S5P64X0_PWR_CFG);
+	tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
+	tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
+	__raw_writel(tmp, S5P64X0_PWR_CFG);
+
+	/*
+	 * set OTHERS register to disable interrupt before going to
+	 * sleep. This bit is present only in S5P6450, it is reserved
+	 * in S5P6440.
+	 */
+	if (soc_is_s5p6450()) {
+		tmp = __raw_readl(S5P64X0_OTHERS);
+		tmp |= S5P6450_OTHERS_DISABLE_INT;
+		__raw_writel(tmp, S5P64X0_OTHERS);
+	}
+
+	/* ensure previous wakeup state is cleared before sleeping */
+	__raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
+
+}
+
+static int s5p64x0_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = s5p64x0_pm_prepare;
+	pm_cpu_sleep = s5p64x0_cpu_suspend;
+	pm_uart_udivslot = 1;
+
+	return 0;
+}
+
+static struct sysdev_driver s5p64x0_pm_driver = {
+	.add		= s5p64x0_pm_add,
+};
+
+static __init int s5p64x0_pm_drvinit(void)
+{
+	s3c_pm_init();
+
+	return sysdev_driver_register(&s5p64x0_sysclass, &s5p64x0_pm_driver);
+}
+arch_initcall(s5p64x0_pm_drvinit);
+
+static void s5p64x0_pm_resume(void)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(S5P64X0_OTHERS);
+	tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
+			S5P64X0_OTHERS_RET_UART);
+	__raw_writel(tmp , S5P64X0_OTHERS);
+}
+
+static struct syscore_ops s5p64x0_pm_syscore_ops = {
+	.resume		= s5p64x0_pm_resume,
+};
+
+static __init int s5p64x0_pm_syscore_init(void)
+{
+	register_syscore_ops(&s5p64x0_pm_syscore_ops);
+
+	return 0;
+}
+arch_initcall(s5p64x0_pm_syscore_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/setup-fb-24bpp.c linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Base S5P64X0 GPIO setup information for LCD framebuffer
+ *
+ * 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+void s5p64x0_fb_gpio_setup_24bpp(void)
+{
+	if (soc_is_s5p6440()) {
+		s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
+		s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
+	} else if (soc_is_s5p6450()) {
+		s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
+		s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/clock.c linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,11 @@ static struct clk s5p_clk_otgphy = {
 	.name		= "otg_phy",
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
 	[0] = &s5p_clk_27m,
 	[1] = &clk_fin_hpll,
@@ -454,14 +459,14 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 0),
@@ -1276,5 +1281,7 @@ void __init s5pc100_register_clocks(void
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,150 +21,246 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA0,
-		.end    = S5PC100_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[30] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_EXTERNAL,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_HSI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_HSI_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_EXTERNAL,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_HSI_RX,
-		[29] = DMACH_HSI_TX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma0_resource),
-	.resource	= s5pc100_pdma0_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma0_pdata,
 	},
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
+struct dma_pl330_peri pdma1_peri[30] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
 	},
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device s5pc100_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma1_pdata,
 	},
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-	&s5pc100_device_pdma0,
-	&s5pc100_device_pdma1,
+	.res = {
+		.start = S5PC100_PA_PDMA1,
+		.end = S5PC100_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-	platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+	amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
+	amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,6 @@
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H __FILE__
 
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
 /* GPIO bank sizes */
 #define S5PC100_GPIO_A0_NR	(8)
 #define S5PC100_GPIO_A1_NR	(5)
@@ -146,6 +141,4 @@ enum s5p_gpio_number {
 /* define the number of gpios we need to the one after the MP04() range */
 #define ARCH_NR_GPIOS		(S5PC100_GPIO_END + 1)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/memory.h
- *
- * Copyright 2008 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * Based on mach-s3c6400/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET     	UL(0x20000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - pwm clock and timer support
- *
- * Based on mach-s3c6400/include/mach/pwm-clock.h
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@ if ARCH_S5PC100
 config CPU_S5PC100
 	bool
 	select S5P_EXT_INT
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	help
 	  Enable S5PC100 CPU support
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,12 +203,6 @@ static struct platform_device *smdkc100_
 	&s5pc100_device_spdif,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
 	.no = S5PC100_GPD(0),
@@ -228,7 +222,7 @@ static void __init smdkc100_map_io(void)
 
 static void __init smdkc100_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* I2C */
 	s3c_i2c0_set_platdata(NULL);
@@ -254,7 +248,7 @@ static void __init smdkc100_machine_init
 
 MACHINE_START(SMDKC100, "SMDKC100")
 	/* Maintainer: Byungho Min <bhmin@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pc100_init_irq,
 	.map_io		= smdkc100_map_io,
 	.init_machine	= smdkc100_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pc100/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pc100/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,17 +11,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -31,35 +21,3 @@ char *s5pc100_hsmmc_clksrcs[4] = {
 	[2] = "sclk_mmc",	/* mmc_bus */
 	/* [3] = "48m",		- note not successfully used yet */
 };
-
-
-void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-				    void __iomem *r,
-				    struct mmc_ios *ios,
-				    struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything according to card-type */
-
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/clock.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -174,6 +174,16 @@ static int s5pv210_clk_mask1_ctrl(struct
 	return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 static struct clk clk_sclk_hdmi27m = {
 	.name		= "sclk_hdmi27m",
 	.rate		= 27000000,
@@ -203,6 +213,11 @@ static struct clk clk_pcmcdclk2 = {
 	.name		= "pcmcdclk",
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
 	[0] = &clk_fin_vpll,
 	[1] = &clk_sclk_hdmi27m,
@@ -289,14 +304,14 @@ static struct clk_ops clk_fout_apll_ops
 
 static struct clk init_clocks_off[] = {
 	{
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 4),
@@ -330,6 +345,40 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
+		.name		= "dac",
+		.devname	= "s5p-sdo",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "mixer",
+		.devname	= "s5p-mixer",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "vp",
+		.devname	= "s5p-mixer",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "hdmi",
+		.devname	= "s5pv210-hdmi",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "hdmiphy",
+		.devname	= "s5pv210-hdmi",
+		.enable		= exynos4_clk_hdmiphy_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dacphy",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_dac_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
 		.name		= "otg",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
@@ -407,6 +456,12 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<9),
 	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-hdmiphy-i2c",
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
 		.name		= "spi",
 		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_pclk_psys.clk,
@@ -594,6 +649,23 @@ static struct clksrc_sources clkset_sclk
 	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
 };
 
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.enable		= s5pv210_clk_mask0_ctrl,
+		.ctrlbit	= (1 << 1),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+};
+
 static struct clk *clkset_sclk_audio0_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = &clk_pcmcdclk0,
@@ -777,14 +849,6 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
 	}, {
 		.clk	= {
-			.name		= "sclk_mixer",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 1),
-		},
-		.sources = &clkset_sclk_mixer,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
-	}, {
-		.clk	= {
 			.name		= "sclk_fimc",
 			.devname	= "s5pv210-fimc.0",
 			.enable		= s5pv210_clk_mask1_ctrl,
@@ -973,9 +1037,6 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_pclk_psys,
 	&clk_vpllsrc,
 	&clk_sclk_vpll,
-	&clk_sclk_dac,
-	&clk_sclk_pixel,
-	&clk_sclk_hdmi,
 	&clk_mout_dmc0,
 	&clk_sclk_dmc0,
 	&clk_sclk_audio0,
@@ -1060,6 +1121,61 @@ static struct clk_ops s5pv210_epll_ops =
 	.get_rate = s5p_epll_get_rate,
 };
 
+static u32 vpll_div[][5] = {
+	{  54000000, 3, 53, 3, 0 },
+	{ 108000000, 3, 53, 2, 0 },
+};
+
+static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int vpll_con;
+	unsigned int i;
+
+	/* Return if nothing changed */
+	if (clk->rate == rate)
+		return 0;
+
+	vpll_con = __raw_readl(S5P_VPLL_CON);
+	vpll_con &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+		if (vpll_div[i][0] == rate) {
+			vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
+			vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
+			vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
+			vpll_con |= vpll_div[i][4] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(vpll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con, S5P_VPLL_CON);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
+		continue;
+
+	clk->rate = rate;
+	return 0;
+}
+static struct clk_ops s5pv210_vpll_ops = {
+	.get_rate = s5pv210_vpll_get_rate,
+	.set_rate = s5pv210_vpll_set_rate,
+};
+
 void __init_or_cpufreq s5pv210_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -1108,6 +1224,7 @@ void __init_or_cpufreq s5pv210_setup_clo
 	clk_fout_apll.ops = &clk_fout_apll_ops;
 	clk_fout_mpll.rate = mpll;
 	clk_fout_epll.rate = epll;
+	clk_fout_vpll.ops = &s5pv210_vpll_ops;
 	clk_fout_vpll.rate = vpll;
 
 	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1153,11 +1270,15 @@ void __init s5pv210_register_clocks(void
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+		s3c_register_clksrc(sclk_tv[ptr], 1);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
 	s3c_pwmclk_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -41,6 +42,7 @@
 #include <plat/keypad-core.h>
 #include <plat/sdhci.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 /* Initial IO mappings */
 
@@ -119,6 +121,7 @@ static void s5pv210_sw_reset(void)
 void __init s5pv210_map_io(void)
 {
 	iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
+	init_consistent_dma_size(14 << 20);
 
 	/* initialise device information early */
 	s5pv210_default_sdhci0();
@@ -143,6 +146,9 @@ void __init s5pv210_map_io(void)
 
 	/* Use s5pv210-keypad instead of samsung-keypad */
 	samsung_keypad_setname("s5pv210-keypad");
+
+	/* setup TV devices */
+	s5p_hdmi_setname("s5pv210-hdmi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/dma.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,151 +21,240 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA0,
-		.end    = S5PV210_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[28] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_MAX,
-		[15] = DMACH_MAX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_MAX,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma0_resource),
-	.resource	= s5pv210_pdma0_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma0_pdata,
 	},
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_PCM2_RX,
-		[31] = DMACH_PCM2_TX,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma1_resource),
-	.resource	= s5pv210_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device s5pv210_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma1_pdata,
 	},
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-	&s5pv210_device_pdma0,
-	&s5pv210_device_pdma1,
+	.res = {
+		.start = S5PV210_PA_PDMA1,
+		.end = S5PV210_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-	platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+	amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
+	amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/dma.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/dma.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H __FILE__
 
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
 /* Practically, GPIO banks up to MP03 are the configurable gpio banks */
 
 /* GPIO bank sizes */
@@ -142,6 +137,4 @@ enum s5p_gpio_number {
 #define ARCH_NR_GPIOS		(S5PV210_MP05(S5PV210_GPIO_MP05_NR) +	\
 				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 #define IRQ_SPI2		S5P_IRQ_VIC1(17)
 #define IRQ_IRDA		S5P_IRQ_VIC1(18)
 #define IRQ_IIC2		S5P_IRQ_VIC1(19)
-#define IRQ_IIC3		S5P_IRQ_VIC1(20)
+#define IRQ_IIC_HDMIPHY		S5P_IRQ_VIC1(20)
 #define IRQ_HSIRX		S5P_IRQ_VIC1(21)
 #define IRQ_HSITX		S5P_IRQ_VIC1(22)
 #define IRQ_UHOST		S5P_IRQ_VIC1(23)
@@ -86,7 +86,7 @@
 #define IRQ_HDMI		S5P_IRQ_VIC2(12)
 #define IRQ_IIC1		S5P_IRQ_VIC2(13)
 #define IRQ_MFC			S5P_IRQ_VIC2(14)
-#define IRQ_TVENC		S5P_IRQ_VIC2(15)
+#define IRQ_SDO			S5P_IRQ_VIC2(15)
 #define IRQ_I2S0		S5P_IRQ_VIC2(16)
 #define IRQ_I2S1		S5P_IRQ_VIC2(17)
 #define IRQ_I2S2		S5P_IRQ_VIC2(18)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/map.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/map.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -90,6 +90,12 @@
 #define S5PV210_PA_FIMC1		0xFB300000
 #define S5PV210_PA_FIMC2		0xFB400000
 
+#define S5PV210_PA_SDO			0xF9000000
+#define S5PV210_PA_VP			0xF9100000
+#define S5PV210_PA_MIXER		0xF9200000
+#define S5PV210_PA_HDMI			0xFA100000
+#define S5PV210_PA_IIC_HDMIPHY		0xFA900000
+
 /* Compatibiltiy Defines */
 
 #define S3C_PA_FB			S5PV210_PA_FB
@@ -110,6 +116,13 @@
 #define S5P_PA_FIMC2			S5PV210_PA_FIMC2
 #define S5P_PA_MIPI_CSIS0		S5PV210_PA_MIPI_CSIS
 #define S5P_PA_MFC			S5PV210_PA_MFC
+#define S5P_PA_IIC_HDMIPHY		S5PV210_PA_IIC_HDMIPHY
+
+#define S5P_PA_SDO			S5PV210_PA_SDO
+#define S5P_PA_VP			S5PV210_PA_VP
+#define S5P_PA_MIXER			S5PV210_PA_MIXER
+#define S5P_PA_HDMI			S5PV210_PA_HDMI
+
 #define S5P_PA_ONENAND			S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA		S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM			S5PV210_PA_SDRAM
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 #define PLAT_PHYS_OFFSET		UL(0x20000000)
-#define CONSISTENT_DMA_SIZE	(SZ_8M + SZ_4M + SZ_2M)
 
 /*
  * Sparsemem support
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/pm-core.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/pm-core.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,4 +43,4 @@ static inline void s3c_pm_arch_update_ua
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5PV210 - pwm clock and timer support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -144,8 +144,9 @@
 
 #define S5P_OTHERS		S5P_CLKREG(0xE000)
 #define S5P_OM_STAT		S5P_CLKREG(0xE100)
+#define S5P_HDMI_PHY_CONTROL	S5P_CLKREG(0xE804)
 #define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
-#define S5P_DAC_CONTROL		S5P_CLKREG(0xE810)
+#define S5P_DAC_PHY_CONTROL	S5P_CLKREG(0xE810)
 #define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
 #define S5P_MIPI_DPHY_ENABLE	(1 << 0)
 #define S5P_MIPI_DPHY_SRESETN	(1 << 1)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,11 @@ if ARCH_S5PV210
 
 config CPU_S5PV210
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_EXT_INT
 	select S5P_HRT
-	select S5PV210_PM if PM
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
 	help
 	  Enable S5PV210 CPU support
 
@@ -94,11 +95,13 @@ config MACH_GONI
 	select S3C_DEV_USB_HSOTG
 	select S5P_DEV_ONENAND
 	select SAMSUNG_DEV_KEYPAD
+	select S5P_DEV_TV
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_I2C1
 	select S5PV210_SETUP_I2C2
 	select S5PV210_SETUP_KEYPAD
 	select S5PV210_SETUP_SDHCI
+	select S5PV210_SETUP_FIMC
 	help
 	  Machine support for Samsung GONI board
 	  S5PC110(MCP) is one of package option of S5PV210
@@ -169,9 +172,4 @@ config MACH_TORBRECK
 
 endmenu
 
-config S5PV210_PM
-	bool
-	help
-	  Power Management code common to S5PV210
-
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-aquila.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-aquila.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-aquila.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-aquila.c	2012-01-04 18:55:44.000000000 -0500
@@ -678,7 +678,7 @@ MACHINE_START(AQUILA, "Aquila")
 	/* Maintainers:
 	   Marek Szyprowski <m.szyprowski@samsung.com>
 	   Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-goni.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-goni.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-goni.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-goni.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,11 @@
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/camport.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/noon010pc30.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -272,6 +277,14 @@ static void __init goni_tsp_init(void)
 	i2c2_devs[0].irq = gpio_to_irq(gpio);
 }
 
+static void goni_camera_init(void)
+{
+	s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
+
+	/* Set max driver strength on CAM_A_CLKOUT pin. */
+	s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
@@ -285,6 +298,7 @@ static struct regulator_consumer_supply
 
 static struct regulator_consumer_supply goni_ldo8_consumers[] = {
 	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+	REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_consumer_supply goni_ldo11_consumers[] = {
@@ -475,6 +489,10 @@ static struct regulator_consumer_supply
 static struct regulator_consumer_supply buck2_consumer =
 	REGULATOR_SUPPLY("vddint", NULL);
 
+static struct regulator_consumer_supply buck3_consumer =
+	REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+
 static struct regulator_init_data goni_buck1_data = {
 	.constraints	= {
 		.name		= "VARM_1.2V",
@@ -511,6 +529,8 @@ static struct regulator_init_data goni_b
 			.enabled = 1,
 		},
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck3_consumer,
 };
 
 static struct regulator_init_data goni_buck4_data = {
@@ -801,6 +821,34 @@ static void goni_setup_sdhci(void)
 	s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
 };
 
+static struct noon010pc30_platform_data noon010pc30_pldata = {
+	.clk_rate	= 16000000UL,
+	.gpio_nreset	= S5PV210_GPB(2), /* CAM_CIF_NRST */
+	.gpio_nstby	= S5PV210_GPB(0), /* CAM_CIF_NSTBY */
+};
+
+static struct i2c_board_info noon010pc30_board_info = {
+	I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
+	.platform_data = &noon010pc30_pldata,
+};
+
+static struct s5p_fimc_isp_info goni_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_ITU_601,
+		.board_info	= &noon010pc30_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 16000000UL,
+	},
+};
+
+struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
+	.isp_info	= goni_camera_sensors,
+	.num_clients	= ARRAY_SIZE(goni_camera_sensors),
+};
+
 static struct platform_device *goni_devices[] __initdata = {
 	&s3c_device_fb,
 	&s5p_device_onenand,
@@ -812,10 +860,13 @@ static struct platform_device *goni_devi
 	&s5p_device_mfc,
 	&s5p_device_mfc_l,
 	&s5p_device_mfc_r,
+	&s5p_device_mixer,
+	&s5p_device_sdo,
 	&s3c_device_i2c0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
+	&s5p_device_fimc_md,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_hsmmc2,
@@ -884,6 +935,12 @@ static void __init goni_machine_init(voi
 	/* FB */
 	s3c_fb_set_platdata(&goni_lcd_pdata);
 
+	/* FIMC */
+	s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	goni_camera_init();
+
 	/* SPI */
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
@@ -897,7 +954,7 @@ static void __init goni_machine_init(voi
 
 MACHINE_START(GONI, "GONI")
 	/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,7 +136,7 @@ static void __init smdkc110_machine_init
 
 MACHINE_START(SMDKC110, "SMDKC110")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,12 +265,6 @@ static struct i2c_board_info smdkv210_i2
 	/* To Be Updated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
 	.no = S5PV210_GPD0(3),
@@ -279,6 +273,7 @@ static struct samsung_bl_gpio_info smdkv
 
 static struct platform_pwm_backlight_data smdkv210_bl_data = {
 	.pwm_id = 3,
+	.pwm_period_ns = 1000,
 };
 
 static void __init smdkv210_map_io(void)
@@ -296,7 +291,7 @@ static void __init smdkv210_machine_init
 	smdkv210_dm9000_init();
 
 	samsung_keypad_set_platdata(&smdkv210_keypad_data);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c1_set_platdata(NULL);
@@ -319,7 +314,7 @@ static void __init smdkv210_machine_init
 
 MACHINE_START(SMDKV210, "SMDKV210")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-torbreck.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-torbreck.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/mach-torbreck.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/mach-torbreck.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@ static void __init torbreck_machine_init
 
 MACHINE_START(TORBRECK, "TORBRECK")
 	/* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Makefile linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@ obj-				:=
 
 obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)	+= setup-i2c0.o
-obj-$(CONFIG_S5PV210_PM)	+= pm.o sleep.o
+obj-$(CONFIG_PM)		+= pm.o
 
 # machine support
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/setup-sdhci.c linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/setup-sdhci.c
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,17 +10,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -30,34 +20,3 @@ char *s5pv210_hsmmc_clksrcs[4] = {
 	[2] = "sclk_mmc",	/* mmc_bus */
 	/* [3] = NULL,		- reserved */
 };
-
-void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
-				    void __iomem *r,
-				    struct mmc_ios *ios,
-				    struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything according to card-type */
-
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/sleep.S linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/mach-s5pv210/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-s5pv210/sleep.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/* linux/arch/arm/plat-s5p/sleep.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV210 power Manager (Suspend-To-RAM) support
- * Based on S3C2410 sleep code by:
- * 	Ben Dooks, (c) 2004 Simtec Electronics
- *
- * Based on PXA/SA1100 sleep code by:
- *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *	Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/memory.h>
-
-	.text
-
-	/* sleep magic, to allow the bootloader to check for an valid
-	 * image to resume to. Must be the first word before the
-	 * s3c_cpu_resume entry.
-	*/
-
-	.word	0x2bedf00d
-
-	/* s3c_cpu_resume
-	 *
-	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
-	*/
-
-ENTRY(s3c_cpu_resume)
-	b	cpu_resume
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/assabet.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/assabet.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/assabet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/assabet.c	2012-01-04 18:55:44.000000000 -0500
@@ -301,8 +301,7 @@ static void __init get_assabet_scr(void)
 }
 
 static void __init
-fixup_assabet(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
+fixup_assabet(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	/* This must be done before any call to machine_has_neponset() */
 	map_sa1100_gpio_regs();
@@ -447,7 +446,7 @@ static void __init assabet_map_io(void)
 
 
 MACHINE_START(ASSABET, "Intel-Assabet")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.fixup		= fixup_assabet,
 	.map_io		= assabet_map_io,
 	.init_irq	= sa1100_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/badge4.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/badge4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/badge4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/badge4.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,7 +302,7 @@ static void __init badge4_map_io(void)
 }
 
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= badge4_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/collie.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/collie.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/collie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/collie.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
+#include <asm/page.h>
 #include <asm/setup.h>
 #include <mach/collie.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/generic.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/generic.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,7 +25,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
-#include <asm/gpio.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/gpio.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/gpio.c
- *
- * Generic SA-1100 GPIO handling
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/gpio.h>
-#include <mach/hardware.h>
-#include "generic.h"
-
-static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return GPLR & GPIO_GPIO(offset);
-}
-
-static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (value)
-		GPSR = GPIO_GPIO(offset);
-	else
-		GPCR = GPIO_GPIO(offset);
-}
-
-static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	GPDR &= ~GPIO_GPIO(offset);
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	sa1100_gpio_set(chip, offset, value);
-	GPDR |= GPIO_GPIO(offset);
-	local_irq_restore(flags);
-	return 0;
-}
-
-static struct gpio_chip sa1100_gpio_chip = {
-	.label			= "gpio",
-	.direction_input	= sa1100_direction_input,
-	.direction_output	= sa1100_direction_output,
-	.set			= sa1100_gpio_set,
-	.get			= sa1100_gpio_get,
-	.base			= 0,
-	.ngpio			= GPIO_MAX + 1,
-};
-
-void __init sa1100_init_gpio(void)
-{
-	gpiochip_add(&sa1100_gpio_chip);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/h3100.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/h3100.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/h3100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/h3100.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@ static void __init h3100_mach_init(void)
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= h3100_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/h3600.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/h3600.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/h3600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/h3600.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@ static void __init h3600_mach_init(void)
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= h3600_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/hackkit.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/hackkit.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/hackkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/hackkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,7 +195,7 @@ static void __init hackkit_init(void)
  */
 
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= hackkit_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 */
 #include <mach/hardware.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		moveq	\rp, #0x80000000	@ physical base address
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <asm/irq.h>
 #include <asm-generic/gpio.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 static inline int gpio_get_value(unsigned gpio)
 {
 	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
@@ -51,7 +53,5 @@ static inline void gpio_set_value(unsign
 
 #define gpio_to_irq(gpio)	((gpio < 11) ? (IRQ_GPIO0 + gpio) : \
 					(IRQ_GPIO11 - 11 + gpio))
-#define irq_to_gpio(irq)	((irq < IRQ_GPIO11_27) ? (irq - IRQ_GPIO0) : \
-					(irq - IRQ_GPIO11 + 11))
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
-
 /*
- * We don't actually have real ISA nor PCI buses, but there is so many 
- * drivers out there that might just work if we fake them...
+ * __io() is required to be an equivalent mapping to __mem_pci() for
+ * SOC_COMMON to work.
  */
 #define __io(a)		__typesafe_io(a)
 #define __mem_pci(a)	(a)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/simpad.h linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/simpad.h
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/include/mach/simpad.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/include/mach/simpad.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,32 +48,80 @@
 #define GPIO_SMART_CARD		GPIO_GPIO10
 #define IRQ_GPIO_SMARD_CARD	IRQ_GPIO10
 
-// CS3 Latch is write only, a shadow is necessary
+/*--- ucb1x00 GPIO ---*/
+#define SIMPAD_UCB1X00_GPIO_BASE	(GPIO_MAX + 1)
+#define SIMPAD_UCB1X00_GPIO_PROG1	(SIMPAD_UCB1X00_GPIO_BASE)
+#define SIMPAD_UCB1X00_GPIO_PROG2	(SIMPAD_UCB1X00_GPIO_BASE + 1)
+#define SIMPAD_UCB1X00_GPIO_UP		(SIMPAD_UCB1X00_GPIO_BASE + 2)
+#define SIMPAD_UCB1X00_GPIO_DOWN	(SIMPAD_UCB1X00_GPIO_BASE + 3)
+#define SIMPAD_UCB1X00_GPIO_LEFT	(SIMPAD_UCB1X00_GPIO_BASE + 4)
+#define SIMPAD_UCB1X00_GPIO_RIGHT	(SIMPAD_UCB1X00_GPIO_BASE + 5)
+#define SIMPAD_UCB1X00_GPIO_6		(SIMPAD_UCB1X00_GPIO_BASE + 6)
+#define SIMPAD_UCB1X00_GPIO_7		(SIMPAD_UCB1X00_GPIO_BASE + 7)
+#define SIMPAD_UCB1X00_GPIO_HEADSET	(SIMPAD_UCB1X00_GPIO_BASE + 8)
+#define SIMPAD_UCB1X00_GPIO_SPEAKER	(SIMPAD_UCB1X00_GPIO_BASE + 9)
+
+/*--- CS3 Latch ---*/
+#define SIMPAD_CS3_GPIO_BASE		(GPIO_MAX + 11)
+#define SIMPAD_CS3_VCC_5V_EN		(SIMPAD_CS3_GPIO_BASE)
+#define SIMPAD_CS3_VCC_3V_EN		(SIMPAD_CS3_GPIO_BASE + 1)
+#define SIMPAD_CS3_EN1			(SIMPAD_CS3_GPIO_BASE + 2)
+#define SIMPAD_CS3_EN0			(SIMPAD_CS3_GPIO_BASE + 3)
+#define SIMPAD_CS3_DISPLAY_ON		(SIMPAD_CS3_GPIO_BASE + 4)
+#define SIMPAD_CS3_PCMCIA_BUFF_DIS	(SIMPAD_CS3_GPIO_BASE + 5)
+#define SIMPAD_CS3_MQ_RESET		(SIMPAD_CS3_GPIO_BASE + 6)
+#define SIMPAD_CS3_PCMCIA_RESET		(SIMPAD_CS3_GPIO_BASE + 7)
+#define SIMPAD_CS3_DECT_POWER_ON	(SIMPAD_CS3_GPIO_BASE + 8)
+#define SIMPAD_CS3_IRDA_SD		(SIMPAD_CS3_GPIO_BASE + 9)
+#define SIMPAD_CS3_RS232_ON		(SIMPAD_CS3_GPIO_BASE + 10)
+#define SIMPAD_CS3_SD_MEDIAQ		(SIMPAD_CS3_GPIO_BASE + 11)
+#define SIMPAD_CS3_LED2_ON		(SIMPAD_CS3_GPIO_BASE + 12)
+#define SIMPAD_CS3_IRDA_MODE		(SIMPAD_CS3_GPIO_BASE + 13)
+#define SIMPAD_CS3_ENABLE_5V		(SIMPAD_CS3_GPIO_BASE + 14)
+#define SIMPAD_CS3_RESET_SIMCARD	(SIMPAD_CS3_GPIO_BASE + 15)
+
+#define SIMPAD_CS3_PCMCIA_BVD1		(SIMPAD_CS3_GPIO_BASE + 16)
+#define SIMPAD_CS3_PCMCIA_BVD2		(SIMPAD_CS3_GPIO_BASE + 17)
+#define SIMPAD_CS3_PCMCIA_VS1		(SIMPAD_CS3_GPIO_BASE + 18)
+#define SIMPAD_CS3_PCMCIA_VS2		(SIMPAD_CS3_GPIO_BASE + 19)
+#define SIMPAD_CS3_LOCK_IND		(SIMPAD_CS3_GPIO_BASE + 20)
+#define SIMPAD_CS3_CHARGING_STATE	(SIMPAD_CS3_GPIO_BASE + 21)
+#define SIMPAD_CS3_PCMCIA_SHORT		(SIMPAD_CS3_GPIO_BASE + 22)
+#define SIMPAD_CS3_GPIO_23		(SIMPAD_CS3_GPIO_BASE + 23)
 
-#define CS3BUSTYPE unsigned volatile long
 #define CS3_BASE        0xf1000000
 
-#define VCC_5V_EN       0x0001 // For 5V PCMCIA
-#define VCC_3V_EN       0x0002 // FOR 3.3V PCMCIA
-#define EN1             0x0004 // This is only for EPROM's
-#define EN0             0x0008 // Both should be enable for 3.3V or 5V
-#define DISPLAY_ON      0x0010
-#define PCMCIA_BUFF_DIS 0x0020
-#define MQ_RESET        0x0040
-#define PCMCIA_RESET    0x0080
-#define DECT_POWER_ON   0x0100
-#define IRDA_SD         0x0200 // Shutdown for powersave
-#define RS232_ON        0x0400
-#define SD_MEDIAQ       0x0800 // Shutdown for powersave
-#define LED2_ON         0x1000
-#define IRDA_MODE       0x2000 // Fast/Slow IrDA mode
-#define ENABLE_5V       0x4000 // Enable 5V circuit
-#define RESET_SIMCARD   0x8000
+long simpad_get_cs3_ro(void);
+long simpad_get_cs3_shadow(void);
+void simpad_set_cs3_bit(int value);
+void simpad_clear_cs3_bit(int value);
 
-#define RS232_ENABLE    0x0440
-#define PCMCIAMASK      0x402f
+#define VCC_5V_EN	0x0001 /* For 5V PCMCIA */
+#define VCC_3V_EN	0x0002 /* FOR 3.3V PCMCIA */
+#define EN1		0x0004 /* This is only for EPROM's */
+#define EN0		0x0008 /* Both should be enable for 3.3V or 5V */
+#define DISPLAY_ON	0x0010
+#define PCMCIA_BUFF_DIS	0x0020
+#define MQ_RESET	0x0040
+#define PCMCIA_RESET	0x0080
+#define DECT_POWER_ON	0x0100
+#define IRDA_SD		0x0200 /* Shutdown for powersave */
+#define RS232_ON	0x0400
+#define SD_MEDIAQ	0x0800 /* Shutdown for powersave */
+#define LED2_ON		0x1000
+#define IRDA_MODE	0x2000 /* Fast/Slow IrDA mode */
+#define ENABLE_5V	0x4000 /* Enable 5V circuit */
+#define RESET_SIMCARD	0x8000
 
+#define PCMCIA_BVD1	0x01
+#define PCMCIA_BVD2	0x02
+#define PCMCIA_VS1	0x04
+#define PCMCIA_VS2	0x08
+#define LOCK_IND	0x10
+#define CHARGING_STATE	0x20
+#define PCMCIA_SHORT	0x40
 
+/*--- Battery ---*/
 struct simpad_battery {
 	unsigned char ac_status;	/* line connected yes/no */
 	unsigned char status;		/* battery loading yes/no */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/jornada720.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/jornada720.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/jornada720.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/jornada720.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/irq.h>
+#include <asm/page.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
@@ -364,7 +365,7 @@ static void __init jornada720_mach_init(
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
 	/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= jornada720_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/lart.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/lart.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/lart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/lart.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@ static void __init lart_map_io(void)
 }
 
 MACHINE_START(LART, "LART")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= lart_map_io,
 	.init_irq	= sa1100_init_irq,
 	.init_machine	= lart_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,6 @@ sa1100_leds_init(void)
 		leds_event = adsbitsy_leds_event;
 	if (machine_is_pt_system3())
 		leds_event = system3_leds_event;
-	if (machine_is_simpad())
-		leds_event = simpad_leds_event; /* what about machine registry? including led, apm... -zecke */
 
 	leds_event(led_start);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds.h linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds.h
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,4 +11,3 @@ extern void pfs168_leds_event(led_event_
 extern void graphicsmaster_leds_event(led_event_t evt);
 extern void adsbitsy_leds_event(led_event_t evt);
 extern void system3_leds_event(led_event_t evt);
-extern void simpad_leds_event(led_event_t evt);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds-simpad.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds-simpad.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/leds-simpad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/leds-simpad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-simpad.c
- *
- * Author: Juergen Messerer <juergen.messerer@siemens.ch>
- */
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-#include <mach/simpad.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define	LED_GREEN	(1)
-#define	LED_MASK	(1)
-
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);     
-
-void simpad_leds_event(led_event_t evt)
-{
-	switch (evt)
-	{
-	case led_start:
-	        hw_led_state = LED_GREEN;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = LED_GREEN;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = LED_GREEN;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= LED_GREEN;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		break;
-
-	case led_idle_end:
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= LED_GREEN;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~LED_GREEN;
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		break;
-
-	case led_red_off:
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		set_cs3_bit(LED2_ON);
-	else 
-	        clear_cs3_bit(LED2_ON);
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/Makefile linux-libre-3.2-gnu1/arch/arm/mach-sa1100/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o
+obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -45,7 +45,6 @@ obj-$(CONFIG_SA1100_PLEB)		+= pleb.o
 obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
 
 obj-$(CONFIG_SA1100_SIMPAD)		+= simpad.o
-led-$(CONFIG_SA1100_SIMPAD)		+= leds-simpad.o
 
 # LEDs support
 obj-$(CONFIG_LEDS) += $(led-y)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-sa1100/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
-   zreladdr-y	:= 0xc0008000
-ifeq ($(CONFIG_ARCH_SA1100),y)
-   zreladdr-$(CONFIG_SA1111)		:= 0xc0208000
+ifeq ($(CONFIG_SA1111),y)
+   zreladdr-y	+= 0xc0208000
+else
+   zreladdr-y	+= 0xc0008000
 endif
 params_phys-y	:= 0xc0000100
 initrd_phys-y	:= 0xc0800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/nanoengine.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/nanoengine.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/nanoengine.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/nanoengine.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@ static void __init nanoengine_init(void)
 }
 
 MACHINE_START(NANOENGINE, "BSE nanoEngine")
-	.boot_params	= 0xc0000000,
+	.atag_offset	= 0x100,
 	.map_io		= nanoengine_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/shannon.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/shannon.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/shannon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/shannon.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,7 +82,7 @@ static void __init shannon_map_io(void)
 }
 
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= shannon_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-sa1100/simpad.c linux-libre-3.2-gnu1/arch/arm/mach-sa1100/simpad.c
--- linux-libre-3.1-gnu1/arch/arm/mach-sa1100/simpad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-sa1100/simpad.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -28,35 +29,92 @@
 
 #include <linux/serial_core.h>
 #include <linux/ioport.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/i2c-gpio.h>
 
 #include "generic.h"
 
-long cs3_shadow;
+/*
+ * CS3 support
+ */
 
-long get_cs3_shadow(void)
+static long cs3_shadow;
+static spinlock_t cs3_lock;
+static struct gpio_chip cs3_gpio;
+
+long simpad_get_cs3_ro(void)
+{
+	return readl(CS3_BASE);
+}
+EXPORT_SYMBOL(simpad_get_cs3_ro);
+
+long simpad_get_cs3_shadow(void)
 {
 	return cs3_shadow;
 }
+EXPORT_SYMBOL(simpad_get_cs3_shadow);
 
-void set_cs3(long value)
+static void __simpad_write_cs3(void)
 {
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
+	writel(cs3_shadow, CS3_BASE);
 }
 
-void set_cs3_bit(int value)
+void simpad_set_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow |= value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_set_cs3_bit);
 
-void clear_cs3_bit(int value)
+void simpad_clear_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow &= ~value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_clear_cs3_bit);
 
-EXPORT_SYMBOL(set_cs3_bit);
-EXPORT_SYMBOL(clear_cs3_bit);
+static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (offset > 15)
+		return;
+	if (value)
+		simpad_set_cs3_bit(1 << offset);
+	else
+		simpad_clear_cs3_bit(1 << offset);
+};
+
+static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return simpad_get_cs3_ro() & (1 << (offset - 16));
+	return simpad_get_cs3_shadow() & (1 << offset);
+};
+
+static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return 0;
+	return -EINVAL;
+};
+
+static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+	int value)
+{
+	if (offset > 15)
+		return -EINVAL;
+	cs3_gpio_set(chip, offset, value);
+	return 0;
+};
 
 static struct map_desc simpad_io_desc[] __initdata = {
 	{	/* MQ200 */
@@ -64,9 +122,9 @@ static struct map_desc simpad_io_desc[]
 		.pfn		= __phys_to_pfn(0x4b800000),
 		.length		= 0x00800000,
 		.type		= MT_DEVICE
-	}, {	/* Paules CS3, write only */
-		.virtual	=  0xf1000000,
-		.pfn		= __phys_to_pfn(0x18000000),
+	}, {	/* Simpad CS3 */
+		.virtual	= CS3_BASE,
+		.pfn		= __phys_to_pfn(SA1100_CS3_PHYS),
 		.length		= 0x00100000,
 		.type		= MT_DEVICE
 	},
@@ -78,12 +136,12 @@ static void simpad_uart_pm(struct uart_p
 	if (port->mapbase == (u_int)&Ser1UTCR0) {
 		if (state)
 		{
-			clear_cs3_bit(RS232_ON);
-			clear_cs3_bit(DECT_POWER_ON);
+			simpad_clear_cs3_bit(RS232_ON);
+			simpad_clear_cs3_bit(DECT_POWER_ON);
 		}else
 		{
-			set_cs3_bit(RS232_ON);
-			set_cs3_bit(DECT_POWER_ON);
+			simpad_set_cs3_bit(RS232_ON);
+			simpad_set_cs3_bit(DECT_POWER_ON);
 		}
 	}
 }
@@ -132,6 +190,7 @@ static struct resource simpad_flash_reso
 static struct mcp_plat_data simpad_mcp_data = {
 	.mccr0		= MCCR0_ADM,
 	.sclk_rate	= 11981000,
+	.gpio_base	= SIMPAD_UCB1X00_GPIO_BASE,
 };
 
 
@@ -142,9 +201,10 @@ static void __init simpad_map_io(void)
 
 	iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc));
 
-	set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-		      ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
-
+	/* Initialize CS3 */
+	cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON |
+		RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
+	__simpad_write_cs3(); /* Spinlocks not yet initialized */
 
         sa1100_register_uart_fns(&simpad_port_fns);
 	sa1100_register_uart(0, 3);  /* serial interface */
@@ -170,13 +230,14 @@ static void __init simpad_map_io(void)
 
 static void simpad_power_off(void)
 {
-	local_irq_disable(); // was cli
-	set_cs3(0x800);        /* only SD_MEDIAQ */
+	local_irq_disable();
+	cs3_shadow = SD_MEDIAQ;
+	__simpad_write_cs3(); /* Bypass spinlock here */
 
 	/* disable internal oscillator, float CS lines */
 	PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
-	/* enable wake-up on GPIO0 (Assabet...) */
-	PWER = GFER = GRER = 1;
+	/* enable wake-up on GPIO0 */
+	PWER = GFER = GRER = PWER_GPIO0;
 	/*
 	 * set scratchpad to zero, just in case it is used as a
 	 * restart address by the bootloader.
@@ -192,6 +253,91 @@ static void simpad_power_off(void)
 
 }
 
+/*
+ * gpio_keys
+*/
+
+static struct gpio_keys_button simpad_button_table[] = {
+	{ KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" },
+};
+
+static struct gpio_keys_platform_data simpad_keys_data = {
+	.buttons = simpad_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_button_table),
+};
+
+static struct platform_device simpad_keys = {
+	.name = "gpio-keys",
+	.dev = {
+		.platform_data = &simpad_keys_data,
+	},
+};
+
+static struct gpio_keys_button simpad_polled_button_table[] = {
+	{ KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" },
+	{ KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" },
+	{ KEY_UP,    SIMPAD_UCB1X00_GPIO_UP,    1, "up button" },
+	{ KEY_DOWN,  SIMPAD_UCB1X00_GPIO_DOWN,  1, "down button" },
+	{ KEY_LEFT,  SIMPAD_UCB1X00_GPIO_LEFT,  1, "left button" },
+	{ KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" },
+};
+
+static struct gpio_keys_platform_data simpad_polled_keys_data = {
+	.buttons = simpad_polled_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_polled_button_table),
+	.poll_interval = 50,
+};
+
+static struct platform_device simpad_polled_keys = {
+	.name = "gpio-keys-polled",
+	.dev = {
+		.platform_data = &simpad_polled_keys_data,
+	},
+};
+
+/*
+ * GPIO LEDs
+ */
+
+static struct gpio_led simpad_leds[] = {
+	{
+		.name = "simpad:power",
+		.gpio = SIMPAD_CS3_LED2_ON,
+		.active_low = 0,
+		.default_trigger = "default-on",
+	},
+};
+
+static struct gpio_led_platform_data simpad_led_data = {
+	.num_leds = ARRAY_SIZE(simpad_leds),
+	.leds = simpad_leds,
+};
+
+static struct platform_device simpad_gpio_leds = {
+	.name = "leds-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_led_data,
+	},
+};
+
+/*
+ * i2c
+ */
+static struct i2c_gpio_platform_data simpad_i2c_data = {
+	.sda_pin = GPIO_GPIO21,
+	.scl_pin = GPIO_GPIO25,
+	.udelay = 10,
+	.timeout = HZ,
+};
+
+static struct platform_device simpad_i2c = {
+	.name = "i2c-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_i2c_data,
+	},
+};
 
 /*
  * MediaQ Video Device
@@ -202,7 +348,11 @@ static struct platform_device simpad_mq2
 };
 
 static struct platform_device *devices[] __initdata = {
-	&simpad_mq200fb
+	&simpad_keys,
+	&simpad_polled_keys,
+	&simpad_mq200fb,
+	&simpad_gpio_leds,
+	&simpad_i2c,
 };
 
 
@@ -211,6 +361,19 @@ static int __init simpad_init(void)
 {
 	int ret;
 
+	spin_lock_init(&cs3_lock);
+
+	cs3_gpio.label = "simpad_cs3";
+	cs3_gpio.base = SIMPAD_CS3_GPIO_BASE;
+	cs3_gpio.ngpio = 24;
+	cs3_gpio.set = cs3_gpio_set;
+	cs3_gpio.get = cs3_gpio_get;
+	cs3_gpio.direction_input = cs3_gpio_direction_input;
+	cs3_gpio.direction_output = cs3_gpio_direction_output;
+	ret = gpiochip_add(&cs3_gpio);
+	if (ret)
+		printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
+
 	pm_power_off = simpad_power_off;
 
 	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
@@ -229,7 +392,7 @@ arch_initcall(simpad_init);
 
 MACHINE_START(SIMPAD, "Simpad")
 	/* Maintainer: Holger Freyther */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= simpad_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shark/core.c linux-libre-3.2-gnu1/arch/arm/mach-shark/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shark/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shark/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,7 +152,7 @@ static struct sys_timer shark_timer = {
 
 MACHINE_START(SHARK, "Shark")
 	/* Maintainer: Alexander Schulz */
-	.boot_params	= 0x08003000,
+	.atag_offset	= 0x3000,
 	.map_io		= shark_map_io,
 	.init_irq	= shark_init_irq,
 	.timer		= &shark_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shark/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-shark/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-shark/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shark/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xe0000000
 		orr	\rp, \rp, #0x000003f8
 		mov	\rv, \rp
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shark/leds.c linux-libre-3.2-gnu1/arch/arm/mach-shark/leds.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shark/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shark/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@ static char led_state;
 static short hw_led_state;
 static short saved_state;
 
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
 
 short sequoia_read(int addr) {
   outw(addr,0x24);
@@ -52,7 +52,7 @@ static void sequoia_leds_event(led_event
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&leds_lock, flags);
+	raw_spin_lock_irqsave(&leds_lock, flags);
 
 	hw_led_state = sequoia_read(0x09);
 
@@ -144,7 +144,7 @@ static void sequoia_leds_event(led_event
 	if  (led_state & LED_STATE_ENABLED)
 		sequoia_write(hw_led_state,0x09);
 
-	spin_unlock_irqrestore(&leds_lock, flags);
+	raw_spin_unlock_irqrestore(&leds_lock, flags);
 }
 
 static int __init leds_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shark/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-shark/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-shark/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shark/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x08008000
+   zreladdr-y	+= 0x08008000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-ag5evm.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-ag5evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-ag5evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-ag5evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_clk.h>
+#include <linux/dma-mapping.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
@@ -58,7 +59,7 @@ static struct resource smsc9220_resource
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start		= gic_spi(33), /* PINT1 */
+		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -338,6 +339,18 @@ static struct platform_device mipidsi0_d
 	},
 };
 
+/* SDHI0 */
+static irqreturn_t ag5evm_sdhi0_gpio_cd(int irq, void *arg)
+{
+	struct device *dev = arg;
+	struct sh_mobile_sdhi_info *info = dev->platform_data;
+	struct tmio_mmc_data *pdata = info->pdata;
+
+	tmio_mmc_cd_wakeup(pdata);
+
+	return IRQ_HANDLED;
+}
+
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
@@ -354,14 +367,17 @@ static struct resource sdhi0_resources[]
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= gic_spi(83),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= gic_spi(84),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= gic_spi(85),
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -397,14 +413,17 @@ static struct resource sdhi1_resources[]
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= gic_spi(87),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= gic_spi(88),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= gic_spi(89),
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -447,25 +466,14 @@ static struct map_desc ag5evm_io_desc[]
 static void __init ag5evm_map_io(void)
 {
 	iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh73a0_add_early_devices();
 	shmobile_setup_console();
 }
 
-#define PINTC_ADDR	0xe6900000
-#define PINTER0A	(PINTC_ADDR + 0xa0)
-#define PINTCR0A	(PINTC_ADDR + 0xb0)
-
-void __init ag5evm_init_irq(void)
-{
-	sh73a0_init_irq();
-
-	/* setup PINT: enable PINTA2 as active low */
-	__raw_writel(__raw_readl(PINTER0A) | (1<<29), PINTER0A);
-	__raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A);
-}
-
 #define DSI0PHYCR	0xe615006c
 
 static void __init ag5evm_init(void)
@@ -507,14 +515,14 @@ static void __init ag5evm_init(void)
 	/* enable MMCIF */
 	gpio_request(GPIO_FN_MMCCLK0, NULL);
 	gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_0, NULL);
-	gpio_request(GPIO_FN_MMCD0_1, NULL);
-	gpio_request(GPIO_FN_MMCD0_2, NULL);
-	gpio_request(GPIO_FN_MMCD0_3, NULL);
-	gpio_request(GPIO_FN_MMCD0_4, NULL);
-	gpio_request(GPIO_FN_MMCD0_5, NULL);
-	gpio_request(GPIO_FN_MMCD0_6, NULL);
-	gpio_request(GPIO_FN_MMCD0_7, NULL);
+	gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
 	gpio_request(GPIO_PORT208, NULL); /* Reset */
 	gpio_direction_output(GPIO_PORT208, 1);
 
@@ -561,6 +569,13 @@ static void __init ag5evm_init(void)
 	gpio_request(GPIO_FN_SDHID0_1, NULL);
 	gpio_request(GPIO_FN_SDHID0_0, NULL);
 
+	if (!request_irq(intcs_evt2irq(0x3c0), ag5evm_sdhi0_gpio_cd,
+			 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			 "sdhi0 cd", &sdhi0_device.dev))
+		sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
+	else
+		pr_warn("Unable to setup SDHI0 GPIO IRQ\n");
+
 	/* enable SDHI1 on CN4 [WLAN I/F] */
 	gpio_request(GPIO_FN_SDHICLK1, NULL);
 	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
@@ -592,7 +607,8 @@ struct sys_timer ag5evm_timer = {
 
 MACHINE_START(AG5EVM, "ag5evm")
 	.map_io		= ag5evm_map_io,
-	.init_irq	= ag5evm_init_irq,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= sh73a0_init_irq,
 	.handle_irq	= shmobile_handle_irq_gic,
 	.init_machine	= ag5evm_init,
 	.timer		= &ag5evm_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-ap4evb.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-ap4evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-ap4evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-ap4evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,8 @@
 #include <linux/leds.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/pm_clock.h>
+#include <linux/dma-mapping.h>
 
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
@@ -198,8 +200,8 @@ static struct physmap_flash_data nor_fla
 
 static struct resource nor_flash_resources[] = {
 	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
+		.start	= 0x20000000, /* CS0 shadow instead of regular CS0 */
+		.end	= 0x28000000 - 1, /* needed by USB MASK ROM boot */
 		.flags	= IORESOURCE_MEM,
 	}
 };
@@ -931,7 +933,7 @@ static struct platform_device ap4evb_cam
 static struct sh_csi2_client_config csi2_clients[] = {
 	{
 		.phy		= SH_CSI2_PHY_MAIN,
-		.lanes		= 3,
+		.lanes		= 0,		/* default: 2 lanes */
 		.channel	= 0,
 		.pdev		= &ap4evb_camera,
 	},
@@ -1170,6 +1172,8 @@ static struct map_desc ap4evb_io_desc[]
 static void __init ap4evb_map_io(void)
 {
 	iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7372_add_early_devices();
@@ -1408,6 +1412,11 @@ static void __init ap4evb_init(void)
 	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
 
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
+
 	hdmi_init_pm_clock();
 	fsi_init_pm_clock();
 	sh7372_pm_init();
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-g3evm.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-g3evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-g3evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-g3evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7367.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -260,6 +261,8 @@ static struct map_desc g3evm_io_desc[] _
 static void __init g3evm_map_io(void)
 {
 	iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7367_add_early_devices();
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-g4evm.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-g4evm.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-g4evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-g4evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -274,6 +275,8 @@ static struct map_desc g4evm_io_desc[] _
 static void __init g4evm_map_io(void)
 {
 	iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7377_add_early_devices();
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-kota2.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-kota2.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-kota2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-kota2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,557 @@
+/*
+ * kota2 board support
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ * Copyright (C) 2010  Takashi Yoshii <yoshii.takashi.zj@renesas.com>
+ * Copyright (C) 2009  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/sh_keysc.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <mach/hardware.h>
+#include <mach/sh73a0.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/traps.h>
+
+/* SMSC 9220 */
+static struct resource smsc9220_resources[] = {
+	[0] = {
+		.start		= 0x14000000, /* CS5A */
+		.end		= 0x140000ff, /* A1->A7 */
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc9220_platdata = {
+	.flags		= SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device eth_device = {
+	.name		= "smsc911x",
+	.id		= 0,
+	.dev  = {
+		.platform_data = &smsc9220_platdata,
+	},
+	.resource	= smsc9220_resources,
+	.num_resources	= ARRAY_SIZE(smsc9220_resources),
+};
+
+/* KEYSC */
+static struct sh_keysc_info keysc_platdata = {
+	.mode		= SH_KEYSC_MODE_6,
+	.scan_timing	= 3,
+	.delay		= 100,
+	.keycodes	= {
+		KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND,
+		0, 0, 0, 0, 0,
+		KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9,
+		0, KEY_DOWN, 0, 0, 0,
+		KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6,
+		KEY_LEFT, KEY_ENTER, KEY_RIGHT, 0, 0,
+		KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3,
+		0, KEY_UP, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+	},
+};
+
+static struct resource keysc_resources[] = {
+	[0] = {
+		.name	= "KEYSC",
+		.start	= 0xe61b0000,
+		.end	= 0xe61b0098 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(71),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device keysc_device = {
+	.name		= "sh_keysc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(keysc_resources),
+	.resource	= keysc_resources,
+	.dev		= {
+		.platform_data	= &keysc_platdata,
+	},
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+	GPIO_KEY(KEY_VOLUMEUP, GPIO_PORT56, "+"), /* S2: VOL+ [IRQ9] */
+	GPIO_KEY(KEY_VOLUMEDOWN, GPIO_PORT54, "-"), /* S3: VOL- [IRQ10] */
+	GPIO_KEY(KEY_MENU, GPIO_PORT27, "Menu"), /* S4: MENU [IRQ30] */
+	GPIO_KEY(KEY_HOMEPAGE, GPIO_PORT26, "Home"), /* S5: HOME [IRQ31] */
+	GPIO_KEY(KEY_BACK, GPIO_PORT11, "Back"), /* S6: BACK [IRQ0] */
+	GPIO_KEY(KEY_PHONE, GPIO_PORT238, "Tel"), /* S7: TEL [IRQ11] */
+	GPIO_KEY(KEY_POWER, GPIO_PORT239, "C1"), /* S8: CAM [IRQ13] */
+	GPIO_KEY(KEY_MAIL, GPIO_PORT224, "Mail"), /* S9: MAIL [IRQ3] */
+	/* Omitted button "C3?": GPIO_PORT223 - S10: CUST [IRQ8] */
+	GPIO_KEY(KEY_CAMERA, GPIO_PORT164, "C2"), /* S11: CAM_HALF [IRQ25] */
+	/* Omitted button "?": GPIO_PORT152 - S12: CAM_FULL [No IRQ] */
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+	.buttons        = gpio_buttons,
+	.nbuttons       = ARRAY_SIZE(gpio_buttons),
+	.poll_interval  = 250, /* polled for now */
+};
+
+static struct platform_device gpio_keys_device = {
+	.name   = "gpio-keys-polled", /* polled for now */
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &gpio_key_info,
+	},
+};
+
+/* GPIO LED */
+#define GPIO_LED(n, g) { .name = n, .gpio = g }
+
+static struct gpio_led gpio_leds[] = {
+	GPIO_LED("G", GPIO_PORT20), /* PORT20 [GPO0] -> LED7 -> "G" */
+	GPIO_LED("H", GPIO_PORT21), /* PORT21 [GPO1] -> LED8 -> "H" */
+	GPIO_LED("J", GPIO_PORT22), /* PORT22 [GPO2] -> LED9 -> "J" */
+};
+
+static struct gpio_led_platform_data gpio_leds_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+	.name   = "leds-gpio",
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &gpio_leds_info,
+	},
+};
+
+/* TPU LED */
+static struct led_renesas_tpu_config led_renesas_tpu12_pdata = {
+	.name		= "V2513",
+	.pin_gpio_fn	= GPIO_FN_TPU1TO2,
+	.pin_gpio	= GPIO_PORT153,
+	.channel_offset = 0x90,
+	.timer_bit = 2,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu12_resources[] = {
+	[0] = {
+		.name	= "TPU12",
+		.start	= 0xe6610090,
+		.end	= 0xe66100b5,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu12_device = {
+	.name = "leds-renesas-tpu",
+	.id = 12,
+	.dev = {
+		.platform_data  = &led_renesas_tpu12_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu12_resources),
+	.resource	= tpu12_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu41_pdata = {
+	.name		= "V2514",
+	.pin_gpio_fn	= GPIO_FN_TPU4TO1,
+	.pin_gpio	= GPIO_PORT199,
+	.channel_offset = 0x50,
+	.timer_bit = 1,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu41_resources[] = {
+	[0] = {
+		.name	= "TPU41",
+		.start	= 0xe6640050,
+		.end	= 0xe6640075,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu41_device = {
+	.name = "leds-renesas-tpu",
+	.id = 41,
+	.dev = {
+		.platform_data  = &led_renesas_tpu41_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu41_resources),
+	.resource	= tpu41_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu21_pdata = {
+	.name		= "V2515",
+	.pin_gpio_fn	= GPIO_FN_TPU2TO1,
+	.pin_gpio	= GPIO_PORT197,
+	.channel_offset = 0x50,
+	.timer_bit = 1,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu21_resources[] = {
+	[0] = {
+		.name	= "TPU21",
+		.start	= 0xe6620050,
+		.end	= 0xe6620075,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu21_device = {
+	.name = "leds-renesas-tpu",
+	.id = 21,
+	.dev = {
+		.platform_data  = &led_renesas_tpu21_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu21_resources),
+	.resource	= tpu21_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu30_pdata = {
+	.name		= "KEYLED",
+	.pin_gpio_fn	= GPIO_FN_TPU3TO0,
+	.pin_gpio	= GPIO_PORT163,
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu30_resources[] = {
+	[0] = {
+		.name	= "TPU30",
+		.start	= 0xe6630010,
+		.end	= 0xe6630035,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu30_device = {
+	.name = "leds-renesas-tpu",
+	.id = 30,
+	.dev = {
+		.platform_data  = &led_renesas_tpu30_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu30_resources),
+	.resource	= tpu30_resources,
+};
+
+/* MMCIF */
+static struct resource mmcif_resources[] = {
+	[0] = {
+		.name   = "MMCIF",
+		.start  = 0xe6bd0000,
+		.end    = 0xe6bd00ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(140),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(141),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_plat_data mmcif_info = {
+	.ocr            = MMC_VDD_165_195,
+	.caps           = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct platform_device mmcif_device = {
+	.name           = "sh_mmcif",
+	.id             = 0,
+	.dev            = {
+		.platform_data          = &mmcif_info,
+	},
+	.num_resources  = ARRAY_SIZE(mmcif_resources),
+	.resource       = mmcif_resources,
+};
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+	.tmio_caps      = MMC_CAP_SD_HIGHSPEED,
+	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] = {
+	[0] = {
+		.name   = "SDHI0",
+		.start  = 0xee100000,
+		.end    = 0xee1000ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(83),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(84),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= gic_spi(85),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi0_device = {
+	.name           = "sh_mobile_sdhi",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(sdhi0_resources),
+	.resource       = sdhi0_resources,
+	.dev    = {
+		.platform_data  = &sdhi0_info,
+	},
+};
+
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info = {
+	.tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
+	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi1_resources[] = {
+	[0] = {
+		.name   = "SDHI1",
+		.start  = 0xee120000,
+		.end    = 0xee1200ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(87),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(88),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= gic_spi(89),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi1_device = {
+	.name           = "sh_mobile_sdhi",
+	.id             = 1,
+	.num_resources  = ARRAY_SIZE(sdhi1_resources),
+	.resource       = sdhi1_resources,
+	.dev    = {
+		.platform_data  = &sdhi1_info,
+	},
+};
+
+static struct platform_device *kota2_devices[] __initdata = {
+	&eth_device,
+	&keysc_device,
+	&gpio_keys_device,
+	&gpio_leds_device,
+	&leds_tpu12_device,
+	&leds_tpu41_device,
+	&leds_tpu21_device,
+	&leds_tpu30_device,
+	&mmcif_device,
+	&sdhi0_device,
+	&sdhi1_device,
+};
+
+static struct map_desc kota2_io_desc[] __initdata = {
+	/* create a 1:1 entity map for 0xe6xxxxxx
+	 * used by CPGA, INTC and PFC.
+	 */
+	{
+		.virtual	= 0xe6000000,
+		.pfn		= __phys_to_pfn(0xe6000000),
+		.length		= 256 << 20,
+		.type		= MT_DEVICE_NONSHARED
+	},
+};
+
+static void __init kota2_map_io(void)
+{
+	iotable_init(kota2_io_desc, ARRAY_SIZE(kota2_io_desc));
+
+	/* setup early devices and console here as well */
+	sh73a0_add_early_devices();
+	shmobile_setup_console();
+}
+
+static void __init kota2_init(void)
+{
+	sh73a0_pinmux_init();
+
+	/* SCIFA2 (UART2) */
+	gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
+	gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
+	gpio_request(GPIO_FN_SCIFA2_RTS1_, NULL);
+	gpio_request(GPIO_FN_SCIFA2_CTS1_, NULL);
+
+	/* SCIFA4 (UART1) */
+	gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
+	gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
+	gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
+	gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
+
+	/* SMSC911X */
+	gpio_request(GPIO_FN_D0_NAF0, NULL);
+	gpio_request(GPIO_FN_D1_NAF1, NULL);
+	gpio_request(GPIO_FN_D2_NAF2, NULL);
+	gpio_request(GPIO_FN_D3_NAF3, NULL);
+	gpio_request(GPIO_FN_D4_NAF4, NULL);
+	gpio_request(GPIO_FN_D5_NAF5, NULL);
+	gpio_request(GPIO_FN_D6_NAF6, NULL);
+	gpio_request(GPIO_FN_D7_NAF7, NULL);
+	gpio_request(GPIO_FN_D8_NAF8, NULL);
+	gpio_request(GPIO_FN_D9_NAF9, NULL);
+	gpio_request(GPIO_FN_D10_NAF10, NULL);
+	gpio_request(GPIO_FN_D11_NAF11, NULL);
+	gpio_request(GPIO_FN_D12_NAF12, NULL);
+	gpio_request(GPIO_FN_D13_NAF13, NULL);
+	gpio_request(GPIO_FN_D14_NAF14, NULL);
+	gpio_request(GPIO_FN_D15_NAF15, NULL);
+	gpio_request(GPIO_FN_CS5A_, NULL);
+	gpio_request(GPIO_FN_WE0__FWE, NULL);
+	gpio_request(GPIO_PORT144, NULL); /* PINTA2 */
+	gpio_direction_input(GPIO_PORT144);
+	gpio_request(GPIO_PORT145, NULL); /* RESET */
+	gpio_direction_output(GPIO_PORT145, 1);
+
+	/* KEYSC */
+	gpio_request(GPIO_FN_KEYIN0_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN1_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN2_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN3_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN4_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN5_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN6_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN7_PU, NULL);
+	gpio_request(GPIO_FN_KEYOUT0, NULL);
+	gpio_request(GPIO_FN_KEYOUT1, NULL);
+	gpio_request(GPIO_FN_KEYOUT2, NULL);
+	gpio_request(GPIO_FN_KEYOUT3, NULL);
+	gpio_request(GPIO_FN_KEYOUT4, NULL);
+	gpio_request(GPIO_FN_KEYOUT5, NULL);
+	gpio_request(GPIO_FN_PORT59_KEYOUT6, NULL);
+	gpio_request(GPIO_FN_PORT58_KEYOUT7, NULL);
+	gpio_request(GPIO_FN_KEYOUT8, NULL);
+
+	/* MMCIF */
+	gpio_request(GPIO_FN_MMCCLK0, NULL);
+	gpio_request(GPIO_FN_MMCD0_0, NULL);
+	gpio_request(GPIO_FN_MMCD0_1, NULL);
+	gpio_request(GPIO_FN_MMCD0_2, NULL);
+	gpio_request(GPIO_FN_MMCD0_3, NULL);
+	gpio_request(GPIO_FN_MMCD0_4, NULL);
+	gpio_request(GPIO_FN_MMCD0_5, NULL);
+	gpio_request(GPIO_FN_MMCD0_6, NULL);
+	gpio_request(GPIO_FN_MMCD0_7, NULL);
+	gpio_request(GPIO_FN_MMCCMD0, NULL);
+	gpio_request(GPIO_PORT208, NULL); /* Reset */
+	gpio_direction_output(GPIO_PORT208, 1);
+
+	/* SDHI0 (microSD) */
+	gpio_request(GPIO_FN_SDHICD0_PU, NULL);
+	gpio_request(GPIO_FN_SDHICMD0_PU, NULL);
+	gpio_request(GPIO_FN_SDHICLK0, NULL);
+	gpio_request(GPIO_FN_SDHID0_3_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_2_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_0_PU, NULL);
+
+	/* SCIFB (BT) */
+	gpio_request(GPIO_FN_PORT159_SCIFB_SCK, NULL);
+	gpio_request(GPIO_FN_PORT160_SCIFB_TXD, NULL);
+	gpio_request(GPIO_FN_PORT161_SCIFB_CTS_, NULL);
+	gpio_request(GPIO_FN_PORT162_SCIFB_RXD, NULL);
+	gpio_request(GPIO_FN_PORT163_SCIFB_RTS_, NULL);
+
+	/* SDHI1 (BCM4330) */
+	gpio_request(GPIO_FN_SDHICLK1, NULL);
+	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
+
+#ifdef CONFIG_CACHE_L2X0
+	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
+	l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff);
+#endif
+	sh73a0_add_standard_devices();
+	platform_add_devices(kota2_devices, ARRAY_SIZE(kota2_devices));
+}
+
+static void __init kota2_timer_init(void)
+{
+	sh73a0_clock_init();
+	shmobile_timer.init();
+	return;
+}
+
+struct sys_timer kota2_timer = {
+	.init	= kota2_timer_init,
+};
+
+MACHINE_START(KOTA2, "kota2")
+	.map_io		= kota2_map_io,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= sh73a0_init_irq,
+	.handle_irq	= shmobile_handle_irq_gic,
+	.init_machine	= kota2_init,
+	.timer		= &kota2_timer,
+MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-mackerel.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-mackerel.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/board-mackerel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/board-mackerel.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,12 +39,13 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/smsc911x.h>
 #include <linux/sh_intc.h>
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/renesas_usbhs.h>
+#include <linux/dma-mapping.h>
 
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
@@ -272,8 +273,8 @@ static struct physmap_flash_data nor_fla
 
 static struct resource nor_flash_resources[] = {
 	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
+		.start	= 0x20000000, /* CS0 shadow instead of regular CS0 */
+		.end	= 0x28000000 - 1, /* needed by USB MASK ROM boot */
 		.flags	= IORESOURCE_MEM,
 	}
 };
@@ -810,6 +811,7 @@ static struct usbhs_private usbhs1_priva
 		},
 		.driver_param = {
 			.buswait_bwait	= 4,
+			.has_otg	= 1,
 			.pipe_type	= usbhs1_pipe_cfg,
 			.pipe_size	= ARRAY_SIZE(usbhs1_pipe_cfg),
 			.d0_tx_id	= SHDMA_SLAVE_USB1_TX,
@@ -1070,14 +1072,17 @@ static struct resource sdhi1_resources[]
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -1121,14 +1126,17 @@ static struct resource sdhi2_resources[]
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= evt2irq(0x1200), /* SDHI2_SDHI2I0 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x1220), /* SDHI2_SDHI2I1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x1240), /* SDHI2_SDHI2I2 */
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -1215,9 +1223,10 @@ static struct soc_camera_platform_info c
 		.width = 640,
 		.height = 480,
 	},
-	.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-	SOCAM_DATA_ACTIVE_HIGH,
+	.mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+	V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+	V4L2_MBUS_DATA_ACTIVE_HIGH,
+	.mbus_type = V4L2_MBUS_PARALLEL,
 	.set_capture = camera_set_capture,
 };
 
@@ -1381,6 +1390,8 @@ static struct map_desc mackerel_io_desc[
 static void __init mackerel_map_io(void)
 {
 	iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7372_add_early_devices();
@@ -1587,7 +1598,17 @@ static void __init mackerel_init(void)
 
 	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
 	sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
+	sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+#endif
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
 
 	hdmi_init_pm_clock();
 	sh7372_pm_init();
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sh_clk.h>
+#include <linux/export.h>
 
 int __init clk_init(void)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock-sh7372.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock-sh7372.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -476,7 +476,7 @@ static struct clk_ops fsidiv_clk_ops = {
 	.disable	= fsidiv_disable,
 };
 
-static struct clk_mapping sh7372_fsidiva_clk_mapping = {
+static struct clk_mapping fsidiva_clk_mapping = {
 	.phys	= FSIDIVA,
 	.len	= 8,
 };
@@ -484,10 +484,10 @@ static struct clk_mapping sh7372_fsidiva
 struct clk sh7372_fsidiva_clk = {
 	.ops		= &fsidiv_clk_ops,
 	.parent		= &div6_reparent_clks[DIV6_FSIA], /* late install */
-	.mapping	= &sh7372_fsidiva_clk_mapping,
+	.mapping	= &fsidiva_clk_mapping,
 };
 
-static struct clk_mapping sh7372_fsidivb_clk_mapping = {
+static struct clk_mapping fsidivb_clk_mapping = {
 	.phys	= FSIDIVB,
 	.len	= 8,
 };
@@ -495,7 +495,7 @@ static struct clk_mapping sh7372_fsidivb
 struct clk sh7372_fsidivb_clk = {
 	.ops		= &fsidiv_clk_ops,
 	.parent		= &div6_reparent_clks[DIV6_FSIB],  /* late install */
-	.mapping	= &sh7372_fsidivb_clk_mapping,
+	.mapping	= &fsidivb_clk_mapping,
 };
 
 static struct clk *late_main_clks[] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,12 @@ static struct clk main_clk = {
 	.ops		= &main_clk_ops,
 };
 
+/* Divide Main clock by two */
+static struct clk main_div2_clk = {
+	.ops		= &div2_clk_ops,
+	.parent		= &main_clk,
+};
+
 /* PLL0, PLL1, PLL2, PLL3 */
 static unsigned long pll_recalc(struct clk *clk)
 {
@@ -181,6 +187,7 @@ static struct clk *main_clks[] = {
 	&extal1_div2_clk,
 	&extal2_div2_clk,
 	&main_clk,
+	&main_div2_clk,
 	&pll0_clk,
 	&pll1_clk,
 	&pll2_clk,
@@ -243,7 +250,7 @@ static struct clk div6_clks[DIV6_NR] = {
 	[DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0),
 	[DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0),
 	[DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0),
-	[DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, 0),
+	[DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT),
 	[DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0),
 	[DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0),
 	[DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
@@ -268,6 +275,7 @@ enum { MSTP001,
 	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
 	MSTP331, MSTP329, MSTP325, MSTP323, MSTP318,
 	MSTP314, MSTP313, MSTP312, MSTP311,
+	MSTP303, MSTP302, MSTP301, MSTP300,
 	MSTP411, MSTP410, MSTP403,
 	MSTP_NR };
 
@@ -301,6 +309,10 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
 	[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
 	[MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */
+	[MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */
+	[MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */
+	[MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */
+	[MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */
 	[MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
 	[MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
 	[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
@@ -350,6 +362,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
 	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/cpuidle.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/cpuidle.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,65 +26,59 @@ void (*shmobile_cpuidle_modes[CPUIDLE_ST
 };
 
 static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
-				  struct cpuidle_state *state)
+				  struct cpuidle_driver *drv,
+				  int index)
 {
 	ktime_t before, after;
-	int requested_state = state - &dev->states[0];
 
-	dev->last_state = &dev->states[requested_state];
 	before = ktime_get();
 
 	local_irq_disable();
 	local_fiq_disable();
 
-	shmobile_cpuidle_modes[requested_state]();
+	shmobile_cpuidle_modes[index]();
 
 	local_irq_enable();
 	local_fiq_enable();
 
 	after = ktime_get();
-	return ktime_to_ns(ktime_sub(after, before)) >> 10;
+	dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	return index;
 }
 
 static struct cpuidle_device shmobile_cpuidle_dev;
 static struct cpuidle_driver shmobile_cpuidle_driver = {
 	.name =		"shmobile_cpuidle",
 	.owner =	THIS_MODULE,
+	.states[0] = {
+		.name = "C1",
+		.desc = "WFI",
+		.exit_latency = 1,
+		.target_residency = 1 * 2,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+	},
+	.safe_state_index = 0, /* C1 */
+	.state_count = 1,
 };
 
-void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 static int shmobile_cpuidle_init(void)
 {
 	struct cpuidle_device *dev = &shmobile_cpuidle_dev;
-	struct cpuidle_state *state;
+	struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
 	int i;
 
-	cpuidle_register_driver(&shmobile_cpuidle_driver);
-
-	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
-		dev->states[i].enter = shmobile_cpuidle_enter;
-	}
-
-	i = CPUIDLE_DRIVER_STATE_START;
-
-	state = &dev->states[i++];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
-	strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
-	state->exit_latency = 1;
-	state->target_residency = 1 * 2;
-	state->power_usage = 3;
-	state->flags = 0;
-	state->flags |= CPUIDLE_FLAG_TIME_VALID;
-
-	dev->safe_state = state;
-	dev->state_count = i;
+	for (i = 0; i < CPUIDLE_STATE_MAX; i++)
+		drv->states[i].enter = shmobile_cpuidle_enter;
 
 	if (shmobile_cpuidle_setup)
-		shmobile_cpuidle_setup(dev);
+		shmobile_cpuidle_setup(drv);
 
+	cpuidle_register_driver(drv);
+
+	dev->state_count = drv->state_count;
 	cpuidle_register_device(dev);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/entry-intc.S linux-libre-3.2-gnu1/arch/arm/mach-shmobile/entry-intc.S
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/entry-intc.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/entry-intc.S	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,4 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	arch_irq_handler shmobile_handle_irq_intc
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/common.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/common.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,9 @@ extern int clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern void shmobile_handle_irq_gic(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_device;
+struct cpuidle_driver;
 extern void (*shmobile_cpuidle_modes[])(void);
-extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);
@@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(
 extern void sh7372_clock_init(void);
 extern void sh7372_pinmux_init(void);
 extern void sh7372_pm_init(void);
-extern void sh7372_cpu_suspend(void);
-extern void sh7372_cpu_resume(void);
+extern void sh7372_resume_core_standby_a3sm(void);
+extern int sh7372_do_idle_a3sm(unsigned long unused);
 extern struct clk sh7372_extal1_clk;
 extern struct clk sh7372_extal2_clk;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,5 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,31 +18,15 @@
 
 #ifdef CONFIG_GPIOLIB
 
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned int irq)
 {
 	return -ENOSYS;
 }
 
+#else
+
+#define __ARM_GPIOLIB_COMPLEX
+
 #endif /* CONFIG_GPIOLIB */
 
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/intc.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/intc.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/intc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/intc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,246 @@
+#ifndef __ASM_MACH_INTC_H
+#define __ASM_MACH_INTC_H
+#include <linux/sh_intc.h>
+
+#define INTC_IRQ_PINS_ENUM_16L(p)				\
+	p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7,		\
+	p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,	\
+	p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
+
+#define INTC_IRQ_PINS_ENUM_16H(p)				\
+	p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,	\
+	p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23,	\
+	p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,	\
+	p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
+
+#define INTC_IRQ_PINS_VECT_16L(p, vect)				\
+	vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220),	\
+	vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260),	\
+	vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0),	\
+	vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0),	\
+	vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320),	\
+	vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360),	\
+	vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0),	\
+	vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
+
+#define INTC_IRQ_PINS_VECT_16H(p, vect)				\
+	vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220),	\
+	vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260),	\
+	vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0),	\
+	vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0),	\
+	vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320),	\
+	vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360),	\
+	vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0),	\
+	vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
+
+#define INTC_IRQ_PINS_MASK_16L(p, base)					\
+	{ base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */	\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */	\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_MASK_16H(p, base)					\
+	{ base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */	\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */	\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_PRIO_16L(p, base)					\
+	{ base + 0x10, 0, 32, 4, /* INTPRI00A */			\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x14, 0, 32, 4, /* INTPRI10A */			\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_PRIO_16H(p, base)					\
+	{ base + 0x18, 0, 32, 4, /* INTPRI20A */			\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x1c, 0, 32, 4, /* INTPRI30A */			\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_SENSE_16L(p, base)				\
+	{ base + 0x00, 32, 4, /* ICR1A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x04, 32, 4, /* ICR2A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_SENSE_16H(p, base)				\
+	{ base + 0x08, 32, 4, /* ICR3A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x0c, 32, 4, /* ICR4A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_ACK_16L(p, base)					\
+	{ base + 0x20, 0, 8, /* INTREQ00A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x24, 0, 8, /* INTREQ10A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_ACK_16H(p, base)					\
+	{ base + 0x28, 0, 8, /* INTREQ20A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x2c, 0, 8, /* INTREQ30A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_16(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x64,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_32(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x6c,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+	INTC_IRQ_PINS_ENUM_16H(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+	INTC_IRQ_PINS_VECT_16H(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+	INTC_IRQ_PINS_MASK_16H(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+	INTC_IRQ_PINS_PRIO_16H(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+	INTC_IRQ_PINS_SENSE_16H(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+	INTC_IRQ_PINS_ACK_16H(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_PINT_E_EMPTY
+#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
+#define INTC_PINT_E(p)							\
+	PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3,	\
+	PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
+
+#define INTC_PINT_V_NONE
+#define INTC_PINT_V(p, vect)					\
+	vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1),	\
+	vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3),	\
+	vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5),	\
+	vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
+
+#define INTC_PINT(p, mask_reg, sense_base, str,				\
+	enums_1, enums_2, enums_3, enums_4,				\
+	vect_1, vect_2, vect_3, vect_4,					\
+	mask_a, mask_b, mask_c, mask_d,					\
+	sense_a, sense_b, sense_c, sense_d)				\
+									\
+enum {									\
+	PINT ## p ## _UNUSED = 0,					\
+	enums_1 enums_2 enums_3 enums_4 				\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	vect_1 vect_2 vect_3 vect_4					\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	{ mask_reg, 0, 32, /* PINTER */					\
+	  { mask_a mask_b mask_c mask_d } }				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	{ sense_base + 0x00, 16, 2, /* PINTCR */			\
+	  { sense_a } },						\
+	{ sense_base + 0x04, 16, 2, /* PINTCR */			\
+	  { sense_b } },						\
+	{ sense_base + 0x08, 16, 2, /* PINTCR */			\
+	  { sense_c } },						\
+	{ sense_base + 0x0c, 16, 2, /* PINTCR */			\
+	  { sense_d } },						\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, NULL,		\
+			     p ## _sense_registers, NULL),		\
+}
+
+#endif  /* __ASM_MACH_INTC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,4 @@
 #define PLAT_PHYS_OFFSET	UL(CONFIG_MEMORY_START)
 #define MEM_SIZE	UL(CONFIG_MEMORY_SIZE)
 
-/* DMA memory at 0xf6000000 - 0xffdfffff */
-#define CONSISTENT_DMA_SIZE (158 << 20)
-
 #endif /* __ASM_MACH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h	2012-01-04 18:55:44.000000000 -0500
@@ -479,7 +479,12 @@ struct platform_device;
 
 struct sh7372_pm_domain {
 	struct generic_pm_domain genpd;
+	struct dev_power_governor *gov;
+	void (*suspend)(void);
+	void (*resume)(void);
 	unsigned int bit_shift;
+	bool no_debug;
+	bool stay_on;
 };
 
 static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
@@ -491,16 +496,24 @@ static inline struct sh7372_pm_domain *t
 extern struct sh7372_pm_domain sh7372_a4lc;
 extern struct sh7372_pm_domain sh7372_a4mp;
 extern struct sh7372_pm_domain sh7372_d4;
+extern struct sh7372_pm_domain sh7372_a4r;
 extern struct sh7372_pm_domain sh7372_a3rv;
 extern struct sh7372_pm_domain sh7372_a3ri;
+extern struct sh7372_pm_domain sh7372_a3sp;
 extern struct sh7372_pm_domain sh7372_a3sg;
 
 extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
 extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
 					struct platform_device *pdev);
+extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+				    struct sh7372_pm_domain *sh7372_sd);
 #else
 #define sh7372_init_pm_domain(pd) do { } while(0)
 #define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
+#define sh7372_pm_add_subdomain(pd, sd) do { } while(0)
 #endif /* CONFIG_PM */
 
+extern void sh7372_intcs_suspend(void);
+extern void sh7372_intcs_resume(void);
+
 #endif /* __ASM_SH7372_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h	2012-01-04 18:55:44.000000000 -0500
@@ -451,18 +451,39 @@ enum {
 	GPIO_FN_KEYIN5_PU,
 	GPIO_FN_KEYIN6_PU,
 	GPIO_FN_KEYIN7_PU,
+	GPIO_FN_SDHICD0_PU,
+	GPIO_FN_SDHID0_0_PU,
+	GPIO_FN_SDHID0_1_PU,
+	GPIO_FN_SDHID0_2_PU,
+	GPIO_FN_SDHID0_3_PU,
+	GPIO_FN_SDHICMD0_PU,
+	GPIO_FN_SDHIWP0_PU,
 	GPIO_FN_SDHID1_0_PU,
 	GPIO_FN_SDHID1_1_PU,
 	GPIO_FN_SDHID1_2_PU,
 	GPIO_FN_SDHID1_3_PU,
 	GPIO_FN_SDHICMD1_PU,
+	GPIO_FN_SDHID2_0_PU,
+	GPIO_FN_SDHID2_1_PU,
+	GPIO_FN_SDHID2_2_PU,
+	GPIO_FN_SDHID2_3_PU,
+	GPIO_FN_SDHICMD2_PU,
 	GPIO_FN_MMCCMD0_PU,
 	GPIO_FN_MMCCMD1_PU,
+	GPIO_FN_MMCD0_0_PU,
+	GPIO_FN_MMCD0_1_PU,
+	GPIO_FN_MMCD0_2_PU,
+	GPIO_FN_MMCD0_3_PU,
+	GPIO_FN_MMCD0_4_PU,
+	GPIO_FN_MMCD0_5_PU,
+	GPIO_FN_MMCD0_6_PU,
+	GPIO_FN_MMCD0_7_PU,
 	GPIO_FN_FSIACK_PU,
 	GPIO_FN_FSIAILR_PU,
 	GPIO_FN_FSIAIBT_PU,
 	GPIO_FN_FSIAISLD_PU,
 };
+
 /* DMA slave IDs */
 enum {
 	SHDMA_SLAVE_INVALID,
@@ -494,4 +515,8 @@ enum {
 	SHDMA_SLAVE_MMCIF_RX,
 };
 
+/* PINT interrupts are located at Linux IRQ 768 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 768)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 800)
+
 #endif /* __ASM_SH73A0_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7367.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7367.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7367.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7367.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -31,8 +32,6 @@ enum {
 	DISABLED,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
 	DIRC,
 	CRYPT1_ERR, CRYPT2_STD,
 	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
@@ -76,14 +75,6 @@ enum {
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(CRYPT1_ERR, 0x05e0),
 	INTC_VECT(CRYPT2_STD, 0x0700),
@@ -163,10 +154,6 @@ static struct intc_group intca_groups[]
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    ARM11_IRQPMU, 0, ARM11_COMMTX, ARM11_COMMRX } },
@@ -212,11 +199,6 @@ static struct intc_mask_reg intca_mask_r
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, ETM11, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { CRYPT1_ERR, CRYPT2_STD,
@@ -240,29 +222,18 @@ static struct intc_prio_reg intca_prio_r
 	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 16, 2, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 16, 2, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-};
-
 static struct intc_desc intca_desc __initdata = {
 	.name = "sh7367-intca",
 	.force_enable = ENABLED,
 	.force_disable = DISABLED,
 	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
 			   intca_mask_registers, intca_prio_registers,
-			   intca_sense_registers, intca_ack_registers),
+			   NULL, NULL),
 };
 
+INTC_IRQ_PINS_16(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7367-intca-irq-pins");
+
 enum {
 	UNUSED_INTCS = 0,
 
@@ -432,6 +403,7 @@ void __init sh7367_init_irq(void)
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7372.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7372.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -29,10 +30,6 @@ enum {
 	UNUSED_INTCA = 0,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
-	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
-	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
 	DIRC,
 	CRYPT_STD,
 	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
@@ -86,22 +83,6 @@ enum {
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
-	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
-	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
-	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ21A, 0x32a0),
-	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
-	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
-	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
-	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
-	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(CRYPT_STD, 0x0700),
 	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
@@ -203,15 +184,6 @@ static struct intc_group intca_groups[]
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
@@ -282,15 +254,6 @@ static struct intc_mask_reg intca_mask_r
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900018, 0, 32, 4, /* INTPRI20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, 0 } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { 0, CRYPT_STD,
@@ -336,33 +299,13 @@ static struct intc_prio_reg intca_prio_r
 	{ 0xe6950050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 32, 4, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 32, 4, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900008, 32, 4, /* ICR3A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690000c, 32, 4, /* ICR4A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900028, 0, 8, /* INTREQ20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690002c, 0, 8, /* INTREQ30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static DECLARE_INTC_DESC_ACK(intca_desc, "sh7372-intca",
-			     intca_vectors, intca_groups,
-			     intca_mask_registers, intca_prio_registers,
-			     intca_sense_registers, intca_ack_registers);
+static DECLARE_INTC_DESC(intca_desc, "sh7372-intca",
+			 intca_vectors, intca_groups,
+			 intca_mask_registers, intca_prio_registers,
+			 NULL);
 
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7372-intca-irq-pins");
 enum {
 	UNUSED_INTCS = 0,
 	ENABLED_INTCS,
@@ -606,14 +549,65 @@ static void intcs_demux(unsigned int irq
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
 }
 
+static void __iomem *intcs_ffd2;
+static void __iomem *intcs_ffd5;
+
 void __init sh7372_init_irq(void)
 {
-	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	void __iomem *intevtsa;
+
+	intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
+	intevtsa = intcs_ffd2 + 0x100;
+	intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
 	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
 	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
+
+static unsigned short ffd2[0x200];
+static unsigned short ffd5[0x100];
+
+void sh7372_intcs_suspend(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		ffd2[k] = __raw_readw(intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		ffd5[k] = __raw_readw(intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		ffd5[k] = __raw_readb(intcs_ffd5 + k);
+}
+
+void sh7372_intcs_resume(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		__raw_writew(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		__raw_writew(ffd5[k], intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		__raw_writeb(ffd5[k], intcs_ffd5 + k);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7377.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7377.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh7377.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh7377.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -31,10 +32,6 @@ enum {
 	DISABLED,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
-	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
-	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
 	DIRC,
 	_2DG,
 	CRYPT_STD,
@@ -91,22 +88,6 @@ enum {
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
-	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
-	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
-	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ31A, 0x32a0),
-	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
-	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
-	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
-	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
-	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(_2DG, 0x05e0),
 	INTC_VECT(CRYPT_STD, 0x0700),
@@ -203,15 +184,6 @@ static struct intc_group intca_groups[]
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
@@ -273,15 +245,6 @@ static struct intc_mask_reg intca_mask_r
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900018, 0, 32, 4, /* INTPRI10A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { _2DG, CRYPT_STD,
@@ -315,37 +278,18 @@ static struct intc_prio_reg intca_prio_r
 	{ 0xe694003c, 0, 16, 4, /* IPRPA3 */ { SCIFA6, 0, 0, 0 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 16, 2, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 16, 2, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900008, 16, 2, /* ICR3A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690000c, 16, 2, /* ICR4A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900028, 0, 8, /* INTREQ20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690002c, 0, 8, /* INTREQ30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
 static struct intc_desc intca_desc __initdata = {
 	.name = "sh7377-intca",
 	.force_enable = ENABLED,
 	.force_disable = DISABLED,
 	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
 			   intca_mask_registers, intca_prio_registers,
-			   intca_sense_registers, intca_ack_registers),
+			   NULL, NULL),
 };
 
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7377-intca-irq-pins");
+
 /* this macro ignore entry which is also in INTCA */
 #define __IGNORE(a...)
 #define __IGNORE0(a...) 0
@@ -638,6 +582,7 @@ void __init sh7377_init_irq(void)
 	void __iomem *intevtsa = ioremap_nocache(INTEVTSA, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
+#include <mach/sh73a0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -255,20 +257,205 @@ static int sh73a0_set_wake(struct irq_da
 	return 0; /* always allow wakeup */
 }
 
+#define RELOC_BASE 0x1000
+
+/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
+
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
+
+static int to_gic_irq(struct irq_data *data)
+{
+	unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
+
+	if (vect >= 0x3200)
+		vect -= 0x3000;
+	else
+		vect -= 0x0200;
+
+	return gic_spi((vect >> 5) + 1);
+}
+
+static int to_intca_reloc_irq(struct irq_data *data)
+{
+	return data->irq + (RELOC_BASE >> 5);
+}
+
+#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
+#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
+
+static void intca_gic_enable(struct irq_data *data)
+{
+	irq_cb(irq_unmask, to_intca_reloc_irq(data));
+	irq_cb(irq_unmask, to_gic_irq(data));
+}
+
+static void intca_gic_disable(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_mask_ack(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_eoi(struct irq_data *data)
+{
+	irq_cb(irq_eoi, to_gic_irq(data));
+}
+
+static int intca_gic_set_type(struct irq_data *data, unsigned int type)
+{
+	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
+}
+
+static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
+{
+	return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
+}
+
+#ifdef CONFIG_SMP
+static int intca_gic_set_affinity(struct irq_data *data,
+				  const struct cpumask *cpumask,
+				  bool force)
+{
+	return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
+}
+#endif
+
+struct irq_chip intca_gic_irq_chip = {
+	.name			= "INTCA-GIC",
+	.irq_mask		= intca_gic_disable,
+	.irq_unmask		= intca_gic_enable,
+	.irq_mask_ack		= intca_gic_mask_ack,
+	.irq_eoi		= intca_gic_eoi,
+	.irq_enable		= intca_gic_enable,
+	.irq_disable		= intca_gic_disable,
+	.irq_shutdown		= intca_gic_disable,
+	.irq_set_type		= intca_gic_set_type,
+	.irq_set_wake		= intca_gic_set_wake,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= intca_gic_set_affinity,
+#endif
+};
+
+static int to_intc_vect(int irq)
+{
+	unsigned int irq_pin = irq - gic_spi(1);
+	unsigned int offs;
+
+	if (irq_pin < 16)
+		offs = 0x0200;
+	else
+		offs = 0x3000;
+
+	return offs + (irq_pin << 5);
+}
+
+static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
+{
+	generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sh73a0_irq_pin_cascade[32];
+
+#define PINTER0 0xe69000a0
+#define PINTER1 0xe69000a4
+#define PINTRR0 0xe69000d0
+#define PINTRR1 0xe69000d4
+
+#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq))
+#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8))
+#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16))
+#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24))
+#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq))
+
+INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0",		\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
+  INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ),		\
+  INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ),		\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D));
+
+INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1",		\
+  INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \
+  INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE,				\
+  INTC_PINT_V_NONE, INTC_PINT_V_NONE,					\
+  INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \
+  INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE);
+
+static struct irqaction sh73a0_pint0_cascade;
+static struct irqaction sh73a0_pint1_cascade;
+
+static void pint_demux(unsigned long rr, unsigned long er, int base_irq)
+{
+	unsigned long value =  ioread32(rr) & ioread32(er);
+	int k;
+
+	for (k = 0; k < 32; k++) {
+		if (value & (1 << (31 - k))) {
+			generic_handle_irq(base_irq + k);
+			iowrite32(~(1 << (31 - k)), rr);
+		}
+	}
+}
+
+static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id)
+{
+	pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
+{
+	pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0));
+	return IRQ_HANDLED;
+}
+
 void __init sh73a0_init_irq(void)
 {
 	void __iomem *gic_dist_base = __io(0xf0001000);
 	void __iomem *gic_cpu_base = __io(0xf0000100);
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	int k, n;
 
 	gic_init(0, 29, gic_dist_base, gic_cpu_base);
 	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
 	register_intc_controller(&intcs_desc);
+	register_intc_controller(&intca_irq_pins_desc);
+	register_intc_controller(&intc_pint0_desc);
+	register_intc_controller(&intc_pint1_desc);
 
 	/* demux using INTEVTSA */
 	sh73a0_intcs_cascade.name = "INTCS cascade";
 	sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
 	sh73a0_intcs_cascade.dev_id = intevtsa;
 	setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
+
+	/* IRQ pins require special handling through INTCA and GIC */
+	for (k = 0; k < 32; k++) {
+		sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
+		sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
+		setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
+
+		n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
+		irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
+					      handle_level_irq, "level");
+		set_irq_flags(n, IRQF_VALID); /* yuck */
+	}
+
+	/* PINT pins are sanely tied to the GIC as SPI */
+	sh73a0_pint0_cascade.name = "PINT0 cascade";
+	sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
+	setup_irq(gic_spi(33), &sh73a0_pint0_cascade);
+
+	sh73a0_pint1_cascade.name = "PINT1 cascade";
+	sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
+	setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@ config ARCH_SH73A0
 	select SH_CLK_CPG
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_GIC
+	select I2C
 
 comment "SH-Mobile Board Type"
 
@@ -69,6 +70,11 @@ config MACH_MACKEREL
 	depends on ARCH_SH7372
 	select ARCH_REQUIRE_GPIOLIB
 
+config MACH_KOTA2
+	bool "KOTA2 board"
+	select ARCH_REQUIRE_GPIOLIB
+	depends on ARCH_SH73A0
+
 comment "SH-Mobile System Configuration"
 
 menu "Memory configuration"
@@ -78,6 +84,7 @@ config MEMORY_START
 	default "0x50000000" if MACH_G3EVM
 	default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
 				MACH_MACKEREL
+	default "0x41000000" if MACH_KOTA2
 	default "0x00000000"
 	---help---
 	  Tweak this only when porting to a new machine which does not
@@ -89,6 +96,7 @@ config MEMORY_SIZE
 	default "0x08000000" if MACH_G3EVM
 	default "0x08000000" if MACH_G4EVM
 	default "0x20000000" if MACH_AG5EVM
+	default "0x1e000000" if MACH_KOTA2
 	default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
 	default "0x04000000"
 	help
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Makefile linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y				:= timer.o console.o clock.o pm_runtime.o
+obj-y				:= timer.o console.o clock.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
@@ -41,6 +41,7 @@ obj-$(CONFIG_MACH_G4EVM)	+= board-g4evm.
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
 obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
+obj-$(CONFIG_MACH_KOTA2)	+= board-kota2.o
 
 # Framework support
 obj-$(CONFIG_SMP)		+= $(smp-y)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 __ZRELADDR	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_MEMORY_START) + 0x8000]')
 
-   zreladdr-y   := $(__ZRELADDR)
+   zreladdr-y   += $(__ZRELADDR)
 
 # Unsupported legacy stuff
 #
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7367.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7367.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7367.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7367.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,68 +21,49 @@
 #include <linux/gpio.h>
 #include <mach/sh7367.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
-	_10(fn, pfx##9, sfx)
-
-#define _273(fn, pfx, sfx)		\
-	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
-	_10(fn, pfx##10, sfx), _90(fn, pfx##1, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_10(fn, pfx##26, sfx), _1(fn, pfx##270, sfx),	\
-	_1(fn, pfx##271, sfx), _1(fn, pfx##272, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_273(str) _273(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
+	PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_10(fn, pfx##26, sfx), PORT_1(fn, pfx##270, sfx),	\
+	PORT_1(fn, pfx##271, sfx), PORT_1(fn, pfx##272, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_273(DATA), /* PORT0_DATA -> PORT272_DATA */
+	PORT_ALL(DATA), /* PORT0_DATA -> PORT272_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_273(IN), /* PORT0_IN -> PORT272_IN */
+	PORT_ALL(IN), /* PORT0_IN -> PORT272_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_273(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
+	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_273(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
+	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_273(OUT), /* PORT0_OUT -> PORT272_OUT */
+	PORT_ALL(OUT), /* PORT0_OUT -> PORT272_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_273(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
-	PORT_273(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
-	PORT_273(FN0), /* PORT0_FN0 -> PORT272_FN0 */
-	PORT_273(FN1), /* PORT0_FN1 -> PORT272_FN1 */
-	PORT_273(FN2), /* PORT0_FN2 -> PORT272_FN2 */
-	PORT_273(FN3), /* PORT0_FN3 -> PORT272_FN3 */
-	PORT_273(FN4), /* PORT0_FN4 -> PORT272_FN4 */
-	PORT_273(FN5), /* PORT0_FN5 -> PORT272_FN5 */
-	PORT_273(FN6), /* PORT0_FN6 -> PORT272_FN6 */
-	PORT_273(FN7), /* PORT0_FN7 -> PORT272_FN7 */
+	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
+	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
+	PORT_ALL(FN0), /* PORT0_FN0 -> PORT272_FN0 */
+	PORT_ALL(FN1), /* PORT0_FN1 -> PORT272_FN1 */
+	PORT_ALL(FN2), /* PORT0_FN2 -> PORT272_FN2 */
+	PORT_ALL(FN3), /* PORT0_FN3 -> PORT272_FN3 */
+	PORT_ALL(FN4), /* PORT0_FN4 -> PORT272_FN4 */
+	PORT_ALL(FN5), /* PORT0_FN5 -> PORT272_FN5 */
+	PORT_ALL(FN6), /* PORT0_FN6 -> PORT272_FN6 */
+	PORT_ALL(FN7), /* PORT0_FN7 -> PORT272_FN7 */
 
 	MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
 	PINMUX_FUNCTION_END,
@@ -327,41 +308,6 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
 	/* specify valid pin states for each pin in GPIO mode */
@@ -1098,13 +1044,9 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_273() _273(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 	/* 49-1 -> 49-6 (GPIO) */
-	GPIO_PORT_273(),
+	GPIO_PORT_ALL(),
 
 	/* Special Pull-up / Pull-down Functions */
 	GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
@@ -1345,22 +1287,6 @@ static struct pinmux_gpio pinmux_gpios[]
 	GPIO_FN(DIVLOCK),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)		\
-	0, (out), (in), 0,			\
-	0, 0, 0, 0,				\
-	0, 0, (in_pd), 0,			\
-	0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)						\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
-		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
-		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
-		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
-		PORT##nr##_FN6, PORT##nr##_FN7 }		\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7372.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7372.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,27 +25,13 @@
 #include <linux/gpio.h>
 #include <mach/sh7372.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _80(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx),	_10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx),	_10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx),	_10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx),	_10(fn, pfx##8, sfx)
-
-#define _190(fn, pfx, sfx) \
-	_10(fn, pfx, sfx), _80(fn, pfx, sfx), _10(fn, pfx##9, sfx), \
-	_10(fn, pfx##10, sfx), _80(fn, pfx##1, sfx), _1(fn, pfx##190, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_ALL(str) _190(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+	PORT_10(fn, pfx, sfx),		PORT_90(fn, pfx, sfx), \
+	PORT_10(fn, pfx##10, sfx),	PORT_10(fn, pfx##11, sfx), \
+	PORT_10(fn, pfx##12, sfx),	PORT_10(fn, pfx##13, sfx), \
+	PORT_10(fn, pfx##14, sfx),	PORT_10(fn, pfx##15, sfx), \
+	PORT_10(fn, pfx##16, sfx),	PORT_10(fn, pfx##17, sfx), \
+	PORT_10(fn, pfx##18, sfx),	PORT_1(fn, pfx##190, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
@@ -381,108 +367,124 @@ enum {
 	PINMUX_MARK_END,
 };
 
-/* PORT_DATA_I_PD(nr) */
-#define _I___D(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_I_PU(nr) */
-#define _I__U_(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_I_PU_PD(nr) */
-#define _I__UD(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-/* PORT_DATA_O(nr) */
-#define __O___(nr)							\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-/* PORT_DATA_IO(nr) */
-#define _IO___(nr)				     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN)
-
-/* PORT_DATA_IO_PD(nr) */
-#define _IO__D(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_IO_PU(nr) */
-#define _IO_U_(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_IO_PU_PD(nr) */
-#define _IO_UD(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
 	/* specify valid pin states for each pin in GPIO mode */
+	PORT_DATA_IO_PD(0),		PORT_DATA_IO_PD(1),
+	PORT_DATA_O(2),			PORT_DATA_I_PD(3),
+	PORT_DATA_I_PD(4),		PORT_DATA_I_PD(5),
+	PORT_DATA_IO_PU_PD(6),		PORT_DATA_I_PD(7),
+	PORT_DATA_IO_PD(8),		PORT_DATA_O(9),
 
-	_IO__D(0), _IO__D(1), __O___(2), _I___D(3), _I___D(4),
-	_I___D(5), _IO_UD(6), _I___D(7), _IO__D(8), __O___(9),
-
-	__O___(10), __O___(11), _IO_UD(12), _IO__D(13), _IO__D(14),
-	__O___(15), _IO__D(16), _IO__D(17), _I___D(18), _IO___(19),
+	PORT_DATA_O(10),		PORT_DATA_O(11),
+	PORT_DATA_IO_PU_PD(12),		PORT_DATA_IO_PD(13),
+	PORT_DATA_IO_PD(14),		PORT_DATA_O(15),
+	PORT_DATA_IO_PD(16),		PORT_DATA_IO_PD(17),
+	PORT_DATA_I_PD(18),		PORT_DATA_IO(19),
 
-	_IO___(20), _IO___(21), _IO___(22), _IO___(23), _IO___(24),
-	_IO___(25), _IO___(26), _IO___(27), _IO___(28), _IO___(29),
+	PORT_DATA_IO(20),		PORT_DATA_IO(21),
+	PORT_DATA_IO(22),		PORT_DATA_IO(23),
+	PORT_DATA_IO(24),		PORT_DATA_IO(25),
+	PORT_DATA_IO(26),		PORT_DATA_IO(27),
+	PORT_DATA_IO(28),		PORT_DATA_IO(29),
 
-	_IO___(30), _IO___(31), _IO___(32), _IO___(33), _IO___(34),
-	_IO___(35), _IO___(36), _IO___(37), _IO___(38), _IO___(39),
+	PORT_DATA_IO(30),		PORT_DATA_IO(31),
+	PORT_DATA_IO(32),		PORT_DATA_IO(33),
+	PORT_DATA_IO(34),		PORT_DATA_IO(35),
+	PORT_DATA_IO(36),		PORT_DATA_IO(37),
+	PORT_DATA_IO(38),		PORT_DATA_IO(39),
 
-	_IO___(40), _IO___(41), _IO___(42), _IO___(43), _IO___(44),
-	_IO___(45), _IO_U_(46), _IO_U_(47), _IO_U_(48), _IO_U_(49),
+	PORT_DATA_IO(40),		PORT_DATA_IO(41),
+	PORT_DATA_IO(42),		PORT_DATA_IO(43),
+	PORT_DATA_IO(44),		PORT_DATA_IO(45),
+	PORT_DATA_IO_PU(46),		PORT_DATA_IO_PU(47),
+	PORT_DATA_IO_PU(48),		PORT_DATA_IO_PU(49),
 
-	_IO_U_(50), _IO_U_(51), _IO_U_(52), _IO_U_(53), _IO_U_(54),
-	_IO_U_(55), _IO_U_(56), _IO_U_(57), _IO_U_(58), _IO_U_(59),
+	PORT_DATA_IO_PU(50),		PORT_DATA_IO_PU(51),
+	PORT_DATA_IO_PU(52),		PORT_DATA_IO_PU(53),
+	PORT_DATA_IO_PU(54),		PORT_DATA_IO_PU(55),
+	PORT_DATA_IO_PU(56),		PORT_DATA_IO_PU(57),
+	PORT_DATA_IO_PU(58),		PORT_DATA_IO_PU(59),
 
-	_IO_U_(60), _IO_U_(61), _IO___(62), __O___(63), __O___(64),
-	_IO_U_(65), __O___(66), _IO_U_(67), __O___(68), _IO___(69), /*66?*/
+	PORT_DATA_IO_PU(60),		PORT_DATA_IO_PU(61),
+	PORT_DATA_IO(62),		PORT_DATA_O(63),
+	PORT_DATA_O(64),		PORT_DATA_IO_PU(65),
+	PORT_DATA_O(66),		PORT_DATA_IO_PU(67),  /*66?*/
+	PORT_DATA_O(68),		PORT_DATA_IO(69),
 
-	_IO___(70), _IO___(71), __O___(72), _I__U_(73), _I__UD(74),
-	_IO_UD(75), _IO_UD(76), _IO_UD(77), _IO_UD(78), _IO_UD(79),
+	PORT_DATA_IO(70),		PORT_DATA_IO(71),
+	PORT_DATA_O(72),		PORT_DATA_I_PU(73),
+	PORT_DATA_I_PU_PD(74),		PORT_DATA_IO_PU_PD(75),
+	PORT_DATA_IO_PU_PD(76),		PORT_DATA_IO_PU_PD(77),
+	PORT_DATA_IO_PU_PD(78),		PORT_DATA_IO_PU_PD(79),
 
-	_IO_UD(80), _IO_UD(81), _IO_UD(82), _IO_UD(83), _IO_UD(84),
-	_IO_UD(85), _IO_UD(86), _IO_UD(87), _IO_UD(88), _IO_UD(89),
+	PORT_DATA_IO_PU_PD(80),		PORT_DATA_IO_PU_PD(81),
+	PORT_DATA_IO_PU_PD(82),		PORT_DATA_IO_PU_PD(83),
+	PORT_DATA_IO_PU_PD(84),		PORT_DATA_IO_PU_PD(85),
+	PORT_DATA_IO_PU_PD(86),		PORT_DATA_IO_PU_PD(87),
+	PORT_DATA_IO_PU_PD(88),		PORT_DATA_IO_PU_PD(89),
 
-	_IO_UD(90), _IO_UD(91), _IO_UD(92), _IO_UD(93), _IO_UD(94),
-	_IO_UD(95), _IO_U_(96), _IO_UD(97), _IO_UD(98), __O___(99), /*99?*/
+	PORT_DATA_IO_PU_PD(90),		PORT_DATA_IO_PU_PD(91),
+	PORT_DATA_IO_PU_PD(92),		PORT_DATA_IO_PU_PD(93),
+	PORT_DATA_IO_PU_PD(94),		PORT_DATA_IO_PU_PD(95),
+	PORT_DATA_IO_PU(96),		PORT_DATA_IO_PU_PD(97),
+	PORT_DATA_IO_PU_PD(98),		PORT_DATA_O(99), /*99?*/
 
-	_IO__D(100), _IO__D(101), _IO__D(102), _IO__D(103), _IO__D(104),
-	_IO__D(105), _IO_U_(106), _IO_U_(107), _IO_U_(108), _IO_U_(109),
+	PORT_DATA_IO_PD(100),		PORT_DATA_IO_PD(101),
+	PORT_DATA_IO_PD(102),		PORT_DATA_IO_PD(103),
+	PORT_DATA_IO_PD(104),		PORT_DATA_IO_PD(105),
+	PORT_DATA_IO_PU(106),		PORT_DATA_IO_PU(107),
+	PORT_DATA_IO_PU(108),		PORT_DATA_IO_PU(109),
 
-	_IO_U_(110), _IO_U_(111), _IO__D(112), _IO__D(113), _IO_U_(114),
-	_IO_U_(115), _IO_U_(116), _IO_U_(117), _IO_U_(118), _IO_U_(119),
+	PORT_DATA_IO_PU(110),		PORT_DATA_IO_PU(111),
+	PORT_DATA_IO_PD(112),		PORT_DATA_IO_PD(113),
+	PORT_DATA_IO_PU(114),		PORT_DATA_IO_PU(115),
+	PORT_DATA_IO_PU(116),		PORT_DATA_IO_PU(117),
+	PORT_DATA_IO_PU(118),		PORT_DATA_IO_PU(119),
 
-	_IO_U_(120), _IO__D(121), _IO__D(122), _IO__D(123), _IO__D(124),
-	_IO__D(125), _IO__D(126), _IO__D(127), _IO__D(128), _IO_UD(129),
+	PORT_DATA_IO_PU(120),		PORT_DATA_IO_PD(121),
+	PORT_DATA_IO_PD(122),		PORT_DATA_IO_PD(123),
+	PORT_DATA_IO_PD(124),		PORT_DATA_IO_PD(125),
+	PORT_DATA_IO_PD(126),		PORT_DATA_IO_PD(127),
+	PORT_DATA_IO_PD(128),		PORT_DATA_IO_PU_PD(129),
 
-	_IO_UD(130), _IO_UD(131), _IO_UD(132), _IO_UD(133), _IO_UD(134),
-	_IO_UD(135), _IO__D(136), _IO__D(137), _IO__D(138), _IO__D(139),
+	PORT_DATA_IO_PU_PD(130),	PORT_DATA_IO_PU_PD(131),
+	PORT_DATA_IO_PU_PD(132),	PORT_DATA_IO_PU_PD(133),
+	PORT_DATA_IO_PU_PD(134),	PORT_DATA_IO_PU_PD(135),
+	PORT_DATA_IO_PD(136),		PORT_DATA_IO_PD(137),
+	PORT_DATA_IO_PD(138),		PORT_DATA_IO_PD(139),
 
-	_IO__D(140), _IO__D(141), _IO__D(142), _IO_UD(143), _IO__D(144),
-	_IO__D(145), _IO__D(146), _IO__D(147), _IO__D(148), _IO__D(149),
+	PORT_DATA_IO_PD(140),		PORT_DATA_IO_PD(141),
+	PORT_DATA_IO_PD(142),		PORT_DATA_IO_PU_PD(143),
+	PORT_DATA_IO_PD(144),		PORT_DATA_IO_PD(145),
+	PORT_DATA_IO_PD(146),		PORT_DATA_IO_PD(147),
+	PORT_DATA_IO_PD(148),		PORT_DATA_IO_PD(149),
 
-	_IO__D(150), _IO__D(151), _IO_UD(152), _I___D(153), _IO_UD(154),
-	_I___D(155), _IO__D(156), _IO__D(157), _I___D(158), _IO__D(159),
+	PORT_DATA_IO_PD(150),		PORT_DATA_IO_PD(151),
+	PORT_DATA_IO_PU_PD(152),	PORT_DATA_I_PD(153),
+	PORT_DATA_IO_PU_PD(154),	PORT_DATA_I_PD(155),
+	PORT_DATA_IO_PD(156),		PORT_DATA_IO_PD(157),
+	PORT_DATA_I_PD(158),		PORT_DATA_IO_PD(159),
 
-	__O___(160), _IO__D(161), _IO__D(162), _IO__D(163), _I___D(164),
-	_IO__D(165), _I___D(166), _I___D(167), _I___D(168), _I___D(169),
+	PORT_DATA_O(160),		PORT_DATA_IO_PD(161),
+	PORT_DATA_IO_PD(162),		PORT_DATA_IO_PD(163),
+	PORT_DATA_I_PD(164),		PORT_DATA_IO_PD(165),
+	PORT_DATA_I_PD(166),		PORT_DATA_I_PD(167),
+	PORT_DATA_I_PD(168),		PORT_DATA_I_PD(169),
 
-	_I___D(170), __O___(171), _IO_UD(172), _IO_UD(173), _IO_UD(174),
-	_IO_UD(175), _IO_UD(176), _IO_UD(177), _IO_UD(178), __O___(179),
+	PORT_DATA_I_PD(170),		PORT_DATA_O(171),
+	PORT_DATA_IO_PU_PD(172),	PORT_DATA_IO_PU_PD(173),
+	PORT_DATA_IO_PU_PD(174),	PORT_DATA_IO_PU_PD(175),
+	PORT_DATA_IO_PU_PD(176),	PORT_DATA_IO_PU_PD(177),
+	PORT_DATA_IO_PU_PD(178),	PORT_DATA_O(179),
 
-	_IO_UD(180), _IO_UD(181), _IO_UD(182), _IO_UD(183), _IO_UD(184),
-	__O___(185), _IO_UD(186), _IO_UD(187), _IO_UD(188), _IO_UD(189),
+	PORT_DATA_IO_PU_PD(180),	PORT_DATA_IO_PU_PD(181),
+	PORT_DATA_IO_PU_PD(182),	PORT_DATA_IO_PU_PD(183),
+	PORT_DATA_IO_PU_PD(184),	PORT_DATA_O(185),
+	PORT_DATA_IO_PU_PD(186),	PORT_DATA_IO_PU_PD(187),
+	PORT_DATA_IO_PU_PD(188),	PORT_DATA_IO_PU_PD(189),
 
-	_IO_UD(190),
+	PORT_DATA_IO_PU_PD(190),
 
 	/* IRQ */
 	PINMUX_DATA(IRQ0_6_MARK,	PORT6_FN0, 	MSEL1CR_0_0),
@@ -926,10 +928,6 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(MFIv4_MARK,		MSEL4CR_6_1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_ALL() _190(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 
 	/* PORT */
@@ -1201,22 +1199,6 @@ static struct pinmux_gpio pinmux_gpios[]
 	GPIO_FN(SDENC_DV_CLKI),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)		\
-	0, (out), (in), 0,			\
-	0, 0, 0, 0,				\
-	0, 0, (in_pd), 0,			\
-	0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)						\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
-		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
-		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
-		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
-		PORT##nr##_FN6, PORT##nr##_FN7 }		\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0,	0xE6051000), /* PORT0CR */
 	PORTCR(1,	0xE6051001), /* PORT1CR */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7377.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7377.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh7377.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh7377.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,84 +22,65 @@
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
-	_10(fn, pfx##9, sfx)
-
-#define _265(fn, pfx, sfx)				\
-	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
-	_10(fn, pfx##10, sfx),				\
-	_1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),	\
-	_1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),	\
-	_1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),	\
-	_1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),	\
-	_1(fn, pfx##118, sfx),				\
-	_1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),	\
-	_10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),	\
-	_10(fn, pfx##15, sfx),				\
-	_1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),	\
-	_1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),	\
-	_1(fn, pfx##164, sfx),				\
-	_1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),	\
-	_1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),	\
-	_1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),	\
-	_1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_1(fn, pfx##260, sfx), _1(fn, pfx##261, sfx),	\
-	_1(fn, pfx##262, sfx), _1(fn, pfx##263, sfx),	\
-	_1(fn, pfx##264, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_265(str) _265(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
+	PORT_10(fn, pfx##10, sfx),				\
+	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
+	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
+	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
+	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
+	PORT_1(fn, pfx##118, sfx),				\
+	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
+	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
+	PORT_10(fn, pfx##15, sfx),				\
+	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
+	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
+	PORT_1(fn, pfx##164, sfx),				\
+	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
+	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
+	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
+	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_1(fn, pfx##260, sfx), PORT_1(fn, pfx##261, sfx),	\
+	PORT_1(fn, pfx##262, sfx), PORT_1(fn, pfx##263, sfx),	\
+	PORT_1(fn, pfx##264, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_265(DATA), /* PORT0_DATA -> PORT264_DATA */
+	PORT_ALL(DATA), /* PORT0_DATA -> PORT264_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_265(IN), /* PORT0_IN -> PORT264_IN */
+	PORT_ALL(IN), /* PORT0_IN -> PORT264_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_265(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
+	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_265(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
+	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_265(OUT), /* PORT0_OUT -> PORT264_OUT */
+	PORT_ALL(OUT), /* PORT0_OUT -> PORT264_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_265(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
-	PORT_265(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
-	PORT_265(FN0), /* PORT0_FN0 -> PORT264_FN0 */
-	PORT_265(FN1), /* PORT0_FN1 -> PORT264_FN1 */
-	PORT_265(FN2), /* PORT0_FN2 -> PORT264_FN2 */
-	PORT_265(FN3), /* PORT0_FN3 -> PORT264_FN3 */
-	PORT_265(FN4), /* PORT0_FN4 -> PORT264_FN4 */
-	PORT_265(FN5), /* PORT0_FN5 -> PORT264_FN5 */
-	PORT_265(FN6), /* PORT0_FN6 -> PORT264_FN6 */
-	PORT_265(FN7), /* PORT0_FN7 -> PORT264_FN7 */
+	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
+	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
+	PORT_ALL(FN0), /* PORT0_FN0 -> PORT264_FN0 */
+	PORT_ALL(FN1), /* PORT0_FN1 -> PORT264_FN1 */
+	PORT_ALL(FN2), /* PORT0_FN2 -> PORT264_FN2 */
+	PORT_ALL(FN3), /* PORT0_FN3 -> PORT264_FN3 */
+	PORT_ALL(FN4), /* PORT0_FN4 -> PORT264_FN4 */
+	PORT_ALL(FN5), /* PORT0_FN5 -> PORT264_FN5 */
+	PORT_ALL(FN6), /* PORT0_FN6 -> PORT264_FN6 */
+	PORT_ALL(FN7), /* PORT0_FN7 -> PORT264_FN7 */
 
 	MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
 	MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
@@ -360,45 +341,6 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 	/* 55-1 (GPIO) */
@@ -1078,13 +1020,9 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_265() _265(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 	/* 55-1 -> 55-5 (GPIO) */
-	GPIO_PORT_265(),
+	GPIO_PORT_ALL(),
 
 	/* Special Pull-up / Pull-down Functions */
 	GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
@@ -1362,23 +1300,6 @@ static struct pinmux_gpio pinmux_gpios[]
 	GPIO_FN(RESETOUTS),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)	\
-	0, (out), (in), 0,	\
-		0, 0, 0, 0,	\
-		0, 0, (in_pd), 0,	\
-		0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)	\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {	\
-			PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				 PORT##nr##_IN_PU, PORT##nr##_OUT),	\
-				PORT##nr##_FN0, PORT##nr##_FN1,	\
-				PORT##nr##_FN2, PORT##nr##_FN3,	\
-				PORT##nr##_FN4, PORT##nr##_FN5,	\
-				PORT##nr##_FN6, PORT##nr##_FN7 }	\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,84 +22,73 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <mach/sh73a0.h>
+#include <mach/irqs.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _310(fn, pfx, sfx)				\
-	_10(fn, pfx,    sfx), _10(fn, pfx##1, sfx),	\
-	_10(fn, pfx##2, sfx), _10(fn, pfx##3, sfx),	\
-	_10(fn, pfx##4, sfx), _10(fn, pfx##5, sfx),	\
-	_10(fn, pfx##6, sfx), _10(fn, pfx##7, sfx),	\
-	_10(fn, pfx##8, sfx), _10(fn, pfx##9, sfx),	\
-	_10(fn, pfx##10, sfx),				\
-	_1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),	\
-	_1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),	\
-	_1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),	\
-	_1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),	\
-	_1(fn, pfx##118, sfx),				\
-	_1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),	\
-	_10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),	\
-	_10(fn, pfx##15, sfx),				\
-	_1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),	\
-	_1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),	\
-	_1(fn, pfx##164, sfx),				\
-	_1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),	\
-	_1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),	\
-	_1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),	\
-	_1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_10(fn, pfx##26, sfx), _10(fn, pfx##27, sfx),	\
-	_1(fn, pfx##280, sfx), _1(fn, pfx##281, sfx),	\
-	_1(fn, pfx##282, sfx),				\
-	_1(fn, pfx##288, sfx), _1(fn, pfx##289, sfx),	\
-	_10(fn, pfx##29, sfx), _10(fn, pfx##30, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_310(str) _310(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx,    sfx), PORT_10(fn, pfx##1, sfx),	\
+	PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx),	\
+	PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx),	\
+	PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx),	\
+	PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx),	\
+	PORT_10(fn, pfx##10, sfx),				\
+	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
+	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
+	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
+	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
+	PORT_1(fn, pfx##118, sfx),				\
+	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
+	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
+	PORT_10(fn, pfx##15, sfx),				\
+	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
+	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
+	PORT_1(fn, pfx##164, sfx),				\
+	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
+	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
+	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
+	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx),	\
+	PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx),	\
+	PORT_1(fn, pfx##282, sfx),				\
+	PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx),	\
+	PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_310(DATA),			/* PORT0_DATA -> PORT309_DATA */
+	PORT_ALL(DATA),			/* PORT0_DATA -> PORT309_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_310(IN),			/* PORT0_IN -> PORT309_IN */
+	PORT_ALL(IN),			/* PORT0_IN -> PORT309_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_310(IN_PU),		/* PORT0_IN_PU -> PORT309_IN_PU */
+	PORT_ALL(IN_PU),		/* PORT0_IN_PU -> PORT309_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_310(IN_PD),		/* PORT0_IN_PD -> PORT309_IN_PD */
+	PORT_ALL(IN_PD),		/* PORT0_IN_PD -> PORT309_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_310(OUT),			/* PORT0_OUT -> PORT309_OUT */
+	PORT_ALL(OUT),			/* PORT0_OUT -> PORT309_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_310(FN_IN),		/* PORT0_FN_IN -> PORT309_FN_IN */
-	PORT_310(FN_OUT),		/* PORT0_FN_OUT -> PORT309_FN_OUT */
-	PORT_310(FN0),			/* PORT0_FN0 -> PORT309_FN0 */
-	PORT_310(FN1),			/* PORT0_FN1 -> PORT309_FN1 */
-	PORT_310(FN2),			/* PORT0_FN2 -> PORT309_FN2 */
-	PORT_310(FN3),			/* PORT0_FN3 -> PORT309_FN3 */
-	PORT_310(FN4),			/* PORT0_FN4 -> PORT309_FN4 */
-	PORT_310(FN5),			/* PORT0_FN5 -> PORT309_FN5 */
-	PORT_310(FN6),			/* PORT0_FN6 -> PORT309_FN6 */
-	PORT_310(FN7),			/* PORT0_FN7 -> PORT309_FN7 */
+	PORT_ALL(FN_IN),		/* PORT0_FN_IN -> PORT309_FN_IN */
+	PORT_ALL(FN_OUT),		/* PORT0_FN_OUT -> PORT309_FN_OUT */
+	PORT_ALL(FN0),			/* PORT0_FN0 -> PORT309_FN0 */
+	PORT_ALL(FN1),			/* PORT0_FN1 -> PORT309_FN1 */
+	PORT_ALL(FN2),			/* PORT0_FN2 -> PORT309_FN2 */
+	PORT_ALL(FN3),			/* PORT0_FN3 -> PORT309_FN3 */
+	PORT_ALL(FN4),			/* PORT0_FN4 -> PORT309_FN4 */
+	PORT_ALL(FN5),			/* PORT0_FN5 -> PORT309_FN5 */
+	PORT_ALL(FN6),			/* PORT0_FN6 -> PORT309_FN6 */
+	PORT_ALL(FN7),			/* PORT0_FN7 -> PORT309_FN7 */
 
 	MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
 	MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
@@ -488,13 +477,34 @@ enum {
 	KEYIN5_PU_MARK,
 	KEYIN6_PU_MARK,
 	KEYIN7_PU_MARK,
+	SDHICD0_PU_MARK,
+	SDHID0_0_PU_MARK,
+	SDHID0_1_PU_MARK,
+	SDHID0_2_PU_MARK,
+	SDHID0_3_PU_MARK,
+	SDHICMD0_PU_MARK,
+	SDHIWP0_PU_MARK,
 	SDHID1_0_PU_MARK,
 	SDHID1_1_PU_MARK,
 	SDHID1_2_PU_MARK,
 	SDHID1_3_PU_MARK,
 	SDHICMD1_PU_MARK,
+	SDHID2_0_PU_MARK,
+	SDHID2_1_PU_MARK,
+	SDHID2_2_PU_MARK,
+	SDHID2_3_PU_MARK,
+	SDHICMD2_PU_MARK,
 	MMCCMD0_PU_MARK,
 	MMCCMD1_PU_MARK,
+	MMCD0_0_PU_MARK,
+	MMCD0_1_PU_MARK,
+	MMCD0_2_PU_MARK,
+	MMCD0_3_PU_MARK,
+	MMCD0_4_PU_MARK,
+	MMCD0_5_PU_MARK,
+	MMCD0_6_PU_MARK,
+	MMCD0_7_PU_MARK,
+	FSIBISLD_PU_MARK,
 	FSIACK_PU_MARK,
 	FSIAILR_PU_MARK,
 	FSIAIBT_PU_MARK,
@@ -503,45 +513,6 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 
@@ -1387,19 +1358,28 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(TS_SCK4_MARK, PORT268_FN3),
 	PINMUX_DATA(SDHICMD2_MARK, PORT269_FN1),
 	PINMUX_DATA(MMCCLK0_MARK, PORT270_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, PORT271_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, PORT272_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, PORT273_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, PORT274_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, PORT275_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SPSYNC5_MARK, PORT275_FN3),
-	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, PORT276_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3),
-	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, PORT277_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3),
-	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, PORT278_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3),
-	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, PORT279_IN_PU,
+		MSEL4CR_MSEL15_0),
 	PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \
 	PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2),
 	PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1),
@@ -1516,28 +1496,55 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(KEYIN6_PU_MARK, PORT72_FN2, PORT72_IN_PU),
 	PINMUX_DATA(KEYIN7_PU_MARK, PORT73_FN2, PORT73_IN_PU),
 
-	PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_IN_PU, PORT259_FN1),
-	PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_IN_PU, PORT260_FN1),
-	PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_IN_PU, PORT261_FN1),
-	PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_IN_PU, PORT262_FN1),
-	PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_IN_PU, PORT263_FN1),
+	PINMUX_DATA(SDHICD0_PU_MARK,  PORT251_FN1, PORT251_IN_PU),
+	PINMUX_DATA(SDHID0_0_PU_MARK, PORT252_FN1, PORT252_IN_PU),
+	PINMUX_DATA(SDHID0_1_PU_MARK, PORT253_FN1, PORT253_IN_PU),
+	PINMUX_DATA(SDHID0_2_PU_MARK, PORT254_FN1, PORT254_IN_PU),
+	PINMUX_DATA(SDHID0_3_PU_MARK, PORT255_FN1, PORT255_IN_PU),
+	PINMUX_DATA(SDHICMD0_PU_MARK, PORT256_FN1, PORT256_IN_PU),
+	PINMUX_DATA(SDHIWP0_PU_MARK,  PORT257_FN1, PORT256_IN_PU),
+	PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_FN1, PORT259_IN_PU),
+	PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_FN1, PORT260_IN_PU),
+	PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_FN1, PORT261_IN_PU),
+	PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_FN1, PORT262_IN_PU),
+	PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_FN1, PORT263_IN_PU),
+	PINMUX_DATA(SDHID2_0_PU_MARK, PORT265_FN1, PORT265_IN_PU),
+	PINMUX_DATA(SDHID2_1_PU_MARK, PORT266_FN1, PORT266_IN_PU),
+	PINMUX_DATA(SDHID2_2_PU_MARK, PORT267_FN1, PORT267_IN_PU),
+	PINMUX_DATA(SDHID2_3_PU_MARK, PORT268_FN1, PORT268_IN_PU),
+	PINMUX_DATA(SDHICMD2_PU_MARK, PORT269_FN1, PORT269_IN_PU),
 
 	PINMUX_DATA(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU,
 		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT279_IN_PU,
+	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU,
 		MSEL4CR_MSEL15_1),
+
+	PINMUX_DATA(MMCD0_0_PU_MARK,
+		    PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_1_PU_MARK,
+		    PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_2_PU_MARK,
+		    PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_3_PU_MARK,
+		    PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_4_PU_MARK,
+		    PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_5_PU_MARK,
+		    PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_6_PU_MARK,
+		    PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_7_PU_MARK,
+		    PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0),
+
+	PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU),
 	PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU),
 	PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU),
 	PINMUX_DATA(FSIAIBT_PU_MARK, PORT51_FN5, PORT51_IN_PU),
 	PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_310() _310(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
-	GPIO_PORT_310(),
+	GPIO_PORT_ALL(),
 
 	/* Table 25-1 (Functions 0-7) */
 	GPIO_FN(VBUS_0),
@@ -2181,31 +2188,39 @@ static struct pinmux_gpio pinmux_gpios[]
 	GPIO_FN(KEYIN5_PU),
 	GPIO_FN(KEYIN6_PU),
 	GPIO_FN(KEYIN7_PU),
+	GPIO_FN(SDHICD0_PU),
+	GPIO_FN(SDHID0_0_PU),
+	GPIO_FN(SDHID0_1_PU),
+	GPIO_FN(SDHID0_2_PU),
+	GPIO_FN(SDHID0_3_PU),
+	GPIO_FN(SDHICMD0_PU),
+	GPIO_FN(SDHIWP0_PU),
 	GPIO_FN(SDHID1_0_PU),
 	GPIO_FN(SDHID1_1_PU),
 	GPIO_FN(SDHID1_2_PU),
 	GPIO_FN(SDHID1_3_PU),
 	GPIO_FN(SDHICMD1_PU),
+	GPIO_FN(SDHID2_0_PU),
+	GPIO_FN(SDHID2_1_PU),
+	GPIO_FN(SDHID2_2_PU),
+	GPIO_FN(SDHID2_3_PU),
+	GPIO_FN(SDHICMD2_PU),
 	GPIO_FN(MMCCMD0_PU),
 	GPIO_FN(MMCCMD1_PU),
+	GPIO_FN(MMCD0_0_PU),
+	GPIO_FN(MMCD0_1_PU),
+	GPIO_FN(MMCD0_2_PU),
+	GPIO_FN(MMCD0_3_PU),
+	GPIO_FN(MMCD0_4_PU),
+	GPIO_FN(MMCD0_5_PU),
+	GPIO_FN(MMCD0_6_PU),
+	GPIO_FN(MMCD0_7_PU),
 	GPIO_FN(FSIACK_PU),
 	GPIO_FN(FSIAILR_PU),
 	GPIO_FN(FSIAIBT_PU),
 	GPIO_FN(FSIAISLD_PU),
 };
 
-#define PORTCR(nr, reg)	\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \
-		0, \
-		/*0001*/ PORT##nr##_OUT , \
-		/*0010*/ PORT##nr##_IN , 0, 0, 0, 0, 0, 0, 0, \
-		/*1010*/ PORT##nr##_IN_PD, 0, 0, 0, \
-		/*1110*/ PORT##nr##_IN_PU, 0, \
-		PORT##nr##_FN0, PORT##nr##_FN1,	PORT##nr##_FN2, \
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5, \
-		PORT##nr##_FN6, PORT##nr##_FN7, 0, 0, 0, 0, 0, 0, 0, 0 } \
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
@@ -2718,6 +2733,45 @@ static struct pinmux_data_reg pinmux_dat
 	{ },
 };
 
+/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
+#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
+#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
+
+static struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
+};
+
 static struct pinmux_info sh73a0_pinmux_info = {
 	.name = "sh73a0_pfc",
 	.reserved_id = PINMUX_RESERVED,
@@ -2738,6 +2792,9 @@ static struct pinmux_info sh73a0_pinmux_
 
 	.gpio_data = pinmux_data,
 	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+
+	.gpio_irq = pinmux_irqs,
+	.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
 };
 
 void sh73a0_pinmux_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,11 @@
 #include <asm/mach-types.h>
 #include <mach/common.h>
 
+#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
+
 static unsigned int __init shmobile_smp_get_core_count(void)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		return sh73a0_get_core_count();
 
 	return 1;
@@ -31,7 +33,7 @@ static unsigned int __init shmobile_smp_
 
 static void __init shmobile_smp_prepare_cpus(void)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		sh73a0_smp_prepare_cpus();
 }
 
@@ -39,13 +41,13 @@ void __cpuinit platform_secondary_init(u
 {
 	trace_hardirqs_off();
 
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		sh73a0_secondary_init(cpu);
 }
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		return sh73a0_boot_secondary(cpu);
 
 	return -ENOSYS;
@@ -56,6 +58,12 @@ void __init smp_init_cpus(void)
 	unsigned int ncores = shmobile_smp_get_core_count();
 	unsigned int i;
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pm_runtime.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pm_runtime.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pm_runtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pm_runtime.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * arch/arm/mach-shmobile/pm_runtime.c
- *
- * Runtime PM support code for SuperH Mobile ARM
- *
- *  Copyright (C) 2009-2010 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_domain.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/sh_clk.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int default_platform_runtime_idle(struct device *dev)
-{
-	/* suspend synchronously to disable clocks immediately */
-	return pm_runtime_suspend(dev);
-}
-
-static struct dev_pm_domain default_pm_domain = {
-	.ops = {
-		.runtime_suspend = pm_clk_suspend,
-		.runtime_resume = pm_clk_resume,
-		.runtime_idle = default_platform_runtime_idle,
-		USE_PLATFORM_PM_SLEEP_OPS
-	},
-};
-
-#define DEFAULT_PM_DOMAIN_PTR	(&default_pm_domain)
-
-#else
-
-#define DEFAULT_PM_DOMAIN_PTR	NULL
-
-#endif /* CONFIG_PM_RUNTIME */
-
-static struct pm_clk_notifier_block platform_bus_notifier = {
-	.pm_domain = DEFAULT_PM_DOMAIN_PTR,
-	.con_ids = { NULL, },
-};
-
-static int __init sh_pm_runtime_init(void)
-{
-	pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
-	return 0;
-}
-core_initcall(sh_pm_runtime_init);
-
-static int __init sh_pm_runtime_late_init(void)
-{
-	pm_genpd_poweroff_unused();
-	return 0;
-}
-late_initcall(sh_pm_runtime_late_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pm-sh7372.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pm-sh7372.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/pm-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/pm-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,23 +15,62 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/bitrev.h>
+#include <linux/console.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
+#include <asm/suspend.h>
 #include <mach/common.h>
 #include <mach/sh7372.h>
 
-#define SMFRAM 0xe6a70000
+/* DBG */
+#define DBGREG1 0xe6100020
+#define DBGREG9 0xe6100040
+
+/* CPGA */
 #define SYSTBCR 0xe6150024
-#define SBAR 0xe6180020
-#define APARMBAREA 0xe6f10020
+#define MSTPSR0 0xe6150030
+#define MSTPSR1 0xe6150038
+#define MSTPSR2 0xe6150040
+#define MSTPSR3 0xe6150048
+#define MSTPSR4 0xe615004c
+#define PLLC01STPCR 0xe61500c8
 
+/* SYSC */
 #define SPDCR 0xe6180008
 #define SWUCR 0xe6180014
+#define SBAR 0xe6180020
+#define WUPRMSK 0xe6180028
+#define WUPSMSK 0xe618002c
+#define WUPSMSK2 0xe6180048
 #define PSTR 0xe6180080
+#define WUPSFAC 0xe6180098
+#define IRQCR 0xe618022c
+#define IRQCR2 0xe6180238
+#define IRQCR3 0xe6180244
+#define IRQCR4 0xe6180248
+#define PDNSEL 0xe6180254
+
+/* INTC */
+#define ICR1A 0xe6900000
+#define ICR2A 0xe6900004
+#define ICR3A 0xe6900008
+#define ICR4A 0xe690000c
+#define INTMSK00A 0xe6900040
+#define INTMSK10A 0xe6900044
+#define INTMSK20A 0xe6900048
+#define INTMSK30A 0xe690004c
+
+/* MFIS */
+#define SMFRAM 0xe6a70000
+
+/* AP-System Core */
+#define APARMBAREA 0xe6f10020
 
 #define PSTR_RETRIES 100
 #define PSTR_DELAY_US 10
@@ -43,6 +82,12 @@ static int pd_power_down(struct generic_
 	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
 	unsigned int mask = 1 << sh7372_pd->bit_shift;
 
+	if (sh7372_pd->suspend)
+		sh7372_pd->suspend();
+
+	if (sh7372_pd->stay_on)
+		return 0;
+
 	if (__raw_readl(PSTR) & mask) {
 		unsigned int retry_count;
 
@@ -55,19 +100,22 @@ static int pd_power_down(struct generic_
 		}
 	}
 
-	pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
-		 mask, __raw_readl(PSTR));
+	if (!sh7372_pd->no_debug)
+		pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
+			 mask, __raw_readl(PSTR));
 
 	return 0;
 }
 
-static int pd_power_up(struct generic_pm_domain *genpd)
+static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume)
 {
-	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
 	unsigned int mask = 1 << sh7372_pd->bit_shift;
 	unsigned int retry_count;
 	int ret = 0;
 
+	if (sh7372_pd->stay_on)
+		goto out;
+
 	if (__raw_readl(PSTR) & mask)
 		goto out;
 
@@ -75,76 +123,63 @@ static int pd_power_up(struct generic_pm
 
 	for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
 		if (!(__raw_readl(SWUCR) & mask))
-			goto out;
+			break;
 		if (retry_count > PSTR_RETRIES)
 			udelay(PSTR_DELAY_US);
 		else
 			cpu_relax();
 	}
-	if (__raw_readl(SWUCR) & mask)
+	if (!retry_count)
 		ret = -EIO;
 
+	if (!sh7372_pd->no_debug)
+		pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
+			 mask, __raw_readl(PSTR));
+
  out:
-	pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
-		 mask, __raw_readl(PSTR));
+	if (ret == 0 && sh7372_pd->resume && do_resume)
+		sh7372_pd->resume();
 
 	return ret;
 }
 
-static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+static int pd_power_up(struct generic_pm_domain *genpd)
 {
-	int ret = pd_power_up(genpd);
-
-	/* force A4LC on after A3RV has been requested on */
-	pm_genpd_poweron(&sh7372_a4lc.genpd);
-
-	return ret;
+	 return __pd_power_up(to_sh7372_pd(genpd), true);
 }
 
-static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+static void sh7372_a4r_suspend(void)
 {
-	int ret = pd_power_down(genpd);
-
-	/* try to power down A4LC after A3RV is requested off */
-	genpd_queue_power_off_work(&sh7372_a4lc.genpd);
-
-	return ret;
+	sh7372_intcs_suspend();
+	__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
 }
 
-static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+static bool pd_active_wakeup(struct device *dev)
 {
-	/* only power down A4LC if A3RV is off */
-	if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
-		return pd_power_down(genpd);
-
-	return -EBUSY;
+	return true;
 }
 
-static bool pd_active_wakeup(struct device *dev)
+static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain)
 {
-	return true;
+	return false;
 }
 
+struct dev_power_governor sh7372_always_on_gov = {
+	.power_down_ok = sh7372_power_down_forbidden,
+};
+
 void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
 {
 	struct generic_pm_domain *genpd = &sh7372_pd->genpd;
 
-	pm_genpd_init(genpd, NULL, false);
+	pm_genpd_init(genpd, sh7372_pd->gov, false);
 	genpd->stop_device = pm_clk_suspend;
 	genpd->start_device = pm_clk_resume;
+	genpd->dev_irq_safe = true;
 	genpd->active_wakeup = pd_active_wakeup;
-
-	if (sh7372_pd == &sh7372_a4lc) {
-		genpd->power_off = pd_power_down_a4lc;
-		genpd->power_on = pd_power_up;
-	} else if (sh7372_pd == &sh7372_a3rv) {
-		genpd->power_off = pd_power_down_a3rv;
-		genpd->power_on = pd_power_up_a3rv;
-	} else {
-		genpd->power_off = pd_power_down;
-		genpd->power_on = pd_power_up;
-	}
-	genpd->power_on(&sh7372_pd->genpd);
+	genpd->power_off = pd_power_down;
+	genpd->power_on = pd_power_up;
+	__pd_power_up(sh7372_pd, false);
 }
 
 void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
@@ -152,11 +187,15 @@ void sh7372_add_device_to_domain(struct
 {
 	struct device *dev = &pdev->dev;
 
-	if (!dev->power.subsys_data) {
-		pm_clk_init(dev);
-		pm_clk_add(dev, NULL);
-	}
 	pm_genpd_add_device(&sh7372_pd->genpd, dev);
+	if (pm_clk_no_clocks(dev))
+		pm_clk_add(dev, NULL);
+}
+
+void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+			     struct sh7372_pm_domain *sh7372_sd)
+{
+	pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd);
 }
 
 struct sh7372_pm_domain sh7372_a4lc = {
@@ -171,6 +210,14 @@ struct sh7372_pm_domain sh7372_d4 = {
 	.bit_shift = 3,
 };
 
+struct sh7372_pm_domain sh7372_a4r = {
+	.bit_shift = 5,
+	.gov = &sh7372_always_on_gov,
+	.suspend = sh7372_a4r_suspend,
+	.resume = sh7372_intcs_resume,
+	.stay_on = true,
+};
+
 struct sh7372_pm_domain sh7372_a3rv = {
 	.bit_shift = 6,
 };
@@ -179,55 +226,211 @@ struct sh7372_pm_domain sh7372_a3ri = {
 	.bit_shift = 8,
 };
 
+struct sh7372_pm_domain sh7372_a3sp = {
+	.bit_shift = 11,
+	.gov = &sh7372_always_on_gov,
+	.no_debug = true,
+};
+
+static void sh7372_a3sp_init(void)
+{
+	/* serial consoles make use of SCIF hardware located in A3SP,
+	 * keep such power domain on if "no_console_suspend" is set.
+	 */
+	sh7372_a3sp.stay_on = !console_suspend_enabled;
+}
+
 struct sh7372_pm_domain sh7372_a3sg = {
 	.bit_shift = 13,
 };
 
-#endif /* CONFIG_PM */
+#else /* !CONFIG_PM */
+
+static inline void sh7372_a3sp_init(void) {}
+
+#endif /* !CONFIG_PM */
+
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+static int sh7372_do_idle_core_standby(unsigned long unused)
+{
+	cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
+	return 0;
+}
 
 static void sh7372_enter_core_standby(void)
 {
-	void __iomem *smfram = (void __iomem *)SMFRAM;
+	/* set reset vector, translate 4k */
+	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+	__raw_writel(0, APARMBAREA);
 
-	__raw_writel(0, APARMBAREA); /* translate 4k */
-	__raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */
-	__raw_writel(0x10, SYSTBCR); /* enable core standby */
+	/* enter sleep mode with SYSTBCR to 0x10 */
+	__raw_writel(0x10, SYSTBCR);
+	cpu_suspend(0, sh7372_do_idle_core_standby);
+	__raw_writel(0, SYSTBCR);
 
-	__raw_writel(0, smfram + 0x3c); /* clear page table address */
+	 /* disable reset vector translation */
+	__raw_writel(0, SBAR);
+}
+#endif
 
-	sh7372_cpu_suspend();
-	cpu_init();
+#ifdef CONFIG_SUSPEND
+static void sh7372_enter_a3sm_common(int pllc0_on)
+{
+	/* set reset vector, translate 4k */
+	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+	__raw_writel(0, APARMBAREA);
 
-	/* if page table address is non-NULL then we have been powered down */
-	if (__raw_readl(smfram + 0x3c)) {
-		__raw_writel(__raw_readl(smfram + 0x40),
-			     __va(__raw_readl(smfram + 0x3c)));
+	if (pllc0_on)
+		__raw_writel(0, PLLC01STPCR);
+	else
+		__raw_writel(1 << 28, PLLC01STPCR);
 
-		flush_tlb_all();
-		set_cr(__raw_readl(smfram + 0x38));
+	__raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */
+	__raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
+	cpu_suspend(0, sh7372_do_idle_a3sm);
+	__raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
+
+	 /* disable reset vector translation */
+	__raw_writel(0, SBAR);
+}
+
+static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p)
+{
+	unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
+	unsigned long msk, msk2;
+
+	/* check active clocks to determine potential wakeup sources */
+
+	mstpsr0 = __raw_readl(MSTPSR0);
+	if ((mstpsr0 & 0x00000003) != 0x00000003) {
+		pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0);
+		return 0;
 	}
 
-	__raw_writel(0, SYSTBCR); /* disable core standby */
-	__raw_writel(0, SBAR); /* disable reset vector translation */
+	mstpsr1 = __raw_readl(MSTPSR1);
+	if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) {
+		pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1);
+		return 0;
+	}
+
+	mstpsr2 = __raw_readl(MSTPSR2);
+	if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
+		pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
+		return 0;
+	}
+
+	mstpsr3 = __raw_readl(MSTPSR3);
+	if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) {
+		pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3);
+		return 0;
+	}
+
+	mstpsr4 = __raw_readl(MSTPSR4);
+	if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) {
+		pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4);
+		return 0;
+	}
+
+	msk = 0;
+	msk2 = 0;
+
+	/* make bitmaps of limited number of wakeup sources */
+
+	if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */
+		msk |= 1 << 31;
+
+	if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */
+		msk |= 1 << 21;
+
+	if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */
+		msk |= 1 << 2;
+
+	if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */
+		msk |= 1 << 1;
+
+	if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */
+		msk |= 1 << 1;
+
+	if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */
+		msk |= 1 << 1;
+
+	if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */
+		msk2 |= 1 << 17;
+
+	*mskp = msk;
+	*msk2p = msk2;
+
+	return 1;
 }
 
+static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
+{
+	u16 tmp, irqcr1, irqcr2;
+	int k;
+
+	irqcr1 = 0;
+	irqcr2 = 0;
+
+	/* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
+	for (k = 0; k <= 7; k++) {
+		tmp = (icr >> ((7 - k) * 4)) & 0xf;
+		irqcr1 |= (tmp & 0x03) << (k * 2);
+		irqcr2 |= (tmp >> 2) << (k * 2);
+	}
+
+	*irqcr1p = irqcr1;
+	*irqcr2p = irqcr2;
+}
+
+static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
+{
+	u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
+	unsigned long tmp;
+
+	/* read IRQ0A -> IRQ15A mask */
+	tmp = bitrev8(__raw_readb(INTMSK00A));
+	tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8;
+
+	/* setup WUPSMSK from clocks and external IRQ mask */
+	msk = (~msk & 0xc030000f) | (tmp << 4);
+	__raw_writel(msk, WUPSMSK);
+
+	/* propage level/edge trigger for external IRQ 0->15 */
+	sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low);
+	sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high);
+	__raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR);
+	__raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2);
+
+	/* read IRQ16A -> IRQ31A mask */
+	tmp = bitrev8(__raw_readb(INTMSK20A));
+	tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8;
+
+	/* setup WUPSMSK2 from clocks and external IRQ mask */
+	msk2 = (~msk2 & 0x00030000) | tmp;
+	__raw_writel(msk2, WUPSMSK2);
+
+	/* propage level/edge trigger for external IRQ 16->31 */
+	sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low);
+	sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high);
+	__raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
+	__raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
+}
+#endif
+
 #ifdef CONFIG_CPU_IDLE
-static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
+
+static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
 {
-	struct cpuidle_state *state;
-	int i = dev->state_count;
+	struct cpuidle_state *state = &drv->states[drv->state_count];
 
-	state = &dev->states[i];
 	snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 	strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 10;
 	state->target_residency = 20 + 10;
-	state->power_usage = 1; /* perhaps not */
-	state->flags = 0;
-	state->flags |= CPUIDLE_FLAG_TIME_VALID;
-	shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
+	state->flags = CPUIDLE_FLAG_TIME_VALID;
+	shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
 
-	dev->state_count = i + 1;
+	drv->state_count++;
 }
 
 static void sh7372_cpuidle_init(void)
@@ -239,9 +442,25 @@ static void sh7372_cpuidle_init(void) {}
 #endif
 
 #ifdef CONFIG_SUSPEND
+
 static int sh7372_enter_suspend(suspend_state_t suspend_state)
 {
-	sh7372_enter_core_standby();
+	unsigned long msk, msk2;
+
+	/* check active clocks to determine potential wakeup sources */
+	if (sh7372_a3sm_valid(&msk, &msk2)) {
+
+		/* convert INTC mask and sense to SYSC mask and sense */
+		sh7372_setup_a3sm(msk, msk2);
+
+		/* enter A3SM sleep with PLLC0 off */
+		pr_debug("entering A3SM\n");
+		sh7372_enter_a3sm_common(0);
+	} else {
+		/* default to Core Standby that supports all wakeup sources */
+		pr_debug("entering Core Standby\n");
+		sh7372_enter_core_standby();
+	}
 	return 0;
 }
 
@@ -253,9 +472,6 @@ static void sh7372_suspend_init(void)
 static void sh7372_suspend_init(void) {}
 #endif
 
-#define DBGREG1 0xe6100020
-#define DBGREG9 0xe6100040
-
 void __init sh7372_pm_init(void)
 {
 	/* enable DBG hardware block to kick SYSC */
@@ -263,6 +479,11 @@ void __init sh7372_pm_init(void)
 	__raw_writel(0x0000a501, DBGREG9);
 	__raw_writel(0x00000000, DBGREG1);
 
+	/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
+	__raw_writel(0, PDNSEL);
+
+	sh7372_a3sp_init();
+
 	sh7372_suspend_init();
 	sh7372_cpuidle_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/setup-sh7372.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/setup-sh7372.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/setup-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/setup-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
+#include <linux/pm_domain.h>
 #include <mach/hardware.h>
 #include <mach/sh7372.h>
 #include <asm/mach-types.h>
@@ -990,9 +991,14 @@ void __init sh7372_add_standard_devices(
 	sh7372_init_pm_domain(&sh7372_a4lc);
 	sh7372_init_pm_domain(&sh7372_a4mp);
 	sh7372_init_pm_domain(&sh7372_d4);
+	sh7372_init_pm_domain(&sh7372_a4r);
 	sh7372_init_pm_domain(&sh7372_a3rv);
 	sh7372_init_pm_domain(&sh7372_a3ri);
 	sh7372_init_pm_domain(&sh7372_a3sg);
+	sh7372_init_pm_domain(&sh7372_a3sp);
+
+	sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
+	sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
 
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
@@ -1003,6 +1009,25 @@ void __init sh7372_add_standard_devices(
 	sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
 }
 
 void __init sh7372_add_early_devices(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/sleep-sh7372.S linux-libre-3.2-gnu1/arch/arm/mach-shmobile/sleep-sh7372.S
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/sleep-sh7372.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/sleep-sh7372.S	2012-01-04 18:55:44.000000000 -0500
@@ -30,58 +30,20 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
 #include <asm/assembler.h>
 
-#define SMFRAM 0xe6a70000
-
-	.align
-kernel_flush:
-	.word	v7_flush_dcache_all
-
-	.align	3
-ENTRY(sh7372_cpu_suspend)
-	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
-
-	ldr	r8, =SMFRAM
-
-	mov	r4, sp			@ Store sp
-	mrs	r5, spsr		@ Store spsr
-	mov	r6, lr			@ Store lr
-	stmia	r8!, {r4-r6}
-
-	mrc	p15, 0, r4, c1, c0, 2	@ Coprocessor access control register
-	mrc	p15, 0, r5, c2, c0, 0	@ TTBR0
-	mrc	p15, 0, r6, c2, c0, 1	@ TTBR1
-	mrc	p15, 0, r7, c2, c0, 2	@ TTBCR
-	stmia	r8!, {r4-r7}
-
-	mrc	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
-	mrc	p15, 0, r5, c10, c2, 0	@ PRRR
-	mrc	p15, 0, r6, c10, c2, 1	@ NMRR
-	stmia	r8!,{r4-r6}
-
-	mrc	p15, 0, r4, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
-	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
-	mrs	r7, cpsr		@ Store current cpsr
-	stmia	r8!, {r4-r7}
-
-	mrc	p15, 0, r4, c1, c0, 0	@ save control register
-	stmia	r8!, {r4}
-
-	/*
-	 * jump out to kernel flush routine
-	 *  - reuse that code is better
-	 *  - it executes in a cached space so is faster than refetch per-block
-	 *  - should be faster and will change with kernel
-	 *  - 'might' have to copy address, load and jump to it
-	 * Flush all data from the L1 data cache before disabling
-	 * SCTLR.C bit.
-	 */
-	ldr	r1, kernel_flush
-	mov	lr, pc
-	bx	r1
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+	.align	12
+	.text
+	.global sh7372_resume_core_standby_a3sm
+sh7372_resume_core_standby_a3sm:
+	ldr     pc, 1f
+1:	.long   cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
 
+	.global	sh7372_do_idle_a3sm
+sh7372_do_idle_a3sm:
 	/*
 	 * Clear the SCTLR.C bit to prevent further data cache
 	 * allocation. Clearing SCTLR.C would make all the data accesses
@@ -92,10 +54,13 @@ ENTRY(sh7372_cpu_suspend)
 	mcr	p15, 0, r0, c1, c0, 0
 	isb
 
+	/* disable L2 cache in the aux control register */
+	mrc     p15, 0, r10, c1, c0, 1
+	bic     r10, r10, #2
+	mcr     p15, 0, r10, c1, c0, 1
+
 	/*
-	 * Invalidate L1 data cache. Even though only invalidate is
-	 * necessary exported flush API is used here. Doing clean
-	 * on already clean cache would be almost NOP.
+	 * Invalidate data cache again.
 	 */
 	ldr	r1, kernel_flush
 	blx	r1
@@ -115,146 +80,16 @@ ENTRY(sh7372_cpu_suspend)
 	dsb
 	dmb
 
-/*
- * ===================================
- * == WFI instruction => Enter idle ==
- * ===================================
- */
-	wfi				@ wait for interrupt
-
-/*
- * ===================================
- * == Resume path for non-OFF modes ==
- * ===================================
- */
-	mrc	p15, 0, r0, c1, c0, 0
-	tst	r0, #(1 << 2)		@ Check C bit enabled?
-	orreq	r0, r0, #(1 << 2)	@ Enable the C bit if cleared
-	mcreq	p15, 0, r0, c1, c0, 0
-	isb
-
-/*
- * ===================================
- * == Exit point from non-OFF modes ==
- * ===================================
- */
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
-
-	.pool
-
-	.align	12
-	.text
-	.global	sh7372_cpu_resume
-sh7372_cpu_resume:
-
-	mov	r1, #0
-	/*
-	 * Invalidate all instruction caches to PoU
-	 * and flush branch target cache
-	 */
-	mcr	p15, 0, r1, c7, c5, 0
-
-	ldr	r3, =SMFRAM
-
-	ldmia	r3!, {r4-r6}
-	mov	sp, r4			@ Restore sp
-	msr	spsr_cxsf, r5		@ Restore spsr
-	mov	lr, r6			@ Restore lr
-
-	ldmia	r3!, {r4-r7}
-	mcr	p15, 0, r4, c1, c0, 2	@ Coprocessor access Control Register
-	mcr	p15, 0, r5, c2, c0, 0	@ TTBR0
-	mcr	p15, 0, r6, c2, c0, 1	@ TTBR1
-	mcr	p15, 0, r7, c2, c0, 2	@ TTBCR
-
-	ldmia	r3!,{r4-r6}
-	mcr	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
-	mcr	p15, 0, r5, c10, c2, 0	@ PRRR
-	mcr	p15, 0, r6, c10, c2, 1	@ NMRR
-
-	ldmia	r3!,{r4-r7}
-	mcr	p15, 0, r4, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
-	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
-	msr	cpsr, r7		@ store cpsr
-
-	/* Starting to enable MMU here */
-	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl
-	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
-	and	r7, #0x7
-	cmp	r7, #0x0
-	beq	usettbr0
-ttbr_error:
-	/*
-	 * More work needs to be done to support N[0:2] value other than 0
-	 * So looping here so that the error can be detected
-	 */
-	b	ttbr_error
-
-	.align
-cache_pred_disable_mask:
-	.word	0xFFFFE7FB
-ttbrbit_mask:
-	.word	0xFFFFC000
-table_index_mask:
-	.word	0xFFF00000
-table_entry:
-	.word	0x00000C02
-usettbr0:
-
-	mrc	p15, 0, r2, c2, c0, 0
-	ldr	r5, ttbrbit_mask
-	and	r2, r5
-	mov	r4, pc
-	ldr	r5, table_index_mask
-	and	r4, r5			@ r4 = 31 to 20 bits of pc
-	/* Extract the value to be written to table entry */
-	ldr	r6, table_entry
-	/* r6 has the value to be written to table entry */
-	add	r6, r6, r4
-	/* Getting the address of table entry to modify */
-	lsr	r4, #18
-	/* r2 has the location which needs to be modified */
-	add	r2, r4
-	ldr	r4, [r2]
-	str	r6, [r2] /* modify the table entry */
-
-	mov	r7, r6
-	mov	r5, r2
-	mov	r6, r4
-	/* r5 = original page table address */
-	/* r6 = original page table data */
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
-	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
-	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
-	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
-
-	/*
-	 * Restore control register. This enables the MMU.
-	 * The caches and prediction are not enabled here, they
-	 * will be enabled after restoring the MMU table entry.
-	 */
-	ldmia	r3!, {r4}
-	stmia	r3!, {r5} /* save original page table address */
-	stmia	r3!, {r6} /* save original page table data */
-	stmia	r3!, {r7} /* save modified page table data */
-
-	ldr	r2, cache_pred_disable_mask
-	and	r4, r2
-	mcr	p15, 0, r4, c1, c0, 0
-	dsb
-	isb
-
-	ldr     r0, =restoremmu_on
-	bx      r0
+#define SPDCR 0xe6180008
+#define A3SM (1 << 12)
 
-/*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
- */
-restoremmu_on:
+	/* A3SM power down */
+	ldr     r0, =SPDCR
+	ldr     r1, =A3SM
+	str     r1, [r0]
+1:
+	b      1b
 
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+kernel_flush:
+	.word v7_flush_dcache_all
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c linux-libre-3.2-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(uns
 
 int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
 {
+	cpu = cpu_logical_map(cpu);
+
 	/* enable cache coherency */
 	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsi
 
 void __init sh73a0_smp_prepare_cpus(void)
 {
+	int cpu = cpu_logical_map(0);
+
 	scu_enable(scu_base_addr());
 
 	/* Map the reset vector (in headsmp.S) */
@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void
 	__raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
 
 	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (0 * 8));
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/memory.h
- *
- * Memory map for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif /* __MACH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear300_evb.c linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear300_evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear300_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear300_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@ static void __init spear300_evb_init(voi
 }
 
 MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear310_evb.c linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear310_evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear310_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear310_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@ static void __init spear310_evb_init(voi
 }
 
 MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear320_evb.c linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear320_evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-spear3xx/spear320_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear3xx/spear320_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ static void __init spear320_evb_init(voi
 }
 
 MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/memory.h
- *
- * Memory map for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif	/* __MACH_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/spear600_evb.c linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/spear600_evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-spear6xx/spear600_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-spear6xx/spear600_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@ static void __init spear600_evb_init(voi
 }
 
 MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear6xx_map_io,
 	.init_irq	=	spear6xx_init_irq,
 	.timer		=	&spear6xx_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tcc8k/board-tcc8000-sdk.c linux-libre-3.2-gnu1/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@ static void __init tcc8k_map_io(void)
 }
 
 MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= tcc8k_map_io,
 	.init_irq	= tcc8k_init_irq,
 	.init_machine	= tcc8k_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tcc8k/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-tcc8k/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-tcc8k/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tcc8k/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y		:= 0x20008000
+   zreladdr-y		+= 0x20008000
 params_phys-y		:= 0x20000100
 initrd_phys-y		:= 0x20800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-dt.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-dt.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-dt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@
 
 void harmony_pinmux_init(void);
 void seaboard_pinmux_init(void);
-
+void ventana_pinmux_init(void);
 
 struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_
 	{}
 };
 
+static struct {
+	char *machine;
+	void (*init)(void);
+} pinmux_configs[] = {
+	{ "nvidia,harmony", harmony_pinmux_init },
+	{ "nvidia,seaboard", seaboard_pinmux_init },
+	{ "nvidia,ventana", ventana_pinmux_init },
+};
+
 static void __init tegra_dt_init(void)
 {
 	struct device_node *node;
+	int i;
 
 	node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
 						TEGRA_ARM_INT_DIST_BASE);
@@ -91,21 +101,28 @@ static void __init tegra_dt_init(void)
 
 	tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-	if (of_machine_is_compatible("nvidia,harmony"))
-		harmony_pinmux_init();
-	else if (of_machine_is_compatible("nvidia,seaboard"))
-		seaboard_pinmux_init();
-
 	/*
 	 * Finished with the static registrations now; fill in the missing
 	 * devices
 	 */
-	of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
+	of_platform_populate(NULL, tegra_dt_match_table,
+				tegra20_auxdata_lookup, NULL);
+
+	for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+		if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+			pinmux_configs[i].init();
+			break;
+		}
+	}
+
+	WARN(i == ARRAY_SIZE(pinmux_configs),
+		"Unknown platform! Pinmuxing not initialized\n");
 }
 
 static const char * tegra_dt_board_compat[] = {
 	"nvidia,harmony",
 	"nvidia,seaboard",
+	"nvidia,ventana",
 	NULL
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,8 @@ static struct plat_serial8250_port debug
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -117,14 +118,15 @@ static struct platform_device *harmony_d
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device2,
 	&tegra_sdhci_device4,
+	&tegra_ehci3_device,
 	&tegra_i2s_device1,
 	&tegra_das_device,
 	&tegra_pcm_device,
 	&harmony_audio_device,
 };
 
-static void __init tegra_harmony_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_harmony_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -140,6 +142,7 @@ static __initdata struct tegra_clk_init_
 	{ "pll_a_out0",	"pll_a",	11289600,	true },
 	{ "cdev1",	NULL,		0,		true },
 	{ "i2s1",	"pll_a_out0",	11289600,	false},
+	{ "usb3",	"clk_m",	12000000,	true },
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -179,7 +182,7 @@ static void __init tegra_harmony_init(vo
 }
 
 MACHINE_START(HARMONY, "harmony")
-	.boot_params  = 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_harmony_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #ifndef _MACH_TEGRA_BOARD_HARMONY_H
 #define _MACH_TEGRA_BOARD_HARMONY_H
 
+#include <mach/gpio-tegra.h>
+
 #define HARMONY_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
 #define HARMONY_GPIO_WM8903(_x_)	(HARMONY_GPIO_TPS6586X(4) + (_x_))
 
@@ -31,6 +33,7 @@
 #define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PW2
 #define TEGRA_GPIO_INT_MIC_EN		TEGRA_GPIO_PX0
 #define TEGRA_GPIO_EXT_MIC_EN		TEGRA_GPIO_PX1
+#define TEGRA_GPIO_EN_VDD_1V05_GPIO	HARMONY_GPIO_TPS6586X(2)
 
 void harmony_pinmux_init(void);
 int harmony_regulator_init(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-pcie.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-pcie.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,12 +24,10 @@
 
 #include <mach/pinmux.h>
 #include "board.h"
+#include "board-harmony.h"
 
 #ifdef CONFIG_TEGRA_PCI
 
-/* GPIO 3 of the PMIC */
-#define EN_VDD_1V05_GPIO	(TEGRA_NR_GPIOS + 2)
-
 static int __init harmony_pcie_init(void)
 {
 	struct regulator *regulator = NULL;
@@ -38,11 +36,11 @@ static int __init harmony_pcie_init(void
 	if (!machine_is_harmony())
 		return 0;
 
-	err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05");
+	err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
 	if (err)
 		return err;
 
-	gpio_direction_output(EN_VDD_1V05_GPIO, 1);
+	gpio_direction_output(TEGRA_GPIO_EN_VDD_1V05_GPIO, 1);
 
 	regulator = regulator_get(NULL, "pex_clk");
 	if (IS_ERR_OR_NULL(regulator))
@@ -68,7 +66,7 @@ err_pcie:
 	regulator_disable(regulator);
 	regulator_put(regulator);
 err_reg:
-	gpio_free(EN_VDD_1V05_GPIO);
+	gpio_free(TEGRA_GPIO_EN_VDD_1V05_GPIO);
 
 	return err;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-pinmux.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-pinmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,13 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
 #include "board-harmony.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,6 +143,11 @@ static struct tegra_pingroup_config harm
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true	},
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true	},
@@ -155,6 +163,10 @@ static struct tegra_gpio_table gpio_tabl
 
 void harmony_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-power.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-power.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-harmony-power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-harmony-power.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,10 +18,11 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-
+#include <linux/io.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps6586x.h>
 
+#include <mach/iomap.h>
 #include <mach/irqs.h>
 
 #include "board-harmony.h"
@@ -113,6 +114,16 @@ static struct i2c_board_info __initdata
 
 int __init harmony_regulator_init(void)
 {
+	void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+	u32 pmc_ctrl;
+
+	/*
+	 * Configure the power management controller to trigger PMU
+	 * interrupts when low
+	 */
+	pmc_ctrl = readl(pmc + PMC_CTRL);
+	writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
 	i2c_register_board_info(3, harmony_regulators, 1);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 #include <linux/pda_power.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/rfkill-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,7 +37,6 @@
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "board-paz00.h"
@@ -45,10 +46,22 @@
 
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
+		/* serial port on JP1 */
+		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
+		.mapbase	= TEGRA_UARTA_BASE,
+		.irq		= INT_UARTA,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		/* serial port on mini-pcie */
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -65,10 +78,48 @@ static struct platform_device debug_uart
 	},
 };
 
+static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
+	.name		= "wifi_rfkill",
+	.reset_gpio	= TEGRA_WIFI_RST,
+	.shutdown_gpio	= TEGRA_WIFI_PWRN,
+	.type	= RFKILL_TYPE_WLAN,
+};
+
+static struct platform_device wifi_rfkill_device = {
+	.name	= "rfkill_gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &wifi_rfkill_platform_data,
+	},
+};
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "wifi-led",
+		.default_trigger	= "rfkill0",
+		.gpio			= TEGRA_WIFI_LED,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &gpio_led_info,
+        },
+};
+
 static struct platform_device *paz00_devices[] __initdata = {
 	&debug_uart,
-	&tegra_sdhci_device1,
 	&tegra_sdhci_device4,
+	&tegra_sdhci_device1,
+	&wifi_rfkill_device,
+	&leds_gpio,
 };
 
 static void paz00_i2c_init(void)
@@ -84,8 +135,8 @@ static void paz00_usb_init(void)
 	platform_device_register(&tegra_ehci3_device);
 }
 
-static void __init tegra_paz00_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -94,7 +145,14 @@ static void __init tegra_paz00_fixup(str
 
 static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
 	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
 	{ "uartd",	"pll_p",	216000000,	true },
+
+	{ "pll_p_out4",	"pll_p",	24000000,	true },
+	{ "usbd",	"clk_m",	12000000,	false },
+	{ "usb2",	"clk_m",	12000000,	false },
+	{ "usb3",	"clk_m",	12000000,	false },
+
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -127,7 +185,7 @@ static void __init tegra_paz00_init(void
 }
 
 MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_paz00_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,21 @@
 #ifndef _MACH_TEGRA_BOARD_PAZ00_H
 #define _MACH_TEGRA_BOARD_PAZ00_H
 
+#include <mach/gpio-tegra.h>
+
+/* SDCARD */
 #define TEGRA_GPIO_SD1_CD		TEGRA_GPIO_PV5
 #define TEGRA_GPIO_SD1_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD1_POWER		TEGRA_GPIO_PT3
+
+/* ULPI */
 #define TEGRA_ULPI_RST			TEGRA_GPIO_PV0
 
+/* WIFI */
+#define TEGRA_WIFI_PWRN			TEGRA_GPIO_PK5
+#define TEGRA_WIFI_RST			TEGRA_GPIO_PD1
+#define TEGRA_WIFI_LED			TEGRA_GPIO_PD0
+
 void paz00_pinmux_init(void);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00-pinmux.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00-pinmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-paz00-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-paz00-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,13 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
 #include "board-paz00.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config paz00_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,15 +143,27 @@ static struct tegra_pingroup_config paz0
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD1_CD,	.enable = true },
 	{ .gpio = TEGRA_GPIO_SD1_WP,	.enable = true },
 	{ .gpio = TEGRA_GPIO_SD1_POWER,	.enable = true },
 	{ .gpio = TEGRA_ULPI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_PWRN,	.enable = true },
+	{ .gpio = TEGRA_WIFI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_LED,	.enable = true },
 };
 
 void paz00_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,12 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 
+#include <sound/wm8903.h>
+
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
+#include <mach/tegra_wm8903_pdata.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,7 +44,8 @@
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
 		/* Memory and IRQ filled in before registration */
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -62,6 +66,12 @@ static __initdata struct tegra_clk_init_
 	/* name		parent		rate		enabled */
 	{ "uartb",	"pll_p",	216000000,	true},
 	{ "uartd",	"pll_p",	216000000,	true},
+	{ "pll_a",	"pll_p_out1",	56448000,	true },
+	{ "pll_a_out0",	"pll_a",	11289600,	true },
+	{ "cdev1",	NULL,		0,		true },
+	{ "i2s1",	"pll_a_out0",	11289600,	false},
+	{ "usbd",	"clk_m",	12000000,	true},
+	{ "usb3",	"clk_m",	12000000,	true},
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -117,6 +127,22 @@ static struct tegra_sdhci_platform_data
 	.is_8bit	= 1,
 };
 
+static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
+	.gpio_spkr_en		= TEGRA_GPIO_SPKR_EN,
+	.gpio_hp_det		= TEGRA_GPIO_HP_DET,
+	.gpio_hp_mute		= -1,
+	.gpio_int_mic_en	= -1,
+	.gpio_ext_mic_en	= -1,
+};
+
+static struct platform_device seaboard_audio_device = {
+	.name	= "tegra-snd-wm8903",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &seaboard_audio_pdata,
+	},
+};
+
 static struct platform_device *seaboard_devices[] __initdata = {
 	&debug_uart,
 	&tegra_pmu_device,
@@ -124,6 +150,10 @@ static struct platform_device *seaboard_
 	&tegra_sdhci_device3,
 	&tegra_sdhci_device1,
 	&seaboard_gpio_keys_device,
+	&tegra_i2s_device1,
+	&tegra_das_device,
+	&tegra_pcm_device,
+	&seaboard_audio_device,
 };
 
 static struct i2c_board_info __initdata isl29018_device = {
@@ -135,12 +165,56 @@ static struct i2c_board_info __initdata
 	I2C_BOARD_INFO("adt7461", 0x4c),
 };
 
+static struct wm8903_platform_data wm8903_pdata = {
+	.irq_active_low = 0,
+	.micdet_cfg = 0,
+	.micdet_delay = 100,
+	.gpio_base = SEABOARD_GPIO_WM8903(0),
+	.gpio_cfg = {
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+		0,
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+	},
+};
+
+static struct i2c_board_info __initdata wm8903_device = {
+	I2C_BOARD_INFO("wm8903", 0x1a),
+	.platform_data = &wm8903_pdata,
+	.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
+};
+
+static int seaboard_ehci_init(void)
+{
+	int gpio_status;
+
+	gpio_status = gpio_request(TEGRA_GPIO_USB1, "VBUS_USB1");
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO FAILED\n");
+		WARN_ON(1);
+	}
+
+	gpio_status = gpio_direction_output(TEGRA_GPIO_USB1, 1);
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO DIRECTION FAILED\n");
+		WARN_ON(1);
+	}
+	gpio_set_value(TEGRA_GPIO_USB1, 1);
+
+	platform_device_register(&tegra_ehci1_device);
+	platform_device_register(&tegra_ehci3_device);
+
+	return 0;
+}
+
 static void __init seaboard_i2c_init(void)
 {
 	gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
 	gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
 
 	i2c_register_board_info(0, &isl29018_device, 1);
+	i2c_register_board_info(0, &wm8903_device, 1);
 
 	i2c_register_board_info(3, &adt7461_device, 1);
 
@@ -161,6 +235,8 @@ static void __init seaboard_common_init(
 	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
 	platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+
+	seaboard_ehci_init();
 }
 
 static void __init tegra_seaboard_init(void)
@@ -182,6 +258,9 @@ static void __init tegra_kaen_init(void)
 	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
 	debug_uart_platform_data[0].irq = INT_UARTB;
 
+	seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
+	tegra_gpio_enable(TEGRA_GPIO_KAEN_HP_MUTE);
+
 	seaboard_common_init();
 
 	seaboard_i2c_init();
@@ -201,7 +280,7 @@ static void __init tegra_wario_init(void
 
 
 MACHINE_START(SEABOARD, "seaboard")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
@@ -210,7 +289,7 @@ MACHINE_START(SEABOARD, "seaboard")
 MACHINE_END
 
 MACHINE_START(KAEN, "kaen")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
@@ -219,7 +298,7 @@ MACHINE_START(KAEN, "kaen")
 MACHINE_END
 
 MACHINE_START(WARIO, "wario")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,11 @@
 #ifndef _MACH_TEGRA_BOARD_SEABOARD_H
 #define _MACH_TEGRA_BOARD_SEABOARD_H
 
+#include <mach/gpio-tegra.h>
+
+#define SEABOARD_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
+#define SEABOARD_GPIO_WM8903(_x_)	(SEABOARD_GPIO_TPS6586X(4) + (_x_))
+
 #define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
 #define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PI6
@@ -31,10 +36,11 @@
 #define TEGRA_GPIO_MAGNETOMETER		TEGRA_GPIO_PN5
 #define TEGRA_GPIO_ISL29018_IRQ		TEGRA_GPIO_PZ2
 #define TEGRA_GPIO_AC_ONLINE		TEGRA_GPIO_PV3
-
-#define TPS_GPIO_BASE			TEGRA_NR_GPIOS
-
-#define TPS_GPIO_WWAN_PWR		(TPS_GPIO_BASE + 2)
+#define TEGRA_GPIO_WWAN_PWR		SEABOARD_GPIO_TPS6586X(2)
+#define TEGRA_GPIO_CDC_IRQ		TEGRA_GPIO_PX3
+#define TEGRA_GPIO_SPKR_EN		SEABOARD_GPIO_WM8903(2)
+#define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PX1
+#define TEGRA_GPIO_KAEN_HP_MUTE		TEGRA_GPIO_PA5
 
 void seaboard_pinmux_init(void);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard-pinmux.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard-pinmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-seaboard-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-seaboard-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2011 Google, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -15,12 +16,14 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 #include <mach/pinmux-t2.h>
 
 #include "gpio-names.h"
 #include "board-seaboard.h"
+#include "devices.h"
 
 #define DEFAULT_DRIVE(_name)					\
 	{							\
@@ -49,7 +52,7 @@ static __initdata struct tegra_pingroup_
 	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
-	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
@@ -133,7 +136,7 @@ static __initdata struct tegra_pingroup_
 	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
@@ -157,24 +160,86 @@ static __initdata struct tegra_pingroup_
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
+	{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTC,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTD,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,  TEGRA_MUX_SFLASH,   TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+};
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
 
-
-static struct tegra_gpio_table gpio_table[] = {
+static struct tegra_gpio_table common_gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_POWER,		.enable = true },
 	{ .gpio = TEGRA_GPIO_LIDSWITCH,		.enable = true },
 	{ .gpio = TEGRA_GPIO_POWERKEY,		.enable = true },
+	{ .gpio = TEGRA_GPIO_HP_DET,		.enable = true },
 	{ .gpio = TEGRA_GPIO_ISL29018_IRQ,	.enable = true },
+	{ .gpio = TEGRA_GPIO_CDC_IRQ,		.enable = true },
+	{ .gpio = TEGRA_GPIO_USB1,		.enable = true },
 };
 
-void __init seaboard_pinmux_init(void)
+static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
 {
+	int i, j;
+	struct tegra_pingroup_config *new_pingroup, *base_pingroup;
+
+	/* Update base seaboard pinmux table with secondary board
+	 * specific pinmux table table.
+	 */
+	for (i = 0; i < size; i++) {
+		new_pingroup = &newtbl[i];
+		for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
+			base_pingroup = &seaboard_pinmux[j];
+			if (new_pingroup->pingroup == base_pingroup->pingroup) {
+				*base_pingroup = *new_pingroup;
+				break;
+			}
+		}
+	}
+}
+
+void __init seaboard_common_pinmux_init(void)
+{
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
 
 	tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
 					ARRAY_SIZE(seaboard_drive_pinmux));
 
-	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+	tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
 }
+
+void __init seaboard_pinmux_init(void)
+{
+	seaboard_common_pinmux_init();
+}
+
+void __init ventana_pinmux_init(void)
+{
+	update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
+	seaboard_common_pinmux_init();
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,6 @@
 
 #include <mach/iomap.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "clock.h"
@@ -46,7 +45,8 @@ static struct plat_serial8250_port debug
 		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
 		.mapbase	= TEGRA_UARTA_BASE,
 		.irq		= INT_UARTA,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -126,8 +126,8 @@ static void trimslice_usb_init(void)
 	platform_device_register(&tegra_ehci1_device);
 }
 
-static void __init tegra_trimslice_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_trimslice_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -171,7 +171,7 @@ static void __init tegra_trimslice_init(
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_trimslice_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
 #define _MACH_TEGRA_BOARD_TRIMSLICE_H
 
+#include <mach/gpio-tegra.h>
+
 #define TRIMSLICE_GPIO_SD4_CD	TEGRA_GPIO_PP1	/* mmc4 cd */
 #define TRIMSLICE_GPIO_SD4_WP	TEGRA_GPIO_PP2	/* mmc4 wp */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice-pinmux.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice-pinmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/board-trimslice-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/board-trimslice-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,16 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
-#include <mach/gpio.h>
 
 #include "gpio-names.h"
 #include "board-trimslice.h"
+#include "devices.h"
 
 static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
@@ -142,6 +143,11 @@ static __initdata struct tegra_pingroup_
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true	}, /* mmc4 cd */
 	{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true	}, /* mmc4 wp */
@@ -152,6 +158,9 @@ static struct tegra_gpio_table gpio_tabl
 
 void __init trimslice_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
 	tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/common.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@ static __initdata struct tegra_clk_init_
 	{ NULL,		NULL,		0,		0},
 };
 
-void __init tegra_init_cache(void)
+static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/cpu-tegra.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/cpu-tegra.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/cpu-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/cpu-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,12 +56,12 @@ static unsigned long target_cpu_speed[NU
 static DEFINE_MUTEX(tegra_cpu_lock);
 static bool is_suspended;
 
-int tegra_verify_speed(struct cpufreq_policy *policy)
+static int tegra_verify_speed(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, freq_table);
 }
 
-unsigned int tegra_getspeed(unsigned int cpu)
+static unsigned int tegra_getspeed(unsigned int cpu)
 {
 	unsigned long rate;
 
@@ -129,7 +129,7 @@ static int tegra_target(struct cpufreq_p
 		       unsigned int target_freq,
 		       unsigned int relation)
 {
-	int idx;
+	unsigned int idx;
 	unsigned int freq;
 	int ret = 0;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/devices.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/devices.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,93 @@
 #include <mach/iomap.h>
 #include <mach/dma.h>
 #include <mach/usb_phy.h>
+
 #include "gpio-names.h"
+#include "devices.h"
+
+static struct resource gpio_resource[] = {
+	[0] = {
+		.start	= TEGRA_GPIO_BASE,
+		.end	= TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_GPIO1,
+		.end	= INT_GPIO1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= INT_GPIO2,
+		.end	= INT_GPIO2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= INT_GPIO3,
+		.end	= INT_GPIO3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= INT_GPIO4,
+		.end	= INT_GPIO4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[5] = {
+		.start	= INT_GPIO5,
+		.end	= INT_GPIO5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= INT_GPIO6,
+		.end	= INT_GPIO6,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[7] = {
+		.start	= INT_GPIO7,
+		.end	= INT_GPIO7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_gpio_device = {
+	.name		= "tegra-gpio",
+	.id		= -1,
+	.resource	= gpio_resource,
+	.num_resources	= ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+	[0] = {
+		/* Tri-state registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x14,
+		.end	= TEGRA_APB_MISC_BASE + 0x20 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* Mux registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x80,
+		.end	= TEGRA_APB_MISC_BASE + 0x9c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		/* Pull-up/down registers */
+		.start	= TEGRA_APB_MISC_BASE + 0xa0,
+		.end	= TEGRA_APB_MISC_BASE + 0xb0 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		/* Pad control registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x868,
+		.end	= TEGRA_APB_MISC_BASE + 0x90c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_pinmux_device = {
+	.name		= "tegra-pinmux",
+	.id		= -1,
+	.resource	= pinmux_resource,
+	.num_resources	= ARRAY_SIZE(pinmux_resource),
+};
 
 static struct resource i2c_resource1[] = {
 	[0] = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/devices.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/devices.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/devices.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/devices.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 
 #include <linux/platform_device.h>
 
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
 extern struct platform_device tegra_sdhci_device1;
 extern struct platform_device tegra_sdhci_device2;
 extern struct platform_device tegra_sdhci_device3;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/dma.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/dma.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,13 +105,17 @@
 
 #define NV_DMA_MAX_TRASFER_SIZE 0x10000
 
-const unsigned int ahb_addr_wrap_table[8] = {
+static const unsigned int ahb_addr_wrap_table[8] = {
 	0, 32, 64, 128, 256, 512, 1024, 2048
 };
 
-const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+static const unsigned int apb_addr_wrap_table[8] = {
+	0, 1, 2, 4, 8, 16, 32, 64
+};
 
-const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+static const unsigned int bus_width_table[5] = {
+	8, 16, 32, 64, 128
+};
 
 #define TEGRA_DMA_NAME_SIZE 16
 struct tegra_dma_channel {
@@ -157,7 +161,7 @@ void tegra_dma_dequeue(struct tegra_dma_
 	return;
 }
 
-void tegra_dma_stop(struct tegra_dma_channel *ch)
+static void tegra_dma_stop(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	u32 status;
@@ -174,7 +178,7 @@ void tegra_dma_stop(struct tegra_dma_cha
 		writel(status, ch->addr + APB_DMA_CHAN_STA);
 }
 
-int tegra_dma_cancel(struct tegra_dma_channel *ch)
+static int tegra_dma_cancel(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	unsigned long irq_flags;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #include <mach/io.h>
 #include <mach/iomap.h>
 
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
         ldr     \rp, =IO_APB_PHYS       @ physical
         ldr     \rv, =IO_APB_VIRT        @ virtual
 	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,60 +1 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_GPIO_H
-#define __MACH_TEGRA_GPIO_H
-
-#include <linux/init.h>
-#include <mach/irqs.h>
-
-#define TEGRA_NR_GPIOS		INT_GPIO_NR
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value		__gpio_get_value
-#define gpio_set_value		__gpio_set_value
-#define gpio_cansleep		__gpio_cansleep
-
-#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
-#define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-	if (gpio < TEGRA_NR_GPIOS)
-		return INT_GPIO_BASE + gpio;
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-	if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
-		return irq - INT_GPIO_BASE;
-	return -EINVAL;
-}
-
-struct tegra_gpio_table {
-	int	gpio;	/* GPIO number */
-	bool	enable;	/* Enable for GPIO at init? */
-};
-
-void tegra_gpio_config(struct tegra_gpio_table *table, int num);
-void tegra_gpio_enable(int gpio);
-void tegra_gpio_disable(int gpio);
-
-#endif
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/gpio-tegra.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/gpio-tegra.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/gpio-tegra.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/gpio-tegra.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_GPIO_TEGRA_H
+#define __MACH_TEGRA_GPIO_TEGRA_H
+
+#include <linux/types.h>
+#include <mach/irqs.h>
+
+#define TEGRA_NR_GPIOS		INT_GPIO_NR
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+
+struct tegra_gpio_table {
+	int	gpio;	/* GPIO number */
+	bool	enable;	/* Enable for GPIO at init? */
+};
+
+void tegra_gpio_config(struct tegra_gpio_table *table, int num);
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,20 +33,26 @@
  *
  */
 
+#ifdef __ASSEMBLY__
+#define IOMEM(x)	(x)
+#else
+#define IOMEM(x)	((void __force __iomem *)(x))
+#endif
+
 #define IO_IRAM_PHYS	0x40000000
-#define IO_IRAM_VIRT	0xFE400000
+#define IO_IRAM_VIRT	IOMEM(0xFE400000)
 #define IO_IRAM_SIZE	SZ_256K
 
 #define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     0xFE000000
+#define IO_CPU_VIRT     IOMEM(0xFE000000)
 #define IO_CPU_SIZE	SZ_16K
 
 #define IO_PPSB_PHYS	0x60000000
-#define IO_PPSB_VIRT	0xFE200000
+#define IO_PPSB_VIRT	IOMEM(0xFE200000)
 #define IO_PPSB_SIZE	SZ_1M
 
 #define IO_APB_PHYS	0x70000000
-#define IO_APB_VIRT	0xFE300000
+#define IO_APB_VIRT	IOMEM(0xFE300000)
 #define IO_APB_SIZE	SZ_1M
 
 #define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
@@ -61,7 +67,7 @@
 		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
 	IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?		\
 		IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :	\
-	0)
+	NULL)
 
 #ifndef __ASSEMBLER__
 
@@ -71,7 +77,7 @@
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
 
-#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
 
 #ifdef CONFIG_TEGRA_PCI
 extern void __iomem *tegra_pcie_io_base;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/memory.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_MEMORY_H
-#define __MACH_TEGRA_MEMORY_H
-
-/* physical offset of RAM */
-#define PLAT_PHYS_OFFSET		UL(0)
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/pinmux.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/pinmux.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/pinmux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/pinmux.h	2012-01-04 18:55:44.000000000 -0500
@@ -199,6 +199,7 @@ struct tegra_drive_pingroup_config {
 
 struct tegra_drive_pingroup_desc {
 	const char *name;
+	s16 reg_bank;
 	s16 reg;
 };
 
@@ -207,6 +208,9 @@ struct tegra_pingroup_desc {
 	int funcs[4];
 	int func_safe;
 	int vddio;
+	s16 tri_bank;	/* Register bank the tri_reg exists within */
+	s16 mux_bank;	/* Register bank the mux_reg exists within */
+	s16 pupd_bank;	/* Register bank the pupd_reg exists within */
 	s16 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
 	s16 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
 	s16 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/powergate.h linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/powergate.h
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/include/mach/powergate.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/include/mach/powergate.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,6 @@
 
 int tegra_powergate_power_on(int id);
 int tegra_powergate_power_off(int id);
-bool tegra_powergate_is_powered(int id);
 int tegra_powergate_remove_clamping(int id);
 
 /* Must be called with clk disabled, and returns with clk enabled */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/io.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/io.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,25 +31,25 @@
 
 static struct map_desc tegra_io_desc[] __initdata = {
 	{
-		.virtual = IO_PPSB_VIRT,
+		.virtual = (unsigned long)IO_PPSB_VIRT,
 		.pfn = __phys_to_pfn(IO_PPSB_PHYS),
 		.length = IO_PPSB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_APB_VIRT,
+		.virtual = (unsigned long)IO_APB_VIRT,
 		.pfn = __phys_to_pfn(IO_APB_PHYS),
 		.length = IO_APB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_CPU_VIRT,
+		.virtual = (unsigned long)IO_CPU_VIRT,
 		.pfn = __phys_to_pfn(IO_CPU_PHYS),
 		.length = IO_CPU_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_IRAM_VIRT,
+		.virtual = (unsigned long)IO_IRAM_VIRT,
 		.pfn = __phys_to_pfn(IO_IRAM_PHYS),
 		.length = IO_IRAM_SIZE,
 		.type = MT_DEVICE,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-tegra/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -69,6 +69,12 @@ config MACH_WARIO
        help
          Support for the Wario version of Seaboard
 
+config MACH_VENTANA
+       bool "Ventana board"
+       select MACH_TEGRA_DT
+       help
+         Support for the nVidia Ventana development platform
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/Makefile linux-libre-3.2-gnu1/arch/arm/mach-tegra/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD}
 
 obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
 obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-tegra/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
-zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00008000
+zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	+= 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
 
 dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
 dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
+dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/pcie.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/pcie.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/sizes.h>
 #include <asm/mach/pci.h>
@@ -41,6 +42,8 @@
 #include <mach/clk.h>
 #include <mach/powergate.h>
 
+#include "board.h"
+
 /* register definitions */
 #define AFI_OFFSET	0x3800
 #define PADS_OFFSET	0x3000
@@ -150,9 +153,9 @@
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 /*
  * Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -460,7 +463,7 @@ static struct pci_bus __init *tegra_pcie
 	struct tegra_pcie_port *pp;
 
 	if (nr >= tegra_pcie.num_ports)
-		return 0;
+		return NULL;
 
 	pp = tegra_pcie.port + nr;
 	pp->root_bus_nr = sys->busnr;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/pinmux.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/pinmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
@@ -169,15 +170,17 @@ static const char *pupd_name(unsigned lo
 	}
 }
 
+static int nbanks;
+static void __iomem **regs;
 
-static inline unsigned long pg_readl(unsigned long offset)
+static inline u32 pg_readl(u32 bank, u32 reg)
 {
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	return readl(regs[bank] + reg);
 }
 
-static inline void pg_writel(unsigned long value, unsigned long offset)
+static inline void pg_writel(u32 val, u32 bank, u32 reg)
 {
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	writel(val, regs[bank] + reg);
 }
 
 static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@@ -217,10 +220,10 @@ static int tegra_pinmux_set_func(const s
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].mux_reg);
+	reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 	reg &= ~(0x3 << pingroups[pg].mux_bit);
 	reg |= mux << pingroups[pg].mux_bit;
-	pg_writel(reg, pingroups[pg].mux_reg);
+	pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -241,11 +244,11 @@ int tegra_pinmux_set_tristate(enum tegra
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].tri_reg);
+	reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 	reg &= ~(0x1 << pingroups[pg].tri_bit);
 	if (tristate)
 		reg |= 1 << pingroups[pg].tri_bit;
-	pg_writel(reg, pingroups[pg].tri_reg);
+	pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -272,10 +275,10 @@ int tegra_pinmux_set_pullupdown(enum teg
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].pupd_reg);
+	reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 	reg &= ~(0x3 << pingroups[pg].pupd_bit);
 	reg |= pupd << pingroups[pg].pupd_bit;
-	pg_writel(reg, pingroups[pg].pupd_reg);
+	pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -362,12 +365,12 @@ static int tegra_drive_pinmux_set_hsm(en
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (hsm == TEGRA_HSM_ENABLE)
 		reg |= (1 << 2);
 	else
 		reg &= ~(1 << 2);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -387,12 +390,12 @@ static int tegra_drive_pinmux_set_schmit
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (schmitt == TEGRA_SCHMITT_ENABLE)
 		reg |= (1 << 3);
 	else
 		reg &= ~(1 << 3);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -412,10 +415,10 @@ static int tegra_drive_pinmux_set_drive(
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 4);
 	reg |= drive << 4;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -435,10 +438,10 @@ static int tegra_drive_pinmux_set_pull_d
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_down << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -458,10 +461,10 @@ static int tegra_drive_pinmux_set_pull_u
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_up << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -481,10 +484,10 @@ static int tegra_drive_pinmux_set_slew_r
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 28);
 	reg |= slew_rising << 28;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -504,10 +507,10 @@ static int tegra_drive_pinmux_set_slew_f
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 30);
 	reg |= slew_falling << 30;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -665,6 +668,99 @@ void tegra_pinmux_config_pullupdown_tabl
 	}
 }
 
+static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int i;
+	int config_bad = 0;
+
+	for (i = 0; ; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+	}
+	nbanks = i;
+
+	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		if (pingroups[i].tri_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].mux_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].pupd_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+		if (drive_pingroups[i].reg_bank >= nbanks) {
+			dev_err(&pdev->dev,
+				"drive pingroup %d: bad reg_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	if (config_bad)
+		return -ENODEV;
+
+	regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
+	if (!regs) {
+		dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < nbanks; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing MEM resource\n");
+			return -ENODEV;
+		}
+
+		if (!devm_request_mem_region(&pdev->dev, res->start,
+					    resource_size(res),
+					    dev_name(&pdev->dev))) {
+			dev_err(&pdev->dev,
+				"Couldn't request MEM resource %d\n", i);
+			return -ENODEV;
+		}
+
+		regs[i] = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+		if (!regs) {
+			dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-pinmux", },
+	{ },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+	.driver		= {
+		.name	= "tegra-pinmux",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_pinmux_of_match,
+	},
+	.probe		= tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+	return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
 #ifdef	CONFIG_DEBUG_FS
 
 #include <linux/debugfs.h>
@@ -684,6 +780,7 @@ static int dbg_pinmux_show(struct seq_fi
 	int len;
 
 	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		unsigned long reg;
 		unsigned long tri;
 		unsigned long mux;
 		unsigned long pupd;
@@ -696,8 +793,9 @@ static int dbg_pinmux_show(struct seq_fi
 			seq_printf(s, "TEGRA_MUX_NONE");
 			len = strlen("NONE");
 		} else {
-			mux = (pg_readl(pingroups[i].mux_reg) >>
-			       pingroups[i].mux_bit) & 0x3;
+			reg = pg_readl(pingroups[i].mux_bank,
+					pingroups[i].mux_reg);
+			mux = (reg >> pingroups[i].mux_bit) & 0x3;
 			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
 				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
 				len = 5;
@@ -713,8 +811,9 @@ static int dbg_pinmux_show(struct seq_fi
 			seq_printf(s, "TEGRA_PUPD_NORMAL");
 			len = strlen("NORMAL");
 		} else {
-			pupd = (pg_readl(pingroups[i].pupd_reg) >>
-				pingroups[i].pupd_bit) & 0x3;
+			reg = pg_readl(pingroups[i].pupd_bank,
+					pingroups[i].pupd_reg);
+			pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
 			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
 			len = strlen(pupd_name(pupd));
 		}
@@ -723,8 +822,9 @@ static int dbg_pinmux_show(struct seq_fi
 		if (pingroups[i].tri_reg < 0) {
 			seq_printf(s, "TEGRA_TRI_NORMAL");
 		} else {
-			tri = (pg_readl(pingroups[i].tri_reg) >>
-			       pingroups[i].tri_bit) & 0x1;
+			reg = pg_readl(pingroups[i].tri_bank,
+					pingroups[i].tri_reg);
+			tri = (reg >> pingroups[i].tri_bit) & 0x1;
 
 			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
 		}
@@ -759,7 +859,8 @@ static int dbg_drive_pinmux_show(struct
 		dbg_pad_field(s, 7 - len);
 
 
-		reg = pg_readl(drive_pingroups[i].reg);
+		reg = pg_readl(drive_pingroups[i].reg_bank,
+				drive_pingroups[i].reg);
 		if (HSM_EN(reg)) {
 			seq_printf(s, "TEGRA_HSM_ENABLE");
 			len = 16;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/pinmux-t2-tables.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/pinmux-t2-tables.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/pinmux-t2-tables.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/pinmux-t2-tables.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,10 +31,16 @@
 #include <mach/pinmux.h>
 #include <mach/suspend.h>
 
+#define TRISTATE_REG_A		0x14
+#define PIN_MUX_CTL_REG_A	0x80
+#define PULLUPDOWN_REG_A	0xa0
+#define PINGROUP_REG_A		0x868
+
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
 		.name = #pg_name,				\
-		.reg = r					\
+		.reg_bank = 3,					\
+		.reg = ((r) - PINGROUP_REG_A)			\
 	}
 
 const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@@ -90,11 +96,14 @@ const struct tegra_drive_pingroup_desc t
 			TEGRA_MUX_ ## f3,			\
 		},						\
 		.func_safe = TEGRA_MUX_ ## f_safe,		\
-		.tri_reg = tri_r,				\
+		.tri_bank = 0,					\
+		.tri_reg = ((tri_r) - TRISTATE_REG_A),		\
 		.tri_bit = tri_b,				\
-		.mux_reg = mux_r,				\
+		.mux_bank = 1,					\
+		.mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),	\
 		.mux_bit = mux_b,				\
-		.pupd_reg = pupd_r,				\
+		.pupd_bank = 2,				\
+		.pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),	\
 		.pupd_bit = pupd_b,				\
 	}
 
@@ -217,62 +226,3 @@ const struct tegra_pingroup_desc tegra_s
 	PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
 	PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
 };
-
-#ifdef CONFIG_PM
-#define TRISTATE_REG_A         0x14
-#define TRISTATE_REG_NUM       4
-#define PIN_MUX_CTL_REG_A      0x80
-#define PIN_MUX_CTL_REG_NUM    8
-#define PULLUPDOWN_REG_A       0xa0
-#define PULLUPDOWN_REG_NUM     5
-
-static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		      PULLUPDOWN_REG_NUM +
-		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
-
-static inline unsigned long pg_readl(unsigned long offset)
-{
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-static inline void pg_writel(unsigned long value, unsigned long offset)
-{
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-void tegra_pinmux_suspend(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
-}
-
-void tegra_pinmux_resume(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		pg_writel(*ctx++, TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
-}
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,10 +114,10 @@ void __init smp_init_cpus(void)
 {
 	unsigned int i, ncores = scu_get_core_count(scu_base);
 
-	if (ncores > NR_CPUS) {
-		printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
-			ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/powergate.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/powergate.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/powergate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/powergate.c	2012-01-04 18:55:44.000000000 -0500
@@ -89,12 +89,11 @@ int tegra_powergate_power_off(int id)
 	return tegra_powergate_set(id, false);
 }
 
-bool tegra_powergate_is_powered(int id)
+static bool tegra_powergate_is_powered(int id)
 {
 	u32 status;
 
-	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
-		return -EINVAL;
+	WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
 
 	status = pmc_read(PWRGATE_STATUS) & (1 << id);
 	return !!status;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/tegra2_clocks.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/tegra2_clocks.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/tegra2_clocks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/tegra2_clocks.c	2012-01-04 18:55:44.000000000 -0500
@@ -166,13 +166,13 @@ static DEFINE_SPINLOCK(clock_register_lo
 static int tegra_periph_clk_enable_refcount[3 * 32];
 
 #define clk_writel(value, reg) \
-	__raw_writel(value, (u32)reg_clk_base + (reg))
+	__raw_writel(value, reg_clk_base + (reg))
 #define clk_readl(reg) \
-	__raw_readl((u32)reg_clk_base + (reg))
+	__raw_readl(reg_clk_base + (reg))
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 unsigned long clk_measure_input_freq(void)
 {
@@ -918,7 +918,7 @@ static struct clk_ops tegra_pll_div_ops
 static void tegra2_periph_clk_init(struct clk *c)
 {
 	u32 val = clk_readl(c->reg);
-	const struct clk_mux_sel *mux = 0;
+	const struct clk_mux_sel *mux = NULL;
 	const struct clk_mux_sel *sel;
 	if (c->flags & MUX) {
 		for (sel = c->inputs; sel->input != NULL; sel++) {
@@ -1459,7 +1459,7 @@ static struct clk tegra_pll_s = {
 static struct clk_mux_sel tegra_clk_m_sel[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
 	{ .input = &tegra_pll_s,  .value = 1},
-	{ 0, 0},
+	{ NULL , 0},
 };
 
 static struct clk tegra_clk_m = {
@@ -1861,7 +1861,7 @@ static const struct audio_sources {
 	{ .name = "ext_audio_clk1", .value = 6 },
 	{ .name = "ext_vimclk", .value = 7 },
 #endif
-	{ 0, 0 }
+	{ NULL, 0 }
 };
 
 static struct clk tegra_clk_audio = {
@@ -1885,7 +1885,7 @@ static struct clk tegra_clk_audio_2x = {
 	},
 };
 
-struct clk_lookup tegra_audio_clk_lookups[] = {
+static struct clk_lookup tegra_audio_clk_lookups[] = {
 	{ .con_id = "audio", .clk = &tegra_clk_audio },
 	{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
 };
@@ -1926,7 +1926,7 @@ static struct clk_mux_sel mux_cclk[] = {
 	{ .input = &tegra_pll_p_out3,	.value = 6},
 	{ .input = &tegra_clk_d,	.value = 7},
 	{ .input = &tegra_pll_x,	.value = 8},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_sclk[] = {
@@ -1938,7 +1938,7 @@ static struct clk_mux_sel mux_sclk[] = {
 	{ .input = &tegra_clk_d,	.value = 5},
 	{ .input = &tegra_clk_32k,	.value = 6},
 	{ .input = &tegra_pll_m_out1,	.value = 7},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_cclk = {
@@ -2009,7 +2009,7 @@ static struct clk_mux_sel mux_pllm_pllc_
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_pll_a_out0, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
@@ -2017,7 +2017,7 @@ static struct clk_mux_sel mux_pllm_pllc_
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
@@ -2025,7 +2025,7 @@ static struct clk_mux_sel mux_pllp_pllc_
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_m, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
@@ -2033,7 +2033,7 @@ static struct clk_mux_sel mux_pllaout0_a
 	{.input = &tegra_clk_audio_2x, .value = 1},
 	{.input = &tegra_pll_p, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
@@ -2041,7 +2041,7 @@ static struct clk_mux_sel mux_pllp_plld_
 	{.input = &tegra_pll_d_out0, .value = 1},
 	{.input = &tegra_pll_c, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
@@ -2050,39 +2050,39 @@ static struct clk_mux_sel mux_pllp_pllc_
 	{.input = &tegra_clk_audio,     .value = 2},
 	{.input = &tegra_clk_m,     .value = 3},
 	{.input = &tegra_clk_32k,   .value = 4},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
 	{.input = &tegra_pll_p,     .value = 0},
 	{.input = &tegra_pll_c,     .value = 1},
 	{.input = &tegra_pll_m,     .value = 2},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_m[] = {
 	{ .input = &tegra_clk_m, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_out3[] = {
 	{ .input = &tegra_pll_p_out3, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_plld[] = {
 	{ .input = &tegra_pll_d, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_32k[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pclk[] = {
 	{ .input = &tegra_clk_pclk, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_emc = {
@@ -2125,7 +2125,7 @@ static struct clk tegra_clk_emc = {
 		.parent = _parent,			\
 	}
 
-struct clk tegra_list_clks[] = {
+static struct clk tegra_list_clks[] = {
 	PERIPH_CLK("apbdma",	"tegra-dma",		NULL,	34,	0,	108000000, mux_pclk,			0),
 	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET),
 	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
@@ -2221,7 +2221,7 @@ struct clk tegra_list_clks[] = {
  * configuration.  List those here to register them twice in the clock lookup
  * table under two names.
  */
-struct clk_duplicate tegra_clk_duplicates[] = {
+static struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("uarta",	"tegra_uart.0",	NULL),
 	CLK_DUPLICATE("uartb",	"tegra_uart.1",	NULL),
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
@@ -2252,7 +2252,7 @@ struct clk_duplicate tegra_clk_duplicate
 		.clk = ck,	\
 	}
 
-struct clk *tegra_ptr_clks[] = {
+static struct clk *tegra_ptr_clks[] = {
 	&tegra_clk_32k,
 	&tegra_pll_s,
 	&tegra_clk_m,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/timer.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,9 +62,9 @@ static struct timespec persistent_ts;
 static u64 persistent_ms, last_persistent_ms;
 
 #define timer_writel(value, reg) \
-	__raw_writel(value, (u32)timer_reg_base + (reg))
+	__raw_writel(value, timer_reg_base + (reg))
 #define timer_readl(reg) \
-	__raw_readl((u32)timer_reg_base + (reg))
+	__raw_readl(timer_reg_base + (reg))
 
 static int tegra_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
@@ -133,7 +133,7 @@ static void notrace tegra_update_sched_c
  * tegra_rtc driver could be executing to avoid race conditions
  * on the RTC shadow register
  */
-u64 tegra_rtc_read_ms(void)
+static u64 tegra_rtc_read_ms(void)
 {
 	u32 ms = readl(rtc_base + RTC_MILLISECONDS);
 	u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-tegra/usb_phy.c linux-libre-3.2-gnu1/arch/arm/mach-tegra/usb_phy.c
--- linux-libre-3.1-gnu1/arch/arm/mach-tegra/usb_phy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-tegra/usb_phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
+#include <mach/gpio-tegra.h>
 #include <mach/usb_phy.h>
 #include <mach/iomap.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/core.c linux-libre-3.2-gnu1/arch/arm/mach-u300/core.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,9 @@
 #include <linux/err.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -37,6 +40,7 @@
 #include <mach/hardware.h>
 #include <mach/syscon.h>
 #include <mach/dma_channels.h>
+#include <mach/gpio-u300.h>
 
 #include "clock.h"
 #include "mmc.h"
@@ -68,30 +72,13 @@ static struct map_desc u300_io_desc[] __
 		.length		= SZ_32K,
 		.type		= MT_DEVICE,
 	},
-	{
-		.virtual	= 0xffff2000, /* TCM memory */
-		.pfn		= __phys_to_pfn(0xffff2000),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	},
-
-	/*
-	 * This overlaps with the IRQ vectors etc at 0xffff0000, so these
-	 * may have to be moved to 0x00000000 in order to use the ROM.
-	 */
-	/*
-	{
-		.virtual	= U300_BOOTROM_VIRT_BASE,
-		.pfn		= __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
-		.length		= SZ_64K,
-		.type		= MT_ROM,
-	},
-	*/
 };
 
 void __init u300_map_io(void)
 {
 	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+	/* We enable a real big DMA buffer if need be. */
+	init_consistent_dma_size(SZ_4M);
 }
 
 /*
@@ -239,7 +226,7 @@ static struct resource gpio_resources[]
 		.end   = IRQ_U300_GPIO_PORT2,
 		.flags = IORESOURCE_IRQ,
 	},
-#ifdef U300_COH901571_3
+#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
 	{
 		.name  = "gpio3",
 		.start = IRQ_U300_GPIO_PORT3,
@@ -252,6 +239,7 @@ static struct resource gpio_resources[]
 		.end   = IRQ_U300_GPIO_PORT4,
 		.flags = IORESOURCE_IRQ,
 	},
+#endif
 #ifdef CONFIG_MACH_U300_BS335
 	{
 		.name  = "gpio5",
@@ -266,7 +254,6 @@ static struct resource gpio_resources[]
 		.flags = IORESOURCE_IRQ,
 	},
 #endif /* CONFIG_MACH_U300_BS335 */
-#endif /* U300_COH901571_3 */
 };
 
 static struct resource keypad_resources[] = {
@@ -361,51 +348,6 @@ static struct resource wdog_resources[]
 	}
 };
 
-/* TODO: These should be protected by suitable #ifdef's */
-static struct resource ave_resources[] = {
-	{
-		.name  = "AVE3e I/O Area",
-		.start = U300_VIDEOENC_BASE,
-		.end   = U300_VIDEOENC_BASE + SZ_512K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e IRQ0",
-		.start = IRQ_U300_VIDEO_ENC_0,
-		.end   = IRQ_U300_VIDEO_ENC_0,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e IRQ1",
-		.start = IRQ_U300_VIDEO_ENC_1,
-		.end   = IRQ_U300_VIDEO_ENC_1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e Physmem Area",
-		.start = 0, /* 0 will be remapped to reserved memory */
-		.end   = SZ_1M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	/*
-	 * The AVE3e requires two regions of 256MB that it considers
-	 * "invisible". The hardware will not be able to access these
-	 * addresses, so they should never point to system RAM.
-	 */
-	{
-		.name  = "AVE3e Reserved 0",
-		.start = 0xd0000000,
-		.end   = 0xd0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e Reserved 1",
-		.start = 0xe0000000,
-		.end   = 0xe0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
 static struct resource dma_resource[] = {
 	{
 		.start = U300_DMAC_BASE,
@@ -1535,6 +1477,14 @@ static struct coh901318_platform coh9013
 	.max_channels = U300_DMA_CHANNELS,
 };
 
+static struct resource pinmux_resources[] = {
+	{
+		.start = U300_SYSCON_BASE,
+		.end   = U300_SYSCON_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
 static struct platform_device wdog_device = {
 	.name = "coh901327_wdog",
 	.id = -1,
@@ -1556,11 +1506,35 @@ static struct platform_device i2c1_devic
 	.resource = i2c1_resources,
 };
 
+/*
+ * The different variants have a few different versions of the
+ * GPIO block, with different number of ports.
+ */
+static struct u300_gpio_platform u300_gpio_plat = {
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+	.variant = U300_GPIO_COH901335,
+	.ports = 3,
+#endif
+#ifdef CONFIG_MACH_U300_BS335
+	.variant = U300_GPIO_COH901571_3_BS335,
+	.ports = 7,
+#endif
+#ifdef CONFIG_MACH_U300_BS365
+	.variant = U300_GPIO_COH901571_3_BS365,
+	.ports = 5,
+#endif
+	.gpio_base = 0,
+	.gpio_irq_base = IRQ_U300_GPIO_BASE,
+};
+
 static struct platform_device gpio_device = {
 	.name = "u300-gpio",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(gpio_resources),
 	.resource = gpio_resources,
+	.dev = {
+		.platform_data = &u300_gpio_plat,
+	},
 };
 
 static struct platform_device keypad_device = {
@@ -1612,13 +1586,6 @@ static struct platform_device nand_devic
 	},
 };
 
-static struct platform_device ave_device = {
-	.name = "video_enc",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(ave_resources),
-	.resource = ave_resources,
-};
-
 static struct platform_device dma_device = {
 	.name		= "coh901318",
 	.id		= -1,
@@ -1630,6 +1597,72 @@ static struct platform_device dma_device
 	},
 };
 
+static struct platform_device pinmux_device = {
+	.name = "pinmux-u300",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(pinmux_resources),
+	.resource = pinmux_resources,
+};
+
+/* Pinmux settings */
+static struct pinmux_map u300_pinmux_map[] = {
+	/* anonymous maps for chip power and EMIFs */
+	PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
+	PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
+	PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"),
+	/* per-device maps for MMC/SD, SPI and UART */
+	PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"),
+	PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"),
+	PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"),
+};
+
+struct u300_mux_hog {
+	const char *name;
+	struct device *dev;
+	struct pinmux *pmx;
+};
+
+static struct u300_mux_hog u300_mux_hogs[] = {
+	{
+		.name = "uart0",
+		.dev = &uart0_device.dev,
+	},
+	{
+		.name = "spi0",
+		.dev = &pl022_device.dev,
+	},
+	{
+		.name = "mmc0",
+		.dev = &mmcsd_device.dev,
+	},
+};
+
+static int __init u300_pinmux_fetch(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) {
+		struct pinmux *pmx;
+		int ret;
+
+		pmx = pinmux_get(u300_mux_hogs[i].dev, NULL);
+		if (IS_ERR(pmx)) {
+			pr_err("u300: could not get pinmux hog %s\n",
+			       u300_mux_hogs[i].name);
+			continue;
+		}
+		ret = pinmux_enable(pmx);
+		if (ret) {
+			pr_err("u300: could enable pinmux hog %s\n",
+			       u300_mux_hogs[i].name);
+			continue;
+		}
+		u300_mux_hogs[i].pmx = pmx;
+	}
+	return 0;
+}
+subsys_initcall(u300_pinmux_fetch);
+
 /*
  * Notice that AMBA devices are initialized before platform devices.
  *
@@ -1643,10 +1676,9 @@ static struct platform_device *platform_
 	&gpio_device,
 	&nand_device,
 	&wdog_device,
-	&ave_device
+	&pinmux_device,
 };
 
-
 /*
  * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
  * together so some interrupts are connected to the first one and some
@@ -1666,7 +1698,7 @@ void __init u300_init_irq(void)
 	BUG_ON(IS_ERR(clk));
 	clk_enable(clk);
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < U300_VIC_IRQS_END; i++)
 		set_bit(i, (unsigned long *) &mask[0]);
 	vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
 	vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
@@ -1828,6 +1860,10 @@ void __init u300_init_devices(void)
 
 	u300_assign_physmem();
 
+	/* Initialize pinmuxing */
+	pinmux_register_mappings(u300_pinmux_map,
+				 ARRAY_SIZE(u300_pinmux_map));
+
 	/* Register subdevices on the I2C buses */
 	u300_i2c_register_board_devices();
 
@@ -1837,17 +1873,10 @@ void __init u300_init_devices(void)
 	/* Register subdevices on the SPI bus */
 	u300_spi_register_board_devices();
 
-#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
-	/*
-	 * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
-	 * both subsystems are requesting this mode.
-	 * If we not share the Acc SDRAM, this is never the case. Therefore
-	 * enable it here from the App side.
-	 */
+	/* Enable SEMI self refresh */
 	val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
 		U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
 	writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
-#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
 }
 
 static int core_module_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/i2c.c linux-libre-3.2-gnu1/arch/arm/mach-u300/i2c.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,57 +256,8 @@ static struct ab3100_platform_data ab310
 };
 #endif
 
-#ifdef CONFIG_AB3550_CORE
-static struct abx500_init_settings ab3550_init_settings[] = {
-	{
-		.bank = 0,
-		.reg = AB3550_IMR1,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR2,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR3,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR4,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR5,
-		/* The two most significant bits are not used */
-		.setting = 0x3f
-	},
-};
-
-static struct ab3550_platform_data ab3550_plf_data = {
-	.irq = {
-		.base = IRQ_AB3550_BASE,
-		.count = (IRQ_AB3550_END - IRQ_AB3550_BASE + 1),
-	},
-	.dev_data = {
-	},
-	.init_settings = ab3550_init_settings,
-	.init_settings_sz = ARRAY_SIZE(ab3550_init_settings),
-};
-#endif
-
 static struct i2c_board_info __initdata bus0_i2c_board_info[] = {
-#if defined(CONFIG_AB3550_CORE)
-	{
-		.type = "ab3550",
-		.addr = 0x4A,
-		.irq = IRQ_U300_IRQ0_EXT,
-		.platform_data = &ab3550_plf_data,
-	},
-#elif defined(CONFIG_AB3100_CORE)
+#ifdef CONFIG_AB3100_CORE
 	{
 		.type = "ab3100",
 		.addr = 0x48,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	/* If we move the address using MMU, use this. */
 	ldr	\rp,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
 	ldr	\rv,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,294 +1 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/gpio.h
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * GPIO block resgister definitions and inline macros for
- * U300 GPIO COH 901 335 or COH 901 571/3
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#ifndef __MACH_U300_GPIO_H
-#define __MACH_U300_GPIO_H
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-/* Switch type depending on platform/chip variant */
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_COH901335
-#endif
-#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
-#define U300_COH901571_3
-#endif
-
-/* Get base address for regs here */
-#include "u300-regs.h"
-/* IRQ numbers */
-#include "irqs.h"
-
-/*
- * This is the GPIO block definitions. GPIO (General Purpose I/O) can be
- * used for anything, and often is. The event/enable etc figures are for
- * the lowermost pin (pin 0 on each port), shift this left to match your
- * pin if you're gonna use these values.
- */
-#ifdef U300_COH901335
-#define U300_GPIO_PORTX_SPACING				(0x1C)
-/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
-#define U300_GPIO_PXPDIR				(0x00)
-#define U300_GPIO_PXPDOR				(0x00)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR					(0x04)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV					(0x08)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN					(0x0C)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR					(0x10)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR					(0x14)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER					(0x18)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
-/* Control Register 32bit (R/W) */
-#define U300_GPIO_CR					(0x54)
-#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE			(0x00000001UL)
-/* three ports of 8 bits each = GPIO pins 0..23 */
-#define U300_GPIO_NUM_PORTS 3
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX	(U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-#ifdef U300_COH901571_3
-/*
- * Control Register 32bit (R/W)
- * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
- * gives the number of GPIO pins.
- * bit 8-2  (mask 0x000001FC) contains the core version ID.
- */
-#define U300_GPIO_CR					(0x00)
-#define U300_GPIO_CR_SYNC_SEL_ENABLE			(0x00000002UL)
-#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE			(0x00000001UL)
-#define U300_GPIO_PORTX_SPACING				(0x30)
-/* Port X Pin Data INPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDIR				(0x04)
-/* Port X Pin Data OUTPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDOR				(0x08)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR					(0x0C)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER					(0x10)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV					(0x14)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN					(0x18)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR					(0x1C)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR					(0x20)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
-#ifdef CONFIG_MACH_U300_BS335
-/* seven ports of 8 bits each = GPIO pins 0..55 */
-#define U300_GPIO_NUM_PORTS 7
-#else
-/* five ports of 8 bits each = GPIO pins 0..39 */
-#define U300_GPIO_NUM_PORTS 5
-#endif
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-/*
- * Individual pin assignments for the B26/S26. Notice that the
- * actual usage of these pins depends on the PAD MUX settings, that
- * is why the same number can potentially appear several times.
- * In the reference design each pin is only used for one purpose.
- * These were determined by inspecting the B26/S26 schematic:
- * 2/1911-ROA 128 1603
- */
-#ifdef CONFIG_MACH_U300_BS2X
-#define U300_GPIO_PIN_UART_RX		0
-#define U300_GPIO_PIN_UART_TX		1
-#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
-#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
-#define U300_GPIO_PIN_CAM_SLEEP		4
-#define U300_GPIO_PIN_CAM_REG_EN	5
-#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
-#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
-#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
-#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
-#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
-#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
-#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
-#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
-#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
-#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
-#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
-#endif
-
-/*
- * Individual pin assignments for the B330/S330 and B365/S365.
- * Notice that the actual usage of these pins depends on the
- * PAD MUX settings, that is why the same number can potentially
- * appear several times. In the reference design each pin is only
- * used for one purpose. These were determined by inspecting the
- * S365 schematic.
- */
-#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
-    defined(CONFIG_MACH_U300_BS335)
-#define U300_GPIO_PIN_UART_RX		0
-#define U300_GPIO_PIN_UART_TX		1
-#define U300_GPIO_PIN_UART_CTS		2
-#define U300_GPIO_PIN_UART_RTS		3
-#define U300_GPIO_PIN_CAM_MAIN_STANDBY	4 /* Camera MAIN standby */
-#define U300_GPIO_PIN_GPIO05		5 /* Unrouted */
-#define U300_GPIO_PIN_MS_CD		6 /* Memory Stick Card insertion */
-#define U300_GPIO_PIN_GPIO07		7 /* Test point TP2430 */
-
-#define U300_GPIO_PIN_GPIO08		8 /* Test point TP2437 */
-#define U300_GPIO_PIN_GPIO09		9 /* Test point TP2431 */
-#define U300_GPIO_PIN_GPIO10		10 /* Test point TP2432 */
-#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_CAM_SUB_STANDBY	13 /* Camera SUB standby */
-#define U300_GPIO_PIN_GPIO14		14 /* Test point TP2436 */
-#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16		16 /* Test point TP2438 */
-#define U300_GPIO_PIN_PHFSENSE		17 /* Headphone jack sensing */
-#define U300_GPIO_PIN_GPIO18		18 /* Test point TP2439 */
-#define U300_GPIO_PIN_GPIO19		19 /* Routed somewhere */
-#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO24		24 /* Unrouted */
-#define U300_GPIO_PIN_GPIO25		25 /* Unrouted */
-#define U300_GPIO_PIN_GPIO26		26 /* Unrouted */
-#define U300_GPIO_PIN_GPIO27		27 /* Unrouted */
-#define U300_GPIO_PIN_GPIO28		28 /* Unrouted */
-#define U300_GPIO_PIN_GPIO29		29 /* Unrouted */
-#define U300_GPIO_PIN_GPIO30		30 /* Unrouted */
-#define U300_GPIO_PIN_GPIO31		31 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO32		32 /* Unrouted */
-#define U300_GPIO_PIN_GPIO33		33 /* Unrouted */
-#define U300_GPIO_PIN_GPIO34		34 /* Unrouted */
-#define U300_GPIO_PIN_GPIO35		35 /* Unrouted */
-#define U300_GPIO_PIN_GPIO36		36 /* Unrouted */
-#define U300_GPIO_PIN_GPIO37		37 /* Unrouted */
-#define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
-#define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
-
-#ifdef CONFIG_MACH_U300_BS335
-
-#define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
-#define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
-#define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
-#define U300_GPIO_PIN_GPIO43		43 /* Unrouted */
-#define U300_GPIO_PIN_GPIO44		44 /* Unrouted */
-#define U300_GPIO_PIN_GPIO45		45 /* Unrouted */
-#define U300_GPIO_PIN_GPIO46		46 /* Unrouted */
-#define U300_GPIO_PIN_GPIO47		47 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO48		48 /* Unrouted */
-#define U300_GPIO_PIN_GPIO49		49 /* Unrouted */
-#define U300_GPIO_PIN_GPIO50		50 /* Unrouted */
-#define U300_GPIO_PIN_GPIO51		51 /* Unrouted */
-#define U300_GPIO_PIN_GPIO52		52 /* Unrouted */
-#define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
-#define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
-#define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
-#endif
-
-#endif
-
-/* translates a pin number to a port number */
-#define PIN_TO_PORT(val) (val >> 3)
-
-/* These can be found in arch/arm/mach-u300/gpio.c */
-extern int gpio_is_valid(int number);
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
-extern int gpio_register_callback(unsigned gpio,
-				  int (*func)(void *arg),
-				  void *);
-extern int gpio_unregister_callback(unsigned gpio);
-extern void enable_irq_on_gpio_pin(unsigned gpio, int edge);
-extern void disable_irq_on_gpio_pin(unsigned gpio);
-extern void gpio_pullup(unsigned gpio, int value);
-extern int gpio_get_value(unsigned gpio);
-extern void gpio_set_value(unsigned gpio, int value);
-
-#define gpio_get_value_cansleep gpio_get_value
-#define gpio_set_value_cansleep gpio_set_value
-
-/* wrappers to sleep-enable the previous two functions */
-static inline unsigned gpio_to_irq(unsigned gpio)
-{
-	return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0;
-}
-
-static inline unsigned irq_to_gpio(unsigned irq)
-{
-	/*
-	 * FIXME: This is no 1-1 mapping at all, it points to the
-	 * whole block of 8 pins.
-	 */
-	return (irq - IRQ_U300_GPIO_PORT0) << 3;
-}
-
-#endif
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/gpio-u300.h linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/gpio-u300.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/gpio-u300.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/gpio-u300.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_U300_H
+#define __MACH_U300_GPIO_U300_H
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
+#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP		4
+#define U300_GPIO_PIN_CAM_REG_EN	5
+#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
+#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+    defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_UART_CTS		2
+#define U300_GPIO_PIN_UART_RTS		3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY	4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05		5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD		6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07		7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08		8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09		9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10		10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY	13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14		14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE		17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18		18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19		19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24		24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25		25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26		26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27		27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28		28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29		29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30		30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31		31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32		32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33		33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34		34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35		35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36		36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37		37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43		43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44		44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45		45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46		46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47		47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48		48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49		49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50		50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51		51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52		52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
+#endif
+
+#endif
+
+/**
+ * enum u300_gpio_variant - the type of U300 GPIO employed
+ */
+enum u300_gpio_variant {
+	U300_GPIO_COH901335,
+	U300_GPIO_COH901571_3_BS335,
+	U300_GPIO_COH901571_3_BS365,
+};
+
+/**
+ * struct u300_gpio_platform - U300 GPIO platform data
+ * @variant: IP block variant
+ * @ports: number of GPIO block ports
+ * @gpio_base: first GPIO number for this block (use a free range)
+ * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
+ */
+struct u300_gpio_platform {
+	enum u300_gpio_variant variant;
+	u8 ports;
+	int gpio_base;
+	int gpio_irq_base;
+};
+
+#endif /* __MACH_U300_GPIO_U300_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,7 +72,7 @@
 
 /* DB3150 and DB3200 have only 45 IRQs */
 #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_NR_IRQS			45
+#define U300_VIC_IRQS_END		45
 #endif
 
 /* The DB3350-specific interrupt lines */
@@ -88,7 +88,7 @@
 #define IRQ_U300_GPIO_PORT4		53
 #define IRQ_U300_GPIO_PORT5		54
 #define IRQ_U300_GPIO_PORT6		55
-#define U300_NR_IRQS			56
+#define U300_VIC_IRQS_END		56
 #endif
 
 /* The DB3210-specific interrupt lines */
@@ -106,16 +106,17 @@
 #define IRQ_U300_NFIF			45
 #define IRQ_U300_NFIF2			46
 #define IRQ_U300_SYSCON_PLL_LOCK	47
-#define U300_NR_IRQS			48
+#define U300_VIC_IRQS_END		48
 #endif
 
-#ifdef CONFIG_AB3550_CORE
-#define IRQ_AB3550_BASE			(U300_NR_IRQS)
-#define IRQ_AB3550_END			(IRQ_AB3550_BASE + 37)
-
-#define NR_IRQS				(IRQ_AB3550_END + 1)
+/* Maximum 8*7 GPIO lines */
+#ifdef CONFIG_GPIO_U300
+#define IRQ_U300_GPIO_BASE		(U300_VIC_IRQS_END)
+#define IRQ_U300_GPIO_END		(IRQ_U300_GPIO_BASE + 56)
 #else
-#define NR_IRQS U300_NR_IRQS
+#define IRQ_U300_GPIO_END		(U300_VIC_IRQS_END)
 #endif
 
+#define NR_IRQS				(IRQ_U300_GPIO_END)
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,30 +13,7 @@
 #ifndef __MACH_MEMORY_H
 #define __MACH_MEMORY_H
 
-#ifdef CONFIG_MACH_U300_DUAL_RAM
-
-#define PLAT_PHYS_OFFSET		UL(0x48000000)
-#define BOOT_PARAMS_OFFSET	(PHYS_OFFSET + 0x100)
-
-#else
-
-#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#else
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#endif
-#define BOOT_PARAMS_OFFSET (0x28000000 + \
-	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE +		\
-	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
-#endif
-
-/*
- * We enable a real big DMA buffer if need be.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
+#define PLAT_PHYS_OFFSET	UL(0x48000000)
+#define BOOT_PARAMS_OFFSET	0x100
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/syscon.h linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/syscon.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/include/mach/syscon.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/include/mach/syscon.h	2012-01-04 18:55:44.000000000 -0500
@@ -234,91 +234,6 @@
 #define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE	(0x0004)
 #define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE		(0x0002)
 #define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE		(0x0001)
-/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
-#define U300_SYSCON_PMC1LR					(0x007C)
-#define U300_SYSCON_PMC1LR_MASK					(0xFFFF)
-#define U300_SYSCON_PMC1LR_CDI_MASK				(0xC000)
-#define U300_SYSCON_PMC1LR_CDI_CDI				(0x0000)
-#define U300_SYSCON_PMC1LR_CDI_EMIF				(0x4000)
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_SYSCON_PMC1LR_CDI_CDI2				(0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO			(0xC000)
-#elif CONFIG_MACH_U300_BS365
-#define U300_SYSCON_PMC1LR_CDI_GPIO				(0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA				(0xC000)
-#endif
-#define U300_SYSCON_PMC1LR_PDI_MASK				(0x3000)
-#define U300_SYSCON_PMC1LR_PDI_PDI				(0x0000)
-#define U300_SYSCON_PMC1LR_PDI_EGG				(0x1000)
-#define U300_SYSCON_PMC1LR_PDI_WCDMA				(0x3000)
-#define U300_SYSCON_PMC1LR_MMCSD_MASK				(0x0C00)
-#define U300_SYSCON_PMC1LR_MMCSD_MMCSD				(0x0000)
-#define U300_SYSCON_PMC1LR_MMCSD_MSPRO				(0x0400)
-#define U300_SYSCON_PMC1LR_MMCSD_DSP				(0x0800)
-#define U300_SYSCON_PMC1LR_MMCSD_WCDMA				(0x0C00)
-#define U300_SYSCON_PMC1LR_ETM_MASK				(0x0300)
-#define U300_SYSCON_PMC1LR_ETM_ACC				(0x0000)
-#define U300_SYSCON_PMC1LR_ETM_APP				(0x0100)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK			(0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF			(0x0040)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM			(0x0080)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB		(0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK			(0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF			(0x0010)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM			(0x0020)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI			(0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK			(0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF			(0x0004)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM			(0x0008)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI			(0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_MASK				(0x0003)
-#define U300_SYSCON_PMC1LR_EMIF_1_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0			(0x0001)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1			(0x0002)
-#define U300_SYSCON_PMC1LR_EMIF_1				(0x0003)
-/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
-#define U300_SYSCON_PMC1HR					(0x007E)
-#define U300_SYSCON_PMC1HR_MASK					(0xFFFF)
-#define U300_SYSCON_PMC1HR_MISC_2_MASK				(0xC000)
-#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_MISC_2_MSPRO				(0x4000)
-#define U300_SYSCON_PMC1HR_MISC_2_DSP				(0x8000)
-#define U300_SYSCON_PMC1HR_MISC_2_AAIF				(0xC000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK			(0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF			(0x1000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP			(0x2000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF			(0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK			(0x0C00)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC			(0x0400)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP			(0x0800)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF			(0x0C00)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK			(0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO		(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI			(0x0100)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF			(0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK			(0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO		(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI			(0x0040)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF			(0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK			(0x0030)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI			(0x0010)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP			(0x0020)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF			(0x0030)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK			(0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0			(0x0004)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS			(0x0008)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF			(0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK			(0x0003)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0			(0x0001)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF			(0x0003)
 /* Step one for killing the applications system 16bit (-/W) */
 #define U300_SYSCON_KA1R					(0x0080)
 #define U300_SYSCON_KA1R_MASK					(0xFFFF)
@@ -357,57 +272,6 @@
 #define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE			(0x0080)
 #define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE			(0x0040)
 #define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK			(0x003F)
-/* Padmux 2 control */
-#define U300_SYSCON_PMC2R					(0x100)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MASK			(0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM			(0x0040)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MMC			(0x0080)
-#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2			(0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MASK			(0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM			(0x0100)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MMC			(0x0200)
-#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2			(0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MASK			(0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM			(0x0400)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MMC			(0x0800)
-#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2			(0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MASK			(0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM			(0x1000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MMC			(0x2000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2			(0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MASK			(0xC000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM			(0x4000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MMC			(0x8000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO			(0xC000)
-/* TODO: More SYSCON registers missing */
-#define U300_SYSCON_PMC3R					(0x10c)
-#define U300_SYSCON_PMC3R_APP_MISC_11_MASK			(0xc000)
-#define U300_SYSCON_PMC3R_APP_MISC_11_SPI			(0x4000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_MASK			(0x3000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_SPI			(0x1000)
-/* TODO: Missing other configs */
-#define U300_SYSCON_PMC4R					(0x168)
-#define U300_SYSCON_PMC4R_APP_MISC_12_MASK			(0x0003)
-#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_MASK			(0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_13_CDI			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA			(0x0004)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2			(0x0008)
-#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO			(0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_14_MASK			(0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA			(0x0010)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2			(0x0020)
-#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO			(0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_16_MASK			(0x0300)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13		(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS		(0x0100)
-#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N	(0x0200)
 /* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
 #define U300_SYSCON_S0CCR					(0x120)
 #define U300_SYSCON_S0CCR_FIELD_MASK				(0x43FF)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/Kconfig linux-libre-3.2-gnu1/arch/arm/mach-u300/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,9 @@ comment "ST-Ericsson Mobile Platform Pro
 
 config MACH_U300
 	bool "U300"
+	select PINCTRL
+	select PINMUX_U300
+	select GPIO_U300
 
 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
 
@@ -48,39 +51,12 @@ config MACH_U300_BS365
 
 endchoice
 
-choice
-	prompt "Memory configuration"
-	default MACH_U300_SINGLE_RAM
-	---help---
-	You have to config the kernel according to the physical memory
-	configuration.
-
-config MACH_U300_SINGLE_RAM
-	bool "Single RAM"
-	help
-		Select this if you want support for Single RAM phones.
-
-config MACH_U300_DUAL_RAM
-	bool "Dual RAM"
-	help
-		Select this if you want support for Dual RAM phones.
-		This is two RAM memories on different EMIFs.
-endchoice
-
 config U300_DEBUG
 	bool "Debug support for U300"
 	depends on PM
 	help
 		Debug support for U300 in sysfs, procfs etc.
 
-config MACH_U300_SEMI_IS_SHARED
-	bool "The SEMI is used by both the access and application side"
-	depends on MACH_U300
-	help
-		This makes it possible to use the SEMI (Shared External
-		Memory Interface) from both from access and application
-		side.
-
 config MACH_U300_SPIDUMMY
 	bool "SSP/SPI dummy chip"
 	select SPI
@@ -93,25 +69,6 @@ config MACH_U300_SPIDUMMY
 		you don't need it. Selecting this will activate the
 		SPI framework and ARM PL022 support.
 
-comment "All the settings below must match the bootloader's settings"
-
-config MACH_U300_ACCESS_MEM_SIZE
-       int "Access CPU memory allocation"
-       range 7 25
-       depends on MACH_U300_SINGLE_RAM
-       default 13
-       help
-		How much memory in MiB that the Access side CPU has allocated
-
-config MACH_U300_2MB_ALIGNMENT_FIX
-       bool "2MiB alignment fix"
-       depends on MACH_U300_SINGLE_RAM
-       default y
-       help
-		If yes and the Access side CPU has allocated an odd size in
-		MiB, this fix gives you one MiB extra that would otherwise be
-		lost due to Linux 2 MiB alignment policy.
-
 endmenu
 
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/Makefile linux-libre-3.2-gnu1/arch/arm/mach-u300/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U300 machine.
 #
 
-obj-y		:= core.o clock.o timer.o padmux.o
+obj-y		:= core.o clock.o timer.o
 obj-m		:=
 obj-n		:=
 obj-		:=
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-u300/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,4 @@
-# Note: the following conditions must always be true:
-#   ZRELADDR == virt_to_phys(TEXTADDR)
-#   PARAMS_PHYS must be within 4MB of ZRELADDR
-#   INITRD_PHYS must be in RAM
-
-ifdef CONFIG_MACH_U300_SINGLE_RAM
-     zreladdr-y	:= 0x28E08000
-  params_phys-y	:= 0x28E00100
-else
-     zreladdr-y	:= 0x48008000
-  params_phys-y	:= 0x48000100
-endif
-
+   zreladdr-y	+= 0x48008000
+params_phys-y	:= 0x48000100
 # This isn't used.
-#initrd_phys-y	:= 0x29800000
+#initrd_phys-y	:= 0x48800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/mmc.c linux-libre-3.2-gnu1/arch/arm/mach-u300/mmc.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,14 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/mmc/host.h>
-#include <linux/gpio.h>
 #include <linux/dmaengine.h>
 #include <linux/amba/mmci.h>
 #include <linux/slab.h>
 #include <mach/coh901318.h>
 #include <mach/dma_channels.h>
+#include <mach/gpio-u300.h>
 
 #include "mmc.h"
-#include "padmux.h"
 
 static struct mmci_platform_data mmc0_plat_data = {
 	/*
@@ -45,24 +44,9 @@ static struct mmci_platform_data mmc0_pl
 int __devinit mmc_init(struct amba_device *adev)
 {
 	struct device *mmcsd_device = &adev->dev;
-	struct pmx *pmx;
 	int ret = 0;
 
 	mmcsd_device->platform_data = &mmc0_plat_data;
 
-	/*
-	 * Setup padmuxing for MMC. Since this must always be
-	 * compiled into the kernel, pmx is never released.
-	 */
-	pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING);
-
-	if (IS_ERR(pmx))
-		pr_warning("Could not get padmux handle\n");
-	else {
-		ret = pmx_activate(mmcsd_device, pmx);
-		if (IS_ERR_VALUE(ret))
-			pr_warning("Could not activate padmuxing\n");
-	}
-
 	return ret;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/padmux.c linux-libre-3.2-gnu1/arch/arm/mach-u300/padmux.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/padmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/padmux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,367 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.c
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX functions
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/bug.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <mach/u300-regs.h>
-#include <mach/syscon.h>
-#include "padmux.h"
-
-static DEFINE_MUTEX(pmx_mutex);
-
-const u32 pmx_registers[] = {
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC2R),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC3R),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC4R)
-};
-
-/* High level functionality */
-
-/* Lazy dog:
- * onmask = {
- *   {"PMC1LR" mask, "PMC1LR" value},
- *   {"PMC1HR" mask, "PMC1HR" value},
- *   {"PMC2R"  mask, "PMC2R"  value},
- *   {"PMC3R"  mask, "PMC3R"  value},
- *   {"PMC4R"  mask, "PMC4R"  value}
- * }
- */
-static struct pmx mmc_setting = {
-	.setting = U300_APP_PMX_MMC_SETTING,
-	.default_on = false,
-	.activated = false,
-	.name = "MMC",
-	.onmask = {
-		   {U300_SYSCON_PMC1LR_MMCSD_MASK,
-		    U300_SYSCON_PMC1LR_MMCSD_MMCSD},
-		   {0, 0},
-		   {0, 0},
-		   {0, 0},
-		   {U300_SYSCON_PMC4R_APP_MISC_12_MASK,
-		    U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO}
-		   },
-};
-
-static struct pmx spi_setting = {
-	.setting = U300_APP_PMX_SPI_SETTING,
-	.default_on = false,
-	.activated = false,
-	.name = "SPI",
-	.onmask = {{0, 0},
-		   {U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
-		    U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI},
-		   {0, 0},
-		   {0, 0},
-		   {0, 0}
-		   },
-};
-
-/* Available padmux settings */
-static struct pmx *pmx_settings[] = {
-	&mmc_setting,
-	&spi_setting,
-};
-
-static void update_registers(struct pmx *pmx, bool activate)
-{
-	u16 regval, val, mask;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) {
-		if (activate)
-			val = pmx->onmask[i].val;
-		else
-			val = 0;
-
-		mask = pmx->onmask[i].mask;
-		if (mask != 0) {
-			regval = readw(pmx_registers[i]);
-			regval &= ~mask;
-			regval |= val;
-			writew(regval, pmx_registers[i]);
-		}
-	}
-}
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting)
-{
-	int i;
-	struct pmx *pmx = ERR_PTR(-ENOENT);
-
-	if (dev == NULL)
-		return ERR_PTR(-EINVAL);
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (setting == pmx_settings[i]->setting) {
-
-			if (pmx_settings[i]->dev != NULL) {
-				WARN(1, "padmux: required setting "
-				     "in use by another consumer\n");
-			} else {
-				pmx = pmx_settings[i];
-				pmx->dev = dev;
-				dev_dbg(dev, "padmux: setting nr %d is now "
-					"bound to %s and ready to use\n",
-					setting, dev_name(dev));
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return pmx;
-}
-EXPORT_SYMBOL(pmx_get);
-
-int pmx_put(struct device *dev, struct pmx *pmx)
-{
-	int i;
-	int ret = -ENOENT;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx->setting == pmx_settings[i]->setting) {
-
-			if (dev != pmx->dev) {
-				WARN(1, "padmux: cannot release handle as "
-					"it is bound to another consumer\n");
-				ret = -EINVAL;
-				break;
-			} else {
-				pmx_settings[i]->dev = NULL;
-				ret = 0;
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(pmx_put);
-
-int pmx_activate(struct device *dev, struct pmx *pmx)
-{
-	int i, j, ret;
-	ret = 0;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-
-	/* Make sure the required bits are not used */
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx)
-			continue;
-
-		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
-			if (pmx_settings[i]->onmask[j].mask & pmx->
-				onmask[j].mask) {
-				/* More than one entry on the same bits */
-				WARN(1, "padmux: cannot activate "
-					"setting. Bit conflict with "
-					"an active setting\n");
-
-				ret = -EUSERS;
-				goto exit;
-			}
-		}
-	}
-	update_registers(pmx, true);
-	pmx->activated = true;
-	dev_dbg(dev, "padmux: setting nr %d is activated\n",
-		pmx->setting);
-
-exit:
-	mutex_unlock(&pmx_mutex);
-	return ret;
-}
-EXPORT_SYMBOL(pmx_activate);
-
-int pmx_deactivate(struct device *dev, struct pmx *pmx)
-{
-	int i;
-	int ret = -ENOENT;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx_settings[i]->dev == NULL)
-			continue;
-
-		if (pmx->setting == pmx_settings[i]->setting) {
-
-			if (dev != pmx->dev) {
-				WARN(1, "padmux: cannot deactivate "
-				     "pmx setting as it was activated "
-				     "by another consumer\n");
-
-				ret = -EBUSY;
-				continue;
-			} else {
-				update_registers(pmx, false);
-				pmx_settings[i]->dev = NULL;
-				pmx->activated = false;
-				ret = 0;
-				dev_dbg(dev, "padmux: setting nr %d is deactivated",
-					pmx->setting);
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(pmx_deactivate);
-
-/*
- * For internal use only. If it is to be exported,
- * it should be reentrant. Notice that pmx_activate
- * (i.e. runtime settings) always override default settings.
- */
-static int pmx_set_default(void)
-{
-	/* Used to identify several entries on the same bits */
-	u16 modbits[ARRAY_SIZE(pmx_registers)];
-
-	int i, j;
-
-	memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16));
-
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (!pmx_settings[i]->default_on)
-			continue;
-
-		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
-			/* Make sure there is only one entry on the same bits */
-			if (modbits[j] & pmx_settings[i]->onmask[j].mask) {
-				BUG();
-				return -EUSERS;
-			}
-			modbits[j] |= pmx_settings[i]->onmask[j].mask;
-		}
-		update_registers(pmx_settings[i], true);
-	}
-	return 0;
-}
-
-#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
-static int pmx_show(struct seq_file *s, void *data)
-{
-	int i;
-	seq_printf(s, "-------------------------------------------------\n");
-	seq_printf(s, "SETTING     BOUND TO DEVICE               STATE\n");
-	seq_printf(s, "-------------------------------------------------\n");
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-		/* Format pmx and device name nicely */
-		char cdp[33];
-		int chars;
-
-		chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name);
-		while (chars < 16) {
-			cdp[chars] = ' ';
-			chars++;
-		}
-		chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ?
-				dev_name(pmx_settings[i]->dev) : "N/A");
-		while (chars < 16) {
-			cdp[chars+16] = ' ';
-			chars++;
-		}
-		cdp[32] = '\0';
-
-		seq_printf(s,
-			"%s\t%s\n",
-			&cdp[0],
-			pmx_settings[i]->activated ?
-			"ACTIVATED" : "DEACTIVATED"
-			);
-
-	}
-	mutex_unlock(&pmx_mutex);
-	return 0;
-}
-
-static int pmx_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pmx_show, NULL);
-}
-
-static const struct file_operations pmx_operations = {
-	.owner		= THIS_MODULE,
-	.open		= pmx_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init init_pmx_read_debugfs(void)
-{
-	/* Expose a simple debugfs interface to view pmx settings */
-	(void) debugfs_create_file("padmux", S_IFREG | S_IRUGO,
-				   NULL, NULL,
-				   &pmx_operations);
-	return 0;
-}
-
-/*
- * This needs to come in after the core_initcall(),
- * because debugfs is not available until
- * the subsystems come up.
- */
-module_init(init_pmx_read_debugfs);
-#endif
-
-static int __init pmx_init(void)
-{
-	int ret;
-
-	ret = pmx_set_default();
-
-	if (IS_ERR_VALUE(ret))
-		pr_crit("padmux: default settings could not be set\n");
-
-	return 0;
-}
-
-/* Should be initialized before consumers */
-core_initcall(pmx_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/padmux.h linux-libre-3.2-gnu1/arch/arm/mach-u300/padmux.h
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/padmux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/padmux.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.h
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX API
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#ifndef __MACH_U300_PADMUX_H
-#define __MACH_U300_PADMUX_H
-
-enum pmx_settings {
-	U300_APP_PMX_MMC_SETTING,
-	U300_APP_PMX_SPI_SETTING
-};
-
-struct pmx_onmask {
-	u16 mask;		/* Mask bits */
-	u16 val;		/* Value when active */
-};
-
-struct pmx {
-	struct device *dev;
-	enum pmx_settings setting;
-	char *name;
-	bool activated;
-	bool default_on;
-	struct pmx_onmask onmask[];
-};
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting);
-int pmx_put(struct device *dev, struct pmx *pmx);
-int pmx_activate(struct device *dev, struct pmx *pmx);
-int pmx_deactivate(struct device *dev, struct pmx *pmx);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/spi.c linux-libre-3.2-gnu1/arch/arm/mach-u300/spi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,6 @@
 #include <mach/coh901318.h>
 #include <mach/dma_channels.h>
 
-#include "padmux.h"
-
 /*
  * The following is for the actual devices on the SSP/SPI bus
  */
@@ -95,25 +93,7 @@ static struct pl022_ssp_controller ssp_p
 
 void __init u300_spi_init(struct amba_device *adev)
 {
-	struct pmx *pmx;
-
 	adev->dev.platform_data = &ssp_platform_data;
-	/*
-	 * Setup padmuxing for SPI. Since this must always be
-	 * compiled into the kernel, pmx is never released.
-	 */
-	pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING);
-
-	if (IS_ERR(pmx))
-		dev_warn(&adev->dev, "Could not get padmux handle\n");
-	else {
-		int ret;
-
-		ret = pmx_activate(&adev->dev, pmx);
-		if (IS_ERR_VALUE(ret))
-			dev_warn(&adev->dev, "Could not activate padmuxing\n");
-	}
-
 }
 
 void __init u300_spi_register_board_devices(void)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-u300/u300.c linux-libre-3.2-gnu1/arch/arm/mach-u300/u300.c
--- linux-libre-3.1-gnu1/arch/arm/mach-u300/u300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-u300/u300.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,21 +23,6 @@
 #include <asm/mach/arch.h>
 #include <asm/memory.h>
 
-static void __init u300_reserve(void)
-{
-	/*
-	 * U300 - This platform family can share physical memory
-	 * between two ARM cpus, one running Linux and the other
-	 * running another OS.
-	 */
-#ifdef CONFIG_MACH_U300_SINGLE_RAM
-#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \
-	CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-        memblock_reserve(PHYS_OFFSET, 0x00100000);
-#endif
-#endif
-}
-
 static void __init u300_init_machine(void)
 {
 	u300_init_devices();
@@ -61,9 +46,8 @@ static void __init u300_init_machine(voi
 
 MACHINE_START(U300, MACH_U300_STRING)
 	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-	.boot_params	= BOOT_PARAMS_OFFSET,
+	.atag_offset	= BOOT_PARAMS_OFFSET,
 	.map_io		= u300_map_io,
-	.reserve	= u300_reserve,
 	.init_irq	= u300_init_irq,
 	.timer		= &u300_timer,
 	.init_machine	= u300_init_machine,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <plat/i2c.h>
 #include <plat/ste_dma40.h>
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -603,28 +604,72 @@ static void __init mop500_init_machine(v
 {
 	int i2c0_devs;
 
+	mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
+	u8500_init_devices();
+
+	mop500_pins_init();
+
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
+
+	mop500_i2c_init();
+	mop500_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+
+	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init snowball_init_machine(void)
+{
+	int i2c0_devs;
+
+	u8500_init_devices();
+
+	snowball_pins_init();
+
+	platform_add_devices(snowball_platform_devs,
+			ARRAY_SIZE(snowball_platform_devs));
+
+	mop500_i2c_init();
+	snowball_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init hrefv60_init_machine(void)
+{
+	int i2c0_devs;
+
 	/*
 	 * The HREFv60 board removed a GPIO expander and routed
 	 * all these GPIO pins to the internal GPIO controller
 	 * instead.
 	 */
-	if (!machine_is_snowball()) {
-		if (machine_is_hrefv60())
-			mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-		else
-			mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-	}
+	mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
 
 	u8500_init_devices();
 
-	mop500_pins_init();
+	hrefv60_pins_init();
 
-	if (machine_is_snowball())
-		platform_add_devices(snowball_platform_devs,
-					ARRAY_SIZE(snowball_platform_devs));
-	else
-		platform_add_devices(mop500_platform_devs,
-					ARRAY_SIZE(mop500_platform_devs));
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
 
 	mop500_i2c_init();
 	mop500_sdi_init();
@@ -632,8 +677,8 @@ static void __init mop500_init_machine(v
 	mop500_uart_init();
 
 	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-	if (machine_is_hrefv60())
-		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+	i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
 
 	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
 	i2c_register_board_info(2, mop500_i2c2_devices,
@@ -645,7 +690,7 @@ static void __init mop500_init_machine(v
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
@@ -654,18 +699,18 @@ MACHINE_START(U8500, "ST-Ericsson MOP500
 MACHINE_END
 
 MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= hrefv60_init_machine,
 MACHINE_END
 
 MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= snowball_init_machine,
 MACHINE_END
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,10 +40,13 @@
 struct i2c_board_info;
 
 extern void mop500_sdi_init(void);
+extern void snowball_sdi_init(void);
 extern void mop500_sdi_tc35892_init(void);
 void __init mop500_u8500uib_init(void);
 void __init mop500_stuib_init(void);
 void __init mop500_pins_init(void);
+void __init hrefv60_pins_init(void);
+void __init snowball_pins_init(void);
 
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
 		unsigned n);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-pins.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-pins.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-pins.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-pins.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,10 +6,10 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 
 #include "pins-db8500.h"
@@ -153,7 +153,7 @@ static pin_cfg_t mop500_pins_default[] =
 	GPIO7_U1_RTSn	| PIN_OUTPUT_HIGH,
 };
 
-static pin_cfg_t mop500_pins_hrefv60[] = {
+static pin_cfg_t hrefv60_pins[] = {
 	/* WLAN */
 	GPIO4_GPIO		| PIN_INPUT_PULLUP,/* WLAN_IRQ */
 	GPIO85_GPIO		| PIN_OUTPUT_LOW,/* WLAN_ENA */
@@ -279,14 +279,26 @@ static pin_cfg_t snowball_pins[] = {
 void __init mop500_pins_init(void)
 {
 	nmk_config_pins(mop500_pins_common,
-				ARRAY_SIZE(mop500_pins_common));
-	if (machine_is_hrefv60())
-		nmk_config_pins(mop500_pins_hrefv60,
-				ARRAY_SIZE(mop500_pins_hrefv60));
-	else if (machine_is_snowball())
-		nmk_config_pins(snowball_pins,
-				ARRAY_SIZE(snowball_pins));
-	else
-		nmk_config_pins(mop500_pins_default,
-				ARRAY_SIZE(mop500_pins_default));
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(mop500_pins_default,
+			ARRAY_SIZE(mop500_pins_default));
+}
+
+void __init snowball_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(snowball_pins,
+			ARRAY_SIZE(snowball_pins));
+}
+
+void __init hrefv60_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(hrefv60_pins,
+			ARRAY_SIZE(hrefv60_pins));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,30 +216,48 @@ void __init mop500_sdi_init(void)
 	/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
 	if (!cpu_is_u8500v10())
 		mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-	/* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
-	if (!machine_is_snowball())
-		db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
 
 	/* On-board eMMC */
 	db8500_add_sdi4(&mop500_sdi4_data, periphid);
 
-	if (machine_is_hrefv60() || machine_is_snowball()) {
-		if (machine_is_hrefv60()) {
-			mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-			sdi0_en = HREFV60_SDMMC_EN_GPIO;
-			sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
-		} else if (machine_is_snowball()) {
-			mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
-			mop500_sdi0_data.cd_invert = true;
-			sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
-			sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
-		}
-		sdi0_configure();
-	}
-
 	/*
 	 * On boards with the TC35892 GPIO expander, sdi0 will finally
 	 * be added when the TC35892 initializes and calls
 	 * mop500_sdi_tc35892_init() above.
 	 */
 }
+
+void __init snowball_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+	mop500_sdi0_data.cd_invert = true;
+	sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+	sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
+
+void __init hrefv60_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+	sdi0_en = HREFV60_SDMMC_EN_GPIO;
+	sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-u8500uib.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-u8500uib.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-mop500-u8500uib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-mop500-u8500uib.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  * Board data for the U8500 UIB, also known as the New UIB
  * License terms: GNU General Public License (GPL), version 2
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -13,7 +13,6 @@
 #include <linux/mfd/tc3589x.h>
 #include <linux/input/matrix_keypad.h>
 
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 #include "board-mop500.h"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-u5500.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-u5500.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-u5500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-u5500.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,15 +8,16 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
-#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/mfd/ab5500/ab5500.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/devices.h>
@@ -87,7 +88,6 @@ static struct lm3530_platform_data u5500
 	.brt_val = 0x7F,	/* Max brightness */
 };
 
-
 static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
 	{
 		/* Backlight */
@@ -101,6 +101,30 @@ static void __init u5500_i2c_init(void)
 	db5500_add_i2c2(&u5500_i2c2_data);
 	i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
 }
+
+static struct ab5500_platform_data ab5500_plf_data = {
+	.irq = {
+		.base = 0,
+		.count = 0,
+	},
+	.init_settings = NULL,
+	.init_settings_sz = 0,
+	.pm_power_off = false,
+};
+
+static struct platform_device ab5500_device = {
+	.name = "ab5500-core",
+	.id = 0,
+	.dev = {
+		.platform_data = &ab5500_plf_data,
+	},
+	.num_resources = 0,
+};
+
+static struct platform_device *u5500_platform_devices[] __initdata = {
+	&ab5500_device,
+};
+
 static void __init u5500_uart_init(void)
 {
 	db5500_add_uart0(NULL);
@@ -115,10 +139,13 @@ static void __init u5500_init_machine(vo
 	u5500_i2c_init();
 	u5500_sdi_init();
 	u5500_uart_init();
+
+	platform_add_devices(u5500_platform_devices,
+		ARRAY_SIZE(u5500_platform_devices));
 }
 
 MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= u5500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,9 +7,9 @@
 
 #include <linux/amba/mmci.h>
 #include <linux/mmc/host.h>
-#include <linux/gpio.h>
 
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/db5500-regs.h>
 #include <plat/ste_dma40.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/cache-l2x0.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/cache-l2x0.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/cache-l2x0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/cache-l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/hardware.h>
+#include <mach/id.h>
+
+static void __iomem *l2x0_base;
+
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
+{
+	/* wait for the operation to complete */
+	while (readl_relaxed(reg) & mask)
+		cpu_relax();
+}
+
+static inline void ux500_cache_sync(void)
+{
+	writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
+	ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
+}
+
+/*
+ * The L2 cache cannot be turned off in the non-secure world.
+ * Dummy until a secure service is in place.
+ */
+static void ux500_l2x0_disable(void)
+{
+}
+
+/*
+ * This is only called when doing a kexec, just after turning off the L2
+ * and L1 cache, and it is surrounded by a spinlock in the generic version.
+ * However, we're not really turning off the L2 cache right now and the
+ * PL310 does not support exclusive accesses (used to implement the spinlock).
+ * So, the invalidation needs to be done without the spinlock.
+ */
+static void ux500_l2x0_inv_all(void)
+{
+	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
+
+	/* invalidate all ways */
+	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+	ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+	ux500_cache_sync();
+}
+
+static int __init ux500_l2x0_unlock(void)
+{
+	int i;
+
+	/*
+	 * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
+	 * apparently locks both caches before jumping to the kernel. The
+	 * l2x0 core will not touch the unlock registers if the l2x0 is
+	 * already enabled, so we do it right here instead. The PL310 has
+	 * 8 sets of registers, one per possible CPU.
+	 */
+	for (i = 0; i < 8; i++) {
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+	}
+	return 0;
+}
+
+static int __init ux500_l2x0_init(void)
+{
+	if (cpu_is_u5500())
+		l2x0_base = __io_address(U5500_L2CC_BASE);
+	else if (cpu_is_u8500())
+		l2x0_base = __io_address(U8500_L2CC_BASE);
+	else
+		ux500_unknown_soc();
+
+	/* Unlock before init */
+	ux500_l2x0_unlock();
+
+	/* 64KB way size, 8 way associativity, force WA */
+	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+	/* Override invalidate function */
+	outer_cache.disable = ux500_l2x0_disable;
+	outer_cache.inv_all = ux500_l2x0_inv_all;
+
+	return 0;
+}
+
+early_initcall(ux500_l2x0_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,14 +10,12 @@
 #include <linux/clk.h>
 #include <linux/mfd/db8500-prcmu.h>
 #include <linux/mfd/db5500-prcmu.h>
+#include <linux/clksrc-dbx500-prcmu.h>
 
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/localtimer.h>
 
-#include <plat/mtu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
@@ -26,10 +24,6 @@
 
 void __iomem *_PRCMU_BASE;
 
-#ifdef CONFIG_CACHE_L2X0
-static void __iomem *l2x0_base;
-#endif
-
 void __init ux500_init_irq(void)
 {
 	void __iomem *dist_base;
@@ -53,96 +47,6 @@ void __init ux500_init_irq(void)
 	if (cpu_is_u5500())
 		db5500_prcmu_early_init();
 	if (cpu_is_u8500())
-		prcmu_early_init();
+		db8500_prcmu_early_init();
 	clk_init();
 }
-
-#ifdef CONFIG_CACHE_L2X0
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
-	/* wait for the operation to complete */
-	while (readl_relaxed(reg) & mask)
-		;
-}
-
-static inline void ux500_cache_sync(void)
-{
-	void __iomem *base = l2x0_base;
-
-	writel_relaxed(0, base + L2X0_CACHE_SYNC);
-	ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
-	void __iomem *base = l2x0_base;
-	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
-
-	/* invalidate all ways */
-	writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY);
-	ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask);
-	ux500_cache_sync();
-}
-
-static int ux500_l2x0_init(void)
-{
-	if (cpu_is_u5500())
-		l2x0_base = __io_address(U5500_L2CC_BASE);
-	else if (cpu_is_u8500())
-		l2x0_base = __io_address(U8500_L2CC_BASE);
-	else
-		ux500_unknown_soc();
-
-	/* 64KB way size, 8 way associativity, force WA */
-	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
-
-	/* Override invalidate function */
-	outer_cache.disable = ux500_l2x0_disable;
-	outer_cache.inv_all = ux500_l2x0_inv_all;
-
-	return 0;
-}
-early_initcall(ux500_l2x0_init);
-#endif
-
-static void __init ux500_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	/* Setup the local timer base */
-	if (cpu_is_u5500())
-		twd_base = __io_address(U5500_TWD_BASE);
-	else if (cpu_is_u8500())
-		twd_base = __io_address(U8500_TWD_BASE);
-	else
-		ux500_unknown_soc();
-#endif
-	if (cpu_is_u5500())
-		mtu_base = __io_address(U5500_MTU0_BASE);
-	else if (cpu_is_u8500ed())
-		mtu_base = __io_address(U8500_MTU0_BASE_ED);
-	else if (cpu_is_u8500())
-		mtu_base = __io_address(U8500_MTU0_BASE);
-	else
-		ux500_unknown_soc();
-
-	nmdk_timer_init();
-}
-
-struct sys_timer ux500_timer = {
-	.init	= ux500_timer_init,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu-db5500.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu-db5500.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu-db5500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu-db5500.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
 
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/devices.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu-db8500.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu-db8500.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/cpu-db8500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/cpu-db8500.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,12 +14,12 @@
 #include <linux/amba/bus.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/devices-common.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/devices-common.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/devices-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/devices-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@ static inline void platform_do_lowpower(
 	for (;;) {
 		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
 				: : : "memory");
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,8 @@
 #define U5500_SCR_BASE		(U5500_PER4_BASE + 0x5000)
 #define U5500_DMC_BASE		(U5500_PER4_BASE + 0x6000)
 #define U5500_PRCMU_BASE	(U5500_PER4_BASE + 0x7000)
+#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
+#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
 #define U5500_MSP1_BASE		(U5500_PER4_BASE + 0x9000)
 #define U5500_GPIO2_BASE	(U5500_PER4_BASE + 0xA000)
 #define U5500_CDETECT_BASE	(U5500_PER4_BASE + 0xF000)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -102,10 +102,13 @@
 #define U8500_SCR_BASE		(U8500_PER4_BASE + 0x05000)
 #define U8500_DMC_BASE		(U8500_PER4_BASE + 0x06000)
 #define U8500_PRCMU_BASE	(U8500_PER4_BASE + 0x07000)
+#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
+#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
 #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
 #define U8500_PRCMU_TCDM_BASE	(U8500_PER4_BASE + 0x68000)
 #define U8500_PRCMU_TCPM_BASE   (U8500_PER4_BASE + 0x60000)
 
+
 /* per3 base addresses */
 #define U8500_FSMC_BASE		(U8500_PER3_BASE + 0x0000)
 #define U8500_SSP0_BASE		(U8500_PER3_BASE + 0x2000)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #define UX500_UART(n)	__UX500_UART(n)
 #define UART_BASE	UX500_UART(CONFIG_UX500_DEBUG_UART)
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =UART_BASE				@ no, physical address
 	ldr	\rv, =IO_ADDRESS(UART_BASE)		@ yes, virtual address
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,4 @@
  */
 #define ARCH_NR_GPIOS	350
 
-#include <plat/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2009 ST-Ericsson
- *
- * 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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-#define BUS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,15 +51,9 @@ static void flush(void)
 static inline void arch_decomp_setup(void)
 {
 	/* Check in run time if we run on an U8500 or U5500 */
-	if (machine_is_u8500() ||
-	    machine_is_svp8500v1() ||
-	    machine_is_svp8500v2() ||
-	    machine_is_hrefv60()   ||
-	    machine_is_snowball())
-		ux500_uart_base = U8500_UART2_BASE;
-	else if (machine_is_u5500())
+	if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
-	else /* not much can be done to help here */
+	else
 		ux500_uart_base = U8500_UART2_BASE;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/Makefile linux-libre-3.2-gnu1/arch/arm/mach-ux500/Makefile
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 #
 
 obj-y				:= clock.o cpu.o devices.o devices-common.o \
-				   id.o usb.o
+				   id.o usb.o timer.o
+obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-ux500/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/pins-db8500.h linux-libre-3.2-gnu1/arch/arm/mach-ux500/pins-db8500.h
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/pins-db8500.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/pins-db8500.h	2012-01-04 18:55:44.000000000 -0500
@@ -35,40 +35,40 @@
 
 #define GPIO4_GPIO		PIN_CFG(4, GPIO)
 #define GPIO4_U1_RXD		PIN_CFG(4, ALT_A)
-#define GPIO4_I2C4_SCL		PIN_CFG_PULL(4, ALT_B, UP)
+#define GPIO4_I2C4_SCL		PIN_CFG_INPUT(4, ALT_B, PULLUP)
 #define GPIO4_IP_TRSTn		PIN_CFG(4, ALT_C)
 
 #define GPIO5_GPIO		PIN_CFG(5, GPIO)
 #define GPIO5_U1_TXD		PIN_CFG(5, ALT_A)
-#define GPIO5_I2C4_SDA		PIN_CFG_PULL(5, ALT_B, UP)
+#define GPIO5_I2C4_SDA		PIN_CFG_INPUT(5, ALT_B, PULLUP)
 #define GPIO5_IP_GPIO6		PIN_CFG(5, ALT_C)
 
 #define GPIO6_GPIO		PIN_CFG(6, GPIO)
 #define GPIO6_U1_CTSn		PIN_CFG(6, ALT_A)
-#define GPIO6_I2C1_SCL		PIN_CFG_PULL(6, ALT_B, UP)
+#define GPIO6_I2C1_SCL		PIN_CFG_INPUT(6, ALT_B, PULLUP)
 #define GPIO6_IP_GPIO0		PIN_CFG(6, ALT_C)
 
 #define GPIO7_GPIO		PIN_CFG(7, GPIO)
 #define GPIO7_U1_RTSn		PIN_CFG(7, ALT_A)
-#define GPIO7_I2C1_SDA		PIN_CFG_PULL(7, ALT_B, UP)
+#define GPIO7_I2C1_SDA		PIN_CFG_INPUT(7, ALT_B, PULLUP)
 #define GPIO7_IP_GPIO1		PIN_CFG(7, ALT_C)
 
 #define GPIO8_GPIO		PIN_CFG(8, GPIO)
-#define GPIO8_IPI2C_SDA		PIN_CFG_PULL(8, ALT_A, UP)
-#define GPIO8_I2C2_SDA		PIN_CFG_PULL(8, ALT_B, UP)
+#define GPIO8_IPI2C_SDA		PIN_CFG_INPUT(8, ALT_A, PULLUP)
+#define GPIO8_I2C2_SDA		PIN_CFG_INPUT(8, ALT_B, PULLUP)
 
 #define GPIO9_GPIO		PIN_CFG(9, GPIO)
-#define GPIO9_IPI2C_SCL		PIN_CFG_PULL(9, ALT_A, UP)
-#define GPIO9_I2C2_SCL		PIN_CFG_PULL(9, ALT_B, UP)
+#define GPIO9_IPI2C_SCL		PIN_CFG_INPUT(9, ALT_A, PULLUP)
+#define GPIO9_I2C2_SCL		PIN_CFG_INPUT(9, ALT_B, PULLUP)
 
 #define GPIO10_GPIO		PIN_CFG(10, GPIO)
-#define GPIO10_IPI2C_SDA	PIN_CFG_PULL(10, ALT_A, UP)
-#define GPIO10_I2C2_SDA		PIN_CFG_PULL(10, ALT_B, UP)
+#define GPIO10_IPI2C_SDA	PIN_CFG_INPUT(10, ALT_A, PULLUP)
+#define GPIO10_I2C2_SDA		PIN_CFG_INPUT(10, ALT_B, PULLUP)
 #define GPIO10_IP_GPIO3		PIN_CFG(10, ALT_C)
 
 #define GPIO11_GPIO		PIN_CFG(11, GPIO)
-#define GPIO11_IPI2C_SCL	PIN_CFG_PULL(11, ALT_A, UP)
-#define GPIO11_I2C2_SCL		PIN_CFG_PULL(11, ALT_B, UP)
+#define GPIO11_IPI2C_SCL	PIN_CFG_INPUT(11, ALT_A, PULLUP)
+#define GPIO11_I2C2_SCL		PIN_CFG_INPUT(11, ALT_B, PULLUP)
 #define GPIO11_IP_GPIO2		PIN_CFG(11, ALT_C)
 
 #define GPIO12_GPIO		PIN_CFG(12, GPIO)
@@ -87,66 +87,66 @@
 
 #define GPIO16_GPIO		PIN_CFG(16, GPIO)
 #define GPIO16_MSP0_RFS		PIN_CFG(16, ALT_A)
-#define GPIO16_I2C1_SCL		PIN_CFG_PULL(16, ALT_B, UP)
+#define GPIO16_I2C1_SCL		PIN_CFG_INPUT(16, ALT_B, PULLUP)
 #define GPIO16_SLIM0_DAT	PIN_CFG(16, ALT_C)
 
 #define GPIO17_GPIO		PIN_CFG(17, GPIO)
 #define GPIO17_MSP0_RCK		PIN_CFG(17, ALT_A)
-#define GPIO17_I2C1_SDA		PIN_CFG_PULL(17, ALT_B, UP)
+#define GPIO17_I2C1_SDA		PIN_CFG_INPUT(17, ALT_B, PULLUP)
 #define GPIO17_SLIM0_CLK	PIN_CFG(17, ALT_C)
 
 #define GPIO18_GPIO		PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR	PIN_CFG_PULL(18, ALT_A, UP)
+#define GPIO18_MC0_CMDDIR	PIN_CFG_INPUT(18, ALT_A, PULLUP)
 #define GPIO18_U2_RXD		PIN_CFG(18, ALT_B)
 #define GPIO18_MS_IEP		PIN_CFG(18, ALT_C)
 
 #define GPIO19_GPIO		PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR	PIN_CFG_PULL(19, ALT_A, UP)
+#define GPIO19_MC0_DAT0DIR	PIN_CFG_INPUT(19, ALT_A, PULLUP)
 #define GPIO19_U2_TXD		PIN_CFG(19, ALT_B)
 #define GPIO19_MS_DAT0DIR	PIN_CFG(19, ALT_C)
 
 #define GPIO20_GPIO		PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR	PIN_CFG_PULL(20, ALT_A, UP)
+#define GPIO20_MC0_DAT2DIR	PIN_CFG_INPUT(20, ALT_A, PULLUP)
 #define GPIO20_UARTMOD_TXD	PIN_CFG(20, ALT_B)
 #define GPIO20_IP_TRIGOUT	PIN_CFG(20, ALT_C)
 
 #define GPIO21_GPIO		PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR	PIN_CFG_PULL(21, ALT_A, UP)
+#define GPIO21_MC0_DAT31DIR	PIN_CFG_INPUT(21, ALT_A, PULLUP)
 #define GPIO21_MSP0_SCK		PIN_CFG(21, ALT_B)
 #define GPIO21_MS_DAT31DIR	PIN_CFG(21, ALT_C)
 
 #define GPIO22_GPIO		PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK	PIN_CFG_PULL(22, ALT_A, UP)
+#define GPIO22_MC0_FBCLK	PIN_CFG_INPUT(22, ALT_A, PULLUP)
 #define GPIO22_UARTMOD_RXD	PIN_CFG(22, ALT_B)
 #define GPIO22_MS_FBCLK		PIN_CFG(22, ALT_C)
 
 #define GPIO23_GPIO		PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK		PIN_CFG_PULL(23, ALT_A, UP)
+#define GPIO23_MC0_CLK		PIN_CFG_INPUT(23, ALT_A, PULLUP)
 #define GPIO23_STMMOD_CLK	PIN_CFG(23, ALT_B)
 #define GPIO23_MS_CLK		PIN_CFG(23, ALT_C)
 
 #define GPIO24_GPIO		PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD		PIN_CFG_PULL(24, ALT_A, UP)
+#define GPIO24_MC0_CMD		PIN_CFG_INPUT(24, ALT_A, PULLUP)
 #define GPIO24_UARTMOD_RXD	PIN_CFG(24, ALT_B)
 #define GPIO24_MS_BS		PIN_CFG(24, ALT_C)
 
 #define GPIO25_GPIO		PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0		PIN_CFG_PULL(25, ALT_A, UP)
+#define GPIO25_MC0_DAT0		PIN_CFG_INPUT(25, ALT_A, PULLUP)
 #define GPIO25_STMMOD_DAT0	PIN_CFG(25, ALT_B)
 #define GPIO25_MS_DAT0		PIN_CFG(25, ALT_C)
 
 #define GPIO26_GPIO		PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1		PIN_CFG_PULL(26, ALT_A, UP)
+#define GPIO26_MC0_DAT1		PIN_CFG_INPUT(26, ALT_A, PULLUP)
 #define GPIO26_STMMOD_DAT1	PIN_CFG(26, ALT_B)
 #define GPIO26_MS_DAT1		PIN_CFG(26, ALT_C)
 
 #define GPIO27_GPIO		PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2		PIN_CFG_PULL(27, ALT_A, UP)
+#define GPIO27_MC0_DAT2		PIN_CFG_INPUT(27, ALT_A, PULLUP)
 #define GPIO27_STMMOD_DAT2	PIN_CFG(27, ALT_B)
 #define GPIO27_MS_DAT2		PIN_CFG(27, ALT_C)
 
 #define GPIO28_GPIO		PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3		PIN_CFG_PULL(28, ALT_A, UP)
+#define GPIO28_MC0_DAT3		PIN_CFG_INPUT(28, ALT_A, PULLUP)
 #define GPIO28_STMMOD_DAT3	PIN_CFG(28, ALT_B)
 #define GPIO28_MS_DAT3		PIN_CFG(28, ALT_C)
 
@@ -357,48 +357,48 @@
 #define GPIO97_MC5_DAT7		PIN_CFG(97, ALT_C)
 
 #define GPIO128_GPIO		PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK		PIN_CFG_PULL(128, ALT_A, UP)
+#define GPIO128_MC2_CLK		PIN_CFG_INPUT(128, ALT_A, PULLUP)
 #define GPIO128_SM_CKO		PIN_CFG(128, ALT_B)
 
 #define GPIO129_GPIO		PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD		PIN_CFG_PULL(129, ALT_A, UP)
+#define GPIO129_MC2_CMD		PIN_CFG_INPUT(129, ALT_A, PULLUP)
 #define GPIO129_SM_WAIT0n	PIN_CFG(129, ALT_B)
 
 #define GPIO130_GPIO		PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK	PIN_CFG_PULL(130, ALT_A, UP)
+#define GPIO130_MC2_FBCLK	PIN_CFG_INPUT(130, ALT_A, PULLUP)
 #define GPIO130_SM_FBCLK	PIN_CFG(130, ALT_B)
 #define GPIO130_MC2_RSTN	PIN_CFG(130, ALT_C)
 
 #define GPIO131_GPIO		PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0	PIN_CFG_PULL(131, ALT_A, UP)
+#define GPIO131_MC2_DAT0	PIN_CFG_INPUT(131, ALT_A, PULLUP)
 #define GPIO131_SM_ADQ8		PIN_CFG(131, ALT_B)
 
 #define GPIO132_GPIO		PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1	PIN_CFG_PULL(132, ALT_A, UP)
+#define GPIO132_MC2_DAT1	PIN_CFG_INPUT(132, ALT_A, PULLUP)
 #define GPIO132_SM_ADQ9		PIN_CFG(132, ALT_B)
 
 #define GPIO133_GPIO		PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2	PIN_CFG_PULL(133, ALT_A, UP)
+#define GPIO133_MC2_DAT2	PIN_CFG_INPUT(133, ALT_A, PULLUP)
 #define GPIO133_SM_ADQ10	PIN_CFG(133, ALT_B)
 
 #define GPIO134_GPIO		PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3	PIN_CFG_PULL(134, ALT_A, UP)
+#define GPIO134_MC2_DAT3	PIN_CFG_INPUT(134, ALT_A, PULLUP)
 #define GPIO134_SM_ADQ11	PIN_CFG(134, ALT_B)
 
 #define GPIO135_GPIO		PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4	PIN_CFG_PULL(135, ALT_A, UP)
+#define GPIO135_MC2_DAT4	PIN_CFG_INPUT(135, ALT_A, PULLUP)
 #define GPIO135_SM_ADQ12	PIN_CFG(135, ALT_B)
 
 #define GPIO136_GPIO		PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5	PIN_CFG_PULL(136, ALT_A, UP)
+#define GPIO136_MC2_DAT5	PIN_CFG_INPUT(136, ALT_A, PULLUP)
 #define GPIO136_SM_ADQ13	PIN_CFG(136, ALT_B)
 
 #define GPIO137_GPIO		PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6	PIN_CFG_PULL(137, ALT_A, UP)
+#define GPIO137_MC2_DAT6	PIN_CFG_INPUT(137, ALT_A, PULLUP)
 #define GPIO137_SM_ADQ14	PIN_CFG(137, ALT_B)
 
 #define GPIO138_GPIO		PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7	PIN_CFG_PULL(138, ALT_A, UP)
+#define GPIO138_MC2_DAT7	PIN_CFG_INPUT(138, ALT_A, PULLUP)
 #define GPIO138_SM_ADQ15	PIN_CFG(138, ALT_B)
 
 #define GPIO139_GPIO		PIN_CFG(139, GPIO)
@@ -434,10 +434,10 @@
 #define GPIO146_SSP0_TXD	PIN_CFG(146, ALT_A)
 
 #define GPIO147_GPIO		PIN_CFG(147, GPIO)
-#define GPIO147_I2C0_SCL	PIN_CFG_PULL(147, ALT_A, UP)
+#define GPIO147_I2C0_SCL	PIN_CFG_INPUT(147, ALT_A, PULLUP)
 
 #define GPIO148_GPIO		PIN_CFG(148, GPIO)
-#define GPIO148_I2C0_SDA	PIN_CFG_PULL(148, ALT_A, UP)
+#define GPIO148_I2C0_SDA	PIN_CFG_INPUT(148, ALT_A, PULLUP)
 
 #define GPIO149_GPIO		PIN_CFG(149, GPIO)
 #define GPIO149_IP_GPIO0	PIN_CFG(149, ALT_A)
@@ -459,82 +459,82 @@
 #define GPIO152_KP_O9		PIN_CFG(152, ALT_C)
 
 #define GPIO153_GPIO		PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7		PIN_CFG_PULL(153, ALT_A, DOWN)
+#define GPIO153_KP_I7		PIN_CFG_INPUT(153, ALT_A, PULLDOWN)
 #define GPIO153_LCD_D24		PIN_CFG(153, ALT_B)
 #define GPIO153_U2_RXD		PIN_CFG(153, ALT_C)
 
 #define GPIO154_GPIO		PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6		PIN_CFG_PULL(154, ALT_A, DOWN)
+#define GPIO154_KP_I6		PIN_CFG_INPUT(154, ALT_A, PULLDOWN)
 #define GPIO154_LCD_D25		PIN_CFG(154, ALT_B)
 #define GPIO154_U2_TXD		PIN_CFG(154, ALT_C)
 
 #define GPIO155_GPIO		PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5		PIN_CFG_PULL(155, ALT_A, DOWN)
+#define GPIO155_KP_I5		PIN_CFG_INPUT(155, ALT_A, PULLDOWN)
 #define GPIO155_LCD_D26		PIN_CFG(155, ALT_B)
 #define GPIO155_STMAPE_CLK	PIN_CFG(155, ALT_C)
 
 #define GPIO156_GPIO		PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4		PIN_CFG_PULL(156, ALT_A, DOWN)
+#define GPIO156_KP_I4		PIN_CFG_INPUT(156, ALT_A, PULLDOWN)
 #define GPIO156_LCD_D27		PIN_CFG(156, ALT_B)
 #define GPIO156_STMAPE_DAT3	PIN_CFG(156, ALT_C)
 
 #define GPIO157_GPIO		PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7		PIN_CFG_PULL(157, ALT_A, UP)
+#define GPIO157_KP_O7		PIN_CFG_INPUT(157, ALT_A, PULLUP)
 #define GPIO157_LCD_D28		PIN_CFG(157, ALT_B)
 #define GPIO157_STMAPE_DAT2	PIN_CFG(157, ALT_C)
 
 #define GPIO158_GPIO		PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6		PIN_CFG_PULL(158, ALT_A, UP)
+#define GPIO158_KP_O6		PIN_CFG_INPUT(158, ALT_A, PULLUP)
 #define GPIO158_LCD_D29		PIN_CFG(158, ALT_B)
 #define GPIO158_STMAPE_DAT1	PIN_CFG(158, ALT_C)
 
 #define GPIO159_GPIO		PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5		PIN_CFG_PULL(159, ALT_A, UP)
+#define GPIO159_KP_O5		PIN_CFG_INPUT(159, ALT_A, PULLUP)
 #define GPIO159_LCD_D30		PIN_CFG(159, ALT_B)
 #define GPIO159_STMAPE_DAT0	PIN_CFG(159, ALT_C)
 
 #define GPIO160_GPIO		PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4		PIN_CFG_PULL(160, ALT_A, UP)
+#define GPIO160_KP_O4		PIN_CFG_INPUT(160, ALT_A, PULLUP)
 #define GPIO160_LCD_D31		PIN_CFG(160, ALT_B)
 #define GPIO160_NONE		PIN_CFG(160, ALT_C)
 
 #define GPIO161_GPIO		PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3		PIN_CFG_PULL(161, ALT_A, DOWN)
+#define GPIO161_KP_I3		PIN_CFG_INPUT(161, ALT_A, PULLDOWN)
 #define GPIO161_LCD_D32		PIN_CFG(161, ALT_B)
 #define GPIO161_UARTMOD_RXD	PIN_CFG(161, ALT_C)
 
 #define GPIO162_GPIO		PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2		PIN_CFG_PULL(162, ALT_A, DOWN)
+#define GPIO162_KP_I2		PIN_CFG_INPUT(162, ALT_A, PULLDOWN)
 #define GPIO162_LCD_D33		PIN_CFG(162, ALT_B)
 #define GPIO162_UARTMOD_TXD	PIN_CFG(162, ALT_C)
 
 #define GPIO163_GPIO		PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1		PIN_CFG_PULL(163, ALT_A, DOWN)
+#define GPIO163_KP_I1		PIN_CFG_INPUT(163, ALT_A, PULLDOWN)
 #define GPIO163_LCD_D34		PIN_CFG(163, ALT_B)
 #define GPIO163_STMMOD_CLK	PIN_CFG(163, ALT_C)
 
 #define GPIO164_GPIO		PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0		PIN_CFG_PULL(164, ALT_A, UP)
+#define GPIO164_KP_I0		PIN_CFG_INPUT(164, ALT_A, PULLUP)
 #define GPIO164_LCD_D35		PIN_CFG(164, ALT_B)
 #define GPIO164_STMMOD_DAT3	PIN_CFG(164, ALT_C)
 
 #define GPIO165_GPIO		PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3		PIN_CFG_PULL(165, ALT_A, UP)
+#define GPIO165_KP_O3		PIN_CFG_INPUT(165, ALT_A, PULLUP)
 #define GPIO165_LCD_D36		PIN_CFG(165, ALT_B)
 #define GPIO165_STMMOD_DAT2	PIN_CFG(165, ALT_C)
 
 #define GPIO166_GPIO		PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2		PIN_CFG_PULL(166, ALT_A, UP)
+#define GPIO166_KP_O2		PIN_CFG_INPUT(166, ALT_A, PULLUP)
 #define GPIO166_LCD_D37		PIN_CFG(166, ALT_B)
 #define GPIO166_STMMOD_DAT1	PIN_CFG(166, ALT_C)
 
 #define GPIO167_GPIO		PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1		PIN_CFG_PULL(167, ALT_A, UP)
+#define GPIO167_KP_O1		PIN_CFG_INPUT(167, ALT_A, PULLUP)
 #define GPIO167_LCD_D38		PIN_CFG(167, ALT_B)
 #define GPIO167_STMMOD_DAT0	PIN_CFG(167, ALT_C)
 
 #define GPIO168_GPIO		PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0		PIN_CFG_PULL(168, ALT_A, UP)
+#define GPIO168_KP_O0		PIN_CFG_INPUT(168, ALT_A, PULLUP)
 #define GPIO168_LCD_D39		PIN_CFG(168, ALT_B)
 #define GPIO168_NONE		PIN_CFG(168, ALT_C)
 
@@ -569,39 +569,39 @@
 #define GPIO196_MSP2_RXD	PIN_CFG(196, ALT_A)
 
 #define GPIO197_GPIO		PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3	PIN_CFG_PULL(197, ALT_A, UP)
+#define GPIO197_MC4_DAT3	PIN_CFG_INPUT(197, ALT_A, PULLUP)
 
 #define GPIO198_GPIO		PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2	PIN_CFG_PULL(198, ALT_A, UP)
+#define GPIO198_MC4_DAT2	PIN_CFG_INPUT(198, ALT_A, PULLUP)
 
 #define GPIO199_GPIO		PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1	PIN_CFG_PULL(199, ALT_A, UP)
+#define GPIO199_MC4_DAT1	PIN_CFG_INPUT(199, ALT_A, PULLUP)
 
 #define GPIO200_GPIO		PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0	PIN_CFG_PULL(200, ALT_A, UP)
+#define GPIO200_MC4_DAT0	PIN_CFG_INPUT(200, ALT_A, PULLUP)
 
 #define GPIO201_GPIO		PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD		PIN_CFG_PULL(201, ALT_A, UP)
+#define GPIO201_MC4_CMD		PIN_CFG_INPUT(201, ALT_A, PULLUP)
 
 #define GPIO202_GPIO		PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK	PIN_CFG_PULL(202, ALT_A, UP)
+#define GPIO202_MC4_FBCLK	PIN_CFG_INPUT(202, ALT_A, PULLUP)
 #define GPIO202_PWL		PIN_CFG(202, ALT_B)
 #define GPIO202_MC4_RSTN	PIN_CFG(202, ALT_C)
 
 #define GPIO203_GPIO		PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK		PIN_CFG_PULL(203, ALT_A, UP)
+#define GPIO203_MC4_CLK		PIN_CFG_INPUT(203, ALT_A, PULLUP)
 
 #define GPIO204_GPIO		PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7	PIN_CFG_PULL(204, ALT_A, UP)
+#define GPIO204_MC4_DAT7	PIN_CFG_INPUT(204, ALT_A, PULLUP)
 
 #define GPIO205_GPIO		PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6	PIN_CFG_PULL(205, ALT_A, UP)
+#define GPIO205_MC4_DAT6	PIN_CFG_INPUT(205, ALT_A, PULLUP)
 
 #define GPIO206_GPIO		PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5	PIN_CFG_PULL(206, ALT_A, UP)
+#define GPIO206_MC4_DAT5	PIN_CFG_INPUT(206, ALT_A, PULLUP)
 
 #define GPIO207_GPIO		PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4	PIN_CFG_PULL(207, ALT_A, UP)
+#define GPIO207_MC4_DAT4	PIN_CFG_INPUT(207, ALT_A, PULLUP)
 
 #define GPIO208_GPIO		PIN_CFG(208, GPIO)
 #define GPIO208_MC1_CLK		PIN_CFG(208, ALT_A)
@@ -632,21 +632,25 @@
 #define GPIO215_MC1_CMDDIR	PIN_CFG(215, ALT_A)
 #define GPIO215_MC3_DAT2DIR	PIN_CFG(215, ALT_B)
 #define GPIO215_CLKOUT1		PIN_CFG(215, ALT_C)
+#define GPIO215_SPI2_TXD	PIN_CFG(215, ALT_C)
 
 #define GPIO216_GPIO		PIN_CFG(216, GPIO)
 #define GPIO216_MC1_DAT2DIR	PIN_CFG(216, ALT_A)
 #define GPIO216_MC3_CMDDIR	PIN_CFG(216, ALT_B)
-#define GPIO216_I2C3_SDA	PIN_CFG_PULL(216, ALT_C, UP)
+#define GPIO216_I2C3_SDA	PIN_CFG_INPUT(216, ALT_C, PULLUP)
+#define GPIO216_SPI2_FRM	PIN_CFG(216, ALT_C)
 
 #define GPIO217_GPIO		PIN_CFG(217, GPIO)
 #define GPIO217_MC1_DAT0DIR	PIN_CFG(217, ALT_A)
 #define GPIO217_MC3_DAT31DIR	PIN_CFG(217, ALT_B)
 #define GPIO217_CLKOUT2		PIN_CFG(217, ALT_C)
+#define GPIO217_SPI2_CLK	PIN_CFG(217, ALT_C)
 
 #define GPIO218_GPIO		PIN_CFG(218, GPIO)
 #define GPIO218_MC1_DAT31DIR	PIN_CFG(218, ALT_A)
 #define GPIO218_MC3_DAT0DIR	PIN_CFG(218, ALT_B)
-#define GPIO218_I2C3_SCL	PIN_CFG_PULL(218, ALT_C, UP)
+#define GPIO218_I2C3_SCL	PIN_CFG_INPUT(218, ALT_C, PULLUP)
+#define GPIO218_SPI2_RXD	PIN_CFG(218, ALT_C)
 
 #define GPIO219_GPIO		PIN_CFG(219, GPIO)
 #define GPIO219_HSIR_FLA0	PIN_CFG(219, ALT_A)
@@ -694,12 +698,12 @@
 #define GPIO229_GPIO		PIN_CFG(229, GPIO)
 #define GPIO229_CLKOUT1		PIN_CFG(229, ALT_A)
 #define GPIO229_PWL		PIN_CFG(229, ALT_B)
-#define GPIO229_I2C3_SDA	PIN_CFG_PULL(229, ALT_C, UP)
+#define GPIO229_I2C3_SDA	PIN_CFG_INPUT(229, ALT_C, PULLUP)
 
 #define GPIO230_GPIO		PIN_CFG(230, GPIO)
 #define GPIO230_CLKOUT2		PIN_CFG(230, ALT_A)
 #define GPIO230_PWL		PIN_CFG(230, ALT_B)
-#define GPIO230_I2C3_SCL	PIN_CFG_PULL(230, ALT_C, UP)
+#define GPIO230_I2C3_SCL	PIN_CFG_INPUT(230, ALT_C, PULLUP)
 
 #define GPIO256_GPIO		PIN_CFG(256, GPIO)
 #define GPIO256_USB_NXT		PIN_CFG(256, ALT_A)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/platsmp.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -96,7 +96,7 @@ int __cpuinit boot_secondary(unsigned in
 	 * the holding pen - release it, then wait for it to flag
 	 * that it has been released by resetting pen_release.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	gic_raise_softirq(cpumask_of(cpu), 1);
 
@@ -156,12 +156,10 @@ void __init smp_init_cpus(void)
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "U8500: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-ux500/timer.c linux-libre-3.2-gnu1/arch/arm/mach-ux500/timer.c
--- linux-libre-3.1-gnu1/arch/arm/mach-ux500/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-ux500/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ */
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/localtimer.h>
+
+#include <plat/mtu.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+static void __init ux500_timer_init(void)
+{
+	void __iomem *prcmu_timer_base;
+
+	if (cpu_is_u5500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U5500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U5500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
+	} else if (cpu_is_u8500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U8500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U8500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
+	} else {
+		ux500_unknown_soc();
+	}
+
+	/*
+	 * Here we register the timerblocks active in the system.
+	 * Localtimers (twd) is started when both cpu is up and running.
+	 * MTU register a clocksource, clockevent and sched_clock.
+	 * Since the MTU is located in the VAPE power domain
+	 * it will be cleared in sleep which makes it unsuitable.
+	 * We however need it as a timer tick (clockevent)
+	 * during boot to calibrate delay until twd is started.
+	 * RTC-RTT have problems as timer tick during boot since it is
+	 * depending on delay which is not yet calibrated. RTC-RTT is in the
+	 * always-on powerdomain and is used as clockevent instead of twd when
+	 * sleeping.
+	 * The PRCMU timer 4(3 for DB5500) register a clocksource and
+	 * sched_clock with higher rating then MTU since is always-on.
+	 *
+	 */
+
+	nmdk_timer_init();
+	clksrc_dbx500_prcmu_init(prcmu_timer_base);
+}
+
+static void ux500_timer_reset(void)
+{
+	nmdk_clkevt_reset();
+	nmdk_clksrc_reset();
+}
+
+struct sys_timer ux500_timer = {
+	.init		= ux500_timer_init,
+	.resume		= ux500_timer_reset,
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp,      #0x001F0000
 		orr	\rp, \rp, #0x00001000
 		orr	\rv, \rp, #0xf1000000	@ virtual base
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-versatile/include/mach/memory.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-versatile/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/versatile_ab.c linux-libre-3.2-gnu1/arch/arm/mach-versatile/versatile_ab.c
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/versatile_ab.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/versatile_ab.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 
 MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-versatile/versatile_pb.c linux-libre-3.2-gnu1/arch/arm/mach-versatile/versatile_pb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-versatile/versatile_pb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-versatile/versatile_pb.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,7 +103,7 @@ static void __init versatile_pb_init(voi
 
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c linux-libre-3.2-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,6 +221,12 @@ static void ct_ca9x4_init_cpu_map(void)
 {
 	int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; ++i)
 		set_cpu_possible(i, true);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/hotplug.c linux-libre-3.2-gnu1/arch/arm/mach-vexpress/hotplug.c
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/system.h>
 
 extern volatile int pen_release;
 
@@ -62,15 +63,9 @@ static inline void platform_do_lowpower(
 	 * code will have already disabled interrupts
 	 */
 	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
+		wfi();
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #define DEBUG_LL_UART_OFFSET	0x00009000
 
-		.macro	addruart,rp,rv
+		.macro	addruart,rp,rv,tmp
 		mov	\rp, #DEBUG_LL_UART_OFFSET
 		orr	\rv, \rp, #0xf8000000	@ virtual base
 		orr	\rp, \rp, #0x10000000	@ physical base
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
-
 #define __io(a)		__typesafe_io(a)
 #define __mem_pci(a)	(a)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/*
- *  arch/arm/mach-vexpress/include/mach/memory.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x60000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-vexpress/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x60008000
+   zreladdr-y	+= 0x60008000
 params_phys-y	:= 0x60000100
 initrd_phys-y	:= 0x60800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vexpress/v2m.c linux-libre-3.2-gnu1/arch/arm/mach-vexpress/v2m.c
--- linux-libre-3.1-gnu1/arch/arm/mach-vexpress/v2m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vexpress/v2m.c	2012-01-04 18:55:44.000000000 -0500
@@ -443,7 +443,7 @@ static void __init v2m_init(void)
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= v2m_map_io,
 	.init_early	= v2m_init_early,
 	.init_irq	= v2m_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/bv07.c linux-libre-3.2-gnu1/arch/arm/mach-vt8500/bv07.c
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/bv07.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/bv07.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ void __init bv07_init(void)
 }
 
 MACHINE_START(BV07, "Benign BV07 Mini Netbook")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= vt8500_reserve_mem,
 	.map_io		= vt8500_map_io,
 	.init_irq	= vt8500_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	mov	\rp,      #0x00200000
 	orr	\rv, \rp, #0xf8000000
 	orr	\rp, \rp, #0xd8000000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
-
 #define __io(a)		__typesafe_io((a) + 0xf0000000)
 #define __mem_pci(a)	(a)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/memory.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-vt8500/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x01000000
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-vt8500/wm8505_7in.c linux-libre-3.2-gnu1/arch/arm/mach-vt8500/wm8505_7in.c
--- linux-libre-3.1-gnu1/arch/arm/mach-vt8500/wm8505_7in.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-vt8500/wm8505_7in.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ void __init wm8505_7in_init(void)
 }
 
 MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= wm8505_reserve_mem,
 	.map_io		= wm8505_map_io,
 	.init_irq	= wm8505_init_irq,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/cpu.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@ static DEFINE_CLK(emc, 7);
 static DEFINE_SUBCLK(rmii, 2);
 static DEFINE_CLK(usbd, 8);
 static DEFINE_CLK(usbh, 9);
-static DEFINE_CLK(g2d, 10);;
+static DEFINE_CLK(g2d, 10);
 static DEFINE_CLK(pwm, 18);
 static DEFINE_CLK(ps2, 24);
 static DEFINE_CLK(kpi, 25);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/dev.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/dev.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -422,7 +422,7 @@ struct platform_device nuc900_device_kpi
 
 /* LCD controller*/
 
-static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
+static struct nuc900fb_display nuc900_lcd_info[] = {
 	/* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
 	[0] = {
 		.type		= LCM_DCCS_VA_SRC_RGB565,
@@ -445,7 +445,7 @@ static struct nuc900fb_display __initdat
 	},
 };
 
-static struct nuc900fb_mach_info nuc900_fb_info __initdata = {
+static struct nuc900fb_mach_info nuc900_fb_info = {
 #if defined(CONFIG_GPM1040A0_320X240)
 	.displays		= &nuc900_lcd_info[0],
 #else
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,16 +15,12 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 static inline int gpio_to_irq(unsigned gpio)
 {
 	return gpio;
 }
+#define gpio_to_irq gpio_to_irq
 
 static inline int irq_to_gpio(unsigned irq)
 {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/memory.h
- *
- * 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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/mfp.h linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/mfp.h
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/mfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/mfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 extern void mfp_set_groupf(struct device *dev);
 extern void mfp_set_groupc(struct device *dev);
 extern void mfp_set_groupi(struct device *dev);
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
+extern void mfp_set_groupd(struct device *dev, const char *subname);
 
 #endif /* __ASM_ARCH_MFP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/nuc900_spi.h linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/nuc900_spi.h
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/include/mach/nuc900_spi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/include/mach/nuc900_spi.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_SPI_H
 #define __ASM_ARCH_SPI_H
 
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
 
 struct nuc900_spi_info {
 	unsigned int num_cs;
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc910evb.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc910evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc910evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc910evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,6 @@ static void __init nuc910evb_init(void)
 
 MACHINE_START(W90P910EVB, "W90P910EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc910evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc910evb_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc950evb.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc950evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc950evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc950evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,6 @@ static void __init nuc950evb_init(void)
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc950evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc950evb_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc960evb.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc960evb.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mach-nuc960evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mach-nuc960evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,6 @@ static void __init nuc960evb_init(void)
 
 MACHINE_START(W90N960EVB, "W90N960EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc960evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc960evb_init,
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-w90x900/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mfp.c linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mfp.c
--- linux-libre-3.1-gnu1/arch/arm/mach-w90x900/mfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-w90x900/mfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,10 +26,8 @@
 #define REG_MFSEL	(W90X900_VA_GCR + 0xC)
 
 #define GPSELF		(0x01 << 1)
-
 #define GPSELC		(0x03 << 2)
-#define ENKPI		(0x02 << 2)
-#define ENNAND		(0x01 << 2)
+#define GPSELD		(0x0f << 4)
 
 #define GPSELEI0	(0x01 << 26)
 #define GPSELEI1	(0x01 << 27)
@@ -37,11 +35,16 @@
 #define GPIOG0TO1	(0x03 << 14)
 #define GPIOG2TO3	(0x03 << 16)
 #define GPIOG22TO23	(0x03 << 22)
+#define GPIOG18TO20	(0x07 << 18)
 
 #define ENSPI		(0x0a << 14)
 #define ENI2C0		(0x01 << 14)
 #define ENI2C1		(0x01 << 16)
 #define ENAC97		(0x02 << 22)
+#define ENSD1		(0x02 << 18)
+#define ENSD0		(0x0a << 4)
+#define ENKPI		(0x02 << 2)
+#define ENNAND		(0x01 << 2)
 
 static DEFINE_MUTEX(mfp_mutex);
 
@@ -127,16 +130,19 @@ void mfp_set_groupi(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupi);
 
-void mfp_set_groupg(struct device *dev)
+void mfp_set_groupg(struct device *dev, const char *subname)
 {
 	unsigned long mfpen;
 	const char *dev_id;
 
-	BUG_ON(!dev);
+	BUG_ON((!dev) && (!subname));
 
 	mutex_lock(&mfp_mutex);
 
-	dev_id = dev_name(dev);
+	if (subname != NULL)
+		dev_id = subname;
+	else
+		dev_id = dev_name(dev);
 
 	mfpen = __raw_readl(REG_MFSEL);
 
@@ -152,6 +158,9 @@ void mfp_set_groupg(struct device *dev)
 	} else if (strcmp(dev_id, "nuc900-audio") == 0) {
 		mfpen &= ~(GPIOG22TO23);
 		mfpen |= ENAC97;/*enable AC97*/
+	} else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
+		mfpen &= ~(GPIOG18TO20);
+		mfpen |= (ENSD1 | 0x01);/*enable sd1*/
 	} else {
 		mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/
 	}
@@ -162,3 +171,30 @@ void mfp_set_groupg(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupg);
 
+void mfp_set_groupd(struct device *dev, const char *subname)
+{
+	unsigned long mfpen;
+	const char *dev_id;
+
+	BUG_ON((!dev) && (!subname));
+
+	mutex_lock(&mfp_mutex);
+
+	if (subname != NULL)
+		dev_id = subname;
+	else
+		dev_id = dev_name(dev);
+
+	mfpen = __raw_readl(REG_MFSEL);
+
+	if (strcmp(dev_id, "nuc900-mmc-port0") == 0) {
+		mfpen &= ~GPSELD;/*enable sd0*/
+		mfpen |= ENSD0;
+	} else
+		mfpen &= (~GPSELD);
+
+	__raw_writel(mfpen, REG_MFSEL);
+
+	mutex_unlock(&mfp_mutex);
+}
+EXPORT_SYMBOL(mfp_set_groupd);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-zynq/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/mach-zynq/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/mach-zynq/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-zynq/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #include <mach/zynq_soc.h>
 #include <mach/uart.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =LL_UART_PADDR	@ physical
 		ldr	\rv, =LL_UART_VADDR	@ virtual
 		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-zynq/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/mach-zynq/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/mach-zynq/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-zynq/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/memory.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_MEMORY_H__
-#define __MACH_MEMORY_H__
-
-#include <asm/sizes.h>
-
-#define PLAT_PHYS_OFFSET	UL(0x0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mach-zynq/Makefile.boot linux-libre-3.2-gnu1/arch/arm/mach-zynq/Makefile.boot
--- linux-libre-3.1-gnu1/arch/arm/mach-zynq/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mach-zynq/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/arm/Makefile linux-libre-3.2-gnu1/arch/arm/Makefile
--- linux-libre-3.1-gnu1/arch/arm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,9 @@ textofs-$(CONFIG_PM_H1940)      := 0x001
 ifeq ($(CONFIG_ARCH_SA1100),y)
 textofs-$(CONFIG_SA1111) := 0x00208000
 endif
+textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
@@ -141,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110)		:= ebsa1
 machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
 machine-$(CONFIG_ARCH_GEMINI)		:= gemini
 machine-$(CONFIG_ARCH_H720X)		:= h720x
+machine-$(CONFIG_ARCH_HIGHBANK)		:= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	:= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		:= iop13xx
 machine-$(CONFIG_ARCH_IOP32X)		:= iop32x
@@ -154,10 +158,8 @@ machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
-machine-$(CONFIG_ARCH_MX1)		:= imx
-machine-$(CONFIG_ARCH_MX2)		:= imx
-machine-$(CONFIG_ARCH_MX25)		:= imx
-machine-$(CONFIG_ARCH_MX3)		:= imx
+machine-$(CONFIG_ARCH_IMX_V4_V5)	:= imx
+machine-$(CONFIG_ARCH_IMX_V6_V7)	:= imx
 machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXS)		:= mxs
 machine-$(CONFIG_ARCH_NETX)		:= netx
@@ -167,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2)		:= omap2
 machine-$(CONFIG_ARCH_OMAP3)		:= omap2
 machine-$(CONFIG_ARCH_OMAP4)		:= omap2
 machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
+machine-$(CONFIG_ARCH_PICOXCELL)	:= picoxcell
 machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
 machine-$(CONFIG_ARCH_PRIMA2)		:= prima2
 machine-$(CONFIG_ARCH_PXA)		:= pxa
@@ -177,7 +180,7 @@ machine-$(CONFIG_ARCH_S3C64XX)		:= s3c64
 machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
-machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos4
+machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
@@ -189,7 +192,6 @@ machine-$(CONFIG_ARCH_VERSATILE)	:= vers
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
 machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
-machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
 machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/alignment.c linux-libre-3.2-gnu1/arch/arm/mm/alignment.c
--- linux-libre-3.1-gnu1/arch/arm/mm/alignment.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/alignment.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,16 +86,6 @@ core_param(alignment, ai_usermode, int,
 #define UM_FIXUP	(1 << 1)
 #define UM_SIGNAL	(1 << 2)
 
-#ifdef CONFIG_PROC_FS
-static const char *usermode_action[] = {
-	"ignored",
-	"warn",
-	"fixup",
-	"fixup+warn",
-	"signal",
-	"signal+warn"
-};
-
 /* Return true if and only if the ARMv6 unaligned access model is in use. */
 static bool cpu_is_v6_unaligned(void)
 {
@@ -123,6 +113,16 @@ static int safe_usermode(int new_usermod
 	return new_usermode;
 }
 
+#ifdef CONFIG_PROC_FS
+static const char *usermode_action[] = {
+	"ignored",
+	"warn",
+	"fixup",
+	"fixup+warn",
+	"signal",
+	"signal+warn"
+};
+
 static int alignment_proc_show(struct seq_file *m, void *v)
 {
 	seq_printf(m, "User:\t\t%lu\n", ai_user);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/cache-l2x0.c linux-libre-3.2-gnu1/arch/arm/mm/cache-l2x0.c
--- linux-libre-3.1-gnu1/arch/arm/mm/cache-l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/cache-l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -26,15 +29,23 @@
 #define CACHE_LINE_SIZE		32
 
 static void __iomem *l2x0_base;
-static DEFINE_SPINLOCK(l2x0_lock);
+static DEFINE_RAW_SPINLOCK(l2x0_lock);
 static uint32_t l2x0_way_mask;	/* Bitmask of active ways */
 static uint32_t l2x0_size;
 
+struct l2x0_regs l2x0_saved_regs;
+
+struct l2x0_of_data {
+	void (*setup)(const struct device_node *, __u32 *, __u32 *);
+	void (*save)(void);
+	void (*resume)(void);
+};
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
 	/* wait for cache operation by line or way to complete */
 	while (readl_relaxed(reg) & mask)
-		;
+		cpu_relax();
 }
 
 #ifdef CONFIG_CACHE_PL310
@@ -50,7 +61,7 @@ static inline void cache_sync(void)
 {
 	void __iomem *base = l2x0_base;
 
-#ifdef CONFIG_ARM_ERRATA_753970
+#ifdef CONFIG_PL310_ERRATA_753970
 	/* write to an unmmapped register */
 	writel_relaxed(0, base + L2X0_DUMMY_REG);
 #else
@@ -115,9 +126,9 @@ static void l2x0_cache_sync(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void __l2x0_flush_all(void)
@@ -134,9 +145,9 @@ static void l2x0_flush_all(void)
 	unsigned long flags;
 
 	/* clean all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	__l2x0_flush_all();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_all(void)
@@ -144,11 +155,11 @@ static void l2x0_clean_all(void)
 	unsigned long flags;
 
 	/* clean all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
 	cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_all(void)
@@ -156,13 +167,13 @@ static void l2x0_inv_all(void)
 	unsigned long flags;
 
 	/* invalidate all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	/* Invalidating when L2 is enabled is a nono */
 	BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_range(unsigned long start, unsigned long end)
@@ -170,7 +181,7 @@ static void l2x0_inv_range(unsigned long
 	void __iomem *base = l2x0_base;
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	if (start & (CACHE_LINE_SIZE - 1)) {
 		start &= ~(CACHE_LINE_SIZE - 1);
 		debug_writel(0x03);
@@ -195,13 +206,13 @@ static void l2x0_inv_range(unsigned long
 		}
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_INV_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_range(unsigned long start, unsigned long end)
@@ -214,7 +225,7 @@ static void l2x0_clean_range(unsigned lo
 		return;
 	}
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
 		unsigned long blk_end = start + min(end - start, 4096UL);
@@ -225,13 +236,13 @@ static void l2x0_clean_range(unsigned lo
 		}
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_flush_range(unsigned long start, unsigned long end)
@@ -244,7 +255,7 @@ static void l2x0_flush_range(unsigned lo
 		return;
 	}
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
 		unsigned long blk_end = start + min(end - start, 4096UL);
@@ -257,27 +268,27 @@ static void l2x0_flush_range(unsigned lo
 		debug_writel(0x00);
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_disable(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	__l2x0_flush_all();
 	writel_relaxed(0, l2x0_base + L2X0_CTRL);
 	dsb();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void __init l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(__u32 cache_id)
 {
 	int lockregs;
 	int i;
@@ -353,6 +364,8 @@ void __init l2x0_init(void __iomem *base
 		/* l2x0 controller is disabled */
 		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
 
+		l2x0_saved_regs.aux_ctrl = aux;
+
 		l2x0_inv_all();
 
 		/* enable L2X0 */
@@ -372,3 +385,202 @@ void __init l2x0_init(void __iomem *base
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
 			ways, cache_id, aux, l2x0_size);
 }
+
+#ifdef CONFIG_OF
+static void __init l2x0_of_setup(const struct device_node *np,
+				 __u32 *aux_val, __u32 *aux_mask)
+{
+	u32 data[2] = { 0, 0 };
+	u32 tag = 0;
+	u32 dirty = 0;
+	u32 val = 0, mask = 0;
+
+	of_property_read_u32(np, "arm,tag-latency", &tag);
+	if (tag) {
+		mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
+		val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
+	}
+
+	of_property_read_u32_array(np, "arm,data-latency",
+				   data, ARRAY_SIZE(data));
+	if (data[0] && data[1]) {
+		mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
+			L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
+		val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
+		       ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
+	}
+
+	of_property_read_u32(np, "arm,dirty-latency", &dirty);
+	if (dirty) {
+		mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
+		val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
+	}
+
+	*aux_val &= ~mask;
+	*aux_val |= val;
+	*aux_mask &= ~mask;
+}
+
+static void __init pl310_of_setup(const struct device_node *np,
+				  __u32 *aux_val, __u32 *aux_mask)
+{
+	u32 data[3] = { 0, 0, 0 };
+	u32 tag[3] = { 0, 0, 0 };
+	u32 filter[2] = { 0, 0 };
+
+	of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
+	if (tag[0] && tag[1] && tag[2])
+		writel_relaxed(
+			((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+			((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+			((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+			l2x0_base + L2X0_TAG_LATENCY_CTRL);
+
+	of_property_read_u32_array(np, "arm,data-latency",
+				   data, ARRAY_SIZE(data));
+	if (data[0] && data[1] && data[2])
+		writel_relaxed(
+			((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+			((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+			((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+			l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+	of_property_read_u32_array(np, "arm,filter-ranges",
+				   filter, ARRAY_SIZE(filter));
+	if (filter[1]) {
+		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
+			       l2x0_base + L2X0_ADDR_FILTER_END);
+		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
+			       l2x0_base + L2X0_ADDR_FILTER_START);
+	}
+}
+
+static void __init pl310_save(void)
+{
+	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+		L2X0_CACHE_ID_RTL_MASK;
+
+	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
+		L2X0_TAG_LATENCY_CTRL);
+	l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
+		L2X0_DATA_LATENCY_CTRL);
+	l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_END);
+	l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_START);
+
+	if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+		/*
+		 * From r2p0, there is Prefetch offset/control register
+		 */
+		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
+			L2X0_PREFETCH_CTRL);
+		/*
+		 * From r3p0, there is Power control register
+		 */
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+			l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
+				L2X0_POWER_CTRL);
+	}
+}
+
+static void l2x0_resume(void)
+{
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore aux ctrl and enable l2 */
+		l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
+
+		writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
+			L2X0_AUX_CTRL);
+
+		l2x0_inv_all();
+
+		writel_relaxed(1, l2x0_base + L2X0_CTRL);
+	}
+}
+
+static void pl310_resume(void)
+{
+	u32 l2x0_revision;
+
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore pl310 setup */
+		writel_relaxed(l2x0_saved_regs.tag_latency,
+			l2x0_base + L2X0_TAG_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.data_latency,
+			l2x0_base + L2X0_DATA_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.filter_end,
+			l2x0_base + L2X0_ADDR_FILTER_END);
+		writel_relaxed(l2x0_saved_regs.filter_start,
+			l2x0_base + L2X0_ADDR_FILTER_START);
+
+		l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+			L2X0_CACHE_ID_RTL_MASK;
+
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+			writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+				l2x0_base + L2X0_PREFETCH_CTRL);
+			if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+				writel_relaxed(l2x0_saved_regs.pwr_ctrl,
+					l2x0_base + L2X0_POWER_CTRL);
+		}
+	}
+
+	l2x0_resume();
+}
+
+static const struct l2x0_of_data pl310_data = {
+	pl310_of_setup,
+	pl310_save,
+	pl310_resume,
+};
+
+static const struct l2x0_of_data l2x0_data = {
+	l2x0_of_setup,
+	NULL,
+	l2x0_resume,
+};
+
+static const struct of_device_id l2x0_ids[] __initconst = {
+	{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
+	{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
+	{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
+	{}
+};
+
+int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+	struct device_node *np;
+	struct l2x0_of_data *data;
+	struct resource res;
+
+	np = of_find_matching_node(NULL, l2x0_ids);
+	if (!np)
+		return -ENODEV;
+
+	if (of_address_to_resource(np, 0, &res))
+		return -ENODEV;
+
+	l2x0_base = ioremap(res.start, resource_size(&res));
+	if (!l2x0_base)
+		return -ENOMEM;
+
+	l2x0_saved_regs.phy_base = res.start;
+
+	data = of_match_node(l2x0_ids, np)->data;
+
+	/* L2 configuration can only be changed if the cache is disabled */
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		if (data->setup)
+			data->setup(np, &aux_val, &aux_mask);
+	}
+
+	if (data->save)
+		data->save();
+
+	l2x0_init(l2x0_base, aux_val, aux_mask);
+
+	outer_cache.resume = data->resume;
+	return 0;
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/context.c linux-libre-3.2-gnu1/arch/arm/mm/context.c
--- linux-libre-3.1-gnu1/arch/arm/mm/context.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/context.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-static DEFINE_SPINLOCK(cpu_asid_lock);
+static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 unsigned int cpu_last_asid = ASID_FIRST_VERSION;
 #ifdef CONFIG_SMP
 DEFINE_PER_CPU(struct mm_struct *, current_mm);
@@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct mm_struct *, curre
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
 	mm->context.id = 0;
-	spin_lock_init(&mm->context.id_lock);
+	raw_spin_lock_init(&mm->context.id_lock);
 }
 
 static void flush_context(void)
@@ -58,7 +58,7 @@ static void set_mm_context(struct mm_str
 	 * the broadcast. This function is also called via IPI so the
 	 * mm->context.id_lock has to be IRQ-safe.
 	 */
-	spin_lock_irqsave(&mm->context.id_lock, flags);
+	raw_spin_lock_irqsave(&mm->context.id_lock, flags);
 	if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
 		/*
 		 * Old version of ASID found. Set the new one and
@@ -67,7 +67,7 @@ static void set_mm_context(struct mm_str
 		mm->context.id = asid;
 		cpumask_clear(mm_cpumask(mm));
 	}
-	spin_unlock_irqrestore(&mm->context.id_lock, flags);
+	raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
 
 	/*
 	 * Set the mm_cpumask(mm) bit for the current CPU.
@@ -117,7 +117,7 @@ void __new_context(struct mm_struct *mm)
 {
 	unsigned int asid;
 
-	spin_lock(&cpu_asid_lock);
+	raw_spin_lock(&cpu_asid_lock);
 #ifdef CONFIG_SMP
 	/*
 	 * Check the ASID again, in case the change was broadcast from
@@ -125,7 +125,7 @@ void __new_context(struct mm_struct *mm)
 	 */
 	if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
 		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-		spin_unlock(&cpu_asid_lock);
+		raw_spin_unlock(&cpu_asid_lock);
 		return;
 	}
 #endif
@@ -153,5 +153,5 @@ void __new_context(struct mm_struct *mm)
 	}
 
 	set_mm_context(mm, asid);
-	spin_unlock(&cpu_asid_lock);
+	raw_spin_unlock(&cpu_asid_lock);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/copypage-v4mc.c linux-libre-3.2-gnu1/arch/arm/mm/copypage-v4mc.c
--- linux-libre-3.1-gnu1/arch/arm/mm/copypage-v4mc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/copypage-v4mc.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_MT_MINICACHE)
 
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
 
 /*
  * ARMv4 mini-dcache optimised copy_user_highpage
@@ -76,14 +76,14 @@ void v4_mc_copy_user_highpage(struct pag
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
-	spin_lock(&minicache_lock);
+	raw_spin_lock(&minicache_lock);
 
 	set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
 	flush_tlb_kernel_page(0xffff8000);
 
 	mc_copy_user_page((void *)0xffff8000, kto);
 
-	spin_unlock(&minicache_lock);
+	raw_spin_unlock(&minicache_lock);
 
 	kunmap_atomic(kto, KM_USER1);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/copypage-v6.c linux-libre-3.2-gnu1/arch/arm/mm/copypage-v6.c
--- linux-libre-3.1-gnu1/arch/arm/mm/copypage-v6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/copypage-v6.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #define from_address	(0xffff8000)
 #define to_address	(0xffffc000)
 
-static DEFINE_SPINLOCK(v6_lock);
+static DEFINE_RAW_SPINLOCK(v6_lock);
 
 /*
  * Copy the user page.  No aliasing to deal with so we can just
@@ -88,7 +88,7 @@ static void v6_copy_user_highpage_aliasi
 	 * Now copy the page using the same cache colour as the
 	 * pages ultimate destination.
 	 */
-	spin_lock(&v6_lock);
+	raw_spin_lock(&v6_lock);
 
 	set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
 	set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
@@ -101,7 +101,7 @@ static void v6_copy_user_highpage_aliasi
 
 	copy_page((void *)kto, (void *)kfrom);
 
-	spin_unlock(&v6_lock);
+	raw_spin_unlock(&v6_lock);
 }
 
 /*
@@ -121,13 +121,13 @@ static void v6_clear_user_highpage_alias
 	 * Now clear the page using the same cache colour as
 	 * the pages ultimate destination.
 	 */
-	spin_lock(&v6_lock);
+	raw_spin_lock(&v6_lock);
 
 	set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
 	flush_tlb_kernel_page(to);
 	clear_page((void *)to);
 
-	spin_unlock(&v6_lock);
+	raw_spin_unlock(&v6_lock);
 }
 
 struct cpu_user_fns v6_user_fns __initdata = {
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/copypage-xscale.c linux-libre-3.2-gnu1/arch/arm/mm/copypage-xscale.c
--- linux-libre-3.1-gnu1/arch/arm/mm/copypage-xscale.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/copypage-xscale.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_MT_MINICACHE)
 
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
 
 /*
  * XScale mini-dcache optimised copy_user_highpage
@@ -98,14 +98,14 @@ void xscale_mc_copy_user_highpage(struct
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
-	spin_lock(&minicache_lock);
+	raw_spin_lock(&minicache_lock);
 
 	set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
 	flush_tlb_kernel_page(COPYPAGE_MINICACHE);
 
 	mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
-	spin_unlock(&minicache_lock);
+	raw_spin_unlock(&minicache_lock);
 
 	kunmap_atomic(kto, KM_USER1);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/dma-mapping.c linux-libre-3.2-gnu1/arch/arm/mm/dma-mapping.c
--- linux-libre-3.1-gnu1/arch/arm/mm/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,12 +18,14 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/highmem.h>
+#include <linux/slab.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
+#include <asm/mach/arch.h>
 
 #include "mm.h"
 
@@ -117,26 +119,36 @@ static void __dma_free_buffer(struct pag
 }
 
 #ifdef CONFIG_MMU
-/* Sanity check size */
-#if (CONSISTENT_DMA_SIZE % SZ_2M)
-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
-#endif
 
-#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT)
 
 /*
  * These are the page tables (2MB each) covering uncached, DMA consistent allocations
  */
-static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
+static pte_t **consistent_pte;
+
+#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
+
+unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
+
+void __init init_consistent_dma_size(unsigned long size)
+{
+	unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
+
+	BUG_ON(consistent_pte); /* Check we're called before DMA region init */
+	BUG_ON(base < VMALLOC_END);
+
+	/* Grow region to accommodate specified size  */
+	if (base < consistent_base)
+		consistent_base = base;
+}
 
 #include "vmregion.h"
 
 static struct arm_vmregion_head consistent_head = {
 	.vm_lock	= __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
 	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
-	.vm_start	= CONSISTENT_BASE,
 	.vm_end		= CONSISTENT_END,
 };
 
@@ -155,7 +167,17 @@ static int __init consistent_init(void)
 	pmd_t *pmd;
 	pte_t *pte;
 	int i = 0;
-	u32 base = CONSISTENT_BASE;
+	unsigned long base = consistent_base;
+	unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
+
+	consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
+	if (!consistent_pte) {
+		pr_err("%s: no memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
+	consistent_head.vm_start = base;
 
 	do {
 		pgd = pgd_offset(&init_mm, base);
@@ -183,7 +205,7 @@ static int __init consistent_init(void)
 		}
 
 		consistent_pte[i++] = pte;
-		base += (1 << PGDIR_SHIFT);
+		base += PMD_SIZE;
 	} while (base < CONSISTENT_END);
 
 	return ret;
@@ -198,7 +220,7 @@ __dma_alloc_remap(struct page *page, siz
 	size_t align;
 	int bit;
 
-	if (!consistent_pte[0]) {
+	if (!consistent_pte) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
 		dump_stack();
 		return NULL;
@@ -310,6 +332,15 @@ __dma_alloc(struct device *dev, size_t s
 	struct page *page;
 	void *addr;
 
+	/*
+	 * Following is a work-around (a.k.a. hack) to prevent pages
+	 * with __GFP_COMP being passed to split_page() which cannot
+	 * handle them.  The real problem is that this flag probably
+	 * should be 0 on ARM as it is not supported on this
+	 * platform; see CONFIG_HUGETLBFS.
+	 */
+	gfp &= ~(__GFP_COMP);
+
 	*handle = ~0;
 	size = PAGE_ALIGN(size);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/fault-armv.c linux-libre-3.2-gnu1/arch/arm/mm/fault-armv.c
--- linux-libre-3.1-gnu1/arch/arm/mm/fault-armv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/fault-armv.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/fault.c linux-libre-3.2-gnu1/arch/arm/mm/fault.c
--- linux-libre-3.1-gnu1/arch/arm/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
 
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/init.c linux-libre-3.2-gnu1/arch/arm/mm/init.c
--- linux-libre-3.1-gnu1/arch/arm/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/mman.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
@@ -660,9 +661,6 @@ void __init mem_init(void)
 			"    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 #endif
 			"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
-#ifdef CONFIG_MMU
-			"    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#endif
 			"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 			"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #ifdef CONFIG_HIGHMEM
@@ -681,9 +679,6 @@ void __init mem_init(void)
 			MLK(ITCM_OFFSET, (unsigned long) itcm_end),
 #endif
 			MLK(FIXADDR_START, FIXADDR_TOP),
-#ifdef CONFIG_MMU
-			MLM(CONSISTENT_BASE, CONSISTENT_END),
-#endif
 			MLM(VMALLOC_START, VMALLOC_END),
 			MLM(PAGE_OFFSET, (unsigned long)high_memory),
 #ifdef CONFIG_HIGHMEM
@@ -706,9 +701,6 @@ void __init mem_init(void)
 	 * be detected at build time already.
 	 */
 #ifdef CONFIG_MMU
-	BUILD_BUG_ON(VMALLOC_END			> CONSISTENT_BASE);
-	BUG_ON(VMALLOC_END				> CONSISTENT_BASE);
-
 	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR);
 	BUG_ON(TASK_SIZE 				> MODULES_VADDR);
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/ioremap.c linux-libre-3.2-gnu1/arch/arm/mm/ioremap.c
--- linux-libre-3.1-gnu1/arch/arm/mm/ioremap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/ioremap.c	2012-01-04 18:55:44.000000000 -0500
@@ -289,6 +289,27 @@ __arm_ioremap(unsigned long phys_addr, s
 }
 EXPORT_SYMBOL(__arm_ioremap);
 
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space as memory. Needed when the kernel wants to execute
+ * code in external memory. This is needed for reprogramming source
+ * clocks that would affect normal memory for example. Please see
+ * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
+ */
+void __iomem *
+__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
+{
+	unsigned int mtype;
+
+	if (cached)
+		mtype = MT_MEMORY;
+	else
+		mtype = MT_MEMORY_NONCACHED;
+
+	return __arm_ioremap_caller(phys_addr, size, mtype,
+			__builtin_return_address(0));
+}
+
 void __iounmap(volatile void __iomem *io_addr)
 {
 	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/Kconfig linux-libre-3.2-gnu1/arch/arm/mm/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/mm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -819,10 +819,10 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
-		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+		   REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
 		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
-		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
+		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/mmap.c linux-libre-3.2-gnu1/arch/arm/mm/mmap.c
--- linux-libre-3.1-gnu1/arch/arm/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,7 @@
 #include <linux/io.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <asm/cputype.h>
-#include <asm/system.h>
+#include <asm/cachetype.h>
 
 #define COLOUR_ALIGN(addr,pgoff)		\
 	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\
@@ -32,25 +31,15 @@ arch_get_unmapped_area(struct file *filp
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-	unsigned int cache_type;
-	int do_align = 0, aliasing = 0;
+	int do_align = 0;
+	int aliasing = cache_is_vipt_aliasing();
 
 	/*
 	 * We only need to do colour alignment if either the I or D
-	 * caches alias.  This is indicated by bits 9 and 21 of the
-	 * cache type register.
+	 * caches alias.
 	 */
-	cache_type = read_cpuid_cachetype();
-	if (cache_type != read_cpuid_id()) {
-		aliasing = (cache_type | cache_type >> 12) & (1 << 11);
-		if (aliasing)
-			do_align = filp || flags & MAP_SHARED;
-	}
-#else
-#define do_align 0
-#define aliasing 0
-#endif
+	if (aliasing)
+		do_align = filp || (flags & MAP_SHARED);
 
 	/*
 	 * We enforce the MAP_FIXED case.
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/mm.h linux-libre-3.2-gnu1/arch/arm/mm/mm.h
--- linux-libre-3.1-gnu1/arch/arm/mm/mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/mm.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,8 @@ static inline pmd_t *pmd_off_k(unsigned
 
 struct mem_type {
 	pteval_t prot_pte;
-	unsigned int prot_l1;
-	unsigned int prot_sect;
+	pmdval_t prot_l1;
+	pmdval_t prot_sect;
 	unsigned int domain;
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/mmu.c linux-libre-3.2-gnu1/arch/arm/mm/mmu.c
--- linux-libre-3.1-gnu1/arch/arm/mm/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@ EXPORT_SYMBOL(pgprot_kernel);
 struct cachepolicy {
 	const char	policy[16];
 	unsigned int	cr_mask;
-	unsigned int	pmd;
+	pmdval_t	pmd;
 	pteval_t	pte;
 };
 
@@ -273,6 +273,14 @@ static struct mem_type mem_types[] = {
 		.prot_l1   = PMD_TYPE_TABLE,
 		.domain    = DOMAIN_KERNEL,
 	},
+	[MT_MEMORY_SO] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_MT_UNCACHED,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
+				PMD_SECT_UNCACHED | PMD_SECT_XN,
+		.domain    = DOMAIN_KERNEL,
+	},
 };
 
 const struct mem_type *get_mem_type(unsigned int type)
@@ -288,7 +296,7 @@ static void __init build_mem_type_table(
 {
 	struct cachepolicy *cp;
 	unsigned int cr = get_cr();
-	unsigned int user_pgprot, kern_pgprot, vecs_pgprot;
+	pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
 	int cpu_arch = cpu_architecture();
 	int i;
 
@@ -863,14 +871,14 @@ static inline void prepare_page_table(vo
 	/*
 	 * Clear out all the mappings below the kernel image.
 	 */
-	for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
+	for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 #ifdef CONFIG_XIP_KERNEL
 	/* The XIP kernel is mapped in the module area -- skip over it */
-	addr = ((unsigned long)_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+	addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
 #endif
-	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+	for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
@@ -885,10 +893,12 @@ static inline void prepare_page_table(vo
 	 * memory bank, up to the end of the vmalloc region.
 	 */
 	for (addr = __phys_to_virt(end);
-	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+	     addr < VMALLOC_END; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 }
 
+#define SWAPPER_PG_DIR_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))
+
 /*
  * Reserve the special regions of memory
  */
@@ -898,7 +908,7 @@ void __init arm_mm_memblock_reserve(void
 	 * Reserve the page tables.  These are already in use,
 	 * and can only be in node 0.
 	 */
-	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
+	memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE);
 
 #ifdef CONFIG_SA1111
 	/*
@@ -926,7 +936,7 @@ static void __init devicemaps_init(struc
 	 */
 	vectors_page = early_alloc(PAGE_SIZE);
 
-	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+	for (addr = VMALLOC_END; addr; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-arm920.S linux-libre-3.2-gnu1/arch/arm/mm/proc-arm920.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-arm920.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-arm920.S	2012-01-04 18:55:44.000000000 -0500
@@ -379,31 +379,26 @@ ENTRY(cpu_arm920_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm920_suspend_size
-.equ	cpu_arm920_suspend_size, 4 * 4
+.equ	cpu_arm920_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm920_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
 	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
-	mrc	p15, 0, r7, c1, c0, 0	@ Control register
-	stmia	r0, {r4 - r7}
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_arm920_do_suspend)
 
 ENTRY(cpu_arm920_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
-	ldmia	r0, {r4 - r7}
+	ldmia	r0, {r4 - r6}
 	mcr	p15, 0, r4, c13, c0, 0	@ PID
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
-	mov	r0, r7			@ control register
-	mov	r2, r6, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm920_do_resume)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-arm926.S linux-libre-3.2-gnu1/arch/arm/mm/proc-arm926.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-arm926.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-arm926.S	2012-01-04 18:55:44.000000000 -0500
@@ -394,31 +394,26 @@ ENTRY(cpu_arm926_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm926_suspend_size
-.equ	cpu_arm926_suspend_size, 4 * 4
+.equ	cpu_arm926_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm926_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
 	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
-	mrc	p15, 0, r7, c1, c0, 0	@ Control register
-	stmia	r0, {r4 - r7}
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_arm926_do_suspend)
 
 ENTRY(cpu_arm926_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
-	ldmia	r0, {r4 - r7}
+	ldmia	r0, {r4 - r6}
 	mcr	p15, 0, r4, c13, c0, 0	@ PID
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
-	mov	r0, r7			@ control register
-	mov	r2, r6, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm926_do_resume)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-sa1100.S linux-libre-3.2-gnu1/arch/arm/mm/proc-sa1100.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-sa1100.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-sa1100.S	2012-01-04 18:55:44.000000000 -0500
@@ -168,20 +168,19 @@ ENTRY(cpu_sa1100_set_pte_ext)
 	mov	pc, lr
 
 .globl	cpu_sa1100_suspend_size
-.equ	cpu_sa1100_suspend_size, 4*4
+.equ	cpu_sa1100_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_sa1100_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
-	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r6, c13, c0, 0		@ PID
-	mrc	p15, 0, r7, c1, c0, 0		@ control reg
-	stmia	r0, {r4 - r7}			@ store cp regs
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r5, c13, c0, 0		@ PID
+	mrc	p15, 0, r6, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r6}			@ store cp regs
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_sa1100_do_suspend)
 
 ENTRY(cpu_sa1100_do_resume)
-	ldmia	r0, {r4 - r7}			@ load cp regs
+	ldmia	r0, {r4 - r6}			@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0		@ flush I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0		@ flush I&D cache
@@ -189,13 +188,9 @@ ENTRY(cpu_sa1100_do_resume)
 	mcr	p15, 0, ip, c9, c0, 5		@ allow user space to use RB
 
 	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
-	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r6, c13, c0, 0		@ PID
-	mov	r0, r7				@ control register
-	mov	r2, r5, lsr #14			@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	mcr	p15, 0, r1, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mov	r0, r6				@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_sa1100_do_resume)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-v6.S linux-libre-3.2-gnu1/arch/arm/mm/proc-v6.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-v6.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-v6.S	2012-01-04 18:55:44.000000000 -0500
@@ -128,20 +128,18 @@ ENTRY(cpu_v6_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
-.equ	cpu_v6_suspend_size, 4 * 8
+.equ	cpu_v6_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v6_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ Translation table base 0
-	mrc	p15, 0, r8, c2, c0, 1	@ Translation table base 1
-	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control register
-	mrc	p15, 0, r10, c1, c0, 2	@ co-processor access control
-	mrc	p15, 0, r11, c1, c0, 0	@ control register
-	stmia	r0, {r4 - r11}
-	ldmfd	sp!, {r4- r11, pc}
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mrc	p15, 0, r8, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r9, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r9}
+	ldmfd	sp!, {r4- r9, pc}
 ENDPROC(cpu_v6_do_suspend)
 
 ENTRY(cpu_v6_do_resume)
@@ -150,25 +148,21 @@ ENTRY(cpu_v6_do_resume)
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
 	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
 	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
-	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0, {r4 - r9}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0	@ Translation table base 0
-	mcr	p15, 0, r8, c2, c0, 1	@ Translation table base 1
-	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control register
-	mcr	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mcr	p15, 0, r8, c1, c0, 2	@ co-processor access control
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mcr	p15, 0, ip, c7, c5, 4	@ ISB
-	mov	r0, r11			@ control register
-	mov	r2, r7, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, cpu_resume_l1_flags
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_v6_do_resume)
-cpu_resume_l1_flags:
-	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
-	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
 #endif
 
 	string	cpu_v6_name, "ARMv6-compatible processor"
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-v7.S linux-libre-3.2-gnu1/arch/arm/mm/proc-v7.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-v7.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-v7.S	2012-01-04 18:55:44.000000000 -0500
@@ -217,56 +217,50 @@ ENDPROC(cpu_v7_set_pte_ext)
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 9
-#ifdef CONFIG_PM_SLEEP
+.equ	cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v7_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r10, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	stmia	r0!, {r4 - r6}
+	mrc	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
+	stmia	r0!, {r4 - r5}
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ TTB 0
-	mrc	p15, 0, r8, c2, c0, 1	@ TTB 1
-	mrc	p15, 0, r9, c1, c0, 0	@ Control register
-	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access control
-	stmia	r0, {r6 - r11}
-	ldmfd	sp!, {r4 - r11, pc}
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r6 - r10}
+	ldmfd	sp!, {r4 - r10, pc}
 ENDPROC(cpu_v7_do_suspend)
 
 ENTRY(cpu_v7_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate TLBs
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
-	ldmia	r0!, {r4 - r6}
+	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0!, {r4 - r5}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	ldmia	r0, {r6 - r11}
+	mcr	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
+	ldmia	r0, {r6 - r10}
 	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0	@ TTB 0
-	mcr	p15, 0, r8, c2, c0, 1	@ TTB 1
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mrc	p15, 0, r4, c1, c0, 1	@ Read Auxiliary control register
-	teq	r4, r10			@ Is it already set?
-	mcrne	p15, 0, r10, c1, c0, 1	@ No, so write it
-	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	teq	r4, r9			@ Is it already set?
+	mcrne	p15, 0, r9, c1, c0, 1	@ No, so write it
+	mcr	p15, 0, r10, c1, c0, 2	@ Co-processor access control
 	ldr	r4, =PRRR		@ PRRR
 	ldr	r5, =NMRR		@ NMRR
 	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
 	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
 	isb
 	dsb
-	mov	r0, r9			@ control register
-	mov	r2, r7, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, cpu_resume_l1_flags
+	mov	r0, r8			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_v7_do_resume)
-cpu_resume_l1_flags:
-	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
-	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
 #endif
 
 	__CPUINIT
@@ -369,11 +363,13 @@ __v7_setup:
 	orreq	r10, r10, #1 << 6		@ set bit #6
 	mcreq	p15, 0, r10, c15, c0, 1		@ write diagnostic register
 #endif
-#ifdef CONFIG_ARM_ERRATA_751472
-	cmp	r6, #0x30			@ present prior to r3p0
+#if defined(CONFIG_ARM_ERRATA_751472) && defined(CONFIG_SMP)
+	ALT_SMP(cmp r6, #0x30)			@ present prior to r3p0
+	ALT_UP_B(1f)
 	mrclt	p15, 0, r10, c15, c0, 1		@ read diagnostic register
 	orrlt	r10, r10, #1 << 11		@ set bit #11
 	mcrlt	p15, 0, r10, c15, c0, 1		@ write diagnostic register
+1:
 #endif
 
 3:	mov	r10, #0
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-xsc3.S linux-libre-3.2-gnu1/arch/arm/mm/proc-xsc3.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-xsc3.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-xsc3.S	2012-01-04 18:55:44.000000000 -0500
@@ -406,24 +406,23 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	.align
 
 .globl	cpu_xsc3_suspend_size
-.equ	cpu_xsc3_suspend_size, 4 * 7
+.equ	cpu_xsc3_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xsc3_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
 	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mrc	p15, 0, r6, c13, c0, 0	@ PID
 	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
-	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
-	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	mrc	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r9, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
-	ldmia	sp!, {r4 - r10, pc}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmia	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xsc3_do_suspend)
 
 ENTRY(cpu_xsc3_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
 	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
@@ -433,15 +432,10 @@ ENTRY(cpu_xsc3_do_resume)
 	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mcr	p15, 0, r6, c13, c0, 0	@ PID
 	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
-	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
-
-	@ temporarily map resume_turn_on_mmu into the page table,
-	@ otherwise prefetch abort occurs after MMU is turned on
-	mov	r0, r10			@ control register
-	mov	r2, r8, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =0x542e		@ section flags
+	orr	r1, r1, #0x18		@ cache the page table in L2
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xsc3_do_resume)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/mm/proc-xscale.S linux-libre-3.2-gnu1/arch/arm/mm/proc-xscale.S
--- linux-libre-3.1-gnu1/arch/arm/mm/proc-xscale.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/mm/proc-xscale.S	2012-01-04 18:55:44.000000000 -0500
@@ -520,24 +520,23 @@ ENTRY(cpu_xscale_set_pte_ext)
 	.align
 
 .globl	cpu_xscale_suspend_size
-.equ	cpu_xscale_suspend_size, 4 * 7
+.equ	cpu_xscale_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xscale_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
 	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mrc	p15, 0, r6, c13, c0, 0	@ PID
 	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
-	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
-	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	mrc	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r9, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
-	ldmfd	sp!, {r4 - r10, pc}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmfd	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xscale_do_suspend)
 
 ENTRY(cpu_xscale_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
@@ -545,13 +544,9 @@ ENTRY(cpu_xscale_do_resume)
 	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mcr	p15, 0, r6, c13, c0, 0	@ PID
 	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
-	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
-	mov	r0, r10			@ control register
-	mov	r2, r8, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/oprofile/common.c linux-libre-3.2-gnu1/arch/arm/oprofile/common.c
--- linux-libre-3.1-gnu1/arch/arm/oprofile/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/oprofile/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@ int __init oprofile_arch_init(struct opr
 	return oprofile_perf_init(ops);
 }
 
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
 {
 	oprofile_perf_exit();
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-iop/gpio.c linux-libre-3.2-gnu1/arch/arm/plat-iop/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-iop/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-iop/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 #include <asm/hardware/iop3xx.h>
 
 void gpio_line_config(int line, int direction)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-iop/time.c linux-libre-3.2-gnu1/arch/arm/plat-iop/time.c
--- linux-libre-3.1-gnu1/arch/arm/plat-iop/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-iop/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/export.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/sched_clock.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/audmux-v2.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/audmux-v2.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/audmux-v2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/audmux-v2.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,18 +187,11 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v2_configur
 static int mxc_audmux_v2_init(void)
 {
 	int ret;
-#if defined(CONFIG_ARCH_MX5)
 	if (cpu_is_mx51()) {
 		audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
-		ret = 0;
-		return ret;
-	}
-#endif
-#if defined(CONFIG_ARCH_MX3)
-	if (cpu_is_mx31())
+	} else if (cpu_is_mx31()) {
 		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
-
-	else if (cpu_is_mx35()) {
+	} else if (cpu_is_mx35()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -207,10 +200,7 @@ static int mxc_audmux_v2_init(void)
 			return ret;
 		}
 		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
-	}
-#endif
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
+	} else if (cpu_is_mx25()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -220,7 +210,7 @@ static int mxc_audmux_v2_init(void)
 		}
 		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
 	}
-#endif /* if defined(CONFIG_SOC_IMX25) */
+
 	audmux_debugfs_init();
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/avic.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/avic.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/avic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/avic.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 #include <mach/hardware.h>
 
 #include "irq-common.h"
@@ -50,6 +51,8 @@
 
 void __iomem *avic_base;
 
+static u32 avic_saved_mask_reg[2];
+
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
@@ -90,24 +93,8 @@ static int avic_set_irq_fiq(unsigned int
 }
 #endif /* CONFIG_FIQ */
 
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
-}
 
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct mxc_irq_chip mxc_avic_chip = {
-	.base = {
-		.irq_ack = mxc_mask_irq,
-		.irq_mask = mxc_mask_irq,
-		.irq_unmask = mxc_unmask_irq,
-	},
+static struct mxc_extra_irq avic_extra_irq = {
 #ifdef CONFIG_MXC_IRQ_PRIOR
 	.set_priority = avic_irq_set_priority,
 #endif
@@ -116,6 +103,68 @@ static struct mxc_irq_chip mxc_avic_chip
 #endif
 };
 
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+	__raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	__raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(unsigned int irq_start)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	int idx = irq_start >> 5;
+
+	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+				    handle_level_irq);
+	gc->private = &avic_extra_irq;
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_ack = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = avic_irq_suspend;
+	ct->chip.irq_resume = avic_irq_resume;
+	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+	ct->regs.ack = ct->regs.mask;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	u32 nivector;
+
+	do {
+		nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+		if (nivector == 0xffff)
+			break;
+
+		handle_IRQ(nivector, regs);
+	} while (1);
+}
+
 /*
  * This function initializes the AVIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +189,9 @@ void __init mxc_init_irq(void __iomem *i
 	/* all IRQ no FIQ */
 	__raw_writel(0, avic_base + AVIC_INTTYPEH);
 	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-	for (i = 0; i < AVIC_NUM_IRQS; i++) {
-		irq_set_chip_and_handler(i, &mxc_avic_chip.base,
-					 handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+
+	for (i = 0; i < AVIC_NUM_IRQS; i += 32)
+		avic_init_gc(i);
 
 	/* Set default priority value (0) for all IRQ's */
 	for (i = 0; i < 8; i++)
@@ -157,4 +204,3 @@ void __init mxc_init_irq(void __iomem *i
 
 	printk(KERN_INFO "MXC IRQ initialized\n");
 }
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/cpu.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/module.h>
+#include <mach/hardware.h>
 
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
@@ -9,3 +10,11 @@ void mxc_set_cpu_type(unsigned int type)
 	__mxc_cpu_type = type;
 }
 
+void imx_print_silicon_rev(const char *cpu, int srev)
+{
+	if (srev == IMX_CHIP_REVISION_UNKNOWN)
+		pr_info("CPU identified as %s, unknown revision\n", cpu);
+	else
+		pr_info("CPU identified as %s, silicon rev %d.%d\n",
+				cpu, (srev >> 4) & 0xf, srev & 0xf);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/cpufreq.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/cpufreq.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  * the CPU clock speed on the fly.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -97,7 +98,7 @@ static int mxc_set_target(struct cpufreq
 	return ret;
 }
 
-static int __init mxc_cpufreq_init(struct cpufreq_policy *policy)
+static int mxc_cpufreq_init(struct cpufreq_policy *policy)
 {
 	int ret;
 	int i;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
@@ -31,6 +31,9 @@ config IMX_HAVE_PLATFORM_IMX_I2C
 config IMX_HAVE_PLATFORM_IMX_KEYPAD
 	bool
 
+config IMX_HAVE_PLATFORM_PATA_IMX
+	bool
+
 config IMX_HAVE_PLATFORM_IMX_SSI
 	bool
 
@@ -76,3 +79,7 @@ config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 
 config IMX_HAVE_PLATFORM_SPI_IMX
 	bool
+
+config IMX_HAVE_PLATFORM_AHCI
+	bool
+	default y if ARCH_MX53
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/Makefile linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@ obj-y += platform-imx-dma.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
@@ -25,3 +26,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC)
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) +=  platform-ahci-imx.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-ahci-imx.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-ahci-imx.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-ahci-imx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-ahci-imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_ahci_imx_data_entry_single(soc, _devid)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _SATA_BASE_ADDR,			\
+		.irq = soc ## _INT_SATA,				\
+	}
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+	imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+	HOST_CAP = 0x00,
+	HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+	HOST_PORTS_IMPL	= 0x0c,
+	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+	u32 tmpdata;
+	int ret = 0;
+	struct clk *clk;
+
+	sata_clk = clk_get(dev, "ahci");
+	if (IS_ERR(sata_clk)) {
+		dev_err(dev, "no sata clock.\n");
+		return PTR_ERR(sata_clk);
+	}
+	ret = clk_enable(sata_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata clock.\n");
+		goto put_sata_clk;
+	}
+
+	/* Get the AHCI SATA PHY CLK */
+	sata_ref_clk = clk_get(dev, "ahci_phy");
+	if (IS_ERR(sata_ref_clk)) {
+		dev_err(dev, "no sata ref clock.\n");
+		ret = PTR_ERR(sata_ref_clk);
+		goto release_sata_clk;
+	}
+	ret = clk_enable(sata_ref_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata ref clock.\n");
+		goto put_sata_ref_clk;
+	}
+
+	/* Get the AHB clock rate, and configure the TIMER1MS reg later */
+	clk = clk_get(dev, "ahci_dma");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "no dma clock.\n");
+		ret = PTR_ERR(clk);
+		goto release_sata_ref_clk;
+	}
+	tmpdata = clk_get_rate(clk) / 1000;
+	clk_put(clk);
+
+	writel(tmpdata, addr + HOST_TIMER1MS);
+
+	tmpdata = readl(addr + HOST_CAP);
+	if (!(tmpdata & HOST_CAP_SSS)) {
+		tmpdata |= HOST_CAP_SSS;
+		writel(tmpdata, addr + HOST_CAP);
+	}
+
+	if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+		writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+			addr + HOST_PORTS_IMPL);
+
+	return 0;
+
+release_sata_ref_clk:
+	clk_disable(sata_ref_clk);
+put_sata_ref_clk:
+	clk_put(sata_ref_clk);
+release_sata_clk:
+	clk_disable(sata_clk);
+put_sata_clk:
+	clk_put(sata_clk);
+
+	return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+	clk_disable(sata_ref_clk);
+	clk_put(sata_ref_clk);
+
+	clk_disable(sata_clk);
+	clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+	struct ahci_platform_data pdata = {
+		.init = imx_sata_init,
+		.exit = imx_sata_exit,
+	};
+
+	return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,11 @@ const struct imx_fsl_usb2_udc_data imx35
 	imx_fsl_usb2_udc_data_entry_single(MX35);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX51);
+#endif
+
 struct platform_device *__init imx_add_fsl_usb2_udc(
 		const struct imx_fsl_usb2_udc_data *data,
 		const struct fsl_usb2_platform_data *pdata)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,12 @@ const struct imx_imx_i2c_data imx51_imx_
 	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
 	imx51_imx_i2c_data_entry(0, 1),
 	imx51_imx_i2c_data_entry(1, 2),
+	{
+		.id = 2,
+		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
+		.iosize = SZ_16K,
+		.irq = MX51_INT_HS_I2C,
+	},
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,15 @@ const struct imx_mxc_ehci_data imx35_mxc
 	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
+const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
 struct platform_device *__init imx_add_mxc_ehci(
 		const struct imx_mxc_ehci_data *data,
 		const struct mxc_usbh_platform_data *pdata)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-pata_imx.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-pata_imx.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices/platform-pata_imx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices/platform-pata_imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_pata_imx_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _ATA_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ATA,					\
+	}
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device("pata_imx", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,73 +23,6 @@
 #include <linux/platform_device.h>
 #include <mach/common.h>
 
-int __init mxc_register_device(struct platform_device *pdev, void *data)
-{
-	int ret;
-
-	pdev->dev.platform_data = data;
-
-	ret = platform_device_register(pdev);
-	if (ret)
-		pr_debug("Unable to register platform device '%s': %d\n",
-			 pdev->name, ret);
-
-	return ret;
-}
-
-struct platform_device *__init imx_add_platform_device_dmamask(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask)
-{
-	int ret = -ENOMEM;
-	struct platform_device *pdev;
-
-	pdev = platform_device_alloc(name, id);
-	if (!pdev)
-		goto err;
-
-	if (dmamask) {
-		/*
-		 * This memory isn't freed when the device is put,
-		 * I don't have a nice idea for that though.  Conceptually
-		 * dma_mask in struct device should not be a pointer.
-		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
-		 */
-		pdev->dev.dma_mask =
-			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-		if (!pdev->dev.dma_mask)
-			/* ret is still -ENOMEM; */
-			goto err;
-
-		*pdev->dev.dma_mask = dmamask;
-		pdev->dev.coherent_dma_mask = dmamask;
-	}
-
-	if (res) {
-		ret = platform_device_add_resources(pdev, res, num_resources);
-		if (ret)
-			goto err;
-	}
-
-	if (data) {
-		ret = platform_device_add_data(pdev, data, size_data);
-		if (ret)
-			goto err;
-	}
-
-	ret = platform_device_add(pdev);
-	if (ret) {
-err:
-		if (dmamask)
-			kfree(pdev->dev.dma_mask);
-		platform_device_put(pdev);
-		return ERR_PTR(ret);
-	}
-
-	return pdev;
-}
-
 struct device mxc_aips_bus = {
 	.init_name	= "mxc_aips",
 	.parent		= &platform_bus,
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/gic.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/gic.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/gic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/gic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <asm/exception.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat, irqnr;
+
+	do {
+		irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+		irqnr = irqstat & 0x3ff;
+		if (irqnr == 1023)
+			break;
+
+		if (irqnr > 15 && irqnr < 1021)
+			handle_IRQ(irqnr, regs);
+#ifdef CONFIG_SMP
+		else {
+			writel_relaxed(irqstat, gic_cpu_base_addr +
+						GIC_CPU_EOI);
+			handle_IPI(irqnr, regs);
+		}
+#endif
+	} while (1);
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/common.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/common.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 struct platform_device;
 struct clk;
+enum mxc_cpu_pwr_mode;
 
 extern void mx1_map_io(void);
 extern void mx21_map_io(void);
@@ -64,12 +65,72 @@ extern int mx51_clocks_init(unsigned lon
 			unsigned long ckih1, unsigned long ckih2);
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
+extern int mx51_clocks_init_dt(void);
+extern int mx53_clocks_init_dt(void);
+extern int mx6q_clocks_init(void);
 extern struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern int mxc_register_device(struct platform_device *pdev, void *data);
 extern void mxc_set_cpu_type(unsigned int type);
 extern void mxc_arch_reset_init(void __iomem *);
 extern void mx51_efikamx_reset(void);
 extern int mx53_revision(void);
 extern int mx53_display_revision(void);
+
+enum mxc_cpu_pwr_mode {
+	WAIT_CLOCKED,		/* wfi only */
+	WAIT_UNCLOCKED,		/* WAIT */
+	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
+	STOP_POWER_ON,		/* just STOP */
+	STOP_POWER_OFF,		/* STOP + SRPG */
+};
+
+extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void imx_print_silicon_rev(const char *cpu, int srev);
+
+void avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+void gic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+#define imx6q_handle_irq gic_handle_irq
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+#ifdef CONFIG_DEBUG_LL
+extern void imx_lluart_map_io(void);
+#else
+static inline void imx_lluart_map_io(void) {}
+#endif
+extern void v7_cpu_resume(void);
+extern u32 *pl310_get_save_ptr(void);
+#ifdef CONFIG_SMP
+extern void v7_secondary_startup(void);
+extern void imx_scu_map_io(void);
+extern void imx_smp_prepare(void);
+#else
+static inline void imx_scu_map_io(void) {}
+static inline void imx_smp_prepare(void) {}
+#endif
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern void imx_src_init(void);
+extern void imx_gpc_init(void);
+extern void imx_gpc_pre_suspend(void);
+extern void imx_gpc_post_resume(void);
+extern void imx51_babbage_common_init(void);
+extern void imx53_ard_common_init(void);
+extern void imx53_evk_common_init(void);
+extern void imx53_qsb_common_init(void);
+extern void imx53_smd_common_init(void);
+extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+extern void imx6q_pm_init(void);
+extern void imx6q_clock_map_io(void);
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,49 +12,25 @@
  */
 #include <mach/hardware.h>
 
-#ifdef CONFIG_SOC_IMX1
+#ifdef CONFIG_DEBUG_IMX1_UART
 #define UART_PADDR	MX1_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX25_UART)
 #define UART_PADDR	MX25_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
 #define UART_PADDR	MX2x_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
 #define UART_PADDR	MX3x_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX51_UART)
 #define UART_PADDR	MX51_UART1_BASE_ADDR
-#endif
-
-/* iMX50/53 have same addresses, but not iMX51 */
-#if defined(CONFIG_SOC_IMX50) || defined(CONFIG_SOC_IMX53)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
 #define UART_PADDR	MX53_UART1_BASE_ADDR
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	MX6Q_UART4_BASE_ADDR
 #endif
 
 #define UART_VADDR	IMX_IO_ADDRESS(UART_PADDR)
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =UART_PADDR	@ physical
 		ldr	\rv, =UART_VADDR	@ virtual
 		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,22 @@
 extern struct device mxc_aips_bus;
 extern struct device mxc_ahb_bus;
 
-struct platform_device *imx_add_platform_device_dmamask(
+static inline struct platform_device *imx_add_platform_device_dmamask(
 		const char *name, int id,
 		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask);
+		const void *data, size_t size_data, u64 dmamask)
+{
+	struct platform_device_info pdevinfo = {
+		.name = name,
+		.id = id,
+		.res = res,
+		.num_res = num_resources,
+		.data = data,
+		.size_data = size_data,
+		.dma_mask = dmamask,
+	};
+	return platform_device_register_full(&pdevinfo);
+}
 
 static inline struct platform_device *imx_add_platform_device(
 		const char *name, int id,
@@ -251,6 +263,14 @@ struct platform_device *__init imx_add_m
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata);
 
+struct imx_pata_imx_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data);
+
 struct imx_mxc_pwm_data {
 	int id;
 	resource_size_t iobase;
@@ -301,3 +321,13 @@ struct platform_device *__init imx_add_s
 struct platform_device *imx_add_imx_dma(void);
 struct platform_device *imx_add_imx_sdma(char *name,
 	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
+
+#include <linux/ahci_platform.h>
+struct imx_ahci_imx_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,72 +9,19 @@
  * published by the Free Software Foundation.
  */
 
-#include <mach/hardware.h>
-
-#define AVIC_NIMASK	0x04
+/* Unused, we use CONFIG_MULTI_IRQ_HANDLER */
 
-	@ this macro disables fast irq (not implemented)
 	.macro	disable_fiq
 	.endm
 
 	.macro  get_irqnr_preamble, base, tmp
-#ifndef CONFIG_MXC_TZIC
-	ldr	\base, =avic_base
-	ldr	\base, [\base]
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	ldr	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	ldr	\base, =tzic_base
-	ldr	\base, [\base]
-#endif /* CONFIG_MXC_TZIC */
 	.endm
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 
-	@ this macro checks which interrupt occurred
-	@ and returns its number in irqnr
-	@ and returns if an interrupt occurred in irqstat
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifndef CONFIG_MXC_TZIC
-	@ Load offset & priority of the highest priority
-	@ interrupt pending from AVIC_NIVECSR
-	ldr	\irqstat, [\base, #0x40]
-	@ Shift to get the decoded IRQ number, using ASR so
-	@ 'no interrupt pending' becomes 0xffffffff
-	mov	\irqnr, \irqstat, asr #16
-	@ set zero flag if IRQ + 1 == 0
-	adds	\tmp, \irqnr, #1
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	bicne	\tmp, \irqstat, #0xFFFFFFE0
-	strne	\tmp, [\base, #AVIC_NIMASK]
-	streq	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	@ Load offset & priority of the highest priority
-	@ interrupt pending.
-	@ 0x080 is INTSEC0 register
-	@ 0xD80 is HIPND0 register
-	mov     \irqnr, #0
-1000:	add	\irqstat, \base, \irqnr, lsr #3
-	ldr	\tmp, [\irqstat, #0xd80]
-	ldr	\irqstat, [\irqstat, #0x080]
-	ands	\tmp, \tmp, \irqstat
-	bne	1001f
-	add	\irqnr, \irqnr, #32
-	cmp     \irqnr, #128
-	blo     1000b
-	b       2001f
-1001:	mov     \irqstat, #1
-1002:	tst     \tmp, \irqstat
-	bne     2002f
-	movs    \tmp, \tmp, lsr #1
-	addne   \irqnr, \irqnr, #1
-	bne     1002b
-2001:
-	mov  \irqnr, #0
-2002:
-	movs \irqnr, \irqnr
-#endif
+	.endm
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,39 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_GPIO_H__
-#define __ASM_ARCH_MXC_GPIO_H__
-
-#include <linux/spinlock.h>
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
-/* range e.g. GPIO_1_5 is gpio 5 under linux */
-#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#define gpio_get_value		__gpio_get_value
-#define gpio_set_value		__gpio_set_value
-#define gpio_cansleep		__gpio_cansleep
-
-#define gpio_to_irq(gpio)	(MXC_GPIO_IRQ_START + (gpio))
-#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
-
-#endif
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/hardware.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/hardware.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,11 +81,21 @@
  *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
  * mx51:
+ *	TZIC	0xe0000000+0x004000	->	0xf5000000+0x004000
  *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
- *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
  *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
  *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x83f00000+0x100000	->	0xf4300000+0x100000
+ * mx53:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx6q:
+ *	SCU	0x00a00000+0x001000	->	0xf4000000+0x001000
+ *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
+ *	ANATOP	0x020c8000+0x001000	->	0xf42c8000+0x001000
+ *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
  */
 #define IMX_IO_P2V(x)	(						\
 			0xf4000000 +					\
@@ -97,6 +107,7 @@
 
 #include <mach/mxc.h>
 
+#include <mach/mx6q.h>
 #include <mach/mx50.h>
 #include <mach/mx51.h>
 #include <mach/mx53.h>
@@ -116,4 +127,10 @@
 	.type = _type,							\
 }
 
+/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* range e.g. GPIO_1_5 is gpio 5 under linux */
+#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
+
+#define IMX_GPIO_TO_IRQ(gpio)	(MXC_GPIO_IRQ_START + (gpio))
+
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/i2c.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/i2c.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/i2c.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/i2c.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,14 +11,10 @@
 
 /**
  * struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @init:	Initialise gpio's and other board specific things
- * @exit:	Free everything initialised by @init
  * @bitrate:	Bus speed measured in Hz
  *
  **/
 struct imxi2c_platform_data {
-	int (*init)(struct device *dev);
-	void (*exit)(struct device *dev);
 	int bitrate;
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/io.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/io.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,32 +14,22 @@
 /* Allow IO space to be anywhere in the memory */
 #define IO_SPACE_LIMIT 0xffffffff
 
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#include <mach/hardware.h>
-
 #define __arch_ioremap __imx_ioremap
 #define __arch_iounmap __iounmap
 
 #define addr_in_module(addr, mod) \
 	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
 
+extern void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int);
+
 static inline void __iomem *
 __imx_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
-	if (mtype == MT_DEVICE && (cpu_is_mx31() || cpu_is_mx35())) {
-		/*
-		 * Access all peripherals below 0x80000000 as nonshared device
-		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
-		 * can occur.
-		 */
-		if (phys_addr < 0x80000000 &&
-				!addr_in_module(phys_addr, MX3x_L2CC))
-			mtype = MT_DEVICE_NONSHARED;
-	}
-
-	return __arm_ioremap(phys_addr, size, mtype);
+	if (imx_ioremap != NULL)
+		return imx_ioremap(phys_addr, size, mtype);
+	else
+		return __arm_ioremap(phys_addr, size, mtype);
 }
-#endif
 
 /* io address mapping macro */
 #define __io(a)		__typesafe_io(a)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx3.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx3.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2012-01-04 18:55:44.000000000 -0500
@@ -735,6 +735,7 @@ enum iomux_pins {
 #define MX31_PIN_KEY_COL5_KEY_COL5	IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL6_KEY_COL6	IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL7_KEY_COL7	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST	IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
 
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 #define __MACH_IOMUX_MX51_H__
 
 #include <mach/iomux-v3.h>
+#define __NA_	0x000
+
 
 /* Pad control groupings */
 #define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
@@ -47,1521 +49,765 @@
 
 /* Raw pin modes without pad control */
 /*							  PAD    MUX ALT INPSE PATH PADCTRL */
-#define _MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x5c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x5c, 7, 0x08d8, 0, 0)
-#define _MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x5c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x5c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x5c, 0x14, 0x09b4, 0, 0)
-#define _MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x5c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x5c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x60, 7, 0x08d4, 0, 0)
-#define _MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x60, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x60, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x60, 3, 0x09ec, 0, 0)
-#define _MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x60, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x60, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x64, 7, 0x08e4, 0, 0)
-#define _MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x64, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x64, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x64, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x64, 4, 0x09f0, 1, 0)
-#define _MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x64, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x68, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x68, 7, 0x08e8, 0, 0)
-#define _MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x68, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x68, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x68, 0x14, 0x09b0, 0, 0)
-#define _MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x68, 3, 0x09e8, 1, 0)
-#define _MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x68, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x6c, 5, 0x08c8, 0, 0)
-#define _MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x6c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x6c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x6c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x6c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x70, 5, 0x08c4, 0, 0)
-#define _MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x70, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x70, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x70, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x70, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x74, 5, 0x08cc, 0, 0)
-#define _MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x74, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x74, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x74, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x78, 5, 0x08d0, 0, 0)
-#define _MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x78, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x78, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x78, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x78, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x7c, 5, 0x08f8, 0, 0)
-#define _MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x7c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x7c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x7c, 0x14, 0x09bc, 0, 0)
-#define _MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x7c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x7c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x80, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x80, 1, 0x09c8, 0, 0)
-#define _MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x80, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x80, 3, 0x09f4, 0, 0)
-#define _MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x80, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x84, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x84, 1, 0x09cc, 0, 0)
-#define _MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x84, 4, 0x09e8, 3, 0)
-#define _MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x84, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x84, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x88, 5, 0x08f4, 0, 0)
-#define _MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x88, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x88, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x88, 0x14, 0x09b8, 0, 0)
-#define _MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x88, 3, 0x09f0, 3, 0)
-#define _MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x88, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x8c, 5, 0x08f0, 0, 0)
-#define _MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x8c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x8c, 1, 0x09d0, 0, 0)
-#define _MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x8c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x90, 5, 0x08ec, 0, 0)
-#define _MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x90, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x90, 1, 0x09d4, 0, 0)
-#define _MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x90, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x94, 5, 0x08fc, 0, 0)
-#define _MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x94, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x94, 1, 0x09d8, 0, 0)
-#define _MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x94, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x98, 5, 0x0900, 0, 0)
-#define _MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x98, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x98, 1, 0x09dc, 0, 0)
-#define _MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x98, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x9c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x9c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__OSC_FREQ_SEL0	IOMUX_PAD(0x430, 0x9c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0xa0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0xa0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__OSC_FREQ_SEL1	IOMUX_PAD(0x434, 0xa0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0xa4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0xa4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0xa4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0xa8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0xa8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0xa8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0xac, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0xac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0xac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0xb0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0xb0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0xb0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0xb4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0xb4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0xb8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0xb8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0xb8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0xbc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0xbc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0xbc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0xc0, 6, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0xc0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0xc0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0xc0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0xc4, 5, 0x09a0, 0, 0)
-#define _MX51_PAD_EIM_A26__DISP2_EXT_CLK	IOMUX_PAD(0x458, 0xc4, 6, 0x0908, 0, 0)
-#define _MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0xc4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0xc4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0xc4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0xc8, 5, 0x099c, 0, 0)
-#define _MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0xc8, 6, 0x09a4, 0, 0)
-#define _MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0xc8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0xc8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0xc8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0xcc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0xd0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0xd4, 6, 0x08e0, 0, 0)
-#define _MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0xd4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0xd4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__FEC_MDIO		IOMUX_PAD(0x468, 0xd4, 3, 0x0954, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0xd4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0xd4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0xd8, 6, 0x08dc, 0, 0)
-#define _MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0xd8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0xd8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0xd8, 3, 0x095c, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0xd8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0xd8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__EIM_OE		IOMUX_PAD(0x470, 0xdc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0xdc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0xe0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0xe0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0xe4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0xe4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0xe8, 6, 0x08d8, 1, 0)
-#define _MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0xe8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0xe8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0xe8, 3, 0x0960, 0, 0)
-#define _MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0xe8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0xe8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0xec, 6, 0x08d4, 1, 0)
-#define _MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0xec, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0xec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0xec, 3, 0x0964, 0, 0)
-#define _MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0xec, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0xec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0xf0, 6, 0x08e4, 1, 0)
-#define _MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0xf0, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0xf0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0xf0, 3, 0x0970, 0, 0)
-#define _MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0xf0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0xf0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0xf4, 6, 0x08e8, 1, 0)
-#define _MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0xf4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__DISP1_EXT_CLK	IOMUX_PAD(0x488, 0xf4, 4, 0x0904, 0, 0)
-#define _MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0xf4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0xf4, 3, 0x0950, 0, 0)
-#define _MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0xf4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0xf4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0xf8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0xf8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0xfc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0xfc, 1, 0x0978, 0, 0)
-#define _MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x097c, 0, 0)
-#define _MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x0980, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__NANDF_WE_B	IOMUX_PAD(0x4e4, 0x108, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x093c, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x0984, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__NANDF_RE_B	IOMUX_PAD(0x4e8, 0x10c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x0940, 0, 0)
-#define _MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x0988, 0, 0)
-#define _MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x098c, 0, 0)
-#define _MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x0990, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__NANDF_WP_B	IOMUX_PAD(0x4f4, 0x118, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__PATA_DMACK	IOMUX_PAD(0x4f4, 0x118, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x0944, 0, 0)
-#define _MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x0930, 0, 0)
-#define _MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x0994, 0, 0)
-#define _MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x0948, 0, 0)
-#define _MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x091c, 0, 0)
-#define _MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x09a8, 0, 0)
-#define _MX51_PAD_NANDF_RB2__ECSPI2_SCLK	IOMUX_PAD(0x500, 0x124, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x094c, 0, 0)
-#define _MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_H3_DP	IOMUX_PAD(0x500, 0x124, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0x0a20, 0, 0)
-#define _MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__ECSPI2_MISO	IOMUX_PAD(0x504, 0x128, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x0968, 0, 0)
-#define _MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x09f8, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_H3_DM	IOMUX_PAD(0x504, 0x128, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x0998, 0, 0)
-#define _MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x0914, 0, 0)
-#define _MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__USBH3_H1_DP	IOMUX_PAD(0x520, 0x138, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__USBH3_H1_DM	IOMUX_PAD(0x524, 0x13c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0x0a24, 0, 0)
-#define _MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0x0a1c, 0, 0)
-#define _MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x0928, 0, 0)
-#define _MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x0974, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x0938, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__SD3_CMD	IOMUX_PAD(0x538, 0x150, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__ECSPI2_MOSI	IOMUX_PAD(0x53c, 0x154, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__PATA_DATA15	IOMUX_PAD(0x53c, 0x154, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x0934, 0, 0)
-#define _MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__PATA_DATA14	IOMUX_PAD(0x540, 0x158, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__PATA_DATA13	IOMUX_PAD(0x544, 0x15c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x0930, 1, 0)
-#define _MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__PATA_DATA12	IOMUX_PAD(0x548, 0x160, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x096c, 0, 0)
-#define _MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__PATA_DATA11	IOMUX_PAD(0x54c, 0x164, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x0948, 1, 0)
-#define _MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__PATA_DATA10	IOMUX_PAD(0x550, 0x168, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x0944, 1, 0)
-#define _MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x0958, 0, 0)
-#define _MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x0940, 1, 0)
-#define _MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x093c, 1, 0)
-#define _MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x09fc, 0, 0)
-#define _MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0x0a00, 0, 0)
-#define _MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0x0a04, 0, 0)
-#define _MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0x0a08, 0, 0)
-#define _MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0x0a0c, 0, 0)
-#define _MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0x0a10, 0, 0)
-#define _MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0x0a14, 0, 0)
-#define _MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0x0a18, 0, 0)
-#define _MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x0998, 1, 0)
-#define _MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__CSI1_VSYNC	IOMUX_PAD(0x5ac, 0x1c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__CSI1_HSYNC	IOMUX_PAD(0x5b0, 0x1c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__CSI2_VSYNC	IOMUX_PAD(0x5dc, 0x1ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__CSI2_HSYNC	IOMUX_PAD(0x5e0, 0x1f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__UART3_RXD	IOMUX_PAD(0x5f4, 0x204, 1, 0x09f4, 2, 0)
-#define _MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x09b4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x08c4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x08cc, 1, 0)
-#define _MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x08c8, 1, 0)
-#define _MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x08d0, 1, 0)
-#define _MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x09b0, 1, 0)
-#define _MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x09e4, 0, 0)
-#define _MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x09e0, 0, 0)
-#define _MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
-#define _MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x09f4, 4, 0)
-#define _MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__OWIRE_LINE	IOMUX_PAD(0x638, 0x248, 0, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x090c, 0, 0)
-#define _MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x0910, 0, 0)
-#define _MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x09b8, 1, 0)
-#define _MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x09f0, 4, 0)
-#define _MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x09bc, 1, 0)
-#define _MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x0914, 1, 0)
-#define _MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x09b8, 2, 0)
-#define _MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x091c, 1, 0)
-#define _MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x09bc, 2, 0)
-#define _MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x09f4, 6, 0)
-#define _MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x0918, 0, 0)
-#define _MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__UART2_CTS	IOMUX_PAD(0x688, 0x288, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__UART2_RXD	IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
-#define _MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__UART2_RTS	IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
-#define _MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x0920, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x0928, 1, 0)
-#define _MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x0934, 1, 0)
-#define _MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x0978, 1, 0)
-#define _MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x097c, 1, 0)
-#define _MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x0980, 1, 0)
-#define _MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN14	IOMUX_PAD(0x6b8, 0x2b8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x0984, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x09a4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x09c4, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x0988, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x09c4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x098c, 1, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x0990, 1, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__GPIO3_8	IOMUX_PAD(0x6c8, 0x2c8, 4, 0x0994, 1, 0)
-#define _MX51_PAD_DISP1_DAT0__DISP1_DAT0	IOMUX_PAD(0x6cc, 0x2cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT1__DISP1_DAT1	IOMUX_PAD(0x6d0, 0x2d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT2__DISP1_DAT2	IOMUX_PAD(0x6d4, 0x2d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT3__DISP1_DAT3	IOMUX_PAD(0x6d8, 0x2d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT4__DISP1_DAT4	IOMUX_PAD(0x6dc, 0x2dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT5__DISP1_DAT5	IOMUX_PAD(0x6e0, 0x2e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__DISP1_DAT6	IOMUX_PAD(0x6e4, 0x2e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__DISP1_DAT7	IOMUX_PAD(0x6e8, 0x2e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__DISP1_DAT8	IOMUX_PAD(0x6ec, 0x2ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__DISP1_DAT9	IOMUX_PAD(0x6f0, 0x2f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x09a8, 1, 0)
-#define _MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x09a0, 1, 0)
-#define _MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x09c0, 0, 0)
-#define _MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__CSI2_DATA_EN	IOMUX_PAD(0x748, 0x340, 3, 0x099c, 1, 0)
-#define _MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x0950, 1, 0)
-#define _MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x0954, 1, 0)
-#define _MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x095c, 1, 0)
-#define _MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x09c0, 1, 0)
-#define _MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x0960, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__DISP2_DAT0	IOMUX_PAD(0x75c, 0x354, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT0__FEC_RDATA3	IOMUX_PAD(0x75c, 0x354, 2, 0x0964, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x09c8, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x09f4, 8, 0)
-#define _MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x09f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__DISP2_DAT1	IOMUX_PAD(0x760, 0x358, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x0970, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x09cc, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0x0a1c, 1, 0)
-#define _MX51_PAD_DISP2_DAT2__DISP2_DAT2	IOMUX_PAD(0x764, 0x35c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT3__DISP2_DAT3	IOMUX_PAD(0x768, 0x360, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT4__DISP2_DAT4	IOMUX_PAD(0x76c, 0x364, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT5__DISP2_DAT5	IOMUX_PAD(0x770, 0x368, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__DISP2_DAT6	IOMUX_PAD(0x774, 0x36c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__FEC_TDATA1	IOMUX_PAD(0x774, 0x36c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x09d0, 1, 0)
-#define _MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0x0a24, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__DISP2_DAT7	IOMUX_PAD(0x778, 0x370, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__FEC_TDATA2	IOMUX_PAD(0x778, 0x370, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x09d4, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0x0a20, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__DISP2_DAT8	IOMUX_PAD(0x77c, 0x374, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__FEC_TDATA3	IOMUX_PAD(0x77c, 0x374, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x09d8, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x09fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x08f4, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__DISP2_DAT9	IOMUX_PAD(0x780, 0x378, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0x0a00, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x094c, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x09dc, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0x0a04, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x08f0, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x0968, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0x0a08, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x08ec, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT12__FEC_RX_DV	IOMUX_PAD(0x78c, 0x384, 2, 0x096c, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0x0a0c, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x08fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x0974, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0x0a10, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__AUD6_TXFS	IOMUX_PAD(0x794, 0x38c, 4, 0x0900, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x0958, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0x0a14, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__AUD6_RXFS	IOMUX_PAD(0x798, 0x390, 4, 0x08f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0x0a18, 1, 0)
-#define _MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x08e0, 1, 0)
-#define _MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x091c, 2, 0)
-#define _MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x08dc, 1, 0)
-#define _MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x0914, 2, 0)
-#define _MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x08d8, 2, 0)
-#define _MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x0918, 1, 0)
-#define _MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(0x000, 0x01c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(0x000, 0x020, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(0x000, 0x024, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(0x000, 0x028, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x08d4, 2, 0)
-#define _MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(0x000, 0x02c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(0x000, 0x030, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(0x000, 0x034, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(0x000, 0x038, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x08e4, 2, 0)
-#define _MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(0x000, 0x044, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(0x000, 0x048, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(0x000, 0x03c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(0x000, 0x040, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x08e8, 2, 0)
-#define _MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x0920, 1, 0)
-#define _MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x0924, 0, 0)
-#define _MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x0918, 2, 0)
-#define _MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(0x000, 0x04c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(0x000, 0x050, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(0x000, 0x054, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(0x000, 0x058, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x000, 0x3b4, 2, 0x091c, 3, 0)
-#define _MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x09b0, 2, 0)
-#define _MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x0914, 3, 0)
-#define _MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x09b4, 2, 0)
-#define _MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x0918, 3, 0)
-#define _MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__USBH3_H2_DP	IOMUX_PAD(0x7c8, 0x3c0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__USBH3_H2_DM	IOMUX_PAD(0x7cc, 0x3c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x0924, 1, 0)
-#define _MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x09b8, 3, 0)
-#define _MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x090c, 1, 0)
-#define _MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x09bc, 3, 0)
-#define _MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x0910, 1, 0)
-#define _MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__DISP2_EXT_CLK	IOMUX_PAD(0x804, 0x3d8, 4, 0x0908, 1, 0)
-#define _MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x0938, 1, 0)
-#define _MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x099c, 2, 0)
-#define _MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, 0x0000, 0, 0)
 
 /* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS		(_MX51_PAD_EIM_D16__AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__AUD5_TXD		(_MX51_PAD_EIM_D16__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__EIM_D16		(_MX51_PAD_EIM_D16__EIM_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__GPIO2_0		(_MX51_PAD_EIM_D16__GPIO2_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__I2C1_SDA		(_MX51_PAD_EIM_D16__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D16__UART2_CTS		(_MX51_PAD_EIM_D16__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D16__USBH2_DATA0		(_MX51_PAD_EIM_D16__USBH2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__AUD5_RXD		(_MX51_PAD_EIM_D17__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__EIM_D17		(_MX51_PAD_EIM_D17__EIM_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__GPIO2_1		(_MX51_PAD_EIM_D17__GPIO2_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART2_RXD		(_MX51_PAD_EIM_D17__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART3_CTS		(_MX51_PAD_EIM_D17__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__USBH2_DATA1		(_MX51_PAD_EIM_D17__USBH2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__AUD5_TXC		(_MX51_PAD_EIM_D18__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__EIM_D18		(_MX51_PAD_EIM_D18__EIM_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__GPIO2_2		(_MX51_PAD_EIM_D18__GPIO2_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART2_TXD		(_MX51_PAD_EIM_D18__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART3_RTS		(_MX51_PAD_EIM_D18__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__USBH2_DATA2		(_MX51_PAD_EIM_D18__USBH2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD4_RXC		(_MX51_PAD_EIM_D19__AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD5_TXFS		(_MX51_PAD_EIM_D19__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__EIM_D19		(_MX51_PAD_EIM_D19__EIM_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__GPIO2_3		(_MX51_PAD_EIM_D19__GPIO2_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__I2C1_SCL		(_MX51_PAD_EIM_D19__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D19__UART2_RTS		(_MX51_PAD_EIM_D19__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D19__USBH2_DATA3		(_MX51_PAD_EIM_D19__USBH2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__AUD4_TXD		(_MX51_PAD_EIM_D20__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__EIM_D20		(_MX51_PAD_EIM_D20__EIM_D20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__GPIO2_4		(_MX51_PAD_EIM_D20__GPIO2_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D20__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__USBH2_DATA4		(_MX51_PAD_EIM_D20__USBH2_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__AUD4_RXD		(_MX51_PAD_EIM_D21__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__EIM_D21		(_MX51_PAD_EIM_D21__EIM_D21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__GPIO2_5		(_MX51_PAD_EIM_D21__GPIO2_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D21__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__USBH2_DATA5		(_MX51_PAD_EIM_D21__USBH2_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__AUD4_TXC		(_MX51_PAD_EIM_D22__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__EIM_D22		(_MX51_PAD_EIM_D22__EIM_D22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__GPIO2_6		(_MX51_PAD_EIM_D22__GPIO2_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__USBH2_DATA6		(_MX51_PAD_EIM_D22__USBH2_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__AUD4_TXFS		(_MX51_PAD_EIM_D23__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__EIM_D23		(_MX51_PAD_EIM_D23__EIM_D23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__GPIO2_7		(_MX51_PAD_EIM_D23__GPIO2_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__SPDIF_OUT1		(_MX51_PAD_EIM_D23__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__USBH2_DATA7		(_MX51_PAD_EIM_D23__USBH2_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__AUD6_RXFS		(_MX51_PAD_EIM_D24__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__EIM_D24		(_MX51_PAD_EIM_D24__EIM_D24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__GPIO2_8		(_MX51_PAD_EIM_D24__GPIO2_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__I2C2_SDA		(_MX51_PAD_EIM_D24__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D24__UART3_CTS		(_MX51_PAD_EIM_D24__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D24__USBOTG_DATA0		(_MX51_PAD_EIM_D24__USBOTG_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__EIM_D25		(_MX51_PAD_EIM_D25__EIM_D25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__KEY_COL6		(_MX51_PAD_EIM_D25__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART2_CTS		(_MX51_PAD_EIM_D25__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART3_RXD		(_MX51_PAD_EIM_D25__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__USBOTG_DATA1		(_MX51_PAD_EIM_D25__USBOTG_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__EIM_D26		(_MX51_PAD_EIM_D26__EIM_D26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__KEY_COL7		(_MX51_PAD_EIM_D26__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART2_RTS		(_MX51_PAD_EIM_D26__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART3_TXD		(_MX51_PAD_EIM_D26__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__USBOTG_DATA2		(_MX51_PAD_EIM_D26__USBOTG_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__AUD6_RXC		(_MX51_PAD_EIM_D27__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__EIM_D27		(_MX51_PAD_EIM_D27__EIM_D27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__GPIO2_9		(_MX51_PAD_EIM_D27__GPIO2_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__I2C2_SCL		(_MX51_PAD_EIM_D27__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D27__UART3_RTS		(_MX51_PAD_EIM_D27__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D27__USBOTG_DATA3		(_MX51_PAD_EIM_D27__USBOTG_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__AUD6_TXD		(_MX51_PAD_EIM_D28__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__EIM_D28		(_MX51_PAD_EIM_D28__EIM_D28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__KEY_ROW4		(_MX51_PAD_EIM_D28__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__USBOTG_DATA4		(_MX51_PAD_EIM_D28__USBOTG_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__AUD6_RXD		(_MX51_PAD_EIM_D29__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__EIM_D29		(_MX51_PAD_EIM_D29__EIM_D29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__KEY_ROW5		(_MX51_PAD_EIM_D29__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__USBOTG_DATA5		(_MX51_PAD_EIM_D29__USBOTG_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__AUD6_TXC		(_MX51_PAD_EIM_D30__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__EIM_D30		(_MX51_PAD_EIM_D30__EIM_D30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__KEY_ROW6		(_MX51_PAD_EIM_D30__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__USBOTG_DATA6		(_MX51_PAD_EIM_D30__USBOTG_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__AUD6_TXFS		(_MX51_PAD_EIM_D31__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__EIM_D31		(_MX51_PAD_EIM_D31__EIM_D31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__KEY_ROW7		(_MX51_PAD_EIM_D31__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__USBOTG_DATA7		(_MX51_PAD_EIM_D31__USBOTG_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__EIM_A16		(_MX51_PAD_EIM_A16__EIM_A16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__GPIO2_10		(_MX51_PAD_EIM_A16__GPIO2_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		(_MX51_PAD_EIM_A16__OSC_FREQ_SEL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__EIM_A17		(_MX51_PAD_EIM_A17__EIM_A17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__GPIO2_11		(_MX51_PAD_EIM_A17__GPIO2_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		(_MX51_PAD_EIM_A17__OSC_FREQ_SEL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__BOOT_LPB0		(_MX51_PAD_EIM_A18__BOOT_LPB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__EIM_A18		(_MX51_PAD_EIM_A18__EIM_A18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__GPIO2_12		(_MX51_PAD_EIM_A18__GPIO2_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__BOOT_LPB1		(_MX51_PAD_EIM_A19__BOOT_LPB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__EIM_A19		(_MX51_PAD_EIM_A19__EIM_A19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__GPIO2_13		(_MX51_PAD_EIM_A19__GPIO2_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	(_MX51_PAD_EIM_A20__BOOT_UART_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__EIM_A20		(_MX51_PAD_EIM_A20__EIM_A20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__GPIO2_14		(_MX51_PAD_EIM_A20__GPIO2_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	(_MX51_PAD_EIM_A21__BOOT_UART_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__EIM_A21		(_MX51_PAD_EIM_A21__EIM_A21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__GPIO2_15		(_MX51_PAD_EIM_A21__GPIO2_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__EIM_A22		(_MX51_PAD_EIM_A22__EIM_A22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__GPIO2_16		(_MX51_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN		(_MX51_PAD_EIM_A23__BOOT_HPN_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__EIM_A23		(_MX51_PAD_EIM_A23__EIM_A23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__GPIO2_17		(_MX51_PAD_EIM_A23__GPIO2_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__EIM_A24		(_MX51_PAD_EIM_A24__EIM_A24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__GPIO2_18		(_MX51_PAD_EIM_A24__GPIO2_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__USBH2_CLK		(_MX51_PAD_EIM_A24__USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__DISP1_PIN4		(_MX51_PAD_EIM_A25__DISP1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__EIM_A25		(_MX51_PAD_EIM_A25__EIM_A25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__GPIO2_19		(_MX51_PAD_EIM_A25__GPIO2_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__USBH2_DIR		(_MX51_PAD_EIM_A25__USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN		(_MX51_PAD_EIM_A26__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		(_MX51_PAD_EIM_A26__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__EIM_A26		(_MX51_PAD_EIM_A26__EIM_A26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__GPIO2_20		(_MX51_PAD_EIM_A26__GPIO2_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__USBH2_STP		(_MX51_PAD_EIM_A26__USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN		(_MX51_PAD_EIM_A27__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__DISP1_PIN1		(_MX51_PAD_EIM_A27__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__EIM_A27		(_MX51_PAD_EIM_A27__EIM_A27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__GPIO2_21		(_MX51_PAD_EIM_A27__GPIO2_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__USBH2_NXT		(_MX51_PAD_EIM_A27__USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB0__EIM_EB0		(_MX51_PAD_EIM_EB0__EIM_EB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB1__EIM_EB1		(_MX51_PAD_EIM_EB1__EIM_EB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__AUD5_RXFS		(_MX51_PAD_EIM_EB2__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__CSI1_D2		(_MX51_PAD_EIM_EB2__CSI1_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__EIM_EB2		(_MX51_PAD_EIM_EB2__EIM_EB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__FEC_MDIO		(_MX51_PAD_EIM_EB2__FEC_MDIO | \
+#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
 		MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
 		PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22		(_MX51_PAD_EIM_EB2__GPIO2_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		(_MX51_PAD_EIM_EB2__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__AUD5_RXC		(_MX51_PAD_EIM_EB3__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__CSI1_D3		(_MX51_PAD_EIM_EB3__CSI1_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__EIM_EB3		(_MX51_PAD_EIM_EB3__EIM_EB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__FEC_RDATA1		(_MX51_PAD_EIM_EB3__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPIO2_23		(_MX51_PAD_EIM_EB3__GPIO2_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		(_MX51_PAD_EIM_EB3__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__EIM_OE			(_MX51_PAD_EIM_OE__EIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__GPIO2_24		(_MX51_PAD_EIM_OE__GPIO2_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__EIM_CS0		(_MX51_PAD_EIM_CS0__EIM_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__GPIO2_25		(_MX51_PAD_EIM_CS0__GPIO2_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__EIM_CS1		(_MX51_PAD_EIM_CS1__EIM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__GPIO2_26		(_MX51_PAD_EIM_CS1__GPIO2_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__AUD5_TXD		(_MX51_PAD_EIM_CS2__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__CSI1_D4		(_MX51_PAD_EIM_CS2__CSI1_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__EIM_CS2		(_MX51_PAD_EIM_CS2__EIM_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__FEC_RDATA2		(_MX51_PAD_EIM_CS2__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__GPIO2_27		(_MX51_PAD_EIM_CS2__GPIO2_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__USBOTG_STP		(_MX51_PAD_EIM_CS2__USBOTG_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__AUD5_RXD		(_MX51_PAD_EIM_CS3__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__CSI1_D5		(_MX51_PAD_EIM_CS3__CSI1_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__EIM_CS3		(_MX51_PAD_EIM_CS3__EIM_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__FEC_RDATA3		(_MX51_PAD_EIM_CS3__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__GPIO2_28		(_MX51_PAD_EIM_CS3__GPIO2_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__USBOTG_NXT		(_MX51_PAD_EIM_CS3__USBOTG_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__AUD5_TXC		(_MX51_PAD_EIM_CS4__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__CSI1_D6		(_MX51_PAD_EIM_CS4__CSI1_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__EIM_CS4		(_MX51_PAD_EIM_CS4__EIM_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		(_MX51_PAD_EIM_CS4__FEC_RX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS4__GPIO2_29		(_MX51_PAD_EIM_CS4__GPIO2_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__USBOTG_CLK		(_MX51_PAD_EIM_CS4__USBOTG_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__AUD5_TXFS		(_MX51_PAD_EIM_CS5__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__CSI1_D7		(_MX51_PAD_EIM_CS5__CSI1_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		(_MX51_PAD_EIM_CS5__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__EIM_CS5		(_MX51_PAD_EIM_CS5__EIM_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__FEC_CRS		(_MX51_PAD_EIM_CS5__FEC_CRS | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS5__GPIO2_30		(_MX51_PAD_EIM_CS5__GPIO2_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__USBOTG_DIR		(_MX51_PAD_EIM_CS5__USBOTG_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__EIM_DTACK		(_MX51_PAD_EIM_DTACK__EIM_DTACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__GPIO2_31		(_MX51_PAD_EIM_DTACK__GPIO2_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__EIM_LBA		(_MX51_PAD_EIM_LBA__EIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__GPIO3_1		(_MX51_PAD_EIM_LBA__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__EIM_CRE		(_MX51_PAD_EIM_CRE__EIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__GPIO3_2		(_MX51_PAD_EIM_CRE__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DRAM_CS1__DRAM_CS1		(_MX51_PAD_DRAM_CS1__DRAM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__GPIO3_3		(_MX51_PAD_NANDF_WE_B__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		(_MX51_PAD_NANDF_WE_B__NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW		(_MX51_PAD_NANDF_WE_B__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__GPIO3_4		(_MX51_PAD_NANDF_RE_B__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		(_MX51_PAD_NANDF_RE_B__NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR		(_MX51_PAD_NANDF_RE_B__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__GPIO3_5		(_MX51_PAD_NANDF_ALE__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__NANDF_ALE		(_MX51_PAD_NANDF_ALE__NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	(_MX51_PAD_NANDF_ALE__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__GPIO3_6		(_MX51_PAD_NANDF_CLE__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__NANDF_CLE		(_MX51_PAD_NANDF_CLE__NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B	(_MX51_PAD_NANDF_CLE__PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__GPIO3_7		(_MX51_PAD_NANDF_WP_B__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		(_MX51_PAD_NANDF_WP_B__NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK		(_MX51_PAD_NANDF_WP_B__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		(_MX51_PAD_NANDF_RB0__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__GPIO3_8		(_MX51_PAD_NANDF_RB0__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__NANDF_RB0		(_MX51_PAD_NANDF_RB0__NANDF_RB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ		(_MX51_PAD_NANDF_RB0__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI		(_MX51_PAD_NANDF_RB1__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		(_MX51_PAD_NANDF_RB1__ECSPI2_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__GPIO3_9		(_MX51_PAD_NANDF_RB1__GPIO3_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__NANDF_RB1		(_MX51_PAD_NANDF_RB1__NANDF_RB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__PATA_IORDY		(_MX51_PAD_NANDF_RB1__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT		(_MX51_PAD_NANDF_RB2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		(_MX51_PAD_NANDF_RB2__ECSPI2_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__FEC_COL		(_MX51_PAD_NANDF_RB2__FEC_COL | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB2__GPIO3_10		(_MX51_PAD_NANDF_RB2__GPIO3_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__NANDF_RB2		(_MX51_PAD_NANDF_RB2__NANDF_RB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		(_MX51_PAD_NANDF_RB2__USBH3_H3_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_NXT		(_MX51_PAD_NANDF_RB2__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT		(_MX51_PAD_NANDF_RB3__DISP1_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		(_MX51_PAD_NANDF_RB3__ECSPI2_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		(_MX51_PAD_NANDF_RB3__FEC_RX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB3__GPIO3_11		(_MX51_PAD_NANDF_RB3__GPIO3_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__NANDF_RB3		(_MX51_PAD_NANDF_RB3__NANDF_RB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_CLK		(_MX51_PAD_NANDF_RB3__USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		(_MX51_PAD_NANDF_RB3__USBH3_H3_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__GPIO_NAND		(_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ		(_MX51_PAD_GPIO_NAND__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__GPIO3_16		(_MX51_PAD_NANDF_CS0__GPIO3_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__NANDF_CS0		(_MX51_PAD_NANDF_CS0__NANDF_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__GPIO3_17		(_MX51_PAD_NANDF_CS1__GPIO3_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__NANDF_CS1		(_MX51_PAD_NANDF_CS1__NANDF_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK		(_MX51_PAD_NANDF_CS2__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		(_MX51_PAD_NANDF_CS2__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS2__GPIO3_18		(_MX51_PAD_NANDF_CS2__GPIO3_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__NANDF_CS2		(_MX51_PAD_NANDF_CS2__NANDF_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__PATA_CS_0		(_MX51_PAD_NANDF_CS2__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		(_MX51_PAD_NANDF_CS2__USBH3_H1_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__FEC_MDC		(_MX51_PAD_NANDF_CS3__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS3__GPIO3_19		(_MX51_PAD_NANDF_CS3__GPIO3_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__NANDF_CS3		(_MX51_PAD_NANDF_CS3__NANDF_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__PATA_CS_1		(_MX51_PAD_NANDF_CS3__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		(_MX51_PAD_NANDF_CS3__USBH3_H1_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1		(_MX51_PAD_NANDF_CS4__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS4__GPIO3_20		(_MX51_PAD_NANDF_CS4__GPIO3_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__NANDF_CS4		(_MX51_PAD_NANDF_CS4__NANDF_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__PATA_DA_0		(_MX51_PAD_NANDF_CS4__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__USBH3_STP		(_MX51_PAD_NANDF_CS4__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2		(_MX51_PAD_NANDF_CS5__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS5__GPIO3_21		(_MX51_PAD_NANDF_CS5__GPIO3_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__NANDF_CS5		(_MX51_PAD_NANDF_CS5__NANDF_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__PATA_DA_1		(_MX51_PAD_NANDF_CS5__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__USBH3_DIR		(_MX51_PAD_NANDF_CS5__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__CSPI_SS3		(_MX51_PAD_NANDF_CS6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3		(_MX51_PAD_NANDF_CS6__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS6__GPIO3_22		(_MX51_PAD_NANDF_CS6__GPIO3_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__NANDF_CS6		(_MX51_PAD_NANDF_CS6__NANDF_CS6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__PATA_DA_2		(_MX51_PAD_NANDF_CS6__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN		(_MX51_PAD_NANDF_CS7__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS7__GPIO3_23		(_MX51_PAD_NANDF_CS7__GPIO3_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__NANDF_CS7		(_MX51_PAD_NANDF_CS7__NANDF_CS7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	(_MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	(_MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	(_MX51_PAD_NANDF_RDY_INT__GPIO3_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	(_MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		(_MX51_PAD_NANDF_D15__ECSPI2_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__GPIO3_25		(_MX51_PAD_NANDF_D15__GPIO3_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__NANDF_D15		(_MX51_PAD_NANDF_D15__NANDF_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__PATA_DATA15		(_MX51_PAD_NANDF_D15__PATA_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__SD3_DAT7		(_MX51_PAD_NANDF_D15__SD3_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3		(_MX51_PAD_NANDF_D14__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__GPIO3_26		(_MX51_PAD_NANDF_D14__GPIO3_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__NANDF_D14		(_MX51_PAD_NANDF_D14__NANDF_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__PATA_DATA14		(_MX51_PAD_NANDF_D14__PATA_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__SD3_DAT6		(_MX51_PAD_NANDF_D14__SD3_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2		(_MX51_PAD_NANDF_D13__ECSPI2_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__GPIO3_27		(_MX51_PAD_NANDF_D13__GPIO3_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__NANDF_D13		(_MX51_PAD_NANDF_D13__NANDF_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__PATA_DATA13		(_MX51_PAD_NANDF_D13__PATA_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__SD3_DAT5		(_MX51_PAD_NANDF_D13__SD3_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1		(_MX51_PAD_NANDF_D12__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__GPIO3_28		(_MX51_PAD_NANDF_D12__GPIO3_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__NANDF_D12		(_MX51_PAD_NANDF_D12__NANDF_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__PATA_DATA12		(_MX51_PAD_NANDF_D12__PATA_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__SD3_DAT4		(_MX51_PAD_NANDF_D12__SD3_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__FEC_RX_DV		(_MX51_PAD_NANDF_D11__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__GPIO3_29		(_MX51_PAD_NANDF_D11__GPIO3_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__NANDF_D11		(_MX51_PAD_NANDF_D11__NANDF_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__PATA_DATA11		(_MX51_PAD_NANDF_D11__PATA_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__SD3_DATA3		(_MX51_PAD_NANDF_D11__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__GPIO3_30		(_MX51_PAD_NANDF_D10__GPIO3_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__NANDF_D10		(_MX51_PAD_NANDF_D10__NANDF_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__PATA_DATA10		(_MX51_PAD_NANDF_D10__PATA_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__SD3_DATA2		(_MX51_PAD_NANDF_D10__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__FEC_RDATA0		(_MX51_PAD_NANDF_D9__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_D9__GPIO3_31		(_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__NANDF_D9		(_MX51_PAD_NANDF_D9__NANDF_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__PATA_DATA9		(_MX51_PAD_NANDF_D9__PATA_DATA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__SD3_DATA1		(_MX51_PAD_NANDF_D9__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__FEC_TDATA0		(_MX51_PAD_NANDF_D8__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_D8__GPIO4_0		(_MX51_PAD_NANDF_D8__GPIO4_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__NANDF_D8		(_MX51_PAD_NANDF_D8__NANDF_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__PATA_DATA8		(_MX51_PAD_NANDF_D8__PATA_DATA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__SD3_DATA0		(_MX51_PAD_NANDF_D8__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__GPIO4_1		(_MX51_PAD_NANDF_D7__GPIO4_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__NANDF_D7		(_MX51_PAD_NANDF_D7__NANDF_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__PATA_DATA7		(_MX51_PAD_NANDF_D7__PATA_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__USBH3_DATA0		(_MX51_PAD_NANDF_D7__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__GPIO4_2		(_MX51_PAD_NANDF_D6__GPIO4_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__NANDF_D6		(_MX51_PAD_NANDF_D6__NANDF_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__PATA_DATA6		(_MX51_PAD_NANDF_D6__PATA_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__SD4_LCTL		(_MX51_PAD_NANDF_D6__SD4_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__USBH3_DATA1		(_MX51_PAD_NANDF_D6__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__GPIO4_3		(_MX51_PAD_NANDF_D5__GPIO4_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__NANDF_D5		(_MX51_PAD_NANDF_D5__NANDF_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__PATA_DATA5		(_MX51_PAD_NANDF_D5__PATA_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__SD4_WP		(_MX51_PAD_NANDF_D5__SD4_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__USBH3_DATA2		(_MX51_PAD_NANDF_D5__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__GPIO4_4		(_MX51_PAD_NANDF_D4__GPIO4_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__NANDF_D4		(_MX51_PAD_NANDF_D4__NANDF_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__PATA_DATA4		(_MX51_PAD_NANDF_D4__PATA_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__SD4_CD		(_MX51_PAD_NANDF_D4__SD4_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__USBH3_DATA3		(_MX51_PAD_NANDF_D4__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__GPIO4_5		(_MX51_PAD_NANDF_D3__GPIO4_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__NANDF_D3		(_MX51_PAD_NANDF_D3__NANDF_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__PATA_DATA3		(_MX51_PAD_NANDF_D3__PATA_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__SD4_DAT4		(_MX51_PAD_NANDF_D3__SD4_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__USBH3_DATA4		(_MX51_PAD_NANDF_D3__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__GPIO4_6		(_MX51_PAD_NANDF_D2__GPIO4_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__NANDF_D2		(_MX51_PAD_NANDF_D2__NANDF_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__PATA_DATA2		(_MX51_PAD_NANDF_D2__PATA_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__SD4_DAT5		(_MX51_PAD_NANDF_D2__SD4_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__USBH3_DATA5		(_MX51_PAD_NANDF_D2__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__GPIO4_7		(_MX51_PAD_NANDF_D1__GPIO4_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__NANDF_D1		(_MX51_PAD_NANDF_D1__NANDF_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__PATA_DATA1		(_MX51_PAD_NANDF_D1__PATA_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__SD4_DAT6		(_MX51_PAD_NANDF_D1__SD4_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__USBH3_DATA6		(_MX51_PAD_NANDF_D1__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__GPIO4_8		(_MX51_PAD_NANDF_D0__GPIO4_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__NANDF_D0		(_MX51_PAD_NANDF_D0__NANDF_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__PATA_DATA0		(_MX51_PAD_NANDF_D0__PATA_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__SD4_DAT7		(_MX51_PAD_NANDF_D0__SD4_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__USBH3_DATA7		(_MX51_PAD_NANDF_D0__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__CSI1_D8		(_MX51_PAD_CSI1_D8__CSI1_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__GPIO3_12		(_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__CSI1_D9		(_MX51_PAD_CSI1_D9__CSI1_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__GPIO3_13		(_MX51_PAD_CSI1_D9__GPIO3_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D10__CSI1_D10		(_MX51_PAD_CSI1_D10__CSI1_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D11__CSI1_D11		(_MX51_PAD_CSI1_D11__CSI1_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D12__CSI1_D12		(_MX51_PAD_CSI1_D12__CSI1_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D13__CSI1_D13		(_MX51_PAD_CSI1_D13__CSI1_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D14__CSI1_D14		(_MX51_PAD_CSI1_D14__CSI1_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D15__CSI1_D15		(_MX51_PAD_CSI1_D15__CSI1_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D16__CSI1_D16		(_MX51_PAD_CSI1_D16__CSI1_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D17__CSI1_D17		(_MX51_PAD_CSI1_D17__CSI1_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D18__CSI1_D18		(_MX51_PAD_CSI1_D18__CSI1_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D19__CSI1_D19		(_MX51_PAD_CSI1_D19__CSI1_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		(_MX51_PAD_CSI1_VSYNC__CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14		(_MX51_PAD_CSI1_VSYNC__GPIO3_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		(_MX51_PAD_CSI1_HSYNC__CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15		(_MX51_PAD_CSI1_HSYNC__GPIO3_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	(_MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		(_MX51_PAD_CSI1_MCLK__CSI1_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__CSI2_D12		(_MX51_PAD_CSI2_D12__CSI2_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__GPIO4_9		(_MX51_PAD_CSI2_D12__GPIO4_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__CSI2_D13		(_MX51_PAD_CSI2_D13__CSI2_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__GPIO4_10		(_MX51_PAD_CSI2_D13__GPIO4_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D14__CSI2_D14		(_MX51_PAD_CSI2_D14__CSI2_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D15__CSI2_D15		(_MX51_PAD_CSI2_D15__CSI2_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D16__CSI2_D16		(_MX51_PAD_CSI2_D16__CSI2_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D17__CSI2_D17		(_MX51_PAD_CSI2_D17__CSI2_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__CSI2_D18		(_MX51_PAD_CSI2_D18__CSI2_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__GPIO4_11		(_MX51_PAD_CSI2_D18__GPIO4_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__CSI2_D19		(_MX51_PAD_CSI2_D19__CSI2_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__GPIO4_12		(_MX51_PAD_CSI2_D19__GPIO4_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		(_MX51_PAD_CSI2_VSYNC__CSI2_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13		(_MX51_PAD_CSI2_VSYNC__GPIO4_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		(_MX51_PAD_CSI2_HSYNC__CSI2_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14		(_MX51_PAD_CSI2_HSYNC__GPIO4_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	(_MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		(_MX51_PAD_CSI2_PIXCLK__GPIO4_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__GPIO4_16		(_MX51_PAD_I2C1_CLK__GPIO4_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__I2C1_CLK		(_MX51_PAD_I2C1_CLK__I2C1_CLK | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__GPIO4_17		(_MX51_PAD_I2C1_DAT__GPIO4_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__I2C1_DAT		(_MX51_PAD_I2C1_DAT__I2C1_DAT | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		(_MX51_PAD_AUD3_BB_TXD__AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		(_MX51_PAD_AUD3_BB_TXD__GPIO4_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		(_MX51_PAD_AUD3_BB_RXD__AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		(_MX51_PAD_AUD3_BB_RXD__GPIO4_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		(_MX51_PAD_AUD3_BB_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		(_MX51_PAD_AUD3_BB_CK__AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20		(_MX51_PAD_AUD3_BB_CK__GPIO4_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		(_MX51_PAD_AUD3_BB_FS__AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21		(_MX51_PAD_AUD3_BB_FS__GPIO4_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD		(_MX51_PAD_AUD3_BB_FS__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	(_MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22		(_MX51_PAD_CSPI1_MOSI__GPIO4_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		(_MX51_PAD_CSPI1_MOSI__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD		(_MX51_PAD_CSPI1_MISO__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	(_MX51_PAD_CSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__GPIO4_23		(_MX51_PAD_CSPI1_MISO__GPIO4_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC		(_MX51_PAD_CSPI1_SS0__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		(_MX51_PAD_CSPI1_SS0__ECSPI1_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__GPIO4_24		(_MX51_PAD_CSPI1_SS0__GPIO4_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD		(_MX51_PAD_CSPI1_SS1__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		(_MX51_PAD_CSPI1_SS1__ECSPI1_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__GPIO4_25		(_MX51_PAD_CSPI1_SS1__GPIO4_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		(_MX51_PAD_CSPI1_RDY__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		(_MX51_PAD_CSPI1_RDY__ECSPI1_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__GPIO4_26		(_MX51_PAD_CSPI1_RDY__GPIO4_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	(_MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27		(_MX51_PAD_CSPI1_SCLK__GPIO4_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		(_MX51_PAD_CSPI1_SCLK__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__GPIO4_28		(_MX51_PAD_UART1_RXD__GPIO4_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__UART1_RXD		(_MX51_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__GPIO4_29		(_MX51_PAD_UART1_TXD__GPIO4_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__PWM2_PWMO		(_MX51_PAD_UART1_TXD__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__UART1_TXD		(_MX51_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__GPIO4_30		(_MX51_PAD_UART1_RTS__GPIO4_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__UART1_RTS		(_MX51_PAD_UART1_RTS__UART1_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__GPIO4_31		(_MX51_PAD_UART1_CTS__GPIO4_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__UART1_CTS		(_MX51_PAD_UART1_CTS__UART1_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__FIRI_TXD		(_MX51_PAD_UART2_RXD__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__GPIO1_20		(_MX51_PAD_UART2_RXD__GPIO1_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__UART2_RXD		(_MX51_PAD_UART2_RXD__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__FIRI_RXD		(_MX51_PAD_UART2_TXD__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__GPIO1_21		(_MX51_PAD_UART2_TXD__GPIO1_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__UART2_TXD		(_MX51_PAD_UART2_TXD__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__CSI1_D0		(_MX51_PAD_UART3_RXD__CSI1_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__GPIO1_22		(_MX51_PAD_UART3_RXD__GPIO1_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART1_DTR		(_MX51_PAD_UART3_RXD__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART3_RXD		(_MX51_PAD_UART3_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__CSI1_D1		(_MX51_PAD_UART3_TXD__CSI1_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__GPIO1_23		(_MX51_PAD_UART3_TXD__GPIO1_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART1_DSR		(_MX51_PAD_UART3_TXD__UART1_DSR | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART3_TXD		(_MX51_PAD_UART3_TXD__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__GPIO1_24		(_MX51_PAD_OWIRE_LINE__GPIO1_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		(_MX51_PAD_OWIRE_LINE__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		(_MX51_PAD_OWIRE_LINE__SPDIF_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW0__KEY_ROW0		(_MX51_PAD_KEY_ROW0__KEY_ROW0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW1__KEY_ROW1		(_MX51_PAD_KEY_ROW1__KEY_ROW1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW2__KEY_ROW2		(_MX51_PAD_KEY_ROW2__KEY_ROW2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW3__KEY_ROW3		(_MX51_PAD_KEY_ROW3__KEY_ROW3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__KEY_COL0		(_MX51_PAD_KEY_COL0__KEY_COL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__PLL1_BYP		(_MX51_PAD_KEY_COL0__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__KEY_COL1		(_MX51_PAD_KEY_COL1__KEY_COL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__PLL2_BYP		(_MX51_PAD_KEY_COL1__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__KEY_COL2		(_MX51_PAD_KEY_COL2__KEY_COL2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__PLL3_BYP		(_MX51_PAD_KEY_COL2__PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL3__KEY_COL3		(_MX51_PAD_KEY_COL3__KEY_COL3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__I2C2_SCL		(_MX51_PAD_KEY_COL4__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__KEY_COL4		(_MX51_PAD_KEY_COL4__KEY_COL4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1		(_MX51_PAD_KEY_COL4__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART1_RI		(_MX51_PAD_KEY_COL4__UART1_RI | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART3_RTS		(_MX51_PAD_KEY_COL4__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__I2C2_SDA		(_MX51_PAD_KEY_COL5__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__KEY_COL5		(_MX51_PAD_KEY_COL5__KEY_COL5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART1_DCD		(_MX51_PAD_KEY_COL5__UART1_DCD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART3_CTS		(_MX51_PAD_KEY_COL5__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK		(_MX51_PAD_USBH1_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__GPIO1_25		(_MX51_PAD_USBH1_CLK__GPIO1_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__I2C2_SCL		(_MX51_PAD_USBH1_CLK__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__USBH1_CLK		(_MX51_PAD_USBH1_CLK__USBH1_CLK | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI		(_MX51_PAD_USBH1_DIR__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__GPIO1_26		(_MX51_PAD_USBH1_DIR__GPIO1_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__I2C2_SDA		(_MX51_PAD_USBH1_DIR__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__USBH1_DIR		(_MX51_PAD_USBH1_DIR__USBH1_DIR | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__CSPI_RDY		(_MX51_PAD_USBH1_STP__CSPI_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__GPIO1_27		(_MX51_PAD_USBH1_STP__GPIO1_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__UART3_RXD		(_MX51_PAD_USBH1_STP__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__USBH1_STP		(_MX51_PAD_USBH1_STP__USBH1_STP | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__CSPI_MISO		(_MX51_PAD_USBH1_NXT__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__GPIO1_28		(_MX51_PAD_USBH1_NXT__GPIO1_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__UART3_TXD		(_MX51_PAD_USBH1_NXT__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__USBH1_NXT		(_MX51_PAD_USBH1_NXT__USBH1_NXT | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__GPIO1_11		(_MX51_PAD_USBH1_DATA0__GPIO1_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__UART2_CTS		(_MX51_PAD_USBH1_DATA0__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	(_MX51_PAD_USBH1_DATA0__USBH1_DATA0 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__GPIO1_12		(_MX51_PAD_USBH1_DATA1__GPIO1_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__UART2_RXD		(_MX51_PAD_USBH1_DATA1__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	(_MX51_PAD_USBH1_DATA1__USBH1_DATA1 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__GPIO1_13		(_MX51_PAD_USBH1_DATA2__GPIO1_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__UART2_TXD		(_MX51_PAD_USBH1_DATA2__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	(_MX51_PAD_USBH1_DATA2__USBH1_DATA2 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__GPIO1_14		(_MX51_PAD_USBH1_DATA3__GPIO1_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__UART2_RTS		(_MX51_PAD_USBH1_DATA3__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	(_MX51_PAD_USBH1_DATA3__USBH1_DATA3 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0		(_MX51_PAD_USBH1_DATA4__CSPI_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__GPIO1_15		(_MX51_PAD_USBH1_DATA4__GPIO1_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	(_MX51_PAD_USBH1_DATA4__USBH1_DATA4 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1		(_MX51_PAD_USBH1_DATA5__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__GPIO1_16		(_MX51_PAD_USBH1_DATA5__GPIO1_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	(_MX51_PAD_USBH1_DATA5__USBH1_DATA5 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3		(_MX51_PAD_USBH1_DATA6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__GPIO1_17		(_MX51_PAD_USBH1_DATA6__GPIO1_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	(_MX51_PAD_USBH1_DATA6__USBH1_DATA6 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI1_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__GPIO1_18		(_MX51_PAD_USBH1_DATA7__GPIO1_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	(_MX51_PAD_USBH1_DATA7__USBH1_DATA7 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__DI1_PIN11		(_MX51_PAD_DI1_PIN11__DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		(_MX51_PAD_DI1_PIN11__ECSPI1_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__GPIO3_0		(_MX51_PAD_DI1_PIN11__GPIO3_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__DI1_PIN12		(_MX51_PAD_DI1_PIN12__DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__GPIO3_1		(_MX51_PAD_DI1_PIN12__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__DI1_PIN13		(_MX51_PAD_DI1_PIN13__DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__GPIO3_2		(_MX51_PAD_DI1_PIN13__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		(_MX51_PAD_DI1_D0_CS__DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__GPIO3_3		(_MX51_PAD_DI1_D0_CS__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		(_MX51_PAD_DI1_D1_CS__DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		(_MX51_PAD_DI1_D1_CS__DISP1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		(_MX51_PAD_DI1_D1_CS__DISP1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__GPIO3_4		(_MX51_PAD_DI1_D1_CS__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	(_MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	(_MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	(_MX51_PAD_DISPB2_SER_DIN__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	(_MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	(_MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	(_MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	(_MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	(_MX51_PAD_DISPB2_SER_CLK__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	(_MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		(_MX51_PAD_DISPB2_SER_RS__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		(_MX51_PAD_DISP1_DAT0__DISP1_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		(_MX51_PAD_DISP1_DAT1__DISP1_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		(_MX51_PAD_DISP1_DAT2__DISP1_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		(_MX51_PAD_DISP1_DAT3__DISP1_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		(_MX51_PAD_DISP1_DAT4__DISP1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		(_MX51_PAD_DISP1_DAT5__DISP1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	(_MX51_PAD_DISP1_DAT6__BOOT_USB_SRC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		(_MX51_PAD_DISP1_DAT6__DISP1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	(_MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		(_MX51_PAD_DISP1_DAT7__DISP1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		(_MX51_PAD_DISP1_DAT8__BOOT_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		(_MX51_PAD_DISP1_DAT8__DISP1_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		(_MX51_PAD_DISP1_DAT9__BOOT_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		(_MX51_PAD_DISP1_DAT9__DISP1_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	(_MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	(_MX51_PAD_DISP1_DAT10__DISP1_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	(_MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	(_MX51_PAD_DISP1_DAT11__DISP1_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	(_MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	(_MX51_PAD_DISP1_DAT12__DISP1_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	(_MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	(_MX51_PAD_DISP1_DAT13__DISP1_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	(_MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	(_MX51_PAD_DISP1_DAT14__DISP1_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	(_MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	(_MX51_PAD_DISP1_DAT15__DISP1_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	(_MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	(_MX51_PAD_DISP1_DAT16__DISP1_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	(_MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	(_MX51_PAD_DISP1_DAT17__DISP1_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	(_MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	(_MX51_PAD_DISP1_DAT18__DISP1_DAT18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	(_MX51_PAD_DISP1_DAT18__DISP2_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	(_MX51_PAD_DISP1_DAT18__DISP2_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	(_MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	(_MX51_PAD_DISP1_DAT19__DISP1_DAT19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	(_MX51_PAD_DISP1_DAT19__DISP2_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	(_MX51_PAD_DISP1_DAT19__DISP2_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	(_MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	(_MX51_PAD_DISP1_DAT20__DISP1_DAT20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	(_MX51_PAD_DISP1_DAT20__DISP2_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	(_MX51_PAD_DISP1_DAT20__DISP2_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	(_MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	(_MX51_PAD_DISP1_DAT21__DISP1_DAT21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	(_MX51_PAD_DISP1_DAT21__DISP2_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	(_MX51_PAD_DISP1_DAT21__DISP2_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	(_MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	(_MX51_PAD_DISP1_DAT22__DISP1_DAT22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	(_MX51_PAD_DISP1_DAT22__DISP2_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	(_MX51_PAD_DISP1_DAT22__DISP2_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	(_MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	(_MX51_PAD_DISP1_DAT23__DISP1_DAT23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	(_MX51_PAD_DISP1_DAT23__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	(_MX51_PAD_DISP1_DAT23__DISP2_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	(_MX51_PAD_DISP1_DAT23__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN3__DI1_PIN3		(_MX51_PAD_DI1_PIN3__DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN2__DI1_PIN2		(_MX51_PAD_DI1_PIN2__DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK		(_MX51_PAD_DI_GP2__DISP1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP2_WAIT		(_MX51_PAD_DI_GP2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN		(_MX51_PAD_DI_GP3__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO		(_MX51_PAD_DI_GP3__DISP1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__FEC_TX_ER		(_MX51_PAD_DI_GP3__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		(_MX51_PAD_DI2_PIN4__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__DI2_PIN4		(_MX51_PAD_DI2_PIN4__DI2_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__FEC_CRS		(_MX51_PAD_DI2_PIN4__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__DI2_PIN2		(_MX51_PAD_DI2_PIN2__DI2_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__FEC_MDC		(_MX51_PAD_DI2_PIN2__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN3__DI2_PIN3		(_MX51_PAD_DI2_PIN3__DI2_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN3__FEC_MDIO		(_MX51_PAD_DI2_PIN3__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	(_MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	(_MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DI2_PIN15		(_MX51_PAD_DI_GP4__DI2_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN		(_MX51_PAD_DI_GP4__DISP1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP2_PIN1		(_MX51_PAD_DI_GP4__DISP2_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__FEC_RDATA2		(_MX51_PAD_DI_GP4__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		(_MX51_PAD_DISP2_DAT0__DISP2_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		(_MX51_PAD_DISP2_DAT0__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__KEY_COL6		(_MX51_PAD_DISP2_DAT0__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__UART3_RXD		(_MX51_PAD_DISP2_DAT0__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK		(_MX51_PAD_DISP2_DAT0__USBH3_CLK | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		(_MX51_PAD_DISP2_DAT1__DISP2_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		(_MX51_PAD_DISP2_DAT1__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__KEY_COL7		(_MX51_PAD_DISP2_DAT1__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__UART3_TXD		(_MX51_PAD_DISP2_DAT1__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR		(_MX51_PAD_DISP2_DAT1__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		(_MX51_PAD_DISP2_DAT2__DISP2_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		(_MX51_PAD_DISP2_DAT3__DISP2_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		(_MX51_PAD_DISP2_DAT4__DISP2_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		(_MX51_PAD_DISP2_DAT5__DISP2_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		(_MX51_PAD_DISP2_DAT6__DISP2_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		(_MX51_PAD_DISP2_DAT6__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT6__GPIO1_19		(_MX51_PAD_DISP2_DAT6__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4		(_MX51_PAD_DISP2_DAT6__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__USBH3_STP		(_MX51_PAD_DISP2_DAT6__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		(_MX51_PAD_DISP2_DAT7__DISP2_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		(_MX51_PAD_DISP2_DAT7__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT7__GPIO1_29		(_MX51_PAD_DISP2_DAT7__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5		(_MX51_PAD_DISP2_DAT7__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT		(_MX51_PAD_DISP2_DAT7__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		(_MX51_PAD_DISP2_DAT8__DISP2_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		(_MX51_PAD_DISP2_DAT8__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT8__GPIO1_30		(_MX51_PAD_DISP2_DAT8__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6		(_MX51_PAD_DISP2_DAT8__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	(_MX51_PAD_DISP2_DAT8__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC		(_MX51_PAD_DISP2_DAT9__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		(_MX51_PAD_DISP2_DAT9__DISP2_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		(_MX51_PAD_DISP2_DAT9__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT9__GPIO1_31		(_MX51_PAD_DISP2_DAT9__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	(_MX51_PAD_DISP2_DAT9__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	(_MX51_PAD_DISP2_DAT10__DISP2_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	(_MX51_PAD_DISP2_DAT10__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__FEC_COL		(_MX51_PAD_DISP2_DAT10__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7		(_MX51_PAD_DISP2_DAT10__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	(_MX51_PAD_DISP2_DAT10__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD		(_MX51_PAD_DISP2_DAT11__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	(_MX51_PAD_DISP2_DAT11__DISP2_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	(_MX51_PAD_DISP2_DAT11__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__GPIO1_10		(_MX51_PAD_DISP2_DAT11__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	(_MX51_PAD_DISP2_DAT11__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD		(_MX51_PAD_DISP2_DAT12__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	(_MX51_PAD_DISP2_DAT12__DISP2_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		(_MX51_PAD_DISP2_DAT12__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	(_MX51_PAD_DISP2_DAT12__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC		(_MX51_PAD_DISP2_DAT13__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	(_MX51_PAD_DISP2_DAT13__DISP2_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	(_MX51_PAD_DISP2_DAT13__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	(_MX51_PAD_DISP2_DAT13__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		(_MX51_PAD_DISP2_DAT14__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	(_MX51_PAD_DISP2_DAT14__DISP2_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	(_MX51_PAD_DISP2_DAT14__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	(_MX51_PAD_DISP2_DAT14__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		(_MX51_PAD_DISP2_DAT15__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	(_MX51_PAD_DISP2_DAT15__DISP1_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	(_MX51_PAD_DISP2_DAT15__DISP2_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	(_MX51_PAD_DISP2_DAT15__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	(_MX51_PAD_DISP2_DAT15__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__AUD5_RXFS		(_MX51_PAD_SD1_CMD__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__CSPI_MOSI		(_MX51_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__SD1_CMD		(_MX51_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__AUD5_RXC		(_MX51_PAD_SD1_CLK__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__CSPI_SCLK		(_MX51_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__SD1_CLK		(_MX51_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD1_DATA0__AUD5_TXD		(_MX51_PAD_SD1_DATA0__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__CSPI_MISO		(_MX51_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA0__EIM_DA0		(_MX51_PAD_EIM_DA0__EIM_DA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA1__EIM_DA1		(_MX51_PAD_EIM_DA1__EIM_DA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA2__EIM_DA2		(_MX51_PAD_EIM_DA2__EIM_DA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA3__EIM_DA3		(_MX51_PAD_EIM_DA3__EIM_DA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__AUD5_RXD		(_MX51_PAD_SD1_DATA1__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA4__EIM_DA4		(_MX51_PAD_EIM_DA4__EIM_DA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA5__EIM_DA5		(_MX51_PAD_EIM_DA5__EIM_DA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA6__EIM_DA6		(_MX51_PAD_EIM_DA6__EIM_DA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA7__EIM_DA7		(_MX51_PAD_EIM_DA7__EIM_DA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__AUD5_TXC		(_MX51_PAD_SD1_DATA2__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA10__EIM_DA10		(_MX51_PAD_EIM_DA10__EIM_DA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA11__EIM_DA11		(_MX51_PAD_EIM_DA11__EIM_DA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA8__EIM_DA8		(_MX51_PAD_EIM_DA8__EIM_DA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA9__EIM_DA9		(_MX51_PAD_EIM_DA9__EIM_DA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS		(_MX51_PAD_SD1_DATA3__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__CSPI_SS1		(_MX51_PAD_SD1_DATA3__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__CSPI_SS2		(_MX51_PAD_GPIO1_0__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__GPIO1_0		(_MX51_PAD_GPIO1_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__SD1_CD		(_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__CSPI_MISO		(_MX51_PAD_GPIO1_1__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__GPIO1_1		(_MX51_PAD_GPIO1_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__SD1_WP		(_MX51_PAD_GPIO1_1__SD1_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_EIM_DA12__EIM_DA12		(_MX51_PAD_EIM_DA12__EIM_DA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA13__EIM_DA13		(_MX51_PAD_EIM_DA13__EIM_DA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA14__EIM_DA14		(_MX51_PAD_EIM_DA14__EIM_DA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA15__EIM_DA15		(_MX51_PAD_EIM_DA15__EIM_DA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__CSPI_MOSI		(_MX51_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__I2C1_SCL		(_MX51_PAD_SD2_CMD__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__SD2_CMD		(_MX51_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__CSPI_SCLK		(_MX51_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__I2C1_SDA		(_MX51_PAD_SD2_CLK__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__SD2_CLK		(_MX51_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD2_DATA0__CSPI_MISO		(_MX51_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD1_DAT4		(_MX51_PAD_SD2_DATA0__SD1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD1_DAT5		(_MX51_PAD_SD2_DATA1__SD1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		(_MX51_PAD_SD2_DATA1__USBH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD1_DAT6		(_MX51_PAD_SD2_DATA2__SD1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		(_MX51_PAD_SD2_DATA2__USBH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__CSPI_SS2		(_MX51_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD1_DAT7		(_MX51_PAD_SD2_DATA3__SD1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__CCM_OUT_2		(_MX51_PAD_GPIO1_2__CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__GPIO1_2		(_MX51_PAD_GPIO1_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__I2C2_SCL		(_MX51_PAD_GPIO1_2__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PLL1_BYP		(_MX51_PAD_GPIO1_2__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PWM1_PWMO		(_MX51_PAD_GPIO1_2__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__GPIO1_3		(_MX51_PAD_GPIO1_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__I2C2_SDA		(_MX51_PAD_GPIO1_3__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PLL2_BYP		(_MX51_PAD_GPIO1_3__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PWM2_PWMO		(_MX51_PAD_GPIO1_3__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	(_MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	(_MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		(_MX51_PAD_GPIO1_4__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__EIM_RDY		(_MX51_PAD_GPIO1_4__EIM_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__GPIO1_4		(_MX51_PAD_GPIO1_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		(_MX51_PAD_GPIO1_4__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__CSI2_MCLK		(_MX51_PAD_GPIO1_5__CSI2_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__DISP2_PIN16		(_MX51_PAD_GPIO1_5__DISP2_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__GPIO1_5		(_MX51_PAD_GPIO1_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		(_MX51_PAD_GPIO1_5__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__DISP2_PIN17		(_MX51_PAD_GPIO1_6__DISP2_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__GPIO1_6		(_MX51_PAD_GPIO1_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__REF_EN_B		(_MX51_PAD_GPIO1_6__REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__CCM_OUT_0		(_MX51_PAD_GPIO1_7__CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__GPIO1_7		(_MX51_PAD_GPIO1_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SD2_WP		(_MX51_PAD_GPIO1_7__SD2_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1		(_MX51_PAD_GPIO1_7__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		(_MX51_PAD_GPIO1_8__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__GPIO1_8		(_MX51_PAD_GPIO1_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__SD2_CD		(_MX51_PAD_GPIO1_8__SD2_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__USBH3_PWR		(_MX51_PAD_GPIO1_8__USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__CCM_OUT_1		(_MX51_PAD_GPIO1_9__CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS		(_MX51_PAD_GPIO1_9__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS		(_MX51_PAD_GPIO1_9__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__GPIO1_9		(_MX51_PAD_GPIO1_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__SD2_LCTL		(_MX51_PAD_GPIO1_9__SD2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__USBH3_OC		(_MX51_PAD_GPIO1_9__USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,2359 +23,1197 @@
 
 /* These 2 defines are for pins that may not have a mux register, but could
  * have a pad setting register, and vice-versa. */
-#define NON_PAD_I	0x00
+#define __NA_	0x00
 
 #define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
 		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
 #define MX53_SDHC_PAD_CTRL 	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
 				PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
 				PAD_CTL_SRE_FAST)
-#define PAD_CTRL_I2C	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | PAD_CTL_PKE | \
-			PAD_CTL_PUE | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP \
-			| PAD_CTL_HYS)
 
-#define _MX53_PAD_GPIO_19__KPP_COL_5		IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
-#define _MX53_PAD_GPIO_19__GPIO4_5		IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__CCM_CLKO		IOMUX_PAD(0x348, 0x20, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SPDIF_OUT1	IOMUX_PAD(0x348, 0x20, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2	IOMUX_PAD(0x348, 0x20, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__ECSPI1_RDY	IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__FEC_TDATA_3	IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SRC_INT_BOOT	IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__GPIO4_6		IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
-#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__ECSPI1_SCLK	IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
-#define _MX53_PAD_KEY_COL0__FEC_RDATA_3	IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST	IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__KPP_ROW_0	IOMUX_PAD(0x350, 0x28, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__GPIO4_7		IOMUX_PAD(0x350, 0x28, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	IOMUX_PAD(0x350, 0x28, 2, 0x74C, 0, 0)
-#define _MX53_PAD_KEY_ROW0__UART4_RXD_MUX	IOMUX_PAD(0x350, 0x28, 4, 0x890, 1, 0)
-#define _MX53_PAD_KEY_ROW0__ECSPI1_MOSI	IOMUX_PAD(0x350, 0x28, 5, 0x7A4, 0, 0)
-#define _MX53_PAD_KEY_ROW0__FEC_TX_ER	IOMUX_PAD(0x350, 0x28, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__KPP_COL_1	IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__GPIO4_8		IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
-#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__ECSPI1_MISO	IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
-#define _MX53_PAD_KEY_COL1__FEC_RX_CLK	IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
-#define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY	IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__KPP_ROW_1	IOMUX_PAD(0x358, 0x30, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__GPIO4_9		IOMUX_PAD(0x358, 0x30, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	IOMUX_PAD(0x358, 0x30, 2, 0x748, 0, 0)
-#define _MX53_PAD_KEY_ROW1__UART5_RXD_MUX	IOMUX_PAD(0x358, 0x30, 4, 0x898, 1, 0)
-#define _MX53_PAD_KEY_ROW1__ECSPI1_SS0	IOMUX_PAD(0x358, 0x30, 5, 0x7A8, 0, 0)
-#define _MX53_PAD_KEY_ROW1__FEC_COL		IOMUX_PAD(0x358, 0x30, 6, 0x800, 0, 0)
-#define _MX53_PAD_KEY_ROW1__USBPHY1_RXVALID	IOMUX_PAD(0x358, 0x30, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__KPP_COL_2	IOMUX_PAD(0x35C, 0x34, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__GPIO4_10		IOMUX_PAD(0x35C, 0x34, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__CAN1_TXCAN	IOMUX_PAD(0x35C, 0x34, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_MDIO		IOMUX_PAD(0x35C, 0x34, 4, 0x804, 0, 0)
-#define _MX53_PAD_KEY_COL2__ECSPI1_SS1	IOMUX_PAD(0x35C, 0x34, 5, 0x7AC, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_RDATA_2	IOMUX_PAD(0x35C, 0x34, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE	IOMUX_PAD(0x35C, 0x34, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__KPP_ROW_2	IOMUX_PAD(0x360, 0x38, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__GPIO4_11	IOMUX_PAD(0x360, 0x38, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__CAN1_RXCAN	IOMUX_PAD(0x360, 0x38, 2, 0x760, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_MDC		IOMUX_PAD(0x360, 0x38, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__ECSPI1_SS2	IOMUX_PAD(0x360, 0x38, 5, 0x7B0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_TDATA_2	IOMUX_PAD(0x360, 0x38, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__USBPHY1_RXERROR	IOMUX_PAD(0x360, 0x38, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__KPP_COL_3	IOMUX_PAD(0x364, 0x3C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__GPIO4_12		IOMUX_PAD(0x364, 0x3C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBOH3_H2_DP	IOMUX_PAD(0x364, 0x3C, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__SPDIF_IN1	IOMUX_PAD(0x364, 0x3C, 3, 0x870, 0, 0)
-#define _MX53_PAD_KEY_COL3__I2C2_SCL		IOMUX_PAD(0x364, 0x3C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, 0)
-#define _MX53_PAD_KEY_COL3__ECSPI1_SS3	IOMUX_PAD(0x364, 0x3C, 5, 0x7B4, 0, 0)
-#define _MX53_PAD_KEY_COL3__FEC_CRS		IOMUX_PAD(0x364, 0x3C, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK	IOMUX_PAD(0x364, 0x3C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__KPP_ROW_3	IOMUX_PAD(0x368, 0x40, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__GPIO4_13	IOMUX_PAD(0x368, 0x40, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBOH3_H2_DM	IOMUX_PAD(0x368, 0x40, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x368, 0x40, 3, 0x768, 0, 0)
-#define _MX53_PAD_KEY_ROW3__I2C2_SDA	IOMUX_PAD(0x368, 0x40, 4 | IOMUX_CONFIG_SION, 0x820, 0, 0)
-#define _MX53_PAD_KEY_ROW3__OSC32K_32K_OUT	IOMUX_PAD(0x368, 0x40, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_PLL4_BYP	IOMUX_PAD(0x368, 0x40, 6, 0x77C, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0	IOMUX_PAD(0x368, 0x40, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__KPP_COL_4	IOMUX_PAD(0x36C, 0x44, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__GPIO4_14		IOMUX_PAD(0x36C, 0x44, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__CAN2_TXCAN	IOMUX_PAD(0x36C, 0x44, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__IPU_SISG_4	IOMUX_PAD(0x36C, 0x44, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__UART5_RTS	IOMUX_PAD(0x36C, 0x44, 4, 0x894, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC	IOMUX_PAD(0x36C, 0x44, 5, 0x89C, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1	IOMUX_PAD(0x36C, 0x44, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__KPP_ROW_4	IOMUX_PAD(0x370, 0x48, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__GPIO4_15	IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__CAN2_RXCAN	IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
-#define _MX53_PAD_KEY_ROW4__IPU_SISG_5	IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR	IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID	IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__GPIO4_16		IOMUX_PAD(0x378, 0x4C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR	IOMUX_PAD(0x378, 0x4C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x4C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0	IOMUX_PAD(0x378, 0x4C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID	IOMUX_PAD(0x378, 0x4C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x50, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__GPIO4_17		IOMUX_PAD(0x37C, 0x50, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC	IOMUX_PAD(0x37C, 0x50, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x50, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1	IOMUX_PAD(0x37C, 0x50, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x50, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		IOMUX_PAD(0x380, 0x54, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x54, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD	IOMUX_PAD(0x380, 0x54, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x54, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x54, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION	IOMUX_PAD(0x380, 0x54, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		IOMUX_PAD(0x384, 0x58, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x58, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS	IOMUX_PAD(0x384, 0x58, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x58, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x58, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x58, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		IOMUX_PAD(0x388, 0x5C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x5C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD	IOMUX_PAD(0x388, 0x5C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__ESDHC1_WP		IOMUX_PAD(0x388, 0x5C, 3, 0x7FC, 0, 0)
-#define _MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD	IOMUX_PAD(0x388, 0x5C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x5C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x5C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0	IOMUX_PAD(0x38C, 0x60, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__GPIO4_21		IOMUX_PAD(0x38C, 0x60, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__CSPI_SCLK		IOMUX_PAD(0x38C, 0x60, 2, 0x780, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x60, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x60, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5	IOMUX_PAD(0x38C, 0x60, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY	IOMUX_PAD(0x38C, 0x60, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1	IOMUX_PAD(0x390, 0x64, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__GPIO4_22		IOMUX_PAD(0x390, 0x64, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__CSPI_MOSI		IOMUX_PAD(0x390, 0x64, 2, 0x788, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x64, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	IOMUX_PAD(0x390, 0x64, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6	IOMUX_PAD(0x390, 0x64, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID	IOMUX_PAD(0x390, 0x64, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2	IOMUX_PAD(0x394, 0x68, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__GPIO4_23		IOMUX_PAD(0x394, 0x68, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__CSPI_MISO		IOMUX_PAD(0x394, 0x68, 2, 0x784, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x68, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE	IOMUX_PAD(0x394, 0x68, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7	IOMUX_PAD(0x394, 0x68, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE	IOMUX_PAD(0x394, 0x68, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3	IOMUX_PAD(0x398, 0x6C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__GPIO4_24		IOMUX_PAD(0x398, 0x6C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__CSPI_SS0		IOMUX_PAD(0x398, 0x6C, 2, 0x78C, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x6C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x6C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8	IOMUX_PAD(0x398, 0x6C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR	IOMUX_PAD(0x398, 0x6C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4	IOMUX_PAD(0x39C, 0x70, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__GPIO4_25		IOMUX_PAD(0x39C, 0x70, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__CSPI_SS1		IOMUX_PAD(0x39C, 0x70, 2, 0x790, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x70, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB	IOMUX_PAD(0x39C, 0x70, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9	IOMUX_PAD(0x39C, 0x70, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK	IOMUX_PAD(0x39C, 0x70, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5	IOMUX_PAD(0x3A0, 0x74, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__GPIO4_26		IOMUX_PAD(0x3A0, 0x74, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__CSPI_SS2		IOMUX_PAD(0x3A0, 0x74, 2, 0x794, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x74, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x74, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10	IOMUX_PAD(0x3A0, 0x74, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x74, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6	IOMUX_PAD(0x3A4, 0x78, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__GPIO4_27		IOMUX_PAD(0x3A4, 0x78, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__CSPI_SS3		IOMUX_PAD(0x3A4, 0x78, 2, 0x798, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x78, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x78, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11	IOMUX_PAD(0x3A4, 0x78, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x78, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7	IOMUX_PAD(0x3A8, 0x7C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__GPIO4_28		IOMUX_PAD(0x3A8, 0x7C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__CSPI_RDY		IOMUX_PAD(0x3A8, 0x7C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x7C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x7C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12	IOMUX_PAD(0x3A8, 0x7C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID	IOMUX_PAD(0x3A8, 0x7C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8	IOMUX_PAD(0x3AC, 0x80, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__GPIO4_29		IOMUX_PAD(0x3AC, 0x80, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__PWM1_PWMO		IOMUX_PAD(0x3AC, 0x80, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B	IOMUX_PAD(0x3AC, 0x80, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x80, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13	IOMUX_PAD(0x3AC, 0x80, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__USBPHY2_AVALID	IOMUX_PAD(0x3AC, 0x80, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9	IOMUX_PAD(0x3B0, 0x84, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__GPIO4_30		IOMUX_PAD(0x3B0, 0x84, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__PWM2_PWMO		IOMUX_PAD(0x3B0, 0x84, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B	IOMUX_PAD(0x3B0, 0x84, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x3B0, 0x84, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14	IOMUX_PAD(0x3B0, 0x84, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0	IOMUX_PAD(0x3B0, 0x84, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10	IOMUX_PAD(0x3B4, 0x88, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__GPIO4_31		IOMUX_PAD(0x3B4, 0x88, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP	IOMUX_PAD(0x3B4, 0x88, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	IOMUX_PAD(0x3B4, 0x88, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15	IOMUX_PAD(0x3B4, 0x88, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1	IOMUX_PAD(0x3B4, 0x88, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11	IOMUX_PAD(0x3B8, 0x8C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__GPIO5_5		IOMUX_PAD(0x3B8, 0x8C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT	IOMUX_PAD(0x3B8, 0x8C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	IOMUX_PAD(0x3B8, 0x8C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16	IOMUX_PAD(0x3B8, 0x8C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2	IOMUX_PAD(0x3B8, 0x8C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12	IOMUX_PAD(0x3BC, 0x90, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__GPIO5_6		IOMUX_PAD(0x3BC, 0x90, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK	IOMUX_PAD(0x3BC, 0x90, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	IOMUX_PAD(0x3BC, 0x90, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17	IOMUX_PAD(0x3BC, 0x90, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3	IOMUX_PAD(0x3BC, 0x90, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13	IOMUX_PAD(0x3C0, 0x94, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__GPIO5_7		IOMUX_PAD(0x3C0, 0x94, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x3C0, 0x94, 3, 0x754, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	IOMUX_PAD(0x3C0, 0x94, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18	IOMUX_PAD(0x3C0, 0x94, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4	IOMUX_PAD(0x3C0, 0x94, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14	IOMUX_PAD(0x3C4, 0x98, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__GPIO5_8		IOMUX_PAD(0x3C4, 0x98, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC	IOMUX_PAD(0x3C4, 0x98, 3, 0x750, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	IOMUX_PAD(0x3C4, 0x98, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19	IOMUX_PAD(0x3C4, 0x98, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5	IOMUX_PAD(0x3C4, 0x98, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15	IOMUX_PAD(0x3C8, 0x9C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__GPIO5_9		IOMUX_PAD(0x3C8, 0x9C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x9C, 2, 0x7AC, 1, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x9C, 3, 0x7C8, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	IOMUX_PAD(0x3C8, 0x9C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20	IOMUX_PAD(0x3C8, 0x9C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6	IOMUX_PAD(0x3C8, 0x9C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16	IOMUX_PAD(0x3CC, 0xA0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__GPIO5_10		IOMUX_PAD(0x3CC, 0xA0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0xA0, 2, 0x7C0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC	IOMUX_PAD(0x3CC, 0xA0, 3, 0x758, 1, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0	IOMUX_PAD(0x3CC, 0xA0, 4, 0x868, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	IOMUX_PAD(0x3CC, 0xA0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21	IOMUX_PAD(0x3CC, 0xA0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7	IOMUX_PAD(0x3CC, 0xA0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17	IOMUX_PAD(0x3D0, 0xA4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__GPIO5_11		IOMUX_PAD(0x3D0, 0xA4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0xA4, 2, 0x7BC, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD	IOMUX_PAD(0x3D0, 0xA4, 3, 0x74C, 1, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1	IOMUX_PAD(0x3D0, 0xA4, 4, 0x86C, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	IOMUX_PAD(0x3D0, 0xA4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22	IOMUX_PAD(0x3D0, 0xA4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18	IOMUX_PAD(0x3D4, 0xA8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__GPIO5_12		IOMUX_PAD(0x3D4, 0xA8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0xA8, 2, 0x7C4, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x3D4, 0xA8, 3, 0x75C, 1, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x3D4, 0xA8, 4, 0x73C, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	IOMUX_PAD(0x3D4, 0xA8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23	IOMUX_PAD(0x3D4, 0xA8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2	IOMUX_PAD(0x3D4, 0xA8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19	IOMUX_PAD(0x3D8, 0xAC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__GPIO5_13		IOMUX_PAD(0x3D8, 0xAC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0xAC, 2, 0x7B8, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD	IOMUX_PAD(0x3D8, 0xAC, 3, 0x748, 1, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC	IOMUX_PAD(0x3D8, 0xAC, 4, 0x738, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	IOMUX_PAD(0x3D8, 0xAC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24	IOMUX_PAD(0x3D8, 0xAC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3	IOMUX_PAD(0x3D8, 0xAC, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20	IOMUX_PAD(0x3DC, 0xB0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__GPIO5_14		IOMUX_PAD(0x3DC, 0xB0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0xB0, 2, 0x79C, 1, 0)
-#define _MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC	IOMUX_PAD(0x3DC, 0xB0, 3, 0x740, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	IOMUX_PAD(0x3DC, 0xB0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25	IOMUX_PAD(0x3DC, 0xB0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0xB0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21	IOMUX_PAD(0x3E0, 0xB4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__GPIO5_15		IOMUX_PAD(0x3E0, 0xB4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0xB4, 2, 0x7A4, 1, 0)
-#define _MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD	IOMUX_PAD(0x3E0, 0xB4, 3, 0x734, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0xB4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26	IOMUX_PAD(0x3E0, 0xB4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SATA_PHY_TDO	IOMUX_PAD(0x3E0, 0xB4, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22	IOMUX_PAD(0x3E4, 0xB8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__GPIO5_16		IOMUX_PAD(0x3E4, 0xB8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0xB8, 2, 0x7A0, 1, 0)
-#define _MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x3E4, 0xB8, 3, 0x744, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0xB8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27	IOMUX_PAD(0x3E4, 0xB8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SATA_PHY_TCK	IOMUX_PAD(0x3E4, 0xB8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23	IOMUX_PAD(0x3E8, 0xBC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__GPIO5_17		IOMUX_PAD(0x3E8, 0xBC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0xBC, 2, 0x7A8, 1, 0)
-#define _MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD	IOMUX_PAD(0x3E8, 0xBC, 3, 0x730, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0xBC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28	IOMUX_PAD(0x3E8, 0xBC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SATA_PHY_TMS	IOMUX_PAD(0x3E8, 0xBC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK	IOMUX_PAD(0x3EC, 0xC0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__GPIO5_18		IOMUX_PAD(0x3EC, 0xC0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0	IOMUX_PAD(0x3EC, 0xC0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29	IOMUX_PAD(0x3EC, 0xC0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0xC4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__GPIO5_19		IOMUX_PAD(0x3F0, 0xC4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0xC4, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1	IOMUX_PAD(0x3F0, 0xC4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30	IOMUX_PAD(0x3F0, 0xC4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__TPIU_TRCTL		IOMUX_PAD(0x3F0, 0xC4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN	IOMUX_PAD(0x3F4, 0xC8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__GPIO5_20		IOMUX_PAD(0x3F4, 0xC8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2	IOMUX_PAD(0x3F4, 0xC8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31	IOMUX_PAD(0x3F4, 0xC8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0xC8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC	IOMUX_PAD(0x3F8, 0xCC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__GPIO5_21		IOMUX_PAD(0x3F8, 0xCC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3	IOMUX_PAD(0x3F8, 0xCC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32	IOMUX_PAD(0x3F8, 0xCC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0xCC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0xD0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__GPIO5_22		IOMUX_PAD(0x3FC, 0xD0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__KPP_COL_5		IOMUX_PAD(0x3FC, 0xD0, 2, 0x840, 1, 0)
-#define _MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		IOMUX_PAD(0x3FC, 0xD0, 3, 0x79C, 2, 0)
-#define _MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP	IOMUX_PAD(0x3FC, 0xD0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	IOMUX_PAD(0x3FC, 0xD0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33	IOMUX_PAD(0x3FC, 0xD0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0xD0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0xD4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__GPIO5_23		IOMUX_PAD(0x400, 0xD4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__KPP_ROW_5		IOMUX_PAD(0x400, 0xD4, 2, 0x84C, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		IOMUX_PAD(0x400, 0xD4, 3, 0x7A4, 2, 0)
-#define _MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT	IOMUX_PAD(0x400, 0xD4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	IOMUX_PAD(0x400, 0xD4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34	IOMUX_PAD(0x400, 0xD4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0xD4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0xD8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__GPIO5_24		IOMUX_PAD(0x404, 0xD8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__KPP_COL_6		IOMUX_PAD(0x404, 0xD8, 2, 0x844, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__ECSPI1_MISO		IOMUX_PAD(0x404, 0xD8, 3, 0x7A0, 2, 0)
-#define _MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK	IOMUX_PAD(0x404, 0xD8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	IOMUX_PAD(0x404, 0xD8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35	IOMUX_PAD(0x404, 0xD8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0xD8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0xDC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__GPIO5_25		IOMUX_PAD(0x408, 0xDC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__KPP_ROW_6		IOMUX_PAD(0x408, 0xDC, 2, 0x850, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__ECSPI1_SS0		IOMUX_PAD(0x408, 0xDC, 3, 0x7A8, 2, 0)
-#define _MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR	IOMUX_PAD(0x408, 0xDC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	IOMUX_PAD(0x408, 0xDC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36	IOMUX_PAD(0x408, 0xDC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0xDC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0xE0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__GPIO5_26		IOMUX_PAD(0x40C, 0xE0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__KPP_COL_7		IOMUX_PAD(0x40C, 0xE0, 2, 0x848, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		IOMUX_PAD(0x40C, 0xE0, 3, 0x7B8, 1, 0)
-#define _MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC	IOMUX_PAD(0x40C, 0xE0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__I2C1_SDA		IOMUX_PAD(0x40C, 0xE0, 5 | IOMUX_CONFIG_SION, 0x818, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37	IOMUX_PAD(0x40C, 0xE0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0xE0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0xE4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__GPIO5_27		IOMUX_PAD(0x410, 0xE4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__KPP_ROW_7		IOMUX_PAD(0x410, 0xE4, 2, 0x854, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		IOMUX_PAD(0x410, 0xE4, 3, 0x7C0, 1, 0)
-#define _MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR	IOMUX_PAD(0x410, 0xE4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__I2C1_SCL		IOMUX_PAD(0x410, 0xE4, 5 | IOMUX_CONFIG_SION, 0x814, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38	IOMUX_PAD(0x410, 0xE4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__GPIO5_28		IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
-#define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC	IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4	IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39	IOMUX_PAD(0x414, 0xE8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0xE8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0xEC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__GPIO5_29		IOMUX_PAD(0x418, 0xEC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__ECSPI2_SS0		IOMUX_PAD(0x418, 0xEC, 3, 0x7C4, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS	IOMUX_PAD(0x418, 0xEC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5	IOMUX_PAD(0x418, 0xEC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40	IOMUX_PAD(0x418, 0xEC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__GPIO5_30		IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6	IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41	IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0xF0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0xF4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__GPIO5_31		IOMUX_PAD(0x420, 0xF4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__UART4_RXD_MUX	IOMUX_PAD(0x420, 0xF4, 2, 0x890, 3, 0)
-#define _MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0xF4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7	IOMUX_PAD(0x420, 0xF4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42	IOMUX_PAD(0x420, 0xF4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__GPIO6_0		IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8	IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43	IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0xF8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0xFC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__GPIO6_1		IOMUX_PAD(0x428, 0xFC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__UART5_RXD_MUX	IOMUX_PAD(0x428, 0xFC, 2, 0x898, 3, 0)
-#define _MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0xFC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9	IOMUX_PAD(0x428, 0xFC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44	IOMUX_PAD(0x428, 0xFC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0xFC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__GPIO6_2		IOMUX_PAD(0x42C, 0x100, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__UART4_RTS		IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10	IOMUX_PAD(0x42C, 0x100, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45	IOMUX_PAD(0x42C, 0x100, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__GPIO6_3		IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11	IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46	IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__GPIO6_4		IOMUX_PAD(0x434, 0x108, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__UART5_RTS		IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, 0)
-#define _MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12	IOMUX_PAD(0x434, 0x108, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47	IOMUX_PAD(0x434, 0x108, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__GPIO6_5		IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13	IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48	IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK	IOMUX_PAD(0x438, 0x10C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__EMI_WEIM_A_25		IOMUX_PAD(0x458, 0x110, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__ECSPI2_RDY		IOMUX_PAD(0x458, 0x110, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI1_PIN12		IOMUX_PAD(0x458, 0x110, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI0_D1_CS		IOMUX_PAD(0x458, 0x110, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		IOMUX_PAD(0x45C, 0x114, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, 0)
-#define _MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__ECSPI1_SS0		IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, 0)
-#define _MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, 0)
-#define _MX53_PAD_EIM_D16__EMI_WEIM_D_16		IOMUX_PAD(0x460, 0x118, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DI0_PIN5		IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK	IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__ECSPI1_SCLK		IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
-#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, 0)
-#define _MX53_PAD_EIM_D17__EMI_WEIM_D_17		IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DI0_PIN6		IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN	IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
-#define _MX53_PAD_EIM_D17__ECSPI1_MISO		IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
-#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, 0)
-#define _MX53_PAD_EIM_D18__EMI_WEIM_D_18		IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI0_PIN7		IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO	IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
-#define _MX53_PAD_EIM_D18__ECSPI1_MOSI		IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
-#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS		IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__EMI_WEIM_D_19		IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DI0_PIN8		IOMUX_PAD(0x46C, 0x124, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS	IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__ECSPI1_SS1		IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
-#define _MX53_PAD_EIM_D19__EPIT1_EPITO		IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
-#define _MX53_PAD_EIM_D20__EMI_WEIM_D_20		IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_DI0_PIN16		IOMUX_PAD(0x470, 0x128, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, 0)
-#define _MX53_PAD_EIM_D20__EPIT2_EPITO		IOMUX_PAD(0x470, 0x128, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, 0)
-#define _MX53_PAD_EIM_D20__USBOH3_USBH2_PWR	IOMUX_PAD(0x470, 0x128, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__EMI_WEIM_D_21		IOMUX_PAD(0x474, 0x12C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DI0_PIN17		IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK	IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
-#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, 0)
-#define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC	IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
-#define _MX53_PAD_EIM_D22__EMI_WEIM_D_22		IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DI0_PIN1		IOMUX_PAD(0x478, 0x130, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN	IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, 0)
-#define _MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, 0)
-#define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR	IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__EMI_WEIM_D_23		IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART1_DCD		IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS		IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN2		IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN14		IOMUX_PAD(0x47C, 0x134, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		IOMUX_PAD(0x480, 0x138, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, 0)
-#define _MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN3		IOMUX_PAD(0x480, 0x138, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16		IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__EMI_WEIM_D_24		IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__ECSPI1_SS2		IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
-#define _MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
-#define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
-#define _MX53_PAD_EIM_D24__ECSPI2_SS2		IOMUX_PAD(0x484, 0x13C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART1_DTR		IOMUX_PAD(0x484, 0x13C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__EMI_WEIM_D_25		IOMUX_PAD(0x488, 0x140, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART3_RXD_MUX		IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI1_SS3		IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, 0)
-#define _MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, 0)
-#define _MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI2_SS3		IOMUX_PAD(0x488, 0x140, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART1_DSR		IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__EMI_WEIM_D_26		IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_CSI0_D_1		IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DI1_PIN11		IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_SISG_2		IOMUX_PAD(0x48C, 0x144, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__EMI_WEIM_D_27		IOMUX_PAD(0x490, 0x148, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__UART2_RXD_MUX		IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, 0)
-#define _MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_CSI0_D_0		IOMUX_PAD(0x490, 0x148, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DI1_PIN13		IOMUX_PAD(0x490, 0x148, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_SISG_3		IOMUX_PAD(0x490, 0x148, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__EMI_WEIM_D_28		IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO	IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
-#define _MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
-#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, 0)
-#define _MX53_PAD_EIM_D28__IPU_EXT_TRIG		IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DI0_PIN13		IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__EMI_WEIM_D_29		IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, 0)
-#define _MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS	IOMUX_PAD(0x498, 0x150, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI1_PIN15		IOMUX_PAD(0x498, 0x150, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI0_PIN14		IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__EMI_WEIM_D_30		IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_CSI0_D_3		IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DI0_PIN11		IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, 0)
-#define _MX53_PAD_EIM_D31__EMI_WEIM_D_31		IOMUX_PAD(0x4A0, 0x158, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, 0)
-#define _MX53_PAD_EIM_D31__IPU_CSI0_D_2		IOMUX_PAD(0x4A0, 0x158, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DI0_PIN12		IOMUX_PAD(0x4A0, 0x158, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH1_PWR	IOMUX_PAD(0x4A0, 0x158, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH2_PWR	IOMUX_PAD(0x4A0, 0x158, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__EMI_WEIM_A_24		IOMUX_PAD(0x4A8, 0x15C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_CSI1_D_19		IOMUX_PAD(0x4A8, 0x15C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_SISG_2		IOMUX_PAD(0x4A8, 0x15C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__EMI_WEIM_A_23		IOMUX_PAD(0x4AC, 0x160, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_CSI1_D_18		IOMUX_PAD(0x4AC, 0x160, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_SISG_3		IOMUX_PAD(0x4AC, 0x160, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__USBPHY2_ENDSESSION	IOMUX_PAD(0x4AC, 0x160, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__EMI_WEIM_A_22		IOMUX_PAD(0x4B0, 0x164, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_CSI1_D_17		IOMUX_PAD(0x4B0, 0x164, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__SRC_BT_CFG1_7		IOMUX_PAD(0x4B0, 0x164, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__EMI_WEIM_A_21		IOMUX_PAD(0x4B4, 0x168, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_CSI1_D_16		IOMUX_PAD(0x4B4, 0x168, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__SRC_BT_CFG1_6		IOMUX_PAD(0x4B4, 0x168, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__EMI_WEIM_A_20		IOMUX_PAD(0x4B8, 0x16C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_CSI1_D_15		IOMUX_PAD(0x4B8, 0x16C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__SRC_BT_CFG1_5		IOMUX_PAD(0x4B8, 0x16C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__EMI_WEIM_A_19		IOMUX_PAD(0x4BC, 0x170, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_CSI1_D_14		IOMUX_PAD(0x4BC, 0x170, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__SRC_BT_CFG1_4		IOMUX_PAD(0x4BC, 0x170, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__EMI_WEIM_A_18		IOMUX_PAD(0x4C0, 0x174, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_CSI1_D_13		IOMUX_PAD(0x4C0, 0x174, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__SRC_BT_CFG1_3		IOMUX_PAD(0x4C0, 0x174, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__EMI_WEIM_A_17		IOMUX_PAD(0x4C4, 0x178, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_CSI1_D_12		IOMUX_PAD(0x4C4, 0x178, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__SRC_BT_CFG1_2		IOMUX_PAD(0x4C4, 0x178, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__EMI_WEIM_A_16		IOMUX_PAD(0x4C8, 0x17C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__SRC_BT_CFG1_1		IOMUX_PAD(0x4C8, 0x17C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		IOMUX_PAD(0x4CC, 0x180, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__ECSPI2_SCLK		IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, 0)
-#define _MX53_PAD_EIM_CS0__IPU_DI1_PIN5		IOMUX_PAD(0x4CC, 0x180, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		IOMUX_PAD(0x4D0, 0x184, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__ECSPI2_MOSI		IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, 0)
-#define _MX53_PAD_EIM_CS1__IPU_DI1_PIN6		IOMUX_PAD(0x4D0, 0x184, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__EMI_WEIM_OE		IOMUX_PAD(0x4D4, 0x188, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__ECSPI2_MISO		IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, 0)
-#define _MX53_PAD_EIM_OE__IPU_DI1_PIN7		IOMUX_PAD(0x4D4, 0x188, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__USBPHY2_IDDIG		IOMUX_PAD(0x4D4, 0x188, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__EMI_WEIM_RW		IOMUX_PAD(0x4D8, 0x18C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, 0)
-#define _MX53_PAD_EIM_RW__IPU_DI1_PIN8		IOMUX_PAD(0x4D8, 0x18C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT	IOMUX_PAD(0x4D8, 0x18C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__EMI_WEIM_LBA		IOMUX_PAD(0x4DC, 0x190, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__ECSPI2_SS1		IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, 0)
-#define _MX53_PAD_EIM_LBA__IPU_DI1_PIN17		IOMUX_PAD(0x4DC, 0x190, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		IOMUX_PAD(0x4DC, 0x190, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		IOMUX_PAD(0x4E4, 0x194, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_CSI1_D_11		IOMUX_PAD(0x4E4, 0x194, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPC_PMIC_RDY		IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, 0)
-#define _MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		IOMUX_PAD(0x4E4, 0x194, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		IOMUX_PAD(0x4E8, 0x198, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_CSI1_D_10		IOMUX_PAD(0x4E8, 0x198, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		IOMUX_PAD(0x4E8, 0x198, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0	IOMUX_PAD(0x4EC, 0x19C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_CSI1_D_9		IOMUX_PAD(0x4EC, 0x19C, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		IOMUX_PAD(0x4EC, 0x19C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1	IOMUX_PAD(0x4F0, 0x1A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_CSI1_D_8		IOMUX_PAD(0x4F0, 0x1A0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		IOMUX_PAD(0x4F0, 0x1A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2	IOMUX_PAD(0x4F4, 0x1A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_CSI1_D_7		IOMUX_PAD(0x4F4, 0x1A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		IOMUX_PAD(0x4F4, 0x1A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3	IOMUX_PAD(0x4F8, 0x1A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_CSI1_D_6		IOMUX_PAD(0x4F8, 0x1A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		IOMUX_PAD(0x4F8, 0x1A8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4	IOMUX_PAD(0x4FC, 0x1AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_CSI1_D_5		IOMUX_PAD(0x4FC, 0x1AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		IOMUX_PAD(0x4FC, 0x1AC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5	IOMUX_PAD(0x500, 0x1B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4		IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_CSI1_D_3		IOMUX_PAD(0x504, 0x1B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		IOMUX_PAD(0x504, 0x1B4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7	IOMUX_PAD(0x508, 0x1B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_CSI1_D_2		IOMUX_PAD(0x508, 0x1B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		IOMUX_PAD(0x508, 0x1B8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8	IOMUX_PAD(0x50C, 0x1BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_CSI1_D_1		IOMUX_PAD(0x50C, 0x1BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		IOMUX_PAD(0x50C, 0x1BC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9	IOMUX_PAD(0x510, 0x1C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_CSI1_D_0		IOMUX_PAD(0x510, 0x1C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		IOMUX_PAD(0x510, 0x1C0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10	IOMUX_PAD(0x514, 0x1C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN	IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, 0)
-#define _MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11	IOMUX_PAD(0x518, 0x1C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_DI1_PIN2		IOMUX_PAD(0x518, 0x1C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, 0)
-#define _MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12	IOMUX_PAD(0x51C, 0x1CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_DI1_PIN3		IOMUX_PAD(0x51C, 0x1CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, 0)
-#define _MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13	IOMUX_PAD(0x520, 0x1D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, 0)
-#define _MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14	IOMUX_PAD(0x524, 0x1D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15	IOMUX_PAD(0x528, 0x1D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN1		IOMUX_PAD(0x528, 0x1D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN4		IOMUX_PAD(0x528, 0x1D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	IOMUX_PAD(0x52C, 0x1DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__GPIO6_12		IOMUX_PAD(0x52C, 0x1DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	IOMUX_PAD(0x530, 0x1E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__GPIO6_13		IOMUX_PAD(0x530, 0x1E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B	IOMUX_PAD(0x534, 0x1E4, 2, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__GPIO6_22		IOMUX_PAD(NON_PAD_I, 0x1EC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3	IOMUX_PAD(NON_PAD_I, 0x1EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__GPIO6_24		IOMUX_PAD(NON_PAD_I, 0x1F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2	IOMUX_PAD(NON_PAD_I, 0x1F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__GPIO6_26		IOMUX_PAD(NON_PAD_I, 0x1F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK	IOMUX_PAD(NON_PAD_I, 0x1F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__GPIO6_28		IOMUX_PAD(NON_PAD_I, 0x1F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1	IOMUX_PAD(NON_PAD_I, 0x1F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__GPIO6_30		IOMUX_PAD(NON_PAD_I, 0x1FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0	IOMUX_PAD(NON_PAD_I, 0x1FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__GPIO7_22		IOMUX_PAD(NON_PAD_I, 0x200, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3	IOMUX_PAD(NON_PAD_I, 0x200, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__GPIO7_24		IOMUX_PAD(NON_PAD_I, 0x204, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK	IOMUX_PAD(NON_PAD_I, 0x204, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__GPIO7_26		IOMUX_PAD(NON_PAD_I, 0x208, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2	IOMUX_PAD(NON_PAD_I, 0x208, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__GPIO7_28		IOMUX_PAD(NON_PAD_I, 0x20C, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1	IOMUX_PAD(NON_PAD_I, 0x20C, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__GPIO7_30		IOMUX_PAD(NON_PAD_I, 0x210, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0	IOMUX_PAD(NON_PAD_I, 0x210, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0	IOMUX_PAD(0x5A0, 0x228, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__GPIO6_8		IOMUX_PAD(0x5A4, 0x22C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1	IOMUX_PAD(0x5A4, 0x22C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	IOMUX_PAD(0x5A8, 0x230, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__GPIO6_9		IOMUX_PAD(0x5A8, 0x230, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2	IOMUX_PAD(0x5A8, 0x230, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	IOMUX_PAD(0x5AC, 0x234, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__GPIO6_10		IOMUX_PAD(0x5AC, 0x234, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3	IOMUX_PAD(0x5AC, 0x234, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	IOMUX_PAD(0x5B0, 0x238, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__GPIO6_11		IOMUX_PAD(0x5B0, 0x238, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4	IOMUX_PAD(0x5B0, 0x238, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1	IOMUX_PAD(0x5B4, 0x23C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__GPIO6_14		IOMUX_PAD(0x5B4, 0x23C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__MLB_MLBCLK		IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, 0)
-#define _MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5	IOMUX_PAD(0x5B4, 0x23C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2	IOMUX_PAD(0x5B8, 0x240, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__GPIO6_15		IOMUX_PAD(0x5B8, 0x240, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__IPU_SISG_0		IOMUX_PAD(0x5B8, 0x240, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__ESAI1_TX0		IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__MLB_MLBSIG		IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, 0)
-#define _MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6	IOMUX_PAD(0x5B8, 0x240, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3	IOMUX_PAD(0x5BC, 0x244, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__GPIO6_16		IOMUX_PAD(0x5BC, 0x244, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__IPU_SISG_1		IOMUX_PAD(0x5BC, 0x244, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__ESAI1_TX1		IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__MLB_MLBDAT		IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, 0)
-#define _MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7	IOMUX_PAD(0x5BC, 0x244, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_MDIO		IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, 0)
-#define _MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__ESAI1_SCKR		IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, 0)
-#define _MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49	IOMUX_PAD(0x5C4, 0x248, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__GPIO1_23		IOMUX_PAD(0x5C8, 0x24C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__ESAI1_FSR		IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50	IOMUX_PAD(0x5C8, 0x24C, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_ER		IOMUX_PAD(0x5CC, 0x250, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__GPIO1_24		IOMUX_PAD(0x5CC, 0x250, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__ESAI1_HCKR		IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_CLK		IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, 0)
-#define _MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__FEC_RX_DV		IOMUX_PAD(0x5D0, 0x254, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__GPIO1_25		IOMUX_PAD(0x5D0, 0x254, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__FEC_RDATA_1		IOMUX_PAD(0x5D4, 0x258, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__ESAI1_FST		IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__MLB_MLBSIG		IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, 0)
-#define _MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__FEC_RDATA_0		IOMUX_PAD(0x5D8, 0x25C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__ESAI1_HCKT		IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, 0)
-#define _MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__FEC_TX_EN		IOMUX_PAD(0x5DC, 0x260, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__GPIO1_28		IOMUX_PAD(0x5DC, 0x260, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__FEC_TDATA_1		IOMUX_PAD(0x5E0, 0x264, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, 0)
-#define _MX53_PAD_FEC_TXD1__MLB_MLBCLK		IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, 0)
-#define _MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK	IOMUX_PAD(0x5E0, 0x264, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__FEC_TDATA_0		IOMUX_PAD(0x5E4, 0x268, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, 0)
-#define _MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0	IOMUX_PAD(0x5E4, 0x268, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, 0)
-#define _MX53_PAD_FEC_MDC__MLB_MLBDAT		IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, 0)
-#define _MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1	IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__PATA_DIOW		IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__GPIO6_17		IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2	IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__PATA_DMACK		IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__GPIO6_18		IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__UART1_RXD_MUX	IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, 0)
-#define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3	IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__PATA_DMARQ		IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__GPIO7_0		IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0	IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4	IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN	IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1	IOMUX_PAD(0x5FC, 0x27C, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__PATA_INTRQ		IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__GPIO7_2		IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN		IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2	IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6	IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__PATA_DIOR		IOMUX_PAD(0x604, 0x284, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__UART2_RTS		IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, 0)
-#define _MX53_PAD_PATA_DIOR__CAN1_RXCAN		IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, 0)
-#define _MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7	IOMUX_PAD(0x604, 0x284, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__GPIO7_4		IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__PATA_IORDY		IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__GPIO7_5		IOMUX_PAD(0x60C, 0x28C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__ESDHC3_CLK		IOMUX_PAD(0x60C, 0x28C, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__UART1_RTS		IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, 0)
-#define _MX53_PAD_PATA_IORDY__CAN2_RXCAN		IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, 0)
-#define _MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1	IOMUX_PAD(0x60C, 0x28C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__PATA_DA_0		IOMUX_PAD(0x610, 0x290, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__GPIO7_6		IOMUX_PAD(0x610, 0x290, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__ESDHC3_RST		IOMUX_PAD(0x610, 0x290, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__OWIRE_LINE		IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, 0)
-#define _MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2	IOMUX_PAD(0x610, 0x290, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__PATA_DA_1		IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__GPIO7_7		IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__ESDHC4_CMD		IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3	IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__PATA_DA_2		IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__GPIO7_8		IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__ESDHC4_CLK		IOMUX_PAD(0x618, 0x298, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__UART3_RTS		IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, 0)
-#define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4	IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__PATA_CS_0		IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5	IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__PATA_CS_1		IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__GPIO7_10		IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, 0)
-#define _MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6	IOMUX_PAD(0x620, 0x2A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPIO2_0		IOMUX_PAD(0x628, 0x2A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	IOMUX_PAD(0x628, 0x2A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0	IOMUX_PAD(0x628, 0x2A4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7	IOMUX_PAD(0x628, 0x2A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPIO2_1		IOMUX_PAD(0x62C, 0x2A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	IOMUX_PAD(0x62C, 0x2A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1	IOMUX_PAD(0x62C, 0x2A8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPIO2_2		IOMUX_PAD(0x630, 0x2AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	IOMUX_PAD(0x630, 0x2AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2	IOMUX_PAD(0x630, 0x2AC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPIO2_3		IOMUX_PAD(0x634, 0x2B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	IOMUX_PAD(0x634, 0x2B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3	IOMUX_PAD(0x634, 0x2B0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPIO2_4		IOMUX_PAD(0x638, 0x2B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	IOMUX_PAD(0x638, 0x2B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4	IOMUX_PAD(0x638, 0x2B4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__PATA_DATA_5	IOMUX_PAD(0x63C, 0x2B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPIO2_5		IOMUX_PAD(0x63C, 0x2B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	IOMUX_PAD(0x63C, 0x2B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5	IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPIO2_6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPIO2_7		IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7	IOMUX_PAD(0x644, 0x2C0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPIO2_8		IOMUX_PAD(0x648, 0x2C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__EMI_NANDF_D_8	IOMUX_PAD(0x648, 0x2C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8	IOMUX_PAD(0x648, 0x2C4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPIO2_9		IOMUX_PAD(0x64C, 0x2C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__EMI_NANDF_D_9	IOMUX_PAD(0x64C, 0x2C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9	IOMUX_PAD(0x64C, 0x2C8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__PATA_DATA_10	IOMUX_PAD(0x650, 0x2CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPIO2_10		IOMUX_PAD(0x650, 0x2CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__EMI_NANDF_D_10	IOMUX_PAD(0x650, 0x2CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10	IOMUX_PAD(0x650, 0x2CC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__PATA_DATA_11	IOMUX_PAD(0x654, 0x2D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPIO2_11		IOMUX_PAD(0x654, 0x2D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__EMI_NANDF_D_11	IOMUX_PAD(0x654, 0x2D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11	IOMUX_PAD(0x654, 0x2D0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__PATA_DATA_12	IOMUX_PAD(0x658, 0x2D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPIO2_12		IOMUX_PAD(0x658, 0x2D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__EMI_NANDF_D_12	IOMUX_PAD(0x658, 0x2D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12	IOMUX_PAD(0x658, 0x2D4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__PATA_DATA_13	IOMUX_PAD(0x65C, 0x2D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPIO2_13		IOMUX_PAD(0x65C, 0x2D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__EMI_NANDF_D_13	IOMUX_PAD(0x65C, 0x2D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13	IOMUX_PAD(0x65C, 0x2D8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__PATA_DATA_14	IOMUX_PAD(0x660, 0x2DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPIO2_14		IOMUX_PAD(0x660, 0x2DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__EMI_NANDF_D_14	IOMUX_PAD(0x660, 0x2DC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14	IOMUX_PAD(0x660, 0x2DC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__PATA_DATA_15	IOMUX_PAD(0x664, 0x2E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPIO2_15		IOMUX_PAD(0x664, 0x2E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__EMI_NANDF_D_15	IOMUX_PAD(0x664, 0x2E0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15	IOMUX_PAD(0x664, 0x2E0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__ESDHC1_DAT0	IOMUX_PAD(0x66C, 0x2E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPIO1_16	IOMUX_PAD(0x66C, 0x2E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPT_CAPIN1	IOMUX_PAD(0x66C, 0x2E4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__CSPI_MISO	IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, 0)
-#define _MX53_PAD_SD1_DATA0__CCM_PLL3_BYP	IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, 0)
-#define _MX53_PAD_SD1_DATA1__ESDHC1_DAT1	IOMUX_PAD(0x670, 0x2E8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPIO1_17	IOMUX_PAD(0x670, 0x2E8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPT_CAPIN2	IOMUX_PAD(0x670, 0x2E8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__CSPI_SS0	IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, 0)
-#define _MX53_PAD_SD1_DATA1__CCM_PLL4_BYP	IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, 0)
-#define _MX53_PAD_SD1_CMD__ESDHC1_CMD	IOMUX_PAD(0x674, 0x2EC, IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPIO1_18		IOMUX_PAD(0x674, 0x2EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPT_CMPOUT1	IOMUX_PAD(0x674, 0x2EC, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, 0)
-#define _MX53_PAD_SD1_CMD__CCM_PLL1_BYP	IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, 0)
-#define _MX53_PAD_SD1_DATA2__ESDHC1_DAT2		IOMUX_PAD(0x678, 0x2F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPIO1_19		IOMUX_PAD(0x678, 0x2F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPT_CMPOUT2		IOMUX_PAD(0x678, 0x2F0, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__PWM2_PWMO		IOMUX_PAD(0x678, 0x2F0, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CSPI_SS1		IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, 0)
-#define _MX53_PAD_SD1_CLK__ESDHC1_CLK	IOMUX_PAD(0x67C, 0x2F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPIO1_20		IOMUX_PAD(0x67C, 0x2F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__OSC32k_32K_OUT	IOMUX_PAD(0x67C, 0x2F4, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPT_CLKIN		IOMUX_PAD(0x67C, 0x2F4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, 0)
-#define _MX53_PAD_SD1_CLK__SATA_PHY_DTB_0	IOMUX_PAD(0x67C, 0x2F4, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__ESDHC1_DAT3	IOMUX_PAD(0x680, 0x2F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPIO1_21	IOMUX_PAD(0x680, 0x2F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPT_CMPOUT3	IOMUX_PAD(0x680, 0x2F8, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__PWM1_PWMO	IOMUX_PAD(0x680, 0x2F8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_B	IOMUX_PAD(0x680, 0x2F8, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__CSPI_SS2	IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1	IOMUX_PAD(0x680, 0x2F8, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__ESDHC2_CLK	IOMUX_PAD(0x688, 0x2FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__GPIO1_10		IOMUX_PAD(0x688, 0x2FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__KPP_COL_5		IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, 0)
-#define _MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, 0)
-#define _MX53_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, 0)
-#define _MX53_PAD_SD2_CLK__SCC_RANDOM_V	IOMUX_PAD(0x688, 0x2FC, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__ESDHC2_CMD	IOMUX_PAD(0x68C, 0x300, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__GPIO1_11		IOMUX_PAD(0x68C, 0x300, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__KPP_ROW_5	IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, 0)
-#define _MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC	IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, 0)
-#define _MX53_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, 0)
-#define _MX53_PAD_SD2_CMD__SCC_RANDOM	IOMUX_PAD(0x68C, 0x300, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__ESDHC2_DAT3	IOMUX_PAD(0x690, 0x304, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__GPIO1_12	IOMUX_PAD(0x690, 0x304, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__KPP_COL_6	IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, 0)
-#define _MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, 0)
-#define _MX53_PAD_SD2_DATA3__CSPI_SS2	IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, 0)
-#define _MX53_PAD_SD2_DATA3__SJC_DONE	IOMUX_PAD(0x690, 0x304, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__ESDHC2_DAT2	IOMUX_PAD(0x694, 0x308, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__GPIO1_13	IOMUX_PAD(0x694, 0x308, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__KPP_ROW_6	IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, 0)
-#define _MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, 0)
-#define _MX53_PAD_SD2_DATA2__CSPI_SS1	IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, 0)
-#define _MX53_PAD_SD2_DATA2__SJC_FAIL	IOMUX_PAD(0x694, 0x308, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__ESDHC2_DAT1	IOMUX_PAD(0x698, 0x30C, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__GPIO1_14	IOMUX_PAD(0x698, 0x30C, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__KPP_COL_7	IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, 0)
-#define _MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, 0)
-#define _MX53_PAD_SD2_DATA1__CSPI_SS0	IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, 0)
-#define _MX53_PAD_SD2_DATA1__RTIC_SEC_VIO	IOMUX_PAD(0x698, 0x30C, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__ESDHC2_DAT0	IOMUX_PAD(0x69C, 0x310, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__GPIO1_15	IOMUX_PAD(0x69C, 0x310, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__KPP_ROW_7	IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, 0)
-#define _MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, 0)
-#define _MX53_PAD_SD2_DATA0__CSPI_MISO	IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, 0)
-#define _MX53_PAD_SD2_DATA0__RTIC_DONE_INT	IOMUX_PAD(0x69C, 0x310, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CCM_CLKO		IOMUX_PAD(0x6A4, 0x314, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__GPIO1_0		IOMUX_PAD(0x6A4, 0x314, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__KPP_COL_5		IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, 0)
-#define _MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	IOMUX_PAD(0x6A4, 0x314, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__EPIT1_EPITO	IOMUX_PAD(0x6A4, 0x314, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__SRTC_ALARM_DEB	IOMUX_PAD(0x6A4, 0x314, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__USBOH3_USBH1_PWR	IOMUX_PAD(0x6A4, 0x314, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CSU_TD		IOMUX_PAD(0x6A4, 0x314, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESAI1_SCKR		IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, 0)
-#define _MX53_PAD_GPIO_1__GPIO1_1		IOMUX_PAD(0x6A8, 0x318, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__KPP_ROW_5		IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, 0)
-#define _MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK	IOMUX_PAD(0x6A8, 0x318, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__PWM2_PWMO	IOMUX_PAD(0x6A8, 0x318, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__WDOG2_WDOG_B	IOMUX_PAD(0x6A8, 0x318, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESDHC1_CD		IOMUX_PAD(0x6A8, 0x318, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__SRC_TESTER_ACK	IOMUX_PAD(0x6A8, 0x318, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESAI1_FSR		IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, 0)
-#define _MX53_PAD_GPIO_9__GPIO1_9		IOMUX_PAD(0x6AC, 0x31C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__KPP_COL_6		IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, 0)
-#define _MX53_PAD_GPIO_9__CCM_REF_EN_B	IOMUX_PAD(0x6AC, 0x31C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__PWM1_PWMO	IOMUX_PAD(0x6AC, 0x31C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__WDOG1_WDOG_B	IOMUX_PAD(0x6AC, 0x31C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESDHC1_WP		IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, 0)
-#define _MX53_PAD_GPIO_9__SCC_FAIL_STATE	IOMUX_PAD(0x6AC, 0x31C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__ESAI1_HCKR		IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, 0)
-#define _MX53_PAD_GPIO_3__GPIO1_3		IOMUX_PAD(0x6B0, 0x320, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__I2C3_SCL		IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, 0)
-#define _MX53_PAD_GPIO_3__DPLLIP1_TOG_EN	IOMUX_PAD(0x6B0, 0x320, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__CCM_CLKO2		IOMUX_PAD(0x6B0, 0x320, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__USBOH3_USBH1_OC	IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, 0)
-#define _MX53_PAD_GPIO_3__MLB_MLBCLK		IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, 0)
-#define _MX53_PAD_GPIO_6__ESAI1_SCKT		IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, 0)
-#define _MX53_PAD_GPIO_6__GPIO1_6		IOMUX_PAD(0x6B4, 0x324, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__I2C3_SDA		IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, 0)
-#define _MX53_PAD_GPIO_6__CCM_CCM_OUT_0	IOMUX_PAD(0x6B4, 0x324, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__CSU_CSU_INT_DEB	IOMUX_PAD(0x6B4, 0x324, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__ESDHC2_LCTL	IOMUX_PAD(0x6B4, 0x324, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__MLB_MLBSIG		IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, 0)
-#define _MX53_PAD_GPIO_2__ESAI1_FST		IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, 0)
-#define _MX53_PAD_GPIO_2__GPIO1_2		IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__KPP_ROW_6		IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, 0)
-#define _MX53_PAD_GPIO_2__CCM_CCM_OUT_1	IOMUX_PAD(0x6B8, 0x328, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0	IOMUX_PAD(0x6B8, 0x328, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__ESDHC2_WP		IOMUX_PAD(0x6B8, 0x328, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__MLB_MLBDAT	IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, 0)
-#define _MX53_PAD_GPIO_4__ESAI1_HCKT		IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, 0)
-#define _MX53_PAD_GPIO_4__GPIO1_4		IOMUX_PAD(0x6BC, 0x32C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__KPP_COL_7		IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, 0)
-#define _MX53_PAD_GPIO_4__CCM_CCM_OUT_2	IOMUX_PAD(0x6BC, 0x32C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1	IOMUX_PAD(0x6BC, 0x32C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__ESDHC2_CD		IOMUX_PAD(0x6BC, 0x32C, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__SCC_SEC_STATE	IOMUX_PAD(0x6BC, 0x32C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__ESAI1_TX2_RX3	IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, 0)
-#define _MX53_PAD_GPIO_5__GPIO1_5		IOMUX_PAD(0x6C0, 0x330, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__KPP_ROW_7		IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_CLKO		IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2	IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_PLL1_BYP	IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
-#define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1	IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
-#define _MX53_PAD_GPIO_7__GPIO1_7		IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__EPIT1_EPITO	IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CAN1_TXCAN	IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__FIRI_RXD		IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
-#define _MX53_PAD_GPIO_7__SPDIF_PLOCK	IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CCM_PLL2_BYP	IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
-#define _MX53_PAD_GPIO_8__ESAI1_TX5_RX0	IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, 0)
-#define _MX53_PAD_GPIO_8__GPIO1_8		IOMUX_PAD(0x6C8, 0x338, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__EPIT2_EPITO	IOMUX_PAD(0x6C8, 0x338, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CAN1_RXCAN	IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, 0)
-#define _MX53_PAD_GPIO_8__UART2_RXD_MUX	IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, 0)
-#define _MX53_PAD_GPIO_8__FIRI_TXD		IOMUX_PAD(0x6C8, 0x338, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__SPDIF_SRCLK	IOMUX_PAD(0x6C8, 0x338, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CCM_PLL3_BYP	IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, 0)
-#define _MX53_PAD_GPIO_16__ESAI1_TX3_RX2	IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, 0)
-#define _MX53_PAD_GPIO_16__GPIO7_11		IOMUX_PAD(0x6CC, 0x33C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT	IOMUX_PAD(0x6CC, 0x33C, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1	IOMUX_PAD(0x6CC, 0x33C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__SPDIF_IN1		IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, 0)
-#define _MX53_PAD_GPIO_16__I2C3_SDA		IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, 0)
-#define _MX53_PAD_GPIO_16__SJC_DE_B		IOMUX_PAD(0x6CC, 0x33C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__ESAI1_TX0		IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, 0)
-#define _MX53_PAD_GPIO_17__GPIO7_12		IOMUX_PAD(0x6D0, 0x340, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0	IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, 0)
-#define _MX53_PAD_GPIO_17__GPC_PMIC_RDY	IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, 0)
-#define _MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG	IOMUX_PAD(0x6D0, 0x340, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SPDIF_OUT1	IOMUX_PAD(0x6D0, 0x340, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__IPU_SNOOP2	IOMUX_PAD(0x6D0, 0x340, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SJC_JTAG_ACT	IOMUX_PAD(0x6D0, 0x340, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__ESAI1_TX1		IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, 0)
-#define _MX53_PAD_GPIO_18__GPIO7_13		IOMUX_PAD(0x6D4, 0x344, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1	IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, 0)
-#define _MX53_PAD_GPIO_18__OWIRE_LINE	IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, 0)
-#define _MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, 0)
-#define _MX53_PAD_GPIO_18__ESDHC1_LCTL	IOMUX_PAD(0x6D4, 0x344, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SRC_SYSTEM_RST	IOMUX_PAD(0x6D4, 0x344, 7, 0x0, 0, 0)
 
-#define MX53_PAD_GPIO_19__KPP_COL_5		(_MX53_PAD_GPIO_19__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__GPIO4_5		(_MX53_PAD_GPIO_19__GPIO4_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__CCM_CLKO		(_MX53_PAD_GPIO_19__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SPDIF_OUT1		(_MX53_PAD_GPIO_19__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		(_MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__ECSPI1_RDY		(_MX53_PAD_GPIO_19__ECSPI1_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__FEC_TDATA_3		(_MX53_PAD_GPIO_19__FEC_TDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SRC_INT_BOOT		(_MX53_PAD_GPIO_19__SRC_INT_BOOT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__KPP_COL_0		(_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__GPIO4_6		(_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		(_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__ECSPI1_SCLK		(_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__FEC_RDATA_3		(_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		(_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__KPP_ROW_0		(_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__GPIO4_7		(_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		(_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI		(_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__FEC_TX_ER		(_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__KPP_COL_1		(_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__GPIO4_8		(_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		(_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__ECSPI1_MISO		(_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__FEC_RX_CLK		(_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		(_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__KPP_ROW_1		(_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__GPIO4_9		(_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		(_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__ECSPI1_SS0		(_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__FEC_COL		(_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		(_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__KPP_COL_2		(_MX53_PAD_KEY_COL2__KPP_COL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__GPIO4_10		(_MX53_PAD_KEY_COL2__GPIO4_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__CAN1_TXCAN		(_MX53_PAD_KEY_COL2__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_MDIO		(_MX53_PAD_KEY_COL2__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__ECSPI1_SS1		(_MX53_PAD_KEY_COL2__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_RDATA_2		(_MX53_PAD_KEY_COL2__FEC_RDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		(_MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__KPP_ROW_2		(_MX53_PAD_KEY_ROW2__KPP_ROW_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__GPIO4_11		(_MX53_PAD_KEY_ROW2__GPIO4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__CAN1_RXCAN		(_MX53_PAD_KEY_ROW2__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_MDC		(_MX53_PAD_KEY_ROW2__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__ECSPI1_SS2		(_MX53_PAD_KEY_ROW2__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_TDATA_2		(_MX53_PAD_KEY_ROW2__FEC_TDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		(_MX53_PAD_KEY_ROW2__USBPHY1_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__KPP_COL_3		(_MX53_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__GPIO4_12		(_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBOH3_H2_DP		(_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__SPDIF_IN1		(_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__I2C2_SCL		(_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_COL3__ECSPI1_SS3		(_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__FEC_CRS		(_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		(_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__KPP_ROW_3		(_MX53_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__GPIO4_13		(_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM		(_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		(_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__I2C2_SDA		(_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		(_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP		(_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		(_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__KPP_COL_4		(_MX53_PAD_KEY_COL4__KPP_COL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__GPIO4_14		(_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__CAN2_TXCAN		(_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__IPU_SISG_4		(_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		(_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		(_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__KPP_ROW_4		(_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__GPIO4_15		(_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__CAN2_RXCAN		(_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__IPU_SISG_5		(_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		(_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		(_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		(_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__GPIO4_16		(_MX53_PAD_DI0_DISP_CLK__GPIO4_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		(_MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		(_MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		(_MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		(_MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		(_MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__GPIO4_17		(_MX53_PAD_DI0_PIN15__GPIO4_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		(_MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		(_MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		(_MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		(_MX53_PAD_DI0_PIN15__USBPHY1_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		(_MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__GPIO4_18		(_MX53_PAD_DI0_PIN2__GPIO4_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		(_MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		(_MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		(_MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		(_MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		(_MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__GPIO4_19		(_MX53_PAD_DI0_PIN3__GPIO4_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		(_MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		(_MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		(_MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		(_MX53_PAD_DI0_PIN3__USBPHY1_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		(_MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__GPIO4_20		(_MX53_PAD_DI0_PIN4__GPIO4_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		(_MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__ESDHC1_WP		(_MX53_PAD_DI0_PIN4__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		(_MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		(_MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		(_MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		(_MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__GPIO4_21		(_MX53_PAD_DISP0_DAT0__GPIO4_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__CSPI_SCLK		(_MX53_PAD_DISP0_DAT0__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		(_MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		(_MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		(_MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		(_MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		(_MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__GPIO4_22		(_MX53_PAD_DISP0_DAT1__GPIO4_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__CSPI_MOSI		(_MX53_PAD_DISP0_DAT1__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		(_MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL		(_MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		(_MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		(_MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		(_MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__GPIO4_23		(_MX53_PAD_DISP0_DAT2__GPIO4_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__CSPI_MISO		(_MX53_PAD_DISP0_DAT2__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		(_MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		(_MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		(_MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		(_MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		(_MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__GPIO4_24		(_MX53_PAD_DISP0_DAT3__GPIO4_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__CSPI_SS0		(_MX53_PAD_DISP0_DAT3__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		(_MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		(_MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		(_MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		(_MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		(_MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__GPIO4_25		(_MX53_PAD_DISP0_DAT4__GPIO4_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__CSPI_SS1		(_MX53_PAD_DISP0_DAT4__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		(_MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		(_MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		(_MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		(_MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		(_MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__GPIO4_26		(_MX53_PAD_DISP0_DAT5__GPIO4_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__CSPI_SS2		(_MX53_PAD_DISP0_DAT5__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		(_MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		(_MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		(_MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		(_MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		(_MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__GPIO4_27		(_MX53_PAD_DISP0_DAT6__GPIO4_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__CSPI_SS3		(_MX53_PAD_DISP0_DAT6__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		(_MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		(_MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		(_MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		(_MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		(_MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__GPIO4_28		(_MX53_PAD_DISP0_DAT7__GPIO4_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__CSPI_RDY		(_MX53_PAD_DISP0_DAT7__CSPI_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		(_MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		(_MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		(_MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		(_MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		(_MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__GPIO4_29		(_MX53_PAD_DISP0_DAT8__GPIO4_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__PWM1_PWMO		(_MX53_PAD_DISP0_DAT8__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		(_MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		(_MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		(_MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		(_MX53_PAD_DISP0_DAT8__USBPHY2_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		(_MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__GPIO4_30		(_MX53_PAD_DISP0_DAT9__GPIO4_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__PWM2_PWMO		(_MX53_PAD_DISP0_DAT9__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		(_MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		(_MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		(_MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		(_MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		(_MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__GPIO4_31		(_MX53_PAD_DISP0_DAT10__GPIO4_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		(_MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3		(_MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		(_MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		(_MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		(_MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__GPIO5_5		(_MX53_PAD_DISP0_DAT11__GPIO5_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		(_MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4		(_MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		(_MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		(_MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		(_MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__GPIO5_6		(_MX53_PAD_DISP0_DAT12__GPIO5_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		(_MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5		(_MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		(_MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		(_MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		(_MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__GPIO5_7		(_MX53_PAD_DISP0_DAT13__GPIO5_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		(_MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0		(_MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		(_MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		(_MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		(_MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__GPIO5_8		(_MX53_PAD_DISP0_DAT14__GPIO5_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		(_MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1		(_MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		(_MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		(_MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		(_MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__GPIO5_9		(_MX53_PAD_DISP0_DAT15__GPIO5_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2		(_MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		(_MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		(_MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		(_MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__GPIO5_10		(_MX53_PAD_DISP0_DAT16__GPIO5_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		(_MX53_PAD_DISP0_DAT16__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		(_MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		(_MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3		(_MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		(_MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		(_MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		(_MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__GPIO5_11		(_MX53_PAD_DISP0_DAT17__GPIO5_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		(_MX53_PAD_DISP0_DAT17__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		(_MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		(_MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4		(_MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		(_MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		(_MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__GPIO5_12		(_MX53_PAD_DISP0_DAT18__GPIO5_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		(_MX53_PAD_DISP0_DAT18__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5		(_MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		(_MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		(_MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		(_MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__GPIO5_13		(_MX53_PAD_DISP0_DAT19__GPIO5_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		(_MX53_PAD_DISP0_DAT19__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6		(_MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		(_MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		(_MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		(_MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__GPIO5_14		(_MX53_PAD_DISP0_DAT20__GPIO5_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		(_MX53_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		(_MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7		(_MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		(_MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		(_MX53_PAD_DISP0_DAT20__SATA_PHY_TDI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		(_MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__GPIO5_15		(_MX53_PAD_DISP0_DAT21__GPIO5_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		(_MX53_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		(_MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		(_MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		(_MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		(_MX53_PAD_DISP0_DAT21__SATA_PHY_TDO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		(_MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__GPIO5_16		(_MX53_PAD_DISP0_DAT22__GPIO5_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		(_MX53_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		(_MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		(_MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		(_MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		(_MX53_PAD_DISP0_DAT22__SATA_PHY_TCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		(_MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__GPIO5_17		(_MX53_PAD_DISP0_DAT23__GPIO5_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		(_MX53_PAD_DISP0_DAT23__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		(_MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		(_MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		(_MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		(_MX53_PAD_DISP0_DAT23__SATA_PHY_TMS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		(_MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__GPIO5_18		(_MX53_PAD_CSI0_PIXCLK__GPIO5_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		(_MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		(_MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		(_MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__GPIO5_19		(_MX53_PAD_CSI0_MCLK__GPIO5_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		(_MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		(_MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		(_MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL		(_MX53_PAD_CSI0_MCLK__TPIU_TRCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		(_MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__GPIO5_20		(_MX53_PAD_CSI0_DATA_EN__GPIO5_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		(_MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		(_MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		(_MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		(_MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__GPIO5_21		(_MX53_PAD_CSI0_VSYNC__GPIO5_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		(_MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		(_MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		(_MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		(_MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__GPIO5_22		(_MX53_PAD_CSI0_DAT4__GPIO5_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__KPP_COL_5		(_MX53_PAD_CSI0_DAT4__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		(_MX53_PAD_CSI0_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		(_MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		(_MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		(_MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		(_MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		(_MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__GPIO5_23		(_MX53_PAD_CSI0_DAT5__GPIO5_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__KPP_ROW_5		(_MX53_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		(_MX53_PAD_CSI0_DAT5__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		(_MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		(_MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		(_MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		(_MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		(_MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__GPIO5_24		(_MX53_PAD_CSI0_DAT6__GPIO5_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__KPP_COL_6		(_MX53_PAD_CSI0_DAT6__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO		(_MX53_PAD_CSI0_DAT6__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		(_MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		(_MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		(_MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		(_MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		(_MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__GPIO5_25		(_MX53_PAD_CSI0_DAT7__GPIO5_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__KPP_ROW_6		(_MX53_PAD_CSI0_DAT7__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0		(_MX53_PAD_CSI0_DAT7__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		(_MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		(_MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		(_MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		(_MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		(_MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__GPIO5_26		(_MX53_PAD_CSI0_DAT8__GPIO5_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__KPP_COL_7		(_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		(_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		(_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__I2C1_SDA		(_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		(_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		(_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		(_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__GPIO5_27		(_MX53_PAD_CSI0_DAT9__GPIO5_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__KPP_ROW_7		(_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		(_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		(_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__I2C1_SCL		(_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		(_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		(_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		(_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__GPIO5_28		(_MX53_PAD_CSI0_DAT10__GPIO5_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		(_MX53_PAD_CSI0_DAT10__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		(_MX53_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		(_MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		(_MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		(_MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		(_MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		(_MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__GPIO5_29		(_MX53_PAD_CSI0_DAT11__GPIO5_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		(_MX53_PAD_CSI0_DAT11__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0		(_MX53_PAD_CSI0_DAT11__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		(_MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		(_MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		(_MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		(_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		(_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__GPIO5_30		(_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		(_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		(_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		(_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		(_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		(_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__GPIO5_31		(_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		(_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		(_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		(_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		(_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		(_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__GPIO6_0		(_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		(_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		(_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		(_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		(_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		(_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__GPIO6_1		(_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		(_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		(_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		(_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		(_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		(_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__GPIO6_2		(_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		(_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		(_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		(_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		(_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		(_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__GPIO6_3		(_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		(_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		(_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		(_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		(_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		(_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__GPIO6_4		(_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		(_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		(_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		(_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		(_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		(_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__GPIO6_5		(_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		(_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		(_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		(_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		(_MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__EMI_WEIM_A_25		(_MX53_PAD_EIM_A25__EMI_WEIM_A_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__GPIO5_2		(_MX53_PAD_EIM_A25__GPIO5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__ECSPI2_RDY		(_MX53_PAD_EIM_A25__ECSPI2_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI1_PIN12		(_MX53_PAD_EIM_A25__IPU_DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__CSPI_SS1		(_MX53_PAD_EIM_A25__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS		(_MX53_PAD_EIM_A25__IPU_DI0_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		(_MX53_PAD_EIM_A25__USBPHY1_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		(_MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__GPIO2_30		(_MX53_PAD_EIM_EB2__GPIO2_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		(_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__ECSPI1_SS0		(_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__I2C2_SCL		(_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D16__EMI_WEIM_D_16		(_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__GPIO3_16		(_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DI0_PIN5		(_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		(_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__ECSPI1_SCLK		(_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__I2C2_SDA		(_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D17__EMI_WEIM_D_17		(_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__GPIO3_17		(_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DI0_PIN6		(_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		(_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__ECSPI1_MISO		(_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__I2C3_SCL		(_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__EMI_WEIM_D_18		(_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__GPIO3_18		(_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DI0_PIN7		(_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		(_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__ECSPI1_MOSI		(_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__I2C3_SDA		(_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS		(_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EMI_WEIM_D_19		(_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__GPIO3_19		(_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DI0_PIN8		(_MX53_PAD_EIM_D19__IPU_DI0_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		(_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__ECSPI1_SS1		(_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EPIT1_EPITO		(_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EMI_WEIM_D_20		(_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__GPIO3_20		(_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_DI0_PIN16		(_MX53_PAD_EIM_D20__IPU_DI0_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		(_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__CSPI_SS0		(_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EPIT2_EPITO		(_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__EMI_WEIM_D_21		(_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__GPIO3_21		(_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DI0_PIN17		(_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		(_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__CSPI_SCLK		(_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__I2C1_SCL		(_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		(_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__EMI_WEIM_D_22		(_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__GPIO3_22		(_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DI0_PIN1		(_MX53_PAD_EIM_D22__IPU_DI0_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		(_MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__CSPI_MISO		(_MX53_PAD_EIM_D22__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		(_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__EMI_WEIM_D_23		(_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__GPIO3_23		(_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART1_DCD		(_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS		(_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN2		(_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN14		(_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		(_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__GPIO2_31		(_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART1_RI		(_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__EMI_WEIM_D_24		(_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__GPIO3_24		(_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI1_SS2		(_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__CSPI_SS2		(_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		(_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI2_SS2		(_MX53_PAD_EIM_D24__ECSPI2_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART1_DTR		(_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__EMI_WEIM_D_25		(_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__GPIO3_25		(_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI1_SS3		(_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__CSPI_SS3		(_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		(_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI2_SS3		(_MX53_PAD_EIM_D25__ECSPI2_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART1_DSR		(_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__EMI_WEIM_D_26		(_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__GPIO3_26		(_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D26__FIRI_RXD		(_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_CSI0_D_1		(_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DI1_PIN11		(_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_SISG_2		(_MX53_PAD_EIM_D26__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		(_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__EMI_WEIM_D_27		(_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__GPIO3_27		(_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D27__FIRI_TXD		(_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_CSI0_D_0		(_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DI1_PIN13		(_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_SISG_3		(_MX53_PAD_EIM_D27__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		(_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__EMI_WEIM_D_28		(_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__GPIO3_28		(_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		(_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__CSPI_MOSI		(_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__I2C1_SDA		(_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D28__IPU_EXT_TRIG		(_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DI0_PIN13		(_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__EMI_WEIM_D_29		(_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__GPIO3_29		(_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		(_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__CSPI_SS0		(_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI1_PIN15		(_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_D29__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI0_PIN14		(_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__EMI_WEIM_D_30		(_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__GPIO3_30		(_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_CSI0_D_3		(_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DI0_PIN11		(_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		(_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__EMI_WEIM_D_31		(_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__GPIO3_31		(_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_CSI0_D_2		(_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DI0_PIN12		(_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		(_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__EMI_WEIM_A_24		(_MX53_PAD_EIM_A24__EMI_WEIM_A_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__GPIO5_4		(_MX53_PAD_EIM_A24__GPIO5_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		(_MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_CSI1_D_19		(_MX53_PAD_EIM_A24__IPU_CSI1_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_SISG_2		(_MX53_PAD_EIM_A24__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__USBPHY2_BVALID		(_MX53_PAD_EIM_A24__USBPHY2_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__EMI_WEIM_A_23		(_MX53_PAD_EIM_A23__EMI_WEIM_A_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__GPIO6_6		(_MX53_PAD_EIM_A23__GPIO6_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		(_MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_CSI1_D_18		(_MX53_PAD_EIM_A23__IPU_CSI1_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_SISG_3		(_MX53_PAD_EIM_A23__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		(_MX53_PAD_EIM_A23__USBPHY2_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__EMI_WEIM_A_22		(_MX53_PAD_EIM_A22__EMI_WEIM_A_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__GPIO2_16		(_MX53_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		(_MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_CSI1_D_17		(_MX53_PAD_EIM_A22__IPU_CSI1_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7		(_MX53_PAD_EIM_A22__SRC_BT_CFG1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__EMI_WEIM_A_21		(_MX53_PAD_EIM_A21__EMI_WEIM_A_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__GPIO2_17		(_MX53_PAD_EIM_A21__GPIO2_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		(_MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_CSI1_D_16		(_MX53_PAD_EIM_A21__IPU_CSI1_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6		(_MX53_PAD_EIM_A21__SRC_BT_CFG1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__EMI_WEIM_A_20		(_MX53_PAD_EIM_A20__EMI_WEIM_A_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__GPIO2_18		(_MX53_PAD_EIM_A20__GPIO2_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		(_MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_CSI1_D_15		(_MX53_PAD_EIM_A20__IPU_CSI1_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5		(_MX53_PAD_EIM_A20__SRC_BT_CFG1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__EMI_WEIM_A_19		(_MX53_PAD_EIM_A19__EMI_WEIM_A_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__GPIO2_19		(_MX53_PAD_EIM_A19__GPIO2_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		(_MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_CSI1_D_14		(_MX53_PAD_EIM_A19__IPU_CSI1_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4		(_MX53_PAD_EIM_A19__SRC_BT_CFG1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__EMI_WEIM_A_18		(_MX53_PAD_EIM_A18__EMI_WEIM_A_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__GPIO2_20		(_MX53_PAD_EIM_A18__GPIO2_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		(_MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_CSI1_D_13		(_MX53_PAD_EIM_A18__IPU_CSI1_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3		(_MX53_PAD_EIM_A18__SRC_BT_CFG1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__EMI_WEIM_A_17		(_MX53_PAD_EIM_A17__EMI_WEIM_A_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__GPIO2_21		(_MX53_PAD_EIM_A17__GPIO2_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		(_MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_CSI1_D_12		(_MX53_PAD_EIM_A17__IPU_CSI1_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2		(_MX53_PAD_EIM_A17__SRC_BT_CFG1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__EMI_WEIM_A_16		(_MX53_PAD_EIM_A16__EMI_WEIM_A_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__GPIO2_22		(_MX53_PAD_EIM_A16__GPIO2_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		(_MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		(_MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1		(_MX53_PAD_EIM_A16__SRC_BT_CFG1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		(_MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__GPIO2_23		(_MX53_PAD_EIM_CS0__GPIO2_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__ECSPI2_SCLK		(_MX53_PAD_EIM_CS0__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5		(_MX53_PAD_EIM_CS0__IPU_DI1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		(_MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__GPIO2_24		(_MX53_PAD_EIM_CS1__GPIO2_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__ECSPI2_MOSI		(_MX53_PAD_EIM_CS1__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6		(_MX53_PAD_EIM_CS1__IPU_DI1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__EMI_WEIM_OE		(_MX53_PAD_EIM_OE__EMI_WEIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__GPIO2_25		(_MX53_PAD_EIM_OE__GPIO2_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__ECSPI2_MISO		(_MX53_PAD_EIM_OE__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__IPU_DI1_PIN7		(_MX53_PAD_EIM_OE__IPU_DI1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__USBPHY2_IDDIG		(_MX53_PAD_EIM_OE__USBPHY2_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__EMI_WEIM_RW		(_MX53_PAD_EIM_RW__EMI_WEIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__GPIO2_26		(_MX53_PAD_EIM_RW__GPIO2_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__ECSPI2_SS0		(_MX53_PAD_EIM_RW__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__IPU_DI1_PIN8		(_MX53_PAD_EIM_RW__IPU_DI1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		(_MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA		(_MX53_PAD_EIM_LBA__EMI_WEIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__GPIO2_27		(_MX53_PAD_EIM_LBA__GPIO2_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__ECSPI2_SS1		(_MX53_PAD_EIM_LBA__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17		(_MX53_PAD_EIM_LBA__IPU_DI1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		(_MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		(_MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPIO2_28		(_MX53_PAD_EIM_EB0__GPIO2_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		(_MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11		(_MX53_PAD_EIM_EB0__IPU_CSI1_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY		(_MX53_PAD_EIM_EB0__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		(_MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		(_MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__GPIO2_29		(_MX53_PAD_EIM_EB1__GPIO2_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		(_MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10		(_MX53_PAD_EIM_EB1__IPU_CSI1_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		(_MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		(_MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__GPIO3_0		(_MX53_PAD_EIM_DA0__GPIO3_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		(_MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9		(_MX53_PAD_EIM_DA0__IPU_CSI1_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		(_MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		(_MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__GPIO3_1		(_MX53_PAD_EIM_DA1__GPIO3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		(_MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8		(_MX53_PAD_EIM_DA1__IPU_CSI1_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		(_MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		(_MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__GPIO3_2		(_MX53_PAD_EIM_DA2__GPIO3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		(_MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7		(_MX53_PAD_EIM_DA2__IPU_CSI1_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		(_MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		(_MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__GPIO3_3		(_MX53_PAD_EIM_DA3__GPIO3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		(_MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6		(_MX53_PAD_EIM_DA3__IPU_CSI1_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		(_MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		(_MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__GPIO3_4		(_MX53_PAD_EIM_DA4__GPIO3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		(_MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5		(_MX53_PAD_EIM_DA4__IPU_CSI1_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		(_MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		(_MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__GPIO3_5		(_MX53_PAD_EIM_DA5__GPIO3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		(_MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4		(_MX53_PAD_EIM_DA5__IPU_CSI1_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		(_MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		(_MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__GPIO3_6		(_MX53_PAD_EIM_DA6__GPIO3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		(_MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3		(_MX53_PAD_EIM_DA6__IPU_CSI1_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		(_MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		(_MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__GPIO3_7		(_MX53_PAD_EIM_DA7__GPIO3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		(_MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2		(_MX53_PAD_EIM_DA7__IPU_CSI1_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		(_MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		(_MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__GPIO3_8		(_MX53_PAD_EIM_DA8__GPIO3_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		(_MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1		(_MX53_PAD_EIM_DA8__IPU_CSI1_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		(_MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		(_MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__GPIO3_9		(_MX53_PAD_EIM_DA9__GPIO3_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		(_MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0		(_MX53_PAD_EIM_DA9__IPU_CSI1_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		(_MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		(_MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__GPIO3_10		(_MX53_PAD_EIM_DA10__GPIO3_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		(_MX53_PAD_EIM_DA10__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		(_MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		(_MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__GPIO3_11		(_MX53_PAD_EIM_DA11__GPIO3_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2		(_MX53_PAD_EIM_DA11__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		(_MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__GPIO3_12		(_MX53_PAD_EIM_DA12__GPIO3_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3		(_MX53_PAD_EIM_DA12__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		(_MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__GPIO3_13		(_MX53_PAD_EIM_DA13__GPIO3_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		(_MX53_PAD_EIM_DA13__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		(_MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__GPIO3_14		(_MX53_PAD_EIM_DA14__GPIO3_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		(_MX53_PAD_EIM_DA14__IPU_DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		(_MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		(_MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__GPIO3_15		(_MX53_PAD_EIM_DA15__GPIO3_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		(_MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__GPIO6_12		(_MX53_PAD_NANDF_WE_B__GPIO6_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		(_MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__GPIO6_13		(_MX53_PAD_NANDF_RE_B__GPIO6_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		(_MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__GPIO5_0		(_MX53_PAD_EIM_WAIT__GPIO5_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		(_MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__GPIO6_22		(_MX53_PAD_LVDS1_TX3_P__GPIO6_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		(_MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__GPIO6_24		(_MX53_PAD_LVDS1_TX2_P__GPIO6_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		(_MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__GPIO6_26		(_MX53_PAD_LVDS1_CLK_P__GPIO6_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		(_MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__GPIO6_28		(_MX53_PAD_LVDS1_TX1_P__GPIO6_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		(_MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__GPIO6_30		(_MX53_PAD_LVDS1_TX0_P__GPIO6_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		(_MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__GPIO7_22		(_MX53_PAD_LVDS0_TX3_P__GPIO7_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		(_MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__GPIO7_24		(_MX53_PAD_LVDS0_CLK_P__GPIO7_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		(_MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__GPIO7_26		(_MX53_PAD_LVDS0_TX2_P__GPIO7_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		(_MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__GPIO7_28		(_MX53_PAD_LVDS0_TX1_P__GPIO7_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		(_MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__GPIO7_30		(_MX53_PAD_LVDS0_TX0_P__GPIO7_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		(_MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__GPIO4_0		(_MX53_PAD_GPIO_10__GPIO4_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		(_MX53_PAD_GPIO_10__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_11__GPIO4_1		(_MX53_PAD_GPIO_11__GPIO4_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_12__GPIO4_2		(_MX53_PAD_GPIO_12__GPIO4_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_13__GPIO4_3		(_MX53_PAD_GPIO_13__GPIO4_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_14__GPIO4_4		(_MX53_PAD_GPIO_14__GPIO4_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		(_MX53_PAD_NANDF_CLE__EMI_NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__GPIO6_7		(_MX53_PAD_NANDF_CLE__GPIO6_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		(_MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		(_MX53_PAD_NANDF_ALE__EMI_NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__GPIO6_8		(_MX53_PAD_NANDF_ALE__GPIO6_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		(_MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		(_MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__GPIO6_9		(_MX53_PAD_NANDF_WP_B__GPIO6_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		(_MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		(_MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__GPIO6_10		(_MX53_PAD_NANDF_RB0__GPIO6_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		(_MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		(_MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__GPIO6_11		(_MX53_PAD_NANDF_CS0__GPIO6_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		(_MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		(_MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__GPIO6_14		(_MX53_PAD_NANDF_CS1__GPIO6_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__MLB_MLBCLK		(_MX53_PAD_NANDF_CS1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		(_MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		(_MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__GPIO6_15		(_MX53_PAD_NANDF_CS2__GPIO6_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__IPU_SISG_0		(_MX53_PAD_NANDF_CS2__IPU_SISG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__ESAI1_TX0		(_MX53_PAD_NANDF_CS2__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		(_MX53_PAD_NANDF_CS2__EMI_WEIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		(_MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__MLB_MLBSIG		(_MX53_PAD_NANDF_CS2__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		(_MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		(_MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__GPIO6_16		(_MX53_PAD_NANDF_CS3__GPIO6_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__IPU_SISG_1		(_MX53_PAD_NANDF_CS3__IPU_SISG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__ESAI1_TX1		(_MX53_PAD_NANDF_CS3__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		(_MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__MLB_MLBDAT		(_MX53_PAD_NANDF_CS3__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		(_MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_MDIO		(_MX53_PAD_FEC_MDIO__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__GPIO1_22		(_MX53_PAD_FEC_MDIO__GPIO1_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__ESAI1_SCKR		(_MX53_PAD_FEC_MDIO__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_COL		(_MX53_PAD_FEC_MDIO__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		(_MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		(_MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		(_MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		(_MX53_PAD_FEC_REF_CLK__FEC_TX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__GPIO1_23		(_MX53_PAD_FEC_REF_CLK__GPIO1_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR		(_MX53_PAD_FEC_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		(_MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		(_MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_ER		(_MX53_PAD_FEC_RX_ER__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__GPIO1_24		(_MX53_PAD_FEC_RX_ER__GPIO1_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR		(_MX53_PAD_FEC_RX_ER__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK		(_MX53_PAD_FEC_RX_ER__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		(_MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV		(_MX53_PAD_FEC_CRS_DV__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__GPIO1_25		(_MX53_PAD_FEC_CRS_DV__GPIO1_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		(_MX53_PAD_FEC_CRS_DV__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__FEC_RDATA_1		(_MX53_PAD_FEC_RXD1__FEC_RDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__GPIO1_26		(_MX53_PAD_FEC_RXD1__GPIO1_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__ESAI1_FST		(_MX53_PAD_FEC_RXD1__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__MLB_MLBSIG		(_MX53_PAD_FEC_RXD1__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		(_MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__FEC_RDATA_0		(_MX53_PAD_FEC_RXD0__FEC_RDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__GPIO1_27		(_MX53_PAD_FEC_RXD0__GPIO1_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__ESAI1_HCKT		(_MX53_PAD_FEC_RXD0__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		(_MX53_PAD_FEC_RXD0__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__FEC_TX_EN		(_MX53_PAD_FEC_TX_EN__FEC_TX_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__GPIO1_28		(_MX53_PAD_FEC_TX_EN__GPIO1_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		(_MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__FEC_TDATA_1		(_MX53_PAD_FEC_TXD1__FEC_TDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__GPIO1_29		(_MX53_PAD_FEC_TXD1__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		(_MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__MLB_MLBCLK		(_MX53_PAD_FEC_TXD1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		(_MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__FEC_TDATA_0		(_MX53_PAD_FEC_TXD0__FEC_TDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__GPIO1_30		(_MX53_PAD_FEC_TXD0__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		(_MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		(_MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__FEC_MDC		(_MX53_PAD_FEC_MDC__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__GPIO1_31		(_MX53_PAD_FEC_MDC__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		(_MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__MLB_MLBDAT		(_MX53_PAD_FEC_MDC__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		(_MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		(_MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__PATA_DIOW		(_MX53_PAD_PATA_DIOW__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__GPIO6_17		(_MX53_PAD_PATA_DIOW__GPIO6_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		(_MX53_PAD_PATA_DIOW__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		(_MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__PATA_DMACK		(_MX53_PAD_PATA_DMACK__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__GPIO6_18		(_MX53_PAD_PATA_DMACK__GPIO6_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		(_MX53_PAD_PATA_DMACK__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		(_MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__PATA_DMARQ		(_MX53_PAD_PATA_DMARQ__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__GPIO7_0		(_MX53_PAD_PATA_DMARQ__GPIO7_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		(_MX53_PAD_PATA_DMARQ__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		(_MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		(_MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		(_MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		(_MX53_PAD_PATA_BUFFER_EN__GPIO7_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		(_MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		(_MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		(_MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__PATA_INTRQ		(_MX53_PAD_PATA_INTRQ__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__GPIO7_2		(_MX53_PAD_PATA_INTRQ__GPIO7_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__UART2_CTS		(_MX53_PAD_PATA_INTRQ__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN		(_MX53_PAD_PATA_INTRQ__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		(_MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		(_MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__PATA_DIOR		(_MX53_PAD_PATA_DIOR__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__GPIO7_3		(_MX53_PAD_PATA_DIOR__GPIO7_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__UART2_RTS		(_MX53_PAD_PATA_DIOR__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__CAN1_RXCAN		(_MX53_PAD_PATA_DIOR__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		(_MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		(_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__GPIO7_4		(_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		(_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		(_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		(_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__PATA_IORDY		(_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__GPIO7_5		(_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__ESDHC3_CLK		(_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__CAN2_RXCAN		(_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		(_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__PATA_DA_0		(_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__GPIO7_6		(_MX53_PAD_PATA_DA_0__GPIO7_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__ESDHC3_RST		(_MX53_PAD_PATA_DA_0__ESDHC3_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__OWIRE_LINE		(_MX53_PAD_PATA_DA_0__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		(_MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__PATA_DA_1		(_MX53_PAD_PATA_DA_1__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__GPIO7_7		(_MX53_PAD_PATA_DA_1__GPIO7_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__ESDHC4_CMD		(_MX53_PAD_PATA_DA_1__ESDHC4_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__UART3_CTS		(_MX53_PAD_PATA_DA_1__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		(_MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__PATA_DA_2		(_MX53_PAD_PATA_DA_2__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__GPIO7_8		(_MX53_PAD_PATA_DA_2__GPIO7_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__ESDHC4_CLK		(_MX53_PAD_PATA_DA_2__ESDHC4_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__UART3_RTS		(_MX53_PAD_PATA_DA_2__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		(_MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__PATA_CS_0		(_MX53_PAD_PATA_CS_0__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__GPIO7_9		(_MX53_PAD_PATA_CS_0__GPIO7_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		(_MX53_PAD_PATA_CS_0__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		(_MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__PATA_CS_1		(_MX53_PAD_PATA_CS_1__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__GPIO7_10		(_MX53_PAD_PATA_CS_1__GPIO7_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		(_MX53_PAD_PATA_CS_1__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		(_MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__PATA_DATA_0		(_MX53_PAD_PATA_DATA0__PATA_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPIO2_0		(_MX53_PAD_PATA_DATA0__GPIO2_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		(_MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		(_MX53_PAD_PATA_DATA0__ESDHC3_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		(_MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		(_MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		(_MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__PATA_DATA_1		(_MX53_PAD_PATA_DATA1__PATA_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPIO2_1		(_MX53_PAD_PATA_DATA1__GPIO2_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		(_MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		(_MX53_PAD_PATA_DATA1__ESDHC3_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		(_MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		(_MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__PATA_DATA_2		(_MX53_PAD_PATA_DATA2__PATA_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPIO2_2		(_MX53_PAD_PATA_DATA2__GPIO2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		(_MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		(_MX53_PAD_PATA_DATA2__ESDHC3_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		(_MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		(_MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__PATA_DATA_3		(_MX53_PAD_PATA_DATA3__PATA_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPIO2_3		(_MX53_PAD_PATA_DATA3__GPIO2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		(_MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		(_MX53_PAD_PATA_DATA3__ESDHC3_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		(_MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		(_MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__PATA_DATA_4		(_MX53_PAD_PATA_DATA4__PATA_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPIO2_4		(_MX53_PAD_PATA_DATA4__GPIO2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		(_MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		(_MX53_PAD_PATA_DATA4__ESDHC4_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		(_MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		(_MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__PATA_DATA_5		(_MX53_PAD_PATA_DATA5__PATA_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPIO2_5		(_MX53_PAD_PATA_DATA5__GPIO2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		(_MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		(_MX53_PAD_PATA_DATA5__ESDHC4_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		(_MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		(_MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__PATA_DATA_6		(_MX53_PAD_PATA_DATA6__PATA_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPIO2_6		(_MX53_PAD_PATA_DATA6__GPIO2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		(_MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		(_MX53_PAD_PATA_DATA6__ESDHC4_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		(_MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		(_MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__PATA_DATA_7		(_MX53_PAD_PATA_DATA7__PATA_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPIO2_7		(_MX53_PAD_PATA_DATA7__GPIO2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		(_MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		(_MX53_PAD_PATA_DATA7__ESDHC4_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		(_MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		(_MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__PATA_DATA_8		(_MX53_PAD_PATA_DATA8__PATA_DATA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPIO2_8		(_MX53_PAD_PATA_DATA8__GPIO2_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		(_MX53_PAD_PATA_DATA8__ESDHC1_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		(_MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		(_MX53_PAD_PATA_DATA8__ESDHC3_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		(_MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		(_MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__PATA_DATA_9		(_MX53_PAD_PATA_DATA9__PATA_DATA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPIO2_9		(_MX53_PAD_PATA_DATA9__GPIO2_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		(_MX53_PAD_PATA_DATA9__ESDHC1_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		(_MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		(_MX53_PAD_PATA_DATA9__ESDHC3_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		(_MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		(_MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__PATA_DATA_10		(_MX53_PAD_PATA_DATA10__PATA_DATA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPIO2_10		(_MX53_PAD_PATA_DATA10__GPIO2_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		(_MX53_PAD_PATA_DATA10__ESDHC1_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		(_MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		(_MX53_PAD_PATA_DATA10__ESDHC3_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		(_MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		(_MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__PATA_DATA_11		(_MX53_PAD_PATA_DATA11__PATA_DATA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPIO2_11		(_MX53_PAD_PATA_DATA11__GPIO2_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		(_MX53_PAD_PATA_DATA11__ESDHC1_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		(_MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		(_MX53_PAD_PATA_DATA11__ESDHC3_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		(_MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		(_MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__PATA_DATA_12		(_MX53_PAD_PATA_DATA12__PATA_DATA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPIO2_12		(_MX53_PAD_PATA_DATA12__GPIO2_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		(_MX53_PAD_PATA_DATA12__ESDHC2_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		(_MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		(_MX53_PAD_PATA_DATA12__ESDHC4_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		(_MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		(_MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__PATA_DATA_13		(_MX53_PAD_PATA_DATA13__PATA_DATA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPIO2_13		(_MX53_PAD_PATA_DATA13__GPIO2_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		(_MX53_PAD_PATA_DATA13__ESDHC2_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		(_MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		(_MX53_PAD_PATA_DATA13__ESDHC4_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		(_MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		(_MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__PATA_DATA_14		(_MX53_PAD_PATA_DATA14__PATA_DATA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPIO2_14		(_MX53_PAD_PATA_DATA14__GPIO2_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		(_MX53_PAD_PATA_DATA14__ESDHC2_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		(_MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		(_MX53_PAD_PATA_DATA14__ESDHC4_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		(_MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		(_MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__PATA_DATA_15		(_MX53_PAD_PATA_DATA15__PATA_DATA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPIO2_15		(_MX53_PAD_PATA_DATA15__GPIO2_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		(_MX53_PAD_PATA_DATA15__ESDHC2_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		(_MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		(_MX53_PAD_PATA_DATA15__ESDHC4_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		(_MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		(_MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0		(_MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPIO1_16		(_MX53_PAD_SD1_DATA0__GPIO1_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPT_CAPIN1		(_MX53_PAD_SD1_DATA0__GPT_CAPIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CSPI_MISO		(_MX53_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		(_MX53_PAD_SD1_DATA0__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1		(_MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPIO1_17		(_MX53_PAD_SD1_DATA1__GPIO1_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPT_CAPIN2		(_MX53_PAD_SD1_DATA1__GPT_CAPIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CSPI_SS0		(_MX53_PAD_SD1_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		(_MX53_PAD_SD1_DATA1__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__ESDHC1_CMD		(_MX53_PAD_SD1_CMD__ESDHC1_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPIO1_18		(_MX53_PAD_SD1_CMD__GPIO1_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPT_CMPOUT1		(_MX53_PAD_SD1_CMD__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CSPI_MOSI		(_MX53_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP		(_MX53_PAD_SD1_CMD__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2		(_MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPIO1_19		(_MX53_PAD_SD1_DATA2__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2		(_MX53_PAD_SD1_DATA2__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__PWM2_PWMO		(_MX53_PAD_SD1_DATA2__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CSPI_SS1		(_MX53_PAD_SD1_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		(_MX53_PAD_SD1_DATA2__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__ESDHC1_CLK		(_MX53_PAD_SD1_CLK__ESDHC1_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPIO1_20		(_MX53_PAD_SD1_CLK__GPIO1_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		(_MX53_PAD_SD1_CLK__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPT_CLKIN		(_MX53_PAD_SD1_CLK__GPT_CLKIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__CSPI_SCLK		(_MX53_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		(_MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3		(_MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPIO1_21		(_MX53_PAD_SD1_DATA3__GPIO1_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3		(_MX53_PAD_SD1_DATA3__GPT_CMPOUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__PWM1_PWMO		(_MX53_PAD_SD1_DATA3__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__CSPI_SS2		(_MX53_PAD_SD1_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		(_MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__ESDHC2_CLK		(_MX53_PAD_SD2_CLK__ESDHC2_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__GPIO1_10		(_MX53_PAD_SD2_CLK__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__KPP_COL_5		(_MX53_PAD_SD2_CLK__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		(_MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__CSPI_SCLK		(_MX53_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__SCC_RANDOM_V		(_MX53_PAD_SD2_CLK__SCC_RANDOM_V | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__ESDHC2_CMD		(_MX53_PAD_SD2_CMD__ESDHC2_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__GPIO1_11		(_MX53_PAD_SD2_CMD__GPIO1_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__KPP_ROW_5		(_MX53_PAD_SD2_CMD__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		(_MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__CSPI_MOSI		(_MX53_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__SCC_RANDOM		(_MX53_PAD_SD2_CMD__SCC_RANDOM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3		(_MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__GPIO1_12		(_MX53_PAD_SD2_DATA3__GPIO1_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__KPP_COL_6		(_MX53_PAD_SD2_DATA3__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		(_MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__CSPI_SS2		(_MX53_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__SJC_DONE		(_MX53_PAD_SD2_DATA3__SJC_DONE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2		(_MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__GPIO1_13		(_MX53_PAD_SD2_DATA2__GPIO1_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__KPP_ROW_6		(_MX53_PAD_SD2_DATA2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		(_MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__CSPI_SS1		(_MX53_PAD_SD2_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__SJC_FAIL		(_MX53_PAD_SD2_DATA2__SJC_FAIL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1		(_MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__GPIO1_14		(_MX53_PAD_SD2_DATA1__GPIO1_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__KPP_COL_7		(_MX53_PAD_SD2_DATA1__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		(_MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__CSPI_SS0		(_MX53_PAD_SD2_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		(_MX53_PAD_SD2_DATA1__RTIC_SEC_VIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0		(_MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__GPIO1_15		(_MX53_PAD_SD2_DATA0__GPIO1_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__KPP_ROW_7		(_MX53_PAD_SD2_DATA0__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		(_MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__CSPI_MISO		(_MX53_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		(_MX53_PAD_SD2_DATA0__RTIC_DONE_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_CLKO		(_MX53_PAD_GPIO_0__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__GPIO1_0		(_MX53_PAD_GPIO_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__KPP_COL_5		(_MX53_PAD_GPIO_0__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		(_MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__EPIT1_EPITO		(_MX53_PAD_GPIO_0__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB		(_MX53_PAD_GPIO_0__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		(_MX53_PAD_GPIO_0__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CSU_TD		(_MX53_PAD_GPIO_0__CSU_TD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESAI1_SCKR		(_MX53_PAD_GPIO_1__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__GPIO1_1		(_MX53_PAD_GPIO_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__KPP_ROW_5		(_MX53_PAD_GPIO_1__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		(_MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__PWM2_PWMO		(_MX53_PAD_GPIO_1__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__WDOG2_WDOG_B		(_MX53_PAD_GPIO_1__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESDHC1_CD		(_MX53_PAD_GPIO_1__ESDHC1_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__SRC_TESTER_ACK		(_MX53_PAD_GPIO_1__SRC_TESTER_ACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESAI1_FSR		(_MX53_PAD_GPIO_9__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__GPIO1_9		(_MX53_PAD_GPIO_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__KPP_COL_6		(_MX53_PAD_GPIO_9__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__CCM_REF_EN_B		(_MX53_PAD_GPIO_9__CCM_REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__PWM1_PWMO		(_MX53_PAD_GPIO_9__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__WDOG1_WDOG_B		(_MX53_PAD_GPIO_9__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESDHC1_WP		(_MX53_PAD_GPIO_9__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__SCC_FAIL_STATE		(_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__ESAI1_HCKR		(_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__GPIO1_3		(_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__I2C3_SCL		(_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN		(_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__CCM_CLKO2		(_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		(_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		(_MX53_PAD_GPIO_3__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__MLB_MLBCLK		(_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESAI1_SCKT		(_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__GPIO1_6		(_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__I2C3_SDA		(_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0		(_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		(_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		(_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESDHC2_LCTL		(_MX53_PAD_GPIO_6__ESDHC2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__MLB_MLBSIG		(_MX53_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESAI1_FST		(_MX53_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__GPIO1_2		(_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__KPP_ROW_6		(_MX53_PAD_GPIO_2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1		(_MX53_PAD_GPIO_2__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		(_MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		(_MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESDHC2_WP		(_MX53_PAD_GPIO_2__ESDHC2_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__MLB_MLBDAT		(_MX53_PAD_GPIO_2__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESAI1_HCKT		(_MX53_PAD_GPIO_4__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__GPIO1_4		(_MX53_PAD_GPIO_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__KPP_COL_7		(_MX53_PAD_GPIO_4__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2		(_MX53_PAD_GPIO_4__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		(_MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		(_MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESDHC2_CD		(_MX53_PAD_GPIO_4__ESDHC2_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__SCC_SEC_STATE		(_MX53_PAD_GPIO_4__SCC_SEC_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3		(_MX53_PAD_GPIO_5__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__GPIO1_5		(_MX53_PAD_GPIO_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__KPP_ROW_7		(_MX53_PAD_GPIO_5__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CCM_CLKO		(_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		(_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		(_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__I2C3_SCL		(_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_5__CCM_PLL1_BYP		(_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1		(_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__GPIO1_7		(_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__EPIT1_EPITO		(_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CAN1_TXCAN		(_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_7__FIRI_RXD		(_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__SPDIF_PLOCK		(_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CCM_PLL2_BYP		(_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0		(_MX53_PAD_GPIO_8__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__GPIO1_8		(_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__EPIT2_EPITO		(_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CAN1_RXCAN		(_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_8__FIRI_TXD		(_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__SPDIF_SRCLK		(_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CCM_PLL3_BYP		(_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2		(_MX53_PAD_GPIO_16__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__GPIO7_11		(_MX53_PAD_GPIO_16__GPIO7_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		(_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		(_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__SPDIF_IN1		(_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__I2C3_SDA		(_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_16__SJC_DE_B		(_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__ESAI1_TX0		(_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPIO7_12		(_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		(_MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPC_PMIC_RDY		(_MX53_PAD_GPIO_17__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		(_MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SPDIF_OUT1		(_MX53_PAD_GPIO_17__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__IPU_SNOOP2		(_MX53_PAD_GPIO_17__IPU_SNOOP2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SJC_JTAG_ACT		(_MX53_PAD_GPIO_17__SJC_JTAG_ACT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESAI1_TX1		(_MX53_PAD_GPIO_18__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__GPIO7_13		(_MX53_PAD_GPIO_18__GPIO7_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		(_MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__OWIRE_LINE		(_MX53_PAD_GPIO_18__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		(_MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		(_MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESDHC1_LCTL		(_MX53_PAD_GPIO_18__ESDHC1_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		(_MX53_PAD_GPIO_18__SRC_SYSTEM_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__KPP_COL_5			IOMUX_PAD(0x348, 0x020, 0, 0x840, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__GPIO4_5			IOMUX_PAD(0x348, 0x020, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__CCM_CLKO			IOMUX_PAD(0x348, 0x020, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SPDIF_OUT1			IOMUX_PAD(0x348, 0x020, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		IOMUX_PAD(0x348, 0x020, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__ECSPI1_RDY			IOMUX_PAD(0x348, 0x020, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__FEC_TDATA_3			IOMUX_PAD(0x348, 0x020, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT			IOMUX_PAD(0x348, 0x020, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__KPP_COL_0			IOMUX_PAD(0x34C, 0x024, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__GPIO4_6			IOMUX_PAD(0x34C, 0x024, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		IOMUX_PAD(0x34C, 0x024, 2, 0x758, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		IOMUX_PAD(0x34C, 0x024, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK			IOMUX_PAD(0x34C, 0x024, 5, 0x79C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3			IOMUX_PAD(0x34C, 0x024, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		IOMUX_PAD(0x34C, 0x024, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0			IOMUX_PAD(0x350, 0x028, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__GPIO4_7			IOMUX_PAD(0x350, 0x028, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		IOMUX_PAD(0x350, 0x028, 2, 0x74C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		IOMUX_PAD(0x350, 0x028, 4, 0x890, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI			IOMUX_PAD(0x350, 0x028, 5, 0x7A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER			IOMUX_PAD(0x350, 0x028, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__KPP_COL_1			IOMUX_PAD(0x354, 0x02C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__GPIO4_8			IOMUX_PAD(0x354, 0x02C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x354, 0x02C, 2, 0x75C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		IOMUX_PAD(0x354, 0x02C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO			IOMUX_PAD(0x354, 0x02C, 5, 0x7A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK			IOMUX_PAD(0x354, 0x02C, 6, 0x808, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		IOMUX_PAD(0x354, 0x02C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1			IOMUX_PAD(0x358, 0x030, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__GPIO4_9			IOMUX_PAD(0x358, 0x030, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		IOMUX_PAD(0x358, 0x030, 2, 0x748, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		IOMUX_PAD(0x358, 0x030, 4, 0x898, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0			IOMUX_PAD(0x358, 0x030, 5, 0x7A8, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__FEC_COL			IOMUX_PAD(0x358, 0x030, 6, 0x800, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		IOMUX_PAD(0x358, 0x030, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__KPP_COL_2			IOMUX_PAD(0x35C, 0x034, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__GPIO4_10			IOMUX_PAD(0x35C, 0x034, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN			IOMUX_PAD(0x35C, 0x034, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_MDIO			IOMUX_PAD(0x35C, 0x034, 4, 0x804, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1			IOMUX_PAD(0x35C, 0x034, 5, 0x7AC, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2			IOMUX_PAD(0x35C, 0x034, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		IOMUX_PAD(0x35C, 0x034, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2			IOMUX_PAD(0x360, 0x038, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__GPIO4_11			IOMUX_PAD(0x360, 0x038, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN			IOMUX_PAD(0x360, 0x038, 2, 0x760, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_MDC			IOMUX_PAD(0x360, 0x038, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2			IOMUX_PAD(0x360, 0x038, 5, 0x7B0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2			IOMUX_PAD(0x360, 0x038, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		IOMUX_PAD(0x360, 0x038, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__KPP_COL_3			IOMUX_PAD(0x364, 0x03C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__GPIO4_12			IOMUX_PAD(0x364, 0x03C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP			IOMUX_PAD(0x364, 0x03C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__SPDIF_IN1			IOMUX_PAD(0x364, 0x03C, 3, 0x870, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__I2C2_SCL			IOMUX_PAD(0x364, 0x03C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3			IOMUX_PAD(0x364, 0x03C, 5, 0x7B4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__FEC_CRS			IOMUX_PAD(0x364, 0x03C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		IOMUX_PAD(0x364, 0x03C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3			IOMUX_PAD(0x368, 0x040, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__GPIO4_13			IOMUX_PAD(0x368, 0x040, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM			IOMUX_PAD(0x368, 0x040, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x368, 0x040, 3, 0x768, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__I2C2_SDA			IOMUX_PAD(0x368, 0x040, 4 | IOMUX_CONFIG_SION, 0x820, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		IOMUX_PAD(0x368, 0x040, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP			IOMUX_PAD(0x368, 0x040, 6, 0x77C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		IOMUX_PAD(0x368, 0x040, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__KPP_COL_4			IOMUX_PAD(0x36C, 0x044, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__GPIO4_14			IOMUX_PAD(0x36C, 0x044, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN			IOMUX_PAD(0x36C, 0x044, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__IPU_SISG_4			IOMUX_PAD(0x36C, 0x044, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__UART5_RTS			IOMUX_PAD(0x36C, 0x044, 4, 0x894, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		IOMUX_PAD(0x36C, 0x044, 5, 0x89C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		IOMUX_PAD(0x36C, 0x044, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4			IOMUX_PAD(0x370, 0x048, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__GPIO4_15			IOMUX_PAD(0x370, 0x048, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN			IOMUX_PAD(0x370, 0x048, 2, 0x764, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5			IOMUX_PAD(0x370, 0x048, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__UART5_CTS			IOMUX_PAD(0x370, 0x048, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		IOMUX_PAD(0x370, 0x048, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		IOMUX_PAD(0x370, 0x048, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		IOMUX_PAD(0x378, 0x04C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16			IOMUX_PAD(0x378, 0x04C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		IOMUX_PAD(0x378, 0x04C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x04C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		IOMUX_PAD(0x378, 0x04C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		IOMUX_PAD(0x378, 0x04C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x050, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__GPIO4_17			IOMUX_PAD(0x37C, 0x050, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		IOMUX_PAD(0x37C, 0x050, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x050, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		IOMUX_PAD(0x37C, 0x050, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x050, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2			IOMUX_PAD(0x380, 0x054, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x054, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		IOMUX_PAD(0x380, 0x054, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x054, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x054, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		IOMUX_PAD(0x380, 0x054, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3			IOMUX_PAD(0x384, 0x058, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x058, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		IOMUX_PAD(0x384, 0x058, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x058, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x058, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x058, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4			IOMUX_PAD(0x388, 0x05C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x05C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		IOMUX_PAD(0x388, 0x05C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP			IOMUX_PAD(0x388, 0x05C, 3, 0x7FC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		IOMUX_PAD(0x388, 0x05C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x05C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x05C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		IOMUX_PAD(0x38C, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__GPIO4_21			IOMUX_PAD(0x38C, 0x060, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK			IOMUX_PAD(0x38C, 0x060, 2, 0x780, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x060, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x060, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		IOMUX_PAD(0x38C, 0x060, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		IOMUX_PAD(0x38C, 0x060, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		IOMUX_PAD(0x390, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__GPIO4_22			IOMUX_PAD(0x390, 0x064, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI			IOMUX_PAD(0x390, 0x064, 2, 0x788, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x064, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	\
+							IOMUX_PAD(0x390, 0x064, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		IOMUX_PAD(0x390, 0x064, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		IOMUX_PAD(0x390, 0x064, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		IOMUX_PAD(0x394, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__GPIO4_23			IOMUX_PAD(0x394, 0x068, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO			IOMUX_PAD(0x394, 0x068, 2, 0x784, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x068, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		IOMUX_PAD(0x394, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		IOMUX_PAD(0x394, 0x068, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		IOMUX_PAD(0x394, 0x068, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		IOMUX_PAD(0x398, 0x06C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__GPIO4_24			IOMUX_PAD(0x398, 0x06C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0			IOMUX_PAD(0x398, 0x06C, 2, 0x78C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x06C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x06C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		IOMUX_PAD(0x398, 0x06C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		IOMUX_PAD(0x398, 0x06C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		IOMUX_PAD(0x39C, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__GPIO4_25			IOMUX_PAD(0x39C, 0x070, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1			IOMUX_PAD(0x39C, 0x070, 2, 0x790, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		IOMUX_PAD(0x39C, 0x070, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		IOMUX_PAD(0x39C, 0x070, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		IOMUX_PAD(0x39C, 0x070, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		IOMUX_PAD(0x3A0, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__GPIO4_26			IOMUX_PAD(0x3A0, 0x074, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2			IOMUX_PAD(0x3A0, 0x074, 2, 0x794, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x074, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x074, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		IOMUX_PAD(0x3A0, 0x074, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x074, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		IOMUX_PAD(0x3A4, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__GPIO4_27			IOMUX_PAD(0x3A4, 0x078, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3			IOMUX_PAD(0x3A4, 0x078, 2, 0x798, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x078, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x078, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		IOMUX_PAD(0x3A4, 0x078, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x078, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		IOMUX_PAD(0x3A8, 0x07C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__GPIO4_28			IOMUX_PAD(0x3A8, 0x07C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY			IOMUX_PAD(0x3A8, 0x07C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x07C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x07C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		IOMUX_PAD(0x3A8, 0x07C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		IOMUX_PAD(0x3A8, 0x07C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		IOMUX_PAD(0x3AC, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__GPIO4_29			IOMUX_PAD(0x3AC, 0x080, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO			IOMUX_PAD(0x3AC, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		IOMUX_PAD(0x3AC, 0x080, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		IOMUX_PAD(0x3AC, 0x080, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		IOMUX_PAD(0x3AC, 0x080, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		IOMUX_PAD(0x3B0, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__GPIO4_30			IOMUX_PAD(0x3B0, 0x084, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO			IOMUX_PAD(0x3B0, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		IOMUX_PAD(0x3B0, 0x084, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2	IOMUX_PAD(0x3B0, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		IOMUX_PAD(0x3B0, 0x084, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		IOMUX_PAD(0x3B0, 0x084, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		IOMUX_PAD(0x3B4, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__GPIO4_31			IOMUX_PAD(0x3B4, 0x088, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		IOMUX_PAD(0x3B4, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	\
+							IOMUX_PAD(0x3B4, 0x088, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		IOMUX_PAD(0x3B4, 0x088, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		IOMUX_PAD(0x3B4, 0x088, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		IOMUX_PAD(0x3B8, 0x08C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__GPIO5_5			IOMUX_PAD(0x3B8, 0x08C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		IOMUX_PAD(0x3B8, 0x08C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	\
+							IOMUX_PAD(0x3B8, 0x08C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		IOMUX_PAD(0x3B8, 0x08C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		IOMUX_PAD(0x3B8, 0x08C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		IOMUX_PAD(0x3BC, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__GPIO5_6			IOMUX_PAD(0x3BC, 0x090, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		IOMUX_PAD(0x3BC, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	\
+							IOMUX_PAD(0x3BC, 0x090, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		IOMUX_PAD(0x3BC, 0x090, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		IOMUX_PAD(0x3BC, 0x090, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		IOMUX_PAD(0x3C0, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__GPIO5_7			IOMUX_PAD(0x3C0, 0x094, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x3C0, 0x094, 3, 0x754, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	\
+							IOMUX_PAD(0x3C0, 0x094, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		IOMUX_PAD(0x3C0, 0x094, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		IOMUX_PAD(0x3C0, 0x094, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		IOMUX_PAD(0x3C4, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__GPIO5_8			IOMUX_PAD(0x3C4, 0x098, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		IOMUX_PAD(0x3C4, 0x098, 3, 0x750, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	\
+							IOMUX_PAD(0x3C4, 0x098, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		IOMUX_PAD(0x3C4, 0x098, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		IOMUX_PAD(0x3C4, 0x098, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		IOMUX_PAD(0x3C8, 0x09C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__GPIO5_9			IOMUX_PAD(0x3C8, 0x09C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x09C, 2, 0x7AC, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x09C, 3, 0x7C8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	\
+							IOMUX_PAD(0x3C8, 0x09C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		IOMUX_PAD(0x3C8, 0x09C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		IOMUX_PAD(0x3C8, 0x09C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		IOMUX_PAD(0x3CC, 0x0A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__GPIO5_10			IOMUX_PAD(0x3CC, 0x0A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0x0A0, 2, 0x7C0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		IOMUX_PAD(0x3CC, 0x0A0, 3, 0x758, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		IOMUX_PAD(0x3CC, 0x0A0, 4, 0x868, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	\
+							IOMUX_PAD(0x3CC, 0x0A0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		IOMUX_PAD(0x3CC, 0x0A0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		IOMUX_PAD(0x3CC, 0x0A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		IOMUX_PAD(0x3D0, 0x0A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__GPIO5_11			IOMUX_PAD(0x3D0, 0x0A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0x0A4, 2, 0x7BC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		IOMUX_PAD(0x3D0, 0x0A4, 3, 0x74C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		IOMUX_PAD(0x3D0, 0x0A4, 4, 0x86C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	\
+							IOMUX_PAD(0x3D0, 0x0A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		IOMUX_PAD(0x3D0, 0x0A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		IOMUX_PAD(0x3D4, 0x0A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__GPIO5_12			IOMUX_PAD(0x3D4, 0x0A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0x0A8, 2, 0x7C4, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x3D4, 0x0A8, 3, 0x75C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x3D4, 0x0A8, 4, 0x73C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	\
+							IOMUX_PAD(0x3D4, 0x0A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		IOMUX_PAD(0x3D4, 0x0A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		IOMUX_PAD(0x3D4, 0x0A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		IOMUX_PAD(0x3D8, 0x0AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__GPIO5_13			IOMUX_PAD(0x3D8, 0x0AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0x0AC, 2, 0x7B8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		IOMUX_PAD(0x3D8, 0x0AC, 3, 0x748, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		IOMUX_PAD(0x3D8, 0x0AC, 4, 0x738, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	\
+							IOMUX_PAD(0x3D8, 0x0AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		IOMUX_PAD(0x3D8, 0x0AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		IOMUX_PAD(0x3D8, 0x0AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		IOMUX_PAD(0x3DC, 0x0B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__GPIO5_14			IOMUX_PAD(0x3DC, 0x0B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0x0B0, 2, 0x79C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		IOMUX_PAD(0x3DC, 0x0B0, 3, 0x740, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	\
+							IOMUX_PAD(0x3DC, 0x0B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		IOMUX_PAD(0x3DC, 0x0B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0x0B0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		IOMUX_PAD(0x3E0, 0x0B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__GPIO5_15			IOMUX_PAD(0x3E0, 0x0B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0x0B4, 2, 0x7A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		IOMUX_PAD(0x3E0, 0x0B4, 3, 0x734, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0x0B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		IOMUX_PAD(0x3E0, 0x0B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		IOMUX_PAD(0x3E0, 0x0B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		IOMUX_PAD(0x3E4, 0x0B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__GPIO5_16			IOMUX_PAD(0x3E4, 0x0B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0x0B8, 2, 0x7A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x3E4, 0x0B8, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0x0B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		IOMUX_PAD(0x3E4, 0x0B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		IOMUX_PAD(0x3E4, 0x0B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		IOMUX_PAD(0x3E8, 0x0BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__GPIO5_17			IOMUX_PAD(0x3E8, 0x0BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0x0BC, 2, 0x7A8, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		IOMUX_PAD(0x3E8, 0x0BC, 3, 0x730, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0x0BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		IOMUX_PAD(0x3E8, 0x0BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		IOMUX_PAD(0x3E8, 0x0BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		IOMUX_PAD(0x3EC, 0x0C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18			IOMUX_PAD(0x3EC, 0x0C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		IOMUX_PAD(0x3EC, 0x0C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		IOMUX_PAD(0x3EC, 0x0C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0x0C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__GPIO5_19			IOMUX_PAD(0x3F0, 0x0C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0x0C4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		IOMUX_PAD(0x3F0, 0x0C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		IOMUX_PAD(0x3F0, 0x0C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL			IOMUX_PAD(0x3F0, 0x0C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		IOMUX_PAD(0x3F4, 0x0C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20			IOMUX_PAD(0x3F4, 0x0C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		IOMUX_PAD(0x3F4, 0x0C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		IOMUX_PAD(0x3F4, 0x0C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0x0C8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		IOMUX_PAD(0x3F8, 0x0CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21			IOMUX_PAD(0x3F8, 0x0CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		IOMUX_PAD(0x3F8, 0x0CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		IOMUX_PAD(0x3F8, 0x0CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0x0CC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0x0D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__GPIO5_22			IOMUX_PAD(0x3FC, 0x0D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5			IOMUX_PAD(0x3FC, 0x0D0, 2, 0x840, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK			IOMUX_PAD(0x3FC, 0x0D0, 3, 0x79C, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		IOMUX_PAD(0x3FC, 0x0D0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		IOMUX_PAD(0x3FC, 0x0D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		IOMUX_PAD(0x3FC, 0x0D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0x0D0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0x0D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__GPIO5_23			IOMUX_PAD(0x400, 0x0D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5			IOMUX_PAD(0x400, 0x0D4, 2, 0x84C, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI			IOMUX_PAD(0x400, 0x0D4, 3, 0x7A4, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		IOMUX_PAD(0x400, 0x0D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		IOMUX_PAD(0x400, 0x0D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		IOMUX_PAD(0x400, 0x0D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0x0D4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0x0D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__GPIO5_24			IOMUX_PAD(0x404, 0x0D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6			IOMUX_PAD(0x404, 0x0D8, 2, 0x844, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO			IOMUX_PAD(0x404, 0x0D8, 3, 0x7A0, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		IOMUX_PAD(0x404, 0x0D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		IOMUX_PAD(0x404, 0x0D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		IOMUX_PAD(0x404, 0x0D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0x0D8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0x0DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__GPIO5_25			IOMUX_PAD(0x408, 0x0DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6			IOMUX_PAD(0x408, 0x0DC, 2, 0x850, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0			IOMUX_PAD(0x408, 0x0DC, 3, 0x7A8, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		IOMUX_PAD(0x408, 0x0DC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		IOMUX_PAD(0x408, 0x0DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		IOMUX_PAD(0x408, 0x0DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0x0DC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0x0E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__GPIO5_26			IOMUX_PAD(0x40C, 0x0E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7			IOMUX_PAD(0x40C, 0x0E0, 2, 0x848, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK			IOMUX_PAD(0x40C, 0x0E0, 3, 0x7B8, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		IOMUX_PAD(0x40C, 0x0E0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA			IOMUX_PAD(0x40C, 0x0E0, 5 | IOMUX_CONFIG_SION, 0x818, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		IOMUX_PAD(0x40C, 0x0E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0x0E0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0x0E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__GPIO5_27			IOMUX_PAD(0x410, 0x0E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7			IOMUX_PAD(0x410, 0x0E4, 2, 0x854, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI			IOMUX_PAD(0x410, 0x0E4, 3, 0x7C0, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		IOMUX_PAD(0x410, 0x0E4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL			IOMUX_PAD(0x410, 0x0E4, 5 | IOMUX_CONFIG_SION, 0x814, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		IOMUX_PAD(0x410, 0x0E4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0x0E4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0x0E8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__GPIO5_28			IOMUX_PAD(0x414, 0x0E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		IOMUX_PAD(0x414, 0x0E8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0x0E8, 3, 0x7BC, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		IOMUX_PAD(0x414, 0x0E8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		IOMUX_PAD(0x414, 0x0E8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		IOMUX_PAD(0x414, 0x0E8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0x0E8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0x0EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__GPIO5_29			IOMUX_PAD(0x418, 0x0EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		IOMUX_PAD(0x418, 0x0EC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0			IOMUX_PAD(0x418, 0x0EC, 3, 0x7C4, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		IOMUX_PAD(0x418, 0x0EC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		IOMUX_PAD(0x418, 0x0EC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		IOMUX_PAD(0x418, 0x0EC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0x0EC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0x0F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__GPIO5_30			IOMUX_PAD(0x41C, 0x0F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		IOMUX_PAD(0x41C, 0x0F0, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0x0F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		IOMUX_PAD(0x41C, 0x0F0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		IOMUX_PAD(0x41C, 0x0F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0x0F0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0x0F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__GPIO5_31			IOMUX_PAD(0x420, 0x0F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		IOMUX_PAD(0x420, 0x0F4, 2, 0x890, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0x0F4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		IOMUX_PAD(0x420, 0x0F4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		IOMUX_PAD(0x420, 0x0F4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0x0F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0x0F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__GPIO6_0			IOMUX_PAD(0x424, 0x0F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		IOMUX_PAD(0x424, 0x0F8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0x0F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		IOMUX_PAD(0x424, 0x0F8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		IOMUX_PAD(0x424, 0x0F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0x0F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0x0FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__GPIO6_1			IOMUX_PAD(0x428, 0x0FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		IOMUX_PAD(0x428, 0x0FC, 2, 0x898, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0x0FC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		IOMUX_PAD(0x428, 0x0FC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		IOMUX_PAD(0x428, 0x0FC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0x0FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__GPIO6_2			IOMUX_PAD(0x42C, 0x100, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__UART4_RTS			IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		IOMUX_PAD(0x42C, 0x100, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		IOMUX_PAD(0x42C, 0x100, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__GPIO6_3			IOMUX_PAD(0x430, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__UART4_CTS			IOMUX_PAD(0x430, 0x104, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		IOMUX_PAD(0x430, 0x104, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		IOMUX_PAD(0x430, 0x104, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__GPIO6_4			IOMUX_PAD(0x434, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__UART5_RTS			IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		IOMUX_PAD(0x434, 0x108, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		IOMUX_PAD(0x434, 0x108, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__GPIO6_5			IOMUX_PAD(0x438, 0x10C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__UART5_CTS			IOMUX_PAD(0x438, 0x10C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		IOMUX_PAD(0x438, 0x10C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		IOMUX_PAD(0x438, 0x10C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		IOMUX_PAD(0x438, 0x10C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25			IOMUX_PAD(0x458, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__ECSPI2_RDY			IOMUX_PAD(0x458, 0x110, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12			IOMUX_PAD(0x458, 0x110, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS			IOMUX_PAD(0x458, 0x110, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2			IOMUX_PAD(0x45C, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0			IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16			IOMUX_PAD(0x460, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5			IOMUX_PAD(0x460, 0x118, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		IOMUX_PAD(0x460, 0x118, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK			IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17			IOMUX_PAD(0x464, 0x11C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6			IOMUX_PAD(0x464, 0x11C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__ECSPI1_MISO			IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18			IOMUX_PAD(0x468, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7			IOMUX_PAD(0x468, 0x120, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI			IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS			IOMUX_PAD(0x468, 0x120, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19			IOMUX_PAD(0x46C, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8			IOMUX_PAD(0x46C, 0x124, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		IOMUX_PAD(0x46C, 0x124, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__ECSPI1_SS1			IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EPIT1_EPITO			IOMUX_PAD(0x46C, 0x124, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20			IOMUX_PAD(0x470, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16			IOMUX_PAD(0x470, 0x128, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EPIT2_EPITO			IOMUX_PAD(0x470, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		IOMUX_PAD(0x470, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21			IOMUX_PAD(0x474, 0x12C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17			IOMUX_PAD(0x474, 0x12C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		IOMUX_PAD(0x474, 0x12C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22			IOMUX_PAD(0x478, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1			IOMUX_PAD(0x478, 0x130, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		IOMUX_PAD(0x478, 0x130, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23			IOMUX_PAD(0x47C, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART1_DCD			IOMUX_PAD(0x47C, 0x134, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS			IOMUX_PAD(0x47C, 0x134, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2			IOMUX_PAD(0x47C, 0x134, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14			IOMUX_PAD(0x47C, 0x134, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3			IOMUX_PAD(0x480, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3			IOMUX_PAD(0x480, 0x138, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16			IOMUX_PAD(0x480, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24			IOMUX_PAD(0x484, 0x13C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX			IOMUX_PAD(0x484, 0x13C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI1_SS2			IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI2_SS2			IOMUX_PAD(0x484, 0x13C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART1_DTR			IOMUX_PAD(0x484, 0x13C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25			IOMUX_PAD(0x488, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX			IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI1_SS3			IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI2_SS3			IOMUX_PAD(0x488, 0x140, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART1_DSR			IOMUX_PAD(0x488, 0x140, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26			IOMUX_PAD(0x48C, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX			IOMUX_PAD(0x48C, 0x144, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1			IOMUX_PAD(0x48C, 0x144, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11			IOMUX_PAD(0x48C, 0x144, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_SISG_2			IOMUX_PAD(0x48C, 0x144, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27			IOMUX_PAD(0x490, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX			IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0			IOMUX_PAD(0x490, 0x148, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13			IOMUX_PAD(0x490, 0x148, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_SISG_3			IOMUX_PAD(0x490, 0x148, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28			IOMUX_PAD(0x494, 0x14C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, PAD_CTRL_I2C)
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG			IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13			IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29			IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		IOMUX_PAD(0x498, 0x150, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15			IOMUX_PAD(0x498, 0x150, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14			IOMUX_PAD(0x498, 0x150, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30			IOMUX_PAD(0x49C, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3			IOMUX_PAD(0x49C, 0x154, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11			IOMUX_PAD(0x49C, 0x154, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31			IOMUX_PAD(0x4A0, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2			IOMUX_PAD(0x4A0, 0x158, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12			IOMUX_PAD(0x4A0, 0x158, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		IOMUX_PAD(0x4A0, 0x158, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		IOMUX_PAD(0x4A0, 0x158, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24			IOMUX_PAD(0x4A8, 0x15C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19			IOMUX_PAD(0x4A8, 0x15C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_SISG_2			IOMUX_PAD(0x4A8, 0x15C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23			IOMUX_PAD(0x4AC, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18			IOMUX_PAD(0x4AC, 0x160, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_SISG_3			IOMUX_PAD(0x4AC, 0x160, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		IOMUX_PAD(0x4AC, 0x160, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22			IOMUX_PAD(0x4B0, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17			IOMUX_PAD(0x4B0, 0x164, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7			IOMUX_PAD(0x4B0, 0x164, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21			IOMUX_PAD(0x4B4, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16			IOMUX_PAD(0x4B4, 0x168, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6			IOMUX_PAD(0x4B4, 0x168, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20			IOMUX_PAD(0x4B8, 0x16C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15			IOMUX_PAD(0x4B8, 0x16C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5			IOMUX_PAD(0x4B8, 0x16C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19			IOMUX_PAD(0x4BC, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14			IOMUX_PAD(0x4BC, 0x170, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4			IOMUX_PAD(0x4BC, 0x170, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18			IOMUX_PAD(0x4C0, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13			IOMUX_PAD(0x4C0, 0x174, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3			IOMUX_PAD(0x4C0, 0x174, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17			IOMUX_PAD(0x4C4, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12			IOMUX_PAD(0x4C4, 0x178, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2			IOMUX_PAD(0x4C4, 0x178, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16			IOMUX_PAD(0x4C8, 0x17C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1			IOMUX_PAD(0x4C8, 0x17C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0			IOMUX_PAD(0x4CC, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK			IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5			IOMUX_PAD(0x4CC, 0x180, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1			IOMUX_PAD(0x4D0, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI			IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6			IOMUX_PAD(0x4D0, 0x184, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE			IOMUX_PAD(0x4D4, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__ECSPI2_MISO			IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7			IOMUX_PAD(0x4D4, 0x188, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG			IOMUX_PAD(0x4D4, 0x188, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW			IOMUX_PAD(0x4D8, 0x18C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8			IOMUX_PAD(0x4D8, 0x18C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		IOMUX_PAD(0x4D8, 0x18C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA			IOMUX_PAD(0x4DC, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1			IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17			IOMUX_PAD(0x4DC, 0x190, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0			IOMUX_PAD(0x4DC, 0x190, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0			IOMUX_PAD(0x4E4, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11			IOMUX_PAD(0x4E4, 0x194, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY			IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7			IOMUX_PAD(0x4E4, 0x194, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1			IOMUX_PAD(0x4E8, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10			IOMUX_PAD(0x4E8, 0x198, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6			IOMUX_PAD(0x4E8, 0x198, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		IOMUX_PAD(0x4EC, 0x19C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9			IOMUX_PAD(0x4EC, 0x19C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5			IOMUX_PAD(0x4EC, 0x19C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		IOMUX_PAD(0x4F0, 0x1A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8			IOMUX_PAD(0x4F0, 0x1A0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4			IOMUX_PAD(0x4F0, 0x1A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		IOMUX_PAD(0x4F4, 0x1A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7			IOMUX_PAD(0x4F4, 0x1A4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3			IOMUX_PAD(0x4F4, 0x1A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		IOMUX_PAD(0x4F8, 0x1A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6			IOMUX_PAD(0x4F8, 0x1A8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2			IOMUX_PAD(0x4F8, 0x1A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		IOMUX_PAD(0x4FC, 0x1AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5			IOMUX_PAD(0x4FC, 0x1AC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7			IOMUX_PAD(0x4FC, 0x1AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		IOMUX_PAD(0x500, 0x1B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4			IOMUX_PAD(0x500, 0x1B0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6			IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		IOMUX_PAD(0x504, 0x1B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3			IOMUX_PAD(0x504, 0x1B4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5			IOMUX_PAD(0x504, 0x1B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		IOMUX_PAD(0x508, 0x1B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2			IOMUX_PAD(0x508, 0x1B8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4			IOMUX_PAD(0x508, 0x1B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		IOMUX_PAD(0x50C, 0x1BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1			IOMUX_PAD(0x50C, 0x1BC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3			IOMUX_PAD(0x50C, 0x1BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		IOMUX_PAD(0x510, 0x1C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0			IOMUX_PAD(0x510, 0x1C0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2			IOMUX_PAD(0x510, 0x1C0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		IOMUX_PAD(0x514, 0x1C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		IOMUX_PAD(0x518, 0x1C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2			IOMUX_PAD(0x518, 0x1C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		IOMUX_PAD(0x51C, 0x1CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3			IOMUX_PAD(0x51C, 0x1CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		IOMUX_PAD(0x520, 0x1D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		IOMUX_PAD(0x524, 0x1D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		IOMUX_PAD(0x528, 0x1D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1			IOMUX_PAD(0x528, 0x1D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4			IOMUX_PAD(0x528, 0x1D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		IOMUX_PAD(0x52C, 0x1DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__GPIO6_12			IOMUX_PAD(0x52C, 0x1DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		IOMUX_PAD(0x530, 0x1E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__GPIO6_13			IOMUX_PAD(0x530, 0x1E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		IOMUX_PAD(0x534, 0x1E4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22			IOMUX_PAD(__NA_, 0x1EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		IOMUX_PAD(__NA_, 0x1EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24			IOMUX_PAD(__NA_, 0x1F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		IOMUX_PAD(__NA_, 0x1F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26			IOMUX_PAD(__NA_, 0x1F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		IOMUX_PAD(__NA_, 0x1F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28			IOMUX_PAD(__NA_, 0x1F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		IOMUX_PAD(__NA_, 0x1F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30			IOMUX_PAD(__NA_, 0x1FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		IOMUX_PAD(__NA_, 0x1FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22			IOMUX_PAD(__NA_, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		IOMUX_PAD(__NA_, 0x200, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24			IOMUX_PAD(__NA_, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		IOMUX_PAD(__NA_, 0x204, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26			IOMUX_PAD(__NA_, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		IOMUX_PAD(__NA_, 0x208, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28			IOMUX_PAD(__NA_, 0x20C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		IOMUX_PAD(__NA_, 0x20C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30			IOMUX_PAD(__NA_, 0x210, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		IOMUX_PAD(__NA_, 0x210, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		IOMUX_PAD(0x5A0, 0x228, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__GPIO6_8			IOMUX_PAD(0x5A4, 0x22C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		IOMUX_PAD(0x5A4, 0x22C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		IOMUX_PAD(0x5A8, 0x230, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__GPIO6_9			IOMUX_PAD(0x5A8, 0x230, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		IOMUX_PAD(0x5A8, 0x230, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		IOMUX_PAD(0x5AC, 0x234, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__GPIO6_10			IOMUX_PAD(0x5AC, 0x234, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		IOMUX_PAD(0x5AC, 0x234, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		IOMUX_PAD(0x5B0, 0x238, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__GPIO6_11			IOMUX_PAD(0x5B0, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		IOMUX_PAD(0x5B0, 0x238, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		IOMUX_PAD(0x5B4, 0x23C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__GPIO6_14			IOMUX_PAD(0x5B4, 0x23C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK			IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		IOMUX_PAD(0x5B4, 0x23C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		IOMUX_PAD(0x5B8, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__GPIO6_15			IOMUX_PAD(0x5B8, 0x240, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0			IOMUX_PAD(0x5B8, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0			IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG			IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		IOMUX_PAD(0x5B8, 0x240, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		IOMUX_PAD(0x5BC, 0x244, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__GPIO6_16			IOMUX_PAD(0x5BC, 0x244, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1			IOMUX_PAD(0x5BC, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1			IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT			IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		IOMUX_PAD(0x5BC, 0x244, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_MDIO			IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR			IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		IOMUX_PAD(0x5C4, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23			IOMUX_PAD(0x5C8, 0x24C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR			IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		IOMUX_PAD(0x5C8, 0x24C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER			IOMUX_PAD(0x5CC, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__GPIO1_24			IOMUX_PAD(0x5CC, 0x250, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR			IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK			IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV			IOMUX_PAD(0x5D0, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25			IOMUX_PAD(0x5D0, 0x254, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT			IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1			IOMUX_PAD(0x5D4, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__ESAI1_FST			IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG			IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0			IOMUX_PAD(0x5D8, 0x25C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT			IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN			IOMUX_PAD(0x5DC, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__GPIO1_28			IOMUX_PAD(0x5DC, 0x260, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1			IOMUX_PAD(0x5E0, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK			IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		IOMUX_PAD(0x5E0, 0x264, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0			IOMUX_PAD(0x5E4, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		IOMUX_PAD(0x5E4, 0x268, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0			IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT			IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		IOMUX_PAD(0x5E8, 0x26C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__PATA_DIOW			IOMUX_PAD(0x5F0, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__GPIO6_17			IOMUX_PAD(0x5F0, 0x270, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		IOMUX_PAD(0x5F0, 0x270, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		IOMUX_PAD(0x5F0, 0x270, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__PATA_DMACK			IOMUX_PAD(0x5F4, 0x274, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__GPIO6_18			IOMUX_PAD(0x5F4, 0x274, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		IOMUX_PAD(0x5F4, 0x274, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ			IOMUX_PAD(0x5F8, 0x278, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__GPIO7_0			IOMUX_PAD(0x5F8, 0x278, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		IOMUX_PAD(0x5F8, 0x278, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		IOMUX_PAD(0x5F8, 0x278, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		IOMUX_PAD(0x5F8, 0x278, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		IOMUX_PAD(0x5FC, 0x27C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		IOMUX_PAD(0x5FC, 0x27C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ			IOMUX_PAD(0x600, 0x280, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__GPIO7_2			IOMUX_PAD(0x600, 0x280, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__UART2_CTS			IOMUX_PAD(0x600, 0x280, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN			IOMUX_PAD(0x600, 0x280, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		IOMUX_PAD(0x600, 0x280, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		IOMUX_PAD(0x600, 0x280, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__PATA_DIOR			IOMUX_PAD(0x604, 0x284, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__UART2_RTS			IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN			IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		IOMUX_PAD(0x604, 0x284, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__GPIO7_4			IOMUX_PAD(0x608, 0x288, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__PATA_IORDY			IOMUX_PAD(0x60C, 0x28C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__GPIO7_5			IOMUX_PAD(0x60C, 0x28C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK			IOMUX_PAD(0x60C, 0x28C, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__UART1_RTS			IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN			IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		IOMUX_PAD(0x60C, 0x28C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__PATA_DA_0			IOMUX_PAD(0x610, 0x290, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__GPIO7_6			IOMUX_PAD(0x610, 0x290, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST			IOMUX_PAD(0x610, 0x290, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE			IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		IOMUX_PAD(0x610, 0x290, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__PATA_DA_1			IOMUX_PAD(0x614, 0x294, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__GPIO7_7			IOMUX_PAD(0x614, 0x294, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD			IOMUX_PAD(0x614, 0x294, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__UART3_CTS			IOMUX_PAD(0x614, 0x294, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		IOMUX_PAD(0x614, 0x294, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__PATA_DA_2			IOMUX_PAD(0x618, 0x298, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__GPIO7_8			IOMUX_PAD(0x618, 0x298, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK			IOMUX_PAD(0x618, 0x298, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__UART3_RTS			IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		IOMUX_PAD(0x618, 0x298, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__PATA_CS_0			IOMUX_PAD(0x61C, 0x29C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		IOMUX_PAD(0x61C, 0x29C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__PATA_CS_1			IOMUX_PAD(0x620, 0x2A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__GPIO7_10			IOMUX_PAD(0x620, 0x2A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		IOMUX_PAD(0x620, 0x2A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPIO2_0			IOMUX_PAD(0x628, 0x2A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		IOMUX_PAD(0x628, 0x2A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		IOMUX_PAD(0x628, 0x2A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		IOMUX_PAD(0x628, 0x2A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPIO2_1			IOMUX_PAD(0x62C, 0x2A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		IOMUX_PAD(0x62C, 0x2A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		IOMUX_PAD(0x62C, 0x2A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPIO2_2			IOMUX_PAD(0x630, 0x2AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		IOMUX_PAD(0x630, 0x2AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		IOMUX_PAD(0x630, 0x2AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPIO2_3			IOMUX_PAD(0x634, 0x2B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		IOMUX_PAD(0x634, 0x2B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		IOMUX_PAD(0x634, 0x2B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPIO2_4			IOMUX_PAD(0x638, 0x2B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		IOMUX_PAD(0x638, 0x2B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		IOMUX_PAD(0x638, 0x2B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5		IOMUX_PAD(0x63C, 0x2B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPIO2_5			IOMUX_PAD(0x63C, 0x2B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		IOMUX_PAD(0x63C, 0x2B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		IOMUX_PAD(0x63C, 0x2B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6		IOMUX_PAD(0x640, 0x2BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPIO2_6			IOMUX_PAD(0x640, 0x2BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		IOMUX_PAD(0x640, 0x2BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		IOMUX_PAD(0x640, 0x2BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPIO2_7			IOMUX_PAD(0x644, 0x2C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		IOMUX_PAD(0x644, 0x2C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		IOMUX_PAD(0x644, 0x2C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPIO2_8			IOMUX_PAD(0x648, 0x2C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		IOMUX_PAD(0x648, 0x2C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		IOMUX_PAD(0x648, 0x2C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPIO2_9			IOMUX_PAD(0x64C, 0x2C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		IOMUX_PAD(0x64C, 0x2C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		IOMUX_PAD(0x64C, 0x2C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10		IOMUX_PAD(0x650, 0x2CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPIO2_10			IOMUX_PAD(0x650, 0x2CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		IOMUX_PAD(0x650, 0x2CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		IOMUX_PAD(0x650, 0x2CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11		IOMUX_PAD(0x654, 0x2D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPIO2_11			IOMUX_PAD(0x654, 0x2D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		IOMUX_PAD(0x654, 0x2D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		IOMUX_PAD(0x654, 0x2D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12		IOMUX_PAD(0x658, 0x2D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPIO2_12			IOMUX_PAD(0x658, 0x2D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		IOMUX_PAD(0x658, 0x2D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		IOMUX_PAD(0x658, 0x2D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13		IOMUX_PAD(0x65C, 0x2D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPIO2_13			IOMUX_PAD(0x65C, 0x2D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		IOMUX_PAD(0x65C, 0x2D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		IOMUX_PAD(0x65C, 0x2D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14		IOMUX_PAD(0x660, 0x2DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPIO2_14			IOMUX_PAD(0x660, 0x2DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		IOMUX_PAD(0x660, 0x2DC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		IOMUX_PAD(0x660, 0x2DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15		IOMUX_PAD(0x664, 0x2E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPIO2_15			IOMUX_PAD(0x664, 0x2E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		IOMUX_PAD(0x664, 0x2E0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		IOMUX_PAD(0x664, 0x2E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0			IOMUX_PAD(0x66C, 0x2E4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPIO1_16			IOMUX_PAD(0x66C, 0x2E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1			IOMUX_PAD(0x66C, 0x2E4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CSPI_MISO			IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1			IOMUX_PAD(0x670, 0x2E8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPIO1_17			IOMUX_PAD(0x670, 0x2E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2			IOMUX_PAD(0x670, 0x2E8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CSPI_SS0			IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD			IOMUX_PAD(0x674, 0x2EC, 0 | IOMUX_CONFIG_SION, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPIO1_18			IOMUX_PAD(0x674, 0x2EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1			IOMUX_PAD(0x674, 0x2EC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CSPI_MOSI			IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP			IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2			IOMUX_PAD(0x678, 0x2F0, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPIO1_19			IOMUX_PAD(0x678, 0x2F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2			IOMUX_PAD(0x678, 0x2F0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO			IOMUX_PAD(0x678, 0x2F0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CSPI_SS1			IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK			IOMUX_PAD(0x67C, 0x2F4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPIO1_20			IOMUX_PAD(0x67C, 0x2F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		IOMUX_PAD(0x67C, 0x2F4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPT_CLKIN			IOMUX_PAD(0x67C, 0x2F4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__CSPI_SCLK			IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		IOMUX_PAD(0x67C, 0x2F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3			IOMUX_PAD(0x680, 0x2F8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPIO1_21			IOMUX_PAD(0x680, 0x2F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3			IOMUX_PAD(0x680, 0x2F8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO			IOMUX_PAD(0x680, 0x2F8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		IOMUX_PAD(0x680, 0x2F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__CSPI_SS2			IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		IOMUX_PAD(0x680, 0x2F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK			IOMUX_PAD(0x688, 0x2FC, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__GPIO1_10			IOMUX_PAD(0x688, 0x2FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__KPP_COL_5			IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__CSPI_SCLK			IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V			IOMUX_PAD(0x688, 0x2FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD			IOMUX_PAD(0x68C, 0x300, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__GPIO1_11			IOMUX_PAD(0x68C, 0x300, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__KPP_ROW_5			IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__CSPI_MOSI			IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__SCC_RANDOM			IOMUX_PAD(0x68C, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3			IOMUX_PAD(0x690, 0x304, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__GPIO1_12			IOMUX_PAD(0x690, 0x304, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__KPP_COL_6			IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__CSPI_SS2			IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__SJC_DONE			IOMUX_PAD(0x690, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2			IOMUX_PAD(0x694, 0x308, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__GPIO1_13			IOMUX_PAD(0x694, 0x308, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6			IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__CSPI_SS1			IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__SJC_FAIL			IOMUX_PAD(0x694, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1			IOMUX_PAD(0x698, 0x30C, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__GPIO1_14			IOMUX_PAD(0x698, 0x30C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__KPP_COL_7			IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__CSPI_SS0			IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		IOMUX_PAD(0x698, 0x30C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0			IOMUX_PAD(0x69C, 0x310, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__GPIO1_15			IOMUX_PAD(0x69C, 0x310, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7			IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__CSPI_MISO			IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		IOMUX_PAD(0x69C, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_CLKO			IOMUX_PAD(0x6A4, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__GPIO1_0			IOMUX_PAD(0x6A4, 0x314, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__KPP_COL_5			IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		IOMUX_PAD(0x6A4, 0x314, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__EPIT1_EPITO			IOMUX_PAD(0x6A4, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB			IOMUX_PAD(0x6A4, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		IOMUX_PAD(0x6A4, 0x314, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CSU_TD				IOMUX_PAD(0x6A4, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESAI1_SCKR			IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__GPIO1_1			IOMUX_PAD(0x6A8, 0x318, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__KPP_ROW_5			IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		IOMUX_PAD(0x6A8, 0x318, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__PWM2_PWMO			IOMUX_PAD(0x6A8, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B			IOMUX_PAD(0x6A8, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESDHC1_CD			IOMUX_PAD(0x6A8, 0x318, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK			IOMUX_PAD(0x6A8, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESAI1_FSR			IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__GPIO1_9			IOMUX_PAD(0x6AC, 0x31C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__KPP_COL_6			IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B			IOMUX_PAD(0x6AC, 0x31C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__PWM1_PWMO			IOMUX_PAD(0x6AC, 0x31C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B			IOMUX_PAD(0x6AC, 0x31C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESDHC1_WP			IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE			IOMUX_PAD(0x6AC, 0x31C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__ESAI1_HCKR			IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__GPIO1_3			IOMUX_PAD(0x6B0, 0x320, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__I2C3_SCL			IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN			IOMUX_PAD(0x6B0, 0x320, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__CCM_CLKO2			IOMUX_PAD(0x6B0, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__MLB_MLBCLK			IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESAI1_SCKT			IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__GPIO1_6			IOMUX_PAD(0x6B4, 0x324, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__I2C3_SDA			IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0			IOMUX_PAD(0x6B4, 0x324, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		IOMUX_PAD(0x6B4, 0x324, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL			IOMUX_PAD(0x6B4, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__MLB_MLBSIG			IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESAI1_FST			IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__GPIO1_2			IOMUX_PAD(0x6B8, 0x328, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__KPP_ROW_6			IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1			IOMUX_PAD(0x6B8, 0x328, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		IOMUX_PAD(0x6B8, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESDHC2_WP			IOMUX_PAD(0x6B8, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__MLB_MLBDAT			IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESAI1_HCKT			IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__GPIO1_4			IOMUX_PAD(0x6BC, 0x32C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__KPP_COL_7			IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2			IOMUX_PAD(0x6BC, 0x32C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		IOMUX_PAD(0x6BC, 0x32C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESDHC2_CD			IOMUX_PAD(0x6BC, 0x32C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE			IOMUX_PAD(0x6BC, 0x32C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3			IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__GPIO1_5			IOMUX_PAD(0x6C0, 0x330, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__KPP_ROW_7			IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_CLKO			IOMUX_PAD(0x6C0, 0x330, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		IOMUX_PAD(0x6C0, 0x330, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__I2C3_SCL			IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP			IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1			IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__GPIO1_7			IOMUX_PAD(0x6C4, 0x334, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__EPIT1_EPITO			IOMUX_PAD(0x6C4, 0x334, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CAN1_TXCAN			IOMUX_PAD(0x6C4, 0x334, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX			IOMUX_PAD(0x6C4, 0x334, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_7__FIRI_RXD			IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK			IOMUX_PAD(0x6C4, 0x334, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP			IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0			IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__GPIO1_8			IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__EPIT2_EPITO			IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CAN1_RXCAN			IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX			IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_8__FIRI_TXD			IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK			IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP			IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2			IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__GPIO7_11			IOMUX_PAD(0x6CC, 0x33C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		IOMUX_PAD(0x6CC, 0x33C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		IOMUX_PAD(0x6CC, 0x33C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SPDIF_IN1			IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__I2C3_SDA			IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SJC_DE_B			IOMUX_PAD(0x6CC, 0x33C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__ESAI1_TX0			IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPIO7_12			IOMUX_PAD(0x6D0, 0x340, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY			IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		IOMUX_PAD(0x6D0, 0x340, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SPDIF_OUT1			IOMUX_PAD(0x6D0, 0x340, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__IPU_SNOOP2			IOMUX_PAD(0x6D0, 0x340, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT			IOMUX_PAD(0x6D0, 0x340, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESAI1_TX1			IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__GPIO7_13			IOMUX_PAD(0x6D4, 0x344, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__OWIRE_LINE			IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL			IOMUX_PAD(0x6D4, 0x344, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		IOMUX_PAD(0x6D4, 0x344, 7, __NA_, 0, NO_PAD_CTRL)
 
 #endif	/* __MACH_IOMUX_MX53_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@ typedef u64 iomux_v3_cfg_t;
 		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
 		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
 
+#define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
 /*
  * Use to set PAD control
  */
@@ -89,11 +90,11 @@ typedef u64 iomux_v3_cfg_t;
 #define PAD_CTL_HYS			(1 << 8)
 
 #define PAD_CTL_PKE			(1 << 7)
-#define PAD_CTL_PUE			(1 << 6)
-#define PAD_CTL_PUS_100K_DOWN		(0 << 4)
-#define PAD_CTL_PUS_47K_UP		(1 << 4)
-#define PAD_CTL_PUS_100K_UP		(2 << 4)
-#define PAD_CTL_PUS_22K_UP		(3 << 4)
+#define PAD_CTL_PUE			(1 << 6 | PAD_CTL_PKE)
+#define PAD_CTL_PUS_100K_DOWN		(0 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_47K_UP		(1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP		(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP		(3 << 4 | PAD_CTL_PUE)
 
 #define PAD_CTL_ODE			(1 << 3)
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/irqs.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,15 @@
 #include <asm-generic/gpio.h>
 
 /*
- * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
+ * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
+ * have 128 IRQs, and those with AVIC have 64.
+ *
+ * To support single image, the biggest number should be defined on
+ * top of the list.
  */
-#ifdef CONFIG_MXC_TZIC
+#if defined CONFIG_ARM_GIC
+#define MXC_INTERNAL_IRQS	160
+#elif defined CONFIG_MXC_TZIC
 #define MXC_INTERNAL_IRQS	128
 #else
 #define MXC_INTERNAL_IRQS	64
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_MEMORY_H__
-#define __ASM_ARCH_MXC_MEMORY_H__
-
-#define MX1_PHYS_OFFSET		UL(0x08000000)
-#define MX21_PHYS_OFFSET	UL(0xc0000000)
-#define MX25_PHYS_OFFSET	UL(0x80000000)
-#define MX27_PHYS_OFFSET	UL(0xa0000000)
-#define MX3x_PHYS_OFFSET	UL(0x80000000)
-#define MX50_PHYS_OFFSET	UL(0x70000000)
-#define MX51_PHYS_OFFSET	UL(0x90000000)
-#define MX53_PHYS_OFFSET	UL(0x70000000)
-
-#if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
-# if defined CONFIG_ARCH_MX1
-#  define PLAT_PHYS_OFFSET		MX1_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX21
-#  define PLAT_PHYS_OFFSET		MX21_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX25
-#  define PLAT_PHYS_OFFSET		MX25_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX27
-#  define PLAT_PHYS_OFFSET		MX27_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX3
-#  define PLAT_PHYS_OFFSET		MX3x_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX50
-#  define PLAT_PHYS_OFFSET		MX50_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX51
-#  define PLAT_PHYS_OFFSET		MX51_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX53
-#  define PLAT_PHYS_OFFSET		MX53_PHYS_OFFSET
-# endif
-#endif
-
-#if defined(CONFIG_MX3_VIDEO)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for mx3 camera driver to capture at least two QXGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#elif defined(CONFIG_MX1_VIDEO) || defined(CONFIG_VIDEO_MX2_HOSTSUPPORT)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for i.MX camera driver to capture at least four VGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-#endif /* CONFIG_MX1_VIDEO || CONFIG_VIDEO_MX2_HOSTSUPPORT */
-
-#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx25.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx25.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx25.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx25.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #define MX25_SSI2_BASE_ADDR		0x50014000
 #define MX25_SSI1_BASE_ADDR		0x50034000
 #define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_IIM_BASE_ADDR		0x53ff0000
 #define MX25_DRYICE_BASE_ADDR		0x53ffc000
 #define MX25_ESDHC1_BASE_ADDR		0x53fb4000
 #define MX25_ESDHC2_BASE_ADDR		0x53fb8000
@@ -104,4 +105,8 @@
 #define MX25_DMA_REQ_SSI1_RX0	28
 #define MX25_DMA_REQ_SSI1_TX0	29
 
+#ifndef __ASSEMBLY__
+extern int mx25_revision(void);
+#endif
+
 #endif /* ifndef __MACH_MX25_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx27.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx27.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx27.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx27.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,10 +24,6 @@
 #ifndef __MACH_MX27_H__
 #define __MACH_MX27_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 #define MX27_AIPI_BASE_ADDR		0x10000000
 #define MX27_AIPI_SIZE			SZ_1M
 #define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
@@ -131,16 +127,6 @@
 #define MX27_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX27_IO_ADDRESS(x)		IOMEM(MX27_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx27_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(cs)));
-}
-#endif
-
 /* fixed interrupt numbers */
 #define MX27_INT_I2C2		1
 #define MX27_INT_GPT6		2
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx31.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx31.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx31.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx31.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,6 @@
 #ifndef __MACH_MX31_H__
 #define __MACH_MX31_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 /*
  * IRAM
  */
@@ -122,16 +118,6 @@
 #define MX31_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX31_IO_ADDRESS(x)		IOMEM(MX31_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx31_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(cs)));
-}
-#endif
-
 #define MX31_INT_I2C3		3
 #define MX31_INT_I2C2		4
 #define MX31_INT_MPEG4_ENCODER	5
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx35.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx35.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx35.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx35.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 #define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
 #define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
 #define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
-#define MX35_ATA_DMA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
+#define MX35_ATA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
 #define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
 #define MX35_FEC_BASE_ADDR		0x50038000
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h	2012-01-04 18:55:44.000000000 -0500
@@ -187,22 +187,8 @@
 /* Mandatory defines used globally */
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
-extern unsigned int mx31_cpu_rev;
-extern void mx31_read_cpu_rev(void);
-
-static inline int mx31_revision(void)
-{
-	return mx31_cpu_rev;
-}
-
-extern unsigned int mx35_cpu_rev;
-extern void mx35_read_cpu_rev(void);
-
-static inline int mx35_revision(void)
-{
-	return mx35_cpu_rev;
-}
+extern int mx35_revision(void);
+extern int mx31_revision(void);
 #endif
 
 #endif /* ifndef __MACH_MX3x_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx51.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx51.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,18 +18,6 @@
 #define MX51_GPU_CTRL_BASE_ADDR		0x30000000
 #define MX51_IPU_CTRL_BASE_ADDR		0x40000000
 
-#define MX51_DEBUG_BASE_ADDR		0x60000000
-#define MX51_DEBUG_SIZE			SZ_1M
-
-#define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x01000)
-#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x02000)
-#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x03000)
-#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x04000)
-#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x05000)
-#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x06000)
-#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x07000)
-#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x08000)
-
 /*
  * SPBA global module enabled #0
  */
@@ -55,7 +43,10 @@
 #define MX51_AIPS1_BASE_ADDR		0x73f00000
 #define MX51_AIPS1_SIZE			SZ_1M
 
-#define MX51_OTG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
+#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
+#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
 #define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
 #define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
 #define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
@@ -132,6 +123,7 @@
 
 #define MX51_GPU2D_BASE_ADDR		0xd0000000
 #define MX51_TZIC_BASE_ADDR		0xe0000000
+#define MX51_TZIC_SIZE			SZ_16K
 
 #define MX51_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
@@ -240,117 +232,114 @@
 /*
  * Interrupt numbers
  */
-#define MX51_MXC_INT_BASE		0
-#define MX51_MXC_INT_RESV0		0
+#define MX51_INT_BASE			0
+#define MX51_INT_RESV0			0
 #define MX51_INT_ESDHC1			1
 #define MX51_INT_ESDHC2			2
 #define MX51_INT_ESDHC3			3
 #define MX51_INT_ESDHC4			4
-#define MX51_MXC_INT_RESV5		5
+#define MX51_INT_RESV5			5
 #define MX51_INT_SDMA			6
-#define MX51_MXC_INT_IOMUX		7
+#define MX51_INT_IOMUX			7
 #define MX51_INT_NFC			8
-#define MX51_MXC_INT_VPU		9
+#define MX51_INT_VPU			9
 #define MX51_INT_IPU_ERR		10
 #define MX51_INT_IPU_SYN		11
-#define MX51_MXC_INT_GPU		12
-#define MX51_MXC_INT_RESV13		13
-#define MX51_MXC_INT_USB_H1		14
-#define MX51_MXC_INT_EMI		15
-#define MX51_MXC_INT_USB_H2		16
-#define MX51_MXC_INT_USB_H3		17
-#define MX51_MXC_INT_USB_OTG		18
-#define MX51_MXC_INT_SAHARA_H0		19
-#define MX51_MXC_INT_SAHARA_H1		20
-#define MX51_MXC_INT_SCC_SMN		21
-#define MX51_MXC_INT_SCC_STZ		22
-#define MX51_MXC_INT_SCC_SCM		23
-#define MX51_MXC_INT_SRTC_NTZ		24
-#define MX51_MXC_INT_SRTC_TZ		25
-#define MX51_MXC_INT_RTIC		26
-#define MX51_MXC_INT_CSU		27
-#define MX51_MXC_INT_SLIM_B		28
+#define MX51_INT_GPU			12
+#define MX51_INT_RESV13			13
+#define MX51_INT_USB_HS1		14
+#define MX51_INT_EMI			15
+#define MX51_INT_USB_HS2		16
+#define MX51_INT_USB_HS3		17
+#define MX51_INT_USB_OTG		18
+#define MX51_INT_SAHARA_H0		19
+#define MX51_INT_SAHARA_H1		20
+#define MX51_INT_SCC_SMN		21
+#define MX51_INT_SCC_STZ		22
+#define MX51_INT_SCC_SCM		23
+#define MX51_INT_SRTC_NTZ		24
+#define MX51_INT_SRTC_TZ		25
+#define MX51_INT_RTIC			26
+#define MX51_INT_CSU			27
+#define MX51_INT_SLIM_B			28
 #define MX51_INT_SSI1			29
 #define MX51_INT_SSI2			30
 #define MX51_INT_UART1			31
 #define MX51_INT_UART2			32
 #define MX51_INT_UART3			33
-#define MX51_MXC_INT_RESV34		34
-#define MX51_MXC_INT_RESV35		35
+#define MX51_INT_RESV34			34
+#define MX51_INT_RESV35			35
 #define MX51_INT_ECSPI1			36
 #define MX51_INT_ECSPI2			37
 #define MX51_INT_CSPI			38
-#define MX51_MXC_INT_GPT		39
-#define MX51_MXC_INT_EPIT1		40
-#define MX51_MXC_INT_EPIT2		41
-#define MX51_MXC_INT_GPIO1_INT7		42
-#define MX51_MXC_INT_GPIO1_INT6		43
-#define MX51_MXC_INT_GPIO1_INT5		44
-#define MX51_MXC_INT_GPIO1_INT4		45
-#define MX51_MXC_INT_GPIO1_INT3		46
-#define MX51_MXC_INT_GPIO1_INT2		47
-#define MX51_MXC_INT_GPIO1_INT1		48
-#define MX51_MXC_INT_GPIO1_INT0		49
-#define MX51_MXC_INT_GPIO1_LOW		50
-#define MX51_MXC_INT_GPIO1_HIGH		51
-#define MX51_MXC_INT_GPIO2_LOW		52
-#define MX51_MXC_INT_GPIO2_HIGH		53
-#define MX51_MXC_INT_GPIO3_LOW		54
-#define MX51_MXC_INT_GPIO3_HIGH		55
-#define MX51_MXC_INT_GPIO4_LOW		56
-#define MX51_MXC_INT_GPIO4_HIGH		57
-#define MX51_MXC_INT_WDOG1		58
-#define MX51_MXC_INT_WDOG2		59
+#define MX51_INT_GPT			39
+#define MX51_INT_EPIT1			40
+#define MX51_INT_EPIT2			41
+#define MX51_INT_GPIO1_INT7		42
+#define MX51_INT_GPIO1_INT6		43
+#define MX51_INT_GPIO1_INT5		44
+#define MX51_INT_GPIO1_INT4		45
+#define MX51_INT_GPIO1_INT3		46
+#define MX51_INT_GPIO1_INT2		47
+#define MX51_INT_GPIO1_INT1		48
+#define MX51_INT_GPIO1_INT0		49
+#define MX51_INT_GPIO1_LOW		50
+#define MX51_INT_GPIO1_HIGH		51
+#define MX51_INT_GPIO2_LOW		52
+#define MX51_INT_GPIO2_HIGH		53
+#define MX51_INT_GPIO3_LOW		54
+#define MX51_INT_GPIO3_HIGH		55
+#define MX51_INT_GPIO4_LOW		56
+#define MX51_INT_GPIO4_HIGH		57
+#define MX51_INT_WDOG1			58
+#define MX51_INT_WDOG2			59
 #define MX51_INT_KPP			60
 #define MX51_INT_PWM1			61
 #define MX51_INT_I2C1			62
 #define MX51_INT_I2C2			63
-#define MX51_MXC_INT_HS_I2C		64
-#define MX51_MXC_INT_RESV65		65
-#define MX51_MXC_INT_RESV66		66
-#define MX51_MXC_INT_SIM_IPB		67
-#define MX51_MXC_INT_SIM_DAT		68
-#define MX51_MXC_INT_IIM		69
-#define MX51_MXC_INT_ATA		70
-#define MX51_MXC_INT_CCM1		71
-#define MX51_MXC_INT_CCM2		72
-#define MX51_MXC_INT_GPC1		73
-#define MX51_MXC_INT_GPC2		74
-#define MX51_MXC_INT_SRC		75
-#define MX51_MXC_INT_NM			76
-#define MX51_MXC_INT_PMU		77
-#define MX51_MXC_INT_CTI_IRQ		78
-#define MX51_MXC_INT_CTI1_TG0		79
-#define MX51_MXC_INT_CTI1_TG1		80
-#define MX51_MXC_INT_MCG_ERR		81
-#define MX51_MXC_INT_MCG_TMR		82
-#define MX51_MXC_INT_MCG_FUNC		83
-#define MX51_MXC_INT_GPU2_IRQ		84
-#define MX51_MXC_INT_GPU2_BUSY		85
-#define MX51_MXC_INT_RESV86		86
+#define MX51_INT_HS_I2C			64
+#define MX51_INT_RESV65			65
+#define MX51_INT_RESV66			66
+#define MX51_INT_SIM_IPB		67
+#define MX51_INT_SIM_DAT		68
+#define MX51_INT_IIM			69
+#define MX51_INT_ATA			70
+#define MX51_INT_CCM1			71
+#define MX51_INT_CCM2			72
+#define MX51_INT_GPC1				73
+#define MX51_INT_GPC2			74
+#define MX51_INT_SRC			75
+#define MX51_INT_NM			76
+#define MX51_INT_PMU			77
+#define MX51_INT_CTI_IRQ		78
+#define MX51_INT_CTI1_TG0		79
+#define MX51_INT_CTI1_TG1		80
+#define MX51_INT_MCG_ERR		81
+#define MX51_INT_MCG_TMR		82
+#define MX51_INT_MCG_FUNC		83
+#define MX51_INT_GPU2_IRQ		84
+#define MX51_INT_GPU2_BUSY		85
+#define MX51_INT_RESV86			86
 #define MX51_INT_FEC			87
-#define MX51_MXC_INT_OWIRE		88
-#define MX51_MXC_INT_CTI1_TG2		89
-#define MX51_MXC_INT_SJC		90
-#define MX51_MXC_INT_SPDIF		91
-#define MX51_MXC_INT_TVE		92
-#define MX51_MXC_INT_FIRI		93
+#define MX51_INT_OWIRE			88
+#define MX51_INT_CTI1_TG2		89
+#define MX51_INT_SJC			90
+#define MX51_INT_SPDIF			91
+#define MX51_INT_TVE			92
+#define MX51_INT_FIRI			93
 #define MX51_INT_PWM2			94
-#define MX51_MXC_INT_SLIM_EXP		95
+#define MX51_INT_SLIM_EXP		95
 #define MX51_INT_SSI3			96
-#define MX51_MXC_INT_EMI_BOOT		97
-#define MX51_MXC_INT_CTI1_TG3		98
-#define MX51_MXC_INT_SMC_RX		99
-#define MX51_MXC_INT_VPU_IDLE		100
-#define MX51_MXC_INT_EMI_NFC		101
-#define MX51_MXC_INT_GPU_IDLE		102
+#define MX51_INT_EMI_BOOT		97
+#define MX51_INT_CTI1_TG3		98
+#define MX51_INT_SMC_RX			99
+#define MX51_INT_VPU_IDLE		100
+#define MX51_INT_EMI_NFC		101
+#define MX51_INT_GPU_IDLE		102
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
 extern void mx51_display_revision(void);
 #endif
 
-/* tape-out 1 defines */
-#define MX51_TZIC_BASE_ADDR_TO1		0x8fffc000
-
 #endif	/* ifndef __MACH_MX51_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx53.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx53.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 /* TZIC */
 #define MX53_TZIC_BASE_ADDR		0x0FFFC000
+#define MX53_TZIC_SIZE			SZ_16K
 
 /*
  * AHCI SATA
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx6q.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx6q.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mx6q.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mx6q.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR		0x00a00000
+#define MX6Q_SCU_SIZE			0x1000
+#define MX6Q_CCM_BASE_ADDR		0x020c4000
+#define MX6Q_CCM_SIZE			0x4000
+#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
+#define MX6Q_ANATOP_SIZE		0x1000
+#define MX6Q_UART4_BASE_ADDR		0x021f0000
+#define MX6Q_UART4_SIZE			0x4000
+
+#endif	/* __MACH_MX6Q_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mxc.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mxc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/mxc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/mxc.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,20 +50,6 @@
 #define IMX_CHIP_REVISION_3_3		0x33
 #define IMX_CHIP_REVISION_UNKNOWN	0xff
 
-#define IMX_CHIP_REVISION_1_0_STRING		"1.0"
-#define IMX_CHIP_REVISION_1_1_STRING		"1.1"
-#define IMX_CHIP_REVISION_1_2_STRING		"1.2"
-#define IMX_CHIP_REVISION_1_3_STRING		"1.3"
-#define IMX_CHIP_REVISION_2_0_STRING		"2.0"
-#define IMX_CHIP_REVISION_2_1_STRING		"2.1"
-#define IMX_CHIP_REVISION_2_2_STRING		"2.2"
-#define IMX_CHIP_REVISION_2_3_STRING		"2.3"
-#define IMX_CHIP_REVISION_3_0_STRING		"3.0"
-#define IMX_CHIP_REVISION_3_1_STRING		"3.1"
-#define IMX_CHIP_REVISION_3_2_STRING		"3.2"
-#define IMX_CHIP_REVISION_3_3_STRING		"3.3"
-#define IMX_CHIP_REVISION_UNKNOWN_STRING	"unknown"
-
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
@@ -183,13 +169,6 @@ struct cpu_op {
 };
 
 int tzic_enable_wake(int is_idle);
-enum mxc_cpu_pwr_mode {
-	WAIT_CLOCKED,		/* wfi only */
-	WAIT_UNCLOCKED,		/* WAIT */
-	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
-	STOP_POWER_ON,		/* just STOP */
-	STOP_POWER_OFF,		/* STOP + SRPG */
-};
 
 extern struct cpu_op *(*get_cpu_op)(int *op);
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/system.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/system.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,43 +17,9 @@
 #ifndef __ASM_ARCH_MXC_SYSTEM_H__
 #define __ASM_ARCH_MXC_SYSTEM_H__
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
-extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
-
 static inline void arch_idle(void)
 {
-	/* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
-	if (cpu_is_mx31() || cpu_is_mx35()) {
-		unsigned long reg = 0;
-		__asm__ __volatile__(
-			/* disable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"bic %0, %0, #0x00001000\n"
-			"bic %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			/* invalidate I cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c5, 0\n"
-			/* clear and invalidate D cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c14, 0\n"
-			/* WFI */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c0, 4\n"
-			"nop\n" "nop\n" "nop\n" "nop\n"
-			"nop\n" "nop\n" "nop\n"
-			/* enable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"orr %0, %0, #0x00001000\n"
-			"orr %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			: "=r" (reg));
-	} else if (cpu_is_mx51())
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-	else
-		cpu_do_idle();
+	cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,7 @@ static __inline__ void __arch_decomp_set
 	case MACH_TYPE_PCM043:
 	case MACH_TYPE_LILLY1131:
 	case MACH_TYPE_VPR200:
+	case MACH_TYPE_EUKREA_CPUIMX35SD:
 		uart_base = MX3X_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MAGX_ZN5:
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/irq-common.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/irq-common.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/irq-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/irq-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,17 @@
 
 int imx_irq_set_priority(unsigned char irq, unsigned char prio)
 {
-	struct mxc_irq_chip *chip;
-	struct irq_chip *base;
+	struct irq_chip_generic *gc;
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
-	base = irq_get_chip(irq);
-	if (base) {
-		chip = container_of(base, struct mxc_irq_chip, base);
-		if (chip->set_priority)
-			ret = chip->set_priority(irq, prio);
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		exirq = gc->private;
+		if (exirq->set_priority)
+			ret = exirq->set_priority(irq, prio);
 	}
 
 	return ret;
@@ -43,15 +43,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
 	struct irq_chip_generic *gc;
-	int (*set_irq_fiq)(unsigned int, unsigned int);
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
 	gc = irq_get_chip_data(irq);
 	if (gc && gc->private) {
-		set_irq_fiq = gc->private;
-		ret = set_irq_fiq(irq, type);
+		exirq = gc->private;
+		if (exirq->set_irq_fiq)
+			ret = exirq->set_irq_fiq(irq, type);
 	}
 
 	return ret;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/irq-common.h linux-libre-3.2-gnu1/arch/arm/plat-mxc/irq-common.h
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/irq-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/irq-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,9 +19,8 @@
 #ifndef __PLAT_MXC_IRQ_COMMON_H__
 #define __PLAT_MXC_IRQ_COMMON_H__
 
-struct mxc_irq_chip
+struct mxc_extra_irq
 {
-	struct irq_chip	base;
 	int (*set_priority)(unsigned char irq, unsigned char prio);
 	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
 };
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-mxc/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,50 +4,34 @@ source "arch/arm/plat-mxc/devices/Kconfi
 
 menu "Freescale MXC Implementations"
 
-config ARCH_MX50_SUPPORTED
-	bool
-
-config ARCH_MX53_SUPPORTED
-	bool
-
 choice
 	prompt "Freescale CPU family:"
-	default ARCH_MX3
-
-config ARCH_MX1
-	bool "MX1-based"
-	help
-	  This enables support for systems based on the Freescale i.MX1 family
-
-config ARCH_MX2
-	bool "MX2-based"
-	help
-	  This enables support for systems based on the Freescale i.MX2 family
+	default ARCH_IMX_V6_V7
 
-config ARCH_MX25
-	bool "MX25-based"
+config ARCH_IMX_V4_V5
+	bool "i.MX1, i.MX21, i.MX25, i.MX27"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX25 family
+	  This enables support for systems based on the Freescale i.MX ARMv4
+	  and ARMv5 SoCs
 
-config ARCH_MX3
-	bool "MX3-based"
+config ARCH_IMX_V6_V7
+	bool "i.MX3, i.MX6"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX3 family
+	  This enables support for systems based on the Freescale i.MX3 and i.MX6
+	  family.
 
-config ARCH_MX503
-	bool "i.MX50 + i.MX53"
-	select ARCH_MX50_SUPPORTED
-	select ARCH_MX53_SUPPORTED
+config ARCH_MX5
+	bool "i.MX50, i.MX51, i.MX53"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for machines using Freescale's i.MX50 and i.MX51
+	  This enables support for machines using Freescale's i.MX50 and i.MX53
 	  processors.
 
-config ARCH_MX51
-	bool "i.MX51"
-	select ARCH_MX51_SUPPORTED
-	help
-	  This enables support for systems based on the Freescale i.MX51 family
-
 endchoice
 
 source "arch/arm/mach-imx/Kconfig"
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/Makefile linux-libre-3.2-gnu1/arch/arm/plat-mxc/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 # Common support
 obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
 
-# MX51 uses the TZIC interrupt controller, older platforms use AVIC
+obj-$(CONFIG_ARM_GIC) += gic.o
 obj-$(CONFIG_MXC_TZIC) += tzic.o
 obj-$(CONFIG_MXC_AVIC) += avic.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/pwm.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/pwm.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,9 @@
 #define MX3_PWMSAR                0x0C    /* PWM Sample Register */
 #define MX3_PWMPR                 0x10    /* PWM Period Register */
 #define MX3_PWMCR_PRESCALER(x)    (((x - 1) & 0xFFF) << 4)
+#define MX3_PWMCR_DOZEEN                (1 << 24)
+#define MX3_PWMCR_WAITEN                (1 << 23)
+#define MX3_PWMCR_DBGEN			(1 << 22)
 #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
 #define MX3_PWMCR_CLKSRC_IPG      (1 << 16)
 #define MX3_PWMCR_EN              (1 << 0)
@@ -57,7 +60,7 @@ int pwm_config(struct pwm_device *pwm, i
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
+	if (!(cpu_is_mx1() || cpu_is_mx21())) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		u32 cr;
@@ -74,10 +77,21 @@ int pwm_config(struct pwm_device *pwm, i
 		do_div(c, period_ns);
 		duty_cycles = c;
 
+		/*
+		 * according to imx pwm RM, the real period value should be
+		 * PERIOD value in PWMPR plus 2.
+		 */
+		if (period_cycles > 2)
+			period_cycles -= 2;
+		else
+			period_cycles = 0;
+
 		writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR);
 		writel(period_cycles, pwm->mmio_base + MX3_PWMPR);
 
-		cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_EN;
+		cr = MX3_PWMCR_PRESCALER(prescale) |
+			MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
+			MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
 
 		if (cpu_is_mx25())
 			cr |= MX3_PWMCR_CLKSRC_IPG;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/system.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/system.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/system.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -28,6 +29,9 @@
 #include <asm/system.h>
 #include <asm/mach-types.h>
 
+void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+EXPORT_SYMBOL_GPL(imx_ioremap);
+
 static void __iomem *wdog_base;
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-mxc/tzic.c linux-libre-3.2-gnu1/arch/arm/plat-mxc/tzic.c
--- linux-libre-3.1-gnu1/arch/arm/plat-mxc/tzic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-mxc/tzic.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -42,7 +43,7 @@
 #define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
 #define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
 #define TZIC_PND0	0x0D00	/* Pending Register 0 */
-#define TZIC_HIPND0	0x0D80	/* High Priority Pending Register */
+#define TZIC_HIPND(i)	(0x0D80+ ((i) << 2))	/* High Priority Pending Register */
 #define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
 #define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
 #define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
@@ -74,6 +75,12 @@ static int tzic_set_irq_fiq(unsigned int
 
 static unsigned int *wakeup_intr[4];
 
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
 static __init void tzic_init_gc(unsigned int irq_start)
 {
 	struct irq_chip_generic *gc;
@@ -82,7 +89,7 @@ static __init void tzic_init_gc(unsigned
 
 	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
 				    handle_level_irq);
-	gc->private = tzic_set_irq_fiq;
+	gc->private = &tzic_extra_irq;
 	gc->wake_enabled = IRQ_MSK(32);
 	wakeup_intr[idx] = &gc->wake_active;
 
@@ -96,6 +103,28 @@ static __init void tzic_init_gc(unsigned
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+	u32 stat;
+	int i, irqofs, handled;
+
+	do {
+		handled = 0;
+
+		for (i = 0; i < 4; i++) {
+			stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+				__raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+			while (stat) {
+				handled = 1;
+				irqofs = fls(stat) - 1;
+				handle_IRQ(irqofs + i * 32, regs);
+				stat &= ~(1 << irqofs);
+			}
+		}
+	} while (handled);
+}
+
 /*
  * This function initializes the TZIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_PLAT_GPIO_H
-#define __ASM_PLAT_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-/*
- * These currently cause a function call to happen, they may be optimized
- * if needed by adding cpu-specific defines to identify blocks
- * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc)
- */
-#define gpio_get_value  __gpio_get_value
-#define gpio_set_value  __gpio_set_value
-#define gpio_cansleep   __gpio_cansleep
-#define gpio_to_irq     __gpio_to_irq
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT	0x00
-#define NMK_GPIO_DATS	0x04
-#define NMK_GPIO_DATC	0x08
-#define NMK_GPIO_PDIS	0x0c
-#define NMK_GPIO_DIR	0x10
-#define NMK_GPIO_DIRS	0x14
-#define NMK_GPIO_DIRC	0x18
-#define NMK_GPIO_SLPC	0x1c
-#define NMK_GPIO_AFSLA	0x20
-#define NMK_GPIO_AFSLB	0x24
-
-#define NMK_GPIO_RIMSC	0x40
-#define NMK_GPIO_FIMSC	0x44
-#define NMK_GPIO_IS	0x48
-#define NMK_GPIO_IC	0x4c
-#define NMK_GPIO_RWIMSC	0x50
-#define NMK_GPIO_FWIMSC	0x54
-#define NMK_GPIO_WKS	0x58
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO	0
-#define NMK_GPIO_ALT_A	1
-#define NMK_GPIO_ALT_B	2
-#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-	NMK_GPIO_PULL_NONE,
-	NMK_GPIO_PULL_UP,
-	NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-	NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_NOCHANGE,
-	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
-extern int nmk_gpio_get_mode(int gpio);
-
-extern void nmk_gpio_wakeups_suspend(void);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-	char *name;
-	int first_gpio;
-	int first_irq;
-	int num_gpio;
-	u32 (*get_secondary_status)(unsigned int bank);
-	void (*set_ioforce)(bool enable);
-	bool supports_sleepmode;
-};
-
-#endif /* __ASM_PLAT_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * 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 __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT	0x00
+#define NMK_GPIO_DATS	0x04
+#define NMK_GPIO_DATC	0x08
+#define NMK_GPIO_PDIS	0x0c
+#define NMK_GPIO_DIR	0x10
+#define NMK_GPIO_DIRS	0x14
+#define NMK_GPIO_DIRC	0x18
+#define NMK_GPIO_SLPC	0x1c
+#define NMK_GPIO_AFSLA	0x20
+#define NMK_GPIO_AFSLB	0x24
+
+#define NMK_GPIO_RIMSC	0x40
+#define NMK_GPIO_FIMSC	0x44
+#define NMK_GPIO_IS	0x48
+#define NMK_GPIO_IC	0x4c
+#define NMK_GPIO_RWIMSC	0x50
+#define NMK_GPIO_FWIMSC	0x54
+#define NMK_GPIO_WKS	0x58
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO	0
+#define NMK_GPIO_ALT_A	1
+#define NMK_GPIO_ALT_B	2
+#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+	NMK_GPIO_PULL_NONE,
+	NMK_GPIO_PULL_UP,
+	NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+extern int nmk_gpio_get_mode(int gpio);
+
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+	char *name;
+	int first_gpio;
+	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
+	bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/mtu.h linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/mtu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/mtu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/mtu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,54 +1,11 @@
 #ifndef __PLAT_MTU_H
 #define __PLAT_MTU_H
 
-/*
- * Guaranteed runtime conversion range in seconds for
- * the clocksource and clockevent.
- */
-#define MTU_MIN_RANGE 4
-
 /* should be set by the platform code */
 extern void __iomem *mtu_base;
 
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
-#define MTU_RIS		0x04	/* Raw interrupt status */
-#define MTU_MIS		0x08	/* Masked interrupt status */
-#define MTU_ICR		0x0C	/* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
-#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
-#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
-#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
-
-/* bits for the control register */
-#define MTU_CRn_ENA		0x80
-#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK	0x0c
-#define MTU_CRn_PRESCALE_1		0x00
-#define MTU_CRn_PRESCALE_16		0x04
-#define MTU_CRn_PRESCALE_256		0x08
-#define MTU_CRn_32BITS		0x02
-#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR	0xff0
-#define MTU_ITOP	0xff4
-
-#define MTU_PERIPH_ID0	0xfe0
-#define MTU_PERIPH_ID1	0xfe4
-#define MTU_PERIPH_ID2	0xfe8
-#define MTU_PERIPH_ID3	0xfeC
-
-#define MTU_PCELL0	0xff0
-#define MTU_PCELL1	0xff4
-#define MTU_PCELL2	0xff8
-#define MTU_PCELL3	0xffC
+void nmdk_clkevt_reset(void);
+void nmdk_clksrc_reset(void);
 
 #endif /* __PLAT_MTU_H */
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,6 @@
  *		     SLPM value = same as normal
  *
  * PIN_CFG	   - default config with alternate function
- * PIN_CFG_PULL	   - default config with alternate function and pull up/down
  */
 
 typedef unsigned long pin_cfg_t;
@@ -133,10 +132,6 @@ typedef unsigned long pin_cfg_t;
 	(PIN_CFG_DEFAULT |\
 	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
 
-#define PIN_CFG_PULL(num, alt, pull)	\
-	((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
-
 extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
 extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
 extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-nomadik/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,10 +15,16 @@ if PLAT_NOMADIK
 
 config HAS_MTU
 	bool
-	select HAVE_SCHED_CLOCK
 	help
 	  Support for Multi Timer Unit. MTU provides access
 	  to multiple interrupt generating programmable
 	  32-bit free running decrementing counters.
 
+config NOMADIK_MTU_SCHED_CLOCK
+	bool
+	depends on HAS_MTU
+	select HAVE_SCHED_CLOCK
+	help
+	  Use the Multi Timer Unit as the sched_clock.
+
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-nomadik/timer.c linux-libre-3.2-gnu1/arch/arm/plat-nomadik/timer.c
--- linux-libre-3.1-gnu1/arch/arm/plat-nomadik/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-nomadik/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,10 +21,59 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include <plat/mtu.h>
+/*
+ * Guaranteed runtime conversion range in seconds for
+ * the clocksource and clockevent.
+ */
+#define MTU_MIN_RANGE 4
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
+#define MTU_RIS		0x04	/* Raw interrupt status */
+#define MTU_MIS		0x08	/* Masked interrupt status */
+#define MTU_ICR		0x0C	/* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
+#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
+#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
+#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA		0x80
+#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK	0x0c
+#define MTU_CRn_PRESCALE_1		0x00
+#define MTU_CRn_PRESCALE_16		0x04
+#define MTU_CRn_PRESCALE_256		0x08
+#define MTU_CRn_32BITS		0x02
+#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR	0xff0
+#define MTU_ITOP	0xff4
+
+#define MTU_PERIPH_ID0	0xfe0
+#define MTU_PERIPH_ID1	0xfe4
+#define MTU_PERIPH_ID2	0xfe8
+#define MTU_PERIPH_ID3	0xfeC
+
+#define MTU_PCELL0	0xff0
+#define MTU_PCELL1	0xff4
+#define MTU_PCELL2	0xff8
+#define MTU_PCELL3	0xffC
+
+static bool clkevt_periodic;
+static u32 clk_prescale;
+static u32 nmdk_cycle;		/* write-once */
 
 void __iomem *mtu_base; /* Assigned by machine code */
 
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
@@ -48,32 +97,56 @@ static void notrace nomadik_update_sched
 	u32 cyc = -readl(mtu_base + MTU_VAL(0));
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
+#endif
 
 /* Clockevent device: use one-shot mode */
+static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
+{
+	writel(1 << 1, mtu_base + MTU_IMSC);
+	writel(evt, mtu_base + MTU_LR(1));
+	/* Load highest value, enable device, enable interrupts */
+	writel(MTU_CRn_ONESHOT | clk_prescale |
+	       MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(1));
+
+	return 0;
+}
+
+void nmdk_clkevt_reset(void)
+{
+	if (clkevt_periodic) {
+
+		/* Timer: configure load and background-load, and fire it up */
+		writel(nmdk_cycle, mtu_base + MTU_LR(1));
+		writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
+
+		writel(MTU_CRn_PERIODIC | clk_prescale |
+		       MTU_CRn_32BITS | MTU_CRn_ENA,
+		       mtu_base + MTU_CR(1));
+		writel(1 << 1, mtu_base + MTU_IMSC);
+	} else {
+		/* Generate an interrupt to start the clockevent again */
+		(void) nmdk_clkevt_next(nmdk_cycle, NULL);
+	}
+}
+
 static void nmdk_clkevt_mode(enum clock_event_mode mode,
 			     struct clock_event_device *dev)
 {
-	u32 cr;
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		pr_err("%s: periodic mode not supported\n", __func__);
+		clkevt_periodic = true;
+		nmdk_clkevt_reset();
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		/* Load highest value, enable device, enable interrupts */
-		cr = readl(mtu_base + MTU_CR(1));
-		writel(0, mtu_base + MTU_LR(1));
-		writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
-		writel(1 << 1, mtu_base + MTU_IMSC);
+		clkevt_periodic = false;
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		/* disable irq */
 		writel(0, mtu_base + MTU_IMSC);
 		/* disable timer */
-		cr = readl(mtu_base + MTU_CR(1));
-		cr &= ~MTU_CRn_ENA;
-		writel(cr, mtu_base + MTU_CR(1));
+		writel(0, mtu_base + MTU_CR(1));
 		/* load some high default value */
 		writel(0xffffffff, mtu_base + MTU_LR(1));
 		break;
@@ -82,16 +155,9 @@ static void nmdk_clkevt_mode(enum clock_
 	}
 }
 
-static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
-{
-	/* writing the value has immediate effect */
-	writel(evt, mtu_base + MTU_LR(1));
-	return 0;
-}
-
 static struct clock_event_device nmdk_clkevt = {
 	.name		= "mtu_1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
 	.rating		= 200,
 	.set_mode	= nmdk_clkevt_mode,
 	.set_next_event	= nmdk_clkevt_next,
@@ -116,11 +182,23 @@ static struct irqaction nmdk_timer_irq =
 	.dev_id		= &nmdk_clkevt,
 };
 
+void nmdk_clksrc_reset(void)
+{
+	/* Disable */
+	writel(0, mtu_base + MTU_CR(0));
+
+	/* ClockSource: configure load and background-load, and fire it up */
+	writel(nmdk_cycle, mtu_base + MTU_LR(0));
+	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(0));
+}
+
 void __init nmdk_timer_init(void)
 {
 	unsigned long rate;
 	struct clk *clk0;
-	u32 cr = MTU_CRn_32BITS;
 
 	clk0 = clk_get_sys("mtu0", NULL);
 	BUG_ON(IS_ERR(clk0));
@@ -138,30 +216,28 @@ void __init nmdk_timer_init(void)
 	rate = clk_get_rate(clk0);
 	if (rate > 32000000) {
 		rate /= 16;
-		cr |= MTU_CRn_PRESCALE_16;
+		clk_prescale = MTU_CRn_PRESCALE_16;
 	} else {
-		cr |= MTU_CRn_PRESCALE_1;
+		clk_prescale = MTU_CRn_PRESCALE_1;
 	}
 
+	nmdk_cycle = (rate + HZ/2) / HZ;
+
+
 	/* Timer 0 is the free running clocksource */
-	writel(cr, mtu_base + MTU_CR(0));
-	writel(0, mtu_base + MTU_LR(0));
-	writel(0, mtu_base + MTU_BGLR(0));
-	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+	nmdk_clksrc_reset();
 
 	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
 			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
 		       "mtu_0");
-
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
-
+#endif
 	/* Timer 1 is used for events */
 
 	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
 
-	writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
-
 	nmdk_clkevt.max_delta_ns =
 		clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
 	nmdk_clkevt.min_delta_ns =
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/clock.c linux-libre-3.2-gnu1/arch/arm/plat-omap/clock.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/clk.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/debug-devices.c linux-libre-3.2-gnu1/arch/arm/plat-omap/debug-devices.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/debug-devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/debug-devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -18,7 +18,6 @@
 #include <mach/hardware.h>
 
 #include <plat/board.h>
-#include <mach/gpio.h>
 
 
 /* Many OMAP development platforms reuse the same "debug board"; these
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/debug-leds.c linux-libre-3.2-gnu1/arch/arm/plat-omap/debug-leds.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/debug-leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/debug-leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
@@ -19,7 +19,6 @@
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 
 /* Many OMAP development platforms reuse the same "debug board"; these
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/devices.c linux-libre-3.2-gnu1/arch/arm/plat-omap/devices.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,91 +24,9 @@
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 #include <plat/menelaus.h>
-#include <plat/mcbsp.h>
 #include <plat/omap44xx.h>
 
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE)
-
-static struct platform_device **omap_mcbsp_devices;
-
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{
-	int i;
-
-	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
-				     GFP_KERNEL);
-	if (!omap_mcbsp_devices) {
-		printk(KERN_ERR "Could not register McBSP devices\n");
-		return;
-	}
-
-	for (i = 0; i < size; i++) {
-		struct platform_device *new_mcbsp;
-		int ret;
-
-		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
-		if (!new_mcbsp)
-			continue;
-		platform_device_add_resources(new_mcbsp, &res[i * res_count],
-					res_count);
-		new_mcbsp->dev.platform_data = &config[i];
-		ret = platform_device_add(new_mcbsp);
-		if (ret) {
-			platform_device_put(new_mcbsp);
-			continue;
-		}
-		omap_mcbsp_devices[i] = new_mcbsp;
-	}
-}
-
-#else
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{  }
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
-		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
-	{
-		.name		= "mcpdm_mem",
-		.start		= OMAP44XX_MCPDM_BASE,
-		.end		= OMAP44XX_MCPDM_BASE + SZ_4K,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.name		= "mcpdm_irq",
-		.start		= OMAP44XX_IRQ_MCPDM,
-		.end		= OMAP44XX_IRQ_MCPDM,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device omap_mcpdm_device = {
-	.name		= "omap-mcpdm",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(mcpdm_resources),
-	.resource	= mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
-	(void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -291,7 +209,6 @@ static int __init omap_init_devices(void
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_rng();
-	omap_init_mcpdm();
 	omap_init_uwire();
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/dmtimer.c linux-libre-3.2-gnu1/arch/arm/plat-omap/dmtimer.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/dmtimer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/dmtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,12 @@
  *
  * OMAP Dual-Mode Timers
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * OMAP2 support by Juha Yrjola
  * API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,168 +35,81 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
 #include <linux/module.h>
-#include <mach/hardware.h>
-#include <plat/dmtimer.h>
-#include <mach/irqs.h>
-
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
-	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
-	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
-	{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
-	{ .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
-	{ .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
-	{ .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-	{ .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
-	{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
-
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
-
-#else
-#define omap1_dm_timers			NULL
-#define omap1_dm_timer_count		0
-#endif	/* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
-	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
-
-static const char *omap2_dm_source_names[] __initdata = {
-	"sys_ck",
-	"func_32k_ck",
-	"alt_ck",
-	NULL
-};
-
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
-
-#else
-#define omap2_dm_timers			NULL
-#define omap2_dm_timer_count		0
-#define omap2_dm_source_names		NULL
-#define omap2_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
-	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
-
-static const char *omap3_dm_source_names[] __initdata = {
-	"sys_ck",
-	"omap_32k_fck",
-	NULL
-};
-
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
-
-#else
-#define omap3_dm_timers			NULL
-#define omap3_dm_timer_count		0
-#define omap3_dm_source_names		NULL
-#define omap3_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
-	{ .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
-	{ .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
-	{ .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
-	{ .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
-	{ .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
-	{ .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
-	{ .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
-	{ .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
-	{ .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
-	{ .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
-	"sys_clkin_ck",
-	"sys_32k_ck",
-	NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
-
-#else
-#define omap4_dm_timers			NULL
-#define omap4_dm_timer_count		0
-#define omap4_dm_source_names		NULL
-#define omap4_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP4 */
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
 
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
+#include <plat/dmtimer.h>
 
-static spinlock_t dm_timer_lock;
+static LIST_HEAD(omap_timer_list);
+static DEFINE_SPINLOCK(dm_timer_lock);
 
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
  */
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
-	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	return __omap_dm_timer_read(timer, reg, timer->posted);
 }
 
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
  */
 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
-	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	__omap_dm_timer_write(timer, reg, value, timer->posted);
+}
+
+static void omap_timer_restore_context(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
+				timer->context.tiocp_cfg);
+	if (timer->revision > 1)
+		__raw_writel(timer->context.tistat, timer->sys_stat);
+
+	__raw_writel(timer->context.tisr, timer->irq_stat);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
+				timer->context.twer);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
+				timer->context.tcrr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+				timer->context.tldr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
+				timer->context.tmar);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+				timer->context.tsicr);
+	__raw_writel(timer->context.tier, timer->irq_ena);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
+				timer->context.tclr);
 }
 
 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 {
 	int c;
 
+	if (!timer->sys_stat)
+		return;
+
 	c = 0;
-	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+	while (!(__raw_readl(timer->sys_stat) & 1)) {
 		c++;
 		if (c > 100000) {
 			printk(KERN_ERR "Timer failed to reset\n");
@@ -201,53 +120,65 @@ static void omap_dm_timer_wait_for_reset
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
-	int autoidle = 0, wakeup = 0;
-
-	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+	omap_dm_timer_enable(timer);
+	if (timer->pdev->id != 1) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 		omap_dm_timer_wait_for_reset(timer);
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
-	/* Enable autoidle on OMAP2+ */
-	if (cpu_class_is_omap2())
-		autoidle = 1;
 
-	/*
-	 * Enable wake-up on OMAP2 CPUs.
-	 */
-	if (cpu_class_is_omap2())
-		wakeup = 1;
-
-	__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
+	__omap_dm_timer_reset(timer, 0, 0);
+	omap_dm_timer_disable(timer);
 	timer->posted = 1;
 }
 
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	int ret;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return -EINVAL;
+	}
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	timer->posted = 1;
+	return ret;
 }
 
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
-	struct omap_dm_timer *timer = NULL;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
-	int i;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	for (i = 0; i < dm_timer_count; i++) {
-		if (dm_timers[i].reserved)
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
 			continue;
 
-		timer = &dm_timers[i];
+		timer = t;
 		timer->reserved = 1;
 		break;
 	}
+
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	if (timer != NULL)
-		omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer request failed!\n", __func__);
 
 	return timer;
 }
@@ -255,74 +186,65 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request)
 
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
-	struct omap_dm_timer *timer;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
-		spin_unlock_irqrestore(&dm_timer_lock, flags);
-		printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
-		       __FILE__, __LINE__, __func__, id);
-		dump_stack();
-		return NULL;
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
 	}
 
-	timer = &dm_timers[id-1];
-	timer->reserved = 1;
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer%d request failed!\n", __func__, id);
 
 	return timer;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
-void omap_dm_timer_free(struct omap_dm_timer *timer)
+int omap_dm_timer_free(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
-	omap_dm_timer_disable(timer);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	clk_put(timer->fclk);
 
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 
 void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
-	if (timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_enable(timer->fclk);
-		clk_enable(timer->iclk);
-	}
-#endif
-
-	timer->enabled = 1;
+	pm_runtime_get_sync(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
-	if (!timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_disable(timer->iclk);
-		clk_disable(timer->fclk);
-	}
-#endif
-
-	timer->enabled = 0;
+	pm_runtime_put(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
-	return timer->irq;
+	if (timer)
+		return timer->irq;
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 
@@ -334,24 +256,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq)
  */
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
-	int i;
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+	unsigned long flags;
 
 	/* If ARMXOR cannot be idled this function call is unnecessary */
 	if (!(inputmask & (1 << 1)))
 		return inputmask;
 
 	/* If any active timer is using ARMXOR return modified mask */
-	for (i = 0; i < dm_timer_count; i++) {
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node) {
 		u32 l;
 
-		l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 		if (l & OMAP_TIMER_CTRL_ST) {
 			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 				inputmask &= ~(1 << 1);
 			else
 				inputmask &= ~(1 << 2);
 		}
+		i++;
 	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
 	return inputmask;
 }
@@ -361,7 +288,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_i
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-	return timer->fclk;
+	if (timer)
+		return timer->fclk;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
 
@@ -375,70 +304,91 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_i
 
 #endif
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
 
-void omap_dm_timer_start(struct omap_dm_timer *timer)
+int omap_dm_timer_start(struct omap_dm_timer *timer)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (!(l & OMAP_TIMER_CTRL_ST)) {
 		l |= OMAP_TIMER_CTRL_ST;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
+
+	/* Save the context */
+	timer->context.tclr = l;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
+int omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
 	unsigned long rate = 0;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	rate = clk_get_rate(timer->fclk);
-#endif
+	if (unlikely(!timer))
+		return -EINVAL;
 
-	__omap_dm_timer_stop(timer->io_base, timer->posted, rate);
+	if (!pdata->needs_manual_reset)
+		rate = clk_get_rate(timer->fclk);
+
+	__omap_dm_timer_stop(timer, timer->posted, rate);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-#ifdef CONFIG_ARCH_OMAP1
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
-	int n = (timer - dm_timers) << 1;
-	u32 l;
-
-	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
-	l |= source << n;
-	omap_writel(l, MOD_CONF_CTRL_1);
+	int ret;
+	struct dmtimer_platform_data *pdata;
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+	if (unlikely(!timer))
+		return -EINVAL;
 
-#else
+	pdata = timer->pdev->dev.platform_data;
 
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	return __omap_dm_timer_set_source(timer->fclk,
-						dm_source_clocks[source]);
+	ret = pdata->set_timer_src(timer->pdev, source);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
-#endif
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 			    unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload)
 		l |= OMAP_TIMER_CTRL_AR;
@@ -448,15 +398,32 @@ void omap_dm_timer_set_load(struct omap_
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
 
 /* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
                             unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload) {
 		l |= OMAP_TIMER_CTRL_AR;
@@ -466,15 +433,25 @@ void omap_dm_timer_set_load_start(struct
 	}
 	l |= OMAP_TIMER_CTRL_ST;
 
-	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+	__omap_dm_timer_load_start(timer, l, load, timer->posted);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	timer->context.tcrr = load;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 			     unsigned int match)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (enable)
 		l |= OMAP_TIMER_CTRL_CE;
@@ -482,14 +459,24 @@ void omap_dm_timer_set_match(struct omap
 		l &= ~OMAP_TIMER_CTRL_CE;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tmar = match;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
 
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
 	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -499,13 +486,22 @@ void omap_dm_timer_set_pwm(struct omap_d
 		l |= OMAP_TIMER_CTRL_PT;
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
 	if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -513,13 +509,28 @@ void omap_dm_timer_set_prescaler(struct
 		l |= prescaler << 2;
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
 {
-	__omap_dm_timer_int_enable(timer->io_base, value);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+	__omap_dm_timer_int_enable(timer, value);
+
+	/* Save the context */
+	timer->context.tier = value;
+	timer->context.twer = value;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
@@ -527,40 +538,61 @@ unsigned int omap_dm_timer_read_status(s
 {
 	unsigned int l;
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return 0;
+	}
+
+	l = __raw_readl(timer->irq_stat);
 
 	return l;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
-	__omap_dm_timer_write_status(timer->io_base, value);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
+		return -EINVAL;
+
+	__omap_dm_timer_write_status(timer, value);
+	/* Save the context */
+	timer->context.tisr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not iavailable or enabled.\n", __func__);
+		return 0;
+	}
+
+	return __omap_dm_timer_read_counter(timer, timer->posted);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+
+	/* Save the context */
+	timer->context.tcrr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
 int omap_dm_timers_active(void)
 {
-	int i;
-
-	for (i = 0; i < dm_timer_count; i++) {
-		struct omap_dm_timer *timer;
-
-		timer = &dm_timers[i];
+	struct omap_dm_timer *timer;
 
-		if (!timer->enabled)
+	list_for_each_entry(timer, &omap_timer_list, node) {
+		if (!timer->reserved)
 			continue;
 
 		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
@@ -572,69 +604,147 @@ int omap_dm_timers_active(void)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
-static int __init omap_dm_timer_init(void)
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 {
+	int ret;
+	unsigned long flags;
 	struct omap_dm_timer *timer;
-	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
-	if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
 		return -ENODEV;
+	}
 
-	spin_lock_init(&dm_timer_lock);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		return -ENODEV;
+	}
 
-	if (cpu_class_is_omap1()) {
-		dm_timers = omap1_dm_timers;
-		dm_timer_count = omap1_dm_timer_count;
-		map_size = SZ_2K;
-	} else if (cpu_is_omap24xx()) {
-		dm_timers = omap2_dm_timers;
-		dm_timer_count = omap2_dm_timer_count;
-		dm_source_names = omap2_dm_source_names;
-		dm_source_clocks = omap2_dm_source_clocks;
-	} else if (cpu_is_omap34xx()) {
-		dm_timers = omap3_dm_timers;
-		dm_timer_count = omap3_dm_timer_count;
-		dm_source_names = omap3_dm_source_names;
-		dm_source_clocks = omap3_dm_source_clocks;
-	} else if (cpu_is_omap44xx()) {
-		dm_timers = omap4_dm_timers;
-		dm_timer_count = omap4_dm_timer_count;
-		dm_source_names = omap4_dm_source_names;
-		dm_source_clocks = omap4_dm_source_clocks;
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		return -ENODEV;
 	}
 
-	if (cpu_class_is_omap2())
-		for (i = 0; dm_source_names[i] != NULL; i++)
-			dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		return -EBUSY;
+	}
 
-	if (cpu_is_omap243x())
-		dm_timers[0].phys_base = 0x49018000;
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free_ioregion;
+	}
 
-	for (i = 0; i < dm_timer_count; i++) {
-		timer = &dm_timers[i];
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
 
-		/* Static mapping, never released */
-		timer->io_base = ioremap(timer->phys_base, map_size);
-		BUG_ON(!timer->io_base);
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->reserved = pdata->reserved;
+	timer->pdev = pdev;
+	timer->loses_context = pdata->loses_context;
+	timer->get_context_loss_count = pdata->get_context_loss_count;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_class_is_omap2()) {
-			char clk_name[16];
-			sprintf(clk_name, "gpt%d_ick", i + 1);
-			timer->iclk = clk_get(NULL, clk_name);
-			sprintf(clk_name, "gpt%d_fck", i + 1);
-			timer->fclk = clk_get(NULL, clk_name);
-		}
+	/* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset) {
+		pm_runtime_enable(&pdev->dev);
+		pm_runtime_irq_safe(&pdev->dev);
+	}
 
-		/* One or two timers may be set up early for sys_timer */
-		if (sys_timer_reserved & (1  << i)) {
-			timer->reserved = 1;
-			timer->posted = 1;
-		}
-#endif
+	if (!timer->reserved) {
+		pm_runtime_get_sync(&pdev->dev);
+		__omap_dm_timer_init_regs(timer);
+		pm_runtime_put(&pdev->dev);
 	}
 
+	/* add the timer element to the list */
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_add_tail(&timer->node, &omap_timer_list);
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
 	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_free_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return ret;
 }
 
-arch_initcall(omap_dm_timer_init);
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node)
+		if (timer->pdev->id == pdev->id) {
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = __devexit_p(omap_dm_timer_remove),
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/i2c.c linux-libre-3.2-gnu1/arch/arm/plat-omap/i2c.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,6 +108,22 @@ static inline int omap1_i2c_add_bus(int
 	res[1].start = INT_I2C;
 	pdata = &i2c_pdata[bus_id - 1];
 
+	/* all OMAP1 have IP version 1 register set */
+	pdata->rev = OMAP_I2C_IP_VERSION_1;
+
+	/* all OMAP1 I2C are implemented like this */
+	pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
+		       OMAP_I2C_FLAG_SIMPLE_CLOCK |
+		       OMAP_I2C_FLAG_16BIT_DATA_REG |
+		       OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
+
+	/* how the cpu bus is wired up differs for 7xx only */
+
+	if (cpu_is_omap7xx())
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
+	else
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
+
 	return platform_device_register(pdev);
 }
 
@@ -123,21 +139,14 @@ static void omap_pm_set_max_mpu_wakeup_l
 	omap_pm_set_max_mpu_wakeup_lat(dev, t);
 }
 
-static struct omap_device_pm_latency omap_i2c_latency[] = {
-	[0] = {
-		.deactivate_func	= omap_device_idle_hwmods,
-		.activate_func		= omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline int omap2_i2c_add_bus(int bus_id)
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
 	struct omap_i2c_bus_platform_data *pdata;
+	struct omap_i2c_dev_attr *dev_attr;
 
 	omap2_i2c_mux_pins(bus_id);
 
@@ -152,6 +161,16 @@ static inline int omap2_i2c_add_bus(int
 
 	pdata = &i2c_pdata[bus_id - 1];
 	/*
+	 * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
+	 * use, and functionality implementation flags, up to the OMAP I2C
+	 * driver via platform data
+	 */
+	pdata->rev = oh->class->rev;
+
+	dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
+	pdata->flags = dev_attr->flags;
+
+	/*
 	 * When waiting for completion of a i2c transfer, we need to
 	 * set a wake up latency constraint for the MPU. This is to
 	 * ensure quick enough wakeup from idle, when transfer
@@ -160,12 +179,12 @@ static inline int omap2_i2c_add_bus(int
 	 */
 	if (cpu_is_omap34xx())
 		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	od = omap_device_build(name, bus_id, oh, pdata,
+	pdev = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
-			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
-	WARN(IS_ERR(od), "Could not build omap_device for %s\n", name);
+			NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
-	return PTR_ERR(od);
+	return PTR_RET(pdev);
 }
 #else
 static inline int omap2_i2c_add_bus(int bus_id)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/clock.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/clock.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,8 +80,6 @@ struct clkops {
  *
  * @div is the divisor that should be applied to the parent clock's rate
  * to produce the current clock's rate.
- *
- * XXX @flags probably should be replaced with an struct omap_chip.
  */
 struct clksel_rate {
 	u32			val;
@@ -167,8 +165,8 @@ struct dpll_data {
 	u8			auto_recal_bit;
 	u8			recal_en_bit;
 	u8			recal_st_bit;
-	u8			flags;
 #  endif
+	u8			flags;
 };
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/common.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/common.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 
 #include <plat/i2c.h>
+#include <plat/omap_hwmod.h>
 
 struct sys_timer;
 
@@ -45,6 +46,20 @@ extern unsigned long long notrace omap_3
 
 extern void omap_reserve(void);
 
+void omap2420_init_early(void);
+void omap2430_init_early(void);
+void omap3430_init_early(void);
+void omap35xx_init_early(void);
+void omap3630_init_early(void);
+void omap3_init_early(void);	/* Do not use this one */
+void am35xx_init_early(void);
+void ti816x_init_early(void);
+void omap4430_init_early(void);
+
+extern int omap_dss_reset(struct omap_hwmod *);
+
+void omap_sram_init(void);
+
 /*
  * IO bases for various OMAP processors
  * Except the tap base, rest all the io bases
@@ -53,13 +68,13 @@ extern void omap_reserve(void);
 struct omap_globals {
 	u32		class;		/* OMAP class to detect */
 	void __iomem	*tap;		/* Control module ID code */
-	unsigned long   sdrc;           /* SDRAM Controller */
-	unsigned long   sms;            /* SDRAM Memory Scheduler */
-	unsigned long   ctrl;           /* System Control Module */
-	unsigned long   ctrl_pad;	/* PAD Control Module */
-	unsigned long   prm;            /* Power and Reset Management */
-	unsigned long   cm;             /* Clock Management */
-	unsigned long   cm2;
+	void __iomem	*sdrc;           /* SDRAM Controller */
+	void __iomem	*sms;            /* SDRAM Memory Scheduler */
+	void __iomem	*ctrl;           /* System Control Module */
+	void __iomem	*ctrl_pad;	/* PAD Control Module */
+	void __iomem	*prm;            /* Power and Reset Management */
+	void __iomem	*cm;             /* Clock Management */
+	void __iomem	*cm2;
 };
 
 void omap2_set_globals_242x(void);
@@ -74,7 +89,11 @@ void omap2_set_globals_sdrc(struct omap_
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 
+void omap242x_map_io(void);
+void omap243x_map_io(void);
 void omap3_map_io(void);
+void omap4_map_io(void);
+
 
 /**
  * omap_test_timeout - busy-loop, testing a condition
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/cpu.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/cpu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -44,13 +44,6 @@
 
 int omap_type(void);
 
-struct omap_chip_id {
-	u16 oc;
-	u8 type;
-};
-
-#define OMAP_CHIP_INIT(x)	{ .oc = x }
-
 /*
  * omap_rev bits:
  * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
@@ -60,19 +53,6 @@ struct omap_chip_id {
 unsigned int omap_rev(void);
 
 /*
- * Define CPU revision bits
- *
- * Verbose meaning of the revision bits may be different for a silicon
- * family. This difference can be handled separately.
- */
-#define OMAP_REVBITS_00		0x00
-#define OMAP_REVBITS_01		0x01
-#define OMAP_REVBITS_02		0x02
-#define OMAP_REVBITS_03		0x03
-#define OMAP_REVBITS_04		0x04
-#define OMAP_REVBITS_05		0x05
-
-/*
  * Get the CPU revision for OMAP devices
  */
 #define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
@@ -262,7 +242,7 @@ IS_OMAP_TYPE(2422, 0x2422)
 IS_OMAP_TYPE(2423, 0x2423)
 IS_OMAP_TYPE(2430, 0x2430)
 IS_OMAP_TYPE(3430, 0x3430)
-IS_OMAP_TYPE(3505, 0x3505)
+IS_OMAP_TYPE(3505, 0x3517)
 IS_OMAP_TYPE(3517, 0x3517)
 
 #define cpu_is_omap310()		0
@@ -354,8 +334,9 @@ IS_OMAP_TYPE(3517, 0x3517)
 						(!omap3_has_sgx()) &&	\
 						(omap3_has_iva()))
 # define cpu_is_omap3530()		(cpu_is_omap3430())
-# define cpu_is_omap3505()		is_omap3505()
 # define cpu_is_omap3517()		is_omap3517()
+# define cpu_is_omap3505()		(cpu_is_omap3517() &&		\
+						!omap3_has_sgx())
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()		is_omap363x()
 # define cpu_is_ti816x()		is_ti816x()
@@ -379,35 +360,31 @@ IS_OMAP_TYPE(3517, 0x3517)
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS		0x24200024
 #define OMAP2420_REV_ES1_0	OMAP242X_CLASS
-#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))
 
 #define OMAP243X_CLASS		0x24300024
 #define OMAP2430_REV_ES1_0	OMAP243X_CLASS
 
 #define OMAP343X_CLASS		0x34300034
 #define OMAP3430_REV_ES1_0	OMAP343X_CLASS
-#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
-#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
-#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
-#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
+#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
+#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
+#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
+#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))
 
 #define OMAP363X_CLASS		0x36300034
 #define OMAP3630_REV_ES1_0	OMAP363X_CLASS
-#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
+#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))
 
-#define OMAP35XX_CLASS		0x35000034
-#define OMAP3503_REV(v)		(OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
-#define OMAP3515_REV(v)		(OMAP35XX_CLASS | (0x3515 << 16) | (v << 8))
-#define OMAP3525_REV(v)		(OMAP35XX_CLASS | (0x3525 << 16) | (v << 8))
-#define OMAP3530_REV(v)		(OMAP35XX_CLASS | (0x3530 << 16) | (v << 8))
-#define OMAP3505_REV(v)		(OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
-#define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
+#define OMAP3517_CLASS		0x35170034
+#define OMAP3517_REV_ES1_0	OMAP3517_CLASS
+#define OMAP3517_REV_ES1_1	(OMAP3517_CLASS | (0x1 << 8))
 
 #define TI816X_CLASS		0x81600034
 #define TI8168_REV_ES1_0	TI816X_CLASS
-#define TI8168_REV_ES1_1	(TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
 
 #define OMAP443X_CLASS		0x44300044
 #define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
@@ -418,65 +395,17 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP446X_CLASS		0x44600044
 #define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
 
-/*
- * omap_chip bits
- *
- * CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is
- * valid on all chips of that type.  CHIP_IS_OMAP3430ES{1,2} indicates
- * something that is only valid on that particular ES revision.
- *
- * These bits may be ORed together to indicate structures that are
- * available on multiple chip types.
- *
- * To test whether a particular structure matches the current OMAP chip type,
- * use omap_chip_is().
- *
- */
-#define CHIP_IS_OMAP2420		(1 << 0)
-#define CHIP_IS_OMAP2430		(1 << 1)
-#define CHIP_IS_OMAP3430		(1 << 2)
-#define CHIP_IS_OMAP3430ES1		(1 << 3)
-#define CHIP_IS_OMAP3430ES2		(1 << 4)
-#define CHIP_IS_OMAP3430ES3_0		(1 << 5)
-#define CHIP_IS_OMAP3430ES3_1		(1 << 6)
-#define CHIP_IS_OMAP3630ES1		(1 << 7)
-#define CHIP_IS_OMAP4430ES1		(1 << 8)
-#define CHIP_IS_OMAP3630ES1_1           (1 << 9)
-#define CHIP_IS_OMAP3630ES1_2           (1 << 10)
-#define CHIP_IS_OMAP4430ES2		(1 << 11)
-#define CHIP_IS_OMAP4430ES2_1		(1 << 12)
-#define CHIP_IS_OMAP4430ES2_2		(1 << 13)
-#define CHIP_IS_TI816X			(1 << 14)
-#define CHIP_IS_OMAP4460ES1_0		(1 << 15)
-
-#define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
-
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
-					 CHIP_IS_OMAP4430ES2 |		\
-					 CHIP_IS_OMAP4430ES2_1 |	\
-					 CHIP_IS_OMAP4430ES2_2 |	\
-					 CHIP_IS_OMAP4460ES1_0)
-
-/*
- * "GE" here represents "greater than or equal to" in terms of ES
- * levels.  So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430
- * chips at ES2 and beyond, but not, for example, any OMAP lines after
- * OMAP3.
- */
-#define CHIP_GE_OMAP3430ES2		(CHIP_IS_OMAP3430ES2 | \
-					 CHIP_IS_OMAP3430ES3_0 | \
-					 CHIP_GE_OMAP3430ES3_1)
-#define CHIP_GE_OMAP3430ES3_1		(CHIP_IS_OMAP3430ES3_1 | \
-					 CHIP_IS_OMAP3630ES1 | \
-					 CHIP_GE_OMAP3630ES1_1)
-#define CHIP_GE_OMAP3630ES1_1		(CHIP_IS_OMAP3630ES1_1 | \
-					 CHIP_IS_OMAP3630ES1_2)
-
-int omap_chip_is(struct omap_chip_id oci);
 void omap2_check_revision(void);
 
 /*
  * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
  */
 extern u32 omap_features;
 
@@ -488,9 +417,10 @@ extern u32 omap_features;
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
 #define OMAP3_HAS_SDRC			BIT(7)
-#define OMAP4_HAS_MPU_1GHZ		BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
+#define OMAP4_HAS_MPU_1GHZ		BIT(9)
+#define OMAP4_HAS_MPU_1_2GHZ		BIT(10)
+#define OMAP4_HAS_MPU_1_5GHZ		BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
@@ -507,12 +437,11 @@ OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
 
 /*
  * Runtime detection of OMAP4 features
  */
-extern u32 omap_features;
-
 #define OMAP4_HAS_FEATURE(feat, flag)			\
 static inline unsigned int omap4_has_ ##feat(void)	\
 {							\
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/dmtimer.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/dmtimer.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/dmtimer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/dmtimer.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
@@ -59,12 +60,56 @@
  * in OMAP4 can be distinguished.
  */
 #define OMAP_TIMER_IP_VERSION_1                        0x1
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
 struct omap_dm_timer;
 struct clk;
 
+struct timer_regs {
+	u32 tidr;
+	u32 tiocp_cfg;
+	u32 tistat;
+	u32 tisr;
+	u32 tier;
+	u32 twer;
+	u32 tclr;
+	u32 tcrr;
+	u32 tldr;
+	u32 ttrg;
+	u32 twps;
+	u32 tmar;
+	u32 tcar1;
+	u32 tsicr;
+	u32 tcar2;
+	u32 tpir;
+	u32 tnir;
+	u32 tcvr;
+	u32 tocr;
+	u32 towr;
+};
+
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_version;
+	u32 needs_manual_reset:1;
+	bool reserved;
+
+	bool loses_context;
+
+	int (*get_context_loss_count)(struct device *dev);
+};
+
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
+int omap_dm_timer_free(struct omap_dm_timer *timer);
 void omap_dm_timer_enable(struct omap_dm_timer *timer);
 void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
@@ -73,23 +118,23 @@ int omap_dm_timer_get_irq(struct omap_dm
 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
+int omap_dm_timer_trigger(struct omap_dm_timer *timer);
+int omap_dm_timer_start(struct omap_dm_timer *timer);
+int omap_dm_timer_stop(struct omap_dm_timer *timer);
 
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
 
 int omap_dm_timers_active(void);
 
@@ -98,12 +143,30 @@ int omap_dm_timers_active(void);
  * used by dmtimer.c and sys_timer related code.
  */
 
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET		0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
-#define _OMAP_TIMER_STAT_OFFSET		0x18
-#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+/*
+ * The interrupt registers are different between v1 and v2 ip.
+ * These registers are offsets from timer->iobase.
+ */
+#define OMAP_TIMER_ID_OFFSET		0x00
+#define OMAP_TIMER_OCP_CFG_OFFSET	0x10
+
+#define OMAP_TIMER_V1_SYS_STAT_OFFSET	0x14
+#define OMAP_TIMER_V1_STAT_OFFSET	0x18
+#define OMAP_TIMER_V1_INT_EN_OFFSET	0x1c
+
+#define OMAP_TIMER_V2_IRQSTATUS_RAW	0x24
+#define OMAP_TIMER_V2_IRQSTATUS		0x28
+#define OMAP_TIMER_V2_IRQENABLE_SET	0x2c
+#define OMAP_TIMER_V2_IRQENABLE_CLR	0x30
+
+/*
+ * The functional registers have a different base on v1 and v2 ip.
+ * These registers are offsets from timer->func_base. The func_base
+ * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
+ *
+ */
+#define OMAP_TIMER_V2_FUNC_OFFSET		0x14
+
 #define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
 #define _OMAP_TIMER_CTRL_OFFSET		0x24
 #define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
@@ -147,21 +210,6 @@ int omap_dm_timers_active(void);
 /* register offsets with the write pending bit encoded */
 #define	WPSHIFT					16
 
-#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
 #define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
 							| (WP_NONE << WPSHIFT))
 
@@ -209,49 +257,88 @@ int omap_dm_timers_active(void);
 
 struct omap_dm_timer {
 	unsigned long phys_base;
+	int id;
 	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct clk *iclk, *fclk;
-#endif
-	void __iomem *io_base;
+
+	void __iomem	*io_base;
+	void __iomem	*sys_stat;	/* TISTAT timer status */
+	void __iomem	*irq_stat;	/* TISR/IRQSTATUS interrupt status */
+	void __iomem	*irq_ena;	/* irq enable */
+	void __iomem	*irq_dis;	/* irq disable, only on v2 ip */
+	void __iomem	*pend;		/* write pending */
+	void __iomem	*func_base;	/* function register base */
+
 	unsigned long rate;
 	unsigned reserved:1;
-	unsigned enabled:1;
 	unsigned posted:1;
+	struct timer_regs context;
+	bool loses_context;
+	int ctx_loss_count;
+	int revision;
+	struct platform_device *pdev;
+	struct list_head node;
+
+	int (*get_context_loss_count)(struct device *dev);
 };
 
-extern u32 sys_timer_reserved;
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+int omap_dm_timer_prepare(struct omap_dm_timer *timer);
 
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
 						int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	return __raw_readl(base + (reg & 0xff));
+	return __raw_readl(timer->func_base + (reg & 0xff));
 }
 
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
-						int posted)
+static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
+					u32 reg, u32 val, int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	__raw_writel(val, base + (reg & 0xff));
+	__raw_writel(val, timer->func_base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
+{
+	u32 tidr;
+
+	/* Assume v1 ip if bits [31:16] are zero */
+	tidr = __raw_readl(timer->io_base);
+	if (!(tidr >> 16)) {
+		timer->revision = 1;
+		timer->sys_stat = timer->io_base +
+				OMAP_TIMER_V1_SYS_STAT_OFFSET;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
+		timer->irq_dis = 0;
+		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
+		timer->func_base = timer->io_base;
+	} else {
+		timer->revision = 2;
+		timer->sys_stat = 0;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
+		timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
+		timer->pend = timer->io_base +
+			_OMAP_TIMER_WRITE_PEND_OFFSET +
+				OMAP_TIMER_V2_FUNC_OFFSET;
+		timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
+	}
 }
 
 /* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
-						int wakeup)
+static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
+					int autoidle, int wakeup)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+	l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
@@ -261,10 +348,10 @@ static inline void __omap_dm_timer_reset
 	if (wakeup)
 		l |= 1 << 2;
 
-	__omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+	__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 
 	/* Match hardware reset default of posted mode */
-	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
 					OMAP_TIMER_CTRL_POSTED, 0);
 }
 
@@ -286,18 +373,18 @@ static inline int __omap_dm_timer_set_so
 	return ret;
 }
 
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
-						unsigned long rate)
+static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
+					int posted, unsigned long rate)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+	l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 	if (l & OMAP_TIMER_CTRL_ST) {
 		l &= ~0x1;
-		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
+		__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
 #ifdef CONFIG_ARCH_OMAP2PLUS
 		/* Readback to make sure write has completed */
-		__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+		__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 		/*
 		 * Wait for functional clock period x 3.5 to make sure that
 		 * timer is stopped
@@ -307,34 +394,34 @@ static inline void __omap_dm_timer_stop(
 	}
 
 	/* Ack possibly pending interrupt */
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
-					OMAP_TIMER_INT_OVERFLOW, 0);
+	__raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
 }
 
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
-						unsigned int load, int posted)
+static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
+						u32 ctrl, unsigned int load,
+						int posted)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
-	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
 }
 
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
+static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
-	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+	__raw_writel(value, timer->irq_ena);
+	__omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
 }
 
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
-							int posted)
+static inline unsigned int
+__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
 {
-	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+	return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
 }
 
-static inline void __omap_dm_timer_write_status(void __iomem *base,
+static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+	__raw_writel(value, timer->irq_stat);
 }
 
 #endif /* __ASM_ARCH_DMTIMER_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -222,26 +222,6 @@ extern void omap_gpio_restore_context(vo
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
 
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned irq)
 {
 	int tmp;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/io.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/io.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -228,13 +228,13 @@
 
 #define OMAP44XX_EMIF2_PHYS	OMAP44XX_EMIF2_BASE
 						/* 0x4d000000 --> 0xfd200000 */
-#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_EMIF2_SIZE	SZ_1M
+#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF1_VIRT + OMAP44XX_EMIF1_SIZE)
 
 #define OMAP44XX_DMM_PHYS	OMAP44XX_DMM_BASE
 						/* 0x4e000000 --> 0xfd300000 */
-#define OMAP44XX_DMM_VIRT	(OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_DMM_SIZE	SZ_1M
+#define OMAP44XX_DMM_VIRT	(OMAP44XX_EMIF2_VIRT + OMAP44XX_EMIF2_SIZE)
 /*
  * ----------------------------------------------------------------------------
  * Omap specific register access
@@ -247,6 +247,8 @@
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
 
+void omap_ioremap_init(void);
+
 extern u8 omap_readb(u32 pa);
 extern u16 omap_readw(u32 pa);
 extern u32 omap_readl(u32 pa);
@@ -256,8 +258,31 @@ extern void omap_writel(u32 v, u32 pa);
 
 struct omap_sdrc_params;
 
-extern void omap1_map_common_io(void);
-extern void omap1_init_common_hw(void);
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+void omap7xx_map_io(void);
+#else
+static inline void omap_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+void omap15xx_map_io(void);
+#else
+static inline void omap15xx_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+void omap16xx_map_io(void);
+#else
+static inline void omap16xx_map_io(void)
+{
+}
+#endif
+
+void omap1_init_early(void);
 
 #ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
@@ -300,7 +325,7 @@ static inline void omap44xx_map_common_i
 #endif
 
 extern void omap2_init_common_infrastructure(void);
-extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1);
 
 #define __arch_ioremap	omap_ioremap
@@ -309,6 +334,8 @@ extern void omap2_init_common_devices(st
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
 
+extern void __init omap_init_consistent_dma_size(void);
+
 #endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iommu2.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iommu2.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iommu2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iommu2.h	2012-01-04 18:55:44.000000000 -0500
@@ -83,12 +83,12 @@
 /*
  * register accessors
  */
-static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
+static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
 {
 	return __raw_readl(obj->regbase + offs);
 }
 
-static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
+static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
 {
 	__raw_writel(val, obj->regbase + offs);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iommu.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iommu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iommu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iommu.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,16 +25,17 @@ struct iotlb_entry {
 	};
 };
 
-struct iommu {
+struct omap_iommu {
 	const char	*name;
 	struct module	*owner;
 	struct clk	*clk;
 	void __iomem	*regbase;
 	struct device	*dev;
 	void		*isr_priv;
+	struct iommu_domain *domain;
 
 	unsigned int	refcount;
-	struct mutex	iommu_lock;	/* global for this whole object */
+	spinlock_t	iommu_lock;	/* global for this whole object */
 
 	/*
 	 * We don't change iopgd for a situation like pgd for a task,
@@ -48,8 +49,6 @@ struct iommu {
 	struct list_head	mmap;
 	struct mutex		mmap_lock; /* protect mmap */
 
-	int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
-
 	void *ctx; /* iommu context: registres saved area */
 	u32 da_start;
 	u32 da_end;
@@ -81,25 +80,27 @@ struct iotlb_lock {
 struct iommu_functions {
 	unsigned long	version;
 
-	int (*enable)(struct iommu *obj);
-	void (*disable)(struct iommu *obj);
-	void (*set_twl)(struct iommu *obj, bool on);
-	u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+	int (*enable)(struct omap_iommu *obj);
+	void (*disable)(struct omap_iommu *obj);
+	void (*set_twl)(struct omap_iommu *obj, bool on);
+	u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
 
-	void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
-	void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+	void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
+	void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
 
-	struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
+	struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
+							struct iotlb_entry *e);
 	int (*cr_valid)(struct cr_regs *cr);
 	u32 (*cr_to_virt)(struct cr_regs *cr);
 	void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
-	ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
+	ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
+							char *buf);
 
 	u32 (*get_pte_attr)(struct iotlb_entry *e);
 
-	void (*save_ctx)(struct iommu *obj);
-	void (*restore_ctx)(struct iommu *obj);
-	ssize_t (*dump_ctx)(struct iommu *obj, char *buf, ssize_t len);
+	void (*save_ctx)(struct omap_iommu *obj);
+	void (*restore_ctx)(struct omap_iommu *obj);
+	ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
 };
 
 struct iommu_platform_data {
@@ -150,40 +151,31 @@ struct iommu_platform_data {
 /*
  * global functions
  */
-extern u32 iommu_arch_version(void);
-
-extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
-extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
+extern u32 omap_iommu_arch_version(void);
 
-extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
-extern void iommu_set_twl(struct iommu *obj, bool on);
-extern void flush_iotlb_page(struct iommu *obj, u32 da);
-extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
-extern void flush_iotlb_all(struct iommu *obj);
+extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
 
-extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
-extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
-				   u32 **ppte);
-extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
+extern int
+omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
 
-extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
-extern struct iommu *iommu_get(const char *name);
-extern void iommu_put(struct iommu *obj);
-extern int iommu_set_isr(const char *name,
-			 int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+extern int omap_iommu_set_isr(const char *name,
+		 int (*isr)(struct omap_iommu *obj, u32 da, u32 iommu_errs,
 				    void *priv),
 			 void *isr_priv);
 
-extern void iommu_save_ctx(struct iommu *obj);
-extern void iommu_restore_ctx(struct iommu *obj);
+extern void omap_iommu_save_ctx(struct omap_iommu *obj);
+extern void omap_iommu_restore_ctx(struct omap_iommu *obj);
 
-extern int install_iommu_arch(const struct iommu_functions *ops);
-extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+extern int omap_install_iommu_arch(const struct iommu_functions *ops);
+extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
 
-extern int foreach_iommu_device(void *data,
+extern int omap_foreach_iommu_device(void *data,
 				int (*fn)(struct device *, void *));
 
-extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len);
-extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len);
+extern ssize_t
+omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
+extern size_t
+omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
+struct device *omap_find_iommu_device(const char *name);
 
 #endif /* __MACH_IOMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iopgtable.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iopgtable.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iopgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iopgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,120 @@
+/*
+ * omap iommu: pagetable definitions
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_OMAP_IOMMU_H
+#define __PLAT_OMAP_IOMMU_H
+
+/*
+ * "L2 table" address mask and size definitions.
+ */
+#define IOPGD_SHIFT		20
+#define IOPGD_SIZE		(1UL << IOPGD_SHIFT)
+#define IOPGD_MASK		(~(IOPGD_SIZE - 1))
+
+/*
+ * "section" address mask and size definitions.
+ */
+#define IOSECTION_SHIFT		20
+#define IOSECTION_SIZE		(1UL << IOSECTION_SHIFT)
+#define IOSECTION_MASK		(~(IOSECTION_SIZE - 1))
+
+/*
+ * "supersection" address mask and size definitions.
+ */
+#define IOSUPER_SHIFT		24
+#define IOSUPER_SIZE		(1UL << IOSUPER_SHIFT)
+#define IOSUPER_MASK		(~(IOSUPER_SIZE - 1))
+
+#define PTRS_PER_IOPGD		(1UL << (32 - IOPGD_SHIFT))
+#define IOPGD_TABLE_SIZE	(PTRS_PER_IOPGD * sizeof(u32))
+
+/*
+ * "small page" address mask and size definitions.
+ */
+#define IOPTE_SHIFT		12
+#define IOPTE_SIZE		(1UL << IOPTE_SHIFT)
+#define IOPTE_MASK		(~(IOPTE_SIZE - 1))
+
+/*
+ * "large page" address mask and size definitions.
+ */
+#define IOLARGE_SHIFT		16
+#define IOLARGE_SIZE		(1UL << IOLARGE_SHIFT)
+#define IOLARGE_MASK		(~(IOLARGE_SIZE - 1))
+
+#define PTRS_PER_IOPTE		(1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
+#define IOPTE_TABLE_SIZE	(PTRS_PER_IOPTE * sizeof(u32))
+
+#define IOPAGE_MASK		IOPTE_MASK
+
+/**
+ * omap_iommu_translate() - va to pa translation
+ * @d:		omap iommu descriptor
+ * @va:		virtual address
+ * @mask:	omap iommu descriptor mask
+ *
+ * va to pa translation
+ */
+static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
+{
+	return (d & mask) | (va & (~mask));
+}
+
+/*
+ * some descriptor attributes.
+ */
+#define IOPGD_TABLE		(1 << 0)
+#define IOPGD_SECTION		(2 << 0)
+#define IOPGD_SUPER		(1 << 18 | 2 << 0)
+
+#define iopgd_is_table(x)	(((x) & 3) == IOPGD_TABLE)
+#define iopgd_is_section(x)	(((x) & (1 << 18 | 3)) == IOPGD_SECTION)
+#define iopgd_is_super(x)	(((x) & (1 << 18 | 3)) == IOPGD_SUPER)
+
+#define IOPTE_SMALL		(2 << 0)
+#define IOPTE_LARGE		(1 << 0)
+
+#define iopte_is_small(x)	(((x) & 2) == IOPTE_SMALL)
+#define iopte_is_large(x)	(((x) & 3) == IOPTE_LARGE)
+
+/* to find an entry in a page-table-directory */
+#define iopgd_index(da)		(((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
+#define iopgd_offset(obj, da)	((obj)->iopgd + iopgd_index(da))
+
+#define iopgd_page_paddr(iopgd)	(*iopgd & ~((1 << 10) - 1))
+#define iopgd_page_vaddr(iopgd)	((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
+
+/* to find an entry in the second-level page table. */
+#define iopte_index(da)		(((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
+#define iopte_offset(iopgd, da)	(iopgd_page_vaddr(iopgd) + iopte_index(da))
+
+static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
+				   u32 flags)
+{
+	memset(e, 0, sizeof(*e));
+
+	e->da		= da;
+	e->pa		= pa;
+	e->valid	= 1;
+	/* FIXME: add OMAP1 support */
+	e->pgsz		= flags & MMU_CAM_PGSZ_MASK;
+	e->endian	= flags & MMU_RAM_ENDIAN_MASK;
+	e->elsz		= flags & MMU_RAM_ELSZ_MASK;
+	e->mixed	= flags & MMU_RAM_MIXED_MASK;
+
+	return iopgsz_to_bytes(e->pgsz);
+}
+
+#define to_iommu(dev)							\
+	(struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
+#endif /* __PLAT_OMAP_IOMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iovmm.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iovmm.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/iovmm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/iovmm.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,10 @@
 #ifndef __IOMMU_MMAP_H
 #define __IOMMU_MMAP_H
 
+#include <linux/iommu.h>
+
 struct iovm_struct {
-	struct iommu		*iommu;	/* iommu object which this belongs to */
+	struct omap_iommu	*iommu;	/* iommu object which this belongs to */
 	u32			da_start; /* area definition */
 	u32			da_end;
 	u32			flags; /* IOVMF_: see below */
@@ -70,20 +72,18 @@ struct iovm_struct {
 #define IOVMF_DA_FIXED		(1 << (4 + IOVMF_SW_SHIFT))
 
 
-extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
-extern u32 iommu_vmap(struct iommu *obj, u32 da,
+extern struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
 			const struct sg_table *sgt, u32 flags);
-extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
-extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
-			   u32 flags);
-extern void iommu_vfree(struct iommu *obj, const u32 da);
-extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
-			u32 flags);
-extern void iommu_kunmap(struct iommu *obj, u32 da);
-extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
-			   u32 flags);
-extern void iommu_kfree(struct iommu *obj, u32 da);
-
-extern void *da_to_va(struct iommu *obj, u32 da);
+extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain,
+				struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, size_t bytes, u32 flags);
+extern void
+omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+				const u32 da);
+extern void *omap_da_to_va(struct omap_iommu *obj, u32 da);
 
 #endif /* __IOMMU_MMAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/mcbsp.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/mcbsp.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/mcbsp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/mcbsp.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,7 @@
 #define __ASM_ARCH_OMAP_MCBSP_H
 
 #include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <plat/clock.h>
+#include <linux/clk.h>
 
 /* macro for building platform_device for McBSP ports */
 #define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\
@@ -40,104 +38,60 @@ static struct platform_device omap_mcbsp
 #define MCBSP_CONFIG_TYPE3	0x3
 #define MCBSP_CONFIG_TYPE4	0x4
 
-#define OMAP7XX_MCBSP1_BASE	0xfffb1000
-#define OMAP7XX_MCBSP2_BASE	0xfffb1800
-
-#define OMAP1510_MCBSP1_BASE	0xe1011800
-#define OMAP1510_MCBSP2_BASE	0xfffb1000
-#define OMAP1510_MCBSP3_BASE	0xe1017000
-
-#define OMAP1610_MCBSP1_BASE	0xe1011800
-#define OMAP1610_MCBSP2_BASE	0xfffb1000
-#define OMAP1610_MCBSP3_BASE	0xe1017000
-
-#ifdef CONFIG_ARCH_OMAP1
-
-#define OMAP_MCBSP_REG_DRR2	0x00
-#define OMAP_MCBSP_REG_DRR1	0x02
-#define OMAP_MCBSP_REG_DXR2	0x04
-#define OMAP_MCBSP_REG_DXR1	0x06
-#define OMAP_MCBSP_REG_DRR	0x02
-#define OMAP_MCBSP_REG_DXR	0x06
-#define OMAP_MCBSP_REG_SPCR2	0x08
-#define OMAP_MCBSP_REG_SPCR1	0x0a
-#define OMAP_MCBSP_REG_RCR2	0x0c
-#define OMAP_MCBSP_REG_RCR1	0x0e
-#define OMAP_MCBSP_REG_XCR2	0x10
-#define OMAP_MCBSP_REG_XCR1	0x12
-#define OMAP_MCBSP_REG_SRGR2	0x14
-#define OMAP_MCBSP_REG_SRGR1	0x16
-#define OMAP_MCBSP_REG_MCR2	0x18
-#define OMAP_MCBSP_REG_MCR1	0x1a
-#define OMAP_MCBSP_REG_RCERA	0x1c
-#define OMAP_MCBSP_REG_RCERB	0x1e
-#define OMAP_MCBSP_REG_XCERA	0x20
-#define OMAP_MCBSP_REG_XCERB	0x22
-#define OMAP_MCBSP_REG_PCR0	0x24
-#define OMAP_MCBSP_REG_RCERC	0x26
-#define OMAP_MCBSP_REG_RCERD	0x28
-#define OMAP_MCBSP_REG_XCERC	0x2A
-#define OMAP_MCBSP_REG_XCERD	0x2C
-#define OMAP_MCBSP_REG_RCERE	0x2E
-#define OMAP_MCBSP_REG_RCERF	0x30
-#define OMAP_MCBSP_REG_XCERE	0x32
-#define OMAP_MCBSP_REG_XCERF	0x34
-#define OMAP_MCBSP_REG_RCERG	0x36
-#define OMAP_MCBSP_REG_RCERH	0x38
-#define OMAP_MCBSP_REG_XCERG	0x3A
-#define OMAP_MCBSP_REG_XCERH	0x3C
-
-/* Dummy defines, these are not available on omap1 */
-#define OMAP_MCBSP_REG_XCCR	0x00
-#define OMAP_MCBSP_REG_RCCR	0x00
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+	/* Common registers */
+	OMAP_MCBSP_REG_SPCR2 = 4,
+	OMAP_MCBSP_REG_SPCR1,
+	OMAP_MCBSP_REG_RCR2,
+	OMAP_MCBSP_REG_RCR1,
+	OMAP_MCBSP_REG_XCR2,
+	OMAP_MCBSP_REG_XCR1,
+	OMAP_MCBSP_REG_SRGR2,
+	OMAP_MCBSP_REG_SRGR1,
+	OMAP_MCBSP_REG_MCR2,
+	OMAP_MCBSP_REG_MCR1,
+	OMAP_MCBSP_REG_RCERA,
+	OMAP_MCBSP_REG_RCERB,
+	OMAP_MCBSP_REG_XCERA,
+	OMAP_MCBSP_REG_XCERB,
+	OMAP_MCBSP_REG_PCR0,
+	OMAP_MCBSP_REG_RCERC,
+	OMAP_MCBSP_REG_RCERD,
+	OMAP_MCBSP_REG_XCERC,
+	OMAP_MCBSP_REG_XCERD,
+	OMAP_MCBSP_REG_RCERE,
+	OMAP_MCBSP_REG_RCERF,
+	OMAP_MCBSP_REG_XCERE,
+	OMAP_MCBSP_REG_XCERF,
+	OMAP_MCBSP_REG_RCERG,
+	OMAP_MCBSP_REG_RCERH,
+	OMAP_MCBSP_REG_XCERG,
+	OMAP_MCBSP_REG_XCERH,
 
-#else
+	/* OMAP1-OMAP2420 registers */
+	OMAP_MCBSP_REG_DRR2 = 0,
+	OMAP_MCBSP_REG_DRR1,
+	OMAP_MCBSP_REG_DXR2,
+	OMAP_MCBSP_REG_DXR1,
 
-#define OMAP_MCBSP_REG_DRR2	0x00
-#define OMAP_MCBSP_REG_DRR1	0x04
-#define OMAP_MCBSP_REG_DXR2	0x08
-#define OMAP_MCBSP_REG_DXR1	0x0C
-#define OMAP_MCBSP_REG_DRR	0x00
-#define OMAP_MCBSP_REG_DXR	0x08
-#define OMAP_MCBSP_REG_SPCR2	0x10
-#define OMAP_MCBSP_REG_SPCR1	0x14
-#define OMAP_MCBSP_REG_RCR2	0x18
-#define OMAP_MCBSP_REG_RCR1	0x1C
-#define OMAP_MCBSP_REG_XCR2	0x20
-#define OMAP_MCBSP_REG_XCR1	0x24
-#define OMAP_MCBSP_REG_SRGR2	0x28
-#define OMAP_MCBSP_REG_SRGR1	0x2C
-#define OMAP_MCBSP_REG_MCR2	0x30
-#define OMAP_MCBSP_REG_MCR1	0x34
-#define OMAP_MCBSP_REG_RCERA	0x38
-#define OMAP_MCBSP_REG_RCERB	0x3C
-#define OMAP_MCBSP_REG_XCERA	0x40
-#define OMAP_MCBSP_REG_XCERB	0x44
-#define OMAP_MCBSP_REG_PCR0	0x48
-#define OMAP_MCBSP_REG_RCERC	0x4C
-#define OMAP_MCBSP_REG_RCERD	0x50
-#define OMAP_MCBSP_REG_XCERC	0x54
-#define OMAP_MCBSP_REG_XCERD	0x58
-#define OMAP_MCBSP_REG_RCERE	0x5C
-#define OMAP_MCBSP_REG_RCERF	0x60
-#define OMAP_MCBSP_REG_XCERE	0x64
-#define OMAP_MCBSP_REG_XCERF	0x68
-#define OMAP_MCBSP_REG_RCERG	0x6C
-#define OMAP_MCBSP_REG_RCERH	0x70
-#define OMAP_MCBSP_REG_XCERG	0x74
-#define OMAP_MCBSP_REG_XCERH	0x78
-#define OMAP_MCBSP_REG_SYSCON	0x8C
-#define OMAP_MCBSP_REG_THRSH2	0x90
-#define OMAP_MCBSP_REG_THRSH1	0x94
-#define OMAP_MCBSP_REG_IRQST	0xA0
-#define OMAP_MCBSP_REG_IRQEN	0xA4
-#define OMAP_MCBSP_REG_WAKEUPEN	0xA8
-#define OMAP_MCBSP_REG_XCCR	0xAC
-#define OMAP_MCBSP_REG_RCCR	0xB0
-#define OMAP_MCBSP_REG_XBUFFSTAT	0xB4
-#define OMAP_MCBSP_REG_RBUFFSTAT	0xB8
-#define OMAP_MCBSP_REG_SSELCR	0xBC
+	/* OMAP2430 and onwards */
+	OMAP_MCBSP_REG_DRR = 0,
+	OMAP_MCBSP_REG_DXR = 2,
+	OMAP_MCBSP_REG_SYSCON =	35,
+	OMAP_MCBSP_REG_THRSH2,
+	OMAP_MCBSP_REG_THRSH1,
+	OMAP_MCBSP_REG_IRQST = 40,
+	OMAP_MCBSP_REG_IRQEN,
+	OMAP_MCBSP_REG_WAKEUPEN,
+	OMAP_MCBSP_REG_XCCR,
+	OMAP_MCBSP_REG_RCCR,
+	OMAP_MCBSP_REG_XBUFFSTAT,
+	OMAP_MCBSP_REG_RBUFFSTAT,
+	OMAP_MCBSP_REG_SSELCR,
+};
 
+/* OMAP3 sidetone control registers */
 #define OMAP_ST_REG_REV		0x00
 #define OMAP_ST_REG_SYSCONFIG	0x10
 #define OMAP_ST_REG_IRQSTATUS	0x18
@@ -146,8 +100,6 @@ static struct platform_device omap_mcbsp
 #define OMAP_ST_REG_SFIRCR	0x28
 #define OMAP_ST_REG_SSELCR	0x2C
 
-#endif
-
 /************************** McBSP SPCR1 bit definitions ***********************/
 #define RRST			0x0001
 #define RRDY			0x0002
@@ -344,20 +296,20 @@ typedef enum {
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
 	void (*free)(unsigned int);
-	int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
-	unsigned long phys_base;
-	u8 dma_rx_sync, dma_tx_sync;
-	u16 rx_irq, tx_irq;
 	struct omap_mcbsp_ops *ops;
-#ifdef CONFIG_ARCH_OMAP3
-	/* Sidetone block for McBSP 2 and 3 */
-	unsigned long phys_base_st;
-#endif
 	u16 buffer_size;
-	unsigned int mcbsp_config_type;
+	u8 reg_size;
+	u8 reg_step;
+
+	/* McBSP platform and instance specific features */
+	bool has_wakeup; /* Wakeup capability */
+	bool has_ccr; /* Transceiver has configuration control registers */
+	int (*enable_st_clock)(unsigned int, bool);
+	int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
+	int (*mux_signal)(struct device *dev, const char *signal, const char *src);
 };
 
 struct omap_mcbsp_st_data {
@@ -389,14 +341,12 @@ struct omap_mcbsp {
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
 	struct clk *fclk;
-#ifdef CONFIG_ARCH_OMAP3
 	struct omap_mcbsp_st_data *st_data;
 	int dma_op_mode;
 	u16 max_tx_thres;
 	u16 max_rx_thres;
-#endif
 	void *reg_cache;
-	unsigned int mcbsp_config_type;
+	int reg_cache_size;
 };
 
 /**
@@ -408,16 +358,10 @@ struct omap_mcbsp_dev_attr {
 };
 
 extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count, omap_mcbsp_cache_size;
-
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
+extern int omap_mcbsp_count;
 
 int omap_mcbsp_init(void);
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size);
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
-#ifdef CONFIG_ARCH_OMAP3
 void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
 void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
 u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
@@ -426,18 +370,6 @@ u16 omap_mcbsp_get_fifo_size(unsigned in
 u16 omap_mcbsp_get_tx_delay(unsigned int id);
 u16 omap_mcbsp_get_rx_delay(unsigned int id);
 int omap_mcbsp_get_dma_op_mode(unsigned int id);
-#else
-static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_fifo_size(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
-static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
-#endif
 int omap_mcbsp_request(unsigned int id);
 void omap_mcbsp_free(unsigned int id);
 void omap_mcbsp_start(unsigned int id, int tx, int rx);
@@ -453,21 +385,11 @@ void omap2_mcbsp1_mux_fsr_src(u8 mux);
 int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
 int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
 
-#ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
 int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
 int omap_st_enable(unsigned int id);
 int omap_st_disable(unsigned int id);
 int omap_st_is_enabled(unsigned int id);
-#else
-static inline int omap_st_set_chgain(unsigned int id, int channel,
-				     s16 chgain) { return 0; }
-static inline int omap_st_get_chgain(unsigned int id, int channel,
-				     s16 *chgain) { return 0; }
-static inline int omap_st_enable(unsigned int id) { return 0; }
-static inline int omap_st_disable(unsigned int id) { return 0; }
-static inline int omap_st_is_enabled(unsigned int id) {  return 0; }
-#endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/memory.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/memory.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/memory.h
- *
- * Memory map for OMAP-1510 and 1610
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * This file was derived from arch/arm/mach-intergrator/include/mach/memory.h
- * Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#if defined(CONFIG_ARCH_OMAP1)
-#define PLAT_PHYS_OFFSET		UL(0x10000000)
-#else
-#define PLAT_PHYS_OFFSET		UL(0x80000000)
-#endif
-
-/*
- * Bus address is physical address, except for OMAP-1510 Local Bus.
- * OMAP-1510 bus address is translated into a Local Bus address if the
- * OMAP bus type is lbus. We do the address translation based on the
- * device overriding the defaults used in the dma-mapping API.
- * Note that the is_lbus_device() test is not very efficient on 1510
- * because of the strncmp().
- */
-#ifdef CONFIG_ARCH_OMAP15XX
-
-/*
- * OMAP-1510 Local Bus address offset
- */
-#define OMAP1510_LB_OFFSET	UL(0x30000000)
-
-#define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
-#define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)	(cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
-
-#define __arch_pfn_to_dma(dev, pfn)	\
-	({ dma_addr_t __dma = __pfn_to_phys(pfn); \
-	   if (is_lbus_device(dev)) \
-		__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
-	   __dma; })
-
-#define __arch_dma_to_pfn(dev, addr)	\
-	({ dma_addr_t __dma = addr;				\
-	   if (is_lbus_device(dev))				\
-		__dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;	\
-	   __phys_to_pfn(__dma);				\
-	})
-
-#define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
-						lbus_to_virt(addr) : \
-						__phys_to_virt(addr)); })
-
-#define __arch_virt_to_dma(dev, addr)	({ unsigned long __addr = (unsigned long)(addr); \
-					   (dma_addr_t) (is_lbus_device(dev) ? \
-						virt_to_lbus(__addr) : \
-						__virt_to_phys(__addr)); })
-
-#endif	/* CONFIG_ARCH_OMAP15XX */
-
-/* Override the ARM default */
-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-
-#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)
-#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 2
-#endif
-
-#define CONSISTENT_DMA_SIZE \
-	(((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)
-
-#endif
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/mmc.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/mmc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,24 @@
 
 #define OMAP_MMC_MAX_SLOTS	2
 
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
+/*
+ * struct omap_mmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ *    should be set if this is the case.  See for example Section 22.5.3
+ *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ *    don't work correctly on some MMC controller instances on some
+ *    OMAP3 SoCs; this flag should be set if this is the case.  See
+ *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ *    Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
 
 struct omap_mmc_dev_attr {
 	u8 flags;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap-alsa.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap-alsa.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap-alsa.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap-alsa.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/omap-alsa.h
- *
- * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
- *
- * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
- *
- * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
- * Written by Daniel Petrini, David Cohen, Anderson Briglia
- *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History
- *  -------
- *
- *  2005/07/25 INdT-10LE Kernel Team - 	Alsa driver for omap osk,
- *  					original version based in sa1100 driver
- *  					and omap oss driver.
- */
-
-#ifndef __OMAP_ALSA_H
-#define __OMAP_ALSA_H
-
-#include <plat/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <plat/mcbsp.h>
-#include <linux/platform_device.h>
-
-#define DMA_BUF_SIZE	(1024 * 8)
-
-/*
- * Buffer management for alsa and dma
- */
-struct audio_stream {
-	char *id;		/* identification string */
-	int stream_id;		/* numeric identification */
-	int dma_dev;		/* dma number of that device */
-	int *lch;		/* Chain of channels this stream is linked to */
-	char started;		/* to store if the chain was started or not */
-	int dma_q_head;		/* DMA Channel Q Head */
-	int dma_q_tail;		/* DMA Channel Q Tail */
-	char dma_q_count;	/* DMA Channel Q Count */
-	int active:1;		/* we are using this stream for transfer now */
-	int period;		/* current transfer period */
-	int periods;		/* current count of periods registerd in the DMA engine */
-	spinlock_t dma_lock;	/* for locking in DMA operations */
-	struct snd_pcm_substream *stream;	/* the pcm stream */
-	unsigned linked:1;	/* dma channels linked */
-	int offset;		/* store start position of the last period in the alsa buffer */
-	int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
-	int (*hw_stop)(void);   /* interface to stop HW interface, e.g. McBSP */
-};
-
-/*
- * Alsa card structure for aic23
- */
-struct snd_card_omap_codec {
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	long samplerate;
-	struct audio_stream s[2];	/* playback & capture */
-};
-
-/* Codec specific information and function pointers.
- * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
- * are responsible for defining the function pointers.
- */
-struct omap_alsa_codec_config {
-	char 	*name;
-	struct	omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
-	struct	snd_pcm_hw_constraint_list *hw_constraints_rates;
-	struct	snd_pcm_hardware *snd_omap_alsa_playback;
-	struct	snd_pcm_hardware *snd_omap_alsa_capture;
-	void	(*codec_configure_dev)(void);
-	void	(*codec_set_samplerate)(long);
-	void	(*codec_clock_setup)(void);
-	int	(*codec_clock_on)(void);
-	int 	(*codec_clock_off)(void);
-	int	(*get_default_samplerate)(void);
-};
-
-/*********** Mixer function prototypes *************************/
-int snd_omap_mixer(struct snd_card_omap_codec *);
-void snd_omap_init_mixer(void);
-
-#ifdef CONFIG_PM
-void snd_omap_suspend_mixer(void);
-void snd_omap_resume_mixer(void);
-#endif
-
-int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
-int snd_omap_alsa_remove(struct platform_device *pdev);
-#ifdef CONFIG_PM
-int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
-int snd_omap_alsa_resume(struct platform_device *pdev);
-#else
-#define snd_omap_alsa_suspend	NULL
-#define snd_omap_alsa_resume	NULL
-#endif
-
-void callback_omap_alsa_sound_dma(void *);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap_device.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap_device.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap_device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap_device.h	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ extern struct device omap_device_parent;
  *
  */
 struct omap_device {
-	struct platform_device		pdev;
+	struct platform_device		*pdev;
 	struct omap_hwmod		**hwmods;
 	struct omap_device_pm_latency	*pm_lats;
 	u32				dev_wakeup_lat;
@@ -88,31 +88,26 @@ int omap_device_shutdown(struct platform
 
 /* Core code interface */
 
-int omap_device_count_resources(struct omap_device *od);
-int omap_device_fill_resources(struct omap_device *od, struct resource *res);
-
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt, int is_early_device);
 
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **oh, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device);
 
-int omap_device_register(struct omap_device *od);
-int omap_early_device_register(struct omap_device *od);
-
 void __iomem *omap_device_get_rt_va(struct omap_device *od);
+struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
 int omap_device_align_pm_lat(struct platform_device *pdev,
 			     u32 new_wakeup_lat_limit);
 struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
@@ -122,11 +117,6 @@ int omap_device_enable_hwmods(struct oma
 int omap_device_disable_clocks(struct omap_device *od);
 int omap_device_enable_clocks(struct omap_device *od);
 
-static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
-{
-	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
-}
-
 /*
  * Entries should be kept in latency order ascending
  *
@@ -157,6 +147,17 @@ struct omap_device_pm_latency {
 #define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
 
 /* Get omap_device pointer from platform_device pointer */
-#define to_omap_device(x) container_of((x), struct omap_device, pdev)
+static inline struct omap_device *to_omap_device(struct platform_device *pdev)
+{
+	return pdev ? pdev->archdata.od : NULL;
+}
+
+static inline
+void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h	2012-01-04 18:55:44.000000000 -0500
@@ -496,7 +496,6 @@ struct omap_hwmod_class {
  * @_state: internal-use hwmod state
  * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
  * @flags: hwmod flags (documented below)
- * @omap_chip: OMAP chips this hwmod is present on
  * @_lock: spinlock serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
@@ -526,7 +525,6 @@ struct omap_hwmod {
 	char				*clkdm_name;
 	struct clockdomain		*clkdm;
 	char				*vdd_name;
-	struct voltagedomain		*voltdm;
 	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
 	struct omap_hwmod_ocp_if	**slaves;  /* connect to *_TA */
 	void				*dev_attr;
@@ -545,7 +543,6 @@ struct omap_hwmod {
 	u8				_int_flags;
 	u8				_state;
 	u8				_postsetup_state;
-	const struct omap_chip_id	omap_chip;
 };
 
 int omap_hwmod_register(struct omap_hwmod **ohs);
@@ -603,7 +600,7 @@ int omap_hwmod_for_each_by_class(const c
 				 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -342,9 +342,9 @@ unsigned long omap_pm_cpu_get_freq(void)
  * driver must restore device context.   If the number of context losses
  * exceeds the maximum positive integer, the function will wrap to 0 and
  * continue counting.  Returns the number of context losses for this device,
- * or zero upon error.
+ * or negative value upon error.
  */
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+int omap_pm_get_dev_context_loss_count(struct device *dev);
 
 void omap_pm_enable_off_mode(void);
 void omap_pm_disable_off_mode(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/serial.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/serial.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,8 +16,8 @@
 #include <linux/init.h>
 
 /*
- * Memory entry used for the DEBUG_LL UART configuration. See also
- * uncompress.h and debug-macro.S.
+ * Memory entry used for the DEBUG_LL UART configuration, relative to
+ * start of RAM. See also uncompress.h and debug-macro.S.
  *
  * Note that using a memory location for storing the UART configuration
  * has at least two limitations:
@@ -27,7 +27,7 @@
  * 2. We assume printascii is called at least once before paging_init,
  *    and addruart has a chance to read OMAP_UART_INFO
  */
-#define OMAP_UART_INFO		(PLAT_PHYS_OFFSET + 0x3ffc)
+#define OMAP_UART_INFO_OFS	0x3ffc
 
 /* OMAP1 serial ports */
 #define OMAP1_UART1_BASE	0xfffb0000
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/uncompress.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/uncompress.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,13 @@ int uart_shift;
  */
 static void set_omap_uart_info(unsigned char port)
 {
-	*(volatile u32 *)OMAP_UART_INFO = port;
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart_shift & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+	*uart_info = port;
 }
 
 static void putc(int c)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/voltage.h linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/voltage.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/include/plat/voltage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/include/plat/voltage.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Copyright (C) 2011, Texas Instruments, Inc.
+ *
+ * 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_OMAP_VOLTAGE_H
+#define __ARCH_ARM_OMAP_VOLTAGE_H
+
+struct voltagedomain;
+
+struct voltagedomain *voltdm_lookup(const char *name);
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/io.c linux-libre-3.2-gnu1/arch/arm/plat-omap/io.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
 
 #include <plat/omap7xx.h>
 #include <plat/omap1510.h>
@@ -23,11 +24,16 @@
 #define BETWEEN(p,st,sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define XLATE(p,pst,vst)	((void __iomem *)((p) - (pst) + (vst)))
 
+static int initialized;
+
 /*
  * Intercept ioremap() requests for addresses in our fixed mapping regions.
  */
 void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
 {
+
+	WARN(!initialized, "Do not use ioremap before init_early\n");
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (cpu_class_is_omap1()) {
 		if (BETWEEN(p, OMAP1_IO_PHYS, OMAP1_IO_SIZE))
@@ -139,3 +145,15 @@ void omap_iounmap(volatile void __iomem
 		__iounmap(addr);
 }
 EXPORT_SYMBOL(omap_iounmap);
+
+void __init omap_init_consistent_dma_size(void)
+{
+#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+	init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
+#endif
+}
+
+void __init omap_ioremap_init(void)
+{
+	initialized++;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/iommu.c linux-libre-3.2-gnu1/arch/arm/plat-omap/iommu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/iommu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1102 +0,0 @@
-/*
- * omap iommu: tlb and pagetable primitives
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
- *		Paul Mundt and Toshihiro Kobayashi
- *
- * 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/err.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include <asm/cacheflush.h>
-
-#include <plat/iommu.h>
-
-#include "iopgtable.h"
-
-#define for_each_iotlb_cr(obj, n, __i, cr)				\
-	for (__i = 0;							\
-	     (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true);	\
-	     __i++)
-
-/* accommodate the difference between omap1 and omap2/3 */
-static const struct iommu_functions *arch_iommu;
-
-static struct platform_driver omap_iommu_driver;
-static struct kmem_cache *iopte_cachep;
-
-/**
- * install_iommu_arch - Install archtecure specific iommu functions
- * @ops:	a pointer to architecture specific iommu functions
- *
- * There are several kind of iommu algorithm(tlb, pagetable) among
- * omap series. This interface installs such an iommu algorighm.
- **/
-int install_iommu_arch(const struct iommu_functions *ops)
-{
-	if (arch_iommu)
-		return -EBUSY;
-
-	arch_iommu = ops;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(install_iommu_arch);
-
-/**
- * uninstall_iommu_arch - Uninstall archtecure specific iommu functions
- * @ops:	a pointer to architecture specific iommu functions
- *
- * This interface uninstalls the iommu algorighm installed previously.
- **/
-void uninstall_iommu_arch(const struct iommu_functions *ops)
-{
-	if (arch_iommu != ops)
-		pr_err("%s: not your arch\n", __func__);
-
-	arch_iommu = NULL;
-}
-EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
-
-/**
- * iommu_save_ctx - Save registers for pm off-mode support
- * @obj:	target iommu
- **/
-void iommu_save_ctx(struct iommu *obj)
-{
-	arch_iommu->save_ctx(obj);
-}
-EXPORT_SYMBOL_GPL(iommu_save_ctx);
-
-/**
- * iommu_restore_ctx - Restore registers for pm off-mode support
- * @obj:	target iommu
- **/
-void iommu_restore_ctx(struct iommu *obj)
-{
-	arch_iommu->restore_ctx(obj);
-}
-EXPORT_SYMBOL_GPL(iommu_restore_ctx);
-
-/**
- * iommu_arch_version - Return running iommu arch version
- **/
-u32 iommu_arch_version(void)
-{
-	return arch_iommu->version;
-}
-EXPORT_SYMBOL_GPL(iommu_arch_version);
-
-static int iommu_enable(struct iommu *obj)
-{
-	int err;
-
-	if (!obj)
-		return -EINVAL;
-
-	if (!arch_iommu)
-		return -ENODEV;
-
-	clk_enable(obj->clk);
-
-	err = arch_iommu->enable(obj);
-
-	clk_disable(obj->clk);
-	return err;
-}
-
-static void iommu_disable(struct iommu *obj)
-{
-	if (!obj)
-		return;
-
-	clk_enable(obj->clk);
-
-	arch_iommu->disable(obj);
-
-	clk_disable(obj->clk);
-}
-
-/*
- *	TLB operations
- */
-void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
-{
-	BUG_ON(!cr || !e);
-
-	arch_iommu->cr_to_e(cr, e);
-}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_e);
-
-static inline int iotlb_cr_valid(struct cr_regs *cr)
-{
-	if (!cr)
-		return -EINVAL;
-
-	return arch_iommu->cr_valid(cr);
-}
-
-static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
-					     struct iotlb_entry *e)
-{
-	if (!e)
-		return NULL;
-
-	return arch_iommu->alloc_cr(obj, e);
-}
-
-u32 iotlb_cr_to_virt(struct cr_regs *cr)
-{
-	return arch_iommu->cr_to_virt(cr);
-}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_virt);
-
-static u32 get_iopte_attr(struct iotlb_entry *e)
-{
-	return arch_iommu->get_pte_attr(e);
-}
-
-static u32 iommu_report_fault(struct iommu *obj, u32 *da)
-{
-	return arch_iommu->fault_isr(obj, da);
-}
-
-static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
-{
-	u32 val;
-
-	val = iommu_read_reg(obj, MMU_LOCK);
-
-	l->base = MMU_LOCK_BASE(val);
-	l->vict = MMU_LOCK_VICT(val);
-
-}
-
-static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
-{
-	u32 val;
-
-	val = (l->base << MMU_LOCK_BASE_SHIFT);
-	val |= (l->vict << MMU_LOCK_VICT_SHIFT);
-
-	iommu_write_reg(obj, val, MMU_LOCK);
-}
-
-static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
-{
-	arch_iommu->tlb_read_cr(obj, cr);
-}
-
-static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
-{
-	arch_iommu->tlb_load_cr(obj, cr);
-
-	iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
-	iommu_write_reg(obj, 1, MMU_LD_TLB);
-}
-
-/**
- * iotlb_dump_cr - Dump an iommu tlb entry into buf
- * @obj:	target iommu
- * @cr:		contents of cam and ram register
- * @buf:	output buffer
- **/
-static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
-				    char *buf)
-{
-	BUG_ON(!cr || !buf);
-
-	return arch_iommu->dump_cr(obj, cr, buf);
-}
-
-/* only used in iotlb iteration for-loop */
-static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
-{
-	struct cr_regs cr;
-	struct iotlb_lock l;
-
-	iotlb_lock_get(obj, &l);
-	l.vict = n;
-	iotlb_lock_set(obj, &l);
-	iotlb_read_cr(obj, &cr);
-
-	return cr;
-}
-
-/**
- * load_iotlb_entry - Set an iommu tlb entry
- * @obj:	target iommu
- * @e:		an iommu tlb entry info
- **/
-int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
-{
-	int err = 0;
-	struct iotlb_lock l;
-	struct cr_regs *cr;
-
-	if (!obj || !obj->nr_tlb_entries || !e)
-		return -EINVAL;
-
-	clk_enable(obj->clk);
-
-	iotlb_lock_get(obj, &l);
-	if (l.base == obj->nr_tlb_entries) {
-		dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
-		err = -EBUSY;
-		goto out;
-	}
-	if (!e->prsvd) {
-		int i;
-		struct cr_regs tmp;
-
-		for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
-			if (!iotlb_cr_valid(&tmp))
-				break;
-
-		if (i == obj->nr_tlb_entries) {
-			dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
-			err = -EBUSY;
-			goto out;
-		}
-
-		iotlb_lock_get(obj, &l);
-	} else {
-		l.vict = l.base;
-		iotlb_lock_set(obj, &l);
-	}
-
-	cr = iotlb_alloc_cr(obj, e);
-	if (IS_ERR(cr)) {
-		clk_disable(obj->clk);
-		return PTR_ERR(cr);
-	}
-
-	iotlb_load_cr(obj, cr);
-	kfree(cr);
-
-	if (e->prsvd)
-		l.base++;
-	/* increment victim for next tlb load */
-	if (++l.vict == obj->nr_tlb_entries)
-		l.vict = l.base;
-	iotlb_lock_set(obj, &l);
-out:
-	clk_disable(obj->clk);
-	return err;
-}
-EXPORT_SYMBOL_GPL(load_iotlb_entry);
-
-/**
- * flush_iotlb_page - Clear an iommu tlb entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_page(struct iommu *obj, u32 da)
-{
-	int i;
-	struct cr_regs cr;
-
-	clk_enable(obj->clk);
-
-	for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
-		u32 start;
-		size_t bytes;
-
-		if (!iotlb_cr_valid(&cr))
-			continue;
-
-		start = iotlb_cr_to_virt(&cr);
-		bytes = iopgsz_to_bytes(cr.cam & 3);
-
-		if ((start <= da) && (da < start + bytes)) {
-			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
-				__func__, start, da, bytes);
-			iotlb_load_cr(obj, &cr);
-			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
-		}
-	}
-	clk_disable(obj->clk);
-
-	if (i == obj->nr_tlb_entries)
-		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_page);
-
-/**
- * flush_iotlb_range - Clear an iommu tlb entries
- * @obj:	target iommu
- * @start:	iommu device virtual address(start)
- * @end:	iommu device virtual address(end)
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
-{
-	u32 da = start;
-
-	while (da < end) {
-		flush_iotlb_page(obj, da);
-		/* FIXME: Optimize for multiple page size */
-		da += IOPTE_SIZE;
-	}
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_range);
-
-/**
- * flush_iotlb_all - Clear all iommu tlb entries
- * @obj:	target iommu
- **/
-void flush_iotlb_all(struct iommu *obj)
-{
-	struct iotlb_lock l;
-
-	clk_enable(obj->clk);
-
-	l.base = 0;
-	l.vict = 0;
-	iotlb_lock_set(obj, &l);
-
-	iommu_write_reg(obj, 1, MMU_GFLUSH);
-
-	clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_all);
-
-/**
- * iommu_set_twl - enable/disable table walking logic
- * @obj:	target iommu
- * @on:		enable/disable
- *
- * Function used to enable/disable TWL. If one wants to work
- * exclusively with locked TLB entries and receive notifications
- * for TLB miss then call this function to disable TWL.
- */
-void iommu_set_twl(struct iommu *obj, bool on)
-{
-	clk_enable(obj->clk);
-	arch_iommu->set_twl(obj, on);
-	clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(iommu_set_twl);
-
-#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
-
-ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
-{
-	if (!obj || !buf)
-		return -EINVAL;
-
-	clk_enable(obj->clk);
-
-	bytes = arch_iommu->dump_ctx(obj, buf, bytes);
-
-	clk_disable(obj->clk);
-
-	return bytes;
-}
-EXPORT_SYMBOL_GPL(iommu_dump_ctx);
-
-static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
-{
-	int i;
-	struct iotlb_lock saved;
-	struct cr_regs tmp;
-	struct cr_regs *p = crs;
-
-	clk_enable(obj->clk);
-	iotlb_lock_get(obj, &saved);
-
-	for_each_iotlb_cr(obj, num, i, tmp) {
-		if (!iotlb_cr_valid(&tmp))
-			continue;
-		*p++ = tmp;
-	}
-
-	iotlb_lock_set(obj, &saved);
-	clk_disable(obj->clk);
-
-	return  p - crs;
-}
-
-/**
- * dump_tlb_entries - dump cr arrays to given buffer
- * @obj:	target iommu
- * @buf:	output buffer
- **/
-size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t bytes)
-{
-	int i, num;
-	struct cr_regs *cr;
-	char *p = buf;
-
-	num = bytes / sizeof(*cr);
-	num = min(obj->nr_tlb_entries, num);
-
-	cr = kcalloc(num, sizeof(*cr), GFP_KERNEL);
-	if (!cr)
-		return 0;
-
-	num = __dump_tlb_entries(obj, cr, num);
-	for (i = 0; i < num; i++)
-		p += iotlb_dump_cr(obj, cr + i, p);
-	kfree(cr);
-
-	return p - buf;
-}
-EXPORT_SYMBOL_GPL(dump_tlb_entries);
-
-int foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
-{
-	return driver_for_each_device(&omap_iommu_driver.driver,
-				      NULL, data, fn);
-}
-EXPORT_SYMBOL_GPL(foreach_iommu_device);
-
-#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
-
-/*
- *	H/W pagetable operations
- */
-static void flush_iopgd_range(u32 *first, u32 *last)
-{
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
-}
-
-static void flush_iopte_range(u32 *first, u32 *last)
-{
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
-}
-
-static void iopte_free(u32 *iopte)
-{
-	/* Note: freed iopte's must be clean ready for re-use */
-	kmem_cache_free(iopte_cachep, iopte);
-}
-
-static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
-{
-	u32 *iopte;
-
-	/* a table has already existed */
-	if (*iopgd)
-		goto pte_ready;
-
-	/*
-	 * do the allocation outside the page table lock
-	 */
-	spin_unlock(&obj->page_table_lock);
-	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
-	spin_lock(&obj->page_table_lock);
-
-	if (!*iopgd) {
-		if (!iopte)
-			return ERR_PTR(-ENOMEM);
-
-		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
-		flush_iopgd_range(iopgd, iopgd);
-
-		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
-	} else {
-		/* We raced, free the reduniovant table */
-		iopte_free(iopte);
-	}
-
-pte_ready:
-	iopte = iopte_offset(iopgd, da);
-
-	dev_vdbg(obj->dev,
-		 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
-		 __func__, da, iopgd, *iopgd, iopte, *iopte);
-
-	return iopte;
-}
-
-static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-
-	if ((da | pa) & ~IOSECTION_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOSECTION_SIZE);
-		return -EINVAL;
-	}
-
-	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
-	flush_iopgd_range(iopgd, iopgd);
-	return 0;
-}
-
-static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	int i;
-
-	if ((da | pa) & ~IOSUPER_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOSUPER_SIZE);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < 16; i++)
-		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
-	flush_iopgd_range(iopgd, iopgd + 15);
-	return 0;
-}
-
-static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	u32 *iopte = iopte_alloc(obj, iopgd, da);
-
-	if (IS_ERR(iopte))
-		return PTR_ERR(iopte);
-
-	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
-	flush_iopte_range(iopte, iopte);
-
-	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
-		 __func__, da, pa, iopte, *iopte);
-
-	return 0;
-}
-
-static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	u32 *iopte = iopte_alloc(obj, iopgd, da);
-	int i;
-
-	if ((da | pa) & ~IOLARGE_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOLARGE_SIZE);
-		return -EINVAL;
-	}
-
-	if (IS_ERR(iopte))
-		return PTR_ERR(iopte);
-
-	for (i = 0; i < 16; i++)
-		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
-	flush_iopte_range(iopte, iopte + 15);
-	return 0;
-}
-
-static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
-{
-	int (*fn)(struct iommu *, u32, u32, u32);
-	u32 prot;
-	int err;
-
-	if (!obj || !e)
-		return -EINVAL;
-
-	switch (e->pgsz) {
-	case MMU_CAM_PGSZ_16M:
-		fn = iopgd_alloc_super;
-		break;
-	case MMU_CAM_PGSZ_1M:
-		fn = iopgd_alloc_section;
-		break;
-	case MMU_CAM_PGSZ_64K:
-		fn = iopte_alloc_large;
-		break;
-	case MMU_CAM_PGSZ_4K:
-		fn = iopte_alloc_page;
-		break;
-	default:
-		fn = NULL;
-		BUG();
-		break;
-	}
-
-	prot = get_iopte_attr(e);
-
-	spin_lock(&obj->page_table_lock);
-	err = fn(obj, e->da, e->pa, prot);
-	spin_unlock(&obj->page_table_lock);
-
-	return err;
-}
-
-/**
- * iopgtable_store_entry - Make an iommu pte entry
- * @obj:	target iommu
- * @e:		an iommu tlb entry info
- **/
-int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
-{
-	int err;
-
-	flush_iotlb_page(obj, e->da);
-	err = iopgtable_store_entry_core(obj, e);
-#ifdef PREFETCH_IOTLB
-	if (!err)
-		load_iotlb_entry(obj, e);
-#endif
-	return err;
-}
-EXPORT_SYMBOL_GPL(iopgtable_store_entry);
-
-/**
- * iopgtable_lookup_entry - Lookup an iommu pte entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- * @ppgd:	iommu pgd entry pointer to be returned
- * @ppte:	iommu pte entry pointer to be returned
- **/
-void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
-{
-	u32 *iopgd, *iopte = NULL;
-
-	iopgd = iopgd_offset(obj, da);
-	if (!*iopgd)
-		goto out;
-
-	if (iopgd_is_table(*iopgd))
-		iopte = iopte_offset(iopgd, da);
-out:
-	*ppgd = iopgd;
-	*ppte = iopte;
-}
-EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
-
-static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
-{
-	size_t bytes;
-	u32 *iopgd = iopgd_offset(obj, da);
-	int nent = 1;
-
-	if (!*iopgd)
-		return 0;
-
-	if (iopgd_is_table(*iopgd)) {
-		int i;
-		u32 *iopte = iopte_offset(iopgd, da);
-
-		bytes = IOPTE_SIZE;
-		if (*iopte & IOPTE_LARGE) {
-			nent *= 16;
-			/* rewind to the 1st entry */
-			iopte = iopte_offset(iopgd, (da & IOLARGE_MASK));
-		}
-		bytes *= nent;
-		memset(iopte, 0, nent * sizeof(*iopte));
-		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
-
-		/*
-		 * do table walk to check if this table is necessary or not
-		 */
-		iopte = iopte_offset(iopgd, 0);
-		for (i = 0; i < PTRS_PER_IOPTE; i++)
-			if (iopte[i])
-				goto out;
-
-		iopte_free(iopte);
-		nent = 1; /* for the next L1 entry */
-	} else {
-		bytes = IOPGD_SIZE;
-		if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
-			nent *= 16;
-			/* rewind to the 1st entry */
-			iopgd = iopgd_offset(obj, (da & IOSUPER_MASK));
-		}
-		bytes *= nent;
-	}
-	memset(iopgd, 0, nent * sizeof(*iopgd));
-	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
-out:
-	return bytes;
-}
-
-/**
- * iopgtable_clear_entry - Remove an iommu pte entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- **/
-size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
-{
-	size_t bytes;
-
-	spin_lock(&obj->page_table_lock);
-
-	bytes = iopgtable_clear_entry_core(obj, da);
-	flush_iotlb_page(obj, da);
-
-	spin_unlock(&obj->page_table_lock);
-
-	return bytes;
-}
-EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
-
-static void iopgtable_clear_entry_all(struct iommu *obj)
-{
-	int i;
-
-	spin_lock(&obj->page_table_lock);
-
-	for (i = 0; i < PTRS_PER_IOPGD; i++) {
-		u32 da;
-		u32 *iopgd;
-
-		da = i << IOPGD_SHIFT;
-		iopgd = iopgd_offset(obj, da);
-
-		if (!*iopgd)
-			continue;
-
-		if (iopgd_is_table(*iopgd))
-			iopte_free(iopte_offset(iopgd, 0));
-
-		*iopgd = 0;
-		flush_iopgd_range(iopgd, iopgd);
-	}
-
-	flush_iotlb_all(obj);
-
-	spin_unlock(&obj->page_table_lock);
-}
-
-/*
- *	Device IOMMU generic operations
- */
-static irqreturn_t iommu_fault_handler(int irq, void *data)
-{
-	u32 da, errs;
-	u32 *iopgd, *iopte;
-	struct iommu *obj = data;
-
-	if (!obj->refcount)
-		return IRQ_NONE;
-
-	clk_enable(obj->clk);
-	errs = iommu_report_fault(obj, &da);
-	clk_disable(obj->clk);
-	if (errs == 0)
-		return IRQ_HANDLED;
-
-	/* Fault callback or TLB/PTE Dynamic loading */
-	if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
-		return IRQ_HANDLED;
-
-	iommu_disable(obj);
-
-	iopgd = iopgd_offset(obj, da);
-
-	if (!iopgd_is_table(*iopgd)) {
-		dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
-			"*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd);
-		return IRQ_NONE;
-	}
-
-	iopte = iopte_offset(iopgd, da);
-
-	dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
-		"pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
-		iopte, *iopte);
-
-	return IRQ_NONE;
-}
-
-static int device_match_by_alias(struct device *dev, void *data)
-{
-	struct iommu *obj = to_iommu(dev);
-	const char *name = data;
-
-	pr_debug("%s: %s %s\n", __func__, obj->name, name);
-
-	return strcmp(obj->name, name) == 0;
-}
-
-/**
- * iommu_set_da_range - Set a valid device address range
- * @obj:		target iommu
- * @start		Start of valid range
- * @end			End of valid range
- **/
-int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
-{
-
-	if (!obj)
-		return -EFAULT;
-
-	if (end < start || !PAGE_ALIGN(start | end))
-		return -EINVAL;
-
-	obj->da_start = start;
-	obj->da_end = end;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(iommu_set_da_range);
-
-/**
- * iommu_get - Get iommu handler
- * @name:	target iommu name
- **/
-struct iommu *iommu_get(const char *name)
-{
-	int err = -ENOMEM;
-	struct device *dev;
-	struct iommu *obj;
-
-	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
-				 device_match_by_alias);
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	obj = to_iommu(dev);
-
-	mutex_lock(&obj->iommu_lock);
-
-	if (obj->refcount++ == 0) {
-		err = iommu_enable(obj);
-		if (err)
-			goto err_enable;
-		flush_iotlb_all(obj);
-	}
-
-	if (!try_module_get(obj->owner))
-		goto err_module;
-
-	mutex_unlock(&obj->iommu_lock);
-
-	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-	return obj;
-
-err_module:
-	if (obj->refcount == 1)
-		iommu_disable(obj);
-err_enable:
-	obj->refcount--;
-	mutex_unlock(&obj->iommu_lock);
-	return ERR_PTR(err);
-}
-EXPORT_SYMBOL_GPL(iommu_get);
-
-/**
- * iommu_put - Put back iommu handler
- * @obj:	target iommu
- **/
-void iommu_put(struct iommu *obj)
-{
-	if (!obj || IS_ERR(obj))
-		return;
-
-	mutex_lock(&obj->iommu_lock);
-
-	if (--obj->refcount == 0)
-		iommu_disable(obj);
-
-	module_put(obj->owner);
-
-	mutex_unlock(&obj->iommu_lock);
-
-	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-}
-EXPORT_SYMBOL_GPL(iommu_put);
-
-int iommu_set_isr(const char *name,
-		  int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
-			     void *priv),
-		  void *isr_priv)
-{
-	struct device *dev;
-	struct iommu *obj;
-
-	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
-				 device_match_by_alias);
-	if (!dev)
-		return -ENODEV;
-
-	obj = to_iommu(dev);
-	mutex_lock(&obj->iommu_lock);
-	if (obj->refcount != 0) {
-		mutex_unlock(&obj->iommu_lock);
-		return -EBUSY;
-	}
-	obj->isr = isr;
-	obj->isr_priv = isr_priv;
-	mutex_unlock(&obj->iommu_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(iommu_set_isr);
-
-/*
- *	OMAP Device MMU(IOMMU) detection
- */
-static int __devinit omap_iommu_probe(struct platform_device *pdev)
-{
-	int err = -ENODEV;
-	void *p;
-	int irq;
-	struct iommu *obj;
-	struct resource *res;
-	struct iommu_platform_data *pdata = pdev->dev.platform_data;
-
-	if (pdev->num_resources != 2)
-		return -EINVAL;
-
-	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
-	if (!obj)
-		return -ENOMEM;
-
-	obj->clk = clk_get(&pdev->dev, pdata->clk_name);
-	if (IS_ERR(obj->clk))
-		goto err_clk;
-
-	obj->nr_tlb_entries = pdata->nr_tlb_entries;
-	obj->name = pdata->name;
-	obj->dev = &pdev->dev;
-	obj->ctx = (void *)obj + sizeof(*obj);
-	obj->da_start = pdata->da_start;
-	obj->da_end = pdata->da_end;
-
-	mutex_init(&obj->iommu_lock);
-	mutex_init(&obj->mmap_lock);
-	spin_lock_init(&obj->page_table_lock);
-	INIT_LIST_HEAD(&obj->mmap);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		err = -ENODEV;
-		goto err_mem;
-	}
-
-	res = request_mem_region(res->start, resource_size(res),
-				 dev_name(&pdev->dev));
-	if (!res) {
-		err = -EIO;
-		goto err_mem;
-	}
-
-	obj->regbase = ioremap(res->start, resource_size(res));
-	if (!obj->regbase) {
-		err = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		err = -ENODEV;
-		goto err_irq;
-	}
-	err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
-			  dev_name(&pdev->dev), obj);
-	if (err < 0)
-		goto err_irq;
-	platform_set_drvdata(pdev, obj);
-
-	p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
-	if (!p) {
-		err = -ENOMEM;
-		goto err_pgd;
-	}
-	memset(p, 0, IOPGD_TABLE_SIZE);
-	clean_dcache_area(p, IOPGD_TABLE_SIZE);
-	obj->iopgd = p;
-
-	BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
-
-	dev_info(&pdev->dev, "%s registered\n", obj->name);
-	return 0;
-
-err_pgd:
-	free_irq(irq, obj);
-err_irq:
-	iounmap(obj->regbase);
-err_ioremap:
-	release_mem_region(res->start, resource_size(res));
-err_mem:
-	clk_put(obj->clk);
-err_clk:
-	kfree(obj);
-	return err;
-}
-
-static int __devexit omap_iommu_remove(struct platform_device *pdev)
-{
-	int irq;
-	struct resource *res;
-	struct iommu *obj = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	iopgtable_clear_entry_all(obj);
-	free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
-
-	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, obj);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	iounmap(obj->regbase);
-
-	clk_put(obj->clk);
-	dev_info(&pdev->dev, "%s removed\n", obj->name);
-	kfree(obj);
-	return 0;
-}
-
-static struct platform_driver omap_iommu_driver = {
-	.probe	= omap_iommu_probe,
-	.remove	= __devexit_p(omap_iommu_remove),
-	.driver	= {
-		.name	= "omap-iommu",
-	},
-};
-
-static void iopte_cachep_ctor(void *iopte)
-{
-	clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
-}
-
-static int __init omap_iommu_init(void)
-{
-	struct kmem_cache *p;
-	const unsigned long flags = SLAB_HWCACHE_ALIGN;
-	size_t align = 1 << 10; /* L2 pagetable alignement */
-
-	p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
-			      iopte_cachep_ctor);
-	if (!p)
-		return -ENOMEM;
-	iopte_cachep = p;
-
-	return platform_driver_register(&omap_iommu_driver);
-}
-module_init(omap_iommu_init);
-
-static void __exit omap_iommu_exit(void)
-{
-	kmem_cache_destroy(iopte_cachep);
-
-	platform_driver_unregister(&omap_iommu_driver);
-}
-module_exit(omap_iommu_exit);
-
-MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
-MODULE_ALIAS("platform:omap-iommu");
-MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
-MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/iommu-debug.c linux-libre-3.2-gnu1/arch/arm/plat-omap/iommu-debug.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/iommu-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/iommu-debug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,418 +0,0 @@
-/*
- * omap iommu: debugfs interface
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-
-#include "iopgtable.h"
-
-#define MAXCOLUMN 100 /* for short messages */
-
-static DEFINE_MUTEX(iommu_debug_lock);
-
-static struct dentry *iommu_debug_root;
-
-static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	u32 ver = iommu_arch_version();
-	char buf[MAXCOLUMN], *p = buf;
-
-	p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
-
-	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-}
-
-static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	ssize_t bytes;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	bytes = iommu_dump_ctx(obj, p, count);
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
-
-	mutex_unlock(&iommu_debug_lock);
-	kfree(buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	ssize_t bytes, rest;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
-	p += sprintf(p, "-----------------------------------------\n");
-	rest = count - (p - buf);
-	p += dump_tlb_entries(obj, p, rest);
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	kfree(buf);
-
-	return bytes;
-}
-
-static ssize_t debug_write_pagetable(struct file *file,
-		     const char __user *userbuf, size_t count, loff_t *ppos)
-{
-	struct iotlb_entry e;
-	struct cr_regs cr;
-	int err;
-	struct iommu *obj = file->private_data;
-	char buf[MAXCOLUMN], *p = buf;
-
-	count = min(count, sizeof(buf));
-
-	mutex_lock(&iommu_debug_lock);
-	if (copy_from_user(p, userbuf, count)) {
-		mutex_unlock(&iommu_debug_lock);
-		return -EFAULT;
-	}
-
-	sscanf(p, "%x %x", &cr.cam, &cr.ram);
-	if (!cr.cam || !cr.ram) {
-		mutex_unlock(&iommu_debug_lock);
-		return -EINVAL;
-	}
-
-	iotlb_cr_to_e(&cr, &e);
-	err = iopgtable_store_entry(obj, &e);
-	if (err)
-		dev_err(obj->dev, "%s: fail to store cr\n", __func__);
-
-	mutex_unlock(&iommu_debug_lock);
-	return count;
-}
-
-#define dump_ioptable_entry_one(lv, da, val)			\
-	({							\
-		int __err = 0;					\
-		ssize_t bytes;					\
-		const int maxcol = 22;				\
-		const char *str = "%d: %08x %08x\n";		\
-		bytes = snprintf(p, maxcol, str, lv, da, val);	\
-		p += bytes;					\
-		len -= bytes;					\
-		if (len < maxcol)				\
-			__err = -ENOMEM;			\
-		__err;						\
-	})
-
-static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len)
-{
-	int i;
-	u32 *iopgd;
-	char *p = buf;
-
-	spin_lock(&obj->page_table_lock);
-
-	iopgd = iopgd_offset(obj, 0);
-	for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
-		int j, err;
-		u32 *iopte;
-		u32 da;
-
-		if (!*iopgd)
-			continue;
-
-		if (!(*iopgd & IOPGD_TABLE)) {
-			da = i << IOPGD_SHIFT;
-
-			err = dump_ioptable_entry_one(1, da, *iopgd);
-			if (err)
-				goto out;
-			continue;
-		}
-
-		iopte = iopte_offset(iopgd, 0);
-
-		for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
-			if (!*iopte)
-				continue;
-
-			da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
-			err = dump_ioptable_entry_one(2, da, *iopgd);
-			if (err)
-				goto out;
-		}
-	}
-out:
-	spin_unlock(&obj->page_table_lock);
-
-	return p - buf;
-}
-
-static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
-				    size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	size_t bytes;
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	p += sprintf(p, "L: %8s %8s\n", "da:", "pa:");
-	p += sprintf(p, "-----------------------------------------\n");
-
-	mutex_lock(&iommu_debug_lock);
-
-	bytes = PAGE_SIZE - (p - buf);
-	p += dump_ioptable(obj, p, bytes);
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	struct iovm_struct *tmp;
-	int uninitialized_var(i);
-	ssize_t bytes;
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
-		     "No", "start", "end", "size", "flags");
-	p += sprintf(p, "-------------------------------------------------\n");
-
-	mutex_lock(&iommu_debug_lock);
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		size_t len;
-		const char *str = "%3d %08x-%08x %6x %8x\n";
-		const int maxcol = 39;
-
-		len = tmp->da_end - tmp->da_start;
-		p += snprintf(p, maxcol, str,
-			      i, tmp->da_start, tmp->da_end, len, tmp->flags);
-
-		if (PAGE_SIZE - (p - buf) < maxcol)
-			break;
-		i++;
-	}
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	struct iovm_struct *area;
-	ssize_t bytes;
-
-	count = min_t(ssize_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	area = find_iovm_area(obj, (u32)ppos);
-	if (IS_ERR(area)) {
-		bytes = -EINVAL;
-		goto err_out;
-	}
-	memcpy(p, area->va, count);
-	p += count;
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	struct iovm_struct *area;
-	char *p, *buf;
-
-	count = min_t(size_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	if (copy_from_user(p, userbuf, count)) {
-		count =  -EFAULT;
-		goto err_out;
-	}
-
-	area = find_iovm_area(obj, (u32)ppos);
-	if (IS_ERR(area)) {
-		count = -EINVAL;
-		goto err_out;
-	}
-	memcpy(area->va, p, count);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return count;
-}
-
-static int debug_open_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-#define DEBUG_FOPS(name)						\
-	static const struct file_operations debug_##name##_fops = {	\
-		.open = debug_open_generic,				\
-		.read = debug_read_##name,				\
-		.write = debug_write_##name,				\
-		.llseek = generic_file_llseek,				\
-	};
-
-#define DEBUG_FOPS_RO(name)						\
-	static const struct file_operations debug_##name##_fops = {	\
-		.open = debug_open_generic,				\
-		.read = debug_read_##name,				\
-		.llseek = generic_file_llseek,				\
-	};
-
-DEBUG_FOPS_RO(ver);
-DEBUG_FOPS_RO(regs);
-DEBUG_FOPS_RO(tlb);
-DEBUG_FOPS(pagetable);
-DEBUG_FOPS_RO(mmap);
-DEBUG_FOPS(mem);
-
-#define __DEBUG_ADD_FILE(attr, mode)					\
-	{								\
-		struct dentry *dent;					\
-		dent = debugfs_create_file(#attr, mode, parent,		\
-					   obj, &debug_##attr##_fops);	\
-		if (!dent)						\
-			return -ENOMEM;					\
-	}
-
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
-#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
-
-static int iommu_debug_register(struct device *dev, void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct iommu *obj = platform_get_drvdata(pdev);
-	struct dentry *d, *parent;
-
-	if (!obj || !obj->dev)
-		return -EINVAL;
-
-	d = debugfs_create_dir(obj->name, iommu_debug_root);
-	if (!d)
-		return -ENOMEM;
-	parent = d;
-
-	d = debugfs_create_u8("nr_tlb_entries", 400, parent,
-			      (u8 *)&obj->nr_tlb_entries);
-	if (!d)
-		return -ENOMEM;
-
-	DEBUG_ADD_FILE_RO(ver);
-	DEBUG_ADD_FILE_RO(regs);
-	DEBUG_ADD_FILE_RO(tlb);
-	DEBUG_ADD_FILE(pagetable);
-	DEBUG_ADD_FILE_RO(mmap);
-	DEBUG_ADD_FILE(mem);
-
-	return 0;
-}
-
-static int __init iommu_debug_init(void)
-{
-	struct dentry *d;
-	int err;
-
-	d = debugfs_create_dir("iommu", NULL);
-	if (!d)
-		return -ENOMEM;
-	iommu_debug_root = d;
-
-	err = foreach_iommu_device(d, iommu_debug_register);
-	if (err)
-		goto err_out;
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(iommu_debug_root);
-	return err;
-}
-module_init(iommu_debug_init)
-
-static void __exit iommu_debugfs_exit(void)
-{
-	debugfs_remove_recursive(iommu_debug_root);
-}
-module_exit(iommu_debugfs_exit)
-
-MODULE_DESCRIPTION("omap iommu: debugfs interface");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/iopgtable.h linux-libre-3.2-gnu1/arch/arm/plat-omap/iopgtable.h
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/iopgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/iopgtable.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * omap iommu: pagetable definitions
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_OMAP_IOMMU_H
-#define __PLAT_OMAP_IOMMU_H
-
-/*
- * "L2 table" address mask and size definitions.
- */
-#define IOPGD_SHIFT		20
-#define IOPGD_SIZE		(1UL << IOPGD_SHIFT)
-#define IOPGD_MASK		(~(IOPGD_SIZE - 1))
-
-/*
- * "section" address mask and size definitions.
- */
-#define IOSECTION_SHIFT		20
-#define IOSECTION_SIZE		(1UL << IOSECTION_SHIFT)
-#define IOSECTION_MASK		(~(IOSECTION_SIZE - 1))
-
-/*
- * "supersection" address mask and size definitions.
- */
-#define IOSUPER_SHIFT		24
-#define IOSUPER_SIZE		(1UL << IOSUPER_SHIFT)
-#define IOSUPER_MASK		(~(IOSUPER_SIZE - 1))
-
-#define PTRS_PER_IOPGD		(1UL << (32 - IOPGD_SHIFT))
-#define IOPGD_TABLE_SIZE	(PTRS_PER_IOPGD * sizeof(u32))
-
-/*
- * "small page" address mask and size definitions.
- */
-#define IOPTE_SHIFT		12
-#define IOPTE_SIZE		(1UL << IOPTE_SHIFT)
-#define IOPTE_MASK		(~(IOPTE_SIZE - 1))
-
-/*
- * "large page" address mask and size definitions.
- */
-#define IOLARGE_SHIFT		16
-#define IOLARGE_SIZE		(1UL << IOLARGE_SHIFT)
-#define IOLARGE_MASK		(~(IOLARGE_SIZE - 1))
-
-#define PTRS_PER_IOPTE		(1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
-#define IOPTE_TABLE_SIZE	(PTRS_PER_IOPTE * sizeof(u32))
-
-#define IOPAGE_MASK		IOPTE_MASK
-
-/*
- * some descriptor attributes.
- */
-#define IOPGD_TABLE		(1 << 0)
-#define IOPGD_SECTION		(2 << 0)
-#define IOPGD_SUPER		(1 << 18 | 2 << 0)
-
-#define iopgd_is_table(x)	(((x) & 3) == IOPGD_TABLE)
-
-#define IOPTE_SMALL		(2 << 0)
-#define IOPTE_LARGE		(1 << 0)
-
-/* to find an entry in a page-table-directory */
-#define iopgd_index(da)		(((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
-#define iopgd_offset(obj, da)	((obj)->iopgd + iopgd_index(da))
-
-#define iopgd_page_paddr(iopgd)	(*iopgd & ~((1 << 10) - 1))
-#define iopgd_page_vaddr(iopgd)	((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
-
-/* to find an entry in the second-level page table. */
-#define iopte_index(da)		(((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
-#define iopte_offset(iopgd, da)	(iopgd_page_vaddr(iopgd) + iopte_index(da))
-
-static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
-				   u32 flags)
-{
-	memset(e, 0, sizeof(*e));
-
-	e->da		= da;
-	e->pa		= pa;
-	e->valid	= 1;
-	/* FIXME: add OMAP1 support */
-	e->pgsz		= flags & MMU_CAM_PGSZ_MASK;
-	e->endian	= flags & MMU_RAM_ENDIAN_MASK;
-	e->elsz		= flags & MMU_RAM_ELSZ_MASK;
-	e->mixed	= flags & MMU_RAM_MIXED_MASK;
-
-	return iopgsz_to_bytes(e->pgsz);
-}
-
-#define to_iommu(dev)							\
-	(struct iommu *)platform_get_drvdata(to_platform_device(dev))
-
-#endif /* __PLAT_OMAP_IOMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/iovmm.c linux-libre-3.2-gnu1/arch/arm/plat-omap/iovmm.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/iovmm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/iovmm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,904 +0,0 @@
-/*
- * omap iommu: simple virtual address space management
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/scatterlist.h>
-
-#include <asm/cacheflush.h>
-#include <asm/mach/map.h>
-
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-
-#include "iopgtable.h"
-
-/*
- * A device driver needs to create address mappings between:
- *
- * - iommu/device address
- * - physical address
- * - mpu virtual address
- *
- * There are 4 possible patterns for them:
- *
- *    |iova/			  mapping		iommu_		page
- *    | da	pa	va	(d)-(p)-(v)		function	type
- *  ---------------------------------------------------------------------------
- *  1 | c	c	c	 1 - 1 - 1	  _kmap() / _kunmap()	s
- *  2 | c	c,a	c	 1 - 1 - 1	_kmalloc()/ _kfree()	s
- *  3 | c	d	c	 1 - n - 1	  _vmap() / _vunmap()	s
- *  4 | c	d,a	c	 1 - n - 1	_vmalloc()/ _vfree()	n*
- *
- *
- *	'iova':	device iommu virtual address
- *	'da':	alias of 'iova'
- *	'pa':	physical address
- *	'va':	mpu virtual address
- *
- *	'c':	contiguous memory area
- *	'd':	discontiguous memory area
- *	'a':	anonymous memory allocation
- *	'()':	optional feature
- *
- *	'n':	a normal page(4KB) size is used.
- *	's':	multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
- *
- *	'*':	not yet, but feasible.
- */
-
-static struct kmem_cache *iovm_area_cachep;
-
-/* return total bytes of sg buffers */
-static size_t sgtable_len(const struct sg_table *sgt)
-{
-	unsigned int i, total = 0;
-	struct scatterlist *sg;
-
-	if (!sgt)
-		return 0;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-
-		bytes = sg->length;
-
-		if (!iopgsz_ok(bytes)) {
-			pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
-			       __func__, i, bytes);
-			return 0;
-		}
-
-		total += bytes;
-	}
-
-	return total;
-}
-#define sgtable_ok(x)	(!!sgtable_len(x))
-
-static unsigned max_alignment(u32 addr)
-{
-	int i;
-	unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
-	for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
-		;
-	return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
-}
-
-/*
- * calculate the optimal number sg elements from total bytes based on
- * iommu superpages
- */
-static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
-{
-	unsigned nr_entries = 0, ent_sz;
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
-		pr_err("%s: wrong size %08x\n", __func__, bytes);
-		return 0;
-	}
-
-	while (bytes) {
-		ent_sz = max_alignment(da | pa);
-		ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
-		nr_entries++;
-		da += ent_sz;
-		pa += ent_sz;
-		bytes -= ent_sz;
-	}
-
-	return nr_entries;
-}
-
-/* allocate and initialize sg_table header(a kind of 'superblock') */
-static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
-							u32 da, u32 pa)
-{
-	unsigned int nr_entries;
-	int err;
-	struct sg_table *sgt;
-
-	if (!bytes)
-		return ERR_PTR(-EINVAL);
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE))
-		return ERR_PTR(-EINVAL);
-
-	if (flags & IOVMF_LINEAR) {
-		nr_entries = sgtable_nents(bytes, da, pa);
-		if (!nr_entries)
-			return ERR_PTR(-EINVAL);
-	} else
-		nr_entries =  bytes / PAGE_SIZE;
-
-	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-	if (!sgt)
-		return ERR_PTR(-ENOMEM);
-
-	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
-	if (err) {
-		kfree(sgt);
-		return ERR_PTR(err);
-	}
-
-	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
-
-	return sgt;
-}
-
-/* free sg_table header(a kind of superblock) */
-static void sgtable_free(struct sg_table *sgt)
-{
-	if (!sgt)
-		return;
-
-	sg_free_table(sgt);
-	kfree(sgt);
-
-	pr_debug("%s: sgt:%p\n", __func__, sgt);
-}
-
-/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
-static void *vmap_sg(const struct sg_table *sgt)
-{
-	u32 va;
-	size_t total;
-	unsigned int i;
-	struct scatterlist *sg;
-	struct vm_struct *new;
-	const struct mem_type *mtype;
-
-	mtype = get_mem_type(MT_DEVICE);
-	if (!mtype)
-		return ERR_PTR(-EINVAL);
-
-	total = sgtable_len(sgt);
-	if (!total)
-		return ERR_PTR(-EINVAL);
-
-	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-	va = (u32)new->addr;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-		u32 pa;
-		int err;
-
-		pa = sg_phys(sg);
-		bytes = sg->length;
-
-		BUG_ON(bytes != PAGE_SIZE);
-
-		err = ioremap_page(va,  pa, mtype);
-		if (err)
-			goto err_out;
-
-		va += bytes;
-	}
-
-	flush_cache_vmap((unsigned long)new->addr,
-				(unsigned long)(new->addr + total));
-	return new->addr;
-
-err_out:
-	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
-	vunmap(new->addr);
-	return ERR_PTR(-EAGAIN);
-}
-
-static inline void vunmap_sg(const void *va)
-{
-	vunmap(va);
-}
-
-static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
-{
-	struct iovm_struct *tmp;
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
-			size_t len;
-
-			len = tmp->da_end - tmp->da_start;
-
-			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
-				__func__, tmp->da_start, da, tmp->da_end, len,
-				tmp->flags);
-
-			return tmp;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * find_iovm_area  -  find iovma which includes @da
- * @da:		iommu device virtual address
- *
- * Find the existing iovma starting at @da
- */
-struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
-{
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-	area = __find_iovm_area(obj, da);
-	mutex_unlock(&obj->mmap_lock);
-
-	return area;
-}
-EXPORT_SYMBOL_GPL(find_iovm_area);
-
-/*
- * This finds the hole(area) which fits the requested address and len
- * in iovmas mmap, and returns the new allocated iovma.
- */
-static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
-					   size_t bytes, u32 flags)
-{
-	struct iovm_struct *new, *tmp;
-	u32 start, prev_end, alignment;
-
-	if (!obj || !bytes)
-		return ERR_PTR(-EINVAL);
-
-	start = da;
-	alignment = PAGE_SIZE;
-
-	if (~flags & IOVMF_DA_FIXED) {
-		/* Don't map address 0 */
-		start = obj->da_start ? obj->da_start : alignment;
-
-		if (flags & IOVMF_LINEAR)
-			alignment = iopgsz_max(bytes);
-		start = roundup(start, alignment);
-	} else if (start < obj->da_start || start > obj->da_end ||
-					obj->da_end - start < bytes) {
-		return ERR_PTR(-EINVAL);
-	}
-
-	tmp = NULL;
-	if (list_empty(&obj->mmap))
-		goto found;
-
-	prev_end = 0;
-	list_for_each_entry(tmp, &obj->mmap, list) {
-
-		if (prev_end > start)
-			break;
-
-		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
-			goto found;
-
-		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
-			start = roundup(tmp->da_end + 1, alignment);
-
-		prev_end = tmp->da_end;
-	}
-
-	if ((start >= prev_end) && (obj->da_end - start >= bytes))
-		goto found;
-
-	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
-		__func__, da, bytes, flags);
-
-	return ERR_PTR(-EINVAL);
-
-found:
-	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-
-	new->iommu = obj;
-	new->da_start = start;
-	new->da_end = start + bytes;
-	new->flags = flags;
-
-	/*
-	 * keep ascending order of iovmas
-	 */
-	if (tmp)
-		list_add_tail(&new->list, &tmp->list);
-	else
-		list_add(&new->list, &obj->mmap);
-
-	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
-		__func__, new->da_start, start, new->da_end, bytes, flags);
-
-	return new;
-}
-
-static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
-{
-	size_t bytes;
-
-	BUG_ON(!obj || !area);
-
-	bytes = area->da_end - area->da_start;
-
-	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
-		__func__, area->da_start, area->da_end, bytes, area->flags);
-
-	list_del(&area->list);
-	kmem_cache_free(iovm_area_cachep, area);
-}
-
-/**
- * da_to_va - convert (d) to (v)
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- * @va:		mpu virtual address
- *
- * Returns mpu virtual addr which corresponds to a given device virtual addr
- */
-void *da_to_va(struct iommu *obj, u32 da)
-{
-	void *va = NULL;
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-	va = area->va;
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return va;
-}
-EXPORT_SYMBOL_GPL(da_to_va);
-
-static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
-{
-	unsigned int i;
-	struct scatterlist *sg;
-	void *va = _va;
-	void *va_end;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		struct page *pg;
-		const size_t bytes = PAGE_SIZE;
-
-		/*
-		 * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
-		 */
-		pg = vmalloc_to_page(va);
-		BUG_ON(!pg);
-		sg_set_page(sg, pg, bytes, 0);
-
-		va += bytes;
-	}
-
-	va_end = _va + PAGE_SIZE * i;
-}
-
-static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
-{
-	/*
-	 * Actually this is not necessary at all, just exists for
-	 * consistency of the code readability.
-	 */
-	BUG_ON(!sgt);
-}
-
-static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
-								size_t len)
-{
-	unsigned int i;
-	struct scatterlist *sg;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		unsigned bytes;
-
-		bytes = max_alignment(da | pa);
-		bytes = min_t(unsigned, bytes, iopgsz_max(len));
-
-		BUG_ON(!iopgsz_ok(bytes));
-
-		sg_set_buf(sg, phys_to_virt(pa), bytes);
-		/*
-		 * 'pa' is cotinuous(linear).
-		 */
-		pa += bytes;
-		da += bytes;
-		len -= bytes;
-	}
-	BUG_ON(len);
-}
-
-static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
-{
-	/*
-	 * Actually this is not necessary at all, just exists for
-	 * consistency of the code readability
-	 */
-	BUG_ON(!sgt);
-}
-
-/* create 'da' <-> 'pa' mapping from 'sgt' */
-static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
-			 const struct sg_table *sgt, u32 flags)
-{
-	int err;
-	unsigned int i, j;
-	struct scatterlist *sg;
-	u32 da = new->da_start;
-
-	if (!obj || !sgt)
-		return -EINVAL;
-
-	BUG_ON(!sgtable_ok(sgt));
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		u32 pa;
-		int pgsz;
-		size_t bytes;
-		struct iotlb_entry e;
-
-		pa = sg_phys(sg);
-		bytes = sg->length;
-
-		flags &= ~IOVMF_PGSZ_MASK;
-		pgsz = bytes_to_iopgsz(bytes);
-		if (pgsz < 0)
-			goto err_out;
-		flags |= pgsz;
-
-		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
-			 i, da, pa, bytes);
-
-		iotlb_init_entry(&e, da, pa, flags);
-		err = iopgtable_store_entry(obj, &e);
-		if (err)
-			goto err_out;
-
-		da += bytes;
-	}
-	return 0;
-
-err_out:
-	da = new->da_start;
-
-	for_each_sg(sgt->sgl, sg, i, j) {
-		size_t bytes;
-
-		bytes = iopgtable_clear_entry(obj, da);
-
-		BUG_ON(!iopgsz_ok(bytes));
-
-		da += bytes;
-	}
-	return err;
-}
-
-/* release 'da' <-> 'pa' mapping */
-static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
-{
-	u32 start;
-	size_t total = area->da_end - area->da_start;
-
-	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
-
-	start = area->da_start;
-	while (total > 0) {
-		size_t bytes;
-
-		bytes = iopgtable_clear_entry(obj, start);
-		if (bytes == 0)
-			bytes = PAGE_SIZE;
-		else
-			dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
-				__func__, start, bytes, area->flags);
-
-		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
-		total -= bytes;
-		start += bytes;
-	}
-	BUG_ON(total);
-}
-
-/* template function for all unmapping */
-static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
-				      void (*fn)(const void *), u32 flags)
-{
-	struct sg_table *sgt = NULL;
-	struct iovm_struct *area;
-
-	if (!IS_ALIGNED(da, PAGE_SIZE)) {
-		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
-		return NULL;
-	}
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-
-	if ((area->flags & flags) != flags) {
-		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
-			area->flags);
-		goto out;
-	}
-	sgt = (struct sg_table *)area->sgt;
-
-	unmap_iovm_area(obj, area);
-
-	fn(area->va);
-
-	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
-		area->da_start, da, area->da_end,
-		area->da_end - area->da_start, area->flags);
-
-	free_iovm_area(obj, area);
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return sgt;
-}
-
-static u32 map_iommu_region(struct iommu *obj, u32 da,
-	      const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
-{
-	int err = -ENOMEM;
-	struct iovm_struct *new;
-
-	mutex_lock(&obj->mmap_lock);
-
-	new = alloc_iovm_area(obj, da, bytes, flags);
-	if (IS_ERR(new)) {
-		err = PTR_ERR(new);
-		goto err_alloc_iovma;
-	}
-	new->va = va;
-	new->sgt = sgt;
-
-	if (map_iovm_area(obj, new, sgt, new->flags))
-		goto err_map;
-
-	mutex_unlock(&obj->mmap_lock);
-
-	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
-		__func__, new->da_start, bytes, new->flags, va);
-
-	return new->da_start;
-
-err_map:
-	free_iovm_area(obj, new);
-err_alloc_iovma:
-	mutex_unlock(&obj->mmap_lock);
-	return err;
-}
-
-static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
-		 const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
-{
-	return map_iommu_region(obj, da, sgt, va, bytes, flags);
-}
-
-/**
- * iommu_vmap  -  (d)-(p)-(v) address mapper
- * @obj:	objective iommu
- * @sgt:	address of scatter gather table
- * @flags:	iovma and page property
- *
- * Creates 1-n-1 mapping with given @sgt and returns @da.
- * All @sgt element must be io page size aligned.
- */
-u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
-		 u32 flags)
-{
-	size_t bytes;
-	void *va = NULL;
-
-	if (!obj || !obj->dev || !sgt)
-		return -EINVAL;
-
-	bytes = sgtable_len(sgt);
-	if (!bytes)
-		return -EINVAL;
-	bytes = PAGE_ALIGN(bytes);
-
-	if (flags & IOVMF_MMIO) {
-		va = vmap_sg(sgt);
-		if (IS_ERR(va))
-			return PTR_ERR(va);
-	}
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_MMIO;
-
-	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		vunmap_sg(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_vmap);
-
-/**
- * iommu_vunmap  -  release virtual mapping obtained by 'iommu_vmap()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Free the iommu virtually contiguous memory area starting at
- * @da, which was returned by 'iommu_vmap()'.
- */
-struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-	/*
-	 * 'sgt' is allocated before 'iommu_vmalloc()' is called.
-	 * Just returns 'sgt' to the caller to free
-	 */
-	sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	return sgt;
-}
-EXPORT_SYMBOL_GPL(iommu_vunmap);
-
-/**
- * iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @bytes:	allocation size
- * @flags:	iovma and page property
- *
- * Allocate @bytes linearly and creates 1-n-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
-{
-	void *va;
-	struct sg_table *sgt;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = vmalloc(bytes);
-	if (!va)
-		return -ENOMEM;
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_ALLOC;
-
-	sgt = sgtable_alloc(bytes, flags, da, 0);
-	if (IS_ERR(sgt)) {
-		da = PTR_ERR(sgt);
-		goto err_sgt_alloc;
-	}
-	sgtable_fill_vmalloc(sgt, va);
-
-	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		goto err_iommu_vmap;
-
-	return da;
-
-err_iommu_vmap:
-	sgtable_drain_vmalloc(sgt);
-	sgtable_free(sgt);
-err_sgt_alloc:
-	vfree(va);
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_vmalloc);
-
-/**
- * iommu_vfree  -  release memory allocated by 'iommu_vmalloc()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually continuous memory area starting at
- * @da, as obtained from 'iommu_vmalloc()'.
- */
-void iommu_vfree(struct iommu *obj, const u32 da)
-{
-	struct sg_table *sgt;
-
-	sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_vfree);
-
-static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
-			  size_t bytes, u32 flags)
-{
-	struct sg_table *sgt;
-
-	sgt = sgtable_alloc(bytes, flags, da, pa);
-	if (IS_ERR(sgt))
-		return PTR_ERR(sgt);
-
-	sgtable_fill_kmalloc(sgt, pa, da, bytes);
-
-	da = map_iommu_region(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da)) {
-		sgtable_drain_kmalloc(sgt);
-		sgtable_free(sgt);
-	}
-
-	return da;
-}
-
-/**
- * iommu_kmap  -  (d)-(p)-(v) address mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @pa:		contiguous physical memory
- * @flags:	iovma and page property
- *
- * Creates 1-1-1 mapping and returns @da again, which can be
- * adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
-		 u32 flags)
-{
-	void *va;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = ioremap(pa, bytes);
-	if (!va)
-		return -ENOMEM;
-
-	flags |= IOVMF_LINEAR;
-	flags |= IOVMF_MMIO;
-
-	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		iounmap(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmap);
-
-/**
- * iommu_kunmap  -  release virtual mapping obtained by 'iommu_kmap()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmap()'.
- */
-void iommu_kunmap(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-	typedef void (*func_t)(const void *);
-
-	sgt = unmap_vm_area(obj, da, (func_t)iounmap,
-			    IOVMF_LINEAR | IOVMF_MMIO);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kunmap);
-
-/**
- * iommu_kmalloc  -  (d)-(p)-(v) address allocator and mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @bytes:	bytes for allocation
- * @flags:	iovma and page property
- *
- * Allocate @bytes linearly and creates 1-1-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
-{
-	void *va;
-	u32 pa;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
-	if (!va)
-		return -ENOMEM;
-	pa = virt_to_phys(va);
-
-	flags |= IOVMF_LINEAR;
-	flags |= IOVMF_ALLOC;
-
-	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		kfree(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmalloc);
-
-/**
- * iommu_kfree  -  release virtual mapping obtained by 'iommu_kmalloc()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmalloc()'.
- */
-void iommu_kfree(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-
-	sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kfree);
-
-
-static int __init iovmm_init(void)
-{
-	const unsigned long flags = SLAB_HWCACHE_ALIGN;
-	struct kmem_cache *p;
-
-	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
-			      flags, NULL);
-	if (!p)
-		return -ENOMEM;
-	iovm_area_cachep = p;
-
-	return 0;
-}
-module_init(iovmm_init);
-
-static void __exit iovmm_exit(void)
-{
-	kmem_cache_destroy(iovm_area_cachep);
-}
-module_exit(iovmm_exit);
-
-MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-omap/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@ config ARCH_OMAP1
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  "Systems based on omap7xx, omap15xx or omap16xx"
 
@@ -132,18 +134,6 @@ config OMAP_MBOX_KFIFO_SIZE
 	  This can also be changed at runtime (via the mbox_kfifo_size
 	  module parameter).
 
-config OMAP_IOMMU
-	tristate
-
-config OMAP_IOMMU_DEBUG
-       tristate "Export OMAP IOMMU internals in DebugFS"
-       depends on OMAP_IOMMU && DEBUG_FS
-       help
-         Select this to see extensive information about
-         the internal state of OMAP IOMMU in debugfs.
-
-         Say N unless you know you need this.
-
 config OMAP_IOMMU_IVA2
 	bool
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/mailbox.c linux-libre-3.2-gnu1/arch/arm/plat-omap/mailbox.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kfifo.h>
 #include <linux/err.h>
 #include <linux/notifier.h>
+#include <linux/module.h>
 
 #include <plat/mailbox.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/Makefile linux-libre-3.2-gnu1/arch/arm/plat-omap/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_device.
 obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
-obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
-obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/mcbsp.c linux-libre-3.2-gnu1/arch/arm/plat-omap/mcbsp.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,45 +24,40 @@
 #include <linux/slab.h>
 
 #include <plat/mcbsp.h>
-#include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
-/* XXX These "sideways" includes are a sign that something is wrong */
-#include "../mach-omap2/cm2xxx_3xxx.h"
-#include "../mach-omap2/cm-regbits-34xx.h"
-
 struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count, omap_mcbsp_cache_size;
+int omap_mcbsp_count;
+
+#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
 
 static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
-	if (cpu_class_is_omap1()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
-	} else if (cpu_is_omap2420()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+		__raw_writew((u16)val, addr);
 	} else {
-		((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val;
-		__raw_writel(val, mcbsp->io_base + reg);
+		((u32 *)mcbsp->reg_cache)[reg] = val;
+		__raw_writel(val, addr);
 	}
 }
 
 static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 {
-	if (cpu_class_is_omap1()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)];
-	} else if (cpu_is_omap2420()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		return !from_cache ? __raw_readw(addr) :
+				     ((u16 *)mcbsp->reg_cache)[reg];
 	} else {
-		return !from_cache ? __raw_readl(mcbsp->io_base + reg) :
-				((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+		return !from_cache ? __raw_readl(addr) :
+				     ((u32 *)mcbsp->reg_cache)[reg];
 	}
 }
 
-#ifdef CONFIG_ARCH_OMAP3
 static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
 	__raw_writel(val, mcbsp->st_data->io_base_st + reg);
@@ -72,7 +67,6 @@ static int omap_mcbsp_st_read(struct oma
 {
 	return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
-#endif
 
 #define MCBSP_READ(mcbsp, reg) \
 		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
@@ -187,7 +181,7 @@ void omap_mcbsp_config(unsigned int id,
 	MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
 	MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
 	MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		MCBSP_WRITE(mcbsp, XCCR, config->xccr);
 		MCBSP_WRITE(mcbsp, RCCR, config->rccr);
 	}
@@ -239,46 +233,28 @@ int omap_mcbsp_dma_reg_params(unsigned i
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	data_reg = mcbsp->phys_dma_base;
-
-	if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+	if (mcbsp->pdata->reg_size == 2) {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR1;
+			data_reg = OMAP_MCBSP_REG_DRR1;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR1;
+			data_reg = OMAP_MCBSP_REG_DXR1;
 	} else {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR;
+			data_reg = OMAP_MCBSP_REG_DRR;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR;
+			data_reg = OMAP_MCBSP_REG_DXR;
 	}
 
-	return data_reg;
+	return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
 }
 EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_device *find_omap_device_by_dev(struct device *dev)
-{
-	struct platform_device *pdev = container_of(dev,
-					struct platform_device, dev);
-	return container_of(pdev, struct omap_device, pdev);
-}
-
 static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
-	struct omap_device *od;
 
-	od = find_omap_device_by_dev(mcbsp->dev);
-
-	/*
-	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
-	 * are enabled or sidetones start sounding ugly.
-	 */
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w &= ~(1 << (mcbsp->id - 2));
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
 
 	/* Enable McBSP Sidetone */
 	w = MCBSP_READ(mcbsp, SSELCR);
@@ -292,9 +268,6 @@ static void omap_st_on(struct omap_mcbsp
 static void omap_st_off(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
@@ -302,17 +275,13 @@ static void omap_st_off(struct omap_mcbs
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w |= 1 << (mcbsp->id - 2);
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
 {
 	u16 val, i;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	val = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -340,9 +309,6 @@ static void omap_st_chgain(struct omap_m
 {
 	u16 w;
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -525,14 +491,13 @@ void omap_mcbsp_set_tx_threshold(unsigne
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_tx_thres)
 		MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
@@ -548,14 +513,13 @@ void omap_mcbsp_set_rx_threshold(unsigne
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_rx_thres)
 		MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
@@ -625,6 +589,8 @@ u16 omap_mcbsp_get_tx_delay(unsigned int
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of free locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
@@ -648,6 +614,8 @@ u16 omap_mcbsp_get_rx_delay(unsigned int
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of used locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
@@ -683,46 +651,6 @@ int omap_mcbsp_get_dma_op_mode(unsigned
 }
 EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
 
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
-{
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
-	/*
-	 * Enable wakup behavior, smart idle and all wakeups
-	 * REVISIT: some wakeups may be unnecessary
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
-	}
-}
-
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
-{
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
-
-	/*
-	 * Disable wakup behavior, smart idle and all wakeups
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		/*
-		 * HW bug workaround - If no_idle mode is taken, we need to
-		 * go to smart_idle before going to always_idle, or the
-		 * device will not hit retention anymore.
-		 */
-
-		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
-	}
-}
-#else
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
-#endif
-
 int omap_mcbsp_request(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
@@ -735,7 +663,7 @@ int omap_mcbsp_request(unsigned int id)
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL);
+	reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
 	if (!reg_cache) {
 		return -ENOMEM;
 	}
@@ -757,8 +685,9 @@ int omap_mcbsp_request(unsigned int id)
 
 	pm_runtime_get_sync(mcbsp->dev);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_request(mcbsp);
+	/* Enable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 
 	/*
 	 * Make sure that transmitter, receiver and sample-rate generator are
@@ -795,8 +724,9 @@ err_clk_disable:
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -825,8 +755,9 @@ void omap_mcbsp_free(unsigned int id)
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -866,7 +797,7 @@ void omap_mcbsp_start(unsigned int id, i
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_start(mcbsp);
 
 	/* Only enable SRG, if McBSP is master */
@@ -904,7 +835,7 @@ void omap_mcbsp_start(unsigned int id, i
 		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
 	}
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		/* Release the transmitter and receiver */
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w &= ~(tx ? XDISABLE : 0);
@@ -934,7 +865,7 @@ void omap_mcbsp_stop(unsigned int id, in
 
 	/* Reset transmitter */
 	tx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w |= (tx ? XDISABLE : 0);
 		MCBSP_WRITE(mcbsp, XCCR, w);
@@ -944,7 +875,7 @@ void omap_mcbsp_stop(unsigned int id, in
 
 	/* Reset receiver */
 	rx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, RCCR);
 		w |= (rx ? RDISABLE : 0);
 		MCBSP_WRITE(mcbsp, RCCR, w);
@@ -961,39 +892,72 @@ void omap_mcbsp_stop(unsigned int id, in
 		MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
 	}
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_stop(mcbsp);
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
-/*
- * The following functions are only required on an OMAP1-only build.
- * mach-omap2/mcbsp.c contains the real functions
- */
-#ifndef CONFIG_ARCH_OMAP2PLUS
 int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return -EINVAL;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+		return -EINVAL;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+		src = "clks_ext";
+	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+		src = "clks_fclk";
+	else
+		return -EINVAL;
+
+	if (mcbsp->pdata->set_clk_src)
+		return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+	else
+		return -EINVAL;
 }
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
 void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == CLKR_SRC_CLKR)
+		src = "clkr";
+	else if (mux == CLKR_SRC_CLKX)
+		src = "clkx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
 void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == FSR_SRC_FSR)
+		src = "fsr";
+	else if (mux == FSR_SRC_FSX)
+		src = "fsx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
 }
-#endif
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
-#ifdef CONFIG_ARCH_OMAP3
 #define max_thres(m)			(mcbsp->pdata->buffer_size)
 #define valid_threshold(m, val)		((val) <= max_thres(m))
 #define THRESHOLD_PROP_BUILDER(prop)					\
@@ -1084,6 +1048,17 @@ unlock:
 
 static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
 
+static const struct attribute *additional_attrs[] = {
+	&dev_attr_max_tx_thres.attr,
+	&dev_attr_max_rx_thres.attr,
+	&dev_attr_dma_op_mode.attr,
+	NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+	.attrs = (struct attribute **)additional_attrs,
+};
+
 static ssize_t st_taps_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -1142,27 +1117,6 @@ out:
 
 static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
 
-static const struct attribute *additional_attrs[] = {
-	&dev_attr_max_tx_thres.attr,
-	&dev_attr_max_rx_thres.attr,
-	&dev_attr_dma_op_mode.attr,
-	NULL,
-};
-
-static const struct attribute_group additional_attr_group = {
-	.attrs = (struct attribute **)additional_attrs,
-};
-
-static inline int __devinit omap_additional_add(struct device *dev)
-{
-	return sysfs_create_group(&dev->kobj, &additional_attr_group);
-}
-
-static inline void __devexit omap_additional_remove(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &additional_attr_group);
-}
-
 static const struct attribute *sidetone_attrs[] = {
 	&dev_attr_st_taps.attr,
 	NULL,
@@ -1172,10 +1126,9 @@ static const struct attribute_group side
 	.attrs = (struct attribute **)sidetone_attrs,
 };
 
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+				 struct resource *res)
 {
-	struct platform_device *pdev;
-	struct resource *res;
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
@@ -1185,9 +1138,6 @@ static int __devinit omap_st_add(struct
 		goto err1;
 	}
 
-	pdev = container_of(mcbsp->dev, struct platform_device, dev);
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
 	st_data->io_base_st = ioremap(res->start, resource_size(res));
 	if (!st_data->io_base_st) {
 		err = -ENOMEM;
@@ -1214,59 +1164,10 @@ static void __devexit omap_st_remove(str
 {
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
-	if (st_data) {
-		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
-		iounmap(st_data->io_base_st);
-		kfree(st_data);
-	}
-}
-
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
-{
-	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
-	if (cpu_is_omap34xx()) {
-		/*
-		 * Initially configure the maximum thresholds to a safe value.
-		 * The McBSP FIFO usage with these values should not go under
-		 * 16 locations.
-		 * If the whole FIFO without safety buffer is used, than there
-		 * is a possibility that the DMA will be not able to push the
-		 * new data on time, causing channel shifts in runtime.
-		 */
-		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
-		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
-		/*
-		 * REVISIT: Set dmap_op_mode to THRESHOLD as default
-		 * for mcbsp2 instances.
-		 */
-		if (omap_additional_add(mcbsp->dev))
-			dev_warn(mcbsp->dev,
-				"Unable to create additional controls\n");
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			if (omap_st_add(mcbsp))
-				dev_warn(mcbsp->dev,
-				 "Unable to create sidetone controls\n");
-
-	} else {
-		mcbsp->max_tx_thres = -EINVAL;
-		mcbsp->max_rx_thres = -EINVAL;
-	}
-}
-
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
-{
-	if (cpu_is_omap34xx()) {
-		omap_additional_remove(mcbsp->dev);
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			omap_st_remove(mcbsp);
-	}
+	sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+	iounmap(st_data->io_base_st);
+	kfree(st_data);
 }
-#else
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
-#endif /* CONFIG_ARCH_OMAP3 */
 
 /*
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
@@ -1316,7 +1217,7 @@ static int __devinit omap_mcbsp_probe(st
 		}
 	}
 	mcbsp->phys_base = res->start;
-	omap_mcbsp_cache_size = resource_size(res);
+	mcbsp->reg_cache_size = resource_size(res);
 	mcbsp->io_base = ioremap(res->start, resource_size(res));
 	if (!mcbsp->io_base) {
 		ret = -ENOMEM;
@@ -1364,15 +1265,52 @@ static int __devinit omap_mcbsp_probe(st
 	mcbsp->pdata = pdata;
 	mcbsp->dev = &pdev->dev;
 	mcbsp_ptr[id] = mcbsp;
-	mcbsp->mcbsp_config_type = pdata->mcbsp_config_type;
 	platform_set_drvdata(pdev, mcbsp);
 	pm_runtime_enable(mcbsp->dev);
 
-	/* Initialize mcbsp properties for OMAP34XX if needed / applicable */
-	omap34xx_device_init(mcbsp);
+	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+	if (mcbsp->pdata->buffer_size) {
+		/*
+		 * Initially configure the maximum thresholds to a safe value.
+		 * The McBSP FIFO usage with these values should not go under
+		 * 16 locations.
+		 * If the whole FIFO without safety buffer is used, than there
+		 * is a possibility that the DMA will be not able to push the
+		 * new data on time, causing channel shifts in runtime.
+		 */
+		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+		ret = sysfs_create_group(&mcbsp->dev->kobj,
+					 &additional_attr_group);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create additional controls\n");
+			goto err_thres;
+		}
+	} else {
+		mcbsp->max_tx_thres = -EINVAL;
+		mcbsp->max_rx_thres = -EINVAL;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	if (res) {
+		ret = omap_st_add(mcbsp, res);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create sidetone controls\n");
+			goto err_st;
+		}
+	}
 
 	return 0;
 
+err_st:
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj,
+				   &additional_attr_group);
+err_thres:
+	clk_put(mcbsp->fclk);
 err_res:
 	iounmap(mcbsp->io_base);
 err_ioremap:
@@ -1392,7 +1330,12 @@ static int __devexit omap_mcbsp_remove(s
 				mcbsp->pdata->ops->free)
 			mcbsp->pdata->ops->free(mcbsp->id);
 
-		omap34xx_device_exit(mcbsp);
+		if (mcbsp->pdata->buffer_size)
+			sysfs_remove_group(&mcbsp->dev->kobj,
+					   &additional_attr_group);
+
+		if (mcbsp->st_data)
+			omap_st_remove(mcbsp);
 
 		clk_put(mcbsp->fclk);
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/omap_device.c linux-libre-3.2-gnu1/arch/arm/plat-omap/omap_device.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/omap_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/omap_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,6 +78,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -85,6 +86,8 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -94,6 +97,23 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
+static int omap_device_register(struct platform_device *pdev);
+static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
+
+
+static struct omap_device_pm_latency omap_default_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
 /* Private functions */
 
 /**
@@ -114,7 +134,7 @@ static int _omap_device_activate(struct
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: activating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
 
 	while (od->pm_lat_level > 0) {
 		struct omap_device_pm_latency *odpl;
@@ -138,25 +158,24 @@ static int _omap_device_activate(struct
 		c = timespec_sub(b, a);
 		act_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 act_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: activate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, act_lat);
 
 		if (act_lat > odpl->activate_lat) {
 			odpl->activate_lat_worst = act_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->activate_lat = act_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "activate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case activate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, act_lat);
 			} else
-				pr_warning("omap_device: %s.%d: activate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat,
-					   odpl->activate_lat);
+				dev_warn(&od->pdev->dev,
+					 "activate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, act_lat,
+					 odpl->activate_lat);
 		}
 
 		od->dev_wakeup_lat -= odpl->activate_lat;
@@ -183,7 +202,7 @@ static int _omap_device_deactivate(struc
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: deactivating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
 
 	while (od->pm_lat_level < od->pm_lats_cnt) {
 		struct omap_device_pm_latency *odpl;
@@ -206,28 +225,26 @@ static int _omap_device_deactivate(struc
 		c = timespec_sub(b, a);
 		deact_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 deact_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: deactivate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, deact_lat);
 
 		if (deact_lat > odpl->deactivate_lat) {
 			odpl->deactivate_lat_worst = deact_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->deactivate_lat = deact_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "deactivate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case deactivate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, deact_lat);
 			} else
-				pr_warning("omap_device: %s.%d: deactivate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat,
-					   odpl->deactivate_lat);
+				dev_warn(&od->pdev->dev,
+					 "deactivate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, deact_lat,
+					 odpl->deactivate_lat);
 		}
 
-
 		od->dev_wakeup_lat += odpl->activate_lat;
 
 		od->pm_lat_level++;
@@ -245,28 +262,27 @@ static void _add_clkdev(struct omap_devi
 	if (!clk_alias || !clk_name)
 		return;
 
-	pr_debug("omap_device: %s: Creating %s -> %s\n",
-		 dev_name(&od->pdev.dev), clk_alias, clk_name);
+	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
 
-	r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
 	if (!IS_ERR(r)) {
-		pr_warning("omap_device: %s: alias %s already exists\n",
-			   dev_name(&od->pdev.dev), clk_alias);
+		dev_warn(&od->pdev->dev,
+			 "alias %s already exists\n", clk_alias);
 		clk_put(r);
 		return;
 	}
 
 	r = omap_clk_get_by_name(clk_name);
 	if (IS_ERR(r)) {
-		pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_name);
+		dev_err(&od->pdev->dev,
+			"omap_clk_get_by_name for %s failed\n", clk_name);
 		return;
 	}
 
-	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
 	if (!l) {
-		pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_alias);
+		dev_err(&od->pdev->dev,
+			"clkdev_alloc for %s failed\n", clk_alias);
 		return;
 	}
 
@@ -304,6 +320,96 @@ static void _add_hwmod_clocks_clkdev(str
 }
 
 
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct device_node *node = pdev->dev.of_node;
+	const char *oh_name;
+	int oh_cnt, i, ret = 0;
+
+	oh_cnt = of_property_count_strings(node, "ti,hwmods");
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+
 /* Public functions for use by core code */
 
 /**
@@ -321,7 +427,7 @@ static void _add_hwmod_clocks_clkdev(str
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
 {
 	struct omap_device *od;
 	u32 ret = 0;
@@ -343,7 +449,7 @@ u32 omap_device_get_context_loss_count(s
  * much memory to allocate before calling
  * omap_device_fill_resources().  Returns the count.
  */
-int omap_device_count_resources(struct omap_device *od)
+static int omap_device_count_resources(struct omap_device *od)
 {
 	int c = 0;
 	int i;
@@ -352,7 +458,7 @@ int omap_device_count_resources(struct o
 		c += omap_hwmod_count_resources(od->hwmods[i]);
 
 	pr_debug("omap_device: %s: counted %d total resources across %d "
-		 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
+		 "hwmods\n", od->pdev->name, c, od->hwmods_cnt);
 
 	return c;
 }
@@ -374,7 +480,8 @@ int omap_device_count_resources(struct o
  * functions to get device resources.  Hacking around the existing
  * platform_device code wastes memory.  Returns 0.
  */
-int omap_device_fill_resources(struct omap_device *od, struct resource *res)
+static int omap_device_fill_resources(struct omap_device *od,
+				      struct resource *res)
 {
 	int c = 0;
 	int i, r;
@@ -389,6 +496,113 @@ int omap_device_fill_resources(struct om
 }
 
 /**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	/*
+	 * HACK: Ideally the resources from DT should match, and hwmod
+	 * should just add the missing ones. Since the name is not
+	 * properly populated by DT, stick to hwmod resources only.
+	 */
+	if (pdev->num_resources && pdev->resource)
+		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+			__func__, pdev->num_resources);
+
+	res_count = omap_device_count_resources(od);
+	if (res_count > 0) {
+		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+			__func__, res_count);
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		omap_device_fill_resources(od, res);
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+	if (!od)
+		return;
+
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
  * omap_device_build - build and register an omap_device with one omap_hwmod
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
@@ -405,7 +619,7 @@ int omap_device_fill_resources(struct om
  * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
  * passes along the return value of omap_device_build_ss().
  */
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
@@ -438,18 +652,15 @@ struct omap_device *omap_device_build(co
  * platform_device record.  Returns an ERR_PTR() on error, or passes
  * along the return value of omap_device_register().
  */
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **ohs, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device)
 {
 	int ret = -ENOMEM;
+	struct platform_device *pdev;
 	struct omap_device *od;
-	char *pdev_name2;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
 
 	if (!ohs || oh_cnt == 0 || !pdev_name)
 		return ERR_PTR(-EINVAL);
@@ -457,72 +668,40 @@ struct omap_device *omap_device_build_ss
 	if (!pdata && pdata_len > 0)
 		return ERR_PTR(-EINVAL);
 
-	pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
-		 oh_cnt);
-
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od)
-		return ERR_PTR(-ENOMEM);
+	pdev = platform_device_alloc(pdev_name, pdev_id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto odbs_exit;
+	}
 
-	od->hwmods_cnt = oh_cnt;
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
-			 GFP_KERNEL);
-	if (!hwmods)
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (!od)
 		goto odbs_exit1;
 
-	memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
-	od->hwmods = hwmods;
-
-	pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL);
-	if (!pdev_name2)
-		goto odbs_exit2;
-	strcpy(pdev_name2, pdev_name);
-
-	od->pdev.name = pdev_name2;
-	od->pdev.id = pdev_id;
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto odbs_exit3;
-	}
-	omap_device_fill_resources(od, res);
-
-	od->pdev.num_resources = res_count;
-	od->pdev.resource = res;
-
-	ret = platform_device_add_data(&od->pdev, pdata, pdata_len);
+	ret = platform_device_add_data(pdev, pdata, pdata_len);
 	if (ret)
-		goto odbs_exit4;
-
-	od->pm_lats = pm_lats;
-	od->pm_lats_cnt = pm_lats_cnt;
+		goto odbs_exit2;
 
 	if (is_early_device)
-		ret = omap_early_device_register(od);
+		ret = omap_early_device_register(pdev);
 	else
-		ret = omap_device_register(od);
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
-
+		ret = omap_device_register(pdev);
 	if (ret)
-		goto odbs_exit4;
+		goto odbs_exit2;
 
-	return od;
+	return pdev;
 
-odbs_exit4:
-	kfree(res);
-odbs_exit3:
-	kfree(pdev_name2);
 odbs_exit2:
-	kfree(hwmods);
+	omap_device_delete(od);
 odbs_exit1:
-	kfree(od);
+	platform_device_put(pdev);
+odbs_exit:
 
 	pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
 
@@ -538,11 +717,11 @@ odbs_exit1:
  * platform_early_add_device() on the underlying platform_device.
  * Returns 0 by default.
  */
-int omap_early_device_register(struct omap_device *od)
+static int omap_early_device_register(struct platform_device *pdev)
 {
 	struct platform_device *devices[1];
 
-	devices[0] = &(od->pdev);
+	devices[0] = pdev;
 	early_platform_add_devices(devices, 1);
 	return 0;
 }
@@ -638,13 +817,13 @@ static struct dev_pm_domain omap_device_
  * platform_device_register() on the underlying platform_device.
  * Returns the return value of platform_device_register().
  */
-int omap_device_register(struct omap_device *od)
+static int omap_device_register(struct platform_device *pdev)
 {
-	pr_debug("omap_device: %s: registering\n", od->pdev.name);
+	pr_debug("omap_device: %s: registering\n", pdev->name);
 
-	od->pdev.dev.parent = &omap_device_parent;
-	od->pdev.dev.pm_domain = &omap_device_pm_domain;
-	return platform_device_register(&od->pdev);
+	pdev->dev.parent = &omap_device_parent;
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+	return platform_device_add(pdev);
 }
 
 
@@ -671,8 +850,9 @@ int omap_device_enable(struct platform_d
 	od = to_omap_device(pdev);
 
 	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -710,8 +890,9 @@ int omap_device_idle(struct platform_dev
 	od = to_omap_device(pdev);
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -742,8 +923,9 @@ int omap_device_shutdown(struct platform
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
 	    od->_state != OMAP_DEVICE_STATE_IDLE) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -837,6 +1019,42 @@ void __iomem *omap_device_get_rt_va(stru
 	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
 }
 
+/**
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
+ * device pointer.
+ * @oh_name: name of the hwmod device
+ *
+ * Returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
+{
+	struct omap_hwmod *oh;
+
+	if (!oh_name) {
+		WARN(1, "%s: no hwmod name!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (IS_ERR_OR_NULL(oh)) {
+		WARN(1, "%s: no hwmod for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+	}
+	if (IS_ERR_OR_NULL(oh->od)) {
+		WARN(1, "%s: no omap_device for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+	}
+
+	if (IS_ERR_OR_NULL(oh->od->pdev))
+		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
+
+	return &oh->od->pdev->dev;
+}
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
+
 /*
  * Public functions intended for use in omap_device_pm_latency
  * .activate_func and .deactivate_func function pointers
@@ -917,8 +1135,13 @@ struct device omap_device_parent = {
 	.parent         = &platform_bus,
 };
 
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
 static int __init omap_device_init(void)
 {
+	bus_register_notifier(&platform_bus_type, &platform_nb);
 	return device_register(&omap_device_parent);
 }
 core_initcall(omap_device_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/omap-pm-noop.c linux-libre-3.2-gnu1/arch/arm/plat-omap/omap-pm-noop.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/omap-pm-noop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/omap-pm-noop.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <plat/omap_device.h>
 
 static bool off_mode_enabled;
-static u32 dummy_context_loss_counter;
+static int dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -311,22 +311,32 @@ void omap_pm_disable_off_mode(void)
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	u32 count;
+	int count;
 
 	if (WARN_ON(!dev))
-		return 0;
+		return -ENODEV;
 
 	if (dev->parent == &omap_device_parent) {
 		count = omap_device_get_context_loss_count(pdev);
 	} else {
 		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
 			  dev_name(dev));
-		if (off_mode_enabled)
-			dummy_context_loss_counter++;
+
 		count = dummy_context_loss_counter;
+
+		if (off_mode_enabled) {
+			count++;
+			/*
+			 * Context loss count has to be a non-negative value.
+			 * Clear the sign bit to get a value range from 0 to
+			 * INT_MAX.
+			 */
+			count &= INT_MAX;
+			dummy_context_loss_counter = count;
+		}
 	}
 
 	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
@@ -337,7 +347,7 @@ u32 omap_pm_get_dev_context_loss_count(s
 
 #else
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	return dummy_context_loss_counter;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-omap/sram.c linux-libre-3.2-gnu1/arch/arm/plat-omap/sram.c
--- linux-libre-3.1-gnu1/arch/arm/plat-omap/sram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-omap/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -29,10 +28,8 @@
 #include <plat/sram.h>
 #include <plat/board.h>
 #include <plat/cpu.h>
-#include <plat/vram.h>
 
 #include "sram.h"
-#include "fb.h"
 
 /* XXX These "sideways" includes are a sign that something is wrong */
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -41,16 +38,9 @@
 #endif
 
 #define OMAP1_SRAM_PA		0x20000000
-#define OMAP1_SRAM_VA		VMALLOC_END
 #define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
-#define OMAP2_SRAM_VA		0xfe400000
-#define OMAP2_SRAM_PUB_VA	(OMAP2_SRAM_VA + 0x800)
-#define OMAP3_SRAM_VA           0xfe400000
 #define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
-#define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_VA		0xfe400000
 #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
-#define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000)
 
 #if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ	0x00
@@ -73,9 +63,9 @@
 #define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
 static unsigned long omap_sram_start;
-static unsigned long omap_sram_base;
+static void __iomem *omap_sram_base;
 static unsigned long omap_sram_size;
-static unsigned long omap_sram_ceil;
+static void __iomem *omap_sram_ceil;
 
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
@@ -112,12 +102,9 @@ static int is_sram_locked(void)
  */
 static void __init omap_detect_sram(void)
 {
-	unsigned long reserved;
-
 	if (cpu_class_is_omap2()) {
 		if (is_sram_locked()) {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_PUB_VA;
 				omap_sram_start = OMAP3_SRAM_PUB_PA;
 				if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
 				    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
@@ -126,25 +113,20 @@ static void __init omap_detect_sram(void
 					omap_sram_size = 0x8000; /* 32K */
 				}
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_PUB_VA;
 				omap_sram_start = OMAP4_SRAM_PUB_PA;
 				omap_sram_size = 0xa000; /* 40K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_PUB_VA;
 				omap_sram_start = OMAP2_SRAM_PUB_PA;
 				omap_sram_size = 0x800; /* 2K */
 			}
 		} else {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_VA;
 				omap_sram_start = OMAP3_SRAM_PA;
 				omap_sram_size = 0x10000; /* 64K */
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_VA;
 				omap_sram_start = OMAP4_SRAM_PA;
 				omap_sram_size = 0xe000; /* 56K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_VA;
 				omap_sram_start = OMAP2_SRAM_PA;
 				if (cpu_is_omap242x())
 					omap_sram_size = 0xa0000; /* 640K */
@@ -153,7 +135,6 @@ static void __init omap_detect_sram(void
 			}
 		}
 	} else {
-		omap_sram_base = OMAP1_SRAM_VA;
 		omap_sram_start = OMAP1_SRAM_PA;
 
 		if (cpu_is_omap7xx())
@@ -170,35 +151,14 @@ static void __init omap_detect_sram(void
 			omap_sram_size = 0x4000;
 		}
 	}
-	reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
-				       omap_sram_size,
-				       omap_sram_start + SRAM_BOOTLOADER_SZ,
-				       omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
-			omap_sram_size,
-			omap_sram_start + SRAM_BOOTLOADER_SZ,
-			omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
-static struct map_desc omap_sram_io_desc[] __initdata = {
-	{	/* .length gets filled in at runtime */
-		.virtual	= OMAP1_SRAM_VA,
-		.pfn		= __phys_to_pfn(OMAP1_SRAM_PA),
-		.type		= MT_MEMORY
-	}
-};
-
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
 static void __init omap_map_sram(void)
 {
-	unsigned long base;
+	int cached = 1;
 
 	if (omap_sram_size == 0)
 		return;
@@ -211,28 +171,18 @@ static void __init omap_map_sram(void)
 		 * the ARM may attempt to write cache lines back to SDRAM
 		 * which will cause the system to hang.
 		 */
-		omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
+		cached = 0;
 	}
 
-	omap_sram_io_desc[0].virtual = omap_sram_base;
-	base = omap_sram_start;
-	base = ROUND_DOWN(base, PAGE_SIZE);
-	omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-	omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
-	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
-
-	pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
-		(long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
-		omap_sram_io_desc[0].virtual,
-		omap_sram_io_desc[0].length);
+	omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
+	omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size,
+						cached);
+	if (!omap_sram_base) {
+		pr_err("SRAM: Could not map\n");
+		return;
+	}
 
-	/*
-	 * Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but since we're called from map_io(), we
-	 * must do it here.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
+	omap_sram_ceil = omap_sram_base + omap_sram_size;
 
 	/*
 	 * Looks like we need to preserve some bootloader code at the
@@ -251,13 +201,18 @@ static void __init omap_map_sram(void)
  */
 void *omap_sram_push_address(unsigned long size)
 {
-	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+	unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
+
+	available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+
+	if (size > available) {
 		pr_err("Not enough space in SRAM\n");
 		return NULL;
 	}
 
-	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
+	new_ceil -= size;
+	new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
+	omap_sram_ceil = IOMEM(new_ceil);
 
 	return (void *)omap_sram_ceil;
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-orion/gpio.c linux-libre-3.2-gnu1/arch/arm/plat-orion/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-orion/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-orion/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -384,12 +384,16 @@ void __init orion_gpio_init(int gpio_bas
 	struct orion_gpio_chip *ochip;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	char gc_label[16];
 
 	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
 		return;
 
+	snprintf(gc_label, sizeof(gc_label), "orion_gpio%d",
+		orion_gpio_chip_count);
+
 	ochip = orion_gpio_chips + orion_gpio_chip_count;
-	ochip->chip.label = "orion_gpio";
+	ochip->chip.label = kstrdup(gc_label, GFP_KERNEL);
 	ochip->chip.request = orion_gpio_request;
 	ochip->chip.direction_input = orion_gpio_direction_input;
 	ochip->chip.get = orion_gpio_get;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-orion/include/plat/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-orion/include/plat/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-orion/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-orion/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,15 +12,7 @@
 #define __PLAT_GPIO_H
 
 #include <linux/init.h>
-#include <asm-generic/gpio.h>
-
-/*
- * GENERIC_GPIO primitives.
- */
-#define gpio_get_value  __gpio_get_value
-#define gpio_set_value  __gpio_set_value
-#define gpio_cansleep   __gpio_cansleep
-#define gpio_to_irq     __gpio_to_irq
+#include <linux/types.h>
 
 /*
  * Orion-specific GPIO API extensions.
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/gpio.c linux-libre-3.2-gnu1/arch/arm/plat-pxa/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,338 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-#include <linux/slab.h>
-
-#include <mach/gpio.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem	*regbase;
-	char label[10];
-
-	unsigned long	irq_mask;
-	unsigned long	irq_edge_rise;
-	unsigned long	irq_edge_fall;
-
-#ifdef CONFIG_PM
-	unsigned long	saved_gplr;
-	unsigned long	saved_gpdr;
-	unsigned long	saved_grer;
-	unsigned long	saved_gfer;
-#endif
-};
-
-static DEFINE_SPINLOCK(gpio_lock);
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c)			\
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
-{
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
-}
-
-static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
-{
-	return &pxa_gpio_chips[gpio_to_bank(gpio)];
-}
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t value, mask = 1 << offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	value = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t tmp, mask = 1 << offset;
-	unsigned long flags;
-
-	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	tmp = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
-}
-
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	__raw_writel(1 << offset, gpio_chip_base(chip) +
-				(value ? GPSR_OFFSET : GPCR_OFFSET));
-}
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
-
-		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-
-		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
-		gpiochip_add(c);
-	}
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-/* Update only those GRERx and GFERx edge detection register bits if those
- * bits are set in c->irq_mask
- */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
-{
-	uint32_t grer, gfer;
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct pxa_gpio_chip *c;
-	int gpio = irq_to_gpio(d->irq);
-	unsigned long gpdr, mask = GPIO_bit(gpio);
-
-	c = gpio_to_pxachip(gpio);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-
-	if (__gpio_is_inverted(gpio))
-		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
-	else
-		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
-	else
-		c->irq_edge_rise &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
-	else
-		c->irq_edge_fall &= ~mask;
-
-	update_edge_detect(c);
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pxa_gpio_chip *c;
-	int loop, gpio, gpio_base, n;
-	unsigned long gedr;
-
-	do {
-		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
-
-			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
-
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
-				loop = 1;
-
-				generic_handle_irq(gpio_to_irq(gpio_base + n));
-				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
-			}
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
-}
-
-static void pxa_mask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-	uint32_t grer, gfer;
-
-	c->irq_mask &= ~GPIO_bit(gpio);
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static void pxa_unmask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= pxa_ack_muxed_gpio,
-	.irq_mask	= pxa_mask_muxed_gpio,
-	.irq_unmask	= pxa_unmask_muxed_gpio,
-	.irq_set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
-{
-	struct pxa_gpio_chip *c;
-	int gpio, irq;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	pxa_init_gpio_chip(end);
-
-	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0,c->regbase + GEDR_OFFSET);
-	}
-
-	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Install handler for GPIO>=2 edge detect interrupts */
-	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.irq_set_wake = fn;
-}
-
-#ifdef CONFIG_PM
-static int pxa_gpio_suspend(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
-		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
-
-		/* Clear GPIO transition detect bits */
-		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
-	}
-	return 0;
-}
-
-static void pxa_gpio_resume(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		/* restore level with set/clear */
-		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
-
-		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
-		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
-		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
-	}
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct syscore_ops pxa_gpio_syscore_ops = {
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,35 +1,10 @@
 #ifndef __PLAT_GPIO_H
 #define __PLAT_GPIO_H
 
-struct irq_data;
-
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
- * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
- * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
- * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
- *
- * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
- * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
- * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
- *
- * NOTE:
- *   BANK 3 is only available on PXA27x and later processors.
- *   BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+#define __ARM_GPIOLIB_COMPLEX
 
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
+/* The individual machine provides register offsets and NR_BUILTIN_GPIO */
+#include <mach/gpio-pxa.h>
 
 static inline int gpio_get_value(unsigned gpio)
 {
@@ -52,13 +27,4 @@ static inline void gpio_set_value(unsign
 
 #define gpio_cansleep		__gpio_cansleep
 
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
-
-extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
 #endif /* __PLAT_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/gpio-pxa.h linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/gpio-pxa.h
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+#ifndef __PLAT_PXA_GPIO_H
+#define __PLAT_PXA_GPIO_H
+
+struct irq_data;
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+
+#endif /* __PLAT_PXA_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/mfp.h linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/mfp.h
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/mfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/mfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -456,7 +456,7 @@ struct mfp_addr_map {
 
 #define MFP_ADDR_END	{ MFP_PIN_INVALID, 0 }
 
-void __init mfp_init_base(unsigned long mfpr_base);
+void __init mfp_init_base(void __iomem *mfpr_base);
 void __init mfp_init_addr(struct mfp_addr_map *map);
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +65,11 @@ struct pxa3xx_nand_platform_data {
 	/* allow platform code to keep OBM/bootloader defined NFC config */
 	int	keep_config;
 
-	const struct mtd_partition		*parts;
-	unsigned int				nr_parts;
+	/* indicate how many chip selects will be used */
+	int	num_cs;
+
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/Makefile linux-libre-3.2-gnu1/arch/arm/plat-pxa/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@
 
 obj-y	:= dma.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-pxa/mfp.c linux-libre-3.2-gnu1/arch/arm/plat-pxa/mfp.c
--- linux-libre-3.1-gnu1/arch/arm/plat-pxa/mfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-pxa/mfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@ void mfp_write(int mfp, unsigned long va
 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 }
 
-void __init mfp_init_base(unsigned long mfpr_base)
+void __init mfp_init_base(void __iomem *mfpr_base)
 {
 	int i;
 
@@ -237,7 +237,7 @@ void __init mfp_init_base(unsigned long
 	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
 		mfp_table[i].config = -1;
 
-	mfpr_mmio_base = (void __iomem *)mfpr_base;
+	mfpr_mmio_base = mfpr_base;
 }
 
 void __init mfp_init_addr(struct mfp_addr_map *map)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/cpu.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -215,19 +215,18 @@ static void s3c24xx_pm_restart(char mode
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode = 0x0;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(mach_desc, size);
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
 	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
-		idcode = s3c24xx_read_idcode_v5();
+		samsung_cpu_id = s3c24xx_read_idcode_v5();
 	} else {
-		idcode = s3c24xx_read_idcode_v4();
+		samsung_cpu_id = s3c24xx_read_idcode_v4();
 	}
+	s3c24xx_init_cpu();
 
 	arm_pm_restart = s3c24xx_pm_restart;
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/devs.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/devs.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/devs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/devs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,528 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/devs.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Base S3C24XX platform device definitions
- *
- * 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <mach/fb.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <plat/udc.h>
-#include <plat/mci.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/regs-spi.h>
-#include <plat/ts.h>
-
-/* Serial port registrations */
-
-static struct resource s3c2410_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart3_resource[] = {
-	[0] = {
-		.start = S3C2443_PA_UART3,
-		.end   = S3C2443_PA_UART3 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX3,
-		.end   = IRQ_S3CUART_ERR3,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= s3c2410_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
-	},
-	[1] = {
-		.resources	= s3c2410_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
-	},
-	[2] = {
-		.resources	= s3c2410_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
-	},
-	[3] = {
-		.resources	= s3c2410_uart3_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart3_resource),
-	},
-};
-
-/* LCD Controller */
-
-static struct resource s3c_lcd_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_LCD,
-		.end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_LCD,
-		.end   = IRQ_LCD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_lcd = {
-	.name		  = "s3c2410-lcd",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
-	.resource	  = s3c_lcd_resource,
-	.dev              = {
-		.dma_mask		= &s3c_device_lcd_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_lcd);
-
-void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
-{
-	struct s3c2410fb_mach_info *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
-	if (npd) {
-		npd->displays = kmemdup(pd->displays,
-			sizeof(struct s3c2410fb_display) * npd->num_displays,
-			GFP_KERNEL);
-		if (!npd->displays)
-			printk(KERN_ERR "no memory for LCD display data\n");
-	} else {
-		printk(KERN_ERR "no memory for LCD platform data\n");
-	}
-}
-
-/* Touchscreen */
-
-static struct resource s3c_ts_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_ADC,
-		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-
-};
-
-struct platform_device s3c_device_ts = {
-	.name		  = "s3c2410-ts",
-	.id		  = -1,
-	.dev.parent	= &s3c_device_adc.dev,
-	.num_resources	  = ARRAY_SIZE(s3c_ts_resource),
-	.resource	  = s3c_ts_resource,
-};
-EXPORT_SYMBOL(s3c_device_ts);
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
-{
-	s3c_set_platdata(hard_s3c2410ts_info,
-			 sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
-}
-
-/* USB Device (Gadget)*/
-
-static struct resource s3c_usbgadget_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_USBDEV,
-		.end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBD,
-		.end   = IRQ_USBD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_usbgadget = {
-	.name		  = "s3c2410-usbgadget",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usbgadget_resource),
-	.resource	  = s3c_usbgadget_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_usbgadget);
-
-void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
-{
-	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
-}
-
-/* USB High Speed 2.0 Device (Gadget) */
-static struct resource s3c_hsudc_resource[] = {
-	[0] = {
-		.start	= S3C2416_PA_HSUDC,
-		.end	= S3C2416_PA_HSUDC + S3C2416_SZ_HSUDC - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USBD,
-		.end	= IRQ_USBD,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_hsudc_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsudc = {
-	.name		= "s3c-hsudc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_hsudc_resource),
-	.resource	= s3c_hsudc_resource,
-	.dev		= {
-		.dma_mask		= &s3c_hsudc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
-}
-
-/* IIS */
-
-static struct resource s3c_iis_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_IIS,
-		.end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-static u64 s3c_device_iis_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_iis = {
-	.name		  = "s3c24xx-iis",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_iis_resource),
-	.resource	  = s3c_iis_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_iis_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_iis);
-
-/* RTC */
-
-static struct resource s3c_rtc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_RTC,
-		.end   = S3C24XX_PA_RTC + 0xff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_RTC,
-		.end   = IRQ_RTC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_TICK,
-		.end   = IRQ_TICK,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-struct platform_device s3c_device_rtc = {
-	.name		  = "s3c2410-rtc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
-	.resource	  = s3c_rtc_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_rtc);
-
-/* ADC */
-
-static struct resource s3c_adc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_ADC,
-		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_ADC,
-		.end   = IRQ_ADC,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_adc = {
-	.name		  = "s3c24xx-adc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_adc_resource),
-	.resource	  = s3c_adc_resource,
-};
-
-/* SDI */
-
-static struct resource s3c_sdi_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SDI,
-		.end   = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SDI,
-		.end   = IRQ_SDI,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_sdi = {
-	.name		  = "s3c2410-sdi",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_sdi_resource),
-	.resource	  = s3c_sdi_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_sdi);
-
-void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
-			 &s3c_device_sdi);
-}
-
-
-/* SPI (0) */
-
-static struct resource s3c_spi0_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI,
-		.end   = S3C24XX_PA_SPI + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI0,
-		.end   = IRQ_SPI0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi0 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_spi0_resource),
-	.resource	  = s3c_spi0_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi0_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi0);
-
-/* SPI (1) */
-
-static struct resource s3c_spi1_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI + S3C2410_SPI1,
-		.end   = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI1,
-		.end   = IRQ_SPI1,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi1 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_spi1_resource),
-	.resource	  = s3c_spi1_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi1_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi1);
-
-#ifdef CONFIG_CPU_S3C2440
-
-/* Camif Controller */
-
-static struct resource s3c_camif_resource[] = {
-	[0] = {
-		.start = S3C2440_PA_CAMIF,
-		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_CAM,
-		.end   = IRQ_CAM,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_camif_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_camif = {
-	.name		  = "s3c2440-camif",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_camif_resource),
-	.resource	  = s3c_camif_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_camif_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_camif);
-
-/* AC97 */
-
-static struct resource s3c_ac97_resource[] = {
-	[0] = {
-		.start = S3C2440_PA_AC97,
-		.end   = S3C2440_PA_AC97 + S3C2440_SZ_AC97 -1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3C244x_AC97,
-		.end   = IRQ_S3C244x_AC97,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.name  = "PCM out",
-		.start = DMACH_PCM_OUT,
-		.end   = DMACH_PCM_OUT,
-		.flags = IORESOURCE_DMA,
-	},
-	[3] = {
-		.name  = "PCM in",
-		.start = DMACH_PCM_IN,
-		.end   = DMACH_PCM_IN,
-		.flags = IORESOURCE_DMA,
-	},
-	[4] = {
-		.name  = "Mic in",
-		.start = DMACH_MIC_IN,
-		.end   = DMACH_MIC_IN,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static u64 s3c_device_audio_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ac97 = {
-	.name		  = "samsung-ac97",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_ac97_resource),
-	.resource	  = s3c_ac97_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_ac97);
-
-/* ASoC I2S */
-
-struct platform_device s3c2412_device_iis = {
-	.name		  = "s3c2412-iis",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c2412_device_iis);
-
-#endif // CONFIG_CPU_S32440
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/dev-uart.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/dev-uart.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/dev-uart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/* linux/arch/arm/plat-s3c24xx/dev-uart.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX UART resource and platform device definitions
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+/* Serial port registrations */
+
+static struct resource s3c2410_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart3_resource[] = {
+	[0] = {
+		.start = S3C2443_PA_UART3,
+		.end   = S3C2443_PA_UART3 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX3,
+		.end   = IRQ_S3CUART_ERR3,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c2410_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c2410_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c2410_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
+	},
+	[3] = {
+		.resources	= s3c2410_uart3_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart3_resource),
+	},
+};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/dma.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/dma.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(enum dma_ch ch
 	 hwcfg |= S3C2410_DISRCC_INC;
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		/* source is hardware */
 		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(enum dma_ch ch
 		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		/* source is memory */
 		pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/gpio.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpio.c
- *
- * Copyright (c) 2004-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-	int ret;
-
-	WARN_ON(to);	/* should be none of these left */
-
-	if (!to) {
-		/* if pull is enabled, try first with up, and if that
-		 * fails, try using down */
-
-		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
-		if (ret)
-			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
-	} else {
-		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
-	}
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-	/* do this via gpiolib until all users removed */
-
-	gpio_request(pin, "temporary");
-	gpio_set_value(pin, to);
-	gpio_free(pin);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long offs = pin - chip->chip.base;
-
-	return __raw_readl(chip->base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-	unsigned long flags;
-	unsigned long misccr;
-
-	local_irq_save(flags);
-	misccr = __raw_readl(S3C24XX_MISCCR);
-	misccr &= ~clear;
-	misccr ^= change;
-	__raw_writel(misccr, S3C24XX_MISCCR);
-	local_irq_restore(flags);
-
-	return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/gpiolib.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/gpiolib.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpiolib.c
- *
- * Copyright (c) 2008-2010 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIOlib support
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
-{
-	return -EINVAL;
-}
-
-static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	local_irq_save(flags);
-
-	con = __raw_readl(base + 0x00);
-	dat = __raw_readl(base + 0x04);
-
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-
-	__raw_writel(dat, base + 0x04);
-
-	con &= ~(1 << offset);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
-{
-	if (offset < 4)
-		return IRQ_EINT0 + offset;
-	
-	if (offset < 8)
-		return IRQ_EINT4 + offset - 4;
-	
-	return -EINVAL;
-}
-
-static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx_a,
-	.get_config	= s3c_gpio_getcfg_s3c24xx_a,
-};
-
-struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-};
-
-struct s3c_gpio_chip s3c24xx_gpios[] = {
-	[0] = {
-		.base	= S3C2410_GPACON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_1bit),
-		.config	= &s3c24xx_gpiocfg_banka,
-		.chip	= {
-			.base			= S3C2410_GPA(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOA",
-			.ngpio			= 24,
-			.direction_input	= s3c24xx_gpiolib_banka_input,
-			.direction_output	= s3c24xx_gpiolib_banka_output,
-		},
-	},
-	[1] = {
-		.base	= S3C2410_GPBCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPB(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOB",
-			.ngpio			= 16,
-		},
-	},
-	[2] = {
-		.base	= S3C2410_GPCCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPC(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOC",
-			.ngpio			= 16,
-		},
-	},
-	[3] = {
-		.base	= S3C2410_GPDCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPD(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOD",
-			.ngpio			= 16,
-		},
-	},
-	[4] = {
-		.base	= S3C2410_GPECON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPE(0),
-			.label			= "GPIOE",
-			.owner			= THIS_MODULE,
-			.ngpio			= 16,
-		},
-	},
-	[5] = {
-		.base	= S3C2410_GPFCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPF(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOF",
-			.ngpio			= 8,
-			.to_irq			= s3c24xx_gpiolib_bankf_toirq,
-		},
-	},
-	[6] = {
-		.base	= S3C2410_GPGCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.irq_base = IRQ_EINT8,
-		.chip	= {
-			.base			= S3C2410_GPG(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOG",
-			.ngpio			= 16,
-			.to_irq			= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= S3C2410_GPHCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPH(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOH",
-			.ngpio			= 11,
-		},
-	},
-		/* GPIOS for the S3C2443 and later devices. */
-	{
-		.base	= S3C2440_GPJCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPJ(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOJ",
-			.ngpio			= 16,
-		},
-	}, {
-		.base	= S3C2443_GPKCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPK(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOK",
-			.ngpio			= 16,
-		},
-	}, {
-		.base	= S3C2443_GPLCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPL(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOL",
-			.ngpio			= 15,
-		},
-	}, {
-		.base	= S3C2443_GPMCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPM(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOM",
-			.ngpio			= 2,
-		},
-	},
-};
-
-
-static __init int s3c24xx_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s3c24xx_gpios;
-	int gpn;
-
-	for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
-		if (!chip->config)
-			chip->config = &s3c24xx_gpiocfg_default;
-
-		s3c_gpiolib_add(chip);
-	}
-
-	return 0;
-}
-
-core_initcall(s3c24xx_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/mach/clkdev.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/mach/clkdev.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - pwm clock and timer support
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg == S3C2410_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << (1 + tcfg1);
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 0;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div) - 1;
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/* arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
- *
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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.
- *
- * Simtec Audio support.
-*/
-
-/**
- * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
- * @use_mpllin: Select codec clock from MPLLin
- * @output_cdclk: Need to output CDCLK to the codec
- * @have_mic: Set if we have a MIC socket
- * @have_lout: Set if we have a LineOut socket
- * @amp_gpio: GPIO pin to enable the AMP
- * @amp_gain: Option GPIO to control AMP gain
- */
-struct s3c24xx_audio_simtec_pdata {
-	unsigned int	use_mpllin:1;
-	unsigned int	output_cdclk:1;
-
-	unsigned int	have_mic:1;
-	unsigned int	have_lout:1;
-
-	int		amp_gpio;
-	int		amp_gain[2];
-
-	void	(*startup)(void);
-};
-
-extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
-			    struct s3c24xx_audio_simtec_pdata *pdata);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/common-smdk.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/common-smdk.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/common-smdk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/common-smdk.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Common code for SMDK2410 and SMDK2440 boards
- *
- * http://www.fluff.org/ben/smdk2440/
- *
- * 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.
-*/
-
-extern void smdk_machine_init(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,287 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/cpu-freq.h
- *
- * Copyright (c) 2006-2009 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C CPU frequency scaling support - core support
- *
- * 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 <plat/cpu-freq.h>
-
-struct seq_file;
-
-#define MAX_BANKS (8)
-#define S3C2412_MAX_IO	(8)
-
-/**
- * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
- * @bankcon: The cached version of settings in this structure.
- * @tacp:
- * @tacs: Time from address valid to nCS asserted.
- * @tcos: Time from nCS asserted to nOE or nWE asserted.
- * @tacc: Time that nOE or nWE is asserted.
- * @tcoh: Time nCS is held after nOE or nWE are released.
- * @tcah: Time address is held for after
- * @nwait_en: Whether nWAIT is enabled for this bank.
- *
- * This structure represents the IO timings for a S3C2410 style IO bank
- * used by the CPU frequency support if it needs to change the settings
- * of the IO.
- */
-struct s3c2410_iobank_timing {
-	unsigned long	bankcon;
-	unsigned int	tacp;
-	unsigned int	tacs;
-	unsigned int	tcos;
-	unsigned int	tacc;
-	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
-	unsigned int	tcah;		/* Address hold after nCS */
-	unsigned char	nwait_en;	/* nWait enabled for bank. */
-};
-
-/**
- * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
- * @idcy: The idle cycle time between transactions.
- * @wstrd: nCS release to end of read cycle.
- * @wstwr: nCS release to end of write cycle.
- * @wstoen: nCS assertion to nOE assertion time.
- * @wstwen: nCS assertion to nWE assertion time.
- * @wstbrd: Burst ready delay.
- * @smbidcyr: Register cache for smbidcyr value.
- * @smbwstrd: Register cache for smbwstrd value.
- * @smbwstwr: Register cache for smbwstwr value.
- * @smbwstoen: Register cache for smbwstoen value.
- * @smbwstwen: Register cache for smbwstwen value.
- * @smbwstbrd: Register cache for smbwstbrd value.
- *
- * Timing information for a IO bank on an S3C2412 or similar system which
- * uses a PL093 block.
- */
-struct s3c2412_iobank_timing {
-	unsigned int	idcy;
-	unsigned int	wstrd;
-	unsigned int	wstwr;
-	unsigned int	wstoen;
-	unsigned int	wstwen;
-	unsigned int	wstbrd;
-
-	/* register cache */
-	unsigned char	smbidcyr;
-	unsigned char	smbwstrd;
-	unsigned char	smbwstwr;
-	unsigned char	smbwstoen;
-	unsigned char	smbwstwen;
-	unsigned char	smbwstbrd;
-};
-
-union s3c_iobank {
-	struct s3c2410_iobank_timing	*io_2410;
-	struct s3c2412_iobank_timing	*io_2412;
-};
-
-/**
- * struct s3c_iotimings - Chip IO timings holder
- * @bank: The timings for each IO bank.
- */
-struct s3c_iotimings {
-	union s3c_iobank	bank[MAX_BANKS];
-};
-
-/**
- * struct s3c_plltab - PLL table information.
- * @vals: List of PLL values.
- * @size: Size of the PLL table @vals.
- */
-struct s3c_plltab {
-	struct s3c_pllval	*vals;
-	int			 size;
-};
-
-/**
- * struct s3c_cpufreq_config - current cpu frequency configuration
- * @freq: The current settings for the core clocks.
- * @max: Maxium settings, derived from core, board and user settings.
- * @pll: The PLL table entry for the current PLL settings.
- * @divs: The divisor settings for the core clocks.
- * @info: The current core driver information.
- * @board: The information for the board we are running on.
- * @lock_pll: Set if the PLL settings cannot be changed.
- *
- * This is for the core drivers that need to know information about
- * the current settings and values. It should not be needed by any
- * device drivers.
-*/
-struct s3c_cpufreq_config {
-	struct s3c_freq		freq;
-	struct s3c_freq		max;
-	struct cpufreq_frequency_table pll;
-	struct s3c_clkdivs	divs;
-	struct s3c_cpufreq_info *info;	/* for core, not drivers */
-	struct s3c_cpufreq_board *board;
-
-	unsigned int	lock_pll:1;
-};
-
-/**
- * struct s3c_cpufreq_info - Information for the CPU frequency driver.
- * @name: The name of this implementation.
- * @max: The maximum frequencies for the system.
- * @latency: Transition latency to give to cpufreq.
- * @locktime_m: The lock-time in uS for the MPLL.
- * @locktime_u: The lock-time in uS for the UPLL.
- * @locttime_bits: The number of bits each LOCKTIME field.
- * @need_pll: Set if this driver needs to change the PLL values to achieve
- *	any frequency changes. This is really only need by devices like the
- *	S3C2410 where there is no or limited divider between the PLL and the
- *	ARMCLK.
- * @resume_clocks: Update the clocks on resume.
- * @get_iotiming: Get the current IO timing data, mainly for use at start.
- * @set_iotiming: Update the IO timings from the cached copies calculated
- *	from the @calc_iotiming entry when changing the frequency.
- * @calc_iotiming: Calculate and update the cached copies of the IO timings
- *	from the newly calculated frequencies.
- * @calc_freqtable: Calculate (fill in) the given frequency table from the
- *	current frequency configuration. If the table passed in is NULL,
- *	then the return is the number of elements to be filled for allocation
- *	of the table.
- * @set_refresh: Set the memory refresh configuration.
- * @set_fvco: Set the PLL frequencies.
- * @set_divs: Update the clock divisors.
- * @calc_divs: Calculate the clock divisors.
- */
-struct s3c_cpufreq_info {
-	const char		*name;
-	struct s3c_freq		max;
-
-	unsigned int		latency;
-
-	unsigned int		locktime_m;
-	unsigned int		locktime_u;
-	unsigned char		locktime_bits;
-
-	unsigned int		need_pll:1;
-
-	/* driver routines */
-
-	void		(*resume_clocks)(void);
-
-	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
-					struct s3c_iotimings *timings);
-
-	void		(*set_iotiming)(struct s3c_cpufreq_config *cfg,
-					struct s3c_iotimings *timings);
-
-	int		(*calc_iotiming)(struct s3c_cpufreq_config *cfg,
-					 struct s3c_iotimings *timings);
-
-	int		(*calc_freqtable)(struct s3c_cpufreq_config *cfg,
-					  struct cpufreq_frequency_table *t,
-					  size_t table_size);
-
-	void		(*debug_io_show)(struct seq_file *seq,
-					 struct s3c_cpufreq_config *cfg,
-					 union s3c_iobank *iob);
-
-	void		(*set_refresh)(struct s3c_cpufreq_config *cfg);
-	void		(*set_fvco)(struct s3c_cpufreq_config *cfg);
-	void		(*set_divs)(struct s3c_cpufreq_config *cfg);
-	int		(*calc_divs)(struct s3c_cpufreq_config *cfg);
-};
-
-extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
-
-extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no);
-
-/* exports and utilities for debugfs */
-extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
-extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
-
-extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
-				     struct s3c_cpufreq_config *cfg,
-				     union s3c_iobank *iob);
-
-extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
-				     struct s3c_cpufreq_config *cfg,
-				     union s3c_iobank *iob);
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
-#define s3c_cpufreq_debugfs_call(x) x
-#else
-#define s3c_cpufreq_debugfs_call(x) NULL
-#endif
-
-/* Useful utility functions. */
-
-extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
-
-/* S3C2410 and compatible exported functions */
-
-extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
-extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
-
-#ifdef CONFIG_S3C2410_IOTIMING
-extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-#else
-#define s3c2410_iotiming_calc NULL
-#define s3c2410_iotiming_get NULL
-#define s3c2410_iotiming_set NULL
-#endif /* CONFIG_S3C2410_IOTIMING */
-
-/* S3C2412 compatible routines */
-
-extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
-#define s3c_freq_dbg(x...) printk(KERN_INFO x)
-#else
-#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
-#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
-#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
-#else
-#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
-#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
-
-static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
-				      int index, size_t table_size,
-				      unsigned int freq)
-{
-	if (index < 0)
-		return index;
-
-	if (table) {
-		if (index >= table_size)
-			return -ENOMEM;
-
-		s3c_freq_dbg("%s: { %d = %u kHz }\n",
-			     __func__, index, freq);
-
-		table[index].index = index;
-		table[index].frequency = freq;
-	}
-
-	return index + 1;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/fiq.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/fiq.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/fiq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/fiq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/fiq.h
- *
- * Copyright (c) 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU FIQ support
- *
- * 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.
-*/
-
-extern int s3c24xx_set_fiq(unsigned int irq, bool on);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/irq.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU IRQ support
- *
- * 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/io.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#define irqdbf(x...)
-#define irqdbf2(x...)
-
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
-/* these are exported for arch/arm/mach-* usage */
-extern struct irq_chip s3c_irq_level_chip;
-extern struct irq_chip s3c_irq_chip;
-
-static inline void
-s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-		int subcheck)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-
-	/* check to see if we need to mask the parent IRQ */
-
-	if ((submask  & subcheck) == subcheck) {
-		__raw_writel(mask | parentbit, S3C2410_INTMSK);
-	}
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-
-}
-
-static inline void
-s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-	mask &= ~parentbit;
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-
-static inline void
-s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	s3c_irqsub_mask(irqno, parentmask, group);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-static inline void
-s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-/* exported for use in arch/arm/mach-s3c2410 */
-
-#ifdef CONFIG_PM
-extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
-#else
-#define s3c_irq_wake NULL
-#endif
-
-extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/map.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/map.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/map.h
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S3C24XX_MAP_H
-#define __ASM_PLAT_S3C24XX_MAP_H
-
-/* interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-#define S3C24XX_VA_IRQ	   S3C_VA_IRQ
-#define S3C2410_PA_IRQ	   (0x4A000000)
-#define S3C24XX_SZ_IRQ	   SZ_1M
-
-/* memory controller registers */
-#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
-#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C24XX_SZ_MEMCTRL SZ_1M
-
-/* UARTs */
-#define S3C24XX_VA_UART	   S3C_VA_UART
-#define S3C2410_PA_UART	   (0x50000000)
-#define S3C24XX_SZ_UART	   SZ_1M
-#define S3C_UART_OFFSET	   (0x4000)
-
-#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
-
-/* Timers */
-#define S3C24XX_VA_TIMER   S3C_VA_TIMER
-#define S3C2410_PA_TIMER   (0x51000000)
-#define S3C24XX_SZ_TIMER   SZ_1M
-
-/* Clock and Power management */
-#define S3C24XX_VA_CLKPWR  S3C_VA_SYS
-#define S3C24XX_SZ_CLKPWR  SZ_1M
-
-/* USB Device port */
-#define S3C2410_PA_USBDEV  (0x52000000)
-#define S3C24XX_SZ_USBDEV  SZ_1M
-
-/* Watchdog */
-#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
-#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C24XX_SZ_WATCHDOG SZ_1M
-
-/* Standard size definitions for peripheral blocks. */
-
-#define S3C24XX_SZ_IIS		SZ_1M
-#define S3C24XX_SZ_ADC		SZ_1M
-#define S3C24XX_SZ_SPI		SZ_1M
-#define S3C24XX_SZ_SDI		SZ_1M
-#define S3C24XX_SZ_NAND		SZ_1M
-
-/* GPIO ports */
-
-/* the calculation for the VA of this must ensure that
- * it is the same distance apart from the UART in the
- * phsyical address space, as the initial mapping for the IO
- * is done as a 1:1 mapping. This puts it (currently) at
- * 0xFA800000, which is not in the way of any current mapping
- * by the base system.
-*/
-
-#define S3C2410_PA_GPIO	   (0x56000000)
-#define S3C24XX_VA_GPIO	   ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
-#define S3C24XX_SZ_GPIO	   SZ_1M
-
-
-/* ISA style IO, for each machine to sort out mappings for, if it
- * implements it. We reserve two 16M regions for ISA.
- */
-
-#define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
-#define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
-
-/* deal with the registers that move under the 2412/2413 */
-
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-#ifndef __ASSEMBLY__
-extern void __iomem *s3c24xx_va_gpio2;
-#endif
-#ifdef CONFIG_CPU_S3C2412_ONLY
-#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
-#else
-#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
-#endif
-#else
-#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
-#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
-#endif
-
-#endif /* __ASM_PLAT_S3C24XX_MAP_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/mci.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/mci.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/mci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/mci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-#ifndef _ARCH_MCI_H
-#define _ARCH_MCI_H
-
-/**
- * struct s3c24xx_mci_pdata - sd/mmc controller platform data
- * @no_wprotect: Set this to indicate there is no write-protect switch.
- * @no_detect: Set this if there is no detect switch.
- * @wprotect_invert: Invert the default sense of the write protect switch.
- * @detect_invert: Invert the default sense of the write protect switch.
- * @use_dma: Set to allow the use of DMA.
- * @gpio_detect: GPIO number for the card detect line.
- * @gpio_wprotect: GPIO number for the write protect line.
- * @ocr_avail: The mask of the available power states, non-zero to use.
- * @set_power: Callback to control the power mode.
- *
- * The @gpio_detect is used for card detection when @no_wprotect is unset,
- * and the default sense is that 0 returned from gpio_get_value() means
- * that a card is inserted. If @detect_invert is set, then the value from
- * gpio_get_value() is inverted, which makes 1 mean card inserted.
- *
- * The driver will use @gpio_wprotect to signal whether the card is write
- * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
- * means the card is read/write, and 1 means read-only. The @wprotect_invert
- * will invert the value returned from gpio_get_value().
- *
- * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
- * to a non-zero value, otherwise the default of 3.2-3.4V is used.
- */
-struct s3c24xx_mci_pdata {
-	unsigned int	no_wprotect : 1;
-	unsigned int	no_detect : 1;
-	unsigned int	wprotect_invert : 1;
-	unsigned int	detect_invert : 1;   /* set => detect active high. */
-	unsigned int	use_dma : 1;
-
-	unsigned int	gpio_detect;
-	unsigned int	gpio_wprotect;
-	unsigned long	ocr_avail;
-	void		(*set_power)(unsigned char power_mode,
-				     unsigned short vdd);
-};
-
-/**
- * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
- * @pdata: The platform data
- *
- * Copy the platform data supplied by @pdata so that this can be marked
- * __initdata.
- */
-extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
-
-#endif /* _ARCH_NCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/pll.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/pll.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - common pll registers and code
- */
-
-#define S3C24XX_PLLCON_MDIVSHIFT	12
-#define S3C24XX_PLLCON_PDIVSHIFT	4
-#define S3C24XX_PLLCON_SDIVSHIFT	0
-#define S3C24XX_PLLCON_MDIVMASK		((1<<(1+(19-12)))-1)
-#define S3C24XX_PLLCON_PDIVMASK		((1<<5)-1)
-#define S3C24XX_PLLCON_SDIVMASK		3
-
-#include <asm/div64.h>
-
-static inline unsigned int
-s3c24xx_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-	unsigned int mdiv, pdiv, sdiv;
-	uint64_t fvco;
-
-	mdiv = pllval >> S3C24XX_PLLCON_MDIVSHIFT;
-	pdiv = pllval >> S3C24XX_PLLCON_PDIVSHIFT;
-	sdiv = pllval >> S3C24XX_PLLCON_SDIVSHIFT;
-
-	mdiv &= S3C24XX_PLLCON_MDIVMASK;
-	pdiv &= S3C24XX_PLLCON_PDIVMASK;
-	sdiv &= S3C24XX_PLLCON_SDIVMASK;
-
-	fvco = (uint64_t)baseclk * (mdiv + 8);
-	do_div(fvco, (pdiv + 2) << sdiv);
-
-	return (unsigned int)fvco;
-}
-
-#define S3C2416_PLL_M_SHIFT	(14)
-#define S3C2416_PLL_P_SHIFT	(5)
-#define S3C2416_PLL_S_MASK	(7)
-#define S3C2416_PLL_M_MASK	((1 << 10) - 1)
-#define S3C2416_PLL_P_MASK	(63)
-
-static inline unsigned int
-s3c2416_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-	unsigned int m, p, s;
-	uint64_t fvco;
-
-	m = pllval >> S3C2416_PLL_M_SHIFT;
-	p = pllval >> S3C2416_PLL_P_SHIFT;
-
-	s = pllval & S3C2416_PLL_S_MASK;
-	m &= S3C2416_PLL_M_MASK;
-	p &= S3C2416_PLL_P_MASK;
-
-	fvco = (uint64_t)baseclk * m;
-	do_div(fvco, (p << s));
-
-	return (unsigned int)fvco;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-dma.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-dma.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/dma.h
- *
- * Copyright (C) 2003-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA support
- *
- * 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.
-*/
-
-/* DMA Register definitions */
-
-#define S3C2410_DMA_DISRC		(0x00)
-#define S3C2410_DMA_DISRCC		(0x04)
-#define S3C2410_DMA_DIDST		(0x08)
-#define S3C2410_DMA_DIDSTC		(0x0C)
-#define S3C2410_DMA_DCON		(0x10)
-#define S3C2410_DMA_DSTAT		(0x14)
-#define S3C2410_DMA_DCSRC		(0x18)
-#define S3C2410_DMA_DCDST		(0x1C)
-#define S3C2410_DMA_DMASKTRIG		(0x20)
-#define S3C2412_DMA_DMAREQSEL		(0x24)
-#define S3C2443_DMA_DMAREQSEL		(0x24)
-
-#define S3C2410_DISRCC_INC		(1<<0)
-#define S3C2410_DISRCC_APB		(1<<1)
-
-#define S3C2410_DMASKTRIG_STOP		(1<<2)
-#define S3C2410_DMASKTRIG_ON		(1<<1)
-#define S3C2410_DMASKTRIG_SWTRIG	(1<<0)
-
-#define S3C2410_DCON_DEMAND		(0<<31)
-#define S3C2410_DCON_HANDSHAKE		(1<<31)
-#define S3C2410_DCON_SYNC_PCLK		(0<<30)
-#define S3C2410_DCON_SYNC_HCLK		(1<<30)
-
-#define S3C2410_DCON_INTREQ		(1<<29)
-
-#define S3C2410_DCON_CH0_XDREQ0		(0<<24)
-#define S3C2410_DCON_CH0_UART0		(1<<24)
-#define S3C2410_DCON_CH0_SDI		(2<<24)
-#define S3C2410_DCON_CH0_TIMER		(3<<24)
-#define S3C2410_DCON_CH0_USBEP1		(4<<24)
-
-#define S3C2410_DCON_CH1_XDREQ1		(0<<24)
-#define S3C2410_DCON_CH1_UART1		(1<<24)
-#define S3C2410_DCON_CH1_I2SSDI		(2<<24)
-#define S3C2410_DCON_CH1_SPI		(3<<24)
-#define S3C2410_DCON_CH1_USBEP2		(4<<24)
-
-#define S3C2410_DCON_CH2_I2SSDO		(0<<24)
-#define S3C2410_DCON_CH2_I2SSDI		(1<<24)
-#define S3C2410_DCON_CH2_SDI		(2<<24)
-#define S3C2410_DCON_CH2_TIMER		(3<<24)
-#define S3C2410_DCON_CH2_USBEP3		(4<<24)
-
-#define S3C2410_DCON_CH3_UART2		(0<<24)
-#define S3C2410_DCON_CH3_SDI		(1<<24)
-#define S3C2410_DCON_CH3_SPI		(2<<24)
-#define S3C2410_DCON_CH3_TIMER		(3<<24)
-#define S3C2410_DCON_CH3_USBEP4		(4<<24)
-
-#define S3C2410_DCON_SRCSHIFT		(24)
-#define S3C2410_DCON_SRCMASK		(7<<24)
-
-#define S3C2410_DCON_BYTE		(0<<20)
-#define S3C2410_DCON_HALFWORD		(1<<20)
-#define S3C2410_DCON_WORD		(2<<20)
-
-#define S3C2410_DCON_AUTORELOAD		(0<<22)
-#define S3C2410_DCON_NORELOAD		(1<<22)
-#define S3C2410_DCON_HWTRIG		(1<<23)
-
-#ifdef CONFIG_CPU_S3C2440
-#define S3C2440_DIDSTC_CHKINT		(1<<2)
-
-#define S3C2440_DCON_CH0_I2SSDO		(5<<24)
-#define S3C2440_DCON_CH0_PCMIN		(6<<24)
-
-#define S3C2440_DCON_CH1_PCMOUT		(5<<24)
-#define S3C2440_DCON_CH1_SDI		(6<<24)
-
-#define S3C2440_DCON_CH2_PCMIN		(5<<24)
-#define S3C2440_DCON_CH2_MICIN		(6<<24)
-
-#define S3C2440_DCON_CH3_MICIN		(5<<24)
-#define S3C2440_DCON_CH3_PCMOUT		(6<<24)
-#endif
-
-#ifdef CONFIG_CPU_S3C2412
-
-#define S3C2412_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2412_DMAREQSEL_HW		(1)
-
-#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
-#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
-#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
-#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
-#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
-#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
-#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
-#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
-#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
-#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
-#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
-#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
-#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
-#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
-#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
-#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
-#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
-#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
-#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
-#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
-
-#endif
-
-#define S3C2443_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2443_DMAREQSEL_HW		(1)
-
-#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
-#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
-#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
-#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
-#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
-#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
-#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
-#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
-#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
-#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
-#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
-#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
-#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
-#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
-#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
-#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
-#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
-#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
-#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
-#define S3C2443_DMAREQSEL_PCMIN 	S3C2443_DMAREQSEL_SRC(28)
-#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-iis.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-iis.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-iis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * 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.
- *
- * S3C2410 IIS register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_IIS_H
-#define __ASM_ARCH_REGS_IIS_H
-
-#define S3C2410_IISCON	 (0x00)
-
-#define S3C2410_IISCON_LRINDEX	  (1<<8)
-#define S3C2410_IISCON_TXFIFORDY  (1<<7)
-#define S3C2410_IISCON_RXFIFORDY  (1<<6)
-#define S3C2410_IISCON_TXDMAEN	  (1<<5)
-#define S3C2410_IISCON_RXDMAEN	  (1<<4)
-#define S3C2410_IISCON_TXIDLE	  (1<<3)
-#define S3C2410_IISCON_RXIDLE	  (1<<2)
-#define S3C2410_IISCON_PSCEN	  (1<<1)
-#define S3C2410_IISCON_IISEN	  (1<<0)
-
-#define S3C2410_IISMOD	 (0x04)
-
-#define S3C2440_IISMOD_MPLL	  (1<<9)
-#define S3C2410_IISMOD_SLAVE	  (1<<8)
-#define S3C2410_IISMOD_NOXFER	  (0<<6)
-#define S3C2410_IISMOD_RXMODE	  (1<<6)
-#define S3C2410_IISMOD_TXMODE	  (2<<6)
-#define S3C2410_IISMOD_TXRXMODE	  (3<<6)
-#define S3C2410_IISMOD_LR_LLOW	  (0<<5)
-#define S3C2410_IISMOD_LR_RLOW	  (1<<5)
-#define S3C2410_IISMOD_IIS	  (0<<4)
-#define S3C2410_IISMOD_MSB	  (1<<4)
-#define S3C2410_IISMOD_8BIT	  (0<<3)
-#define S3C2410_IISMOD_16BIT	  (1<<3)
-#define S3C2410_IISMOD_BITMASK	  (1<<3)
-#define S3C2410_IISMOD_256FS	  (0<<2)
-#define S3C2410_IISMOD_384FS	  (1<<2)
-#define S3C2410_IISMOD_16FS	  (0<<0)
-#define S3C2410_IISMOD_32FS	  (1<<0)
-#define S3C2410_IISMOD_48FS	  (2<<0)
-#define S3C2410_IISMOD_FS_MASK	  (3<<0)
-
-#define S3C2410_IISPSR		(0x08)
-#define S3C2410_IISPSR_INTMASK	(31<<5)
-#define S3C2410_IISPSR_INTSHIFT	(5)
-#define S3C2410_IISPSR_EXTMASK	(31<<0)
-#define S3C2410_IISPSR_EXTSHFIT	(0)
-
-#define S3C2410_IISFCON  (0x0c)
-
-#define S3C2410_IISFCON_TXDMA	  (1<<15)
-#define S3C2410_IISFCON_RXDMA	  (1<<14)
-#define S3C2410_IISFCON_TXENABLE  (1<<13)
-#define S3C2410_IISFCON_RXENABLE  (1<<12)
-#define S3C2410_IISFCON_TXMASK	  (0x3f << 6)
-#define S3C2410_IISFCON_TXSHIFT	  (6)
-#define S3C2410_IISFCON_RXMASK	  (0x3f)
-#define S3C2410_IISFCON_RXSHIFT	  (0)
-
-#define S3C2410_IISFIFO  (0x10)
-#endif /* __ASM_ARCH_REGS_IIS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-spi.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-spi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-spi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-spi.h
- *
- * Copyright (c) 2004 Fetron GmbH
- *
- * 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.
- *
- * S3C2410 SPI register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_SPI_H
-#define __ASM_ARCH_REGS_SPI_H
-
-#define S3C2410_SPI1	(0x20)
-#define S3C2412_SPI1	(0x100)
-
-#define S3C2410_SPCON	(0x00)
-
-#define S3C2412_SPCON_RXFIFO_RB2	(0<<14)
-#define S3C2412_SPCON_RXFIFO_RB4	(1<<14)
-#define S3C2412_SPCON_RXFIFO_RB12	(2<<14)
-#define S3C2412_SPCON_RXFIFO_RB14	(3<<14)
-#define S3C2412_SPCON_TXFIFO_RB2	(0<<12)
-#define S3C2412_SPCON_TXFIFO_RB4	(1<<12)
-#define S3C2412_SPCON_TXFIFO_RB12	(2<<12)
-#define S3C2412_SPCON_TXFIFO_RB14	(3<<12)
-#define S3C2412_SPCON_RXFIFO_RESET	(1<<11) /* RxFIFO reset */
-#define S3C2412_SPCON_TXFIFO_RESET	(1<<10) /* TxFIFO reset */
-#define S3C2412_SPCON_RXFIFO_EN		(1<<9)  /* RxFIFO Enable */
-#define S3C2412_SPCON_TXFIFO_EN		(1<<8)  /* TxFIFO Enable */
-
-#define S3C2412_SPCON_DIRC_RX	  (1<<7)
-
-#define S3C2410_SPCON_SMOD_DMA	  (2<<5)	/* DMA mode */
-#define S3C2410_SPCON_SMOD_INT	  (1<<5)	/* interrupt mode */
-#define S3C2410_SPCON_SMOD_POLL   (0<<5)	/* polling mode */
-#define S3C2410_SPCON_ENSCK	  (1<<4)	/* Enable SCK */
-#define S3C2410_SPCON_MSTR	  (1<<3)	/* Master/Slave select
-						   0: slave, 1: master */
-#define S3C2410_SPCON_CPOL_HIGH	  (1<<2)	/* Clock polarity select */
-#define S3C2410_SPCON_CPOL_LOW	  (0<<2)	/* Clock polarity select */
-
-#define S3C2410_SPCON_CPHA_FMTB	  (1<<1)	/* Clock Phase Select */
-#define S3C2410_SPCON_CPHA_FMTA	  (0<<1)	/* Clock Phase Select */
-
-#define S3C2410_SPCON_TAGD	  (1<<0)	/* Tx auto garbage data mode */
-
-
-#define S3C2410_SPSTA	 (0x04)
-
-#define S3C2412_SPSTA_RXFIFO_AE		(1<<11)
-#define S3C2412_SPSTA_TXFIFO_AE		(1<<10)
-#define S3C2412_SPSTA_RXFIFO_ERROR	(1<<9)
-#define S3C2412_SPSTA_TXFIFO_ERROR	(1<<8)
-#define S3C2412_SPSTA_RXFIFO_FIFO	(1<<7)
-#define S3C2412_SPSTA_RXFIFO_EMPTY	(1<<6)
-#define S3C2412_SPSTA_TXFIFO_NFULL	(1<<5)
-#define S3C2412_SPSTA_TXFIFO_EMPTY	(1<<4)
-
-#define S3C2410_SPSTA_DCOL	  (1<<2)	/* Data Collision Error */
-#define S3C2410_SPSTA_MULD	  (1<<1)	/* Multi Master Error */
-#define S3C2410_SPSTA_READY	  (1<<0)	/* Data Tx/Rx ready */
-#define S3C2412_SPSTA_READY_ORG	  (1<<3)
-
-#define S3C2410_SPPIN	 (0x08)
-
-#define S3C2410_SPPIN_ENMUL	  (1<<2)	/* Multi Master Error detect */
-#define S3C2410_SPPIN_RESERVED	  (1<<1)
-#define S3C2410_SPPIN_KEEP	  (1<<0)	/* Master Out keep */
-
-#define S3C2410_SPPRE	 (0x0C)
-#define S3C2410_SPTDAT	 (0x10)
-#define S3C2410_SPRDAT	 (0x14)
-
-#define S3C2412_TXFIFO	 (0x18)
-#define S3C2412_RXFIFO	 (0x18)
-#define S3C2412_SPFIC	 (0x24)
-
-
-#endif /* __ASM_ARCH_REGS_SPI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-udc.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-udc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-udc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/regs-udc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-udc.h
- *
- * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
- *
- * This include file 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 __ASM_ARCH_REGS_UDC_H
-#define __ASM_ARCH_REGS_UDC_H
-
-#define S3C2410_USBDREG(x) (x)
-
-#define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
-#define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
-#define S3C2410_UDC_EP_INT_REG		S3C2410_USBDREG(0x0148)
-
-#define S3C2410_UDC_USB_INT_REG		S3C2410_USBDREG(0x0158)
-#define S3C2410_UDC_EP_INT_EN_REG	S3C2410_USBDREG(0x015c)
-
-#define S3C2410_UDC_USB_INT_EN_REG	S3C2410_USBDREG(0x016c)
-
-#define S3C2410_UDC_FRAME_NUM1_REG	S3C2410_USBDREG(0x0170)
-#define S3C2410_UDC_FRAME_NUM2_REG	S3C2410_USBDREG(0x0174)
-
-#define S3C2410_UDC_EP0_FIFO_REG	S3C2410_USBDREG(0x01c0)
-#define S3C2410_UDC_EP1_FIFO_REG	S3C2410_USBDREG(0x01c4)
-#define S3C2410_UDC_EP2_FIFO_REG	S3C2410_USBDREG(0x01c8)
-#define S3C2410_UDC_EP3_FIFO_REG	S3C2410_USBDREG(0x01cc)
-#define S3C2410_UDC_EP4_FIFO_REG	S3C2410_USBDREG(0x01d0)
-
-#define S3C2410_UDC_EP1_DMA_CON		S3C2410_USBDREG(0x0200)
-#define S3C2410_UDC_EP1_DMA_UNIT	S3C2410_USBDREG(0x0204)
-#define S3C2410_UDC_EP1_DMA_FIFO	S3C2410_USBDREG(0x0208)
-#define S3C2410_UDC_EP1_DMA_TTC_L	S3C2410_USBDREG(0x020c)
-#define S3C2410_UDC_EP1_DMA_TTC_M	S3C2410_USBDREG(0x0210)
-#define S3C2410_UDC_EP1_DMA_TTC_H	S3C2410_USBDREG(0x0214)
-
-#define S3C2410_UDC_EP2_DMA_CON		S3C2410_USBDREG(0x0218)
-#define S3C2410_UDC_EP2_DMA_UNIT	S3C2410_USBDREG(0x021c)
-#define S3C2410_UDC_EP2_DMA_FIFO	S3C2410_USBDREG(0x0220)
-#define S3C2410_UDC_EP2_DMA_TTC_L	S3C2410_USBDREG(0x0224)
-#define S3C2410_UDC_EP2_DMA_TTC_M	S3C2410_USBDREG(0x0228)
-#define S3C2410_UDC_EP2_DMA_TTC_H	S3C2410_USBDREG(0x022c)
-
-#define S3C2410_UDC_EP3_DMA_CON		S3C2410_USBDREG(0x0240)
-#define S3C2410_UDC_EP3_DMA_UNIT	S3C2410_USBDREG(0x0244)
-#define S3C2410_UDC_EP3_DMA_FIFO	S3C2410_USBDREG(0x0248)
-#define S3C2410_UDC_EP3_DMA_TTC_L	S3C2410_USBDREG(0x024c)
-#define S3C2410_UDC_EP3_DMA_TTC_M	S3C2410_USBDREG(0x0250)
-#define S3C2410_UDC_EP3_DMA_TTC_H	S3C2410_USBDREG(0x0254)
-
-#define S3C2410_UDC_EP4_DMA_CON		S3C2410_USBDREG(0x0258)
-#define S3C2410_UDC_EP4_DMA_UNIT	S3C2410_USBDREG(0x025c)
-#define S3C2410_UDC_EP4_DMA_FIFO	S3C2410_USBDREG(0x0260)
-#define S3C2410_UDC_EP4_DMA_TTC_L	S3C2410_USBDREG(0x0264)
-#define S3C2410_UDC_EP4_DMA_TTC_M	S3C2410_USBDREG(0x0268)
-#define S3C2410_UDC_EP4_DMA_TTC_H	S3C2410_USBDREG(0x026c)
-
-#define S3C2410_UDC_INDEX_REG		S3C2410_USBDREG(0x0178)
-
-/* indexed registers */
-
-#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x0180)
-
-#define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
-
-#define S3C2410_UDC_IN_CSR1_REG		S3C2410_USBDREG(0x0184)
-#define S3C2410_UDC_IN_CSR2_REG		S3C2410_USBDREG(0x0188)
-
-#define S3C2410_UDC_OUT_CSR1_REG	S3C2410_USBDREG(0x0190)
-#define S3C2410_UDC_OUT_CSR2_REG	S3C2410_USBDREG(0x0194)
-#define S3C2410_UDC_OUT_FIFO_CNT1_REG	S3C2410_USBDREG(0x0198)
-#define S3C2410_UDC_OUT_FIFO_CNT2_REG	S3C2410_USBDREG(0x019c)
-
-#define S3C2410_UDC_FUNCADDR_UPDATE	(1<<7)
-
-#define S3C2410_UDC_PWR_ISOUP		(1<<7) // R/W
-#define S3C2410_UDC_PWR_RESET		(1<<3) // R
-#define S3C2410_UDC_PWR_RESUME		(1<<2) // R/W
-#define S3C2410_UDC_PWR_SUSPEND		(1<<1) // R
-#define S3C2410_UDC_PWR_ENSUSPEND	(1<<0) // R/W
-
-#define S3C2410_UDC_PWR_DEFAULT		0x00
-
-#define S3C2410_UDC_INT_EP4		(1<<4) // R/W (clear only)
-#define S3C2410_UDC_INT_EP3		(1<<3) // R/W (clear only)
-#define S3C2410_UDC_INT_EP2		(1<<2) // R/W (clear only)
-#define S3C2410_UDC_INT_EP1		(1<<1) // R/W (clear only)
-#define S3C2410_UDC_INT_EP0		(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_USBINT_RESET	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_USBINT_RESUME	(1<<1) // R/W (clear only)
-#define S3C2410_UDC_USBINT_SUSPEND	(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_INTE_EP4		(1<<4) // R/W
-#define S3C2410_UDC_INTE_EP3		(1<<3) // R/W
-#define S3C2410_UDC_INTE_EP2		(1<<2) // R/W
-#define S3C2410_UDC_INTE_EP1		(1<<1) // R/W
-#define S3C2410_UDC_INTE_EP0		(1<<0) // R/W
-
-#define S3C2410_UDC_USBINTE_RESET	(1<<2) // R/W
-#define S3C2410_UDC_USBINTE_SUSPEND	(1<<0) // R/W
-
-
-#define S3C2410_UDC_INDEX_EP0		(0x00)
-#define S3C2410_UDC_INDEX_EP1		(0x01) // ??
-#define S3C2410_UDC_INDEX_EP2		(0x02) // ??
-#define S3C2410_UDC_INDEX_EP3		(0x03) // ??
-#define S3C2410_UDC_INDEX_EP4		(0x04) // ??
-
-#define S3C2410_UDC_ICSR1_CLRDT		(1<<6) // R/W
-#define S3C2410_UDC_ICSR1_SENTSTL	(1<<5) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_SENDSTL	(1<<4) // R/W
-#define S3C2410_UDC_ICSR1_FFLUSH	(1<<3) // W   (set only)
-#define S3C2410_UDC_ICSR1_UNDRUN	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_PKTRDY	(1<<0) // R/W (set only)
-
-#define S3C2410_UDC_ICSR2_AUTOSET	(1<<7) // R/W
-#define S3C2410_UDC_ICSR2_ISO		(1<<6) // R/W
-#define S3C2410_UDC_ICSR2_MODEIN	(1<<5) // R/W
-#define S3C2410_UDC_ICSR2_DMAIEN	(1<<4) // R/W
-
-#define S3C2410_UDC_OCSR1_CLRDT		(1<<7) // R/W
-#define S3C2410_UDC_OCSR1_SENTSTL	(1<<6) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_SENDSTL	(1<<5) // R/W
-#define S3C2410_UDC_OCSR1_FFLUSH	(1<<4) // R/W
-#define S3C2410_UDC_OCSR1_DERROR	(1<<3) // R
-#define S3C2410_UDC_OCSR1_OVRRUN	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_PKTRDY	(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_OCSR2_AUTOCLR	(1<<7) // R/W
-#define S3C2410_UDC_OCSR2_ISO		(1<<6) // R/W
-#define S3C2410_UDC_OCSR2_DMAIEN	(1<<5) // R/W
-
-#define S3C2410_UDC_EP0_CSR_OPKRDY	(1<<0)
-#define S3C2410_UDC_EP0_CSR_IPKRDY	(1<<1)
-#define S3C2410_UDC_EP0_CSR_SENTSTL	(1<<2)
-#define S3C2410_UDC_EP0_CSR_DE		(1<<3)
-#define S3C2410_UDC_EP0_CSR_SE		(1<<4)
-#define S3C2410_UDC_EP0_CSR_SENDSTL	(1<<5)
-#define S3C2410_UDC_EP0_CSR_SOPKTRDY	(1<<6)
-#define S3C2410_UDC_EP0_CSR_SSE	(1<<7)
-
-#define S3C2410_UDC_MAXP_8		(1<<0)
-#define S3C2410_UDC_MAXP_16		(1<<1)
-#define S3C2410_UDC_MAXP_32		(1<<2)
-#define S3C2410_UDC_MAXP_64		(1<<3)
-
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2410.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2410.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2410.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 machine directory
- *
- * 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.
- *
-*/
-
-#ifdef CONFIG_CPU_S3C2410
-
-extern  int s3c2410_init(void);
-extern  int s3c2410a_init(void);
-
-extern void s3c2410_map_io(void);
-
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2410_init_clocks(int xtal);
-
-#else
-#define s3c2410_init_clocks NULL
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#define s3c2410a_init NULL
-#endif
-
-extern int s3c2410_baseclk_add(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2412.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2412.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2412.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2412.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2412 cpu support
- *
- * 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2412
-
-extern  int s3c2412_init(void);
-
-extern void s3c2412_map_io(void);
-
-extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2412_init_clocks(int xtal);
-
-extern  int s3c2412_baseclk_add(void);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2416.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2416.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2416.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2416.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
- *
- * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
- *
- * Header file for s3c2416 cpu support
- *
- * 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2416
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2416_init(void);
-
-extern void s3c2416_map_io(void);
-
-extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2416_init_clocks(int xtal);
-
-extern  int s3c2416_baseclk_add(void);
-
-#else
-#define s3c2416_init_clocks NULL
-#define s3c2416_init_uarts NULL
-#define s3c2416_map_io NULL
-#define s3c2416_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2443.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2443.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2443.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c2443.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2443 cpu support
- *
- * 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2443
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2443_init(void);
-
-extern void s3c2443_map_io(void);
-
-extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2443_init_clocks(int xtal);
-
-extern  int s3c2443_baseclk_add(void);
-
-#else
-#define s3c2443_init_clocks NULL
-#define s3c2443_init_uarts NULL
-#define s3c2443_map_io NULL
-#define s3c2443_init NULL
-#endif
-
-/* common code used by s3c2443 and others.
- * note, not to be used outside of arch/arm/mach-s3c* */
-
-struct clk;	/* some files don't need clk.h otherwise */
-
-typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
-typedef unsigned int (*fdiv_fn)(unsigned long clkcon0);
-
-extern void s3c2443_common_setup_clocks(pll_fn get_mpll, fdiv_fn fdiv);
-extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, fdiv_fn fdiv);
-
-extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
-
-extern struct clksrc_clk clk_epllref;
-extern struct clksrc_clk clk_esysclk;
-extern struct clksrc_clk clk_msysclk;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c244x.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c244x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/s3c244x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2440 and S3C2442 cpu support
- *
- * 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.
-*/
-
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
-
-extern void s3c244x_map_io(void);
-
-extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c244x_init_clocks(int xtal);
-
-#else
-#define s3c244x_init_clocks NULL
-#define s3c244x_init_uarts NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-
-extern void s3c2440_map_io(void);
-#else
-#define s3c2440_init NULL
-#define s3c2440_map_io NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-
-extern void s3c2442_map_io(void);
-#else
-#define s3c2442_init NULL
-#define s3c2442_map_io NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/udc.h linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/udc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/include/plat/udc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/include/plat/udc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/udc.h
- *
- * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
- *
- *
- *  Changelog:
- *	14-Mar-2005	RTP	Created file
- *	02-Aug-2005	RTP	File rename
- *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
- *	18-Jan-2007	HMW	Add per-platform vbus_draw function
-*/
-
-#ifndef __ASM_ARM_ARCH_UDC_H
-#define __ASM_ARM_ARCH_UDC_H
-
-enum s3c2410_udc_cmd_e {
-	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
-	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
-	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
-};
-
-struct s3c2410_udc_mach_info {
-	void	(*udc_command)(enum s3c2410_udc_cmd_e);
- 	void	(*vbus_draw)(unsigned int ma);
-
-	unsigned int pullup_pin;
-	unsigned int pullup_pin_inverted;
-
-	unsigned int vbus_pin;
-	unsigned char vbus_pin_inverted;
-};
-
-extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
-
-/**
- * s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
- * @epnum: Number of endpoints to be instantiated by the controller driver.
- * @gpio_init: Platform specific USB related GPIO initialization.
- * @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
- *
- * Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
- * controllers.
- */
-struct s3c24xx_hsudc_platdata {
-	unsigned int	epnum;
-	void		(*gpio_init)(void);
-	void		(*gpio_uninit)(void);
-};
-
-extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
-
-#endif /* __ASM_ARM_ARCH_UDC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@ config PLAT_S3C24XX
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_DEV_NAND
-	select S3C_GPIO_CFG_S3C24XX
 	help
 	  Base platform code for any Samsung S3C24XX device
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/Makefile linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,7 @@ obj-				:=
 
 obj-y				+= cpu.o
 obj-y				+= irq.o
-obj-y				+= devs.o
-obj-y				+= gpio.o
-obj-y				+= gpiolib.o
+obj-y				+= dev-uart.o
 obj-y				+= clock.o
 obj-$(CONFIG_S3C24XX_DCLK)	+= clock-dclk.o
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,6 +160,124 @@ static struct clk clk_prediv = {
 	},
 };
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+*/
+
+static unsigned int *armdiv;
+static int nr_armdiv;
+static int armdivmask;
+
+static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned best = 256; /* bigger than any value */
+	unsigned div;
+	int ptr;
+
+	if (!nr_armdiv)
+		return -EINVAL;
+
+	for (ptr = 0; ptr < nr_armdiv; ptr++) {
+		div = armdiv[ptr];
+		if (div) {
+			/* cpufreq provides 266mhz as 266666000 not 266666666 */
+			calc = (parent / div / 1000) * 1000;
+			if (calc <= rate && div < best)
+				best = div;
+		}
+	}
+
+	return parent / best;
+}
+
+static unsigned long s3c2443_armclk_getrate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	unsigned long clkcon0;
+	int val;
+
+	if (!nr_armdiv || !armdivmask)
+		return -EINVAL;
+
+	clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+	clkcon0 &= armdivmask;
+	val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
+
+	return rate / armdiv[val];
+}
+
+static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned div;
+	unsigned best = 256; /* bigger than any value */
+	int ptr;
+	int val = -1;
+
+	if (!nr_armdiv || !armdivmask)
+		return -EINVAL;
+
+	for (ptr = 0; ptr < nr_armdiv; ptr++) {
+		div = armdiv[ptr];
+		if (div) {
+			/* cpufreq provides 266mhz as 266666000 not 266666666 */
+			calc = (parent / div / 1000) * 1000;
+			if (calc <= rate && div < best) {
+				best = div;
+				val = ptr;
+			}
+		}
+	}
+
+	if (val >= 0) {
+		unsigned long clkcon0;
+
+		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+		clkcon0 &= ~armdivmask;
+		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
+		__raw_writel(clkcon0, S3C2443_CLKDIV0);
+	}
+
+	return (val == -1) ? -EINVAL : 0;
+}
+
+static struct clk clk_armdiv = {
+	.name		= "armdiv",
+	.parent		= &clk_msysclk.clk,
+	.ops		= &(struct clk_ops) {
+		.round_rate = s3c2443_armclk_roundrate,
+		.get_rate = s3c2443_armclk_getrate,
+		.set_rate = s3c2443_armclk_setrate,
+	},
+};
+
+/* armclk
+ *
+ * this is the clock fed into the ARM core itself, from armdiv or from hclk.
+ */
+
+static struct clk *clk_arm_sources[] = {
+	[0] = &clk_armdiv,
+	[1] = &clk_h,
+};
+
+static struct clksrc_clk clk_arm = {
+	.clk	= {
+		.name		= "armclk",
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_arm_sources,
+		.nr_sources = ARRAY_SIZE(clk_arm_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
+};
+
 /* usbhost
  *
  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
@@ -205,9 +323,64 @@ static struct clksrc_clk clksrc_clks[] =
 	},
 };
 
+static struct clk clk_i2s_ext = {
+	.name		= "i2s-ext",
+};
+
+/* i2s_eplldiv
+ *
+ * This clock is the output from the I2S divisor of ESYSCLK, and is separate
+ * from the mux that comes after it (cannot merge into one single clock)
+*/
+
+static struct clksrc_clk clk_i2s_eplldiv = {
+	.clk	= {
+		.name		= "i2s-eplldiv",
+		.parent		= &clk_esysclk.clk,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+ *
+ * Note, this used to be two clocks, but was compressed into one.
+*/
+
+static struct clk *clk_i2s_srclist[] = {
+	[0] = &clk_i2s_eplldiv.clk,
+	[1] = &clk_i2s_ext,
+	[2] = &clk_epllref.clk,
+	[3] = &clk_epllref.clk,
+};
+
+static struct clksrc_clk clk_i2s = {
+	.clk	= {
+		.name		= "i2s-if",
+		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
+		.enable		= s3c2443_clkcon_enable_s,
+
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_i2s_srclist,
+		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
+};
 
 static struct clk init_clocks_off[] = {
 	{
+		.name		= "iis",
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_IIS,
+	}, {
+		.name		= "hsspi",
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_HSSPI,
+	}, {
 		.name		= "adc",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
@@ -253,6 +426,7 @@ static struct clk init_clocks[] = {
 		.ctrlbit	= S3C2443_HCLKCON_DMA5,
 	}, {
 		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_HSMMC,
@@ -347,8 +521,7 @@ static inline unsigned long s3c2443_get_
 
 /* EPLLCON compatible enough to get on/off information */
 
-void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll,
-						   fdiv_fn get_fdiv)
+void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
 {
 	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
 	unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
@@ -368,7 +541,7 @@ void __init_or_cpufreq s3c2443_common_se
 	pll = get_mpll(mpllcon, xtal);
 	clk_msysclk.clk.rate = pll;
 
-	fclk = pll / get_fdiv(clkdiv0);
+	fclk = clk_get_rate(&clk_armdiv);
 	hclk = s3c2443_prediv_getrate(&clk_prediv);
 	hclk /= s3c2443_get_hdiv(clkdiv0);
 	pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
@@ -403,20 +576,29 @@ static struct clk *clks[] __initdata = {
 	&clk_ext,
 	&clk_epll,
 	&clk_usb_bus,
+	&clk_armdiv,
 };
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+	&clk_i2s_eplldiv,
+	&clk_i2s,
 	&clk_usb_bus_host,
 	&clk_epllref,
 	&clk_esysclk,
 	&clk_msysclk,
+	&clk_arm,
 };
 
 void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
-				       fdiv_fn get_fdiv)
+				       unsigned int *divs, int nr_divs,
+				       int divmask)
 {
 	int ptr;
 
+	armdiv = divs;
+	nr_armdiv = nr_divs;
+	armdivmask = divmask;
+
 	/* s3c2443 parents h and p clocks from prediv */
 	clk_h.parent = &clk_prediv;
 	clk_p.parent = &clk_prediv;
@@ -437,5 +619,5 @@ void __init s3c2443_common_init_clocks(i
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
-	s3c2443_common_setup_clocks(get_mpll, get_fdiv);
+	s3c2443_common_setup_clocks(get_mpll);
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/cpu.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,48 +33,66 @@ static const char name_s5p6450[] = "S5P6
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
 static const char name_exynos4210[] = "EXYNOS4210";
+static const char name_exynos4212[] = "EXYNOS4212";
+static const char name_exynos4412[] = "EXYNOS4412";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x56440100,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6440_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6440_map_io,
 		.init_clocks	= s5p6440_init_clocks,
 		.init_uarts	= s5p6440_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6440,
 	}, {
-		.idcode		= 0x36450000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6450_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6450_map_io,
 		.init_clocks	= s5p6450_init_clocks,
 		.init_uarts	= s5p6450_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6450,
 	}, {
-		.idcode		= 0x43100000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PC100_CPU_ID,
+		.idmask		= S5PC100_CPU_MASK,
 		.map_io		= s5pc100_map_io,
 		.init_clocks	= s5pc100_init_clocks,
 		.init_uarts	= s5pc100_init_uarts,
 		.init		= s5pc100_init,
 		.name		= name_s5pc100,
 	}, {
-		.idcode		= 0x43110000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PV210_CPU_ID,
+		.idmask		= S5PV210_CPU_MASK,
 		.map_io		= s5pv210_map_io,
 		.init_clocks	= s5pv210_init_clocks,
 		.init_uarts	= s5pv210_init_uarts,
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
 	}, {
-		.idcode		= 0x43210000,
-		.idmask		= 0xfffe0000,
+		.idcode		= EXYNOS4210_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
-		.init		= exynos4_init,
+		.init		= exynos_init,
 		.name		= name_exynos4210,
+	}, {
+		.idcode		= EXYNOS4212_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos_init,
+		.name		= name_exynos4212,
+	}, {
+		.idcode		= EXYNOS4412_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos_init,
+		.name		= name_exynos4412,
 	},
 };
 
@@ -114,13 +132,13 @@ static struct map_desc s5p_iodesc[] __in
 void __init s5p_init_io(struct map_desc *mach_desc,
 			int size, void __iomem *cpuid_addr)
 {
-	unsigned long idcode;
-
 	/* initialize the io descriptors we need for initialization */
 	iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
 	if (mach_desc)
 		iotable_init(mach_desc, size);
 
-	idcode = __raw_readl(cpuid_addr);
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	/* detect cpu id and rev. */
+	s5p_init_cpu(cpuid_addr);
+
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-csis0.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-csis0.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-csis0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-csis0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 0
- *
- * 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/interrupt.h>
-#include <linux/platform_device.h>
-#include <mach/map.h>
-
-static struct resource s5p_mipi_csis0_resource[] = {
-	[0] = {
-		.start = S5P_PA_MIPI_CSIS0,
-		.end   = S5P_PA_MIPI_CSIS0 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_MIPI_CSIS0,
-		.end   = IRQ_MIPI_CSIS0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s5p_device_mipi_csis0 = {
-	.name		  = "s5p-mipi-csis",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5p_mipi_csis0_resource),
-	.resource	  = s5p_mipi_csis0_resource,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-csis1.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-csis1.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-csis1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-csis1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 1
- *
- * 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/interrupt.h>
-#include <linux/platform_device.h>
-#include <mach/map.h>
-
-static struct resource s5p_mipi_csis1_resource[] = {
-	[0] = {
-		.start = S5P_PA_MIPI_CSIS1,
-		.end   = S5P_PA_MIPI_CSIS1 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_MIPI_CSIS1,
-		.end   = IRQ_MIPI_CSIS1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5p_device_mipi_csis1 = {
-	.name		  = "s5p-mipi-csis",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5p_mipi_csis1_resource),
-	.resource	  = s5p_mipi_csis1_resource,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-ehci.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-ehci.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-ehci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/ehci.h>
-#include <plat/usb-phy.h>
-
-/* USB EHCI Host Controller registration */
-static struct resource s5p_ehci_resource[] = {
-	[0] = {
-		.start	= S5P_PA_EHCI,
-		.end	= S5P_PA_EHCI + SZ_256 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USB_HOST,
-		.end	= IRQ_USB_HOST,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s5p_device_ehci_dmamask = 0xffffffffUL;
-
-struct platform_device s5p_device_ehci = {
-	.name		= "s5p-ehci",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_ehci_resource),
-	.resource	= s5p_ehci_resource,
-	.dev		= {
-		.dma_mask = &s5p_device_ehci_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
-{
-	struct s5p_ehci_platdata *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
-			&s5p_device_ehci);
-
-	if (!npd->phy_init)
-		npd->phy_init = s5p_usb_phy_init;
-	if (!npd->phy_exit)
-		npd->phy_exit = s5p_usb_phy_exit;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc0.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc0.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc0.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC0 resource and device definitions
- *
- * 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc0_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC0,
-		.end	= S5P_PA_FIMC0 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC0,
-		.end	= IRQ_FIMC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc0 = {
-	.name		= "s5p-fimc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimc0_resource),
-	.resource	= s5p_fimc0_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc0_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc1.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc1.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc1.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC1 resource and device definitions
- *
- * 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc1_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC1,
-		.end	= S5P_PA_FIMC1 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC1,
-		.end	= IRQ_FIMC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc1 = {
-	.name		= "s5p-fimc",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p_fimc1_resource),
-	.resource	= s5p_fimc1_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc1_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc2.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc2.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc2.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC2 resource and device definitions
- *
- * 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc2_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC2,
-		.end	= S5P_PA_FIMC2 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC2,
-		.end	= IRQ_FIMC2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc2 = {
-	.name		= "s5p-fimc",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s5p_fimc2_resource),
-	.resource	= s5p_fimc2_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc2_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc3.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc3.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimc3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimc3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc3.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC3 resource and device definitions
- *
- * 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc3_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC3,
-		.end	= S5P_PA_FIMC3 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC3,
-		.end	= IRQ_FIMC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc3 = {
-	.name		= "s5p-fimc",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s5p_fimc3_resource),
-	.resource	= s5p_fimc3_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc3_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimd0.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimd0.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-fimd0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-fimd0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimd0.c
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Core file for Samsung Display Controller (FIMD) driver
- *
- * 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/string.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/fb.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s5p_fimd0_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMD0,
-		.end	= S5P_PA_FIMD0 + SZ_32K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMD0_VSYNC,
-		.end	= IRQ_FIMD0_VSYNC,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_FIMD0_FIFO,
-		.end	= IRQ_FIMD0_FIFO,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_FIMD0_SYSTEM,
-		.end	= IRQ_FIMD0_SYSTEM,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 fimd0_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimd0 = {
-	.name		= "s5p-fb",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
-	.resource	= s5p_fimd0_resource,
-	.dev		= {
-		.dma_mask		= &fimd0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-			&s5p_device_fimd0);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-mfc.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-mfc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-mfc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-mfc.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,56 +22,6 @@
 #include <plat/irqs.h>
 #include <plat/mfc.h>
 
-static struct resource s5p_mfc_resource[] = {
-	[0] = {
-		.start	= S5P_PA_MFC,
-		.end	= S5P_PA_MFC + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_MFC,
-		.end	= IRQ_MFC,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s5p_device_mfc = {
-	.name		= "s5p-mfc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
-	.resource	= s5p_mfc_resource,
-};
-
-/*
- * MFC hardware has 2 memory interfaces which are modelled as two separate
- * platform devices to let dma-mapping distinguish between them.
- *
- * MFC parent device (s5p_device_mfc) must be registered before memory
- * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
- */
-
-static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_mfc_l = {
-	.name		= "s5p-mfc-l",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_mfc_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device s5p_device_mfc_r = {
-	.name		= "s5p-mfc-r",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_mfc_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
 struct s5p_mfc_reserved_mem {
 	phys_addr_t	base;
 	unsigned long	size;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-onenand.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-onenand.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-onenand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-onenand.c
- *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S5P series device definition for OneNAND devices
- *
- * 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/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-static struct resource s5p_onenand_resources[] = {
-	[0] = {
-		.start	= S5P_PA_ONENAND,
-		.end	= S5P_PA_ONENAND + SZ_128K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S5P_PA_ONENAND_DMA,
-		.end	= S5P_PA_ONENAND_DMA + SZ_8K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND_AUDI,
-		.end	= IRQ_ONENAND_AUDI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5p_device_onenand = {
-	.name		= "s5pc110-onenand",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
-	.resource	= s5p_onenand_resources,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-pmu.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-pmu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-pmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/plat-s5p/dev-pmu.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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/platform_device.h>
-#include <asm/pmu.h>
-#include <mach/irqs.h>
-
-static struct resource s5p_pmu_resource = {
-	.start	= IRQ_PMU,
-	.end	= IRQ_PMU,
-	.flags	= IORESOURCE_IRQ,
-};
-
-struct platform_device s5p_device_pmu = {
-	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
-	.num_resources	= 1,
-	.resource	= &s5p_pmu_resource,
-};
-
-static int __init s5p_pmu_init(void)
-{
-	platform_device_register(&s5p_device_pmu);
-	return 0;
-}
-arch_initcall(s5p_pmu_init);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-uart.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-uart.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/dev-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,20 +32,10 @@ static struct resource s5p_uart0_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX0,
-		.end	= IRQ_S5P_UART_RX0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX0,
-		.end	= IRQ_S5P_UART_TX0,
+		.start	= IRQ_UART0,
+		.end	= IRQ_UART0,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR0,
-		.end	= IRQ_S5P_UART_ERR0,
-		.flags	= IORESOURCE_IRQ,
-	}
 };
 
 static struct resource s5p_uart1_resource[] = {
@@ -55,18 +45,8 @@ static struct resource s5p_uart1_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX1,
-		.end	= IRQ_S5P_UART_RX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX1,
-		.end	= IRQ_S5P_UART_TX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR1,
-		.end	= IRQ_S5P_UART_ERR1,
+		.start	= IRQ_UART1,
+		.end	= IRQ_UART1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -78,18 +58,8 @@ static struct resource s5p_uart2_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX2,
-		.end	= IRQ_S5P_UART_RX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX2,
-		.end	= IRQ_S5P_UART_TX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR2,
-		.end	= IRQ_S5P_UART_ERR2,
+		.start	= IRQ_UART2,
+		.end	= IRQ_UART2,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -102,18 +72,8 @@ static struct resource s5p_uart3_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX3,
-		.end	= IRQ_S5P_UART_RX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX3,
-		.end	= IRQ_S5P_UART_TX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR3,
-		.end	= IRQ_S5P_UART_ERR3,
+		.start	= IRQ_UART3,
+		.end	= IRQ_UART3,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
@@ -127,18 +87,8 @@ static struct resource s5p_uart4_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX4,
-		.end	= IRQ_S5P_UART_RX4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX4,
-		.end	= IRQ_S5P_UART_TX4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR4,
-		.end	= IRQ_S5P_UART_ERR4,
+		.start	= IRQ_UART4,
+		.end	= IRQ_UART4,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
@@ -152,18 +102,8 @@ static struct resource s5p_uart5_resourc
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX5,
-		.end	= IRQ_S5P_UART_RX5,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX5,
-		.end	= IRQ_S5P_UART_TX5,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR5,
-		.end	= IRQ_S5P_UART_ERR5,
+		.start	= IRQ_UART5,
+		.end	= IRQ_UART5,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/camport.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/camport.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/camport.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5P series camera interface helper functions
- *
- * 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 PLAT_S5P_CAMPORT_H_
-#define PLAT_S5P_CAMPORT_H_ __FILE__
-
-enum s5p_camport_id {
-	S5P_CAMPORT_A,
-	S5P_CAMPORT_B,
-};
-
-/*
- * The helper functions to configure GPIO for the camera parallel bus.
- * The camera port can be multiplexed with any FIMC entity, even multiple
- * FIMC entities are allowed to be attached to a single port simultaneously.
- * These functions are to be used in the board setup code.
- */
-int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
-int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/ehci.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/ehci.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/ehci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/ehci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_S5P_EHCI_H
-#define __PLAT_S5P_EHCI_H
-
-struct s5p_ehci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
-
-#endif /* __PLAT_S5P_EHCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/exynos4.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/exynos4.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/exynos4.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/exynos4.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/exynos4.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for exynos4 cpu support
- *
- * 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.
-*/
-
-/* Common init code for EXYNOS4 related SoCs */
-
-extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void exynos4_register_clocks(void);
-extern void exynos4_setup_clocks(void);
-
-#ifdef CONFIG_CPU_EXYNOS4210
-
-extern  int exynos4_init(void);
-extern void exynos4_init_irq(void);
-extern void exynos4_map_io(void);
-extern void exynos4_init_clocks(int xtal);
-extern struct sys_timer exynos4_timer;
-
-#define exynos4_init_uarts exynos4_common_init_uarts
-
-#else
-#define exynos4_init_clocks NULL
-#define exynos4_init_uarts NULL
-#define exynos4_map_io NULL
-#define exynos4_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/irqs.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/irqs.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P Common IRQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_IRQS_H
-#define __ASM_PLAT_S5P_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S5P_IRQ_OFFSET		(32)
-
-#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
-
-#define S5P_VIC0_BASE		S5P_IRQ(0)
-#define S5P_VIC1_BASE		S5P_IRQ(32)
-#define S5P_VIC2_BASE		S5P_IRQ(64)
-#define S5P_VIC3_BASE		S5P_IRQ(96)
-
-#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
-
-#define IRQ_VIC0_BASE		S5P_VIC0_BASE
-#define IRQ_VIC1_BASE		S5P_VIC1_BASE
-#define IRQ_VIC2_BASE		S5P_VIC2_BASE
-
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S5P_UART_BASE0	(16)
-#define IRQ_S5P_UART_BASE1	(20)
-#define IRQ_S5P_UART_BASE2	(24)
-#define IRQ_S5P_UART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-
-#define IRQ_S5P_UART_RX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR0	(IRQ_S5P_UART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR1	(IRQ_S5P_UART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR2	(IRQ_S5P_UART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR3	(IRQ_S5P_UART_BASE3 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX0		IRQ_S5P_UART_RX0
-#define IRQ_S3CUART_RX1		IRQ_S5P_UART_RX1
-#define IRQ_S3CUART_RX2		IRQ_S5P_UART_RX2
-#define IRQ_S3CUART_RX3		IRQ_S5P_UART_RX3
-
-/* VIC based IRQs */
-
-#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
-#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
-#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
-#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
-
-#define S5P_TIMER_IRQ(x)	(11 + (x))
-
-#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
-#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
-#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
-#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
-#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
-
-#define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
-					: ((x) - 16 + S5P_EINT_BASE2))
-
-#define EINT_OFFSET(irq)	((irq) < S5P_EINT_BASE2 ? \
-						((irq) - S5P_EINT_BASE1) : \
-						((irq) + 16 - S5P_EINT_BASE2))
-
-#define IRQ_EINT_BIT(x)		EINT_OFFSET(x)
-
-/* Typically only a few gpio chips require gpio interrupt support.
-   To avoid memory waste irq descriptors are allocated only for
-   S5P_GPIOINT_GROUP_COUNT chips, each with total number of
-   S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
-   to any gpio chip with the s5p_register_gpio_interrupt() function */
-#define S5P_GPIOINT_GROUP_COUNT 4
-#define S5P_GPIOINT_GROUP_SIZE	8
-#define S5P_GPIOINT_COUNT	(S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
-
-/* IRQ types common for all s5p platforms */
-#define S5P_IRQ_TYPE_LEVEL_LOW		(0x00)
-#define S5P_IRQ_TYPE_LEVEL_HIGH		(0x01)
-#define S5P_IRQ_TYPE_EDGE_FALLING	(0x02)
-#define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
-#define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
-
-#endif /* __ASM_PLAT_S5P_IRQS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/map-s5p.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_MAP_S5P_H
-#define __ASM_PLAT_MAP_S5P_H __FILE__
-
-#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
-#define S5P_VA_CMU		S3C_ADDR(0x02100000)
-#define S5P_VA_PMU		S3C_ADDR(0x02180000)
-#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
-#define S5P_VA_GPIO1		S5P_VA_GPIO
-#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
-#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
-
-#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
-#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
-#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
-#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
-
-#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
-#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
-
-#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
-#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
-
-#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
-
-#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
-#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
-
-#define S3C_VA_USB_HSPHY	S3C_ADDR(0x02900000)
-
-#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
-#define VA_VIC0			VA_VIC(0)
-#define VA_VIC1			VA_VIC(1)
-#define VA_VIC2			VA_VIC(2)
-#define VA_VIC3			VA_VIC(3)
-
-#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_VA_UART0		S5P_VA_UART(0)
-#define S5P_VA_UART1		S5P_VA_UART(1)
-#define S5P_VA_UART2		S5P_VA_UART(2)
-#define S5P_VA_UART3		S5P_VA_UART(3)
-
-#ifndef S3C_UART_OFFSET
-#define S3C_UART_OFFSET		(0x400)
-#endif
-
-#endif /* __ASM_PLAT_MAP_S5P_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/mfc.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/mfc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/mfc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/mfc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- *
- * 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 __PLAT_S5P_MFC_H
-#define __PLAT_S5P_MFC_H
-
-/**
- * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
- * @rbase:	base address for MFC 'right' memory interface
- * @rsize:	size of the memory reserved for MFC 'right' interface
- * @lbase:	base address for MFC 'left' memory interface
- * @lsize:	size of the memory reserved for MFC 'left' interface
- *
- * This function reserves system memory for both MFC device memory
- * interfaces and registers it to respective struct device entries as
- * coherent memory.
- */
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
-				phys_addr_t lbase, unsigned int lsize);
-
-#endif /* __PLAT_S5P_MFC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/mipi_csis.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/mipi_csis.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/mipi_csis.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/mipi_csis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series MIPI CSI slave device support
- *
- * 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 PLAT_S5P_MIPI_CSIS_H_
-#define PLAT_S5P_MIPI_CSIS_H_ __FILE__
-
-struct platform_device;
-
-/**
- * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
- *		   driver or true in case this regulator has no enable function
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
- */
-struct s5p_platform_mipi_csis {
-	unsigned long clk_rate;
-	u8 lanes;
-	u8 alignment;
-	u8 hs_settle;
-	bool fixed_phy_vdd;
-	int (*phy_enable)(struct platform_device *pdev, bool on);
-};
-
-/**
- * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @pdev: MIPI-CSIS platform device
- * @on: true to enable D-PHY and deassert its reset
- *	false to disable D-PHY
- */
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
-
-#endif /* PLAT_S5P_MIPI_CSIS_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/pll.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/pll.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/pll.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P PLL code
- *
- * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
- *
- * 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.
-*/
-
-#define PLL45XX_MDIV_MASK	(0x3FF)
-#define PLL45XX_PDIV_MASK	(0x3F)
-#define PLL45XX_SDIV_MASK	(0x7)
-#define PLL45XX_MDIV_SHIFT	(16)
-#define PLL45XX_PDIV_SHIFT	(8)
-#define PLL45XX_SDIV_SHIFT	(0)
-
-#include <asm/div64.h>
-
-enum pll45xx_type_t {
-	pll_4500,
-	pll_4502,
-	pll_4508
-};
-
-static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
-					    enum pll45xx_type_t pll_type)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
-
-	if (pll_type == pll_4508)
-		sdiv = sdiv - 1;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-#define PLL46XX_KDIV_MASK	(0xFFFF)
-#define PLL4650C_KDIV_MASK	(0xFFF)
-#define PLL46XX_MDIV_MASK	(0x1FF)
-#define PLL46XX_PDIV_MASK	(0x3F)
-#define PLL46XX_SDIV_MASK	(0x7)
-#define PLL46XX_MDIV_SHIFT	(16)
-#define PLL46XX_PDIV_SHIFT	(8)
-#define PLL46XX_SDIV_SHIFT	(0)
-
-enum pll46xx_type_t {
-	pll_4600,
-	pll_4650,
-	pll_4650c,
-};
-
-static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
-					    u32 pll_con0, u32 pll_con1,
-					    enum pll46xx_type_t pll_type)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
-	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
-	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
-	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	if (pll_type == pll_4650c)
-		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
-	else
-		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	tmp = baseclk;
-
-	if (pll_type == pll_4600) {
-		tmp *= (mdiv << 16) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 16;
-	} else {
-		tmp *= (mdiv << 10) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 10;
-	}
-
-	return result;
-}
-
-#define PLL90XX_MDIV_MASK	(0xFF)
-#define PLL90XX_PDIV_MASK	(0x3F)
-#define PLL90XX_SDIV_MASK	(0x7)
-#define PLL90XX_KDIV_MASK	(0xffff)
-#define PLL90XX_MDIV_SHIFT	(16)
-#define PLL90XX_PDIV_SHIFT	(8)
-#define PLL90XX_SDIV_SHIFT	(0)
-#define PLL90XX_KDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
-					    u32 pll_con, u32 pll_conk)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
-	kdiv = pll_conk & PLL90XX_KDIV_MASK;
-
-	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
-
-#define PLL65XX_MDIV_MASK	(0x3FF)
-#define PLL65XX_PDIV_MASK	(0x3F)
-#define PLL65XX_SDIV_MASK	(0x7)
-#define PLL65XX_MDIV_SHIFT	(16)
-#define PLL65XX_PDIV_SHIFT	(8)
-#define PLL65XX_SDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/regs-srom.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P SROMC register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_REGS_SROM_H
-#define __ASM_PLAT_S5P_REGS_SROM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_SROMREG(x)		(S5P_VA_SROMC + (x))
-
-#define S5P_SROM_BW		S5P_SROMREG(0x0)
-#define S5P_SROM_BC0		S5P_SROMREG(0x4)
-#define S5P_SROM_BC1		S5P_SROMREG(0x8)
-#define S5P_SROM_BC2		S5P_SROMREG(0xc)
-#define S5P_SROM_BC3		S5P_SROMREG(0x10)
-#define S5P_SROM_BC4		S5P_SROMREG(0x14)
-#define S5P_SROM_BC5		S5P_SROMREG(0x18)
-
-/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
-
-#define S5P_SROM_BW__DATAWIDTH__SHIFT		0
-#define S5P_SROM_BW__ADDRMODE__SHIFT		1
-#define S5P_SROM_BW__WAITENABLE__SHIFT		2
-#define S5P_SROM_BW__BYTEENABLE__SHIFT		3
-
-#define S5P_SROM_BW__CS_MASK			0xf
-
-#define S5P_SROM_BW__NCS0__SHIFT		0
-#define S5P_SROM_BW__NCS1__SHIFT		4
-#define S5P_SROM_BW__NCS2__SHIFT		8
-#define S5P_SROM_BW__NCS3__SHIFT		12
-#define S5P_SROM_BW__NCS4__SHIFT		16
-#define S5P_SROM_BW__NCS5__SHIFT		20
-
-/* applies to same to BCS0 - BCS3 */
-
-#define S5P_SROM_BCX__PMC__SHIFT		0
-#define S5P_SROM_BCX__TACP__SHIFT		4
-#define S5P_SROM_BCX__TCAH__SHIFT		8
-#define S5P_SROM_BCX__TCOH__SHIFT		12
-#define S5P_SROM_BCX__TACC__SHIFT		16
-#define S5P_SROM_BCX__TCOS__SHIFT		24
-#define S5P_SROM_BCX__TACS__SHIFT		28
-
-#endif /* __ASM_PLAT_S5P_REGS_SROM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/reset.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/reset.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/reset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/reset.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_RESET_H
-#define __ASM_PLAT_S5P_RESET_H __FILE__
-
-extern void (*s5p_reset_hook)(void);
-
-#endif /* __ASM_PLAT_S5P_RESET_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p6440.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p6440.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p6440.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p6440.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5p6440.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5p6440 cpu support
- *
- * 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.
-*/
-
- /* Common init code for S5P6440 related SoCs */
-
-extern void s5p6440_register_clocks(void);
-extern void s5p6440_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5P6440
-
-extern  int s5p64x0_init(void);
-extern void s5p6440_init_irq(void);
-extern void s5p6440_map_io(void);
-extern void s5p6440_init_clocks(int xtal);
-
-extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6440_init_clocks NULL
-#define s5p6440_init_uarts NULL
-#define s5p6440_map_io NULL
-#define s5p64x0_init NULL
-#endif
-
-/* S5P6440 timer */
-
-extern struct sys_timer s5p6440_timer;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p6450.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p6450.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p6450.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p6450.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5p6450.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p6450 cpu support
- *
- * 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.
-*/
-
-/* Common init code for S5P6450 related SoCs */
-
-extern void s5p6450_register_clocks(void);
-extern void s5p6450_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5P6450
-
-extern  int s5p64x0_init(void);
-extern void s5p6450_init_irq(void);
-extern void s5p6450_map_io(void);
-extern void s5p6450_init_clocks(int xtal);
-
-extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6450_init_clocks NULL
-#define s5p6450_init_uarts NULL
-#define s5p6450_map_io NULL
-#define s5p64x0_init NULL
-#endif
-
-/* S5P6450 timer */
-
-extern struct sys_timer s5p6450_timer;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5pc100.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5pc100.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5pc100.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5pc100.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5pc100.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pc100 cpu support
- *
- * 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.
-*/
-
-/* Common init code for S5PC100 related SoCs */
-
-extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pc100_register_clocks(void);
-extern void s5pc100_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PC100
-
-extern  int s5pc100_init(void);
-extern void s5pc100_init_irq(void);
-extern void s5pc100_map_io(void);
-extern void s5pc100_init_clocks(int xtal);
-
-#define s5pc100_init_uarts s5pc100_common_init_uarts
-
-#else
-#define s5pc100_init_clocks NULL
-#define s5pc100_init_uarts NULL
-#define s5pc100_map_io NULL
-#define s5pc100_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p-clock.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p-clock.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_CLOCK_H
-#define __ASM_PLAT_S5P_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-#define clk_fin_dpll clk_ext_xtal_mux
-#define clk_fin_vpll clk_ext_xtal_mux
-#define clk_fin_hpll clk_ext_xtal_mux
-
-extern struct clk clk_ext_xtal_mux;
-extern struct clk clk_xusbxti;
-extern struct clk clk_48m;
-extern struct clk s5p_clk_27m;
-extern struct clk clk_fout_apll;
-extern struct clk clk_fout_mpll;
-extern struct clk clk_fout_epll;
-extern struct clk clk_fout_dpll;
-extern struct clk clk_fout_vpll;
-extern struct clk clk_arm;
-extern struct clk clk_vpll;
-
-extern struct clksrc_sources clk_src_apll;
-extern struct clksrc_sources clk_src_mpll;
-extern struct clksrc_sources clk_src_epll;
-extern struct clksrc_sources clk_src_dpll;
-
-extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
-
-/* Common EPLL operations for S5P platform */
-extern int s5p_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p_epll_get_rate(struct clk *clk);
-
-/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
-extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
-extern unsigned long s5p_spdif_get_rate(struct clk *clk);
-
-extern struct clk_ops s5p_sclk_spdif_ops;
-#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p-time.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p-time.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5p-time.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5p-time.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5p-time.h
- *
- * Copyright 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5p time support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_TIME_H
-#define __ASM_PLAT_S5P_TIME_H __FILE__
-
-/* S5P HR-Timer Clock mode */
-enum s5p_timer_mode {
-	S5P_PWM0,
-	S5P_PWM1,
-	S5P_PWM2,
-	S5P_PWM3,
-	S5P_PWM4,
-};
-
-struct s5p_timer_source {
-	unsigned int event_id;
-	unsigned int source_id;
-};
-
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define S5PTIMER_MIN_RANGE	4
-
-#define TCNT_MAX		0xffffffff
-#define NON_PERIODIC		0
-#define PERIODIC		1
-
-extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
-					enum s5p_timer_mode source);
-extern	struct sys_timer s5p_timer;
-#endif /* __ASM_PLAT_S5P_TIME_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5pv210.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5pv210.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/s5pv210.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/s5pv210.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5pv210.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pv210 cpu support
- *
- * 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.
-*/
-
-/* Common init code for S5PV210 related SoCs */
-
-extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pv210_register_clocks(void);
-extern void s5pv210_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PV210
-
-extern  int s5pv210_init(void);
-extern void s5pv210_init_irq(void);
-extern void s5pv210_map_io(void);
-extern void s5pv210_init_clocks(int xtal);
-
-#define s5pv210_init_uarts s5pv210_common_init_uarts
-
-#else
-#define s5pv210_init_clocks NULL
-#define s5pv210_init_uarts NULL
-#define s5pv210_map_io NULL
-#define s5pv210_init NULL
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/sysmmu.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,95 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Samsung System MMU driver for S5P platform
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM__PLAT_SYSMMU_H
-#define __ASM__PLAT_SYSMMU_H __FILE__
-
-enum S5P_SYSMMU_INTERRUPT_TYPE {
-	SYSMMU_PAGEFAULT,
-	SYSMMU_AR_MULTIHIT,
-	SYSMMU_AW_MULTIHIT,
-	SYSMMU_BUSERROR,
-	SYSMMU_AR_SECURITY,
-	SYSMMU_AR_ACCESS,
-	SYSMMU_AW_SECURITY,
-	SYSMMU_AW_PROTECTION, /* 7 */
-	SYSMMU_FAULTS_NUM
-};
-
-#ifdef CONFIG_S5P_SYSTEM_MMU
-
-#include <mach/sysmmu.h>
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- * #pgd: Base physical address of the 1st level page table
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-
-/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
- * @itype: type of fault.
- * @pgtable_base: the physical address of page table base. This is 0 if @ips is
- *               SYSMMU_BUSERROR.
- * @fault_addr: the device (virtual) address that the System MMU tried to
- *             translated. This is 0 if @ips is SYSMMU_BUSERROR.
- * Called when interrupt occurred by the System MMUs
- * The device drivers of peripheral devices that has a System MMU can implement
- * a fault handler to resolve address translation fault by System MMU.
- * The meanings of return value and parameters are described below.
-
- * return value: non-zero if the fault is correctly resolved.
- *         zero if the fault is not handled.
- */
-void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
-			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
-					unsigned long pgtable_base,
-					unsigned long fault_addr));
-#else
-#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
-#define s5p_sysmmu_disable(ips) do { } while (0)
-#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
-#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
-#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
-#endif
-#endif /* __ASM_PLAT_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/system-reset.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/system-reset.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/system-reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/system-reset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/system-reset.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
- *
- * S5P - System define for arch_reset()
- *
- * 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 <plat/watchdog-reset.h>
-
-void (*s5p_reset_hook)(void);
-
-static void arch_reset(char mode, const char *cmd)
-{
-	/* SWRESET support in s5p_reset_hook() */
-
-	if (s5p_reset_hook)
-		s5p_reset_hook();
-
-	/* Perform reset using Watchdog reset
-	 * if there is no s5p_reset_hook()
-	 */
-
-	arch_wdt_reset();
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/usb-phy.h linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/usb-phy.h
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/include/plat/usb-phy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/include/plat/usb-phy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_S5P_USB_PHY_H
-#define __PLAT_S5P_USB_PHY_H
-
-enum s5p_usb_phy_type {
-	S5P_USB_PHY_DEVICE,
-	S5P_USB_PHY_HOST,
-};
-
-extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
-extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
-
-#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/irq.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/irq.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,42 +17,10 @@
 
 #include <asm/hardware/vic.h>
 
-#include <linux/serial_core.h>
 #include <mach/map.h>
 #include <plat/regs-timer.h>
-#include <plat/regs-serial.h>
 #include <plat/cpu.h>
 #include <plat/irq-vic-timer.h>
-#include <plat/irq-uart.h>
-
-/*
- * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static struct s3c_uart_irq uart_irqs[] = {
-	[0] = {
-		.regs		= S5P_VA_UART0,
-		.base_irq	= IRQ_S5P_UART_BASE0,
-		.parent_irq	= IRQ_UART0,
-	},
-	[1] = {
-		.regs		= S5P_VA_UART1,
-		.base_irq	= IRQ_S5P_UART_BASE1,
-		.parent_irq	= IRQ_UART1,
-	},
-	[2] = {
-		.regs		= S5P_VA_UART2,
-		.base_irq	= IRQ_S5P_UART_BASE2,
-		.parent_irq	= IRQ_UART2,
-	},
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
-	[3] = {
-		.regs		= S5P_VA_UART3,
-		.base_irq	= IRQ_S5P_UART_BASE3,
-		.parent_irq	= IRQ_UART3,
-	},
-#endif
-};
 
 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 {
@@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 n
 #endif
 
 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
-	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/irq-gpioint.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/irq-gpioint.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/irq-gpioint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/irq-gpioint.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@ struct s5p_gpioint_bank {
 	int			start;
 	int			nr_groups;
 	int			irq;
-	struct s3c_gpio_chip	**chips;
+	struct samsung_gpio_chip	**chips;
 	void			(*handler)(unsigned int, struct irq_desc *);
 };
 
@@ -87,7 +87,7 @@ static void s5p_gpioint_handler(unsigned
 	chained_irq_enter(chip, desc);
 
 	for (group = 0; group < bank->nr_groups; group++) {
-		struct s3c_gpio_chip *chip = bank->chips[group];
+		struct samsung_gpio_chip *chip = bank->chips[group];
 		if (!chip)
 			continue;
 
@@ -110,7 +110,7 @@ static void s5p_gpioint_handler(unsigned
 	chained_irq_exit(chip, desc);
 }
 
-static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
+static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
 {
 	static int used_gpioint_groups = 0;
 	int group = chip->group;
@@ -131,7 +131,7 @@ static __init int s5p_gpioint_add(struct
 		return -EINVAL;
 
 	if (!bank->handler) {
-		bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+		bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
 				      bank->nr_groups, GFP_KERNEL);
 		if (!bank->chips)
 			return -ENOMEM;
@@ -174,7 +174,7 @@ static __init int s5p_gpioint_add(struct
 
 int __init s5p_register_gpio_interrupt(int pin)
 {
-	struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin);
+	struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
 	int offset, group;
 	int ret;
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-s5p/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4)
+	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
 	default y
 	select ARM_VIC if !ARCH_EXYNOS4
 	select ARM_GIC if ARCH_EXYNOS4
@@ -16,13 +16,9 @@ config PLAT_S5P
 	select S3C_GPIO_TRACK
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_GPIOLIB_4BIT
-	select S3C_GPIO_CFG_S3C64XX
-	select S3C_GPIO_PULL_UPDOWN
-	select S3C_GPIO_CFG_S3C24XX
 	select PLAT_SAMSUNG
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_IRQ_VIC_TIMER
-	select SAMSUNG_IRQ_UART
 	help
 	  Base platform code for Samsung's S5P series SoC.
 
@@ -43,6 +39,12 @@ config S5P_HRT
 	help
 	  Use the High Resolution timer support
 
+config S5P_PM
+	bool
+	help
+	  Common code for power management support on S5P and newer SoCs
+	  Note: Do not select this for S5P6440 and S5P6450.
+
 comment "System MMU"
 
 config S5P_SYSTEM_MMU
@@ -51,6 +53,12 @@ config S5P_SYSTEM_MMU
 	help
 	  Say Y here if you want to enable System MMU
 
+config S5P_SLEEP
+	bool
+	help
+	  Internal config node to apply common S5P sleep management code.
+	  Can be selected by S5P and newer SoCs with similar sleep procedure.
+
 config S5P_DEV_FIMC0
 	bool
 	help
@@ -76,6 +84,11 @@ config S5P_DEV_FIMD0
 	help
 	  Compile in platform device definitions for FIMD controller 0
 
+config S5P_DEV_I2C_HDMIPHY
+	bool
+	help
+	  Compile in platform device definitions for I2C HDMIPHY controller
+
 config S5P_DEV_MFC
 	bool
 	help
@@ -96,6 +109,11 @@ config S5P_DEV_CSIS1
 	help
 	  Compile in platform device definitions for MIPI-CSIS channel 1
 
+config S5P_DEV_TV
+	bool
+	help
+	  Compile in platform device definition for TV interface
+
 config S5P_DEV_USB_EHCI
 	bool
 	help
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/Makefile linux-libre-3.2-gnu1/arch/arm/plat-s5p/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@ obj-				:=
 
 # Core files
 
-obj-y				+= dev-pmu.o
 obj-y				+= dev-uart.o
 obj-y				+= cpu.o
 obj-y				+= clock.o
@@ -20,19 +19,10 @@ obj-y				+= irq.o
 obj-$(CONFIG_S5P_EXT_INT)	+= irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)	+= irq-gpioint.o
 obj-$(CONFIG_S5P_SYSTEM_MMU)	+= sysmmu.o
-obj-$(CONFIG_PM)		+= pm.o
-obj-$(CONFIG_PM)		+= irq-pm.o
+obj-$(CONFIG_S5P_PM)		+= pm.o irq-pm.o
+obj-$(CONFIG_S5P_SLEEP)		+= sleep.o
 obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
 
 # devices
 obj-$(CONFIG_S5P_DEV_MFC)	+= dev-mfc.o
-obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0.o
-obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
-obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.o
-obj-$(CONFIG_S5P_DEV_FIMC3)	+= dev-fimc3.o
-obj-$(CONFIG_S5P_DEV_FIMD0)	+= dev-fimd0.o
-obj-$(CONFIG_S5P_DEV_ONENAND)	+= dev-onenand.o
-obj-$(CONFIG_S5P_DEV_CSIS0)	+= dev-csis0.o
-obj-$(CONFIG_S5P_DEV_CSIS1)	+= dev-csis1.o
-obj-$(CONFIG_S5P_DEV_USB_EHCI)	+= dev-ehci.o
 obj-$(CONFIG_S5P_SETUP_MIPIPHY)	+= setup-mipiphy.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/sleep.S linux-libre-3.2-gnu1/arch/arm/plat-s5p/sleep.S
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+/* linux/arch/arm/plat-s5p/sleep.S
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Common S5P Sleep Code
+ * Based on S3C64XX sleep code by:
+ *	Ben Dooks, (c) 2008 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	.text
+
+	/*
+	 * sleep magic, to allow the bootloader to check for an valid
+	 * image to resume to. Must be the first word before the
+	 * s3c_cpu_resume entry.
+	 */
+
+	.word	0x2bedf00d
+
+	/*
+	 * s3c_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	 */
+
+ENTRY(s3c_cpu_resume)
+	b	cpu_resume
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-s5p/sysmmu.c linux-libre-3.2-gnu1/arch/arm/plat-s5p/sysmmu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-s5p/sysmmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-s5p/sysmmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <asm/pgtable.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/adc.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/adc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/adc.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@
 
 enum s3c_cpu_type {
 	TYPE_ADCV1, /* S3C24XX */
+	TYPE_ADCV11, /* S3C2443 */
+	TYPE_ADCV12, /* S3C2416, S3C2450 */
 	TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
 	TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
@@ -98,13 +100,17 @@ static inline void s3c_adc_select(struct
 
 	client->select_cb(client, 1);
 
-	con &= ~S3C2410_ADCCON_MUXMASK;
+	if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
+		con &= ~S3C2410_ADCCON_MUXMASK;
 	con &= ~S3C2410_ADCCON_STDBM;
 	con &= ~S3C2410_ADCCON_STARTMASK;
 
 	if (!client->is_ts) {
 		if (cpu == TYPE_ADCV3)
 			writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+		else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
+			writel(client->channel & 0xf,
+						adc->regs + S3C2443_ADCMUX);
 		else
 			con |= S3C2410_ADCCON_SELMUX(client->channel);
 	}
@@ -293,13 +299,13 @@ static irqreturn_t s3c_adc_irq(int irq,
 
 	client->nr_samples--;
 
-	if (cpu != TYPE_ADCV1) {
-		/* S3C64XX/S5P ADC resolution is 12-bit */
-		data0 &= 0xfff;
-		data1 &= 0xfff;
-	} else {
+	if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
 		data0 &= 0x3ff;
 		data1 &= 0x3ff;
+	} else {
+		/* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
+		data0 &= 0xfff;
+		data1 &= 0xfff;
 	}
 
 	if (client->convert_cb)
@@ -320,7 +326,7 @@ static irqreturn_t s3c_adc_irq(int irq,
 	}
 
 exit:
-	if (cpu != TYPE_ADCV1) {
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
 		/* Clear ADC interrupt */
 		writel(0, adc->regs + S3C64XX_ADCCLRINT);
 	}
@@ -332,6 +338,7 @@ static int s3c_adc_probe(struct platform
 	struct device *dev = &pdev->dev;
 	struct adc_device *adc;
 	struct resource *regs;
+	enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
 	int ret;
 	unsigned tmp;
 
@@ -394,10 +401,13 @@ static int s3c_adc_probe(struct platform
 	clk_enable(adc->clk);
 
 	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
-	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
-		/* Enable 12-bit ADC resolution */
+
+	/* Enable 12-bit ADC resolution */
+	if (cpu == TYPE_ADCV12)
+		tmp |= S3C2416_ADCCON_RESSEL;
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
 		tmp |= S3C64XX_ADCCON_RESSEL;
-	}
+
 	writel(tmp, adc->regs + S3C2410_ADCCON);
 
 	dev_info(dev, "attached adc driver\n");
@@ -464,6 +474,7 @@ static int s3c_adc_resume(struct device
 	struct platform_device *pdev = container_of(dev,
 			struct platform_device, dev);
 	struct adc_device *adc = platform_get_drvdata(pdev);
+	enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
 	int ret;
 	unsigned long tmp;
 
@@ -474,9 +485,13 @@ static int s3c_adc_resume(struct device
 	enable_irq(adc->irq);
 
 	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+
 	/* Enable 12-bit ADC resolution */
-	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+	if (cpu == TYPE_ADCV12)
+		tmp |= S3C2416_ADCCON_RESSEL;
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
 		tmp |= S3C64XX_ADCCON_RESSEL;
+
 	writel(tmp, adc->regs + S3C2410_ADCCON);
 
 	return 0;
@@ -492,6 +507,12 @@ static struct platform_device_id s3c_adc
 		.name           = "s3c24xx-adc",
 		.driver_data    = TYPE_ADCV1,
 	}, {
+		.name		= "s3c2443-adc",
+		.driver_data	= TYPE_ADCV11,
+	}, {
+		.name		= "s3c2416-adc",
+		.driver_data	= TYPE_ADCV12,
+	}, {
 		.name           = "s3c64xx-adc",
 		.driver_data    = TYPE_ADCV2,
 	}, {
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/cpu.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/cpu.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+/* linux/arch/arm/plat-samsung/cpu.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung CPU Support
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+unsigned long samsung_cpu_id;
+static unsigned int samsung_cpu_rev;
+
+unsigned int samsung_rev(void)
+{
+	return samsung_cpu_rev;
+}
+EXPORT_SYMBOL(samsung_rev);
+
+void __init s3c24xx_init_cpu(void)
+{
+	/* nothing here yet */
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s3c64xx_init_cpu(void)
+{
+	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
+	if (!samsung_cpu_id) {
+		/*
+		 * S3C6400 has the ID register in a different place,
+		 * and needs a write before it can be read.
+		 */
+		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+		samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
+	}
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s5p_init_cpu(void __iomem *cpuid_addr)
+{
+	samsung_cpu_id = __raw_readl(cpuid_addr);
+	samsung_cpu_rev = samsung_cpu_id & 0xFF;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-adc.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-adc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-adc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-adc.c
- *
- * Copyright 2010 Maurus Cuelenaere
- *
- * S3C64xx series device definition for ADC device
- *
- * 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/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/adc.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_adc_resource[] = {
-	[0] = {
-		.start = SAMSUNG_PA_ADC,
-		.end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_ADC,
-		.end   = IRQ_ADC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_adc = {
-	.name		= "samsung-adc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
-	.resource	= s3c_adc_resource,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-asocdma.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-asocdma.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-asocdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-asocdma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-asocdma.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <plat/devs.h>
-
-static u64 audio_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device samsung_asoc_dma = {
-	.name		  = "samsung-audio",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &audio_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	}
-};
-EXPORT_SYMBOL(samsung_asoc_dma);
-
-struct platform_device samsung_asoc_idma = {
-	.name		= "samsung-idma",
-	.id		= -1,
-	.dev		= {
-		.dma_mask		= &audio_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
-EXPORT_SYMBOL(samsung_asoc_idma);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-backlight.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-backlight.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/pwm_backlight.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-fb.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-fb.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-fb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-fb.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for framebuffer device
- *
- * 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/string.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/fb.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_fb_resource[] = {
-	[0] = {
-		.start = S3C_PA_FB,
-		.end   = S3C_PA_FB + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_LCD_VSYNC,
-		.end   = IRQ_LCD_VSYNC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_LCD_FIFO,
-		.end   = IRQ_LCD_FIFO,
-		.flags = IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start = IRQ_LCD_SYSTEM,
-		.end   = IRQ_LCD_SYSTEM,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_fb = {
-	.name		  = "s3c-fb",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_fb_resource),
-	.resource	  = s3c_fb_resource,
-	.dev.dma_mask	  = &s3c_device_fb.dev.coherent_dma_mask,
-	.dev.coherent_dma_mask = 0xffffffffUL,
-};
-
-void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-			 &s3c_device_fb);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc1.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc1.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc1.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc device 1
- *
- * 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/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc1_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC1,
-		.end   = S3C_PA_HSMMC1 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC1,
-		.end   = IRQ_HSMMC1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc1_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc1 = {
-	.name		= "s3c-sdhci",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc1_resource),
-	.resource	= s3c_hsmmc1_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc1_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc1_def_platdata,
-	},
-};
-
-void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc2.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc2.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc2.c
- *
- * Copyright (c) 2009 Samsung Electronics
- * Copyright (c) 2009 Maurus Cuelenaere
- *
- * Based on arch/arm/plat-s3c/dev-hsmmc1.c
- * original file Copyright (c) 2008 Simtec Electronics
- *
- * S3C series device definition for hsmmc device 2
- *
- * 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/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc2_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC2,
-		.end   = S3C_PA_HSMMC2 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC2,
-		.end   = IRQ_HSMMC2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc2_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc2 = {
-	.name		= "s3c-sdhci",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc2_resource),
-	.resource	= s3c_hsmmc2_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc2_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc2_def_platdata,
-	},
-};
-
-void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc3.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc3.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hsmmc3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/plat-samsung/dev-hsmmc1.c
- *
- * Samsung device definition for hsmmc device 3
- *
- * 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/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc3_resource[] = {
-	[0] = {
-		.start	= S3C_PA_HSMMC3,
-		.end	= S3C_PA_HSMMC3 + S3C_SZ_HSMMC - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_HSMMC3,
-		.end	= IRQ_HSMMC3,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc3_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc3 = {
-	.name		= "s3c-sdhci",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc3_resource),
-	.resource	= s3c_hsmmc3_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc3_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc3_def_platdata,
-	},
-};
-
-void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hsmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hsmmc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc devices
- *
- * 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/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC0,
-		.end   = S3C_PA_HSMMC0 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC0,
-		.end   = IRQ_HSMMC0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc0 = {
-	.name		= "s3c-sdhci",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc_resource),
-	.resource	= s3c_hsmmc_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc0_def_platdata,
-	},
-};
-
-void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hwmon.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hwmon.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-hwmon.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hwmon.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Adapted for HWMON by Maurus Cuelenaere
- *
- * Samsung series device definition for HWMON
- *
- * 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/platform_device.h>
-
-#include <plat/devs.h>
-#include <plat/hwmon.h>
-
-struct platform_device s3c_device_hwmon = {
-	.name		= "s3c-hwmon",
-	.id		= -1,
-	.dev.parent	= &s3c_device_adc.dev,
-};
-
-void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
-			 &s3c_device_hwmon);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c0.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c0.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c0.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 0
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC,
-		.end   = S3C_PA_IIC + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC,
-		.end   = IRQ_IIC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c0 = {
-	.name		  = "s3c2410-i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
-	.id		  = 0,
-#else
-	.id		  = -1,
-#endif
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-struct s3c2410_platform_i2c default_i2c_data __initdata = {
-	.flags		= 0,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
-void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd)
-		pd = &default_i2c_data;
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c0);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c1.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c1.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c1.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 1
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC1,
-		.end   = S3C_PA_IIC1 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC1,
-		.end   = IRQ_IIC1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c1 = {
-	.name		  = "s3c2410-i2c",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 1;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c1);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c2.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c2.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c2.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S3C series device definition for i2c device 2
- *
- * Based on plat-samsung/dev-i2c0.c
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC2,
-		.end   = S3C_PA_IIC2 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC2,
-		.end   = IRQ_IIC2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c2 = {
-	.name		  = "s3c2410-i2c",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 2;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c2);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c3.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c3.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC3,
-		.end	= S3C_PA_IIC3 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC3,
-		.end	= IRQ_IIC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c3 = {
-	.name		= "s3c2440-i2c",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 3;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c3);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c4.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c4.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC4,
-		.end	= S3C_PA_IIC4 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC4,
-		.end	= IRQ_IIC4,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c4 = {
-	.name		= "s3c2440-i2c",
-	.id		= 4,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 4;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c4);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c5.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c5.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC5,
-		.end	= S3C_PA_IIC5 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC5,
-		.end	= IRQ_IIC5,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c5 = {
-	.name		= "s3c2440-i2c",
-	.id		= 5,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 5;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c5);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c6.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c6.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 6
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC6,
-		.end	= S3C_PA_IIC6 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC6,
-		.end	= IRQ_IIC6,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c6 = {
-	.name		= "s3c2440-i2c",
-	.id		= 6,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 6;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c6);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c7.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c7.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-i2c7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-i2c7.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 7
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC7,
-		.end	= S3C_PA_IIC7 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC7,
-		.end	= IRQ_IIC7,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c7 = {
-	.name		= "s3c2440-i2c",
-	.id		= 7,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 7;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c7);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-ide.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-ide.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-ide.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Samsung CF-ATA device definition.
- *
- * 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/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-#include <plat/ata.h>
-#include <plat/devs.h>
-
-static struct resource s3c_cfcon_resource[] = {
-	[0] = {
-		.start	= SAMSUNG_PA_CFCON,
-		.end	= SAMSUNG_PA_CFCON + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CFCON,
-		.end	= IRQ_CFCON,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_cfcon = {
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_cfcon_resource),
-	.resource	= s3c_cfcon_resource,
-};
-
-void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
-			 &s3c_device_cfcon);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-keypad.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-keypad.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-keypad.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/keypad.h>
-
-static struct resource samsung_keypad_resources[] = {
-	[0] = {
-		.start	= SAMSUNG_PA_KEYPAD,
-		.end	= SAMSUNG_PA_KEYPAD + 0x20 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_KEYPAD,
-		.end	= IRQ_KEYPAD,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device samsung_device_keypad = {
-	.name		= "samsung-keypad",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(samsung_keypad_resources),
-	.resource	= samsung_keypad_resources,
-};
-
-void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
-{
-	struct samsung_keypad_platdata *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
-			&samsung_device_keypad);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = samsung_keypad_cfg_gpio;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-nand.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-nand.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-nand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,125 +0,0 @@
-/*
- * S3C series device definition for nand device
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/nand.h>
-
-static struct resource s3c_nand_resource[] = {
-	[0] = {
-		.start = S3C_PA_NAND,
-		.end   = S3C_PA_NAND + SZ_1M,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-struct platform_device s3c_device_nand = {
-	.name		  = "s3c2410-nand",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
-	.resource	  = s3c_nand_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_nand);
-
-/**
- * s3c_nand_copy_set() - copy nand set data
- * @set: The new structure, directly copied from the old.
- *
- * Copy all the fields from the NAND set field from what is probably __initdata
- * to new kernel memory. The code returns 0 if the copy happened correctly or
- * an error code for the calling function to display.
- *
- * Note, we currently do not try and look to see if we've already copied the
- * data in a previous set.
- */
-static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
-{
-	void *ptr;
-	int size;
-
-	size = sizeof(struct mtd_partition) * set->nr_partitions;
-	if (size) {
-		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
-		set->partitions = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-	
-	if (set->nr_map && set->nr_chips) {
-		size = sizeof(int) * set->nr_chips;
-		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
-		set->nr_map = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-
-	if (set->ecc_layout) {
-		ptr = kmemdup(set->ecc_layout,
-			      sizeof(struct nand_ecclayout), GFP_KERNEL);
-		set->ecc_layout = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-	
-	return 0;
-}
-
-void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
-{
-	struct s3c2410_platform_nand *npd;
-	int size;
-	int ret;
-
-	/* note, if we get a failure in allocation, we simply drop out of the
-	 * function. If there is so little memory available at initialisation
-	 * time then there is little chance the system is going to run.
-	 */ 
-
-	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
-				&s3c_device_nand);
-	if (!npd)
-		return;
-
-	/* now see if we need to copy any of the nand set data */
-
-	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
-	if (size) {
-		struct s3c2410_nand_set *from = npd->sets;
-		struct s3c2410_nand_set *to;
-		int i;
-
-		to = kmemdup(from, size, GFP_KERNEL);
-		npd->sets = to;	/* set, even if we failed */
-
-		if (!to) {
-			printk(KERN_ERR "%s: no memory for sets\n", __func__);
-			return;
-		}
-		
-		for (i = 0; i < npd->nr_sets; i++) {
-			ret = s3c_nand_copy_set(to);
-			if (ret) {
-				printk(KERN_ERR "%s: failed to copy set %d\n",
-				__func__, i);
-				return;
-			}
-			to++;
-		}
-	}
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-onenand.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-onenand.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-onenand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-onenand.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX/S5PC100 series device definition for OneNAND devices
- *
- * 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/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-static struct resource s3c_onenand_resources[] = {
-	[0] = {
-		.start	= S3C_PA_ONENAND,
-		.end	= S3C_PA_ONENAND + 0x400 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S3C_PA_ONENAND_BUF,
-		.end	= S3C_PA_ONENAND_BUF + S3C_SZ_ONENAND_BUF - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND,
-		.end	= IRQ_ONENAND,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_onenand = {
-	.name		= "samsung-onenand",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_onenand_resources),
-	.resource	= s3c_onenand_resources,
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-pwm.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-pwm.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-pwm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-pwm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2007 Ben Dooks
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * S3C series device definition for the PWM timer
- *
- * 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/platform_device.h>
-
-#include <mach/irqs.h>
-
-#include <plat/devs.h>
-
-#define TIMER_RESOURCE_SIZE (1)
-
-#define TIMER_RESOURCE(_tmr, _irq)			\
-	(struct resource [TIMER_RESOURCE_SIZE]) {	\
-		[0] = {					\
-			.start	= _irq,			\
-			.end	= _irq,			\
-			.flags	= IORESOURCE_IRQ	\
-		}					\
-	}
-
-#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
-	.name		= "s3c24xx-pwm",		\
-	.id		= _tmr_no,			\
-	.num_resources	= TIMER_RESOURCE_SIZE,		\
-	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
-
-/*
- * since we already have an static mapping for the timer,
- * we do not bother setting any IO resource for the base.
- */
-
-struct platform_device s3c_device_timer[] = {
-	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
-};
-EXPORT_SYMBOL(s3c_device_timer);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-rtc.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-rtc.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-rtc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-rtc.c
- *
- * Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_rtc_resource[] = {
-	[0] = {
-		.start	= S3C_PA_RTC,
-		.end	= S3C_PA_RTC + 0xff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_RTC_ALARM,
-		.end	= IRQ_RTC_ALARM,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_RTC_TIC,
-		.end	= IRQ_RTC_TIC,
-		.flags	= IORESOURCE_IRQ
-	}
-};
-
-struct platform_device s3c_device_rtc = {
-	.name		= "s3c64xx-rtc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
-	.resource	= s3c_rtc_resource,
-};
-EXPORT_SYMBOL(s3c_device_rtc);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/devs.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/devs.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/devs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/devs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1463 @@
+/* linux/arch/arm/plat-samsung/devs.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Base SAMSUNG platform device definitions
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+#include <asm/pmu.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/adc.h>
+#include <plat/ata.h>
+#include <plat/ehci.h>
+#include <plat/fb.h>
+#include <plat/fb-s3c2410.h>
+#include <plat/hwmon.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/mci.h>
+#include <plat/nand.h>
+#include <plat/sdhci.h>
+#include <plat/ts.h>
+#include <plat/udc.h>
+#include <plat/usb-control.h>
+#include <plat/usb-phy.h>
+#include <plat/regs-iic.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-spi.h>
+
+static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+
+/* AC97 */
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_ac97_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
+	[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
+	[2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
+	[3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
+	[4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
+};
+
+struct platform_device s3c_device_ac97 = {
+	.name		= "samsung-ac97",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_ac97_resource),
+	.resource	= s3c_ac97_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ADC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_adc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+	[2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+	.name		= "s3c24xx-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
+	.resource	= s3c_adc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#if defined(CONFIG_SAMSUNG_DEV_ADC)
+static struct resource s3c_adc_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+	[2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+	.name		= "samsung-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
+	.resource	= s3c_adc_resource,
+};
+#endif /* CONFIG_SAMSUNG_DEV_ADC */
+
+/* Camif Controller */
+
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_camif_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF),
+	[1] = DEFINE_RES_IRQ(IRQ_CAM),
+};
+
+struct platform_device s3c_device_camif = {
+	.name		= "s3c2440-camif",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_camif_resource),
+	.resource	= s3c_camif_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ASOC DMA */
+
+struct platform_device samsung_asoc_dma = {
+	.name		= "samsung-audio",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+struct platform_device samsung_asoc_idma = {
+	.name		= "samsung-idma",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+/* FB */
+
+#ifdef CONFIG_S3C_DEV_FB
+static struct resource s3c_fb_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
+	[2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
+	[3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
+};
+
+struct platform_device s3c_device_fb = {
+	.name		= "s3c-fb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_fb_resource),
+	.resource	= s3c_fb_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			 &s3c_device_fb);
+}
+#endif /* CONFIG_S3C_DEV_FB */
+
+/* FIMC */
+
+#ifdef CONFIG_S5P_DEV_FIMC0
+static struct resource s5p_fimc0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC0),
+};
+
+struct platform_device s5p_device_fimc0 = {
+	.name		= "s5p-fimc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimc0_resource),
+	.resource	= s5p_fimc0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device s5p_device_fimc_md = {
+	.name	= "s5p-fimc-md",
+	.id	= -1,
+};
+#endif /* CONFIG_S5P_DEV_FIMC0 */
+
+#ifdef CONFIG_S5P_DEV_FIMC1
+static struct resource s5p_fimc1_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC1),
+};
+
+struct platform_device s5p_device_fimc1 = {
+	.name		= "s5p-fimc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p_fimc1_resource),
+	.resource	= s5p_fimc1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC1 */
+
+#ifdef CONFIG_S5P_DEV_FIMC2
+static struct resource s5p_fimc2_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC2),
+};
+
+struct platform_device s5p_device_fimc2 = {
+	.name		= "s5p-fimc",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s5p_fimc2_resource),
+	.resource	= s5p_fimc2_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC2 */
+
+#ifdef CONFIG_S5P_DEV_FIMC3
+static struct resource s5p_fimc3_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC3),
+};
+
+struct platform_device s5p_device_fimc3 = {
+	.name		= "s5p-fimc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s5p_fimc3_resource),
+	.resource	= s5p_fimc3_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC3 */
+
+/* FIMD0 */
+
+#ifdef CONFIG_S5P_DEV_FIMD0
+static struct resource s5p_fimd0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
+	[2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
+	[3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
+};
+
+struct platform_device s5p_device_fimd0 = {
+	.name		= "s5p-fb",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
+	.resource	= s5p_fimd0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			 &s5p_device_fimd0);
+}
+#endif /* CONFIG_S5P_DEV_FIMD0 */
+
+/* HWMON */
+
+#ifdef CONFIG_S3C_DEV_HWMON
+struct platform_device s3c_device_hwmon = {
+	.name		= "s3c-hwmon",
+	.id		= -1,
+	.dev.parent	= &s3c_device_adc.dev,
+};
+
+void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+			 &s3c_device_hwmon);
+}
+#endif /* CONFIG_S3C_DEV_HWMON */
+
+/* HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static struct resource s3c_hsmmc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC0),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc0 = {
+	.name		= "s3c-sdhci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc_resource),
+	.resource	= s3c_hsmmc_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc0_def_platdata,
+	},
+};
+
+void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static struct resource s3c_hsmmc1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC1),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc1 = {
+	.name		= "s3c-sdhci",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc1_resource),
+	.resource	= s3c_hsmmc1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc1_def_platdata,
+	},
+};
+
+void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+/* HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static struct resource s3c_hsmmc2_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC2),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc2 = {
+	.name		= "s3c-sdhci",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc2_resource),
+	.resource	= s3c_hsmmc2_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc2_def_platdata,
+	},
+};
+
+void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC3
+static struct resource s3c_hsmmc3_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC3),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc3 = {
+	.name		= "s3c-sdhci",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc3_resource),
+	.resource	= s3c_hsmmc3_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc3_def_platdata,
+	},
+};
+
+void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC3 */
+
+/* I2C */
+
+static struct resource s3c_i2c0_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC),
+};
+
+struct platform_device s3c_device_i2c0 = {
+	.name		= "s3c2410-i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+	.id		= 0,
+#else
+	.id		= -1,
+#endif
+	.num_resources	= ARRAY_SIZE(s3c_i2c0_resource),
+	.resource	= s3c_i2c0_resource,
+};
+
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
+	.flags		= 0,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+};
+
+void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd)
+		pd = &default_i2c_data;
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c0);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+}
+
+#ifdef CONFIG_S3C_DEV_I2C1
+static struct resource s3c_i2c1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC1),
+};
+
+struct platform_device s3c_device_i2c1 = {
+	.name		= "s3c2410-i2c",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_i2c1_resource),
+	.resource	= s3c_i2c1_resource,
+};
+
+void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 1;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c1);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C1 */
+
+#ifdef CONFIG_S3C_DEV_I2C2
+static struct resource s3c_i2c2_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC2),
+};
+
+struct platform_device s3c_device_i2c2 = {
+	.name		= "s3c2410-i2c",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s3c_i2c2_resource),
+	.resource	= s3c_i2c2_resource,
+};
+
+void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 2;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c2);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C2 */
+
+#ifdef CONFIG_S3C_DEV_I2C3
+static struct resource s3c_i2c3_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC3),
+};
+
+struct platform_device s3c_device_i2c3 = {
+	.name		= "s3c2440-i2c",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s3c_i2c3_resource),
+	.resource	= s3c_i2c3_resource,
+};
+
+void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 3;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c3);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C3 */
+
+#ifdef CONFIG_S3C_DEV_I2C4
+static struct resource s3c_i2c4_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC4, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC4),
+};
+
+struct platform_device s3c_device_i2c4 = {
+	.name		= "s3c2440-i2c",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(s3c_i2c4_resource),
+	.resource	= s3c_i2c4_resource,
+};
+
+void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 4;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c4);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C4 */
+
+#ifdef CONFIG_S3C_DEV_I2C5
+static struct resource s3c_i2c5_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC5, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC5),
+};
+
+struct platform_device s3c_device_i2c5 = {
+	.name		= "s3c2440-i2c",
+	.id		= 5,
+	.num_resources	= ARRAY_SIZE(s3c_i2c5_resource),
+	.resource	= s3c_i2c5_resource,
+};
+
+void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 5;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c5);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C5 */
+
+#ifdef CONFIG_S3C_DEV_I2C6
+static struct resource s3c_i2c6_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC6, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC6),
+};
+
+struct platform_device s3c_device_i2c6 = {
+	.name		= "s3c2440-i2c",
+	.id		= 6,
+	.num_resources	= ARRAY_SIZE(s3c_i2c6_resource),
+	.resource	= s3c_i2c6_resource,
+};
+
+void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 6;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c6);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C6 */
+
+#ifdef CONFIG_S3C_DEV_I2C7
+static struct resource s3c_i2c7_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC7, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC7),
+};
+
+struct platform_device s3c_device_i2c7 = {
+	.name		= "s3c2440-i2c",
+	.id		= 7,
+	.num_resources	= ARRAY_SIZE(s3c_i2c7_resource),
+	.resource	= s3c_i2c7_resource,
+};
+
+void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 7;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c7);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C7 */
+
+/* I2C HDMIPHY */
+
+#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
+static struct resource s5p_i2c_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
+};
+
+struct platform_device s5p_device_i2c_hdmiphy = {
+	.name		= "s3c2440-hdmiphy-i2c",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_i2c_resource),
+	.resource	= s5p_i2c_resource,
+};
+
+void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+
+		if (soc_is_exynos4210())
+			pd->bus_num = 8;
+		else if (soc_is_s5pv210())
+			pd->bus_num = 3;
+		else
+			pd->bus_num = 0;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s5p_device_i2c_hdmiphy);
+}
+#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
+
+/* I2S */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_iis_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
+};
+
+struct platform_device s3c_device_iis = {
+	.name		= "s3c24xx-iis",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_iis_resource),
+	.resource	= s3c_iis_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_CPU_S3C2440
+struct platform_device s3c2412_device_iis = {
+	.name		= "s3c2412-iis",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* IDE CFCON */
+
+#ifdef CONFIG_SAMSUNG_DEV_IDE
+static struct resource s3c_cfcon_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_CFCON, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_CFCON),
+};
+
+struct platform_device s3c_device_cfcon = {
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_cfcon_resource),
+	.resource	= s3c_cfcon_resource,
+};
+
+void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
+			 &s3c_device_cfcon);
+}
+#endif /* CONFIG_SAMSUNG_DEV_IDE */
+
+/* KEYPAD */
+
+#ifdef CONFIG_SAMSUNG_DEV_KEYPAD
+static struct resource samsung_keypad_resources[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_KEYPAD, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_KEYPAD),
+};
+
+struct platform_device samsung_device_keypad = {
+	.name		= "samsung-keypad",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(samsung_keypad_resources),
+	.resource	= samsung_keypad_resources,
+};
+
+void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
+{
+	struct samsung_keypad_platdata *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
+			&samsung_device_keypad);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = samsung_keypad_cfg_gpio;
+}
+#endif /* CONFIG_SAMSUNG_DEV_KEYPAD */
+
+/* LCD Controller */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_lcd_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD),
+	[1] = DEFINE_RES_IRQ(IRQ_LCD),
+};
+
+struct platform_device s3c_device_lcd = {
+	.name		= "s3c2410-lcd",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_lcd_resource),
+	.resource	= s3c_lcd_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
+{
+	struct s3c2410fb_mach_info *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
+	if (npd) {
+		npd->displays = kmemdup(pd->displays,
+			sizeof(struct s3c2410fb_display) * npd->num_displays,
+			GFP_KERNEL);
+		if (!npd->displays)
+			printk(KERN_ERR "no memory for LCD display data\n");
+	} else {
+		printk(KERN_ERR "no memory for LCD platform data\n");
+	}
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* MFC */
+
+#ifdef CONFIG_S5P_DEV_MFC
+static struct resource s5p_mfc_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
+	[1] = DEFINE_RES_IRQ(IRQ_MFC),
+};
+
+struct platform_device s5p_device_mfc = {
+	.name		= "s5p-mfc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
+	.resource	= s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+struct platform_device s5p_device_mfc_l = {
+	.name		= "s5p-mfc-l",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device s5p_device_mfc_r = {
+	.name		= "s5p-mfc-r",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_MFC */
+
+/* MIPI CSIS */
+
+#ifdef CONFIG_S5P_DEV_CSIS0
+static struct resource s5p_mipi_csis0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
+};
+
+struct platform_device s5p_device_mipi_csis0 = {
+	.name		= "s5p-mipi-csis",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_mipi_csis0_resource),
+	.resource	= s5p_mipi_csis0_resource,
+};
+#endif /* CONFIG_S5P_DEV_CSIS0 */
+
+#ifdef CONFIG_S5P_DEV_CSIS1
+static struct resource s5p_mipi_csis1_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
+};
+
+struct platform_device s5p_device_mipi_csis1 = {
+	.name		= "s5p-mipi-csis",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p_mipi_csis1_resource),
+	.resource	= s5p_mipi_csis1_resource,
+};
+#endif
+
+/* NAND */
+
+#ifdef CONFIG_S3C_DEV_NAND
+static struct resource s3c_nand_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_NAND, SZ_1M),
+};
+
+struct platform_device s3c_device_nand = {
+	.name		= "s3c2410-nand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_nand_resource),
+	.resource	= s3c_nand_resource,
+};
+
+/*
+ * s3c_nand_copy_set() - copy nand set data
+ * @set: The new structure, directly copied from the old.
+ *
+ * Copy all the fields from the NAND set field from what is probably __initdata
+ * to new kernel memory. The code returns 0 if the copy happened correctly or
+ * an error code for the calling function to display.
+ *
+ * Note, we currently do not try and look to see if we've already copied the
+ * data in a previous set.
+ */
+static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
+{
+	void *ptr;
+	int size;
+
+	size = sizeof(struct mtd_partition) * set->nr_partitions;
+	if (size) {
+		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
+		set->partitions = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	if (set->nr_map && set->nr_chips) {
+		size = sizeof(int) * set->nr_chips;
+		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
+		set->nr_map = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	if (set->ecc_layout) {
+		ptr = kmemdup(set->ecc_layout,
+			      sizeof(struct nand_ecclayout), GFP_KERNEL);
+		set->ecc_layout = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
+{
+	struct s3c2410_platform_nand *npd;
+	int size;
+	int ret;
+
+	/* note, if we get a failure in allocation, we simply drop out of the
+	 * function. If there is so little memory available at initialisation
+	 * time then there is little chance the system is going to run.
+	 */
+
+	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+				&s3c_device_nand);
+	if (!npd)
+		return;
+
+	/* now see if we need to copy any of the nand set data */
+
+	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
+	if (size) {
+		struct s3c2410_nand_set *from = npd->sets;
+		struct s3c2410_nand_set *to;
+		int i;
+
+		to = kmemdup(from, size, GFP_KERNEL);
+		npd->sets = to;	/* set, even if we failed */
+
+		if (!to) {
+			printk(KERN_ERR "%s: no memory for sets\n", __func__);
+			return;
+		}
+
+		for (i = 0; i < npd->nr_sets; i++) {
+			ret = s3c_nand_copy_set(to);
+			if (ret) {
+				printk(KERN_ERR "%s: failed to copy set %d\n",
+				__func__, i);
+				return;
+			}
+			to++;
+		}
+	}
+}
+#endif /* CONFIG_S3C_DEV_NAND */
+
+/* ONENAND */
+
+#ifdef CONFIG_S3C_DEV_ONENAND
+static struct resource s3c_onenand_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_ONENAND, SZ_1K),
+	[1] = DEFINE_RES_MEM(S3C_PA_ONENAND_BUF, S3C_SZ_ONENAND_BUF),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND),
+};
+
+struct platform_device s3c_device_onenand = {
+	.name		= "samsung-onenand",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_onenand_resources),
+	.resource	= s3c_onenand_resources,
+};
+#endif /* CONFIG_S3C_DEV_ONENAND */
+
+#ifdef CONFIG_S3C64XX_DEV_ONENAND1
+static struct resource s3c64xx_onenand1_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1, SZ_1K),
+	[1] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1_BUF, S3C64XX_SZ_ONENAND1_BUF),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND1),
+};
+
+struct platform_device s3c64xx_device_onenand1 = {
+	.name		= "samsung-onenand",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c64xx_onenand1_resources),
+	.resource	= s3c64xx_onenand1_resources,
+};
+
+void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+			 &s3c64xx_device_onenand1);
+}
+#endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
+
+#ifdef CONFIG_S5P_DEV_ONENAND
+static struct resource s5p_onenand_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
+	[1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
+};
+
+struct platform_device s5p_device_onenand = {
+	.name		= "s5pc110-onenand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
+	.resource	= s5p_onenand_resources,
+};
+#endif /* CONFIG_S5P_DEV_ONENAND */
+
+/* PMU */
+
+#ifdef CONFIG_PLAT_S5P
+static struct resource s5p_pmu_resource[] = {
+	DEFINE_RES_IRQ(IRQ_PMU)
+};
+
+struct platform_device s5p_device_pmu = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.num_resources	= ARRAY_SIZE(s5p_pmu_resource),
+	.resource	= s5p_pmu_resource,
+};
+
+static int __init s5p_pmu_init(void)
+{
+	platform_device_register(&s5p_device_pmu);
+	return 0;
+}
+arch_initcall(s5p_pmu_init);
+#endif /* CONFIG_PLAT_S5P */
+
+/* PWM Timer */
+
+#ifdef CONFIG_SAMSUNG_DEV_PWM
+
+#define TIMER_RESOURCE_SIZE (1)
+
+#define TIMER_RESOURCE(_tmr, _irq)			\
+	(struct resource [TIMER_RESOURCE_SIZE]) {	\
+		[0] = {					\
+			.start	= _irq,			\
+			.end	= _irq,			\
+			.flags	= IORESOURCE_IRQ	\
+		}					\
+	}
+
+#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
+	.name		= "s3c24xx-pwm",		\
+	.id		= _tmr_no,			\
+	.num_resources	= TIMER_RESOURCE_SIZE,		\
+	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
+
+/*
+ * since we already have an static mapping for the timer,
+ * we do not bother setting any IO resource for the base.
+ */
+
+struct platform_device s3c_device_timer[] = {
+	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
+	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
+	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
+	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
+	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+};
+#endif /* CONFIG_SAMSUNG_DEV_PWM */
+
+/* RTC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_rtc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_RTC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_RTC),
+	[2] = DEFINE_RES_IRQ(IRQ_TICK),
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		= "s3c2410-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
+	.resource	= s3c_rtc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_S3C_DEV_RTC
+static struct resource s3c_rtc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_RTC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_RTC_ALARM),
+	[2] = DEFINE_RES_IRQ(IRQ_RTC_TIC),
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		= "s3c64xx-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
+	.resource	= s3c_rtc_resource,
+};
+#endif /* CONFIG_S3C_DEV_RTC */
+
+/* SDI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_sdi_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SDI, S3C24XX_SZ_SDI),
+	[1] = DEFINE_RES_IRQ(IRQ_SDI),
+};
+
+struct platform_device s3c_device_sdi = {
+	.name		= "s3c2410-sdi",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_sdi_resource),
+	.resource	= s3c_sdi_resource,
+};
+
+void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+			 &s3c_device_sdi);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* SPI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_spi0_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SPI, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_SPI0),
+};
+
+struct platform_device s3c_device_spi0 = {
+	.name		= "s3c2410-spi",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_spi0_resource),
+	.resource	= s3c_spi0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+static struct resource s3c_spi1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SPI1, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_SPI1),
+};
+
+struct platform_device s3c_device_spi1 = {
+	.name		= "s3c2410-spi",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_spi1_resource),
+	.resource	= s3c_spi1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* Touchscreen */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_ts_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+struct platform_device s3c_device_ts = {
+	.name		= "s3c2410-ts",
+	.id		= -1,
+	.dev.parent	= &s3c_device_adc.dev,
+	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
+	.resource	= s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+	s3c_set_platdata(hard_s3c2410ts_info,
+			 sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_SAMSUNG_DEV_TS
+static struct resource s3c_ts_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+	.delay			= 10000,
+	.presc			= 49,
+	.oversampling_shift	= 2,
+};
+
+struct platform_device s3c_device_ts = {
+	.name		= "s3c64xx-ts",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
+	.resource	= s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
+{
+	if (!pd)
+		pd = &default_ts_data;
+
+	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+			 &s3c_device_ts);
+}
+#endif /* CONFIG_SAMSUNG_DEV_TS */
+
+/* TV */
+
+#ifdef CONFIG_S5P_DEV_TV
+
+static struct resource s5p_hdmi_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
+	[1] = DEFINE_RES_IRQ(IRQ_HDMI),
+};
+
+struct platform_device s5p_device_hdmi = {
+	.name		= "s5p-hdmi",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_hdmi_resources),
+	.resource	= s5p_hdmi_resources,
+};
+
+static struct resource s5p_sdo_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
+	[1] = DEFINE_RES_IRQ(IRQ_SDO),
+};
+
+struct platform_device s5p_device_sdo = {
+	.name		= "s5p-sdo",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_sdo_resources),
+	.resource	= s5p_sdo_resources,
+};
+
+static struct resource s5p_mixer_resources[] = {
+	[0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
+	[1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
+	[2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
+};
+
+struct platform_device s5p_device_mixer = {
+	.name		= "s5p-mixer",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_mixer_resources),
+	.resource	= s5p_mixer_resources,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_S5P_DEV_TV */
+
+/* USB */
+
+#ifdef CONFIG_S3C_DEV_USB_HOST
+static struct resource s3c_usb_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_USBHOST, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_USBH),
+};
+
+struct platform_device s3c_device_ohci = {
+	.name		= "s3c2410-ohci",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_resource),
+	.resource	= s3c_usb_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+/*
+ * s3c_ohci_set_platdata - initialise OHCI device platform data
+ * @info: The platform data.
+ *
+ * This call copies the @info passed in and sets the device .platform_data
+ * field to that copy. The @info is copied so that the original can be marked
+ * __initdata.
+ */
+
+void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
+{
+	s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+			 &s3c_device_ohci);
+}
+#endif /* CONFIG_S3C_DEV_USB_HOST */
+
+/* USB Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_usbgadget_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_USBDEV, S3C24XX_SZ_USBDEV),
+	[1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usbgadget = {
+	.name		= "s3c2410-usbgadget",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usbgadget_resource),
+	.resource	= s3c_usbgadget_resource,
+};
+
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* USB EHCI Host Controller */
+
+#ifdef CONFIG_S5P_DEV_USB_EHCI
+static struct resource s5p_ehci_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_EHCI, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
+};
+
+struct platform_device s5p_device_ehci = {
+	.name		= "s5p-ehci",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_ehci_resource),
+	.resource	= s5p_ehci_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
+{
+	struct s5p_ehci_platdata *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
+			&s5p_device_ehci);
+
+	if (!npd->phy_init)
+		npd->phy_init = s5p_usb_phy_init;
+	if (!npd->phy_exit)
+		npd->phy_exit = s5p_usb_phy_exit;
+}
+#endif /* CONFIG_S5P_DEV_USB_EHCI */
+
+/* USB HSOTG */
+
+#ifdef CONFIG_S3C_DEV_USB_HSOTG
+static struct resource s3c_usb_hsotg_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_USB_HSOTG, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_OTG),
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+	.name		= "s3c-hsotg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
+	.resource	= s3c_usb_hsotg_resources,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S3C_DEV_USB_HSOTG */
+
+/* USB High Spped 2.0 Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_hsudc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2416_PA_HSUDC, S3C2416_SZ_HSUDC),
+	[1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usb_hsudc = {
+	.name		= "s3c-hsudc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_hsudc_resource),
+	.resource	= s3c_hsudc_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* WDT */
+
+#ifdef CONFIG_S3C_DEV_WDT
+static struct resource s3c_wdt_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_WDT, SZ_1K),
+	[1] = DEFINE_RES_IRQ(IRQ_WDT),
+};
+
+struct platform_device s3c_device_wdt = {
+	.name		= "s3c2410-wdt",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_wdt_resource),
+	.resource	= s3c_wdt_resource,
+};
+#endif /* CONFIG_S3C_DEV_WDT */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-ts.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-ts.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-ts.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* linux/arch/arm/mach-s3c64xx/dev-ts.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * Adapted by Maurus Cuelenaere for s3c64xx
- *
- * S3C64XX series device definition for touchscreen device
- *
- * 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/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/ts.h>
-
-static struct resource s3c_ts_resource[] = {
-	[0] = {
-		.start = SAMSUNG_PA_ADC,
-		.end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_ts = {
-	.name		= "s3c64xx-ts",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
-	.resource	= s3c_ts_resource,
-};
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
-			 &s3c_device_ts);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-usb.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-usb.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-usb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB host
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/usb-control.h>
-
-static struct resource s3c_usb_resource[] = {
-	[0] = {
-		.start = S3C_PA_USBHOST,
-		.end   = S3C_PA_USBHOST + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBH,
-		.end   = IRQ_USBH,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ohci = {
-	.name		  = "s3c2410-ohci",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
-	.resource	  = s3c_usb_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_usb_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_ohci);
-
-/**
- * s3c_ohci_set_platdata - initialise OHCI device platform data
- * @info: The platform data.
- *
- * This call copies the @info passed in and sets the device .platform_data
- * field to that copy. The @info is copied so that the original can be marked
- * __initdata.
- */
-void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
-{
-	s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
-			 &s3c_device_ohci);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-usb-hsotg.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-usb-hsotg.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-usb-hsotg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-usb-hsotg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB high-speed UDC/OtG block
- *
- * 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/string.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_usb_hsotg_resources[] = {
-	[0] = {
-		.start	= S3C_PA_USB_HSOTG,
-		.end	= S3C_PA_USB_HSOTG + 0x10000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_OTG,
-		.end	= IRQ_OTG,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s3c_hsotg_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsotg = {
-	.name		= "s3c-hsotg",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
-	.resource	= s3c_usb_hsotg_resources,
-	.dev		= {
-		.dma_mask		= &s3c_hsotg_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-wdt.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-wdt.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dev-wdt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dev-wdt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-wdt.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C series device definition for the watchdog timer
- *
- * 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/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_wdt_resource[] = {
-	[0] = {
-		.start	= S3C_PA_WDT,
-		.end	= S3C_PA_WDT + SZ_1K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_WDT,
-		.end	= IRQ_WDT,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s3c_device_wdt = {
-	.name		= "s3c2410-wdt",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_wdt_resource),
-	.resource	= s3c_wdt_resource,
-};
-EXPORT_SYMBOL(s3c_device_wdt);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/dma-ops.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/dma-ops.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/dma-ops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/dma-ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,132 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * 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/errno.h>
+#include <linux/amba/pl330.h>
+#include <linux/scatterlist.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+static inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = chan->private;
+	return peri->peri_id == (unsigned)param;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+				struct samsung_dma_info *info)
+{
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+	struct dma_slave_config slave_config;
+
+	dma_cap_zero(mask);
+	dma_cap_set(info->cap, mask);
+
+	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+	if (info->direction == DMA_FROM_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.src_addr = info->fifo;
+		slave_config.src_addr_width = info->width;
+		slave_config.src_maxburst = 1;
+		dmaengine_slave_config(chan, &slave_config);
+	} else if (info->direction == DMA_TO_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.dst_addr = info->fifo;
+		slave_config.dst_addr_width = info->width;
+		slave_config.dst_maxburst = 1;
+		dmaengine_slave_config(chan, &slave_config);
+	}
+
+	return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+			struct s3c2410_dma_client *client)
+{
+	dma_release_channel((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+			struct samsung_dma_prep_info *info)
+{
+	struct scatterlist sg;
+	struct dma_chan *chan = (struct dma_chan *)ch;
+	struct dma_async_tx_descriptor *desc;
+
+	switch (info->cap) {
+	case DMA_SLAVE:
+		sg_init_table(&sg, 1);
+		sg_dma_len(&sg) = info->len;
+		sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+			    info->len, offset_in_page(info->buf));
+		sg_dma_address(&sg) = info->buf;
+
+		desc = chan->device->device_prep_slave_sg(chan,
+			&sg, 1, info->direction, DMA_PREP_INTERRUPT);
+		break;
+	case DMA_CYCLIC:
+		desc = chan->device->device_prep_dma_cyclic(chan,
+			info->buf, info->len, info->period, info->direction);
+		break;
+	default:
+		dev_err(&chan->dev->device, "unsupported format\n");
+		return -EFAULT;
+	}
+
+	if (!desc) {
+		dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+		return -EFAULT;
+	}
+
+	desc->callback = info->fp;
+	desc->callback_param = info->fp_param;
+
+	dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+	dma_async_issue_pending((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+	return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+	.request	= samsung_dmadev_request,
+	.release	= samsung_dmadev_release,
+	.prepare	= samsung_dmadev_prepare,
+	.trigger	= samsung_dmadev_trigger,
+	.started	= NULL,
+	.flush		= samsung_dmadev_flush,
+	.stop		= samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+	return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/gpio.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * 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/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-
-#include <plat/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-	unsigned int gpn;
-	int i;
-
-	gpn = chip->chip.base;
-	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-		s3c_gpios[gpn] = chip;
-	}
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *	        gpio n: 2 bits starting at (2*n)
- *		00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-
-	__raw_writel(con, base + 0x00);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-			      unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-	con |= 1 << (offset * 2);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-			    unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	unsigned long val;
-
-	val = __raw_readl(ourchip->base + 0x04);
-	val >>= offset;
-	val &= 1;
-
-	return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-	struct gpio_chip *gc = &chip->chip;
-	int ret;
-
-	BUG_ON(!chip->base);
-	BUG_ON(!gc->label);
-	BUG_ON(!gc->ngpio);
-
-	spin_lock_init(&chip->lock);
-
-	if (!gc->direction_input)
-		gc->direction_input = s3c_gpiolib_input;
-	if (!gc->direction_output)
-		gc->direction_output = s3c_gpiolib_output;
-	if (!gc->set)
-		gc->set = s3c_gpiolib_set;
-	if (!gc->get)
-		gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-	if (chip->pm != NULL) {
-		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
-			       gc->label);
-	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-	/* gpiochip_add() prints own failure message on error. */
-	ret = gpiochip_add(gc);
-	if (ret >= 0)
-		s3c_gpiolib_track(chip);
-}
-
-int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return s3c_chip->irq_base + offset;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/gpio-config.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/gpio-config.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/gpio-config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/gpio-config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,431 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio-config.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO configuration core
- *
- * 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/module.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset;
-	int ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	s3c_gpio_lock(chip, flags);
-	ret = s3c_gpio_do_setcfg(chip, offset, config);
-	s3c_gpio_unlock(chip, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_cfgpin);
-
-int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
-			  unsigned int cfg)
-{
-	int ret;
-
-	for (; nr > 0; nr--, start++) {
-		ret = s3c_gpio_cfgpin(start, cfg);
-		if (ret != 0)
-			return ret;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
-
-int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-			  unsigned int cfg, s3c_gpio_pull_t pull)
-{
-	int ret;
-
-	for (; nr > 0; nr--, start++) {
-		s3c_gpio_setpull(start, pull);
-		ret = s3c_gpio_cfgpin(start, cfg);
-		if (ret != 0)
-			return ret;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
-
-unsigned s3c_gpio_getcfg(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	unsigned ret = 0;
-	int offset;
-
-	if (chip) {
-		offset = pin - chip->chip.base;
-
-		s3c_gpio_lock(chip, flags);
-		ret = s3c_gpio_do_getcfg(chip, offset);
-		s3c_gpio_unlock(chip, flags);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_getcfg);
-
-
-int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset, ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	s3c_gpio_lock(chip, flags);
-	ret = s3c_gpio_do_setpull(chip, offset, pull);
-	s3c_gpio_unlock(chip, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_setpull);
-
-s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset;
-	u32 pup = 0;
-
-	if (chip) {
-		offset = pin - chip->chip.base;
-
-		s3c_gpio_lock(chip, flags);
-		pup = s3c_gpio_do_getpull(chip, offset);
-		s3c_gpio_unlock(chip, flags);
-	}
-
-	return (__force s3c_gpio_pull_t)pup;
-}
-EXPORT_SYMBOL(s3c_gpio_getpull);
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-			      unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-
-		/* Map output to 0, and SFN2 to 1 */
-		cfg -= 1;
-		if (cfg > 1)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x1 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-				   unsigned int off)
-{
-	u32 con;
-
-	con = __raw_readl(chip->base);
-	con >>= off;
-	con &= 1;
-	con++;
-
-	return S3C_GPIO_SFN(con);
-}
-
-int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-			    unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off * 2;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		if (cfg > 3)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x3 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	u32 con;
-
-	con = __raw_readl(chip->base);
-	con >>= off * 2;
-	con &= 3;
-
-	/* this conversion works for IN and OUT as well as special mode */
-	return S3C_GPIO_SPECIAL(con);
-}
-#endif
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
-int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-				 unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = (off & 7) * 4;
-	u32 con;
-
-	if (off < 8 && chip->chip.ngpio > 8)
-		reg -= 4;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0xf << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-				      unsigned int off)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = (off & 7) * 4;
-	u32 con;
-
-	if (off < 8 && chip->chip.ngpio > 8)
-		reg -= 4;
-
-	con = __raw_readl(reg);
-	con >>= shift;
-	con &= 0xf;
-
-	/* this conversion works for IN and OUT as well as special mode */
-	return S3C_GPIO_SPECIAL(con);
-}
-
-#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
-int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-			    unsigned int off, s3c_gpio_pull_t pull)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup;
-
-	pup = __raw_readl(reg);
-	pup &= ~(3 << shift);
-	pup |= pull << shift;
-	__raw_writel(pup, reg);
-
-	return 0;
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					unsigned int off)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup = __raw_readl(reg);
-
-	pup >>= shift;
-	pup &= 0x3;
-	return (__force s3c_gpio_pull_t)pup;
-}
-
-#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
-int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull)
-{
-	switch (pull) {
-	case S3C_GPIO_PULL_NONE:
-		pull = 0x01;
-		break;
-	case S3C_GPIO_PULL_UP:
-		pull = 0x00;
-		break;
-	case S3C_GPIO_PULL_DOWN:
-		pull = 0x02;
-		break;
-	}
-	return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
-					unsigned int off)
-{
-	s3c_gpio_pull_t pull;
-
-	pull = s3c_gpio_getpull_updown(chip, off);
-
-	switch (pull) {
-	case 0x00:
-		pull = S3C_GPIO_PULL_UP;
-		break;
-	case 0x01:
-	case 0x03:
-		pull = S3C_GPIO_PULL_NONE;
-		break;
-	case 0x02:
-		pull = S3C_GPIO_PULL_DOWN;
-		break;
-	}
-
-	return pull;
-}
-#endif
-#endif
-
-#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
-static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull,
-			 s3c_gpio_pull_t updown)
-{
-	void __iomem *reg = chip->base + 0x08;
-	u32 pup = __raw_readl(reg);
-
-	if (pull == updown)
-		pup &= ~(1 << off);
-	else if (pull == S3C_GPIO_PULL_NONE)
-		pup |= (1 << off);
-	else
-		return -EINVAL;
-
-	__raw_writel(pup, reg);
-	return 0;
-}
-
-static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
-				     unsigned int off, s3c_gpio_pull_t updown)
-{
-	void __iomem *reg = chip->base + 0x08;
-	u32 pup = __raw_readl(reg);
-
-	pup &= (1 << off);
-	return pup ? S3C_GPIO_PULL_NONE : updown;
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
-}
-
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull)
-{
-	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP */
-
-#ifdef CONFIG_S3C_GPIO_PULL_DOWN
-s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
-}
-
-int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull)
-{
-	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S5P_GPIO_DRVSTR
-s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned int off;
-	void __iomem *reg;
-	int shift;
-	u32 drvstr;
-
-	if (!chip)
-		return -EINVAL;
-
-	off = pin - chip->chip.base;
-	shift = off * 2;
-	reg = chip->base + 0x0C;
-
-	drvstr = __raw_readl(reg);
-	drvstr = drvstr >> shift;
-	drvstr &= 0x3;
-
-	return (__force s5p_gpio_drvstr_t)drvstr;
-}
-EXPORT_SYMBOL(s5p_gpio_get_drvstr);
-
-int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned int off;
-	void __iomem *reg;
-	int shift;
-	u32 tmp;
-
-	if (!chip)
-		return -EINVAL;
-
-	off = pin - chip->chip.base;
-	shift = off * 2;
-	reg = chip->base + 0x0C;
-
-	tmp = __raw_readl(reg);
-	tmp &= ~(0x3 << shift);
-	tmp |= drvstr << shift;
-
-	__raw_writel(tmp, reg);
-
-	return 0;
-}
-EXPORT_SYMBOL(s5p_gpio_set_drvstr);
-#endif	/* CONFIG_S5P_GPIO_DRVSTR */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/adc-core.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/adc-core.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/adc-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/adc-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 /* re-define device name depending on support. */
 static inline void s3c_adc_setname(char *name)
 {
-#ifdef CONFIG_SAMSUNG_DEV_ADC
+#if defined(CONFIG_SAMSUNG_DEV_ADC) || defined(CONFIG_PLAT_S3C24XX)
 	s3c_device_adc.name = name;
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/audio-simtec.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/audio-simtec.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/audio-simtec.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/audio-simtec.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/* arch/arm/plat-samsung/include/plat/audio-simtec.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+ * Simtec Audio support.
+*/
+
+/**
+ * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
+ * @use_mpllin: Select codec clock from MPLLin
+ * @output_cdclk: Need to output CDCLK to the codec
+ * @have_mic: Set if we have a MIC socket
+ * @have_lout: Set if we have a LineOut socket
+ * @amp_gpio: GPIO pin to enable the AMP
+ * @amp_gain: Option GPIO to control AMP gain
+ */
+struct s3c24xx_audio_simtec_pdata {
+	unsigned int	use_mpllin:1;
+	unsigned int	output_cdclk:1;
+
+	unsigned int	have_mic:1;
+	unsigned int	have_lout:1;
+
+	int		amp_gpio;
+	int		amp_gain[2];
+
+	void	(*startup)(void);
+};
+
+extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
+			    struct s3c24xx_audio_simtec_pdata *pdata);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/camport.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/camport.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/camport.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series camera interface helper functions
+ *
+ * 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 __PLAT_SAMSUNG_CAMPORT_H_
+#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
+
+enum s5p_camport_id {
+	S5P_CAMPORT_A,
+	S5P_CAMPORT_B,
+};
+
+/*
+ * The helper functions to configure GPIO for the camera parallel bus.
+ * The camera port can be multiplexed with any FIMC entity, even multiple
+ * FIMC entities are allowed to be attached to a single port simultaneously.
+ * These functions are to be used in the board setup code.
+ */
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
+
+#endif /* __PLAT_SAMSUNG_CAMPORT_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/common-smdk.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/common-smdk.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/common-smdk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/common-smdk.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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.
+*/
+
+extern void smdk_machine_init(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/cpu-freq-core.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,293 @@
+/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
+ *
+ * Copyright (c) 2006-2009 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C CPU frequency scaling support - core support
+ *
+ * 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 <plat/cpu-freq.h>
+
+struct seq_file;
+
+#define MAX_BANKS (8)
+#define S3C2412_MAX_IO	(8)
+
+/**
+ * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
+ * @bankcon: The cached version of settings in this structure.
+ * @tacp:
+ * @tacs: Time from address valid to nCS asserted.
+ * @tcos: Time from nCS asserted to nOE or nWE asserted.
+ * @tacc: Time that nOE or nWE is asserted.
+ * @tcoh: Time nCS is held after nOE or nWE are released.
+ * @tcah: Time address is held for after
+ * @nwait_en: Whether nWAIT is enabled for this bank.
+ *
+ * This structure represents the IO timings for a S3C2410 style IO bank
+ * used by the CPU frequency support if it needs to change the settings
+ * of the IO.
+ */
+struct s3c2410_iobank_timing {
+	unsigned long	bankcon;
+	unsigned int	tacp;
+	unsigned int	tacs;
+	unsigned int	tcos;
+	unsigned int	tacc;
+	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
+	unsigned int	tcah;		/* Address hold after nCS */
+	unsigned char	nwait_en;	/* nWait enabled for bank. */
+};
+
+/**
+ * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
+ * @idcy: The idle cycle time between transactions.
+ * @wstrd: nCS release to end of read cycle.
+ * @wstwr: nCS release to end of write cycle.
+ * @wstoen: nCS assertion to nOE assertion time.
+ * @wstwen: nCS assertion to nWE assertion time.
+ * @wstbrd: Burst ready delay.
+ * @smbidcyr: Register cache for smbidcyr value.
+ * @smbwstrd: Register cache for smbwstrd value.
+ * @smbwstwr: Register cache for smbwstwr value.
+ * @smbwstoen: Register cache for smbwstoen value.
+ * @smbwstwen: Register cache for smbwstwen value.
+ * @smbwstbrd: Register cache for smbwstbrd value.
+ *
+ * Timing information for a IO bank on an S3C2412 or similar system which
+ * uses a PL093 block.
+ */
+struct s3c2412_iobank_timing {
+	unsigned int	idcy;
+	unsigned int	wstrd;
+	unsigned int	wstwr;
+	unsigned int	wstoen;
+	unsigned int	wstwen;
+	unsigned int	wstbrd;
+
+	/* register cache */
+	unsigned char	smbidcyr;
+	unsigned char	smbwstrd;
+	unsigned char	smbwstwr;
+	unsigned char	smbwstoen;
+	unsigned char	smbwstwen;
+	unsigned char	smbwstbrd;
+};
+
+union s3c_iobank {
+	struct s3c2410_iobank_timing	*io_2410;
+	struct s3c2412_iobank_timing	*io_2412;
+};
+
+/**
+ * struct s3c_iotimings - Chip IO timings holder
+ * @bank: The timings for each IO bank.
+ */
+struct s3c_iotimings {
+	union s3c_iobank	bank[MAX_BANKS];
+};
+
+/**
+ * struct s3c_plltab - PLL table information.
+ * @vals: List of PLL values.
+ * @size: Size of the PLL table @vals.
+ */
+struct s3c_plltab {
+	struct s3c_pllval	*vals;
+	int			 size;
+};
+
+/**
+ * struct s3c_cpufreq_config - current cpu frequency configuration
+ * @freq: The current settings for the core clocks.
+ * @max: Maxium settings, derived from core, board and user settings.
+ * @pll: The PLL table entry for the current PLL settings.
+ * @divs: The divisor settings for the core clocks.
+ * @info: The current core driver information.
+ * @board: The information for the board we are running on.
+ * @lock_pll: Set if the PLL settings cannot be changed.
+ *
+ * This is for the core drivers that need to know information about
+ * the current settings and values. It should not be needed by any
+ * device drivers.
+*/
+struct s3c_cpufreq_config {
+	struct s3c_freq		freq;
+	struct s3c_freq		max;
+	struct cpufreq_frequency_table pll;
+	struct s3c_clkdivs	divs;
+	struct s3c_cpufreq_info *info;	/* for core, not drivers */
+	struct s3c_cpufreq_board *board;
+
+	unsigned int	lock_pll:1;
+};
+
+/**
+ * struct s3c_cpufreq_info - Information for the CPU frequency driver.
+ * @name: The name of this implementation.
+ * @max: The maximum frequencies for the system.
+ * @latency: Transition latency to give to cpufreq.
+ * @locktime_m: The lock-time in uS for the MPLL.
+ * @locktime_u: The lock-time in uS for the UPLL.
+ * @locttime_bits: The number of bits each LOCKTIME field.
+ * @need_pll: Set if this driver needs to change the PLL values to achieve
+ *	any frequency changes. This is really only need by devices like the
+ *	S3C2410 where there is no or limited divider between the PLL and the
+ *	ARMCLK.
+ * @resume_clocks: Update the clocks on resume.
+ * @get_iotiming: Get the current IO timing data, mainly for use at start.
+ * @set_iotiming: Update the IO timings from the cached copies calculated
+ *	from the @calc_iotiming entry when changing the frequency.
+ * @calc_iotiming: Calculate and update the cached copies of the IO timings
+ *	from the newly calculated frequencies.
+ * @calc_freqtable: Calculate (fill in) the given frequency table from the
+ *	current frequency configuration. If the table passed in is NULL,
+ *	then the return is the number of elements to be filled for allocation
+ *	of the table.
+ * @set_refresh: Set the memory refresh configuration.
+ * @set_fvco: Set the PLL frequencies.
+ * @set_divs: Update the clock divisors.
+ * @calc_divs: Calculate the clock divisors.
+ */
+struct s3c_cpufreq_info {
+	const char		*name;
+	struct s3c_freq		max;
+
+	unsigned int		latency;
+
+	unsigned int		locktime_m;
+	unsigned int		locktime_u;
+	unsigned char		locktime_bits;
+
+	unsigned int		need_pll:1;
+
+	/* driver routines */
+
+	void		(*resume_clocks)(void);
+
+	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
+					struct s3c_iotimings *timings);
+
+	void		(*set_iotiming)(struct s3c_cpufreq_config *cfg,
+					struct s3c_iotimings *timings);
+
+	int		(*calc_iotiming)(struct s3c_cpufreq_config *cfg,
+					 struct s3c_iotimings *timings);
+
+	int		(*calc_freqtable)(struct s3c_cpufreq_config *cfg,
+					  struct cpufreq_frequency_table *t,
+					  size_t table_size);
+
+	void		(*debug_io_show)(struct seq_file *seq,
+					 struct s3c_cpufreq_config *cfg,
+					 union s3c_iobank *iob);
+
+	void		(*set_refresh)(struct s3c_cpufreq_config *cfg);
+	void		(*set_fvco)(struct s3c_cpufreq_config *cfg);
+	void		(*set_divs)(struct s3c_cpufreq_config *cfg);
+	int		(*calc_divs)(struct s3c_cpufreq_config *cfg);
+};
+
+extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
+
+extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
+			       unsigned int plls_no);
+
+/* exports and utilities for debugfs */
+extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
+extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
+#define s3c_cpufreq_debugfs_call(x) x
+#else
+#define s3c_cpufreq_debugfs_call(x) NULL
+#endif
+
+/* Useful utility functions. */
+
+extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
+
+/* S3C2410 and compatible exported functions */
+
+extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
+extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+
+#ifdef CONFIG_S3C2410_IOTIMING
+extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
+				     struct s3c_cpufreq_config *cfg,
+				     union s3c_iobank *iob);
+
+extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+
+extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
+				struct s3c_iotimings *timings);
+
+extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+#else
+#define s3c2410_iotiming_debugfs NULL
+#define s3c2410_iotiming_calc NULL
+#define s3c2410_iotiming_get NULL
+#define s3c2410_iotiming_set NULL
+#endif /* CONFIG_S3C2410_IOTIMING */
+
+/* S3C2412 compatible routines */
+
+#ifdef CONFIG_S3C2412_IOTIMING
+extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
+				     struct s3c_cpufreq_config *cfg,
+				     union s3c_iobank *iob);
+
+extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
+				struct s3c_iotimings *timings);
+
+extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+
+extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+#else
+#define s3c2412_iotiming_debugfs NULL
+#define s3c2412_iotiming_calc NULL
+#define s3c2412_iotiming_get NULL
+#define s3c2412_iotiming_set NULL
+#endif /* CONFIG_S3C2412_IOTIMING */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
+#define s3c_freq_dbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
+#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
+
+static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
+				      int index, size_t table_size,
+				      unsigned int freq)
+{
+	if (index < 0)
+		return index;
+
+	if (table) {
+		if (index >= table_size)
+			return -ENOMEM;
+
+		s3c_freq_dbg("%s: { %d = %u kHz }\n",
+			     __func__, index, freq);
+
+		table[index].index = index;
+		table[index].frequency = freq;
+	}
+
+	return index + 1;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/cpu.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/cpu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,12 @@
 /* linux/arch/arm/plat-samsung/include/plat/cpu.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Header file for S3C24XX CPU support
+ * Header file for Samsung CPU support
  *
  * 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 +18,108 @@
 #ifndef __SAMSUNG_PLAT_CPU_H
 #define __SAMSUNG_PLAT_CPU_H
 
+extern unsigned long samsung_cpu_id;
+
+#define S3C24XX_CPU_ID		0x32400000
+#define S3C24XX_CPU_MASK	0xFFF00000
+
+#define S3C6400_CPU_ID		0x36400000
+#define S3C6410_CPU_ID		0x36410000
+#define S3C64XX_CPU_MASK	0xFFFFF000
+
+#define S5P6440_CPU_ID		0x56440000
+#define S5P6450_CPU_ID		0x36450000
+#define S5P64XX_CPU_MASK	0xFFFFF000
+
+#define S5PC100_CPU_ID		0x43100000
+#define S5PC100_CPU_MASK	0xFFFFF000
+
+#define S5PV210_CPU_ID		0x43110000
+#define S5PV210_CPU_MASK	0xFFFFF000
+
+#define EXYNOS4210_CPU_ID	0x43210000
+#define EXYNOS4212_CPU_ID	0x43220000
+#define EXYNOS4412_CPU_ID	0xE4412200
+#define EXYNOS4_CPU_MASK	0xFFFE0000
+
+#define IS_SAMSUNG_CPU(name, id, mask)		\
+static inline int is_samsung_##name(void)	\
+{						\
+	return ((samsung_cpu_id & mask) == (id & mask));	\
+}
+
+IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
+IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
+    defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
+    defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \
+    defined(CONFIG_CPU_S3C2443)
+# define soc_is_s3c24xx()	is_samsung_s3c24xx()
+#else
+# define soc_is_s3c24xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c64xx()	(is_samsung_s3c6400() || is_samsung_s3c6410())
+#else
+# define soc_is_s3c64xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6440)
+# define soc_is_s5p6440()	is_samsung_s5p6440()
+#else
+# define soc_is_s5p6440()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6450)
+# define soc_is_s5p6450()	is_samsung_s5p6450()
+#else
+# define soc_is_s5p6450()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PC100)
+# define soc_is_s5pc100()	is_samsung_s5pc100()
+#else
+# define soc_is_s5pc100()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PV210)
+# define soc_is_s5pv210()	is_samsung_s5pv210()
+#else
+# define soc_is_s5pv210()	0
+#endif
+
+#if defined(CONFIG_CPU_EXYNOS4210)
+# define soc_is_exynos4210()	is_samsung_exynos4210()
+#else
+# define soc_is_exynos4210()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4212)
+# define soc_is_exynos4212()	is_samsung_exynos4212()
+#else
+# define soc_is_exynos4212()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4412)
+# define soc_is_exynos4412()	is_samsung_exynos4412()
+#else
+# define soc_is_exynos4412()	0
+#endif
+
+#define EXYNOS4210_REV_0	(0x0)
+#define EXYNOS4210_REV_1_0	(0x10)
+#define EXYNOS4210_REV_1_1	(0x11)
+
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
@@ -55,6 +160,12 @@ extern void s3c64xx_init_io(struct map_d
 extern void s5p_init_io(struct map_desc *mach_desc,
 			int size, void __iomem *cpuid_addr);
 
+extern void s3c24xx_init_cpu(void);
+extern void s3c64xx_init_cpu(void);
+extern void s5p_init_cpu(void __iomem *cpuid_addr);
+
+extern unsigned int samsung_rev(void);
+
 extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/devs.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/devs.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/devs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/devs.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,30 +30,24 @@ extern struct s3c24xx_uart_resources s5p
 extern struct platform_device *s3c24xx_uart_devs[];
 extern struct platform_device *s3c24xx_uart_src[];
 
-extern struct platform_device s3c_device_timer[];
-
+extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c64xx_device_iis0;
 extern struct platform_device s3c64xx_device_iis1;
 extern struct platform_device s3c64xx_device_iisv4;
-
-extern struct platform_device s3c64xx_device_spi0;
-extern struct platform_device s3c64xx_device_spi1;
-
-extern struct platform_device samsung_asoc_dma;
-extern struct platform_device samsung_asoc_idma;
-
+extern struct platform_device s3c64xx_device_onenand1;
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
+extern struct platform_device s3c64xx_device_spi0;
+extern struct platform_device s3c64xx_device_spi1;
 
-extern struct platform_device s3c64xx_device_ac97;
-
-extern struct platform_device s3c_device_ts;
-
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_cfcon;
 extern struct platform_device s3c_device_fb;
-extern struct platform_device s5p_device_fimd0;
-extern struct platform_device s3c_device_ohci;
-extern struct platform_device s3c_device_lcd;
-extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_hwmon;
+extern struct platform_device s3c_device_hsmmc0;
+extern struct platform_device s3c_device_hsmmc1;
+extern struct platform_device s3c_device_hsmmc2;
+extern struct platform_device s3c_device_hsmmc3;
 extern struct platform_device s3c_device_i2c0;
 extern struct platform_device s3c_device_i2c1;
 extern struct platform_device s3c_device_i2c2;
@@ -62,93 +56,90 @@ extern struct platform_device s3c_device
 extern struct platform_device s3c_device_i2c5;
 extern struct platform_device s3c_device_i2c6;
 extern struct platform_device s3c_device_i2c7;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_nand;
+extern struct platform_device s3c_device_ohci;
+extern struct platform_device s3c_device_onenand;
 extern struct platform_device s3c_device_rtc;
-extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
-extern struct platform_device s3c_device_iis;
-extern struct platform_device s3c_device_hwmon;
-extern struct platform_device s3c_device_hsmmc0;
-extern struct platform_device s3c_device_hsmmc1;
-extern struct platform_device s3c_device_hsmmc2;
-extern struct platform_device s3c_device_hsmmc3;
-extern struct platform_device s3c_device_cfcon;
-
 extern struct platform_device s3c_device_spi0;
 extern struct platform_device s3c_device_spi1;
-
-extern struct platform_device s5pc100_device_spi0;
-extern struct platform_device s5pc100_device_spi1;
-extern struct platform_device s5pc100_device_spi2;
-extern struct platform_device s5pv210_device_spi0;
-extern struct platform_device s5pv210_device_spi1;
-extern struct platform_device s5p64x0_device_spi0;
-extern struct platform_device s5p64x0_device_spi1;
-
-extern struct platform_device s3c_device_hwmon;
-
-extern struct platform_device s3c_device_nand;
-extern struct platform_device s3c_device_onenand;
-extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5p_device_onenand;
-
+extern struct platform_device s3c_device_ts;
+extern struct platform_device s3c_device_timer[];
 extern struct platform_device s3c_device_usbgadget;
-extern struct platform_device s3c_device_usb_hsudc;
 extern struct platform_device s3c_device_usb_hsotg;
+extern struct platform_device s3c_device_usb_hsudc;
+extern struct platform_device s3c_device_wdt;
 
-extern struct platform_device s5pv210_device_ac97;
-extern struct platform_device s5pv210_device_pcm0;
-extern struct platform_device s5pv210_device_pcm1;
-extern struct platform_device s5pv210_device_pcm2;
-extern struct platform_device s5pv210_device_iis0;
-extern struct platform_device s5pv210_device_iis1;
-extern struct platform_device s5pv210_device_iis2;
-extern struct platform_device s5pv210_device_spdif;
-
-extern struct platform_device exynos4_device_ac97;
-extern struct platform_device exynos4_device_pcm0;
-extern struct platform_device exynos4_device_pcm1;
-extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_i2s0;
-extern struct platform_device exynos4_device_i2s1;
-extern struct platform_device exynos4_device_i2s2;
-extern struct platform_device exynos4_device_spdif;
-extern struct platform_device exynos4_device_pd[];
-extern struct platform_device exynos4_device_ahci;
-extern struct platform_device exynos4_device_dwmci;
+extern struct platform_device s5p_device_ehci;
+extern struct platform_device s5p_device_fimc0;
+extern struct platform_device s5p_device_fimc1;
+extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_fimc3;
+extern struct platform_device s5p_device_fimc_md;
+extern struct platform_device s5p_device_fimd0;
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_i2c_hdmiphy;
+extern struct platform_device s5p_device_mfc;
+extern struct platform_device s5p_device_mfc_l;
+extern struct platform_device s5p_device_mfc_r;
+extern struct platform_device s5p_device_mipi_csis0;
+extern struct platform_device s5p_device_mipi_csis1;
+extern struct platform_device s5p_device_mixer;
+extern struct platform_device s5p_device_onenand;
+extern struct platform_device s5p_device_sdo;
 
-extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
+extern struct platform_device s5p6440_device_pcm;
 
 extern struct platform_device s5p6450_device_iis0;
 extern struct platform_device s5p6450_device_iis1;
 extern struct platform_device s5p6450_device_iis2;
 extern struct platform_device s5p6450_device_pcm0;
 
+extern struct platform_device s5p64x0_device_spi0;
+extern struct platform_device s5p64x0_device_spi1;
+
 extern struct platform_device s5pc100_device_ac97;
-extern struct platform_device s5pc100_device_pcm0;
-extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_iis0;
 extern struct platform_device s5pc100_device_iis1;
 extern struct platform_device s5pc100_device_iis2;
+extern struct platform_device s5pc100_device_pcm0;
+extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_spdif;
+extern struct platform_device s5pc100_device_spi0;
+extern struct platform_device s5pc100_device_spi1;
+extern struct platform_device s5pc100_device_spi2;
 
-extern struct platform_device samsung_device_keypad;
-
-extern struct platform_device s5p_device_fimc0;
-extern struct platform_device s5p_device_fimc1;
-extern struct platform_device s5p_device_fimc2;
-extern struct platform_device s5p_device_fimc3;
-
-extern struct platform_device s5p_device_mfc;
-extern struct platform_device s5p_device_mfc_l;
-extern struct platform_device s5p_device_mfc_r;
-extern struct platform_device s5p_device_mipi_csis0;
-extern struct platform_device s5p_device_mipi_csis1;
-
-extern struct platform_device s5p_device_ehci;
+extern struct platform_device s5pv210_device_ac97;
+extern struct platform_device s5pv210_device_iis0;
+extern struct platform_device s5pv210_device_iis1;
+extern struct platform_device s5pv210_device_iis2;
+extern struct platform_device s5pv210_device_pcm0;
+extern struct platform_device s5pv210_device_pcm1;
+extern struct platform_device s5pv210_device_pcm2;
+extern struct platform_device s5pv210_device_spdif;
+extern struct platform_device s5pv210_device_spi0;
+extern struct platform_device s5pv210_device_spi1;
 
+extern struct platform_device exynos4_device_ac97;
+extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
+extern struct platform_device exynos4_device_i2s0;
+extern struct platform_device exynos4_device_i2s1;
+extern struct platform_device exynos4_device_i2s2;
+extern struct platform_device exynos4_device_pcm0;
+extern struct platform_device exynos4_device_pcm1;
+extern struct platform_device exynos4_device_pcm2;
+extern struct platform_device exynos4_device_pd[];
+extern struct platform_device exynos4_device_spdif;
 extern struct platform_device exynos4_device_sysmmu;
 
+extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
+extern struct platform_device samsung_device_keypad;
+
 /* s3c2440 specific devices */
 
 #ifdef CONFIG_CPU_S3C2440
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,17 +10,14 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
 	S3C2410_RES_OK,
 	S3C2410_RES_ERR,
 	S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
@@ -112,7 +109,7 @@ extern int s3c2410_dma_config(enum dma_c
 */
 
 extern int s3c2410_dma_devconfig(enum dma_ch channel,
-		enum s3c2410_dmasrc source, unsigned long devaddr);
+		enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
@@ -126,3 +123,4 @@ extern int s3c2410_dma_set_opfn(enum dma
 extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-ops.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-ops.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-ops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-ops.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * 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 __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	dma_addr_t buf;
+	unsigned long period;
+	unsigned long len;
+	void (*fp)(void *data);
+	void *fp_param;
+};
+
+struct samsung_dma_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	enum dma_slave_buswidth width;
+	dma_addr_t fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+	int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+	int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+	int (*trigger)(unsigned ch);
+	int (*started)(unsigned ch);
+	int (*flush)(unsigned ch);
+	int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+	if (samsung_dma_is_dmadev())
+		return samsung_dmadev_get_ops();
+	else
+		return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-pl330.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-pl330.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-pl330.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-pl330.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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 __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
+
+/*
+ * PL330 can assign any channel to communicate with
+ * any of the peripherals attched to the DMAC.
+ * For the sake of consistency across client drivers,
+ * We keep the channel names unchanged and only add
+ * missing peripherals are added.
+ * Order is not important since DMA PL330 API driver
+ * use these just as IDs.
+ */
+enum dma_ch {
+	DMACH_UART0_RX,
+	DMACH_UART0_TX,
+	DMACH_UART1_RX,
+	DMACH_UART1_TX,
+	DMACH_UART2_RX,
+	DMACH_UART2_TX,
+	DMACH_UART3_RX,
+	DMACH_UART3_TX,
+	DMACH_UART4_RX,
+	DMACH_UART4_TX,
+	DMACH_UART5_RX,
+	DMACH_UART5_TX,
+	DMACH_USI_RX,
+	DMACH_USI_TX,
+	DMACH_IRDA,
+	DMACH_I2S0_RX,
+	DMACH_I2S0_TX,
+	DMACH_I2S0S_TX,
+	DMACH_I2S1_RX,
+	DMACH_I2S1_TX,
+	DMACH_I2S2_RX,
+	DMACH_I2S2_TX,
+	DMACH_SPI0_RX,
+	DMACH_SPI0_TX,
+	DMACH_SPI1_RX,
+	DMACH_SPI1_TX,
+	DMACH_SPI2_RX,
+	DMACH_SPI2_TX,
+	DMACH_AC97_MICIN,
+	DMACH_AC97_PCMIN,
+	DMACH_AC97_PCMOUT,
+	DMACH_EXTERNAL,
+	DMACH_PWM,
+	DMACH_SPDIF,
+	DMACH_HSI_RX,
+	DMACH_HSI_TX,
+	DMACH_PCM0_TX,
+	DMACH_PCM0_RX,
+	DMACH_PCM1_TX,
+	DMACH_PCM1_RX,
+	DMACH_PCM2_TX,
+	DMACH_PCM2_RX,
+	DMACH_MSM_REQ3,
+	DMACH_MSM_REQ2,
+	DMACH_MSM_REQ1,
+	DMACH_MSM_REQ0,
+	DMACH_SLIMBUS0_RX,
+	DMACH_SLIMBUS0_TX,
+	DMACH_SLIMBUS0AUX_RX,
+	DMACH_SLIMBUS0AUX_TX,
+	DMACH_SLIMBUS1_RX,
+	DMACH_SLIMBUS1_TX,
+	DMACH_SLIMBUS2_RX,
+	DMACH_SLIMBUS2_TX,
+	DMACH_SLIMBUS3_RX,
+	DMACH_SLIMBUS3_TX,
+	DMACH_SLIMBUS4_RX,
+	DMACH_SLIMBUS4_TX,
+	DMACH_SLIMBUS5_RX,
+	DMACH_SLIMBUS5_TX,
+	/* END Marker, also used to denote a reserved channel */
+	DMACH_MAX,
+};
+
+struct s3c2410_dma_client {
+	char	*name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+	return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return true;
+}
+
+#include <plat/dma-ops.h>
+
+#endif	/* __DMA_PL330_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,11 +18,6 @@ extern struct s3c2410_dma_chan s3c2410_c
 #define DMA_CH_VALID		(1<<31)
 #define DMA_CH_NEVER		(1<<30)
 
-struct s3c24xx_dma_addr {
-	unsigned long		from;
-	unsigned long		to;
-};
-
 /* struct s3c24xx_dma_map
  *
  * this holds the mapping information for the channel selected
@@ -31,7 +26,6 @@ struct s3c24xx_dma_addr {
 
 struct s3c24xx_dma_map {
 	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
 
 	unsigned long		 channels[S3C_DMA_CHANNELS];
 	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
@@ -47,7 +41,7 @@ struct s3c24xx_dma_selection {
 
 	void	(*direction)(struct s3c2410_dma_chan *chan,
 			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
+			     enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/ehci.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/ehci.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/ehci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/ehci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_SAMSUNG_EHCI_H
+#define __PLAT_SAMSUNG_EHCI_H __FILE__
+
+struct s5p_ehci_platdata {
+	int (*phy_init)(struct platform_device *pdev, int type);
+	int (*phy_exit)(struct platform_device *pdev, int type);
+};
+
+extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
+
+#endif /* __PLAT_SAMSUNG_EHCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/exynos4.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/exynos4.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/exynos4.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/exynos4.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/* linux/arch/arm/plat-samsung/include/plat/exynos4.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for exynos4 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for EXYNOS4 related SoCs */
+
+extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void exynos4_register_clocks(void);
+extern void exynos4210_register_clocks(void);
+extern void exynos4212_register_clocks(void);
+extern void exynos4_setup_clocks(void);
+
+#ifdef CONFIG_ARCH_EXYNOS
+extern  int exynos_init(void);
+extern void exynos4_init_irq(void);
+extern void exynos4_map_io(void);
+extern void exynos4_init_clocks(int xtal);
+extern struct sys_timer exynos4_timer;
+
+#define exynos4_init_uarts exynos4_common_init_uarts
+
+#else
+#define exynos4_init_clocks NULL
+#define exynos4_init_uarts NULL
+#define exynos4_map_io NULL
+#define exynos_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fb.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fb.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -109,4 +109,11 @@ extern void s5pv210_fb_gpio_setup_24bpp(
  */
 extern void exynos4_fimd0_gpio_setup_24bpp(void);
 
+/**
+ * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5p64x0_fb_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fb-s3c2410.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fb-s3c2410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fb-s3c2410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/* arch/arm/plat-samsung/include/plat/fb-s3c2410.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_FB_S3C2410_H
+#define __ASM_PLAT_FB_S3C2410_H __FILE__
+
+struct s3c2410fb_hw {
+	unsigned long	lcdcon1;
+	unsigned long	lcdcon2;
+	unsigned long	lcdcon3;
+	unsigned long	lcdcon4;
+	unsigned long	lcdcon5;
+};
+
+/* LCD description */
+struct s3c2410fb_display {
+	/* LCD type */
+	unsigned type;
+
+	/* Screen size */
+	unsigned short width;
+	unsigned short height;
+
+	/* Screen info */
+	unsigned short xres;
+	unsigned short yres;
+	unsigned short bpp;
+
+	unsigned pixclock;		/* pixclock in picoseconds */
+	unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short upper_margin;	/* value in lines (TFT) or 0 (STN) */
+	unsigned short lower_margin;	/* value in lines (TFT) or 0 (STN) */
+	unsigned short vsync_len;	/* value in lines (TFT) or 0 (STN) */
+
+	/* lcd configuration registers */
+	unsigned long	lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+
+	struct s3c2410fb_display *displays;	/* attached diplays info */
+	unsigned num_displays;			/* number of defined displays */
+	unsigned default_display;
+
+	/* GPIOs */
+
+	unsigned long	gpcup;
+	unsigned long	gpcup_mask;
+	unsigned long	gpccon;
+	unsigned long	gpccon_mask;
+	unsigned long	gpdup;
+	unsigned long	gpdup_mask;
+	unsigned long	gpdcon;
+	unsigned long	gpdcon_mask;
+
+	/* lpc3600 control register */
+	unsigned long	lpcsel;
+};
+
+extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
+
+#endif /* __ASM_PLAT_FB_S3C2410_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fiq.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fiq.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/fiq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/fiq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+/* linux/arch/arm/plat-samsung/include/plat/fiq.h
+ *
+ * Copyright (c) 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU FIQ support
+ *
+ * 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.
+*/
+
+extern int s3c24xx_set_fiq(unsigned int irq, bool on);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,14 +24,16 @@
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
-typedef unsigned int __bitwise__ s3c_gpio_pull_t;
+#include<linux/types.h>
+
+typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_cfg GPIO configuration
+ * struct samsung_gpio_cfg GPIO configuration
  * @cfg_eint: Configuration setting when used for external interrupt source
  * @get_pull: Read the current pull configuration for the GPIO
  * @set_pull: Set the current pull configuraiton for the GPIO
@@ -44,20 +46,20 @@ struct s3c_gpio_chip;
  * per-bank configuration information that other systems such as the
  * external interrupt code will need.
  *
- * @sa s3c_gpio_cfgpin
+ * @sa samsung_gpio_cfgpin
  * @sa s3c_gpio_getcfg
  * @sa s3c_gpio_setpull
  * @sa s3c_gpio_getpull
  */
-struct s3c_gpio_cfg {
+struct samsung_gpio_cfg {
 	unsigned int	cfg_eint;
 
-	s3c_gpio_pull_t	(*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
-	int		(*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
-				    s3c_gpio_pull_t pull);
+	samsung_gpio_pull_t	(*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
+	int		(*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
+				    samsung_gpio_pull_t pull);
 
-	unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
-	int	 (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
+	unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
+	int	 (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
 			       unsigned config);
 };
 
@@ -69,7 +71,7 @@ struct s3c_gpio_cfg {
 #define S3C_GPIO_OUTPUT	(S3C_GPIO_SPECIAL(1))
 #define S3C_GPIO_SFN(x)	(S3C_GPIO_SPECIAL(x))
 
-#define s3c_gpio_is_cfg_special(_cfg) \
+#define samsung_gpio_is_cfg_special(_cfg) \
 	(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
 
 /**
@@ -128,9 +130,9 @@ extern int s3c_gpio_cfgpin_range(unsigne
  * up or down settings, and it may be dependent on the chip that is being
  * used to whether the particular mode is available.
  */
-#define S3C_GPIO_PULL_NONE	((__force s3c_gpio_pull_t)0x00)
-#define S3C_GPIO_PULL_DOWN	((__force s3c_gpio_pull_t)0x01)
-#define S3C_GPIO_PULL_UP	((__force s3c_gpio_pull_t)0x02)
+#define S3C_GPIO_PULL_NONE	((__force samsung_gpio_pull_t)0x00)
+#define S3C_GPIO_PULL_DOWN	((__force samsung_gpio_pull_t)0x01)
+#define S3C_GPIO_PULL_UP	((__force samsung_gpio_pull_t)0x02)
 
 /**
  * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
@@ -143,7 +145,7 @@ extern int s3c_gpio_cfgpin_range(unsigne
  *
  * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
 */
-extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
+extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
 
 /**
  * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
@@ -151,7 +153,7 @@ extern int s3c_gpio_setpull(unsigned int
  *
  * Read the pull resistor value for the specified pin.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
+extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
 
 /* configure `all` aspects of an gpio */
 
@@ -170,7 +172,7 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(
  * @sa s3c_gpio_cfgpin_range
  */
 extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-				 unsigned int cfg, s3c_gpio_pull_t pull);
+				 unsigned int cfg, samsung_gpio_pull_t pull);
 
 static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
 					   unsigned int cfg)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,11 +1,11 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C Platform - GPIO pin configuration helper definitions
+ * Samsung Platform - GPIO pin configuration helper definitions
  *
  * 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
@@ -24,120 +24,30 @@
  * by disabling interrupts.
 */
 
-static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int config)
+static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
+					 unsigned int off, unsigned int config)
 {
 	return (chip->config->set_config)(chip, off, config);
 }
 
-static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip,
-					  unsigned int off)
+static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
+					      unsigned int off)
 {
 	return (chip->config->get_config)(chip, off);
 }
 
-static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
-				      unsigned int off, s3c_gpio_pull_t pull)
+static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
+					  unsigned int off, samsung_gpio_pull_t pull)
 {
 	return (chip->config->set_pull)(chip, off, pull);
 }
 
-static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
-						  unsigned int off)
+static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
+							  unsigned int off)
 {
 	return chip->config->get_pull(chip, off);
 }
 
-/**
- * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has two bits of configuration per gpio, which have the following
- * functions:
- *	00 = input
- *	01 = output
- *	1x = special function
-*/
-extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				   unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
- * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
- * S3C_GPIO_SPECIAL() macro.
- */
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				     unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has one bit of configuration for the gpio, where setting the bit
- * means the pin is in special function mode and unset means output.
-*/
-extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
- * GPIO configuration value.
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- * @sa s3c_gpio_getcfg_s3c64xx_4bit
- */
-extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-					  unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- *	0000 = Input
- *	0001 = Output
- *	others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of functions for
- * each case.
-*/
-extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-					unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
- * register setting into a value the software can use, such as could be passed
- * to s3c_gpio_setcfg_s3c64xx_4bit().
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- */
-extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-					     unsigned int off);
-
 /* Pull-{up,down} resistor controls.
  *
  * S3C2410,S3C2440 = Pull-UP,
@@ -147,7 +57,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_
  */
 
 /**
- * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -155,11 +65,11 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-up resistor.
  */
-extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+				    unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
  * @chip: The gpio chip that is being configured
  * @off: The offset for the GPIO being configured
  * @param: pull: The pull mode being requested
@@ -167,11 +77,13 @@ extern int s3c_gpio_setpull_1up(struct s
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-down resistor.
  */
-extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-				  unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+				      unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * samsung_gpio_setpull_upown() - Pull configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -183,45 +95,46 @@ extern int s3c_gpio_setpull_1down(struct
  *	01 = Pull-up resistor connected
  *	10 = Pull-down resistor connected
  */
-extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-				   unsigned int off, s3c_gpio_pull_t pull);
-
+extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+				       unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * samsung_gpio_getpull_updown() - Get configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * This helper function reads the state of the pull-{up,down} resistor
+ * for the given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					       unsigned int off);
+extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+						       unsigned int off);
 
 /**
- * s3c_gpio_getpull_1up() - Get configuration for choice of up or none
+ * s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-up resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1up.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1up.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-					    unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+						    unsigned int off);
 
 /**
- * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-down resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1down.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1down.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-					    unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+						      unsigned int off);
 
 /**
- * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * s3c2443_gpio_setpull() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -233,19 +146,18 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_
  *	10 = Pull-down resistor connected
  *	x1 = No pull up resistor
  */
-extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-				    unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
  * @chip: The gpio chip that the GPIO pin belongs to.
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
+extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
 						unsigned int off);
 
 #endif /* __PLAT_GPIO_CFG_HELPERS_H */
-
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,22 +25,22 @@
  * specific code.
 */
 
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_pm - power management (suspend/resume) information
+ * struct samsung_gpio_pm - power management (suspend/resume) information
  * @save: Routine to save the state of the GPIO block
  * @resume: Routine to resume the GPIO block.
  */
-struct s3c_gpio_pm {
-	void (*save)(struct s3c_gpio_chip *chip);
-	void (*resume)(struct s3c_gpio_chip *chip);
+struct samsung_gpio_pm {
+	void (*save)(struct samsung_gpio_chip *chip);
+	void (*resume)(struct samsung_gpio_chip *chip);
 };
 
-struct s3c_gpio_cfg;
+struct samsung_gpio_cfg;
 
 /**
- * struct s3c_gpio_chip - wrapper for specific implementation of gpio
+ * struct samsung_gpio_chip - wrapper for specific implementation of gpio
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @group: The group register number for gpio interrupt support.
@@ -60,10 +60,10 @@ struct s3c_gpio_cfg;
  * CPU cores trying to get one lock for different GPIO banks, where each
  * bank of GPIO has its own register space and configuration registers.
  */
-struct s3c_gpio_chip {
+struct samsung_gpio_chip {
 	struct gpio_chip	chip;
-	struct s3c_gpio_cfg	*config;
-	struct s3c_gpio_pm	*pm;
+	struct samsung_gpio_cfg	*config;
+	struct samsung_gpio_pm	*pm;
 	void __iomem		*base;
 	int			irq_base;
 	int			group;
@@ -73,58 +73,11 @@ struct s3c_gpio_chip {
 #endif
 };
 
-static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
+static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
 {
-	return container_of(gpc, struct s3c_gpio_chip, chip);
+	return container_of(gpc, struct samsung_gpio_chip, chip);
 }
 
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
-/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
- * for use with the configuration calls, and other parts of the s3c gpiolib
- * support code.
- *
- * Not all s3c support code will need this, as some configurations of cpu
- * may only support one or two different configuration options and have an
- * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
- * the machine support file should provide its own s3c_gpiolib_getchip()
- * and any other necessary functions.
- */
-
-/**
- * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- * 0000 = Input
- * 0001 = Output
- * others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of function
- * (samsung_gpiolib_add_4bit2_chips)for each case.
- */
-extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips);
-extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-					    int nr_chips);
-extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips);
-
-extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
-extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
-
-
 /**
  * samsung_gpiolib_to_irq - convert gpio pin to irq number
  * @chip: The gpio chip that the pin belongs to.
@@ -136,36 +89,36 @@ extern void samsung_gpiolib_add_4bit2(st
 extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
 
 /* exported for core SoC support to change */
-extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
+extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
 
 #ifdef CONFIG_S3C_GPIO_TRACK
-extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
 {
 	return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
 }
 #else
-/* machine specific code should provide s3c_gpiolib_getchip */
+/* machine specific code should provide samsung_gpiolib_getchip */
 
 #include <mach/gpio-track.h>
 
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
 #endif
 
 #ifdef CONFIG_PM
-extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
 #define __gpio_pm(x) x
 #else
-#define s3c_gpio_pm_1bit NULL
-#define s3c_gpio_pm_2bit NULL
-#define s3c_gpio_pm_4bit NULL
+#define samsung_gpio_pm_1bit NULL
+#define samsung_gpio_pm_2bit NULL
+#define samsung_gpio_pm_4bit NULL
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
 
 /* locking wrappers to deal with multiple access to the same gpio bank */
-#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
-#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
+#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-fns.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-fns.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/gpio-fns.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/gpio-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * 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 __MACH_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
+*/
+
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
+	s3c_gpio_cfgpin(pin, cfg);
+}
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *	< 0 = no interrupt for this pin
+ *	>=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+				  unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ *      0 => enable the pull-up
+ *
+ * eg;
+ *
+ *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/iic.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/iic.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/iic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/iic.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct
 extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
+extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
 
 /* defined by architecture to configure gpio */
 extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/irq.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/irq.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/* linux/arch/arm/plat-samsung/include/plat/irq.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU IRQ support
+ *
+ * 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/io.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+/* these are exported for arch/arm/mach-* usage */
+extern struct irq_chip s3c_irq_level_chip;
+extern struct irq_chip s3c_irq_chip;
+
+static inline void s3c_irqsub_mask(unsigned int irqno,
+				   unsigned int parentbit,
+				   int subcheck)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
+
+	/* check to see if we need to mask the parent IRQ */
+
+	if ((submask  & subcheck) == subcheck)
+		__raw_writel(mask | parentbit, S3C2410_INTMSK);
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+
+}
+
+static inline void s3c_irqsub_unmask(unsigned int irqno,
+				     unsigned int parentbit)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
+	mask &= ~parentbit;
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+
+static inline void s3c_irqsub_maskack(unsigned int irqno,
+				      unsigned int parentmask,
+				      unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	s3c_irqsub_mask(irqno, parentmask, group);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+static inline void s3c_irqsub_ack(unsigned int irqno,
+				  unsigned int parentmask,
+				  unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
+extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/irqs.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/irqs.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,80 @@
+/* linux/arch/arm/plat-samsung/include/plat/irqs.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P Common IRQ support
+ *
+ * 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 __PLAT_SAMSUNG_IRQS_H
+#define __PLAT_SAMSUNG_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S5P_IRQ_OFFSET		(32)
+
+#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
+
+#define S5P_VIC0_BASE		S5P_IRQ(0)
+#define S5P_VIC1_BASE		S5P_IRQ(32)
+#define S5P_VIC2_BASE		S5P_IRQ(64)
+#define S5P_VIC3_BASE		S5P_IRQ(96)
+
+#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
+
+#define IRQ_VIC0_BASE		S5P_VIC0_BASE
+#define IRQ_VIC1_BASE		S5P_VIC1_BASE
+#define IRQ_VIC2_BASE		S5P_VIC2_BASE
+
+/* VIC based IRQs */
+
+#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
+#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
+#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
+#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
+
+#define S5P_TIMER_IRQ(x)	(11 + (x))
+
+#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
+#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
+#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
+#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
+#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
+
+#define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
+					: ((x) - 16 + S5P_EINT_BASE2))
+
+#define EINT_OFFSET(irq)	((irq) < S5P_EINT_BASE2 ? \
+						((irq) - S5P_EINT_BASE1) : \
+						((irq) + 16 - S5P_EINT_BASE2))
+
+#define IRQ_EINT_BIT(x)		EINT_OFFSET(x)
+
+/* Typically only a few gpio chips require gpio interrupt support.
+   To avoid memory waste irq descriptors are allocated only for
+   S5P_GPIOINT_GROUP_COUNT chips, each with total number of
+   S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
+   to any gpio chip with the s5p_register_gpio_interrupt() function */
+#define S5P_GPIOINT_GROUP_COUNT 4
+#define S5P_GPIOINT_GROUP_SIZE	8
+#define S5P_GPIOINT_COUNT	(S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
+
+/* IRQ types common for all s5p platforms */
+#define S5P_IRQ_TYPE_LEVEL_LOW		(0x00)
+#define S5P_IRQ_TYPE_LEVEL_HIGH		(0x01)
+#define S5P_IRQ_TYPE_EDGE_FALLING	(0x02)
+#define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
+#define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
+
+#endif /* __PLAT_SAMSUNG_IRQS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/map-s3c.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/map-s3c.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/map-s3c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/map-s3c.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S3C_H
+#define __ASM_PLAT_MAP_S3C_H __FILE__
+
+#define S3C24XX_VA_IRQ		S3C_VA_IRQ
+#define S3C24XX_VA_MEMCTRL	S3C_VA_MEM
+#define S3C24XX_VA_UART		S3C_VA_UART
+
+#define S3C24XX_VA_TIMER	S3C_VA_TIMER
+#define S3C24XX_VA_CLKPWR	S3C_VA_SYS
+#define S3C24XX_VA_WATCHDOG	S3C_VA_WATCHDOG
+
+#define S3C2412_VA_SSMC		S3C_ADDR_CPU(0x00000000)
+#define S3C2412_VA_EBI		S3C_ADDR_CPU(0x00010000)
+
+#define S3C2410_PA_UART		(0x50000000)
+#define S3C24XX_PA_UART		S3C2410_PA_UART
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+/*
+ * GPIO ports
+ *
+ * the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 mapping. This puts it (currently) at
+ * 0xFA800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
+#define S3C2410_PA_GPIO		(0x56000000)
+#define S3C24XX_PA_GPIO		S3C2410_PA_GPIO
+
+#define S3C24XX_VA_GPIO		((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
+#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
+
+#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
+#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
+
+#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
+
+/*
+ * ISA style IO, for each machine to sort out mappings for,
+ * if it implements it. We reserve two 16M regions for ISA.
+ */
+
+#define S3C2410_ADDR(x)		S3C_ADDR(x)
+
+#define S3C24XX_VA_ISA_WORD	S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE	S3C2410_ADDR(0x03000000)
+
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2	(S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
+#include <plat/map-s5p.h>
+
+#endif /* __ASM_PLAT_MAP_S3C_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/map-s5p.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/map-s5p.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/map-s5p.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/map-s5p.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S5P_H
+#define __ASM_PLAT_MAP_S5P_H __FILE__
+
+#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
+#define S5P_VA_CMU		S3C_ADDR(0x02100000)
+#define S5P_VA_PMU		S3C_ADDR(0x02180000)
+#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
+#define S5P_VA_GPIO1		S5P_VA_GPIO
+#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
+#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
+
+#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
+#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
+#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
+#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
+
+#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
+#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
+
+#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
+#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
+
+#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
+#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
+#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
+#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
+
+#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
+
+#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
+#define VA_VIC0			VA_VIC(0)
+#define VA_VIC1			VA_VIC(1)
+#define VA_VIC2			VA_VIC(2)
+#define VA_VIC3			VA_VIC(3)
+
+#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_VA_UART0		S5P_VA_UART(0)
+#define S5P_VA_UART1		S5P_VA_UART(1)
+#define S5P_VA_UART2		S5P_VA_UART(2)
+#define S5P_VA_UART3		S5P_VA_UART(3)
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+#include <plat/map-s3c.h>
+
+#endif /* __ASM_PLAT_MAP_S5P_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mci.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mci.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+#ifndef _ARCH_MCI_H
+#define _ARCH_MCI_H
+
+/**
+ * struct s3c24xx_mci_pdata - sd/mmc controller platform data
+ * @no_wprotect: Set this to indicate there is no write-protect switch.
+ * @no_detect: Set this if there is no detect switch.
+ * @wprotect_invert: Invert the default sense of the write protect switch.
+ * @detect_invert: Invert the default sense of the write protect switch.
+ * @use_dma: Set to allow the use of DMA.
+ * @gpio_detect: GPIO number for the card detect line.
+ * @gpio_wprotect: GPIO number for the write protect line.
+ * @ocr_avail: The mask of the available power states, non-zero to use.
+ * @set_power: Callback to control the power mode.
+ *
+ * The @gpio_detect is used for card detection when @no_wprotect is unset,
+ * and the default sense is that 0 returned from gpio_get_value() means
+ * that a card is inserted. If @detect_invert is set, then the value from
+ * gpio_get_value() is inverted, which makes 1 mean card inserted.
+ *
+ * The driver will use @gpio_wprotect to signal whether the card is write
+ * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
+ * means the card is read/write, and 1 means read-only. The @wprotect_invert
+ * will invert the value returned from gpio_get_value().
+ *
+ * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
+ * to a non-zero value, otherwise the default of 3.2-3.4V is used.
+ */
+struct s3c24xx_mci_pdata {
+	unsigned int	no_wprotect:1;
+	unsigned int	no_detect:1;
+	unsigned int	wprotect_invert:1;
+	unsigned int	detect_invert:1;	/* set => detect active high */
+	unsigned int	use_dma:1;
+
+	unsigned int	gpio_detect;
+	unsigned int	gpio_wprotect;
+	unsigned long	ocr_avail;
+	void		(*set_power)(unsigned char power_mode,
+				     unsigned short vdd);
+};
+
+/**
+ * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
+ * @pdata: The platform data
+ *
+ * Copy the platform data supplied by @pdata so that this can be marked
+ * __initdata.
+ */
+extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
+
+#endif /* _ARCH_NCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mfc.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mfc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mfc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mfc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ *
+ * 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 __PLAT_SAMSUNG_MFC_H
+#define __PLAT_SAMSUNG_MFC_H __FILE__
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase:	base address for MFC 'right' memory interface
+ * @rsize:	size of the memory reserved for MFC 'right' interface
+ * @lbase:	base address for MFC 'left' memory interface
+ * @lsize:	size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+				phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_SAMSUNG_MFC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mipi_csis.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mipi_csis.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/mipi_csis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/mipi_csis.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series MIPI CSI slave device support
+ *
+ * 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 __PLAT_SAMSUNG_MIPI_CSIS_H_
+#define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
+
+struct platform_device;
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
+ *		   driver or true in case this regulator has no enable function
+ * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ */
+struct s5p_platform_mipi_csis {
+	unsigned long clk_rate;
+	u8 lanes;
+	u8 alignment;
+	u8 hs_settle;
+	bool fixed_phy_vdd;
+	int (*phy_enable)(struct platform_device *pdev, bool on);
+};
+
+/**
+ * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
+ * @pdev: MIPI-CSIS platform device
+ * @on: true to enable D-PHY and deassert its reset
+ *	false to disable D-PHY
+ */
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+
+#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pll6553x.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pll6553x.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pll6553x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pll6553x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/pll6553x.h
- *	partially from arch/arm/mach-s3c64xx/include/mach/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Samsung PLL6553x PLL code
- *
- * 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.
-*/
-
-/* S3C6400 and compatible (S3C2416, etc.) EPLL code */
-
-#define PLL6553X_MDIV_MASK	((1 << (23-16)) - 1)
-#define PLL6553X_PDIV_MASK	((1 << (13-8)) - 1)
-#define PLL6553X_SDIV_MASK	((1 << (2-0)) - 1)
-#define PLL6553X_MDIV_SHIFT	(16)
-#define PLL6553X_PDIV_SHIFT	(8)
-#define PLL6553X_SDIV_SHIFT	(0)
-#define PLL6553X_KDIV_MASK	(0xffff)
-
-static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
-					     u32 pll0, u32 pll1)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
-	pdiv = (pll0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
-	sdiv = (pll0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
-	kdiv = pll1 & PLL6553X_KDIV_MASK;
-
-	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pll.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pll.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pll.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,323 @@
+/* linux/arch/arm/plat-samsung/include/plat/pll.h
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Samsung PLL codes
+ *
+ * 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 <asm/div64.h>
+
+#define S3C24XX_PLL_MDIV_MASK		(0xFF)
+#define S3C24XX_PLL_PDIV_MASK		(0x1F)
+#define S3C24XX_PLL_SDIV_MASK		(0x3)
+#define S3C24XX_PLL_MDIV_SHIFT		(12)
+#define S3C24XX_PLL_PDIV_SHIFT		(4)
+#define S3C24XX_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
+					   unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
+	pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
+	sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
+
+	fvco = (uint64_t)baseclk * (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+#define S3C2416_PLL_MDIV_MASK		(0x3FF)
+#define S3C2416_PLL_PDIV_MASK		(0x3F)
+#define S3C2416_PLL_SDIV_MASK		(0x7)
+#define S3C2416_PLL_MDIV_SHIFT		(14)
+#define S3C2416_PLL_PDIV_SHIFT		(5)
+#define S3C2416_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned int s3c2416_get_pll(unsigned int pllval,
+					   unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
+	pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
+	sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
+
+	fvco = (uint64_t)baseclk * mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned int)fvco;
+}
+
+#define S3C6400_PLL_MDIV_MASK		(0x3FF)
+#define S3C6400_PLL_PDIV_MASK		(0x3F)
+#define S3C6400_PLL_SDIV_MASK		(0x7)
+#define S3C6400_PLL_MDIV_SHIFT		(16)
+#define S3C6400_PLL_PDIV_SHIFT		(8)
+#define S3C6400_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
+					    u32 pllcon)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
+	pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
+	sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL6553X_MDIV_MASK	(0x7F)
+#define PLL6553X_PDIV_MASK	(0x1F)
+#define PLL6553X_SDIV_MASK	(0x3)
+#define PLL6553X_KDIV_MASK	(0xFFFF)
+#define PLL6553X_MDIV_SHIFT	(16)
+#define PLL6553X_PDIV_SHIFT	(8)
+#define PLL6553X_SDIV_SHIFT	(0)
+
+static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
+					     u32 pll_con0, u32 pll_con1)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+	kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+	/*
+	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	tmp = baseclk;
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL35XX_MDIV_MASK	(0x3FF)
+#define PLL35XX_PDIV_MASK	(0x3F)
+#define PLL35XX_SDIV_MASK	(0x7)
+#define PLL35XX_MDIV_SHIFT	(16)
+#define PLL35XX_PDIV_SHIFT	(8)
+#define PLL35XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL36XX_KDIV_MASK	(0xFFFF)
+#define PLL36XX_MDIV_MASK	(0x1FF)
+#define PLL36XX_PDIV_MASK	(0x3F)
+#define PLL36XX_SDIV_MASK	(0x7)
+#define PLL36XX_MDIV_SHIFT	(16)
+#define PLL36XX_PDIV_SHIFT	(8)
+#define PLL36XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL45XX_MDIV_MASK	(0x3FF)
+#define PLL45XX_PDIV_MASK	(0x3F)
+#define PLL45XX_SDIV_MASK	(0x7)
+#define PLL45XX_MDIV_SHIFT	(16)
+#define PLL45XX_PDIV_SHIFT	(8)
+#define PLL45XX_SDIV_SHIFT	(0)
+
+enum pll45xx_type_t {
+	pll_4500,
+	pll_4502,
+	pll_4508
+};
+
+static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
+					    enum pll45xx_type_t pll_type)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+	if (pll_type == pll_4508)
+		sdiv = sdiv - 1;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+/* CON0 bit-fields */
+#define PLL46XX_MDIV_MASK	(0x1FF)
+#define PLL46XX_PDIV_MASK	(0x3F)
+#define PLL46XX_SDIV_MASK	(0x7)
+#define PLL46XX_LOCKED_SHIFT	(29)
+#define PLL46XX_MDIV_SHIFT	(16)
+#define PLL46XX_PDIV_SHIFT	(8)
+#define PLL46XX_SDIV_SHIFT	(0)
+
+/* CON1 bit-fields */
+#define PLL46XX_MRR_MASK	(0x1F)
+#define PLL46XX_MFR_MASK	(0x3F)
+#define PLL46XX_KDIV_MASK	(0xFFFF)
+#define PLL4650C_KDIV_MASK	(0xFFF)
+#define PLL46XX_MRR_SHIFT	(24)
+#define PLL46XX_MFR_SHIFT	(16)
+#define PLL46XX_KDIV_SHIFT	(0)
+
+enum pll46xx_type_t {
+	pll_4600,
+	pll_4650,
+	pll_4650c,
+};
+
+static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1,
+					    enum pll46xx_type_t pll_type)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+	if (pll_type == pll_4650c)
+		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+	else
+		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	if (pll_type == pll_4600) {
+		tmp *= (mdiv << 16) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 16;
+	} else {
+		tmp *= (mdiv << 10) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 10;
+	}
+
+	return result;
+}
+
+#define PLL90XX_MDIV_MASK	(0xFF)
+#define PLL90XX_PDIV_MASK	(0x3F)
+#define PLL90XX_SDIV_MASK	(0x7)
+#define PLL90XX_KDIV_MASK	(0xffff)
+#define PLL90XX_LOCKED_SHIFT	(29)
+#define PLL90XX_MDIV_SHIFT	(16)
+#define PLL90XX_PDIV_SHIFT	(8)
+#define PLL90XX_SDIV_SHIFT	(0)
+#define PLL90XX_KDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
+					    u32 pll_con, u32 pll_conk)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
+	kdiv = pll_conk & PLL90XX_KDIV_MASK;
+
+	/*
+	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	tmp = baseclk;
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL65XX_MDIV_MASK	(0x3FF)
+#define PLL65XX_PDIV_MASK	(0x3F)
+#define PLL65XX_SDIV_MASK	(0x7)
+#define PLL65XX_MDIV_SHIFT	(16)
+#define PLL65XX_PDIV_SHIFT	(8)
+#define PLL65XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pm.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pm.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -165,20 +165,20 @@ extern void s3c_pm_check_store(void);
 extern void s3c_pm_configure_extint(void);
 
 /**
- * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
  *
  * Restore the state of the GPIO pins after sleep, which may involve ensuring
  * that we do not glitch the state of the pins from that the bootloader's
  * resume code has done.
 */
-extern void s3c_pm_restore_gpios(void);
+extern void samsung_pm_restore_gpios(void);
 
 /**
- * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ * samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
  *
- * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
  */
-extern void s3c_pm_save_gpios(void);
+extern void samsung_pm_save_gpios(void);
 
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pwm-clock.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pwm-clock.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/pwm-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * SAMSUNG - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_PWM_CLOCK_H
+#define __ASM_PLAT_PWM_CLOCK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	if (soc_is_s3c24xx())
+		return tcfg == S3C2410_TCFG1_MUX_TCLK;
+	else if (soc_is_s3c64xx() || soc_is_s5pc100())
+		return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
+	else if (soc_is_s5p6440() || soc_is_s5p6450())
+		return 0;
+	else
+		return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	if (soc_is_s3c24xx())
+		return 1 << (tcfg1 + 1);
+	else
+		return 1 << tcfg1;
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	if (soc_is_s3c24xx())
+		return 0;
+	else
+		return 1;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	if (soc_is_s3c24xx())
+		return ilog2(div) - 1;
+	else
+		return ilog2(div);
+}
+#endif /* __ASM_PLAT_PWM_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-adc.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-adc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-adc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-adc.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #define S3C2410_ADCDAT0	   S3C2410_ADCREG(0x0C)
 #define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
 #define S3C64XX_ADCUPDN		S3C2410_ADCREG(0x14)
+#define S3C2443_ADCMUX		S3C2410_ADCREG(0x18)
 #define S3C64XX_ADCCLRINT	S3C2410_ADCREG(0x18)
 #define S5P_ADCMUX		S3C2410_ADCREG(0x1C)
 #define S3C64XX_ADCCLRINTPNDNUP	S3C2410_ADCREG(0x20)
@@ -33,6 +34,7 @@
 #define S3C2410_ADCCON_PRSCVLMASK	(0xFF<<6)
 #define S3C2410_ADCCON_SELMUX(x)	(((x)&0x7)<<3)
 #define S3C2410_ADCCON_MUXMASK		(0x7<<3)
+#define S3C2416_ADCCON_RESSEL		(1 << 3)
 #define S3C2410_ADCCON_STDBM		(1<<2)
 #define S3C2410_ADCCON_READ_START	(1<<1)
 #define S3C2410_ADCCON_ENABLE_START	(1<<0)
@@ -40,6 +42,7 @@
 
 
 /* ADCTSC Register Bits */
+#define S3C2443_ADCTSC_UD_SEN		(1 << 8)
 #define S3C2410_ADCTSC_YM_SEN		(1<<7)
 #define S3C2410_ADCTSC_YP_SEN		(1<<6)
 #define S3C2410_ADCTSC_XM_SEN		(1<<5)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-dma.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-dma.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-dma.h
+ *
+ * Copyright (C) 2003-2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_DMA_H
+#define __ASM_PLAT_REGS_DMA_H __FILE__
+
+#define S3C2410_DMA_DISRC		(0x00)
+#define S3C2410_DMA_DISRCC		(0x04)
+#define S3C2410_DMA_DIDST		(0x08)
+#define S3C2410_DMA_DIDSTC		(0x0C)
+#define S3C2410_DMA_DCON		(0x10)
+#define S3C2410_DMA_DSTAT		(0x14)
+#define S3C2410_DMA_DCSRC		(0x18)
+#define S3C2410_DMA_DCDST		(0x1C)
+#define S3C2410_DMA_DMASKTRIG		(0x20)
+#define S3C2412_DMA_DMAREQSEL		(0x24)
+#define S3C2443_DMA_DMAREQSEL		(0x24)
+
+#define S3C2410_DISRCC_INC		(1 << 0)
+#define S3C2410_DISRCC_APB		(1 << 1)
+
+#define S3C2410_DMASKTRIG_STOP		(1 << 2)
+#define S3C2410_DMASKTRIG_ON		(1 << 1)
+#define S3C2410_DMASKTRIG_SWTRIG	(1 << 0)
+
+#define S3C2410_DCON_DEMAND		(0 << 31)
+#define S3C2410_DCON_HANDSHAKE		(1 << 31)
+#define S3C2410_DCON_SYNC_PCLK		(0 << 30)
+#define S3C2410_DCON_SYNC_HCLK		(1 << 30)
+
+#define S3C2410_DCON_INTREQ		(1 << 29)
+
+#define S3C2410_DCON_CH0_XDREQ0		(0 << 24)
+#define S3C2410_DCON_CH0_UART0		(1 << 24)
+#define S3C2410_DCON_CH0_SDI		(2 << 24)
+#define S3C2410_DCON_CH0_TIMER		(3 << 24)
+#define S3C2410_DCON_CH0_USBEP1		(4 << 24)
+
+#define S3C2410_DCON_CH1_XDREQ1		(0 << 24)
+#define S3C2410_DCON_CH1_UART1		(1 << 24)
+#define S3C2410_DCON_CH1_I2SSDI		(2 << 24)
+#define S3C2410_DCON_CH1_SPI		(3 << 24)
+#define S3C2410_DCON_CH1_USBEP2		(4 << 24)
+
+#define S3C2410_DCON_CH2_I2SSDO		(0 << 24)
+#define S3C2410_DCON_CH2_I2SSDI		(1 << 24)
+#define S3C2410_DCON_CH2_SDI		(2 << 24)
+#define S3C2410_DCON_CH2_TIMER		(3 << 24)
+#define S3C2410_DCON_CH2_USBEP3		(4 << 24)
+
+#define S3C2410_DCON_CH3_UART2		(0 << 24)
+#define S3C2410_DCON_CH3_SDI		(1 << 24)
+#define S3C2410_DCON_CH3_SPI		(2 << 24)
+#define S3C2410_DCON_CH3_TIMER		(3 << 24)
+#define S3C2410_DCON_CH3_USBEP4		(4 << 24)
+
+#define S3C2410_DCON_SRCSHIFT		(24)
+#define S3C2410_DCON_SRCMASK		(7 << 24)
+
+#define S3C2410_DCON_BYTE		(0 << 20)
+#define S3C2410_DCON_HALFWORD		(1 << 20)
+#define S3C2410_DCON_WORD		(2 << 20)
+
+#define S3C2410_DCON_AUTORELOAD		(0 << 22)
+#define S3C2410_DCON_NORELOAD		(1 << 22)
+#define S3C2410_DCON_HWTRIG		(1 << 23)
+
+#ifdef CONFIG_CPU_S3C2440
+
+#define S3C2440_DIDSTC_CHKINT		(1 << 2)
+
+#define S3C2440_DCON_CH0_I2SSDO		(5 << 24)
+#define S3C2440_DCON_CH0_PCMIN		(6 << 24)
+
+#define S3C2440_DCON_CH1_PCMOUT		(5 << 24)
+#define S3C2440_DCON_CH1_SDI		(6 << 24)
+
+#define S3C2440_DCON_CH2_PCMIN		(5 << 24)
+#define S3C2440_DCON_CH2_MICIN		(6 << 24)
+
+#define S3C2440_DCON_CH3_MICIN		(5 << 24)
+#define S3C2440_DCON_CH3_PCMOUT		(6 << 24)
+#endif /* CONFIG_CPU_S3C2440 */
+
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x)	((x) << 1)
+
+#define S3C2412_DMAREQSEL_HW		(1)
+
+#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
+#endif /* CONFIG_CPU_S3C2412 */
+
+#ifdef CONFIG_CPU_S3C2443
+
+#define S3C2443_DMAREQSEL_SRC(x)	((x) << 1)
+
+#define S3C2443_DMAREQSEL_HW		(1)
+
+#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN		S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
+#endif /* CONFIG_CPU_S3C2443 */
+
+#endif /* __ASM_PLAT_REGS_DMA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-iis.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-iis.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-iis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-iis.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,70 @@
+/* arch/arm/plat-samsung/include/plat/regs-iis.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 IIS register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_IIS_H
+#define __ASM_ARCH_REGS_IIS_H
+
+#define S3C2410_IISCON			(0x00)
+
+#define S3C2410_IISCON_LRINDEX		(1 << 8)
+#define S3C2410_IISCON_TXFIFORDY	(1 << 7)
+#define S3C2410_IISCON_RXFIFORDY	(1 << 6)
+#define S3C2410_IISCON_TXDMAEN		(1 << 5)
+#define S3C2410_IISCON_RXDMAEN		(1 << 4)
+#define S3C2410_IISCON_TXIDLE		(1 << 3)
+#define S3C2410_IISCON_RXIDLE		(1 << 2)
+#define S3C2410_IISCON_PSCEN		(1 << 1)
+#define S3C2410_IISCON_IISEN		(1 << 0)
+
+#define S3C2410_IISMOD			(0x04)
+
+#define S3C2440_IISMOD_MPLL		(1 << 9)
+#define S3C2410_IISMOD_SLAVE		(1 << 8)
+#define S3C2410_IISMOD_NOXFER		(0 << 6)
+#define S3C2410_IISMOD_RXMODE		(1 << 6)
+#define S3C2410_IISMOD_TXMODE		(2 << 6)
+#define S3C2410_IISMOD_TXRXMODE		(3 << 6)
+#define S3C2410_IISMOD_LR_LLOW		(0 << 5)
+#define S3C2410_IISMOD_LR_RLOW		(1 << 5)
+#define S3C2410_IISMOD_IIS		(0 << 4)
+#define S3C2410_IISMOD_MSB		(1 << 4)
+#define S3C2410_IISMOD_8BIT		(0 << 3)
+#define S3C2410_IISMOD_16BIT		(1 << 3)
+#define S3C2410_IISMOD_BITMASK		(1 << 3)
+#define S3C2410_IISMOD_256FS		(0 << 2)
+#define S3C2410_IISMOD_384FS		(1 << 2)
+#define S3C2410_IISMOD_16FS		(0 << 0)
+#define S3C2410_IISMOD_32FS		(1 << 0)
+#define S3C2410_IISMOD_48FS		(2 << 0)
+#define S3C2410_IISMOD_FS_MASK		(3 << 0)
+
+#define S3C2410_IISPSR			(0x08)
+
+#define S3C2410_IISPSR_INTMASK		(31 << 5)
+#define S3C2410_IISPSR_INTSHIFT		(5)
+#define S3C2410_IISPSR_EXTMASK		(31 << 0)
+#define S3C2410_IISPSR_EXTSHFIT		(0)
+
+#define S3C2410_IISFCON			(0x0c)
+
+#define S3C2410_IISFCON_TXDMA		(1 << 15)
+#define S3C2410_IISFCON_RXDMA		(1 << 14)
+#define S3C2410_IISFCON_TXENABLE	(1 << 13)
+#define S3C2410_IISFCON_RXENABLE	(1 << 12)
+#define S3C2410_IISFCON_TXMASK		(0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT		(6)
+#define S3C2410_IISFCON_RXMASK		(0x3f)
+#define S3C2410_IISFCON_RXSHIFT		(0)
+
+#define S3C2410_IISFIFO			(0x10)
+
+#endif /* __ASM_ARCH_REGS_IIS_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-serial.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-serial.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -186,6 +186,11 @@
 #define S3C64XX_UINTSP		0x34
 #define S3C64XX_UINTM		0x38
 
+#define S3C64XX_UINTM_RXD	(0)
+#define S3C64XX_UINTM_TXD	(2)
+#define S3C64XX_UINTM_RXD_MSK	(1 << S3C64XX_UINTM_RXD)
+#define S3C64XX_UINTM_TXD_MSK	(1 << S3C64XX_UINTM_TXD)
+
 /* Following are specific to S5PV210 */
 #define S5PV210_UCON_CLKMASK	(1<<10)
 #define S5PV210_UCON_PCLK	(0<<10)
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-spi.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-spi.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-spi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-spi.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/* arch/arm/plat-samsung/include/plat/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * 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.
+ *
+ * S3C2410 SPI register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+#define S3C2410_SPI1		(0x20)
+#define S3C2412_SPI1		(0x100)
+
+#define S3C2410_SPCON		(0x00)
+
+#define S3C2410_SPCON_SMOD_DMA	(2 << 5)	/* DMA mode */
+#define S3C2410_SPCON_SMOD_INT	(1 << 5)	/* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL	(0 << 5)	/* polling mode */
+#define S3C2410_SPCON_ENSCK	(1 << 4)	/* Enable SCK */
+#define S3C2410_SPCON_MSTR	(1 << 3)	/* Master:1, Slave:0 select */
+#define S3C2410_SPCON_CPOL_HIGH	(1 << 2)	/* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW	(0 << 2)	/* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB	(1 << 1)	/* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA	(0 << 1)	/* Clock Phase Select */
+
+#define S3C2410_SPSTA		(0x04)
+
+#define S3C2410_SPSTA_DCOL	(1 << 2)	/* Data Collision Error */
+#define S3C2410_SPSTA_MULD	(1 << 1)	/* Multi Master Error */
+#define S3C2410_SPSTA_READY	(1 << 0)	/* Data Tx/Rx ready */
+#define S3C2412_SPSTA_READY_ORG	(1 << 3)
+
+#define S3C2410_SPPIN		(0x08)
+
+#define S3C2410_SPPIN_ENMUL	(1 << 2)	/* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED	(1 << 1)
+#define S3C2410_SPPIN_KEEP	(1 << 0)	/* Master Out keep */
+
+#define S3C2410_SPPRE		(0x0C)
+#define S3C2410_SPTDAT		(0x10)
+#define S3C2410_SPRDAT		(0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-srom.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-srom.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-srom.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/* linux/arch/arm/plat-samsung/include/plat/regs-srom.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P SROMC register definitions
+ *
+ * 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 __PLAT_SAMSUNG_REGS_SROM_H
+#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SROMREG(x)		(S5P_VA_SROMC + (x))
+
+#define S5P_SROM_BW		S5P_SROMREG(0x0)
+#define S5P_SROM_BC0		S5P_SROMREG(0x4)
+#define S5P_SROM_BC1		S5P_SROMREG(0x8)
+#define S5P_SROM_BC2		S5P_SROMREG(0xc)
+#define S5P_SROM_BC3		S5P_SROMREG(0x10)
+#define S5P_SROM_BC4		S5P_SROMREG(0x14)
+#define S5P_SROM_BC5		S5P_SROMREG(0x18)
+
+/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
+
+#define S5P_SROM_BW__DATAWIDTH__SHIFT		0
+#define S5P_SROM_BW__ADDRMODE__SHIFT		1
+#define S5P_SROM_BW__WAITENABLE__SHIFT		2
+#define S5P_SROM_BW__BYTEENABLE__SHIFT		3
+
+#define S5P_SROM_BW__CS_MASK			0xf
+
+#define S5P_SROM_BW__NCS0__SHIFT		0
+#define S5P_SROM_BW__NCS1__SHIFT		4
+#define S5P_SROM_BW__NCS2__SHIFT		8
+#define S5P_SROM_BW__NCS3__SHIFT		12
+#define S5P_SROM_BW__NCS4__SHIFT		16
+#define S5P_SROM_BW__NCS5__SHIFT		20
+
+/* applies to same to BCS0 - BCS3 */
+
+#define S5P_SROM_BCX__PMC__SHIFT		0
+#define S5P_SROM_BCX__TACP__SHIFT		4
+#define S5P_SROM_BCX__TCAH__SHIFT		8
+#define S5P_SROM_BCX__TCOH__SHIFT		12
+#define S5P_SROM_BCX__TACC__SHIFT		16
+#define S5P_SROM_BCX__TCOS__SHIFT		24
+#define S5P_SROM_BCX__TACS__SHIFT		28
+
+#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-udc.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-udc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/regs-udc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/regs-udc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-udc.h
+ *
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file 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 __ASM_ARCH_REGS_UDC_H
+#define __ASM_ARCH_REGS_UDC_H
+
+#define S3C2410_USBDREG(x) (x)
+
+#define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
+#define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
+#define S3C2410_UDC_EP_INT_REG		S3C2410_USBDREG(0x0148)
+
+#define S3C2410_UDC_USB_INT_REG		S3C2410_USBDREG(0x0158)
+#define S3C2410_UDC_EP_INT_EN_REG	S3C2410_USBDREG(0x015c)
+
+#define S3C2410_UDC_USB_INT_EN_REG	S3C2410_USBDREG(0x016c)
+
+#define S3C2410_UDC_FRAME_NUM1_REG	S3C2410_USBDREG(0x0170)
+#define S3C2410_UDC_FRAME_NUM2_REG	S3C2410_USBDREG(0x0174)
+
+#define S3C2410_UDC_EP0_FIFO_REG	S3C2410_USBDREG(0x01c0)
+#define S3C2410_UDC_EP1_FIFO_REG	S3C2410_USBDREG(0x01c4)
+#define S3C2410_UDC_EP2_FIFO_REG	S3C2410_USBDREG(0x01c8)
+#define S3C2410_UDC_EP3_FIFO_REG	S3C2410_USBDREG(0x01cc)
+#define S3C2410_UDC_EP4_FIFO_REG	S3C2410_USBDREG(0x01d0)
+
+#define S3C2410_UDC_EP1_DMA_CON		S3C2410_USBDREG(0x0200)
+#define S3C2410_UDC_EP1_DMA_UNIT	S3C2410_USBDREG(0x0204)
+#define S3C2410_UDC_EP1_DMA_FIFO	S3C2410_USBDREG(0x0208)
+#define S3C2410_UDC_EP1_DMA_TTC_L	S3C2410_USBDREG(0x020c)
+#define S3C2410_UDC_EP1_DMA_TTC_M	S3C2410_USBDREG(0x0210)
+#define S3C2410_UDC_EP1_DMA_TTC_H	S3C2410_USBDREG(0x0214)
+
+#define S3C2410_UDC_EP2_DMA_CON		S3C2410_USBDREG(0x0218)
+#define S3C2410_UDC_EP2_DMA_UNIT	S3C2410_USBDREG(0x021c)
+#define S3C2410_UDC_EP2_DMA_FIFO	S3C2410_USBDREG(0x0220)
+#define S3C2410_UDC_EP2_DMA_TTC_L	S3C2410_USBDREG(0x0224)
+#define S3C2410_UDC_EP2_DMA_TTC_M	S3C2410_USBDREG(0x0228)
+#define S3C2410_UDC_EP2_DMA_TTC_H	S3C2410_USBDREG(0x022c)
+
+#define S3C2410_UDC_EP3_DMA_CON		S3C2410_USBDREG(0x0240)
+#define S3C2410_UDC_EP3_DMA_UNIT	S3C2410_USBDREG(0x0244)
+#define S3C2410_UDC_EP3_DMA_FIFO	S3C2410_USBDREG(0x0248)
+#define S3C2410_UDC_EP3_DMA_TTC_L	S3C2410_USBDREG(0x024c)
+#define S3C2410_UDC_EP3_DMA_TTC_M	S3C2410_USBDREG(0x0250)
+#define S3C2410_UDC_EP3_DMA_TTC_H	S3C2410_USBDREG(0x0254)
+
+#define S3C2410_UDC_EP4_DMA_CON		S3C2410_USBDREG(0x0258)
+#define S3C2410_UDC_EP4_DMA_UNIT	S3C2410_USBDREG(0x025c)
+#define S3C2410_UDC_EP4_DMA_FIFO	S3C2410_USBDREG(0x0260)
+#define S3C2410_UDC_EP4_DMA_TTC_L	S3C2410_USBDREG(0x0264)
+#define S3C2410_UDC_EP4_DMA_TTC_M	S3C2410_USBDREG(0x0268)
+#define S3C2410_UDC_EP4_DMA_TTC_H	S3C2410_USBDREG(0x026c)
+
+#define S3C2410_UDC_INDEX_REG		S3C2410_USBDREG(0x0178)
+
+/* indexed registers */
+
+#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x0180)
+
+#define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
+
+#define S3C2410_UDC_IN_CSR1_REG		S3C2410_USBDREG(0x0184)
+#define S3C2410_UDC_IN_CSR2_REG		S3C2410_USBDREG(0x0188)
+
+#define S3C2410_UDC_OUT_CSR1_REG	S3C2410_USBDREG(0x0190)
+#define S3C2410_UDC_OUT_CSR2_REG	S3C2410_USBDREG(0x0194)
+#define S3C2410_UDC_OUT_FIFO_CNT1_REG	S3C2410_USBDREG(0x0198)
+#define S3C2410_UDC_OUT_FIFO_CNT2_REG	S3C2410_USBDREG(0x019c)
+
+#define S3C2410_UDC_FUNCADDR_UPDATE	(1 << 7)
+
+#define S3C2410_UDC_PWR_ISOUP		(1 << 7) /* R/W */
+#define S3C2410_UDC_PWR_RESET		(1 << 3) /* R   */
+#define S3C2410_UDC_PWR_RESUME		(1 << 2) /* R/W */
+#define S3C2410_UDC_PWR_SUSPEND		(1 << 1) /* R   */
+#define S3C2410_UDC_PWR_ENSUSPEND	(1 << 0) /* R/W */
+
+#define S3C2410_UDC_PWR_DEFAULT		(0x00)
+
+#define S3C2410_UDC_INT_EP4		(1 << 4) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP3		(1 << 3) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP2		(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP1		(1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP0		(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_USBINT_RESET	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_RESUME	(1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_SUSPEND	(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_INTE_EP4		(1 << 4) /* R/W */
+#define S3C2410_UDC_INTE_EP3		(1 << 3) /* R/W */
+#define S3C2410_UDC_INTE_EP2		(1 << 2) /* R/W */
+#define S3C2410_UDC_INTE_EP1		(1 << 1) /* R/W */
+#define S3C2410_UDC_INTE_EP0		(1 << 0) /* R/W */
+
+#define S3C2410_UDC_USBINTE_RESET	(1 << 2) /* R/W */
+#define S3C2410_UDC_USBINTE_SUSPEND	(1 << 0) /* R/W */
+
+#define S3C2410_UDC_INDEX_EP0		(0x00)
+#define S3C2410_UDC_INDEX_EP1		(0x01)
+#define S3C2410_UDC_INDEX_EP2		(0x02)
+#define S3C2410_UDC_INDEX_EP3		(0x03)
+#define S3C2410_UDC_INDEX_EP4		(0x04)
+
+#define S3C2410_UDC_ICSR1_CLRDT		(1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR1_SENTSTL	(1 << 5) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_SENDSTL	(1 << 4) /* R/W */
+#define S3C2410_UDC_ICSR1_FFLUSH	(1 << 3) /* W   (set only) */
+#define S3C2410_UDC_ICSR1_UNDRUN	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_PKTRDY	(1 << 0) /* R/W (set only) */
+
+#define S3C2410_UDC_ICSR2_AUTOSET	(1 << 7) /* R/W */
+#define S3C2410_UDC_ICSR2_ISO		(1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR2_MODEIN	(1 << 5) /* R/W */
+#define S3C2410_UDC_ICSR2_DMAIEN	(1 << 4) /* R/W */
+
+#define S3C2410_UDC_OCSR1_CLRDT		(1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR1_SENTSTL	(1 << 6) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_SENDSTL	(1 << 5) /* R/W */
+#define S3C2410_UDC_OCSR1_FFLUSH	(1 << 4) /* R/W */
+#define S3C2410_UDC_OCSR1_DERROR	(1 << 3) /* R   */
+#define S3C2410_UDC_OCSR1_OVRRUN	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_PKTRDY	(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_OCSR2_AUTOCLR	(1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR2_ISO		(1 << 6) /* R/W */
+#define S3C2410_UDC_OCSR2_DMAIEN	(1 << 5) /* R/W */
+
+#define S3C2410_UDC_EP0_CSR_OPKRDY	(1 << 0)
+#define S3C2410_UDC_EP0_CSR_IPKRDY	(1 << 1)
+#define S3C2410_UDC_EP0_CSR_SENTSTL	(1 << 2)
+#define S3C2410_UDC_EP0_CSR_DE		(1 << 3)
+#define S3C2410_UDC_EP0_CSR_SE		(1 << 4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL	(1 << 5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY	(1 << 6)
+#define S3C2410_UDC_EP0_CSR_SSE		(1 << 7)
+
+#define S3C2410_UDC_MAXP_8		(1 << 0)
+#define S3C2410_UDC_MAXP_16		(1 << 1)
+#define S3C2410_UDC_MAXP_32		(1 << 2)
+#define S3C2410_UDC_MAXP_64		(1 << 3)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/reset.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/reset.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+/* linux/arch/arm/plat-samsung/include/plat/reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_SAMSUNG_RESET_H
+#define __PLAT_SAMSUNG_RESET_H __FILE__
+
+extern void (*s5p_reset_hook)(void);
+
+#endif /* __PLAT_SAMSUNG_RESET_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2410.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2410.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * 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.
+ *
+*/
+
+#ifdef CONFIG_CPU_S3C2410
+
+extern  int s3c2410_init(void);
+extern  int s3c2410a_init(void);
+
+extern void s3c2410_map_io(void);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2410_init_clocks(int xtal);
+
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#define s3c2410a_init NULL
+#endif
+
+extern int s3c2410_baseclk_add(void);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2412.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2412.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2412.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2412.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(void);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2416.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2416.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2416.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2416.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2416.h
+ *
+ * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * Header file for s3c2416 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2416
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2416_init(void);
+
+extern void s3c2416_map_io(void);
+
+extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2416_init_clocks(int xtal);
+
+extern  int s3c2416_baseclk_add(void);
+
+#else
+#define s3c2416_init_clocks NULL
+#define s3c2416_init_uarts NULL
+#define s3c2416_map_io NULL
+#define s3c2416_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2443.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2443.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c2443.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c2443.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2443_init(void);
+
+extern void s3c2443_map_io(void);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern  int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
+
+/* common code used by s3c2443 and others.
+ * note, not to be used outside of arch/arm/mach-s3c* */
+
+struct clk;	/* some files don't need clk.h otherwise */
+
+typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
+
+extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
+extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
+				       unsigned int *divs, int nr_divs,
+				       int divmask);
+
+extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
+
+extern struct clksrc_clk clk_epllref;
+extern struct clksrc_clk clk_esysclk;
+extern struct clksrc_clk clk_msysclk;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c244x.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c244x.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c244x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c244x.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c244x.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * 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.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(void);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+
+extern void s3c2440_map_io(void);
+#else
+#define s3c2440_init NULL
+#define s3c2440_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+
+extern void s3c2442_map_io(void);
+#else
+#define s3c2442_init NULL
+#define s3c2442_map_io NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c6400.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c6400.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c6400.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c6400.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6400.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6400 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for S3C6400 related SoCs */
+
+extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c6400_setup_clocks(void);
+
+extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
+
+#ifdef CONFIG_CPU_S3C6400
+
+extern  int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
+extern void s3c6400_map_io(void);
+extern void s3c6400_init_clocks(int xtal);
+
+#define s3c6400_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6400_init_clocks NULL
+#define s3c6400_init_uarts NULL
+#define s3c6400_map_io NULL
+#define s3c6400_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c6410.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c6410.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c6410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6410.h
+ *
+ * Copyright 2008 Openmoko,  Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6410 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C6410
+
+extern  int s3c6410_init(void);
+extern void s3c6410_init_irq(void);
+extern void s3c6410_map_io(void);
+extern void s3c6410_init_clocks(int xtal);
+
+#define s3c6410_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6410_init_clocks NULL
+#define s3c6410_init_uarts NULL
+#define s3c6410_map_io NULL
+#define s3c6410_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART		(1 << 0)
-#define S3C2410_DMAF_CIRCULAR		(1 << 1)
-
-/*
- * PL330 can assign any channel to communicate with
- * any of the peripherals attched to the DMAC.
- * For the sake of consistency across client drivers,
- * We keep the channel names unchanged and only add
- * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
- * use these just as IDs.
- */
-enum dma_ch {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_UART4_RX,
-	DMACH_UART4_TX,
-	DMACH_UART5_RX,
-	DMACH_UART5_TX,
-	DMACH_USI_RX,
-	DMACH_USI_TX,
-	DMACH_IRDA,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_I2S2_RX,
-	DMACH_I2S2_TX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_SPI2_RX,
-	DMACH_SPI2_TX,
-	DMACH_AC97_MICIN,
-	DMACH_AC97_PCMIN,
-	DMACH_AC97_PCMOUT,
-	DMACH_EXTERNAL,
-	DMACH_PWM,
-	DMACH_SPDIF,
-	DMACH_HSI_RX,
-	DMACH_HSI_TX,
-	DMACH_PCM0_TX,
-	DMACH_PCM0_RX,
-	DMACH_PCM1_TX,
-	DMACH_PCM1_RX,
-	DMACH_PCM2_TX,
-	DMACH_PCM2_RX,
-	DMACH_MSM_REQ3,
-	DMACH_MSM_REQ2,
-	DMACH_MSM_REQ1,
-	DMACH_MSM_REQ0,
-	DMACH_SLIMBUS0_RX,
-	DMACH_SLIMBUS0_TX,
-	DMACH_SLIMBUS0AUX_RX,
-	DMACH_SLIMBUS0AUX_TX,
-	DMACH_SLIMBUS1_RX,
-	DMACH_SLIMBUS1_TX,
-	DMACH_SLIMBUS2_RX,
-	DMACH_SLIMBUS2_TX,
-	DMACH_SLIMBUS3_RX,
-	DMACH_SLIMBUS3_TX,
-	DMACH_SLIMBUS4_RX,
-	DMACH_SLIMBUS4_TX,
-	DMACH_SLIMBUS5_RX,
-	DMACH_SLIMBUS5_TX,
-	/* END Marker, also used to denote a reserved channel */
-	DMACH_MAX,
-};
-
-static inline bool s3c_dma_has_circular(void)
-{
-	return true;
-}
-
-#include <plat/dma.h>
-
-#endif	/* __S3C_DMA_PL330_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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 __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/s3c-dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-	enum dma_ch peri[32];
-};
-
-#endif /* __S3C_PL330_PDATA_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p6440.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p6440.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p6440.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p6440.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6440.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p6440 cpu support
+ *
+ * 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.
+*/
+
+ /* Common init code for S5P6440 related SoCs */
+
+extern void s5p6440_register_clocks(void);
+extern void s5p6440_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6440
+
+extern  int s5p64x0_init(void);
+extern void s5p6440_init_irq(void);
+extern void s5p6440_map_io(void);
+extern void s5p6440_init_clocks(int xtal);
+
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6440_init_clocks NULL
+#define s5p6440_init_uarts NULL
+#define s5p6440_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6440 timer */
+
+extern struct sys_timer s5p6440_timer;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p6450.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p6450.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p6450.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p6450.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p6450 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern  int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5pc100.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5pc100.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5pc100.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5pc100.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pc100.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pc100 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for S5PC100 related SoCs */
+
+extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pc100_register_clocks(void);
+extern void s5pc100_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PC100
+
+extern  int s5pc100_init(void);
+extern void s5pc100_init_irq(void);
+extern void s5pc100_map_io(void);
+extern void s5pc100_init_clocks(int xtal);
+
+#define s5pc100_init_uarts s5pc100_common_init_uarts
+
+#else
+#define s5pc100_init_clocks NULL
+#define s5pc100_init_uarts NULL
+#define s5pc100_map_io NULL
+#define s5pc100_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p-clock.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p-clock.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_CLOCK_H
+#define __ASM_PLAT_S5P_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+#define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_mpll clk_ext_xtal_mux
+#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
+#define clk_fin_vpll clk_ext_xtal_mux
+#define clk_fin_hpll clk_ext_xtal_mux
+
+extern struct clk clk_ext_xtal_mux;
+extern struct clk clk_xusbxti;
+extern struct clk clk_48m;
+extern struct clk s5p_clk_27m;
+extern struct clk clk_fout_apll;
+extern struct clk clk_fout_mpll;
+extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
+extern struct clk clk_fout_vpll;
+extern struct clk clk_arm;
+extern struct clk clk_vpll;
+
+extern struct clksrc_sources clk_src_apll;
+extern struct clksrc_sources clk_src_mpll;
+extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
+
+extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
+
+/* Common EPLL operations for S5P platform */
+extern int s5p_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p_epll_get_rate(struct clk *clk);
+
+/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
+extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long s5p_spdif_get_rate(struct clk *clk);
+
+extern struct clk_ops s5p_sclk_spdif_ops;
+#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p-time.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p-time.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5p-time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5p-time.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p-time.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p time support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_TIME_H
+#define __ASM_PLAT_S5P_TIME_H __FILE__
+
+/* S5P HR-Timer Clock mode */
+enum s5p_timer_mode {
+	S5P_PWM0,
+	S5P_PWM1,
+	S5P_PWM2,
+	S5P_PWM3,
+	S5P_PWM4,
+};
+
+struct s5p_timer_source {
+	unsigned int event_id;
+	unsigned int source_id;
+};
+
+/* Be able to sleep for atleast 4 seconds (usually more) */
+#define S5PTIMER_MIN_RANGE	4
+
+#define TCNT_MAX		0xffffffff
+#define NON_PERIODIC		0
+#define PERIODIC		1
+
+extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
+					enum s5p_timer_mode source);
+extern	struct sys_timer s5p_timer;
+#endif /* __ASM_PLAT_S5P_TIME_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5pv210.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5pv210.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/s5pv210.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/s5pv210.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pv210.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pv210 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for S5PV210 related SoCs */
+
+extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pv210_register_clocks(void);
+extern void s5pv210_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PV210
+
+extern  int s5pv210_init(void);
+extern void s5pv210_init_irq(void);
+extern void s5pv210_map_io(void);
+extern void s5pv210_init_clocks(int xtal);
+
+#define s5pv210_init_uarts s5pv210_common_init_uarts
+
+#else
+#define s5pv210_init_clocks NULL
+#define s5pv210_init_uarts NULL
+#define s5pv210_map_io NULL
+#define s5pv210_init NULL
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,10 +55,6 @@ enum clk_types {
  *		 cd_type == S3C_SDHCI_CD_GPIO
  * @ext_cd_gpio_invert: invert values for external CD gpio line
  * @cfg_gpio: Configure the GPIO for a specific card bit-width
- * @cfg_card: Configure the interface for a specific card and speed. This
- *            is necessary the controllers and/or GPIO blocks require the
- *	      changing of driver-strength and other controls dependent on
- *	      the card and speed of operation.
  *
  * Initialisation data specific to either the machine or the platform
  * for the device driver to use or call-back when configuring gpio or
@@ -80,12 +76,15 @@ struct s3c_sdhci_platdata {
 						      int state));
 
 	void	(*cfg_gpio)(struct platform_device *dev, int width);
-	void	(*cfg_card)(struct platform_device *dev,
-			    void __iomem *regbase,
-			    struct mmc_ios *ios,
-			    struct mmc_card *card);
 };
 
+/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
+ * @pd: The default platform data for this device.
+ * @set: Pointer to the platform data to fill in.
+ */
+extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+				    struct s3c_sdhci_platdata *set);
+
 /**
  * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
  * @pd: Platform data to register to device.
@@ -132,17 +131,11 @@ extern void exynos4_setup_sdhci3_cfg_gpi
 #ifdef CONFIG_S3C2416_SETUP_SDHCI
 extern char *s3c2416_hsmmc_clksrcs[4];
 
-extern void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s3c2416_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC */
 }
 
@@ -151,7 +144,6 @@ static inline void s3c2416_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC1 */
 }
 
@@ -165,17 +157,11 @@ static inline void s3c2416_default_sdhci
 #ifdef CONFIG_S3C64XX_SETUP_SDHCI
 extern char *s3c64xx_hsmmc_clksrcs[4];
 
-extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-					 void __iomem *r,
-					 struct mmc_ios *ios,
-					 struct mmc_card *card);
-
 static inline void s3c6400_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -184,7 +170,6 @@ static inline void s3c6400_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -193,21 +178,14 @@ static inline void s3c6400_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
-extern void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-					 void __iomem *r,
-					 struct mmc_ios *ios,
-					 struct mmc_card *card);
-
 static inline void s3c6410_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -216,7 +194,6 @@ static inline void s3c6410_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -225,7 +202,6 @@ static inline void s3c6410_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -244,17 +220,11 @@ static inline void s3c6400_default_sdhci
 #ifdef CONFIG_S5PC100_SETUP_SDHCI
 extern char *s5pc100_hsmmc_clksrcs[4];
 
-extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s5pc100_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -263,7 +233,6 @@ static inline void s5pc100_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -272,7 +241,6 @@ static inline void s5pc100_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -288,17 +256,11 @@ static inline void s5pc100_default_sdhci
 #ifdef CONFIG_S5PV210_SETUP_SDHCI
 extern char *s5pv210_hsmmc_clksrcs[4];
 
-extern void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s5pv210_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -307,7 +269,6 @@ static inline void s5pv210_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -316,7 +277,6 @@ static inline void s5pv210_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -325,7 +285,6 @@ static inline void s5pv210_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC3
 	s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
-	s3c_hsmmc3_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -341,17 +300,11 @@ static inline void s5pv210_default_sdhci
 #ifdef CONFIG_EXYNOS4_SETUP_SDHCI
 extern char *exynos4_hsmmc_clksrcs[4];
 
-extern void exynos4_setup_sdhci_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void exynos4_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -360,7 +313,6 @@ static inline void exynos4_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -369,7 +321,6 @@ static inline void exynos4_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -378,7 +329,6 @@ static inline void exynos4_default_sdhci
 #ifdef CONFIG_S3C_DEV_HSMMC3
 	s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs;
 	s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
-	s3c_hsmmc3_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/sysmmu.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/sysmmu.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung System MMU driver for S5P platform
+ *
+ * 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 __PLAT_SAMSUNG_SYSMMU_H
+#define __PLAT_SAMSUNG_SYSMMU_H __FILE__
+
+enum S5P_SYSMMU_INTERRUPT_TYPE {
+	SYSMMU_PAGEFAULT,
+	SYSMMU_AR_MULTIHIT,
+	SYSMMU_AW_MULTIHIT,
+	SYSMMU_BUSERROR,
+	SYSMMU_AR_SECURITY,
+	SYSMMU_AR_ACCESS,
+	SYSMMU_AW_SECURITY,
+	SYSMMU_AW_PROTECTION, /* 7 */
+	SYSMMU_FAULTS_NUM
+};
+
+#ifdef CONFIG_S5P_SYSTEM_MMU
+
+#include <mach/sysmmu.h>
+
+/**
+ * s5p_sysmmu_enable() - enable system mmu of ip
+ * @ips: The ip connected system mmu.
+ * #pgd: Base physical address of the 1st level page table
+ *
+ * This function enable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_disable() - disable sysmmu mmu of ip
+ * @ips: The ip connected system mmu.
+ *
+ * This function disable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_disable(sysmmu_ips ips);
+
+/**
+ * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
+ * @ips: The ip connected system mmu.
+ * @pgd: The page table base address.
+ *
+ * This function set page table base address
+ * When system mmu transfer address from virtaul address to physical address,
+ * system mmu refer address information from page table
+ */
+void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
+ * @ips: The ip connected system mmu.
+ *
+ * This function flush all TLB entry in system mmu
+ */
+void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
+
+/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
+ * @itype: type of fault.
+ * @pgtable_base: the physical address of page table base. This is 0 if @ips is
+ *               SYSMMU_BUSERROR.
+ * @fault_addr: the device (virtual) address that the System MMU tried to
+ *             translated. This is 0 if @ips is SYSMMU_BUSERROR.
+ * Called when interrupt occurred by the System MMUs
+ * The device drivers of peripheral devices that has a System MMU can implement
+ * a fault handler to resolve address translation fault by System MMU.
+ * The meanings of return value and parameters are described below.
+
+ * return value: non-zero if the fault is correctly resolved.
+ *         zero if the fault is not handled.
+ */
+void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
+			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+					unsigned long pgtable_base,
+					unsigned long fault_addr));
+#else
+#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
+#define s5p_sysmmu_disable(ips) do { } while (0)
+#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
+#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
+#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
+#endif
+#endif /* __ASM_PLAT_SYSMMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/system-reset.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/system-reset.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/system-reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/system-reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/system-reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
+ *
+ * S5P - System define for arch_reset()
+ *
+ * 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 <plat/watchdog-reset.h>
+
+void (*s5p_reset_hook)(void);
+
+static void arch_reset(char mode, const char *cmd)
+{
+	/* SWRESET support in s5p_reset_hook() */
+
+	if (s5p_reset_hook)
+		s5p_reset_hook();
+
+	/* Perform reset using Watchdog reset
+	 * if there is no s5p_reset_hook()
+	 */
+
+	arch_wdt_reset();
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/tv-core.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/tv-core.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/tv-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/tv-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-samsung/include/plat/tv.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *	Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * Samsung TV driver core functions
+ *
+ * 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 __SAMSUNG_PLAT_TV_H
+#define __SAMSUNG_PLAT_TV_H __FILE__
+
+/*
+ * These functions are only for use with the core support code, such as
+ * the CPU-specific initialization code.
+ */
+
+/* Re-define device name to differentiate the subsystem in various SoCs. */
+static inline void s5p_hdmi_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_hdmi.name = name;
+#endif
+}
+
+static inline void s5p_mixer_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_mixer.name = name;
+#endif
+}
+
+static inline void s5p_sdo_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_sdo.name = name;
+#endif
+}
+
+#endif /* __SAMSUNG_PLAT_TV_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/udc.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/udc.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/udc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/udc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,57 @@
+/* arch/arm/plat-samsung/include/plat/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
+ *
+ *
+ *  Changelog:
+ *	14-Mar-2005	RTP	Created file
+ *	02-Aug-2005	RTP	File rename
+ *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
+ *	18-Jan-2007	HMW	Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
+	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
+	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
+};
+
+struct s3c2410_udc_mach_info {
+	void	(*udc_command)(enum s3c2410_udc_cmd_e);
+	void	(*vbus_draw)(unsigned int ma);
+
+	unsigned int pullup_pin;
+	unsigned int pullup_pin_inverted;
+
+	unsigned int vbus_pin;
+	unsigned char vbus_pin_inverted;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+/**
+ * s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
+ * @epnum: Number of endpoints to be instantiated by the controller driver.
+ * @gpio_init: Platform specific USB related GPIO initialization.
+ * @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
+ *
+ * Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
+ * controllers.
+ */
+struct s3c24xx_hsudc_platdata {
+	unsigned int	epnum;
+	void		(*gpio_init)(void);
+	void		(*gpio_uninit)(void);
+};
+
+extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/usb-phy.h linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/usb-phy.h
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/include/plat/usb-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/include/plat/usb-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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 __PLAT_SAMSUNG_USB_PHY_H
+#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
+
+enum s5p_usb_phy_type {
+	S5P_USB_PHY_DEVICE,
+	S5P_USB_PHY_HOST,
+};
+
+extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
+extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
+
+#endif /* __PLAT_SAMSUNG_USB_PHY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/irq-uart.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/irq-uart.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/irq-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/irq-uart.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* arch/arm/plat-samsung/irq-uart.c
- *	originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Samsung- UART Interrupt handling
- *
- * 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/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <plat/irq-uart.h>
-#include <plat/regs-serial.h>
-#include <plat/cpu.h>
-
-/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
-	struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
-	struct irq_chip *chip = irq_get_chip(irq);
-	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
-	int base = uirq->base_irq;
-
-	chained_irq_enter(chip, desc);
-
-	if (pend & (1 << 0))
-		generic_handle_irq(base);
-	if (pend & (1 << 1))
-		generic_handle_irq(base + 1);
-	if (pend & (1 << 2))
-		generic_handle_irq(base + 2);
-	if (pend & (1 << 3))
-		generic_handle_irq(base + 3);
-
-	chained_irq_exit(chip, desc);
-}
-
-static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
-{
-	void __iomem *reg_base = uirq->regs;
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	/* mask all interrupts at the start. */
-	__raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
-	gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,
-				    handle_level_irq);
-
-	if (!gc) {
-		pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n",
-		       __func__, uirq->base_irq);
-		return;
-	}
-
-	ct = gc->chip_types;
-	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_mask = irq_gc_mask_set_bit;
-	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-	ct->regs.ack = S3C64XX_UINTP;
-	ct->regs.mask = S3C64XX_UINTM;
-	irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-
-	irq_set_handler_data(uirq->parent_irq, uirq);
-	irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
-/**
- * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
- * @irq: The interrupt data for registering
- * @nr_irqs: The number of interrupt descriptions in @irq.
- *
- * Register the UART interrupts specified by @irq including the demuxing
- * routines. This supports the S3C6400 and newer style of devices.
- */
-void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs)
-{
-	for (; nr_irqs > 0; nr_irqs--, irq++)
-		s3c_init_uart_irq(irq);
-}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/Kconfig linux-libre-3.2-gnu1/arch/arm/plat-samsung/Kconfig
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER
        help
          Internal configuration to build the VIC timer interrupt code.
 
-config SAMSUNG_IRQ_UART
-       bool
-       help
-         Internal configuration to build the IRQ UART demux code.
-
 # options for gpio configuration support
 
 config SAMSUNG_GPIOLIB_4BIT
@@ -79,39 +74,12 @@ config SAMSUNG_GPIOLIB_4BIT
 	  configuration. GPIOlib shall be compiled only for S3C64XX and S5P
 	  series of processors.
 
-config S3C_GPIO_CFG_S3C24XX
-	bool
-	help
-	  Internal configuration to enable S3C24XX style GPIO configuration
-	  functions.
-
 config S3C_GPIO_CFG_S3C64XX
 	bool
 	help
 	  Internal configuration to enable S3C64XX style GPIO configuration
 	  functions.
 
-config S3C_GPIO_PULL_UPDOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_S3C2443
-	bool
-	select S3C_GPIO_PULL_UPDOWN
-	help
-	  Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO
-
-config S3C_GPIO_PULL_DOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_UP
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
 config S5P_GPIO_DRVSTR
 	bool
 	help
@@ -300,11 +268,14 @@ config S3C_DMA
 	help
 	  Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
+config SAMSUNG_DMADEV
 	bool
-	select PL330
+	select DMADEVICES
+	select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
+					CPU_S5P6450 || CPU_S5P6440)
+	select ARM_AMBA
 	help
-	  S3C DMA API Driver for PL330 DMAC.
+	  Use DMA device engine for PL330 DMAC.
 
 comment "Power management"
 
@@ -367,4 +338,11 @@ config SAMSUNG_PD
 	help
 	  Say Y here if you want to control Power Domain by Runtime PM.
 
+config DEBUG_S3C_UART
+	depends on PLAT_SAMSUNG
+	int
+	default "0" if DEBUG_S3C_UART0
+	default "1" if DEBUG_S3C_UART1
+	default "2" if DEBUG_S3C_UART2
+
 endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/Makefile linux-libre-3.2-gnu1/arch/arm/plat-samsung/Makefile
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-# arch/arm/plat-s3c64xx/Makefile
+# arch/arm/plat-samsung/Makefile
 #
 # Copyright 2009 Simtec Electronics
 #
@@ -11,17 +11,13 @@ obj-				:=
 
 # Objects we always build independent of SoC choice
 
-obj-y				+= init.o
+obj-y				+= init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y				+= clock.o
 obj-y				+= pwm-clock.o
-obj-y				+= gpio.o
-obj-y				+= gpio-config.o
-obj-y				+= dev-asocdma.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
 
-obj-$(CONFIG_SAMSUNG_IRQ_UART)	+= irq-uart.o
 obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
 
 # ADC
@@ -32,40 +28,16 @@ obj-$(CONFIG_S3C_ADC)	+= adc.o
 
 obj-y				+= platformdata.o
 
-obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
-obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
-obj-$(CONFIG_S3C_DEV_HSMMC2)	+= dev-hsmmc2.o
-obj-$(CONFIG_S3C_DEV_HSMMC3)	+= dev-hsmmc3.o
-obj-$(CONFIG_S3C_DEV_HWMON)	+= dev-hwmon.o
-obj-y				+= dev-i2c0.o
-obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
-obj-$(CONFIG_S3C_DEV_I2C2)	+= dev-i2c2.o
-obj-$(CONFIG_S3C_DEV_I2C3)	+= dev-i2c3.o
-obj-$(CONFIG_S3C_DEV_I2C4)	+= dev-i2c4.o
-obj-$(CONFIG_S3C_DEV_I2C5)	+= dev-i2c5.o
-obj-$(CONFIG_S3C_DEV_I2C6)	+= dev-i2c6.o
-obj-$(CONFIG_S3C_DEV_I2C7)	+= dev-i2c7.o
-obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
+obj-y				+= devs.o
 obj-y				+= dev-uart.o
-obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
-obj-$(CONFIG_S3C_DEV_USB_HSOTG)	+= dev-usb-hsotg.o
-obj-$(CONFIG_S3C_DEV_WDT)	+= dev-wdt.o
-obj-$(CONFIG_S3C_DEV_NAND)	+= dev-nand.o
-obj-$(CONFIG_S3C_DEV_ONENAND)	+= dev-onenand.o
-obj-$(CONFIG_S3C_DEV_RTC)	+= dev-rtc.o
 
-obj-$(CONFIG_SAMSUNG_DEV_ADC)	+= dev-adc.o
-obj-$(CONFIG_SAMSUNG_DEV_IDE)	+= dev-ide.o
-obj-$(CONFIG_SAMSUNG_DEV_TS)	+= dev-ts.o
-obj-$(CONFIG_SAMSUNG_DEV_KEYPAD)	+= dev-keypad.o
-obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
 obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)	+= dev-backlight.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)		+= dma.o
+obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o
+obj-$(CONFIG_SAMSUNG_DMADEV)	+= dma-ops.o
 
 # PM support
 
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/pd.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/pd.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/pd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/pd.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/platformdata.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/platformdata.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/platformdata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/platformdata.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,10 +10,12 @@
 */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
 
 #include <plat/devs.h>
+#include <plat/sdhci.h>
 
 void __init *s3c_set_platdata(void *pd, size_t pdsize,
 			      struct platform_device *pdev)
@@ -35,3 +37,22 @@ void __init *s3c_set_platdata(void *pd,
 	pdev->dev.platform_data = npd;
 	return npd;
 }
+
+void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+			     struct s3c_sdhci_platdata *set)
+{
+	set->cd_type = pd->cd_type;
+	set->ext_cd_init = pd->ext_cd_init;
+	set->ext_cd_cleanup = pd->ext_cd_cleanup;
+	set->ext_cd_gpio = pd->ext_cd_gpio;
+	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
+
+	if (pd->max_width)
+		set->max_width = pd->max_width;
+	if (pd->cfg_gpio)
+		set->cfg_gpio = pd->cfg_gpio;
+	if (pd->host_caps)
+		set->host_caps |= pd->host_caps;
+	if (pd->clk_type)
+		set->clk_type = pd->clk_type;
+}
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/pm.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/pm.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -268,8 +268,8 @@ static int s3c_pm_enter(suspend_state_t
 
 	/* save all necessary core registers not covered by the drivers */
 
-	s3c_pm_save_gpios();
-	s3c_pm_saved_gpios();
+	samsung_pm_save_gpios();
+	samsung_pm_saved_gpios();
 	s3c_pm_save_uarts();
 	s3c_pm_save_core();
 
@@ -306,7 +306,7 @@ static int s3c_pm_enter(suspend_state_t
 
 	s3c_pm_restore_core();
 	s3c_pm_restore_uarts();
-	s3c_pm_restore_gpios();
+	samsung_pm_restore_gpios();
 	s3c_pm_restored_gpios();
 
 	s3c_pm_debug_init();
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/pm-gpio.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/pm-gpio.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/pm-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/pm-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,13 +28,13 @@
 #define OFFS_DAT	(0x04)
 #define OFFS_UP		(0x08)
 
-static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
 }
 
-static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -60,12 +60,12 @@ static void s3c_gpio_pm_1bit_resume(stru
 		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-	.save	= s3c_gpio_pm_1bit_save,
-	.resume = s3c_gpio_pm_1bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_1bit = {
+	.save	= samsung_gpio_pm_1bit_save,
+	.resume = samsung_gpio_pm_1bit_resume,
 };
 
-static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
@@ -95,7 +95,7 @@ static inline int is_out(unsigned long c
 }
 
 /**
- * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
  * @chip: The chip information to resume.
  *
  * Restore one of the GPIO banks that was saved during suspend. This is
@@ -121,7 +121,7 @@ static inline int is_out(unsigned long c
  * [1] this assumes that writing to a pin DAT whilst in SFN will set the
  *     state for when it is next output.
  */
-static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -187,13 +187,13 @@ static void s3c_gpio_pm_2bit_resume(stru
 		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-	.save	= s3c_gpio_pm_2bit_save,
-	.resume = s3c_gpio_pm_2bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_2bit = {
+	.save	= samsung_gpio_pm_2bit_save,
+	.resume = samsung_gpio_pm_2bit_resume,
 };
 
 #if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
-static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
@@ -203,7 +203,7 @@ static void s3c_gpio_pm_4bit_save(struct
 		chip->pm_save[0] = __raw_readl(chip->base - 4);
 }
 
-static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
 {
 	u32 old, new, mask;
 	u32 change_mask = 0x0;
@@ -242,14 +242,14 @@ static u32 s3c_gpio_pm_4bit_mask(u32 old
 	return change_mask;
 }
 
-static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
 {
 	void __iomem *con = chip->base + (index * 4);
 	u32 old_gpcon = __raw_readl(con);
 	u32 gps_gpcon = chip->pm_save[index + 1];
 	u32 gpcon, mask;
 
-	mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+	mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
 
 	gpcon = old_gpcon & ~mask;
 	gpcon |= gps_gpcon & mask;
@@ -257,7 +257,7 @@ static void s3c_gpio_pm_4bit_con(struct
 	__raw_writel(gpcon, con);
 }
 
-static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon[2];
@@ -269,10 +269,10 @@ static void s3c_gpio_pm_4bit_resume(stru
 	old_gpcon[0] = 0;
 	old_gpcon[1] = __raw_readl(base + OFFS_CON);
 
-	s3c_gpio_pm_4bit_con(chip, 0);
+	samsung_gpio_pm_4bit_con(chip, 0);
 	if (chip->chip.ngpio > 8) {
 		old_gpcon[0] = __raw_readl(base - 4);
-		s3c_gpio_pm_4bit_con(chip, -1);
+		samsung_gpio_pm_4bit_con(chip, -1);
 	}
 
 	/* Now change the configurations that require DAT,CON */
@@ -298,19 +298,19 @@ static void s3c_gpio_pm_4bit_resume(stru
 			  old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-	.save	= s3c_gpio_pm_4bit_save,
-	.resume = s3c_gpio_pm_4bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_4bit = {
+	.save	= samsung_gpio_pm_4bit_save,
+	.resume = samsung_gpio_pm_4bit_resume,
 };
 #endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
- * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * samsung_pm_save_gpio() - save gpio chip data for suspend
  * @ourchip: The chip for suspend.
  */
-static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
 {
-	struct s3c_gpio_pm *pm = ourchip->pm;
+	struct samsung_gpio_pm *pm = ourchip->pm;
 
 	if (pm == NULL || pm->save == NULL)
 		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -319,24 +319,24 @@ static void s3c_pm_save_gpio(struct s3c_
 }
 
 /**
- * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ * samsung_pm_save_gpios() - Save the state of the GPIO banks.
  *
  * For all the GPIO banks, save the state of each one ready for going
  * into a suspend mode.
  */
-void s3c_pm_save_gpios(void)
+void samsung_pm_save_gpios(void)
 {
-	struct s3c_gpio_chip *ourchip;
+	struct samsung_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
 	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		ourchip = samsung_gpiolib_getchip(gpio_nr);
 		if (!ourchip) {
 			gpio_nr++;
 			continue;
 		}
 
-		s3c_pm_save_gpio(ourchip);
+		samsung_pm_save_gpio(ourchip);
 
 		S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
 			  ourchip->chip.label,
@@ -351,12 +351,12 @@ void s3c_pm_save_gpios(void)
 }
 
 /**
- * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * samsung_pm_resume_gpio() - restore gpio chip data after suspend
  * @ourchip: The suspended chip.
  */
-static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
 {
-	struct s3c_gpio_pm *pm = ourchip->pm;
+	struct samsung_gpio_pm *pm = ourchip->pm;
 
 	if (pm == NULL || pm->resume == NULL)
 		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -364,19 +364,19 @@ static void s3c_pm_resume_gpio(struct s3
 		pm->resume(ourchip);
 }
 
-void s3c_pm_restore_gpios(void)
+void samsung_pm_restore_gpios(void)
 {
-	struct s3c_gpio_chip *ourchip;
+	struct samsung_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
 	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		ourchip = samsung_gpiolib_getchip(gpio_nr);
 		if (!ourchip) {
 			gpio_nr++;
 			continue;
 		}
 
-		s3c_pm_resume_gpio(ourchip);
+		samsung_pm_resume_gpio(ourchip);
 
 		gpio_nr += ourchip->chip.ngpio;
 		gpio_nr += CONFIG_S3C_GPIO_SPACE;
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/pwm.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/pwm.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * the Free Software Foundation; either version 2 of the License.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -299,6 +299,9 @@ static int s3c_pwm_probe(struct platform
 		goto err_clk_tin;
 	}
 
+	clk_enable(pwm->clk);
+	clk_enable(pwm->clk_div);
+
 	local_irq_save(flags);
 
 	tcon = __raw_readl(S3C2410_TCON);
@@ -326,6 +329,8 @@ static int s3c_pwm_probe(struct platform
 	return 0;
 
  err_clk_tdiv:
+	clk_disable(pwm->clk_div);
+	clk_disable(pwm->clk);
 	clk_put(pwm->clk_div);
 
  err_clk_tin:
@@ -340,6 +345,8 @@ static int __devexit s3c_pwm_remove(stru
 {
 	struct pwm_device *pwm = platform_get_drvdata(pdev);
 
+	clk_disable(pwm->clk_div);
+	clk_disable(pwm->clk);
 	clk_put(pwm->clk_div);
 	clk_put(pwm->clk);
 	kfree(pwm);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/pwm-clock.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/pwm-clock.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/pwm-clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/pwm-clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <plat/cpu.h>
 
 #include <plat/regs-timer.h>
-#include <mach/pwm-clock.h>
+#include <plat/pwm-clock.h>
 
 /* Each of the timers 0 through 5 go through the following
  * clock tree, with the inputs depending on the timers.
@@ -339,8 +339,17 @@ static int clk_pwm_tin_set_parent(struct
 	unsigned long bits;
 	unsigned long shift = S3C2410_TCFG1_SHIFT(id);
 
+	unsigned long mux_tclk;
+
+	if (soc_is_s3c24xx())
+		mux_tclk = S3C2410_TCFG1_MUX_TCLK;
+	else if (soc_is_s5p6440() || soc_is_s5p6450())
+		mux_tclk = 0;
+	else
+		mux_tclk = S3C64XX_TCFG1_MUX_TCLK;
+
 	if (parent == s3c24xx_pwmclk_tclk(id))
-		bits = S3C_TCFG1_MUX_TCLK << shift;
+		bits = mux_tclk << shift;
 	else if (parent == s3c24xx_pwmclk_tdiv(id))
 		bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
 	else
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/s3c-dma-ops.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/s3c-dma-ops.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/s3c-dma-ops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/s3c-dma-ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,131 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * 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/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+	void (*fp) (void *);
+	void *fp_param;
+	unsigned ch;
+	struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+		       int size, enum s3c2410_dma_buffresult res)
+{
+	struct cb_data *data = param;
+
+	data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+				 struct samsung_dma_info *info)
+{
+	struct cb_data *data;
+
+	if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+		s3c2410_dma_free(dma_ch, info->client);
+		return 0;
+	}
+
+	data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+	data->ch = dma_ch;
+	list_add_tail(&data->node, &dma_list);
+
+	s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
+
+	if (info->cap == DMA_CYCLIC)
+		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+	s3c2410_dma_config(dma_ch, info->width);
+
+	return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+	struct cb_data *data;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+	list_del(&data->node);
+
+	s3c2410_dma_free(ch, client);
+	kfree(data);
+
+	return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+	struct cb_data *data;
+	int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+
+	if (!data->fp) {
+		s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+		data->fp = info->fp;
+		data->fp_param = info->fp_param;
+	}
+
+	s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+	return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+	.request	= s3c_dma_request,
+	.release	= s3c_dma_release,
+	.prepare	= s3c_dma_prepare,
+	.trigger	= s3c_dma_trigger,
+	.started	= s3c_dma_started,
+	.flush		= s3c_dma_flush,
+	.stop		= s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+	return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-samsung/s3c-pl330.c linux-libre-3.2-gnu1/arch/arm/plat-samsung/s3c-pl330.c
--- linux-libre-3.1-gnu1/arch/arm/plat-samsung/s3c-pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-samsung/s3c-pl330.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-	unsigned		busy_chan;
-	enum dma_ch		*peri;
-	struct list_head	node;
-	struct pl330_info	*pi;
-	struct kmem_cache	*kmcache;
-	struct clk		*clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-	void			*token;
-	struct list_head	node;
-	struct pl330_xfer	px;
-	struct s3c_pl330_chan	*chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- * 	a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- * 	NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @req: Two requests to communicate with the PL330 engine.
- * @callback_fn: Callback function to the client.
- * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next executed.
- * @dmac: Pointer to the DMAC that manages this channel, NULL if the
- * 	channel is available to be acquired.
- * @client: Client of this channel. NULL if the
- * 	channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-	void				*pl330_chan_id;
-	enum dma_ch			id;
-	unsigned int			options;
-	unsigned long			sdaddr;
-	struct list_head		node;
-	struct pl330_req		*lrq;
-	struct list_head		xfer_list;
-	struct pl330_req		req[2];
-	s3c2410_dma_cbfn_t		callback_fn;
-	struct pl330_reqcfg		rqcfg;
-	struct s3c_pl330_xfer		*xfer_head;
-	struct s3c_pl330_dmac		*dmac;
-	struct s3c2410_dma_client	*client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch;
-
-	list_for_each_entry(ch, &chan_list, node)
-		if (ch->id == id)
-			return ch;
-
-	return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-
-	/* Return if the channel already exists */
-	if (ch)
-		return;
-
-	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-	/* Return silently to work with other channels */
-	if (!ch)
-		return;
-
-	ch->id = id;
-	ch->dmac = NULL;
-
-	list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-	if (!ch)
-		return false;
-
-	/* Channel points to some DMAC only when it's acquired */
-	return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-	enum dma_ch *id = dmac->peri;
-	int i;
-
-	/* Discount invalid markers */
-	if (ch_id == DMACH_MAX)
-		return 0;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch_id)
-			return i + 1;
-
-	return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-	struct pl330_info *pi = dmac->pi;
-
-	return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	struct s3c_pl330_chan *ch;
-	unsigned found, count = 0;
-	enum dma_ch p;
-	int i;
-
-	for (i = 0; i < PL330_MAX_PERI; i++) {
-		p = id[i];
-		ch = id_to_chan(p);
-
-		if (p == DMACH_MAX || !chan_free(ch))
-			continue;
-
-		found = 0;
-		list_for_each_entry(d, &dmac_list, node) {
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found)
-			count++;
-	}
-
-	return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT	UINT_MAX
-#define MIN_SUIT	0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-		struct s3c_pl330_chan *ch)
-{
-	struct pl330_info *pi = dmac->pi;
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	unsigned s;
-	int i;
-
-	s = MIN_SUIT;
-	/* If all the DMAC channel threads are busy */
-	if (dmac_busy(dmac))
-		return s;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch->id)
-			break;
-
-	/* If the 'dmac' can't talk to 'ch' */
-	if (i == PL330_MAX_PERI)
-		return s;
-
-	s = MAX_SUIT;
-	list_for_each_entry(d, &dmac_list, node) {
-		/*
-		 * If some other dmac can talk to this
-		 * peri and has some channel free.
-		 */
-		if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-			s = 0;
-			break;
-		}
-	}
-	if (s)
-		return s;
-
-	s = 100;
-
-	/* Good if free chans are more, bad otherwise */
-	s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-	return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *d, *dmac = NULL;
-	unsigned sn, sl = MIN_SUIT;
-
-	list_for_each_entry(d, &dmac_list, node) {
-		sn = suitablility(d, ch);
-
-		if (sn == MAX_SUIT)
-			return d;
-
-		if (sn > sl)
-			dmac = d;
-	}
-
-	return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct s3c_pl330_dmac *dmac;
-
-	/* If the channel doesn't exist or is already acquired */
-	if (!ch || !chan_free(ch)) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac = map_chan_to_dmac(ch);
-	/* If couldn't map */
-	if (!dmac) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac->busy_chan++;
-	ch->dmac = dmac;
-
-acq_exit:
-	return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-	struct s3c_pl330_xfer *t;
-	struct s3c_pl330_chan *ch;
-	int found;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Make sure xfer is in the queue */
-	found = 0;
-	list_for_each_entry(t, &ch->xfer_list, node)
-		if (t == xfer) {
-			found = 1;
-			break;
-		}
-
-	if (!found)
-		return;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		t = list_entry(ch->xfer_list.next,
-				struct s3c_pl330_xfer, node);
-	else
-		t = list_entry(xfer->node.next,
-				struct s3c_pl330_xfer, node);
-
-	/* If there was only one node left */
-	if (t == xfer)
-		ch->xfer_head = NULL;
-	else if (ch->xfer_head == xfer)
-		ch->xfer_head = t;
-
-	list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-		int pluck)
-{
-	struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-	if (!xfer)
-		return NULL;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		ch->xfer_head = list_entry(ch->xfer_list.next,
-					struct s3c_pl330_xfer, node);
-	else
-		ch->xfer_head = list_entry(xfer->node.next,
-					struct s3c_pl330_xfer, node);
-
-	if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		del_from_queue(xfer);
-
-	return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-		struct s3c_pl330_xfer *xfer, int front)
-{
-	struct pl330_xfer *xt;
-
-	/* If queue empty */
-	if (ch->xfer_head == NULL)
-		ch->xfer_head = xfer;
-
-	xt = &ch->xfer_head->px;
-	/* If the head already submitted (CIRCULAR head) */
-	if (ch->options & S3C2410_DMAF_CIRCULAR &&
-		(xt == ch->req[0].x || xt == ch->req[1].x))
-		ch->xfer_head = xfer;
-
-	/* If this is a resubmission, it should go at the head */
-	if (front) {
-		ch->xfer_head = xfer;
-		list_add(&xfer->node, &ch->xfer_list);
-	} else {
-		list_add_tail(&xfer->node, &ch->xfer_list);
-	}
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-		enum s3c2410_dma_buffresult res, int ffree)
-{
-	struct s3c_pl330_chan *ch;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Do callback */
-	if (ch->callback_fn)
-		ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-	/* Force Free or if buffer is not needed anymore */
-	if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-		struct pl330_req *r)
-{
-	struct s3c_pl330_xfer *xfer;
-	int ret = 0;
-
-	/* If already submitted */
-	if (r->x)
-		return 0;
-
-	xfer = get_from_queue(ch, 0);
-	if (xfer) {
-		r->x = &xfer->px;
-
-		/* Use max bandwidth for M<->M xfers */
-		if (r->rqtype == MEMTOMEM) {
-			struct pl330_info *pi = xfer->chan->dmac->pi;
-			int burst = 1 << ch->rqcfg.brst_size;
-			u32 bytes = r->x->bytes;
-			int bl;
-
-			bl = pi->pcfg.data_bus_width / 8;
-			bl *= pi->pcfg.data_buf_dep;
-			bl /= burst;
-
-			/* src/dst_burst_len can't be more than 16 */
-			if (bl > 16)
-				bl = 16;
-
-			while (bl > 1) {
-				if (!(bytes % (bl * burst)))
-					break;
-				bl--;
-			}
-
-			ch->rqcfg.brst_len = bl;
-		} else {
-			ch->rqcfg.brst_len = 1;
-		}
-
-		ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-		/* If submission was successful */
-		if (!ret) {
-			ch->lrq = r; /* latest submitted req */
-			return 0;
-		}
-
-		r->x = NULL;
-
-		/* If both of the PL330 ping-pong buffers filled */
-		if (ret == -EAGAIN) {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			/* Queue back again */
-			add_to_queue(ch, xfer, 1);
-			ret = 0;
-		} else {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			_finish_off(xfer, S3C2410_RES_ERR, 0);
-		}
-	}
-
-	return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-	struct pl330_req *r, enum pl330_op_err err)
-{
-	unsigned long flags;
-	struct s3c_pl330_xfer *xfer;
-	struct pl330_xfer *xl = r->x;
-	enum s3c2410_dma_buffresult res;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	r->x = NULL;
-
-	s3c_pl330_submit(ch, r);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	/* Map result to S3C DMA API */
-	if (err == PL330_ERR_NONE)
-		res = S3C2410_RES_OK;
-	else if (err == PL330_ERR_ABORT)
-		res = S3C2410_RES_ABORT;
-	else
-		res = S3C2410_RES_ERR;
-
-	/* If last request had some xfer */
-	if (xl) {
-		xfer = container_of(xl, struct s3c_pl330_xfer, px);
-		_finish_off(xfer, res, 0);
-	} else {
-		dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-			__func__, __LINE__);
-	}
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[0]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[1]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *dmac;
-
-	if (chan_free(ch))
-		return;
-
-	dmac = ch->dmac;
-	ch->dmac = NULL;
-	dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-	struct s3c_pl330_xfer *xfer;
-	enum pl330_chan_op pl330op;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int idx, ret;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto ctrl_exit;
-	}
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		/* Make sure both reqs are enqueued */
-		idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-		s3c_pl330_submit(ch, &ch->req[idx]);
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-		pl330op = PL330_OP_START;
-		break;
-
-	case S3C2410_DMAOP_STOP:
-		pl330op = PL330_OP_ABORT;
-		break;
-
-	case S3C2410_DMAOP_FLUSH:
-		pl330op = PL330_OP_FLUSH;
-		break;
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-	case S3C2410_DMAOP_TIMEOUT:
-	case S3C2410_DMAOP_STARTED:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-
-	default:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return -EINVAL;
-	}
-
-	ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-	if (pl330op == PL330_OP_START) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return ret;
-	}
-
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	/* Abort the current xfer */
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		/* Drop xfer during FLUSH */
-		if (pl330op == PL330_OP_FLUSH)
-			del_from_queue(xfer);
-
-		ch->req[idx].x = NULL;
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT,
-				pl330op == PL330_OP_FLUSH ? 1 : 0);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Flush the whole queue */
-	if (pl330op == PL330_OP_FLUSH) {
-
-		if (ch->req[1 - idx].x) {
-			xfer = container_of(ch->req[1 - idx].x,
-					struct s3c_pl330_xfer, px);
-
-			del_from_queue(xfer);
-
-			ch->req[1 - idx].x = NULL;
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-		}
-
-		/* Finish off the remaining in the queue */
-		xfer = ch->xfer_head;
-		while (xfer) {
-
-			del_from_queue(xfer);
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-
-			xfer = ch->xfer_head;
-		}
-	}
-
-ctrl_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-			dma_addr_t addr, int size)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int idx, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	/* Error if invalid or free channel */
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	/* Error if size is unaligned */
-	if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-	if (!xfer) {
-		ret = -ENOMEM;
-		goto enq_exit;
-	}
-
-	xfer->token = token;
-	xfer->chan = ch;
-	xfer->px.bytes = size;
-	xfer->px.next = NULL; /* Single request */
-
-	/* For S3C DMA API, direction is always fixed for all xfers */
-	if (ch->req[0].rqtype == MEMTODEV) {
-		xfer->px.src_addr = addr;
-		xfer->px.dst_addr = ch->sdaddr;
-	} else {
-		xfer->px.src_addr = ch->sdaddr;
-		xfer->px.dst_addr = addr;
-	}
-
-	add_to_queue(ch, xfer, 0);
-
-	/* Try submitting on either request */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (!ch->req[idx].x)
-		s3c_pl330_submit(ch, &ch->req[idx]);
-	else
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	if (ch->options & S3C2410_DMAF_AUTOSTART)
-		s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-	return 0;
-
-enq_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c_pl330_dmac *dmac;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = chan_acquire(id);
-	if (!ch) {
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	dmac = ch->dmac;
-
-	ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-	if (!ch->pl330_chan_id) {
-		chan_release(ch);
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	ch->client = client;
-	ch->options = 0; /* Clear any option */
-	ch->callback_fn = NULL; /* Clear any callback */
-	ch->lrq = NULL;
-
-	ch->rqcfg.brst_size = 2; /* Default word size */
-	ch->rqcfg.swap = SWAP_NO;
-	ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.privileged = 0;
-	ch->rqcfg.insnaccess = 0;
-
-	/* Set invalid direction */
-	ch->req[0].rqtype = DEVTODEV;
-	ch->req[1].rqtype = ch->req[0].rqtype;
-
-	ch->req[0].cfg = &ch->rqcfg;
-	ch->req[1].cfg = ch->req[0].cfg;
-
-	ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-	ch->req[1].peri = ch->req[0].peri;
-
-	ch->req[0].token = &ch->req[0];
-	ch->req[0].xfer_cb = s3c_pl330_rq0;
-	ch->req[1].token = &ch->req[1];
-	ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-	ch->req[0].x = NULL;
-	ch->req[1].x = NULL;
-
-	/* Reset xfer list */
-	INIT_LIST_HEAD(&ch->xfer_list);
-	ch->xfer_head = NULL;
-
-req_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int ret = 0;
-	unsigned idx;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		goto free_exit;
-
-	/* Refuse if someone else wanted to free the channel */
-	if (ch->client != client) {
-		ret = -EBUSY;
-		goto free_exit;
-	}
-
-	/* Stop any active xfer, Flushe the queue and do callbacks */
-	pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-	/* Abort the submitted requests */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	if (ch->req[1 - idx].x) {
-		xfer = container_of(ch->req[1 - idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[1 - idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Pluck and Abort the queued requests in order */
-	do {
-		xfer = get_from_queue(ch, 1);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	} while (xfer);
-
-	ch->client = NULL;
-
-	pl330_release_channel(ch->pl330_chan_id);
-
-	ch->pl330_chan_id = NULL;
-
-	chan_release(ch);
-
-free_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-	struct s3c_pl330_chan *ch;
-	struct pl330_info *pi;
-	unsigned long flags;
-	int i, dbwidth, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	pi = ch->dmac->pi;
-	dbwidth = pi->pcfg.data_bus_width / 8;
-
-	/* Max size of xfer can be pcfg.data_bus_width */
-	if (xferunit > dbwidth) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	i = 0;
-	while (xferunit != (1 << i))
-		i++;
-
-	/* If valid value */
-	if (xferunit == (1 << i))
-		ch->rqcfg.brst_size = i;
-	else
-		ret = -EINVAL;
-
-cfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-		ret = -EINVAL;
-	else
-		ch->options = options;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		ret = -EINVAL;
-	else
-		ch->callback_fn = rtn;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-			  unsigned long address)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	switch (source) {
-	case S3C2410_DMASRC_HW: /* P->M */
-		ch->req[0].rqtype = DEVTOMEM;
-		ch->req[1].rqtype = DEVTOMEM;
-		ch->rqcfg.src_inc = 0;
-		ch->rqcfg.dst_inc = 1;
-		break;
-	case S3C2410_DMASRC_MEM: /* M->P */
-		ch->req[0].rqtype = MEMTODEV;
-		ch->req[1].rqtype = MEMTODEV;
-		ch->rqcfg.src_inc = 1;
-		ch->rqcfg.dst_inc = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	ch->sdaddr = address;
-
-devcfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct pl330_chanstatus status;
-	int ret;
-
-	if (!ch || chan_free(ch))
-		return -EINVAL;
-
-	ret = pl330_chan_status(ch->pl330_chan_id, &status);
-	if (ret < 0)
-		return ret;
-
-	*src = status.src_addr;
-	*dst = status.dst_addr;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-	if (pl330_update(data))
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *s3c_pl330_dmac;
-	struct s3c_pl330_platdata *pl330pd;
-	struct pl330_info *pl330_info;
-	struct resource *res;
-	int i, ret, irq;
-
-	pl330pd = pdev->dev.platform_data;
-
-	/* Can't do without the list of _32_ peripherals */
-	if (!pl330pd || !pl330pd->peri) {
-		dev_err(&pdev->dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-	if (!pl330_info)
-		return -ENOMEM;
-
-	pl330_info->pl330_data = NULL;
-	pl330_info->dev = &pdev->dev;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto probe_err1;
-	}
-
-	request_mem_region(res->start, resource_size(res), pdev->name);
-
-	pl330_info->base = ioremap(res->start, resource_size(res));
-	if (!pl330_info->base) {
-		ret = -ENXIO;
-		goto probe_err2;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		ret = irq;
-		goto probe_err3;
-	}
-
-	ret = request_irq(irq, pl330_irq_handler, 0,
-			dev_name(&pdev->dev), pl330_info);
-	if (ret)
-		goto probe_err4;
-
-	/* Allocate a new DMAC */
-	s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-	if (!s3c_pl330_dmac) {
-		ret = -ENOMEM;
-		goto probe_err5;
-	}
-
-	/* Get operation clock and enable it */
-	s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-	if (IS_ERR(s3c_pl330_dmac->clk)) {
-		dev_err(&pdev->dev, "Cannot get operation clock.\n");
-		ret = -EINVAL;
-		goto probe_err6;
-	}
-	clk_enable(s3c_pl330_dmac->clk);
-
-	ret = pl330_add(pl330_info);
-	if (ret)
-		goto probe_err7;
-
-	/* Hook the info */
-	s3c_pl330_dmac->pi = pl330_info;
-
-	/* No busy channels */
-	s3c_pl330_dmac->busy_chan = 0;
-
-	s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-				sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-	if (!s3c_pl330_dmac->kmcache) {
-		ret = -ENOMEM;
-		goto probe_err8;
-	}
-
-	/* Get the list of peripherals */
-	s3c_pl330_dmac->peri = pl330pd->peri;
-
-	/* Attach to the list of DMACs */
-	list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-	/* Create a channel for each peripheral in the DMAC
-	 * that is, if it doesn't already exist
-	 */
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-			chan_add(s3c_pl330_dmac->peri[i]);
-
-	printk(KERN_INFO
-		"Loaded driver for PL330 DMAC-%d %s\n",	pdev->id, pdev->name);
-	printk(KERN_INFO
-		"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-		pl330_info->pcfg.data_buf_dep,
-		pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-		pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-	return 0;
-
-probe_err8:
-	pl330_del(pl330_info);
-probe_err7:
-	clk_disable(s3c_pl330_dmac->clk);
-	clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-	kfree(s3c_pl330_dmac);
-probe_err5:
-	free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-	iounmap(pl330_info->base);
-probe_err2:
-	release_mem_region(res->start, resource_size(res));
-probe_err1:
-	kfree(pl330_info);
-
-	return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *dmac, *d;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int del, found;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	found = 0;
-	list_for_each_entry(d, &dmac_list, node)
-		if (d->pi->dev == &pdev->dev) {
-			found = 1;
-			break;
-		}
-
-	if (!found) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-	}
-
-	dmac = d;
-
-	/* Remove all Channels that are managed only by this DMAC */
-	list_for_each_entry(ch, &chan_list, node) {
-
-		/* Only channels that are handled by this DMAC */
-		if (iface_of_dmac(dmac, ch->id))
-			del = 1;
-		else
-			continue;
-
-		/* Don't remove if some other DMAC has it too */
-		list_for_each_entry(d, &dmac_list, node)
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				del = 0;
-				break;
-			}
-
-		if (del) {
-			spin_unlock_irqrestore(&res_lock, flags);
-			s3c2410_dma_free(ch->id, ch->client);
-			spin_lock_irqsave(&res_lock, flags);
-			list_del(&ch->node);
-			kfree(ch);
-		}
-	}
-
-	/* Disable operation clock */
-	clk_disable(dmac->clk);
-	clk_put(dmac->clk);
-
-	/* Remove the DMAC */
-	list_del(&dmac->node);
-	kfree(dmac);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-
-static struct platform_driver pl330_driver = {
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "s3c-pl330",
-	},
-	.probe		= pl330_probe,
-	.remove		= pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-	return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-	platform_driver_unregister(&pl330_driver);
-	return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/debug-macro.S linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/amba/serial.h>
 #include <mach/hardware.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
 		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
 		.endm
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/gpio.h linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/gpio.h
--- linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,24 +1 @@
-/*
- * arch/arm/plat-spear/include/plat/gpio.h
- *
- * GPIO macros for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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 __PLAT_GPIO_H
-#define __PLAT_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-#endif /* __PLAT_GPIO_H */
+/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/memory.h linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/memory.h
--- linux-libre-3.1-gnu1/arch/arm/plat-spear/include/plat/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-spear/include/plat/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/memory.h
- *
- * Memory map for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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 __PLAT_MEMORY_H
-#define __PLAT_MEMORY_H
-
-/* Physical DRAM offset */
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif /* __PLAT_MEMORY_H */
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-tcc/include/mach/debug-macro.S linux-libre-3.2-gnu1/arch/arm/plat-tcc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu1/arch/arm/plat-tcc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-tcc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  *
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		moveq	\rp, #0x90000000	@ physical base address
 		movne	\rv, #0xF1000000	@ virtual base
 		orr	\rp, \rp, #0x00007000	@ UART0
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-tcc/include/mach/memory.h linux-libre-3.2-gnu1/arch/arm/plat-tcc/include/mach/memory.h
--- linux-libre-3.1-gnu1/arch/arm/plat-tcc/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-tcc/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2008-2009 Telechips
- * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
- *
- * Licensed under the terms of the GPL v2.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/arm/plat-versatile/platsmp.c linux-libre-3.2-gnu1/arch/arm/plat-versatile/platsmp.c
--- linux-libre-3.1-gnu1/arch/arm/plat-versatile/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/plat-versatile/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ int __cpuinit boot_secondary(unsigned in
 	 * since we haven't sent them a soft interrupt, they shouldn't
 	 * be there.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	/*
 	 * Send the secondary CPU a soft interrupt, thereby causing
diff -druNp linux-libre-3.1-gnu1/arch/arm/tools/mach-types linux-libre-3.2-gnu1/arch/arm/tools/mach-types
--- linux-libre-3.1-gnu1/arch/arm/tools/mach-types	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/tools/mach-types	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,9 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# XXX: This is a cut-down version of the file; it contains only machines that
-# XXX: are in mainline or have been submitted to the machine database within
-# XXX: the last 12 months.  If your entry is missing please email rmk at
-# XXX: <linux@arm.linux.org.uk>
+# This is a cut-down version of the file; it contains only machines that
+# are merged into mainline or have been edited in the machine database
+# within the last 12 months.  References to machine_is_NAME() do not count!
 #
 # Last update: Sat May 7 08:48:24 2011
 #
@@ -65,6 +64,7 @@ h7201			ARCH_H7201		H7201			161
 h7202			ARCH_H7202		H7202			162
 iq80321			ARCH_IQ80321		IQ80321			169
 ks8695			ARCH_KS8695		KS8695			180
+karo			ARCH_KARO		KARO			190
 smdk2410		ARCH_SMDK2410		SMDK2410		193
 ceiva			ARCH_CEIVA		CEIVA			200
 voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
@@ -188,6 +188,7 @@ omap_2430sdp		MACH_OMAP_2430SDP	OMAP_243
 davinci_evm		MACH_DAVINCI_EVM	DAVINCI_EVM		901
 palmz72			MACH_PALMZ72		PALMZ72			904
 nxdb500			MACH_NXDB500		NXDB500			905
+apf9328			MACH_APF9328		APF9328			906
 palmt5			MACH_PALMT5		PALMT5			917
 palmtc			MACH_PALMTC		PALMTC			918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
@@ -271,10 +272,12 @@ pcm038			MACH_PCM038		PCM038			1551
 ts_x09			MACH_TS209		TS209			1565
 at91cap9adk		MACH_AT91CAP9ADK	AT91CAP9ADK		1566
 mx31moboard		MACH_MX31MOBOARD	MX31MOBOARD		1574
+vision_ep9307		MACH_VISION_EP9307	VISION_EP9307		1578
 terastation_pro2	MACH_TERASTATION_PRO2	TERASTATION_PRO2	1584
 linkstation_pro		MACH_LINKSTATION_PRO	LINKSTATION_PRO		1585
 e350			MACH_E350		E350			1596
 ts409			MACH_TS409		TS409			1601
+rsi_ews			MACH_RSI_EWS		RSI_EWS			1609
 cm_x300			MACH_CM_X300		CM_X300			1616
 at91sam9g20ek		MACH_AT91SAM9G20EK	AT91SAM9G20EK		1624
 smdk6410		MACH_SMDK6410		SMDK6410		1626
@@ -331,6 +334,7 @@ smdkc100		MACH_SMDKC100		SMDKC100		1826
 tavorevb		MACH_TAVOREVB		TAVOREVB		1827
 saar			MACH_SAAR		SAAR			1828
 at91sam9m10g45ek	MACH_AT91SAM9M10G45EK	AT91SAM9M10G45EK	1830
+usb_a9g20		MACH_USB_A9G20		USB_A9G20		1841
 mxlads			MACH_MXLADS		MXLADS			1851
 linkstation_mini	MACH_LINKSTATION_MINI	LINKSTATION_MINI	1858
 afeb9260		MACH_AFEB9260		AFEB9260		1859
@@ -369,6 +373,7 @@ pcm043			MACH_PCM043		PCM043			2072
 sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
 avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
 mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
+tx37			MACH_TX37		TX37			2127
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
 ts219			MACH_TS219		TS219			2139
@@ -379,6 +384,7 @@ omap_4430sdp		MACH_OMAP_4430SDP	OMAP_443
 magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
 btmavb101		MACH_BTMAVB101		BTMAVB101		2172
 btmawb101		MACH_BTMAWB101		BTMAWB101		2173
+tx25			MACH_TX25		TX25			2177
 omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
 anw6410			MACH_ANW6410		ANW6410			2183
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
@@ -423,6 +429,7 @@ raumfeld_rc		MACH_RAUMFELD_RC	RAUMFELD_R
 raumfeld_connector	MACH_RAUMFELD_CONNECTOR	RAUMFELD_CONNECTOR	2414
 raumfeld_speaker	MACH_RAUMFELD_SPEAKER	RAUMFELD_SPEAKER	2415
 tnetv107x		MACH_TNETV107X		TNETV107X		2418
+mx51_m2id		MACH_MX51_M2ID		MX51_M2ID		2428
 smdkv210		MACH_SMDKV210		SMDKV210		2456
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
@@ -433,14 +440,17 @@ omapl138_hawkboard	MACH_OMAPL138_HAWKBOA
 ts41x			MACH_TS41X		TS41X			2502
 phy3250			MACH_PHY3250		PHY3250			2511
 mini6410		MACH_MINI6410		MINI6410		2520
+tx51			MACH_TX51		TX51			2529
 mx28evk			MACH_MX28EVK		MX28EVK			2531
 smartq5			MACH_SMARTQ5		SMARTQ5			2534
 davinci_dm6467tevm	MACH_DAVINCI_DM6467TEVM	DAVINCI_DM6467TEVM	2548
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
 riot_bei2		MACH_RIOT_BEI2		RIOT_BEI2		2576
 riot_x37		MACH_RIOT_X37		RIOT_X37		2578
+pca101			MACH_PCA101		PCA101			2595
 capc7117		MACH_CAPC7117		CAPC7117		2612
 icontrol		MACH_ICONTROL		ICONTROL		2624
+gplugd			MACH_GPLUGD		GPLUGD			2625
 qsd8x50a_st1_5		MACH_QSD8X50A_ST1_5	QSD8X50A_ST1_5		2627
 mx23evk			MACH_MX23EVK		MX23EVK			2629
 ap4evb			MACH_AP4EVB		AP4EVB			2630
@@ -1113,3 +1123,6 @@ blissc			MACH_BLISSC		BLISSC			3491
 thales_adc		MACH_THALES_ADC		THALES_ADC		3492
 ubisys_p9d_evp		MACH_UBISYS_P9D_EVP	UBISYS_P9D_EVP		3493
 atdgp318		MACH_ATDGP318		ATDGP318		3494
+m28evk			MACH_M28EVK		M28EVK			3613
+smdk4212		MACH_SMDK4212		SMDK4212		3638
+smdk4412		MACH_SMDK4412		SMDK4412		3765
diff -druNp linux-libre-3.1-gnu1/arch/arm/vfp/Makefile linux-libre-3.2-gnu1/arch/arm/vfp/Makefile
--- linux-libre-3.1-gnu1/arch/arm/vfp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/vfp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 # ccflags-y := -DDEBUG
 # asflags-y := -DDEBUG
 
-KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft)
 LDFLAGS		+=--no-warn-mismatch
 
 obj-y			+= vfp.o
diff -druNp linux-libre-3.1-gnu1/arch/arm/vfp/vfpmodule.c linux-libre-3.2-gnu1/arch/arm/vfp/vfpmodule.c
--- linux-libre-3.1-gnu1/arch/arm/vfp/vfpmodule.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/arm/vfp/vfpmodule.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,9 +8,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/cpu.h>
+#include <linux/cpu_pm.h>
 #include <linux/kernel.h>
 #include <linux/notifier.h>
 #include <linux/signal.h>
@@ -68,7 +68,7 @@ static bool vfp_state_in_hw(unsigned int
 /*
  * Force a reload of the VFP context from the thread structure.  We do
  * this by ensuring that access to the VFP hardware is disabled, and
- * clear last_VFP_context.  Must be called from non-preemptible context.
+ * clear vfp_current_hw_state.  Must be called from non-preemptible context.
  */
 static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)
 {
@@ -436,9 +436,7 @@ static void vfp_enable(void *unused)
 	set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
 }
 
-#ifdef CONFIG_PM
-#include <linux/syscore_ops.h>
-
+#ifdef CONFIG_CPU_PM
 static int vfp_pm_suspend(void)
 {
 	struct thread_info *ti = current_thread_info();
@@ -468,19 +466,33 @@ static void vfp_pm_resume(void)
 	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
 }
 
-static struct syscore_ops vfp_pm_syscore_ops = {
-	.suspend	= vfp_pm_suspend,
-	.resume		= vfp_pm_resume,
+static int vfp_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
+	void *v)
+{
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		vfp_pm_suspend();
+		break;
+	case CPU_PM_ENTER_FAILED:
+	case CPU_PM_EXIT:
+		vfp_pm_resume();
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vfp_cpu_pm_notifier_block = {
+	.notifier_call = vfp_cpu_pm_notifier,
 };
 
 static void vfp_pm_init(void)
 {
-	register_syscore_ops(&vfp_pm_syscore_ops);
+	cpu_pm_register_notifier(&vfp_cpu_pm_notifier_block);
 }
 
 #else
 static inline void vfp_pm_init(void) { }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_CPU_PM */
 
 /*
  * Ensure that the VFP state stored in 'thread->vfpstate' is up to date
diff -druNp linux-libre-3.1-gnu1/arch/avr32/boards/atngw100/setup.c linux-libre-3.2-gnu1/arch/avr32/boards/atngw100/setup.c
--- linux-libre-3.1-gnu1/arch/avr32/boards/atngw100/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/boards/atngw100/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,11 +90,6 @@ static struct mtd_partition nand_partiti
 	},
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(nand_partitions);
-	return nand_partitions;
-}
 
 static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
 	.cle		= 21,
@@ -102,7 +97,8 @@ static struct atmel_nand_data atngw100mk
 	.rdy_pin	= GPIO_PIN_PB(28),
 	.enable_pin	= GPIO_PIN_PE(23),
 	.bus_width_16	= true,
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(nand_partitions),
 };
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/avr32/boards/atstk1000/atstk1002.c linux-libre-3.2-gnu1/arch/avr32/boards/atstk1000/atstk1002.c
--- linux-libre-3.1-gnu1/arch/avr32/boards/atstk1000/atstk1002.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/boards/atstk1000/atstk1002.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,18 +90,13 @@ static struct mtd_partition nand_partiti
 	},
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(nand_partitions);
-	return nand_partitions;
-}
-
 static struct atmel_nand_data atstk1006_nand_data __initdata = {
 	.cle		= 21,
 	.ale		= 22,
 	.rdy_pin	= GPIO_PIN_PB(30),
 	.enable_pin	= GPIO_PIN_PB(29),
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(num_partitions),
 };
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/clock.c linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/clock.c
--- linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/list.h>
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/cpufreq.c linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/cpufreq.c
--- linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <asm/system.h>
 
 static struct clk *cpuclk;
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/include/mach/board.h linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/include/mach/board.h
--- linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/include/mach/board.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/include/mach/board.h	2012-01-04 18:55:44.000000000 -0500
@@ -128,7 +128,8 @@ struct atmel_nand_data {
 	u8	ale;		/* address line number connected to ALE */
 	u8	cle;		/* address line number connected to CLE */
 	u8	bus_width_16;	/* buswidth is 16 bit */
-	struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+	struct mtd_partition *parts;
+	unsigned int	num_parts;
 };
 struct platform_device *
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/intc.c linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/intc.c
--- linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/intc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/intc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/pio.c linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/pio.c
--- linux-libre-3.1-gnu1/arch/avr32/mach-at32ap/pio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mach-at32ap/pio.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/clk.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
diff -druNp linux-libre-3.1-gnu1/arch/avr32/mm/dma-coherent.c linux-libre-3.2-gnu1/arch/avr32/mm/dma-coherent.c
--- linux-libre-3.1-gnu1/arch/avr32/mm/dma-coherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/avr32/mm/dma-coherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
+#include <linux/export.h>
 
 #include <asm/addrspace.h>
 #include <asm/cacheflush.h>
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig linux-libre-3.2-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig
--- linux-libre-3.1-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
@@ -40,7 +39,6 @@ CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -55,7 +53,6 @@ CONFIG_IP_PNP=y
 CONFIG_CAN=m
 CONFIG_CAN_RAW=m
 CONFIG_CAN_BCM=m
-CONFIG_CAN_DEV=m
 CONFIG_CAN_BFIN=m
 CONFIG_IRDA=m
 CONFIG_IRLAN=m
@@ -67,7 +64,6 @@ CONFIG_BFIN_SIR3=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -105,12 +101,12 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_AD7877=m
 CONFIG_INPUT_MISC=y
 # CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_BFIN_JTAG_COMM=m
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_UART1=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -163,6 +159,7 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_OTG_BLACKLIST_HUB=y
 CONFIG_USB_MON=y
 CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_BLACKFIN=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK=m
@@ -185,8 +182,6 @@ CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_CIFS=y
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_936=m
@@ -196,7 +191,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HWERR=y
@@ -206,5 +200,4 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ON
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_BFIN_PSEUDODBG_INSNS=y
-CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/include/asm/atomic.h linux-libre-3.2-gnu1/arch/blackfin/include/asm/atomic.h
--- linux-libre-3.1-gnu1/arch/blackfin/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
+ * Copyright 2004-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,111 +7,27 @@
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
 
-#ifndef CONFIG_SMP
-# include <asm-generic/atomic.h>
-#else
-
-#include <linux/types.h>
-#include <asm/system.h>	/* local_irq_XXX() */
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-#define atomic_set(v, i)	(((v)->counter) = i)
+#ifdef CONFIG_SMP
 
-#define atomic_read(v)	__raw_uncached_fetch_asm(&(v)->counter)
+#include <linux/linkage.h>
 
 asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
-
 asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	return __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	return __raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline void atomic_inc(volatile atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, 1);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, -1);
-}
-
-static inline void atomic_clear_mask(int mask, atomic_t *v)
-{
-	__raw_atomic_clear_asm(&v->counter, mask);
-}
-
-static inline void atomic_set_mask(int mask, atomic_t *v)
-{
-	__raw_atomic_set_asm(&v->counter, mask);
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#define __atomic_add_unless(v, a, u)				\
-({								\
-	int c, old;						\
-	c = atomic_read(v);					\
-	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-		c = old;					\
-	c;							\
-})
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
 
-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
+#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
 
+#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
+#define atomic_set_mask(m, v)   __raw_atomic_set_asm(&(v)->counter, m)
 
 #endif
 
+#include <asm-generic/atomic.h>
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/include/asm/bfin_serial.h linux-libre-3.2-gnu1/arch/blackfin/include/asm/bfin_serial.h
--- linux-libre-3.1-gnu1/arch/blackfin/include/asm/bfin_serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/include/asm/bfin_serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@ struct work_struct;
 struct bfin_serial_port {
 	struct uart_port port;
 	unsigned int old_status;
+	int tx_irq;
+	int rx_irq;
 	int status_irq;
 #ifndef BFIN_UART_BF54X_STYLE
 	unsigned int lsr;
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/include/asm/Kbuild linux-libre-3.2-gnu1/arch/blackfin/include/asm/Kbuild
--- linux-libre-3.1-gnu1/arch/blackfin/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@ generic-y += local64.h
 generic-y += local.h
 generic-y += mman.h
 generic-y += msgbuf.h
+generic-y += mutex.h
 generic-y += param.h
 generic-y += percpu.h
 generic-y += pgalloc.h
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/include/asm/mutex.h linux-libre-3.2-gnu1/arch/blackfin/include/asm/mutex.h
--- linux-libre-3.1-gnu1/arch/blackfin/include/asm/mutex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/include/asm/uaccess.h linux-libre-3.2-gnu1/arch/blackfin/include/asm/uaccess.h
--- linux-libre-3.1-gnu1/arch/blackfin/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -195,17 +195,17 @@ static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	if (access_ok(VERIFY_READ, from, n))
-		memcpy(to, from, n);
+		memcpy(to, (const void __force *)from, n);
 	else
 		return n;
 	return 0;
 }
 
 static inline unsigned long __must_check
-copy_to_user(void *to, const void __user *from, unsigned long n)
+copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
-		memcpy(to, from, n);
+		memcpy((void __force *)to, from, n);
 	else
 		return n;
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/Kconfig linux-libre-3.2-gnu1/arch/blackfin/Kconfig
--- linux-libre-3.1-gnu1/arch/blackfin/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -248,10 +248,6 @@ config HOTPLUG_CPU
 	depends on SMP && HOTPLUG
 	default y
 
-config HAVE_LEGACY_PER_CPU_AREA
-	def_bool y
-	depends on SMP
-
 config BF_REV_MIN
 	int
 	default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/dma-mapping.c linux-libre-3.2-gnu1/arch/blackfin/kernel/dma-mapping.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 
 static spinlock_t dma_page_lock;
 static unsigned long *dma_page;
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/kgdb_test.c linux-libre-3.2-gnu1/arch/blackfin/kernel/kgdb_test.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/kgdb_test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/kgdb_test.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,8 +50,7 @@ void kgdb_l2_test(void)
 
 #endif
 
-
-int kgdb_test(char *name, int len, int count, int z)
+noinline int kgdb_test(char *name, int len, int count, int z)
 {
 	pr_alert("kgdb name(%d): %s, %d, %d\n", len, name, count, z);
 	count = z;
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/Makefile linux-libre-3.2-gnu1/arch/blackfin/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,6 @@ obj-$(CONFIG_PERF_EVENTS)            +=
 
 # the kgdb test puts code into L2 and without linker
 # relaxation, we need to force long calls to/from it
-CFLAGS_kgdb_test.o := -mlong-calls -O0
+CFLAGS_kgdb_test.o := -mlong-calls
 
 obj-$(CONFIG_DEBUG_MMRS)             += debug-mmrs.o
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/perf_event.c linux-libre-3.2-gnu1/arch/blackfin/kernel/perf_event.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/perf_event.h>
 #include <asm/bfin_pfmon.h>
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/sys_bfin.c linux-libre-3.2-gnu1/arch/blackfin/kernel/sys_bfin.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/sys_bfin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/sys_bfin.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@ asmlinkage void *sys_dma_memcpy(void *de
 
 #if defined(CONFIG_FB) || defined(CONFIG_FB_MODULE)
 #include <linux/fb.h>
+#include <linux/export.h>
 unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
 	unsigned long len, unsigned long pgoff, unsigned long flags)
 {
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/time.c linux-libre-3.2-gnu1/arch/blackfin/kernel/time.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,6 @@
 
 static struct irqaction bfin_timer_irq = {
 	.name = "Blackfin Timer Tick",
-	.flags = IRQF_DISABLED
 };
 
 #if defined(CONFIG_IPIPE)
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/kernel/time-ts.c linux-libre-3.2-gnu1/arch/blackfin/kernel/time-ts.c
--- linux-libre-3.1-gnu1/arch/blackfin/kernel/time-ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/kernel/time-ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -188,8 +188,7 @@ irqreturn_t bfin_gptmr0_interrupt(int ir
 
 static struct irqaction gptmr0_irq = {
 	.name		= "Blackfin GPTimer0",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | \
-			  IRQF_IRQPOLL | IRQF_PERCPU,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
 	.handler	= bfin_gptmr0_interrupt,
 };
 
@@ -297,8 +296,7 @@ irqreturn_t bfin_coretmr_interrupt(int i
 
 static struct irqaction coretmr_irq = {
 	.name		= "Blackfin CoreTimer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | \
-			  IRQF_IRQPOLL | IRQF_PERCPU,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
 	.handler	= bfin_coretmr_interrupt,
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -372,8 +373,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -415,8 +421,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,8 +309,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -352,8 +357,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -380,8 +381,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -423,8 +429,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -539,8 +540,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -582,8 +588,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -417,8 +418,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -460,8 +466,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -710,8 +711,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -753,8 +759,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -495,8 +496,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -539,8 +545,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,8 +193,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,8 +221,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -292,8 +292,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/H8606.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/H8606.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/H8606.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/H8606.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,8 @@ static struct resource dm9000_resources[
 	[2] = {
 		.start	= IRQ_PF10,
 		.end	= IRQ_PF10,
-		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH),
+		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		           IORESOURCE_IRQ_SHAREABLE),
 	},
 };
 
@@ -237,8 +238,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,8 +151,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/stamp.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/stamp.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf533/boards/stamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf533/boards/stamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -298,8 +298,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
@@ -305,8 +306,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -366,8 +372,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -605,7 +616,7 @@ static struct platform_device bfin_mac_d
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,8 +307,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -349,8 +355,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -570,7 +581,7 @@ static struct platform_device bfin_mac_d
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -236,8 +237,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -280,8 +286,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end   = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end   = IRQ_UART1_RX+1,
+		.end   = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c	2012-01-04 18:55:44.000000000 -0500
@@ -240,8 +240,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -283,8 +288,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -100,6 +101,7 @@ static struct platform_device smc91x_dev
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
+#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_RMII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
@@ -308,8 +310,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -351,8 +358,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/stamp.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/stamp.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/stamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/stamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -962,10 +963,10 @@ static struct spi_board_info bfin_spi_bo
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
 	{
-		.modalias = "ad183x",
+		.modalias = "ad1836",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
@@ -984,9 +985,9 @@ static struct spi_board_info bfin_spi_bo
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADV80X_MODULE)
 	{
-		.modalias = "adav80x",
+		.modalias = "adav801",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
@@ -1566,8 +1567,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -1621,8 +1627,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -2101,7 +2112,7 @@ static struct i2c_board_info __initdata
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADAV80X_MODULE)
 	{
 		I2C_BOARD_INFO("adav803", 0x10),
 	},
@@ -2134,23 +2145,6 @@ static struct i2c_board_info __initdata
 	},
 #endif
 
-#if defined(CONFIG_AD7414) || defined(CONFIG_AD7414_MODULE)
-	{
-		I2C_BOARD_INFO("ad7414", 0x9),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-	},
-#endif
-
-#if defined(CONFIG_AD7416) || defined(CONFIG_AD7416_MODULE)
-	{
-		I2C_BOARD_INFO("ad7417", 0xb),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-		.platform_data = (void *)GPIO_PF4,
-	},
-#endif
-
 #if defined(CONFIG_ADE7854_I2C) || defined(CONFIG_ADE7854_I2C_MODULE)
 	{
 		I2C_BOARD_INFO("ade7854", 0x38),
@@ -2161,15 +2155,6 @@ static struct i2c_board_info __initdata
 	{
 		I2C_BOARD_INFO("adt75", 0x9),
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-	},
-#endif
-
-#if defined(CONFIG_ADT7408) || defined(CONFIG_ADT7408_MODULE)
-	{
-		I2C_BOARD_INFO("adt7408", 0x18),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 	},
 #endif
 
@@ -2178,7 +2163,6 @@ static struct i2c_board_info __initdata
 		I2C_BOARD_INFO("adt7410", 0x48),
 		/* CT critical temperature event. line 0 */
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 		.platform_data = (void *)&adt7410_platform_data,
 	},
 #endif
@@ -2187,7 +2171,6 @@ static struct i2c_board_info __initdata
 	{
 		I2C_BOARD_INFO("ad7291", 0x20),
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 	},
 #endif
 
@@ -2275,6 +2258,11 @@ static struct i2c_board_info __initdata
 		I2C_BOARD_INFO("adau1361", 0x38),
 	},
 #endif
+#if defined(CONFIG_SND_SOC_ADAU1701) || defined(CONFIG_SND_SOC_ADAU1701_MODULE)
+	{
+		I2C_BOARD_INFO("adau1701", 0x34),
+	},
+#endif
 #if defined(CONFIG_AD525X_DPOT) || defined(CONFIG_AD525X_DPOT_MODULE)
 	{
 		I2C_BOARD_INFO("ad5258", 0x18),
@@ -2388,7 +2376,7 @@ static struct platform_device bfin_sport
 #define PATA_INT	IRQ_PF5
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 1,
-	.irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_flags = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
@@ -2540,13 +2528,21 @@ static struct platform_device bfin_ac97_
 };
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
 static struct platform_device bfin_ad73311_codec_device = {
 	.name = "ad73311",
 	.id = -1,
 };
 #endif
 
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+static struct platform_device bfin_eval_adav801_device = {
+	.name = "bfin-eval-adav801",
+	.id = -1,
+};
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE)
 static struct platform_device bfin_i2s = {
 	.name = "bfin-i2s",
@@ -2661,6 +2657,20 @@ static struct platform_device iio_gpio_t
 };
 #endif
 
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+static struct platform_device bf5xx_adau1373_device = {
+	.name = "bfin-eval-adau1373",
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+static struct platform_device bf5xx_adau1701_device = {
+	.name = "bfin-eval-adau1701",
+};
+#endif
+
 static struct platform_device *stamp_devices[] __initdata = {
 
 	&bfin_dpmc,
@@ -2782,7 +2792,7 @@ static struct platform_device *stamp_dev
 	&bfin_ac97_pcm,
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
 	&bfin_ad73311_codec_device,
 #endif
 
@@ -2821,6 +2831,21 @@ static struct platform_device *stamp_dev
 	defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
 	&iio_gpio_trigger,
 #endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+	&bf5xx_adau1373_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+	&bf5xx_adau1701_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+	&bfin_eval_adav801_device,
+#endif
 };
 
 static int __init net2272_init(void)
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,8 +307,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -349,8 +355,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -572,7 +583,7 @@ static struct platform_device bfin_mac_d
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,8 +49,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -104,8 +109,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -147,8 +157,13 @@ static struct resource bfin_uart2_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c	2012-01-04 18:55:44.000000000 -0500
@@ -135,8 +135,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -178,8 +183,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -237,8 +247,13 @@ static struct resource bfin_uart2_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -280,8 +295,13 @@ static struct resource bfin_uart3_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART3_TX,
+		.end = IRQ_UART3_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART3_RX,
-		.end = IRQ_UART3_RX+1,
+		.end = IRQ_UART3_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -241,8 +241,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -284,8 +289,13 @@ static struct resource bfin_uart1_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -343,8 +353,13 @@ static struct resource bfin_uart2_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -386,8 +401,13 @@ static struct resource bfin_uart3_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART3_TX,
+		.end = IRQ_UART3_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART3_RX,
-		.end = IRQ_UART3_RX+1,
+		.end = IRQ_UART3_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,8 +203,13 @@ static struct resource bfin_uart0_resour
 	 .flags = IORESOURCE_MEM,
 	 },
 	{
+	 .start = IRQ_UART_TX,
+	 .end = IRQ_UART_TX,
+	 .flags = IORESOURCE_IRQ,
+	 },
+	{
 	 .start = IRQ_UART_RX,
-	 .end = IRQ_UART_RX + 1,
+	 .end = IRQ_UART_RX,
 	 .flags = IORESOURCE_IRQ,
 	 },
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c	2012-01-04 18:55:44.000000000 -0500
@@ -277,8 +277,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -348,7 +353,7 @@ static struct platform_device bfin_sir0_
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,8 +172,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/tepla.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/tepla.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/boards/tepla.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/boards/tepla.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,8 +51,13 @@ static struct resource bfin_uart0_resour
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/smp.c linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/smp.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-bf561/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-bf561/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,7 +114,7 @@ void __init platform_request_ipi(int irq
 	int ret;
 	const char *name = (irq == IRQ_SUPPLE_0) ? supple0 : supple1;
 
-	ret = request_irq(irq, handler, IRQF_DISABLED | IRQF_PERCPU, name, handler);
+	ret = request_irq(irq, handler, IRQF_PERCPU, name, handler);
 	if (ret)
 		panic("Cannot request %s for IPI service", name);
 }
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-common/cpufreq.c linux-libre-3.2-gnu1/arch/blackfin/mach-common/cpufreq.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-common/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-common/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mach-common/smp.c linux-libre-3.2-gnu1/arch/blackfin/mach-common/smp.c
--- linux-libre-3.1-gnu1/arch/blackfin/mach-common/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mach-common/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -295,10 +295,15 @@ EXPORT_SYMBOL_GPL(smp_call_function_sing
 
 void smp_send_reschedule(int cpu)
 {
+	cpumask_t callmap;
 	/* simply trigger an ipi */
 	if (cpu_is_offline(cpu))
 		return;
-	platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+
+	cpumask_clear(&callmap);
+	cpumask_set_cpu(cpu, &callmap);
+
+	smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
 
 	return;
 }
diff -druNp linux-libre-3.1-gnu1/arch/blackfin/mm/init.c linux-libre-3.2-gnu1/arch/blackfin/mm/init.c
--- linux-libre-3.1-gnu1/arch/blackfin/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/blackfin/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/swap.h>
 #include <linux/bootmem.h>
 #include <linux/uaccess.h>
+#include <linux/export.h>
 #include <asm/bfin-global.h>
 #include <asm/pda.h>
 #include <asm/cplbinit.h>
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v10/drivers/Kconfig linux-libre-3.2-gnu1/arch/cris/arch-v10/drivers/Kconfig
--- linux-libre-3.1-gnu1/arch/cris/arch-v10/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v10/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@ if ETRAX_ARCH_V10
 config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V10
-	select NET_ETHERNET
+	select ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v10/Kconfig linux-libre-3.2-gnu1/arch/cris/arch-v10/Kconfig
--- linux-libre-3.1-gnu1/arch/cris/arch-v10/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v10/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,8 @@ config ETRAX_PA_LEDS
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent.  It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on port PA.  Some products
 	  put the leds on PB or a memory-mapped latch (CSP0) instead.
 
@@ -34,8 +34,8 @@ config ETRAX_PB_LEDS
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent.  It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on port PB.  Some products
 	  put the leds on PA or a memory-mapped latch (CSP0) instead.
 
@@ -44,8 +44,8 @@ config ETRAX_CSP0_LEDS
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent. It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on a memory-mapped latch
 	  using chip select CSP0, this is mapped at 0x90000000.
 	  Some products put the leds on PA or PB instead.
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v10/kernel/kgdb.c linux-libre-3.2-gnu1/arch/cris/arch-v10/kernel/kgdb.c
--- linux-libre-3.1-gnu1/arch/cris/arch-v10/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v10/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -694,7 +694,7 @@ mem2hex(char *buf, unsigned char *mem, i
                 /* Valid mem address. */
                 for (i = 0; i < count; i++) {
                         ch = *mem++;
-			buf = pack_hex_byte(buf, ch);
+			buf = hex_byte_pack(buf, ch);
                 }
         }
         
@@ -868,7 +868,7 @@ stub_is_stopped(int sigval)
 	/* Send trap type (converted to signal) */
 
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/* Send register contents. We probably only need to send the
 	 * PC, frame pointer and stack pointer here. Other registers will be
@@ -881,7 +881,7 @@ stub_is_stopped(int sigval)
                 status = read_register (regno, &reg_cont);
                 
 		if (status == SUCCESS) {
-			ptr = pack_hex_byte(ptr, regno);
+			ptr = hex_byte_pack(ptr, regno);
                         *ptr++ = ':';
 
                         ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/Kconfig linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/Kconfig
--- linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@ if ETRAX_ARCH_V32
 config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V32
-	select NET_ETHERNET
+	select ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX FS built-in 10/100Mbit Ethernet
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/mach-a3/nandflash.c linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
--- linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@ struct mtd_info *__init crisv32_nand_fla
 	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
-	/* this->options = NAND_USE_FLASH_BBT; */
+	/* this->bbt_options = NAND_BBT_USE_FLASH; */
 
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/mach-fs/nandflash.c linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
--- linux-libre-3.1-gnu1/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,7 +154,7 @@ struct mtd_info *__init crisv32_nand_fla
 	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
-	/* this->options = NAND_USE_FLASH_BBT; */
+	/* this->bbt_options = NAND_BBT_USE_FLASH; */
 
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v32/kernel/kgdb.c linux-libre-3.2-gnu1/arch/cris/arch-v32/kernel/kgdb.c
--- linux-libre-3.1-gnu1/arch/cris/arch-v32/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v32/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -677,7 +677,7 @@ mem2hex(char *buf, unsigned char *mem, i
                 /* Valid mem address. */
 		for (i = 0; i < count; i++) {
 			ch = *mem++;
-			buf = pack_hex_byte(buf, ch);
+			buf = hex_byte_pack(buf, ch);
 		}
         }
         /* Terminate properly. */
@@ -695,7 +695,7 @@ mem2hex_nbo(char *buf, unsigned char *me
 	mem += count - 1;
 	for (i = 0; i < count; i++) {
 		ch = *mem--;
-		buf = pack_hex_byte(buf, ch);
+		buf = hex_byte_pack(buf, ch);
         }
 
         /* Terminate properly. */
@@ -880,7 +880,7 @@ stub_is_stopped(int sigval)
 	/* Send trap type (converted to signal) */
 
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	if (((reg.exs & 0xff00) >> 8) == 0xc) {
 
@@ -988,26 +988,26 @@ stub_is_stopped(int sigval)
 	}
 	/* Only send PC, frame and stack pointer. */
 	read_register(PC, &reg_cont);
-	ptr = pack_hex_byte(ptr, PC);
+	ptr = hex_byte_pack(ptr, PC);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]);
 	*ptr++ = ';';
 
 	read_register(R8, &reg_cont);
-	ptr = pack_hex_byte(ptr, R8);
+	ptr = hex_byte_pack(ptr, R8);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]);
 	*ptr++ = ';';
 
 	read_register(SP, &reg_cont);
-	ptr = pack_hex_byte(ptr, SP);
+	ptr = hex_byte_pack(ptr, SP);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]);
 	*ptr++ = ';';
 
 	/* Send ERP as well; this will save us an entire register fetch in some cases. */
         read_register(ERP, &reg_cont);
-	ptr = pack_hex_byte(ptr, ERP);
+	ptr = hex_byte_pack(ptr, ERP);
         *ptr++ = ':';
         ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]);
         *ptr++ = ';';
diff -druNp linux-libre-3.1-gnu1/arch/cris/arch-v32/lib/nand_init.S linux-libre-3.2-gnu1/arch/cris/arch-v32/lib/nand_init.S
--- linux-libre-3.1-gnu1/arch/cris/arch-v32/lib/nand_init.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/arch-v32/lib/nand_init.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,178 +0,0 @@
-##=============================================================================
-##
-##      nand_init.S
-##
-##      The bootrom copies data from the NAND flash to the internal RAM but
-##      due to a bug/feature we can only trust the 256 first bytes. So this
-##      code copies more data from NAND flash to internal RAM. Obvioulsy this
-##      code must fit in the first 256 bytes so alter with care.
-##
-##	Some notes about the bug/feature for future reference:
-##        The bootrom copies the first 127 KB from NAND flash to internal
-##        memory. The problem is that it does a bytewise copy. NAND flashes
-##        does autoincrement on the address so for a 16-bite device each
-##        read/write increases the address by two. So the copy loop in the
-##        bootrom will discard every second byte. This is solved by inserting
-##        zeroes in every second byte in the first erase block.
-##
-##        The bootrom also incorrectly assumes that it can read the flash
-##        linear with only one read command but the flash will actually
-##        switch between normal area and spare area if you do that so we
-##        can't trust more than the first 256 bytes.
-##
-##=============================================================================
-
-#include <arch/hwregs/asm/reg_map_asm.h>
-#include <arch/hwregs/asm/gio_defs_asm.h>
-#include <arch/hwregs/asm/pinmux_defs_asm.h>
-#include <arch/hwregs/asm/bif_core_defs_asm.h>
-#include <arch/hwregs/asm/config_defs_asm.h>
-
-;; There are 8-bit NAND flashes and 16-bit NAND flashes.
-;; We need to treat them slightly different.
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-#define PAGE_SIZE 256
-#else
-#error 2
-#define PAGE_SIZE 512
-#endif
-#define ERASE_BLOCK 16384
-
-;; GPIO pins connected to NAND flash
-#define CE 4
-#define CLE 5
-#define ALE 6
-#define BY 7
-
-;; Address space for NAND flash
-#define NAND_RD_ADDR 0x90000000
-#define NAND_WR_ADDR 0x94000000
-
-#define READ_CMD 0x00
-
-;; Readability macros
-#define CSP_MASK \
-	REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \
-	REG_MASK(bif_core, rw_grp3_cfg, gated_csp1)
-#define CSP_VAL \
-	REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \
-	REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr)
-
-;;----------------------------------------------------------------------------
-;; Macros to set/clear GPIO bits
-
-.macro SET x
-	or.b   (1<<\x),$r9
-	move.d $r9, [$r2]
-.endm
-
-.macro CLR x
-	and.b  ~(1<<\x),$r9
-	move.d $r9, [$r2]
-.endm
-
-;;----------------------------------------------------------------------------
-
-nand_boot:
-	;; Check if nand boot was selected
-	move.d REG_ADDR(config, regi_config, r_bootsel), $r0
-	move.d [$r0], $r0
-	and.d  REG_MASK(config, r_bootsel, boot_mode), $r0
-	cmp.d  REG_STATE(config, r_bootsel, boot_mode, nand), $r0
-	bne normal_boot ; No NAND boot
-	nop
-
-copy_nand_to_ram:
-	;; copy_nand_to_ram
-	;; Arguments
-	;;   r10 - destination
-	;;   r11 - source offset
-	;;   r12 - size
-	;;   r13 - Address to jump to after completion
-	;; Note : r10-r12 are clobbered on return
-	;; Registers used:
-	;;   r0 - NAND_RD_ADDR
-	;;   r1 - NAND_WR_ADDR
-	;;   r2 - reg_gio_rw_pa_dout
-	;;   r3 - reg_gio_r_pa_din
-	;;   r4 - tmp
-	;;   r5 - byte counter within a page
-	;;   r6 - reg_pinmux_rw_pa
-	;;   r7 - reg_gio_rw_pa_oe
-	;;   r8 - reg_bif_core_rw_grp3_cfg
-	;;   r9 - reg_gio_rw_pa_dout shadow
-	move.d 0x90000000, $r0
-	move.d 0x94000000, $r1
-	move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2
-	move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3
-	move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6
-	move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7
-	move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8
-
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	lsrq	1, $r11
-#endif
-	;; Set up GPIO
-	move.d [$r2], $r9
-	move.d [$r7], $r4
-	or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4
-	move.d $r4, [$r7]
-
-	;; Set up bif
-	move.d [$r8], $r4
-	and.d CSP_MASK, $r4
-	or.d CSP_VAL, $r4
-	move.d $r4, [$r8]
-
-1:	;; Copy one page
-	CLR CE
-	SET CLE
-	moveq	READ_CMD, $r4
-	move.b	$r4, [$r1]
-	moveq	20, $r4
-2:	bne	2b
-	subq	1, $r4
-	CLR CLE
-	SET ALE
-	clear.w [$r1] 		; Column address = 0
-	move.d	$r11, $r4
-	lsrq	8, $r4
-	move.b	$r4, [$r1]	; Row address
-	lsrq	8, $r4
-	move.b	$r4, [$r1]	; Row address
-	moveq	20, $r4
-2:	bne	2b
-	subq	1, $r4
-	CLR ALE
-2:	move.d	[$r3], $r4
-	and.d	1 << BY, $r4
-	beq 2b
-	movu.w  PAGE_SIZE, $r5
-2:	; Copy one byte/word
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	move.w  [$r0], $r4
-#else
-	move.b  [$r0], $r4
-#endif
-	subq	1, $r5
-	bne	2b
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	move.w  $r4, [$r10+]
-	subu.w	PAGE_SIZE*2, $r12
-#else
-	move.b  $r4, [$r10+]
-	subu.w	PAGE_SIZE, $r12
-#endif
-	bpl	1b
-	addu.w	PAGE_SIZE, $r11
-
-	;; End of copy
-	jump	$r13
-	nop
-
-	;; This will warn if the code above is too large. If you consider
-	;; to remove this you don't understand the bug/feature.
-	.org 256
-	.org ERASE_BLOCK
-
-normal_boot:
diff -druNp linux-libre-3.1-gnu1/arch/cris/Kconfig linux-libre-3.2-gnu1/arch/cris/Kconfig
--- linux-libre-3.1-gnu1/arch/cris/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/cris/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -282,8 +282,8 @@ config ETRAX_RTC
 	  Enables drivers for the Real-Time Clock battery-backed chips on
 	  some products. The kernel reads the time when booting, and
 	  the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
-	  rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
-	  device.  You can check the time with cat /proc/rtc, but
+	  rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the
+	  /dev/rtc device.  You can check the time with cat /proc/rtc, but
 	  normal time reading should be done using libc function time and
 	  friends.
 
diff -druNp linux-libre-3.1-gnu1/arch/frv/kernel/gdb-stub.c linux-libre-3.2-gnu1/arch/frv/kernel/gdb-stub.c
--- linux-libre-3.1-gnu1/arch/frv/kernel/gdb-stub.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/frv/kernel/gdb-stub.c	2012-01-04 18:55:44.000000000 -0500
@@ -672,7 +672,7 @@ static unsigned char *mem2hex(const void
 	if ((uint32_t)mem&1 && count>=1) {
 		if (!gdbstub_read_byte(mem,ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 		mem++;
 		count--;
 	}
@@ -680,8 +680,8 @@ static unsigned char *mem2hex(const void
 	if ((uint32_t)mem&3 && count>=2) {
 		if (!gdbstub_read_word(mem,(uint16_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -689,10 +689,10 @@ static unsigned char *mem2hex(const void
 	while (count>=4) {
 		if (!gdbstub_read_dword(mem,(uint32_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
-		buf = pack_hex_byte(buf, ch[2]);
-		buf = pack_hex_byte(buf, ch[3]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[2]);
+		buf = hex_byte_pack(buf, ch[3]);
 		mem += 4;
 		count -= 4;
 	}
@@ -700,8 +700,8 @@ static unsigned char *mem2hex(const void
 	if (count>=2) {
 		if (!gdbstub_read_word(mem,(uint16_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -709,7 +709,7 @@ static unsigned char *mem2hex(const void
 	if (count>=1) {
 		if (!gdbstub_read_byte(mem,ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 	}
 
 	*buf = 0;
@@ -1498,21 +1498,21 @@ void gdbstub(int sigval)
 		ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
 
 		hx = hex_asc_hi(brr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1526,10 +1526,10 @@ void gdbstub(int sigval)
 
 	/* Send trap type (converted to signal) */
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/* Send Error PC */
-	ptr = pack_hex_byte(ptr, GDB_REG_PC);
+	ptr = hex_byte_pack(ptr, GDB_REG_PC);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1537,7 +1537,7 @@ void gdbstub(int sigval)
 	/*
 	 * Send frame pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REG_FP);
+	ptr = hex_byte_pack(ptr, GDB_REG_FP);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1545,7 +1545,7 @@ void gdbstub(int sigval)
 	/*
 	 * Send stack pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REG_SP);
+	ptr = hex_byte_pack(ptr, GDB_REG_SP);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
 	*ptr++ = ';';
diff -druNp linux-libre-3.1-gnu1/arch/h8300/include/asm/gpio.h linux-libre-3.2-gnu1/arch/h8300/include/asm/gpio.h
--- linux-libre-3.1-gnu1/arch/h8300/include/asm/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/h8300/include/asm/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-#ifndef _H8300_GPIO_H
-#define _H8300_GPIO_H
-
-#define H8300_GPIO_P1 0
-#define H8300_GPIO_P2 1
-#define H8300_GPIO_P3 2
-#define H8300_GPIO_P4 3
-#define H8300_GPIO_P5 4
-#define H8300_GPIO_P6 5
-#define H8300_GPIO_P7 6
-#define H8300_GPIO_P8 7
-#define H8300_GPIO_P9 8
-#define H8300_GPIO_PA 9
-#define H8300_GPIO_PB 10
-#define H8300_GPIO_PC 11
-#define H8300_GPIO_PD 12
-#define H8300_GPIO_PE 13
-#define H8300_GPIO_PF 14
-#define H8300_GPIO_PG 15
-#define H8300_GPIO_PH 16
-
-#define H8300_GPIO_B7 0x80
-#define H8300_GPIO_B6 0x40
-#define H8300_GPIO_B5 0x20
-#define H8300_GPIO_B4 0x10
-#define H8300_GPIO_B3 0x08
-#define H8300_GPIO_B2 0x04
-#define H8300_GPIO_B1 0x02
-#define H8300_GPIO_B0 0x01
-
-#define H8300_GPIO_INPUT 0
-#define H8300_GPIO_OUTPUT 1
-
-#define H8300_GPIO_RESERVE(port, bits) \
-        h8300_reserved_gpio(port, bits)
-
-#define H8300_GPIO_FREE(port, bits) \
-        h8300_free_gpio(port, bits)
-
-#define H8300_GPIO_DDR(port, bit, dir) \
-        h8300_set_gpio_dir(((port) << 8) | (bit), dir)
-
-#define H8300_GPIO_GETDIR(port, bit) \
-        h8300_get_gpio_dir(((port) << 8) | (bit))
-
-extern int h8300_reserved_gpio(int port, int bits);
-extern int h8300_free_gpio(int port, int bits);
-extern int h8300_set_gpio_dir(int port_bit, int dir);
-extern int h8300_get_gpio_dir(int port_bit);
-extern int h8300_init_gpio(void);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/h8300/include/asm/gpio-internal.h linux-libre-3.2-gnu1/arch/h8300/include/asm/gpio-internal.h
--- linux-libre-3.1-gnu1/arch/h8300/include/asm/gpio-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/h8300/include/asm/gpio-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+#ifndef _H8300_GPIO_H
+#define _H8300_GPIO_H
+
+#define H8300_GPIO_P1 0
+#define H8300_GPIO_P2 1
+#define H8300_GPIO_P3 2
+#define H8300_GPIO_P4 3
+#define H8300_GPIO_P5 4
+#define H8300_GPIO_P6 5
+#define H8300_GPIO_P7 6
+#define H8300_GPIO_P8 7
+#define H8300_GPIO_P9 8
+#define H8300_GPIO_PA 9
+#define H8300_GPIO_PB 10
+#define H8300_GPIO_PC 11
+#define H8300_GPIO_PD 12
+#define H8300_GPIO_PE 13
+#define H8300_GPIO_PF 14
+#define H8300_GPIO_PG 15
+#define H8300_GPIO_PH 16
+
+#define H8300_GPIO_B7 0x80
+#define H8300_GPIO_B6 0x40
+#define H8300_GPIO_B5 0x20
+#define H8300_GPIO_B4 0x10
+#define H8300_GPIO_B3 0x08
+#define H8300_GPIO_B2 0x04
+#define H8300_GPIO_B1 0x02
+#define H8300_GPIO_B0 0x01
+
+#define H8300_GPIO_INPUT 0
+#define H8300_GPIO_OUTPUT 1
+
+#define H8300_GPIO_RESERVE(port, bits) \
+        h8300_reserved_gpio(port, bits)
+
+#define H8300_GPIO_FREE(port, bits) \
+        h8300_free_gpio(port, bits)
+
+#define H8300_GPIO_DDR(port, bit, dir) \
+        h8300_set_gpio_dir(((port) << 8) | (bit), dir)
+
+#define H8300_GPIO_GETDIR(port, bit) \
+        h8300_get_gpio_dir(((port) << 8) | (bit))
+
+extern int h8300_reserved_gpio(int port, int bits);
+extern int h8300_free_gpio(int port, int bits);
+extern int h8300_set_gpio_dir(int port_bit, int dir);
+extern int h8300_get_gpio_dir(int port_bit);
+extern int h8300_init_gpio(void);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/h8300/Kconfig linux-libre-3.2-gnu1/arch/h8300/Kconfig
--- linux-libre-3.1-gnu1/arch/h8300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/h8300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,7 @@ config VT_CONSOLE
 
 config HW_CONSOLE
 	bool
-	depends on VT && !S390 && !UM
+	depends on VT
 	default y
 
 comment "Unix98 PTY support"
@@ -195,7 +195,7 @@ config UNIX98_PTYS
 
 source "drivers/char/pcmcia/Kconfig"
 
-source "drivers/serial/Kconfig"
+source "drivers/tty/serial/Kconfig"
 
 source "drivers/i2c/Kconfig"
 
diff -druNp linux-libre-3.1-gnu1/arch/h8300/platform/h8300h/irq.c linux-libre-3.2-gnu1/arch/h8300/platform/h8300h/irq.c
--- linux-libre-3.1-gnu1/arch/h8300/platform/h8300h/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/h8300/platform/h8300h/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs306x.h>
 
 const int __initdata h8300_saved_vectors[] = {
diff -druNp linux-libre-3.1-gnu1/arch/h8300/platform/h8s/irq.c linux-libre-3.2-gnu1/arch/h8300/platform/h8s/irq.c
--- linux-libre-3.1-gnu1/arch/h8300/platform/h8s/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/h8300/platform/h8s/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs267x.h>
 
 /* saved vector list */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/configs/comet_defconfig linux-libre-3.2-gnu1/arch/hexagon/configs/comet_defconfig
--- linux-libre-3.1-gnu1/arch/hexagon/configs/comet_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/configs/comet_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,85 @@
+CONFIG_SMP=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_HZ_100=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="hexagon-"
+CONFIG_LOCALVERSION="-smp"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_BITBANG=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=y
+CONFIG_FRAME_WARN=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/asm-offsets.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/asm-offsets.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/asm-offsets.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/asm-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/atomic.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/atomic.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/atomic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,164 @@
+/*
+ * Atomic operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <linux/types.h>
+
+#define ATOMIC_INIT(i)		{ (i) }
+#define atomic_set(v, i)	((v)->counter = (i))
+
+/**
+ * atomic_read - reads a word, atomically
+ * @v: pointer to atomic value
+ *
+ * Assumes all word reads on our architecture are atomic.
+ */
+#define atomic_read(v)		((v)->counter)
+
+/**
+ * atomic_xchg - atomic
+ * @v: pointer to memory to change
+ * @new: new value (technically passed in a register -- see xchg)
+ */
+#define atomic_xchg(v, new)	(xchg(&((v)->counter), (new)))
+
+
+/**
+ * atomic_cmpxchg - atomic compare-and-exchange values
+ * @v: pointer to value to change
+ * @old:  desired old value to match
+ * @new:  new value to put in
+ *
+ * Parameters are then pointer, value-in-register, value-in-register,
+ * and the output is the old value.
+ *
+ * Apparently this is complicated for archs that don't support
+ * the memw_locked like we do (or it's broken or whatever).
+ *
+ * Kind of the lynchpin of the rest of the generically defined routines.
+ * Remember V2 had that bug with dotnew predicate set by memw_locked.
+ *
+ * "old" is "expected" old val, __oldval is actual old value
+ */
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	int __oldval;
+
+	asm volatile(
+		"1:	%0 = memw_locked(%1);\n"
+		"	{ P0 = cmp.eq(%0,%2);\n"
+		"	  if (!P0.new) jump:nt 2f; }\n"
+		"	memw_locked(%1,P0) = %3;\n"
+		"	if (!P0) jump 1b;\n"
+		"2:\n"
+		: "=&r" (__oldval)
+		: "r" (&v->counter), "r" (old), "r" (new)
+		: "memory", "p0"
+	);
+
+	return __oldval;
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	int output;
+
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = add(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0;\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+
+}
+
+#define atomic_add(i, v) atomic_add_return(i, (v))
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	int output;
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = sub(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_sub(i, v) atomic_sub_return(i, (v))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer to value
+ * @a: amount to add
+ * @u: unless value is equal to u
+ *
+ * Returns 1 if the add happened, 0 if it didn't.
+ */
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int output, __oldval;
+	asm volatile(
+		"1:	%0 = memw_locked(%2);"
+		"	{"
+		"		p3 = cmp.eq(%0, %4);"
+		"		if (p3.new) jump:nt 2f;"
+		"		%0 = add(%0, %3);"
+		"		%1 = #0;"
+		"	}"
+		"	memw_locked(%2, p3) = %0;"
+		"	{"
+		"		if !p3 jump 1b;"
+		"		%1 = #1;"
+		"	}"
+		"2:"
+		: "=&r" (__oldval), "=&r" (output)
+		: "r" (v), "r" (a), "r" (u)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_inc(v) atomic_add(1, (v))
+#define atomic_dec(v) atomic_sub(1, (v))
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
+#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
+
+
+#define atomic_inc_return(v) (atomic_add_return(1, v))
+#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/bitops.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/bitops.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/bitops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Bit operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BITOPS_H
+#define _ASM_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef __KERNEL__
+
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/*
+ * The offset calculations for these are based on BITS_PER_LONG == 32
+ * (i.e. I get to shift by #5-2 (32 bits per long, 4 bytes per access),
+ * mask by 0x0000001F)
+ *
+ * Typically, R10 is clobbered for address, R11 bit nr, and R12 is temp
+ */
+
+/**
+ * test_and_clear_bit - clear a bit and return its old value
+ * @nr:  bit number to clear
+ * @addr:  pointer to memory
+ */
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+}
+
+/**
+ * test_and_set_bit - set a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+
+	return oldval;
+
+}
+
+/**
+ * test_and_change_bit - toggle a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+
+}
+
+/*
+ * Atomic, but doesn't care about the return value.
+ * Rewrite later to save a cycle or two.
+ */
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void set_bit(int nr, volatile void *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+
+/*
+ * These are allowed to be non-atomic.  In fact the generic flavors are
+ * in non-atomic.h.  Would it be better to use intrinsics for this?
+ *
+ * OK, writes in our architecture do not invalidate LL/SC, so this has to
+ * be atomic, particularly for things like slab_lock and slab_unlock.
+ *
+ */
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+/*  Apparently, at least some of these are allowed to be non-atomic  */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_clear_bit(nr, addr);
+}
+
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_set_bit(nr, addr);
+}
+
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_change_bit(nr, addr);
+}
+
+static inline int __test_bit(int nr, const volatile unsigned long *addr)
+{
+	int retval;
+
+	asm volatile(
+	"{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+	: "=&r" (retval)
+	: "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+	: "p0"
+	);
+
+	return retval;
+}
+
+#define test_bit(nr, addr) __test_bit(nr, addr)
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline long ffz(int x)
+{
+	int r;
+
+	asm("%0 = ct1(%1);\n"
+		: "=&r" (r)
+		: "r" (x));
+	return r;
+}
+
+/*
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline long fls(int x)
+{
+	int r;
+
+	asm("{ %0 = cl0(%1);}\n"
+		"%0 = sub(#32,%0);\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline long ffs(int x)
+{
+	int r;
+
+	asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
+		"{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ *
+ * bits_per_long assumed to be 32
+ * numbering starts at 0 I think (instead of 1 like ffs)
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+	int num;
+
+	asm("%0 = ct0(%1);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+/*
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ * bits_per_long assumed to be 32
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+	int num;
+
+	asm("%0 = cl0(%1);\n"
+		"%0 = sub(#31,%0);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/bitsperlong.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/bitsperlong.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/bitsperlong.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_HEXAGON_BITSPERLONG_H
+#define __ASM_HEXAGON_BITSPERLONG_H
+
+#define __BITS_PER_LONG 32
+
+#include <asm-generic/bitsperlong.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/byteorder.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/byteorder.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/byteorder.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/byteorder.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/cacheflush.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/cacheflush.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/cacheflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/cacheflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Cache flush operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <asm/string.h>
+#include <asm-generic/cacheflush.h>
+
+/* Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
+ *  - flush_icache_range(start, end) flush a range of instructions
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ *  Need to doublecheck which one is really needed for ptrace stuff to work.
+ */
+#define LINESIZE	32
+#define LINEBITS	5
+
+/*
+ * Flush Dcache range through current map.
+ */
+extern void flush_dcache_range(unsigned long start, unsigned long end);
+
+/*
+ * Flush Icache range through current map.
+ */
+#undef flush_icache_range
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
+/*
+ * Memory-management related flushes are there to ensure in non-physically
+ * indexed cache schemes that stale lines belonging to a given ASID aren't
+ * in the cache to confuse things.  The prototype Hexagon Virtual Machine
+ * only uses a single ASID for all user-mode maps, which should
+ * mean that they aren't necessary.  A brute-force, flush-everything
+ * implementation, with the name xxxxx_hexagon() is present in
+ * arch/hexagon/mm/cache.c, but let's not wire it up until we know
+ * it is needed.
+ */
+extern void flush_cache_all_hexagon(void);
+
+/*
+ * This may or may not ever have to be non-null, depending on the
+ * virtual machine MMU.  For a native kernel, it's definitiely  a no-op
+ *
+ * This is also the place where deferred cache coherency stuff seems
+ * to happen, classically...  but instead we do it like ia64 and
+ * clean the cache when the PTE is set.
+ *
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+					unsigned long address, pte_t *ptep)
+{
+	/*  generic_ptrace_pokedata doesn't wind up here, does it?  */
+}
+
+#undef copy_to_user_page
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+					     struct page *page,
+					     unsigned long vaddr,
+					     void *dst, void *src, int len)
+{
+	memcpy(dst, src, len);
+	if (vma->vm_flags & VM_EXEC) {
+		flush_icache_range((unsigned long) dst,
+		(unsigned long) dst + len);
+	}
+}
+
+
+extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
+extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/cache.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/cache.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/cache.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/cache.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Cache definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+/* Bytes per L1 cache line */
+#define L1_CACHE_SHIFT		(5)
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+#define __cacheline_aligned	__aligned(L1_CACHE_BYTES)
+#define ____cacheline_aligned	__aligned(L1_CACHE_BYTES)
+
+/* See http://kerneltrap.org/node/15100  */
+#define __read_mostly
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/checksum.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/checksum.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/checksum.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_CHECKSUM_H
+
+#define do_csum	do_csum
+unsigned int do_csum(const void *voidptr, int len);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+#define csum_partial_copy_nocheck csum_partial_copy_nocheck
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					int len, __wsum sum);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#define csum_tcpudp_magic csum_tcpudp_magic
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#include <asm-generic/checksum.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/delay.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/delay.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/delay.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/delay.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+#include <asm/param.h>
+
+extern void __udelay(unsigned long usecs);
+
+#define udelay(usecs) __udelay((usecs))
+
+#endif /* _ASM_DELAY_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/dma.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/dma.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>
+
+#define MAX_DMA_CHANNELS 1
+#define MAX_DMA_ADDRESS  (PAGE_OFFSET)
+
+extern size_t hexagon_coherent_pool_size;
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/dma-mapping.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * DMA operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dma-attrs.h>
+#include <asm/io.h>
+
+struct device;
+extern int bad_dma_address;
+
+extern struct dma_map_ops *dma_ops;
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	if (unlikely(dev == NULL))
+		return NULL;
+
+	return dma_ops;
+}
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+			   enum dma_data_direction direction);
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops->mapping_error)
+		return dma_ops->mapping_error(dev, dma_addr);
+
+	return (dma_addr == bad_dma_address);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *ret;
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	BUG_ON(!dma_ops);
+
+	ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+
+	debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+	return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	BUG_ON(!dma_ops);
+
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+
+	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/elf.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/elf.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,229 @@
+/*
+ * ELF definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_ELF_H
+#define __ASM_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/*
+ * This should really be in linux/elf-em.h.
+ */
+#define EM_HEXAGON	164   /* QUALCOMM Hexagon */
+
+struct elf32_hdr;
+
+/*
+ * ELF header e_flags defines.
+ */
+
+/*  should have stuff like "CPU type" and maybe "ABI version", etc  */
+
+/* Hexagon relocations */
+  /* V2 */
+#define R_HEXAGON_NONE           0
+#define R_HEXAGON_B22_PCREL      1
+#define R_HEXAGON_B15_PCREL      2
+#define R_HEXAGON_B7_PCREL       3
+#define R_HEXAGON_LO16           4
+#define R_HEXAGON_HI16           5
+#define R_HEXAGON_32             6
+#define R_HEXAGON_16             7
+#define R_HEXAGON_8              8
+#define R_HEXAGON_GPREL16_0      9
+#define R_HEXAGON_GPREL16_1     10
+#define R_HEXAGON_GPREL16_2     11
+#define R_HEXAGON_GPREL16_3     12
+#define R_HEXAGON_HL16          13
+  /* V3 */
+#define R_HEXAGON_B13_PCREL     14
+  /* V4 */
+#define R_HEXAGON_B9_PCREL      15
+  /* V4 (extenders) */
+#define R_HEXAGON_B32_PCREL_X   16
+#define R_HEXAGON_32_6_X        17
+  /* V4 (extended) */
+#define R_HEXAGON_B22_PCREL_X   18
+#define R_HEXAGON_B15_PCREL_X   19
+#define R_HEXAGON_B13_PCREL_X   20
+#define R_HEXAGON_B9_PCREL_X    21
+#define R_HEXAGON_B7_PCREL_X    22
+#define R_HEXAGON_16_X          23
+#define R_HEXAGON_12_X          24
+#define R_HEXAGON_11_X          25
+#define R_HEXAGON_10_X          26
+#define R_HEXAGON_9_X           27
+#define R_HEXAGON_8_X           28
+#define R_HEXAGON_7_X           29
+#define R_HEXAGON_6_X           30
+  /* V2 PIC */
+#define R_HEXAGON_32_PCREL      31
+#define R_HEXAGON_COPY          32
+#define R_HEXAGON_GLOB_DAT      33
+#define R_HEXAGON_JMP_SLOT      34
+#define R_HEXAGON_RELATIVE      35
+#define R_HEXAGON_PLT_B22_PCREL 36
+#define R_HEXAGON_GOTOFF_LO16   37
+#define R_HEXAGON_GOTOFF_HI16   38
+#define R_HEXAGON_GOTOFF_32     39
+#define R_HEXAGON_GOT_LO16      40
+#define R_HEXAGON_GOT_HI16      41
+#define R_HEXAGON_GOT_32        42
+#define R_HEXAGON_GOT_16        43
+
+/*
+ * ELF register definitions..
+ */
+typedef unsigned long elf_greg_t;
+
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t)/sizeof(unsigned long))
+
+/*  Placeholder  */
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * Bypass the whole "regsets" thing for now and use the define.
+ */
+
+#define ELF_CORE_COPY_REGS(DEST, REGS)	\
+do {					\
+	DEST.r0 = REGS->r00;		\
+	DEST.r1 = REGS->r01;		\
+	DEST.r2 = REGS->r02;		\
+	DEST.r3 = REGS->r03;		\
+	DEST.r4 = REGS->r04;		\
+	DEST.r5 = REGS->r05;		\
+	DEST.r6 = REGS->r06;		\
+	DEST.r7 = REGS->r07;		\
+	DEST.r8 = REGS->r08;		\
+	DEST.r9 = REGS->r09;		\
+	DEST.r10 = REGS->r10;		\
+	DEST.r11 = REGS->r11;		\
+	DEST.r12 = REGS->r12;		\
+	DEST.r13 = REGS->r13;		\
+	DEST.r14 = REGS->r14;		\
+	DEST.r15 = REGS->r15;		\
+	DEST.r16 = REGS->r16;		\
+	DEST.r17 = REGS->r17;		\
+	DEST.r18 = REGS->r18;		\
+	DEST.r19 = REGS->r19;		\
+	DEST.r20 = REGS->r20;		\
+	DEST.r21 = REGS->r21;		\
+	DEST.r22 = REGS->r22;		\
+	DEST.r23 = REGS->r23;		\
+	DEST.r24 = REGS->r24;		\
+	DEST.r25 = REGS->r25;		\
+	DEST.r26 = REGS->r26;		\
+	DEST.r27 = REGS->r27;		\
+	DEST.r28 = REGS->r28;		\
+	DEST.r29 = pt_psp(REGS);	\
+	DEST.r30 = REGS->r30;		\
+	DEST.r31 = REGS->r31;		\
+	DEST.sa0 = REGS->sa0;		\
+	DEST.lc0 = REGS->lc0;		\
+	DEST.sa1 = REGS->sa1;		\
+	DEST.lc1 = REGS->lc1;		\
+	DEST.m0 = REGS->m0;		\
+	DEST.m1 = REGS->m1;		\
+	DEST.usr = REGS->usr;		\
+	DEST.p3_0 = REGS->preds;	\
+	DEST.gp = REGS->gp;		\
+	DEST.ugp = REGS->ugp;		\
+	DEST.pc = pt_elr(REGS);	\
+	DEST.cause = pt_cause(REGS);	\
+	DEST.badva = pt_badva(REGS);	\
+} while (0);
+
+
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ * Checks the machine and ABI type.
+ */
+#define elf_check_arch(hdr)	((hdr)->e_machine == EM_HEXAGON)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_HEXAGON
+
+#ifdef CONFIG_HEXAGON_ARCH_V2
+#define ELF_CORE_EFLAGS 0x1
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V3
+#define ELF_CORE_EFLAGS 0x2
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V4
+#define ELF_CORE_EFLAGS 0x3
+#endif
+
+/*
+ * Some architectures have ld.so set up a pointer to a function
+ * to be registered using atexit, to facilitate cleanup.  So that
+ * static executables will be well-behaved, we would null the register
+ * in question here, in the pt_regs structure passed.  For now,
+ * leave it a null macro.
+ */
+#define ELF_PLAT_INIT(regs, load_addr) do { } while (0)
+
+#define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
+
+/* Hrm is this going to cause problems for changing PAGE_SIZE?  */
+#define ELF_EXEC_PAGESIZE	4096
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE         0x08000000UL
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(0)
+
+/*
+ * 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.
+ */
+#define ELF_PLATFORM  (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#endif
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+				       int uses_interp);
+
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/fixmap.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/fixmap.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/fixmap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/fixmap.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * Fixmap support for Hexagon - enough to support highmem features
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * A lot of the fixmap info is already in mem-layout.h
+ */
+#include <asm/mem-layout.h>
+
+/*
+ * Full fixmap support involves set_fixmap() functions, but
+ * these may not be needed if all we're after is an area for
+ * highmem kernel mappings.
+ */
+#define	__fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define	__virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/**
+ * fix_to_virt -- "index to address" translation.
+ *
+ * If anyone tries to use the idx directly without translation,
+ * we catch the bug with a NULL-deference kernel oops. Illegal
+ * ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * This branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
+	if (idx >= __end_of_fixed_addresses)
+		__this_fixmap_does_not_exist();
+
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
+				(vaddr)), (vaddr)), (vaddr))
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/fpu.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/fpu.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/fpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/fpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+/*
+ * If the FPU is used inside the kernel,
+ * kernel_fpu_end() will be defined here.
+ */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/futex.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/futex.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/futex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/futex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,137 @@
+#ifndef _ASM_HEXAGON_FUTEX_H
+#define _ASM_HEXAGON_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+/* XXX TODO-- need to add sync barriers! */
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+	__asm__ __volatile( \
+	"1: %0 = memw_locked(%3);\n" \
+	    /* For example: %1 = %4 */ \
+	    insn \
+	"2: memw_locked(%3,p2) = %1;\n" \
+	"   if !p2 jump 1b;\n" \
+	"   %1 = #0;\n" \
+	"3:\n" \
+	".section .fixup,\"ax\"\n" \
+	"4: %1 = #%5;\n" \
+	"   jump 3b\n" \
+	".previous\n" \
+	".section __ex_table,\"a\"\n" \
+	".long 1b,4b,2b,4b\n" \
+	".previous\n" \
+	: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
+	: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+	: "p2", "memory")
+
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
+				  oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ:
+			ret = (oldval == cmparg);
+			break;
+		case FUTEX_OP_CMP_NE:
+			ret = (oldval != cmparg);
+			break;
+		case FUTEX_OP_CMP_LT:
+			ret = (oldval < cmparg);
+			break;
+		case FUTEX_OP_CMP_GE:
+			ret = (oldval >= cmparg);
+			break;
+		case FUTEX_OP_CMP_LE:
+			ret = (oldval <= cmparg);
+			break;
+		case FUTEX_OP_CMP_GT:
+			ret = (oldval > cmparg);
+			break;
+		default:
+			ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
+			      u32 newval)
+{
+	int prev;
+	int ret;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	__asm__ __volatile__ (
+	"1: %1 = memw_locked(%3)\n"
+	"   {\n"
+	"      p2 = cmp.eq(%1,%4)\n"
+	"      if !p2.new jump:NT 3f\n"
+	"   }\n"
+	"2: memw_locked(%3,p2) = %5\n"
+	"   if !p2 jump 1b\n"
+	"3:\n"
+	".section .fixup,\"ax\"\n"
+	"4: %0 = #%6\n"
+	"   jump 3b\n"
+	".previous\n"
+	".section __ex_table,\"a\"\n"
+	".long 1b,4b,2b,4b\n"
+	".previous\n"
+	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+	: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
+	: "p2", "memory");
+
+	*uval = prev;
+	return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_HEXAGON_FUTEX_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/hexagon_vm.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/hexagon_vm.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/hexagon_vm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/hexagon_vm.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,281 @@
+/*
+ * Declarations for to Hexagon Virtal Machine.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_HEXAGON_VM_H
+#define ASM_HEXAGON_VM_H
+
+/*
+ * In principle, a Linux kernel for the VM could
+ * selectively define the virtual instructions
+ * as inline assembler macros, but for a first pass,
+ * we'll use subroutines for both the VM and the native
+ * kernels.  It's costing a subroutine call/return,
+ * but it makes for a single set of entry points
+ * for tracing/debugging.
+ */
+
+/*
+ * Lets make this stuff visible only if configured,
+ * so we can unconditionally include the file.
+ */
+
+#ifndef __ASSEMBLY__
+
+enum VM_CACHE_OPS {
+	ickill,
+	dckill,
+	l2kill,
+	dccleaninva,
+	icinva,
+	idsync,
+	fetch_cfg
+};
+
+enum VM_INT_OPS {
+	nop,
+	globen,
+	globdis,
+	locen,
+	locdis,
+	affinity,
+	get,
+	peek,
+	status,
+	post,
+	clear
+};
+
+extern void _K_VM_event_vector(void);
+
+void __vmrte(void);
+long __vmsetvec(void *);
+long __vmsetie(long);
+long __vmgetie(void);
+long __vmintop(enum VM_INT_OPS, long, long, long, long);
+long __vmclrmap(void *, unsigned long);
+long __vmnewmap(void *);
+long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
+unsigned long long __vmgettime(void);
+long __vmsettime(unsigned long long);
+long __vmstart(void *, void *);
+void __vmstop(void);
+long __vmwait(void);
+void __vmyield(void);
+long __vmvpid(void);
+
+static inline long __vmcache_ickill(void)
+{
+	return __vmcache(ickill, 0, 0);
+}
+
+static inline long __vmcache_dckill(void)
+{
+	return __vmcache(dckill, 0, 0);
+}
+
+static inline long __vmcache_l2kill(void)
+{
+	return __vmcache(l2kill, 0, 0);
+}
+
+static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(dccleaninva, addr, len);
+}
+
+static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(icinva, addr, len);
+}
+
+static inline long __vmcache_idsync(unsigned long addr,
+					   unsigned long len)
+{
+	return __vmcache(idsync, addr, len);
+}
+
+static inline long __vmcache_fetch_cfg(unsigned long val)
+{
+	return __vmcache(fetch_cfg, val, 0);
+}
+
+/* interrupt operations  */
+
+static inline long __vmintop_nop(void)
+{
+	return __vmintop(nop, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_globen(long i)
+{
+	return __vmintop(globen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_globdis(long i)
+{
+	return __vmintop(globdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locen(long i)
+{
+	return __vmintop(locen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locdis(long i)
+{
+	return __vmintop(locdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_affinity(long i, long cpu)
+{
+	return __vmintop(locdis, i, cpu, 0, 0);
+}
+
+static inline long __vmintop_get(void)
+{
+	return __vmintop(get, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_peek(void)
+{
+	return __vmintop(peek, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_status(long i)
+{
+	return __vmintop(status, i, 0, 0, 0);
+}
+
+static inline long __vmintop_post(long i)
+{
+	return __vmintop(post, i, 0, 0, 0);
+}
+
+static inline long __vmintop_clear(long i)
+{
+	return __vmintop(clear, i, 0, 0, 0);
+}
+
+#else /* Only assembly code should reference these */
+
+#define HVM_TRAP1_VMRTE			1
+#define HVM_TRAP1_VMSETVEC		2
+#define HVM_TRAP1_VMSETIE		3
+#define HVM_TRAP1_VMGETIE		4
+#define HVM_TRAP1_VMINTOP		5
+#define HVM_TRAP1_VMCLRMAP		10
+#define HVM_TRAP1_VMNEWMAP		11
+#define HVM_TRAP1_FORMERLY_VMWIRE	12
+#define HVM_TRAP1_VMCACHE		13
+#define HVM_TRAP1_VMGETTIME		14
+#define HVM_TRAP1_VMSETTIME		15
+#define HVM_TRAP1_VMWAIT		16
+#define HVM_TRAP1_VMYIELD		17
+#define HVM_TRAP1_VMSTART		18
+#define HVM_TRAP1_VMSTOP		19
+#define HVM_TRAP1_VMVPID		20
+#define HVM_TRAP1_VMSETREGS		21
+#define HVM_TRAP1_VMGETREGS		22
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Constants for virtual instruction parameters and return values
+ */
+
+/* vmsetie arguments */
+
+#define VM_INT_DISABLE	0
+#define VM_INT_ENABLE	1
+
+/* vmsetimask arguments */
+
+#define VM_INT_UNMASK	0
+#define VM_INT_MASK	1
+
+#define VM_NEWMAP_TYPE_LINEAR	0
+#define VM_NEWMAP_TYPE_PGTABLES	1
+
+
+/*
+ * Event Record definitions useful to both C and Assembler
+ */
+
+/* VMEST Layout */
+
+#define HVM_VMEST_UM_SFT	31
+#define HVM_VMEST_UM_MSK	1
+#define HVM_VMEST_IE_SFT	30
+#define HVM_VMEST_IE_MSK	1
+#define HVM_VMEST_EVENTNUM_SFT	16
+#define HVM_VMEST_EVENTNUM_MSK	0xff
+#define HVM_VMEST_CAUSE_SFT	0
+#define HVM_VMEST_CAUSE_MSK	0xffff
+
+/*
+ * The initial program gets to find a system environment descriptor
+ * on its stack when it begins exection. The first word is a version
+ * code to indicate what is there.  Zero means nothing more.
+ */
+
+#define HEXAGON_VM_SED_NULL	0
+
+/*
+ * Event numbers for vector binding
+ */
+
+#define HVM_EV_RESET		0
+#define HVM_EV_MACHCHECK	1
+#define HVM_EV_GENEX		2
+#define HVM_EV_TRAP		8
+#define HVM_EV_INTR		15
+/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
+#define HVM_EV_INTR_0		16
+#define HVM_MAX_INTR		240
+
+/*
+ * Cause values for General Exception
+ */
+
+#define HVM_GE_C_BUS	0x01
+#define HVM_GE_C_XPROT	0x11
+#define HVM_GE_C_XUSER	0x14
+#define HVM_GE_C_INVI	0x15
+#define HVM_GE_C_PRIVI	0x1B
+#define HVM_GE_C_XMAL	0x1C
+#define HVM_GE_C_RMAL	0x20
+#define HVM_GE_C_WMAL	0x21
+#define HVM_GE_C_RPROT	0x22
+#define HVM_GE_C_WPROT	0x23
+#define HVM_GE_C_RUSER	0x24
+#define HVM_GE_C_WUSER	0x25
+#define HVM_GE_C_CACHE	0x28
+
+/*
+ * Cause codes for Machine Check
+ */
+
+#define	HVM_MCHK_C_DOWN		0x00
+#define	HVM_MCHK_C_BADSP	0x01
+#define	HVM_MCHK_C_BADEX	0x02
+#define	HVM_MCHK_C_BADPT	0x03
+#define	HVM_MCHK_C_REGWR	0x29
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/intrinsics.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/intrinsics.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/intrinsics.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/intrinsics.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_INTRINSICS_H
+#define _ASM_HEXAGON_INTRINSICS_H
+
+#define HEXAGON_P_vrmpyhacc_PP	__builtin_HEXAGON_M2_vrmac_s0
+#define HEXAGON_P_vrmpyh_PP	__builtin_HEXAGON_M2_vrmpy_s0
+#define HEXAGON_R_cl0_R		__builtin_HEXAGON_S2_cl0
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/io.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/io.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,326 @@
+/*
+ * IO definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+#include <asm/mem-layout.h>
+#include <asm/iomap.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't have PCI yet.
+ * _IO_BASE is pointing at what should be unused virtual space.
+ */
+#define IO_SPACE_LIMIT 0xffff
+#define _IO_BASE ((void __iomem *)0xfe000000)
+
+extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
+				unsigned long end, unsigned long flags);
+
+extern void __iounmap(const volatile void __iomem *addr);
+
+/* Defined in lib/io.c, needed for smc91x driver. */
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+
+extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
+
+#define readsw(p, d, l)	__raw_readsw(p, d, l)
+#define writesw(p, d, l) __raw_writesw(p, d, l)
+
+#define readsl(p, d, l)   __raw_readsl(p, d, l)
+#define writesl(p, d, l)  __raw_writesl(p, d, l)
+
+/*
+ * virt_to_phys - map virtual address to physical
+ * @address:  address to map
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+	return __pa(address);
+}
+
+/*
+ * phys_to_virt - map physical address to virtual
+ * @address: address to map
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+/*
+ * convert a physical pointer to a virtual kernel pointer for
+ * /dev/mem access.
+ */
+#define xlate_dev_kmem_ptr(p)    __va(p)
+#define xlate_dev_mem_ptr(p)    __va(p)
+
+/*
+ * IO port access primitives.  Hexagon doesn't have special IO access
+ * instructions; all I/O is memory mapped.
+ *
+ * in/out are used for "ports", but we don't have "port instructions",
+ * so these are really just memory mapped too.
+ */
+
+/*
+ * readb - read byte from memory mapped device
+ * @addr:  pointer to memory
+ *
+ * Operates on "I/O bus memory space"
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile(
+		"%0 = memb(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile(
+		"%0 = memh(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile(
+		"%0 = memw(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+/*
+ * writeb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  pointer to memory
+ *
+ */
+static inline void writeb(u8 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memb(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+static inline void writew(u16 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memh(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+
+}
+
+static inline void writel(u32 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memw(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+/*
+ * Need an mtype somewhere in here, for cache type deals?
+ * This is probably too long for an inline.
+ */
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+
+static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
+{
+	return ioremap_nocache(phys_addr, size);
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+	__iounmap(addr);
+}
+
+#define __raw_writel writel
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+	int count)
+{
+	memcpy(dst, (void *) src, count);
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+	int count)
+{
+	memcpy((void *) dst, src, count);
+}
+
+#define PCI_IO_ADDR	(volatile void __iomem *)
+
+/*
+ * inb - read byte from I/O port or something
+ * @port:  address in I/O space
+ *
+ * Operates on "I/O bus I/O space"
+ */
+static inline u8 inb(unsigned long port)
+{
+	return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u16 inw(unsigned long port)
+{
+	return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u32 inl(unsigned long port)
+{
+	return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+/*
+ * outb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  address in I/O space
+ */
+static inline void outb(u8 data, unsigned long port)
+{
+	writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outw(u16 data, unsigned long port)
+{
+	writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outl(u32 data, unsigned long port)
+{
+	writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+
+static inline void insb(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u8 *buf = buffer;
+		do {
+			u8 x = inb(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insw(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u16 *buf = buffer;
+		do {
+			u16 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insl(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u32 *buf = buffer;
+		do {
+			u32 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void outsb(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u8 *buf = buffer;
+		do {
+			outb(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsw(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u16 *buf = buffer;
+		do {
+			outw(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsl(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u32 *buf = buffer;
+		do {
+			outl(*buf++, port);
+		} while (--count);
+	}
+}
+
+#define flush_write_buffers() do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/irqflags.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/irqflags.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/irqflags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/irqflags.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * IRQ support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/hexagon_vm.h>
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return __vmgetie();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	return __vmsetie(VM_INT_DISABLE);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return !__vmgetie();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	__vmsetie(VM_INT_ENABLE);
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	__vmsetie(VM_INT_DISABLE);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	__vmsetie(flags);
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/irq.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/irq.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQ_H_
+#define _ASM_IRQ_H_
+
+/* Number of first-level interrupts associated with the CPU core. */
+#define HEXAGON_CPUINTS 32
+
+/*
+ * Must define NR_IRQS before including <asm-generic/irq.h>
+ * 64 == the two SIRC's, 176 == the two gpio's
+ *
+ * IRQ configuration is still in flux; defining this to a comfortably
+ * large number.
+ */
+#define NR_IRQS 512
+
+#include <asm-generic/irq.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/Kbuild linux-libre-3.2-gnu1/arch/hexagon/include/asm/Kbuild
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+header-y += ucontext.h
+header-y += user.h
+
+generic-y += auxvec.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += iomap.h
+generic-y += ipcbuf.h
+generic-y += ipc.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local64.h
+generic-y += local.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += rwsem.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += xor.h
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/kgdb.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/kgdb.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/kgdb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/kgdb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __HEXAGON_KGDB_H__
+#define __HEXAGON_KGDB_H__
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE   1
+#define BUFMAX       ((NUMREGBYTES * 2) + 512)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm("trap0(#0xDB)");
+}
+
+/* Registers:
+ * 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
+ * vm regs = psp+elr+est+badva = 4
+ * syscall+restart = 2 more
+ * so 48 = 42 +4 + 2
+ */
+#define DBG_USER_REGS 42
+#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
+#define NUMREGBYTES  (DBG_MAX_REG_NUM*4)
+
+#endif /* __HEXAGON_KGDB_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/linkage.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/linkage.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/linkage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/linkage.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN		.align 4
+#define __ALIGN_STR	".align 4"
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/mem-layout.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/mem-layout.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/mem-layout.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/mem-layout.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/*
+ * Memory layout definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
+#define _ASM_HEXAGON_MEM_LAYOUT_H
+
+#include <linux/const.h>
+
+/*
+ * Have to do this for ginormous numbers, else they get printed as
+ * negative numbers, which the linker no likey when you try to
+ * assign it to the location counter.
+ */
+
+#define PAGE_OFFSET			_AC(0xc0000000, UL)
+
+/*
+ * LOAD_ADDRESS is the physical/linear address of where in memory
+ * the kernel gets loaded. The 12 least significant bits must be zero (0)
+ * due to limitations on setting the EVB
+ *
+ */
+
+#ifndef LOAD_ADDRESS
+#define LOAD_ADDRESS			0x00000000
+#endif
+
+#define TASK_SIZE			(PAGE_OFFSET)
+
+/*  not sure how these are used yet  */
+#define STACK_TOP			TASK_SIZE
+#define STACK_TOP_MAX			TASK_SIZE
+
+#ifndef __ASSEMBLY__
+enum fixed_addresses {
+	FIX_KMAP_BEGIN,
+	FIX_KMAP_END,  /*  check for per-cpuism  */
+	__end_of_fixed_addresses
+};
+
+#define MIN_KERNEL_SEG 0x300   /* From 0xc0000000 */
+extern int max_kernel_seg;
+
+/*
+ * Start of vmalloc virtual address space for kernel;
+ * supposed to be based on the amount of physical memory available
+ */
+
+#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
+	(unsigned long)high_memory)
+
+/* Gap between physical ram and vmalloc space for guard purposes. */
+#define VMALLOC_OFFSET PAGE_SIZE
+
+/*
+ * Create the space between VMALLOC_START and FIXADDR_TOP backwards
+ * from the ... "top".
+ *
+ * Permanent IO mappings will live at 0xfexx_xxxx
+ * Hypervisor occupies the last 16MB page at 0xffxxxxxx
+ */
+
+#define FIXADDR_TOP     0xfe000000
+#define FIXADDR_SIZE    (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START   (FIXADDR_TOP - FIXADDR_SIZE)
+
+/*
+ * "permanent kernel mappings", defined as long-lasting mappings of
+ * high-memory page frames into the kernel address space.
+ */
+
+#define LAST_PKMAP	PTRS_PER_PTE
+#define LAST_PKMAP_MASK	(LAST_PKMAP - 1)
+#define PKMAP_NR(virt)	((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)	(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * To the "left" of the fixed map space is the kmap space
+ *
+ * "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
+ * that looks like it's actually walked.
+ * Need to check the alignment/shift usage; some archs use
+ * PMD_MASK on this value
+ */
+#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
+
+/*
+ * 2 pages of guard gap between where vmalloc area ends
+ * and pkmap_base begins.
+ */
+#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
+#endif /*  !__ASSEMBLY__  */
+
+
+#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/mmu_context.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/mmu_context.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/mmu_context.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/mmu_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * MM context support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/mem-layout.h>
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+}
+
+/*
+ * VM port hides all TLB management, so "lazy TLB" isn't very
+ * meaningful.  Even for ports to architectures with visble TLBs,
+ * this is almost invariably a null function.
+ */
+static inline void enter_lazy_tlb(struct mm_struct *mm,
+	struct task_struct *tsk)
+{
+}
+
+/*
+ * Architecture-specific actions, if any, for memory map deactivation.
+ */
+static inline void deactivate_mm(struct task_struct *tsk,
+	struct mm_struct *mm)
+{
+}
+
+/**
+ * init_new_context - initialize context related info for new mm_struct instance
+ * @tsk: pointer to a task struct
+ * @mm: pointer to a new mm struct
+ */
+static inline int init_new_context(struct task_struct *tsk,
+					struct mm_struct *mm)
+{
+	/* mm->context is set up by pgd_alloc */
+	return 0;
+}
+
+/*
+ *  Switch active mm context
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+				struct task_struct *tsk)
+{
+	int l1;
+
+	/*
+	 * For virtual machine, we have to update system map if it's been
+	 * touched.
+	 */
+	if (next->context.generation < prev->context.generation) {
+		for (l1 = MIN_KERNEL_SEG; l1 <= max_kernel_seg; l1++)
+			next->pgd[l1] = init_mm.pgd[l1];
+
+		next->context.generation = prev->context.generation;
+	}
+
+	__vmnewmap((void *)next->context.ptbase);
+}
+
+/*
+ *  Activate new memory map for task
+ */
+static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm(prev, next, current_thread_info()->task);
+	local_irq_restore(flags);
+}
+
+/*  Generic hooks for arch_dup_mmap and arch_exit_mmap  */
+#include <asm-generic/mm_hooks.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/mmu.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/mmu.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+#include <asm/vdso.h>
+
+/*
+ * Architecture-specific state for a mm_struct.
+ * For the Hexagon Virtual Machine, it can be a copy
+ * of the pointer to the page table base.
+ */
+struct mm_context {
+	unsigned long long generation;
+	unsigned long ptbase;
+	struct hexagon_vdso *vdso;
+};
+
+typedef struct mm_context mm_context_t;
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/module.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/module.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/module.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/mutex.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/mutex.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/mutex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+#include <asm-generic/mutex-xchg.h>
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/page.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/page.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,157 @@
+/*
+ * Page management definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#include <linux/const.h>
+
+/*  This is probably not the most graceful way to handle this.  */
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PAGE_SHIFT 12
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT 14
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT 16
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PAGE_SHIFT 18
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PAGE_SHIFT 20
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
+#endif
+
+/*
+ *  These should be defined in hugetlb.h, but apparently not.
+ *  "Huge" for us should be 4MB or 16MB, which are both represented
+ *  in L1 PTE's.  Right now, it's set up for 4MB.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE-1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define HVM_HUGEPAGE_SIZE 0x5
+#endif
+
+#define PAGE_SIZE  (1UL << PAGE_SHIFT)
+#define PAGE_MASK  (~((1 << PAGE_SHIFT) - 1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * This is for PFN_DOWN, which mm.h needs.  Seems the right place to pull it in.
+ */
+#include <linux/pfn.h>
+
+/*
+ * We implement a two-level architecture-specific page table structure.
+ * Null intermediate page table level (pmd, pud) definitions will come from
+ * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)     ((x).pte)
+#define pgd_val(x)     ((x).pgd)
+#define pgprot_val(x)  ((x).pgprot)
+#define __pte(x)       ((pte_t) { (x) })
+#define __pgd(x)       ((pgd_t) { (x) })
+#define __pgprot(x)    ((pgprot_t) { (x) })
+
+/*
+ * We need a __pa and a __va routine for kernel space.
+ * MIPS says they're only used during mem_init.
+ * also, check if we need a PHYS_OFFSET.
+ */
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+/* The "page frame" descriptor is defined in linux/mm.h */
+struct page;
+
+/* Returns page frame descriptor for virtual address. */
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
+
+/* Default vm area behavior is non-executable.  */
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+				VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+/*  Need to not use a define for linesize; may move this to another file.  */
+static inline void clear_page(void *page)
+{
+	/*  This can only be done on pages with L1 WB cache */
+	asm volatile(
+		"	loop0(1f,%1);\n"
+		"1:	{ dczeroa(%0);\n"
+		"	  %0 = add(%0,#32); }:endloop0\n"
+		: "+r" (page)
+		: "r" (PAGE_SIZE/32)
+		: "lc0", "sa0", "memory"
+	);
+}
+
+#define copy_page(to, from)	memcpy((to), (from), PAGE_SIZE)
+
+/*
+ * Under assumption that kernel always "sees" user map...
+ */
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+/*
+ * page_to_phys - convert page to physical address
+ * @page - pointer to page entry in mem_map
+ */
+#define page_to_phys(page)      (page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * For port to Hexagon Virtual Machine, MAYBE we check for attempts
+ * to reference reserved HVM space, but in any case, the VM will be
+ * protected.
+ */
+#define kern_addr_valid(addr)   (1)
+
+#include <asm-generic/memory_model.h>
+/* XXX Todo: implement assembly-optimized version of getorder. */
+#include <asm-generic/getorder.h>
+
+#endif /* ifdef __ASSEMBLY__ */
+#endif /* ifdef __KERNEL__ */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/param.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/param.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/param.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/param.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#define EXEC_PAGESIZE	16384
+
+#include <asm-generic/param.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/perf_event.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/perf_event.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/perf_event.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PERF_EVENT_H
+#define _ASM_PERF_EVENT_H
+
+#define PERF_EVENT_INDEX_OFFSET	0
+
+#endif /* _ASM_PERF_EVENT_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/pgalloc.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/pgalloc.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/pgalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,146 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/mem-layout.h>
+#include <asm/atomic.h>
+
+#define check_pgt_cache() do {} while (0)
+
+extern unsigned long long kmap_generation;
+
+/*
+ * Page table creation interface
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd;
+
+	pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+	/*
+	 * There may be better ways to do this, but to ensure
+	 * that new address spaces always contain the kernel
+	 * base mapping, and to ensure that the user area is
+	 * initially marked invalid, initialize the new map
+	 * map with a copy of the kernel's persistent map.
+	 */
+
+	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+	mm->context.generation = kmap_generation;
+
+	/* Physical version is what is passed to virtual machine on switch */
+	mm->context.ptbase = __pa(pgd);
+
+	return pgd;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	free_page((unsigned long) pgd);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long address)
+{
+	struct page *pte;
+
+	pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+
+	if (pte)
+		pgtable_page_ctor(pte);
+
+	return pte;
+}
+
+/* _kernel variant gets to use a different allocator */
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	gfp_t flags =  GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+	return (pte_t *) __get_free_page(flags);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte)
+{
+	/*
+	 * Conveniently, zero in 3 LSB means indirect 4K page table.
+	 * Not so convenient when you're trying to vary the page size.
+	 */
+	set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
+		HEXAGON_L1_PTE_SIZE));
+}
+
+/*
+ * Other architectures seem to have ways of making all processes
+ * share the same pmd's for their kernel mappings, but the v0.3
+ * Hexagon VM spec has a "monolithic" L1 table for user and kernel
+ * segments.  We track "generations" of the kernel map to minimize
+ * overhead, and update the "slave" copies of the kernel mappings
+ * as part of switch_mm.  However, we still need to update the
+ * kernel map of the active thread who's calling pmd_populate_kernel...
+ */
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	extern spinlock_t kmap_gen_lock;
+	pmd_t *ppmd;
+	int pmdindex;
+
+	spin_lock(&kmap_gen_lock);
+	kmap_generation++;
+	mm->context.generation = kmap_generation;
+	current->active_mm->context.generation = kmap_generation;
+	spin_unlock(&kmap_gen_lock);
+
+	set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+
+	/*
+	 * Now the "slave" copy of the current thread.
+	 * This is pointer arithmetic, not byte addresses!
+	 */
+	pmdindex = (pgd_t *)pmd - mm->pgd;
+	ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
+	set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+	if (pmdindex > max_kernel_seg)
+		max_kernel_seg = pmdindex;
+}
+
+#define __pte_free_tlb(tlb, pte, addr)		\
+do {						\
+	pgtable_page_dtor((pte));		\
+	tlb_remove_page((tlb), (pte));		\
+} while (0)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/pgtable.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/pgtable.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/pgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,518 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+/*
+ * Page table definitions for Qualcomm Hexagon processor.
+ */
+#include <linux/swap.h>
+#include <asm/page.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* A handy thing to have if one has the RAM. Declared in head.S */
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+/*
+ * The PTE model described here is that of the Hexagon Virtual Machine,
+ * which autonomously walks 2-level page tables.  At a lower level, we
+ * also describe the RISCish software-loaded TLB entry structure of
+ * the underlying Hexagon processor. A kernel built to run on the
+ * virtual machine has no need to know about the underlying hardware.
+ */
+#include <asm/vm_mmu.h>
+
+/*
+ * To maximize the comfort level for the PTE manipulation macros,
+ * define the "well known" architecture-specific bits.
+ */
+#define _PAGE_READ	__HVM_PTE_R
+#define _PAGE_WRITE	__HVM_PTE_W
+#define _PAGE_EXECUTE	__HVM_PTE_X
+#define _PAGE_USER	__HVM_PTE_U
+
+/*
+ * We have a total of 4 "soft" bits available in the abstract PTE.
+ * The two mandatory software bits are Dirty and Accessed.
+ * To make nonlinear swap work according to the more recent
+ * model, we want a low order "Present" bit to indicate whether
+ * the PTE describes MMU programming or swap space.
+ */
+#define _PAGE_PRESENT	(1<<0)
+#define _PAGE_DIRTY	(1<<1)
+#define _PAGE_ACCESSED	(1<<2)
+
+/*
+ * _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
+ * _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
+ * So we can overload the bit...
+ */
+#define _PAGE_FILE	_PAGE_DIRTY /* set:  pagecache, unset = swap */
+
+/*
+ * For now, let's say that Valid and Present are the same thing.
+ * Alternatively, we could say that it's the "or" of R, W, and X
+ * permissions.
+ */
+#define _PAGE_VALID	_PAGE_PRESENT
+
+/*
+ * We're not defining _PAGE_GLOBAL here, since there's no concept
+ * of global pages or ASIDs exposed to the Hexagon Virtual Machine,
+ * and we want to use the same page table structures and macros in
+ * the native kernel as we do in the virtual machine kernel.
+ * So we'll put up with a bit of inefficiency for now...
+ */
+
+/*
+ * Top "FOURTH" level (pgd), which for the Hexagon VM is really
+ * only the second from the bottom, pgd and pud both being collapsed.
+ * Each entry represents 4MB of virtual address space, 4K of table
+ * thus maps the full 4GB.
+ */
+#define PGDIR_SHIFT 22
+#define PTRS_PER_PGD 1024
+
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PTRS_PER_PTE 1024
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PTRS_PER_PTE 256
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PTRS_PER_PTE 64
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PTRS_PER_PTE 16
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PTRS_PER_PTE 4
+#endif
+
+/*  Any bigger and the PTE disappears.  */
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
+		pgd_val(e))
+
+/*
+ * Page Protection Constants. Includes (in this variant) cache attributes.
+ */
+extern unsigned long _dflt_cache_att;
+
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_dflt_cache_att)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY	PAGE_READONLY
+#define PAGE_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY_EXEC	PAGE_EXEC
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+				_PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_READ | \
+				_PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
+
+
+/*
+ * Aliases for mapping mmap() protection bits to page protections.
+ * These get used for static initialization, so using the _dflt_cache_att
+ * variable for the default cache attribute isn't workable. If the
+ * default gets changed at boot time, the boot option code has to
+ * update data structures like the protaction_map[] array.
+ */
+#define CACHEDEF	(CACHE_DEFAULT << 6)
+
+/* Private (copy-on-write) page protections. */
+#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
+#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
+#define __P010 __P000	/* Write-only copy-on-write */
+#define __P011 __P001	/* Read/Write copy-on-write */
+#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
+			_PAGE_READ | CACHEDEF)
+#define __P110 __P100	/* Write/execute copy-on-write */
+#define __P111 __P101	/* Read/Write/Execute, copy-on-write */
+
+/* Shared page protections. */
+#define __S000 __P000
+#define __S001 __P001
+#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __S101 __P101
+#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];  /* located in head.S */
+
+/* Seems to be zero even in architectures where the zero page is firewalled? */
+#define FIRST_USER_ADDRESS 0
+#define pte_special(pte)	0
+#define pte_mkspecial(pte)	(pte)
+
+/*  HUGETLB not working currently  */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
+#endif
+
+/*
+ * For now, assume that higher-level code will do TLB/MMU invalidations
+ * and don't insert that overhead into this low-level function.
+ */
+extern void sync_icache_dcache(pte_t pte);
+
+#define pte_present_exec_user(pte) \
+	((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
+	(_PAGE_EXECUTE | _PAGE_USER))
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+	/*  should really be using pte_exec, if it weren't declared later. */
+	if (pte_present_exec_user(pteval))
+		sync_icache_dcache(pteval);
+
+	*ptep = pteval;
+}
+
+/*
+ * For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
+ * L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
+ * (Linux PTE), the key is to have bits 11..9 all zero.  We'd use 0x7
+ * as a universal null entry, but some of those least significant bits
+ * are interpreted by software.
+ */
+#define _NULL_PMD	0x7
+#define _NULL_PTE	0x0
+
+static inline void pmd_clear(pmd_t *pmd_entry_ptr)
+{
+	 pmd_val(*pmd_entry_ptr) = _NULL_PMD;
+}
+
+/*
+ * Conveniently, a null PTE value is invalid.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+				pte_t *ptep)
+{
+	pte_val(*ptep) = _NULL_PTE;
+}
+
+#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
+/**
+ * pmd_index - returns the index of the entry in the PMD page
+ * which would control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+#endif
+
+/**
+ * pgd_index - returns the index of the entry in the PGD page
+ * which would control the given virtual address
+ *
+ * This returns the *index* for the address in the pgd_t
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/*
+ * pgd_offset - find an offset in a page-table-directory
+ */
+#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+
+/*
+ * pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/**
+ * pmd_none - check if pmd_entry is mapped
+ * @pmd_entry:  pmd entry
+ *
+ * MIPS checks it against that "invalid pte table" thing.
+ */
+static inline int pmd_none(pmd_t pmd)
+{
+	return pmd_val(pmd) == _NULL_PMD;
+}
+
+/**
+ * pmd_present - is there a page table behind this?
+ * Essentially the inverse of pmd_none.  We maybe
+ * save an inline instruction by defining it this
+ * way, instead of simply "!pmd_none".
+ */
+static inline int pmd_present(pmd_t pmd)
+{
+	return pmd_val(pmd) != (unsigned long)_NULL_PMD;
+}
+
+/**
+ * pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
+ * As we have no known cause of badness, it's null, as it is for many
+ * architectures.
+ */
+static inline int pmd_bad(pmd_t pmd)
+{
+	return 0;
+}
+
+/*
+ * pmd_page - converts a PMD entry to a page pointer
+ */
+#define pmd_page(pmd)  (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/**
+ * pte_none - check if pte is mapped
+ * @pte: pte_t entry
+ */
+static inline int pte_none(pte_t pte)
+{
+	return pte_val(pte) == _NULL_PTE;
+};
+
+/*
+ * pte_present - check if page is present
+ */
+static inline int pte_present(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_PRESENT;
+}
+
+/* mk_pte - make a PTE out of a page pointer and protection bits */
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+/* pte_mkold - mark PTE as not recently accessed */
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkyoung - mark PTE as recently accessed */
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkclean - mark page as in sync with backing store */
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_mkdirty - mark page as modified */
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_young - "is PTE marked as accessed"? */
+static inline int pte_young(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+/* pte_dirty - "is PTE dirty?" */
+static inline int pte_dirty(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_DIRTY;
+}
+
+/* pte_modify - set protection bits on PTE */
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+	pte_val(pte) &= PAGE_MASK;
+	pte_val(pte) |= pgprot_val(prot);
+	return pte;
+}
+
+/* pte_wrprotect - mark page as not writable */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkwrite - mark page as writable */
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkexec - mark PTE as executable */
+static inline pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_EXECUTE;
+	return pte;
+}
+
+/* pte_read - "is PTE marked as readable?" */
+static inline int pte_read(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_READ;
+}
+
+/* pte_write - "is PTE marked as writable?" */
+static inline int pte_write(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_WRITE;
+}
+
+
+/* pte_exec - "is PTE marked as executable?" */
+static inline int pte_exec(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_EXECUTE;
+}
+
+/* __pte_to_swp_entry - extract swap entry from PTE */
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+
+/* __swp_entry_to_pte - extract PTE from swap entry */
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* pfn_pte - convert page number and protection value to page table entry */
+#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/* pte_pfn - convert pte to page frame number */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+/*
+ * set_pte_at - update page table and do whatever magic may be
+ * necessary to make the underlying hardware/firmware take note.
+ *
+ * VM may require a virtual instruction to alert the MMU.
+ */
+#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
+
+/*
+ * May need to invoke the virtual machine as well...
+ */
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+/*
+ * pte_offset_map - returns the linear address of the page table entry
+ * corresponding to an address
+ */
+#define pte_offset_map(dir, address)                                    \
+	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+
+#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
+
+/* pte_offset_kernel - kernel version of pte_offset */
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+				+  __pte_offset(address))
+
+/* ZERO_PAGE - returns the globally shared zero page */
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+/* Nothing special about IO remapping at this point */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+/*  I think this is in case we have page table caches; needed by init/main.c  */
+#define pgtable_cache_init()    do { } while (0)
+
+/*
+ * Swap/file PTE definitions.  If _PAGE_PRESENT is zero, the rest of the
+ * PTE is interpreted as swap information.  Depending on the _PAGE_FILE
+ * bit, the remaining free bits are eitehr interpreted as a file offset
+ * or a swap type/offset tuple.  Rather than have the TLB fill handler
+ * test _PAGE_PRESENT, we're going to reserve the permissions bits
+ * and set them to all zeros for swap entries, which speeds up the
+ * miss handler at the cost of 3 bits of offset.  That trade-off can
+ * be revisited if necessary, but Hexagon processor architecture and
+ * target applications suggest a lot of TLB misses and not much swap space.
+ *
+ * Format of swap PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-6:	swap type (arch independent layer uses 5 bits max)
+ *	bits	7-9:	bits 2:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 21:3 of swap offset
+ *
+ * Format of file PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-9:	bits 7:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 26:8 of swap offset
+ *
+ * The split offset makes some of the following macros a little gnarly,
+ * but there's plenty of precedent for this sort of thing.
+ */
+#define PTE_FILE_MAX_BITS     27
+
+/* Used for swap PTEs */
+#define __swp_type(swp_pte)		(((swp_pte).val >> 2) & 0x1f)
+
+#define __swp_offset(swp_pte) \
+	((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
+
+#define __swp_entry(type, offset) \
+	((swp_entry_t)	{ \
+		((type << 2) | \
+		 ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
+
+/* Used for file PTEs */
+#define pte_file(pte) \
+	((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
+
+#define pte_to_pgoff(pte) \
+	(((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
+	| _PAGE_FILE) })
+
+/*  Oh boy.  There are a lot of possible arch overrides found in this file.  */
+#include <asm-generic/pgtable.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/processor.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/processor.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ * Process/processor support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/mem-layout.h>
+#include <asm/registers.h>
+#include <asm/hexagon_vm.h>
+
+/*  must be a macro  */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*  task_struct, defined elsewhere, is the "process descriptor" */
+struct task_struct;
+
+/*  this is defined in arch/process.c  */
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
+
+/*
+ * thread_struct is supposed to be for context switch data.
+ * Specifically, to hold the state necessary to perform switch_to...
+ */
+struct thread_struct {
+	void *switch_sp;
+};
+
+/*
+ * initializes thread_struct
+ * The only thing we have in there is switch_sp
+ * which doesn't really need to be initialized.
+ */
+
+#define INIT_THREAD { \
+}
+
+#define cpu_relax() __vmyield()
+
+/*
+ * "Unlazying all lazy status" occurs here.
+ */
+static inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+/*
+ * Decides where the kernel will search for a free chunk of vm space during
+ * mmaps.
+ * See also arch_get_unmapped_area.
+ * Doesn't affect if you have MAX_FIXED in the page flags set though...
+ *
+ * Apparently the convention is that ld.so will ask for "unmapped" private
+ * memory to be allocated SOMEWHERE, but it also asks for memory explicitly
+ * via MAP_FIXED at the lower * addresses starting at VA=0x0.
+ *
+ * If the two requests collide, you get authentic segfaulting action, so
+ * you have to kick the "unmapped" base requests higher up.
+ */
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE/3))
+
+
+#define task_pt_regs(task) \
+	((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+
+#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
+#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
+
+/*  Free all resources held by a thread; defined in process.c  */
+extern void release_thread(struct task_struct *dead_task);
+
+/* Get wait channel for task P.  */
+extern unsigned long get_wchan(struct task_struct *p);
+
+/*  The following stuff is pretty HEXAGON specific.  */
+
+/*  This is really just here for __switch_to.
+    Offsets are pulled via asm-offsets.c  */
+
+/*
+ * No real reason why VM and native switch stacks should be different.
+ * Ultimately this should merge.  Note that Rev C. ABI called out only
+ * R24-27 as callee saved GPRs needing explicit attention (R29-31 being
+ * dealt with automagically by allocframe), but the current ABI has
+ * more, R16-R27.  By saving more, the worst case is that we waste some
+ * cycles if building with the old compilers.
+ */
+
+struct hexagon_switch_stack {
+	unsigned long long	r1716;
+	unsigned long long	r1918;
+	unsigned long long	r2120;
+	unsigned long long	r2322;
+	unsigned long long	r2524;
+	unsigned long long	r2726;
+	unsigned long		fp;
+	unsigned long		lr;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/ptrace.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/ptrace.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/registers.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/registers.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/registers.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/registers.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,236 @@
+/*
+ * Register definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#define SP r29
+
+#ifndef __ASSEMBLY__
+
+/*  See kernel/entry.S for further documentation.  */
+
+/*
+ * Entry code copies the event record out of guest registers into
+ * this structure (which is on the stack).
+ */
+
+struct hvm_event_record {
+	unsigned long vmel;     /* Event Linkage (return address) */
+	unsigned long vmest;    /* Event context - pre-event SSR values */
+	unsigned long vmpsp;    /* Previous stack pointer */
+	unsigned long vmbadva;  /* Bad virtual address for addressing events */
+};
+
+struct pt_regs {
+	long restart_r0;        /* R0 checkpoint for syscall restart */
+	long syscall_nr;        /* Only used in system calls */
+	union {
+		struct {
+			unsigned long usr;
+			unsigned long preds;
+		};
+		long long int predsusr;
+	};
+	union {
+		struct {
+			unsigned long m0;
+			unsigned long m1;
+		};
+		long long int m1m0;
+	};
+	union {
+		struct {
+			unsigned long sa1;
+			unsigned long lc1;
+		};
+		long long int lc1sa1;
+	};
+	union {
+		struct {
+			unsigned long sa0;
+			unsigned long lc0;
+		};
+		long long int lc0sa0;
+	};
+	union {
+		struct {
+			unsigned long gp;
+			unsigned long ugp;
+		};
+		long long int ugpgp;
+	};
+	/*
+	* Be extremely careful with rearranging these, if at all.  Some code
+	* assumes the 32 registers exist exactly like this in memory;
+	* e.g. kernel/ptrace.c
+	* e.g. kernel/signal.c (restore_sigcontext)
+	*/
+	union {
+		struct {
+			unsigned long r00;
+			unsigned long r01;
+		};
+		long long int r0100;
+	};
+	union {
+		struct {
+			unsigned long r02;
+			unsigned long r03;
+		};
+		long long int r0302;
+	};
+	union {
+		struct {
+			unsigned long r04;
+			unsigned long r05;
+		};
+		long long int r0504;
+	};
+	union {
+		struct {
+			unsigned long r06;
+			unsigned long r07;
+		};
+		long long int r0706;
+	};
+	union {
+		struct {
+			unsigned long r08;
+			unsigned long r09;
+		};
+		long long int r0908;
+	};
+	union {
+	       struct {
+			unsigned long r10;
+			unsigned long r11;
+	       };
+	       long long int r1110;
+	};
+	union {
+	       struct {
+			unsigned long r12;
+			unsigned long r13;
+	       };
+	       long long int r1312;
+	};
+	union {
+	       struct {
+			unsigned long r14;
+			unsigned long r15;
+	       };
+	       long long int r1514;
+	};
+	union {
+		struct {
+			unsigned long r16;
+			unsigned long r17;
+		};
+		long long int r1716;
+	};
+	union {
+		struct {
+			unsigned long r18;
+			unsigned long r19;
+		};
+		long long int r1918;
+	};
+	union {
+		struct {
+			unsigned long r20;
+			unsigned long r21;
+		};
+		long long int r2120;
+	};
+	union {
+		struct {
+			unsigned long r22;
+			unsigned long r23;
+		};
+		long long int r2322;
+	};
+	union {
+		struct {
+			unsigned long r24;
+			unsigned long r25;
+		};
+		long long int r2524;
+	};
+	union {
+		struct {
+			unsigned long r26;
+			unsigned long r27;
+		};
+		long long int r2726;
+	};
+	union {
+		struct {
+			unsigned long r28;
+			unsigned long r29;
+	       };
+	       long long int r2928;
+	};
+	union {
+		struct {
+			unsigned long r30;
+			unsigned long r31;
+		};
+		long long int r3130;
+	};
+	/* VM dispatch pushes event record onto stack - we can build on it */
+	struct hvm_event_record hvmer;
+};
+
+/* Defines to conveniently access the values  */
+
+/*
+ * As of the VM spec 0.5, these registers are now set/retrieved via a
+ * VM call.  On the in-bound side, we just fetch the values
+ * at the entry points and stuff them into the old record in pt_regs.
+ * However, on the outbound side, probably at VM rte, we set the
+ * registers back.
+ */
+
+#define pt_elr(regs) ((regs)->hvmer.vmel)
+#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
+#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
+#define user_mode(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
+#define ints_enabled(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
+#define pt_psp(regs) ((regs)->hvmer.vmpsp)
+#define pt_badva(regs) ((regs)->hvmer.vmbadva)
+
+#define pt_set_rte_sp(regs, sp) do {\
+	pt_psp(regs) = (sp);\
+	(regs)->SP = (unsigned long) &((regs)->hvmer);\
+	} while (0)
+
+#define pt_set_kmode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#define pt_set_usermode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
+			    | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#endif  /*  ifndef __ASSEMBLY  */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/setup.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/setup.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/setup.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/setup.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+extern char external_cmdline_buffer;
+
+void __init setup_arch_memory(void);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/sigcontext.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/sigcontext.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/sigcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/signal.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/signal.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/signal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/signal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/smp.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/smp.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * SMP definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/cpumask.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+enum ipi_message_type {
+	IPI_NOP = 0,
+	IPI_RESCHEDULE = 1,
+	IPI_CALL_FUNC,
+	IPI_CALL_FUNC_SINGLE,
+	IPI_CPU_STOP,
+	IPI_TIMER,
+};
+
+extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
+extern void smp_start_cpus(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+extern void smp_vm_unmask_irq(void *info);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/spinlock.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/spinlock.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/spinlock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,186 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#include <asm/irqflags.h>
+
+/*
+ * This file is pulled in for SMP builds.
+ * Really need to check all the barrier stuff for "true" SMP
+ */
+
+/*
+ * Read locks:
+ * - load the lock value
+ * - increment it
+ * - if the lock value is still negative, go back and try again.
+ * - unsuccessful store is unsuccessful.  Go back and try again.  Loser.
+ * - successful store new lock value if positive -> lock acquired
+ */
+static inline void arch_read_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	{ P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	R6 = add(R6,#-1);\n"
+		"	memw_locked(%0,P3) = R6\n"
+		"	if !P3 jump 1b;\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+/*  I think this returns 0 on fail, 1 on success.  */
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	{ %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	{ %0 = P3 }\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+static inline int arch_read_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+/*  Stuffs a -1 in the lock value?  */
+static inline void arch_write_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0)\n"
+		"	{ P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+}
+
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1)\n"
+		"	{ %0 = #0; P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1b; R6 = #1; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+/*
+ * SMP spinlocks are intended to allow only a single CPU at the lock
+ */
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+#define arch_spin_unlock_wait(lock) \
+	do {while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define arch_spin_is_locked(x) ((x)->lock != 0)
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/spinlock_types.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/spinlock_types.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/spinlock_types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/spinlock_types.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#include <linux/version.h>
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/string.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/string.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/string.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/string.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_STRING_H_
+#define _ASM_STRING_H_
+
+#ifdef __KERNEL__
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+/*  ToDo:  use dczeroa, accelerate the compiler-constant zero case  */
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__to, int c, size_t __n);
+#endif
+
+
+#endif /* _ASM_STRING_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/suspend.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/suspend.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/suspend.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SUSPEND_H
+#define _ASM_SUSPEND_H
+
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/swab.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/swab.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/swab.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/swab.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#define __SWAB_64_THRU_32__
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/syscall.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/syscall.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/syscall.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/syscall.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Syscall support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_SYSCALL_H
+#define _ASM_HEXAGON_SYSCALL_H
+
+typedef long (*syscall_fn)(unsigned long, unsigned long,
+	unsigned long, unsigned long,
+	unsigned long, unsigned long);
+
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
+			  char __user * __user *envp);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp);
+
+#define sys_execve	sys_execve
+#define sys_clone	sys_clone
+
+#include <asm-generic/syscalls.h>
+
+extern void *sys_call_table[];
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->r06;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+	memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/system.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,126 @@
+/*
+ * System level definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SYSTEM_H
+#define _ASM_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+#include <asm/atomic.h>
+#include <asm/hexagon_vm.h>
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+	struct task_struct *,
+	struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+	r = __switch_to((p), (n), (r));\
+} while (0)
+
+
+#define rmb()				barrier()
+#define read_barrier_depends()		barrier()
+#define wmb()				barrier()
+#define mb()				barrier()
+#define smp_rmb()			barrier()
+#define smp_read_barrier_depends()	barrier()
+#define smp_wmb()			barrier()
+#define smp_mb()			barrier()
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size:  size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note:  there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+				   int size)
+{
+	unsigned long retval;
+
+	/*  Can't seem to use printk or panic here, so just stop  */
+	if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+	__asm__ __volatile__ (
+	"1:	%0 = memw_locked(%1);\n"    /*  load into retval */
+	"	memw_locked(%1,P0) = %2;\n" /*  store into memory */
+	"	if !P0 jump 1b;\n"
+	: "=&r" (retval)
+	: "r" (ptr), "r" (x)
+	: "memory", "p0"
+	);
+	return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory.  Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+	sizeof(*(ptr))))
+
+/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
+#define set_mb(var, value) \
+	do { var = value; mb(); } while (0)
+
+/*
+ *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ *  looks just like atomic_cmpxchg on our arch currently with a bunch of
+ *  variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new)					\
+({								\
+	__typeof__(ptr) __ptr = (ptr);				\
+	__typeof__(*(ptr)) __old = (old);			\
+	__typeof__(*(ptr)) __new = (new);			\
+	__typeof__(*(ptr)) __oldval = 0;			\
+								\
+	asm volatile(						\
+		"1:	%0 = memw_locked(%1);\n"		\
+		"	{ P0 = cmp.eq(%0,%2);\n"		\
+		"	  if (!P0.new) jump:nt 2f; }\n"		\
+		"	memw_locked(%1,p0) = %3;\n"		\
+		"	if (!P0) jump 1b;\n"			\
+		"2:\n"						\
+		: "=&r" (__oldval)				\
+		: "r" (__ptr), "r" (__old), "r" (__new)		\
+		: "memory", "p0"				\
+	);							\
+	__oldval;						\
+})
+
+/*  Should probably shoot for an 8-byte aligned stack pointer  */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/thread_info.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/thread_info.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/thread_info.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/thread_info.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+/*
+ * Thread support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+#endif
+
+#define THREAD_SHIFT		12
+#define THREAD_SIZE		(1<<THREAD_SHIFT)
+
+#if THREAD_SHIFT >= PAGE_SHIFT
+#define THREAD_SIZE_ORDER	(THREAD_SHIFT - PAGE_SHIFT)
+#else  /*  don't use standard allocator  */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
+extern void free_thread_info(struct thread_info *ti);
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+/*
+ * This is union'd with the "bottom" of the kernel stack.
+ * It keeps track of thread info which is handy for routines
+ * to access quickly.
+ */
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain      *exec_domain;   /* execution domain */
+	unsigned long		flags;          /* low level flags */
+	__u32                   cpu;            /* current cpu */
+	int                     preempt_count;  /* 0=>preemptible,<0=>BUG */
+	mm_segment_t            addr_limit;     /* segmentation sux */
+	/*
+	 * used for syscalls somehow;
+	 * seems to have a function pointer and four arguments
+	 */
+	struct restart_block    restart_block;
+	/* Points to the current pt_regs frame  */
+	struct pt_regs		*regs;
+	/*
+	 * saved kernel sp at switch_to time;
+	 * not sure if this is used (it's not in the VM model it seems;
+	 * see thread_struct)
+	 */
+	unsigned long		sp;
+};
+
+#else /* !__ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+#endif  /* __ASSEMBLY__  */
+
+/*  looks like "linux/hardirq.h" uses this.  */
+
+#define PREEMPT_ACTIVE		0x10000000
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)                   \
+{                                               \
+	.task           = &tsk,                 \
+	.exec_domain    = &default_exec_domain, \
+	.flags          = 0,                    \
+	.cpu            = 0,                    \
+	.preempt_count  = 1,                    \
+	.addr_limit     = KERNEL_DS,            \
+	.restart_block = {                      \
+		.fn = do_no_restart_syscall,    \
+	},                                      \
+	.sp = 0,				\
+	.regs = NULL,			\
+}
+
+#define init_thread_info        (init_thread_union.thread_info)
+#define init_stack              (init_thread_union.stack)
+
+/* Tacky preprocessor trickery */
+#define	qqstr(s) qstr(s)
+#define qstr(s) #s
+#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
+
+register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
+#define current_thread_info()  __current_thread_info
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files
+ *   may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+
+#define TIF_SYSCALL_TRACE       0       /* syscall trace active */
+#define TIF_NOTIFY_RESUME       1       /* resumption notification requested */
+#define TIF_SIGPENDING          2       /* signal pending */
+#define TIF_NEED_RESCHED        3       /* rescheduling necessary */
+#define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
+#define TIF_IRET                5       /* return with iret */
+#define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG      16
+#define TIF_MEMDIE              17      /* OOM killer killed process */
+
+#define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME      (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
+#define _TIF_IRET               (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
+#define _TIF_WORK_MASK          (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK       0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/time.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/time.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/time.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_TIME_H
+#define ASM_TIME_H
+
+extern cycles_t        pcycle_freq_mhz;
+extern cycles_t        thread_freq_mhz;
+extern cycles_t        sleep_clk_freq;
+
+void setup_percpu_clockdev(void);
+void ipi_timer(void);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/timer-regs.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/timer-regs.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/timer-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/timer-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * Timer support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+/*  This stuff should go into a platform specific file  */
+#define TCX0_CLK_RATE		19200
+#define TIMER_ENABLE		0
+#define TIMER_CLR_ON_MATCH	1
+
+/*
+ * 8x50 HDD Specs 5-8.  Simulator co-sim not fixed until
+ * release 1.1, and then it's "adjustable" and probably not defaulted.
+ */
+#define RTOS_TIMER_INT		3
+#ifdef CONFIG_HEXAGON_COMET
+#define RTOS_TIMER_REGS_ADDR	0xAB000000UL
+#endif
+#define SLEEP_CLK_RATE		32000
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/timex.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/timex.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#include <asm-generic/timex.h>
+#include <asm/timer-regs.h>
+
+/* Using TCX0 as our clock.  CLOCK_TICK_RATE scheduled to be removed. */
+#define CLOCK_TICK_RATE              TCX0_CLK_RATE
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+static inline int read_current_timer(unsigned long *timer_val)
+{
+	*timer_val = (unsigned long) __vmgettime();
+	return 0;
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/tlbflush.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/tlbflush.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/tlbflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * TLB flush support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+/*
+ * TLB flushing -- in "SMP", these routines get defined to be the
+ * ones from smp.c, else they are some local flavors.
+ */
+
+/*
+ * These functions are commonly macros, but in the interests of
+ * VM vs. native implementation and code size, we simply declare
+ * the function prototypes here.
+ */
+extern void tlb_flush_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma,
+				unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long);
+
+/*
+ * "This is called in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here..."
+ *
+ * The VM kernel doesn't walk page tables, and they are passed to the VMM
+ * by logical address. There doesn't seem to be any possibility that they
+ * could be referenced by the VM kernel based on a stale mapping, since
+ * they would only be located by consulting the mm structure, and they
+ * will have been purged from that structure by the munmap.  Seems like
+ * a noop on HVM as well.
+ */
+#define flush_tlb_pgtables(mm, start, end)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/tlb.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/tlb.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/tlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/tlb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <linux/pagemap.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't need any special per-pte or per-vma handling...
+ */
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb)		flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/traps.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/traps.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/traps.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/traps.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Trap support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_TRAPS_H
+#define _ASM_HEXAGON_TRAPS_H
+
+#include <asm/registers.h>
+
+extern int die(const char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
+
+#endif /* _ASM_HEXAGON_TRAPS_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/uaccess.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/uaccess.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/uaccess.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/*
+ * User memory access support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+
+/*
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block *may* be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * User address space in Hexagon, like x86, goes to 0xbfffffff, so the
+ * simple MSB-based tests used by MIPS won't work.  Some further
+ * optimization is probably possible here, but for now, keep it
+ * reasonably simple and not *too* slow.  After all, we've got the
+ * MMU for backup.
+ */
+#define VERIFY_READ     0
+#define VERIFY_WRITE    1
+
+#define __access_ok(addr, size) \
+	((get_fs().seg == KERNEL_DS.seg) || \
+	(((unsigned long)addr < get_fs().seg) && \
+	  (unsigned long)size < (get_fs().seg - (unsigned long)addr)))
+
+/*
+ * When a kernel-mode page fault is taken, the faulting instruction
+ * address is checked against a table of exception_table_entries.
+ * Each entry is a tuple of the address of an instruction that may
+ * be authorized to fault, and the address at which execution should
+ * be resumed instead of the faulting instruction, so as to effect
+ * a workaround.
+ */
+
+/*  Assembly somewhat optimized copy routines  */
+unsigned long __copy_from_user_hexagon(void *to, const void __user *from,
+				     unsigned long n);
+unsigned long __copy_to_user_hexagon(void __user *to, const void *from,
+				   unsigned long n);
+
+#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n)
+#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n)
+
+/*
+ * XXX todo: some additonal performance gain is possible by
+ * implementing __copy_to/from_user_inatomic, which is much
+ * like __copy_to/from_user, but performs slightly less checking.
+ */
+
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
+#define __clear_user(a, s) __clear_user_hexagon((a), (s))
+
+#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
+
+/*  get around the ifndef in asm-generic/uaccess.h  */
+#define __strnlen_user __strnlen_user
+
+extern long __strnlen_user(const char __user *src, long n);
+
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n);
+
+#include <asm-generic/uaccess.h>
+
+/*  Todo:  an actual accelerated version of this.  */
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n)
+{
+	long res = __strnlen_user(src, n);
+
+	/* return from strnlen can't be zero -- that would be rubbish. */
+
+	if (res > n) {
+		copy_from_user(dst, src, n);
+		return n;
+	} else {
+		copy_from_user(dst, src, res);
+		return res-1;
+	}
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/unistd.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/unistd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
+#define _ASM_HEXAGON_UNISTD_H
+
+/*
+ *  The kernel pulls this unistd.h in three different ways:
+ *  1.  the "normal" way which gets all the __NR defines
+ *  2.  with __SYSCALL defined to produce function declarations
+ *  3.  with __SYSCALL defined to produce syscall table initialization
+ *  See also:  syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/user.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/user.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef HEXAGON_ASM_USER_H
+#define HEXAGON_ASM_USER_H
+
+/*
+ * Layout for registers passed in elf core dumps to userspace.
+ *
+ * Basically a rearranged subset of "pt_regs".
+ *
+ * Interested parties:  libc, gdb...
+ */
+
+struct user_regs_struct {
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long r15;
+	unsigned long r16;
+	unsigned long r17;
+	unsigned long r18;
+	unsigned long r19;
+	unsigned long r20;
+	unsigned long r21;
+	unsigned long r22;
+	unsigned long r23;
+	unsigned long r24;
+	unsigned long r25;
+	unsigned long r26;
+	unsigned long r27;
+	unsigned long r28;
+	unsigned long r29;
+	unsigned long r30;
+	unsigned long r31;
+	unsigned long sa0;
+	unsigned long lc0;
+	unsigned long sa1;
+	unsigned long lc1;
+	unsigned long m0;
+	unsigned long m1;
+	unsigned long usr;
+	unsigned long p3_0;
+	unsigned long gp;
+	unsigned long ugp;
+	unsigned long pc;
+	unsigned long cause;
+	unsigned long badva;
+	unsigned long pad1;  /* pad out to 48 words total */
+	unsigned long pad2;  /* pad out to 48 words total */
+	unsigned long pad3;  /* pad out to 48 words total */
+};
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/vdso.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/vdso.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/vdso.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/vdso.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#include <linux/types.h>
+
+struct hexagon_vdso {
+	u32 rt_signal_trampoline[2];
+};
+
+#endif /* __ASM_VDSO_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/vm_fault.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/vm_fault.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/vm_fault.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/vm_fault.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_VM_FAULT_H
+#define _ASM_HEXAGON_VM_FAULT_H
+
+extern void execute_protection_fault(struct pt_regs *);
+extern void write_protection_fault(struct pt_regs *);
+extern void read_protection_fault(struct pt_regs *);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/include/asm/vm_mmu.h linux-libre-3.2-gnu1/arch/hexagon/include/asm/vm_mmu.h
--- linux-libre-3.1-gnu1/arch/hexagon/include/asm/vm_mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/include/asm/vm_mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,111 @@
+/*
+ * Hexagon VM page table entry definitions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_VM_MMU_H
+#define _ASM_VM_MMU_H
+
+/*
+ * Shift, mask, and other constants for the Hexagon Virtual Machine
+ * page tables.
+ *
+ * Virtual machine MMU allows first-level entries to either be
+ * single-level lookup PTEs for very large pages, or PDEs pointing
+ * to second-level PTEs for smaller pages. If PTE is single-level,
+ * the least significant bits cannot be used as software bits to encode
+ * virtual memory subsystem information about the page, and that state
+ * must be maintained in some parallel data structure.
+ */
+
+/* S or Page Size field in PDE */
+#define	__HVM_PDE_S		(0x7 << 0)
+#define __HVM_PDE_S_4KB		0
+#define __HVM_PDE_S_16KB	1
+#define __HVM_PDE_S_64KB	2
+#define __HVM_PDE_S_256KB	3
+#define __HVM_PDE_S_1MB		4
+#define __HVM_PDE_S_4MB		5
+#define __HVM_PDE_S_16MB	6
+#define __HVM_PDE_S_INVALID	7
+
+/* Masks for L2 page table pointer, as function of page size */
+#define __HVM_PDE_PTMASK_4KB	0xfffff000
+#define __HVM_PDE_PTMASK_16KB	0xfffffc00
+#define __HVM_PDE_PTMASK_64KB	0xffffff00
+#define __HVM_PDE_PTMASK_256KB	0xffffffc0
+#define __HVM_PDE_PTMASK_1MB	0xfffffff0
+
+/*
+ * Virtual Machine PTE Bits/Fields
+ */
+#define __HVM_PTE_T		(1<<4)
+#define __HVM_PTE_U		(1<<5)
+#define	__HVM_PTE_C		(0x7<<6)
+#define __HVM_PTE_CVAL(pte)	(((pte) & __HVM_PTE_C) >> 6)
+#define __HVM_PTE_R		(1<<9)
+#define __HVM_PTE_W		(1<<10)
+#define __HVM_PTE_X		(1<<11)
+
+/*
+ * Cache Attributes, to be shifted as necessary for virtual/physical PTEs
+ */
+
+#define __HEXAGON_C_WB		0x0	/* Write-back, no L2 */
+#define	__HEXAGON_C_WT		0x1	/* Write-through, no L2 */
+#define	__HEXAGON_C_DEV		0x4	/* Device register space */
+#define	__HEXAGON_C_WT_L2	0x5	/* Write-through, with L2 */
+/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
+#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
+#define __HEXAGON_C_UNC		__HEXAGON_C_DEV
+#else
+#define	__HEXAGON_C_UNC		0x6	/* Uncached memory */
+#endif
+#define	__HEXAGON_C_WB_L2	0x7	/* Write-back, with L2 */
+
+/*
+ * This can be overriden, but we're defaulting to the most aggressive
+ * cache policy, the better to find bugs sooner.
+ */
+
+#define	CACHE_DEFAULT	__HEXAGON_C_WB_L2
+
+/* Masks for physical page address, as a function of page size */
+
+#define __HVM_PTE_PGMASK_4KB	0xfffff000
+#define __HVM_PTE_PGMASK_16KB	0xffffc000
+#define __HVM_PTE_PGMASK_64KB	0xffff0000
+#define __HVM_PTE_PGMASK_256KB	0xfffc0000
+#define __HVM_PTE_PGMASK_1MB	0xfff00000
+
+/* Masks for single-level large page lookups */
+
+#define __HVM_PTE_PGMASK_4MB	0xffc00000
+#define __HVM_PTE_PGMASK_16MB	0xff000000
+
+/*
+ * "Big kernel page mappings" (see vm_init_segtable.S)
+ * are currently 16MB
+ */
+
+#define BIG_KERNEL_PAGE_SHIFT 24
+#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
+
+
+
+#endif /* _ASM_VM_MMU_H */
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/Kconfig linux-libre-3.2-gnu1/arch/hexagon/Kconfig
--- linux-libre-3.1-gnu1/arch/hexagon/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+# Hexagon configuration
+comment "Linux Kernel Configuration for Hexagon"
+
+config HEXAGON
+	def_bool y
+	select HAVE_OPROFILE
+	select USE_GENERIC_SMP_HELPERS if SMP
+	# Other pending projects/to-do items.
+	# select HAVE_REGS_AND_STACK_ACCESS_API
+	# select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	# select ARCH_HAS_CPU_IDLE_WAIT
+	# select ARCH_WANT_OPTIONAL_GPIOLIB
+	# select ARCH_REQUIRE_GPIOLIB
+	# select HAVE_CLK
+	# select IRQ_PER_CPU
+	select HAVE_IRQ_WORK
+	# select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_ATOMIC64
+	select HAVE_PERF_EVENTS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
+	select GENERIC_ALLOCATOR
+	select GENERIC_IRQ_SHOW
+	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_TRACEHOOK
+	select NO_IOPORT
+	# mostly generic routines, with some accelerated ones
+	---help---
+	  Qualcomm Hexagon is a processor architecture designed for high
+	  performance and low power across a wide variety of applications.
+
+config HEXAGON_ARCH_V1
+	bool
+
+config HEXAGON_ARCH_V2
+	bool
+
+config HEXAGON_ARCH_V3
+	bool
+
+config HEXAGON_ARCH_V4
+	bool
+
+config FRAME_POINTER
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config PCI
+	def_bool n
+
+config EARLY_PRINTK
+	def_bool y
+
+config KTIME_SCALAR
+	def_bool y
+
+config MMU
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config GENERIC_CSUM
+	def_bool y
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_IRQ_PROBE
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+#config ZONE_DMA
+#	bool
+#	default y
+
+config HAS_DMA
+	bool
+	select HAVE_DMA_ATTRS
+	default y
+
+config NEED_SG_DMA_LENGTH
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool n
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_TIME
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	def_bool y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+	def_bool y
+
+config STACKTRACE_SUPPORT
+	def_bool y
+	select STACKTRACE
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+
+config BUG
+	def_bool y
+
+menu "Machine selection"
+
+choice
+	prompt "System type"
+	default HEXAGON_ARCH_V2
+
+config HEXAGON_COMET
+	bool "Comet Board"
+	select HEXAGON_ARCH_V2
+	---help---
+	  Support for the Comet platform.
+
+endchoice
+
+config HEXAGON_VM
+	def_bool y
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+	  On some platforms, there is currently no way for the boot loader
+	  to pass arguments to the kernel. For these, you should supply some
+	  command-line options at build time by entering them here.  At a
+	  minimum, you should specify the memory size and the root device
+	  (e.g., mem=64M root=/dev/nfs).
+
+config HEXAGON_ANGEL_TRAPS
+	bool "Use Angel Traps"
+	default n
+	---help---
+	  Enable angel debug traps (for printk's).
+
+config SMP
+	bool "Multi-Processing support"
+	---help---
+	  Enables SMP support in the kernel.  If unsure, say "Y"
+
+config NR_CPUS
+	int "Maximum number of CPUs" if SMP
+	range 2 6 if SMP
+	default "1" if !SMP
+	default "6" if SMP
+	---help---
+	  This allows you to specify the maximum number of CPUs which this
+	  kernel will support.  The maximum supported value is 6 and the
+	  minimum value which makes sense is 2.
+
+	  This is purely to save memory - each supported CPU adds
+	  approximately eight kilobytes to the kernel image.
+
+choice
+	prompt "Kernel page size"
+	default PAGE_SIZE_4KB
+	---help---
+	  Changes the default page size; use with caution.
+
+config PAGE_SIZE_4KB
+	bool "4KB"
+
+config PAGE_SIZE_16KB
+	bool "16KB"
+
+config PAGE_SIZE_64KB
+	bool "64KB"
+
+config PAGE_SIZE_256KB
+	bool "256KB"
+
+endchoice
+
+source "mm/Kconfig"
+
+source "kernel/Kconfig.hz"
+source "kernel/time/Kconfig"
+
+config GENERIC_GPIO
+	bool "Generic GPIO support"
+	default n
+
+endmenu
+
+source "init/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Executable File Formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/asm-offsets.c linux-libre-3.2-gnu1/arch/hexagon/kernel/asm-offsets.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/asm-offsets.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kbuild.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+/*  This file is used to produce asm/linkerscript constants from header
+    files typically used in c.  Specifically, it generates asm-offsets.h  */
+
+int main(void)
+{
+	COMMENT("This is a comment.");
+	/*  might get these from somewhere else.  */
+	DEFINE(_PAGE_SIZE, PAGE_SIZE);
+	DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+	BLANK();
+
+	COMMENT("Hexagon pt_regs definitions");
+	OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
+	OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+	OFFSET(_PT_R3130, pt_regs, r3130);
+	OFFSET(_PT_R2928, pt_regs, r2928);
+	OFFSET(_PT_R2726, pt_regs, r2726);
+	OFFSET(_PT_R2524, pt_regs, r2524);
+	OFFSET(_PT_R2322, pt_regs, r2322);
+	OFFSET(_PT_R2120, pt_regs, r2120);
+	OFFSET(_PT_R1918, pt_regs, r1918);
+	OFFSET(_PT_R1716, pt_regs, r1716);
+	OFFSET(_PT_R1514, pt_regs, r1514);
+	OFFSET(_PT_R1312, pt_regs, r1312);
+	OFFSET(_PT_R1110, pt_regs, r1110);
+	OFFSET(_PT_R0908, pt_regs, r0908);
+	OFFSET(_PT_R0706, pt_regs, r0706);
+	OFFSET(_PT_R0504, pt_regs, r0504);
+	OFFSET(_PT_R0302, pt_regs, r0302);
+	OFFSET(_PT_R0100, pt_regs, r0100);
+	OFFSET(_PT_LC0SA0, pt_regs, lc0sa0);
+	OFFSET(_PT_LC1SA1, pt_regs, lc1sa1);
+	OFFSET(_PT_M1M0, pt_regs, m1m0);
+	OFFSET(_PT_PREDSUSR, pt_regs, predsusr);
+	OFFSET(_PT_EVREC, pt_regs, hvmer);
+	OFFSET(_PT_ER_VMEL, pt_regs, hvmer.vmel);
+	OFFSET(_PT_ER_VMEST, pt_regs, hvmer.vmest);
+	OFFSET(_PT_ER_VMPSP, pt_regs, hvmer.vmpsp);
+	OFFSET(_PT_ER_VMBADVA, pt_regs, hvmer.vmbadva);
+	DEFINE(_PT_REGS_SIZE, sizeof(struct pt_regs));
+	BLANK();
+
+	COMMENT("Hexagon thread_info definitions");
+	OFFSET(_THREAD_INFO_FLAGS, thread_info, flags);
+	OFFSET(_THREAD_INFO_PT_REGS, thread_info, regs);
+	OFFSET(_THREAD_INFO_SP, thread_info, sp);
+	DEFINE(_THREAD_SIZE, THREAD_SIZE);
+	BLANK();
+
+	COMMENT("Hexagon hexagon_switch_stack definitions");
+	OFFSET(_SWITCH_R1716, hexagon_switch_stack, r1716);
+	OFFSET(_SWITCH_R1918, hexagon_switch_stack, r1918);
+	OFFSET(_SWITCH_R2120, hexagon_switch_stack, r2120);
+	OFFSET(_SWITCH_R2322, hexagon_switch_stack, r2322);
+
+	OFFSET(_SWITCH_R2524, hexagon_switch_stack, r2524);
+	OFFSET(_SWITCH_R2726, hexagon_switch_stack, r2726);
+	OFFSET(_SWITCH_FP, hexagon_switch_stack, fp);
+	OFFSET(_SWITCH_LR, hexagon_switch_stack, lr);
+	DEFINE(_SWITCH_STACK_SIZE, sizeof(struct hexagon_switch_stack));
+	BLANK();
+
+	COMMENT("Hexagon task_struct definitions");
+	OFFSET(_TASK_THREAD_INFO, task_struct, stack);
+	OFFSET(_TASK_STRUCT_THREAD, task_struct, thread);
+
+	COMMENT("Hexagon thread_struct definitions");
+	OFFSET(_THREAD_STRUCT_SWITCH_SP, thread_struct, switch_sp);
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/dma.c linux-libre-3.2-gnu1/arch/hexagon/kernel/dma.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+/*
+ * DMA implementation for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/genalloc.h>
+#include <asm/dma-mapping.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+int bad_dma_address;  /*  globals are automatically initialized to zero  */
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	if (mask == DMA_BIT_MASK(32))
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+static struct gen_pool *coherent_pool;
+
+
+/* Allocates from a pool of uncached memory that was reserved at boot time */
+
+void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_addr, gfp_t flag)
+{
+	void *ret;
+
+	if (coherent_pool == NULL) {
+		coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
+
+		if (coherent_pool == NULL)
+			panic("Can't create %s() memory pool!", __func__);
+		else
+			gen_pool_add(coherent_pool,
+				(PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)),
+				hexagon_coherent_pool_size, -1);
+	}
+
+	ret = (void *) gen_pool_alloc(coherent_pool, size);
+
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_addr = (dma_addr_t) (ret - PAGE_OFFSET);
+	} else
+		*dma_addr = ~0;
+
+	return ret;
+}
+
+static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
+				  dma_addr_t dma_addr)
+{
+	gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
+}
+
+static int check_addr(const char *name, struct device *hwdev,
+		      dma_addr_t bus, size_t size)
+{
+	if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
+		if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
+			printk(KERN_ERR
+				"%s: overflow %Lx+%zu of device mask %Lx\n",
+				name, (long long)bus, size,
+				(long long)*hwdev->dma_mask);
+		return 0;
+	}
+	return 1;
+}
+
+static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
+			  int nents, enum dma_data_direction dir,
+			  struct dma_attrs *attrs)
+{
+	struct scatterlist *s;
+	int i;
+
+	WARN_ON(nents == 0 || sg[0].length == 0);
+
+	for_each_sg(sg, s, nents, i) {
+		s->dma_address = sg_phys(s);
+		if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+			return 0;
+
+		s->dma_length = s->length;
+
+		flush_dcache_range(PAGE_OFFSET + s->dma_address,
+				   PAGE_OFFSET + s->dma_address + s->length);
+	}
+
+	return nents;
+}
+
+/*
+ * address is virtual
+ */
+static inline void dma_sync(void *addr, size_t size,
+			    enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		hexagon_clean_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_FROM_DEVICE:
+		hexagon_inv_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_BIDIRECTIONAL:
+		flush_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
+{
+	return phys_to_virt((unsigned long) dma_addr);
+}
+
+/**
+ * hexagon_map_page() - maps an address for device DMA
+ * @dev:	pointer to DMA device
+ * @page:	pointer to page struct of DMA memory
+ * @offset:	offset within page
+ * @size:	size of memory to map
+ * @dir:	transfer direction
+ * @attrs:	pointer to DMA attrs (not used)
+ *
+ * Called to map a memory address to a DMA address prior
+ * to accesses to/from device.
+ *
+ * We don't particularly have many hoops to jump through
+ * so far.  Straight translation between phys and virtual.
+ *
+ * DMA is not cache coherent so sync is necessary; this
+ * seems to be a convenient place to do it.
+ *
+ */
+static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
+				   unsigned long offset, size_t size,
+				   enum dma_data_direction dir,
+				   struct dma_attrs *attrs)
+{
+	dma_addr_t bus = page_to_phys(page) + offset;
+	WARN_ON(size == 0);
+
+	if (!check_addr("map_single", dev, bus, size))
+		return bad_dma_address;
+
+	dma_sync(dma_addr_to_virt(bus), size, dir);
+
+	return bus;
+}
+
+static void hexagon_sync_single_for_cpu(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+static void hexagon_sync_single_for_device(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+struct dma_map_ops hexagon_dma_ops = {
+	.alloc_coherent	= hexagon_dma_alloc_coherent,
+	.free_coherent	= hexagon_free_coherent,
+	.map_sg		= hexagon_map_sg,
+	.map_page	= hexagon_map_page,
+	.sync_single_for_cpu = hexagon_sync_single_for_cpu,
+	.sync_single_for_device = hexagon_sync_single_for_device,
+	.is_phys	= 1,
+};
+
+void __init hexagon_dma_init(void)
+{
+	if (dma_ops)
+		return;
+
+	dma_ops = &hexagon_dma_ops;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/head.S linux-libre-3.2-gnu1/arch/hexagon/kernel/head.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/head.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Early kernel startup code for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/mem-layout.h>
+#include <asm/vm_mmu.h>
+#include <asm/page.h>
+
+	__INIT
+ENTRY(stext)
+	/*
+	 * VMM will already have set up true vector page, MMU, etc.
+	 * To set up initial kernel identity map, we have to pass
+	 * the VMM a pointer to some canonical page tables. In
+	 * this implementation, we're assuming that we've got
+	 * them precompiled. Generate value in R24, as we'll need
+	 * it again shortly.
+	 */
+	r24.L = #LO(swapper_pg_dir)
+	r24.H = #HI(swapper_pg_dir)
+
+	/*
+	 * Symbol is kernel segment address, but we need
+	 * the logical/physical address.
+	 */
+	r24 = asl(r24, #2)
+	r24 = lsr(r24, #2)
+
+	r0 = r24
+
+	/*
+	 * Initialize a 16MB PTE to make the virtual and physical
+	 * addresses where the kernel was loaded be identical.
+	 */
+#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		  | __HEXAGON_C_WB_L2 << 6			\
+		  | __HVM_PDE_S_4MB)
+
+	r1 = pc
+	r2.H = #0xffc0
+	r2.L = #0x0000
+	r1 = and(r1,r2)		/* round PC to 4MB boundary	*/
+	r2 = lsr(r1, #22)	/* 4MB page number		*/
+	r2 = asl(r2, #2)	/* times sizeof(PTE) (4bytes)	*/
+	r0 = add(r0,r2)		/* r0 = address of correct PTE	*/
+	r2 = #PTE_BITS
+	r1 = add(r1,r2)		/* r1 = 4MB PTE for the first entry	*/
+	r2.h = #0x0040
+	r2.l = #0x0000		/* 4MB	*/
+	memw(r0 ++ #4) = r1
+	r1 = add(r1, r2)
+	memw(r0 ++ #4) = r1
+
+	r0 = r24
+
+	/*
+	 * The subroutine wrapper around the virtual instruction touches
+	 * no memory, so we should be able to use it even here.
+	 */
+	call	__vmnewmap;
+
+	/*  Jump into virtual address range.  */
+
+	r31.h = #hi(__head_s_vaddr_target)
+	r31.l = #lo(__head_s_vaddr_target)
+	jumpr r31
+
+	/*  Insert trippy space effects.  */
+
+__head_s_vaddr_target:
+	/*
+	 * Tear down VA=PA translation now that we are running
+	 * in the desgnated kernel segments.
+	 */
+	r0 = #__HVM_PDE_S_INVALID
+	r1 = r24
+	loop0(1f,#0x100)
+1:
+	{
+		memw(R1 ++ #4) = R0
+	}:endloop0
+
+	r0 = r24
+	call __vmnewmap
+
+	/*  Go ahead and install the trap0 return so angel calls work  */
+	r0.h = #hi(_K_provisional_vec)
+	r0.l = #lo(_K_provisional_vec)
+	call __vmsetvec
+
+	/*
+	 * OK, at this point we should start to be much more careful,
+	 * we're going to enter C code and start touching memory
+	 * in all sorts of places.
+	 * This means:
+	 *      SGP needs to be OK
+	 *	Need to lock shared resources
+	 *	A bunch of other things that will cause
+	 * 	all kinds of painful bugs
+	 */
+
+	/*
+	 * Stack pointer should be pointed at the init task's
+	 * thread stack, which should have been declared in arch/init_task.c.
+	 * So uhhhhh...
+	 * It's accessible via the init_thread_union, which is a union
+	 * of a thread_info struct and a stack; of course, the top
+	 * of the stack is not for you.  The end of the stack
+	 * is simply init_thread_union + THREAD_SIZE.
+	 */
+
+	{r29.H = #HI(init_thread_union); r0.H = #HI(_THREAD_SIZE); }
+	{r29.L = #LO(init_thread_union); r0.L = #LO(_THREAD_SIZE); }
+
+	/*  initialize the register used to point to current_thread_info */
+	/*  Fixme:  THREADINFO_REG can't be R2 because of that memset thing. */
+	{r29 = add(r29,r0); THREADINFO_REG = r29; }
+
+	/*  Hack:  zero bss; */
+	{ r0.L = #LO(__bss_start);  r1 = #0; r2.l = #LO(__bss_stop); }
+	{ r0.H = #HI(__bss_start);           r2.h = #HI(__bss_stop); }
+
+	r2 = sub(r2,r0);
+	call memset;
+
+	/* Time to make the doughnuts.   */
+	call start_kernel
+
+	/*
+	 * Should not reach here.
+	 */
+1:
+	jump 1b
+
+.p2align PAGE_SHIFT
+ENTRY(external_cmdline_buffer)
+        .fill _PAGE_SIZE,1,0
+
+.data
+.p2align PAGE_SHIFT
+ENTRY(empty_zero_page)
+        .fill _PAGE_SIZE,1,0
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/hexagon_ksyms.c linux-libre-3.2-gnu1/arch/hexagon/kernel/hexagon_ksyms.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/hexagon_ksyms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/hexagon_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/*
+ * Export of symbols defined in assembly files and/or libgcc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(__copy_from_user_hexagon);
+EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__vmgetie);
+EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+#define DECLARE_EXPORT(name)     \
+	extern void name(void); EXPORT_SYMBOL(name)
+
+/* Symbols found in libgcc that assorted kernel modules need */
+DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
+
+DECLARE_EXPORT(__hexagon_divsi3);
+DECLARE_EXPORT(__hexagon_modsi3);
+DECLARE_EXPORT(__hexagon_udivsi3);
+DECLARE_EXPORT(__hexagon_umodsi3);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/init_task.c linux-libre-3.2-gnu1/arch/hexagon/kernel/init_task.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/init_task.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Init task definition
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ */
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"),
+		__aligned__(THREAD_SIZE))) = {
+			INIT_THREAD_INFO(init_task)
+		};
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/irq_cpu.c linux-libre-3.2-gnu1/arch/hexagon/kernel/irq_cpu.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/irq_cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/irq_cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * First-level interrupt controller model for Hexagon.
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/hexagon_vm.h>
+
+static void mask_irq(struct irq_data *data)
+{
+	__vmintop_locdis((long) data->irq);
+}
+
+static void mask_irq_num(unsigned int irq)
+{
+	__vmintop_locdis((long) irq);
+}
+
+static void unmask_irq(struct irq_data *data)
+{
+	__vmintop_locen((long) data->irq);
+}
+
+/*  This is actually all we need for handle_fasteoi_irq  */
+static void eoi_irq(struct irq_data *data)
+{
+	__vmintop_globen((long) data->irq);
+}
+
+/* Power mamangement wake call. We don't need this, however,
+ * if this is absent, then an -ENXIO error is returned to the
+ * msm_serial driver, and it fails to correctly initialize.
+ * This is a bug in the msm_serial driver, but, for now, we
+ * work around it here, by providing this bogus handler.
+ * XXX FIXME!!! remove this when msm_serial is fixed.
+ */
+static int set_wake(struct irq_data *data, unsigned int on)
+{
+	return 0;
+}
+
+static struct irq_chip hexagon_irq_chip = {
+	.name		= "HEXAGON",
+	.irq_mask	= mask_irq,
+	.irq_unmask	= unmask_irq,
+	.irq_set_wake	= set_wake,
+	.irq_eoi	= eoi_irq
+};
+
+/**
+ * The hexagon core comes with a first-level interrupt controller
+ * with 32 total possible interrupts.  When the core is embedded
+ * into different systems/platforms, it is typically wrapped by
+ * macro cells that provide one or more second-level interrupt
+ * controllers that are cascaded into one or more of the first-level
+ * interrupts handled here. The precise wiring of these other
+ * irqs varies from platform to platform, and are set up & configured
+ * in the platform-specific files.
+ *
+ * The first-level interrupt controller is wrapped by the VM, which
+ * virtualizes the interrupt controller for us.  It provides a very
+ * simple, fast & efficient API, and so the fasteoi handler is
+ * appropriate for this case.
+ */
+void __init init_IRQ(void)
+{
+	int irq;
+
+	for (irq = 0; irq < HEXAGON_CPUINTS; irq++) {
+		mask_irq_num(irq);
+		irq_set_chip_and_handler(irq, &hexagon_irq_chip,
+						 handle_fasteoi_irq);
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/kgdb.c linux-libre-3.2-gnu1/arch/hexagon/kernel/kgdb.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/kgdb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,254 @@
+/*
+ * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kdebug.h>
+#include <linux/kgdb.h>
+
+/* All registers are 4 bytes, for now */
+#define GDB_SIZEOF_REG 4
+
+/* The register names are used during printing of the regs;
+ * Keep these at three letters to pretty-print. */
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+	{ " r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, r00)},
+	{ " r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, r01)},
+	{ " r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r02)},
+	{ " r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r03)},
+	{ " r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r04)},
+	{ " r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r05)},
+	{ " r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r06)},
+	{ " r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r07)},
+	{ " r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r08)},
+	{ " r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r09)},
+	{ "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10)},
+	{ "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11)},
+	{ "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12)},
+	{ "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13)},
+	{ "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14)},
+	{ "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15)},
+	{ "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, r16)},
+	{ "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, r17)},
+	{ "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, r18)},
+	{ "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, r19)},
+	{ "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, r20)},
+	{ "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, r21)},
+	{ "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, r22)},
+	{ "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, r23)},
+	{ "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, r24)},
+	{ "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, r25)},
+	{ "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, r26)},
+	{ "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, r27)},
+	{ "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, r28)},
+	{ "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, r29)},
+	{ "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, r30)},
+	{ "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, r31)},
+
+	{ "usr", GDB_SIZEOF_REG, offsetof(struct pt_regs, usr)},
+	{ "preds", GDB_SIZEOF_REG, offsetof(struct pt_regs, preds)},
+	{ " m0", GDB_SIZEOF_REG, offsetof(struct pt_regs, m0)},
+	{ " m1", GDB_SIZEOF_REG, offsetof(struct pt_regs, m1)},
+	{ "sa0", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa0)},
+	{ "sa1", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa1)},
+	{ "lc0", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc0)},
+	{ "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
+	{ " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
+	{ "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
+	{ "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
+	{ "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
+	{ "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
+	{ "badva", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmbadva)},
+	{ "restart_r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, restart_r0)},
+	{ "syscall_nr", GDB_SIZEOF_REG, offsetof(struct pt_regs, syscall_nr)},
+};
+
+struct kgdb_arch arch_kgdb_ops = {
+	/* trap0(#0xDB) 0x0cdb0054 */
+	.gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x0c},
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return NULL;
+
+	*((unsigned long *) mem) = *((unsigned long *) ((void *)regs +
+		dbg_reg_def[regno].offset));
+
+	return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return -EINVAL;
+
+	*((unsigned long *) ((void *)regs + dbg_reg_def[regno].offset)) =
+		*((unsigned long *) mem);
+
+	return 0;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+	instruction_pointer(regs) = pc;
+}
+
+#ifdef CONFIG_SMP
+
+/**
+ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
+ * @flags: Current IRQ state
+ *
+ * On SMP systems, we need to get the attention of the other CPUs
+ * and get them be in a known state.  This should do what is needed
+ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
+ * the NMI approach is not used for rounding up all the CPUs. For example,
+ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
+ * this case, we have to make sure that interrupts are enabled before
+ * calling smp_call_function(). The argument to this function is
+ * the flags that will be used when restoring the interrupts. There is
+ * local_irq_save() call before kgdb_roundup_cpus().
+ *
+ * On non-SMP systems, this is not called.
+ */
+
+static void hexagon_kgdb_nmi_hook(void *ignored)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_enable();
+	smp_call_function(hexagon_kgdb_nmi_hook, NULL, 0);
+	local_irq_disable();
+}
+#endif
+
+
+/*  Not yet working  */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+				 struct task_struct *task)
+{
+	struct pt_regs *thread_regs;
+
+	if (task == NULL)
+		return;
+
+	/* Initialize to zero */
+	memset(gdb_regs, 0, NUMREGBYTES);
+
+	/* Otherwise, we have only some registers from switch_to() */
+	thread_regs = task_pt_regs(task);
+	gdb_regs[0] = thread_regs->r00;
+}
+
+/**
+ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
+ * @vector: The error vector of the exception that happened.
+ * @signo: The signal number of the exception that happened.
+ * @err_code: The error code of the exception that happened.
+ * @remcom_in_buffer: The buffer of the packet we have read.
+ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
+ * @regs: The &struct pt_regs of the current process.
+ *
+ * This function MUST handle the 'c' and 's' command packets,
+ * as well packets to set / remove a hardware breakpoint, if used.
+ * If there are additional packets which the hardware needs to handle,
+ * they are handled here.  The code should return -1 if it wants to
+ * process more packets, and a %0 or %1 if it wants to exit from the
+ * kgdb callback.
+ *
+ * Not yet working.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	switch (remcom_in_buffer[0]) {
+	case 's':
+	case 'c':
+		return 0;
+	}
+	/* Stay in the debugger. */
+	return -1;
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	/* cpu roundup */
+	if (atomic_read(&kgdb_active) != -1) {
+		kgdb_nmicallback(smp_processor_id(), args->regs);
+		return NOTIFY_STOP;
+	}
+
+	if (user_mode(args->regs))
+		return NOTIFY_DONE;
+
+	if (kgdb_handle_exception(args->trapnr & 0xff, args->signr, args->err,
+				    args->regs))
+		return NOTIFY_DONE;
+
+	return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+	ret = __kgdb_notify(ptr, cmd);
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call = kgdb_notify,
+
+	/*
+	 * Lowest-prio notifier priority, we want to be notified last:
+	 */
+	.priority = -INT_MAX,
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+	return register_die_notifier(&kgdb_notifier);
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+	unregister_die_notifier(&kgdb_notifier);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/Makefile linux-libre-3.2-gnu1/arch/hexagon/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-$(CONFIG_SMP) += smp.o topology.o
+
+obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
+obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
+obj-y += vdso.o
+
+obj-$(CONFIG_KGDB)    += kgdb.o
+obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
+
+# Modules required to work with the Hexagon Virtual Machine
+obj-y += vm_entry.o vm_events.o vm_switch.o vm_ops.o vm_init_segtable.o
+obj-y += vm_vectors.o
+
+obj-$(CONFIG_HAS_DMA) += dma.o
+
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/module.c linux-libre-3.2-gnu1/arch/hexagon/kernel/module.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Kernel module loader for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/module.h>
+#include <linux/elf.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+/*
+ * module_frob_arch_sections - tweak got/plt sections.
+ * @hdr - pointer to elf header
+ * @sechdrs - pointer to elf load section headers
+ * @secstrings - symbol names
+ * @mod - pointer to module
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+				char *secstrings,
+				struct module *mod)
+{
+	unsigned int i;
+	int found = 0;
+
+	/* Look for .plt and/or .got.plt and/or .init.plt sections */
+	for (i = 0; i < hdr->e_shnum; i++) {
+		DEBUGP("Section %d is %s\n", i,
+		       secstrings + sechdrs[i].sh_name);
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".got.plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".rela.plt") == 0)
+			found = i+1;
+	}
+
+	/* At this time, we don't support modules comiled with -shared */
+	if (found) {
+		printk(KERN_WARNING
+			"Module '%s' contains unexpected .plt/.got sections.\n",
+			mod->name);
+		/*  return -ENOEXEC;  */
+	}
+
+	return 0;
+}
+
+/*
+ * apply_relocate_add - perform rela relocations.
+ * @sechdrs - pointer to section headers
+ * @strtab - some sort of start address?
+ * @symindex - symbol index offset or something?
+ * @relsec - address to relocate to?
+ * @module - pointer to module
+ *
+ * Perform rela relocations.
+ */
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+			unsigned int symindex, unsigned int relsec,
+			struct module *module)
+{
+	unsigned int i;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	uint32_t value;
+	unsigned int nrelocs = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
+	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Word sym_info = sechdrs[relsec].sh_info;
+	Elf32_Sym *sym_base = (Elf32_Sym *) sechdrs[symindex].sh_addr;
+	void *loc_base = (void *) sechdrs[sym_info].sh_addr;
+
+	DEBUGP("Applying relocations in section %u to section %u base=%p\n",
+	       relsec, sym_info, loc_base);
+
+	for (i = 0; i < nrelocs; i++) {
+
+		/* Symbol to relocate */
+		sym = sym_base + ELF32_R_SYM(rela[i].r_info);
+
+		/* Where to make the change */
+		location = loc_base + rela[i].r_offset;
+
+		/* `Everything is relative'. */
+		value = sym->st_value + rela[i].r_addend;
+
+		DEBUGP("%d: value=%08x loc=%p reloc=%d symbol=%s\n",
+		       i, value, location, ELF32_R_TYPE(rela[i].r_info),
+		       sym->st_name ?
+		       &strtab[sym->st_name] : "(anonymous)");
+
+		switch (ELF32_R_TYPE(rela[i].r_info)) {
+		case R_HEXAGON_B22_PCREL: {
+			int dist = (int)(value - (uint32_t)location);
+			if ((dist < -0x00800000) ||
+			    (dist >= 0x00800000)) {
+				printk(KERN_ERR
+				       "%s: %s: %08x=%08x-%08x %s\n",
+				       module->name,
+				       "R_HEXAGON_B22_PCREL reloc out of range",
+				       dist, value, (uint32_t)location,
+				       sym->st_name ?
+				       &strtab[sym->st_name] : "(anonymous)");
+				return -ENOEXEC;
+			}
+			DEBUGP("B22_PCREL contents: %08X.\n", *location);
+			*location &= ~0x01ff3fff;
+			*location |= 0x00003fff & dist;
+			*location |= 0x01ff0000 & (dist<<2);
+			DEBUGP("Contents after reloc: %08x\n", *location);
+			break;
+		}
+		case R_HEXAGON_HI16:
+			value = (value>>16) & 0xffff;
+			/* fallthrough */
+		case R_HEXAGON_LO16:
+			*location &= ~0x00c03fff;
+			*location |= value & 0x3fff;
+			*location |= (value & 0xc000) << 8;
+			break;
+		case R_HEXAGON_32:
+			*location = value;
+			break;
+		case R_HEXAGON_32_PCREL:
+			*location = value - (uint32_t)location;
+			break;
+		case R_HEXAGON_PLT_B22_PCREL:
+		case R_HEXAGON_GOTOFF_LO16:
+		case R_HEXAGON_GOTOFF_HI16:
+			printk(KERN_ERR "%s: GOT/PLT relocations unsupported\n",
+			       module->name);
+			return -ENOEXEC;
+		default:
+			printk(KERN_ERR "%s: unknown relocation: %u\n",
+			       module->name,
+			       ELF32_R_TYPE(rela[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/process.c linux-libre-3.2-gnu1/arch/hexagon/kernel/process.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/process.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,279 @@
+/*
+ * Process creation support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/tick.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+/*
+ * Kernel thread creation.  The desired kernel function is "wrapped"
+ * in the kernel_thread_helper function, which does cleanup
+ * afterwards.
+ */
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
+{
+	do_exit(fn(arg));
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	/*
+	 * Yes, we're exploting illicit knowledge of the ABI here.
+	 */
+	regs.r00 = (unsigned long) arg;
+	regs.r01 = (unsigned long) fn;
+	pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
+	pt_set_kmode(&regs);
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Program thread launch.  Often defined as a macro in processor.h,
+ * but we're shooting for a small footprint and it's not an inner-loop
+ * performance-critical operation.
+ *
+ * The Hexagon ABI specifies that R28 is zero'ed before program launch,
+ * so that gets automatically done here.  If we ever stop doing that here,
+ * we'll probably want to define the ELF_PLAT_INIT macro.
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+	/* Set to run with user-mode data segmentation */
+	set_fs(USER_DS);
+	/* We want to zero all data-containing registers. Is this overkill? */
+	memset(regs, 0, sizeof(*regs));
+	/* We might want to also zero all Processor registers here */
+	pt_set_usermode(regs);
+	pt_set_elr(regs, pc);
+	pt_set_rte_sp(regs, sp);
+}
+
+/*
+ *  Spin, or better still, do a hardware or VM wait instruction
+ *  If hardware or VM offer wait termination even though interrupts
+ *  are disabled.
+ */
+static void default_idle(void)
+{
+	__vmwait();
+}
+
+void (*idle_sleep)(void) = default_idle;
+
+void cpu_idle(void)
+{
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		local_irq_disable();
+		while (!need_resched()) {
+			idle_sleep();
+			/*  interrupts wake us up, but aren't serviced  */
+			local_irq_enable();	/* service interrupt   */
+			local_irq_disable();
+		}
+		local_irq_enable();
+		tick_nohz_restart_sched_tick();
+		schedule();
+	}
+}
+
+/*
+ *  Return saved PC of a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return 0;
+}
+
+/*
+ * Copy architecture-specific thread state
+ */
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+		unsigned long unused, struct task_struct *p,
+		struct pt_regs *regs)
+{
+	struct thread_info *ti = task_thread_info(p);
+	struct hexagon_switch_stack *ss;
+	struct pt_regs *childregs;
+	asmlinkage void ret_from_fork(void);
+
+	childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
+					sizeof(*childregs));
+
+	memcpy(childregs, regs, sizeof(*childregs));
+	ti->regs = childregs;
+
+	/*
+	 * Establish kernel stack pointer and initial PC for new thread
+	 */
+	ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
+						    sizeof(*ss));
+	ss->lr = (unsigned long)ret_from_fork;
+	p->thread.switch_sp = ss;
+
+	/* If User mode thread, set pt_reg stack pointer as per parameter */
+	if (user_mode(childregs)) {
+		pt_set_rte_sp(childregs, usp);
+
+		/* Child sees zero return value */
+		childregs->r00 = 0;
+
+		/*
+		 * The clone syscall has the C signature:
+		 * int [r0] clone(int flags [r0],
+		 *           void *child_frame [r1],
+		 *           void *parent_tid [r2],
+		 *           void *child_tid [r3],
+		 *           void *thread_control_block [r4]);
+		 * ugp is used to provide TLS support.
+		 */
+		if (clone_flags & CLONE_SETTLS)
+			childregs->ugp = childregs->r04;
+
+		/*
+		 * Parent sees new pid -- not necessary, not even possible at
+		 * this point in the fork process
+		 * Might also want to set things like ti->addr_limit
+		 */
+	} else {
+		/*
+		 * If kernel thread, resume stack is kernel stack base.
+		 * Note that this is pointer arithmetic on pt_regs *
+		 */
+		pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
+		/*
+		 * We need the current thread_info fast path pointer
+		 * set up in pt_regs.  The register to be used is
+		 * parametric for assembler code, but the mechanism
+		 * doesn't drop neatly into C.  Needs to be fixed.
+		 */
+		childregs->THREADINFO_REG = (unsigned long) ti;
+	}
+
+	/*
+	 * thread_info pointer is pulled out of task_struct "stack"
+	 * field on switch_to.
+	 */
+	p->stack = (void *)ti;
+
+	return 0;
+}
+
+/*
+ * Release any architecture-specific resources locked by thread
+ */
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Free any architecture-specific thread data structures, etc.
+ */
+void exit_thread(void)
+{
+}
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void)
+{
+}
+
+/*
+ * The "wait channel" terminology is archaic, but what we want
+ * is an identification of the point at which the scheduler
+ * was invoked by a blocked thread.
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)task_stack_page(p);
+	fp = ((struct hexagon_switch_stack *)p->thread.switch_sp)->fp;
+	do {
+		if (fp < (stack_page + sizeof(struct thread_info)) ||
+			fp >= (THREAD_SIZE - 8 + stack_page))
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		if (!in_sched_functions(pc))
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+
+	return 0;
+}
+
+/*
+ * Borrowed from PowerPC -- basically allow smaller kernel stacks if we
+ * go crazy with the page sizes.
+ */
+#if THREAD_SHIFT < PAGE_SHIFT
+
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
+{
+	struct thread_info *ti;
+
+	ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
+	if (unlikely(ti == NULL))
+		return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+	memset(ti, 0, THREAD_SIZE);
+#endif
+	return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	kmem_cache_free(thread_info_cache, ti);
+}
+
+/*  Weak symbol; called by init/main.c  */
+
+void thread_info_cache_init(void)
+{
+	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+					      THREAD_SIZE, 0, NULL);
+	BUG_ON(thread_info_cache == NULL);
+}
+
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+/*
+ * Required placeholder.
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/ptrace.c linux-libre-3.2-gnu1/arch/hexagon/kernel/ptrace.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/ptrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,180 @@
+/*
+ * Ptrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <generated/compile.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/user.h>
+
+#include <asm/system.h>
+#include <asm/user.h>
+
+static int genregs_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+	unsigned int dummy;
+	struct pt_regs *regs = task_pt_regs(target);
+
+
+	if (!regs)
+		return -EIO;
+
+	/* The general idea here is that the copyout must happen in
+	 * exactly the same order in which the userspace expects these
+	 * regs. Now, the sequence in userspace does not match the
+	 * sequence in the kernel, so everything past the 32 gprs
+	 * happens one at a time.
+	 */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define ONEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				 sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	ONEXT(&regs->sa0, sa0);
+	ONEXT(&regs->lc0, lc0);
+	ONEXT(&regs->sa1, sa1);
+	ONEXT(&regs->lc1, lc1);
+	ONEXT(&regs->m0, m0);
+	ONEXT(&regs->m1, m1);
+	ONEXT(&regs->usr, usr);
+	ONEXT(&regs->preds, p3_0);
+	ONEXT(&regs->gp, gp);
+	ONEXT(&regs->ugp, ugp);
+	ONEXT(&pt_elr(regs), pc);
+	dummy = pt_cause(regs);
+	ONEXT(&dummy, cause);
+	ONEXT(&pt_badva(regs), badva);
+
+	/* Pad the rest with zeros, if needed */
+	if (!ret)
+		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+	return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	unsigned long bucket;
+	struct pt_regs *regs = task_pt_regs(target);
+
+	if (!regs)
+		return -EIO;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define INEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	INEXT(&regs->sa0, sa0);
+	INEXT(&regs->lc0, lc0);
+	INEXT(&regs->sa1, sa1);
+	INEXT(&regs->lc1, lc1);
+	INEXT(&regs->m0, m0);
+	INEXT(&regs->m1, m1);
+	INEXT(&regs->usr, usr);
+	INEXT(&regs->preds, p3_0);
+	INEXT(&regs->gp, gp);
+	INEXT(&regs->ugp, ugp);
+	INEXT(&pt_elr(regs), pc);
+
+	/* CAUSE and BADVA aren't writeable. */
+	INEXT(&bucket, cause);
+	INEXT(&bucket, badva);
+
+	/* Ignore the rest, if needed */
+	if (!ret)
+		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * This is special; SP is actually restored by the VM via the
+	 * special event record which is set by the special trap.
+	 */
+	regs->hvmer.vmpsp = regs->r29;
+	return 0;
+}
+
+enum hexagon_regset {
+	REGSET_GENERAL,
+};
+
+static const struct user_regset hexagon_regsets[] = {
+	[REGSET_GENERAL] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = ELF_NGREG,
+		.size = sizeof(unsigned long),
+		.align = sizeof(unsigned long),
+		.get = genregs_get,
+		.set = genregs_set,
+	},
+};
+
+static const struct user_regset_view hexagon_user_view = {
+	.name = UTS_MACHINE,
+	.e_machine = ELF_ARCH,
+	.ei_osabi = ELF_OSABI,
+	.regsets = hexagon_regsets,
+	.n = ARRAY_SIZE(hexagon_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &hexagon_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+	/* Boilerplate - resolves to null inline if no HW single-step */
+	user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	return ptrace_request(child, request, addr, data);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/reset.c linux-libre-3.2-gnu1/arch/hexagon/kernel/reset.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/reset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/smp.h>
+#include <asm/hexagon_vm.h>
+
+void machine_power_off(void)
+{
+	smp_send_stop();
+	__vmstop();
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+}
+
+void pm_power_off(void)
+{
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/setup.c linux-libre-3.2-gnu1/arch/hexagon/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * Arch related setup for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/of_fdt.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/hexagon_vm.h>
+#include <asm/vm_mmu.h>
+#include <asm/time.h>
+#ifdef CONFIG_OF
+#include <asm/prom.h>
+#endif
+
+char cmd_line[COMMAND_LINE_SIZE];
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+int on_simulator;
+
+void __cpuinit calibrate_delay(void)
+{
+	loops_per_jiffy = thread_freq_mhz * 1000000 / HZ;
+}
+
+/*
+ * setup_arch -  high level architectural setup routine
+ * @cmdline_p: pointer to pointer to command-line arguments
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+	char *p = &external_cmdline_buffer;
+
+	/*
+	 * These will eventually be pulled in via either some hypervisor
+	 * or devicetree description.  Hardwiring for now.
+	 */
+	pcycle_freq_mhz = 600;
+	thread_freq_mhz = 100;
+	sleep_clk_freq = 32000;
+
+	/*
+	 * Set up event bindings to handle exceptions and interrupts.
+	 */
+	__vmsetvec(_K_VM_event_vector);
+
+	/*
+	 * Simulator has a few differences from the hardware.
+	 * For now, check uninitialized-but-mapped memory
+	 * prior to invoking setup_arch_memory().
+	 */
+	if (*(int *)((unsigned long)_end + 8) == 0x1f1f1f1f)
+		on_simulator = 1;
+	else
+		on_simulator = 0;
+
+	if (p[0] != '\0')
+		strlcpy(boot_command_line, p, COMMAND_LINE_SIZE);
+	else
+		strlcpy(boot_command_line, default_command_line,
+			COMMAND_LINE_SIZE);
+
+	/*
+	 * boot_command_line and the value set up by setup_arch
+	 * are both picked up by the init code. If no reason to
+	 * make them different, pass the same pointer back.
+	 */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	setup_arch_memory();
+
+#ifdef CONFIG_SMP
+	smp_start_cpus();
+#endif
+}
+
+/*
+ * Functions for dumping CPU info via /proc
+ * Probably should move to kernel/proc.c or something.
+ */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+/*
+ * Eventually this will dump information about
+ * CPU properties like ISA level, TLB size, etc.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	int cpu = (unsigned long) v - 1;
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
+	seq_printf(m, "BogoMips\t: %lu.%02lu\n",
+		(loops_per_jiffy * HZ) / 500000,
+		((loops_per_jiffy * HZ) / 5000) % 100);
+	seq_printf(m, "\n");
+	return 0;
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start  = &c_start,
+	.next   = &c_next,
+	.stop   = &c_stop,
+	.show   = &show_cpuinfo,
+};
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/signal.c linux-libre-3.2-gnu1/arch/hexagon/kernel/signal.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/signal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,345 @@
+/*
+ * Signal support for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <asm/registers.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+#include <asm/signal.h>
+#include <asm/vdso.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+	unsigned long tramp[2];
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			  size_t frame_size)
+{
+	unsigned long sp = regs->r29;
+
+	/* Switch to signal stack if appropriate */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
+			    32*sizeof(unsigned long));
+
+	err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __put_user(regs->m0, &sc->sc_regs.m0);
+	err |= __put_user(regs->m1, &sc->sc_regs.m1);
+	err |= __put_user(regs->usr, &sc->sc_regs.usr);
+	err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __put_user(regs->gp, &sc->sc_regs.gp);
+	err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
+
+	tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
+	tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
+	tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
+
+	return err;
+}
+
+static int restore_sigcontext(struct pt_regs *regs,
+			      struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
+			      32 * sizeof(unsigned long));
+
+	err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __get_user(regs->m0, &sc->sc_regs.m0);
+	err |= __get_user(regs->m1, &sc->sc_regs.m1);
+	err |= __get_user(regs->usr, &sc->sc_regs.usr);
+	err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __get_user(regs->gp, &sc->sc_regs.gp);
+	err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
+
+	err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
+
+	return err;
+}
+
+/*
+ * Setup signal stack frame with siginfo structure
+ */
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set,  struct pt_regs *regs)
+{
+	int err = 0;
+	struct rt_sigframe __user *frame;
+	struct hexagon_vdso *vdso = current->mm->context.vdso;
+
+	frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
+		goto	sigsegv;
+
+	if (copy_siginfo_to_user(&frame->info, info))
+		goto	sigsegv;
+
+	/* The on-stack signal trampoline is no longer executed;
+	 * however, the libgcc signal frame unwinding code checks for
+	 * the presence of these two numeric magic values.
+	 */
+	err |= __put_user(0x7800d166, &frame->tramp[0]);
+	err |= __put_user(0x5400c004, &frame->tramp[1]);
+	err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	if (err)
+		goto sigsegv;
+
+	/* Load r0/r1 pair with signumber/siginfo pointer... */
+	regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
+		| (unsigned long long)signr;
+	regs->r02 = (unsigned long) &frame->uc;
+	regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
+	pt_psp(regs) = (unsigned long) frame;
+	pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+
+	return 0;
+
+sigsegv:
+	force_sigsegv(signr, current);
+	return -EFAULT;
+}
+
+/*
+ * Setup invocation of signal handler
+ */
+static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+			 sigset_t *oldset, struct pt_regs *regs)
+{
+	int rc;
+
+	/*
+	 * If we're handling a signal that aborted a system call,
+	 * set up the error return value before adding the signal
+	 * frame to the stack.
+	 */
+
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->r00 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->r00 = -EINTR;
+				break;
+			}
+			/* Fall through */
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			pt_set_elr(regs, pt_elr(regs) - 4);
+			regs->r00 = regs->restart_r0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Set up the stack frame; not doing the SA_SIGINFO thing.  We
+	 * only set up the rt_frame flavor.
+	 */
+	rc = setup_rt_frame(sig, ka, info, oldset, regs);
+
+	/* If there was an error on setup, no signal was delivered. */
+	if (rc)
+		return rc;
+
+	spin_lock_irq(&current->sighand->siglock);
+	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked, sig);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	return 0;
+}
+
+/*
+ * Called from return-from-event code.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+	struct k_sigaction sigact;
+	siginfo_t info;
+	int signo;
+
+	if (!user_mode(regs))
+		return;
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
+
+	if (signo > 0) {
+		sigset_t *oldset;
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+
+		if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
+			/*
+			 * Successful delivery case.  The saved sigmask is
+			 * stored in the signal frame, and will be restored
+			 * by sigreturn.  We can clear the TIF flag.
+			 */
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signo, &info, &sigact, regs,
+				test_thread_flag(TIF_SINGLESTEP));
+		}
+		return;
+	}
+
+no_signal:
+	/*
+	 * If we came from a system call, handle the restart.
+	 */
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->r06 = __NR_restart_syscall;
+			break;
+		default:
+			goto no_restart;
+		}
+		pt_set_elr(regs, pt_elr(regs) - 4);
+		regs->r00 = regs->restart_r0;
+	}
+
+no_restart:
+	/* If there's no signal to deliver, put the saved sigmask back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
+
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
+/*
+ * Architecture-specific wrappers for signal-related system calls
+ */
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+
+	return do_sigaltstack(uss, uoss, regs->r29);
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+	struct rt_sigframe __user *frame;
+	sigset_t blocked;
+
+	frame = (struct rt_sigframe __user *)pt_psp(regs);
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
+		goto badframe;
+
+	sigdelsetmask(&blocked, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = blocked;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	/* Restore the user's stack as well */
+	pt_psp(regs) = regs->r29;
+
+	/*
+	 * Leave a trace in the stack frame that this was a sigreturn.
+	 * If the system call is to replay, we've already restored the
+	 * number in the GPR slot and it will be regenerated on the
+	 * new system call trap entry. Note that if restore_sigcontext()
+	 * did something other than a bulk copy of the pt_regs struct,
+	 * we could avoid this assignment by simply not overwriting
+	 * regs->syscall_nr.
+	 */
+	regs->syscall_nr = __NR_rt_sigreturn;
+
+	/*
+	 * If we were meticulous, we'd only call this if we knew that
+	 * we were actually going to use an alternate stack, and we'd
+	 * consider any error to be fatal.  What we do here, in common
+	 * with many other architectures, is call it blindly and only
+	 * consider the -EFAULT return case to be proof of a problem.
+	 */
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+		goto badframe;
+
+	return 0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/smp.c linux-libre-3.2-gnu1/arch/hexagon/kernel/smp.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * SMP support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h>  /*  xchg  */
+#include <asm/time.h>    /*  timer_interrupt  */
+#include <asm/hexagon_vm.h>
+
+#define BASE_IPI_IRQ 26
+
+/*
+ * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * (which is prior to any of our smp_prepare_cpu crap), in order to set
+ * up the...  per_cpu areas.
+ */
+
+struct ipi_data {
+	unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
+				int cpu)
+{
+	unsigned long msg = 0;
+	do {
+		msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+		switch (msg) {
+
+		case IPI_TIMER:
+			ipi_timer();
+			break;
+
+		case IPI_CALL_FUNC:
+			generic_smp_call_function_interrupt();
+			break;
+
+		case IPI_CALL_FUNC_SINGLE:
+			generic_smp_call_function_single_interrupt();
+			break;
+
+		case IPI_CPU_STOP:
+			/*
+			 * call vmstop()
+			 */
+			__vmstop();
+			break;
+
+		case IPI_RESCHEDULE:
+			scheduler_ipi();
+			break;
+		}
+	} while (msg < BITS_PER_LONG);
+}
+
+/*  Used for IPI call from other CPU's to unmask int  */
+void smp_vm_unmask_irq(void *info)
+{
+	__vmintop_locen((long) info);
+}
+
+
+/*
+ * This is based on Alpha's IPI stuff.
+ * Supposed to take (int, void*) as args now.
+ * Specifically, first arg is irq, second is the irq_desc.
+ */
+
+irqreturn_t handle_ipi(int irq, void *desc)
+{
+	int cpu = smp_processor_id();
+	struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+	unsigned long ops;
+
+	while ((ops = xchg(&ipi->bits, 0)) != 0)
+		__handle_ipi(&ops, ipi, cpu);
+	return IRQ_HANDLED;
+}
+
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
+{
+	unsigned long flags;
+	unsigned long cpu;
+	unsigned long retval;
+
+	local_irq_save(flags);
+
+	for_each_cpu(cpu, cpumask) {
+		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+
+		set_bit(msg, &ipi->bits);
+		/*  Possible barrier here  */
+		retval = __vmintop_post(BASE_IPI_IRQ+cpu);
+
+		if (retval != 0) {
+			printk(KERN_ERR "interrupt %ld not configured?\n",
+				BASE_IPI_IRQ+cpu);
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct irqaction ipi_intdesc = {
+	.handler = handle_ipi,
+	.flags = IRQF_TRIGGER_RISING,
+	.name = "ipi_handler"
+};
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * interrupts should already be disabled from the VM
+ * SP should already be correct; need to set THREADINFO_REG
+ * to point to current thread info
+ */
+
+void __cpuinit start_secondary(void)
+{
+	unsigned int cpu;
+	unsigned long thread_ptr;
+
+	/*  Calculate thread_info pointer from stack pointer  */
+	__asm__ __volatile__(
+		"%0 = SP;\n"
+		: "=r" (thread_ptr)
+	);
+
+	thread_ptr = thread_ptr & ~(THREAD_SIZE-1);
+
+	__asm__ __volatile__(
+		QUOTED_THREADINFO_REG " = %0;\n"
+		:
+		: "r" (thread_ptr)
+	);
+
+	/*  Set the memory struct  */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+
+	cpu = smp_processor_id();
+
+	setup_irq(BASE_IPI_IRQ + cpu, &ipi_intdesc);
+
+	/*  Register the clock_event dummy  */
+	setup_percpu_clockdev();
+
+	printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+
+	set_cpu_online(cpu, true);
+	while (!cpumask_test_cpu(cpu, cpu_active_mask))
+		cpu_relax();
+	local_irq_enable();
+
+	cpu_idle();
+}
+
+
+/*
+ * called once for each present cpu
+ * apparently starts up the CPU and then
+ * maintains control until "cpu_online(cpu)" is set.
+ */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+	struct task_struct *idle;
+	struct thread_info *thread;
+	void *stack_start;
+
+	/*  Create new init task for the CPU  */
+	idle = fork_idle(cpu);
+	if (IS_ERR(idle))
+		panic(KERN_ERR "fork_idle failed\n");
+
+	thread = (struct thread_info *)idle->stack;
+	thread->cpu = cpu;
+
+	/*  Boot to the head.  */
+	stack_start =  ((void *) thread) + THREAD_SIZE;
+	__vmstart(start_secondary, stack_start);
+
+	while (!cpu_isset(cpu, cpu_online_map))
+		barrier();
+
+	return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * should eventually have some sort of machine
+	 * descriptor that has this stuff
+	 */
+
+	/*  Right now, let's just fake it. */
+	for (i = 0; i < max_cpus; i++)
+		cpu_set(i, cpu_present_map);
+
+	/*  Also need to register the interrupts for IPI  */
+	if (max_cpus > 1)
+		setup_irq(BASE_IPI_IRQ, &ipi_intdesc);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+	struct cpumask targets;
+	cpumask_copy(&targets, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &targets);
+	send_ipi(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_CALL_FUNC);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+void smp_start_cpus(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		cpu_set(i, cpu_possible_map);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/stacktrace.c linux-libre-3.2-gnu1/arch/hexagon/kernel/stacktrace.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/stacktrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/*
+ * Stacktrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/module.h>
+
+register unsigned long current_frame_pointer asm("r30");
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long rets;
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long low, high;
+	unsigned long fp;
+	struct stackframe *frame;
+	int skip = trace->skip;
+
+	low = (unsigned long)task_stack_page(current);
+	high = low + THREAD_SIZE;
+	fp = current_frame_pointer;
+
+	while (fp >= low && fp <= (high - sizeof(*frame))) {
+		frame = (struct stackframe *)fp;
+
+		if (skip) {
+			skip--;
+		} else {
+			trace->entries[trace->nr_entries++] = frame->rets;
+			if (trace->nr_entries >= trace->max_entries)
+				break;
+		}
+
+		/*
+		 * The next frame must be at a higher address than the
+		 * current frame.
+		 */
+		low = fp + sizeof(*frame);
+		fp = frame->fp;
+	}
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/syscall.c linux-libre-3.2-gnu1/arch/hexagon/kernel/syscall.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/syscall.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/syscall.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * Hexagon system calls
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <asm/mman.h>
+#include <asm/registers.h>
+
+/*
+ * System calls with architecture-specific wrappers.
+ * See signal.c for signal-related system call wrappers.
+ */
+
+asmlinkage int sys_execve(char __user *ufilename,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+	char *filename;
+	int retval;
+
+	filename = getname(ufilename);
+	retval = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return retval;
+
+	retval = do_execve(filename, argv, envp, pregs);
+	putname(filename);
+
+	return retval;
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+
+	if (!newsp)
+		newsp = pregs->SP;
+	return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
+		       (int __user *)child_tidp);
+}
+
+/*
+ * Do a system call from the kernel, so as to have a proper pt_regs
+ * and recycle the sys_execvpe infrustructure.
+ */
+int kernel_execve(const char *filename,
+		  const char *const argv[], const char *const envp[])
+{
+	register unsigned long __a0 asm("r0") = (unsigned long) filename;
+	register unsigned long __a1 asm("r1") = (unsigned long) argv;
+	register unsigned long __a2 asm("r2") = (unsigned long) envp;
+	int retval;
+
+	__asm__ volatile(
+		"	R6 = #%4;\n"
+		"	trap0(#1);\n"
+		"	%0 = R0;\n"
+		: "=r" (retval)
+		: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
+	);
+
+	return retval;
+}
+EXPORT_SYMBOL(kernel_execve);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/syscalltab.c linux-libre-3.2-gnu1/arch/hexagon/kernel/syscalltab.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/syscalltab.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/syscalltab.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * System call table for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/time.c linux-libre-3.2-gnu1/arch/hexagon/kernel/time.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,250 @@
+/*
+ * Time related functions for Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/timer-regs.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * For the clocksource we need:
+ *	pcycle frequency (600MHz)
+ * For the loops_per_jiffy we need:
+ *	thread/cpu frequency (100MHz)
+ * And for the timer, we need:
+ *	sleep clock rate
+ */
+
+cycles_t	pcycle_freq_mhz;
+cycles_t	thread_freq_mhz;
+cycles_t	sleep_clk_freq;
+
+static struct resource rtos_timer_resources[] = {
+	{
+		.start	= RTOS_TIMER_REGS_ADDR,
+		.end	= RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device rtos_timer_device = {
+	.name		= "rtos_timer",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtos_timer_resources),
+	.resource	= rtos_timer_resources,
+};
+
+/*  A lot of this stuff should move into a platform specific section.  */
+struct adsp_hw_timer_struct {
+	u32 match;   /*  Match value  */
+	u32 count;
+	u32 enable;  /*  [1] - CLR_ON_MATCH_EN, [0] - EN  */
+	u32 clear;   /*  one-shot register that clears the count  */
+};
+
+/*  Look for "TCX0" for related constants.  */
+static __iomem struct adsp_hw_timer_struct *rtos_timer;
+
+static cycle_t timer_get_cycles(struct clocksource *cs)
+{
+	return (cycle_t) __vmgettime();
+}
+
+static struct clocksource hexagon_clocksource = {
+	.name		= "pcycles",
+	.rating		= 250,
+	.read		= timer_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int set_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+	/*  Assuming the timer will be disabled when we enter here.  */
+
+	iowrite32(1, &rtos_timer->clear);
+	iowrite32(0, &rtos_timer->clear);
+
+	iowrite32(delta, &rtos_timer->match);
+	iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable);
+	return 0;
+}
+
+/*
+ * Sets the mode (periodic, shutdown, oneshot, etc) of a timer.
+ */
+static void set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* XXX implement me */
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_SMP
+/*  Broadcast mechanism  */
+static void broadcast(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_TIMER);
+}
+#endif
+
+static struct clock_event_device hexagon_clockevent_dev = {
+	.name		= "clockevent",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 400,
+	.irq		= RTOS_TIMER_INT,
+	.set_next_event = set_next_event,
+	.set_mode	= set_mode,
+#ifdef CONFIG_SMP
+	.broadcast	= broadcast,
+#endif
+};
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct clock_event_device, clock_events);
+
+void setup_percpu_clockdev(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct clock_event_device *dummy_clock_dev =
+		&per_cpu(clock_events, cpu);
+
+	memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
+	INIT_LIST_HEAD(&dummy_clock_dev->list);
+
+	dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
+	dummy_clock_dev->cpumask = cpumask_of(cpu);
+	dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED;
+
+	clockevents_register_device(dummy_clock_dev);
+}
+
+/*  Called from smp.c for each CPU's timer ipi call  */
+void ipi_timer(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
+
+	ce_dev->event_handler(ce_dev);
+}
+#endif /* CONFIG_SMP */
+
+static irqreturn_t timer_interrupt(int irq, void *devid)
+{
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+
+	iowrite32(0, &rtos_timer->enable);
+	ce_dev->event_handler(ce_dev);
+
+	return IRQ_HANDLED;
+}
+
+/*  This should also be pulled from devtree  */
+static struct irqaction rtos_timer_intdesc = {
+	.handler = timer_interrupt,
+	.flags = IRQF_TIMER | IRQF_TRIGGER_RISING,
+	.name = "rtos_timer"
+};
+
+/*
+ * time_init_deferred - called by start_kernel to set up timer/clock source
+ *
+ * Install the IRQ handler for the clock, setup timers.
+ * This is done late, as that way, we can use ioremap().
+ *
+ * This runs just before the delay loop is calibrated, and
+ * is used for delay calibration.
+ */
+void __init time_init_deferred(void)
+{
+	struct resource *resource = NULL;
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct device_node *dn;
+	struct resource r;
+	int err;
+
+	ce_dev->cpumask = cpu_all_mask;
+
+	if (!resource)
+		resource = rtos_timer_device.resource;
+
+	/*  ioremap here means this has to run later, after paging init  */
+	rtos_timer = ioremap(resource->start, resource->end
+		- resource->start + 1);
+
+	if (!rtos_timer) {
+		release_mem_region(resource->start, resource->end
+			- resource->start + 1);
+	}
+	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
+
+	/*  Note: the sim generic RTOS clock is apparently really 18750Hz  */
+
+	/*
+	 * Last arg is some guaranteed seconds for which the conversion will
+	 * work without overflow.
+	 */
+	clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
+
+	ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
+	ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
+
+#ifdef CONFIG_SMP
+	setup_percpu_clockdev();
+#endif
+
+	clockevents_register_device(ce_dev);
+	setup_irq(ce_dev->irq, &rtos_timer_intdesc);
+}
+
+void __init time_init(void)
+{
+	late_time_init = time_init_deferred;
+}
+
+/*
+ * This could become parametric or perhaps even computed at run-time,
+ * but for now we take the observed simulator jitter.
+ */
+static long long fudgefactor = 350;  /* Maybe lower if kernel optimized. */
+
+void __udelay(unsigned long usecs)
+{
+	unsigned long long start = __vmgettime();
+	unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
+
+	while ((__vmgettime() - start) < finish)
+		cpu_relax(); /*  not sure how this improves readability  */
+}
+EXPORT_SYMBOL(__udelay);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/topology.c linux-libre-3.2-gnu1/arch/hexagon/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * CPU topology for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+/*  Swiped from MIPS.  */
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int i, ret;
+
+	for_each_present_cpu(i) {
+
+		/*
+		 * register_cpu takes a per_cpu pointer and
+		 * just points it at another per_cpu struct...
+		 */
+
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		if (ret)
+			printk(KERN_WARNING "topology_init: register_cpu %d "
+			       "failed (%d)\n", i, ret);
+	}
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/trampoline.S linux-libre-3.2-gnu1/arch/hexagon/kernel/trampoline.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/trampoline.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/trampoline.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Trampoline sequences to be copied onto user stack.
+ * This consumes a little more space than hand-assembling
+ * immediate constants for use in C, but is more portable
+ * to future tweaks to the Hexagon instruction set.
+ */
+
+#include <asm/unistd.h>
+
+/*  Sig trampolines - call sys_sigreturn or sys_rt_sigreturn as appropriate */
+
+/*  plain sigreturn is gone.  */
+
+	.globl __rt_sigtramp_template
+__rt_sigtramp_template:
+	r6 = #__NR_rt_sigreturn;
+	trap0(#1);
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/traps.c linux-libre-3.2-gnu1/arch/hexagon/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/traps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,454 @@
+/*
+ * Kernel traps/events for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/tracehook.h>
+#include <asm/traps.h>
+#include <asm/vm_fault.h>
+#include <asm/syscall.h>
+#include <asm/registers.h>
+#include <asm/unistd.h>
+#include <asm/sections.h>
+#ifdef CONFIG_KGDB
+# include <linux/kgdb.h>
+#endif
+
+#define TRAP_SYSCALL	1
+#define TRAP_DEBUG	0xdb
+
+void __init trap_init(void)
+{
+}
+
+#ifdef CONFIG_GENERIC_BUG
+/* Maybe should resemble arch/sh/kernel/traps.c ?? */
+int is_valid_bugaddr(unsigned long addr)
+{
+	return 1;
+}
+#endif /* CONFIG_GENERIC_BUG */
+
+static const char *ex_name(int ex)
+{
+	switch (ex) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		return "Execute protection fault";
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		return "Read protection fault";
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		return "Write protection fault";
+	case HVM_GE_C_XMAL:
+		return "Misaligned instruction";
+	case HVM_GE_C_RMAL:
+		return "Misaligned data load";
+	case HVM_GE_C_WMAL:
+		return "Misaligned data store";
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		return "Illegal instruction";
+	case HVM_GE_C_BUS:
+		return "Precise bus error";
+	case HVM_GE_C_CACHE:
+		return "Cache error";
+
+	case 0xdb:
+		return "Debugger trap";
+
+	default:
+		return "Unrecognized exception";
+	}
+}
+
+static void do_show_stack(struct task_struct *task, unsigned long *fp,
+			  unsigned long ip)
+{
+	int kstack_depth_to_print = 24;
+	unsigned long offset, size;
+	const char *name = NULL;
+	unsigned long *newfp;
+	unsigned long low, high;
+	char tmpstr[128];
+	char *modname;
+	int i;
+
+	if (task == NULL)
+		task = current;
+
+	printk(KERN_INFO "CPU#%d, %s/%d, Call Trace:\n",
+	       raw_smp_processor_id(), task->comm,
+	       task_pid_nr(task));
+
+	if (fp == NULL) {
+		if (task == current) {
+			asm("%0 = r30" : "=r" (fp));
+		} else {
+			fp = (unsigned long *)
+			     ((struct hexagon_switch_stack *)
+			     task->thread.switch_sp)->fp;
+		}
+	}
+
+	if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
+		printk(KERN_INFO "-- Corrupt frame pointer %p\n", fp);
+		return;
+	}
+
+	/* Saved link reg is one word above FP */
+	if (!ip)
+		ip = *(fp+1);
+
+	/* Expect kernel stack to be in-bounds */
+	low = (unsigned long)task_stack_page(task);
+	high = low + THREAD_SIZE - 8;
+	low += sizeof(struct thread_info);
+
+	for (i = 0; i < kstack_depth_to_print; i++) {
+
+		name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
+
+		printk(KERN_INFO "[%p] 0x%lx: %s + 0x%lx", fp, ip, name,
+			offset);
+		if (((unsigned long) fp < low) || (high < (unsigned long) fp))
+			printk(KERN_CONT " (FP out of bounds!)");
+		if (modname)
+			printk(KERN_CONT " [%s] ", modname);
+		printk(KERN_CONT "\n");
+
+		newfp = (unsigned long *) *fp;
+
+		if (((unsigned long) newfp) & 0x3) {
+			printk(KERN_INFO "-- Corrupt frame pointer %p\n",
+				newfp);
+			break;
+		}
+
+		/* Attempt to continue past exception. */
+		if (0 == newfp) {
+			struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
+						+ 8);
+
+			if (regs->syscall_nr != -1) {
+				printk(KERN_INFO "-- trap0 -- syscall_nr: %ld",
+					regs->syscall_nr);
+				printk(KERN_CONT "  psp: %lx  elr: %lx\n",
+					 pt_psp(regs), pt_elr(regs));
+				break;
+			} else {
+				/* really want to see more ... */
+				kstack_depth_to_print += 6;
+				printk(KERN_INFO "-- %s (0x%lx)  badva: %lx\n",
+					ex_name(pt_cause(regs)), pt_cause(regs),
+					pt_badva(regs));
+			}
+
+			newfp = (unsigned long *) regs->r30;
+			ip = pt_elr(regs);
+		} else {
+			ip = *(newfp + 1);
+		}
+
+		/* If link reg is null, we are done. */
+		if (ip == 0x0)
+			break;
+
+		/* If newfp isn't larger, we're tracing garbage. */
+		if (newfp > fp)
+			fp = newfp;
+		else
+			break;
+	}
+}
+
+void show_stack(struct task_struct *task, unsigned long *fp)
+{
+	/* Saved link reg is one word above FP */
+	do_show_stack(task, fp, 0);
+}
+
+void dump_stack(void)
+{
+	unsigned long *fp;
+	asm("%0 = r30" : "=r" (fp));
+	show_stack(current, fp);
+}
+EXPORT_SYMBOL(dump_stack);
+
+int die(const char *str, struct pt_regs *regs, long err)
+{
+	static struct {
+		spinlock_t lock;
+		int counter;
+	} die = {
+		.lock = __SPIN_LOCK_UNLOCKED(die.lock),
+		.counter = 0
+	};
+
+	console_verbose();
+	oops_enter();
+
+	spin_lock_irq(&die.lock);
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
+
+	if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
+	    NOTIFY_STOP)
+		return 1;
+
+	print_modules();
+	show_regs(regs);
+	do_show_stack(current, &regs->r30, pt_elr(regs));
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+
+	spin_unlock_irq(&die.lock);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	oops_exit();
+	do_exit(err);
+	return 0;
+}
+
+int die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs))
+		return die(str, regs, err);
+	else
+		return 0;
+}
+
+/*
+ * It's not clear that misaligned fetches are ever recoverable.
+ */
+static void misaligned_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Instruction", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * Misaligned loads and stores, on the other hand, can be
+ * emulated, and probably should be, some day.  But for now
+ * they will be considered fatal.
+ */
+static void misaligned_data_load(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Load", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void misaligned_data_store(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Store", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void illegal_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Illegal Instruction", regs, 0);
+	force_sig(SIGILL, current);
+}
+
+/*
+ * Precise bus errors may be recoverable with a a retry,
+ * but for now, treat them as irrecoverable.
+ */
+static void precise_bus_error(struct pt_regs *regs)
+{
+	die_if_kernel("Precise Bus Error", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * If anything is to be done here other than panic,
+ * it will probably be complex and migrate to another
+ * source module.  For now, just die.
+ */
+static void cache_error(struct pt_regs *regs)
+{
+	die("Cache Error", regs, 0);
+}
+
+/*
+ * General exception handler
+ */
+void do_genex(struct pt_regs *regs)
+{
+	/*
+	 * Decode Cause and Dispatch
+	 */
+	switch (pt_cause(regs)) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		execute_protection_fault(regs);
+		break;
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		read_protection_fault(regs);
+		break;
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		write_protection_fault(regs);
+		break;
+	case HVM_GE_C_XMAL:
+		misaligned_instruction(regs);
+		break;
+	case HVM_GE_C_RMAL:
+		misaligned_data_load(regs);
+		break;
+	case HVM_GE_C_WMAL:
+		misaligned_data_store(regs);
+		break;
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		illegal_instruction(regs);
+		break;
+	case HVM_GE_C_BUS:
+		precise_bus_error(regs);
+		break;
+	case HVM_GE_C_CACHE:
+		cache_error(regs);
+		break;
+	default:
+		/* Halt and catch fire */
+		panic("Unrecognized exception 0x%lx\n", pt_cause(regs));
+		break;
+	}
+}
+
+/* Indirect system call dispatch */
+long sys_syscall(void)
+{
+	printk(KERN_ERR "sys_syscall invoked!\n");
+	return -ENOSYS;
+}
+
+void do_trap0(struct pt_regs *regs)
+{
+	unsigned long syscallret = 0;
+	syscall_fn syscall;
+
+	switch (pt_cause(regs)) {
+	case TRAP_SYSCALL:
+		/* System call is trap0 #1 */
+
+		/* allow strace to catch syscall args  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&
+			tracehook_report_syscall_entry(regs)))
+			return;  /*  return -ENOSYS somewhere?  */
+
+		/* Interrupts should be re-enabled for syscall processing */
+		__vmsetie(VM_INT_ENABLE);
+
+		/*
+		 * System call number is in r6, arguments in r0..r5.
+		 * Fortunately, no Linux syscall has more than 6 arguments,
+		 * and Hexagon ABI passes first 6 arguments in registers.
+		 * 64-bit arguments are passed in odd/even register pairs.
+		 * Fortunately, we have no system calls that take more
+		 * than three arguments with more than one 64-bit value.
+		 * Should that change, we'd need to redesign to copy
+		 * between user and kernel stacks.
+		 */
+		regs->syscall_nr = regs->r06;
+
+		/*
+		 * GPR R0 carries the first parameter, and is also used
+		 * to report the return value.  We need a backup of
+		 * the user's value in case we need to do a late restart
+		 * of the system call.
+		 */
+		regs->restart_r0 = regs->r00;
+
+		if ((unsigned long) regs->syscall_nr >= __NR_syscalls) {
+			regs->r00 = -1;
+		} else {
+			syscall = (syscall_fn)
+				  (sys_call_table[regs->syscall_nr]);
+			syscallret = syscall(regs->r00, regs->r01,
+				   regs->r02, regs->r03,
+				   regs->r04, regs->r05);
+		}
+
+		/*
+		 * If it was a sigreturn system call, don't overwrite
+		 * r0 value in stack frame with return value.
+		 *
+		 * __NR_sigreturn doesn't seem to exist in new unistd.h
+		 */
+
+		if (regs->syscall_nr != __NR_rt_sigreturn)
+			regs->r00 = syscallret;
+
+		/* allow strace to get the syscall return state  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
+			tracehook_report_syscall_exit(regs, 0);
+
+		break;
+	case TRAP_DEBUG:
+		/* Trap0 0xdb is debug breakpoint */
+		if (user_mode(regs)) {
+			struct siginfo info;
+
+			info.si_signo = SIGTRAP;
+			info.si_errno = 0;
+			/*
+			 * Some architecures add some per-thread state
+			 * to distinguish between breakpoint traps and
+			 * trace traps.  We may want to do that, and
+			 * set the si_code value appropriately, or we
+			 * may want to use a different trap0 flavor.
+			 */
+			info.si_code = TRAP_BRKPT;
+			info.si_addr = (void __user *) pt_elr(regs);
+			send_sig_info(SIGTRAP, &info, current);
+		} else {
+#ifdef CONFIG_KGDB
+			kgdb_handle_exception(pt_cause(regs), SIGTRAP,
+					      TRAP_BRKPT, regs);
+#endif
+		}
+		break;
+	}
+	/* Ignore other trap0 codes for now, especially 0 (Angel calls) */
+}
+
+/*
+ * Machine check exception handler
+ */
+void do_machcheck(struct pt_regs *regs)
+{
+	/* Halt and catch fire */
+	__vmstop();
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vdso.c linux-libre-3.2-gnu1/arch/hexagon/kernel/vdso.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vdso.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/vdso.h>
+
+static struct page *vdso_page;
+
+/* Create a vDSO page holding the signal trampoline.
+ * We want this for a non-executable stack.
+ */
+static int __init vdso_init(void)
+{
+	struct hexagon_vdso *vdso;
+
+	vdso_page = alloc_page(GFP_KERNEL);
+	if (!vdso_page)
+		panic("Cannot allocate vdso");
+
+	vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+	if (!vdso)
+		panic("Cannot map vdso");
+	clear_page(vdso);
+
+	/* Install the signal trampoline; currently looks like this:
+	 *	r6 = #__NR_rt_sigreturn;
+	 *	trap0(#1);
+	 */
+	vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
+	vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
+
+	vunmap(vdso);
+
+	return 0;
+}
+arch_initcall(vdso_init);
+
+/*
+ * Called from binfmt_elf.  Create a VMA for the vDSO page.
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int ret;
+	unsigned long vdso_base;
+	struct mm_struct *mm = current->mm;
+
+	down_write(&mm->mmap_sem);
+
+	/* Try to get it loaded right near ld.so/glibc. */
+	vdso_base = STACK_TOP;
+
+	vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		ret = vdso_base;
+		goto up_fail;
+	}
+
+	/* MAYWRITE to allow gdb to COW and set breakpoints. */
+	ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				      VM_ALWAYSDUMP,
+				      &vdso_page);
+
+	if (ret)
+		goto up_fail;
+
+	mm->context.vdso = (void *)vdso_base;
+
+up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	return NULL;
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_entry.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_entry.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,269 @@
+/*
+ * Event entry/exit for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h>  /*  assembly-safer versions of C defines */
+#include <asm/mem-layout.h>   /*  sigh, except for page_offset  */
+#include <asm/hexagon_vm.h>
+#include <asm/thread_info.h>
+
+/*
+ * Entry into guest-mode Linux under Hexagon Virtual Machine.
+ * Stack pointer points to event record - build pt_regs on top of it,
+ * set up a plausible C stack frame, and dispatch to the C handler.
+ * On return, do vmrte virtual instruction with SP where we started.
+ *
+ * VM Spec 0.5 uses a trap to fetch HVM record now.
+ */
+
+/*
+ * Save full register state, while setting up thread_info struct
+ * pointer derived from kernel stack pointer in THREADINFO_REG
+ * register, putting prior thread_info.regs pointer in a callee-save
+ * register (R24, which had better not ever be assigned to THREADINFO_REG),
+ * and updating thread_info.regs to point to current stack frame,
+ * so as to support nested events in kernel mode.
+ *
+ * As this is common code, we set the pt_regs system call number
+ * to -1 for all events.  It will be replaced with the system call
+ * number in the case where we decode a system call (trap0(#1)).
+ */
+
+#define save_pt_regs()\
+	memd(R0 + #_PT_R3130) = R31:30; \
+	{ memw(R0 + #_PT_R2928) = R28; \
+	  R31 = memw(R0 + #_PT_ER_VMPSP); }\
+	{ memw(R0 + #(_PT_R2928 + 4)) = R31; \
+	  R31 = ugp; } \
+	{ memd(R0 + #_PT_R2726) = R27:26; \
+	  R30 = gp ; } \
+	memd(R0 + #_PT_R2524) = R25:24; \
+	memd(R0 + #_PT_R2322) = R23:22; \
+	memd(R0 + #_PT_R2120) = R21:20; \
+	memd(R0 + #_PT_R1918) = R19:18; \
+	memd(R0 + #_PT_R1716) = R17:16; \
+	memd(R0 + #_PT_R1514) = R15:14; \
+	memd(R0 + #_PT_R1312) = R13:12; \
+	{ memd(R0 + #_PT_R1110) = R11:10; \
+	  R15 = lc0; } \
+	{ memd(R0 + #_PT_R0908) = R9:8; \
+	  R14 = sa0; } \
+	{ memd(R0 + #_PT_R0706) = R7:6; \
+	  R13 = lc1; } \
+	{ memd(R0 + #_PT_R0504) = R5:4; \
+	  R12 = sa1; } \
+	{ memd(R0 + #_PT_UGPGP) = R31:30; \
+	  R11 = m1; \
+	  R2.H = #HI(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC0SA0) = R15:14; \
+	  R10 = m0; \
+	  R2.L = #LO(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC1SA1) = R13:12; \
+	  R15 = p3:0; \
+	  R2 = neg(R2); } \
+	{ memd(R0 + #_PT_M1M0) = R11:10; \
+	  R14  = usr; \
+	  R2 = and(R0,R2); } \
+	{ memd(R0 + #_PT_PREDSUSR) =  R15:14; \
+	  THREADINFO_REG = R2; } \
+	{ r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+	  memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+	  R2 = #-1; } \
+	{ memw(R0 + #_PT_SYSCALL_NR) = R2; \
+	  R30 = #0; }
+
+/*
+ * Restore registers and thread_info.regs state. THREADINFO_REG
+ * is assumed to still be sane, and R24 to have been correctly
+ * preserved. Don't restore R29 (SP) until later.
+ */
+
+#define restore_pt_regs() \
+	{ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+	  R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+	{ R11:10 = memd(R0 + #_PT_M1M0); \
+	  p3:0 = R15; } \
+	{ R13:12 = memd(R0 + #_PT_LC1SA1); \
+	  usr = R14; } \
+	{ R15:14 = memd(R0 + #_PT_LC0SA0); \
+	  m1 = R11; } \
+	{ R3:2 = memd(R0 + #_PT_R0302); \
+	  m0 = R10; } \
+	{ R5:4 = memd(R0 + #_PT_R0504); \
+	  lc1 = R13; } \
+	{ R7:6 = memd(R0 + #_PT_R0706); \
+	  sa1 = R12; } \
+	{ R9:8 = memd(R0 + #_PT_R0908); \
+	  lc0 = R15; } \
+	{ R11:10 = memd(R0 + #_PT_R1110); \
+	  sa0 = R14; } \
+	{ R13:12 = memd(R0 + #_PT_R1312); \
+	  R15:14 = memd(R0 + #_PT_R1514); } \
+	{ R17:16 = memd(R0 + #_PT_R1716); \
+	  R19:18 = memd(R0 + #_PT_R1918); } \
+	{ R21:20 = memd(R0 + #_PT_R2120); \
+	  R23:22 = memd(R0 + #_PT_R2322); } \
+	{ R25:24 = memd(R0 + #_PT_R2524); \
+	  R27:26 = memd(R0 + #_PT_R2726); } \
+	R31:30 = memd(R0 + #_PT_UGPGP); \
+	{ R28 = memw(R0 + #_PT_R2928); \
+	  ugp = R31; } \
+	{ R31:30 = memd(R0 + #_PT_R3130); \
+	  gp = R30; }
+
+	/*
+	 * Clears off enough space for the rest of pt_regs; evrec is a part
+	 * of pt_regs in HVM mode.  Save R0/R1, set handler's address in R1.
+	 * R0 is the address of pt_regs and is the parameter to save_pt_regs.
+	 */
+
+/*
+ * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
+ * we'll subract the entire size out and then fill it in ourselves.
+ * Need to save off R0, R1, R2, R3 immediately.
+ */
+
+#define	vm_event_entry(CHandler) \
+	{ \
+		R29 = add(R29, #-(_PT_REGS_SIZE)); \
+		memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+	} \
+	{ \
+		memd(R29 +#_PT_R0302) = R3:2; \
+	} \
+	trap1(#HVM_TRAP1_VMGETREGS); \
+	{ \
+		memd(R29 + #_PT_ER_VMEL) = R1:0; \
+		R0 = R29; \
+		R1.L = #LO(CHandler); \
+	} \
+	{ \
+		memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+		R1.H = #HI(CHandler); \
+		jump event_dispatch; \
+	}
+
+.text
+	/*
+	 * Do bulk save/restore in one place.
+	 * Adds a jump to dispatch latency, but
+	 * saves hundreds of bytes.
+	 */
+
+event_dispatch:
+	save_pt_regs()
+	callr	r1
+
+	/*
+	 * If we were in kernel mode, we don't need to check scheduler
+	 * or signals if CONFIG_PREEMPT is not set.  If set, then it has
+	 * to jump to a need_resched kind of block.
+	 * BTW, CONFIG_PREEMPT is not supported yet.
+	 */
+
+#ifdef CONFIG_PREEMPT
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+#endif
+
+	/*  "Nested control path" -- if the previous mode was kernel  */
+	R0 = memw(R29 + #_PT_ER_VMEST);
+	P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+	if !P0 jump restore_all;
+	/*
+	 * Returning from system call, normally coming back from user mode
+	 */
+return_from_syscall:
+	/*  Disable interrupts while checking TIF  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*
+	 * Coming back from the C-world, our thread info pointer
+	 * should be in the designated register (usually R19)
+	 */
+	R1.L = #LO(_TIF_ALLWORK_MASK)
+	{
+		R1.H = #HI(_TIF_ALLWORK_MASK);
+		R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+	}
+
+	/*
+	 * Compare against the "return to userspace" _TIF_WORK_MASK
+	 */
+	R1 = and(R1,R0);
+	{ P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
+	jump restore_all;  /*  we're outta here!  */
+
+work_pending:
+	{
+		P0 = tstbit(R1, #TIF_NEED_RESCHED);
+		if (!P0.new) jump:nt work_notifysig;
+	}
+	call schedule
+	jump return_from_syscall;  /*  check for more work  */
+
+work_notifysig:
+	/*  this is the part that's kind of fuzzy.  */
+	R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
+	P0 = cmp.eq(R1, #0);
+	if P0 jump restore_all
+	R1 = R0; 	/* unsigned long thread_info_flags */
+	R0 = R29;	/* regs should still be at top of stack  */
+	call do_notify_resume
+
+restore_all:
+	/* Disable interrupts, if they weren't already, before reg restore.  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*  do the setregs here for VM 0.5  */
+	/*  R29 here should already be pointing at pt_regs  */
+	R1:0 = memd(R29 + #_PT_ER_VMEL);
+	R3:2 = memd(R29 + #_PT_ER_VMPSP);
+	trap1(#HVM_TRAP1_VMSETREGS);
+
+	R0 = R29
+	restore_pt_regs()
+	R1:0 = memd(R29 + #_PT_R0100);
+	R29 = add(R29, #_PT_REGS_SIZE);
+	trap1(#HVM_TRAP1_VMRTE)
+	/* Notreached */
+
+	.globl _K_enter_genex
+_K_enter_genex:
+	vm_event_entry(do_genex)
+
+	.globl _K_enter_interrupt
+_K_enter_interrupt:
+	vm_event_entry(arch_do_IRQ)
+
+	.globl _K_enter_trap0
+_K_enter_trap0:
+	vm_event_entry(do_trap0)
+
+	.globl _K_enter_machcheck
+_K_enter_machcheck:
+	vm_event_entry(do_machcheck)
+
+
+	.globl ret_from_fork
+ret_from_fork:
+	call schedule_tail
+	jump return_from_syscall
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_events.c linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_events.c
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_events.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_events.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Mostly IRQ support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <asm/registers.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+#include <asm/system.h>
+
+/*
+ * show_regs - print pt_regs structure
+ * @regs: pointer to pt_regs
+ *
+ * To-do:  add all the accessor definitions to registers.h
+ *
+ * Will make this routine a lot easier to write.
+ */
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_EMERG "restart_r0: \t0x%08lx   syscall_nr: %ld\n",
+	       regs->restart_r0, regs->syscall_nr);
+	printk(KERN_EMERG "preds: \t\t0x%08lx\n", regs->preds);
+	printk(KERN_EMERG "lc0: \t0x%08lx   sa0: 0x%08lx   m0:  0x%08lx\n",
+	       regs->lc0, regs->sa0, regs->m0);
+	printk(KERN_EMERG "lc1: \t0x%08lx   sa1: 0x%08lx   m1:  0x%08lx\n",
+	       regs->lc1, regs->sa1, regs->m1);
+	printk(KERN_EMERG "gp: \t0x%08lx   ugp: 0x%08lx   usr: 0x%08lx\n",
+	       regs->gp, regs->ugp, regs->usr);
+	printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
+		regs->r01,
+		regs->r02,
+		regs->r03);
+	printk(KERN_EMERG "r4:  \t0x%08lx %08lx %08lx %08lx\n", regs->r04,
+		regs->r05,
+		regs->r06,
+		regs->r07);
+	printk(KERN_EMERG "r8:  \t0x%08lx %08lx %08lx %08lx\n", regs->r08,
+		regs->r09,
+		regs->r10,
+		regs->r11);
+	printk(KERN_EMERG "r12: \t0x%08lx %08lx %08lx %08lx\n", regs->r12,
+		regs->r13,
+		regs->r14,
+		regs->r15);
+	printk(KERN_EMERG "r16: \t0x%08lx %08lx %08lx %08lx\n", regs->r16,
+		regs->r17,
+		regs->r18,
+		regs->r19);
+	printk(KERN_EMERG "r20: \t0x%08lx %08lx %08lx %08lx\n", regs->r20,
+		regs->r21,
+		regs->r22,
+		regs->r23);
+	printk(KERN_EMERG "r24: \t0x%08lx %08lx %08lx %08lx\n", regs->r24,
+		regs->r25,
+		regs->r26,
+		regs->r27);
+	printk(KERN_EMERG "r28: \t0x%08lx %08lx %08lx %08lx\n", regs->r28,
+		regs->r29,
+		regs->r30,
+		regs->r31);
+
+	printk(KERN_EMERG "elr: \t0x%08lx   cause: 0x%08lx   user_mode: %d\n",
+		pt_elr(regs), pt_cause(regs), user_mode(regs));
+	printk(KERN_EMERG "psp: \t0x%08lx   badva: 0x%08lx   int_enabled: %d\n",
+		pt_psp(regs), pt_badva(regs), ints_enabled(regs));
+}
+
+void dummy_handler(struct pt_regs *regs)
+{
+	unsigned int elr = pt_elr(regs);
+	printk(KERN_ERR "Unimplemented handler; ELR=0x%08x\n", elr);
+}
+
+
+void arch_do_IRQ(struct pt_regs *regs)
+{
+	int irq = pt_cause(regs);
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+	generic_handle_irq(irq);
+	irq_exit();
+	set_irq_regs(old_regs);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_init_segtable.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_init_segtable.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_init_segtable.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_init_segtable.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,442 @@
+/*
+ * Initial page table for Linux kernel under Hexagon VM,
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * These tables are pre-computed and linked into kernel.
+ */
+
+#include <asm/vm_mmu.h>
+/*  #include <asm/iomap.h>  */
+
+/*
+ * Start with mapping PA=0 to both VA=0x0 and VA=0xc000000 as 16MB large pages.
+ * No user mode access, RWX, write-back cache.  The entry needs
+ * to be replicated for all 4 virtual segments mapping to the page.
+ */
+
+/* "Big Kernel Page"  */
+#define BKP(pa) (((pa) & __HVM_PTE_PGMASK_4MB)		\
+		| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		| __HEXAGON_C_WB_L2 << 6			\
+		| __HVM_PDE_S_16MB)
+
+/*  No cache version  */
+
+#define BKPG_IO(pa) (((pa) & __HVM_PTE_PGMASK_16MB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HVM_PDE_S_16MB | __HEXAGON_C_DEV << 6 )
+
+#define FOURK_IO(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HEXAGON_C_DEV << 6 )
+
+#define L2_PTR(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PDE_S_4KB  )
+
+#define X __HVM_PDE_S_INVALID
+
+	.p2align 12
+	.globl swapper_pg_dir
+	.globl _K_init_segtable
+swapper_pg_dir:
+/* VA 0x00000000 */
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x40000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x80000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/*0xa8*/.word X,X,X,X
+#ifdef CONFIG_COMET_EARLY_UART_DEBUG
+UART_PTE_ENTRY:
+/*0xa9*/.word BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000)
+#else
+/*0xa9*/.word X,X,X,X
+#endif
+/*0xaa*/.word X,X,X,X
+/*0xab*/.word X,X,X,X
+/*0xac*/.word X,X,X,X
+/*0xad*/.word X,X,X,X
+/*0xae*/.word X,X,X,X
+/*0xaf*/.word X,X,X,X
+/*0xb0*/.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+_K_init_segtable:
+/* VA 0xC0000000 */
+	.word BKP(0x00000000), BKP(0x00400000), BKP(0x00800000), BKP(0x00c00000)
+	.word BKP(0x01000000), BKP(0x01400000), BKP(0x01800000), BKP(0x01c00000)
+	.word BKP(0x02000000), BKP(0x02400000), BKP(0x02800000), BKP(0x02c00000)
+	.word BKP(0x03000000), BKP(0x03400000), BKP(0x03800000), BKP(0x03c00000)
+	.word BKP(0x04000000), BKP(0x04400000), BKP(0x04800000), BKP(0x04c00000)
+	.word BKP(0x05000000), BKP(0x05400000), BKP(0x05800000), BKP(0x05c00000)
+	.word BKP(0x06000000), BKP(0x06400000), BKP(0x06800000), BKP(0x06c00000)
+	.word BKP(0x07000000), BKP(0x07400000), BKP(0x07800000), BKP(0x07c00000)
+
+	.word BKP(0x08000000), BKP(0x08400000), BKP(0x08800000), BKP(0x08c00000)
+	.word BKP(0x09000000), BKP(0x09400000), BKP(0x09800000), BKP(0x09c00000)
+	.word BKP(0x0a000000), BKP(0x0a400000), BKP(0x0a800000), BKP(0x0ac00000)
+	.word BKP(0x0b000000), BKP(0x0b400000), BKP(0x0b800000), BKP(0x0bc00000)
+	.word BKP(0x0c000000), BKP(0x0c400000), BKP(0x0c800000), BKP(0x0cc00000)
+	.word BKP(0x0d000000), BKP(0x0d400000), BKP(0x0d800000), BKP(0x0dc00000)
+	.word BKP(0x0e000000), BKP(0x0e400000), BKP(0x0e800000), BKP(0x0ec00000)
+	.word BKP(0x0f000000), BKP(0x0f400000), BKP(0x0f800000), BKP(0x0fc00000)
+
+	.word BKP(0x10000000), BKP(0x10400000), BKP(0x10800000), BKP(0x10c00000)
+	.word BKP(0x11000000), BKP(0x11400000), BKP(0x11800000), BKP(0x11c00000)
+	.word BKP(0x12000000), BKP(0x12400000), BKP(0x12800000), BKP(0x12c00000)
+	.word BKP(0x13000000), BKP(0x13400000), BKP(0x13800000), BKP(0x13c00000)
+	.word BKP(0x14000000), BKP(0x14400000), BKP(0x14800000), BKP(0x14c00000)
+	.word BKP(0x15000000), BKP(0x15400000), BKP(0x15800000), BKP(0x15c00000)
+	.word BKP(0x16000000), BKP(0x16400000), BKP(0x16800000), BKP(0x16c00000)
+	.word BKP(0x17000000), BKP(0x17400000), BKP(0x17800000), BKP(0x17c00000)
+
+	.word BKP(0x18000000), BKP(0x18400000), BKP(0x18800000), BKP(0x18c00000)
+	.word BKP(0x19000000), BKP(0x19400000), BKP(0x19800000), BKP(0x19c00000)
+	.word BKP(0x1a000000), BKP(0x1a400000), BKP(0x1a800000), BKP(0x1ac00000)
+	.word BKP(0x1b000000), BKP(0x1b400000), BKP(0x1b800000), BKP(0x1bc00000)
+	.word BKP(0x1c000000), BKP(0x1c400000), BKP(0x1c800000), BKP(0x1cc00000)
+	.word BKP(0x1d000000), BKP(0x1d400000), BKP(0x1d800000), BKP(0x1dc00000)
+	.word BKP(0x1e000000), BKP(0x1e400000), BKP(0x1e800000), BKP(0x1ec00000)
+	.word BKP(0x1f000000), BKP(0x1f400000), BKP(0x1f800000), BKP(0x1fc00000)
+
+	.word BKP(0x20000000), BKP(0x20400000), BKP(0x20800000), BKP(0x20c00000)
+	.word BKP(0x21000000), BKP(0x21400000), BKP(0x21800000), BKP(0x21c00000)
+	.word BKP(0x22000000), BKP(0x22400000), BKP(0x22800000), BKP(0x22c00000)
+	.word BKP(0x23000000), BKP(0x23400000), BKP(0x23800000), BKP(0x23c00000)
+	.word BKP(0x24000000), BKP(0x24400000), BKP(0x24800000), BKP(0x24c00000)
+	.word BKP(0x25000000), BKP(0x25400000), BKP(0x25800000), BKP(0x25c00000)
+	.word BKP(0x26000000), BKP(0x26400000), BKP(0x26800000), BKP(0x26c00000)
+	.word BKP(0x27000000), BKP(0x27400000), BKP(0x27800000), BKP(0x27c00000)
+
+	.word BKP(0x28000000), BKP(0x28400000), BKP(0x28800000), BKP(0x28c00000)
+	.word BKP(0x29000000), BKP(0x29400000), BKP(0x29800000), BKP(0x29c00000)
+	.word BKP(0x2a000000), BKP(0x2a400000), BKP(0x2a800000), BKP(0x2ac00000)
+	.word BKP(0x2b000000), BKP(0x2b400000), BKP(0x2b800000), BKP(0x2bc00000)
+	.word BKP(0x2c000000), BKP(0x2c400000), BKP(0x2c800000), BKP(0x2cc00000)
+	.word BKP(0x2d000000), BKP(0x2d400000), BKP(0x2d800000), BKP(0x2dc00000)
+	.word BKP(0x2e000000), BKP(0x2e400000), BKP(0x2e800000), BKP(0x2ec00000)
+	.word BKP(0x2f000000), BKP(0x2f400000), BKP(0x2f800000), BKP(0x2fc00000)
+
+	.word BKP(0x30000000), BKP(0x30400000), BKP(0x30800000), BKP(0x30c00000)
+	.word BKP(0x31000000), BKP(0x31400000), BKP(0x31800000), BKP(0x31c00000)
+	.word BKP(0x32000000), BKP(0x32400000), BKP(0x32800000), BKP(0x32c00000)
+	.word BKP(0x33000000), BKP(0x33400000), BKP(0x33800000), BKP(0x33c00000)
+	.word BKP(0x34000000), BKP(0x34400000), BKP(0x34800000), BKP(0x34c00000)
+	.word BKP(0x35000000), BKP(0x35400000), BKP(0x35800000), BKP(0x35c00000)
+	.word BKP(0x36000000), BKP(0x36400000), BKP(0x36800000), BKP(0x36c00000)
+	.word BKP(0x37000000), BKP(0x37400000), BKP(0x37800000), BKP(0x37c00000)
+
+	.word BKP(0x38000000), BKP(0x38400000), BKP(0x38800000), BKP(0x38c00000)
+	.word BKP(0x39000000), BKP(0x39400000), BKP(0x39800000), BKP(0x39c00000)
+	.word BKP(0x3a000000), BKP(0x3a400000), BKP(0x3a800000), BKP(0x3ac00000)
+	.word BKP(0x3b000000), BKP(0x3b400000), BKP(0x3b800000), BKP(0x3bc00000)
+	.word BKP(0x3c000000), BKP(0x3c400000), BKP(0x3c800000), BKP(0x3cc00000)
+	.word BKP(0x3d000000), BKP(0x3d400000), BKP(0x3d800000), BKP(0x3dc00000)
+_K_io_map:
+	.word X,X,X,X /* 0x3e000000 - device IO early remap */
+	.word X,X,X,X /* 0x3f000000 - hypervisor space*/
+
+#if 0
+/*
+ * This is in here as an example for devices which need to be mapped really
+ * early.
+ */
+	.p2align 12
+	.globl _K_io_kmap
+	.globl _K_init_devicetable
+_K_init_devicetable:  /*  Should be 4MB worth of entries  */
+	.word FOURK_IO(MSM_GPIO1_PHYS),FOURK_IO(MSM_GPIO2_PHYS),FOURK_IO(MSM_SIRC_PHYS),X
+	.word FOURK_IO(TLMM_GPIO1_PHYS),X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vmlinux.lds.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * Linker script for Hexagon kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define LOAD_OFFSET PAGE_OFFSET
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h>	/*  Most of the kernel defines are here  */
+#include <asm/mem-layout.h>	/*  except for page_offset  */
+#include <asm/cache.h>		/*  and now we're pulling cache line size  */
+OUTPUT_ARCH(hexagon)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+/*
+See asm-generic/vmlinux.lds.h for expansion of some of these macros.
+See asm-generic/sections.h for seemingly required labels.
+*/
+
+#define PAGE_SIZE _PAGE_SIZE
+
+/*  This LOAD_OFFSET is temporary for debugging on the simulator; it may change
+    for hypervisor pseudo-physical memory.  */
+
+
+SECTIONS
+{
+	. = PAGE_OFFSET + LOAD_ADDRESS;
+
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	PERCPU_SECTION(L1_CACHE_BYTES)
+	__init_end = .;
+
+        . = ALIGN(_PAGE_SIZE);
+	_stext = .;
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		_text = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+	}
+	_etext = .;
+
+	INIT_DATA_SECTION(PAGE_SIZE)
+
+	_sdata = .;
+		RW_DATA_SECTION(32,PAGE_SIZE,PAGE_SIZE)
+		RO_DATA_SECTION(PAGE_SIZE)
+	_edata = .;
+
+	EXCEPTION_TABLE(16)
+	NOTES
+
+	BSS_SECTION(_PAGE_SIZE, _PAGE_SIZE, _PAGE_SIZE)
+
+	_end = .;
+
+	/DISCARD/ : {
+		EXIT_TEXT
+		EXIT_DATA
+		EXIT_CALL
+	}
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_ops.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_ops.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_ops.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_ops.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Hexagon VM instruction support
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * C wrappers for virtual machine "instructions".  These
+ * could be, and perhaps some day will be, handled as in-line
+ * macros, but for tracing/debugging it's handy to have
+ * a single point of invocation for each of them.
+ * Conveniently, they take paramters and return values
+ * consistent with the ABI calling convention.
+ */
+
+ENTRY(__vmrte)
+	trap1(#HVM_TRAP1_VMRTE);
+	jumpr	R31;
+
+ENTRY(__vmsetvec)
+	trap1(#HVM_TRAP1_VMSETVEC);
+	jumpr	R31;
+
+ENTRY(__vmsetie)
+	trap1(#HVM_TRAP1_VMSETIE);
+	jumpr	R31;
+
+ENTRY(__vmgetie)
+	trap1(#HVM_TRAP1_VMGETIE);
+	jumpr	R31;
+
+ENTRY(__vmintop)
+	trap1(#HVM_TRAP1_VMINTOP);
+	jumpr	R31;
+
+ENTRY(__vmclrmap)
+	trap1(#HVM_TRAP1_VMCLRMAP);
+	jumpr	R31;
+
+ENTRY(__vmnewmap)
+	r1 = #VM_NEWMAP_TYPE_PGTABLES;
+	trap1(#HVM_TRAP1_VMNEWMAP);
+	jumpr	R31;
+
+ENTRY(__vmcache)
+	trap1(#HVM_TRAP1_VMCACHE);
+	jumpr	R31;
+
+ENTRY(__vmgettime)
+	trap1(#HVM_TRAP1_VMGETTIME);
+	jumpr	R31;
+
+ENTRY(__vmsettime)
+	trap1(#HVM_TRAP1_VMSETTIME);
+	jumpr	R31;
+
+ENTRY(__vmwait)
+	trap1(#HVM_TRAP1_VMWAIT);
+	jumpr	R31;
+
+ENTRY(__vmyield)
+	trap1(#HVM_TRAP1_VMYIELD);
+	jumpr	R31;
+
+ENTRY(__vmstart)
+	trap1(#HVM_TRAP1_VMSTART);
+	jumpr	R31;
+
+ENTRY(__vmstop)
+	trap1(#HVM_TRAP1_VMSTOP);
+	jumpr	R31;
+
+ENTRY(__vmvpid)
+	trap1(#HVM_TRAP1_VMVPID);
+	jumpr	R31;
+
+/*  Probably not actually going to use these; see vm_entry.S  */
+
+ENTRY(__vmsetregs)
+	trap1(#HVM_TRAP1_VMSETREGS);
+	jumpr	R31;
+
+ENTRY(__vmgetregs)
+	trap1(#HVM_TRAP1_VMGETREGS);
+	jumpr	R31;
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_switch.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_switch.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_switch.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_switch.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/*
+ * Context switch support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h>
+
+.text
+
+/*
+ * The register used as a fast-path thread information pointer
+ * is determined as a kernel configuration option.  If it happens
+ * to be a callee-save register, we're going to be saving and
+ * restoring it twice here.
+ *
+ * This code anticipates a revised ABI where R20-23 are added
+ * to the set of callee-save registers, but this should be
+ * backward compatible to legacy tools.
+ */
+
+
+/*
+ *	void switch_to(struct task_struct *prev,
+ *		struct task_struct *next, struct task_struct *last);
+ */
+	.p2align 2
+	.globl __switch_to
+	.type	__switch_to, @function
+
+/*
+ * When we exit the wormhole, we need to store the previous task
+ * in the new R0's pointer.  Technically it should be R2, but they should
+ * be the same; seems like a legacy thing.  In short, don't butcher
+ * R0, let it go back out unmolested.
+ */
+
+__switch_to:
+	/*
+	 * Push callee-saves onto "prev" stack.
+	 * Here, we're sneaky because the LR and FP
+	 * storage of the thread_stack structure
+	 * is automagically allocated by allocframe,
+	 * so we pass struct size less 8.
+	 */
+	allocframe(#(_SWITCH_STACK_SIZE - 8));
+	memd(R29+#(_SWITCH_R2726))=R27:26;
+	memd(R29+#(_SWITCH_R2524))=R25:24;
+	memd(R29+#(_SWITCH_R2322))=R23:22;
+	memd(R29+#(_SWITCH_R2120))=R21:20;
+	memd(R29+#(_SWITCH_R1918))=R19:18;
+	memd(R29+#(_SWITCH_R1716))=R17:16;
+	/* Stash thread_info pointer in task_struct */
+	memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
+	memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
+	/* Switch to "next" stack and restore callee saves from there */
+	R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
+	{
+	    R27:26 = memd(R29+#(_SWITCH_R2726));
+	    R25:24 = memd(R29+#(_SWITCH_R2524));
+	}
+	{
+	    R23:22 = memd(R29+#(_SWITCH_R2322));
+	    R21:20 = memd(R29+#(_SWITCH_R2120));
+	}
+	{
+	    R19:18 = memd(R29+#(_SWITCH_R1918));
+	    R17:16 = memd(R29+#(_SWITCH_R1716));
+	}
+	{
+	    /* THREADINFO_REG is currently one of the callee-saved regs
+	     * above, and so be sure to re-load it last.
+	     */
+	    THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
+	    R31:30 = memd(R29+#_SWITCH_FP);
+	}
+	{
+	    R29 = add(R29,#_SWITCH_STACK_SIZE);
+	    jumpr R31;
+	}
+	.size	__switch_to, .-__switch_to
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_vectors.S linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_vectors.S
--- linux-libre-3.1-gnu1/arch/hexagon/kernel/vm_vectors.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/kernel/vm_vectors.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/*
+ * Event jump tables
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+
+.text
+
+/*  This is registered early on to allow angel  */
+.global _K_provisional_vec
+_K_provisional_vec:
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	trap1(#HVM_TRAP1_VMRTE)
+	jump 1f;
+	jump 1f;
+
+
+.global _K_VM_event_vector
+_K_VM_event_vector:
+1:
+	jump 1b;  /*  Reset  */
+	jump _K_enter_machcheck;
+	jump _K_enter_genex;
+	jump 1b;  /*  3 Rsvd  */
+	jump 1b;  /*  4 Rsvd  */
+	jump _K_enter_trap0;
+	jump 1b;  /*  6 Rsvd  */
+	jump _K_enter_interrupt;
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/lib/checksum.c linux-libre-3.2-gnu1/arch/hexagon/lib/checksum.c
--- linux-libre-3.1-gnu1/arch/hexagon/lib/checksum.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/lib/checksum.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,203 @@
+/*
+ * Checksum functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*  This was derived from arch/alpha/lib/checksum.c  */
+
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+#include <linux/uaccess.h>
+#include <asm/intrinsics.h>
+
+
+/*  Vector value operations  */
+#define SIGN(x, y)	((0x8000ULL*x)<<y)
+#define CARRY(x, y)	((0x0002ULL*x)<<y)
+#define SELECT(x, y)	((0x0001ULL*x)<<y)
+
+#define VR_NEGATE(a, b, c, d)	(SIGN(a, 48) + SIGN(b, 32) + SIGN(c, 16) \
+	+ SIGN(d, 0))
+#define VR_CARRY(a, b, c, d)	(CARRY(a, 48) + CARRY(b, 32) + CARRY(c, 16) \
+	+ CARRY(d, 0))
+#define VR_SELECT(a, b, c, d)	(SELECT(a, 48) + SELECT(b, 32) + SELECT(c, 16) \
+	+ SELECT(d, 0))
+
+
+/* optimized HEXAGON V3 intrinsic version */
+static inline unsigned short from64to16(u64 x)
+{
+	u64 sum;
+
+	sum = HEXAGON_P_vrmpyh_PP(x^VR_NEGATE(1, 1, 1, 1),
+			     VR_SELECT(1, 1, 1, 1));
+	sum += VR_CARRY(0, 0, 1, 0);
+	sum = HEXAGON_P_vrmpyh_PP(sum, VR_SELECT(0, 0, 1, 1));
+
+	return 0xFFFF & sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	return (__force __sum16)~from64to16(
+		(__force u64)saddr + (__force u64)daddr +
+		(__force u64)sum + ((len + proto) << 8));
+}
+
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	u64 result;
+
+	result = (__force u64)saddr + (__force u64)daddr +
+		 (__force u64)sum + ((len + proto) << 8);
+
+	/* Fold down to 32-bits so we don't lose in the typedef-less
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+
+/* optimized HEXAGON intrinsic version, with over read fixed */
+unsigned int do_csum(const void *voidptr, int len)
+{
+	u64 sum0, sum1, x0, x1, *ptr8_o, *ptr8_e, *ptr8;
+	int i, start, mid, end, mask;
+	const char *ptr = voidptr;
+	unsigned short *ptr2;
+	unsigned int *ptr4;
+
+	if (len <= 0)
+		return 0;
+
+	start = 0xF & (16-(((int) ptr) & 0xF)) ;
+	mask  = 0x7fffffffUL >> HEXAGON_R_cl0_R(len);
+	start = start & mask ;
+
+	mid = len - start;
+	end = mid & 0xF;
+	mid = mid>>4;
+	sum0 = mid << 18;
+	sum1 = 0;
+
+	if (start & 1)
+		sum0 += (u64) (ptr[0] << 8);
+	ptr2 = (unsigned short *) &ptr[start & 1];
+	if (start & 2)
+		sum1 += (u64) ptr2[0];
+	ptr4 = (unsigned int *) &ptr[start & 3];
+	if (start & 4) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum0 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr8 = (u64 *) &ptr[start & 7];
+	if (start & 8) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 += VR_CARRY(0, 0, 1, 0);
+	}
+	ptr8_o = (u64 *) (ptr + start);
+	ptr8_e = (u64 *) (ptr + start + 8);
+
+	if (mid) {
+		x0 = *ptr8_e; ptr8_e += 2;
+		x1 = *ptr8_o; ptr8_o += 2;
+		if (mid > 1)
+			for (i = 0; i < mid-1; i++) {
+				sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+					x0^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+					x1^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				x0 = *ptr8_e; ptr8_e += 2;
+				x1 = *ptr8_o; ptr8_o += 2;
+			}
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0, x0^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1, x1^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+	}
+
+	ptr4 = (unsigned int *) &ptr[start + (mid * 16) + (end & 8)];
+	if (end & 4) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum1 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr2 = (unsigned short *) &ptr[start + (mid * 16) + (end & 12)];
+	if (end & 2)
+		sum0 += (u64) ptr2[0];
+
+	if (end & 1)
+		sum1 += (u64) ptr[start + (mid * 16) + (end & 14)];
+
+	ptr8 = (u64 *) &ptr[start + (mid * 16)];
+	if (end & 8) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum0 += VR_CARRY(0, 0, 1, 0);
+	}
+	sum0 = HEXAGON_P_vrmpyh_PP((sum0+sum1)^VR_NEGATE(0, 0, 0, 1),
+		VR_SELECT(0, 0, 1, 1));
+	sum0 += VR_NEGATE(0, 0, 0, 1);
+	sum0 = HEXAGON_P_vrmpyh_PP(sum0, VR_SELECT(0, 0, 1, 1));
+
+	if (start & 1)
+		sum0 = (sum0 << 8) | (0xFF & (sum0 >> 8));
+
+	return 0xFFFF & sum0;
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/lib/io.c linux-libre-3.2-gnu1/arch/hexagon/lib/io.c
--- linux-libre-3.1-gnu1/arch/hexagon/lib/io.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/lib/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * I/O access functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/io.h>
+
+/*  These are all FIFO routines!  */
+
+/*
+ * __raw_readsw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_readsw(const void __iomem *addr, void *data, int len)
+{
+	const volatile short int *src = (short int *) addr;
+	short int *dst = (short int *) data;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to readsw");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+}
+
+/*
+ * __raw_writesw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_writesw(void __iomem *addr, const void *data, int len)
+{
+	const short int *src = (short int *)data;
+	volatile short int *dst = (short int *)addr;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to writesw");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
+
+/*  Pretty sure len is pre-adjusted for the length of the access already */
+void __raw_readsl(const void __iomem *addr, void *data, int len)
+{
+	const volatile long *src = (long *) addr;
+	long *dst = (long *) data;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to readsl");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+
+}
+
+void __raw_writesl(void __iomem *addr, const void *data, int len)
+{
+	const long *src = (long *)data;
+	volatile long *dst = (long *)addr;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to writesl");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/lib/Makefile linux-libre-3.2-gnu1/arch/hexagon/lib/Makefile
--- linux-libre-3.1-gnu1/arch/hexagon/lib/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/lib/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#
+# Makefile for hexagon-specific library files.
+#
+obj-y = checksum.o io.o memcpy.o memset.o
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/lib/memcpy.S linux-libre-3.2-gnu1/arch/hexagon/lib/memcpy.S
--- linux-libre-3.1-gnu1/arch/hexagon/lib/memcpy.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/lib/memcpy.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Description
+ *
+ *   library function for memcpy where length bytes are copied from
+ *   ptr_in to ptr_out. ptr_out is returned unchanged.
+ *   Allows any combination of alignment on input and output pointers
+ *   and length from 0 to 2^32-1
+ *
+ * Restrictions
+ *   The arrays should not overlap, the program will produce undefined output
+ *   if they do.
+ *   For blocks less than 16 bytes a byte by byte copy is performed. For
+ *   8byte alignments, and length multiples, a dword copy is performed up to
+ *   96bytes
+ * History
+ *
+ *   DJH  5/15/09 Initial version 1.0
+ *   DJH  6/ 1/09 Version 1.1 modified ABI to inlcude R16-R19
+ *   DJH  7/12/09 Version 1.2 optimized codesize down to 760 was 840
+ *   DJH 10/14/09 Version 1.3 added special loop for aligned case, was
+ *                            overreading bloated codesize back up to 892
+ *   DJH  4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads
+ *                            occuring if only 1 left outstanding, fixes bug
+ *                            # 3888, corrected for all alignments. Peeled off
+ *                            1 32byte chunk from kernel loop and extended 8byte
+ *                            loop at end to solve all combinations and prevent
+ *                            over read.  Fixed Ldword_loop_prolog to prevent
+ *                            overread for blocks less than 48bytes. Reduced
+ *                            codesize to 752 bytes
+ *   DJH  4/21/10 version 1.5 1.4 fix broke code for input block ends not
+ *                            aligned to dword boundaries,underwriting by 1
+ *                            byte, added detection for this and fixed. A
+ *                            little bloat.
+ *   DJH  4/23/10 version 1.6 corrected stack error, R20 was not being restored
+ *                            always, fixed the error of R20 being modified
+ *                            before it was being saved
+ * Natural c model
+ * ===============
+ * void * memcpy(char * ptr_out, char * ptr_in, int length) {
+ *   int i;
+ *   if(length) for(i=0; i < length; i++) { ptr_out[i] = ptr_in[i]; }
+ *   return(ptr_out);
+ * }
+ *
+ * Optimized memcpy function
+ * =========================
+ * void * memcpy(char * ptr_out, char * ptr_in, int len) {
+ *   int i, prolog, kernel, epilog, mask;
+ *   u8 offset;
+ *   s64 data0, dataF8, data70;
+ *
+ *   s64 * ptr8_in;
+ *   s64 * ptr8_out;
+ *   s32 * ptr4;
+ *   s16 * ptr2;
+ *
+ *   offset = ((int) ptr_in) & 7;
+ *   ptr8_in = (s64 *) &ptr_in[-offset];   //read in the aligned pointers
+ *
+ *   data70 = *ptr8_in++;
+ *   dataF8 = *ptr8_in++;
+ *
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   prolog = 32 - ((int) ptr_out);
+ *   mask  = 0x7fffffff >> HEXAGON_R_cl0_R(len);
+ *   prolog = prolog & mask;
+ *   kernel = len - prolog;
+ *   epilog = kernel & 0x1F;
+ *   kernel = kernel>>5;
+ *
+ *   if (prolog & 1) { ptr_out[0] = (u8) data0; data0 >>= 8; ptr_out += 1;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (prolog & 2) { ptr2[0] = (u16) data0;  data0 >>= 16; ptr_out += 2;}
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (prolog & 4) { ptr4[0] = (u32) data0;  data0 >>= 32; ptr_out += 4;}
+ *
+ *   offset = offset + (prolog & 7);
+ *   if (offset >= 8) {
+ *     data70 = dataF8;
+ *     dataF8 = *ptr8_in++;
+ *   }
+ *   offset = offset & 0x7;
+ *
+ *   prolog = prolog >> 3;
+ *   if (prolog) for (i=0; i < prolog; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   if(kernel) { kernel -= 1; epilog += 32; }
+ *   if(kernel) for(i=0; i < kernel; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   epilogdws = epilog >> 3;
+ *   if (epilogdws) for (i=0; i < epilogdws; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (epilog & 4) { ptr4[0] = (u32) data0; data0 >>= 32; ptr_out += 4;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (epilog & 2) { ptr2[0] = (u16) data0; data0 >>= 16; ptr_out += 2;}
+ *   if (epilog & 1) { *ptr_out++ = (u8) data0; }
+ *
+ *   return(ptr_out - length);
+ * }
+ *
+ * Codesize : 784 bytes
+ */
+
+
+#define ptr_out		R0	/*  destination  pounter  */
+#define ptr_in		R1	/*  source pointer  */
+#define len		R2	/*  length of copy in bytes  */
+
+#define data70		R13:12	/*  lo 8 bytes of non-aligned transfer  */
+#define dataF8		R11:10	/*  hi 8 bytes of non-aligned transfer  */
+#define ldata0		R7:6	/*  even 8 bytes chunks  */
+#define ldata1		R25:24	/*  odd 8 bytes chunks  */
+#define data1		R7	/*  lower 8 bytes of ldata1  */
+#define data0		R6	/*  lower 8 bytes of ldata0  */
+
+#define ifbyte		p0	/*  if transfer has bytes in epilog/prolog  */
+#define ifhword		p0	/*  if transfer has shorts in epilog/prolog  */
+#define ifword		p0	/*  if transfer has words in epilog/prolog  */
+#define noprolog	p0	/*  no prolog, xfer starts at 32byte  */
+#define nokernel	p1	/*  no 32byte multiple block in the transfer  */
+#define noepilog	p0	/*  no epilog, xfer ends on 32byte boundary  */
+#define align		p2	/*  alignment of input rel to 8byte boundary  */
+#define kernel1		p0	/*  kernel count == 1  */
+
+#define dalign		R25	/*  rel alignment of input to output data  */
+#define star3		R16	/*  number bytes in prolog - dwords  */
+#define rest		R8	/*  length - prolog bytes  */
+#define back		R7	/*  nr bytes > dword boundary in src block  */
+#define epilog		R3	/*  bytes in epilog  */
+#define inc		R15:14	/*  inc kernel by -1 and defetch ptr by 32  */
+#define kernel		R4	/*  number of 32byte chunks in kernel  */
+#define ptr_in_p_128	R5	/*  pointer for prefetch of input data  */
+#define mask		R8	/*  mask used to determine prolog size  */
+#define shift		R8	/*  used to work a shifter to extract bytes  */
+#define shift2		R5	/*  in epilog to workshifter to extract bytes */
+#define prolog		R15	/*  bytes in  prolog  */
+#define epilogdws	R15	/*  number dwords in epilog  */
+#define shiftb		R14	/*  used to extract bytes  */
+#define offset		R9	/*  same as align in reg  */
+#define ptr_out_p_32	R17	/*  pointer to output dczero  */
+#define align888	R14	/*  if simple dword loop can be used  */
+#define len8		R9	/*  number of dwords in length  */
+#define over		R20	/*  nr of bytes > last inp buf dword boundary */
+
+#define ptr_in_p_128kernel	R5:4	/*  packed fetch pointer & kernel cnt */
+
+	.section .text
+	.p2align 4
+        .global memcpy
+        .type memcpy, @function
+memcpy:
+{
+	p2 = cmp.eq(len, #0);		/*  =0 */
+	align888 = or(ptr_in, ptr_out);	/*  %8 < 97 */
+	p0 = cmp.gtu(len, #23);		/*  %1, <24 */
+	p1 = cmp.eq(ptr_in, ptr_out);	/*  attempt to overwrite self */
+}
+{
+	p1 = or(p2, p1);
+	p3 = cmp.gtu(len, #95);		/*  %8 < 97 */
+	align888 = or(align888, len);	/*  %8 < 97 */
+	len8 = lsr(len, #3);		/*  %8 < 97 */
+}
+{
+	dcfetch(ptr_in);		/*  zero/ptrin=ptrout causes fetch */
+	p2 = bitsclr(align888, #7);	/*  %8 < 97  */
+	if(p1) jumpr r31;		/*  =0  */
+}
+{
+	p2 = and(p2,!p3);			/*  %8 < 97  */
+	if (p2.new) len = add(len, #-8);	/*  %8 < 97  */
+	if (p2.new) jump:NT .Ldwordaligned; 	/*  %8 < 97  */
+}
+{
+	if(!p0) jump .Lbytes23orless;	/*  %1, <24  */
+	mask.l = #LO(0x7fffffff);
+	/*  all bytes before line multiples of data  */
+	prolog = sub(#0, ptr_out);
+}
+{
+	/*  save r31 on stack, decrement sp by 16  */
+	allocframe(#24);
+	mask.h = #HI(0x7fffffff);
+	ptr_in_p_128 = add(ptr_in, #32);
+	back = cl0(len);
+}
+{
+	memd(sp+#0) = R17:16;		/*  save r16,r17 on stack6  */
+	r31.l = #LO(.Lmemcpy_return);	/*  set up final return pointer  */
+	prolog &= lsr(mask, back);
+	offset = and(ptr_in, #7);
+}
+{
+	memd(sp+#8) = R25:24;		/*  save r25,r24 on stack  */
+	dalign = sub(ptr_out, ptr_in);
+	r31.h = #HI(.Lmemcpy_return);	/*  set up final return pointer  */
+}
+{
+	/*  see if there if input buffer end if aligned  */
+	over = add(len, ptr_in);
+	back = add(len, offset);
+	memd(sp+#16) = R21:20;		/*  save r20,r21 on stack  */
+}
+{
+	noprolog = bitsclr(prolog, #7);
+	prolog = and(prolog, #31);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	kernel = sub(len, prolog);
+	shift = asl(prolog, #3);
+	star3 = and(prolog, #7);
+	ptr_in = and(ptr_in, #-8);
+}
+{
+	prolog = lsr(prolog, #3);
+	epilog = and(kernel, #31);
+	ptr_out_p_32 = add(ptr_out, prolog);
+	over = and(over, #7);
+}
+{
+	p3 = cmp.gtu(back, #8);
+	kernel = lsr(kernel, #5);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	p1 = cmp.eq(prolog, #0);
+	if(!p1.new) prolog = add(prolog, #1);
+	dcfetch(ptr_in_p_128);	/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	nokernel = cmp.eq(kernel,#0);
+	dcfetch(ptr_in_p_128);	/* reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	shiftb = and(shift, #8);
+}
+{
+	dcfetch(ptr_in_p_128);		/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	if(nokernel) jump .Lskip64;
+	p2 = cmp.eq(kernel, #1);	/*  skip ovr if kernel == 0  */
+}
+{
+	dczeroa(ptr_out_p_32);
+	/*  don't advance pointer  */
+	if(!p2) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dalign = and(dalign, #31);
+	dczeroa(ptr_out_p_32);
+}
+.Lskip64:
+{
+	data70 = memd(ptr_in++#16);
+	if(p3) dataF8 = memd(ptr_in+#8);
+	if(noprolog) jump .Lnoprolog32;
+	align = offset;
+}
+/*  upto initial 7 bytes  */
+{
+	ldata0 = valignb(dataF8, data70, align);
+	ifbyte = tstbit(shift,#3);
+	offset = add(offset, star3);
+}
+{
+	if(ifbyte) memb(ptr_out++#1) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	shiftb = and(shift, #16);
+	ifhword = tstbit(shift,#4);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifword = tstbit(shift,#5);
+	p2 = cmp.gtu(offset, #7);
+}
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	if(p2) data70 = dataF8;
+	if(p2) dataF8 = memd(ptr_in++#8);	/*  another 8 bytes  */
+	align = offset;
+}
+.Lnoprolog32:
+{
+	p3 = sp1loop0(.Ldword_loop_prolog, prolog)
+	rest = sub(len, star3);	/*  whats left after the loop  */
+	p0 = cmp.gt(over, #0);
+}
+	if(p0) rest = add(rest, #16);
+.Ldword_loop_prolog:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p0 = cmp.gt(rest, #16);
+}
+{
+	data70 = dataF8;
+	if(p0) dataF8 = memd(ptr_in++#8);
+	rest = add(rest, #-8);
+}:endloop0
+.Lkernel:
+{
+	/*  kernel is at least 32bytes  */
+	p3 = cmp.gtu(kernel, #0);
+	/*  last itn. remove edge effects  */
+	if(p3.new) kernel = add(kernel, #-1);
+	/*  dealt with in last dword loop  */
+	if(p3.new) epilog = add(epilog, #32);
+}
+{
+	nokernel = cmp.eq(kernel, #0);		/*  after adjustment, recheck */
+	if(nokernel.new) jump:NT .Lepilog;	/*  likely not taken  */
+	inc = combine(#32, #-1);
+	p3 = cmp.gtu(dalign, #24);
+}
+{
+	if(p3) jump .Lodd_alignment;
+}
+{
+	loop0(.Loword_loop_25to31, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = kernel;
+}
+	.falign
+.Loword_loop_25to31:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+	p3 = cmp.eq(kernel, rest);
+}
+{
+	/*  kernel -= 1  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	/*  kill write on first iteration  */
+	if(!p3) memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+{
+	memd(ptr_out++#8) = ldata1;
+	jump .Lepilog;
+}
+.Lodd_alignment:
+{
+	loop0(.Loword_loop_00to24, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = add(kernel, #-1);
+}
+	.falign
+.Loword_loop_00to24:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+.Lepilog:
+{
+	noepilog = cmp.eq(epilog,#0);
+	epilogdws = lsr(epilog, #3);
+	kernel = and(epilog, #7);
+}
+{
+	if(noepilog) jumpr r31;
+	if(noepilog) ptr_out = sub(ptr_out, len);
+	p3 = cmp.eq(epilogdws, #0);
+	shift2 = asl(epilog, #3);
+}
+{
+	shiftb = and(shift2, #32);
+	ifword = tstbit(epilog,#2);
+	if(p3) jump .Lepilog60;
+	if(!p3) epilog = add(epilog, #-16);
+}
+{
+	loop0(.Ldword_loop_epilog, epilogdws);
+	/*  stop criteria is lsbs unless = 0 then its 8  */
+	p3 = cmp.eq(kernel, #0);
+	if(p3.new) kernel= #8;
+	p1 = cmp.gt(over, #0);
+}
+	/*  if not aligned to end of buffer execute 1 more iteration  */
+	if(p1) kernel= #0;
+.Ldword_loop_epilog:
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p3 = cmp.gt(epilog, kernel);
+}
+{
+	data70 = dataF8;
+	if(p3) dataF8 = memd(ptr_in++#8);
+	epilog = add(epilog, #-8);
+}:endloop0
+/* copy last 7 bytes */
+.Lepilog60:
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifhword = tstbit(epilog,#1);
+	shiftb = and(shift2, #16);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifbyte = tstbit(epilog,#0);
+	if(ifbyte.new) len = add(len, #-1);
+}
+{
+	if(ifbyte) memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);	/*  return dest pointer  */
+        jumpr r31;
+}
+/*  do byte copy for small n  */
+.Lbytes23orless:
+{
+	p3 = sp1loop0(.Lbyte_copy, len);
+	len = add(len, #-1);
+}
+.Lbyte_copy:
+{
+	data0 = memb(ptr_in++#1);
+	if(p3) memb(ptr_out++#1) = data0;
+}:endloop0
+{
+	memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;
+}
+/*  do dword copies for aligned in, out and length  */
+.Ldwordaligned:
+{
+	p3 = sp1loop0(.Ldword_copy, len8);
+}
+.Ldword_copy:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = memd(ptr_in++#8);
+}:endloop0
+{
+	memd(ptr_out) = ldata0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;	/*  return to function caller  */
+}
+.Lmemcpy_return:
+	r21:20 = memd(sp+#16);	/*  restore r20+r21  */
+{
+	r25:24 = memd(sp+#8);	/*  restore r24+r25  */
+	r17:16 = memd(sp+#0);	/*  restore r16+r17  */
+}
+	deallocframe;	/*  restore r31 and incrment stack by 16  */
+	jumpr r31
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/lib/memset.S linux-libre-3.2-gnu1/arch/hexagon/lib/memset.S
--- linux-libre-3.1-gnu1/arch/hexagon/lib/memset.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/lib/memset.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+/* HEXAGON assembly optimized memset */
+/* Replaces the standard library function memset */
+
+
+        .macro HEXAGON_OPT_FUNC_BEGIN name
+	.text
+	.p2align 4
+	.globl \name
+	.type  \name, @function
+\name:
+	.endm
+
+	.macro HEXAGON_OPT_FUNC_FINISH name
+	.size  \name, . - \name
+	.endm
+
+/* FUNCTION: memset (v2 version) */
+#if __HEXAGON_ARCH__ < 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r6 = #8
+		r7 = extractu(r0, #3 , #0)
+		p0 = cmp.eq(r2, #0)
+		p1 = cmp.gtu(r2, #7)
+	}
+	{
+		r4 = vsplatb(r1)
+		r8 = r0           /* leave r0 intact for return val  */
+		r9 = sub(r6, r7)  /* bytes until double alignment  */
+		if p0 jumpr r31   /* count == 0, so return  */
+	}
+	{
+		r3 = #0
+		r7 = #0
+		p0 = tstbit(r9, #0)
+		if p1 jump 2f /* skip byte loop */
+	}
+
+/* less than 8 bytes to set, so just set a byte at a time and return  */
+
+		loop0(1f, r2) /* byte loop */
+	.falign
+1: /* byte loop */
+	{
+		memb(r8++#1) = r4
+	}:endloop0
+		jumpr r31
+	.falign
+2: /* skip byte loop */
+	{
+		r6 = #1
+		p0 = tstbit(r9, #1)
+		p1 = cmp.eq(r2, #1)
+		if !p0 jump 3f /* skip initial byte store */
+	}
+	{
+		memb(r8++#1) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+3: /* skip initial byte store */
+	{
+		r6 = #2
+		p0 = tstbit(r9, #2)
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 4f /* skip initial half store */
+	}
+	{
+		memh(r8++#2) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+4: /* skip initial half store */
+	{
+		r6 = #4
+		p0 = cmp.gtu(r2, #7)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 5f /* skip initial word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		p0 = cmp.gtu(r2, #11)
+		if p1 jumpr r31
+	}
+	.falign
+5: /* skip initial word store */
+	{
+		r10 = lsr(r2, #3)
+		p1 = cmp.eq(r3, #1)
+		if !p0 jump 7f /* skip double loop */
+	}
+	{
+		r5 = r4
+		r6 = #8
+		loop0(6f, r10) /* double loop */
+	}
+
+/* set bytes a double word at a time  */
+
+	.falign
+6: /* double loop */
+	{
+		memd(r8++#8) = r5:4
+		r3:2 = sub(r3:2, r7:6)
+		p1 = cmp.eq(r2, #8)
+	}:endloop0
+	.falign
+7: /* skip double loop */
+	{
+		p0 = tstbit(r2, #2)
+		if p1 jumpr r31
+	}
+	{
+		r6 = #4
+		p0 = tstbit(r2, #1)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 8f /* skip final word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+8: /* skip final word store */
+	{
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 9f /* skip final half store */
+	}
+	{
+		memh(r8++#2) = r4
+		if p1 jumpr r31
+	}
+	.falign
+9: /* skip final half store */
+	{
+		memb(r8++#1) = r4
+		jumpr r31
+	}
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
+
+
+/*  FUNCTION: memset (v3 and higher version)  */
+#if __HEXAGON_ARCH__ >= 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r7=vsplatb(r1)
+		r6 = r0
+		if (r2==#0) jump:nt .L1
+	}
+	{
+		r5:4=combine(r7,r7)
+		p0 = cmp.gtu(r2,#8)
+		if (p0.new) jump:nt .L3
+	}
+	{
+		r3 = r0
+		loop0(.L47,r2)
+	}
+	.falign
+.L47:
+	{
+		memb(r3++#1) = r1
+	}:endloop0 /* start=.L47 */
+		jumpr r31
+.L3:
+	{
+		p0 = tstbit(r0,#0)
+		if (!p0.new) jump:nt .L8
+		p1 = cmp.eq(r2, #1)
+	}
+	{
+		r6 = add(r0, #1)
+		r2 = add(r2,#-1)
+		memb(r0) = r1
+		if (p1) jump .L1
+	}
+.L8:
+	{
+		p0 = tstbit(r6,#1)
+		if (!p0.new) jump:nt .L10
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+		p0 = cmp.eq(r2, #2)
+		if (p0.new) jump:nt .L1
+	}
+.L10:
+	{
+		p0 = tstbit(r6,#2)
+		if (!p0.new) jump:nt .L12
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+		p0 = cmp.eq(r2, #4)
+		if (p0.new) jump:nt .L1
+	}
+.L12:
+	{
+		p0 = cmp.gtu(r2,#127)
+		if (!p0.new) jump:nt .L14
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+.L17:
+	{
+		r3 = lsr(r2,#5)
+		if (r1!=#0) jump:nt .L18
+	}
+	{
+		r8 = r3
+		r3 = r6
+		loop0(.L46,r3)
+	}
+	.falign
+.L46:
+	{
+		dczeroa(r6)
+		r6 = add(r6,#32)
+		r2 = add(r2,#-32)
+	}:endloop0 /* start=.L46 */
+.L14:
+	{
+		p0 = cmp.gtu(r2,#7)
+		if (!p0.new) jump:nt .L28
+		r8 = lsr(r2,#3)
+	}
+		loop0(.L44,r8)
+	.falign
+.L44:
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}:endloop0 /* start=.L44 */
+.L28:
+	{
+		p0 = tstbit(r2,#2)
+		if (!p0.new) jump:nt .L33
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+	}
+.L33:
+	{
+		p0 = tstbit(r2,#1)
+		if (!p0.new) jump:nt .L35
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+	}
+.L35:
+		p0 = cmp.eq(r2,#1)
+		if (p0) memb(r6) = r1
+.L1:
+		jumpr r31
+.L18:
+		loop0(.L45,r3)
+	.falign
+.L45:
+		dczeroa(r6)
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-32)
+	}
+		memd(r6++#8) = r5:4
+		memd(r6++#8) = r5:4
+	{
+		memd(r6++#8) = r5:4
+	}:endloop0 /* start=.L45  */
+		jump .L14
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/Makefile linux-libre-3.2-gnu1/arch/hexagon/Makefile
--- linux-libre-3.1-gnu1/arch/hexagon/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+#  Makefile for the Hexagon arch
+
+KBUILD_DEFCONFIG = comet_defconfig
+
+# Do not use GP-relative jumps
+KBUILD_CFLAGS += -G0
+LDFLAGS_vmlinux += -G0
+
+# Do not use single-byte enums; these will overflow.
+KBUILD_CFLAGS += -fno-short-enums
+
+# Modules must use either long-calls, or use pic/plt.
+# Use long-calls for now, it's easier.  And faster.
+# CFLAGS_MODULE += -fPIC
+# LDFLAGS_MODULE += -shared
+CFLAGS_MODULE += -mlong-calls
+
+cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
+
+#  no KBUILD_LDFLAGS?
+LDFLAGS += $(ldflags-y)
+
+# Thread-info register will be r19.  This value is not configureable;
+# it is hard-coded in several files.
+TIR_NAME := r19
+KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
+KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC)
+
+head-y := arch/hexagon/kernel/head.o \
+	arch/hexagon/kernel/init_task.o
+
+core-y += arch/hexagon/kernel/ \
+	arch/hexagon/mm/ \
+	arch/hexagon/lib/
+
+#	arch/hexagon/platform/common/
+#
+#core-$(CONFIG_HEXAGON_COMET)		+= arch/hexagon/platform/comet/
+#machine-$(CONFIG_HEXAGON_COMET)		:= comet
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/cache.c linux-libre-3.2-gnu1/arch/hexagon/mm/cache.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/cache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Cache management functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/hexagon_vm.h>
+
+#define spanlines(start, end) \
+	(((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleaninva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+			"	dccleana(%0); "
+			"	icinva(%0);	"
+			:
+			: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	__asm__ __volatile__ (
+		"isync"
+	);
+	local_irq_restore(flags);
+}
+
+void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleana(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dcinva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+
+
+
+/*
+ * This is just really brutal and shouldn't be used anyways,
+ * especially on V2.  Left here just in case.
+ */
+void flush_cache_all_hexagon(void)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	__vmcache_ickill();
+	__vmcache_dckill();
+	__vmcache_l2kill();
+	local_irq_restore(flags);
+	mb();
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/copy_from_user.S linux-libre-3.2-gnu1/arch/hexagon/mm/copy_from_user.S
--- linux-libre-3.1-gnu1/arch/hexagon/mm/copy_from_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/copy_from_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * User memory copy functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy from user: loads can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_from_user_hexagon
+#include "copy_user_template.S"
+
+	/* LOAD FAULTS from COPY_FROM_USER */
+
+	/* Alignment loop.  r2 has been updated. Return it. */
+	.falign
+1009:
+2009:
+4009:
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops. Do epilog. Use src-src_sav to compute distance */
+	/* X - (A - B) == X + B - A */
+	.falign
+8089:
+	{
+		memd(dst) = d_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+4089:
+	{
+		memw(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+2089:
+	{
+		memh(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+1089:
+	{
+		memb(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY FROM USER: only loads can fail */
+
+	.section __ex_table,"a"
+	.long 1000b,1009b
+	.long 2000b,2009b
+	.long 4000b,4009b
+	.long 8080b,8089b
+	.long 4080b,4089b
+	.long 2080b,2089b
+	.long 1080b,1089b
+	.previous
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/copy_to_user.S linux-libre-3.2-gnu1/arch/hexagon/mm/copy_to_user.S
--- linux-libre-3.1-gnu1/arch/hexagon/mm/copy_to_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/copy_to_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/*
+ * User memory copying routines for the Hexagon Kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy to user: stores can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_to_user_hexagon
+#include "copy_user_template.S"
+
+	/* STORE FAULTS from COPY_TO_USER */
+	.falign
+1109:
+2109:
+4109:
+	/* Alignment loop.  r2 has been updated.  Return it. */
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops.  Use dst-dst_sav to compute distance */
+	/* dst holds best write, no need to unwind any loops */
+	/* X - (A - B) == X + B - A */
+	.falign
+8189:
+8199:
+4189:
+4199:
+2189:
+2199:
+1189:
+1199:
+	{
+		r2 += sub(dst_sav,dst)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY TO USER: only stores can fail */
+	.section __ex_table,"a"
+	.long 1100b,1109b
+	.long 2100b,2109b
+	.long 4100b,4109b
+	.long 8180b,8189b
+	.long 8190b,8199b
+	.long 4180b,4189b
+	.long 4190b,4199b
+	.long 2180b,2189b
+	.long 2190b,2199b
+	.long 1180b,1189b
+	.long 1190b,1199b
+	.previous
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/copy_user_template.S linux-libre-3.2-gnu1/arch/hexagon/mm/copy_user_template.S
--- linux-libre-3.1-gnu1/arch/hexagon/mm/copy_user_template.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/copy_user_template.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Numerology:
+ * WXYZ
+ * W: width in bytes
+ * X: Load=0, Store=1
+ * Y: Location 0=preamble,8=loop,9=epilog
+ * Z: Location=0,handler=9
+ */
+	.text
+	.global FUNCNAME
+	.type FUNCNAME, @function
+	.p2align 5
+FUNCNAME:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (!p0.new) jump:nt .Ldone
+		r3 = or(dst,src)
+		r4 = xor(dst,src)
+	}
+	{
+		p1 = cmp.gtu(bytes,#15)
+		p0 = bitsclr(r3,#7)
+		if (!p0.new) jump:nt .Loop_not_aligned_8
+		src_dst_sav = combine(src,dst)
+	}
+
+	{
+		loopcount = lsr(bytes,#3)
+		if (!p1) jump .Lsmall
+	}
+	p3=sp1loop0(.Loop8,loopcount)
+.Loop8:
+8080:
+8180:
+	{
+		if (p3) memd(dst++#8) = d_dbuf
+		d_dbuf = memd(src++#8)
+	}:endloop0
+8190:
+	{
+		memd(dst++#8) = d_dbuf
+		bytes -= asl(loopcount,#3)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_8:
+	{
+		p0 = bitsclr(r4,#7)
+		if (p0.new) jump:nt .Lalign
+	}
+	{
+		p0 = bitsclr(r3,#3)
+		if (!p0.new) jump:nt .Loop_not_aligned_4
+		p1 = cmp.gtu(bytes,#7)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#2)
+	}
+	p3=sp1loop0(.Loop4,loopcount)
+.Loop4:
+4080:
+4180:
+	{
+		if (p3) memw(dst++#4) = w_dbuf
+		w_dbuf = memw(src++#4)
+	}:endloop0
+4190:
+	{
+		memw(dst++#4) = w_dbuf
+		bytes -= asl(loopcount,#2)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_4:
+	{
+		p0 = bitsclr(r3,#1)
+		if (!p0.new) jump:nt .Loop_not_aligned
+		p1 = cmp.gtu(bytes,#3)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#1)
+	}
+	p3=sp1loop0(.Loop2,loopcount)
+.Loop2:
+2080:
+2180:
+	{
+		if (p3) memh(dst++#2) = w_dbuf
+		w_dbuf = memuh(src++#2)
+	}:endloop0
+2190:
+	{
+		memh(dst++#2) = w_dbuf
+		bytes -= asl(loopcount,#1)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned: /* Works for as small as one byte */
+	p3=sp1loop0(.Loop1,bytes)
+.Loop1:
+1080:
+1180:
+	{
+		if (p3) memb(dst++#1) = w_dbuf
+		w_dbuf = memub(src++#1)
+	}:endloop0
+	/* Done */
+1190:
+	{
+		memb(dst) = w_dbuf
+		jumpr r31
+		r0 = #0
+	}
+
+.Lsmall:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (p0.new) jump:nt .Loop_not_aligned
+	}
+.Ldone:
+	{
+		r0 = #0
+		jumpr r31
+	}
+	.falign
+.Lalign:
+1000:
+	{
+		if (p0.new) w_dbuf = memub(src)
+		p0 = tstbit(src,#0)
+		if (!p1) jump .Lsmall
+	}
+1100:
+	{
+		if (p0) memb(dst++#1) = w_dbuf
+		if (p0) bytes = add(bytes,#-1)
+		if (p0) src = add(src,#1)
+	}
+2000:
+	{
+		if (p0.new) w_dbuf = memuh(src)
+		p0 = tstbit(src,#1)
+		if (!p1) jump .Lsmall
+	}
+2100:
+	{
+		if (p0) memh(dst++#2) = w_dbuf
+		if (p0) bytes = add(bytes,#-2)
+		if (p0) src = add(src,#2)
+	}
+4000:
+	{
+		if (p0.new) w_dbuf = memw(src)
+		p0 = tstbit(src,#2)
+		if (!p1) jump .Lsmall
+	}
+4100:
+	{
+		if (p0) memw(dst++#4) = w_dbuf
+		if (p0) bytes = add(bytes,#-4)
+		if (p0) src = add(src,#4)
+		jump FUNCNAME
+	}
+	.size FUNCNAME,.-FUNCNAME
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/init.c linux-libre-3.2-gnu1/arch/hexagon/mm/init.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * Memory subsystem initialization for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/atomic.h>
+#include <linux/highmem.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+#include <asm/vm_mmu.h>
+
+/*
+ * Define a startpg just past the end of the kernel image and a lastpg
+ * that corresponds to the end of real or simulated platform memory.
+ */
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+
+unsigned long bootmem_lastpg;  /*  Should be set by platform code  */
+
+/*  Set as variable to limit PMD copies  */
+int max_kernel_seg = 0x303;
+
+/*  think this should be (page_size-1) the way it's used...*/
+unsigned long zero_page_mask;
+
+/*  indicate pfn's of high memory  */
+unsigned long highstart_pfn, highend_pfn;
+
+/* struct mmu_gather defined in asm-generic.h;  */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/* Default cache attribute for newly created page tables */
+unsigned long _dflt_cache_att = CACHEDEF;
+
+/*
+ * The current "generation" of kernel map, which should not roll
+ * over until Hell freezes over.  Actual bound in years needs to be
+ * calculated to confirm.
+ */
+DEFINE_SPINLOCK(kmap_gen_lock);
+
+/*  checkpatch says don't init this to 0.  */
+unsigned long long kmap_generation;
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Fixes up more stuff for HIGHMEM
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+	/*  No idea where this is actually declared.  Seems to evade LXR.  */
+	totalram_pages += free_all_bootmem();
+	num_physpages = bootmem_lastpg;	/*  seriously, what?  */
+
+	printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
+
+	/*
+	 *  To-Do:  someone somewhere should wipe out the bootmem map
+	 *  after we're done?
+	 */
+
+	/*
+	 * This can be moved to some more virtual-memory-specific
+	 * initialization hook at some point.  Set the init_mm
+	 * descriptors "context" value to point to the initial
+	 * kernel segment table's physical address.
+	 */
+	init_mm.context.ptbase = __pa(init_mm.pgd);
+}
+
+/*
+ * free_initmem - frees memory used by stuff declared with __init
+ *
+ * Todo:  free pages between __init_begin and __init_end; possibly
+ * some devtree related stuff as well.
+ */
+void __init_refok free_initmem(void)
+{
+}
+
+/*
+ * free_initrd_mem - frees...  initrd memory.
+ * @start - start of init memory
+ * @end - end of init memory
+ *
+ * Apparently has to be passed the address of the initrd memory.
+ *
+ * Wrapped by #ifdef CONFIG_BLKDEV_INITRD
+ */
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
+
+void sync_icache_dcache(pte_t pte)
+{
+	unsigned long addr;
+	struct page *page;
+
+	page = pte_page(pte);
+	addr = (unsigned long) page_address(page);
+
+	__vmcache_idsync(addr, PAGE_SIZE);
+}
+
+/*
+ * In order to set up page allocator "nodes",
+ * somebody has to call free_area_init() for UMA.
+ *
+ * In this mode, we only have one pg_data_t
+ * structure: contig_mem_data.
+ */
+void __init paging_init(void)
+{
+	unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
+
+	/*
+	 *  This is not particularly well documented anywhere, but
+	 *  give ZONE_NORMAL all the memory, including the big holes
+	 *  left by the kernel+bootmem_map which are already left as reserved
+	 *  in the bootmem_map; free_area_init should see those bits and
+	 *  adjust accordingly.
+	 */
+
+	zones_sizes[ZONE_NORMAL] = max_low_pfn;
+
+	free_area_init(zones_sizes);  /*  sets up the zonelists and mem_map  */
+
+	/*
+	 * Start of high memory area.  Will probably need something more
+	 * fancy if we...  get more fancy.
+	 */
+	high_memory = (void *)((bootmem_lastpg + 1) << PAGE_SHIFT);
+}
+
+#ifndef DMA_RESERVE
+#define DMA_RESERVE		(4)
+#endif
+
+#define DMA_CHUNKSIZE		(1<<22)
+#define DMA_RESERVED_BYTES	(DMA_RESERVE * DMA_CHUNKSIZE)
+
+/*
+ * Pick out the memory size.  We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	unsigned long size;
+	char *endp;
+
+	size = memparse(p, &endp);
+
+	bootmem_lastpg = PFN_DOWN(size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22);
+
+void __init setup_arch_memory(void)
+{
+	int bootmap_size;
+	/*  XXX Todo: this probably should be cleaned up  */
+	u32 *segtable = (u32 *) &swapper_pg_dir[0];
+	u32 *segtable_end;
+
+	/*
+	 * Set up boot memory allocator
+	 *
+	 * The Gorman book also talks about these functions.
+	 * This needs to change for highmem setups.
+	 */
+
+	/* Memory size needs to be a multiple of 16M */
+	bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
+		~((BIG_KERNEL_PAGE_SIZE) - 1));
+
+	/*
+	 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
+	 * memory allocation
+	 */
+	bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
+				    PFN_DOWN(DMA_RESERVED_BYTES));
+
+	printk(KERN_INFO "bootmem_startpg:  0x%08lx\n", bootmem_startpg);
+	printk(KERN_INFO "bootmem_lastpg:  0x%08lx\n", bootmem_lastpg);
+	printk(KERN_INFO "bootmap_size:  %d\n", bootmap_size);
+	printk(KERN_INFO "max_low_pfn:  0x%08lx\n", max_low_pfn);
+
+	/*
+	 * The default VM page tables (will be) populated with
+	 * VA=PA+PAGE_OFFSET mapping.  We go in and invalidate entries
+	 * higher than what we have memory for.
+	 */
+
+	/*  this is pointer arithmetic; each entry covers 4MB  */
+	segtable = segtable + (PAGE_OFFSET >> 22);
+
+	/*  this actually only goes to the end of the first gig  */
+	segtable_end = segtable + (1<<(30-22));
+
+	/*  Move forward to the start of empty pages  */
+	segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+
+	{
+	    int i;
+
+	    for (i = 1 ; i <= DMA_RESERVE ; i++)
+		segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+				| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
+				| __HEXAGON_C_UNC << 6
+				| __HVM_PDE_S_4MB);
+	}
+
+	printk(KERN_INFO "clearing segtable from %p to %p\n", segtable,
+		segtable_end);
+	while (segtable < (segtable_end-8))
+		*(segtable++) = __HVM_PDE_S_INVALID;
+	/* stop the pointer at the device I/O 4MB page  */
+
+	printk(KERN_INFO "segtable = %p (should be equal to _K_io_map)\n",
+		segtable);
+
+#if 0
+	/*  Other half of the early device table from vm_init_segtable. */
+	printk(KERN_INFO "&_K_init_devicetable = 0x%08x\n",
+		(unsigned long) _K_init_devicetable-PAGE_OFFSET);
+	*segtable = ((u32) (unsigned long) _K_init_devicetable-PAGE_OFFSET) |
+		__HVM_PDE_S_4KB;
+	printk(KERN_INFO "*segtable = 0x%08x\n", *segtable);
+#endif
+
+	/*
+	 * Free all the memory that wasn't taken up by the bootmap, the DMA
+	 * reserve, or kernel itself.
+	 */
+	free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+		     PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
+		     DMA_RESERVED_BYTES);
+
+	/*
+	 *  The bootmem allocator seemingly just lives to feed memory
+	 *  to the paging system
+	 */
+	printk(KERN_INFO "PAGE_SIZE=%lu\n", PAGE_SIZE);
+	paging_init();  /*  See Gorman Book, 2.3  */
+
+	/*
+	 *  At this point, the page allocator is kind of initialized, but
+	 *  apparently no pages are available (just like with the bootmem
+	 *  allocator), and need to be freed themselves via mem_init(),
+	 *  which is called by start_kernel() later on in the process
+	 */
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/ioremap.c linux-libre-3.2-gnu1/arch/hexagon/mm/ioremap.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/ioremap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/ioremap.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * I/O remap functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+	unsigned long last_addr, addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	struct vm_struct *area;
+
+	pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE
+					|(__HEXAGON_C_DEV << 6));
+
+	last_addr = phys_addr + size - 1;
+
+	/*  Wrapping not allowed  */
+	if (!size || (last_addr < phys_addr))
+		return NULL;
+
+	/*  Rounds up to next page size, including whole-page offset */
+	size = PAGE_ALIGN(offset + size);
+
+	area = get_vm_area(size, VM_IOREMAP);
+	addr = (unsigned long)area->addr;
+
+	if (ioremap_page_range(addr, addr+size, phys_addr, prot)) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	return (void __iomem *) (offset + addr);
+}
+
+void __iounmap(const volatile void __iomem *addr)
+{
+	vunmap((void *) ((unsigned long) addr & PAGE_MASK));
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/Makefile linux-libre-3.2-gnu1/arch/hexagon/mm/Makefile
--- linux-libre-3.1-gnu1/arch/hexagon/mm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#
+# Makefile for Hexagon memory management subsystem
+#
+
+obj-y := init.o pgalloc.o ioremap.o uaccess.o vm_fault.o cache.o
+obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/pgalloc.c linux-libre-3.2-gnu1/arch/hexagon/mm/pgalloc.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/pgalloc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/pgalloc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+
+void __init pgtable_cache_init(void)
+{
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/strnlen_user.S linux-libre-3.2-gnu1/arch/hexagon/mm/strnlen_user.S
--- linux-libre-3.1-gnu1/arch/hexagon/mm/strnlen_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/strnlen_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * User string length functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define isrc	r0
+#define max	r1	/*  Do not change!  */
+
+#define end	r2
+#define tmp1	r3
+
+#define obo	r6	/*  off-by-one  */
+#define start	r7
+#define mod8	r8
+#define dbuf    r15:14
+#define dcmp	r13:12
+
+/*
+ * The vector mask version of this turned out *really* badly.
+ * The hardware loop version also turned out *really* badly.
+ * Seems straight pointer arithmetic basically wins here.
+ */
+
+#define fname __strnlen_user
+
+	.text
+	.global fname
+	.type fname, @function
+	.p2align 5  /*  why?  */
+fname:
+	{
+		mod8 = and(isrc,#7);
+		end = add(isrc,max);
+		start = isrc;
+	}
+	{
+		P0 = cmp.eq(mod8,#0);
+		mod8 = and(end,#7);
+		dcmp = #0;
+		if (P0.new) jump:t dw_loop;	/*  fire up the oven  */
+	}
+
+alignment_loop:
+fail_1:	{
+		tmp1 = memb(start++#1);
+	}
+	{
+		P0 = cmp.eq(tmp1,#0);
+		if (P0.new) jump:nt exit_found;
+		P1 = cmp.gtu(end,start);
+		mod8 = and(start,#7);
+	}
+	{
+		if (!P1) jump exit_error;  /*  hit the end  */
+		P0 = cmp.eq(mod8,#0);
+	}
+	{
+		if (!P0) jump alignment_loop;
+	}
+
+
+
+dw_loop:
+fail_2:	{
+		dbuf = memd(start);
+		obo = add(start,#1);
+	}
+	{
+		P0 = vcmpb.eq(dbuf,dcmp);
+	}
+	{
+		tmp1 = P0;
+		P0 = cmp.gtu(end,start);
+	}
+	{
+		tmp1 = ct0(tmp1);
+		mod8 = and(end,#7);
+		if (!P0) jump end_check;
+	}
+	{
+		P0 = cmp.eq(tmp1,#32);
+		if (!P0.new) jump:nt exit_found;
+		if (!P0.new) start = add(obo,tmp1);
+	}
+	{
+		start = add(start,#8);
+		jump dw_loop;
+	}	/*  might be nice to combine these jumps...   */
+
+
+end_check:
+	{
+		P0 = cmp.gt(tmp1,mod8);
+		if (P0.new) jump:nt exit_error;	/*  neverfound!  */
+		start = add(obo,tmp1);
+	}
+
+exit_found:
+	{
+		R0 = sub(start,isrc);
+		jumpr R31;
+	}
+
+exit_error:
+	{
+		R0 = add(max,#1);
+		jumpr R31;
+	}
+
+	/*  Uh, what does the "fixup" return here?  */
+	.falign
+fix_1:
+	{
+		R0 = #0;
+		jumpr R31;
+	}
+
+	.size fname,.-fname
+
+
+.section __ex_table,"a"
+.long fail_1,fix_1
+.long fail_2,fix_1
+.previous
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/uaccess.c linux-libre-3.2-gnu1/arch/hexagon/mm/uaccess.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/uaccess.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/uaccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Support for user memory access from kernel.  This will
+ * probably be inlined for performance at some point, but
+ * for ease of debug, and to a lesser degree for code size,
+ * we implement here as subroutines.
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+/*
+ * For clear_user(), exploit previously defined copy_to_user function
+ * and the fact that we've got a handy zero page defined in kernel/head.S
+ *
+ * dczero here would be even faster.
+ */
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	long uncleared;
+
+	while (count > PAGE_SIZE) {
+		uncleared = __copy_to_user_hexagon(dest, &empty_zero_page,
+						PAGE_SIZE);
+		if (uncleared)
+			return count - (PAGE_SIZE - uncleared);
+		count -= PAGE_SIZE;
+		dest += PAGE_SIZE;
+	}
+	if (count)
+		count = __copy_to_user_hexagon(dest, &empty_zero_page, count);
+
+	return count;
+}
+
+unsigned long clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	if (!access_ok(VERIFY_WRITE, dest, count))
+		return count;
+	else
+		return __clear_user_hexagon(dest, count);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/vm_fault.c linux-libre-3.2-gnu1/arch/hexagon/mm/vm_fault.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/vm_fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/vm_fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,187 @@
+/*
+ * Memory fault handling for Hexagon
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Page fault handling for the Hexagon Virtual Machine.
+ * Can also be called by a native port emulating the HVM
+ * execptions.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+
+/*
+ * Decode of hardware exception sends us to one of several
+ * entry points.  At each, we generate canonical arguments
+ * for handling by the abstract memory management code.
+ */
+#define FLT_IFETCH     -1
+#define FLT_LOAD        0
+#define FLT_STORE       1
+
+
+/*
+ * Canonical page fault handler
+ */
+void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	siginfo_t info;
+	int si_code = SEGV_MAPERR;
+	int fault;
+	const struct exception_table_entry *fixup;
+
+	/*
+	 * If we're in an interrupt or have no user context,
+	 * then must not take the fault.
+	 */
+	if (unlikely(in_interrupt() || !mm))
+		goto no_context;
+
+	local_irq_enable();
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+
+	if (vma->vm_start <= address)
+		goto good_area;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+good_area:
+	/* Address space is OK.  Now check access rights. */
+	si_code = SEGV_ACCERR;
+
+	switch (cause) {
+	case FLT_IFETCH:
+		if (!(vma->vm_flags & VM_EXEC))
+			goto bad_area;
+		break;
+	case FLT_LOAD:
+		if (!(vma->vm_flags & VM_READ))
+			goto bad_area;
+		break;
+	case FLT_STORE:
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+		break;
+	}
+
+	fault = handle_mm_fault(mm, vma, address, (cause > 0));
+
+	/* The most common case -- we are done. */
+	if (likely(!(fault & VM_FAULT_ERROR))) {
+		if (fault & VM_FAULT_MAJOR)
+			current->maj_flt++;
+		else
+			current->min_flt++;
+
+		up_read(&mm->mmap_sem);
+		return;
+	}
+
+	up_read(&mm->mmap_sem);
+
+	/* Handle copyin/out exception cases */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_OOM) {
+		pagefault_out_of_memory();
+		return;
+	}
+
+	/* User-mode address is in the memory map, but we are
+	 * unable to fix up the page fault.
+	 */
+	if (fault & VM_FAULT_SIGBUS) {
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+	}
+	/* Address is not in the memory map */
+	else {
+		info.si_signo = SIGSEGV;
+		info.si_code = SEGV_ACCERR;
+	}
+	info.si_errno = 0;
+	info.si_addr = (void __user *)address;
+	force_sig_info(info.si_code, &info, current);
+	return;
+
+bad_area:
+	up_read(&mm->mmap_sem);
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = si_code;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+	/* Kernel-mode fault falls through */
+
+no_context:
+	fixup = search_exception_tables(pt_elr(regs));
+	if (fixup) {
+		pt_set_elr(regs, fixup->fixup);
+		return;
+	}
+
+	/* Things are looking very, very bad now */
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Unable to handle kernel paging request at "
+		"virtual address 0x%08lx, regs %p\n", address, regs);
+	die("Bad Kernel VA", regs, SIGKILL);
+}
+
+
+void read_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_LOAD, regs);
+}
+
+void write_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_STORE, regs);
+}
+
+void execute_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_IFETCH, regs);
+}
diff -druNp linux-libre-3.1-gnu1/arch/hexagon/mm/vm_tlb.c linux-libre-3.2-gnu1/arch/hexagon/mm/vm_tlb.c
--- linux-libre-3.1-gnu1/arch/hexagon/mm/vm_tlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/hexagon/mm/vm_tlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ * Hexagon Virtual Machine TLB functions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The Hexagon Virtual Machine conceals the real workings of
+ * the TLB, but there are one or two functions that need to
+ * be instantiated for it, differently from a native build.
+ */
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * Initial VM implementation has only one map active at a time, with
+ * TLB purgings on changes.  So either we're nuking the current map,
+ * or it's a no-op.  This operation is messy on true SMPs where other
+ * processors must be induced to flush the copies in their local TLBs,
+ * but Hexagon thread-based virtual processors share the same MMU.
+ */
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase == current->active_mm->context.ptbase)
+		__vmclrmap((void *)start, end - start);
+}
+
+/*
+ * Flush a page from the kernel virtual map - used by highmem
+ */
+void flush_tlb_one(unsigned long vaddr)
+{
+	__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush all TLBs across all CPUs, virtual or real.
+ * A single Hexagon core has 6 thread contexts but
+ * only one TLB.
+ */
+void tlb_flush_all(void)
+{
+	/*  should probably use that fixaddr end or whateve label  */
+	__vmclrmap(0, 0xffff0000);
+}
+
+/*
+ * Flush TLB entries associated with a given mm_struct mapping.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	/* Current Virtual Machine has only one map active at a time */
+	if (current->active_mm->context.ptbase == mm->context.ptbase)
+		tlb_flush_all();
+}
+
+/*
+ * Flush TLB state associated with a page of a vma.
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase  == current->active_mm->context.ptbase)
+		__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush TLB entries associated with a kernel address range.
+ * Like flush range, but without the check on the vma->vm_mm.
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+		__vmclrmap((void *)start, end - start);
+}
diff -druNp linux-libre-3.1-gnu1/arch/ia64/configs/generic_defconfig linux-libre-3.2-gnu1/arch/ia64/configs/generic_defconfig
--- linux-libre-3.1-gnu1/arch/ia64/configs/generic_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/configs/generic_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_IGB=y
@@ -234,4 +235,4 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
 CONFIG_MISC_DEVICES=y
-CONFIG_DMAR=y
+CONFIG_INTEL_IOMMU=y
diff -druNp linux-libre-3.1-gnu1/arch/ia64/configs/gensparse_defconfig linux-libre-3.2-gnu1/arch/ia64/configs/gensparse_defconfig
--- linux-libre-3.1-gnu1/arch/ia64/configs/gensparse_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/configs/gensparse_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -75,6 +75,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druNp linux-libre-3.1-gnu1/arch/ia64/configs/tiger_defconfig linux-libre-3.2-gnu1/arch/ia64/configs/tiger_defconfig
--- linux-libre-3.1-gnu1/arch/ia64/configs/tiger_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/configs/tiger_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druNp linux-libre-3.1-gnu1/arch/ia64/configs/xen_domu_defconfig linux-libre-3.2-gnu1/arch/ia64/configs/xen_domu_defconfig
--- linux-libre-3.1-gnu1/arch/ia64/configs/xen_domu_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/configs/xen_domu_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druNp linux-libre-3.1-gnu1/arch/ia64/configs/zx1_defconfig linux-libre-3.2-gnu1/arch/ia64/configs/zx1_defconfig
--- linux-libre-3.1-gnu1/arch/ia64/configs/zx1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/configs/zx1_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@ CONFIG_TULIP_MMIO=y
 CONFIG_TULIP_NAPI=y
 CONFIG_TULIP_NAPI_HW_MITIGATION=y
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=y
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druNp linux-libre-3.1-gnu1/arch/ia64/dig/Makefile linux-libre-3.2-gnu1/arch/ia64/dig/Makefile
--- linux-libre-3.1-gnu1/arch/ia64/dig/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/dig/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #
 
 obj-y := setup.o
-ifeq ($(CONFIG_DMAR), y)
+ifeq ($(CONFIG_INTEL_IOMMU), y)
 obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o
 else
 obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff -druNp linux-libre-3.1-gnu1/arch/ia64/hp/common/hwsw_iommu.c linux-libre-3.2-gnu1/arch/ia64/hp/common/hwsw_iommu.c
--- linux-libre-3.1-gnu1/arch/ia64/hp/common/hwsw_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/hp/common/hwsw_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/swiotlb.h>
+#include <linux/export.h>
 #include <asm/machvec.h>
 
 extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
diff -druNp linux-libre-3.1-gnu1/arch/ia64/hp/common/sba_iommu.c linux-libre-3.2-gnu1/arch/ia64/hp/common/sba_iommu.c
--- linux-libre-3.1-gnu1/arch/ia64/hp/common/sba_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/hp/common/sba_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -915,7 +915,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static dma_addr_t sba_map_page(struct device *dev, struct page *page,
 			       unsigned long poff, size_t size,
@@ -1044,7 +1044,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
 			   enum dma_data_direction dir, struct dma_attrs *attrs)
@@ -1127,7 +1127,7 @@ void sba_unmap_single_attrs(struct devic
  * @size:  number of bytes mapped in driver buffer.
  * @dma_handle:  IOVA of new buffer.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void *
 sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
@@ -1190,7 +1190,7 @@ sba_alloc_coherent (struct device *dev,
  * @vaddr:  virtual address IOVA of "consistent" buffer.
  * @dma_handler:  IO virtual address of "consistent" buffer.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_free_coherent (struct device *dev, size_t size, void *vaddr,
 			       dma_addr_t dma_handle)
@@ -1453,7 +1453,7 @@ static void sba_unmap_sg_attrs(struct de
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
 			    int nents, enum dma_data_direction dir,
@@ -1549,7 +1549,7 @@ static int sba_map_sg_attrs(struct devic
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
 			       int nents, enum dma_data_direction dir,
diff -druNp linux-libre-3.1-gnu1/arch/ia64/hp/sim/simeth.c linux-libre-3.2-gnu1/arch/ia64/hp/sim/simeth.c
--- linux-libre-3.1-gnu1/arch/ia64/hp/sim/simeth.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/hp/sim/simeth.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,7 +172,7 @@ static const struct net_device_ops simet
 	.ndo_stop		= simeth_close,
 	.ndo_start_xmit		= simeth_tx,
 	.ndo_get_stats		= simeth_get_stats,
-	.ndo_set_multicast_list	= set_multicast_list, /* not yet used */
+	.ndo_set_rx_mode	= set_multicast_list, /* not yet used */
 
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/cputime.h linux-libre-3.2-gnu1/arch/ia64/include/asm/cputime.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@ typedef u64 cputime64_t;
  */
 #define cputime_to_usecs(__ct)		((__ct) / NSEC_PER_USEC)
 #define usecs_to_cputime(__usecs)	((__usecs) * NSEC_PER_USEC)
+#define usecs_to_cputime64(__usecs)	usecs_to_cputime(__usecs)
 
 /*
  * Convert cputime <-> seconds
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/device.h linux-libre-3.2-gnu1/arch/ia64/include/asm/device.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@ struct dev_archdata {
 #ifdef CONFIG_ACPI
 	void	*acpi_handle;
 #endif
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/iommu.h linux-libre-3.2-gnu1/arch/ia64/include/asm/iommu.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/iommu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/iommu.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,14 @@
 
 extern void pci_iommu_shutdown(void);
 extern void no_iommu_init(void);
+#ifdef	CONFIG_INTEL_IOMMU
 extern int force_iommu, no_iommu;
-extern int iommu_detected;
-#ifdef	CONFIG_DMAR
 extern int iommu_pass_through;
+extern int iommu_detected;
 #else
 #define iommu_pass_through	(0)
+#define no_iommu		(1)
+#define iommu_detected		(0)
 #endif
 extern void iommu_dma_init(void);
 extern void machvec_init(const char *name);
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/pci.h linux-libre-3.2-gnu1/arch/ia64/include/asm/pci.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/pci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@ static inline int pci_get_legacy_ide_irq
 	return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
 }
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 extern void pci_iommu_alloc(void);
 #endif
 #endif /* _ASM_IA64_PCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/unistd.h linux-libre-3.2-gnu1/arch/ia64/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -321,11 +321,13 @@
 #define __NR_syncfs			1329
 #define __NR_setns			1330
 #define __NR_sendmmsg			1331
+#define __NR_process_vm_readv		1332
+#define __NR_process_vm_writev		1333
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls			308 /* length of syscall table */
+#define NR_syscalls			310 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/xen/grant_table.h linux-libre-3.2-gnu1/arch/ia64/include/asm/xen/grant_table.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/xen/grant_table.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/xen/grant_table.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/grant_table.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef _ASM_IA64_XEN_GRANT_TABLE_H
-#define _ASM_IA64_XEN_GRANT_TABLE_H
-
-struct vm_struct *xen_alloc_vm_area(unsigned long size);
-void xen_free_vm_area(struct vm_struct *area);
-
-#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */
diff -druNp linux-libre-3.1-gnu1/arch/ia64/include/asm/xen/interface.h linux-libre-3.2-gnu1/arch/ia64/include/asm/xen/interface.h
--- linux-libre-3.1-gnu1/arch/ia64/include/asm/xen/interface.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/include/asm/xen/interface.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,7 @@ DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
 DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
+DEFINE_GUEST_HANDLE(uint64_t);
 
 typedef unsigned long xen_pfn_t;
 DEFINE_GUEST_HANDLE(xen_pfn_t);
diff -druNp linux-libre-3.1-gnu1/arch/ia64/Kconfig linux-libre-3.2-gnu1/arch/ia64/Kconfig
--- linux-libre-3.1-gnu1/arch/ia64/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@ config HAVE_SETUP_PER_CPU_AREA
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool y
+	bool
 
 config DMI
 	bool
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/acpi.c linux-libre-3.2-gnu1/arch/ia64/kernel/acpi.c
--- linux-libre-3.1-gnu1/arch/ia64/kernel/acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,7 @@ acpi_get_sysname(void)
 	struct acpi_table_rsdp *rsdp;
 	struct acpi_table_xsdt *xsdt;
 	struct acpi_table_header *hdr;
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	u64 i, nentries;
 #endif
 
@@ -125,7 +125,7 @@ acpi_get_sysname(void)
 		return "xen";
 	}
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	/* Look for Intel IOMMU */
 	nentries = (hdr->length - sizeof(*hdr)) /
 			 sizeof(xsdt->table_offset_entry[0]);
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/dma-mapping.c linux-libre-3.2-gnu1/arch/ia64/kernel/dma-mapping.c
--- linux-libre-3.1-gnu1/arch/ia64/kernel/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 /* Set this to 1 if there is a HW IOMMU in the system */
 int iommu_detected __read_mostly;
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/entry.S linux-libre-3.2-gnu1/arch/ia64/kernel/entry.S
--- linux-libre-3.1-gnu1/arch/ia64/kernel/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -1777,6 +1777,8 @@ sys_call_table:
 	data8 sys_syncfs
 	data8 sys_setns				// 1330
 	data8 sys_sendmmsg
+	data8 sys_process_vm_readv
+	data8 sys_process_vm_writev
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/Makefile linux-libre-3.2-gnu1/arch/ia64/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/ia64/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@ obj-$(CONFIG_IA64_ESI)		+= esi.o
 ifneq ($(CONFIG_IA64_ESI),)
 obj-y				+= esi_stub.o	# must be in kernel proper
 endif
-obj-$(CONFIG_DMAR)		+= pci-dma.o
+obj-$(CONFIG_INTEL_IOMMU)	+= pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= pci-swiotlb.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= elfcore.o
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/msi_ia64.c linux-libre-3.2-gnu1/arch/ia64/kernel/msi_ia64.c
--- linux-libre-3.1-gnu1/arch/ia64/kernel/msi_ia64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/msi_ia64.c	2012-01-04 18:55:44.000000000 -0500
@@ -131,7 +131,7 @@ void arch_teardown_msi_irq(unsigned int
 	return ia64_teardown_msi_irq(irq);
 }
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 #ifdef CONFIG_SMP
 static int dmar_msi_set_affinity(struct irq_data *data,
 				 const struct cpumask *mask, bool force)
@@ -210,5 +210,5 @@ int arch_setup_dmar_msi(unsigned int irq
 				      "edge");
 	return 0;
 }
-#endif /* CONFIG_DMAR */
+#endif /* CONFIG_INTEL_IOMMU */
 
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/pci-dma.c linux-libre-3.2-gnu1/arch/ia64/kernel/pci-dma.c
--- linux-libre-3.1-gnu1/arch/ia64/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <asm/system.h>
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 
 #include <linux/kernel.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kernel/topology.c linux-libre-3.2-gnu1/arch/ia64/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/ia64/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/nodemask.h>
 #include <linux/notifier.h>
+#include <linux/export.h>
 #include <asm/mmzone.h>
 #include <asm/numa.h>
 #include <asm/cpu.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/kvm/kvm-ia64.c linux-libre-3.2-gnu1/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-3.1-gnu1/arch/ia64/kvm/kvm-ia64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/kvm/kvm-ia64.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/uaccess.h>
 #include <linux/iommu.h>
 #include <linux/intel-iommu.h>
+#include <linux/pci.h>
 
 #include <asm/pgtable.h>
 #include <asm/gcc_intrin.h>
@@ -204,7 +205,7 @@ int kvm_dev_ioctl_check_extension(long e
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
 	case KVM_CAP_IOMMU:
-		r = iommu_found();
+		r = iommu_present(&pci_bus_type);
 		break;
 	default:
 		r = 0;
diff -druNp linux-libre-3.1-gnu1/arch/ia64/pci/pci.c linux-libre-3.2-gnu1/arch/ia64/pci/pci.c
--- linux-libre-3.1-gnu1/arch/ia64/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 
 #include <asm/machvec.h>
 #include <asm/page.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/kernel/io_acpi_init.c linux-libre-3.2-gnu1/arch/ia64/sn/kernel/io_acpi_init.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/kernel/io_acpi_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/kernel/io_acpi_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "xtalk/hubdev.h"
 #include <linux/acpi.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/kernel/io_init.c linux-libre-3.2-gnu1/arch/ia64/sn/kernel/io_init.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/kernel/io_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/kernel/io_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/kernel/sn2/sn_hwperf.c linux-libre-3.2-gnu1/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2012-01-04 18:55:44.000000000 -0500
@@ -615,11 +615,15 @@ static int sn_hwperf_op_cpu(struct sn_hw
 		}
 	}
 
-	if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
-		/* don't care, or already on correct cpu */
+	if (cpu == SN_HWPERF_ARG_ANY_CPU) {
+		/* don't care which cpu */
 		sn_hwperf_call_sal(op_info);
-	}
-	else {
+	} else if (cpu == get_cpu()) {
+		/* already on correct cpu */
+		sn_hwperf_call_sal(op_info);
+		put_cpu();
+	} else {
+		put_cpu();
 		if (use_ipi) {
 			/* use an interprocessor interrupt to call SAL */
 			smp_call_function_single(cpu, sn_hwperf_call_sal,
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/pci/pcibr/pcibr_dma.c linux-libre-3.2-gnu1/arch/ia64/sn/pci/pcibr/pcibr_dma.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/pcibr_provider.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-libre-3.2-gnu1/arch/ia64/sn/pci/pcibr/pcibr_provider.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/pcibr_provider.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/sn/pci/tioca_provider.c linux-libre-3.2-gnu1/arch/ia64/sn/pci/tioca_provider.c
--- linux-libre-3.1-gnu1/arch/ia64/sn/pci/tioca_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/sn/pci/tioca_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/ia64/xen/grant-table.c linux-libre-3.2-gnu1/arch/ia64/xen/grant-table.c
--- linux-libre-3.1-gnu1/arch/ia64/xen/grant-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/xen/grant-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,68 +31,6 @@
 
 #include <asm/xen/hypervisor.h>
 
-struct vm_struct *xen_alloc_vm_area(unsigned long size)
-{
-	int order;
-	unsigned long virt;
-	unsigned long nr_pages;
-	struct vm_struct *area;
-
-	order = get_order(size);
-	virt = __get_free_pages(GFP_KERNEL, order);
-	if (virt == 0)
-		goto err0;
-	nr_pages = 1 << order;
-	scrub_pages(virt, nr_pages);
-
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
-	if (area == NULL)
-		goto err1;
-
-	area->flags = VM_IOREMAP;
-	area->addr = (void *)virt;
-	area->size = size;
-	area->pages = NULL;
-	area->nr_pages = nr_pages;
-	area->phys_addr = 0;	/* xenbus_map_ring_valloc uses this field!  */
-
-	return area;
-
-err1:
-	free_pages(virt, order);
-err0:
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(xen_alloc_vm_area);
-
-void xen_free_vm_area(struct vm_struct *area)
-{
-	unsigned int order = get_order(area->size);
-	unsigned long i;
-	unsigned long phys_addr = __pa(area->addr);
-
-	/* This area is used for foreign page mappping.
-	 * So underlying machine page may not be assigned. */
-	for (i = 0; i < (1 << order); i++) {
-		unsigned long ret;
-		unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i;
-		struct xen_memory_reservation reservation = {
-			.nr_extents   = 1,
-			.address_bits = 0,
-			.extent_order = 0,
-			.domid        = DOMID_SELF
-		};
-		set_xen_guest_handle(reservation.extent_start, &gpfn);
-		ret = HYPERVISOR_memory_op(XENMEM_populate_physmap,
-					   &reservation);
-		BUG_ON(ret != 1);
-	}
-	free_pages((unsigned long)area->addr, order);
-	kfree(area);
-}
-EXPORT_SYMBOL_GPL(xen_free_vm_area);
-
-
 /****************************************************************************
  * grant table hack
  * cmd: GNTTABOP_xxx
diff -druNp linux-libre-3.1-gnu1/arch/ia64/xen/hypervisor.c linux-libre-3.2-gnu1/arch/ia64/xen/hypervisor.c
--- linux-libre-3.1-gnu1/arch/ia64/xen/hypervisor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/ia64/xen/hypervisor.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/privop.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/m32r/Kconfig linux-libre-3.2-gnu1/arch/m32r/Kconfig
--- linux-libre-3.1-gnu1/arch/m32r/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m32r/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@ config M32R
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
+	select GENERIC_ATOMIC64
 
 config SBUS
 	bool
@@ -322,13 +323,6 @@ config NODES_SHIFT
 	default "1"
 	depends on NEED_MULTIPLE_NODES
 
-# turning this on wastes a bunch of space.
-# Summit needs it only when NUMA is on
-config BOOT_IOREMAP
-	bool
-	depends on NUMA
-	default n
-
 endmenu
 
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/amiga/amiints.c linux-libre-3.2-gnu1/arch/m68k/amiga/amiints.c
--- linux-libre-3.1-gnu1/arch/m68k/amiga/amiints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/amiga/amiints.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,43 +1,15 @@
 /*
- * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ * Amiga Linux interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
- *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
- *           be careful that dev_id for this sources is unique since this the
- *           only possibility to distinguish between different handlers for
- *           free_irq. irq lists also have different irq flags:
- *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
- *                           fast handlers)
- *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
- *                           they're executed irq level is set to the previous
- *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occurred, slow handlers will be just
- *                           called again.
- *           The whole interrupt handling for CIAs is moved to cia.c
- *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with IRQF_DISABLED and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/irq.h>
 #include <asm/traps.h>
@@ -45,56 +17,6 @@
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
 
-static void amiga_enable_irq(unsigned int irq);
-static void amiga_disable_irq(unsigned int irq);
-static irqreturn_t ami_int1(int irq, void *dev_id);
-static irqreturn_t ami_int3(int irq, void *dev_id);
-static irqreturn_t ami_int4(int irq, void *dev_id);
-static irqreturn_t ami_int5(int irq, void *dev_id);
-
-static struct irq_controller amiga_irq_controller = {
-	.name		= "amiga",
-	.lock		= __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
-	.enable		= amiga_enable_irq,
-	.disable	= amiga_disable_irq,
-};
-
-/*
- * void amiga_init_IRQ(void)
- *
- * Parameters:	None
- *
- * Returns:	Nothing
- *
- * This function should be called during kernel startup to initialize
- * the amiga IRQ handling routines.
- */
-
-void __init amiga_init_IRQ(void)
-{
-	if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
-		pr_err("Couldn't register int%d\n", 1);
-	if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
-		pr_err("Couldn't register int%d\n", 3);
-	if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
-		pr_err("Couldn't register int%d\n", 4);
-	if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
-		pr_err("Couldn't register int%d\n", 5);
-
-	m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
-
-	/* turn off PCMCIA interrupts */
-	if (AMIGAHW_PRESENT(PCMCIA))
-		gayle.inten = GAYLE_IRQ_IDE;
-
-	/* turn off all interrupts and enable the master interrupt bit */
-	amiga_custom.intena = 0x7fff;
-	amiga_custom.intreq = 0x7fff;
-	amiga_custom.intena = IF_SETCLR | IF_INTEN;
-
-	cia_init_IRQ(&ciaa_base);
-	cia_init_IRQ(&ciab_base);
-}
 
 /*
  * Enable/disable a particular machine specific interrupt source.
@@ -103,112 +25,150 @@ void __init amiga_init_IRQ(void)
  * internal data, that may not be changed by the interrupt at the same time.
  */
 
-static void amiga_enable_irq(unsigned int irq)
+static void amiga_irq_enable(struct irq_data *data)
 {
-	amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
+	amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
 }
 
-static void amiga_disable_irq(unsigned int irq)
+static void amiga_irq_disable(struct irq_data *data)
 {
-	amiga_custom.intena = 1 << (irq - IRQ_USER);
+	amiga_custom.intena = 1 << (data->irq - IRQ_USER);
 }
 
+static struct irq_chip amiga_irq_chip = {
+	.name		= "amiga",
+	.irq_enable	= amiga_irq_enable,
+	.irq_disable	= amiga_irq_disable,
+};
+
+
 /*
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static irqreturn_t ami_int1(int irq, void *dev_id)
+static void ami_int1(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		amiga_custom.intreq = IF_TBE;
-		m68k_handle_int(IRQ_AMIGA_TBE);
+		generic_handle_irq(IRQ_AMIGA_TBE);
 	}
 
 	/* if floppy disk transfer complete, interrupt */
 	if (ints & IF_DSKBLK) {
 		amiga_custom.intreq = IF_DSKBLK;
-		m68k_handle_int(IRQ_AMIGA_DSKBLK);
+		generic_handle_irq(IRQ_AMIGA_DSKBLK);
 	}
 
 	/* if software interrupt set, interrupt */
 	if (ints & IF_SOFT) {
 		amiga_custom.intreq = IF_SOFT;
-		m68k_handle_int(IRQ_AMIGA_SOFT);
+		generic_handle_irq(IRQ_AMIGA_SOFT);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int3(int irq, void *dev_id)
+static void ami_int3(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		amiga_custom.intreq = IF_BLIT;
-		m68k_handle_int(IRQ_AMIGA_BLIT);
+		generic_handle_irq(IRQ_AMIGA_BLIT);
 	}
 
 	/* if a copper interrupt */
 	if (ints & IF_COPER) {
 		amiga_custom.intreq = IF_COPER;
-		m68k_handle_int(IRQ_AMIGA_COPPER);
+		generic_handle_irq(IRQ_AMIGA_COPPER);
 	}
 
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB) {
 		amiga_custom.intreq = IF_VERTB;
-		m68k_handle_int(IRQ_AMIGA_VERTB);
+		generic_handle_irq(IRQ_AMIGA_VERTB);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int4(int irq, void *dev_id)
+static void ami_int4(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		amiga_custom.intreq = IF_AUD0;
-		m68k_handle_int(IRQ_AMIGA_AUD0);
+		generic_handle_irq(IRQ_AMIGA_AUD0);
 	}
 
 	/* if audio 1 interrupt */
 	if (ints & IF_AUD1) {
 		amiga_custom.intreq = IF_AUD1;
-		m68k_handle_int(IRQ_AMIGA_AUD1);
+		generic_handle_irq(IRQ_AMIGA_AUD1);
 	}
 
 	/* if audio 2 interrupt */
 	if (ints & IF_AUD2) {
 		amiga_custom.intreq = IF_AUD2;
-		m68k_handle_int(IRQ_AMIGA_AUD2);
+		generic_handle_irq(IRQ_AMIGA_AUD2);
 	}
 
 	/* if audio 3 interrupt */
 	if (ints & IF_AUD3) {
 		amiga_custom.intreq = IF_AUD3;
-		m68k_handle_int(IRQ_AMIGA_AUD3);
+		generic_handle_irq(IRQ_AMIGA_AUD3);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int5(int irq, void *dev_id)
+static void ami_int5(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
-		m68k_handle_int(IRQ_AMIGA_RBF);
+		generic_handle_irq(IRQ_AMIGA_RBF);
 	}
 
 	/* if a disk sync interrupt */
 	if (ints & IF_DSKSYN) {
 		amiga_custom.intreq = IF_DSKSYN;
-		m68k_handle_int(IRQ_AMIGA_DSKSYN);
+		generic_handle_irq(IRQ_AMIGA_DSKSYN);
 	}
-	return IRQ_HANDLED;
+}
+
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters:	None
+ *
+ * Returns:	Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+void __init amiga_init_IRQ(void)
+{
+	m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
+				  AMI_STD_IRQS);
+
+	irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
+	irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
+	irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
+	irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
+
+	/* turn off PCMCIA interrupts */
+	if (AMIGAHW_PRESENT(PCMCIA))
+		gayle.inten = GAYLE_IRQ_IDE;
+
+	/* turn off all interrupts and enable the master interrupt bit */
+	amiga_custom.intena = 0x7fff;
+	amiga_custom.intreq = 0x7fff;
+	amiga_custom.intena = IF_SETCLR | IF_INTEN;
+
+	cia_init_IRQ(&ciaa_base);
+	cia_init_IRQ(&ciab_base);
 }
diff -druNp linux-libre-3.1-gnu1/arch/m68k/amiga/cia.c linux-libre-3.2-gnu1/arch/m68k/amiga/cia.c
--- linux-libre-3.1-gnu1/arch/m68k/amiga/cia.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/amiga/cia.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,13 +93,14 @@ static irqreturn_t cia_handler(int irq,
 	amiga_custom.intreq = base->int_mask;
 	for (; ints; mach_irq++, ints >>= 1) {
 		if (ints & 1)
-			m68k_handle_int(mach_irq);
+			generic_handle_irq(mach_irq);
 	}
 	return IRQ_HANDLED;
 }
 
-static void cia_enable_irq(unsigned int irq)
+static void cia_irq_enable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	unsigned char mask;
 
 	if (irq >= IRQ_AMIGA_CIAB) {
@@ -113,19 +114,20 @@ static void cia_enable_irq(unsigned int
 	}
 }
 
-static void cia_disable_irq(unsigned int irq)
+static void cia_irq_disable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq >= IRQ_AMIGA_CIAB)
 		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
 	else
 		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
 }
 
-static struct irq_controller cia_irq_controller = {
+static struct irq_chip cia_irq_chip = {
 	.name		= "cia",
-	.lock		= __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
-	.enable		= cia_enable_irq,
-	.disable	= cia_disable_irq,
+	.irq_enable	= cia_irq_enable,
+	.irq_disable	= cia_irq_disable,
 };
 
 /*
@@ -134,9 +136,9 @@ static struct irq_controller cia_irq_con
  * into this chain.
  */
 
-static void auto_enable_irq(unsigned int irq)
+static void auto_irq_enable(struct irq_data *data)
 {
-	switch (irq) {
+	switch (data->irq) {
 	case IRQ_AUTO_2:
 		amiga_custom.intena = IF_SETCLR | IF_PORTS;
 		break;
@@ -146,9 +148,9 @@ static void auto_enable_irq(unsigned int
 	}
 }
 
-static void auto_disable_irq(unsigned int irq)
+static void auto_irq_disable(struct irq_data *data)
 {
-	switch (irq) {
+	switch (data->irq) {
 	case IRQ_AUTO_2:
 		amiga_custom.intena = IF_PORTS;
 		break;
@@ -158,24 +160,25 @@ static void auto_disable_irq(unsigned in
 	}
 }
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
 	.name		= "auto",
-	.lock		= __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-	.enable		= auto_enable_irq,
-	.disable	= auto_disable_irq,
+	.irq_enable	= auto_irq_enable,
+	.irq_disable	= auto_irq_disable,
 };
 
 void __init cia_init_IRQ(struct ciabase *base)
 {
-	m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
+	m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq,
+				  base->cia_irq, CIA_IRQS);
 
 	/* clear any pending interrupt and turn off all interrupts */
 	cia_set_irq(base, CIA_ICR_ALL);
 	cia_able_irq(base, CIA_ICR_ALL);
 
 	/* override auto int and install CIA handler */
-	m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
-	m68k_irq_startup(base->handler_irq);
+	m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq,
+				  base->handler_irq, 1);
+	m68k_irq_startup_irq(base->handler_irq);
 	if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
 			base->name, base))
 		pr_err("Couldn't register %s interrupt\n", base->name);
diff -druNp linux-libre-3.1-gnu1/arch/m68k/apollo/dn_ints.c linux-libre-3.2-gnu1/arch/m68k/apollo/dn_ints.c
--- linux-libre-3.1-gnu1/arch/m68k/apollo/dn_ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/apollo/dn_ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,19 +1,13 @@
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/apollohw.h>
 
-void dn_process_int(unsigned int irq, struct pt_regs *fp)
+unsigned int apollo_irq_startup(struct irq_data *data)
 {
-	__m68k_handle_int(irq, fp);
-
-	*(volatile unsigned char *)(pica)=0x20;
-	*(volatile unsigned char *)(picb)=0x20;
-}
+	unsigned int irq = data->irq;
 
-int apollo_irq_startup(unsigned int irq)
-{
 	if (irq < 8)
 		*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
 	else
@@ -21,24 +15,33 @@ int apollo_irq_startup(unsigned int irq)
 	return 0;
 }
 
-void apollo_irq_shutdown(unsigned int irq)
+void apollo_irq_shutdown(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq < 8)
 		*(volatile unsigned char *)(pica+1) |= (1 << irq);
 	else
 		*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
 }
 
-static struct irq_controller apollo_irq_controller = {
+void apollo_irq_eoi(struct irq_data *data)
+{
+	*(volatile unsigned char *)(pica) = 0x20;
+	*(volatile unsigned char *)(picb) = 0x20;
+}
+
+static struct irq_chip apollo_irq_chip = {
 	.name           = "apollo",
-	.lock           = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
-	.startup        = apollo_irq_startup,
-	.shutdown       = apollo_irq_shutdown,
+	.irq_startup    = apollo_irq_startup,
+	.irq_shutdown   = apollo_irq_shutdown,
+	.irq_eoi	= apollo_irq_eoi,
 };
 
 
 void __init dn_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
-	m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
+	m68k_setup_user_interrupt(VEC_USER + 96, 16);
+	m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
+				  IRQ_APOLLO, 16);
 }
diff -druNp linux-libre-3.1-gnu1/arch/m68k/atari/ataints.c linux-libre-3.2-gnu1/arch/m68k/atari/ataints.c
--- linux-libre-3.1-gnu1/arch/m68k/atari/ataints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/atari/ataints.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,243 +60,7 @@
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  * be allocated by atari_register_vme_int().
- *
- * Each interrupt can be of three types:
- *
- *  - SLOW: The handler runs with all interrupts enabled, except the one it
- *    was called by (to avoid reentering). This should be the usual method.
- *    But it is currently possible only for MFP ints, since only the MFP
- *    offers an easy way to mask interrupts.
- *
- *  - FAST: The handler runs with all interrupts disabled. This should be used
- *    only for really fast handlers, that just do actions immediately
- *    necessary, and let the rest do a bottom half or task queue.
- *
- *  - PRIORITIZED: The handler can be interrupted by higher-level ints
- *    (greater IPL, no MFP priorities!). This is the method of choice for ints
- *    which should be slow, but are not from a MFP.
- *
- * The feature of more than one handler for one int source is still there, but
- * only applicable if all handers are of the same type. To not slow down
- * processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_irq_list() is only plugged in at the time the
- * second handler is registered.
- *
- * Implementation notes: For fast-as-possible int handling, there are separate
- * entry points for each type (slow/fast/prio). The assembler handler calls
- * the irq directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_irq_list() is registered as handler and calls
- * in turn the real irq's. To ease access from assembler level to the irq
- * function pointer and accompanying data, these two are stored in a separate
- * array, irq_handler[]. The rest of data (type, name) are put into a second
- * array, irq_param, that is accessed from C only. For each slow interrupt (32
- * in all) there are separate handler functions, which makes it possible to
- * hard-code the MFP register address and value, are necessary to mask the
- * int. If there'd be only one generic function, lots of calculations would be
- * needed to determine MFP register and int mask from the vector number :-(
- *
- * Furthermore, slow ints may not lower the IPL below its previous value
- * (before the int happened). This is needed so that an int of class PRIO, on
- * that this int may be stacked, cannot be reentered. This feature is
- * implemented as follows: If the stack frame format is 1 (throwaway), the int
- * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
- * 2, which still blocks the HSYNC, but no interrupts of interest. If the
- * frame format is 0, the int is nested, and the old IPL value can be found in
- * the sr copy in the frame.
- */
-
-#if 0
-
-#define	NUM_INT_SOURCES	(8 + NUM_ATARI_SOURCES)
-
-typedef void (*asm_irq_handler)(void);
-
-struct irqhandler {
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
-	void	*dev_id;
-};
-
-struct irqparam {
-	unsigned long	flags;
-	const char	*devname;
-};
-
-/*
- * Array with irq's and their parameter data. This array is accessed from low
- * level assembler code, so an element size of 8 allows usage of index scaling
- * addressing mode.
  */
-static struct irqhandler irq_handler[NUM_INT_SOURCES];
-
-/*
- * This array hold the rest of parameters of int handlers: type
- * (slow,fast,prio) and the name of the handler. These values are only
- * accessed from C
- */
-static struct irqparam irq_param[NUM_INT_SOURCES];
-
-/* check for valid int number (complex, sigh...) */
-#define	IS_VALID_INTNO(n)											\
-	((n) > 0 &&														\
-	 /* autovec and ST-MFP ok anyway */								\
-	 (((n) < TTMFP_SOURCE_BASE) ||									\
-	  /* TT-MFP ok if present */									\
-	  ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE &&			\
-	   ATARIHW_PRESENT(TT_MFP)) ||									\
-	  /* SCC ok if present and number even */						\
-	  ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE &&			\
-	   !((n) & 1) && ATARIHW_PRESENT(SCC)) ||						\
-	  /* greater numbers ok if they are registered VME vectors */		\
-	  ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
-		  free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
-
-
-/*
- * Here start the assembler entry points for interrupts
- */
-
-#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-
-#define	BUILD_SLOW_IRQ(n)						   \
-asmlinkage void IRQ_NAME(n);						   \
-/* Dummy function to allow asm with operands.  */			   \
-void atari_slow_irq_##n##_dummy (void) {				   \
-__asm__ (__ALIGN_STR "\n"						   \
-"atari_slow_irq_" #n "_handler:\t"					   \
-"	addl	%6,%5\n"	/* preempt_count() += HARDIRQ_OFFSET */	   \
-	SAVE_ALL_INT "\n"						   \
-	GET_CURRENT(%%d0) "\n"						   \
-"	andb	#~(1<<(%c3&7)),%a4:w\n"	/* mask this interrupt */	   \
-	/* get old IPL from stack frame */				   \
-"	bfextu	%%sp@(%c2){#5,#3},%%d0\n"				   \
-"	movew	%%sr,%%d1\n"						   \
-"	bfins	%%d0,%%d1{#21,#3}\n"					   \
-"	movew	%%d1,%%sr\n"		/* set IPL = previous value */	   \
-"	addql	#1,%a0\n"						   \
-"	lea	%a1,%%a0\n"						   \
-"	pea	%%sp@\n"		/* push addr of frame */	   \
-"	movel	%%a0@(4),%%sp@-\n"	/* push handler data */		   \
-"	pea	(%c3+8)\n"		/* push int number */		   \
-"	movel	%%a0@,%%a0\n"						   \
-"	jbsr	%%a0@\n"		/* call the handler */		   \
-"	addql	#8,%%sp\n"						   \
-"	addql	#4,%%sp\n"						   \
-"	orw	#0x0600,%%sr\n"						   \
-"	andw	#0xfeff,%%sr\n"		/* set IPL = 6 again */		   \
-"	orb	#(1<<(%c3&7)),%a4:w\n"	/* now unmask the int again */	   \
-"	jbra	ret_from_interrupt\n"					   \
-	 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),	   \
-	     "n" (PT_OFF_SR), "n" (n),					   \
-	     "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
-		        : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
-	     "m" (preempt_count()), "di" (HARDIRQ_OFFSET)		   \
-);									   \
-	for (;;);			/* fake noreturn */		   \
-}
-
-BUILD_SLOW_IRQ(0);
-BUILD_SLOW_IRQ(1);
-BUILD_SLOW_IRQ(2);
-BUILD_SLOW_IRQ(3);
-BUILD_SLOW_IRQ(4);
-BUILD_SLOW_IRQ(5);
-BUILD_SLOW_IRQ(6);
-BUILD_SLOW_IRQ(7);
-BUILD_SLOW_IRQ(8);
-BUILD_SLOW_IRQ(9);
-BUILD_SLOW_IRQ(10);
-BUILD_SLOW_IRQ(11);
-BUILD_SLOW_IRQ(12);
-BUILD_SLOW_IRQ(13);
-BUILD_SLOW_IRQ(14);
-BUILD_SLOW_IRQ(15);
-BUILD_SLOW_IRQ(16);
-BUILD_SLOW_IRQ(17);
-BUILD_SLOW_IRQ(18);
-BUILD_SLOW_IRQ(19);
-BUILD_SLOW_IRQ(20);
-BUILD_SLOW_IRQ(21);
-BUILD_SLOW_IRQ(22);
-BUILD_SLOW_IRQ(23);
-BUILD_SLOW_IRQ(24);
-BUILD_SLOW_IRQ(25);
-BUILD_SLOW_IRQ(26);
-BUILD_SLOW_IRQ(27);
-BUILD_SLOW_IRQ(28);
-BUILD_SLOW_IRQ(29);
-BUILD_SLOW_IRQ(30);
-BUILD_SLOW_IRQ(31);
-
-asm_irq_handler slow_handlers[32] = {
-	[0]	= atari_slow_irq_0_handler,
-	[1]	= atari_slow_irq_1_handler,
-	[2]	= atari_slow_irq_2_handler,
-	[3]	= atari_slow_irq_3_handler,
-	[4]	= atari_slow_irq_4_handler,
-	[5]	= atari_slow_irq_5_handler,
-	[6]	= atari_slow_irq_6_handler,
-	[7]	= atari_slow_irq_7_handler,
-	[8]	= atari_slow_irq_8_handler,
-	[9]	= atari_slow_irq_9_handler,
-	[10]	= atari_slow_irq_10_handler,
-	[11]	= atari_slow_irq_11_handler,
-	[12]	= atari_slow_irq_12_handler,
-	[13]	= atari_slow_irq_13_handler,
-	[14]	= atari_slow_irq_14_handler,
-	[15]	= atari_slow_irq_15_handler,
-	[16]	= atari_slow_irq_16_handler,
-	[17]	= atari_slow_irq_17_handler,
-	[18]	= atari_slow_irq_18_handler,
-	[19]	= atari_slow_irq_19_handler,
-	[20]	= atari_slow_irq_20_handler,
-	[21]	= atari_slow_irq_21_handler,
-	[22]	= atari_slow_irq_22_handler,
-	[23]	= atari_slow_irq_23_handler,
-	[24]	= atari_slow_irq_24_handler,
-	[25]	= atari_slow_irq_25_handler,
-	[26]	= atari_slow_irq_26_handler,
-	[27]	= atari_slow_irq_27_handler,
-	[28]	= atari_slow_irq_28_handler,
-	[29]	= atari_slow_irq_29_handler,
-	[30]	= atari_slow_irq_30_handler,
-	[31]	= atari_slow_irq_31_handler
-};
-
-asmlinkage void atari_fast_irq_handler( void );
-asmlinkage void atari_prio_irq_handler( void );
-
-/* Dummy function to allow asm with operands.  */
-void atari_fast_prio_irq_dummy (void) {
-__asm__ (__ALIGN_STR "\n"
-"atari_fast_irq_handler:\n\t"
-	"orw	#0x700,%%sr\n"		/* disable all interrupts */
-"atari_prio_irq_handler:\n\t"
-	"addl	%3,%2\n\t"		/* preempt_count() += HARDIRQ_OFFSET */
-	SAVE_ALL_INT "\n\t"
-	GET_CURRENT(%%d0) "\n\t"
-	/* get vector number from stack frame and convert to source */
-	"bfextu	%%sp@(%c1){#4,#10},%%d0\n\t"
-	"subw	#(0x40-8),%%d0\n\t"
-	"jpl	1f\n\t"
-	"addw	#(0x40-8-0x18),%%d0\n"
-    "1:\tlea	%a0,%%a0\n\t"
-	"addql	#1,%%a0@(%%d0:l:4)\n\t"
-	"lea	irq_handler,%%a0\n\t"
-	"lea	%%a0@(%%d0:l:8),%%a0\n\t"
-	"pea	%%sp@\n\t"		/* push frame address */
-	"movel	%%a0@(4),%%sp@-\n\t"	/* push handler data */
-	"movel	%%d0,%%sp@-\n\t"	/* push int number */
-	"movel	%%a0@,%%a0\n\t"
-	"jsr	%%a0@\n\t"		/* and call the handler */
-	"addql	#8,%%sp\n\t"
-	"addql	#4,%%sp\n\t"
-	"jbra	ret_from_interrupt"
-	 : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
-	     "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
-);
-	for (;;);
-}
-#endif
 
 /*
  * Bitmap for free interrupt vector numbers
@@ -320,31 +84,44 @@ extern void atari_microwire_cmd(int cmd)
 
 extern int atari_SCC_reset_done;
 
-static int atari_startup_irq(unsigned int irq)
+static unsigned int atari_irq_startup(struct irq_data *data)
 {
-	m68k_irq_startup(irq);
+	unsigned int irq = data->irq;
+
+	m68k_irq_startup(data);
 	atari_turnon_irq(irq);
 	atari_enable_irq(irq);
 	return 0;
 }
 
-static void atari_shutdown_irq(unsigned int irq)
+static void atari_irq_shutdown(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	atari_disable_irq(irq);
 	atari_turnoff_irq(irq);
-	m68k_irq_shutdown(irq);
+	m68k_irq_shutdown(data);
 
 	if (irq == IRQ_AUTO_4)
 	    vectors[VEC_INT4] = falcon_hblhandler;
 }
 
-static struct irq_controller atari_irq_controller = {
+static void atari_irq_enable(struct irq_data *data)
+{
+	atari_enable_irq(data->irq);
+}
+
+static void atari_irq_disable(struct irq_data *data)
+{
+	atari_disable_irq(data->irq);
+}
+
+static struct irq_chip atari_irq_chip = {
 	.name		= "atari",
-	.lock		= __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
-	.startup	= atari_startup_irq,
-	.shutdown	= atari_shutdown_irq,
-	.enable		= atari_enable_irq,
-	.disable	= atari_disable_irq,
+	.irq_startup	= atari_irq_startup,
+	.irq_shutdown	= atari_irq_shutdown,
+	.irq_enable	= atari_irq_enable,
+	.irq_disable	= atari_irq_disable,
 };
 
 /*
@@ -360,8 +137,9 @@ static struct irq_controller atari_irq_c
 
 void __init atari_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
-	m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
+	m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
+	m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
+				  NUM_ATARI_SOURCES - 1);
 
 	/* Initialize the MFP(s) */
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/atari/time.c linux-libre-3.2-gnu1/arch/m68k/atari/time.c
--- linux-libre-3.1-gnu1/arch/m68k/atari/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/atari/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/atariints.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/bvme6000/config.c linux-libre-3.2-gnu1/arch/m68k/bvme6000/config.c
--- linux-libre-3.1-gnu1/arch/m68k/bvme6000/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/bvme6000/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@ static void bvme6000_get_model(char *mod
  */
 static void __init bvme6000_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_bvme6000(void)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/emu/nfblock.c linux-libre-3.2-gnu1/arch/m68k/emu/nfblock.c
--- linux-libre-3.1-gnu1/arch/m68k/emu/nfblock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/emu/nfblock.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,7 +59,7 @@ struct nfhd_device {
 	struct gendisk *disk;
 };
 
-static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
+static void nfhd_make_request(struct request_queue *queue, struct bio *bio)
 {
 	struct nfhd_device *dev = queue->queuedata;
 	struct bio_vec *bvec;
@@ -76,7 +76,6 @@ static int nfhd_make_request(struct requ
 		sec += len;
 	}
 	bio_endio(bio, 0);
-	return 0;
 }
 
 static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/hp300/time.c linux-libre-3.2-gnu1/arch/m68k/hp300/time.c
--- linux-libre-3.1-gnu1/arch/m68k/hp300/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/hp300/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/entry.h linux-libre-3.2-gnu1/arch/m68k/include/asm/entry.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,254 @@
-#ifdef __uClinux__
-#include "entry_no.h"
+#ifndef __M68K_ENTRY_H
+#define __M68K_ENTRY_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
+
+/*
+ * Stack layout in 'ret_from_exception':
+ *
+ *	This allows access to the syscall arguments in registers d1-d5
+ *
+ *	 0(sp) - d1
+ *	 4(sp) - d2
+ *	 8(sp) - d3
+ *	 C(sp) - d4
+ *	10(sp) - d5
+ *	14(sp) - a0
+ *	18(sp) - a1
+ *	1C(sp) - a2
+ *	20(sp) - d0
+ *	24(sp) - orig_d0
+ *	28(sp) - stack adjustment
+ *	2C(sp) - [ sr              ] [ format & vector ]
+ *	2E(sp) - [ pc-hiword       ] [ sr              ]
+ *	30(sp) - [ pc-loword       ] [ pc-hiword       ]
+ *	32(sp) - [ format & vector ] [ pc-loword       ]
+ *		  ^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^
+ *			M68K		  COLDFIRE
+ */
+
+/* the following macro is used when enabling interrupts */
+#if defined(MACH_ATARI_ONLY)
+	/* block out HSYNC on the atari */
+#define ALLOWINT	(~0x400)
+#define	MAX_NOINT_IPL	3
 #else
-#include "entry_mm.h"
+	/* portable version */
+#define ALLOWINT	(~0x700)
+#define	MAX_NOINT_IPL	0
+#endif /* machine compilation types */
+
+#ifdef __ASSEMBLY__
+/*
+ * This defines the normal kernel pt-regs layout.
+ *
+ * regs a3-a6 and d6-d7 are preserved by C code
+ * the kernel doesn't mess with usp unless it needs to
+ */
+#define SWITCH_STACK_SIZE	(6*4+4)	/* includes return address */
+
+#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ * This is made a little more tricky on older ColdFires. There is no
+ * separate supervisor and user stack pointers. Need to artificially
+ * construct a usp in software... When doing this we need to disable
+ * interrupts, otherwise bad things will happen.
+ */
+.globl sw_usp
+.globl sw_ksp
+
+.macro SAVE_ALL_SYS
+	move	#0x2700,%sr		/* disable intrs */
+	btst	#5,%sp@(2)		/* from user? */
+	bnes	6f			/* no, skip */
+	movel	%sp,sw_usp		/* save user sp */
+	addql	#8,sw_usp		/* remove exception */
+	movel	sw_ksp,%sp		/* kernel sp */
+	subql	#8,%sp			/* room for exception */
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+	movel	sw_usp,%a0		/* get usp */
+	movel	%a0@-,%sp@(PT_OFF_PC)	/* copy exception program counter */
+	movel	%a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
+	bra	7f
+	6:
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+	7:
+.endm
+
+.macro SAVE_ALL_INT
+	SAVE_ALL_SYS
+	moveq	#-1,%d0			/* not system call entry */
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+.endm
+
+.macro RESTORE_USER
+	move	#0x2700,%sr		/* disable intrs */
+	movel	sw_usp,%a0		/* get usp */
+	movel	%sp@(PT_OFF_PC),%a0@-	/* copy exception program counter */
+	movel	%sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
+	moveml	%sp@,%d1-%d5/%a0-%a2
+	lea	%sp@(32),%sp		/* space for 8 regs */
+	movel	%sp@+,%d0
+	addql	#4,%sp			/* orig d0 */
+	addl	%sp@+,%sp		/* stkadj */
+	addql	#8,%sp			/* remove exception */
+	movel	%sp,sw_ksp		/* save ksp */
+	subql	#8,sw_usp		/* set exception */
+	movel	sw_usp,%sp		/* restore usp */
+	rte
+.endm
+
+.macro RDUSP
+	movel	sw_usp,%a3
+.endm
+
+.macro WRUSP
+	movel	%a3,sw_usp
+.endm
+
+#else /* !CONFIG_COLDFIRE_SW_A7 */
+/*
+ * Modern ColdFire parts have separate supervisor and user stack
+ * pointers. Simple load and restore macros for this case.
+ */
+.macro SAVE_ALL_SYS
+	move	#0x2700,%sr		/* disable intrs */
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro SAVE_ALL_INT
+	move	#0x2700,%sr		/* disable intrs */
+	clrl	%sp@-			/* stkadj */
+	pea	-1:w			/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro RESTORE_USER
+	moveml	%sp@,%d1-%d5/%a0-%a2
+	lea	%sp@(32),%sp		/* space for 8 regs */
+	movel	%sp@+,%d0
+	addql	#4,%sp			/* orig d0 */
+	addl	%sp@+,%sp		/* stkadj */
+	rte
+.endm
+
+.macro RDUSP
+	/*move	%usp,%a3*/
+	.word	0x4e6b
+.endm
+
+.macro WRUSP
+	/*move	%a3,%usp*/
+	.word	0x4e63
+.endm
+
+#endif /* !CONFIG_COLDFIRE_SW_A7 */
+
+.macro SAVE_SWITCH_STACK
+	lea	%sp@(-24),%sp		/* 6 regs */
+	moveml	%a3-%a6/%d6-%d7,%sp@
+.endm
+
+.macro RESTORE_SWITCH_STACK
+	moveml	%sp@,%a3-%a6/%d6-%d7
+	lea	%sp@(24),%sp		/* 6 regs */
+.endm
+
+#else /* !CONFIG_COLDFIRE */
+
+/*
+ * All other types of m68k parts (68000, 680x0, CPU32) have the same
+ * entry and exit code.
+ */
+
+/*
+ * a -1 in the orig_d0 field signifies
+ * that the stack frame is NOT for syscall
+ */
+.macro SAVE_ALL_INT
+	clrl	%sp@-			/* stk_adj */
+	pea	-1:w			/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	moveml	%d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro SAVE_ALL_SYS
+	clrl	%sp@-			/* stk_adj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	moveml	%d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro RESTORE_ALL
+	moveml	%sp@+,%a0-%a2/%d1-%d5
+	movel	%sp@+,%d0
+	addql	#4,%sp			/* orig d0 */
+	addl	%sp@+,%sp		/* stk adj */
+	rte
+.endm
+
+
+.macro SAVE_SWITCH_STACK
+	moveml	%a3-%a6/%d6-%d7,%sp@-
+.endm
+
+.macro RESTORE_SWITCH_STACK
+	moveml	%sp@+,%a3-%a6/%d6-%d7
+.endm
+
+#endif /* !CONFIG_COLDFIRE */
+
+/*
+ * Register %a2 is reserved and set to current task on MMU enabled systems.
+ * Non-MMU systems do not reserve %a2 in this way, and this definition is
+ * not used for them.
+ */
+#define curptr a2
+
+#define GET_CURRENT(tmp) get_current tmp
+.macro get_current reg=%d0
+	movel	%sp,\reg
+	andw	#-THREAD_SIZE,\reg
+	movel	\reg,%curptr
+	movel	%curptr@,%curptr
+.endm
+
+#else /* C source */
+
+#define STR(X) STR1(X)
+#define STR1(X) #X
+
+#define SAVE_ALL_INT				\
+	"clrl	%%sp@-;"    /* stk_adj */	\
+	"pea	-1:w;"	    /* orig d0 = -1 */	\
+	"movel	%%d0,%%sp@-;" /* d0 */		\
+	"moveml	%%d1-%%d5/%%a0-%%a2,%%sp@-"
+
+#define GET_CURRENT(tmp) \
+	"movel	%%sp,"#tmp"\n\t" \
+	"andw	#-"STR(THREAD_SIZE)","#tmp"\n\t" \
+	"movel	"#tmp",%%a2\n\t" \
+	"movel	%%a2@,%%a2"
+
 #endif
+
+#endif /* __M68K_ENTRY_H */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/entry_mm.h linux-libre-3.2-gnu1/arch/m68k/include/asm/entry_mm.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/entry_mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/entry_mm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-#ifndef __M68K_ENTRY_H
-#define __M68K_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#ifdef __ASSEMBLY__
-#include <asm/thread_info.h>
-#endif
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- *	This allows access to the syscall arguments in registers d1-d5
- *
- *	 0(sp) - d1
- *	 4(sp) - d2
- *	 8(sp) - d3
- *	 C(sp) - d4
- *	10(sp) - d5
- *	14(sp) - a0
- *	18(sp) - a1
- *	1C(sp) - a2
- *	20(sp) - d0
- *	24(sp) - orig_d0
- *	28(sp) - stack adjustment
- *	2C(sp) - sr
- *	2E(sp) - pc
- *	32(sp) - format & vector
- */
-
-/*
- * 97/05/14 Andreas: Register %a2 is now set to the current task throughout
- *		     the whole kernel.
- */
-
-/* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY)
-	/* block out HSYNC on the atari */
-#define ALLOWINT	(~0x400)
-#define	MAX_NOINT_IPL	3
-#else
-	/* portable version */
-#define ALLOWINT	(~0x700)
-#define	MAX_NOINT_IPL	0
-#endif /* machine compilation types */
-
-#ifdef __ASSEMBLY__
-
-#define curptr a2
-
-LFLUSH_I_AND_D = 0x00000808
-
-#define SAVE_ALL_INT save_all_int
-#define SAVE_ALL_SYS save_all_sys
-#define RESTORE_ALL restore_all
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs a3-a6 and d6-d7 are preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-/*
- * a -1 in the orig_d0 field signifies
- * that the stack frame is NOT for syscall
- */
-.macro	save_all_int
-	clrl	%sp@-		| stk_adj
-	pea	-1:w		| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro	save_all_sys
-	clrl	%sp@-		| stk_adj
-	movel	%d0,%sp@-	| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro	restore_all
-	moveml	%sp@+,%a0-%a1/%curptr/%d1-%d5
-	movel	%sp@+,%d0
-	addql	#4,%sp		| orig d0
-	addl	%sp@+,%sp	| stk adj
-	rte
-.endm
-
-#define SWITCH_STACK_SIZE (6*4+4)	/* includes return address */
-
-#define SAVE_SWITCH_STACK save_switch_stack
-#define RESTORE_SWITCH_STACK restore_switch_stack
-#define GET_CURRENT(tmp) get_current tmp
-
-.macro	save_switch_stack
-	moveml	%a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro	restore_switch_stack
-	moveml	%sp@+,%a3-%a6/%d6-%d7
-.endm
-
-.macro	get_current reg=%d0
-	movel	%sp,\reg
-	andw	#-THREAD_SIZE,\reg
-	movel	\reg,%curptr
-	movel	%curptr@,%curptr
-.endm
-
-#else /* C source */
-
-#define STR(X) STR1(X)
-#define STR1(X) #X
-
-#define SAVE_ALL_INT				\
-	"clrl	%%sp@-;"    /* stk_adj */	\
-	"pea	-1:w;"	    /* orig d0 = -1 */	\
-	"movel	%%d0,%%sp@-;" /* d0 */		\
-	"moveml	%%d1-%%d5/%%a0-%%a2,%%sp@-"
-#define GET_CURRENT(tmp) \
-	"movel	%%sp,"#tmp"\n\t" \
-	"andw	#-"STR(THREAD_SIZE)","#tmp"\n\t" \
-	"movel	"#tmp",%%a2\n\t" \
-	"movel	%%a2@,%%a2"
-
-#endif
-
-#endif /* __M68K_ENTRY_H */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/entry_no.h linux-libre-3.2-gnu1/arch/m68k/include/asm/entry_no.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/entry_no.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/entry_no.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,181 +0,0 @@
-#ifndef __M68KNOMMU_ENTRY_H
-#define __M68KNOMMU_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- * This allows access to the syscall arguments in registers d1-d5
- *
- *	 0(sp) - d1
- *	 4(sp) - d2
- *	 8(sp) - d3
- *	 C(sp) - d4
- *	10(sp) - d5
- *	14(sp) - a0
- *	18(sp) - a1
- *	1C(sp) - a2
- *	20(sp) - d0
- *	24(sp) - orig_d0
- *	28(sp) - stack adjustment
- *	2C(sp) - [ sr              ] [ format & vector ]
- *	2E(sp) - [ pc-hiword       ] [ sr              ]
- *	30(sp) - [ pc-loword       ] [ pc-hiword       ]
- *	32(sp) - [ format & vector ] [ pc-loword       ]
- *		  ^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^
- *			M68K		  COLDFIRE
- */
-
-#define ALLOWINT (~0x700)
-
-#ifdef __ASSEMBLY__
-
-#define SWITCH_STACK_SIZE (6*4+4)	/* Includes return address */
-
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs are a2-a6 and d6-d7 preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-#ifdef CONFIG_COLDFIRE
-#ifdef CONFIG_COLDFIRE_SW_A7
-/*
- * This is made a little more tricky on older ColdFires. There is no
- * separate supervisor and user stack pointers. Need to artificially
- * construct a usp in software... When doing this we need to disable
- * interrupts, otherwise bad things will happen.
- */
-.globl sw_usp
-.globl sw_ksp
-
-.macro SAVE_ALL
-	move	#0x2700,%sr		/* disable intrs */
-	btst	#5,%sp@(2)		/* from user? */
-	bnes	6f			/* no, skip */
-	movel	%sp,sw_usp		/* save user sp */
-	addql	#8,sw_usp		/* remove exception */
-	movel	sw_ksp,%sp		/* kernel sp */
-	subql	#8,%sp			/* room for exception */
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-	movel	sw_usp,%a0		/* get usp */
-	movel	%a0@-,%sp@(PT_OFF_PC)	/* copy exception program counter */
-	movel	%a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
-	bra	7f
-	6:
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-	7:
-.endm
-
-.macro RESTORE_USER
-	move	#0x2700,%sr		/* disable intrs */
-	movel	sw_usp,%a0		/* get usp */
-	movel	%sp@(PT_OFF_PC),%a0@-	/* copy exception program counter */
-	movel	%sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
-	moveml	%sp@,%d1-%d5/%a0-%a2
-	lea	%sp@(32),%sp		/* space for 8 regs */
-	movel	%sp@+,%d0
-	addql	#4,%sp			/* orig d0 */
-	addl	%sp@+,%sp		/* stkadj */
-	addql	#8,%sp			/* remove exception */
-	movel	%sp,sw_ksp		/* save ksp */
-	subql	#8,sw_usp		/* set exception */
-	movel	sw_usp,%sp		/* restore usp */
-	rte
-.endm
-
-.macro RDUSP
-	movel	sw_usp,%a3
-.endm
-
-.macro WRUSP
-	movel	%a3,sw_usp
-.endm
-
-#else /* !CONFIG_COLDFIRE_SW_A7 */
-/*
- * Modern ColdFire parts have separate supervisor and user stack
- * pointers. Simple load and restore macros for this case.
- */
-.macro SAVE_ALL
-	move	#0x2700,%sr		/* disable intrs */
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-.endm
-
-.macro RESTORE_USER
-	moveml	%sp@,%d1-%d5/%a0-%a2
-	lea	%sp@(32),%sp		/* space for 8 regs */
-	movel	%sp@+,%d0
-	addql	#4,%sp			/* orig d0 */
-	addl	%sp@+,%sp		/* stkadj */
-	rte
-.endm
-
-.macro RDUSP
-	/*move	%usp,%a3*/
-	.word	0x4e6b
-.endm
-
-.macro WRUSP
-	/*move	%a3,%usp*/
-	.word	0x4e63
-.endm
-
-#endif /* !CONFIG_COLDFIRE_SW_A7 */
-
-.macro SAVE_SWITCH_STACK
-	lea	%sp@(-24),%sp		/* 6 regs */
-	moveml	%a3-%a6/%d6-%d7,%sp@
-.endm
-
-.macro RESTORE_SWITCH_STACK
-	moveml	%sp@,%a3-%a6/%d6-%d7
-	lea	%sp@(24),%sp		/* 6 regs */
-.endm
-
-#else /* !CONFIG_COLDFIRE */
-
-/*
- * Standard 68k interrupt entry and exit macros.
- */
-.macro SAVE_ALL
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	moveml	%d1-%d5/%a0-%a2,%sp@-
-.endm
-
-.macro RESTORE_ALL
-	moveml	%sp@+,%a0-%a2/%d1-%d5
-	movel	%sp@+,%d0
-	addql	#4,%sp			/* orig d0 */
-	addl	%sp@+,%sp		/* stkadj */
-	rte
-.endm
-
-.macro SAVE_SWITCH_STACK
-	moveml	%a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro RESTORE_SWITCH_STACK
-	moveml	%sp@+,%a3-%a6/%d6-%d7
-.endm
-
-#endif /* !COLDFIRE_SW_A7 */
-#endif /* __ASSEMBLY__ */
-#endif /* __M68KNOMMU_ENTRY_H */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/hardirq.h linux-libre-3.2-gnu1/arch/m68k/include/asm/hardirq.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/hardirq.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,11 @@
 
 #ifdef CONFIG_MMU
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+	pr_crit("unexpected IRQ trap at vector %02x\n", irq);
+}
+
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
 	unsigned int __softirq_pending;
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/irq.h linux-libre-3.2-gnu1/arch/m68k/include/asm/irq.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,11 +27,6 @@
 
 #ifdef CONFIG_MMU
 
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
 /*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
@@ -54,10 +49,6 @@
 
 #define IRQ_USER	8
 
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - IRQF_DISABLED and
@@ -71,57 +62,27 @@ struct pt_regs;
 #define IRQ_FLG_STD	(0x8000)	/* internally used		*/
 #endif
 
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
-	irqreturn_t	(*handler)(int, void *);
-	void		*dev_id;
-	struct irq_node *next;
-	unsigned long	flags;
-	const char	*devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
-	int		(*handler)(int, void *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-};
-
-struct irq_controller {
-	const char *name;
-	spinlock_t lock;
-	int (*startup)(unsigned int irq);
-	void (*shutdown)(unsigned int irq);
-	void (*enable)(unsigned int irq);
-	void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
-
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-				      void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
+struct irq_data;
+struct irq_chip;
+struct irq_desc;
+extern unsigned int m68k_irq_startup(struct irq_data *data);
+extern unsigned int m68k_irq_startup_irq(unsigned int irq);
+extern void m68k_irq_shutdown(struct irq_data *data);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
+						      struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
+extern void m68k_setup_irq_controller(struct irq_chip *,
+				      void (*handle)(unsigned int irq,
+						     struct irq_desc *desc),
+				      unsigned int irq, unsigned int cnt);
 
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+extern unsigned int irq_canonicalize(unsigned int irq);
 
 #else
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern atomic_t irq_err_count;
 
 #endif /* _M68K_IRQ_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/m520xsim.h linux-libre-3.2-gnu1/arch/m68k/include/asm/m520xsim.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/m520xsim.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/m520xsim.h	2012-01-04 18:55:44.000000000 -0500
@@ -90,15 +90,13 @@
 #define MCFGPIO_PDDR_FECH		0xFC0A4013
 #define MCFGPIO_PDDR_FECL		0xFC0A4014
 
-#define MCFGPIO_PPDSDR_BUSCTL		0xFC0A401A
-#define MCFGPIO_PPDSDR_BE		0xFC0A401B
-#define MCFGPIO_PPDSDR_CS		0xFC0A401C
-#define MCFGPIO_PPDSDR_FECI2C		0xFC0A401D
-#define MCFGPIO_PPDSDR_QSPI		0xFC0A401E
-#define MCFGPIO_PPDSDR_TIMER		0xFC0A401F
-#define MCFGPIO_PPDSDR_UART		0xFC0A4021
-#define MCFGPIO_PPDSDR_FECH		0xFC0A4021
-#define MCFGPIO_PPDSDR_FECL		0xFC0A4022
+#define MCFGPIO_PPDSDR_CS		0xFC0A401A
+#define MCFGPIO_PPDSDR_FECI2C		0xFC0A401B
+#define MCFGPIO_PPDSDR_QSPI		0xFC0A401C
+#define MCFGPIO_PPDSDR_TIMER		0xFC0A401D
+#define MCFGPIO_PPDSDR_UART		0xFC0A401E
+#define MCFGPIO_PPDSDR_FECH		0xFC0A401F
+#define MCFGPIO_PPDSDR_FECL		0xFC0A4020
 
 #define MCFGPIO_PCLRR_BUSCTL		0xFC0A4024
 #define MCFGPIO_PCLRR_BE		0xFC0A4025
@@ -113,11 +111,11 @@
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PODR			MCFGPIO_PODR_BUSCTL
-#define MCFGPIO_PDDR			MCFGPIO_PDDR_BUSCTL
-#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_SETR			MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_CLRR			MCFGPIO_PCLRR_BUSCTL
+#define MCFGPIO_PODR			MCFGPIO_PODR_CS
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_CS
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_CS
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_CS
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_CS
 
 #define MCFGPIO_PIN_MAX			80
 #define MCFGPIO_IRQ_MAX			8
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/macintosh.h linux-libre-3.2-gnu1/arch/m68k/include/asm/macintosh.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/macintosh.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/macintosh.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,8 @@ extern void mac_reset(void);
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
 extern int mac_irq_pending(unsigned int);
+extern void mac_irq_enable(struct irq_data *data);
+extern void mac_irq_disable(struct irq_data *data);
 
 /*
  *	Floppy driver magic hook - probably shouldn't be here
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/mcfqspi.h linux-libre-3.2-gnu1/arch/m68k/include/asm/mcfqspi.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/mcfqspi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/mcfqspi.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,9 +24,11 @@
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define	MCFQSPI_IOBASE		(MCF_IPSBAR + 0x340)
 #elif defined(CONFIG_M5249)
-#define MCFQSPI_IOBASE		(MCF_MBAR + 0x300)
-#elif defined(CONFIG_M520x) || defined(CONFIG_M532x)
-#define MCFQSPI_IOBASE		0xFC058000
+#define MCFQSPI_IOBASE         (MCF_MBAR + 0x300)
+#elif defined(CONFIG_M520x)
+#define MCFQSPI_IOBASE         0xFC05C000
+#elif defined(CONFIG_M532x)
+#define MCFQSPI_IOBASE         0xFC058000
 #endif
 #define MCFQSPI_IOSIZE		0x40
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/page_no.h linux-libre-3.2-gnu1/arch/m68k/include/asm/page_no.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/page_no.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/page_no.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,9 @@
  
 extern unsigned long memory_start;
 extern unsigned long memory_end;
+extern unsigned long _rambase;
+extern unsigned long _ramstart;
+extern unsigned long _ramend;
 
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/processor.h linux-libre-3.2-gnu1/arch/m68k/include/asm/processor.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -135,6 +135,12 @@ do {
 	wrusp(_usp);                                    \
 } while(0)
 
+static inline  int handle_kernel_fault(struct pt_regs *regs)
+{
+	/* Any fault in kernel is fatal on non-mmu */
+	return 0;
+}
+
 #endif
 
 /* Forward declaration, a strange C thing */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/q40ints.h linux-libre-3.2-gnu1/arch/m68k/include/asm/q40ints.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/q40ints.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/q40ints.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,3 @@
 #define Q40_IRQ10_MASK       (1<<5)
 #define Q40_IRQ14_MASK       (1<<6)
 #define Q40_IRQ15_MASK       (1<<7)
-
-extern unsigned long q40_probe_irq_on (void);
-extern int q40_probe_irq_off (unsigned long irqs);
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/sections.h linux-libre-3.2-gnu1/arch/m68k/include/asm/sections.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/sections.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,6 @@
 
 #include <asm-generic/sections.h>
 
+extern char _sbss[], _ebss[];
+
 #endif /* _ASM_M68K_SECTIONS_H */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/include/asm/unistd.h linux-libre-3.2-gnu1/arch/m68k/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/m68k/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -350,10 +350,12 @@
 #define __NR_clock_adjtime	342
 #define __NR_syncfs		343
 #define __NR_setns		344
+#define __NR_process_vm_readv	345
+#define __NR_process_vm_writev	346
 
 #ifdef __KERNEL__
 
-#define NR_syscalls		345
+#define NR_syscalls		347
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig linux-libre-3.2-gnu1/arch/m68k/Kconfig
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@ config M68K
 	select HAVE_IDE
 	select HAVE_AOUT if MMU
 	select GENERIC_ATOMIC64 if MMU
-	select HAVE_GENERIC_HARDIRQS if !MMU
-	select GENERIC_IRQ_SHOW if !MMU
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 
 config RWSEM_GENERIC_SPINLOCK
@@ -21,6 +21,15 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
 	bool
 
+config GENERIC_CLOCKEVENTS
+	bool
+
+config GENERIC_CMOS_UPDATE
+	def_bool !MMU
+
+config GENERIC_GPIO
+	bool
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -29,10 +38,16 @@ config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
 
+config GENERIC_IOMAP
+	def_bool MMU
+
 config TIME_LOW_RES
 	bool
 	default y
 
+config ARCH_USES_GETTIMEOFFSET
+	def_bool MMU
+
 config NO_IOPORT
 	def_bool y
 
@@ -62,13 +77,31 @@ config MMU
 	  Select if you want MMU-based virtualised addressing space
 	  support by paged memory management. If unsure, say 'Y'.
 
-menu "Platform dependent setup"
+config MMU_MOTOROLA
+	bool
 
-if MMU
-source arch/m68k/Kconfig.mmu
+config MMU_SUN3
+	bool
+	depends on MMU && !MMU_MOTOROLA
+
+menu "Platform setup"
+
+source arch/m68k/Kconfig.cpu
+
+source arch/m68k/Kconfig.machine
+
+source arch/m68k/Kconfig.bus
+
+endmenu
+
+menu "Kernel Features"
+
+if COLDFIRE
+source "kernel/Kconfig.preempt"
 endif
-if !MMU
-source arch/m68k/Kconfig.nommu
+
+if !MMU || COLDFIRE
+source "kernel/time/Kconfig"
 endif
 
 source "mm/Kconfig"
@@ -85,9 +118,9 @@ if !MMU
 menu "Power management options"
 
 config PM
-        bool "Power Management support"
-        help
-          Support processor power management modes
+	bool "Power Management support"
+	help
+	  Support processor power management modes
 
 endmenu
 endif
@@ -96,151 +129,7 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
-if MMU
-
-menu "Character devices"
-
-config ATARI_MFPSER
-	tristate "Atari MFP serial support"
-	depends on ATARI
-	---help---
-	  If you like to use the MFP serial ports ("Modem1", "Serial1") under
-	  Linux, say Y. The driver equally supports all kinds of MFP serial
-	  ports and automatically detects whether Serial1 is available.
-
-	  To compile this driver as a module, choose M here.
-
-	  Note for Falcon users: You also have an MFP port, it's just not
-	  wired to the outside... But you could use the port under Linux.
-
-config ATARI_MIDI
-	tristate "Atari MIDI serial support"
-	depends on ATARI
-	help
-	  If you want to use your Atari's MIDI port in Linux, say Y.
-
-	  To compile this driver as a module, choose M here.
-
-config ATARI_DSP56K
-	tristate "Atari DSP56k support (EXPERIMENTAL)"
-	depends on ATARI && EXPERIMENTAL
-	help
-	  If you want to be able to use the DSP56001 in Falcons, say Y. This
-	  driver is still experimental, and if you don't know what it is, or
-	  if you don't have this processor, just say N.
-
-	  To compile this driver as a module, choose M here.
-
-config AMIGA_BUILTIN_SERIAL
-	tristate "Amiga builtin serial support"
-	depends on AMIGA
-	help
-	  If you want to use your Amiga's built-in serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config MULTIFACE_III_TTY
-	tristate "Multiface Card III serial support"
-	depends on AMIGA
-	help
-	  If you want to use a Multiface III card's serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config GVPIOEXT
-	tristate "GVP IO-Extender support"
-	depends on PARPORT=n && ZORRO
-	help
-	  If you want to use a GVP IO-Extender serial card in Linux, say Y.
-	  Otherwise, say N.
-
-config GVPIOEXT_LP
-	tristate "GVP IO-Extender parallel printer support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable driving a printer from the parallel port on your
-	  GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
-	tristate "GVP IO-Extender PLIP support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable doing IP over the parallel port on your GVP
-	  IO-Extender card, N otherwise.
-
-config MAC_HID
-	bool
-	depends on INPUT_ADBHID
-	default y
-
-config HPDCA
-	tristate "HP DCA serial support"
-	depends on DIO && SERIAL_8250
-	help
-	  If you want to use the internal "DCA" serial ports on an HP300
-	  machine, say Y here.
-
-config HPAPCI
-	tristate "HP APCI serial support"
-	depends on HP300 && SERIAL_8250 && EXPERIMENTAL
-	help
-	  If you want to use the internal "APCI" serial ports on an HP400
-	  machine, say Y here.
-
-config MVME147_SCC
-	bool "SCC support for MVME147 serial ports"
-	depends on MVME147 && BROKEN
-	help
-	  This is the driver for the serial ports on the Motorola MVME147
-	  boards.  Everyone using one of these boards should say Y here.
-
-config MVME162_SCC
-	bool "SCC support for MVME162 serial ports"
-	depends on MVME16x && BROKEN
-	help
-	  This is the driver for the serial ports on the Motorola MVME162 and
-	  172 boards.  Everyone using one of these boards should say Y here.
-
-config BVME6000_SCC
-	bool "SCC support for BVME6000 serial ports"
-	depends on BVME6000 && BROKEN
-	help
-	  This is the driver for the serial ports on the BVME4000 and BVME6000
-	  boards from BVM Ltd.  Everyone using one of these boards should say
-	  Y here.
-
-config DN_SERIAL
-	bool "Support for DN serial port (dummy)"
-	depends on APOLLO
-
-config SERIAL_CONSOLE
-	bool "Support for serial port console"
-	depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
-	---help---
-	  If you say Y here, it will be possible to use a serial port as the
-	  system console (the system console is the device which receives all
-	  kernel messages and warnings and which allows logins in single user
-	  mode). This could be useful if some terminal or printer is connected
-	  to that serial port.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttyS1". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
-	  If you don't have a VGA card installed and you say Y here, the
-	  kernel will automatically use the first serial line, /dev/ttyS0, as
-	  system console.
-
-	  If unsure, say N.
-
-endmenu
-
-endif
+source "arch/m68k/Kconfig.devices"
 
 source "fs/Kconfig"
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.bus linux-libre-3.2-gnu1/arch/m68k/Kconfig.bus
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.bus	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.bus	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+if MMU
+
+comment "Bus Support"
+
+config DIO
+	bool "DIO bus support"
+	depends on HP300
+	default y
+	help
+	  Say Y here to enable support for the "DIO" expansion bus used in
+	  HP300 machines. If you are using such a system you almost certainly
+	  want this.
+
+config NUBUS
+	bool
+	depends on MAC
+	default y
+
+config ZORRO
+	bool "Amiga Zorro (AutoConfig) bus support"
+	depends on AMIGA
+	help
+	  This enables support for the Zorro bus in the Amiga. If you have
+	  expansion cards in your Amiga that conform to the Amiga
+	  AutoConfig(tm) specification, say Y, otherwise N. Note that even
+	  expansion cards that do not fit in the Zorro slots but fit in e.g.
+	  the CPU slot may fall in this category, so you have to say Y to let
+	  Linux use these.
+
+config AMIGA_PCMCIA
+	bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
+	depends on AMIGA && EXPERIMENTAL
+	help
+	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
+	  600. If you intend to use pcmcia cards say Y; otherwise say N.
+
+config ISA
+	bool
+	depends on Q40 || AMIGA_PCMCIA
+	default y
+	help
+	  Find out whether you have ISA slots on your motherboard.  ISA is the
+	  name of a bus system, i.e. the way the CPU talks to the other stuff
+	  inside your box.  Other bus systems are PCI, EISA, MicroChannel
+	  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
+	  newer boards don't support it.  If you have ISA, say Y, otherwise N.
+
+config GENERIC_ISA_DMA
+	def_bool ISA
+
+source "drivers/pci/Kconfig"
+
+source "drivers/zorro/Kconfig"
+
+endif
+
+if !MMU
+
+config ISA_DMA_API
+        def_bool !M5272
+
+source "drivers/pcmcia/Kconfig"
+
+endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.cpu linux-libre-3.2-gnu1/arch/m68k/Kconfig.cpu
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.cpu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.cpu	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,429 @@
+comment "Processor Type"
+
+config M68000
+	bool
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale (was Motorola) 68000 CPU is the first generation of
+	  the well known M68K family of processors. The CPU core as well as
+	  being available as a stand alone CPU was also used in many
+	  System-On-Chip devices (eg 68328, 68302, etc). It does not contain
+	  a paging MMU.
+
+config MCPU32
+	bool
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale (was then Motorola) CPU32 is a CPU core that is
+	  based on the 68020 processor. For the most part it is used in
+	  System-On-Chip parts, and does not contain a paging MMU.
+
+config COLDFIRE
+	bool
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale ColdFire family of processors is a modern derivitive
+	  of the 68000 processor family. They are mainly targeted at embedded
+	  applications, and are all System-On-Chip (SOC) devices, as opposed
+	  to stand alone CPUs. They implement a subset of the original 68000
+	  processor instruction set.
+
+config M68020
+	bool "68020 support"
+	depends on MMU
+	help
+	  If you anticipate running this kernel on a computer with a MC68020
+	  processor, say Y. Otherwise, say N. Note that the 68020 requires a
+	  68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
+	  Sun 3, which provides its own version.
+
+config M68030
+	bool "68030 support"
+	depends on MMU && !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68030
+	  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
+	  work, as it does not include an MMU (Memory Management Unit).
+
+config M68040
+	bool "68040 support"
+	depends on MMU && !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68LC040
+	  or MC68040 processor, say Y. Otherwise, say N. Note that an
+	  MC68EC040 will not work, as it does not include an MMU (Memory
+	  Management Unit).
+
+config M68060
+	bool "68060 support"
+	depends on MMU && !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68060
+	  processor, say Y. Otherwise, say N.
+
+config M68328
+	bool "MC68328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68328 processor support.
+
+config M68EZ328
+	bool "MC68EZ328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68EX328 processor support.
+
+config M68VZ328
+	bool "MC68VZ328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68VZ328 processor support.
+
+config M68360
+	bool "MC68360"
+	depends on !MMU
+	select MCPU32
+	help
+	  Motorola 68360 processor support.
+
+config M5206
+	bool "MCF5206"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206 processor support.
+
+config M5206e
+	bool "MCF5206e"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206e processor support.
+
+config M520x
+	bool "MCF520x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	help
+	   Freescale Coldfire 5207/5208 processor support.
+
+config M523x
+	bool "MCF523x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Freescale Coldfire 5230/1/2/4/5 processor support
+
+config M5249
+	bool "MCF5249"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5249 processor support.
+
+config M527x
+	bool
+
+config M5271
+	bool "MCF5271"
+	depends on !MMU
+	select COLDFIRE
+	select M527x
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	select GENERIC_CLOCKEVENTS
+	help
+	  Freescale (Motorola) ColdFire 5270/5271 processor support.
+
+config M5272
+	bool "MCF5272"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5272 processor support.
+
+config M5275
+	bool "MCF5275"
+	depends on !MMU
+	select COLDFIRE
+	select M527x
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	select GENERIC_CLOCKEVENTS
+	help
+	  Freescale (Motorola) ColdFire 5274/5275 processor support.
+
+config M528x
+	bool "MCF528x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Motorola ColdFire 5280/5282 processor support.
+
+config M5307
+	bool "MCF5307"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5307 processor support.
+
+config M532x
+	bool "MCF532x"
+	depends on !MMU
+	select COLDFIRE
+	select HAVE_CACHE_CB
+	help
+	  Freescale (Motorola) ColdFire 532x processor support.
+
+config M5407
+	bool "MCF5407"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5407 processor support.
+
+config M54xx
+	bool
+
+config M547x
+	bool "MCF547x"
+	depends on !MMU
+	select COLDFIRE
+	select M54xx
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
+
+config M548x
+	bool "MCF548x"
+	depends on !MMU
+	select COLDFIRE
+	select M54xx
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
+
+comment "Processor Specific Options"
+
+config M68KFPU_EMU
+	bool "Math emulation support (EXPERIMENTAL)"
+	depends on MMU
+	depends on EXPERIMENTAL
+	help
+	  At some point in the future, this will cause floating-point math
+	  instructions to be emulated by the kernel on machines that lack a
+	  floating-point math coprocessor.  Thrill-seekers and chronically
+	  sleep-deprived psychotic hacker types can say Y now, everyone else
+	  should probably wait a while.
+
+config M68KFPU_EMU_EXTRAPREC
+	bool "Math emulation extra precision"
+	depends on M68KFPU_EMU
+	help
+	  The fpu uses normally a few bit more during calculations for
+	  correct rounding, the emulator can (often) do the same but this
+	  extra calculation can cost quite some time, so you can disable
+	  it here. The emulator will then "only" calculate with a 64 bit
+	  mantissa and round slightly incorrect, what is more than enough
+	  for normal usage.
+
+config M68KFPU_EMU_ONLY
+	bool "Math emulation only kernel"
+	depends on M68KFPU_EMU
+	help
+	  This option prevents any floating-point instructions from being
+	  compiled into the kernel, thereby the kernel doesn't save any
+	  floating point context anymore during task switches, so this
+	  kernel will only be usable on machines without a floating-point
+	  math coprocessor. This makes the kernel a bit faster as no tests
+	  needs to be executed whether a floating-point instruction in the
+	  kernel should be executed or not.
+
+config ADVANCED
+	bool "Advanced configuration options"
+	depends on MMU
+	---help---
+	  This gives you access to some advanced options for the CPU. The
+	  defaults should be fine for most users, but these options may make
+	  it possible for you to improve performance somewhat if you know what
+	  you are doing.
+
+	  Note that the answer to this question won't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about these options.
+
+	  Most users should say N to this question.
+
+config RMW_INSNS
+	bool "Use read-modify-write instructions"
+	depends on ADVANCED
+	---help---
+	  This allows to use certain instructions that work with indivisible
+	  read-modify-write bus cycles. While this is faster than the
+	  workaround of disabling interrupts, it can conflict with DMA
+	  ( = direct memory access) on many Amiga systems, and it is also said
+	  to destabilize other machines. It is very likely that this will
+	  cause serious problems on any Amiga or Atari Medusa if set. The only
+	  configuration where it should work are 68030-based Ataris, where it
+	  apparently improves performance. But you've been warned! Unless you
+	  really know what you are doing, say N. Try Y only if you're quite
+	  adventurous.
+
+config SINGLE_MEMORY_CHUNK
+	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+	depends on MMU
+	default y if SUN3
+	select NEED_MULTIPLE_NODES
+	help
+	  Ignore all but the first contiguous chunk of physical memory for VM
+	  purposes.  This will save a few bytes kernel size and may speed up
+	  some operations.  Say N if not sure.
+
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool MMU && !SINGLE_MEMORY_CHUNK
+
+config 060_WRITETHROUGH
+	bool "Use write-through caching for 68060 supervisor accesses"
+	depends on ADVANCED && M68060
+	---help---
+	  The 68060 generally uses copyback caching of recently accessed data.
+	  Copyback caching means that memory writes will be held in an on-chip
+	  cache and only written back to memory some time later.  Saying Y
+	  here will force supervisor (kernel) accesses to use writethrough
+	  caching.  Writethrough caching means that data is written to memory
+	  straight away, so that cache and memory data always agree.
+	  Writethrough caching is less efficient, but is needed for some
+	  drivers on 68060 based systems where the 68060 bus snooping signal
+	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
+	  this problem.
+
+config M68K_L2_CACHE
+	bool
+	depends on MAC
+	default y
+
+config NODES_SHIFT
+	int
+	default "3"
+	depends on !SINGLE_MEMORY_CHUNK
+
+config FPU
+	bool
+
+config COLDFIRE_SW_A7
+	bool
+
+config HAVE_CACHE_SPLIT
+	bool
+
+config HAVE_CACHE_CB
+	bool
+
+config HAVE_MBAR
+	bool
+
+config HAVE_IPSBAR
+	bool
+
+config CLOCK_SET
+	bool "Enable setting the CPU clock frequency"
+	depends on COLDFIRE
+	default n
+	help
+	  On some CPU's you do not need to know what the core CPU clock
+	  frequency is. On these you can disable clock setting. On some
+	  traditional 68K parts, and on all ColdFire parts you need to set
+	  the appropriate CPU clock frequency. On these devices many of the
+	  onboard peripherals derive their timing from the master CPU clock
+	  frequency.
+
+config CLOCK_FREQ
+	int "Set the core clock frequency"
+	default "66666666"
+	depends on CLOCK_SET
+	help
+	  Define the CPU clock frequency in use. This is the core clock
+	  frequency, it may or may not be the same as the external clock
+	  crystal fitted to your board. Some processors have an internal
+	  PLL and can have their frequency programmed at run time, others
+	  use internal dividers. In general the kernel won't setup a PLL
+	  if it is fitted (there are some exceptions). This value will be
+	  specific to the exact CPU that you are using.
+
+config OLDMASK
+	bool "Old mask 5307 (1H55J) silicon"
+	depends on M5307
+	help
+	  Build support for the older revision ColdFire 5307 silicon.
+	  Specifically this is the 1H55J mask revision.
+
+if HAVE_CACHE_SPLIT
+choice
+	prompt "Split Cache Configuration"
+	default CACHE_I
+
+config CACHE_I
+	bool "Instruction"
+	help
+	  Use all of the ColdFire CPU cache memory as an instruction cache.
+
+config CACHE_D
+	bool "Data"
+	help
+	  Use all of the ColdFire CPU cache memory as a data cache.
+
+config CACHE_BOTH
+	bool "Both"
+	help
+	  Split the ColdFire CPU cache, and use half as an instruction cache
+	  and half as a data cache.
+endchoice
+endif
+
+if HAVE_CACHE_CB
+choice
+	prompt "Data cache mode"
+	default CACHE_WRITETHRU
+
+config CACHE_WRITETHRU
+	bool "Write-through"
+	help
+	  The ColdFire CPU cache is set into Write-through mode.
+
+config CACHE_COPYBACK
+	bool "Copy-back"
+	help
+	  The ColdFire CPU cache is set into Copy-back mode.
+endchoice
+endif
+
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.devices linux-libre-3.2-gnu1/arch/m68k/Kconfig.devices
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.devices	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.devices	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+if MMU
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+	depends on BROKEN && (Q40 || SUN3X)
+	default y
+
+menu "Platform devices"
+
+config HEARTBEAT
+	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
+	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
+	help
+	  Use the power-on LED on your machine as a load meter.  The exact
+	  behavior is platform-dependent, but normally the flash frequency is
+	  a hyperbolic function of the 5-minute load average.
+
+# We have a dedicated heartbeat LED. :-)
+config PROC_HARDWARE
+	bool "/proc/hardware support"
+	help
+	  Say Y here to support the /proc/hardware file, which gives you
+	  access to information about the machine you're running on,
+	  including the model, CPU, MMU, clock speed, BogoMIPS rating,
+	  and memory size.
+
+config NATFEAT
+	bool "ARAnyM emulator support"
+	depends on ATARI
+	help
+	  This option enables support for ARAnyM native features, such as
+	  access to a disk image as /dev/hda.
+
+config NFBLOCK
+	tristate "NatFeat block device support"
+	depends on BLOCK && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat block device
+	  which allows direct access to the hard drives without using
+	  the hardware emulation.
+
+config NFCON
+	tristate "NatFeat console driver"
+	depends on NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat console driver
+	  which allows the console output to be redirected to the stderr
+	  output of ARAnyM.
+
+config NFETH
+	tristate "NatFeat Ethernet support"
+	depends on ETHERNET && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat network device
+	  which will emulate a regular ethernet device while presenting an
+	  ethertap device to the host system.
+
+endmenu
+
+menu "Character devices"
+
+config ATARI_MFPSER
+	tristate "Atari MFP serial support"
+	depends on ATARI
+	---help---
+	  If you like to use the MFP serial ports ("Modem1", "Serial1") under
+	  Linux, say Y. The driver equally supports all kinds of MFP serial
+	  ports and automatically detects whether Serial1 is available.
+
+	  To compile this driver as a module, choose M here.
+
+	  Note for Falcon users: You also have an MFP port, it's just not
+	  wired to the outside... But you could use the port under Linux.
+
+config ATARI_MIDI
+	tristate "Atari MIDI serial support"
+	depends on ATARI
+	help
+	  If you want to use your Atari's MIDI port in Linux, say Y.
+
+	  To compile this driver as a module, choose M here.
+
+config ATARI_DSP56K
+	tristate "Atari DSP56k support (EXPERIMENTAL)"
+	depends on ATARI && EXPERIMENTAL
+	help
+	  If you want to be able to use the DSP56001 in Falcons, say Y. This
+	  driver is still experimental, and if you don't know what it is, or
+	  if you don't have this processor, just say N.
+
+	  To compile this driver as a module, choose M here.
+
+config AMIGA_BUILTIN_SERIAL
+	tristate "Amiga builtin serial support"
+	depends on AMIGA
+	help
+	  If you want to use your Amiga's built-in serial port in Linux,
+	  answer Y.
+
+	  To compile this driver as a module, choose M here.
+
+config MULTIFACE_III_TTY
+	tristate "Multiface Card III serial support"
+	depends on AMIGA
+	help
+	  If you want to use a Multiface III card's serial port in Linux,
+	  answer Y.
+
+	  To compile this driver as a module, choose M here.
+
+config HPDCA
+	tristate "HP DCA serial support"
+	depends on DIO && SERIAL_8250
+	help
+	  If you want to use the internal "DCA" serial ports on an HP300
+	  machine, say Y here.
+
+config HPAPCI
+	tristate "HP APCI serial support"
+	depends on HP300 && SERIAL_8250 && EXPERIMENTAL
+	help
+	  If you want to use the internal "APCI" serial ports on an HP400
+	  machine, say Y here.
+
+config DN_SERIAL
+	bool "Support for DN serial port (dummy)"
+	depends on APOLLO
+
+config SERIAL_CONSOLE
+	bool "Support for serial port console"
+	depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || MULTIFACE_III_TTY=y || SERIAL=y || SERIAL167 || DN_SERIAL)
+	---help---
+	  If you say Y here, it will be possible to use a serial port as the
+	  system console (the system console is the device which receives all
+	  kernel messages and warnings and which allows logins in single user
+	  mode). This could be useful if some terminal or printer is connected
+	  to that serial port.
+
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttyS1". (Try "man bootparam" or see the documentation of
+	  your boot loader (lilo or loadlin) about how to pass options to the
+	  kernel at boot time.)
+
+	  If you don't have a VGA card installed and you say Y here, the
+	  kernel will automatically use the first serial line, /dev/ttyS0, as
+	  system console.
+
+	  If unsure, say N.
+
+endmenu
+
+endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.machine linux-libre-3.2-gnu1/arch/m68k/Kconfig.machine
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.machine	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.machine	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,583 @@
+comment "Machine Types"
+
+config AMIGA
+	bool "Amiga support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the Amiga series of computers. If
+	  you plan to use this kernel on an Amiga, say Y here and browse the
+	  material available in <file:Documentation/m68k>; otherwise say N.
+
+config ATARI
+	bool "Atari support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the 68000-based Atari series of
+	  computers (including the TT, Falcon and Medusa). If you plan to use
+	  this kernel on an Atari, say Y here and browse the material
+	  available in <file:Documentation/m68k>; otherwise say N.
+
+config MAC
+	bool "Macintosh support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the Apple Macintosh series of
+	  computers (yes, there is experimental support now, at least for part
+	  of the series).
+
+	  Say N unless you're willing to code the remaining necessary support.
+	  ;)
+
+config APOLLO
+	bool "Apollo support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  Say Y here if you want to run Linux on an MC680x0-based Apollo
+	  Domain workstation such as the DN3500.
+
+config VME
+	bool "VME (Motorola and BVM) support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  Say Y here if you want to build a kernel for a 680x0 based VME
+	  board.  Boards currently supported include Motorola boards MVME147,
+	  MVME162, MVME166, MVME167, MVME172, and MVME177.  BVME4000 and
+	  BVME6000 boards from BVM Ltd are also supported.
+
+config MVME147
+	bool "MVME147 support"
+	depends on MMU
+	depends on VME
+	help
+	  Say Y to include support for early Motorola VME boards.  This will
+	  build a kernel which can run on MVME147 single-board computers.  If
+	  you select this option you will have to select the appropriate
+	  drivers for SCSI, Ethernet and serial ports later on.
+
+config MVME16x
+	bool "MVME162, 166 and 167 support"
+	depends on MMU
+	depends on VME
+	help
+	  Say Y to include support for Motorola VME boards.  This will build a
+	  kernel which can run on MVME162, MVME166, MVME167, MVME172, and
+	  MVME177 boards.  If you select this option you will have to select
+	  the appropriate drivers for SCSI, Ethernet and serial ports later
+	  on.
+
+config BVME6000
+	bool "BVME4000 and BVME6000 support"
+	depends on MMU
+	depends on VME
+	help
+	  Say Y to include support for VME boards from BVM Ltd.  This will
+	  build a kernel which can run on BVME4000 and BVME6000 boards.  If
+	  you select this option you will have to select the appropriate
+	  drivers for SCSI, Ethernet and serial ports later on.
+
+config HP300
+	bool "HP9000/300 and HP9000/400 support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the HP9000/300 and HP9000/400 series
+	  of workstations. Support for these machines is still somewhat
+	  experimental. If you plan to try to use the kernel on such a machine
+	  say Y here.
+	  Everybody else says N.
+
+config SUN3X
+	bool "Sun3x support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	select M68030
+	help
+	  This option enables support for the Sun 3x series of workstations.
+	  Be warned that this support is very experimental.
+	  Note that Sun 3x kernels are not compatible with Sun 3 hardware.
+	  General Linux information on the Sun 3x series (now discontinued)
+	  is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+	  If you don't want to compile a kernel for a Sun 3x, say N.
+
+config Q40
+	bool "Q40/Q60 support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	help
+	  The Q40 is a Motorola 68040-based successor to the Sinclair QL
+	  manufactured in Germany.  There is an official Q40 home page at
+	  <http://www.q40.de/>.  This option enables support for the Q40 and
+	  Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
+	  emulation.
+
+config SUN3
+	bool "Sun3 support"
+	depends on MMU
+	depends on !MMU_MOTOROLA
+	select MMU_SUN3 if MMU
+	select M68020
+	help
+	  This option enables support for the Sun 3 series of workstations
+	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
+	  that all other hardware types must be disabled, as Sun 3 kernels
+	  are incompatible with all other m68k targets (including Sun 3x!).
+
+	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
+
+config PILOT
+	bool
+
+config PILOT3
+	bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
+	depends on M68328
+	select PILOT
+	help
+	  Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
+
+config XCOPILOT_BUGS
+	bool "(X)Copilot support"
+	depends on PILOT3
+	help
+	  Support the bugs of Xcopilot.
+
+config UC5272
+	bool "Arcturus Networks uC5272 dimm board support"
+	depends on M5272
+	help
+	  Support for the Arcturus Networks uC5272 dimm board.
+
+config UC5282
+	bool "Arcturus Networks uC5282 board support"
+	depends on M528x
+	help
+	  Support for the Arcturus Networks uC5282 dimm board.
+
+config UCSIMM
+	bool "uCsimm module support"
+	depends on M68EZ328
+	help
+	  Support for the Arcturus Networks uCsimm module.
+
+config UCDIMM
+	bool "uDsimm module support"
+	depends on M68VZ328
+	help
+	  Support for the Arcturus Networks uDsimm module.
+
+config DRAGEN2
+	bool "DragenEngine II board support"
+	depends on M68VZ328
+	help
+	  Support for the DragenEngine II board.
+
+config DIRECT_IO_ACCESS
+	bool "Allow user to access IO directly"
+	depends on (UCSIMM || UCDIMM || DRAGEN2)
+	help
+	  Disable the CPU internal registers protection in user mode,
+	  to allow a user application to read/write them.
+
+config INIT_LCD
+	bool "Initialize LCD"
+	depends on (UCSIMM || UCDIMM || DRAGEN2)
+	help
+	  Initialize the LCD controller of the 68x328 processor.
+
+config MEMORY_RESERVE
+	int "Memory reservation (MiB)"
+	depends on (UCSIMM || UCDIMM)
+	help
+	  Reserve certain memory regions on 68x328 based boards.
+
+config UCQUICC
+	bool "Lineo uCquicc board support"
+	depends on M68360
+	help
+	  Support for the Lineo uCquicc board.
+
+config ARNEWSH
+	bool
+
+config ARN5206
+	bool "Arnewsh 5206 board support"
+	depends on M5206
+	select ARNEWSH
+	help
+	  Support for the Arnewsh 5206 board.
+
+config FREESCALE
+	bool
+
+config M5206eC3
+	bool "Motorola M5206eC3 board support"
+	depends on M5206e
+	select FREESCALE
+	help
+	  Support for the Motorola M5206eC3 board.
+
+config ELITE
+	bool "Motorola M5206eLITE board support"
+	depends on M5206e
+	help
+	  Support for the Motorola M5206eLITE board.
+
+config M5208EVB
+	bool "Freescale M5208EVB board support"
+	depends on M520x
+	select FREESCALE
+	help
+	  Support for the Freescale Coldfire M5208EVB.
+
+config M5235EVB
+	bool "Freescale M5235EVB support"
+	depends on M523x
+	select FREESCALE
+	help
+	  Support for the Freescale M5235EVB board.
+
+config M5249C3
+	bool "Motorola M5249C3 board support"
+	depends on M5249
+	select FREESCALE
+	help
+	  Support for the Motorola M5249C3 board.
+
+config M5271EVB
+	bool "Freescale (Motorola) M5271EVB board support"
+	depends on M5271
+	select FREESCALE
+	help
+	  Support for the Freescale (Motorola) M5271EVB board.
+
+config M5275EVB
+	bool "Freescale (Motorola) M5275EVB board support"
+	depends on M5275
+	select FREESCALE
+	help
+	  Support for the Freescale (Motorola) M5275EVB board.
+
+config M5272C3
+	bool "Motorola M5272C3 board support"
+	depends on M5272
+	select FREESCALE
+	help
+	  Support for the Motorola M5272C3 board.
+
+config senTec
+	bool
+
+config COBRA5272
+	bool "senTec COBRA5272 board support"
+	depends on M5272
+	select senTec
+	help
+	  Support for the senTec COBRA5272 board.
+
+config AVNET
+	bool
+
+config AVNET5282
+	bool "Avnet 5282 board support"
+	depends on M528x
+	select AVNET
+	help
+	  Support for the Avnet 5282 board.
+
+config M5282EVB
+	bool "Motorola M5282EVB board support"
+	depends on M528x
+	select FREESCALE
+	help
+	  Support for the Motorola M5282EVB board.
+
+config COBRA5282
+	bool "senTec COBRA5282 board support"
+	depends on M528x
+	select senTec
+	help
+	  Support for the senTec COBRA5282 board.
+
+config SOM5282EM
+	bool "EMAC.Inc SOM5282EM board support"
+	depends on M528x
+	select EMAC_INC
+	help
+	  Support for the EMAC.Inc SOM5282EM module.
+
+config WILDFIRE
+	bool "Intec Automation Inc. WildFire board support"
+	depends on M528x
+	help
+	  Support for the Intec Automation Inc. WildFire.
+
+config WILDFIREMOD
+	bool "Intec Automation Inc. WildFire module support"
+	depends on M528x
+	help
+	  Support for the Intec Automation Inc. WildFire module.
+
+config ARN5307
+	bool "Arnewsh 5307 board support"
+	depends on M5307
+	select ARNEWSH
+	help
+	  Support for the Arnewsh 5307 board.
+
+config M5307C3
+	bool "Motorola M5307C3 board support"
+	depends on M5307
+	select FREESCALE
+	help
+	  Support for the Motorola M5307C3 board.
+
+config SECUREEDGEMP3
+	bool "SnapGear SecureEdge/MP3 platform support"
+	depends on M5307
+	help
+	  Support for the SnapGear SecureEdge/MP3 platform.
+
+config M5329EVB
+	bool "Freescale (Motorola) M5329EVB board support"
+	depends on M532x
+	select FREESCALE
+	help
+	  Support for the Freescale (Motorola) M5329EVB board.
+
+config COBRA5329
+	bool "senTec COBRA5329 board support"
+	depends on M532x
+	help
+	  Support for the senTec COBRA5329 board.
+
+config M5407C3
+	bool "Motorola M5407C3 board support"
+	depends on M5407
+	select FREESCALE
+	help
+	  Support for the Motorola M5407C3 board.
+
+config FIREBEE
+	bool "FireBee board support"
+	depends on M547x
+	help
+	  Support for the FireBee ColdFire 5475 based board.
+
+config CLEOPATRA
+	bool "Feith CLEOPATRA board support"
+	depends on (M5307 || M5407)
+	help
+	  Support for the Feith Cleopatra boards.
+
+config CANCam
+	bool "Feith CANCam board support"
+	depends on M5272
+	help
+	  Support for the Feith CANCam board.
+
+config SCALES
+	bool "Feith SCALES board support"
+	depends on M5272
+	help
+	  Support for the Feith SCALES board.
+
+config NETtel
+	bool "SecureEdge/NETtel board support"
+	depends on (M5206e || M5272 || M5307)
+	help
+	  Support for the SnapGear NETtel/SecureEdge/SnapGear boards.
+
+config SNAPGEAR
+	bool "SnapGear router board support"
+	depends on NETtel
+	help
+	  Special additional support for SnapGear router boards.
+
+config SNEHA
+	bool
+
+config CPU16B
+	bool "Sneha Technologies S.L. Sarasvati board support"
+	depends on M5272
+	select SNEHA
+	help
+	  Support for the SNEHA CPU16B board.
+
+config MOD5272
+	bool "Netburner MOD-5272 board support"
+	depends on M5272
+	help
+	  Support for the Netburner MOD-5272 board.
+
+config SAVANT
+	bool
+
+config SAVANTrosie1
+	bool "Savant Rosie1 board support"
+	depends on M523x
+	select SAVANT
+	help
+	  Support for the Savant Rosie1 board.
+
+
+if !MMU || COLDFIRE
+
+comment "Machine Options"
+
+config UBOOT
+	bool "Support for U-Boot command line parameters"
+	help
+	  If you say Y here kernel will try to collect command
+	  line parameters from the initial u-boot stack.
+	default n
+
+config 4KSTACKS
+	bool "Use 4Kb for kernel stacks instead of 8Kb"
+	default y
+	help
+	  If you say Y here the kernel will use a 4Kb stacksize for the
+	  kernel stack attached to each process/thread. This facilitates
+	  running more threads on a system and also reduces the pressure
+	  on the VM subsystem for higher order allocations.
+
+comment "RAM configuration"
+
+config RAMBASE
+	hex "Address of the base of RAM"
+	default "0"
+	help
+	  Define the address that RAM starts at. On many platforms this is
+	  0, the base of the address space. And this is the default. Some
+	  platforms choose to setup their RAM at other addresses within the
+	  processor address space.
+
+config RAMSIZE
+	hex "Size of RAM (in bytes), or 0 for automatic"
+	default "0x400000"
+	help
+	  Define the size of the system RAM. If you select 0 then the
+	  kernel will try to probe the RAM size at runtime. This is not
+	  supported on all CPU types.
+
+config VECTORBASE
+	hex "Address of the base of system vectors"
+	default "0"
+	help
+	  Define the address of the system vectors. Commonly this is
+	  put at the start of RAM, but it doesn't have to be. On ColdFire
+	  platforms this address is programmed into the VBR register, thus
+	  actually setting the address to use.
+
+config MBAR
+	hex "Address of the MBAR (internal peripherals)"
+	default "0x10000000"
+	depends on HAVE_MBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors MBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x10000000 value, so if unsure then
+	  use this.
+
+config IPSBAR
+	hex "Address of the IPSBAR (internal peripherals)"
+	default "0x40000000"
+	depends on HAVE_IPSBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors IPSBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x40000000 value, so if unsure then
+	  use this.
+
+config KERNELBASE
+	hex "Address of the base of kernel code"
+	default "0x400"
+	help
+	  Typically on m68k systems the kernel will not start at the base
+	  of RAM, but usually some small offset from it. Define the start
+	  address of the kernel here. The most common setup will have the
+	  processor vectors at the base of RAM and then the start of the
+	  kernel. On some platforms some RAM is reserved for boot loaders
+	  and the kernel starts after that. The 0x400 default was based on
+	  a system with the RAM based at address 0, and leaving enough room
+	  for the theoretical maximum number of 256 vectors.
+
+comment "ROM configuration"
+
+config ROM
+	bool "Specify ROM linker regions"
+	default n
+	help
+	  Define a ROM region for the linker script. This creates a kernel
+	  that can be stored in flash, with possibly the text, and data
+	  regions being copied out to RAM at startup.
+
+config ROMBASE
+	hex "Address of the base of ROM device"
+	default "0"
+	depends on ROM
+	help
+	  Define the address that the ROM region starts at. Some platforms
+	  use this to set their chip select region accordingly for the boot
+	  device.
+
+config ROMVEC
+	hex "Address of the base of the ROM vectors"
+	default "0"
+	depends on ROM
+	help
+	  This is almost always the same as the base of the ROM. Since on all
+	  68000 type variants the vectors are at the base of the boot device
+	  on system startup.
+
+config ROMVECSIZE
+	hex "Size of ROM vector region (in bytes)"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the size of the vector region in ROM. For most 68000
+	  variants this would be 0x400 bytes in size. Set to 0 if you do
+	  not want a vector region at the start of the ROM.
+
+config ROMSTART
+	hex "Address of the base of system image in ROM"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the start address of the system image in ROM. Commonly this
+	  is strait after the ROM vectors.
+
+config ROMSIZE
+	hex "Size of the ROM device"
+	default "0x100000"
+	depends on ROM
+	help
+	  Size of the ROM device. On some platforms this is used to setup
+	  the chip select that controls the boot ROM device.
+
+choice
+	prompt "Kernel executes from"
+	---help---
+	  Choose the memory type that the kernel will be running in.
+
+config RAMKERNEL
+	bool "RAM"
+	help
+	  The kernel will be resident in RAM when running.
+
+config ROMKERNEL
+	bool "ROM"
+	help
+	  The kernel will be resident in FLASH/ROM when running. This is
+	  often referred to as Execute-in-Place (XIP), since the kernel
+	  code executes from the position it is stored in the FLASH/ROM.
+
+endchoice
+
+endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.mmu linux-libre-3.2-gnu1/arch/m68k/Kconfig.mmu
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.mmu	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.mmu	1969-12-31 19:00:00.000000000 -0500
@@ -1,411 +0,0 @@
-config GENERIC_IOMAP
-	bool
-	default y
-
-config ARCH_MAY_HAVE_PC_FDC
-	bool
-	depends on BROKEN && (Q40 || SUN3X)
-	default y
-
-config ARCH_USES_GETTIMEOFFSET
-	def_bool y
-
-config EISA
-	bool
-	---help---
-	  The Extended Industry Standard Architecture (EISA) bus was
-	  developed as an open alternative to the IBM MicroChannel bus.
-
-	  The EISA bus provided some of the features of the IBM MicroChannel
-	  bus while maintaining backward compatibility with cards made for
-	  the older ISA bus.  The EISA bus saw limited use between 1988 and
-	  1995 when it was made obsolete by the PCI bus.
-
-	  Say Y here if you are building a kernel for an EISA-based machine.
-
-	  Otherwise, say N.
-
-config MCA
-	bool
-	help
-	  MicroChannel Architecture is found in some IBM PS/2 machines and
-	  laptops.  It is a bus system similar to PCI or ISA. See
-	  <file:Documentation/mca.txt> (and especially the web page given
-	  there) before attempting to build an MCA bus kernel.
-
-config PCMCIA
-	tristate
-	---help---
-	  Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
-	  computer.  These are credit-card size devices such as network cards,
-	  modems or hard drives often used with laptops computers.  There are
-	  actually two varieties of these cards: the older 16 bit PCMCIA cards
-	  and the newer 32 bit CardBus cards.  If you want to use CardBus
-	  cards, you need to say Y here and also to "CardBus support" below.
-
-	  To use your PC-cards, you will need supporting software from David
-	  Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
-	  for location).  Please also read the PCMCIA-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as modules, choose M here: the
-	  modules will be called pcmcia_core and ds.
-
-config AMIGA
-	bool "Amiga support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the Amiga series of computers. If
-	  you plan to use this kernel on an Amiga, say Y here and browse the
-	  material available in <file:Documentation/m68k>; otherwise say N.
-
-config ATARI
-	bool "Atari support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the 68000-based Atari series of
-	  computers (including the TT, Falcon and Medusa). If you plan to use
-	  this kernel on an Atari, say Y here and browse the material
-	  available in <file:Documentation/m68k>; otherwise say N.
-
-config MAC
-	bool "Macintosh support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the Apple Macintosh series of
-	  computers (yes, there is experimental support now, at least for part
-	  of the series).
-
-	  Say N unless you're willing to code the remaining necessary support.
-	  ;)
-
-config NUBUS
-	bool
-	depends on MAC
-	default y
-
-config M68K_L2_CACHE
-	bool
-	depends on MAC
-	default y
-
-config APOLLO
-	bool "Apollo support"
-	select MMU_MOTOROLA if MMU
-	help
-	  Say Y here if you want to run Linux on an MC680x0-based Apollo
-	  Domain workstation such as the DN3500.
-
-config VME
-	bool "VME (Motorola and BVM) support"
-	select MMU_MOTOROLA if MMU
-	help
-	  Say Y here if you want to build a kernel for a 680x0 based VME
-	  board.  Boards currently supported include Motorola boards MVME147,
-	  MVME162, MVME166, MVME167, MVME172, and MVME177.  BVME4000 and
-	  BVME6000 boards from BVM Ltd are also supported.
-
-config MVME147
-	bool "MVME147 support"
-	depends on VME
-	help
-	  Say Y to include support for early Motorola VME boards.  This will
-	  build a kernel which can run on MVME147 single-board computers.  If
-	  you select this option you will have to select the appropriate
-	  drivers for SCSI, Ethernet and serial ports later on.
-
-config MVME16x
-	bool "MVME162, 166 and 167 support"
-	depends on VME
-	help
-	  Say Y to include support for Motorola VME boards.  This will build a
-	  kernel which can run on MVME162, MVME166, MVME167, MVME172, and
-	  MVME177 boards.  If you select this option you will have to select
-	  the appropriate drivers for SCSI, Ethernet and serial ports later
-	  on.
-
-config BVME6000
-	bool "BVME4000 and BVME6000 support"
-	depends on VME
-	help
-	  Say Y to include support for VME boards from BVM Ltd.  This will
-	  build a kernel which can run on BVME4000 and BVME6000 boards.  If
-	  you select this option you will have to select the appropriate
-	  drivers for SCSI, Ethernet and serial ports later on.
-
-config HP300
-	bool "HP9000/300 and HP9000/400 support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the HP9000/300 and HP9000/400 series
-	  of workstations. Support for these machines is still somewhat
-	  experimental. If you plan to try to use the kernel on such a machine
-	  say Y here.
-	  Everybody else says N.
-
-config DIO
-	bool "DIO bus support"
-	depends on HP300
-	default y
-	help
-	  Say Y here to enable support for the "DIO" expansion bus used in
-	  HP300 machines. If you are using such a system you almost certainly
-	  want this.
-
-config SUN3X
-	bool "Sun3x support"
-	select MMU_MOTOROLA if MMU
-	select M68030
-	help
-	  This option enables support for the Sun 3x series of workstations.
-	  Be warned that this support is very experimental.
-	  Note that Sun 3x kernels are not compatible with Sun 3 hardware.
-	  General Linux information on the Sun 3x series (now discontinued)
-	  is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
-
-	  If you don't want to compile a kernel for a Sun 3x, say N.
-
-config Q40
-	bool "Q40/Q60 support"
-	select MMU_MOTOROLA if MMU
-	help
-	  The Q40 is a Motorola 68040-based successor to the Sinclair QL
-	  manufactured in Germany.  There is an official Q40 home page at
-	  <http://www.q40.de/>.  This option enables support for the Q40 and
-	  Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
-	  emulation.
-
-config SUN3
-	bool "Sun3 support"
-	depends on !MMU_MOTOROLA
-	select MMU_SUN3 if MMU
-	select M68020
-	help
-	  This option enables support for the Sun 3 series of workstations
-	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
-	  that all other hardware types must be disabled, as Sun 3 kernels
-	  are incompatible with all other m68k targets (including Sun 3x!).
-
-	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
-config NATFEAT
-	bool "ARAnyM emulator support"
-	depends on ATARI
-	help
-	  This option enables support for ARAnyM native features, such as
-	  access to a disk image as /dev/hda.
-
-config NFBLOCK
-	tristate "NatFeat block device support"
-	depends on BLOCK && NATFEAT
-	help
-	  Say Y to include support for the ARAnyM NatFeat block device
-	  which allows direct access to the hard drives without using
-	  the hardware emulation.
-
-config NFCON
-	tristate "NatFeat console driver"
-	depends on NATFEAT
-	help
-	  Say Y to include support for the ARAnyM NatFeat console driver
-	  which allows the console output to be redirected to the stderr
-	  output of ARAnyM.
-
-config NFETH
-	tristate "NatFeat Ethernet support"
-	depends on NET_ETHERNET && NATFEAT
-	help
-	  Say Y to include support for the ARAnyM NatFeat network device
-	  which will emulate a regular ethernet device while presenting an
-	  ethertap device to the host system.
-
-comment "Processor type"
-
-config M68020
-	bool "68020 support"
-	help
-	  If you anticipate running this kernel on a computer with a MC68020
-	  processor, say Y. Otherwise, say N. Note that the 68020 requires a
-	  68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
-	  Sun 3, which provides its own version.
-
-config M68030
-	bool "68030 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68030
-	  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
-	  work, as it does not include an MMU (Memory Management Unit).
-
-config M68040
-	bool "68040 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68LC040
-	  or MC68040 processor, say Y. Otherwise, say N. Note that an
-	  MC68EC040 will not work, as it does not include an MMU (Memory
-	  Management Unit).
-
-config M68060
-	bool "68060 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68060
-	  processor, say Y. Otherwise, say N.
-
-config MMU_MOTOROLA
-	bool
-
-config MMU_SUN3
-	bool
-	depends on MMU && !MMU_MOTOROLA
-
-config M68KFPU_EMU
-	bool "Math emulation support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	help
-	  At some point in the future, this will cause floating-point math
-	  instructions to be emulated by the kernel on machines that lack a
-	  floating-point math coprocessor.  Thrill-seekers and chronically
-	  sleep-deprived psychotic hacker types can say Y now, everyone else
-	  should probably wait a while.
-
-config M68KFPU_EMU_EXTRAPREC
-	bool "Math emulation extra precision"
-	depends on M68KFPU_EMU
-	help
-	  The fpu uses normally a few bit more during calculations for
-	  correct rounding, the emulator can (often) do the same but this
-	  extra calculation can cost quite some time, so you can disable
-	  it here. The emulator will then "only" calculate with a 64 bit
-	  mantissa and round slightly incorrect, what is more than enough
-	  for normal usage.
-
-config M68KFPU_EMU_ONLY
-	bool "Math emulation only kernel"
-	depends on M68KFPU_EMU
-	help
-	  This option prevents any floating-point instructions from being
-	  compiled into the kernel, thereby the kernel doesn't save any
-	  floating point context anymore during task switches, so this
-	  kernel will only be usable on machines without a floating-point
-	  math coprocessor. This makes the kernel a bit faster as no tests
-	  needs to be executed whether a floating-point instruction in the
-	  kernel should be executed or not.
-
-config ADVANCED
-	bool "Advanced configuration options"
-	---help---
-	  This gives you access to some advanced options for the CPU. The
-	  defaults should be fine for most users, but these options may make
-	  it possible for you to improve performance somewhat if you know what
-	  you are doing.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about these options.
-
-	  Most users should say N to this question.
-
-config RMW_INSNS
-	bool "Use read-modify-write instructions"
-	depends on ADVANCED
-	---help---
-	  This allows to use certain instructions that work with indivisible
-	  read-modify-write bus cycles. While this is faster than the
-	  workaround of disabling interrupts, it can conflict with DMA
-	  ( = direct memory access) on many Amiga systems, and it is also said
-	  to destabilize other machines. It is very likely that this will
-	  cause serious problems on any Amiga or Atari Medusa if set. The only
-	  configuration where it should work are 68030-based Ataris, where it
-	  apparently improves performance. But you've been warned! Unless you
-	  really know what you are doing, say N. Try Y only if you're quite
-	  adventurous.
-
-config SINGLE_MEMORY_CHUNK
-	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
-	default y if SUN3
-	select NEED_MULTIPLE_NODES
-	help
-	  Ignore all but the first contiguous chunk of physical memory for VM
-	  purposes.  This will save a few bytes kernel size and may speed up
-	  some operations.  Say N if not sure.
-
-config 060_WRITETHROUGH
-	bool "Use write-through caching for 68060 supervisor accesses"
-	depends on ADVANCED && M68060
-	---help---
-	  The 68060 generally uses copyback caching of recently accessed data.
-	  Copyback caching means that memory writes will be held in an on-chip
-	  cache and only written back to memory some time later.  Saying Y
-	  here will force supervisor (kernel) accesses to use writethrough
-	  caching.  Writethrough caching means that data is written to memory
-	  straight away, so that cache and memory data always agree.
-	  Writethrough caching is less efficient, but is needed for some
-	  drivers on 68060 based systems where the 68060 bus snooping signal
-	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
-	  this problem.
-
-config ARCH_DISCONTIGMEM_ENABLE
-	def_bool !SINGLE_MEMORY_CHUNK
-
-config NODES_SHIFT
-	int
-	default "3"
-	depends on !SINGLE_MEMORY_CHUNK
-
-config ZORRO
-	bool "Amiga Zorro (AutoConfig) bus support"
-	depends on AMIGA
-	help
-	  This enables support for the Zorro bus in the Amiga. If you have
-	  expansion cards in your Amiga that conform to the Amiga
-	  AutoConfig(tm) specification, say Y, otherwise N. Note that even
-	  expansion cards that do not fit in the Zorro slots but fit in e.g.
-	  the CPU slot may fall in this category, so you have to say Y to let
-	  Linux use these.
-
-config AMIGA_PCMCIA
-	bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
-	depends on AMIGA && EXPERIMENTAL
-	help
-	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
-	  600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config HEARTBEAT
-	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
-	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
-	help
-	  Use the power-on LED on your machine as a load meter.  The exact
-	  behavior is platform-dependent, but normally the flash frequency is
-	  a hyperbolic function of the 5-minute load average.
-
-# We have a dedicated heartbeat LED. :-)
-config PROC_HARDWARE
-	bool "/proc/hardware support"
-	help
-	  Say Y here to support the /proc/hardware file, which gives you
-	  access to information about the machine you're running on,
-	  including the model, CPU, MMU, clock speed, BogoMIPS rating,
-	  and memory size.
-
-config ISA
-	bool
-	depends on Q40 || AMIGA_PCMCIA
-	default y
-	help
-	  Find out whether you have ISA slots on your motherboard.  ISA is the
-	  name of a bus system, i.e. the way the CPU talks to the other stuff
-	  inside your box.  Other bus systems are PCI, EISA, MicroChannel
-	  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
-	  newer boards don't support it.  If you have ISA, say Y, otherwise N.
-
-config GENERIC_ISA_DMA
-	bool
-	depends on Q40 || AMIGA_PCMCIA
-	default y
-
-source "drivers/pci/Kconfig"
-
-source "drivers/zorro/Kconfig"
-
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Kconfig.nommu linux-libre-3.2-gnu1/arch/m68k/Kconfig.nommu
--- linux-libre-3.1-gnu1/arch/m68k/Kconfig.nommu	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Kconfig.nommu	1969-12-31 19:00:00.000000000 -0500
@@ -1,787 +0,0 @@
-config FPU
-	bool
-	default n
-
-config GENERIC_GPIO
-	bool
-	default n
-
-config GENERIC_CMOS_UPDATE
-	bool
-	default y
-
-config GENERIC_CLOCKEVENTS
-	bool
-	default n
-
-config M68000
-	bool
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale (was Motorola) 68000 CPU is the first generation of
-	  the well known M68K family of processors. The CPU core as well as
-	  being available as a stand alone CPU was also used in many
-	  System-On-Chip devices (eg 68328, 68302, etc). It does not contain
-	  a paging MMU.
-
-config MCPU32
-	bool
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale (was then Motorola) CPU32 is a CPU core that is
-	  based on the 68020 processor. For the most part it is used in
-	  System-On-Chip parts, and does not contain a paging MMU.
-
-config COLDFIRE
-	bool
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale ColdFire family of processors is a modern derivitive
-	  of the 68000 processor family. They are mainly targeted at embedded
-	  applications, and are all System-On-Chip (SOC) devices, as opposed
-	  to stand alone CPUs. They implement a subset of the original 68000
-	  processor instruction set.
-
-config COLDFIRE_SW_A7
-	bool
-	default n
-
-config HAVE_CACHE_SPLIT
-	bool
-
-config HAVE_CACHE_CB
-	bool
-
-config HAVE_MBAR
-	bool
-
-config HAVE_IPSBAR
-	bool
-
-choice
-	prompt "CPU"
-	default M68EZ328
-
-config M68328
-	bool "MC68328"
-	select M68000
-	help
-	  Motorola 68328 processor support.
-
-config M68EZ328
-	bool "MC68EZ328"
-	select M68000
-	help
-	  Motorola 68EX328 processor support.
-
-config M68VZ328
-	bool "MC68VZ328"
-	select M68000
-	help
-	  Motorola 68VZ328 processor support.
-
-config M68360
-	bool "MC68360"
-	select MCPU32
-	help
-	  Motorola 68360 processor support.
-
-config M5206
-	bool "MCF5206"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5206 processor support.
-
-config M5206e
-	bool "MCF5206e"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5206e processor support.
-
-config M520x
-	bool "MCF520x"
-	select COLDFIRE
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	help
-	   Freescale Coldfire 5207/5208 processor support.
-
-config M523x
-	bool "MCF523x"
-	select COLDFIRE
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Freescale Coldfire 5230/1/2/4/5 processor support
-
-config M5249
-	bool "MCF5249"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5249 processor support.
-
-config M5271
-	bool "MCF5271"
-	select COLDFIRE
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Freescale (Motorola) ColdFire 5270/5271 processor support.
-
-config M5272
-	bool "MCF5272"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5272 processor support.
-
-config M5275
-	bool "MCF5275"
-	select COLDFIRE
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Freescale (Motorola) ColdFire 5274/5275 processor support.
-
-config M528x
-	bool "MCF528x"
-	select COLDFIRE
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Motorola ColdFire 5280/5282 processor support.
-
-config M5307
-	bool "MCF5307"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5307 processor support.
-
-config M532x
-	bool "MCF532x"
-	select COLDFIRE
-	select HAVE_CACHE_CB
-	help
-	  Freescale (Motorola) ColdFire 532x processor support.
-
-config M5407
-	bool "MCF5407"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5407 processor support.
-
-config M547x
-	bool "MCF547x"
-	select COLDFIRE
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
-
-config M548x
-	bool "MCF548x"
-	select COLDFIRE
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
-
-endchoice
-
-config M527x
-	bool
-	depends on (M5271 || M5275)
-	select GENERIC_CLOCKEVENTS
-	default y
-
-config M54xx
-	bool
-	depends on (M548x || M547x)
-	default y
-
-config CLOCK_SET
-	bool "Enable setting the CPU clock frequency"
-	default n
-	help
-	  On some CPU's you do not need to know what the core CPU clock
-	  frequency is. On these you can disable clock setting. On some
-	  traditional 68K parts, and on all ColdFire parts you need to set
-	  the appropriate CPU clock frequency. On these devices many of the
-	  onboard peripherals derive their timing from the master CPU clock
-	  frequency.
-
-config CLOCK_FREQ
-	int "Set the core clock frequency"
-	default "66666666"
-	depends on CLOCK_SET
-	help
-	  Define the CPU clock frequency in use. This is the core clock
-	  frequency, it may or may not be the same as the external clock
-	  crystal fitted to your board. Some processors have an internal
-	  PLL and can have their frequency programmed at run time, others
-	  use internal dividers. In general the kernel won't setup a PLL
-	  if it is fitted (there are some exceptions). This value will be
-	  specific to the exact CPU that you are using.
-
-config OLDMASK
-	bool "Old mask 5307 (1H55J) silicon"
-	depends on M5307
-	help
-	  Build support for the older revision ColdFire 5307 silicon.
-	  Specifically this is the 1H55J mask revision.
-
-if HAVE_CACHE_SPLIT
-choice
-	prompt "Split Cache Configuration"
-	default CACHE_I
-
-config CACHE_I
-	bool "Instruction"
-	help
-	  Use all of the ColdFire CPU cache memory as an instruction cache.
-
-config CACHE_D
-	bool "Data"
-	help
-	  Use all of the ColdFire CPU cache memory as a data cache.
-
-config CACHE_BOTH
-	bool "Both"
-	help
-	  Split the ColdFire CPU cache, and use half as an instruction cache
-	  and half as a data cache.
-endchoice
-endif
-
-if HAVE_CACHE_CB
-choice
-	prompt "Data cache mode"
-	default CACHE_WRITETHRU
-
-config CACHE_WRITETHRU
-	bool "Write-through"
-	help
-	  The ColdFire CPU cache is set into Write-through mode.
-
-config CACHE_COPYBACK
-	bool "Copy-back"
-	help
-	  The ColdFire CPU cache is set into Copy-back mode.
-endchoice
-endif
-
-comment "Platform"
-
-config PILOT3
-	bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
-	depends on M68328
-	help
-	  Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
-
-config XCOPILOT_BUGS
-	bool "(X)Copilot support"
-	depends on PILOT3
-	help
-	  Support the bugs of Xcopilot.
-
-config UC5272
-	bool 'Arcturus Networks uC5272 dimm board support'
-	depends on M5272
-	help
-	  Support for the Arcturus Networks uC5272 dimm board.
-
-config UC5282
-	bool "Arcturus Networks uC5282 board support"
-	depends on M528x
-	help
-	  Support for the Arcturus Networks uC5282 dimm board.
-
-config UCSIMM
-	bool "uCsimm module support"
-	depends on M68EZ328
-	help
-	  Support for the Arcturus Networks uCsimm module.
-
-config UCDIMM
-	bool "uDsimm module support"
-	depends on M68VZ328
-	help
-	  Support for the Arcturus Networks uDsimm module.
-
-config DRAGEN2
-	bool "DragenEngine II board support"
-	depends on M68VZ328
-	help
-	  Support for the DragenEngine II board.
-
-config DIRECT_IO_ACCESS
-	bool "Allow user to access IO directly"
-	depends on (UCSIMM || UCDIMM || DRAGEN2)
-	help
-	  Disable the CPU internal registers protection in user mode,
-	  to allow a user application to read/write them.
-
-config INIT_LCD
-	bool "Initialize LCD"
-	depends on (UCSIMM || UCDIMM || DRAGEN2)
-	help
-	  Initialize the LCD controller of the 68x328 processor.
-
-config MEMORY_RESERVE
-	int "Memory reservation (MiB)"
-	depends on (UCSIMM || UCDIMM)
-	help
-	  Reserve certain memory regions on 68x328 based boards.
-
-config UCQUICC
-	bool "Lineo uCquicc board support"
-	depends on M68360
-	help
-	  Support for the Lineo uCquicc board.
-
-config ARN5206
-	bool "Arnewsh 5206 board support"
-	depends on M5206
-	help
-	  Support for the Arnewsh 5206 board.
-
-config M5206eC3
-	bool "Motorola M5206eC3 board support"
-	depends on M5206e
-	help
-	  Support for the Motorola M5206eC3 board.
-
-config ELITE
-	bool "Motorola M5206eLITE board support"
-	depends on M5206e
-	help
-	  Support for the Motorola M5206eLITE board.
-
-config M5208EVB
-	bool "Freescale M5208EVB board support"
-	depends on M520x
-	help
-	  Support for the Freescale Coldfire M5208EVB.
-
-config M5235EVB
-	bool "Freescale M5235EVB support"
-	depends on M523x
-	help
-	  Support for the Freescale M5235EVB board.
-
-config M5249C3
-	bool "Motorola M5249C3 board support"
-	depends on M5249
-	help
-	  Support for the Motorola M5249C3 board.
-
-config M5271EVB
-	bool "Freescale (Motorola) M5271EVB board support"
-	depends on M5271
-	help
-	  Support for the Freescale (Motorola) M5271EVB board.
-
-config M5275EVB
-	bool "Freescale (Motorola) M5275EVB board support"
-	depends on M5275
-	help
-	  Support for the Freescale (Motorola) M5275EVB board.
-
-config M5272C3
-	bool "Motorola M5272C3 board support"
-	depends on M5272
-	help
-	  Support for the Motorola M5272C3 board.
-
-config COBRA5272
-	bool "senTec COBRA5272 board support"
-	depends on M5272
-	help
-	  Support for the senTec COBRA5272 board.
-
-config AVNET5282
-	bool "Avnet 5282 board support"
-	depends on M528x
-	help
-	  Support for the Avnet 5282 board.  
-	  
-config M5282EVB
-	bool "Motorola M5282EVB board support"
-	depends on M528x
-	help
-	  Support for the Motorola M5282EVB board.
-
-config COBRA5282
-	bool "senTec COBRA5282 board support"
-	depends on M528x
-	help
-	  Support for the senTec COBRA5282 board.
-	  
-config SOM5282EM
-	bool "EMAC.Inc SOM5282EM board support"
-	depends on M528x
-	help
-	  Support for the EMAC.Inc SOM5282EM module.  
-	  
-config WILDFIRE
-	bool "Intec Automation Inc. WildFire board support"
-	depends on M528x
-	help
-	  Support for the Intec Automation Inc. WildFire.
-	  
-config WILDFIREMOD
-	bool "Intec Automation Inc. WildFire module support"
-	depends on M528x
-	help
-	  Support for the Intec Automation Inc. WildFire module.
-
-config ARN5307
-	bool "Arnewsh 5307 board support"
-	depends on M5307
-	help
-	  Support for the Arnewsh 5307 board.
-
-config M5307C3
-	bool "Motorola M5307C3 board support"
-	depends on M5307
-	help
-	  Support for the Motorola M5307C3 board.
-
-config SECUREEDGEMP3
-	bool "SnapGear SecureEdge/MP3 platform support"
-	depends on M5307
-	help
-	  Support for the SnapGear SecureEdge/MP3 platform.
-
-config M5329EVB
-	bool "Freescale (Motorola) M5329EVB board support"
-	depends on M532x
-	help
-	  Support for the Freescale (Motorola) M5329EVB board.
-
-config COBRA5329
-	bool "senTec COBRA5329 board support"
-	depends on M532x
-	help
-	  Support for the senTec COBRA5329 board.
-
-config M5407C3
-	bool "Motorola M5407C3 board support"
-	depends on M5407
-	help
-	  Support for the Motorola M5407C3 board.
-
-config FIREBEE
-	bool "FireBee board support"
-	depends on M547x
-	help
-	  Support for the FireBee ColdFire 5475 based board.
-
-config CLEOPATRA
-	bool "Feith CLEOPATRA board support"
-	depends on (M5307 || M5407)
-	help
-	  Support for the Feith Cleopatra boards.
-
-config CANCam
-	bool "Feith CANCam board support"
-	depends on M5272
-	help
-	  Support for the Feith CANCam board.
-
-config SCALES
-	bool "Feith SCALES board support"
-	depends on M5272
-	help
-	  Support for the Feith SCALES board.
-
-config NETtel
-	bool "SecureEdge/NETtel board support"
-	depends on (M5206e || M5272 || M5307)
-	help
-	  Support for the SnapGear NETtel/SecureEdge/SnapGear boards.
-
-config SNAPGEAR
-	bool "SnapGear router board support"
-	depends on NETtel
-	help
-	  Special additional support for SnapGear router boards.
-
-config CPU16B
-	bool "Sneha Technologies S.L. Sarasvati board support"
-	depends on M5272
-	help
-	  Support for the SNEHA CPU16B board.
-
-config MOD5272
-	bool "Netburner MOD-5272 board support"
-	depends on M5272
-	help
-	  Support for the Netburner MOD-5272 board.
-
-config SAVANTrosie1
-	bool "Savant Rosie1 board support"
-	depends on M523x
-	help
-	  Support for the Savant Rosie1 board.
-
-config ROMFS_FROM_ROM
-	bool "ROMFS image not RAM resident"
-	depends on (NETtel || SNAPGEAR)
-	help
-	  The ROMfs filesystem will stay resident in the FLASH/ROM, not be
-	  moved into RAM.
-
-config PILOT
-	bool
-	default y
-	depends on (PILOT3 || PILOT5)
-
-config ARNEWSH
-	bool
-	default y
-	depends on (ARN5206 || ARN5307)
-
-config FREESCALE
-	bool
-	default y
-	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3)
-
-config HW_FEITH
-	bool
-	default y
-	depends on (CLEOPATRA || CANCam || SCALES)
-
-config senTec
-	bool
-	default y
-	depends on (COBRA5272 || COBRA5282)
-	
-config EMAC_INC
-	bool
-	default y
-	depends on (SOM5282EM)
-
-config SNEHA
-	bool
-	default y
-	depends on CPU16B
-
-config SAVANT
-	bool
-	default y
-	depends on SAVANTrosie1
-
-config AVNET
-	bool
-	default y
-	depends on (AVNET5282)
-
-config UBOOT
-	bool "Support for U-Boot command line parameters"
-	help
-	  If you say Y here kernel will try to collect command
-	  line parameters from the initial u-boot stack.
-	default n
-
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	default y
-	help
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations.
-
-comment "RAM configuration"
-
-config RAMBASE
-	hex "Address of the base of RAM"
-	default "0"
-	help
-	  Define the address that RAM starts at. On many platforms this is
-	  0, the base of the address space. And this is the default. Some
-	  platforms choose to setup their RAM at other addresses within the
-	  processor address space.
-
-config RAMSIZE
-	hex "Size of RAM (in bytes), or 0 for automatic"
-	default "0x400000"
-	help
-	  Define the size of the system RAM. If you select 0 then the
-	  kernel will try to probe the RAM size at runtime. This is not
-	  supported on all CPU types.
-
-config VECTORBASE
-	hex "Address of the base of system vectors"
-	default "0"
-	help
-	  Define the address of the system vectors. Commonly this is
-	  put at the start of RAM, but it doesn't have to be. On ColdFire
-	  platforms this address is programmed into the VBR register, thus
-	  actually setting the address to use.
-
-config MBAR
-	hex "Address of the MBAR (internal peripherals)"
-	default "0x10000000"
-	depends on HAVE_MBAR
-	help
-	  Define the address of the internal system peripherals. This value
-	  is set in the processors MBAR register. This is generally setup by
-	  the boot loader, and will not be written by the kernel. By far most
-	  ColdFire boards use the default 0x10000000 value, so if unsure then
-	  use this.
-
-config IPSBAR
-	hex "Address of the IPSBAR (internal peripherals)"
-	default "0x40000000"
-	depends on HAVE_IPSBAR
-	help
-	  Define the address of the internal system peripherals. This value
-	  is set in the processors IPSBAR register. This is generally setup by
-	  the boot loader, and will not be written by the kernel. By far most
-	  ColdFire boards use the default 0x40000000 value, so if unsure then
-	  use this.
-
-config KERNELBASE
-	hex "Address of the base of kernel code"
-	default "0x400"
-	help
-	  Typically on m68k systems the kernel will not start at the base
-	  of RAM, but usually some small offset from it. Define the start
-	  address of the kernel here. The most common setup will have the
-	  processor vectors at the base of RAM and then the start of the
-	  kernel. On some platforms some RAM is reserved for boot loaders
-	  and the kernel starts after that. The 0x400 default was based on
-	  a system with the RAM based at address 0, and leaving enough room
-	  for the theoretical maximum number of 256 vectors.
-
-choice
-	prompt "RAM bus width"
-	default RAMAUTOBIT
-
-config RAMAUTOBIT
-	bool "AUTO"
-	help
-	  Select the physical RAM data bus size. Not needed on most platforms,
-	  so you can generally choose AUTO.
-
-config RAM8BIT
-	bool "8bit"
-	help
-	  Configure RAM bus to be 8 bits wide.
-
-config RAM16BIT
-	bool "16bit"
-	help
-	  Configure RAM bus to be 16 bits wide.
-
-config RAM32BIT
-	bool "32bit"
-	help
-	  Configure RAM bus to be 32 bits wide.
-
-endchoice
-
-comment "ROM configuration"
-
-config ROM
-	bool "Specify ROM linker regions"
-	default n
-	help
-	  Define a ROM region for the linker script. This creates a kernel
-	  that can be stored in flash, with possibly the text, and data
-	  regions being copied out to RAM at startup.
-
-config ROMBASE
-	hex "Address of the base of ROM device"
-	default "0"
-	depends on ROM
-	help
-	  Define the address that the ROM region starts at. Some platforms
-	  use this to set their chip select region accordingly for the boot
-	  device.
-
-config ROMVEC
-	hex "Address of the base of the ROM vectors"
-	default "0"
-	depends on ROM
-	help
-	  This is almost always the same as the base of the ROM. Since on all
-	  68000 type variants the vectors are at the base of the boot device
-	  on system startup.
-
-config ROMVECSIZE
-	hex "Size of ROM vector region (in bytes)"
-	default "0x400"
-	depends on ROM
-	help
-	  Define the size of the vector region in ROM. For most 68000
-	  variants this would be 0x400 bytes in size. Set to 0 if you do
-	  not want a vector region at the start of the ROM.
-
-config ROMSTART
-	hex "Address of the base of system image in ROM"
-	default "0x400"
-	depends on ROM
-	help
-	  Define the start address of the system image in ROM. Commonly this
-	  is strait after the ROM vectors.
-
-config ROMSIZE
-	hex "Size of the ROM device"
-	default "0x100000"
-	depends on ROM
-	help
-	  Size of the ROM device. On some platforms this is used to setup
-	  the chip select that controls the boot ROM device.
-
-choice
-	prompt "Kernel executes from"
-	---help---
-	  Choose the memory type that the kernel will be running in.
-
-config RAMKERNEL
-	bool "RAM"
-	help
-	  The kernel will be resident in RAM when running.
-
-config ROMKERNEL
-	bool "ROM"
-	help
-	  The kernel will be resident in FLASH/ROM when running. This is
-	  often referred to as Execute-in-Place (XIP), since the kernel
-	  code executes from the position it is stored in the FLASH/ROM.
-
-endchoice
-
-if COLDFIRE
-source "kernel/Kconfig.preempt"
-endif
-
-source "kernel/time/Kconfig"
-
-config ISA_DMA_API
-	bool
-	depends on !M5272
-	default y
-
-source "drivers/pcmcia/Kconfig"
-
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/dma_mm.c linux-libre-3.2-gnu1/arch/m68k/kernel/dma_mm.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/dma_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/dma_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 
 #include <asm/pgalloc.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/dma_no.c linux-libre-3.2-gnu1/arch/m68k/kernel/dma_no.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/dma_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/dma_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <asm/cacheflush.h>
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/entry_mm.S linux-libre-3.2-gnu1/arch/m68k/kernel/entry_mm.S
--- linux-libre-3.1-gnu1/arch/m68k/kernel/entry_mm.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/entry_mm.S	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,7 @@
 .globl sys_fork, sys_clone, sys_vfork
 .globl ret_from_interrupt, bad_interrupt
 .globl auto_irqhandler_fixup
-.globl user_irqvec_fixup, user_irqhandler_fixup
+.globl user_irqvec_fixup
 
 .text
 ENTRY(buserr)
@@ -207,7 +207,7 @@ ENTRY(auto_inthandler)
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
 auto_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
+	jsr	do_IRQ			|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 ret_from_interrupt:
@@ -240,8 +240,7 @@ user_irqvec_fixup = . + 2
 
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
-user_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
+	jsr	do_IRQ			|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/entry_no.S linux-libre-3.2-gnu1/arch/m68k/kernel/entry_no.S
--- linux-libre-3.1-gnu1/arch/m68k/kernel/entry_no.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/entry_no.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 .globl sys_vfork
 
 ENTRY(buserr)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
@@ -52,7 +52,7 @@ ENTRY(buserr)
 	jra	ret_from_exception
 
 ENTRY(trap)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
@@ -64,7 +64,7 @@ ENTRY(trap)
 
 .globl dbginterrupt
 ENTRY(dbginterrupt)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/ints.c linux-libre-3.2-gnu1/arch/m68k/kernel/ints.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,25 +4,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 07/03/96: Timer initialization, and thus mach_sched_init(),
- *           removed from request_irq() and moved to init_time().
- *           We should therefore consider renaming our add_isr() and
- *           remove_isr() to request_irq() and free_irq()
- *           respectively, so they are compliant with the other
- *           architectures.                                     /Jes
- * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
- *           Removed irq list support, if any machine needs an irq server
- *           it must implement this itself (as it's already done), instead
- *           only default handler are used with mach_default_handler.
- *           request_irq got some flags different from other architectures:
- *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
- *                               can be replaced without this flag)
- *           - IRQ_FLG_LOCK : handler can't be replaced
- *           There are other machine depending flags, see there
- *           If you want to replace a default handler you should know what
- *           you're doing, since it might handle different other irq sources
- *           which must be served                               /Roman Zippel
  */
 
 #include <linux/module.h>
@@ -47,33 +28,22 @@
 #endif
 
 extern u32 auto_irqhandler_fixup[];
-extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
 
-/* table for system interrupt handlers */
-static struct irq_node *irq_list[NR_IRQS];
-static struct irq_controller *irq_controller[NR_IRQS];
-static int irq_depth[NR_IRQS];
-
 static int m68k_first_user_vec;
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
 	.name		= "auto",
-	.lock		= __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
 };
 
-static struct irq_controller user_irq_controller = {
+static struct irq_chip user_irq_chip = {
 	.name		= "user",
-	.lock		= __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
 };
 
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
 /*
  * void init_IRQ(void)
  *
@@ -96,7 +66,7 @@ void __init init_IRQ(void)
 	}
 
 	for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
-		irq_controller[i] = &auto_irq_controller;
+		irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
 	mach_init_IRQ();
 }
@@ -106,7 +76,7 @@ void __init init_IRQ(void)
  * @handler: called from auto vector interrupts
  *
  * setup the handler to be called from auto vector interrupts instead of the
- * standard __m68k_handle_int(), it will be called with irq numbers in the range
+ * standard do_IRQ(), it will be called with irq numbers in the range
  * from IRQ_AUTO_1 - IRQ_AUTO_7.
  */
 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
@@ -120,217 +90,49 @@ void __init m68k_setup_auto_interrupt(vo
  * m68k_setup_user_interrupt
  * @vec: first user vector interrupt to handle
  * @cnt: number of active user vector interrupts
- * @handler: called from user vector interrupts
  *
  * setup user vector interrupts, this includes activating the specified range
  * of interrupts, only then these interrupts can be requested (note: this is
- * different from auto vector interrupts). An optional handler can be installed
- * to be called instead of the default __m68k_handle_int(), it will be called
- * with irq numbers starting from IRQ_USER.
+ * different from auto vector interrupts).
  */
-void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-				      void (*handler)(unsigned int, struct pt_regs *))
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)
 {
 	int i;
 
 	BUG_ON(IRQ_USER + cnt > NR_IRQS);
 	m68k_first_user_vec = vec;
 	for (i = 0; i < cnt; i++)
-		irq_controller[IRQ_USER + i] = &user_irq_controller;
+		irq_set_chip(IRQ_USER + i, &user_irq_chip);
 	*user_irqvec_fixup = vec - IRQ_USER;
-	if (handler)
-		*user_irqhandler_fixup = (u32)handler;
 	flush_icache();
 }
 
 /**
  * m68k_setup_irq_controller
- * @contr: irq controller which controls specified irq
+ * @chip: irq chip which controls specified irq
+ * @handle: flow handler which handles specified irq
  * @irq: first irq to be managed by the controller
+ * @cnt: number of irqs to be managed by the controller
  *
  * Change the controller for the specified range of irq, which will be used to
  * manage these irq. auto/user irq already have a default controller, which can
  * be changed as well, but the controller probably should use m68k_irq_startup/
  * m68k_irq_shutdown.
  */
-void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+void m68k_setup_irq_controller(struct irq_chip *chip,
+			       irq_flow_handler_t handle, unsigned int irq,
 			       unsigned int cnt)
 {
 	int i;
 
-	for (i = 0; i < cnt; i++)
-		irq_controller[irq + i] = contr;
-}
-
-irq_node_t *new_irq_node(void)
-{
-	irq_node_t *node;
-	short i;
-
-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
-		if (!node->handler) {
-			memset(node, 0, sizeof(*node));
-			return node;
-		}
-	}
-
-	printk ("new_irq_node: out of nodes\n");
-	return NULL;
-}
-
-int setup_irq(unsigned int irq, struct irq_node *node)
-{
-	struct irq_controller *contr;
-	struct irq_node **prev;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d from %s\n",
-		       __func__, irq, node->devname);
-		return -ENXIO;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-
-	prev = irq_list + irq;
-	if (*prev) {
-		/* Can't share interrupts unless both agree to */
-		if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
-			spin_unlock_irqrestore(&contr->lock, flags);
-			return -EBUSY;
-		}
-		while (*prev)
-			prev = &(*prev)->next;
-	}
-
-	if (!irq_list[irq]) {
-		if (contr->startup)
-			contr->startup(irq);
-		else
-			contr->enable(irq);
-	}
-	node->next = NULL;
-	*prev = node;
-
-	spin_unlock_irqrestore(&contr->lock, flags);
-
-	return 0;
-}
-
-int request_irq(unsigned int irq,
-		irq_handler_t handler,
-		unsigned long flags, const char *devname, void *dev_id)
-{
-	struct irq_node *node;
-	int res;
-
-	node = new_irq_node();
-	if (!node)
-		return -ENOMEM;
-
-	node->handler = handler;
-	node->flags   = flags;
-	node->dev_id  = dev_id;
-	node->devname = devname;
-
-	res = setup_irq(irq, node);
-	if (res)
-		node->handler = NULL;
-
-	return res;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	struct irq_controller *contr;
-	struct irq_node **p, *node;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n", __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-
-	p = irq_list + irq;
-	while ((node = *p)) {
-		if (node->dev_id == dev_id)
-			break;
-		p = &node->next;
-	}
-
-	if (node) {
-		*p = node->next;
-		node->handler = NULL;
-	} else
-		printk("%s: Removing probably wrong IRQ %d\n",
-		       __func__, irq);
-
-	if (!irq_list[irq]) {
-		if (contr->shutdown)
-			contr->shutdown(irq);
-		else
-			contr->disable(irq);
-	}
-
-	spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(free_irq);
-
-void enable_irq(unsigned int irq)
-{
-	struct irq_controller *contr;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n",
-		       __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-	if (irq_depth[irq]) {
-		if (!--irq_depth[irq]) {
-			if (contr->enable)
-				contr->enable(irq);
-		}
-	} else
-		WARN_ON(1);
-	spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(enable_irq);
-
-void disable_irq(unsigned int irq)
-{
-	struct irq_controller *contr;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n",
-		       __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-	if (!irq_depth[irq]++) {
-		if (contr->disable)
-			contr->disable(irq);
+	for (i = 0; i < cnt; i++) {
+		irq_set_chip(irq + i, chip);
+		if (handle)
+			irq_set_handler(irq + i, handle);
 	}
-	spin_unlock_irqrestore(&contr->lock, flags);
 }
 
-EXPORT_SYMBOL(disable_irq);
-
-void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
-
-EXPORT_SYMBOL(disable_irq_nosync);
-
-int m68k_irq_startup(unsigned int irq)
+unsigned int m68k_irq_startup_irq(unsigned int irq)
 {
 	if (irq <= IRQ_AUTO_7)
 		vectors[VEC_SPUR + irq] = auto_inthandler;
@@ -339,41 +141,21 @@ int m68k_irq_startup(unsigned int irq)
 	return 0;
 }
 
-void m68k_irq_shutdown(unsigned int irq)
+unsigned int m68k_irq_startup(struct irq_data *data)
 {
-	if (irq <= IRQ_AUTO_7)
-		vectors[VEC_SPUR + irq] = bad_inthandler;
-	else
-		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+	return m68k_irq_startup_irq(data->irq);
 }
 
-
-/*
- * Do we need these probe functions on the m68k?
- *
- *  ... may be useful with ISA devices
- */
-unsigned long probe_irq_on (void)
+void m68k_irq_shutdown(struct irq_data *data)
 {
-#ifdef CONFIG_Q40
-	if (MACH_IS_Q40)
-		return q40_probe_irq_on();
-#endif
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
+	unsigned int irq = data->irq;
 
-int probe_irq_off (unsigned long irqs)
-{
-#ifdef CONFIG_Q40
-	if (MACH_IS_Q40)
-		return q40_probe_irq_off(irqs);
-#endif
-	return 0;
+	if (irq <= IRQ_AUTO_7)
+		vectors[VEC_SPUR + irq] = bad_inthandler;
+	else
+		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
 }
 
-EXPORT_SYMBOL(probe_irq_off);
 
 unsigned int irq_canonicalize(unsigned int irq)
 {
@@ -386,52 +168,9 @@ unsigned int irq_canonicalize(unsigned i
 
 EXPORT_SYMBOL(irq_canonicalize);
 
-asmlinkage void m68k_handle_int(unsigned int irq)
-{
-	struct irq_node *node;
-	kstat_cpu(0).irqs[irq]++;
-	node = irq_list[irq];
-	do {
-		node->handler(irq, node->dev_id);
-		node = node->next;
-	} while (node);
-}
-
-asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
-{
-	struct pt_regs *old_regs;
-	old_regs = set_irq_regs(regs);
-	m68k_handle_int(irq);
-	set_irq_regs(old_regs);
-}
 
 asmlinkage void handle_badint(struct pt_regs *regs)
 {
-	kstat_cpu(0).irqs[0]++;
-	printk("unexpected interrupt from %u\n", regs->vector);
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	struct irq_controller *contr;
-	struct irq_node *node;
-	int i = *(loff_t *) v;
-
-	/* autovector interrupts */
-	if (irq_list[i]) {
-		contr = irq_controller[i];
-		node = irq_list[i];
-		seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
-		while ((node = node->next))
-			seq_printf(p, ", %s", node->devname);
-		seq_puts(p, "\n");
-	}
-	return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-void init_irq_proc(void)
-{
-	/* Insert /proc/irq driver here */
+	atomic_inc(&irq_err_count);
+	pr_warn("unexpected interrupt from %u\n", regs->vector);
 }
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,20 @@
-ifdef CONFIG_MMU
-include arch/m68k/kernel/Makefile_mm
-else
-include arch/m68k/kernel/Makefile_no
+#
+# Makefile for the linux kernel.
+#
+
+extra-$(CONFIG_MMU)	:= head.o
+extra-$(CONFIG_SUN3)	:= sun3-head.o
+extra-y			+= vmlinux.lds
+
+obj-y	:= entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \
+	   signal.o sys_m68k.o syscalltable.o time.o traps.o
+
+obj-$(CONFIG_MMU)	+= ints.o vectors.o
+
+ifndef CONFIG_MMU_SUN3
+obj-y			+= dma.o
 endif
+ifndef CONFIG_MMU
+obj-y			+= init_task.o
+endif
+
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile_mm linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile_mm
--- linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile_mm	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-ifndef CONFIG_SUN3
-  extra-y := head.o
-else
-  extra-y := sun3-head.o
-endif
-extra-y	+= vmlinux.lds
-
-obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
-	   sys_m68k.o time.o setup.o m68k_ksyms.o devres.o syscalltable.o
-
-devres-y = ../../../kernel/irq/devres.o
-
-obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile_no linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile_no
--- linux-libre-3.1-gnu1/arch/m68k/kernel/Makefile_no	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/Makefile_no	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Makefile for arch/m68knommu/kernel.
-#
-
-extra-y := vmlinux.lds
-
-obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
-	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
-
-obj-$(CONFIG_MODULES)	+= module.o
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/setup_no.c linux-libre-3.2-gnu1/arch/m68k/kernel/setup_no.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/setup_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/setup_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <asm/irq.h>
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
+#include <asm/sections.h>
 
 unsigned long memory_start;
 unsigned long memory_end;
@@ -80,9 +81,6 @@ void (*mach_power_off)(void);
 #define	CPU_INSTR_PER_JIFFY	16
 #endif
 
-extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
-extern int _ramstart, _ramend;
-
 #if defined(CONFIG_UBOOT)
 /*
  * parse_uboot_commandline
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/syscalltable.S linux-libre-3.2-gnu1/arch/m68k/kernel/syscalltable.S
--- linux-libre-3.1-gnu1/arch/m68k/kernel/syscalltable.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/syscalltable.S	2012-01-04 18:55:44.000000000 -0500
@@ -365,4 +365,6 @@ ENTRY(sys_call_table)
 	.long sys_clock_adjtime
 	.long sys_syncfs
 	.long sys_setns
+	.long sys_process_vm_readv	/* 345 */
+	.long sys_process_vm_writev
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/traps.c linux-libre-3.2-gnu1/arch/m68k/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,1107 @@
-#ifdef CONFIG_MMU
-#include "traps_mm.c"
+/*
+ *  linux/arch/m68k/kernel/traps.c
+ *
+ *  Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ *  68040 fixes by Michael Rausch
+ *  68040 fixes by Martin Apel
+ *  68040 fixes and writeback by Richard Zidlicky
+ *  68060 fixes by Roman Hodek
+ *  68060 fixes by Jesper Skov
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/pgalloc.h>
+#include <asm/machdep.h>
+#include <asm/siginfo.h>
+
+
+static const char *vec_names[] = {
+	[VEC_RESETSP]	= "RESET SP",
+	[VEC_RESETPC]	= "RESET PC",
+	[VEC_BUSERR]	= "BUS ERROR",
+	[VEC_ADDRERR]	= "ADDRESS ERROR",
+	[VEC_ILLEGAL]	= "ILLEGAL INSTRUCTION",
+	[VEC_ZERODIV]	= "ZERO DIVIDE",
+	[VEC_CHK]	= "CHK",
+	[VEC_TRAP]	= "TRAPcc",
+	[VEC_PRIV]	= "PRIVILEGE VIOLATION",
+	[VEC_TRACE]	= "TRACE",
+	[VEC_LINE10]	= "LINE 1010",
+	[VEC_LINE11]	= "LINE 1111",
+	[VEC_RESV12]	= "UNASSIGNED RESERVED 12",
+	[VEC_COPROC]	= "COPROCESSOR PROTOCOL VIOLATION",
+	[VEC_FORMAT]	= "FORMAT ERROR",
+	[VEC_UNINT]	= "UNINITIALIZED INTERRUPT",
+	[VEC_RESV16]	= "UNASSIGNED RESERVED 16",
+	[VEC_RESV17]	= "UNASSIGNED RESERVED 17",
+	[VEC_RESV18]	= "UNASSIGNED RESERVED 18",
+	[VEC_RESV19]	= "UNASSIGNED RESERVED 19",
+	[VEC_RESV20]	= "UNASSIGNED RESERVED 20",
+	[VEC_RESV21]	= "UNASSIGNED RESERVED 21",
+	[VEC_RESV22]	= "UNASSIGNED RESERVED 22",
+	[VEC_RESV23]	= "UNASSIGNED RESERVED 23",
+	[VEC_SPUR]	= "SPURIOUS INTERRUPT",
+	[VEC_INT1]	= "LEVEL 1 INT",
+	[VEC_INT2]	= "LEVEL 2 INT",
+	[VEC_INT3]	= "LEVEL 3 INT",
+	[VEC_INT4]	= "LEVEL 4 INT",
+	[VEC_INT5]	= "LEVEL 5 INT",
+	[VEC_INT6]	= "LEVEL 6 INT",
+	[VEC_INT7]	= "LEVEL 7 INT",
+	[VEC_SYS]	= "SYSCALL",
+	[VEC_TRAP1]	= "TRAP #1",
+	[VEC_TRAP2]	= "TRAP #2",
+	[VEC_TRAP3]	= "TRAP #3",
+	[VEC_TRAP4]	= "TRAP #4",
+	[VEC_TRAP5]	= "TRAP #5",
+	[VEC_TRAP6]	= "TRAP #6",
+	[VEC_TRAP7]	= "TRAP #7",
+	[VEC_TRAP8]	= "TRAP #8",
+	[VEC_TRAP9]	= "TRAP #9",
+	[VEC_TRAP10]	= "TRAP #10",
+	[VEC_TRAP11]	= "TRAP #11",
+	[VEC_TRAP12]	= "TRAP #12",
+	[VEC_TRAP13]	= "TRAP #13",
+	[VEC_TRAP14]	= "TRAP #14",
+	[VEC_TRAP15]	= "TRAP #15",
+	[VEC_FPBRUC]	= "FPCP BSUN",
+	[VEC_FPIR]	= "FPCP INEXACT",
+	[VEC_FPDIVZ]	= "FPCP DIV BY 0",
+	[VEC_FPUNDER]	= "FPCP UNDERFLOW",
+	[VEC_FPOE]	= "FPCP OPERAND ERROR",
+	[VEC_FPOVER]	= "FPCP OVERFLOW",
+	[VEC_FPNAN]	= "FPCP SNAN",
+	[VEC_FPUNSUP]	= "FPCP UNSUPPORTED OPERATION",
+	[VEC_MMUCFG]	= "MMU CONFIGURATION ERROR",
+	[VEC_MMUILL]	= "MMU ILLEGAL OPERATION ERROR",
+	[VEC_MMUACC]	= "MMU ACCESS LEVEL VIOLATION ERROR",
+	[VEC_RESV59]	= "UNASSIGNED RESERVED 59",
+	[VEC_UNIMPEA]	= "UNASSIGNED RESERVED 60",
+	[VEC_UNIMPII]	= "UNASSIGNED RESERVED 61",
+	[VEC_RESV62]	= "UNASSIGNED RESERVED 62",
+	[VEC_RESV63]	= "UNASSIGNED RESERVED 63",
+};
+
+static const char *space_names[] = {
+	[0]		= "Space 0",
+	[USER_DATA]	= "User Data",
+	[USER_PROGRAM]	= "User Program",
+#ifndef CONFIG_SUN3
+	[3]		= "Space 3",
 #else
-#include "traps_no.c"
+	[FC_CONTROL]	= "Control",
+#endif
+	[4]		= "Space 4",
+	[SUPER_DATA]	= "Super Data",
+	[SUPER_PROGRAM]	= "Super Program",
+	[CPU_SPACE]	= "CPU"
+};
+
+void die_if_kernel(char *,struct pt_regs *,int);
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+                             unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
+
+asmlinkage void trap_c(struct frame *fp);
+
+#if defined (CONFIG_M68060)
+static inline void access_error060 (struct frame *fp)
+{
+	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
+
+#ifdef DEBUG
+	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
+#endif
+
+	if (fslw & MMU060_BPE) {
+		/* branch prediction error -> clear branch cache */
+		__asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
+				      "orl   #0x00400000,%/d0\n\t"
+				      "movec %/d0,%/cacr"
+				      : : : "d0" );
+		/* return if there's no other error */
+		if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
+			return;
+	}
+
+	if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
+		unsigned long errorcode;
+		unsigned long addr = fp->un.fmt4.effaddr;
+
+		if (fslw & MMU060_MA)
+			addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
+
+		errorcode = 1;
+		if (fslw & MMU060_DESC_ERR) {
+			__flush_tlb040_one(addr);
+			errorcode = 0;
+		}
+		if (fslw & MMU060_W)
+			errorcode |= 2;
+#ifdef DEBUG
+		printk("errorcode = %d\n", errorcode );
+#endif
+		do_page_fault(&fp->ptregs, addr, errorcode);
+	} else if (fslw & (MMU060_SEE)){
+		/* Software Emulation Error.
+		 * fault during mem_read/mem_write in ifpsp060/os.S
+		 */
+		send_fault_sig(&fp->ptregs);
+	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
+		   send_fault_sig(&fp->ptregs) > 0) {
+		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
+		printk( "68060 access error, fslw=%lx\n", fslw );
+		trap_c( fp );
+	}
+}
+#endif /* CONFIG_M68060 */
+
+#if defined (CONFIG_M68040)
+static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
+{
+	unsigned long mmusr;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(MAKE_MM_SEG(wbs));
+
+	if (iswrite)
+		asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
+	else
+		asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
+
+	asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
+
+	set_fs(old_fs);
+
+	return mmusr;
+}
+
+static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
+				   unsigned long wbd)
+{
+	int res = 0;
+	mm_segment_t old_fs = get_fs();
+
+	/* set_fs can not be moved, otherwise put_user() may oops */
+	set_fs(MAKE_MM_SEG(wbs));
+
+	switch (wbs & WBSIZ_040) {
+	case BA_SIZE_BYTE:
+		res = put_user(wbd & 0xff, (char __user *)wba);
+		break;
+	case BA_SIZE_WORD:
+		res = put_user(wbd & 0xffff, (short __user *)wba);
+		break;
+	case BA_SIZE_LONG:
+		res = put_user(wbd, (int __user *)wba);
+		break;
+	}
+
+	/* set_fs can not be moved, otherwise put_user() may oops */
+	set_fs(old_fs);
+
+
+#ifdef DEBUG
+	printk("do_040writeback1, res=%d\n",res);
+#endif
+
+	return res;
+}
+
+/* after an exception in a writeback the stack frame corresponding
+ * to that exception is discarded, set a few bits in the old frame
+ * to simulate what it should look like
+ */
+static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
+{
+	fp->un.fmt7.faddr = wba;
+	fp->un.fmt7.ssw = wbs & 0xff;
+	if (wba != current->thread.faddr)
+	    fp->un.fmt7.ssw |= MA_040;
+}
+
+static inline void do_040writebacks(struct frame *fp)
+{
+	int res = 0;
+#if 0
+	if (fp->un.fmt7.wb1s & WBV_040)
+		printk("access_error040: cannot handle 1st writeback. oops.\n");
+#endif
+
+	if ((fp->un.fmt7.wb2s & WBV_040) &&
+	    !(fp->un.fmt7.wb2s & WBTT_040)) {
+		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
+				       fp->un.fmt7.wb2d);
+		if (res)
+			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
+		else
+			fp->un.fmt7.wb2s = 0;
+	}
+
+	/* do the 2nd wb only if the first one was successful (except for a kernel wb) */
+	if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
+		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
+				       fp->un.fmt7.wb3d);
+		if (res)
+		    {
+			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
+
+			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
+			fp->un.fmt7.wb3s &= (~WBV_040);
+			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
+			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
+		    }
+		else
+			fp->un.fmt7.wb3s = 0;
+	}
+
+	if (res)
+		send_fault_sig(&fp->ptregs);
+}
+
+/*
+ * called from sigreturn(), must ensure userspace code didn't
+ * manipulate exception frame to circumvent protection, then complete
+ * pending writebacks
+ * we just clear TM2 to turn it into a userspace access
+ */
+asmlinkage void berr_040cleanup(struct frame *fp)
+{
+	fp->un.fmt7.wb2s &= ~4;
+	fp->un.fmt7.wb3s &= ~4;
+
+	do_040writebacks(fp);
+}
+
+static inline void access_error040(struct frame *fp)
+{
+	unsigned short ssw = fp->un.fmt7.ssw;
+	unsigned long mmusr;
+
+#ifdef DEBUG
+	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
+        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
+		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
+	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
+		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
+		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
+#endif
+
+	if (ssw & ATC_040) {
+		unsigned long addr = fp->un.fmt7.faddr;
+		unsigned long errorcode;
+
+		/*
+		 * The MMU status has to be determined AFTER the address
+		 * has been corrected if there was a misaligned access (MA).
+		 */
+		if (ssw & MA_040)
+			addr = (addr + 7) & -8;
+
+		/* MMU error, get the MMUSR info for this access */
+		mmusr = probe040(!(ssw & RW_040), addr, ssw);
+#ifdef DEBUG
+		printk("mmusr = %lx\n", mmusr);
+#endif
+		errorcode = 1;
+		if (!(mmusr & MMU_R_040)) {
+			/* clear the invalid atc entry */
+			__flush_tlb040_one(addr);
+			errorcode = 0;
+		}
+
+		/* despite what documentation seems to say, RMW
+		 * accesses have always both the LK and RW bits set */
+		if (!(ssw & RW_040) || (ssw & LK_040))
+			errorcode |= 2;
+
+		if (do_page_fault(&fp->ptregs, addr, errorcode)) {
+#ifdef DEBUG
+			printk("do_page_fault() !=0\n");
+#endif
+			if (user_mode(&fp->ptregs)){
+				/* delay writebacks after signal delivery */
+#ifdef DEBUG
+			        printk(".. was usermode - return\n");
+#endif
+				return;
+			}
+			/* disable writeback into user space from kernel
+			 * (if do_page_fault didn't fix the mapping,
+                         * the writeback won't do good)
+			 */
+disable_wb:
+#ifdef DEBUG
+			printk(".. disabling wb2\n");
+#endif
+			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
+				fp->un.fmt7.wb2s &= ~WBV_040;
+			if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
+				fp->un.fmt7.wb3s &= ~WBV_040;
+		}
+	} else {
+		/* In case of a bus error we either kill the process or expect
+		 * the kernel to catch the fault, which then is also responsible
+		 * for cleaning up the mess.
+		 */
+		current->thread.signo = SIGBUS;
+		current->thread.faddr = fp->un.fmt7.faddr;
+		if (send_fault_sig(&fp->ptregs) >= 0)
+			printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
+			       fp->un.fmt7.faddr);
+		goto disable_wb;
+	}
+
+	do_040writebacks(fp);
+}
+#endif /* CONFIG_M68040 */
+
+#if defined(CONFIG_SUN3)
+#include <asm/sun3mmu.h>
+
+extern int mmu_emu_handle_fault (unsigned long, int, int);
+
+/* sun3 version of bus_error030 */
+
+static inline void bus_error030 (struct frame *fp)
+{
+	unsigned char buserr_type = sun3_get_buserr ();
+	unsigned long addr, errorcode;
+	unsigned short ssw = fp->un.fmtb.ssw;
+	extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
+
+#ifdef DEBUG
+	if (ssw & (FC | FB))
+		printk ("Instruction fault at %#010lx\n",
+			ssw & FC ?
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+			:
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+	if (ssw & DF)
+		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+			ssw & RW ? "read" : "write",
+			fp->un.fmtb.daddr,
+			space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+	/*
+	 * Check if this page should be demand-mapped. This needs to go before
+	 * the testing for a bad kernel-space access (demand-mapping applies
+	 * to kernel accesses too).
+	 */
+
+	if ((ssw & DF)
+	    && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
+		if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
+			return;
+	}
+
+	/* Check for kernel-space pagefault (BAD). */
+	if (fp->ptregs.sr & PS_S) {
+		/* kernel fault must be a data fault to user space */
+		if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
+		     // try checking the kernel mappings before surrender
+		     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
+			  return;
+			/* instruction fault or kernel data fault! */
+			if (ssw & (FC | FB))
+				printk ("Instruction fault at %#010lx\n",
+					fp->ptregs.pc);
+			if (ssw & DF) {
+				/* was this fault incurred testing bus mappings? */
+				if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
+				   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
+					send_fault_sig(&fp->ptregs);
+					return;
+				}
+
+				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+					ssw & RW ? "read" : "write",
+					fp->un.fmtb.daddr,
+					space_names[ssw & DFC], fp->ptregs.pc);
+			}
+			printk ("BAD KERNEL BUSERR\n");
+
+			die_if_kernel("Oops", &fp->ptregs,0);
+			force_sig(SIGKILL, current);
+			return;
+		}
+	} else {
+		/* user fault */
+		if (!(ssw & (FC | FB)) && !(ssw & DF))
+			/* not an instruction fault or data fault! BAD */
+			panic ("USER BUSERR w/o instruction or data fault");
+	}
+
+
+	/* First handle the data fault, if any.  */
+	if (ssw & DF) {
+		addr = fp->un.fmtb.daddr;
+
+// errorcode bit 0:	0 -> no page		1 -> protection fault
+// errorcode bit 1:	0 -> read fault		1 -> write fault
+
+// (buserr_type & SUN3_BUSERR_PROTERR)	-> protection fault
+// (buserr_type & SUN3_BUSERR_INVALID)	-> invalid page fault
+
+		if (buserr_type & SUN3_BUSERR_PROTERR)
+			errorcode = 0x01;
+		else if (buserr_type & SUN3_BUSERR_INVALID)
+			errorcode = 0x00;
+		else {
+#ifdef DEBUG
+			printk ("*** unexpected busfault type=%#04x\n", buserr_type);
+			printk ("invalid %s access at %#lx from pc %#lx\n",
+				!(ssw & RW) ? "write" : "read", addr,
+				fp->ptregs.pc);
+#endif
+			die_if_kernel ("Oops", &fp->ptregs, buserr_type);
+			force_sig (SIGBUS, current);
+			return;
+		}
+
+//todo: wtf is RM bit? --m
+		if (!(ssw & RW) || ssw & RM)
+			errorcode |= 0x02;
+
+		/* Handle page fault. */
+		do_page_fault (&fp->ptregs, addr, errorcode);
+
+		/* Retry the data fault now. */
+		return;
+	}
+
+	/* Now handle the instruction fault. */
+
+	/* Get the fault address. */
+	if (fp->ptregs.format == 0xA)
+		addr = fp->ptregs.pc + 4;
+	else
+		addr = fp->un.fmtb.baddr;
+	if (ssw & FC)
+		addr -= 2;
+
+	if (buserr_type & SUN3_BUSERR_INVALID) {
+		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+			do_page_fault (&fp->ptregs, addr, 0);
+       } else {
+#ifdef DEBUG
+		printk ("protection fault on insn access (segv).\n");
+#endif
+		force_sig (SIGSEGV, current);
+       }
+}
+#else
+#if defined(CPU_M68020_OR_M68030)
+static inline void bus_error030 (struct frame *fp)
+{
+	volatile unsigned short temp;
+	unsigned short mmusr;
+	unsigned long addr, errorcode;
+	unsigned short ssw = fp->un.fmtb.ssw;
+#ifdef DEBUG
+	unsigned long desc;
+
+	printk ("pid = %x  ", current->pid);
+	printk ("SSW=%#06x  ", ssw);
+
+	if (ssw & (FC | FB))
+		printk ("Instruction fault at %#010lx\n",
+			ssw & FC ?
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+			:
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+	if (ssw & DF)
+		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+			ssw & RW ? "read" : "write",
+			fp->un.fmtb.daddr,
+			space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+	/* ++andreas: If a data fault and an instruction fault happen
+	   at the same time map in both pages.  */
+
+	/* First handle the data fault, if any.  */
+	if (ssw & DF) {
+		addr = fp->un.fmtb.daddr;
+
+#ifdef DEBUG
+		asm volatile ("ptestr %3,%2@,#7,%0\n\t"
+			      "pmove %%psr,%1@"
+			      : "=a&" (desc)
+			      : "a" (&temp), "a" (addr), "d" (ssw));
+#else
+		asm volatile ("ptestr %2,%1@,#7\n\t"
+			      "pmove %%psr,%0@"
+			      : : "a" (&temp), "a" (addr), "d" (ssw));
+#endif
+		mmusr = temp;
+
+#ifdef DEBUG
+		printk("mmusr is %#x for addr %#lx in task %p\n",
+		       mmusr, addr, current);
+		printk("descriptor address is %#lx, contents %#lx\n",
+		       __va(desc), *(unsigned long *)__va(desc));
+#endif
+
+		errorcode = (mmusr & MMU_I) ? 0 : 1;
+		if (!(ssw & RW) || (ssw & RM))
+			errorcode |= 2;
+
+		if (mmusr & (MMU_I | MMU_WP)) {
+			if (ssw & 4) {
+				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+				       ssw & RW ? "read" : "write",
+				       fp->un.fmtb.daddr,
+				       space_names[ssw & DFC], fp->ptregs.pc);
+				goto buserr;
+			}
+			/* Don't try to do anything further if an exception was
+			   handled. */
+			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
+				return;
+		} else if (!(mmusr & MMU_I)) {
+			/* probably a 020 cas fault */
+			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
+				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
+		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+			printk("invalid %s access at %#lx from pc %#lx\n",
+			       !(ssw & RW) ? "write" : "read", addr,
+			       fp->ptregs.pc);
+			die_if_kernel("Oops",&fp->ptregs,mmusr);
+			force_sig(SIGSEGV, current);
+			return;
+		} else {
+#if 0
+			static volatile long tlong;
+#endif
+
+			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
+			       !(ssw & RW) ? "write" : "read", addr,
+			       fp->ptregs.pc, ssw);
+			asm volatile ("ptestr #1,%1@,#0\n\t"
+				      "pmove %%psr,%0@"
+				      : /* no outputs */
+				      : "a" (&temp), "a" (addr));
+			mmusr = temp;
+
+			printk ("level 0 mmusr is %#x\n", mmusr);
+#if 0
+			asm volatile ("pmove %%tt0,%0@"
+				      : /* no outputs */
+				      : "a" (&tlong));
+			printk("tt0 is %#lx, ", tlong);
+			asm volatile ("pmove %%tt1,%0@"
+				      : /* no outputs */
+				      : "a" (&tlong));
+			printk("tt1 is %#lx\n", tlong);
+#endif
+#ifdef DEBUG
+			printk("Unknown SIGSEGV - 1\n");
+#endif
+			die_if_kernel("Oops",&fp->ptregs,mmusr);
+			force_sig(SIGSEGV, current);
+			return;
+		}
+
+		/* setup an ATC entry for the access about to be retried */
+		if (!(ssw & RW) || (ssw & RM))
+			asm volatile ("ploadw %1,%0@" : /* no outputs */
+				      : "a" (addr), "d" (ssw));
+		else
+			asm volatile ("ploadr %1,%0@" : /* no outputs */
+				      : "a" (addr), "d" (ssw));
+	}
+
+	/* Now handle the instruction fault. */
+
+	if (!(ssw & (FC|FB)))
+		return;
+
+	if (fp->ptregs.sr & PS_S) {
+		printk("Instruction fault at %#010lx\n",
+			fp->ptregs.pc);
+	buserr:
+		printk ("BAD KERNEL BUSERR\n");
+		die_if_kernel("Oops",&fp->ptregs,0);
+		force_sig(SIGKILL, current);
+		return;
+	}
+
+	/* get the fault address */
+	if (fp->ptregs.format == 10)
+		addr = fp->ptregs.pc + 4;
+	else
+		addr = fp->un.fmtb.baddr;
+	if (ssw & FC)
+		addr -= 2;
+
+	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
+		/* Insn fault on same page as data fault.  But we
+		   should still create the ATC entry.  */
+		goto create_atc_entry;
+
+#ifdef DEBUG
+	asm volatile ("ptestr #1,%2@,#7,%0\n\t"
+		      "pmove %%psr,%1@"
+		      : "=a&" (desc)
+		      : "a" (&temp), "a" (addr));
+#else
+	asm volatile ("ptestr #1,%1@,#7\n\t"
+		      "pmove %%psr,%0@"
+		      : : "a" (&temp), "a" (addr));
+#endif
+	mmusr = temp;
+
+#ifdef DEBUG
+	printk ("mmusr is %#x for addr %#lx in task %p\n",
+		mmusr, addr, current);
+	printk ("descriptor address is %#lx, contents %#lx\n",
+		__va(desc), *(unsigned long *)__va(desc));
+#endif
+
+	if (mmusr & MMU_I)
+		do_page_fault (&fp->ptregs, addr, 0);
+	else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+		printk ("invalid insn access at %#lx from pc %#lx\n",
+			addr, fp->ptregs.pc);
+#ifdef DEBUG
+		printk("Unknown SIGSEGV - 2\n");
+#endif
+		die_if_kernel("Oops",&fp->ptregs,mmusr);
+		force_sig(SIGSEGV, current);
+		return;
+	}
+
+create_atc_entry:
+	/* setup an ATC entry for the access about to be retried */
+	asm volatile ("ploadr #2,%0@" : /* no outputs */
+		      : "a" (addr));
+}
+#endif /* CPU_M68020_OR_M68030 */
+#endif /* !CONFIG_SUN3 */
+
+asmlinkage void buserr_c(struct frame *fp)
+{
+	/* Only set esp0 if coming from user mode */
+	if (user_mode(&fp->ptregs))
+		current->thread.esp0 = (unsigned long) fp;
+
+#ifdef DEBUG
+	printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
+#endif
+
+	switch (fp->ptregs.format) {
+#if defined (CONFIG_M68060)
+	case 4:				/* 68060 access error */
+	  access_error060 (fp);
+	  break;
+#endif
+#if defined (CONFIG_M68040)
+	case 0x7:			/* 68040 access error */
+	  access_error040 (fp);
+	  break;
+#endif
+#if defined (CPU_M68020_OR_M68030)
+	case 0xa:
+	case 0xb:
+	  bus_error030 (fp);
+	  break;
+#endif
+	default:
+	  die_if_kernel("bad frame format",&fp->ptregs,0);
+#ifdef DEBUG
+	  printk("Unknown SIGSEGV - 4\n");
+#endif
+	  force_sig(SIGSEGV, current);
+	}
+}
+
+
+static int kstack_depth_to_print = 48;
+
+void show_trace(unsigned long *stack)
+{
+	unsigned long *endstack;
+	unsigned long addr;
+	int i;
+
+	printk("Call Trace:");
+	addr = (unsigned long)stack + THREAD_SIZE - 1;
+	endstack = (unsigned long *)(addr & -THREAD_SIZE);
+	i = 0;
+	while (stack + 1 <= endstack) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (__kernel_text_address(addr)) {
+#ifndef CONFIG_KALLSYMS
+			if (i % 5 == 0)
+				printk("\n       ");
+#endif
+			printk(" [<%08lx>] %pS\n", addr, (void *)addr);
+			i++;
+		}
+	}
+	printk("\n");
+}
+
+void show_registers(struct pt_regs *regs)
+{
+	struct frame *fp = (struct frame *)regs;
+	mm_segment_t old_fs = get_fs();
+	u16 c, *cp;
+	unsigned long addr;
+	int i;
+
+	print_modules();
+	printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
+	printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
+	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+	       regs->d0, regs->d1, regs->d2, regs->d3);
+	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
+	       regs->d4, regs->d5, regs->a0, regs->a1);
+
+	printk("Process %s (pid: %d, task=%p)\n",
+		current->comm, task_pid_nr(current), current);
+	addr = (unsigned long)&fp->un;
+	printk("Frame format=%X ", regs->format);
+	switch (regs->format) {
+	case 0x2:
+		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+		addr += sizeof(fp->un.fmt2);
+		break;
+	case 0x3:
+		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+		addr += sizeof(fp->un.fmt3);
+		break;
+	case 0x4:
+		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
+			: "eff addr=%08lx pc=%08lx\n"),
+			fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+		addr += sizeof(fp->un.fmt4);
+		break;
+	case 0x7:
+		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
+		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
+		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
+		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
+		printk("push data: %08lx %08lx %08lx %08lx\n",
+			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
+			fp->un.fmt7.pd3);
+		addr += sizeof(fp->un.fmt7);
+		break;
+	case 0x9:
+		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+		addr += sizeof(fp->un.fmt9);
+		break;
+	case 0xa:
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
+			fp->un.fmta.daddr, fp->un.fmta.dobuf);
+		addr += sizeof(fp->un.fmta);
+		break;
+	case 0xb:
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
+			fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
+		printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
+		addr += sizeof(fp->un.fmtb);
+		break;
+	default:
+		printk("\n");
+	}
+	show_stack(NULL, (unsigned long *)addr);
+
+	printk("Code:");
+	set_fs(KERNEL_DS);
+	cp = (u16 *)regs->pc;
+	for (i = -8; i < 16; i++) {
+		if (get_user(c, cp + i) && i >= 0) {
+			printk(" Bad PC value.");
+			break;
+		}
+		printk(i ? " %04x" : " <%04x>", c);
+	}
+	set_fs(old_fs);
+	printk ("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long *p;
+	unsigned long *endstack;
+	int i;
+
+	if (!stack) {
+		if (task)
+			stack = (unsigned long *)task->thread.esp0;
+		else
+			stack = (unsigned long *)&stack;
+	}
+	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
+
+	printk("Stack from %08lx:", (unsigned long)stack);
+	p = stack;
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (p + 1 > endstack)
+			break;
+		if (i % 8 == 0)
+			printk("\n       ");
+		printk(" %08lx", *p++);
+	}
+	printk("\n");
+	show_trace(stack);
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_trace(&stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+/*
+ * The vector number returned in the frame pointer may also contain
+ * the "fs" (Fault Status) bits on ColdFire. These are in the bottom
+ * 2 bits, and upper 2 bits. So we need to mask out the real vector
+ * number before using it in comparisons. You don't need to do this on
+ * real 68k parts, but it won't hurt either.
+ */
+
+void bad_super_trap (struct frame *fp)
+{
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+
+	console_verbose();
+	if (vector < ARRAY_SIZE(vec_names))
+		printk ("*** %s ***   FORMAT=%X\n",
+			vec_names[vector],
+			fp->ptregs.format);
+	else
+		printk ("*** Exception %d ***   FORMAT=%X\n",
+			vector, fp->ptregs.format);
+	if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) {
+		unsigned short ssw = fp->un.fmtb.ssw;
+
+		printk ("SSW=%#06x  ", ssw);
+
+		if (ssw & RC)
+			printk ("Pipe stage C instruction fault at %#010lx\n",
+				(fp->ptregs.format) == 0xA ?
+				fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
+		if (ssw & RB)
+			printk ("Pipe stage B instruction fault at %#010lx\n",
+				(fp->ptregs.format) == 0xA ?
+				fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+		if (ssw & DF)
+			printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+				ssw & RW ? "read" : "write",
+				fp->un.fmtb.daddr, space_names[ssw & DFC],
+				fp->ptregs.pc);
+	}
+	printk ("Current process id is %d\n", task_pid_nr(current));
+	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
+}
+
+asmlinkage void trap_c(struct frame *fp)
+{
+	int sig;
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+	siginfo_t info;
+
+	if (fp->ptregs.sr & PS_S) {
+		if (vector == VEC_TRACE) {
+			/* traced a trapping instruction on a 68020/30,
+			 * real exception will be executed afterwards.
+			 */
+		} else if (!handle_kernel_fault(&fp->ptregs))
+			bad_super_trap(fp);
+		return;
+	}
+
+	/* send the appropriate signal to the user program */
+	switch (vector) {
+	    case VEC_ADDRERR:
+		info.si_code = BUS_ADRALN;
+		sig = SIGBUS;
+		break;
+	    case VEC_ILLEGAL:
+	    case VEC_LINE10:
+	    case VEC_LINE11:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_PRIV:
+		info.si_code = ILL_PRVOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_COPROC:
+		info.si_code = ILL_COPROC;
+		sig = SIGILL;
+		break;
+	    case VEC_TRAP1:
+	    case VEC_TRAP2:
+	    case VEC_TRAP3:
+	    case VEC_TRAP4:
+	    case VEC_TRAP5:
+	    case VEC_TRAP6:
+	    case VEC_TRAP7:
+	    case VEC_TRAP8:
+	    case VEC_TRAP9:
+	    case VEC_TRAP10:
+	    case VEC_TRAP11:
+	    case VEC_TRAP12:
+	    case VEC_TRAP13:
+	    case VEC_TRAP14:
+		info.si_code = ILL_ILLTRP;
+		sig = SIGILL;
+		break;
+	    case VEC_FPBRUC:
+	    case VEC_FPOE:
+	    case VEC_FPNAN:
+		info.si_code = FPE_FLTINV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPIR:
+		info.si_code = FPE_FLTRES;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPDIVZ:
+		info.si_code = FPE_FLTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPUNDER:
+		info.si_code = FPE_FLTUND;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPOVER:
+		info.si_code = FPE_FLTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_ZERODIV:
+		info.si_code = FPE_INTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_CHK:
+	    case VEC_TRAP:
+		info.si_code = FPE_INTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_TRACE:		/* ptrace single step */
+		info.si_code = TRAP_TRACE;
+		sig = SIGTRAP;
+		break;
+	    case VEC_TRAP15:		/* breakpoint */
+		info.si_code = TRAP_BRKPT;
+		sig = SIGTRAP;
+		break;
+	    default:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	}
+	info.si_signo = sig;
+	info.si_errno = 0;
+	switch (fp->ptregs.format) {
+	    default:
+		info.si_addr = (void *) fp->ptregs.pc;
+		break;
+	    case 2:
+		info.si_addr = (void *) fp->un.fmt2.iaddr;
+		break;
+	    case 7:
+		info.si_addr = (void *) fp->un.fmt7.effaddr;
+		break;
+	    case 9:
+		info.si_addr = (void *) fp->un.fmt9.iaddr;
+		break;
+	    case 10:
+		info.si_addr = (void *) fp->un.fmta.daddr;
+		break;
+	    case 11:
+		info.si_addr = (void *) fp->un.fmtb.daddr;
+		break;
+	}
+	force_sig_info (sig, &info, current);
+}
+
+void die_if_kernel (char *str, struct pt_regs *fp, int nr)
+{
+	if (!(fp->sr & PS_S))
+		return;
+
+	console_verbose();
+	printk("%s: %08x\n",str,nr);
+	show_registers(fp);
+	add_taint(TAINT_DIE);
+	do_exit(SIGSEGV);
+}
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+	current->thread.esp0 = ssp;
+}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
+	do_exit(SIGSEGV);
+}
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+	siginfo_t info;
+
+	info.si_signo = signal;
+	info.si_errno = 0;
+	info.si_code = code;
+	info.si_addr = addr;
+	force_sig_info(signal, &info, current);
+}
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/traps_mm.c linux-libre-3.2-gnu1/arch/m68k/kernel/traps_mm.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/traps_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/traps_mm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1207 +0,0 @@
-/*
- *  linux/arch/m68k/kernel/traps.c
- *
- *  Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- *  68040 fixes by Michael Rausch
- *  68040 fixes by Martin Apel
- *  68040 fixes and writeback by Richard Zidlicky
- *  68060 fixes by Roman Hodek
- *  68060 fixes by Jesper Skov
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Sets up all exception vectors
- */
-
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgalloc.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-/* assembler routines */
-asmlinkage void system_call(void);
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void nmihandler(void);
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpu_emu(void);
-#endif
-
-e_vector vectors[256];
-
-/* nmi handler for the Amiga */
-asm(".text\n"
-    __ALIGN_STR "\n"
-    "nmihandler: rte");
-
-/*
- * this must be called very early as the kernel might
- * use some instruction that are emulated on the 060
- * and so we're prepared for early probe attempts (e.g. nf_init).
- */
-void __init base_trap_init(void)
-{
-	if (MACH_IS_SUN3X) {
-		extern e_vector *sun3x_prom_vbr;
-
-		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
-	}
-
-	/* setup the exception vector table */
-	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
-
-	if (CPU_IS_060) {
-		/* set up ISP entry points */
-		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-
-		vectors[VEC_UNIMPII] = unimp_vec;
-	}
-
-	vectors[VEC_BUSERR] = buserr;
-	vectors[VEC_ILLEGAL] = trap;
-	vectors[VEC_SYS] = system_call;
-}
-
-void __init trap_init (void)
-{
-	int i;
-
-	for (i = VEC_SPUR; i <= VEC_INT7; i++)
-		vectors[i] = bad_inthandler;
-
-	for (i = 0; i < VEC_USER; i++)
-		if (!vectors[i])
-			vectors[i] = trap;
-
-	for (i = VEC_USER; i < 256; i++)
-		vectors[i] = bad_inthandler;
-
-#ifdef CONFIG_M68KFPU_EMU
-	if (FPU_IS_EMU)
-		vectors[VEC_LINE11] = fpu_emu;
-#endif
-
-	if (CPU_IS_040 && !FPU_IS_EMU) {
-		/* set up FPSP entry points */
-		asmlinkage void dz_vec(void) asm ("dz");
-		asmlinkage void inex_vec(void) asm ("inex");
-		asmlinkage void ovfl_vec(void) asm ("ovfl");
-		asmlinkage void unfl_vec(void) asm ("unfl");
-		asmlinkage void snan_vec(void) asm ("snan");
-		asmlinkage void operr_vec(void) asm ("operr");
-		asmlinkage void bsun_vec(void) asm ("bsun");
-		asmlinkage void fline_vec(void) asm ("fline");
-		asmlinkage void unsupp_vec(void) asm ("unsupp");
-
-		vectors[VEC_FPDIVZ] = dz_vec;
-		vectors[VEC_FPIR] = inex_vec;
-		vectors[VEC_FPOVER] = ovfl_vec;
-		vectors[VEC_FPUNDER] = unfl_vec;
-		vectors[VEC_FPNAN] = snan_vec;
-		vectors[VEC_FPOE] = operr_vec;
-		vectors[VEC_FPBRUC] = bsun_vec;
-		vectors[VEC_LINE11] = fline_vec;
-		vectors[VEC_FPUNSUP] = unsupp_vec;
-	}
-
-	if (CPU_IS_060 && !FPU_IS_EMU) {
-		/* set up IFPSP entry points */
-		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
-		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
-		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
-		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
-		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
-		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
-		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
-		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
-		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
-
-		vectors[VEC_FPNAN] = snan_vec6;
-		vectors[VEC_FPOE] = operr_vec6;
-		vectors[VEC_FPOVER] = ovfl_vec6;
-		vectors[VEC_FPUNDER] = unfl_vec6;
-		vectors[VEC_FPDIVZ] = dz_vec6;
-		vectors[VEC_FPIR] = inex_vec6;
-		vectors[VEC_LINE11] = fline_vec6;
-		vectors[VEC_FPUNSUP] = unsupp_vec6;
-		vectors[VEC_UNIMPEA] = effadd_vec6;
-	}
-
-        /* if running on an amiga, make the NMI interrupt do nothing */
-	if (MACH_IS_AMIGA) {
-		vectors[VEC_INT7] = nmihandler;
-	}
-}
-
-
-static const char *vec_names[] = {
-	[VEC_RESETSP]	= "RESET SP",
-	[VEC_RESETPC]	= "RESET PC",
-	[VEC_BUSERR]	= "BUS ERROR",
-	[VEC_ADDRERR]	= "ADDRESS ERROR",
-	[VEC_ILLEGAL]	= "ILLEGAL INSTRUCTION",
-	[VEC_ZERODIV]	= "ZERO DIVIDE",
-	[VEC_CHK]	= "CHK",
-	[VEC_TRAP]	= "TRAPcc",
-	[VEC_PRIV]	= "PRIVILEGE VIOLATION",
-	[VEC_TRACE]	= "TRACE",
-	[VEC_LINE10]	= "LINE 1010",
-	[VEC_LINE11]	= "LINE 1111",
-	[VEC_RESV12]	= "UNASSIGNED RESERVED 12",
-	[VEC_COPROC]	= "COPROCESSOR PROTOCOL VIOLATION",
-	[VEC_FORMAT]	= "FORMAT ERROR",
-	[VEC_UNINT]	= "UNINITIALIZED INTERRUPT",
-	[VEC_RESV16]	= "UNASSIGNED RESERVED 16",
-	[VEC_RESV17]	= "UNASSIGNED RESERVED 17",
-	[VEC_RESV18]	= "UNASSIGNED RESERVED 18",
-	[VEC_RESV19]	= "UNASSIGNED RESERVED 19",
-	[VEC_RESV20]	= "UNASSIGNED RESERVED 20",
-	[VEC_RESV21]	= "UNASSIGNED RESERVED 21",
-	[VEC_RESV22]	= "UNASSIGNED RESERVED 22",
-	[VEC_RESV23]	= "UNASSIGNED RESERVED 23",
-	[VEC_SPUR]	= "SPURIOUS INTERRUPT",
-	[VEC_INT1]	= "LEVEL 1 INT",
-	[VEC_INT2]	= "LEVEL 2 INT",
-	[VEC_INT3]	= "LEVEL 3 INT",
-	[VEC_INT4]	= "LEVEL 4 INT",
-	[VEC_INT5]	= "LEVEL 5 INT",
-	[VEC_INT6]	= "LEVEL 6 INT",
-	[VEC_INT7]	= "LEVEL 7 INT",
-	[VEC_SYS]	= "SYSCALL",
-	[VEC_TRAP1]	= "TRAP #1",
-	[VEC_TRAP2]	= "TRAP #2",
-	[VEC_TRAP3]	= "TRAP #3",
-	[VEC_TRAP4]	= "TRAP #4",
-	[VEC_TRAP5]	= "TRAP #5",
-	[VEC_TRAP6]	= "TRAP #6",
-	[VEC_TRAP7]	= "TRAP #7",
-	[VEC_TRAP8]	= "TRAP #8",
-	[VEC_TRAP9]	= "TRAP #9",
-	[VEC_TRAP10]	= "TRAP #10",
-	[VEC_TRAP11]	= "TRAP #11",
-	[VEC_TRAP12]	= "TRAP #12",
-	[VEC_TRAP13]	= "TRAP #13",
-	[VEC_TRAP14]	= "TRAP #14",
-	[VEC_TRAP15]	= "TRAP #15",
-	[VEC_FPBRUC]	= "FPCP BSUN",
-	[VEC_FPIR]	= "FPCP INEXACT",
-	[VEC_FPDIVZ]	= "FPCP DIV BY 0",
-	[VEC_FPUNDER]	= "FPCP UNDERFLOW",
-	[VEC_FPOE]	= "FPCP OPERAND ERROR",
-	[VEC_FPOVER]	= "FPCP OVERFLOW",
-	[VEC_FPNAN]	= "FPCP SNAN",
-	[VEC_FPUNSUP]	= "FPCP UNSUPPORTED OPERATION",
-	[VEC_MMUCFG]	= "MMU CONFIGURATION ERROR",
-	[VEC_MMUILL]	= "MMU ILLEGAL OPERATION ERROR",
-	[VEC_MMUACC]	= "MMU ACCESS LEVEL VIOLATION ERROR",
-	[VEC_RESV59]	= "UNASSIGNED RESERVED 59",
-	[VEC_UNIMPEA]	= "UNASSIGNED RESERVED 60",
-	[VEC_UNIMPII]	= "UNASSIGNED RESERVED 61",
-	[VEC_RESV62]	= "UNASSIGNED RESERVED 62",
-	[VEC_RESV63]	= "UNASSIGNED RESERVED 63",
-};
-
-static const char *space_names[] = {
-	[0]		= "Space 0",
-	[USER_DATA]	= "User Data",
-	[USER_PROGRAM]	= "User Program",
-#ifndef CONFIG_SUN3
-	[3]		= "Space 3",
-#else
-	[FC_CONTROL]	= "Control",
-#endif
-	[4]		= "Space 4",
-	[SUPER_DATA]	= "Super Data",
-	[SUPER_PROGRAM]	= "Super Program",
-	[CPU_SPACE]	= "CPU"
-};
-
-void die_if_kernel(char *,struct pt_regs *,int);
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-                             unsigned long error_code);
-int send_fault_sig(struct pt_regs *regs);
-
-asmlinkage void trap_c(struct frame *fp);
-
-#if defined (CONFIG_M68060)
-static inline void access_error060 (struct frame *fp)
-{
-	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
-
-#ifdef DEBUG
-	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
-#endif
-
-	if (fslw & MMU060_BPE) {
-		/* branch prediction error -> clear branch cache */
-		__asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
-				      "orl   #0x00400000,%/d0\n\t"
-				      "movec %/d0,%/cacr"
-				      : : : "d0" );
-		/* return if there's no other error */
-		if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
-			return;
-	}
-
-	if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
-		unsigned long errorcode;
-		unsigned long addr = fp->un.fmt4.effaddr;
-
-		if (fslw & MMU060_MA)
-			addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
-
-		errorcode = 1;
-		if (fslw & MMU060_DESC_ERR) {
-			__flush_tlb040_one(addr);
-			errorcode = 0;
-		}
-		if (fslw & MMU060_W)
-			errorcode |= 2;
-#ifdef DEBUG
-		printk("errorcode = %d\n", errorcode );
-#endif
-		do_page_fault(&fp->ptregs, addr, errorcode);
-	} else if (fslw & (MMU060_SEE)){
-		/* Software Emulation Error.
-		 * fault during mem_read/mem_write in ifpsp060/os.S
-		 */
-		send_fault_sig(&fp->ptregs);
-	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
-		   send_fault_sig(&fp->ptregs) > 0) {
-		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
-		printk( "68060 access error, fslw=%lx\n", fslw );
-		trap_c( fp );
-	}
-}
-#endif /* CONFIG_M68060 */
-
-#if defined (CONFIG_M68040)
-static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
-{
-	unsigned long mmusr;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(MAKE_MM_SEG(wbs));
-
-	if (iswrite)
-		asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
-	else
-		asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
-
-	asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
-
-	set_fs(old_fs);
-
-	return mmusr;
-}
-
-static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
-				   unsigned long wbd)
-{
-	int res = 0;
-	mm_segment_t old_fs = get_fs();
-
-	/* set_fs can not be moved, otherwise put_user() may oops */
-	set_fs(MAKE_MM_SEG(wbs));
-
-	switch (wbs & WBSIZ_040) {
-	case BA_SIZE_BYTE:
-		res = put_user(wbd & 0xff, (char __user *)wba);
-		break;
-	case BA_SIZE_WORD:
-		res = put_user(wbd & 0xffff, (short __user *)wba);
-		break;
-	case BA_SIZE_LONG:
-		res = put_user(wbd, (int __user *)wba);
-		break;
-	}
-
-	/* set_fs can not be moved, otherwise put_user() may oops */
-	set_fs(old_fs);
-
-
-#ifdef DEBUG
-	printk("do_040writeback1, res=%d\n",res);
-#endif
-
-	return res;
-}
-
-/* after an exception in a writeback the stack frame corresponding
- * to that exception is discarded, set a few bits in the old frame
- * to simulate what it should look like
- */
-static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
-{
-	fp->un.fmt7.faddr = wba;
-	fp->un.fmt7.ssw = wbs & 0xff;
-	if (wba != current->thread.faddr)
-	    fp->un.fmt7.ssw |= MA_040;
-}
-
-static inline void do_040writebacks(struct frame *fp)
-{
-	int res = 0;
-#if 0
-	if (fp->un.fmt7.wb1s & WBV_040)
-		printk("access_error040: cannot handle 1st writeback. oops.\n");
-#endif
-
-	if ((fp->un.fmt7.wb2s & WBV_040) &&
-	    !(fp->un.fmt7.wb2s & WBTT_040)) {
-		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
-				       fp->un.fmt7.wb2d);
-		if (res)
-			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
-		else
-			fp->un.fmt7.wb2s = 0;
-	}
-
-	/* do the 2nd wb only if the first one was successful (except for a kernel wb) */
-	if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
-		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
-				       fp->un.fmt7.wb3d);
-		if (res)
-		    {
-			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
-
-			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
-			fp->un.fmt7.wb3s &= (~WBV_040);
-			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
-			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
-		    }
-		else
-			fp->un.fmt7.wb3s = 0;
-	}
-
-	if (res)
-		send_fault_sig(&fp->ptregs);
-}
-
-/*
- * called from sigreturn(), must ensure userspace code didn't
- * manipulate exception frame to circumvent protection, then complete
- * pending writebacks
- * we just clear TM2 to turn it into a userspace access
- */
-asmlinkage void berr_040cleanup(struct frame *fp)
-{
-	fp->un.fmt7.wb2s &= ~4;
-	fp->un.fmt7.wb3s &= ~4;
-
-	do_040writebacks(fp);
-}
-
-static inline void access_error040(struct frame *fp)
-{
-	unsigned short ssw = fp->un.fmt7.ssw;
-	unsigned long mmusr;
-
-#ifdef DEBUG
-	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
-        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
-		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
-	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
-		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
-		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
-#endif
-
-	if (ssw & ATC_040) {
-		unsigned long addr = fp->un.fmt7.faddr;
-		unsigned long errorcode;
-
-		/*
-		 * The MMU status has to be determined AFTER the address
-		 * has been corrected if there was a misaligned access (MA).
-		 */
-		if (ssw & MA_040)
-			addr = (addr + 7) & -8;
-
-		/* MMU error, get the MMUSR info for this access */
-		mmusr = probe040(!(ssw & RW_040), addr, ssw);
-#ifdef DEBUG
-		printk("mmusr = %lx\n", mmusr);
-#endif
-		errorcode = 1;
-		if (!(mmusr & MMU_R_040)) {
-			/* clear the invalid atc entry */
-			__flush_tlb040_one(addr);
-			errorcode = 0;
-		}
-
-		/* despite what documentation seems to say, RMW
-		 * accesses have always both the LK and RW bits set */
-		if (!(ssw & RW_040) || (ssw & LK_040))
-			errorcode |= 2;
-
-		if (do_page_fault(&fp->ptregs, addr, errorcode)) {
-#ifdef DEBUG
-			printk("do_page_fault() !=0\n");
-#endif
-			if (user_mode(&fp->ptregs)){
-				/* delay writebacks after signal delivery */
-#ifdef DEBUG
-			        printk(".. was usermode - return\n");
-#endif
-				return;
-			}
-			/* disable writeback into user space from kernel
-			 * (if do_page_fault didn't fix the mapping,
-                         * the writeback won't do good)
-			 */
-disable_wb:
-#ifdef DEBUG
-			printk(".. disabling wb2\n");
-#endif
-			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
-				fp->un.fmt7.wb2s &= ~WBV_040;
-			if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
-				fp->un.fmt7.wb3s &= ~WBV_040;
-		}
-	} else {
-		/* In case of a bus error we either kill the process or expect
-		 * the kernel to catch the fault, which then is also responsible
-		 * for cleaning up the mess.
-		 */
-		current->thread.signo = SIGBUS;
-		current->thread.faddr = fp->un.fmt7.faddr;
-		if (send_fault_sig(&fp->ptregs) >= 0)
-			printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
-			       fp->un.fmt7.faddr);
-		goto disable_wb;
-	}
-
-	do_040writebacks(fp);
-}
-#endif /* CONFIG_M68040 */
-
-#if defined(CONFIG_SUN3)
-#include <asm/sun3mmu.h>
-
-extern int mmu_emu_handle_fault (unsigned long, int, int);
-
-/* sun3 version of bus_error030 */
-
-static inline void bus_error030 (struct frame *fp)
-{
-	unsigned char buserr_type = sun3_get_buserr ();
-	unsigned long addr, errorcode;
-	unsigned short ssw = fp->un.fmtb.ssw;
-	extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
-
-#ifdef DEBUG
-	if (ssw & (FC | FB))
-		printk ("Instruction fault at %#010lx\n",
-			ssw & FC ?
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
-			:
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-	if (ssw & DF)
-		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-			ssw & RW ? "read" : "write",
-			fp->un.fmtb.daddr,
-			space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
-	/*
-	 * Check if this page should be demand-mapped. This needs to go before
-	 * the testing for a bad kernel-space access (demand-mapping applies
-	 * to kernel accesses too).
-	 */
-
-	if ((ssw & DF)
-	    && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
-		if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
-			return;
-	}
-
-	/* Check for kernel-space pagefault (BAD). */
-	if (fp->ptregs.sr & PS_S) {
-		/* kernel fault must be a data fault to user space */
-		if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
-		     // try checking the kernel mappings before surrender
-		     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
-			  return;
-			/* instruction fault or kernel data fault! */
-			if (ssw & (FC | FB))
-				printk ("Instruction fault at %#010lx\n",
-					fp->ptregs.pc);
-			if (ssw & DF) {
-				/* was this fault incurred testing bus mappings? */
-				if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
-				   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
-					send_fault_sig(&fp->ptregs);
-					return;
-				}
-
-				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-					ssw & RW ? "read" : "write",
-					fp->un.fmtb.daddr,
-					space_names[ssw & DFC], fp->ptregs.pc);
-			}
-			printk ("BAD KERNEL BUSERR\n");
-
-			die_if_kernel("Oops", &fp->ptregs,0);
-			force_sig(SIGKILL, current);
-			return;
-		}
-	} else {
-		/* user fault */
-		if (!(ssw & (FC | FB)) && !(ssw & DF))
-			/* not an instruction fault or data fault! BAD */
-			panic ("USER BUSERR w/o instruction or data fault");
-	}
-
-
-	/* First handle the data fault, if any.  */
-	if (ssw & DF) {
-		addr = fp->un.fmtb.daddr;
-
-// errorcode bit 0:	0 -> no page		1 -> protection fault
-// errorcode bit 1:	0 -> read fault		1 -> write fault
-
-// (buserr_type & SUN3_BUSERR_PROTERR)	-> protection fault
-// (buserr_type & SUN3_BUSERR_INVALID)	-> invalid page fault
-
-		if (buserr_type & SUN3_BUSERR_PROTERR)
-			errorcode = 0x01;
-		else if (buserr_type & SUN3_BUSERR_INVALID)
-			errorcode = 0x00;
-		else {
-#ifdef DEBUG
-			printk ("*** unexpected busfault type=%#04x\n", buserr_type);
-			printk ("invalid %s access at %#lx from pc %#lx\n",
-				!(ssw & RW) ? "write" : "read", addr,
-				fp->ptregs.pc);
-#endif
-			die_if_kernel ("Oops", &fp->ptregs, buserr_type);
-			force_sig (SIGBUS, current);
-			return;
-		}
-
-//todo: wtf is RM bit? --m
-		if (!(ssw & RW) || ssw & RM)
-			errorcode |= 0x02;
-
-		/* Handle page fault. */
-		do_page_fault (&fp->ptregs, addr, errorcode);
-
-		/* Retry the data fault now. */
-		return;
-	}
-
-	/* Now handle the instruction fault. */
-
-	/* Get the fault address. */
-	if (fp->ptregs.format == 0xA)
-		addr = fp->ptregs.pc + 4;
-	else
-		addr = fp->un.fmtb.baddr;
-	if (ssw & FC)
-		addr -= 2;
-
-	if (buserr_type & SUN3_BUSERR_INVALID) {
-		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
-			do_page_fault (&fp->ptregs, addr, 0);
-       } else {
-#ifdef DEBUG
-		printk ("protection fault on insn access (segv).\n");
-#endif
-		force_sig (SIGSEGV, current);
-       }
-}
-#else
-#if defined(CPU_M68020_OR_M68030)
-static inline void bus_error030 (struct frame *fp)
-{
-	volatile unsigned short temp;
-	unsigned short mmusr;
-	unsigned long addr, errorcode;
-	unsigned short ssw = fp->un.fmtb.ssw;
-#ifdef DEBUG
-	unsigned long desc;
-
-	printk ("pid = %x  ", current->pid);
-	printk ("SSW=%#06x  ", ssw);
-
-	if (ssw & (FC | FB))
-		printk ("Instruction fault at %#010lx\n",
-			ssw & FC ?
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
-			:
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-	if (ssw & DF)
-		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-			ssw & RW ? "read" : "write",
-			fp->un.fmtb.daddr,
-			space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
-	/* ++andreas: If a data fault and an instruction fault happen
-	   at the same time map in both pages.  */
-
-	/* First handle the data fault, if any.  */
-	if (ssw & DF) {
-		addr = fp->un.fmtb.daddr;
-
-#ifdef DEBUG
-		asm volatile ("ptestr %3,%2@,#7,%0\n\t"
-			      "pmove %%psr,%1@"
-			      : "=a&" (desc)
-			      : "a" (&temp), "a" (addr), "d" (ssw));
-#else
-		asm volatile ("ptestr %2,%1@,#7\n\t"
-			      "pmove %%psr,%0@"
-			      : : "a" (&temp), "a" (addr), "d" (ssw));
-#endif
-		mmusr = temp;
-
-#ifdef DEBUG
-		printk("mmusr is %#x for addr %#lx in task %p\n",
-		       mmusr, addr, current);
-		printk("descriptor address is %#lx, contents %#lx\n",
-		       __va(desc), *(unsigned long *)__va(desc));
-#endif
-
-		errorcode = (mmusr & MMU_I) ? 0 : 1;
-		if (!(ssw & RW) || (ssw & RM))
-			errorcode |= 2;
-
-		if (mmusr & (MMU_I | MMU_WP)) {
-			if (ssw & 4) {
-				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-				       ssw & RW ? "read" : "write",
-				       fp->un.fmtb.daddr,
-				       space_names[ssw & DFC], fp->ptregs.pc);
-				goto buserr;
-			}
-			/* Don't try to do anything further if an exception was
-			   handled. */
-			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
-				return;
-		} else if (!(mmusr & MMU_I)) {
-			/* probably a 020 cas fault */
-			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
-				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
-		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-			printk("invalid %s access at %#lx from pc %#lx\n",
-			       !(ssw & RW) ? "write" : "read", addr,
-			       fp->ptregs.pc);
-			die_if_kernel("Oops",&fp->ptregs,mmusr);
-			force_sig(SIGSEGV, current);
-			return;
-		} else {
-#if 0
-			static volatile long tlong;
-#endif
-
-			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
-			       !(ssw & RW) ? "write" : "read", addr,
-			       fp->ptregs.pc, ssw);
-			asm volatile ("ptestr #1,%1@,#0\n\t"
-				      "pmove %%psr,%0@"
-				      : /* no outputs */
-				      : "a" (&temp), "a" (addr));
-			mmusr = temp;
-
-			printk ("level 0 mmusr is %#x\n", mmusr);
-#if 0
-			asm volatile ("pmove %%tt0,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk("tt0 is %#lx, ", tlong);
-			asm volatile ("pmove %%tt1,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk("tt1 is %#lx\n", tlong);
-#endif
-#ifdef DEBUG
-			printk("Unknown SIGSEGV - 1\n");
-#endif
-			die_if_kernel("Oops",&fp->ptregs,mmusr);
-			force_sig(SIGSEGV, current);
-			return;
-		}
-
-		/* setup an ATC entry for the access about to be retried */
-		if (!(ssw & RW) || (ssw & RM))
-			asm volatile ("ploadw %1,%0@" : /* no outputs */
-				      : "a" (addr), "d" (ssw));
-		else
-			asm volatile ("ploadr %1,%0@" : /* no outputs */
-				      : "a" (addr), "d" (ssw));
-	}
-
-	/* Now handle the instruction fault. */
-
-	if (!(ssw & (FC|FB)))
-		return;
-
-	if (fp->ptregs.sr & PS_S) {
-		printk("Instruction fault at %#010lx\n",
-			fp->ptregs.pc);
-	buserr:
-		printk ("BAD KERNEL BUSERR\n");
-		die_if_kernel("Oops",&fp->ptregs,0);
-		force_sig(SIGKILL, current);
-		return;
-	}
-
-	/* get the fault address */
-	if (fp->ptregs.format == 10)
-		addr = fp->ptregs.pc + 4;
-	else
-		addr = fp->un.fmtb.baddr;
-	if (ssw & FC)
-		addr -= 2;
-
-	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
-		/* Insn fault on same page as data fault.  But we
-		   should still create the ATC entry.  */
-		goto create_atc_entry;
-
-#ifdef DEBUG
-	asm volatile ("ptestr #1,%2@,#7,%0\n\t"
-		      "pmove %%psr,%1@"
-		      : "=a&" (desc)
-		      : "a" (&temp), "a" (addr));
-#else
-	asm volatile ("ptestr #1,%1@,#7\n\t"
-		      "pmove %%psr,%0@"
-		      : : "a" (&temp), "a" (addr));
-#endif
-	mmusr = temp;
-
-#ifdef DEBUG
-	printk ("mmusr is %#x for addr %#lx in task %p\n",
-		mmusr, addr, current);
-	printk ("descriptor address is %#lx, contents %#lx\n",
-		__va(desc), *(unsigned long *)__va(desc));
-#endif
-
-	if (mmusr & MMU_I)
-		do_page_fault (&fp->ptregs, addr, 0);
-	else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-		printk ("invalid insn access at %#lx from pc %#lx\n",
-			addr, fp->ptregs.pc);
-#ifdef DEBUG
-		printk("Unknown SIGSEGV - 2\n");
-#endif
-		die_if_kernel("Oops",&fp->ptregs,mmusr);
-		force_sig(SIGSEGV, current);
-		return;
-	}
-
-create_atc_entry:
-	/* setup an ATC entry for the access about to be retried */
-	asm volatile ("ploadr #2,%0@" : /* no outputs */
-		      : "a" (addr));
-}
-#endif /* CPU_M68020_OR_M68030 */
-#endif /* !CONFIG_SUN3 */
-
-asmlinkage void buserr_c(struct frame *fp)
-{
-	/* Only set esp0 if coming from user mode */
-	if (user_mode(&fp->ptregs))
-		current->thread.esp0 = (unsigned long) fp;
-
-#ifdef DEBUG
-	printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
-	switch (fp->ptregs.format) {
-#if defined (CONFIG_M68060)
-	case 4:				/* 68060 access error */
-	  access_error060 (fp);
-	  break;
-#endif
-#if defined (CONFIG_M68040)
-	case 0x7:			/* 68040 access error */
-	  access_error040 (fp);
-	  break;
-#endif
-#if defined (CPU_M68020_OR_M68030)
-	case 0xa:
-	case 0xb:
-	  bus_error030 (fp);
-	  break;
-#endif
-	default:
-	  die_if_kernel("bad frame format",&fp->ptregs,0);
-#ifdef DEBUG
-	  printk("Unknown SIGSEGV - 4\n");
-#endif
-	  force_sig(SIGSEGV, current);
-	}
-}
-
-
-static int kstack_depth_to_print = 48;
-
-void show_trace(unsigned long *stack)
-{
-	unsigned long *endstack;
-	unsigned long addr;
-	int i;
-
-	printk("Call Trace:");
-	addr = (unsigned long)stack + THREAD_SIZE - 1;
-	endstack = (unsigned long *)(addr & -THREAD_SIZE);
-	i = 0;
-	while (stack + 1 <= endstack) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the
-		 * kernel, or in the region which contains vmalloc'ed
-		 * memory, it *may* be the address of a calling
-		 * routine; if so, print it so that someone tracing
-		 * down the cause of the crash will be able to figure
-		 * out the call path that was taken.
-		 */
-		if (__kernel_text_address(addr)) {
-#ifndef CONFIG_KALLSYMS
-			if (i % 5 == 0)
-				printk("\n       ");
-#endif
-			printk(" [<%08lx>] %pS\n", addr, (void *)addr);
-			i++;
-		}
-	}
-	printk("\n");
-}
-
-void show_registers(struct pt_regs *regs)
-{
-	struct frame *fp = (struct frame *)regs;
-	mm_segment_t old_fs = get_fs();
-	u16 c, *cp;
-	unsigned long addr;
-	int i;
-
-	print_modules();
-	printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
-	printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
-	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       regs->d0, regs->d1, regs->d2, regs->d3);
-	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
-	       regs->d4, regs->d5, regs->a0, regs->a1);
-
-	printk("Process %s (pid: %d, task=%p)\n",
-		current->comm, task_pid_nr(current), current);
-	addr = (unsigned long)&fp->un;
-	printk("Frame format=%X ", regs->format);
-	switch (regs->format) {
-	case 0x2:
-		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
-		addr += sizeof(fp->un.fmt2);
-		break;
-	case 0x3:
-		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
-		addr += sizeof(fp->un.fmt3);
-		break;
-	case 0x4:
-		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
-			: "eff addr=%08lx pc=%08lx\n"),
-			fp->un.fmt4.effaddr, fp->un.fmt4.pc);
-		addr += sizeof(fp->un.fmt4);
-		break;
-	case 0x7:
-		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
-			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
-		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
-		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
-		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
-		printk("push data: %08lx %08lx %08lx %08lx\n",
-			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
-			fp->un.fmt7.pd3);
-		addr += sizeof(fp->un.fmt7);
-		break;
-	case 0x9:
-		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
-		addr += sizeof(fp->un.fmt9);
-		break;
-	case 0xa:
-		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
-			fp->un.fmta.daddr, fp->un.fmta.dobuf);
-		addr += sizeof(fp->un.fmta);
-		break;
-	case 0xb:
-		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
-			fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
-		printk("baddr=%08lx dibuf=%08lx ver=%x\n",
-			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
-		addr += sizeof(fp->un.fmtb);
-		break;
-	default:
-		printk("\n");
-	}
-	show_stack(NULL, (unsigned long *)addr);
-
-	printk("Code:");
-	set_fs(KERNEL_DS);
-	cp = (u16 *)regs->pc;
-	for (i = -8; i < 16; i++) {
-		if (get_user(c, cp + i) && i >= 0) {
-			printk(" Bad PC value.");
-			break;
-		}
-		printk(i ? " %04x" : " <%04x>", c);
-	}
-	set_fs(old_fs);
-	printk ("\n");
-}
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
-	unsigned long *p;
-	unsigned long *endstack;
-	int i;
-
-	if (!stack) {
-		if (task)
-			stack = (unsigned long *)task->thread.esp0;
-		else
-			stack = (unsigned long *)&stack;
-	}
-	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
-
-	printk("Stack from %08lx:", (unsigned long)stack);
-	p = stack;
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (p + 1 > endstack)
-			break;
-		if (i % 8 == 0)
-			printk("\n       ");
-		printk(" %08lx", *p++);
-	}
-	printk("\n");
-	show_trace(stack);
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
-	unsigned long stack;
-
-	show_trace(&stack);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
-void bad_super_trap (struct frame *fp)
-{
-	console_verbose();
-	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
-		printk ("*** %s ***   FORMAT=%X\n",
-			vec_names[(fp->ptregs.vector) >> 2],
-			fp->ptregs.format);
-	else
-		printk ("*** Exception %d ***   FORMAT=%X\n",
-			(fp->ptregs.vector) >> 2,
-			fp->ptregs.format);
-	if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
-		unsigned short ssw = fp->un.fmtb.ssw;
-
-		printk ("SSW=%#06x  ", ssw);
-
-		if (ssw & RC)
-			printk ("Pipe stage C instruction fault at %#010lx\n",
-				(fp->ptregs.format) == 0xA ?
-				fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
-		if (ssw & RB)
-			printk ("Pipe stage B instruction fault at %#010lx\n",
-				(fp->ptregs.format) == 0xA ?
-				fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-		if (ssw & DF)
-			printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-				ssw & RW ? "read" : "write",
-				fp->un.fmtb.daddr, space_names[ssw & DFC],
-				fp->ptregs.pc);
-	}
-	printk ("Current process id is %d\n", task_pid_nr(current));
-	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
-	int sig;
-	siginfo_t info;
-
-	if (fp->ptregs.sr & PS_S) {
-		if (fp->ptregs.vector == VEC_TRACE << 2) {
-			/* traced a trapping instruction on a 68020/30,
-			 * real exception will be executed afterwards.
-			 */
-		} else if (!handle_kernel_fault(&fp->ptregs))
-			bad_super_trap(fp);
-		return;
-	}
-
-	/* send the appropriate signal to the user program */
-	switch ((fp->ptregs.vector) >> 2) {
-	    case VEC_ADDRERR:
-		info.si_code = BUS_ADRALN;
-		sig = SIGBUS;
-		break;
-	    case VEC_ILLEGAL:
-	    case VEC_LINE10:
-	    case VEC_LINE11:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_PRIV:
-		info.si_code = ILL_PRVOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_COPROC:
-		info.si_code = ILL_COPROC;
-		sig = SIGILL;
-		break;
-	    case VEC_TRAP1:
-	    case VEC_TRAP2:
-	    case VEC_TRAP3:
-	    case VEC_TRAP4:
-	    case VEC_TRAP5:
-	    case VEC_TRAP6:
-	    case VEC_TRAP7:
-	    case VEC_TRAP8:
-	    case VEC_TRAP9:
-	    case VEC_TRAP10:
-	    case VEC_TRAP11:
-	    case VEC_TRAP12:
-	    case VEC_TRAP13:
-	    case VEC_TRAP14:
-		info.si_code = ILL_ILLTRP;
-		sig = SIGILL;
-		break;
-	    case VEC_FPBRUC:
-	    case VEC_FPOE:
-	    case VEC_FPNAN:
-		info.si_code = FPE_FLTINV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPIR:
-		info.si_code = FPE_FLTRES;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPDIVZ:
-		info.si_code = FPE_FLTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPUNDER:
-		info.si_code = FPE_FLTUND;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPOVER:
-		info.si_code = FPE_FLTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_ZERODIV:
-		info.si_code = FPE_INTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_CHK:
-	    case VEC_TRAP:
-		info.si_code = FPE_INTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_TRACE:		/* ptrace single step */
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP15:		/* breakpoint */
-		info.si_code = TRAP_BRKPT;
-		sig = SIGTRAP;
-		break;
-	    default:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	}
-	info.si_signo = sig;
-	info.si_errno = 0;
-	switch (fp->ptregs.format) {
-	    default:
-		info.si_addr = (void *) fp->ptregs.pc;
-		break;
-	    case 2:
-		info.si_addr = (void *) fp->un.fmt2.iaddr;
-		break;
-	    case 7:
-		info.si_addr = (void *) fp->un.fmt7.effaddr;
-		break;
-	    case 9:
-		info.si_addr = (void *) fp->un.fmt9.iaddr;
-		break;
-	    case 10:
-		info.si_addr = (void *) fp->un.fmta.daddr;
-		break;
-	    case 11:
-		info.si_addr = (void *) fp->un.fmtb.daddr;
-		break;
-	}
-	force_sig_info (sig, &info, current);
-}
-
-void die_if_kernel (char *str, struct pt_regs *fp, int nr)
-{
-	if (!(fp->sr & PS_S))
-		return;
-
-	console_verbose();
-	printk("%s: %08x\n",str,nr);
-	show_registers(fp);
-	add_taint(TAINT_DIE);
-	do_exit(SIGSEGV);
-}
-
-/*
- * This function is called if an error occur while accessing
- * user-space from the fpsp040 code.
- */
-asmlinkage void fpsp040_die(void)
-{
-	do_exit(SIGSEGV);
-}
-
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpemu_signal(int signal, int code, void *addr)
-{
-	siginfo_t info;
-
-	info.si_signo = signal;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
-	force_sig_info(signal, &info, current);
-}
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/traps_no.c linux-libre-3.2-gnu1/arch/m68k/kernel/traps_no.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/traps_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/traps_no.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,361 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/traps.c
- *
- *  Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- *  68040 fixes by Michael Rausch
- *  68040 fixes by Martin Apel
- *  68060 fixes by Roman Hodek
- *  68060 fixes by Jesper Skov
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Sets up all exception vectors
- */
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-static char const * const vec_names[] = {
-	"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
-	"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
-	"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
-	"UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
-	"FORMAT ERROR", "UNINITIALIZED INTERRUPT",
-	"UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
-	"UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
-	"UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
-	"UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
-	"SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
-	"LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
-	"SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
-	"TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
-	"TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
-	"TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
-	"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
-	"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
-	"FPCP UNSUPPORTED OPERATION",
-	"MMU CONFIGURATION ERROR"
-};
-
-void die_if_kernel(char *str, struct pt_regs *fp, int nr)
-{
-	if (!(fp->sr & PS_S))
-		return;
-
-	console_verbose();
-	printk(KERN_EMERG "%s: %08x\n",str,nr);
-	printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
-	       fp->pc, fp->sr, fp, fp->a2);
-	printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       fp->d0, fp->d1, fp->d2, fp->d3);
-	printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
-	       fp->d4, fp->d5, fp->a0, fp->a1);
-
-	printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
-		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
-	show_stack(NULL, (unsigned long *)(fp + 1));
-	add_taint(TAINT_DIE);
-	do_exit(SIGSEGV);
-}
-
-asmlinkage void buserr_c(struct frame *fp)
-{
-	/* Only set esp0 if coming from user mode */
-	if (user_mode(&fp->ptregs))
-		current->thread.esp0 = (unsigned long) fp;
-
-#if defined(DEBUG)
-	printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
-	die_if_kernel("bad frame format",&fp->ptregs,0);
-#if defined(DEBUG)
-	printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
-#endif
-	force_sig(SIGSEGV, current);
-}
-
-static void print_this_address(unsigned long addr, int i)
-{
-#ifdef CONFIG_KALLSYMS
-	printk(KERN_EMERG " [%08lx] ", addr);
-	print_symbol(KERN_CONT "%s\n", addr);
-#else
-	if (i % 5)
-		printk(KERN_CONT " [%08lx] ", addr);
-	else
-		printk(KERN_EMERG " [%08lx] ", addr);
-	i++;
-#endif
-}
-
-int kstack_depth_to_print = 48;
-
-static void __show_stack(struct task_struct *task, unsigned long *stack)
-{
-	unsigned long *endstack, addr;
-#ifdef CONFIG_FRAME_POINTER
-	unsigned long *last_stack;
-#endif
-	int i;
-
-	if (!stack)
-		stack = (unsigned long *)task->thread.ksp;
-
-	addr = (unsigned long) stack;
-	endstack = (unsigned long *) PAGE_ALIGN(addr);
-
-	printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (stack + 1 + i > endstack)
-			break;
-		if (i % 8 == 0)
-			printk(KERN_EMERG "       ");
-		printk(KERN_CONT " %08lx", *(stack + i));
-	}
-	printk("\n");
-	i = 0;
-
-#ifdef CONFIG_FRAME_POINTER
-	printk(KERN_EMERG "Call Trace:\n");
-
-	last_stack = stack - 1;
-	while (stack <= endstack && stack > last_stack) {
-
-		addr = *(stack + 1);
-		print_this_address(addr, i);
-		i++;
-
-		last_stack = stack;
-		stack = (unsigned long *)*stack;
-	}
-	printk("\n");
-#else
-	printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
-	while (stack <= endstack) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the kernel,
-		 * or in a region which is occupied by a module then it *may*
-		 * be the address of a calling routine; if so, print it so that
-		 * someone tracing down the cause of the crash will be able to
-		 * figure out the call path that was taken.
-		 */
-		if (__kernel_text_address(addr)) {
-			print_this_address(addr, i);
-			i++;
-		}
-	}
-	printk(KERN_CONT "\n");
-#endif
-}
-
-void bad_super_trap(struct frame *fp)
-{
-	int vector = (fp->ptregs.vector >> 2) & 0xff;
-
-	console_verbose();
-	if (vector < ARRAY_SIZE(vec_names))
-		printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
-			vec_names[vector],
-			fp->ptregs.format);
-	else
-		printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
-			vector,
-			fp->ptregs.format);
-	printk (KERN_WARNING "Current process id is %d\n", current->pid);
-	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
-	int sig;
-	int vector = (fp->ptregs.vector >> 2) & 0xff;
-	siginfo_t info;
-
-	if (fp->ptregs.sr & PS_S) {
-		if (vector == VEC_TRACE) {
-			/* traced a trapping instruction */
-		} else
-			bad_super_trap(fp);
-		return;
-	}
-
-	/* send the appropriate signal to the user program */
-	switch (vector) {
-	    case VEC_ADDRERR:
-		info.si_code = BUS_ADRALN;
-		sig = SIGBUS;
-		break;
-	    case VEC_ILLEGAL:
-	    case VEC_LINE10:
-	    case VEC_LINE11:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_PRIV:
-		info.si_code = ILL_PRVOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_COPROC:
-		info.si_code = ILL_COPROC;
-		sig = SIGILL;
-		break;
-	    case VEC_TRAP1: /* gdbserver breakpoint */
-		fp->ptregs.pc -= 2;
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP2:
-	    case VEC_TRAP3:
-	    case VEC_TRAP4:
-	    case VEC_TRAP5:
-	    case VEC_TRAP6:
-	    case VEC_TRAP7:
-	    case VEC_TRAP8:
-	    case VEC_TRAP9:
-	    case VEC_TRAP10:
-	    case VEC_TRAP11:
-	    case VEC_TRAP12:
-	    case VEC_TRAP13:
-	    case VEC_TRAP14:
-		info.si_code = ILL_ILLTRP;
-		sig = SIGILL;
-		break;
-	    case VEC_FPBRUC:
-	    case VEC_FPOE:
-	    case VEC_FPNAN:
-		info.si_code = FPE_FLTINV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPIR:
-		info.si_code = FPE_FLTRES;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPDIVZ:
-		info.si_code = FPE_FLTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPUNDER:
-		info.si_code = FPE_FLTUND;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPOVER:
-		info.si_code = FPE_FLTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_ZERODIV:
-		info.si_code = FPE_INTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_CHK:
-	    case VEC_TRAP:
-		info.si_code = FPE_INTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_TRACE:		/* ptrace single step */
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP15:		/* breakpoint */
-		info.si_code = TRAP_BRKPT;
-		sig = SIGTRAP;
-		break;
-	    default:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	}
-	info.si_signo = sig;
-	info.si_errno = 0;
-	switch (fp->ptregs.format) {
-	    default:
-		info.si_addr = (void *) fp->ptregs.pc;
-		break;
-	    case 2:
-		info.si_addr = (void *) fp->un.fmt2.iaddr;
-		break;
-	    case 7:
-		info.si_addr = (void *) fp->un.fmt7.effaddr;
-		break;
-	    case 9:
-		info.si_addr = (void *) fp->un.fmt9.iaddr;
-		break;
-	    case 10:
-		info.si_addr = (void *) fp->un.fmta.daddr;
-		break;
-	    case 11:
-		info.si_addr = (void *) fp->un.fmtb.daddr;
-		break;
-	}
-	force_sig_info (sig, &info, current);
-}
-
-asmlinkage void set_esp0(unsigned long ssp)
-{
-	current->thread.esp0 = ssp;
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
-	/*
-	 * We need frame pointers for this little trick, which works as follows:
-	 *
-	 * +------------+ 0x00
-	 * | Next SP	|	-> 0x0c
-	 * +------------+ 0x04
-	 * | Caller	|
-	 * +------------+ 0x08
-	 * | Local vars	|	-> our stack var
-	 * +------------+ 0x0c
-	 * | Next SP	|	-> 0x18, that is what we pass to show_stack()
-	 * +------------+ 0x10
-	 * | Caller	|
-	 * +------------+ 0x14
-	 * | Local vars	|
-	 * +------------+ 0x18
-	 * | ...	|
-	 * +------------+
-	 */
-
-	unsigned long *stack;
-
-	stack = (unsigned long *)&stack;
-	stack++;
-	__show_stack(current, stack);
-}
-EXPORT_SYMBOL(dump_stack);
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
-	if (!stack && !task)
-		dump_stack();
-	else
-		__show_stack(task, stack);
-}
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/vectors.c linux-libre-3.2-gnu1/arch/m68k/kernel/vectors.c
--- linux-libre-3.1-gnu1/arch/m68k/kernel/vectors.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/vectors.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ *  vectors.c
+ *
+ *  Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ *  68040 fixes by Michael Rausch
+ *  68040 fixes by Martin Apel
+ *  68040 fixes and writeback by Richard Zidlicky
+ *  68060 fixes by Roman Hodek
+ *  68060 fixes by Jesper Skov
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void nmihandler(void);
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpu_emu(void);
+#endif
+
+e_vector vectors[256];
+
+/* nmi handler for the Amiga */
+asm(".text\n"
+    __ALIGN_STR "\n"
+    "nmihandler: rte");
+
+/*
+ * this must be called very early as the kernel might
+ * use some instruction that are emulated on the 060
+ * and so we're prepared for early probe attempts (e.g. nf_init).
+ */
+void __init base_trap_init(void)
+{
+	if (MACH_IS_SUN3X) {
+		extern e_vector *sun3x_prom_vbr;
+
+		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
+	}
+
+	/* setup the exception vector table */
+	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+
+	if (CPU_IS_060) {
+		/* set up ISP entry points */
+		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+		vectors[VEC_UNIMPII] = unimp_vec;
+	}
+
+	vectors[VEC_BUSERR] = buserr;
+	vectors[VEC_ILLEGAL] = trap;
+	vectors[VEC_SYS] = system_call;
+}
+
+void __init trap_init (void)
+{
+	int i;
+
+	for (i = VEC_SPUR; i <= VEC_INT7; i++)
+		vectors[i] = bad_inthandler;
+
+	for (i = 0; i < VEC_USER; i++)
+		if (!vectors[i])
+			vectors[i] = trap;
+
+	for (i = VEC_USER; i < 256; i++)
+		vectors[i] = bad_inthandler;
+
+#ifdef CONFIG_M68KFPU_EMU
+	if (FPU_IS_EMU)
+		vectors[VEC_LINE11] = fpu_emu;
+#endif
+
+	if (CPU_IS_040 && !FPU_IS_EMU) {
+		/* set up FPSP entry points */
+		asmlinkage void dz_vec(void) asm ("dz");
+		asmlinkage void inex_vec(void) asm ("inex");
+		asmlinkage void ovfl_vec(void) asm ("ovfl");
+		asmlinkage void unfl_vec(void) asm ("unfl");
+		asmlinkage void snan_vec(void) asm ("snan");
+		asmlinkage void operr_vec(void) asm ("operr");
+		asmlinkage void bsun_vec(void) asm ("bsun");
+		asmlinkage void fline_vec(void) asm ("fline");
+		asmlinkage void unsupp_vec(void) asm ("unsupp");
+
+		vectors[VEC_FPDIVZ] = dz_vec;
+		vectors[VEC_FPIR] = inex_vec;
+		vectors[VEC_FPOVER] = ovfl_vec;
+		vectors[VEC_FPUNDER] = unfl_vec;
+		vectors[VEC_FPNAN] = snan_vec;
+		vectors[VEC_FPOE] = operr_vec;
+		vectors[VEC_FPBRUC] = bsun_vec;
+		vectors[VEC_LINE11] = fline_vec;
+		vectors[VEC_FPUNSUP] = unsupp_vec;
+	}
+
+	if (CPU_IS_060 && !FPU_IS_EMU) {
+		/* set up IFPSP entry points */
+		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
+		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
+		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
+		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
+		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
+		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
+		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
+		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
+		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
+
+		vectors[VEC_FPNAN] = snan_vec6;
+		vectors[VEC_FPOE] = operr_vec6;
+		vectors[VEC_FPOVER] = ovfl_vec6;
+		vectors[VEC_FPUNDER] = unfl_vec6;
+		vectors[VEC_FPDIVZ] = dz_vec6;
+		vectors[VEC_FPIR] = inex_vec6;
+		vectors[VEC_LINE11] = fline_vec6;
+		vectors[VEC_FPUNSUP] = unsupp_vec6;
+		vectors[VEC_UNIMPEA] = effadd_vec6;
+	}
+
+        /* if running on an amiga, make the NMI interrupt do nothing */
+	if (MACH_IS_AMIGA) {
+		vectors[VEC_INT7] = nmihandler;
+	}
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/m68k/kernel/vmlinux.lds_no.S linux-libre-3.2-gnu1/arch/m68k/kernel/vmlinux.lds_no.S
--- linux-libre-3.1-gnu1/arch/m68k/kernel/vmlinux.lds_no.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/kernel/vmlinux.lds_no.S	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,6 @@ SECTIONS {
 
 		*(.rodata) *(.rodata.*)
 		*(__vermagic)		/* Kernel version magic */
-		*(__markers_strings)
 		*(.rodata1)
 		*(.rodata.str1.1)
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/lib/memcpy.c linux-libre-3.2-gnu1/arch/m68k/lib/memcpy.c
--- linux-libre-3.1-gnu1/arch/m68k/lib/memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/lib/memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,15 @@ void *memcpy(void *to, const void *from,
 		from = cfrom;
 		n--;
 	}
+#if defined(CONFIG_M68000)
+	if ((long)from & 1) {
+		char *cto = to;
+		const char *cfrom = from;
+		for (; n; n--)
+			*cto++ = *cfrom++;
+		return xto;
+	}
+#endif
 	if (n > 2 && (long)to & 2) {
 		short *sto = to;
 		const short *sfrom = from;
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/baboon.c linux-libre-3.2-gnu1/arch/m68k/mac/baboon.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/baboon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/baboon.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -20,9 +21,6 @@
 
 /* #define DEBUG_IRQS */
 
-extern void mac_enable_irq(unsigned int);
-extern void mac_disable_irq(unsigned int);
-
 int baboon_present;
 static volatile struct baboon *baboon;
 static unsigned char baboon_disabled;
@@ -53,7 +51,7 @@ void __init baboon_init(void)
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-static irqreturn_t baboon_irq(int irq, void *dev_id)
+static void baboon_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_bit, irq_num;
 	unsigned char events;
@@ -64,15 +62,16 @@ static irqreturn_t baboon_irq(int irq, v
 		(uint) baboon->mb_status);
 #endif
 
-	if (!(events = baboon->mb_ifr & 0x07))
-		return IRQ_NONE;
+	events = baboon->mb_ifr & 0x07;
+	if (!events)
+		return;
 
 	irq_num = IRQ_BABOON_0;
 	irq_bit = 1;
 	do {
 	        if (events & irq_bit) {
 			baboon->mb_ifr &= ~irq_bit;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		irq_bit <<= 1;
 		irq_num++;
@@ -82,7 +81,6 @@ static irqreturn_t baboon_irq(int irq, v
 	/* for now we need to smash all interrupts */
 	baboon->mb_ifr &= ~events;
 #endif
-	return IRQ_HANDLED;
 }
 
 /*
@@ -92,8 +90,7 @@ static irqreturn_t baboon_irq(int irq, v
 void __init baboon_register_interrupts(void)
 {
 	baboon_disabled = 0;
-	if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
-		pr_err("Couldn't register baboon interrupt\n");
+	irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
 }
 
 /*
@@ -111,7 +108,7 @@ void baboon_irq_enable(int irq)
 
 	baboon_disabled &= ~(1 << irq_idx);
 	if (!baboon_disabled)
-		mac_enable_irq(IRQ_NUBUS_C);
+		mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_disable(int irq)
@@ -124,7 +121,7 @@ void baboon_irq_disable(int irq)
 
 	baboon_disabled |= 1 << irq_idx;
 	if (baboon_disabled)
-		mac_disable_irq(IRQ_NUBUS_C);
+		mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_clear(int irq)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/iop.c linux-libre-3.2-gnu1/arch/m68k/mac/iop.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/iop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/iop.c	2012-01-04 18:55:44.000000000 -0500
@@ -305,15 +305,13 @@ void __init iop_register_interrupts(void
 {
 	if (iop_ism_present) {
 		if (oss_present) {
-			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
-					IRQ_FLG_LOCK, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+					"ISM IOP", (void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 			oss_irq_enable(IRQ_MAC_ADB);
 		} else {
-			if (request_irq(IRQ_VIA2_0, iop_ism_irq,
-					IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
+					(void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 		}
 		if (!iop_alive(iop_base[IOP_NUM_ISM])) {
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/macints.c linux-libre-3.2-gnu1/arch/m68k/mac/macints.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/macints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/macints.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,14 +190,10 @@ irqreturn_t mac_debug_handler(int, void
 
 /* #define DEBUG_MACINTS */
 
-void mac_enable_irq(unsigned int irq);
-void mac_disable_irq(unsigned int irq);
-
-static struct irq_controller mac_irq_controller = {
+static struct irq_chip mac_irq_chip = {
 	.name		= "mac",
-	.lock		= __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
-	.enable		= mac_enable_irq,
-	.disable	= mac_disable_irq,
+	.irq_enable	= mac_irq_enable,
+	.irq_disable	= mac_irq_disable,
 };
 
 void __init mac_init_IRQ(void)
@@ -205,7 +201,7 @@ void __init mac_init_IRQ(void)
 #ifdef DEBUG_MACINTS
 	printk("mac_init_IRQ(): Setting things up...\n");
 #endif
-	m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
+	m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER,
 				  NUM_MAC_SOURCES - IRQ_USER);
 	/* Make sure the SONIC interrupt is cleared or things get ugly */
 #ifdef SHUTUP_SONIC
@@ -241,16 +237,17 @@ void __init mac_init_IRQ(void)
 }
 
 /*
- *  mac_enable_irq - enable an interrupt source
- * mac_disable_irq - disable an interrupt source
+ *  mac_irq_enable - enable an interrupt source
+ * mac_irq_disable - disable an interrupt source
  *   mac_clear_irq - clears a pending interrupt
- * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
+ * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending)
  *
  * These routines are just dispatchers to the VIA/OSS/PSC routines.
  */
 
-void mac_enable_irq(unsigned int irq)
+void mac_irq_enable(struct irq_data *data)
 {
+	int irq = data->irq;
 	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
@@ -283,8 +280,9 @@ void mac_enable_irq(unsigned int irq)
 	}
 }
 
-void mac_disable_irq(unsigned int irq)
+void mac_irq_disable(struct irq_data *data)
 {
+	int irq = data->irq;
 	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
@@ -370,7 +368,7 @@ int mac_irq_pending(unsigned int irq)
 		break;
 	case 4:
 		if (psc_present)
-			psc_irq_pending(irq);
+			return psc_irq_pending(irq);
 		break;
 	}
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/misc.c linux-libre-3.2-gnu1/arch/m68k/mac/misc.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,35 +304,41 @@ static void via_write_pram(int offset, _
 static long via_read_time(void)
 {
 	union {
-		__u8  cdata[4];
-		long  idata;
+		__u8 cdata[4];
+		long idata;
 	} result, last_result;
-	int	ct;
+	int count = 1;
+
+	via_pram_command(0x81, &last_result.cdata[3]);
+	via_pram_command(0x85, &last_result.cdata[2]);
+	via_pram_command(0x89, &last_result.cdata[1]);
+	via_pram_command(0x8D, &last_result.cdata[0]);
 
 	/*
 	 * The NetBSD guys say to loop until you get the same reading
 	 * twice in a row.
 	 */
 
-	ct = 0;
-	do {
-		if (++ct > 10) {
-			printk("via_read_time: couldn't get valid time, "
-			       "last read = 0x%08lx and 0x%08lx\n",
-			       last_result.idata, result.idata);
-			break;
-		}
-
-		last_result.idata = result.idata;
-		result.idata = 0;
-
+	while (1) {
 		via_pram_command(0x81, &result.cdata[3]);
 		via_pram_command(0x85, &result.cdata[2]);
 		via_pram_command(0x89, &result.cdata[1]);
 		via_pram_command(0x8D, &result.cdata[0]);
-	} while (result.idata != last_result.idata);
 
-	return result.idata - RTC_OFFSET;
+		if (result.idata == last_result.idata)
+			return result.idata - RTC_OFFSET;
+
+		if (++count > 10)
+			break;
+
+		last_result.idata = result.idata;
+	}
+
+	pr_err("via_read_time: failed to read a stable value; "
+	       "got 0x%08lx then 0x%08lx\n",
+	       last_result.idata, result.idata);
+
+	return 0;
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/oss.c linux-libre-3.2-gnu1/arch/m68k/mac/oss.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/oss.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/oss.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -29,10 +30,7 @@
 int oss_present;
 volatile struct mac_oss *oss;
 
-static irqreturn_t oss_irq(int, void *);
-static irqreturn_t oss_nubus_irq(int, void *);
-
-extern irqreturn_t via1_irq(int, void *);
+extern void via1_irq(unsigned int irq, struct irq_desc *desc);
 
 /*
  * Initialize the OSS
@@ -60,26 +58,6 @@ void __init oss_init(void)
 }
 
 /*
- * Register the OSS and NuBus interrupt dispatchers.
- */
-
-void __init oss_register_interrupts(void)
-{
-	if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-			"scsi", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "scsi");
-	if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-			"nubus", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "nubus");
-	if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-			"sound", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "sound");
-	if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-			"via1", (void *) via1))
-		pr_err("Couldn't register %s interrupt\n", "via1");
-}
-
-/*
  * Initialize OSS for Nubus access
  */
 
@@ -92,17 +70,17 @@ void __init oss_nubus_init(void)
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
 
-static irqreturn_t oss_irq(int irq, void *dev_id)
+static void oss_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int events;
 
 	events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 #ifdef DEBUG_IRQS
 	if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
-		printk("oss_irq: irq %d events = 0x%04X\n", irq,
+		printk("oss_irq: irq %u events = 0x%04X\n", irq,
 			(int) oss->irq_pending);
 	}
 #endif
@@ -113,11 +91,10 @@ static irqreturn_t oss_irq(int irq, void
 		/* FIXME: call sound handler */
 	} else if (events & OSS_IP_SCSI) {
 		oss->irq_pending &= ~OSS_IP_SCSI;
-		m68k_handle_int(IRQ_MAC_SCSI);
+		generic_handle_irq(IRQ_MAC_SCSI);
 	} else {
 		/* FIXME: error check here? */
 	}
-	return IRQ_HANDLED;
 }
 
 /*
@@ -126,13 +103,13 @@ static irqreturn_t oss_irq(int irq, void
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
+static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int events, irq_bit, i;
 
 	events = oss->irq_pending & OSS_IP_NUBUS;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 #ifdef DEBUG_NUBUS_INT
 	if (console_loglevel > 7) {
@@ -148,10 +125,21 @@ static irqreturn_t oss_nubus_irq(int irq
 		irq_bit >>= 1;
 		if (events & irq_bit) {
 			oss->irq_pending &= ~irq_bit;
-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+			generic_handle_irq(NUBUS_SOURCE_BASE + i);
 		}
 	} while(events & (irq_bit - 1));
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the OSS and NuBus interrupt dispatchers.
+ */
+
+void __init oss_register_interrupts(void)
+{
+	irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
+	irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
+	irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
+	irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/psc.c linux-libre-3.2-gnu1/arch/m68k/mac/psc.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/psc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/psc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -30,8 +31,6 @@
 int psc_present;
 volatile __u8 *psc;
 
-irqreturn_t psc_irq(int, void *);
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -112,52 +111,52 @@ void __init psc_init(void)
 }
 
 /*
- * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
- */
-
-void __init psc_register_interrupts(void)
-{
-	if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
-		pr_err("Couldn't register psc%d interrupt\n", 3);
-	if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
-		pr_err("Couldn't register psc%d interrupt\n", 4);
-	if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
-		pr_err("Couldn't register psc%d interrupt\n", 5);
-	if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
-		pr_err("Couldn't register psc%d interrupt\n", 6);
-}
-
-/*
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-irqreturn_t psc_irq(int irq, void *dev_id)
+static void psc_irq(unsigned int irq, struct irq_desc *desc)
 {
-	int pIFR	= pIFRbase + ((int) dev_id);
-	int pIER	= pIERbase + ((int) dev_id);
+	unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
+	int pIFR	= pIFRbase + offset;
+	int pIER	= pIERbase + offset;
 	int irq_num;
 	unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
-	printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+	printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
 		irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
 #endif
 
 	events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = irq << 3;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			psc_write_byte(pIFR, irq_bit);
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		irq_num++;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
+ */
+
+void __init psc_register_interrupts(void)
+{
+	irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
+	irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
+	irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
+	irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
 }
 
 void psc_irq_enable(int irq) {
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mac/via.c linux-libre-3.2-gnu1/arch/m68k/mac/via.c
--- linux-libre-3.1-gnu1/arch/m68k/mac/via.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mac/via.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -77,9 +78,6 @@ static int gIER,gIFR,gBufA,gBufB;
 static u8 nubus_disabled;
 
 void via_debug_dump(void);
-irqreturn_t via1_irq(int, void *);
-irqreturn_t via2_irq(int, void *);
-irqreturn_t via_nubus_irq(int, void *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
@@ -281,40 +279,11 @@ void __init via_init_clock(irq_handler_t
 	via1[vT1CL] = MAC_CLOCK_LOW;
 	via1[vT1CH] = MAC_CLOCK_HIGH;
 
-	if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
 		pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
 /*
- * Register the interrupt dispatchers for VIA or RBV machines only.
- */
-
-void __init via_register_interrupts(void)
-{
-	if (via_alt_mapping) {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "software");
-		if (request_irq(IRQ_AUTO_6, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "via1");
-	} else {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "via1");
-	}
-	if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-			"via2", (void *) via2))
-		pr_err("Couldn't register %s interrupt\n", "via2");
-	if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
-			IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
-		pr_err("Couldn't register %s interrupt\n", "nubus");
-}
-
-/*
  * Debugging dump, used in various places to see what's going on.
  */
 
@@ -446,48 +415,46 @@ void __init via_nubus_init(void)
  * via6522.c :-), disable/pending masks added.
  */
 
-irqreturn_t via1_irq(int irq, void *dev_id)
+void via1_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_num;
 	unsigned char irq_bit, events;
 
 	events = via1[vIFR] & via1[vIER] & 0x7F;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = VIA1_SOURCE_BASE;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			via1[vIFR] = irq_bit;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		++irq_num;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
 }
 
-irqreturn_t via2_irq(int irq, void *dev_id)
+static void via2_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_num;
 	unsigned char irq_bit, events;
 
 	events = via2[gIFR] & via2[gIER] & 0x7F;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = VIA2_SOURCE_BASE;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			via2[gIFR] = irq_bit | rbv_clear;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		++irq_num;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
 }
 
 /*
@@ -495,7 +462,7 @@ irqreturn_t via2_irq(int irq, void *dev_
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-irqreturn_t via_nubus_irq(int irq, void *dev_id)
+void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int slot_irq;
 	unsigned char slot_bit, events;
@@ -506,7 +473,7 @@ irqreturn_t via_nubus_irq(int irq, void
 	else
 		events &= ~via2[vDirA];
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	do {
 		slot_irq = IRQ_NUBUS_F;
@@ -514,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void
 		do {
 			if (events & slot_bit) {
 				events &= ~slot_bit;
-				m68k_handle_int(slot_irq);
+				generic_handle_irq(slot_irq);
 			}
 			--slot_irq;
 			slot_bit >>= 1;
@@ -528,7 +495,24 @@ irqreturn_t via_nubus_irq(int irq, void
 		else
 			events &= ~via2[vDirA];
 	} while (events);
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the interrupt dispatchers for VIA or RBV machines only.
+ */
+
+void __init via_register_interrupts(void)
+{
+	if (via_alt_mapping) {
+		/* software interrupt */
+		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+		/* via1 interrupt */
+		irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
+	} else {
+		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+	}
+	irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
+	irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
 }
 
 void via_irq_enable(int irq) {
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Makefile linux-libre-3.2-gnu1/arch/m68k/Makefile
--- linux-libre-3.1-gnu1/arch/m68k/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,171 @@
+#
+# m68k/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Hamish Macdonald
+# Copyright (C) 2002,2011 Greg Ungerer <gerg@snapgear.com>
+#
+
 KBUILD_DEFCONFIG := multi_defconfig
 
+#
+#	Enable processor type. Ordering of these is important - we want to
+#	use the minimum processor type of the range we support. The logic
+#	for 680x0 will only allow use of the -m68060 or -m68040 if no other
+#	680x0 type is specified - and no option is specified for 68030 or
+#	68020. The other m68k/ColdFire types always specify some type of
+#	compiler cpu type flag.
+#
+ifndef CONFIG_M68040
+cpuflags-$(CONFIG_M68060)	:= -m68060
+endif
+ifndef CONFIG_M68060
+cpuflags-$(CONFIG_M68040)	:= -m68040
+endif
+cpuflags-$(CONFIG_M68030)	:=
+cpuflags-$(CONFIG_M68020)	:=
+cpuflags-$(CONFIG_M68360)	:= -m68332
+cpuflags-$(CONFIG_M68000)	:= -m68000
+cpuflags-$(CONFIG_M54xx)	:= $(call cc-option,-mcpu=5475,-m5200)
+cpuflags-$(CONFIG_M5407)	:= $(call cc-option,-mcpu=5407,-m5200)
+cpuflags-$(CONFIG_M532x)	:= $(call cc-option,-mcpu=532x,-m5307)
+cpuflags-$(CONFIG_M5307)	:= $(call cc-option,-mcpu=5307,-m5200)
+cpuflags-$(CONFIG_M528x)	:= $(call cc-option,-mcpu=528x,-m5307)
+cpuflags-$(CONFIG_M5275)	:= $(call cc-option,-mcpu=5275,-m5307)
+cpuflags-$(CONFIG_M5272)	:= $(call cc-option,-mcpu=5272,-m5307)
+cpuflags-$(CONFIG_M5271)	:= $(call cc-option,-mcpu=5271,-m5307)
+cpuflags-$(CONFIG_M523x)	:= $(call cc-option,-mcpu=523x,-m5307)
+cpuflags-$(CONFIG_M5249)	:= $(call cc-option,-mcpu=5249,-m5200)
+cpuflags-$(CONFIG_M520x)	:= $(call cc-option,-mcpu=5208,-m5200)
+cpuflags-$(CONFIG_M5206e)	:= $(call cc-option,-mcpu=5206e,-m5200)
+cpuflags-$(CONFIG_M5206)	:= $(call cc-option,-mcpu=5206,-m5200)
+
+KBUILD_AFLAGS += $(cpuflags-y)
+KBUILD_CFLAGS += $(cpuflags-y) -pipe
 ifdef CONFIG_MMU
-include $(srctree)/arch/m68k/Makefile_mm
+# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
+KBUILD_CFLAGS += -fno-strength-reduce -ffixed-a2
 else
-include $(srctree)/arch/m68k/Makefile_no
+# we can use a m68k-linux-gcc toolchain with these in place
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+KBUILD_CFLAGS += -D__uClinux__
+KBUILD_AFLAGS += -D__uClinux__
+endif
+
+LDFLAGS := -m m68kelf
+KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
+ifneq ($(SUBARCH),$(ARCH))
+	ifeq ($(CROSS_COMPILE),)
+		CROSS_COMPILE := $(call cc-cross-prefix, \
+			m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+	endif
+endif
+
+ifdef CONFIG_SUN3
+LDFLAGS_vmlinux = -N
+endif
+
+CHECKFLAGS += -D__mc68000__
+
+
+ifdef CONFIG_KGDB
+# If configured for kgdb support, include debugging infos and keep the
+# frame pointer
+KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
+endif
+
+#
+# Select the assembler head startup code. Order is important. The default
+# head code is first, processor specific selections can override it after.
+#
+head-y				:= arch/m68k/kernel/head.o
+head-$(CONFIG_SUN3)		:= arch/m68k/kernel/sun3-head.o
+head-$(CONFIG_M68360)		:= arch/m68k/platform/68360/head.o
+head-$(CONFIG_M68000)		:= arch/m68k/platform/68328/head.o
+head-$(CONFIG_COLDFIRE)		:= arch/m68k/platform/coldfire/head.o
+
+core-y				+= arch/m68k/kernel/	arch/m68k/mm/
+libs-y				+= arch/m68k/lib/
+
+core-$(CONFIG_Q40)		+= arch/m68k/q40/
+core-$(CONFIG_AMIGA)		+= arch/m68k/amiga/
+core-$(CONFIG_ATARI)		+= arch/m68k/atari/
+core-$(CONFIG_MAC)		+= arch/m68k/mac/
+core-$(CONFIG_HP300)		+= arch/m68k/hp300/
+core-$(CONFIG_APOLLO)		+= arch/m68k/apollo/
+core-$(CONFIG_MVME147)		+= arch/m68k/mvme147/
+core-$(CONFIG_MVME16x)		+= arch/m68k/mvme16x/
+core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
+core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
+core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
+core-$(CONFIG_NATFEAT)		+= arch/m68k/emu/
+core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
+core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
+core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
+core-$(CONFIG_M68360)		+= arch/m68k/platform/68360/
+core-$(CONFIG_M68000)		+= arch/m68k/platform/68328/
+core-$(CONFIG_M68EZ328)		+= arch/m68k/platform/68EZ328/
+core-$(CONFIG_M68VZ328)		+= arch/m68k/platform/68VZ328/
+core-$(CONFIG_COLDFIRE)		+= arch/m68k/platform/coldfire/
+core-$(CONFIG_M5206)		+= arch/m68k/platform/5206/
+core-$(CONFIG_M5206e)		+= arch/m68k/platform/5206/
+core-$(CONFIG_M520x)		+= arch/m68k/platform/520x/
+core-$(CONFIG_M523x)		+= arch/m68k/platform/523x/
+core-$(CONFIG_M5249)		+= arch/m68k/platform/5249/
+core-$(CONFIG_M527x)		+= arch/m68k/platform/527x/
+core-$(CONFIG_M5272)		+= arch/m68k/platform/5272/
+core-$(CONFIG_M528x)		+= arch/m68k/platform/528x/
+core-$(CONFIG_M5307)		+= arch/m68k/platform/5307/
+core-$(CONFIG_M532x)		+= arch/m68k/platform/532x/
+core-$(CONFIG_M5407)		+= arch/m68k/platform/5407/
+core-$(CONFIG_M54xx)		+= arch/m68k/platform/54xx/
+
+
+all:	zImage
+
+lilo:	vmlinux
+	if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
+	if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+	cat vmlinux > $(INSTALL_PATH)/vmlinux
+	cp System.map $(INSTALL_PATH)/System.map
+	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+zImage compressed: vmlinux.gz
+
+vmlinux.gz: vmlinux
+
+ifndef CONFIG_KGDB
+	cp vmlinux vmlinux.tmp
+	$(STRIP) vmlinux.tmp
+	gzip -9c vmlinux.tmp >vmlinux.gz
+	rm vmlinux.tmp
+else
+	gzip -9c vmlinux >vmlinux.gz
 endif
+
+bzImage: vmlinux.bz2
+
+vmlinux.bz2: vmlinux
+
+ifndef CONFIG_KGDB
+	cp vmlinux vmlinux.tmp
+	$(STRIP) vmlinux.tmp
+	bzip2 -1c vmlinux.tmp >vmlinux.bz2
+	rm vmlinux.tmp
+else
+	bzip2 -1c vmlinux >vmlinux.bz2
+endif
+
+archclean:
+	rm -f vmlinux.gz vmlinux.bz2
+
+install:
+	sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Makefile_mm linux-libre-3.2-gnu1/arch/m68k/Makefile_mm
--- linux-libre-3.1-gnu1/arch/m68k/Makefile_mm	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-#
-# m68k/Makefile
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Hamish Macdonald
-#
-
-# override top level makefile
-AS += -m68020
-LDFLAGS := -m m68kelf
-KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(SUBARCH),$(ARCH))
-	ifeq ($(CROSS_COMPILE),)
-		CROSS_COMPILE := $(call cc-cross-prefix, \
-			m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
-	endif
-endif
-
-ifdef CONFIG_SUN3
-LDFLAGS_vmlinux = -N
-endif
-
-CHECKFLAGS += -D__mc68000__
-
-# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
-KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
-
-# enable processor switch if compiled only for a single cpu
-ifndef CONFIG_M68020
-ifndef CONFIG_M68030
-
-ifndef CONFIG_M68060
-KBUILD_CFLAGS += -m68040
-endif
-
-ifndef CONFIG_M68040
-KBUILD_CFLAGS += -m68060
-endif
-
-endif
-endif
-
-ifdef CONFIG_KGDB
-# If configured for kgdb support, include debugging infos and keep the
-# frame pointer
-KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
-endif
-
-ifndef CONFIG_SUN3
-head-y := arch/m68k/kernel/head.o
-else
-head-y := arch/m68k/kernel/sun3-head.o
-endif
-
-core-y				+= arch/m68k/kernel/	arch/m68k/mm/
-libs-y				+= arch/m68k/lib/
-
-core-$(CONFIG_Q40)		+= arch/m68k/q40/
-core-$(CONFIG_AMIGA)		+= arch/m68k/amiga/
-core-$(CONFIG_ATARI)		+= arch/m68k/atari/
-core-$(CONFIG_MAC)		+= arch/m68k/mac/
-core-$(CONFIG_HP300)		+= arch/m68k/hp300/
-core-$(CONFIG_APOLLO)		+= arch/m68k/apollo/
-core-$(CONFIG_MVME147)		+= arch/m68k/mvme147/
-core-$(CONFIG_MVME16x)		+= arch/m68k/mvme16x/
-core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
-core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
-core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
-core-$(CONFIG_NATFEAT)		+= arch/m68k/emu/
-core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
-core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
-core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
-
-all:	zImage
-
-lilo:	vmlinux
-	if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
-	if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-	cat vmlinux > $(INSTALL_PATH)/vmlinux
-	cp System.map $(INSTALL_PATH)/System.map
-	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-zImage compressed: vmlinux.gz
-
-vmlinux.gz: vmlinux
-
-ifndef CONFIG_KGDB
-	cp vmlinux vmlinux.tmp
-	$(STRIP) vmlinux.tmp
-	gzip -9c vmlinux.tmp >vmlinux.gz
-	rm vmlinux.tmp
-else
-	gzip -9c vmlinux >vmlinux.gz
-endif
-
-bzImage: vmlinux.bz2
-
-vmlinux.bz2: vmlinux
-
-ifndef CONFIG_KGDB
-	cp vmlinux vmlinux.tmp
-	$(STRIP) vmlinux.tmp
-	bzip2 -1c vmlinux.tmp >vmlinux.bz2
-	rm vmlinux.tmp
-else
-	bzip2 -1c vmlinux >vmlinux.bz2
-endif
-
-archclean:
-	rm -f vmlinux.gz vmlinux.bz2
-
-install:
-	sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff -druNp linux-libre-3.1-gnu1/arch/m68k/Makefile_no linux-libre-3.2-gnu1/arch/m68k/Makefile_no
--- linux-libre-3.1-gnu1/arch/m68k/Makefile_no	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/Makefile_no	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-#
-# arch/m68k/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
-#
-
-platform-$(CONFIG_M68328)	:= 68328
-platform-$(CONFIG_M68EZ328)	:= 68EZ328
-platform-$(CONFIG_M68VZ328)	:= 68VZ328
-platform-$(CONFIG_M68360)	:= 68360
-platform-$(CONFIG_M5206)	:= 5206
-platform-$(CONFIG_M5206e)	:= 5206
-platform-$(CONFIG_M520x)	:= 520x
-platform-$(CONFIG_M523x)	:= 523x
-platform-$(CONFIG_M5249)	:= 5249
-platform-$(CONFIG_M527x)	:= 527x
-platform-$(CONFIG_M5272)	:= 5272
-platform-$(CONFIG_M528x)	:= 528x
-platform-$(CONFIG_M5307)	:= 5307
-platform-$(CONFIG_M532x)	:= 532x
-platform-$(CONFIG_M5407)	:= 5407
-platform-$(CONFIG_M54xx)	:= 54xx
-PLATFORM := $(platform-y)
-
-board-$(CONFIG_PILOT)		:= pilot
-board-$(CONFIG_UC5272)          := UC5272
-board-$(CONFIG_UC5282)          := UC5282
-board-$(CONFIG_UCSIMM)		:= ucsimm
-board-$(CONFIG_UCDIMM)		:= ucdimm
-board-$(CONFIG_UCQUICC)		:= uCquicc
-board-$(CONFIG_DRAGEN2)		:= de2
-board-$(CONFIG_ARNEWSH)		:= ARNEWSH
-board-$(CONFIG_FREESCALE)	:= FREESCALE
-board-$(CONFIG_M5235EVB)	:= M5235EVB
-board-$(CONFIG_M5271EVB)	:= M5271EVB
-board-$(CONFIG_M5275EVB)	:= M5275EVB
-board-$(CONFIG_M5282EVB)	:= M5282EVB
-board-$(CONFIG_ELITE)		:= eLITE
-board-$(CONFIG_NETtel)		:= NETtel
-board-$(CONFIG_SECUREEDGEMP3)	:= MP3
-board-$(CONFIG_CLEOPATRA)	:= CLEOPATRA
-board-$(CONFIG_senTec)		:= senTec
-board-$(CONFIG_SNEHA) 	        := SNEHA
-board-$(CONFIG_M5208EVB)	:= M5208EVB
-board-$(CONFIG_MOD5272)		:= MOD5272
-board-$(CONFIG_AVNET)           := AVNET
-board-$(CONFIG_SAVANT)		:= SAVANT
-BOARD := $(board-y)
-
-model-$(CONFIG_RAMKERNEL)	:= ram
-model-$(CONFIG_ROMKERNEL)	:= rom
-MODEL := $(model-y)
-
-#
-# Some code support is grouped together for a common cpu-subclass (for
-# example all ColdFire cpu's are very similar). Determine the sub-class
-# for the selected cpu. ONLY need to define this for the non-base member
-# of the family.
-#
-cpuclass-$(CONFIG_M5206)	:= coldfire
-cpuclass-$(CONFIG_M5206e)	:= coldfire
-cpuclass-$(CONFIG_M520x)	:= coldfire
-cpuclass-$(CONFIG_M523x)	:= coldfire
-cpuclass-$(CONFIG_M5249)	:= coldfire
-cpuclass-$(CONFIG_M527x)	:= coldfire
-cpuclass-$(CONFIG_M5272)	:= coldfire
-cpuclass-$(CONFIG_M528x)	:= coldfire
-cpuclass-$(CONFIG_M5307)	:= coldfire
-cpuclass-$(CONFIG_M532x)	:= coldfire
-cpuclass-$(CONFIG_M5407)	:= coldfire
-cpuclass-$(CONFIG_M54xx)	:= coldfire
-cpuclass-$(CONFIG_M68328)	:= 68328
-cpuclass-$(CONFIG_M68EZ328)	:= 68328
-cpuclass-$(CONFIG_M68VZ328)	:= 68328
-cpuclass-$(CONFIG_M68360)	:= 68360
-CPUCLASS := $(cpuclass-y)
-
-ifneq ($(CPUCLASS),$(PLATFORM))
-CLASSDIR := arch/m68k/platform/$(cpuclass-y)/
-endif
-
-export PLATFORM BOARD MODEL CPUCLASS
-
-#
-# Some CFLAG additions based on specific CPU type.
-#
-cflags-$(CONFIG_M5206)		:= $(call cc-option,-mcpu=5206,-m5200)
-cflags-$(CONFIG_M5206e)		:= $(call cc-option,-mcpu=5206e,-m5200)
-cflags-$(CONFIG_M520x)		:= $(call cc-option,-mcpu=5208,-m5200)
-cflags-$(CONFIG_M523x)		:= $(call cc-option,-mcpu=523x,-m5307)
-cflags-$(CONFIG_M5249)		:= $(call cc-option,-mcpu=5249,-m5200)
-cflags-$(CONFIG_M5271)		:= $(call cc-option,-mcpu=5271,-m5307)
-cflags-$(CONFIG_M5272)		:= $(call cc-option,-mcpu=5272,-m5307)
-cflags-$(CONFIG_M5275)		:= $(call cc-option,-mcpu=5275,-m5307)
-cflags-$(CONFIG_M528x)		:= $(call cc-option,-mcpu=528x,-m5307)
-cflags-$(CONFIG_M5307)		:= $(call cc-option,-mcpu=5307,-m5200)
-cflags-$(CONFIG_M532x)		:= $(call cc-option,-mcpu=532x,-m5307)
-cflags-$(CONFIG_M5407)		:= $(call cc-option,-mcpu=5407,-m5200)
-cflags-$(CONFIG_M54xx)		:= $(call cc-option,-mcpu=5475,-m5200)
-cflags-$(CONFIG_M68328)		:= -m68000
-cflags-$(CONFIG_M68EZ328)	:= -m68000
-cflags-$(CONFIG_M68VZ328)	:= -m68000
-cflags-$(CONFIG_M68360)		:= -m68332
-
-KBUILD_AFLAGS += $(cflags-y)
-
-KBUILD_CFLAGS += $(cflags-y)
-KBUILD_CFLAGS += -D__linux__
-KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-
-head-y := arch/m68k/platform/$(cpuclass-y)/head.o
-
-core-y	+= arch/m68k/kernel/ \
-	   arch/m68k/mm/ \
-	   $(CLASSDIR) \
-	   arch/m68k/platform/$(PLATFORM)/
-libs-y	+= arch/m68k/lib/
-
-archclean:
-
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mm/init_no.c linux-libre-3.2-gnu1/arch/m68k/mm/init_no.c
--- linux-libre-3.1-gnu1/arch/m68k/mm/init_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mm/init_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/gfp.h>
 
 #include <asm/setup.h>
+#include <asm/sections.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -44,9 +45,6 @@
  */
 void *empty_zero_page;
 
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
 /*
  * paging_init() continues the virtual memory environment setup which
  * was begun by the code in arch/head.S.
@@ -78,8 +76,6 @@ void __init mem_init(void)
 {
 	int codek = 0, datak = 0, initk = 0;
 	unsigned long tmp;
-	extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
-	extern unsigned int _ramend, _rambase;
 	unsigned long len = _ramend - _rambase;
 	unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
 	unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
@@ -95,9 +91,9 @@ void __init mem_init(void)
 	/* this will put all memory onto the freelists */
 	totalram_pages = free_all_bootmem();
 
-	codek = (&_etext - &_stext) >> 10;
-	datak = (&_ebss - &_sdata) >> 10;
-	initk = (&__init_begin - &__init_end) >> 10;
+	codek = (_etext - _stext) >> 10;
+	datak = (_ebss - _sdata) >> 10;
+	initk = (__init_begin - __init_end) >> 10;
 
 	tmp = nr_free_pages() << PAGE_SHIFT;
 	printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
@@ -129,22 +125,21 @@ void free_initmem(void)
 {
 #ifdef CONFIG_RAMKERNEL
 	unsigned long addr;
-	extern char __init_begin, __init_end;
 	/*
 	 * The following code should be cool even if these sections
 	 * are not page aligned.
 	 */
-	addr = PAGE_ALIGN((unsigned long)(&__init_begin));
+	addr = PAGE_ALIGN((unsigned long) __init_begin);
 	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
+	for (; addr + PAGE_SIZE < ((unsigned long) __init_end); addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
 		free_page(addr);
 		totalram_pages++;
 	}
 	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
-			(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
-			(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
+			(addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10,
+			(int)(PAGE_ALIGN((unsigned long) __init_begin)),
 			(int)(addr - PAGE_SIZE));
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mvme147/config.c linux-libre-3.2-gnu1/arch/m68k/mvme147/config.c
--- linux-libre-3.1-gnu1/arch/m68k/mvme147/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mvme147/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@ static void mvme147_get_model(char *mode
 
 void __init mvme147_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_mvme147(void)
@@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (in
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
 	tick_handler = timer_routine;
-	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
-			"timer 1", NULL))
+	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
 		pr_err("Couldn't register timer interrupt\n");
 
 	/* Init the clock with a value */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/mvme16x/config.c linux-libre-3.2-gnu1/arch/m68k/mvme16x/config.c
--- linux-libre-3.1-gnu1/arch/m68k/mvme16x/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/mvme16x/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(st
 
 static void __init mvme16x_init_IRQ (void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 #define pcc2chip	((volatile u_char *)0xfff42000)
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/520x/config.c linux-libre-3.2-gnu1/arch/m68k/platform/520x/config.c
--- linux-libre-3.1-gnu1/arch/m68k/platform/520x/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/520x/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -91,9 +91,9 @@ static struct resource m520x_qspi_resour
 	},
 };
 
-#define MCFQSPI_CS0    62
-#define MCFQSPI_CS1    63
-#define MCFQSPI_CS2    44
+#define MCFQSPI_CS0    46
+#define MCFQSPI_CS1    47
+#define MCFQSPI_CS2    27
 
 static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
 {
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/520x/gpio.c linux-libre-3.2-gnu1/arch/m68k/platform/520x/gpio.c
--- linux-libre-3.1-gnu1/arch/m68k/platform/520x/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/520x/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,42 +38,6 @@ static struct mcf_gpio_chip mcf_gpio_chi
 	},
 	{
 		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 8,
-			.ngpio			= 4,
-		},
-		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
-		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
-		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BE",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 4,
-		},
-		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
-		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
-		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
-		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
-		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
-	},
-	{
-		.gpio_chip			= {
 			.label			= "CS",
 			.request		= mcf_gpio_request,
 			.free			= mcf_gpio_free,
@@ -81,7 +45,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 25,
+			.base			= 9,
 			.ngpio			= 3,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
@@ -99,7 +63,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
+			.base			= 16,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
@@ -117,7 +81,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
+			.base			= 24,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
@@ -135,7 +99,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 48,
+			.base			= 32,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
@@ -153,7 +117,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
+			.base			= 40,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
@@ -171,7 +135,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
+			.base			= 48,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
@@ -189,7 +153,7 @@ static struct mcf_gpio_chip mcf_gpio_chi
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
+			.base			= 56,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/68328/entry.S linux-libre-3.2-gnu1/arch/m68k/platform/68328/entry.S
--- linux-libre-3.1-gnu1/arch/m68k/platform/68328/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/68328/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -67,7 +67,7 @@ ret_from_signal:
 	jra	ret_from_exception
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 
 	/* save top of frame*/
 	pea	%sp@
@@ -129,7 +129,7 @@ Lsignal_return:
  * This is the main interrupt handler, responsible for calling process_int()
  */
 inthandler1:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -140,7 +140,7 @@ inthandler1:
 	bra	ret_from_interrupt
 
 inthandler2:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -151,7 +151,7 @@ inthandler2:
 	bra	ret_from_interrupt
 
 inthandler3:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -162,7 +162,7 @@ inthandler3:
 	bra	ret_from_interrupt
 
 inthandler4:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -173,7 +173,7 @@ inthandler4:
 	bra	ret_from_interrupt
 
 inthandler5:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -184,7 +184,7 @@ inthandler5:
 	bra	ret_from_interrupt
 
 inthandler6:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -195,7 +195,7 @@ inthandler6:
 	bra	ret_from_interrupt
 
 inthandler7:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -206,7 +206,7 @@ inthandler7:
 	bra	ret_from_interrupt
 
 inthandler:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/68328/Makefile linux-libre-3.2-gnu1/arch/m68k/platform/68328/Makefile
--- linux-libre-3.1-gnu1/arch/m68k/platform/68328/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/68328/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,10 @@
 # Makefile for arch/m68knommu/platform/68328.
 #
 
-head-y			= head-$(MODEL).o
+model-y			  := ram
+model-$(CONFIG_ROMKERNEL) := rom
+
+head-y			= head-$(model-y).o
 head-$(CONFIG_PILOT)	= head-pilot.o
 head-$(CONFIG_DRAGEN2)	= head-de2.o
 
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/68360/entry.S linux-libre-3.2-gnu1/arch/m68k/platform/68360/entry.S
--- linux-libre-3.1-gnu1/arch/m68k/platform/68360/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/68360/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@ ret_from_signal:
 	jra	ret_from_exception
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 
 	/* save top of frame*/
 	pea	%sp@
@@ -125,7 +125,7 @@ Lsignal_return:
  * This is the main interrupt handler, responsible for calling do_IRQ()
  */
 inthandler:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and.l	#0x3ff, %d0
 	lsr.l   #0x02,  %d0
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/68360/Makefile linux-libre-3.2-gnu1/arch/m68k/platform/68360/Makefile
--- linux-libre-3.1-gnu1/arch/m68k/platform/68360/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/68360/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,12 @@
 #
 # Makefile for arch/m68knommu/platform/68360.
 #
+model-y			  := ram
+model-$(CONFIG_ROMKERNEL) := rom
 
 obj-y := config.o commproc.o entry.o ints.o
 
 extra-y := head.o
 
-$(obj)/head.o: $(obj)/head-$(MODEL).o
-	ln -sf head-$(MODEL).o $(obj)/head.o
+$(obj)/head.o: $(obj)/head-$(model-y).o
+	ln -sf head-$(model-y).o $(obj)/head.o
diff -druNp linux-libre-3.1-gnu1/arch/m68k/platform/coldfire/entry.S linux-libre-3.2-gnu1/arch/m68k/platform/coldfire/entry.S
--- linux-libre-3.1-gnu1/arch/m68k/platform/coldfire/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/platform/coldfire/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@ enosys:
 	bra	1f
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 	move	#0x2000,%sr		/* enable intrs again */
 
 	cmpl	#NR_syscalls,%d0
@@ -165,9 +165,7 @@ Lsignal_return:
  * sources). Calls up to high level code to do all the work.
  */
 ENTRY(inthandler)
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+	SAVE_ALL_INT
 
 	movew	%sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
 	andl	#0x03fc,%d0		/* mask out vector only */
diff -druNp linux-libre-3.1-gnu1/arch/m68k/q40/q40ints.c linux-libre-3.2-gnu1/arch/m68k/q40/q40ints.c
--- linux-libre-3.1-gnu1/arch/m68k/q40/q40ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/q40/q40ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,10 +15,10 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
-#include <asm/irq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
@@ -35,35 +35,36 @@
 */
 
 static void q40_irq_handler(unsigned int, struct pt_regs *fp);
-static void q40_enable_irq(unsigned int);
-static void q40_disable_irq(unsigned int);
+static void q40_irq_enable(struct irq_data *data);
+static void q40_irq_disable(struct irq_data *data);
 
 unsigned short q40_ablecount[35];
 unsigned short q40_state[35];
 
-static int q40_irq_startup(unsigned int irq)
+static unsigned int q40_irq_startup(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	/* test for ISA ints not implemented by HW */
 	switch (irq) {
 	case 1: case 2: case 8: case 9:
 	case 11: case 12: case 13:
 		printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
-		return -ENXIO;
+		/* FIXME return -ENXIO; */
 	}
 	return 0;
 }
 
-static void q40_irq_shutdown(unsigned int irq)
+static void q40_irq_shutdown(struct irq_data *data)
 {
 }
 
-static struct irq_controller q40_irq_controller = {
+static struct irq_chip q40_irq_chip = {
 	.name		= "q40",
-	.lock		= __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
-	.startup	= q40_irq_startup,
-	.shutdown	= q40_irq_shutdown,
-	.enable		= q40_enable_irq,
-	.disable	= q40_disable_irq,
+	.irq_startup	= q40_irq_startup,
+	.irq_shutdown	= q40_irq_shutdown,
+	.irq_enable	= q40_irq_enable,
+	.irq_disable	= q40_irq_disable,
 };
 
 /*
@@ -81,13 +82,14 @@ static int disabled;
 
 void __init q40_init_IRQ(void)
 {
-	m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
+	m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
+				  Q40_IRQ_MAX);
 
 	/* setup handler for ISA ints */
 	m68k_setup_auto_interrupt(q40_irq_handler);
 
-	m68k_irq_startup(IRQ_AUTO_2);
-	m68k_irq_startup(IRQ_AUTO_4);
+	m68k_irq_startup_irq(IRQ_AUTO_2);
+	m68k_irq_startup_irq(IRQ_AUTO_4);
 
 	/* now enable some ints.. */
 	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
@@ -218,11 +220,11 @@ static void q40_irq_handler(unsigned int
 	switch (irq) {
 	case 4:
 	case 6:
-		__m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+		do_IRQ(Q40_IRQ_SAMPLE, fp);
 		return;
 	}
 	if (mir & Q40_IRQ_FRAME_MASK) {
-		__m68k_handle_int(Q40_IRQ_FRAME, fp);
+		do_IRQ(Q40_IRQ_FRAME, fp);
 		master_outb(-1, FRAME_CLEAR_REG);
 	}
 	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
@@ -257,7 +259,7 @@ static void q40_irq_handler(unsigned int
 					goto iirq;
 				}
 				q40_state[irq] |= IRQ_INPROGRESS;
-				__m68k_handle_int(irq, fp);
+				do_IRQ(irq, fp);
 				q40_state[irq] &= ~IRQ_INPROGRESS;
 
 				/* naively enable everything, if that fails than    */
@@ -288,25 +290,29 @@ static void q40_irq_handler(unsigned int
 	mir = master_inb(IIRQ_REG);
 	/* should test whether keyboard irq is really enabled, doing it in defhand */
 	if (mir & Q40_IRQ_KEYB_MASK)
-		__m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+		do_IRQ(Q40_IRQ_KEYBOARD, fp);
 
 	return;
 }
 
-void q40_enable_irq(unsigned int irq)
+void q40_irq_enable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq >= 5 && irq <= 15) {
 		mext_disabled--;
 		if (mext_disabled > 0)
-			printk("q40_enable_irq : nested disable/enable\n");
+			printk("q40_irq_enable : nested disable/enable\n");
 		if (mext_disabled == 0)
 			master_outb(1, EXT_ENABLE_REG);
 	}
 }
 
 
-void q40_disable_irq(unsigned int irq)
+void q40_irq_disable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	/* disable ISA iqs : only do something if the driver has been
 	 * verified to be Q40 "compatible" - right now IDE, NE2K
 	 * Any driver should not attempt to sleep across disable_irq !!
@@ -319,13 +325,3 @@ void q40_disable_irq(unsigned int irq)
 			printk("disable_irq nesting count %d\n",mext_disabled);
 	}
 }
-
-unsigned long q40_probe_irq_on(void)
-{
-	printk("irq probing not working - reconfigure the driver to avoid this\n");
-	return -1;
-}
-int q40_probe_irq_off(unsigned long irqs)
-{
-	return -1;
-}
diff -druNp linux-libre-3.1-gnu1/arch/m68k/q40/README linux-libre-3.2-gnu1/arch/m68k/q40/README
--- linux-libre-3.1-gnu1/arch/m68k/q40/README	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/q40/README	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@ drivers used by the Q40, apart from the
 		char/joystick/*		# most of this should work, not
 				        # in default config.in
 	        block/q40ide.c		# startup for ide
-		      ide*		# see Documentation/ide.txt
+		      ide*		# see Documentation/ide/ide.txt
 		      floppy.c		# normal PC driver, DMA emu in asm/floppy.h
 					# and arch/m68k/kernel/entry.S
 					# see drivers/block/README.fd
diff -druNp linux-libre-3.1-gnu1/arch/m68k/sun3/sun3ints.c linux-libre-3.2-gnu1/arch/m68k/sun3/sun3ints.c
--- linux-libre-3.1-gnu1/arch/m68k/sun3/sun3ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/m68k/sun3/sun3ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,25 +51,29 @@ void sun3_disable_irq(unsigned int irq)
 
 static irqreturn_t sun3_int7(int irq, void *dev_id)
 {
-	*sun3_intreg |=  (1 << irq);
-	if (!(kstat_cpu(0).irqs[irq] % 2000))
-		sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
+	unsigned int cnt;
+
+	cnt = kstat_irqs_cpu(irq, 0);
+	if (!(cnt % 2000))
+		sun3_leds(led_pattern[cnt % 16000 / 2000]);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
+	unsigned int cnt;
+
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        *sun3_intreg |=  (1 << irq);
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
 	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
-        if (!(kstat_cpu(0).irqs[irq] % 20))
-                sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
+	cnt = kstat_irqs_cpu(irq, 0);
+	if (!(cnt % 20))
+		sun3_leds(led_pattern[cnt % 160 / 20]);
 	return IRQ_HANDLED;
 }
 
@@ -79,29 +83,33 @@ static irqreturn_t sun3_vec255(int irq,
 	return IRQ_HANDLED;
 }
 
-static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+static void sun3_irq_enable(struct irq_data *data)
 {
-        *sun3_intreg &= ~(1 << irq);
+    sun3_enable_irq(data->irq);
+};
 
-	__m68k_handle_int(irq, fp);
-}
+static void sun3_irq_disable(struct irq_data *data)
+{
+    sun3_disable_irq(data->irq);
+};
 
-static struct irq_controller sun3_irq_controller = {
+static struct irq_chip sun3_irq_chip = {
 	.name		= "sun3",
-	.lock		= __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
-	.enable		= sun3_enable_irq,
-	.disable	= sun3_disable_irq,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
+	.irq_enable	= sun3_irq_enable,
+	.irq_disable	= sun3_irq_disable,
+	.irq_mask	= sun3_irq_disable,
+	.irq_unmask	= sun3_irq_enable,
 };
 
 void __init sun3_init_IRQ(void)
 {
 	*sun3_intreg = 1;
 
-	m68k_setup_auto_interrupt(sun3_inthandle);
-	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-	m68k_setup_user_interrupt(VEC_USER, 128, NULL);
+	m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
+				  7);
+	m68k_setup_user_interrupt(VEC_USER, 128);
 
 	if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
 		pr_err("Couldn't register %s interrupt\n", "int5");
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/microblaze/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/microblaze/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #define _ASM_MICROBLAZE_DMA_MAPPING_H
 
 /*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  */
 
@@ -28,12 +28,12 @@
 #include <linux/dma-attrs.h>
 #include <asm/io.h>
 #include <asm-generic/dma-coherent.h>
+#include <asm/cacheflush.h>
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
 #define __dma_alloc_coherent(dev, gfp, size, handle)	NULL
 #define __dma_free_coherent(size, addr)		((void)0)
-#define __dma_sync(addr, size, rw)		((void)0)
 
 static inline unsigned long device_to_mask(struct device *dev)
 {
@@ -95,6 +95,22 @@ static inline int dma_set_mask(struct de
 
 #include <asm-generic/dma-mapping-common.h>
 
+static inline void __dma_sync(unsigned long paddr,
+			      size_t size, enum dma_data_direction direction)
+{
+	switch (direction) {
+	case DMA_TO_DEVICE:
+	case DMA_BIDIRECTIONAL:
+		flush_dcache_range(paddr, paddr + size);
+		break;
+	case DMA_FROM_DEVICE:
+		invalidate_dcache_range(paddr, paddr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
@@ -135,7 +151,7 @@ static inline void dma_cache_sync(struct
 		enum dma_data_direction direction)
 {
 	BUG_ON(direction == DMA_NONE);
-	__dma_sync(vaddr, size, (int)direction);
+	__dma_sync(virt_to_phys(vaddr), size, (int)direction);
 }
 
 #endif	/* _ASM_MICROBLAZE_DMA_MAPPING_H */
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/include/asm/elf.h linux-libre-3.2-gnu1/arch/microblaze/include/asm/elf.h
--- linux-libre-3.1-gnu1/arch/microblaze/include/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,13 +16,15 @@
  * I've snaffled the value from the microblaze binutils source code
  * /binutils/microblaze/include/elf/microblaze.h
  */
-#define EM_XILINX_MICROBLAZE	0xbaab
-#define ELF_ARCH		EM_XILINX_MICROBLAZE
+#define EM_MICROBLAZE		189
+#define EM_MICROBLAZE_OLD	0xbaab
+#define ELF_ARCH		EM_MICROBLAZE
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x)	((x)->e_machine == EM_XILINX_MICROBLAZE)
+#define elf_check_arch(x)	((x)->e_machine == EM_MICROBLAZE \
+				 || (x)->e_machine == EM_MICROBLAZE_OLD)
 
 /*
  * These are used to set parameters in the core dumps.
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/include/asm/namei.h linux-libre-3.2-gnu1/arch/microblaze/include/asm/namei.h
--- linux-libre-3.1-gnu1/arch/microblaze/include/asm/namei.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/include/asm/namei.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_NAMEI_H
-#define _ASM_MICROBLAZE_NAMEI_H
-
-#ifdef __KERNEL__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_NAMEI_H */
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/include/asm/system.h linux-libre-3.2-gnu1/arch/microblaze/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/microblaze/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 #include <asm-generic/cmpxchg.h>
 #include <asm-generic/cmpxchg-local.h>
 
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
 struct task_struct;
 struct thread_info;
 
@@ -96,11 +94,4 @@ extern struct dentry *of_debugfs_root;
 
 #define arch_align_stack(x) (x)
 
-/*
- * MicroBlaze doesn't handle unaligned accesses in hardware.
- *
- * Based on this we force the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN	2
-
 #endif /* _ASM_MICROBLAZE_SYSTEM_H */
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/include/asm/uaccess.h linux-libre-3.2-gnu1/arch/microblaze/include/asm/uaccess.h
--- linux-libre-3.1-gnu1/arch/microblaze/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@ static inline int ___range_ok(unsigned l
  *  - "addr", "addr + size" and "size" are all below the limit
  */
 #define access_ok(type, addr, size) \
-	(get_fs().seg > (((unsigned long)(addr)) | \
+	(get_fs().seg >= (((unsigned long)(addr)) | \
 		(size) | ((unsigned long)(addr) + (size))))
 
 /* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n",
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-3.2-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@ const struct cpu_ver_key cpu_ver_lookup[
 	{"8.00.a", 0x12},
 	{"8.00.b", 0x13},
 	{"8.10.a", 0x14},
+	{"8.20.a", 0x15},
 	{NULL, 0},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/dma.c linux-libre-3.2-gnu1/arch/microblaze/kernel/dma.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
 #include <linux/dma-debug.h>
+#include <linux/export.h>
 #include <asm/bug.h>
-#include <asm/cacheflush.h>
 
 /*
  * Generic direct DMA implementation
@@ -21,21 +21,6 @@
  * can set archdata.dma_data to an unsigned long holding the offset. By
  * default the offset is PCI_DRAM_OFFSET.
  */
-static inline void __dma_sync_page(unsigned long paddr, unsigned long offset,
-				size_t size, enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_TO_DEVICE:
-	case DMA_BIDIRECTIONAL:
-		flush_dcache_range(paddr + offset, paddr + offset + size);
-		break;
-	case DMA_FROM_DEVICE:
-		invalidate_dcache_range(paddr + offset, paddr + offset + size);
-		break;
-	default:
-		BUG();
-	}
-}
 
 static unsigned long get_dma_direct_offset(struct device *dev)
 {
@@ -91,7 +76,7 @@ static int dma_direct_map_sg(struct devi
 	/* FIXME this part of code is untested */
 	for_each_sg(sgl, sg, nents, i) {
 		sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
-		__dma_sync_page(page_to_phys(sg_page(sg)), sg->offset,
+		__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
 							sg->length, direction);
 	}
 
@@ -116,7 +101,7 @@ static inline dma_addr_t dma_direct_map_
 					     enum dma_data_direction direction,
 					     struct dma_attrs *attrs)
 {
-	__dma_sync_page(page_to_phys(page), offset, size, direction);
+	__dma_sync(page_to_phys(page) + offset, size, direction);
 	return page_to_phys(page) + offset + get_dma_direct_offset(dev);
 }
 
@@ -131,7 +116,63 @@ static inline void dma_direct_unmap_page
  * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
  * dma_address is physical address
  */
-	__dma_sync_page(dma_address, 0 , size, direction);
+	__dma_sync(dma_address, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_cpu(struct device *dev,
+			       dma_addr_t dma_handle, size_t size,
+			       enum dma_data_direction direction)
+{
+	/*
+	 * It's pointless to flush the cache as the memory segment
+	 * is given to the CPU
+	 */
+
+	if (direction == DMA_FROM_DEVICE)
+		__dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_device(struct device *dev,
+				  dma_addr_t dma_handle, size_t size,
+				  enum dma_data_direction direction)
+{
+	/*
+	 * It's pointless to invalidate the cache if the device isn't
+	 * supposed to write to the relevant region
+	 */
+
+	if (direction == DMA_TO_DEVICE)
+		__dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_cpu(struct device *dev,
+			   struct scatterlist *sgl, int nents,
+			   enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	/* FIXME this part of code is untested */
+	if (direction == DMA_FROM_DEVICE)
+		for_each_sg(sgl, sg, nents, i)
+			__dma_sync(sg->dma_address, sg->length, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_device(struct device *dev,
+			      struct scatterlist *sgl, int nents,
+			      enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	/* FIXME this part of code is untested */
+	if (direction == DMA_TO_DEVICE)
+		for_each_sg(sgl, sg, nents, i)
+			__dma_sync(sg->dma_address, sg->length, direction);
 }
 
 struct dma_map_ops dma_direct_ops = {
@@ -142,6 +183,10 @@ struct dma_map_ops dma_direct_ops = {
 	.dma_supported	= dma_direct_dma_supported,
 	.map_page	= dma_direct_map_page,
 	.unmap_page	= dma_direct_unmap_page,
+	.sync_single_for_cpu		= dma_direct_sync_single_for_cpu,
+	.sync_single_for_device		= dma_direct_sync_single_for_device,
+	.sync_sg_for_cpu		= dma_direct_sync_sg_for_cpu,
+	.sync_sg_for_device		= dma_direct_sync_sg_for_device,
 };
 EXPORT_SYMBOL(dma_direct_ops);
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/exceptions.c linux-libre-3.2-gnu1/arch/microblaze/kernel/exceptions.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/exceptions.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/exceptions.c	2012-01-04 18:55:44.000000000 -0500
@@ -119,7 +119,7 @@ asmlinkage void full_exception(struct pt
 	case MICROBLAZE_DIV_ZERO_EXCEPTION:
 		if (user_mode(regs)) {
 			pr_debug("Divide by zero exception in user mode\n");
-			_exception(SIGILL, regs, FPE_INTDIV, addr);
+			_exception(SIGFPE, regs, FPE_INTDIV, addr);
 			return;
 		}
 		printk(KERN_WARNING "Divide by zero exception " \
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/irq.c linux-libre-3.2-gnu1/arch/microblaze/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/of_irq.h>
+#include <linux/export.h>
 
 #include <asm/prom.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/process.c linux-libre-3.2-gnu1/arch/microblaze/kernel/process.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,6 +179,7 @@ int copy_thread(unsigned long clone_flag
 
 	ti->cpu_context.msr = (childregs->msr|MSR_VM);
 	ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */
+	ti->cpu_context.msr &= ~MSR_IE;
 #endif
 	ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/ptrace.c linux-libre-3.2-gnu1/arch/microblaze/kernel/ptrace.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@ asmlinkage long do_syscall_trace_enter(s
 		ret = -1L;
 
 	if (unlikely(current->audit_context))
-		audit_syscall_entry(EM_XILINX_MICROBLAZE, regs->r12,
+		audit_syscall_entry(EM_MICROBLAZE, regs->r12,
 				    regs->r5, regs->r6,
 				    regs->r7, regs->r8);
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/kernel/timer.c linux-libre-3.2-gnu1/arch/microblaze/kernel/timer.c
--- linux-libre-3.1-gnu1/arch/microblaze/kernel/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/kernel/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -308,7 +308,8 @@ unsigned long long notrace sched_clock(v
 {
 	if (timer_initialized) {
 		struct clocksource *cs = &clocksource_microblaze;
-		cycle_t cyc = cnt32_to_63(cs->read(NULL));
+
+		cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX;
 		return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
 	}
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/lib/Makefile linux-libre-3.2-gnu1/arch/microblaze/lib/Makefile
--- linux-libre-3.1-gnu1/arch/microblaze/lib/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/lib/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -25,5 +25,6 @@ lib-y += lshrdi3.o
 lib-y += modsi3.o
 lib-y += muldi3.o
 lib-y += mulsi3.o
+lib-y += ucmpdi2.o
 lib-y += udivsi3.o
 lib-y += umodsi3.o
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/lib/uaccess_old.S linux-libre-3.2-gnu1/arch/microblaze/lib/uaccess_old.S
--- linux-libre-3.1-gnu1/arch/microblaze/lib/uaccess_old.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/lib/uaccess_old.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/errno.h>
 #include <linux/linkage.h>
+#include <asm/page.h>
 
 /*
  * int __strncpy_user(char *to, char *from, int len);
@@ -33,8 +34,8 @@ __strncpy_user:
 	 * r3 - temp count
 	 * r4 - temp val
 	 */
+	beqid	r7,3f
 	addik	r3,r7,0		/* temp_count = len */
-	beqi	r3,3f
 1:
 	lbu	r4,r6,r0
 	sb	r4,r5,r0
@@ -76,8 +77,8 @@ __strncpy_user:
 .type  __strnlen_user, @function
 .align 4;
 __strnlen_user:
+	beqid	r6,3f
 	addik	r3,r6,0
-	beqi	r3,3f
 1:
 	lbu	r4,r5,r0
 	beqid	r4,2f		/* break on NUL */
@@ -102,6 +103,49 @@ __strnlen_user:
 	.section	__ex_table,"a"
 	.word	1b,4b
 
+/* Loop unrolling for __copy_tofrom_user */
+#define COPY(offset)	\
+1:	lwi	r4 , r6, 0x0000 + offset;	\
+2:	lwi	r19, r6, 0x0004 + offset;	\
+3:	lwi	r20, r6, 0x0008 + offset;	\
+4:	lwi	r21, r6, 0x000C + offset;	\
+5:	lwi	r22, r6, 0x0010 + offset;	\
+6:	lwi	r23, r6, 0x0014 + offset;	\
+7:	lwi	r24, r6, 0x0018 + offset;	\
+8:	lwi	r25, r6, 0x001C + offset;	\
+9:	swi	r4 , r5, 0x0000 + offset;	\
+10:	swi	r19, r5, 0x0004 + offset;	\
+11:	swi	r20, r5, 0x0008 + offset;	\
+12:	swi	r21, r5, 0x000C + offset;	\
+13:	swi	r22, r5, 0x0010 + offset;	\
+14:	swi	r23, r5, 0x0014 + offset;	\
+15:	swi	r24, r5, 0x0018 + offset;	\
+16:	swi	r25, r5, 0x001C + offset;	\
+	.section __ex_table,"a";		\
+	.word	1b, 0f;				\
+	.word	2b, 0f;				\
+	.word	3b, 0f;				\
+	.word	4b, 0f;				\
+	.word	5b, 0f;				\
+	.word	6b, 0f;				\
+	.word	7b, 0f;				\
+	.word	8b, 0f;				\
+	.word	9b, 0f;				\
+	.word	10b, 0f;			\
+	.word	11b, 0f;			\
+	.word	12b, 0f;			\
+	.word	13b, 0f;			\
+	.word	14b, 0f;			\
+	.word	15b, 0f;			\
+	.word	16b, 0f;			\
+	.text
+
+#define COPY_80(offset)	\
+	COPY(0x00 + offset);\
+	COPY(0x20 + offset);\
+	COPY(0x40 + offset);\
+	COPY(0x60 + offset);
+
 /*
  * int __copy_tofrom_user(char *to, char *from, int len)
  * Return:
@@ -119,34 +163,79 @@ __copy_tofrom_user:
 	 * r7, r3 - count
 	 * r4 - tempval
 	 */
-	beqid	r7, 3f /* zero size is not likely */
-	andi	r3, r7, 0x3 /* filter add count */
-	bneid	r3, 4f /* if is odd value then byte copying */
+	beqid	r7, 0f /* zero size is not likely */
 	or	r3, r5, r6 /* find if is any to/from unaligned */
-	andi	r3, r3, 0x3 /* mask unaligned */
-	bneid	r3, 1f /* it is unaligned -> then jump */
+	or	r3, r3, r7 /* find if count is unaligned */
+	andi	r3, r3, 0x3 /* mask last 3 bits */
+	bneid	r3, bu1 /* if r3 is not zero then byte copying */
 	or	r3, r0, r0
 
-/* at least one 4 byte copy */
-5:	lw	r4, r6, r3
-6:	sw	r4, r5, r3
+	rsubi	r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
+	beqid	r3, page;
+	or	r3, r0, r0
+
+w1:	lw	r4, r6, r3 /* at least one 4 byte copy */
+w2:	sw	r4, r5, r3
 	addik	r7, r7, -4
-	bneid	r7, 5b
+	bneid	r7, w1
 	addik	r3, r3, 4
 	addik	r3, r7, 0
 	rtsd	r15, 8
 	nop
-4:	or	r3, r0, r0
-1:	lbu	r4,r6,r3
-2:	sb	r4,r5,r3
+
+	.section	__ex_table,"a"
+	.word	w1, 0f;
+	.word	w2, 0f;
+	.text
+
+.align 4 /* Alignment is important to keep icache happy */
+page:	/* Create room on stack and save registers for storign values */
+	addik   r1, r1, -32
+	swi	r19, r1, 4
+	swi	r20, r1, 8
+	swi	r21, r1, 12
+	swi	r22, r1, 16
+	swi	r23, r1, 20
+	swi	r24, r1, 24
+	swi	r25, r1, 28
+loop:	/* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
+	/* Loop unrolling to get performance boost */
+	COPY_80(0x000);
+	COPY_80(0x080);
+	COPY_80(0x100);
+	COPY_80(0x180);
+	/* copy loop */
+	addik	r6, r6, 0x200
+	addik	r7, r7, -0x200
+	bneid	r7, loop
+	addik	r5, r5, 0x200
+	/* Restore register content */
+	lwi	r19, r1, 4
+	lwi	r20, r1, 8
+	lwi	r21, r1, 12
+	lwi	r22, r1, 16
+	lwi	r23, r1, 20
+	lwi	r24, r1, 24
+	lwi	r25, r1, 28
+	addik   r1, r1, 32
+	/* return back */
+	addik	r3, r7, 0
+	rtsd	r15, 8
+	nop
+
+.align 4 /* Alignment is important to keep icache happy */
+bu1:	lbu	r4,r6,r3
+bu2:	sb	r4,r5,r3
 	addik	r7,r7,-1
-	bneid	r7,1b
+	bneid	r7,bu1
 	addik	r3,r3,1		/* delay slot */
-3:
+0:
 	addik	r3,r7,0
 	rtsd	r15,8
 	nop
 	.size   __copy_tofrom_user, . - __copy_tofrom_user
 
 	.section	__ex_table,"a"
-	.word	1b,3b,2b,3b,5b,3b,6b,3b
+	.word	bu1, 0b;
+	.word	bu2, 0b;
+	.text
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/lib/ucmpdi2.c linux-libre-3.2-gnu1/arch/microblaze/lib/ucmpdi2.c
--- linux-libre-3.1-gnu1/arch/microblaze/lib/ucmpdi2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/microblaze/lib/ucmpdi2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+	const DWunion au = {.ll = a};
+	const DWunion bu = {.ll = b};
+
+	if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+		return 0;
+	else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+		return 2;
+	if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+		return 0;
+	else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+		return 2;
+	return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/mm/init.c linux-libre-3.2-gnu1/arch/microblaze/mm/init.c
--- linux-libre-3.1-gnu1/arch/microblaze/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/pfn.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/export.h>
 
 #include <asm/page.h>
 #include <asm/mmu_context.h>
@@ -304,11 +305,11 @@ asmlinkage void __init mmu_init(void)
 	/* Map in all of RAM starting at CONFIG_KERNEL_START */
 	mapin_ram();
 
-#ifdef HIGHMEM_START_BOOL
-	ioremap_base = HIGHMEM_START;
+#ifdef CONFIG_HIGHMEM_START_BOOL
+	ioremap_base = CONFIG_HIGHMEM_START;
 #else
 	ioremap_base = 0xfe000000UL;	/* for now, could be 0xfffff000 */
-#endif /* CONFIG_HIGHMEM */
+#endif /* CONFIG_HIGHMEM_START_BOOL */
 	ioremap_bot = ioremap_base;
 
 	/* Initialize the context management stuff */
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/pci/iomap.c linux-libre-3.2-gnu1/arch/microblaze/pci/iomap.c
--- linux-libre-3.1-gnu1/arch/microblaze/pci/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/pci/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/microblaze/pci/pci-common.c linux-libre-3.2-gnu1/arch/microblaze/pci/pci-common.c
--- linux-libre-3.1-gnu1/arch/microblaze/pci/pci-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/microblaze/pci/pci-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/dbdma.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/dbdma.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/dbdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/dbdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-
 /*
  * The Descriptor Based DMA supports up to 16 channels.
  *
@@ -62,120 +60,96 @@ static dbdma_global_t *dbdma_gptr =
 			(dbdma_global_t *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
 static int dbdma_initialized;
 
-static dbdev_tab_t dbdev_tab[] = {
-#ifdef CONFIG_SOC_AU1550
+static dbdev_tab_t *dbdev_tab;
+
+static dbdev_tab_t au1550_dbdev_tab[] __initdata = {
 	/* UARTS */
-	{ DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
-	{ DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
-	{ DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
-	{ DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART0_RX, DEV_FLAGS_IN,  0, 8, 0x11100000, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART3_RX, DEV_FLAGS_IN,  0, 8, 0x11400000, 0, 0 },
 
 	/* EXT DMA */
-	{ DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
 
 	/* USB DEV */
-	{ DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
-	{ DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
-	{ DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
-
-	/* PSC 0 */
-	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
-
-	/* PSC 1 */
-	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
-
-	/* PSC 2 */
-	{ DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN,  4, 8, 0x10200000, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN,  4, 8, 0x10200010, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN,  4, 8, 0x10200014, 0, 0 },
 
-	/* PSC 3 */
-	{ DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
+	/* PSCs */
+	{ AU1550_DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN,  0, 0, 0x11a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN,  0, 0, 0x11b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN,  0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN,  0, 0, 0x10b0001c, 0, 0 },
 
-	{ DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 },	/* PCI */
-	{ DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 },	/* NAND */
+	{ AU1550_DSCR_CMD0_PCI_WRITE,  0, 0, 0, 0x00000000, 0, 0 },  /* PCI */
+	{ AU1550_DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
 
 	/* MAC 0 */
-	{ DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN,  0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
 
 	/* MAC 1 */
-	{ DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
-
-#endif /* CONFIG_SOC_AU1550 */
-
-#ifdef CONFIG_SOC_AU1200
-	{ DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
-	{ DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
-	{ DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
-	{ DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN,  0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_ALWAYS,   DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+};
 
-	{ DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+static dbdev_tab_t au1200_dbdev_tab[] __initdata = {
+	{ AU1200_DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART0_RX, DEV_FLAGS_IN,  0, 8, 0x11100000, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART1_RX, DEV_FLAGS_IN,  0, 8, 0x11200000, 0, 0 },
 
-	{ DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
-	{ DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 },
+	{ AU1200_DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
-	{ DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN,  4, 8, 0x10600004, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN,  4, 8, 0x10680004, 0, 0 },
 
-	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
+	{ AU1200_DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
 
-	{ DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
-	{ DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
-	{ DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
-	{ DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_TX,   DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_RX,   DEV_FLAGS_IN,  0, 16, 0x11a0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_TX,   DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_RX,   DEV_FLAGS_IN,  0, 16, 0x11b0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXA,  DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXB,  DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXC,  DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-#endif /* CONFIG_SOC_AU1200 */
+	{ AU1200_DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
 
 	{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-
-	/* Provide 16 user definable device types */
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
+	{ DSCR_CMD0_ALWAYS,   DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 };
 
-#define DBDEV_TAB_SIZE	ARRAY_SIZE(dbdev_tab)
-
+/* 32 predefined plus 32 custom */
+#define DBDEV_TAB_SIZE		64
 
 static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
 
@@ -1028,38 +1002,43 @@ static struct syscore_ops alchemy_dbdma_
 	.resume		= alchemy_dbdma_resume,
 };
 
-static int __init au1xxx_dbdma_init(void)
+static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
 {
-	int irq_nr, ret;
+	int ret;
+
+	dbdev_tab = kzalloc(sizeof(dbdev_tab_t) * DBDEV_TAB_SIZE, GFP_KERNEL);
+	if (!dbdev_tab)
+		return -ENOMEM;
+
+	memcpy(dbdev_tab, idtable, 32 * sizeof(dbdev_tab_t));
+	for (ret = 32; ret < DBDEV_TAB_SIZE; ret++)
+		dbdev_tab[ret].dev_id = ~0;
 
 	dbdma_gptr->ddma_config = 0;
 	dbdma_gptr->ddma_throttle = 0;
 	dbdma_gptr->ddma_inten = 0xffff;
 	au_sync();
 
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1550:
-		irq_nr = AU1550_DDMA_INT;
-		break;
-	case ALCHEMY_CPU_AU1200:
-		irq_nr = AU1200_DDMA_INT;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	ret = request_irq(irq_nr, dbdma_interrupt, IRQF_DISABLED,
-			"Au1xxx dbdma", (void *)dbdma_gptr);
+	ret = request_irq(irq, dbdma_interrupt, IRQF_DISABLED, "dbdma",
+			  (void *)dbdma_gptr);
 	if (ret)
 		printk(KERN_ERR "Cannot grab DBDMA interrupt!\n");
 	else {
 		dbdma_initialized = 1;
-		printk(KERN_INFO "Alchemy DBDMA initialized\n");
 		register_syscore_ops(&alchemy_dbdma_syscore_ops);
 	}
 
 	return ret;
 }
-subsys_initcall(au1xxx_dbdma_init);
 
-#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
+static int __init alchemy_dbdma_init(void)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1550:
+		return dbdma_setup(AU1550_DDMA_INT, au1550_dbdev_tab);
+	case ALCHEMY_CPU_AU1200:
+		return dbdma_setup(AU1200_DDMA_INT, au1200_dbdev_tab);
+	}
+	return 0;
+}
+subsys_initcall(alchemy_dbdma_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/dma.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/dma.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1000_dma.h>
 
-#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \
-    defined(CONFIG_SOC_AU1100)
 /*
  * A note on resource allocation:
  *
@@ -88,12 +86,12 @@ static const struct dma_dev {
 	{ AU1000_AC97_PHYS_ADDR + 0x08, DMA_DW16 | DMA_DR },	/* AC97 RX c */
 	{ AU1000_UART3_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC },	/* UART3_TX */
 	{ AU1000_UART3_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* UART3_RX */
-	{ AU1000_USBD_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* EP0RD */
-	{ AU1000_USBD_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC }, /* EP0WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x08, DMA_DW8 | DMA_NC }, /* EP2WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x0c, DMA_DW8 | DMA_NC }, /* EP3WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x10, DMA_DW8 | DMA_NC | DMA_DR }, /* EP4RD */
-	{ AU1000_USBD_PHYS_ADDR + 0x14, DMA_DW8 | DMA_NC | DMA_DR }, /* EP5RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* EP0RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC }, /* EP0WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x08, DMA_DW8 | DMA_NC }, /* EP2WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x0c, DMA_DW8 | DMA_NC }, /* EP3WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x10, DMA_DW8 | DMA_NC | DMA_DR }, /* EP4RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x14, DMA_DW8 | DMA_NC | DMA_DR }, /* EP5RD */
 	/* on Au1500, these 2 are DMA_REQ2/3 (GPIO208/209) instead! */
 	{ AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC},	/* I2S TX */
 	{ AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC | DMA_DR}, /* I2S RX */
@@ -170,13 +168,13 @@ int request_au1000_dma(int dev_id, const
 	const struct dma_dev *dev;
 	int i, ret;
 
-#if defined(CONFIG_SOC_AU1100)
-	if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
-		return -EINVAL;
-#else
-	if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
-		return -EINVAL;
-#endif
+	if (alchemy_get_cputype() == ALCHEMY_CPU_AU1100) {
+		if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
+			return -EINVAL;
+	} else {
+		if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
+			return -EINVAL;
+	}
 
 	for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
 		if (au1000_dma_table[i].dev_id < 0)
@@ -239,30 +237,28 @@ EXPORT_SYMBOL(free_au1000_dma);
 
 static int __init au1000_dma_init(void)
 {
-        int base, i;
+	int base, i;
 
-        switch (alchemy_get_cputype()) {
-        case ALCHEMY_CPU_AU1000:
-                base = AU1000_DMA_INT_BASE;
-                break;
-        case ALCHEMY_CPU_AU1500:
-                base = AU1500_DMA_INT_BASE;
-                break;
-        case ALCHEMY_CPU_AU1100:
-                base = AU1100_DMA_INT_BASE;
-                break;
-        default:
-                goto out;
-        }
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+		base = AU1000_DMA_INT_BASE;
+		break;
+	case ALCHEMY_CPU_AU1500:
+		base = AU1500_DMA_INT_BASE;
+		break;
+	case ALCHEMY_CPU_AU1100:
+		base = AU1100_DMA_INT_BASE;
+		break;
+	default:
+		goto out;
+	}
 
-        for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
-                au1000_dma_table[i].irq = base + i;
+	for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
+		au1000_dma_table[i].irq = base + i;
 
-        printk(KERN_INFO "Alchemy DMA initialized\n");
+	printk(KERN_INFO "Alchemy DMA initialized\n");
 
 out:
-        return 0;
+	return 0;
 }
 arch_initcall(au1000_dma_init);
-
-#endif /* AU1000 AU1500 AU1100 */
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/gpiolib-au1000.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/gpiolib-au1000.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/gpiolib-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/gpiolib-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,126 +0,0 @@
-/*
- *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
- *  	GPIOLIB support for Au1000, Au1500, Au1100, Au1550 and Au12x0.
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Notes :
- * 	au1000 SoC have only one GPIO block : GPIO1
- * 	Au1100, Au15x0, Au12x0 have a second one : GPIO2
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio.h>
-
-static int gpio2_get(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
-}
-
-static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value);
-}
-
-static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE);
-}
-
-static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset,
-				  int value)
-{
-	return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE,
-						value);
-}
-
-static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE);
-}
-
-
-static int gpio1_get(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
-}
-
-static void gpio1_set(struct gpio_chip *chip,
-				unsigned offset, int value)
-{
-	alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value);
-}
-
-static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE);
-}
-
-static int gpio1_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE,
-					     value);
-}
-
-static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
-}
-
-struct gpio_chip alchemy_gpio_chip[] = {
-	[0] = {
-		.label			= "alchemy-gpio1",
-		.direction_input	= gpio1_direction_input,
-		.direction_output	= gpio1_direction_output,
-		.get			= gpio1_get,
-		.set			= gpio1_set,
-		.to_irq			= gpio1_to_irq,
-		.base			= ALCHEMY_GPIO1_BASE,
-		.ngpio			= ALCHEMY_GPIO1_NUM,
-	},
-	[1] = {
-		.label                  = "alchemy-gpio2",
-		.direction_input        = gpio2_direction_input,
-		.direction_output       = gpio2_direction_output,
-		.get                    = gpio2_get,
-		.set                    = gpio2_set,
-		.to_irq			= gpio2_to_irq,
-		.base                   = ALCHEMY_GPIO2_BASE,
-		.ngpio                  = ALCHEMY_GPIO2_NUM,
-	},
-};
-
-static int __init alchemy_gpiolib_init(void)
-{
-	gpiochip_add(&alchemy_gpio_chip[0]);
-	if (alchemy_get_cputype() != ALCHEMY_CPU_AU1000)
-		gpiochip_add(&alchemy_gpio_chip[1]);
-
-	return 0;
-}
-arch_initcall(alchemy_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/gpiolib.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/gpiolib.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/gpiolib.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *	GPIOLIB support for Alchemy chips.
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Notes :
+ *	This file must ONLY be built when CONFIG_GPIOLIB=y and
+ *	 CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail!
+ *	au1000 SoC have only one GPIO block : GPIO1
+ *	Au1100, Au15x0, Au12x0 have a second one : GPIO2
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
+
+static int gpio2_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value);
+}
+
+static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset,
+				  int value)
+{
+	return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE,
+						value);
+}
+
+static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE);
+}
+
+
+static int gpio1_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static void gpio1_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value);
+}
+
+static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static int gpio1_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE,
+					     value);
+}
+
+static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
+}
+
+struct gpio_chip alchemy_gpio_chip[] = {
+	[0] = {
+		.label			= "alchemy-gpio1",
+		.direction_input	= gpio1_direction_input,
+		.direction_output	= gpio1_direction_output,
+		.get			= gpio1_get,
+		.set			= gpio1_set,
+		.to_irq			= gpio1_to_irq,
+		.base			= ALCHEMY_GPIO1_BASE,
+		.ngpio			= ALCHEMY_GPIO1_NUM,
+	},
+	[1] = {
+		.label                  = "alchemy-gpio2",
+		.direction_input        = gpio2_direction_input,
+		.direction_output       = gpio2_direction_output,
+		.get                    = gpio2_get,
+		.set                    = gpio2_set,
+		.to_irq			= gpio2_to_irq,
+		.base                   = ALCHEMY_GPIO2_BASE,
+		.ngpio                  = ALCHEMY_GPIO2_NUM,
+	},
+};
+
+static int __init alchemy_gpiochip_init(void)
+{
+	int ret = 0;
+
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+		ret = gpiochip_add(&alchemy_gpio_chip[0]);
+		break;
+	case ALCHEMY_CPU_AU1500...ALCHEMY_CPU_AU1200:
+		ret = gpiochip_add(&alchemy_gpio_chip[0]);
+		ret |= gpiochip_add(&alchemy_gpio_chip[1]);
+		break;
+	}
+	return ret;
+}
+arch_initcall(alchemy_gpiochip_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/Makefile linux-libre-3.2-gnu1/arch/mips/alchemy/common/Makefile
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,5 @@ obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) +=
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
- ifeq ($(CONFIG_GPIOLIB),y)
-  obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += gpiolib-au1000.o
- endif
+ obj-$(CONFIG_GPIOLIB) += gpiolib.o
 endif
-
-obj-$(CONFIG_PCI)		+= pci.o
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/pci.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/pci.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Alchemy/AMD Au1x00 PCI support.
- *
- * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- *  Support for all devices (greater than 16) added by David Gathright.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-/* TBD */
-static struct resource pci_io_resource = {
-	.start	= PCI_IO_START,
-	.end	= PCI_IO_END,
-	.name	= "PCI IO space",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	.start	= PCI_MEM_START,
-	.end	= PCI_MEM_END,
-	.name	= "PCI memory space",
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops au1x_pci_ops;
-
-static struct pci_controller au1x_controller = {
-	.pci_ops	= &au1x_pci_ops,
-	.io_resource	= &pci_io_resource,
-	.mem_resource	= &pci_mem_resource,
-};
-
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-static unsigned long virt_io_addr;
-#endif
-
-static int __init au1x_pci_setup(void)
-{
-	extern void au1x_pci_cfg_init(void);
-
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-	virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
-			Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
-
-	if (!virt_io_addr) {
-		printk(KERN_ERR "Unable to ioremap pci space\n");
-		return 1;
-	}
-	au1x_controller.io_map_base = virt_io_addr;
-
-#ifdef CONFIG_DMA_NONCOHERENT
-	{
-		/*
-		 *  Set the NC bit in controller for Au1500 pre-AC silicon
-		 */
-		u32 prid = read_c0_prid();
-
-		if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
-			au_writel((1 << 16) | au_readl(Au1500_PCI_CFG),
-				  Au1500_PCI_CFG);
-			printk(KERN_INFO "Non-coherent PCI accesses enabled\n");
-		}
-	}
-#endif
-
-	set_io_port_base(virt_io_addr);
-#endif
-
-	au1x_pci_cfg_init();
-
-	register_pci_controller(&au1x_controller);
-	return 0;
-}
-
-arch_initcall(au1x_pci_setup);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 #include <asm/mach-au1x00/au1xxx_eth.h>
@@ -111,270 +111,87 @@ static void __init alchemy_setup_uarts(i
 		printk(KERN_INFO "Alchemy: failed to register UARTs\n");
 }
 
-/* OHCI (USB full speed host controller) */
-static struct resource au1xxx_usb_ohci_resources[] = {
-	[0] = {
-		.start		= USB_OHCI_BASE,
-		.end		= USB_OHCI_BASE + USB_OHCI_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= FOR_PLATFORM_C_USB_HOST_INT,
-		.end		= FOR_PLATFORM_C_USB_HOST_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-/* The dmamask must be set for OHCI to work */
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_ohci_device = {
-	.name		= "au1xxx-ohci",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ohci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_ohci_resources),
-	.resource	= au1xxx_usb_ohci_resources,
-};
-
-/*** AU1100 LCD controller ***/
 
-#ifdef CONFIG_FB_AU1100
-static struct resource au1100_lcd_resources[] = {
-	[0] = {
-		.start          = LCD_PHYS_ADDR,
-		.end            = LCD_PHYS_ADDR + 0x800 - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start          = AU1100_LCD_INT,
-		.end            = AU1100_LCD_INT,
-		.flags          = IORESOURCE_IRQ,
-	}
-};
-
-static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1100_lcd_device = {
-	.name           = "au1100-lcd",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &au1100_lcd_dmamask,
-		.coherent_dma_mask      = DMA_BIT_MASK(32),
-	},
-	.num_resources  = ARRAY_SIZE(au1100_lcd_resources),
-	.resource       = au1100_lcd_resources,
-};
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-/* EHCI (USB high speed host controller) */
-static struct resource au1xxx_usb_ehci_resources[] = {
-	[0] = {
-		.start		= USB_EHCI_BASE,
-		.end		= USB_EHCI_BASE + USB_EHCI_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static u64 ehci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_ehci_device = {
-	.name		= "au1xxx-ehci",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ehci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_ehci_resources),
-	.resource	= au1xxx_usb_ehci_resources,
-};
-
-/* Au1200 UDC (USB gadget controller) */
-static struct resource au1xxx_usb_gdt_resources[] = {
-	[0] = {
-		.start		= USB_UDC_BASE,
-		.end		= USB_UDC_BASE + USB_UDC_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static u64 udc_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_gdt_device = {
-	.name		= "au1xxx-udc",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &udc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_gdt_resources),
-	.resource	= au1xxx_usb_gdt_resources,
-};
+/* The dmamask must be set for OHCI/EHCI to work */
+static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32);
+static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32);
 
-/* Au1200 UOC (USB OTG controller) */
-static struct resource au1xxx_usb_otg_resources[] = {
-	[0] = {
-		.start		= USB_UOC_BASE,
-		.end		= USB_UOC_BASE + USB_UOC_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
+static unsigned long alchemy_ohci_data[][2] __initdata = {
+	[ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT },
 };
 
-static u64 uoc_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_otg_device = {
-	.name		= "au1xxx-uoc",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &uoc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_otg_resources),
-	.resource	= au1xxx_usb_otg_resources,
+static unsigned long alchemy_ehci_data[][2] __initdata = {
+	[ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT },
 };
 
-static struct resource au1200_lcd_resources[] = {
-	[0] = {
-		.start          = LCD_PHYS_ADDR,
-		.end            = LCD_PHYS_ADDR + 0x800 - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start          = AU1200_LCD_INT,
-		.end            = AU1200_LCD_INT,
-		.flags          = IORESOURCE_IRQ,
+static int __init _new_usbres(struct resource **r, struct platform_device **d)
+{
+	*r = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!*r)
+		return -ENOMEM;
+	*d = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+	if (!*d) {
+		kfree(*r);
+		return -ENOMEM;
 	}
-};
 
-static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+	(*d)->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	(*d)->num_resources = 2;
+	(*d)->resource = *r;
 
-static struct platform_device au1200_lcd_device = {
-	.name           = "au1200-lcd",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &au1200_lcd_dmamask,
-		.coherent_dma_mask      = DMA_BIT_MASK(32),
-	},
-	.num_resources  = ARRAY_SIZE(au1200_lcd_resources),
-	.resource       = au1200_lcd_resources,
-};
+	return 0;
+}
 
-static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+static void __init alchemy_setup_usb(int ctype)
+{
+	struct resource *res;
+	struct platform_device *pdev;
 
-extern struct au1xmmc_platform_data au1xmmc_platdata[2];
+	/* setup OHCI0.  Every variant has one */
+	if (_new_usbres(&res, &pdev))
+		return;
 
-static struct resource au1200_mmc0_resources[] = {
-	[0] = {
-		.start          = AU1100_SD0_PHYS_ADDR,
-		.end            = AU1100_SD0_PHYS_ADDR + 0xfff,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_SD_INT,
-		.end		= AU1200_SD_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start		= DSCR_CMD0_SDMS_TX0,
-		.end		= DSCR_CMD0_SDMS_TX0,
-		.flags		= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start          = DSCR_CMD0_SDMS_RX0,
-		.end		= DSCR_CMD0_SDMS_RX0,
-		.flags          = IORESOURCE_DMA,
-	}
-};
+	res[0].start = alchemy_ohci_data[ctype][0];
+	res[0].end = res[0].start + 0x100 - 1;
+	res[0].flags = IORESOURCE_MEM;
+	res[1].start = alchemy_ohci_data[ctype][1];
+	res[1].end = res[1].start;
+	res[1].flags = IORESOURCE_IRQ;
+	pdev->name = "au1xxx-ohci";
+	pdev->id = 0;
+	pdev->dev.dma_mask = &alchemy_ohci_dmamask;
 
-static struct platform_device au1200_mmc0_device = {
-	.name = "au1xxx-mmc",
-	.id = 0,
-	.dev = {
-		.dma_mask		= &au1xxx_mmc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &au1xmmc_platdata[0],
-	},
-	.num_resources	= ARRAY_SIZE(au1200_mmc0_resources),
-	.resource	= au1200_mmc0_resources,
-};
+	if (platform_device_register(pdev))
+		printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
 
-#ifndef CONFIG_MIPS_DB1200
-static struct resource au1200_mmc1_resources[] = {
-	[0] = {
-		.start          = AU1100_SD1_PHYS_ADDR,
-		.end            = AU1100_SD1_PHYS_ADDR + 0xfff,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_SD_INT,
-		.end		= AU1200_SD_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start		= DSCR_CMD0_SDMS_TX1,
-		.end		= DSCR_CMD0_SDMS_TX1,
-		.flags		= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start          = DSCR_CMD0_SDMS_RX1,
-		.end		= DSCR_CMD0_SDMS_RX1,
-		.flags          = IORESOURCE_DMA,
-	}
-};
 
-static struct platform_device au1200_mmc1_device = {
-	.name = "au1xxx-mmc",
-	.id = 1,
-	.dev = {
-		.dma_mask		= &au1xxx_mmc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &au1xmmc_platdata[1],
-	},
-	.num_resources	= ARRAY_SIZE(au1200_mmc1_resources),
-	.resource	= au1200_mmc1_resources,
-};
-#endif /* #ifndef CONFIG_MIPS_DB1200 */
-#endif /* #ifdef CONFIG_SOC_AU1200 */
+	/* setup EHCI0: Au1200 */
+	if (ctype == ALCHEMY_CPU_AU1200) {
+		if (_new_usbres(&res, &pdev))
+			return;
 
-/* All Alchemy demoboards with I2C have this #define in their headers */
-#ifdef SMBUS_PSC_BASE
-static struct resource pbdb_smbus_resources[] = {
-	{
-		.start	= CPHYSADDR(SMBUS_PSC_BASE),
-		.end	= CPHYSADDR(SMBUS_PSC_BASE + 0xfffff),
-		.flags	= IORESOURCE_MEM,
-	},
-};
+		res[0].start = alchemy_ehci_data[ctype][0];
+		res[0].end = res[0].start + 0x100 - 1;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = alchemy_ehci_data[ctype][1];
+		res[1].end = res[1].start;
+		res[1].flags = IORESOURCE_IRQ;
+		pdev->name = "au1xxx-ehci";
+		pdev->id = 0;
+		pdev->dev.dma_mask = &alchemy_ehci_dmamask;
 
-static struct platform_device pbdb_smbus_device = {
-	.name		= "au1xpsc_smbus",
-	.id		= 0,	/* bus number */
-	.num_resources	= ARRAY_SIZE(pbdb_smbus_resources),
-	.resource	= pbdb_smbus_resources,
-};
-#endif
+		if (platform_device_register(pdev))
+			printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
+	}
+}
 
 /* Macro to help defining the Ethernet MAC resources */
-#define MAC_RES_COUNT	3	/* MAC regs base, MAC enable reg, MAC INT */
-#define MAC_RES(_base, _enable, _irq)			\
+#define MAC_RES_COUNT	4	/* MAC regs, MAC en, MAC INT, MACDMA regs */
+#define MAC_RES(_base, _enable, _irq, _macdma)		\
 	{						\
 		.start	= _base,			\
 		.end	= _base + 0xffff,		\
@@ -389,28 +206,37 @@ static struct platform_device pbdb_smbus
 		.start	= _irq,				\
 		.end	= _irq,				\
 		.flags	= IORESOURCE_IRQ		\
+	},						\
+	{						\
+		.start	= _macdma,			\
+		.end	= _macdma + 0x1ff,		\
+		.flags	= IORESOURCE_MEM,		\
 	}
 
 static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = {
 	[ALCHEMY_CPU_AU1000] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1000_MAC0_DMA_INT)
+			AU1000_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1500] = {
 		MAC_RES(AU1500_MAC0_PHYS_ADDR,
 			AU1500_MACEN_PHYS_ADDR,
-			AU1500_MAC0_DMA_INT)
+			AU1500_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1100] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1100_MAC0_DMA_INT)
+			AU1100_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1550] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1550_MAC0_DMA_INT)
+			AU1550_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 };
 
@@ -429,17 +255,20 @@ static struct resource au1xxx_eth1_resou
 	[ALCHEMY_CPU_AU1000] = {
 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR + 4,
-			AU1000_MAC1_DMA_INT)
+			AU1000_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1500] = {
 		MAC_RES(AU1500_MAC1_PHYS_ADDR,
 			AU1500_MACEN_PHYS_ADDR + 4,
-			AU1500_MAC1_DMA_INT)
+			AU1500_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1550] = {
 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR + 4,
-			AU1550_MAC1_DMA_INT)
+			AU1550_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 };
 
@@ -521,36 +350,15 @@ static void __init alchemy_setup_macs(in
 	}
 }
 
-static struct platform_device *au1xxx_platform_devices[] __initdata = {
-	&au1xxx_usb_ohci_device,
-#ifdef CONFIG_FB_AU1100
-	&au1100_lcd_device,
-#endif
-#ifdef CONFIG_SOC_AU1200
-	&au1xxx_usb_ehci_device,
-	&au1xxx_usb_gdt_device,
-	&au1xxx_usb_otg_device,
-	&au1200_lcd_device,
-	&au1200_mmc0_device,
-#ifndef CONFIG_MIPS_DB1200
-	&au1200_mmc1_device,
-#endif
-#endif
-#ifdef SMBUS_PSC_BASE
-	&pbdb_smbus_device,
-#endif
-};
-
 static int __init au1xxx_platform_init(void)
 {
-	int err, ctype = alchemy_get_cputype();
+	int ctype = alchemy_get_cputype();
 
 	alchemy_setup_uarts(ctype);
 	alchemy_setup_macs(ctype);
+	alchemy_setup_usb(ctype);
 
-	err = platform_add_devices(au1xxx_platform_devices,
-				   ARRAY_SIZE(au1xxx_platform_devices));
-	return err;
+	return 0;
 }
 
 arch_initcall(au1xxx_platform_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/power.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/power.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/power.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,6 @@
 #include <asm/uaccess.h>
 #include <asm/mach-au1x00/au1000.h>
 
-#ifdef CONFIG_PM
-
 /*
  * We need to save/restore a bunch of core registers that are
  * either volatile or reset to some state across a processor sleep.
@@ -49,7 +47,6 @@
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int sleep_usb[2];
 static unsigned int sleep_sys_clocks[5];
 static unsigned int sleep_sys_pinfunc;
 static unsigned int sleep_static_memctlr[4][3];
@@ -57,31 +54,6 @@ static unsigned int sleep_static_memctlr
 
 static void save_core_regs(void)
 {
-#ifndef CONFIG_SOC_AU1200
-	/* Shutdown USB host/device. */
-	sleep_usb[0] = au_readl(USB_HOST_CONFIG);
-
-	/* There appears to be some undocumented reset register.... */
-	au_writel(0, 0xb0100004);
-	au_sync();
-	au_writel(0, USB_HOST_CONFIG);
-	au_sync();
-
-	sleep_usb[1] = au_readl(USBD_ENABLE);
-	au_writel(0, USBD_ENABLE);
-	au_sync();
-
-#else	/* AU1200 */
-
-	/* enable access to OTG mmio so we can save OTG CAP/MUX.
-	 * FIXME: write an OTG driver and move this stuff there!
-	 */
-	au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
-	au_sync();
-	sleep_usb[0] = au_readl(0xb4020020);	/* OTG_CAP */
-	sleep_usb[1] = au_readl(0xb4020024);	/* OTG_MUX */
-#endif
-
 	/* Clocks and PLLs. */
 	sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
 	sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
@@ -125,22 +97,6 @@ static void restore_core_regs(void)
 	au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
 	au_sync();
 
-#ifndef CONFIG_SOC_AU1200
-	au_writel(sleep_usb[0], USB_HOST_CONFIG);
-	au_writel(sleep_usb[1], USBD_ENABLE);
-	au_sync();
-#else
-	/* enable access to OTG memory */
-	au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
-	au_sync();
-
-	/* restore OTG caps and port mux. */
-	au_writel(sleep_usb[0], 0xb4020020 + 0);	/* OTG_CAP */
-	au_sync();
-	au_writel(sleep_usb[1], 0xb4020020 + 4);	/* OTG_MUX */
-	au_sync();
-#endif
-
 	/* Restore the static memory controller configuration. */
 	au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
 	au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
@@ -174,5 +130,3 @@ void au_sleep(void)
 
 	restore_core_regs();
 }
-
-#endif	/* CONFIG_PM */
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/common/setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/common/setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/common/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/common/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,8 +73,8 @@ void __init plat_mem_setup(void)
 /* This routine should be valid for all Au1x based boards */
 phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
-	u32 start = (u32)Au1500_PCI_MEM_START;
-	u32 end   = (u32)Au1500_PCI_MEM_END;
+	unsigned long start = ALCHEMY_PCI_MEMWIN_START;
+	unsigned long end = ALCHEMY_PCI_MEMWIN_END;
 
 	/* Don't fixup 36-bit addresses */
 	if ((phys_addr >> 32) != 0)
@@ -82,7 +82,7 @@ phys_t __fixup_bigphys_addr(phys_t phys_
 
 	/* Check for PCI memory window */
 	if (phys_addr >= start && (phys_addr + size - 1) <= end)
-		return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
+		return (phys_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr);
 
 	/* default nop */
 	return phys_addr;
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1200/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1200/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1200/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1200/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -213,7 +213,12 @@ static struct resource db1200_ide_res[]
 		.start	= DB1200_IDE_INT,
 		.end	= DB1200_IDE_INT,
 		.flags	= IORESOURCE_IRQ,
-	}
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.end	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.flags	= IORESOURCE_DMA,
+	},
 };
 
 static u64 ide_dmamask = DMA_BIT_MASK(32);
@@ -328,23 +333,85 @@ static struct led_classdev db1200_mmc_le
 	.brightness_set	= db1200_mmcled_set,
 };
 
-/* needed by arch/mips/alchemy/common/platform.c */
-struct au1xmmc_platform_data au1xmmc_platdata[] = {
+static struct au1xmmc_platform_data db1200mmc_platdata = {
+	.cd_setup	= db1200_mmc_cd_setup,
+	.set_power	= db1200_mmc_set_power,
+	.card_inserted	= db1200_mmc_card_inserted,
+	.card_readonly	= db1200_mmc_card_readonly,
+	.led		= &db1200_mmc_led,
+};
+
+static struct resource au1200_mmc0_resources[] = {
 	[0] = {
-		.cd_setup	= db1200_mmc_cd_setup,
-		.set_power	= db1200_mmc_set_power,
-		.card_inserted	= db1200_mmc_card_inserted,
-		.card_readonly	= db1200_mmc_card_readonly,
-		.led		= &db1200_mmc_led,
+		.start	= AU1100_SD0_PHYS_ADDR,
+		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+
+static struct platform_device db1200_mmc0_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &db1200mmc_platdata,
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc0_resources),
+	.resource	= au1200_mmc0_resources,
+};
+
+/**********************************************************************/
+
+static struct resource au1200_lcd_res[] = {
+	[0] = {
+		.start	= AU1200_LCD_PHYS_ADDR,
+		.end	= AU1200_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= AU1200_LCD_INT,
+		.end	= AU1200_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1200_lcd_dev = {
+	.name		= "au1200-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1200_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1200_lcd_res),
+	.resource	= au1200_lcd_res,
 };
 
 /**********************************************************************/
 
 static struct resource au1200_psc0_res[] = {
 	[0] = {
-		.start	= PSC0_PHYS_ADDR,
-		.end	= PSC0_PHYS_ADDR + 0x000fffff,
+		.start	= AU1550_PSC0_PHYS_ADDR,
+		.end	= AU1550_PSC0_PHYS_ADDR + 0xfff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -353,13 +420,13 @@ static struct resource au1200_psc0_res[]
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
-		.start	= DSCR_CMD0_PSC0_TX,
-		.end	= DSCR_CMD0_PSC0_TX,
+		.start	= AU1200_DSCR_CMD0_PSC0_TX,
+		.end	= AU1200_DSCR_CMD0_PSC0_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 	[3] = {
-		.start	= DSCR_CMD0_PSC0_RX,
-		.end	= DSCR_CMD0_PSC0_RX,
+		.start	= AU1200_DSCR_CMD0_PSC0_RX,
+		.end	= AU1200_DSCR_CMD0_PSC0_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -401,8 +468,8 @@ static struct platform_device db1200_spi
 
 static struct resource au1200_psc1_res[] = {
 	[0] = {
-		.start	= PSC1_PHYS_ADDR,
-		.end	= PSC1_PHYS_ADDR + 0x000fffff,
+		.start	= AU1550_PSC1_PHYS_ADDR,
+		.end	= AU1550_PSC1_PHYS_ADDR + 0xfff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -411,17 +478,18 @@ static struct resource au1200_psc1_res[]
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
-		.start	= DSCR_CMD0_PSC1_TX,
-		.end	= DSCR_CMD0_PSC1_TX,
+		.start	= AU1200_DSCR_CMD0_PSC1_TX,
+		.end	= AU1200_DSCR_CMD0_PSC1_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 	[3] = {
-		.start	= DSCR_CMD0_PSC1_RX,
-		.end	= DSCR_CMD0_PSC1_RX,
+		.start	= AU1200_DSCR_CMD0_PSC1_RX,
+		.end	= AU1200_DSCR_CMD0_PSC1_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
 
+/* AC97 or I2S device */
 static struct platform_device db1200_audio_dev = {
 	/* name assigned later based on switch setting */
 	.id		= 1,	/* PSC ID */
@@ -429,19 +497,34 @@ static struct platform_device db1200_aud
 	.resource	= au1200_psc1_res,
 };
 
+/* DB1200 ASoC card device */
+static struct platform_device db1200_sound_dev = {
+	/* name assigned later based on switch setting */
+	.id		= 1,	/* PSC ID */
+};
+
 static struct platform_device db1200_stac_dev = {
 	.name		= "ac97-codec",
 	.id		= 1,	/* on PSC1 */
 };
 
+static struct platform_device db1200_audiodma_dev = {
+	.name		= "au1xpsc-pcm",
+	.id		= 1,	/* PSC ID */
+};
+
 static struct platform_device *db1200_devs[] __initdata = {
 	NULL,		/* PSC0, selected by S6.8 */
 	&db1200_ide_dev,
+	&db1200_mmc0_dev,
+	&au1200_lcd_dev,
 	&db1200_eth_dev,
 	&db1200_rtc_dev,
 	&db1200_nand_dev,
+	&db1200_audiodma_dev,
 	&db1200_audio_dev,
 	&db1200_stac_dev,
+	&db1200_sound_dev,
 };
 
 static int __init db1200_dev_init(void)
@@ -501,41 +584,39 @@ static int __init db1200_dev_init(void)
 	if (sw == BCSR_SWITCHES_DIP_8) {
 		bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX);
 		db1200_audio_dev.name = "au1xpsc_i2s";
+		db1200_sound_dev.name = "db1200-i2s";
 		printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n");
 	} else {
 		bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0);
 		db1200_audio_dev.name = "au1xpsc_ac97";
+		db1200_sound_dev.name = "db1200-ac97";
 		printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n");
 	}
 
 	/* Audio PSC clock is supplied externally. (FIXME: platdata!!) */
 	__raw_writel(PSC_SEL_CLK_SERCLK,
-		(void __iomem *)KSEG1ADDR(PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
+		(void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    DB1200_PC0_INT,
-				    DB1200_PC0_INSERT_INT,
-				    /*DB1200_PC0_STSCHG_INT*/0,
-				    DB1200_PC0_EJECT_INT,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		DB1200_PC0_INT, DB1200_PC0_INSERT_INT,
+		/*DB1200_PC0_STSCHG_INT*/0, DB1200_PC0_EJECT_INT, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
-				    DB1200_PC1_INT,
-				    DB1200_PC1_INSERT_INT,
-				    /*DB1200_PC1_STSCHG_INT*/0,
-				    DB1200_PC1_EJECT_INT,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
+		DB1200_PC1_INT, DB1200_PC1_INSERT_INT,
+		/*DB1200_PC1_STSCHG_INT*/0, DB1200_PC1_EJECT_INT, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1200_SWAPBOOT;
 	db1x_register_norflash(64 << 20, 2, swapped);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1x00/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1x00/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1x00/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1x00/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,24 +40,6 @@
 
 #include <prom.h>
 
-#ifdef CONFIG_MIPS_DB1500
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff }, /* IDSEL 12 - HPT371   */
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */
-};
-
-#endif
-
-
-#ifdef CONFIG_MIPS_DB1550
-char irq_tab_alchemy[][5] __initdata = {
-	[11] = { -1, AU1550_PCI_INTC, 0xff, 0xff, 0xff }, /* IDSEL 11 - on-board HPT371 */
-	[12] = { -1, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD, AU1550_PCI_INTA }, /* IDSEL 12 - PCI slot 2 (left) */
-	[13] = { -1, AU1550_PCI_INTA, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-#endif
-
-
 #ifdef CONFIG_MIPS_BOSPORUS
 char irq_tab_alchemy[][5] __initdata = {
 	[11] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 11 - miniPCI  */
@@ -91,12 +73,6 @@ const char *get_system_type(void)
 
 
 #ifdef CONFIG_MIPS_MIRAGE
-char irq_tab_alchemy[][5] __initdata = {
-	[11] = { -1, AU1500_PCI_INTD, 0xff, 0xff, 0xff }, /* IDSEL 11 - SMI VGX */
-	[12] = { -1, 0xff, 0xff, AU1500_PCI_INTC, 0xff }, /* IDSEL 12 - PNX1300 */
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 13 - miniPCI */
-};
-
 static void mirage_power_off(void)
 {
 	alchemy_gpio_direction_output(210, 1);
@@ -158,9 +134,7 @@ void __init board_setup(void)
 	/* initialize board register space */
 	bcsr_init(bcsr1, bcsr2);
 
-	/* Not valid for Au1550 */
-#if defined(CONFIG_IRDA) && \
-   (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+#if defined(CONFIG_IRDA) && defined(CONFIG_AU1000_FIR)
 	{
 		u32 pin_func;
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1x00/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1x00/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/db1x00/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/db1x00/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,12 +19,17 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
 #include <asm/mach-db1x00/bcsr.h>
 #include "../platform.h"
 
+struct pci_dev;
+
 /* DB1xxx PCMCIA interrupt sources:
  * CD0/1 	GPIO0/3
  * STSCHG0/1	GPIO1/4
@@ -85,34 +90,227 @@
 #endif
 #endif
 
+#ifdef CONFIG_PCI
+#ifdef CONFIG_MIPS_DB1500
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_DB1550
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 11)
+		return (pin == 1) ? AU1550_PCI_INTC : 0xff;
+	if (slot == 12) {
+		switch (pin) {
+		case 1: return AU1550_PCI_INTB;
+		case 2: return AU1550_PCI_INTC;
+		case 3: return AU1550_PCI_INTD;
+		case 4: return AU1550_PCI_INTA;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1550_PCI_INTA;
+		case 2: return AU1550_PCI_INTB;
+		case 3: return AU1550_PCI_INTC;
+		case 4: return AU1550_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_BOSPORUS
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 11) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		default: return 0xff;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_MIRAGE
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 11)
+		return (pin == 1) ? AU1500_PCI_INTD : 0xff;
+	if (slot == 12)
+		return (pin == 3) ? AU1500_PCI_INTC : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		default: return 0xff;
+		}
+	}
+	return -1;
+}
+#endif
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata db1xxx_pci_pd = {
+	.board_map_irq	= db1xxx_map_pci_irq,
+};
+
+static struct platform_device db1xxx_pci_host_dev = {
+	.dev.platform_data = &db1xxx_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+static int __init db15x0_pci_init(void)
+{
+	return platform_device_register(&db1xxx_pci_host_dev);
+}
+/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
+arch_initcall(db15x0_pci_init);
+#endif
+
+#ifdef CONFIG_MIPS_DB1100
+static struct resource au1100_lcd_resources[] = {
+	[0] = {
+		.start	= AU1100_LCD_PHYS_ADDR,
+		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1100_LCD_INT,
+		.end	= AU1100_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1100_lcd_device = {
+	.name		= "au1100-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1100_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
+	.resource	= au1100_lcd_resources,
+};
+#endif
+
+static struct resource alchemy_ac97c_res[] = {
+	[0] = {
+		.start	= AU1000_AC97_PHYS_ADDR,
+		.end	= AU1000_AC97_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMA_ID_AC97C_TX,
+		.end	= DMA_ID_AC97C_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMA_ID_AC97C_RX,
+		.end	= DMA_ID_AC97C_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device alchemy_ac97c_dev = {
+	.name		= "alchemy-ac97c",
+	.id		= -1,
+	.resource	= alchemy_ac97c_res,
+	.num_resources	= ARRAY_SIZE(alchemy_ac97c_res),
+};
+
+static struct platform_device alchemy_ac97c_dma_dev = {
+	.name		= "alchemy-pcm-dma",
+	.id		= 0,
+};
+
+static struct platform_device db1x00_codec_dev = {
+	.name		= "ac97-codec",
+	.id		= -1,
+};
+
+static struct platform_device db1x00_audio_dev = {
+	.name		= "db1000-audio",
+};
+
 static int __init db1xxx_dev_init(void)
 {
 #ifdef DB1XXX_HAS_PCMCIA
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    DB1XXX_PCMCIA_CARD0,
-				    DB1XXX_PCMCIA_CD0,
-				    /*DB1XXX_PCMCIA_STSCHG0*/0,
-				    0,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		DB1XXX_PCMCIA_CARD0, DB1XXX_PCMCIA_CD0,
+		/*DB1XXX_PCMCIA_STSCHG0*/0, 0, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
-				    DB1XXX_PCMCIA_CARD1,
-				    DB1XXX_PCMCIA_CD1,
-				    /*DB1XXX_PCMCIA_STSCHG1*/0,
-				    0,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
+		DB1XXX_PCMCIA_CARD1, DB1XXX_PCMCIA_CD1,
+		/*DB1XXX_PCMCIA_STSCHG1*/0, 0, 1);
+#endif
+#ifdef CONFIG_MIPS_DB1100
+	platform_device_register(&au1100_lcd_device);
 #endif
 	db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED);
+
+	platform_device_register(&db1x00_codec_dev);
+	platform_device_register(&alchemy_ac97c_dma_dev);
+	platform_device_register(&alchemy_ac97c_dev);
+	platform_device_register(&db1x00_audio_dev);
+
 	return 0;
 }
 device_initcall(db1xxx_dev_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1100/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1100/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1100/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1100/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,31 +19,58 @@
  */
 
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static struct resource au1100_lcd_resources[] = {
+	[0] = {
+		.start	= AU1100_LCD_PHYS_ADDR,
+		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1100_LCD_INT,
+		.end	= AU1100_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1100_lcd_device = {
+	.name		= "au1100-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1100_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
+	.resource	= au1100_lcd_resources,
+};
+
 static int __init pb1100_dev_init(void)
 {
 	int swapped;
 
 	/* PCMCIA. single socket, identical to Pb1500 */
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1100_GPIO11_INT,	 /* card */
-				    AU1100_GPIO9_INT,	 /* insert */
-				    /*AU1100_GPIO10_INT*/0, /* stschg */
-				    0,			 /* eject */
-				    0);			 /* id */
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1100_GPIO11_INT, AU1100_GPIO9_INT,	 /* card / insert */
+		/*AU1100_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
 	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
+	platform_device_register(&au1100_lcd_device);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1200/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1200/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1200/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1200/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,9 +24,11 @@
 #include <linux/platform_device.h>
 #include <linux/smc91x.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-db1x00/bcsr.h>
+#include <asm/mach-pb1x00/pb1200.h>
 
 #include "../platform.h"
 
@@ -88,7 +90,7 @@ static int pb1200mmc1_card_inserted(void
 	return (bcsr_read(BCSR_SIGSTAT) & BCSR_INT_SD1INSERT) ? 1 : 0;
 }
 
-const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
+static struct au1xmmc_platform_data pb1200mmc_platdata[2] = {
 	[0] = {
 		.set_power	= pb1200mmc0_set_power,
 		.card_inserted	= pb1200mmc0_card_inserted,
@@ -105,6 +107,79 @@ const struct au1xmmc_platform_data au1xm
 	},
 };
 
+static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+
+static struct resource au1200_mmc0_res[] = {
+	[0] = {
+		.start	= AU1100_SD0_PHYS_ADDR,
+		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct platform_device pb1200_mmc0_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &pb1200mmc_platdata[0],
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc0_res),
+	.resource	= au1200_mmc0_res,
+};
+
+static struct resource au1200_mmc1_res[] = {
+	[0] = {
+		.start	= AU1100_SD1_PHYS_ADDR,
+		.end	= AU1100_SD1_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX1,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX1,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX1,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX1,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct platform_device pb1200_mmc1_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 1,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &pb1200mmc_platdata[1],
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc1_res),
+	.resource	= au1200_mmc1_res,
+};
+
+
 static struct resource ide_resources[] = {
 	[0] = {
 		.start	= IDE_PHYS_ADDR,
@@ -115,7 +190,12 @@ static struct resource ide_resources[] =
 		.start	= IDE_INT,
 		.end	= IDE_INT,
 		.flags	= IORESOURCE_IRQ
-	}
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.end	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.flags	= IORESOURCE_DMA,
+	},
 };
 
 static u64 ide_dmamask = DMA_BIT_MASK(32);
@@ -161,38 +241,94 @@ static struct platform_device smc91c111_
 	.resource	= smc91c111_resources
 };
 
+static struct resource au1200_psc0_res[] = {
+	[0] = {
+		.start	= AU1550_PSC0_PHYS_ADDR,
+		.end	= AU1550_PSC0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_PSC0_INT,
+		.end	= AU1200_PSC0_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_PSC0_TX,
+		.end	= AU1200_DSCR_CMD0_PSC0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_PSC0_RX,
+		.end	= AU1200_DSCR_CMD0_PSC0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device pb1200_i2c_dev = {
+	.name		= "au1xpsc_smbus",
+	.id		= 0,	/* bus number */
+	.num_resources	= ARRAY_SIZE(au1200_psc0_res),
+	.resource	= au1200_psc0_res,
+};
+
+static struct resource au1200_lcd_res[] = {
+	[0] = {
+		.start	= AU1200_LCD_PHYS_ADDR,
+		.end	= AU1200_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_LCD_INT,
+		.end	= AU1200_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1200_lcd_dev = {
+	.name		= "au1200-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1200_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1200_lcd_res),
+	.resource	= au1200_lcd_res,
+};
+
 static struct platform_device *board_platform_devices[] __initdata = {
 	&ide_device,
-	&smc91c111_device
+	&smc91c111_device,
+	&pb1200_i2c_dev,
+	&pb1200_mmc0_dev,
+	&pb1200_mmc1_dev,
+	&au1200_lcd_dev,
 };
 
 static int __init board_register_devices(void)
 {
 	int swapped;
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    PB1200_PC0_INT,
-				    PB1200_PC0_INSERT_INT,
-				    /*PB1200_PC0_STSCHG_INT*/0,
-				    PB1200_PC0_EJECT_INT,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		PB1200_PC0_INT, PB1200_PC0_INSERT_INT,
+		/*PB1200_PC0_STSCHG_INT*/0, PB1200_PC0_EJECT_INT, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
-				    PB1200_PC1_INT,
-				    PB1200_PC1_INSERT_INT,
-				    /*PB1200_PC1_STSCHG_INT*/0,
-				    PB1200_PC1_EJECT_INT,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
+		PB1200_PC1_INT, PB1200_PC1_INSERT_INT,
+		/*PB1200_PC1_STSCHG_INT*/0, PB1200_PC1_EJECT_INT, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1200_SWAPBOOT;
 	db1x_register_norflash(128 * 1024 * 1024, 2, swapped);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1500/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1500/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1500/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1500/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,13 +33,6 @@
 
 #include <prom.h>
 
-
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff },   /* IDSEL 12 - HPT370	*/
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD },   /* IDSEL 13 - PCI slot */
-};
-
-
 const char *get_system_type(void)
 {
 	return "Alchemy Pb1500";
@@ -101,20 +94,18 @@ void __init board_setup(void)
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 #ifdef CONFIG_PCI
-	/* Setup PCI bus controller */
-	au_writel(0, Au1500_PCI_CMEM);
-	au_writel(0x00003fff, Au1500_CFG_BASE);
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-	au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
-	au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
-	au_writel(0x02a00356, Au1500_PCI_STATCMD);
-	au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
-	au_writel(0x00000008, Au1500_PCI_MBAR);
-	au_sync();
+	{
+		void __iomem *base =
+				(void __iomem *)KSEG1ADDR(AU1500_PCI_PHYS_ADDR);
+		/* Setup PCI bus controller */
+		__raw_writel(0x00003fff, base + PCI_REG_CMEM);
+		__raw_writel(0xf0000000, base + PCI_REG_MWMASK_DEV);
+		__raw_writel(0, base + PCI_REG_MWBASE_REV_CCL);
+		__raw_writel(0x02a00356, base + PCI_REG_STATCMD);
+		__raw_writel(0x00003c04, base + PCI_REG_PARAM);
+		__raw_writel(0x00000008, base + PCI_REG_MBAR);
+		wmb();
+	}
 #endif
 
 	/* Enable sys bus clock divider when IDLE state or no bus activity. */
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1500/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1500/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1500/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1500/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,32 +18,77 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static int pb1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata pb1500_pci_pd = {
+	.board_map_irq	= pb1500_map_pci_irq,
+	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			  PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			  0,
+#endif
+};
+
+static struct platform_device pb1500_pci_host = {
+	.dev.platform_data = &pb1500_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
 static int __init pb1500_dev_init(void)
 {
 	int swapped;
 
-	/* PCMCIA. single socket, identical to Pb1500 */
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1500_GPIO11_INT,	 /* card */
-				    AU1500_GPIO9_INT,	 /* insert */
-				    /*AU1500_GPIO10_INT*/0, /* stschg */
-				    0,			 /* eject */
-				    0);			 /* id */
+	/* PCMCIA. single socket, identical to Pb1100 */
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1500_GPIO11_INT, AU1500_GPIO9_INT,	 /* card / insert */
+		/*AU1500_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
 	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
+	platform_device_register(&pb1500_pci_host);
 
 	return 0;
 }
-device_initcall(pb1500_dev_init);
+arch_initcall(pb1500_dev_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1550/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1550/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1550/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1550/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,12 +37,6 @@
 
 #include <prom.h>
 
-
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD, AU1550_PCI_INTA }, /* IDSEL 12 - PCI slot 2 (left)  */
-	[13] = { -1, AU1550_PCI_INTA, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-
 const char *get_system_type(void)
 {
 	return "Alchemy Pb1550";
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1550/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1550/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/devboards/pb1550/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/devboards/pb1550/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,89 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
-
+#include <linux/platform_device.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-pb1x00/pb1550.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static int pb1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTB;
+		case 2: return AU1500_PCI_INTC;
+		case 3: return AU1500_PCI_INTD;
+		case 4: return AU1500_PCI_INTA;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata pb1550_pci_pd = {
+	.board_map_irq	= pb1550_map_pci_irq,
+};
+
+static struct platform_device pb1550_pci_host = {
+	.dev.platform_data = &pb1550_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+static struct resource au1550_psc2_res[] = {
+	[0] = {
+		.start	= AU1550_PSC2_PHYS_ADDR,
+		.end	= AU1550_PSC2_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1550_PSC2_INT,
+		.end	= AU1550_PSC2_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1550_DSCR_CMD0_PSC2_TX,
+		.end	= AU1550_DSCR_CMD0_PSC2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1550_DSCR_CMD0_PSC2_RX,
+		.end	= AU1550_DSCR_CMD0_PSC2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device pb1550_i2c_dev = {
+	.name		= "au1xpsc_smbus",
+	.id		= 0,	/* bus number */
+	.num_resources	= ARRAY_SIZE(au1550_psc2_res),
+	.resource	= au1550_psc2_res,
+};
+
 static int __init pb1550_dev_init(void)
 {
 	int swapped;
@@ -37,33 +112,29 @@ static int __init pb1550_dev_init(void)
 	* drivers are used to shared irqs and b) statuschange isn't really use-
 	* ful anyway.
 	*/
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1550_GPIO201_205_INT,
-				    AU1550_GPIO0_INT,
-				    0,
-				    0,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1550_GPIO201_205_INT, AU1550_GPIO0_INT, 0, 0, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
-				    AU1550_GPIO201_205_INT,
-				    AU1550_GPIO1_INT,
-				    0,
-				    0,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
+		AU1550_GPIO201_205_INT, AU1550_GPIO1_INT, 0, 0, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_PB1550_SWAPBOOT;
 	db1x_register_norflash(128 * 1024 * 1024, 4, swapped);
+	platform_device_register(&pb1550_pci_host);
+	platform_device_register(&pb1550_i2c_dev);
 
 	return 0;
 }
-device_initcall(pb1550_dev_init);
+arch_initcall(pb1550_dev_init);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/gpr/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/gpr/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/gpr/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/gpr/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,10 +36,6 @@
 
 #include <prom.h>
 
-char irq_tab_alchemy[][5] __initdata = {
-	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff },
-};
-
 static void gpr_reset(char *c)
 {
 	/* switch System-LED to orange (red# and green# on) */
@@ -76,12 +72,4 @@ void __init board_setup(void)
 
 	/* Take away Reset of UMTS-card */
 	alchemy_gpio_direction_output(215, 1);
-
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-#endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/gpr/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/gpr/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/gpr/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/gpr/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,6 +167,45 @@ static struct i2c_board_info gpr_i2c_inf
 	}
 };
 
+
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int gpr_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot == 0) && (pin == 1))
+		return AU1550_PCI_INTA;
+	else if ((slot == 0) && (pin == 2))
+		return AU1550_PCI_INTB;
+
+	return -1;
+}
+
+static struct alchemy_pci_platdata gpr_pci_pd = {
+	.board_map_irq	= gpr_map_pci_irq,
+	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			  PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			  0,
+#endif
+};
+
+static struct platform_device gpr_pci_host_dev = {
+	.dev.platform_data = &gpr_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
 static struct platform_device *gpr_devices[] __initdata = {
 	&gpr_wdt_device,
 	&gpr_mtd_device,
@@ -174,6 +213,14 @@ static struct platform_device *gpr_devic
 	&gpr_led_devices,
 };
 
+static int __init gpr_pci_init(void)
+{
+	return platform_device_register(&gpr_pci_host_dev);
+}
+/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
+arch_initcall(gpr_pci_init);
+
+
 static int __init gpr_dev_init(void)
 {
 	i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/Kconfig linux-libre-3.2-gnu1/arch/mips/alchemy/Kconfig
--- linux-libre-3.1-gnu1/arch/mips/alchemy/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -18,20 +18,20 @@ config MIPS_MTX1
 	bool "4G Systems MTX-1 board"
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_BOSPORUS
 	bool "Alchemy Bosporus board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_DB1000
 	bool "Alchemy DB1000 board"
-	select SOC_AU1000
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -39,14 +39,14 @@ config MIPS_DB1000
 
 config MIPS_DB1100
 	bool "Alchemy DB1100 board"
-	select SOC_AU1100
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_DB1200
 	bool "Alchemy DB1200 board"
-	select SOC_AU1200
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_COHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -54,7 +54,7 @@ config MIPS_DB1200
 
 config MIPS_DB1500
 	bool "Alchemy DB1500 board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -64,7 +64,7 @@ config MIPS_DB1500
 
 config MIPS_DB1550
 	bool "Alchemy DB1550 board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select HW_HAS_PCI
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -74,13 +74,13 @@ config MIPS_DB1550
 config MIPS_MIRAGE
 	bool "Alchemy Mirage board"
 	select DMA_NONCOHERENT
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_PB1000
 	bool "Alchemy PB1000 board"
-	select SOC_AU1000
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SWAP_IO_SPACE
@@ -89,7 +89,7 @@ config MIPS_PB1000
 
 config MIPS_PB1100
 	bool "Alchemy PB1100 board"
-	select SOC_AU1100
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SWAP_IO_SPACE
@@ -98,7 +98,7 @@ config MIPS_PB1100
 
 config MIPS_PB1200
 	bool "Alchemy PB1200 board"
-	select SOC_AU1200
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -106,7 +106,7 @@ config MIPS_PB1200
 
 config MIPS_PB1500
 	bool "Alchemy PB1500 board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -114,7 +114,7 @@ config MIPS_PB1500
 
 config MIPS_PB1550
 	bool "Alchemy PB1550 board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -124,13 +124,13 @@ config MIPS_PB1550
 config MIPS_XXS1500
 	bool "MyCable XXS1500 board"
 	select DMA_NONCOHERENT
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_GPR
 	bool "Trapeze ITS GPR board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select HW_HAS_PCI
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -138,23 +138,3 @@ config MIPS_GPR
 	select SYS_HAS_EARLY_PRINTK
 
 endchoice
-
-config SOC_AU1000
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1100
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1500
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1550
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1200
-	bool
-	select ALCHEMY_GPIOINT_AU1000
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/mtx-1/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/mtx-1/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/mtx-1/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/mtx-1/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,20 +38,6 @@
 
 #include <prom.h>
 
-char irq_tab_alchemy[][5] __initdata = {
-	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 00 - AdapterA-Slot0 (top) */
-	[1] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
-	[2] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 02 - AdapterB-Slot0 (top) */
-	[3] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
-	[4] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 04 - AdapterC-Slot0 (top) */
-	[5] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
-	[6] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 06 - AdapterD-Slot0 (top) */
-	[7] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
-};
-
-extern int (*board_pci_idsel)(unsigned int devsel, int assert);
-int mtx1_pci_idsel(unsigned int devsel, int assert);
-
 static void mtx1_reset(char *c)
 {
 	/* Jump to the reset vector */
@@ -74,15 +60,6 @@ void __init board_setup(void)
 	alchemy_gpio_direction_output(204, 0);
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-	board_pci_idsel = mtx1_pci_idsel;
-#endif
-
 	/* Initialize sys_pinfunc */
 	au_writel(SYS_PF_NI2, SYS_PINFUNC);
 
@@ -104,23 +81,6 @@ void __init board_setup(void)
 	printk(KERN_INFO "4G Systems MTX-1 Board\n");
 }
 
-int
-mtx1_pci_idsel(unsigned int devsel, int assert)
-{
-	/* This function is only necessary to support a proprietary Cardbus
-	 * adapter on the mtx-1 "singleboard" variant. It triggers a custom
-	 * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
-	 */
-	if (assert && devsel != 0)
-		/* Suppress signal to Cardbus */
-		alchemy_gpio_set_value(1, 0);	/* set EXT_IO3 OFF */
-	else
-		alchemy_gpio_set_value(1, 1);	/* set EXT_IO3 ON */
-
-	udelay(1);
-	return 1;
-}
-
 static int __init mtx1_init_irq(void)
 {
 	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/mtx-1/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/mtx-1/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/mtx-1/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/mtx-1/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -135,7 +135,69 @@ static struct platform_device mtx1_mtd =
 	.resource	= &mtx1_mtd_resource,
 };
 
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int mtx1_pci_idsel(unsigned int devsel, int assert)
+{
+	/* This function is only necessary to support a proprietary Cardbus
+	 * adapter on the mtx-1 "singleboard" variant. It triggers a custom
+	 * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
+	 */
+	if (assert && devsel != 0)
+		/* Suppress signal to Cardbus */
+		alchemy_gpio_set_value(1, 0);	/* set EXT_IO3 OFF */
+	else
+		alchemy_gpio_set_value(1, 1);	/* set EXT_IO3 ON */
+
+	udelay(1);
+	return 1;
+}
+
+static const char mtx1_irqtab[][5] = {
+	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 00 - AdapterA-Slot0 (top) */
+	[1] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
+	[2] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 02 - AdapterB-Slot0 (top) */
+	[3] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
+	[4] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 04 - AdapterC-Slot0 (top) */
+	[5] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
+	[6] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 06 - AdapterD-Slot0 (top) */
+	[7] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
+};
+
+static int mtx1_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	return mtx1_irqtab[slot][pin];
+}
+
+static struct alchemy_pci_platdata mtx1_pci_pd = {
+	.board_map_irq	 = mtx1_map_pci_irq,
+	.board_pci_idsel = mtx1_pci_idsel,
+	.pci_cfg_set	 = PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			   PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			   PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			   0,
+#endif
+};
+
+static struct platform_device mtx1_pci_host = {
+	.dev.platform_data = &mtx1_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+
 static struct __initdata platform_device * mtx1_devs[] = {
+	&mtx1_pci_host,
 	&mtx1_gpio_leds,
 	&mtx1_wdt,
 	&mtx1_button,
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/xxs1500/board_setup.c linux-libre-3.2-gnu1/arch/mips/alchemy/xxs1500/board_setup.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/xxs1500/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/xxs1500/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,14 +70,6 @@ void __init board_setup(void)
 	/* Enable DTR (MCR bit 0) = USB power up */
 	__raw_writel(1, (void __iomem *)KSEG1ADDR(AU1000_UART3_PHYS_ADDR + 0x18));
 	wmb();
-
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-#endif
 }
 
 static int __init xxs1500_init_irq(void)
diff -druNp linux-libre-3.1-gnu1/arch/mips/alchemy/xxs1500/platform.c linux-libre-3.2-gnu1/arch/mips/alchemy/xxs1500/platform.c
--- linux-libre-3.1-gnu1/arch/mips/alchemy/xxs1500/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/alchemy/xxs1500/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,20 +27,20 @@ static struct resource xxs1500_pcmcia_re
 	{
 		.name	= "pcmcia-io",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_IO_PHYS_ADDR,
-		.end	= PCMCIA_IO_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_IO_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_IO_PHYS_ADDR + 0x000400000 - 1,
 	},
 	{
 		.name	= "pcmcia-attr",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_ATTR_PHYS_ADDR,
-		.end	= PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
 	},
 	{
 		.name	= "pcmcia-mem",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_MEM_PHYS_ADDR,
-		.end	= PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_MEM_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/gpio.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/gpio.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
  */
 
+#include <linux/export.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_driver_chipcommon.h>
 #include <linux/ssb/ssb_driver_extif.h>
@@ -20,42 +21,82 @@ static DECLARE_BITMAP(gpio_in_use, BCM47
 
 int gpio_request(unsigned gpio, const char *tag)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return -EINVAL;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return -EINVAL;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-		return -EINVAL;
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return -EINVAL;
 
-	if (test_and_set_bit(gpio, gpio_in_use))
-		return -EBUSY;
+		if (test_and_set_bit(gpio, gpio_in_use))
+			return -EBUSY;
 
-	return 0;
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+			return -EINVAL;
+
+		if (test_and_set_bit(gpio, gpio_in_use))
+			return -EBUSY;
+
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL(gpio_request);
 
 void gpio_free(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return;
+
+		clear_bit(gpio, gpio_in_use);
 		return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+			return;
 
-	clear_bit(gpio, gpio_in_use);
+		clear_bit(gpio, gpio_in_use);
+		return;
+#endif
+	}
 }
 EXPORT_SYMBOL(gpio_free);
 
 int gpio_to_irq(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco))
-		return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
-	else if (ssb_extif_available(&ssb_bcm47xx.extif))
-		return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
-	else
-		return -EINVAL;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
+			return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
+		else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
+			return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
+		else
+			return -EINVAL;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
+#endif
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(gpio_to_irq);
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/irq.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/irq.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/irq_cpu.h>
+#include <bcm47xx.h>
 
 void plat_irq_dispatch(void)
 {
@@ -51,5 +52,16 @@ void plat_irq_dispatch(void)
 
 void __init arch_init_irq(void)
 {
+#ifdef CONFIG_BCM47XX_BCMA
+	if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+		bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
+			     BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
+		/*
+		 * the kernel reads the timer irq from some register and thinks
+		 * it's #5, but we offset it by 2 and route to #7
+		 */
+		cp0_compare_irq = 7;
+	}
+#endif
 	mips_cpu_irq_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/Kconfig linux-libre-3.2-gnu1/arch/mips/bcm47xx/Kconfig
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+if BCM47XX
+
+config BCM47XX_SSB
+	bool "SSB Support for Broadcom BCM47XX"
+	select SYS_HAS_CPU_MIPS32_R1
+	select SSB
+	select SSB_DRIVER_MIPS
+	select SSB_DRIVER_EXTIF
+	select SSB_EMBEDDED
+	select SSB_B43_PCI_BRIDGE if PCI
+	select SSB_PCICORE_HOSTMODE if PCI
+	default y
+	help
+	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
+
+	 This will generate an image with support for SSB and MIPS32 R1 instruction set.
+
+config BCM47XX_BCMA
+	bool "BCMA Support for Broadcom BCM47XX"
+	select SYS_HAS_CPU_MIPS32_R2
+	select BCMA
+	select BCMA_HOST_SOC
+	select BCMA_DRIVER_MIPS
+	select BCMA_DRIVER_PCI_HOSTMODE if PCI
+	default y
+	help
+	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
+
+	 This will generate an image with support for BCMA and MIPS32 R2 instruction set.
+
+endif
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/Makefile linux-libre-3.2-gnu1/arch/mips/bcm47xx/Makefile
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,5 @@
 # under Linux.
 #
 
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y 				+= gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/nvram.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/nvram.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,14 +26,35 @@ static char nvram_buf[NVRAM_SPACE];
 /* Probe for NVRAM header */
 static void early_nvram_init(void)
 {
-	struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+#ifdef CONFIG_BCM47XX_SSB
+	struct ssb_mipscore *mcore_ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	struct bcma_drv_cc *bcma_cc;
+#endif
 	struct nvram_header *header;
 	int i;
-	u32 base, lim, off;
+	u32 base = 0;
+	u32 lim = 0;
+	u32 off;
 	u32 *src, *dst;
 
-	base = mcore->flash_window;
-	lim = mcore->flash_window_size;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+		base = mcore_ssb->flash_window;
+		lim = mcore_ssb->flash_window_size;
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
+		base = bcma_cc->pflash.window;
+		lim = bcma_cc->pflash.window_size;
+		break;
+#endif
+	}
 
 	off = FLASH_MIN;
 	while (off <= lim) {
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/serial.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/serial.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,10 +23,11 @@ static struct platform_device uart8250_d
 	},
 };
 
-static int __init uart8250_init(void)
+#ifdef CONFIG_BCM47XX_SSB
+static int __init uart8250_init_ssb(void)
 {
 	int i;
-	struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+	struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
 
 	memset(&uart8250_data, 0,  sizeof(uart8250_data));
 
@@ -44,6 +45,47 @@ static int __init uart8250_init(void)
 	}
 	return platform_device_register(&uart8250_device);
 }
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static int __init uart8250_init_bcma(void)
+{
+	int i;
+	struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
+
+	memset(&uart8250_data, 0,  sizeof(uart8250_data));
+
+	for (i = 0; i < cc->nr_serial_ports; i++) {
+		struct plat_serial8250_port *p = &(uart8250_data[i]);
+		struct bcma_serial_port *bcma_port;
+		bcma_port = &(cc->serial_ports[i]);
+
+		p->mapbase = (unsigned int) bcma_port->regs;
+		p->membase = (void *) bcma_port->regs;
+		p->irq = bcma_port->irq + 2;
+		p->uartclk = bcma_port->baud_base;
+		p->regshift = bcma_port->reg_shift;
+		p->iotype = UPIO_MEM;
+		p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	}
+	return platform_device_register(&uart8250_device);
+}
+#endif
+
+static int __init uart8250_init(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		return uart8250_init_ssb();
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return uart8250_init_bcma();
+#endif
+	}
+	return -EINVAL;
+}
 
 module_init(uart8250_init);
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/setup.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/setup.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,24 +26,40 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma_soc.h>
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
-struct ssb_bus ssb_bcm47xx;
-EXPORT_SYMBOL(ssb_bcm47xx);
+union bcm47xx_bus bcm47xx_bus;
+EXPORT_SYMBOL(bcm47xx_bus);
+
+enum bcm47xx_bus_type bcm47xx_bus_type;
+EXPORT_SYMBOL(bcm47xx_bus_type);
 
 static void bcm47xx_machine_restart(char *command)
 {
 	printk(KERN_ALERT "Please stand by while rebooting the system...\n");
 	local_irq_disable();
 	/* Set the watchdog timer to reset immediately */
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+		break;
+#endif
+	}
 	while (1)
 		cpu_relax();
 }
@@ -52,11 +68,23 @@ static void bcm47xx_machine_halt(void)
 {
 	/* Disable interrupts and watchdog and spin forever */
 	local_irq_disable();
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
+		break;
+#endif
+	}
 	while (1)
 		cpu_relax();
 }
 
+#ifdef CONFIG_BCM47XX_SSB
 #define READ_FROM_NVRAM(_outvar, name, buf) \
 	if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
 		sprom->_outvar = simple_strtoul(buf, NULL, 0);
@@ -247,7 +275,7 @@ static int bcm47xx_get_invariants(struct
 	return 0;
 }
 
-void __init plat_mem_setup(void)
+static void __init bcm47xx_register_ssb(void)
 {
 	int err;
 	char buf[100];
@@ -258,12 +286,12 @@ void __init plat_mem_setup(void)
 		printk(KERN_WARNING "bcm47xx: someone else already registered"
 			" a ssb SPROM callback handler (err %d)\n", err);
 
-	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+	err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
 				      bcm47xx_get_invariants);
 	if (err)
 		panic("Failed to initialize SSB bus (err %d)\n", err);
 
-	mcore = &ssb_bcm47xx.mipscore;
+	mcore = &bcm47xx_bus.ssb.mipscore;
 	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
 		if (strstr(buf, "console=ttyS1")) {
 			struct ssb_serial_port port;
@@ -276,8 +304,57 @@ void __init plat_mem_setup(void)
 			memcpy(&mcore->serial_ports[1], &port, sizeof(port));
 		}
 	}
+}
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static void __init bcm47xx_register_bcma(void)
+{
+	int err;
+
+	err = bcma_host_soc_register(&bcm47xx_bus.bcma);
+	if (err)
+		panic("Failed to initialize BCMA bus (err %d)\n", err);
+}
+#endif
+
+void __init plat_mem_setup(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	if (c->cputype == CPU_74K) {
+		printk(KERN_INFO "bcm47xx: using bcma bus\n");
+#ifdef CONFIG_BCM47XX_BCMA
+		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
+		bcm47xx_register_bcma();
+#endif
+	} else {
+		printk(KERN_INFO "bcm47xx: using ssb bus\n");
+#ifdef CONFIG_BCM47XX_SSB
+		bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
+		bcm47xx_register_ssb();
+#endif
+	}
 
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
 	pm_power_off = bcm47xx_machine_halt;
 }
+
+static int __init bcm47xx_register_bus_complete(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		/* Nothing to do */
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_bus_register(&bcm47xx_bus.bcma.bus);
+		break;
+#endif
+	}
+	return 0;
+}
+device_initcall(bcm47xx_register_bus_complete);
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/time.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/time.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 void __init plat_time_init(void)
 {
-	unsigned long hz;
+	unsigned long hz = 0;
 
 	/*
 	 * Use deterministic values for initial counter interrupt
@@ -39,7 +39,19 @@ void __init plat_time_init(void)
 	write_c0_count(0);
 	write_c0_compare(0xffff);
 
-	hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+		break;
+#endif
+	}
+
 	if (!hz)
 		hz = 100000000;
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/bcm47xx/wgt634u.c linux-libre-3.2-gnu1/arch/mips/bcm47xx/wgt634u.c
--- linux-libre-3.1-gnu1/arch/mips/bcm47xx/wgt634u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/bcm47xx/wgt634u.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int ir
 
 	/* Interrupts are shared, check if the current one is
 	   a GPIO interrupt. */
-	if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+	if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
 				   SSB_CHIPCO_IRQ_GPIO))
 		return IRQ_NONE;
 
@@ -132,22 +132,26 @@ static int __init wgt634u_init(void)
 	 * machine. Use the MAC address as an heuristic. Netgear Inc. has
 	 * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
 	 */
+	u8 *et0mac;
 
-	u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
+	if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
+		return -ENODEV;
+
+	et0mac = bcm47xx_bus.ssb.sprom.et0mac;
 
 	if (et0mac[0] == 0x00 &&
 	    ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
 	     (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
-		struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+		struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
 
 		printk(KERN_INFO "WGT634U machine detected.\n");
 
 		if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
 				 gpio_interrupt, IRQF_SHARED,
-				 "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+				 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
 			gpio_direction_input(WGT634U_GPIO_RESET);
 			gpio_intmask(WGT634U_GPIO_RESET, 1);
-			ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+			ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
 					    SSB_CHIPCO_IRQ_GPIO,
 					    SSB_CHIPCO_IRQ_GPIO);
 		}
diff -druNp linux-libre-3.1-gnu1/arch/mips/cavium-octeon/csrc-octeon.c linux-libre-3.2-gnu1/arch/mips/cavium-octeon/csrc-octeon.c
--- linux-libre-3.1-gnu1/arch/mips/cavium-octeon/csrc-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/cavium-octeon/csrc-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  * Copyright (C) 2009, 2010 Cavium Networks, Inc.
  */
 #include <linux/clocksource.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/smp.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/cavium-octeon/dma-octeon.c linux-libre-3.2-gnu1/arch/mips/cavium-octeon/dma-octeon.c
--- linux-libre-3.1-gnu1/arch/mips/cavium-octeon/dma-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/cavium-octeon/dma-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/swiotlb.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/cavium-octeon/flash_setup.c linux-libre-3.2-gnu1/arch/mips/cavium-octeon/flash_setup.c
--- linux-libre-3.1-gnu1/arch/mips/cavium-octeon/flash_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/cavium-octeon/flash_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * Copyright (C) 2007, 2008 Cavium Networks
  */
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
@@ -16,8 +17,6 @@
 
 static struct map_info flash_map;
 static struct mtd_info *mymtd;
-static int nr_parts;
-static struct mtd_partition *parts;
 static const char *part_probe_types[] = {
 	"cmdlinepart",
 #ifdef CONFIG_MTD_REDBOOT_PARTS
@@ -60,11 +59,8 @@ static int __init flash_init(void)
 		mymtd = do_map_probe("cfi_probe", &flash_map);
 		if (mymtd) {
 			mymtd->owner = THIS_MODULE;
-
-			nr_parts = parse_mtd_partitions(mymtd,
-							part_probe_types,
-							&parts, 0);
-			mtd_device_register(mymtd, parts, nr_parts);
+			mtd_device_parse_register(mymtd, part_probe_types,
+						  0, NULL, 0);
 		} else {
 			pr_err("Failed to register MTD device for flash\n");
 		}
diff -druNp linux-libre-3.1-gnu1/arch/mips/cavium-octeon/smp.c linux-libre-3.2-gnu1/arch/mips/cavium-octeon/smp.c
--- linux-libre-3.1-gnu1/arch/mips/cavium-octeon/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/cavium-octeon/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -207,8 +207,9 @@ void octeon_prepare_cpus(unsigned int ma
 	 * the other bits alone.
 	 */
 	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff);
-	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
-			"SMP-IPI", mailbox_interrupt)) {
+	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt,
+			IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI",
+			mailbox_interrupt)) {
 		panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
 	}
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/emma/common/prom.c linux-libre-3.2-gnu1/arch/mips/emma/common/prom.c
--- linux-libre-3.1-gnu1/arch/mips/emma/common/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/emma/common/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,7 +50,7 @@ void __init prom_init(void)
 
 	/* arg[0] is "g", the rest is boot parameters */
 	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		if (strlen(arcs_cmdline) + strlen(arg[i]) + 1
 		    >= sizeof(arcs_cmdline))
 			break;
 		strcat(arcs_cmdline, arg[i]);
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/cacheflush.h linux-libre-3.2-gnu1/arch/mips/include/asm/cacheflush.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/cacheflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/cacheflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -114,4 +114,28 @@ unsigned long run_uncached(void *func);
 extern void *kmap_coherent(struct page *page, unsigned long addr);
 extern void kunmap_coherent(void);
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+	BUG_ON(cpu_has_dc_aliases && PageHighMem(page));
+}
+
+/*
+ * For now flush_kernel_vmap_range and invalidate_kernel_vmap_range both do a
+ * cache writeback and invalidate operation.
+ */
+extern void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
+
+static inline void flush_kernel_vmap_range(void *vaddr, int size)
+{
+	if (cpu_has_dc_aliases)
+		__flush_kernel_vmap_range((unsigned long) vaddr, size);
+}
+
+static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
+{
+	if (cpu_has_dc_aliases)
+		__flush_kernel_vmap_range((unsigned long) vaddr, size);
+}
+
 #endif /* _ASM_CACHEFLUSH_H */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/compat.h linux-libre-3.2-gnu1/arch/mips/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,8 @@ struct compat_statfs {
 	int		f_bavail;
 	compat_fsid_t	f_fsid;
 	int		f_namelen;
-	int		f_spare[6];
+	int		f_flags;
+	int		f_spare[5];
 };
 
 #define COMPAT_RLIM_INFINITY	0x7fffffffUL
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/cpu.h linux-libre-3.2-gnu1/arch/mips/include/asm/cpu.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -135,6 +135,9 @@
 #define PRID_IMP_CAVIUM_CN50XX 0x0600
 #define PRID_IMP_CAVIUM_CN52XX 0x0700
 #define PRID_IMP_CAVIUM_CN63XX 0x9000
+#define PRID_IMP_CAVIUM_CN68XX 0x9100
+#define PRID_IMP_CAVIUM_CN66XX 0x9200
+#define PRID_IMP_CAVIUM_CN61XX 0x9300
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/io.h linux-libre-3.2-gnu1/arch/mips/include/asm/io.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -329,14 +329,10 @@ static inline void pfx##write##bwlq(type
 			"dsrl32	%L0, %L0, 0"			"\n\t"	\
 			"dsll32	%M0, %M0, 0"			"\n\t"	\
 			"or	%L0, %L0, %M0"			"\n\t"	\
-			".set	push"				"\n\t"	\
-			".set	noreorder"			"\n\t"	\
-			".set	nomacro"			"\n\t"	\
 			"sd	%L0, %2"			"\n\t"	\
-			".set	pop"				"\n\t"	\
 			".set	mips0"				"\n"	\
 			: "=r" (__tmp)					\
-			: "0" (__val), "R" (*__mem));			\
+			: "0" (__val), "m" (*__mem));			\
 		if (irq)						\
 			local_irq_restore(__flags);			\
 	} else								\
@@ -359,16 +355,12 @@ static inline type pfx##read##bwlq(const
 			local_irq_save(__flags);			\
 		__asm__ __volatile__(					\
 			".set	mips3"		"\t\t# __readq"	"\n\t"	\
-			".set	push"				"\n\t"	\
-			".set	noreorder"			"\n\t"	\
-			".set	nomacro"			"\n\t"	\
 			"ld	%L0, %1"			"\n\t"	\
-			".set	pop"				"\n\t"	\
 			"dsra32	%M0, %L0, 0"			"\n\t"	\
 			"sll	%L0, %L0, 0"			"\n\t"	\
 			".set	mips0"				"\n"	\
 			: "=r" (__val)					\
-			: "R" (*__mem));				\
+			: "m" (*__mem));				\
 		if (irq)						\
 			local_irq_restore(__flags);			\
 	} else {							\
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/lasat/lasat.h linux-libre-3.2-gnu1/arch/mips/include/asm/lasat/lasat.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/lasat/lasat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/lasat/lasat.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,10 +41,8 @@ enum lasat_mtdparts {
 
 /*
  * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
+ * See the LASAT Hardware Configuration field specification for a detailed
+ * description of the config field.
  */
 #include <linux/types.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1000.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1000.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1000.h	2012-01-04 18:55:44.000000000 -0500
@@ -245,6 +245,23 @@ void alchemy_sleep_au1000(void);
 void alchemy_sleep_au1550(void);
 void au_sleep(void);
 
+/* USB: drivers/usb/host/alchemy-common.c */
+enum alchemy_usb_block {
+	ALCHEMY_USB_OHCI0,
+	ALCHEMY_USB_UDC0,
+	ALCHEMY_USB_EHCI0,
+	ALCHEMY_USB_OTG0,
+};
+int alchemy_usb_control(int block, int enable);
+
+/* PCI controller platform data */
+struct alchemy_pci_platdata {
+	int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
+	int (*board_pci_idsel)(unsigned int devsel, int assert);
+	/* bits to set/clear in PCI_CONFIG register */
+	unsigned long pci_cfg_set;
+	unsigned long pci_cfg_clr;
+};
 
 /* SOC Interrupt numbers */
 
@@ -575,38 +592,95 @@ enum soc_au1200_ints {
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
 /*
- * SDRAM register offsets
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200
  */
-#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \
-    defined(CONFIG_SOC_AU1100)
-#define MEM_SDMODE0		0x0000
-#define MEM_SDMODE1		0x0004
-#define MEM_SDMODE2		0x0008
-#define MEM_SDADDR0		0x000C
-#define MEM_SDADDR1		0x0010
-#define MEM_SDADDR2		0x0014
-#define MEM_SDREFCFG		0x0018
-#define MEM_SDPRECMD		0x001C
-#define MEM_SDAUTOREF		0x0020
-#define MEM_SDWRMD0		0x0024
-#define MEM_SDWRMD1		0x0028
-#define MEM_SDWRMD2		0x002C
-#define MEM_SDSLEEP		0x0030
-#define MEM_SDSMCKE		0x0034
 
-/*
- * MEM_SDMODE register content definitions
- */
+#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
+#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
+#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR		0x10300000 /* 4 */
+#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
+#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 24 */
+#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
+#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
+#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 01234 */
+#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
+#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 34 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 34 */
+#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 4 */
+#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
+#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
+#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 4 */
+#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 01234 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 01234 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 01234 */
+
+
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0		0x0000
+#define AU1000_MEM_SDMODE1		0x0004
+#define AU1000_MEM_SDMODE2		0x0008
+#define AU1000_MEM_SDADDR0		0x000C
+#define AU1000_MEM_SDADDR1		0x0010
+#define AU1000_MEM_SDADDR2		0x0014
+#define AU1000_MEM_SDREFCFG		0x0018
+#define AU1000_MEM_SDPRECMD		0x001C
+#define AU1000_MEM_SDAUTOREF		0x0020
+#define AU1000_MEM_SDWRMD0		0x0024
+#define AU1000_MEM_SDWRMD1		0x0028
+#define AU1000_MEM_SDWRMD2		0x002C
+#define AU1000_MEM_SDSLEEP		0x0030
+#define AU1000_MEM_SDSMCKE		0x0034
+
+/* MEM_SDMODE register content definitions */
 #define MEM_SDMODE_F		(1 << 22)
 #define MEM_SDMODE_SR		(1 << 21)
 #define MEM_SDMODE_BS		(1 << 20)
 #define MEM_SDMODE_RS		(3 << 18)
 #define MEM_SDMODE_CS		(7 << 15)
-#define MEM_SDMODE_TRAS 	(15 << 11)
-#define MEM_SDMODE_TMRD 	(3 << 9)
+#define MEM_SDMODE_TRAS		(15 << 11)
+#define MEM_SDMODE_TMRD		(3 << 9)
 #define MEM_SDMODE_TWR		(3 << 7)
 #define MEM_SDMODE_TRP		(3 << 5)
-#define MEM_SDMODE_TRCD 	(3 << 3)
+#define MEM_SDMODE_TRCD		(3 << 3)
 #define MEM_SDMODE_TCL		(7 << 0)
 
 #define MEM_SDMODE_BS_2Bank	(0 << 20)
@@ -628,173 +702,43 @@ enum soc_au1200_ints {
 #define MEM_SDMODE_TRCD_N(N)	((N) << 3)
 #define MEM_SDMODE_TCL_N(N)	((N) << 0)
 
-/*
- * MEM_SDADDR register contents definitions
- */
+/* MEM_SDADDR register contents definitions */
 #define MEM_SDADDR_E		(1 << 20)
-#define MEM_SDADDR_CSBA 	(0x03FF << 10)
+#define MEM_SDADDR_CSBA		(0x03FF << 10)
 #define MEM_SDADDR_CSMASK	(0x03FF << 0)
 #define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
 #define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
 
-/*
- * MEM_SDREFCFG register content definitions
- */
+/* MEM_SDREFCFG register content definitions */
 #define MEM_SDREFCFG_TRC	(15 << 28)
 #define MEM_SDREFCFG_TRPM	(3 << 26)
 #define MEM_SDREFCFG_E		(1 << 25)
-#define MEM_SDREFCFG_RE 	(0x1ffffff << 0)
+#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
 #define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
 #define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
 #define MEM_SDREFCFG_REF_N(N)	(N)
-#endif
-
-/***********************************************************************/
-
-/*
- * Au1550 SDRAM Register Offsets
- */
-
-/***********************************************************************/
-
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-#define MEM_SDMODE0		0x0800
-#define MEM_SDMODE1		0x0808
-#define MEM_SDMODE2		0x0810
-#define MEM_SDADDR0		0x0820
-#define MEM_SDADDR1		0x0828
-#define MEM_SDADDR2		0x0830
-#define MEM_SDCONFIGA		0x0840
-#define MEM_SDCONFIGB		0x0848
-#define MEM_SDSTAT		0x0850
-#define MEM_SDERRADDR		0x0858
-#define MEM_SDSTRIDE0		0x0860
-#define MEM_SDSTRIDE1		0x0868
-#define MEM_SDSTRIDE2		0x0870
-#define MEM_SDWRMD0		0x0880
-#define MEM_SDWRMD1		0x0888
-#define MEM_SDWRMD2		0x0890
-#define MEM_SDPRECMD		0x08C0
-#define MEM_SDAUTOREF		0x08C8
-#define MEM_SDSREF		0x08D0
-#define MEM_SDSLEEP		MEM_SDSREF
-
-#endif
-
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200
- */
-
-#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
-#define AU1000_USBD_PHYS_ADDR		0x10200000 /* 0123 */
-#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
-#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 24 */
-#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
-#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
-#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
-#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 01234 */
-#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 34 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 34 */
-#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
-
-
-#ifdef CONFIG_SOC_AU1000
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define	IRDA_PHYS_ADDR		0x10300000
-#define	SSI0_PHYS_ADDR		0x11600000
-#define	SSI1_PHYS_ADDR		0x11680000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/********************************************************************/
 
-#ifdef CONFIG_SOC_AU1500
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define PCI_PHYS_ADDR		0x14005000
-#define PCI_MEM_PHYS_ADDR	0x400000000ULL
-#define PCI_IO_PHYS_ADDR	0x500000000ULL
-#define PCI_CONFIG0_PHYS_ADDR	0x600000000ULL
-#define PCI_CONFIG1_PHYS_ADDR	0x680000000ULL
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/********************************************************************/
-
-#ifdef CONFIG_SOC_AU1100
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define	IRDA_PHYS_ADDR		0x10300000
-#define	SSI0_PHYS_ADDR		0x11600000
-#define	SSI1_PHYS_ADDR		0x11680000
-#define LCD_PHYS_ADDR		0x15000000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/***********************************************************************/
-
-#ifdef CONFIG_SOC_AU1550
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x14020000
-#define PCI_PHYS_ADDR		0x14005000
-#define PE_PHYS_ADDR		0x14008000
-#define PSC0_PHYS_ADDR		0x11A00000
-#define PSC1_PHYS_ADDR		0x11B00000
-#define PSC2_PHYS_ADDR		0x10A00000
-#define PSC3_PHYS_ADDR		0x10B00000
-#define PCI_MEM_PHYS_ADDR	0x400000000ULL
-#define PCI_IO_PHYS_ADDR	0x500000000ULL
-#define PCI_CONFIG0_PHYS_ADDR	0x600000000ULL
-#define PCI_CONFIG1_PHYS_ADDR	0x680000000ULL
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/***********************************************************************/
-
-#ifdef CONFIG_SOC_AU1200
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define AES_PHYS_ADDR		0x10300000
-#define CIM_PHYS_ADDR		0x14004000
-#define USBM_PHYS_ADDR		0x14020000
-#define	USBH_PHYS_ADDR		0x14020100
-#define PSC0_PHYS_ADDR	 	0x11A00000
-#define PSC1_PHYS_ADDR	 	0x11B00000
-#define LCD_PHYS_ADDR		0x15000000
-#define SWCNT_PHYS_ADDR		0x1110010C
-#define MAEFE_PHYS_ADDR		0x14012000
-#define MAEBE_PHYS_ADDR		0x14010000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0		0x0800
+#define AU1550_MEM_SDMODE1		0x0808
+#define AU1550_MEM_SDMODE2		0x0810
+#define AU1550_MEM_SDADDR0		0x0820
+#define AU1550_MEM_SDADDR1		0x0828
+#define AU1550_MEM_SDADDR2		0x0830
+#define AU1550_MEM_SDCONFIGA		0x0840
+#define AU1550_MEM_SDCONFIGB		0x0848
+#define AU1550_MEM_SDSTAT		0x0850
+#define AU1550_MEM_SDERRADDR		0x0858
+#define AU1550_MEM_SDSTRIDE0		0x0860
+#define AU1550_MEM_SDSTRIDE1		0x0868
+#define AU1550_MEM_SDSTRIDE2		0x0870
+#define AU1550_MEM_SDWRMD0		0x0880
+#define AU1550_MEM_SDWRMD1		0x0888
+#define AU1550_MEM_SDWRMD2		0x0890
+#define AU1550_MEM_SDPRECMD		0x08C0
+#define AU1550_MEM_SDAUTOREF		0x08C8
+#define AU1550_MEM_SDSREF		0x08D0
+#define AU1550_MEM_SDSLEEP		MEM_SDSREF
 
 /* Static Bus Controller */
 #define MEM_STCFG0		0xB4001000
@@ -813,80 +757,13 @@ enum soc_au1200_ints {
 #define MEM_STTIME3		0xB4001034
 #define MEM_STADDR3		0xB4001038
 
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
 #define MEM_STNDCTL		0xB4001100
 #define MEM_STSTAT		0xB4001104
 
 #define MEM_STNAND_CMD		0x0
 #define MEM_STNAND_ADDR 	0x4
 #define MEM_STNAND_DATA 	0x20
-#endif
-
-
-
-
-/* Au1000 */
-#ifdef CONFIG_SOC_AU1000
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017FFFC
-#define FOR_PLATFORM_C_USB_HOST_INT AU1000_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1000 */
-
-/* Au1500 */
-#ifdef CONFIG_SOC_AU1500
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017fffc
-#define FOR_PLATFORM_C_USB_HOST_INT AU1500_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1500 */
-
-/* Au1100 */
-#ifdef CONFIG_SOC_AU1100
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017FFFC
-#define FOR_PLATFORM_C_USB_HOST_INT AU1100_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1100 */
-
-#ifdef CONFIG_SOC_AU1550
-
-#define USB_OHCI_BASE		0x14020000	/* phys addr for ioremap */
-#define USB_OHCI_LEN		0x00060000
-#define USB_HOST_CONFIG 	0xB4027ffc
-#define FOR_PLATFORM_C_USB_HOST_INT AU1550_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1550 */
-
-
-#ifdef CONFIG_SOC_AU1200
-
-#define USB_UOC_BASE		0x14020020
-#define USB_UOC_LEN		0x20
-#define USB_OHCI_BASE		0x14020100
-#define USB_OHCI_LEN		0x100
-#define USB_EHCI_BASE		0x14020200
-#define USB_EHCI_LEN		0x100
-#define USB_UDC_BASE		0x14022000
-#define USB_UDC_LEN		0x2000
-#define USB_MSR_BASE		0xB4020000
-#define USB_MSR_MCFG		4
-#define USBMSRMCFG_OMEMEN	0
-#define USBMSRMCFG_OBMEN	1
-#define USBMSRMCFG_EMEMEN	2
-#define USBMSRMCFG_EBMEN	3
-#define USBMSRMCFG_DMEMEN	4
-#define USBMSRMCFG_DBMEN	5
-#define USBMSRMCFG_GMEMEN	6
-#define USBMSRMCFG_OHCCLKEN	16
-#define USBMSRMCFG_EHCCLKEN	17
-#define USBMSRMCFG_UDCCLKEN	18
-#define USBMSRMCFG_PHYPLLEN	19
-#define USBMSRMCFG_RDCOMB	30
-#define USBMSRMCFG_PFEN 	31
 
-#define FOR_PLATFORM_C_USB_HOST_INT AU1200_USB_INT
-
-#endif /* CONFIG_SOC_AU1200 */
 
 /* Programmable Counters 0 and 1 */
 #define SYS_BASE		0xB1900000
@@ -958,56 +835,6 @@ enum soc_au1200_ints {
 #  define I2S_CONTROL_D 	(1 << 1)
 #  define I2S_CONTROL_CE	(1 << 0)
 
-/* USB Host Controller */
-#ifndef USB_OHCI_LEN
-#define USB_OHCI_LEN		0x00100000
-#endif
-
-#ifndef CONFIG_SOC_AU1200
-
-/* USB Device Controller */
-#define USBD_EP0RD		0xB0200000
-#define USBD_EP0WR		0xB0200004
-#define USBD_EP2WR		0xB0200008
-#define USBD_EP3WR		0xB020000C
-#define USBD_EP4RD		0xB0200010
-#define USBD_EP5RD		0xB0200014
-#define USBD_INTEN		0xB0200018
-#define USBD_INTSTAT		0xB020001C
-#  define USBDEV_INT_SOF	(1 << 12)
-#  define USBDEV_INT_HF_BIT	6
-#  define USBDEV_INT_HF_MASK	(0x3f << USBDEV_INT_HF_BIT)
-#  define USBDEV_INT_CMPLT_BIT	0
-#  define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT)
-#define USBD_CONFIG		0xB0200020
-#define USBD_EP0CS		0xB0200024
-#define USBD_EP2CS		0xB0200028
-#define USBD_EP3CS		0xB020002C
-#define USBD_EP4CS		0xB0200030
-#define USBD_EP5CS		0xB0200034
-#  define USBDEV_CS_SU		(1 << 14)
-#  define USBDEV_CS_NAK 	(1 << 13)
-#  define USBDEV_CS_ACK 	(1 << 12)
-#  define USBDEV_CS_BUSY	(1 << 11)
-#  define USBDEV_CS_TSIZE_BIT	1
-#  define USBDEV_CS_TSIZE_MASK	(0x3ff << USBDEV_CS_TSIZE_BIT)
-#  define USBDEV_CS_STALL	(1 << 0)
-#define USBD_EP0RDSTAT		0xB0200040
-#define USBD_EP0WRSTAT		0xB0200044
-#define USBD_EP2WRSTAT		0xB0200048
-#define USBD_EP3WRSTAT		0xB020004C
-#define USBD_EP4RDSTAT		0xB0200050
-#define USBD_EP5RDSTAT		0xB0200054
-#  define USBDEV_FSTAT_FLUSH	(1 << 6)
-#  define USBDEV_FSTAT_UF	(1 << 5)
-#  define USBDEV_FSTAT_OF	(1 << 4)
-#  define USBDEV_FSTAT_FCNT_BIT 0
-#  define USBDEV_FSTAT_FCNT_MASK (0x0f << USBDEV_FSTAT_FCNT_BIT)
-#define USBD_ENABLE		0xB0200058
-#  define USBDEV_ENABLE 	(1 << 1)
-#  define USBDEV_CE		(1 << 0)
-
-#endif /* !CONFIG_SOC_AU1200 */
 
 /* Ethernet Controllers  */
 
@@ -1322,7 +1149,6 @@ enum soc_au1200_ints {
 #  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
 
 /* Au1200 only */
-#ifdef CONFIG_SOC_AU1200
 #define SYS_PINFUNC_DMA 	(1 << 31)
 #define SYS_PINFUNC_S0A 	(1 << 30)
 #define SYS_PINFUNC_S1A 	(1 << 29)
@@ -1350,7 +1176,6 @@ enum soc_au1200_ints {
 #define SYS_PINFUNC_P0B 	(1 << 4)
 #define SYS_PINFUNC_U0T 	(1 << 3)
 #define SYS_PINFUNC_S1B 	(1 << 2)
-#endif
 
 /* Power Management */
 #define SYS_SCRATCH0		0xB1900018
@@ -1406,12 +1231,12 @@ enum soc_au1200_ints {
 #  define SYS_CS_MI2_MASK	(0x7 << SYS_CS_MI2_BIT)
 #  define SYS_CS_DI2		(1 << 16)
 #  define SYS_CS_CI2		(1 << 15)
-#ifdef CONFIG_SOC_AU1100
+
 #  define SYS_CS_ML_BIT 	7
 #  define SYS_CS_ML_MASK	(0x7 << SYS_CS_ML_BIT)
 #  define SYS_CS_DL		(1 << 6)
 #  define SYS_CS_CL		(1 << 5)
-#else
+
 #  define SYS_CS_MUH_BIT	12
 #  define SYS_CS_MUH_MASK	(0x7 << SYS_CS_MUH_BIT)
 #  define SYS_CS_DUH		(1 << 11)
@@ -1420,7 +1245,7 @@ enum soc_au1200_ints {
 #  define SYS_CS_MUD_MASK	(0x7 << SYS_CS_MUD_BIT)
 #  define SYS_CS_DUD		(1 << 6)
 #  define SYS_CS_CUD		(1 << 5)
-#endif
+
 #  define SYS_CS_MIR_BIT	2
 #  define SYS_CS_MIR_MASK	(0x7 << SYS_CS_MIR_BIT)
 #  define SYS_CS_DIR		(1 << 1)
@@ -1467,58 +1292,30 @@ enum soc_au1200_ints {
 #  define AC97C_RS		(1 << 1)
 #  define AC97C_CE		(1 << 0)
 
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-/* Au1500 PCI Controller */
-#define Au1500_CFG_BASE 	0xB4005000	/* virtual, KSEG1 addr */
-#define Au1500_PCI_CMEM 	(Au1500_CFG_BASE + 0)
-#define Au1500_PCI_CFG		(Au1500_CFG_BASE + 4)
-#  define PCI_ERROR		((1 << 22) | (1 << 23) | (1 << 24) | \
-				 (1 << 25) | (1 << 26) | (1 << 27))
-#define Au1500_PCI_B2BMASK_CCH	(Au1500_CFG_BASE + 8)
-#define Au1500_PCI_B2B0_VID	(Au1500_CFG_BASE + 0xC)
-#define Au1500_PCI_B2B1_ID	(Au1500_CFG_BASE + 0x10)
-#define Au1500_PCI_MWMASK_DEV	(Au1500_CFG_BASE + 0x14)
-#define Au1500_PCI_MWBASE_REV_CCL (Au1500_CFG_BASE + 0x18)
-#define Au1500_PCI_ERR_ADDR	(Au1500_CFG_BASE + 0x1C)
-#define Au1500_PCI_SPEC_INTACK	(Au1500_CFG_BASE + 0x20)
-#define Au1500_PCI_ID		(Au1500_CFG_BASE + 0x100)
-#define Au1500_PCI_STATCMD	(Au1500_CFG_BASE + 0x104)
-#define Au1500_PCI_CLASSREV	(Au1500_CFG_BASE + 0x108)
-#define Au1500_PCI_HDRTYPE	(Au1500_CFG_BASE + 0x10C)
-#define Au1500_PCI_MBAR 	(Au1500_CFG_BASE + 0x110)
-
-#define Au1500_PCI_HDR		0xB4005100	/* virtual, KSEG1 addr */
 
-/*
- * All of our structures, like PCI resource, have 32-bit members.
- * Drivers are expected to do an ioremap on the PCI MEM resource, but it's
- * hard to store 0x4 0000 0000 in a 32-bit type.  We require a small patch
- * to __ioremap to check for addresses between (u32)Au1500_PCI_MEM_START and
- * (u32)Au1500_PCI_MEM_END and change those to the full 36-bit PCI MEM
- * addresses.  For PCI I/O, it's simpler because we get to do the ioremap
- * ourselves and then adjust the device's resources.
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI.  When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
  */
-#define Au1500_EXT_CFG		0x600000000ULL
-#define Au1500_EXT_CFG_TYPE1	0x680000000ULL
-#define Au1500_PCI_IO_START	0x500000000ULL
-#define Au1500_PCI_IO_END	0x5000FFFFFULL
-#define Au1500_PCI_MEM_START	0x440000000ULL
-#define Au1500_PCI_MEM_END	0x44FFFFFFFULL
+#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
 
-#define PCI_IO_START	0x00001000
-#define PCI_IO_END	0x000FFFFF
-#define PCI_MEM_START	0x40000000
-#define PCI_MEM_END	0x4FFFFFFF
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START		0x00001000
+#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
 
-#define PCI_FIRST_DEVFN (0 << 3)
-#define PCI_LAST_DEVFN	(19 << 3)
+#ifdef CONFIG_PCI
 
 #define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
 #define IOPORT_RESOURCE_END	0xffffffff
 #define IOMEM_RESOURCE_START	0x10000000
 #define IOMEM_RESOURCE_END	0xfffffffffULL
 
-#else /* Au1000 and Au1100 and Au1200 */
+#else
 
 /* Don't allow any legacy ports probing */
 #define IOPORT_RESOURCE_START	0x10000000
@@ -1526,13 +1323,77 @@ enum soc_au1200_ints {
 #define IOMEM_RESOURCE_START	0x10000000
 #define IOMEM_RESOURCE_END	0xfffffffffULL
 
-#define PCI_IO_START	0
-#define PCI_IO_END	0
-#define PCI_MEM_START	0
-#define PCI_MEM_END	0
-#define PCI_FIRST_DEVFN 0
-#define PCI_LAST_DEVFN	0
-
 #endif
 
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM		0x0000
+#define PCI_REG_CONFIG		0x0004
+#define PCI_REG_B2BMASK_CCH	0x0008
+#define PCI_REG_B2BBASE0_VID	0x000C
+#define PCI_REG_B2BBASE1_SID	0x0010
+#define PCI_REG_MWMASK_DEV	0x0014
+#define PCI_REG_MWBASE_REV_CCL	0x0018
+#define PCI_REG_ERR_ADDR	0x001C
+#define PCI_REG_SPEC_INTACK	0x0020
+#define PCI_REG_ID		0x0100
+#define PCI_REG_STATCMD		0x0104
+#define PCI_REG_CLASSREV	0x0108
+#define PCI_REG_PARAM		0x010C
+#define PCI_REG_MBAR		0x0110
+#define PCI_REG_TIMEOUT		0x0140
+
+/* PCI controller block register bits */
+#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
+#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
+#define PCI_CONFIG_EP		(1 << 24) /* parity error */
+#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
+#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
+#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
+#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
+#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x)  (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x)  ((x) & 0xff)
+#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
+#define PCI_ID_VID(x)		((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x)	((x) & 0xff)
+#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x)	((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
+#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2012-01-04 18:55:44.000000000 -0500
@@ -126,66 +126,62 @@ typedef volatile struct au1xxx_ddma_desc
 #define SW_STATUS_INUSE 	(1 << 0)
 
 /* Command 0 device IDs. */
-#ifdef CONFIG_SOC_AU1550
-#define DSCR_CMD0_UART0_TX	0
-#define DSCR_CMD0_UART0_RX	1
-#define DSCR_CMD0_UART3_TX	2
-#define DSCR_CMD0_UART3_RX	3
-#define DSCR_CMD0_DMA_REQ0	4
-#define DSCR_CMD0_DMA_REQ1	5
-#define DSCR_CMD0_DMA_REQ2	6
-#define DSCR_CMD0_DMA_REQ3	7
-#define DSCR_CMD0_USBDEV_RX0	8
-#define DSCR_CMD0_USBDEV_TX0	9
-#define DSCR_CMD0_USBDEV_TX1	10
-#define DSCR_CMD0_USBDEV_TX2	11
-#define DSCR_CMD0_USBDEV_RX3	12
-#define DSCR_CMD0_USBDEV_RX4	13
-#define DSCR_CMD0_PSC0_TX	14
-#define DSCR_CMD0_PSC0_RX	15
-#define DSCR_CMD0_PSC1_TX	16
-#define DSCR_CMD0_PSC1_RX	17
-#define DSCR_CMD0_PSC2_TX	18
-#define DSCR_CMD0_PSC2_RX	19
-#define DSCR_CMD0_PSC3_TX	20
-#define DSCR_CMD0_PSC3_RX	21
-#define DSCR_CMD0_PCI_WRITE	22
-#define DSCR_CMD0_NAND_FLASH	23
-#define DSCR_CMD0_MAC0_RX	24
-#define DSCR_CMD0_MAC0_TX	25
-#define DSCR_CMD0_MAC1_RX	26
-#define DSCR_CMD0_MAC1_TX	27
-#endif /* CONFIG_SOC_AU1550 */
+#define AU1550_DSCR_CMD0_UART0_TX	0
+#define AU1550_DSCR_CMD0_UART0_RX	1
+#define AU1550_DSCR_CMD0_UART3_TX	2
+#define AU1550_DSCR_CMD0_UART3_RX	3
+#define AU1550_DSCR_CMD0_DMA_REQ0	4
+#define AU1550_DSCR_CMD0_DMA_REQ1	5
+#define AU1550_DSCR_CMD0_DMA_REQ2	6
+#define AU1550_DSCR_CMD0_DMA_REQ3	7
+#define AU1550_DSCR_CMD0_USBDEV_RX0	8
+#define AU1550_DSCR_CMD0_USBDEV_TX0	9
+#define AU1550_DSCR_CMD0_USBDEV_TX1	10
+#define AU1550_DSCR_CMD0_USBDEV_TX2	11
+#define AU1550_DSCR_CMD0_USBDEV_RX3	12
+#define AU1550_DSCR_CMD0_USBDEV_RX4	13
+#define AU1550_DSCR_CMD0_PSC0_TX	14
+#define AU1550_DSCR_CMD0_PSC0_RX	15
+#define AU1550_DSCR_CMD0_PSC1_TX	16
+#define AU1550_DSCR_CMD0_PSC1_RX	17
+#define AU1550_DSCR_CMD0_PSC2_TX	18
+#define AU1550_DSCR_CMD0_PSC2_RX	19
+#define AU1550_DSCR_CMD0_PSC3_TX	20
+#define AU1550_DSCR_CMD0_PSC3_RX	21
+#define AU1550_DSCR_CMD0_PCI_WRITE	22
+#define AU1550_DSCR_CMD0_NAND_FLASH	23
+#define AU1550_DSCR_CMD0_MAC0_RX	24
+#define AU1550_DSCR_CMD0_MAC0_TX	25
+#define AU1550_DSCR_CMD0_MAC1_RX	26
+#define AU1550_DSCR_CMD0_MAC1_TX	27
 
-#ifdef CONFIG_SOC_AU1200
-#define DSCR_CMD0_UART0_TX	0
-#define DSCR_CMD0_UART0_RX	1
-#define DSCR_CMD0_UART1_TX	2
-#define DSCR_CMD0_UART1_RX	3
-#define DSCR_CMD0_DMA_REQ0	4
-#define DSCR_CMD0_DMA_REQ1	5
-#define DSCR_CMD0_MAE_BE	6
-#define DSCR_CMD0_MAE_FE	7
-#define DSCR_CMD0_SDMS_TX0	8
-#define DSCR_CMD0_SDMS_RX0	9
-#define DSCR_CMD0_SDMS_TX1	10
-#define DSCR_CMD0_SDMS_RX1	11
-#define DSCR_CMD0_AES_TX	13
-#define DSCR_CMD0_AES_RX	12
-#define DSCR_CMD0_PSC0_TX	14
-#define DSCR_CMD0_PSC0_RX	15
-#define DSCR_CMD0_PSC1_TX	16
-#define DSCR_CMD0_PSC1_RX	17
-#define DSCR_CMD0_CIM_RXA	18
-#define DSCR_CMD0_CIM_RXB	19
-#define DSCR_CMD0_CIM_RXC	20
-#define DSCR_CMD0_MAE_BOTH	21
-#define DSCR_CMD0_LCD		22
-#define DSCR_CMD0_NAND_FLASH	23
-#define DSCR_CMD0_PSC0_SYNC	24
-#define DSCR_CMD0_PSC1_SYNC	25
-#define DSCR_CMD0_CIM_SYNC	26
-#endif /* CONFIG_SOC_AU1200 */
+#define AU1200_DSCR_CMD0_UART0_TX	0
+#define AU1200_DSCR_CMD0_UART0_RX	1
+#define AU1200_DSCR_CMD0_UART1_TX	2
+#define AU1200_DSCR_CMD0_UART1_RX	3
+#define AU1200_DSCR_CMD0_DMA_REQ0	4
+#define AU1200_DSCR_CMD0_DMA_REQ1	5
+#define AU1200_DSCR_CMD0_MAE_BE		6
+#define AU1200_DSCR_CMD0_MAE_FE		7
+#define AU1200_DSCR_CMD0_SDMS_TX0	8
+#define AU1200_DSCR_CMD0_SDMS_RX0	9
+#define AU1200_DSCR_CMD0_SDMS_TX1	10
+#define AU1200_DSCR_CMD0_SDMS_RX1	11
+#define AU1200_DSCR_CMD0_AES_TX		13
+#define AU1200_DSCR_CMD0_AES_RX		12
+#define AU1200_DSCR_CMD0_PSC0_TX	14
+#define AU1200_DSCR_CMD0_PSC0_RX	15
+#define AU1200_DSCR_CMD0_PSC1_TX	16
+#define AU1200_DSCR_CMD0_PSC1_RX	17
+#define AU1200_DSCR_CMD0_CIM_RXA	18
+#define AU1200_DSCR_CMD0_CIM_RXB	19
+#define AU1200_DSCR_CMD0_CIM_RXC	20
+#define AU1200_DSCR_CMD0_MAE_BOTH	21
+#define AU1200_DSCR_CMD0_LCD		22
+#define AU1200_DSCR_CMD0_NAND_FLASH	23
+#define AU1200_DSCR_CMD0_PSC0_SYNC	24
+#define AU1200_DSCR_CMD0_PSC1_SYNC	25
+#define AU1200_DSCR_CMD0_CIM_SYNC	26
 
 #define DSCR_CMD0_THROTTLE	30
 #define DSCR_CMD0_ALWAYS	31
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _AU1XXX_H_
-#define _AU1XXX_H_
-
-#include <asm/mach-au1x00/au1000.h>
-
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \
-    defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550)
-#include <asm/mach-db1x00/db1x00.h>
-
-#elif defined(CONFIG_MIPS_PB1550)
-#include <asm/mach-pb1x00/pb1550.h>
-
-#elif defined(CONFIG_MIPS_PB1200)
-#include <asm/mach-pb1x00/pb1200.h>
-
-#elif defined(CONFIG_MIPS_DB1200)
-#include <asm/mach-db1x00/db1200.h>
-
-#endif
-
-#endif /* _AU1XXX_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h	2012-01-04 18:55:44.000000000 -0500
@@ -58,6 +58,7 @@ typedef struct {
 #endif
 	int			irq;
 	u32			regbase;
+	int			ddma_id;
 } _auide_hwif;
 
 /******************************************************************************/
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,19 +33,6 @@
 #ifndef _AU1000_PSC_H_
 #define _AU1000_PSC_H_
 
-/* The PSC base addresses.  */
-#ifdef CONFIG_SOC_AU1550
-#define PSC0_BASE_ADDR		0xb1a00000
-#define PSC1_BASE_ADDR		0xb1b00000
-#define PSC2_BASE_ADDR		0xb0a00000
-#define PSC3_BASE_ADDR		0xb0b00000
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-#define PSC0_BASE_ADDR		0xb1a00000
-#define PSC1_BASE_ADDR		0xb1b00000
-#endif
-
 /*
  * The PSC select and control registers are common to all protocols.
  */
@@ -80,19 +67,6 @@
 #define PSC_AC97GPO_OFFSET	0x00000028
 #define PSC_AC97GPI_OFFSET	0x0000002c
 
-#define AC97_PSC_SEL		(AC97_PSC_BASE + PSC_SEL_OFFSET)
-#define AC97_PSC_CTRL		(AC97_PSC_BASE + PSC_CTRL_OFFSET)
-#define PSC_AC97CFG		(AC97_PSC_BASE + PSC_AC97CFG_OFFSET)
-#define PSC_AC97MSK		(AC97_PSC_BASE + PSC_AC97MSK_OFFSET)
-#define PSC_AC97PCR		(AC97_PSC_BASE + PSC_AC97PCR_OFFSET)
-#define PSC_AC97STAT		(AC97_PSC_BASE + PSC_AC97STAT_OFFSET)
-#define PSC_AC97EVNT		(AC97_PSC_BASE + PSC_AC97EVNT_OFFSET)
-#define PSC_AC97TXRX		(AC97_PSC_BASE + PSC_AC97TXRX_OFFSET)
-#define PSC_AC97CDC		(AC97_PSC_BASE + PSC_AC97CDC_OFFSET)
-#define PSC_AC97RST		(AC97_PSC_BASE + PSC_AC97RST_OFFSET)
-#define PSC_AC97GPO		(AC97_PSC_BASE + PSC_AC97GPO_OFFSET)
-#define PSC_AC97GPI		(AC97_PSC_BASE + PSC_AC97GPI_OFFSET)
-
 /* AC97 Config Register. */
 #define PSC_AC97CFG_RT_MASK	(3 << 30)
 #define PSC_AC97CFG_RT_FIFO1	(0 << 30)
@@ -394,19 +368,6 @@ typedef struct	psc_spi {
 #define PSC_SPITXRX_LC		(1 << 29)
 #define PSC_SPITXRX_SR		(1 << 28)
 
-/* PSC in SMBus (I2C) Mode. */
-typedef struct	psc_smb {
-	u32	psc_sel;
-	u32	psc_ctrl;
-	u32	psc_smbcfg;
-	u32	psc_smbmsk;
-	u32	psc_smbpcr;
-	u32	psc_smbstat;
-	u32	psc_smbevnt;
-	u32	psc_smbtxrx;
-	u32	psc_smbtmr;
-} psc_smb_t;
-
 /* SMBus Config Register. */
 #define PSC_SMBCFG_RT_MASK	(3 << 30)
 #define PSC_SMBCFG_RT_FIFO1	(0 << 30)
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/gpio-au1000.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2012-01-04 18:55:44.000000000 -0500
@@ -347,17 +347,6 @@ static inline int alchemy_gpio2_to_irq(i
 
 /**********************************************************************/
 
-/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
- * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200 this
- * register enables use of GPIOs as wake source.
- */
-static inline void alchemy_gpio1_input_enable(void)
-{
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
-	__raw_writel(0, base + SYS_PININPUTEN);	/* the write op is key */
-	wmb();
-}
-
 /* GPIO2 shared interrupts and control */
 
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
@@ -561,6 +550,7 @@ static inline int alchemy_irq_to_gpio(in
 
 #ifndef CONFIG_GPIOLIB
 
+#ifdef CONFIG_ALCHEMY_GPIOINT_AU1000
 
 #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (4) */
 
@@ -665,24 +655,7 @@ static inline void gpio_unexport(unsigne
 
 #endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
 
-
-#else	/* CONFIG GPIOLIB */
-
-
- /* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (2) */
-
-/* get everything through gpiolib */
-#define gpio_to_irq	__gpio_to_irq
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define irq_to_gpio	alchemy_irq_to_gpio
-
-#include <asm-generic/gpio.h>
-
-#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
+#endif	/* CONFIG_ALCHEMY_GPIOINT_AU1000 */
 
 #endif	/* !CONFIG_GPIOLIB */
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/gpio.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/gpio.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-au1x00/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-au1x00/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,83 @@
+/*
+ * Alchemy GPIO support.
+ *
+ * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within
+ *  the same kernel image.
+ * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the
+ *  appropriate CPU type (AU1000 currently).
+ */
+
 #ifndef _ALCHEMY_GPIO_H_
 #define _ALCHEMY_GPIO_H_
 
-#if defined(CONFIG_ALCHEMY_GPIOINT_AU1000)
-
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/gpio-au1000.h>
 
-#endif
+/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
+ * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200/Au1300 this
+ * register enables use of GPIOs as wake source.
+ */
+static inline void alchemy_gpio1_input_enable(void)
+{
+	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+	__raw_writel(0, base + 0x110);		/* the write op is key */
+	wmb();
+}
+
+
+/* Linux gpio framework integration.
+*
+* 4 use cases of Alchemy GPIOS:
+*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
+*	Board must register gpiochips.
+*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
+*	A gpiochip for the 75 GPIOs is registered.
+*
+*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
+*	the boards' gpio.h must provide	the linux gpio wrapper functions,
+*
+*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
+*	inlinable gpio functions are provided which enable access to the
+*	Au1300 gpios only by using the numbers straight out of the data-
+*	sheets.
+
+* Cases 1 and 3 are intended for boards which want to provide their own
+* GPIO namespace and -operations (i.e. for example you have 8 GPIOs
+* which are in part provided by spare Au1300 GPIO pins and in part by
+* an external FPGA but you still want them to be accssible in linux
+* as gpio0-7. The board can of course use the alchemy_gpioX_* functions
+* as required).
+*/
+
+#ifdef CONFIG_GPIOLIB
+
+/* wraps the cpu-dependent irq_to_gpio functions */
+/* FIXME: gpiolib needs an irq_to_gpio hook */
+static inline int __au_irq_to_gpio(unsigned int irq)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+		return alchemy_irq_to_gpio(irq);
+	}
+	return -EINVAL;
+}
+
+
+/* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
+#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (2) */
+
+/* get everything through gpiolib */
+#define gpio_to_irq	__gpio_to_irq
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define irq_to_gpio	__au_irq_to_gpio
+
+#include <asm-generic/gpio.h>
+
+#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
+
+
+#endif	/* CONFIG_GPIOLIB */
 
 #endif	/* _ALCHEMY_GPIO_H_ */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,29 @@
 #ifndef __ASM_BCM47XX_H
 #define __ASM_BCM47XX_H
 
-/* SSB bus */
-extern struct ssb_bus ssb_bcm47xx;
+#include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+enum bcm47xx_bus_type {
+#ifdef CONFIG_BCM47XX_SSB
+	BCM47XX_BUS_TYPE_SSB,
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	BCM47XX_BUS_TYPE_BCMA,
+#endif
+};
+
+union bcm47xx_bus {
+#ifdef CONFIG_BCM47XX_SSB
+	struct ssb_bus ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	struct bcma_soc bcma;
+#endif
+};
+
+extern union bcm47xx_bus bcm47xx_bus;
+extern enum bcm47xx_bus_type bcm47xx_bus_type;
 
 #endif /* __ASM_BCM47XX_H */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-bcm47xx/gpio.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-bcm47xx/gpio.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-bcm47xx/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-bcm47xx/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #define __BCM47XX_GPIO_H
 
 #include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma.h>
 #include <asm/mach-bcm47xx/bcm47xx.h>
 
 #define BCM47XX_EXTIF_GPIO_LINES	5
@@ -21,45 +22,134 @@ extern int gpio_to_irq(unsigned gpio);
 
 static inline int gpio_get_value(unsigned gpio)
 {
-	return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
+					   1 << gpio);
+#endif
+	}
+	return -EINVAL;
 }
 
+#define gpio_get_value_cansleep	gpio_get_value
+
 static inline void gpio_set_value(unsigned gpio, int value)
 {
-	ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+			     value ? 1 << gpio : 0);
+		return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				     value ? 1 << gpio : 0);
+		return;
+#endif
+	}
 }
 
-static inline int gpio_direction_input(unsigned gpio)
+#define gpio_set_value_cansleep gpio_set_value
+
+static inline int gpio_cansleep(unsigned gpio)
 {
-	ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
 	return 0;
 }
 
+static inline int gpio_is_valid(unsigned gpio)
+{
+	return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
+}
+
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				       0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
+}
+
 static inline int gpio_direction_output(unsigned gpio, int value)
 {
-	/* first set the gpio out value */
-	ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
-	/* then set the gpio mode */
-	ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		/* first set the gpio out value */
+		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+			     value ? 1 << gpio : 0);
+		/* then set the gpio mode */
+		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* first set the gpio out value */
+		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				     value ? 1 << gpio : 0);
+		/* then set the gpio mode */
+		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				       1 << gpio);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 static inline int gpio_intmask(unsigned gpio, int value)
 {
-	ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
-			 value ? 1 << gpio : 0);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
+				 value ? 1 << gpio : 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
+					 1 << gpio, value ? 1 << gpio : 0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 static inline int gpio_polarity(unsigned gpio, int value)
 {
-	ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
-			  value ? 1 << gpio : 0);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
+				  value ? 1 << gpio : 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
+					  1 << gpio, value ? 1 << gpio : 0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 
-/* cansleep wrappers */
-#include <asm-generic/gpio.h>
-
 #endif /* __BCM47XX_GPIO_H */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-db1x00/db1200.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-db1x00/db1200.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-db1x00/db1200.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-db1x00/db1200.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,8 +46,6 @@
 
 #define IDE_PHYS_ADDR		0x18800000
 #define IDE_REG_SHIFT		5
-#define IDE_DDMA_REQ		DSCR_CMD0_DMA_REQ1
-#define IDE_RQSIZE		128
 
 #define DB1200_IDE_PHYS_ADDR	IDE_PHYS_ADDR
 #define DB1200_IDE_PHYS_LEN	(16 << IDE_REG_SHIFT)
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-db1x00/db1x00.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-db1x00/db1x00.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-db1x00/db1x00.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-db1x00/db1x00.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,15 +31,15 @@
 
 #ifdef CONFIG_MIPS_DB1550
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC3_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC3_RX
+#define DBDMA_AC97_TX_CHAN	AU1550_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1550_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1550_DSCR_CMD0_PSC3_TX
+#define DBDMA_I2S_RX_CHAN	AU1550_DSCR_CMD0_PSC3_RX
 
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define AC97_PSC_BASE		PSC1_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC2_BASE_ADDR
-#define I2S_PSC_BASE		PSC3_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define AC97_PSC_BASE		AU1550_PSC1_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC2_PHYS_ADDR
+#define I2S_PSC_BASE		AU1550_PSC3_PHYS_ADDR
 
 #define NAND_PHYS_ADDR		0x20000000
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-pb1x00/pb1200.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-pb1x00/pb1200.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-pb1x00/pb1200.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-pb1x00/pb1200.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,23 +28,23 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC1_RX
+#define DBDMA_AC97_TX_CHAN	AU1200_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1200_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1200_DSCR_CMD0_PSC1_TX
+#define DBDMA_I2S_RX_CHAN	AU1200_DSCR_CMD0_PSC1_RX
 
 /*
  * SPI and SMB are muxed on the Pb1200 board.
  * Refer to board documentation.
  */
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC0_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC0_PHYS_ADDR
 /*
  * AC97 and I2S are muxed on the Pb1200 board.
  * Refer to board documentation.
  */
-#define AC97_PSC_BASE       PSC1_BASE_ADDR
-#define I2S_PSC_BASE	PSC1_BASE_ADDR
+#define AC97_PSC_BASE       AU1550_PSC1_PHYS_ADDR
+#define I2S_PSC_BASE	AU1550_PSC1_PHYS_ADDR
 
 
 #define BCSR_SYSTEM_VDDI	0x001F
@@ -76,8 +76,6 @@
 #define IDE_REG_SHIFT		5
 #define IDE_PHYS_LEN		(16 << IDE_REG_SHIFT)
 #define IDE_INT 		PB1200_IDE_INT
-#define IDE_DDMA_REQ		DSCR_CMD0_DMA_REQ1
-#define IDE_RQSIZE		128
 
 #define NAND_PHYS_ADDR 	0x1C000000
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mach-pb1x00/pb1550.h linux-libre-3.2-gnu1/arch/mips/include/asm/mach-pb1x00/pb1550.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mach-pb1x00/pb1550.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mach-pb1x00/pb1550.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,15 +30,15 @@
 #include <linux/types.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC3_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC3_RX
+#define DBDMA_AC97_TX_CHAN	AU1550_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1550_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1550_DSCR_CMD0_PSC3_TX
+#define DBDMA_I2S_RX_CHAN	AU1550_DSCR_CMD0_PSC3_RX
 
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define AC97_PSC_BASE		PSC1_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC2_BASE_ADDR
-#define I2S_PSC_BASE		PSC3_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define AC97_PSC_BASE		AU1550_PSC1_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC2_PHYS_ADDR
+#define I2S_PSC_BASE		AU1550_PSC3_PHYS_ADDR
 
 /*
  * Timing values as described in databook, * ns value stripped of
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mipsprom.h linux-libre-3.2-gnu1/arch/mips/include/asm/mipsprom.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mipsprom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mipsprom.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
-#ifndef __ASM_MIPS_PROM_H
-#define __ASM_MIPS_PROM_H
+#ifndef __ASM_MIPSPROM_H
+#define __ASM_MIPSPROM_H
 
 #define PROM_RESET		0
 #define PROM_EXEC		1
@@ -73,4 +73,4 @@
 
 extern char *prom_getenv(char *);
 
-#endif /* __ASM_MIPS_PROM_H */
+#endif /* __ASM_MIPSPROM_H */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/mipsregs.h linux-libre-3.2-gnu1/arch/mips/include/asm/mipsregs.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/mipsregs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/mipsregs.h	2012-01-04 18:55:44.000000000 -0500
@@ -1006,18 +1006,26 @@ do {									\
 #define write_c0_perfctrl0(val)	__write_32bit_c0_register($25, 0, val)
 #define read_c0_perfcntr0()	__read_32bit_c0_register($25, 1)
 #define write_c0_perfcntr0(val)	__write_32bit_c0_register($25, 1, val)
+#define read_c0_perfcntr0_64()	__read_64bit_c0_register($25, 1)
+#define write_c0_perfcntr0_64(val) __write_64bit_c0_register($25, 1, val)
 #define read_c0_perfctrl1()	__read_32bit_c0_register($25, 2)
 #define write_c0_perfctrl1(val)	__write_32bit_c0_register($25, 2, val)
 #define read_c0_perfcntr1()	__read_32bit_c0_register($25, 3)
 #define write_c0_perfcntr1(val)	__write_32bit_c0_register($25, 3, val)
+#define read_c0_perfcntr1_64()	__read_64bit_c0_register($25, 3)
+#define write_c0_perfcntr1_64(val) __write_64bit_c0_register($25, 3, val)
 #define read_c0_perfctrl2()	__read_32bit_c0_register($25, 4)
 #define write_c0_perfctrl2(val)	__write_32bit_c0_register($25, 4, val)
 #define read_c0_perfcntr2()	__read_32bit_c0_register($25, 5)
 #define write_c0_perfcntr2(val)	__write_32bit_c0_register($25, 5, val)
+#define read_c0_perfcntr2_64()	__read_64bit_c0_register($25, 5)
+#define write_c0_perfcntr2_64(val) __write_64bit_c0_register($25, 5, val)
 #define read_c0_perfctrl3()	__read_32bit_c0_register($25, 6)
 #define write_c0_perfctrl3(val)	__write_32bit_c0_register($25, 6, val)
 #define read_c0_perfcntr3()	__read_32bit_c0_register($25, 7)
 #define write_c0_perfcntr3(val)	__write_32bit_c0_register($25, 7, val)
+#define read_c0_perfcntr3_64()	__read_64bit_c0_register($25, 7)
+#define write_c0_perfcntr3_64(val) __write_64bit_c0_register($25, 7, val)
 
 /* RM9000 PerfCount performance counter register */
 #define read_c0_perfcount()	__read_64bit_c0_register($25, 0)
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/prom.h linux-libre-3.2-gnu1/arch/mips/include/asm/prom.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/prom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/prom.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  *
  */
-#ifndef __ASM_MIPS_PROM_H
-#define __ASM_MIPS_PROM_H
+#ifndef __ASM_PROM_H
+#define __ASM_PROM_H
 
 #ifdef CONFIG_OF
 #include <asm/bootinfo.h>
@@ -25,4 +25,4 @@ extern void device_tree_init(void);
 static inline void device_tree_init(void) { }
 #endif /* CONFIG_OF */
 
-#endif /* _ASM_MIPS_PROM_H */
+#endif /* __ASM_PROM_H */
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/regdef.h linux-libre-3.2-gnu1/arch/mips/include/asm/regdef.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/regdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/regdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,8 @@
  * Copyright (C) 1985 MIPS Computer Systems, Inc.
  * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle
  * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2011 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #ifndef _ASM_REGDEF_H
 #define _ASM_REGDEF_H
@@ -30,9 +32,13 @@
 #define t2      $10
 #define t3      $11
 #define t4      $12
+#define ta0	$12
 #define t5      $13
+#define ta1	$13
 #define t6      $14
+#define ta2	$14
 #define t7      $15
+#define ta3	$15
 #define s0      $16     /* callee saved */
 #define s1      $17
 #define s2      $18
diff -druNp linux-libre-3.1-gnu1/arch/mips/include/asm/unistd.h linux-libre-3.2-gnu1/arch/mips/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/mips/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -365,16 +365,18 @@
 #define __NR_syncfs			(__NR_Linux + 342)
 #define __NR_sendmmsg			(__NR_Linux + 343)
 #define __NR_setns			(__NR_Linux + 344)
+#define __NR_process_vm_readv		(__NR_Linux + 345)
+#define __NR_process_vm_writev		(__NR_Linux + 346)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		344
+#define __NR_Linux_syscalls		346
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		344
+#define __NR_O32_Linux_syscalls		346
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -686,16 +688,18 @@
 #define __NR_syncfs			(__NR_Linux + 301)
 #define __NR_sendmmsg			(__NR_Linux + 302)
 #define __NR_setns			(__NR_Linux + 303)
+#define __NR_process_vm_readv		(__NR_Linux + 304)
+#define __NR_process_vm_writev		(__NR_Linux + 305)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		303
+#define __NR_Linux_syscalls		305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		303
+#define __NR_64_Linux_syscalls		305
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -1012,16 +1016,18 @@
 #define __NR_syncfs			(__NR_Linux + 306)
 #define __NR_sendmmsg			(__NR_Linux + 307)
 #define __NR_setns			(__NR_Linux + 308)
+#define __NR_process_vm_readv		(__NR_Linux + 309)
+#define __NR_process_vm_writev		(__NR_Linux + 310)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		308
+#define __NR_Linux_syscalls		310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		308
+#define __NR_N32_Linux_syscalls		310
 
 #ifdef __KERNEL__
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/jz4740/gpio.c linux-libre-3.2-gnu1/arch/mips/jz4740/gpio.c
--- linux-libre-3.1-gnu1/arch/mips/jz4740/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/jz4740/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
@@ -30,6 +28,8 @@
 
 #include <asm/mach-jz4740/base.h>
 
+#include "irq.h"
+
 #define JZ4740_GPIO_BASE_A (32*0)
 #define JZ4740_GPIO_BASE_B (32*1)
 #define JZ4740_GPIO_BASE_C (32*2)
@@ -77,14 +77,10 @@
 struct jz_gpio_chip {
 	unsigned int irq;
 	unsigned int irq_base;
-	uint32_t wakeup;
-	uint32_t suspend_mask;
 	uint32_t edge_trigger_both;
 
 	void __iomem *base;
 
-	spinlock_t lock;
-
 	struct gpio_chip gpio_chip;
 };
 
@@ -102,7 +98,8 @@ static inline struct jz_gpio_chip *gpio_
 
 static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data)
 {
-	return irq_data_get_irq_chip_data(data);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	return gc->private;
 }
 
 static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
@@ -304,21 +301,15 @@ static void jz_gpio_irq_demux_handler(un
 {
 	uint32_t flag;
 	unsigned int gpio_irq;
-	unsigned int gpio_bank;
 	struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc);
 
-	gpio_bank = JZ4740_IRQ_GPIO0 - irq;
-
 	flag = readl(chip->base + JZ_REG_GPIO_FLAG);
-
 	if (!flag)
 		return;
 
-	gpio_irq = __fls(flag);
-
-	jz_gpio_check_trigger_both(chip, irq);
+	gpio_irq = chip->irq_base + __fls(flag);
 
-	gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0);
+	jz_gpio_check_trigger_both(chip, gpio_irq);
 
 	generic_handle_irq(gpio_irq);
 };
@@ -329,18 +320,12 @@ static inline void jz_gpio_set_irq_bit(s
 	writel(IRQ_TO_BIT(data->irq), chip->base + reg);
 }
 
-static void jz_gpio_irq_mask(struct irq_data *data)
-{
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET);
-};
-
 static void jz_gpio_irq_unmask(struct irq_data *data)
 {
 	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
 
 	jz_gpio_check_trigger_both(chip, data->irq);
-
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR);
+	irq_gc_unmask_enable_reg(data);
 };
 
 /* TODO: Check if function is gpio */
@@ -353,18 +338,13 @@ static unsigned int jz_gpio_irq_startup(
 
 static void jz_gpio_irq_shutdown(struct irq_data *data)
 {
-	jz_gpio_irq_mask(data);
+	irq_gc_mask_disable_reg(data);
 
 	/* Set direction to input */
 	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR);
 	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR);
 }
 
-static void jz_gpio_irq_ack(struct irq_data *data)
-{
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR);
-};
-
 static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
 {
 	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
@@ -408,35 +388,13 @@ static int jz_gpio_irq_set_type(struct i
 static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
 {
 	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
-	spin_lock(&chip->lock);
-	if (on)
-		chip->wakeup |= IRQ_TO_BIT(data->irq);
-	else
-		chip->wakeup &= ~IRQ_TO_BIT(data->irq);
-	spin_unlock(&chip->lock);
 
+	irq_gc_set_wake(data, on);
 	irq_set_irq_wake(chip->irq, on);
+
 	return 0;
 }
 
-static struct irq_chip jz_gpio_irq_chip = {
-	.name = "GPIO",
-	.irq_mask = jz_gpio_irq_mask,
-	.irq_unmask = jz_gpio_irq_unmask,
-	.irq_ack = jz_gpio_irq_ack,
-	.irq_startup = jz_gpio_irq_startup,
-	.irq_shutdown = jz_gpio_irq_shutdown,
-	.irq_set_type = jz_gpio_irq_set_type,
-	.irq_set_wake = jz_gpio_irq_set_wake,
-	.flags = IRQCHIP_SET_TYPE_MASKED,
-};
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
 #define JZ4740_GPIO_CHIP(_bank) { \
 	.irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \
 	.gpio_chip = { \
@@ -458,64 +416,44 @@ static struct jz_gpio_chip jz4740_gpio_c
 	JZ4740_GPIO_CHIP(D),
 };
 
-static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip)
-{
-	chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK);
-	writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET);
-	writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR);
-}
-
-static int jz4740_gpio_suspend(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++)
-		jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]);
-
-	return 0;
-}
-
-static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip)
+static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
 {
-	uint32_t mask = chip->suspend_mask;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
 
-	writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR);
-	writel(mask, chip->base + JZ_REG_GPIO_MASK_SET);
-}
+	chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
 
-static void jz4740_gpio_resume(void)
-{
-	int i;
+	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
+	irq_set_handler_data(chip->irq, chip);
+	irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
 
-	for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--)
-		jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]);
-}
+	gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base,
+		chip->base, handle_level_irq);
 
-static struct syscore_ops jz4740_gpio_syscore_ops = {
-	.suspend = jz4740_gpio_suspend,
-	.resume = jz4740_gpio_resume,
-};
+	gc->wake_enabled = IRQ_MSK(chip->gpio_chip.ngpio);
+	gc->private = chip;
 
-static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
-{
-	int irq;
+	ct = gc->chip_types;
+	ct->regs.enable = JZ_REG_GPIO_MASK_CLEAR;
+	ct->regs.disable = JZ_REG_GPIO_MASK_SET;
+	ct->regs.ack = JZ_REG_GPIO_FLAG_CLEAR;
 
-	spin_lock_init(&chip->lock);
+	ct->chip.name = "GPIO";
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = jz_gpio_irq_unmask;
+	ct->chip.irq_ack = irq_gc_ack_set_bit;
+	ct->chip.irq_suspend = jz4740_irq_suspend;
+	ct->chip.irq_resume = jz4740_irq_resume;
+	ct->chip.irq_startup = jz_gpio_irq_startup;
+	ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
+	ct->chip.irq_set_type = jz_gpio_irq_set_type;
+	ct->chip.irq_set_wake = jz_gpio_irq_set_wake;
+	ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
 
-	chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
+	irq_setup_generic_chip(gc, IRQ_MSK(chip->gpio_chip.ngpio),
+		IRQ_GC_INIT_NESTED_LOCK, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	gpiochip_add(&chip->gpio_chip);
-
-	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
-	irq_set_handler_data(chip->irq, chip);
-	irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
-
-	for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
-		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_data(irq, chip);
-		irq_set_chip_and_handler(irq, &jz_gpio_irq_chip,
-					 handle_level_irq);
-	}
 }
 
 static int __init jz4740_gpio_init(void)
@@ -525,8 +463,6 @@ static int __init jz4740_gpio_init(void)
 	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i)
 		jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i);
 
-	register_syscore_ops(&jz4740_gpio_syscore_ops);
-
 	printk(KERN_INFO "JZ4740 GPIO initialized\n");
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/mips/jz4740/irq.c linux-libre-3.2-gnu1/arch/mips/jz4740/irq.c
--- linux-libre-3.1-gnu1/arch/mips/jz4740/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/jz4740/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,6 @@
 #include <asm/mach-jz4740/base.h>
 
 static void __iomem *jz_intc_base;
-static uint32_t jz_intc_wakeup;
-static uint32_t jz_intc_saved;
 
 #define JZ_REG_INTC_STATUS	0x00
 #define JZ_REG_INTC_MASK	0x04
@@ -41,51 +39,36 @@ static uint32_t jz_intc_saved;
 #define JZ_REG_INTC_CLEAR_MASK	0x0c
 #define JZ_REG_INTC_PENDING	0x10
 
-#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
-
-static inline unsigned long intc_irq_bit(struct irq_data *data)
+static irqreturn_t jz4740_cascade(int irq, void *data)
 {
-	return (unsigned long)irq_data_get_irq_chip_data(data);
-}
+	uint32_t irq_reg;
 
-static void intc_irq_unmask(struct irq_data *data)
-{
-	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-}
+	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
 
-static void intc_irq_mask(struct irq_data *data)
-{
-	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_SET_MASK);
+	if (irq_reg)
+		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+
+	return IRQ_HANDLED;
 }
 
-static int intc_irq_set_wake(struct irq_data *data, unsigned int on)
+static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 {
-	if (on)
-		jz_intc_wakeup |= intc_irq_bit(data);
-	else
-		jz_intc_wakeup &= ~intc_irq_bit(data);
+	struct irq_chip_regs *regs = &gc->chip_types->regs;
 
-	return 0;
+	writel(mask, gc->reg_base + regs->enable);
+	writel(~mask, gc->reg_base + regs->disable);
 }
 
-static struct irq_chip intc_irq_type = {
-	.name =		"INTC",
-	.irq_mask =	intc_irq_mask,
-	.irq_mask_ack =	intc_irq_mask,
-	.irq_unmask =	intc_irq_unmask,
-	.irq_set_wake =	intc_irq_set_wake,
-};
-
-static irqreturn_t jz4740_cascade(int irq, void *data)
+void jz4740_irq_suspend(struct irq_data *data)
 {
-	uint32_t irq_reg;
-
-	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
-
-	if (irq_reg)
-		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	jz4740_irq_set_mask(gc, gc->wake_active);
+}
 
-	return IRQ_HANDLED;
+void jz4740_irq_resume(struct irq_data *data)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	jz4740_irq_set_mask(gc, gc->mask_cache);
 }
 
 static struct irqaction jz4740_cascade_action = {
@@ -95,7 +78,9 @@ static struct irqaction jz4740_cascade_a
 
 void __init arch_init_irq(void)
 {
-	int i;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
 	mips_cpu_irq_init();
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
@@ -103,10 +88,22 @@ void __init arch_init_irq(void)
 	/* Mask all irqs */
 	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
 
-	for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
-		irq_set_chip_data(i, (void *)IRQ_BIT(i));
-		irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
-	}
+	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
+		handle_level_irq);
+
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
+	ct->regs.disable = JZ_REG_INTC_SET_MASK;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = jz4740_irq_suspend;
+	ct->chip.irq_resume = jz4740_irq_resume;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	setup_irq(2, &jz4740_cascade_action);
 }
@@ -122,19 +119,6 @@ asmlinkage void plat_irq_dispatch(void)
 		spurious_interrupt();
 }
 
-void jz4740_intc_suspend(void)
-{
-	jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
-	writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
-	writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-}
-
-void jz4740_intc_resume(void)
-{
-	writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-	writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
-}
-
 #ifdef CONFIG_DEBUG_FS
 
 static inline void intc_seq_reg(struct seq_file *s, const char *name,
diff -druNp linux-libre-3.1-gnu1/arch/mips/jz4740/irq.h linux-libre-3.2-gnu1/arch/mips/jz4740/irq.h
--- linux-libre-3.1-gnu1/arch/mips/jz4740/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/jz4740/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,9 @@
 #ifndef __MIPS_JZ4740_IRQ_H__
 #define __MIPS_JZ4740_IRQ_H__
 
-extern void jz4740_intc_suspend(void);
-extern void jz4740_intc_resume(void);
+#include <linux/irq.h>
+
+extern void jz4740_irq_suspend(struct irq_data *data);
+extern void jz4740_irq_resume(struct irq_data *data);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/mips/jz4740/pm.c linux-libre-3.2-gnu1/arch/mips/jz4740/pm.c
--- linux-libre-3.1-gnu1/arch/mips/jz4740/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/jz4740/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,11 +21,9 @@
 #include <asm/mach-jz4740/clock.h>
 
 #include "clock.h"
-#include "irq.h"
 
 static int jz4740_pm_enter(suspend_state_t state)
 {
-	jz4740_intc_suspend();
 	jz4740_clock_suspend();
 
 	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
@@ -37,7 +35,6 @@ static int jz4740_pm_enter(suspend_state
 	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
 
 	jz4740_clock_resume();
-	jz4740_intc_resume();
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/Kconfig linux-libre-3.2-gnu1/arch/mips/Kconfig
--- linux-libre-3.1-gnu1/arch/mips/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,8 @@ config MIPS_ALCHEMY
 	select GENERIC_GPIO
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
+	select USB_ARCH_HAS_OHCI
+	select USB_ARCH_HAS_EHCI
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -92,15 +94,8 @@ config BCM47XX
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select SSB
-	select SSB_DRIVER_MIPS
-	select SSB_DRIVER_EXTIF
-	select SSB_EMBEDDED
-	select SSB_B43_PCI_BRIDGE if PCI
-	select SSB_PCICORE_HOSTMODE if PCI
 	select GENERIC_GPIO
 	select SYS_HAS_EARLY_PRINTK
 	select CFE
@@ -213,6 +208,7 @@ config MACH_JZ4740
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_PWM
 	select HAVE_CLK
+	select GENERIC_IRQ_CHIP
 
 config LANTIQ
 	bool "Lantiq based platforms"
@@ -791,6 +787,7 @@ endchoice
 
 source "arch/mips/alchemy/Kconfig"
 source "arch/mips/ath79/Kconfig"
+source "arch/mips/bcm47xx/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
@@ -823,10 +820,6 @@ config ARCH_HAS_ILOG2_U64
 	bool
 	default n
 
-config ARCH_SUPPORTS_OPROFILE
-	bool
-	default y if !MIPS_MT_SMTC
-
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -2098,7 +2091,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && CPU_MIPS32
+	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON)
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
@@ -2258,16 +2251,6 @@ config HZ
 
 source "kernel/Kconfig.preempt"
 
-config MIPS_INSANE_LARGE
-	bool "Support for large 64-bit configurations"
-	depends on CPU_R10000 && 64BIT
-	help
-	  MIPS R10000 does support a 44 bit / 16TB address space as opposed to
-	  previous 64-bit processors which only supported 40 bit / 1TB. If you
-	  need processes of more than 1TB virtual address space, say Y here.
-	  This will result in additional memory usage, so it is not
-	  recommended for normal users.
-
 config KEXEC
 	bool "Kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/8250-platform.c linux-libre-3.2-gnu1/arch/mips/kernel/8250-platform.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/8250-platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/8250-platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
  */
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/serial_8250.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/cevt-r4k.c linux-libre-3.2-gnu1/arch/mips/kernel/cevt-r4k.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/cevt-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/cevt-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,19 +103,10 @@ static int c0_compare_int_pending(void)
 
 /*
  * Compare interrupt can be routed and latched outside the core,
- * so a single execution hazard barrier may not be enough to give
- * it time to clear as seen in the Cause register.  4 time the
- * pipeline depth seems reasonably conservative, and empirically
- * works better in configurations with high CPU/bus clock ratios.
+ * so wait up to worst case number of cycle counter ticks for timer interrupt
+ * changes to propagate to the cause register.
  */
-
-#define compare_change_hazard() \
-	do { \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-	} while (0)
+#define COMPARE_INT_SEEN_TICKS 50
 
 int c0_compare_int_usable(void)
 {
@@ -126,8 +117,12 @@ int c0_compare_int_usable(void)
 	 * IP7 already pending?  Try to clear it by acking the timer.
 	 */
 	if (c0_compare_int_pending()) {
-		write_c0_compare(read_c0_count());
-		compare_change_hazard();
+		cnt = read_c0_count();
+		write_c0_compare(cnt);
+		back_to_back_c0_hazard();
+		while (read_c0_count() < (cnt  + COMPARE_INT_SEEN_TICKS))
+			if (!c0_compare_int_pending())
+				break;
 		if (c0_compare_int_pending())
 			return 0;
 	}
@@ -136,7 +131,7 @@ int c0_compare_int_usable(void)
 		cnt = read_c0_count();
 		cnt += delta;
 		write_c0_compare(cnt);
-		compare_change_hazard();
+		back_to_back_c0_hazard();
 		if ((int)(read_c0_count() - cnt) < 0)
 		    break;
 		/* increase delta if the timer was already expired */
@@ -145,12 +140,17 @@ int c0_compare_int_usable(void)
 	while ((int)(read_c0_count() - cnt) <= 0)
 		;	/* Wait for expiry  */
 
-	compare_change_hazard();
+	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+		if (c0_compare_int_pending())
+			break;
 	if (!c0_compare_int_pending())
 		return 0;
-
-	write_c0_compare(read_c0_count());
-	compare_change_hazard();
+	cnt = read_c0_count();
+	write_c0_compare(cnt);
+	back_to_back_c0_hazard();
+	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+		if (!c0_compare_int_pending())
+			break;
 	if (c0_compare_int_pending())
 		return 0;
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/cpufreq/loongson2_clock.c linux-libre-3.2-gnu1/arch/mips/kernel/cpufreq/loongson2_clock.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/cpufreq/loongson2_clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/cpufreq/loongson2_clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/cpu-probe.c linux-libre-3.2-gnu1/arch/mips/kernel/cpu-probe.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/cpu-probe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/cpu-probe.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
@@ -24,6 +24,7 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 #include <asm/watch.h>
+#include <asm/elf.h>
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
@@ -978,7 +979,10 @@ static inline void cpu_probe_cavium(stru
 platform:
 		set_elf_platform(cpu, "octeon");
 		break;
+	case PRID_IMP_CAVIUM_CN61XX:
 	case PRID_IMP_CAVIUM_CN63XX:
+	case PRID_IMP_CAVIUM_CN66XX:
+	case PRID_IMP_CAVIUM_CN68XX:
 		c->cputype = CPU_CAVIUM_OCTEON2;
 		__cpu_name[cpu] = "Cavium Octeon II";
 		set_elf_platform(cpu, "octeon2");
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/i8253.c linux-libre-3.2-gnu1/arch/mips/kernel/i8253.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/i8253.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/i8253.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 #include <linux/clockchips.h>
 #include <linux/i8253.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/smp.h>
 #include <linux/irq.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/init_task.c linux-libre-3.2-gnu1/arch/mips/kernel/init_task.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/init_task.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/irq.c linux-libre-3.2-gnu1/arch/mips/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/random.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/irq-msc01.c linux-libre-3.2-gnu1/arch/mips/kernel/irq-msc01.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/irq-msc01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/irq-msc01.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *
  * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
  */
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/Makefile linux-libre-3.2-gnu1/arch/mips/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/mips/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@ obj-y		+= cpu-probe.o branch.o entry.o g
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
+CFLAGS_REMOVE_perf_event.o = -pg
+CFLAGS_REMOVE_perf_event_mipsxx.o = -pg
 endif
 
 obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
@@ -106,7 +108,8 @@ obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+=
 
 obj-$(CONFIG_MIPS_CPUFREQ)	+= cpufreq/
 
-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_mipsxx.o
 
 obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/mips_ksyms.c linux-libre-3.2-gnu1/arch/mips/kernel/mips_ksyms.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/mips_ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/mips_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
  */
 #include <linux/interrupt.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/mips-mt.c linux-libre-3.2-gnu1/arch/mips/kernel/mips-mt.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/mips-mt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/mips-mt.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/security.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/module.c linux-libre-3.2-gnu1/arch/mips/kernel/module.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/jump_label.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/perf_event.c linux-libre-3.2-gnu1/arch/mips/kernel/perf_event.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,533 +14,16 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
 #include <linux/perf_event.h>
-#include <linux/uaccess.h>
 
-#include <asm/irq.h>
-#include <asm/irq_regs.h>
 #include <asm/stacktrace.h>
-#include <asm/time.h> /* For perf_irq */
-
-/* These are for 32bit counters. For 64bit ones, define them accordingly. */
-#define MAX_PERIOD	((1ULL << 32) - 1)
-#define VALID_COUNT	0x7fffffff
-#define TOTAL_BITS	32
-#define HIGHEST_BIT	31
-
-#define MIPS_MAX_HWEVENTS 4
-
-struct cpu_hw_events {
-	/* Array of events on this cpu. */
-	struct perf_event	*events[MIPS_MAX_HWEVENTS];
-
-	/*
-	 * Set the bit (indexed by the counter number) when the counter
-	 * is used for an event.
-	 */
-	unsigned long		used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
-
-	/*
-	 * The borrowed MSB for the performance counter. A MIPS performance
-	 * counter uses its bit 31 (for 32bit counters) or bit 63 (for 64bit
-	 * counters) as a factor of determining whether a counter overflow
-	 * should be signaled. So here we use a separate MSB for each
-	 * counter to make things easy.
-	 */
-	unsigned long		msbs[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
-
-	/*
-	 * Software copy of the control register for each performance counter.
-	 * MIPS CPUs vary in performance counters. They use this differently,
-	 * and even may not use it.
-	 */
-	unsigned int		saved_ctrl[MIPS_MAX_HWEVENTS];
-};
-DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
-	.saved_ctrl = {0},
-};
-
-/* The description of MIPS performance events. */
-struct mips_perf_event {
-	unsigned int event_id;
-	/*
-	 * MIPS performance counters are indexed starting from 0.
-	 * CNTR_EVEN indicates the indexes of the counters to be used are
-	 * even numbers.
-	 */
-	unsigned int cntr_mask;
-	#define CNTR_EVEN	0x55555555
-	#define CNTR_ODD	0xaaaaaaaa
-#ifdef CONFIG_MIPS_MT_SMP
-	enum {
-		T  = 0,
-		V  = 1,
-		P  = 2,
-	} range;
-#else
-	#define T
-	#define V
-	#define P
-#endif
-};
-
-static struct mips_perf_event raw_event;
-static DEFINE_MUTEX(raw_event_mutex);
-
-#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-struct mips_pmu {
-	const char	*name;
-	int		irq;
-	irqreturn_t	(*handle_irq)(int irq, void *dev);
-	int		(*handle_shared_irq)(void);
-	void		(*start)(void);
-	void		(*stop)(void);
-	int		(*alloc_counter)(struct cpu_hw_events *cpuc,
-					struct hw_perf_event *hwc);
-	u64		(*read_counter)(unsigned int idx);
-	void		(*write_counter)(unsigned int idx, u64 val);
-	void		(*enable_event)(struct hw_perf_event *evt, int idx);
-	void		(*disable_event)(int idx);
-	const struct mips_perf_event *(*map_raw_event)(u64 config);
-	const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX];
-	const struct mips_perf_event (*cache_event_map)
-				[PERF_COUNT_HW_CACHE_MAX]
-				[PERF_COUNT_HW_CACHE_OP_MAX]
-				[PERF_COUNT_HW_CACHE_RESULT_MAX];
-	unsigned int	num_counters;
-};
-
-static const struct mips_pmu *mipspmu;
-
-static int
-mipspmu_event_set_period(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	s64 left = local64_read(&hwc->period_left);
-	s64 period = hwc->sample_period;
-	int ret = 0;
-	u64 uleft;
-	unsigned long flags;
-
-	if (unlikely(left <= -period)) {
-		left = period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (unlikely(left <= 0)) {
-		left += period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (left > (s64)MAX_PERIOD)
-		left = MAX_PERIOD;
-
-	local64_set(&hwc->prev_count, (u64)-left);
-
-	local_irq_save(flags);
-	uleft = (u64)(-left) & MAX_PERIOD;
-	uleft > VALID_COUNT ?
-		set_bit(idx, cpuc->msbs) : clear_bit(idx, cpuc->msbs);
-	mipspmu->write_counter(idx, (u64)(-left) & VALID_COUNT);
-	local_irq_restore(flags);
-
-	perf_event_update_userpage(event);
-
-	return ret;
-}
-
-static void mipspmu_event_update(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-	int shift = 64 - TOTAL_BITS;
-	s64 prev_raw_count, new_raw_count;
-	u64 delta;
-
-again:
-	prev_raw_count = local64_read(&hwc->prev_count);
-	local_irq_save(flags);
-	/* Make the counter value be a "real" one. */
-	new_raw_count = mipspmu->read_counter(idx);
-	if (new_raw_count & (test_bit(idx, cpuc->msbs) << HIGHEST_BIT)) {
-		new_raw_count &= VALID_COUNT;
-		clear_bit(idx, cpuc->msbs);
-	} else
-		new_raw_count |= (test_bit(idx, cpuc->msbs) << HIGHEST_BIT);
-	local_irq_restore(flags);
-
-	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-				new_raw_count) != prev_raw_count)
-		goto again;
-
-	delta = (new_raw_count << shift) - (prev_raw_count << shift);
-	delta >>= shift;
-
-	local64_add(delta, &event->count);
-	local64_sub(delta, &hwc->period_left);
-}
-
-static void mipspmu_start(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	if (!mipspmu)
-		return;
-
-	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-
-	hwc->state = 0;
-
-	/* Set the period for the event. */
-	mipspmu_event_set_period(event, hwc, hwc->idx);
-
-	/* Enable the event. */
-	mipspmu->enable_event(hwc, hwc->idx);
-}
-
-static void mipspmu_stop(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	if (!mipspmu)
-		return;
-
-	if (!(hwc->state & PERF_HES_STOPPED)) {
-		/* We are working on a local event. */
-		mipspmu->disable_event(hwc->idx);
-		barrier();
-		mipspmu_event_update(event, hwc, hwc->idx);
-		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	}
-}
-
-static int mipspmu_add(struct perf_event *event, int flags)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx;
-	int err = 0;
-
-	perf_pmu_disable(event->pmu);
-
-	/* To look for a free counter for this event. */
-	idx = mipspmu->alloc_counter(cpuc, hwc);
-	if (idx < 0) {
-		err = idx;
-		goto out;
-	}
-
-	/*
-	 * If there is an event in the counter we are going to use then
-	 * make sure it is disabled.
-	 */
-	event->hw.idx = idx;
-	mipspmu->disable_event(idx);
-	cpuc->events[idx] = event;
-
-	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	if (flags & PERF_EF_START)
-		mipspmu_start(event, PERF_EF_RELOAD);
-
-	/* Propagate our changes to the userspace mapping. */
-	perf_event_update_userpage(event);
-
-out:
-	perf_pmu_enable(event->pmu);
-	return err;
-}
-
-static void mipspmu_del(struct perf_event *event, int flags)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	mipspmu_stop(event, PERF_EF_UPDATE);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
-
-	perf_event_update_userpage(event);
-}
-
-static void mipspmu_read(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	/* Don't read disabled counters! */
-	if (hwc->idx < 0)
-		return;
-
-	mipspmu_event_update(event, hwc, hwc->idx);
-}
-
-static void mipspmu_enable(struct pmu *pmu)
-{
-	if (mipspmu)
-		mipspmu->start();
-}
-
-static void mipspmu_disable(struct pmu *pmu)
-{
-	if (mipspmu)
-		mipspmu->stop();
-}
-
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-static int (*save_perf_irq)(void);
-
-static int mipspmu_get_irq(void)
-{
-	int err;
-
-	if (mipspmu->irq >= 0) {
-		/* Request my own irq handler. */
-		err = request_irq(mipspmu->irq, mipspmu->handle_irq,
-			IRQF_DISABLED | IRQF_NOBALANCING,
-			"mips_perf_pmu", NULL);
-		if (err) {
-			pr_warning("Unable to request IRQ%d for MIPS "
-			   "performance counters!\n", mipspmu->irq);
-		}
-	} else if (cp0_perfcount_irq < 0) {
-		/*
-		 * We are sharing the irq number with the timer interrupt.
-		 */
-		save_perf_irq = perf_irq;
-		perf_irq = mipspmu->handle_shared_irq;
-		err = 0;
-	} else {
-		pr_warning("The platform hasn't properly defined its "
-			"interrupt controller.\n");
-		err = -ENOENT;
-	}
-
-	return err;
-}
-
-static void mipspmu_free_irq(void)
-{
-	if (mipspmu->irq >= 0)
-		free_irq(mipspmu->irq, NULL);
-	else if (cp0_perfcount_irq < 0)
-		perf_irq = save_perf_irq;
-}
-
-/*
- * mipsxx/rm9000/loongson2 have different performance counters, they have
- * specific low-level init routines.
- */
-static void reset_counters(void *arg);
-static int __hw_perf_event_init(struct perf_event *event);
-
-static void hw_perf_event_destroy(struct perf_event *event)
-{
-	if (atomic_dec_and_mutex_lock(&active_events,
-				&pmu_reserve_mutex)) {
-		/*
-		 * We must not call the destroy function with interrupts
-		 * disabled.
-		 */
-		on_each_cpu(reset_counters,
-			(void *)(long)mipspmu->num_counters, 1);
-		mipspmu_free_irq();
-		mutex_unlock(&pmu_reserve_mutex);
-	}
-}
-
-static int mipspmu_event_init(struct perf_event *event)
-{
-	int err = 0;
-
-	switch (event->attr.type) {
-	case PERF_TYPE_RAW:
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-		break;
-
-	default:
-		return -ENOENT;
-	}
-
-	if (!mipspmu || event->cpu >= nr_cpumask_bits ||
-		(event->cpu >= 0 && !cpu_online(event->cpu)))
-		return -ENODEV;
-
-	if (!atomic_inc_not_zero(&active_events)) {
-		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
-			atomic_dec(&active_events);
-			return -ENOSPC;
-		}
-
-		mutex_lock(&pmu_reserve_mutex);
-		if (atomic_read(&active_events) == 0)
-			err = mipspmu_get_irq();
-
-		if (!err)
-			atomic_inc(&active_events);
-		mutex_unlock(&pmu_reserve_mutex);
-	}
-
-	if (err)
-		return err;
-
-	err = __hw_perf_event_init(event);
-	if (err)
-		hw_perf_event_destroy(event);
-
-	return err;
-}
-
-static struct pmu pmu = {
-	.pmu_enable	= mipspmu_enable,
-	.pmu_disable	= mipspmu_disable,
-	.event_init	= mipspmu_event_init,
-	.add		= mipspmu_add,
-	.del		= mipspmu_del,
-	.start		= mipspmu_start,
-	.stop		= mipspmu_stop,
-	.read		= mipspmu_read,
-};
-
-static inline unsigned int
-mipspmu_perf_event_encode(const struct mips_perf_event *pev)
-{
-/*
- * Top 8 bits for range, next 16 bits for cntr_mask, lowest 8 bits for
- * event_id.
- */
-#ifdef CONFIG_MIPS_MT_SMP
-	return ((unsigned int)pev->range << 24) |
-		(pev->cntr_mask & 0xffff00) |
-		(pev->event_id & 0xff);
-#else
-	return (pev->cntr_mask & 0xffff00) |
-		(pev->event_id & 0xff);
-#endif
-}
-
-static const struct mips_perf_event *
-mipspmu_map_general_event(int idx)
-{
-	const struct mips_perf_event *pev;
-
-	pev = ((*mipspmu->general_event_map)[idx].event_id ==
-		UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
-		&(*mipspmu->general_event_map)[idx]);
-
-	return pev;
-}
-
-static const struct mips_perf_event *
-mipspmu_map_cache_event(u64 config)
-{
-	unsigned int cache_type, cache_op, cache_result;
-	const struct mips_perf_event *pev;
-
-	cache_type = (config >> 0) & 0xff;
-	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
-		return ERR_PTR(-EINVAL);
-
-	cache_op = (config >> 8) & 0xff;
-	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
-		return ERR_PTR(-EINVAL);
-
-	cache_result = (config >> 16) & 0xff;
-	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
-		return ERR_PTR(-EINVAL);
-
-	pev = &((*mipspmu->cache_event_map)
-					[cache_type]
-					[cache_op]
-					[cache_result]);
-
-	if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID)
-		return ERR_PTR(-EOPNOTSUPP);
-
-	return pev;
-
-}
-
-static int validate_event(struct cpu_hw_events *cpuc,
-	       struct perf_event *event)
-{
-	struct hw_perf_event fake_hwc = event->hw;
-
-	/* Allow mixed event group. So return 1 to pass validation. */
-	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
-		return 1;
-
-	return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0;
-}
-
-static int validate_group(struct perf_event *event)
-{
-	struct perf_event *sibling, *leader = event->group_leader;
-	struct cpu_hw_events fake_cpuc;
-
-	memset(&fake_cpuc, 0, sizeof(fake_cpuc));
-
-	if (!validate_event(&fake_cpuc, leader))
-		return -ENOSPC;
-
-	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
-		if (!validate_event(&fake_cpuc, sibling))
-			return -ENOSPC;
-	}
-
-	if (!validate_event(&fake_cpuc, event))
-		return -ENOSPC;
-
-	return 0;
-}
-
-/* This is needed by specific irq handlers in perf_event_*.c */
-static void
-handle_associated_event(struct cpu_hw_events *cpuc,
-	int idx, struct perf_sample_data *data, struct pt_regs *regs)
-{
-	struct perf_event *event = cpuc->events[idx];
-	struct hw_perf_event *hwc = &event->hw;
-
-	mipspmu_event_update(event, hwc, idx);
-	data->period = event->hw.last_period;
-	if (!mipspmu_event_set_period(event, hwc, idx))
-		return;
-
-	if (perf_event_overflow(event, data, regs))
-		mipspmu->disable_event(idx);
-}
-
-#include "perf_event_mipsxx.c"
 
 /* Callchain handling code. */
 
 /*
  * Leave userspace callchain empty for now. When we find a way to trace
- * the user stack callchains, we add here.
+ * the user stack callchains, we will add it here.
  */
-void perf_callchain_user(struct perf_callchain_entry *entry,
-		    struct pt_regs *regs)
-{
-}
 
 static void save_raw_perf_callchain(struct perf_callchain_entry *entry,
 	unsigned long reg29)
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/perf_event_mipsxx.c linux-libre-3.2-gnu1/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/perf_event_mipsxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/perf_event_mipsxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,13 +1,112 @@
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) || \
-    defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_SB1)
+/*
+ * Linux performance counter support for MIPS.
+ *
+ * Copyright (C) 2010 MIPS Technologies, Inc.
+ * Copyright (C) 2011 Cavium Networks, Inc.
+ * Author: Deng-Cheng Zhu
+ *
+ * This code is based on the implementation for ARM, which is in turn
+ * based on the sparc64 perf event code and the x86 code. Performance
+ * counter access is based on the MIPS Oprofile code. And the callchain
+ * support references the code of MIPS stacktrace.c.
+ *
+ * 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/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/uaccess.h>
+
+#include <asm/irq.h>
+#include <asm/irq_regs.h>
+#include <asm/stacktrace.h>
+#include <asm/time.h> /* For perf_irq */
+
+#define MIPS_MAX_HWEVENTS 4
+
+struct cpu_hw_events {
+	/* Array of events on this cpu. */
+	struct perf_event	*events[MIPS_MAX_HWEVENTS];
+
+	/*
+	 * Set the bit (indexed by the counter number) when the counter
+	 * is used for an event.
+	 */
+	unsigned long		used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
+
+	/*
+	 * Software copy of the control register for each performance counter.
+	 * MIPS CPUs vary in performance counters. They use this differently,
+	 * and even may not use it.
+	 */
+	unsigned int		saved_ctrl[MIPS_MAX_HWEVENTS];
+};
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+	.saved_ctrl = {0},
+};
+
+/* The description of MIPS performance events. */
+struct mips_perf_event {
+	unsigned int event_id;
+	/*
+	 * MIPS performance counters are indexed starting from 0.
+	 * CNTR_EVEN indicates the indexes of the counters to be used are
+	 * even numbers.
+	 */
+	unsigned int cntr_mask;
+	#define CNTR_EVEN	0x55555555
+	#define CNTR_ODD	0xaaaaaaaa
+	#define CNTR_ALL	0xffffffff
+#ifdef CONFIG_MIPS_MT_SMP
+	enum {
+		T  = 0,
+		V  = 1,
+		P  = 2,
+	} range;
+#else
+	#define T
+	#define V
+	#define P
+#endif
+};
+
+static struct mips_perf_event raw_event;
+static DEFINE_MUTEX(raw_event_mutex);
+
+#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+struct mips_pmu {
+	u64		max_period;
+	u64		valid_count;
+	u64		overflow;
+	const char	*name;
+	int		irq;
+	u64		(*read_counter)(unsigned int idx);
+	void		(*write_counter)(unsigned int idx, u64 val);
+	const struct mips_perf_event *(*map_raw_event)(u64 config);
+	const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX];
+	const struct mips_perf_event (*cache_event_map)
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+	unsigned int	num_counters;
+};
+
+static struct mips_pmu mipspmu;
 
 #define M_CONFIG1_PC	(1 << 4)
 
-#define M_PERFCTL_EXL			(1UL      <<  0)
-#define M_PERFCTL_KERNEL		(1UL      <<  1)
-#define M_PERFCTL_SUPERVISOR		(1UL      <<  2)
-#define M_PERFCTL_USER			(1UL      <<  3)
-#define M_PERFCTL_INTERRUPT_ENABLE	(1UL      <<  4)
+#define M_PERFCTL_EXL			(1      <<  0)
+#define M_PERFCTL_KERNEL		(1      <<  1)
+#define M_PERFCTL_SUPERVISOR		(1      <<  2)
+#define M_PERFCTL_USER			(1      <<  3)
+#define M_PERFCTL_INTERRUPT_ENABLE	(1      <<  4)
 #define M_PERFCTL_EVENT(event)		(((event) & 0x3ff)  << 5)
 #define M_PERFCTL_VPEID(vpe)		((vpe)    << 16)
 #define M_PERFCTL_MT_EN(filter)		((filter) << 20)
@@ -15,8 +114,8 @@
 #define    M_TC_EN_VPE			M_PERFCTL_MT_EN(1)
 #define    M_TC_EN_TC			M_PERFCTL_MT_EN(2)
 #define M_PERFCTL_TCID(tcid)		((tcid)   << 22)
-#define M_PERFCTL_WIDE			(1UL      << 30)
-#define M_PERFCTL_MORE			(1UL      << 31)
+#define M_PERFCTL_WIDE			(1      << 30)
+#define M_PERFCTL_MORE			(1      << 31)
 
 #define M_PERFCTL_COUNT_EVENT_WHENEVER	(M_PERFCTL_EXL |		\
 					M_PERFCTL_KERNEL |		\
@@ -31,11 +130,12 @@
 #endif
 #define M_PERFCTL_EVENT_MASK		0xfe0
 
-#define M_COUNTER_OVERFLOW		(1UL      << 31)
 
 #ifdef CONFIG_MIPS_MT_SMP
 static int cpu_has_mipsmt_pertccounters;
 
+static DEFINE_RWLOCK(pmuint_rwlock);
+
 /*
  * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
  * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
@@ -49,209 +149,673 @@ static int cpu_has_mipsmt_pertccounters;
 #endif
 
 /* Copied from op_model_mipsxx.c */
-static inline unsigned int vpe_shift(void)
+static unsigned int vpe_shift(void)
 {
 	if (num_possible_cpus() > 1)
 		return 1;
 
 	return 0;
 }
-#else /* !CONFIG_MIPS_MT_SMP */
-#define vpe_id()	0
 
-static inline unsigned int vpe_shift(void)
-{
-	return 0;
-}
-#endif /* CONFIG_MIPS_MT_SMP */
-
-static inline unsigned int
-counters_total_to_per_cpu(unsigned int counters)
+static unsigned int counters_total_to_per_cpu(unsigned int counters)
 {
 	return counters >> vpe_shift();
 }
 
-static inline unsigned int
-counters_per_cpu_to_total(unsigned int counters)
+static unsigned int counters_per_cpu_to_total(unsigned int counters)
 {
 	return counters << vpe_shift();
 }
 
-#define __define_perf_accessors(r, n, np)				\
-									\
-static inline unsigned int r_c0_ ## r ## n(void)			\
-{									\
-	unsigned int cpu = vpe_id();					\
-									\
-	switch (cpu) {							\
-	case 0:								\
-		return read_c0_ ## r ## n();				\
-	case 1:								\
-		return read_c0_ ## r ## np();				\
-	default:							\
-		BUG();							\
-	}								\
-	return 0;							\
-}									\
-									\
-static inline void w_c0_ ## r ## n(unsigned int value)			\
-{									\
-	unsigned int cpu = vpe_id();					\
-									\
-	switch (cpu) {							\
-	case 0:								\
-		write_c0_ ## r ## n(value);				\
-		return;							\
-	case 1:								\
-		write_c0_ ## r ## np(value);				\
-		return;							\
-	default:							\
-		BUG();							\
-	}								\
-	return;								\
-}									\
+#else /* !CONFIG_MIPS_MT_SMP */
+#define vpe_id()	0
 
-__define_perf_accessors(perfcntr, 0, 2)
-__define_perf_accessors(perfcntr, 1, 3)
-__define_perf_accessors(perfcntr, 2, 0)
-__define_perf_accessors(perfcntr, 3, 1)
+#endif /* CONFIG_MIPS_MT_SMP */
 
-__define_perf_accessors(perfctrl, 0, 2)
-__define_perf_accessors(perfctrl, 1, 3)
-__define_perf_accessors(perfctrl, 2, 0)
-__define_perf_accessors(perfctrl, 3, 1)
+static void resume_local_counters(void);
+static void pause_local_counters(void);
+static irqreturn_t mipsxx_pmu_handle_irq(int, void *);
+static int mipsxx_pmu_handle_shared_irq(void);
 
-static inline int __n_counters(void)
+static unsigned int mipsxx_pmu_swizzle_perf_idx(unsigned int idx)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
-		return 0;
-	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
-		return 1;
-	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
-		return 2;
-	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
-		return 3;
-
-	return 4;
+	if (vpe_id() == 1)
+		idx = (idx + 2) & 3;
+	return idx;
 }
 
-static inline int n_counters(void)
+static u64 mipsxx_pmu_read_counter(unsigned int idx)
 {
-	int counters;
-
-	switch (current_cpu_type()) {
-	case CPU_R10000:
-		counters = 2;
-		break;
-
-	case CPU_R12000:
-	case CPU_R14000:
-		counters = 4;
-		break;
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
 
+	switch (idx) {
+	case 0:
+		/*
+		 * The counters are unsigned, we must cast to truncate
+		 * off the high bits.
+		 */
+		return (u32)read_c0_perfcntr0();
+	case 1:
+		return (u32)read_c0_perfcntr1();
+	case 2:
+		return (u32)read_c0_perfcntr2();
+	case 3:
+		return (u32)read_c0_perfcntr3();
 	default:
-		counters = __n_counters();
+		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+		return 0;
 	}
-
-	return counters;
 }
 
-static void reset_counters(void *arg)
+static u64 mipsxx_pmu_read_counter_64(unsigned int idx)
 {
-	int counters = (int)(long)arg;
-	switch (counters) {
-	case 4:
-		w_c0_perfctrl3(0);
-		w_c0_perfcntr3(0);
-	case 3:
-		w_c0_perfctrl2(0);
-		w_c0_perfcntr2(0);
-	case 2:
-		w_c0_perfctrl1(0);
-		w_c0_perfcntr1(0);
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+	switch (idx) {
+	case 0:
+		return read_c0_perfcntr0_64();
 	case 1:
-		w_c0_perfctrl0(0);
-		w_c0_perfcntr0(0);
+		return read_c0_perfcntr1_64();
+	case 2:
+		return read_c0_perfcntr2_64();
+	case 3:
+		return read_c0_perfcntr3_64();
+	default:
+		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+		return 0;
 	}
 }
 
-static inline u64
-mipsxx_pmu_read_counter(unsigned int idx)
+static void mipsxx_pmu_write_counter(unsigned int idx, u64 val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		return r_c0_perfcntr0();
+		write_c0_perfcntr0(val);
+		return;
 	case 1:
-		return r_c0_perfcntr1();
+		write_c0_perfcntr1(val);
+		return;
 	case 2:
-		return r_c0_perfcntr2();
+		write_c0_perfcntr2(val);
+		return;
 	case 3:
-		return r_c0_perfcntr3();
-	default:
-		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
-		return 0;
+		write_c0_perfcntr3(val);
+		return;
 	}
 }
 
-static inline void
-mipsxx_pmu_write_counter(unsigned int idx, u64 val)
+static void mipsxx_pmu_write_counter_64(unsigned int idx, u64 val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		w_c0_perfcntr0(val);
+		write_c0_perfcntr0_64(val);
 		return;
 	case 1:
-		w_c0_perfcntr1(val);
+		write_c0_perfcntr1_64(val);
 		return;
 	case 2:
-		w_c0_perfcntr2(val);
+		write_c0_perfcntr2_64(val);
 		return;
 	case 3:
-		w_c0_perfcntr3(val);
+		write_c0_perfcntr3_64(val);
 		return;
 	}
 }
 
-static inline unsigned int
-mipsxx_pmu_read_control(unsigned int idx)
+static unsigned int mipsxx_pmu_read_control(unsigned int idx)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		return r_c0_perfctrl0();
+		return read_c0_perfctrl0();
 	case 1:
-		return r_c0_perfctrl1();
+		return read_c0_perfctrl1();
 	case 2:
-		return r_c0_perfctrl2();
+		return read_c0_perfctrl2();
 	case 3:
-		return r_c0_perfctrl3();
+		return read_c0_perfctrl3();
 	default:
 		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
 		return 0;
 	}
 }
 
-static inline void
-mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
+static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		w_c0_perfctrl0(val);
+		write_c0_perfctrl0(val);
 		return;
 	case 1:
-		w_c0_perfctrl1(val);
+		write_c0_perfctrl1(val);
 		return;
 	case 2:
-		w_c0_perfctrl2(val);
+		write_c0_perfctrl2(val);
 		return;
 	case 3:
-		w_c0_perfctrl3(val);
+		write_c0_perfctrl3(val);
 		return;
 	}
 }
 
+static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
+				    struct hw_perf_event *hwc)
+{
+	int i;
+
+	/*
+	 * We only need to care the counter mask. The range has been
+	 * checked definitely.
+	 */
+	unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
+
+	for (i = mipspmu.num_counters - 1; i >= 0; i--) {
+		/*
+		 * Note that some MIPS perf events can be counted by both
+		 * even and odd counters, wheresas many other are only by
+		 * even _or_ odd counters. This introduces an issue that
+		 * when the former kind of event takes the counter the
+		 * latter kind of event wants to use, then the "counter
+		 * allocation" for the latter event will fail. In fact if
+		 * they can be dynamically swapped, they both feel happy.
+		 * But here we leave this issue alone for now.
+		 */
+		if (test_bit(i, &cntr_mask) &&
+			!test_and_set_bit(i, cpuc->used_mask))
+			return i;
+	}
+
+	return -EAGAIN;
+}
+
+static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
+		(evt->config_base & M_PERFCTL_CONFIG_MASK) |
+		/* Make sure interrupt enabled. */
+		M_PERFCTL_INTERRUPT_ENABLE;
+	/*
+	 * We do not actually let the counter run. Leave it until start().
+	 */
+}
+
+static void mipsxx_pmu_disable_event(int idx)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	unsigned long flags;
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	local_irq_save(flags);
+	cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
+		~M_PERFCTL_COUNT_EVENT_WHENEVER;
+	mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
+	local_irq_restore(flags);
+}
+
+static int mipspmu_event_set_period(struct perf_event *event,
+				    struct hw_perf_event *hwc,
+				    int idx)
+{
+	u64 left = local64_read(&hwc->period_left);
+	u64 period = hwc->sample_period;
+	int ret = 0;
+
+	if (unlikely((left + period) & (1ULL << 63))) {
+		/* left underflowed by more than period. */
+		left = period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	} else	if (unlikely((left + period) <= period)) {
+		/* left underflowed by less than period. */
+		left += period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (left > mipspmu.max_period) {
+		left = mipspmu.max_period;
+		local64_set(&hwc->period_left, left);
+	}
+
+	local64_set(&hwc->prev_count, mipspmu.overflow - left);
+
+	mipspmu.write_counter(idx, mipspmu.overflow - left);
+
+	perf_event_update_userpage(event);
+
+	return ret;
+}
+
+static void mipspmu_event_update(struct perf_event *event,
+				 struct hw_perf_event *hwc,
+				 int idx)
+{
+	u64 prev_raw_count, new_raw_count;
+	u64 delta;
+
+again:
+	prev_raw_count = local64_read(&hwc->prev_count);
+	new_raw_count = mipspmu.read_counter(idx);
+
+	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+				new_raw_count) != prev_raw_count)
+		goto again;
+
+	delta = new_raw_count - prev_raw_count;
+
+	local64_add(delta, &event->count);
+	local64_sub(delta, &hwc->period_left);
+}
+
+static void mipspmu_start(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+	hwc->state = 0;
+
+	/* Set the period for the event. */
+	mipspmu_event_set_period(event, hwc, hwc->idx);
+
+	/* Enable the event. */
+	mipsxx_pmu_enable_event(hwc, hwc->idx);
+}
+
+static void mipspmu_stop(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		/* We are working on a local event. */
+		mipsxx_pmu_disable_event(hwc->idx);
+		barrier();
+		mipspmu_event_update(event, hwc, hwc->idx);
+		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	}
+}
+
+static int mipspmu_add(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx;
+	int err = 0;
+
+	perf_pmu_disable(event->pmu);
+
+	/* To look for a free counter for this event. */
+	idx = mipsxx_pmu_alloc_counter(cpuc, hwc);
+	if (idx < 0) {
+		err = idx;
+		goto out;
+	}
+
+	/*
+	 * If there is an event in the counter we are going to use then
+	 * make sure it is disabled.
+	 */
+	event->hw.idx = idx;
+	mipsxx_pmu_disable_event(idx);
+	cpuc->events[idx] = event;
+
+	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	if (flags & PERF_EF_START)
+		mipspmu_start(event, PERF_EF_RELOAD);
+
+	/* Propagate our changes to the userspace mapping. */
+	perf_event_update_userpage(event);
+
+out:
+	perf_pmu_enable(event->pmu);
+	return err;
+}
+
+static void mipspmu_del(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	mipspmu_stop(event, PERF_EF_UPDATE);
+	cpuc->events[idx] = NULL;
+	clear_bit(idx, cpuc->used_mask);
+
+	perf_event_update_userpage(event);
+}
+
+static void mipspmu_read(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	/* Don't read disabled counters! */
+	if (hwc->idx < 0)
+		return;
+
+	mipspmu_event_update(event, hwc, hwc->idx);
+}
+
+static void mipspmu_enable(struct pmu *pmu)
+{
 #ifdef CONFIG_MIPS_MT_SMP
-static DEFINE_RWLOCK(pmuint_rwlock);
+	write_unlock(&pmuint_rwlock);
+#endif
+	resume_local_counters();
+}
+
+/*
+ * MIPS performance counters can be per-TC. The control registers can
+ * not be directly accessed accross CPUs. Hence if we want to do global
+ * control, we need cross CPU calls. on_each_cpu() can help us, but we
+ * can not make sure this function is called with interrupts enabled. So
+ * here we pause local counters and then grab a rwlock and leave the
+ * counters on other CPUs alone. If any counter interrupt raises while
+ * we own the write lock, simply pause local counters on that CPU and
+ * spin in the handler. Also we know we won't be switched to another
+ * CPU after pausing local counters and before grabbing the lock.
+ */
+static void mipspmu_disable(struct pmu *pmu)
+{
+	pause_local_counters();
+#ifdef CONFIG_MIPS_MT_SMP
+	write_lock(&pmuint_rwlock);
 #endif
+}
+
+static atomic_t active_events = ATOMIC_INIT(0);
+static DEFINE_MUTEX(pmu_reserve_mutex);
+static int (*save_perf_irq)(void);
+
+static int mipspmu_get_irq(void)
+{
+	int err;
+
+	if (mipspmu.irq >= 0) {
+		/* Request my own irq handler. */
+		err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq,
+			IRQF_PERCPU | IRQF_NOBALANCING,
+			"mips_perf_pmu", NULL);
+		if (err) {
+			pr_warning("Unable to request IRQ%d for MIPS "
+			   "performance counters!\n", mipspmu.irq);
+		}
+	} else if (cp0_perfcount_irq < 0) {
+		/*
+		 * We are sharing the irq number with the timer interrupt.
+		 */
+		save_perf_irq = perf_irq;
+		perf_irq = mipsxx_pmu_handle_shared_irq;
+		err = 0;
+	} else {
+		pr_warning("The platform hasn't properly defined its "
+			"interrupt controller.\n");
+		err = -ENOENT;
+	}
+
+	return err;
+}
+
+static void mipspmu_free_irq(void)
+{
+	if (mipspmu.irq >= 0)
+		free_irq(mipspmu.irq, NULL);
+	else if (cp0_perfcount_irq < 0)
+		perf_irq = save_perf_irq;
+}
+
+/*
+ * mipsxx/rm9000/loongson2 have different performance counters, they have
+ * specific low-level init routines.
+ */
+static void reset_counters(void *arg);
+static int __hw_perf_event_init(struct perf_event *event);
+
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+	if (atomic_dec_and_mutex_lock(&active_events,
+				&pmu_reserve_mutex)) {
+		/*
+		 * We must not call the destroy function with interrupts
+		 * disabled.
+		 */
+		on_each_cpu(reset_counters,
+			(void *)(long)mipspmu.num_counters, 1);
+		mipspmu_free_irq();
+		mutex_unlock(&pmu_reserve_mutex);
+	}
+}
+
+static int mipspmu_event_init(struct perf_event *event)
+{
+	int err = 0;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HARDWARE:
+	case PERF_TYPE_HW_CACHE:
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
+	if (event->cpu >= nr_cpumask_bits ||
+	    (event->cpu >= 0 && !cpu_online(event->cpu)))
+		return -ENODEV;
+
+	if (!atomic_inc_not_zero(&active_events)) {
+		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
+			atomic_dec(&active_events);
+			return -EINVAL;
+		}
+
+		mutex_lock(&pmu_reserve_mutex);
+		if (atomic_read(&active_events) == 0)
+			err = mipspmu_get_irq();
+
+		if (!err)
+			atomic_inc(&active_events);
+		mutex_unlock(&pmu_reserve_mutex);
+	}
+
+	if (err)
+		return err;
+
+	err = __hw_perf_event_init(event);
+	if (err)
+		hw_perf_event_destroy(event);
+
+	return err;
+}
+
+static struct pmu pmu = {
+	.pmu_enable	= mipspmu_enable,
+	.pmu_disable	= mipspmu_disable,
+	.event_init	= mipspmu_event_init,
+	.add		= mipspmu_add,
+	.del		= mipspmu_del,
+	.start		= mipspmu_start,
+	.stop		= mipspmu_stop,
+	.read		= mipspmu_read,
+};
+
+static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev)
+{
+/*
+ * Top 8 bits for range, next 16 bits for cntr_mask, lowest 8 bits for
+ * event_id.
+ */
+#ifdef CONFIG_MIPS_MT_SMP
+	return ((unsigned int)pev->range << 24) |
+		(pev->cntr_mask & 0xffff00) |
+		(pev->event_id & 0xff);
+#else
+	return (pev->cntr_mask & 0xffff00) |
+		(pev->event_id & 0xff);
+#endif
+}
+
+static const struct mips_perf_event *mipspmu_map_general_event(int idx)
+{
+	const struct mips_perf_event *pev;
+
+	pev = ((*mipspmu.general_event_map)[idx].event_id ==
+		UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
+		&(*mipspmu.general_event_map)[idx]);
+
+	return pev;
+}
+
+static const struct mips_perf_event *mipspmu_map_cache_event(u64 config)
+{
+	unsigned int cache_type, cache_op, cache_result;
+	const struct mips_perf_event *pev;
+
+	cache_type = (config >> 0) & 0xff;
+	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+		return ERR_PTR(-EINVAL);
+
+	cache_op = (config >> 8) & 0xff;
+	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+		return ERR_PTR(-EINVAL);
+
+	cache_result = (config >> 16) & 0xff;
+	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return ERR_PTR(-EINVAL);
+
+	pev = &((*mipspmu.cache_event_map)
+					[cache_type]
+					[cache_op]
+					[cache_result]);
+
+	if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return pev;
+
+}
+
+static int validate_event(struct cpu_hw_events *cpuc,
+	       struct perf_event *event)
+{
+	struct hw_perf_event fake_hwc = event->hw;
+
+	/* Allow mixed event group. So return 1 to pass validation. */
+	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+		return 1;
+
+	return mipsxx_pmu_alloc_counter(cpuc, &fake_hwc) >= 0;
+}
+
+static int validate_group(struct perf_event *event)
+{
+	struct perf_event *sibling, *leader = event->group_leader;
+	struct cpu_hw_events fake_cpuc;
+
+	memset(&fake_cpuc, 0, sizeof(fake_cpuc));
+
+	if (!validate_event(&fake_cpuc, leader))
+		return -EINVAL;
+
+	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+		if (!validate_event(&fake_cpuc, sibling))
+			return -EINVAL;
+	}
+
+	if (!validate_event(&fake_cpuc, event))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* This is needed by specific irq handlers in perf_event_*.c */
+static void handle_associated_event(struct cpu_hw_events *cpuc,
+				    int idx, struct perf_sample_data *data,
+				    struct pt_regs *regs)
+{
+	struct perf_event *event = cpuc->events[idx];
+	struct hw_perf_event *hwc = &event->hw;
+
+	mipspmu_event_update(event, hwc, idx);
+	data->period = event->hw.last_period;
+	if (!mipspmu_event_set_period(event, hwc, idx))
+		return;
+
+	if (perf_event_overflow(event, data, regs))
+		mipsxx_pmu_disable_event(idx);
+}
+
+
+static int __n_counters(void)
+{
+	if (!(read_c0_config1() & M_CONFIG1_PC))
+		return 0;
+	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+		return 1;
+	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+		return 2;
+	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+		return 3;
+
+	return 4;
+}
+
+static int n_counters(void)
+{
+	int counters;
+
+	switch (current_cpu_type()) {
+	case CPU_R10000:
+		counters = 2;
+		break;
+
+	case CPU_R12000:
+	case CPU_R14000:
+		counters = 4;
+		break;
+
+	default:
+		counters = __n_counters();
+	}
+
+	return counters;
+}
+
+static void reset_counters(void *arg)
+{
+	int counters = (int)(long)arg;
+	switch (counters) {
+	case 4:
+		mipsxx_pmu_write_control(3, 0);
+		mipspmu.write_counter(3, 0);
+	case 3:
+		mipsxx_pmu_write_control(2, 0);
+		mipspmu.write_counter(2, 0);
+	case 2:
+		mipsxx_pmu_write_control(1, 0);
+		mipspmu.write_counter(1, 0);
+	case 1:
+		mipsxx_pmu_write_control(0, 0);
+		mipspmu.write_counter(0, 0);
+	}
+}
 
 /* 24K/34K/1004K cores can share the same event map. */
 static const struct mips_perf_event mipsxxcore_event_map
@@ -277,6 +841,16 @@ static const struct mips_perf_event mips
 	[PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
 };
 
+static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
+	[PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL },
+	[PERF_COUNT_HW_CACHE_REFERENCES] = { 0x2b, CNTR_ALL },
+	[PERF_COUNT_HW_CACHE_MISSES] = { 0x2e, CNTR_ALL  },
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x08, CNTR_ALL },
+	[PERF_COUNT_HW_BRANCH_MISSES] = { 0x09, CNTR_ALL },
+	[PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL },
+};
+
 /* 24K/34K/1004K cores can share the same cache event map. */
 static const struct mips_perf_event mipsxxcore_cache_map
 				[PERF_COUNT_HW_CACHE_MAX]
@@ -510,10 +1084,105 @@ static const struct mips_perf_event mips
 },
 };
 
+
+static const struct mips_perf_event octeon_cache_map
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x2b, CNTR_ALL },
+		[C(RESULT_MISS)]	= { 0x2e, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x30, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(L1I)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x18, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { 0x19, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(LL)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(DTLB)] = {
+	/*
+	 * Only general DTLB misses are counted use the same event for
+	 * read and write.
+	 */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x35, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x35, CNTR_ALL },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(ITLB)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x37, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(BPU)] = {
+	/* Using the same code for *HW_BRANCH* */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+};
+
 #ifdef CONFIG_MIPS_MT_SMP
-static void
-check_and_calc_range(struct perf_event *event,
-			const struct mips_perf_event *pev)
+static void check_and_calc_range(struct perf_event *event,
+				 const struct mips_perf_event *pev)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
@@ -536,9 +1205,8 @@ check_and_calc_range(struct perf_event *
 		hwc->config_base |= M_TC_EN_ALL;
 }
 #else
-static void
-check_and_calc_range(struct perf_event *event,
-			const struct mips_perf_event *pev)
+static void check_and_calc_range(struct perf_event *event,
+				 const struct mips_perf_event *pev)
 {
 }
 #endif
@@ -560,7 +1228,7 @@ static int __hw_perf_event_init(struct p
 	} else if (PERF_TYPE_RAW == event->attr.type) {
 		/* We are working on the global raw event. */
 		mutex_lock(&raw_event_mutex);
-		pev = mipspmu->map_raw_event(event->attr.config);
+		pev = mipspmu.map_raw_event(event->attr.config);
 	} else {
 		/* The event type is not (yet) supported. */
 		return -EOPNOTSUPP;
@@ -605,7 +1273,7 @@ static int __hw_perf_event_init(struct p
 	hwc->config = 0;
 
 	if (!hwc->sample_period) {
-		hwc->sample_period  = MAX_PERIOD;
+		hwc->sample_period  = mipspmu.max_period;
 		hwc->last_period    = hwc->sample_period;
 		local64_set(&hwc->period_left, hwc->sample_period);
 	}
@@ -618,70 +1286,47 @@ static int __hw_perf_event_init(struct p
 	}
 
 	event->destroy = hw_perf_event_destroy;
-
 	return err;
 }
 
 static void pause_local_counters(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	int counters = mipspmu->num_counters;
+	int ctr = mipspmu.num_counters;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	switch (counters) {
-	case 4:
-		cpuc->saved_ctrl[3] = r_c0_perfctrl3();
-		w_c0_perfctrl3(cpuc->saved_ctrl[3] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 3:
-		cpuc->saved_ctrl[2] = r_c0_perfctrl2();
-		w_c0_perfctrl2(cpuc->saved_ctrl[2] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 2:
-		cpuc->saved_ctrl[1] = r_c0_perfctrl1();
-		w_c0_perfctrl1(cpuc->saved_ctrl[1] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 1:
-		cpuc->saved_ctrl[0] = r_c0_perfctrl0();
-		w_c0_perfctrl0(cpuc->saved_ctrl[0] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	}
+	do {
+		ctr--;
+		cpuc->saved_ctrl[ctr] = mipsxx_pmu_read_control(ctr);
+		mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr] &
+					 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
+	} while (ctr > 0);
 	local_irq_restore(flags);
 }
 
 static void resume_local_counters(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	int counters = mipspmu->num_counters;
-	unsigned long flags;
+	int ctr = mipspmu.num_counters;
 
-	local_irq_save(flags);
-	switch (counters) {
-	case 4:
-		w_c0_perfctrl3(cpuc->saved_ctrl[3]);
-	case 3:
-		w_c0_perfctrl2(cpuc->saved_ctrl[2]);
-	case 2:
-		w_c0_perfctrl1(cpuc->saved_ctrl[1]);
-	case 1:
-		w_c0_perfctrl0(cpuc->saved_ctrl[0]);
-	}
-	local_irq_restore(flags);
+	do {
+		ctr--;
+		mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr]);
+	} while (ctr > 0);
 }
 
 static int mipsxx_pmu_handle_shared_irq(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct perf_sample_data data;
-	unsigned int counters = mipspmu->num_counters;
-	unsigned int counter;
+	unsigned int counters = mipspmu.num_counters;
+	u64 counter;
 	int handled = IRQ_NONE;
 	struct pt_regs *regs;
 
 	if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
 		return handled;
-
 	/*
 	 * First we pause the local counters, so that when we are locked
 	 * here, the counters are all paused. When it gets locked due to
@@ -702,13 +1347,9 @@ static int mipsxx_pmu_handle_shared_irq(
 #define HANDLE_COUNTER(n)						\
 	case n + 1:							\
 		if (test_bit(n, cpuc->used_mask)) {			\
-			counter = r_c0_perfcntr ## n();			\
-			if (counter & M_COUNTER_OVERFLOW) {		\
-				w_c0_perfcntr ## n(counter &		\
-						VALID_COUNT);		\
-				if (test_and_change_bit(n, cpuc->msbs))	\
-					handle_associated_event(cpuc,	\
-						n, &data, regs);	\
+			counter = mipspmu.read_counter(n);		\
+			if (counter & mipspmu.overflow) {		\
+				handle_associated_event(cpuc, n, &data, regs); \
 				handled = IRQ_HANDLED;			\
 			}						\
 		}
@@ -733,104 +1374,11 @@ static int mipsxx_pmu_handle_shared_irq(
 	return handled;
 }
 
-static irqreturn_t
-mipsxx_pmu_handle_irq(int irq, void *dev)
+static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
 {
 	return mipsxx_pmu_handle_shared_irq();
 }
 
-static void mipsxx_pmu_start(void)
-{
-#ifdef CONFIG_MIPS_MT_SMP
-	write_unlock(&pmuint_rwlock);
-#endif
-	resume_local_counters();
-}
-
-/*
- * MIPS performance counters can be per-TC. The control registers can
- * not be directly accessed across CPUs. Hence if we want to do global
- * control, we need cross CPU calls. on_each_cpu() can help us, but we
- * can not make sure this function is called with interrupts enabled. So
- * here we pause local counters and then grab a rwlock and leave the
- * counters on other CPUs alone. If any counter interrupt raises while
- * we own the write lock, simply pause local counters on that CPU and
- * spin in the handler. Also we know we won't be switched to another
- * CPU after pausing local counters and before grabbing the lock.
- */
-static void mipsxx_pmu_stop(void)
-{
-	pause_local_counters();
-#ifdef CONFIG_MIPS_MT_SMP
-	write_lock(&pmuint_rwlock);
-#endif
-}
-
-static int
-mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
-			struct hw_perf_event *hwc)
-{
-	int i;
-
-	/*
-	 * We only need to care the counter mask. The range has been
-	 * checked definitely.
-	 */
-	unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
-
-	for (i = mipspmu->num_counters - 1; i >= 0; i--) {
-		/*
-		 * Note that some MIPS perf events can be counted by both
-		 * even and odd counters, wheresas many other are only by
-		 * even _or_ odd counters. This introduces an issue that
-		 * when the former kind of event takes the counter the
-		 * latter kind of event wants to use, then the "counter
-		 * allocation" for the latter event will fail. In fact if
-		 * they can be dynamically swapped, they both feel happy.
-		 * But here we leave this issue alone for now.
-		 */
-		if (test_bit(i, &cntr_mask) &&
-			!test_and_set_bit(i, cpuc->used_mask))
-			return i;
-	}
-
-	return -EAGAIN;
-}
-
-static void
-mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	local_irq_save(flags);
-	cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
-		(evt->config_base & M_PERFCTL_CONFIG_MASK) |
-		/* Make sure interrupt enabled. */
-		M_PERFCTL_INTERRUPT_ENABLE;
-	/*
-	 * We do not actually let the counter run. Leave it until start().
-	 */
-	local_irq_restore(flags);
-}
-
-static void
-mipsxx_pmu_disable_event(int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	local_irq_save(flags);
-	cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
-		~M_PERFCTL_COUNT_EVENT_WHENEVER;
-	mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
-	local_irq_restore(flags);
-}
-
 /* 24K */
 #define IS_UNSUPPORTED_24K_EVENT(r, b)					\
 	((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 ||		\
@@ -892,8 +1440,7 @@ mipsxx_pmu_disable_event(int idx)
  * then 128 needs to be added to 15 as the input for the event config,
  * i.e., 143 (0x8F) to be used.
  */
-static const struct mips_perf_event *
-mipsxx_pmu_map_raw_event(u64 config)
+static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 {
 	unsigned int raw_id = config & 0xff;
 	unsigned int base_id = raw_id & 0x7f;
@@ -970,40 +1517,44 @@ mipsxx_pmu_map_raw_event(u64 config)
 	return &raw_event;
 }
 
-static struct mips_pmu mipsxxcore_pmu = {
-	.handle_irq = mipsxx_pmu_handle_irq,
-	.handle_shared_irq = mipsxx_pmu_handle_shared_irq,
-	.start = mipsxx_pmu_start,
-	.stop = mipsxx_pmu_stop,
-	.alloc_counter = mipsxx_pmu_alloc_counter,
-	.read_counter = mipsxx_pmu_read_counter,
-	.write_counter = mipsxx_pmu_write_counter,
-	.enable_event = mipsxx_pmu_enable_event,
-	.disable_event = mipsxx_pmu_disable_event,
-	.map_raw_event = mipsxx_pmu_map_raw_event,
-	.general_event_map = &mipsxxcore_event_map,
-	.cache_event_map = &mipsxxcore_cache_map,
-};
+static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
+{
+	unsigned int raw_id = config & 0xff;
+	unsigned int base_id = raw_id & 0x7f;
 
-static struct mips_pmu mipsxx74Kcore_pmu = {
-	.handle_irq = mipsxx_pmu_handle_irq,
-	.handle_shared_irq = mipsxx_pmu_handle_shared_irq,
-	.start = mipsxx_pmu_start,
-	.stop = mipsxx_pmu_stop,
-	.alloc_counter = mipsxx_pmu_alloc_counter,
-	.read_counter = mipsxx_pmu_read_counter,
-	.write_counter = mipsxx_pmu_write_counter,
-	.enable_event = mipsxx_pmu_enable_event,
-	.disable_event = mipsxx_pmu_disable_event,
-	.map_raw_event = mipsxx_pmu_map_raw_event,
-	.general_event_map = &mipsxx74Kcore_event_map,
-	.cache_event_map = &mipsxx74Kcore_cache_map,
-};
+
+	raw_event.cntr_mask = CNTR_ALL;
+	raw_event.event_id = base_id;
+
+	if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
+		if (base_id > 0x42)
+			return ERR_PTR(-EOPNOTSUPP);
+	} else {
+		if (base_id > 0x3a)
+			return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	switch (base_id) {
+	case 0x00:
+	case 0x0f:
+	case 0x1e:
+	case 0x1f:
+	case 0x2f:
+	case 0x34:
+	case 0x3b ... 0x3f:
+		return ERR_PTR(-EOPNOTSUPP);
+	default:
+		break;
+	}
+
+	return &raw_event;
+}
 
 static int __init
 init_hw_perf_events(void)
 {
 	int counters, irq;
+	int counter_bits;
 
 	pr_info("Performance counters: ");
 
@@ -1035,32 +1586,36 @@ init_hw_perf_events(void)
 	}
 #endif
 
-	on_each_cpu(reset_counters, (void *)(long)counters, 1);
+	mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
 
 	switch (current_cpu_type()) {
 	case CPU_24K:
-		mipsxxcore_pmu.name = "mips/24K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/24K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
 		break;
 	case CPU_34K:
-		mipsxxcore_pmu.name = "mips/34K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/34K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
 		break;
 	case CPU_74K:
-		mipsxx74Kcore_pmu.name = "mips/74K";
-		mipsxx74Kcore_pmu.num_counters = counters;
-		mipsxx74Kcore_pmu.irq = irq;
-		mipspmu = &mipsxx74Kcore_pmu;
+		mipspmu.name = "mips/74K";
+		mipspmu.general_event_map = &mipsxx74Kcore_event_map;
+		mipspmu.cache_event_map = &mipsxx74Kcore_cache_map;
 		break;
 	case CPU_1004K:
-		mipsxxcore_pmu.name = "mips/1004K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/1004K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
+		break;
+	case CPU_CAVIUM_OCTEON:
+	case CPU_CAVIUM_OCTEON_PLUS:
+	case CPU_CAVIUM_OCTEON2:
+		mipspmu.name = "octeon";
+		mipspmu.general_event_map = &octeon_event_map;
+		mipspmu.cache_event_map = &octeon_cache_map;
+		mipspmu.map_raw_event = octeon_pmu_map_raw_event;
 		break;
 	default:
 		pr_cont("Either hardware does not support performance "
@@ -1068,15 +1623,33 @@ init_hw_perf_events(void)
 		return -ENODEV;
 	}
 
-	if (mipspmu)
-		pr_cont("%s PMU enabled, %d counters available to each "
-			"CPU, irq %d%s\n", mipspmu->name, counters, irq,
-			irq < 0 ? " (share with timer interrupt)" : "");
+	mipspmu.num_counters = counters;
+	mipspmu.irq = irq;
+
+	if (read_c0_perfctrl0() & M_PERFCTL_WIDE) {
+		mipspmu.max_period = (1ULL << 63) - 1;
+		mipspmu.valid_count = (1ULL << 63) - 1;
+		mipspmu.overflow = 1ULL << 63;
+		mipspmu.read_counter = mipsxx_pmu_read_counter_64;
+		mipspmu.write_counter = mipsxx_pmu_write_counter_64;
+		counter_bits = 64;
+	} else {
+		mipspmu.max_period = (1ULL << 31) - 1;
+		mipspmu.valid_count = (1ULL << 31) - 1;
+		mipspmu.overflow = 1ULL << 31;
+		mipspmu.read_counter = mipsxx_pmu_read_counter;
+		mipspmu.write_counter = mipsxx_pmu_write_counter;
+		counter_bits = 32;
+	}
+
+	on_each_cpu(reset_counters, (void *)(long)counters, 1);
+
+	pr_cont("%s PMU enabled, %d %d-bit counters available to each "
+		"CPU, irq %d%s\n", mipspmu.name, counters, counter_bits, irq,
+		irq < 0 ? " (share with timer interrupt)" : "");
 
 	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
 early_initcall(init_hw_perf_events);
-
-#endif /* defined(CONFIG_CPU_MIPS32)... */
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/process.c linux-libre-3.2-gnu1/arch/mips/kernel/process.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,13 +9,13 @@
  * Copyright (C) 2004 Thiemo Seufer
  */
 #include <linux/errno.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/tick.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
+#include <linux/export.h>
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/personality.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/prom.c linux-libre-3.2-gnu1/arch/mips/kernel/prom.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/reset.c linux-libre-3.2-gnu1/arch/mips/kernel/reset.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/reset.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 #include <linux/types.h>
 #include <linux/reboot.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/rtlx.c linux-libre-3.2-gnu1/arch/mips/kernel/rtlx.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/rtlx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/rtlx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 
 #include <linux/device.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/scall32-o32.S linux-libre-3.2-gnu1/arch/mips/kernel/scall32-o32.S
--- linux-libre-3.1-gnu1/arch/mips/kernel/scall32-o32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/scall32-o32.S	2012-01-04 18:55:44.000000000 -0500
@@ -496,7 +496,7 @@ einval:	li	v0, -ENOSYS
 	sys	sys_lookup_dcookie	4
 	sys	sys_epoll_create	1
 	sys	sys_epoll_ctl		4
-	sys	sys_epoll_wait		3	/* 4250 */
+	sys	sys_epoll_wait		4	/* 4250 */
 	sys	sys_remap_file_pages	5
 	sys	sys_set_tid_address	1
 	sys	sys_restart_syscall	0
@@ -591,6 +591,8 @@ einval:	li	v0, -ENOSYS
 	sys	sys_syncfs		1
 	sys	sys_sendmmsg		4
 	sys	sys_setns		2
+	sys	sys_process_vm_readv	6	/* 4345 */
+	sys	sys_process_vm_writev	6
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/scall64-64.S linux-libre-3.2-gnu1/arch/mips/kernel/scall64-64.S
--- linux-libre-3.1-gnu1/arch/mips/kernel/scall64-64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/scall64-64.S	2012-01-04 18:55:44.000000000 -0500
@@ -430,4 +430,6 @@ sys_call_table:
 	PTR	sys_syncfs
 	PTR	sys_sendmmsg
 	PTR	sys_setns
+	PTR	sys_process_vm_readv
+	PTR	sys_process_vm_writev		/* 5305 */
 	.size	sys_call_table,.-sys_call_table
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/scall64-n32.S linux-libre-3.2-gnu1/arch/mips/kernel/scall64-n32.S
--- linux-libre-3.1-gnu1/arch/mips/kernel/scall64-n32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/scall64-n32.S	2012-01-04 18:55:44.000000000 -0500
@@ -430,4 +430,6 @@ EXPORT(sysn32_call_table)
 	PTR	sys_syncfs
 	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
+	PTR	compat_sys_process_vm_readv
+	PTR	compat_sys_process_vm_writev	/* 6310 */
 	.size	sysn32_call_table,.-sysn32_call_table
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/scall64-o32.S linux-libre-3.2-gnu1/arch/mips/kernel/scall64-o32.S
--- linux-libre-3.1-gnu1/arch/mips/kernel/scall64-o32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/scall64-o32.S	2012-01-04 18:55:44.000000000 -0500
@@ -548,4 +548,6 @@ sys_call_table:
 	PTR	sys_syncfs
 	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
+	PTR	compat_sys_process_vm_readv	/* 4345 */
+	PTR	compat_sys_process_vm_writev
 	.size	sys_call_table,.-sys_call_table
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/setup.c linux-libre-3.2-gnu1/arch/mips/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/spinlock_test.c linux-libre-3.2-gnu1/arch/mips/kernel/spinlock_test.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/spinlock_test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/spinlock_test.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #include <linux/hrtimer.h>
 #include <linux/fs.h>
 #include <linux/debugfs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/spinlock.h>
 
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/stacktrace.c linux-libre-3.2-gnu1/arch/mips/kernel/stacktrace.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  */
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/stacktrace.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/time.c linux-libre-3.2-gnu1/arch/mips/kernel/time.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/timex.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/cpu-features.h>
 #include <asm/div64.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/traps.c linux-libre-3.2-gnu1/arch/mips/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
@@ -1597,7 +1596,8 @@ void __cpuinit per_cpu_trap_init(void)
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+	if (!cpu_data[cpu].asid_cache)
+		cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/unaligned.c linux-libre-3.2-gnu1/arch/mips/kernel/unaligned.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/unaligned.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/unaligned.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,6 @@
  *       Undo the partial store in this case.
  */
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/kernel/vpe.c linux-libre-3.2-gnu1/arch/mips/kernel/vpe.c
--- linux-libre-3.1-gnu1/arch/mips/kernel/vpe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/kernel/vpe.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/clk.c linux-libre-3.2-gnu1/arch/mips/lantiq/clk.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/clk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/clk.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/devices.c linux-libre-3.2-gnu1/arch/mips/lantiq/devices.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/prom.c linux-libre-3.2-gnu1/arch/mips/lantiq/prom.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/setup.c linux-libre-3.2-gnu1/arch/mips/lantiq/setup.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <asm/bootinfo.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/clk-ase.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/clk-ase.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/clk-ase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/clk-ase.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/clk-xway.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/clk-xway.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/clk-xway.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/clk-xway.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/devices.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/devices.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mtd/physmap.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/dma.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/dma.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/ioport.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio_ebu.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio_ebu.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio_ebu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio_ebu.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio_stp.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio_stp.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/gpio_stp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/gpio_stp.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/prom-ase.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/prom-ase.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/prom-ase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/prom-ase.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/prom-xway.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/prom-xway.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/prom-xway.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/prom-xway.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/lantiq/xway/reset.c linux-libre-3.2-gnu1/arch/mips/lantiq/xway/reset.c
--- linux-libre-3.1-gnu1/arch/mips/lantiq/xway/reset.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/lantiq/xway/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/pm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/reboot.h>
 
 #include <lantiq_soc.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/loongson/common/platform.c linux-libre-3.2-gnu1/arch/mips/loongson/common/platform.c
--- linux-libre-3.1-gnu1/arch/mips/loongson/common/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/loongson/common/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/smp.h>
 #include <linux/platform_device.h>
 
 static struct platform_device loongson2_cpufreq_device = {
diff -druNp linux-libre-3.1-gnu1/arch/mips/Makefile linux-libre-3.2-gnu1/arch/mips/Makefile
--- linux-libre-3.1-gnu1/arch/mips/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -226,7 +226,7 @@ LDFLAGS			+= -m $(ld-emul)
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \
 	egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
-	sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
+	sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/")
 ifdef CONFIG_64BIT
 CHECKFLAGS		+= -m64
 endif
@@ -286,16 +286,18 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 archprepare:
 ifdef CONFIG_MIPS32_N32
 	@echo '  Checking missing-syscalls for N32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
 	@echo '  Checking missing-syscalls for O32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32"
 endif
 
 install:
 	$(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
 	$(Q)install -D -m 755 vmlinuz $(INSTALL_PATH)/vmlinuz-$(KERNELRELEASE)
+endif
 	$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
 	$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/cache.c linux-libre-3.2-gnu1/arch/mips/mm/cache.c
--- linux-libre-3.1-gnu1/arch/mips/mm/cache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,11 @@ void (*local_flush_icache_range)(unsigne
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);
 
+void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
+void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
+
+EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
 void (*local_flush_data_cache_page)(void * addr);
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/c-octeon.c linux-libre-3.2-gnu1/arch/mips/mm/c-octeon.c
--- linux-libre-3.1-gnu1/arch/mips/mm/c-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/c-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -169,6 +169,10 @@ static void octeon_flush_cache_page(stru
 		octeon_flush_icache_all_cores(vma);
 }
 
+static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
 
 /**
  * Probe Octeon's caches
@@ -273,6 +277,8 @@ void __cpuinit octeon_cache_init(void)
 	flush_icache_range		= octeon_flush_icache_range;
 	local_flush_icache_range	= local_octeon_flush_icache_range;
 
+	__flush_kernel_vmap_range	= octeon_flush_kernel_vmap_range;
+
 	build_clear_page();
 	build_copy_page();
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/c-r3k.c linux-libre-3.2-gnu1/arch/mips/mm/c-r3k.c
--- linux-libre-3.1-gnu1/arch/mips/mm/c-r3k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/c-r3k.c	2012-01-04 18:55:44.000000000 -0500
@@ -299,6 +299,11 @@ static void r3k_flush_cache_sigtramp(uns
 	write_c0_status(flags);
 }
 
+static void r3k_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
+
 static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
 {
 	/* Catch bad driver code */
@@ -323,6 +328,8 @@ void __cpuinit r3k_cache_init(void)
 	flush_icache_range = r3k_flush_icache_range;
 	local_flush_icache_range = r3k_flush_icache_range;
 
+	__flush_kernel_vmap_range = r3k_flush_kernel_vmap_range;
+
 	flush_cache_sigtramp = r3k_flush_cache_sigtramp;
 	local_flush_data_cache_page = local_r3k_flush_data_cache_page;
 	flush_data_cache_page = r3k_flush_data_cache_page;
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/c-r4k.c linux-libre-3.2-gnu1/arch/mips/mm/c-r4k.c
--- linux-libre-3.1-gnu1/arch/mips/mm/c-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/c-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -722,6 +722,39 @@ static void r4k_flush_icache_all(void)
 		r4k_blast_icache();
 }
 
+struct flush_kernel_vmap_range_args {
+	unsigned long	vaddr;
+	int		size;
+};
+
+static inline void local_r4k_flush_kernel_vmap_range(void *args)
+{
+	struct flush_kernel_vmap_range_args *vmra = args;
+	unsigned long vaddr = vmra->vaddr;
+	int size = vmra->size;
+
+	/*
+	 * Aliases only affect the primary caches so don't bother with
+	 * S-caches or T-caches.
+	 */
+	if (cpu_has_safe_index_cacheops && size >= dcache_size)
+		r4k_blast_dcache();
+	else {
+		R4600_HIT_CACHEOP_WAR_IMPL;
+		blast_dcache_range(vaddr, vaddr + size);
+	}
+}
+
+static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	struct flush_kernel_vmap_range_args args;
+
+	args.vaddr = (unsigned long) vaddr;
+	args.size = size;
+
+	r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args);
+}
+
 static inline void rm7k_erratum31(void)
 {
 	const unsigned long ic_lsize = 32;
@@ -1403,6 +1436,8 @@ void __cpuinit r4k_cache_init(void)
 	flush_cache_page	= r4k_flush_cache_page;
 	flush_cache_range	= r4k_flush_cache_range;
 
+	__flush_kernel_vmap_range = r4k_flush_kernel_vmap_range;
+
 	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;
 	flush_icache_all	= r4k_flush_icache_all;
 	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/c-tx39.c linux-libre-3.2-gnu1/arch/mips/mm/c-tx39.c
--- linux-libre-3.1-gnu1/arch/mips/mm/c-tx39.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/c-tx39.c	2012-01-04 18:55:44.000000000 -0500
@@ -253,6 +253,11 @@ static void tx39_flush_icache_range(unsi
 	}
 }
 
+static void tx39_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
+
 static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 {
 	unsigned long end;
@@ -394,6 +399,8 @@ void __cpuinit tx39_cache_init(void)
 		flush_icache_range = tx39_flush_icache_range;
 		local_flush_icache_range = tx39_flush_icache_range;
 
+		__flush_kernel_vmap_range = tx39_flush_kernel_vmap_range;
+
 		flush_cache_sigtramp = tx39_flush_cache_sigtramp;
 		local_flush_data_cache_page = local_tx39_flush_data_cache_page;
 		flush_data_cache_page = tx39_flush_data_cache_page;
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/tlb-r3k.c linux-libre-3.2-gnu1/arch/mips/mm/tlb-r3k.c
--- linux-libre-3.1-gnu1/arch/mips/mm/tlb-r3k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/tlb-r3k.c	2012-01-04 18:55:44.000000000 -0500
@@ -223,8 +223,8 @@ void __update_tlb(struct vm_area_struct
 	local_irq_restore(flags);
 }
 
-void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-			    unsigned long entryhi, unsigned long pagemask)
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+		     unsigned long entryhi, unsigned long pagemask)
 {
 	unsigned long flags;
 	unsigned long old_ctx;
diff -druNp linux-libre-3.1-gnu1/arch/mips/mm/tlb-r4k.c linux-libre-3.2-gnu1/arch/mips/mm/tlb-r4k.c
--- linux-libre-3.1-gnu1/arch/mips/mm/tlb-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/mm/tlb-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -337,8 +337,8 @@ void __update_tlb(struct vm_area_struct
 	EXIT_CRITICAL(flags);
 }
 
-void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-	unsigned long entryhi, unsigned long pagemask)
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+		     unsigned long entryhi, unsigned long pagemask)
 {
 	unsigned long flags;
 	unsigned long wired;
diff -druNp linux-libre-3.1-gnu1/arch/mips/netlogic/Platform linux-libre-3.2-gnu1/arch/mips/netlogic/Platform
--- linux-libre-3.1-gnu1/arch/mips/netlogic/Platform	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/netlogic/Platform	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,11 @@ cflags-$(CONFIG_NLM_COMMON)  += -I$(srct
 cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/netlogic
 
 #
+# use mips64 if xlr is not available
+#
+cflags-$(CONFIG_NLM_XLR)	+= $(call cc-option,-march=xlr,-march=mips64)
+
+#
 # NETLOGIC XLR/XLS SoC, Simulator and boards
 #
 core-$(CONFIG_NLM_XLR)	      += arch/mips/netlogic/xlr/
diff -druNp linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/setup.c linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/setup.c
--- linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@ unsigned long netlogic_io_base = (unsign
 unsigned long nlm_common_ebase = 0x0;
 struct psb_info nlm_prom_info;
 
-static void nlm_early_serial_setup(void)
+static void __init nlm_early_serial_setup(void)
 {
 	struct uart_port s;
 	nlm_reg_t *uart_base;
@@ -101,7 +101,7 @@ void __init prom_free_prom_memory(void)
 	/* Nothing yet */
 }
 
-static void build_arcs_cmdline(int *argv)
+static void __init build_arcs_cmdline(int *argv)
 {
 	int i, remain, len;
 	char *arg;
diff -druNp linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/smpboot.S linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/smpboot.S
--- linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/smpboot.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/smpboot.S	2012-01-04 18:55:44.000000000 -0500
@@ -32,17 +32,19 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/init.h>
+
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 
-
-/* Don't jump to linux function from Bootloader stack. Change it
- * here. Kernel might allocate bootloader memory before all the CPUs are
- * brought up (eg: Inode cache region) and we better don't overwrite this
- * memory
+/*
+ * Early code for secondary CPUs. This will get them out of the bootloader
+ * code and into linux. Needed because the bootloader area will be taken
+ * and initialized by linux.
  */
+	__CPUINIT
 NESTED(prom_pre_boot_secondary_cpus, 16, sp)
 	.set	mips64
 	mfc0	t0, $15, 1	# read ebase
@@ -73,7 +75,11 @@ NESTED(prom_pre_boot_secondary_cpus, 16,
 	jr	t0
 	nop
 END(prom_pre_boot_secondary_cpus)
+	__FINIT
 
+/*
+ * NMI code, used for CPU wakeup, copied to reset entry
+ */
 NESTED(nlm_boot_smp_nmi, 0, sp)
 	.set push
 	.set noat
diff -druNp linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/smp.c linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/smp.c
--- linux-libre-3.1-gnu1/arch/mips/netlogic/xlr/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/netlogic/xlr/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,6 +158,10 @@ void __init nlm_smp_setup(void)
 
 	num_cpus = 1;
 	for (i = 0; i < NR_CPUS; i++) {
+		/*
+		 * BSP is not set in nlm_cpu_ready array, it is only for
+		 * ASPs (goto see smpboot.S)
+		 */
 		if (nlm_cpu_ready[i]) {
 			cpu_set(i, phys_cpu_present_map);
 			__cpu_number_map[i] = num_cpus;
@@ -191,7 +195,7 @@ struct plat_smp_ops nlm_smp_ops = {
 
 unsigned long secondary_entry_point;
 
-int nlm_wakeup_secondary_cpus(u32 wakeup_mask)
+int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
 {
 	unsigned int tid, pid, ipi, i, boot_cpu;
 	void *reset_vec;
diff -druNp linux-libre-3.1-gnu1/arch/mips/nxp/pnx8550/common/pci.c linux-libre-3.2-gnu1/arch/mips/nxp/pnx8550/common/pci.c
--- linux-libre-3.1-gnu1/arch/mips/nxp/pnx8550/common/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/nxp/pnx8550/common/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *
- * Author: source@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <pci.h>
-#include <glb.h>
-#include <nand.h>
-
-static struct resource pci_io_resource = {
-	.start	= PNX8550_PCIIO + 0x1000,	/* reserve regacy I/O space */
-	.end	= PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
-	.name	= "pci IO space",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	.start	= PNX8550_PCIMEM,
-	.end	= PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
-	.name	= "pci memory space",
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops pnx8550_pci_ops;
-
-static struct pci_controller pnx8550_controller = {
-	.pci_ops	= &pnx8550_pci_ops,
-	.io_map_base	= PNX8550_PORT_BASE,
-	.io_resource	= &pci_io_resource,
-	.mem_resource	= &pci_mem_resource,
-};
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-static inline unsigned long get_system_mem_size(void)
-{
-	/* Read IP2031_RANK0_ADDR_LO */
-	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-	/* Read IP2031_RANK1_ADDR_HI */
-	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-	return dram_r1_hi - dram_r0_lo + 1;
-}
-
-static int __init pnx8550_pci_setup(void)
-{
-	int pci_mem_code;
-	int mem_size = get_system_mem_size() >> 20;
-
-	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
-	   Bit 1:Enable DAC Powerdown
-	  -> 0:DACs are enabled and are working normally
-	     1:DACs are powerdown
-	   Bit 0:Enable of PCI inta output
-	  -> 0 = Disable PCI inta output
-	     1 = Enable PCI inta output
-	*/
-	PNX8550_GLB2_ENAB_INTA_O = 0;
-
-	/* Calc the PCI mem size code */
-	if (mem_size >= 128)
-		pci_mem_code = SIZE_128M;
-	else if (mem_size >= 64)
-		pci_mem_code = SIZE_64M;
-	else if (mem_size >= 32)
-		pci_mem_code = SIZE_32M;
-	else
-		pci_mem_code = SIZE_16M;
-
-	/* Set PCI_XIO registers */
-	outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
-	outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
-	outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
-	outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
-
-	/* Send memory transaction via PCI_BASE2 */
-	outl(0x00000001, PCI_BASE | PCI_IO);
-
-	/* Unlock the setup register */
-	outl(0xca, PCI_BASE | PCI_UNLOCKREG);
-
-	/*
-	 * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
-	 * to work, and in order for bus_to_baddr to work without any
-	 * hacks.
-	 */
-	outl(0x00000000, PCI_BASE | PCI_BASE10);
-
-	/*
-	 *These two bars are set by default or the boot code.
-	 * However, it's safer to set them here so we're not boot
-	 * code dependent.
-	 */
-	outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */
-	outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */
-
-	outl(PCI_EN_TA |
-	     PCI_EN_PCI2MMI |
-	     PCI_EN_XIO |
-	     PCI_SETUP_BASE18_SIZE(SIZE_32M) |
-	     PCI_SETUP_BASE18_EN |
-	     PCI_SETUP_BASE14_EN |
-	     PCI_SETUP_BASE10_PREF |
-	     PCI_SETUP_BASE10_SIZE(pci_mem_code) |
-	     PCI_SETUP_CFGMANAGE_EN |
-	     PCI_SETUP_PCIARB_EN,
-	     PCI_BASE |
-	     PCI_SETUP);	/* PCI_SETUP */
-	outl(0x00000000, PCI_BASE | PCI_CTRL);	/* PCI_CONTROL */
-
-	register_pci_controller(&pnx8550_controller);
-
-	return 0;
-}
-
-arch_initcall(pnx8550_pci_setup);
diff -druNp linux-libre-3.1-gnu1/arch/mips/nxp/pnx8550/common/setup.c linux-libre-3.2-gnu1/arch/mips/nxp/pnx8550/common/setup.c
--- linux-libre-3.1-gnu1/arch/mips/nxp/pnx8550/common/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/nxp/pnx8550/common/setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,143 +0,0 @@
-/*
- *
- * 2.6 port, Embedded Alley Solutions, Inc
- *
- *  Based on Per Hallsmark, per.hallsmark@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/serial_pnx8xxx.h>
-#include <linux/pm.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/time.h>
-
-#include <glb.h>
-#include <int.h>
-#include <pci.h>
-#include <uart.h>
-#include <nand.h>
-
-extern void __init board_setup(void);
-extern void pnx8550_machine_restart(char *);
-extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern char *prom_getcmdline(void);
-
-struct resource standard_io_resources[] = {
-	{
-		.start	= 0x00,
-		.end	= 0x1f,
-		.name	= "dma1",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x40,
-		.end	= 0x5f,
-		.name	= "timer",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x80,
-		.end	= 0x8f,
-		.name	= "dma page reg",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0xc0,
-		.end	= 0xdf,
-		.name	= "dma2",
-		.flags	= IORESOURCE_BUSY
-	},
-};
-
-#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
-
-extern struct resource pci_io_resource;
-extern struct resource pci_mem_resource;
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-unsigned long get_system_mem_size(void)
-{
-	/* Read IP2031_RANK0_ADDR_LO */
-	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-	/* Read IP2031_RANK1_ADDR_HI */
-	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-	return dram_r1_hi - dram_r0_lo + 1;
-}
-
-int pnx8550_console_port = -1;
-
-void __init plat_mem_setup(void)
-{
-	int i;
-	char* argptr;
-
-	board_setup();  /* board specific setup */
-
-        _machine_restart = pnx8550_machine_restart;
-        _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
-
-	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
-	   Bit 1:Enable DAC Powerdown
-	  -> 0:DACs are enabled and are working normally
-	     1:DACs are powerdown
-	   Bit 0:Enable of PCI inta output
-	  -> 0 = Disable PCI inta output
-	     1 = Enable PCI inta output
-	*/
-	PNX8550_GLB2_ENAB_INTA_O = 0;
-
-	/* IO/MEM resources. */
-	set_io_port_base(PNX8550_PORT_BASE);
-	ioport_resource.start = 0;
-	ioport_resource.end = ~0;
-	iomem_resource.start = 0;
-	iomem_resource.end = ~0;
-
-	/* Request I/O space for devices on this board */
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources + i);
-
-	/* Place the Mode Control bit for GPIO pin 16 in primary function */
-	/* Pin 16 is used by UART1, UA1_TX                                */
-	outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
-			(PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
-			PNX8550_GPIO_MC1);
-
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
-		argptr += strlen("console=ttyS");
-		pnx8550_console_port = *argptr == '0' ? 0 : 1;
-
-		/* We must initialize the UART (console) before early printk */
-		/* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
-		ip3106_lcr(UART_BASE, pnx8550_console_port) =
-			PNX8XXX_UART_LCR_8BIT;
-		ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
-	}
-}
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/fixup-au1000.c linux-libre-3.2-gnu1/arch/mips/pci/fixup-au1000.c
--- linux-libre-3.1-gnu1/arch/mips/pci/fixup-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/fixup-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Board specific PCI fixups.
- *
- * Copyright 2001-2003, 2008 MontaVista Software Inc.
- * Author: 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.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-
-extern char irq_tab_alchemy[][5];
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return irq_tab_alchemy[slot][pin];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/Makefile linux-libre-3.2-gnu1/arch/mips/pci/Makefile
--- linux-libre-3.1-gnu1/arch/mips/pci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,13 @@ obj-$(CONFIG_PCI_TX4927)	+= ops-tx4927.o
 obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
 obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
 					ops-bcm63xx.o
+obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
 
 #
 # These are still pretty much in the old state, watch, go blind.
 #
 obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
-obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
-obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
 obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/ops-au1000.c linux-libre-3.2-gnu1/arch/mips/pci/ops-au1000.c
--- linux-libre-3.1-gnu1/arch/mips/pci/ops-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/ops-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Alchemy/AMD Au1xx0 PCI support.
- *
- * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  Support for all devices (greater than 16) added by David Gathright.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-#undef	DEBUG
-#ifdef	DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-int (*board_pci_idsel)(unsigned int devsel, int assert);
-
-void mod_wired_entry(int entry, unsigned long entrylo0,
-		unsigned long entrylo1, unsigned long entryhi,
-		unsigned long pagemask)
-{
-	unsigned long old_pagemask;
-	unsigned long old_ctx;
-
-	/* Save old context and create impossible VPN2 value */
-	old_ctx = read_c0_entryhi() & 0xff;
-	old_pagemask = read_c0_pagemask();
-	write_c0_index(entry);
-	write_c0_pagemask(pagemask);
-	write_c0_entryhi(entryhi);
-	write_c0_entrylo0(entrylo0);
-	write_c0_entrylo1(entrylo1);
-	tlb_write_indexed();
-	write_c0_entryhi(old_ctx);
-	write_c0_pagemask(old_pagemask);
-}
-
-static struct vm_struct *pci_cfg_vm;
-static int pci_cfg_wired_entry;
-static unsigned long last_entryLo0, last_entryLo1;
-
-/*
- * We can't ioremap the entire pci config space because it's too large.
- * Nor can we call ioremap dynamically because some device drivers use
- * the PCI config routines from within interrupt handlers and that
- * becomes a problem in get_vm_area().  We use one wired TLB to handle
- * all config accesses for all busses.
- */
-void __init au1x_pci_cfg_init(void)
-{
-	/* Reserve a wired entry for PCI config accesses */
-	pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
-	if (!pci_cfg_vm)
-		panic(KERN_ERR "PCI unable to get vm area\n");
-	pci_cfg_wired_entry = read_c0_wired();
-	add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K);
-	last_entryLo0 = last_entryLo1 = 0xffffffff;
-}
-
-static int config_access(unsigned char access_type, struct pci_bus *bus,
-			 unsigned int dev_fn, unsigned char where, u32 *data)
-{
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-	unsigned int device = PCI_SLOT(dev_fn);
-	unsigned int function = PCI_FUNC(dev_fn);
-	unsigned long offset, status;
-	unsigned long cfg_base;
-	unsigned long flags;
-	int error = PCIBIOS_SUCCESSFUL;
-	unsigned long entryLo0, entryLo1;
-
-	if (device > 19) {
-		*data = 0xffffffff;
-		return -1;
-	}
-
-	local_irq_save(flags);
-	au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)),
-			Au1500_PCI_STATCMD);
-	au_sync_udelay(1);
-
-	/*
-	 * Allow board vendors to implement their own off-chip IDSEL.
-	 * If it doesn't succeed, may as well bail out at this point.
-	 */
-	if (board_pci_idsel && board_pci_idsel(device, 1) == 0) {
-		*data = 0xffffffff;
-		local_irq_restore(flags);
-		return -1;
-	}
-
-	/* Setup the config window */
-	if (bus->number == 0)
-		cfg_base = (1 << device) << 11;
-	else
-		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
-
-	/* Setup the lower bits of the 36-bit address */
-	offset = (function << 8) | (where & ~0x3);
-	/* Pick up any address that falls below the page mask */
-	offset |= cfg_base & ~PAGE_MASK;
-
-	/* Page boundary */
-	cfg_base = cfg_base & PAGE_MASK;
-
-	/*
-	 * To improve performance, if the current device is the same as
-	 * the last device accessed, we don't touch the TLB.
-	 */
-	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
-	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
-	if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) {
-		mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1,
-				(unsigned long)pci_cfg_vm->addr, PM_4K);
-		last_entryLo0 = entryLo0;
-		last_entryLo1 = entryLo1;
-	}
-
-	if (access_type == PCI_ACCESS_WRITE)
-		au_writel(*data, (int)(pci_cfg_vm->addr + offset));
-	else
-		*data = au_readl((int)(pci_cfg_vm->addr + offset));
-
-	au_sync_udelay(2);
-
-	DBG("cfg_access %d bus->number %u dev %u at %x *data %x conf %lx\n",
-	    access_type, bus->number, device, where, *data, offset);
-
-	/* Check master abort */
-	status = au_readl(Au1500_PCI_STATCMD);
-
-	if (status & (1 << 29)) {
-		*data = 0xffffffff;
-		error = -1;
-		DBG("Au1x Master Abort\n");
-	} else if ((status >> 28) & 0xf) {
-		DBG("PCI ERR detected: device %u, status %lx\n",
-		    device, (status >> 28) & 0xf);
-
-		/* Clear errors */
-		au_writel(status & 0xf000ffff, Au1500_PCI_STATCMD);
-
-		*data = 0xffffffff;
-		error = -1;
-	}
-
-	/* Take away the IDSEL. */
-	if (board_pci_idsel)
-		(void)board_pci_idsel(device, 0);
-
-	local_irq_restore(flags);
-	return error;
-#endif
-}
-
-static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
-			    int where,	u8 *val)
-{
-	u32 data;
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
-	if (where & 1)
-		data >>= 8;
-	if (where & 2)
-		data >>= 16;
-	*val = data & 0xff;
-	return ret;
-}
-
-static int read_config_word(struct pci_bus *bus, unsigned int devfn,
-			    int where, u16 *val)
-{
-	u32 data;
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
-	if (where & 2)
-		data >>= 16;
-	*val = data & 0xffff;
-	return ret;
-}
-
-static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
-			     int where, u32 *val)
-{
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
-	return ret;
-}
-
-static int write_config_byte(struct pci_bus *bus, unsigned int devfn,
-			     int where, u8 val)
-{
-	u32 data = 0;
-
-	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-		return -1;
-
-	data = (data & ~(0xff << ((where & 3) << 3))) |
-	       (val << ((where & 3) << 3));
-
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_bus *bus, unsigned int devfn,
-			     int where, u16 val)
-{
-	u32 data = 0;
-
-	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-		return -1;
-
-	data = (data & ~(0xffff << ((where & 3) << 3))) |
-	       (val << ((where & 3) << 3));
-
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_dword(struct pci_bus *bus, unsigned int devfn,
-			      int where, u32 val)
-{
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int config_read(struct pci_bus *bus, unsigned int devfn,
-		       int where, int size, u32 *val)
-{
-	switch (size) {
-	case 1: {
-			u8 _val;
-			int rc = read_config_byte(bus, devfn, where, &_val);
-
-			*val = _val;
-			return rc;
-		}
-	case 2: {
-			u16 _val;
-			int rc = read_config_word(bus, devfn, where, &_val);
-
-			*val = _val;
-			return rc;
-		}
-	default:
-		return read_config_dword(bus, devfn, where, val);
-	}
-}
-
-static int config_write(struct pci_bus *bus, unsigned int devfn,
-			int where, int size, u32 val)
-{
-	switch (size) {
-	case 1:
-		return write_config_byte(bus, devfn, where, (u8) val);
-	case 2:
-		return write_config_word(bus, devfn, where, (u16) val);
-	default:
-		return write_config_dword(bus, devfn, where, val);
-	}
-}
-
-struct pci_ops au1x_pci_ops = {
-	config_read,
-	config_write
-};
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/pci-alchemy.c linux-libre-3.2-gnu1/arch/mips/pci/pci-alchemy.c
--- linux-libre-3.1-gnu1/arch/mips/pci/pci-alchemy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/mips/pci/pci-alchemy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,517 @@
+/*
+ * Alchemy PCI host mode support.
+ *
+ * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * Support for all devices (greater than 16) added by David Gathright.
+ */
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_DEBUG_PCI
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...) do {} while (0)
+#endif
+
+#define PCI_ACCESS_READ		0
+#define PCI_ACCESS_WRITE	1
+
+struct alchemy_pci_context {
+	struct pci_controller alchemy_pci_ctrl;	/* leave as first member! */
+	void __iomem *regs;			/* ctrl base */
+	/* tools for wired entry for config space access */
+	unsigned long last_elo0;
+	unsigned long last_elo1;
+	int wired_entry;
+	struct vm_struct *pci_cfg_vm;
+
+	unsigned long pm[12];
+
+	int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
+	int (*board_pci_idsel)(unsigned int devsel, int assert);
+};
+
+/* IO/MEM resources for PCI. Keep the memres in sync with __fixup_bigphys_addr
+ * in arch/mips/alchemy/common/setup.c
+ */
+static struct resource alchemy_pci_def_memres = {
+	.start	= ALCHEMY_PCI_MEMWIN_START,
+	.end	= ALCHEMY_PCI_MEMWIN_END,
+	.name	= "PCI memory space",
+	.flags	= IORESOURCE_MEM
+};
+
+static struct resource alchemy_pci_def_iores = {
+	.start	= ALCHEMY_PCI_IOWIN_START,
+	.end	= ALCHEMY_PCI_IOWIN_END,
+	.name	= "PCI IO space",
+	.flags	= IORESOURCE_IO
+};
+
+static void mod_wired_entry(int entry, unsigned long entrylo0,
+		unsigned long entrylo1, unsigned long entryhi,
+		unsigned long pagemask)
+{
+	unsigned long old_pagemask;
+	unsigned long old_ctx;
+
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi() & 0xff;
+	old_pagemask = read_c0_pagemask();
+	write_c0_index(entry);
+	write_c0_pagemask(pagemask);
+	write_c0_entryhi(entryhi);
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	tlb_write_indexed();
+	write_c0_entryhi(old_ctx);
+	write_c0_pagemask(old_pagemask);
+}
+
+static void alchemy_pci_wired_entry(struct alchemy_pci_context *ctx)
+{
+	ctx->wired_entry = read_c0_wired();
+	add_wired_entry(0, 0, (unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
+	ctx->last_elo0 = ctx->last_elo1 = ~0;
+}
+
+static int config_access(unsigned char access_type, struct pci_bus *bus,
+			 unsigned int dev_fn, unsigned char where, u32 *data)
+{
+	struct alchemy_pci_context *ctx = bus->sysdata;
+	unsigned int device = PCI_SLOT(dev_fn);
+	unsigned int function = PCI_FUNC(dev_fn);
+	unsigned long offset, status, cfg_base, flags, entryLo0, entryLo1, r;
+	int error = PCIBIOS_SUCCESSFUL;
+
+	if (device > 19) {
+		*data = 0xffffffff;
+		return -1;
+	}
+
+	/* YAMON on all db1xxx boards wipes the TLB and writes zero to C0_wired
+	 * on resume, clearing our wired entry.  Unfortunately the ->resume()
+	 * callback is called way way way too late (and ->suspend() too early)
+	 * to have them destroy and recreate it.  Instead just test if c0_wired
+	 * is now lower than the index we retrieved before suspending and then
+	 * recreate the entry if necessary.  Of course this is totally bonkers
+	 * and breaks as soon as someone else adds another wired entry somewhere
+	 * else.  Anyone have any ideas how to handle this better?
+	 */
+	if (unlikely(read_c0_wired() < ctx->wired_entry))
+		alchemy_pci_wired_entry(ctx);
+
+	local_irq_save(flags);
+	r = __raw_readl(ctx->regs + PCI_REG_STATCMD) & 0x0000ffff;
+	r |= PCI_STATCMD_STATUS(0x2000);
+	__raw_writel(r, ctx->regs + PCI_REG_STATCMD);
+	wmb();
+
+	/* Allow board vendors to implement their own off-chip IDSEL.
+	 * If it doesn't succeed, may as well bail out at this point.
+	 */
+	if (ctx->board_pci_idsel(device, 1) == 0) {
+		*data = 0xffffffff;
+		local_irq_restore(flags);
+		return -1;
+	}
+
+	/* Setup the config window */
+	if (bus->number == 0)
+		cfg_base = (1 << device) << 11;
+	else
+		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
+
+	/* Setup the lower bits of the 36-bit address */
+	offset = (function << 8) | (where & ~0x3);
+	/* Pick up any address that falls below the page mask */
+	offset |= cfg_base & ~PAGE_MASK;
+
+	/* Page boundary */
+	cfg_base = cfg_base & PAGE_MASK;
+
+	/* To improve performance, if the current device is the same as
+	 * the last device accessed, we don't touch the TLB.
+	 */
+	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
+	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
+	if ((entryLo0 != ctx->last_elo0) || (entryLo1 != ctx->last_elo1)) {
+		mod_wired_entry(ctx->wired_entry, entryLo0, entryLo1,
+				(unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
+		ctx->last_elo0 = entryLo0;
+		ctx->last_elo1 = entryLo1;
+	}
+
+	if (access_type == PCI_ACCESS_WRITE)
+		__raw_writel(*data, ctx->pci_cfg_vm->addr + offset);
+	else
+		*data = __raw_readl(ctx->pci_cfg_vm->addr + offset);
+	wmb();
+
+	DBG("alchemy-pci: cfg access %d bus %u dev %u at %x dat %x conf %lx\n",
+	    access_type, bus->number, device, where, *data, offset);
+
+	/* check for errors, master abort */
+	status = __raw_readl(ctx->regs + PCI_REG_STATCMD);
+	if (status & (1 << 29)) {
+		*data = 0xffffffff;
+		error = -1;
+		DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d",
+		    access_type, bus->number, device);
+	} else if ((status >> 28) & 0xf) {
+		DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n",
+		    device, (status >> 28) & 0xf);
+
+		/* clear errors */
+		__raw_writel(status & 0xf000ffff, ctx->regs + PCI_REG_STATCMD);
+
+		*data = 0xffffffff;
+		error = -1;
+	}
+
+	/* Take away the IDSEL. */
+	(void)ctx->board_pci_idsel(device, 0);
+
+	local_irq_restore(flags);
+	return error;
+}
+
+static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
+			    int where,	u8 *val)
+{
+	u32 data;
+	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+
+	if (where & 1)
+		data >>= 8;
+	if (where & 2)
+		data >>= 16;
+	*val = data & 0xff;
+	return ret;
+}
+
+static int read_config_word(struct pci_bus *bus, unsigned int devfn,
+			    int where, u16 *val)
+{
+	u32 data;
+	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+
+	if (where & 2)
+		data >>= 16;
+	*val = data & 0xffff;
+	return ret;
+}
+
+static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
+			     int where, u32 *val)
+{
+	return config_access(PCI_ACCESS_READ, bus, devfn, where, val);
+}
+
+static int write_config_byte(struct pci_bus *bus, unsigned int devfn,
+			     int where, u8 val)
+{
+	u32 data = 0;
+
+	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+		return -1;
+
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_bus *bus, unsigned int devfn,
+			     int where, u16 val)
+{
+	u32 data = 0;
+
+	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+		return -1;
+
+	data = (data & ~(0xffff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_dword(struct pci_bus *bus, unsigned int devfn,
+			      int where, u32 val)
+{
+	return config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val);
+}
+
+static int alchemy_pci_read(struct pci_bus *bus, unsigned int devfn,
+		       int where, int size, u32 *val)
+{
+	switch (size) {
+	case 1: {
+			u8 _val;
+			int rc = read_config_byte(bus, devfn, where, &_val);
+
+			*val = _val;
+			return rc;
+		}
+	case 2: {
+			u16 _val;
+			int rc = read_config_word(bus, devfn, where, &_val);
+
+			*val = _val;
+			return rc;
+		}
+	default:
+		return read_config_dword(bus, devfn, where, val);
+	}
+}
+
+static int alchemy_pci_write(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 val)
+{
+	switch (size) {
+	case 1:
+		return write_config_byte(bus, devfn, where, (u8) val);
+	case 2:
+		return write_config_word(bus, devfn, where, (u16) val);
+	default:
+		return write_config_dword(bus, devfn, where, val);
+	}
+}
+
+static struct pci_ops alchemy_pci_ops = {
+	.read	= alchemy_pci_read,
+	.write	= alchemy_pci_write,
+};
+
+static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
+{
+	return 1;	/* success */
+}
+
+static int __devinit alchemy_pci_probe(struct platform_device *pdev)
+{
+	struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
+	struct alchemy_pci_context *ctx;
+	void __iomem *virt_io;
+	unsigned long val;
+	struct resource *r;
+	int ret;
+
+	/* need at least PCI IRQ mapping table */
+	if (!pd) {
+		dev_err(&pdev->dev, "need platform data for PCI setup\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		dev_err(&pdev->dev, "no memory for pcictl context\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no  pcictl ctrl regs resource\n");
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r), pdev->name)) {
+		dev_err(&pdev->dev, "cannot claim pci regs\n");
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	ctx->regs = ioremap_nocache(r->start, resource_size(r));
+	if (!ctx->regs) {
+		dev_err(&pdev->dev, "cannot map pci regs\n");
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	/* map parts of the PCI IO area */
+	/* REVISIT: if this changes with a newer variant (doubt it) make this
+	 * a platform resource.
+	 */
+	virt_io = ioremap(AU1500_PCI_IO_PHYS_ADDR, 0x00100000);
+	if (!virt_io) {
+		dev_err(&pdev->dev, "cannot remap pci io space\n");
+		ret = -ENODEV;
+		goto out3;
+	}
+	ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io;
+
+#ifdef CONFIG_DMA_NONCOHERENT
+	/* Au1500 revisions older than AD have borked coherent PCI */
+	if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) &&
+	    (read_c0_prid() < 0x01030202)) {
+		val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
+		val |= PCI_CONFIG_NC;
+		__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
+		wmb();
+		dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n");
+	}
+#endif
+
+	if (pd->board_map_irq)
+		ctx->board_map_irq = pd->board_map_irq;
+
+	if (pd->board_pci_idsel)
+		ctx->board_pci_idsel = pd->board_pci_idsel;
+	else
+		ctx->board_pci_idsel = alchemy_pci_def_idsel;
+
+	/* fill in relevant pci_controller members */
+	ctx->alchemy_pci_ctrl.pci_ops = &alchemy_pci_ops;
+	ctx->alchemy_pci_ctrl.mem_resource = &alchemy_pci_def_memres;
+	ctx->alchemy_pci_ctrl.io_resource = &alchemy_pci_def_iores;
+
+	/* we can't ioremap the entire pci config space because it's too large,
+	 * nor can we dynamically ioremap it because some drivers use the
+	 * PCI config routines from within atomic contex and that becomes a
+	 * problem in get_vm_area().  Instead we use one wired TLB entry to
+	 * handle all config accesses for all busses.
+	 */
+	ctx->pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
+	if (!ctx->pci_cfg_vm) {
+		dev_err(&pdev->dev, "unable to get vm area\n");
+		ret = -ENOMEM;
+		goto out4;
+	}
+	ctx->wired_entry = 8192;	/* impossibly high value */
+
+	set_io_port_base((unsigned long)ctx->alchemy_pci_ctrl.io_map_base);
+
+	/* board may want to modify bits in the config register, do it now */
+	val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
+	val &= ~pd->pci_cfg_clr;
+	val |= pd->pci_cfg_set;
+	val &= ~PCI_CONFIG_PD;		/* clear disable bit */
+	__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
+	wmb();
+
+	platform_set_drvdata(pdev, ctx);
+	register_pci_controller(&ctx->alchemy_pci_ctrl);
+
+	return 0;
+
+out4:
+	iounmap(virt_io);
+out3:
+	iounmap(ctx->regs);
+out2:
+	release_mem_region(r->start, resource_size(r));
+out1:
+	kfree(ctx);
+out:
+	return ret;
+}
+
+
+#ifdef CONFIG_PM
+/* save PCI controller register contents. */
+static int alchemy_pci_suspend(struct device *dev)
+{
+	struct alchemy_pci_context *ctx = dev_get_drvdata(dev);
+
+	ctx->pm[0]  = __raw_readl(ctx->regs + PCI_REG_CMEM);
+	ctx->pm[1]  = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
+	ctx->pm[2]  = __raw_readl(ctx->regs + PCI_REG_B2BMASK_CCH);
+	ctx->pm[3]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE0_VID);
+	ctx->pm[4]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE1_SID);
+	ctx->pm[5]  = __raw_readl(ctx->regs + PCI_REG_MWMASK_DEV);
+	ctx->pm[6]  = __raw_readl(ctx->regs + PCI_REG_MWBASE_REV_CCL);
+	ctx->pm[7]  = __raw_readl(ctx->regs + PCI_REG_ID);
+	ctx->pm[8]  = __raw_readl(ctx->regs + PCI_REG_CLASSREV);
+	ctx->pm[9]  = __raw_readl(ctx->regs + PCI_REG_PARAM);
+	ctx->pm[10] = __raw_readl(ctx->regs + PCI_REG_MBAR);
+	ctx->pm[11] = __raw_readl(ctx->regs + PCI_REG_TIMEOUT);
+
+	return 0;
+}
+
+static int alchemy_pci_resume(struct device *dev)
+{
+	struct alchemy_pci_context *ctx = dev_get_drvdata(dev);
+
+	__raw_writel(ctx->pm[0],  ctx->regs + PCI_REG_CMEM);
+	__raw_writel(ctx->pm[2],  ctx->regs + PCI_REG_B2BMASK_CCH);
+	__raw_writel(ctx->pm[3],  ctx->regs + PCI_REG_B2BBASE0_VID);
+	__raw_writel(ctx->pm[4],  ctx->regs + PCI_REG_B2BBASE1_SID);
+	__raw_writel(ctx->pm[5],  ctx->regs + PCI_REG_MWMASK_DEV);
+	__raw_writel(ctx->pm[6],  ctx->regs + PCI_REG_MWBASE_REV_CCL);
+	__raw_writel(ctx->pm[7],  ctx->regs + PCI_REG_ID);
+	__raw_writel(ctx->pm[8],  ctx->regs + PCI_REG_CLASSREV);
+	__raw_writel(ctx->pm[9],  ctx->regs + PCI_REG_PARAM);
+	__raw_writel(ctx->pm[10], ctx->regs + PCI_REG_MBAR);
+	__raw_writel(ctx->pm[11], ctx->regs + PCI_REG_TIMEOUT);
+	wmb();
+	__raw_writel(ctx->pm[1],  ctx->regs + PCI_REG_CONFIG);
+	wmb();
+
+	return 0;
+}
+
+static const struct dev_pm_ops alchemy_pci_pmops = {
+	.suspend	= alchemy_pci_suspend,
+	.resume		= alchemy_pci_resume,
+};
+
+#define ALCHEMY_PCICTL_PM	(&alchemy_pci_pmops)
+
+#else
+#define ALCHEMY_PCICTL_PM	NULL
+#endif
+
+static struct platform_driver alchemy_pcictl_driver = {
+	.probe		= alchemy_pci_probe,
+	.driver	= {
+		.name	= "alchemy-pci",
+		.owner	= THIS_MODULE,
+		.pm	= ALCHEMY_PCICTL_PM,
+	},
+};
+
+static int __init alchemy_pci_init(void)
+{
+	/* Au1500/Au1550 have PCI */
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1550:
+		return platform_driver_register(&alchemy_pcictl_driver);
+	}
+	return 0;
+}
+arch_initcall(alchemy_pci_init);
+
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct alchemy_pci_context *ctx = dev->sysdata;
+	if (ctx && ctx->board_map_irq)
+		return ctx->board_map_irq(dev, slot, pin);
+	return -1;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/pci-bcm47xx.c linux-libre-3.2-gnu1/arch/mips/pci/pci-bcm47xx.c
--- linux-libre-3.1-gnu1/arch/mips/pci/pci-bcm47xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/pci-bcm47xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/ssb/ssb.h>
+#include <bcm47xx.h>
 
 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
@@ -33,9 +34,13 @@ int __init pcibios_map_irq(const struct
 
 int pcibios_plat_dev_init(struct pci_dev *dev)
 {
+#ifdef CONFIG_BCM47XX_SSB
 	int res;
 	u8 slot, pin;
 
+	if (bcm47xx_bus_type !=  BCM47XX_BUS_TYPE_SSB)
+		return 0;
+
 	res = ssb_pcibios_plat_dev_init(dev);
 	if (res < 0) {
 		printk(KERN_ALERT "PCI: Failed to init device %s\n",
@@ -55,5 +60,6 @@ int pcibios_plat_dev_init(struct pci_dev
 	}
 
 	dev->irq = res;
+#endif
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/pci.c linux-libre-3.2-gnu1/arch/mips/pci/pci.c
--- linux-libre-3.1-gnu1/arch/mips/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/pci.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/pci-ip27.c linux-libre-3.2-gnu1/arch/mips/pci/pci-ip27.c
--- linux-libre-3.1-gnu1/arch/mips/pci/pci-ip27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/pci-ip27.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <asm/sn/arch.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/pci/pci-lantiq.c linux-libre-3.2-gnu1/arch/mips/pci/pci-lantiq.c
--- linux-libre-3.1-gnu1/arch/mips/pci/pci-lantiq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pci/pci-lantiq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 
 #include <asm/pci.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/pmc-sierra/msp71xx/msp_serial.c linux-libre-3.2-gnu1/arch/mips/pmc-sierra/msp71xx/msp_serial.c
--- linux-libre-3.1-gnu1/arch/mips/pmc-sierra/msp71xx/msp_serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pmc-sierra/msp71xx/msp_serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
+#include <linux/slab.h>
 
 #include <asm/bootinfo.h>
 #include <asm/io.h>
@@ -38,6 +39,55 @@
 #include <msp_int.h>
 #include <msp_regs.h>
 
+struct msp_uart_data {
+	int	last_lcr;
+};
+
+static void msp_serial_out(struct uart_port *p, int offset, int value)
+{
+	struct msp_uart_data *d = p->private_data;
+
+	if (offset == UART_LCR)
+		d->last_lcr = value;
+
+	offset <<= p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static unsigned int msp_serial_in(struct uart_port *p, int offset)
+{
+	offset <<= p->regshift;
+
+	return readb(p->membase + offset);
+}
+
+static int msp_serial_handle_irq(struct uart_port *p)
+{
+	struct msp_uart_data *d = p->private_data;
+	unsigned int iir = readb(p->membase + (UART_IIR << p->regshift));
+
+	if (serial8250_handle_irq(p, iir)) {
+		return 1;
+	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+		/*
+		 * The DesignWare APB UART has an Busy Detect (0x07) interrupt
+		 * meaning an LCR write attempt occurred while the UART was
+		 * busy. The interrupt must be cleared by reading the UART
+		 * status register (USR) and the LCR re-written.
+		 *
+		 * Note: MSP reserves 0x20 bytes of address space for the UART
+		 * and the USR is mapped in a separate block at an offset of
+		 * 0xc0 from the start of the UART.
+		 */
+		(void)readb(p->membase + 0xc0);
+		writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift));
+
+		return 1;
+	}
+
+	return 0;
+}
+
 void __init msp_serial_setup(void)
 {
 	char    *s;
@@ -59,13 +109,22 @@ void __init msp_serial_setup(void)
 	up.irq          = MSP_INT_UART0;
 	up.uartclk      = uartclk;
 	up.regshift     = 2;
-	up.iotype       = UPIO_DWAPB; /* UPIO_MEM like */
+	up.iotype       = UPIO_MEM;
 	up.flags        = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
 	up.type         = PORT_16550A;
 	up.line         = 0;
-	up.private_data		= (void*)UART0_STATUS_REG;
-	if (early_serial_setup(&up))
-		printk(KERN_ERR "Early serial init of port 0 failed\n");
+	up.serial_out	= msp_serial_out;
+	up.serial_in	= msp_serial_in;
+	up.handle_irq	= msp_serial_handle_irq;
+	up.private_data	= kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL);
+	if (!up.private_data) {
+		pr_err("failed to allocate uart private data\n");
+		return;
+	}
+	if (early_serial_setup(&up)) {
+		kfree(up.private_data);
+		pr_err("Early serial init of port 0 failed\n");
+	}
 
 	/* Initialize the second serial port, if one exists */
 	switch (mips_machtype) {
@@ -88,6 +147,8 @@ void __init msp_serial_setup(void)
 	up.irq          = MSP_INT_UART1;
 	up.line         = 1;
 	up.private_data		= (void*)UART1_STATUS_REG;
-	if (early_serial_setup(&up))
-		printk(KERN_ERR "Early serial init of port 1 failed\n");
+	if (early_serial_setup(&up)) {
+		kfree(up.private_data);
+		pr_err("Early serial init of port 1 failed\n");
+	}
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/pmc-sierra/msp71xx/msp_setup.c linux-libre-3.2-gnu1/arch/mips/pmc-sierra/msp71xx/msp_setup.c
--- linux-libre-3.1-gnu1/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <asm/cacheflush.h>
 #include <asm/r4kcache.h>
 #include <asm/reboot.h>
+#include <asm/smp-ops.h>
 #include <asm/time.h>
 
 #include <msp_prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/pmc-sierra/yosemite/prom.c linux-libre-3.2-gnu1/arch/mips/pmc-sierra/yosemite/prom.c
--- linux-libre-3.1-gnu1/arch/mips/pmc-sierra/yosemite/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pmc-sierra/yosemite/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@ void __init prom_init(void)
 
 	/* Get the boot parameters */
 	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+		if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >=
 		    sizeof(arcs_cmdline))
 			break;
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/pmc-sierra/yosemite/py-console.c linux-libre-3.2-gnu1/arch/mips/pmc-sierra/yosemite/py-console.c
--- linux-libre-3.1-gnu1/arch/mips/pmc-sierra/yosemite/py-console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pmc-sierra/yosemite/py-console.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,15 +65,11 @@ static unsigned char readb_outer_space(u
 
 	__asm__ __volatile__ (
 	"	.set	mips3		\n"
-	"	.set	push		\n"
-	"	.set	noreorder	\n"
-	"	.set	nomacro		\n"
 	"	ld	%0, %1		\n"
-	"	.set	pop		\n"
 	"	lbu	%0, (%0)	\n"
 	"	.set	mips0		\n"
 	: "=r" (res)
-	: "R" (vaddr));
+	: "m" (vaddr));
 
 	write_c0_status(sr);
 	ssnop_4();
@@ -93,15 +89,11 @@ static void writeb_outer_space(unsigned
 
 	__asm__ __volatile__ (
 	"	.set	mips3		\n"
-	"	.set	push		\n"
-	"	.set	noreorder	\n"
-	"	.set	nomacro		\n"
 	"	ld	%0, %1		\n"
-	"	.set	pop		\n"
 	"	sb	%2, (%0)	\n"
 	"	.set	mips0		\n"
 	: "=&r" (tmp)
-	: "R" (vaddr), "r" (c));
+	: "m" (vaddr), "r" (c));
 
 	write_c0_status(sr);
 	ssnop_4();
diff -druNp linux-libre-3.1-gnu1/arch/mips/pnx8550/common/prom.c linux-libre-3.2-gnu1/arch/mips/pnx8550/common/prom.c
--- linux-libre-3.1-gnu1/arch/mips/pnx8550/common/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/pnx8550/common/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@ typedef struct
 }t_env_var;
 
 
-char * prom_getcmdline(void)
+char * __init prom_getcmdline(void)
 {
 	return &(arcs_cmdline[0]);
 }
diff -druNp linux-libre-3.1-gnu1/arch/mips/powertv/asic/Kconfig linux-libre-3.2-gnu1/arch/mips/powertv/asic/Kconfig
--- linux-libre-3.1-gnu1/arch/mips/powertv/asic/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/powertv/asic/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-config MIN_RUNTIME_RESOURCES
-	bool "Support for minimum runtime resources"
-	default n
-	depends on POWERTV
-	help
-	  Enables support for minimizing the number of (SA asic) runtime
-	  resources that are preallocated by the kernel.
-
-config MIN_RUNTIME_DOCSIS
-	bool "Support for minimum DOCSIS resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated DOCSIS resource.
-
-config MIN_RUNTIME_PMEM
-	bool "Support for minimum PMEM resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated Memory resource.
-
-config MIN_RUNTIME_TFTP
-	bool "Support for minimum TFTP resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated TFTP resource.
diff -druNp linux-libre-3.1-gnu1/arch/mips/powertv/Kconfig linux-libre-3.2-gnu1/arch/mips/powertv/Kconfig
--- linux-libre-3.1-gnu1/arch/mips/powertv/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/powertv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,3 @@
-source "arch/mips/powertv/asic/Kconfig"
-
 config BOOTLOADER_DRIVER
 	bool "PowerTV Bootloader Driver Support"
 	default n
diff -druNp linux-libre-3.1-gnu1/arch/mips/powertv/pci/fixup-powertv.c linux-libre-3.2-gnu1/arch/mips/powertv/pci/fixup-powertv.c
--- linux-libre-3.1-gnu1/arch/mips/powertv/pci/fixup-powertv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/powertv/pci/fixup-powertv.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/mach-powertv/interrupts.h>
 #include "powertv-pci.h"
diff -druNp linux-libre-3.1-gnu1/arch/mips/powertv/powertv-usb.c linux-libre-3.2-gnu1/arch/mips/powertv/powertv-usb.c
--- linux-libre-3.1-gnu1/arch/mips/powertv/powertv-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/powertv/powertv-usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <asm/mach-powertv/asic.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/rb532/gpio.c linux-libre-3.2-gnu1/arch/mips/rb532/gpio.c
--- linux-libre-3.1-gnu1/arch/mips/rb532/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/rb532/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/export.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/rb532/setup.c linux-libre-3.2-gnu1/arch/mips/rb532/setup.c
--- linux-libre-3.1-gnu1/arch/mips/rb532/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/rb532/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/sgi-ip27/ip27-irq.c linux-libre-3.2-gnu1/arch/mips/sgi-ip27/ip27-irq.c
--- linux-libre-3.1-gnu1/arch/mips/sgi-ip27/ip27-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/sgi-ip27/ip27-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -337,12 +337,12 @@ static struct irq_chip bridge_irq_type =
 	.irq_unmask	= enable_bridge_irq,
 };
 
-void __devinit register_bridge_irq(unsigned int irq)
+void register_bridge_irq(unsigned int irq)
 {
 	irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
 }
 
-int __devinit request_bridge_irq(struct bridge_controller *bc)
+int request_bridge_irq(struct bridge_controller *bc)
 {
 	int irq = allocate_irqno();
 	int swlevel, cpu;
diff -druNp linux-libre-3.1-gnu1/arch/mips/txx9/generic/setup_tx4939.c linux-libre-3.2-gnu1/arch/mips/txx9/generic/setup_tx4939.c
--- linux-libre-3.1-gnu1/arch/mips/txx9/generic/setup_tx4939.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/txx9/generic/setup_tx4939.c	2012-01-04 18:55:44.000000000 -0500
@@ -321,7 +321,7 @@ void __init tx4939_sio_init(unsigned int
 static u32 tx4939_get_eth_speed(struct net_device *dev)
 {
 	struct ethtool_cmd cmd;
-	if (dev_ethtool_get_settings(dev, &cmd))
+	if (__ethtool_get_settings(dev, &cmd))
 		return 100;	/* default 100Mbps */
 
 	return ethtool_cmd_speed(&cmd);
diff -druNp linux-libre-3.1-gnu1/arch/mips/txx9/generic/spi_eeprom.c linux-libre-3.2-gnu1/arch/mips/txx9/generic/spi_eeprom.c
--- linux-libre-3.1-gnu1/arch/mips/txx9/generic/spi_eeprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/txx9/generic/spi_eeprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/txx9/rbtx4939/setup.c linux-libre-3.2-gnu1/arch/mips/txx9/rbtx4939/setup.c
--- linux-libre-3.1-gnu1/arch/mips/txx9/rbtx4939/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/txx9/rbtx4939/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/interrupt.h>
diff -druNp linux-libre-3.1-gnu1/arch/mips/vr41xx/common/giu.c linux-libre-3.2-gnu1/arch/mips/vr41xx/common/giu.c
--- linux-libre-3.1-gnu1/arch/mips/vr41xx/common/giu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/vr41xx/common/giu.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mips/vr41xx/common/rtc.c linux-libre-3.2-gnu1/arch/mips/vr41xx/common/rtc.c
--- linux-libre-3.1-gnu1/arch/mips/vr41xx/common/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mips/vr41xx/common/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/mn10300/Kconfig linux-libre-3.2-gnu1/arch/mn10300/Kconfig
--- linux-libre-3.1-gnu1/arch/mn10300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mn10300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -47,9 +47,6 @@ config GENERIC_CMOS_UPDATE
 config GENERIC_HWEIGHT
 	def_bool y
 
-config GENERIC_TIME
-	def_bool y
-
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
@@ -195,7 +192,7 @@ config SMP
 	  singleprocessor machines. On a singleprocessor machine, the kernel
 	  will run faster if you say N here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://www.tldp.org/docs.html#howto>.
 
diff -druNp linux-libre-3.1-gnu1/arch/mn10300/kernel/gdb-stub.c linux-libre-3.2-gnu1/arch/mn10300/kernel/gdb-stub.c
--- linux-libre-3.1-gnu1/arch/mn10300/kernel/gdb-stub.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mn10300/kernel/gdb-stub.c	2012-01-04 18:55:44.000000000 -0500
@@ -798,7 +798,7 @@ unsigned char *mem2hex(const void *_mem,
 	if ((u32) mem & 1 && count >= 1) {
 		if (gdbstub_read_byte(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 		mem++;
 		count--;
 	}
@@ -806,8 +806,8 @@ unsigned char *mem2hex(const void *_mem,
 	if ((u32) mem & 3 && count >= 2) {
 		if (gdbstub_read_word(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -815,10 +815,10 @@ unsigned char *mem2hex(const void *_mem,
 	while (count >= 4) {
 		if (gdbstub_read_dword(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
-		buf = pack_hex_byte(buf, ch[2]);
-		buf = pack_hex_byte(buf, ch[3]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[2]);
+		buf = hex_byte_pack(buf, ch[3]);
 		mem += 4;
 		count -= 4;
 	}
@@ -826,8 +826,8 @@ unsigned char *mem2hex(const void *_mem,
 	if (count >= 2) {
 		if (gdbstub_read_word(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -835,7 +835,7 @@ unsigned char *mem2hex(const void *_mem,
 	if (count >= 1) {
 		if (gdbstub_read_byte(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 	}
 
 	*buf = 0;
@@ -1273,13 +1273,13 @@ static int gdbstub(struct pt_regs *regs,
 		ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
 
 		hx = hex_asc_hi(excep >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(excep >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(excep);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(excep);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1291,21 +1291,21 @@ static int gdbstub(struct pt_regs *regs,
 		ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
 
 		hx = hex_asc_hi(bcberr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1321,12 +1321,12 @@ static int gdbstub(struct pt_regs *regs,
 	 * Send trap type (converted to signal)
 	 */
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/*
 	 * Send Error PC
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REGID_PC);
+	ptr = hex_byte_pack(ptr, GDB_REGID_PC);
 	*ptr++ = ':';
 	ptr = mem2hex(&regs->pc, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1334,7 +1334,7 @@ static int gdbstub(struct pt_regs *regs,
 	/*
 	 * Send frame pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REGID_FP);
+	ptr = hex_byte_pack(ptr, GDB_REGID_FP);
 	*ptr++ = ':';
 	ptr = mem2hex(&regs->a3, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1343,7 +1343,7 @@ static int gdbstub(struct pt_regs *regs,
 	 * Send stack pointer
 	 */
 	ssp = (unsigned long) (regs + 1);
-	ptr = pack_hex_byte(ptr, GDB_REGID_SP);
+	ptr = hex_byte_pack(ptr, GDB_REGID_SP);
 	*ptr++ = ':';
 	ptr = mem2hex(&ssp, ptr, 4, 0);
 	*ptr++ = ';';
diff -druNp linux-libre-3.1-gnu1/arch/mn10300/kernel/irq.c linux-libre-3.2-gnu1/arch/mn10300/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/mn10300/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/mn10300/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -260,7 +260,6 @@ void set_intr_level(int irq, u16 level)
 /*
  * mark an interrupt to be ACK'd after interrupt handlers have been run rather
  * than before
- * - see Documentation/mn10300/features.txt
  */
 void mn10300_set_lateack_irq_type(int irq)
 {
diff -druNp linux-libre-3.1-gnu1/arch/openrisc/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/openrisc/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/openrisc/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/openrisc/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #define __ASM_OPENRISC_DMA_MAPPING_H
 
 /*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  *
  * This file is written with the intention of eventually moving over
diff -druNp linux-libre-3.1-gnu1/arch/openrisc/Kconfig linux-libre-3.2-gnu1/arch/openrisc/Kconfig
--- linux-libre-3.1-gnu1/arch/openrisc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/openrisc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
 #
 
 config OPENRISC
@@ -19,9 +19,6 @@ config OPENRISC
 config MMU
 	def_bool y
 
-config WISHBONE_BUS_BIG_ENDIAN
-	def_bool y
-
 config SYMBOL_PREFIX
         string
         default ""
@@ -160,15 +157,6 @@ config JUMP_UPON_UNHANDLED_EXCEPTION
 
 	  Say Y if you are unsure.
 
-config OPENRISC_EXCEPTION_DEBUG
-	bool "Print processor state at each exception"
-	default n
-	help
-	  This option will make your kernel unusable for all but kernel
-	  debugging.
-
-	  Say N if you are unsure.
-
 config OPENRISC_ESR_EXCEPTION_BUG_CHECK
 	bool "Check for possible ESR exception bug"
 	default n
diff -druNp linux-libre-3.1-gnu1/arch/parisc/include/asm/compat.h linux-libre-3.2-gnu1/arch/parisc/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/parisc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -105,7 +105,8 @@ struct compat_statfs {
 	__kernel_fsid_t	f_fsid;
 	s32		f_namelen;
 	s32		f_frsize;
-	s32		f_spare[5];
+	s32		f_flags;
+	s32		f_spare[4];
 };
 
 struct compat_sigcontext {
diff -druNp linux-libre-3.1-gnu1/arch/parisc/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/parisc/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/parisc/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
 
-/* See Documentation/PCI/PCI-DMA-mapping.txt */
+/* See Documentation/DMA-API-HOWTO.txt */
 struct hppa_dma_ops {
 	int  (*dma_supported)(struct device *dev, u64 mask);
 	void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
diff -druNp linux-libre-3.1-gnu1/arch/parisc/Kconfig linux-libre-3.2-gnu1/arch/parisc/Kconfig
--- linux-libre-3.1-gnu1/arch/parisc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -169,9 +169,7 @@ config 64BIT
 
 choice
 	prompt "Kernel page size"
-	default PARISC_PAGE_SIZE_4KB  if !64BIT
-	default PARISC_PAGE_SIZE_4KB  if 64BIT
-#	default PARISC_PAGE_SIZE_16KB if 64BIT
+	default PARISC_PAGE_SIZE_4KB
 
 config PARISC_PAGE_SIZE_4KB
 	bool "4KB"
diff -druNp linux-libre-3.1-gnu1/arch/parisc/kernel/drivers.c linux-libre-3.2-gnu1/arch/parisc/kernel/drivers.c
--- linux-libre-3.1-gnu1/arch/parisc/kernel/drivers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/kernel/drivers.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
diff -druNp linux-libre-3.1-gnu1/arch/parisc/kernel/pci-dma.c linux-libre-3.2-gnu1/arch/parisc/kernel/pci-dma.c
--- linux-libre-3.1-gnu1/arch/parisc/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 ** PARISC 1.1 Dynamic DMA mapping support.
 ** This implementation is for PA-RISC platforms that do not support
 ** I/O TLBs (aka DMA address translation hardware).
-** See Documentation/PCI/PCI-DMA-mapping.txt for interface definitions.
+** See Documentation/DMA-API-HOWTO.txt for interface definitions.
 **
 **      (c) Copyright 1999,2000 Hewlett-Packard Company
 **      (c) Copyright 2000 Grant Grundler
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma.h>    /* for DMA_CHUNK_SIZE */
diff -druNp linux-libre-3.1-gnu1/arch/parisc/kernel/setup.c linux-libre-3.2-gnu1/arch/parisc/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/parisc/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #undef PCI_DEBUG
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/pdc.h>
diff -druNp linux-libre-3.1-gnu1/arch/parisc/lib/iomap.c linux-libre-3.2-gnu1/arch/parisc/lib/iomap.c
--- linux-libre-3.1-gnu1/arch/parisc/lib/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/parisc/lib/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/io.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/charon.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/charon.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/charon.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/charon.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,236 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "anon,charon";
+	compatible = "anon,charon";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB
+	};
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			device_type = "dma-controller";
+			compatible = "fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		serial@2000 {		// PSC1
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		serial@2400 {		// PSC3
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2400 0x100>;
+			interrupts = <2 3 0>;
+		};
+
+		ethernet@3000 {
+			compatible = "fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			fixed-link = <1 1 100 0 0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+		};
+
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+
+			dtt@28 {
+				compatible = "national,lm80";
+				reg = <0x28>;
+			};
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+			};
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <	0 0 0xfc000000 0x02000000
+				1 0 0xe0000000 0x04000000 // CS1 range, SM501
+				3 0 0xe8000000 0x00080000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+		};
+
+		display@1,0 {
+			compatible = "smi,sm501";
+			reg = <1 0x00000000 0x00800000
+			       1 0x03e00000 0x00200000>;
+			mode = "640x480-32@60";
+			interrupts = <1 1 3>;
+			little-endian;
+		};
+
+		mram0@3,0 {
+			compatible = "mtd-ram";
+			reg = <3 0x00000 0x80000>;
+			bank-width = <1>;
+		};
+	};
+
+	pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+				 0xc000 0 0 2 &mpc5200_pic 0 0 3
+				 0xc000 0 0 3 &mpc5200_pic 0 0 3
+				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts	2012-01-04 18:55:44.000000000 -0500
@@ -23,19 +23,26 @@
 
 	soc5200@f0000000 {
 		timer@600 {	// General Purpose Timer
+			#gpio-cells = <2>;
 			fsl,has-wdt;
+			gpio-controller;
 		};
 
-		rtc@800 {
-			status = "disabled";
+		timer@610 {
+			#gpio-cells = <2>;
+			gpio-controller;
 		};
 
-		can@900 {
+		rtc@800 {
 			status = "disabled";
 		};
 
-		can@980 {
-			status = "disabled";
+		spi@f00 {
+			msp430@0 {
+				compatible = "spidev";
+				spi-max-frequency = <32000>;
+				reg = <0>;
+			};
 		};
 
 		psc@2000 {		// PSC1
@@ -73,11 +80,16 @@
 		};
 
 		i2c@3d00 {
-			rtc@50 {
+			eeprom@50 {
 				compatible = "at,24c08";
 				reg = <0x50>;
 			};
 
+			rtc@56 {
+				compatible = "mc,rv3029c2";
+				reg = <0x56>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1339";
 				reg = <0x68>;
@@ -90,11 +102,22 @@
 	};
 
 	pci@f0000d00 {
-		status = "disabled";
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+				 0xc000 0 0 2 &mpc5200_pic 0 0 3
+				 0xc000 0 0 3 &mpc5200_pic 0 0 3
+				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
 	};
 
 	localbus {
-		ranges = <0 0 0xff000000 0x1000000>;
+		ranges = <0 0 0xff000000 0x1000000
+			  4 0 0x60000000 0x0001000>;
 
 		// 16-bit flash device at LocalPlus Bus CS0
 		flash@0,0 {
@@ -122,5 +145,25 @@
 				reg = <0x00f00000 0x100000>;
 			};
 		};
+
+		can@4,0 {
+			compatible = "nxp,sja1000";
+			reg = <4 0x000 0x80>;
+			nxp,external-clock-frequency = <24000000>;
+			interrupts = <1 2 3>; // Level-low
+		};
+
+		can@4,100 {
+			compatible = "nxp,sja1000";
+			reg = <4 0x100 0x80>;
+			nxp,external-clock-frequency = <24000000>;
+			interrupts = <1 2 3>;  // Level-low
+		};
+
+		serial@4,200 {
+			compatible = "nxp,sc28l92";
+			reg = <4 0x200 0x10>;
+			interrupts = <1 3 3>;
+		};
 	};
 };
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_ppc9a.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_ppc9a.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_ppc9a.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_ppc9a.dts	2012-01-04 18:55:44.000000000 -0500
@@ -269,14 +269,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -290,25 +292,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_sbc310.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_sbc310.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_sbc310.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_sbc310.dts	2012-01-04 18:55:44.000000000 -0500
@@ -267,14 +267,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -288,25 +290,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_sbc610.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_sbc610.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/gef_sbc610.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/gef_sbc610.dts	2012-01-04 18:55:44.000000000 -0500
@@ -267,14 +267,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -288,25 +290,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/hcu4.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/hcu4.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/hcu4.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/hcu4.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/*
-* Device Tree Source for Netstal Maschinen HCU4
-* based on the IBM Walnut
-*
-* Copyright 2008
-* Niklaus Giger <niklaus.giger@member.fsf.org>
-*
-* Copyright 2007 IBM Corp.
-* Josh Boyer <jwboyer@linux.vnet.ibm.com>
-*
-* 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.
-*/
-
-/dts-v1/;
-
-/ {
-	#address-cells = <0x1>;
-	#size-cells = <0x1>;
-	model = "netstal,hcu4";
-	compatible = "netstal,hcu4";
-	dcr-parent = <0x1>;
-
-	aliases {
-		ethernet0 = "/plb/opb/ethernet@ef600800";
-		serial0 = "/plb/opb/serial@ef600300";
-	};
-
-	cpus {
-		#address-cells = <0x1>;
-		#size-cells = <0x0>;
-
-		cpu@0 {
-			device_type = "cpu";
-			model = "PowerPC,405GPr";
-			reg = <0x0>;
-			clock-frequency = <0>;		/* Filled in by U-Boot */
-			timebase-frequency = <0x0>;	/* Filled in by U-Boot */
-			i-cache-line-size = <0x20>;
-			d-cache-line-size = <0x20>;
-			i-cache-size = <0x4000>;
-			d-cache-size = <0x4000>;
-			dcr-controller;
-			dcr-access-method = "native";
-			linux,phandle = <0x1>;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x0 0x0>;	/* Filled in by U-Boot */
-	};
-
-	UIC0: interrupt-controller {
-		compatible = "ibm,uic";
-		interrupt-controller;
-		cell-index = <0x0>;
-		dcr-reg = <0xc0 0x9>;
-		#address-cells = <0x0>;
-		#size-cells = <0x0>;
-		#interrupt-cells = <0x2>;
-		linux,phandle = <0x2>;
-	};
-
-	plb {
-		compatible = "ibm,plb3";
-		#address-cells = <0x1>;
-		#size-cells = <0x1>;
-		ranges;
-		clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-		SDRAM0: memory-controller {
-			compatible = "ibm,sdram-405gp";
-			dcr-reg = <0x10 0x2>;
-		};
-
-		MAL: mcmal {
-			compatible = "ibm,mcmal-405gp", "ibm,mcmal";
-			dcr-reg = <0x180 0x62>;
-			num-tx-chans = <0x1>;
-			num-rx-chans = <0x1>;
-			interrupt-parent = <0x2>;
-			interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>;
-			linux,phandle = <0x3>;
-		};
-
-		POB0: opb {
-			compatible = "ibm,opb-405gp", "ibm,opb";
-			#address-cells = <0x1>;
-			#size-cells = <0x1>;
-			ranges = <0xef600000 0xef600000 0xa00000>;
-			dcr-reg = <0xa0 0x5>;
-			clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-			UART0: serial@ef600300 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600300 0x8>;
-				virtual-reg = <0xef600300>;
-				clock-frequency = <0x0>;/* Filled in by U-Boot */
-				current-speed = <0>;	/* Filled in by U-Boot */
-				interrupt-parent = <0x2>;
-				interrupts = <0x0 0x4>;
-			};
-
-			IIC: i2c@ef600500 {
-				compatible = "ibm,iic-405gp", "ibm,iic";
-				reg = <0xef600500 0x11>;
-				interrupt-parent = <0x2>;
-				interrupts = <0x2 0x4>;
-			};
-
-			GPIO: gpio@ef600700 {
-				compatible = "ibm,gpio-405gp";
-				reg = <0xef600700 0x20>;
-			};
-
-			EMAC: ethernet@ef600800 {
-				device_type = "network";
-				compatible = "ibm,emac-405gp", "ibm,emac";
-				interrupt-parent = <0x2>;
-				interrupts = <0xf 0x4 0x9 0x4>;
-				local-mac-address = [00 00 00 00 00 00];
-				reg = <0xef600800 0x70>;
-				mal-device = <0x3>;
-				mal-tx-channel = <0x0>;
-				mal-rx-channel = <0x0>;
-				cell-index = <0x0>;
-				max-frame-size = <0x5dc>;
-				rx-fifo-size = <0x1000>;
-				tx-fifo-size = <0x800>;
-				phy-mode = "rmii";
-				phy-map = <0x1>;
-			};
-		};
-
-		EBC0: ebc {
-			compatible = "ibm,ebc-405gp", "ibm,ebc";
-			dcr-reg = <0x12 0x2>;
-			#address-cells = <0x2>;
-			#size-cells = <0x1>;
-			clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-			sram@0,0 {
-				reg = <0x0 0x0 0x80000>;
-			};
-
-			flash@0,80000 {
-				compatible = "jedec-flash";
-				bank-width = <0x1>;
-				reg = <0x0 0x80000 0x80000>;
-				#address-cells = <0x1>;
-				#size-cells = <0x1>;
-
-				partition@0 {
-					label = "OpenBIOS";
-					reg = <0x0 0x80000>;
-					read-only;
-				};
-			};
-		};
-	};
-
-	chosen {
-		linux,stdout-path = "/plb/opb/serial@ef600300";
-	};
-};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/ksi8560.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/ksi8560.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/ksi8560.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/ksi8560.dts	2012-01-04 18:55:44.000000000 -0500
@@ -306,7 +306,7 @@
 	localbus@fdf05000 {
 		#address-cells = <2>;
 		#size-cells = <1>;
-		compatible = "fsl,mpc8560-localbus";
+		compatible = "fsl,mpc8560-localbus", "simple-bus";
 		reg = <0xfdf05000 0x68>;
 
 		ranges = <0x0 0x0 0xe0000000 0x00800000
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mgcoge.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mgcoge.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mgcoge.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mgcoge.dts	2012-01-04 18:55:44.000000000 -0500
@@ -213,6 +213,15 @@
 				linux,network-index = <2>;
 				fsl,cpm-command = <0x16200300>;
 			};
+
+			usb@11b60 {
+				compatible = "fsl,mpc8272-cpm-usb";
+				mode = "peripheral";
+				reg = <0x11b60 0x40 0x8b00 0x100>;
+				interrupts = <11 8>;
+				interrupt-parent = <&PIC>;
+				usb-clock = <5>;
+			};
 		};
 
 		cpm2_pio_c: gpio-controller@10d40 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -147,6 +147,8 @@
 		};
 
 		spi@f00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mpc8349emitx.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mpc8349emitx.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/mpc8349emitx.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/mpc8349emitx.dts	2012-01-04 18:55:44.000000000 -0500
@@ -390,7 +390,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc8349e-localbus",
-			     "fsl,pq2pro-localbus";
+			     "fsl,pq2pro-localbus",
+			     "simple-bus";
 		reg = <0xe0005000 0xd8>;
 		ranges = <0x0 0x0 0xfe000000 0x1000000	/* flash */
 			  0x1 0x0 0xf8000000 0x20000	/* VSC 7385 */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1010rdb.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1010rdb.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1010rdb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1010rdb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 		ethernet2 = &enet2;
 		pci0 = &pci0;
 		pci1 = &pci1;
+		can0 = &can0;
+		can1 = &can1;
 	};
 
 	memory {
@@ -169,14 +171,6 @@
 			};
 		};
 
-		can0@1c000 {
-			fsl,flexcan-clock-source = "platform";
-		};
-
-		can1@1d000 {
-			fsl,flexcan-clock-source = "platform";
-		};
-
 		usb@22000 {
 			phy_type = "utmi";
 		};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1010si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1010si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1010si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1010si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -140,20 +140,18 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		can0@1c000 {
-			compatible = "fsl,flexcan-v1.0";
+		can0: can@1c000 {
+			compatible = "fsl,p1010-flexcan";
 			reg = <0x1c000 0x1000>;
 			interrupts = <48 0x2>;
 			interrupt-parent = <&mpic>;
-			fsl,flexcan-clock-divider = <2>;
 		};
 
-		can1@1d000 {
-			compatible = "fsl,flexcan-v1.0";
+		can1: can@1d000 {
+			compatible = "fsl,p1010-flexcan";
 			reg = <0x1d000 0x1000>;
 			interrupts = <61 0x2>;
 			interrupt-parent = <&mpic>;
-			fsl,flexcan-clock-divider = <2>;
 		};
 
 		L2: l2-cache-controller@20000 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1022ds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1022ds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1022ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1022ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -150,7 +150,7 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p1022ds-pixis";
+			compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
 			reg = <3 0 0x30>;
 			interrupt-parent = <&mpic>;
 			/*
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1023rds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1023rds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p1023rds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p1023rds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -449,6 +449,7 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/* IRQ[0:3] are pulled up on board, set to active-low */
 			interrupt-map = <
 				/* IDSEL 0x0 */
 				0000 0 0 1 &mpic 0 1
@@ -488,11 +489,15 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/*
+			 * IRQ[4:6] only for PCIe, set to active-high,
+			 * IRQ[7] is pulled up on board, set to active-low
+			 */
 			interrupt-map = <
 				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 4 1
-				0000 0 0 2 &mpic 5 1
-				0000 0 0 3 &mpic 6 1
+				0000 0 0 1 &mpic 4 2
+				0000 0 0 2 &mpic 5 2
+				0000 0 0 3 &mpic 6 2
 				0000 0 0 4 &mpic 7 1
 				>;
 			ranges = <0x2000000 0x0 0xa0000000
@@ -527,12 +532,16 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/*
+			 * IRQ[8:10] are pulled up on board, set to active-low
+			 * IRQ[11] only for PCIe, set to active-high,
+			 */
 			interrupt-map = <
 				/* IDSEL 0x0 */
 				0000 0 0 1 &mpic 8 1
 				0000 0 0 2 &mpic 9 1
 				0000 0 0 3 &mpic 10 1
-				0000 0 0 4 &mpic 11 1
+				0000 0 0 4 &mpic 11 2
 				>;
 			ranges = <0x2000000 0x0 0x80000000
 				  0x2000000 0x0 0x80000000
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2020ds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2020ds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2020ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2020ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -118,6 +118,11 @@
 			};
 		};
 
+		board-control@3,0 {
+			compatible = "fsl,p2020ds-fpga", "fsl,fpga-ngpixis";
+			reg = <0x3 0x0 0x30>;
+		};
+
 		nand@4,0 {
 			compatible = "fsl,elbc-fcm-nand";
 			reg = <0x4 0x0 0x40000>;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2040rdb.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2040rdb.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2040rdb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2040rdb.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,166 +0,0 @@
-/*
- * P2040RDB Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/include/ "p2040si.dtsi"
-
-/ {
-	model = "fsl,P2040RDB";
-	compatible = "fsl,P2040RDB";
-	#address-cells = <2>;
-	#size-cells = <2>;
-	interrupt-parent = <&mpic>;
-
-	memory {
-		device_type = "memory";
-	};
-
-	soc: soc@ffe000000 {
-		spi@110000 {
-			flash@0 {
-				#address-cells = <1>;
-				#size-cells = <1>;
-				compatible = "spansion,s25sl12801";
-				reg = <0>;
-				spi-max-frequency = <40000000>; /* input clock */
-				partition@u-boot {
-					label = "u-boot";
-					reg = <0x00000000 0x00100000>;
-					read-only;
-				};
-				partition@kernel {
-					label = "kernel";
-					reg = <0x00100000 0x00500000>;
-					read-only;
-				};
-				partition@dtb {
-					label = "dtb";
-					reg = <0x00600000 0x00100000>;
-					read-only;
-				};
-				partition@fs {
-					label = "file system";
-					reg = <0x00700000 0x00900000>;
-				};
-			};
-		};
-
-		i2c@118000 {
-			lm75b@48 {
-				compatible = "nxp,lm75a";
-				reg = <0x48>;
-			};
-			eeprom@50 {
-				compatible = "at24,24c256";
-				reg = <0x50>;
-			};
-			rtc@68 {
-				compatible = "pericom,pt7c4338";
-				reg = <0x68>;
-			};
-		};
-
-		i2c@118100 {
-			eeprom@50 {
-				compatible = "at24,24c256";
-				reg = <0x50>;
-			};
-		};
-
-		usb0: usb@210000 {
-			phy_type = "utmi";
-		};
-
-		usb1: usb@211000 {
-			dr_mode = "host";
-			phy_type = "utmi";
-		};
-	};
-
-	localbus@ffe124000 {
-		reg = <0xf 0xfe124000 0 0x1000>;
-		ranges = <0 0 0xf 0xe8000000 0x08000000>;
-
-		flash@0,0 {
-			compatible = "cfi-flash";
-			reg = <0 0 0x08000000>;
-			bank-width = <2>;
-			device-width = <2>;
-		};
-	};
-
-	pci0: pcie@ffe200000 {
-		reg = <0xf 0xfe200000 0 0x1000>;
-		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
-			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-
-	pci1: pcie@ffe201000 {
-		reg = <0xf 0xfe201000 0 0x1000>;
-		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
-			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-
-	pci2: pcie@ffe202000 {
-		reg = <0xf 0xfe202000 0 0x1000>;
-		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
-			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2040si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2040si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2040si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2040si.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,623 +0,0 @@
-/*
- * P2040 Silicon Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/dts-v1/;
-
-/ {
-	compatible = "fsl,P2040";
-	#address-cells = <2>;
-	#size-cells = <2>;
-	interrupt-parent = <&mpic>;
-
-	aliases {
-		ccsr = &soc;
-
-		serial0 = &serial0;
-		serial1 = &serial1;
-		serial2 = &serial2;
-		serial3 = &serial3;
-		pci0 = &pci0;
-		pci1 = &pci1;
-		pci2 = &pci2;
-		usb0 = &usb0;
-		usb1 = &usb1;
-		dma0 = &dma0;
-		dma1 = &dma1;
-		sdhc = &sdhc;
-		msi0 = &msi0;
-		msi1 = &msi1;
-		msi2 = &msi2;
-
-		crypto = &crypto;
-		sec_jr0 = &sec_jr0;
-		sec_jr1 = &sec_jr1;
-		sec_jr2 = &sec_jr2;
-		sec_jr3 = &sec_jr3;
-		rtic_a = &rtic_a;
-		rtic_b = &rtic_b;
-		rtic_c = &rtic_c;
-		rtic_d = &rtic_d;
-		sec_mon = &sec_mon;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: PowerPC,e500mc@0 {
-			device_type = "cpu";
-			reg = <0>;
-			next-level-cache = <&L2_0>;
-			L2_0: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu1: PowerPC,e500mc@1 {
-			device_type = "cpu";
-			reg = <1>;
-			next-level-cache = <&L2_1>;
-			L2_1: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu2: PowerPC,e500mc@2 {
-			device_type = "cpu";
-			reg = <2>;
-			next-level-cache = <&L2_2>;
-			L2_2: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu3: PowerPC,e500mc@3 {
-			device_type = "cpu";
-			reg = <3>;
-			next-level-cache = <&L2_3>;
-			L2_3: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-	};
-
-	soc: soc@ffe000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "soc";
-		compatible = "simple-bus";
-		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
-		reg = <0xf 0xfe000000 0 0x00001000>;
-
-		soc-sram-error {
-			compatible = "fsl,soc-sram-error";
-			interrupts = <16 2 1 29>;
-		};
-
-		corenet-law@0 {
-			compatible = "fsl,corenet-law";
-			reg = <0x0 0x1000>;
-			fsl,num-laws = <32>;
-		};
-
-		memory-controller@8000 {
-			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
-			reg = <0x8000 0x1000>;
-			interrupts = <16 2 1 23>;
-		};
-
-		cpc: l3-cache-controller@10000 {
-			compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
-			reg = <0x10000 0x1000>;
-			interrupts = <16 2 1 27>;
-		};
-
-		corenet-cf@18000 {
-			compatible = "fsl,corenet-cf";
-			reg = <0x18000 0x1000>;
-			interrupts = <16 2 1 31>;
-			fsl,ccf-num-csdids = <32>;
-			fsl,ccf-num-snoopids = <32>;
-		};
-
-		iommu@20000 {
-			compatible = "fsl,pamu-v1.0", "fsl,pamu";
-			reg = <0x20000 0x4000>;
-			interrupts = <
-				24 2 0 0
-				16 2 1 30>;
-		};
-
-		mpic: pic@40000 {
-			clock-frequency = <0>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <4>;
-			reg = <0x40000 0x40000>;
-			compatible = "fsl,mpic", "chrp,open-pic";
-			device_type = "open-pic";
-		};
-
-		msi0: msi@41600 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41600 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xe0 0 0 0
-				0xe1 0 0 0
-				0xe2 0 0 0
-				0xe3 0 0 0
-				0xe4 0 0 0
-				0xe5 0 0 0
-				0xe6 0 0 0
-				0xe7 0 0 0>;
-		};
-
-		msi1: msi@41800 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41800 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xe8 0 0 0
-				0xe9 0 0 0
-				0xea 0 0 0
-				0xeb 0 0 0
-				0xec 0 0 0
-				0xed 0 0 0
-				0xee 0 0 0
-				0xef 0 0 0>;
-		};
-
-		msi2: msi@41a00 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41a00 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xf0 0 0 0
-				0xf1 0 0 0
-				0xf2 0 0 0
-				0xf3 0 0 0
-				0xf4 0 0 0
-				0xf5 0 0 0
-				0xf6 0 0 0
-				0xf7 0 0 0>;
-		};
-
-		guts: global-utilities@e0000 {
-			compatible = "fsl,qoriq-device-config-1.0";
-			reg = <0xe0000 0xe00>;
-			fsl,has-rstcr;
-			#sleep-cells = <1>;
-			fsl,liodn-bits = <12>;
-		};
-
-		pins: global-utilities@e0e00 {
-			compatible = "fsl,qoriq-pin-control-1.0";
-			reg = <0xe0e00 0x200>;
-			#sleep-cells = <2>;
-		};
-
-		clockgen: global-utilities@e1000 {
-			compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
-			reg = <0xe1000 0x1000>;
-			clock-frequency = <0>;
-		};
-
-		rcpm: global-utilities@e2000 {
-			compatible = "fsl,qoriq-rcpm-1.0";
-			reg = <0xe2000 0x1000>;
-			#sleep-cells = <1>;
-		};
-
-		sfp: sfp@e8000 {
-			compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
-			reg	   = <0xe8000 0x1000>;
-		};
-
-		serdes: serdes@ea000 {
-			compatible = "fsl,p2040-serdes";
-			reg	   = <0xea000 0x1000>;
-		};
-
-		dma0: dma@100300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
-			reg = <0x100300 0x4>;
-			ranges = <0x0 0x100100 0x200>;
-			cell-index = <0>;
-			dma-channel@0 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupts = <28 2 0 0>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupts = <29 2 0 0>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupts = <30 2 0 0>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupts = <31 2 0 0>;
-			};
-		};
-
-		dma1: dma@101300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
-			reg = <0x101300 0x4>;
-			ranges = <0x0 0x101100 0x200>;
-			cell-index = <1>;
-			dma-channel@0 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupts = <32 2 0 0>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupts = <33 2 0 0>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupts = <34 2 0 0>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupts = <35 2 0 0>;
-			};
-		};
-
-		spi@110000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
-			reg = <0x110000 0x1000>;
-			interrupts = <53 0x2 0 0>;
-			fsl,espi-num-chipselects = <4>;
-
-		};
-
-		sdhc: sdhc@114000 {
-			compatible = "fsl,p2040-esdhc", "fsl,esdhc";
-			reg = <0x114000 0x1000>;
-			interrupts = <48 2 0 0>;
-			sdhci,auto-cmd12;
-			clock-frequency = <0>;
-		};
-
-
-		i2c@118000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x118000 0x100>;
-			interrupts = <38 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@118100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <1>;
-			compatible = "fsl-i2c";
-			reg = <0x118100 0x100>;
-			interrupts = <38 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@119000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <2>;
-			compatible = "fsl-i2c";
-			reg = <0x119000 0x100>;
-			interrupts = <39 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@119100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <3>;
-			compatible = "fsl-i2c";
-			reg = <0x119100 0x100>;
-			interrupts = <39 2 0 0>;
-			dfsrr;
-		};
-
-		serial0: serial@11c500 {
-			cell-index = <0>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2 0 0>;
-		};
-
-		serial1: serial@11c600 {
-			cell-index = <1>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2 0 0>;
-		};
-
-		serial2: serial@11d500 {
-			cell-index = <2>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2 0 0>;
-		};
-
-		serial3: serial@11d600 {
-			cell-index = <3>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2 0 0>;
-		};
-
-		gpio0: gpio@130000 {
-			compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
-			reg = <0x130000 0x1000>;
-			interrupts = <55 2 0 0>;
-			#gpio-cells = <2>;
-			gpio-controller;
-		};
-
-		usb0: usb@210000 {
-			compatible = "fsl,p2040-usb2-mph",
-					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
-			reg = <0x210000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <44 0x2 0 0>;
-			port0;
-		};
-
-		usb1: usb@211000 {
-			compatible = "fsl,p2040-usb2-dr",
-					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
-			reg = <0x211000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <45 0x2 0 0>;
-		};
-
-		sata@220000 {
-			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
-			reg = <0x220000 0x1000>;
-			interrupts = <68 0x2 0 0>;
-		};
-
-		sata@221000 {
-			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
-			reg = <0x221000 0x1000>;
-			interrupts = <69 0x2 0 0>;
-		};
-
-		crypto: crypto@300000 {
-			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x300000 0x10000>;
-			ranges = <0 0x300000 0x10000>;
-			interrupts = <92 2 0 0>;
-
-			sec_jr0: jr@1000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x1000 0x1000>;
-				interrupts = <88 2 0 0>;
-			};
-
-			sec_jr1: jr@2000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x2000 0x1000>;
-				interrupts = <89 2 0 0>;
-			};
-
-			sec_jr2: jr@3000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x3000 0x1000>;
-				interrupts = <90 2 0 0>;
-			};
-
-			sec_jr3: jr@4000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x4000 0x1000>;
-				interrupts = <91 2 0 0>;
-			};
-
-			rtic@6000 {
-				compatible = "fsl,sec-v4.2-rtic",
-					     "fsl,sec-v4.0-rtic";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x6000 0x100>;
-				ranges = <0x0 0x6100 0xe00>;
-
-				rtic_a: rtic-a@0 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x00 0x20 0x100 0x80>;
-				};
-
-				rtic_b: rtic-b@20 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x20 0x20 0x200 0x80>;
-				};
-
-				rtic_c: rtic-c@40 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x40 0x20 0x300 0x80>;
-				};
-
-				rtic_d: rtic-d@60 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x60 0x20 0x500 0x80>;
-				};
-			};
-		};
-
-		sec_mon: sec_mon@314000 {
-			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
-			reg = <0x314000 0x1000>;
-			interrupts = <93 2 0 0>;
-		};
-
-	};
-
-	localbus@ffe124000 {
-		compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
-		interrupts = <25 2 0 0>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-	};
-
-	pci0: pcie@ffe200000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0x0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi0>;
-		interrupts = <16 2 1 15>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 15>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 40 1 0 0
-				0000 0 0 2 &mpic 1 1 0 0
-				0000 0 0 3 &mpic 2 1 0 0
-				0000 0 0 4 &mpic 3 1 0 0
-				>;
-		};
-	};
-
-	pci1: pcie@ffe201000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi1>;
-		interrupts = <16 2 1 14>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 14>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 41 1 0 0
-				0000 0 0 2 &mpic 5 1 0 0
-				0000 0 0 3 &mpic 6 1 0 0
-				0000 0 0 4 &mpic 7 1 0 0
-				>;
-		};
-	};
-
-	pci2: pcie@ffe202000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0x0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi2>;
-		interrupts = <16 2 1 13>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 13>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 42 1 0 0
-				0000 0 0 2 &mpic 9 1 0 0
-				0000 0 0 3 &mpic 10 1 0 0
-				0000 0 0 4 &mpic 11 1 0 0
-				>;
-		};
-	};
-};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2041rdb.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2041rdb.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2041rdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2041rdb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,165 @@
+/*
+ * P2041RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p2041si.dtsi"
+
+/ {
+	model = "fsl,P2041RDB";
+	compatible = "fsl,P2041RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118000 {
+			lm75b@48 {
+				compatible = "nxp,lm75a";
+				reg = <0x48>;
+			};
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+			rtc@68 {
+				compatible = "pericom,pt7c4338";
+				reg = <0x68>;
+			};
+		};
+
+		i2c@118100 {
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+		};
+
+		usb1: usb@211000 {
+			dr_mode = "host";
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2041si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2041si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p2041si.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p2041si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,692 @@
+/*
+ * P2041 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P2041";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,e500mc@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,e500mc@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		ddr: memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x4000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p2041-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p2041-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p2041-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p2041-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p2041-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			phy_type = "utmi";
+			port0;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p2041-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+			phy_type = "utmi";
+		};
+
+		sata@220000 {
+			compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+		};
+
+		sata@221000 {
+			compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupts = <93 2 0 0>;
+		};
+
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3041ds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3041ds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3041ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3041ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -147,8 +151,8 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p3041ds-pixis";
-			reg = <3 0 0x20>;
+			compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
 		};
 	};
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3041si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3041si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3041si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3041si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -114,6 +115,74 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p43041-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p43041-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p43041-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p43041-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -133,7 +202,7 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3060qds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3060qds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3060qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3060qds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,238 @@
+/*
+ * P3060QDS Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p3060si.dtsi"
+
+/ {
+	model = "fsl,P3060QDS";
+	compatible = "fsl,P3060QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+			flash@1 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,en25q32b";
+				reg = <1>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi1 {
+					label = "spi1";
+					reg = <0x00000000 0x00400000>;
+				};
+			};
+			flash@2 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at45db081d";
+				reg = <2>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi1 {
+					label = "spi2";
+					reg = <0x00000000 0x00100000>;
+				};
+			};
+			flash@3 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,sst25wf040";
+				reg = <3>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi3 {
+					label = "spi3";
+					reg = <0x00000000 0x00080000>;
+				};
+			};
+		};
+
+		i2c@118000 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@53 {
+				compatible = "at24,24c256";
+				reg = <0x53>;
+			};
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+
+		usb0: usb@210000 {
+			phy_type = "ulpi";
+		};
+
+		usb1: usb@211000 {
+			dr_mode = "host";
+			phy_type = "ulpi";
+		};
+	};
+
+	rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xffa00000 0x00040000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			partition@0 {
+				label = "NAND U-Boot Image";
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			partition@2000000 {
+				label = "NAND Root File System";
+				reg = <0x02000000 0x10000000>;
+			};
+
+			partition@12000000 {
+				label = "NAND Compressed RFS Image";
+				reg = <0x12000000 0x08000000>;
+			};
+
+			partition@1a000000 {
+				label = "NAND Linux Kernel Image";
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			partition@1e000000 {
+				label = "NAND DTB Image";
+				reg = <0x1e000000 0x01000000>;
+			};
+
+			partition@1f000000 {
+				label = "NAND Writable User area";
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,p3060qds-fpga", "fsl,fpga-qixis";
+			reg = <3 0 0x100>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3060si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3060si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p3060si.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p3060si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,719 @@
+/*
+ * P3060 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P3060";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu4: PowerPC,e500mc@4 {
+			device_type = "cpu";
+			reg = <4>;
+			next-level-cache = <&L2_4>;
+			L2_4: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu5: PowerPC,e500mc@5 {
+			device_type = "cpu";
+			reg = <5>;
+			next-level-cache = <&L2_5>;
+			L2_5: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu6: PowerPC,e500mc@6 {
+			device_type = "cpu";
+			reg = <6>;
+			next-level-cache = <&L2_6>;
+			L2_6: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu7: PowerPC,e500mc@7 {
+			device_type = "cpu";
+			reg = <7>;
+			next-level-cache = <&L2_7>;
+			L2_7: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p3060-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p3060-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p3060-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p3060-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@44000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu4>;
+			reg = <0x44000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@45000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu5>;
+			reg = <0x45000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@46000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu6>;
+			reg = <0x46000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@47000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu7>;
+			reg = <0x47000 0x1000>;
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		ddr: memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p3060-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000
+			       0x11000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x5000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		rmu: rmu@d3000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,srio-rmu";
+			reg = <0xd3000 0x500>;
+			ranges = <0x0 0xd3000 0x500>;
+
+			message-unit@0 {
+				compatible = "fsl,srio-msg-unit";
+				reg = <0x0 0x100>;
+				interrupts = <
+					60 2 0 0  /* msg1_tx_irq */
+					61 2 0 0>;/* msg1_rx_irq */
+			};
+			message-unit@100 {
+				compatible = "fsl,srio-msg-unit";
+				reg = <0x100 0x100>;
+				interrupts = <
+					62 2 0 0  /* msg2_tx_irq */
+					63 2 0 0>;/* msg2_rx_irq */
+			};
+			doorbell-unit@400 {
+				compatible = "fsl,srio-dbell-unit";
+				reg = <0x400 0x80>;
+				interrupts = <
+					56 2 0 0  /* bell_outb_irq */
+					57 2 0 0>;/* bell_inb_irq */
+			};
+			port-write-unit@4e0 {
+				compatible = "fsl,srio-port-write-unit";
+				reg = <0x4e0 0x20>;
+				interrupts = <16 2 1 11>;
+			};
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p3060-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p3060-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p3060-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p3060-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p3060-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p3060-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p3060-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.1", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.1-rtic", "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.1-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <93 2 0 0>;
+		};
+	};
+
+	rapidio@ffe0c0000 {
+		compatible = "fsl,srio";
+		interrupts = <16 2 1 11>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		fsl,srio-rmu-handle = <&rmu>;
+		ranges;
+
+		port1 {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			cell-index = <1>;
+		};
+
+		port2 {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			cell-index = <2>;
+		};
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p3060-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p4080ds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p4080ds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p4080ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p4080ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -108,7 +112,8 @@
 
 	localbus@ffe124000 {
 		reg = <0xf 0xfe124000 0 0x1000>;
-		ranges = <0 0 0xf 0xe8000000 0x08000000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  3 0 0xf 0xffdf0000 0x00008000>;
 
 		flash@0,0 {
 			compatible = "cfi-flash";
@@ -116,6 +121,11 @@
 			bank-width = <2>;
 			device-width = <2>;
 		};
+
+		board-control@3,0 {
+			compatible = "fsl,p4080ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
+		};
 	};
 
 	pci0: pcie@ffe200000 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p4080si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p4080si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p4080si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p4080si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -77,7 +78,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu0: PowerPC,4080@0 {
+		cpu0: PowerPC,e500mc@0 {
 			device_type = "cpu";
 			reg = <0>;
 			next-level-cache = <&L2_0>;
@@ -85,7 +86,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu1: PowerPC,4080@1 {
+		cpu1: PowerPC,e500mc@1 {
 			device_type = "cpu";
 			reg = <1>;
 			next-level-cache = <&L2_1>;
@@ -93,7 +94,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu2: PowerPC,4080@2 {
+		cpu2: PowerPC,e500mc@2 {
 			device_type = "cpu";
 			reg = <2>;
 			next-level-cache = <&L2_2>;
@@ -101,7 +102,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu3: PowerPC,4080@3 {
+		cpu3: PowerPC,e500mc@3 {
 			device_type = "cpu";
 			reg = <3>;
 			next-level-cache = <&L2_3>;
@@ -109,7 +110,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu4: PowerPC,4080@4 {
+		cpu4: PowerPC,e500mc@4 {
 			device_type = "cpu";
 			reg = <4>;
 			next-level-cache = <&L2_4>;
@@ -117,7 +118,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu5: PowerPC,4080@5 {
+		cpu5: PowerPC,e500mc@5 {
 			device_type = "cpu";
 			reg = <5>;
 			next-level-cache = <&L2_5>;
@@ -125,7 +126,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu6: PowerPC,4080@6 {
+		cpu6: PowerPC,e500mc@6 {
 			device_type = "cpu";
 			reg = <6>;
 			next-level-cache = <&L2_6>;
@@ -133,7 +134,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu7: PowerPC,4080@7 {
+		cpu7: PowerPC,e500mc@7 {
 			device_type = "cpu";
 			reg = <7>;
 			next-level-cache = <&L2_7>;
@@ -143,6 +144,99 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-ddr@13000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr2>;
+			reg = <0x13000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@44000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu4>;
+			reg = <0x44000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@45000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu5>;
+			reg = <0x45000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@46000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu6>;
+			reg = <0x46000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@47000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu7>;
+			reg = <0x47000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -162,13 +256,13 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr1: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
 		};
 
-		memory-controller@9000 {
+		ddr2: memory-controller@9000 {
 			compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
 			reg = <0x9000 0x1000>;
 			interrupts = <16 2 1 22>;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p5020ds.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p5020ds.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p5020ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p5020ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -147,8 +151,8 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p5020ds-pixis";
-			reg = <3 0 0x20>;
+			compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
 		};
 	};
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p5020si.dtsi linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p5020si.dtsi
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/p5020si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/p5020si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -98,6 +99,69 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-ddr@13000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr2>;
+			reg = <0x13000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -117,13 +181,13 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr1: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
 		};
 
-		memory-controller@9000 {
+		ddr2: memory-controller@9000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x9000 0x1000>;
 			interrupts = <16 2 1 22>;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/sbc8560.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/sbc8560.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/sbc8560.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/sbc8560.dts	2012-01-04 18:55:44.000000000 -0500
@@ -331,7 +331,7 @@
 	};
 
 	localbus@ff705000 {
-		compatible = "fsl,mpc8560-localbus";
+		compatible = "fsl,mpc8560-localbus", "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xff705000 0x100>;	// BRx, ORx, etc.
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/dts/yosemite.dts linux-libre-3.2-gnu1/arch/powerpc/boot/dts/yosemite.dts
--- linux-libre-3.1-gnu1/arch/powerpc/boot/dts/yosemite.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/dts/yosemite.dts	2012-01-04 18:55:44.000000000 -0500
@@ -138,6 +138,42 @@
 				clock-frequency = <0>; /* Filled in by zImage */
 				interrupts = <0x5 0x1>;
 				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl256n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x04000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "ramdisk";
+						reg = <0x00200000 0x01400000>;
+					};
+					partition@1600000 {
+						label = "jffs2";
+						reg = <0x01600000 0x00400000>;
+					};
+					partition@1a00000 {
+						label = "user";
+						reg = <0x01a00000 0x02540000>;
+					};
+					partition@3f40000 {
+						label = "env";
+						reg = <0x03f40000 0x00040000>;
+					};
+					partition@3f80000 {
+						label = "u-boot";
+						reg = <0x03f80000 0x00080000>;
+					};
+				};
 			};
 
 			UART0: serial@ef600300 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/boot/Makefile linux-libre-3.2-gnu1/arch/powerpc/boot/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -58,7 +58,7 @@ $(addprefix $(obj)/,$(zlib) cuboot-c2k.o
 libfdt       := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 libfdtheader := fdt.h libfdt.h libfdt_internal.h
 
-$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
 	$(addprefix $(obj)/,$(libfdtheader))
 
 src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
@@ -171,6 +171,7 @@ quiet_cmd_wrap	= WRAP    $@
 		$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
 
 image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
+image-$(CONFIG_PPC_POWERNV)		+= zImage.pseries
 image-$(CONFIG_PPC_MAPLE)		+= zImage.maple
 image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
 image-$(CONFIG_PPC_PS3)			+= dtbImage.ps3
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/acadia_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/acadia_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/acadia_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/acadia_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,12 +44,13 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/ep405_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/ep405_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/ep405_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/ep405_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/hcu4_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/hcu4_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/hcu4_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/hcu4_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-CONFIG_40x=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_HCU4=y
-# CONFIG_WALNUT is not set
-CONFIG_SPARSE_IRQ=y
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=m
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=35000
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/kilauea_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/kilauea_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/kilauea_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/kilauea_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -51,10 +51,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/makalu_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/makalu_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/makalu_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/makalu_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -43,10 +43,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/40x/walnut_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/40x/walnut_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/40x/walnut_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/40x/walnut_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/arches_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/arches_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/arches_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/arches_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/bamboo_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/bamboo_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/bamboo_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/bamboo_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/bluestone_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/bluestone_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/bluestone_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/bluestone_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -38,10 +38,11 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -49,10 +49,11 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/ebony_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/ebony_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/ebony_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/ebony_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/eiger_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/eiger_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/eiger_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/eiger_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -55,10 +55,11 @@ CONFIG_FUSION=y
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/icon_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/icon_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/icon_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/icon_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -56,8 +56,9 @@ CONFIG_FUSION_SAS=y
 CONFIG_FUSION_CTL=y
 CONFIG_FUSION_LOGGING=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/katmai_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/katmai_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/katmai_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/katmai_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/redwood_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/redwood_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/redwood_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/redwood_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,12 @@ CONFIG_FUSION=y
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,8 +44,9 @@ CONFIG_ATA=y
 # CONFIG_SATA_PMP is not set
 CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_INPUT_FF_MEMLESS=m
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/sequoia_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/sequoia_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/sequoia_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/sequoia_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -46,8 +46,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/taishan_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/taishan_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/taishan_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/taishan_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/44x/warp_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/44x/warp_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/44x/warp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/44x/warp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -54,9 +54,10 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,10 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -38,17 +38,18 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC_MPC52xx=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
 CONFIG_SERIAL_MPC52xx=y
 CONFIG_SERIAL_MPC52xx_CONSOLE=y
 CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
@@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=11520
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
 CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/85xx/p1023rds_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/85xx/p1023rds_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/85xx/p1023rds_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/85xx/p1023rds_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@ CONFIG_P1023_RDS=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_XES_MPC85xx=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SPARSE_IRQ=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/corenet32_smp_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/corenet32_smp_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/corenet32_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/corenet32_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
@@ -23,8 +21,9 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_P2040_RDB=y
+CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
+CONFIG_P3060_QDS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
@@ -69,7 +68,6 @@ CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -107,7 +105,6 @@ CONFIG_FSL_PQ_MDIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -136,8 +133,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -146,7 +141,6 @@ CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_VIRT_DRIVERS=y
 CONFIG_FSL_HV_MANAGER=y
 CONFIG_EXT2_FS=y
@@ -173,7 +167,6 @@ CONFIG_MAC_PARTITION=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/corenet64_smp_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/corenet64_smp_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/corenet64_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/corenet64_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -25,7 +23,6 @@ CONFIG_P5020_DS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
-# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -93,10 +90,8 @@ CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=m
 CONFIG_FRAME_WARN=1024
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/mgcoge_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/mgcoge_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/mgcoge_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/mgcoge_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,22 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
+# CONFIG_RD_GZIP is not set
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
@@ -24,11 +31,10 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
+CONFIG_TIPC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
@@ -42,7 +48,6 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -50,6 +55,7 @@ CONFIG_FS_ENET=y
 CONFIG_FS_ENET_MDIO_FCC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -57,24 +63,24 @@ CONFIG_SERIAL_CPM=y
 CONFIG_SERIAL_CPM_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_POWERMAC is not set
 CONFIG_I2C_CPM=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_G_SERIAL=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
 CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -82,7 +88,6 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/mpc512x_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/mpc512x_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/mpc512x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/mpc512x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,10 +13,11 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
 CONFIG_MPC5121_ADS=y
+CONFIG_MPC5121_GENERIC=y
+CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_NO_HZ=y
 CONFIG_HZ_1000=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_MIGRATION is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_PCI is not set
@@ -35,18 +36,16 @@ CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
 CONFIG_CAN_VCAN=y
-CONFIG_CAN_DEV=y
 CONFIG_CAN_MSCAN=y
 CONFIG_CAN_DEBUG_DEVICES=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_XIP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -99,10 +99,14 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=11520
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_MPC512x_PSC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
 CONFIG_VIDEO_ADV_DEBUG=y
 # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
 CONFIG_VIDEO_SAA711X=y
@@ -132,6 +136,5 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/mpc5200_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/mpc5200_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/mpc5200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/mpc5200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,18 @@ CONFIG_FB_RADEON=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_PPC is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MPC5200_I2S=y
+CONFIG_SND_MPC52xx_SOC_PCM030=y
+CONFIG_SND_MPC52xx_SOC_EFIKA=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/mpc85xx_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/mpc85xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/mpc85xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,10 +10,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -41,7 +39,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -123,6 +120,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -206,7 +204,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -42,7 +40,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -124,6 +121,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -207,10 +205,8 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/ppc40x_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/ppc40x_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/ppc40x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/ppc40x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC4xx_GPIO=y
 CONFIG_ACADIA=y
 CONFIG_EP405=y
-CONFIG_HCU4=y
 CONFIG_HOTFOOT=y
 CONFIG_KILAUEA=y
 CONFIG_MAKALU=y
@@ -50,8 +49,9 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_XILINX_SYSACE=m
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/ppc44x_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/ppc44x_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/ppc44x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/ppc44x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -52,6 +52,8 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_NDFC=m
 CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_PROC_DEVICETREE=y
@@ -63,8 +65,9 @@ CONFIG_BLK_DEV_SD=m
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/ppc64_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/ppc64_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/ppc64_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/ppc64_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -485,3 +485,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/ppc6xx_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/ppc6xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/ppc6xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@ CONFIG_TAU_AVERAGE=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_PPC_BESTCOMM=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_MCU_MPC8349EMITX=m
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/configs/pseries_defconfig linux-libre-3.2-gnu1/arch/powerpc/configs/pseries_defconfig
--- linux-libre-3.1-gnu1/arch/powerpc/configs/pseries_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/configs/pseries_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -362,3 +362,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/atomic.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/atomic.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,13 +49,13 @@ static __inline__ int atomic_add_return(
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2		# atomic_add_return\n\
 	add	%0,%1,%0\n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -85,13 +85,13 @@ static __inline__ int atomic_sub_return(
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2		# atomic_sub_return\n\
 	subf	%0,%1,%0\n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -119,13 +119,13 @@ static __inline__ int atomic_inc_return(
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_inc_return\n\
 	addic	%0,%0,1\n"
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -163,13 +163,13 @@ static __inline__ int atomic_dec_return(
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_dec_return\n\
 	addic	%0,%0,-1\n"
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -194,7 +194,7 @@ static __inline__ int __atomic_add_unles
 	int t;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpw	0,%0,%3 \n\
 	beq-	2f \n\
@@ -202,7 +202,7 @@ static __inline__ int __atomic_add_unles
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%1 \n\
 	bne-	1b \n"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 "	subf	%0,%2,%0 \n\
 2:"
 	: "=&r" (t)
@@ -226,7 +226,7 @@ static __inline__ int atomic_dec_if_posi
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_dec_if_positive\n\
 	cmpwi	%0,1\n\
 	addi	%0,%0,-1\n\
@@ -234,7 +234,7 @@ static __inline__ int atomic_dec_if_posi
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"	: "=&b" (t)
 	: "r" (&v->counter)
@@ -285,12 +285,12 @@ static __inline__ long atomic64_add_retu
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2		# atomic64_add_return\n\
 	add	%0,%1,%0\n\
 	stdcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -319,12 +319,12 @@ static __inline__ long atomic64_sub_retu
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2		# atomic64_sub_return\n\
 	subf	%0,%1,%0\n\
 	stdcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -351,12 +351,12 @@ static __inline__ long atomic64_inc_retu
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_inc_return\n\
 	addic	%0,%0,1\n\
 	stdcx.	%0,0,%1 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -393,12 +393,12 @@ static __inline__ long atomic64_dec_retu
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_dec_return\n\
 	addic	%0,%0,-1\n\
 	stdcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -418,13 +418,13 @@ static __inline__ long atomic64_dec_if_p
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_dec_if_positive\n\
 	addic.	%0,%0,-1\n\
 	blt-	2f\n\
 	stdcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"	: "=&r" (t)
 	: "r" (&v->counter)
@@ -450,14 +450,14 @@ static __inline__ int atomic64_add_unles
 	long t;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpd	0,%0,%3 \n\
 	beq-	2f \n\
 	add	%0,%2,%0 \n"
 "	stdcx.	%0,0,%1 \n\
 	bne-	1b \n"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 "	subf	%0,%2,%0 \n\
 2:"
 	: "=&r" (t)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/bitops.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/bitops.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -124,14 +124,14 @@ static __inline__ unsigned long fn(			\
 	return (old & mask);				\
 }
 
-DEFINE_TESTOP(test_and_set_bits, or, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
 DEFINE_TESTOP(test_and_set_bits_lock, or, "",
 	      PPC_ACQUIRE_BARRIER, 1)
-DEFINE_TESTOP(test_and_clear_bits, andc, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
-DEFINE_TESTOP(test_and_change_bits, xor, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
+DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
 
 static __inline__ int test_and_set_bit(unsigned long nr,
 				       volatile unsigned long *addr)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/compat.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,8 @@ struct compat_statfs {
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/cputime.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/cputime.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -150,6 +150,8 @@ static inline cputime_t usecs_to_cputime
 	return ct;
 }
 
+#define usecs_to_cputime64(us)		usecs_to_cputime(us)
+
 /*
  * Convert cputime <-> seconds
  */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/device.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/device.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,4 +37,6 @@ struct pdev_archdata {
 	u64 dma_mask;
 };
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 #endif /* _ASM_POWERPC_DEVICE_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/firmware.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/firmware.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/firmware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/firmware.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,8 @@
 #define FW_FEATURE_CMO		ASM_CONST(0x0000000002000000)
 #define FW_FEATURE_VPHN		ASM_CONST(0x0000000004000000)
 #define FW_FEATURE_XCMO		ASM_CONST(0x0000000008000000)
+#define FW_FEATURE_OPAL		ASM_CONST(0x0000000010000000)
+#define FW_FEATURE_OPALv2	ASM_CONST(0x0000000020000000)
 
 #ifndef __ASSEMBLY__
 
@@ -65,6 +67,8 @@ enum {
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
 	FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+	FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+	FW_FEATURE_POWERNV_ALWAYS = 0,
 	FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
@@ -78,6 +82,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
 		FW_FEATURE_ISERIES_POSSIBLE |
 #endif
+#ifdef CONFIG_PPC_POWERNV
+		FW_FEATURE_POWERNV_POSSIBLE |
+#endif
 #ifdef CONFIG_PPC_PS3
 		FW_FEATURE_PS3_POSSIBLE |
 #endif
@@ -95,6 +102,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
 		FW_FEATURE_ISERIES_ALWAYS &
 #endif
+#ifdef CONFIG_PPC_POWERNV
+		FW_FEATURE_POWERNV_ALWAYS &
+#endif
 #ifdef CONFIG_PPC_PS3
 		FW_FEATURE_PS3_ALWAYS &
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/floppy.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/floppy.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/floppy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/floppy.h	2012-01-04 18:55:44.000000000 -0500
@@ -108,10 +108,10 @@ static int fd_request_irq(void)
 {
 	if (can_use_virtual_dma)
 		return request_irq(FLOPPY_IRQ, floppy_hardint,
-				   IRQF_DISABLED, "floppy", NULL);
+				   0, "floppy", NULL);
 	else
 		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-				   IRQF_DISABLED, "floppy", NULL);
+				   0, "floppy", NULL);
 }
 
 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/futex.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/futex.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/futex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/futex.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,12 +11,13 @@
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
   __asm__ __volatile ( \
-	PPC_RELEASE_BARRIER \
+	PPC_ATOMIC_ENTRY_BARRIER \
 "1:	lwarx	%0,0,%2\n" \
 	insn \
 	PPC405_ERR77(0, %2) \
 "2:	stwcx.	%1,0,%2\n" \
 	"bne-	1b\n" \
+	PPC_ATOMIC_EXIT_BARRIER \
 	"li	%1,0\n" \
 "3:	.section .fixup,\"ax\"\n" \
 "4:	li	%1,%3\n" \
@@ -92,14 +93,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		return -EFAULT;
 
         __asm__ __volatile__ (
-        PPC_RELEASE_BARRIER
+        PPC_ATOMIC_ENTRY_BARRIER
 "1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
         cmpw    0,%1,%4\n\
         bne-    3f\n"
         PPC405_ERR77(0,%3)
 "2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
-        PPC_ACQUIRE_BARRIER
+        PPC_ATOMIC_EXIT_BARRIER
 "3:	.section .fixup,\"ax\"\n\
 4:	li	%0,%6\n\
 	b	3b\n\
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/hugetlb.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/hugetlb.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/hugetlb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/hugetlb.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,60 @@
 #ifndef _ASM_POWERPC_HUGETLB_H
 #define _ASM_POWERPC_HUGETLB_H
 
+#ifdef CONFIG_HUGETLB_PAGE
 #include <asm/page.h>
 
+extern struct kmem_cache *hugepte_cache;
+extern void __init reserve_hugetlb_gpages(void);
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+	BUG_ON(!hugepd_ok(hpd));
+	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+}
+
+static inline unsigned int hugepd_shift(hugepd_t hpd)
+{
+	return hpd.pd & HUGEPD_SHIFT_MASK;
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+				    unsigned pdshift)
+{
+	/*
+	 * On 32-bit, we have multiple higher-level table entries that point to
+	 * the same hugepte.  Just use the first one since they're all
+	 * identical.  So for that case, idx=0.
+	 */
+	unsigned long idx = 0;
+
+	pte_t *dir = hugepd_page(*hpdp);
+#ifdef CONFIG_PPC64
+	idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
+#endif
+
+	return dir + idx;
+}
+
 pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
 				 unsigned long addr, unsigned *shift);
 
 void flush_dcache_icache_hugepage(struct page *page);
 
+#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 			   unsigned long len);
+#else
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+					 unsigned long addr,
+					 unsigned long len)
+{
+	return 0;
+}
+#endif
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte);
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 			    unsigned long end, unsigned long floor,
@@ -50,8 +95,11 @@ static inline void set_huge_pte_at(struc
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 					    unsigned long addr, pte_t *ptep)
 {
-	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
-	return __pte(old);
+#ifdef CONFIG_PPC64
+	return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+#else
+	return __pte(pte_update(ptep, ~0UL, 0));
+#endif
 }
 
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -93,4 +141,15 @@ static inline void arch_release_hugepage
 {
 }
 
+#else /* ! CONFIG_HUGETLB_PAGE */
+static inline void reserve_hugetlb_gpages(void)
+{
+	pr_err("Cannot reserve gpages without hugetlb enabled\n");
+}
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+				      unsigned long vmaddr)
+{
+}
+#endif
+
 #endif /* _ASM_POWERPC_HUGETLB_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kexec.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kexec.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kexec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kexec.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #define _ASM_POWERPC_KEXEC_H
 #ifdef __KERNEL__
 
-#ifdef CONFIG_FSL_BOOKE
+#if defined(CONFIG_FSL_BOOKE) || defined(CONFIG_44x)
 
 /*
  * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s_64.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s_64.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,4 +29,37 @@ static inline struct kvmppc_book3s_shado
 
 #define SPAPR_TCE_SHIFT		12
 
+static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
+					     unsigned long pte_index)
+{
+	unsigned long rb, va_low;
+
+	rb = (v & ~0x7fUL) << 16;		/* AVA field */
+	va_low = pte_index >> 3;
+	if (v & HPTE_V_SECONDARY)
+		va_low = ~va_low;
+	/* xor vsid from AVA */
+	if (!(v & HPTE_V_1TB_SEG))
+		va_low ^= v >> 12;
+	else
+		va_low ^= v >> 24;
+	va_low &= 0x7ff;
+	if (v & HPTE_V_LARGE) {
+		rb |= 1;			/* L field */
+		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+		    (r & 0xff000)) {
+			/* non-16MB large page, must be 64k */
+			/* (masks depend on page size) */
+			rb |= 0x1000;		/* page encoding in LP field */
+			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
+		}
+	} else {
+		/* 4kB page */
+		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
+	}
+	rb |= (v >> 54) & 0x300;		/* B field */
+	return rb;
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s_asm.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s_asm.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s_asm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s_asm.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,6 +75,8 @@ struct kvmppc_host_state {
 	ulong scratch0;
 	ulong scratch1;
 	u8 in_guest;
+	u8 restore_hid5;
+	u8 napping;
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	struct kvm_vcpu *kvm_vcpu;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_book3s.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_book3s.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,15 +139,14 @@ extern void kvmppc_giveup_ext(struct kvm
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
-extern void kvmppc_handler_lowmem_trampoline(void);
-extern void kvmppc_handler_trampoline_enter(void);
-extern void kvmppc_rmcall(ulong srr0, ulong srr1);
+extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
 extern void kvmppc_load_up_fpu(void);
 extern void kvmppc_load_up_altivec(void);
 extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
+extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm.h	2012-01-04 18:55:44.000000000 -0500
@@ -276,6 +276,11 @@ struct kvm_guest_debug_arch {
 #define KVM_INTERRUPT_UNSET	-2U
 #define KVM_INTERRUPT_SET_LEVEL	-3U
 
+#define KVM_CPU_440		1
+#define KVM_CPU_E500V2		2
+#define KVM_CPU_3S_32		3
+#define KVM_CPU_3S_64		4
+
 /* for KVM_CAP_SPAPR_TCE */
 struct kvm_create_spapr_tce {
 	__u64 liobn;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_host.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -198,21 +198,29 @@ struct kvm_arch {
  */
 struct kvmppc_vcore {
 	int n_runnable;
-	int n_blocked;
+	int n_busy;
 	int num_threads;
 	int entry_exit_count;
 	int n_woken;
 	int nap_count;
+	int napping_threads;
 	u16 pcpu;
-	u8 vcore_running;
+	u8 vcore_state;
 	u8 in_guest;
 	struct list_head runnable_threads;
 	spinlock_t lock;
+	wait_queue_head_t wq;
 };
 
 #define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
 #define VCORE_EXIT_COUNT(vc)	((vc)->entry_exit_count >> 8)
 
+/* Values for vcore_state */
+#define VCORE_INACTIVE	0
+#define VCORE_RUNNING	1
+#define VCORE_EXITING	2
+#define VCORE_SLEEPING	3
+
 struct kvmppc_pte {
 	ulong eaddr;
 	u64 vpage;
@@ -258,14 +266,6 @@ struct kvm_vcpu_arch {
 	ulong host_stack;
 	u32 host_pid;
 #ifdef CONFIG_PPC_BOOK3S
-	ulong host_msr;
-	ulong host_r2;
-	void *host_retip;
-	ulong trampoline_lowmem;
-	ulong trampoline_enter;
-	ulong highmem_handler;
-	ulong rmcall;
-	ulong host_paca_phys;
 	struct kvmppc_slb slb[64];
 	int slb_max;		/* 1 + index of last valid entry in slb[] */
 	int slb_nr;		/* total number of entries in SLB */
@@ -389,6 +389,9 @@ struct kvm_vcpu_arch {
 	u8 dcr_is_write;
 	u8 osi_needed;
 	u8 osi_enabled;
+	u8 papr_enabled;
+	u8 sane;
+	u8 cpu_type;
 	u8 hcall_needed;
 
 	u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
@@ -408,11 +411,13 @@ struct kvm_vcpu_arch {
 	struct dtl *dtl;
 	struct dtl *dtl_end;
 
+	wait_queue_head_t *wqp;
 	struct kvmppc_vcore *vcore;
 	int ret;
 	int trap;
 	int state;
 	int ptid;
+	bool timer_running;
 	wait_queue_head_t cpu_run;
 
 	struct kvm_vcpu_arch_shared *shared;
@@ -428,8 +433,9 @@ struct kvm_vcpu_arch {
 #endif
 };
 
-#define KVMPPC_VCPU_BUSY_IN_HOST	0
-#define KVMPPC_VCPU_BLOCKED		1
+/* Values for vcpu->arch.state */
+#define KVMPPC_VCPU_STOPPED		0
+#define KVMPPC_VCPU_BUSY_IN_HOST	1
 #define KVMPPC_VCPU_RUNNABLE		2
 
 #endif /* __POWERPC_KVM_HOST_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_ppc.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_ppc.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/kvm_ppc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/kvm_ppc.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(st
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/lv1call.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/lv1call.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/lv1call.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/lv1call.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #if !defined(__ASSEMBLY__)
 
 #include <linux/types.h>
+#include <linux/export.h>
 
 /* lv1 call declaration macros */
 
@@ -315,7 +316,7 @@ LV1_CALL(gpu_context_free,
 LV1_CALL(gpu_context_iomap,                             5, 0, 221 )
 LV1_CALL(gpu_context_attribute,                         6, 0, 225 )
 LV1_CALL(gpu_context_intr,                              1, 1, 227 )
-LV1_CALL(gpu_attribute,                                 5, 0, 228 )
+LV1_CALL(gpu_attribute,                                 3, 0, 228 )
 LV1_CALL(get_rtc,                                       0, 2, 232 )
 LV1_CALL(set_ppe_periodic_tracer_frequency,             1, 0, 240 )
 LV1_CALL(start_ppe_periodic_tracer,                     5, 0, 241 )
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/machdep.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/machdep.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/machdep.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/machdep.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/setup.h>
 
@@ -85,8 +86,9 @@ struct machdep_calls {
 	void		(*pci_dma_dev_setup)(struct pci_dev *dev);
 	void		(*pci_dma_bus_setup)(struct pci_bus *bus);
 
-	/* Platform set_dma_mask override */
+	/* Platform set_dma_mask and dma_get_required_mask overrides */
 	int		(*dma_set_mask)(struct device *dev, u64 dma_mask);
+	u64		(*dma_get_required_mask)(struct device *dev);
 
 	int		(*probe)(void);
 	void		(*setup_arch)(void); /* Optional, may be NULL */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu-book3e.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu-book3e.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu-book3e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu-book3e.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,7 @@
 #define MAS2_M			0x00000004
 #define MAS2_G			0x00000002
 #define MAS2_E			0x00000001
+#define MAS2_WIMGE_MASK		0x0000001f
 #define MAS2_EPN_MASK(size)		(~0 << (size + 10))
 #define MAS2_VAL(addr, size, flags)	((addr) & MAS2_EPN_MASK(size) | (flags))
 
@@ -80,6 +81,7 @@
 #define MAS3_SW			0x00000004
 #define MAS3_UR			0x00000002
 #define MAS3_SR			0x00000001
+#define MAS3_BAP_MASK		0x0000003f
 #define MAS3_SPSIZE		0x0000003e
 #define MAS3_SPSIZE_SHIFT	1
 
@@ -212,6 +214,11 @@ typedef struct {
 	unsigned int	id;
 	unsigned int	active;
 	unsigned long	vdso_base;
+#ifdef CONFIG_PPC_MM_SLICES
+	u64 low_slices_psize;   /* SLB page size encodings */
+	u64 high_slices_psize;  /* 4 bits per slice for now */
+	u16 user_psize;         /* page size index */
+#endif
 } mm_context_t;
 
 /* Page size definitions, common between 32 and 64-bit
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -175,14 +175,16 @@ extern u64 ppc64_rma_size;
 #define MMU_PAGE_64K_AP	3	/* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K	4
 #define MMU_PAGE_1M	5
-#define MMU_PAGE_8M	6
-#define MMU_PAGE_16M	7
-#define MMU_PAGE_256M	8
-#define MMU_PAGE_1G	9
-#define MMU_PAGE_16G	10
-#define MMU_PAGE_64G	11
-#define MMU_PAGE_COUNT	12
+#define MMU_PAGE_4M	6
+#define MMU_PAGE_8M	7
+#define MMU_PAGE_16M	8
+#define MMU_PAGE_64M	9
+#define MMU_PAGE_256M	10
+#define MMU_PAGE_1G	11
+#define MMU_PAGE_16G	12
+#define MMU_PAGE_64G	13
 
+#define MMU_PAGE_COUNT	14
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu-hash64.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu-hash64.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/mmu-hash64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/mmu-hash64.h	2012-01-04 18:55:44.000000000 -0500
@@ -262,8 +262,7 @@ extern void hash_failure_debug(unsigned
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 			     unsigned long pstart, unsigned long prot,
 			     int psize, int ssize);
-extern void add_gpage(unsigned long addr, unsigned long page_size,
-			  unsigned long number_of_pages);
+extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/mpic.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/mpic.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/mpic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/mpic.h	2012-01-04 18:55:44.000000000 -0500
@@ -273,8 +273,6 @@ struct mpic
 	unsigned int		irq_count;
 	/* Number of sources */
 	unsigned int		num_sources;
-	/* Number of CPUs */
-	unsigned int		num_cpus;
 	/* default senses array */
 	unsigned char		*senses;
 	unsigned int		senses_count;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/opal.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/opal.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/opal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/opal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,443 @@
+/*
+ * PowerNV OPAL definitions.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __OPAL_H
+#define __OPAL_H
+
+/****** Takeover interface ********/
+
+/* PAPR H-Call used to querty the HAL existence and/or instanciate
+ * it from within pHyp (tech preview only).
+ *
+ * This is exclusively used in prom_init.c
+ */
+
+#ifndef __ASSEMBLY__
+
+struct opal_takeover_args {
+	u64	k_image;		/* r4 */
+	u64	k_size;			/* r5 */
+	u64	k_entry;		/* r6 */
+	u64	k_entry2;		/* r7 */
+	u64	hal_addr;		/* r8 */
+	u64	rd_image;		/* r9 */
+	u64	rd_size;		/* r10 */
+	u64	rd_loc;			/* r11 */
+};
+
+extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
+
+extern long opal_do_takeover(struct opal_takeover_args *args);
+
+struct rtas_args;
+extern int opal_enter_rtas(struct rtas_args *args,
+			   unsigned long data,
+			   unsigned long entry);
+
+#endif /* __ASSEMBLY__ */
+
+/****** OPAL APIs ******/
+
+/* Return codes */
+#define OPAL_SUCCESS 		0
+#define OPAL_PARAMETER		-1
+#define OPAL_BUSY		-2
+#define OPAL_PARTIAL		-3
+#define OPAL_CONSTRAINED	-4
+#define OPAL_CLOSED		-5
+#define OPAL_HARDWARE		-6
+#define OPAL_UNSUPPORTED	-7
+#define OPAL_PERMISSION		-8
+#define OPAL_NO_MEM		-9
+#define OPAL_RESOURCE		-10
+#define OPAL_INTERNAL_ERROR	-11
+#define OPAL_BUSY_EVENT		-12
+#define OPAL_HARDWARE_FROZEN	-13
+
+/* API Tokens (in r0) */
+#define OPAL_CONSOLE_WRITE			1
+#define OPAL_CONSOLE_READ			2
+#define OPAL_RTC_READ				3
+#define OPAL_RTC_WRITE				4
+#define OPAL_CEC_POWER_DOWN			5
+#define OPAL_CEC_REBOOT				6
+#define OPAL_READ_NVRAM				7
+#define OPAL_WRITE_NVRAM			8
+#define OPAL_HANDLE_INTERRUPT			9
+#define OPAL_POLL_EVENTS			10
+#define OPAL_PCI_SET_HUB_TCE_MEMORY		11
+#define OPAL_PCI_SET_PHB_TCE_MEMORY		12
+#define OPAL_PCI_CONFIG_READ_BYTE		13
+#define OPAL_PCI_CONFIG_READ_HALF_WORD  	14
+#define OPAL_PCI_CONFIG_READ_WORD		15
+#define OPAL_PCI_CONFIG_WRITE_BYTE		16
+#define OPAL_PCI_CONFIG_WRITE_HALF_WORD		17
+#define OPAL_PCI_CONFIG_WRITE_WORD		18
+#define OPAL_SET_XIVE				19
+#define OPAL_GET_XIVE				20
+#define OPAL_GET_COMPLETION_TOKEN_STATUS	21 /* obsolete */
+#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER	22
+#define OPAL_PCI_EEH_FREEZE_STATUS		23
+#define OPAL_PCI_SHPC				24
+#define OPAL_CONSOLE_WRITE_BUFFER_SPACE		25
+#define OPAL_PCI_EEH_FREEZE_CLEAR		26
+#define OPAL_PCI_PHB_MMIO_ENABLE		27
+#define OPAL_PCI_SET_PHB_MEM_WINDOW		28
+#define OPAL_PCI_MAP_PE_MMIO_WINDOW		29
+#define OPAL_PCI_SET_PHB_TABLE_MEMORY		30
+#define OPAL_PCI_SET_PE				31
+#define OPAL_PCI_SET_PELTV			32
+#define OPAL_PCI_SET_MVE			33
+#define OPAL_PCI_SET_MVE_ENABLE			34
+#define OPAL_PCI_GET_XIVE_REISSUE		35
+#define OPAL_PCI_SET_XIVE_REISSUE		36
+#define OPAL_PCI_SET_XIVE_PE			37
+#define OPAL_GET_XIVE_SOURCE			38
+#define OPAL_GET_MSI_32				39
+#define OPAL_GET_MSI_64				40
+#define OPAL_START_CPU				41
+#define OPAL_QUERY_CPU_STATUS			42
+#define OPAL_WRITE_OPPANEL			43
+#define OPAL_PCI_MAP_PE_DMA_WINDOW		44
+#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL		45
+#define OPAL_PCI_RESET				49
+
+#ifndef __ASSEMBLY__
+
+/* Other enums */
+enum OpalVendorApiTokens {
+	OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
+};
+enum OpalFreezeState {
+	OPAL_EEH_STOPPED_NOT_FROZEN = 0,
+	OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
+	OPAL_EEH_STOPPED_DMA_FREEZE = 2,
+	OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
+	OPAL_EEH_STOPPED_RESET = 4,
+	OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
+	OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
+};
+enum OpalEehFreezeActionToken {
+	OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
+	OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
+	OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+};
+enum OpalPciStatusToken {
+	OPAL_EEH_PHB_NO_ERROR = 0,
+	OPAL_EEH_PHB_FATAL = 1,
+	OPAL_EEH_PHB_RECOVERABLE = 2,
+	OPAL_EEH_PHB_BUS_ERROR = 3,
+	OPAL_EEH_PCI_NO_DEVSEL = 4,
+	OPAL_EEH_PCI_TA = 5,
+	OPAL_EEH_PCIEX_UR = 6,
+	OPAL_EEH_PCIEX_CA = 7,
+	OPAL_EEH_PCI_MMIO_ERROR = 8,
+	OPAL_EEH_PCI_DMA_ERROR = 9
+};
+enum OpalShpcAction {
+	OPAL_SHPC_GET_LINK_STATE = 0,
+	OPAL_SHPC_GET_SLOT_STATE = 1
+};
+enum OpalShpcLinkState {
+	OPAL_SHPC_LINK_DOWN = 0,
+	OPAL_SHPC_LINK_UP = 1
+};
+enum OpalMmioWindowType {
+	OPAL_M32_WINDOW_TYPE = 1,
+	OPAL_M64_WINDOW_TYPE = 2,
+	OPAL_IO_WINDOW_TYPE = 3
+};
+enum OpalShpcSlotState {
+	OPAL_SHPC_DEV_NOT_PRESENT = 0,
+	OPAL_SHPC_DEV_PRESENT = 1
+};
+enum OpalExceptionHandler {
+	OPAL_MACHINE_CHECK_HANDLER = 1,
+	OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
+	OPAL_SOFTPATCH_HANDLER = 3
+};
+enum OpalPendingState {
+	OPAL_EVENT_OPAL_INTERNAL = 0x1,
+	OPAL_EVENT_NVRAM = 0x2,
+	OPAL_EVENT_RTC = 0x4,
+	OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
+	OPAL_EVENT_CONSOLE_INPUT = 0x10
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+	OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+	OpalMCE_SEV_NO_ERROR = 0,
+	OpalMCE_SEV_WARNING = 1,
+	OpalMCE_SEV_ERROR_SYNC = 2,
+	OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+	OpalMCE_DISPOSITION_RECOVERED = 0,
+	OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+	OpalMCE_INITIATOR_UNKNOWN = 0,
+	OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+	OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+	OpalMCE_ERROR_TYPE_UE = 1,
+	OpalMCE_ERROR_TYPE_SLB = 2,
+	OpalMCE_ERROR_TYPE_ERAT = 3,
+	OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+	OpalMCE_UE_ERROR_INDETERMINATE = 0,
+	OpalMCE_UE_ERROR_IFETCH = 1,
+	OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+	OpalMCE_UE_ERROR_LOAD_STORE = 3,
+	OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+	OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+	OpalMCE_SLB_ERROR_PARITY = 1,
+	OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+	OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+	OpalMCE_ERAT_ERROR_PARITY = 1,
+	OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+	OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+	OpalMCE_TLB_ERROR_PARITY = 1,
+	OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+	OPAL_THREAD_INACTIVE = 0x0,
+	OPAL_THREAD_STARTED = 0x1
+};
+
+enum OpalPciBusCompare {
+	OpalPciBusAny	= 0,	/* Any bus number match */
+	OpalPciBus3Bits	= 2,	/* Match top 3 bits of bus number */
+	OpalPciBus4Bits	= 3,	/* Match top 4 bits of bus number */
+	OpalPciBus5Bits	= 4,	/* Match top 5 bits of bus number */
+	OpalPciBus6Bits	= 5,	/* Match top 6 bits of bus number */
+	OpalPciBus7Bits	= 6,	/* Match top 7 bits of bus number */
+	OpalPciBusAll	= 7,	/* Match bus number exactly */
+};
+
+enum OpalDeviceCompare {
+	OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
+	OPAL_COMPARE_RID_DEVICE_NUMBER = 1
+};
+
+enum OpalFuncCompare {
+	OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
+	OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
+};
+
+enum OpalPeAction {
+	OPAL_UNMAP_PE = 0,
+	OPAL_MAP_PE = 1
+};
+
+enum OpalPciResetAndReinitScope {
+	OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
+	OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
+	OPAL_PCI_IODA_RESET = 6,
+};
+
+enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+
+struct opal_machine_check_event {
+	enum OpalMCE_Version	version:8;	/* 0x00 */
+	uint8_t			in_use;		/* 0x01 */
+	enum OpalMCE_Severity	severity:8;	/* 0x02 */
+	enum OpalMCE_Initiator	initiator:8;	/* 0x03 */
+	enum OpalMCE_ErrorType	error_type:8;	/* 0x04 */
+	enum OpalMCE_Disposition disposition:8; /* 0x05 */
+	uint8_t			reserved_1[2];	/* 0x06 */
+	uint64_t		gpr3;		/* 0x08 */
+	uint64_t		srr0;		/* 0x10 */
+	uint64_t		srr1;		/* 0x18 */
+	union {					/* 0x20 */
+		struct {
+			enum OpalMCE_UeErrorType ue_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		physical_address_provided;
+			uint8_t		reserved_1[5];
+			uint64_t	effective_address;
+			uint64_t	physical_address;
+			uint8_t		reserved_2[8];
+		} ue_error;
+
+		struct {
+			enum OpalMCE_SlbErrorType slb_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} slb_error;
+
+		struct {
+			enum OpalMCE_EratErrorType erat_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} erat_error;
+
+		struct {
+			enum OpalMCE_TlbErrorType tlb_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} tlb_error;
+	} u;
+};
+
+typedef struct oppanel_line {
+	/* XXX */
+} oppanel_line_t;
+
+/* API functions */
+int64_t opal_console_write(int64_t term_number, int64_t *length,
+			   const uint8_t *buffer);
+int64_t opal_console_read(int64_t term_number, int64_t *length,
+			  uint8_t *buffer);
+int64_t opal_console_write_buffer_space(int64_t term_number,
+					int64_t *length);
+int64_t opal_rtc_read(uint32_t *year_month_day,
+		      uint64_t *hour_minute_second_millisecond);
+int64_t opal_rtc_write(uint32_t year_month_day,
+		       uint64_t hour_minute_second_millisecond);
+int64_t opal_cec_power_down(uint64_t request);
+int64_t opal_cec_reboot(void);
+int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
+				    uint64_t tce_mem_size);
+int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
+				    uint64_t tce_mem_size);
+int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
+				  uint64_t offset, uint8_t *data);
+int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+				       uint64_t offset, uint16_t *data);
+int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
+				  uint64_t offset, uint32_t *data);
+int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
+				   uint64_t offset, uint8_t data);
+int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+					uint64_t offset, uint16_t data);
+int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
+				   uint64_t offset, uint32_t data);
+int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
+int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_register_exception_handler(uint64_t opal_exception,
+					uint64_t handler_address,
+					uint64_t glue_cache_line);
+int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
+				   uint8_t *freeze_state,
+				   uint16_t *pci_error_type,
+				   uint64_t *phb_status);
+int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
+				  uint64_t eeh_action_token);
+int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
+
+
+
+int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
+				 uint16_t window_num, uint16_t enable);
+int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
+				    uint16_t window_num,
+				    uint64_t starting_real_address,
+				    uint64_t starting_pci_address,
+				    uint16_t segment_size);
+int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
+				    uint16_t window_type, uint16_t window_num,
+				    uint16_t segment_num);
+int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
+				      uint64_t ivt_addr, uint64_t ivt_len,
+				      uint64_t reject_array_addr,
+				      uint64_t peltv_addr);
+int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
+			uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
+			uint8_t pe_action);
+int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
+			   uint8_t state);
+int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
+int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
+				uint32_t state);
+int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+				  uint8_t *p_bit, uint8_t *q_bit);
+int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+				  uint8_t p_bit, uint8_t q_bit);
+int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
+			     uint32_t xive_num);
+int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
+			     int32_t *interrupt_source_number);
+int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
+			uint8_t msi_range, uint32_t *msi_address,
+			uint32_t *message_data);
+int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
+			uint32_t xive_num, uint8_t msi_range,
+			uint64_t *msi_address, uint32_t *message_data);
+int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
+int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
+int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
+int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
+				   uint16_t tce_levels, uint64_t tce_table_addr,
+				   uint64_t tce_table_size, uint64_t tce_page_size);
+int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
+					uint16_t dma_window_number, uint64_t pci_start_addr,
+					uint64_t pci_mem_size);
+int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+				   int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+struct rtc_time;
+extern int opal_set_rtc_time(struct rtc_time *tm);
+extern void opal_get_rtc_time(struct rtc_time *tm);
+extern unsigned long opal_get_boot_time(void);
+extern void opal_nvram_init(void);
+
+extern int opal_machine_check(struct pt_regs *regs);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __OPAL_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/paca.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/paca.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/paca.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/paca.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@ extern unsigned int debug_smp_processor_
 #define get_slb_shadow()	(get_paca()->slb_shadow_ptr)
 
 struct task_struct;
+struct opal_machine_check_event;
 
 /*
  * Defines the layout of the paca.
@@ -135,6 +136,13 @@ struct paca_struct {
 	u8 io_sync;			/* writel() needs spin_unlock sync */
 	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 
+#ifdef CONFIG_PPC_POWERNV
+	/* Pointer to OPAL machine check event structure set by the
+	 * early exception handler for use by high level C handler
+	 */
+	struct opal_machine_check_event *opal_mc_evt;
+#endif
+
 	/* Stuff for accurate time accounting */
 	u64 user_time;			/* accumulated usermode TB ticks */
 	u64 system_time;		/* accumulated system TB ticks */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/page_64.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/page_64.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/page_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/page_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,17 +64,6 @@ extern void copy_page(void *to, void *fr
 /* Log 2 of page table size */
 extern u64 ppc64_pft_size;
 
-/* Large pages size */
-#ifdef CONFIG_HUGETLB_PAGE
-extern unsigned int HPAGE_SHIFT;
-#else
-#define HPAGE_SHIFT PAGE_SHIFT
-#endif
-#define HPAGE_SIZE		((1UL) << HPAGE_SHIFT)
-#define HPAGE_MASK		(~(HPAGE_SIZE - 1))
-#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
-#define HUGE_MAX_HSTATE		(MMU_PAGE_COUNT-1)
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_MM_SLICES
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/page.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,18 @@
 
 #define PAGE_SIZE		(ASM_CONST(1) << PAGE_SHIFT)
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+extern unsigned int HPAGE_SHIFT;
+#else
+#define HPAGE_SHIFT PAGE_SHIFT
+#endif
+#define HPAGE_SIZE		((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK		(~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE		(MMU_PAGE_COUNT-1)
+#endif
+
 /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
 #define __HAVE_ARCH_GATE_AREA		1
 
@@ -158,6 +170,24 @@ extern phys_addr_t kernstart_addr;
 #define is_kernel_addr(x)	((x) >= PAGE_OFFSET)
 #endif
 
+/*
+ * Use the top bit of the higher-level page table entries to indicate whether
+ * the entries we point to contain hugepages.  This works because we know that
+ * the page tables live in kernel space.  If we ever decide to support having
+ * page tables at arbitrary addresses, this breaks and will have to change.
+ */
+#ifdef CONFIG_PPC64
+#define PD_HUGE 0x8000000000000000
+#else
+#define PD_HUGE 0x80000000
+#endif
+
+/*
+ * Some number of bits at the level of the page table that points to
+ * a hugepte are used to encode the size.  This masks those bits.
+ */
+#define HUGEPD_SHIFT_MASK     0x3f
+
 #ifndef __ASSEMBLY__
 
 #undef STRICT_MM_TYPECHECKS
@@ -243,7 +273,6 @@ typedef unsigned long pgprot_t;
 #endif
 
 typedef struct { signed long pd; } hugepd_t;
-#define HUGEPD_SHIFT_MASK     0x3f
 
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hugepd_ok(hugepd_t hpd)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/pte-book3e.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/pte-book3e.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/pte-book3e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/pte-book3e.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,9 @@
 #define	PTE_RPN_SHIFT	(24)
 #endif
 
+#define PTE_WIMGE_SHIFT (19)
+#define PTE_BAP_SHIFT	(2)
+
 /* On 32-bit, we never clear the top part of the PTE */
 #ifdef CONFIG_PPC32
 #define _PTE_NONE_MASK	0xffffffff00000000ULL
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/qe.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/qe.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/qe.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/qe.h	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@ static inline int qe_alive_during_sleep(
 
 /* Structure that defines QE firmware binary files.
  *
- * See Documentation/powerpc/qe-firmware.txt for a description of these
+ * See Documentation/powerpc/qe_firmware.txt for a description of these
  * fields.
  */
 struct qe_firmware {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/reg_booke.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/reg_booke.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/reg_booke.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #define MSR_		MSR_ME | MSR_CE
 #define MSR_KERNEL	MSR_ | MSR_64BIT
-#define MSR_USER32	MSR_ | MSR_PR | MSR_EE | MSR_DE
+#define MSR_USER32	MSR_ | MSR_PR | MSR_EE
 #define MSR_USER64	MSR_USER32 | MSR_64BIT
 #elif defined (CONFIG_40x)
 #define MSR_KERNEL	(MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
@@ -548,6 +548,9 @@
 #define L1CSR1_ICFI	0x00000002	/* Instr Cache Flash Invalidate */
 #define L1CSR1_ICE	0x00000001	/* Instr Cache Enable */
 
+/* Bit definitions for L1CSR2. */
+#define L1CSR2_DCWS	0x40000000	/* Data Cache write shadow */
+
 /* Bit definitions for L2CSR0. */
 #define L2CSR0_L2E	0x80000000	/* L2 Cache Enable */
 #define L2CSR0_L2PE	0x40000000	/* L2 Cache Parity/ECC Enable */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/rtas.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/rtas.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/rtas.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/rtas.h	2012-01-04 18:55:44.000000000 -0500
@@ -249,10 +249,12 @@ extern void pSeries_log_error(char *buf,
 #define ERR_FLAG_ALREADY_LOGGED	0x0
 #define ERR_FLAG_BOOT		0x1 	/* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG	0x2	/* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC	0x4	/* from panic() */
+#define ERR_TYPE_KERNEL_PANIC	0x4	/* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8	/* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/sections.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/sections.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/sections.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #ifdef __powerpc64__
 
-extern char _end[];
+extern char __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/smp.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/smp.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/sparsemem.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/sparsemem.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/sparsemem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/sparsemem.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern void create_section_mapping(unsigned long start, unsigned long end);
+extern int create_section_mapping(unsigned long start, unsigned long end);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/spu.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/spu.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/spu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/spu.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/workqueue.h>
 #include <linux/sysdev.h>
+#include <linux/mutex.h>
 
 #define LS_SIZE (256 * 1024)
 #define LS_ADDR_MASK (LS_SIZE - 1)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/synch.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/synch.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/synch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/synch.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
 			     void *fixup_end);
+extern void do_final_fixups(void);
 
 static inline void eieio(void)
 {
@@ -41,11 +42,15 @@ static inline void isync(void)
 	START_LWSYNC_SECTION(97);			\
 	isync;						\
 	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
-#define PPC_ACQUIRE_BARRIER	"\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
-#define PPC_RELEASE_BARRIER	stringify_in_c(LWSYNC) "\n"
+#define PPC_ACQUIRE_BARRIER	 "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+#define PPC_RELEASE_BARRIER	 stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_EXIT_BARRIER	 "\n" stringify_in_c(sync) "\n"
 #else
 #define PPC_ACQUIRE_BARRIER
 #define PPC_RELEASE_BARRIER
+#define PPC_ATOMIC_ENTRY_BARRIER
+#define PPC_ATOMIC_EXIT_BARRIER
 #endif
 
 #endif /* __KERNEL__ */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/systbl.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/systbl.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/systbl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/systbl.h	2012-01-04 18:55:44.000000000 -0500
@@ -354,3 +354,5 @@ COMPAT_SYS_SPU(clock_adjtime)
 SYSCALL_SPU(syncfs)
 COMPAT_SYS_SPU(sendmmsg)
 SYSCALL_SPU(setns)
+COMPAT_SYS(process_vm_readv)
+COMPAT_SYS(process_vm_writev)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/topology.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/topology.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/topology.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,14 +19,10 @@ struct device_node;
 #define RECLAIM_DISTANCE 10
 
 /*
- * Before going off node we want the VM to try and reclaim from the local
- * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
- * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
- * 20, we never reclaim and go off node straight away.
- *
- * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ * Avoid creating an extra level of balancing (SD_ALLNODES) on the largest
+ * POWER7 boxes which have a maximum of 32 nodes.
  */
-#define RECLAIM_DISTANCE 10
+#define SD_NODES_PER_DOMAIN 32
 
 #include <asm/mmzone.h>
 
@@ -69,11 +65,11 @@ static inline int pcibus_to_node(struct
 	.forkexec_idx		= 0,					\
 									\
 	.flags			= 1*SD_LOAD_BALANCE			\
-				| 1*SD_BALANCE_NEWIDLE			\
+				| 0*SD_BALANCE_NEWIDLE			\
 				| 1*SD_BALANCE_EXEC			\
 				| 1*SD_BALANCE_FORK			\
 				| 0*SD_BALANCE_WAKE			\
-				| 0*SD_WAKE_AFFINE			\
+				| 1*SD_WAKE_AFFINE			\
 				| 0*SD_PREFER_LOCAL			\
 				| 0*SD_SHARE_CPUPOWER			\
 				| 0*SD_POWERSAVINGS_BALANCE		\
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/udbg.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/udbg.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/udbg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/udbg.h	2012-01-04 18:55:44.000000000 -0500
@@ -54,6 +54,10 @@ extern void __init udbg_init_40x_realmod
 extern void __init udbg_init_cpm(void);
 extern void __init udbg_init_usbgecko(void);
 extern void __init udbg_init_wsp(void);
+extern void __init udbg_init_ehv_bc(void);
+extern void __init udbg_init_ps3gelic(void);
+extern void __init udbg_init_debug_opal_raw(void);
+extern void __init udbg_init_debug_opal_hvsi(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/unistd.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -373,10 +373,12 @@
 #define __NR_syncfs		348
 #define __NR_sendmmsg		349
 #define __NR_setns		350
+#define __NR_process_vm_readv	351
+#define __NR_process_vm_writev	352
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		351
+#define __NR_syscalls		353
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/include/asm/xics.h linux-libre-3.2-gnu1/arch/powerpc/include/asm/xics.h
--- linux-libre-3.1-gnu1/arch/powerpc/include/asm/xics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/include/asm/xics.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,8 +15,8 @@
 #define	DEFAULT_PRIORITY	5
 
 /*
- * Mark IPIs as higher priority so we can take them inside interrupts that
- * arent marked IRQF_DISABLED
+ * Mark IPIs as higher priority so we can take them inside interrupts
+ * FIXME: still true now?
  */
 #define IPI_PRIORITY		4
 
@@ -27,10 +27,18 @@
 #define MAX_NUM_PRIORITIES	3
 
 /* Native ICP */
+#ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
+#else
+static inline int icp_native_init(void) { return -ENODEV; }
+#endif
 
 /* PAPR ICP */
+#ifdef CONFIG_PPC_ICP_HV
 extern int icp_hv_init(void);
+#else
+static inline int icp_hv_init(void) { return -ENODEV; }
+#endif
 
 /* ICP ops */
 struct icp_ops {
@@ -51,7 +59,18 @@ extern const struct icp_ops *icp_ops;
 extern int ics_native_init(void);
 
 /* RTAS ICS */
+#ifdef CONFIG_PPC_ICS_RTAS
 extern int ics_rtas_init(void);
+#else
+static inline int ics_rtas_init(void) { return -ENODEV; }
+#endif
+
+/* HAL ICS */
+#ifdef CONFIG_PPC_POWERNV
+extern int ics_opal_init(void);
+#else
+static inline int ics_opal_init(void) { return -ENODEV; }
+#endif
 
 /* ICS instance, hooked up to chip_data of an irq */
 struct ics {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/Kconfig linux-libre-3.2-gnu1/arch/powerpc/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@ config SWIOTLB
 
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
-	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
@@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
-	depends on (PPC_BOOK3S || FSL_BOOKE) && EXPERIMENTAL
+	depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
 	help
 	  kexec is a system call that implements the ability to shutdown your
 	  current kernel, and to start another kernel.  It is like a reboot
@@ -379,10 +379,6 @@ config PHYP_DUMP
 
 	  If unsure, say "N"
 
-config PPCBUG_NVRAM
-	bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
-	default y if PPC_PREP
-
 config IRQ_ALL_CPUS
 	bool "Distribute interrupts on all CPUs by default"
 	depends on SMP && !MV64360
@@ -429,8 +425,7 @@ config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
-       def_bool y
-       depends on PPC_BOOK3S_64
+	bool
 
 source "mm/Kconfig"
 
@@ -656,6 +651,8 @@ config SBUS
 
 config FSL_SOC
 	bool
+	select HAVE_CAN_FLEXCAN if NET && CAN
+	select PPC_CLOCK if CAN_FLEXCAN
 
 config FSL_PCI
  	bool
@@ -744,24 +741,6 @@ config 8260_PCI9
 	depends on PCI_8260 && !8272
 	default y
 
-choice
-	prompt "IDMA channel for PCI 9 workaround"
-	depends on 8260_PCI9
-
-config 8260_PCI9_IDMA1
-	bool "IDMA1"
-
-config 8260_PCI9_IDMA2
-	bool "IDMA2"
-
-config 8260_PCI9_IDMA3
-	bool "IDMA3"
-
-config 8260_PCI9_IDMA4
-	bool "IDMA4"
-
-endchoice
-
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/Kconfig.debug linux-libre-3.2-gnu1/arch/powerpc/Kconfig.debug
--- linux-libre-3.1-gnu1/arch/powerpc/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -141,9 +141,6 @@ config BOOTX_TEXT
 
 config PPC_EARLY_DEBUG
 	bool "Early debugging (dangerous)"
-	# PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
-	# mark, which doesn't work with current 440 KVM.
-	depends on !KVM
 	help
 	  Say Y to enable some early debugging facilities that may be available
 	  for your processor/board combination. Those facilities are hacks
@@ -222,7 +219,9 @@ config PPC_EARLY_DEBUG_BEAT
 
 config PPC_EARLY_DEBUG_44x
 	bool "Early serial debugging for IBM/AMCC 44x CPUs"
-	depends on 44x
+	# PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+	# mark, which doesn't work with current 440 KVM.
+	depends on 44x && !KVM
 	help
 	  Select this to enable early debugging for IBM 44x chips via the
 	  inbuilt serial port.  If you enable this, ensure you set
@@ -258,8 +257,35 @@ config PPC_EARLY_DEBUG_WSP
 	depends on PPC_WSP
 	select PPC_UDBG_16550
 
+config PPC_EARLY_DEBUG_PS3GELIC
+	bool "Early debugging through the PS3 Ethernet port"
+	depends on PPC_PS3
+	select PS3GELIC_UDBG
+	help
+	  Select this to enable early debugging for the PlayStation3 via
+	  UDP broadcasts sent out through the Ethernet port.
+
+config PPC_EARLY_DEBUG_OPAL_RAW
+	bool "OPAL raw console"
+	depends on HVC_OPAL
+	help
+	  Select this to enable early debugging for the PowerNV platform
+	  using a "raw" console
+
+config PPC_EARLY_DEBUG_OPAL_HVSI
+	bool "OPAL hvsi console"
+	depends on HVC_OPAL
+	help
+	  Select this to enable early debugging for the PowerNV platform
+	  using an "hvsi" console
+
 endchoice
 
+config PPC_EARLY_DEBUG_OPAL
+	def_bool y
+	depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
+
+
 config PPC_EARLY_DEBUG_HVSI_VTERMNO
 	hex "vterm number to use with early debug HVSI"
 	depends on PPC_EARLY_DEBUG_LPAR_HVSI
@@ -268,6 +294,18 @@ config PPC_EARLY_DEBUG_HVSI_VTERMNO
 	  You probably want 0x30000000 for your first serial port and
 	  0x30000001 for your second one
 
+config PPC_EARLY_DEBUG_OPAL_VTERMNO
+	hex "vterm number to use with OPAL early debug"
+	depends on PPC_EARLY_DEBUG_OPAL
+	default "0"
+	help
+	  This correspond to which /dev/hvcN you want to use for early
+	  debug.
+
+	  On OPAL v1 (takeover) this should always be 0
+	  On OPAL v2, this will be 0 for network console and 1 or 2 for
+	  the machine built-in serial ports.
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
 	hex "Low 32 bits of early debug UART physical address"
 	depends on PPC_EARLY_DEBUG_44x
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/asm-offsets.c linux-libre-3.2-gnu1/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,14 @@
 #include <asm/compat.h>
 #include <asm/mmu.h>
 #include <asm/hvcall.h>
+#include <asm/xics.h>
 #endif
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/alpaca.h>
 #endif
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#endif
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
 #include <linux/kvm_host.h>
 #endif
@@ -449,8 +453,6 @@ int main(void)
 #ifdef CONFIG_PPC_BOOK3S
 	DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
 	DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
-	DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip));
-	DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
 	DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
 	DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
 	DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
@@ -458,14 +460,12 @@ int main(void)
 	DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
 	DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
 	DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
-	DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
-	DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
-	DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
-	DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall));
 	DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
 	DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
 	DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
 	DEFINE(VCPU_PENDING_EXC, offsetof(struct kvm_vcpu, arch.pending_exceptions));
+	DEFINE(VCPU_CEDED, offsetof(struct kvm_vcpu, arch.ceded));
+	DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
 	DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa));
 	DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
 	DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
@@ -481,6 +481,7 @@ int main(void)
 	DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
 	DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
 	DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
+	DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
 	DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
 			   offsetof(struct kvmppc_vcpu_book3s, vcpu));
 	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
@@ -537,6 +538,8 @@ int main(void)
 	HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
 	HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
 	HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
+	HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
+	HSTATE_FIELD(HSTATE_NAPPING, napping);
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
@@ -549,6 +552,7 @@ int main(void)
 	HSTATE_FIELD(HSTATE_DSCR, host_dscr);
 	HSTATE_FIELD(HSTATE_DABR, dabr);
 	HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+	DEFINE(IPI_PRIORITY, IPI_PRIORITY);
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 #else /* CONFIG_PPC_BOOK3S */
@@ -609,5 +613,12 @@ int main(void)
 					arch.timing_last_enter.tv32.tbl));
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+	DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
+	DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
+	DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
+	DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
+#endif
+
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/btext.c linux-libre-3.2-gnu1/arch/powerpc/kernel/btext.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/btext.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/btext.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memblock.h>
 
 #include <asm/sections.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/clock.c linux-libre-3.2-gnu1/arch/powerpc/kernel/clock.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/clk_interface.h>
 
 struct clk_interface clk_functions;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/cputable.c linux-libre-3.2-gnu1/arch/powerpc/kernel/cputable.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/cputable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/cputable.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/oprofile_impl.h>
 #include <asm/cputable.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/crash.c linux-libre-3.2-gnu1/arch/powerpc/kernel/crash.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/crash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/crash.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/reboot.h>
 #include <linux/kexec.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/crash_dump.h>
 #include <linux/delay.h>
 #include <linux/elf.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/dma.c linux-libre-3.2-gnu1/arch/powerpc/kernel/dma.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/dma-debug.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/export.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 #include <asm/machdep.h>
@@ -96,6 +97,18 @@ static int dma_direct_dma_supported(stru
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+	u64 end, mask;
+
+	end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
 					     struct page *page,
 					     unsigned long offset,
@@ -137,13 +150,14 @@ static inline void dma_direct_sync_singl
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-	.alloc_coherent	= dma_direct_alloc_coherent,
-	.free_coherent	= dma_direct_free_coherent,
-	.map_sg		= dma_direct_map_sg,
-	.unmap_sg	= dma_direct_unmap_sg,
-	.dma_supported	= dma_direct_dma_supported,
-	.map_page	= dma_direct_map_page,
-	.unmap_page	= dma_direct_unmap_page,
+	.alloc_coherent			= dma_direct_alloc_coherent,
+	.free_coherent			= dma_direct_free_coherent,
+	.map_sg				= dma_direct_map_sg,
+	.unmap_sg			= dma_direct_unmap_sg,
+	.dma_supported			= dma_direct_dma_supported,
+	.map_page			= dma_direct_map_page,
+	.unmap_page			= dma_direct_unmap_page,
+	.get_required_mask		= dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
 	.sync_single_for_cpu 		= dma_direct_sync_single,
 	.sync_single_for_device 	= dma_direct_sync_single,
@@ -170,6 +184,23 @@ int dma_set_mask(struct device *dev, u64
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (ppc_md.dma_get_required_mask)
+		return ppc_md.dma_get_required_mask(dev);
+
+	if (unlikely(dma_ops == NULL))
+		return 0;
+
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
+
+	return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/dma-iommu.c linux-libre-3.2-gnu1/arch/powerpc/kernel/dma-iommu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/dma-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/dma-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
  * busses using the iommu infrastructure
  */
 
+#include <linux/export.h>
 #include <asm/iommu.h>
 
 /*
@@ -90,13 +91,27 @@ static int dma_iommu_dma_supported(struc
 		return 1;
 }
 
+static u64 dma_iommu_get_required_mask(struct device *dev)
+{
+	struct iommu_table *tbl = get_iommu_table_base(dev);
+	u64 mask;
+	if (!tbl)
+		return 0;
+
+	mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
-	.alloc_coherent	= dma_iommu_alloc_coherent,
-	.free_coherent	= dma_iommu_free_coherent,
-	.map_sg		= dma_iommu_map_sg,
-	.unmap_sg	= dma_iommu_unmap_sg,
-	.dma_supported	= dma_iommu_dma_supported,
-	.map_page	= dma_iommu_map_page,
-	.unmap_page	= dma_iommu_unmap_page,
+	.alloc_coherent		= dma_iommu_alloc_coherent,
+	.free_coherent		= dma_iommu_free_coherent,
+	.map_sg			= dma_iommu_map_sg,
+	.unmap_sg		= dma_iommu_unmap_sg,
+	.dma_supported		= dma_iommu_dma_supported,
+	.map_page		= dma_iommu_map_page,
+	.unmap_page		= dma_iommu_unmap_page,
+	.get_required_mask	= dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/dma-swiotlb.c linux-libre-3.2-gnu1/arch/powerpc/kernel/dma-swiotlb.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/dma-swiotlb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/dma-swiotlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,21 @@
 
 unsigned int ppc_swiotlb_enable;
 
+static u64 swiotlb_powerpc_get_required(struct device *dev)
+{
+	u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+	end = memblock_end_of_DRAM();
+	if (max_direct_dma_addr && end > max_direct_dma_addr)
+		end = max_direct_dma_addr;
+	end += get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 /*
  * At the moment, all platforms that use this code only require
  * swiotlb to be used if we're operating on HIGHMEM.  Since
@@ -44,6 +59,7 @@ struct dma_map_ops swiotlb_dma_ops = {
 	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
 	.sync_sg_for_device = swiotlb_sync_sg_for_device,
 	.mapping_error = swiotlb_dma_mapping_error,
+	.get_required_mask = swiotlb_powerpc_get_required,
 };
 
 void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/entry_32.S linux-libre-3.2-gnu1/arch/powerpc/kernel/entry_32.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/entry_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/entry_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -215,7 +215,22 @@ reenable_mmu:				/* re-enable mmu so we
 	stw	r9,8(r1)
 	stw	r11,12(r1)
 	stw	r3,ORIG_GPR3(r1)
+	/*
+	 * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
+	 * If from user mode there is only one stack frame on the stack, and
+	 * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
+	 * stack frame to make trace_hardirqs_off happy.
+	 */
+	andi.	r12,r12,MSR_PR
+	beq	11f
+	stwu	r1,-16(r1)
 	bl	trace_hardirqs_off
+	addi	r1,r1,16
+	b	12f
+
+11:
+	bl	trace_hardirqs_off
+12:
 	lwz	r0,GPR0(r1)
 	lwz	r3,ORIG_GPR3(r1)
 	lwz	r4,GPR4(r1)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/exceptions-64s.S linux-libre-3.2-gnu1/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/exceptions-64s.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/exceptions-64s.S	2012-01-04 18:55:44.000000000 -0500
@@ -267,7 +267,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
 
 	STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
@@ -275,7 +275,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
 
 	STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
@@ -283,7 +283,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
 	. = 0x3000
@@ -427,16 +427,6 @@ slb_miss_user_pseries:
 	b	.				/* prevent spec. execution */
 #endif /* __DISABLED__ */
 
-/* KVM's trampoline code needs to be close to the interrupt handlers */
-
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#ifdef CONFIG_KVM_BOOK3S_PR
-#include "../kvm/book3s_rmhandlers.S"
-#else
-#include "../kvm/book3s_hv_rmhandlers.S"
-#endif
-#endif
-
 	.align	7
 	.globl	__end_interrupts
 __end_interrupts:
@@ -1143,7 +1133,7 @@ _GLOBAL(do_stab_bolted)
 	rfid
 	b	.	/* prevent speculative execution */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
  * This address (0x7000) is fixed by the RPA.
@@ -1151,7 +1141,7 @@ _GLOBAL(do_stab_bolted)
 	.= 0x7000
 	.globl fwnmi_data_area
 fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 	/* iSeries does not use the FWNMI stuff, so it is safe to put
 	 * this here, even if we later allow kernels that will boot on
@@ -1176,9 +1166,12 @@ xLparMap:
 
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
+	/* pseries and powernv need to keep the whole page from
+	 * 0x7000 to 0x8000 free for use by the firmware
+	 */
         . = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 /*
  * Space for CPU0's segment table.
@@ -1193,3 +1186,19 @@ xLparMap:
 	.globl initial_stab
 initial_stab:
 	.space	4096
+#ifdef CONFIG_PPC_POWERNV
+_GLOBAL(opal_mc_secondary_handler)
+	HMT_MEDIUM
+	SET_SCRATCH0(r13)
+	GET_PACA(r13)
+	clrldi	r3,r3,2
+	tovirt(r3,r3)
+	std	r3,PACA_OPAL_MC_EVT(r13)
+	ld	r13,OPAL_MC_SRR0(r3)
+	mtspr	SPRN_SRR0,r13
+	ld	r13,OPAL_MC_SRR1(r3)
+	mtspr	SPRN_SRR1,r13
+	ld	r3,OPAL_MC_GPR3(r3)
+	GET_SCRATCH0(r13)
+	b	machine_check_pSeries
+#endif /* CONFIG_PPC_POWERNV */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/firmware.c linux-libre-3.2-gnu1/arch/powerpc/kernel/firmware.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/firmware.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/firmware.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/cache.h>
 
 #include <asm/firmware.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_32.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_32.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -139,8 +139,7 @@ __start:
 	trap
 #endif /* CONFIG_PPC_PMAC */
 
-1:	mr	r31,r3			/* save parameters */
-	mr	r30,r4
+1:	mr	r31,r3			/* save device tree ptr */
 	li	r24,0			/* cpu # */
 
 /*
@@ -964,8 +963,8 @@ start_here:
  * Do early platform-specific initialization,
  * and set up the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	__save_cpu_setup
 	bl	MMU_init
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_40x.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_40x.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_40x.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_40x.S	2012-01-04 18:55:44.000000000 -0500
@@ -58,13 +58,7 @@
 _ENTRY(_stext);
 _ENTRY(_start);
 
-	/* Save parameters we are passed.
-	*/
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3			/* save device tree ptr */
 
 	/* We have to turn on the MMU right away so we get cache modes
 	 * set correctly.
@@ -849,11 +843,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_44x.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_44x.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_44x.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_44x.S	2012-01-04 18:55:44.000000000 -0500
@@ -61,14 +61,7 @@ _ENTRY(_start);
 	 * of abatron_pteptrs
 	 */
 	nop
-/*
- * Save parameters we are passed
- */
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3		/* save device tree ptr */
 	li	r24,0		/* CPU number */
 
 	bl	init_cpu_state
@@ -120,11 +113,8 @@ _ENTRY(_start);
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_64.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_64.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,11 @@
  *  For pSeries or server processors:
  *   1. The MMU is off & open firmware is running in real mode.
  *   2. The kernel is entered at __start
+ * -or- For OPAL entry:
+ *   1. The MMU is off, processor in HV mode, primary CPU enters at 0
+ *      with device-tree in gpr3. We also get OPAL base in r8 and
+ *	entry in r9 for debugging purposes
+ *   2. Secondary processors enter at 0x60 with PIR in gpr3
  *
  *  For iSeries:
  *   1. The MMU is on (as it always is for iSeries)
@@ -331,6 +336,11 @@ _GLOBAL(__start_initialization_multiplat
 	/* Save parameters */
 	mr	r31,r3
 	mr	r30,r4
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* Save OPAL entry */
+	mr	r28,r8
+	mr	r29,r9
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
 	bl	.start_initialization_book3e
@@ -674,9 +684,9 @@ _GLOBAL(enable_64b_mode)
 _GLOBAL(relative_toc)
 	mflr	r0
 	bcl	20,31,$+4
-0:	mflr	r9
-	ld	r2,(p_toc - 0b)(r9)
-	add	r2,r2,r9
+0:	mflr	r11
+	ld	r2,(p_toc - 0b)(r11)
+	add	r2,r2,r11
 	mtlr	r0
 	blr
 
@@ -707,6 +717,12 @@ _INIT_STATIC(start_here_multiplatform)
 	bdnz	3b
 4:
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* Setup OPAL entry */
+	std	r28,0(r11);
+	std	r29,8(r11);
+#endif
+
 #ifndef CONFIG_PPC_BOOK3E
 	mfmsr	r6
 	ori	r6,r6,MSR_RI
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_8xx.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_8xx.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_8xx.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_8xx.S	2012-01-04 18:55:44.000000000 -0500
@@ -76,11 +76,7 @@ _ENTRY(_start);
  */
 	.globl	__start
 __start:
-	mr	r31,r3			/* save parameters */
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3			/* save device tree ptr */
 
 	/* We have to turn on the MMU right away so we get cache modes
 	 * set correctly.
@@ -723,11 +719,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/head_fsl_booke.S linux-libre-3.2-gnu1/arch/powerpc/kernel/head_fsl_booke.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/head_fsl_booke.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/head_fsl_booke.S	2012-01-04 18:55:44.000000000 -0500
@@ -63,17 +63,30 @@ _ENTRY(_start);
 	 * of abatron_pteptrs
 	 */
 	nop
-/*
- * Save parameters we are passed
- */
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
-	li	r25,0		/* phys kernel start (low) */
-	li	r24,0		/* CPU number */
-	li	r23,0		/* phys kernel start (high) */
+
+	/* Translate device tree address to physical, save in r30/r31 */
+	mfmsr	r16
+	mfspr	r17,SPRN_PID
+	rlwinm	r17,r17,16,0x3fff0000	/* turn PID into MAS6[SPID] */
+	rlwimi	r17,r16,28,0x00000001	/* turn MSR[DS] into MAS6[SAS] */
+	mtspr	SPRN_MAS6,r17
+
+	tlbsx	0,r3			/* must succeed */
+
+	mfspr	r16,SPRN_MAS1
+	mfspr	r20,SPRN_MAS3
+	rlwinm	r17,r16,25,0x1f		/* r17 = log2(page size) */
+	li	r18,1024
+	slw	r18,r18,r17		/* r18 = page size */
+	addi	r18,r18,-1
+	and	r19,r3,r18		/* r19 = page offset */
+	andc	r31,r20,r18		/* r31 = page base */
+	or	r31,r31,r19		/* r31 = devtree phys addr */
+	mfspr	r30,SPRN_MAS7
+
+	li	r25,0			/* phys kernel start (low) */
+	li	r24,0			/* CPU number */
+	li	r23,0			/* phys kernel start (high) */
 
 /* We try to not make any assumptions about how the boot loader
  * setup or used the TLBs.  We invalidate all mappings from the
@@ -198,11 +211,8 @@ _ENTRY(__early_start)
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	mr	r3,r30
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
@@ -236,8 +246,24 @@ _ENTRY(__early_start)
  * if we find the pte (fall through):
  *   r11 is low pte word
  *   r12 is pointer to the pte
+ *   r10 is the pshift from the PGD, if we're a hugepage
  */
 #ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_HUGETLB_PAGE
+#define FIND_PTE	\
+	rlwinm	r12, r10, 13, 19, 29;	/* Compute pgdir/pmd offset */	\
+	lwzx	r11, r12, r11;		/* Get pgd/pmd entry */		\
+	rlwinm.	r12, r11, 0, 0, 20;	/* Extract pt base address */	\
+	blt	1000f;			/* Normal non-huge page */	\
+	beq	2f;			/* Bail if no table */		\
+	oris	r11, r11, PD_HUGE@h;	/* Put back address bit */	\
+	andi.	r10, r11, HUGEPD_SHIFT_MASK@l; /* extract size field */	\
+	xor	r12, r10, r11;		/* drop size bits from pointer */ \
+	b	1001f;							\
+1000:	rlwimi	r12, r10, 23, 20, 28;	/* Compute pte address */	\
+	li	r10, 0;			/* clear r10 */			\
+1001:	lwz	r11, 4(r12);		/* Get pte entry */
+#else
 #define FIND_PTE	\
 	rlwinm	r12, r10, 13, 19, 29;	/* Compute pgdir/pmd offset */	\
 	lwzx	r11, r12, r11;		/* Get pgd/pmd entry */		\
@@ -245,7 +271,8 @@ _ENTRY(__early_start)
 	beq	2f;			/* Bail if no table */		\
 	rlwimi	r12, r10, 23, 20, 28;	/* Compute pte address */	\
 	lwz	r11, 4(r12);		/* Get pte entry */
-#else
+#endif /* HUGEPAGE */
+#else /* !PTE_64BIT */
 #define FIND_PTE	\
 	rlwimi	r11, r10, 12, 20, 29;	/* Create L1 (pgdir/pmd) address */	\
 	lwz	r11, 0(r11);		/* Get L1 entry */			\
@@ -402,8 +429,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-	subf	r10,r11,r12		/* create false data dep */
-	lwzx	r13,r11,r10		/* Get upper pte bits */
+	subf	r13,r11,r12		/* create false data dep */
+	lwzx	r13,r11,r13		/* Get upper pte bits */
 #else
 	lwz	r13,0(r12)		/* Get upper pte bits */
 #endif
@@ -483,8 +510,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-	subf	r10,r11,r12		/* create false data dep */
-	lwzx	r13,r11,r10		/* Get upper pte bits */
+	subf	r13,r11,r12		/* create false data dep */
+	lwzx	r13,r11,r13		/* Get upper pte bits */
 #else
 	lwz	r13,0(r12)		/* Get upper pte bits */
 #endif
@@ -548,7 +575,7 @@ interrupt_base:
 /*
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
- *	r10 - available to use
+ *	r10 - tsize encoding (if HUGETLB_PAGE) or available to use
  *	r11 - TLB (info from Linux PTE)
  *	r12 - available to use
  *	r13 - upper bits of PTE (if PTE_64BIT) or available to use
@@ -558,21 +585,73 @@ interrupt_base:
  *	Upon exit, we reload everything and RFI.
  */
 finish_tlb_load:
+#ifdef CONFIG_HUGETLB_PAGE
+	cmpwi	6, r10, 0			/* check for huge page */
+	beq	6, finish_tlb_load_cont    	/* !huge */
+
+	/* Alas, we need more scratch registers for hugepages */
+	mfspr	r12, SPRN_SPRG_THREAD
+	stw	r14, THREAD_NORMSAVE(4)(r12)
+	stw	r15, THREAD_NORMSAVE(5)(r12)
+	stw	r16, THREAD_NORMSAVE(6)(r12)
+	stw	r17, THREAD_NORMSAVE(7)(r12)
+
+	/* Get the next_tlbcam_idx percpu var */
+#ifdef CONFIG_SMP
+	lwz	r12, THREAD_INFO-THREAD(r12)
+	lwz	r15, TI_CPU(r12)
+	lis     r14, __per_cpu_offset@h
+	ori     r14, r14, __per_cpu_offset@l
+	rlwinm  r15, r15, 2, 0, 29
+	lwzx    r16, r14, r15
+#else
+	li	r16, 0
+#endif
+	lis     r17, next_tlbcam_idx@h
+	ori	r17, r17, next_tlbcam_idx@l
+	add	r17, r17, r16			/* r17 = *next_tlbcam_idx */
+	lwz     r15, 0(r17)			/* r15 = next_tlbcam_idx */
+
+	lis	r14, MAS0_TLBSEL(1)@h		/* select TLB1 (TLBCAM) */
+	rlwimi	r14, r15, 16, 4, 15		/* next_tlbcam_idx entry */
+	mtspr	SPRN_MAS0, r14
+
+	/* Extract TLB1CFG(NENTRY) */
+	mfspr	r16, SPRN_TLB1CFG
+	andi.	r16, r16, 0xfff
+
+	/* Update next_tlbcam_idx, wrapping when necessary */
+	addi	r15, r15, 1
+	cmpw	r15, r16
+	blt 	100f
+	lis	r14, tlbcam_index@h
+	ori	r14, r14, tlbcam_index@l
+	lwz	r15, 0(r14)
+100:	stw	r15, 0(r17)
+
+	/*
+	 * Calc MAS1_TSIZE from r10 (which has pshift encoded)
+	 * tlb_enc = (pshift - 10).
+	 */
+	subi	r15, r10, 10
+	mfspr	r16, SPRN_MAS1
+	rlwimi	r16, r15, 7, 20, 24
+	mtspr	SPRN_MAS1, r16
+
+	/* copy the pshift for use later */
+	mr	r14, r10
+
+	/* fall through */
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
 	/*
 	 * We set execute, because we don't have the granularity to
 	 * properly set this at the page level (Linux problem).
 	 * Many of these bits are software only.  Bits we don't set
 	 * here we (properly should) assume have the appropriate value.
 	 */
-
-	mfspr	r12, SPRN_MAS2
-#ifdef CONFIG_PTE_64BIT
-	rlwimi	r12, r11, 32-19, 27, 31	/* extract WIMGE from pte */
-#else
-	rlwimi	r12, r11, 26, 27, 31	/* extract WIMGE from pte */
-#endif
-	mtspr	SPRN_MAS2, r12
-
+finish_tlb_load_cont:
 #ifdef CONFIG_PTE_64BIT
 	rlwinm	r12, r11, 32-2, 26, 31	/* Move in perm bits */
 	andi.	r10, r11, _PAGE_DIRTY
@@ -581,22 +660,40 @@ finish_tlb_load:
 	andc	r12, r12, r10
 1:	rlwimi	r12, r13, 20, 0, 11	/* grab RPN[32:43] */
 	rlwimi	r12, r11, 20, 12, 19	/* grab RPN[44:51] */
-	mtspr	SPRN_MAS3, r12
+2:	mtspr	SPRN_MAS3, r12
 BEGIN_MMU_FTR_SECTION
 	srwi	r10, r13, 12		/* grab RPN[12:31] */
 	mtspr	SPRN_MAS7, r10
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
 #else
 	li	r10, (_PAGE_EXEC | _PAGE_PRESENT)
+	mr	r13, r11
 	rlwimi	r10, r11, 31, 29, 29	/* extract _PAGE_DIRTY into SW */
 	and	r12, r11, r10
 	andi.	r10, r11, _PAGE_USER	/* Test for _PAGE_USER */
 	slwi	r10, r12, 1
 	or	r10, r10, r12
 	iseleq	r12, r12, r10
-	rlwimi	r11, r12, 0, 20, 31	/* Extract RPN from PTE and merge with perms */
-	mtspr	SPRN_MAS3, r11
+	rlwimi	r13, r12, 0, 20, 31	/* Get RPN from PTE, merge w/ perms */
+	mtspr	SPRN_MAS3, r13
 #endif
+
+	mfspr	r12, SPRN_MAS2
+#ifdef CONFIG_PTE_64BIT
+	rlwimi	r12, r11, 32-19, 27, 31	/* extract WIMGE from pte */
+#else
+	rlwimi	r12, r11, 26, 27, 31	/* extract WIMGE from pte */
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	beq	6, 3f			/* don't mask if page isn't huge */
+	li	r13, 1
+	slw	r13, r13, r14
+	subi	r13, r13, 1
+	rlwinm	r13, r13, 0, 0, 19	/* bottom bits used for WIMGE/etc */
+	andc	r12, r12, r13		/* mask off ea bits within the page */
+#endif
+3:	mtspr	SPRN_MAS2, r12
+
 #ifdef CONFIG_E200
 	/* Round robin TLB1 entries assignment */
 	mfspr	r12, SPRN_MAS0
@@ -622,11 +719,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PH
 	mtspr	SPRN_MAS0,r12
 #endif /* CONFIG_E200 */
 
+tlb_write_entry:
 	tlbwe
 
 	/* Done...restore registers and get out of here.  */
 	mfspr	r10, SPRN_SPRG_THREAD
-	lwz	r11, THREAD_NORMSAVE(3)(r10)
+#ifdef CONFIG_HUGETLB_PAGE
+	beq	6, 8f /* skip restore for 4k page faults */
+	lwz	r14, THREAD_NORMSAVE(4)(r10)
+	lwz	r15, THREAD_NORMSAVE(5)(r10)
+	lwz	r16, THREAD_NORMSAVE(6)(r10)
+	lwz	r17, THREAD_NORMSAVE(7)(r10)
+#endif
+8:	lwz	r11, THREAD_NORMSAVE(3)(r10)
 	mtcr	r11
 	lwz	r13, THREAD_NORMSAVE(2)(r10)
 	lwz	r12, THREAD_NORMSAVE(1)(r10)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/hw_breakpoint.c linux-libre-3.2-gnu1/arch/powerpc/kernel/hw_breakpoint.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/hw_breakpoint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/hw_breakpoint.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 #include <linux/kprobes.h>
 #include <linux/percpu.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/ibmebus.c linux-libre-3.2-gnu1/arch/powerpc/kernel/ibmebus.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/ibmebus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/ibmebus.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,12 +37,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/console.h>
 #include <linux/kobject.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/of_platform.h>
 #include <asm/ibmebus.h>
 #include <asm/abs_addr.h>
@@ -125,17 +127,23 @@ static void ibmebus_unmap_sg(struct devi
 
 static int ibmebus_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	return mask == DMA_BIT_MASK(64);
+}
+
+static u64 ibmebus_dma_get_required_mask(struct device *dev)
+{
+	return DMA_BIT_MASK(64);
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-	.alloc_coherent = ibmebus_alloc_coherent,
-	.free_coherent  = ibmebus_free_coherent,
-	.map_sg         = ibmebus_map_sg,
-	.unmap_sg       = ibmebus_unmap_sg,
-	.dma_supported  = ibmebus_dma_supported,
-	.map_page       = ibmebus_map_page,
-	.unmap_page     = ibmebus_unmap_page,
+	.alloc_coherent     = ibmebus_alloc_coherent,
+	.free_coherent      = ibmebus_free_coherent,
+	.map_sg             = ibmebus_map_sg,
+	.unmap_sg           = ibmebus_unmap_sg,
+	.dma_supported      = ibmebus_dma_supported,
+	.get_required_mask  = ibmebus_dma_get_required_mask,
+	.map_page           = ibmebus_map_page,
+	.unmap_page         = ibmebus_unmap_page,
 };
 
 static int ibmebus_match_path(struct device *dev, void *data)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/idle_e500.S linux-libre-3.2-gnu1/arch/powerpc/kernel/idle_e500.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/idle_e500.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/idle_e500.S	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@ _GLOBAL(e500_idle)
 	ori	r4,r4,_TLF_NAPPING	/* so when we take an exception */
 	stw	r4,TI_LOCAL_FLAGS(r3)	/* it will return to our caller */
 
-#ifdef CONFIG_E500MC
+#ifdef CONFIG_PPC_E500MC
 	wrteei	1
 1:	wait
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/init_task.c linux-libre-3.2-gnu1/arch/powerpc/kernel/init_task.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/init_task.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/io.c linux-libre-3.2-gnu1/arch/powerpc/kernel/io.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/firmware.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/iomap.c linux-libre-3.2-gnu1/arch/powerpc/kernel/iomap.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/iommu.c linux-libre-3.2-gnu1/arch/powerpc/kernel/iommu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -501,6 +501,14 @@ struct iommu_table *iommu_init_table(str
 	tbl->it_map = page_address(page);
 	memset(tbl->it_map, 0, sz);
 
+	/*
+	 * Reserve page 0 so it will not be used for any mappings.
+	 * This avoids buggy drivers that consider page 0 to be invalid
+	 * to crash the machine or even lose data.
+	 */
+	if (tbl->it_offset == 0)
+		set_bit(0, tbl->it_map);
+
 	tbl->it_hint = 0;
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/io-workarounds.c linux-libre-3.2-gnu1/arch/powerpc/kernel/io-workarounds.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/io-workarounds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/io-workarounds.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/sched.h>	/* for init_mm */
 
 #include <asm/io.h>
 #include <asm/machdep.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/irq.c linux-libre-3.2-gnu1/arch/powerpc/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/threads.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/isa-bridge.c linux-libre-3.2-gnu1/arch/powerpc/kernel/isa-bridge.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/isa-bridge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/isa-bridge.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/notifier.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/jump_label.c linux-libre-3.2-gnu1/arch/powerpc/kernel/jump_label.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/jump_label.h>
 #include <asm/code-patching.h>
 
+#ifdef HAVE_JUMP_LABEL
 void arch_jump_label_transform(struct jump_entry *entry,
 			       enum jump_label_type type)
 {
@@ -21,3 +22,4 @@ void arch_jump_label_transform(struct ju
 	else
 		patch_instruction(addr, PPC_INST_NOP);
 }
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/kvm.c linux-libre-3.2-gnu1/arch/powerpc/kernel/kvm.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/kvm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/kvm.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/kvm_para.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -131,7 +132,6 @@ static void kvm_patch_ins_b(u32 *inst, i
 	/* On relocatable kernels interrupts handlers and our code
 	   can be in different regions, so we don't patch them */
 
-	extern u32 __end_interrupts;
 	if ((ulong)inst < (ulong)&__end_interrupts)
 		return;
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/legacy_serial.c linux-libre-3.2-gnu1/arch/powerpc/kernel/legacy_serial.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/legacy_serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/legacy_serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/serial_reg.h>
 #include <asm/io.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
@@ -47,6 +48,24 @@ static struct __initdata of_device_id le
 static unsigned int legacy_serial_count;
 static int legacy_serial_console = -1;
 
+static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int tmp;
+	offset = offset << p->regshift;
+	if (offset == UART_IIR) {
+		tmp = readl(p->membase + (UART_IIR & ~3));
+		return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+	} else
+		return readb(p->membase + offset);
+}
+
+static void tsi_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+		writeb(value, p->membase + offset);
+}
+
 static int __init add_legacy_port(struct device_node *np, int want_index,
 				  int iotype, phys_addr_t base,
 				  phys_addr_t taddr, unsigned long irq,
@@ -102,6 +121,7 @@ static int __init add_legacy_port(struct
 		legacy_serial_ports[index].iobase = base;
 	else
 		legacy_serial_ports[index].mapbase = base;
+
 	legacy_serial_ports[index].iotype = iotype;
 	legacy_serial_ports[index].uartclk = clock;
 	legacy_serial_ports[index].irq = irq;
@@ -112,6 +132,11 @@ static int __init add_legacy_port(struct
 	legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
 	legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
+	if (iotype == UPIO_TSI) {
+		legacy_serial_ports[index].serial_in = tsi_serial_in;
+		legacy_serial_ports[index].serial_out = tsi_serial_out;
+	}
+
 	printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
 	       index, np->full_name);
 	printk(KERN_DEBUG "  %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/machine_kexec_64.c linux-libre-3.2-gnu1/arch/powerpc/kernel/machine_kexec_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/machine_kexec_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/machine_kexec_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,7 @@ int default_machine_kexec_prepare(struct
 	}
 
 	/* We also should not overwrite the tce tables */
-	for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
-			node = of_find_node_by_type(node, "pci")) {
+	for_each_node_by_type(node, "pci") {
 		basep = of_get_property(node, "linux,tce-base", NULL);
 		sizep = of_get_property(node, "linux,tce-size", NULL);
 		if (basep == NULL || sizep == NULL)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/misc_32.S linux-libre-3.2-gnu1/arch/powerpc/kernel/misc_32.S
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/misc_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/misc_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,8 @@
  * kexec bits:
  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * PPC44x port. Copyright (C) 2011,  IBM Corporation
+ * 		Author: Suzuki Poulose <suzuki@in.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -736,6 +738,175 @@ relocate_new_kernel:
 	mr      r5, r31
 
 	li	r0, 0
+#elif defined(CONFIG_44x)  && !defined(CONFIG_PPC_47x)
+
+/*
+ * Code for setting up 1:1 mapping for PPC440x for KEXEC
+ *
+ * We cannot switch off the MMU on PPC44x.
+ * So we:
+ * 1) Invalidate all the mappings except the one we are running from.
+ * 2) Create a tmp mapping for our code in the other address space(TS) and
+ *    jump to it. Invalidate the entry we started in.
+ * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
+ * 4) Jump to the 1:1 mapping in original TS.
+ * 5) Invalidate the tmp mapping.
+ *
+ * - Based on the kexec support code for FSL BookE
+ * - Doesn't support 47x yet.
+ *
+ */
+	/* Save our parameters */
+	mr	r29, r3
+	mr	r30, r4
+	mr	r31, r5
+
+	/* Load our MSR_IS and TID to MMUCR for TLB search */
+	mfspr	r3,SPRN_PID
+	mfmsr	r4
+	andi.	r4,r4,MSR_IS@l
+	beq	wmmucr
+	oris	r3,r3,PPC44x_MMUCR_STS@h
+wmmucr:
+	mtspr	SPRN_MMUCR,r3
+	sync
+
+	/*
+	 * Invalidate all the TLB entries except the current entry
+	 * where we are running from
+	 */
+	bl	0f				/* Find our address */
+0:	mflr	r5				/* Make it accessible */
+	tlbsx	r23,0,r5			/* Find entry we are in */
+	li	r4,0				/* Start at TLB entry 0 */
+	li	r3,0				/* Set PAGEID inval value */
+1:	cmpw	r23,r4				/* Is this our entry? */
+	beq	skip				/* If so, skip the inval */
+	tlbwe	r3,r4,PPC44x_TLB_PAGEID		/* If not, inval the entry */
+skip:
+	addi	r4,r4,1				/* Increment */
+	cmpwi	r4,64				/* Are we done?	*/
+	bne	1b				/* If not, repeat */
+	isync
+
+	/* Create a temp mapping and jump to it */
+	andi.	r6, r23, 1		/* Find the index to use */
+	addi	r24, r6, 1		/* r24 will contain 1 or 2 */
+
+	mfmsr	r9			/* get the MSR */
+	rlwinm	r5, r9, 27, 31, 31	/* Extract the MSR[IS] */
+	xori	r7, r5, 1		/* Use the other address space */
+
+	/* Read the current mapping entries */
+	tlbre	r3, r23, PPC44x_TLB_PAGEID
+	tlbre	r4, r23, PPC44x_TLB_XLAT
+	tlbre	r5, r23, PPC44x_TLB_ATTRIB
+
+	/* Save our current XLAT entry */
+	mr	r25, r4
+
+	/* Extract the TLB PageSize */
+	li	r10, 1 			/* r10 will hold PageSize */
+	rlwinm	r11, r3, 0, 24, 27	/* bits 24-27 */
+
+	/* XXX: As of now we use 256M, 4K pages */
+	cmpwi	r11, PPC44x_TLB_256M
+	bne	tlb_4k
+	rotlwi	r10, r10, 28		/* r10 = 256M */
+	b	write_out
+tlb_4k:
+	cmpwi	r11, PPC44x_TLB_4K
+	bne	default
+	rotlwi	r10, r10, 12		/* r10 = 4K */
+	b	write_out
+default:
+	rotlwi	r10, r10, 10		/* r10 = 1K */
+
+write_out:
+	/*
+	 * Write out the tmp 1:1 mapping for this code in other address space
+	 * Fixup  EPN = RPN , TS=other address space
+	 */
+	insrwi	r3, r7, 1, 23		/* Bit 23 is TS for PAGEID field */
+
+	/* Write out the tmp mapping entries */
+	tlbwe	r3, r24, PPC44x_TLB_PAGEID
+	tlbwe	r4, r24, PPC44x_TLB_XLAT
+	tlbwe	r5, r24, PPC44x_TLB_ATTRIB
+
+	subi	r11, r10, 1		/* PageOffset Mask = PageSize - 1 */
+	not	r10, r11		/* Mask for PageNum */
+
+	/* Switch to other address space in MSR */
+	insrwi	r9, r7, 1, 26		/* Set MSR[IS] = r7 */
+
+	bl	1f
+1:	mflr	r8
+	addi	r8, r8, (2f-1b)		/* Find the target offset */
+
+	/* Jump to the tmp mapping */
+	mtspr	SPRN_SRR0, r8
+	mtspr	SPRN_SRR1, r9
+	rfi
+
+2:
+	/* Invalidate the entry we were executing from */
+	li	r3, 0
+	tlbwe	r3, r23, PPC44x_TLB_PAGEID
+
+	/* attribute fields. rwx for SUPERVISOR mode */
+	li	r5, 0
+	ori	r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+
+	/* Create 1:1 mapping in 256M pages */
+	xori	r7, r7, 1			/* Revert back to Original TS */
+
+	li	r8, 0				/* PageNumber */
+	li	r6, 3				/* TLB Index, start at 3  */
+
+next_tlb:
+	rotlwi	r3, r8, 28			/* Create EPN (bits 0-3) */
+	mr	r4, r3				/* RPN = EPN  */
+	ori	r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
+	insrwi	r3, r7, 1, 23			/* Set TS from r7 */
+
+	tlbwe	r3, r6, PPC44x_TLB_PAGEID	/* PageID field : EPN, V, SIZE */
+	tlbwe	r4, r6, PPC44x_TLB_XLAT		/* Address translation : RPN   */
+	tlbwe	r5, r6, PPC44x_TLB_ATTRIB	/* Attributes */
+
+	addi	r8, r8, 1			/* Increment PN */
+	addi	r6, r6, 1			/* Increment TLB Index */
+	cmpwi	r8, 8				/* Are we done ? */
+	bne	next_tlb
+	isync
+
+	/* Jump to the new mapping 1:1 */
+	li	r9,0
+	insrwi	r9, r7, 1, 26			/* Set MSR[IS] = r7 */
+
+	bl	1f
+1:	mflr	r8
+	and	r8, r8, r11			/* Get our offset within page */
+	addi	r8, r8, (2f-1b)
+
+	and	r5, r25, r10			/* Get our target PageNum */
+	or	r8, r8, r5			/* Target jump address */
+
+	mtspr	SPRN_SRR0, r8
+	mtspr	SPRN_SRR1, r9
+	rfi
+2:
+	/* Invalidate the tmp entry we used */
+	li	r3, 0
+	tlbwe	r3, r24, PPC44x_TLB_PAGEID
+	sync
+
+	/* Restore the parameters */
+	mr	r3, r29
+	mr	r4, r30
+	mr	r5, r31
+
+	li	r0, 0
 #else
 	li	r0, 0
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/module.c linux-libre-3.2-gnu1/arch/powerpc/kernel/module.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
-#include <linux/module.h>
 #include <linux/elf.h>
 #include <linux/moduleloader.h>
 #include <linux/err.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/of_platform.c linux-libre-3.2-gnu1/arch/powerpc/kernel/of_platform.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/of_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/of_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/pci.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/paca.c linux-libre-3.2-gnu1/arch/powerpc/kernel/paca.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/paca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/paca.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  */
 
 #include <linux/smp.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memblock.h>
 
 #include <asm/firmware.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_32.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_32.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_64.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pci-common.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pci-common.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pci-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pci-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
 #include <linux/mm.h>
@@ -1730,6 +1731,17 @@ void __devinit pcibios_scan_phb(struct p
 
 	if (mode == PCI_PROBE_NORMAL)
 		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+
+	/* Configure PCI Express settings */
+	if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+		struct pci_bus *child;
+		list_for_each_entry(child, &bus->children, node) {
+			struct pci_dev *self = child->self;
+			if (!self)
+				continue;
+			pcie_bus_configure_settings(child, self->pcie_mpss);
+		}
+	}
 }
 
 static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_dn.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_dn.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_dn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_dn.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/gfp.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_of_scan.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_of_scan.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pci_of_scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pci_of_scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/pci-bridge.h>
 #include <asm/prom.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/pmc.c linux-libre-3.2-gnu1/arch/powerpc/kernel/pmc.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/errno.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/cputable.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/power6-pmu.c linux-libre-3.2-gnu1/arch/powerpc/kernel/power6-pmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/power6-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/power6-pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -487,8 +487,8 @@ static int power6_generic_events[] = {
  */
 static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
-		[C(OP_READ)] = {	0x80082,	0x80080		},
-		[C(OP_WRITE)] = {	0x80086,	0x80088		},
+		[C(OP_READ)] = {	0x280030,	0x80080		},
+		[C(OP_WRITE)] = {	0x180032,	0x80088		},
 		[C(OP_PREFETCH)] = {	0x810a4,	0		},
 	},
 	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/power7-pmu.c linux-libre-3.2-gnu1/arch/powerpc/kernel/power7-pmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/power7-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/power7-pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -297,6 +297,8 @@ static void power7_disable_pmc(unsigned
 
 static int power7_generic_events[] = {
 	[PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
 	[PERF_COUNT_HW_INSTRUCTIONS] = 2,
 	[PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,	/* LD_REF_L1_LSU*/
 	[PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,		/* LD_MISS_L1	*/
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/ppc_ksyms.c linux-libre-3.2-gnu1/arch/powerpc/kernel/ppc_ksyms.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/ppc_ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/ppc_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/process.c linux-libre-3.2-gnu1/arch/powerpc/kernel/process.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/prctl.h>
 #include <linux/init_task.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kallsyms.h>
 #include <linux/mqueue.h>
 #include <linux/hardirq.h>
@@ -486,28 +486,6 @@ struct task_struct *__switch_to(struct t
 	new_thread = &new->thread;
 	old_thread = &current->thread;
 
-#if defined(CONFIG_PPC_BOOK3E_64)
-	/* XXX Current Book3E code doesn't deal with kernel side DBCR0,
-	 * we always hold the user values, so we set it now.
-	 *
-	 * However, we ensure the kernel MSR:DE is appropriately cleared too
-	 * to avoid spurrious single step exceptions in the kernel.
-	 *
-	 * This will have to change to merge with the ppc32 code at some point,
-	 * but I don't like much what ppc32 is doing today so there's some
-	 * thinking needed there
-	 */
-	if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) {
-		u32 dbcr0;
-
-		mtmsr(mfmsr() & ~MSR_DE);
-		isync();
-		dbcr0 = mfspr(SPRN_DBCR0);
-		dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0;
-		mtspr(SPRN_DBCR0, dbcr0);
-	}
-#endif /* CONFIG_PPC64_BOOK3E */
-
 #ifdef CONFIG_PPC64
 	/*
 	 * Collect processor utilization data per process
@@ -657,7 +635,7 @@ void show_regs(struct pt_regs * regs)
 	if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
 		printk("CFAR: "REG"\n", regs->orig_gpr3);
 	if (trap == 0x300 || trap == 0x600)
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 		printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
 		printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/prom.c linux-libre-3.2-gnu1/arch/powerpc/kernel/prom.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/delay.h>
 #include <linux/initrd.h>
 #include <linux/bitops.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kexec.h>
 #include <linux/debugfs.h>
 #include <linux/irq.h>
@@ -54,6 +54,8 @@
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
+#include <asm/opal.h>
+
 #include <mm/mmu_decl.h>
 
 #ifdef DEBUG
@@ -707,11 +709,23 @@ void __init early_init_devtree(void *par
 	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+	/* Some machines might need OPAL info for debugging, grab it now. */
+	of_scan_flat_dt(early_init_dt_scan_opal, NULL);
+#endif
+
 #ifdef CONFIG_PHYP_DUMP
 	/* scan tree to see if dump occurred during last boot */
 	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 #endif
 
+	/* Pre-initialize the cmd_line with the content of boot_commmand_line,
+	 * which will be empty except when the content of the variable has
+	 * been overriden by a bootloading mechanism. This happens typically
+	 * with HAL takeover
+	 */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
 	/* Retrieve various informations from the /chosen node of the
 	 * device-tree, including the platform type, initrd location and
 	 * size, TCE reserve, and more ...
@@ -723,12 +737,15 @@ void __init early_init_devtree(void *par
 
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
-	setup_initial_memory_limit(memstart_addr, first_memblock_size);
 
 	/* Save command line for /proc/cmdline and then parse parameters */
 	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 
+	/* make sure we've parsed cmdline for mem= before this */
+	if (memory_limit)
+		first_memblock_size = min(first_memblock_size, memory_limit);
+	setup_initial_memory_limit(memstart_addr, first_memblock_size);
 	/* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
 	memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
 	/* If relocatable, reserve first 32k for interrupt vectors etc. */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_init.c linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_init.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
+#include <asm/opal.h>
 
 #include <linux/linux_logo.h>
 
@@ -139,7 +140,9 @@ struct mem_map_entry {
 
 typedef u32 cell_t;
 
-extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
+		    unsigned long r6, unsigned long r7, unsigned long r8,
+		    unsigned long r9);
 
 #ifdef CONFIG_PPC64
 extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -185,6 +188,7 @@ static unsigned long __initdata prom_tce
 #define PLATFORM_LPAR		0x0001
 #define PLATFORM_POWERMAC	0x0400
 #define PLATFORM_GENERIC	0x0500
+#define PLATFORM_OPAL		0x0600
 
 static int __initdata of_platform;
 
@@ -644,7 +648,7 @@ static void __init early_cmdline_parse(v
 	}
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * There are two methods for telling firmware what our capabilities are.
  * Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1278,284 @@ static void __init prom_init_mem(void)
 	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
 }
 
+static void __init prom_close_stdin(void)
+{
+	struct prom_t *_prom = &RELOC(prom);
+	ihandle val;
+
+	if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
+		call_prom("close", 1, 0, val);
+}
+
+#ifdef CONFIG_PPC_POWERNV
+
+static u64 __initdata prom_opal_size;
+static u64 __initdata prom_opal_align;
+static int __initdata prom_rtas_start_cpu;
+static u64 __initdata prom_rtas_data;
+static u64 __initdata prom_rtas_entry;
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+static u64 __initdata prom_opal_base;
+static u64 __initdata prom_opal_entry;
+#endif
+
+/* XXX Don't change this structure without updating opal-takeover.S */
+static struct opal_secondary_data {
+	s64				ack;	/*  0 */
+	u64				go;	/*  8 */
+	struct opal_takeover_args	args;	/* 16 */
+} opal_secondary_data;
+
+extern char opal_secondary_entry;
+
+static void prom_query_opal(void)
+{
+	long rc;
+
+	/* We must not query for OPAL presence on a machine that
+	 * supports TNK takeover (970 blades), as this uses the same
+	 * h-call with different arguments and will crash
+	 */
+	if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
+				    ADDR("/tnk-memory-map")))) {
+		prom_printf("TNK takeover detected, skipping OPAL check\n");
+		return;
+	}
+
+	prom_printf("Querying for OPAL presence... ");
+	rc = opal_query_takeover(&RELOC(prom_opal_size),
+				 &RELOC(prom_opal_align));
+	prom_debug("(rc = %ld) ", rc);
+	if (rc != 0) {
+		prom_printf("not there.\n");
+		return;
+	}
+	RELOC(of_platform) = PLATFORM_OPAL;
+	prom_printf(" there !\n");
+	prom_debug("  opal_size  = 0x%lx\n", RELOC(prom_opal_size));
+	prom_debug("  opal_align = 0x%lx\n", RELOC(prom_opal_align));
+	if (RELOC(prom_opal_align) < 0x10000)
+		RELOC(prom_opal_align) = 0x10000;
+}
+
+static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+	struct rtas_args rtas_args;
+	va_list list;
+	int i;
+
+	rtas_args.token = token;
+	rtas_args.nargs = nargs;
+	rtas_args.nret  = nret;
+	rtas_args.rets  = (rtas_arg_t *)&(rtas_args.args[nargs]);
+	va_start(list, outputs);
+	for (i = 0; i < nargs; ++i)
+		rtas_args.args[i] = va_arg(list, rtas_arg_t);
+	va_end(list);
+
+	for (i = 0; i < nret; ++i)
+		rtas_args.rets[i] = 0;
+
+	opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
+			RELOC(prom_rtas_entry));
+
+	if (nret > 1 && outputs != NULL)
+		for (i = 0; i < nret-1; ++i)
+			outputs[i] = rtas_args.rets[i+1];
+	return (nret > 0)? rtas_args.rets[0]: 0;
+}
+
+static void __init prom_opal_hold_cpus(void)
+{
+	int i, cnt, cpu, rc;
+	long j;
+	phandle node;
+	char type[64];
+	u32 servers[8];
+	struct prom_t *_prom = &RELOC(prom);
+	void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
+	struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+
+	prom_debug("prom_opal_hold_cpus: start...\n");
+	prom_debug("    - entry       = 0x%x\n", entry);
+	prom_debug("    - data        = 0x%x\n", data);
+
+	data->ack = -1;
+	data->go = 0;
+
+	/* look for cpus */
+	for (node = 0; prom_next_node(&node); ) {
+		type[0] = 0;
+		prom_getprop(node, "device_type", type, sizeof(type));
+		if (strcmp(type, RELOC("cpu")) != 0)
+			continue;
+
+		/* Skip non-configured cpus. */
+		if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+			if (strcmp(type, RELOC("okay")) != 0)
+				continue;
+
+		cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
+			     sizeof(servers));
+		if (cnt == PROM_ERROR)
+			break;
+		cnt >>= 2;
+		for (i = 0; i < cnt; i++) {
+			cpu = servers[i];
+			prom_debug("CPU %d ... ", cpu);
+			if (cpu == _prom->cpu) {
+				prom_debug("booted !\n");
+				continue;
+			}
+			prom_debug("starting ... ");
+
+			/* Init the acknowledge var which will be reset by
+			 * the secondary cpu when it awakens from its OF
+			 * spinloop.
+			 */
+			data->ack = -1;
+			rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
+					    NULL, cpu, entry, data);
+			prom_debug("rtas rc=%d ...", rc);
+
+			for (j = 0; j < 100000000 && data->ack == -1; j++) {
+				HMT_low();
+				mb();
+			}
+			HMT_medium();
+			if (data->ack != -1)
+				prom_debug("done, PIR=0x%x\n", data->ack);
+			else
+				prom_debug("timeout !\n");
+		}
+	}
+	prom_debug("prom_opal_hold_cpus: end...\n");
+}
+
+static void prom_opal_takeover(void)
+{
+	struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+	struct opal_takeover_args *args = &data->args;
+	u64 align = RELOC(prom_opal_align);
+	u64 top_addr, opal_addr;
+
+	args->k_image	= (u64)RELOC(_stext);
+	args->k_size	= _end - _stext;
+	args->k_entry	= 0;
+	args->k_entry2	= 0x60;
+
+	top_addr = _ALIGN_UP(args->k_size, align);
+
+	if (RELOC(prom_initrd_start) != 0) {
+		args->rd_image = RELOC(prom_initrd_start);
+		args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
+		args->rd_loc = top_addr;
+		top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
+	}
+
+	/* Pickup an address for the HAL. We want to go really high
+	 * up to avoid problem with future kexecs. On the other hand
+	 * we don't want to be all over the TCEs on P5IOC2 machines
+	 * which are going to be up there too. We assume the machine
+	 * has plenty of memory, and we ask for the HAL for now to
+	 * be just below the 1G point, or above the initrd
+	 */
+	opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
+	if (opal_addr < top_addr)
+		opal_addr = top_addr;
+	args->hal_addr = opal_addr;
+
+	/* Copy the command line to the kernel image */
+	strlcpy(RELOC(boot_command_line), RELOC(prom_cmd_line),
+		COMMAND_LINE_SIZE);
+
+	prom_debug("  k_image    = 0x%lx\n", args->k_image);
+	prom_debug("  k_size     = 0x%lx\n", args->k_size);
+	prom_debug("  k_entry    = 0x%lx\n", args->k_entry);
+	prom_debug("  k_entry2   = 0x%lx\n", args->k_entry2);
+	prom_debug("  hal_addr   = 0x%lx\n", args->hal_addr);
+	prom_debug("  rd_image   = 0x%lx\n", args->rd_image);
+	prom_debug("  rd_size    = 0x%lx\n", args->rd_size);
+	prom_debug("  rd_loc     = 0x%lx\n", args->rd_loc);
+	prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
+	prom_close_stdin();
+	mb();
+	data->go = 1;
+	for (;;)
+		opal_do_takeover(args);
+}
+
+/*
+ * Allocate room for and instantiate OPAL
+ */
+static void __init prom_instantiate_opal(void)
+{
+	phandle opal_node;
+	ihandle opal_inst;
+	u64 base, entry;
+	u64 size = 0, align = 0x10000;
+	u32 rets[2];
+
+	prom_debug("prom_instantiate_opal: start...\n");
+
+	opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
+	prom_debug("opal_node: %x\n", opal_node);
+	if (!PHANDLE_VALID(opal_node))
+		return;
+
+	prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
+	if (size == 0)
+		return;
+	prom_getprop(opal_node, "opal-runtime-alignment", &align,
+		     sizeof(align));
+
+	base = alloc_down(size, align, 0);
+	if (base == 0) {
+		prom_printf("OPAL allocation failed !\n");
+		return;
+	}
+
+	opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
+	if (!IHANDLE_VALID(opal_inst)) {
+		prom_printf("opening opal package failed (%x)\n", opal_inst);
+		return;
+	}
+
+	prom_printf("instantiating opal at 0x%x...", base);
+
+	if (call_prom_ret("call-method", 4, 3, rets,
+			  ADDR("load-opal-runtime"),
+			  opal_inst,
+			  base >> 32, base & 0xffffffff) != 0
+	    || (rets[0] == 0 && rets[1] == 0)) {
+		prom_printf(" failed\n");
+		return;
+	}
+	entry = (((u64)rets[0]) << 32) | rets[1];
+
+	prom_printf(" done\n");
+
+	reserve_mem(base, size);
+
+	prom_debug("opal base     = 0x%x\n", base);
+	prom_debug("opal align    = 0x%x\n", align);
+	prom_debug("opal entry    = 0x%x\n", entry);
+	prom_debug("opal size     = 0x%x\n", (long)size);
+
+	prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
+		     &base, sizeof(base));
+	prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
+		     &entry, sizeof(entry));
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	RELOC(prom_opal_base) = base;
+	RELOC(prom_opal_entry) = entry;
+#endif
+	prom_debug("prom_instantiate_opal: end...\n");
+}
+
+#endif /* CONFIG_PPC_POWERNV */
 
 /*
  * Allocate room for and instantiate RTAS
@@ -1297,10 +1579,8 @@ static void __init prom_instantiate_rtas
 		return;
 
 	base = alloc_down(size, PAGE_SIZE, 0);
-	if (base == 0) {
-		prom_printf("RTAS allocation failed !\n");
-		return;
-	}
+	if (base == 0)
+		prom_panic("Could not allocate memory for RTAS\n");
 
 	rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
 	if (!IHANDLE_VALID(rtas_inst)) {
@@ -1326,6 +1606,12 @@ static void __init prom_instantiate_rtas
 	prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
 		     &entry, sizeof(entry));
 
+#ifdef CONFIG_PPC_POWERNV
+	/* PowerVN takeover hack */
+	RELOC(prom_rtas_data) = base;
+	RELOC(prom_rtas_entry) = entry;
+	prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
+#endif
 	prom_debug("rtas base     = 0x%x\n", base);
 	prom_debug("rtas entry    = 0x%x\n", entry);
 	prom_debug("rtas size     = 0x%x\n", (long)size);
@@ -1543,7 +1829,7 @@ static void __init prom_hold_cpus(void)
 		*acknowledge = (unsigned long)-1;
 
 		if (reg != _prom->cpu) {
-			/* Primary Thread of non-boot cpu */
+			/* Primary Thread of non-boot cpu or any thread */
 			prom_printf("starting cpu hw idx %lu... ", reg);
 			call_prom("start-cpu", 3, 0, node,
 				  secondary_hold, reg);
@@ -1652,15 +1938,6 @@ static void __init prom_init_stdout(void
 		prom_setprop(val, path, "linux,boot-display", NULL, 0);
 }
 
-static void __init prom_close_stdin(void)
-{
-	struct prom_t *_prom = &RELOC(prom);
-	ihandle val;
-
-	if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
-		call_prom("close", 1, 0, val);
-}
-
 static int __init prom_find_machine_type(void)
 {
 	struct prom_t *_prom = &RELOC(prom);
@@ -1671,7 +1948,7 @@ static int __init prom_find_machine_type
 	int x;
 #endif
 
-	/* Look for a PowerMac */
+	/* Look for a PowerMac or a Cell */
 	len = prom_getprop(_prom->root, "compatible",
 			   compat, sizeof(compat)-1);
 	if (len > 0) {
@@ -1697,7 +1974,11 @@ static int __init prom_find_machine_type
 		}
 	}
 #ifdef CONFIG_PPC64
-	/* If not a mac, try to figure out if it's an IBM pSeries or any other
+	/* Try to detect OPAL */
+	if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
+		return PLATFORM_OPAL;
+
+	/* Try to figure out if it's an IBM pSeries or any other
 	 * PAPR compliant platform. We assume it is if :
 	 *  - /device_type is "chrp" (please, do NOT use that for future
 	 *    non-IBM designs !
@@ -1924,7 +2205,7 @@ static void __init scan_dt_build_struct(
 	unsigned long soff;
 	unsigned char *valp;
 	static char pname[MAX_PROPERTY_NAME];
-	int l, room;
+	int l, room, has_phandle = 0;
 
 	dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -2008,19 +2289,26 @@ static void __init scan_dt_build_struct(
 		valp = make_room(mem_start, mem_end, l, 4);
 		call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
 		*mem_start = _ALIGN(*mem_start, 4);
+
+		if (!strcmp(RELOC(pname), RELOC("phandle")))
+			has_phandle = 1;
 	}
 
-	/* Add a "linux,phandle" property. */
-	soff = dt_find_string(RELOC("linux,phandle"));
-	if (soff == 0)
-		prom_printf("WARNING: Can't find string index for"
-			    " <linux-phandle> node %s\n", path);
-	else {
-		dt_push_token(OF_DT_PROP, mem_start, mem_end);
-		dt_push_token(4, mem_start, mem_end);
-		dt_push_token(soff, mem_start, mem_end);
-		valp = make_room(mem_start, mem_end, 4, 4);
-		*(u32 *)valp = node;
+	/* Add a "linux,phandle" property if no "phandle" property already
+	 * existed (can happen with OPAL)
+	 */
+	if (!has_phandle) {
+		soff = dt_find_string(RELOC("linux,phandle"));
+		if (soff == 0)
+			prom_printf("WARNING: Can't find string index for"
+				    " <linux-phandle> node %s\n", path);
+		else {
+			dt_push_token(OF_DT_PROP, mem_start, mem_end);
+			dt_push_token(4, mem_start, mem_end);
+			dt_push_token(soff, mem_start, mem_end);
+			valp = make_room(mem_start, mem_end, 4, 4);
+			*(u32 *)valp = node;
+		}
 	}
 
 	/* do all our children */
@@ -2504,6 +2792,7 @@ static void __init prom_check_initrd(uns
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -2553,6 +2842,7 @@ unsigned long __init prom_init(unsigned
 	 * between pSeries SMP and pSeries LPAR
 	 */
 	RELOC(of_platform) = prom_find_machine_type();
+	prom_printf("Detected machine type: %x\n", RELOC(of_platform));
 
 #ifndef CONFIG_RELOCATABLE
 	/* Bail if this is a kdump kernel. */
@@ -2565,7 +2855,7 @@ unsigned long __init prom_init(unsigned
 	 */
 	prom_check_initrd(r3, r4);
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 	/*
 	 * On pSeries, inform the firmware about our capabilities
 	 */
@@ -2611,14 +2901,33 @@ unsigned long __init prom_init(unsigned
 #endif
 
 	/*
-	 * On non-powermacs, try to instantiate RTAS and puts all CPUs
-	 * in spin-loops. PowerMacs don't have a working RTAS and use
-	 * a different way to spin CPUs
+	 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
+	 * have a usable RTAS implementation.
 	 */
-	if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+	if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+	    RELOC(of_platform) != PLATFORM_OPAL)
 		prom_instantiate_rtas();
+
+#ifdef CONFIG_PPC_POWERNV
+	/* Detect HAL and try instanciating it & doing takeover */
+	if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
+		prom_query_opal();
+		if (RELOC(of_platform) == PLATFORM_OPAL) {
+			prom_opal_hold_cpus();
+			prom_opal_takeover();
+		}
+	} else if (RELOC(of_platform) == PLATFORM_OPAL)
+		prom_instantiate_opal();
+#endif
+
+	/*
+	 * On non-powermacs, put all CPUs in spin-loops.
+	 *
+	 * PowerMacs use a different mechanism to spin CPUs
+	 */
+	if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+	    RELOC(of_platform) != PLATFORM_OPAL)
 		prom_hold_cpus();
-	}
 
 	/*
 	 * Fill in some infos for use by the kernel later on
@@ -2685,7 +2994,13 @@ unsigned long __init prom_init(unsigned
 	reloc_got2(-offset);
 #endif
 
-	__start(hdr, kbase, 0);
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* OPAL early debug gets the OPAL base & entry in r8 and r9 */
+	__start(hdr, kbase, 0, 0, 0,
+		RELOC(prom_opal_base), RELOC(prom_opal_entry));
+#else
+	__start(hdr, kbase, 0, 0, 0, 0, 0);
+#endif
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_init_check.sh linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_init_check.sh
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_init_check.sh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_init_check.sh	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,9 @@ WHITELIST="add_reloc_offset __bss_start
 _end enter_prom memcpy memset reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr linux_banner"
+reloc_got2 kernstart_addr memstart_addr linux_banner _stext
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
+boot_command_line"
 
 NM="$1"
 OBJ="$2"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_parse.c linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_parse.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/prom_parse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/prom_parse.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/ptrace.c linux-libre-3.2-gnu1/arch/powerpc/kernel/ptrace.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,6 @@
 #include <linux/seccomp.h>
 #include <linux/audit.h>
 #include <trace/syscall.h>
-#ifdef CONFIG_PPC32
-#include <linux/module.h>
-#endif
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
 
@@ -1497,9 +1494,14 @@ long arch_ptrace(struct task_struct *chi
 		if (index < PT_FPR0) {
 			tmp = ptrace_get_reg(child, (int) index);
 		} else {
+			unsigned int fpidx = index - PT_FPR0;
+
 			flush_fp_to_thread(child);
-			tmp = ((unsigned long *)child->thread.fpr)
-				[TS_FPRWIDTH * (index - PT_FPR0)];
+			if (fpidx < (PT_FPSCR - PT_FPR0))
+				tmp = ((unsigned long *)child->thread.fpr)
+					[fpidx * TS_FPRWIDTH];
+			else
+				tmp = child->thread.fpscr.val;
 		}
 		ret = put_user(tmp, datalp);
 		break;
@@ -1525,9 +1527,14 @@ long arch_ptrace(struct task_struct *chi
 		if (index < PT_FPR0) {
 			ret = ptrace_put_reg(child, index, data);
 		} else {
+			unsigned int fpidx = index - PT_FPR0;
+
 			flush_fp_to_thread(child);
-			((unsigned long *)child->thread.fpr)
-				[TS_FPRWIDTH * (index - PT_FPR0)] = data;
+			if (fpidx < (PT_FPSCR - PT_FPR0))
+				((unsigned long *)child->thread.fpr)
+					[fpidx * TS_FPRWIDTH] = data;
+			else
+				child->thread.fpscr.val = data;
 			ret = 0;
 		}
 		break;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/rtas.c linux-libre-3.2-gnu1/arch/powerpc/kernel/rtas.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/rtas.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/rtas.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/delay.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/setup_32.c linux-libre-3.2-gnu1/arch/powerpc/kernel/setup_32.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/setup_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/setup_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,8 @@ notrace unsigned long __init early_init(
 			 PTRRELOC(&__start___lwsync_fixup),
 			 PTRRELOC(&__stop___lwsync_fixup));
 
+	do_final_fixups();
+
 	return KERNELBASE + offset;
 }
 
@@ -117,7 +119,7 @@ notrace unsigned long __init early_init(
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(unsigned long dt_ptr)
+notrace void __init machine_init(u64 dt_ptr)
 {
 	lockdep_init();
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/setup_64.c linux-libre-3.2-gnu1/arch/powerpc/kernel/setup_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/setup_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/setup_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -278,14 +278,14 @@ static void __init initialize_cache_info
 
 	DBG(" -> initialize_cache_info()\n");
 
-	for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+	for_each_node_by_type(np, "cpu") {
 		num_cpus += 1;
 
-		/* We're assuming *all* of the CPUs have the same
+		/*
+		 * We're assuming *all* of the CPUs have the same
 		 * d-cache and i-cache sizes... -Peter
 		 */
-
-		if ( num_cpus == 1 ) {
+		if (num_cpus == 1) {
 			const u32 *sizep, *lsizep;
 			u32 size, lsize;
 
@@ -294,10 +294,13 @@ static void __init initialize_cache_info
 			sizep = of_get_property(np, "d-cache-size", NULL);
 			if (sizep != NULL)
 				size = *sizep;
-			lsizep = of_get_property(np, "d-cache-block-size", NULL);
+			lsizep = of_get_property(np, "d-cache-block-size",
+						 NULL);
 			/* fallback if block size missing */
 			if (lsizep == NULL)
-				lsizep = of_get_property(np, "d-cache-line-size", NULL);
+				lsizep = of_get_property(np,
+							 "d-cache-line-size",
+							 NULL);
 			if (lsizep != NULL)
 				lsize = *lsizep;
 			if (sizep == 0 || lsizep == 0)
@@ -314,9 +317,12 @@ static void __init initialize_cache_info
 			sizep = of_get_property(np, "i-cache-size", NULL);
 			if (sizep != NULL)
 				size = *sizep;
-			lsizep = of_get_property(np, "i-cache-block-size", NULL);
+			lsizep = of_get_property(np, "i-cache-block-size",
+						 NULL);
 			if (lsizep == NULL)
-				lsizep = of_get_property(np, "i-cache-line-size", NULL);
+				lsizep = of_get_property(np,
+							 "i-cache-line-size",
+							 NULL);
 			if (lsizep != NULL)
 				lsize = *lsizep;
 			if (sizep == 0 || lsizep == 0)
@@ -353,6 +359,7 @@ void __init setup_system(void)
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 	do_lwsync_fixups(cur_cpu_spec->cpu_features,
 			 &__start___lwsync_fixup, &__stop___lwsync_fixup);
+	do_final_fixups();
 
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/setup-common.c linux-libre-3.2-gnu1/arch/powerpc/kernel/setup-common.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/setup-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/setup-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/signal_32.c linux-libre-3.2-gnu1/arch/powerpc/kernel/signal_32.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/signal_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/signal_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,7 +97,7 @@ static inline int put_sigset_t(compat_si
 	compat_sigset_t	cset;
 
 	switch (_NSIG_WORDS) {
-	case 4: cset.sig[5] = set->sig[3] & 0xffffffffull;
+	case 4: cset.sig[6] = set->sig[3] & 0xffffffffull;
 		cset.sig[7] = set->sig[3] >> 32;
 	case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;
 		cset.sig[5] = set->sig[2] >> 32;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/signal_64.c linux-libre-3.2-gnu1/arch/powerpc/kernel/signal_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/signal_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/signal_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/stddef.h>
 #include <linux/elf.h>
 #include <linux/ptrace.h>
-#include <linux/module.h>
 #include <linux/ratelimit.h>
 
 #include <asm/sigcontext.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/smp.c linux-libre-3.2-gnu1/arch/powerpc/kernel/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
@@ -70,6 +70,10 @@
 static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
 #define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
 #define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+
+/* State of each CPU during hotplug phases */
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
 #else
 static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define get_idle_for_cpu(x)      (idle_thread_array[(x)])
@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int n
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
-	paca[nr].cpu_start = 1;
-	smp_mb();
+	if (!paca[nr].cpu_start) {
+		paca[nr].cpu_start = 1;
+		smp_mb();
+		return 0;
+	}
+
+#ifdef CONFIG_HOTPLUG_CPU
+	/*
+	 * Ok it's not there, so it might be soft-unplugged, let's
+	 * try to bring it back
+	 */
+	per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+	smp_wmb();
+	smp_send_reschedule(nr);
+#endif /* CONFIG_HOTPLUG_CPU */
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_PPC64 */
 
 static irqreturn_t call_function_action(int irq, void *data)
 {
@@ -170,7 +187,7 @@ int smp_request_message_ipi(int virq, in
 		return 1;
 	}
 #endif
-	err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+	err = request_irq(virq, smp_ipi_action[msg], IRQF_PERCPU,
 			  smp_ipi_name[msg], 0);
 	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
 		virq, smp_ipi_name[msg], err);
@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* State of each CPU during hotplug phases */
-static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int c
 {
 	per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
+
+int generic_check_cpu_restart(unsigned int cpu)
+{
+	return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
+}
 #endif
 
 struct create_idle {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/stacktrace.c linux-libre-3.2-gnu1/arch/powerpc/kernel/stacktrace.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <asm/ptrace.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/swsusp_64.c linux-libre-3.2-gnu1/arch/powerpc/kernel/swsusp_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/swsusp_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/swsusp_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <asm/system.h>
 #include <asm/iommu.h>
 #include <linux/irq.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 void do_after_copyback(void)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/swsusp.c linux-libre-3.2-gnu1/arch/powerpc/kernel/swsusp.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/swsusp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/swsusp.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,6 @@ void save_processor_state(void)
 void restore_processor_state(void)
 {
 #ifdef CONFIG_PPC32
-	switch_mmu_context(NULL, current->active_mm);
+	switch_mmu_context(current->active_mm, current->active_mm);
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/sysfs.c linux-libre-3.2-gnu1/arch/powerpc/kernel/sysfs.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/cpumask.h>
 #include <linux/notifier.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/time.c linux-libre-3.2-gnu1/arch/powerpc/kernel/time.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/traps.c linux-libre-3.2-gnu1/arch/powerpc/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,7 +457,14 @@ int machine_check_e500mc(struct pt_regs
 
 	if (reason & MCSR_DCPERR_MC) {
 		printk("Data Cache Parity Error\n");
-		recoverable = 0;
+
+		/*
+		 * In write shadow mode we auto-recover from the error, but it
+		 * may still get logged and cause a machine check.  We should
+		 * only treat the non-write shadow case as non-recoverable.
+		 */
+		if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
+			recoverable = 0;
 	}
 
 	if (reason & MCSR_L2MMU_MHIT) {
@@ -1291,14 +1298,12 @@ void __kprobes DebugException(struct pt_
 
 		if (user_mode(regs)) {
 			current->thread.dbcr0 &= ~DBCR0_IC;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 			if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
 					       current->thread.dbcr1))
 				regs->msr |= MSR_DE;
 			else
 				/* Make sure the IDM bit is off */
 				current->thread.dbcr0 &= ~DBCR0_IDM;
-#endif
 		}
 
 		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/udbg.c linux-libre-3.2-gnu1/arch/powerpc/kernel/udbg.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/udbg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/udbg.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,6 +67,14 @@ void __init udbg_early_init(void)
 	udbg_init_usbgecko();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP)
 	udbg_init_wsp();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
+	udbg_init_ehv_bc();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC)
+	udbg_init_ps3gelic();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW)
+	udbg_init_debug_opal_raw();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI)
+	udbg_init_debug_opal_hvsi();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/vdso.c linux-libre-3.2-gnu1/arch/powerpc/kernel/vdso.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/vdso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kernel/vio.c linux-libre-3.2-gnu1/arch/powerpc/kernel/vio.c
--- linux-libre-3.1-gnu1/arch/powerpc/kernel/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kernel/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,12 @@
  */
 
 #include <linux/types.h>
+#include <linux/stat.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/console.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/kobject.h>
@@ -605,15 +606,20 @@ static int vio_dma_iommu_dma_supported(s
         return dma_iommu_ops.dma_supported(dev, mask);
 }
 
-struct dma_map_ops vio_dma_mapping_ops = {
-	.alloc_coherent = vio_dma_iommu_alloc_coherent,
-	.free_coherent  = vio_dma_iommu_free_coherent,
-	.map_sg         = vio_dma_iommu_map_sg,
-	.unmap_sg       = vio_dma_iommu_unmap_sg,
-	.map_page       = vio_dma_iommu_map_page,
-	.unmap_page     = vio_dma_iommu_unmap_page,
-	.dma_supported  = vio_dma_iommu_dma_supported,
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
 
+struct dma_map_ops vio_dma_mapping_ops = {
+	.alloc_coherent    = vio_dma_iommu_alloc_coherent,
+	.free_coherent     = vio_dma_iommu_free_coherent,
+	.map_sg            = vio_dma_iommu_map_sg,
+	.unmap_sg          = vio_dma_iommu_unmap_sg,
+	.map_page          = vio_dma_iommu_map_page,
+	.unmap_page        = vio_dma_iommu_unmap_page,
+	.dma_supported     = vio_dma_iommu_dma_supported,
+	.get_required_mask = vio_dma_get_required_mask,
 };
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/44x.c linux-libre-3.2-gnu1/arch/powerpc/kvm/44x.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/44x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/44x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -78,6 +79,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vc
 	for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
 		vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
+	vcpu->arch.cpu_type = KVM_CPU_440;
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_32_sr.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_32_sr.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_32_sr.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_32_sr.S	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 	 * R1 = host R1
 	 * R2 = host R2
 	 * R3 = shadow vcpu
-	 * all other volatile GPRS = free
+	 * all other volatile GPRS = free except R4, R6
 	 * SVCPU[CR]  = guest CR
 	 * SVCPU[XER] = guest XER
 	 * SVCPU[CTR] = guest CTR
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_64_mmu.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_64_mmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_64_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_64_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,7 +128,13 @@ static hva_t kvmppc_mmu_book3s_64_get_pt
 	dprintk("MMU: page=0x%x sdr1=0x%llx pteg=0x%llx vsid=0x%llx\n",
 		page, vcpu_book3s->sdr1, pteg, slbe->vsid);
 
-	r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+	/* When running a PAPR guest, SDR1 contains a HVA address instead
+           of a GPA */
+	if (vcpu_book3s->vcpu.arch.papr_enabled)
+		r = pteg;
+	else
+		r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+
 	if (kvm_is_error_hva(r))
 		return r;
 	return r | (pteg & ~PAGE_MASK);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_64_slb.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_64_slb.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_64_slb.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_64_slb.S	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@ slb_exit_skip_ ## num:
 	 * R1 = host R1
 	 * R2 = host R2
 	 * R3 = shadow vcpu
-	 * all other volatile GPRS = free
+	 * all other volatile GPRS = free except R4, R6
 	 * SVCPU[CR]  = guest CR
 	 * SVCPU[XER] = guest XER
 	 * SVCPU[CTR] = guest CTR
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include <asm/reg.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_emulate.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_emulate.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_emulate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_emulate.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,25 @@
  * function pointers, so let's just disable the define. */
 #undef mfsrin
 
+enum priv_level {
+	PRIV_PROBLEM = 0,
+	PRIV_SUPER = 1,
+	PRIV_HYPER = 2,
+};
+
+static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
+{
+	/* PAPR VMs only access supervisor SPRs */
+	if (vcpu->arch.papr_enabled && (level > PRIV_SUPER))
+		return false;
+
+	/* Limit user space to its own small SPR set */
+	if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM)
+		return false;
+
+	return true;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -296,6 +315,8 @@ int kvmppc_core_emulate_mtspr(struct kvm
 
 	switch (sprn) {
 	case SPRN_SDR1:
+		if (!spr_allowed(vcpu, PRIV_HYPER))
+			goto unprivileged;
 		to_book3s(vcpu)->sdr1 = spr_val;
 		break;
 	case SPRN_DSISR:
@@ -390,6 +411,7 @@ int kvmppc_core_emulate_mtspr(struct kvm
 	case SPRN_PMC4_GEKKO:
 	case SPRN_WPAR_GEKKO:
 		break;
+unprivileged:
 	default:
 		printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
 #ifndef DEBUG_SPR
@@ -421,6 +443,8 @@ int kvmppc_core_emulate_mfspr(struct kvm
 		break;
 	}
 	case SPRN_SDR1:
+		if (!spr_allowed(vcpu, PRIV_HYPER))
+			goto unprivileged;
 		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
 		break;
 	case SPRN_DSISR:
@@ -449,6 +473,10 @@ int kvmppc_core_emulate_mfspr(struct kvm
 	case SPRN_HID5:
 		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
 		break;
+	case SPRN_CFAR:
+	case SPRN_PURR:
+		kvmppc_set_gpr(vcpu, rt, 0);
+		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
 	case SPRN_GQR2:
@@ -476,6 +504,7 @@ int kvmppc_core_emulate_mfspr(struct kvm
 		kvmppc_set_gpr(vcpu, rt, 0);
 		break;
 	default:
+unprivileged:
 		printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
 #ifndef DEBUG_SPR
 		emulated = EMULATE_FAIL;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_exports.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_exports.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,15 +17,13 @@
  * Authors: Alexander Graf <agraf@suse.de>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/kvm_book3s.h>
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
 #else
-EXPORT_SYMBOL_GPL(kvmppc_handler_trampoline_enter);
-EXPORT_SYMBOL_GPL(kvmppc_handler_lowmem_trampoline);
-EXPORT_SYMBOL_GPL(kvmppc_rmcall);
+EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
 EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_builtin.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_builtin.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_builtin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_builtin.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/preempt.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/bootmem.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/preempt.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/anon_inodes.h>
 #include <linux/cpumask.h>
@@ -43,6 +44,7 @@
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
+#include <asm/hvcall.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
@@ -62,6 +64,8 @@
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	local_paca->kvm_hstate.kvm_vcpu = vcpu;
@@ -72,40 +76,10 @@ void kvmppc_core_vcpu_put(struct kvm_vcp
 {
 }
 
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu);
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu);
-
-void kvmppc_vcpu_block(struct kvm_vcpu *vcpu)
-{
-	u64 now;
-	unsigned long dec_nsec;
-
-	now = get_tb();
-	if (now >= vcpu->arch.dec_expires && !kvmppc_core_pending_dec(vcpu))
-		kvmppc_core_queue_dec(vcpu);
-	if (vcpu->arch.pending_exceptions)
-		return;
-	if (vcpu->arch.dec_expires != ~(u64)0) {
-		dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC /
-			tb_ticks_per_sec;
-		hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
-			      HRTIMER_MODE_REL);
-	}
-
-	kvmppc_vcpu_blocked(vcpu);
-
-	kvm_vcpu_block(vcpu);
-	vcpu->stat.halt_wakeup++;
-
-	if (vcpu->arch.dec_expires != ~(u64)0)
-		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-
-	kvmppc_vcpu_unblocked(vcpu);
-}
-
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
 {
 	vcpu->arch.shregs.msr = msr;
+	kvmppc_end_cede(vcpu);
 }
 
 void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
@@ -257,15 +231,6 @@ int kvmppc_pseries_do_hcall(struct kvm_v
 
 	switch (req) {
 	case H_CEDE:
-		vcpu->arch.shregs.msr |= MSR_EE;
-		vcpu->arch.ceded = 1;
-		smp_mb();
-		if (!vcpu->arch.prodded)
-			kvmppc_vcpu_block(vcpu);
-		else
-			vcpu->arch.prodded = 0;
-		smp_mb();
-		vcpu->arch.ceded = 0;
 		break;
 	case H_PROD:
 		target = kvmppc_get_gpr(vcpu, 4);
@@ -388,20 +353,6 @@ static int kvmppc_handle_exit(struct kvm
 		break;
 	}
 
-
-	if (!(r & RESUME_HOST)) {
-		/* To avoid clobbering exit_reason, only check for signals if
-		 * we aren't already exiting to userspace for some other
-		 * reason. */
-		if (signal_pending(tsk)) {
-			vcpu->stat.signal_exits++;
-			run->exit_reason = KVM_EXIT_INTR;
-			r = -EINTR;
-		} else {
-			kvmppc_core_deliver_interrupts(vcpu);
-		}
-	}
-
 	return r;
 }
 
@@ -479,13 +430,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 	kvmppc_mmu_book3s_hv_init(vcpu);
 
 	/*
-	 * Some vcpus may start out in stopped state.  If we initialize
-	 * them to busy-in-host state they will stop other vcpus in the
-	 * vcore from running.  Instead we initialize them to blocked
-	 * state, effectively considering them to be stopped until we
-	 * see the first run ioctl for them.
+	 * We consider the vcpu stopped until we see the first run ioctl for it.
 	 */
-	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+	vcpu->arch.state = KVMPPC_VCPU_STOPPED;
 
 	init_waitqueue_head(&vcpu->arch.cpu_run);
 
@@ -496,6 +443,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 		if (vcore) {
 			INIT_LIST_HEAD(&vcore->runnable_threads);
 			spin_lock_init(&vcore->lock);
+			init_waitqueue_head(&vcore->wq);
 		}
 		kvm->arch.vcores[core] = vcore;
 	}
@@ -506,10 +454,12 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 
 	spin_lock(&vcore->lock);
 	++vcore->num_threads;
-	++vcore->n_blocked;
 	spin_unlock(&vcore->lock);
 	vcpu->arch.vcore = vcore;
 
+	vcpu->arch.cpu_type = KVM_CPU_3S_64;
+	kvmppc_sanity_check(vcpu);
+
 	return vcpu;
 
 free_vcpu:
@@ -524,30 +474,31 @@ void kvmppc_core_vcpu_free(struct kvm_vc
 	kfree(vcpu);
 }
 
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu)
+static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+	unsigned long dec_nsec, now;
 
-	spin_lock(&vc->lock);
-	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
-	++vc->n_blocked;
-	if (vc->n_runnable > 0 &&
-	    vc->n_runnable + vc->n_blocked == vc->num_threads) {
-		vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
-					arch.run_list);
-		wake_up(&vcpu->arch.cpu_run);
+	now = get_tb();
+	if (now > vcpu->arch.dec_expires) {
+		/* decrementer has already gone negative */
+		kvmppc_core_queue_dec(vcpu);
+		kvmppc_core_deliver_interrupts(vcpu);
+		return;
 	}
-	spin_unlock(&vc->lock);
+	dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC
+		   / tb_ticks_per_sec;
+	hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
+		      HRTIMER_MODE_REL);
+	vcpu->arch.timer_running = 1;
 }
 
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu)
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcore *vc = vcpu->arch.vcore;
-
-	spin_lock(&vc->lock);
-	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-	--vc->n_blocked;
-	spin_unlock(&vc->lock);
+	vcpu->arch.ceded = 0;
+	if (vcpu->arch.timer_running) {
+		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+		vcpu->arch.timer_running = 0;
+	}
 }
 
 extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
@@ -562,6 +513,7 @@ static void kvmppc_remove_runnable(struc
 		return;
 	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
 	--vc->n_runnable;
+	++vc->n_busy;
 	/* decrement the physical thread id of each following vcpu */
 	v = vcpu;
 	list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
@@ -575,15 +527,20 @@ static void kvmppc_start_thread(struct k
 	struct paca_struct *tpaca;
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
+	if (vcpu->arch.timer_running) {
+		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+		vcpu->arch.timer_running = 0;
+	}
 	cpu = vc->pcpu + vcpu->arch.ptid;
 	tpaca = &paca[cpu];
 	tpaca->kvm_hstate.kvm_vcpu = vcpu;
 	tpaca->kvm_hstate.kvm_vcore = vc;
+	tpaca->kvm_hstate.napping = 0;
+	vcpu->cpu = vc->pcpu;
 	smp_wmb();
-#ifdef CONFIG_PPC_ICP_NATIVE
+#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
 	if (vcpu->arch.ptid) {
 		tpaca->cpu_start = 0x80;
-		tpaca->kvm_hstate.in_guest = KVM_GUEST_MODE_GUEST;
 		wmb();
 		xics_wake_cpu(cpu);
 		++vc->n_woken;
@@ -631,9 +588,10 @@ static int on_primary_thread(void)
  */
 static int kvmppc_run_core(struct kvmppc_vcore *vc)
 {
-	struct kvm_vcpu *vcpu, *vnext;
+	struct kvm_vcpu *vcpu, *vcpu0, *vnext;
 	long ret;
 	u64 now;
+	int ptid;
 
 	/* don't start if any threads have a signal pending */
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
@@ -652,29 +610,50 @@ static int kvmppc_run_core(struct kvmppc
 		goto out;
 	}
 
+	/*
+	 * Assign physical thread IDs, first to non-ceded vcpus
+	 * and then to ceded ones.
+	 */
+	ptid = 0;
+	vcpu0 = NULL;
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
+		if (!vcpu->arch.ceded) {
+			if (!ptid)
+				vcpu0 = vcpu;
+			vcpu->arch.ptid = ptid++;
+		}
+	}
+	if (!vcpu0)
+		return 0;		/* nothing to run */
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		if (vcpu->arch.ceded)
+			vcpu->arch.ptid = ptid++;
+
 	vc->n_woken = 0;
 	vc->nap_count = 0;
 	vc->entry_exit_count = 0;
-	vc->vcore_running = 1;
+	vc->vcore_state = VCORE_RUNNING;
 	vc->in_guest = 0;
 	vc->pcpu = smp_processor_id();
+	vc->napping_threads = 0;
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
 		kvmppc_start_thread(vcpu);
-	vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
-				arch.run_list);
 
+	preempt_disable();
 	spin_unlock(&vc->lock);
 
-	preempt_disable();
 	kvm_guest_enter();
-	__kvmppc_vcore_entry(NULL, vcpu);
+	__kvmppc_vcore_entry(NULL, vcpu0);
 
-	/* wait for secondary threads to finish writing their state to memory */
 	spin_lock(&vc->lock);
+	/* disable sending of IPIs on virtual external irqs */
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		vcpu->cpu = -1;
+	/* wait for secondary threads to finish writing their state to memory */
 	if (vc->nap_count < vc->n_woken)
 		kvmppc_wait_for_nap(vc);
 	/* prevent other vcpu threads from doing kvmppc_start_thread() now */
-	vc->vcore_running = 2;
+	vc->vcore_state = VCORE_EXITING;
 	spin_unlock(&vc->lock);
 
 	/* make sure updates to secondary vcpu structs are visible now */
@@ -690,22 +669,26 @@ static int kvmppc_run_core(struct kvmppc
 		if (now < vcpu->arch.dec_expires &&
 		    kvmppc_core_pending_dec(vcpu))
 			kvmppc_core_dequeue_dec(vcpu);
-		if (!vcpu->arch.trap) {
-			if (signal_pending(vcpu->arch.run_task)) {
-				vcpu->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
-				vcpu->arch.ret = -EINTR;
-			}
-			continue;		/* didn't get to run */
-		}
-		ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
-					 vcpu->arch.run_task);
+
+		ret = RESUME_GUEST;
+		if (vcpu->arch.trap)
+			ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
+						 vcpu->arch.run_task);
+
 		vcpu->arch.ret = ret;
 		vcpu->arch.trap = 0;
+
+		if (vcpu->arch.ceded) {
+			if (ret != RESUME_GUEST)
+				kvmppc_end_cede(vcpu);
+			else
+				kvmppc_set_timer(vcpu);
+		}
 	}
 
 	spin_lock(&vc->lock);
  out:
-	vc->vcore_running = 0;
+	vc->vcore_state = VCORE_INACTIVE;
 	list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
 				 arch.run_list) {
 		if (vcpu->arch.ret != RESUME_GUEST) {
@@ -717,82 +700,130 @@ static int kvmppc_run_core(struct kvmppc
 	return 1;
 }
 
-static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+/*
+ * Wait for some other vcpu thread to execute us, and
+ * wake us up when we need to handle something in the host.
+ */
+static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
 {
-	int ptid;
-	int wait_state;
-	struct kvmppc_vcore *vc;
 	DEFINE_WAIT(wait);
 
-	/* No need to go into the guest when all we do is going out */
-	if (signal_pending(current)) {
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		return -EINTR;
+	prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
+	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+		schedule();
+	finish_wait(&vcpu->arch.cpu_run, &wait);
+}
+
+/*
+ * All the vcpus in this vcore are idle, so wait for a decrementer
+ * or external interrupt to one of the vcpus.  vc->lock is held.
+ */
+static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
+{
+	DEFINE_WAIT(wait);
+	struct kvm_vcpu *v;
+	int all_idle = 1;
+
+	prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
+	vc->vcore_state = VCORE_SLEEPING;
+	spin_unlock(&vc->lock);
+	list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
+		if (!v->arch.ceded || v->arch.pending_exceptions) {
+			all_idle = 0;
+			break;
+		}
 	}
+	if (all_idle)
+		schedule();
+	finish_wait(&vc->wq, &wait);
+	spin_lock(&vc->lock);
+	vc->vcore_state = VCORE_INACTIVE;
+}
 
-	/* On PPC970, check that we have an RMA region */
-	if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
-		return -EPERM;
+static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	int n_ceded;
+	int prev_state;
+	struct kvmppc_vcore *vc;
+	struct kvm_vcpu *v, *vn;
 
 	kvm_run->exit_reason = 0;
 	vcpu->arch.ret = RESUME_GUEST;
 	vcpu->arch.trap = 0;
 
-	flush_fp_to_thread(current);
-	flush_altivec_to_thread(current);
-	flush_vsx_to_thread(current);
-
 	/*
 	 * Synchronize with other threads in this virtual core
 	 */
 	vc = vcpu->arch.vcore;
 	spin_lock(&vc->lock);
-	/* This happens the first time this is called for a vcpu */
-	if (vcpu->arch.state == KVMPPC_VCPU_BLOCKED)
-		--vc->n_blocked;
-	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
-	ptid = vc->n_runnable;
+	vcpu->arch.ceded = 0;
 	vcpu->arch.run_task = current;
 	vcpu->arch.kvm_run = kvm_run;
-	vcpu->arch.ptid = ptid;
+	prev_state = vcpu->arch.state;
+	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
 	list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
 	++vc->n_runnable;
 
-	wait_state = TASK_INTERRUPTIBLE;
-	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
-		if (signal_pending(current)) {
-			if (!vc->vcore_running) {
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				vcpu->arch.ret = -EINTR;
-				break;
-			}
-			/* have to wait for vcore to stop executing guest */
-			wait_state = TASK_UNINTERRUPTIBLE;
-			smp_send_reschedule(vc->pcpu);
+	/*
+	 * This happens the first time this is called for a vcpu.
+	 * If the vcore is already running, we may be able to start
+	 * this thread straight away and have it join in.
+	 */
+	if (prev_state == KVMPPC_VCPU_STOPPED) {
+		if (vc->vcore_state == VCORE_RUNNING &&
+		    VCORE_EXIT_COUNT(vc) == 0) {
+			vcpu->arch.ptid = vc->n_runnable - 1;
+			kvmppc_start_thread(vcpu);
 		}
 
-		if (!vc->vcore_running &&
-		    vc->n_runnable + vc->n_blocked == vc->num_threads) {
-			/* we can run now */
-			if (kvmppc_run_core(vc))
-				continue;
+	} else if (prev_state == KVMPPC_VCPU_BUSY_IN_HOST)
+		--vc->n_busy;
+
+	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
+	       !signal_pending(current)) {
+		if (vc->n_busy || vc->vcore_state != VCORE_INACTIVE) {
+			spin_unlock(&vc->lock);
+			kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
+			spin_lock(&vc->lock);
+			continue;
 		}
+		n_ceded = 0;
+		list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+			n_ceded += v->arch.ceded;
+		if (n_ceded == vc->n_runnable)
+			kvmppc_vcore_blocked(vc);
+		else
+			kvmppc_run_core(vc);
 
-		if (vc->vcore_running == 1 && VCORE_EXIT_COUNT(vc) == 0)
-			kvmppc_start_thread(vcpu);
+		list_for_each_entry_safe(v, vn, &vc->runnable_threads,
+					 arch.run_list) {
+			kvmppc_core_deliver_interrupts(v);
+			if (signal_pending(v->arch.run_task)) {
+				kvmppc_remove_runnable(vc, v);
+				v->stat.signal_exits++;
+				v->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
+				v->arch.ret = -EINTR;
+				wake_up(&v->arch.cpu_run);
+			}
+		}
+	}
 
-		/* wait for other threads to come in, or wait for vcore */
-		prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
-		spin_unlock(&vc->lock);
-		schedule();
-		finish_wait(&vcpu->arch.cpu_run, &wait);
-		spin_lock(&vc->lock);
+	if (signal_pending(current)) {
+		if (vc->vcore_state == VCORE_RUNNING ||
+		    vc->vcore_state == VCORE_EXITING) {
+			spin_unlock(&vc->lock);
+			kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
+			spin_lock(&vc->lock);
+		}
+		if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+			kvmppc_remove_runnable(vc, vcpu);
+			vcpu->stat.signal_exits++;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			vcpu->arch.ret = -EINTR;
+		}
 	}
 
-	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
-		kvmppc_remove_runnable(vc, vcpu);
 	spin_unlock(&vc->lock);
-
 	return vcpu->arch.ret;
 }
 
@@ -800,6 +831,26 @@ int kvmppc_vcpu_run(struct kvm_run *run,
 {
 	int r;
 
+	if (!vcpu->arch.sane) {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
+	/* No need to go into the guest when all we'll do is come back out */
+	if (signal_pending(current)) {
+		run->exit_reason = KVM_EXIT_INTR;
+		return -EINTR;
+	}
+
+	/* On PPC970, check that we have an RMA region */
+	if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
+		return -EPERM;
+
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
+	flush_vsx_to_thread(current);
+	vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+
 	do {
 		r = kvmppc_run_vcpu(run, vcpu);
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_rmhandlers.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_rmhandlers.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,10 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
+#include <asm/mmu.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/hvcall.h>
 #include <asm/asm-offsets.h>
 #include <asm/exception-64s.h>
 
@@ -49,7 +52,7 @@ kvmppc_skip_Hinterrupt:
 	b	.
 
 /*
- * Call kvmppc_handler_trampoline_enter in real mode.
+ * Call kvmppc_hv_entry in real mode.
  * Must be called with interrupts hard-disabled.
  *
  * Input Registers:
@@ -89,6 +92,12 @@ _GLOBAL(kvmppc_hv_entry_trampoline)
 kvm_start_guest:
 	ld	r1,PACAEMERGSP(r13)
 	subi	r1,r1,STACK_FRAME_OVERHEAD
+	ld	r2,PACATOC(r13)
+
+	/* were we napping due to cede? */
+	lbz	r0,HSTATE_NAPPING(r13)
+	cmpwi	r0,0
+	bne	kvm_end_cede
 
 	/* get vcpu pointer */
 	ld	r4, HSTATE_KVM_VCPU(r13)
@@ -276,15 +285,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	cmpwi	r0,0
 	beq	20b
 
-	/* Set LPCR.  Set the MER bit if there is a pending external irq. */
+	/* Set LPCR and RMOR. */
 10:	ld	r8,KVM_LPCR(r9)
-	ld	r0,VCPU_PENDING_EXC(r4)
-	li	r7,(1 << BOOK3S_IRQPRIO_EXTERNAL)
-	oris	r7,r7,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
-	and.	r0,r0,r7
-	beq	11f
-	ori	r8,r8,LPCR_MER
-11:	mtspr	SPRN_LPCR,r8
+	mtspr	SPRN_LPCR,r8
 	ld	r8,KVM_RMOR(r9)
 	mtspr	SPRN_RMOR,r8
 	isync
@@ -448,19 +451,50 @@ toc_tlbie_lock:
 	mtctr	r6
 	mtxer	r7
 
-	/* Move SRR0 and SRR1 into the respective regs */
+kvmppc_cede_reentry:		/* r4 = vcpu, r13 = paca */
 	ld	r6, VCPU_SRR0(r4)
 	ld	r7, VCPU_SRR1(r4)
-	mtspr	SPRN_SRR0, r6
-	mtspr	SPRN_SRR1, r7
-
 	ld	r10, VCPU_PC(r4)
+	ld	r11, VCPU_MSR(r4)	/* r11 = vcpu->arch.msr & ~MSR_HV */
 
-	ld	r11, VCPU_MSR(r4)	/* r10 = vcpu->arch.msr & ~MSR_HV */
 	rldicl	r11, r11, 63 - MSR_HV_LG, 1
 	rotldi	r11, r11, 1 + MSR_HV_LG
 	ori	r11, r11, MSR_ME
 
+	/* Check if we can deliver an external or decrementer interrupt now */
+	ld	r0,VCPU_PENDING_EXC(r4)
+	li	r8,(1 << BOOK3S_IRQPRIO_EXTERNAL)
+	oris	r8,r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
+	and	r0,r0,r8
+	cmpdi	cr1,r0,0
+	andi.	r0,r11,MSR_EE
+	beq	cr1,11f
+BEGIN_FTR_SECTION
+	mfspr	r8,SPRN_LPCR
+	ori	r8,r8,LPCR_MER
+	mtspr	SPRN_LPCR,r8
+	isync
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+	beq	5f
+	li	r0,BOOK3S_INTERRUPT_EXTERNAL
+12:	mr	r6,r10
+	mr	r10,r0
+	mr	r7,r11
+	li	r11,(MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11,r11,63
+	b	5f
+11:	beq	5f
+	mfspr	r0,SPRN_DEC
+	cmpwi	r0,0
+	li	r0,BOOK3S_INTERRUPT_DECREMENTER
+	blt	12b
+
+	/* Move SRR0 and SRR1 into the respective regs */
+5:	mtspr	SPRN_SRR0, r6
+	mtspr	SPRN_SRR1, r7
+	li	r0,0
+	stb	r0,VCPU_CEDED(r4)	/* cancel cede */
+
 fast_guest_return:
 	mtspr	SPRN_HSRR0,r10
 	mtspr	SPRN_HSRR1,r11
@@ -574,21 +608,20 @@ kvmppc_interrupt:
 	/* See if this is something we can handle in real mode */
 	cmpwi	r12,BOOK3S_INTERRUPT_SYSCALL
 	beq	hcall_try_real_mode
-hcall_real_cont:
 
 	/* Check for mediated interrupts (could be done earlier really ...) */
 BEGIN_FTR_SECTION
 	cmpwi	r12,BOOK3S_INTERRUPT_EXTERNAL
 	bne+	1f
-	ld	r5,VCPU_KVM(r9)
-	ld	r5,KVM_LPCR(r5)
 	andi.	r0,r11,MSR_EE
 	beq	1f
+	mfspr	r5,SPRN_LPCR
 	andi.	r0,r5,LPCR_MER
 	bne	bounce_ext_interrupt
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
+hcall_real_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	/* Save DEC */
 	mfspr	r5,SPRN_DEC
 	mftb	r6
@@ -682,7 +715,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_201)
 	slbia
 	ptesync
 
-hdec_soon:
+hdec_soon:			/* r9 = vcpu, r12 = trap, r13 = paca */
 BEGIN_FTR_SECTION
 	b	32f
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
@@ -700,6 +733,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	addi	r0,r3,0x100
 	stwcx.	r0,0,r6
 	bne	41b
+	lwsync
 
 	/*
 	 * At this point we have an interrupt that we have to pass
@@ -713,18 +747,39 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	 * interrupt, since the other threads will already be on their
 	 * way here in that case.
 	 */
+	cmpwi	r3,0x100	/* Are we the first here? */
+	bge	43f
+	cmpwi	r3,1		/* Are any other threads in the guest? */
+	ble	43f
 	cmpwi	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
 	beq	40f
-	cmpwi	r3,0x100	/* Are we the first here? */
-	bge	40f
-	cmpwi	r3,1
-	ble	40f
 	li	r0,0
 	mtspr	SPRN_HDEC,r0
 40:
+	/*
+	 * Send an IPI to any napping threads, since an HDEC interrupt
+	 * doesn't wake CPUs up from nap.
+	 */
+	lwz	r3,VCORE_NAPPING_THREADS(r5)
+	lwz	r4,VCPU_PTID(r9)
+	li	r0,1
+	sldi	r0,r0,r4
+	andc.	r3,r3,r0		/* no sense IPI'ing ourselves */
+	beq	43f
+	mulli	r4,r4,PACA_SIZE		/* get paca for thread 0 */
+	subf	r6,r4,r13
+42:	andi.	r0,r3,1
+	beq	44f
+	ld	r8,HSTATE_XICS_PHYS(r6)	/* get thread's XICS reg addr */
+	li	r0,IPI_PRIORITY
+	li	r7,XICS_QIRR
+	stbcix	r0,r7,r8		/* trigger the IPI */
+44:	srdi.	r3,r3,1
+	addi	r6,r6,PACA_SIZE
+	bne	42b
 
 	/* Secondary threads wait for primary to do partition switch */
-	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
+43:	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
 	ld	r5,HSTATE_KVM_VCORE(r13)
 	lwz	r3,VCPU_PTID(r9)
 	cmpwi	r3,0
@@ -1077,7 +1132,6 @@ hcall_try_real_mode:
 hcall_real_fallback:
 	li	r12,BOOK3S_INTERRUPT_SYSCALL
 	ld	r9, HSTATE_KVM_VCPU(r13)
-	ld	r11, VCPU_MSR(r9)
 
 	b	hcall_real_cont
 
@@ -1139,7 +1193,7 @@ hcall_real_table:
 	.long	0		/* 0xd4 */
 	.long	0		/* 0xd8 */
 	.long	0		/* 0xdc */
-	.long	0		/* 0xe0 */
+	.long	.kvmppc_h_cede - hcall_real_table
 	.long	0		/* 0xe4 */
 	.long	0		/* 0xe8 */
 	.long	0		/* 0xec */
@@ -1168,7 +1222,8 @@ bounce_ext_interrupt:
 	mtspr	SPRN_SRR0,r10
 	mtspr	SPRN_SRR1,r11
 	li	r10,BOOK3S_INTERRUPT_EXTERNAL
-	LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
+	li	r11,(MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11,r11,63
 	b	fast_guest_return
 
 _GLOBAL(kvmppc_h_set_dabr)
@@ -1177,6 +1232,178 @@ _GLOBAL(kvmppc_h_set_dabr)
 	li	r3,0
 	blr
 
+_GLOBAL(kvmppc_h_cede)
+	ori	r11,r11,MSR_EE
+	std	r11,VCPU_MSR(r3)
+	li	r0,1
+	stb	r0,VCPU_CEDED(r3)
+	sync			/* order setting ceded vs. testing prodded */
+	lbz	r5,VCPU_PRODDED(r3)
+	cmpwi	r5,0
+	bne	1f
+	li	r0,0		/* set trap to 0 to say hcall is handled */
+	stw	r0,VCPU_TRAP(r3)
+	li	r0,H_SUCCESS
+	std	r0,VCPU_GPR(r3)(r3)
+BEGIN_FTR_SECTION
+	b	2f		/* just send it up to host on 970 */
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
+
+	/*
+	 * Set our bit in the bitmask of napping threads unless all the
+	 * other threads are already napping, in which case we send this
+	 * up to the host.
+	 */
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	lwz	r6,VCPU_PTID(r3)
+	lwz	r8,VCORE_ENTRY_EXIT(r5)
+	clrldi	r8,r8,56
+	li	r0,1
+	sld	r0,r0,r6
+	addi	r6,r5,VCORE_NAPPING_THREADS
+31:	lwarx	r4,0,r6
+	or	r4,r4,r0
+	PPC_POPCNTW(r7,r4)
+	cmpw	r7,r8
+	bge	2f
+	stwcx.	r4,0,r6
+	bne	31b
+	li	r0,1
+	stb	r0,HSTATE_NAPPING(r13)
+	/* order napping_threads update vs testing entry_exit_count */
+	lwsync
+	mr	r4,r3
+	lwz	r7,VCORE_ENTRY_EXIT(r5)
+	cmpwi	r7,0x100
+	bge	33f		/* another thread already exiting */
+
+/*
+ * Although not specifically required by the architecture, POWER7
+ * preserves the following registers in nap mode, even if an SMT mode
+ * switch occurs: SLB entries, PURR, SPURR, AMOR, UAMOR, AMR, SPRG0-3,
+ * DAR, DSISR, DABR, DABRX, DSCR, PMCx, MMCRx, SIAR, SDAR.
+ */
+	/* Save non-volatile GPRs */
+	std	r14, VCPU_GPR(r14)(r3)
+	std	r15, VCPU_GPR(r15)(r3)
+	std	r16, VCPU_GPR(r16)(r3)
+	std	r17, VCPU_GPR(r17)(r3)
+	std	r18, VCPU_GPR(r18)(r3)
+	std	r19, VCPU_GPR(r19)(r3)
+	std	r20, VCPU_GPR(r20)(r3)
+	std	r21, VCPU_GPR(r21)(r3)
+	std	r22, VCPU_GPR(r22)(r3)
+	std	r23, VCPU_GPR(r23)(r3)
+	std	r24, VCPU_GPR(r24)(r3)
+	std	r25, VCPU_GPR(r25)(r3)
+	std	r26, VCPU_GPR(r26)(r3)
+	std	r27, VCPU_GPR(r27)(r3)
+	std	r28, VCPU_GPR(r28)(r3)
+	std	r29, VCPU_GPR(r29)(r3)
+	std	r30, VCPU_GPR(r30)(r3)
+	std	r31, VCPU_GPR(r31)(r3)
+
+	/* save FP state */
+	bl	.kvmppc_save_fp
+
+	/*
+	 * Take a nap until a decrementer or external interrupt occurs,
+	 * with PECE1 (wake on decr) and PECE0 (wake on external) set in LPCR
+	 */
+	li	r0,0x80
+	stb	r0,PACAPROCSTART(r13)
+	mfspr	r5,SPRN_LPCR
+	ori	r5,r5,LPCR_PECE0 | LPCR_PECE1
+	mtspr	SPRN_LPCR,r5
+	isync
+	li	r0, 0
+	std	r0, HSTATE_SCRATCH0(r13)
+	ptesync
+	ld	r0, HSTATE_SCRATCH0(r13)
+1:	cmpd	r0, r0
+	bne	1b
+	nap
+	b	.
+
+kvm_end_cede:
+	/* Woken by external or decrementer interrupt */
+	ld	r1, HSTATE_HOST_R1(r13)
+	ld	r2, PACATOC(r13)
+
+	/* If we're a secondary thread and we got here by an IPI, ack it */
+	ld	r4,HSTATE_KVM_VCPU(r13)
+	lwz	r3,VCPU_PTID(r4)
+	cmpwi	r3,0
+	beq	27f
+	mfspr	r3,SPRN_SRR1
+	rlwinm	r3,r3,44-31,0x7		/* extract wake reason field */
+	cmpwi	r3,4			/* was it an external interrupt? */
+	bne	27f
+	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r0,0xff
+	li	r6,XICS_QIRR
+	li	r7,XICS_XIRR
+	lwzcix	r8,r5,r7		/* ack the interrupt */
+	sync
+	stbcix	r0,r5,r6		/* clear it */
+	stwcix	r8,r5,r7		/* EOI it */
+27:
+	/* load up FP state */
+	bl	kvmppc_load_fp
+
+	/* Load NV GPRS */
+	ld	r14, VCPU_GPR(r14)(r4)
+	ld	r15, VCPU_GPR(r15)(r4)
+	ld	r16, VCPU_GPR(r16)(r4)
+	ld	r17, VCPU_GPR(r17)(r4)
+	ld	r18, VCPU_GPR(r18)(r4)
+	ld	r19, VCPU_GPR(r19)(r4)
+	ld	r20, VCPU_GPR(r20)(r4)
+	ld	r21, VCPU_GPR(r21)(r4)
+	ld	r22, VCPU_GPR(r22)(r4)
+	ld	r23, VCPU_GPR(r23)(r4)
+	ld	r24, VCPU_GPR(r24)(r4)
+	ld	r25, VCPU_GPR(r25)(r4)
+	ld	r26, VCPU_GPR(r26)(r4)
+	ld	r27, VCPU_GPR(r27)(r4)
+	ld	r28, VCPU_GPR(r28)(r4)
+	ld	r29, VCPU_GPR(r29)(r4)
+	ld	r30, VCPU_GPR(r30)(r4)
+	ld	r31, VCPU_GPR(r31)(r4)
+
+	/* clear our bit in vcore->napping_threads */
+33:	ld	r5,HSTATE_KVM_VCORE(r13)
+	lwz	r3,VCPU_PTID(r4)
+	li	r0,1
+	sld	r0,r0,r3
+	addi	r6,r5,VCORE_NAPPING_THREADS
+32:	lwarx	r7,0,r6
+	andc	r7,r7,r0
+	stwcx.	r7,0,r6
+	bne	32b
+	li	r0,0
+	stb	r0,HSTATE_NAPPING(r13)
+
+	/* see if any other thread is already exiting */
+	lwz	r0,VCORE_ENTRY_EXIT(r5)
+	cmpwi	r0,0x100
+	blt	kvmppc_cede_reentry	/* if not go back to guest */
+
+	/* some threads are exiting, so go to the guest exit path */
+	b	hcall_real_fallback
+
+	/* cede when already previously prodded case */
+1:	li	r0,0
+	stb	r0,VCPU_PRODDED(r3)
+	sync			/* order testing prodded vs. clearing ceded */
+	stb	r0,VCPU_CEDED(r3)
+	li	r3,H_SUCCESS
+	blr
+
+	/* we've ceded but we want to give control to the host */
+2:	li	r3,H_TOO_HARD
+	blr
+
 secondary_too_late:
 	ld	r5,HSTATE_KVM_VCORE(r13)
 	HMT_LOW
@@ -1194,14 +1421,20 @@ secondary_too_late:
 	slbmte	r6,r5
 1:	addi	r11,r11,16
 	.endr
-	b	50f
 
 secondary_nap:
-	/* Clear any pending IPI */
-50:	ld	r5, HSTATE_XICS_PHYS(r13)
+	/* Clear any pending IPI - assume we're a secondary thread */
+	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r7, XICS_XIRR
+	lwzcix	r3, r5, r7		/* ack any pending interrupt */
+	rlwinm.	r0, r3, 0, 0xffffff	/* any pending? */
+	beq	37f
+	sync
 	li	r0, 0xff
 	li	r6, XICS_QIRR
-	stbcix	r0, r5, r6
+	stbcix	r0, r5, r6		/* clear the IPI */
+	stwcix	r3, r5, r7		/* EOI it */
+37:	sync
 
 	/* increment the nap count and then go to nap mode */
 	ld	r4, HSTATE_KVM_VCORE(r13)
@@ -1211,13 +1444,12 @@ secondary_nap:
 	addi	r3, r3, 1
 	stwcx.	r3, 0, r4
 	bne	51b
-	isync
 
+	li	r3, LPCR_PECE0
 	mfspr	r4, SPRN_LPCR
-	li	r0, LPCR_PECE
-	andc	r4, r4, r0
-	ori	r4, r4, LPCR_PECE0	/* exit nap on interrupt */
+	rlwimi	r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
 	mtspr	SPRN_LPCR, r4
+	isync
 	li	r0, 0
 	std	r0, HSTATE_SCRATCH0(r13)
 	ptesync
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_rm_mmu.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,39 +110,6 @@ long kvmppc_h_enter(struct kvm_vcpu *vcp
 	return H_SUCCESS;
 }
 
-static unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
-				      unsigned long pte_index)
-{
-	unsigned long rb, va_low;
-
-	rb = (v & ~0x7fUL) << 16;		/* AVA field */
-	va_low = pte_index >> 3;
-	if (v & HPTE_V_SECONDARY)
-		va_low = ~va_low;
-	/* xor vsid from AVA */
-	if (!(v & HPTE_V_1TB_SEG))
-		va_low ^= v >> 12;
-	else
-		va_low ^= v >> 24;
-	va_low &= 0x7ff;
-	if (v & HPTE_V_LARGE) {
-		rb |= 1;			/* L field */
-		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
-		    (r & 0xff000)) {
-			/* non-16MB large page, must be 64k */
-			/* (masks depend on page size) */
-			rb |= 0x1000;		/* page encoding in LP field */
-			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
-			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
-		}
-	} else {
-		/* 4kB page */
-		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
-	}
-	rb |= (v >> 54) & 0x300;		/* B field */
-	return rb;
-}
-
 #define LOCK_TOKEN	(*(u32 *)(&get_paca()->lock_token))
 
 static inline int try_lock_tlbie(unsigned int *lock)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_interrupts.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_interrupts.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_interrupts.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_interrupts.S	2012-01-04 18:55:44.000000000 -0500
@@ -29,27 +29,11 @@
 #define ULONG_SIZE 		8
 #define FUNC(name) 		GLUE(.,name)
 
-#define GET_SHADOW_VCPU_R13
-
-#define DISABLE_INTERRUPTS	\
-	mfmsr   r0;		\
-	rldicl  r0,r0,48,1;	\
-	rotldi  r0,r0,16;	\
-	mtmsrd  r0,1;		\
-
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
 #define ULONG_SIZE              4
 #define FUNC(name)		name
 
-#define GET_SHADOW_VCPU_R13	\
-	lwz	r13, (THREAD + THREAD_KVM_SVCPU)(r2)
-
-#define DISABLE_INTERRUPTS	\
-	mfmsr   r0;		\
-	rlwinm  r0,r0,0,17,15;	\
-	mtmsr   r0;		\
-
 #endif /* CONFIG_PPC_BOOK3S_XX */
 
 
@@ -108,44 +92,17 @@ kvm_start_entry:
 
 kvm_start_lightweight:
 
-	GET_SHADOW_VCPU_R13
-	PPC_LL	r3, VCPU_HIGHMEM_HANDLER(r4)
-	PPC_STL	r3, HSTATE_VMHANDLER(r13)
-
-	PPC_LL	r10, VCPU_SHADOW_MSR(r4)	/* r10 = vcpu->arch.shadow_msr */
-
-	DISABLE_INTERRUPTS
-
 #ifdef CONFIG_PPC_BOOK3S_64
-	/* Some guests may need to have dcbz set to 32 byte length.
-	 *
-	 * Usually we ensure that by patching the guest's instructions
-	 * to trap on dcbz and emulate it in the hypervisor.
-	 *
-	 * If we can, we should tell the CPU to use 32 byte dcbz though,
-	 * because that's a lot faster.
-	 */
-
 	PPC_LL	r3, VCPU_HFLAGS(r4)
-	rldicl.	r3, r3, 0, 63		/* CR = ((r3 & 1) == 0) */
-	beq	no_dcbz32_on
-
-	mfspr   r3,SPRN_HID5
-	ori     r3, r3, 0x80		/* XXX HID5_dcbz32 = 0x80 */
-	mtspr   SPRN_HID5,r3
-
-no_dcbz32_on:
-
+	rldicl	r3, r3, 0, 63		/* r3 &= 1 */
+	stb	r3, HSTATE_RESTORE_HID5(r13)
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
-	PPC_LL	r6, VCPU_RMCALL(r4)
-	mtctr	r6
-
-	PPC_LL	r3, VCPU_TRAMPOLINE_ENTER(r4)
-	LOAD_REG_IMMEDIATE(r4, MSR_KERNEL & ~(MSR_IR | MSR_DR))
+	PPC_LL	r4, VCPU_SHADOW_MSR(r4)	/* get shadow_msr */
 
 	/* Jump to segment patching handler and into our guest */
-	bctr
+	bl	FUNC(kvmppc_entry_trampoline)
+	nop
 
 /*
  * This is the handler in module memory. It gets jumped at from the
@@ -170,21 +127,6 @@ kvmppc_handler_highmem:
 	/* R7 = vcpu */
 	PPC_LL	r7, GPR4(r1)
 
-#ifdef CONFIG_PPC_BOOK3S_64
-
-	PPC_LL	r5, VCPU_HFLAGS(r7)
-	rldicl.	r5, r5, 0, 63		/* CR = ((r5 & 1) == 0) */
-	beq	no_dcbz32_off
-
-	li	r4, 0
-	mfspr   r5,SPRN_HID5
-	rldimi  r5,r4,6,56
-	mtspr   SPRN_HID5,r5
-
-no_dcbz32_off:
-
-#endif /* CONFIG_PPC_BOOK3S_64 */
-
 	PPC_STL	r14, VCPU_GPR(r14)(r7)
 	PPC_STL	r15, VCPU_GPR(r15)(r7)
 	PPC_STL	r16, VCPU_GPR(r16)(r7)
@@ -204,67 +146,6 @@ no_dcbz32_off:
 	PPC_STL	r30, VCPU_GPR(r30)(r7)
 	PPC_STL	r31, VCPU_GPR(r31)(r7)
 
-	/* Restore host msr -> SRR1 */
-	PPC_LL	r6, VCPU_HOST_MSR(r7)
-
-	/*
-	 * For some interrupts, we need to call the real Linux
-	 * handler, so it can do work for us. This has to happen
-	 * as if the interrupt arrived from the kernel though,
-	 * so let's fake it here where most state is restored.
-	 *
-	 * Call Linux for hardware interrupts/decrementer
-	 * r3 = address of interrupt handler (exit reason)
-	 */
-
-	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
-	beq	call_linux_handler
-	cmpwi	r12, BOOK3S_INTERRUPT_DECREMENTER
-	beq	call_linux_handler
-	cmpwi	r12, BOOK3S_INTERRUPT_PERFMON
-	beq	call_linux_handler
-
-	/* Back to EE=1 */
-	mtmsr	r6
-	sync
-	b	kvm_return_point
-
-call_linux_handler:
-
-	/*
-	 * If we land here we need to jump back to the handler we
-	 * came from.
-	 *
-	 * We have a page that we can access from real mode, so let's
-	 * jump back to that and use it as a trampoline to get back into the
-	 * interrupt handler!
-	 *
-	 * R3 still contains the exit code,
-	 * R5 VCPU_HOST_RETIP and
-	 * R6 VCPU_HOST_MSR
-	 */
-
-	/* Restore host IP -> SRR0 */
-	PPC_LL	r5, VCPU_HOST_RETIP(r7)
-
-	/* XXX Better move to a safe function?
-	 *     What if we get an HTAB flush in between mtsrr0 and mtsrr1? */
-
-	mtlr	r12
-
-	PPC_LL	r4, VCPU_TRAMPOLINE_LOWMEM(r7)
-	mtsrr0	r4
-	LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR))
-	mtsrr1	r3
-
-	RFI
-
-.global kvm_return_point
-kvm_return_point:
-
-	/* Jump back to lightweight entry if we're supposed to */
-	/* go back into the guest */
-
 	/* Pass the exit number as 3rd argument to kvmppc_handle_exit */
 	mr	r5, r12
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_pr.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_pr.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_pr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_pr.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/kvm_host.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 
@@ -152,14 +153,18 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcp
 		kvmppc_mmu_book3s_64_init(vcpu);
 		to_book3s(vcpu)->hior = 0xfff00000;
 		to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+		vcpu->arch.cpu_type = KVM_CPU_3S_64;
 	} else
 #endif
 	{
 		kvmppc_mmu_book3s_32_init(vcpu);
 		to_book3s(vcpu)->hior = 0;
 		to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+		vcpu->arch.cpu_type = KVM_CPU_3S_32;
 	}
 
+	kvmppc_sanity_check(vcpu);
+
 	/* If we are in hypervisor level on 970, we can tell the CPU to
 	 * treat DCBZ as 32 bytes store */
 	vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
@@ -646,7 +651,29 @@ program_interrupt:
 		break;
 	}
 	case BOOK3S_INTERRUPT_SYSCALL:
-		if (vcpu->arch.osi_enabled &&
+		if (vcpu->arch.papr_enabled &&
+		    (kvmppc_get_last_inst(vcpu) == 0x44000022) &&
+		    !(vcpu->arch.shared->msr & MSR_PR)) {
+			/* SC 1 papr hypercalls */
+			ulong cmd = kvmppc_get_gpr(vcpu, 3);
+			int i;
+
+#ifdef CONFIG_KVM_BOOK3S_64_PR
+			if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) {
+				r = RESUME_GUEST;
+				break;
+			}
+#endif
+
+			run->papr_hcall.nr = cmd;
+			for (i = 0; i < 9; ++i) {
+				ulong gpr = kvmppc_get_gpr(vcpu, 4 + i);
+				run->papr_hcall.args[i] = gpr;
+			}
+			run->exit_reason = KVM_EXIT_PAPR_HCALL;
+			vcpu->arch.hcall_needed = 1;
+			r = RESUME_HOST;
+		} else if (vcpu->arch.osi_enabled &&
 		    (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
 		    (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
 			/* MOL hypercalls */
@@ -841,8 +868,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 	if (!p)
 		goto uninit_vcpu;
 
-	vcpu->arch.host_retip = kvm_return_point;
-	vcpu->arch.host_msr = mfmsr();
 #ifdef CONFIG_PPC_BOOK3S_64
 	/* default to book3s_64 (970fx) */
 	vcpu->arch.pvr = 0x3C0301;
@@ -853,16 +878,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
 	vcpu->arch.slb_nr = 64;
 
-	/* remember where some real-mode handlers are */
-	vcpu->arch.trampoline_lowmem = __pa(kvmppc_handler_lowmem_trampoline);
-	vcpu->arch.trampoline_enter = __pa(kvmppc_handler_trampoline_enter);
-	vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
-#ifdef CONFIG_PPC_BOOK3S_64
-	vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
-#else
-	vcpu->arch.rmcall = (ulong)kvmppc_rmcall;
-#endif
-
 	vcpu->arch.shadow_msr = MSR_USER64;
 
 	err = kvmppc_mmu_init(vcpu);
@@ -908,6 +923,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_
 #endif
 	ulong ext_msr;
 
+	/* Check if we can run the vcpu at all */
+	if (!vcpu->arch.sane) {
+		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
 	/* No need to go into the guest when all we do is going out */
 	if (signal_pending(current)) {
 		kvm_run->exit_reason = KVM_EXIT_INTR;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_pr_papr.c linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_pr_papr.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_pr_papr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_pr_papr.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011. Freescale Inc. All rights reserved.
+ *
+ * Authors:
+ *    Alexander Graf <agraf@suse.de>
+ *    Paul Mackerras <paulus@samba.org>
+ *
+ * Description:
+ *
+ * Hypercall handling for running PAPR guests in PR KVM on Book 3S
+ * processors.
+ *
+ * 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 <asm/uaccess.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+
+static unsigned long get_pteg_addr(struct kvm_vcpu *vcpu, long pte_index)
+{
+	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
+	unsigned long pteg_addr;
+
+	pte_index <<= 4;
+	pte_index &= ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1) << 7 | 0x70;
+	pteg_addr = vcpu_book3s->sdr1 & 0xfffffffffffc0000ULL;
+	pteg_addr |= pte_index;
+
+	return pteg_addr;
+}
+
+static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
+{
+	long flags = kvmppc_get_gpr(vcpu, 4);
+	long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long pteg[2 * 8];
+	unsigned long pteg_addr, i, *hpte;
+
+	pte_index &= ~7UL;
+	pteg_addr = get_pteg_addr(vcpu, pte_index);
+
+	copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
+	hpte = pteg;
+
+	if (likely((flags & H_EXACT) == 0)) {
+		pte_index &= ~7UL;
+		for (i = 0; ; ++i) {
+			if (i == 8)
+				return H_PTEG_FULL;
+			if ((*hpte & HPTE_V_VALID) == 0)
+				break;
+			hpte += 2;
+		}
+	} else {
+		i = kvmppc_get_gpr(vcpu, 5) & 7UL;
+		hpte += i * 2;
+	}
+
+	hpte[0] = kvmppc_get_gpr(vcpu, 6);
+	hpte[1] = kvmppc_get_gpr(vcpu, 7);
+	copy_to_user((void __user *)pteg_addr, pteg, sizeof(pteg));
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+	kvmppc_set_gpr(vcpu, 4, pte_index | i);
+
+	return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags= kvmppc_get_gpr(vcpu, 4);
+	unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+	unsigned long v = 0, pteg, rb;
+	unsigned long pte[2];
+
+	pteg = get_pteg_addr(vcpu, pte_index);
+	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+	if ((pte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn) ||
+	    ((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) {
+		kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+		return EMULATE_DONE;
+	}
+
+	copy_to_user((void __user *)pteg, &v, sizeof(v));
+
+	rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
+	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+	kvmppc_set_gpr(vcpu, 4, pte[0]);
+	kvmppc_set_gpr(vcpu, 5, pte[1]);
+
+	return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags = kvmppc_get_gpr(vcpu, 4);
+	unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+	unsigned long rb, pteg, r, v;
+	unsigned long pte[2];
+
+	pteg = get_pteg_addr(vcpu, pte_index);
+	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+	if ((pte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn)) {
+		kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+		return EMULATE_DONE;
+	}
+
+	v = pte[0];
+	r = pte[1];
+	r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_HI |
+	       HPTE_R_KEY_LO);
+	r |= (flags << 55) & HPTE_R_PP0;
+	r |= (flags << 48) & HPTE_R_KEY_HI;
+	r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+
+	pte[1] = r;
+
+	rb = compute_tlbie_rb(v, r, pte_index);
+	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+	copy_to_user((void __user *)pteg, pte, sizeof(pte));
+
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+
+	return EMULATE_DONE;
+}
+
+int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
+{
+	switch (cmd) {
+	case H_ENTER:
+		return kvmppc_h_pr_enter(vcpu);
+	case H_REMOVE:
+		return kvmppc_h_pr_remove(vcpu);
+	case H_PROTECT:
+		return kvmppc_h_pr_protect(vcpu);
+	case H_BULK_REMOVE:
+		/* We just flush all PTEs, so user space can
+		   handle the HPT modifications */
+		kvmppc_mmu_pte_flush(vcpu, 0, 0);
+		break;
+	case H_CEDE:
+		kvm_vcpu_block(vcpu);
+		vcpu->stat.halt_wakeup++;
+		return EMULATE_DONE;
+	}
+
+	return EMULATE_FAIL;
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_rmhandlers.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_rmhandlers.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_rmhandlers.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_rmhandlers.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
+#include <asm/mmu.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
@@ -35,10 +36,10 @@
 
 #if defined(CONFIG_PPC_BOOK3S_64)
 
-#define LOAD_SHADOW_VCPU(reg)	GET_PACA(reg)					
-#define MSR_NOIRQ		MSR_KERNEL & ~(MSR_IR | MSR_DR)
 #define FUNC(name) 		GLUE(.,name)
+#define MTMSR_EERI(reg)		mtmsrd	(reg),1
 
+	.globl	kvmppc_skip_interrupt
 kvmppc_skip_interrupt:
 	/*
 	 * Here all GPRs are unchanged from when the interrupt happened
@@ -51,6 +52,7 @@ kvmppc_skip_interrupt:
 	rfid
 	b	.
 
+	.globl	kvmppc_skip_Hinterrupt
 kvmppc_skip_Hinterrupt:
 	/*
 	 * Here all GPRs are unchanged from when the interrupt happened
@@ -65,8 +67,8 @@ kvmppc_skip_Hinterrupt:
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
-#define MSR_NOIRQ		MSR_KERNEL
 #define FUNC(name)		name
+#define MTMSR_EERI(reg)		mtmsr	(reg)
 
 .macro INTERRUPT_TRAMPOLINE intno
 
@@ -167,40 +169,24 @@ kvmppc_handler_skip_ins:
 #endif
 
 /*
- * This trampoline brings us back to a real mode handler
- *
- * Input Registers:
- *
- * R5 = SRR0
- * R6 = SRR1
- * LR = real-mode IP
+ * Call kvmppc_handler_trampoline_enter in real mode
  *
+ * On entry, r4 contains the guest shadow MSR
  */
-.global kvmppc_handler_lowmem_trampoline
-kvmppc_handler_lowmem_trampoline:
+_GLOBAL(kvmppc_entry_trampoline)
+	mfmsr	r5
+	LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
+	toreal(r7)
 
-	mtsrr0	r5
+	li	r9, MSR_RI
+	ori	r9, r9, MSR_EE
+	andc	r9, r5, r9	/* Clear EE and RI in MSR value */
+	li	r6, MSR_IR | MSR_DR
+	ori	r6, r6, MSR_EE
+	andc	r6, r5, r6	/* Clear EE, DR and IR in MSR value */
+	MTMSR_EERI(r9)		/* Clear EE and RI in MSR */
+	mtsrr0	r7		/* before we set srr0/1 */
 	mtsrr1	r6
-	blr
-kvmppc_handler_lowmem_trampoline_end:
-
-/*
- * Call a function in real mode
- *
- * Input Registers:
- *
- * R3 = function
- * R4 = MSR
- * R5 = scratch register
- *
- */
-_GLOBAL(kvmppc_rmcall)
-	LOAD_REG_IMMEDIATE(r5, MSR_NOIRQ)
-	mtmsr	r5		/* Disable relocation and interrupts, so mtsrr
-				   doesn't get interrupted */
-	sync
-	mtsrr0	r3
-	mtsrr1	r4
 	RFI
 
 #if defined(CONFIG_PPC_BOOK3S_32)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_segment.S linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_segment.S
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/book3s_segment.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/book3s_segment.S	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 
 #define GET_SHADOW_VCPU(reg)    \
 	mr	reg, r13
+#define MTMSR_EERI(reg)		mtmsrd	(reg),1
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
@@ -30,6 +31,7 @@
 	tophys(reg, r2);       			\
 	lwz     reg, (THREAD + THREAD_KVM_SVCPU)(reg);	\
 	tophys(reg, reg)
+#define MTMSR_EERI(reg)		mtmsr	(reg)
 
 #endif
 
@@ -57,10 +59,12 @@ kvmppc_handler_trampoline_enter:
 	/* Required state:
 	 *
 	 * MSR = ~IR|DR
-	 * R13 = PACA
 	 * R1 = host R1
 	 * R2 = host R2
-	 * R10 = guest MSR
+	 * R4 = guest shadow MSR
+	 * R5 = normal host MSR
+	 * R6 = current host MSR (EE, IR, DR off)
+	 * LR = highmem guest exit code
 	 * all other volatile GPRS = free
 	 * SVCPU[CR] = guest CR
 	 * SVCPU[XER] = guest XER
@@ -71,15 +75,15 @@ kvmppc_handler_trampoline_enter:
 	/* r3 = shadow vcpu */
 	GET_SHADOW_VCPU(r3)
 
+	/* Save guest exit handler address and MSR */
+	mflr	r0
+	PPC_STL	r0, HSTATE_VMHANDLER(r3)
+	PPC_STL	r5, HSTATE_HOST_MSR(r3)
+
 	/* Save R1/R2 in the PACA (64-bit) or shadow_vcpu (32-bit) */
 	PPC_STL	r1, HSTATE_HOST_R1(r3)
 	PPC_STL	r2, HSTATE_HOST_R2(r3)
 
-	/* Move SRR0 and SRR1 into the respective regs */
-	PPC_LL  r9, SVCPU_PC(r3)
-	mtsrr0	r9
-	mtsrr1	r10
-
 	/* Activate guest mode, so faults get handled by KVM */
 	li	r11, KVM_GUEST_MODE_GUEST
 	stb	r11, HSTATE_IN_GUEST(r3)
@@ -87,17 +91,46 @@ kvmppc_handler_trampoline_enter:
 	/* Switch to guest segment. This is subarch specific. */
 	LOAD_GUEST_SEGMENTS
 
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* Some guests may need to have dcbz set to 32 byte length.
+	 *
+	 * Usually we ensure that by patching the guest's instructions
+	 * to trap on dcbz and emulate it in the hypervisor.
+	 *
+	 * If we can, we should tell the CPU to use 32 byte dcbz though,
+	 * because that's a lot faster.
+	 */
+	lbz	r0, HSTATE_RESTORE_HID5(r3)
+	cmpwi	r0, 0
+	beq	no_dcbz32_on
+
+	mfspr   r0,SPRN_HID5
+	ori     r0, r0, 0x80		/* XXX HID5_dcbz32 = 0x80 */
+	mtspr   SPRN_HID5,r0
+no_dcbz32_on:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
 	/* Enter guest */
 
-	PPC_LL	r4, SVCPU_CTR(r3)
-	PPC_LL	r5, SVCPU_LR(r3)
-	lwz	r6, SVCPU_CR(r3)
-	lwz	r7, SVCPU_XER(r3)
+	PPC_LL	r8, SVCPU_CTR(r3)
+	PPC_LL	r9, SVCPU_LR(r3)
+	lwz	r10, SVCPU_CR(r3)
+	lwz	r11, SVCPU_XER(r3)
 
-	mtctr	r4
-	mtlr	r5
-	mtcr	r6
-	mtxer	r7
+	mtctr	r8
+	mtlr	r9
+	mtcr	r10
+	mtxer	r11
+
+	/* Move SRR0 and SRR1 into the respective regs */
+	PPC_LL  r9, SVCPU_PC(r3)
+	/* First clear RI in our current MSR value */
+	li	r0, MSR_RI
+	andc	r6, r6, r0
+	MTMSR_EERI(r6)
+	mtsrr0	r9
+	mtsrr1	r4
 
 	PPC_LL	r0, SVCPU_R0(r3)
 	PPC_LL	r1, SVCPU_R1(r3)
@@ -213,11 +246,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
 	beq	ld_last_inst
 	cmpwi	r12, BOOK3S_INTERRUPT_PROGRAM
 	beq	ld_last_inst
+	cmpwi	r12, BOOK3S_INTERRUPT_SYSCALL
+	beq	ld_last_prev_inst
 	cmpwi	r12, BOOK3S_INTERRUPT_ALIGNMENT
 	beq-	ld_last_inst
 
 	b	no_ld_last_inst
 
+ld_last_prev_inst:
+	addi	r3, r3, -4
+
 ld_last_inst:
 	/* Save off the guest instruction we're at */
 
@@ -254,6 +292,43 @@ no_ld_last_inst:
 	/* Switch back to host MMU */
 	LOAD_HOST_SEGMENTS
 
+#ifdef CONFIG_PPC_BOOK3S_64
+
+	lbz	r5, HSTATE_RESTORE_HID5(r13)
+	cmpwi	r5, 0
+	beq	no_dcbz32_off
+
+	li	r4, 0
+	mfspr   r5,SPRN_HID5
+	rldimi  r5,r4,6,56
+	mtspr   SPRN_HID5,r5
+
+no_dcbz32_off:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
+	/*
+	 * For some interrupts, we need to call the real Linux
+	 * handler, so it can do work for us. This has to happen
+	 * as if the interrupt arrived from the kernel though,
+	 * so let's fake it here where most state is restored.
+	 *
+	 * Having set up SRR0/1 with the address where we want
+	 * to continue with relocation on (potentially in module
+	 * space), we either just go straight there with rfi[d],
+	 * or we jump to an interrupt handler with bctr if there
+	 * is an interrupt to be handled first.  In the latter
+	 * case, the rfi[d] at the end of the interrupt handler
+	 * will get us back to where we want to continue.
+	 */
+
+	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
+	beq	1f
+	cmpwi	r12, BOOK3S_INTERRUPT_DECREMENTER
+	beq	1f
+	cmpwi	r12, BOOK3S_INTERRUPT_PERFMON
+1:	mtctr	r12
+
 	/* Register usage at this point:
 	 *
 	 * R1       = host R1
@@ -264,13 +339,15 @@ no_ld_last_inst:
 	 *
 	 */
 
-	/* RFI into the highmem handler */
-	mfmsr	r7
-	ori	r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME	/* Enable paging */
-	mtsrr1	r7
-	/* Load highmem handler address */
+	PPC_LL	r6, HSTATE_HOST_MSR(r13)
 	PPC_LL	r8, HSTATE_VMHANDLER(r13)
+
+	/* Restore host msr -> SRR1 */
+	mtsrr1	r6
+	/* Load highmem handler address */
 	mtsrr0	r8
 
+	/* RFI into the highmem handler, or jump to interrupt handler */
+	beqctr
 	RFI
 kvmppc_handler_trampoline_exit_end:
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/booke.c linux-libre-3.2-gnu1/arch/powerpc/kvm/booke.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/booke.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/booke.c	2012-01-04 18:55:44.000000000 -0500
@@ -316,6 +316,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_
 {
 	int ret;
 
+	if (!vcpu->arch.sane) {
+		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
 	local_irq_disable();
 	kvm_guest_enter();
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
@@ -618,6 +623,7 @@ int kvmppc_handle_exit(struct kvm_run *r
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	int i;
+	int r;
 
 	vcpu->arch.pc = 0;
 	vcpu->arch.shared->msr = 0;
@@ -634,7 +640,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 
 	kvmppc_init_timing_stats(vcpu);
 
-	return kvmppc_core_vcpu_setup(vcpu);
+	r = kvmppc_core_vcpu_setup(vcpu);
+	kvmppc_sanity_check(vcpu);
+	return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/e500.c linux-libre-3.2-gnu1/arch/powerpc/kvm/e500.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/e500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/e500.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -73,6 +74,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vc
 	/* Since booke kvm only support one core, update all vcpus' PIR to 0 */
 	vcpu->vcpu_id = 0;
 
+	vcpu->arch.cpu_type = KVM_CPU_E500V2;
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/Makefile linux-libre-3.2-gnu1/arch/powerpc/kvm/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -43,18 +43,22 @@ kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_6
 	fpu.o \
 	book3s_paired_singles.o \
 	book3s_pr.o \
+	book3s_pr_papr.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
 	book3s_64_mmu_host.o \
 	book3s_64_mmu.o \
 	book3s_32_mmu.o
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+	book3s_rmhandlers.o
 
 kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv.o \
 	book3s_hv_interrupts.o \
 	book3s_64_mmu_hv.o
 kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
 	book3s_64_vio_hv.o \
 	book3s_hv_builtin.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/kvm/powerpc.c linux-libre-3.2-gnu1/arch/powerpc/kvm/powerpc.c
--- linux-libre-3.1-gnu1/arch/powerpc/kvm/powerpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/kvm/powerpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
-#include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/hrtimer.h>
 #include <linux/fs.h>
@@ -39,12 +38,8 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 	return !(v->arch.shared->msr & MSR_WE) ||
 	       !!(v->arch.pending_exceptions);
-#else
-	return !(v->arch.ceded) || !!(v->arch.pending_exceptions);
-#endif
 }
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -95,6 +90,31 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 	return r;
 }
 
+int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
+{
+	int r = false;
+
+	/* We have to know what CPU to virtualize */
+	if (!vcpu->arch.pvr)
+		goto out;
+
+	/* PAPR only works with book3s_64 */
+	if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
+		goto out;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	/* HV KVM can only do PAPR mode for now */
+	if (!vcpu->arch.papr_enabled)
+		goto out;
+#endif
+
+	r = true;
+
+out:
+	vcpu->arch.sane = r;
+	return r ? 0 : -EINVAL;
+}
+
 int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er;
@@ -188,6 +208,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_PPC_BOOKE_SREGS:
 #else
 	case KVM_CAP_PPC_SEGSTATE:
+	case KVM_CAP_PPC_PAPR:
 #endif
 	case KVM_CAP_PPC_UNSET_IRQ:
 	case KVM_CAP_PPC_IRQ_LEVEL:
@@ -258,6 +279,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 {
 	struct kvm_vcpu *vcpu;
 	vcpu = kvmppc_core_vcpu_create(kvm, id);
+	vcpu->arch.wqp = &vcpu->wq;
 	if (!IS_ERR(vcpu))
 		kvmppc_create_vcpu_debugfs(vcpu, id);
 	return vcpu;
@@ -289,8 +311,8 @@ static void kvmppc_decrementer_func(unsi
 
 	kvmppc_core_queue_dec(vcpu);
 
-	if (waitqueue_active(&vcpu->wq)) {
-		wake_up_interruptible(&vcpu->wq);
+	if (waitqueue_active(vcpu->arch.wqp)) {
+		wake_up_interruptible(vcpu->arch.wqp);
 		vcpu->stat.halt_wakeup++;
 	}
 }
@@ -543,13 +565,15 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
-	if (irq->irq == KVM_INTERRUPT_UNSET)
+	if (irq->irq == KVM_INTERRUPT_UNSET) {
 		kvmppc_core_dequeue_external(vcpu, irq);
-	else
-		kvmppc_core_queue_external(vcpu, irq);
+		return 0;
+	}
 
-	if (waitqueue_active(&vcpu->wq)) {
-		wake_up_interruptible(&vcpu->wq);
+	kvmppc_core_queue_external(vcpu, irq);
+
+	if (waitqueue_active(vcpu->arch.wqp)) {
+		wake_up_interruptible(vcpu->arch.wqp);
 		vcpu->stat.halt_wakeup++;
 	} else if (vcpu->cpu != -1) {
 		smp_send_reschedule(vcpu->cpu);
@@ -571,11 +595,18 @@ static int kvm_vcpu_ioctl_enable_cap(str
 		r = 0;
 		vcpu->arch.osi_enabled = true;
 		break;
+	case KVM_CAP_PPC_PAPR:
+		r = 0;
+		vcpu->arch.papr_enabled = true;
+		break;
 	default:
 		r = -EINVAL;
 		break;
 	}
 
+	if (!r)
+		r = kvmppc_sanity_check(vcpu);
+
 	return r;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/lib/checksum_wrappers_64.c linux-libre-3.2-gnu1/arch/powerpc/lib/checksum_wrappers_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/lib/checksum_wrappers_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/lib/checksum_wrappers_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *
  * Author: Anton Blanchard <anton@au.ibm.com>
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/checksum.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/lib/devres.c linux-libre-3.2-gnu1/arch/powerpc/lib/devres.c
--- linux-libre-3.1-gnu1/arch/powerpc/lib/devres.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/lib/devres.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/device.h>	/* devres_*(), devm_ioremap_release() */
 #include <linux/gfp.h>
 #include <linux/io.h>		/* ioremap_prot() */
-#include <linux/module.h>	/* EXPORT_SYMBOL() */
+#include <linux/export.h>	/* EXPORT_SYMBOL() */
 
 /**
  * devm_ioremap_prot - Managed ioremap_prot()
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/lib/feature-fixups.c linux-libre-3.2-gnu1/arch/powerpc/lib/feature-fixups.c
--- linux-libre-3.1-gnu1/arch/powerpc/lib/feature-fixups.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/lib/feature-fixups.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
+#include <asm/page.h>
+#include <asm/sections.h>
 
 
 struct fixup_entry {
@@ -128,6 +130,27 @@ void do_lwsync_fixups(unsigned long valu
 	}
 }
 
+void do_final_fixups(void)
+{
+#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
+	int *src, *dest;
+	unsigned long length;
+
+	if (PHYSICAL_START == 0)
+		return;
+
+	src = (int *)(KERNELBASE + PHYSICAL_START);
+	dest = (int *)KERNELBASE;
+	length = (__end_interrupts - _stext) / sizeof(int);
+
+	while (length--) {
+		patch_instruction(dest, *src);
+		src++;
+		dest++;
+	}
+#endif
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)	\
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/lib/locks.c linux-libre-3.2-gnu1/arch/powerpc/lib/locks.c
--- linux-libre-3.1-gnu1/arch/powerpc/lib/locks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/lib/locks.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/stringify.h>
 #include <linux/smp.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/lib/rheap.c linux-libre-3.2-gnu1/arch/powerpc/lib/rheap.c
--- linux-libre-3.1-gnu1/arch/powerpc/lib/rheap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/lib/rheap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/Makefile linux-libre-3.2-gnu1/arch/powerpc/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -255,12 +255,6 @@ checkbin:
 		echo 'disable kernel modules' ; \
 		false ; \
 	fi
-	@if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
-		echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
-		echo 'correctly with old versions of binutils.' ; \
-		echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
-		false ; \
-	fi
 
 CLEAN_FILES += $(TOUT)
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/math-emu/math_efp.c linux-libre-3.2-gnu1/arch/powerpc/math-emu/math_efp.c
--- linux-libre-3.1-gnu1/arch/powerpc/math-emu/math_efp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/math-emu/math_efp.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,10 +171,6 @@ static unsigned long insn_type(unsigned
 	case EFDNABS:	ret = XA;	break;
 	case EFDNEG:	ret = XA;	break;
 	case EFDSUB:	ret = AB;	break;
-
-	default:
-		printk(KERN_ERR "\nOoops! SPE instruction no type found.");
-		printk(KERN_ERR "\ninst code: %08lx\n", speinsn);
 	}
 
 	return ret;
@@ -195,7 +191,7 @@ int do_spe_mathemu(struct pt_regs *regs)
 
 	type = insn_type(speinsn);
 	if (type == NOTYPE)
-		return -ENOSYS;
+		goto illegal;
 
 	func = speinsn & 0x7ff;
 	fc = (speinsn >> 21) & 0x1f;
@@ -212,12 +208,10 @@ int do_spe_mathemu(struct pt_regs *regs)
 
 	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
 
-#ifdef DEBUG
-	printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
-	printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-	printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-	printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+	pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+	pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+	pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+	pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
 	switch (src) {
 	case SPFP: {
@@ -235,10 +229,8 @@ int do_spe_mathemu(struct pt_regs *regs)
 			break;
 		}
 
-#ifdef DEBUG
-		printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
-		printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
-#endif
+		pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
+		pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
 
 		switch (func) {
 		case EFSABS:
@@ -305,10 +297,10 @@ int do_spe_mathemu(struct pt_regs *regs)
 			FP_DECL_D(DB);
 			FP_CLEAR_EXCEPTIONS;
 			FP_UNPACK_DP(DB, vb.dp);
-#ifdef DEBUG
-			printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+
+			pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
 					DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
+
 			FP_CONV(S, D, 1, 2, SR, DB);
 			goto pack_s;
 		}
@@ -332,9 +324,8 @@ int do_spe_mathemu(struct pt_regs *regs)
 		break;
 
 pack_s:
-#ifdef DEBUG
-		printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
-#endif
+		pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
+
 		FP_PACK_SP(vc.wp + 1, SR);
 		goto update_regs;
 
@@ -365,12 +356,10 @@ cmp_s:
 			break;
 		}
 
-#ifdef DEBUG
-		printk("DA: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n",
 				DA_s, DA_f1, DA_f0, DA_e, DA_c);
-		printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
 				DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
 
 		switch (func) {
 		case EFDABS:
@@ -438,10 +427,10 @@ cmp_s:
 			FP_DECL_S(SB);
 			FP_CLEAR_EXCEPTIONS;
 			FP_UNPACK_SP(SB, vb.wp + 1);
-#ifdef DEBUG
-			printk("SB: %ld %08lx %ld (%ld)\n",
+
+			pr_debug("SB: %ld %08lx %ld (%ld)\n",
 					SB_s, SB_f, SB_e, SB_c);
-#endif
+
 			FP_CONV(D, S, 2, 1, DR, SB);
 			goto pack_d;
 		}
@@ -471,10 +460,9 @@ cmp_s:
 		break;
 
 pack_d:
-#ifdef DEBUG
-		printk("DR: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n",
 				DR_s, DR_f1, DR_f0, DR_e, DR_c);
-#endif
+
 		FP_PACK_DP(vc.dp, DR);
 		goto update_regs;
 
@@ -511,12 +499,14 @@ cmp_d:
 			break;
 		}
 
-#ifdef DEBUG
-		printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c);
-		printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c);
-		printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c);
-		printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c);
-#endif
+		pr_debug("SA0: %ld %08lx %ld (%ld)\n",
+				SA0_s, SA0_f, SA0_e, SA0_c);
+		pr_debug("SA1: %ld %08lx %ld (%ld)\n",
+				SA1_s, SA1_f, SA1_e, SA1_c);
+		pr_debug("SB0: %ld %08lx %ld (%ld)\n",
+				SB0_s, SB0_f, SB0_e, SB0_c);
+		pr_debug("SB1: %ld %08lx %ld (%ld)\n",
+				SB1_s, SB1_f, SB1_e, SB1_c);
 
 		switch (func) {
 		case EVFSABS:
@@ -605,10 +595,11 @@ cmp_d:
 		break;
 
 pack_vs:
-#ifdef DEBUG
-		printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c);
-		printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c);
-#endif
+		pr_debug("SR0: %ld %08lx %ld (%ld)\n",
+				SR0_s, SR0_f, SR0_e, SR0_c);
+		pr_debug("SR1: %ld %08lx %ld (%ld)\n",
+				SR1_s, SR1_f, SR1_e, SR1_c);
+
 		FP_PACK_SP(vc.wp, SR0);
 		FP_PACK_SP(vc.wp + 1, SR1);
 		goto update_regs;
@@ -646,14 +637,12 @@ update_regs:
 	current->thread.evr[fc] = vc.wp[0];
 	regs->gpr[fc] = vc.wp[1];
 
-#ifdef DEBUG
-	printk("ccr = %08lx\n", regs->ccr);
-	printk("cur exceptions = %08x spefscr = %08lx\n",
+	pr_debug("ccr = %08lx\n", regs->ccr);
+	pr_debug("cur exceptions = %08x spefscr = %08lx\n",
 			FP_CUR_EXCEPTIONS, __FPU_FPSCR);
-	printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-	printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-	printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+	pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+	pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+	pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
 	return 0;
 
@@ -661,9 +650,7 @@ illegal:
 	if (have_e500_cpu_a005_erratum) {
 		/* according to e500 cpu a005 erratum, reissue efp inst */
 		regs->nip -= 4;
-#ifdef DEBUG
-		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
-#endif
+		pr_debug("re-issue efp inst: %08lx\n", speinsn);
 		return 0;
 	}
 
@@ -685,13 +672,20 @@ int speround_handler(struct pt_regs *reg
 	type = insn_type(speinsn & 0x7ff);
 	if (type == XCR) return -ENOSYS;
 
+	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+	pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+
+	/* No need to round if the result is exact */
+	if (!(__FPU_FPSCR & FP_EX_INEXACT))
+		return 0;
+
 	fc = (speinsn >> 21) & 0x1f;
 	s_lo = regs->gpr[fc] & SIGN_BIT_S;
 	s_hi = current->thread.evr[fc] & SIGN_BIT_S;
 	fgpr.wp[0] = current->thread.evr[fc];
 	fgpr.wp[1] = regs->gpr[fc];
 
-	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+	pr_debug("round fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
 	switch ((speinsn >> 5) & 0x7) {
 	/* Since SPE instructions on E500 core can handle round to nearest
@@ -731,6 +725,8 @@ int speround_handler(struct pt_regs *reg
 	current->thread.evr[fc] = fgpr.wp[0];
 	regs->gpr[fc] = fgpr.wp[1];
 
+	pr_debug("  to fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/dma-noncoherent.c linux-libre-3.2-gnu1/arch/powerpc/mm/dma-noncoherent.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/dma-noncoherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/dma-noncoherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/tlbflush.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/fsl_booke_mmu.c linux-libre-3.2-gnu1/arch/powerpc/mm/fsl_booke_mmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/fsl_booke_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/fsl_booke_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -101,17 +101,17 @@ unsigned long p_mapped_by_tlbcam(phys_ad
 
 /*
  * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
- * in particular size must be a power of 4 between 4k and 256M (or 1G, for cpus
- * that support extended page sizes).  Note that while some cpus support a
- * page size of 4G, we don't allow its use here.
+ * in particular size must be a power of 4 between 4k and the max supported by
+ * an implementation; max may further be limited by what can be represented in
+ * an unsigned long (for example, 32-bit implementations cannot support a 4GB
+ * size).
  */
 static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
 		unsigned long size, unsigned long flags, unsigned int pid)
 {
-	unsigned int tsize, lz;
+	unsigned int tsize;
 
-	asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size));
-	tsize = 21 - lz;
+	tsize = __ilog2(size) - 10;
 
 #ifdef CONFIG_SMP
 	if ((flags & _PAGE_NO_CACHE) == 0)
@@ -146,29 +146,36 @@ static void settlbcam(int index, unsigne
 	loadcam_entry(index);
 }
 
+unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+			  phys_addr_t phys)
+{
+	unsigned int camsize = __ilog2(ram) & ~1U;
+	unsigned int align = __ffs(virt | phys) & ~1U;
+	unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+
+	/* Convert (4^max) kB to (2^max) bytes */
+	max_cam = max_cam * 2 + 10;
+
+	if (camsize > align)
+		camsize = align;
+	if (camsize > max_cam)
+		camsize = max_cam;
+
+	return 1UL << camsize;
+}
+
 unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
 {
 	int i;
 	unsigned long virt = PAGE_OFFSET;
 	phys_addr_t phys = memstart_addr;
 	unsigned long amount_mapped = 0;
-	unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
-
-	/* Convert (4^max) kB to (2^max) bytes */
-	max_cam = max_cam * 2 + 10;
 
 	/* Calculate CAM values */
 	for (i = 0; ram && i < max_cam_idx; i++) {
-		unsigned int camsize = __ilog2(ram) & ~1U;
-		unsigned int align = __ffs(virt | phys) & ~1U;
 		unsigned long cam_sz;
 
-		if (camsize > align)
-			camsize = align;
-		if (camsize > max_cam)
-			camsize = max_cam;
-
-		cam_sz = 1UL << camsize;
+		cam_sz = calc_cam_sz(ram, virt, phys);
 		settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0);
 
 		ram -= cam_sz;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/gup.c linux-libre-3.2-gnu1/arch/powerpc/mm/gup.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,16 +16,6 @@
 
 #ifdef __HAVE_ARCH_PTE_SPECIAL
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 /*
  * The performance critical leaf functions are made noinline otherwise gcc
  * inlines everything into a single function which results in too much
@@ -57,8 +47,6 @@ static noinline int gup_pte_range(pmd_t
 			put_page(page);
 			return 0;
 		}
-		if (PageTail(page))
-			get_huge_page_tail(page);
 		pages[*nr] = page;
 		(*nr)++;
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/hash_utils_64.c linux-libre-3.2-gnu1/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/hash_utils_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/hash_utils_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/sysctl.h>
+#include <linux/export.h>
 #include <linux/ctype.h>
 #include <linux/cache.h>
 #include <linux/init.h>
@@ -105,9 +106,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
 u16 mmu_slb_size = 64;
 EXPORT_SYMBOL_GPL(mmu_slb_size);
-#ifdef CONFIG_HUGETLB_PAGE
-unsigned int HPAGE_SHIFT;
-#endif
 #ifdef CONFIG_PPC_64K_PAGES
 int mmu_ci_restrictions;
 #endif
@@ -534,11 +532,11 @@ static unsigned long __init htab_get_tab
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-void create_section_mapping(unsigned long start, unsigned long end)
+int create_section_mapping(unsigned long start, unsigned long end)
 {
-	BUG_ON(htab_bolt_mapping(start, end, __pa(start),
+	return htab_bolt_mapping(start, end, __pa(start),
 				 pgprot_val(PAGE_KERNEL), mmu_linear_psize,
-				 mmu_kernel_ssize));
+				 mmu_kernel_ssize);
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/hugetlbpage-book3e.c linux-libre-3.2-gnu1/arch/powerpc/mm/hugetlbpage-book3e.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/hugetlbpage-book3e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/hugetlbpage-book3e.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,121 @@
+/*
+ * PPC Huge TLB Page Support for Book3E MMU
+ *
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
+ *
+ */
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+static inline int mmu_get_tsize(int psize)
+{
+	return mmu_psize_defs[psize].enc;
+}
+
+static inline int book3e_tlb_exists(unsigned long ea, unsigned long pid)
+{
+	int found = 0;
+
+	mtspr(SPRN_MAS6, pid << 16);
+	if (mmu_has_feature(MMU_FTR_USE_TLBRSRV)) {
+		asm volatile(
+			"li	%0,0\n"
+			"tlbsx.	0,%1\n"
+			"bne	1f\n"
+			"li	%0,1\n"
+			"1:\n"
+			: "=&r"(found) : "r"(ea));
+	} else {
+		asm volatile(
+			"tlbsx	0,%1\n"
+			"mfspr	%0,0x271\n"
+			"srwi	%0,%0,31\n"
+			: "=&r"(found) : "r"(ea));
+	}
+
+	return found;
+}
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte)
+{
+	unsigned long mas1, mas2;
+	u64 mas7_3;
+	unsigned long psize, tsize, shift;
+	unsigned long flags;
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	int index, lz, ncams;
+	struct vm_area_struct *vma;
+#endif
+
+	if (unlikely(is_kernel_addr(ea)))
+		return;
+
+#ifdef CONFIG_PPC_MM_SLICES
+	psize = mmu_get_tsize(get_slice_psize(mm, ea));
+	tsize = mmu_get_psize(psize);
+	shift = mmu_psize_defs[psize].shift;
+#else
+	vma = find_vma(mm, ea);
+	psize = vma_mmu_pagesize(vma);	/* returns actual size in bytes */
+	asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (psize));
+	shift = 31 - lz;
+	tsize = 21 - lz;
+#endif
+
+	/*
+	 * We can't be interrupted while we're setting up the MAS
+	 * regusters or after we've confirmed that no tlb exists.
+	 */
+	local_irq_save(flags);
+
+	if (unlikely(book3e_tlb_exists(ea, mm->context.id))) {
+		local_irq_restore(flags);
+		return;
+	}
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+	/* We have to use the CAM(TLB1) on FSL parts for hugepages */
+	index = __get_cpu_var(next_tlbcam_idx);
+	mtspr(SPRN_MAS0, MAS0_ESEL(index) | MAS0_TLBSEL(1));
+
+	/* Just round-robin the entries and wrap when we hit the end */
+	if (unlikely(index == ncams - 1))
+		__get_cpu_var(next_tlbcam_idx) = tlbcam_index;
+	else
+		__get_cpu_var(next_tlbcam_idx)++;
+#endif
+	mas1 = MAS1_VALID | MAS1_TID(mm->context.id) | MAS1_TSIZE(tsize);
+	mas2 = ea & ~((1UL << shift) - 1);
+	mas2 |= (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+	mas7_3 = (u64)pte_pfn(pte) << PAGE_SHIFT;
+	mas7_3 |= (pte_val(pte) >> PTE_BAP_SHIFT) & MAS3_BAP_MASK;
+	if (!pte_dirty(pte))
+		mas7_3 &= ~(MAS3_SW|MAS3_UW);
+
+	mtspr(SPRN_MAS1, mas1);
+	mtspr(SPRN_MAS2, mas2);
+
+	if (mmu_has_feature(MMU_FTR_USE_PAIRED_MAS)) {
+		mtspr(SPRN_MAS7_MAS3, mas7_3);
+	} else {
+		mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
+		mtspr(SPRN_MAS3, lower_32_bits(mas7_3));
+	}
+
+	asm volatile ("tlbwe");
+
+	local_irq_restore(flags);
+}
+
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+	struct hstate *hstate = hstate_file(vma->vm_file);
+	unsigned long tsize = huge_page_shift(hstate) - 10;
+
+	__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
+
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/hugetlbpage.c linux-libre-3.2-gnu1/arch/powerpc/mm/hugetlbpage.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/hugetlbpage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/hugetlbpage.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,8 @@
 /*
- * PPC64 (POWER4) Huge TLB Page Support for Kernel.
+ * PPC Huge TLB Page Support for Kernel.
  *
  * Copyright (C) 2003 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
  *
  * Based on the IA-32 version:
  * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
@@ -11,24 +12,40 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/of_fdt.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/moduleparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 #define PAGE_SHIFT_64K	16
 #define PAGE_SHIFT_16M	24
 #define PAGE_SHIFT_16G	34
 
-#define MAX_NUMBER_GPAGES	1024
+unsigned int HPAGE_SHIFT;
 
-/* Tracks the 16G pages after the device tree is scanned and before the
- * huge_boot_pages list is ready.  */
-static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+/*
+ * Tracks gpages after the device tree is scanned and before the
+ * huge_boot_pages list is ready.  On 64-bit implementations, this is
+ * just used to track 16G pages and so is a single array.  32-bit
+ * implementations may have more than one gpage size due to limitations
+ * of the memory allocators, so we need multiple arrays
+ */
+#ifdef CONFIG_PPC64
+#define MAX_NUMBER_GPAGES	1024
+static u64 gpage_freearray[MAX_NUMBER_GPAGES];
 static unsigned nr_gpages;
-
-/* Flag to mark huge PD pointers.  This means pmd_bad() and pud_bad()
- * will choke on pointers to hugepte tables, which is handy for
- * catching screwups early. */
+#else
+#define MAX_NUMBER_GPAGES	128
+struct psize_gpages {
+	u64 gpage_list[MAX_NUMBER_GPAGES];
+	unsigned int nr_gpages;
+};
+static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT];
+#endif
 
 static inline int shift_to_mmu_psize(unsigned int shift)
 {
@@ -49,25 +66,6 @@ static inline unsigned int mmu_psize_to_
 
 #define hugepd_none(hpd)	((hpd).pd == 0)
 
-static inline pte_t *hugepd_page(hugepd_t hpd)
-{
-	BUG_ON(!hugepd_ok(hpd));
-	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000);
-}
-
-static inline unsigned int hugepd_shift(hugepd_t hpd)
-{
-	return hpd.pd & HUGEPD_SHIFT_MASK;
-}
-
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift)
-{
-	unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
-	pte_t *dir = hugepd_page(*hpdp);
-
-	return dir + idx;
-}
-
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 {
 	pgd_t *pg;
@@ -93,7 +91,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *
 			if (is_hugepd(pm))
 				hpdp = (hugepd_t *)pm;
 			else if (!pmd_none(*pm)) {
-				return pte_offset_map(pm, ea);
+				return pte_offset_kernel(pm, ea);
 			}
 		}
 	}
@@ -114,8 +112,18 @@ pte_t *huge_pte_offset(struct mm_struct
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
 			   unsigned long address, unsigned pdshift, unsigned pshift)
 {
-	pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift),
-				       GFP_KERNEL|__GFP_REPEAT);
+	struct kmem_cache *cachep;
+	pte_t *new;
+
+#ifdef CONFIG_PPC64
+	cachep = PGT_CACHE(pdshift - pshift);
+#else
+	int i;
+	int num_hugepd = 1 << (pshift - pdshift);
+	cachep = hugepte_cache;
+#endif
+
+	new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
 
 	BUG_ON(pshift > HUGEPD_SHIFT_MASK);
 	BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -124,10 +132,31 @@ static int __hugepte_alloc(struct mm_str
 		return -ENOMEM;
 
 	spin_lock(&mm->page_table_lock);
+#ifdef CONFIG_PPC64
 	if (!hugepd_none(*hpdp))
-		kmem_cache_free(PGT_CACHE(pdshift - pshift), new);
+		kmem_cache_free(cachep, new);
 	else
-		hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift;
+		hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+#else
+	/*
+	 * We have multiple higher-level entries that point to the same
+	 * actual pte location.  Fill in each as we go and backtrack on error.
+	 * We need all of these so the DTLB pgtable walk code can find the
+	 * right higher-level entry without knowing if it's a hugepage or not.
+	 */
+	for (i = 0; i < num_hugepd; i++, hpdp++) {
+		if (unlikely(!hugepd_none(*hpdp)))
+			break;
+		else
+			hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+	}
+	/* If we bailed from the for loop early, an error occurred, clean up */
+	if (i < num_hugepd) {
+		for (i = i - 1 ; i >= 0; i--, hpdp--)
+			hpdp->pd = 0;
+		kmem_cache_free(cachep, new);
+	}
+#endif
 	spin_unlock(&mm->page_table_lock);
 	return 0;
 }
@@ -169,11 +198,132 @@ pte_t *huge_pte_alloc(struct mm_struct *
 	return hugepte_offset(hpdp, addr, pdshift);
 }
 
+#ifdef CONFIG_PPC32
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy or bootmem allocator is setup.
  */
-void add_gpage(unsigned long addr, unsigned long page_size,
-	unsigned long number_of_pages)
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
+{
+	unsigned int idx = shift_to_mmu_psize(__ffs(page_size));
+	int i;
+
+	if (addr == 0)
+		return;
+
+	gpage_freearray[idx].nr_gpages = number_of_pages;
+
+	for (i = 0; i < number_of_pages; i++) {
+		gpage_freearray[idx].gpage_list[i] = addr;
+		addr += page_size;
+	}
+}
+
+/*
+ * Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+	struct huge_bootmem_page *m;
+	int idx = shift_to_mmu_psize(hstate->order + PAGE_SHIFT);
+	int nr_gpages = gpage_freearray[idx].nr_gpages;
+
+	if (nr_gpages == 0)
+		return 0;
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * If gpages can be in highmem we can't use the trick of storing the
+	 * data structure in the page; allocate space for this
+	 */
+	m = alloc_bootmem(sizeof(struct huge_bootmem_page));
+	m->phys = gpage_freearray[idx].gpage_list[--nr_gpages];
+#else
+	m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]);
+#endif
+
+	list_add(&m->list, &huge_boot_pages);
+	gpage_freearray[idx].nr_gpages = nr_gpages;
+	gpage_freearray[idx].gpage_list[nr_gpages] = 0;
+	m->hstate = hstate;
+
+	return 1;
+}
+/*
+ * Scan the command line hugepagesz= options for gigantic pages; store those in
+ * a list that we use to allocate the memory once all options are parsed.
+ */
+
+unsigned long gpage_npages[MMU_PAGE_COUNT];
+
+static int __init do_gpage_early_setup(char *param, char *val)
+{
+	static phys_addr_t size;
+	unsigned long npages;
+
+	/*
+	 * The hugepagesz and hugepages cmdline options are interleaved.  We
+	 * use the size variable to keep track of whether or not this was done
+	 * properly and skip over instances where it is incorrect.  Other
+	 * command-line parsing code will issue warnings, so we don't need to.
+	 *
+	 */
+	if ((strcmp(param, "default_hugepagesz") == 0) ||
+	    (strcmp(param, "hugepagesz") == 0)) {
+		size = memparse(val, NULL);
+	} else if (strcmp(param, "hugepages") == 0) {
+		if (size != 0) {
+			if (sscanf(val, "%lu", &npages) <= 0)
+				npages = 0;
+			gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages;
+			size = 0;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * This function allocates physical space for pages that are larger than the
+ * buddy allocator can handle.  We want to allocate these in highmem because
+ * the amount of lowmem is limited.  This means that this function MUST be
+ * called before lowmem_end_addr is set up in MMU_init() in order for the lmb
+ * allocate to grab highmem.
+ */
+void __init reserve_hugetlb_gpages(void)
+{
+	static __initdata char cmdline[COMMAND_LINE_SIZE];
+	phys_addr_t size, base;
+	int i;
+
+	strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
+	parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+
+	/*
+	 * Walk gpage list in reverse, allocating larger page sizes first.
+	 * Skip over unsupported sizes, or sizes that have 0 gpages allocated.
+	 * When we reach the point in the list where pages are no longer
+	 * considered gpages, we're done.
+	 */
+	for (i = MMU_PAGE_COUNT-1; i >= 0; i--) {
+		if (mmu_psize_defs[i].shift == 0 || gpage_npages[i] == 0)
+			continue;
+		else if (mmu_psize_to_shift(i) < (MAX_ORDER + PAGE_SHIFT))
+			break;
+
+		size = (phys_addr_t)(1ULL << mmu_psize_to_shift(i));
+		base = memblock_alloc_base(size * gpage_npages[i], size,
+					   MEMBLOCK_ALLOC_ANYWHERE);
+		add_gpage(base, size, gpage_npages[i]);
+	}
+}
+
+#else /* PPC64 */
+
+/* Build list of addresses of gigantic pages.  This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
 {
 	if (!addr)
 		return;
@@ -199,19 +349,79 @@ int alloc_bootmem_huge_page(struct hstat
 	m->hstate = hstate;
 	return 1;
 }
+#endif
 
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
 {
 	return 0;
 }
 
+#ifdef CONFIG_PPC32
+#define HUGEPD_FREELIST_SIZE \
+	((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t))
+
+struct hugepd_freelist {
+	struct rcu_head	rcu;
+	unsigned int index;
+	void *ptes[0];
+};
+
+static DEFINE_PER_CPU(struct hugepd_freelist *, hugepd_freelist_cur);
+
+static void hugepd_free_rcu_callback(struct rcu_head *head)
+{
+	struct hugepd_freelist *batch =
+		container_of(head, struct hugepd_freelist, rcu);
+	unsigned int i;
+
+	for (i = 0; i < batch->index; i++)
+		kmem_cache_free(hugepte_cache, batch->ptes[i]);
+
+	free_page((unsigned long)batch);
+}
+
+static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
+{
+	struct hugepd_freelist **batchp;
+
+	batchp = &__get_cpu_var(hugepd_freelist_cur);
+
+	if (atomic_read(&tlb->mm->mm_users) < 2 ||
+	    cpumask_equal(mm_cpumask(tlb->mm),
+			  cpumask_of(smp_processor_id()))) {
+		kmem_cache_free(hugepte_cache, hugepte);
+		return;
+	}
+
+	if (*batchp == NULL) {
+		*batchp = (struct hugepd_freelist *)__get_free_page(GFP_ATOMIC);
+		(*batchp)->index = 0;
+	}
+
+	(*batchp)->ptes[(*batchp)->index++] = hugepte;
+	if ((*batchp)->index == HUGEPD_FREELIST_SIZE) {
+		call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback);
+		*batchp = NULL;
+	}
+}
+#endif
+
 static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift,
 			      unsigned long start, unsigned long end,
 			      unsigned long floor, unsigned long ceiling)
 {
 	pte_t *hugepte = hugepd_page(*hpdp);
-	unsigned shift = hugepd_shift(*hpdp);
+	int i;
+
 	unsigned long pdmask = ~((1UL << pdshift) - 1);
+	unsigned int num_hugepd = 1;
+
+#ifdef CONFIG_PPC64
+	unsigned int shift = hugepd_shift(*hpdp);
+#else
+	/* Note: On 32-bit the hpdp may be the first of several */
+	num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift));
+#endif
 
 	start &= pdmask;
 	if (start < floor)
@@ -224,9 +434,15 @@ static void free_hugepd_range(struct mmu
 	if (end - 1 > ceiling - 1)
 		return;
 
-	hpdp->pd = 0;
+	for (i = 0; i < num_hugepd; i++, hpdp++)
+		hpdp->pd = 0;
+
 	tlb->need_flush = 1;
+#ifdef CONFIG_PPC64
 	pgtable_free_tlb(tlb, hugepte, pdshift - shift);
+#else
+	hugepd_free(tlb, hugepte);
+#endif
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
@@ -331,18 +547,27 @@ void hugetlb_free_pgd_range(struct mmu_g
 	 * too.
 	 */
 
-	pgd = pgd_offset(tlb->mm, addr);
 	do {
 		next = pgd_addr_end(addr, end);
+		pgd = pgd_offset(tlb->mm, addr);
 		if (!is_hugepd(pgd)) {
 			if (pgd_none_or_clear_bad(pgd))
 				continue;
 			hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
 		} else {
+#ifdef CONFIG_PPC32
+			/*
+			 * Increment next by the size of the huge mapping since
+			 * on 32-bit there may be more than one entry at the pgd
+			 * level for a single hugepage, but all of them point to
+			 * the same kmem cache that holds the hugepte.
+			 */
+			next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+#endif
 			free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT,
 					  addr, next, floor, ceiling);
 		}
-	} while (pgd++, addr = next, addr != end);
+	} while (addr = next, addr != end);
 }
 
 struct page *
@@ -390,7 +615,7 @@ static noinline int gup_hugepte(pte_t *p
 {
 	unsigned long mask;
 	unsigned long pte_end;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	pte_t pte;
 	int refs;
 
@@ -413,6 +638,7 @@ static noinline int gup_hugepte(pte_t *p
 	head = pte_page(pte);
 
 	page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -428,10 +654,20 @@ static noinline int gup_hugepte(pte_t *p
 
 	if (unlikely(pte_val(pte) != pte_val(*ptep))) {
 		/* Could be optimized better */
-		while (*nr) {
-			put_page(page);
-			(*nr)--;
-		}
+		*nr -= refs;
+		while (refs--)
+			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
@@ -466,17 +702,35 @@ unsigned long hugetlb_get_unmapped_area(
 					unsigned long len, unsigned long pgoff,
 					unsigned long flags)
 {
+#ifdef CONFIG_PPC_MM_SLICES
 	struct hstate *hstate = hstate_file(file);
 	int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
 	return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
+#else
+	return get_unmapped_area(file, addr, len, pgoff, flags);
+#endif
 }
 
 unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
 {
+#ifdef CONFIG_PPC_MM_SLICES
 	unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
 
 	return 1UL << mmu_psize_to_shift(psize);
+#else
+	if (!is_vm_hugetlb_page(vma))
+		return PAGE_SIZE;
+
+	return huge_page_size(hstate_vma(vma));
+#endif
+}
+
+static inline bool is_power_of_4(unsigned long x)
+{
+	if (is_power_of_2(x))
+		return (__ilog2(x) % 2) ? false : true;
+	return false;
 }
 
 static int __init add_huge_page_size(unsigned long long size)
@@ -486,9 +740,14 @@ static int __init add_huge_page_size(uns
 
 	/* Check that it is a page size supported by the hardware and
 	 * that it fits within pagetable and slice limits. */
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if ((size < PAGE_SIZE) || !is_power_of_4(size))
+		return -EINVAL;
+#else
 	if (!is_power_of_2(size)
 	    || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT))
 		return -EINVAL;
+#endif
 
 	if ((mmu_psize = shift_to_mmu_psize(shift)) < 0)
 		return -EINVAL;
@@ -525,6 +784,46 @@ static int __init hugepage_setup_sz(char
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
+#ifdef CONFIG_FSL_BOOKE
+struct kmem_cache *hugepte_cache;
+static int __init hugetlbpage_init(void)
+{
+	int psize;
+
+	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+		unsigned shift;
+
+		if (!mmu_psize_defs[psize].shift)
+			continue;
+
+		shift = mmu_psize_to_shift(psize);
+
+		/* Don't treat normal page sizes as huge... */
+		if (shift != PAGE_SHIFT)
+			if (add_huge_page_size(1ULL << shift) < 0)
+				continue;
+	}
+
+	/*
+	 * Create a kmem cache for hugeptes.  The bottom bits in the pte have
+	 * size information encoded in them, so align them to allow this
+	 */
+	hugepte_cache =  kmem_cache_create("hugepte-cache", sizeof(pte_t),
+					   HUGEPD_SHIFT_MASK + 1, 0, NULL);
+	if (hugepte_cache == NULL)
+		panic("%s: Unable to create kmem cache for hugeptes\n",
+		      __func__);
+
+	/* Default hpage size = 4M */
+	if (mmu_psize_defs[MMU_PAGE_4M].shift)
+		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_4M].shift;
+	else
+		panic("%s: Unable to set default huge page size\n", __func__);
+
+
+	return 0;
+}
+#else
 static int __init hugetlbpage_init(void)
 {
 	int psize;
@@ -567,15 +866,23 @@ static int __init hugetlbpage_init(void)
 
 	return 0;
 }
-
+#endif
 module_init(hugetlbpage_init);
 
 void flush_dcache_icache_hugepage(struct page *page)
 {
 	int i;
+	void *start;
 
 	BUG_ON(!PageCompound(page));
 
-	for (i = 0; i < (1UL << compound_order(page)); i++)
-		__flush_dcache_icache(page_address(page+i));
+	for (i = 0; i < (1UL << compound_order(page)); i++) {
+		if (!PageHighMem(page)) {
+			__flush_dcache_icache(page_address(page+i));
+		} else {
+			start = kmap_atomic(page+i, KM_PPC_SYNC_ICACHE);
+			__flush_dcache_icache(start);
+			kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+		}
+	}
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/init_32.c linux-libre-3.2-gnu1/arch/powerpc/mm/init_32.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/init_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/init_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -44,6 +46,7 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/system.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
@@ -123,6 +126,12 @@ void __init MMU_init(void)
 	/* parse args from command line */
 	MMU_setup();
 
+	/*
+	 * Reserve gigantic pages for hugetlb.  This MUST occur before
+	 * lowmem_end_addr is initialized below.
+	 */
+	reserve_hugetlb_gpages();
+
 	if (memblock.memory.cnt > 1) {
 #ifndef CONFIG_WII
 		memblock.memory.cnt = 1;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/Makefile linux-libre-3.2-gnu1/arch/powerpc/mm/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/mm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_MM_SLICES)	+= slice.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
 obj-y				+= hugetlbpage.o
 obj-$(CONFIG_PPC_STD_MMU_64)	+= hugetlbpage-hash64.o
+obj-$(CONFIG_PPC_BOOK3E_MMU)	+= hugetlbpage-book3e.o
 endif
 obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/mem.c linux-libre-3.2-gnu1/arch/powerpc/mm/mem.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/memblock.h>
 #include <linux/hugetlb.h>
+#include <linux/slab.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -123,7 +124,8 @@ int arch_add_memory(int nid, u64 start,
 	pgdata = NODE_DATA(nid);
 
 	start = (unsigned long)__va(start);
-	create_section_mapping(start, start + size);
+	if (create_section_mapping(start, start + size))
+		return -EINVAL;
 
 	/* this should work for most non-highmem platforms */
 	zone = pgdata->node_zones;
@@ -548,4 +550,38 @@ void update_mmu_cache(struct vm_area_str
 		return;
 	hash_preload(vma->vm_mm, address, access, trap);
 #endif /* CONFIG_PPC_STD_MMU */
+#if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \
+	&& defined(CONFIG_HUGETLB_PAGE)
+	if (is_vm_hugetlb_page(vma))
+		book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
+#endif
+}
+
+/*
+ * System memory should not be in /proc/iomem but various tools expect it
+ * (eg kdump).
+ */
+static int add_system_ram_resources(void)
+{
+	struct memblock_region *reg;
+
+	for_each_memblock(memory, reg) {
+		struct resource *res;
+		unsigned long base = reg->base;
+		unsigned long size = reg->size;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		WARN_ON(!res);
+
+		if (res) {
+			res->name = "System RAM";
+			res->start = base;
+			res->end = base + size - 1;
+			res->flags = IORESOURCE_MEM;
+			WARN_ON(request_resource(&iomem_resource, res) < 0);
+		}
+	}
+
+	return 0;
 }
+subsys_initcall(add_system_ram_resources);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_hash32.c linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_hash32.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_hash32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_hash32.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/export.h>
 
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_hash64.c linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_hash64.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_hash64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_hash64.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
 
@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct m
 	if (!mm || !acop)
 		return -EINVAL;
 
-	/* We need to make sure mm_users doesn't change */
-	down_read(&mm->mmap_sem);
+	/* The page_table_lock ensures mm_users won't change under us */
+	spin_lock(&mm->page_table_lock);
 	spin_lock(mm->context.cop_lockp);
 
 	if (mm->context.cop_pid == COP_PID_NONE) {
@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct m
 
 out:
 	spin_unlock(mm->context.cop_lockp);
-	up_read(&mm->mmap_sem);
+	spin_unlock(&mm->page_table_lock);
 
 	return ret;
 }
@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct
 	if (WARN_ON_ONCE(!mm))
 		return;
 
-	/* We need to make sure mm_users doesn't change */
-	down_read(&mm->mmap_sem);
+	/* The page_table_lock ensures mm_users won't change under us */
+	spin_lock(&mm->page_table_lock);
 	spin_lock(mm->context.cop_lockp);
 
 	mm->context.acop &= ~acop;
@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct
 	}
 
 	spin_unlock(mm->context.cop_lockp);
-	up_read(&mm->mmap_sem);
+	spin_unlock(&mm->page_table_lock);
 }
 EXPORT_SYMBOL_GPL(drop_cop);
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_nohash.c linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_nohash.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_context_nohash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_context_nohash.c	2012-01-04 18:55:44.000000000 -0500
@@ -292,6 +292,11 @@ int init_new_context(struct task_struct
 	mm->context.id = MMU_NO_CONTEXT;
 	mm->context.active = 0;
 
+#ifdef CONFIG_PPC_MM_SLICES
+	if (slice_mm_new_context(mm))
+		slice_set_user_psize(mm, mmu_virtual_psize);
+#endif
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_decl.h linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_decl.h
--- linux-libre-3.1-gnu1/arch/powerpc/mm/mmu_decl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/mmu_decl.h	2012-01-04 18:55:44.000000000 -0500
@@ -142,6 +142,8 @@ extern unsigned long mmu_mapin_ram(unsig
 
 #elif defined(CONFIG_PPC_FSL_BOOK3E)
 extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+				 phys_addr_t phys);
 #ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/numa.c linux-libre-3.2-gnu1/arch/powerpc/mm/numa.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/numa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/numa.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
@@ -315,7 +315,10 @@ static int __init find_min_common_depth(
 	struct device_node *root;
 	const char *vec5;
 
-	root = of_find_node_by_path("/rtas");
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		root = of_find_node_by_path("/ibm,opal");
+	else
+		root = of_find_node_by_path("/rtas");
 	if (!root)
 		root = of_find_node_by_path("/");
 
@@ -344,12 +347,19 @@ static int __init find_min_common_depth(
 
 #define VEC5_AFFINITY_BYTE	5
 #define VEC5_AFFINITY		0x80
-	chosen = of_find_node_by_path("/chosen");
-	if (chosen) {
-		vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
-		if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
-			dbg("Using form 1 affinity\n");
-			form1_affinity = 1;
+
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		form1_affinity = 1;
+	else {
+		chosen = of_find_node_by_path("/chosen");
+		if (chosen) {
+			vec5 = of_get_property(chosen,
+					       "ibm,architecture-vec-5", NULL);
+			if (vec5 && (vec5[VEC5_AFFINITY_BYTE] &
+							VEC5_AFFINITY)) {
+				dbg("Using form 1 affinity\n");
+				form1_affinity = 1;
+			}
 		}
 	}
 
@@ -709,8 +719,7 @@ static void __init parse_drconf_memory(s
 
 static int __init parse_numa_properties(void)
 {
-	struct device_node *cpu = NULL;
-	struct device_node *memory = NULL;
+	struct device_node *memory;
 	int default_nid = 0;
 	unsigned long i;
 
@@ -732,6 +741,7 @@ static int __init parse_numa_properties(
 	 * each node to be onlined must have NODE_DATA etc backing it.
 	 */
 	for_each_present_cpu(i) {
+		struct device_node *cpu;
 		int nid;
 
 		cpu = of_get_cpu_node(i, NULL);
@@ -750,8 +760,8 @@ static int __init parse_numa_properties(
 	}
 
 	get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
-	memory = NULL;
-	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+
+	for_each_node_by_type(memory, "memory") {
 		unsigned long start;
 		unsigned long size;
 		int nid;
@@ -800,8 +810,9 @@ new_range:
 	}
 
 	/*
-	 * Now do the same thing for each MEMBLOCK listed in the ibm,dynamic-memory
-	 * property in the ibm,dynamic-reconfiguration-memory node.
+	 * Now do the same thing for each MEMBLOCK listed in the
+	 * ibm,dynamic-memory property in the
+	 * ibm,dynamic-reconfiguration-memory node.
 	 */
 	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
 	if (memory)
@@ -1187,10 +1198,10 @@ static int hot_add_drconf_scn_to_nid(str
  */
 int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
-	struct device_node *memory = NULL;
+	struct device_node *memory;
 	int nid = -1;
 
-	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+	for_each_node_by_type(memory, "memory") {
 		unsigned long start, size;
 		int ranges;
 		const unsigned int *memcell_buf;
@@ -1214,11 +1225,12 @@ int hot_add_node_scn_to_nid(unsigned lon
 			break;
 		}
 
-		of_node_put(memory);
 		if (nid >= 0)
 			break;
 	}
 
+	of_node_put(memory);
+
 	return nid;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/pgtable_64.c linux-libre-3.2-gnu1/arch/powerpc/mm/pgtable_64.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/pgtable_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/pgtable_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/pgtable.c linux-libre-3.2-gnu1/arch/powerpc/mm/pgtable.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/pgtable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/pgtable.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/hugetlb.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -212,7 +213,7 @@ int ptep_set_access_flags(struct vm_area
 	entry = set_access_flags_filter(entry, vma, dirty);
 	changed = !pte_same(*(ptep), entry);
 	if (changed) {
-		if (!(vma->vm_flags & VM_HUGETLB))
+		if (!is_vm_hugetlb_page(vma))
 			assert_pte_locked(vma->vm_mm, address);
 		__ptep_set_access_flags(ptep, entry);
 		flush_tlb_page_nohash(vma, address);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/slice.c linux-libre-3.2-gnu1/arch/powerpc/mm/slice.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/slice.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/slice.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/pagemap.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/mman.h>
 #include <asm/mmu.h>
 #include <asm/spu.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_hash32.c linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_hash32.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_hash32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_hash32.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/export.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_low_64e.S linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_low_64e.S
--- linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_low_64e.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_low_64e.S	2012-01-04 18:55:44.000000000 -0500
@@ -553,24 +553,24 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TL
 	rldicl	r11,r16,64-VPTE_PGD_SHIFT,64-PGD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
 	/* Get to PUD entry */
 	rldicl	r11,r16,64-VPTE_PUD_SHIFT,64-PUD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
 	/* Get to PMD entry */
 	rldicl	r11,r16,64-VPTE_PMD_SHIFT,64-PMD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 
 	/* Ok, we're all right, we can now create a kernel translation for
 	 * a 4K or 64K page from r16 -> r15.
@@ -802,24 +802,24 @@ htw_tlb_miss:
 	rldicl	r11,r16,64-(PGDIR_SHIFT-3),64-PGD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
 	/* Get to PUD entry */
 	rldicl	r11,r16,64-(PUD_SHIFT-3),64-PUD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
 	/* Get to PMD entry */
 	rldicl	r11,r16,64-(PMD_SHIFT-3),64-PMD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 
 	/* Ok, we're all right, we can now create an indirect entry for
 	 * a 1M or 256M page.
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_nohash.c linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_nohash.c
--- linux-libre-3.1-gnu1/arch/powerpc/mm/tlb_nohash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/mm/tlb_nohash.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
@@ -36,14 +37,49 @@
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
+#include <linux/hugetlb.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/code-patching.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
-#ifdef CONFIG_PPC_BOOK3E
+/*
+ * This struct lists the sw-supported page sizes.  The hardawre MMU may support
+ * other sizes not listed here.   The .ind field is only used on MMUs that have
+ * indirect page table entries.
+ */
+#ifdef CONFIG_PPC_BOOK3E_MMU
+#ifdef CONFIG_FSL_BOOKE
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
+	[MMU_PAGE_4K] = {
+		.shift	= 12,
+		.enc	= BOOK3E_PAGESZ_4K,
+	},
+	[MMU_PAGE_4M] = {
+		.shift	= 22,
+		.enc	= BOOK3E_PAGESZ_4M,
+	},
+	[MMU_PAGE_16M] = {
+		.shift	= 24,
+		.enc	= BOOK3E_PAGESZ_16M,
+	},
+	[MMU_PAGE_64M] = {
+		.shift	= 26,
+		.enc	= BOOK3E_PAGESZ_64M,
+	},
+	[MMU_PAGE_256M] = {
+		.shift	= 28,
+		.enc	= BOOK3E_PAGESZ_256M,
+	},
+	[MMU_PAGE_1G] = {
+		.shift	= 30,
+		.enc	= BOOK3E_PAGESZ_1GB,
+	},
+};
+#else
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
 	[MMU_PAGE_4K] = {
 		.shift	= 12,
@@ -77,6 +113,8 @@ struct mmu_psize_def mmu_psize_defs[MMU_
 		.enc	= BOOK3E_PAGESZ_1GB,
 	},
 };
+#endif /* CONFIG_FSL_BOOKE */
+
 static inline int mmu_get_tsize(int psize)
 {
 	return mmu_psize_defs[psize].enc;
@@ -87,7 +125,7 @@ static inline int mmu_get_tsize(int psiz
 	/* This isn't used on !Book3E for now */
 	return 0;
 }
-#endif
+#endif /* CONFIG_PPC_BOOK3E_MMU */
 
 /* The variables below are currently only used on 64-bit Book3E
  * though this will probably be made common with other nohash
@@ -266,6 +304,11 @@ void __flush_tlb_page(struct mm_struct *
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
+#ifdef CONFIG_HUGETLB_PAGE
+	if (is_vm_hugetlb_page(vma))
+		flush_hugetlb_page(vma, vmaddr);
+#endif
+
 	__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
 			 mmu_get_tsize(mmu_virtual_psize), 0);
 }
@@ -600,13 +643,28 @@ void __cpuinit early_init_mmu_secondary(
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				phys_addr_t first_memblock_size)
 {
-	/* On Embedded 64-bit, we adjust the RMA size to match
+	/* On non-FSL Embedded 64-bit, we adjust the RMA size to match
 	 * the bolted TLB entry. We know for now that only 1G
 	 * entries are supported though that may eventually
-	 * change. We crop it to the size of the first MEMBLOCK to
+	 * change.
+	 *
+	 * on FSL Embedded 64-bit, we adjust the RMA size to match the
+	 * first bolted TLB entry size.  We still limit max to 1G even if
+	 * the TLB could cover more.  This is due to what the early init
+	 * code is setup to do.
+	 *
+	 * We crop it to the size of the first MEMBLOCK to
 	 * avoid going over total available memory just in case...
 	 */
-	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+		unsigned long linear_sz;
+		linear_sz = calc_cam_sz(first_memblock_size, PAGE_OFFSET,
+					first_memblock_base);
+		ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
+	} else
+#endif
+		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
 	/* Finally limit subsequent allocations */
 	memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/hcu4.c linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/hcu4.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/hcu4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/hcu4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/*
- * Architecture- / platform-specific boot-time initialization code for
- * IBM PowerPC 4xx based boards. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 IBM Corporation
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- *
- * 2002 (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/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id hcu4_of_bus[] = {
-	{ .compatible = "ibm,plb3", },
-	{ .compatible = "ibm,opb", },
-	{ .compatible = "ibm,ebc", },
-	{},
-};
-
-static int __init hcu4_device_probe(void)
-{
-	of_platform_bus_probe(NULL, hcu4_of_bus, NULL);
-	return 0;
-}
-machine_device_initcall(hcu4, hcu4_device_probe);
-
-static int __init hcu4_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	if (!of_flat_dt_is_compatible(root, "netstal,hcu4"))
-		return 0;
-
-	return 1;
-}
-
-define_machine(hcu4) {
-	.name			= "HCU4",
-	.probe			= hcu4_probe,
-	.progress		= udbg_progress,
-	.init_IRQ		= uic_init_tree,
-	.get_irq		= uic_get_irq,
-	.restart		= ppc4xx_reset_system,
-	.calibrate_decr		= generic_calibrate_decr,
-};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -32,14 +32,6 @@ config EP405
 	help
 	  This option enables support for the EP405/EP405PC boards.
 
-config HCU4
-	bool "Hcu4"
-	depends on 40x
-	default n
-	select 405GPR
-	help
-	  This option enables support for the Nestal Maschinen HCU4 board.
-
 config HOTFOOT
         bool "Hotfoot"
 	depends on 40x
@@ -115,11 +107,6 @@ config PPC40x_SIMPLE
 	help
 	  This option enables the simple PowerPC 40x platform support.
 
-# 40x specific CPU modules, selected based on the board above.
-config NP405H
-	bool
-	#depends on ASH
-
 # OAK doesn't exist but wanted to keep this around for any future 403GCX boards
 config 403GCX
 	bool
@@ -130,21 +117,21 @@ config 405GP
 	bool
 	select IBM405_ERR77
 	select IBM405_ERR51
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 
 config 405EP
 	bool
 
 config 405EX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
 
 config 405EZ
 	bool
-	select IBM_NEW_EMAC_NO_FLOW_CTRL
-	select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
-	select IBM_NEW_EMAC_MAL_COMMON_ERR
+	select IBM_EMAC_NO_FLOW_CTRL
+	select IBM_EMAC_MAL_CLR_ICINTSTAT
+	select IBM_EMAC_MAL_COMMON_ERR
 
 config 405GPR
 	bool
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/40x/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/40x/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,3 @@
-obj-$(CONFIG_HCU4)				+= hcu4.o
 obj-$(CONFIG_WALNUT)				+= walnut.o
 obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD)	+= virtex.o
 obj-$(CONFIG_EP405)				+= ep405.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/44x/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/44x/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/44x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/44x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@ config BLUESTONE
 	default n
 	select PPC44x_SIMPLE
 	select APM821xx
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_RGMII
 	help
 	  This option enables support for the APM APM821xx Evaluation board.
 
@@ -122,8 +122,8 @@ config CANYONLANDS
 	select PPC4xx_PCI_EXPRESS
 	select PCI_MSI
 	select PPC4xx_MSI
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 	help
 	  This option enables support for the AMCC PPC460EX evaluation board.
 
@@ -135,8 +135,8 @@ config GLACIER
 	select 460EX # Odd since it uses 460GT but the effects are the same
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 	help
 	  This option enables support for the AMCC PPC460GT evaluation board.
 
@@ -161,7 +161,7 @@ config EIGER
 	select 460SX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_RGMII
 	help
 	  This option enables support for the AMCC PPC460SX evaluation board.
 
@@ -260,59 +260,59 @@ config 440EP
 	bool
 	select PPC_FPU
 	select IBM440EP_ERR42
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 	select USB_ARCH_HAS_OHCI
 
 config 440EPX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 
 config 440GRX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 
 config 440GP
 	bool
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 
 config 440GX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII #test only
-	select IBM_NEW_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII #test only
+	select IBM_EMAC_TAH  #test only
 
 config 440SP
 	bool
 
 config 440SPe
 	bool
-	select IBM_NEW_EMAC_EMAC4
+	select IBM_EMAC_EMAC4
 
 config 460EX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_TAH
 
 config 460SX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
+	select IBM_EMAC_TAH
 
 config APM821xx
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_TAH
 
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/44x/warp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/44x/warp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/44x/warp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/44x/warp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/clock.c linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/clock.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@ config PPC_MPC512x
 	select PPC_CLOCK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config MPC5121_ADS
 	bool "Freescale MPC5121E ADS"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/mpc512x_shared.c linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/mpc512x_shared.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/512x/mpc512x_shared.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/512x/mpc512x_shared.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
-				      int monitor_port)
+u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
+			     unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(un
 	return 0x00000400;
 }
 
-void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
+			     char *gamma_table_base)
 {
 }
 
-void mpc512x_set_monitor_port(int monitor_port)
+void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 }
 
@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned in
 	iounmap(ccm);
 }
 
-ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
-{
-	return sprintf(buf, "0 - 5121 LCD\n");
-}
-
-int mpc512x_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return 0;
+	return FSL_DIU_PORT_DVI;
 }
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
@@ -256,7 +253,7 @@ void __init mpc512x_init_diu(void)
 	}
 
 	mode = in_be32(&diu_reg->diu_mode);
-	if (mode != MFB_MODE1) {
+	if (mode == MFB_MODE0) {
 		pr_info("%s: DIU OFF\n", __func__);
 		goto out;
 	}
@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void)
 	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc512x_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc512x_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc512x_valid_monitor_port;
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+	"anon,charon",
 	"intercontrol,digsy-mtc",
 	"manroland,mucmc52",
 	"manroland,uc101",
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_common.c linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_common.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_gpt.c linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,6 +67,7 @@
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 #include <asm/div64.h>
 #include <asm/mpc52xx.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/82xx/km82xx.c linux-libre-3.2-gnu1/arch/powerpc/platforms/82xx/km82xx.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/82xx/km82xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/82xx/km82xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,9 @@ struct cpm_pin {
 };
 
 static __initdata struct cpm_pin km82xx_pins[] = {
+	/* SMC1 */
+	{2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
 
 	/* SMC2 */
 	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
@@ -137,6 +140,7 @@ static void __init init_ioports(void)
 	}
 
 	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+	cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
 	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
 	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
 	cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -114,18 +114,21 @@ config KMETER1
 
 endif
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC831x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 # used for math-emu
 config PPC_MPC832x
 	bool
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC834x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC837x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/reboot.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
@@ -30,6 +32,7 @@
  */
 #define MCU_REG_CTRL	0x20
 #define MCU_CTRL_POFF	0x40
+#define MCU_CTRL_BTN	0x80
 
 #define MCU_NUM_GPIO	2
 
@@ -42,13 +45,55 @@ struct mcu {
 
 static struct mcu *glob_mcu;
 
+struct task_struct *shutdown_thread;
+static int shutdown_thread_fn(void *data)
+{
+	int ret;
+	struct mcu *mcu = glob_mcu;
+
+	while (!kthread_should_stop()) {
+		ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+		if (ret < 0)
+			pr_err("MCU status reg read failed.\n");
+		mcu->reg_ctrl = ret;
+
+
+		if (mcu->reg_ctrl & MCU_CTRL_BTN) {
+			i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
+						  mcu->reg_ctrl & ~MCU_CTRL_BTN);
+
+			ctrl_alt_del();
+		}
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
+
+	return 0;
+}
+
+static ssize_t show_status(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct mcu *mcu = glob_mcu;
+
+	ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+	if (ret < 0)
+		return -ENODEV;
+	mcu->reg_ctrl = ret;
+
+	return sprintf(buf, "%02x\n", ret);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
 static void mcu_power_off(void)
 {
 	struct mcu *mcu = glob_mcu;
 
 	pr_info("Sending power-off request to the MCU...\n");
 	mutex_lock(&mcu->lock);
-	i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+	i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
 				  mcu->reg_ctrl | MCU_CTRL_POFF);
 	mutex_unlock(&mcu->lock);
 }
@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2
 		dev_info(&client->dev, "will provide power-off service\n");
 	}
 
+	if (device_create_file(&client->dev, &dev_attr_status))
+		dev_err(&client->dev,
+			"couldn't create device file for status\n");
+
+	shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
+				      "mcu-i2c-shdn");
+
 	return 0;
 err:
 	kfree(mcu);
@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i
 	struct mcu *mcu = i2c_get_clientdata(client);
 	int ret;
 
+	kthread_stop(shutdown_thread);
+
+	device_remove_file(&client->dev, &dev_attr_status);
+
 	if (glob_mcu == mcu) {
 		ppc_md.power_off = NULL;
 		glob_mcu = NULL;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/suspend.c linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/suspend.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/83xx/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/83xx/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -80,7 +80,7 @@ config P1010_RDB
 config P1022_DS
 	bool "Freescale P1022 DS"
 	select DEFAULT_UIMAGE
-	select CONFIG_PHYS_64BIT	# The DTS has 36-bit addresses
+	select PHYS_64BIT	# The DTS has 36-bit addresses
 	select SWIOTLB
 	help
 	  This option enables support for the Freescale P1022DS reference board.
@@ -171,17 +171,18 @@ config SBC8560
 	help
 	  This option enables support for the Wind River SBC8560 board
 
-config P2040_RDB
-	bool "Freescale P2040 RDB"
+config P2041_RDB
+	bool "Freescale P2041 RDB"
 	select DEFAULT_UIMAGE
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
-	  This option enables support for the P2040 RDB board
+	  This option enables support for the P2041 RDB board
 
 config P3041_DS
 	bool "Freescale P3041 DS"
@@ -189,19 +190,33 @@ config P3041_DS
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
 	  This option enables support for the P3041 DS board
 
+config P3060_QDS
+	bool "Freescale P3060 QDS"
+	select DEFAULT_UIMAGE
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select GPIO_MPC8XXX
+	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
+	help
+	  This option enables support for the P3060 QDS board
+
 config P4080_DS
 	bool "Freescale P4080 DS"
 	select DEFAULT_UIMAGE
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
@@ -216,7 +231,8 @@ config P5020_DS
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,9 @@ obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
-obj-$(CONFIG_P2040_RDB)   += p2040_rdb.o corenet_ds.o
+obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
+obj-$(CONFIG_P3060_QDS)   += p3060_qds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/mpc85xx_cds.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/mpc85xx_cds.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p1022_ds.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p1022_ds.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p1022_ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p1022_ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,8 +93,8 @@
  * The Area Descriptor is a 32-bit value that determine which bits in each
  * pixel are to be used for each color.
  */
-static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
-	int monitor_port)
+static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+				    unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_fo
  * On some boards, the gamma table for some ports may need to be modified.
  * This is not the case on the P1022DS, so we do nothing.
 */
-static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+				    char *gamma_table_base)
 {
 }
 
@@ -126,38 +127,43 @@ static void p1022ds_set_gamma_table(int
  * p1022ds_set_monitor_port: switch the output to a different monitor port
  *
  */
-static void p1022ds_set_monitor_port(int monitor_port)
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-	struct device_node *pixis_node;
+	struct device_node *np;
 	void __iomem *pixis;
 	u8 __iomem *brdcfg1;
 
-	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
-	if (!pixis_node) {
+	np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
+	if (!np)
+		/* older device trees used "fsl,p1022ds-pixis" */
+		np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
+	if (!np) {
 		pr_err("p1022ds: missing ngPIXIS node\n");
 		return;
 	}
 
-	pixis = of_iomap(pixis_node, 0);
+	pixis = of_iomap(np, 0);
 	if (!pixis) {
 		pr_err("p1022ds: could not map ngPIXIS registers\n");
 		return;
 	}
 	brdcfg1 = pixis + 9;	/* BRDCFG1 is at offset 9 in the ngPIXIS */
 
-	switch (monitor_port) {
-	case 0: /* DVI */
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DVI port, disable the DFP and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DVIEN);
 		break;
-	case 1: /* Single link LVDS */
+	case FSL_DIU_PORT_LVDS:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DFP port, disable the DVI and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DFPEN);
 		break;
 	default:
-		pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+		pr_err("p1022ds: unsupported monitor port %i\n", port);
 	}
 
 	iounmap(pixis);
@@ -214,23 +220,18 @@ void p1022ds_set_pixel_clock(unsigned in
 }
 
 /**
- * p1022ds_show_monitor_port: show the current monitor
- *
- * This function returns a string indicating whether the current monitor is
- * set to DVI or LVDS.
- */
-ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
-{
-	return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
-		monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
-}
-
-/**
- * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ * p1022ds_valid_monitor_port: set the monitor port for sysfs
  */
-int p1022ds_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 2 ? val : 0;
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+	case FSL_DIU_PORT_LVDS:
+		return port;
+	default:
+		return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+	}
 }
 
 #endif
@@ -305,8 +306,7 @@ static void __init p1022_ds_setup_arch(v
 	diu_ops.set_gamma_table		= p1022ds_set_gamma_table;
 	diu_ops.set_monitor_port	= p1022ds_set_monitor_port;
 	diu_ops.set_pixel_clock		= p1022ds_set_pixel_clock;
-	diu_ops.show_monitor_port	= p1022ds_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= p1022ds_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= p1022ds_valid_monitor_port;
 #endif
 
 #ifdef CONFIG_SMP
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p2040_rdb.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p2040_rdb.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p2040_rdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p2040_rdb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * P2040 RDB Setup
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/system.h>
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p2040_rdb_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p2040_rdb) {
-	.name			= "P2040 RDB",
-	.probe			= p2040_rdb_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-	.power_save		= e500_idle,
-};
-
-machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p2041_rdb.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p2041_rdb.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p2041_rdb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p2041_rdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * P2041 RDB Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p2041_rdb_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p2041_rdb) {
+	.name			= "P2041 RDB",
+	.probe			= p2041_rdb_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.power_save		= e500_idle,
+};
+
+machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p3060_qds.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p3060_qds.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/p3060_qds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/p3060_qds.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,77 @@
+/*
+ * P3060 QDS Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3060_qds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P3060QDS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		 */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p3060_qds) {
+	.name			= "P3060 QDS",
+	.probe			= p3060_qds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.power_save		= e500_idle,
+};
+
+machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/sbc8548.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/sbc8548.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/sbc8548.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/sbc8548.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/sbc8560.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/sbc8560.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/sbc8560.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/sbc8560.c	2012-01-04 18:55:44.000000000 -0500
@@ -283,7 +283,7 @@ static int __init sbc8560_bdrstcr_init(v
 
 	of_address_to_resource(np, 0, &res);
 
-	printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
+	printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res);
 
 	brstcr = ioremap(res.start, resource_size(&res));
 	if(!brstcr)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/85xx/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/85xx/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,10 +48,11 @@ smp_85xx_kick_cpu(int nr)
 	const u64 *cpu_rel_addr;
 	__iomem u32 *bptr_vaddr;
 	struct device_node *np;
-	int n = 0;
+	int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
 	int ioremappable;
 
-	WARN_ON (nr < 0 || nr >= NR_CPUS);
+	WARN_ON(nr < 0 || nr >= NR_CPUS);
+	WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
 
 	pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
@@ -79,7 +80,7 @@ smp_85xx_kick_cpu(int nr)
 
 	local_irq_save(flags);
 
-	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
 	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -88,7 +89,7 @@ smp_85xx_kick_cpu(int nr)
 				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 
 	/* Wait a bit for the CPU to ack. */
-	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
+	while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
 		mdelay(1);
 #else
 	smp_generic_kick_cpu(nr);
@@ -206,7 +207,7 @@ static void mpc85xx_smp_machine_kexec(st
 	if ( !timeout )
 		printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-	for (i = 0; i < num_cpus; i++)
+	for_each_online_cpu(i)
 	{
 		if ( i == smp_processor_id() ) continue;
 		mpic_reset_core(i);
@@ -243,6 +244,7 @@ void __init mpc85xx_smp_init(void)
 		 * If left NULL, .message_pass defaults to
 		 * smp_muxed_ipi_message_pass
 		 */
+		smp_85xx_ops.message_pass = NULL;
 		smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
 	}
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/gef_gpio.c linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/gef_gpio.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/gef_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/gef_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define GEF_GPIO_DIRECT		0x00
 #define GEF_GPIO_IN		0x04
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@ menuconfig PPC_86xx
 	depends on 6xx
 	select FSL_SOC
 	select ALTIVEC
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  The Freescale E600 SoCs have 74xx cores.
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/mpc8610_hpcd.c linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mp
 	(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
 	(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
 
-unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
-						int monitor_port)
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+				 unsigned int bits_per_pixel)
 {
-	static const unsigned long pixelformat[][3] = {
+	static const u32 pixelformat[][3] = {
 		{
 			MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
 			MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_forma
 	unsigned int arch_monitor;
 
 	/* The DVI port is mis-wired on revision 1 of this board. */
-	arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
+	arch_monitor =
+		((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
 
 	switch (bits_per_pixel) {
 	case 32:
@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_forma
 	}
 }
 
-void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+				 char *gamma_table_base)
 {
 	int i;
-	if (monitor_port == 2) {		/* dual link LVDS */
+	if (port == FSL_DIU_PORT_DLVDS) {
 		for (i = 0; i < 256*3; i++)
 			gamma_table_base[i] = (gamma_table_base[i] << 2) |
 					 ((gamma_table_base[i] >> 6) & 0x03);
@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int mon
 #define PX_BRDCFG0_DLINK	(1 << 4)
 #define PX_BRDCFG0_DIU_MASK	(PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
 
-void mpc8610hpcd_set_monitor_port(int monitor_port)
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-	static const u8 bdcfg[] = {
-		PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
-		PX_BRDCFG0_DLINK,
-		0,
-	};
-
-	if (monitor_port < 3)
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
 		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
-			     bdcfg[monitor_port]);
+			     PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_LVDS:
+		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+			     PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_DLVDS:
+		clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+		break;
+	}
 }
 
 /**
@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigne
 	iounmap(guts);
 }
 
-ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE,
-			"%c0 - DVI\n"
-			"%c1 - Single link LVDS\n"
-			"%c2 - Dual link LVDS\n",
-			monitor_port == 0 ? '*' : ' ',
-			monitor_port == 1 ? '*' : ' ',
-			monitor_port == 2 ? '*' : ' ');
-}
-
-int mpc8610hpcd_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 3 ? val : 0;
+	return port;
 }
 
 #endif
@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_ar
 	diu_ops.set_gamma_table		= mpc8610hpcd_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc8610hpcd_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc8610hpcd_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc8610hpcd_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc8610hpcd_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc8610hpcd_valid_monitor_port;
 #endif
 
 	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/8xx/tqm8xx_setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/8xx/tqm8xx_setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/axon_msi.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/axon_msi.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/axon_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/axon_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/of_platform.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/rtc.h>
@@ -230,7 +230,7 @@ static int __init beat_register_event(vo
 		}
 		ev->virq = virq;
 
-		rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+		rc = request_irq(virq, ev->handler, 0,
 				      ev->typecode, NULL);
 		if (rc != 0) {
 			printk(KERN_ERR "Beat: failed to request virtual IRQ"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat_spu_priv1.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat_spu_priv1.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat_spu_priv1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat_spu_priv1.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <linux/module.h>
-
 #include <asm/types.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat_wrapper.h linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat_wrapper.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/beat_wrapper.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/beat_wrapper.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 #ifndef BEAT_HCALL
+#include <linux/string.h>
 #include "beat_syscall.h"
 
 /* defined in hvCall.S */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/module.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
+#include <linux/module.h>
 #include <linux/of_platform.h>
 
 #include <asm/processor.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_powerbutton.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_powerbutton.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_powerbutton.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_powerbutton.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/input.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <asm/pmi.h>
 #include <asm/prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_regs.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_regs.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cbe_regs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cbe_regs.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <linux/percpu.h>
 #include <linux/types.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/celleb_scc_pciex.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/celleb_scc_pciex.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2012-01-04 18:55:44.000000000 -0500
@@ -514,7 +514,7 @@ static __init int celleb_setup_pciex(str
 	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 				     oirq.size);
 	if (request_irq(virq, pciex_handle_internal_irq,
-			IRQF_DISABLED, "pciex", (void *)phb)) {
+			0, "pciex", (void *)phb)) {
 		pr_err("PCIEXC:Failed to request irq\n");
 		goto error;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/celleb_setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/celleb_setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/celleb_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/celleb_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/cpu.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/atomic.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/interrupt.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/interrupt.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/iommu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/iommu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -412,8 +412,7 @@ static void cell_iommu_enable_hardware(s
 			IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT));
 	BUG_ON(virq == NO_IRQ);
 
-	ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED,
-			iommu->name, iommu);
+	ret = request_irq(virq, ioc_interrupt, 0, iommu->name, iommu);
 	BUG_ON(ret);
 
 	/* set the IOC segment table origin register (and turn on the iommu) */
@@ -1159,6 +1158,26 @@ static int __init setup_iommu_fixed(char
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+	struct dma_map_ops *dma_ops;
+
+	if (!dev->dma_mask)
+		return 0;
+
+	if (!iommu_fixed_disabled &&
+			cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+		return DMA_BIT_MASK(64);
+
+	dma_ops = get_dma_ops(dev);
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
+
+	WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
+
+	return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
 	struct device_node *np;
@@ -1175,6 +1194,7 @@ static int __init cell_iommu_init(void)
 
 	/* Setup various ppc_md. callbacks */
 	ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+	ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
 	ppc_md.tce_build = tce_build_cell;
 	ppc_md.tce_free = tce_free_cell;
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -17,10 +17,10 @@ config PPC_CELL_NATIVE
 	select PPC_CELL_COMMON
 	select MPIC
 	select PPC_IO_WORKAROUNDS
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII #test only
-	select IBM_NEW_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII #test only
+	select IBM_EMAC_TAH  #test only
 	default n
 
 config PPC_IBM_CELL_BLADE
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/pmu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/pmu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/irq_regs.h>
 #include <asm/machdep.h>
@@ -391,7 +392,7 @@ static int __init cbe_init_pm_irq(void)
 		}
 
 		rc = request_irq(irq, cbe_pm_irq,
-				 IRQF_DISABLED, "cbe-pmu-0", NULL);
+				 0, "cbe-pmu-0", NULL);
 		if (rc) {
 			printk("ERROR: Request for irq on node %d failed\n",
 			       node);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/qpace_setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/qpace_setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/qpace_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/qpace_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/console.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
+#include <linux/export.h>
 #include <linux/unistd.h>
 #include <linux/user.h>
 #include <linux/reboot.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_base.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_base.c	2012-01-04 18:55:44.000000000 -0500
@@ -442,8 +442,7 @@ static int spu_request_irqs(struct spu *
 		snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",
 			 spu->number);
 		ret = request_irq(spu->irqs[0], spu_irq_class_0,
-				  IRQF_DISABLED,
-				  spu->irq_c0, spu);
+				  0, spu->irq_c0, spu);
 		if (ret)
 			goto bail0;
 	}
@@ -451,8 +450,7 @@ static int spu_request_irqs(struct spu *
 		snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",
 			 spu->number);
 		ret = request_irq(spu->irqs[1], spu_irq_class_1,
-				  IRQF_DISABLED,
-				  spu->irq_c1, spu);
+				  0, spu->irq_c1, spu);
 		if (ret)
 			goto bail1;
 	}
@@ -460,8 +458,7 @@ static int spu_request_irqs(struct spu *
 		snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",
 			 spu->number);
 		ret = request_irq(spu->irqs[2], spu_irq_class_2,
-				  IRQF_DISABLED,
-				  spu->irq_c2, spu);
+				  0, spu->irq_c2, spu);
 		if (ret)
 			goto bail2;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_callbacks.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_callbacks.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_callbacks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_callbacks.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 #undef DEBUG
 
 #include <linux/kallsyms.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/syscalls.h>
 
 #include <asm/spu.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_fault.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_fault.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/backing_ops.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/backing_ops.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/backing_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/backing_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/context.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/context.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/context.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/context.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,9 +22,9 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/coredump.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/coredump.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/coredump.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/coredump.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,6 @@
 #include <linux/fs.h>
 #include <linux/gfp.h>
 #include <linux/list.h>
-#include <linux/module.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/fault.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/fault.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/file.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/file.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/file.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/file.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
 
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/hw_ops.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/hw_ops.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/hw_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/hw_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/sched.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/sched.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/sched.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/sched.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/switch.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/switch.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/switch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/switch.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/hardirq.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/syscalls.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/syscalls.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spufs/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spufs/syscalls.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_manage.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_manage.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_manage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_manage.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/ptrace.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_notify.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_notify.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_notify.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_notify.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,8 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/notifier.h>
 #include <asm/spu.h>
 #include "spufs/spufs.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_priv1_mmio.c linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_priv1_mmio.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/cell/spu_priv1_mmio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/cell/spu_priv1_mmio.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/module.h>
 #include <linux/ptrace.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/holly.c linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/holly.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/holly.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/holly.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 #include <linux/of_platform.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -87,10 +87,6 @@ config MV64X60
 config MPC10X_OPENPIC
 	bool
 
-config MPC10X_STORE_GATHERING
-	bool "Enable MPC10x store gathering"
-	depends on MPC10X_BRIDGE
-
 config GAMECUBE_COMMON
 	bool
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/kdev_t.h>
 #include <linux/console.h>
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/storcenter.c linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/storcenter.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/embedded6xx/storcenter.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/embedded6xx/storcenter.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ static void __init storcenter_setup_arch
 }
 
 /*
- * Interrupt setup and service.  Interrrupts on the turbostation come
+ * Interrupt setup and service.  Interrupts on the turbostation come
  * from the four PCI slots plus onboard 8241 devices: I2C, DUART.
  */
 static void __init storcenter_init_IRQ(void)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/hvlpconfig.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/hvlpconfig.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/hvlpconfig.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/hvlpconfig.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/iseries/hv_lp_config.h>
 #include "it_lp_naca.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/iommu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/iommu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include <asm/iommu.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/ksyms.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/ksyms.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *      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/export.h>
 
 #include <asm/hw_irq.h>
 #include <asm/iseries/hv_call_sc.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/lpardata.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/lpardata.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/lpardata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/lpardata.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  */
 #include <linux/types.h>
 #include <linux/threads.h>
-#include <linux/module.h>
 #include <linux/bitops.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/lpevents.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/lpevents.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/lpevents.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/lpevents.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/system.h>
 #include <asm/paca.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/mf.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/mf.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/mf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/mf.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/proc_fs.h>
 #include <linux/dma-mapping.h>
 #include <linux/bcd.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/pci.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/pci.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/of.h>
 #include <linux/ratelimit.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/param.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/seq_file.h>
 #include <linux/kdev_t.h>
 #include <linux/kexec.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/vio.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/vio.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/firmware.h>
 #include <asm/vio.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/viopath.c linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/viopath.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/iseries/viopath.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/iseries/viopath.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 menu "Platform support"
 
+source "arch/powerpc/platforms/powernv/Kconfig"
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
@@ -333,16 +334,6 @@ config OF_RTC
 
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
-config MPC8xxx_GPIO
-	bool "MPC512x/MPC8xxx GPIO support"
-	depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
-		   FSL_SOC_BOOKE || PPC_86xx
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	help
-	  Say Y here if you're going to use hardware that connects to the
-	  MPC512x/831x/834x/837x/8572/8610 GPIOs.
-
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
 	depends on PPC
@@ -355,8 +346,8 @@ config SIMPLE_GPIO
 	  on-board peripherals.
 
 config MCU_MPC8349EMITX
-	tristate "MPC8349E-mITX MCU driver"
-	depends on I2C && PPC_83xx
+	bool "MPC8349E-mITX MCU driver"
+	depends on I2C=y && PPC_83xx
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/Kconfig.cputype linux-libre-3.2-gnu1/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/Kconfig.cputype	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/Kconfig.cputype	2012-01-04 18:55:44.000000000 -0500
@@ -69,6 +69,7 @@ config PPC_BOOK3S_64
 	bool "Server processors"
 	select PPC_FPU
 	select PPC_HAVE_PMU_SUPPORT
+	select SYS_SUPPORTS_HUGETLBFS
 
 config PPC_BOOK3E_64
 	bool "Embedded processors"
@@ -173,6 +174,7 @@ config BOOKE
 config FSL_BOOKE
 	bool
 	depends on (E200 || E500) && PPC32
+	select SYS_SUPPORTS_HUGETLBFS if PHYS_64BIT
 	default y
 
 # this is for common code between PPC32 & PPC64 FSL BOOKE
@@ -282,21 +284,13 @@ config PPC_MMU_NOHASH
 	def_bool y
 	depends on !PPC_STD_MMU
 
-config PPC_MMU_NOHASH_32
-	def_bool y
-	depends on PPC_MMU_NOHASH && PPC32
-
-config PPC_MMU_NOHASH_64
-	def_bool y
-	depends on PPC_MMU_NOHASH && PPC64
-
 config PPC_BOOK3E_MMU
 	def_bool y
 	depends on FSL_BOOKE || PPC_BOOK3E
 
 config PPC_MM_SLICES
 	bool
-	default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
+	default y if (PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES)
 	default n
 
 config VIRT_CPU_ACCOUNTING
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@ obj-$(CONFIG_PPC_82xx)		+= 82xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_FSL_SOC_BOOKE)	+= 85xx/
 obj-$(CONFIG_PPC_86xx)		+= 86xx/
+obj-$(CONFIG_PPC_POWERNV)	+= powernv/
 obj-$(CONFIG_PPC_PSERIES)	+= pseries/
 obj-$(CONFIG_PPC_ISERIES)	+= iseries/
 obj-$(CONFIG_PPC_MAPLE)		+= maple/
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/maple/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/maple/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/maple/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/maple/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/cpufreq.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/cpufreq.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/timer.h>
+#include <linux/module.h>
 
 #include <asm/hw_irq.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/dma_lib.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/dma_lib.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/dma_lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/dma_lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,10 +19,11 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/sched.h>
 
 #include <asm/pasemi_dma.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pasemi/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pasemi/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <linux/gfp.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/backlight.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/backlight.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/atomic.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/backlight.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/feature.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/feature.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/feature.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/feature.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/ioport.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/sections.h>
 #include <asm/errno.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/low_i2c.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/low_i2c.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/low_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/low_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/delay.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/nvram.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/nvram.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  *
  *  Todo: - add support for the OF persistent properties
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/pic.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/pic.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <linux/module.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -273,7 +272,6 @@ static struct irqaction xmon_action = {
 
 static struct irqaction gatwick_cascade_action = {
 	.handler	= gatwick_action,
-	.flags		= IRQF_DISABLED,
 	.name		= "cascade",
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
+#include <linux/export.h>
 #include <linux/user.h>
 #include <linux/tty.h>
 #include <linux/string.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powermac/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powermac/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@ static int psurge_secondary_ipi_init(voi
 
 	if (psurge_secondary_virq)
 		rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
-			IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+			IRQF_PERCPU, "IPI", NULL);
 
 	if (rc)
 		pr_err("Failed to setup secondary cpu IPI\n");
@@ -408,7 +408,7 @@ static int __init smp_psurge_kick_cpu(in
 
 static struct irqaction psurge_irqaction = {
 	.handler = psurge_ipi_intr,
-	.flags = IRQF_DISABLED|IRQF_PERCPU,
+	.flags = IRQF_PERCPU,
 	.name = "primary IPI",
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+config PPC_POWERNV
+	depends on PPC64 && PPC_BOOK3S
+	bool "IBM PowerNV (Non-Virtualized) platform support"
+	select PPC_NATIVE
+	select PPC_XICS
+	select PPC_ICP_NATIVE
+	select PPC_P7_NAP
+	select PPC_PCI_CHOICE if EMBEDDED
+	default y
+
+config PPC_POWERNV_RTAS
+	depends on PPC_POWERNV
+	bool "Support for RTAS based PowerNV platforms such as BML"
+	default y
+	select PPC_ICS_RTAS
+	select PPC_RTAS
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+obj-y			+= setup.o opal-takeover.o opal-wrappers.o opal.o
+obj-y			+= opal-rtc.o opal-nvram.o
+
+obj-$(CONFIG_SMP)	+= smp.o
+obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,322 @@
+/*
+ * PowerNV OPAL high level interfaces
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+#include "powernv.h"
+
+struct opal {
+	u64 base;
+	u64 entry;
+} opal;
+
+static struct device_node *opal_node;
+static DEFINE_SPINLOCK(opal_write_lock);
+extern u64 opal_mc_secondary_handler[];
+
+int __init early_init_dt_scan_opal(unsigned long node,
+				   const char *uname, int depth, void *data)
+{
+	const void *basep, *entryp;
+	unsigned long basesz, entrysz;
+	u64 glue;
+
+	if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+		return 0;
+
+	basep  = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
+	entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+
+	if (!basep || !entryp)
+		return 1;
+
+	opal.base = of_read_number(basep, basesz/4);
+	opal.entry = of_read_number(entryp, entrysz/4);
+
+	pr_debug("OPAL Base  = 0x%llx (basep=%p basesz=%ld)\n",
+		 opal.base, basep, basesz);
+	pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
+		 opal.entry, entryp, entrysz);
+
+	powerpc_firmware_features |= FW_FEATURE_OPAL;
+	if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+		powerpc_firmware_features |= FW_FEATURE_OPALv2;
+		printk("OPAL V2 detected !\n");
+	} else {
+		printk("OPAL V1 detected !\n");
+	}
+
+	/* Hookup some exception handlers. We use the fwnmi area at 0x7000
+	 * to provide the glue space to OPAL
+	 */
+	glue = 0x7000;
+	opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
+					__pa(opal_mc_secondary_handler[0]),
+					glue);
+	glue += 128;
+	opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+					0, glue);
+	glue += 128;
+	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+
+	return 1;
+}
+
+int opal_get_chars(uint32_t vtermno, char *buf, int count)
+{
+	s64 len, rc;
+	u64 evt;
+
+	if (!opal.entry)
+		return -ENODEV;
+	opal_poll_events(&evt);
+	if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+		return 0;
+	len = count;
+	rc = opal_console_read(vtermno, &len, buf);
+	if (rc == OPAL_SUCCESS)
+		return len;
+	return 0;
+}
+
+int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
+{
+	int written = 0;
+	s64 len, rc;
+	unsigned long flags;
+	u64 evt;
+
+	if (!opal.entry)
+		return -ENODEV;
+
+	/* We want put_chars to be atomic to avoid mangling of hvsi
+	 * packets. To do that, we first test for room and return
+	 * -EAGAIN if there isn't enough.
+	 *
+	 * Unfortunately, opal_console_write_buffer_space() doesn't
+	 * appear to work on opal v1, so we just assume there is
+	 * enough room and be done with it
+	 */
+	spin_lock_irqsave(&opal_write_lock, flags);
+	if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+		rc = opal_console_write_buffer_space(vtermno, &len);
+		if (rc || len < total_len) {
+			spin_unlock_irqrestore(&opal_write_lock, flags);
+			/* Closed -> drop characters */
+			if (rc)
+				return total_len;
+			opal_poll_events(&evt);
+			return -EAGAIN;
+		}
+	}
+
+	/* We still try to handle partial completions, though they
+	 * should no longer happen.
+	 */
+	rc = OPAL_BUSY;
+	while(total_len > 0 && (rc == OPAL_BUSY ||
+				rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
+		len = total_len;
+		rc = opal_console_write(vtermno, &len, data);
+		if (rc == OPAL_SUCCESS) {
+			total_len -= len;
+			data += len;
+			written += len;
+		}
+		/* This is a bit nasty but we need that for the console to
+		 * flush when there aren't any interrupts. We will clean
+		 * things a bit later to limit that to synchronous path
+		 * such as the kernel console and xmon/udbg
+		 */
+		do
+			opal_poll_events(&evt);
+		while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+	}
+	spin_unlock_irqrestore(&opal_write_lock, flags);
+	return written;
+}
+
+int opal_machine_check(struct pt_regs *regs)
+{
+	struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
+	struct opal_machine_check_event evt;
+	const char *level, *sevstr, *subtype;
+	static const char *opal_mc_ue_types[] = {
+		"Indeterminate",
+		"Instruction fetch",
+		"Page table walk ifetch",
+		"Load/Store",
+		"Page table walk Load/Store",
+	};
+	static const char *opal_mc_slb_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+	static const char *opal_mc_erat_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+	static const char *opal_mc_tlb_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+
+	/* Copy the event structure and release the original */
+	evt = *opal_evt;
+	opal_evt->in_use = 0;
+
+	/* Print things out */
+	if (evt.version != OpalMCE_V1) {
+		pr_err("Machine Check Exception, Unknown event version %d !\n",
+		       evt.version);
+		return 0;
+	}
+	switch(evt.severity) {
+	case OpalMCE_SEV_NO_ERROR:
+		level = KERN_INFO;
+		sevstr = "Harmless";
+		break;
+	case OpalMCE_SEV_WARNING:
+		level = KERN_WARNING;
+		sevstr = "";
+		break;
+	case OpalMCE_SEV_ERROR_SYNC:
+		level = KERN_ERR;
+		sevstr = "Severe";
+		break;
+	case OpalMCE_SEV_FATAL:
+	default:
+		level = KERN_ERR;
+		sevstr = "Fatal";
+		break;
+	}
+
+	printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+	       evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
+	       "Recovered" : "[Not recovered");
+	printk("%s  Initiator: %s\n", level,
+	       evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
+	switch(evt.error_type) {
+	case OpalMCE_ERROR_TYPE_UE:
+		subtype = evt.u.ue_error.ue_error_type <
+			ARRAY_SIZE(opal_mc_ue_types) ?
+			opal_mc_ue_types[evt.u.ue_error.ue_error_type]
+			: "Unknown";
+		printk("%s  Error type: UE [%s]\n", level, subtype);
+		if (evt.u.ue_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.ue_error.effective_address);
+		if (evt.u.ue_error.physical_address_provided)
+			printk("%s      Physial address: %016llx\n",
+			       level, evt.u.ue_error.physical_address);
+		break;
+	case OpalMCE_ERROR_TYPE_SLB:
+		subtype = evt.u.slb_error.slb_error_type <
+			ARRAY_SIZE(opal_mc_slb_types) ?
+			opal_mc_slb_types[evt.u.slb_error.slb_error_type]
+			: "Unknown";
+		printk("%s  Error type: SLB [%s]\n", level, subtype);
+		if (evt.u.slb_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.slb_error.effective_address);
+		break;
+	case OpalMCE_ERROR_TYPE_ERAT:
+		subtype = evt.u.erat_error.erat_error_type <
+			ARRAY_SIZE(opal_mc_erat_types) ?
+			opal_mc_erat_types[evt.u.erat_error.erat_error_type]
+			: "Unknown";
+		printk("%s  Error type: ERAT [%s]\n", level, subtype);
+		if (evt.u.erat_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.erat_error.effective_address);
+		break;
+	case OpalMCE_ERROR_TYPE_TLB:
+		subtype = evt.u.tlb_error.tlb_error_type <
+			ARRAY_SIZE(opal_mc_tlb_types) ?
+			opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
+			: "Unknown";
+		printk("%s  Error type: TLB [%s]\n", level, subtype);
+		if (evt.u.tlb_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.tlb_error.effective_address);
+		break;
+	default:
+	case OpalMCE_ERROR_TYPE_UNKNOWN:
+		printk("%s  Error type: Unknown\n", level);
+		break;
+	}
+	return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+}
+
+static irqreturn_t opal_interrupt(int irq, void *data)
+{
+	uint64_t events;
+
+	opal_handle_interrupt(virq_to_hw(irq), &events);
+
+	/* XXX TODO: Do something with the events */
+
+	return IRQ_HANDLED;
+}
+
+static int __init opal_init(void)
+{
+	struct device_node *np, *consoles;
+	const u32 *irqs;
+	int rc, i, irqlen;
+
+	opal_node = of_find_node_by_path("/ibm,opal");
+	if (!opal_node) {
+		pr_warn("opal: Node not found\n");
+		return -ENODEV;
+	}
+	if (firmware_has_feature(FW_FEATURE_OPALv2))
+		consoles = of_find_node_by_path("/ibm,opal/consoles");
+	else
+		consoles = of_node_get(opal_node);
+
+	/* Register serial ports */
+	for_each_child_of_node(consoles, np) {
+		if (strcmp(np->name, "serial"))
+			continue;
+		of_platform_device_create(np, NULL, NULL);
+	}
+	of_node_put(consoles);
+
+	/* Find all OPAL interrupts and request them */
+	irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
+	pr_debug("opal: Found %d interrupts reserved for OPAL\n",
+		 irqs ? (irqlen / 4) : 0);
+	for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
+		unsigned int hwirq = be32_to_cpup(irqs);
+		unsigned int irq = irq_create_mapping(NULL, hwirq);
+		if (irq == NO_IRQ) {
+			pr_warning("opal: Failed to map irq 0x%x\n", hwirq);
+			continue;
+		}
+		rc = request_irq(irq, opal_interrupt, 0, "opal", NULL);
+		if (rc)
+			pr_warning("opal: Error %d requesting irq %d"
+				   " (0x%x)\n", rc, irq, hwirq);
+	}
+	return 0;
+}
+subsys_initcall(opal_init);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-nvram.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-nvram.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-nvram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * PowerNV nvram code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+
+#include <asm/opal.h>
+#include <asm/machdep.h>
+
+static unsigned int nvram_size;
+
+static ssize_t opal_nvram_size(void)
+{
+	return nvram_size;
+}
+
+static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
+{
+	s64 rc;
+	int off;
+
+	if (*index >= nvram_size)
+		return 0;
+	off = *index;
+	if ((off + count) > nvram_size)
+		count = nvram_size - off;
+	rc = opal_read_nvram(__pa(buf), count, off);
+	if (rc != OPAL_SUCCESS)
+		return -EIO;
+	*index += count;
+	return count;
+}
+
+static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
+{
+	s64 rc = OPAL_BUSY;
+	int off;
+
+	if (*index >= nvram_size)
+		return 0;
+	off = *index;
+	if ((off + count) > nvram_size)
+		count = nvram_size - off;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_write_nvram(__pa(buf), count, off);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+	}
+	*index += count;
+	return count;
+}
+
+void __init opal_nvram_init(void)
+{
+	struct device_node *np;
+	const u32 *nbytes_p;
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
+	if (np == NULL)
+		return;
+
+	nbytes_p = of_get_property(np, "#bytes", NULL);
+	if (!nbytes_p) {
+		of_node_put(np);
+		return;
+	}
+	nvram_size = *nbytes_p;
+
+	printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size);
+	of_node_put(np);
+
+	ppc_md.nvram_read = opal_nvram_read;
+	ppc_md.nvram_write = opal_nvram_write;
+	ppc_md.nvram_size = opal_nvram_size;
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-rtc.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-rtc.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-rtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+ * PowerNV Real Time Clock.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
+{
+	tm->tm_year	= ((bcd2bin(y_m_d >> 24) * 100) +
+			   bcd2bin((y_m_d >> 16) & 0xff)) - 1900;
+	tm->tm_mon	= bcd2bin((y_m_d >> 8) & 0xff) - 1;
+	tm->tm_mday	= bcd2bin(y_m_d & 0xff);
+	tm->tm_hour	= bcd2bin((h_m_s_ms >> 56) & 0xff);
+	tm->tm_min	= bcd2bin((h_m_s_ms >> 48) & 0xff);
+	tm->tm_sec	= bcd2bin((h_m_s_ms >> 40) & 0xff);
+
+        GregorianDay(tm);
+}
+
+unsigned long __init opal_get_boot_time(void)
+{
+	struct rtc_time tm;
+	u32 y_m_d;
+	u64 h_m_s_ms;
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	if (rc != OPAL_SUCCESS)
+		return 0;
+	opal_to_tm(y_m_d, h_m_s_ms, &tm);
+	return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		      tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+void opal_get_rtc_time(struct rtc_time *tm)
+{
+	long rc = OPAL_BUSY;
+	u32 y_m_d;
+	u64 h_m_s_ms;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	if (rc != OPAL_SUCCESS)
+		return;
+	opal_to_tm(y_m_d, h_m_s_ms, tm);
+}
+
+int opal_set_rtc_time(struct rtc_time *tm)
+{
+	long rc = OPAL_BUSY;
+	u32 y_m_d = 0;
+	u64 h_m_s_ms = 0;
+
+	y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) / 100)) << 24;
+	y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) % 100)) << 16;
+	y_m_d |= ((u32)bin2bcd((tm->tm_mon + 1))) << 8;
+	y_m_d |= ((u32)bin2bcd(tm->tm_mday));
+
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_hour)) << 56;
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_min)) << 48;
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_sec)) << 40;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_write(y_m_d, h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	return rc == OPAL_SUCCESS ? 0 : -EIO;
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-takeover.S linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-takeover.S
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-takeover.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-takeover.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,140 @@
+/*
+ * PowerNV OPAL takeover assembly code, for use by prom_init.c
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+#define STK_PARAM(i)	(48 + ((i)-3)*8)
+
+#define H_HAL_TAKEOVER			0x5124
+#define H_HAL_TAKEOVER_QUERY_MAGIC	-1
+
+	.text
+_GLOBAL(opal_query_takeover)
+	mfcr	r0
+	stw	r0,8(r1)
+	std	r3,STK_PARAM(r3)(r1)
+	std	r4,STK_PARAM(r4)(r1)
+	li	r3,H_HAL_TAKEOVER
+	li	r4,H_HAL_TAKEOVER_QUERY_MAGIC
+	HVSC
+	ld	r10,STK_PARAM(r3)(r1)
+	std	r4,0(r10)
+	ld	r10,STK_PARAM(r4)(r1)
+	std	r5,0(r10)
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+	blr
+
+_GLOBAL(opal_do_takeover)
+	mfcr	r0
+	stw	r0,8(r1)
+	mflr	r0
+	std	r0,16(r1)
+	bl	__opal_do_takeover
+	ld	r0,16(r1)
+	mtlr	r0
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+	blr
+
+__opal_do_takeover:
+	ld	r4,0(r3)
+	ld	r5,0x8(r3)
+	ld	r6,0x10(r3)
+	ld	r7,0x18(r3)
+	ld	r8,0x20(r3)
+	ld	r9,0x28(r3)
+	ld	r10,0x30(r3)
+	ld	r11,0x38(r3)
+	li	r3,H_HAL_TAKEOVER
+	HVSC
+	blr
+
+	.globl opal_secondary_entry
+opal_secondary_entry:
+	mr	r31,r3
+	mfmsr	r11
+	li	r12,(MSR_SF | MSR_ISF)@highest
+	sldi	r12,r12,48
+	or	r11,r11,r12
+	mtmsrd	r11
+	isync
+	mfspr	r4,SPRN_PIR
+	std	r4,0(r3)
+1:	HMT_LOW
+	ld	r4,8(r3)
+	cmpli	cr0,r4,0
+	beq	1b
+	HMT_MEDIUM
+1:	addi	r3,r31,16
+	bl	__opal_do_takeover
+	b	1b
+
+_GLOBAL(opal_enter_rtas)
+	mflr	r0
+	std	r0,16(r1)
+        stdu	r1,-PROM_FRAME_SIZE(r1)	/* Save SP and create stack space */
+
+	/* Because PROM is running in 32b mode, it clobbers the high order half
+	 * of all registers that it saves.  We therefore save those registers
+	 * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
+	*/
+	SAVE_GPR(2, r1)
+	SAVE_GPR(13, r1)
+	SAVE_8GPRS(14, r1)
+	SAVE_10GPRS(22, r1)
+	mfcr	r10
+	mfmsr	r11
+	std	r10,_CCR(r1)
+	std	r11,_MSR(r1)
+
+	/* Get the PROM entrypoint */
+	mtlr	r5
+
+	/* Switch MSR to 32 bits mode
+	 */
+        li      r12,1
+        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+        andc    r11,r11,r12
+        li      r12,1
+        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+        andc    r11,r11,r12
+        mtmsrd  r11
+        isync
+
+	/* Enter RTAS here... */
+	blrl
+
+	/* Just make sure that r1 top 32 bits didn't get
+	 * corrupt by OF
+	 */
+	rldicl	r1,r1,0,32
+
+	/* Restore the MSR (back to 64 bits) */
+	ld	r0,_MSR(r1)
+	MTMSRD(r0)
+        isync
+
+	/* Restore other registers */
+	REST_GPR(2, r1)
+	REST_GPR(13, r1)
+	REST_8GPRS(14, r1)
+	REST_10GPRS(22, r1)
+	ld	r4,_CCR(r1)
+	mtcr	r4
+
+        addi	r1,r1,PROM_FRAME_SIZE
+	ld	r0,16(r1)
+	mtlr    r0
+	blr
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-wrappers.S
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/opal-wrappers.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/opal-wrappers.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * PowerNV OPAL API wrappers
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+/* TODO:
+ *
+ * - Trace irqs in/off (needs saving/restoring all args, argh...)
+ * - Get r11 feed up by Dave so I can have better register usage
+ */
+#define OPAL_CALL(name, token)		\
+ _GLOBAL(name);				\
+	mflr	r0;			\
+	mfcr	r12;			\
+	std	r0,16(r1);		\
+	std	r12,8(r1);		\
+	std	r1,PACAR1(r13);		\
+	li	r0,0;			\
+	mfmsr	r12;			\
+	ori	r0,r0,MSR_EE;		\
+	std	r12,PACASAVEDMSR(r13);	\
+	andc	r12,r12,r0;		\
+	mtmsrd	r12,1;			\
+	LOAD_REG_ADDR(r0,.opal_return);	\
+	mtlr	r0;			\
+	li	r0,MSR_DR|MSR_IR;	\
+	andc	r12,r12,r0;		\
+	li	r0,token;		\
+	mtspr	SPRN_HSRR1,r12;		\
+	LOAD_REG_ADDR(r11,opal);	\
+	ld	r12,8(r11);		\
+	ld	r2,0(r11);		\
+	mtspr	SPRN_HSRR0,r12;		\
+	hrfid
+
+_STATIC(opal_return)
+	ld	r2,PACATOC(r13);
+	ld	r4,8(r1);
+	ld	r5,16(r1);
+	ld	r6,PACASAVEDMSR(r13);
+	mtspr	SPRN_SRR0,r5;
+	mtspr	SPRN_SRR1,r6;
+	mtcr	r4;
+	rfid
+
+OPAL_CALL(opal_console_write,			OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read,			OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space,	OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_rtc_read,			OPAL_RTC_READ);
+OPAL_CALL(opal_rtc_write,			OPAL_RTC_WRITE);
+OPAL_CALL(opal_cec_power_down,			OPAL_CEC_POWER_DOWN);
+OPAL_CALL(opal_cec_reboot,			OPAL_CEC_REBOOT);
+OPAL_CALL(opal_read_nvram,			OPAL_READ_NVRAM);
+OPAL_CALL(opal_write_nvram,			OPAL_WRITE_NVRAM);
+OPAL_CALL(opal_handle_interrupt,		OPAL_HANDLE_INTERRUPT);
+OPAL_CALL(opal_poll_events,			OPAL_POLL_EVENTS);
+OPAL_CALL(opal_pci_set_hub_tce_memory,		OPAL_PCI_SET_HUB_TCE_MEMORY);
+OPAL_CALL(opal_pci_set_phb_tce_memory,		OPAL_PCI_SET_PHB_TCE_MEMORY);
+OPAL_CALL(opal_pci_config_read_byte,		OPAL_PCI_CONFIG_READ_BYTE);
+OPAL_CALL(opal_pci_config_read_half_word,	OPAL_PCI_CONFIG_READ_HALF_WORD);
+OPAL_CALL(opal_pci_config_read_word,		OPAL_PCI_CONFIG_READ_WORD);
+OPAL_CALL(opal_pci_config_write_byte,		OPAL_PCI_CONFIG_WRITE_BYTE);
+OPAL_CALL(opal_pci_config_write_half_word,	OPAL_PCI_CONFIG_WRITE_HALF_WORD);
+OPAL_CALL(opal_pci_config_write_word,		OPAL_PCI_CONFIG_WRITE_WORD);
+OPAL_CALL(opal_set_xive,			OPAL_SET_XIVE);
+OPAL_CALL(opal_get_xive,			OPAL_GET_XIVE);
+OPAL_CALL(opal_register_exception_handler,	OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
+OPAL_CALL(opal_pci_eeh_freeze_status,		OPAL_PCI_EEH_FREEZE_STATUS);
+OPAL_CALL(opal_pci_eeh_freeze_clear,		OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_shpc,			OPAL_PCI_SHPC);
+OPAL_CALL(opal_pci_phb_mmio_enable,		OPAL_PCI_PHB_MMIO_ENABLE);
+OPAL_CALL(opal_pci_set_phb_mem_window,		OPAL_PCI_SET_PHB_MEM_WINDOW);
+OPAL_CALL(opal_pci_map_pe_mmio_window,		OPAL_PCI_MAP_PE_MMIO_WINDOW);
+OPAL_CALL(opal_pci_set_phb_table_memory,	OPAL_PCI_SET_PHB_TABLE_MEMORY);
+OPAL_CALL(opal_pci_set_pe,			OPAL_PCI_SET_PE);
+OPAL_CALL(opal_pci_set_peltv,			OPAL_PCI_SET_PELTV);
+OPAL_CALL(opal_pci_set_mve,			OPAL_PCI_SET_MVE);
+OPAL_CALL(opal_pci_set_mve_enable,		OPAL_PCI_SET_MVE_ENABLE);
+OPAL_CALL(opal_pci_get_xive_reissue,		OPAL_PCI_GET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_reissue,		OPAL_PCI_SET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_pe,			OPAL_PCI_SET_XIVE_PE);
+OPAL_CALL(opal_get_xive_source,			OPAL_GET_XIVE_SOURCE);
+OPAL_CALL(opal_get_msi_32,			OPAL_GET_MSI_32);
+OPAL_CALL(opal_get_msi_64,			OPAL_GET_MSI_64);
+OPAL_CALL(opal_start_cpu,			OPAL_START_CPU);
+OPAL_CALL(opal_query_cpu_status,		OPAL_QUERY_CPU_STATUS);
+OPAL_CALL(opal_write_oppanel,			OPAL_WRITE_OPPANEL);
+OPAL_CALL(opal_pci_map_pe_dma_window,		OPAL_PCI_MAP_PE_DMA_WINDOW);
+OPAL_CALL(opal_pci_map_pe_dma_window_real,	OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
+OPAL_CALL(opal_pci_reset,			OPAL_PCI_RESET);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,427 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* Delay in usec */
+#define PCI_RESET_DELAY_US	3000000
+
+#define cfg_dbg(fmt...)	do { } while(0)
+//#define cfg_dbg(fmt...)	printk(fmt)
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+
+	return (phb && phb->msi_map) ? 0 : -ENODEV;
+}
+
+static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
+{
+	unsigned int id;
+
+	spin_lock(&phb->lock);
+	id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
+	if (id >= phb->msi_count && phb->msi_next)
+		id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
+	if (id >= phb->msi_count) {
+		spin_unlock(&phb->lock);
+		return 0;
+	}
+	__set_bit(id, phb->msi_map);
+	spin_unlock(&phb->lock);
+	return id + phb->msi_base;
+}
+
+static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
+{
+	unsigned int id;
+
+	if (WARN_ON(hwirq < phb->msi_base ||
+		    hwirq >= (phb->msi_base + phb->msi_count)))
+		return;
+	id = hwirq - phb->msi_base;
+	spin_lock(&phb->lock);
+	__clear_bit(id, phb->msi_map);
+	spin_unlock(&phb->lock);
+}
+
+static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	unsigned int hwirq, virq;
+	int rc;
+
+	if (WARN_ON(!phb))
+		return -ENODEV;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
+			pr_warn("%s: Supports only 64-bit MSIs\n",
+				pci_name(pdev));
+			return -ENXIO;
+		}
+		hwirq = pnv_get_one_msi(phb);
+		if (!hwirq) {
+			pr_warn("%s: Failed to find a free MSI\n",
+				pci_name(pdev));
+			return -ENOSPC;
+		}
+		virq = irq_create_mapping(NULL, hwirq);
+		if (virq == NO_IRQ) {
+			pr_warn("%s: Failed to map MSI to linux irq\n",
+				pci_name(pdev));
+			pnv_put_msi(phb, hwirq);
+			return -ENOMEM;
+		}
+		rc = phb->msi_setup(phb, pdev, hwirq, entry->msi_attrib.is_64,
+				    &msg);
+		if (rc) {
+			pr_warn("%s: Failed to setup MSI\n", pci_name(pdev));
+			irq_dispose_mapping(virq);
+			pnv_put_msi(phb, hwirq);
+			return rc;
+		}
+		irq_set_msi_desc(virq, entry);
+		write_msi_msg(virq, &msg);
+	}
+	return 0;
+}
+
+static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct msi_desc *entry;
+
+	if (WARN_ON(!phb))
+		return;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+		irq_set_msi_desc(entry->irq, NULL);
+		pnv_put_msi(phb, virq_to_hw(entry->irq));
+		irq_dispose_mapping(entry->irq);
+	}
+}
+#endif /* CONFIG_PCI_MSI */
+
+static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
+				     u32 bdfn)
+{
+	s64	rc;
+	u8	fstate;
+	u16	pcierr;
+	u32	pe_no;
+
+	/* Get PE# if we support IODA */
+	pe_no = phb->bdfn_to_pe ? phb->bdfn_to_pe(phb, bus, bdfn & 0xff) : 0;
+
+	/* Read freeze status */
+	rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
+					NULL);
+	if (rc) {
+		pr_warning("PCI %d: Failed to read EEH status for PE#%d,"
+			   " err %lld\n", phb->hose->global_number, pe_no, rc);
+		return;
+	}
+	cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
+		bdfn, pe_no, fstate);
+	if (fstate != 0) {
+		rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+					      OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+		if (rc) {
+			pr_warning("PCI %d: Failed to clear EEH freeze state"
+				   " for PE#%d, err %lld\n",
+				   phb->hose->global_number, pe_no, rc);
+		}
+	}
+}
+
+static int pnv_pci_read_config(struct pci_bus *bus,
+			       unsigned int devfn,
+			       int where, int size, u32 *val)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pnv_phb *phb = hose->private_data;
+	u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+	s64 rc;
+
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1: {
+		u8 v8;
+		rc = opal_pci_config_read_byte(phb->opal_id, bdfn, where, &v8);
+		*val = (rc == OPAL_SUCCESS) ? v8 : 0xff;
+		break;
+	}
+	case 2: {
+		u16 v16;
+		rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where,
+						   &v16);
+		*val = (rc == OPAL_SUCCESS) ? v16 : 0xffff;
+		break;
+	}
+	case 4: {
+		u32 v32;
+		rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32);
+		*val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff;
+		break;
+	}
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+	cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n",
+		bus->number, devfn, where, size, *val);
+
+	/* Check if the PHB got frozen due to an error (no response) */
+	pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pnv_pci_write_config(struct pci_bus *bus,
+				unsigned int devfn,
+				int where, int size, u32 val)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pnv_phb *phb = hose->private_data;
+	u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	cfg_dbg("pnv_pci_write_config bus: %x devfn: %x +%x/%x -> %08x\n",
+		bus->number, devfn, where, size, val);
+	switch (size) {
+	case 1:
+		opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
+		break;
+	case 2:
+		opal_pci_config_write_half_word(phb->opal_id, bdfn, where, val);
+		break;
+	case 4:
+		opal_pci_config_write_word(phb->opal_id, bdfn, where, val);
+		break;
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+	/* Check if the PHB got frozen due to an error (no response) */
+	pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pnv_pci_ops = {
+	.read = pnv_pci_read_config,
+	.write = pnv_pci_write_config,
+};
+
+static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
+			 unsigned long uaddr, enum dma_data_direction direction,
+			 struct dma_attrs *attrs)
+{
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
+
+	proto_tce = TCE_PCI_READ; // Read allowed
+
+	if (direction != DMA_TO_DEVICE)
+		proto_tce |= TCE_PCI_WRITE;
+
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--) {
+		/* can't move this out since we might cross LMB boundary */
+		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+		uaddr += TCE_PAGE_SIZE;
+		tcep++;
+	}
+	return 0;
+}
+
+static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+{
+	u64 *tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--)
+		*(tcep++) = 0;
+}
+
+void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+			       void *tce_mem, u64 tce_size,
+			       u64 dma_offset)
+{
+	tbl->it_blocksize = 16;
+	tbl->it_base = (unsigned long)tce_mem;
+	tbl->it_offset = dma_offset >> IOMMU_PAGE_SHIFT;
+	tbl->it_index = 0;
+	tbl->it_size = tce_size >> 3;
+	tbl->it_busno = 0;
+	tbl->it_type = TCE_PCI;
+}
+
+static struct iommu_table * __devinit
+pnv_pci_setup_bml_iommu(struct pci_controller *hose)
+{
+	struct iommu_table *tbl;
+	const __be64 *basep;
+	const __be32 *sizep;
+
+	basep = of_get_property(hose->dn, "linux,tce-base", NULL);
+	sizep = of_get_property(hose->dn, "linux,tce-size", NULL);
+	if (basep == NULL || sizep == NULL) {
+		pr_err("PCI: %s has missing tce entries !\n", hose->dn->full_name);
+		return NULL;
+	}
+	tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, hose->node);
+	if (WARN_ON(!tbl))
+		return NULL;
+	pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
+				  be32_to_cpup(sizep), 0);
+	iommu_init_table(tbl, hose->node);
+	return tbl;
+}
+
+static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
+						 struct pci_dev *pdev)
+{
+	struct device_node *np = pci_bus_to_OF_node(hose->bus);
+	struct pci_dn *pdn;
+
+	if (np == NULL)
+		return;
+	pdn = PCI_DN(np);
+	if (!pdn->iommu_table)
+		pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
+	if (!pdn->iommu_table)
+		return;
+	set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+}
+
+static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+
+	/* If we have no phb structure, try to setup a fallback based on
+	 * the device-tree (RTAS PCI for example)
+	 */
+	if (phb && phb->dma_dev_setup)
+		phb->dma_dev_setup(phb, pdev);
+	else
+		pnv_pci_dma_fallback_setup(hose, pdev);
+}
+
+static int pnv_pci_probe_mode(struct pci_bus *bus)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	const __be64 *tstamp;
+	u64 now, target;
+
+
+	/* We hijack this as a way to ensure we have waited long
+	 * enough since the reset was lifted on the PCI bus
+	 */
+	if (bus != hose->bus)
+		return PCI_PROBE_NORMAL;
+	tstamp = of_get_property(hose->dn, "reset-clear-timestamp", NULL);
+	if (!tstamp || !*tstamp)
+		return PCI_PROBE_NORMAL;
+
+	now = mftb() / tb_ticks_per_usec;
+	target = (be64_to_cpup(tstamp) / tb_ticks_per_usec)
+		+ PCI_RESET_DELAY_US;
+
+	pr_devel("pci %04d: Reset target: 0x%llx now: 0x%llx\n",
+		 hose->global_number, target, now);
+
+	if (now < target)
+		msleep((target - now + 999) / 1000);
+
+	return PCI_PROBE_NORMAL;
+}
+
+void __init pnv_pci_init(void)
+{
+	struct device_node *np;
+
+	pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
+
+	/* We do not want to just probe */
+	pci_probe_only = 0;
+
+	/* OPAL absent, try POPAL first then RTAS detection of PHBs */
+	if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+#ifdef CONFIG_PPC_POWERNV_RTAS
+		init_pci_config_tokens();
+		find_and_init_phbs();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+	} else {
+		/* OPAL is here, do our normal stuff */
+
+		/* Look for p5ioc2 IO-Hubs */
+		for_each_compatible_node(np, NULL, "ibm,p5ioc2")
+			pnv_pci_init_p5ioc2_hub(np);
+	}
+
+	/* Setup the linkage between OF nodes and PHBs */
+	pci_devs_phb_init();
+
+	/* Configure IOMMU DMA hooks */
+	ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
+	ppc_md.tce_build = pnv_tce_build;
+	ppc_md.tce_free = pnv_tce_free;
+	ppc_md.pci_probe_mode = pnv_pci_probe_mode;
+	set_pci_dma_ops(&dma_iommu_ops);
+
+	/* Configure MSIs */
+#ifdef CONFIG_PCI_MSI
+	ppc_md.msi_check_device = pnv_msi_check_device;
+	ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
+#endif
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci.h linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+#ifndef __POWERNV_PCI_H
+#define __POWERNV_PCI_H
+
+struct pci_dn;
+
+enum pnv_phb_type {
+	PNV_PHB_P5IOC2,
+	PNV_PHB_IODA1,
+	PNV_PHB_IODA2,
+};
+
+struct pnv_phb {
+	struct pci_controller	*hose;
+	enum pnv_phb_type	type;
+	u64			opal_id;
+	void __iomem		*regs;
+	spinlock_t		lock;
+
+#ifdef CONFIG_PCI_MSI
+	unsigned long		*msi_map;
+	unsigned int		msi_base;
+	unsigned int		msi_count;
+	unsigned int		msi_next;
+	unsigned int		msi32_support;
+#endif
+	int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
+			 unsigned int hwirq, unsigned int is_64,
+			 struct msi_msg *msg);
+	void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+	void (*fixup_phb)(struct pci_controller *hose);
+	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
+
+	union {
+		struct {
+			struct iommu_table iommu_table;
+		} p5ioc2;
+	};
+};
+
+extern struct pci_ops pnv_pci_ops;
+
+extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+				      void *tce_mem, u64 tce_size,
+				      u64 dma_offset);
+extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
+
+
+#endif /* __POWERNV_PCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci-p5ioc2.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci-p5ioc2.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/pci-p5ioc2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/pci-p5ioc2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,234 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* For now, use a fixed amount of TCE memory for each p5ioc2
+ * hub, 16M will do
+ */
+#define P5IOC2_TCE_MEMORY	0x01000000
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
+				    unsigned int hwirq, unsigned int is_64,
+				    struct msi_msg *msg)
+{
+	if (WARN_ON(!is_64))
+		return -ENXIO;
+	msg->data = hwirq - phb->msi_base;
+	msg->address_hi = 0x10000000;
+	msg->address_lo = 0;
+
+	return 0;
+}
+
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
+{
+	unsigned int bmap_size;
+	const __be32 *prop = of_get_property(phb->hose->dn,
+					     "ibm,opal-msi-ranges", NULL);
+	if (!prop)
+		return;
+
+	/* Don't do MSI's on p5ioc2 PCI-X are they are not properly
+	 * verified in HW
+	 */
+	if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix"))
+		return;
+	phb->msi_base = be32_to_cpup(prop);
+	phb->msi_count = be32_to_cpup(prop + 1);
+	bmap_size = BITS_TO_LONGS(phb->msi_count) * sizeof(unsigned long);
+	phb->msi_map = zalloc_maybe_bootmem(bmap_size, GFP_KERNEL);
+	if (!phb->msi_map) {
+		pr_err("PCI %d: Failed to allocate MSI bitmap !\n",
+		       phb->hose->global_number);
+		return;
+	}
+	phb->msi_setup = pnv_pci_p5ioc2_msi_setup;
+	phb->msi32_support = 0;
+	pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
+		phb->msi_count, phb->msi_base);
+}
+#else
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
+#endif /* CONFIG_PCI_MSI */
+
+static void __devinit pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
+						   struct pci_dev *pdev)
+{
+	if (phb->p5ioc2.iommu_table.it_map == NULL)
+		iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node);
+
+	set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+}
+
+static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
+					   void *tce_mem, u64 tce_size)
+{
+	struct pnv_phb *phb;
+	const u64 *prop64;
+	u64 phb_id;
+	int64_t rc;
+	static int primary = 1;
+
+	pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name);
+
+	prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
+	if (!prop64) {
+		pr_err("  Missing \"ibm,opal-phbid\" property !\n");
+		return;
+	}
+	phb_id = be64_to_cpup(prop64);
+	pr_devel("  PHB-ID  : 0x%016llx\n", phb_id);
+	pr_devel("  TCE AT  : 0x%016lx\n", __pa(tce_mem));
+	pr_devel("  TCE SZ  : 0x%016llx\n", tce_size);
+
+	rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("  Failed to set TCE memory, OPAL error %lld\n", rc);
+		return;
+	}
+
+	phb = alloc_bootmem(sizeof(struct pnv_phb));
+	if (phb) {
+		memset(phb, 0, sizeof(struct pnv_phb));
+		phb->hose = pcibios_alloc_controller(np);
+	}
+	if (!phb || !phb->hose) {
+		pr_err("  Failed to allocate PCI controller\n");
+		return;
+	}
+
+	spin_lock_init(&phb->lock);
+	phb->hose->first_busno = 0;
+	phb->hose->last_busno = 0xff;
+	phb->hose->private_data = phb;
+	phb->opal_id = phb_id;
+	phb->type = PNV_PHB_P5IOC2;
+
+	phb->regs = of_iomap(np, 0);
+
+	if (phb->regs == NULL)
+		pr_err("  Failed to map registers !\n");
+	else {
+		pr_devel("  P_BUID     = 0x%08x\n", in_be32(phb->regs + 0x100));
+		pr_devel("  P_IOSZ     = 0x%08x\n", in_be32(phb->regs + 0x1b0));
+		pr_devel("  P_IO_ST    = 0x%08x\n", in_be32(phb->regs + 0x1e0));
+		pr_devel("  P_MEM1_H   = 0x%08x\n", in_be32(phb->regs + 0x1a0));
+		pr_devel("  P_MEM1_L   = 0x%08x\n", in_be32(phb->regs + 0x190));
+		pr_devel("  P_MSZ1_L   = 0x%08x\n", in_be32(phb->regs + 0x1c0));
+		pr_devel("  P_MEM_ST   = 0x%08x\n", in_be32(phb->regs + 0x1d0));
+		pr_devel("  P_MEM2_H   = 0x%08x\n", in_be32(phb->regs + 0x2c0));
+		pr_devel("  P_MEM2_L   = 0x%08x\n", in_be32(phb->regs + 0x2b0));
+		pr_devel("  P_MSZ2_H   = 0x%08x\n", in_be32(phb->regs + 0x2d0));
+		pr_devel("  P_MSZ2_L   = 0x%08x\n", in_be32(phb->regs + 0x2e0));
+	}
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(phb->hose, np, primary);
+	primary = 0;
+
+	phb->hose->ops = &pnv_pci_ops;
+
+	/* Setup MSI support */
+	pnv_pci_init_p5ioc2_msis(phb);
+
+	/* Setup TCEs */
+	phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
+	pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
+				  tce_mem, tce_size, 0);
+}
+
+void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
+{
+	struct device_node *phbn;
+	const u64 *prop64;
+	u64 hub_id;
+	void *tce_mem;
+	uint64_t tce_per_phb;
+	int64_t rc;
+	int phb_count = 0;
+
+	pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name);
+
+	prop64 = of_get_property(np, "ibm,opal-hubid", NULL);
+	if (!prop64) {
+		pr_err(" Missing \"ibm,opal-hubid\" property !\n");
+		return;
+	}
+	hub_id = be64_to_cpup(prop64);
+	pr_info(" HUB-ID : 0x%016llx\n", hub_id);
+
+	/* Currently allocate 16M of TCE memory for every Hub
+	 *
+	 * XXX TODO: Make it chip local if possible
+	 */
+	tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY,
+				  __pa(MAX_DMA_ADDRESS));
+	if (!tce_mem) {
+		pr_err(" Failed to allocate TCE Memory !\n");
+		return;
+	}
+	pr_debug(" TCE    : 0x%016lx..0x%016lx\n",
+		__pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1);
+	rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem),
+					P5IOC2_TCE_MEMORY);
+	if (rc != OPAL_SUCCESS) {
+		pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc);
+		return;
+	}
+
+	/* Count child PHBs */
+	for_each_child_of_node(np, phbn) {
+		if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+		    of_device_is_compatible(phbn, "ibm,p5ioc2-pciex"))
+			phb_count++;
+	}
+
+	/* Calculate how much TCE space we can give per PHB */
+	tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count);
+	pr_info(" Allocating %lld MB of TCE memory per PHB\n",
+		tce_per_phb >> 20);
+
+	/* Initialize PHBs */
+	for_each_child_of_node(np, phbn) {
+		if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+		    of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) {
+			pnv_pci_init_p5ioc2_phb(phbn, tce_mem, tce_per_phb);
+			tce_mem += tce_per_phb;
+		}
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/powernv.h linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/powernv.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/powernv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/powernv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+#ifndef _POWERNV_H
+#define _POWERNV_H
+
+#ifdef CONFIG_SMP
+extern void pnv_smp_init(void);
+#else
+static inline void pnv_smp_init(void) { }
+#endif
+
+#ifdef CONFIG_PCI
+extern void pnv_pci_init(void);
+#else
+static inline void pnv_pci_init(void) { }
+#endif
+
+#endif /* _POWERNV_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,196 @@
+/*
+ * PowerNV setup code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/bug.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/xics.h>
+#include <asm/rtas.h>
+#include <asm/opal.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __init pnv_setup_arch(void)
+{
+	/* Initialize SMP */
+	pnv_smp_init();
+
+	/* Setup PCI */
+	pnv_pci_init();
+
+	/* Setup RTC and NVRAM callbacks */
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		opal_nvram_init();
+
+	/* Enable NAP mode */
+	powersave_nap = 1;
+
+	/* XXX PMCS */
+}
+
+static void __init pnv_init_early(void)
+{
+#ifdef CONFIG_HVC_OPAL
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		hvc_opal_init_early();
+	else
+#endif
+		add_preferred_console("hvc", 0, NULL);
+}
+
+static void __init pnv_init_IRQ(void)
+{
+	xics_init();
+
+	WARN_ON(!ppc_md.get_irq);
+}
+
+static void pnv_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = of_get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+	if (firmware_has_feature(FW_FEATURE_OPALv2))
+		seq_printf(m, "firmware\t: OPAL v2\n");
+	else if (firmware_has_feature(FW_FEATURE_OPAL))
+		seq_printf(m, "firmware\t: OPAL v1\n");
+	else
+		seq_printf(m, "firmware\t: BML\n");
+	of_node_put(root);
+}
+
+static void  __noreturn pnv_restart(char *cmd)
+{
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_cec_reboot();
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	for (;;)
+		opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_power_off(void)
+{
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_cec_power_down(0);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	for (;;)
+		opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_halt(void)
+{
+	pnv_power_off();
+}
+
+static void pnv_progress(char *s, unsigned short hex)
+{
+}
+
+#ifdef CONFIG_KEXEC
+static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+	xics_kexec_teardown_cpu(secondary);
+}
+#endif /* CONFIG_KEXEC */
+
+static void __init pnv_setup_machdep_opal(void)
+{
+	ppc_md.get_boot_time = opal_get_boot_time;
+	ppc_md.get_rtc_time = opal_get_rtc_time;
+	ppc_md.set_rtc_time = opal_set_rtc_time;
+	ppc_md.restart = pnv_restart;
+	ppc_md.power_off = pnv_power_off;
+	ppc_md.halt = pnv_halt;
+	ppc_md.machine_check_exception = opal_machine_check;
+}
+
+#ifdef CONFIG_PPC_POWERNV_RTAS
+static void __init pnv_setup_machdep_rtas(void)
+{
+	if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) {
+		ppc_md.get_boot_time = rtas_get_boot_time;
+		ppc_md.get_rtc_time = rtas_get_rtc_time;
+		ppc_md.set_rtc_time = rtas_set_rtc_time;
+	}
+	ppc_md.restart = rtas_restart;
+	ppc_md.power_off = rtas_power_off;
+	ppc_md.halt = rtas_halt;
+}
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+static int __init pnv_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+		return 0;
+
+	hpte_init_native();
+
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		pnv_setup_machdep_opal();
+#ifdef CONFIG_PPC_POWERNV_RTAS
+	else if (rtas.base)
+		pnv_setup_machdep_rtas();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+	pr_debug("PowerNV detected !\n");
+
+	return 1;
+}
+
+define_machine(powernv) {
+	.name			= "PowerNV",
+	.probe			= pnv_probe,
+	.init_early		= pnv_init_early,
+	.setup_arch		= pnv_setup_arch,
+	.init_IRQ		= pnv_init_IRQ,
+	.show_cpuinfo		= pnv_show_cpuinfo,
+	.progress		= pnv_progress,
+	.power_save             = power7_idle,
+	.calibrate_decr		= generic_calibrate_decr,
+#ifdef CONFIG_KEXEC
+	.kexec_cpu_down		= pnv_kexec_cpu_down,
+#endif
+};
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/powernv/smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/powernv/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,182 @@
+/*
+ * SMP support for PowerNV machines.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __cpuinit pnv_smp_setup_cpu(int cpu)
+{
+	if (cpu != boot_cpuid)
+		xics_setup_cpu();
+}
+
+static int pnv_smp_cpu_bootable(unsigned int nr)
+{
+	/* Special case - we inhibit secondary thread startup
+	 * during boot if the user requests it.
+	 */
+	if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+		if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+			return 0;
+		if (smt_enabled_at_boot
+		    && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+			return 0;
+	}
+
+	return 1;
+}
+
+int __devinit pnv_smp_kick_cpu(int nr)
+{
+	unsigned int pcpu = get_hard_smp_processor_id(nr);
+	unsigned long start_here = __pa(*((unsigned long *)
+					  generic_secondary_smp_init));
+	long rc;
+
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+	/* On OPAL v2 the CPU are still spinning inside OPAL itself,
+	 * get them back now
+	 */
+	if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+		pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
+		rc = opal_start_cpu(pcpu, start_here);
+		if (rc != OPAL_SUCCESS)
+			pr_warn("OPAL Error %ld starting CPU %d\n",
+				rc, nr);
+	}
+	return smp_generic_kick_cpu(nr);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int pnv_smp_cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+
+	/* This is identical to pSeries... might consolidate by
+	 * moving migrate_irqs_away to a ppc_md with default to
+	 * the generic fixup_irqs. --BenH.
+	 */
+	set_cpu_online(cpu, false);
+	vdso_data->processorCount--;
+	if (cpu == boot_cpuid)
+		boot_cpuid = cpumask_any(cpu_online_mask);
+	xics_migrate_irqs_away();
+	return 0;
+}
+
+static void pnv_smp_cpu_kill_self(void)
+{
+	unsigned int cpu;
+
+	/* If powersave_nap is enabled, use NAP mode, else just
+	 * spin aimlessly
+	 */
+	if (!powersave_nap) {
+		generic_mach_cpu_die();
+		return;
+	}
+
+	/* Standard hot unplug procedure */
+	local_irq_disable();
+	idle_task_exit();
+	current->active_mm = NULL; /* for sanity */
+	cpu = smp_processor_id();
+	DBG("CPU%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
+	smp_wmb();
+
+	/* We don't want to take decrementer interrupts while we are offline,
+	 * so clear LPCR:PECE1. We keep PECE2 enabled.
+	 */
+	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+	while (!generic_check_cpu_restart(cpu)) {
+		power7_idle();
+		if (!generic_check_cpu_restart(cpu)) {
+			DBG("CPU%d Unexpected exit while offline !\n", cpu);
+			/* We may be getting an IPI, so we re-enable
+			 * interrupts to process it, it will be ignored
+			 * since we aren't online (hopefully)
+			 */
+			local_irq_enable();
+			local_irq_disable();
+		}
+	}
+	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
+	DBG("CPU%d coming online...\n", cpu);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct smp_ops_t pnv_smp_ops = {
+	.message_pass	= smp_muxed_ipi_message_pass,
+	.cause_ipi	= NULL,	/* Filled at runtime by xics_smp_probe() */
+	.probe		= xics_smp_probe,
+	.kick_cpu	= pnv_smp_kick_cpu,
+	.setup_cpu	= pnv_smp_setup_cpu,
+	.cpu_bootable	= pnv_smp_cpu_bootable,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable	= pnv_smp_cpu_disable,
+	.cpu_die	= generic_cpu_die,
+#endif /* CONFIG_HOTPLUG_CPU */
+};
+
+/* This is called very early during platform setup_arch */
+void __init pnv_smp_init(void)
+{
+	smp_ops = &pnv_smp_ops;
+
+	/* XXX We don't yet have a proper entry point from HAL, for
+	 * now we rely on kexec-style entry from BML
+	 */
+
+#ifdef CONFIG_PPC_RTAS
+	/* Non-lpar has additional take/give timebase */
+	if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+		smp_ops->give_timebase = rtas_give_timebase;
+		smp_ops->take_timebase = rtas_take_timebase;
+	}
+#endif /* CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_HOTPLUG_CPU
+	ppc_md.cpu_die	= pnv_smp_cpu_kill_self;
+#endif
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/prep/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/prep/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/prep/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/prep/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,3 @@ config PREP_RESIDUAL
 	  or pass the 'noresidual' option to the kernel.
 
 	  If you are running a PReP system, say Y here, otherwise say N.
-
-config PROC_PREPRESIDUAL
-	bool "Support for reading of PReP Residual Data in /proc"
-	depends on PREP_RESIDUAL && PROC_FS
-	help
-	  Enabling this option will create a /proc/residual file which allows
-	  you to get at the residual data on PReP systems.  You will need a tool
-	  (lsresidual) to parse it.  If you aren't on a PReP system, you don't
-	  want this.
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/device-init.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/device-init.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/device-init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/device-init.c	2012-01-04 18:55:44.000000000 -0500
@@ -825,7 +825,7 @@ static int ps3_probe_thread(void *data)
 
 	spin_lock_init(&dev.lock);
 
-	res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
+	res = request_irq(irq, ps3_notification_interrupt, 0,
 			  "ps3_notification", &dev);
 	if (res) {
 		pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/exports.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/exports.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/module.h>
-
 #define LV1_CALL(name, in, out, num)                          \
   extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \
   EXPORT_SYMBOL(_lv1_##name);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/gelic_udbg.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/gelic_udbg.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/gelic_udbg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/gelic_udbg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * udbg debug output routine via GELIC UDP broadcasts
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ * Copyright (C) 2010 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2011 Andre Heider <a.heider@gmail.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 <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+				       GELIC_DESCR_TX_DMA_IKE | \
+				       GELIC_DESCR_TX_DMA_NO_CHKSUM)
+
+static u64 bus_addr;
+
+struct gelic_descr {
+	/* as defined by the hardware */
+	__be32 buf_addr;
+	__be32 buf_size;
+	__be32 next_descr_addr;
+	__be32 dmac_cmd_status;
+	__be32 result_size;
+	__be32 valid_size;	/* all zeroes for tx */
+	__be32 data_status;
+	__be32 data_error;	/* all zeroes for tx */
+} __attribute__((aligned(32)));
+
+struct debug_block {
+	struct gelic_descr descr;
+	u8 pkt[1520];
+} __packed;
+
+struct ethhdr {
+	u8 dest[6];
+	u8 src[6];
+	u16 type;
+} __packed;
+
+struct vlantag {
+	u16 vlan;
+	u16 subtype;
+} __packed;
+
+struct iphdr {
+	u8 ver_len;
+	u8 dscp_ecn;
+	u16 total_length;
+	u16 ident;
+	u16 frag_off_flags;
+	u8 ttl;
+	u8 proto;
+	u16 checksum;
+	u32 src;
+	u32 dest;
+} __packed;
+
+struct udphdr {
+	u16 src;
+	u16 dest;
+	u16 len;
+	u16 checksum;
+} __packed;
+
+static __iomem struct ethhdr *h_eth;
+static __iomem struct vlantag *h_vlan;
+static __iomem struct iphdr *h_ip;
+static __iomem struct udphdr *h_udp;
+
+static __iomem char *pmsg;
+static __iomem char *pmsgc;
+
+static __iomem struct debug_block dbg __attribute__((aligned(32)));
+
+static int header_size;
+
+static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
+			u64 *real_bus_addr)
+{
+	s64 result;
+	u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
+	u64 real_end = real_addr + len;
+	u64 map_start = real_addr & ~0xfff;
+	u64 map_end = (real_end + 0xfff) & ~0xfff;
+	u64 bus_addr = 0;
+
+	u64 flags = 0xf800000000000000UL;
+
+	result = lv1_allocate_device_dma_region(bus_id, dev_id,
+						map_end - map_start, 12, 0,
+						&bus_addr);
+	if (result)
+		lv1_panic(0);
+
+	result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
+					   bus_addr, map_end - map_start,
+					   flags);
+	if (result)
+		lv1_panic(0);
+
+	*real_bus_addr = bus_addr + real_addr - map_start;
+}
+
+static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len)
+{
+	s64 result;
+	u64 real_bus_addr;
+
+	real_bus_addr = bus_addr & ~0xfff;
+	len += bus_addr - real_bus_addr;
+	len = (len + 0xfff) & ~0xfff;
+
+	result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr,
+					     len);
+	if (result)
+		return result;
+
+	return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr);
+}
+
+static void gelic_debug_init(void)
+{
+	s64 result;
+	u64 v2;
+	u64 mac;
+	u64 vlan_id;
+
+	result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0);
+	if (result)
+		lv1_panic(0);
+
+	map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg),
+		    &bus_addr);
+
+	memset(&dbg, 0, sizeof(dbg));
+
+	dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt);
+
+	wmb();
+
+	result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+				 GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0,
+				 &mac, &v2);
+	if (result)
+		lv1_panic(0);
+
+	mac <<= 16;
+
+	h_eth = (struct ethhdr *)dbg.pkt;
+
+	memset(&h_eth->dest, 0xff, 6);
+	memcpy(&h_eth->src, &mac, 6);
+
+	header_size = sizeof(struct ethhdr);
+
+	result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+				 GELIC_LV1_GET_VLAN_ID,
+				 GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
+				 &vlan_id, &v2);
+	if (!result) {
+		h_eth->type = 0x8100;
+
+		header_size += sizeof(struct vlantag);
+		h_vlan = (struct vlantag *)(h_eth + 1);
+		h_vlan->vlan = vlan_id;
+		h_vlan->subtype = 0x0800;
+		h_ip = (struct iphdr *)(h_vlan + 1);
+	} else {
+		h_eth->type = 0x0800;
+		h_ip = (struct iphdr *)(h_eth + 1);
+	}
+
+	header_size += sizeof(struct iphdr);
+	h_ip->ver_len = 0x45;
+	h_ip->ttl = 10;
+	h_ip->proto = 0x11;
+	h_ip->src = 0x00000000;
+	h_ip->dest = 0xffffffff;
+
+	header_size += sizeof(struct udphdr);
+	h_udp = (struct udphdr *)(h_ip + 1);
+	h_udp->src = GELIC_DEBUG_PORT;
+	h_udp->dest = GELIC_DEBUG_PORT;
+
+	pmsgc = pmsg = (char *)(h_udp + 1);
+}
+
+static void gelic_debug_shutdown(void)
+{
+	if (bus_addr)
+		unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID,
+			      bus_addr, sizeof(dbg));
+	lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID);
+}
+
+static void gelic_sendbuf(int msgsize)
+{
+	u16 *p;
+	u32 sum;
+	int i;
+
+	dbg.descr.buf_size = header_size + msgsize;
+	h_ip->total_length = msgsize + sizeof(struct udphdr) +
+			     sizeof(struct iphdr);
+	h_udp->len = msgsize + sizeof(struct udphdr);
+
+	h_ip->checksum = 0;
+	sum = 0;
+	p = (u16 *)h_ip;
+	for (i = 0; i < 5; i++)
+		sum += *p++;
+	h_ip->checksum = ~(sum + (sum >> 16));
+
+	dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
+				    GELIC_DESCR_TX_DMA_FRAME_TAIL;
+	dbg.descr.result_size = 0;
+	dbg.descr.data_status = 0;
+
+	wmb();
+
+	lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0);
+
+	while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) ==
+	       GELIC_DESCR_DMA_CARDOWNED)
+		cpu_relax();
+}
+
+static void ps3gelic_udbg_putc(char ch)
+{
+	*pmsgc++ = ch;
+	if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) {
+		gelic_sendbuf(pmsgc-pmsg);
+		pmsgc = pmsg;
+	}
+}
+
+void __init udbg_init_ps3gelic(void)
+{
+	gelic_debug_init();
+	udbg_putc = ps3gelic_udbg_putc;
+}
+
+void udbg_shutdown_ps3gelic(void)
+{
+	udbg_putc = NULL;
+	gelic_debug_shutdown();
+}
+EXPORT_SYMBOL(udbg_shutdown_ps3gelic);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/interrupt.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/interrupt.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 
 #include <asm/machdep.h>
@@ -88,6 +88,7 @@ struct ps3_private {
 	struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
 	u64 ppe_id;
 	u64 thread_id;
+	unsigned long ipi_mask;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
@@ -144,7 +145,11 @@ static void ps3_chip_unmask(struct irq_d
 static void ps3_chip_eoi(struct irq_data *d)
 {
 	const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
-	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
+
+	/* non-IPIs are EOIed here. */
+
+	if (!test_bit(63 - d->irq, &pd->ipi_mask))
+		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -691,6 +696,16 @@ void __init ps3_register_ipi_debug_brk(u
 		cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
+{
+	struct ps3_private *pd = &per_cpu(ps3_private, cpu);
+
+	set_bit(63 - virq, &pd->ipi_mask);
+
+	DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
+		cpu, virq, pd->ipi_mask);
+}
+
 static unsigned int ps3_get_irq(void)
 {
 	struct ps3_private *pd = &__get_cpu_var(ps3_private);
@@ -720,6 +735,12 @@ static unsigned int ps3_get_irq(void)
 		BUG();
 	}
 #endif
+
+	/* IPIs are EOIed here. */
+
+	if (test_bit(63 - plug, &pd->ipi_mask))
+		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
+
 	return plug;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -148,4 +148,16 @@ config PS3_LPM
 	  profiling support of the Cell processor with programs like
 	  oprofile and perfmon2, then say Y or M, otherwise say N.
 
+config PS3GELIC_UDBG
+	bool "PS3 udbg output via UDP broadcasts on Ethernet"
+	depends on PPC_PS3
+	help
+	  Enables udbg early debugging output by sending broadcast UDP
+	  via the Ethernet port (UDP port number 18194).
+
+	  This driver uses a trivial implementation and is independent
+	  from the main network driver.
+
+	  If in doubt, say N here.
+
 endmenu
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@ obj-y += setup.o mm.o time.o hvcall.o ht
 obj-y += interrupt.o exports.o os-area.o
 obj-y += system-bus.o
 
+obj-$(CONFIG_PS3GELIC_UDBG) += gelic_udbg.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
 obj-y += device-init.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/mm.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/mm.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memory_hotplug.h>
 #include <linux/memblock.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/os-area.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/os-area.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/os-area.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/os-area.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/syscalls.h>
+#include <linux/export.h>
 #include <linux/ctype.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/platform.h linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/platform.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/platform.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/platform.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@ void ps3_mm_shutdown(void);
 void ps3_init_IRQ(void);
 void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq);
 
 /* smp */
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/repository.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/repository.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/repository.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/repository.c	2012-01-04 18:55:44.000000000 -0500
@@ -184,7 +184,7 @@ int ps3_repository_read_bus_type(unsigne
 	enum ps3_bus_type *bus_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -199,7 +199,7 @@ int ps3_repository_read_bus_num_dev(unsi
 	unsigned int *num_dev)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -239,7 +239,7 @@ int ps3_repository_read_dev_type(unsigne
 	unsigned int dev_index, enum ps3_dev_type *dev_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -256,8 +256,8 @@ int ps3_repository_read_dev_intr(unsigne
 	enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
 {
 	int result;
-	u64 v1;
-	u64 v2;
+	u64 v1 = 0;
+	u64 v2 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -275,7 +275,7 @@ int ps3_repository_read_dev_reg_type(uns
 	enum ps3_reg_type *reg_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -615,7 +615,7 @@ int ps3_repository_read_stor_dev_num_reg
 	unsigned int dev_index, unsigned int *num_regions)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -631,7 +631,7 @@ int ps3_repository_read_stor_dev_region_
 	unsigned int *region_id)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 	    make_first_field("bus", bus_index),
@@ -786,7 +786,7 @@ int ps3_repository_read_mm_info(u64 *rm_
 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -805,7 +805,7 @@ int ps3_repository_read_num_spu_reserved
 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -827,8 +827,8 @@ int ps3_repository_read_spu_resource_id(
 	enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
 {
 	int result;
-	u64 v1;
-	u64 v2;
+	u64 v1 = 0;
+	u64 v2 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -854,7 +854,7 @@ static int ps3_repository_read_boot_dat_
 int ps3_repository_read_boot_dat_size(unsigned int *size)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -869,7 +869,7 @@ int ps3_repository_read_boot_dat_size(un
 int ps3_repository_read_vuart_av_port(unsigned int *port)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -884,7 +884,7 @@ int ps3_repository_read_vuart_av_port(un
 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -919,7 +919,7 @@ int ps3_repository_read_boot_dat_info(u6
 int ps3_repository_read_num_be(unsigned int *num_be)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("ben", 0),
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/fs.h>
 #include <linux/root_dev.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 
 #include <asm/machdep.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,46 +59,49 @@ static void ps3_smp_message_pass(int cpu
 
 static int ps3_smp_probe(void)
 {
-	return 2;
-}
+	int cpu;
 
-static void __init ps3_smp_setup_cpu(int cpu)
-{
-	int result;
-	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
-	int i;
+	for (cpu = 0; cpu < 2; cpu++) {
+		int result;
+		unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
+		int i;
 
-	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+		DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-	/*
-	 * Check assumptions on ps3_ipi_virqs[] indexing. If this
-	 * check fails, then a different mapping of PPC_MSG_
-	 * to index needs to be setup.
-	 */
+		/*
+		* Check assumptions on ps3_ipi_virqs[] indexing. If this
+		* check fails, then a different mapping of PPC_MSG_
+		* to index needs to be setup.
+		*/
 
-	BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
-	BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
-	BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
-	BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
+		BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
+		BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
+		BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
+		BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
 
-	for (i = 0; i < MSG_COUNT; i++) {
-		result = ps3_event_receive_port_setup(cpu, &virqs[i]);
+		for (i = 0; i < MSG_COUNT; i++) {
+			result = ps3_event_receive_port_setup(cpu, &virqs[i]);
 
-		if (result)
-			continue;
+			if (result)
+				continue;
 
-		DBG("%s:%d: (%d, %d) => virq %u\n",
-			__func__, __LINE__, cpu, i, virqs[i]);
+			DBG("%s:%d: (%d, %d) => virq %u\n",
+				__func__, __LINE__, cpu, i, virqs[i]);
 
-		result = smp_request_message_ipi(virqs[i], i);
+			result = smp_request_message_ipi(virqs[i], i);
 
-		if (result)
-			virqs[i] = NO_IRQ;
-	}
+			if (result)
+				virqs[i] = NO_IRQ;
+			else
+				ps3_register_ipi_irq(cpu, virqs[i]);
+		}
 
-	ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
+		ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
 
-	DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+		DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+	}
+
+	return 2;
 }
 
 void ps3_smp_cleanup_cpu(int cpu)
@@ -121,7 +124,6 @@ static struct smp_ops_t ps3_smp_ops = {
 	.probe		= ps3_smp_probe,
 	.message_pass	= ps3_smp_message_pass,
 	.kick_cpu	= smp_generic_kick_cpu,
-	.setup_cpu	= ps3_smp_setup_cpu,
 };
 
 void smp_init_ps3(void)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/spu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/spu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/spu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/spu.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mmzone.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/mm.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/system-bus.c linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/system-bus.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/ps3/system-bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/ps3/system-bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -695,12 +695,18 @@ static int ps3_dma_supported(struct devi
 	return mask >= DMA_BIT_MASK(32);
 }
 
+static u64 ps3_dma_get_required_mask(struct device *_dev)
+{
+	return DMA_BIT_MASK(32);
+}
+
 static struct dma_map_ops ps3_sb_dma_ops = {
 	.alloc_coherent = ps3_alloc_coherent,
 	.free_coherent = ps3_free_coherent,
 	.map_sg = ps3_sb_map_sg,
 	.unmap_sg = ps3_sb_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_sb_map_page,
 	.unmap_page = ps3_unmap_page,
 };
@@ -711,6 +717,7 @@ static struct dma_map_ops ps3_ioc0_dma_o
 	.map_sg = ps3_ioc0_map_sg,
 	.unmap_sg = ps3_ioc0_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_ioc0_map_page,
 	.unmap_page = ps3_unmap_page,
 };
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/dlpar.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/dlpar.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/dlpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/dlpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -112,6 +112,7 @@ void dlpar_free_cc_nodes(struct device_n
 	dlpar_free_one_cc_node(dn);
 }
 
+#define COMPLETE	0
 #define NEXT_SIBLING    1
 #define NEXT_CHILD      2
 #define NEXT_PROPERTY   3
@@ -158,6 +159,9 @@ struct device_node *dlpar_configure_conn
 		spin_unlock(&rtas_data_buf_lock);
 
 		switch (rc) {
+		case COMPLETE:
+			break;
+
 		case NEXT_SIBLING:
 			dn = dlpar_parse_cc_node(ccwa);
 			if (!dn)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/sched.h>	/* for init_mm */
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/pci.h>
@@ -29,6 +30,7 @@
 #include <linux/rbtree.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/of.h>
 
 #include <linux/atomic.h>
@@ -1338,7 +1340,7 @@ static const struct file_operations proc
 static int __init eeh_init_proc(void)
 {
 	if (machine_is(pseries))
-		proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
+		proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
 	return 0;
 }
 __initcall(eeh_init_proc);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh_event.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh_event.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
  * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 #include <linux/pci.h>
+#include <linux/stat.h>
 #include <asm/ppc-pci.h>
 #include <asm/pci-bridge.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/hotplug-cpu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/hotplug-cpu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/hotplug-cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/hotplug-cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/sched.h>	/* for idle_task_exit */
 #include <linux/cpu.h>
 #include <asm/system.h>
 #include <asm/prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/hvconsole.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/hvconsole.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/hvconsole.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/hvconsole.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,8 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/errno.h>
 #include <asm/hvcall.h>
 #include <asm/hvconsole.h>
 #include "plpar_wrappers.h"
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/io_event_irq.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/io_event_irq.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/io_event_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/io_event_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/iommu.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>	/* for show_stack */
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -939,14 +940,14 @@ static u64 enable_ddw(struct pci_dev *de
 	if (ret) {
 		dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
 			 dn->full_name, ret);
-		goto out_clear_window;
+		goto out_free_window;
 	}
 
 	ret = prom_add_property(pdn, win64);
 	if (ret) {
 		dev_err(&dev->dev, "unable to add dma window property for %s: %d",
 			 pdn->full_name, ret);
-		goto out_clear_window;
+		goto out_free_window;
 	}
 
 	window->device = pdn;
@@ -958,6 +959,9 @@ static u64 enable_ddw(struct pci_dev *de
 	dma_addr = of_read_number(&create.addr_hi, 2);
 	goto out_unlock;
 
+out_free_window:
+	kfree(window);
+
 out_clear_window:
 	remove_ddw(pdn);
 
@@ -1077,12 +1081,38 @@ check_mask:
 	return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	if (!disable_ddw && dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		struct device_node *dn;
+
+		dn = pci_device_to_OF_node(pdev);
+
+		/* search upwards for ibm,dma-window */
+		for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+				dn = dn->parent)
+			if (of_get_property(dn, "ibm,dma-window", NULL))
+				break;
+		/* if there is a ibm,ddw-applicable property require 64 bits */
+		if (dn && PCI_DN(dn) &&
+				of_get_property(dn, "ibm,ddw-applicable", NULL))
+			return DMA_BIT_MASK(64);
+	}
+
+	return dma_iommu_ops.get_required_mask(dev);
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries	NULL
 #define pci_dma_dev_setup_pSeries	NULL
 #define pci_dma_bus_setup_pSeriesLP	NULL
 #define pci_dma_dev_setup_pSeriesLP	NULL
 #define dma_set_mask_pSeriesLP		NULL
+#define dma_get_required_mask_pSeriesLP	NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1216,7 @@ void iommu_init_early_pSeries(void)
 		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
 		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
 		ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
+		ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@ config PPC_PSERIES
 	select PPC_UDBG_16550
 	select PPC_NATIVE
 	select PPC_PCI_CHOICE if EXPERT
+	select ZLIB_DEFLATE
 	default y
 
 config PPC_SPLPAR
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/lpar.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/lpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/lpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/page.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/mobility.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/mobility.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/mobility.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/mobility.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/smp.h>
+#include <linux/stat.h>
 #include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/delay.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/nvram.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/nvram.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/kmsg_dump.h>
+#include <linux/ctype.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -78,8 +80,41 @@ static struct kmsg_dumper nvram_kmsg_dum
 #define NVRAM_RTAS_READ_TIMEOUT 5		/* seconds */
 static unsigned long last_unread_rtas_event;	/* timestamp */
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static char *oops_buf;
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a prefix.
+ * The prefix is just a u16 holding the length of the compressed* text.
+ * (*Or uncompressed, if compression fails.)  oops_buf[] gets written
+ * to NVRAM.
+ *
+ * oops_len points to the prefix.  oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |		+- oops_data
+ * v		v
+ * +------------+-----------------------------------------------+
+ * | length	| text                                          |
+ * | (2 bytes)	| (oops_data_sz bytes)                          |
+ * +------------+-----------------------------------------------+
+ * ^
+ * +- oops_len
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static u16 *oops_len;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -387,11 +422,44 @@ static void __init nvram_init_oops_parti
 						sizeof(rtas_log_partition));
 	}
 	oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+	if (!oops_buf) {
+		pr_err("nvram: No memory for %s partition\n",
+						oops_log_partition.name);
+		return;
+	}
+	oops_len = (u16*) oops_buf;
+	oops_data = oops_buf + sizeof(u16);
+	oops_data_sz = oops_log_partition.size - sizeof(u16);
+
+	/*
+	 * Figure compression (preceded by elimination of each line's <n>
+	 * severity prefix) will reduce the oops/panic report to at most
+	 * 45% of its original size.
+	 */
+	big_oops_buf_sz = (oops_data_sz * 100) / 45;
+	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+	if (big_oops_buf) {
+		stream.workspace = kmalloc(zlib_deflate_workspacesize(
+				WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+		if (!stream.workspace) {
+			pr_err("nvram: No memory for compression workspace; "
+				"skipping compression of %s partition data\n",
+				oops_log_partition.name);
+			kfree(big_oops_buf);
+			big_oops_buf = NULL;
+		}
+	} else {
+		pr_err("No memory for uncompressed %s data; "
+			"skipping compression\n", oops_log_partition.name);
+		stream.workspace = NULL;
+	}
+
 	rc = kmsg_dump_register(&nvram_kmsg_dumper);
 	if (rc != 0) {
 		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
 		kfree(oops_buf);
-		return;
+		kfree(big_oops_buf);
+		kfree(stream.workspace);
 	}
 }
 
@@ -473,7 +541,83 @@ static int clobbering_unread_rtas_event(
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* our kmsg_dump callback */
+/* Squeeze out each line's <n> severity prefix. */
+static size_t elide_severities(char *buf, size_t len)
+{
+	char *in, *out, *buf_end = buf + len;
+	/* Assume a <n> at the very beginning marks the start of a line. */
+	int newline = 1;
+
+	in = out = buf;
+	while (in < buf_end) {
+		if (newline && in+3 <= buf_end &&
+				*in == '<' && isdigit(in[1]) && in[2] == '>') {
+			in += 3;
+			newline = 0;
+		} else {
+			newline = (*in == '\n');
+			*out++ = *in++;
+		}
+	}
+	return out - buf;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+							size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+						MEM_LEVEL, Z_DEFAULT_STRATEGY);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_deflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_deflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	if (stream.total_out >= stream.total_in)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+	int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+								oops_data_sz);
+	if (zipped_len < 0) {
+		pr_err("nvram: compression failed; returned %d\n", zipped_len);
+		pr_err("nvram: logging uncompressed oops/panic report\n");
+		return -1;
+	}
+	*oops_len = (u16) zipped_len;
+	return 0;
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
 		enum kmsg_dump_reason reason,
 		const char *old_msgs, unsigned long old_len,
@@ -482,6 +626,8 @@ static void oops_to_nvram(struct kmsg_du
 	static unsigned int oops_count = 0;
 	static bool panicking = false;
 	size_t text_len;
+	unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+	int rc = -1;
 
 	switch (reason) {
 	case KMSG_DUMP_RESTART:
@@ -509,8 +655,19 @@ static void oops_to_nvram(struct kmsg_du
 	if (clobbering_unread_rtas_event())
 		return;
 
-	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
-					oops_buf, oops_log_partition.size);
+	if (big_oops_buf) {
+		text_len = capture_last_msgs(old_msgs, old_len,
+			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
+		text_len = elide_severities(big_oops_buf, text_len);
+		rc = zip_oops(text_len);
+	}
+	if (rc != 0) {
+		text_len = capture_last_msgs(old_msgs, old_len,
+				new_msgs, new_len, oops_data, oops_data_sz);
+		err_type = ERR_TYPE_KERNEL_PANIC;
+		*oops_len = (u16) text_len;
+	}
+
 	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+		(int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count);
 }
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/pci_dlpar.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/pci_dlpar.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/pci_dlpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/pci_dlpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/plpar_wrappers.h linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/plpar_wrappers.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/plpar_wrappers.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/plpar_wrappers.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,10 @@
 #ifndef _PSERIES_PLPAR_WRAPPERS_H
 #define _PSERIES_PLPAR_WRAPPERS_H
 
+#include <linux/string.h>
+
 #include <asm/hvcall.h>
+#include <asm/paca.h>
 #include <asm/page.h>
 
 /* Get state of physical CPU from query_cpu_stopped */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/setup.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/pci.h>
 #include <linux/utsname.h>
 #include <linux/adb.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/smp.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/smp.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/suspend.c linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/suspend.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/pseries/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/pseries/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 
 #include <linux/delay.h>
 #include <linux/suspend.h>
+#include <linux/stat.h>
 #include <asm/firmware.h>
 #include <asm/hvcall.h>
 #include <asm/machdep.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/ics.c linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/ics.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/ics.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/ics.c	2012-01-04 18:55:44.000000000 -0500
@@ -710,3 +710,51 @@ void __init wsp_init_irq(void)
 	/* We need to patch our irq chip's EOI to point to the right ICP */
 	wsp_irq_chip.irq_eoi = icp_ops->eoi;
 }
+
+#ifdef CONFIG_PCI_MSI
+static void wsp_ics_msi_unmask_irq(struct irq_data *d)
+{
+	wsp_chip_unmask_irq(d);
+	unmask_msi_irq(d);
+}
+
+static unsigned int wsp_ics_msi_startup(struct irq_data *d)
+{
+	wsp_ics_msi_unmask_irq(d);
+	return 0;
+}
+
+static void wsp_ics_msi_mask_irq(struct irq_data *d)
+{
+	mask_msi_irq(d);
+	wsp_chip_mask_irq(d);
+}
+
+/*
+ * we do it this way because we reassinge default EOI handling in
+ * irq_init() above
+ */
+static void wsp_ics_eoi(struct irq_data *data)
+{
+	wsp_irq_chip.irq_eoi(data);
+}
+
+static struct irq_chip wsp_ics_msi = {
+	.name = "WSP ICS MSI",
+	.irq_startup = wsp_ics_msi_startup,
+	.irq_mask = wsp_ics_msi_mask_irq,
+	.irq_unmask = wsp_ics_msi_unmask_irq,
+	.irq_eoi = wsp_ics_eoi,
+	.irq_set_affinity = wsp_chip_set_affinity
+};
+
+void wsp_ics_set_msi_chip(unsigned int irq)
+{
+	irq_set_chip(irq, &wsp_ics_msi);
+}
+
+void wsp_ics_set_std_chip(unsigned int irq)
+{
+	irq_set_chip(irq, &wsp_irq_chip);
+}
+#endif /* CONFIG_PCI_MSI */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/ics.h linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/ics.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/ics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/ics.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,4 +17,9 @@ extern void wsp_init_irq(void);
 extern int wsp_ics_alloc_irq(struct device_node *dn, int num);
 extern void wsp_ics_free_irq(struct device_node *dn, unsigned int irq);
 
+#ifdef CONFIG_PCI_MSI
+extern void wsp_ics_set_msi_chip(unsigned int irq);
+extern void wsp_ics_set_std_chip(unsigned int irq);
+#endif /* CONFIG_PCI_MSI */
+
 #endif /* __ICS_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/Kconfig linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/Kconfig
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,12 @@
 config PPC_WSP
 	bool
+	select PPC_A2
+	select PPC_SCOM
+	select PPC_XICS
+	select PPC_ICP_NATIVE
+	select PCI
+	select PPC_IO_WORKAROUNDS if PCI
+	select PPC_INDIRECT_PIO if PCI
 	default n
 
 menu "WSP platform selection"
@@ -7,13 +14,9 @@ menu "WSP platform selection"
 
 config PPC_PSR2
 	bool "PSR-2 platform"
-	select PPC_A2
 	select GENERIC_TBSYNC
-	select PPC_SCOM
 	select EPAPR_BOOT
 	select PPC_WSP
-	select PPC_XICS
-	select PPC_ICP_NATIVE
 	default y
 
 endmenu
@@ -21,8 +24,3 @@ endmenu
 config PPC_A2_DD2
 	bool "Support for DD2 based A2/WSP systems"
 	depends on PPC_A2
-
-config WORKAROUND_ERRATUM_463
-	depends on PPC_A2_DD2
-	bool "Workaround erratum 463"
-	default y
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/Makefile linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,5 @@ obj-y				+= setup.o ics.o
 obj-$(CONFIG_PPC_PSR2)		+= psr2.o opb_pic.o
 obj-$(CONFIG_PPC_WSP)		+= scom_wsp.o
 obj-$(CONFIG_SMP)		+= smp.o scom_smp.o
+obj-$(CONFIG_PCI)		+= wsp_pci.o
+obj-$(CONFIG_PCI_MSI)		+= msi.o
\ No newline at end of file
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/msi.c linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/msi.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/msi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "msi.h"
+#include "ics.h"
+#include "wsp_pci.h"
+
+/* Magic addresses for 32 & 64-bit MSIs with hardcoded MVE 0 */
+#define MSI_ADDR_32		0xFFFF0000ul
+#define MSI_ADDR_64		0x1000000000000000ul
+
+int wsp_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct pci_controller *phb;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	unsigned int virq;
+	int hwirq;
+
+	phb = pci_bus_to_host(dev->bus);
+	if (!phb)
+		return -ENOENT;
+
+	entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+	if (entry->msi_attrib.is_64) {
+		msg.address_lo = 0;
+		msg.address_hi = MSI_ADDR_64 >> 32;
+	} else {
+		msg.address_lo = MSI_ADDR_32;
+		msg.address_hi = 0;
+	}
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		hwirq = wsp_ics_alloc_irq(phb->dn, 1);
+		if (hwirq < 0) {
+			dev_warn(&dev->dev, "wsp_msi: hwirq alloc failed!\n");
+			return hwirq;
+		}
+
+		virq = irq_create_mapping(NULL, hwirq);
+		if (virq == NO_IRQ) {
+			dev_warn(&dev->dev, "wsp_msi: virq alloc failed!\n");
+			return -1;
+		}
+
+		dev_dbg(&dev->dev, "wsp_msi: allocated irq %#x/%#x\n",
+			hwirq, virq);
+
+		wsp_ics_set_msi_chip(virq);
+		irq_set_msi_desc(virq, entry);
+		msg.data = hwirq & XIVE_ADDR_MASK;
+		write_msi_msg(virq, &msg);
+	}
+
+	return 0;
+}
+
+void wsp_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct pci_controller *phb;
+	struct msi_desc *entry;
+	int hwirq;
+
+	phb = pci_bus_to_host(dev->bus);
+
+	dev_dbg(&dev->dev, "wsp_msi: tearing down msi irqs\n");
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+
+		irq_set_msi_desc(entry->irq, NULL);
+		wsp_ics_set_std_chip(entry->irq);
+
+		hwirq = virq_to_hw(entry->irq);
+		/* In this order to avoid racing with irq_create_mapping() */
+		irq_dispose_mapping(entry->irq);
+		wsp_ics_free_irq(phb->dn, hwirq);
+	}
+}
+
+void wsp_setup_phb_msi(struct pci_controller *phb)
+{
+	/* Create a single MVE at offset 0 that matches everything */
+	out_be64(phb->cfg_data + PCIE_REG_IODA_ADDR, PCIE_REG_IODA_AD_TBL_MVT);
+	out_be64(phb->cfg_data + PCIE_REG_IODA_DATA0, 1ull << 63);
+
+	ppc_md.setup_msi_irqs = wsp_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = wsp_teardown_msi_irqs;
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/msi.h linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/msi.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/msi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/msi.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __WSP_MSI_H
+#define __WSP_MSI_H
+
+#ifdef CONFIG_PCI_MSI
+extern void wsp_setup_phb_msi(struct pci_controller *phb);
+#else
+static inline void wsp_setup_phb_msi(struct pci_controller *phb) { }
+#endif
+
+#endif /* __WSP_MSI_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/psr2.c linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/psr2.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/psr2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/psr2.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,10 @@ static void __init psr2_setup_arch(void)
 #ifdef CONFIG_SMP
 	a2_setup_smp();
 #endif
+#ifdef CONFIG_PCI
+	wsp_setup_pci();
+#endif
+
 }
 
 static int __init psr2_probe(void)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp.h linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,9 @@
 
 #include <asm/wsp.h>
 
+/* Devtree compatible strings for major devices */
+#define PCIE_COMPATIBLE     "ibm,wsp-pciex"
+
 extern void wsp_setup_pci(void);
 extern void scom_init_wsp(void);
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp_pci.c linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp_pci.c
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1133 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * 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.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/iommu.h>
+#include <asm/io-workarounds.h>
+
+#include "wsp.h"
+#include "wsp_pci.h"
+#include "msi.h"
+
+
+/* Max number of TVTs for one table. Only 32-bit tables can use
+ * multiple TVTs and so the max currently supported is thus 8
+ * since only 2G of DMA space is supported
+ */
+#define MAX_TABLE_TVT_COUNT		8
+
+struct wsp_dma_table {
+	struct list_head	link;
+	struct iommu_table	table;
+	struct wsp_phb	*phb;
+	struct page		*tces[MAX_TABLE_TVT_COUNT];
+};
+
+/* We support DMA regions from 0...2G in 32bit space (no support for
+ * 64-bit DMA just yet). Each device gets a separate TCE table (TVT
+ * entry) with validation enabled (though not supported by SimiCS
+ * just yet).
+ *
+ * To simplify things, we divide this 2G space into N regions based
+ * on the constant below which could be turned into a tunable eventually
+ *
+ * We then assign dynamically those regions to devices as they show up.
+ *
+ * We use a bitmap as an allocator for these.
+ *
+ * Tables are allocated/created dynamically as devices are discovered,
+ * multiple TVT entries are used if needed
+ *
+ * When 64-bit DMA support is added we should simply use a separate set
+ * of larger regions (the HW supports 64 TVT entries). We can
+ * additionally create a bypass region in 64-bit space for performances
+ * though that would have a cost in term of security.
+ *
+ * If you set NUM_DMA32_REGIONS to 1, then a single table is shared
+ * for all devices and bus/dev/fn validation is disabled
+ *
+ * Note that a DMA32 region cannot be smaller than 256M so the max
+ * supported here for now is 8. We don't yet support sharing regions
+ * between multiple devices so the max number of devices supported
+ * is MAX_TABLE_TVT_COUNT.
+ */
+#define NUM_DMA32_REGIONS	1
+
+struct wsp_phb {
+	struct pci_controller	*hose;
+
+	/* Lock controlling access to the list of dma tables.
+	 * It does -not- protect against dma_* operations on
+	 * those tables, those should be stopped before an entry
+	 * is removed from the list.
+	 *
+	 * The lock is also used for error handling operations
+	 */
+	spinlock_t		lock;
+	struct list_head	dma_tables;
+	unsigned long		dma32_map;
+	unsigned long		dma32_base;
+	unsigned int		dma32_num_regions;
+	unsigned long		dma32_region_size;
+
+	/* Debugfs stuff */
+	struct dentry		*ddir;
+
+	struct list_head	all;
+};
+static LIST_HEAD(wsp_phbs);
+
+//#define cfg_debug(fmt...)	pr_debug(fmt)
+#define cfg_debug(fmt...)
+
+
+static int wsp_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+				  int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	int suboff;
+	u64 addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = PCIE_REG_CA_ENABLE |
+		((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+		((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+		((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+	suboff = offset & 3;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+
+	switch (len) {
+	case 1:
+		addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+			>> (suboff << 3)) & 0xff;
+		cfg_debug("read 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	case 2:
+		addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+			>> (suboff << 3)) & 0xffff;
+		cfg_debug("read 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	default:
+		addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA);
+		cfg_debug("read 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int wsp_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				   int offset, int len, u32 val)
+{
+	struct pci_controller *hose;
+	int suboff;
+	u64 addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = PCIE_REG_CA_ENABLE |
+		((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+		((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+		((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+	suboff = offset & 3;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		val <<= suboff << 3;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	case 2:
+		addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		val <<= suboff << 3;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	default:
+		addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops wsp_pcie_pci_ops =
+{
+	.read = wsp_pcie_read_config,
+	.write = wsp_pcie_write_config,
+};
+
+#define TCE_SHIFT		12
+#define TCE_PAGE_SIZE		(1 << TCE_SHIFT)
+#define TCE_PCI_WRITE		0x2		 /* write from PCI allowed */
+#define TCE_PCI_READ		0x1	 	 /* read from PCI allowed */
+#define TCE_RPN_MASK		0x3fffffffffful  /* 42-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT		12
+
+//#define dma_debug(fmt...)	pr_debug(fmt)
+#define dma_debug(fmt...)
+
+static int tce_build_wsp(struct iommu_table *tbl, long index, long npages,
+			   unsigned long uaddr, enum dma_data_direction direction,
+			   struct dma_attrs *attrs)
+{
+	struct wsp_dma_table *ptbl = container_of(tbl,
+						    struct wsp_dma_table,
+						    table);
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
+
+	proto_tce = TCE_PCI_READ;
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	proto_tce |= TCE_PCI_WRITE;
+#else
+	if (direction != DMA_TO_DEVICE)
+		proto_tce |= TCE_PCI_WRITE;
+#endif
+
+	/* XXX Make this faster by factoring out the page address for
+	 * within a TCE table
+	 */
+	while (npages--) {
+		/* We don't use it->base as the table can be scattered */
+		tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+		tcep += (index & 0xffff);
+
+		/* can't move this out since we might cross LMB boundary */
+		rpn = __pa(uaddr) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+		dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n",
+			  tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT);
+
+		uaddr += TCE_PAGE_SIZE;
+		index++;
+	}
+	return 0;
+}
+
+static void tce_free_wsp(struct iommu_table *tbl, long index, long npages)
+{
+	struct wsp_dma_table *ptbl = container_of(tbl,
+						    struct wsp_dma_table,
+						    table);
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	struct pci_controller *hose = ptbl->phb->hose;
+#endif
+	u64 *tcep;
+
+	/* XXX Make this faster by factoring out the page address for
+	 * within a TCE table. Also use line-kill option to kill multiple
+	 * TCEs at once
+	 */
+	while (npages--) {
+		/* We don't use it->base as the table can be scattered */
+		tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+		tcep += (index & 0xffff);
+		dma_debug("[DMA] TCE %p cleared\n", tcep);
+		*tcep = 0;
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+		/* Don't write there since it would pollute other MMIO accesses */
+		out_be64(hose->cfg_data + PCIE_REG_TCE_KILL,
+			 PCIE_REG_TCEKILL_SINGLE | PCIE_REG_TCEKILL_PS_4K |
+			 (__pa(tcep) & PCIE_REG_TCEKILL_ADDR_MASK));
+#endif
+		index++;
+	}
+}
+
+static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
+							    unsigned int region,
+							    struct pci_dev *validate)
+{
+	struct pci_controller *hose = phb->hose;
+	unsigned long size = phb->dma32_region_size;
+	unsigned long addr = phb->dma32_region_size * region + phb->dma32_base;
+	struct wsp_dma_table *tbl;
+	int tvts_per_table, i, tvt, nid;
+	unsigned long flags;
+
+	nid = of_node_to_nid(phb->hose->dn);
+
+	/* Calculate how many TVTs are needed */
+	tvts_per_table = size / 0x10000000;
+	if (tvts_per_table == 0)
+		tvts_per_table = 1;
+
+	/* Calculate the base TVT index. We know all tables have the same
+	 * size so we just do a simple multiply here
+	 */
+	tvt = region * tvts_per_table;
+
+	pr_debug("         Region : %d\n", region);
+	pr_debug("      DMA range : 0x%08lx..0x%08lx\n", addr, addr + size - 1);
+	pr_debug(" Number of TVTs : %d\n", tvts_per_table);
+	pr_debug("       Base TVT : %d\n", tvt);
+	pr_debug("         Node   : %d\n", nid);
+
+	tbl = kzalloc_node(sizeof(struct wsp_dma_table), GFP_KERNEL, nid);
+	if (!tbl)
+		return ERR_PTR(-ENOMEM);
+	tbl->phb = phb;
+
+	/* Create as many TVTs as needed, each represents 256M at most */
+	for (i = 0; i < tvts_per_table; i++) {
+		u64 tvt_data1, tvt_data0;
+
+		/* Allocate table. We use a 4K TCE size for now always so
+		 * one table is always 8 * (258M / 4K) == 512K
+		 */
+		tbl->tces[i] = alloc_pages_node(nid, GFP_KERNEL, get_order(0x80000));
+		if (tbl->tces[i] == NULL)
+			goto fail;
+		memset(page_address(tbl->tces[i]), 0, 0x80000);
+
+		pr_debug(" TCE table %d at : %p\n", i, page_address(tbl->tces[i]));
+
+		/* Table size. We currently set it to be the whole 256M region */
+		tvt_data0 = 2ull << IODA_TVT0_TCE_TABLE_SIZE_SHIFT;
+		/* IO page size set to 4K */
+		tvt_data1 = 1ull << IODA_TVT1_IO_PAGE_SIZE_SHIFT;
+		/* Shift in the address */
+		tvt_data0 |= __pa(page_address(tbl->tces[i])) << IODA_TVT0_TTA_SHIFT;
+
+		/* Validation stuff. We only validate fully bus/dev/fn for now
+		 * one day maybe we can group devices but that isn't the case
+		 * at the moment
+		 */
+		if (validate) {
+			tvt_data0 |= IODA_TVT0_BUSNUM_VALID_MASK;
+			tvt_data0 |= validate->bus->number;
+			tvt_data1 |= IODA_TVT1_DEVNUM_VALID;
+			tvt_data1 |= ((u64)PCI_SLOT(validate->devfn))
+				<< IODA_TVT1_DEVNUM_VALUE_SHIFT;
+			tvt_data1 |= IODA_TVT1_FUNCNUM_VALID;
+			tvt_data1 |= ((u64)PCI_FUNC(validate->devfn))
+				<< IODA_TVT1_FUNCNUM_VALUE_SHIFT;
+		}
+
+		/* XX PE number is always 0 for now */
+
+		/* Program the values using the PHB lock */
+		spin_lock_irqsave(&phb->lock, flags);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+			 (tvt + i) | PCIE_REG_IODA_AD_TBL_TVT);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, tvt_data1);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, tvt_data0);
+		spin_unlock_irqrestore(&phb->lock, flags);
+	}
+
+	/* Init bits and pieces */
+	tbl->table.it_blocksize = 16;
+	tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT;
+	tbl->table.it_size = size >> IOMMU_PAGE_SHIFT;
+
+	/*
+	 * It's already blank but we clear it anyway.
+	 * Consider an aditiona interface that makes cleaing optional
+	 */
+	iommu_init_table(&tbl->table, nid);
+
+	list_add(&tbl->link, &phb->dma_tables);
+	return tbl;
+
+ fail:
+	pr_debug("  Failed to allocate a 256M TCE table !\n");
+	for (i = 0; i < tvts_per_table; i++)
+		if (tbl->tces[i])
+			__free_pages(tbl->tces[i], get_order(0x80000));
+	kfree(tbl);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	struct dev_archdata *archdata = &pdev->dev.archdata;
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct wsp_phb *phb = hose->private_data;
+	struct wsp_dma_table *table = NULL;
+	unsigned long flags;
+	int i;
+
+	/* Don't assign an iommu table to a bridge */
+	if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+		return;
+
+	pr_debug("%s: Setting up DMA...\n", pci_name(pdev));
+
+	spin_lock_irqsave(&phb->lock, flags);
+
+	/* If only one region, check if it already exist */
+	if (phb->dma32_num_regions == 1) {
+		spin_unlock_irqrestore(&phb->lock, flags);
+		if (list_empty(&phb->dma_tables))
+			table = wsp_pci_create_dma32_table(phb, 0, NULL);
+		else
+			table = list_first_entry(&phb->dma_tables,
+						 struct wsp_dma_table,
+						 link);
+	} else {
+		/* else find a free region */
+		for (i = 0; i < phb->dma32_num_regions && !table; i++) {
+			if (__test_and_set_bit(i, &phb->dma32_map))
+				continue;
+			spin_unlock_irqrestore(&phb->lock, flags);
+			table = wsp_pci_create_dma32_table(phb, i, pdev);
+		}
+	}
+
+	/* Check if we got an error */
+	if (IS_ERR(table)) {
+		pr_err("%s: Failed to create DMA table, err %ld !\n",
+		       pci_name(pdev), PTR_ERR(table));
+		return;
+	}
+
+	/* Or a valid table */
+	if (table) {
+		pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n",
+			pci_name(pdev),
+			table->table.it_offset << IOMMU_PAGE_SHIFT,
+			(table->table.it_offset << IOMMU_PAGE_SHIFT)
+			+ phb->dma32_region_size - 1);
+		archdata->dma_data.iommu_table_base = &table->table;
+		return;
+	}
+
+	/* Or no room */
+	spin_unlock_irqrestore(&phb->lock, flags);
+	pr_err("%s: Out of DMA space !\n", pci_name(pdev));
+}
+
+static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
+{
+	u64 val;
+	int i;
+
+#define DUMP_REG(x) \
+	pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
+	/* WSP DD1 has a bogus class code by default in the PCI-E
+	 * root complex's built-in P2P bridge */
+	val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
+	pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
+	out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
+		 (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
+	pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
+#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	/* XXX Disable TCE caching, it doesn't work on DD1 */
+	out_be64(hose->cfg_data + 0xe50,
+		 in_be64(hose->cfg_data + 0xe50) | (3ull << 62));
+	printk("PCI-E DEBUG CONTROL 5 = 0x%llx\n", in_be64(hose->cfg_data + 0xe50));
+#endif
+
+	/* Configure M32A and IO. IO is hard wired to be 1M for now */
+	out_be64(hose->cfg_data + PCIE_REG_IO_BASE_ADDR, hose->io_base_phys);
+	out_be64(hose->cfg_data + PCIE_REG_IO_BASE_MASK,
+		 (~(hose->io_resource.end - hose->io_resource.start)) &
+		 0x3fffffff000ul);
+	out_be64(hose->cfg_data + PCIE_REG_IO_START_ADDR, 0 | 1);
+
+	out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_ADDR,
+		 hose->mem_resources[0].start);
+	printk("Want to write to M32A_BASE_MASK : 0x%llx\n",
+		 (~(hose->mem_resources[0].end -
+		    hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+	out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_MASK,
+		 (~(hose->mem_resources[0].end -
+		    hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+	out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR,
+		 (hose->mem_resources[0].start - hose->pci_mem_offset) | 1);
+
+	/* Clear all TVT entries
+	 *
+	 * XX Might get TVT count from device-tree
+	 */
+	for (i = 0; i < IODA_TVT_COUNT; i++) {
+		out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+			 PCIE_REG_IODA_AD_TBL_TVT | i);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, 0);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, 0);
+	}
+
+	/* Kill the TCE cache */
+	out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG,
+		 in_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG) |
+		 PCIE_REG_PHBC_64B_TCE_EN);
+
+	/* Enable 32 & 64-bit MSIs, IO space and M32A */
+	val = PCIE_REG_PHBC_32BIT_MSI_EN |
+	      PCIE_REG_PHBC_IO_EN |
+	      PCIE_REG_PHBC_64BIT_MSI_EN |
+	      PCIE_REG_PHBC_M32A_EN;
+	if (iommu_is_off)
+		val |= PCIE_REG_PHBC_DMA_XLATE_BYPASS;
+	pr_debug("Will write config: 0x%llx\n", val);
+	out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, val);
+
+	/* Enable error reporting */
+	out_be64(hose->cfg_data + 0xe00,
+		 in_be64(hose->cfg_data + 0xe00) | 0x0008000000000000ull);
+
+	/* Mask an error that's generated when doing config space probe
+	 *
+	 * XXX Maybe we should only mask it around config space cycles... that or
+	 * ignore it when we know we had a config space cycle recently ?
+	 */
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS_MASK, 0x8000000000000000ull);
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS_MASK, 0x8000000000000000ull);
+
+	/* Enable UTL errors, for now, all of them got to UTL irq 1
+	 *
+	 * We similarily mask one UTL error caused apparently during normal
+	 * probing. We also mask the link up error
+	 */
+	out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_ERR_SEV, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_RC_ERR_SEVERITY, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_ERROR_SEV, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_IRQ_EN, 0xffffffff00000000ull);
+	out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_IRQ_EN, 0xff5fffff00000000ull);
+	out_be64(hose->cfg_data + PCIE_UTL_EP_ERR_IRQ_EN, 0xffffffff00000000ull);
+
+	DUMP_REG(PCIE_REG_IO_BASE_ADDR);
+	DUMP_REG(PCIE_REG_IO_BASE_MASK);
+	DUMP_REG(PCIE_REG_IO_START_ADDR);
+	DUMP_REG(PCIE_REG_M32A_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M32A_BASE_MASK);
+	DUMP_REG(PCIE_REG_M32A_START_ADDR);
+	DUMP_REG(PCIE_REG_M32B_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M32B_BASE_MASK);
+	DUMP_REG(PCIE_REG_M32B_START_ADDR);
+	DUMP_REG(PCIE_REG_M64_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M64_BASE_MASK);
+	DUMP_REG(PCIE_REG_M64_START_ADDR);
+	DUMP_REG(PCIE_REG_PHB_CONFIG);
+}
+
+static void wsp_pci_wait_io_idle(struct wsp_phb *phb, unsigned long port)
+{
+	u64 val;
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		val = in_be64(phb->hose->cfg_data + 0xe08);
+		if ((val & 0x1900000000000000ull) == 0x0100000000000000ull)
+			return;
+		udelay(1);
+	}
+	pr_warning("PCI IO timeout on domain %d port 0x%lx\n",
+		   phb->hose->global_number, port);
+}
+
+#define DEF_PCI_AC_RET_pio(name, ret, at, al, aa)		\
+static ret wsp_pci_##name at					\
+{								\
+	struct iowa_bus *bus;					\
+	struct wsp_phb *phb;					\
+	unsigned long flags;					\
+	ret rval;						\
+	bus = iowa_pio_find_bus(aa);				\
+	WARN_ON(!bus);						\
+	phb = bus->private;					\
+	spin_lock_irqsave(&phb->lock, flags);			\
+	wsp_pci_wait_io_idle(phb, aa);				\
+	rval = __do_##name al;					\
+	spin_unlock_irqrestore(&phb->lock, flags);		\
+	return rval;						\
+}
+
+#define DEF_PCI_AC_NORET_pio(name, at, al, aa)			\
+static void wsp_pci_##name at					\
+{								\
+	struct iowa_bus *bus;					\
+	struct wsp_phb *phb;					\
+	unsigned long flags;					\
+	bus = iowa_pio_find_bus(aa);				\
+	WARN_ON(!bus);						\
+	phb = bus->private;					\
+	spin_lock_irqsave(&phb->lock, flags);			\
+	wsp_pci_wait_io_idle(phb, aa);				\
+	__do_##name al;						\
+	spin_unlock_irqrestore(&phb->lock, flags);		\
+}
+
+#define DEF_PCI_AC_RET_mem(name, ret, at, al, aa)
+#define DEF_PCI_AC_NORET_mem(name, at, al, aa)
+
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
+	DEF_PCI_AC_RET_##space(name, ret, at, al, aa)
+
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
+	DEF_PCI_AC_NORET_##space(name, at, al, aa)		\
+
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+static struct ppc_pci_io wsp_pci_iops = {
+	.inb = wsp_pci_inb,
+	.inw = wsp_pci_inw,
+	.inl = wsp_pci_inl,
+	.outb = wsp_pci_outb,
+	.outw = wsp_pci_outw,
+	.outl = wsp_pci_outl,
+	.insb = wsp_pci_insb,
+	.insw = wsp_pci_insw,
+	.insl = wsp_pci_insl,
+	.outsb = wsp_pci_outsb,
+	.outsw = wsp_pci_outsw,
+	.outsl = wsp_pci_outsl,
+};
+
+static int __init wsp_setup_one_phb(struct device_node *np)
+{
+	struct pci_controller *hose;
+	struct wsp_phb *phb;
+
+	pr_info("PCI: Setting up PCIe host bridge 0x%s\n", np->full_name);
+
+	phb = zalloc_maybe_bootmem(sizeof(struct wsp_phb), GFP_KERNEL);
+	if (!phb)
+		return -ENOMEM;
+	hose = pcibios_alloc_controller(np);
+	if (!hose) {
+		/* Can't really free the phb */
+		return -ENOMEM;
+	}
+	hose->private_data = phb;
+	phb->hose = hose;
+
+	INIT_LIST_HEAD(&phb->dma_tables);
+	spin_lock_init(&phb->lock);
+
+	/* XXX Use bus-range property ? */
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* We use cfg_data as the address for the whole bridge MMIO space
+	 */
+	hose->cfg_data = of_iomap(hose->dn, 0);
+
+	pr_debug("PCIe registers mapped at 0x%p\n", hose->cfg_data);
+
+	/* Get the ranges of the device-tree */
+	pci_process_bridge_OF_ranges(hose, np, 0);
+
+	/* XXX Force re-assigning of everything for now */
+	pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC |
+		      PCI_ENABLE_PROC_DOMAINS);
+	pci_probe_only = 0;
+
+	/* Calculate how the TCE space is divided */
+	phb->dma32_base		= 0;
+	phb->dma32_num_regions	= NUM_DMA32_REGIONS;
+	if (phb->dma32_num_regions > MAX_TABLE_TVT_COUNT) {
+		pr_warning("IOMMU: Clamped to %d DMA32 regions\n",
+			   MAX_TABLE_TVT_COUNT);
+		phb->dma32_num_regions = MAX_TABLE_TVT_COUNT;
+	}
+	phb->dma32_region_size	= 0x80000000 / phb->dma32_num_regions;
+
+	BUG_ON(!is_power_of_2(phb->dma32_region_size));
+
+	/* Setup config ops */
+	hose->ops = &wsp_pcie_pci_ops;
+
+	/* Configure the HW */
+	wsp_pcie_configure_hw(hose);
+
+	/* Instanciate IO workarounds */
+	iowa_register_bus(hose, &wsp_pci_iops, NULL, phb);
+#ifdef CONFIG_PCI_MSI
+	wsp_setup_phb_msi(hose);
+#endif
+
+	/* Add to global list */
+	list_add(&phb->all, &wsp_phbs);
+
+	return 0;
+}
+
+void __init wsp_setup_pci(void)
+{
+	struct device_node *np;
+	int rc;
+
+	/* Find host bridges */
+	for_each_compatible_node(np, "pciex", PCIE_COMPATIBLE) {
+		rc = wsp_setup_one_phb(np);
+		if (rc)
+			pr_err("Failed to setup PCIe bridge %s, rc=%d\n",
+			       np->full_name, rc);
+	}
+
+	/* Establish device-tree linkage */
+	pci_devs_phb_init();
+
+	/* Set DMA ops to use TCEs */
+	if (iommu_is_off) {
+		pr_info("PCI-E: Disabled TCEs, using direct DMA\n");
+		set_pci_dma_ops(&dma_direct_ops);
+	} else {
+		ppc_md.pci_dma_dev_setup = wsp_pci_dma_dev_setup;
+		ppc_md.tce_build = tce_build_wsp;
+		ppc_md.tce_free = tce_free_wsp;
+		set_pci_dma_ops(&dma_iommu_ops);
+	}
+}
+
+#define err_debug(fmt...)	pr_debug(fmt)
+//#define err_debug(fmt...)
+
+static int __init wsp_pci_get_err_irq_no_dt(struct device_node *np)
+{
+	const u32 *prop;
+	int hw_irq;
+
+	/* Ok, no interrupts property, let's try to find our child P2P */
+	np = of_get_next_child(np, NULL);
+	if (np == NULL)
+		return 0;
+
+	/* Grab it's interrupt map */
+	prop = of_get_property(np, "interrupt-map", NULL);
+	if (prop == NULL)
+		return 0;
+
+	/* Grab one of the interrupts in there, keep the low 4 bits */
+	hw_irq = prop[5] & 0xf;
+
+	/* 0..4 for PHB 0 and 5..9 for PHB 1 */
+	if (hw_irq < 5)
+		hw_irq = 4;
+	else
+		hw_irq = 9;
+	hw_irq |= prop[5] & ~0xf;
+
+	err_debug("PCI: Using 0x%x as error IRQ for %s\n",
+		  hw_irq, np->parent->full_name);
+	return irq_create_mapping(NULL, hw_irq);
+}
+
+static const struct {
+	u32 offset;
+	const char *name;
+} wsp_pci_regs[] = {
+#define DREG(x) { PCIE_REG_##x, #x }
+#define DUTL(x) { PCIE_UTL_##x, "UTL_" #x }
+	/* Architected registers except CONFIG_ and IODA
+         * to avoid side effects
+	 */
+	DREG(DMA_CHAN_STATUS),
+	DREG(CPU_LOADSTORE_STATUS),
+	DREG(LOCK0),
+	DREG(LOCK1),
+	DREG(PHB_CONFIG),
+	DREG(IO_BASE_ADDR),
+	DREG(IO_BASE_MASK),
+	DREG(IO_START_ADDR),
+	DREG(M32A_BASE_ADDR),
+	DREG(M32A_BASE_MASK),
+	DREG(M32A_START_ADDR),
+	DREG(M32B_BASE_ADDR),
+	DREG(M32B_BASE_MASK),
+	DREG(M32B_START_ADDR),
+	DREG(M64_BASE_ADDR),
+	DREG(M64_BASE_MASK),
+	DREG(M64_START_ADDR),
+	DREG(TCE_KILL),
+	DREG(LOCK2),
+	DREG(PHB_GEN_CAP),
+	DREG(PHB_TCE_CAP),
+	DREG(PHB_IRQ_CAP),
+	DREG(PHB_EEH_CAP),
+	DREG(PAPR_ERR_INJ_CONTROL),
+	DREG(PAPR_ERR_INJ_ADDR),
+	DREG(PAPR_ERR_INJ_MASK),
+
+	/* UTL core regs */
+	DUTL(SYS_BUS_CONTROL),
+	DUTL(STATUS),
+	DUTL(SYS_BUS_AGENT_STATUS),
+	DUTL(SYS_BUS_AGENT_ERR_SEV),
+	DUTL(SYS_BUS_AGENT_IRQ_EN),
+	DUTL(SYS_BUS_BURST_SZ_CONF),
+	DUTL(REVISION_ID),
+	DUTL(OUT_POST_HDR_BUF_ALLOC),
+	DUTL(OUT_POST_DAT_BUF_ALLOC),
+	DUTL(IN_POST_HDR_BUF_ALLOC),
+	DUTL(IN_POST_DAT_BUF_ALLOC),
+	DUTL(OUT_NP_BUF_ALLOC),
+	DUTL(IN_NP_BUF_ALLOC),
+	DUTL(PCIE_TAGS_ALLOC),
+	DUTL(GBIF_READ_TAGS_ALLOC),
+
+	DUTL(PCIE_PORT_CONTROL),
+	DUTL(PCIE_PORT_STATUS),
+	DUTL(PCIE_PORT_ERROR_SEV),
+	DUTL(PCIE_PORT_IRQ_EN),
+	DUTL(RC_STATUS),
+	DUTL(RC_ERR_SEVERITY),
+	DUTL(RC_IRQ_EN),
+	DUTL(EP_STATUS),
+	DUTL(EP_ERR_SEVERITY),
+	DUTL(EP_ERR_IRQ_EN),
+	DUTL(PCI_PM_CTRL1),
+	DUTL(PCI_PM_CTRL2),
+
+	/* PCIe stack regs */
+	DREG(SYSTEM_CONFIG1),
+	DREG(SYSTEM_CONFIG2),
+	DREG(EP_SYSTEM_CONFIG),
+	DREG(EP_FLR),
+	DREG(EP_BAR_CONFIG),
+	DREG(LINK_CONFIG),
+	DREG(PM_CONFIG),
+	DREG(DLP_CONTROL),
+	DREG(DLP_STATUS),
+	DREG(ERR_REPORT_CONTROL),
+	DREG(SLOT_CONTROL1),
+	DREG(SLOT_CONTROL2),
+	DREG(UTL_CONFIG),
+	DREG(BUFFERS_CONFIG),
+	DREG(ERROR_INJECT),
+	DREG(SRIOV_CONFIG),
+	DREG(PF0_SRIOV_STATUS),
+	DREG(PF1_SRIOV_STATUS),
+	DREG(PORT_NUMBER),
+	DREG(POR_SYSTEM_CONFIG),
+
+	/* Internal logic regs */
+	DREG(PHB_VERSION),
+	DREG(RESET),
+	DREG(PHB_CONTROL),
+	DREG(PHB_TIMEOUT_CONTROL1),
+	DREG(PHB_QUIESCE_DMA),
+	DREG(PHB_DMA_READ_TAG_ACTV),
+	DREG(PHB_TCE_READ_TAG_ACTV),
+
+	/* FIR registers */
+	DREG(LEM_FIR_ACCUM),
+	DREG(LEM_FIR_AND_MASK),
+	DREG(LEM_FIR_OR_MASK),
+	DREG(LEM_ACTION0),
+	DREG(LEM_ACTION1),
+	DREG(LEM_ERROR_MASK),
+	DREG(LEM_ERROR_AND_MASK),
+	DREG(LEM_ERROR_OR_MASK),
+
+	/* Error traps registers */
+	DREG(PHB_ERR_STATUS),
+	DREG(PHB_ERR_STATUS),
+	DREG(PHB_ERR1_STATUS),
+	DREG(PHB_ERR_INJECT),
+	DREG(PHB_ERR_LEM_ENABLE),
+	DREG(PHB_ERR_IRQ_ENABLE),
+	DREG(PHB_ERR_FREEZE_ENABLE),
+	DREG(PHB_ERR_SIDE_ENABLE),
+	DREG(PHB_ERR_LOG_0),
+	DREG(PHB_ERR_LOG_1),
+	DREG(PHB_ERR_STATUS_MASK),
+	DREG(PHB_ERR1_STATUS_MASK),
+	DREG(MMIO_ERR_STATUS),
+	DREG(MMIO_ERR1_STATUS),
+	DREG(MMIO_ERR_INJECT),
+	DREG(MMIO_ERR_LEM_ENABLE),
+	DREG(MMIO_ERR_IRQ_ENABLE),
+	DREG(MMIO_ERR_FREEZE_ENABLE),
+	DREG(MMIO_ERR_SIDE_ENABLE),
+	DREG(MMIO_ERR_LOG_0),
+	DREG(MMIO_ERR_LOG_1),
+	DREG(MMIO_ERR_STATUS_MASK),
+	DREG(MMIO_ERR1_STATUS_MASK),
+	DREG(DMA_ERR_STATUS),
+	DREG(DMA_ERR1_STATUS),
+	DREG(DMA_ERR_INJECT),
+	DREG(DMA_ERR_LEM_ENABLE),
+	DREG(DMA_ERR_IRQ_ENABLE),
+	DREG(DMA_ERR_FREEZE_ENABLE),
+	DREG(DMA_ERR_SIDE_ENABLE),
+	DREG(DMA_ERR_LOG_0),
+	DREG(DMA_ERR_LOG_1),
+	DREG(DMA_ERR_STATUS_MASK),
+	DREG(DMA_ERR1_STATUS_MASK),
+
+	/* Debug and Trace registers */
+	DREG(PHB_DEBUG_CONTROL0),
+	DREG(PHB_DEBUG_STATUS0),
+	DREG(PHB_DEBUG_CONTROL1),
+	DREG(PHB_DEBUG_STATUS1),
+	DREG(PHB_DEBUG_CONTROL2),
+	DREG(PHB_DEBUG_STATUS2),
+	DREG(PHB_DEBUG_CONTROL3),
+	DREG(PHB_DEBUG_STATUS3),
+	DREG(PHB_DEBUG_CONTROL4),
+	DREG(PHB_DEBUG_STATUS4),
+	DREG(PHB_DEBUG_CONTROL5),
+	DREG(PHB_DEBUG_STATUS5),
+
+	/* Don't seem to exist ...
+	DREG(PHB_DEBUG_CONTROL6),
+	DREG(PHB_DEBUG_STATUS6),
+	*/
+};
+
+static int wsp_pci_regs_show(struct seq_file *m, void *private)
+{
+	struct wsp_phb *phb = m->private;
+	struct pci_controller *hose = phb->hose;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+		/* Skip write-only regs */
+		if (wsp_pci_regs[i].offset == 0xc08 ||
+		    wsp_pci_regs[i].offset == 0xc10 ||
+		    wsp_pci_regs[i].offset == 0xc38 ||
+		    wsp_pci_regs[i].offset == 0xc40)
+			continue;
+		seq_printf(m, "0x%03x: 0x%016llx %s\n",
+			   wsp_pci_regs[i].offset,
+			   in_be64(hose->cfg_data + wsp_pci_regs[i].offset),
+			   wsp_pci_regs[i].name);
+	}
+	return 0;
+}
+
+static int wsp_pci_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wsp_pci_regs_show, inode->i_private);
+}
+
+static const struct file_operations wsp_pci_regs_fops = {
+	.open = wsp_pci_regs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int wsp_pci_reg_set(void *data, u64 val)
+{
+	out_be64((void __iomem *)data, val);
+	return 0;
+}
+
+static int wsp_pci_reg_get(void *data, u64 *val)
+{
+	*val = in_be64((void __iomem *)data);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(wsp_pci_reg_fops, wsp_pci_reg_get, wsp_pci_reg_set, "0x%llx\n");
+
+static irqreturn_t wsp_pci_err_irq(int irq, void *dev_id)
+{
+	struct wsp_phb *phb = dev_id;
+	struct pci_controller *hose = phb->hose;
+	irqreturn_t handled = IRQ_NONE;
+	struct wsp_pcie_err_log_data ed;
+
+	pr_err("PCI: Error interrupt on %s (PHB %d)\n",
+	       hose->dn->full_name, hose->global_number);
+ again:
+	memset(&ed, 0, sizeof(ed));
+
+	/* Read and clear UTL errors */
+	ed.utl_sys_err = in_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS);
+	if (ed.utl_sys_err)
+		out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS, ed.utl_sys_err);
+	ed.utl_port_err = in_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS);
+	if (ed.utl_port_err)
+		out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS, ed.utl_port_err);
+	ed.utl_rc_err = in_be64(hose->cfg_data + PCIE_UTL_RC_STATUS);
+	if (ed.utl_rc_err)
+		out_be64(hose->cfg_data + PCIE_UTL_RC_STATUS, ed.utl_rc_err);
+
+	/* Read and clear main trap errors */
+	ed.phb_err = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS);
+	if (ed.phb_err) {
+		ed.phb_err1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS);
+		ed.phb_log0 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_0);
+		ed.phb_log1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS, 0);
+	}
+	ed.mmio_err = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS);
+	if (ed.mmio_err) {
+		ed.mmio_err1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS);
+		ed.mmio_log0 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_0);
+		ed.mmio_log1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS, 0);
+	}
+	ed.dma_err = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS);
+	if (ed.dma_err) {
+		ed.dma_err1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS);
+		ed.dma_log0 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_0);
+		ed.dma_log1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS, 0);
+	}
+
+	/* Now print things out */
+	if (ed.phb_err) {
+		pr_err("   PHB Error Status      : 0x%016llx\n", ed.phb_err);
+		pr_err("   PHB First Error Status: 0x%016llx\n", ed.phb_err1);
+		pr_err("   PHB Error Log 0       : 0x%016llx\n", ed.phb_log0);
+		pr_err("   PHB Error Log 1       : 0x%016llx\n", ed.phb_log1);
+	}
+	if (ed.mmio_err) {
+		pr_err("  MMIO Error Status      : 0x%016llx\n", ed.mmio_err);
+		pr_err("  MMIO First Error Status: 0x%016llx\n", ed.mmio_err1);
+		pr_err("  MMIO Error Log 0       : 0x%016llx\n", ed.mmio_log0);
+		pr_err("  MMIO Error Log 1       : 0x%016llx\n", ed.mmio_log1);
+	}
+	if (ed.dma_err) {
+		pr_err("   DMA Error Status      : 0x%016llx\n", ed.dma_err);
+		pr_err("   DMA First Error Status: 0x%016llx\n", ed.dma_err1);
+		pr_err("   DMA Error Log 0       : 0x%016llx\n", ed.dma_log0);
+		pr_err("   DMA Error Log 1       : 0x%016llx\n", ed.dma_log1);
+	}
+	if (ed.utl_sys_err)
+		pr_err("   UTL Sys Error Status  : 0x%016llx\n", ed.utl_sys_err);
+	if (ed.utl_port_err)
+		pr_err("   UTL Port Error Status : 0x%016llx\n", ed.utl_port_err);
+	if (ed.utl_rc_err)
+		pr_err("   UTL RC Error Status   : 0x%016llx\n", ed.utl_rc_err);
+
+	/* Interrupts are caused by the error traps. If we had any error there
+	 * we loop again in case the UTL buffered some new stuff between
+	 * going there and going to the traps
+	 */
+	if (ed.dma_err || ed.mmio_err || ed.phb_err) {
+		handled = IRQ_HANDLED;
+		goto again;
+	}
+	return handled;
+}
+
+static void __init wsp_setup_pci_err_reporting(struct wsp_phb *phb)
+{
+	struct pci_controller *hose = phb->hose;
+	int err_irq, i, rc;
+	char fname[16];
+
+	/* Create a debugfs file for that PHB */
+	sprintf(fname, "phb%d", phb->hose->global_number);
+	phb->ddir = debugfs_create_dir(fname, powerpc_debugfs_root);
+
+	/* Some useful debug output */
+	if (phb->ddir) {
+		struct dentry *d = debugfs_create_dir("regs", phb->ddir);
+		char tmp[64];
+
+		for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+			sprintf(tmp, "%03x_%s", wsp_pci_regs[i].offset,
+				wsp_pci_regs[i].name);
+			debugfs_create_file(tmp, 0600, d,
+					    hose->cfg_data + wsp_pci_regs[i].offset,
+					    &wsp_pci_reg_fops);
+		}
+		debugfs_create_file("all_regs", 0600, phb->ddir, phb, &wsp_pci_regs_fops);
+	}
+
+	/* Find the IRQ number for that PHB */
+	err_irq = irq_of_parse_and_map(hose->dn, 0);
+	if (err_irq == 0)
+		/* XXX Error IRQ lacking from device-tree */
+		err_irq = wsp_pci_get_err_irq_no_dt(hose->dn);
+	if (err_irq == 0) {
+		pr_err("PCI: Failed to fetch error interrupt for %s\n",
+		       hose->dn->full_name);
+		return;
+	}
+	/* Request it */
+	rc = request_irq(err_irq, wsp_pci_err_irq, 0, "wsp_pci error", phb);
+	if (rc) {
+		pr_err("PCI: Failed to request interrupt for %s\n",
+		       hose->dn->full_name);
+	}
+	/* Enable interrupts for all errors for now */
+	out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+	out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+}
+
+/*
+ * This is called later to hookup with the error interrupt
+ */
+static int __init wsp_setup_pci_late(void)
+{
+	struct wsp_phb *phb;
+
+	list_for_each_entry(phb, &wsp_phbs, all)
+		wsp_setup_pci_err_reporting(phb);
+
+	return 0;
+}
+arch_initcall(wsp_setup_pci_late);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp_pci.h linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp_pci.h
--- linux-libre-3.1-gnu1/arch/powerpc/platforms/wsp/wsp_pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/platforms/wsp/wsp_pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * 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 __WSP_PCI_H
+#define __WSP_PCI_H
+
+/* Architected registers */
+#define PCIE_REG_DMA_CHAN_STATUS	0x110
+#define PCIE_REG_CPU_LOADSTORE_STATUS	0x120
+
+#define PCIE_REG_CONFIG_DATA		0x130
+#define PCIE_REG_LOCK0			0x138
+#define PCIE_REG_CONFIG_ADDRESS		0x140
+#define   PCIE_REG_CA_ENABLE			0x8000000000000000ull
+#define	  PCIE_REG_CA_BUS_MASK			0x0ff0000000000000ull
+#define   PCIE_REG_CA_BUS_SHIFT			(20+32)
+#define   PCIE_REG_CA_DEV_MASK			0x000f800000000000ull
+#define   PCIE_REG_CA_DEV_SHIFT			(15+32)
+#define   PCIE_REG_CA_FUNC_MASK			0x0000700000000000ull
+#define   PCIE_REG_CA_FUNC_SHIFT		(12+32)
+#define   PCIE_REG_CA_REG_MASK			0x00000fff00000000ull
+#define   PCIE_REG_CA_REG_SHIFT			( 0+32)
+#define   PCIE_REG_CA_BE_MASK			0x00000000f0000000ull
+#define   PCIE_REG_CA_BE_SHIFT			(   28)
+#define PCIE_REG_LOCK1			0x148
+
+#define PCIE_REG_PHB_CONFIG		0x160
+#define   PCIE_REG_PHBC_64B_TCE_EN		0x2000000000000000ull
+#define   PCIE_REG_PHBC_MMIO_DMA_FREEZE_EN	0x1000000000000000ull
+#define   PCIE_REG_PHBC_32BIT_MSI_EN		0x0080000000000000ull
+#define   PCIE_REG_PHBC_M64_EN			0x0040000000000000ull
+#define   PCIE_REG_PHBC_IO_EN			0x0008000000000000ull
+#define   PCIE_REG_PHBC_64BIT_MSI_EN		0x0002000000000000ull
+#define   PCIE_REG_PHBC_M32A_EN			0x0000800000000000ull
+#define   PCIE_REG_PHBC_M32B_EN			0x0000400000000000ull
+#define   PCIE_REG_PHBC_MSI_PE_VALIDATE		0x0000200000000000ull
+#define   PCIE_REG_PHBC_DMA_XLATE_BYPASS	0x0000100000000000ull
+
+#define PCIE_REG_IO_BASE_ADDR		0x170
+#define PCIE_REG_IO_BASE_MASK		0x178
+#define PCIE_REG_IO_START_ADDR		0x180
+
+#define PCIE_REG_M32A_BASE_ADDR		0x190
+#define PCIE_REG_M32A_BASE_MASK		0x198
+#define PCIE_REG_M32A_START_ADDR	0x1a0
+
+#define PCIE_REG_M32B_BASE_ADDR		0x1b0
+#define PCIE_REG_M32B_BASE_MASK		0x1b8
+#define PCIE_REG_M32B_START_ADDR	0x1c0
+
+#define PCIE_REG_M64_BASE_ADDR		0x1e0
+#define PCIE_REG_M64_BASE_MASK		0x1e8
+#define PCIE_REG_M64_START_ADDR		0x1f0
+
+#define PCIE_REG_TCE_KILL		0x210
+#define   PCIE_REG_TCEKILL_SINGLE	0x8000000000000000ull
+#define   PCIE_REG_TCEKILL_ADDR_MASK	0x000003fffffffff8ull
+#define   PCIE_REG_TCEKILL_PS_4K	0
+#define   PCIE_REG_TCEKILL_PS_64K	1
+#define   PCIE_REG_TCEKILL_PS_16M	2
+#define   PCIE_REG_TCEKILL_PS_16G	3
+
+#define PCIE_REG_IODA_ADDR		0x220
+#define   PCIE_REG_IODA_AD_AUTOINC	0x8000000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_MVT	0x0005000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PELT	0x0006000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTA	0x0007000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTB	0x0008000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TVT	0x0009000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TCE	0x000a000000000000ull
+#define PCIE_REG_IODA_DATA0		0x228
+#define PCIE_REG_IODA_DATA1		0x230
+
+#define PCIE_REG_LOCK2			0x240
+
+#define PCIE_REG_PHB_GEN_CAP		0x250
+#define PCIE_REG_PHB_TCE_CAP		0x258
+#define PCIE_REG_PHB_IRQ_CAP		0x260
+#define PCIE_REG_PHB_EEH_CAP		0x268
+
+#define PCIE_REG_PAPR_ERR_INJ_CONTROL	0x2b0
+#define PCIE_REG_PAPR_ERR_INJ_ADDR	0x2b8
+#define PCIE_REG_PAPR_ERR_INJ_MASK	0x2c0
+
+
+#define PCIE_REG_SYS_CFG1		0x600
+#define   PCIE_REG_SYS_CFG1_CLASS_CODE	0x0000000000ffffffull
+
+#define IODA_TVT0_TTA_MASK		0x000fffffffff0000ull
+#define IODA_TVT0_TTA_SHIFT		4
+#define IODA_TVT0_BUSNUM_VALID_MASK	0x000000000000e000ull
+#define IODA_TVT0_TCE_TABLE_SIZE_MASK	0x0000000000001f00ull
+#define IODA_TVT0_TCE_TABLE_SIZE_SHIFT	8
+#define IODA_TVT0_BUSNUM_VALUE_MASK	0x00000000000000ffull
+#define IODA_TVT0_BUSNUM_VALID_SHIFT	0
+#define IODA_TVT1_DEVNUM_VALID		0x2000000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_MASK	0x1f00000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_SHIFT	56
+#define IODA_TVT1_FUNCNUM_VALID		0x0008000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_MASK	0x0007000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_SHIFT	48
+#define IODA_TVT1_IO_PAGE_SIZE_MASK	0x00001f0000000000ull
+#define IODA_TVT1_IO_PAGE_SIZE_SHIFT	40
+#define IODA_TVT1_PE_NUMBER_MASK	0x000000000000003full
+#define IODA_TVT1_PE_NUMBER_SHIFT	0
+
+#define IODA_TVT_COUNT			64
+
+/* UTL Core registers */
+#define PCIE_UTL_SYS_BUS_CONTROL	0x400
+#define PCIE_UTL_STATUS			0x408
+#define PCIE_UTL_SYS_BUS_AGENT_STATUS	0x410
+#define PCIE_UTL_SYS_BUS_AGENT_ERR_SEV	0x418
+#define PCIE_UTL_SYS_BUS_AGENT_IRQ_EN	0x420
+#define PCIE_UTL_SYS_BUS_BURST_SZ_CONF	0x440
+#define PCIE_UTL_REVISION_ID		0x448
+
+#define PCIE_UTL_OUT_POST_HDR_BUF_ALLOC	0x4c0
+#define PCIE_UTL_OUT_POST_DAT_BUF_ALLOC	0x4d0
+#define PCIE_UTL_IN_POST_HDR_BUF_ALLOC	0x4e0
+#define PCIE_UTL_IN_POST_DAT_BUF_ALLOC	0x4f0
+#define PCIE_UTL_OUT_NP_BUF_ALLOC	0x500
+#define PCIE_UTL_IN_NP_BUF_ALLOC	0x510
+#define PCIE_UTL_PCIE_TAGS_ALLOC	0x520
+#define PCIE_UTL_GBIF_READ_TAGS_ALLOC	0x530
+
+#define PCIE_UTL_PCIE_PORT_CONTROL	0x540
+#define PCIE_UTL_PCIE_PORT_STATUS	0x548
+#define PCIE_UTL_PCIE_PORT_ERROR_SEV	0x550
+#define PCIE_UTL_PCIE_PORT_IRQ_EN	0x558
+#define PCIE_UTL_RC_STATUS		0x560
+#define PCIE_UTL_RC_ERR_SEVERITY	0x568
+#define PCIE_UTL_RC_IRQ_EN		0x570
+#define PCIE_UTL_EP_STATUS		0x578
+#define PCIE_UTL_EP_ERR_SEVERITY	0x580
+#define PCIE_UTL_EP_ERR_IRQ_EN		0x588
+
+#define PCIE_UTL_PCI_PM_CTRL1		0x590
+#define PCIE_UTL_PCI_PM_CTRL2		0x598
+
+/* PCIe stack registers */
+#define PCIE_REG_SYSTEM_CONFIG1		0x600
+#define PCIE_REG_SYSTEM_CONFIG2		0x608
+#define PCIE_REG_EP_SYSTEM_CONFIG	0x618
+#define PCIE_REG_EP_FLR			0x620
+#define PCIE_REG_EP_BAR_CONFIG		0x628
+#define PCIE_REG_LINK_CONFIG		0x630
+#define PCIE_REG_PM_CONFIG		0x640
+#define PCIE_REG_DLP_CONTROL		0x650
+#define PCIE_REG_DLP_STATUS		0x658
+#define PCIE_REG_ERR_REPORT_CONTROL	0x660
+#define PCIE_REG_SLOT_CONTROL1		0x670
+#define PCIE_REG_SLOT_CONTROL2		0x678
+#define PCIE_REG_UTL_CONFIG		0x680
+#define PCIE_REG_BUFFERS_CONFIG		0x690
+#define PCIE_REG_ERROR_INJECT		0x698
+#define PCIE_REG_SRIOV_CONFIG		0x6a0
+#define PCIE_REG_PF0_SRIOV_STATUS	0x6a8
+#define PCIE_REG_PF1_SRIOV_STATUS	0x6b0
+#define PCIE_REG_PORT_NUMBER		0x700
+#define PCIE_REG_POR_SYSTEM_CONFIG	0x708
+
+/* PHB internal logic registers */
+#define PCIE_REG_PHB_VERSION		0x800
+#define PCIE_REG_RESET			0x808
+#define PCIE_REG_PHB_CONTROL		0x810
+#define PCIE_REG_PHB_TIMEOUT_CONTROL1	0x878
+#define PCIE_REG_PHB_QUIESCE_DMA	0x888
+#define PCIE_REG_PHB_DMA_READ_TAG_ACTV	0x900
+#define PCIE_REG_PHB_TCE_READ_TAG_ACTV	0x908
+
+/* FIR registers */
+#define PCIE_REG_LEM_FIR_ACCUM		0xc00
+#define PCIE_REG_LEM_FIR_AND_MASK	0xc08
+#define PCIE_REG_LEM_FIR_OR_MASK	0xc10
+#define PCIE_REG_LEM_ACTION0		0xc18
+#define PCIE_REG_LEM_ACTION1		0xc20
+#define PCIE_REG_LEM_ERROR_MASK		0xc30
+#define PCIE_REG_LEM_ERROR_AND_MASK	0xc38
+#define PCIE_REG_LEM_ERROR_OR_MASK	0xc40
+
+/* PHB Error registers */
+#define PCIE_REG_PHB_ERR_STATUS		0xc80
+#define PCIE_REG_PHB_ERR1_STATUS	0xc88
+#define PCIE_REG_PHB_ERR_INJECT		0xc90
+#define PCIE_REG_PHB_ERR_LEM_ENABLE	0xc98
+#define PCIE_REG_PHB_ERR_IRQ_ENABLE	0xca0
+#define PCIE_REG_PHB_ERR_FREEZE_ENABLE	0xca8
+#define PCIE_REG_PHB_ERR_SIDE_ENABLE	0xcb8
+#define PCIE_REG_PHB_ERR_LOG_0		0xcc0
+#define PCIE_REG_PHB_ERR_LOG_1		0xcc8
+#define PCIE_REG_PHB_ERR_STATUS_MASK	0xcd0
+#define PCIE_REG_PHB_ERR1_STATUS_MASK	0xcd8
+
+#define PCIE_REG_MMIO_ERR_STATUS	0xd00
+#define PCIE_REG_MMIO_ERR1_STATUS	0xd08
+#define PCIE_REG_MMIO_ERR_INJECT	0xd10
+#define PCIE_REG_MMIO_ERR_LEM_ENABLE	0xd18
+#define PCIE_REG_MMIO_ERR_IRQ_ENABLE	0xd20
+#define PCIE_REG_MMIO_ERR_FREEZE_ENABLE	0xd28
+#define PCIE_REG_MMIO_ERR_SIDE_ENABLE	0xd38
+#define PCIE_REG_MMIO_ERR_LOG_0		0xd40
+#define PCIE_REG_MMIO_ERR_LOG_1		0xd48
+#define PCIE_REG_MMIO_ERR_STATUS_MASK	0xd50
+#define PCIE_REG_MMIO_ERR1_STATUS_MASK	0xd58
+
+#define PCIE_REG_DMA_ERR_STATUS		0xd80
+#define PCIE_REG_DMA_ERR1_STATUS	0xd88
+#define PCIE_REG_DMA_ERR_INJECT		0xd90
+#define PCIE_REG_DMA_ERR_LEM_ENABLE	0xd98
+#define PCIE_REG_DMA_ERR_IRQ_ENABLE	0xda0
+#define PCIE_REG_DMA_ERR_FREEZE_ENABLE	0xda8
+#define PCIE_REG_DMA_ERR_SIDE_ENABLE	0xdb8
+#define PCIE_REG_DMA_ERR_LOG_0		0xdc0
+#define PCIE_REG_DMA_ERR_LOG_1		0xdc8
+#define PCIE_REG_DMA_ERR_STATUS_MASK	0xdd0
+#define PCIE_REG_DMA_ERR1_STATUS_MASK	0xdd8
+
+/* Shortcuts for access to the above using the PHB definitions
+ * with an offset
+ */
+#define PCIE_REG_ERR_PHB_OFFSET		0x0
+#define PCIE_REG_ERR_MMIO_OFFSET	0x80
+#define PCIE_REG_ERR_DMA_OFFSET		0x100
+
+/* Debug and Trace registers */
+#define PCIE_REG_PHB_DEBUG_CONTROL0	0xe00
+#define PCIE_REG_PHB_DEBUG_STATUS0	0xe08
+#define PCIE_REG_PHB_DEBUG_CONTROL1	0xe10
+#define PCIE_REG_PHB_DEBUG_STATUS1	0xe18
+#define PCIE_REG_PHB_DEBUG_CONTROL2	0xe20
+#define PCIE_REG_PHB_DEBUG_STATUS2	0xe28
+#define PCIE_REG_PHB_DEBUG_CONTROL3	0xe30
+#define PCIE_REG_PHB_DEBUG_STATUS3	0xe38
+#define PCIE_REG_PHB_DEBUG_CONTROL4	0xe40
+#define PCIE_REG_PHB_DEBUG_STATUS4	0xe48
+#define PCIE_REG_PHB_DEBUG_CONTROL5	0xe50
+#define PCIE_REG_PHB_DEBUG_STATUS5	0xe58
+#define PCIE_REG_PHB_DEBUG_CONTROL6	0xe60
+#define PCIE_REG_PHB_DEBUG_STATUS6	0xe68
+
+/* Definition for PCIe errors */
+struct wsp_pcie_err_log_data {
+	__u64	phb_err;
+	__u64	phb_err1;
+	__u64	phb_log0;
+	__u64	phb_log1;
+	__u64	mmio_err;
+	__u64	mmio_err1;
+	__u64	mmio_log0;
+	__u64	mmio_log1;
+	__u64	dma_err;
+	__u64	dma_err1;
+	__u64	dma_log0;
+	__u64	dma_log1;
+	__u64	utl_sys_err;
+	__u64	utl_port_err;
+	__u64	utl_rc_err;
+	__u64	unused;
+};
+
+#endif /* __WSP_PCI_H */
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/axonram.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/axonram.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/axonram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/axonram.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@ axon_ram_irq_handler(int irq, void *dev)
  * axon_ram_make_request - make_request() method for block device
  * @queue, @bio: see blk_queue_make_request()
  */
-static int
+static void
 axon_ram_make_request(struct request_queue *queue, struct bio *bio)
 {
 	struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
@@ -113,7 +113,6 @@ axon_ram_make_request(struct request_que
 	struct bio_vec *vec;
 	unsigned int transfered;
 	unsigned short idx;
-	int rc = 0;
 
 	phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
 	phys_end = bank->io_addr + bank->size;
@@ -121,8 +120,7 @@ axon_ram_make_request(struct request_que
 	bio_for_each_segment(vec, bio, idx) {
 		if (unlikely(phys_mem + vec->bv_len > phys_end)) {
 			bio_io_error(bio);
-			rc = -ERANGE;
-			break;
+			return;
 		}
 
 		user_mem = page_address(vec->bv_page) + vec->bv_offset;
@@ -135,8 +133,6 @@ axon_ram_make_request(struct request_que
 		transfered += vec->bv_len;
 	}
 	bio_endio(bio, 0);
-
-	return rc;
 }
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/bestcomm/sram.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/bestcomm/sram.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/bestcomm/sram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/bestcomm/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/cpm_common.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/cpm_common.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/cpm_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/cpm_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  *
  * Author: Scott Wood <scottwood@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
  *
  * Some parts derived from commproc.c/cpm2_common.c, which is:
  * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/of_device.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/of.h>
 #include <linux/slab.h>
 
@@ -146,6 +147,7 @@ unsigned long cpm_muram_alloc(unsigned l
 	spin_lock_irqsave(&cpm_muram_lock, flags);
 	cpm_muram_info.alignment = align;
 	start = rh_alloc(&cpm_muram_info, size, "commproc");
+	memset(cpm_muram_addr(start), 0, size);
 	spin_unlock_irqrestore(&cpm_muram_lock, flags);
 
 	return start;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/dcr.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/dcr.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/dcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/dcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/dcr.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/ehv_pic.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/ehv_pic.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/ehv_pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/ehv_pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -280,6 +280,7 @@ void __init ehv_pic_init(void)
 
 	if (!ehv_pic->irqhost) {
 		of_node_put(np);
+		kfree(ehv_pic);
 		return;
 	}
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_gtm.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_gtm.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_gtm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_gtm.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/fsl_gtm.h>
 
 #define GTCFR_STP(x)		((x) & 1 ? 1 << 5 : 1 << 1)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_lbc.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_lbc.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_lbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_lbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/mod_devicetable.h>
@@ -327,6 +328,7 @@ static int __devinit fsl_lbc_ctrl_probe(
 err:
 	iounmap(fsl_lbc_ctrl_dev->regs);
 	kfree(fsl_lbc_ctrl_dev);
+	fsl_lbc_ctrl_dev = NULL;
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_msi.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_msi.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@ LIST_HEAD(msi_head);
 
 struct fsl_msi_feature {
 	u32 fsl_pic_ip;
-	u32 msiir_offset;
+	u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */
 };
 
 struct fsl_msi_cascade_data {
@@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct p
 {
 	struct fsl_msi *msi_data = fsl_msi_data;
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-	u64 base = fsl_pci_immrbar_base(hose);
+	u64 address; /* Physical address of the MSIIR */
+	int len;
+	const u64 *reg;
 
-	msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
-	msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
+	/* If the msi-address-64 property exists, then use it */
+	reg = of_get_property(hose->dn, "msi-address-64", &len);
+	if (reg && (len == sizeof(u64)))
+		address = be64_to_cpup(reg);
+	else
+		address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
+
+	msg->address_lo = lower_32_bits(address);
+	msg->address_hi = upper_32_bits(address);
 
 	msg->data = hwirq;
 
@@ -296,7 +305,7 @@ static int __devinit fsl_msi_setup_hwirq
 	}
 
 	msi->msi_virqs[irq_index] = virt_msir;
-	cascade_data->index = offset + irq_index;
+	cascade_data->index = offset;
 	cascade_data->msi_data = msi;
 	irq_set_handler_data(virt_msir, cascade_data);
 	irq_set_chained_handler(virt_msir, fsl_msi_cascade);
@@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(st
 
 	msi->irqhost->host_data = msi;
 
-	msi->msi_addr_hi = 0x0;
-	msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
+	msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
 
 	rc = fsl_msi_init_allocator(msi);
 	if (rc) {
@@ -376,8 +384,10 @@ static int __devinit fsl_of_msi_probe(st
 		goto error_out;
 	}
 
-	if (!p)
+	if (!p) {
 		p = all_avail;
+		len = sizeof(all_avail);
+	}
 
 	for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
 		if (p[i * 2] % IRQS_PER_MSI_REG ||
@@ -393,7 +403,7 @@ static int __devinit fsl_of_msi_probe(st
 		count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
 
 		for (j = 0; j < count; j++, irq_index++) {
-			err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
+			err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
 			if (err)
 				goto error_out;
 		}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_msi.h linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_msi.h
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_msi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_msi.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,8 +28,7 @@ struct fsl_msi {
 
 	unsigned long cascade_irq;
 
-	u32 msi_addr_lo;
-	u32 msi_addr_hi;
+	u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
 	void __iomem *msi_regs;
 	u32 feature;
 	int msi_virqs[NR_MSI_REG];
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_pmc.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_pmc.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_rio.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_rio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_rio.c	2012-01-04 18:55:44.000000000 -0500
@@ -1608,6 +1608,7 @@ int fsl_rio_setup(struct platform_device
 	return 0;
 err:
 	iounmap(priv->regs_win);
+	release_resource(&port->iores);
 err_res:
 	kfree(priv);
 err_priv:
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_soc.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_soc.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_soc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_soc.h linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_soc.h
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/fsl_soc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/fsl_soc.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,24 @@ struct device_node;
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* The different ports that the DIU can be connected to */
+enum fsl_diu_monitor_port {
+	FSL_DIU_PORT_DVI,	/* DVI */
+	FSL_DIU_PORT_LVDS,	/* Single-link LVDS */
+	FSL_DIU_PORT_DLVDS	/* Dual-link LVDS */
+};
+
 struct platform_diu_data_ops {
-	unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
-		int monitor_port);
-	void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
-	void (*set_monitor_port) (int monitor_port);
-	void (*set_pixel_clock) (unsigned int pixclock);
-	ssize_t (*show_monitor_port) (int monitor_port, char *buf);
-	int (*set_sysfs_monitor_port) (int val);
-	void (*release_bootmem) (void);
+	u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+		unsigned int bpp);
+	void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+		char *gamma_table_base);
+	void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+	void (*set_pixel_clock)(unsigned int pixclock);
+	enum fsl_diu_monitor_port (*valid_monitor_port)
+		(enum fsl_diu_monitor_port port);
+	void (*release_bootmem)(void);
 };
 
 extern struct platform_diu_data_ops diu_ops;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/Makefile linux-libre-3.2-gnu1/arch/powerpc/sysdev/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@ obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fs
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
-obj-$(CONFIG_MPC8xxx_GPIO)	+= mpc8xxx_gpio.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
 obj-$(CONFIG_FSL_RIO)		+= fsl_rio.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc5xxx_clocks.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc5xxx_clocks.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc5xxx_clocks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc5xxx_clocks.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
+#include <linux/export.h>
 
 unsigned int
 mpc5xxx_get_bus_frequency(struct device_node *node)
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc8xx_pic.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc8xx_pic.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc8xx_pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc8xx_pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,395 +0,0 @@
-/*
- * GPIOs on MPC512x/8349/8572/8610 and compatible
- *
- * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-
-#define MPC8XXX_GPIO_PINS	32
-
-#define GPIO_DIR		0x00
-#define GPIO_ODR		0x04
-#define GPIO_DAT		0x08
-#define GPIO_IER		0x0c
-#define GPIO_IMR		0x10
-#define GPIO_ICR		0x14
-#define GPIO_ICR2		0x18
-
-struct mpc8xxx_gpio_chip {
-	struct of_mm_gpio_chip mm_gc;
-	spinlock_t lock;
-
-	/*
-	 * shadowed data register to be able to clear/set output pins in
-	 * open drain mode safely
-	 */
-	u32 data;
-	struct irq_host *irq;
-	void *of_dev_id_data;
-};
-
-static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
-{
-	return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
-}
-
-static inline struct mpc8xxx_gpio_chip *
-to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
-{
-	return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
-}
-
-static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
-}
-
-/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
- * defined as output cannot be determined by reading GPDAT register,
- * so we use shadow data register instead. The status of input pins
- * is determined by reading GPDAT register.
- */
-static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	u32 val;
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
-
-	return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
-}
-
-static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-
-	return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
-}
-
-static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	if (val)
-		mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
-	else
-		mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
-
-	out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-
-	return 0;
-}
-
-static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	mpc8xxx_gpio_set(gc, gpio, val);
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-
-	return 0;
-}
-
-static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
-		return irq_create_mapping(mpc8xxx_gc->irq, offset);
-	else
-		return -ENXIO;
-}
-
-static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned int mask;
-
-	mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
-	if (mask)
-		generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
-						     32 - ffs(mask)));
-}
-
-static void mpc8xxx_irq_unmask(struct irq_data *d)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static void mpc8xxx_irq_mask(struct irq_data *d)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static void mpc8xxx_irq_ack(struct irq_data *d)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-
-	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-}
-
-static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long flags;
-
-	switch (flow_type) {
-	case IRQ_TYPE_EDGE_FALLING:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		setbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long gpio = irqd_to_hwirq(d);
-	void __iomem *reg;
-	unsigned int shift;
-	unsigned long flags;
-
-	if (gpio < 16) {
-		reg = mm->regs + GPIO_ICR;
-		shift = (15 - gpio) * 2;
-	} else {
-		reg = mm->regs + GPIO_ICR2;
-		shift = (15 - (gpio % 16)) * 2;
-	}
-
-	switch (flow_type) {
-	case IRQ_TYPE_EDGE_FALLING:
-	case IRQ_TYPE_LEVEL_LOW:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrsetbits_be32(reg, 3 << shift, 2 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	case IRQ_TYPE_EDGE_RISING:
-	case IRQ_TYPE_LEVEL_HIGH:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrsetbits_be32(reg, 3 << shift, 1 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrbits32(reg, 3 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct irq_chip mpc8xxx_irq_chip = {
-	.name		= "mpc8xxx-gpio",
-	.irq_unmask	= mpc8xxx_irq_unmask,
-	.irq_mask	= mpc8xxx_irq_mask,
-	.irq_ack	= mpc8xxx_irq_ack,
-	.irq_set_type	= mpc8xxx_irq_set_type,
-};
-
-static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
-				irq_hw_number_t hw)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
-
-	if (mpc8xxx_gc->of_dev_id_data)
-		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
-
-	irq_set_chip_data(virq, h->host_data);
-	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
-	irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
-	return 0;
-}
-
-static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
-				  const u32 *intspec, unsigned int intsize,
-				  irq_hw_number_t *out_hwirq,
-				  unsigned int *out_flags)
-
-{
-	/* interrupt sense values coming from the device tree equal either
-	 * EDGE_FALLING or EDGE_BOTH
-	 */
-	*out_hwirq = intspec[0];
-	*out_flags = intspec[1];
-
-	return 0;
-}
-
-static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
-	.map	= mpc8xxx_gpio_irq_map,
-	.xlate	= mpc8xxx_gpio_irq_xlate,
-};
-
-static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
-	{ .compatible = "fsl,mpc8349-gpio", },
-	{ .compatible = "fsl,mpc8572-gpio", },
-	{ .compatible = "fsl,mpc8610-gpio", },
-	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
-	{ .compatible = "fsl,qoriq-gpio",   },
-	{}
-};
-
-static void __init mpc8xxx_add_controller(struct device_node *np)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc;
-	struct of_mm_gpio_chip *mm_gc;
-	struct gpio_chip *gc;
-	const struct of_device_id *id;
-	unsigned hwirq;
-	int ret;
-
-	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
-	if (!mpc8xxx_gc) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	spin_lock_init(&mpc8xxx_gc->lock);
-
-	mm_gc = &mpc8xxx_gc->mm_gc;
-	gc = &mm_gc->gc;
-
-	mm_gc->save_regs = mpc8xxx_gpio_save_regs;
-	gc->ngpio = MPC8XXX_GPIO_PINS;
-	gc->direction_input = mpc8xxx_gpio_dir_in;
-	gc->direction_output = mpc8xxx_gpio_dir_out;
-	if (of_device_is_compatible(np, "fsl,mpc8572-gpio"))
-		gc->get = mpc8572_gpio_get;
-	else
-		gc->get = mpc8xxx_gpio_get;
-	gc->set = mpc8xxx_gpio_set;
-	gc->to_irq = mpc8xxx_gpio_to_irq;
-
-	ret = of_mm_gpiochip_add(np, mm_gc);
-	if (ret)
-		goto err;
-
-	hwirq = irq_of_parse_and_map(np, 0);
-	if (hwirq == NO_IRQ)
-		goto skip_irq;
-
-	mpc8xxx_gc->irq =
-		irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
-			       &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
-	if (!mpc8xxx_gc->irq)
-		goto skip_irq;
-
-	id = of_match_node(mpc8xxx_gpio_ids, np);
-	if (id)
-		mpc8xxx_gc->of_dev_id_data = id->data;
-
-	mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
-
-	/* ack and mask all irqs */
-	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
-	out_be32(mm_gc->regs + GPIO_IMR, 0);
-
-	irq_set_handler_data(hwirq, mpc8xxx_gc);
-	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
-
-skip_irq:
-	return;
-
-err:
-	pr_err("%s: registration failed with status %d\n",
-	       np->full_name, ret);
-	kfree(mpc8xxx_gc);
-
-	return;
-}
-
-static int __init mpc8xxx_add_gpiochips(void)
-{
-	struct device_node *np;
-
-	for_each_matching_node(np, mpc8xxx_gpio_ids)
-		mpc8xxx_add_controller(np);
-
-	return 0;
-}
-arch_initcall(mpc8xxx_add_gpiochips);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpic.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpic.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/mpic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/mpic.c	2012-01-04 18:55:44.000000000 -0500
@@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data
 	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
 	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
 	 * applying to them. We EOI them late to avoid re-entering.
-	 * We mark IPI's with IRQF_DISABLED as they must run with
-	 * irqs disabled.
 	 */
 	mpic_eoi(mpic);
 }
@@ -1285,13 +1283,11 @@ struct mpic * __init mpic_alloc(struct d
 			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_MCK);
 
-	/* Read feature register, calculate num CPUs and, for non-ISU
-	 * MPICs, num sources as well. On ISU MPICs, sources are counted
-	 * as ISUs are added
+	/*
+	 * Read feature register.  For non-ISU MPICs, num sources as well. On
+	 * ISU MPICs, sources are counted as ISUs are added
 	 */
 	greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-	mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
-			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 	if (isu_size == 0) {
 		if (flags & MPIC_BROKEN_FRR_NIRQS)
 			mpic->num_sources = mpic->irq_count;
@@ -1301,10 +1297,18 @@ struct mpic * __init mpic_alloc(struct d
 				 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 	}
 
+	/*
+	 * The MPIC driver will crash if there are more cores than we
+	 * can initialize, so we may as well catch that problem here.
+	 */
+	BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
+
 	/* Map the per-CPU registers */
-	for (i = 0; i < mpic->num_cpus; i++) {
-		mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
-			 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
+	for_each_possible_cpu(i) {
+		unsigned int cpu = get_hard_smp_processor_id(i);
+
+		mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu],
+			 MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
 			 0x1000);
 	}
 
@@ -1343,7 +1347,7 @@ struct mpic * __init mpic_alloc(struct d
 	}
 	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
 	       " max %d CPUs\n",
-	       name, vers, (unsigned long long)paddr, mpic->num_cpus);
+	       name, vers, (unsigned long long)paddr, num_possible_cpus());
 	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
 	       mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
 
@@ -1742,6 +1746,7 @@ void mpic_reset_core(int cpu)
 	struct mpic *mpic = mpic_primary;
 	u32 pir;
 	int cpuid = get_hard_smp_processor_id(cpu);
+	int i;
 
 	/* Set target bit for core reset */
 	pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
@@ -1753,6 +1758,15 @@ void mpic_reset_core(int cpu)
 	pir &= ~(1 << cpuid);
 	mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
 	mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
+
+	/* Perform 15 EOI on each reset core to clear pending interrupts.
+	 * This is required for FSL CoreNet based devices */
+	if (mpic->flags & MPIC_FSL) {
+		for (i = 0; i < 15; i++) {
+			_mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
+				      MPIC_CPU_EOI, 0);
+		}
+	}
 }
 #endif /* CONFIG_SMP */
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/mv64x60_pci.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/mv64x60_pci.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/mv64x60_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/mv64x60_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/stat.h>
 #include <linux/pci.h>
 
 #include <asm/prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/pmi.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/pmi.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/pmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/pmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_msi.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_msi.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/msi.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_pci.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_pci.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -834,7 +834,7 @@ static int __init ppc440spe_pciex_core_i
 	return 3;
 }
 
-static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val = 1 << 24;
 
@@ -872,12 +872,12 @@ static int ppc440spe_pciex_init_port_hw(
 	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
-static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	return ppc440spe_pciex_init_port_hw(port);
 }
 
-static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	int rc = ppc440spe_pciex_init_port_hw(port);
 
@@ -936,7 +936,7 @@ static int __init ppc460ex_pciex_core_in
 	return 2;
 }
 
-static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val;
 	u32 utlset1;
@@ -1092,6 +1092,10 @@ static int __init ppc460sx_pciex_core_in
 	mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
 	mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
 
+	/* Set HSS PRBS enabled */
+	mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
+	mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
+
 	udelay(100);
 
 	/* De-assert PLLRESET */
@@ -1122,7 +1126,7 @@ static int __init ppc460sx_pciex_core_in
 	return 2;
 }
 
-static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 
 	if (port->endpoint)
@@ -1132,9 +1136,6 @@ static int ppc460sx_pciex_init_port_hw(s
 		dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
 				0, 0x01000000);
 
-	/*Gen-1*/
-	mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
-
 	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
 			(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
 			PESDRx_RCSSET_RSTPYN);
@@ -1148,14 +1149,42 @@ static int ppc460sx_pciex_init_utl(struc
 {
 	/* Max 128 Bytes */
 	out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
+	/* Assert VRB and TXE - per datasheet turn off addr validation */
+	out_be32(port->utl_base + PEUTL_PCTL,  0x80800000);
 	return 0;
 }
 
+static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+	void __iomem *mbase;
+	int attempt = 50;
+
+	port->link = 0;
+
+	mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
+	if (mbase == NULL) {
+		printk(KERN_ERR "%s: Can't map internal config space !",
+			port->node->full_name);
+		goto done;
+	}
+
+	while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
+			& PECFG_460SX_DLLSTA_LINKUP))) {
+		attempt--;
+		mdelay(10);
+	}
+	if (attempt)
+		port->link = 1;
+done:
+	iounmap(mbase);
+
+}
+
 static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
 	.core_init	= ppc460sx_pciex_core_init,
 	.port_init_hw	= ppc460sx_pciex_init_port_hw,
 	.setup_utl	= ppc460sx_pciex_init_utl,
-	.check_link	= ppc4xx_pciex_check_link_sdr,
+	.check_link	= ppc460sx_pciex_check_link,
 };
 
 #endif /* CONFIG_44x */
@@ -1189,7 +1218,7 @@ static void ppc405ex_pcie_phy_reset(stru
 	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);
 }
 
-static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val;
 
@@ -1338,15 +1367,15 @@ static int __init ppc4xx_pciex_port_init
 	if (rc != 0)
 		return rc;
 
-	if (ppc4xx_pciex_hwops->check_link)
-		ppc4xx_pciex_hwops->check_link(port);
-
 	/*
 	 * Initialize mapping: disable all regions and configure
 	 * CFG and REG regions based on resources in the device tree
 	 */
 	ppc4xx_pciex_port_init_mapping(port);
 
+	if (ppc4xx_pciex_hwops->check_link)
+		ppc4xx_pciex_hwops->check_link(port);
+
 	/*
 	 * Map UTL
 	 */
@@ -1360,13 +1389,23 @@ static int __init ppc4xx_pciex_port_init
 		ppc4xx_pciex_hwops->setup_utl(port);
 
 	/*
-	 * Check for VC0 active and assert RDY.
+	 * Check for VC0 active or PLL Locked and assert RDY.
 	 */
 	if (port->sdr_base) {
-		if (port->link &&
-		    ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
-					     1 << 16, 1 << 16, 5000)) {
-			printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+		if (of_device_is_compatible(port->node,
+				"ibm,plb-pciex-460sx")){
+			if (port->link && ppc4xx_pciex_wait_on_sdr(port,
+					PESDRn_RCSSTS,
+					1 << 12, 1 << 12, 5000)) {
+				printk(KERN_INFO "PCIE%d: PLL not locked\n",
+						port->index);
+				port->link = 0;
+			}
+		} else if (port->link &&
+			ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+				1 << 16, 1 << 16, 5000)) {
+			printk(KERN_INFO "PCIE%d: VC0 not active\n",
+					port->index);
 			port->link = 0;
 		}
 
@@ -1573,8 +1612,15 @@ static int __init ppc4xx_setup_one_pciex
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
-		/* Note that 3 here means enabled | single region */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
+		/*Enabled and single region */
+		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+				sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
+					| DCRO_PEGPL_OMRxMSKL_VAL);
+		else
+			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+				sa | DCRO_PEGPL_OMR1MSKL_UOT
+					| DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	case 1:
 		out_le32(mbase + PECFG_POM1LAH, pciah);
@@ -1582,8 +1628,8 @@ static int __init ppc4xx_setup_one_pciex
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
-		/* Note that 3 here means enabled | single region */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
+		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
+				sa | DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	case 2:
 		out_le32(mbase + PECFG_POM2LAH, pciah);
@@ -1592,7 +1638,9 @@ static int __init ppc4xx_setup_one_pciex
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
 		/* Note that 3 here means enabled | IO space !!! */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
+		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
+				sa | DCRO_PEGPL_OMR3MSKL_IO
+					| DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	}
 
@@ -1693,6 +1741,9 @@ static void __init ppc4xx_configure_pcie
 		if (res->flags & IORESOURCE_PREFETCH)
 			sa |= 0x8;
 
+		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+			sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
 		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
 		out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
 
@@ -1854,6 +1905,10 @@ static void __init ppc4xx_pciex_port_set
 	}
 	out_le16(mbase + 0x202, val);
 
+	/* Enable Bus master, memory, and io space */
+	if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+		out_le16(mbase + 0x204, 0x7);
+
 	if (!port->endpoint) {
 		/* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
 		out_le32(mbase + 0x208, 0x06040001);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_pci.h linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_pci.h
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_pci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -464,6 +464,18 @@
 #define PECFG_POM2LAL		0x390
 #define PECFG_POM2LAH		0x394
 
+/* 460sx only */
+#define PECFG_460SX_DLLSTA     0x3f8
+
+/* 460sx Bit Mappings */
+#define PECFG_460SX_DLLSTA_LINKUP	 0x00000010
+#define DCRO_PEGPL_460SX_OMR1MSKL_UOT	 0x00000004
+
+/* PEGPL Bit Mappings */
+#define DCRO_PEGPL_OMRxMSKL_VAL	 0x00000001
+#define DCRO_PEGPL_OMR1MSKL_UOT	 0x00000002
+#define DCRO_PEGPL_OMR3MSKL_IO	 0x00000002
+
 /* SDR Bit Mappings */
 #define PESDRx_RCSSET_HLDPLB	0x10000000
 #define PESDRx_RCSSET_RSTGU	0x01000000
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_soc.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_soc.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/ppc4xx_soc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/ppc4xx_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,7 +115,7 @@ static int __init ppc4xx_l2c_probe(void)
 	}
 
 	/* Install error handler */
-	if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
+	if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
 		printk(KERN_ERR "Cannot install L2C error handler"
 		       ", cache is not enabled\n");
 		of_node_put(np);
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/gpio.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/gpio.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/qe.h>
 
 struct qe_gpio_chip {
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/qe.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/qe.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/qe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/qe.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,7 +216,7 @@ int qe_setbrg(enum qe_clock brg, unsigne
 	/* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
 	   that the BRG divisor must be even if you're not using divide-by-16
 	   mode. */
-	if (!div16 && (divisor & 1))
+	if (!div16 && (divisor & 1) && (divisor > 3))
 		divisor++;
 
 	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
@@ -382,7 +382,7 @@ static void qe_upload_microcode(const vo
 /*
  * Upload a microcode to the I-RAM at a specific address.
  *
- * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
+ * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
  * uploading.
  *
  * Currently, only version 1 is supported, so the 'version' field must be
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc_fast.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc_fast.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc_fast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc_fast.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc_slow.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc_slow.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/ucc_slow.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/ucc_slow.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/usb.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/usb.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/qe_lib/usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/qe_lib/usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <asm/immap_qe.h>
 #include <asm/qe.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/rtc_cmos_setup.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/rtc_cmos_setup.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/rtc_cmos_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/rtc_cmos_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/mc146818rtc.h>
 
 #include <asm/prom.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/scom.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/scom.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/scom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/scom.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/scom.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/simple_gpio.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/simple_gpio.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/simple_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/simple_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/tsi108_dev.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/tsi108_dev.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/tsi108_dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/tsi108_dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/of_net.h>
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/uic.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/uic.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/uic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/uic.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@ struct uic {
 	int index;
 	int dcrbase;
 
-	spinlock_t lock;
+	raw_spinlock_t lock;
 
 	/* The remapper for this UIC */
 	struct irq_host	*irqhost;
@@ -61,14 +61,14 @@ static void uic_unmask_irq(struct irq_da
 	u32 er, sr;
 
 	sr = 1 << (31-src);
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	/* ack level-triggered interrupts here */
 	if (irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er |= sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_mask_irq(struct irq_data *d)
@@ -78,11 +78,11 @@ static void uic_mask_irq(struct irq_data
 	unsigned long flags;
 	u32 er;
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er &= ~(1 << (31 - src));
 	mtdcr(uic->dcrbase + UIC_ER, er);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_ack_irq(struct irq_data *d)
@@ -91,9 +91,9 @@ static void uic_ack_irq(struct irq_data
 	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_mask_ack_irq(struct irq_data *d)
@@ -104,7 +104,7 @@ static void uic_mask_ack_irq(struct irq_
 	u32 er, sr;
 
 	sr = 1 << (31-src);
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er &= ~sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
@@ -118,7 +118,7 @@ static void uic_mask_ack_irq(struct irq_
 	 */
 	if (!irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
@@ -152,7 +152,7 @@ static int uic_set_irq_type(struct irq_d
 
 	mask = ~(1 << (31 - src));
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	tr = mfdcr(uic->dcrbase + UIC_TR);
 	pr = mfdcr(uic->dcrbase + UIC_PR);
 	tr = (tr & mask) | (trigger << (31-src));
@@ -161,7 +161,7 @@ static int uic_set_irq_type(struct irq_d
 	mtdcr(uic->dcrbase + UIC_PR, pr);
 	mtdcr(uic->dcrbase + UIC_TR, tr);
 
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 
 	return 0;
 }
@@ -254,7 +254,7 @@ static struct uic * __init uic_init_one(
 	if (! uic)
 		return NULL; /* FIXME: panic? */
 
-	spin_lock_init(&uic->lock);
+	raw_spin_lock_init(&uic->lock);
 	indexp = of_get_property(node, "cell-index", &len);
 	if (!indexp || (len != sizeof(u32))) {
 		printk(KERN_ERR "uic: Device node %s has missing or invalid "
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/icp-native.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/icp-native.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/icp-native.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/icp-native.c	2012-01-04 18:55:44.000000000 -0500
@@ -276,7 +276,7 @@ static const struct icp_ops icp_native_o
 #endif
 };
 
-int icp_native_init(void)
+int __init icp_native_init(void)
 {
 	struct device_node *np;
 	u32 indx = 0;
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/ics-opal.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/ics-opal.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/ics-opal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/ics-opal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,244 @@
+/*
+ * ICS backend for OPAL managed interrupts.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/msi.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static int ics_opal_mangle_server(int server)
+{
+	/* No link for now */
+	return server << 2;
+}
+
+static int ics_opal_unmangle_server(int server)
+{
+	/* No link for now */
+	return server >> 2;
+}
+
+static void ics_opal_unmask_irq(struct irq_data *d)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	int64_t rc;
+	int server;
+
+	pr_devel("ics-hal: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return;
+
+	server = xics_get_irq_server(d->irq, d->affinity, 0);
+	server = ics_opal_mangle_server(server);
+
+	rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
+	if (rc != OPAL_SUCCESS)
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+}
+
+static unsigned int ics_opal_startup(struct irq_data *d)
+{
+#ifdef CONFIG_PCI_MSI
+	/*
+	 * The generic MSI code returns with the interrupt disabled on the
+	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
+	 * at that level, so we do it here by hand.
+	 */
+	if (d->msi_desc)
+		unmask_msi_irq(d);
+#endif
+
+	/* unmask it */
+	ics_opal_unmask_irq(d);
+	return 0;
+}
+
+static void ics_opal_mask_real_irq(unsigned int hw_irq)
+{
+	int server = ics_opal_mangle_server(xics_default_server);
+	int64_t rc;
+
+	if (hw_irq == XICS_IPI)
+		return;
+
+	/* Have to set XIVE to 0xff to be able to remove a slot */
+	rc = opal_set_xive(hw_irq, server, 0xff);
+	if (rc != OPAL_SUCCESS)
+		pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n",
+		       __func__, hw_irq, rc);
+}
+
+static void ics_opal_mask_irq(struct irq_data *d)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+
+	pr_devel("ics-hal: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return;
+	ics_opal_mask_real_irq(hw_irq);
+}
+
+static int ics_opal_set_affinity(struct irq_data *d,
+				 const struct cpumask *cpumask,
+				 bool force)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	int16_t server;
+	int8_t priority;
+	int64_t rc;
+	int wanted_server;
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return -1;
+
+	rc = opal_get_xive(hw_irq, &server, &priority);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+		return -1;
+	}
+
+	wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
+	if (wanted_server < 0) {
+		char cpulist[128];
+		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		pr_warning("%s: No online cpus in the mask %s for irq %d\n",
+			   __func__, cpulist, d->irq);
+		return -1;
+	}
+	server = ics_opal_mangle_server(wanted_server);
+
+	pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
+		 d->irq, hw_irq, wanted_server, server);
+
+	rc = opal_set_xive(hw_irq, server, priority);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+		return -1;
+	}
+	return 0;
+}
+
+static struct irq_chip ics_opal_irq_chip = {
+	.name = "OPAL ICS",
+	.irq_startup = ics_opal_startup,
+	.irq_mask = ics_opal_mask_irq,
+	.irq_unmask = ics_opal_unmask_irq,
+	.irq_eoi = NULL, /* Patched at init time */
+	.irq_set_affinity = ics_opal_set_affinity
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq);
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec);
+static long ics_opal_get_server(struct ics *ics, unsigned long vec);
+
+static int ics_opal_host_match(struct ics *ics, struct device_node *node)
+{
+	return 1;
+}
+
+/* Only one global & state struct ics */
+static struct ics ics_hal = {
+	.map		= ics_opal_map,
+	.mask_unknown	= ics_opal_mask_unknown,
+	.get_server	= ics_opal_get_server,
+	.host_match	= ics_opal_host_match,
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq)
+{
+	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
+		return -EINVAL;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(hw_irq, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return -ENXIO;
+
+	irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
+	irq_set_chip_data(virq, &ics_hal);
+
+	return 0;
+}
+
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
+{
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(vec, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return;
+
+	ics_opal_mask_real_irq(vec);
+}
+
+static long ics_opal_get_server(struct ics *ics, unsigned long vec)
+{
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(vec, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return -1;
+	return ics_opal_unmangle_server(server);
+}
+
+int __init ics_opal_init(void)
+{
+	if (!firmware_has_feature(FW_FEATURE_OPAL))
+		return -ENODEV;
+
+	/* We need to patch our irq chip's EOI to point to the
+	 * right ICP
+	 */
+	ics_opal_irq_chip.irq_eoi = icp_ops->eoi;
+
+	/* Register ourselves */
+	xics_register_ics(&ics_hal);
+
+	pr_info("ICS OPAL backend registered\n");
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/Makefile linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/Makefile
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,4 @@ obj-y				+= xics-common.o
 obj-$(CONFIG_PPC_ICP_NATIVE)	+= icp-native.o
 obj-$(CONFIG_PPC_ICP_HV)	+= icp-hv.o
 obj-$(CONFIG_PPC_ICS_RTAS)	+= ics-rtas.o
+obj-$(CONFIG_PPC_POWERNV)	+= ics-opal.o
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/xics-common.c linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/xics-common.c
--- linux-libre-3.1-gnu1/arch/powerpc/sysdev/xics/xics-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/sysdev/xics/xics-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -134,11 +134,10 @@ static void xics_request_ipi(void)
 	BUG_ON(ipi == NO_IRQ);
 
 	/*
-	 * IPIs are marked IRQF_DISABLED as they must run with irqs
-	 * disabled, and PERCPU.  The handler was set in map.
+	 * IPIs are marked IRQF_PERCPU. The handler was set in map.
 	 */
 	BUG_ON(request_irq(ipi, icp_ops->ipi_action,
-			   IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL));
+			   IRQF_PERCPU, "IPI", NULL));
 }
 
 int __init xics_smp_probe(void)
@@ -409,14 +408,10 @@ void __init xics_init(void)
 	int rc = -1;
 
 	/* Fist locate ICP */
-#ifdef CONFIG_PPC_ICP_HV
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		rc = icp_hv_init();
-#endif
-#ifdef CONFIG_PPC_ICP_NATIVE
 	if (rc < 0)
 		rc = icp_native_init();
-#endif
 	if (rc < 0) {
 		pr_warning("XICS: Cannot find a Presentation Controller !\n");
 		return;
@@ -429,9 +424,9 @@ void __init xics_init(void)
 	xics_ipi_chip.irq_eoi = icp_ops->eoi;
 
 	/* Now locate ICS */
-#ifdef CONFIG_PPC_ICS_RTAS
 	rc = ics_rtas_init();
-#endif
+	if (rc < 0)
+		rc = ics_opal_init();
 	if (rc < 0)
 		pr_warning("XICS: Cannot find a Source Controller !\n");
 
diff -druNp linux-libre-3.1-gnu1/arch/powerpc/xmon/xmon.c linux-libre-3.2-gnu1/arch/powerpc/xmon/xmon.c
--- linux-libre-3.1-gnu1/arch/powerpc/xmon/xmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/powerpc/xmon/xmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/kallsyms.h>
 #include <linux/cpumask.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -340,8 +340,8 @@ int cpus_are_in_xmon(void)
 
 static inline int unrecoverable_excp(struct pt_regs *regs)
 {
-#ifdef CONFIG_4xx
-	/* We have no MSR_RI bit on 4xx, so we simply return false */
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOK3E)
+	/* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
 	return 0;
 #else
 	return ((regs->msr & MSR_RI) == 0);
diff -druNp linux-libre-3.1-gnu1/arch/s390/boot/compressed/misc.c linux-libre-3.2-gnu1/arch/s390/boot/compressed/misc.c
--- linux-libre-3.1-gnu1/arch/s390/boot/compressed/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/boot/compressed/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@ static unsigned long free_mem_end_ptr;
 
 extern _sclp_print_early(const char *);
 
-int puts(const char *s)
+static int puts(const char *s)
 {
 	_sclp_print_early(s);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/arch/s390/crypto/crypt_s390.h linux-libre-3.2-gnu1/arch/s390/crypto/crypt_s390.h
--- linux-libre-3.1-gnu1/arch/s390/crypto/crypt_s390.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/crypto/crypt_s390.h	2012-01-04 18:55:44.000000000 -0500
@@ -368,9 +368,12 @@ static inline int crypt_s390_func_availa
 
 	if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
 		return 0;
-	if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
+
+	if (facility_mask & CRYPT_S390_MSA3 &&
+	    (!test_facility(2) || !test_facility(76)))
 		return 0;
-	if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
+	if (facility_mask & CRYPT_S390_MSA4 &&
+	    (!test_facility(2) || !test_facility(77)))
 		return 0;
 
 	switch (func & CRYPT_S390_OP_MASK) {
diff -druNp linux-libre-3.1-gnu1/arch/s390/crypto/sha_common.c linux-libre-3.2-gnu1/arch/s390/crypto/sha_common.c
--- linux-libre-3.1-gnu1/arch/s390/crypto/sha_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/crypto/sha_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  */
 
 #include <crypto/internal/hash.h>
+#include <linux/module.h>
 #include "sha.h"
 #include "crypt_s390.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/defconfig linux-libre-3.2-gnu1/arch/s390/defconfig
--- linux-libre-3.1-gnu1/arch/s390/defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@ CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
diff -druNp linux-libre-3.1-gnu1/arch/s390/hypfs/hypfs_diag.c linux-libre-3.2-gnu1/arch/s390/hypfs/hypfs_diag.c
--- linux-libre-3.1-gnu1/arch/s390/hypfs/hypfs_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/hypfs/hypfs_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -562,10 +562,9 @@ static int dbfs_d204_create(void **data,
 	void *base;
 
 	buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
-	base = vmalloc(buf_size);
+	base = vzalloc(buf_size);
 	if (!base)
 		return -ENOMEM;
-	memset(base, 0, buf_size);
 	d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr);
 	rc = diag204_do_store(d204->buf, diag204_buf_pages);
 	if (rc) {
diff -druNp linux-libre-3.1-gnu1/arch/s390/hypfs/inode.c linux-libre-3.2-gnu1/arch/s390/hypfs/inode.c
--- linux-libre-3.1-gnu1/arch/s390/hypfs/inode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/hypfs/inode.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,9 +108,7 @@ static struct inode *hypfs_make_inode(st
 		ret->i_gid = hypfs_info->gid;
 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
 		if (mode & S_IFDIR)
-			ret->i_nlink = 2;
-		else
-			ret->i_nlink = 1;
+			set_nlink(ret, 2);
 	}
 	return ret;
 }
@@ -361,7 +359,7 @@ static struct dentry *hypfs_create_file(
 	} else if (mode & S_IFDIR) {
 		inode->i_op = &simple_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
-		parent->d_inode->i_nlink++;
+		inc_nlink(parent->d_inode);
 	} else
 		BUG();
 	inode->i_private = data;
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/ccwdev.h linux-libre-3.2-gnu1/arch/s390/include/asm/ccwdev.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/ccwdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/ccwdev.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <asm/fcx.h>
+#include <asm/irq.h>
 
 /* structs from asm/cio.h */
 struct irb;
@@ -127,6 +128,7 @@ enum uc_todo {
  * @restore: callback for restoring after hibernation
  * @uc_handler: callback for unit check handler
  * @driver: embedded device driver structure
+ * @int_class: interruption class to use for accounting interrupts
  */
 struct ccw_driver {
 	struct ccw_device_id *ids;
@@ -144,6 +146,7 @@ struct ccw_driver {
 	int (*restore)(struct ccw_device *);
 	enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
 	struct device_driver driver;
+	enum interruption_class int_class;
 };
 
 extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/compat.h linux-libre-3.2-gnu1/arch/s390/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #define PSW32_MASK_IO		0x02000000UL
 #define PSW32_MASK_EXT		0x01000000UL
 #define PSW32_MASK_KEY		0x00F00000UL
+#define PSW32_MASK_BASE		0x00080000UL	/* Always one */
 #define PSW32_MASK_MCHECK	0x00040000UL
 #define PSW32_MASK_WAIT		0x00020000UL
 #define PSW32_MASK_PSTATE	0x00010000UL
@@ -19,21 +20,19 @@
 #define PSW32_MASK_CC		0x00003000UL
 #define PSW32_MASK_PM		0x00000f00UL
 
-#define PSW32_ADDR_AMODE31	0x80000000UL
+#define PSW32_MASK_USER		0x00003F00UL
+
+#define PSW32_ADDR_AMODE	0x80000000UL
 #define PSW32_ADDR_INSN		0x7FFFFFFFUL
 
-#define PSW32_BASE_BITS		0x00080000UL
+#define PSW32_DEFAULT_KEY	(((u32) PAGE_DEFAULT_ACC) << 20)
 
 #define PSW32_ASC_PRIMARY	0x00000000UL
 #define PSW32_ASC_ACCREG	0x00004000UL
 #define PSW32_ASC_SECONDARY	0x00008000UL
 #define PSW32_ASC_HOME		0x0000C000UL
 
-#define PSW32_MASK_MERGE(CURRENT,NEW) \
-	(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
-	 ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
-
-extern long psw32_user_bits;
+extern u32 psw32_user_bits;
 
 #define COMPAT_USER_HZ		100
 #define COMPAT_UTS_MACHINE	"s390\0\0\0\0"
@@ -131,7 +130,8 @@ struct compat_statfs {
 	compat_fsid_t	f_fsid;
 	s32		f_namelen;
 	s32		f_frsize;
-	s32		f_spare[6];
+	s32		f_flags;
+	s32		f_spare[5];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/cputime.h linux-libre-3.2-gnu1/arch/s390/include/asm/cputime.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,8 @@ usecs_to_cputime(const unsigned int m)
 	return (cputime_t) m * 4096;
 }
 
+#define usecs_to_cputime64(m)		usecs_to_cputime(m)
+
 /*
  * Convert cputime to milliseconds and back.
  */
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/ipl.h linux-libre-3.2-gnu1/arch/s390/include/asm/ipl.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/ipl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/ipl.h	2012-01-04 18:55:44.000000000 -0500
@@ -168,5 +168,6 @@ enum diag308_rc {
 
 extern int diag308(unsigned long subcode, void *addr);
 extern void diag308_reset(void);
+extern void store_status(void);
 
 #endif /* _ASM_S390_IPL_H */
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/irq.h linux-libre-3.2-gnu1/arch/s390/include/asm/irq.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,8 @@ enum interruption_class {
 	EXTERNAL_INTERRUPT,
 	IO_INTERRUPT,
 	EXTINT_CLK,
-	EXTINT_IPI,
+	EXTINT_EXC,
+	EXTINT_EMS,
 	EXTINT_TMR,
 	EXTINT_TLA,
 	EXTINT_PFL,
@@ -17,8 +18,8 @@ enum interruption_class {
 	EXTINT_SCP,
 	EXTINT_IUC,
 	EXTINT_CPM,
+	IOINT_CIO,
 	IOINT_QAI,
-	IOINT_QDI,
 	IOINT_DAS,
 	IOINT_C15,
 	IOINT_C70,
@@ -28,6 +29,7 @@ enum interruption_class {
 	IOINT_CLW,
 	IOINT_CTC,
 	IOINT_APB,
+	IOINT_CSC,
 	NMI_NMI,
 	NR_IRQS,
 };
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/kexec.h linux-libre-3.2-gnu1/arch/s390/include/asm/kexec.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/kexec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/kexec.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,15 @@
 /* Not more than 2GB */
 #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
 
+/* Maximum address we can use for the crash control pages */
+#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
+
 /* Allocate one page for the pdp and the second for the code */
 #define KEXEC_CONTROL_PAGE_SIZE 4096
 
+/* Alignment of crashkernel memory */
+#define KEXEC_CRASH_MEM_ALIGN HPAGE_SIZE
+
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/kvm_host.h linux-libre-3.2-gnu1/arch/s390/include/asm/kvm_host.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@ struct sca_block {
 #define KVM_HPAGE_MASK(x)	(~(KVM_HPAGE_SIZE(x) - 1))
 #define KVM_PAGES_PER_HPAGE(x)	(KVM_HPAGE_SIZE(x) / PAGE_SIZE)
 
-#define CPUSTAT_HOST       0x80000000
+#define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
 #define CPUSTAT_STOP_INT   0x04000000
@@ -119,6 +119,7 @@ struct kvm_vcpu_stat {
 	u32 instruction_lctlg;
 	u32 exit_program_interruption;
 	u32 exit_instr_and_program;
+	u32 deliver_external_call;
 	u32 deliver_emergency_signal;
 	u32 deliver_service_signal;
 	u32 deliver_virtio_interrupt;
@@ -138,11 +139,14 @@ struct kvm_vcpu_stat {
 	u32 instruction_stfl;
 	u32 instruction_tprot;
 	u32 instruction_sigp_sense;
+	u32 instruction_sigp_sense_running;
+	u32 instruction_sigp_external_call;
 	u32 instruction_sigp_emergency;
 	u32 instruction_sigp_stop;
 	u32 instruction_sigp_arch;
 	u32 instruction_sigp_prefix;
 	u32 instruction_sigp_restart;
+	u32 diagnose_10;
 	u32 diagnose_44;
 };
 
@@ -174,6 +178,10 @@ struct kvm_s390_prefix_info {
 	__u32 address;
 };
 
+struct kvm_s390_extcall_info {
+	__u16 code;
+};
+
 struct kvm_s390_emerg_info {
 	__u16 code;
 };
@@ -186,6 +194,7 @@ struct kvm_s390_interrupt_info {
 		struct kvm_s390_ext_info ext;
 		struct kvm_s390_pgm_info pgm;
 		struct kvm_s390_emerg_info emerg;
+		struct kvm_s390_extcall_info extcall;
 		struct kvm_s390_prefix_info prefix;
 	};
 };
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/lowcore.h linux-libre-3.2-gnu1/arch/s390/include/asm/lowcore.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/lowcore.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/lowcore.h	2012-01-04 18:55:44.000000000 -0500
@@ -151,10 +151,8 @@ struct _lowcore {
 	 */
 	__u32	ipib;				/* 0x0e00 */
 	__u32	ipib_checksum;			/* 0x0e04 */
-
-	/* 64 bit save area */
-	__u64	save_area_64;			/* 0x0e08 */
-	__u8	pad_0x0e10[0x0f00-0x0e10];	/* 0x0e10 */
+	__u32	vmcore_info;			/* 0x0e08 */
+	__u8	pad_0x0e0c[0x0f00-0x0e0c];	/* 0x0e0c */
 
 	/* Extended facility list */
 	__u64	stfle_fac_list[32];		/* 0x0f00 */
@@ -290,9 +288,7 @@ struct _lowcore {
 	 */
 	__u64	ipib;				/* 0x0e00 */
 	__u32	ipib_checksum;			/* 0x0e08 */
-
-	/* 64 bit save area */
-	__u64	save_area_64;			/* 0x0e0c */
+	__u64	vmcore_info;			/* 0x0e0c */
 	__u8	pad_0x0e14[0x0f00-0x0e14];	/* 0x0e14 */
 
 	/* Extended facility list */
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/page.h linux-libre-3.2-gnu1/arch/s390/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -177,6 +177,7 @@ static inline int page_test_and_clear_yo
 struct page;
 void arch_free_page(struct page *page, int order);
 void arch_alloc_page(struct page *page, int order);
+void arch_set_page_states(int make_stable);
 
 static inline int devmem_is_allowed(unsigned long pfn)
 {
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/pgtable.h linux-libre-3.2-gnu1/arch/s390/include/asm/pgtable.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/pgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -593,14 +593,16 @@ static inline pgste_t pgste_update_all(p
 	unsigned long address, bits;
 	unsigned char skey;
 
+	if (!pte_present(*ptep))
+		return pgste;
 	address = pte_val(*ptep) & PAGE_MASK;
 	skey = page_get_storage_key(address);
 	bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
 	/* Clear page changed & referenced bit in the storage key */
-	if (bits) {
-		skey ^= bits;
-		page_set_storage_key(address, skey, 1);
-	}
+	if (bits & _PAGE_CHANGED)
+		page_set_storage_key(address, skey ^ bits, 1);
+	else if (bits)
+		page_reset_referenced(address);
 	/* Transfer page changed & referenced bit to guest bits in pgste */
 	pgste_val(pgste) |= bits << 48;		/* RCP_GR_BIT & RCP_GC_BIT */
 	/* Get host changed & referenced bits from pgste */
@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young
 #ifdef CONFIG_PGSTE
 	int young;
 
+	if (!pte_present(*ptep))
+		return pgste;
 	young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
 	/* Transfer page referenced bit to pte software bit (host view) */
 	if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young
 
 }
 
-static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
+static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
 #ifdef CONFIG_PGSTE
 	unsigned long address;
 	unsigned long okey, nkey;
 
-	address = pte_val(*ptep) & PAGE_MASK;
+	if (!pte_present(entry))
+		return;
+	address = pte_val(entry) & PAGE_MASK;
 	okey = nkey = page_get_storage_key(address);
 	nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
 	/* Set page access key and fetch protection bit from pgste */
@@ -696,7 +702,9 @@ void gmap_disable(struct gmap *gmap);
 int gmap_map_segment(struct gmap *gmap, unsigned long from,
 		     unsigned long to, unsigned long length);
 int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -710,7 +718,7 @@ static inline void set_pte_at(struct mm_
 
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_get_lock(ptep);
-		pgste_set_pte(ptep, pgste);
+		pgste_set_pte(ptep, pgste, entry);
 		*ptep = entry;
 		pgste_set_unlock(ptep, pgste);
 	} else
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/processor.h linux-libre-3.2-gnu1/arch/s390/include/asm/processor.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,8 @@ static inline void get_cpu_id(struct cpu
 
 extern void s390_adjust_jiffies(void);
 extern int get_cpu_capability(unsigned int *);
+extern const struct seq_operations cpuinfo_op;
+extern int sysctl_ieee_emulation_warnings;
 
 /*
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -118,17 +120,17 @@ struct stack_frame {
 /*
  * Do necessary setup to start up a new thread.
  */
-#define start_thread(regs, new_psw, new_stackp) do {		\
-	regs->psw.mask	= psw_user_bits;			\
-	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\
-	regs->gprs[15]	= new_stackp;				\
+#define start_thread(regs, new_psw, new_stackp) do {			\
+	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
+	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
+	regs->gprs[15]	= new_stackp;					\
 } while (0)
 
-#define start_thread31(regs, new_psw, new_stackp) do {		\
-	regs->psw.mask	= psw_user32_bits;			\
-	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\
-	regs->gprs[15]	= new_stackp;				\
-	crst_table_downgrade(current->mm, 1UL << 31);		\
+#define start_thread31(regs, new_psw, new_stackp) do {			\
+	regs->psw.mask	= psw_user_bits | PSW_MASK_BA;			\
+	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
+	regs->gprs[15]	= new_stackp;					\
+	crst_table_downgrade(current->mm, 1UL << 31);			\
 } while (0)
 
 /* Forward declaration, a strange C thing */
@@ -187,7 +189,6 @@ static inline void __load_psw(psw_t psw)
  * Set PSW mask to specified value, while leaving the
  * PSW addr pointing to the next instruction.
  */
-
 static inline void __load_psw_mask (unsigned long mask)
 {
 	unsigned long addr;
@@ -212,26 +213,37 @@ static inline void __load_psw_mask (unsi
 		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
 #endif /* __s390x__ */
 }
- 
+
 /*
- * Function to stop a processor until an interruption occurred
+ * Rewind PSW instruction address by specified number of bytes.
  */
-static inline void enabled_wait(void)
+static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
 {
-	__load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
-			PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
-}
+#ifndef __s390x__
+	if (psw.addr & PSW_ADDR_AMODE)
+		/* 31 bit mode */
+		return (psw.addr - ilc) | PSW_ADDR_AMODE;
+	/* 24 bit mode */
+	return (psw.addr - ilc) & ((1UL << 24) - 1);
+#else
+	unsigned long mask;
 
+	mask = (psw.mask & PSW_MASK_EA) ? -1UL :
+	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
+					  (1UL << 24) - 1;
+	return (psw.addr - ilc) & mask;
+#endif
+}
+ 
 /*
  * Function to drop a processor into disabled wait state
  */
-
 static inline void ATTRIB_NORET disabled_wait(unsigned long code)
 {
         unsigned long ctl_buf;
         psw_t dw_psw;
 
-        dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+	dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
         dw_psw.addr = code;
         /* 
          * Store status and then load disabled wait psw,
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/ptrace.h linux-libre-3.2-gnu1/arch/s390/include/asm/ptrace.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -230,17 +230,21 @@ typedef struct
 #define PSW_MASK_IO		0x02000000UL
 #define PSW_MASK_EXT		0x01000000UL
 #define PSW_MASK_KEY		0x00F00000UL
+#define PSW_MASK_BASE		0x00080000UL	/* always one */
 #define PSW_MASK_MCHECK		0x00040000UL
 #define PSW_MASK_WAIT		0x00020000UL
 #define PSW_MASK_PSTATE		0x00010000UL
 #define PSW_MASK_ASC		0x0000C000UL
 #define PSW_MASK_CC		0x00003000UL
 #define PSW_MASK_PM		0x00000F00UL
+#define PSW_MASK_EA		0x00000000UL
+#define PSW_MASK_BA		0x00000000UL
+
+#define PSW_MASK_USER		0x00003F00UL
 
 #define PSW_ADDR_AMODE		0x80000000UL
 #define PSW_ADDR_INSN		0x7FFFFFFFUL
 
-#define PSW_BASE_BITS		0x00080000UL
 #define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 20)
 
 #define PSW_ASC_PRIMARY		0x00000000UL
@@ -254,6 +258,7 @@ typedef struct
 #define PSW_MASK_DAT		0x0400000000000000UL
 #define PSW_MASK_IO		0x0200000000000000UL
 #define PSW_MASK_EXT		0x0100000000000000UL
+#define PSW_MASK_BASE		0x0000000000000000UL
 #define PSW_MASK_KEY		0x00F0000000000000UL
 #define PSW_MASK_MCHECK		0x0004000000000000UL
 #define PSW_MASK_WAIT		0x0002000000000000UL
@@ -261,12 +266,14 @@ typedef struct
 #define PSW_MASK_ASC		0x0000C00000000000UL
 #define PSW_MASK_CC		0x0000300000000000UL
 #define PSW_MASK_PM		0x00000F0000000000UL
+#define PSW_MASK_EA		0x0000000100000000UL
+#define PSW_MASK_BA		0x0000000080000000UL
+
+#define PSW_MASK_USER		0x00003F0180000000UL
 
 #define PSW_ADDR_AMODE		0x0000000000000000UL
 #define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
 
-#define PSW_BASE_BITS		0x0000000180000000UL
-#define PSW_BASE32_BITS		0x0000000080000000UL
 #define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 52)
 
 #define PSW_ASC_PRIMARY		0x0000000000000000UL
@@ -279,18 +286,7 @@ typedef struct
 #ifdef __KERNEL__
 extern long psw_kernel_bits;
 extern long psw_user_bits;
-#ifdef CONFIG_64BIT
-extern long psw_user32_bits;
 #endif
-#endif
-
-/* This macro merges a NEW PSW mask specified by the user into
-   the currently active PSW mask CURRENT, modifying only those
-   bits in CURRENT that the user may be allowed to change: this
-   is the condition code and the program mask bits.  */
-#define PSW_MASK_MERGE(CURRENT,NEW) \
-	(((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \
-	 ((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
 
 /*
  * The s390_regs structure is used to define the elf_gregset_t.
@@ -328,8 +324,7 @@ struct pt_regs
 	psw_t psw;
 	unsigned long gprs[NUM_GPRS];
 	unsigned long orig_gpr2;
-	unsigned short ilc;
-	unsigned short svcnr;
+	unsigned int svc_code;
 };
 
 /*
@@ -487,6 +482,8 @@ typedef struct
 #define PTRACE_POKETEXT_AREA	      0x5004
 #define PTRACE_POKEDATA_AREA 	      0x5005
 #define PTRACE_GET_LAST_BREAK	      0x5006
+#define PTRACE_PEEK_SYSTEM_CALL       0x5007
+#define PTRACE_POKE_SYSTEM_CALL	      0x5008
 
 /*
  * PT_PROT definition is loosely based on hppa bsd definition in
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/qdio.h linux-libre-3.2-gnu1/arch/s390/include/asm/qdio.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/qdio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/qdio.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,8 @@ struct qdesfmt0 {
 	u32	 : 16;
 } __attribute__ ((packed));
 
+#define QDR_AC_MULTI_BUFFER_ENABLE 0x01
+
 /**
  * struct qdr - queue description record (QDR)
  * @qfmt: queue format
@@ -123,6 +125,40 @@ struct slibe {
 };
 
 /**
+ * struct qaob - queue asynchronous operation block
+ * @res0: reserved parameters
+ * @res1: reserved parameter
+ * @res2: reserved parameter
+ * @res3: reserved parameter
+ * @aorc: asynchronous operation return code
+ * @flags: internal flags
+ * @cbtbs: control block type
+ * @sb_count: number of storage blocks
+ * @sba: storage block element addresses
+ * @dcount: size of storage block elements
+ * @user0: user defineable value
+ * @res4: reserved paramater
+ * @user1: user defineable value
+ * @user2: user defineable value
+ */
+struct qaob {
+	u64 res0[6];
+	u8 res1;
+	u8 res2;
+	u8 res3;
+	u8 aorc;
+	u8 flags;
+	u16 cbtbs;
+	u8 sb_count;
+	u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
+	u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
+	u64 user0;
+	u64 res4[2];
+	u64 user1;
+	u64 user2;
+} __attribute__ ((packed, aligned(256)));
+
+/**
  * struct slib - storage list information block (SLIB)
  * @nsliba: next SLIB address (if any)
  * @sla: SL address
@@ -222,9 +258,46 @@ struct slsb {
 	u8 val[QDIO_MAX_BUFFERS_PER_Q];
 } __attribute__ ((packed, aligned(256)));
 
+#define CHSC_AC2_MULTI_BUFFER_AVAILABLE	0x0080
+#define CHSC_AC2_MULTI_BUFFER_ENABLED	0x0040
 #define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
 #define CHSC_AC2_DATA_DIV_ENABLED	0x0002
 
+/**
+ * struct qdio_outbuf_state - SBAL related asynchronous operation information
+ *   (for communication with upper layer programs)
+ *   (only required for use with completion queues)
+ * @flags: flags indicating state of buffer
+ * @aob: pointer to QAOB used for the particular SBAL
+ * @user: pointer to upper layer program's state information related to SBAL
+ *        (stored in user1 data of QAOB)
+ */
+struct qdio_outbuf_state {
+	u8 flags;
+	struct qaob *aob;
+	void *user;
+};
+
+#define QDIO_OUTBUF_STATE_FLAG_NONE	0x00
+#define QDIO_OUTBUF_STATE_FLAG_PENDING	0x01
+
+#define CHSC_AC1_INITIATE_INPUTQ	0x80
+
+
+/* qdio adapter-characteristics-1 flag */
+#define AC1_SIGA_INPUT_NEEDED		0x40	/* process input queues */
+#define AC1_SIGA_OUTPUT_NEEDED		0x20	/* process output queues */
+#define AC1_SIGA_SYNC_NEEDED		0x10	/* ask hypervisor to sync */
+#define AC1_AUTOMATIC_SYNC_ON_THININT	0x08	/* set by hypervisor */
+#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI	0x04	/* set by hypervisor */
+#define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */
+#define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */
+
+#define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
+#define CHSC_AC2_DATA_DIV_ENABLED	0x0002
+
+#define CHSC_AC3_FORMAT2_CQ_AVAILABLE	0x8000
+
 struct qdio_ssqd_desc {
 	u8 flags;
 	u8:8;
@@ -243,8 +316,7 @@ struct qdio_ssqd_desc {
 	u64 sch_token;
 	u8 mro;
 	u8 mri;
-	u8:8;
-	u8 sbalic;
+	u16 qdioac3;
 	u16:16;
 	u8:8;
 	u8 mmwc;
@@ -280,13 +352,16 @@ typedef void qdio_handler_t(struct ccw_d
  * @no_output_qs: number of output queues
  * @input_handler: handler to be called for input queues
  * @output_handler: handler to be called for output queues
+ * @queue_start_poll: polling handlers (one per input queue or NULL)
  * @int_parm: interruption parameter
  * @input_sbal_addr_array:  address of no_input_qs * 128 pointers
  * @output_sbal_addr_array: address of no_output_qs * 128 pointers
+ * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
  */
 struct qdio_initialize {
 	struct ccw_device *cdev;
 	unsigned char q_format;
+	unsigned char qdr_ac;
 	unsigned char adapter_name[8];
 	unsigned int qib_param_field_format;
 	unsigned char *qib_param_field;
@@ -297,11 +372,12 @@ struct qdio_initialize {
 	unsigned int no_output_qs;
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
-	void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
+	void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
 	int scan_threshold;
 	unsigned long int_parm;
 	void **input_sbal_addr_array;
 	void **output_sbal_addr_array;
+	struct qdio_outbuf_state *output_sbal_state_array;
 };
 
 #define QDIO_STATE_INACTIVE		0x00000002 /* after qdio_cleanup */
@@ -316,6 +392,7 @@ struct qdio_initialize {
 extern int qdio_allocate(struct qdio_initialize *);
 extern int qdio_establish(struct qdio_initialize *);
 extern int qdio_activate(struct ccw_device *);
+extern void qdio_release_aob(struct qaob *);
 extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
 		   unsigned int);
 extern int qdio_start_irq(struct ccw_device *, int);
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/reset.h linux-libre-3.2-gnu1/arch/s390/include/asm/reset.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,5 @@ struct reset_call {
 
 extern void register_reset_call(struct reset_call *reset);
 extern void unregister_reset_call(struct reset_call *reset);
-extern void s390_reset_system(void);
+extern void s390_reset_system(void (*func)(void *), void *data);
 #endif /* _ASM_S390_RESET_H */
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/setup.h linux-libre-3.2-gnu1/arch/s390/include/asm/setup.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/setup.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/setup.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,15 +26,21 @@
 #define IPL_DEVICE        (*(unsigned long *)  (0x10404))
 #define INITRD_START      (*(unsigned long *)  (0x1040C))
 #define INITRD_SIZE       (*(unsigned long *)  (0x10414))
+#define OLDMEM_BASE	  (*(unsigned long *)  (0x1041C))
+#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10424))
 #else /* __s390x__ */
 #define IPL_DEVICE        (*(unsigned long *)  (0x10400))
 #define INITRD_START      (*(unsigned long *)  (0x10408))
 #define INITRD_SIZE       (*(unsigned long *)  (0x10410))
+#define OLDMEM_BASE	  (*(unsigned long *)  (0x10418))
+#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10420))
 #endif /* __s390x__ */
 #define COMMAND_LINE      ((char *)            (0x10480))
 
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY  1
+#define CHUNK_OLDMEM	 4
+#define CHUNK_CRASHK	 5
 
 struct mem_chunk {
 	unsigned long addr;
@@ -48,6 +54,8 @@ extern int memory_end_set;
 extern unsigned long memory_end;
 
 void detect_memory_layout(struct mem_chunk chunk[]);
+void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
+		     unsigned long size, int type);
 
 #define PRIMARY_SPACE_MODE	0
 #define ACCESS_REGISTER_MODE	1
@@ -74,6 +82,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_LPAR	(1UL << 12)
 #define MACHINE_FLAG_SPP	(1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY	(1UL << 14)
+#define MACHINE_FLAG_STCKF	(1UL << 15)
 
 #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -92,6 +101,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF	(0)
 #define MACHINE_HAS_SPP		(0)
 #define MACHINE_HAS_TOPOLOGY	(0)
+#define MACHINE_HAS_STCKF	(0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE	(1)
 #define MACHINE_HAS_CSP		(1)
@@ -103,9 +113,11 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_STCKF	(S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)
+#define ZFCPDUMP_HSA_SIZE_MAX	(64UL<<20)
 
 /*
  * Console mode. Override with conmode=
@@ -134,10 +146,14 @@ extern char kernel_nss_name[];
 #define IPL_DEVICE        0x10404
 #define INITRD_START      0x1040C
 #define INITRD_SIZE       0x10414
+#define OLDMEM_BASE	  0x1041C
+#define OLDMEM_SIZE	  0x10424
 #else /* __s390x__ */
 #define IPL_DEVICE        0x10400
 #define INITRD_START      0x10408
 #define INITRD_SIZE       0x10410
+#define OLDMEM_BASE	  0x10418
+#define OLDMEM_SIZE	  0x10420
 #endif /* __s390x__ */
 #define COMMAND_LINE      0x10480
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/sfp-util.h linux-libre-3.2-gnu1/arch/s390/include/asm/sfp-util.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/sfp-util.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/sfp-util.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,6 @@ extern unsigned long __udiv_qrnnd (unsig
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
-#define abort() return 0
+#define abort() BUG()
 
 #define __BYTE_ORDER __BIG_ENDIAN
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/smp.h linux-libre-3.2-gnu1/arch/s390/include/asm/smp.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@ extern struct save_area *zfcpdump_save_a
 extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
 extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
 			      int from, int to);
+extern void smp_restart_with_online_cpu(void);
 extern void smp_restart_cpu(void);
 
 /*
@@ -64,6 +65,10 @@ static inline void smp_switch_to_ipl_cpu
 	func(data);
 }
 
+static inline void smp_restart_with_online_cpu(void)
+{
+}
+
 #define smp_vcpu_scheduled	(1)
 
 #endif /* CONFIG_SMP */
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/spinlock.h linux-libre-3.2-gnu1/arch/s390/include/asm/spinlock.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/spinlock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 
 #include <linux/smp.h>
 
+extern int spin_retry;
+
 static inline int
 _raw_compare_and_swap(volatile unsigned int *lock,
 		      unsigned int old, unsigned int new)
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/syscall.h linux-libre-3.2-gnu1/arch/s390/include/asm/syscall.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/syscall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/syscall.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #define _ASM_SYSCALL_H	1
 
 #include <linux/sched.h>
+#include <linux/err.h>
 #include <asm/ptrace.h>
 
 /*
@@ -25,7 +26,8 @@ extern const unsigned int sys_call_table
 static inline long syscall_get_nr(struct task_struct *task,
 				  struct pt_regs *regs)
 {
-	return regs->svcnr ? regs->svcnr : -1;
+	return test_tsk_thread_flag(task, TIF_SYSCALL) ?
+		(regs->svc_code & 0xffff) : -1;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
@@ -37,7 +39,7 @@ static inline void syscall_rollback(stru
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 {
-	return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
+	return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/system.h linux-libre-3.2-gnu1/arch/s390/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 
 struct task_struct;
 
+extern int sysctl_userprocess_debug;
+
 extern struct task_struct *__switch_to(void *, void *);
 extern void update_per_regs(struct task_struct *task);
 
@@ -114,6 +116,8 @@ extern void pfault_fini(void);
 extern void cmma_init(void);
 extern int memcpy_real(void *, void *, size_t);
 extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
 
 #define finish_arch_switch(prev) do {					     \
 	set_fs(current->thread.mm_segment);				     \
@@ -210,8 +214,10 @@ __set_psw_mask(unsigned long mask)
 	__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
 }
 
-#define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
-#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+#define local_mcck_enable() \
+	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+#define local_mcck_disable() \
+	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
 
 #ifdef CONFIG_SMP
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/thread_info.h linux-libre-3.2-gnu1/arch/s390/include/asm/thread_info.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/thread_info.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/thread_info.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@ struct thread_info {
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct restart_block	restart_block;
+	unsigned int		system_call;
 	__u64			user_timer;
 	__u64			system_timer;
 	unsigned long		last_break;	/* last breaking-event-address. */
@@ -84,10 +85,10 @@ static inline struct thread_info *curren
 /*
  * thread information flags bit numbers
  */
+#define TIF_SYSCALL		0	/* inside a system call */
 #define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
-#define TIF_RESTART_SVC		4	/* restart svc with new svc number */
 #define TIF_PER_TRAP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
@@ -103,11 +104,11 @@ static inline struct thread_info *curren
 #define TIF_SINGLE_STEP		20	/* This task is single stepped */
 #define TIF_FREEZE		21	/* thread is freezing for suspend */
 
+#define _TIF_SYSCALL		(1<<TIF_SYSCALL)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
 #define _TIF_PER_TRAP		(1<<TIF_PER_TRAP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -117,7 +118,7 @@ static inline struct thread_info *curren
 #define _TIF_SIE		(1<<TIF_SIE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
-#define _TIF_SINGLE_STEP	(1<<TIF_FREEZE)
+#define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 #ifdef CONFIG_64BIT
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/timex.h linux-libre-3.2-gnu1/arch/s390/include/asm/timex.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,17 @@ static inline void get_clock_ext(char *c
 	asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 }
 
+static inline unsigned long long get_clock_fast(void)
+{
+	unsigned long long clk;
+
+	if (MACHINE_HAS_STCKF)
+		asm volatile(".insn	s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
+	else
+		clk = get_clock();
+	return clk;
+}
+
 static inline unsigned long long get_clock_xt(void)
 {
 	unsigned char clk[16];
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/tlbflush.h linux-libre-3.2-gnu1/arch/s390/include/asm/tlbflush.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/tlbflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@ static inline void __tlb_flush_full(stru
 }
 #else
 #define __tlb_flush_full(mm)	__tlb_flush_local()
+#define __tlb_flush_global()	__tlb_flush_local()
 #endif
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/s390/include/asm/unistd.h linux-libre-3.2-gnu1/arch/s390/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/s390/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -277,7 +277,9 @@
 #define __NR_clock_adjtime	337
 #define __NR_syncfs		338
 #define __NR_setns		339
-#define NR_syscalls 340
+#define __NR_process_vm_readv	340
+#define __NR_process_vm_writev	341
+#define NR_syscalls 342
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -druNp linux-libre-3.1-gnu1/arch/s390/Kconfig linux-libre-3.2-gnu1/arch/s390/Kconfig
--- linux-libre-3.1-gnu1/arch/s390/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -91,6 +91,7 @@ config S390
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
 	select HAVE_RCU_TABLE_FREE if SMP
+	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_INLINE_SPIN_TRYLOCK
 	select ARCH_INLINE_SPIN_TRYLOCK_BH
 	select ARCH_INLINE_SPIN_LOCK
@@ -568,6 +569,17 @@ config KEXEC
 	  current kernel, and to start another kernel.  It is like a reboot
 	  but is independent of hardware/microcode support.
 
+config CRASH_DUMP
+	bool "kernel crash dumps"
+	depends on 64BIT
+	select KEXEC
+	help
+	  Generate crash dump after being started by kexec.
+	  Crash dump kernels are loaded in the main kernel with kexec-tools
+	  into a specially reserved region and then later executed after
+	  a crash by kdump/kexec.
+	  For more details see Documentation/kdump/kdump.txt
+
 config ZFCPDUMP
 	def_bool n
 	prompt "zfcpdump support"
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/asm-offsets.c linux-libre-3.2-gnu1/arch/s390/kernel/asm-offsets.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,8 +45,7 @@ int main(void)
 	DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
 	DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
 	DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
-	DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
-	DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
+	DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code));
 	DEFINE(__PT_SIZE, sizeof(struct pt_regs));
 	BLANK();
 	DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
@@ -141,7 +140,6 @@ int main(void)
 	DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
 	DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
 	DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
-	DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64));
 #ifdef CONFIG_32BIT
 	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
 #else /* CONFIG_32BIT */
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/base.S linux-libre-3.2-gnu1/arch/s390/kernel/base.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/base.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/base.S	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,8 @@ s390_base_pgm_handler_fn:
 ENTRY(diag308_reset)
 	larl	%r4,.Lctlregs		# Save control registers
 	stctg	%c0,%c15,0(%r4)
+	larl	%r4,.Lfpctl		# Floating point control register
+	stfpc	0(%r4)
 	larl	%r4,.Lrestart_psw	# Setup restart PSW at absolute 0
 	lghi	%r3,0
 	lg	%r4,0(%r4)		# Save PSW
@@ -99,6 +101,8 @@ ENTRY(diag308_reset)
 	sam64				# Switch to 64 bit addressing mode
 	larl	%r4,.Lctlregs		# Restore control registers
 	lctlg	%c0,%c15,0(%r4)
+	larl	%r4,.Lfpctl		# Restore floating point ctl register
+	lfpc	0(%r4)
 	br	%r14
 .align 16
 .Lrestart_psw:
@@ -110,6 +114,8 @@ ENTRY(diag308_reset)
 	.rept	16
 	.quad	0
 	.endr
+.Lfpctl:
+	.long	0
 	.previous
 
 #else /* CONFIG_64BIT */
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/compat_linux.c linux-libre-3.2-gnu1/arch/s390/kernel/compat_linux.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/compat_linux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/compat_linux.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,12 +60,9 @@
 
 #include "compat_linux.h"
 
-long psw_user32_bits	= (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
-long psw32_user_bits	= (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
-			   PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
-			   PSW32_MASK_PSTATE);
+u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
+		      PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
+		      PSW32_MASK_PSTATE | PSW32_ASC_HOME;
  
 /* For this source file, we want overflow handling. */
 
@@ -365,12 +362,7 @@ asmlinkage long sys32_rt_sigprocmask(int
 	if (set) {
 		if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
 			return -EFAULT;
-		switch (_NSIG_WORDS) {
-		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
-		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
-		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
-		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
-		}
+		s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 	}
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigprocmask(how,
@@ -380,12 +372,8 @@ asmlinkage long sys32_rt_sigprocmask(int
 	set_fs (old_fs);
 	if (ret) return ret;
 	if (oset) {
-		switch (_NSIG_WORDS) {
-		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
-		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
-		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
-		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
-		}
+		s32.sig[1] = (s.sig[0] >> 32);
+		s32.sig[0] = s.sig[0];
 		if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
 			return -EFAULT;
 	}
@@ -404,12 +392,8 @@ asmlinkage long sys32_rt_sigpending(comp
 	ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
 	set_fs (old_fs);
 	if (!ret) {
-		switch (_NSIG_WORDS) {
-		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
-		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
-		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
-		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
-		}
+		s32.sig[1] = (s.sig[0] >> 32);
+		s32.sig[0] = s.sig[0];
 		if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
 			return -EFAULT;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/compat_signal.c linux-libre-3.2-gnu1/arch/s390/kernel/compat_signal.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/compat_signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/compat_signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,8 @@ int copy_siginfo_from_user32(siginfo_t *
 			break;
 		case __SI_FAULT >> 16:
 			err |= __get_user(tmp, &from->si_addr);
-			to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
+			to->si_addr = (void __force __user *)
+				(u64) (tmp & PSW32_ADDR_INSN);
 			break;
 		case __SI_POLL >> 16:
 			err |= __get_user(to->si_band, &from->si_band);
@@ -213,16 +214,8 @@ sys32_rt_sigaction(int sig, const struct
 		ret = get_user(sa_handler, &act->sa_handler);
 		ret |= __copy_from_user(&set32, &act->sa_mask,
 					sizeof(compat_sigset_t));
-		switch (_NSIG_WORDS) {
-		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
-				| (((long)set32.sig[7]) << 32);
-		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
-				| (((long)set32.sig[5]) << 32);
-		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
-				| (((long)set32.sig[3]) << 32);
-		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
-				| (((long)set32.sig[1]) << 32);
-		}
+		new_ka.sa.sa_mask.sig[0] =
+			set32.sig[0] | (((long)set32.sig[1]) << 32);
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		
 		if (ret)
@@ -233,20 +226,8 @@ sys32_rt_sigaction(int sig, const struct
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		switch (_NSIG_WORDS) {
-		case 4:
-			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
-			set32.sig[6] = old_ka.sa.sa_mask.sig[3];
-		case 3:
-			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
-			set32.sig[4] = old_ka.sa.sa_mask.sig[2];
-		case 2:
-			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
-			set32.sig[2] = old_ka.sa.sa_mask.sig[1];
-		case 1:
-			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
-			set32.sig[0] = old_ka.sa.sa_mask.sig[0];
-		}
+		set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+		set32.sig[0] = old_ka.sa.sa_mask.sig[0];
 		ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
 		ret |= __copy_to_user(&oact->sa_mask, &set32,
 				      sizeof(compat_sigset_t));
@@ -300,9 +281,10 @@ static int save_sigregs32(struct pt_regs
 	_s390_regs_common32 regs32;
 	int err, i;
 
-	regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
-					   (__u32)(regs->psw.mask >> 32));
-	regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
+	regs32.psw.mask = psw32_user_bits |
+		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
+	regs32.psw.addr = (__u32) regs->psw.addr |
+		(__u32)(regs->psw.mask & PSW_MASK_BA);
 	for (i = 0; i < NUM_GPRS; i++)
 		regs32.gprs[i] = (__u32) regs->gprs[i];
 	save_access_regs(current->thread.acrs);
@@ -327,8 +309,9 @@ static int restore_sigregs32(struct pt_r
 	err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
 	if (err)
 		return err;
-	regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
-				        (__u64)regs32.psw.mask << 32);
+	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+		(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
+		(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
 	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
 	for (i = 0; i < NUM_GPRS; i++)
 		regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -342,7 +325,7 @@ static int restore_sigregs32(struct pt_r
 		return err;
 
 	restore_fp_regs(&current->thread.fp_regs);
-	regs->svcnr = 0;	/* disable syscall checks */
+	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
 
@@ -496,11 +479,11 @@ static int setup_frame32(int sig, struct
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
 	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->gprs[14] = (__u64) ka->sa.sa_restorer;
+		regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
 	} else {
-		regs->gprs[14] = (__u64) frame->retcode;
+		regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
-		               (u16 __user *)(frame->retcode)))
+			       (u16 __force __user *)(frame->retcode)))
 			goto give_sigsegv;
         }
 
@@ -509,11 +492,12 @@ static int setup_frame32(int sig, struct
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->gprs[15] = (__u64) frame;
-	regs->psw.addr = (__u64) ka->sa.sa_handler;
+	regs->gprs[15] = (__force __u64) frame;
+	regs->psw.mask |= PSW_MASK_BA;		/* force amode 31 */
+	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
 	regs->gprs[2] = map_signal(sig);
-	regs->gprs[3] = (__u64) &frame->sc;
+	regs->gprs[3] = (__force __u64) &frame->sc;
 
 	/* We forgot to include these in the sigcontext.
 	   To avoid breaking binary compatibility, they are passed as args. */
@@ -521,7 +505,7 @@ static int setup_frame32(int sig, struct
 	regs->gprs[5] = current->thread.prot_addr;
 
 	/* Place signal number on stack to allow backtrace from handler.  */
-	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+	if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
 		goto give_sigsegv;
 	return 0;
 
@@ -564,20 +548,21 @@ static int setup_rt_frame32(int sig, str
 	} else {
 		regs->gprs[14] = (__u64) frame->retcode;
 		err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-		                  (u16 __user *)(frame->retcode));
+				  (u16 __force __user *)(frame->retcode));
 	}
 
 	/* Set up backchain. */
-	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
+	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->gprs[15] = (__u64) frame;
+	regs->gprs[15] = (__force __u64) frame;
+	regs->psw.mask |= PSW_MASK_BA;		/* force amode 31 */
 	regs->psw.addr = (__u64) ka->sa.sa_handler;
 
 	regs->gprs[2] = map_signal(sig);
-	regs->gprs[3] = (__u64) &frame->info;
-	regs->gprs[4] = (__u64) &frame->uc;
+	regs->gprs[3] = (__force __u64) &frame->info;
+	regs->gprs[4] = (__force __u64) &frame->uc;
 	return 0;
 
 give_sigsegv:
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/compat_wrapper.S linux-libre-3.2-gnu1/arch/s390/kernel/compat_wrapper.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/compat_wrapper.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/compat_wrapper.S	2012-01-04 18:55:44.000000000 -0500
@@ -1623,8 +1623,27 @@ ENTRY(sys_syncfs_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_syncfs
 
-	.globl	sys_setns_wrapper
-sys_setns_wrapper:
+ENTRY(sys_setns_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_setns
+
+ENTRY(compat_sys_process_vm_readv_wrapper)
+	lgfr	%r2,%r2			# compat_pid_t
+	llgtr	%r3,%r3			# struct compat_iovec __user *
+	llgfr	%r4,%r4			# unsigned long
+	llgtr	%r5,%r5			# struct compat_iovec __user *
+	llgfr	%r6,%r6			# unsigned long
+	llgf	%r0,164(%r15)		# unsigned long
+	stg	%r0,160(%r15)
+	jg	sys_process_vm_readv
+
+ENTRY(compat_sys_process_vm_writev_wrapper)
+	lgfr	%r2,%r2			# compat_pid_t
+	llgtr	%r3,%r3			# struct compat_iovec __user *
+	llgfr	%r4,%r4			# unsigned long
+	llgtr	%r5,%r5			# struct compat_iovec __user *
+	llgfr	%r6,%r6			# unsigned long
+	llgf	%r0,164(%r15)		# unsigned long
+	stg	%r0,160(%r15)
+	jg	sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/crash_dump.c linux-libre-3.2-gnu1/arch/s390/kernel/crash_dump.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/crash_dump.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/s390/kernel/crash_dump.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,426 @@
+/*
+ * S390 kdump implementation
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <linux/crash_dump.h>
+#include <asm/lowcore.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <linux/elf.h>
+#include <asm/ipl.h>
+
+#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
+#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
+#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
+
+/*
+ * Copy one page from "oldmem"
+ *
+ * For the kdump reserved memory this functions performs a swap operation:
+ *  - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
+ *  - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset, int userbuf)
+{
+	unsigned long src;
+
+	if (!csize)
+		return 0;
+
+	src = (pfn << PAGE_SHIFT) + offset;
+	if (src < OLDMEM_SIZE)
+		src += OLDMEM_BASE;
+	else if (src > OLDMEM_BASE &&
+		 src < OLDMEM_BASE + OLDMEM_SIZE)
+		src -= OLDMEM_BASE;
+	if (userbuf)
+		copy_to_user_real((void __force __user *) buf, (void *) src,
+				  csize);
+	else
+		memcpy_real(buf, (void *) src, csize);
+	return csize;
+}
+
+/*
+ * Copy memory from old kernel
+ */
+static int copy_from_oldmem(void *dest, void *src, size_t count)
+{
+	unsigned long copied = 0;
+	int rc;
+
+	if ((unsigned long) src < OLDMEM_SIZE) {
+		copied = min(count, OLDMEM_SIZE - (unsigned long) src);
+		rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
+		if (rc)
+			return rc;
+	}
+	return memcpy_real(dest + copied, src + copied, count - copied);
+}
+
+/*
+ * Alloc memory and panic in case of ENOMEM
+ */
+static void *kzalloc_panic(int len)
+{
+	void *rc;
+
+	rc = kzalloc(len, GFP_KERNEL);
+	if (!rc)
+		panic("s390 kdump kzalloc (%d) failed", len);
+	return rc;
+}
+
+/*
+ * Get memory layout and create hole for oldmem
+ */
+static struct mem_chunk *get_memory_layout(void)
+{
+	struct mem_chunk *chunk_array;
+
+	chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
+	detect_memory_layout(chunk_array);
+	create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
+	return chunk_array;
+}
+
+/*
+ * Initialize ELF note
+ */
+static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len,
+		     const char *name)
+{
+	Elf64_Nhdr *note;
+	u64 len;
+
+	note = (Elf64_Nhdr *)buf;
+	note->n_namesz = strlen(name) + 1;
+	note->n_descsz = d_len;
+	note->n_type = type;
+	len = sizeof(Elf64_Nhdr);
+
+	memcpy(buf + len, name, note->n_namesz);
+	len = roundup(len + note->n_namesz, 4);
+
+	memcpy(buf + len, desc, note->n_descsz);
+	len = roundup(len + note->n_descsz, 4);
+
+	return PTR_ADD(buf, len);
+}
+
+/*
+ * Initialize prstatus note
+ */
+static void *nt_prstatus(void *ptr, struct save_area *sa)
+{
+	struct elf_prstatus nt_prstatus;
+	static int cpu_nr = 1;
+
+	memset(&nt_prstatus, 0, sizeof(nt_prstatus));
+	memcpy(&nt_prstatus.pr_reg.gprs, sa->gp_regs, sizeof(sa->gp_regs));
+	memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
+	memcpy(&nt_prstatus.pr_reg.acrs, sa->acc_regs, sizeof(sa->acc_regs));
+	nt_prstatus.pr_pid = cpu_nr;
+	cpu_nr++;
+
+	return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
+			 "CORE");
+}
+
+/*
+ * Initialize fpregset (floating point) note
+ */
+static void *nt_fpregset(void *ptr, struct save_area *sa)
+{
+	elf_fpregset_t nt_fpregset;
+
+	memset(&nt_fpregset, 0, sizeof(nt_fpregset));
+	memcpy(&nt_fpregset.fpc, &sa->fp_ctrl_reg, sizeof(sa->fp_ctrl_reg));
+	memcpy(&nt_fpregset.fprs, &sa->fp_regs, sizeof(sa->fp_regs));
+
+	return nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset),
+		       "CORE");
+}
+
+/*
+ * Initialize timer note
+ */
+static void *nt_s390_timer(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer),
+			 KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD clock comparator note
+ */
+static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp,
+		       sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD programmable register note
+ */
+static void *nt_s390_tod_preg(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg,
+		       sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize control register note
+ */
+static void *nt_s390_ctrs(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs,
+		       sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize prefix register note
+ */
+static void *nt_s390_prefix(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg,
+			 sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Fill ELF notes for one CPU with save area registers
+ */
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
+{
+	ptr = nt_prstatus(ptr, sa);
+	ptr = nt_fpregset(ptr, sa);
+	ptr = nt_s390_timer(ptr, sa);
+	ptr = nt_s390_tod_cmp(ptr, sa);
+	ptr = nt_s390_tod_preg(ptr, sa);
+	ptr = nt_s390_ctrs(ptr, sa);
+	ptr = nt_s390_prefix(ptr, sa);
+	return ptr;
+}
+
+/*
+ * Initialize prpsinfo note (new kernel)
+ */
+static void *nt_prpsinfo(void *ptr)
+{
+	struct elf_prpsinfo prpsinfo;
+
+	memset(&prpsinfo, 0, sizeof(prpsinfo));
+	prpsinfo.pr_sname = 'R';
+	strcpy(prpsinfo.pr_fname, "vmlinux");
+	return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
+		       KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize vmcoreinfo note (new kernel)
+ */
+static void *nt_vmcoreinfo(void *ptr)
+{
+	char nt_name[11], *vmcoreinfo;
+	Elf64_Nhdr note;
+	void *addr;
+
+	if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
+		return ptr;
+	memset(nt_name, 0, sizeof(nt_name));
+	if (copy_from_oldmem(&note, addr, sizeof(note)))
+		return ptr;
+	if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
+		return ptr;
+	if (strcmp(nt_name, "VMCOREINFO") != 0)
+		return ptr;
+	vmcoreinfo = kzalloc_panic(note.n_descsz + 1);
+	if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
+		return ptr;
+	vmcoreinfo[note.n_descsz + 1] = 0;
+	return nt_init(ptr, 0, vmcoreinfo, note.n_descsz, "VMCOREINFO");
+}
+
+/*
+ * Initialize ELF header (new kernel)
+ */
+static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
+{
+	memset(ehdr, 0, sizeof(*ehdr));
+	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+	ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
+	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
+	ehdr->e_type = ET_CORE;
+	ehdr->e_machine = EM_S390;
+	ehdr->e_version = EV_CURRENT;
+	ehdr->e_phoff = sizeof(Elf64_Ehdr);
+	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
+	ehdr->e_phentsize = sizeof(Elf64_Phdr);
+	ehdr->e_phnum = mem_chunk_cnt + 1;
+	return ehdr + 1;
+}
+
+/*
+ * Return CPU count for ELF header (new kernel)
+ */
+static int get_cpu_cnt(void)
+{
+	int i, cpus = 0;
+
+	for (i = 0; zfcpdump_save_areas[i]; i++) {
+		if (zfcpdump_save_areas[i]->pref_reg == 0)
+			continue;
+		cpus++;
+	}
+	return cpus;
+}
+
+/*
+ * Return memory chunk count for ELF header (new kernel)
+ */
+static int get_mem_chunk_cnt(void)
+{
+	struct mem_chunk *chunk_array, *mem_chunk;
+	int i, cnt = 0;
+
+	chunk_array = get_memory_layout();
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		mem_chunk = &chunk_array[i];
+		if (chunk_array[i].type != CHUNK_READ_WRITE &&
+		    chunk_array[i].type != CHUNK_READ_ONLY)
+			continue;
+		if (mem_chunk->size == 0)
+			continue;
+		cnt++;
+	}
+	kfree(chunk_array);
+	return cnt;
+}
+
+/*
+ * Relocate pointer in order to allow vmcore code access the data
+ */
+static inline unsigned long relocate(unsigned long addr)
+{
+	return OLDMEM_BASE + addr;
+}
+
+/*
+ * Initialize ELF loads (new kernel)
+ */
+static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
+{
+	struct mem_chunk *chunk_array, *mem_chunk;
+	int i;
+
+	chunk_array = get_memory_layout();
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		mem_chunk = &chunk_array[i];
+		if (mem_chunk->size == 0)
+			break;
+		if (chunk_array[i].type != CHUNK_READ_WRITE &&
+		    chunk_array[i].type != CHUNK_READ_ONLY)
+			continue;
+		else
+			phdr->p_filesz = mem_chunk->size;
+		phdr->p_type = PT_LOAD;
+		phdr->p_offset = mem_chunk->addr;
+		phdr->p_vaddr = mem_chunk->addr;
+		phdr->p_paddr = mem_chunk->addr;
+		phdr->p_memsz = mem_chunk->size;
+		phdr->p_flags = PF_R | PF_W | PF_X;
+		phdr->p_align = PAGE_SIZE;
+		phdr++;
+	}
+	kfree(chunk_array);
+	return i;
+}
+
+/*
+ * Initialize notes (new kernel)
+ */
+static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
+{
+	struct save_area *sa;
+	void *ptr_start = ptr;
+	int i;
+
+	ptr = nt_prpsinfo(ptr);
+
+	for (i = 0; zfcpdump_save_areas[i]; i++) {
+		sa = zfcpdump_save_areas[i];
+		if (sa->pref_reg == 0)
+			continue;
+		ptr = fill_cpu_elf_notes(ptr, sa);
+	}
+	ptr = nt_vmcoreinfo(ptr);
+	memset(phdr, 0, sizeof(*phdr));
+	phdr->p_type = PT_NOTE;
+	phdr->p_offset = relocate(notes_offset);
+	phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
+	phdr->p_memsz = phdr->p_filesz;
+	return ptr;
+}
+
+/*
+ * Create ELF core header (new kernel)
+ */
+static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
+{
+	Elf64_Phdr *phdr_notes, *phdr_loads;
+	int mem_chunk_cnt;
+	void *ptr, *hdr;
+	u32 alloc_size;
+	u64 hdr_off;
+
+	mem_chunk_cnt = get_mem_chunk_cnt();
+
+	alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
+		mem_chunk_cnt * sizeof(Elf64_Phdr);
+	hdr = kzalloc_panic(alloc_size);
+	/* Init elf header */
+	ptr = ehdr_init(hdr, mem_chunk_cnt);
+	/* Init program headers */
+	phdr_notes = ptr;
+	ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
+	phdr_loads = ptr;
+	ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
+	/* Init notes */
+	hdr_off = PTR_DIFF(ptr, hdr);
+	ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
+	/* Init loads */
+	hdr_off = PTR_DIFF(ptr, hdr);
+	loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
+	*elfcorebuf_sz = hdr_off;
+	*elfcorebuf = (void *) relocate((unsigned long) hdr);
+	BUG_ON(*elfcorebuf_sz > alloc_size);
+}
+
+/*
+ * Create kdump ELF core header in new kernel, if it has not been passed via
+ * the "elfcorehdr" kernel parameter
+ */
+static int setup_kdump_elfcorehdr(void)
+{
+	size_t elfcorebuf_sz;
+	char *elfcorebuf;
+
+	if (!OLDMEM_BASE || is_kdump_kernel())
+		return -EINVAL;
+	s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
+	elfcorehdr_addr = (unsigned long long) elfcorebuf;
+	elfcorehdr_size = elfcorebuf_sz;
+	return 0;
+}
+
+subsys_initcall(setup_kdump_elfcorehdr);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/early.c linux-libre-3.2-gnu1/arch/s390/kernel/early.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/early.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/early.c	2012-01-04 18:55:44.000000000 -0500
@@ -252,7 +252,7 @@ static noinline __init void setup_lowcor
 {
 	psw_t psw;
 
-	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
 	S390_lowcore.external_new_psw = psw;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
@@ -390,6 +390,8 @@ static __init void detect_machine_facili
 		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 	if (test_facility(40))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+	if (test_facility(25))
+		S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/entry64.S linux-libre-3.2-gnu1/arch/s390/kernel/entry64.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/entry64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/entry64.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,19 +43,18 @@ SP_R13	     =	STACK_FRAME_OVERHEAD + __P
 SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 112
 SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 120
 SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR      =	STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE  =	STACK_FRAME_OVERHEAD + __PT_SVC_CODE
 SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
-		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+		 _TIF_MCCK_PENDING | _TIF_PER_TRAP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
-		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+		 _TIF_SYSCALL_TRACEPOINT)
 _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
@@ -249,9 +248,10 @@ ENTRY(system_call)
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),_TIF_SYSCALL
 sysc_vtime:
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -260,14 +260,14 @@ sysc_update:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 	LAST_BREAK
 sysc_do_svc:
-	llgh	%r7,SP_SVCNR(%r15)
+	llgh	%r7,SP_SVC_CODE+2(%r15)
 	slag	%r7,%r7,2	# shift and test for svc 0
 	jnz	sysc_nr_ok
 	# svc 0: system call number in %r1
 	llgfr	%r1,%r1		# clear high word in r1
 	cghi	%r1,NR_syscalls
 	jnl	sysc_nr_ok
-	sth	%r1,SP_SVCNR(%r15)
+	sth	%r1,SP_SVC_CODE+2(%r15)
 	slag	%r7,%r1,2	# shift and test for svc 0
 sysc_nr_ok:
 	larl	%r10,sys_call_table
@@ -277,7 +277,7 @@ sysc_nr_ok:
 	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls
 sysc_noemu:
 #endif
-	tm	__TI_flags+6(%r12),_TIF_SYSCALL
+	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8
 	mvc	SP_ARGS(8,%r15),SP_R7(%r15)
 	lgf	%r8,0(%r7,%r10) # load address of system call routine
 	jnz	sysc_tracesys
@@ -287,23 +287,19 @@ sysc_noemu:
 sysc_return:
 	LOCKDEP_SYS_EXIT
 sysc_tif:
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
+	jno	sysc_restore
 	tm	__TI_flags+7(%r12),_TIF_WORK_SVC
 	jnz	sysc_work	# there is work to do (signals etc.)
+	ni	__TI_flags+7(%r12),255-_TIF_SYSCALL
 sysc_restore:
 	RESTORE_ALL __LC_RETURN_PSW,1
 sysc_done:
 
 #
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
-	tm	SP_PSW+1(%r15),0x01	# returning to user ?
-	jno	sysc_restore
-
-#
 # One of the work bits is on. Find out which one.
 #
-sysc_work_tif:
+sysc_work:
 	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
 	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
@@ -312,8 +308,6 @@ sysc_work_tif:
 	jo	sysc_sigpending
 	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME
 	jo	sysc_notify_resume
-	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
-	jo	sysc_restart
 	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
 	jo	sysc_singlestep
 	j	sysc_return		# beware of critical section cleanup
@@ -339,11 +333,15 @@ sysc_sigpending:
 	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	brasl	%r14,do_signal		# call do_signal
-	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
-	jo	sysc_restart
-	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
-	jo	sysc_singlestep
-	j	sysc_return
+	tm	__TI_flags+7(%r12),_TIF_SYSCALL
+	jno	sysc_return
+	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	lghi	%r7,0			# svc 0 returns -ENOSYS
+	lh	%r1,SP_SVC_CODE+2(%r15)	# load new svc number
+	cghi	%r1,NR_syscalls
+	jnl	sysc_nr_ok		# invalid svc number -> do svc 0
+	slag	%r7,%r1,2
+	j	sysc_nr_ok		# restart svc
 
 #
 # _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -354,23 +352,10 @@ sysc_notify_resume:
 	jg	do_notify_resume	# call do_notify_resume
 
 #
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
-	ni	__TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	lg	%r7,SP_R2(%r15)		# load new svc number
-	mvc	SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
-	sth	%r7,SP_SVCNR(%r15)
-	slag	%r7,%r7,2
-	j	sysc_nr_ok		# restart svc
-
-#
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP	# clear TIF_PER_TRAP
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
+	ni	__TI_flags+7(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	larl	%r14,sysc_return	# load adr. of system return
 	jg	do_per_trap
@@ -382,7 +367,7 @@ sysc_singlestep:
 sysc_tracesys:
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
-	llgh	%r0,SP_SVCNR(%r15)
+	llgh	%r0,SP_SVC_CODE+2(%r15)
 	stg	%r0,SP_R2(%r15)
 	brasl	%r14,do_syscall_trace_enter
 	lghi	%r0,NR_syscalls
@@ -397,7 +382,7 @@ sysc_tracego:
 	basr	%r14,%r8		# call sys_xxx
 	stg	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+6(%r12),_TIF_SYSCALL
+	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8
 	jz	sysc_return
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	larl	%r14,sysc_return	# return point is sysc_return
@@ -470,7 +455,6 @@ ENTRY(pgm_check_handler)
 	jnz	pgm_per 		 # got per exception -> special case
 	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	xc	SP_ILC(4,%r15),SP_ILC(%r15)
 	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	HANDLE_SIE_INTERCEPT
@@ -550,9 +534,10 @@ pgm_exit2:
 pgm_svcper:
 	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -561,7 +546,6 @@ pgm_svcper:
 	mvc	__THREAD_per_cause(2,%r8),__LC_PER_CAUSE
 	mvc	__THREAD_per_address(8,%r8),__LC_PER_ADDRESS
 	mvc	__THREAD_per_paid(1,%r8),__LC_PER_PAID
-	oi	__TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	j	sysc_do_svc
@@ -571,7 +555,6 @@ pgm_svcper:
 #
 kernel_per:
 	REENABLE_IRQS
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)	# clear svc number
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	brasl	%r14,do_per_trap
 	j	pgm_exit
@@ -869,12 +852,12 @@ restart_go:
 # PSW restart interrupt handler
 #
 ENTRY(psw_restart_int_handler)
-	stg	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
+	stg	%r15,__LC_SAVE_AREA+120(%r0)	# save r15
 	larl	%r15,restart_stack		# load restart stack
 	lg	%r15,0(%r15)
 	aghi	%r15,-SP_SIZE			# make room for pt_regs
 	stmg	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
-	mvc	SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+	mvc	SP_R15(8,%r15),__LC_SAVE_AREA+120(%r0)# store saved %r15 to stack
 	mvc	SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
 	brasl	%r14,do_restart
@@ -972,9 +955,11 @@ cleanup_system_call:
 	stg	%r15,32(%r12)
 	stg	%r11,0(%r12)
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	mvc	8(8,%r12),__LC_THREAD_INFO
+	lg	%r12,__LC_THREAD_INFO
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),_TIF_SYSCALL
 cleanup_vtime:
 	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
 	jhe	cleanup_stime
@@ -1096,6 +1081,7 @@ sie_exit:
 	lghi	%r2,0
 	br	%r14
 sie_fault:
+	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/entry.h linux-libre-3.2-gnu1/arch/s390/kernel/entry.h
--- linux-libre-3.1-gnu1/arch/s390/kernel/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,24 +5,33 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 
+
+extern void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
+extern void *restart_stack;
+
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
+
 void do_protection_exception(struct pt_regs *, long, unsigned long);
 void do_dat_exception(struct pt_regs *, long, unsigned long);
 void do_asce_exception(struct pt_regs *, long, unsigned long);
 
-extern int sysctl_userprocess_debug;
-
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
 void do_signal(struct pt_regs *regs);
 int handle_signal32(unsigned long sig, struct k_sigaction *ka,
 		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+void do_notify_resume(struct pt_regs *regs);
 
 void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
+void do_restart(void);
 int __cpuinit start_secondary(void *cpuvoid);
 void __init startup_init(void);
 void die(const char * str, struct pt_regs * regs, long err);
 
+void __init time_init(void);
+
 struct s390_mmap_arg_struct;
 struct fadvise64_64_args;
 struct old_sigaction;
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/entry.S linux-libre-3.2-gnu1/arch/s390/kernel/entry.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,16 +43,15 @@ SP_R13	     =	STACK_FRAME_OVERHEAD + __P
 SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
 SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 60
 SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR     =	STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE  =	STACK_FRAME_OVERHEAD + __PT_SVC_CODE
 SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
-		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+		 _TIF_MCCK_PENDING | _TIF_PER_TRAP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
-		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+		 _TIF_SYSCALL_TRACEPOINT)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -228,9 +227,10 @@ ENTRY(system_call)
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),_TIF_SYSCALL
 sysc_vtime:
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -239,17 +239,17 @@ sysc_update:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 sysc_do_svc:
 	xr	%r7,%r7
-	icm	%r7,3,SP_SVCNR(%r15)	# load svc number and test for svc 0
+	icm	%r7,3,SP_SVC_CODE+2(%r15)# load svc number and test for svc 0
 	bnz	BASED(sysc_nr_ok)	# svc number > 0
 	# svc 0: system call number in %r1
 	cl	%r1,BASED(.Lnr_syscalls)
 	bnl	BASED(sysc_nr_ok)
-	sth	%r1,SP_SVCNR(%r15)
+	sth	%r1,SP_SVC_CODE+2(%r15)
 	lr	%r7,%r1 	  # copy svc number to %r7
 sysc_nr_ok:
 	sll	%r7,2		  # svc number *4
 	l	%r10,BASED(.Lsysc_table)
-	tm	__TI_flags+2(%r12),_TIF_SYSCALL
+	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
 	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
 	l	%r8,0(%r7,%r10)	  # get system call addr.
 	bnz	BASED(sysc_tracesys)
@@ -259,23 +259,19 @@ sysc_nr_ok:
 sysc_return:
 	LOCKDEP_SYS_EXIT
 sysc_tif:
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
+	bno	BASED(sysc_restore)
 	tm	__TI_flags+3(%r12),_TIF_WORK_SVC
 	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
+	ni	__TI_flags+3(%r12),255-_TIF_SYSCALL
 sysc_restore:
 	RESTORE_ALL __LC_RETURN_PSW,1
 sysc_done:
 
 #
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
-	tm	SP_PSW+1(%r15),0x01	# returning to user ?
-	bno	BASED(sysc_restore)
-
-#
 # One of the work bits is on. Find out which one.
 #
-sysc_work_tif:
+sysc_work:
 	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
 	bo	BASED(sysc_mcck_pending)
 	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
@@ -284,8 +280,6 @@ sysc_work_tif:
 	bo	BASED(sysc_sigpending)
 	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
 	bo	BASED(sysc_notify_resume)
-	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
-	bo	BASED(sysc_restart)
 	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
 	bo	BASED(sysc_singlestep)
 	b	BASED(sysc_return)	# beware of critical section cleanup
@@ -314,11 +308,14 @@ sysc_sigpending:
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	l	%r1,BASED(.Ldo_signal)
 	basr	%r14,%r1		# call do_signal
-	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
-	bo	BASED(sysc_restart)
-	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
-	bo	BASED(sysc_singlestep)
-	b	BASED(sysc_return)
+	tm	__TI_flags+3(%r12),_TIF_SYSCALL
+	bno	BASED(sysc_return)
+	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	xr	%r7,%r7			# svc 0 returns -ENOSYS
+	clc	SP_SVC_CODE+2(2,%r15),BASED(.Lnr_syscalls+2)
+	bnl	BASED(sysc_nr_ok)	# invalid svc number -> do svc 0
+	icm	%r7,3,SP_SVC_CODE+2(%r15)# load new svc number
+	b	BASED(sysc_nr_ok)	# restart svc
 
 #
 # _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -329,24 +326,11 @@ sysc_notify_resume:
 	la	%r14,BASED(sysc_return)
 	br	%r1			# call do_notify_resume
 
-
-#
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
-	ni	__TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	l	%r7,SP_R2(%r15) 	# load new svc number
-	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
-	sth	%r7,SP_SVCNR(%r15)
-	b	BASED(sysc_nr_ok)	# restart svc
-
 #
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
+	ni	__TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
 	la	%r14,BASED(sysc_return)	# load adr. of system return
@@ -361,7 +345,7 @@ sysc_tracesys:
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
 	xr	%r0,%r0
-	icm	%r0,3,SP_SVCNR(%r15)
+	icm	%r0,3,SP_SVC_CODE(%r15)
 	st	%r0,SP_R2(%r15)
 	basr	%r14,%r1
 	cl	%r2,BASED(.Lnr_syscalls)
@@ -376,7 +360,7 @@ sysc_tracego:
 	basr	%r14,%r8		# call sys_xxx
 	st	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+2(%r12),_TIF_SYSCALL
+	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
 	bz	BASED(sysc_return)
 	l	%r1,BASED(.Ltrace_exit)
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
@@ -454,7 +438,6 @@ ENTRY(pgm_check_handler)
 	bnz	BASED(pgm_per)		# got per exception -> special case
 	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	xc	SP_ILC(4,%r15),SP_ILC(%r15)
 	mvc	SP_PSW(8,%r15),__LC_PGM_OLD_PSW
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
@@ -530,9 +513,10 @@ pgm_exit2:
 pgm_svcper:
 	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -540,7 +524,6 @@ pgm_svcper:
 	mvc	__THREAD_per_cause(2,%r8),__LC_PER_CAUSE
 	mvc	__THREAD_per_address(4,%r8),__LC_PER_ADDRESS
 	mvc	__THREAD_per_paid(1,%r8),__LC_PER_PAID
-	oi	__TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	b	BASED(sysc_do_svc)
@@ -550,7 +533,6 @@ pgm_svcper:
 #
 kernel_per:
 	REENABLE_IRQS
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
 	basr	%r14,%r1		# branch to do_single_step
@@ -853,13 +835,13 @@ restart_go:
 # PSW restart interrupt handler
 #
 ENTRY(psw_restart_int_handler)
-	st	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
+	st	%r15,__LC_SAVE_AREA+48(%r0)	# save r15
 	basr	%r15,0
 0:	l	%r15,.Lrestart_stack-0b(%r15)	# load restart stack
 	l	%r15,0(%r15)
 	ahi	%r15,-SP_SIZE			# make room for pt_regs
 	stm	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
-	mvc	SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+	mvc	SP_R15(4,%r15),__LC_SAVE_AREA+48(%r0)# store saved %r15 to stack
 	mvc	SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
 	basr	%r14,0
@@ -965,9 +947,11 @@ cleanup_system_call:
 	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	st	%r15,12(%r12)
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	mvc	0(4,%r12),__LC_THREAD_INFO
+	l	%r12,__LC_THREAD_INFO
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),_TIF_SYSCALL
 cleanup_vtime:
 	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
 	bhe	BASED(cleanup_stime)
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/head31.S linux-libre-3.2-gnu1/arch/s390/kernel/head31.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/head31.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/head31.S	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@ ENTRY(_stext)
 .LPG3:
 # check control registers
 	stctl	%c0,%c15,0(%r15)
-	oi	2(%r15),0x40		# enable sigp emergency signal
+	oi	2(%r15),0x60		# enable sigp emergency & external call
 	oi	0(%r15),0x10		# switch on low address protection
 	lctl	%c0,%c15,0(%r15)
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/head64.S linux-libre-3.2-gnu1/arch/s390/kernel/head64.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/head64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/head64.S	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,7 @@ ENTRY(_stext)
 .LPG3:
 # check control registers
 	stctg	%c0,%c15,0(%r15)
-	oi	6(%r15),0x40		# enable sigp emergency signal
+	oi	6(%r15),0x60		# enable sigp emergency & external call
 	oi	4(%r15),0x10		# switch on low address proctection
 	lctlg	%c0,%c15,0(%r15)
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/head_kdump.S linux-libre-3.2-gnu1/arch/s390/kernel/head_kdump.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/head_kdump.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/s390/kernel/head_kdump.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,119 @@
+/*
+ * S390 kdump lowlevel functions (new kernel)
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#define DATAMOVER_ADDR	0x4000
+#define COPY_PAGE_ADDR	0x6000
+
+#ifdef CONFIG_CRASH_DUMP
+
+#
+# kdump entry (new kernel - not yet relocated)
+#
+# Note: This code has to be position independent
+#
+
+.align 2
+.Lep_startup_kdump:
+	lhi	%r1,2				# mode 2 = esame (dump)
+	sigp	%r1,%r0,0x12			# Switch to esame mode
+	sam64					# Switch to 64 bit addressing
+	basr	%r13,0
+.Lbase:
+	larl	%r2,.Lbase_addr			# Check, if we have been
+	lg	%r2,0(%r2)			# already relocated:
+	clgr	%r2,%r13			#
+	jne	.Lrelocate			# No : Start data mover
+	lghi	%r2,0				# Yes: Start kdump kernel
+	brasl	%r14,startup_kdump_relocated
+
+.Lrelocate:
+	larl	%r4,startup
+	lg	%r2,0x418(%r4)			# Get kdump base
+	lg	%r3,0x420(%r4)			# Get kdump size
+
+	larl	%r10,.Lcopy_start		# Source of data mover
+	lghi	%r8,DATAMOVER_ADDR		# Target of data mover
+	mvc	0(256,%r8),0(%r10)		# Copy data mover code
+
+	agr	%r8,%r2				# Copy data mover to
+	mvc	0(256,%r8),0(%r10)		# reserved mem
+
+	lghi	%r14,DATAMOVER_ADDR		# Jump to copied data mover
+	basr	%r14,%r14
+.Lbase_addr:
+	.quad	.Lbase
+
+#
+# kdump data mover code (runs at address DATAMOVER_ADDR)
+#
+# r2: kdump base address
+# r3: kdump size
+#
+.Lcopy_start:
+	basr	%r13,0				# Base
+0:
+	lgr	%r11,%r2			# Save kdump base address
+	lgr	%r12,%r2
+	agr	%r12,%r3			# Compute kdump end address
+
+	lghi	%r5,0
+	lghi	%r10,COPY_PAGE_ADDR		# Load copy page address
+1:
+	mvc	0(256,%r10),0(%r5)		# Copy old kernel to tmp
+	mvc	0(256,%r5),0(%r11)		# Copy new kernel to old
+	mvc	0(256,%r11),0(%r10)		# Copy tmp to new
+	aghi	%r11,256
+	aghi	%r5,256
+	clgr	%r11,%r12
+	jl	1b
+
+	lg	%r14,.Lstartup_kdump-0b(%r13)
+	basr	%r14,%r14			# Start relocated kernel
+.Lstartup_kdump:
+	.long	0x00000000,0x00000000 + startup_kdump_relocated
+.Lcopy_end:
+
+#
+# Startup of kdump (relocated new kernel)
+#
+.align 2
+startup_kdump_relocated:
+	basr	%r13,0
+0:
+	mvc	0(8,%r0),.Lrestart_psw-0b(%r13)	# Setup restart PSW
+	mvc	464(16,%r0),.Lpgm_psw-0b(%r13)	# Setup pgm check PSW
+	lhi	%r1,1				# Start new kernel
+	diag	%r1,%r1,0x308			# with diag 308
+
+.Lno_diag308:					# No diag 308
+	sam31					# Switch to 31 bit addr mode
+	sr	%r1,%r1				# Erase register r1
+	sr	%r2,%r2				# Erase register r2
+	sigp	%r1,%r2,0x12			# Switch to 31 bit arch mode
+	lpsw	0				# Start new kernel...
+.align	8
+.Lrestart_psw:
+	.long	0x00080000,0x80000000 + startup
+.Lpgm_psw:
+	.quad	0x0000000180000000,0x0000000000000000 + .Lno_diag308
+#else
+.align 2
+.Lep_startup_kdump:
+#ifdef CONFIG_64BIT
+	larl	%r13,startup_kdump_crash
+	lpswe	0(%r13)
+.align 8
+startup_kdump_crash:
+	.quad	0x0002000080000000,0x0000000000000000 + startup_kdump_crash
+#else
+	basr	%r13,0
+0:	lpsw	startup_kdump_crash-0b(%r13)
+.align 8
+startup_kdump_crash:
+	.long	0x000a0000,0x00000000 + startup_kdump_crash
+#endif /* CONFIG_64BIT */
+#endif /* CONFIG_CRASH_DUMP */
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/head.S linux-libre-3.2-gnu1/arch/s390/kernel/head.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -449,10 +449,28 @@ ENTRY(start)
 #
 	.org	0x10000
 ENTRY(startup)
+	j	.Lep_startup_normal
+	.org	0x10008
+#
+# This is a list of s390 kernel entry points. At address 0x1000f the number of
+# valid entry points is stored.
+#
+# IMPORTANT: Do not change this table, it is s390 kernel ABI!
+#
+	.ascii	"S390EP"
+	.byte	0x00,0x01
+#
+# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
+#
+	.org	0x10010
+ENTRY(startup_kdump)
+	j	.Lep_startup_kdump
+.Lep_startup_normal:
 	basr	%r13,0			# get base
 .LPG0:
 	xc	0x200(256),0x200	# partially clear lowcore
 	xc	0x300(256),0x300
+	xc	0xe00(256),0xe00
 	stck	__LC_LAST_UPDATE_CLOCK
 	spt	5f-.LPG0(%r13)
 	mvc	__LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
@@ -534,6 +552,8 @@ ENTRY(startup)
 	.align	8
 5:	.long	0x7fffffff,0xffffffff
 
+#include "head_kdump.S"
+
 #
 # params at 10400 (setup.h)
 #
@@ -541,6 +561,8 @@ ENTRY(startup)
 	.long	0,0			# IPL_DEVICE
 	.long	0,0			# INITRD_START
 	.long	0,0			# INITRD_SIZE
+	.long	0,0			# OLDMEM_BASE
+	.long	0,0			# OLDMEM_SIZE
 
 	.org	COMMAND_LINE
 	.byte	"root=/dev/ram0 ro"
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/ipl.c linux-libre-3.2-gnu1/arch/s390/kernel/ipl.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/ipl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/ipl.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/ctype.h>
 #include <linux/fs.h>
 #include <linux/gfp.h>
+#include <linux/crash_dump.h>
 #include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
@@ -26,6 +27,7 @@
 #include <asm/sclp.h>
 #include <asm/sigp.h>
 #include <asm/checksum.h>
+#include "entry.h"
 
 #define IPL_PARM_BLOCK_VERSION 0
 
@@ -275,8 +277,8 @@ static ssize_t ipl_type_show(struct kobj
 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
 /* VM IPL PARM routines */
-size_t reipl_get_ascii_vmparm(char *dest, size_t size,
-				   const struct ipl_parameter_block *ipb)
+static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
+				     const struct ipl_parameter_block *ipb)
 {
 	int i;
 	size_t len;
@@ -338,8 +340,8 @@ static size_t scpdata_length(const char*
 	return count;
 }
 
-size_t reipl_append_ascii_scpdata(char *dest, size_t size,
-				  const struct ipl_parameter_block *ipb)
+static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
+					 const struct ipl_parameter_block *ipb)
 {
 	size_t count;
 	size_t i;
@@ -1738,7 +1740,11 @@ static struct kobj_attribute on_restart_
 
 void do_restart(void)
 {
+	smp_restart_with_online_cpu();
 	smp_send_stop();
+#ifdef CONFIG_CRASH_DUMP
+	crash_kexec(NULL);
+#endif
 	on_restart_trigger.action->fn(&on_restart_trigger);
 	stop_run(&on_restart_trigger);
 }
@@ -2009,7 +2015,7 @@ static void do_reset_calls(void)
 
 u32 dump_prefix_page;
 
-void s390_reset_system(void)
+void s390_reset_system(void (*func)(void *), void *data)
 {
 	struct _lowcore *lc;
 
@@ -2028,15 +2034,19 @@ void s390_reset_system(void)
 	__ctl_clear_bit(0,28);
 
 	/* Set new machine check handler */
-	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
 	S390_lowcore.mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
 	/* Set new program check handler */
-	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
 	S390_lowcore.program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
+	/* Store status at absolute zero */
+	store_status();
+
 	do_reset_calls();
+	if (func)
+		func(data);
 }
-
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/irq.c linux-libre-3.2-gnu1/arch/s390/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,8 @@ static const struct irq_class intrclass_
 	{.name = "EXT" },
 	{.name = "I/O" },
 	{.name = "CLK", .desc = "[EXT] Clock Comparator" },
-	{.name = "IPI", .desc = "[EXT] Signal Processor" },
+	{.name = "EXC", .desc = "[EXT] External Call" },
+	{.name = "EMS", .desc = "[EXT] Emergency Signal" },
 	{.name = "TMR", .desc = "[EXT] CPU Timer" },
 	{.name = "TAL", .desc = "[EXT] Timing Alert" },
 	{.name = "PFL", .desc = "[EXT] Pseudo Page Fault" },
@@ -42,8 +43,8 @@ static const struct irq_class intrclass_
 	{.name = "SCP", .desc = "[EXT] Service Call" },
 	{.name = "IUC", .desc = "[EXT] IUCV" },
 	{.name = "CPM", .desc = "[EXT] CPU Measurement" },
+	{.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" },
 	{.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" },
-	{.name = "QDI", .desc = "[I/O] QDIO Interrupt" },
 	{.name = "DAS", .desc = "[I/O] DASD" },
 	{.name = "C15", .desc = "[I/O] 3215" },
 	{.name = "C70", .desc = "[I/O] 3270" },
@@ -53,6 +54,7 @@ static const struct irq_class intrclass_
 	{.name = "CLW", .desc = "[I/O] CLAW" },
 	{.name = "CTC", .desc = "[I/O] CTC" },
 	{.name = "APB", .desc = "[I/O] AP Bus" },
+	{.name = "CSC", .desc = "[I/O] CHSC Subchannel" },
 	{.name = "NMI", .desc = "[NMI] Machine Check" },
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/jump_label.c linux-libre-3.2-gnu1/arch/s390/kernel/jump_label.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,26 +18,15 @@ struct insn {
 } __packed;
 
 struct insn_args {
-	unsigned long *target;
-	struct insn *insn;
-	ssize_t size;
+	struct jump_entry *entry;
+	enum jump_label_type type;
 };
 
-static int __arch_jump_label_transform(void *data)
-{
-	struct insn_args *args = data;
-	int rc;
-
-	rc = probe_kernel_write(args->target, args->insn, args->size);
-	WARN_ON_ONCE(rc < 0);
-	return 0;
-}
-
-void arch_jump_label_transform(struct jump_entry *entry,
-			       enum jump_label_type type)
+static void __jump_label_transform(struct jump_entry *entry,
+				   enum jump_label_type type)
 {
-	struct insn_args args;
 	struct insn insn;
+	int rc;
 
 	if (type == JUMP_LABEL_ENABLE) {
 		/* brcl 15,offset */
@@ -49,11 +38,33 @@ void arch_jump_label_transform(struct ju
 		insn.offset = 0;
 	}
 
-	args.target = (void *) entry->code;
-	args.insn = &insn;
-	args.size = JUMP_LABEL_NOP_SIZE;
+	rc = probe_kernel_write((void *)entry->code, &insn, JUMP_LABEL_NOP_SIZE);
+	WARN_ON_ONCE(rc < 0);
+}
 
-	stop_machine(__arch_jump_label_transform, &args, NULL);
+static int __sm_arch_jump_label_transform(void *data)
+{
+	struct insn_args *args = data;
+
+	__jump_label_transform(args->entry, args->type);
+	return 0;
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
+	struct insn_args args;
+
+	args.entry = entry;
+	args.type = type;
+
+	stop_machine(__sm_arch_jump_label_transform, &args, NULL);
+}
+
+void arch_jump_label_transform_static(struct jump_entry *entry,
+				      enum jump_label_type type)
+{
+	__jump_label_transform(entry, type);
 }
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/kprobes.c linux-libre-3.2-gnu1/arch/s390/kernel/kprobes.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/kprobes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/kprobes.c	2012-01-04 18:55:44.000000000 -0500
@@ -635,7 +635,7 @@ void __kprobes jprobe_return(void)
 	asm volatile(".word 0x0002");
 }
 
-void __kprobes jprobe_return_end(void)
+static void __used __kprobes jprobe_return_end(void)
 {
 	asm volatile("bcr 0,0");
 }
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/machine_kexec.c linux-libre-3.2-gnu1/arch/s390/kernel/machine_kexec.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/machine_kexec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/machine_kexec.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,11 @@
 /*
  * arch/s390/kernel/machine_kexec.c
  *
- * Copyright IBM Corp. 2005,2006
+ * Copyright IBM Corp. 2005,2011
  *
  * Author(s): Rolf Adelsberger,
  *	      Heiko Carstens <heiko.carstens@de.ibm.com>
+ *	      Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
 #include <linux/device.h>
@@ -21,12 +22,162 @@
 #include <asm/smp.h>
 #include <asm/reset.h>
 #include <asm/ipl.h>
+#include <asm/diag.h>
+#include <asm/asm-offsets.h>
 
 typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
 
 extern const unsigned char relocate_kernel[];
 extern const unsigned long long relocate_kernel_len;
 
+#ifdef CONFIG_CRASH_DUMP
+
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
+
+/*
+ * Create ELF notes for one CPU
+ */
+static void add_elf_notes(int cpu)
+{
+	struct save_area *sa = (void *) 4608 + store_prefix();
+	void *ptr;
+
+	memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa));
+	ptr = (u64 *) per_cpu_ptr(crash_notes, cpu);
+	ptr = fill_cpu_elf_notes(ptr, sa);
+	memset(ptr, 0, sizeof(struct elf_note));
+}
+
+/*
+ * Store status of next available physical CPU
+ */
+static int store_status_next(int start_cpu, int this_cpu)
+{
+	struct save_area *sa = (void *) 4608 + store_prefix();
+	int cpu, rc;
+
+	for (cpu = start_cpu; cpu < 65536; cpu++) {
+		if (cpu == this_cpu)
+			continue;
+		do {
+			rc = raw_sigp(cpu, sigp_stop_and_store_status);
+		} while (rc == sigp_busy);
+		if (rc != sigp_order_code_accepted)
+			continue;
+		if (sa->pref_reg)
+			return cpu;
+	}
+	return -1;
+}
+
+/*
+ * Initialize CPU ELF notes
+ */
+void setup_regs(void)
+{
+	unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
+	int cpu, this_cpu, phys_cpu = 0, first = 1;
+
+	this_cpu = stap();
+
+	if (!S390_lowcore.prefixreg_save_area)
+		first = 0;
+	for_each_online_cpu(cpu) {
+		if (first) {
+			add_elf_notes(cpu);
+			first = 0;
+			continue;
+		}
+		phys_cpu = store_status_next(phys_cpu, this_cpu);
+		if (phys_cpu == -1)
+			break;
+		add_elf_notes(cpu);
+		phys_cpu++;
+	}
+	/* Copy dump CPU store status info to absolute zero */
+	memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
+}
+
+#endif
+
+/*
+ * Start kdump: We expect here that a store status has been done on our CPU
+ */
+static void __do_machine_kdump(void *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+	int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
+
+	__load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
+	setup_regs();
+	start_kdump(1);
+#endif
+}
+
+/*
+ * Check if kdump checksums are valid: We call purgatory with parameter "0"
+ */
+static int kdump_csum_valid(struct kimage *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+	int (*start_kdump)(int) = (void *)image->start;
+	int rc;
+
+	__arch_local_irq_stnsm(0xfb); /* disable DAT */
+	rc = start_kdump(0);
+	__arch_local_irq_stosm(0x04); /* enable DAT */
+	return rc ? 0 : -EINVAL;
+#else
+	return -EINVAL;
+#endif
+}
+
+/*
+ * Map or unmap crashkernel memory
+ */
+static void crash_map_pages(int enable)
+{
+	unsigned long size = resource_size(&crashk_res);
+
+	BUG_ON(crashk_res.start % KEXEC_CRASH_MEM_ALIGN ||
+	       size % KEXEC_CRASH_MEM_ALIGN);
+	if (enable)
+		vmem_add_mapping(crashk_res.start, size);
+	else
+		vmem_remove_mapping(crashk_res.start, size);
+}
+
+/*
+ * Map crashkernel memory
+ */
+void crash_map_reserved_pages(void)
+{
+	crash_map_pages(1);
+}
+
+/*
+ * Unmap crashkernel memory
+ */
+void crash_unmap_reserved_pages(void)
+{
+	crash_map_pages(0);
+}
+
+/*
+ * Give back memory to hypervisor before new kdump is loaded
+ */
+static int machine_kexec_prepare_kdump(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	if (MACHINE_IS_VM)
+		diag10_range(PFN_DOWN(crashk_res.start),
+			     PFN_DOWN(crashk_res.end - crashk_res.start + 1));
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
 int machine_kexec_prepare(struct kimage *image)
 {
 	void *reboot_code_buffer;
@@ -35,6 +186,9 @@ int machine_kexec_prepare(struct kimage
 	if (ipl_flags & IPL_NSS_VALID)
 		return -ENOSYS;
 
+	if (image->type == KEXEC_TYPE_CRASH)
+		return machine_kexec_prepare_kdump();
+
 	/* We don't support anything but the default image type for now. */
 	if (image->type != KEXEC_TYPE_DEFAULT)
 		return -EINVAL;
@@ -51,27 +205,53 @@ void machine_kexec_cleanup(struct kimage
 {
 }
 
+void arch_crash_save_vmcoreinfo(void)
+{
+	VMCOREINFO_SYMBOL(lowcore_ptr);
+	VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
+}
+
 void machine_shutdown(void)
 {
 }
 
-static void __machine_kexec(void *data)
+/*
+ * Do normal kexec
+ */
+static void __do_machine_kexec(void *data)
 {
 	relocate_kernel_t data_mover;
 	struct kimage *image = data;
 
-	pfault_fini();
-	s390_reset_system();
-
 	data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
 
 	/* Call the moving routine */
 	(*data_mover)(&image->head, image->start);
-	for (;;);
 }
 
+/*
+ * Reset system and call either kdump or normal kexec
+ */
+static void __machine_kexec(void *data)
+{
+	struct kimage *image = data;
+
+	pfault_fini();
+	if (image->type == KEXEC_TYPE_CRASH)
+		s390_reset_system(__do_machine_kdump, data);
+	else
+		s390_reset_system(__do_machine_kexec, data);
+	disabled_wait((unsigned long) __builtin_return_address(0));
+}
+
+/*
+ * Do either kdump or normal kexec. In case of kdump we first ask
+ * purgatory, if kdump checksums are valid.
+ */
 void machine_kexec(struct kimage *image)
 {
+	if (image->type == KEXEC_TYPE_CRASH && !kdump_csum_valid(image))
+		return;
 	tracer_disable();
 	smp_send_stop();
 	smp_switch_to_ipl_cpu(__machine_kexec, image);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/Makefile linux-libre-3.2-gnu1/arch/s390/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/s390/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@ obj-$(CONFIG_FUNCTION_TRACER)	+= $(if $(
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 # Kexec part
 S390_KEXEC_OBJS := machine_kexec.o crash.o
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/mem_detect.c linux-libre-3.2-gnu1/arch/s390/kernel/mem_detect.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/mem_detect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/mem_detect.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,3 +62,72 @@ void detect_memory_layout(struct mem_chu
 	arch_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(detect_memory_layout);
+
+/*
+ * Create memory hole with given address, size, and type
+ */
+void create_mem_hole(struct mem_chunk chunks[], unsigned long addr,
+		     unsigned long size, int type)
+{
+	unsigned long start, end, new_size;
+	int i;
+
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		if (chunks[i].size == 0)
+			continue;
+		if (addr + size < chunks[i].addr)
+			continue;
+		if (addr >= chunks[i].addr + chunks[i].size)
+			continue;
+		start = max(addr, chunks[i].addr);
+		end = min(addr + size, chunks[i].addr + chunks[i].size);
+		new_size = end - start;
+		if (new_size == 0)
+			continue;
+		if (start == chunks[i].addr &&
+		    end == chunks[i].addr + chunks[i].size) {
+			/* Remove chunk */
+			chunks[i].type = type;
+		} else if (start == chunks[i].addr) {
+			/* Make chunk smaller at start */
+			if (i >= MEMORY_CHUNKS - 1)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 1], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 1)));
+			chunks[i + 1].addr = chunks[i].addr + new_size;
+			chunks[i + 1].size = chunks[i].size - new_size;
+			chunks[i].size = new_size;
+			chunks[i].type = type;
+			i += 1;
+		} else if (end == chunks[i].addr + chunks[i].size) {
+			/* Make chunk smaller at end */
+			if (i >= MEMORY_CHUNKS - 1)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 1], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 1)));
+			chunks[i + 1].addr = start;
+			chunks[i + 1].size = new_size;
+			chunks[i + 1].type = type;
+			chunks[i].size -= new_size;
+			i += 1;
+		} else {
+			/* Create memory hole */
+			if (i >= MEMORY_CHUNKS - 2)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 2], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 2)));
+			chunks[i + 1].addr = addr;
+			chunks[i + 1].size = size;
+			chunks[i + 1].type = type;
+			chunks[i + 2].addr = addr + size;
+			chunks[i + 2].size =
+				chunks[i].addr + chunks[i].size - (addr + size);
+			chunks[i + 2].type = chunks[i].type;
+			chunks[i].size = addr - chunks[i].addr;
+			i += 2;
+		}
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/process.c linux-libre-3.2-gnu1/arch/s390/kernel/process.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/elfcore.h>
 #include <linux/smp.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -117,7 +118,8 @@ int kernel_thread(int (*fn)(void *), voi
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+	regs.psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/processor.c linux-libre-3.2-gnu1/arch/s390/kernel/processor.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/processor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/processor.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@ static int show_cpuinfo(struct seq_file
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL;
+	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/ptrace.c linux-libre-3.2-gnu1/arch/s390/kernel/ptrace.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,34 +42,37 @@ enum s390_regset {
 	REGSET_GENERAL,
 	REGSET_FP,
 	REGSET_LAST_BREAK,
+	REGSET_SYSTEM_CALL,
 	REGSET_GENERAL_EXTENDED,
 };
 
 void update_per_regs(struct task_struct *task)
 {
-	static const struct per_regs per_single_step = {
-		.control = PER_EVENT_IFETCH,
-		.start = 0,
-		.end = PSW_ADDR_INSN,
-	};
 	struct pt_regs *regs = task_pt_regs(task);
 	struct thread_struct *thread = &task->thread;
-	const struct per_regs *new;
-	struct per_regs old;
+	struct per_regs old, new;
 
-	/* TIF_SINGLE_STEP overrides the user specified PER registers. */
-	new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
-		&per_single_step : &thread->per_user;
+	/* Copy user specified PER registers */
+	new.control = thread->per_user.control;
+	new.start = thread->per_user.start;
+	new.end = thread->per_user.end;
+
+	/* merge TIF_SINGLE_STEP into user specified PER registers. */
+	if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
+		new.control |= PER_EVENT_IFETCH;
+		new.start = 0;
+		new.end = PSW_ADDR_INSN;
+	}
 
 	/* Take care of the PER enablement bit in the PSW. */
-	if (!(new->control & PER_EVENT_MASK)) {
+	if (!(new.control & PER_EVENT_MASK)) {
 		regs->psw.mask &= ~PSW_MASK_PER;
 		return;
 	}
 	regs->psw.mask |= PSW_MASK_PER;
 	__ctl_store(old, 9, 11);
-	if (memcmp(new, &old, sizeof(struct per_regs)) != 0)
-		__ctl_load(*new, 9, 11);
+	if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
+		__ctl_load(new, 9, 11);
 }
 
 void user_enable_single_step(struct task_struct *task)
@@ -166,8 +169,8 @@ static unsigned long __peek_user(struct
 		 */
 		tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
 		if (addr == (addr_t) &dummy->regs.psw.mask)
-			/* Remove per bit from user psw. */
-			tmp &= ~PSW_MASK_PER;
+			/* Return a clean psw mask. */
+			tmp = psw_user_bits | (tmp & PSW_MASK_USER);
 
 	} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
 		/*
@@ -289,18 +292,10 @@ static int __poke_user(struct task_struc
 		 * psw and gprs are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy->regs.psw.mask &&
-#ifdef CONFIG_COMPAT
-		    data != PSW_MASK_MERGE(psw_user32_bits, data) &&
-#endif
-		    data != PSW_MASK_MERGE(psw_user_bits, data))
+		    ((data & ~PSW_MASK_USER) != psw_user_bits ||
+		     ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))
 			/* Invalid psw mask. */
 			return -EINVAL;
-#ifndef CONFIG_64BIT
-		if (addr == (addr_t) &dummy->regs.psw.addr)
-			/* I'd like to reject addresses without the
-			   high order bit but older gdb's rely on it */
-			data |= PSW_ADDR_AMODE;
-#endif
 		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
 
 	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
@@ -495,21 +490,21 @@ static u32 __peek_user_compat(struct tas
 	__u32 tmp;
 
 	if (addr < (addr_t) &dummy32->regs.acrs) {
+		struct pt_regs *regs = task_pt_regs(child);
 		/*
 		 * psw and gprs are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Fake a 31 bit psw mask. */
-			tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
-			tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
+			tmp = (__u32)(regs->psw.mask >> 32);
+			tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Fake a 31 bit psw address. */
-			tmp = (__u32) task_pt_regs(child)->psw.addr |
-				PSW32_ADDR_AMODE31;
+			tmp = (__u32) regs->psw.addr |
+				(__u32)(regs->psw.mask & PSW_MASK_BA);
 		} else {
 			/* gpr 0-15 */
-			tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
-					 addr*2 + 4);
+			tmp = *(__u32 *)((addr_t) &regs->psw + addr*2 + 4);
 		}
 	} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
 		/*
@@ -594,24 +589,27 @@ static int __poke_user_compat(struct tas
 	addr_t offset;
 
 	if (addr < (addr_t) &dummy32->regs.acrs) {
+		struct pt_regs *regs = task_pt_regs(child);
 		/*
 		 * psw, gprs, acrs and orig_gpr2 are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Build a 64 bit psw mask from 31 bit mask. */
-			if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp))
+			if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits)
 				/* Invalid psw mask. */
 				return -EINVAL;
-			task_pt_regs(child)->psw.mask =
-				PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
+			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+				(regs->psw.mask & PSW_MASK_BA) |
+				(__u64)(tmp & PSW32_MASK_USER) << 32;
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Build a 64 bit psw address from 31 bit address. */
-			task_pt_regs(child)->psw.addr =
-				(__u64) tmp & PSW32_ADDR_INSN;
+			regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
+			/* Transfer 31 bit amode bit to psw mask. */
+			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
+				(__u64)(tmp & PSW32_ADDR_AMODE);
 		} else {
 			/* gpr 0-15 */
-			*(__u32*)((addr_t) &task_pt_regs(child)->psw
-				  + addr*2 + 4) = tmp;
+			*(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
 		}
 	} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
 		/*
@@ -735,7 +733,7 @@ asmlinkage long do_syscall_trace_enter(s
 		 * debugger stored an invalid system call number. Skip
 		 * the system call and the system call restart handling.
 		 */
-		regs->svcnr = 0;
+		clear_thread_flag(TIF_SYSCALL);
 		ret = -1;
 	}
 
@@ -895,8 +893,36 @@ static int s390_last_break_get(struct ta
 	return 0;
 }
 
+static int s390_last_break_set(struct task_struct *target,
+			       const struct user_regset *regset,
+			       unsigned int pos, unsigned int count,
+			       const void *kbuf, const void __user *ubuf)
+{
+	return 0;
+}
+
 #endif
 
+static int s390_system_call_get(struct task_struct *target,
+				const struct user_regset *regset,
+				unsigned int pos, unsigned int count,
+				void *kbuf, void __user *ubuf)
+{
+	unsigned int *data = &task_thread_info(target)->system_call;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   data, 0, sizeof(unsigned int));
+}
+
+static int s390_system_call_set(struct task_struct *target,
+				const struct user_regset *regset,
+				unsigned int pos, unsigned int count,
+				const void *kbuf, const void __user *ubuf)
+{
+	unsigned int *data = &task_thread_info(target)->system_call;
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				  data, 0, sizeof(unsigned int));
+}
+
 static const struct user_regset s390_regsets[] = {
 	[REGSET_GENERAL] = {
 		.core_note_type = NT_PRSTATUS,
@@ -921,8 +947,17 @@ static const struct user_regset s390_reg
 		.size = sizeof(long),
 		.align = sizeof(long),
 		.get = s390_last_break_get,
+		.set = s390_last_break_set,
 	},
 #endif
+	[REGSET_SYSTEM_CALL] = {
+		.core_note_type = NT_S390_SYSTEM_CALL,
+		.n = 1,
+		.size = sizeof(unsigned int),
+		.align = sizeof(unsigned int),
+		.get = s390_system_call_get,
+		.set = s390_system_call_set,
+	},
 };
 
 static const struct user_regset_view user_s390_view = {
@@ -1078,6 +1113,14 @@ static int s390_compat_last_break_get(st
 	return 0;
 }
 
+static int s390_compat_last_break_set(struct task_struct *target,
+				      const struct user_regset *regset,
+				      unsigned int pos, unsigned int count,
+				      const void *kbuf, const void __user *ubuf)
+{
+	return 0;
+}
+
 static const struct user_regset s390_compat_regsets[] = {
 	[REGSET_GENERAL] = {
 		.core_note_type = NT_PRSTATUS,
@@ -1101,6 +1144,15 @@ static const struct user_regset s390_com
 		.size = sizeof(long),
 		.align = sizeof(long),
 		.get = s390_compat_last_break_get,
+		.set = s390_compat_last_break_set,
+	},
+	[REGSET_SYSTEM_CALL] = {
+		.core_note_type = NT_S390_SYSTEM_CALL,
+		.n = 1,
+		.size = sizeof(compat_uint_t),
+		.align = sizeof(compat_uint_t),
+		.get = s390_system_call_get,
+		.set = s390_system_call_set,
 	},
 	[REGSET_GENERAL_EXTENDED] = {
 		.core_note_type = NT_S390_HIGH_GPRS,
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/reipl64.S linux-libre-3.2-gnu1/arch/s390/kernel/reipl64.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/reipl64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/reipl64.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,11 @@
 #
 ENTRY(store_status)
 	/* Save register one and load save area base */
-	stg	%r1,__LC_SAVE_AREA_64(%r0)
+	stg	%r1,__LC_SAVE_AREA+120(%r0)
 	lghi	%r1,SAVE_AREA_BASE
 	/* General purpose registers */
 	stmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
-	lg	%r2,__LC_SAVE_AREA_64(%r0)
+	lg	%r2,__LC_SAVE_AREA+120(%r0)
 	stg	%r2,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE+8(%r1)
 	/* Control registers */
 	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
@@ -62,8 +62,11 @@ ENTRY(store_status)
 	larl	%r2,store_status
 	stg	%r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1)
 	br	%r14
-.align	8
+
+	.section .bss
+	.align	8
 .Lclkcmp:	.quad	0x0000000000000000
+	.previous
 
 #
 # do_reipl_asm
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/reipl.S linux-libre-3.2-gnu1/arch/s390/kernel/reipl.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/reipl.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/reipl.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,12 @@
 #include <asm/asm-offsets.h>
 
 #
+# store_status: Empty implementation until kdump is supported on 31 bit
+#
+ENTRY(store_status)
+		br	%r14
+
+#
 # do_reipl_asm
 # Parameter: r2 = schid of reipl device
 #
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/setup.c linux-libre-3.2-gnu1/arch/s390/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@
 #include <linux/reboot.h>
 #include <linux/topology.h>
 #include <linux/ftrace.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+#include <linux/memory.h>
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
@@ -57,12 +60,13 @@
 #include <asm/ebcdic.h>
 #include <asm/compat.h>
 #include <asm/kvm_virtio.h>
+#include <asm/diag.h>
 
-long psw_kernel_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
-			   PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
-long psw_user_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw_kernel_bits	= PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
+			  PSW_MASK_EA | PSW_MASK_BA;
+long psw_user_bits	= PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
+			  PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
+			  PSW_MASK_PSTATE | PSW_ASC_HOME;
 
 /*
  * User copy operations.
@@ -207,6 +211,8 @@ static void __init setup_zfcpdump(unsign
 
 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
 		return;
+	if (OLDMEM_BASE)
+		return;
 	if (console_devno != -1)
 		sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
 			ipl_info.data.fcp.dev_id.devno, console_devno);
@@ -274,22 +280,14 @@ early_param("mem", early_parse_mem);
 unsigned int user_mode = HOME_SPACE_MODE;
 EXPORT_SYMBOL_GPL(user_mode);
 
-static int set_amode_and_uaccess(unsigned long user_amode,
-				 unsigned long user32_amode)
+static int set_amode_primary(void)
 {
-	psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
-			PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
+	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
 #ifdef CONFIG_COMPAT
-	psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
-			  PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			  PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
-	psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
-			  PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
-			  PSW32_MASK_PSTATE;
+	psw32_user_bits =
+		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
 #endif
-	psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			  PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
 
 	if (MACHINE_HAS_MVCOS) {
 		memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
@@ -325,7 +323,7 @@ early_param("user_mode", early_parse_use
 static void setup_addressing_mode(void)
 {
 	if (user_mode == PRIMARY_SPACE_MODE) {
-		if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
+		if (set_amode_primary())
 			pr_info("Address spaces switched, "
 				"mvcos available\n");
 		else
@@ -344,24 +342,25 @@ setup_lowcore(void)
 	 */
 	BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
 	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
-	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lc->restart_psw.mask = psw_kernel_bits;
 	lc->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
-	if (user_mode != HOME_SPACE_MODE)
-		lc->restart_psw.mask |= PSW_ASC_HOME;
-	lc->external_new_psw.mask = psw_kernel_bits;
+	lc->external_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->external_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-	lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+	lc->svc_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-	lc->program_new_psw.mask = psw_kernel_bits;
+	lc->program_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->program_new_psw.addr =
-		PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
-	lc->mcck_new_psw.mask =
-		psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
+		PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
+	lc->mcck_new_psw.mask = psw_kernel_bits;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-	lc->io_new_psw.mask = psw_kernel_bits;
+	lc->io_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
 	lc->clock_comparator = -1ULL;
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
@@ -435,10 +434,14 @@ static void __init setup_resources(void)
 	for (i = 0; i < MEMORY_CHUNKS; i++) {
 		if (!memory_chunk[i].size)
 			continue;
+		if (memory_chunk[i].type == CHUNK_OLDMEM ||
+		    memory_chunk[i].type == CHUNK_CRASHK)
+			continue;
 		res = alloc_bootmem_low(sizeof(*res));
 		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
 		switch (memory_chunk[i].type) {
 		case CHUNK_READ_WRITE:
+		case CHUNK_CRASHK:
 			res->name = "System RAM";
 			break;
 		case CHUNK_READ_ONLY:
@@ -479,8 +482,9 @@ static void __init setup_memory_end(void
 	unsigned long max_mem;
 	int i;
 
+
 #ifdef CONFIG_ZFCPDUMP
-	if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
+	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
 		memory_end = ZFCPDUMP_HSA_SIZE;
 		memory_end_set = 1;
 	}
@@ -545,11 +549,201 @@ static void __init setup_restart_psw(voi
 	 * Setup restart PSW for absolute zero lowcore. This is necesary
 	 * if PSW restart is done on an offline CPU that has lowcore zero
 	 */
-	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
 	copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
 }
 
+static void __init setup_vmcoreinfo(void)
+{
+#ifdef CONFIG_KEXEC
+	unsigned long ptr = paddr_vmcoreinfo_note();
+
+	copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
+#endif
+}
+
+#ifdef CONFIG_CRASH_DUMP
+
+/*
+ * Find suitable location for crashkernel memory
+ */
+static unsigned long __init find_crash_base(unsigned long crash_size,
+					    char **msg)
+{
+	unsigned long crash_base;
+	struct mem_chunk *chunk;
+	int i;
+
+	if (memory_chunk[0].size < crash_size) {
+		*msg = "first memory chunk must be at least crashkernel size";
+		return 0;
+	}
+	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE)
+		return OLDMEM_BASE;
+
+	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) {
+		chunk = &memory_chunk[i];
+		if (chunk->size == 0)
+			continue;
+		if (chunk->type != CHUNK_READ_WRITE)
+			continue;
+		if (chunk->size < crash_size)
+			continue;
+		crash_base = (chunk->addr + chunk->size) - crash_size;
+		if (crash_base < crash_size)
+			continue;
+		if (crash_base < ZFCPDUMP_HSA_SIZE_MAX)
+			continue;
+		if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
+			continue;
+		return crash_base;
+	}
+	*msg = "no suitable area found";
+	return 0;
+}
+
+/*
+ * Check if crash_base and crash_size is valid
+ */
+static int __init verify_crash_base(unsigned long crash_base,
+				    unsigned long crash_size,
+				    char **msg)
+{
+	struct mem_chunk *chunk;
+	int i;
+
+	/*
+	 * Because we do the swap to zero, we must have at least 'crash_size'
+	 * bytes free space before crash_base
+	 */
+	if (crash_size > crash_base) {
+		*msg = "crashkernel offset must be greater than size";
+		return -EINVAL;
+	}
+
+	/* First memory chunk must be at least crash_size */
+	if (memory_chunk[0].size < crash_size) {
+		*msg = "first memory chunk must be at least crashkernel size";
+		return -EINVAL;
+	}
+	/* Check if we fit into the respective memory chunk */
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		chunk = &memory_chunk[i];
+		if (chunk->size == 0)
+			continue;
+		if (crash_base < chunk->addr)
+			continue;
+		if (crash_base >= chunk->addr + chunk->size)
+			continue;
+		/* we have found the memory chunk */
+		if (crash_base + crash_size > chunk->addr + chunk->size) {
+			*msg = "selected memory chunk is too small for "
+				"crashkernel memory";
+			return -EINVAL;
+		}
+		return 0;
+	}
+	*msg = "invalid memory range specified";
+	return -EINVAL;
+}
+
+/*
+ * Reserve kdump memory by creating a memory hole in the mem_chunk array
+ */
+static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size,
+					 int type)
+{
+
+	create_mem_hole(memory_chunk, addr, size, type);
+}
+
+/*
+ * When kdump is enabled, we have to ensure that no memory from
+ * the area [0 - crashkernel memory size] and
+ * [crashk_res.start - crashk_res.end] is set offline.
+ */
+static int kdump_mem_notifier(struct notifier_block *nb,
+			      unsigned long action, void *data)
+{
+	struct memory_notify *arg = data;
+
+	if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
+		return NOTIFY_BAD;
+	if (arg->start_pfn > PFN_DOWN(crashk_res.end))
+		return NOTIFY_OK;
+	if (arg->start_pfn + arg->nr_pages - 1 < PFN_DOWN(crashk_res.start))
+		return NOTIFY_OK;
+	return NOTIFY_BAD;
+}
+
+static struct notifier_block kdump_mem_nb = {
+	.notifier_call = kdump_mem_notifier,
+};
+
+#endif
+
+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void reserve_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	if (!OLDMEM_BASE)
+		return;
+
+	reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
+	reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
+			      CHUNK_OLDMEM);
+	if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
+		saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
+	else
+		saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
+#endif
+}
+
+/*
+ * Reserve memory for kdump kernel to be loaded with kexec
+ */
+static void __init reserve_crashkernel(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	unsigned long long crash_base, crash_size;
+	char *msg;
+	int rc;
+
+	rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,
+			       &crash_base);
+	if (rc || crash_size == 0)
+		return;
+	crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
+	crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
+	if (register_memory_notifier(&kdump_mem_nb))
+		return;
+	if (!crash_base)
+		crash_base = find_crash_base(crash_size, &msg);
+	if (!crash_base) {
+		pr_info("crashkernel reservation failed: %s\n", msg);
+		unregister_memory_notifier(&kdump_mem_nb);
+		return;
+	}
+	if (verify_crash_base(crash_base, crash_size, &msg)) {
+		pr_info("crashkernel reservation failed: %s\n", msg);
+		unregister_memory_notifier(&kdump_mem_nb);
+		return;
+	}
+	if (!OLDMEM_BASE && MACHINE_IS_VM)
+		diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+	insert_resource(&iomem_resource, &crashk_res);
+	reserve_kdump_bootmem(crash_base, crash_size, CHUNK_CRASHK);
+	pr_info("Reserving %lluMB of memory at %lluMB "
+		"for crashkernel (System RAM: %luMB)\n",
+		crash_size >> 20, crash_base >> 20, memory_end >> 20);
+#endif
+}
+
 static void __init
 setup_memory(void)
 {
@@ -580,6 +774,14 @@ setup_memory(void)
 		if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
 			start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
 
+#ifdef CONFIG_CRASH_DUMP
+			if (OLDMEM_BASE) {
+				/* Move initrd behind kdump oldmem */
+				if (start + INITRD_SIZE > OLDMEM_BASE &&
+				    start < OLDMEM_BASE + OLDMEM_SIZE)
+					start = OLDMEM_BASE + OLDMEM_SIZE;
+			}
+#endif
 			if (start + INITRD_SIZE > memory_end) {
 				pr_err("initrd extends beyond end of "
 				       "memory (0x%08lx > 0x%08lx) "
@@ -610,7 +812,8 @@ setup_memory(void)
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
 		unsigned long start_chunk, end_chunk, pfn;
 
-		if (memory_chunk[i].type != CHUNK_READ_WRITE)
+		if (memory_chunk[i].type != CHUNK_READ_WRITE &&
+		    memory_chunk[i].type != CHUNK_CRASHK)
 			continue;
 		start_chunk = PFN_DOWN(memory_chunk[i].addr);
 		end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
@@ -644,6 +847,15 @@ setup_memory(void)
 	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
 			BOOTMEM_DEFAULT);
 
+#ifdef CONFIG_CRASH_DUMP
+	if (crashk_res.start)
+		reserve_bootmem(crashk_res.start,
+				crashk_res.end - crashk_res.start + 1,
+				BOOTMEM_DEFAULT);
+	if (is_kdump_kernel())
+		reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+				PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (INITRD_START && INITRD_SIZE) {
 		if (INITRD_START + INITRD_SIZE <= memory_end) {
@@ -812,8 +1024,11 @@ setup_arch(char **cmdline_p)
 	setup_ipl();
 	setup_memory_end();
 	setup_addressing_mode();
+	reserve_oldmem();
+	reserve_crashkernel();
 	setup_memory();
 	setup_resources();
+	setup_vmcoreinfo();
 	setup_restart_psw();
 	setup_lowcore();
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/signal.c linux-libre-3.2-gnu1/arch/s390/kernel/signal.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/compat.h>
 #include "entry.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -116,7 +117,8 @@ static int save_sigregs(struct pt_regs *
 
 	/* Copy a 'clean' PSW mask to the user to avoid leaking
 	   information about whether PER is currently on.  */
-	user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
+	user_sregs.regs.psw.mask = psw_user_bits |
+		(regs->psw.mask & PSW_MASK_USER);
 	user_sregs.regs.psw.addr = regs->psw.addr;
 	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
 	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
@@ -143,9 +145,13 @@ static int restore_sigregs(struct pt_reg
 	err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
 	if (err)
 		return err;
-	regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
-					user_sregs.regs.psw.mask);
-	regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr;
+	/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+		(user_sregs.regs.psw.mask & PSW_MASK_USER);
+	/* Check for invalid amode */
+	if (regs->psw.mask & PSW_MASK_EA)
+		regs->psw.mask |= PSW_MASK_BA;
+	regs->psw.addr = user_sregs.regs.psw.addr;
 	memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
 	memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
 	       sizeof(sregs->regs.acrs));
@@ -156,7 +162,7 @@ static int restore_sigregs(struct pt_reg
 	current->thread.fp_regs.fpc &= FPC_VALID_MASK;
 
 	restore_fp_regs(&current->thread.fp_regs);
-	regs->svcnr = 0;	/* disable syscall checks */
+	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
 
@@ -288,6 +294,7 @@ static int setup_frame(int sig, struct k
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
+	regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;	/* 64 bit amode */
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
 	regs->gprs[2] = map_signal(sig);
@@ -356,6 +363,7 @@ static int setup_rt_frame(int sig, struc
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
+	regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;	/* 64 bit amode */
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
 	regs->gprs[2] = map_signal(sig);
@@ -401,7 +409,6 @@ static int handle_signal(unsigned long s
  */
 void do_signal(struct pt_regs *regs)
 {
-	unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
 	siginfo_t info;
 	int signr;
 	struct k_sigaction ka;
@@ -421,54 +428,45 @@ void do_signal(struct pt_regs *regs)
 	else
 		oldset = &current->blocked;
 
-	/* Are we from a system call? */
-	if (regs->svcnr) {
-		continue_addr = regs->psw.addr;
-		restart_addr = continue_addr - regs->ilc;
-		retval = regs->gprs[2];
-
-		/* Prepare for system call restart.  We do this here so that a
-		   debugger will see the already changed PSW. */
-		switch (retval) {
-		case -ERESTARTNOHAND:
-		case -ERESTARTSYS:
-		case -ERESTARTNOINTR:
-			regs->gprs[2] = regs->orig_gpr2;
-			regs->psw.addr = restart_addr;
-			break;
-		case -ERESTART_RESTARTBLOCK:
-			regs->gprs[2] = -EINTR;
-		}
-		regs->svcnr = 0;	/* Don't deal with this again. */
-	}
-
-	/* Get signal to deliver.  When running under ptrace, at this point
-	   the debugger may change all our registers ... */
+	/*
+	 * Get signal to deliver. When running under ptrace, at this point
+	 * the debugger may change all our registers, including the system
+	 * call information.
+	 */
+	current_thread_info()->system_call =
+		test_thread_flag(TIF_SYSCALL) ? regs->svc_code : 0;
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* Depending on the signal settings we may need to revert the
-	   decision to restart the system call. */
-	if (signr > 0 && regs->psw.addr == restart_addr) {
-		if (retval == -ERESTARTNOHAND
-		    || (retval == -ERESTARTSYS
-			 && !(current->sighand->action[signr-1].sa.sa_flags
-			      & SA_RESTART))) {
-			regs->gprs[2] = -EINTR;
-			regs->psw.addr = continue_addr;
-		}
-	}
-
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		int ret;
-#ifdef CONFIG_COMPAT
-		if (is_compat_task()) {
-			ret = handle_signal32(signr, &ka, &info, oldset, regs);
-	        }
-		else
-#endif
-			ret = handle_signal(signr, &ka, &info, oldset, regs);
-		if (!ret) {
+		if (current_thread_info()->system_call) {
+			regs->svc_code = current_thread_info()->system_call;
+			/* Check for system call restarting. */
+			switch (regs->gprs[2]) {
+			case -ERESTART_RESTARTBLOCK:
+			case -ERESTARTNOHAND:
+				regs->gprs[2] = -EINTR;
+				break;
+			case -ERESTARTSYS:
+				if (!(ka.sa.sa_flags & SA_RESTART)) {
+					regs->gprs[2] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->gprs[2] = regs->orig_gpr2;
+				regs->psw.addr =
+					__rewind_psw(regs->psw,
+						     regs->svc_code >> 16);
+				break;
+			}
+		}
+		/* No longer in a system call */
+		clear_thread_flag(TIF_SYSCALL);
+
+		if ((is_compat_task() ?
+		     handle_signal32(signr, &ka, &info, oldset, regs) :
+		     handle_signal(signr, &ka, &info, oldset, regs)) == 0) {
 			/*
 			 * A signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
@@ -482,11 +480,30 @@ void do_signal(struct pt_regs *regs)
 			 * Let tracing know that we've done the handler setup.
 			 */
 			tracehook_signal_handler(signr, &info, &ka, regs,
-					test_thread_flag(TIF_SINGLE_STEP));
+					 test_thread_flag(TIF_SINGLE_STEP));
 		}
 		return;
 	}
 
+	/* No handlers present - check for system call restart */
+	clear_thread_flag(TIF_SYSCALL);
+	if (current_thread_info()->system_call) {
+		regs->svc_code = current_thread_info()->system_call;
+		switch (regs->gprs[2]) {
+		case -ERESTART_RESTARTBLOCK:
+			/* Restart with sys_restart_syscall */
+			regs->svc_code = __NR_restart_syscall;
+		/* fallthrough */
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			/* Restart system call with magic TIF bit. */
+			regs->gprs[2] = regs->orig_gpr2;
+			set_thread_flag(TIF_SYSCALL);
+			break;
+		}
+	}
+
 	/*
 	 * If there's no signal to deliver, we just put the saved sigmask back.
 	 */
@@ -494,13 +511,6 @@ void do_signal(struct pt_regs *regs)
 		clear_thread_flag(TIF_RESTORE_SIGMASK);
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
-
-	/* Restart a different system call. */
-	if (retval == -ERESTART_RESTARTBLOCK
-	    && regs->psw.addr == continue_addr) {
-		regs->gprs[2] = __NR_restart_syscall;
-		set_thread_flag(TIF_RESTART_SVC);
-	}
 }
 
 void do_notify_resume(struct pt_regs *regs)
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/smp.c linux-libre-3.2-gnu1/arch/s390/kernel/smp.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/timex.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
+#include <linux/crash_dump.h>
 #include <asm/asm-offsets.h>
 #include <asm/ipl.h>
 #include <asm/setup.h>
@@ -97,6 +98,29 @@ static inline int cpu_stopped(int cpu)
 	return raw_cpu_stopped(cpu_logical_map(cpu));
 }
 
+/*
+ * Ensure that PSW restart is done on an online CPU
+ */
+void smp_restart_with_online_cpu(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		if (stap() == __cpu_logical_map[cpu]) {
+			/* We are online: Enable DAT again and return */
+			__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+			return;
+		}
+	}
+	/* We are not online: Do PSW restart on an online CPU */
+	while (sigp(cpu, sigp_restart) == sigp_busy)
+		cpu_relax();
+	/* And stop ourself */
+	while (raw_sigp(stap(), sigp_stop) == sigp_busy)
+		cpu_relax();
+	for (;;);
+}
+
 void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
 {
 	struct _lowcore *lc, *current_lc;
@@ -106,14 +130,16 @@ void smp_switch_to_ipl_cpu(void (*func)(
 
 	if (smp_processor_id() == 0)
 		func(data);
-	__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
+	__load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE |
+			PSW_MASK_EA | PSW_MASK_BA);
 	/* Disable lowcore protection */
 	__ctl_clear_bit(0, 28);
 	current_lc = lowcore_ptr[smp_processor_id()];
 	lc = lowcore_ptr[0];
 	if (!lc)
 		lc = current_lc;
-	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lc->restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
 	if (!cpu_online(0))
 		smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
@@ -135,7 +161,7 @@ void smp_send_stop(void)
 	int cpu, rc;
 
 	/* Disable all interrupts/machine checks */
-	__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
+	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
 	trace_hardirqs_off();
 
 	/* stop all processors */
@@ -161,7 +187,10 @@ static void do_ext_call_interrupt(unsign
 {
 	unsigned long bits;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
+	if (ext_int_code == 0x1202)
+		kstat_cpu(smp_processor_id()).irqs[EXTINT_EXC]++;
+	else
+		kstat_cpu(smp_processor_id()).irqs[EXTINT_EMS]++;
 	/*
 	 * handle bit signal external calls
 	 */
@@ -183,12 +212,19 @@ static void do_ext_call_interrupt(unsign
  */
 static void smp_ext_bitcall(int cpu, int sig)
 {
+	int order;
+
 	/*
 	 * Set signaling bit in lowcore of target cpu and kick it
 	 */
 	set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
-	while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
+	while (1) {
+		order = smp_vcpu_scheduled(cpu) ?
+			sigp_external_call : sigp_emergency_signal;
+		if (sigp(cpu, order) != sigp_busy)
+			break;
 		udelay(10);
+	}
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -281,11 +317,13 @@ void smp_ctl_clear_bit(int cr, int bit)
 }
 EXPORT_SYMBOL(smp_ctl_clear_bit);
 
-#ifdef CONFIG_ZFCPDUMP
+#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
 
 static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
 {
-	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
+	if (ipl_info.type != IPL_TYPE_FCP_DUMP && !OLDMEM_BASE)
+		return;
+	if (is_kdump_kernel())
 		return;
 	if (cpu >= NR_CPUS) {
 		pr_warning("CPU %i exceeds the maximum %i and is excluded from "
@@ -403,6 +441,18 @@ static void __init smp_detect_cpus(void)
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		panic("smp_detect_cpus failed to allocate memory\n");
+#ifdef CONFIG_CRASH_DUMP
+	if (OLDMEM_BASE && !is_kdump_kernel()) {
+		struct save_area *save_area;
+
+		save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
+		if (!save_area)
+			panic("could not allocate memory for save area\n");
+		copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),
+				 0x200, 0);
+		zfcpdump_save_areas[0] = save_area;
+	}
+#endif
 	/* Use sigp detection algorithm if sclp doesn't work. */
 	if (sclp_get_cpu_info(info)) {
 		smp_use_sigp_detection = 1;
@@ -463,7 +513,8 @@ int __cpuinit start_secondary(void *cpuv
 	set_cpu_online(smp_processor_id(), true);
 	ipi_call_unlock();
 	__ctl_clear_bit(0, 28); /* Disable lowcore protection */
-	S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	S390_lowcore.restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	S390_lowcore.restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
 	__ctl_set_bit(0, 28); /* Enable lowcore protection */
@@ -511,7 +562,8 @@ static int __cpuinit smp_alloc_lowcore(i
 	memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
 	lowcore->async_stack = async_stack + ASYNC_SIZE;
 	lowcore->panic_stack = panic_stack + PAGE_SIZE;
-	lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lowcore->restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	lowcore->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
 	if (user_mode != HOME_SPACE_MODE)
@@ -712,6 +764,9 @@ void __init smp_prepare_cpus(unsigned in
 	/* request the 0x1201 emergency signal external interrupt */
 	if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
 		panic("Couldn't request external interrupt 0x1201");
+	/* request the 0x1202 external call external interrupt */
+	if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
+		panic("Couldn't request external interrupt 0x1202");
 
 	/* Reallocate current lowcore, but keep its contents. */
 	lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/suspend.c linux-libre-3.2-gnu1/arch/s390/kernel/suspend.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,8 @@
  */
 
 #include <linux/pfn.h>
+#include <linux/suspend.h>
+#include <linux/mm.h>
 #include <asm/system.h>
 
 /*
@@ -14,6 +16,123 @@
  */
 extern const void __nosave_begin, __nosave_end;
 
+/*
+ * The restore of the saved pages in an hibernation image will set
+ * the change and referenced bits in the storage key for each page.
+ * Overindication of the referenced bits after an hibernation cycle
+ * does not cause any harm but the overindication of the change bits
+ * would cause trouble.
+ * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
+ * page to the most significant byte of the associated page frame
+ * number in the hibernation image.
+ */
+
+/*
+ * Key storage is allocated as a linked list of pages.
+ * The size of the keys array is (PAGE_SIZE - sizeof(long))
+ */
+struct page_key_data {
+	struct page_key_data *next;
+	unsigned char data[];
+};
+
+#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
+
+static struct page_key_data *page_key_data;
+static struct page_key_data *page_key_rp, *page_key_wp;
+static unsigned long page_key_rx, page_key_wx;
+
+/*
+ * For each page in the hibernation image one additional byte is
+ * stored in the most significant byte of the page frame number.
+ * On suspend no additional memory is required but on resume the
+ * keys need to be memorized until the page data has been restored.
+ * Only then can the storage keys be set to their old state.
+ */
+unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+}
+
+/*
+ * Free page_key_data list of arrays.
+ */
+void page_key_free(void)
+{
+	struct page_key_data *pkd;
+
+	while (page_key_data) {
+		pkd = page_key_data;
+		page_key_data = pkd->next;
+		free_page((unsigned long) pkd);
+	}
+}
+
+/*
+ * Allocate page_key_data list of arrays with enough room to store
+ * one byte for each page in the hibernation image.
+ */
+int page_key_alloc(unsigned long pages)
+{
+	struct page_key_data *pk;
+	unsigned long size;
+
+	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+	while (size--) {
+		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
+		if (!pk) {
+			page_key_free();
+			return -ENOMEM;
+		}
+		pk->next = page_key_data;
+		page_key_data = pk;
+	}
+	page_key_rp = page_key_wp = page_key_data;
+	page_key_rx = page_key_wx = 0;
+	return 0;
+}
+
+/*
+ * Save the storage key into the upper 8 bits of the page frame number.
+ */
+void page_key_read(unsigned long *pfn)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) page_address(pfn_to_page(*pfn));
+	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
+}
+
+/*
+ * Extract the storage key from the upper 8 bits of the page frame number
+ * and store it in the page_key_data list of arrays.
+ */
+void page_key_memorize(unsigned long *pfn)
+{
+	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
+	*(unsigned char *) pfn = 0;
+	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_wp = page_key_wp->next;
+	page_key_wx = 0;
+}
+
+/*
+ * Get the next key from the page_key_data list of arrays and set the
+ * storage key of the page referred by @address. If @address refers to
+ * a "safe" page the swsusp_arch_resume code will transfer the storage
+ * key from the buffer page to the original page.
+ */
+void page_key_write(void *address)
+{
+	page_set_storage_key((unsigned long) address,
+			     page_key_rp->data[page_key_rx], 0);
+	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_rp = page_key_rp->next;
+	page_key_rx = 0;
+}
+
 int pfn_is_nosave(unsigned long pfn)
 {
 	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/swsusp_asm64.S linux-libre-3.2-gnu1/arch/s390/kernel/swsusp_asm64.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/swsusp_asm64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/swsusp_asm64.S	2012-01-04 18:55:44.000000000 -0500
@@ -136,11 +136,14 @@ ENTRY(swsusp_arch_resume)
 0:
 	lg	%r2,8(%r1)
 	lg	%r4,0(%r1)
+	iske	%r0,%r4
 	lghi	%r3,PAGE_SIZE
 	lghi	%r5,PAGE_SIZE
 1:
 	mvcle	%r2,%r4,0
 	jo	1b
+	lg	%r2,8(%r1)
+	sske	%r0,%r2
 	lg	%r1,16(%r1)
 	ltgr	%r1,%r1
 	jnz	0b
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/syscalls.S linux-libre-3.2-gnu1/arch/s390/kernel/syscalls.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/syscalls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/syscalls.S	2012-01-04 18:55:44.000000000 -0500
@@ -348,3 +348,5 @@ SYSCALL(sys_open_by_handle_at,sys_open_b
 SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
 SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/sysinfo.c linux-libre-3.2-gnu1/arch/s390/kernel/sysinfo.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/sysinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/sysinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -442,7 +442,7 @@ void s390_adjust_jiffies(void)
 		 */
 		FP_UNPACK_SP(SA, &fmil);
 		if ((info->capability >> 23) == 0)
-			FP_FROM_INT_S(SB, info->capability, 32, int);
+			FP_FROM_INT_S(SB, (long) info->capability, 64, long);
 		else
 			FP_UNPACK_SP(SB, &info->capability);
 		FP_DIV_S(SR, SA, SB);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/time.c linux-libre-3.2-gnu1/arch/s390/kernel/time.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 #include <asm/timer.h>
 #include <asm/etr.h>
 #include <asm/cio.h>
+#include "entry.h"
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
@@ -109,10 +110,14 @@ static void fixup_clock_comparator(unsig
 	set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
-static int s390_next_event(unsigned long delta,
+static int s390_next_ktime(ktime_t expires,
 			   struct clock_event_device *evt)
 {
-	S390_lowcore.clock_comparator = get_clock() + delta;
+	u64 nsecs;
+
+	nsecs = ktime_to_ns(ktime_sub(expires, ktime_get_monotonic_offset()));
+	do_div(nsecs, 125);
+	S390_lowcore.clock_comparator = TOD_UNIX_EPOCH + (nsecs << 9);
 	set_clock_comparator(S390_lowcore.clock_comparator);
 	return 0;
 }
@@ -137,14 +142,15 @@ void init_cpu_timer(void)
 	cpu = smp_processor_id();
 	cd = &per_cpu(comparators, cpu);
 	cd->name		= "comparator";
-	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
+	cd->features		= CLOCK_EVT_FEAT_ONESHOT |
+				  CLOCK_EVT_FEAT_KTIME;
 	cd->mult		= 16777;
 	cd->shift		= 12;
 	cd->min_delta_ns	= 1;
 	cd->max_delta_ns	= LONG_MAX;
 	cd->rating		= 400;
 	cd->cpumask		= cpumask_of(cpu);
-	cd->set_next_event	= s390_next_event;
+	cd->set_next_ktime	= s390_next_ktime;
 	cd->set_mode		= s390_set_mode;
 
 	clockevents_register_device(cd);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/topology.c linux-libre-3.2-gnu1/arch/s390/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,8 +68,10 @@ static cpumask_t cpu_group_map(struct ma
 	return mask;
 }
 
-static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
-			     struct mask_info *book, struct mask_info *core)
+static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
+					  struct mask_info *book,
+					  struct mask_info *core,
+					  int z10)
 {
 	unsigned int cpu;
 
@@ -88,10 +90,16 @@ static void add_cpus_to_mask(struct topo
 			cpu_book_id[lcpu] = book->id;
 #endif
 			cpumask_set_cpu(lcpu, &core->mask);
-			cpu_core_id[lcpu] = core->id;
+			if (z10) {
+				cpu_core_id[lcpu] = rcpu;
+				core = core->next;
+			} else {
+				cpu_core_id[lcpu] = core->id;
+			}
 			smp_cpu_polarization[lcpu] = tl_cpu->pp;
 		}
 	}
+	return core;
 }
 
 static void clear_masks(void)
@@ -123,18 +131,41 @@ static void tl_to_cores(struct sysinfo_1
 {
 #ifdef CONFIG_SCHED_BOOK
 	struct mask_info *book = &book_info;
+	struct cpuid cpu_id;
 #else
 	struct mask_info *book = NULL;
 #endif
 	struct mask_info *core = &core_info;
 	union topology_entry *tle, *end;
+	int z10 = 0;
 
-
+#ifdef CONFIG_SCHED_BOOK
+	get_cpu_id(&cpu_id);
+	z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
+#endif
 	spin_lock_irq(&topology_lock);
 	clear_masks();
 	tle = info->tle;
 	end = (union topology_entry *)((unsigned long)info + info->length);
 	while (tle < end) {
+#ifdef CONFIG_SCHED_BOOK
+		if (z10) {
+			switch (tle->nl) {
+			case 1:
+				book = book->next;
+				book->id = tle->container.id;
+				break;
+			case 0:
+				core = add_cpus_to_mask(&tle->cpu, book, core, z10);
+				break;
+			default:
+				clear_masks();
+				goto out;
+			}
+			tle = next_tle(tle);
+			continue;
+		}
+#endif
 		switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
 		case 2:
@@ -147,7 +178,7 @@ static void tl_to_cores(struct sysinfo_1
 			core->id = tle->container.id;
 			break;
 		case 0:
-			add_cpus_to_mask(&tle->cpu, book, core);
+			add_cpus_to_mask(&tle->cpu, book, core, z10);
 			break;
 		default:
 			clear_masks();
@@ -299,8 +330,8 @@ out:
 }
 __initcall(init_topology_update);
 
-static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask,
-			int offset)
+static void __init alloc_masks(struct sysinfo_15_1_x *info,
+			       struct mask_info *mask, int offset)
 {
 	int i, nr_masks;
 
@@ -328,8 +359,8 @@ void __init s390_init_cpu_topology(void)
 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
 		printk(" %d", info->mag[i]);
 	printk(" / %d\n", info->mnest);
-	alloc_masks(info, &core_info, 2);
+	alloc_masks(info, &core_info, 1);
 #ifdef CONFIG_SCHED_BOOK
-	alloc_masks(info, &book_info, 3);
+	alloc_masks(info, &book_info, 2);
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/traps.c linux-libre-3.2-gnu1/arch/s390/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@ void show_registers(struct pt_regs *regs
 	       mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
 	       mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
 #ifdef CONFIG_64BIT
-	printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS));
+	printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
 #endif
 	printk("\n%s GPRS: " FOURLONG, mode,
 	       regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
@@ -334,7 +334,8 @@ void __kprobes do_per_trap(struct pt_reg
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
 	info.si_code = TRAP_HWBKPT;
-	info.si_addr = (void *) current->thread.per_event.address;
+	info.si_addr =
+		(void __force __user *) current->thread.per_event.address;
 	force_sig_info(SIGTRAP, &info, current);
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/vmlinux.lds.S linux-libre-3.2-gnu1/arch/s390/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu1/arch/s390/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,8 @@ SECTIONS
 
 	NOTES :text :note
 
+	.dummy : { *(.dummy) } :data
+
 	RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
diff -druNp linux-libre-3.1-gnu1/arch/s390/kernel/vtime.c linux-libre-3.2-gnu1/arch/s390/kernel/vtime.c
--- linux-libre-3.1-gnu1/arch/s390/kernel/vtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kernel/vtime.c	2012-01-04 18:55:44.000000000 -0500
@@ -170,7 +170,8 @@ void __kprobes vtime_stop_cpu(void)
 	psw_t psw;
 
 	/* Wait for external, I/O or machine check interrupt. */
-	psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+	psw.mask = psw_kernel_bits | PSW_MASK_WAIT |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 
 	idle->nohz_delay = 0;
 
@@ -183,7 +184,8 @@ void __kprobes vtime_stop_cpu(void)
 		 *	set_cpu_timer(VTIMER_MAX_SLICE);
 		 *	idle->idle_enter = get_clock();
 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
-		 *			   PSW_MASK_IO | PSW_MASK_EXT);
+		 *			   PSW_MASK_DAT | PSW_MASK_IO |
+		 *			   PSW_MASK_EXT | PSW_MASK_MCHECK);
 		 * The difference is that the inline assembly makes sure that
 		 * the last three instruction are stpt, stck and lpsw in that
 		 * order. This is done to increase the precision.
@@ -216,7 +218,8 @@ void __kprobes vtime_stop_cpu(void)
 		 *	vq->idle = get_cpu_timer();
 		 *	idle->idle_enter = get_clock();
 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
-		 *			   PSW_MASK_IO | PSW_MASK_EXT);
+		 *			   PSW_MASK_DAT | PSW_MASK_IO |
+		 *			   PSW_MASK_EXT | PSW_MASK_MCHECK);
 		 * The difference is that the inline assembly makes sure that
 		 * the last three instruction are stpt, stck and lpsw in that
 		 * order. This is done to increase the precision.
@@ -458,7 +461,7 @@ void add_virt_timer_periodic(void *new)
 }
 EXPORT_SYMBOL(add_virt_timer_periodic);
 
-int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
+static int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
 {
 	struct vtimer_queue *vq;
 	unsigned long flags;
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/diag.c linux-libre-3.2-gnu1/arch/s390/kvm/diag.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * diag.c - handling diagnose instructions
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2011
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -15,6 +15,34 @@
 #include <linux/kvm_host.h>
 #include "kvm-s390.h"
 
+static int diag_release_pages(struct kvm_vcpu *vcpu)
+{
+	unsigned long start, end;
+	unsigned long prefix  = vcpu->arch.sie_block->prefix;
+
+	start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
+	end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+
+	if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
+	    || start < 2 * PAGE_SIZE)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+	VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
+	vcpu->stat.diagnose_10++;
+
+	/* we checked for start > end above */
+	if (end < prefix || start >= prefix + 2 * PAGE_SIZE) {
+		gmap_discard(start, end, vcpu->arch.gmap);
+	} else {
+		if (start < prefix)
+			gmap_discard(start, prefix, vcpu->arch.gmap);
+		if (end >= prefix)
+			gmap_discard(prefix + 2 * PAGE_SIZE,
+				     end, vcpu->arch.gmap);
+	}
+	return 0;
+}
+
 static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
@@ -42,7 +70,7 @@ static int __diag_ipl_functions(struct k
 		return -EOPNOTSUPP;
 	}
 
-	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+	atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
@@ -57,6 +85,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu
 	int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
 
 	switch (code) {
+	case 0x10:
+		return diag_release_pages(vcpu);
 	case 0x44:
 		return __diag_time_slice_end(vcpu);
 	case 0x308:
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/intercept.c linux-libre-3.2-gnu1/arch/s390/kvm/intercept.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/intercept.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/intercept.c	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *
 	int rc = 0;
 
 	vcpu->stat.exit_stop_request++;
-	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	spin_lock_bh(&vcpu->arch.local_int.lock);
 	if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
 		vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
@@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *
 	}
 
 	if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+		atomic_set_mask(CPUSTAT_STOPPED,
+				&vcpu->arch.sie_block->cpuflags);
 		vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
 		VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
 		rc = -EOPNOTSUPP;
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/interrupt.c linux-libre-3.2-gnu1/arch/s390/kvm/interrupt.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,11 @@ static int __interrupt_is_deliverable(st
 				      struct kvm_s390_interrupt_info *inti)
 {
 	switch (inti->type) {
+	case KVM_S390_INT_EXTERNAL_CALL:
+		if (psw_extint_disabled(vcpu))
+			return 0;
+		if (vcpu->arch.sie_block->gcr[0] & 0x2000ul)
+			return 1;
 	case KVM_S390_INT_EMERGENCY:
 		if (psw_extint_disabled(vcpu))
 			return 0;
@@ -98,6 +103,7 @@ static void __set_intercept_indicator(st
 				      struct kvm_s390_interrupt_info *inti)
 {
 	switch (inti->type) {
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 	case KVM_S390_INT_SERVICE:
 	case KVM_S390_INT_VIRTIO:
@@ -143,6 +149,28 @@ static void __do_deliver_interrupt(struc
 			exception = 1;
 		break;
 
+	case KVM_S390_INT_EXTERNAL_CALL:
+		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
+		vcpu->stat.deliver_external_call++;
+		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->extcall.code);
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+			__LC_EXT_NEW_PSW, sizeof(psw_t));
+		if (rc == -EFAULT)
+			exception = 1;
+		break;
+
 	case KVM_S390_INT_SERVICE:
 		VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
 			   inti->ext.ext_params);
@@ -224,6 +252,7 @@ static void __do_deliver_interrupt(struc
 			offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
 		if (rc == -EFAULT)
 			exception = 1;
+		atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 		break;
 
 	case KVM_S390_PROGRAM_INT:
@@ -522,6 +551,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
 		break;
 	case KVM_S390_PROGRAM_INT:
 	case KVM_S390_SIGP_STOP:
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 	default:
 		kfree(inti);
@@ -581,6 +611,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu
 		break;
 	case KVM_S390_SIGP_STOP:
 	case KVM_S390_RESTART:
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 		VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
 		inti->type = s390int->type;
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/kvm-s390.c linux-libre-3.2-gnu1/arch/s390/kvm/kvm-s390.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/kvm-s390.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/kvm-s390.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
 	{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
 	{ "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
+	{ "deliver_external_call", VCPU_STAT(deliver_external_call) },
 	{ "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
 	{ "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
 	{ "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
@@ -64,11 +65,14 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
 	{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
 	{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+	{ "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
+	{ "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
 	{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
 	{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
 	{ "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
 	{ "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
 	{ "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
+	{ "diagnose_10", VCPU_STAT(diagnose_10) },
 	{ "diagnose_44", VCPU_STAT(diagnose_44) },
 	{ NULL }
 };
@@ -124,6 +128,7 @@ int kvm_dev_ioctl_check_extension(long e
 	switch (ext) {
 	case KVM_CAP_S390_PSW:
 	case KVM_CAP_S390_GMAP:
+	case KVM_CAP_SYNC_MMU:
 		r = 1;
 		break;
 	default:
@@ -175,6 +180,8 @@ int kvm_arch_init_vm(struct kvm *kvm)
 	if (rc)
 		goto out_err;
 
+	rc = -ENOMEM;
+
 	kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
 	if (!kvm->arch.sca)
 		goto out_err;
@@ -265,10 +272,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 	restore_fp_regs(&vcpu->arch.guest_fpregs);
 	restore_access_regs(vcpu->arch.guest_acrs);
 	gmap_enable(vcpu->arch.gmap);
+	atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	gmap_disable(vcpu->arch.gmap);
 	save_fp_regs(&vcpu->arch.guest_fpregs);
 	save_access_regs(vcpu->arch.guest_acrs);
@@ -296,7 +305,9 @@ static void kvm_s390_vcpu_initial_reset(
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
+	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
+						    CPUSTAT_SM |
+						    CPUSTAT_STOPPED);
 	vcpu->arch.sie_block->ecb   = 6;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
 	vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -312,11 +323,17 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 				      unsigned int id)
 {
-	struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
-	int rc = -ENOMEM;
+	struct kvm_vcpu *vcpu;
+	int rc = -EINVAL;
 
+	if (id >= KVM_MAX_VCPUS)
+		goto out;
+
+	rc = -ENOMEM;
+
+	vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
 	if (!vcpu)
-		goto out_nomem;
+		goto out;
 
 	vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
 					get_zeroed_page(GFP_KERNEL);
@@ -352,7 +369,7 @@ out_free_sie_block:
 	free_page((unsigned long)(vcpu->arch.sie_block));
 out_free_cpu:
 	kfree(vcpu);
-out_nomem:
+out:
 	return ERR_PTR(rc);
 }
 
@@ -386,6 +403,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 {
 	memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
 	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
+	restore_access_regs(vcpu->arch.guest_acrs);
 	return 0;
 }
 
@@ -401,6 +419,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct k
 {
 	memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
 	vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+	restore_fp_regs(&vcpu->arch.guest_fpregs);
 	return 0;
 }
 
@@ -415,7 +434,7 @@ static int kvm_arch_vcpu_ioctl_set_initi
 {
 	int rc = 0;
 
-	if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
+	if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
 		rc = -EBUSY;
 	else {
 		vcpu->run->psw_mask = psw.mask;
@@ -488,7 +507,7 @@ rerun_vcpu:
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
-	atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+	atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 
 	BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
 
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/priv.c linux-libre-3.2-gnu1/arch/s390/kvm/priv.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/priv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/priv.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,6 +336,7 @@ static int handle_tprot(struct kvm_vcpu
 	u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
 	u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
 	struct vm_area_struct *vma;
+	unsigned long user_address;
 
 	vcpu->stat.instruction_tprot++;
 
@@ -349,9 +350,14 @@ static int handle_tprot(struct kvm_vcpu
 		return -EOPNOTSUPP;
 
 
+	/* we must resolve the address without holding the mmap semaphore.
+	 * This is ok since the userspace hypervisor is not supposed to change
+	 * the mapping while the guest queries the memory. Otherwise the guest
+	 * might crash or get wrong info anyway. */
+	user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
+
 	down_read(&current->mm->mmap_sem);
-	vma = find_vma(current->mm,
-			(unsigned long) __guestaddr_to_user(vcpu, address1));
+	vma = find_vma(current->mm, user_address);
 	if (!vma) {
 		up_read(&current->mm->mmap_sem);
 		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
diff -druNp linux-libre-3.1-gnu1/arch/s390/kvm/sigp.c linux-libre-3.2-gnu1/arch/s390/kvm/sigp.c
--- linux-libre-3.1-gnu1/arch/s390/kvm/sigp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/kvm/sigp.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,9 +31,11 @@
 #define SIGP_SET_PREFIX        0x0d
 #define SIGP_STORE_STATUS_ADDR 0x0e
 #define SIGP_SET_ARCH          0x12
+#define SIGP_SENSE_RUNNING     0x15
 
 /* cpu status bits */
 #define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_NOT_RUNNING	    0x00000400UL
 #define SIGP_STAT_INCORRECT_STATE   0x00000200UL
 #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
 #define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
@@ -57,8 +59,8 @@ static int __sigp_sense(struct kvm_vcpu
 	spin_lock(&fi->lock);
 	if (fi->local_int[cpu_addr] == NULL)
 		rc = 3; /* not operational */
-	else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
-		 & CPUSTAT_RUNNING) {
+	else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
+		  & CPUSTAT_STOPPED)) {
 		*reg &= 0xffffffff00000000UL;
 		rc = 1; /* status stored */
 	} else {
@@ -87,6 +89,7 @@ static int __sigp_emergency(struct kvm_v
 		return -ENOMEM;
 
 	inti->type = KVM_S390_INT_EMERGENCY;
+	inti->emerg.code = vcpu->vcpu_id;
 
 	spin_lock(&fi->lock);
 	li = fi->local_int[cpu_addr];
@@ -103,9 +106,47 @@ static int __sigp_emergency(struct kvm_v
 		wake_up_interruptible(&li->wq);
 	spin_unlock_bh(&li->lock);
 	rc = 0; /* order accepted */
+	VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
+unlock:
+	spin_unlock(&fi->lock);
+	return rc;
+}
+
+static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+	struct kvm_s390_local_interrupt *li;
+	struct kvm_s390_interrupt_info *inti;
+	int rc;
+
+	if (cpu_addr >= KVM_MAX_VCPUS)
+		return 3; /* not operational */
+
+	inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+	if (!inti)
+		return -ENOMEM;
+
+	inti->type = KVM_S390_INT_EXTERNAL_CALL;
+	inti->extcall.code = vcpu->vcpu_id;
+
+	spin_lock(&fi->lock);
+	li = fi->local_int[cpu_addr];
+	if (li == NULL) {
+		rc = 3; /* not operational */
+		kfree(inti);
+		goto unlock;
+	}
+	spin_lock_bh(&li->lock);
+	list_add_tail(&inti->list, &li->list);
+	atomic_set(&li->active, 1);
+	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+	if (waitqueue_active(&li->wq))
+		wake_up_interruptible(&li->wq);
+	spin_unlock_bh(&li->lock);
+	rc = 0; /* order accepted */
+	VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr);
 unlock:
 	spin_unlock(&fi->lock);
-	VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
 	return rc;
 }
 
@@ -212,7 +253,7 @@ static int __sigp_set_prefix(struct kvm_
 
 	spin_lock_bh(&li->lock);
 	/* cpu must be in stopped state */
-	if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
+	if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
 		rc = 1; /* incorrect state */
 		*reg &= SIGP_STAT_INCORRECT_STATE;
 		kfree(inti);
@@ -236,6 +277,38 @@ out_fi:
 	return rc;
 }
 
+static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
+				unsigned long *reg)
+{
+	int rc;
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+
+	if (cpu_addr >= KVM_MAX_VCPUS)
+		return 3; /* not operational */
+
+	spin_lock(&fi->lock);
+	if (fi->local_int[cpu_addr] == NULL)
+		rc = 3; /* not operational */
+	else {
+		if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
+		    & CPUSTAT_RUNNING) {
+			/* running */
+			rc = 1;
+		} else {
+			/* not running */
+			*reg &= 0xffffffff00000000UL;
+			*reg |= SIGP_STAT_NOT_RUNNING;
+			rc = 0;
+		}
+	}
+	spin_unlock(&fi->lock);
+
+	VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
+		   rc);
+
+	return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
 	int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -267,6 +340,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu
 		rc = __sigp_sense(vcpu, cpu_addr,
 				  &vcpu->arch.guest_gprs[r1]);
 		break;
+	case SIGP_EXTERNAL_CALL:
+		vcpu->stat.instruction_sigp_external_call++;
+		rc = __sigp_external_call(vcpu, cpu_addr);
+		break;
 	case SIGP_EMERGENCY:
 		vcpu->stat.instruction_sigp_emergency++;
 		rc = __sigp_emergency(vcpu, cpu_addr);
@@ -288,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu
 		rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
 				       &vcpu->arch.guest_gprs[r1]);
 		break;
+	case SIGP_SENSE_RUNNING:
+		vcpu->stat.instruction_sigp_sense_running++;
+		rc = __sigp_sense_running(vcpu, cpu_addr,
+					  &vcpu->arch.guest_gprs[r1]);
+		break;
 	case SIGP_RESTART:
 		vcpu->stat.instruction_sigp_restart++;
 		/* user space must know about restart */
diff -druNp linux-libre-3.1-gnu1/arch/s390/lib/delay.c linux-libre-3.2-gnu1/arch/s390/lib/delay.c
--- linux-libre-3.1-gnu1/arch/s390/lib/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/lib/delay.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,8 @@ static void __udelay_disabled(unsigned l
 	u64 clock_saved;
 	u64 end;
 
-	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+	mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_WAIT |
+		PSW_MASK_EXT | PSW_MASK_MCHECK;
 	end = get_clock() + (usecs << 12);
 	clock_saved = local_tick_disable();
 	__ctl_store(cr0_saved, 0, 0);
diff -druNp linux-libre-3.1-gnu1/arch/s390/lib/uaccess_pt.c linux-libre-3.2-gnu1/arch/s390/lib/uaccess_pt.c
--- linux-libre-3.1-gnu1/arch/s390/lib/uaccess_pt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/lib/uaccess_pt.c	2012-01-04 18:55:44.000000000 -0500
@@ -342,7 +342,8 @@ int futex_atomic_op_pt(int op, u32 __use
 	if (segment_eq(get_fs(), KERNEL_DS))
 		return __futex_atomic_op_pt(op, uaddr, oparg, old);
 	spin_lock(&current->mm->page_table_lock);
-	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+	uaddr = (u32 __force __user *)
+		__dat_user_addr((__force unsigned long) uaddr);
 	if (!uaddr) {
 		spin_unlock(&current->mm->page_table_lock);
 		return -EFAULT;
@@ -378,7 +379,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u
 	if (segment_eq(get_fs(), KERNEL_DS))
 		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
-	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+	uaddr = (u32 __force __user *)
+		__dat_user_addr((__force unsigned long) uaddr);
 	if (!uaddr) {
 		spin_unlock(&current->mm->page_table_lock);
 		return -EFAULT;
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/fault.c linux-libre-3.2-gnu1/arch/s390/mm/fault.c
--- linux-libre-3.1-gnu1/arch/s390/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -307,7 +307,7 @@ static inline int do_exception(struct pt
 
 #ifdef CONFIG_PGSTE
 	if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
-		address = gmap_fault(address,
+		address = __gmap_fault(address,
 				     (struct gmap *) S390_lowcore.gmap);
 		if (address == -EFAULT) {
 			fault = VM_FAULT_BADMAP;
@@ -393,7 +393,7 @@ void __kprobes do_protection_exception(s
 	int fault;
 
 	/* Protection exception is suppressing, decrement psw address. */
-	regs->psw.addr -= (pgm_int_code >> 16);
+	regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16);
 	/*
 	 * Check for low-address protection.  This needs to be treated
 	 * as a special case because the translation exception code
@@ -454,7 +454,7 @@ int __handle_fault(unsigned long uaddr,
 	struct pt_regs regs;
 	int access, fault;
 
-	regs.psw.mask = psw_kernel_bits;
+	regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
 	if (!irqs_disabled())
 		regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) __builtin_return_address(0);
@@ -587,8 +587,13 @@ static void pfault_interrupt(unsigned in
 		} else {
 			/* Completion interrupt was faster than initial
 			 * interrupt. Set pfault_wait to -1 so the initial
-			 * interrupt doesn't put the task to sleep. */
-			tsk->thread.pfault_wait = -1;
+			 * interrupt doesn't put the task to sleep.
+			 * If the task is not running, ignore the completion
+			 * interrupt since it must be a leftover of a PFAULT
+			 * CANCEL operation which didn't remove all pending
+			 * completion interrupts. */
+			if (tsk->state == TASK_RUNNING)
+				tsk->thread.pfault_wait = -1;
 		}
 		put_task_struct(tsk);
 	} else {
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/gup.c linux-libre-3.2-gnu1/arch/s390/mm/gup.c
--- linux-libre-3.1-gnu1/arch/s390/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@ static inline int gup_huge_pmd(pmd_t *pm
 		unsigned long end, int write, struct page **pages, int *nr)
 {
 	unsigned long mask, result;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	int refs;
 
 	result = write ? 0 : _SEGMENT_ENTRY_RO;
@@ -64,6 +64,7 @@ static inline int gup_huge_pmd(pmd_t *pm
 	refs = 0;
 	head = pmd_page(pmd);
 	page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -81,6 +82,17 @@ static inline int gup_huge_pmd(pmd_t *pm
 		*nr -= refs;
 		while (refs--)
 			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/init.c linux-libre-3.2-gnu1/arch/s390/mm/init.c
--- linux-libre-3.1-gnu1/arch/s390/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/initrd.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <asm/processor.h>
 #include <asm/system.h>
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/maccess.c linux-libre-3.2-gnu1/arch/s390/mm/maccess.c
--- linux-libre-3.1-gnu1/arch/s390/mm/maccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/maccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/gfp.h>
 #include <asm/system.h>
 
 /*
@@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const
 	return copied < 0 ? -EFAULT : 0;
 }
 
+/*
+ * Copy memory in real mode (kernel to kernel)
+ */
 int memcpy_real(void *dest, void *src, size_t count)
 {
 	register unsigned long _dest asm("2") = (unsigned long) dest;
@@ -101,3 +105,55 @@ void copy_to_absolute_zero(void *dest, v
 	__ctl_load(cr0, 0, 0);
 	preempt_enable();
 }
+
+/*
+ * Copy memory from kernel (real) to user (virtual)
+ */
+int copy_to_user_real(void __user *dest, void *src, size_t count)
+{
+	int offs = 0, size, rc;
+	char *buf;
+
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	rc = -EFAULT;
+	while (offs < count) {
+		size = min(PAGE_SIZE, count - offs);
+		if (memcpy_real(buf, src + offs, size))
+			goto out;
+		if (copy_to_user(dest + offs, buf, size))
+			goto out;
+		offs += size;
+	}
+	rc = 0;
+out:
+	free_page((unsigned long) buf);
+	return rc;
+}
+
+/*
+ * Copy memory from user (virtual) to kernel (real)
+ */
+int copy_from_user_real(void *dest, void __user *src, size_t count)
+{
+	int offs = 0, size, rc;
+	char *buf;
+
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	rc = -EFAULT;
+	while (offs < count) {
+		size = min(PAGE_SIZE, count - offs);
+		if (copy_from_user(buf, src + offs, size))
+			goto out;
+		if (memcpy_real(dest + offs, buf, size))
+			goto out;
+		offs += size;
+	}
+	rc = 0;
+out:
+	free_page((unsigned long) buf);
+	return rc;
+}
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/mmap.c linux-libre-3.2-gnu1/arch/s390/mm/mmap.c
--- linux-libre-3.1-gnu1/arch/s390/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/personality.h>
 #include <linux/mm.h>
+#include <linux/mman.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <asm/pgalloc.h>
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/pageattr.c linux-libre-3.2-gnu1/arch/s390/mm/pageattr.c
--- linux-libre-3.1-gnu1/arch/s390/mm/pageattr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/pageattr.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
 static void change_page_attr(unsigned long addr, int numpages,
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/pgtable.c linux-libre-3.2-gnu1/arch/s390/mm/pgtable.c
--- linux-libre-3.1-gnu1/arch/s390/mm/pgtable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/pgtable.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007,2009
+ *    Copyright IBM Corp. 2007,2011
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
@@ -222,6 +222,7 @@ void gmap_free(struct gmap *gmap)
 
 	/* Free all segment & region tables. */
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	list_for_each_entry_safe(page, next, &gmap->crst_list, lru) {
 		table = (unsigned long *) page_to_phys(page);
 		if ((*table & _REGION_ENTRY_TYPE_MASK) == 0)
@@ -230,6 +231,7 @@ void gmap_free(struct gmap *gmap)
 				gmap_unlink_segment(gmap, table);
 		__free_pages(page, ALLOC_ORDER);
 	}
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	list_del(&gmap->list);
 	kfree(gmap);
@@ -256,6 +258,9 @@ void gmap_disable(struct gmap *gmap)
 }
 EXPORT_SYMBOL_GPL(gmap_disable);
 
+/*
+ * gmap_alloc_table is assumed to be called with mmap_sem held
+ */
 static int gmap_alloc_table(struct gmap *gmap,
 			       unsigned long *table, unsigned long init)
 {
@@ -267,14 +272,12 @@ static int gmap_alloc_table(struct gmap
 		return -ENOMEM;
 	new = (unsigned long *) page_to_phys(page);
 	crst_table_init(new, init);
-	down_read(&gmap->mm->mmap_sem);
 	if (*table & _REGION_ENTRY_INV) {
 		list_add(&page->lru, &gmap->crst_list);
 		*table = (unsigned long) new | _REGION_ENTRY_LENGTH |
 			(*table & _REGION_ENTRY_TYPE_MASK);
 	} else
 		__free_pages(page, ALLOC_ORDER);
-	up_read(&gmap->mm->mmap_sem);
 	return 0;
 }
 
@@ -299,6 +302,7 @@ int gmap_unmap_segment(struct gmap *gmap
 
 	flush = 0;
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the guest addr space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -320,6 +324,7 @@ int gmap_unmap_segment(struct gmap *gmap
 		*table = _SEGMENT_ENTRY_INV;
 	}
 out:
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	if (flush)
 		gmap_flush_tlb(gmap);
@@ -350,6 +355,7 @@ int gmap_map_segment(struct gmap *gmap,
 
 	flush = 0;
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the gmap address space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -373,19 +379,24 @@ int gmap_map_segment(struct gmap *gmap,
 		flush |= gmap_unlink_segment(gmap, table);
 		*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
 	}
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	if (flush)
 		gmap_flush_tlb(gmap);
 	return 0;
 
 out_unmap:
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	gmap_unmap_segment(gmap, to, len);
 	return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(gmap_map_segment);
 
-unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
 {
 	unsigned long *table, vmaddr, segment;
 	struct mm_struct *mm;
@@ -445,16 +456,75 @@ unsigned long gmap_fault(unsigned long a
 		page = pmd_page(*pmd);
 		mp = (struct gmap_pgtable *) page->index;
 		rmap->entry = table;
+		spin_lock(&mm->page_table_lock);
 		list_add(&rmap->list, &mp->mapper);
+		spin_unlock(&mm->page_table_lock);
 		/* Set gmap segment table entry to page table. */
 		*table = pmd_val(*pmd) & PAGE_MASK;
 		return vmaddr | (address & ~PMD_MASK);
 	}
 	return -EFAULT;
+}
+
+unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+{
+	unsigned long rc;
 
+	down_read(&gmap->mm->mmap_sem);
+	rc = __gmap_fault(address, gmap);
+	up_read(&gmap->mm->mmap_sem);
+
+	return rc;
 }
 EXPORT_SYMBOL_GPL(gmap_fault);
 
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
+{
+
+	unsigned long *table, address, size;
+	struct vm_area_struct *vma;
+	struct gmap_pgtable *mp;
+	struct page *page;
+
+	down_read(&gmap->mm->mmap_sem);
+	address = from;
+	while (address < to) {
+		/* Walk the gmap address space page table */
+		table = gmap->table + ((address >> 53) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 42) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 31) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 20) & 0x7ff);
+		if (unlikely(*table & _SEGMENT_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		page = pfn_to_page(*table >> PAGE_SHIFT);
+		mp = (struct gmap_pgtable *) page->index;
+		vma = find_vma(gmap->mm, mp->vmaddr);
+		size = min(to - address, PMD_SIZE - (address & ~PMD_MASK));
+		zap_page_range(vma, mp->vmaddr | (address & ~PMD_MASK),
+			       size, NULL);
+		address = (address + PMD_SIZE) & PMD_MASK;
+	}
+	up_read(&gmap->mm->mmap_sem);
+}
+EXPORT_SYMBOL_GPL(gmap_discard);
+
 void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
 {
 	struct gmap_rmap *rmap, *next;
@@ -662,8 +732,9 @@ void page_table_free_rcu(struct mmu_gath
 
 void __tlb_remove_table(void *_table)
 {
-	void *table = (void *)((unsigned long) _table & PAGE_MASK);
-	unsigned type = (unsigned long) _table & ~PAGE_MASK;
+	const unsigned long mask = (FRAG_MASK << 4) | FRAG_MASK;
+	void *table = (void *)((unsigned long) _table & ~mask);
+	unsigned type = (unsigned long) _table & mask;
 
 	if (type)
 		__page_table_free_rcu(table, type);
diff -druNp linux-libre-3.1-gnu1/arch/s390/mm/vmem.c linux-libre-3.2-gnu1/arch/s390/mm/vmem.c
--- linux-libre-3.1-gnu1/arch/s390/mm/vmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/mm/vmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,6 +335,9 @@ void __init vmem_map_init(void)
 	ro_start = ((unsigned long)&_stext) & PAGE_MASK;
 	ro_end = PFN_ALIGN((unsigned long)&_eshared);
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		if (memory_chunk[i].type == CHUNK_CRASHK ||
+		    memory_chunk[i].type == CHUNK_OLDMEM)
+			continue;
 		start = memory_chunk[i].addr;
 		end = memory_chunk[i].addr + memory_chunk[i].size;
 		if (start >= ro_end || end <= ro_start)
@@ -368,6 +371,9 @@ static int __init vmem_convert_memory_ch
 	for (i = 0; i < MEMORY_CHUNKS; i++) {
 		if (!memory_chunk[i].size)
 			continue;
+		if (memory_chunk[i].type == CHUNK_CRASHK ||
+		    memory_chunk[i].type == CHUNK_OLDMEM)
+			continue;
 		seg = kzalloc(sizeof(*seg), GFP_KERNEL);
 		if (!seg)
 			panic("Out of memory...\n");
diff -druNp linux-libre-3.1-gnu1/arch/s390/oprofile/hwsampler.c linux-libre-3.2-gnu1/arch/s390/oprofile/hwsampler.c
--- linux-libre-3.1-gnu1/arch/s390/oprofile/hwsampler.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/oprofile/hwsampler.c	2012-01-04 18:55:44.000000000 -0500
@@ -994,7 +994,7 @@ allocate_error:
  *
  * Returns 0 on success, !0 on failure.
  */
-int hwsampler_deallocate()
+int hwsampler_deallocate(void)
 {
 	int rc;
 
@@ -1035,7 +1035,7 @@ unsigned long hwsampler_get_sample_overf
 	return cb->sample_overflow;
 }
 
-int hwsampler_setup()
+int hwsampler_setup(void)
 {
 	int rc;
 	int cpu;
@@ -1102,7 +1102,7 @@ setup_exit:
 	return rc;
 }
 
-int hwsampler_shutdown()
+int hwsampler_shutdown(void)
 {
 	int rc;
 
@@ -1203,7 +1203,7 @@ start_all_exit:
  *
  * Returns 0 on success, !0 on failure.
  */
-int hwsampler_stop_all()
+int hwsampler_stop_all(void)
 {
 	int tmp_rc, rc, cpu;
 	struct hws_cpu_buffer *cb;
diff -druNp linux-libre-3.1-gnu1/arch/s390/oprofile/init.c linux-libre-3.2-gnu1/arch/s390/oprofile/init.c
--- linux-libre-3.1-gnu1/arch/s390/oprofile/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/s390/oprofile/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,7 @@ static ssize_t hwsampler_write(struct fi
 		return -EINVAL;
 
 	retval = oprofilefs_ulong_from_user(&val, buf, count);
-	if (retval)
+	if (retval <= 0)
 		return retval;
 
 	if (oprofile_started)
diff -druNp linux-libre-3.1-gnu1/arch/score/Kconfig linux-libre-3.2-gnu1/arch/score/Kconfig
--- linux-libre-3.1-gnu1/arch/score/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/score/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -52,16 +52,6 @@ config GENERIC_CALIBRATE_DELAY
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config SCHED_NO_NO_OMIT_FRAME_POINTER
-	def_bool y
-
-config GENERIC_SYSCALL_TABLE
-	def_bool y
-
-config SCORE_L1_CACHE_SHIFT
-	int
-	default "4"
-
 menu "Kernel type"
 
 config 32BIT
@@ -96,15 +86,6 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
-config PROBE_INITRD_HEADER
-	bool "Probe initrd header created by addinitrd"
-	depends on BLK_DEV_INITRD
-	help
-	  Probe initrd header at the last page of kernel image.
-	  Say Y here if you are using arch/score/boot/addinitrd.c to
-	  add initrd or initramfs image to the kernel image.
-	  Otherwise, say N.
-
 config MMU
 	def_bool y
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/board-espt.c linux-libre-3.2-gnu1/arch/sh/boards/board-espt.c
--- linux-libre-3.1-gnu1/arch/sh/boards/board-espt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/board-espt.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,9 @@
 #include <linux/interrupt.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
+#include <linux/sh_eth.h>
 #include <asm/machvec.h>
 #include <asm/sizes.h>
-#include <asm/sh_eth.h>
 
 /* NOR Flash */
 static struct mtd_partition espt_nor_flash_partitions[] = {
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/board-secureedge5410.c linux-libre-3.2-gnu1/arch/sh/boards/board-secureedge5410.c
--- linux-libre-3.1-gnu1/arch/sh/boards/board-secureedge5410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/board-secureedge5410.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,7 @@ static int __init eraseconfig_init(void)
 	printk("SnapGear: EraseConfig init\n");
 
 	/* Setup "EraseConfig" switch on external IRQ 0 */
-	if (request_irq(irq, eraseconfig_interrupt, IRQF_DISABLED,
-				"Erase Config", NULL))
+	if (request_irq(irq, eraseconfig_interrupt, 0, "Erase Config", NULL))
 		printk("SnapGear: failed to register IRQ%d for Reset witch\n",
 				irq);
 	else
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/board-sh7757lcr.c linux-libre-3.2-gnu1/arch/sh/boards/board-sh7757lcr.c
--- linux-libre-3.1-gnu1/arch/sh/boards/board-sh7757lcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/board-sh7757lcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/sh_eth.h>
 #include <cpu/sh7757.h>
-#include <asm/sh_eth.h>
 #include <asm/heartbeat.h>
 
 static struct resource heartbeat_resource = {
@@ -50,9 +50,9 @@ static struct platform_device heartbeat_
 #define GBECONT		0xffc10100
 #define GBECONT_RMII1	BIT(17)
 #define GBECONT_RMII0	BIT(16)
-static void sh7757_eth_set_mdio_gate(unsigned long addr)
+static void sh7757_eth_set_mdio_gate(void *addr)
 {
-	if ((addr & 0x00000fff) < 0x0800)
+	if (((unsigned long)addr & 0x00000fff) < 0x0800)
 		writel(readl(GBECONT) | GBECONT_RMII0, GBECONT);
 	else
 		writel(readl(GBECONT) | GBECONT_RMII1, GBECONT);
@@ -116,9 +116,9 @@ static struct platform_device sh7757_eth
 	},
 };
 
-static void sh7757_eth_giga_set_mdio_gate(unsigned long addr)
+static void sh7757_eth_giga_set_mdio_gate(void *addr)
 {
-	if ((addr & 0x00000fff) < 0x0800) {
+	if (((unsigned long)addr & 0x00000fff) < 0x0800) {
 		gpio_set_value(GPIO_PTT4, 1);
 		writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT);
 	} else {
@@ -210,8 +210,12 @@ static struct resource sh_mmcif_resource
 };
 
 static struct sh_mmcif_dma sh7757lcr_mmcif_dma = {
-	.chan_priv_tx	= SHDMA_SLAVE_MMCIF_TX,
-	.chan_priv_rx	= SHDMA_SLAVE_MMCIF_RX,
+	.chan_priv_tx	= {
+		.slave_id = SHDMA_SLAVE_MMCIF_TX,
+	},
+	.chan_priv_rx	= {
+		.slave_id = SHDMA_SLAVE_MMCIF_RX,
+	}
 };
 
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-ap325rxa/setup.c linux-libre-3.2-gnu1/arch/sh/boards/mach-ap325rxa/setup.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-ap325rxa/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-ap325rxa/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -345,9 +345,10 @@ static struct soc_camera_platform_info c
 		.width = 640,
 		.height = 480,
 	},
-	.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-	SOCAM_DATA_ACTIVE_HIGH,
+	.mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+	V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+	V4L2_MBUS_DATA_ACTIVE_HIGH,
+	.mbus_type = V4L2_MBUS_PARALLEL,
 	.set_capture = camera_set_capture,
 };
 
@@ -501,8 +502,7 @@ static struct i2c_board_info ap325rxa_i2
 };
 
 static struct ov772x_camera_info ov7725_info = {
-	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP | \
-			  OV772X_FLAG_8BIT,
+	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
 	.edgectrl	= OV772X_AUTO_EDGECTRL(0xf, 0),
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-cayman/irq.c linux-libre-3.2-gnu1/arch/sh/boards/mach-cayman/irq.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-cayman/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-cayman/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,13 +46,11 @@ static irqreturn_t cayman_interrupt_pci2
 static struct irqaction cayman_action_smsc = {
 	.name		= "Cayman SMSC Mux",
 	.handler	= cayman_interrupt_smsc,
-	.flags		= IRQF_DISABLED,
 };
 
 static struct irqaction cayman_action_pci2 = {
 	.name		= "Cayman PCI2 Mux",
 	.handler	= cayman_interrupt_pci2,
-	.flags		= IRQF_DISABLED,
 };
 
 static void enable_cayman_irq(struct irq_data *data)
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-ecovec24/setup.c linux-libre-3.2-gnu1/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-ecovec24/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-ecovec24/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,13 +28,13 @@
 #include <linux/spi/mmc_spi.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/sh_eth.h>
 #include <video/sh_mobile_lcdc.h>
 #include <sound/sh_fsi.h>
 #include <media/sh_mobile_ceu.h>
 #include <media/tw9910.h>
 #include <media/mt9t112.h>
 #include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
 #include <asm/clock.h>
 #include <asm/suspend.h>
 #include <cpu/sh7724.h>
@@ -248,6 +248,10 @@ static struct renesas_usbhs_platform_inf
 	.driver_param = {
 		.buswait_bwait		= 4,
 		.detection_delay	= 5,
+		.d0_tx_id = SHDMA_SLAVE_USB1D0_TX,
+		.d0_rx_id = SHDMA_SLAVE_USB1D0_RX,
+		.d1_tx_id = SHDMA_SLAVE_USB1D1_TX,
+		.d1_rx_id = SHDMA_SLAVE_USB1D1_RX,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-hp6xx/hp6xx_apm.c linux-libre-3.2-gnu1/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-hp6xx/hp6xx_apm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-hp6xx/hp6xx_apm.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@ static int __init hp6x0_apm_init(void)
 	int ret;
 
 	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
-			  IRQF_DISABLED, MODNAME, NULL);
+			  0, MODNAME, NULL);
 	if (unlikely(ret < 0)) {
 		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 		       HP680_BTN_IRQ);
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-migor/setup.c linux-libre-3.2-gnu1/arch/sh/boards/mach-migor/setup.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-migor/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-migor/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -448,9 +448,7 @@ static struct i2c_board_info migor_i2c_c
 	},
 };
 
-static struct ov772x_camera_info ov7725_info = {
-	.flags		= OV772X_FLAG_8BIT,
-};
+static struct ov772x_camera_info ov7725_info;
 
 static struct soc_camera_link ov7725_link = {
 	.power		= ov7725_power,
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-se/7724/setup.c linux-libre-3.2-gnu1/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-se/7724/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-se/7724/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,12 +23,12 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/sh_eth.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
 #include <sound/sh_fsi.h>
 #include <asm/io.h>
 #include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
 #include <asm/clock.h>
 #include <asm/suspend.h>
 #include <cpu/sh7724.h>
diff -druNp linux-libre-3.1-gnu1/arch/sh/boards/mach-sh7763rdp/setup.c linux-libre-3.2-gnu1/arch/sh/boards/mach-sh7763rdp/setup.c
--- linux-libre-3.1-gnu1/arch/sh/boards/mach-sh7763rdp/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boards/mach-sh7763rdp/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,8 @@
 #include <linux/mtd/physmap.h>
 #include <linux/fb.h>
 #include <linux/io.h>
+#include <linux/sh_eth.h>
 #include <mach/sh7763rdp.h>
-#include <asm/sh_eth.h>
 #include <asm/sh7760fb.h>
 
 /* NOR Flash */
diff -druNp linux-libre-3.1-gnu1/arch/sh/boot/Makefile linux-libre-3.2-gnu1/arch/sh/boot/Makefile
--- linux-libre-3.1-gnu1/arch/sh/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@ CONFIG_MEMORY_START	?= 0x0c000000
 CONFIG_BOOT_LINK_OFFSET	?= 0x00800000
 CONFIG_ZERO_PAGE_OFFSET	?= 0x00001000
 CONFIG_ENTRY_OFFSET	?= 0x00001000
+CONFIG_PHYSICAL_START	?= $(CONFIG_MEMORY_START)
 
 suffix-y := bin
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
@@ -48,7 +49,7 @@ $(obj)/romimage/vmlinux: $(obj)/zImage F
 	$(Q)$(MAKE) $(build)=$(obj)/romimage $@
 
 KERNEL_MEMORY	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
+		     $$[$(CONFIG_PHYSICAL_START) & 0x1fffffff]')
 
 KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
@@ -114,4 +115,5 @@ $(obj)/uImage: $(obj)/uImage.$(suffix-y)
 	@echo '  Image $@ is ready'
 
 export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
-       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
+       CONFIG_PHYSICAL_START CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET \
+       KERNEL_MEMORY suffix-y
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/dma/dmabrg.c linux-libre-3.2-gnu1/arch/sh/drivers/dma/dmabrg.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/dma/dmabrg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/dma/dmabrg.c	2012-01-04 18:55:44.000000000 -0500
@@ -174,17 +174,17 @@ static int __init dmabrg_init(void)
 	or = __raw_readl(DMAOR);
 	__raw_writel(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
 
-	ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI0, dmabrg_irq, 0,
 			"DMABRG USB address error", NULL);
 	if (ret)
 		goto out0;
 
-	ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI1, dmabrg_irq, 0,
 			"DMABRG Transfer End", NULL);
 	if (ret)
 		goto out1;
 
-	ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI2, dmabrg_irq, 0,
 			"DMABRG Transfer Half", NULL);
 	if (ret == 0)
 		return ret;
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-g2.c linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-g2.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-g2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-g2.c	2012-01-04 18:55:44.000000000 -0500
@@ -170,7 +170,7 @@ static int __init g2_dma_init(void)
 {
 	int ret;
 
-	ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+	ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, 0,
 			  "g2 DMA handler", &g2_dma_info);
 	if (unlikely(ret))
 		return -EINVAL;
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-pvr2.c linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-pvr2.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-pvr2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-pvr2.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,6 @@ static int pvr2_xfer_dma(struct dma_chan
 static struct irqaction pvr2_dma_irq = {
 	.name		= "pvr2 DMA handler",
 	.handler	= pvr2_dma_interrupt,
-	.flags		= IRQF_DISABLED,
 };
 
 static struct dma_ops pvr2_dma_ops = {
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-sh.c linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-sh.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-sh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-sh.c	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@ static int sh_dmac_request_dma(struct dm
 #if defined(CONFIG_SH_DMA_IRQ_MULTI)
 				IRQF_SHARED,
 #else
-				IRQF_DISABLED,
+				0,
 #endif
 				chan->dev_id, chan);
 }
@@ -305,7 +305,7 @@ static int __init sh_dmac_init(void)
 #if defined(CONFIG_SH_DMA_IRQ_MULTI)
 				IRQF_SHARED,
 #else
-				IRQF_DISABLED,
+				0,
 #endif
 				dmae_name[n], (void *)dmae_name[n]);
 		if (unlikely(i < 0)) {
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-sysfs.c linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-sysfs.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/dma/dma-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/dma/dma-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/stat.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci.c linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 
 unsigned long PCIBIOS_MIN_IO = 0x0000;
 unsigned long PCIBIOS_MIN_MEM = 0;
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci-sh5.c linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci-sh5.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci-sh5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci-sh5.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,13 +107,13 @@ static int __init sh5pci_init(void)
 	u32 uval;
 
         if (request_irq(IRQ_ERR, pcish5_err_irq,
-                        IRQF_DISABLED, "PCI Error",NULL) < 0) {
+                        0, "PCI Error",NULL) < 0) {
                 printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
                 return -EINVAL;
         }
 
         if (request_irq(IRQ_SERR, pcish5_serr_irq,
-                        IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
+                        0, "PCI SERR interrupt", NULL) < 0) {
                 printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
                 return -EINVAL;
         }
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci-sh7780.c linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci-sh7780.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/pci/pci-sh7780.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/pci/pci-sh7780.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,7 +172,7 @@ static int __init sh7780_pci_setup_irqs(
 		     PCI_STATUS_SIG_TARGET_ABORT | \
 		     PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
 
-	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED,
+	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0,
 			  "PCI SERR interrupt", hose);
 	if (unlikely(ret)) {
 		printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
diff -druNp linux-libre-3.1-gnu1/arch/sh/drivers/push-switch.c linux-libre-3.2-gnu1/arch/sh/drivers/push-switch.c
--- linux-libre-3.1-gnu1/arch/sh/drivers/push-switch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/drivers/push-switch.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@ static int switch_drv_probe(struct platf
 	BUG_ON(!psw_info);
 
 	ret = request_irq(irq, psw_info->irq_handler,
-			  IRQF_DISABLED | psw_info->irq_flags,
+			  psw_info->irq_flags,
 			  psw_info->name ? psw_info->name : DRV_NAME, pdev);
 	if (unlikely(ret < 0))
 		goto err;
diff -druNp linux-libre-3.1-gnu1/arch/sh/include/asm/page.h linux-libre-3.2-gnu1/arch/sh/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/sh/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,16 @@ typedef struct page *pgtable_t;
 #define __MEMORY_SIZE		CONFIG_MEMORY_SIZE
 
 /*
+ * PHYSICAL_OFFSET is the offset in physical memory where the base
+ * of the kernel is loaded.
+ */
+#ifdef CONFIG_PHYSICAL_START
+#define PHYSICAL_OFFSET (CONFIG_PHYSICAL_START - __MEMORY_START)
+#else
+#define PHYSICAL_OFFSET 0
+#endif
+
+/*
  * PAGE_OFFSET is the virtual address of the start of kernel address
  * space.
  */
@@ -141,8 +151,13 @@ typedef struct page *pgtable_t;
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_UNCACHED_MAPPING
+#if defined(CONFIG_29BIT)
+#define UNCAC_ADDR(addr)	P2SEGADDR(addr)
+#define CAC_ADDR(addr)		P1SEGADDR(addr)
+#else
 #define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + uncached_start)
 #define CAC_ADDR(addr)		((addr) - uncached_start + PAGE_OFFSET)
+#endif
 #else
 #define UNCAC_ADDR(addr)	((addr))
 #define CAC_ADDR(addr)		((addr))
diff -druNp linux-libre-3.1-gnu1/arch/sh/include/asm/sh_eth.h linux-libre-3.2-gnu1/arch/sh/include/asm/sh_eth.h
--- linux-libre-3.1-gnu1/arch/sh/include/asm/sh_eth.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/include/asm/sh_eth.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-#ifndef __ASM_SH_ETH_H__
-#define __ASM_SH_ETH_H__
-
-#include <linux/phy.h>
-
-enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
-enum {
-	SH_ETH_REG_GIGABIT,
-	SH_ETH_REG_FAST_SH4,
-	SH_ETH_REG_FAST_SH3_SH2
-};
-
-struct sh_eth_plat_data {
-	int phy;
-	int edmac_endian;
-	int register_type;
-	phy_interface_t phy_interface;
-	void (*set_mdio_gate)(unsigned long addr);
-
-	unsigned char mac_addr[6];
-	unsigned no_ether_link:1;
-	unsigned ether_link_active_low:1;
-};
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/sh/include/asm/unistd_32.h linux-libre-3.2-gnu1/arch/sh/include/asm/unistd_32.h
--- linux-libre-3.1-gnu1/arch/sh/include/asm/unistd_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/include/asm/unistd_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -375,8 +375,10 @@
 #define __NR_syncfs		362
 #define __NR_sendmmsg		363
 #define __NR_setns		364
+#define __NR_process_vm_readv	365
+#define __NR_process_vm_writev	366
 
-#define NR_syscalls 365
+#define NR_syscalls 367
 
 #ifdef __KERNEL__
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/include/asm/unistd_64.h linux-libre-3.2-gnu1/arch/sh/include/asm/unistd_64.h
--- linux-libre-3.1-gnu1/arch/sh/include/asm/unistd_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/include/asm/unistd_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -396,10 +396,12 @@
 #define __NR_syncfs		373
 #define __NR_sendmmsg		374
 #define __NR_setns		375
+#define __NR_process_vm_readv	376
+#define __NR_process_vm_writev	377
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 376
+#define NR_syscalls 378
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druNp linux-libre-3.1-gnu1/arch/sh/Kconfig linux-libre-3.2-gnu1/arch/sh/Kconfig
--- linux-libre-3.1-gnu1/arch/sh/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -101,10 +101,6 @@ config GENERIC_LOCKBREAK
 	def_bool y
 	depends on SMP && PREEMPT
 
-config SYS_SUPPORTS_PM
-	bool
-	depends on !SMP
-
 config ARCH_SUSPEND_POSSIBLE
 	def_bool n
 
@@ -649,7 +645,7 @@ config CRASH_DUMP
 	  a specially reserved region and then later executed after
 	  a crash by kdump/kexec. The crash dump kernel must be compiled
 	  to a memory address not used by the main kernel using
-	  MEMORY_START.
+	  PHYSICAL_START.
 
 	  For more details see Documentation/kdump/kdump.txt
 
@@ -660,6 +656,17 @@ config KEXEC_JUMP
 	  Jump between original kernel and kexeced kernel and invoke
 	  code via KEXEC
 
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
+	default MEMORY_START
+	---help---
+	  This gives the physical address where the kernel is loaded
+	  and is ordinarily the same as MEMORY_START.
+
+	  Different values are primarily used in the case of kexec on panic
+	  where the fail safe kernel needs to run at a different address
+	  than the panic-ed kernel.
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,10 +176,12 @@ static DECLARE_INTC_DESC(intc_desc, "sh7
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xfffe8000,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 192, 192, 192, 192 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -193,10 +195,12 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xfffe8800,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 196, 196, 196, 196 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -210,10 +214,12 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfffe9000,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 200, 200, 200, 200 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -227,10 +233,12 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xfffe9800,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 204, 204, 204, 204 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,7 +113,14 @@ static struct clk_lookup lookups[] = {
 
 	/* MSTP32 clocks */
 	CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
-	CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic3", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic4", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic5", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic6", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic7", &mstp_clks[MSTP000]),
 
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]),
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]),
@@ -121,6 +128,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
 
+	CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
 	CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh4a/smp-shx3.c linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh4a/smp-shx3.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@ static void shx3_prepare_cpus(unsigned i
 
 	for (i = 0; i < SMP_MSG_NR; i++)
 		request_irq(104 + i, ipi_interrupt_handler,
-			    IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i);
+			    IRQF_PERCPU, "IPI", (void *)(long)i);
 
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c linux-libre-3.2-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 #include <asm/suspend.h>
 #include <asm/uaccess.h>
 #include <asm/hwblk.h>
@@ -25,11 +26,12 @@ static unsigned long cpuidle_mode[] = {
 };
 
 static int cpuidle_sleep_enter(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+				int index)
 {
 	unsigned long allowed_mode = arch_hwblk_sleep_mode();
 	ktime_t before, after;
-	int requested_state = state - &dev->states[0];
+	int requested_state = index;
 	int allowed_state;
 	int k;
 
@@ -46,11 +48,13 @@ static int cpuidle_sleep_enter(struct cp
 	 */
 	k = min_t(int, allowed_state, requested_state);
 
-	dev->last_state = &dev->states[k];
 	before = ktime_get();
 	sh_mobile_call_standby(cpuidle_mode[k]);
 	after = ktime_get();
-	return ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	return k;
 }
 
 static struct cpuidle_device cpuidle_dev;
@@ -62,19 +66,19 @@ static struct cpuidle_driver cpuidle_dri
 void sh_mobile_setup_cpuidle(void)
 {
 	struct cpuidle_device *dev = &cpuidle_dev;
+	struct cpuidle_driver *drv = &cpuidle_driver;
 	struct cpuidle_state *state;
 	int i;
 
-	cpuidle_register_driver(&cpuidle_driver);
 
 	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
+		drv->states[i].name[0] = '\0';
+		drv->states[i].desc[0] = '\0';
 	}
 
 	i = CPUIDLE_DRIVER_STATE_START;
 
-	state = &dev->states[i++];
+	state = &drv->states[i++];
 	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
 	strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 1;
@@ -84,10 +88,10 @@ void sh_mobile_setup_cpuidle(void)
 	state->flags |= CPUIDLE_FLAG_TIME_VALID;
 	state->enter = cpuidle_sleep_enter;
 
-	dev->safe_state = state;
+	drv->safe_state_index = i-1;
 
 	if (sh_mobile_sleep_supported & SUSP_SH_SF) {
-		state = &dev->states[i++];
+		state = &drv->states[i++];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 		strncpy(state->desc, "SuperH Sleep Mode [SF]",
 			CPUIDLE_DESC_LEN);
@@ -100,7 +104,7 @@ void sh_mobile_setup_cpuidle(void)
 	}
 
 	if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
-		state = &dev->states[i++];
+		state = &drv->states[i++];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
 		strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
 			CPUIDLE_DESC_LEN);
@@ -112,7 +116,10 @@ void sh_mobile_setup_cpuidle(void)
 		state->enter = cpuidle_sleep_enter;
 	}
 
+	drv->state_count = i;
 	dev->state_count = i;
 
+	cpuidle_register_driver(&cpuidle_driver);
+
 	cpuidle_register_device(dev);
 }
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/perf_event.c linux-libre-3.2-gnu1/arch/sh/kernel/perf_event.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/perf_event.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 
 struct cpu_hw_events {
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/setup.c linux-libre-3.2-gnu1/arch/sh/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -211,13 +211,16 @@ void __init __add_active_range(unsigned
 	}
 
 	/*
-	 *  We don't know which RAM region contains kernel data,
-	 *  so we try it repeatedly and let the resource manager
-	 *  test it.
+	 * We don't know which RAM region contains kernel data or
+	 * the reserved crashkernel region, so try it repeatedly
+	 * and let the resource manager test it.
 	 */
 	request_resource(res, &code_resource);
 	request_resource(res, &data_resource);
 	request_resource(res, &bss_resource);
+#ifdef CONFIG_KEXEC
+	request_resource(res, &crashk_res);
+#endif
 
 	/*
 	 * Also make sure that there is a PMB mapping that covers this
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/syscalls_32.S linux-libre-3.2-gnu1/arch/sh/kernel/syscalls_32.S
--- linux-libre-3.1-gnu1/arch/sh/kernel/syscalls_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/syscalls_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -382,3 +382,5 @@ ENTRY(sys_call_table)
 	.long sys_syncfs
 	.long sys_sendmmsg
 	.long sys_setns
+	.long sys_process_vm_readv	/* 365 */
+	.long sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/syscalls_64.S linux-libre-3.2-gnu1/arch/sh/kernel/syscalls_64.S
--- linux-libre-3.1-gnu1/arch/sh/kernel/syscalls_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/syscalls_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -402,3 +402,5 @@ sys_call_table:
 	.long sys_syncfs
 	.long sys_sendmmsg
 	.long sys_setns			/* 375 */
+	.long sys_process_vm_readv
+	.long sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/topology.c linux-libre-3.2-gnu1/arch/sh/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/sh/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,8 +11,10 @@
 #include <linux/cpumask.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
+#include <linux/topology.h>
 #include <linux/node.h>
 #include <linux/nodemask.h>
+#include <linux/export.h>
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/kernel/vmlinux.lds.S linux-libre-3.2-gnu1/arch/sh/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu1/arch/sh/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@ OUTPUT_ARCH(sh)
 ENTRY(_start)
 SECTIONS
 {
-	. = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
+	. = PAGE_OFFSET + MEMORY_OFFSET + PHYSICAL_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
 
 	_text = .;		/* Text and read-only data */
 
diff -druNp linux-libre-3.1-gnu1/arch/sh/Makefile linux-libre-3.2-gnu1/arch/sh/Makefile
--- linux-libre-3.1-gnu1/arch/sh/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@ defaultimage-$(CONFIG_SH_RSK)			:= uImag
 defaultimage-$(CONFIG_SH_URQUELL)		:= uImage
 defaultimage-$(CONFIG_SH_MIGOR)			:= uImage
 defaultimage-$(CONFIG_SH_AP325RXA)		:= uImage
+defaultimage-$(CONFIG_SH_SH7757LCR)		:= uImage
 defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE)	:= uImage
 defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= vmlinux
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= vmlinux
diff -druNp linux-libre-3.1-gnu1/arch/sh/mm/init.c linux-libre-3.2-gnu1/arch/sh/mm/init.c
--- linux-libre-3.1-gnu1/arch/sh/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/memblock.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <asm/mmu_context.h>
 #include <asm/mmzone.h>
 #include <asm/kexec.h>
@@ -287,6 +288,8 @@ static void __init do_init_bootmem(void)
 static void __init early_reserve_mem(void)
 {
 	unsigned long start_pfn;
+	u32 zero_base = (u32)__MEMORY_START + (u32)PHYSICAL_OFFSET;
+	u32 start = zero_base + (u32)CONFIG_ZERO_PAGE_OFFSET;
 
 	/*
 	 * Partially used pages are not usable - thus
@@ -300,15 +303,13 @@ static void __init early_reserve_mem(voi
 	 * this catches the (definitely buggy) case of us accidentally
 	 * initializing the bootmem allocator with an invalid RAM area.
 	 */
-	memblock_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
-		    (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
-		    (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+	memblock_reserve(start, (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - start);
 
 	/*
 	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
 	 */
 	if (CONFIG_ZERO_PAGE_OFFSET != 0)
-		memblock_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+		memblock_reserve(zero_base, CONFIG_ZERO_PAGE_OFFSET);
 
 	/*
 	 * Handle additional early reservations
diff -druNp linux-libre-3.1-gnu1/arch/sh/oprofile/common.c linux-libre-3.2-gnu1/arch/sh/oprofile/common.c
--- linux-libre-3.1-gnu1/arch/sh/oprofile/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sh/oprofile/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,7 @@ int __init oprofile_arch_init(struct opr
 	return oprofile_perf_init(ops);
 }
 
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
 {
 	oprofile_perf_exit();
 	kfree(sh_pmu_op_name);
@@ -60,5 +60,5 @@ int __init oprofile_arch_init(struct opr
 	ops->backtrace = sh_backtrace;
 	return -ENODEV;
 }
-void __exit oprofile_arch_exit(void) {}
+void oprofile_arch_exit(void) {}
 #endif /* CONFIG_HW_PERF_EVENTS */
diff -druNp linux-libre-3.1-gnu1/arch/sparc/include/asm/compat.h linux-libre-3.2-gnu1/arch/sparc/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/sparc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -134,7 +134,8 @@ struct compat_statfs {
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_INFINITY 0x7fffffff
diff -druNp linux-libre-3.1-gnu1/arch/sparc/include/asm/pgtable_32.h linux-libre-3.2-gnu1/arch/sparc/include/asm/pgtable_32.h
--- linux-libre-3.1-gnu1/arch/sparc/include/asm/pgtable_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/include/asm/pgtable_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_b
 #define kern_addr_valid(addr) \
 	(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
-			      unsigned long from, unsigned long pfn,
-			      unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_
 #define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)			(pfn & 0x0fffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+			   unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+				     unsigned long from, unsigned long pfn,
+				     unsigned long size, pgprot_t prot)
+{
+	unsigned long long offset, space, phys_base;
+
+	offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+	space = GET_IOSPACE(pfn);
+	phys_base = offset | (space << 32ULL);
+
+	return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
 ({									  \
diff -druNp linux-libre-3.1-gnu1/arch/sparc/include/asm/pgtable_64.h linux-libre-3.2-gnu1/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-3.1-gnu1/arch/sparc/include/asm/pgtable_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/include/asm/pgtable_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsig
 
 extern int page_in_phys_avail(unsigned long paddr);
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-			       unsigned long pfn,
-			       unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_
 #define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)			(pfn & 0x0fffffffffffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+			   unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+				     unsigned long from, unsigned long pfn,
+				     unsigned long size, pgprot_t prot)
+{
+	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+	int space = GET_IOSPACE(pfn);
+	unsigned long phys_base;
+
+	phys_base = offset | (((unsigned long) space) << 32UL);
+
+	return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
diff -druNp linux-libre-3.1-gnu1/arch/sparc/include/asm/termios.h linux-libre-3.2-gnu1/arch/sparc/include/asm/termios.h
--- linux-libre-3.1-gnu1/arch/sparc/include/asm/termios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/include/asm/termios.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,6 @@ struct winsize {
 };
 
 #ifdef __KERNEL__
-#include <linux/module.h>
 
 /*
  * c_cc characters in the termio structure.  Oh, how I love being
diff -druNp linux-libre-3.1-gnu1/arch/sparc/include/asm/unistd.h linux-libre-3.2-gnu1/arch/sparc/include/asm/unistd.h
--- linux-libre-3.1-gnu1/arch/sparc/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -406,8 +406,10 @@
 #define __NR_syncfs		335
 #define __NR_sendmmsg		336
 #define __NR_setns		337
+#define __NR_process_vm_readv	338
+#define __NR_process_vm_writev	339
 
-#define NR_syscalls		338
+#define NR_syscalls		340
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff -druNp linux-libre-3.1-gnu1/arch/sparc/Kconfig linux-libre-3.2-gnu1/arch/sparc/Kconfig
--- linux-libre-3.1-gnu1/arch/sparc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -560,12 +560,7 @@ config SUN_OPENPROMFS
 	  Only choose N if you know in advance that you will not need to modify
 	  OpenPROM settings on the running system.
 
-# Makefile helpers
-config SPARC32_PCI
-	bool
-	default y
-	depends on SPARC32 && PCI
-
+# Makefile helper
 config SPARC64_PCI
 	bool
 	default y
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/apc.c linux-libre-3.2-gnu1/arch/sparc/kernel/apc.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/apc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/apc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/oplib.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/auxio_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/auxio_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/auxio_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/auxio_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/export.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/auxio.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/btext.c linux-libre-3.2-gnu1/arch/sparc/kernel/btext.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/btext.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/btext.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/console.h>
 
 #include <asm/btext.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/central.c linux-libre-3.2-gnu1/arch/sparc/kernel/central.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/central.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/central.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/of_device.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/cpu.c linux-libre-3.2-gnu1/arch/sparc/kernel/cpu.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/cpumap.c linux-libre-3.2-gnu1/arch/sparc/kernel/cpumap.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/cpumap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/cpumap.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2009 Hong H. Pham <hong.pham@windriver.com>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/dma.c linux-libre-3.2-gnu1/arch/sparc/kernel/dma.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-debug.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/ds.c linux-libre-3.2-gnu1/arch/sparc/kernel/ds.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -1181,13 +1181,11 @@ static int __devinit ds_probe(struct vio
 
 	dp->rcv_buf_len = 4096;
 
-	dp->ds_states = kzalloc(sizeof(ds_states_template),
-				GFP_KERNEL);
+	dp->ds_states = kmemdup(ds_states_template,
+				sizeof(ds_states_template), GFP_KERNEL);
 	if (!dp->ds_states)
 		goto out_free_rcv_buf;
 
-	memcpy(dp->ds_states, ds_states_template,
-	       sizeof(ds_states_template));
 	dp->num_ds_states = ARRAY_SIZE(ds_states_template);
 
 	for (i = 0; i < dp->num_ds_states; i++)
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/ebus.c linux-libre-3.2-gnu1/arch/sparc/kernel/ebus.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/ebus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/ebus.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  * Copyright (C) 1999  David S. Miller (davem@redhat.com)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/entry.h linux-libre-3.2-gnu1/arch/sparc/kernel/entry.h
--- linux-libre-3.1-gnu1/arch/sparc/kernel/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 #else /* CONFIG_SPARC32 */
+
+#include <asm/trap_block.h>
+
 struct popc_3insn_patch_entry {
 	unsigned int	addr;
 	unsigned int	insns[3];
@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __p
 	__popc_6insn_patch_end;
 
 extern void __init per_cpu_patch(void);
+extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
+				    struct sun4v_1insn_patch_entry *);
+extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+				    struct sun4v_2insn_patch_entry *);
 extern void __init sun4v_patch(void);
 extern void __init boot_cpu_id_too_large(int cpu);
 extern unsigned int dcache_parity_tl1_occurred;
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/hvapi.c linux-libre-3.2-gnu1/arch/sparc/kernel/hvapi.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/hvapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/hvapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 
 #include <asm/hypervisor.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/idprom.c linux-libre-3.2-gnu1/arch/sparc/kernel/idprom.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/idprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/idprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/oplib.h>
 #include <asm/idprom.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/iommu.c linux-libre-3.2-gnu1/arch/sparc/kernel/iommu.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/irq_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/irq_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/irq_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/irq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cpudata.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/irq_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/irq_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/irq_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/irq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  * Copyright (C) 1998  Jakub Jelinek    (jj@ultra.linux.cz)
  */
 
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/linkage.h>
 #include <linux/ptrace.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/jump_label.c linux-libre-3.2-gnu1/arch/sparc/kernel/jump_label.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,12 +36,4 @@ void arch_jump_label_transform(struct ju
 	put_online_cpus();
 }
 
-void arch_jump_label_text_poke_early(jump_label_t addr)
-{
-	u32 *insn_p = (u32 *) (unsigned long) addr;
-
-	*insn_p = 0x01000000;
-	flushi(insn_p);
-}
-
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/ldc.c linux-libre-3.2-gnu1/arch/sparc/kernel/ldc.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/ldc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/ldc.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/leon_kernel.c linux-libre-3.2-gnu1/arch/sparc/kernel/leon_kernel.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/leon_kernel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/leon_kernel.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/leon_pci.c linux-libre-3.2-gnu1/arch/sparc/kernel/leon_pci.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/leon_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/leon_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/of_device.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/leon.h>
 #include <asm/leon_pci.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/leon_pci_grpci2.c linux-libre-3.2-gnu1/arch/sparc/kernel/leon_pci_grpci2.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/leon_pci_grpci2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/leon_pci_grpci2.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/leon.h>
 #include <asm/vaddrs.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/mdesc.c linux-libre-3.2-gnu1/arch/sparc/kernel/mdesc.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/mdesc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/mdesc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,11 +11,13 @@
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 
 #include <asm/cpudata.h>
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
 #include <asm/prom.h>
+#include <asm/uaccess.h>
 #include <asm/oplib.h>
 #include <asm/smp.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/module.c linux-libre-3.2-gnu1/arch/sparc/kernel/module.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <asm/processor.h>
 #include <asm/spitfire.h>
 
+#include "entry.h"
+
 #ifdef CONFIG_SPARC64
 
 #include <linux/jump_label.h>
@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs
 }
 
 #ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+			      const Elf_Shdr *sechdrs)
+{
+	const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+		if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+			sun4v_1insn = s;
+		if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+			sun4v_2insn = s;
+	}
+
+	if (sun4v_1insn && tlb_type == hypervisor) {
+		void *p = (void *) sun4v_1insn->sh_addr;
+		sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+	}
+	if (sun4v_2insn && tlb_type == hypervisor) {
+		void *p = (void *) sun4v_2insn->sh_addr;
+		sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+	}
+}
+
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
 	/* make jump label nops */
 	jump_label_apply_nops(me);
 
+	do_patch_sections(hdr, sechdrs);
+
 	/* Cheetah's I-cache is fully coherent.  */
 	if (tlb_type == spitfire) {
 		unsigned long va;
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/nmi.c linux-libre-3.2-gnu1/arch/sparc/kernel/nmi.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/nmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/nmi.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kprobes.h>
 #include <linux/kernel_stat.h>
 #include <linux/reboot.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,13 +2,14 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <asm/spitfire.h>
 
 #include "of_device_common.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_common.c linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_common.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/of_device_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/of_device_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * with minor modifications, see there for credits.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pcic.c linux-libre-3.2-gnu1/arch/sparc/kernel/pcic.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pcic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pcic.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 
 #include <asm/irq.h>
 #include <asm/oplib.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci_fire.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci_fire.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci_fire.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci_fire.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 #include <linux/of_device.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci_psycho.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci_psycho.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci_psycho.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci_psycho.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci_sabre.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci_sabre.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci_sabre.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci_sabre.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci_schizo.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci_schizo.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci_schizo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci_schizo.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pci_sun4v.c linux-libre-3.2-gnu1/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pci_sun4v.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pci_sun4v.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/percpu.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/log2.h>
 #include <linux/of_device.h>
 
@@ -848,10 +849,10 @@ static int pci_sun4v_msiq_build_irq(stru
 	if (!irq)
 		return -ENOMEM;
 
-	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
-		return -EINVAL;
 	if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
 		return -EINVAL;
+	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+		return -EINVAL;
 
 	return irq;
 }
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pcr.c linux-libre-3.2-gnu1/arch/sparc/kernel/pcr.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 
@@ -13,6 +13,7 @@
 #include <asm/pil.h>
 #include <asm/pcr.h>
 #include <asm/nmi.h>
+#include <asm/spitfire.h>
 
 /* This code is shared between various users of the performance
  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/pmc.c linux-libre-3.2-gnu1/arch/sparc/kernel/pmc.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/oplib.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/power.c linux-libre-3.2-gnu1/arch/sparc/kernel/power.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/power.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/process_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/process_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/process_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/process_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 #include <stdarg.h>
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/prom_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/prom_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/prom_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/prom_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
-#include <linux/module.h>
 
 #include <asm/prom.h>
 #include <asm/oplib.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/prom_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/prom_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/prom_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/prom_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/prom_common.c linux-libre-3.2-gnu1/arch/sparc/kernel/prom_common.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/prom_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/prom_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -58,12 +58,10 @@ int of_set_property(struct device_node *
 	void *new_val;
 	int err;
 
-	new_val = kmalloc(len, GFP_KERNEL);
+	new_val = kmemdup(val, len, GFP_KERNEL);
 	if (!new_val)
 		return -ENOMEM;
 
-	memcpy(new_val, val, len);
-
 	err = -ENODEV;
 
 	mutex_lock(&of_set_property_mutex);
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/reboot.c linux-libre-3.2-gnu1/arch/sparc/kernel/reboot.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/reboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/reboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/reboot.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 
 #include <asm/system.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/sbus.c linux-libre-3.2-gnu1/arch/sparc/kernel/sbus.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/sbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/sbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/setup_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/setup_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/setup_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/setup_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/setup_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/setup_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/setup_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/setup_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
 	}
 }
 
-void __init sun4v_patch(void)
+void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
+			     struct sun4v_1insn_patch_entry *end)
 {
-	extern void sun4v_hvapi_init(void);
-	struct sun4v_1insn_patch_entry *p1;
-	struct sun4v_2insn_patch_entry *p2;
-
-	if (tlb_type != hypervisor)
-		return;
-
-	p1 = &__sun4v_1insn_patch;
-	while (p1 < &__sun4v_1insn_patch_end) {
-		unsigned long addr = p1->addr;
+	while (start < end) {
+		unsigned long addr = start->addr;
 
-		*(unsigned int *) (addr +  0) = p1->insn;
+		*(unsigned int *) (addr +  0) = start->insn;
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  0));
 
-		p1++;
+		start++;
 	}
+}
 
-	p2 = &__sun4v_2insn_patch;
-	while (p2 < &__sun4v_2insn_patch_end) {
-		unsigned long addr = p2->addr;
+void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+			     struct sun4v_2insn_patch_entry *end)
+{
+	while (start < end) {
+		unsigned long addr = start->addr;
 
-		*(unsigned int *) (addr +  0) = p2->insns[0];
+		*(unsigned int *) (addr +  0) = start->insns[0];
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  0));
 
-		*(unsigned int *) (addr +  4) = p2->insns[1];
+		*(unsigned int *) (addr +  4) = start->insns[1];
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  4));
 
-		p2++;
+		start++;
 	}
+}
+
+void __init sun4v_patch(void)
+{
+	extern void sun4v_hvapi_init(void);
+
+	if (tlb_type != hypervisor)
+		return;
+
+	sun4v_patch_1insn_range(&__sun4v_1insn_patch,
+				&__sun4v_1insn_patch_end);
+
+	sun4v_patch_2insn_range(&__sun4v_2insn_patch,
+				&__sun4v_2insn_patch_end);
 
 	sun4v_hvapi_init();
 }
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/signal_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/signal_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/signal_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/signal_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -519,10 +519,26 @@ static void do_signal(struct pt_regs *re
 	siginfo_t info;
 	int signr;
 
+	/* It's a lot of work and synchronization to add a new ptrace
+	 * register for GDB to save and restore in order to get
+	 * orig_i0 correct for syscall restarts when debugging.
+	 *
+	 * Although it should be the case that most of the global
+	 * registers are volatile across a system call, glibc already
+	 * depends upon that fact that we preserve them.  So we can't
+	 * just use any global register to save away the orig_i0 value.
+	 *
+	 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+	 * preserved across a system call trap by various pieces of
+	 * code in glibc.
+	 *
+	 * %g7 is used as the "thread register".   %g6 is not used in
+	 * any fixed manner.  %g6 is used as a scratch register and
+	 * a compiler temporary, but it's value is never used across
+	 * a system call.  Therefore %g6 is usable for orig_i0 storage.
+	 */
 	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
-		restart_syscall = 1;
-	else
-		restart_syscall = 0;
+		regs->u_regs[UREG_G6] = orig_i0;
 
 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
 		oldset = &current->saved_sigmask;
@@ -535,8 +551,12 @@ static void do_signal(struct pt_regs *re
 	 * the software "in syscall" bit, directing us to not perform
 	 * a syscall restart.
 	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
+
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/signal32.c linux-libre-3.2-gnu1/arch/sparc/kernel/signal32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/signal32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/signal32.c	2012-01-04 18:55:44.000000000 -0500
@@ -822,21 +822,23 @@ static inline void syscall_restart32(uns
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
-		 int restart_syscall, unsigned long orig_i0)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs)
 {
 	struct k_sigaction ka;
+	unsigned long orig_i0;
+	int restart_syscall;
 	siginfo_t info;
 	int signr;
 	
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* If the debugger messes with the program counter, it clears
-	 * the "in syscall" bit, directing us to not perform a syscall
-	 * restart.
-	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	orig_i0 = 0;
+	if (pt_regs_is_syscall(regs) &&
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/signal_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/signal_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/signal_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/signal_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *re
 	siginfo_t info;
 	int signr;
 	
+	/* It's a lot of work and synchronization to add a new ptrace
+	 * register for GDB to save and restore in order to get
+	 * orig_i0 correct for syscall restarts when debugging.
+	 *
+	 * Although it should be the case that most of the global
+	 * registers are volatile across a system call, glibc already
+	 * depends upon that fact that we preserve them.  So we can't
+	 * just use any global register to save away the orig_i0 value.
+	 *
+	 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+	 * preserved across a system call trap by various pieces of
+	 * code in glibc.
+	 *
+	 * %g7 is used as the "thread register".   %g6 is not used in
+	 * any fixed manner.  %g6 is used as a scratch register and
+	 * a compiler temporary, but it's value is never used across
+	 * a system call.  Therefore %g6 is usable for orig_i0 storage.
+	 */
 	if (pt_regs_is_syscall(regs) &&
-	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
-		restart_syscall = 1;
-	} else
-		restart_syscall = 0;
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+		regs->u_regs[UREG_G6] = orig_i0;
 
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 		oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *re
 
 #ifdef CONFIG_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
-		extern void do_signal32(sigset_t *, struct pt_regs *,
-					int restart_syscall,
-					unsigned long orig_i0);
-		do_signal32(oldset, regs, restart_syscall, orig_i0);
+		extern void do_signal32(sigset_t *, struct pt_regs *);
+		do_signal32(oldset, regs);
 		return;
 	}
 #endif	
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* If the debugger messes with the program counter, it clears
-	 * the software "in syscall" bit, directing us to not perform
-	 * a syscall restart.
-	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	if (pt_regs_is_syscall(regs) &&
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/sigutil_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/sigutil_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/sigutil_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/sigutil_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
+#include <linux/errno.h>
 
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/smp_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/smp_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/smp_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/smp_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/sparc_ksyms_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/sparc_ksyms_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/sparc_ksyms_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/sparc_ksyms_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/stacktrace.c linux-libre-3.2-gnu1/arch/sparc/kernel/stacktrace.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
 #include <linux/ftrace.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/sys_sparc32.c linux-libre-3.2-gnu1/arch/sparc/kernel/sys_sparc32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/sys_sparc32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/sys_sparc32.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/uio.h>
 #include <linux/nfs_fs.h>
 #include <linux/quota.h>
-#include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/sys_sparc_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/sys_sparc_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/sys_sparc_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/sys_sparc_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/ipc.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/uaccess.h>
 #include <asm/utrap.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/systbls_32.S linux-libre-3.2-gnu1/arch/sparc/kernel/systbls_32.S
--- linux-libre-3.1-gnu1/arch/sparc/kernel/systbls_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/systbls_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -84,4 +84,4 @@ sys_call_table:
 /*320*/	.long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-/*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns
+/*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/systbls_64.S linux-libre-3.2-gnu1/arch/sparc/kernel/systbls_64.S
--- linux-libre-3.1-gnu1/arch/sparc/kernel/systbls_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/systbls_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -85,7 +85,7 @@ sys_call_table32:
 /*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
 	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
-	.word sys_syncfs, compat_sys_sendmmsg, sys_setns
+	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 
 #endif /* CONFIG_COMPAT */
 
@@ -162,4 +162,4 @@ sys_call_table:
 /*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-	.word sys_syncfs, sys_sendmmsg, sys_setns
+	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/time_64.c linux-libre-3.2-gnu1/arch/sparc/kernel/time_64.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/time_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/time_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/traps_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/traps_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/traps_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/traps_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 
 #include <asm/delay.h>
 #include <asm/system.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/unaligned_32.c linux-libre-3.2-gnu1/arch/sparc/kernel/unaligned_32.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/unaligned_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/unaligned_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/system.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/vio.c linux-libre-3.2-gnu1/arch/sparc/kernel/vio.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <linux/export.h>
 #include <linux/init.h>
 
 #include <asm/mdesc.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/viohs.c linux-libre-3.2-gnu1/arch/sparc/kernel/viohs.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/viohs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/viohs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/kernel/visemul.c linux-libre-3.2-gnu1/arch/sparc/kernel/visemul.c
--- linux-libre-3.1-gnu1/arch/sparc/kernel/visemul.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/kernel/visemul.c	2012-01-04 18:55:44.000000000 -0500
@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, u
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a > b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPGT32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a > b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, u
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a <= b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPLE32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a <= b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, u
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a != b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPNE32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a != b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, u
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a == b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPEQ32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a == b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/sparc/lib/memcpy.S linux-libre-3.2-gnu1/arch/sparc/lib/memcpy.S
--- linux-libre-3.1-gnu1/arch/sparc/lib/memcpy.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/lib/memcpy.S	2012-01-04 18:55:44.000000000 -0500
@@ -7,40 +7,12 @@
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#ifdef __KERNEL__
-
-#define FUNC(x) 											\
+#define FUNC(x) 		\
 	.globl	x;		\
 	.type	x,@function;	\
-	.align	4;											\
+	.align	4;		\
 x:
 
-#undef FASTER_REVERSE
-#undef FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-/* In kernel these functions don't return a value.
- * One should use macros in asm/string.h for that purpose.
- * We return 0, so that bugs are more apparent.
- */
-#define SETUP_RETL
-#define RETL_INSN	clr	%o0
-
-#else
-
-/* libc */
-
-#include "DEFS.h"
-
-#define FASTER_REVERSE
-#define FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-#define SETUP_RETL	mov	%o0, %g6
-#define RETL_INSN	mov	%g6, %o0
-
-#endif
-
 /* Both these macros have to start with exactly the same insn */
 #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
 	ldd	[%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@ x:
 	.text
 	.align	4
 
-#ifdef FASTER_REVERSE
-
-70:	/* rdword_align */
-
-	andcc		%o1, 1, %g0
-	be		4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1 - 1], %g2
-	sub		%o1, 1, %o1
-	stb		%g2, [%o0 - 1]
-	sub		%o2, 1, %o2
-	be		3f
-	 sub		%o0, 1, %o0
-4:
-	lduh		[%o1 - 2], %g2
-	sub		%o1, 2, %o1
-	sth		%g2, [%o0 - 2]
-	sub		%o2, 2, %o2
-	b		3f
-	 sub		%o0, 2, %o0
-
-#endif /* FASTER_REVERSE */
-
 0:
 	retl
 	 nop		! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@ FUNC(__memmove)
 #endif
 FUNC(memmove)
 	cmp		%o0, %o1
-	SETUP_RETL
+	mov		%o0, %g7
 	bleu		9f
 	 sub		%o0, %o1, %o4
 
@@ -207,8 +155,6 @@ FUNC(memmove)
 	bleu		0f
 	 andcc		%o4, 3, %o5
 
-#ifndef FASTER_REVERSE
-
 	add		%o1, %o2, %o1
 	add		%o0, %o2, %o0
 	sub		%o1, 1, %o1
@@ -224,295 +170,7 @@ FUNC(memmove)
 	 sub		%o0, 1, %o0
 
 	retl
-	 RETL_INSN
-
-#else /* FASTER_REVERSE */
-
-	add		%o1, %o2, %o1
-	add		%o0, %o2, %o0
-	bne		77f
-	 cmp		%o2, 15
-	bleu		91f
-	 andcc		%o1, 3, %g0
-	bne		70b
-3:
-	 andcc		%o1, 4, %g0
-
-	be		2f
-	 mov		%o2, %g1
-
-	ld		[%o1 - 4], %o4
-	sub		%g1, 4, %g1
-	st		%o4, [%o0 - 4]
-	sub		%o1, 4, %o1
-	sub		%o0, 4, %o0
-2:
-	andcc		%g1, 0xffffff80, %g7
-	be		3f
-	 andcc		%o0, 4, %g0
-
-	be		74f + 4
-5:
-	RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	sub		%o1, 128, %o1
-	bne		5b
-	 sub		%o0, 128, %o0
-3:
-	andcc		%g1, 0x70, %g7
-	be		72f
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(72f), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	sub		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(72f), %g0
-	 sub		%o0, %g7, %o0
-
-71:	/* rmemcpy_table */
-	RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-
-72:	/* rmemcpy_table_end */
-
-	be		73f
-	 andcc		%g1, 4, %g0
-
-	ldd		[%o1 - 0x08], %g2
-	sub		%o0, 8, %o0
-	sub		%o1, 8, %o1
-	st		%g2, [%o0]
-	st		%g3, [%o0 + 0x04]
-
-73:	/* rmemcpy_last7 */
-
-	be		1f
-	 andcc		%g1, 2, %g0
-
-	ld		[%o1 - 4], %g2
-	sub		%o1, 4, %o1
-	st		%g2, [%o0 - 4]
-	sub		%o0, 4, %o0
-1:
-	be		1f
-	 andcc		%g1, 1, %g0
-
-	lduh		[%o1 - 2], %g2
-	sub		%o1, 2, %o1
-	sth		%g2, [%o0 - 2]
-	sub		%o0, 2, %o0
-1:
-	be		1f
-	 nop
-
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 - 1]
-1:
-	retl
- 	 RETL_INSN
-
-74:	/* rldd_std */
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	sub		%o1, 128, %o1
-	bne		74b
-	 sub		%o0, 128, %o0
-
-	andcc		%g1, 0x70, %g7
-	be		72b
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(72b), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	sub		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(72b), %g0
-	 sub		%o0, %g7, %o0
-
-75:	/* rshort_end */
-
-	and		%o2, 0xe, %o3
-2:
-	sethi		%hi(76f), %o5
-	sll		%o3, 3, %o4
-	sub		%o0, %o3, %o0
-	sub		%o5, %o4, %o5
-	sub		%o1, %o3, %o1
-	jmpl		%o5 + %lo(76f), %g0
-	 andcc		%o2, 1, %g0
-
-	RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-
-76:	/* rshort_table_end */
-
-	be		1f
-	 nop
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 - 1]
-1:
-	retl
- 	 RETL_INSN
-
-91:	/* rshort_aligned_end */
-
-	bne		75b
-	 andcc		%o2, 8, %g0
-
-	be		1f
-	 andcc		%o2, 4, %g0
-
-	ld		[%o1 - 0x08], %g2
-	ld		[%o1 - 0x04], %g3
-	sub		%o1, 8, %o1
-	st		%g2, [%o0 - 0x08]
-	st		%g3, [%o0 - 0x04]
-	sub		%o0, 8, %o0
-1:
-	b		73b
-	 mov		%o2, %g1
-
-77:	/* rnon_aligned */
-	cmp		%o2, 15
-	bleu		75b
-	 andcc		%o0, 3, %g0
-	be		64f
-	 andcc		%o0, 1, %g0
-	be		63f
-	 andcc		%o0, 2, %g0
-	ldub		[%o1 - 1], %g5
-	sub		%o1, 1, %o1
-	stb		%g5, [%o0 - 1]
-	sub		%o0, 1, %o0
-	be		64f
-	 sub		%o2, 1, %o2
-63:
-	ldub		[%o1 - 1], %g5
-	sub		%o1, 2, %o1
-	stb		%g5, [%o0 - 1]
-	sub		%o0, 2, %o0
-	ldub		[%o1], %g5
-	sub		%o2, 2, %o2
-	stb		%g5, [%o0]
-64:	
-	and		%o1, 3, %g2
-	and		%o1, -4, %o1
-	and		%o2, 0xc, %g3
-	add		%o1, 4, %o1
-	cmp		%g3, 4
-	sll		%g2, 3, %g4
-	mov		32, %g2
-	be		4f
-	 sub		%g2, %g4, %g7
-
-	blu		3f
-	 cmp		%g3, 8
-
-	be		2f
-	 srl		%o2, 2, %g3
-
-	ld		[%o1 - 4], %o3
-	add		%o0, -8, %o0
-	ld		[%o1 - 8], %o4
-	add		%o1, -16, %o1
-	b		7f
-	 add		%g3, 1, %g3
-2:
-	ld		[%o1 - 4], %o4
-	add		%o0, -4, %o0
-	ld		[%o1 - 8], %g1
-	add		%o1, -12, %o1
-	b		8f
-	 add		%g3, 2, %g3
-3:
-	ld		[%o1 - 4], %o5
-	add		%o0, -12, %o0
-	ld		[%o1 - 8], %o3
-	add		%o1, -20, %o1
-	b		6f
-	 srl		%o2, 2, %g3
-4:
-	ld		[%o1 - 4], %g1
-	srl		%o2, 2, %g3
-	ld		[%o1 - 8], %o5
-	add		%o1, -24, %o1
-	add		%o0, -16, %o0
-	add		%g3, -1, %g3
-
-	ld		[%o1 + 12], %o3
-5:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 12]
-6:
-	ld		[%o1 + 8], %o4
-	sll		%o3, %g4, %g2
-	srl		%o5, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 8]
-7:
-	ld		[%o1 + 4], %g1
-	sll		%o4, %g4, %g2
-	srl		%o3, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 4]
-8:
-	ld		[%o1], %o5
-	sll		%g1, %g4, %g2
-	srl		%o4, %g7, %g5
-	addcc		%g3, -4, %g3
-	or		%g2, %g5, %g2
-	add		%o1, -16, %o1
-	st		%g2, [%o0]
-	add		%o0, -16, %o0
-	bne,a		5b	
-	 ld		[%o1 + 12], %o3
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	srl		%g4, 3, %g3
-	or		%g2, %g5, %g2
-	add		%o1, %g3, %o1
-	andcc		%o2, 2, %g0
-	st		%g2, [%o0 + 12]
-	be		1f
-	 andcc		%o2, 1, %g0
-	
-	ldub		[%o1 + 15], %g5
-	add		%o1, -2, %o1
-	stb		%g5, [%o0 + 11]
-	add		%o0, -2, %o0
-	ldub		[%o1 + 16], %g5
-	stb		%g5, [%o0 + 12]
-1:
-	be		1f
-	 nop
-	ldub		[%o1 + 15], %g5
-	stb		%g5, [%o0 + 11]
-1:
-	retl
-	 RETL_INSN
-
-#endif /* FASTER_REVERSE */
+	 mov		%g7, %o0
 
 /* NOTE: This code is executed just for the cases,
          where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@ FUNC(memmove)
 FUNC(memcpy)	/* %o0=dst %o1=src %o2=len */
 
 	sub		%o0, %o1, %o4
-	SETUP_RETL
+	mov		%o0, %g7
 9:
 	andcc		%o4, 3, %o5
 0:
@@ -569,7 +227,7 @@ FUNC(memcpy)	/* %o0=dst %o1=src %o2=len
 	add		%o1, 4, %o1
 	add		%o0, 4, %o0
 2:
-	andcc		%g1, 0xffffff80, %g7
+	andcc		%g1, 0xffffff80, %g0
 	be		3f
 	 andcc		%o0, 4, %g0
 
@@ -579,22 +237,23 @@ FUNC(memcpy)	/* %o0=dst %o1=src %o2=len
 	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
+	sub		%g1, 128, %g1
 	add		%o1, 128, %o1
-	bne		5b
+	cmp		%g1, 128
+	bge		5b
 	 add		%o0, 128, %o0
 3:
-	andcc		%g1, 0x70, %g7
+	andcc		%g1, 0x70, %g4
 	be		80f
 	 andcc		%g1, 8, %g0
 
 	sethi		%hi(80f), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
+	srl		%g4, 1, %o4
+	add		%g4, %o4, %o4
+	add		%o1, %g4, %o1
 	sub		%o5, %o4, %o5
 	jmpl		%o5 + %lo(80f), %g0
-	 add		%o0, %g7, %o0
+	 add		%o0, %g4, %o0
 
 79:	/* memcpy_table */
 
@@ -641,43 +300,28 @@ FUNC(memcpy)	/* %o0=dst %o1=src %o2=len
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
+	 mov		%g7, %o0
 
 82:	/* ldd_std */
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
+	subcc		%g1, 128, %g1
 	add		%o1, 128, %o1
-	bne		82b
+	cmp		%g1, 128
+	bge		82b
 	 add		%o0, 128, %o0
 
-#ifndef FASTER_ALIGNED
-
-	andcc		%g1, 0x70, %g7
-	be		80b
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(80b), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(80b), %g0
-	 add		%o0, %g7, %o0
-
-#else /* FASTER_ALIGNED */
-
-	andcc		%g1, 0x70, %g7
+	andcc		%g1, 0x70, %g4
 	be		84f
 	 andcc		%g1, 8, %g0
 
 	sethi		%hi(84f), %o5
-	add		%o1, %g7, %o1
-	sub		%o5, %g7, %o5
+	add		%o1, %g4, %o1
+	sub		%o5, %g4, %o5
 	jmpl		%o5 + %lo(84f), %g0
-	 add		%o0, %g7, %o0
+	 add		%o0, %g4, %o0
 
 83:	/* amemcpy_table */
 
@@ -721,382 +365,132 @@ FUNC(memcpy)	/* %o0=dst %o1=src %o2=len
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
-
-#endif /* FASTER_ALIGNED */
+	 mov		%g7, %o0
 
 86:	/* non_aligned */
 	cmp		%o2, 6
 	bleu		88f
+	 nop
 
-#ifdef FASTER_NONALIGNED
-
-	 cmp		%o2, 256
-	bcc		87f
-
-#endif /* FASTER_NONALIGNED */
-
-	 andcc		%o0, 3, %g0
+	save		%sp, -96, %sp
+	andcc		%i0, 3, %g0
 	be		61f
-	 andcc		%o0, 1, %g0
+	 andcc		%i0, 1, %g0
 	be		60f
-	 andcc		%o0, 2, %g0
+	 andcc		%i0, 2, %g0
 
-	ldub		[%o1], %g5
-	add		%o1, 1, %o1
-	stb		%g5, [%o0]
-	sub		%o2, 1, %o2
+	ldub		[%i1], %g5
+	add		%i1, 1, %i1
+	stb		%g5, [%i0]
+	sub		%i2, 1, %i2
 	bne		61f
-	 add		%o0, 1, %o0
+	 add		%i0, 1, %i0
 60:
-	ldub		[%o1], %g3
-	add		%o1, 2, %o1
-	stb		%g3, [%o0]
-	sub		%o2, 2, %o2
-	ldub		[%o1 - 1], %g3
-	add		%o0, 2, %o0
-	stb		%g3, [%o0 - 1]
+	ldub		[%i1], %g3
+	add		%i1, 2, %i1
+	stb		%g3, [%i0]
+	sub		%i2, 2, %i2
+	ldub		[%i1 - 1], %g3
+	add		%i0, 2, %i0
+	stb		%g3, [%i0 - 1]
 61:
-	and		%o1, 3, %g2
-	and		%o2, 0xc, %g3
-	and		%o1, -4, %o1
+	and		%i1, 3, %g2
+	and		%i2, 0xc, %g3
+	and		%i1, -4, %i1
 	cmp		%g3, 4
 	sll		%g2, 3, %g4
 	mov		32, %g2
 	be		4f
-	 sub		%g2, %g4, %g7
+	 sub		%g2, %g4, %l0
 	
 	blu		3f
 	 cmp		%g3, 0x8
 
 	be		2f
-	 srl		%o2, 2, %g3
+	 srl		%i2, 2, %g3
 
-	ld		[%o1], %o3
-	add		%o0, -8, %o0
-	ld		[%o1 + 4], %o4
+	ld		[%i1], %i3
+	add		%i0, -8, %i0
+	ld		[%i1 + 4], %i4
 	b		8f
 	 add		%g3, 1, %g3
 2:
-	ld		[%o1], %o4
-	add		%o0, -12, %o0
-	ld		[%o1 + 4], %o5
+	ld		[%i1], %i4
+	add		%i0, -12, %i0
+	ld		[%i1 + 4], %i5
 	add		%g3, 2, %g3
 	b		9f
-	 add		%o1, -4, %o1
+	 add		%i1, -4, %i1
 3:
-	ld		[%o1], %g1
-	add		%o0, -4, %o0
-	ld		[%o1 + 4], %o3
-	srl		%o2, 2, %g3
+	ld		[%i1], %g1
+	add		%i0, -4, %i0
+	ld		[%i1 + 4], %i3
+	srl		%i2, 2, %g3
 	b		7f
-	 add		%o1, 4, %o1
+	 add		%i1, 4, %i1
 4:
-	ld		[%o1], %o5
-	cmp		%o2, 7
-	ld		[%o1 + 4], %g1
-	srl		%o2, 2, %g3
+	ld		[%i1], %i5
+	cmp		%i2, 7
+	ld		[%i1 + 4], %g1
+	srl		%i2, 2, %g3
 	bleu		10f
-	 add		%o1, 8, %o1
+	 add		%i1, 8, %i1
 
-	ld		[%o1], %o3
+	ld		[%i1], %i3
 	add		%g3, -1, %g3
 5:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
+	sll		%i5, %g4, %g2
+	srl		%g1, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0]
+	st		%g2, [%i0]
 7:
-	ld		[%o1 + 4], %o4
+	ld		[%i1 + 4], %i4
 	sll		%g1, %g4, %g2
-	srl		%o3, %g7, %g5
+	srl		%i3, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 4]
+	st		%g2, [%i0 + 4]
 8:
-	ld		[%o1 + 8], %o5
-	sll		%o3, %g4, %g2
-	srl		%o4, %g7, %g5
+	ld		[%i1 + 8], %i5
+	sll		%i3, %g4, %g2
+	srl		%i4, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 8]
+	st		%g2, [%i0 + 8]
 9:
-	ld		[%o1 + 12], %g1
-	sll		%o4, %g4, %g2
-	srl		%o5, %g7, %g5
+	ld		[%i1 + 12], %g1
+	sll		%i4, %g4, %g2
+	srl		%i5, %l0, %g5
 	addcc		%g3, -4, %g3
 	or		%g2, %g5, %g2
-	add		%o1, 16, %o1
-	st		%g2, [%o0 + 12]
-	add		%o0, 16, %o0
+	add		%i1, 16, %i1
+	st		%g2, [%i0 + 12]
+	add		%i0, 16, %i0
 	bne,a		5b
-	 ld		[%o1], %o3
+	 ld		[%i1], %i3
 10:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	srl		%g7, 3, %g3
+	sll		%i5, %g4, %g2
+	srl		%g1, %l0, %g5
+	srl		%l0, 3, %g3
 	or		%g2, %g5, %g2
-	sub		%o1, %g3, %o1
-	andcc		%o2, 2, %g0
-	st		%g2, [%o0]
+	sub		%i1, %g3, %i1
+	andcc		%i2, 2, %g0
+	st		%g2, [%i0]
 	be		1f
-	 andcc		%o2, 1, %g0
+	 andcc		%i2, 1, %g0
 
-	ldub		[%o1], %g2
-	add		%o1, 2, %o1
-	stb		%g2, [%o0 + 4]
-	add		%o0, 2, %o0
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 + 3]
+	ldub		[%i1], %g2
+	add		%i1, 2, %i1
+	stb		%g2, [%i0 + 4]
+	add		%i0, 2, %i0
+	ldub		[%i1 - 1], %g2
+	stb		%g2, [%i0 + 3]
 1:
 	be		1f
 	 nop
-	ldub		[%o1], %g2
-	stb		%g2, [%o0 + 4]
-1:
-	retl
-	 RETL_INSN
-
-#ifdef FASTER_NONALIGNED
-
-87:	/* faster_nonaligned */
-
-	andcc		%o1, 3, %g0
-	be		3f
-	 andcc		%o1, 1, %g0
-
-	be		4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1], %g2
-	add		%o1, 1, %o1
-	stb		%g2, [%o0]
-	sub		%o2, 1, %o2
-	bne		3f
-	 add		%o0, 1, %o0
-4:
-	lduh		[%o1], %g2
-	add		%o1, 2, %o1
-	srl		%g2, 8, %g3
-	sub		%o2, 2, %o2
-	stb		%g3, [%o0]
-	add		%o0, 2, %o0
-	stb		%g2, [%o0 - 1]
-3:
-	 andcc		%o1, 4, %g0
-
-	bne		2f
-	 cmp		%o5, 1
-
-	ld		[%o1], %o4
-	srl		%o4, 24, %g2
-	stb		%g2, [%o0]
-	srl		%o4, 16, %g3
-	stb		%g3, [%o0 + 1]
-	srl		%o4, 8, %g2
-	stb		%g2, [%o0 + 2]
-	sub		%o2, 4, %o2
-	stb		%o4, [%o0 + 3]
-	add		%o1, 4, %o1
-	add		%o0, 4, %o0
-2:
-	be		33f
-	 cmp		%o5, 2
-	be		32f
-	 sub		%o2, 4, %o2
-31:
-	ld		[%o1], %g2
-	add		%o1, 4, %o1
-	srl		%g2, 24, %g3
-	and		%o0, 7, %g5
-	stb		%g3, [%o0]
-	cmp		%g5, 7
-	sll		%g2, 8, %g1
-	add		%o0, 4, %o0
-	be		41f
-	 and		%o2, 0xffffffc0, %o3
-	ld		[%o0 - 7], %o4
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	st		%o4, [%o0 - 7]
-	sth		%g2, [%o0 - 3]
-	srl		%g1, 8, %g4
-	b		88f
-	 stb		%g4, [%o0 - 1]
-32:
-	ld		[%o1], %g2
-	add		%o1, 4, %o1
-	srl		%g2, 16, %g3
-	and		%o0, 7, %g5
-	sth		%g3, [%o0]
-	cmp		%g5, 6
-	sll		%g2, 16, %g1
-	add		%o0, 4, %o0
-	be		42f
-	 and		%o2, 0xffffffc0, %o3
-	ld		[%o0 - 6], %o4
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	st		%o4, [%o0 - 6]
-	b		88f
-	 sth		%g2, [%o0 - 2]
-33:
-	ld		[%o1], %g2
-	sub		%o2, 4, %o2
-	srl		%g2, 24, %g3
-	and		%o0, 7, %g5
-	stb		%g3, [%o0]
-	cmp		%g5, 5
-	srl		%g2, 8, %g4
-	sll		%g2, 24, %g1
-	sth		%g4, [%o0 + 1]
-	add		%o1, 4, %o1
-	be		43f
-	 and		%o2, 0xffffffc0, %o3
-
-	ld		[%o0 - 1], %o4
-	add		%o0, 4, %o0
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 24, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 24, %g2
-1:
-	st		%o4, [%o0 - 5]
-	b		88f
-	 stb		%g2, [%o0 - 1]
-41:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		41b
-	 add		%o0, 64, %o0
-	 
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	sth		%g2, [%o0 - 3]
-	srl		%g1, 8, %g4
-	b		88f
-	 stb		%g4, [%o0 - 1]
-43:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		43b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 24, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 24, %g2
-1:
-	stb		%g2, [%o0 + 3]
-	b		88f
-	 add		%o0, 4, %o0
-42:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		42b
-	 add		%o0, 64, %o0
-	 
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
+	ldub		[%i1], %g2
+	stb		%g2, [%i0 + 4]
 1:
-	sth		%g2, [%o0 - 2]
-
-	/* Fall through */
-	 
-#endif /* FASTER_NONALIGNED */
+	ret
+	 restore	%g7, %g0, %o0
 
 88:	/* short_end */
 
@@ -1127,7 +521,7 @@ FUNC(memcpy)	/* %o0=dst %o1=src %o2=len
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
+	 mov		%g7, %o0
 
 90:	/* short_aligned_end */
 	bne		88b
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/btfixup.c linux-libre-3.2-gnu1/arch/sparc/mm/btfixup.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/btfixup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/btfixup.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,8 +302,7 @@ void __init btfixup(void)
 				case 'i':	/* INT */
 					if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
 						set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
-					else if ((insn & 0x80002000) == 0x80002000 &&
-					         (insn & 0x01800000) != 0x01800000) /* %LO */
+					else if ((insn & 0x80002000) == 0x80002000) /* %LO */
 						set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
 					else {
 						prom_printf(insn_i, p, addr, insn);
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/fault_32.c linux-libre-3.2-gnu1/arch/sparc/mm/fault_32.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/fault_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/fault_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
 #include <linux/kdebug.h>
 
 #include <asm/system.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/generic_32.c linux-libre-3.2-gnu1/arch/sparc/mm/generic_32.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/generic_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/generic_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
-		address += PAGE_SIZE;
-		offset += PAGE_SIZE;
-		pte++;
-	} while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	offset -= address;
-	do {
-		pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-		if (!pte)
-			return -ENOMEM;
-		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-	return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-		       unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	int error = 0;
-	pgd_t * dir;
-	unsigned long beg = from;
-	unsigned long end = from + size;
-	struct mm_struct *mm = vma->vm_mm;
-	int space = GET_IOSPACE(pfn);
-	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-
-	/* See comment in mm/memory.c remap_pfn_range */
-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-	vma->vm_pgoff = (offset >> PAGE_SHIFT) |
-		((unsigned long)space << 28UL);
-
-	offset -= from;
-	dir = pgd_offset(mm, from);
-	flush_cache_range(vma, beg, end);
-
-	while (from < end) {
-		pmd_t *pmd = pmd_alloc(mm, dir, from);
-		error = -ENOMEM;
-		if (!pmd)
-			break;
-		error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
-		if (error)
-			break;
-		from = (from + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	}
-
-	flush_tlb_range(vma, beg, end);
-	return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/generic_64.c linux-libre-3.2-gnu1/arch/sparc/mm/generic_64.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/generic_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/generic_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
-				      unsigned long address,
-				      unsigned long size,
-				      unsigned long offset, pgprot_t prot,
-				      int space)
-{
-	unsigned long end;
-
-	/* clear hack bit that was used as a write_combine side-effect flag */
-	offset &= ~0x1UL;
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		pte_t entry;
-		unsigned long curend = address + PAGE_SIZE;
-		
-		entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
-		if (!(address & 0xffff)) {
-			if (PAGE_SIZE < (4 * 1024 * 1024) &&
-			    !(address & 0x3fffff) &&
-			    !(offset & 0x3ffffe) &&
-			    end >= address + 0x400000) {
-				entry = mk_pte_io(offset, prot, space,
-						  4 * 1024 * 1024);
-				curend = address + 0x400000;
-				offset += 0x400000;
-			} else if (PAGE_SIZE < (512 * 1024) &&
-				   !(address & 0x7ffff) &&
-				   !(offset & 0x7fffe) &&
-				   end >= address + 0x80000) {
-				entry = mk_pte_io(offset, prot, space,
-						  512 * 1024 * 1024);
-				curend = address + 0x80000;
-				offset += 0x80000;
-			} else if (PAGE_SIZE < (64 * 1024) &&
-				   !(offset & 0xfffe) &&
-				   end >= address + 0x10000) {
-				entry = mk_pte_io(offset, prot, space,
-						  64 * 1024);
-				curend = address + 0x10000;
-				offset += 0x10000;
-			} else
-				offset += PAGE_SIZE;
-		} else
-			offset += PAGE_SIZE;
-
-		if (pte_write(entry))
-			entry = pte_mkdirty(entry);
-		do {
-			BUG_ON(!pte_none(*pte));
-			set_pte_at(mm, address, pte, entry);
-			address += PAGE_SIZE;
-			pte_val(entry) += PAGE_SIZE;
-			pte++;
-		} while (address < curend);
-	} while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	offset -= address;
-	do {
-		pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-		if (!pte)
-			return -ENOMEM;
-		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-		pte_unmap(pte);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-	return 0;
-}
-
-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PUD_MASK;
-	end = address + size;
-	if (end > PUD_SIZE)
-		end = PUD_SIZE;
-	offset -= address;
-	do {
-		pmd_t *pmd = pmd_alloc(mm, pud, address);
-		if (!pud)
-			return -ENOMEM;
-		io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
-		address = (address + PUD_SIZE) & PUD_MASK;
-		pud++;
-	} while (address < end);
-	return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-		unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	int error = 0;
-	pgd_t * dir;
-	unsigned long beg = from;
-	unsigned long end = from + size;
-	struct mm_struct *mm = vma->vm_mm;
-	int space = GET_IOSPACE(pfn);
-	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-	unsigned long phys_base;
-
-	phys_base = offset | (((unsigned long) space) << 32UL);
-
-	/* See comment in mm/memory.c remap_pfn_range */
-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-	vma->vm_pgoff = phys_base >> PAGE_SHIFT;
-
-	offset -= from;
-	dir = pgd_offset(mm, from);
-	flush_cache_range(vma, beg, end);
-
-	while (from < end) {
-		pud_t *pud = pud_alloc(mm, dir, from);
-		error = -ENOMEM;
-		if (!pud)
-			break;
-		error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
-		if (error)
-			break;
-		from = (from + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	}
-
-	flush_tlb_range(vma, beg, end);
-	return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/gup.c linux-libre-3.2-gnu1/arch/sparc/mm/gup.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,8 @@ static noinline int gup_pte_range(pmd_t
 			put_page(head);
 			return 0;
 		}
+		if (head != page)
+			get_huge_page_tail(page);
 
 		pages[*nr] = page;
 		(*nr)++;
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/highmem.c linux-libre-3.2-gnu1/arch/sparc/mm/highmem.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/highmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/highmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/export.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/hugetlbpage.c linux-libre-3.2-gnu1/arch/sparc/mm/hugetlbpage.c
--- linux-libre-3.1-gnu1/arch/sparc/mm/hugetlbpage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/hugetlbpage.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
diff -druNp linux-libre-3.1-gnu1/arch/sparc/mm/Makefile linux-libre-3.2-gnu1/arch/sparc/mm/Makefile
--- linux-libre-3.1-gnu1/arch/sparc/mm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/sparc/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64)   += ultra.o tlb.o
 obj-y                   += fault_$(BITS).o
 obj-y                   += init_$(BITS).o
 obj-$(CONFIG_SPARC32)   += loadmmu.o
-obj-y                   += generic_$(BITS).o
 obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
 obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
 obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff -druNp linux-libre-3.1-gnu1/arch/tile/configs/tilegx_defconfig linux-libre-3.2-gnu1/arch/tile/configs/tilegx_defconfig
--- linux-libre-3.1-gnu1/arch/tile/configs/tilegx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/configs/tilegx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_DEFAULT_MIGRATION_COST=10000000
diff -druNp linux-libre-3.1-gnu1/arch/tile/configs/tilepro_defconfig linux-libre-3.2-gnu1/arch/tile/configs/tilepro_defconfig
--- linux-libre-3.1-gnu1/arch/tile/configs/tilepro_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/configs/tilepro_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_DEFAULT_MIGRATION_COST=10000000
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/arch/abi.h linux-libre-3.2-gnu1/arch/tile/include/arch/abi.h
--- linux-libre-3.1-gnu1/arch/tile/include/arch/abi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/arch/abi.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,13 +15,78 @@
 /**
  * @file
  *
- * ABI-related register definitions helpful when writing assembly code.
+ * ABI-related register definitions.
  */
 
 #ifndef __ARCH_ABI_H__
-#define __ARCH_ABI_H__
 
-#include <arch/chip.h>
+#if !defined __need_int_reg_t && !defined __DOXYGEN__
+# define __ARCH_ABI_H__
+# include <arch/chip.h>
+#endif
+
+/* Provide the basic machine types. */
+#ifndef __INT_REG_BITS
+
+/** Number of bits in a register. */
+#if defined __tilegx__
+# define __INT_REG_BITS 64
+#elif defined __tilepro__
+# define __INT_REG_BITS 32
+#elif !defined __need_int_reg_t
+# include <arch/chip.h>
+# define __INT_REG_BITS CHIP_WORD_SIZE()
+#else
+# error Unrecognized architecture with __need_int_reg_t
+#endif
+
+#if __INT_REG_BITS == 64
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "ll"
+
+#else
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "l"
+
+#endif
+#endif /* __INT_REG_BITS */
+
+
+#ifndef __need_int_reg_t
+
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef __uint_reg_t uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef __int_reg_t int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define INT_REG_FMT __INT_REG_FMT
+
+/** Number of bits in a register. */
+#define INT_REG_BITS __INT_REG_BITS
+
 
 /* Registers 0 - 55 are "normal", but some perform special roles. */
 
@@ -59,7 +124,7 @@
  * The ABI requires callers to allocate a caller state save area of
  * this many bytes at the bottom of each stack frame.
  */
-#define C_ABI_SAVE_AREA_SIZE (2 * (CHIP_WORD_SIZE() / 8))
+#define C_ABI_SAVE_AREA_SIZE (2 * (INT_REG_BITS / 8))
 
 /**
  * The operand to an 'info' opcode directing the backtracer to not
@@ -67,30 +132,10 @@
  */
 #define INFO_OP_CANNOT_BACKTRACE 2
 
-#ifndef __ASSEMBLER__
-#if CHIP_WORD_SIZE() > 32
 
-/** Unsigned type that can hold a register. */
-typedef unsigned long long uint_reg_t;
-
-/** Signed type that can hold a register. */
-typedef long long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "ll"
-
-#elif !defined(__LP64__)   /* avoid confusion with LP64 cross-build tools */
-
-/** Unsigned type that can hold a register. */
-typedef unsigned long uint_reg_t;
-
-/** Signed type that can hold a register. */
-typedef long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "l"
+#endif /* !__need_int_reg_t */
 
-#endif
-#endif /* __ASSEMBLER__ */
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_int_reg_t
 
 #endif /* !__ARCH_ABI_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/arch/Kbuild linux-libre-3.2-gnu1/arch/tile/include/arch/Kbuild
--- linux-libre-3.1-gnu1/arch/tile/include/arch/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/arch/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+header-y += abi.h
+header-y += chip.h
+header-y += chip_tile64.h
+header-y += chip_tilegx.h
+header-y += chip_tilepro.h
+header-y += icache.h
+header-y += interrupts.h
+header-y += interrupts_32.h
+header-y += interrupts_64.h
+header-y += opcode.h
+header-y += opcode_tilegx.h
+header-y += opcode_tilepro.h
+header-y += sim.h
+header-y += sim_def.h
+header-y += spr_def.h
+header-y += spr_def_32.h
+header-y += spr_def_64.h
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/arch/opcode.h linux-libre-3.2-gnu1/arch/tile/include/arch/opcode.h
--- linux-libre-3.1-gnu1/arch/tile/include/arch/opcode.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/arch/opcode.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#if defined(__tilepro__)
+#include <arch/opcode_tilepro.h>
+#elif defined(__tilegx__)
+#include <arch/opcode_tilegx.h>
+#else
+#error Unexpected Tilera chip type
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/arch/opcode_tilegx.h linux-libre-3.2-gnu1/arch/tile/include/arch/opcode_tilegx.h
--- linux-libre-3.1-gnu1/arch/tile/include/arch/opcode_tilegx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/arch/opcode_tilegx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1405 @@
+/* TILE-Gx opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilegx_bundle_bits;
+
+/* These are the bits that determine if a bundle is in the X encoding. */
+#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEGX_NUM_REGISTERS = 64,
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilegx_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
+
+static __inline unsigned int
+get_BFEnd_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 24)) & 0xf);
+}
+
+static __inline unsigned int
+get_BFStart_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x0001ffc0);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_JumpOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x7ffffff);
+}
+
+static __inline unsigned int
+get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_MF_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3fff);
+}
+
+static __inline unsigned int
+get_MT_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0);
+}
+
+static __inline unsigned int
+get_Mode(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 62)) & 0x3);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilegx_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 56)) & 0x00000002);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilegx_bundle_bits
+create_BFEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_BFOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 24);
+}
+
+static __inline tilegx_bundle_bits
+create_BFStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_MF_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_MT_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+
+enum
+{
+  ADDI_IMM8_OPCODE_X0 = 1,
+  ADDI_IMM8_OPCODE_X1 = 1,
+  ADDI_OPCODE_Y0 = 0,
+  ADDI_OPCODE_Y1 = 1,
+  ADDLI_OPCODE_X0 = 1,
+  ADDLI_OPCODE_X1 = 0,
+  ADDXI_IMM8_OPCODE_X0 = 2,
+  ADDXI_IMM8_OPCODE_X1 = 2,
+  ADDXI_OPCODE_Y0 = 1,
+  ADDXI_OPCODE_Y1 = 2,
+  ADDXLI_OPCODE_X0 = 2,
+  ADDXLI_OPCODE_X1 = 1,
+  ADDXSC_RRR_0_OPCODE_X0 = 1,
+  ADDXSC_RRR_0_OPCODE_X1 = 1,
+  ADDX_RRR_0_OPCODE_X0 = 2,
+  ADDX_RRR_0_OPCODE_X1 = 2,
+  ADDX_RRR_0_OPCODE_Y0 = 0,
+  ADDX_SPECIAL_0_OPCODE_Y1 = 0,
+  ADD_RRR_0_OPCODE_X0 = 3,
+  ADD_RRR_0_OPCODE_X1 = 3,
+  ADD_RRR_0_OPCODE_Y0 = 1,
+  ADD_SPECIAL_0_OPCODE_Y1 = 1,
+  ANDI_IMM8_OPCODE_X0 = 3,
+  ANDI_IMM8_OPCODE_X1 = 3,
+  ANDI_OPCODE_Y0 = 2,
+  ANDI_OPCODE_Y1 = 3,
+  AND_RRR_0_OPCODE_X0 = 4,
+  AND_RRR_0_OPCODE_X1 = 4,
+  AND_RRR_5_OPCODE_Y0 = 0,
+  AND_RRR_5_OPCODE_Y1 = 0,
+  BEQZT_BRANCH_OPCODE_X1 = 16,
+  BEQZ_BRANCH_OPCODE_X1 = 17,
+  BFEXTS_BF_OPCODE_X0 = 4,
+  BFEXTU_BF_OPCODE_X0 = 5,
+  BFINS_BF_OPCODE_X0 = 6,
+  BF_OPCODE_X0 = 3,
+  BGEZT_BRANCH_OPCODE_X1 = 18,
+  BGEZ_BRANCH_OPCODE_X1 = 19,
+  BGTZT_BRANCH_OPCODE_X1 = 20,
+  BGTZ_BRANCH_OPCODE_X1 = 21,
+  BLBCT_BRANCH_OPCODE_X1 = 22,
+  BLBC_BRANCH_OPCODE_X1 = 23,
+  BLBST_BRANCH_OPCODE_X1 = 24,
+  BLBS_BRANCH_OPCODE_X1 = 25,
+  BLEZT_BRANCH_OPCODE_X1 = 26,
+  BLEZ_BRANCH_OPCODE_X1 = 27,
+  BLTZT_BRANCH_OPCODE_X1 = 28,
+  BLTZ_BRANCH_OPCODE_X1 = 29,
+  BNEZT_BRANCH_OPCODE_X1 = 30,
+  BNEZ_BRANCH_OPCODE_X1 = 31,
+  BRANCH_OPCODE_X1 = 2,
+  CMOVEQZ_RRR_0_OPCODE_X0 = 5,
+  CMOVEQZ_RRR_4_OPCODE_Y0 = 0,
+  CMOVNEZ_RRR_0_OPCODE_X0 = 6,
+  CMOVNEZ_RRR_4_OPCODE_Y0 = 1,
+  CMPEQI_IMM8_OPCODE_X0 = 4,
+  CMPEQI_IMM8_OPCODE_X1 = 4,
+  CMPEQI_OPCODE_Y0 = 3,
+  CMPEQI_OPCODE_Y1 = 4,
+  CMPEQ_RRR_0_OPCODE_X0 = 7,
+  CMPEQ_RRR_0_OPCODE_X1 = 5,
+  CMPEQ_RRR_3_OPCODE_Y0 = 0,
+  CMPEQ_RRR_3_OPCODE_Y1 = 2,
+  CMPEXCH4_RRR_0_OPCODE_X1 = 6,
+  CMPEXCH_RRR_0_OPCODE_X1 = 7,
+  CMPLES_RRR_0_OPCODE_X0 = 8,
+  CMPLES_RRR_0_OPCODE_X1 = 8,
+  CMPLES_RRR_2_OPCODE_Y0 = 0,
+  CMPLES_RRR_2_OPCODE_Y1 = 0,
+  CMPLEU_RRR_0_OPCODE_X0 = 9,
+  CMPLEU_RRR_0_OPCODE_X1 = 9,
+  CMPLEU_RRR_2_OPCODE_Y0 = 1,
+  CMPLEU_RRR_2_OPCODE_Y1 = 1,
+  CMPLTSI_IMM8_OPCODE_X0 = 5,
+  CMPLTSI_IMM8_OPCODE_X1 = 5,
+  CMPLTSI_OPCODE_Y0 = 4,
+  CMPLTSI_OPCODE_Y1 = 5,
+  CMPLTS_RRR_0_OPCODE_X0 = 10,
+  CMPLTS_RRR_0_OPCODE_X1 = 10,
+  CMPLTS_RRR_2_OPCODE_Y0 = 2,
+  CMPLTS_RRR_2_OPCODE_Y1 = 2,
+  CMPLTUI_IMM8_OPCODE_X0 = 6,
+  CMPLTUI_IMM8_OPCODE_X1 = 6,
+  CMPLTU_RRR_0_OPCODE_X0 = 11,
+  CMPLTU_RRR_0_OPCODE_X1 = 11,
+  CMPLTU_RRR_2_OPCODE_Y0 = 3,
+  CMPLTU_RRR_2_OPCODE_Y1 = 3,
+  CMPNE_RRR_0_OPCODE_X0 = 12,
+  CMPNE_RRR_0_OPCODE_X1 = 12,
+  CMPNE_RRR_3_OPCODE_Y0 = 1,
+  CMPNE_RRR_3_OPCODE_Y1 = 3,
+  CMULAF_RRR_0_OPCODE_X0 = 13,
+  CMULA_RRR_0_OPCODE_X0 = 14,
+  CMULFR_RRR_0_OPCODE_X0 = 15,
+  CMULF_RRR_0_OPCODE_X0 = 16,
+  CMULHR_RRR_0_OPCODE_X0 = 17,
+  CMULH_RRR_0_OPCODE_X0 = 18,
+  CMUL_RRR_0_OPCODE_X0 = 19,
+  CNTLZ_UNARY_OPCODE_X0 = 1,
+  CNTLZ_UNARY_OPCODE_Y0 = 1,
+  CNTTZ_UNARY_OPCODE_X0 = 2,
+  CNTTZ_UNARY_OPCODE_Y0 = 2,
+  CRC32_32_RRR_0_OPCODE_X0 = 20,
+  CRC32_8_RRR_0_OPCODE_X0 = 21,
+  DBLALIGN2_RRR_0_OPCODE_X0 = 22,
+  DBLALIGN2_RRR_0_OPCODE_X1 = 13,
+  DBLALIGN4_RRR_0_OPCODE_X0 = 23,
+  DBLALIGN4_RRR_0_OPCODE_X1 = 14,
+  DBLALIGN6_RRR_0_OPCODE_X0 = 24,
+  DBLALIGN6_RRR_0_OPCODE_X1 = 15,
+  DBLALIGN_RRR_0_OPCODE_X0 = 25,
+  DRAIN_UNARY_OPCODE_X1 = 1,
+  DTLBPR_UNARY_OPCODE_X1 = 2,
+  EXCH4_RRR_0_OPCODE_X1 = 16,
+  EXCH_RRR_0_OPCODE_X1 = 17,
+  FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,
+  FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,
+  FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,
+  FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,
+  FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,
+  FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,
+  FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,
+  FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,
+  FETCHADD4_RRR_0_OPCODE_X1 = 18,
+  FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,
+  FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,
+  FETCHADD_RRR_0_OPCODE_X1 = 21,
+  FETCHAND4_RRR_0_OPCODE_X1 = 22,
+  FETCHAND_RRR_0_OPCODE_X1 = 23,
+  FETCHOR4_RRR_0_OPCODE_X1 = 24,
+  FETCHOR_RRR_0_OPCODE_X1 = 25,
+  FINV_UNARY_OPCODE_X1 = 3,
+  FLUSHWB_UNARY_OPCODE_X1 = 4,
+  FLUSH_UNARY_OPCODE_X1 = 5,
+  FNOP_UNARY_OPCODE_X0 = 3,
+  FNOP_UNARY_OPCODE_X1 = 6,
+  FNOP_UNARY_OPCODE_Y0 = 3,
+  FNOP_UNARY_OPCODE_Y1 = 8,
+  FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,
+  FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,
+  FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,
+  FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,
+  FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,
+  FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
+  FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,
+  FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,
+  ICOH_UNARY_OPCODE_X1 = 7,
+  ILL_UNARY_OPCODE_X1 = 8,
+  ILL_UNARY_OPCODE_Y1 = 9,
+  IMM8_OPCODE_X0 = 4,
+  IMM8_OPCODE_X1 = 3,
+  INV_UNARY_OPCODE_X1 = 9,
+  IRET_UNARY_OPCODE_X1 = 10,
+  JALRP_UNARY_OPCODE_X1 = 11,
+  JALRP_UNARY_OPCODE_Y1 = 10,
+  JALR_UNARY_OPCODE_X1 = 12,
+  JALR_UNARY_OPCODE_Y1 = 11,
+  JAL_JUMP_OPCODE_X1 = 0,
+  JRP_UNARY_OPCODE_X1 = 13,
+  JRP_UNARY_OPCODE_Y1 = 12,
+  JR_UNARY_OPCODE_X1 = 14,
+  JR_UNARY_OPCODE_Y1 = 13,
+  JUMP_OPCODE_X1 = 4,
+  J_JUMP_OPCODE_X1 = 1,
+  LD1S_ADD_IMM8_OPCODE_X1 = 7,
+  LD1S_OPCODE_Y2 = 0,
+  LD1S_UNARY_OPCODE_X1 = 15,
+  LD1U_ADD_IMM8_OPCODE_X1 = 8,
+  LD1U_OPCODE_Y2 = 1,
+  LD1U_UNARY_OPCODE_X1 = 16,
+  LD2S_ADD_IMM8_OPCODE_X1 = 9,
+  LD2S_OPCODE_Y2 = 2,
+  LD2S_UNARY_OPCODE_X1 = 17,
+  LD2U_ADD_IMM8_OPCODE_X1 = 10,
+  LD2U_OPCODE_Y2 = 3,
+  LD2U_UNARY_OPCODE_X1 = 18,
+  LD4S_ADD_IMM8_OPCODE_X1 = 11,
+  LD4S_OPCODE_Y2 = 1,
+  LD4S_UNARY_OPCODE_X1 = 19,
+  LD4U_ADD_IMM8_OPCODE_X1 = 12,
+  LD4U_OPCODE_Y2 = 2,
+  LD4U_UNARY_OPCODE_X1 = 20,
+  LDNA_UNARY_OPCODE_X1 = 21,
+  LDNT1S_ADD_IMM8_OPCODE_X1 = 13,
+  LDNT1S_UNARY_OPCODE_X1 = 22,
+  LDNT1U_ADD_IMM8_OPCODE_X1 = 14,
+  LDNT1U_UNARY_OPCODE_X1 = 23,
+  LDNT2S_ADD_IMM8_OPCODE_X1 = 15,
+  LDNT2S_UNARY_OPCODE_X1 = 24,
+  LDNT2U_ADD_IMM8_OPCODE_X1 = 16,
+  LDNT2U_UNARY_OPCODE_X1 = 25,
+  LDNT4S_ADD_IMM8_OPCODE_X1 = 17,
+  LDNT4S_UNARY_OPCODE_X1 = 26,
+  LDNT4U_ADD_IMM8_OPCODE_X1 = 18,
+  LDNT4U_UNARY_OPCODE_X1 = 27,
+  LDNT_ADD_IMM8_OPCODE_X1 = 19,
+  LDNT_UNARY_OPCODE_X1 = 28,
+  LD_ADD_IMM8_OPCODE_X1 = 20,
+  LD_OPCODE_Y2 = 3,
+  LD_UNARY_OPCODE_X1 = 29,
+  LNK_UNARY_OPCODE_X1 = 30,
+  LNK_UNARY_OPCODE_Y1 = 14,
+  LWNA_ADD_IMM8_OPCODE_X1 = 21,
+  MFSPR_IMM8_OPCODE_X1 = 22,
+  MF_UNARY_OPCODE_X1 = 31,
+  MM_BF_OPCODE_X0 = 7,
+  MNZ_RRR_0_OPCODE_X0 = 40,
+  MNZ_RRR_0_OPCODE_X1 = 26,
+  MNZ_RRR_4_OPCODE_Y0 = 2,
+  MNZ_RRR_4_OPCODE_Y1 = 2,
+  MODE_OPCODE_YA2 = 1,
+  MODE_OPCODE_YB2 = 2,
+  MODE_OPCODE_YC2 = 3,
+  MTSPR_IMM8_OPCODE_X1 = 23,
+  MULAX_RRR_0_OPCODE_X0 = 41,
+  MULAX_RRR_3_OPCODE_Y0 = 2,
+  MULA_HS_HS_RRR_0_OPCODE_X0 = 42,
+  MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,
+  MULA_HS_HU_RRR_0_OPCODE_X0 = 43,
+  MULA_HS_LS_RRR_0_OPCODE_X0 = 44,
+  MULA_HS_LU_RRR_0_OPCODE_X0 = 45,
+  MULA_HU_HU_RRR_0_OPCODE_X0 = 46,
+  MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,
+  MULA_HU_LS_RRR_0_OPCODE_X0 = 47,
+  MULA_HU_LU_RRR_0_OPCODE_X0 = 48,
+  MULA_LS_LS_RRR_0_OPCODE_X0 = 49,
+  MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,
+  MULA_LS_LU_RRR_0_OPCODE_X0 = 50,
+  MULA_LU_LU_RRR_0_OPCODE_X0 = 51,
+  MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,
+  MULX_RRR_0_OPCODE_X0 = 52,
+  MULX_RRR_3_OPCODE_Y0 = 3,
+  MUL_HS_HS_RRR_0_OPCODE_X0 = 53,
+  MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,
+  MUL_HS_HU_RRR_0_OPCODE_X0 = 54,
+  MUL_HS_LS_RRR_0_OPCODE_X0 = 55,
+  MUL_HS_LU_RRR_0_OPCODE_X0 = 56,
+  MUL_HU_HU_RRR_0_OPCODE_X0 = 57,
+  MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,
+  MUL_HU_LS_RRR_0_OPCODE_X0 = 58,
+  MUL_HU_LU_RRR_0_OPCODE_X0 = 59,
+  MUL_LS_LS_RRR_0_OPCODE_X0 = 60,
+  MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,
+  MUL_LS_LU_RRR_0_OPCODE_X0 = 61,
+  MUL_LU_LU_RRR_0_OPCODE_X0 = 62,
+  MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,
+  MZ_RRR_0_OPCODE_X0 = 63,
+  MZ_RRR_0_OPCODE_X1 = 27,
+  MZ_RRR_4_OPCODE_Y0 = 3,
+  MZ_RRR_4_OPCODE_Y1 = 3,
+  NAP_UNARY_OPCODE_X1 = 32,
+  NOP_UNARY_OPCODE_X0 = 5,
+  NOP_UNARY_OPCODE_X1 = 33,
+  NOP_UNARY_OPCODE_Y0 = 5,
+  NOP_UNARY_OPCODE_Y1 = 15,
+  NOR_RRR_0_OPCODE_X0 = 64,
+  NOR_RRR_0_OPCODE_X1 = 28,
+  NOR_RRR_5_OPCODE_Y0 = 1,
+  NOR_RRR_5_OPCODE_Y1 = 1,
+  ORI_IMM8_OPCODE_X0 = 7,
+  ORI_IMM8_OPCODE_X1 = 24,
+  OR_RRR_0_OPCODE_X0 = 65,
+  OR_RRR_0_OPCODE_X1 = 29,
+  OR_RRR_5_OPCODE_Y0 = 2,
+  OR_RRR_5_OPCODE_Y1 = 2,
+  PCNT_UNARY_OPCODE_X0 = 6,
+  PCNT_UNARY_OPCODE_Y0 = 6,
+  REVBITS_UNARY_OPCODE_X0 = 7,
+  REVBITS_UNARY_OPCODE_Y0 = 7,
+  REVBYTES_UNARY_OPCODE_X0 = 8,
+  REVBYTES_UNARY_OPCODE_Y0 = 8,
+  ROTLI_SHIFT_OPCODE_X0 = 1,
+  ROTLI_SHIFT_OPCODE_X1 = 1,
+  ROTLI_SHIFT_OPCODE_Y0 = 0,
+  ROTLI_SHIFT_OPCODE_Y1 = 0,
+  ROTL_RRR_0_OPCODE_X0 = 66,
+  ROTL_RRR_0_OPCODE_X1 = 30,
+  ROTL_RRR_6_OPCODE_Y0 = 0,
+  ROTL_RRR_6_OPCODE_Y1 = 0,
+  RRR_0_OPCODE_X0 = 5,
+  RRR_0_OPCODE_X1 = 5,
+  RRR_0_OPCODE_Y0 = 5,
+  RRR_0_OPCODE_Y1 = 6,
+  RRR_1_OPCODE_Y0 = 6,
+  RRR_1_OPCODE_Y1 = 7,
+  RRR_2_OPCODE_Y0 = 7,
+  RRR_2_OPCODE_Y1 = 8,
+  RRR_3_OPCODE_Y0 = 8,
+  RRR_3_OPCODE_Y1 = 9,
+  RRR_4_OPCODE_Y0 = 9,
+  RRR_4_OPCODE_Y1 = 10,
+  RRR_5_OPCODE_Y0 = 10,
+  RRR_5_OPCODE_Y1 = 11,
+  RRR_6_OPCODE_Y0 = 11,
+  RRR_6_OPCODE_Y1 = 12,
+  RRR_7_OPCODE_Y0 = 12,
+  RRR_7_OPCODE_Y1 = 13,
+  RRR_8_OPCODE_Y0 = 13,
+  RRR_9_OPCODE_Y0 = 14,
+  SHIFT_OPCODE_X0 = 6,
+  SHIFT_OPCODE_X1 = 6,
+  SHIFT_OPCODE_Y0 = 15,
+  SHIFT_OPCODE_Y1 = 14,
+  SHL16INSLI_OPCODE_X0 = 7,
+  SHL16INSLI_OPCODE_X1 = 7,
+  SHL1ADDX_RRR_0_OPCODE_X0 = 67,
+  SHL1ADDX_RRR_0_OPCODE_X1 = 31,
+  SHL1ADDX_RRR_7_OPCODE_Y0 = 1,
+  SHL1ADDX_RRR_7_OPCODE_Y1 = 1,
+  SHL1ADD_RRR_0_OPCODE_X0 = 68,
+  SHL1ADD_RRR_0_OPCODE_X1 = 32,
+  SHL1ADD_RRR_1_OPCODE_Y0 = 0,
+  SHL1ADD_RRR_1_OPCODE_Y1 = 0,
+  SHL2ADDX_RRR_0_OPCODE_X0 = 69,
+  SHL2ADDX_RRR_0_OPCODE_X1 = 33,
+  SHL2ADDX_RRR_7_OPCODE_Y0 = 2,
+  SHL2ADDX_RRR_7_OPCODE_Y1 = 2,
+  SHL2ADD_RRR_0_OPCODE_X0 = 70,
+  SHL2ADD_RRR_0_OPCODE_X1 = 34,
+  SHL2ADD_RRR_1_OPCODE_Y0 = 1,
+  SHL2ADD_RRR_1_OPCODE_Y1 = 1,
+  SHL3ADDX_RRR_0_OPCODE_X0 = 71,
+  SHL3ADDX_RRR_0_OPCODE_X1 = 35,
+  SHL3ADDX_RRR_7_OPCODE_Y0 = 3,
+  SHL3ADDX_RRR_7_OPCODE_Y1 = 3,
+  SHL3ADD_RRR_0_OPCODE_X0 = 72,
+  SHL3ADD_RRR_0_OPCODE_X1 = 36,
+  SHL3ADD_RRR_1_OPCODE_Y0 = 2,
+  SHL3ADD_RRR_1_OPCODE_Y1 = 2,
+  SHLI_SHIFT_OPCODE_X0 = 2,
+  SHLI_SHIFT_OPCODE_X1 = 2,
+  SHLI_SHIFT_OPCODE_Y0 = 1,
+  SHLI_SHIFT_OPCODE_Y1 = 1,
+  SHLXI_SHIFT_OPCODE_X0 = 3,
+  SHLXI_SHIFT_OPCODE_X1 = 3,
+  SHLX_RRR_0_OPCODE_X0 = 73,
+  SHLX_RRR_0_OPCODE_X1 = 37,
+  SHL_RRR_0_OPCODE_X0 = 74,
+  SHL_RRR_0_OPCODE_X1 = 38,
+  SHL_RRR_6_OPCODE_Y0 = 1,
+  SHL_RRR_6_OPCODE_Y1 = 1,
+  SHRSI_SHIFT_OPCODE_X0 = 4,
+  SHRSI_SHIFT_OPCODE_X1 = 4,
+  SHRSI_SHIFT_OPCODE_Y0 = 2,
+  SHRSI_SHIFT_OPCODE_Y1 = 2,
+  SHRS_RRR_0_OPCODE_X0 = 75,
+  SHRS_RRR_0_OPCODE_X1 = 39,
+  SHRS_RRR_6_OPCODE_Y0 = 2,
+  SHRS_RRR_6_OPCODE_Y1 = 2,
+  SHRUI_SHIFT_OPCODE_X0 = 5,
+  SHRUI_SHIFT_OPCODE_X1 = 5,
+  SHRUI_SHIFT_OPCODE_Y0 = 3,
+  SHRUI_SHIFT_OPCODE_Y1 = 3,
+  SHRUXI_SHIFT_OPCODE_X0 = 6,
+  SHRUXI_SHIFT_OPCODE_X1 = 6,
+  SHRUX_RRR_0_OPCODE_X0 = 76,
+  SHRUX_RRR_0_OPCODE_X1 = 40,
+  SHRU_RRR_0_OPCODE_X0 = 77,
+  SHRU_RRR_0_OPCODE_X1 = 41,
+  SHRU_RRR_6_OPCODE_Y0 = 3,
+  SHRU_RRR_6_OPCODE_Y1 = 3,
+  SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,
+  ST1_ADD_IMM8_OPCODE_X1 = 25,
+  ST1_OPCODE_Y2 = 0,
+  ST1_RRR_0_OPCODE_X1 = 42,
+  ST2_ADD_IMM8_OPCODE_X1 = 26,
+  ST2_OPCODE_Y2 = 1,
+  ST2_RRR_0_OPCODE_X1 = 43,
+  ST4_ADD_IMM8_OPCODE_X1 = 27,
+  ST4_OPCODE_Y2 = 2,
+  ST4_RRR_0_OPCODE_X1 = 44,
+  STNT1_ADD_IMM8_OPCODE_X1 = 28,
+  STNT1_RRR_0_OPCODE_X1 = 45,
+  STNT2_ADD_IMM8_OPCODE_X1 = 29,
+  STNT2_RRR_0_OPCODE_X1 = 46,
+  STNT4_ADD_IMM8_OPCODE_X1 = 30,
+  STNT4_RRR_0_OPCODE_X1 = 47,
+  STNT_ADD_IMM8_OPCODE_X1 = 31,
+  STNT_RRR_0_OPCODE_X1 = 48,
+  ST_ADD_IMM8_OPCODE_X1 = 32,
+  ST_OPCODE_Y2 = 3,
+  ST_RRR_0_OPCODE_X1 = 49,
+  SUBXSC_RRR_0_OPCODE_X0 = 79,
+  SUBXSC_RRR_0_OPCODE_X1 = 50,
+  SUBX_RRR_0_OPCODE_X0 = 80,
+  SUBX_RRR_0_OPCODE_X1 = 51,
+  SUBX_RRR_0_OPCODE_Y0 = 2,
+  SUBX_RRR_0_OPCODE_Y1 = 2,
+  SUB_RRR_0_OPCODE_X0 = 81,
+  SUB_RRR_0_OPCODE_X1 = 52,
+  SUB_RRR_0_OPCODE_Y0 = 3,
+  SUB_RRR_0_OPCODE_Y1 = 3,
+  SWINT0_UNARY_OPCODE_X1 = 34,
+  SWINT1_UNARY_OPCODE_X1 = 35,
+  SWINT2_UNARY_OPCODE_X1 = 36,
+  SWINT3_UNARY_OPCODE_X1 = 37,
+  TBLIDXB0_UNARY_OPCODE_X0 = 9,
+  TBLIDXB0_UNARY_OPCODE_Y0 = 9,
+  TBLIDXB1_UNARY_OPCODE_X0 = 10,
+  TBLIDXB1_UNARY_OPCODE_Y0 = 10,
+  TBLIDXB2_UNARY_OPCODE_X0 = 11,
+  TBLIDXB2_UNARY_OPCODE_Y0 = 11,
+  TBLIDXB3_UNARY_OPCODE_X0 = 12,
+  TBLIDXB3_UNARY_OPCODE_Y0 = 12,
+  UNARY_RRR_0_OPCODE_X0 = 82,
+  UNARY_RRR_0_OPCODE_X1 = 53,
+  UNARY_RRR_1_OPCODE_Y0 = 3,
+  UNARY_RRR_1_OPCODE_Y1 = 3,
+  V1ADDI_IMM8_OPCODE_X0 = 8,
+  V1ADDI_IMM8_OPCODE_X1 = 33,
+  V1ADDUC_RRR_0_OPCODE_X0 = 83,
+  V1ADDUC_RRR_0_OPCODE_X1 = 54,
+  V1ADD_RRR_0_OPCODE_X0 = 84,
+  V1ADD_RRR_0_OPCODE_X1 = 55,
+  V1ADIFFU_RRR_0_OPCODE_X0 = 85,
+  V1AVGU_RRR_0_OPCODE_X0 = 86,
+  V1CMPEQI_IMM8_OPCODE_X0 = 9,
+  V1CMPEQI_IMM8_OPCODE_X1 = 34,
+  V1CMPEQ_RRR_0_OPCODE_X0 = 87,
+  V1CMPEQ_RRR_0_OPCODE_X1 = 56,
+  V1CMPLES_RRR_0_OPCODE_X0 = 88,
+  V1CMPLES_RRR_0_OPCODE_X1 = 57,
+  V1CMPLEU_RRR_0_OPCODE_X0 = 89,
+  V1CMPLEU_RRR_0_OPCODE_X1 = 58,
+  V1CMPLTSI_IMM8_OPCODE_X0 = 10,
+  V1CMPLTSI_IMM8_OPCODE_X1 = 35,
+  V1CMPLTS_RRR_0_OPCODE_X0 = 90,
+  V1CMPLTS_RRR_0_OPCODE_X1 = 59,
+  V1CMPLTUI_IMM8_OPCODE_X0 = 11,
+  V1CMPLTUI_IMM8_OPCODE_X1 = 36,
+  V1CMPLTU_RRR_0_OPCODE_X0 = 91,
+  V1CMPLTU_RRR_0_OPCODE_X1 = 60,
+  V1CMPNE_RRR_0_OPCODE_X0 = 92,
+  V1CMPNE_RRR_0_OPCODE_X1 = 61,
+  V1DDOTPUA_RRR_0_OPCODE_X0 = 161,
+  V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,
+  V1DDOTPUS_RRR_0_OPCODE_X0 = 94,
+  V1DDOTPU_RRR_0_OPCODE_X0 = 162,
+  V1DOTPA_RRR_0_OPCODE_X0 = 95,
+  V1DOTPUA_RRR_0_OPCODE_X0 = 163,
+  V1DOTPUSA_RRR_0_OPCODE_X0 = 96,
+  V1DOTPUS_RRR_0_OPCODE_X0 = 97,
+  V1DOTPU_RRR_0_OPCODE_X0 = 164,
+  V1DOTP_RRR_0_OPCODE_X0 = 98,
+  V1INT_H_RRR_0_OPCODE_X0 = 99,
+  V1INT_H_RRR_0_OPCODE_X1 = 62,
+  V1INT_L_RRR_0_OPCODE_X0 = 100,
+  V1INT_L_RRR_0_OPCODE_X1 = 63,
+  V1MAXUI_IMM8_OPCODE_X0 = 12,
+  V1MAXUI_IMM8_OPCODE_X1 = 37,
+  V1MAXU_RRR_0_OPCODE_X0 = 101,
+  V1MAXU_RRR_0_OPCODE_X1 = 64,
+  V1MINUI_IMM8_OPCODE_X0 = 13,
+  V1MINUI_IMM8_OPCODE_X1 = 38,
+  V1MINU_RRR_0_OPCODE_X0 = 102,
+  V1MINU_RRR_0_OPCODE_X1 = 65,
+  V1MNZ_RRR_0_OPCODE_X0 = 103,
+  V1MNZ_RRR_0_OPCODE_X1 = 66,
+  V1MULTU_RRR_0_OPCODE_X0 = 104,
+  V1MULUS_RRR_0_OPCODE_X0 = 105,
+  V1MULU_RRR_0_OPCODE_X0 = 106,
+  V1MZ_RRR_0_OPCODE_X0 = 107,
+  V1MZ_RRR_0_OPCODE_X1 = 67,
+  V1SADAU_RRR_0_OPCODE_X0 = 108,
+  V1SADU_RRR_0_OPCODE_X0 = 109,
+  V1SHLI_SHIFT_OPCODE_X0 = 7,
+  V1SHLI_SHIFT_OPCODE_X1 = 7,
+  V1SHL_RRR_0_OPCODE_X0 = 110,
+  V1SHL_RRR_0_OPCODE_X1 = 68,
+  V1SHRSI_SHIFT_OPCODE_X0 = 8,
+  V1SHRSI_SHIFT_OPCODE_X1 = 8,
+  V1SHRS_RRR_0_OPCODE_X0 = 111,
+  V1SHRS_RRR_0_OPCODE_X1 = 69,
+  V1SHRUI_SHIFT_OPCODE_X0 = 9,
+  V1SHRUI_SHIFT_OPCODE_X1 = 9,
+  V1SHRU_RRR_0_OPCODE_X0 = 112,
+  V1SHRU_RRR_0_OPCODE_X1 = 70,
+  V1SUBUC_RRR_0_OPCODE_X0 = 113,
+  V1SUBUC_RRR_0_OPCODE_X1 = 71,
+  V1SUB_RRR_0_OPCODE_X0 = 114,
+  V1SUB_RRR_0_OPCODE_X1 = 72,
+  V2ADDI_IMM8_OPCODE_X0 = 14,
+  V2ADDI_IMM8_OPCODE_X1 = 39,
+  V2ADDSC_RRR_0_OPCODE_X0 = 115,
+  V2ADDSC_RRR_0_OPCODE_X1 = 73,
+  V2ADD_RRR_0_OPCODE_X0 = 116,
+  V2ADD_RRR_0_OPCODE_X1 = 74,
+  V2ADIFFS_RRR_0_OPCODE_X0 = 117,
+  V2AVGS_RRR_0_OPCODE_X0 = 118,
+  V2CMPEQI_IMM8_OPCODE_X0 = 15,
+  V2CMPEQI_IMM8_OPCODE_X1 = 40,
+  V2CMPEQ_RRR_0_OPCODE_X0 = 119,
+  V2CMPEQ_RRR_0_OPCODE_X1 = 75,
+  V2CMPLES_RRR_0_OPCODE_X0 = 120,
+  V2CMPLES_RRR_0_OPCODE_X1 = 76,
+  V2CMPLEU_RRR_0_OPCODE_X0 = 121,
+  V2CMPLEU_RRR_0_OPCODE_X1 = 77,
+  V2CMPLTSI_IMM8_OPCODE_X0 = 16,
+  V2CMPLTSI_IMM8_OPCODE_X1 = 41,
+  V2CMPLTS_RRR_0_OPCODE_X0 = 122,
+  V2CMPLTS_RRR_0_OPCODE_X1 = 78,
+  V2CMPLTUI_IMM8_OPCODE_X0 = 17,
+  V2CMPLTUI_IMM8_OPCODE_X1 = 42,
+  V2CMPLTU_RRR_0_OPCODE_X0 = 123,
+  V2CMPLTU_RRR_0_OPCODE_X1 = 79,
+  V2CMPNE_RRR_0_OPCODE_X0 = 124,
+  V2CMPNE_RRR_0_OPCODE_X1 = 80,
+  V2DOTPA_RRR_0_OPCODE_X0 = 125,
+  V2DOTP_RRR_0_OPCODE_X0 = 126,
+  V2INT_H_RRR_0_OPCODE_X0 = 127,
+  V2INT_H_RRR_0_OPCODE_X1 = 81,
+  V2INT_L_RRR_0_OPCODE_X0 = 128,
+  V2INT_L_RRR_0_OPCODE_X1 = 82,
+  V2MAXSI_IMM8_OPCODE_X0 = 18,
+  V2MAXSI_IMM8_OPCODE_X1 = 43,
+  V2MAXS_RRR_0_OPCODE_X0 = 129,
+  V2MAXS_RRR_0_OPCODE_X1 = 83,
+  V2MINSI_IMM8_OPCODE_X0 = 19,
+  V2MINSI_IMM8_OPCODE_X1 = 44,
+  V2MINS_RRR_0_OPCODE_X0 = 130,
+  V2MINS_RRR_0_OPCODE_X1 = 84,
+  V2MNZ_RRR_0_OPCODE_X0 = 131,
+  V2MNZ_RRR_0_OPCODE_X1 = 85,
+  V2MULFSC_RRR_0_OPCODE_X0 = 132,
+  V2MULS_RRR_0_OPCODE_X0 = 133,
+  V2MULTS_RRR_0_OPCODE_X0 = 134,
+  V2MZ_RRR_0_OPCODE_X0 = 135,
+  V2MZ_RRR_0_OPCODE_X1 = 86,
+  V2PACKH_RRR_0_OPCODE_X0 = 136,
+  V2PACKH_RRR_0_OPCODE_X1 = 87,
+  V2PACKL_RRR_0_OPCODE_X0 = 137,
+  V2PACKL_RRR_0_OPCODE_X1 = 88,
+  V2PACKUC_RRR_0_OPCODE_X0 = 138,
+  V2PACKUC_RRR_0_OPCODE_X1 = 89,
+  V2SADAS_RRR_0_OPCODE_X0 = 139,
+  V2SADAU_RRR_0_OPCODE_X0 = 140,
+  V2SADS_RRR_0_OPCODE_X0 = 141,
+  V2SADU_RRR_0_OPCODE_X0 = 142,
+  V2SHLI_SHIFT_OPCODE_X0 = 10,
+  V2SHLI_SHIFT_OPCODE_X1 = 10,
+  V2SHLSC_RRR_0_OPCODE_X0 = 143,
+  V2SHLSC_RRR_0_OPCODE_X1 = 90,
+  V2SHL_RRR_0_OPCODE_X0 = 144,
+  V2SHL_RRR_0_OPCODE_X1 = 91,
+  V2SHRSI_SHIFT_OPCODE_X0 = 11,
+  V2SHRSI_SHIFT_OPCODE_X1 = 11,
+  V2SHRS_RRR_0_OPCODE_X0 = 145,
+  V2SHRS_RRR_0_OPCODE_X1 = 92,
+  V2SHRUI_SHIFT_OPCODE_X0 = 12,
+  V2SHRUI_SHIFT_OPCODE_X1 = 12,
+  V2SHRU_RRR_0_OPCODE_X0 = 146,
+  V2SHRU_RRR_0_OPCODE_X1 = 93,
+  V2SUBSC_RRR_0_OPCODE_X0 = 147,
+  V2SUBSC_RRR_0_OPCODE_X1 = 94,
+  V2SUB_RRR_0_OPCODE_X0 = 148,
+  V2SUB_RRR_0_OPCODE_X1 = 95,
+  V4ADDSC_RRR_0_OPCODE_X0 = 149,
+  V4ADDSC_RRR_0_OPCODE_X1 = 96,
+  V4ADD_RRR_0_OPCODE_X0 = 150,
+  V4ADD_RRR_0_OPCODE_X1 = 97,
+  V4INT_H_RRR_0_OPCODE_X0 = 151,
+  V4INT_H_RRR_0_OPCODE_X1 = 98,
+  V4INT_L_RRR_0_OPCODE_X0 = 152,
+  V4INT_L_RRR_0_OPCODE_X1 = 99,
+  V4PACKSC_RRR_0_OPCODE_X0 = 153,
+  V4PACKSC_RRR_0_OPCODE_X1 = 100,
+  V4SHLSC_RRR_0_OPCODE_X0 = 154,
+  V4SHLSC_RRR_0_OPCODE_X1 = 101,
+  V4SHL_RRR_0_OPCODE_X0 = 155,
+  V4SHL_RRR_0_OPCODE_X1 = 102,
+  V4SHRS_RRR_0_OPCODE_X0 = 156,
+  V4SHRS_RRR_0_OPCODE_X1 = 103,
+  V4SHRU_RRR_0_OPCODE_X0 = 157,
+  V4SHRU_RRR_0_OPCODE_X1 = 104,
+  V4SUBSC_RRR_0_OPCODE_X0 = 158,
+  V4SUBSC_RRR_0_OPCODE_X1 = 105,
+  V4SUB_RRR_0_OPCODE_X0 = 159,
+  V4SUB_RRR_0_OPCODE_X1 = 106,
+  WH64_UNARY_OPCODE_X1 = 38,
+  XORI_IMM8_OPCODE_X0 = 20,
+  XORI_IMM8_OPCODE_X1 = 45,
+  XOR_RRR_0_OPCODE_X0 = 160,
+  XOR_RRR_0_OPCODE_X1 = 107,
+  XOR_RRR_5_OPCODE_Y0 = 3,
+  XOR_RRR_5_OPCODE_Y1 = 3
+};
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/arch/opcode_tilepro.h linux-libre-3.2-gnu1/arch/tile/include/arch/opcode_tilepro.h
--- linux-libre-3.1-gnu1/arch/tile/include/arch/opcode_tilepro.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/arch/opcode_tilepro.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1471 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilepro_bundle_bits;
+
+/* This is the bit that determines if a bundle is in the Y encoding. */
+#define TILEPRO_BUNDLE_Y_ENCODING_MASK ((tilepro_bundle_bits)1 << 63)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEPRO_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEPRO_BUNDLE_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEPRO_BUNDLE_SIZE_IN_BYTES = 1 << TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Log base 2 of TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
+
+  /* Static network instructions take this many bytes. */
+  TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES =
+    (1 << TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEPRO_NUM_REGISTERS = 64,
+
+  /* Number of static network registers. */
+  TILEPRO_NUM_SN_REGISTERS = 4
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilepro_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEPRO_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEPRO_BPT_BUNDLE 0x400b3cae70166000ULL
+
+static __inline unsigned int
+get_BrOff_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0xf);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 2)) & 0x3);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmRROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 8)) & 0x3);
+}
+
+static __inline unsigned int
+get_JOffLong_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x18000000);
+}
+
+static __inline unsigned int
+get_JOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x08000000);
+}
+
+static __inline unsigned int
+get_MF_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x00003fff) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_MMEnd_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMEnd_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 23)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MT_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_Mode(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 63)) & 0x1);
+}
+
+static __inline unsigned int
+get_NoRegOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 10)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 56)) & 0x7);
+}
+
+static __inline unsigned int
+get_RROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 4)) & 0xf);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_RouteOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_S_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0x1);
+}
+
+static __inline unsigned int
+get_S_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilepro_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 50)) & 0x0000003e);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Src_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x7);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x7);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilepro_bundle_bits
+create_BrOff_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 2);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7f)) << 51);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmRROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 8);
+}
+
+static __inline tilepro_bundle_bits
+create_JOffLong_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x18000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_JOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x08000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_MF_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00003fff)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 23);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilepro_bundle_bits
+create_MT_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x00003fc0)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 63);
+}
+
+static __inline tilepro_bundle_bits
+create_NoRegOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 10);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 56);
+}
+
+static __inline tilepro_bundle_bits
+create_RROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 4);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1ff) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1ff)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RouteOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilepro_bundle_bits)(n & 0x0000003e)) << 50);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Src_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3ff)) << 48);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 48);
+}
+
+
+enum
+{
+  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
+  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
+  ADDB_SPECIAL_0_OPCODE_X0 = 1,
+  ADDB_SPECIAL_0_OPCODE_X1 = 1,
+  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
+  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
+  ADDH_SPECIAL_0_OPCODE_X0 = 2,
+  ADDH_SPECIAL_0_OPCODE_X1 = 2,
+  ADDIB_IMM_0_OPCODE_X0 = 1,
+  ADDIB_IMM_0_OPCODE_X1 = 1,
+  ADDIH_IMM_0_OPCODE_X0 = 2,
+  ADDIH_IMM_0_OPCODE_X1 = 2,
+  ADDI_IMM_0_OPCODE_X0 = 3,
+  ADDI_IMM_0_OPCODE_X1 = 3,
+  ADDI_IMM_1_OPCODE_SN = 1,
+  ADDI_OPCODE_Y0 = 9,
+  ADDI_OPCODE_Y1 = 7,
+  ADDLIS_OPCODE_X0 = 1,
+  ADDLIS_OPCODE_X1 = 2,
+  ADDLI_OPCODE_X0 = 2,
+  ADDLI_OPCODE_X1 = 3,
+  ADDS_SPECIAL_0_OPCODE_X0 = 96,
+  ADDS_SPECIAL_0_OPCODE_X1 = 66,
+  ADD_SPECIAL_0_OPCODE_X0 = 3,
+  ADD_SPECIAL_0_OPCODE_X1 = 3,
+  ADD_SPECIAL_0_OPCODE_Y0 = 0,
+  ADD_SPECIAL_0_OPCODE_Y1 = 0,
+  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
+  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
+  ANDI_IMM_0_OPCODE_X0 = 1,
+  ANDI_IMM_0_OPCODE_X1 = 4,
+  ANDI_OPCODE_Y0 = 10,
+  ANDI_OPCODE_Y1 = 8,
+  AND_SPECIAL_0_OPCODE_X0 = 6,
+  AND_SPECIAL_0_OPCODE_X1 = 4,
+  AND_SPECIAL_2_OPCODE_Y0 = 0,
+  AND_SPECIAL_2_OPCODE_Y1 = 0,
+  AULI_OPCODE_X0 = 3,
+  AULI_OPCODE_X1 = 4,
+  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
+  AVGH_SPECIAL_0_OPCODE_X0 = 8,
+  BBNST_BRANCH_OPCODE_X1 = 15,
+  BBNS_BRANCH_OPCODE_X1 = 14,
+  BBNS_OPCODE_SN = 63,
+  BBST_BRANCH_OPCODE_X1 = 13,
+  BBS_BRANCH_OPCODE_X1 = 12,
+  BBS_OPCODE_SN = 62,
+  BGEZT_BRANCH_OPCODE_X1 = 7,
+  BGEZ_BRANCH_OPCODE_X1 = 6,
+  BGEZ_OPCODE_SN = 61,
+  BGZT_BRANCH_OPCODE_X1 = 5,
+  BGZ_BRANCH_OPCODE_X1 = 4,
+  BGZ_OPCODE_SN = 58,
+  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
+  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
+  BLEZT_BRANCH_OPCODE_X1 = 11,
+  BLEZ_BRANCH_OPCODE_X1 = 10,
+  BLEZ_OPCODE_SN = 59,
+  BLZT_BRANCH_OPCODE_X1 = 9,
+  BLZ_BRANCH_OPCODE_X1 = 8,
+  BLZ_OPCODE_SN = 60,
+  BNZT_BRANCH_OPCODE_X1 = 3,
+  BNZ_BRANCH_OPCODE_X1 = 2,
+  BNZ_OPCODE_SN = 57,
+  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
+  BRANCH_OPCODE_X1 = 5,
+  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
+  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
+  BZT_BRANCH_OPCODE_X1 = 1,
+  BZ_BRANCH_OPCODE_X1 = 0,
+  BZ_OPCODE_SN = 56,
+  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
+  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
+  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
+  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
+  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
+  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
+  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
+  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
+  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
+  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
+  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
+  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
+  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
+  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
+  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
+  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
+  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
+  IMM_0_OPCODE_SN = 0,
+  IMM_0_OPCODE_X0 = 4,
+  IMM_0_OPCODE_X1 = 6,
+  IMM_1_OPCODE_SN = 1,
+  IMM_OPCODE_0_X0 = 5,
+  INTHB_SPECIAL_0_OPCODE_X0 = 11,
+  INTHB_SPECIAL_0_OPCODE_X1 = 5,
+  INTHH_SPECIAL_0_OPCODE_X0 = 12,
+  INTHH_SPECIAL_0_OPCODE_X1 = 6,
+  INTLB_SPECIAL_0_OPCODE_X0 = 13,
+  INTLB_SPECIAL_0_OPCODE_X1 = 7,
+  INTLH_SPECIAL_0_OPCODE_X0 = 14,
+  INTLH_SPECIAL_0_OPCODE_X1 = 8,
+  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
+  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
+  JALB_OPCODE_X1 = 13,
+  JALF_OPCODE_X1 = 12,
+  JALRP_SPECIAL_0_OPCODE_X1 = 9,
+  JALRR_IMM_1_OPCODE_SN = 3,
+  JALR_RR_IMM_0_OPCODE_SN = 5,
+  JALR_SPECIAL_0_OPCODE_X1 = 10,
+  JB_OPCODE_X1 = 11,
+  JF_OPCODE_X1 = 10,
+  JRP_SPECIAL_0_OPCODE_X1 = 11,
+  JRR_IMM_1_OPCODE_SN = 2,
+  JR_RR_IMM_0_OPCODE_SN = 4,
+  JR_SPECIAL_0_OPCODE_X1 = 12,
+  LBADD_IMM_0_OPCODE_X1 = 22,
+  LBADD_U_IMM_0_OPCODE_X1 = 23,
+  LB_OPCODE_Y2 = 0,
+  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
+  LB_U_OPCODE_Y2 = 1,
+  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
+  LHADD_IMM_0_OPCODE_X1 = 24,
+  LHADD_U_IMM_0_OPCODE_X1 = 25,
+  LH_OPCODE_Y2 = 2,
+  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
+  LH_U_OPCODE_Y2 = 3,
+  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
+  LNK_SPECIAL_0_OPCODE_X1 = 13,
+  LWADD_IMM_0_OPCODE_X1 = 26,
+  LWADD_NA_IMM_0_OPCODE_X1 = 27,
+  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
+  LW_OPCODE_Y2 = 4,
+  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
+  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
+  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
+  MAXH_SPECIAL_0_OPCODE_X0 = 16,
+  MAXH_SPECIAL_0_OPCODE_X1 = 15,
+  MAXIB_U_IMM_0_OPCODE_X0 = 4,
+  MAXIB_U_IMM_0_OPCODE_X1 = 5,
+  MAXIH_IMM_0_OPCODE_X0 = 5,
+  MAXIH_IMM_0_OPCODE_X1 = 6,
+  MFSPR_IMM_0_OPCODE_X1 = 7,
+  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
+  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
+  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
+  MINH_SPECIAL_0_OPCODE_X0 = 18,
+  MINH_SPECIAL_0_OPCODE_X1 = 17,
+  MINIB_U_IMM_0_OPCODE_X0 = 6,
+  MINIB_U_IMM_0_OPCODE_X1 = 8,
+  MINIH_IMM_0_OPCODE_X0 = 7,
+  MINIH_IMM_0_OPCODE_X1 = 9,
+  MM_OPCODE_X0 = 6,
+  MM_OPCODE_X1 = 7,
+  MNZB_SPECIAL_0_OPCODE_X0 = 19,
+  MNZB_SPECIAL_0_OPCODE_X1 = 18,
+  MNZH_SPECIAL_0_OPCODE_X0 = 20,
+  MNZH_SPECIAL_0_OPCODE_X1 = 19,
+  MNZ_SPECIAL_0_OPCODE_X0 = 21,
+  MNZ_SPECIAL_0_OPCODE_X1 = 20,
+  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
+  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
+  MOVEI_IMM_1_OPCODE_SN = 0,
+  MOVE_RR_IMM_0_OPCODE_SN = 8,
+  MTSPR_IMM_0_OPCODE_X1 = 10,
+  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
+  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
+  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
+  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
+  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
+  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
+  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
+  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
+  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
+  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
+  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
+  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
+  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
+  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
+  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
+  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
+  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
+  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
+  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
+  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
+  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
+  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
+  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
+  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
+  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
+  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
+  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
+  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
+  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
+  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
+  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
+  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
+  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
+  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
+  MVZ_SPECIAL_0_OPCODE_X0 = 46,
+  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
+  MZB_SPECIAL_0_OPCODE_X0 = 47,
+  MZB_SPECIAL_0_OPCODE_X1 = 21,
+  MZH_SPECIAL_0_OPCODE_X0 = 48,
+  MZH_SPECIAL_0_OPCODE_X1 = 22,
+  MZ_SPECIAL_0_OPCODE_X0 = 49,
+  MZ_SPECIAL_0_OPCODE_X1 = 23,
+  MZ_SPECIAL_1_OPCODE_Y0 = 3,
+  MZ_SPECIAL_1_OPCODE_Y1 = 2,
+  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
+  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
+  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
+  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
+  NOREG_RR_IMM_0_OPCODE_SN = 0,
+  NOR_SPECIAL_0_OPCODE_X0 = 50,
+  NOR_SPECIAL_0_OPCODE_X1 = 24,
+  NOR_SPECIAL_2_OPCODE_Y0 = 1,
+  NOR_SPECIAL_2_OPCODE_Y1 = 1,
+  ORI_IMM_0_OPCODE_X0 = 8,
+  ORI_IMM_0_OPCODE_X1 = 11,
+  ORI_OPCODE_Y0 = 11,
+  ORI_OPCODE_Y1 = 9,
+  OR_SPECIAL_0_OPCODE_X0 = 51,
+  OR_SPECIAL_0_OPCODE_X1 = 25,
+  OR_SPECIAL_2_OPCODE_Y0 = 2,
+  OR_SPECIAL_2_OPCODE_Y1 = 2,
+  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
+  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
+  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
+  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
+  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
+  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
+  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
+  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
+  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
+  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
+  RLI_SHUN_0_OPCODE_X0 = 1,
+  RLI_SHUN_0_OPCODE_X1 = 1,
+  RLI_SHUN_0_OPCODE_Y0 = 1,
+  RLI_SHUN_0_OPCODE_Y1 = 1,
+  RL_SPECIAL_0_OPCODE_X0 = 54,
+  RL_SPECIAL_0_OPCODE_X1 = 28,
+  RL_SPECIAL_3_OPCODE_Y0 = 0,
+  RL_SPECIAL_3_OPCODE_Y1 = 0,
+  RR_IMM_0_OPCODE_SN = 0,
+  S1A_SPECIAL_0_OPCODE_X0 = 55,
+  S1A_SPECIAL_0_OPCODE_X1 = 29,
+  S1A_SPECIAL_0_OPCODE_Y0 = 1,
+  S1A_SPECIAL_0_OPCODE_Y1 = 1,
+  S2A_SPECIAL_0_OPCODE_X0 = 56,
+  S2A_SPECIAL_0_OPCODE_X1 = 30,
+  S2A_SPECIAL_0_OPCODE_Y0 = 2,
+  S2A_SPECIAL_0_OPCODE_Y1 = 2,
+  S3A_SPECIAL_0_OPCODE_X0 = 57,
+  S3A_SPECIAL_0_OPCODE_X1 = 31,
+  S3A_SPECIAL_5_OPCODE_Y0 = 1,
+  S3A_SPECIAL_5_OPCODE_Y1 = 1,
+  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
+  SADAH_SPECIAL_0_OPCODE_X0 = 59,
+  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
+  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
+  SADH_SPECIAL_0_OPCODE_X0 = 62,
+  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
+  SBADD_IMM_0_OPCODE_X1 = 28,
+  SB_OPCODE_Y2 = 5,
+  SB_SPECIAL_0_OPCODE_X1 = 32,
+  SEQB_SPECIAL_0_OPCODE_X0 = 64,
+  SEQB_SPECIAL_0_OPCODE_X1 = 33,
+  SEQH_SPECIAL_0_OPCODE_X0 = 65,
+  SEQH_SPECIAL_0_OPCODE_X1 = 34,
+  SEQIB_IMM_0_OPCODE_X0 = 9,
+  SEQIB_IMM_0_OPCODE_X1 = 12,
+  SEQIH_IMM_0_OPCODE_X0 = 10,
+  SEQIH_IMM_0_OPCODE_X1 = 13,
+  SEQI_IMM_0_OPCODE_X0 = 11,
+  SEQI_IMM_0_OPCODE_X1 = 14,
+  SEQI_OPCODE_Y0 = 12,
+  SEQI_OPCODE_Y1 = 10,
+  SEQ_SPECIAL_0_OPCODE_X0 = 66,
+  SEQ_SPECIAL_0_OPCODE_X1 = 35,
+  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
+  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
+  SHADD_IMM_0_OPCODE_X1 = 29,
+  SHL8II_IMM_0_OPCODE_SN = 3,
+  SHLB_SPECIAL_0_OPCODE_X0 = 67,
+  SHLB_SPECIAL_0_OPCODE_X1 = 36,
+  SHLH_SPECIAL_0_OPCODE_X0 = 68,
+  SHLH_SPECIAL_0_OPCODE_X1 = 37,
+  SHLIB_SHUN_0_OPCODE_X0 = 2,
+  SHLIB_SHUN_0_OPCODE_X1 = 2,
+  SHLIH_SHUN_0_OPCODE_X0 = 3,
+  SHLIH_SHUN_0_OPCODE_X1 = 3,
+  SHLI_SHUN_0_OPCODE_X0 = 4,
+  SHLI_SHUN_0_OPCODE_X1 = 4,
+  SHLI_SHUN_0_OPCODE_Y0 = 2,
+  SHLI_SHUN_0_OPCODE_Y1 = 2,
+  SHL_SPECIAL_0_OPCODE_X0 = 69,
+  SHL_SPECIAL_0_OPCODE_X1 = 38,
+  SHL_SPECIAL_3_OPCODE_Y0 = 1,
+  SHL_SPECIAL_3_OPCODE_Y1 = 1,
+  SHR1_RR_IMM_0_OPCODE_SN = 9,
+  SHRB_SPECIAL_0_OPCODE_X0 = 70,
+  SHRB_SPECIAL_0_OPCODE_X1 = 39,
+  SHRH_SPECIAL_0_OPCODE_X0 = 71,
+  SHRH_SPECIAL_0_OPCODE_X1 = 40,
+  SHRIB_SHUN_0_OPCODE_X0 = 5,
+  SHRIB_SHUN_0_OPCODE_X1 = 5,
+  SHRIH_SHUN_0_OPCODE_X0 = 6,
+  SHRIH_SHUN_0_OPCODE_X1 = 6,
+  SHRI_SHUN_0_OPCODE_X0 = 7,
+  SHRI_SHUN_0_OPCODE_X1 = 7,
+  SHRI_SHUN_0_OPCODE_Y0 = 3,
+  SHRI_SHUN_0_OPCODE_Y1 = 3,
+  SHR_SPECIAL_0_OPCODE_X0 = 72,
+  SHR_SPECIAL_0_OPCODE_X1 = 41,
+  SHR_SPECIAL_3_OPCODE_Y0 = 2,
+  SHR_SPECIAL_3_OPCODE_Y1 = 2,
+  SHUN_0_OPCODE_X0 = 7,
+  SHUN_0_OPCODE_X1 = 8,
+  SHUN_0_OPCODE_Y0 = 13,
+  SHUN_0_OPCODE_Y1 = 11,
+  SH_OPCODE_Y2 = 6,
+  SH_SPECIAL_0_OPCODE_X1 = 42,
+  SLTB_SPECIAL_0_OPCODE_X0 = 73,
+  SLTB_SPECIAL_0_OPCODE_X1 = 43,
+  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
+  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
+  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
+  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
+  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
+  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
+  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
+  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
+  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
+  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
+  SLTE_SPECIAL_0_OPCODE_X0 = 79,
+  SLTE_SPECIAL_0_OPCODE_X1 = 49,
+  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
+  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
+  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
+  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
+  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
+  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
+  SLTH_SPECIAL_0_OPCODE_X0 = 81,
+  SLTH_SPECIAL_0_OPCODE_X1 = 51,
+  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
+  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
+  SLTIB_IMM_0_OPCODE_X0 = 12,
+  SLTIB_IMM_0_OPCODE_X1 = 15,
+  SLTIB_U_IMM_0_OPCODE_X0 = 13,
+  SLTIB_U_IMM_0_OPCODE_X1 = 16,
+  SLTIH_IMM_0_OPCODE_X0 = 14,
+  SLTIH_IMM_0_OPCODE_X1 = 17,
+  SLTIH_U_IMM_0_OPCODE_X0 = 15,
+  SLTIH_U_IMM_0_OPCODE_X1 = 18,
+  SLTI_IMM_0_OPCODE_X0 = 16,
+  SLTI_IMM_0_OPCODE_X1 = 19,
+  SLTI_OPCODE_Y0 = 14,
+  SLTI_OPCODE_Y1 = 12,
+  SLTI_U_IMM_0_OPCODE_X0 = 17,
+  SLTI_U_IMM_0_OPCODE_X1 = 20,
+  SLTI_U_OPCODE_Y0 = 15,
+  SLTI_U_OPCODE_Y1 = 13,
+  SLT_SPECIAL_0_OPCODE_X0 = 83,
+  SLT_SPECIAL_0_OPCODE_X1 = 53,
+  SLT_SPECIAL_4_OPCODE_Y0 = 2,
+  SLT_SPECIAL_4_OPCODE_Y1 = 2,
+  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
+  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
+  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
+  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
+  SNEB_SPECIAL_0_OPCODE_X0 = 85,
+  SNEB_SPECIAL_0_OPCODE_X1 = 55,
+  SNEH_SPECIAL_0_OPCODE_X0 = 86,
+  SNEH_SPECIAL_0_OPCODE_X1 = 56,
+  SNE_SPECIAL_0_OPCODE_X0 = 87,
+  SNE_SPECIAL_0_OPCODE_X1 = 57,
+  SNE_SPECIAL_5_OPCODE_Y0 = 3,
+  SNE_SPECIAL_5_OPCODE_Y1 = 3,
+  SPECIAL_0_OPCODE_X0 = 0,
+  SPECIAL_0_OPCODE_X1 = 1,
+  SPECIAL_0_OPCODE_Y0 = 1,
+  SPECIAL_0_OPCODE_Y1 = 1,
+  SPECIAL_1_OPCODE_Y0 = 2,
+  SPECIAL_1_OPCODE_Y1 = 2,
+  SPECIAL_2_OPCODE_Y0 = 3,
+  SPECIAL_2_OPCODE_Y1 = 3,
+  SPECIAL_3_OPCODE_Y0 = 4,
+  SPECIAL_3_OPCODE_Y1 = 4,
+  SPECIAL_4_OPCODE_Y0 = 5,
+  SPECIAL_4_OPCODE_Y1 = 5,
+  SPECIAL_5_OPCODE_Y0 = 6,
+  SPECIAL_5_OPCODE_Y1 = 6,
+  SPECIAL_6_OPCODE_Y0 = 7,
+  SPECIAL_7_OPCODE_Y0 = 8,
+  SRAB_SPECIAL_0_OPCODE_X0 = 88,
+  SRAB_SPECIAL_0_OPCODE_X1 = 58,
+  SRAH_SPECIAL_0_OPCODE_X0 = 89,
+  SRAH_SPECIAL_0_OPCODE_X1 = 59,
+  SRAIB_SHUN_0_OPCODE_X0 = 8,
+  SRAIB_SHUN_0_OPCODE_X1 = 8,
+  SRAIH_SHUN_0_OPCODE_X0 = 9,
+  SRAIH_SHUN_0_OPCODE_X1 = 9,
+  SRAI_SHUN_0_OPCODE_X0 = 10,
+  SRAI_SHUN_0_OPCODE_X1 = 10,
+  SRAI_SHUN_0_OPCODE_Y0 = 4,
+  SRAI_SHUN_0_OPCODE_Y1 = 4,
+  SRA_SPECIAL_0_OPCODE_X0 = 90,
+  SRA_SPECIAL_0_OPCODE_X1 = 60,
+  SRA_SPECIAL_3_OPCODE_Y0 = 3,
+  SRA_SPECIAL_3_OPCODE_Y1 = 3,
+  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
+  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
+  SUBB_SPECIAL_0_OPCODE_X0 = 91,
+  SUBB_SPECIAL_0_OPCODE_X1 = 61,
+  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
+  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
+  SUBH_SPECIAL_0_OPCODE_X0 = 92,
+  SUBH_SPECIAL_0_OPCODE_X1 = 62,
+  SUBS_SPECIAL_0_OPCODE_X0 = 97,
+  SUBS_SPECIAL_0_OPCODE_X1 = 67,
+  SUB_SPECIAL_0_OPCODE_X0 = 93,
+  SUB_SPECIAL_0_OPCODE_X1 = 63,
+  SUB_SPECIAL_0_OPCODE_Y0 = 3,
+  SUB_SPECIAL_0_OPCODE_Y1 = 3,
+  SWADD_IMM_0_OPCODE_X1 = 30,
+  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
+  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
+  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
+  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
+  SW_OPCODE_Y2 = 7,
+  SW_SPECIAL_0_OPCODE_X1 = 64,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
+  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
+  UN_0_SHUN_0_OPCODE_X0 = 11,
+  UN_0_SHUN_0_OPCODE_X1 = 11,
+  UN_0_SHUN_0_OPCODE_Y0 = 5,
+  UN_0_SHUN_0_OPCODE_Y1 = 5,
+  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
+  XORI_IMM_0_OPCODE_X0 = 2,
+  XORI_IMM_0_OPCODE_X1 = 21,
+  XOR_SPECIAL_0_OPCODE_X0 = 94,
+  XOR_SPECIAL_0_OPCODE_X1 = 65,
+  XOR_SPECIAL_2_OPCODE_Y0 = 3,
+  XOR_SPECIAL_2_OPCODE_Y1 = 3
+};
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/irq.h linux-libre-3.2-gnu1/arch/tile/include/asm/irq.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,16 +74,6 @@ enum {
  */
 void tile_irq_activate(unsigned int irq, int tile_irq_type);
 
-/*
- * For onboard, non-PCI (e.g. TILE_IRQ_PERCPU) devices, drivers know
- * how to use enable/disable_percpu_irq() to manage interrupts on each
- * core.  We can't use the generic enable/disable_irq() because they
- * use a single reference count per irq, rather than per cpu per irq.
- */
-void enable_percpu_irq(unsigned int irq);
-void disable_percpu_irq(unsigned int irq);
-
-
 void setup_irq_regs(void);
 
 #endif /* _ASM_TILE_IRQ_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/Kbuild linux-libre-3.2-gnu1/arch/tile/include/asm/Kbuild
--- linux-libre-3.1-gnu1/arch/tile/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,7 @@
 include include/asm-generic/Kbuild.asm
 
+header-y += ../arch/
+
 header-y += ucontext.h
 header-y += hardwall.h
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants_32.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants_32.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,480 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-/* This file is machine-generated; DO NOT EDIT! */
-
-
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
-enum
-{
-  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
-  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
-  ADDB_SPECIAL_0_OPCODE_X0 = 1,
-  ADDB_SPECIAL_0_OPCODE_X1 = 1,
-  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
-  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
-  ADDH_SPECIAL_0_OPCODE_X0 = 2,
-  ADDH_SPECIAL_0_OPCODE_X1 = 2,
-  ADDIB_IMM_0_OPCODE_X0 = 1,
-  ADDIB_IMM_0_OPCODE_X1 = 1,
-  ADDIH_IMM_0_OPCODE_X0 = 2,
-  ADDIH_IMM_0_OPCODE_X1 = 2,
-  ADDI_IMM_0_OPCODE_X0 = 3,
-  ADDI_IMM_0_OPCODE_X1 = 3,
-  ADDI_IMM_1_OPCODE_SN = 1,
-  ADDI_OPCODE_Y0 = 9,
-  ADDI_OPCODE_Y1 = 7,
-  ADDLIS_OPCODE_X0 = 1,
-  ADDLIS_OPCODE_X1 = 2,
-  ADDLI_OPCODE_X0 = 2,
-  ADDLI_OPCODE_X1 = 3,
-  ADDS_SPECIAL_0_OPCODE_X0 = 96,
-  ADDS_SPECIAL_0_OPCODE_X1 = 66,
-  ADD_SPECIAL_0_OPCODE_X0 = 3,
-  ADD_SPECIAL_0_OPCODE_X1 = 3,
-  ADD_SPECIAL_0_OPCODE_Y0 = 0,
-  ADD_SPECIAL_0_OPCODE_Y1 = 0,
-  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
-  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
-  ANDI_IMM_0_OPCODE_X0 = 1,
-  ANDI_IMM_0_OPCODE_X1 = 4,
-  ANDI_OPCODE_Y0 = 10,
-  ANDI_OPCODE_Y1 = 8,
-  AND_SPECIAL_0_OPCODE_X0 = 6,
-  AND_SPECIAL_0_OPCODE_X1 = 4,
-  AND_SPECIAL_2_OPCODE_Y0 = 0,
-  AND_SPECIAL_2_OPCODE_Y1 = 0,
-  AULI_OPCODE_X0 = 3,
-  AULI_OPCODE_X1 = 4,
-  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
-  AVGH_SPECIAL_0_OPCODE_X0 = 8,
-  BBNST_BRANCH_OPCODE_X1 = 15,
-  BBNS_BRANCH_OPCODE_X1 = 14,
-  BBNS_OPCODE_SN = 63,
-  BBST_BRANCH_OPCODE_X1 = 13,
-  BBS_BRANCH_OPCODE_X1 = 12,
-  BBS_OPCODE_SN = 62,
-  BGEZT_BRANCH_OPCODE_X1 = 7,
-  BGEZ_BRANCH_OPCODE_X1 = 6,
-  BGEZ_OPCODE_SN = 61,
-  BGZT_BRANCH_OPCODE_X1 = 5,
-  BGZ_BRANCH_OPCODE_X1 = 4,
-  BGZ_OPCODE_SN = 58,
-  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
-  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
-  BLEZT_BRANCH_OPCODE_X1 = 11,
-  BLEZ_BRANCH_OPCODE_X1 = 10,
-  BLEZ_OPCODE_SN = 59,
-  BLZT_BRANCH_OPCODE_X1 = 9,
-  BLZ_BRANCH_OPCODE_X1 = 8,
-  BLZ_OPCODE_SN = 60,
-  BNZT_BRANCH_OPCODE_X1 = 3,
-  BNZ_BRANCH_OPCODE_X1 = 2,
-  BNZ_OPCODE_SN = 57,
-  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
-  BRANCH_OPCODE_X1 = 5,
-  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
-  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
-  BZT_BRANCH_OPCODE_X1 = 1,
-  BZ_BRANCH_OPCODE_X1 = 0,
-  BZ_OPCODE_SN = 56,
-  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
-  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
-  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
-  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
-  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
-  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
-  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
-  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
-  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
-  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
-  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
-  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
-  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
-  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
-  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
-  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
-  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
-  IMM_0_OPCODE_SN = 0,
-  IMM_0_OPCODE_X0 = 4,
-  IMM_0_OPCODE_X1 = 6,
-  IMM_1_OPCODE_SN = 1,
-  IMM_OPCODE_0_X0 = 5,
-  INTHB_SPECIAL_0_OPCODE_X0 = 11,
-  INTHB_SPECIAL_0_OPCODE_X1 = 5,
-  INTHH_SPECIAL_0_OPCODE_X0 = 12,
-  INTHH_SPECIAL_0_OPCODE_X1 = 6,
-  INTLB_SPECIAL_0_OPCODE_X0 = 13,
-  INTLB_SPECIAL_0_OPCODE_X1 = 7,
-  INTLH_SPECIAL_0_OPCODE_X0 = 14,
-  INTLH_SPECIAL_0_OPCODE_X1 = 8,
-  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
-  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
-  JALB_OPCODE_X1 = 13,
-  JALF_OPCODE_X1 = 12,
-  JALRP_SPECIAL_0_OPCODE_X1 = 9,
-  JALRR_IMM_1_OPCODE_SN = 3,
-  JALR_RR_IMM_0_OPCODE_SN = 5,
-  JALR_SPECIAL_0_OPCODE_X1 = 10,
-  JB_OPCODE_X1 = 11,
-  JF_OPCODE_X1 = 10,
-  JRP_SPECIAL_0_OPCODE_X1 = 11,
-  JRR_IMM_1_OPCODE_SN = 2,
-  JR_RR_IMM_0_OPCODE_SN = 4,
-  JR_SPECIAL_0_OPCODE_X1 = 12,
-  LBADD_IMM_0_OPCODE_X1 = 22,
-  LBADD_U_IMM_0_OPCODE_X1 = 23,
-  LB_OPCODE_Y2 = 0,
-  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
-  LB_U_OPCODE_Y2 = 1,
-  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
-  LHADD_IMM_0_OPCODE_X1 = 24,
-  LHADD_U_IMM_0_OPCODE_X1 = 25,
-  LH_OPCODE_Y2 = 2,
-  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
-  LH_U_OPCODE_Y2 = 3,
-  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
-  LNK_SPECIAL_0_OPCODE_X1 = 13,
-  LWADD_IMM_0_OPCODE_X1 = 26,
-  LWADD_NA_IMM_0_OPCODE_X1 = 27,
-  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
-  LW_OPCODE_Y2 = 4,
-  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
-  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
-  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
-  MAXH_SPECIAL_0_OPCODE_X0 = 16,
-  MAXH_SPECIAL_0_OPCODE_X1 = 15,
-  MAXIB_U_IMM_0_OPCODE_X0 = 4,
-  MAXIB_U_IMM_0_OPCODE_X1 = 5,
-  MAXIH_IMM_0_OPCODE_X0 = 5,
-  MAXIH_IMM_0_OPCODE_X1 = 6,
-  MFSPR_IMM_0_OPCODE_X1 = 7,
-  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
-  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
-  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
-  MINH_SPECIAL_0_OPCODE_X0 = 18,
-  MINH_SPECIAL_0_OPCODE_X1 = 17,
-  MINIB_U_IMM_0_OPCODE_X0 = 6,
-  MINIB_U_IMM_0_OPCODE_X1 = 8,
-  MINIH_IMM_0_OPCODE_X0 = 7,
-  MINIH_IMM_0_OPCODE_X1 = 9,
-  MM_OPCODE_X0 = 6,
-  MM_OPCODE_X1 = 7,
-  MNZB_SPECIAL_0_OPCODE_X0 = 19,
-  MNZB_SPECIAL_0_OPCODE_X1 = 18,
-  MNZH_SPECIAL_0_OPCODE_X0 = 20,
-  MNZH_SPECIAL_0_OPCODE_X1 = 19,
-  MNZ_SPECIAL_0_OPCODE_X0 = 21,
-  MNZ_SPECIAL_0_OPCODE_X1 = 20,
-  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
-  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
-  MOVEI_IMM_1_OPCODE_SN = 0,
-  MOVE_RR_IMM_0_OPCODE_SN = 8,
-  MTSPR_IMM_0_OPCODE_X1 = 10,
-  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
-  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
-  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
-  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
-  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
-  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
-  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
-  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
-  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
-  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
-  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
-  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
-  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
-  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
-  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
-  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
-  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
-  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
-  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
-  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
-  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
-  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
-  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
-  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
-  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
-  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
-  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
-  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
-  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
-  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
-  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
-  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
-  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
-  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
-  MVZ_SPECIAL_0_OPCODE_X0 = 46,
-  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
-  MZB_SPECIAL_0_OPCODE_X0 = 47,
-  MZB_SPECIAL_0_OPCODE_X1 = 21,
-  MZH_SPECIAL_0_OPCODE_X0 = 48,
-  MZH_SPECIAL_0_OPCODE_X1 = 22,
-  MZ_SPECIAL_0_OPCODE_X0 = 49,
-  MZ_SPECIAL_0_OPCODE_X1 = 23,
-  MZ_SPECIAL_1_OPCODE_Y0 = 3,
-  MZ_SPECIAL_1_OPCODE_Y1 = 2,
-  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
-  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
-  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
-  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
-  NOREG_RR_IMM_0_OPCODE_SN = 0,
-  NOR_SPECIAL_0_OPCODE_X0 = 50,
-  NOR_SPECIAL_0_OPCODE_X1 = 24,
-  NOR_SPECIAL_2_OPCODE_Y0 = 1,
-  NOR_SPECIAL_2_OPCODE_Y1 = 1,
-  ORI_IMM_0_OPCODE_X0 = 8,
-  ORI_IMM_0_OPCODE_X1 = 11,
-  ORI_OPCODE_Y0 = 11,
-  ORI_OPCODE_Y1 = 9,
-  OR_SPECIAL_0_OPCODE_X0 = 51,
-  OR_SPECIAL_0_OPCODE_X1 = 25,
-  OR_SPECIAL_2_OPCODE_Y0 = 2,
-  OR_SPECIAL_2_OPCODE_Y1 = 2,
-  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
-  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
-  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
-  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
-  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
-  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
-  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
-  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
-  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
-  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
-  RLI_SHUN_0_OPCODE_X0 = 1,
-  RLI_SHUN_0_OPCODE_X1 = 1,
-  RLI_SHUN_0_OPCODE_Y0 = 1,
-  RLI_SHUN_0_OPCODE_Y1 = 1,
-  RL_SPECIAL_0_OPCODE_X0 = 54,
-  RL_SPECIAL_0_OPCODE_X1 = 28,
-  RL_SPECIAL_3_OPCODE_Y0 = 0,
-  RL_SPECIAL_3_OPCODE_Y1 = 0,
-  RR_IMM_0_OPCODE_SN = 0,
-  S1A_SPECIAL_0_OPCODE_X0 = 55,
-  S1A_SPECIAL_0_OPCODE_X1 = 29,
-  S1A_SPECIAL_0_OPCODE_Y0 = 1,
-  S1A_SPECIAL_0_OPCODE_Y1 = 1,
-  S2A_SPECIAL_0_OPCODE_X0 = 56,
-  S2A_SPECIAL_0_OPCODE_X1 = 30,
-  S2A_SPECIAL_0_OPCODE_Y0 = 2,
-  S2A_SPECIAL_0_OPCODE_Y1 = 2,
-  S3A_SPECIAL_0_OPCODE_X0 = 57,
-  S3A_SPECIAL_0_OPCODE_X1 = 31,
-  S3A_SPECIAL_5_OPCODE_Y0 = 1,
-  S3A_SPECIAL_5_OPCODE_Y1 = 1,
-  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
-  SADAH_SPECIAL_0_OPCODE_X0 = 59,
-  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
-  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
-  SADH_SPECIAL_0_OPCODE_X0 = 62,
-  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
-  SBADD_IMM_0_OPCODE_X1 = 28,
-  SB_OPCODE_Y2 = 5,
-  SB_SPECIAL_0_OPCODE_X1 = 32,
-  SEQB_SPECIAL_0_OPCODE_X0 = 64,
-  SEQB_SPECIAL_0_OPCODE_X1 = 33,
-  SEQH_SPECIAL_0_OPCODE_X0 = 65,
-  SEQH_SPECIAL_0_OPCODE_X1 = 34,
-  SEQIB_IMM_0_OPCODE_X0 = 9,
-  SEQIB_IMM_0_OPCODE_X1 = 12,
-  SEQIH_IMM_0_OPCODE_X0 = 10,
-  SEQIH_IMM_0_OPCODE_X1 = 13,
-  SEQI_IMM_0_OPCODE_X0 = 11,
-  SEQI_IMM_0_OPCODE_X1 = 14,
-  SEQI_OPCODE_Y0 = 12,
-  SEQI_OPCODE_Y1 = 10,
-  SEQ_SPECIAL_0_OPCODE_X0 = 66,
-  SEQ_SPECIAL_0_OPCODE_X1 = 35,
-  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
-  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
-  SHADD_IMM_0_OPCODE_X1 = 29,
-  SHL8II_IMM_0_OPCODE_SN = 3,
-  SHLB_SPECIAL_0_OPCODE_X0 = 67,
-  SHLB_SPECIAL_0_OPCODE_X1 = 36,
-  SHLH_SPECIAL_0_OPCODE_X0 = 68,
-  SHLH_SPECIAL_0_OPCODE_X1 = 37,
-  SHLIB_SHUN_0_OPCODE_X0 = 2,
-  SHLIB_SHUN_0_OPCODE_X1 = 2,
-  SHLIH_SHUN_0_OPCODE_X0 = 3,
-  SHLIH_SHUN_0_OPCODE_X1 = 3,
-  SHLI_SHUN_0_OPCODE_X0 = 4,
-  SHLI_SHUN_0_OPCODE_X1 = 4,
-  SHLI_SHUN_0_OPCODE_Y0 = 2,
-  SHLI_SHUN_0_OPCODE_Y1 = 2,
-  SHL_SPECIAL_0_OPCODE_X0 = 69,
-  SHL_SPECIAL_0_OPCODE_X1 = 38,
-  SHL_SPECIAL_3_OPCODE_Y0 = 1,
-  SHL_SPECIAL_3_OPCODE_Y1 = 1,
-  SHR1_RR_IMM_0_OPCODE_SN = 9,
-  SHRB_SPECIAL_0_OPCODE_X0 = 70,
-  SHRB_SPECIAL_0_OPCODE_X1 = 39,
-  SHRH_SPECIAL_0_OPCODE_X0 = 71,
-  SHRH_SPECIAL_0_OPCODE_X1 = 40,
-  SHRIB_SHUN_0_OPCODE_X0 = 5,
-  SHRIB_SHUN_0_OPCODE_X1 = 5,
-  SHRIH_SHUN_0_OPCODE_X0 = 6,
-  SHRIH_SHUN_0_OPCODE_X1 = 6,
-  SHRI_SHUN_0_OPCODE_X0 = 7,
-  SHRI_SHUN_0_OPCODE_X1 = 7,
-  SHRI_SHUN_0_OPCODE_Y0 = 3,
-  SHRI_SHUN_0_OPCODE_Y1 = 3,
-  SHR_SPECIAL_0_OPCODE_X0 = 72,
-  SHR_SPECIAL_0_OPCODE_X1 = 41,
-  SHR_SPECIAL_3_OPCODE_Y0 = 2,
-  SHR_SPECIAL_3_OPCODE_Y1 = 2,
-  SHUN_0_OPCODE_X0 = 7,
-  SHUN_0_OPCODE_X1 = 8,
-  SHUN_0_OPCODE_Y0 = 13,
-  SHUN_0_OPCODE_Y1 = 11,
-  SH_OPCODE_Y2 = 6,
-  SH_SPECIAL_0_OPCODE_X1 = 42,
-  SLTB_SPECIAL_0_OPCODE_X0 = 73,
-  SLTB_SPECIAL_0_OPCODE_X1 = 43,
-  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
-  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
-  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
-  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
-  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
-  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
-  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
-  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
-  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
-  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
-  SLTE_SPECIAL_0_OPCODE_X0 = 79,
-  SLTE_SPECIAL_0_OPCODE_X1 = 49,
-  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
-  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
-  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
-  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
-  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
-  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
-  SLTH_SPECIAL_0_OPCODE_X0 = 81,
-  SLTH_SPECIAL_0_OPCODE_X1 = 51,
-  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
-  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
-  SLTIB_IMM_0_OPCODE_X0 = 12,
-  SLTIB_IMM_0_OPCODE_X1 = 15,
-  SLTIB_U_IMM_0_OPCODE_X0 = 13,
-  SLTIB_U_IMM_0_OPCODE_X1 = 16,
-  SLTIH_IMM_0_OPCODE_X0 = 14,
-  SLTIH_IMM_0_OPCODE_X1 = 17,
-  SLTIH_U_IMM_0_OPCODE_X0 = 15,
-  SLTIH_U_IMM_0_OPCODE_X1 = 18,
-  SLTI_IMM_0_OPCODE_X0 = 16,
-  SLTI_IMM_0_OPCODE_X1 = 19,
-  SLTI_OPCODE_Y0 = 14,
-  SLTI_OPCODE_Y1 = 12,
-  SLTI_U_IMM_0_OPCODE_X0 = 17,
-  SLTI_U_IMM_0_OPCODE_X1 = 20,
-  SLTI_U_OPCODE_Y0 = 15,
-  SLTI_U_OPCODE_Y1 = 13,
-  SLT_SPECIAL_0_OPCODE_X0 = 83,
-  SLT_SPECIAL_0_OPCODE_X1 = 53,
-  SLT_SPECIAL_4_OPCODE_Y0 = 2,
-  SLT_SPECIAL_4_OPCODE_Y1 = 2,
-  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
-  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
-  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
-  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
-  SNEB_SPECIAL_0_OPCODE_X0 = 85,
-  SNEB_SPECIAL_0_OPCODE_X1 = 55,
-  SNEH_SPECIAL_0_OPCODE_X0 = 86,
-  SNEH_SPECIAL_0_OPCODE_X1 = 56,
-  SNE_SPECIAL_0_OPCODE_X0 = 87,
-  SNE_SPECIAL_0_OPCODE_X1 = 57,
-  SNE_SPECIAL_5_OPCODE_Y0 = 3,
-  SNE_SPECIAL_5_OPCODE_Y1 = 3,
-  SPECIAL_0_OPCODE_X0 = 0,
-  SPECIAL_0_OPCODE_X1 = 1,
-  SPECIAL_0_OPCODE_Y0 = 1,
-  SPECIAL_0_OPCODE_Y1 = 1,
-  SPECIAL_1_OPCODE_Y0 = 2,
-  SPECIAL_1_OPCODE_Y1 = 2,
-  SPECIAL_2_OPCODE_Y0 = 3,
-  SPECIAL_2_OPCODE_Y1 = 3,
-  SPECIAL_3_OPCODE_Y0 = 4,
-  SPECIAL_3_OPCODE_Y1 = 4,
-  SPECIAL_4_OPCODE_Y0 = 5,
-  SPECIAL_4_OPCODE_Y1 = 5,
-  SPECIAL_5_OPCODE_Y0 = 6,
-  SPECIAL_5_OPCODE_Y1 = 6,
-  SPECIAL_6_OPCODE_Y0 = 7,
-  SPECIAL_7_OPCODE_Y0 = 8,
-  SRAB_SPECIAL_0_OPCODE_X0 = 88,
-  SRAB_SPECIAL_0_OPCODE_X1 = 58,
-  SRAH_SPECIAL_0_OPCODE_X0 = 89,
-  SRAH_SPECIAL_0_OPCODE_X1 = 59,
-  SRAIB_SHUN_0_OPCODE_X0 = 8,
-  SRAIB_SHUN_0_OPCODE_X1 = 8,
-  SRAIH_SHUN_0_OPCODE_X0 = 9,
-  SRAIH_SHUN_0_OPCODE_X1 = 9,
-  SRAI_SHUN_0_OPCODE_X0 = 10,
-  SRAI_SHUN_0_OPCODE_X1 = 10,
-  SRAI_SHUN_0_OPCODE_Y0 = 4,
-  SRAI_SHUN_0_OPCODE_Y1 = 4,
-  SRA_SPECIAL_0_OPCODE_X0 = 90,
-  SRA_SPECIAL_0_OPCODE_X1 = 60,
-  SRA_SPECIAL_3_OPCODE_Y0 = 3,
-  SRA_SPECIAL_3_OPCODE_Y1 = 3,
-  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
-  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
-  SUBB_SPECIAL_0_OPCODE_X0 = 91,
-  SUBB_SPECIAL_0_OPCODE_X1 = 61,
-  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
-  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
-  SUBH_SPECIAL_0_OPCODE_X0 = 92,
-  SUBH_SPECIAL_0_OPCODE_X1 = 62,
-  SUBS_SPECIAL_0_OPCODE_X0 = 97,
-  SUBS_SPECIAL_0_OPCODE_X1 = 67,
-  SUB_SPECIAL_0_OPCODE_X0 = 93,
-  SUB_SPECIAL_0_OPCODE_X1 = 63,
-  SUB_SPECIAL_0_OPCODE_Y0 = 3,
-  SUB_SPECIAL_0_OPCODE_Y1 = 3,
-  SWADD_IMM_0_OPCODE_X1 = 30,
-  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
-  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
-  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
-  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
-  SW_OPCODE_Y2 = 7,
-  SW_SPECIAL_0_OPCODE_X1 = 64,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
-  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
-  UN_0_SHUN_0_OPCODE_X0 = 11,
-  UN_0_SHUN_0_OPCODE_X1 = 11,
-  UN_0_SHUN_0_OPCODE_Y0 = 5,
-  UN_0_SHUN_0_OPCODE_Y1 = 5,
-  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
-  XORI_IMM_0_OPCODE_X0 = 2,
-  XORI_IMM_0_OPCODE_X1 = 21,
-  XOR_SPECIAL_0_OPCODE_X0 = 94,
-  XOR_SPECIAL_0_OPCODE_X1 = 65,
-  XOR_SPECIAL_2_OPCODE_Y0 = 3,
-  XOR_SPECIAL_2_OPCODE_Y1 = 3
-};
-
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants_64.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants_64.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,609 +0,0 @@
-/*
- * Copyright 2011 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-/* This file is machine-generated; DO NOT EDIT! */
-
-
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
-enum
-{
-  ADDI_IMM8_OPCODE_X0 = 1,
-  ADDI_IMM8_OPCODE_X1 = 1,
-  ADDI_OPCODE_Y0 = 0,
-  ADDI_OPCODE_Y1 = 1,
-  ADDLI_OPCODE_X0 = 1,
-  ADDLI_OPCODE_X1 = 0,
-  ADDXI_IMM8_OPCODE_X0 = 2,
-  ADDXI_IMM8_OPCODE_X1 = 2,
-  ADDXI_OPCODE_Y0 = 1,
-  ADDXI_OPCODE_Y1 = 2,
-  ADDXLI_OPCODE_X0 = 2,
-  ADDXLI_OPCODE_X1 = 1,
-  ADDXSC_RRR_0_OPCODE_X0 = 1,
-  ADDXSC_RRR_0_OPCODE_X1 = 1,
-  ADDX_RRR_0_OPCODE_X0 = 2,
-  ADDX_RRR_0_OPCODE_X1 = 2,
-  ADDX_RRR_0_OPCODE_Y0 = 0,
-  ADDX_SPECIAL_0_OPCODE_Y1 = 0,
-  ADD_RRR_0_OPCODE_X0 = 3,
-  ADD_RRR_0_OPCODE_X1 = 3,
-  ADD_RRR_0_OPCODE_Y0 = 1,
-  ADD_SPECIAL_0_OPCODE_Y1 = 1,
-  ANDI_IMM8_OPCODE_X0 = 3,
-  ANDI_IMM8_OPCODE_X1 = 3,
-  ANDI_OPCODE_Y0 = 2,
-  ANDI_OPCODE_Y1 = 3,
-  AND_RRR_0_OPCODE_X0 = 4,
-  AND_RRR_0_OPCODE_X1 = 4,
-  AND_RRR_5_OPCODE_Y0 = 0,
-  AND_RRR_5_OPCODE_Y1 = 0,
-  BEQZT_BRANCH_OPCODE_X1 = 16,
-  BEQZ_BRANCH_OPCODE_X1 = 17,
-  BFEXTS_BF_OPCODE_X0 = 4,
-  BFEXTU_BF_OPCODE_X0 = 5,
-  BFINS_BF_OPCODE_X0 = 6,
-  BF_OPCODE_X0 = 3,
-  BGEZT_BRANCH_OPCODE_X1 = 18,
-  BGEZ_BRANCH_OPCODE_X1 = 19,
-  BGTZT_BRANCH_OPCODE_X1 = 20,
-  BGTZ_BRANCH_OPCODE_X1 = 21,
-  BLBCT_BRANCH_OPCODE_X1 = 22,
-  BLBC_BRANCH_OPCODE_X1 = 23,
-  BLBST_BRANCH_OPCODE_X1 = 24,
-  BLBS_BRANCH_OPCODE_X1 = 25,
-  BLEZT_BRANCH_OPCODE_X1 = 26,
-  BLEZ_BRANCH_OPCODE_X1 = 27,
-  BLTZT_BRANCH_OPCODE_X1 = 28,
-  BLTZ_BRANCH_OPCODE_X1 = 29,
-  BNEZT_BRANCH_OPCODE_X1 = 30,
-  BNEZ_BRANCH_OPCODE_X1 = 31,
-  BRANCH_OPCODE_X1 = 2,
-  CMOVEQZ_RRR_0_OPCODE_X0 = 5,
-  CMOVEQZ_RRR_4_OPCODE_Y0 = 0,
-  CMOVNEZ_RRR_0_OPCODE_X0 = 6,
-  CMOVNEZ_RRR_4_OPCODE_Y0 = 1,
-  CMPEQI_IMM8_OPCODE_X0 = 4,
-  CMPEQI_IMM8_OPCODE_X1 = 4,
-  CMPEQI_OPCODE_Y0 = 3,
-  CMPEQI_OPCODE_Y1 = 4,
-  CMPEQ_RRR_0_OPCODE_X0 = 7,
-  CMPEQ_RRR_0_OPCODE_X1 = 5,
-  CMPEQ_RRR_3_OPCODE_Y0 = 0,
-  CMPEQ_RRR_3_OPCODE_Y1 = 2,
-  CMPEXCH4_RRR_0_OPCODE_X1 = 6,
-  CMPEXCH_RRR_0_OPCODE_X1 = 7,
-  CMPLES_RRR_0_OPCODE_X0 = 8,
-  CMPLES_RRR_0_OPCODE_X1 = 8,
-  CMPLES_RRR_2_OPCODE_Y0 = 0,
-  CMPLES_RRR_2_OPCODE_Y1 = 0,
-  CMPLEU_RRR_0_OPCODE_X0 = 9,
-  CMPLEU_RRR_0_OPCODE_X1 = 9,
-  CMPLEU_RRR_2_OPCODE_Y0 = 1,
-  CMPLEU_RRR_2_OPCODE_Y1 = 1,
-  CMPLTSI_IMM8_OPCODE_X0 = 5,
-  CMPLTSI_IMM8_OPCODE_X1 = 5,
-  CMPLTSI_OPCODE_Y0 = 4,
-  CMPLTSI_OPCODE_Y1 = 5,
-  CMPLTS_RRR_0_OPCODE_X0 = 10,
-  CMPLTS_RRR_0_OPCODE_X1 = 10,
-  CMPLTS_RRR_2_OPCODE_Y0 = 2,
-  CMPLTS_RRR_2_OPCODE_Y1 = 2,
-  CMPLTUI_IMM8_OPCODE_X0 = 6,
-  CMPLTUI_IMM8_OPCODE_X1 = 6,
-  CMPLTU_RRR_0_OPCODE_X0 = 11,
-  CMPLTU_RRR_0_OPCODE_X1 = 11,
-  CMPLTU_RRR_2_OPCODE_Y0 = 3,
-  CMPLTU_RRR_2_OPCODE_Y1 = 3,
-  CMPNE_RRR_0_OPCODE_X0 = 12,
-  CMPNE_RRR_0_OPCODE_X1 = 12,
-  CMPNE_RRR_3_OPCODE_Y0 = 1,
-  CMPNE_RRR_3_OPCODE_Y1 = 3,
-  CMULAF_RRR_0_OPCODE_X0 = 13,
-  CMULA_RRR_0_OPCODE_X0 = 14,
-  CMULFR_RRR_0_OPCODE_X0 = 15,
-  CMULF_RRR_0_OPCODE_X0 = 16,
-  CMULHR_RRR_0_OPCODE_X0 = 17,
-  CMULH_RRR_0_OPCODE_X0 = 18,
-  CMUL_RRR_0_OPCODE_X0 = 19,
-  CNTLZ_UNARY_OPCODE_X0 = 1,
-  CNTLZ_UNARY_OPCODE_Y0 = 1,
-  CNTTZ_UNARY_OPCODE_X0 = 2,
-  CNTTZ_UNARY_OPCODE_Y0 = 2,
-  CRC32_32_RRR_0_OPCODE_X0 = 20,
-  CRC32_8_RRR_0_OPCODE_X0 = 21,
-  DBLALIGN2_RRR_0_OPCODE_X0 = 22,
-  DBLALIGN2_RRR_0_OPCODE_X1 = 13,
-  DBLALIGN4_RRR_0_OPCODE_X0 = 23,
-  DBLALIGN4_RRR_0_OPCODE_X1 = 14,
-  DBLALIGN6_RRR_0_OPCODE_X0 = 24,
-  DBLALIGN6_RRR_0_OPCODE_X1 = 15,
-  DBLALIGN_RRR_0_OPCODE_X0 = 25,
-  DRAIN_UNARY_OPCODE_X1 = 1,
-  DTLBPR_UNARY_OPCODE_X1 = 2,
-  EXCH4_RRR_0_OPCODE_X1 = 16,
-  EXCH_RRR_0_OPCODE_X1 = 17,
-  FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,
-  FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,
-  FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,
-  FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,
-  FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,
-  FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,
-  FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,
-  FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,
-  FETCHADD4_RRR_0_OPCODE_X1 = 18,
-  FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,
-  FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,
-  FETCHADD_RRR_0_OPCODE_X1 = 21,
-  FETCHAND4_RRR_0_OPCODE_X1 = 22,
-  FETCHAND_RRR_0_OPCODE_X1 = 23,
-  FETCHOR4_RRR_0_OPCODE_X1 = 24,
-  FETCHOR_RRR_0_OPCODE_X1 = 25,
-  FINV_UNARY_OPCODE_X1 = 3,
-  FLUSHWB_UNARY_OPCODE_X1 = 4,
-  FLUSH_UNARY_OPCODE_X1 = 5,
-  FNOP_UNARY_OPCODE_X0 = 3,
-  FNOP_UNARY_OPCODE_X1 = 6,
-  FNOP_UNARY_OPCODE_Y0 = 3,
-  FNOP_UNARY_OPCODE_Y1 = 8,
-  FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,
-  FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,
-  FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,
-  FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,
-  FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,
-  FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
-  FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,
-  FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,
-  ICOH_UNARY_OPCODE_X1 = 7,
-  ILL_UNARY_OPCODE_X1 = 8,
-  ILL_UNARY_OPCODE_Y1 = 9,
-  IMM8_OPCODE_X0 = 4,
-  IMM8_OPCODE_X1 = 3,
-  INV_UNARY_OPCODE_X1 = 9,
-  IRET_UNARY_OPCODE_X1 = 10,
-  JALRP_UNARY_OPCODE_X1 = 11,
-  JALRP_UNARY_OPCODE_Y1 = 10,
-  JALR_UNARY_OPCODE_X1 = 12,
-  JALR_UNARY_OPCODE_Y1 = 11,
-  JAL_JUMP_OPCODE_X1 = 0,
-  JRP_UNARY_OPCODE_X1 = 13,
-  JRP_UNARY_OPCODE_Y1 = 12,
-  JR_UNARY_OPCODE_X1 = 14,
-  JR_UNARY_OPCODE_Y1 = 13,
-  JUMP_OPCODE_X1 = 4,
-  J_JUMP_OPCODE_X1 = 1,
-  LD1S_ADD_IMM8_OPCODE_X1 = 7,
-  LD1S_OPCODE_Y2 = 0,
-  LD1S_UNARY_OPCODE_X1 = 15,
-  LD1U_ADD_IMM8_OPCODE_X1 = 8,
-  LD1U_OPCODE_Y2 = 1,
-  LD1U_UNARY_OPCODE_X1 = 16,
-  LD2S_ADD_IMM8_OPCODE_X1 = 9,
-  LD2S_OPCODE_Y2 = 2,
-  LD2S_UNARY_OPCODE_X1 = 17,
-  LD2U_ADD_IMM8_OPCODE_X1 = 10,
-  LD2U_OPCODE_Y2 = 3,
-  LD2U_UNARY_OPCODE_X1 = 18,
-  LD4S_ADD_IMM8_OPCODE_X1 = 11,
-  LD4S_OPCODE_Y2 = 1,
-  LD4S_UNARY_OPCODE_X1 = 19,
-  LD4U_ADD_IMM8_OPCODE_X1 = 12,
-  LD4U_OPCODE_Y2 = 2,
-  LD4U_UNARY_OPCODE_X1 = 20,
-  LDNA_UNARY_OPCODE_X1 = 21,
-  LDNT1S_ADD_IMM8_OPCODE_X1 = 13,
-  LDNT1S_UNARY_OPCODE_X1 = 22,
-  LDNT1U_ADD_IMM8_OPCODE_X1 = 14,
-  LDNT1U_UNARY_OPCODE_X1 = 23,
-  LDNT2S_ADD_IMM8_OPCODE_X1 = 15,
-  LDNT2S_UNARY_OPCODE_X1 = 24,
-  LDNT2U_ADD_IMM8_OPCODE_X1 = 16,
-  LDNT2U_UNARY_OPCODE_X1 = 25,
-  LDNT4S_ADD_IMM8_OPCODE_X1 = 17,
-  LDNT4S_UNARY_OPCODE_X1 = 26,
-  LDNT4U_ADD_IMM8_OPCODE_X1 = 18,
-  LDNT4U_UNARY_OPCODE_X1 = 27,
-  LDNT_ADD_IMM8_OPCODE_X1 = 19,
-  LDNT_UNARY_OPCODE_X1 = 28,
-  LD_ADD_IMM8_OPCODE_X1 = 20,
-  LD_OPCODE_Y2 = 3,
-  LD_UNARY_OPCODE_X1 = 29,
-  LNK_UNARY_OPCODE_X1 = 30,
-  LNK_UNARY_OPCODE_Y1 = 14,
-  LWNA_ADD_IMM8_OPCODE_X1 = 21,
-  MFSPR_IMM8_OPCODE_X1 = 22,
-  MF_UNARY_OPCODE_X1 = 31,
-  MM_BF_OPCODE_X0 = 7,
-  MNZ_RRR_0_OPCODE_X0 = 40,
-  MNZ_RRR_0_OPCODE_X1 = 26,
-  MNZ_RRR_4_OPCODE_Y0 = 2,
-  MNZ_RRR_4_OPCODE_Y1 = 2,
-  MODE_OPCODE_YA2 = 1,
-  MODE_OPCODE_YB2 = 2,
-  MODE_OPCODE_YC2 = 3,
-  MTSPR_IMM8_OPCODE_X1 = 23,
-  MULAX_RRR_0_OPCODE_X0 = 41,
-  MULAX_RRR_3_OPCODE_Y0 = 2,
-  MULA_HS_HS_RRR_0_OPCODE_X0 = 42,
-  MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,
-  MULA_HS_HU_RRR_0_OPCODE_X0 = 43,
-  MULA_HS_LS_RRR_0_OPCODE_X0 = 44,
-  MULA_HS_LU_RRR_0_OPCODE_X0 = 45,
-  MULA_HU_HU_RRR_0_OPCODE_X0 = 46,
-  MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,
-  MULA_HU_LS_RRR_0_OPCODE_X0 = 47,
-  MULA_HU_LU_RRR_0_OPCODE_X0 = 48,
-  MULA_LS_LS_RRR_0_OPCODE_X0 = 49,
-  MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,
-  MULA_LS_LU_RRR_0_OPCODE_X0 = 50,
-  MULA_LU_LU_RRR_0_OPCODE_X0 = 51,
-  MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,
-  MULX_RRR_0_OPCODE_X0 = 52,
-  MULX_RRR_3_OPCODE_Y0 = 3,
-  MUL_HS_HS_RRR_0_OPCODE_X0 = 53,
-  MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,
-  MUL_HS_HU_RRR_0_OPCODE_X0 = 54,
-  MUL_HS_LS_RRR_0_OPCODE_X0 = 55,
-  MUL_HS_LU_RRR_0_OPCODE_X0 = 56,
-  MUL_HU_HU_RRR_0_OPCODE_X0 = 57,
-  MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,
-  MUL_HU_LS_RRR_0_OPCODE_X0 = 58,
-  MUL_HU_LU_RRR_0_OPCODE_X0 = 59,
-  MUL_LS_LS_RRR_0_OPCODE_X0 = 60,
-  MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,
-  MUL_LS_LU_RRR_0_OPCODE_X0 = 61,
-  MUL_LU_LU_RRR_0_OPCODE_X0 = 62,
-  MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,
-  MZ_RRR_0_OPCODE_X0 = 63,
-  MZ_RRR_0_OPCODE_X1 = 27,
-  MZ_RRR_4_OPCODE_Y0 = 3,
-  MZ_RRR_4_OPCODE_Y1 = 3,
-  NAP_UNARY_OPCODE_X1 = 32,
-  NOP_UNARY_OPCODE_X0 = 5,
-  NOP_UNARY_OPCODE_X1 = 33,
-  NOP_UNARY_OPCODE_Y0 = 5,
-  NOP_UNARY_OPCODE_Y1 = 15,
-  NOR_RRR_0_OPCODE_X0 = 64,
-  NOR_RRR_0_OPCODE_X1 = 28,
-  NOR_RRR_5_OPCODE_Y0 = 1,
-  NOR_RRR_5_OPCODE_Y1 = 1,
-  ORI_IMM8_OPCODE_X0 = 7,
-  ORI_IMM8_OPCODE_X1 = 24,
-  OR_RRR_0_OPCODE_X0 = 65,
-  OR_RRR_0_OPCODE_X1 = 29,
-  OR_RRR_5_OPCODE_Y0 = 2,
-  OR_RRR_5_OPCODE_Y1 = 2,
-  PCNT_UNARY_OPCODE_X0 = 6,
-  PCNT_UNARY_OPCODE_Y0 = 6,
-  REVBITS_UNARY_OPCODE_X0 = 7,
-  REVBITS_UNARY_OPCODE_Y0 = 7,
-  REVBYTES_UNARY_OPCODE_X0 = 8,
-  REVBYTES_UNARY_OPCODE_Y0 = 8,
-  ROTLI_SHIFT_OPCODE_X0 = 1,
-  ROTLI_SHIFT_OPCODE_X1 = 1,
-  ROTLI_SHIFT_OPCODE_Y0 = 0,
-  ROTLI_SHIFT_OPCODE_Y1 = 0,
-  ROTL_RRR_0_OPCODE_X0 = 66,
-  ROTL_RRR_0_OPCODE_X1 = 30,
-  ROTL_RRR_6_OPCODE_Y0 = 0,
-  ROTL_RRR_6_OPCODE_Y1 = 0,
-  RRR_0_OPCODE_X0 = 5,
-  RRR_0_OPCODE_X1 = 5,
-  RRR_0_OPCODE_Y0 = 5,
-  RRR_0_OPCODE_Y1 = 6,
-  RRR_1_OPCODE_Y0 = 6,
-  RRR_1_OPCODE_Y1 = 7,
-  RRR_2_OPCODE_Y0 = 7,
-  RRR_2_OPCODE_Y1 = 8,
-  RRR_3_OPCODE_Y0 = 8,
-  RRR_3_OPCODE_Y1 = 9,
-  RRR_4_OPCODE_Y0 = 9,
-  RRR_4_OPCODE_Y1 = 10,
-  RRR_5_OPCODE_Y0 = 10,
-  RRR_5_OPCODE_Y1 = 11,
-  RRR_6_OPCODE_Y0 = 11,
-  RRR_6_OPCODE_Y1 = 12,
-  RRR_7_OPCODE_Y0 = 12,
-  RRR_7_OPCODE_Y1 = 13,
-  RRR_8_OPCODE_Y0 = 13,
-  RRR_9_OPCODE_Y0 = 14,
-  SHIFT_OPCODE_X0 = 6,
-  SHIFT_OPCODE_X1 = 6,
-  SHIFT_OPCODE_Y0 = 15,
-  SHIFT_OPCODE_Y1 = 14,
-  SHL16INSLI_OPCODE_X0 = 7,
-  SHL16INSLI_OPCODE_X1 = 7,
-  SHL1ADDX_RRR_0_OPCODE_X0 = 67,
-  SHL1ADDX_RRR_0_OPCODE_X1 = 31,
-  SHL1ADDX_RRR_7_OPCODE_Y0 = 1,
-  SHL1ADDX_RRR_7_OPCODE_Y1 = 1,
-  SHL1ADD_RRR_0_OPCODE_X0 = 68,
-  SHL1ADD_RRR_0_OPCODE_X1 = 32,
-  SHL1ADD_RRR_1_OPCODE_Y0 = 0,
-  SHL1ADD_RRR_1_OPCODE_Y1 = 0,
-  SHL2ADDX_RRR_0_OPCODE_X0 = 69,
-  SHL2ADDX_RRR_0_OPCODE_X1 = 33,
-  SHL2ADDX_RRR_7_OPCODE_Y0 = 2,
-  SHL2ADDX_RRR_7_OPCODE_Y1 = 2,
-  SHL2ADD_RRR_0_OPCODE_X0 = 70,
-  SHL2ADD_RRR_0_OPCODE_X1 = 34,
-  SHL2ADD_RRR_1_OPCODE_Y0 = 1,
-  SHL2ADD_RRR_1_OPCODE_Y1 = 1,
-  SHL3ADDX_RRR_0_OPCODE_X0 = 71,
-  SHL3ADDX_RRR_0_OPCODE_X1 = 35,
-  SHL3ADDX_RRR_7_OPCODE_Y0 = 3,
-  SHL3ADDX_RRR_7_OPCODE_Y1 = 3,
-  SHL3ADD_RRR_0_OPCODE_X0 = 72,
-  SHL3ADD_RRR_0_OPCODE_X1 = 36,
-  SHL3ADD_RRR_1_OPCODE_Y0 = 2,
-  SHL3ADD_RRR_1_OPCODE_Y1 = 2,
-  SHLI_SHIFT_OPCODE_X0 = 2,
-  SHLI_SHIFT_OPCODE_X1 = 2,
-  SHLI_SHIFT_OPCODE_Y0 = 1,
-  SHLI_SHIFT_OPCODE_Y1 = 1,
-  SHLXI_SHIFT_OPCODE_X0 = 3,
-  SHLXI_SHIFT_OPCODE_X1 = 3,
-  SHLX_RRR_0_OPCODE_X0 = 73,
-  SHLX_RRR_0_OPCODE_X1 = 37,
-  SHL_RRR_0_OPCODE_X0 = 74,
-  SHL_RRR_0_OPCODE_X1 = 38,
-  SHL_RRR_6_OPCODE_Y0 = 1,
-  SHL_RRR_6_OPCODE_Y1 = 1,
-  SHRSI_SHIFT_OPCODE_X0 = 4,
-  SHRSI_SHIFT_OPCODE_X1 = 4,
-  SHRSI_SHIFT_OPCODE_Y0 = 2,
-  SHRSI_SHIFT_OPCODE_Y1 = 2,
-  SHRS_RRR_0_OPCODE_X0 = 75,
-  SHRS_RRR_0_OPCODE_X1 = 39,
-  SHRS_RRR_6_OPCODE_Y0 = 2,
-  SHRS_RRR_6_OPCODE_Y1 = 2,
-  SHRUI_SHIFT_OPCODE_X0 = 5,
-  SHRUI_SHIFT_OPCODE_X1 = 5,
-  SHRUI_SHIFT_OPCODE_Y0 = 3,
-  SHRUI_SHIFT_OPCODE_Y1 = 3,
-  SHRUXI_SHIFT_OPCODE_X0 = 6,
-  SHRUXI_SHIFT_OPCODE_X1 = 6,
-  SHRUX_RRR_0_OPCODE_X0 = 76,
-  SHRUX_RRR_0_OPCODE_X1 = 40,
-  SHRU_RRR_0_OPCODE_X0 = 77,
-  SHRU_RRR_0_OPCODE_X1 = 41,
-  SHRU_RRR_6_OPCODE_Y0 = 3,
-  SHRU_RRR_6_OPCODE_Y1 = 3,
-  SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,
-  ST1_ADD_IMM8_OPCODE_X1 = 25,
-  ST1_OPCODE_Y2 = 0,
-  ST1_RRR_0_OPCODE_X1 = 42,
-  ST2_ADD_IMM8_OPCODE_X1 = 26,
-  ST2_OPCODE_Y2 = 1,
-  ST2_RRR_0_OPCODE_X1 = 43,
-  ST4_ADD_IMM8_OPCODE_X1 = 27,
-  ST4_OPCODE_Y2 = 2,
-  ST4_RRR_0_OPCODE_X1 = 44,
-  STNT1_ADD_IMM8_OPCODE_X1 = 28,
-  STNT1_RRR_0_OPCODE_X1 = 45,
-  STNT2_ADD_IMM8_OPCODE_X1 = 29,
-  STNT2_RRR_0_OPCODE_X1 = 46,
-  STNT4_ADD_IMM8_OPCODE_X1 = 30,
-  STNT4_RRR_0_OPCODE_X1 = 47,
-  STNT_ADD_IMM8_OPCODE_X1 = 31,
-  STNT_RRR_0_OPCODE_X1 = 48,
-  ST_ADD_IMM8_OPCODE_X1 = 32,
-  ST_OPCODE_Y2 = 3,
-  ST_RRR_0_OPCODE_X1 = 49,
-  SUBXSC_RRR_0_OPCODE_X0 = 79,
-  SUBXSC_RRR_0_OPCODE_X1 = 50,
-  SUBX_RRR_0_OPCODE_X0 = 80,
-  SUBX_RRR_0_OPCODE_X1 = 51,
-  SUBX_RRR_0_OPCODE_Y0 = 2,
-  SUBX_RRR_0_OPCODE_Y1 = 2,
-  SUB_RRR_0_OPCODE_X0 = 81,
-  SUB_RRR_0_OPCODE_X1 = 52,
-  SUB_RRR_0_OPCODE_Y0 = 3,
-  SUB_RRR_0_OPCODE_Y1 = 3,
-  SWINT0_UNARY_OPCODE_X1 = 34,
-  SWINT1_UNARY_OPCODE_X1 = 35,
-  SWINT2_UNARY_OPCODE_X1 = 36,
-  SWINT3_UNARY_OPCODE_X1 = 37,
-  TBLIDXB0_UNARY_OPCODE_X0 = 9,
-  TBLIDXB0_UNARY_OPCODE_Y0 = 9,
-  TBLIDXB1_UNARY_OPCODE_X0 = 10,
-  TBLIDXB1_UNARY_OPCODE_Y0 = 10,
-  TBLIDXB2_UNARY_OPCODE_X0 = 11,
-  TBLIDXB2_UNARY_OPCODE_Y0 = 11,
-  TBLIDXB3_UNARY_OPCODE_X0 = 12,
-  TBLIDXB3_UNARY_OPCODE_Y0 = 12,
-  UNARY_RRR_0_OPCODE_X0 = 82,
-  UNARY_RRR_0_OPCODE_X1 = 53,
-  UNARY_RRR_1_OPCODE_Y0 = 3,
-  UNARY_RRR_1_OPCODE_Y1 = 3,
-  V1ADDI_IMM8_OPCODE_X0 = 8,
-  V1ADDI_IMM8_OPCODE_X1 = 33,
-  V1ADDUC_RRR_0_OPCODE_X0 = 83,
-  V1ADDUC_RRR_0_OPCODE_X1 = 54,
-  V1ADD_RRR_0_OPCODE_X0 = 84,
-  V1ADD_RRR_0_OPCODE_X1 = 55,
-  V1ADIFFU_RRR_0_OPCODE_X0 = 85,
-  V1AVGU_RRR_0_OPCODE_X0 = 86,
-  V1CMPEQI_IMM8_OPCODE_X0 = 9,
-  V1CMPEQI_IMM8_OPCODE_X1 = 34,
-  V1CMPEQ_RRR_0_OPCODE_X0 = 87,
-  V1CMPEQ_RRR_0_OPCODE_X1 = 56,
-  V1CMPLES_RRR_0_OPCODE_X0 = 88,
-  V1CMPLES_RRR_0_OPCODE_X1 = 57,
-  V1CMPLEU_RRR_0_OPCODE_X0 = 89,
-  V1CMPLEU_RRR_0_OPCODE_X1 = 58,
-  V1CMPLTSI_IMM8_OPCODE_X0 = 10,
-  V1CMPLTSI_IMM8_OPCODE_X1 = 35,
-  V1CMPLTS_RRR_0_OPCODE_X0 = 90,
-  V1CMPLTS_RRR_0_OPCODE_X1 = 59,
-  V1CMPLTUI_IMM8_OPCODE_X0 = 11,
-  V1CMPLTUI_IMM8_OPCODE_X1 = 36,
-  V1CMPLTU_RRR_0_OPCODE_X0 = 91,
-  V1CMPLTU_RRR_0_OPCODE_X1 = 60,
-  V1CMPNE_RRR_0_OPCODE_X0 = 92,
-  V1CMPNE_RRR_0_OPCODE_X1 = 61,
-  V1DDOTPUA_RRR_0_OPCODE_X0 = 161,
-  V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,
-  V1DDOTPUS_RRR_0_OPCODE_X0 = 94,
-  V1DDOTPU_RRR_0_OPCODE_X0 = 162,
-  V1DOTPA_RRR_0_OPCODE_X0 = 95,
-  V1DOTPUA_RRR_0_OPCODE_X0 = 163,
-  V1DOTPUSA_RRR_0_OPCODE_X0 = 96,
-  V1DOTPUS_RRR_0_OPCODE_X0 = 97,
-  V1DOTPU_RRR_0_OPCODE_X0 = 164,
-  V1DOTP_RRR_0_OPCODE_X0 = 98,
-  V1INT_H_RRR_0_OPCODE_X0 = 99,
-  V1INT_H_RRR_0_OPCODE_X1 = 62,
-  V1INT_L_RRR_0_OPCODE_X0 = 100,
-  V1INT_L_RRR_0_OPCODE_X1 = 63,
-  V1MAXUI_IMM8_OPCODE_X0 = 12,
-  V1MAXUI_IMM8_OPCODE_X1 = 37,
-  V1MAXU_RRR_0_OPCODE_X0 = 101,
-  V1MAXU_RRR_0_OPCODE_X1 = 64,
-  V1MINUI_IMM8_OPCODE_X0 = 13,
-  V1MINUI_IMM8_OPCODE_X1 = 38,
-  V1MINU_RRR_0_OPCODE_X0 = 102,
-  V1MINU_RRR_0_OPCODE_X1 = 65,
-  V1MNZ_RRR_0_OPCODE_X0 = 103,
-  V1MNZ_RRR_0_OPCODE_X1 = 66,
-  V1MULTU_RRR_0_OPCODE_X0 = 104,
-  V1MULUS_RRR_0_OPCODE_X0 = 105,
-  V1MULU_RRR_0_OPCODE_X0 = 106,
-  V1MZ_RRR_0_OPCODE_X0 = 107,
-  V1MZ_RRR_0_OPCODE_X1 = 67,
-  V1SADAU_RRR_0_OPCODE_X0 = 108,
-  V1SADU_RRR_0_OPCODE_X0 = 109,
-  V1SHLI_SHIFT_OPCODE_X0 = 7,
-  V1SHLI_SHIFT_OPCODE_X1 = 7,
-  V1SHL_RRR_0_OPCODE_X0 = 110,
-  V1SHL_RRR_0_OPCODE_X1 = 68,
-  V1SHRSI_SHIFT_OPCODE_X0 = 8,
-  V1SHRSI_SHIFT_OPCODE_X1 = 8,
-  V1SHRS_RRR_0_OPCODE_X0 = 111,
-  V1SHRS_RRR_0_OPCODE_X1 = 69,
-  V1SHRUI_SHIFT_OPCODE_X0 = 9,
-  V1SHRUI_SHIFT_OPCODE_X1 = 9,
-  V1SHRU_RRR_0_OPCODE_X0 = 112,
-  V1SHRU_RRR_0_OPCODE_X1 = 70,
-  V1SUBUC_RRR_0_OPCODE_X0 = 113,
-  V1SUBUC_RRR_0_OPCODE_X1 = 71,
-  V1SUB_RRR_0_OPCODE_X0 = 114,
-  V1SUB_RRR_0_OPCODE_X1 = 72,
-  V2ADDI_IMM8_OPCODE_X0 = 14,
-  V2ADDI_IMM8_OPCODE_X1 = 39,
-  V2ADDSC_RRR_0_OPCODE_X0 = 115,
-  V2ADDSC_RRR_0_OPCODE_X1 = 73,
-  V2ADD_RRR_0_OPCODE_X0 = 116,
-  V2ADD_RRR_0_OPCODE_X1 = 74,
-  V2ADIFFS_RRR_0_OPCODE_X0 = 117,
-  V2AVGS_RRR_0_OPCODE_X0 = 118,
-  V2CMPEQI_IMM8_OPCODE_X0 = 15,
-  V2CMPEQI_IMM8_OPCODE_X1 = 40,
-  V2CMPEQ_RRR_0_OPCODE_X0 = 119,
-  V2CMPEQ_RRR_0_OPCODE_X1 = 75,
-  V2CMPLES_RRR_0_OPCODE_X0 = 120,
-  V2CMPLES_RRR_0_OPCODE_X1 = 76,
-  V2CMPLEU_RRR_0_OPCODE_X0 = 121,
-  V2CMPLEU_RRR_0_OPCODE_X1 = 77,
-  V2CMPLTSI_IMM8_OPCODE_X0 = 16,
-  V2CMPLTSI_IMM8_OPCODE_X1 = 41,
-  V2CMPLTS_RRR_0_OPCODE_X0 = 122,
-  V2CMPLTS_RRR_0_OPCODE_X1 = 78,
-  V2CMPLTUI_IMM8_OPCODE_X0 = 17,
-  V2CMPLTUI_IMM8_OPCODE_X1 = 42,
-  V2CMPLTU_RRR_0_OPCODE_X0 = 123,
-  V2CMPLTU_RRR_0_OPCODE_X1 = 79,
-  V2CMPNE_RRR_0_OPCODE_X0 = 124,
-  V2CMPNE_RRR_0_OPCODE_X1 = 80,
-  V2DOTPA_RRR_0_OPCODE_X0 = 125,
-  V2DOTP_RRR_0_OPCODE_X0 = 126,
-  V2INT_H_RRR_0_OPCODE_X0 = 127,
-  V2INT_H_RRR_0_OPCODE_X1 = 81,
-  V2INT_L_RRR_0_OPCODE_X0 = 128,
-  V2INT_L_RRR_0_OPCODE_X1 = 82,
-  V2MAXSI_IMM8_OPCODE_X0 = 18,
-  V2MAXSI_IMM8_OPCODE_X1 = 43,
-  V2MAXS_RRR_0_OPCODE_X0 = 129,
-  V2MAXS_RRR_0_OPCODE_X1 = 83,
-  V2MINSI_IMM8_OPCODE_X0 = 19,
-  V2MINSI_IMM8_OPCODE_X1 = 44,
-  V2MINS_RRR_0_OPCODE_X0 = 130,
-  V2MINS_RRR_0_OPCODE_X1 = 84,
-  V2MNZ_RRR_0_OPCODE_X0 = 131,
-  V2MNZ_RRR_0_OPCODE_X1 = 85,
-  V2MULFSC_RRR_0_OPCODE_X0 = 132,
-  V2MULS_RRR_0_OPCODE_X0 = 133,
-  V2MULTS_RRR_0_OPCODE_X0 = 134,
-  V2MZ_RRR_0_OPCODE_X0 = 135,
-  V2MZ_RRR_0_OPCODE_X1 = 86,
-  V2PACKH_RRR_0_OPCODE_X0 = 136,
-  V2PACKH_RRR_0_OPCODE_X1 = 87,
-  V2PACKL_RRR_0_OPCODE_X0 = 137,
-  V2PACKL_RRR_0_OPCODE_X1 = 88,
-  V2PACKUC_RRR_0_OPCODE_X0 = 138,
-  V2PACKUC_RRR_0_OPCODE_X1 = 89,
-  V2SADAS_RRR_0_OPCODE_X0 = 139,
-  V2SADAU_RRR_0_OPCODE_X0 = 140,
-  V2SADS_RRR_0_OPCODE_X0 = 141,
-  V2SADU_RRR_0_OPCODE_X0 = 142,
-  V2SHLI_SHIFT_OPCODE_X0 = 10,
-  V2SHLI_SHIFT_OPCODE_X1 = 10,
-  V2SHLSC_RRR_0_OPCODE_X0 = 143,
-  V2SHLSC_RRR_0_OPCODE_X1 = 90,
-  V2SHL_RRR_0_OPCODE_X0 = 144,
-  V2SHL_RRR_0_OPCODE_X1 = 91,
-  V2SHRSI_SHIFT_OPCODE_X0 = 11,
-  V2SHRSI_SHIFT_OPCODE_X1 = 11,
-  V2SHRS_RRR_0_OPCODE_X0 = 145,
-  V2SHRS_RRR_0_OPCODE_X1 = 92,
-  V2SHRUI_SHIFT_OPCODE_X0 = 12,
-  V2SHRUI_SHIFT_OPCODE_X1 = 12,
-  V2SHRU_RRR_0_OPCODE_X0 = 146,
-  V2SHRU_RRR_0_OPCODE_X1 = 93,
-  V2SUBSC_RRR_0_OPCODE_X0 = 147,
-  V2SUBSC_RRR_0_OPCODE_X1 = 94,
-  V2SUB_RRR_0_OPCODE_X0 = 148,
-  V2SUB_RRR_0_OPCODE_X1 = 95,
-  V4ADDSC_RRR_0_OPCODE_X0 = 149,
-  V4ADDSC_RRR_0_OPCODE_X1 = 96,
-  V4ADD_RRR_0_OPCODE_X0 = 150,
-  V4ADD_RRR_0_OPCODE_X1 = 97,
-  V4INT_H_RRR_0_OPCODE_X0 = 151,
-  V4INT_H_RRR_0_OPCODE_X1 = 98,
-  V4INT_L_RRR_0_OPCODE_X0 = 152,
-  V4INT_L_RRR_0_OPCODE_X1 = 99,
-  V4PACKSC_RRR_0_OPCODE_X0 = 153,
-  V4PACKSC_RRR_0_OPCODE_X1 = 100,
-  V4SHLSC_RRR_0_OPCODE_X0 = 154,
-  V4SHLSC_RRR_0_OPCODE_X1 = 101,
-  V4SHL_RRR_0_OPCODE_X0 = 155,
-  V4SHL_RRR_0_OPCODE_X1 = 102,
-  V4SHRS_RRR_0_OPCODE_X0 = 156,
-  V4SHRS_RRR_0_OPCODE_X1 = 103,
-  V4SHRU_RRR_0_OPCODE_X0 = 157,
-  V4SHRU_RRR_0_OPCODE_X1 = 104,
-  V4SUBSC_RRR_0_OPCODE_X0 = 158,
-  V4SUBSC_RRR_0_OPCODE_X1 = 105,
-  V4SUB_RRR_0_OPCODE_X0 = 159,
-  V4SUB_RRR_0_OPCODE_X1 = 106,
-  WH64_UNARY_OPCODE_X1 = 38,
-  XORI_IMM8_OPCODE_X0 = 20,
-  XORI_IMM8_OPCODE_X1 = 45,
-  XOR_RRR_0_OPCODE_X0 = 160,
-  XOR_RRR_0_OPCODE_X1 = 107,
-  XOR_RRR_5_OPCODE_Y0 = 3,
-  XOR_RRR_5_OPCODE_Y1 = 3
-};
-
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode_constants.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode_constants.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-#ifndef _ASM_TILE_OPCODE_CONSTANTS_H
-#define _ASM_TILE_OPCODE_CONSTANTS_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode_constants_64.h>
-#else
-#include <asm/opcode_constants_32.h>
-#endif
-
-#endif /* _ASM_TILE_OPCODE_CONSTANTS_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile_32.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile_32.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1513 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tile_bundle_bits;
-
-
-enum
-{
-  TILE_MAX_OPERANDS = 5 /* mm */
-};
-
-typedef enum
-{
-  TILE_OPC_BPT,
-  TILE_OPC_INFO,
-  TILE_OPC_INFOL,
-  TILE_OPC_J,
-  TILE_OPC_JAL,
-  TILE_OPC_MOVE,
-  TILE_OPC_MOVE_SN,
-  TILE_OPC_MOVEI,
-  TILE_OPC_MOVEI_SN,
-  TILE_OPC_MOVELI,
-  TILE_OPC_MOVELI_SN,
-  TILE_OPC_MOVELIS,
-  TILE_OPC_PREFETCH,
-  TILE_OPC_RAISE,
-  TILE_OPC_ADD,
-  TILE_OPC_ADD_SN,
-  TILE_OPC_ADDB,
-  TILE_OPC_ADDB_SN,
-  TILE_OPC_ADDBS_U,
-  TILE_OPC_ADDBS_U_SN,
-  TILE_OPC_ADDH,
-  TILE_OPC_ADDH_SN,
-  TILE_OPC_ADDHS,
-  TILE_OPC_ADDHS_SN,
-  TILE_OPC_ADDI,
-  TILE_OPC_ADDI_SN,
-  TILE_OPC_ADDIB,
-  TILE_OPC_ADDIB_SN,
-  TILE_OPC_ADDIH,
-  TILE_OPC_ADDIH_SN,
-  TILE_OPC_ADDLI,
-  TILE_OPC_ADDLI_SN,
-  TILE_OPC_ADDLIS,
-  TILE_OPC_ADDS,
-  TILE_OPC_ADDS_SN,
-  TILE_OPC_ADIFFB_U,
-  TILE_OPC_ADIFFB_U_SN,
-  TILE_OPC_ADIFFH,
-  TILE_OPC_ADIFFH_SN,
-  TILE_OPC_AND,
-  TILE_OPC_AND_SN,
-  TILE_OPC_ANDI,
-  TILE_OPC_ANDI_SN,
-  TILE_OPC_AULI,
-  TILE_OPC_AVGB_U,
-  TILE_OPC_AVGB_U_SN,
-  TILE_OPC_AVGH,
-  TILE_OPC_AVGH_SN,
-  TILE_OPC_BBNS,
-  TILE_OPC_BBNS_SN,
-  TILE_OPC_BBNST,
-  TILE_OPC_BBNST_SN,
-  TILE_OPC_BBS,
-  TILE_OPC_BBS_SN,
-  TILE_OPC_BBST,
-  TILE_OPC_BBST_SN,
-  TILE_OPC_BGEZ,
-  TILE_OPC_BGEZ_SN,
-  TILE_OPC_BGEZT,
-  TILE_OPC_BGEZT_SN,
-  TILE_OPC_BGZ,
-  TILE_OPC_BGZ_SN,
-  TILE_OPC_BGZT,
-  TILE_OPC_BGZT_SN,
-  TILE_OPC_BITX,
-  TILE_OPC_BITX_SN,
-  TILE_OPC_BLEZ,
-  TILE_OPC_BLEZ_SN,
-  TILE_OPC_BLEZT,
-  TILE_OPC_BLEZT_SN,
-  TILE_OPC_BLZ,
-  TILE_OPC_BLZ_SN,
-  TILE_OPC_BLZT,
-  TILE_OPC_BLZT_SN,
-  TILE_OPC_BNZ,
-  TILE_OPC_BNZ_SN,
-  TILE_OPC_BNZT,
-  TILE_OPC_BNZT_SN,
-  TILE_OPC_BYTEX,
-  TILE_OPC_BYTEX_SN,
-  TILE_OPC_BZ,
-  TILE_OPC_BZ_SN,
-  TILE_OPC_BZT,
-  TILE_OPC_BZT_SN,
-  TILE_OPC_CLZ,
-  TILE_OPC_CLZ_SN,
-  TILE_OPC_CRC32_32,
-  TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8,
-  TILE_OPC_CRC32_8_SN,
-  TILE_OPC_CTZ,
-  TILE_OPC_CTZ_SN,
-  TILE_OPC_DRAIN,
-  TILE_OPC_DTLBPR,
-  TILE_OPC_DWORD_ALIGN,
-  TILE_OPC_DWORD_ALIGN_SN,
-  TILE_OPC_FINV,
-  TILE_OPC_FLUSH,
-  TILE_OPC_FNOP,
-  TILE_OPC_ICOH,
-  TILE_OPC_ILL,
-  TILE_OPC_INTHB,
-  TILE_OPC_INTHB_SN,
-  TILE_OPC_INTHH,
-  TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB,
-  TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH,
-  TILE_OPC_INTLH_SN,
-  TILE_OPC_INV,
-  TILE_OPC_IRET,
-  TILE_OPC_JALB,
-  TILE_OPC_JALF,
-  TILE_OPC_JALR,
-  TILE_OPC_JALRP,
-  TILE_OPC_JB,
-  TILE_OPC_JF,
-  TILE_OPC_JR,
-  TILE_OPC_JRP,
-  TILE_OPC_LB,
-  TILE_OPC_LB_SN,
-  TILE_OPC_LB_U,
-  TILE_OPC_LB_U_SN,
-  TILE_OPC_LBADD,
-  TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U,
-  TILE_OPC_LBADD_U_SN,
-  TILE_OPC_LH,
-  TILE_OPC_LH_SN,
-  TILE_OPC_LH_U,
-  TILE_OPC_LH_U_SN,
-  TILE_OPC_LHADD,
-  TILE_OPC_LHADD_SN,
-  TILE_OPC_LHADD_U,
-  TILE_OPC_LHADD_U_SN,
-  TILE_OPC_LNK,
-  TILE_OPC_LNK_SN,
-  TILE_OPC_LW,
-  TILE_OPC_LW_SN,
-  TILE_OPC_LW_NA,
-  TILE_OPC_LW_NA_SN,
-  TILE_OPC_LWADD,
-  TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA,
-  TILE_OPC_LWADD_NA_SN,
-  TILE_OPC_MAXB_U,
-  TILE_OPC_MAXB_U_SN,
-  TILE_OPC_MAXH,
-  TILE_OPC_MAXH_SN,
-  TILE_OPC_MAXIB_U,
-  TILE_OPC_MAXIB_U_SN,
-  TILE_OPC_MAXIH,
-  TILE_OPC_MAXIH_SN,
-  TILE_OPC_MF,
-  TILE_OPC_MFSPR,
-  TILE_OPC_MINB_U,
-  TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH,
-  TILE_OPC_MINH_SN,
-  TILE_OPC_MINIB_U,
-  TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH,
-  TILE_OPC_MINIH_SN,
-  TILE_OPC_MM,
-  TILE_OPC_MNZ,
-  TILE_OPC_MNZ_SN,
-  TILE_OPC_MNZB,
-  TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH,
-  TILE_OPC_MNZH_SN,
-  TILE_OPC_MTSPR,
-  TILE_OPC_MULHH_SS,
-  TILE_OPC_MULHH_SS_SN,
-  TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_SU_SN,
-  TILE_OPC_MULHH_UU,
-  TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHHA_SS,
-  TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU,
-  TILE_OPC_MULHHA_SU_SN,
-  TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHA_UU_SN,
-  TILE_OPC_MULHHSA_UU,
-  TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU,
-  TILE_OPC_MULHL_SU_SN,
-  TILE_OPC_MULHL_US,
-  TILE_OPC_MULHL_US_SN,
-  TILE_OPC_MULHL_UU,
-  TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULHLA_SS,
-  TILE_OPC_MULHLA_SS_SN,
-  TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_SU_SN,
-  TILE_OPC_MULHLA_US,
-  TILE_OPC_MULHLA_US_SN,
-  TILE_OPC_MULHLA_UU,
-  TILE_OPC_MULHLA_UU_SN,
-  TILE_OPC_MULHLSA_UU,
-  TILE_OPC_MULHLSA_UU_SN,
-  TILE_OPC_MULLL_SS,
-  TILE_OPC_MULLL_SS_SN,
-  TILE_OPC_MULLL_SU,
-  TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU,
-  TILE_OPC_MULLL_UU_SN,
-  TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SS_SN,
-  TILE_OPC_MULLLA_SU,
-  TILE_OPC_MULLLA_SU_SN,
-  TILE_OPC_MULLLA_UU,
-  TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLLSA_UU_SN,
-  TILE_OPC_MVNZ,
-  TILE_OPC_MVNZ_SN,
-  TILE_OPC_MVZ,
-  TILE_OPC_MVZ_SN,
-  TILE_OPC_MZ,
-  TILE_OPC_MZ_SN,
-  TILE_OPC_MZB,
-  TILE_OPC_MZB_SN,
-  TILE_OPC_MZH,
-  TILE_OPC_MZH_SN,
-  TILE_OPC_NAP,
-  TILE_OPC_NOP,
-  TILE_OPC_NOR,
-  TILE_OPC_NOR_SN,
-  TILE_OPC_OR,
-  TILE_OPC_OR_SN,
-  TILE_OPC_ORI,
-  TILE_OPC_ORI_SN,
-  TILE_OPC_PACKBS_U,
-  TILE_OPC_PACKBS_U_SN,
-  TILE_OPC_PACKHB,
-  TILE_OPC_PACKHB_SN,
-  TILE_OPC_PACKHS,
-  TILE_OPC_PACKHS_SN,
-  TILE_OPC_PACKLB,
-  TILE_OPC_PACKLB_SN,
-  TILE_OPC_PCNT,
-  TILE_OPC_PCNT_SN,
-  TILE_OPC_RL,
-  TILE_OPC_RL_SN,
-  TILE_OPC_RLI,
-  TILE_OPC_RLI_SN,
-  TILE_OPC_S1A,
-  TILE_OPC_S1A_SN,
-  TILE_OPC_S2A,
-  TILE_OPC_S2A_SN,
-  TILE_OPC_S3A,
-  TILE_OPC_S3A_SN,
-  TILE_OPC_SADAB_U,
-  TILE_OPC_SADAB_U_SN,
-  TILE_OPC_SADAH,
-  TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U,
-  TILE_OPC_SADAH_U_SN,
-  TILE_OPC_SADB_U,
-  TILE_OPC_SADB_U_SN,
-  TILE_OPC_SADH,
-  TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U,
-  TILE_OPC_SADH_U_SN,
-  TILE_OPC_SB,
-  TILE_OPC_SBADD,
-  TILE_OPC_SEQ,
-  TILE_OPC_SEQ_SN,
-  TILE_OPC_SEQB,
-  TILE_OPC_SEQB_SN,
-  TILE_OPC_SEQH,
-  TILE_OPC_SEQH_SN,
-  TILE_OPC_SEQI,
-  TILE_OPC_SEQI_SN,
-  TILE_OPC_SEQIB,
-  TILE_OPC_SEQIB_SN,
-  TILE_OPC_SEQIH,
-  TILE_OPC_SEQIH_SN,
-  TILE_OPC_SH,
-  TILE_OPC_SHADD,
-  TILE_OPC_SHL,
-  TILE_OPC_SHL_SN,
-  TILE_OPC_SHLB,
-  TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH,
-  TILE_OPC_SHLH_SN,
-  TILE_OPC_SHLI,
-  TILE_OPC_SHLI_SN,
-  TILE_OPC_SHLIB,
-  TILE_OPC_SHLIB_SN,
-  TILE_OPC_SHLIH,
-  TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHR,
-  TILE_OPC_SHR_SN,
-  TILE_OPC_SHRB,
-  TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH,
-  TILE_OPC_SHRH_SN,
-  TILE_OPC_SHRI,
-  TILE_OPC_SHRI_SN,
-  TILE_OPC_SHRIB,
-  TILE_OPC_SHRIB_SN,
-  TILE_OPC_SHRIH,
-  TILE_OPC_SHRIH_SN,
-  TILE_OPC_SLT,
-  TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U,
-  TILE_OPC_SLT_U_SN,
-  TILE_OPC_SLTB,
-  TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U,
-  TILE_OPC_SLTB_U_SN,
-  TILE_OPC_SLTE,
-  TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U,
-  TILE_OPC_SLTE_U_SN,
-  TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U,
-  TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_SN,
-  TILE_OPC_SLTEH_U,
-  TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTH,
-  TILE_OPC_SLTH_SN,
-  TILE_OPC_SLTH_U,
-  TILE_OPC_SLTH_U_SN,
-  TILE_OPC_SLTI,
-  TILE_OPC_SLTI_SN,
-  TILE_OPC_SLTI_U,
-  TILE_OPC_SLTI_U_SN,
-  TILE_OPC_SLTIB,
-  TILE_OPC_SLTIB_SN,
-  TILE_OPC_SLTIB_U,
-  TILE_OPC_SLTIB_U_SN,
-  TILE_OPC_SLTIH,
-  TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U,
-  TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SNE,
-  TILE_OPC_SNE_SN,
-  TILE_OPC_SNEB,
-  TILE_OPC_SNEB_SN,
-  TILE_OPC_SNEH,
-  TILE_OPC_SNEH_SN,
-  TILE_OPC_SRA,
-  TILE_OPC_SRA_SN,
-  TILE_OPC_SRAB,
-  TILE_OPC_SRAB_SN,
-  TILE_OPC_SRAH,
-  TILE_OPC_SRAH_SN,
-  TILE_OPC_SRAI,
-  TILE_OPC_SRAI_SN,
-  TILE_OPC_SRAIB,
-  TILE_OPC_SRAIB_SN,
-  TILE_OPC_SRAIH,
-  TILE_OPC_SRAIH_SN,
-  TILE_OPC_SUB,
-  TILE_OPC_SUB_SN,
-  TILE_OPC_SUBB,
-  TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBBS_U,
-  TILE_OPC_SUBBS_U_SN,
-  TILE_OPC_SUBH,
-  TILE_OPC_SUBH_SN,
-  TILE_OPC_SUBHS,
-  TILE_OPC_SUBHS_SN,
-  TILE_OPC_SUBS,
-  TILE_OPC_SUBS_SN,
-  TILE_OPC_SW,
-  TILE_OPC_SWADD,
-  TILE_OPC_SWINT0,
-  TILE_OPC_SWINT1,
-  TILE_OPC_SWINT2,
-  TILE_OPC_SWINT3,
-  TILE_OPC_TBLIDXB0,
-  TILE_OPC_TBLIDXB0_SN,
-  TILE_OPC_TBLIDXB1,
-  TILE_OPC_TBLIDXB1_SN,
-  TILE_OPC_TBLIDXB2,
-  TILE_OPC_TBLIDXB2_SN,
-  TILE_OPC_TBLIDXB3,
-  TILE_OPC_TBLIDXB3_SN,
-  TILE_OPC_TNS,
-  TILE_OPC_TNS_SN,
-  TILE_OPC_WH64,
-  TILE_OPC_XOR,
-  TILE_OPC_XOR_SN,
-  TILE_OPC_XORI,
-  TILE_OPC_XORI_SN,
-  TILE_OPC_NONE
-} tile_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILEPRO
-
-#define TILE_ELF_NAME "elf32-tilepro"
-
-
-static __inline unsigned int
-get_BrOff_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000);
-}
-
-static __inline unsigned int
-get_BrType_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0xf);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 2)) & 0x3);
-}
-
-static __inline unsigned int
-get_Dest_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmRROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 8)) & 0x3);
-}
-
-static __inline unsigned int
-get_JOffLong_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x18000000);
-}
-
-static __inline unsigned int
-get_JOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x08000000);
-}
-
-static __inline unsigned int
-get_MF_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x00003fff) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_MMEnd_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMEnd_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 23)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MT_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_Mode(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 63)) & 0x1);
-}
-
-static __inline unsigned int
-get_NoRegOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 10)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 56)) & 0x7);
-}
-
-static __inline unsigned int
-get_RROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 4)) & 0xf);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_RouteOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_S_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0x1);
-}
-
-static __inline unsigned int
-get_S_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tile_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 50)) & 0x0000003e);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Src_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x7);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x7);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tile_bundle_bits
-create_BrOff_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20);
-}
-
-static __inline tile_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Dest_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 2);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7f)) << 51);
-}
-
-static __inline tile_bundle_bits
-create_ImmRROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 8);
-}
-
-static __inline tile_bundle_bits
-create_JOffLong_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x18000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_JOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x08000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_MF_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00003fff)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 18);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 23);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tile_bundle_bits
-create_MT_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x00003fc0)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 63);
-}
-
-static __inline tile_bundle_bits
-create_NoRegOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 10);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 56);
-}
-
-static __inline tile_bundle_bits
-create_RROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 4);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1ff) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1ff)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RouteOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_S_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1) << 27);
-}
-
-static __inline tile_bundle_bits
-create_S_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tile_bundle_bits)(n & 0x0000003e)) << 50);
-}
-
-static __inline tile_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Src_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 0);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3ff)) << 48);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 48);
-}
-
-
-
-typedef enum
-{
-  TILE_PIPELINE_X0,
-  TILE_PIPELINE_X1,
-  TILE_PIPELINE_Y0,
-  TILE_PIPELINE_Y1,
-  TILE_PIPELINE_Y2,
-} tile_pipeline;
-
-#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1)
-
-typedef enum
-{
-  TILE_OP_TYPE_REGISTER,
-  TILE_OP_TYPE_IMMEDIATE,
-  TILE_OP_TYPE_ADDRESS,
-  TILE_OP_TYPE_SPR
-} tile_operand_type;
-
-/* This is the bit that determines if a bundle is in the Y encoding. */
-#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILE_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */
-  TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILE_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */
-  TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
-
-  /* Static network instructions take this many bytes. */
-  TILE_SN_INSTRUCTION_SIZE_IN_BYTES =
-    (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILE_NUM_REGISTERS = 64,
-
-  /* Number of static network registers. */
-  TILE_NUM_SN_REGISTERS = 4
-};
-
-
-struct tile_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tile_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tile_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tile_bundle_bits bundle);
-};
-
-
-extern const struct tile_operand tile_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS];
-
-
-struct tile_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tile_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tile_operands[] table. */
-  unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS];
-
-};
-
-extern const struct tile_opcode tile_opcodes[];
-
-
-/* Used for non-textual disassembly into structs. */
-struct tile_decoded_instruction
-{
-  const struct tile_opcode *opcode;
-  const struct tile_operand *operands[TILE_MAX_OPERANDS];
-  int operand_values[TILE_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tile(tile_bundle_bits bits,
-                           unsigned int pc,
-                           struct tile_decoded_instruction
-                           decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-/* Given a set of bundle bits and a specific pipe, returns which
- * instruction the bundle contains in that pipe.
- */
-extern const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe);
-
-
-
-#endif /* opcode_tile_h */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile_64.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile_64.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1248 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tilegx_bundle_bits;
-
-
-enum
-{
-  TILEGX_MAX_OPERANDS = 4 /* bfexts */
-};
-
-typedef enum
-{
-  TILEGX_OPC_BPT,
-  TILEGX_OPC_INFO,
-  TILEGX_OPC_INFOL,
-  TILEGX_OPC_MOVE,
-  TILEGX_OPC_MOVEI,
-  TILEGX_OPC_MOVELI,
-  TILEGX_OPC_PREFETCH,
-  TILEGX_OPC_PREFETCH_ADD_L1,
-  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L2,
-  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L3,
-  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
-  TILEGX_OPC_PREFETCH_L1,
-  TILEGX_OPC_PREFETCH_L1_FAULT,
-  TILEGX_OPC_PREFETCH_L2,
-  TILEGX_OPC_PREFETCH_L2_FAULT,
-  TILEGX_OPC_PREFETCH_L3,
-  TILEGX_OPC_PREFETCH_L3_FAULT,
-  TILEGX_OPC_RAISE,
-  TILEGX_OPC_ADD,
-  TILEGX_OPC_ADDI,
-  TILEGX_OPC_ADDLI,
-  TILEGX_OPC_ADDX,
-  TILEGX_OPC_ADDXI,
-  TILEGX_OPC_ADDXLI,
-  TILEGX_OPC_ADDXSC,
-  TILEGX_OPC_AND,
-  TILEGX_OPC_ANDI,
-  TILEGX_OPC_BEQZ,
-  TILEGX_OPC_BEQZT,
-  TILEGX_OPC_BFEXTS,
-  TILEGX_OPC_BFEXTU,
-  TILEGX_OPC_BFINS,
-  TILEGX_OPC_BGEZ,
-  TILEGX_OPC_BGEZT,
-  TILEGX_OPC_BGTZ,
-  TILEGX_OPC_BGTZT,
-  TILEGX_OPC_BLBC,
-  TILEGX_OPC_BLBCT,
-  TILEGX_OPC_BLBS,
-  TILEGX_OPC_BLBST,
-  TILEGX_OPC_BLEZ,
-  TILEGX_OPC_BLEZT,
-  TILEGX_OPC_BLTZ,
-  TILEGX_OPC_BLTZT,
-  TILEGX_OPC_BNEZ,
-  TILEGX_OPC_BNEZT,
-  TILEGX_OPC_CLZ,
-  TILEGX_OPC_CMOVEQZ,
-  TILEGX_OPC_CMOVNEZ,
-  TILEGX_OPC_CMPEQ,
-  TILEGX_OPC_CMPEQI,
-  TILEGX_OPC_CMPEXCH,
-  TILEGX_OPC_CMPEXCH4,
-  TILEGX_OPC_CMPLES,
-  TILEGX_OPC_CMPLEU,
-  TILEGX_OPC_CMPLTS,
-  TILEGX_OPC_CMPLTSI,
-  TILEGX_OPC_CMPLTU,
-  TILEGX_OPC_CMPLTUI,
-  TILEGX_OPC_CMPNE,
-  TILEGX_OPC_CMUL,
-  TILEGX_OPC_CMULA,
-  TILEGX_OPC_CMULAF,
-  TILEGX_OPC_CMULF,
-  TILEGX_OPC_CMULFR,
-  TILEGX_OPC_CMULH,
-  TILEGX_OPC_CMULHR,
-  TILEGX_OPC_CRC32_32,
-  TILEGX_OPC_CRC32_8,
-  TILEGX_OPC_CTZ,
-  TILEGX_OPC_DBLALIGN,
-  TILEGX_OPC_DBLALIGN2,
-  TILEGX_OPC_DBLALIGN4,
-  TILEGX_OPC_DBLALIGN6,
-  TILEGX_OPC_DRAIN,
-  TILEGX_OPC_DTLBPR,
-  TILEGX_OPC_EXCH,
-  TILEGX_OPC_EXCH4,
-  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
-  TILEGX_OPC_FDOUBLE_ADDSUB,
-  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
-  TILEGX_OPC_FDOUBLE_PACK1,
-  TILEGX_OPC_FDOUBLE_PACK2,
-  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
-  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
-  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
-  TILEGX_OPC_FETCHADD,
-  TILEGX_OPC_FETCHADD4,
-  TILEGX_OPC_FETCHADDGEZ,
-  TILEGX_OPC_FETCHADDGEZ4,
-  TILEGX_OPC_FETCHAND,
-  TILEGX_OPC_FETCHAND4,
-  TILEGX_OPC_FETCHOR,
-  TILEGX_OPC_FETCHOR4,
-  TILEGX_OPC_FINV,
-  TILEGX_OPC_FLUSH,
-  TILEGX_OPC_FLUSHWB,
-  TILEGX_OPC_FNOP,
-  TILEGX_OPC_FSINGLE_ADD1,
-  TILEGX_OPC_FSINGLE_ADDSUB2,
-  TILEGX_OPC_FSINGLE_MUL1,
-  TILEGX_OPC_FSINGLE_MUL2,
-  TILEGX_OPC_FSINGLE_PACK1,
-  TILEGX_OPC_FSINGLE_PACK2,
-  TILEGX_OPC_FSINGLE_SUB1,
-  TILEGX_OPC_ICOH,
-  TILEGX_OPC_ILL,
-  TILEGX_OPC_INV,
-  TILEGX_OPC_IRET,
-  TILEGX_OPC_J,
-  TILEGX_OPC_JAL,
-  TILEGX_OPC_JALR,
-  TILEGX_OPC_JALRP,
-  TILEGX_OPC_JR,
-  TILEGX_OPC_JRP,
-  TILEGX_OPC_LD,
-  TILEGX_OPC_LD1S,
-  TILEGX_OPC_LD1S_ADD,
-  TILEGX_OPC_LD1U,
-  TILEGX_OPC_LD1U_ADD,
-  TILEGX_OPC_LD2S,
-  TILEGX_OPC_LD2S_ADD,
-  TILEGX_OPC_LD2U,
-  TILEGX_OPC_LD2U_ADD,
-  TILEGX_OPC_LD4S,
-  TILEGX_OPC_LD4S_ADD,
-  TILEGX_OPC_LD4U,
-  TILEGX_OPC_LD4U_ADD,
-  TILEGX_OPC_LD_ADD,
-  TILEGX_OPC_LDNA,
-  TILEGX_OPC_LDNA_ADD,
-  TILEGX_OPC_LDNT,
-  TILEGX_OPC_LDNT1S,
-  TILEGX_OPC_LDNT1S_ADD,
-  TILEGX_OPC_LDNT1U,
-  TILEGX_OPC_LDNT1U_ADD,
-  TILEGX_OPC_LDNT2S,
-  TILEGX_OPC_LDNT2S_ADD,
-  TILEGX_OPC_LDNT2U,
-  TILEGX_OPC_LDNT2U_ADD,
-  TILEGX_OPC_LDNT4S,
-  TILEGX_OPC_LDNT4S_ADD,
-  TILEGX_OPC_LDNT4U,
-  TILEGX_OPC_LDNT4U_ADD,
-  TILEGX_OPC_LDNT_ADD,
-  TILEGX_OPC_LNK,
-  TILEGX_OPC_MF,
-  TILEGX_OPC_MFSPR,
-  TILEGX_OPC_MM,
-  TILEGX_OPC_MNZ,
-  TILEGX_OPC_MTSPR,
-  TILEGX_OPC_MUL_HS_HS,
-  TILEGX_OPC_MUL_HS_HU,
-  TILEGX_OPC_MUL_HS_LS,
-  TILEGX_OPC_MUL_HS_LU,
-  TILEGX_OPC_MUL_HU_HU,
-  TILEGX_OPC_MUL_HU_LS,
-  TILEGX_OPC_MUL_HU_LU,
-  TILEGX_OPC_MUL_LS_LS,
-  TILEGX_OPC_MUL_LS_LU,
-  TILEGX_OPC_MUL_LU_LU,
-  TILEGX_OPC_MULA_HS_HS,
-  TILEGX_OPC_MULA_HS_HU,
-  TILEGX_OPC_MULA_HS_LS,
-  TILEGX_OPC_MULA_HS_LU,
-  TILEGX_OPC_MULA_HU_HU,
-  TILEGX_OPC_MULA_HU_LS,
-  TILEGX_OPC_MULA_HU_LU,
-  TILEGX_OPC_MULA_LS_LS,
-  TILEGX_OPC_MULA_LS_LU,
-  TILEGX_OPC_MULA_LU_LU,
-  TILEGX_OPC_MULAX,
-  TILEGX_OPC_MULX,
-  TILEGX_OPC_MZ,
-  TILEGX_OPC_NAP,
-  TILEGX_OPC_NOP,
-  TILEGX_OPC_NOR,
-  TILEGX_OPC_OR,
-  TILEGX_OPC_ORI,
-  TILEGX_OPC_PCNT,
-  TILEGX_OPC_REVBITS,
-  TILEGX_OPC_REVBYTES,
-  TILEGX_OPC_ROTL,
-  TILEGX_OPC_ROTLI,
-  TILEGX_OPC_SHL,
-  TILEGX_OPC_SHL16INSLI,
-  TILEGX_OPC_SHL1ADD,
-  TILEGX_OPC_SHL1ADDX,
-  TILEGX_OPC_SHL2ADD,
-  TILEGX_OPC_SHL2ADDX,
-  TILEGX_OPC_SHL3ADD,
-  TILEGX_OPC_SHL3ADDX,
-  TILEGX_OPC_SHLI,
-  TILEGX_OPC_SHLX,
-  TILEGX_OPC_SHLXI,
-  TILEGX_OPC_SHRS,
-  TILEGX_OPC_SHRSI,
-  TILEGX_OPC_SHRU,
-  TILEGX_OPC_SHRUI,
-  TILEGX_OPC_SHRUX,
-  TILEGX_OPC_SHRUXI,
-  TILEGX_OPC_SHUFFLEBYTES,
-  TILEGX_OPC_ST,
-  TILEGX_OPC_ST1,
-  TILEGX_OPC_ST1_ADD,
-  TILEGX_OPC_ST2,
-  TILEGX_OPC_ST2_ADD,
-  TILEGX_OPC_ST4,
-  TILEGX_OPC_ST4_ADD,
-  TILEGX_OPC_ST_ADD,
-  TILEGX_OPC_STNT,
-  TILEGX_OPC_STNT1,
-  TILEGX_OPC_STNT1_ADD,
-  TILEGX_OPC_STNT2,
-  TILEGX_OPC_STNT2_ADD,
-  TILEGX_OPC_STNT4,
-  TILEGX_OPC_STNT4_ADD,
-  TILEGX_OPC_STNT_ADD,
-  TILEGX_OPC_SUB,
-  TILEGX_OPC_SUBX,
-  TILEGX_OPC_SUBXSC,
-  TILEGX_OPC_SWINT0,
-  TILEGX_OPC_SWINT1,
-  TILEGX_OPC_SWINT2,
-  TILEGX_OPC_SWINT3,
-  TILEGX_OPC_TBLIDXB0,
-  TILEGX_OPC_TBLIDXB1,
-  TILEGX_OPC_TBLIDXB2,
-  TILEGX_OPC_TBLIDXB3,
-  TILEGX_OPC_V1ADD,
-  TILEGX_OPC_V1ADDI,
-  TILEGX_OPC_V1ADDUC,
-  TILEGX_OPC_V1ADIFFU,
-  TILEGX_OPC_V1AVGU,
-  TILEGX_OPC_V1CMPEQ,
-  TILEGX_OPC_V1CMPEQI,
-  TILEGX_OPC_V1CMPLES,
-  TILEGX_OPC_V1CMPLEU,
-  TILEGX_OPC_V1CMPLTS,
-  TILEGX_OPC_V1CMPLTSI,
-  TILEGX_OPC_V1CMPLTU,
-  TILEGX_OPC_V1CMPLTUI,
-  TILEGX_OPC_V1CMPNE,
-  TILEGX_OPC_V1DDOTPU,
-  TILEGX_OPC_V1DDOTPUA,
-  TILEGX_OPC_V1DDOTPUS,
-  TILEGX_OPC_V1DDOTPUSA,
-  TILEGX_OPC_V1DOTP,
-  TILEGX_OPC_V1DOTPA,
-  TILEGX_OPC_V1DOTPU,
-  TILEGX_OPC_V1DOTPUA,
-  TILEGX_OPC_V1DOTPUS,
-  TILEGX_OPC_V1DOTPUSA,
-  TILEGX_OPC_V1INT_H,
-  TILEGX_OPC_V1INT_L,
-  TILEGX_OPC_V1MAXU,
-  TILEGX_OPC_V1MAXUI,
-  TILEGX_OPC_V1MINU,
-  TILEGX_OPC_V1MINUI,
-  TILEGX_OPC_V1MNZ,
-  TILEGX_OPC_V1MULTU,
-  TILEGX_OPC_V1MULU,
-  TILEGX_OPC_V1MULUS,
-  TILEGX_OPC_V1MZ,
-  TILEGX_OPC_V1SADAU,
-  TILEGX_OPC_V1SADU,
-  TILEGX_OPC_V1SHL,
-  TILEGX_OPC_V1SHLI,
-  TILEGX_OPC_V1SHRS,
-  TILEGX_OPC_V1SHRSI,
-  TILEGX_OPC_V1SHRU,
-  TILEGX_OPC_V1SHRUI,
-  TILEGX_OPC_V1SUB,
-  TILEGX_OPC_V1SUBUC,
-  TILEGX_OPC_V2ADD,
-  TILEGX_OPC_V2ADDI,
-  TILEGX_OPC_V2ADDSC,
-  TILEGX_OPC_V2ADIFFS,
-  TILEGX_OPC_V2AVGS,
-  TILEGX_OPC_V2CMPEQ,
-  TILEGX_OPC_V2CMPEQI,
-  TILEGX_OPC_V2CMPLES,
-  TILEGX_OPC_V2CMPLEU,
-  TILEGX_OPC_V2CMPLTS,
-  TILEGX_OPC_V2CMPLTSI,
-  TILEGX_OPC_V2CMPLTU,
-  TILEGX_OPC_V2CMPLTUI,
-  TILEGX_OPC_V2CMPNE,
-  TILEGX_OPC_V2DOTP,
-  TILEGX_OPC_V2DOTPA,
-  TILEGX_OPC_V2INT_H,
-  TILEGX_OPC_V2INT_L,
-  TILEGX_OPC_V2MAXS,
-  TILEGX_OPC_V2MAXSI,
-  TILEGX_OPC_V2MINS,
-  TILEGX_OPC_V2MINSI,
-  TILEGX_OPC_V2MNZ,
-  TILEGX_OPC_V2MULFSC,
-  TILEGX_OPC_V2MULS,
-  TILEGX_OPC_V2MULTS,
-  TILEGX_OPC_V2MZ,
-  TILEGX_OPC_V2PACKH,
-  TILEGX_OPC_V2PACKL,
-  TILEGX_OPC_V2PACKUC,
-  TILEGX_OPC_V2SADAS,
-  TILEGX_OPC_V2SADAU,
-  TILEGX_OPC_V2SADS,
-  TILEGX_OPC_V2SADU,
-  TILEGX_OPC_V2SHL,
-  TILEGX_OPC_V2SHLI,
-  TILEGX_OPC_V2SHLSC,
-  TILEGX_OPC_V2SHRS,
-  TILEGX_OPC_V2SHRSI,
-  TILEGX_OPC_V2SHRU,
-  TILEGX_OPC_V2SHRUI,
-  TILEGX_OPC_V2SUB,
-  TILEGX_OPC_V2SUBSC,
-  TILEGX_OPC_V4ADD,
-  TILEGX_OPC_V4ADDSC,
-  TILEGX_OPC_V4INT_H,
-  TILEGX_OPC_V4INT_L,
-  TILEGX_OPC_V4PACKSC,
-  TILEGX_OPC_V4SHL,
-  TILEGX_OPC_V4SHLSC,
-  TILEGX_OPC_V4SHRS,
-  TILEGX_OPC_V4SHRU,
-  TILEGX_OPC_V4SUB,
-  TILEGX_OPC_V4SUBSC,
-  TILEGX_OPC_WH64,
-  TILEGX_OPC_XOR,
-  TILEGX_OPC_XORI,
-  TILEGX_OPC_NONE
-} tilegx_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILE64
-
-#define TILE_ELF_NAME "elf32-tile64"
-
-
-static __inline unsigned int
-get_BFEnd_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 24)) & 0xf);
-}
-
-static __inline unsigned int
-get_BFStart_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x0001ffc0);
-}
-
-static __inline unsigned int
-get_BrType_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_JumpOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x7ffffff);
-}
-
-static __inline unsigned int
-get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_MF_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3fff);
-}
-
-static __inline unsigned int
-get_MT_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0);
-}
-
-static __inline unsigned int
-get_Mode(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 62)) & 0x3);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tilegx_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 56)) & 0x00000002);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tilegx_bundle_bits
-create_BFEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_BFOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 24);
-}
-
-static __inline tilegx_bundle_bits
-create_BFStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_MF_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_MT_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-
-typedef enum
-{
-  TILEGX_PIPELINE_X0,
-  TILEGX_PIPELINE_X1,
-  TILEGX_PIPELINE_Y0,
-  TILEGX_PIPELINE_Y1,
-  TILEGX_PIPELINE_Y2,
-} tilegx_pipeline;
-
-#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
-
-typedef enum
-{
-  TILEGX_OP_TYPE_REGISTER,
-  TILEGX_OP_TYPE_IMMEDIATE,
-  TILEGX_OP_TYPE_ADDRESS,
-  TILEGX_OP_TYPE_SPR
-} tilegx_operand_type;
-
-/* These are the bits that determine if a bundle is in the X encoding. */
-#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILEGX_NUM_REGISTERS = 64,
-};
-
-
-struct tilegx_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tilegx_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tilegx_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tilegx_bundle_bits bundle);
-};
-
-
-extern const struct tilegx_operand tilegx_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
-
-
-struct tilegx_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tilegx_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tilegx_operands[] table. */
-  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
-
-};
-
-extern const struct tilegx_opcode tilegx_opcodes[];
-
-/* Used for non-textual disassembly into structs. */
-struct tilegx_decoded_instruction
-{
-  const struct tilegx_opcode *opcode;
-  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
-  long long operand_values[TILEGX_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tilegx(tilegx_bundle_bits bits,
-                             unsigned long long pc,
-                             struct tilegx_decoded_instruction
-                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-
-#endif /* opcode_tilegx_h */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile.h linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/opcode-tile.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/opcode-tile.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-#ifndef _ASM_TILE_OPCODE_TILE_H
-#define _ASM_TILE_OPCODE_TILE_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode-tile_64.h>
-#else
-#include <asm/opcode-tile_32.h>
-#endif
-
-/* These definitions are not correct for TILE64, so just avoid them. */
-#undef TILE_ELF_MACHINE_CODE
-#undef TILE_ELF_NAME
-
-#endif /* _ASM_TILE_OPCODE_TILE_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/sigcontext.h linux-libre-3.2-gnu1/arch/tile/include/asm/sigcontext.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/sigcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,8 @@
 #ifndef _ASM_TILE_SIGCONTEXT_H
 #define _ASM_TILE_SIGCONTEXT_H
 
+/* Don't pollute the namespace since <signal.h> includes this file. */
+#define __need_int_reg_t
 #include <arch/abi.h>
 
 /*
@@ -22,14 +24,14 @@
  * but is simplified since we know the fault is from userspace.
  */
 struct sigcontext {
-	uint_reg_t gregs[53];	/* General-purpose registers.  */
-	uint_reg_t tp;		/* Aliases gregs[TREG_TP].  */
-	uint_reg_t sp;		/* Aliases gregs[TREG_SP].  */
-	uint_reg_t lr;		/* Aliases gregs[TREG_LR].  */
-	uint_reg_t pc;		/* Program counter.  */
-	uint_reg_t ics;		/* In Interrupt Critical Section?  */
-	uint_reg_t faultnum;	/* Fault number.  */
-	uint_reg_t pad[5];
+	__uint_reg_t gregs[53];	/* General-purpose registers.  */
+	__uint_reg_t tp;	/* Aliases gregs[TREG_TP].  */
+	__uint_reg_t sp;	/* Aliases gregs[TREG_SP].  */
+	__uint_reg_t lr;	/* Aliases gregs[TREG_LR].  */
+	__uint_reg_t pc;	/* Program counter.  */
+	__uint_reg_t ics;	/* In Interrupt Critical Section?  */
+	__uint_reg_t faultnum;	/* Fault number.  */
+	__uint_reg_t pad[5];
 };
 
 #endif /* _ASM_TILE_SIGCONTEXT_H */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc_32.h linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc_32.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,553 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef opcode_tilepro_h
+#define opcode_tilepro_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEPRO_MAX_OPERANDS = 5 /* mm */
+};
+
+typedef enum
+{
+  TILEPRO_OPC_BPT,
+  TILEPRO_OPC_INFO,
+  TILEPRO_OPC_INFOL,
+  TILEPRO_OPC_J,
+  TILEPRO_OPC_JAL,
+  TILEPRO_OPC_MOVE,
+  TILEPRO_OPC_MOVE_SN,
+  TILEPRO_OPC_MOVEI,
+  TILEPRO_OPC_MOVEI_SN,
+  TILEPRO_OPC_MOVELI,
+  TILEPRO_OPC_MOVELI_SN,
+  TILEPRO_OPC_MOVELIS,
+  TILEPRO_OPC_PREFETCH,
+  TILEPRO_OPC_RAISE,
+  TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADD_SN,
+  TILEPRO_OPC_ADDB,
+  TILEPRO_OPC_ADDB_SN,
+  TILEPRO_OPC_ADDBS_U,
+  TILEPRO_OPC_ADDBS_U_SN,
+  TILEPRO_OPC_ADDH,
+  TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADDHS,
+  TILEPRO_OPC_ADDHS_SN,
+  TILEPRO_OPC_ADDI,
+  TILEPRO_OPC_ADDI_SN,
+  TILEPRO_OPC_ADDIB,
+  TILEPRO_OPC_ADDIB_SN,
+  TILEPRO_OPC_ADDIH,
+  TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDLI,
+  TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_ADDLIS,
+  TILEPRO_OPC_ADDS,
+  TILEPRO_OPC_ADDS_SN,
+  TILEPRO_OPC_ADIFFB_U,
+  TILEPRO_OPC_ADIFFB_U_SN,
+  TILEPRO_OPC_ADIFFH,
+  TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND,
+  TILEPRO_OPC_AND_SN,
+  TILEPRO_OPC_ANDI,
+  TILEPRO_OPC_ANDI_SN,
+  TILEPRO_OPC_AULI,
+  TILEPRO_OPC_AVGB_U,
+  TILEPRO_OPC_AVGB_U_SN,
+  TILEPRO_OPC_AVGH,
+  TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_BBNS,
+  TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST,
+  TILEPRO_OPC_BBNST_SN,
+  TILEPRO_OPC_BBS,
+  TILEPRO_OPC_BBS_SN,
+  TILEPRO_OPC_BBST,
+  TILEPRO_OPC_BBST_SN,
+  TILEPRO_OPC_BGEZ,
+  TILEPRO_OPC_BGEZ_SN,
+  TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BGEZT_SN,
+  TILEPRO_OPC_BGZ,
+  TILEPRO_OPC_BGZ_SN,
+  TILEPRO_OPC_BGZT,
+  TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BITX,
+  TILEPRO_OPC_BITX_SN,
+  TILEPRO_OPC_BLEZ,
+  TILEPRO_OPC_BLEZ_SN,
+  TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BLZ,
+  TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT,
+  TILEPRO_OPC_BLZT_SN,
+  TILEPRO_OPC_BNZ,
+  TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BNZT_SN,
+  TILEPRO_OPC_BYTEX,
+  TILEPRO_OPC_BYTEX_SN,
+  TILEPRO_OPC_BZ,
+  TILEPRO_OPC_BZ_SN,
+  TILEPRO_OPC_BZT,
+  TILEPRO_OPC_BZT_SN,
+  TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CLZ_SN,
+  TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_32_SN,
+  TILEPRO_OPC_CRC32_8,
+  TILEPRO_OPC_CRC32_8_SN,
+  TILEPRO_OPC_CTZ,
+  TILEPRO_OPC_CTZ_SN,
+  TILEPRO_OPC_DRAIN,
+  TILEPRO_OPC_DTLBPR,
+  TILEPRO_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_FINV,
+  TILEPRO_OPC_FLUSH,
+  TILEPRO_OPC_FNOP,
+  TILEPRO_OPC_ICOH,
+  TILEPRO_OPC_ILL,
+  TILEPRO_OPC_INTHB,
+  TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTHH_SN,
+  TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLB_SN,
+  TILEPRO_OPC_INTLH,
+  TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_INV,
+  TILEPRO_OPC_IRET,
+  TILEPRO_OPC_JALB,
+  TILEPRO_OPC_JALF,
+  TILEPRO_OPC_JALR,
+  TILEPRO_OPC_JALRP,
+  TILEPRO_OPC_JB,
+  TILEPRO_OPC_JF,
+  TILEPRO_OPC_JR,
+  TILEPRO_OPC_JRP,
+  TILEPRO_OPC_LB,
+  TILEPRO_OPC_LB_SN,
+  TILEPRO_OPC_LB_U,
+  TILEPRO_OPC_LB_U_SN,
+  TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_SN,
+  TILEPRO_OPC_LBADD_U,
+  TILEPRO_OPC_LBADD_U_SN,
+  TILEPRO_OPC_LH,
+  TILEPRO_OPC_LH_SN,
+  TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LH_U_SN,
+  TILEPRO_OPC_LHADD,
+  TILEPRO_OPC_LHADD_SN,
+  TILEPRO_OPC_LHADD_U,
+  TILEPRO_OPC_LHADD_U_SN,
+  TILEPRO_OPC_LNK,
+  TILEPRO_OPC_LNK_SN,
+  TILEPRO_OPC_LW,
+  TILEPRO_OPC_LW_SN,
+  TILEPRO_OPC_LW_NA,
+  TILEPRO_OPC_LW_NA_SN,
+  TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA,
+  TILEPRO_OPC_LWADD_NA_SN,
+  TILEPRO_OPC_MAXB_U,
+  TILEPRO_OPC_MAXB_U_SN,
+  TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MAXIB_U,
+  TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH,
+  TILEPRO_OPC_MAXIH_SN,
+  TILEPRO_OPC_MF,
+  TILEPRO_OPC_MFSPR,
+  TILEPRO_OPC_MINB_U,
+  TILEPRO_OPC_MINB_U_SN,
+  TILEPRO_OPC_MINH,
+  TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH,
+  TILEPRO_OPC_MINIH_SN,
+  TILEPRO_OPC_MM,
+  TILEPRO_OPC_MNZ,
+  TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZH_SN,
+  TILEPRO_OPC_MTSPR,
+  TILEPRO_OPC_MULHH_SS,
+  TILEPRO_OPC_MULHH_SS_SN,
+  TILEPRO_OPC_MULHH_SU,
+  TILEPRO_OPC_MULHH_SU_SN,
+  TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SS_SN,
+  TILEPRO_OPC_MULHHA_SU,
+  TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU,
+  TILEPRO_OPC_MULHHA_UU_SN,
+  TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SS_SN,
+  TILEPRO_OPC_MULHL_SU,
+  TILEPRO_OPC_MULHL_SU_SN,
+  TILEPRO_OPC_MULHL_US,
+  TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULHL_UU_SN,
+  TILEPRO_OPC_MULHLA_SS,
+  TILEPRO_OPC_MULHLA_SS_SN,
+  TILEPRO_OPC_MULHLA_SU,
+  TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US,
+  TILEPRO_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MULHLA_UU,
+  TILEPRO_OPC_MULHLA_UU_SN,
+  TILEPRO_OPC_MULHLSA_UU,
+  TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_SS_SN,
+  TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_SU_SN,
+  TILEPRO_OPC_MULLL_UU,
+  TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_SS_SN,
+  TILEPRO_OPC_MULLLA_SU,
+  TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLA_UU_SN,
+  TILEPRO_OPC_MULLLSA_UU,
+  TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MVNZ,
+  TILEPRO_OPC_MVNZ_SN,
+  TILEPRO_OPC_MVZ,
+  TILEPRO_OPC_MVZ_SN,
+  TILEPRO_OPC_MZ,
+  TILEPRO_OPC_MZ_SN,
+  TILEPRO_OPC_MZB,
+  TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH,
+  TILEPRO_OPC_MZH_SN,
+  TILEPRO_OPC_NAP,
+  TILEPRO_OPC_NOP,
+  TILEPRO_OPC_NOR,
+  TILEPRO_OPC_NOR_SN,
+  TILEPRO_OPC_OR,
+  TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_ORI,
+  TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_PACKBS_U,
+  TILEPRO_OPC_PACKBS_U_SN,
+  TILEPRO_OPC_PACKHB,
+  TILEPRO_OPC_PACKHB_SN,
+  TILEPRO_OPC_PACKHS,
+  TILEPRO_OPC_PACKHS_SN,
+  TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_PACKLB_SN,
+  TILEPRO_OPC_PCNT,
+  TILEPRO_OPC_PCNT_SN,
+  TILEPRO_OPC_RL,
+  TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_RLI,
+  TILEPRO_OPC_RLI_SN,
+  TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S1A_SN,
+  TILEPRO_OPC_S2A,
+  TILEPRO_OPC_S2A_SN,
+  TILEPRO_OPC_S3A,
+  TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U,
+  TILEPRO_OPC_SADAB_U_SN,
+  TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_SN,
+  TILEPRO_OPC_SADAH_U,
+  TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U,
+  TILEPRO_OPC_SADB_U_SN,
+  TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_SN,
+  TILEPRO_OPC_SADH_U,
+  TILEPRO_OPC_SADH_U_SN,
+  TILEPRO_OPC_SB,
+  TILEPRO_OPC_SBADD,
+  TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SEQB,
+  TILEPRO_OPC_SEQB_SN,
+  TILEPRO_OPC_SEQH,
+  TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQI,
+  TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SEQIB,
+  TILEPRO_OPC_SEQIB_SN,
+  TILEPRO_OPC_SEQIH,
+  TILEPRO_OPC_SEQIH_SN,
+  TILEPRO_OPC_SH,
+  TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SHL,
+  TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLB_SN,
+  TILEPRO_OPC_SHLH,
+  TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHLI_SN,
+  TILEPRO_OPC_SHLIB,
+  TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLIH_SN,
+  TILEPRO_OPC_SHR,
+  TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRB_SN,
+  TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SHRI_SN,
+  TILEPRO_OPC_SHRIB,
+  TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH,
+  TILEPRO_OPC_SHRIH_SN,
+  TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_SN,
+  TILEPRO_OPC_SLT_U,
+  TILEPRO_OPC_SLT_U_SN,
+  TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U,
+  TILEPRO_OPC_SLTB_U_SN,
+  TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U,
+  TILEPRO_OPC_SLTE_U_SN,
+  TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH,
+  TILEPRO_OPC_SLTEH_SN,
+  TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTH,
+  TILEPRO_OPC_SLTH_SN,
+  TILEPRO_OPC_SLTH_U,
+  TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLTI,
+  TILEPRO_OPC_SLTI_SN,
+  TILEPRO_OPC_SLTI_U,
+  TILEPRO_OPC_SLTI_U_SN,
+  TILEPRO_OPC_SLTIB,
+  TILEPRO_OPC_SLTIB_SN,
+  TILEPRO_OPC_SLTIB_U,
+  TILEPRO_OPC_SLTIB_U_SN,
+  TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SNE_SN,
+  TILEPRO_OPC_SNEB,
+  TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH,
+  TILEPRO_OPC_SNEH_SN,
+  TILEPRO_OPC_SRA,
+  TILEPRO_OPC_SRA_SN,
+  TILEPRO_OPC_SRAB,
+  TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH,
+  TILEPRO_OPC_SRAH_SN,
+  TILEPRO_OPC_SRAI,
+  TILEPRO_OPC_SRAI_SN,
+  TILEPRO_OPC_SRAIB,
+  TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH,
+  TILEPRO_OPC_SRAIH_SN,
+  TILEPRO_OPC_SUB,
+  TILEPRO_OPC_SUB_SN,
+  TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBBS_U,
+  TILEPRO_OPC_SUBBS_U_SN,
+  TILEPRO_OPC_SUBH,
+  TILEPRO_OPC_SUBH_SN,
+  TILEPRO_OPC_SUBHS,
+  TILEPRO_OPC_SUBHS_SN,
+  TILEPRO_OPC_SUBS,
+  TILEPRO_OPC_SUBS_SN,
+  TILEPRO_OPC_SW,
+  TILEPRO_OPC_SWADD,
+  TILEPRO_OPC_SWINT0,
+  TILEPRO_OPC_SWINT1,
+  TILEPRO_OPC_SWINT2,
+  TILEPRO_OPC_SWINT3,
+  TILEPRO_OPC_TBLIDXB0,
+  TILEPRO_OPC_TBLIDXB0_SN,
+  TILEPRO_OPC_TBLIDXB1,
+  TILEPRO_OPC_TBLIDXB1_SN,
+  TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB2_SN,
+  TILEPRO_OPC_TBLIDXB3,
+  TILEPRO_OPC_TBLIDXB3_SN,
+  TILEPRO_OPC_TNS,
+  TILEPRO_OPC_TNS_SN,
+  TILEPRO_OPC_WH64,
+  TILEPRO_OPC_XOR,
+  TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_XORI,
+  TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE
+} tilepro_mnemonic;
+
+
+
+
+typedef enum
+{
+  TILEPRO_PIPELINE_X0,
+  TILEPRO_PIPELINE_X1,
+  TILEPRO_PIPELINE_Y0,
+  TILEPRO_PIPELINE_Y1,
+  TILEPRO_PIPELINE_Y2,
+} tilepro_pipeline;
+
+#define tilepro_is_x_pipeline(p) ((int)(p) <= (int)TILEPRO_PIPELINE_X1)
+
+typedef enum
+{
+  TILEPRO_OP_TYPE_REGISTER,
+  TILEPRO_OP_TYPE_IMMEDIATE,
+  TILEPRO_OP_TYPE_ADDRESS,
+  TILEPRO_OP_TYPE_SPR
+} tilepro_operand_type;
+
+struct tilepro_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilepro_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilepro_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilepro_bundle_bits bundle);
+};
+
+
+extern const struct tilepro_operand tilepro_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilepro_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilepro_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilepro_operands[] table. */
+  unsigned char operands[TILEPRO_NUM_PIPELINE_ENCODINGS][TILEPRO_MAX_OPERANDS];
+
+};
+
+extern const struct tilepro_opcode tilepro_opcodes[];
+
+
+/* Used for non-textual disassembly into structs. */
+struct tilepro_decoded_instruction
+{
+  const struct tilepro_opcode *opcode;
+  const struct tilepro_operand *operands[TILEPRO_MAX_OPERANDS];
+  int operand_values[TILEPRO_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilepro(tilepro_bundle_bits bits,
+                              unsigned int pc,
+                              struct tilepro_decoded_instruction
+                              decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+/* Given a set of bundle bits and a specific pipe, returns which
+ * instruction the bundle contains in that pipe.
+ */
+extern const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe);
+
+
+
+#endif /* opcode_tilepro_h */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc_64.h linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc_64.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,483 @@
+/* TILE-Gx opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef opcode_tile_h
+#define opcode_tile_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEGX_MAX_OPERANDS = 4 /* bfexts */
+};
+
+typedef enum
+{
+  TILEGX_OPC_BPT,
+  TILEGX_OPC_INFO,
+  TILEGX_OPC_INFOL,
+  TILEGX_OPC_MOVE,
+  TILEGX_OPC_MOVEI,
+  TILEGX_OPC_MOVELI,
+  TILEGX_OPC_PREFETCH,
+  TILEGX_OPC_PREFETCH_ADD_L1,
+  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L2,
+  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L3,
+  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+  TILEGX_OPC_PREFETCH_L1,
+  TILEGX_OPC_PREFETCH_L1_FAULT,
+  TILEGX_OPC_PREFETCH_L2,
+  TILEGX_OPC_PREFETCH_L2_FAULT,
+  TILEGX_OPC_PREFETCH_L3,
+  TILEGX_OPC_PREFETCH_L3_FAULT,
+  TILEGX_OPC_RAISE,
+  TILEGX_OPC_ADD,
+  TILEGX_OPC_ADDI,
+  TILEGX_OPC_ADDLI,
+  TILEGX_OPC_ADDX,
+  TILEGX_OPC_ADDXI,
+  TILEGX_OPC_ADDXLI,
+  TILEGX_OPC_ADDXSC,
+  TILEGX_OPC_AND,
+  TILEGX_OPC_ANDI,
+  TILEGX_OPC_BEQZ,
+  TILEGX_OPC_BEQZT,
+  TILEGX_OPC_BFEXTS,
+  TILEGX_OPC_BFEXTU,
+  TILEGX_OPC_BFINS,
+  TILEGX_OPC_BGEZ,
+  TILEGX_OPC_BGEZT,
+  TILEGX_OPC_BGTZ,
+  TILEGX_OPC_BGTZT,
+  TILEGX_OPC_BLBC,
+  TILEGX_OPC_BLBCT,
+  TILEGX_OPC_BLBS,
+  TILEGX_OPC_BLBST,
+  TILEGX_OPC_BLEZ,
+  TILEGX_OPC_BLEZT,
+  TILEGX_OPC_BLTZ,
+  TILEGX_OPC_BLTZT,
+  TILEGX_OPC_BNEZ,
+  TILEGX_OPC_BNEZT,
+  TILEGX_OPC_CLZ,
+  TILEGX_OPC_CMOVEQZ,
+  TILEGX_OPC_CMOVNEZ,
+  TILEGX_OPC_CMPEQ,
+  TILEGX_OPC_CMPEQI,
+  TILEGX_OPC_CMPEXCH,
+  TILEGX_OPC_CMPEXCH4,
+  TILEGX_OPC_CMPLES,
+  TILEGX_OPC_CMPLEU,
+  TILEGX_OPC_CMPLTS,
+  TILEGX_OPC_CMPLTSI,
+  TILEGX_OPC_CMPLTU,
+  TILEGX_OPC_CMPLTUI,
+  TILEGX_OPC_CMPNE,
+  TILEGX_OPC_CMUL,
+  TILEGX_OPC_CMULA,
+  TILEGX_OPC_CMULAF,
+  TILEGX_OPC_CMULF,
+  TILEGX_OPC_CMULFR,
+  TILEGX_OPC_CMULH,
+  TILEGX_OPC_CMULHR,
+  TILEGX_OPC_CRC32_32,
+  TILEGX_OPC_CRC32_8,
+  TILEGX_OPC_CTZ,
+  TILEGX_OPC_DBLALIGN,
+  TILEGX_OPC_DBLALIGN2,
+  TILEGX_OPC_DBLALIGN4,
+  TILEGX_OPC_DBLALIGN6,
+  TILEGX_OPC_DRAIN,
+  TILEGX_OPC_DTLBPR,
+  TILEGX_OPC_EXCH,
+  TILEGX_OPC_EXCH4,
+  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
+  TILEGX_OPC_FDOUBLE_ADDSUB,
+  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
+  TILEGX_OPC_FDOUBLE_PACK1,
+  TILEGX_OPC_FDOUBLE_PACK2,
+  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
+  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
+  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
+  TILEGX_OPC_FETCHADD,
+  TILEGX_OPC_FETCHADD4,
+  TILEGX_OPC_FETCHADDGEZ,
+  TILEGX_OPC_FETCHADDGEZ4,
+  TILEGX_OPC_FETCHAND,
+  TILEGX_OPC_FETCHAND4,
+  TILEGX_OPC_FETCHOR,
+  TILEGX_OPC_FETCHOR4,
+  TILEGX_OPC_FINV,
+  TILEGX_OPC_FLUSH,
+  TILEGX_OPC_FLUSHWB,
+  TILEGX_OPC_FNOP,
+  TILEGX_OPC_FSINGLE_ADD1,
+  TILEGX_OPC_FSINGLE_ADDSUB2,
+  TILEGX_OPC_FSINGLE_MUL1,
+  TILEGX_OPC_FSINGLE_MUL2,
+  TILEGX_OPC_FSINGLE_PACK1,
+  TILEGX_OPC_FSINGLE_PACK2,
+  TILEGX_OPC_FSINGLE_SUB1,
+  TILEGX_OPC_ICOH,
+  TILEGX_OPC_ILL,
+  TILEGX_OPC_INV,
+  TILEGX_OPC_IRET,
+  TILEGX_OPC_J,
+  TILEGX_OPC_JAL,
+  TILEGX_OPC_JALR,
+  TILEGX_OPC_JALRP,
+  TILEGX_OPC_JR,
+  TILEGX_OPC_JRP,
+  TILEGX_OPC_LD,
+  TILEGX_OPC_LD1S,
+  TILEGX_OPC_LD1S_ADD,
+  TILEGX_OPC_LD1U,
+  TILEGX_OPC_LD1U_ADD,
+  TILEGX_OPC_LD2S,
+  TILEGX_OPC_LD2S_ADD,
+  TILEGX_OPC_LD2U,
+  TILEGX_OPC_LD2U_ADD,
+  TILEGX_OPC_LD4S,
+  TILEGX_OPC_LD4S_ADD,
+  TILEGX_OPC_LD4U,
+  TILEGX_OPC_LD4U_ADD,
+  TILEGX_OPC_LD_ADD,
+  TILEGX_OPC_LDNA,
+  TILEGX_OPC_LDNA_ADD,
+  TILEGX_OPC_LDNT,
+  TILEGX_OPC_LDNT1S,
+  TILEGX_OPC_LDNT1S_ADD,
+  TILEGX_OPC_LDNT1U,
+  TILEGX_OPC_LDNT1U_ADD,
+  TILEGX_OPC_LDNT2S,
+  TILEGX_OPC_LDNT2S_ADD,
+  TILEGX_OPC_LDNT2U,
+  TILEGX_OPC_LDNT2U_ADD,
+  TILEGX_OPC_LDNT4S,
+  TILEGX_OPC_LDNT4S_ADD,
+  TILEGX_OPC_LDNT4U,
+  TILEGX_OPC_LDNT4U_ADD,
+  TILEGX_OPC_LDNT_ADD,
+  TILEGX_OPC_LNK,
+  TILEGX_OPC_MF,
+  TILEGX_OPC_MFSPR,
+  TILEGX_OPC_MM,
+  TILEGX_OPC_MNZ,
+  TILEGX_OPC_MTSPR,
+  TILEGX_OPC_MUL_HS_HS,
+  TILEGX_OPC_MUL_HS_HU,
+  TILEGX_OPC_MUL_HS_LS,
+  TILEGX_OPC_MUL_HS_LU,
+  TILEGX_OPC_MUL_HU_HU,
+  TILEGX_OPC_MUL_HU_LS,
+  TILEGX_OPC_MUL_HU_LU,
+  TILEGX_OPC_MUL_LS_LS,
+  TILEGX_OPC_MUL_LS_LU,
+  TILEGX_OPC_MUL_LU_LU,
+  TILEGX_OPC_MULA_HS_HS,
+  TILEGX_OPC_MULA_HS_HU,
+  TILEGX_OPC_MULA_HS_LS,
+  TILEGX_OPC_MULA_HS_LU,
+  TILEGX_OPC_MULA_HU_HU,
+  TILEGX_OPC_MULA_HU_LS,
+  TILEGX_OPC_MULA_HU_LU,
+  TILEGX_OPC_MULA_LS_LS,
+  TILEGX_OPC_MULA_LS_LU,
+  TILEGX_OPC_MULA_LU_LU,
+  TILEGX_OPC_MULAX,
+  TILEGX_OPC_MULX,
+  TILEGX_OPC_MZ,
+  TILEGX_OPC_NAP,
+  TILEGX_OPC_NOP,
+  TILEGX_OPC_NOR,
+  TILEGX_OPC_OR,
+  TILEGX_OPC_ORI,
+  TILEGX_OPC_PCNT,
+  TILEGX_OPC_REVBITS,
+  TILEGX_OPC_REVBYTES,
+  TILEGX_OPC_ROTL,
+  TILEGX_OPC_ROTLI,
+  TILEGX_OPC_SHL,
+  TILEGX_OPC_SHL16INSLI,
+  TILEGX_OPC_SHL1ADD,
+  TILEGX_OPC_SHL1ADDX,
+  TILEGX_OPC_SHL2ADD,
+  TILEGX_OPC_SHL2ADDX,
+  TILEGX_OPC_SHL3ADD,
+  TILEGX_OPC_SHL3ADDX,
+  TILEGX_OPC_SHLI,
+  TILEGX_OPC_SHLX,
+  TILEGX_OPC_SHLXI,
+  TILEGX_OPC_SHRS,
+  TILEGX_OPC_SHRSI,
+  TILEGX_OPC_SHRU,
+  TILEGX_OPC_SHRUI,
+  TILEGX_OPC_SHRUX,
+  TILEGX_OPC_SHRUXI,
+  TILEGX_OPC_SHUFFLEBYTES,
+  TILEGX_OPC_ST,
+  TILEGX_OPC_ST1,
+  TILEGX_OPC_ST1_ADD,
+  TILEGX_OPC_ST2,
+  TILEGX_OPC_ST2_ADD,
+  TILEGX_OPC_ST4,
+  TILEGX_OPC_ST4_ADD,
+  TILEGX_OPC_ST_ADD,
+  TILEGX_OPC_STNT,
+  TILEGX_OPC_STNT1,
+  TILEGX_OPC_STNT1_ADD,
+  TILEGX_OPC_STNT2,
+  TILEGX_OPC_STNT2_ADD,
+  TILEGX_OPC_STNT4,
+  TILEGX_OPC_STNT4_ADD,
+  TILEGX_OPC_STNT_ADD,
+  TILEGX_OPC_SUB,
+  TILEGX_OPC_SUBX,
+  TILEGX_OPC_SUBXSC,
+  TILEGX_OPC_SWINT0,
+  TILEGX_OPC_SWINT1,
+  TILEGX_OPC_SWINT2,
+  TILEGX_OPC_SWINT3,
+  TILEGX_OPC_TBLIDXB0,
+  TILEGX_OPC_TBLIDXB1,
+  TILEGX_OPC_TBLIDXB2,
+  TILEGX_OPC_TBLIDXB3,
+  TILEGX_OPC_V1ADD,
+  TILEGX_OPC_V1ADDI,
+  TILEGX_OPC_V1ADDUC,
+  TILEGX_OPC_V1ADIFFU,
+  TILEGX_OPC_V1AVGU,
+  TILEGX_OPC_V1CMPEQ,
+  TILEGX_OPC_V1CMPEQI,
+  TILEGX_OPC_V1CMPLES,
+  TILEGX_OPC_V1CMPLEU,
+  TILEGX_OPC_V1CMPLTS,
+  TILEGX_OPC_V1CMPLTSI,
+  TILEGX_OPC_V1CMPLTU,
+  TILEGX_OPC_V1CMPLTUI,
+  TILEGX_OPC_V1CMPNE,
+  TILEGX_OPC_V1DDOTPU,
+  TILEGX_OPC_V1DDOTPUA,
+  TILEGX_OPC_V1DDOTPUS,
+  TILEGX_OPC_V1DDOTPUSA,
+  TILEGX_OPC_V1DOTP,
+  TILEGX_OPC_V1DOTPA,
+  TILEGX_OPC_V1DOTPU,
+  TILEGX_OPC_V1DOTPUA,
+  TILEGX_OPC_V1DOTPUS,
+  TILEGX_OPC_V1DOTPUSA,
+  TILEGX_OPC_V1INT_H,
+  TILEGX_OPC_V1INT_L,
+  TILEGX_OPC_V1MAXU,
+  TILEGX_OPC_V1MAXUI,
+  TILEGX_OPC_V1MINU,
+  TILEGX_OPC_V1MINUI,
+  TILEGX_OPC_V1MNZ,
+  TILEGX_OPC_V1MULTU,
+  TILEGX_OPC_V1MULU,
+  TILEGX_OPC_V1MULUS,
+  TILEGX_OPC_V1MZ,
+  TILEGX_OPC_V1SADAU,
+  TILEGX_OPC_V1SADU,
+  TILEGX_OPC_V1SHL,
+  TILEGX_OPC_V1SHLI,
+  TILEGX_OPC_V1SHRS,
+  TILEGX_OPC_V1SHRSI,
+  TILEGX_OPC_V1SHRU,
+  TILEGX_OPC_V1SHRUI,
+  TILEGX_OPC_V1SUB,
+  TILEGX_OPC_V1SUBUC,
+  TILEGX_OPC_V2ADD,
+  TILEGX_OPC_V2ADDI,
+  TILEGX_OPC_V2ADDSC,
+  TILEGX_OPC_V2ADIFFS,
+  TILEGX_OPC_V2AVGS,
+  TILEGX_OPC_V2CMPEQ,
+  TILEGX_OPC_V2CMPEQI,
+  TILEGX_OPC_V2CMPLES,
+  TILEGX_OPC_V2CMPLEU,
+  TILEGX_OPC_V2CMPLTS,
+  TILEGX_OPC_V2CMPLTSI,
+  TILEGX_OPC_V2CMPLTU,
+  TILEGX_OPC_V2CMPLTUI,
+  TILEGX_OPC_V2CMPNE,
+  TILEGX_OPC_V2DOTP,
+  TILEGX_OPC_V2DOTPA,
+  TILEGX_OPC_V2INT_H,
+  TILEGX_OPC_V2INT_L,
+  TILEGX_OPC_V2MAXS,
+  TILEGX_OPC_V2MAXSI,
+  TILEGX_OPC_V2MINS,
+  TILEGX_OPC_V2MINSI,
+  TILEGX_OPC_V2MNZ,
+  TILEGX_OPC_V2MULFSC,
+  TILEGX_OPC_V2MULS,
+  TILEGX_OPC_V2MULTS,
+  TILEGX_OPC_V2MZ,
+  TILEGX_OPC_V2PACKH,
+  TILEGX_OPC_V2PACKL,
+  TILEGX_OPC_V2PACKUC,
+  TILEGX_OPC_V2SADAS,
+  TILEGX_OPC_V2SADAU,
+  TILEGX_OPC_V2SADS,
+  TILEGX_OPC_V2SADU,
+  TILEGX_OPC_V2SHL,
+  TILEGX_OPC_V2SHLI,
+  TILEGX_OPC_V2SHLSC,
+  TILEGX_OPC_V2SHRS,
+  TILEGX_OPC_V2SHRSI,
+  TILEGX_OPC_V2SHRU,
+  TILEGX_OPC_V2SHRUI,
+  TILEGX_OPC_V2SUB,
+  TILEGX_OPC_V2SUBSC,
+  TILEGX_OPC_V4ADD,
+  TILEGX_OPC_V4ADDSC,
+  TILEGX_OPC_V4INT_H,
+  TILEGX_OPC_V4INT_L,
+  TILEGX_OPC_V4PACKSC,
+  TILEGX_OPC_V4SHL,
+  TILEGX_OPC_V4SHLSC,
+  TILEGX_OPC_V4SHRS,
+  TILEGX_OPC_V4SHRU,
+  TILEGX_OPC_V4SUB,
+  TILEGX_OPC_V4SUBSC,
+  TILEGX_OPC_WH64,
+  TILEGX_OPC_XOR,
+  TILEGX_OPC_XORI,
+  TILEGX_OPC_NONE
+} tilegx_mnemonic;
+
+
+
+typedef enum
+{
+  TILEGX_PIPELINE_X0,
+  TILEGX_PIPELINE_X1,
+  TILEGX_PIPELINE_Y0,
+  TILEGX_PIPELINE_Y1,
+  TILEGX_PIPELINE_Y2,
+} tilegx_pipeline;
+
+#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
+
+typedef enum
+{
+  TILEGX_OP_TYPE_REGISTER,
+  TILEGX_OP_TYPE_IMMEDIATE,
+  TILEGX_OP_TYPE_ADDRESS,
+  TILEGX_OP_TYPE_SPR
+} tilegx_operand_type;
+
+struct tilegx_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilegx_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilegx_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilegx_bundle_bits bundle);
+};
+
+
+extern const struct tilegx_operand tilegx_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilegx_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilegx_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilegx_operands[] table. */
+  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
+
+};
+
+extern const struct tilegx_opcode tilegx_opcodes[];
+
+/* Used for non-textual disassembly into structs. */
+struct tilegx_decoded_instruction
+{
+  const struct tilegx_opcode *opcode;
+  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
+  long long operand_values[TILEGX_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilegx(tilegx_bundle_bits bits,
+                             unsigned long long pc,
+                             struct tilegx_decoded_instruction
+                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+
+#endif /* opcode_tilegx_h */
diff -druNp linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc.h linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc.h
--- linux-libre-3.1-gnu1/arch/tile/include/asm/tile-desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/tile/include/asm/tile-desc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef __tilegx__
+#include <asm/tile-desc_32.h>
+#else
+#include <asm/tile-desc_64.h>
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/tile/Kconfig linux-libre-3.2-gnu1/arch/tile/Kconfig
--- linux-libre-3.1-gnu1/arch/tile/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -46,9 +46,6 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
 
-config GENERIC_TIME
-	def_bool y
-
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/backtrace.c linux-libre-3.2-gnu1/arch/tile/kernel/backtrace.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/backtrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/backtrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -15,13 +15,11 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <asm/backtrace.h>
-#include <asm/opcode-tile.h>
+#include <asm/tile-desc.h>
 #include <arch/abi.h>
 
 #ifdef __tilegx__
-#define tile_bundle_bits tilegx_bundle_bits
 #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE
-#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
 #define tile_decoded_instruction tilegx_decoded_instruction
 #define tile_mnemonic tilegx_mnemonic
 #define parse_insn_tile parse_insn_tilegx
@@ -35,7 +33,18 @@
 #define OPCODE_STORE TILEGX_OPC_ST
 typedef long long bt_int_reg_t;
 #else
-#define OPCODE_STORE TILE_OPC_SW
+#define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE
+#define tile_decoded_instruction tilepro_decoded_instruction
+#define tile_mnemonic tilepro_mnemonic
+#define parse_insn_tile parse_insn_tilepro
+#define TILE_OPC_IRET TILEPRO_OPC_IRET
+#define TILE_OPC_ADDI TILEPRO_OPC_ADDI
+#define TILE_OPC_ADDLI TILEPRO_OPC_ADDLI
+#define TILE_OPC_INFO TILEPRO_OPC_INFO
+#define TILE_OPC_INFOL TILEPRO_OPC_INFOL
+#define TILE_OPC_JRP TILEPRO_OPC_JRP
+#define TILE_OPC_MOVE TILEPRO_OPC_MOVE
+#define OPCODE_STORE TILEPRO_OPC_SW
 typedef int bt_int_reg_t;
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/irq.c linux-libre-3.2-gnu1/arch/tile/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,14 +152,13 @@ void tile_dev_intr(struct pt_regs *regs,
  * Remove an irq from the disabled mask.  If we're in an interrupt
  * context, defer enabling the HW interrupt until we leave.
  */
-void enable_percpu_irq(unsigned int irq)
+static void tile_irq_chip_enable(struct irq_data *d)
 {
-	get_cpu_var(irq_disable_mask) &= ~(1UL << irq);
+	get_cpu_var(irq_disable_mask) &= ~(1UL << d->irq);
 	if (__get_cpu_var(irq_depth) == 0)
-		unmask_irqs(1UL << irq);
+		unmask_irqs(1UL << d->irq);
 	put_cpu_var(irq_disable_mask);
 }
-EXPORT_SYMBOL(enable_percpu_irq);
 
 /*
  * Add an irq to the disabled mask.  We disable the HW interrupt
@@ -167,13 +166,12 @@ EXPORT_SYMBOL(enable_percpu_irq);
  * in an interrupt context, the return path is careful to avoid
  * unmasking a newly disabled interrupt.
  */
-void disable_percpu_irq(unsigned int irq)
+static void tile_irq_chip_disable(struct irq_data *d)
 {
-	get_cpu_var(irq_disable_mask) |= (1UL << irq);
-	mask_irqs(1UL << irq);
+	get_cpu_var(irq_disable_mask) |= (1UL << d->irq);
+	mask_irqs(1UL << d->irq);
 	put_cpu_var(irq_disable_mask);
 }
-EXPORT_SYMBOL(disable_percpu_irq);
 
 /* Mask an interrupt. */
 static void tile_irq_chip_mask(struct irq_data *d)
@@ -209,6 +207,8 @@ static void tile_irq_chip_eoi(struct irq
 
 static struct irq_chip tile_irq_chip = {
 	.name = "tile_irq_chip",
+	.irq_enable = tile_irq_chip_enable,
+	.irq_disable = tile_irq_chip_disable,
 	.irq_ack = tile_irq_chip_ack,
 	.irq_eoi = tile_irq_chip_eoi,
 	.irq_mask = tile_irq_chip_mask,
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/module.c linux-libre-3.2-gnu1/arch/tile/kernel/module.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,9 +20,9 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <asm/opcode-tile.h>
 #include <asm/pgtable.h>
 #include <asm/homecache.h>
+#include <arch/opcode.h>
 
 #ifdef __tilegx__
 # define Elf_Rela Elf64_Rela
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/pci.c linux-libre-3.2-gnu1/arch/tile/kernel/pci.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/pci-dma.c linux-libre-3.2-gnu1/arch/tile/kernel/pci-dma.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <asm/tlbflush.h>
 #include <asm/homecache.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/single_step.c linux-libre-3.2-gnu1/arch/tile/kernel/single_step.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/single_step.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/single_step.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,8 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <asm/cacheflush.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <arch/abi.h>
+#include <arch/opcode.h>
 
 #define signExtend17(val) sign_extend((val), 17)
 #define TILE_X1_MASK (0xffffffffULL << 31)
@@ -118,7 +117,7 @@ static tile_bundle_bits rewrite_load_sto
 	int val_reg, addr_reg, err, val;
 
 	/* Get address and value registers */
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
 		addr_reg = get_SrcA_Y2(bundle);
 		val_reg = get_SrcBDest_Y2(bundle);
 	} else if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {
@@ -229,7 +228,7 @@ P("\n");
 	}
 	++unaligned_fixup_count;
 
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
 		/* Convert the Y2 instruction to a prefetch. */
 		bundle &= ~(create_SrcBDest_Y2(-1) |
 			    create_Opcode_Y2(-1));
@@ -389,7 +388,7 @@ void single_step_once(struct pt_regs *re
 	state->branch_next_pc = 0;
 	state->update = 0;
 
-	if (!(bundle & TILE_BUNDLE_Y_ENCODING_MASK)) {
+	if (!(bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)) {
 		/* two wide, check for control flow */
 		int opcode = get_Opcode_X1(bundle);
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/sysfs.c linux-libre-3.2-gnu1/arch/tile/kernel/sysfs.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
+#include <linux/stat.h>
 #include <hv/hypervisor.h>
 
 /* Return a string queried from the hypervisor, truncated to page size. */
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/tile-desc_32.c linux-libre-3.2-gnu1/arch/tile/kernel/tile-desc_32.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/tile-desc_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/tile-desc_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,23 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
@@ -6,1217 +26,1217 @@
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
-const struct tile_opcode tile_opcodes[395] =
+const struct tilepro_opcode tilepro_opcodes[395] =
 {
- { "bpt", TILE_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
+ { "bpt", TILEPRO_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "info", TILE_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
+  { "info", TILEPRO_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
     { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } },
   },
-  { "infol", TILE_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
+  { "infol", TILEPRO_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
     { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "j", TILE_OPC_J, 0x2, 1, TREG_ZERO, 1,
+  { "j", TILEPRO_OPC_J, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jal", TILE_OPC_JAL, 0x2, 1, TREG_LR, 1,
+  { "jal", TILEPRO_OPC_JAL, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "move", TILE_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
+  { "move", TILEPRO_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 9, 10 }, { 11, 12 }, { 13, 14 }, { 0, } },
   },
-  { "move.sn", TILE_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
+  { "move.sn", TILEPRO_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 8 }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movei", TILE_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
+  { "movei", TILEPRO_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
     { { 7, 0 }, { 9, 1 }, { 11, 2 }, { 13, 3 }, { 0, } },
   },
-  { "movei.sn", TILE_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
+  { "movei.sn", TILEPRO_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 0 }, { 9, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli", TILE_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
+  { "moveli", TILEPRO_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli.sn", TILE_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
+  { "moveli.sn", TILEPRO_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movelis", TILE_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
+  { "movelis", TILEPRO_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "prefetch", TILE_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
+  { "prefetch", TILEPRO_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 15 } },
   },
-  { "raise", TILE_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
+  { "raise", TILEPRO_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "add", TILE_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
+  { "add", TILEPRO_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "add.sn", TILE_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
+  { "add.sn", TILEPRO_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb", TILE_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
+  { "addb", TILEPRO_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb.sn", TILE_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
+  { "addb.sn", TILEPRO_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u", TILE_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "addbs_u", TILEPRO_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u.sn", TILE_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "addbs_u.sn", TILEPRO_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh", TILE_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
+  { "addh", TILEPRO_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh.sn", TILE_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
+  { "addh.sn", TILEPRO_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs", TILE_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
+  { "addhs", TILEPRO_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs.sn", TILE_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
+  { "addhs.sn", TILEPRO_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addi", TILE_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
+  { "addi", TILEPRO_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "addi.sn", TILE_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
+  { "addi.sn", TILEPRO_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib", TILE_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
+  { "addib", TILEPRO_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib.sn", TILE_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
+  { "addib.sn", TILEPRO_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih", TILE_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
+  { "addih", TILEPRO_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih.sn", TILE_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
+  { "addih.sn", TILEPRO_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli", TILE_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
+  { "addli", TILEPRO_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli.sn", TILE_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
+  { "addli.sn", TILEPRO_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addlis", TILE_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
+  { "addlis", TILEPRO_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds", TILE_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
+  { "adds", TILEPRO_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds.sn", TILE_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
+  { "adds.sn", TILEPRO_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u", TILE_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
+  { "adiffb_u", TILEPRO_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u.sn", TILE_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffb_u.sn", TILEPRO_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh", TILE_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
+  { "adiffh", TILEPRO_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh.sn", TILE_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffh.sn", TILEPRO_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "and", TILE_OPC_AND, 0xf, 3, TREG_ZERO, 1,
+  { "and", TILEPRO_OPC_AND, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "and.sn", TILE_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
+  { "and.sn", TILEPRO_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "andi", TILE_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
+  { "andi", TILEPRO_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "andi.sn", TILE_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
+  { "andi.sn", TILEPRO_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "auli", TILE_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
+  { "auli", TILEPRO_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u", TILE_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
+  { "avgb_u", TILEPRO_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u.sn", TILE_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "avgb_u.sn", TILEPRO_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh", TILE_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
+  { "avgh", TILEPRO_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh.sn", TILE_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
+  { "avgh.sn", TILEPRO_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns", TILE_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
+  { "bbns", TILEPRO_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns.sn", TILE_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbns.sn", TILEPRO_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst", TILE_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
+  { "bbnst", TILEPRO_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst.sn", TILE_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbnst.sn", TILEPRO_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs", TILE_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
+  { "bbs", TILEPRO_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs.sn", TILE_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbs.sn", TILEPRO_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst", TILE_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
+  { "bbst", TILEPRO_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst.sn", TILE_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbst.sn", TILEPRO_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez", TILE_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgez", TILEPRO_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez.sn", TILE_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgez.sn", TILEPRO_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt", TILE_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgezt", TILEPRO_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt.sn", TILE_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgezt.sn", TILEPRO_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz", TILE_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgz", TILEPRO_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz.sn", TILE_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgz.sn", TILEPRO_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt", TILE_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgzt", TILEPRO_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt.sn", TILE_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgzt.sn", TILEPRO_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bitx", TILE_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
+  { "bitx", TILEPRO_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bitx.sn", TILE_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
+  { "bitx.sn", TILEPRO_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez", TILE_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
+  { "blez", TILEPRO_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez.sn", TILE_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blez.sn", TILEPRO_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt", TILE_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
+  { "blezt", TILEPRO_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt.sn", TILE_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blezt.sn", TILEPRO_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz", TILE_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
+  { "blz", TILEPRO_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz.sn", TILE_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blz.sn", TILEPRO_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt", TILE_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
+  { "blzt", TILEPRO_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt.sn", TILE_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blzt.sn", TILEPRO_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz", TILE_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
+  { "bnz", TILEPRO_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz.sn", TILE_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bnz.sn", TILEPRO_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt", TILE_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
+  { "bnzt", TILEPRO_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt.sn", TILE_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bnzt.sn", TILEPRO_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bytex", TILE_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
+  { "bytex", TILEPRO_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bytex.sn", TILE_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
+  { "bytex.sn", TILEPRO_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz", TILE_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
+  { "bz", TILEPRO_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz.sn", TILE_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bz.sn", TILEPRO_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt", TILE_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
+  { "bzt", TILEPRO_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt.sn", TILE_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bzt.sn", TILEPRO_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "clz", TILE_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
+  { "clz", TILEPRO_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "clz.sn", TILE_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
+  { "clz.sn", TILEPRO_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32", TILE_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_32", TILEPRO_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32.sn", TILE_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_32.sn", TILEPRO_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8", TILE_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_8", TILEPRO_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8.sn", TILE_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_8.sn", TILEPRO_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "ctz", TILE_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
+  { "ctz", TILEPRO_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "ctz.sn", TILE_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
+  { "ctz.sn", TILEPRO_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "drain", TILE_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
+  { "drain", TILEPRO_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "dtlbpr", TILE_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
+  { "dtlbpr", TILEPRO_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align", TILE_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
+  { "dword_align", TILEPRO_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align.sn", TILE_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
+  { "dword_align.sn", TILEPRO_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "finv", TILE_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
+  { "finv", TILEPRO_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "flush", TILE_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
+  { "flush", TILEPRO_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "fnop", TILE_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
+  { "fnop", TILEPRO_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "icoh", TILE_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
+  { "icoh", TILEPRO_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ill", TILE_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
+  { "ill", TILEPRO_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, {  }, { 0, } },
   },
-  { "inthb", TILE_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
+  { "inthb", TILEPRO_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthb.sn", TILE_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
+  { "inthb.sn", TILEPRO_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh", TILE_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
+  { "inthh", TILEPRO_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh.sn", TILE_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
+  { "inthh.sn", TILEPRO_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb", TILE_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
+  { "intlb", TILEPRO_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb.sn", TILE_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
+  { "intlb.sn", TILEPRO_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh", TILE_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
+  { "intlh", TILEPRO_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh.sn", TILE_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
+  { "intlh.sn", TILEPRO_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inv", TILE_OPC_INV, 0x2, 1, TREG_ZERO, 1,
+  { "inv", TILEPRO_OPC_INV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "iret", TILE_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
+  { "iret", TILEPRO_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalb", TILE_OPC_JALB, 0x2, 1, TREG_LR, 1,
+  { "jalb", TILEPRO_OPC_JALB, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalf", TILE_OPC_JALF, 0x2, 1, TREG_LR, 1,
+  { "jalf", TILEPRO_OPC_JALF, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalr", TILE_OPC_JALR, 0x2, 1, TREG_LR, 1,
+  { "jalr", TILEPRO_OPC_JALR, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalrp", TILE_OPC_JALRP, 0x2, 1, TREG_LR, 1,
+  { "jalrp", TILEPRO_OPC_JALRP, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jb", TILE_OPC_JB, 0x2, 1, TREG_ZERO, 1,
+  { "jb", TILEPRO_OPC_JB, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jf", TILE_OPC_JF, 0x2, 1, TREG_ZERO, 1,
+  { "jf", TILEPRO_OPC_JF, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jr", TILE_OPC_JR, 0x2, 1, TREG_ZERO, 1,
+  { "jr", TILEPRO_OPC_JR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jrp", TILE_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
+  { "jrp", TILEPRO_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb", TILE_OPC_LB, 0x12, 2, TREG_ZERO, 1,
+  { "lb", TILEPRO_OPC_LB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb.sn", TILE_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
+  { "lb.sn", TILEPRO_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb_u", TILE_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
+  { "lb_u", TILEPRO_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb_u.sn", TILE_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lb_u.sn", TILEPRO_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd", TILE_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd", TILEPRO_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd.sn", TILE_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd.sn", TILEPRO_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u", TILE_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd_u", TILEPRO_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u.sn", TILE_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd_u.sn", TILEPRO_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh", TILE_OPC_LH, 0x12, 2, TREG_ZERO, 1,
+  { "lh", TILEPRO_OPC_LH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh.sn", TILE_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
+  { "lh.sn", TILEPRO_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh_u", TILE_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
+  { "lh_u", TILEPRO_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh_u.sn", TILE_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lh_u.sn", TILEPRO_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd", TILE_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd", TILEPRO_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd.sn", TILE_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd.sn", TILEPRO_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u", TILE_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd_u", TILEPRO_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u.sn", TILE_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd_u.sn", TILEPRO_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk", TILE_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
+  { "lnk", TILEPRO_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk.sn", TILE_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
+  { "lnk.sn", TILEPRO_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw", TILE_OPC_LW, 0x12, 2, TREG_ZERO, 1,
+  { "lw", TILEPRO_OPC_LW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lw.sn", TILE_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
+  { "lw.sn", TILEPRO_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na", TILE_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
+  { "lw_na", TILEPRO_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na.sn", TILE_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
+  { "lw_na.sn", TILEPRO_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd", TILE_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd", TILEPRO_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd.sn", TILE_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd.sn", TILEPRO_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na", TILE_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd_na", TILEPRO_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na.sn", TILE_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd_na.sn", TILEPRO_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u", TILE_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxb_u", TILEPRO_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u.sn", TILE_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxb_u.sn", TILEPRO_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh", TILE_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
+  { "maxh", TILEPRO_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh.sn", TILE_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxh.sn", TILEPRO_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u", TILE_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxib_u", TILEPRO_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u.sn", TILE_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxib_u.sn", TILEPRO_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih", TILE_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
+  { "maxih", TILEPRO_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih.sn", TILE_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxih.sn", TILEPRO_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mf", TILE_OPC_MF, 0x2, 0, TREG_ZERO, 1,
+  { "mf", TILEPRO_OPC_MF, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "mfspr", TILE_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mfspr", TILEPRO_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 25 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u", TILE_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minb_u", TILEPRO_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u.sn", TILE_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minb_u.sn", TILEPRO_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh", TILE_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
+  { "minh", TILEPRO_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh.sn", TILE_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
+  { "minh.sn", TILEPRO_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u", TILE_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minib_u", TILEPRO_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u.sn", TILE_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minib_u.sn", TILEPRO_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih", TILE_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
+  { "minih", TILEPRO_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih.sn", TILE_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
+  { "minih.sn", TILEPRO_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mm", TILE_OPC_MM, 0x3, 5, TREG_ZERO, 1,
+  { "mm", TILEPRO_OPC_MM, 0x3, 5, TREG_ZERO, 1,
     { { 7, 8, 16, 26, 27 }, { 9, 10, 17, 28, 29 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnz", TILE_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
+  { "mnz", TILEPRO_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mnz.sn", TILE_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mnz.sn", TILEPRO_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb", TILE_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
+  { "mnzb", TILEPRO_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb.sn", TILE_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzb.sn", TILEPRO_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh", TILE_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
+  { "mnzh", TILEPRO_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh.sn", TILE_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzh.sn", TILEPRO_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mtspr", TILE_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mtspr", TILEPRO_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 30, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_ss", TILE_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_ss", TILEPRO_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_ss.sn", TILE_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_ss.sn", TILEPRO_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su", TILE_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhh_su", TILEPRO_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su.sn", TILE_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_su.sn", TILEPRO_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_uu", TILE_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_uu", TILEPRO_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_uu.sn", TILE_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_uu.sn", TILEPRO_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_ss", TILE_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_ss", TILEPRO_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_ss.sn", TILE_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_ss.sn", TILEPRO_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su", TILE_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhha_su", TILEPRO_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su.sn", TILE_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_su.sn", TILEPRO_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_uu", TILE_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_uu", TILEPRO_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_uu.sn", TILE_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_uu.sn", TILEPRO_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu", TILE_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhhsa_uu", TILEPRO_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu.sn", TILE_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhhsa_uu.sn", TILEPRO_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss", TILE_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_ss", TILEPRO_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss.sn", TILE_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_ss.sn", TILEPRO_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su", TILE_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_su", TILEPRO_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su.sn", TILE_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_su.sn", TILEPRO_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us", TILE_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_us", TILEPRO_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us.sn", TILE_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_us.sn", TILEPRO_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu", TILE_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_uu", TILEPRO_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu.sn", TILE_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_uu.sn", TILEPRO_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss", TILE_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_ss", TILEPRO_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss.sn", TILE_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_ss.sn", TILEPRO_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su", TILE_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_su", TILEPRO_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su.sn", TILE_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_su.sn", TILEPRO_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us", TILE_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_us", TILEPRO_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us.sn", TILE_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_us.sn", TILEPRO_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu", TILE_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_uu", TILEPRO_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu.sn", TILE_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_uu.sn", TILEPRO_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu", TILE_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhlsa_uu", TILEPRO_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu.sn", TILE_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhlsa_uu.sn", TILEPRO_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_ss", TILE_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_ss", TILEPRO_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_ss.sn", TILE_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_ss.sn", TILEPRO_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su", TILE_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulll_su", TILEPRO_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su.sn", TILE_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_su.sn", TILEPRO_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_uu", TILE_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_uu", TILEPRO_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_uu.sn", TILE_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_uu.sn", TILEPRO_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_ss", TILE_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_ss", TILEPRO_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_ss.sn", TILE_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_ss.sn", TILEPRO_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su", TILE_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mullla_su", TILEPRO_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su.sn", TILE_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_su.sn", TILEPRO_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_uu", TILE_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_uu", TILEPRO_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_uu.sn", TILE_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_uu.sn", TILEPRO_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu", TILE_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulllsa_uu", TILEPRO_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu.sn", TILE_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulllsa_uu.sn", TILEPRO_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvnz", TILE_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvnz", TILEPRO_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvnz.sn", TILE_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvnz.sn", TILEPRO_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvz", TILE_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvz", TILEPRO_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvz.sn", TILE_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvz.sn", TILEPRO_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mz", TILE_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
+  { "mz", TILEPRO_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mz.sn", TILE_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mz.sn", TILEPRO_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb", TILE_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
+  { "mzb", TILEPRO_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb.sn", TILE_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mzb.sn", TILEPRO_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh", TILE_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
+  { "mzh", TILEPRO_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh.sn", TILE_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mzh.sn", TILEPRO_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "nap", TILE_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
+  { "nap", TILEPRO_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "nop", TILE_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
+  { "nop", TILEPRO_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "nor", TILE_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
+  { "nor", TILEPRO_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "nor.sn", TILE_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
+  { "nor.sn", TILEPRO_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "or", TILE_OPC_OR, 0xf, 3, TREG_ZERO, 1,
+  { "or", TILEPRO_OPC_OR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "or.sn", TILE_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
+  { "or.sn", TILEPRO_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ori", TILE_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
+  { "ori", TILEPRO_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "ori.sn", TILE_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
+  { "ori.sn", TILEPRO_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u", TILE_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "packbs_u", TILEPRO_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u.sn", TILE_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "packbs_u.sn", TILEPRO_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb", TILE_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
+  { "packhb", TILEPRO_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb.sn", TILE_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
+  { "packhb.sn", TILEPRO_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs", TILE_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
+  { "packhs", TILEPRO_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs.sn", TILE_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
+  { "packhs.sn", TILEPRO_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb", TILE_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
+  { "packlb", TILEPRO_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb.sn", TILE_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
+  { "packlb.sn", TILEPRO_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "pcnt", TILE_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
+  { "pcnt", TILEPRO_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "pcnt.sn", TILE_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
+  { "pcnt.sn", TILEPRO_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "rl", TILE_OPC_RL, 0xf, 3, TREG_ZERO, 1,
+  { "rl", TILEPRO_OPC_RL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "rl.sn", TILE_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
+  { "rl.sn", TILEPRO_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "rli", TILE_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
+  { "rli", TILEPRO_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "rli.sn", TILE_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
+  { "rli.sn", TILEPRO_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s1a", TILE_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
+  { "s1a", TILEPRO_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s1a.sn", TILE_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
+  { "s1a.sn", TILEPRO_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s2a", TILE_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
+  { "s2a", TILEPRO_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s2a.sn", TILE_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
+  { "s2a.sn", TILEPRO_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s3a", TILE_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
+  { "s3a", TILEPRO_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s3a.sn", TILE_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
+  { "s3a.sn", TILEPRO_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u", TILE_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadab_u", TILEPRO_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u.sn", TILE_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadab_u.sn", TILEPRO_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah", TILE_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
+  { "sadah", TILEPRO_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah.sn", TILE_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah.sn", TILEPRO_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u", TILE_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadah_u", TILEPRO_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u.sn", TILE_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah_u.sn", TILEPRO_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u", TILE_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadb_u", TILEPRO_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u.sn", TILE_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadb_u.sn", TILEPRO_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh", TILE_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
+  { "sadh", TILEPRO_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh.sn", TILE_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh.sn", TILEPRO_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u", TILE_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadh_u", TILEPRO_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u.sn", TILE_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh_u.sn", TILEPRO_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sb", TILE_OPC_SB, 0x12, 2, TREG_ZERO, 1,
+  { "sb", TILEPRO_OPC_SB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "sbadd", TILE_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
+  { "sbadd", TILEPRO_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seq", TILE_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
+  { "seq", TILEPRO_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "seq.sn", TILE_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
+  { "seq.sn", TILEPRO_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb", TILE_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
+  { "seqb", TILEPRO_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb.sn", TILE_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqb.sn", TILEPRO_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh", TILE_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
+  { "seqh", TILEPRO_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh.sn", TILE_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqh.sn", TILEPRO_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqi", TILE_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
+  { "seqi", TILEPRO_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "seqi.sn", TILE_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
+  { "seqi.sn", TILEPRO_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib", TILE_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
+  { "seqib", TILEPRO_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib.sn", TILE_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqib.sn", TILEPRO_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih", TILE_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
+  { "seqih", TILEPRO_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih.sn", TILE_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqih.sn", TILEPRO_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sh", TILE_OPC_SH, 0x12, 2, TREG_ZERO, 1,
+  { "sh", TILEPRO_OPC_SH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "shadd", TILE_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
+  { "shadd", TILEPRO_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shl", TILE_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
+  { "shl", TILEPRO_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shl.sn", TILE_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
+  { "shl.sn", TILEPRO_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb", TILE_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
+  { "shlb", TILEPRO_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb.sn", TILE_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlb.sn", TILEPRO_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh", TILE_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
+  { "shlh", TILEPRO_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh.sn", TILE_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlh.sn", TILEPRO_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shli", TILE_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
+  { "shli", TILEPRO_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shli.sn", TILE_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
+  { "shli.sn", TILEPRO_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib", TILE_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
+  { "shlib", TILEPRO_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib.sn", TILE_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlib.sn", TILEPRO_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih", TILE_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
+  { "shlih", TILEPRO_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih.sn", TILE_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlih.sn", TILEPRO_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shr", TILE_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
+  { "shr", TILEPRO_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shr.sn", TILE_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
+  { "shr.sn", TILEPRO_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb", TILE_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
+  { "shrb", TILEPRO_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb.sn", TILE_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrb.sn", TILEPRO_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh", TILE_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
+  { "shrh", TILEPRO_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh.sn", TILE_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrh.sn", TILEPRO_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shri", TILE_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
+  { "shri", TILEPRO_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shri.sn", TILE_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
+  { "shri.sn", TILEPRO_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib", TILE_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
+  { "shrib", TILEPRO_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib.sn", TILE_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrib.sn", TILEPRO_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih", TILE_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
+  { "shrih", TILEPRO_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih.sn", TILE_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrih.sn", TILEPRO_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt", TILE_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
+  { "slt", TILEPRO_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt.sn", TILE_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
+  { "slt.sn", TILEPRO_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt_u", TILE_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
+  { "slt_u", TILEPRO_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt_u.sn", TILE_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slt_u.sn", TILEPRO_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb", TILE_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
+  { "sltb", TILEPRO_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb.sn", TILE_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb.sn", TILEPRO_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u", TILE_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltb_u", TILEPRO_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u.sn", TILE_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb_u.sn", TILEPRO_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte", TILE_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
+  { "slte", TILEPRO_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte.sn", TILE_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
+  { "slte.sn", TILEPRO_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte_u", TILE_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
+  { "slte_u", TILEPRO_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte_u.sn", TILE_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slte_u.sn", TILEPRO_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb", TILE_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
+  { "slteb", TILEPRO_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb.sn", TILE_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb.sn", TILEPRO_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u", TILE_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteb_u", TILEPRO_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u.sn", TILE_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb_u.sn", TILEPRO_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh", TILE_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
+  { "slteh", TILEPRO_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh.sn", TILE_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh.sn", TILEPRO_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u", TILE_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteh_u", TILEPRO_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u.sn", TILE_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh_u.sn", TILEPRO_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth", TILE_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
+  { "slth", TILEPRO_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth.sn", TILE_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
+  { "slth.sn", TILEPRO_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u", TILE_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slth_u", TILEPRO_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u.sn", TILE_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slth_u.sn", TILEPRO_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti", TILE_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
+  { "slti", TILEPRO_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti.sn", TILE_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
+  { "slti.sn", TILEPRO_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti_u", TILE_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
+  { "slti_u", TILEPRO_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti_u.sn", TILE_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slti_u.sn", TILEPRO_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib", TILE_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
+  { "sltib", TILEPRO_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib.sn", TILE_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib.sn", TILEPRO_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u", TILE_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltib_u", TILEPRO_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u.sn", TILE_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib_u.sn", TILEPRO_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih", TILE_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
+  { "sltih", TILEPRO_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih.sn", TILE_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih.sn", TILEPRO_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u", TILE_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltih_u", TILEPRO_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u.sn", TILE_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih_u.sn", TILEPRO_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sne", TILE_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
+  { "sne", TILEPRO_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sne.sn", TILE_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
+  { "sne.sn", TILEPRO_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb", TILE_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
+  { "sneb", TILEPRO_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb.sn", TILE_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
+  { "sneb.sn", TILEPRO_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh", TILE_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
+  { "sneh", TILEPRO_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh.sn", TILE_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
+  { "sneh.sn", TILEPRO_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sra", TILE_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
+  { "sra", TILEPRO_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sra.sn", TILE_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
+  { "sra.sn", TILEPRO_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab", TILE_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
+  { "srab", TILEPRO_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab.sn", TILE_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
+  { "srab.sn", TILEPRO_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah", TILE_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
+  { "srah", TILEPRO_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah.sn", TILE_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
+  { "srah.sn", TILEPRO_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srai", TILE_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
+  { "srai", TILEPRO_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "srai.sn", TILE_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
+  { "srai.sn", TILEPRO_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib", TILE_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
+  { "sraib", TILEPRO_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib.sn", TILE_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sraib.sn", TILEPRO_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih", TILE_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
+  { "sraih", TILEPRO_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih.sn", TILE_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sraih.sn", TILEPRO_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sub", TILE_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
+  { "sub", TILEPRO_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sub.sn", TILE_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
+  { "sub.sn", TILEPRO_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb", TILE_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
+  { "subb", TILEPRO_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb.sn", TILE_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
+  { "subb.sn", TILEPRO_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u", TILE_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "subbs_u", TILEPRO_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u.sn", TILE_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "subbs_u.sn", TILEPRO_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh", TILE_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
+  { "subh", TILEPRO_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh.sn", TILE_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
+  { "subh.sn", TILEPRO_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs", TILE_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
+  { "subhs", TILEPRO_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs.sn", TILE_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
+  { "subhs.sn", TILEPRO_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs", TILE_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
+  { "subs", TILEPRO_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs.sn", TILE_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
+  { "subs.sn", TILEPRO_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sw", TILE_OPC_SW, 0x12, 2, TREG_ZERO, 1,
+  { "sw", TILEPRO_OPC_SW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "swadd", TILE_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
+  { "swadd", TILEPRO_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint0", TILE_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
+  { "swint0", TILEPRO_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint1", TILE_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
+  { "swint1", TILEPRO_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint2", TILE_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
+  { "swint2", TILEPRO_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint3", TILE_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
+  { "swint3", TILEPRO_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb0", TILE_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb0", TILEPRO_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb0.sn", TILE_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb0.sn", TILEPRO_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb1", TILE_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb1", TILEPRO_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb1.sn", TILE_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb1.sn", TILEPRO_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb2", TILE_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb2", TILEPRO_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb2.sn", TILE_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb2.sn", TILEPRO_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb3", TILE_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb3", TILEPRO_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb3.sn", TILE_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb3.sn", TILEPRO_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns", TILE_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
+  { "tns", TILEPRO_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns.sn", TILE_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
+  { "tns.sn", TILEPRO_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "wh64", TILE_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
+  { "wh64", TILEPRO_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xor", TILE_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
+  { "xor", TILEPRO_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "xor.sn", TILE_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
+  { "xor.sn", TILEPRO_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori", TILE_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
+  { "xori", TILEPRO_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori.sn", TILE_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
+  { "xori.sn", TILEPRO_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { NULL, TILE_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
+  { NULL, TILEPRO_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
   }
 };
 #define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6))
-#define CHILD(array_index) (TILE_OPC_NONE + (array_index))
+#define CHILD(array_index) (TILEPRO_OPC_NONE + (array_index))
 
 static const unsigned short decode_X0_fsm[1153] =
 {
   BITFIELD(22, 9) /* index 0 */,
   CHILD(513), CHILD(530), CHILD(547), CHILD(564), CHILD(596), CHILD(613),
-  CHILD(630), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(663), CHILD(680), CHILD(697), CHILD(714), CHILD(746),
-  CHILD(763), CHILD(780), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(813), CHILD(813), CHILD(813),
+  CHILD(630), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(663), CHILD(680), CHILD(697),
+  CHILD(714), CHILD(746), CHILD(763), CHILD(780), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
@@ -1227,7 +1247,7 @@ static const unsigned short decode_X0_fs
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
-  CHILD(813), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
+  CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
@@ -1237,7 +1257,8 @@ static const unsigned short decode_X0_fs
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
-  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(843),
+  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
+  CHILD(828), CHILD(828), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
@@ -1248,333 +1269,371 @@ static const unsigned short decode_X0_fs
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(843), CHILD(843), CHILD(873), CHILD(878), CHILD(883),
-  CHILD(903), CHILD(908), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(913),
-  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(953), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(988), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(993),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(1076), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(873), CHILD(878), CHILD(883), CHILD(903), CHILD(908),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(913),
+  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(953), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(988), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(993), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1076), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD,
-  TILE_OPC_ADIFFB_U, TILE_OPC_ADIFFH, TILE_OPC_AND, TILE_OPC_AVGB_U,
-  TILE_OPC_AVGH, TILE_OPC_CRC32_32, TILE_OPC_CRC32_8, TILE_OPC_INTHB,
-  TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH, TILE_OPC_MAXB_U,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADIFFB_U, TILEPRO_OPC_ADIFFH, TILEPRO_OPC_AND,
+  TILEPRO_OPC_AVGB_U, TILEPRO_OPC_AVGH, TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_8, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTLB, TILEPRO_OPC_INTLH, TILEPRO_OPC_MAXB_U,
   BITFIELD(18, 4) /* index 530 */,
-  TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH, TILE_OPC_MNZB, TILE_OPC_MNZH,
-  TILE_OPC_MNZ, TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_SU, TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHSA_UU, TILE_OPC_MULHH_SS, TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_UU, TILE_OPC_MULHLA_SS, TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_US,
+  TILEPRO_OPC_MAXH, TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZH, TILEPRO_OPC_MNZ, TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SU, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_SU, TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHLA_SS, TILEPRO_OPC_MULHLA_SU, TILEPRO_OPC_MULHLA_US,
   BITFIELD(18, 4) /* index 547 */,
-  TILE_OPC_MULHLA_UU, TILE_OPC_MULHLSA_UU, TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SU, TILE_OPC_MULHL_US, TILE_OPC_MULHL_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SU, TILE_OPC_MULLLA_UU, TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLL_SS, TILE_OPC_MULLL_SU, TILE_OPC_MULLL_UU, TILE_OPC_MVNZ,
-  TILE_OPC_MVZ, TILE_OPC_MZB,
+  TILEPRO_OPC_MULHLA_UU, TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SU, TILEPRO_OPC_MULHL_US, TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULLLA_SS, TILEPRO_OPC_MULLLA_SU, TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLSA_UU, TILEPRO_OPC_MULLL_SS, TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_UU, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZB,
   BITFIELD(18, 4) /* index 564 */,
-  TILE_OPC_MZH, TILE_OPC_MZ, TILE_OPC_NOR, CHILD(581), TILE_OPC_PACKHB,
-  TILE_OPC_PACKLB, TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
-  TILE_OPC_SADAB_U, TILE_OPC_SADAH, TILE_OPC_SADAH_U, TILE_OPC_SADB_U,
-  TILE_OPC_SADH, TILE_OPC_SADH_U,
+  TILEPRO_OPC_MZH, TILEPRO_OPC_MZ, TILEPRO_OPC_NOR, CHILD(581),
+  TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB, TILEPRO_OPC_RL, TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S2A, TILEPRO_OPC_S3A, TILEPRO_OPC_SADAB_U, TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_U, TILEPRO_OPC_SADB_U, TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_U,
   BITFIELD(12, 2) /* index 581 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(586),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(586),
   BITFIELD(14, 2) /* index 586 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(591),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(591),
   BITFIELD(16, 2) /* index 591 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 4) /* index 596 */,
-  TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB, TILE_OPC_SHLH,
-  TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR, TILE_OPC_SLTB,
-  TILE_OPC_SLTB_U, TILE_OPC_SLTEB, TILE_OPC_SLTEB_U, TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
+  TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ, TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB, TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHR, TILEPRO_OPC_SLTB, TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_U, TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTE,
   BITFIELD(18, 4) /* index 613 */,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
-  TILE_OPC_XOR, TILE_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB, TILEPRO_OPC_XOR, TILEPRO_OPC_DWORD_ALIGN,
   BITFIELD(18, 3) /* index 630 */,
   CHILD(639), CHILD(642), CHILD(645), CHILD(648), CHILD(651), CHILD(654),
   CHILD(657), CHILD(660),
   BITFIELD(21, 1) /* index 639 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 642 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 645 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 648 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 651 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 654 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 657 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 660 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 663 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_ADIFFB_U_SN, TILE_OPC_ADIFFH_SN, TILE_OPC_AND_SN,
-  TILE_OPC_AVGB_U_SN, TILE_OPC_AVGH_SN, TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB_SN, TILE_OPC_INTLH_SN, TILE_OPC_MAXB_U_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_ADIFFB_U_SN, TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND_SN, TILEPRO_OPC_AVGB_U_SN, TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_CRC32_32_SN, TILEPRO_OPC_CRC32_8_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_MAXB_U_SN,
   BITFIELD(18, 4) /* index 680 */,
-  TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN, TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN, TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU_SN, TILE_OPC_MULHHA_UU_SN, TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHH_SS_SN, TILE_OPC_MULHH_SU_SN, TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHLA_SS_SN, TILE_OPC_MULHLA_SU_SN, TILE_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MAXH_SN, TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MNZB_SN, TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MULHHA_SS_SN, TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU_SN, TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHH_SS_SN, TILEPRO_OPC_MULHH_SU_SN, TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHLA_SS_SN, TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US_SN,
   BITFIELD(18, 4) /* index 697 */,
-  TILE_OPC_MULHLA_UU_SN, TILE_OPC_MULHLSA_UU_SN, TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU_SN, TILE_OPC_MULHL_US_SN, TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULLLA_SS_SN, TILE_OPC_MULLLA_SU_SN, TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU_SN, TILE_OPC_MULLL_SS_SN, TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU_SN, TILE_OPC_MVNZ_SN, TILE_OPC_MVZ_SN, TILE_OPC_MZB_SN,
+  TILEPRO_OPC_MULHLA_UU_SN, TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS_SN, TILEPRO_OPC_MULHL_SU_SN, TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU_SN, TILEPRO_OPC_MULLLA_SS_SN, TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU_SN, TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS_SN, TILEPRO_OPC_MULLL_SU_SN, TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MVNZ_SN, TILEPRO_OPC_MVZ_SN, TILEPRO_OPC_MZB_SN,
   BITFIELD(18, 4) /* index 714 */,
-  TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN, CHILD(731),
-  TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN, TILE_OPC_S1A_SN,
-  TILE_OPC_S2A_SN, TILE_OPC_S3A_SN, TILE_OPC_SADAB_U_SN, TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U_SN, TILE_OPC_SADB_U_SN, TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(731),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U_SN, TILEPRO_OPC_SADAH_SN, TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U_SN, TILEPRO_OPC_SADH_SN, TILEPRO_OPC_SADH_U_SN,
   BITFIELD(12, 2) /* index 731 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(736),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(736),
   BITFIELD(14, 2) /* index 736 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(741),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(741),
   BITFIELD(16, 2) /* index 741 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(18, 4) /* index 746 */,
-  TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN, TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN, TILE_OPC_SHRH_SN,
-  TILE_OPC_SHR_SN, TILE_OPC_SLTB_SN, TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U_SN, TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTE_SN,
+  TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN, TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN, TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN, TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SLTB_SN, TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U_SN, TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTE_SN,
   BITFIELD(18, 4) /* index 763 */,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN, TILE_OPC_XOR_SN, TILE_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN, TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
   BITFIELD(18, 3) /* index 780 */,
   CHILD(789), CHILD(792), CHILD(795), CHILD(798), CHILD(801), CHILD(804),
   CHILD(807), CHILD(810),
   BITFIELD(21, 1) /* index 789 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 792 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 795 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 798 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 801 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 804 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 807 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 810 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(6, 2) /* index 813 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(818),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(818),
   BITFIELD(8, 2) /* index 818 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(823),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(823),
   BITFIELD(10, 2) /* index 823 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(6, 2) /* index 828 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(833),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(833),
   BITFIELD(8, 2) /* index 833 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(838),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(838),
   BITFIELD(10, 2) /* index 838 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(0, 2) /* index 843 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(848),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(848),
   BITFIELD(2, 2) /* index 848 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(853),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(853),
   BITFIELD(4, 2) /* index 853 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(858),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(858),
   BITFIELD(6, 2) /* index 858 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(863),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(863),
   BITFIELD(8, 2) /* index 863 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(868),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(868),
   BITFIELD(10, 2) /* index 868 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(20, 2) /* index 873 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
   BITFIELD(20, 2) /* index 878 */,
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MINIB_U, TILE_OPC_MINIH,
+  TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIH,
   BITFIELD(20, 2) /* index 883 */,
-  CHILD(888), TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI,
+  CHILD(888), TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI,
   BITFIELD(6, 2) /* index 888 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(893),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(893),
   BITFIELD(8, 2) /* index 893 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(898),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(898),
   BITFIELD(10, 2) /* index 898 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(20, 2) /* index 903 */,
-  TILE_OPC_SLTIB, TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIB, TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_U,
   BITFIELD(20, 2) /* index 908 */,
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 913 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN,
   BITFIELD(20, 2) /* index 918 */,
-  TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH_SN,
+  TILEPRO_OPC_MAXIB_U_SN, TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH_SN,
   BITFIELD(20, 2) /* index 923 */,
-  CHILD(928), TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN,
+  CHILD(928), TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
   BITFIELD(6, 2) /* index 928 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(933),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(933),
   BITFIELD(8, 2) /* index 933 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(938),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(938),
   BITFIELD(10, 2) /* index 938 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(20, 2) /* index 943 */,
-  TILE_OPC_SLTIB_SN, TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTIB_SN, TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U_SN,
   BITFIELD(20, 2) /* index 948 */,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 953 */,
-  TILE_OPC_NONE, CHILD(958), TILE_OPC_XORI, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(958), TILEPRO_OPC_XORI, TILEPRO_OPC_NONE,
   BITFIELD(0, 2) /* index 958 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(963),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(963),
   BITFIELD(2, 2) /* index 963 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(968),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(968),
   BITFIELD(4, 2) /* index 968 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(973),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(973),
   BITFIELD(6, 2) /* index 973 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(978),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(978),
   BITFIELD(8, 2) /* index 978 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(983),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(983),
   BITFIELD(10, 2) /* index 983 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(20, 2) /* index 988 */,
-  TILE_OPC_NONE, TILE_OPC_ANDI_SN, TILE_OPC_XORI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 993 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLIB, TILE_OPC_SHLIH, TILE_OPC_SHLI,
-  TILE_OPC_SHRIB, TILE_OPC_SHRIH, TILE_OPC_SHRI, TILE_OPC_SRAIB,
-  TILE_OPC_SRAIH, TILE_OPC_SRAI, CHILD(1026), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLIB, TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRIB, TILEPRO_OPC_SHRIH, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_SRAIH, TILEPRO_OPC_SRAI, CHILD(1026),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1026 */,
-  TILE_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
+  TILEPRO_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
   CHILD(1055), CHILD(1058), CHILD(1061), CHILD(1064), CHILD(1067),
-  CHILD(1070), CHILD(1073), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1070), CHILD(1073), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1043 */,
-  TILE_OPC_BITX, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1046 */,
-  TILE_OPC_BYTEX, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1049 */,
-  TILE_OPC_CLZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1052 */,
-  TILE_OPC_CTZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1055 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1058 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1061 */,
-  TILE_OPC_PCNT, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1064 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1067 */,
-  TILE_OPC_TBLIDXB1, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1070 */,
-  TILE_OPC_TBLIDXB2, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1073 */,
-  TILE_OPC_TBLIDXB3, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 1076 */,
-  TILE_OPC_NONE, TILE_OPC_RLI_SN, TILE_OPC_SHLIB_SN, TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHLI_SN, TILE_OPC_SHRIB_SN, TILE_OPC_SHRIH_SN, TILE_OPC_SHRI_SN,
-  TILE_OPC_SRAIB_SN, TILE_OPC_SRAIH_SN, TILE_OPC_SRAI_SN, CHILD(1109),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI_SN, TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_SRAI_SN, CHILD(1109), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1109 */,
-  TILE_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
+  TILEPRO_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
   CHILD(1055), CHILD(1058), CHILD(1138), CHILD(1141), CHILD(1144),
-  CHILD(1147), CHILD(1150), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1147), CHILD(1150), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1126 */,
-  TILE_OPC_BITX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1129 */,
-  TILE_OPC_BYTEX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1132 */,
-  TILE_OPC_CLZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1135 */,
-  TILE_OPC_CTZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1138 */,
-  TILE_OPC_PCNT_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1141 */,
-  TILE_OPC_TBLIDXB0_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1144 */,
-  TILE_OPC_TBLIDXB1_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1147 */,
-  TILE_OPC_TBLIDXB2_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1150 */,
-  TILE_OPC_TBLIDXB3_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_X1_fsm[1540] =
 {
   BITFIELD(54, 9) /* index 0 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(513), CHILD(561), CHILD(594),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(641), CHILD(689),
-  CHILD(722), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(766),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(513), CHILD(561), CHILD(594), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(641),
+  CHILD(689), CHILD(722), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
@@ -1596,594 +1655,641 @@ static const unsigned short decode_X1_fs
   CHILD(826), CHILD(826), CHILD(826), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(941), CHILD(950), CHILD(974), CHILD(983),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(992),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  CHILD(1334), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(941), CHILD(950), CHILD(974), CHILD(983), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(992),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1334),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD, TILE_OPC_AND,
-  TILE_OPC_INTHB, TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH,
-  TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR, TILE_OPC_LNK,
-  TILE_OPC_MAXB_U, TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH,
-  TILE_OPC_MNZB, TILE_OPC_MNZH, TILE_OPC_MNZ, TILE_OPC_MZB, TILE_OPC_MZH,
-  TILE_OPC_MZ, TILE_OPC_NOR, CHILD(546), TILE_OPC_PACKHB, TILE_OPC_PACKLB,
-  TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_AND, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH, TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLH, TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP,
+  TILEPRO_OPC_JR, TILEPRO_OPC_LNK, TILEPRO_OPC_MAXB_U, TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB, TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MZB, TILEPRO_OPC_MZH, TILEPRO_OPC_MZ,
+  TILEPRO_OPC_NOR, CHILD(546), TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_RL, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_S3A,
   BITFIELD(43, 2) /* index 546 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(551),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(551),
   BITFIELD(45, 2) /* index 551 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(556),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(556),
   BITFIELD(47, 2) /* index 556 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 5) /* index 561 */,
-  TILE_OPC_SB, TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB,
-  TILE_OPC_SHLH, TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR,
-  TILE_OPC_SH, TILE_OPC_SLTB, TILE_OPC_SLTB_U, TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_U, TILE_OPC_SLTEH, TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SHLB, TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRH, TILEPRO_OPC_SHR, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB, TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U, TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB,
   BITFIELD(49, 4) /* index 594 */,
   CHILD(611), CHILD(614), CHILD(617), CHILD(620), CHILD(623), CHILD(626),
-  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 611 */,
-  TILE_OPC_SW, TILE_OPC_NONE,
+  TILEPRO_OPC_SW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 614 */,
-  TILE_OPC_XOR, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 617 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 620 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 623 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 626 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 629 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 632 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 635 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 638 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 641 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_AND_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN, TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH_SN, TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR,
-  TILE_OPC_LNK_SN, TILE_OPC_MAXB_U_SN, TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN, TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN,
-  TILE_OPC_MZB_SN, TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN,
-  CHILD(674), TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN,
-  TILE_OPC_S1A_SN, TILE_OPC_S2A_SN, TILE_OPC_S3A_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_AND_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP, TILEPRO_OPC_JR,
+  TILEPRO_OPC_LNK_SN, TILEPRO_OPC_MAXB_U_SN, TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN, TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN, TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(674),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
   BITFIELD(43, 2) /* index 674 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(679),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(679),
   BITFIELD(45, 2) /* index 679 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(684),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(684),
   BITFIELD(47, 2) /* index 684 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(49, 5) /* index 689 */,
-  TILE_OPC_SB, TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN,
-  TILE_OPC_SHLB_SN, TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH_SN, TILE_OPC_SHR_SN, TILE_OPC_SH, TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN, TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN, TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQ_SN, TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHL_SN, TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHR_SN, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN, TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN, TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN,
   BITFIELD(49, 4) /* index 722 */,
   CHILD(611), CHILD(739), CHILD(742), CHILD(745), CHILD(748), CHILD(751),
-  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 739 */,
-  TILE_OPC_XOR_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 742 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 745 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 748 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 751 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 754 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 757 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 760 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 763 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(37, 2) /* index 766 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(771),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(771),
   BITFIELD(39, 2) /* index 771 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(776),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(776),
   BITFIELD(41, 2) /* index 776 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(37, 2) /* index 781 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(786),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(786),
   BITFIELD(39, 2) /* index 786 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(791),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(791),
   BITFIELD(41, 2) /* index 791 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(31, 2) /* index 796 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(801),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(801),
   BITFIELD(33, 2) /* index 801 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(806),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(806),
   BITFIELD(35, 2) /* index 806 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(811),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(811),
   BITFIELD(37, 2) /* index 811 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(816),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(816),
   BITFIELD(39, 2) /* index 816 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(821),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(821),
   BITFIELD(41, 2) /* index 821 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(31, 4) /* index 826 */,
-  TILE_OPC_BZ, TILE_OPC_BZT, TILE_OPC_BNZ, TILE_OPC_BNZT, TILE_OPC_BGZ,
-  TILE_OPC_BGZT, TILE_OPC_BGEZ, TILE_OPC_BGEZT, TILE_OPC_BLZ, TILE_OPC_BLZT,
-  TILE_OPC_BLEZ, TILE_OPC_BLEZT, TILE_OPC_BBS, TILE_OPC_BBST, TILE_OPC_BBNS,
-  TILE_OPC_BBNST,
+  TILEPRO_OPC_BZ, TILEPRO_OPC_BZT, TILEPRO_OPC_BNZ, TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BGZ, TILEPRO_OPC_BGZT, TILEPRO_OPC_BGEZ, TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BLZ, TILEPRO_OPC_BLZT, TILEPRO_OPC_BLEZ, TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BBS, TILEPRO_OPC_BBST, TILEPRO_OPC_BBNS, TILEPRO_OPC_BBNST,
   BITFIELD(31, 4) /* index 843 */,
-  TILE_OPC_BZ_SN, TILE_OPC_BZT_SN, TILE_OPC_BNZ_SN, TILE_OPC_BNZT_SN,
-  TILE_OPC_BGZ_SN, TILE_OPC_BGZT_SN, TILE_OPC_BGEZ_SN, TILE_OPC_BGEZT_SN,
-  TILE_OPC_BLZ_SN, TILE_OPC_BLZT_SN, TILE_OPC_BLEZ_SN, TILE_OPC_BLEZT_SN,
-  TILE_OPC_BBS_SN, TILE_OPC_BBST_SN, TILE_OPC_BBNS_SN, TILE_OPC_BBNST_SN,
+  TILEPRO_OPC_BZ_SN, TILEPRO_OPC_BZT_SN, TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT_SN, TILEPRO_OPC_BGZ_SN, TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BGEZ_SN, TILEPRO_OPC_BGEZT_SN, TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT_SN, TILEPRO_OPC_BLEZ_SN, TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BBS_SN, TILEPRO_OPC_BBST_SN, TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST_SN,
   BITFIELD(51, 3) /* index 860 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI, CHILD(869),
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
+  CHILD(869), TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MFSPR,
   BITFIELD(31, 2) /* index 869 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(874),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(874),
   BITFIELD(33, 2) /* index 874 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(879),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(879),
   BITFIELD(35, 2) /* index 879 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(884),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(884),
   BITFIELD(37, 2) /* index 884 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(889),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(889),
   BITFIELD(39, 2) /* index 889 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(894),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(894),
   BITFIELD(41, 2) /* index 894 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(51, 3) /* index 899 */,
-  TILE_OPC_MINIB_U, TILE_OPC_MINIH, TILE_OPC_MTSPR, CHILD(908),
-  TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI, TILE_OPC_SLTIB,
+  TILEPRO_OPC_MINIB_U, TILEPRO_OPC_MINIH, TILEPRO_OPC_MTSPR, CHILD(908),
+  TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI, TILEPRO_OPC_SLTIB,
   BITFIELD(37, 2) /* index 908 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(913),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(913),
   BITFIELD(39, 2) /* index 913 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(918),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(918),
   BITFIELD(41, 2) /* index 918 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(51, 3) /* index 923 */,
-  TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U, TILE_OPC_SLTI,
-  TILE_OPC_SLTI_U, TILE_OPC_XORI, TILE_OPC_LBADD, TILE_OPC_LBADD_U,
+  TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH, TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_XORI, TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_U,
   BITFIELD(51, 3) /* index 932 */,
-  TILE_OPC_LHADD, TILE_OPC_LHADD_U, TILE_OPC_LWADD, TILE_OPC_LWADD_NA,
-  TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD, TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD, TILEPRO_OPC_LHADD_U, TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_NA, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(51, 3) /* index 941 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
-  TILE_OPC_ANDI_SN, TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MFSPR,
   BITFIELD(51, 3) /* index 950 */,
-  TILE_OPC_MINIB_U_SN, TILE_OPC_MINIH_SN, TILE_OPC_MTSPR, CHILD(959),
-  TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN, TILE_OPC_SLTIB_SN,
+  TILEPRO_OPC_MINIB_U_SN, TILEPRO_OPC_MINIH_SN, TILEPRO_OPC_MTSPR, CHILD(959),
+  TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SLTIB_SN,
   BITFIELD(37, 2) /* index 959 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(964),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(964),
   BITFIELD(39, 2) /* index 964 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(969),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(969),
   BITFIELD(41, 2) /* index 969 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(51, 3) /* index 974 */,
-  TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN, TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_XORI_SN, TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U_SN,
+  TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN, TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_LBADD_SN, TILEPRO_OPC_LBADD_U_SN,
   BITFIELD(51, 3) /* index 983 */,
-  TILE_OPC_LHADD_SN, TILE_OPC_LHADD_U_SN, TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA_SN, TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD,
-  TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD_SN, TILEPRO_OPC_LHADD_U_SN, TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA_SN, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 992 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1121),
-  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124), CHILD(1124),
-  CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127), CHILD(1127),
-  CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130), CHILD(1130),
-  CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1136),
-  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139), CHILD(1139),
-  CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142), CHILD(1142),
-  CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145), CHILD(1145),
-  CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1151),
-  CHILD(1242), CHILD(1290), CHILD(1323), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124),
+  CHILD(1124), CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127),
+  CHILD(1127), CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130),
+  CHILD(1130), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133),
+  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139),
+  CHILD(1139), CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142),
+  CHILD(1142), CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145),
+  CHILD(1145), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148),
+  CHILD(1151), CHILD(1242), CHILD(1290), CHILD(1323), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1121 */,
-  TILE_OPC_RLI, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1124 */,
-  TILE_OPC_SHLIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1127 */,
-  TILE_OPC_SHLIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1130 */,
-  TILE_OPC_SHLI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1133 */,
-  TILE_OPC_SHRIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1136 */,
-  TILE_OPC_SHRIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1139 */,
-  TILE_OPC_SHRI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1142 */,
-  TILE_OPC_SRAIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1145 */,
-  TILE_OPC_SRAIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1148 */,
-  TILE_OPC_SRAI, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1151 */,
-  TILE_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
+  TILEPRO_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
   CHILD(1172), CHILD(1175), CHILD(1178),
   BITFIELD(53, 1) /* index 1160 */,
-  TILE_OPC_DRAIN, TILE_OPC_NONE,
+  TILEPRO_OPC_DRAIN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1163 */,
-  TILE_OPC_DTLBPR, TILE_OPC_NONE,
+  TILEPRO_OPC_DTLBPR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1166 */,
-  TILE_OPC_FINV, TILE_OPC_NONE,
+  TILEPRO_OPC_FINV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1169 */,
-  TILE_OPC_FLUSH, TILE_OPC_NONE,
+  TILEPRO_OPC_FLUSH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1172 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1175 */,
-  TILE_OPC_ICOH, TILE_OPC_NONE,
+  TILEPRO_OPC_ICOH, TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1178 */,
   CHILD(1183), CHILD(1211), CHILD(1239), CHILD(1239),
   BITFIELD(53, 1) /* index 1183 */,
-  CHILD(1186), TILE_OPC_NONE,
+  CHILD(1186), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1186 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1191),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1191),
   BITFIELD(35, 2) /* index 1191 */,
-  TILE_OPC_ILL, CHILD(1196), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1196), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1196 */,
-  TILE_OPC_ILL, CHILD(1201), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1201), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1201 */,
-  TILE_OPC_ILL, CHILD(1206), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1206), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1206 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_BPT, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_BPT, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1211 */,
-  CHILD(1214), TILE_OPC_NONE,
+  CHILD(1214), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1214 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1219),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1219),
   BITFIELD(35, 2) /* index 1219 */,
-  TILE_OPC_ILL, CHILD(1224), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1224), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1224 */,
-  TILE_OPC_ILL, CHILD(1229), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1229), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1229 */,
-  TILE_OPC_ILL, CHILD(1234), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1234), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1234 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_RAISE, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_RAISE, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1239 */,
-  TILE_OPC_ILL, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1242 */,
   CHILD(1251), CHILD(1254), CHILD(1257), CHILD(1275), CHILD(1278),
   CHILD(1281), CHILD(1284), CHILD(1287),
   BITFIELD(53, 1) /* index 1251 */,
-  TILE_OPC_INV, TILE_OPC_NONE,
+  TILEPRO_OPC_INV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1254 */,
-  TILE_OPC_IRET, TILE_OPC_NONE,
+  TILEPRO_OPC_IRET, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1257 */,
-  CHILD(1260), TILE_OPC_NONE,
+  CHILD(1260), TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1260 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1265),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1265),
   BITFIELD(33, 2) /* index 1265 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1270),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1270),
   BITFIELD(35, 2) /* index 1270 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
   BITFIELD(53, 1) /* index 1275 */,
-  TILE_OPC_LB_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1278 */,
-  TILE_OPC_LH, TILE_OPC_NONE,
+  TILEPRO_OPC_LH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1281 */,
-  TILE_OPC_LH_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1284 */,
-  TILE_OPC_LW, TILE_OPC_NONE,
+  TILEPRO_OPC_LW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1287 */,
-  TILE_OPC_MF, TILE_OPC_NONE,
+  TILEPRO_OPC_MF, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1290 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1317), CHILD(1320),
   BITFIELD(53, 1) /* index 1299 */,
-  TILE_OPC_NAP, TILE_OPC_NONE,
+  TILEPRO_OPC_NAP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1302 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1305 */,
-  TILE_OPC_SWINT0, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT0, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1308 */,
-  TILE_OPC_SWINT1, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT1, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1311 */,
-  TILE_OPC_SWINT2, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT2, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1314 */,
-  TILE_OPC_SWINT3, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT3, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1317 */,
-  TILE_OPC_TNS, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1320 */,
-  TILE_OPC_WH64, TILE_OPC_NONE,
+  TILEPRO_OPC_WH64, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1323 */,
-  CHILD(1328), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1328), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1328 */,
-  CHILD(1331), TILE_OPC_NONE,
+  CHILD(1331), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1331 */,
-  TILE_OPC_LW_NA, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 1334 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1463),
-  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466), CHILD(1466),
-  CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469), CHILD(1469),
-  CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472), CHILD(1472),
-  CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1478),
-  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481), CHILD(1481),
-  CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484), CHILD(1484),
-  CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487), CHILD(1487),
-  CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1151),
-  CHILD(1493), CHILD(1517), CHILD(1529), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466),
+  CHILD(1466), CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469),
+  CHILD(1469), CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472),
+  CHILD(1472), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475),
+  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481),
+  CHILD(1481), CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484),
+  CHILD(1484), CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487),
+  CHILD(1487), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490),
+  CHILD(1151), CHILD(1493), CHILD(1517), CHILD(1529), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1463 */,
-  TILE_OPC_RLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1466 */,
-  TILE_OPC_SHLIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1469 */,
-  TILE_OPC_SHLIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1472 */,
-  TILE_OPC_SHLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1475 */,
-  TILE_OPC_SHRIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1478 */,
-  TILE_OPC_SHRIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1481 */,
-  TILE_OPC_SHRI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1484 */,
-  TILE_OPC_SRAIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1487 */,
-  TILE_OPC_SRAIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1490 */,
-  TILE_OPC_SRAI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1493 */,
   CHILD(1251), CHILD(1254), CHILD(1502), CHILD(1505), CHILD(1508),
   CHILD(1511), CHILD(1514), CHILD(1287),
   BITFIELD(53, 1) /* index 1502 */,
-  TILE_OPC_LB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1505 */,
-  TILE_OPC_LB_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1508 */,
-  TILE_OPC_LH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1511 */,
-  TILE_OPC_LH_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1514 */,
-  TILE_OPC_LW_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1517 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1526), CHILD(1320),
   BITFIELD(53, 1) /* index 1526 */,
-  TILE_OPC_TNS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1529 */,
-  CHILD(1534), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1534), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1534 */,
-  CHILD(1537), TILE_OPC_NONE,
+  CHILD(1537), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1537 */,
-  TILE_OPC_LW_NA_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y0_fsm[168] =
 {
   BITFIELD(27, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), CHILD(62), CHILD(67), TILE_OPC_ADDI, CHILD(72), CHILD(102),
-  TILE_OPC_SEQI, CHILD(117), TILE_OPC_SLTI, TILE_OPC_SLTI_U,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), CHILD(62), CHILD(67), TILEPRO_OPC_ADDI, CHILD(72), CHILD(102),
+  TILEPRO_OPC_SEQI, CHILD(117), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U,
   BITFIELD(18, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(18, 2) /* index 22 */,
-  TILE_OPC_MNZ, TILE_OPC_MVNZ, TILE_OPC_MVZ, TILE_OPC_MZ,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZ,
   BITFIELD(18, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(12, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(14, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(16, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(18, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(18, 2) /* index 57 */,
-  TILE_OPC_MULHLSA_UU, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(18, 2) /* index 62 */,
-  TILE_OPC_MULHH_SS, TILE_OPC_MULHH_UU, TILE_OPC_MULLL_SS, TILE_OPC_MULLL_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_UU, TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_UU,
   BITFIELD(18, 2) /* index 67 */,
-  TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULHHA_SS, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_UU,
   BITFIELD(0, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(2, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(4, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(6, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(92),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(92),
   BITFIELD(8, 2) /* index 92 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(97),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(97),
   BITFIELD(10, 2) /* index 97 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(6, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(107),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(107),
   BITFIELD(8, 2) /* index 107 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(112),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(112),
   BITFIELD(10, 2) /* index 112 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(15, 5) /* index 117 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_RLI,
-  TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHLI,
-  TILE_OPC_SHLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SHRI, TILE_OPC_SHRI,
-  TILE_OPC_SHRI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI,
-  CHILD(150), CHILD(159), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI,
+  CHILD(150), CHILD(159), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 3) /* index 150 */,
-  TILE_OPC_NONE, TILE_OPC_BITX, TILE_OPC_BYTEX, TILE_OPC_CLZ, TILE_OPC_CTZ,
-  TILE_OPC_FNOP, TILE_OPC_NOP, TILE_OPC_PCNT,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_BITX, TILEPRO_OPC_BYTEX, TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_FNOP, TILEPRO_OPC_NOP, TILEPRO_OPC_PCNT,
   BITFIELD(12, 3) /* index 159 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_TBLIDXB1, TILE_OPC_TBLIDXB2, TILE_OPC_TBLIDXB3,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y1_fsm[140] =
 {
   BITFIELD(59, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), TILE_OPC_ADDI, CHILD(62), CHILD(92), TILE_OPC_SEQI, CHILD(107),
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), TILEPRO_OPC_ADDI, CHILD(62), CHILD(92), TILEPRO_OPC_SEQI,
+  CHILD(107), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(49, 2) /* index 22 */,
-  TILE_OPC_NONE, TILE_OPC_MNZ, TILE_OPC_MZ, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_MNZ, TILEPRO_OPC_MZ, TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(43, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(45, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(47, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(49, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(49, 2) /* index 57 */,
-  TILE_OPC_NONE, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(31, 2) /* index 62 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(67),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(67),
   BITFIELD(33, 2) /* index 67 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(72),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(72),
   BITFIELD(35, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(37, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(39, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(41, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(37, 2) /* index 92 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(97),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(97),
   BITFIELD(39, 2) /* index 97 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(102),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(102),
   BITFIELD(41, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(48, 3) /* index 107 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SRAI,
-  CHILD(116), TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, CHILD(116), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 116 */,
-  TILE_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 125 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 130 */,
-  TILE_OPC_ILL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 135 */,
-  TILE_OPC_NOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y2_fsm[24] =
 {
   BITFIELD(56, 3) /* index 0 */,
-  CHILD(9), TILE_OPC_LB_U, TILE_OPC_LH, TILE_OPC_LH_U, TILE_OPC_LW,
-  TILE_OPC_SB, TILE_OPC_SH, TILE_OPC_SW,
+  CHILD(9), TILEPRO_OPC_LB_U, TILEPRO_OPC_LH, TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LW, TILEPRO_OPC_SB, TILEPRO_OPC_SH, TILEPRO_OPC_SW,
   BITFIELD(20, 2) /* index 9 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(14),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(14),
   BITFIELD(22, 2) /* index 14 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(19),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(19),
   BITFIELD(24, 2) /* index 19 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
 };
 
 #undef BITFIELD
 #undef CHILD
 const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS] =
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS] =
 {
   decode_X0_fsm,
   decode_X1_fsm,
@@ -2191,220 +2297,220 @@ tile_bundle_decoder_fsms[TILE_NUM_PIPELI
   decode_Y1_fsm,
   decode_Y2_fsm
 };
-const struct tile_operand tile_operands[43] =
+const struct tilepro_operand tilepro_operands[43] =
 {
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X0, get_Imm8_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X1, get_Imm8_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y0, get_Imm8_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y1, get_Imm8_Y1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X0),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X0, get_Imm16_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X1),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X1, get_Imm16_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_JOFFLONG_X1),
-    29, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_JOFFLONG_X1),
+    29, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOffLong_X1, get_JOffLong_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X0, get_SrcA_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X1, get_Dest_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y0, get_SrcA_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y1, get_Dest_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y1, get_SrcA_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y2, get_SrcA_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X0, get_SrcB_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X1, get_SrcB_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y0, get_SrcB_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y1, get_SrcB_Y1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_BROFF_X1),
-    17, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_BROFF_X1),
+    17, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
-    28, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    28, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOff_X1, get_JOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MF_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MF_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MF_Imm15_X1, get_MF_Imm15_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X0),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X0, get_MMStart_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X0),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X0, get_MMEnd_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X1),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X1, get_MMStart_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X1),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X1, get_MMEnd_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MT_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MT_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MT_Imm15_X1, get_MT_Imm15_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X0, get_ShAmt_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X1, get_ShAmt_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y0, get_ShAmt_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y1, get_ShAmt_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_DEST_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Dest_Imm8_X1, get_Dest_Imm8_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_SN_BROFF),
-    10, 1, 0, 0, 1, TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    10, 1, 0, 0, 1, TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
     create_BrOff_SN, get_BrOff_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_UIMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 0, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_IMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 1, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 0, 1, 0, 0,
     create_Dest_SN, get_Dest_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 1, 0, 0, 0,
     create_Src_SN, get_Src_SN
   }
@@ -2416,10 +2522,10 @@ const struct tile_operand tile_operands[
 /* Given a set of bundle bits and a specific pipe, returns which
  * instruction the bundle contains in that pipe.
  */
-const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe)
+const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe)
 {
-  const unsigned short *table = tile_bundle_decoder_fsms[pipe];
+  const unsigned short *table = tilepro_bundle_decoder_fsms[pipe];
   int index = 0;
 
   while (1)
@@ -2429,51 +2535,51 @@ find_opcode(tile_bundle_bits bits, tile_
       ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6);
 
     unsigned short next = table[index + 1 + bitfield];
-    if (next <= TILE_OPC_NONE)
-      return &tile_opcodes[next];
+    if (next <= TILEPRO_OPC_NONE)
+      return &tilepro_opcodes[next];
 
-    index = next - TILE_OPC_NONE;
+    index = next - TILEPRO_OPC_NONE;
   }
 }
 
 
 int
-parse_insn_tile(tile_bundle_bits bits,
-                unsigned int pc,
-                struct tile_decoded_instruction
-                decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE])
+parse_insn_tilepro(tilepro_bundle_bits bits,
+                   unsigned int pc,
+                   struct tilepro_decoded_instruction
+                   decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE])
 {
   int num_instructions = 0;
   int pipe;
 
   int min_pipe, max_pipe;
-  if ((bits & TILE_BUNDLE_Y_ENCODING_MASK) == 0)
+  if ((bits & TILEPRO_BUNDLE_Y_ENCODING_MASK) == 0)
   {
-    min_pipe = TILE_PIPELINE_X0;
-    max_pipe = TILE_PIPELINE_X1;
+    min_pipe = TILEPRO_PIPELINE_X0;
+    max_pipe = TILEPRO_PIPELINE_X1;
   }
   else
   {
-    min_pipe = TILE_PIPELINE_Y0;
-    max_pipe = TILE_PIPELINE_Y2;
+    min_pipe = TILEPRO_PIPELINE_Y0;
+    max_pipe = TILEPRO_PIPELINE_Y2;
   }
 
   /* For each pipe, find an instruction that fits. */
   for (pipe = min_pipe; pipe <= max_pipe; pipe++)
   {
-    const struct tile_opcode *opc;
-    struct tile_decoded_instruction *d;
+    const struct tilepro_opcode *opc;
+    struct tilepro_decoded_instruction *d;
     int i;
 
     d = &decoded[num_instructions++];
-    opc = find_opcode (bits, (tile_pipeline)pipe);
+    opc = find_opcode (bits, (tilepro_pipeline)pipe);
     d->opcode = opc;
 
     /* Decode each operand, sign extending, etc. as appropriate. */
     for (i = 0; i < opc->num_operands; i++)
     {
-      const struct tile_operand *op =
-        &tile_operands[opc->operands[pipe][i]];
+      const struct tilepro_operand *op =
+        &tilepro_operands[opc->operands[pipe][i]];
       int opval = op->extract (bits);
       if (op->is_signed)
       {
@@ -2483,9 +2589,9 @@ parse_insn_tile(tile_bundle_bits bits,
       }
 
       /* Adjust PC-relative scaled branch offsets. */
-      if (op->type == TILE_OP_TYPE_ADDRESS)
+      if (op->type == TILEPRO_OP_TYPE_ADDRESS)
       {
-        opval *= TILE_BUNDLE_SIZE_IN_BYTES;
+        opval *= TILEPRO_BUNDLE_SIZE_IN_BYTES;
         opval += (int)pc;
       }
 
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/tile-desc_64.c linux-libre-3.2-gnu1/arch/tile/kernel/tile-desc_64.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/tile-desc_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/tile-desc_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,23 @@
+/* TILE-Gx opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
@@ -6,10 +26,8 @@
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile_64.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
 const struct tilegx_opcode tilegx_opcodes[334] =
 {
@@ -2040,12 +2058,12 @@ const struct tilegx_operand tilegx_opera
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0),
     6, 0, 0, 0, 0, 0,
     create_BFStart_X0, get_BFStart_X0
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0),
     6, 0, 0, 0, 0, 0,
     create_BFEnd_X0, get_BFEnd_X0
   },
diff -druNp linux-libre-3.1-gnu1/arch/tile/kernel/traps.c linux-libre-3.2-gnu1/arch/tile/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/tile/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,13 +19,12 @@
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/ptrace.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
+#include <arch/opcode.h>
 
 void __init trap_init(void)
 {
@@ -135,7 +134,7 @@ static int special_ill(bundle_bits bundl
 	if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1)
 		return 0;
 #else
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK)
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)
 		return 0;
 	if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1)
 		return 0;
diff -druNp linux-libre-3.1-gnu1/arch/tile/lib/exports.c linux-libre-3.2-gnu1/arch/tile/lib/exports.c
--- linux-libre-3.1-gnu1/arch/tile/lib/exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/lib/exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@ EXPORT_SYMBOL(finv_user_asm);
 EXPORT_SYMBOL(current_text_addr);
 EXPORT_SYMBOL(dump_stack);
 
+/* arch/tile/kernel/head.S */
+EXPORT_SYMBOL(empty_zero_page);
+
 /* arch/tile/lib/, various memcpy files */
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__copy_to_user_inatomic);
@@ -79,8 +82,6 @@ EXPORT_SYMBOL(__umoddi3);
 int64_t __moddi3(int64_t dividend, int64_t divisor);
 EXPORT_SYMBOL(__moddi3);
 #ifndef __tilegx__
-uint64_t __ll_mul(uint64_t n0, uint64_t n1);
-EXPORT_SYMBOL(__ll_mul);
 int64_t __muldi3(int64_t, int64_t);
 EXPORT_SYMBOL(__muldi3);
 uint64_t __lshrdi3(uint64_t, unsigned int);
diff -druNp linux-libre-3.1-gnu1/arch/tile/mm/homecache.c linux-libre-3.2-gnu1/arch/tile/mm/homecache.c
--- linux-libre-3.1-gnu1/arch/tile/mm/homecache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/tile/mm/homecache.c	2012-01-04 18:55:44.000000000 -0500
@@ -449,9 +449,12 @@ void homecache_free_pages(unsigned long
 	VM_BUG_ON(!virt_addr_valid((void *)addr));
 	page = virt_to_page((void *)addr);
 	if (put_page_testzero(page)) {
-		int pages = (1 << order);
 		homecache_change_page_home(page, order, initial_page_home());
-		while (pages--)
-			__free_page(page++);
+		if (order == 0) {
+			free_hot_cold_page(page, 0);
+		} else {
+			init_page_count(page);
+			__free_pages(page, order);
+		}
 	}
 }
diff -druNp linux-libre-3.1-gnu1/arch/um/defconfig linux-libre-3.2-gnu1/arch/um/defconfig
--- linux-libre-3.1-gnu1/arch/um/defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@ CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_STACKTRACE_SUPPORT is not set
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_IRQ_RELEASE_METHOD=y
 CONFIG_HZ=100
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/chan.h linux-libre-3.2-gnu1/arch/um/drivers/chan.h
--- linux-libre-3.1-gnu1/arch/um/drivers/chan.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/chan.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/* 
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_KERN_H__
+#define __CHAN_KERN_H__
+
+#include <linux/tty.h>
+#include <linux/list.h>
+#include <linux/console.h>
+#include "chan_user.h"
+#include "line.h"
+
+struct chan {
+	struct list_head list;
+	struct list_head free_list;
+	struct line *line;
+	char *dev;
+	unsigned int primary:1;
+	unsigned int input:1;
+	unsigned int output:1;
+	unsigned int opened:1;
+	unsigned int enabled:1;
+	int fd;
+	const struct chan_ops *ops;
+	void *data;
+};
+
+extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+			   struct tty_struct *tty, int irq);
+extern int parse_chan_pair(char *str, struct line *line, int device,
+			   const struct chan_opts *opts, char **error_out);
+extern int write_chan(struct list_head *chans, const char *buf, int len,
+			     int write_irq);
+extern int console_write_chan(struct list_head *chans, const char *buf, 
+			      int len);
+extern int console_open_chan(struct line *line, struct console *co);
+extern void deactivate_chan(struct list_head *chans, int irq);
+extern void reactivate_chan(struct list_head *chans, int irq);
+extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
+extern int enable_chan(struct line *line);
+extern void close_chan(struct list_head *chans, int delay_free_irq);
+extern int chan_window_size(struct list_head *chans, 
+			     unsigned short *rows_out, 
+			     unsigned short *cols_out);
+extern int chan_config_string(struct list_head *chans, char *str, int size,
+			      char **error_out);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/chan_kern.c linux-libre-3.2-gnu1/arch/um/drivers/chan_kern.c
--- linux-libre-3.1-gnu1/arch/um/drivers/chan_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/chan_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include "chan_kern.h"
+#include "chan.h"
 #include "os.h"
 
 #ifdef CONFIG_NOCONFIG_CHAN
@@ -358,11 +358,11 @@ int chan_window_size(struct list_head *c
 	return 0;
 }
 
-static void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan)
 {
 	list_del(&chan->list);
 
-	close_one_chan(chan, delay_free_irq);
+	close_one_chan(chan, 0);
 
 	if (chan->ops->free != NULL)
 		(*chan->ops->free)(chan->data);
@@ -372,14 +372,14 @@ static void free_one_chan(struct chan *c
 	kfree(chan);
 }
 
-static void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans)
 {
 	struct list_head *ele, *next;
 	struct chan *chan;
 
 	list_for_each_safe(ele, next, chans) {
 		chan = list_entry(ele, struct chan, list);
-		free_one_chan(chan, delay_free_irq);
+		free_one_chan(chan);
 	}
 }
 
@@ -547,7 +547,7 @@ int parse_chan_pair(char *str, struct li
 	char *in, *out;
 
 	if (!list_empty(chans)) {
-		free_chan(chans, 0);
+		free_chan(chans);
 		INIT_LIST_HEAD(chans);
 	}
 
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/chan_user.c linux-libre-3.2-gnu1/arch/um/drivers/chan_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/chan_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/chan_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 void generic_close(int fd, void *unused)
 {
@@ -283,7 +281,12 @@ void register_winch(int fd, struct tty_s
 		return;
 
 	pid = tcgetpgrp(fd);
-	if (!is_skas_winch(pid, fd, tty) && (pid == -1)) {
+	if (is_skas_winch(pid, fd, tty)) {
+		register_winch_irq(-1, fd, -1, tty, 0);
+		return;
+	}
+
+	if (pid == -1) {
 		thread = winch_tramp(fd, tty, &thread_fd, &stack);
 		if (thread < 0)
 			return;
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/chan_user.h linux-libre-3.2-gnu1/arch/um/drivers/chan_user.h
--- linux-libre-3.1-gnu1/arch/um/drivers/chan_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/chan_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_USER_H__
+#define __CHAN_USER_H__
+
+#include "init.h"
+
+struct chan_opts {
+	void (*const announce)(char *dev_name, int dev);
+	char *xterm_title;
+	const int raw;
+};
+
+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
+
+struct chan_ops {
+	char *type;
+	void *(*init)(char *, int, const struct chan_opts *);
+	int (*open)(int, int, int, void *, char **);
+	void (*close)(int, void *);
+	int (*read)(int, char *, void *);
+	int (*write)(int, const char *, int, void *);
+	int (*console_write)(int, const char *, int);
+	int (*window_size)(int, void *, unsigned short *, unsigned short *);
+	void (*free)(void *);
+	int winch;
+};
+
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+	tty_ops, xterm_ops;
+
+extern void generic_close(int fd, void *unused);
+extern int generic_read(int fd, char *c_out, void *unused);
+extern int generic_write(int fd, const char *buf, int n, void *unused);
+extern int generic_console_write(int fd, const char *buf, int n);
+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			       unsigned short *cols_out);
+extern void generic_free(void *data);
+
+struct tty_struct;
+extern void register_winch(int fd,  struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
+
+#define __channel_help(fn, prefix) \
+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
+"    Attach a console or serial line to a host channel.  See\n" \
+"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
+"    description of this switch.\n\n" \
+);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/cow_sys.h linux-libre-3.2-gnu1/arch/um/drivers/cow_sys.h
--- linux-libre-3.1-gnu1/arch/um/drivers/cow_sys.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/cow_sys.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,6 @@
 
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 #include "um_malloc.h"
 
 static inline void *cow_malloc(int size)
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/daemon_user.c linux-libre-3.2-gnu1/arch/um/drivers/daemon_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/daemon_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/daemon_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,6 @@
 #include "net_user.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 enum request_type { REQ_NEW_CONTROL };
 
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/fd.c linux-libre-3.2-gnu1/arch/um/drivers/fd.c
--- linux-libre-3.1-gnu1/arch/um/drivers/fd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/fd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,10 +9,8 @@
 #include <errno.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct fd_chan {
 	int fd;
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/harddog_user.c linux-libre-3.2-gnu1/arch/um/drivers/harddog_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/harddog_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/harddog_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include "os.h"
-#include "user.h"
 
 struct dog_data {
 	int stdin;
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/line.c linux-libre-3.2-gnu1/arch/um/drivers/line.c
--- linux-libre-3.1-gnu1/arch/um/drivers/line.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/line.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 #include "linux/kd.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_kern.h"
 #include "irq_user.h"
 #include "kern_util.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/line.h linux-libre-3.2-gnu1/arch/um/drivers/line.h
--- linux-libre-3.1-gnu1/arch/um/drivers/line.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/line.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/* 
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __LINE_H__
+#define __LINE_H__
+
+#include "linux/list.h"
+#include "linux/workqueue.h"
+#include "linux/tty.h"
+#include "linux/interrupt.h"
+#include "linux/spinlock.h"
+#include "linux/mutex.h"
+#include "chan_user.h"
+#include "mconsole_kern.h"
+
+/* There's only one modifiable field in this - .mc.list */
+struct line_driver {
+	const char *name;
+	const char *device_name;
+	const short major;
+	const short minor_start;
+	const short type;
+	const short subtype;
+	const int read_irq;
+	const char *read_irq_name;
+	const int write_irq;
+	const char *write_irq_name;
+	struct mc_device mc;
+};
+
+struct line {
+	struct tty_struct *tty;
+	spinlock_t count_lock;
+	unsigned long count;
+	int valid;
+
+	char *init_str;
+	int init_pri;
+	struct list_head chan_list;
+
+	/*This lock is actually, mostly, local to*/
+	spinlock_t lock;
+	int throttled;
+	/* Yes, this is a real circular buffer.
+	 * XXX: And this should become a struct kfifo!
+	 *
+	 * buffer points to a buffer allocated on demand, of length
+	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
+	char *buffer;
+	char *head;
+	char *tail;
+
+	int sigio;
+	struct delayed_work task;
+	const struct line_driver *driver;
+	int have_irq;
+};
+
+#define LINE_INIT(str, d) \
+	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
+	  .init_str =	str,	\
+	  .init_pri =	INIT_STATIC, \
+	  .valid =	1, \
+	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
+	  .driver =	d }
+
+extern void line_close(struct tty_struct *tty, struct file * filp);
+extern int line_open(struct line *lines, struct tty_struct *tty);
+extern int line_setup(struct line *lines, unsigned int sizeof_lines,
+		      char *init, char **error_out);
+extern int line_write(struct tty_struct *tty, const unsigned char *buf,
+		      int len);
+extern int line_put_char(struct tty_struct *tty, unsigned char ch);
+extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
+extern int line_chars_in_buffer(struct tty_struct *tty);
+extern void line_flush_buffer(struct tty_struct *tty);
+extern void line_flush_chars(struct tty_struct *tty);
+extern int line_write_room(struct tty_struct *tty);
+extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg);
+extern void line_throttle(struct tty_struct *tty);
+extern void line_unthrottle(struct tty_struct *tty);
+
+extern char *add_xterm_umid(char *base);
+extern int line_setup_irq(int fd, int input, int output, struct line *line,
+			  void *data);
+extern void line_close_chan(struct line *line);
+extern struct tty_driver *register_lines(struct line_driver *line_driver,
+					 const struct tty_operations *driver,
+					 struct line *lines, int nlines);
+extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
+extern void close_lines(struct line *lines, int nlines);
+
+extern int line_config(struct line *lines, unsigned int sizeof_lines,
+		       char *str, const struct chan_opts *opts,
+		       char **error_out);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
+		       char **error_out);
+extern int line_get_config(char *dev, struct line *lines,
+			   unsigned int sizeof_lines, char *str,
+			   int size, char **error_out);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/mconsole.h linux-libre-3.2-gnu1/arch/um/drivers/mconsole.h
--- linux-libre-3.1-gnu1/arch/um/drivers/mconsole.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/mconsole.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_H__
+#define __MCONSOLE_H__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#define u32 uint32_t
+#endif
+
+#include "sysdep/ptrace.h"
+
+#define MCONSOLE_MAGIC (0xcafebabe)
+#define MCONSOLE_MAX_DATA (512)
+#define MCONSOLE_VERSION 2
+
+struct mconsole_request {
+	u32 magic;
+	u32 version;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_reply {
+	u32 err;
+	u32 more;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_notify {
+	u32 magic;
+	u32 version;
+	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
+	       MCONSOLE_USER_NOTIFY } type;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mc_request;
+
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
+struct mconsole_command
+{
+	char *command;
+	void (*handler)(struct mc_request *req);
+	enum mc_context context;
+};
+
+struct mc_request
+{
+	int len;
+	int as_interrupt;
+
+	int originating_fd;
+	unsigned int originlen;
+	unsigned char origin[128];			/* sockaddr_un */
+
+	struct mconsole_request request;
+	struct mconsole_command *cmd;
+	struct uml_pt_regs regs;
+};
+
+extern char mconsole_socket_name[];
+
+extern int mconsole_unlink_socket(void);
+extern int mconsole_reply_len(struct mc_request *req, const char *reply,
+			      int len, int err, int more);
+extern int mconsole_reply(struct mc_request *req, const char *str, int err,
+			  int more);
+
+extern void mconsole_version(struct mc_request *req);
+extern void mconsole_help(struct mc_request *req);
+extern void mconsole_halt(struct mc_request *req);
+extern void mconsole_reboot(struct mc_request *req);
+extern void mconsole_config(struct mc_request *req);
+extern void mconsole_remove(struct mc_request *req);
+extern void mconsole_sysrq(struct mc_request *req);
+extern void mconsole_cad(struct mc_request *req);
+extern void mconsole_stop(struct mc_request *req);
+extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
+extern void mconsole_stack(struct mc_request *req);
+
+extern int mconsole_get_request(int fd, struct mc_request *req);
+extern int mconsole_notify(char *sock_name, int type, const void *data,
+			   int len);
+extern char *mconsole_notify_socket(void);
+extern void lock_notify(void);
+extern void unlock_notify(void);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/mconsole_kern.h linux-libre-3.2-gnu1/arch/um/drivers/mconsole_kern.h
--- linux-libre-3.1-gnu1/arch/um/drivers/mconsole_kern.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/mconsole_kern.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_KERN_H__
+#define __MCONSOLE_KERN_H__
+
+#include "linux/list.h"
+#include "mconsole.h"
+
+struct mconsole_entry {
+	struct list_head list;
+	struct mc_request request;
+};
+
+/* All these methods are called in process context. */
+struct mc_device {
+	struct list_head list;
+	char *name;
+	int (*config)(char *, char **);
+	int (*get_config)(char *, char *, int, char **);
+	int (*id)(char **, int *, int *);
+	int (*remove)(int, char **);
+};
+
+#define CONFIG_CHUNK(str, size, current, chunk, end) \
+do { \
+	current += strlen(chunk); \
+	if(current >= size) \
+		str = NULL; \
+	if(str != NULL){ \
+		strcpy(str, chunk); \
+		str += strlen(chunk); \
+	} \
+	if(end) \
+		current++; \
+} while(0)
+
+#ifdef CONFIG_MCONSOLE
+
+extern void mconsole_register_dev(struct mc_device *new);
+
+#else
+
+static inline void mconsole_register_dev(struct mc_device *new)
+{
+}
+
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/mconsole_user.c linux-libre-3.2-gnu1/arch/um/drivers/mconsole_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/mconsole_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/mconsole_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "mconsole.h"
-#include "user.h"
 
 static struct mconsole_command commands[] = {
 	/*
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/net_kern.c linux-libre-3.2-gnu1/arch/um/drivers/net_kern.c
--- linux-libre-3.1-gnu1/arch/um/drivers/net_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/net_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -368,7 +368,7 @@ static const struct net_device_ops uml_n
 	.ndo_open 		= uml_net_open,
 	.ndo_stop 		= uml_net_close,
 	.ndo_start_xmit 	= uml_net_start_xmit,
-	.ndo_set_multicast_list = uml_net_set_multicast_list,
+	.ndo_set_rx_mode	= uml_net_set_multicast_list,
 	.ndo_tx_timeout 	= uml_net_tx_timeout,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu 	= uml_net_change_mtu,
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/net_user.c linux-libre-3.2-gnu1/arch/um/drivers/net_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/net_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/net_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "net_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 int tap_open_common(void *dev, char *gate_addr)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/pcap_user.c linux-libre-3.2-gnu1/arch/um/drivers/pcap_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/pcap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/pcap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,7 @@
 #include <asm/types.h>
 #include "net_user.h"
 #include "pcap_user.h"
-#include "kern_constants.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define PCAP_FD(p) (*(int *)(p))
 
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/port_user.c linux-libre-3.2-gnu1/arch/um/drivers/port_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/port_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/port_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #include <unistd.h>
 #include <netinet/in.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "port.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct port_chan {
 	int raw;
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/pty.c linux-libre-3.2-gnu1/arch/um/drivers/pty.c
--- linux-libre-3.1-gnu1/arch/um/drivers/pty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/pty.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include <termios.h>
 #include <sys/stat.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/slip_user.c linux-libre-3.2-gnu1/arch/um/drivers/slip_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/slip_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/slip_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,12 +11,10 @@
 #include <string.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slip.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static int slip_user_init(void *data, void *dev)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/slirp_user.c linux-libre-3.2-gnu1/arch/um/drivers/slirp_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/slirp_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/slirp_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,11 +7,9 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slirp.h"
-#include "user.h"
 
 static int slirp_user_init(void *data, void *dev)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/ssl.c linux-libre-3.2-gnu1/arch/um/drivers/ssl.c
--- linux-libre-3.1-gnu1/arch/um/drivers/ssl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/ssl.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
-#include "line.h"
 #include "ssl.h"
-#include "chan_kern.h"
-#include "kern.h"
+#include "chan.h"
 #include "init.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/stdio_console.c linux-libre-3.2-gnu1/arch/um/drivers/stdio_console.c
--- linux-libre-3.1-gnu1/arch/um/drivers/stdio_console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/stdio_console.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,7 @@
 #include "asm/current.h"
 #include "asm/irq.h"
 #include "stdio_console.h"
-#include "line.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
 #include "init.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/tty.c linux-libre-3.2-gnu1/arch/um/drivers/tty.c
--- linux-libre-3.1-gnu1/arch/um/drivers/tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,8 @@
 #include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct tty_chan {
 	char *dev;
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/ubd_kern.c linux-libre-3.2-gnu1/arch/um/drivers/ubd_kern.c
--- linux-libre-3.1-gnu1/arch/um/drivers/ubd_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/ubd_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,7 +46,6 @@
 #include "asm/tlbflush.h"
 #include "mem_user.h"
 #include "kern_util.h"
-#include "kern.h"
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
@@ -54,7 +53,6 @@
 #include "ubd_user.h"
 #include "os.h"
 #include "mem.h"
-#include "mem_kern.h"
 #include "cow.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
@@ -513,8 +511,37 @@ __uml_exitcall(kill_io_thread);
 static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
 {
 	char *file;
+	int fd;
+	int err;
 
-	file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
+	__u32 version;
+	__u32 align;
+	char *backing_file;
+	time_t mtime;
+	unsigned long long size;
+	int sector_size;
+	int bitmap_offset;
+
+	if (ubd_dev->file && ubd_dev->cow.file) {
+		file = ubd_dev->cow.file;
+
+		goto out;
+	}
+
+	fd = os_open_file(ubd_dev->file, global_openflags, 0);
+	if (fd < 0)
+		return fd;
+
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, \
+		&mtime, &size, &sector_size, &align, &bitmap_offset);
+	os_close_file(fd);
+
+	if(err == -EINVAL)
+		file = ubd_dev->file;
+	else
+		file = backing_file;
+
+out:
 	return os_file_size(file, size_out);
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/ubd_user.c linux-libre-3.2-gnu1/arch/um/drivers/ubd_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/ubd_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/ubd_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
-#include "user.h"
 #include "ubd_user.h"
 #include "os.h"
 #include "cow.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/ubd_user.h linux-libre-3.2-gnu1/arch/um/drivers/ubd_user.h
--- linux-libre-3.1-gnu1/arch/um/drivers/ubd_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/drivers/ubd_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+/* 
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_UBD_USER_H
+#define __UM_UBD_USER_H
+
+extern void ignore_sigwinch_sig(void);
+extern int start_io_thread(unsigned long sp, int *fds_out);
+extern int io_thread(void *arg);
+extern int kernel_fd;
+
+#endif
+
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/umcast_user.c linux-libre-3.2-gnu1/arch/um/drivers/umcast_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/umcast_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/umcast_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <netinet/in.h>
-#include "kern_constants.h"
 #include "umcast.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static struct sockaddr_in *new_addr(char *addr, unsigned short port)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/vde_user.c linux-libre-3.2-gnu1/arch/um/drivers/vde_user.c
--- linux-libre-3.1-gnu1/arch/um/drivers/vde_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/vde_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,10 +6,8 @@
 #include <stddef.h>
 #include <errno.h>
 #include <libvdeplug.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "vde.h"
 
 static int vde_user_init(void *data, void *dev)
diff -druNp linux-libre-3.1-gnu1/arch/um/drivers/xterm.c linux-libre-3.2-gnu1/arch/um/drivers/xterm.c
--- linux-libre-3.1-gnu1/arch/um/drivers/xterm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/drivers/xterm.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <string.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "xterm.h"
 
 struct xterm_chan {
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/apic.h linux-libre-3.2-gnu1/arch/um/include/asm/apic.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/apic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/apic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef __UM_APIC_H
-#define __UM_APIC_H
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/arch_hweight.h linux-libre-3.2-gnu1/arch/um/include/asm/arch_hweight.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/arch_hweight.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/arch_hweight.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_HWEIGHT_H
-#define _ASM_UM_HWEIGHT_H
-
-#include <asm-generic/bitops/arch_hweight.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/bug.h linux-libre-3.2-gnu1/arch/um/include/asm/bug.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/bug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/bug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_BUG_H
-#define __UM_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/checksum.h linux-libre-3.2-gnu1/arch/um/include/asm/checksum.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_CHECKSUM_H
-#define __UM_CHECKSUM_H
-
-#include "sysdep/checksum.h"
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/cputime.h linux-libre-3.2-gnu1/arch/um/include/asm/cputime.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/cputime.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_CPUTIME_H
-#define __UM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __UM_CPUTIME_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/desc.h linux-libre-3.2-gnu1/arch/um/include/asm/desc.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-#ifndef __UM_DESC_H
-#define __UM_DESC_H
-
-/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
- * compile, and has never been used. */
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/device.h linux-libre-3.2-gnu1/arch/um/include/asm/device.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/device.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/emergency-restart.h linux-libre-3.2-gnu1/arch/um/include/asm/emergency-restart.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/emergency-restart.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/emergency-restart.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/ftrace.h linux-libre-3.2-gnu1/arch/um/include/asm/ftrace.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/ftrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/ftrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-/* empty */
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/futex.h linux-libre-3.2-gnu1/arch/um/include/asm/futex.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/futex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/futex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/hardirq.h linux-libre-3.2-gnu1/arch/um/include/asm/hardirq.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/hardirq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/hardirq.h>
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/hw_irq.h linux-libre-3.2-gnu1/arch/um/include/asm/hw_irq.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/hw_irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/hw_irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _ASM_UM_HW_IRQ_H
-#define _ASM_UM_HW_IRQ_H
-
-#include "asm/irq.h"
-#include "asm/archparam.h"
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/irqflags.h linux-libre-3.2-gnu1/arch/um/include/asm/irqflags.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/irqflags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/irqflags.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,42 @@
 #ifndef __UM_IRQFLAGS_H
 #define __UM_IRQFLAGS_H
 
-/* Empty for now */
+extern int get_signals(void);
+extern int set_signals(int enable);
+extern void block_signals(void);
+extern void unblock_signals(void);
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return get_signals();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	set_signals(flags);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	unblock_signals();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	block_signals();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_local_save_flags() == 0;
+}
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/irq_regs.h linux-libre-3.2-gnu1/arch/um/include/asm/irq_regs.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/irq_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/irq_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/irq_vectors.h linux-libre-3.2-gnu1/arch/um/include/asm/irq_vectors.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/irq_vectors.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/irq_vectors.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_IRQ_VECTORS_H
-#define __UM_IRQ_VECTORS_H
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/Kbuild linux-libre-3.2-gnu1/arch/um/include/asm/Kbuild
--- linux-libre-3.1-gnu1/arch/um/include/asm/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3 @@
+generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
+generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
+generic-y += ftrace.h
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/kdebug.h linux-libre-3.2-gnu1/arch/um/include/asm/kdebug.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/kdebug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/kdebug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/mmu_context.h linux-libre-3.2-gnu1/arch/um/include/asm/mmu_context.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/mmu_context.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/mmu_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,15 +6,12 @@
 #ifndef __UM_MMU_CONTEXT_H
 #define __UM_MMU_CONTEXT_H
 
-#include "linux/sched.h"
-#include "um_mmu.h"
+#include <linux/sched.h>
+#include <asm/mmu.h>
 
 extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
 extern void arch_exit_mmap(struct mm_struct *mm);
 
-#define get_mmu_context(task) do ; while(0)
-#define activate_context(tsk) do ; while(0)
-
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 extern void force_flush_all(void);
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/mmu.h linux-libre-3.2-gnu1/arch/um/include/asm/mmu.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,12 +1,24 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#ifndef __MMU_H
-#define __MMU_H
+#ifndef __ARCH_UM_MMU_H
+#define __ARCH_UM_MMU_H
 
-#include "um_mmu.h"
+#include "mm_id.h"
+#include <asm/mm_context.h>
 
-#endif
+typedef struct mm_context {
+	struct mm_id id;
+	struct uml_arch_mm_context arch;
+	struct page **stub_pages;
+} mm_context_t;
+
+extern void __switch_mm(struct mm_id * mm_idp);
 
+/* Avoid tangled inclusion with asm/ldt.h */
+extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+extern void free_ldt(struct mm_context *mm);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/page.h linux-libre-3.2-gnu1/arch/um/include/asm/page.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 struct page;
 
 #include <linux/types.h>
-#include <sysdep/vm-flags.h>
+#include <asm/vm-flags.h>
 
 /*
  * These are used to make use of C type-checking..
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/page_offset.h linux-libre-3.2-gnu1/arch/um/include/asm/page_offset.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/page_offset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/page_offset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#define PAGE_OFFSET_RAW (uml_physmem)
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/pda.h linux-libre-3.2-gnu1/arch/um/include/asm/pda.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/pda.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/pda.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PDA_X86_64_H
-#define __UM_PDA_X86_64_H
-
-/* XXX */
-struct foo {
-	unsigned int __softirq_pending;
-	unsigned int __nmi_count;
-};
-
-extern struct foo me;
-
-#define read_pda(me) (&me)
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/percpu.h linux-libre-3.2-gnu1/arch/um/include/asm/percpu.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/percpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/percpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_PERCPU_H
-#define __UM_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __UM_PERCPU_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/ptrace-generic.h linux-libre-3.2-gnu1/arch/um/include/asm/ptrace-generic.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/ptrace-generic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/ptrace-generic.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,10 @@ struct pt_regs {
 #define PT_REGS_IP(r) UPT_IP(&(r)->regs)
 #define PT_REGS_SP(r) UPT_SP(&(r)->regs)
 
-#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg)
-#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val)
-
-#define PT_REGS_SET_SYSCALL_RETURN(r, res) \
-	UPT_SET_SYSCALL_RETURN(&(r)->regs, res)
 #define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)
 
 #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
 
-#define PT_REGS_SC(r) UPT_SC(&(r)->regs)
-
 #define instruction_pointer(regs) PT_REGS_IP(regs)
 
 struct task_struct;
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/required-features.h linux-libre-3.2-gnu1/arch/um/include/asm/required-features.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/required-features.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/required-features.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __UM_REQUIRED_FEATURES_H
-#define __UM_REQUIRED_FEATURES_H
-
-/*
- * Nothing to see, just need something for the i386 and x86_64 asm
- * headers to include.
- */
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/sections.h linux-libre-3.2-gnu1/arch/um/include/asm/sections.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/sections.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _UM_SECTIONS_H
-#define _UM_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/segment.h linux-libre-3.2-gnu1/arch/um/include/asm/segment.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/segment.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/segment.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#ifndef __UM_SEGMENT_H
-#define __UM_SEGMENT_H
-
-extern int host_gdt_entry_tls_min;
-
-#define GDT_ENTRY_TLS_ENTRIES 3
-#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
-#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/system.h linux-libre-3.2-gnu1/arch/um/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-#ifndef __UM_SYSTEM_GENERIC_H
-#define __UM_SYSTEM_GENERIC_H
-
-#include "sysdep/system.h"
-
-extern int get_signals(void);
-extern int set_signals(int enable);
-extern void block_signals(void);
-extern void unblock_signals(void);
-
-static inline unsigned long arch_local_save_flags(void)
-{
-	return get_signals();
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-	set_signals(flags);
-}
-
-static inline void arch_local_irq_enable(void)
-{
-	unblock_signals();
-}
-
-static inline void arch_local_irq_disable(void)
-{
-	block_signals();
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
-	unsigned long flags;
-	flags = arch_local_save_flags();
-	arch_local_irq_disable();
-	return flags;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
-	return arch_local_save_flags() == 0;
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/topology.h linux-libre-3.2-gnu1/arch/um/include/asm/topology.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/topology.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_TOPOLOGY_H
-#define _ASM_UM_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/uaccess.h linux-libre-3.2-gnu1/arch/um/include/asm/uaccess.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,15 +6,15 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
-#include <asm/errno.h>
-#include <asm/processor.h>
-
 /* thread_info has a mm_segment_t in it, so put the definition up here */
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#include "linux/thread_info.h"
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <asm/elf.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -38,7 +38,86 @@ typedef struct {
 
 #define segment_eq(a, b) ((a).seg == (b).seg)
 
-#include "um_uaccess.h"
+#define __under_task_size(addr, size) \
+	(((unsigned long) (addr) < TASK_SIZE) && \
+	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define __access_ok_vsyscall(type, addr, size) \
+	 ((type == VERIFY_READ) && \
+	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
+	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
+	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
+
+#define __addr_range_nowrap(addr, size) \
+	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
+
+#define access_ok(type, addr, size) \
+	(__addr_range_nowrap(addr, size) && \
+	 (__under_task_size(addr, size) || \
+	  __access_ok_vsyscall(type, addr, size) || \
+	  segment_eq(get_fs(), KERNEL_DS)))
+
+extern int copy_from_user(void *to, const void __user *from, int n);
+extern int copy_to_user(void __user *to, const void *from, int n);
+
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
+extern int strncpy_from_user(char *dst, const char __user *src, int count);
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int __clear_user(void __user *mem, int len);
+
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int clear_user(void __user *mem, int len);
+
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+extern int strnlen_user(const void __user *str, int len);
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 
diff -druNp linux-libre-3.1-gnu1/arch/um/include/asm/xor.h linux-libre-3.2-gnu1/arch/um/include/asm/xor.h
--- linux-libre-3.1-gnu1/arch/um/include/asm/xor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/asm/xor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_XOR_H
-#define __UM_XOR_H
-
-#include "asm-generic/xor.h"
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/as-layout.h linux-libre-3.2-gnu1/arch/um/include/shared/as-layout.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/as-layout.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/as-layout.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __START_H__
 #define __START_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * Stolen from linux/const.h, which can't be directly included since
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/chan_kern.h linux-libre-3.2-gnu1/arch/um/include/shared/chan_kern.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/chan_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/chan_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_KERN_H__
-#define __CHAN_KERN_H__
-
-#include "linux/tty.h"
-#include "linux/list.h"
-#include "linux/console.h"
-#include "chan_user.h"
-#include "line.h"
-
-struct chan {
-	struct list_head list;
-	struct list_head free_list;
-	struct line *line;
-	char *dev;
-	unsigned int primary:1;
-	unsigned int input:1;
-	unsigned int output:1;
-	unsigned int opened:1;
-	unsigned int enabled:1;
-	int fd;
-	const struct chan_ops *ops;
-	void *data;
-};
-
-extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
-			   struct tty_struct *tty, int irq);
-extern int parse_chan_pair(char *str, struct line *line, int device,
-			   const struct chan_opts *opts, char **error_out);
-extern int write_chan(struct list_head *chans, const char *buf, int len,
-			     int write_irq);
-extern int console_write_chan(struct list_head *chans, const char *buf, 
-			      int len);
-extern int console_open_chan(struct line *line, struct console *co);
-extern void deactivate_chan(struct list_head *chans, int irq);
-extern void reactivate_chan(struct list_head *chans, int irq);
-extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern int enable_chan(struct line *line);
-extern void close_chan(struct list_head *chans, int delay_free_irq);
-extern int chan_window_size(struct list_head *chans, 
-			     unsigned short *rows_out, 
-			     unsigned short *cols_out);
-extern int chan_config_string(struct list_head *chans, char *str, int size,
-			      char **error_out);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/chan_user.h linux-libre-3.2-gnu1/arch/um/include/shared/chan_user.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/chan_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/chan_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_USER_H__
-#define __CHAN_USER_H__
-
-#include "init.h"
-
-struct chan_opts {
-	void (*const announce)(char *dev_name, int dev);
-	char *xterm_title;
-	const int raw;
-};
-
-enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
-
-struct chan_ops {
-	char *type;
-	void *(*init)(char *, int, const struct chan_opts *);
-	int (*open)(int, int, int, void *, char **);
-	void (*close)(int, void *);
-	int (*read)(int, char *, void *);
-	int (*write)(int, const char *, int, void *);
-	int (*console_write)(int, const char *, int);
-	int (*window_size)(int, void *, unsigned short *, unsigned short *);
-	void (*free)(void *);
-	int winch;
-};
-
-extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
-	tty_ops, xterm_ops;
-
-extern void generic_close(int fd, void *unused);
-extern int generic_read(int fd, char *c_out, void *unused);
-extern int generic_write(int fd, const char *buf, int n, void *unused);
-extern int generic_console_write(int fd, const char *buf, int n);
-extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			       unsigned short *cols_out);
-extern void generic_free(void *data);
-
-struct tty_struct;
-extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid,
-			       struct tty_struct *tty, unsigned long stack);
-
-#define __channel_help(fn, prefix) \
-__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
-"    Attach a console or serial line to a host channel.  See\n" \
-"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
-"    description of this switch.\n\n" \
-);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/common-offsets.h linux-libre-3.2-gnu1/arch/um/include/shared/common-offsets.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/common-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/common-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 
 DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 
-OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 OFFSET(HOST_TASK_PID, task_struct, pid);
 
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/initrd.h linux-libre-3.2-gnu1/arch/um/include/shared/initrd.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/initrd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/initrd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __INITRD_USER_H__
-#define __INITRD_USER_H__
-
-extern int load_initrd(char *filename, void *buf, int size);
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/kern.h linux-libre-3.2-gnu1/arch/um/include/shared/kern.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/kern.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,28 +13,10 @@
  * includes.
  */
 
-extern int errno;
-
-extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
-extern int sleep(int);
 extern int printf(const char *fmt, ...);
-extern char *strerror(int errnum);
-extern char *ptsname(int __fd);
-extern int munmap(void *, int);
 extern void *sbrk(int increment);
-extern void *malloc(int size);
-extern void perror(char *err);
-extern int kill(int pid, int sig);
-extern int getuid(void);
-extern int getgid(void);
 extern int pause(void);
-extern int write(int, const void *, int);
 extern void exit(int);
-extern int close(int);
-extern int read(unsigned int, char *, int);
-extern int pipe(int *);
-extern int sched_yield(void);
-extern int ptrace(int op, int pid, long addr, long data);
 
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/kern_util.h linux-libre-3.2-gnu1/arch/um/include/shared/kern_util.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/kern_util.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/kern_util.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@ extern unsigned long alloc_stack(int ord
 extern void free_stack(unsigned long stack, int order);
 
 extern int do_signal(void);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
 extern void interrupt_end(void);
 extern void relay_signal(int sig, struct uml_pt_regs *regs);
 
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/ldt.h linux-libre-3.2-gnu1/arch/um/include/shared/ldt.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_H
-#define __ASM_LDT_H
-
-#include <linux/mutex.h>
-#include <sysdep/host_ldt.h>
-
-extern void ldt_host_info(void);
-
-#define LDT_PAGES_MAX \
-	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
-	(PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
-	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
-	__u32 a;
-	__u32 b;
-};
-
-typedef struct uml_ldt {
-	int entry_count;
-	struct mutex lock;
-	union {
-		struct ldt_entry * pages[LDT_PAGES_MAX];
-		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
-	} u;
-} uml_ldt_t;
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/line.h linux-libre-3.2-gnu1/arch/um/include/shared/line.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/line.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/line.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __LINE_H__
-#define __LINE_H__
-
-#include "linux/list.h"
-#include "linux/workqueue.h"
-#include "linux/tty.h"
-#include "linux/interrupt.h"
-#include "linux/spinlock.h"
-#include "linux/mutex.h"
-#include "chan_user.h"
-#include "mconsole_kern.h"
-
-/* There's only one modifiable field in this - .mc.list */
-struct line_driver {
-	const char *name;
-	const char *device_name;
-	const short major;
-	const short minor_start;
-	const short type;
-	const short subtype;
-	const int read_irq;
-	const char *read_irq_name;
-	const int write_irq;
-	const char *write_irq_name;
-	struct mc_device mc;
-};
-
-struct line {
-	struct tty_struct *tty;
-	spinlock_t count_lock;
-	unsigned long count;
-	int valid;
-
-	char *init_str;
-	int init_pri;
-	struct list_head chan_list;
-
-	/*This lock is actually, mostly, local to*/
-	spinlock_t lock;
-	int throttled;
-	/* Yes, this is a real circular buffer.
-	 * XXX: And this should become a struct kfifo!
-	 *
-	 * buffer points to a buffer allocated on demand, of length
-	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
-	char *buffer;
-	char *head;
-	char *tail;
-
-	int sigio;
-	struct delayed_work task;
-	const struct line_driver *driver;
-	int have_irq;
-};
-
-#define LINE_INIT(str, d) \
-	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
-	  .init_str =	str,	\
-	  .init_pri =	INIT_STATIC, \
-	  .valid =	1, \
-	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
-	  .driver =	d }
-
-extern void line_close(struct tty_struct *tty, struct file * filp);
-extern int line_open(struct line *lines, struct tty_struct *tty);
-extern int line_setup(struct line *lines, unsigned int sizeof_lines,
-		      char *init, char **error_out);
-extern int line_write(struct tty_struct *tty, const unsigned char *buf,
-		      int len);
-extern int line_put_char(struct tty_struct *tty, unsigned char ch);
-extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
-extern int line_chars_in_buffer(struct tty_struct *tty);
-extern void line_flush_buffer(struct tty_struct *tty);
-extern void line_flush_chars(struct tty_struct *tty);
-extern int line_write_room(struct tty_struct *tty);
-extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
-				unsigned long arg);
-extern void line_throttle(struct tty_struct *tty);
-extern void line_unthrottle(struct tty_struct *tty);
-
-extern char *add_xterm_umid(char *base);
-extern int line_setup_irq(int fd, int input, int output, struct line *line,
-			  void *data);
-extern void line_close_chan(struct line *line);
-extern struct tty_driver *register_lines(struct line_driver *line_driver,
-					 const struct tty_operations *driver,
-					 struct line *lines, int nlines);
-extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
-extern void close_lines(struct line *lines, int nlines);
-
-extern int line_config(struct line *lines, unsigned int sizeof_lines,
-		       char *str, const struct chan_opts *opts,
-		       char **error_out);
-extern int line_id(char **str, int *start_out, int *end_out);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
-		       char **error_out);
-extern int line_get_config(char *dev, struct line *lines,
-			   unsigned int sizeof_lines, char *str,
-			   int size, char **error_out);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/mconsole.h linux-libre-3.2-gnu1/arch/um/include/shared/mconsole.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/mconsole.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/mconsole.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_H__
-#define __MCONSOLE_H__
-
-#ifndef __KERNEL__
-#include <stdint.h>
-#define u32 uint32_t
-#endif
-
-#include "sysdep/ptrace.h"
-
-#define MCONSOLE_MAGIC (0xcafebabe)
-#define MCONSOLE_MAX_DATA (512)
-#define MCONSOLE_VERSION 2
-
-struct mconsole_request {
-	u32 magic;
-	u32 version;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_reply {
-	u32 err;
-	u32 more;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_notify {
-	u32 magic;
-	u32 version;
-	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
-	       MCONSOLE_USER_NOTIFY } type;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mc_request;
-
-enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
-
-struct mconsole_command
-{
-	char *command;
-	void (*handler)(struct mc_request *req);
-	enum mc_context context;
-};
-
-struct mc_request
-{
-	int len;
-	int as_interrupt;
-
-	int originating_fd;
-	unsigned int originlen;
-	unsigned char origin[128];			/* sockaddr_un */
-
-	struct mconsole_request request;
-	struct mconsole_command *cmd;
-	struct uml_pt_regs regs;
-};
-
-extern char mconsole_socket_name[];
-
-extern int mconsole_unlink_socket(void);
-extern int mconsole_reply_len(struct mc_request *req, const char *reply,
-			      int len, int err, int more);
-extern int mconsole_reply(struct mc_request *req, const char *str, int err,
-			  int more);
-
-extern void mconsole_version(struct mc_request *req);
-extern void mconsole_help(struct mc_request *req);
-extern void mconsole_halt(struct mc_request *req);
-extern void mconsole_reboot(struct mc_request *req);
-extern void mconsole_config(struct mc_request *req);
-extern void mconsole_remove(struct mc_request *req);
-extern void mconsole_sysrq(struct mc_request *req);
-extern void mconsole_cad(struct mc_request *req);
-extern void mconsole_stop(struct mc_request *req);
-extern void mconsole_go(struct mc_request *req);
-extern void mconsole_log(struct mc_request *req);
-extern void mconsole_proc(struct mc_request *req);
-extern void mconsole_stack(struct mc_request *req);
-
-extern int mconsole_get_request(int fd, struct mc_request *req);
-extern int mconsole_notify(char *sock_name, int type, const void *data,
-			   int len);
-extern char *mconsole_notify_socket(void);
-extern void lock_notify(void);
-extern void unlock_notify(void);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/mconsole_kern.h linux-libre-3.2-gnu1/arch/um/include/shared/mconsole_kern.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/mconsole_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/mconsole_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_KERN_H__
-#define __MCONSOLE_KERN_H__
-
-#include "linux/list.h"
-#include "mconsole.h"
-
-struct mconsole_entry {
-	struct list_head list;
-	struct mc_request request;
-};
-
-/* All these methods are called in process context. */
-struct mc_device {
-	struct list_head list;
-	char *name;
-	int (*config)(char *, char **);
-	int (*get_config)(char *, char *, int, char **);
-	int (*id)(char **, int *, int *);
-	int (*remove)(int, char **);
-};
-
-#define CONFIG_CHUNK(str, size, current, chunk, end) \
-do { \
-	current += strlen(chunk); \
-	if(current >= size) \
-		str = NULL; \
-	if(str != NULL){ \
-		strcpy(str, chunk); \
-		str += strlen(chunk); \
-	} \
-	if(end) \
-		current++; \
-} while(0)
-
-#ifdef CONFIG_MCONSOLE
-
-extern void mconsole_register_dev(struct mc_device *new);
-
-#else
-
-static inline void mconsole_register_dev(struct mc_device *new)
-{
-}
-
-#endif
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/mem_kern.h linux-libre-3.2-gnu1/arch/um/include/shared/mem_kern.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/mem_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/mem_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __MEM_KERN_H__
-#define __MEM_KERN_H__
-
-#include "linux/list.h"
-#include "linux/types.h"
-
-struct remapper {
-	struct list_head list;
-	int (*proc)(int, unsigned long, int, __u64);
-};
-
-extern void register_remapper(struct remapper *info);
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/os.h linux-libre-3.2-gnu1/arch/um/include/shared/os.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/os.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/os.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
 #include "irq_user.h"
 #include "longjmp.h"
 #include "mm_id.h"
-#include "sysdep/tls.h"
 
 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
 
@@ -203,12 +202,6 @@ extern int os_drop_memory(void *addr, in
 extern int can_drop_memory(void);
 extern void os_flush_stdout(void);
 
-/* uaccess.c */
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
-				    void **fault_addr, jmp_buf **fault_catcher,
-				    void (*op)(void *to, const void *from,
-					       int n), int *faulted_out);
-
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
 /* helper.c */
@@ -218,10 +211,6 @@ extern int run_helper_thread(int (*proc)
 extern int helper_wait(int pid);
 
 
-/* tls.c */
-extern int os_set_thread_area(user_desc_t *info, int pid);
-extern int os_get_thread_area(user_desc_t *info, int pid);
-
 /* umid.c */
 extern int umid_file_name(char *name, char *buf, int len);
 extern int set_umid(char *name);
@@ -231,7 +220,7 @@ extern char *get_umid(void);
 extern void timer_init(void);
 extern void set_sigstack(void *sig_stack, int size);
 extern void remove_sigstack(void);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern void set_handler(int sig);
 extern int change_sig(int signal, int on);
 extern void block_signals(void);
 extern void unblock_signals(void);
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/process.h linux-libre-3.2-gnu1/arch/um/include/shared/process.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/process.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/process.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __PROCESS_H__
-#define __PROCESS_H__
-
-#include <signal.h>
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-extern void sig_handler(int sig, struct sigcontext *sc);
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/ptrace_user.h linux-libre-3.2-gnu1/arch/um/include/shared/ptrace_user.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/ptrace_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,8 @@
 #ifndef __PTRACE_USER_H__
 #define __PTRACE_USER_H__
 
-#include "sysdep/ptrace_user.h"
+#include <sys/ptrace.h>
+#include <sysdep/ptrace_user.h>
 
 extern int ptrace_getregs(long pid, unsigned long *regs_out);
 extern int ptrace_setregs(long pid, unsigned long *regs_in);
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/skas_ptregs.h linux-libre-3.2-gnu1/arch/um/include/shared/skas_ptregs.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/skas_ptregs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/skas_ptregs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __SKAS_PT_REGS_
-#define __SKAS_PT_REGS_
-
-#include <user_constants.h>
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/syscall.h linux-libre-3.2-gnu1/arch/um/include/shared/syscall.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/syscall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/syscall.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSCALL_USER_H
-#define __SYSCALL_USER_H
-
-extern int record_syscall_start(int syscall);
-extern void record_syscall_end(int index, long result);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/task.h linux-libre-3.2-gnu1/arch/um/include/shared/task.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/task.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/task.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __TASK_H
-#define __TASK_H
-
-#include <kern_constants.h>
-
-#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
-#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/tlb.h linux-libre-3.2-gnu1/arch/um/include/shared/tlb.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/tlb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/tlb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TLB_H__
-#define __TLB_H__
-
-#include "um_mmu.h"
-
-extern void force_flush_all(void);
-extern int flush_tlb_kernel_range_common(unsigned long start,
-					 unsigned long end);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/ubd_user.h linux-libre-3.2-gnu1/arch/um/include/shared/ubd_user.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/ubd_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/ubd_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_UBD_USER_H
-#define __UM_UBD_USER_H
-
-extern void ignore_sigwinch_sig(void);
-extern int start_io_thread(unsigned long sp, int *fds_out);
-extern int io_thread(void *arg);
-extern int kernel_fd;
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/um_malloc.h linux-libre-3.2-gnu1/arch/um/include/shared/um_malloc.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/um_malloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/um_malloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __UM_MALLOC_H__
 #define __UM_MALLOC_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 extern void *uml_kmalloc(int size, int flags);
 extern void kfree(const void *ptr);
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/um_mmu.h linux-libre-3.2-gnu1/arch/um/include/shared/um_mmu.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/um_mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/um_mmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_MMU_H
-#define __ARCH_UM_MMU_H
-
-#include "mm_id.h"
-#include "ldt.h"
-
-typedef struct mm_context {
-	struct mm_id id;
-	struct uml_ldt ldt;
-	struct page **stub_pages;
-} mm_context_t;
-
-extern void __switch_mm(struct mm_id * mm_idp);
-
-/* Avoid tangled inclusion with asm/ldt.h */
-extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
-extern void free_ldt(struct mm_context *mm);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/um_uaccess.h linux-libre-3.2-gnu1/arch/um/include/shared/um_uaccess.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/um_uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/um_uaccess.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_UACCESS_H
-#define __ARCH_UM_UACCESS_H
-
-#include <asm/elf.h>
-#include <asm/fixmap.h>
-#include "sysdep/archsetjmp.h"
-
-#define __under_task_size(addr, size) \
-	(((unsigned long) (addr) < TASK_SIZE) && \
-	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
-
-#define __access_ok_vsyscall(type, addr, size) \
-	 ((type == VERIFY_READ) && \
-	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
-	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
-	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
-
-#define __addr_range_nowrap(addr, size) \
-	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
-
-#define access_ok(type, addr, size) \
-	(__addr_range_nowrap(addr, size) && \
-	 (__under_task_size(addr, size) || \
-	  __access_ok_vsyscall(type, addr, size) || \
-	  segment_eq(get_fs(), KERNEL_DS)))
-
-extern int copy_from_user(void *to, const void __user *from, int n);
-extern int copy_to_user(void __user *to, const void *from, int n);
-
-extern int __do_copy_to_user(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher);
-
-/*
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-
-extern int strncpy_from_user(char *dst, const char __user *src, int count);
-
-/*
- * __clear_user: - Zero a block of memory in user space, with less checking.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int __clear_user(void __user *mem, int len);
-
-/*
- * clear_user: - Zero a block of memory in user space.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int clear_user(void __user *mem, int len);
-
-/*
- * strlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- * @n:   The maximum valid length
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-extern int strnlen_user(const void __user *str, int len);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/include/shared/user.h linux-libre-3.2-gnu1/arch/um/include/shared/user.h
--- linux-libre-3.1-gnu1/arch/um/include/shared/user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/include/shared/user.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __USER_H__
 #define __USER_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * The usual definition - copied here because the kernel provides its own,
@@ -36,10 +36,11 @@ static inline int printk(const char *fmt
 }
 #endif
 
-extern void schedule(void);
 extern int in_aton(char *str);
-extern int open_gdb_chan(void);
 extern size_t strlcpy(char *, const char *, size_t);
 extern size_t strlcat(char *, const char *, size_t);
 
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/um/Kconfig.char linux-libre-3.2-gnu1/arch/um/Kconfig.char
--- linux-libre-3.1-gnu1/arch/um/Kconfig.char	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Kconfig.char	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
-
-menu "Character Devices"
+menu "UML Character Devices"
 
 config STDERR_CONSOLE
 	bool "stderr console"
@@ -105,92 +104,6 @@ config SSL_CHAN
           this if you expect the UML that you build to be run in environments
           which don't have a set of /dev/pty* devices.
 
-config UNIX98_PTYS
-	bool "Unix98 PTY support"
-	help
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  All modern Linux systems use the Unix98 ptys.  Say Y unless
-	  you're on an embedded system and want to conserve memory.
-
-config LEGACY_PTYS
-	bool "Legacy (BSD) PTY support"
-	default y
-	help
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx
-	  for masters and /dev/ttyxx for slaves of pseudo
-	  terminals. This scheme has a number of problems, including
-	  security.  This option enables these legacy devices; on most
-	  systems, it is safe to say N.
-
-config RAW_DRIVER
-        tristate "RAW driver (/dev/raw/rawN)"
-	depends on BLOCK
-        help
-          The raw driver permits block devices to be bound to /dev/raw/rawN.
-          Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
-          See the raw(8) manpage for more details.
-
-          Applications should preferably open the device (eg /dev/hda1)
-          with the O_DIRECT flag.
-
-config MAX_RAW_DEVS
-        int "Maximum number of RAW devices to support (1-8192)"
-        depends on RAW_DRIVER
-        default "256"
-        help
-          The maximum number of RAW devices that are supported.
-          Default is 256. Increase this number in case you need lots of
-          raw devices.
-
-config LEGACY_PTY_COUNT
-	int "Maximum number of legacy PTY in use"
-	depends on LEGACY_PTYS
-	default "256"
-	help
-	  The maximum number of legacy PTYs that can be used at any one time.
-	  The default is 256, and should be more than enough.  Embedded
-	  systems may want to reduce this to save memory.
-
-	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
-	  architectures and 24 bytes on 64-bit architectures.
-
-config WATCHDOG
-	bool "Watchdog Timer Support"
-
-config WATCHDOG_NOWAYOUT
-	bool "Disable watchdog shutdown on close"
-	depends on WATCHDOG
-
-config SOFT_WATCHDOG
-	tristate "Software Watchdog"
-	depends on WATCHDOG
-
-config UML_WATCHDOG
-	tristate "UML watchdog"
-	depends on WATCHDOG
-
 config UML_SOUND
 	tristate "Sound support"
 	help
@@ -211,29 +124,4 @@ config HOSTAUDIO
 	tristate
 	default UML_SOUND
 
-#It is selected elsewhere, so kconfig would warn without this.
-config HW_RANDOM
-	tristate
-	default n
-
-config UML_RANDOM
-	tristate "Hardware random number generator"
-	help
-	  This option enables UML's "hardware" random number generator.  It
-	  attaches itself to the host's /dev/random, supplying as much entropy
-	  as the host has, rather than the small amount the UML gets from its
-	  own drivers.  It registers itself as a standard hardware random number
-	  generator, major 10, minor 183, and the canonical device name is
-	  /dev/hwrng.
-	  The way to make use of this is to install the rng-tools package
-	  (check your distro, or download from
-	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
-	  /dev/hwrng and injects the entropy into /dev/random.
-
-config MMAPPER
-	tristate "iomem emulation driver"
-	help
-	  This driver allows a host file to be used as emulated IO memory inside
-	  UML.
-
 endmenu
diff -druNp linux-libre-3.1-gnu1/arch/um/Kconfig.rest linux-libre-3.2-gnu1/arch/um/Kconfig.rest
--- linux-libre-3.1-gnu1/arch/um/Kconfig.rest	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Kconfig.rest	2012-01-04 18:55:44.000000000 -0500
@@ -2,20 +2,14 @@ source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
-source "drivers/block/Kconfig"
-
 source "arch/um/Kconfig.char"
 
-source "drivers/base/Kconfig"
+source "drivers/Kconfig"
 
 source "net/Kconfig"
 
 source "arch/um/Kconfig.net"
 
-source "drivers/net/Kconfig"
-
-source "drivers/connector/Kconfig"
-
 source "fs/Kconfig"
 
 source "security/Kconfig"
@@ -24,19 +18,4 @@ source "crypto/Kconfig"
 
 source "lib/Kconfig"
 
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-if BROKEN
-	source "drivers/mtd/Kconfig"
-endif
-
-source "drivers/leds/Kconfig"
-
-#This is just to shut up some Kconfig warnings, so no prompt.
-config INPUT
-	tristate
-	default n
-
 source "arch/um/Kconfig.debug"
diff -druNp linux-libre-3.1-gnu1/arch/um/Kconfig.um linux-libre-3.2-gnu1/arch/um/Kconfig.um
--- linux-libre-3.1-gnu1/arch/um/Kconfig.um	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Kconfig.um	2012-01-04 18:55:44.000000000 -0500
@@ -148,5 +148,11 @@ config KERNEL_STACK_ORDER
 	  be 1 << order pages.  The default is OK unless you're running Valgrind
 	  on UML, in which case, set this to 3.
 
+config MMAPPER
+	tristate "iomem emulation driver"
+	help
+	  This driver allows a host file to be used as emulated IO memory inside
+	  UML.
+
 config NO_DMA
 	def_bool y
diff -druNp linux-libre-3.1-gnu1/arch/um/Kconfig.x86 linux-libre-3.2-gnu1/arch/um/Kconfig.x86
--- linux-libre-3.1-gnu1/arch/um/Kconfig.x86	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Kconfig.x86	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
-
-source "arch/um/Kconfig.common"
-
-menu "UML-specific options"
-
-menu "Host processor type and features"
-
-config CMPXCHG_LOCAL
-	bool
-	default n
-
-config CMPXCHG_DOUBLE
-	bool
-	default n
-
-source "arch/x86/Kconfig.cpu"
-
-endmenu
-
-config UML_X86
-	def_bool y
-	select GENERIC_FIND_FIRST_BIT
-
-config 64BIT
-	bool
-	default SUBARCH = "x86_64"
-
-config X86_32
-	def_bool !64BIT
-	select HAVE_AOUT
-
-config X86_64
-	def_bool 64BIT
-
-config RWSEM_XCHGADD_ALGORITHM
-	def_bool X86_XADD && 64BIT
-
-config RWSEM_GENERIC_SPINLOCK
-	def_bool !RWSEM_XCHGADD_ALGORITHM
-
-config 3_LEVEL_PGTABLES
-	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
-	default 64BIT
-	depends on EXPERIMENTAL
-	help
-	Three-level pagetables will let UML have more than 4G of physical
-	memory.  All the memory that can't be mapped directly will be treated
-	as high memory.
-
-	However, this it experimental on 32-bit architectures, so if unsure say
-	N (on x86-64 it's automatically enabled, instead, as it's safe there).
-
-config ARCH_HAS_SC_SIGNALS
-	def_bool !64BIT
-
-config ARCH_REUSE_HOST_VSYSCALL_AREA
-	def_bool !64BIT
-
-config SMP_BROKEN
-	def_bool 64BIT
-
-config GENERIC_HWEIGHT
-	def_bool y
-
-source "arch/um/Kconfig.um"
-
-endmenu
-
-source "arch/um/Kconfig.rest"
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/exec.c linux-libre-3.2-gnu1/arch/um/kernel/exec.c
--- linux-libre-3.1-gnu1/arch/um/kernel/exec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/exec.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,14 +3,15 @@
  * Licensed under the GPL
  */
 
-#include "linux/stddef.h"
-#include "linux/fs.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
 #include "as-layout.h"
 #include "mem_user.h"
 #include "skas.h"
@@ -41,6 +42,7 @@ void start_thread(struct pt_regs *regs,
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
 }
+EXPORT_SYMBOL(start_thread);
 
 static long execve1(const char *file,
 		    const char __user *const __user *argv,
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/gmon_syms.c linux-libre-3.2-gnu1/arch/um/kernel/gmon_syms.c
--- linux-libre-3.1-gnu1/arch/um/kernel/gmon_syms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/gmon_syms.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,18 +7,3 @@
 
 extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
-
-/*
- * This is defined (and referred to in profiling stub code) only by some GCC
- * versions in libgcov.
- *
- * Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which
- * will be overridden by any other one.
- */
-
-extern void __gcov_init(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_init);
-
-extern void __gcov_merge_add(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_merge_add);
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/initrd.c linux-libre-3.2-gnu1/arch/um/kernel/initrd.c
--- linux-libre-3.1-gnu1/arch/um/kernel/initrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/initrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,12 @@
 #include "linux/bootmem.h"
 #include "linux/initrd.h"
 #include "asm/types.h"
-#include "initrd.h"
 #include "init.h"
 #include "os.h"
 
 /* Changed by uml_initrd_setup, which is a setup */
 static char *initrd __initdata = NULL;
+static int load_initrd(char *filename, void *buf, int size);
 
 static int __init read_initrd(void)
 {
@@ -62,7 +62,7 @@ __uml_setup("initrd=", uml_initrd_setup,
 "    name of the file containing the image.\n\n"
 );
 
-int load_initrd(char *filename, void *buf, int size)
+static int load_initrd(char *filename, void *buf, int size)
 {
 	int fd, n;
 
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/irq.c linux-libre-3.2-gnu1/arch/um/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/um/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,6 +258,7 @@ void deactivate_fd(int fd, int irqnum)
 
 	ignore_sigio_fd(fd);
 }
+EXPORT_SYMBOL(deactivate_fd);
 
 /*
  * Called just before shutdown in order to provide a clean exec
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/ksyms.c linux-libre-3.2-gnu1/arch/um/kernel/ksyms.c
--- linux-libre-3.1-gnu1/arch/um/kernel/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,33 +3,11 @@
  * Licensed under the GPL
  */
 
-#include "linux/module.h"
-#include "linux/syscalls.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "mem_user.h"
+#include <linux/module.h>
 #include "os.h"
 
-EXPORT_SYMBOL(uml_physmem);
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(flush_tlb_range);
-
-EXPORT_SYMBOL(high_physmem);
-EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(handle_page_fault);
-EXPORT_SYMBOL(find_iomem);
-
-EXPORT_SYMBOL(strnlen_user);
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(uml_strdup);
 
 EXPORT_SYMBOL(os_stat_fd);
 EXPORT_SYMBOL(os_stat_file);
@@ -57,24 +35,10 @@ EXPORT_SYMBOL(os_connect_socket);
 EXPORT_SYMBOL(os_accept_connection);
 EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
-EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(os_major);
 EXPORT_SYMBOL(os_minor);
 EXPORT_SYMBOL(os_makedev);
 
 EXPORT_SYMBOL(add_sigio_fd);
 EXPORT_SYMBOL(ignore_sigio_fd);
-EXPORT_SYMBOL(deactivate_fd);
 EXPORT_SYMBOL(sigio_broken);
-
-#ifdef CONFIG_SMP
-
-/* required for SMP */
-
-extern void __write_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__write_lock_failed);
-
-extern void __read_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__read_lock_failed);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/Makefile linux-libre-3.2-gnu1/arch/um/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/um/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@ clean-files :=
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 	physmem.o process.o ptrace.o reboot.o sigio.o \
-	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
+	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
 	um_arch.o umid.o skas/
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/mem.c linux-libre-3.2-gnu1/arch/um/kernel/mem.c
--- linux-libre-3.1-gnu1/arch/um/kernel/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include <linux/stddef.h>
+#include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
@@ -20,6 +21,7 @@
 
 /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
+EXPORT_SYMBOL(empty_zero_page);
 /* allocated in paging_init and unchanged thereafter */
 static unsigned long *empty_bad_page = NULL;
 
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/physmem.c linux-libre-3.2-gnu1/arch/um/kernel/physmem.c
--- linux-libre-3.1-gnu1/arch/um/kernel/physmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/physmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,20 +3,22 @@
  * Licensed under the GPL
  */
 
-#include "linux/bootmem.h"
-#include "linux/mm.h"
-#include "linux/pfn.h"
-#include "asm/page.h"
-#include "as-layout.h"
-#include "init.h"
-#include "kern.h"
-#include "mem_user.h"
-#include "os.h"
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <asm/page.h>
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <mem_user.h>
+#include <os.h>
 
 static int physmem_fd = -1;
 
 /* Changed during early boot */
 unsigned long high_physmem;
+EXPORT_SYMBOL(high_physmem);
 
 extern unsigned long long physmem_size;
 
@@ -184,6 +186,7 @@ unsigned long find_iomem(char *driver, u
 
 	return 0;
 }
+EXPORT_SYMBOL(find_iomem);
 
 static int setup_iomem(void)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/process.c linux-libre-3.2-gnu1/arch/um/kernel/process.c
--- linux-libre-3.1-gnu1/arch/um/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,12 +20,12 @@
 #include <linux/threads.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/uaccess.h>
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 /*
  * This is a per-cpu array.  A processor only modifies its entry and it only
@@ -78,6 +78,7 @@ int kernel_thread(int (*fn)(void *), voi
 		      &current->thread.regs, 0, NULL, NULL);
 	return pid;
 }
+EXPORT_SYMBOL(kernel_thread);
 
 static inline void set_current(struct task_struct *task)
 {
@@ -286,6 +287,7 @@ char *uml_strdup(const char *string)
 {
 	return kstrdup(string, GFP_KERNEL);
 }
+EXPORT_SYMBOL(uml_strdup);
 
 int copy_to_user_proc(void __user *to, void *from, int size)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/signal.c linux-libre-3.2-gnu1/arch/um/kernel/signal.c
--- linux-libre-3.1-gnu1/arch/um/kernel/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 #include <asm/unistd.h>
 #include "frame_kern.h"
 #include "kern_util.h"
-#include <sysdep/sigcontext.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/skas/clone.c linux-libre-3.2-gnu1/arch/um/kernel/skas/clone.c
--- linux-libre-3.1-gnu1/arch/um/kernel/skas/clone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/skas/clone.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
 #include <asm/unistd.h>
 #include <sys/time.h>
 #include "as-layout.h"
-#include "kern_constants.h"
 #include "ptrace_user.h"
 #include "stub-data.h"
 #include "sysdep/stub.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/skas/uaccess.c linux-libre-3.2-gnu1/arch/um/kernel/skas/uaccess.c
--- linux-libre-3.1-gnu1/arch/um/kernel/skas/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/skas/uaccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/current.h>
 #include <asm/page.h>
@@ -149,6 +150,7 @@ int copy_from_user(void *to, const void
 	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
 	       n;
 }
+EXPORT_SYMBOL(copy_from_user);
 
 static int copy_chunk_to_user(unsigned long to, int len, void *arg)
 {
@@ -170,6 +172,7 @@ int copy_to_user(void __user *to, const
 	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
 	       n;
 }
+EXPORT_SYMBOL(copy_to_user);
 
 static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
 {
@@ -204,6 +207,7 @@ int strncpy_from_user(char *dst, const c
 		return -EFAULT;
 	return strnlen(dst, count);
 }
+EXPORT_SYMBOL(strncpy_from_user);
 
 static int clear_chunk(unsigned long addr, int len, void *unused)
 {
@@ -226,6 +230,7 @@ int clear_user(void __user *mem, int len
 	return access_ok(VERIFY_WRITE, mem, len) ?
 	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
 }
+EXPORT_SYMBOL(clear_user);
 
 static int strnlen_chunk(unsigned long str, int len, void *arg)
 {
@@ -251,3 +256,4 @@ int strnlen_user(const void __user *str,
 		return count + 1;
 	return -EFAULT;
 }
+EXPORT_SYMBOL(strnlen_user);
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/tlb.c linux-libre-3.2-gnu1/arch/um/kernel/tlb.c
--- linux-libre-3.1-gnu1/arch/um/kernel/tlb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/tlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -11,7 +12,6 @@
 #include "mem_user.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 struct host_vm_change {
 	struct host_vm_op {
@@ -287,7 +287,7 @@ void fix_range_common(struct mm_struct *
 	}
 }
 
-int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm;
 	pgd_t *pgd;
@@ -499,6 +499,7 @@ void flush_tlb_range(struct vm_area_stru
 		flush_tlb_kernel_range_common(start, end);
 	else fix_range(vma->vm_mm, start, end, 0);
 }
+EXPORT_SYMBOL(flush_tlb_range);
 
 void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 			unsigned long end)
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/trap.c linux-libre-3.2-gnu1/arch/um/kernel/trap.c
--- linux-libre-3.1-gnu1/arch/um/kernel/trap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/trap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/hardirq.h>
+#include <linux/module.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -14,7 +15,6 @@
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "sysdep/sigcontext.h"
 
 /*
  * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
@@ -112,6 +112,7 @@ out_of_memory:
 	pagefault_out_of_memory();
 	return 0;
 }
+EXPORT_SYMBOL(handle_page_fault);
 
 static void show_segv_info(struct uml_pt_regs *regs)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/uaccess.c linux-libre-3.2-gnu1/arch/um/kernel/uaccess.c
--- linux-libre-3.1-gnu1/arch/um/kernel/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/uaccess.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-/*
- * These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-#include <linux/string.h>
-#include "os.h"
-
-static void __do_copy(void *to, const void *from, int n)
-{
-	memcpy(to, from, n);
-}
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
-		      void **fault_addr, jmp_buf **fault_catcher)
-{
-	unsigned long fault;
-	int faulted;
-
-	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-			       __do_copy, &faulted);
-	if (!faulted)
-		return 0;
-	else
-		return n - (fault - (unsigned long) to);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/kernel/um_arch.c linux-libre-3.2-gnu1/arch/um/kernel/um_arch.c
--- linux-libre-3.1-gnu1/arch/um/kernel/um_arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/kernel/um_arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,6 +102,8 @@ const struct seq_operations cpuinfo_op =
 
 /* Set in linux_main */
 unsigned long uml_physmem;
+EXPORT_SYMBOL(uml_physmem);
+
 unsigned long uml_reserved; /* Also modified in mem_init */
 unsigned long start_vm;
 unsigned long end_vm;
diff -druNp linux-libre-3.1-gnu1/arch/um/Makefile linux-libre-3.2-gnu1/arch/um/Makefile
--- linux-libre-3.1-gnu1/arch/um/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -20,15 +20,27 @@ core-y			+= $(ARCH_DIR)/kernel/		\
 
 MODE_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
+HEADER_ARCH 	:= $(SUBARCH)
+
+# Additional ARCH settings for x86
+ifeq ($(SUBARCH),i386)
+        HEADER_ARCH := x86
+endif
+ifeq ($(SUBARCH),x86_64)
+        HEADER_ARCH := x86
+endif
+
+HOST_DIR := arch/$(HEADER_ARCH)
+
 include $(srctree)/$(ARCH_DIR)/Makefile-skas
+include $(srctree)/$(HOST_DIR)/Makefile.um
+
+core-y += $(HOST_DIR)/um/
 
 SHARED_HEADERS	:= $(ARCH_DIR)/include/shared
 ARCH_INCLUDE	:= -I$(srctree)/$(SHARED_HEADERS)
-ARCH_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
-ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE	+= -I$(SHARED_HEADERS)
-endif
-KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
+ARCH_INCLUDE	+= -I$(srctree)/$(HOST_DIR)/um/shared
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
 
 # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
 # named - it's a common symbol in libpcap, so we get a binary which crashes.
@@ -47,14 +59,12 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
 	$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
-	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
-
-include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include
 
 #This will adjust *FLAGS accordingly to the platform.
 include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 
-KBUILD_CPPFLAGS += -I$(srctree)/arch/$(HEADER_ARCH)/include
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -84,10 +94,9 @@ define archhelp
   echo '		   find in the kernel root.'
 endef
 
-KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
+KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig
 
-archprepare: $(SHARED_HEADERS)/user_constants.h
-archprepare: $(SHARED_HEADERS)/kern_constants.h
+archprepare: include/generated/user_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -118,9 +127,7 @@ endef
 
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
-CLEAN_FILES += linux x.i gmon.out \
-	$(SHARED_HEADERS)/user_constants.h \
-	$(SHARED_HEADERS)/kern_constants.h
+CLEAN_FILES += linux x.i gmon.out
 
 archclean:
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
@@ -128,8 +135,8 @@ archclean:
 
 # Generated files
 
-$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
-	$(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
+$(HOST_DIR)/um/user-offsets.s: FORCE
+	$(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@
 
 define filechk_gen-asm-offsets
         (set -e; \
@@ -144,11 +151,7 @@ define filechk_gen-asm-offsets
          echo ""; )
 endef
 
-$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+include/generated/user_constants.h: $(HOST_DIR)/um/user-offsets.s
 	$(call filechk,gen-asm-offsets)
 
-$(SHARED_HEADERS)/kern_constants.h:
-	$(Q)mkdir -p $(dir $@)
-	$(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
-
-export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH
diff -druNp linux-libre-3.1-gnu1/arch/um/Makefile-i386 linux-libre-3.2-gnu1/arch/um/Makefile-i386
--- linux-libre-3.1-gnu1/arch/um/Makefile-i386	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Makefile-i386	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-core-y += arch/um/sys-i386/ arch/x86/crypto/
-
-TOP_ADDR := $(CONFIG_TOP_ADDR)
-
-START := 0x8048000
-
-LDFLAGS			+= -m elf_i386
-ELF_ARCH		:= $(SUBARCH)
-ELF_FORMAT 		:= elf32-$(SUBARCH)
-OBJCOPYFLAGS  		:= -O binary -R .note -R .comment -S
-HEADER_ARCH		:= x86
-CHECKFLAGS	+= -D__i386__
-
-ifeq ("$(origin SUBARCH)", "command line")
-ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
-KBUILD_CFLAGS		+= $(call cc-option,-m32)
-KBUILD_AFLAGS		+= $(call cc-option,-m32)
-LINK-y			+= $(call cc-option,-m32)
-UML_OBJCOPYFLAGS	+= -F $(ELF_FORMAT)
-
-export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
-endif
-endif
-
-# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
-include $(srctree)/arch/x86/Makefile_32.cpu
-
-# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
-cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
-
-# Prevent sprintf in nfsd from being converted to strcpy and resulting in
-# an unresolved reference.
-cflags-y += -ffreestanding
-
-# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
-# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
-# 4.3.0 needs -funit-at-a-time for extern inline functions.
-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
-			echo $(call cc-option,-fno-unit-at-a-time); \
-			else echo $(call cc-option,-funit-at-a-time); fi ;)
-
-KBUILD_CFLAGS += $(cflags-y)
diff -druNp linux-libre-3.1-gnu1/arch/um/Makefile-x86_64 linux-libre-3.2-gnu1/arch/um/Makefile-x86_64
--- linux-libre-3.1-gnu1/arch/um/Makefile-x86_64	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/Makefile-x86_64	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-# Copyright 2003 - 2004 Pathscale, Inc
-# Released under the GPL
-
-core-y += arch/um/sys-x86_64/ arch/x86/crypto/
-START := 0x60000000
-
-_extra_flags_ = -fno-builtin -m64
-
-KBUILD_CFLAGS += $(_extra_flags_)
-
-CHECKFLAGS  += -m64 -D__x86_64__
-KBUILD_AFLAGS += -m64
-LDFLAGS += -m elf_x86_64
-KBUILD_CPPFLAGS += -m64
-
-ELF_ARCH := i386:x86-64
-ELF_FORMAT := elf64-x86-64
-HEADER_ARCH := x86
-
-# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
-
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
-LINK-y += -m64
-
-# Do unit-at-a-time unconditionally on x86_64, following the host
-KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/aio.c linux-libre-3.2-gnu1/arch/um/os-Linux/aio.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/aio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/aio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <asm/unistd.h>
 #include "aio.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct aio_thread_req {
 	enum aio_type type;
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/drivers/ethertap_user.c linux-libre-3.2-gnu1/arch/um/os-Linux/drivers/ethertap_user.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/drivers/ethertap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/drivers/ethertap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "etap.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/drivers/tuntap_user.c linux-libre-3.2-gnu1/arch/um/os-Linux/drivers/tuntap_user.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/drivers/tuntap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/drivers/tuntap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "tuntap.h"
-#include "user.h"
 
 static int tuntap_user_init(void *data, void *dev)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/elf_aux.c linux-libre-3.2-gnu1/arch/um/os-Linux/elf_aux.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/elf_aux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/elf_aux.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
-#include <kern_constants.h>
 
 typedef Elf32_auxv_t elf_auxv_t;
 
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/file.c linux-libre-3.2-gnu1/arch/um/os-Linux/file.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/file.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/file.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/helper.c linux-libre-3.2-gnu1/arch/um/os-Linux/helper.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #include <linux/limits.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct helper_data {
 	void (*pre_exec)(void*);
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/internal.h linux-libre-3.2-gnu1/arch/um/os-Linux/internal.h
--- linux-libre-3.1-gnu1/arch/um/os-Linux/internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+void alarm_handler(int, mcontext_t *);
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/irq.c linux-libre-3.2-gnu1/arch/um/os-Linux/irq.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,11 +9,8 @@
 #include <signal.h>
 #include <string.h>
 #include "irq_user.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "process.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/main.c linux-libre-3.2-gnu1/arch/um/os-Linux/main.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include <sys/resource.h>
 #include "as-layout.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/Makefile linux-libre-3.2-gnu1/arch/um/os-Linux/Makefile
--- linux-libre-3.1-gnu1/arch/um/os-Linux/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,14 +4,14 @@
 #
 
 obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
-	registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
-	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
+	registers.o sigio.o signal.o start_up.o time.o tty.o \
+	umid.o user_syms.o util.o drivers/ skas/
 
 obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
-	tty.o tls.o uaccess.o umid.o util.o
+	tty.o umid.o util.o
 
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
 
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/mem.c linux-libre-3.2-gnu1/arch/um/os-Linux/mem.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,7 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 /* Modified by which_tmpdir, which is called during early boot */
 static char *default_tmpdir = "/tmp";
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/process.c linux-libre-3.2-gnu1/arch/um/os-Linux/process.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,9 @@
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "longjmp.h"
 #include "os.h"
-#include "process.h"
 #include "skas_ptrace.h"
-#include "user.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -237,21 +234,13 @@ out:
 
 void init_new_thread_signals(void)
 {
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+	set_handler(SIGSEGV);
+	set_handler(SIGTRAP);
+	set_handler(SIGFPE);
+	set_handler(SIGILL);
+	set_handler(SIGBUS);
 	signal(SIGHUP, SIG_IGN);
-
-	set_handler(SIGIO, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
-		    SIGVTALRM, -1);
+	set_handler(SIGIO);
 	signal(SIGWINCH, SIG_IGN);
 	signal(SIGTERM, SIG_DFL);
 }
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sigio.c linux-libre-3.2-gnu1/arch/um/os-Linux/sigio.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sigio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sigio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,14 +11,11 @@
 #include <sched.h>
 #include <signal.h>
 #include <string.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "init.h"
 #include "os.h"
-#include "process.h"
 #include "sigio.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Protected by sigio_lock(), also used by sigio_cleanup, which is an
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/signal.c linux-libre-3.2-gnu1/arch/um/os-Linux/signal.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,13 +12,7 @@
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "sysdep/barrier.h"
-#include "sysdep/sigcontext.h"
-#include "user.h"
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
+#include "sysdep/mcontext.h"
 
 void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
 	[SIGTRAP]	= relay_signal,
@@ -30,7 +24,7 @@ void (*sig_info[NSIG])(int, struct uml_p
 	[SIGIO]		= sigio_handler,
 	[SIGVTALRM]	= timer_handler };
 
-static void sig_handler_common(int sig, struct sigcontext *sc)
+static void sig_handler_common(int sig, mcontext_t *mc)
 {
 	struct uml_pt_regs r;
 	int save_errno = errno;
@@ -38,8 +32,8 @@ static void sig_handler_common(int sig,
 	r.is_user = 0;
 	if (sig == SIGSEGV) {
 		/* For segfaults, we want the data from the sigcontext. */
-		copy_sc(&r, sc);
-		GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+		get_regs_from_mc(&r, mc);
+		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
 	}
 
 	/* enable signals if sig isn't IRQ signal */
@@ -66,7 +60,7 @@ static void sig_handler_common(int sig,
 static int signals_enabled;
 static unsigned int signals_pending;
 
-void sig_handler(int sig, struct sigcontext *sc)
+void sig_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -78,23 +72,23 @@ void sig_handler(int sig, struct sigcont
 
 	block_signals();
 
-	sig_handler_common(sig, sc);
+	sig_handler_common(sig, mc);
 
 	set_signals(enabled);
 }
 
-static void real_alarm_handler(struct sigcontext *sc)
+static void real_alarm_handler(mcontext_t *mc)
 {
 	struct uml_pt_regs regs;
 
-	if (sc != NULL)
-		copy_sc(&regs, sc);
+	if (mc != NULL)
+		get_regs_from_mc(&regs, mc);
 	regs.is_user = 0;
 	unblock_signals();
 	timer_handler(SIGVTALRM, &regs);
 }
 
-void alarm_handler(int sig, struct sigcontext *sc)
+void alarm_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -106,14 +100,13 @@ void alarm_handler(int sig, struct sigco
 
 	block_signals();
 
-	real_alarm_handler(sc);
+	real_alarm_handler(mc);
 	set_signals(enabled);
 }
 
 void timer_init(void)
 {
-	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+	set_handler(SIGVTALRM);
 }
 
 void set_sigstack(void *sig_stack, int size)
@@ -126,10 +119,23 @@ void set_sigstack(void *sig_stack, int s
 		panic("enabling signal stack failed, errno = %d\n", errno);
 }
 
-static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = {
+	[SIGSEGV] = sig_handler,
+	[SIGBUS] = sig_handler,
+	[SIGILL] = sig_handler,
+	[SIGFPE] = sig_handler,
+	[SIGTRAP] = sig_handler,
 
-void handle_signal(int sig, struct sigcontext *sc)
+	[SIGIO] = sig_handler,
+	[SIGWINCH] = sig_handler,
+	[SIGVTALRM] = alarm_handler
+};
+
+
+static void hard_handler(int sig, siginfo_t *info, void *p)
 {
+	struct ucontext *uc = p;
+	mcontext_t *mc = &uc->uc_mcontext;
 	unsigned long pending = 1UL << sig;
 
 	do {
@@ -155,7 +161,7 @@ void handle_signal(int sig, struct sigco
 		while ((sig = ffs(pending)) != 0){
 			sig--;
 			pending &= ~(1 << sig);
-			(*handlers[sig])(sig, sc);
+			(*handlers[sig])(sig, mc);
 		}
 
 		/*
@@ -169,28 +175,26 @@ void handle_signal(int sig, struct sigco
 	} while (pending);
 }
 
-extern void hard_handler(int sig);
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
+void set_handler(int sig)
 {
 	struct sigaction action;
-	va_list ap;
+	int flags = SA_SIGINFO | SA_ONSTACK;
 	sigset_t sig_mask;
-	int mask;
 
-	handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
-	action.sa_handler = hard_handler;
+	action.sa_sigaction = hard_handler;
 
+	/* block irq ones */
 	sigemptyset(&action.sa_mask);
-
-	va_start(ap, flags);
-	while ((mask = va_arg(ap, int)) != -1)
-		sigaddset(&action.sa_mask, mask);
-	va_end(ap);
+	sigaddset(&action.sa_mask, SIGVTALRM);
+	sigaddset(&action.sa_mask, SIGIO);
+	sigaddset(&action.sa_mask, SIGWINCH);
 
 	if (sig == SIGSEGV)
 		flags |= SA_NODEFER;
 
+	if (sigismember(&action.sa_mask, sig))
+		flags |= SA_RESTART; /* if it's an irq signal */
+
 	action.sa_flags = flags;
 	action.sa_restorer = NULL;
 	if (sigaction(sig, &action, NULL) < 0)
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/skas/mem.c linux-libre-3.2-gnu1/arch/um/os-Linux/skas/mem.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/skas/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/skas/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
 #include <string.h>
 #include <sys/mman.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "as-layout.h"
 #include "mm_id.h"
 #include "os.h"
@@ -17,7 +16,6 @@
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
-#include "user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/stub.h"
 
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/skas/process.c linux-libre-3.2-gnu1/arch/um/os-Linux/skas/process.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/skas/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/skas/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,31 +9,23 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "as-layout.h"
-#include "chan_user.h"
-#include "kern_constants.h"
+#include "init.h"
 #include "kern_util.h"
 #include "mem.h"
 #include "os.h"
-#include "process.h"
 #include "proc_mm.h"
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
 #include "skas_ptrace.h"
-#include "user.h"
 #include "sysdep/stub.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-	if (pid != getpgrp())
-		return 0;
-
-	register_winch_irq(-1, fd, -1, data, 0);
-	return 1;
+	return pid == getpgrp();
 }
 
 static int ptrace_dump_regs(int pid)
@@ -169,7 +161,7 @@ static void handle_trap(int pid, struct
 
 	if (!local_using_sysemu)
 	{
-		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 			     __NR_getpid);
 		if (err < 0) {
 			printk(UM_KERN_ERR "handle_trap - nullifying syscall "
@@ -257,8 +249,8 @@ static int userspace_tramp(void *stack)
 
 		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
 		sigemptyset(&sa.sa_mask);
-		sa.sa_flags = SA_ONSTACK | SA_NODEFER;
-		sa.sa_handler = (void *) v;
+		sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
+		sa.sa_sigaction = (void *) v;
 		sa.sa_restorer = NULL;
 		if (sigaction(SIGSEGV, &sa, NULL) < 0) {
 			printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
@@ -661,8 +653,7 @@ int start_idle_thread(void *stack, jmp_b
 {
 	int n;
 
-	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1);
+	set_handler(SIGWINCH);
 
 	/*
 	 * Can't use UML_SETJMP or UML_LONGJMP here because they save
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/start_up.c linux-libre-3.2-gnu1/arch/um/os-Linux/start_up.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/start_up.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/start_up.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,10 @@
 #include <signal.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "mem_user.h"
 #include "ptrace_user.h"
@@ -225,7 +223,7 @@ static void __init check_sysemu(void)
 		goto fail;
 	}
 
-	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+	n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
 	if (n < 0) {
 		non_fatal("check_sysemu : failed to modify system call "
 			  "return");
@@ -261,7 +259,7 @@ static void __init check_sysemu(void)
 					  "doesn't singlestep");
 				goto fail;
 			}
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
 				   os_getpid());
 			if (n < 0)
 				fatal_perror("check_sysemu : failed to modify "
@@ -317,10 +315,10 @@ static void __init check_ptrace(void)
 			fatal("check_ptrace : expected (SIGTRAP|0x80), "
 			       "got status = %d", status);
 
-		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
+		syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
 		if (syscall == __NR_getpid) {
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 				   __NR_getppid);
 			if (n < 0)
 				fatal_perror("check_ptrace : failed to modify "
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/Makefile linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/Makefile
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o signal.o task_size.o tls.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/registers.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/registers.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/registers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/registers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <sys/user.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-#include "sysdep/ptrace_user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int save_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case EIP:
-		return buf[0]->__eip;
-	case UESP:
-		return buf[0]->__esp;
-	case EBP:
-		return buf[0]->__ebp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int have_fpx_regs = 1;
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return save_fpx_registers(pid, regs);
-	else
-		return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return restore_fpx_registers(pid, regs);
-	else
-		return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
-	struct user_fpxregs_struct fpx_regs;
-	int err;
-
-	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
-	if (!err)
-		return;
-
-	if (errno != EIO)
-		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
-		      errno);
-
-	have_fpx_regs = 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/signal.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/signal.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	handle_signal(sig, (struct sigcontext *) (&sig + 1));
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/task_size.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/task_size.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/task_size.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/task_size.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include "longjmp.h"
-#include "kern_constants.h"
-
-static jmp_buf buf;
-
-static void segfault(int sig)
-{
-	longjmp(buf, 1);
-}
-
-static int page_ok(unsigned long page)
-{
-	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
-	unsigned long n = ~0UL;
-	void *mapped = NULL;
-	int ok = 0;
-
-	/*
-	 * First see if the page is readable.  If it is, it may still
-	 * be a VDSO, so we go on to see if it's writable.  If not
-	 * then try mapping memory there.  If that fails, then we're
-	 * still in the kernel area.  As a sanity check, we'll fail if
-	 * the mmap succeeds, but gives us an address different from
-	 * what we wanted.
-	 */
-	if (setjmp(buf) == 0)
-		n = *address;
-	else {
-		mapped = mmap(address, UM_KERN_PAGE_SIZE,
-			      PROT_READ | PROT_WRITE,
-			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		if (mapped == MAP_FAILED)
-			return 0;
-		if (mapped != address)
-			goto out;
-	}
-
-	/*
-	 * Now, is it writeable?  If so, then we're in user address
-	 * space.  If not, then try mprotecting it and try the write
-	 * again.
-	 */
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-		goto out;
-	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
-			    PROT_READ | PROT_WRITE) != 0)
-		goto out;
-
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-	}
-
- out:
-	if (mapped != NULL)
-		munmap(mapped, UM_KERN_PAGE_SIZE);
-	return ok;
-}
-
-unsigned long os_get_top_address(void)
-{
-	struct sigaction sa, old;
-	unsigned long bottom = 0;
-	/*
-	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
-	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
-	 * and written.  However, exec discovers later that it can't be
-	 * unmapped.  So, just set the highest address to be checked to just
-	 * below it.  This might waste some address space on 4G/4G 32-bit
-	 * hosts, but shouldn't hurt otherwise.
-	 */
-	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
-	unsigned long test, original;
-
-	printf("Locating the bottom of the address space ... ");
-	fflush(stdout);
-
-	/*
-	 * We're going to be longjmping out of the signal handler, so
-	 * SA_DEFER needs to be set.
-	 */
-	sa.sa_handler = segfault;
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = SA_NODEFER;
-	if (sigaction(SIGSEGV, &sa, &old)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-
-	/* Manually scan the address space, bottom-up, until we find
-	 * the first valid page (or run out of them).
-	 */
-	for (bottom = 0; bottom < top; bottom++) {
-		if (page_ok(bottom))
-			break;
-	}
-
-	/* If we've got this far, we ran out of pages. */
-	if (bottom == top) {
-		fprintf(stderr, "Unable to determine bottom of address "
-			"space.\n");
-		exit(1);
-	}
-
-	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
-	printf("Locating the top of the address space ... ");
-	fflush(stdout);
-
-	original = bottom;
-
-	/* This could happen with a 4G/4G split */
-	if (page_ok(top))
-		goto out;
-
-	do {
-		test = bottom + (top - bottom) / 2;
-		if (page_ok(test))
-			bottom = test;
-		else
-			top = test;
-	} while (top - bottom > 1);
-
-out:
-	/* Restore the old SIGSEGV handling */
-	if (sigaction(SIGSEGV, &old, NULL)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-	top <<= UM_KERN_PAGE_SHIFT;
-	printf("0x%x\n", top);
-
-	return top;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/tls.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/tls.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-i386/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-i386/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-#include <errno.h>
-#include <linux/unistd.h>
-
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "sysdep/tls.h"
-#include "user.h"
-
-/* Checks whether host supports TLS, and sets *tls_min according to the value
- * valid on the host.
- * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
-void check_host_supports_tls(int *supports_tls, int *tls_min) {
-	/* Values for x86 and x86_64.*/
-	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(val); i++) {
-		user_desc_t info;
-		info.entry_number = val[i];
-
-		if (syscall(__NR_get_thread_area, &info) == 0) {
-			*tls_min = val[i];
-			*supports_tls = 1;
-			return;
-		} else {
-			if (errno == EINVAL)
-				continue;
-			else if (errno == ENOSYS)
-				*supports_tls = 0;
-				return;
-		}
-	}
-
-	*supports_tls = 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/Makefile linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/Makefile
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o prctl.o signal.o task_size.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/prctl.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/prctl.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/prctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/prctl.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
- * Licensed under the GPL
- */
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-
-int os_arch_prctl(int pid, int code, unsigned long *addr)
-{
-        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/registers.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/registers.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/registers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/registers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case RIP:
-		return buf[0]->__rip;
-	case RSP:
-		return buf[0]->__rsp;
-	case RBP:
-		return buf[0]->__rbp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	return restore_fp_registers(pid, regs);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/signal.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/signal.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	struct ucontext *uc;
-	asm("movq %%rdx, %0" : "=r" (uc));
-
-	handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/task_size.c linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/task_size.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/sys-x86_64/task_size.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/sys-x86_64/task_size.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-unsigned long os_get_top_address(unsigned long shift)
-{
-	/* The old value of CONFIG_TOP_ADDR */
-	return 0x7fc0000000;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/time.c linux-libre-3.2-gnu1/arch/um/os-Linux/time.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,9 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/time.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "user.h"
+#include "internal.h"
 
 int set_interval(void)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/tls.c linux-libre-3.2-gnu1/arch/um/os-Linux/tls.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-#include <errno.h>
-#include <sys/ptrace.h>
-#include "sysdep/tls.h"
-
-/* TLS support - we basically rely on the host's one.*/
-
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
-
-#ifndef PTRACE_SET_THREAD_AREA
-#define PTRACE_SET_THREAD_AREA 26
-#endif
-
-int os_set_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
-
-int os_get_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/tty.c linux-libre-3.2-gnu1/arch/um/os-Linux/tty.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct grantpt_info {
 	int fd;
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/uaccess.c linux-libre-3.2-gnu1/arch/um/os-Linux/uaccess.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/uaccess.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include "longjmp.h"
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher,
-			     void (*op)(void *to, const void *from,
-					int n), int *faulted_out)
-{
-	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
-	jmp_buf jbuf;
-	*fault_catcher = &jbuf;
-	if (UML_SETJMP(&jbuf) == 0) {
-		(*op)(to, from, n);
-		ret = 0;
-		*faulted_out = 0;
-	}
-	else {
-		ret = *faddrp;
-		*faulted_out = 1;
-	}
-	*fault_addr = NULL;
-	*fault_catcher = NULL;
-	return ret;
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/umid.c linux-libre-3.2-gnu1/arch/um/os-Linux/umid.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/umid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/umid.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 #define UML_DIR "~/.uml/"
 
diff -druNp linux-libre-3.1-gnu1/arch/um/os-Linux/util.c linux-libre-3.2-gnu1/arch/um/os-Linux/util.c
--- linux-libre-3.1-gnu1/arch/um/os-Linux/util.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/os-Linux/util.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <wait.h>
 #include <sys/mman.h>
 #include <sys/utsname.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 void stack_protections(unsigned long address)
 {
diff -druNp linux-libre-3.1-gnu1/arch/um/scripts/Makefile.rules linux-libre-3.2-gnu1/arch/um/scripts/Makefile.rules
--- linux-libre-3.1-gnu1/arch/um/scripts/Makefile.rules	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/scripts/Makefile.rules	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y)
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS:.o=.%): \
-	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
+	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
 $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 
@@ -25,8 +25,3 @@ $(UNPROFILE_OBJS) : CHECKFLAGS := -D__li
 define unprofile
 	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 endef
-
-ifdef subarch-obj-y
-obj-y += subarch.o
-subarch-y = $(addprefix ../../$(HEADER_ARCH)/,$(subarch-obj-y))
-endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/asm/archparam.h linux-libre-3.2-gnu1/arch/um/sys-i386/asm/archparam.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/asm/archparam.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_I386_H
-#define __UM_ARCHPARAM_I386_H
-
-#ifdef CONFIG_X86_PAE
-#define LAST_PKMAP 512
-#else
-#define LAST_PKMAP 1024
-#endif
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/asm/elf.h linux-libre-3.2-gnu1/arch/um/sys-i386/asm/elf.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_I386_H
-#define __UM_ELF_I386_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-#define R_386_NONE	0
-#define R_386_32	1
-#define R_386_PC32	2
-#define R_386_GOT32	3
-#define R_386_PLT32	4
-#define R_386_COPY	5
-#define R_386_GLOB_DAT	6
-#define R_386_JMP_SLOT	7
-#define R_386_RELATIVE	8
-#define R_386_GOTOFF	9
-#define R_386_GOTPC	10
-#define R_386_NUM	11
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_386
-
-#define ELF_PLAT_INIT(regs, load_addr) do { \
-	PT_REGS_EBX(regs) = 0; \
-	PT_REGS_ECX(regs) = 0; \
-	PT_REGS_EDX(regs) = 0; \
-	PT_REGS_ESI(regs) = 0; \
-	PT_REGS_EDI(regs) = 0; \
-	PT_REGS_EBP(regs) = 0; \
-	PT_REGS_EAX(regs) = 0; \
-} while (0)
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-/* Shamelessly stolen from include/asm-i386/elf.h */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
-	pr_reg[0] = PT_REGS_EBX(regs);		\
-	pr_reg[1] = PT_REGS_ECX(regs);		\
-	pr_reg[2] = PT_REGS_EDX(regs);		\
-	pr_reg[3] = PT_REGS_ESI(regs);		\
-	pr_reg[4] = PT_REGS_EDI(regs);		\
-	pr_reg[5] = PT_REGS_EBP(regs);		\
-	pr_reg[6] = PT_REGS_EAX(regs);		\
-	pr_reg[7] = PT_REGS_DS(regs);		\
-	pr_reg[8] = PT_REGS_ES(regs);		\
-	/* fake once used fs and gs selectors? */	\
-	pr_reg[9] = PT_REGS_DS(regs);		\
-	pr_reg[10] = PT_REGS_DS(regs);		\
-	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
-	pr_reg[12] = PT_REGS_IP(regs);		\
-	pr_reg[13] = PT_REGS_CS(regs);		\
-	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
-	pr_reg[15] = PT_REGS_SP(regs);		\
-	pr_reg[16] = PT_REGS_SS(regs);		\
-} while (0);
-
-#define task_pt_regs(t) (&(t)->thread.regs)
-
-struct task_struct;
-
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-extern char * elf_aux_platform;
-#define ELF_PLATFORM (elf_aux_platform)
-
-#define SET_PERSONALITY(ex) do { } while (0)
-
-extern unsigned long vsyscall_ehdr;
-extern unsigned long vsyscall_end;
-extern unsigned long __kernel_vsyscall;
-
-#define VSYSCALL_BASE vsyscall_ehdr
-#define VSYSCALL_END vsyscall_end
-
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START      VSYSCALL_BASE
-#define FIXADDR_USER_END        VSYSCALL_END
-
-#define __HAVE_ARCH_GATE_AREA 1
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO		32
-#define AT_SYSINFO_EHDR		33
-
-#define ARCH_DLINFO						\
-do {								\
-	if ( vsyscall_ehdr ) {					\
-		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
-	}							\
-} while (0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/asm/module.h linux-libre-3.2-gnu1/arch/um/sys-i386/asm/module.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/asm/module.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-#ifndef __UM_MODULE_I386_H
-#define __UM_MODULE_I386_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/asm/processor.h linux-libre-3.2-gnu1/arch/um/sys-i386/asm/processor.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_I386_H
-#define __UM_PROCESSOR_I386_H
-
-#include "linux/string.h"
-#include <sysdep/host_ldt.h>
-#include "asm/segment.h"
-
-extern int host_has_cmov;
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct uml_tls_struct {
-	struct user_desc tls;
-	unsigned flushed:1;
-	unsigned present:1;
-};
-
-struct arch_thread {
-	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
-	unsigned long debugregs[8];
-	int debugregs_seq;
-	struct faultinfo faultinfo;
-};
-
-#define INIT_ARCH_THREAD { \
-	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
-				    { .present = 0, .flushed = 0 } }, \
-	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
-	.debugregs_seq		= 0, \
-	.faultinfo		= { 0, 0, 0 } \
-}
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-	/* Clear any TLS still hanging */
-	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
-}
-
-#include <asm/user.h>
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()	rep_nop()
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter"). Stolen
- * from asm-i386/processor.h
- */
-#define current_text_addr() \
-	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-       (address + 32 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP)
-#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/asm/ptrace.h linux-libre-3.2-gnu1/arch/um/sys-i386/asm/ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_I386_H
-#define __UM_PTRACE_I386_H
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
-
-#include "linux/compiler.h"
-#include "asm/ptrace-generic.h"
-
-#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
-#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
-#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
-#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
-#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
-#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
-#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
-
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-
-/*
- * Forward declaration to avoid including sysdep/tls.h, which causes a
- * circular include, and compilation failures.
- */
-struct user_desc;
-
-extern int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-extern int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/atomic64_cx8_32.S linux-libre-3.2-gnu1/arch/um/sys-i386/atomic64_cx8_32.S
--- linux-libre-3.1-gnu1/arch/um/sys-i386/atomic64_cx8_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/atomic64_cx8_32.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,225 +0,0 @@
-/*
- * atomic64_t for 586+
- *
- * Copied from arch/x86/lib/atomic64_cx8_32.S
- *
- * Copyright Â© 2010  Luca Barbieri
- *
- * 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/linkage.h>
-#include <asm/alternative-asm.h>
-#include <asm/dwarf2.h>
-
-.macro SAVE reg
-	pushl_cfi %\reg
-	CFI_REL_OFFSET \reg, 0
-.endm
-
-.macro RESTORE reg
-	popl_cfi %\reg
-	CFI_RESTORE \reg
-.endm
-
-.macro read64 reg
-	movl %ebx, %eax
-	movl %ecx, %edx
-/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
-	LOCK_PREFIX
-	cmpxchg8b (\reg)
-.endm
-
-ENTRY(atomic64_read_cx8)
-	CFI_STARTPROC
-
-	read64 %ecx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_read_cx8)
-
-ENTRY(atomic64_set_cx8)
-	CFI_STARTPROC
-
-1:
-/* we don't need LOCK_PREFIX since aligned 64-bit writes
- * are atomic on 586 and newer */
-	cmpxchg8b (%esi)
-	jne 1b
-
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_set_cx8)
-
-ENTRY(atomic64_xchg_cx8)
-	CFI_STARTPROC
-
-	movl %ebx, %eax
-	movl %ecx, %edx
-1:
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_xchg_cx8)
-
-.macro addsub_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
-	CFI_STARTPROC
-	SAVE ebp
-	SAVE ebx
-	SAVE esi
-	SAVE edi
-
-	movl %eax, %esi
-	movl %edx, %edi
-	movl %ecx, %ebp
-
-	read64 %ebp
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	\ins\()l %esi, %ebx
-	\insc\()l %edi, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%ebp)
-	jne 1b
-
-10:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE edi
-	RESTORE esi
-	RESTORE ebx
-	RESTORE ebp
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-addsub_return add add adc
-addsub_return sub sub sbb
-
-.macro incdec_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	\ins\()l $1, %ebx
-	\insc\()l $0, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-10:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE ebx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-incdec_return inc add adc
-incdec_return dec sub sbb
-
-ENTRY(atomic64_dec_if_positive_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	subl $1, %ebx
-	sbb $0, %ecx
-	js 2f
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-2:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE ebx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_dec_if_positive_cx8)
-
-ENTRY(atomic64_add_unless_cx8)
-	CFI_STARTPROC
-	SAVE ebp
-	SAVE ebx
-/* these just push these two parameters on the stack */
-	SAVE edi
-	SAVE esi
-
-	movl %ecx, %ebp
-	movl %eax, %esi
-	movl %edx, %edi
-
-	read64 %ebp
-1:
-	cmpl %eax, 0(%esp)
-	je 4f
-2:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	addl %esi, %ebx
-	adcl %edi, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%ebp)
-	jne 1b
-
-	movl $1, %eax
-3:
-	addl $8, %esp
-	CFI_ADJUST_CFA_OFFSET -8
-	RESTORE ebx
-	RESTORE ebp
-	ret
-4:
-	cmpl %edx, 4(%esp)
-	jne 2b
-	xorl %eax, %eax
-	jmp 3b
-	CFI_ENDPROC
-ENDPROC(atomic64_add_unless_cx8)
-
-ENTRY(atomic64_inc_not_zero_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	testl %eax, %eax
-	je 4f
-2:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	addl $1, %ebx
-	adcl $0, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-	movl $1, %eax
-3:
-	RESTORE ebx
-	ret
-4:
-	testl %edx, %edx
-	jne 2b
-	jmp 3b
-	CFI_ENDPROC
-ENDPROC(atomic64_inc_not_zero_cx8)
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/bug.c linux-libre-3.2-gnu1/arch/um/sys-i386/bug.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/bug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/bugs.c linux-libre-3.2-gnu1/arch/um/sys-i386/bugs.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/bugs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/bugs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "kern_constants.h"
-#include "kern_util.h"
-#include "longjmp.h"
-#include "task.h"
-#include "user.h"
-#include "sysdep/ptrace.h"
-
-/* Set during early boot */
-static int host_has_cmov = 1;
-static jmp_buf cmov_test_return;
-
-static void cmov_sigill_test_handler(int sig)
-{
-	host_has_cmov = 0;
-	longjmp(cmov_test_return, 1);
-}
-
-void arch_check_bugs(void)
-{
-	struct sigaction old, new;
-
-	printk(UM_KERN_INFO "Checking for host processor cmov support...");
-	new.sa_handler = cmov_sigill_test_handler;
-
-	/* Make sure that SIGILL is enabled after the handler longjmps back */
-	new.sa_flags = SA_NODEFER;
-	sigemptyset(&new.sa_mask);
-	sigaction(SIGILL, &new, &old);
-
-	if (setjmp(cmov_test_return) == 0) {
-		unsigned long foo = 0;
-		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
-		printk(UM_KERN_CONT "Yes\n");
-	} else
-		printk(UM_KERN_CONT "No\n");
-
-	sigaction(SIGILL, &old, &new);
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-	unsigned char tmp[2];
-
-	/*
-	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
-	 * SIGILL in init.
-	 */
-	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
-		return;
-
-	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
-		printk(UM_KERN_ERR "SIGILL in init, could not read "
-		       "instructions!\n");
-		return;
-	}
-
-	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
-		return;
-
-	if (host_has_cmov == 0)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor doesn't implement.  Boot a filesystem "
-		       "compiled for older processors");
-	else if (host_has_cmov == 1)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor claims to implement");
-	else
-		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
-			host_has_cmov);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/checksum.S linux-libre-3.2-gnu1/arch/um/sys-i386/checksum.S
--- linux-libre-3.1-gnu1/arch/um/sys-i386/checksum.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/checksum.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,458 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IP/TCP/UDP checksumming routines
- *
- * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
- *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		Tom May, <ftom@netcom.com>
- *              Pentium Pro/II routines:
- *              Alexander Kjeldaas <astor@guardian.no>
- *              Finn Arne Gangstad <finnag@guardian.no>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
- *			     handling.
- *		Andi Kleen,  add zeroing on error
- *                   converted to pure assembler
- *
- *		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 <asm/errno.h>
-				
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-
-/*	
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
- */
-		
-.text
-.align 4
-.globl csum_partial
-		
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-	  /*		
-	   * Experiments with Ethernet and SLIP connections show that buff
-	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
-	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
-	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
-	   * alignment for the unrolled loop.
-	   */		
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg: unsigned char *buff
-	testl $2, %esi		# Check alignment.
-	jz 2f			# Jump if alignment is ok.
-	subl $2, %ecx		# Alignment uses up two bytes.
-	jae 1f			# Jump if we had at least two bytes.
-	addl $2, %ecx		# ecx was < 2.  Deal with it.
-	jmp 4f
-1:	movw (%esi), %bx
-	addl $2, %esi
-	addw %bx, %ax
-	adcl $0, %eax
-2:
-	movl %ecx, %edx
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-1:	movl (%esi), %ebx
-	adcl %ebx, %eax
-	movl 4(%esi), %ebx
-	adcl %ebx, %eax
-	movl 8(%esi), %ebx
-	adcl %ebx, %eax
-	movl 12(%esi), %ebx
-	adcl %ebx, %eax
-	movl 16(%esi), %ebx
-	adcl %ebx, %eax
-	movl 20(%esi), %ebx
-	adcl %ebx, %eax
-	movl 24(%esi), %ebx
-	adcl %ebx, %eax
-	movl 28(%esi), %ebx
-	adcl %ebx, %eax
-	lea 32(%esi), %esi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx		# This clears CF
-3:	adcl (%esi), %eax
-	lea 4(%esi), %esi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-	movw (%esi),%cx
-	leal 2(%esi),%esi
-	je 6f
-	shll $16,%ecx
-5:	movb (%esi),%cl
-6:	addl %ecx,%eax
-	adcl $0, %eax 
-7:	
-	popl %ebx
-	popl %esi
-	ret
-
-#else
-
-/* Version for PentiumII/PPro */
-
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
-
-	testl $2, %esi         
-	jnz 30f                 
-10:
-	movl %ecx, %edx
-	movl %ecx, %ebx
-	andl $0x7c, %ebx
-	shrl $7, %ecx
-	addl %ebx,%esi
-	shrl $2, %ebx  
-	negl %ebx
-	lea 45f(%ebx,%ebx,2), %ebx
-	testl %esi, %esi
-	jmp *%ebx
-
-	# Handle 2-byte-aligned regions
-20:	addw (%esi), %ax
-	lea 2(%esi), %esi
-	adcl $0, %eax
-	jmp 10b
-
-30:	subl $2, %ecx          
-	ja 20b                 
-	je 32f
-	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
-	addl %ebx, %eax
-	adcl $0, %eax
-	jmp 80f
-32:
-	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
-	adcl $0, %eax
-	jmp 80f
-
-40: 
-	addl -128(%esi), %eax
-	adcl -124(%esi), %eax
-	adcl -120(%esi), %eax
-	adcl -116(%esi), %eax   
-	adcl -112(%esi), %eax   
-	adcl -108(%esi), %eax
-	adcl -104(%esi), %eax
-	adcl -100(%esi), %eax
-	adcl -96(%esi), %eax
-	adcl -92(%esi), %eax
-	adcl -88(%esi), %eax
-	adcl -84(%esi), %eax
-	adcl -80(%esi), %eax
-	adcl -76(%esi), %eax
-	adcl -72(%esi), %eax
-	adcl -68(%esi), %eax
-	adcl -64(%esi), %eax     
-	adcl -60(%esi), %eax     
-	adcl -56(%esi), %eax     
-	adcl -52(%esi), %eax   
-	adcl -48(%esi), %eax   
-	adcl -44(%esi), %eax
-	adcl -40(%esi), %eax
-	adcl -36(%esi), %eax
-	adcl -32(%esi), %eax
-	adcl -28(%esi), %eax
-	adcl -24(%esi), %eax
-	adcl -20(%esi), %eax
-	adcl -16(%esi), %eax
-	adcl -12(%esi), %eax
-	adcl -8(%esi), %eax
-	adcl -4(%esi), %eax
-45:
-	lea 128(%esi), %esi
-	adcl $0, %eax
-	dec %ecx
-	jge 40b
-	movl %edx, %ecx
-50:	andl $3, %ecx
-	jz 80f
-
-	# Handle the last 1-3 bytes without jumping
-	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
-	movl $0xffffff,%ebx	# by the shll and shrl instructions
-	shll $3,%ecx
-	shrl %cl,%ebx
-	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
-	addl %ebx,%eax
-	adcl $0,%eax
-80: 
-	popl %ebx
-	popl %esi
-	ret
-				
-#endif
-
-/*
-unsigned int csum_partial_copy_generic (const char *src, char *dst,
-				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
- */ 
-
-/*
- * Copy from ds while checksumming, otherwise like csum_partial
- *
- * The macros SRC and DST specify the type of access for the instruction.
- * thus we can call a custom exception handler for all access types.
- *
- * FIXME: could someone double-check whether I haven't mixed up some SRC and
- *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
- *	  them all but there's no guarantee.
- */
-
-#define SRC(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6001f	;	\
-	.previous
-
-#define DST(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6002f	;	\
-	.previous
-
-.align 4
-
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-#define ARGBASE 16		
-#define FP		12
-
-csum_partial_copy_generic_i386:
-	subl  $4,%esp	
-	pushl %edi
-	pushl %esi
-	pushl %ebx
-	movl ARGBASE+16(%esp),%eax	# sum
-	movl ARGBASE+12(%esp),%ecx	# len
-	movl ARGBASE+4(%esp),%esi	# src
-	movl ARGBASE+8(%esp),%edi	# dst
-
-	testl $2, %edi			# Check alignment. 
-	jz 2f				# Jump if alignment is ok.
-	subl $2, %ecx			# Alignment uses up two bytes.
-	jae 1f				# Jump if we had at least two bytes.
-	addl $2, %ecx			# ecx was < 2.  Deal with it.
-	jmp 4f
-SRC(1:	movw (%esi), %bx	)
-	addl $2, %esi
-DST(	movw %bx, (%edi)	)
-	addl $2, %edi
-	addw %bx, %ax	
-	adcl $0, %eax
-2:
-	movl %ecx, FP(%esp)
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-SRC(1:	movl (%esi), %ebx	)
-SRC(	movl 4(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 4(%edi)	)
-
-SRC(	movl 8(%esi), %ebx	)
-SRC(	movl 12(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 8(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 12(%edi)	)
-
-SRC(	movl 16(%esi), %ebx 	)
-SRC(	movl 20(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 16(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 20(%edi)	)
-
-SRC(	movl 24(%esi), %ebx	)
-SRC(	movl 28(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 24(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 28(%edi)	)
-
-	lea 32(%esi), %esi
-	lea 32(%edi), %edi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl FP(%esp), %edx
-	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx			# This clears CF
-SRC(3:	movl (%esi), %ebx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	lea 4(%esi), %esi
-	lea 4(%edi), %edi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-SRC(	movw (%esi), %cx	)
-	leal 2(%esi), %esi
-DST(	movw %cx, (%edi)	)
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%ecx
-SRC(5:	movb (%esi), %cl	)
-DST(	movb %cl, (%edi)	)
-6:	addl %ecx, %eax
-	adcl $0, %eax
-7:
-5000:
-
-# Exception handler:
-.section .fixup, "ax"							
-
-6001:
-	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
-	movl $-EFAULT, (%ebx)
-
-	# zero the complete destination - computing the rest
-	# is too much work 
-	movl ARGBASE+8(%esp), %edi	# dst
-	movl ARGBASE+12(%esp), %ecx	# len
-	xorl %eax,%eax
-	rep ; stosb
-
-	jmp 5000b
-
-6002:
-	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT,(%ebx)
-	jmp 5000b
-
-.previous
-
-	popl %ebx
-	popl %esi
-	popl %edi
-	popl %ecx			# equivalent to addl $4,%esp
-	ret	
-
-#else
-
-/* Version for PentiumII/PPro */
-
-#define ROUND1(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	; 
-
-#define ROUND(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	adcl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	;
-
-#define ARGBASE 12
-		
-csum_partial_copy_generic_i386:
-	pushl %ebx
-	pushl %edi
-	pushl %esi
-	movl ARGBASE+4(%esp),%esi	#src
-	movl ARGBASE+8(%esp),%edi	#dst	
-	movl ARGBASE+12(%esp),%ecx	#len
-	movl ARGBASE+16(%esp),%eax	#sum
-#	movl %ecx, %edx  
-	movl %ecx, %ebx  
-	movl %esi, %edx
-	shrl $6, %ecx     
-	andl $0x3c, %ebx  
-	negl %ebx
-	subl %ebx, %esi  
-	subl %ebx, %edi  
-	lea  -1(%esi),%edx
-	andl $-32,%edx
-	lea 3f(%ebx,%ebx), %ebx
-	testl %esi, %esi 
-	jmp *%ebx
-1:	addl $64,%esi
-	addl $64,%edi 
-	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
-	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
-	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
-	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
-	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
-3:	adcl $0,%eax
-	addl $64, %edx
-	dec %ecx
-	jge 1b
-4:	movl ARGBASE+12(%esp),%edx	#len
-	andl $3, %edx
-	jz 7f
-	cmpl $2, %edx
-	jb 5f
-SRC(	movw (%esi), %dx         )
-	leal 2(%esi), %esi
-DST(	movw %dx, (%edi)         )
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%edx
-5:
-SRC(	movb (%esi), %dl         )
-DST(	movb %dl, (%edi)         )
-6:	addl %edx, %eax
-	adcl $0, %eax
-7:
-.section .fixup, "ax"
-6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
-	movl $-EFAULT, (%ebx)
-	# zero the complete destination (computing the rest is too much work)
-	movl ARGBASE+8(%esp),%edi	# dst
-	movl ARGBASE+12(%esp),%ecx	# len
-	xorl %eax,%eax
-	rep; stosb
-	jmp 7b
-6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT, (%ebx)
-	jmp  7b			
-.previous				
-
-	popl %esi
-	popl %edi
-	popl %ebx
-	ret
-				
-#undef ROUND
-#undef ROUND1		
-		
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/delay.c linux-libre-3.2-gnu1/arch/um/sys-i386/delay.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/delay.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.c
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/elfcore.c linux-libre-3.2-gnu1/arch/um/sys-i386/elfcore.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/elfcore.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/elfcore.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-#include <linux/elf.h>
-#include <linux/coredump.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-
-#include <asm/elf.h>
-
-
-Elf32_Half elf_core_extra_phdrs(void)
-{
-	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
-}
-
-int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			       unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-		Elf32_Off ofs = 0;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			struct elf_phdr phdr = phdrp[i];
-
-			if (phdr.p_type == PT_LOAD) {
-				ofs = phdr.p_offset = offset;
-				offset += phdr.p_filesz;
-			} else {
-				phdr.p_offset += ofs;
-			}
-			phdr.p_paddr = 0; /* match other core phdrs */
-			*size += sizeof(phdr);
-			if (*size > limit
-			    || !dump_write(file, &phdr, sizeof(phdr)))
-				return 0;
-		}
-	}
-	return 1;
-}
-
-int elf_core_write_extra_data(struct file *file, size_t *size,
-			      unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			if (phdrp[i].p_type == PT_LOAD) {
-				void *addr = (void *) phdrp[i].p_vaddr;
-				size_t filesz = phdrp[i].p_filesz;
-
-				*size += filesz;
-				if (*size > limit
-				    || !dump_write(file, addr, filesz))
-					return 0;
-			}
-		}
-	}
-	return 1;
-}
-
-size_t elf_core_extra_data_size(void)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *)vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i)
-			if (phdrp[i].p_type == PT_LOAD)
-				return (size_t) phdrp[i].p_filesz;
-	}
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/fault.c linux-libre-3.2-gnu1/arch/um/sys-i386/fault.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/fault.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/ksyms.c linux-libre-3.2-gnu1/arch/um/sys-i386/ksyms.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/ksyms.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#include "linux/module.h"
-#include "asm/checksum.h"
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/ldt.c linux-libre-3.2-gnu1/arch/um/sys-i386/ldt.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/ldt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/ldt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <asm/unistd.h>
-#include "os.h"
-#include "proc_mm.h"
-#include "skas.h"
-#include "skas_ptrace.h"
-#include "sysdep/tls.h"
-
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-static long write_ldt_entry(struct mm_id *mm_idp, int func,
-		     struct user_desc *desc, void **addr, int done)
-{
-	long res;
-
-	if (proc_mm) {
-		/*
-		 * This is a special handling for the case, that the mm to
-		 * modify isn't current->active_mm.
-		 * If this is called directly by modify_ldt,
-		 *     (current->active_mm->context.skas.u == mm_idp)
-		 * will be true. So no call to __switch_mm(mm_idp) is done.
-		 * If this is called in case of init_new_ldt or PTRACE_LDT,
-		 * mm_idp won't belong to current->active_mm, but child->mm.
-		 * So we need to switch child's mm into our userspace, then
-		 * later switch back.
-		 *
-		 * Note: I'm unsure: should interrupts be disabled here?
-		 */
-		if (!current->active_mm || current->active_mm == &init_mm ||
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(mm_idp);
-	}
-
-	if (ptrace_ldt) {
-		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
-			.func = func,
-			.ptr = desc,
-			.bytecount = sizeof(*desc)};
-		u32 cpu;
-		int pid;
-
-		if (!proc_mm)
-			pid = mm_idp->u.pid;
-		else {
-			cpu = get_cpu();
-			pid = userspace_pid[cpu];
-		}
-
-		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
-
-		if (proc_mm)
-			put_cpu();
-	}
-	else {
-		void *stub_addr;
-		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
-					(sizeof(*desc) + sizeof(long) - 1) &
-					    ~(sizeof(long) - 1),
-					addr, &stub_addr);
-		if (!res) {
-			unsigned long args[] = { func,
-						 (unsigned long)stub_addr,
-						 sizeof(*desc),
-						 0, 0, 0 };
-			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
-					       0, addr, done);
-		}
-	}
-
-	if (proc_mm) {
-		/*
-		 * This is the second part of special handling, that makes
-		 * PTRACE_LDT possible to implement.
-		 */
-		if (current->active_mm && current->active_mm != &init_mm &&
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(&current->active_mm->context.id);
-	}
-
-	return res;
-}
-
-static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
-{
-	int res, n;
-	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
-			.func = 0,
-			.bytecount = bytecount,
-			.ptr = kmalloc(bytecount, GFP_KERNEL)};
-	u32 cpu;
-
-	if (ptrace_ldt.ptr == NULL)
-		return -ENOMEM;
-
-	/*
-	 * This is called from sys_modify_ldt only, so userspace_pid gives
-	 * us the right number
-	 */
-
-	cpu = get_cpu();
-	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
-	put_cpu();
-	if (res < 0)
-		goto out;
-
-	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
-	if (n != 0)
-		res = -EFAULT;
-
-  out:
-	kfree(ptrace_ldt.ptr);
-
-	return res;
-}
-
-/*
- * In skas mode, we hold our own ldt data in UML.
- * Thus, the code implementing sys_modify_ldt_skas
- * is very similar to (and mostly stolen from) sys_modify_ldt
- * for arch/i386/kernel/ldt.c
- * The routines copied and modified in part are:
- * - read_ldt
- * - read_default_ldt
- * - write_ldt
- * - sys_modify_ldt_skas
- */
-
-static int read_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int i, err = 0;
-	unsigned long size;
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-
-	if (!ldt->entry_count)
-		goto out;
-	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
-		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
-	err = bytecount;
-
-	if (ptrace_ldt)
-		return read_ldt_from_host(ptr, bytecount);
-
-	mutex_lock(&ldt->lock);
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
-		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
-		if (size > bytecount)
-			size = bytecount;
-		if (copy_to_user(ptr, ldt->u.entries, size))
-			err = -EFAULT;
-		bytecount -= size;
-		ptr += size;
-	}
-	else {
-		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
-		     i++) {
-			size = PAGE_SIZE;
-			if (size > bytecount)
-				size = bytecount;
-			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
-				err = -EFAULT;
-				break;
-			}
-			bytecount -= size;
-			ptr += size;
-		}
-	}
-	mutex_unlock(&ldt->lock);
-
-	if (bytecount == 0 || err == -EFAULT)
-		goto out;
-
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-out:
-	return err;
-}
-
-static int read_default_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int err;
-
-	if (bytecount > 5*LDT_ENTRY_SIZE)
-		bytecount = 5*LDT_ENTRY_SIZE;
-
-	err = bytecount;
-	/*
-	 * UML doesn't support lcall7 and lcall27.
-	 * So, we don't really have a default ldt, but emulate
-	 * an empty ldt of common host default ldt size.
-	 */
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-	return err;
-}
-
-static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
-{
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-	struct mm_id * mm_idp = &current->mm->context.id;
-	int i, err;
-	struct user_desc ldt_info;
-	struct ldt_entry entry0, *ldt_p;
-	void *addr = NULL;
-
-	err = -EINVAL;
-	if (bytecount != sizeof(ldt_info))
-		goto out;
-	err = -EFAULT;
-	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
-		goto out;
-
-	err = -EINVAL;
-	if (ldt_info.entry_number >= LDT_ENTRIES)
-		goto out;
-	if (ldt_info.contents == 3) {
-		if (func == 1)
-			goto out;
-		if (ldt_info.seg_not_present == 0)
-			goto out;
-	}
-
-	if (!ptrace_ldt)
-		mutex_lock(&ldt->lock);
-
-	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
-	if (err)
-		goto out_unlock;
-	else if (ptrace_ldt) {
-		/* With PTRACE_LDT available, this is used as a flag only */
-		ldt->entry_count = 1;
-		goto out;
-	}
-
-	if (ldt_info.entry_number >= ldt->entry_count &&
-	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
-		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
-		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
-		     i++) {
-			if (i == 0)
-				memcpy(&entry0, ldt->u.entries,
-				       sizeof(entry0));
-			ldt->u.pages[i] = (struct ldt_entry *)
-				__get_free_page(GFP_KERNEL|__GFP_ZERO);
-			if (!ldt->u.pages[i]) {
-				err = -ENOMEM;
-				/* Undo the change in host */
-				memset(&ldt_info, 0, sizeof(ldt_info));
-				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
-				goto out_unlock;
-			}
-			if (i == 0) {
-				memcpy(ldt->u.pages[0], &entry0,
-				       sizeof(entry0));
-				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
-				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
-			}
-			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
-		}
-	}
-	if (ldt->entry_count <= ldt_info.entry_number)
-		ldt->entry_count = ldt_info.entry_number + 1;
-
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
-		ldt_p = ldt->u.entries + ldt_info.entry_number;
-	else
-		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
-			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
-
-	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
-	   (func == 1 || LDT_empty(&ldt_info))) {
-		ldt_p->a = 0;
-		ldt_p->b = 0;
-	}
-	else{
-		if (func == 1)
-			ldt_info.useable = 0;
-		ldt_p->a = LDT_entry_a(&ldt_info);
-		ldt_p->b = LDT_entry_b(&ldt_info);
-	}
-	err = 0;
-
-out_unlock:
-	mutex_unlock(&ldt->lock);
-out:
-	return err;
-}
-
-static long do_modify_ldt_skas(int func, void __user *ptr,
-			       unsigned long bytecount)
-{
-	int ret = -ENOSYS;
-
-	switch (func) {
-		case 0:
-			ret = read_ldt(ptr, bytecount);
-			break;
-		case 1:
-		case 0x11:
-			ret = write_ldt(ptr, bytecount, func);
-			break;
-		case 2:
-			ret = read_default_ldt(ptr, bytecount);
-			break;
-	}
-	return ret;
-}
-
-static DEFINE_SPINLOCK(host_ldt_lock);
-static short dummy_list[9] = {0, -1};
-static short * host_ldt_entries = NULL;
-
-static void ldt_get_host_info(void)
-{
-	long ret;
-	struct ldt_entry * ldt;
-	short *tmp;
-	int i, size, k, order;
-
-	spin_lock(&host_ldt_lock);
-
-	if (host_ldt_entries != NULL) {
-		spin_unlock(&host_ldt_lock);
-		return;
-	}
-	host_ldt_entries = dummy_list+1;
-
-	spin_unlock(&host_ldt_lock);
-
-	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
-		;
-
-	ldt = (struct ldt_entry *)
-	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
-	if (ldt == NULL) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
-		       "for host ldt\n");
-		return;
-	}
-
-	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
-	if (ret < 0) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
-		goto out_free;
-	}
-	if (ret == 0) {
-		/* default_ldt is active, simply write an empty entry 0 */
-		host_ldt_entries = dummy_list;
-		goto out_free;
-	}
-
-	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			size++;
-	}
-
-	if (size < ARRAY_SIZE(dummy_list))
-		host_ldt_entries = dummy_list;
-	else {
-		size = (size + 1) * sizeof(dummy_list[0]);
-		tmp = kmalloc(size, GFP_KERNEL);
-		if (tmp == NULL) {
-			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
-			       "host ldt list\n");
-			goto out_free;
-		}
-		host_ldt_entries = tmp;
-	}
-
-	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			host_ldt_entries[k++] = i;
-	}
-	host_ldt_entries[k] = -1;
-
-out_free:
-	free_pages((unsigned long)ldt, order);
-}
-
-long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
-{
-	struct user_desc desc;
-	short * num_p;
-	int i;
-	long page, err=0;
-	void *addr = NULL;
-	struct proc_mm_op copy;
-
-
-	if (!ptrace_ldt)
-		mutex_init(&new_mm->ldt.lock);
-
-	if (!from_mm) {
-		memset(&desc, 0, sizeof(desc));
-		/*
-		 * We have to initialize a clean ldt.
-		 */
-		if (proc_mm) {
-			/*
-			 * If the new mm was created using proc_mm, host's
-			 * default-ldt currently is assigned, which normally
-			 * contains the call-gates for lcall7 and lcall27.
-			 * To remove these gates, we simply write an empty
-			 * entry as number 0 to the host.
-			 */
-			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
-		}
-		else{
-			/*
-			 * Now we try to retrieve info about the ldt, we
-			 * inherited from the host. All ldt-entries found
-			 * will be reset in the following loop
-			 */
-			ldt_get_host_info();
-			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
-				desc.entry_number = *num_p;
-				err = write_ldt_entry(&new_mm->id, 1, &desc,
-						      &addr, *(num_p + 1) == -1);
-				if (err)
-					break;
-			}
-		}
-		new_mm->ldt.entry_count = 0;
-
-		goto out;
-	}
-
-	if (proc_mm) {
-		/*
-		 * We have a valid from_mm, so we now have to copy the LDT of
-		 * from_mm to new_mm, because using proc_mm an new mm with
-		 * an empty/default LDT was created in new_mm()
-		 */
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	=
-					      { .copy_segments =
-							from_mm->id.u.mm_fd } } );
-		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
-		if (i != sizeof(copy))
-			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
-			       "failed, err = %d\n", -i);
-	}
-
-	if (!ptrace_ldt) {
-		/*
-		 * Our local LDT is used to supply the data for
-		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
-		 * i.e., we have to use the stub for modify_ldt, which
-		 * can't handle the big read buffer of up to 64kB.
-		 */
-		mutex_lock(&from_mm->ldt.lock);
-		if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
-			memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
-			       sizeof(new_mm->ldt.u.entries));
-		else {
-			i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-			while (i-->0) {
-				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
-				if (!page) {
-					err = -ENOMEM;
-					break;
-				}
-				new_mm->ldt.u.pages[i] =
-					(struct ldt_entry *) page;
-				memcpy(new_mm->ldt.u.pages[i],
-				       from_mm->ldt.u.pages[i], PAGE_SIZE);
-			}
-		}
-		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
-		mutex_unlock(&from_mm->ldt.lock);
-	}
-
-    out:
-	return err;
-}
-
-
-void free_ldt(struct mm_context *mm)
-{
-	int i;
-
-	if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
-		i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-		while (i-- > 0)
-			free_page((long) mm->ldt.u.pages[i]);
-	}
-	mm->ldt.entry_count = 0;
-}
-
-int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
-{
-	return do_modify_ldt_skas(func, ptr, bytecount);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/Makefile linux-libre-3.2-gnu1/arch/um/sys-i386/Makefile
--- linux-libre-3.1-gnu1/arch/um/sys-i386/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-#
-
-obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
-	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-	sys_call_table.o tls.o atomic64_cx8_32.o mem.o
-
-obj-$(CONFIG_BINFMT_ELF) += elfcore.o
-
-subarch-obj-y = lib/string_32.o
-subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o
-subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-USER_OBJS := bugs.o ptrace_user.o fault.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/mem.c linux-libre-3.2-gnu1/arch/um/sys-i386/mem.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/mem.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * 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/mm.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-static struct vm_area_struct gate_vma;
-
-static int __init gate_vma_init(void)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	gate_vma.vm_mm = NULL;
-	gate_vma.vm_start = FIXADDR_USER_START;
-	gate_vma.vm_end = FIXADDR_USER_END;
-	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
-	gate_vma.vm_page_prot = __P101;
-
-	/*
-	 * Make sure the vDSO gets into every core dump.
-	 * Dumping its contents makes post-mortem fully interpretable later
-	 * without matching up the same kernel and hardware config to see
-	 * what PC values meant.
-	 */
-	gate_vma.vm_flags |= VM_ALWAYSDUMP;
-
-	return 0;
-}
-__initcall(gate_vma_init);
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return FIXADDR_USER_START ? &gate_vma : NULL;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
-		return 1;
-
-	return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	struct vm_area_struct *vma = get_gate_vma(mm);
-
-	if (!vma)
-		return 0;
-
-	return (addr >= vma->vm_start) && (addr < vma->vm_end);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/ptrace.c linux-libre-3.2-gnu1/arch/um/sys-i386/ptrace.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/ptrace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "skas.h"
-
-extern int arch_switch_tls(struct task_struct *to);
-
-void arch_switch_to(struct task_struct *to)
-{
-	int err = arch_switch_tls(to);
-	if (!err)
-		return;
-
-	if (err != -EINVAL)
-		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
-		       "not EINVAL\n", -err);
-	else
-		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
-}
-
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/* access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk(KERN_ERR "is_syscall : failed to read "
-			       "instruction from 0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* int 0x80 or sysenter */
-	return (instr == 0x80cd) || (instr == 0x340f);
-}
-
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_FS(&child->thread.regs) = value;
-		return 0;
-	case GS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_GS(&child->thread.regs) = value;
-		return 0;
-	case DS:
-	case ES:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case SS:
-	case CS:
-		if ((value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case EFL:
-		value &= FLAG_MASK;
-		value |= PT_REGS_EFLAGS(&child->thread.regs);
-		break;
-	}
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-	}
-	return retval;
-}
-
-/* read the word at location addr in the USER area. */
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET) {
-		tmp = getreg(child, addr);
-	}
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long __user *) data);
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu],
-				    (unsigned long *) &fpregs);
-}
-
-static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fpx_registers(userspace_pid[cpu],
-				     (unsigned long *) &fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
-		ret = get_fpxregs(datap, child);
-		break;
-	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
-		ret = set_fpxregs(datap, child);
-		break;
-	default:
-		ret = -EIO;
-	}
-	return ret;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/ptrace_user.c linux-libre-3.2-gnu1/arch/um/sys-i386/ptrace_user.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/ptrace_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return 0;
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
-		return -errno;
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/setjmp.S linux-libre-3.2-gnu1/arch/um/sys-i386/setjmp.S
--- linux-libre-3.1-gnu1/arch/um/sys-i386/setjmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/setjmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-#
-# arch/i386/setjmp.S
-#
-# setjmp/longjmp for the i386 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%ebx
-#	%esp
-#	%ebp
-#	%esi
-#	%edi
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-#ifdef _REGPARM
-	movl %eax,%edx
-#else
-	movl 4(%esp),%edx
-#endif
-	popl %ecx			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movl %ebx,(%edx)
-	movl %esp,4(%edx)		# Post-return %esp!
-	pushl %ecx			# Make the call/return stack happy
-	movl %ebp,8(%edx)
-	movl %esi,12(%edx)
-	movl %edi,16(%edx)
-	movl %ecx,20(%edx)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-#ifdef _REGPARM
-	xchgl %eax,%edx
-#else
-	movl 4(%esp),%edx		# jmp_ptr address
-	movl 8(%esp),%eax		# Return value
-#endif
-	movl (%edx),%ebx
-	movl 4(%edx),%esp
-	movl 8(%edx),%ebp
-	movl 12(%edx),%esi
-	movl 16(%edx),%edi
-	jmp *20(%edx)
-
-	.size longjmp,.-longjmp
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/archsetjmp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * arch/um/include/sysdep-i386/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned int __ebx;
-	unsigned int __esp;
-	unsigned int __ebp;
-	unsigned int __esi;
-	unsigned int __edi;
-	unsigned int __eip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __eip
-#define JB_SP __esp
-
-#endif				/* _SETJMP_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/barrier.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/barrier.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/barrier.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/barrier.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __SYSDEP_I386_BARRIER_H
-#define __SYSDEP_I386_BARRIER_H
-
-/* Copied from include/asm-i386 for use by userspace.  i386 has the option
- * of using mfence, but I'm just using this, which works everywhere, for now.
- */
-#define mb() asm volatile("lock; addl $0,0(%esp)")
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/checksum.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/checksum.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-/* 
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/in6.h"
-#include "linux/string.h"
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-					 int len, __wsum sum, int *err_ptr)
-{
-	if (copy_from_user(dst, src, len)) {
-		*err_ptr = -EFAULT;
-		return (__force __wsum)-1;
-	}
-
-	return csum_partial(dst, len, sum);
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- *
- *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
- *	Arnt Gulbrandsen.
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	__asm__ __volatile__(
-	    "movl (%1), %0	;\n"
-	    "subl $4, %2	;\n"
-	    "jbe 2f		;\n"
-	    "addl 4(%1), %0	;\n"
-	    "adcl 8(%1), %0	;\n"
-	    "adcl 12(%1), %0	;\n"
-"1:	    adcl 16(%1), %0	;\n"
-	    "lea 4(%1), %1	;\n"
-	    "decl %2		;\n"
-	    "jne 1b		;\n"
-	    "adcl $0, %0	;\n"
-	    "movl %0, %2	;\n"
-	    "shrl $16, %0	;\n"
-	    "addw %w2, %w0	;\n"
-	    "adcl $0, %0	;\n"
-	    "notl %0		;\n"
-"2:				;\n"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"addl %1, %0		;\n"
-		"adcl $0xffff, %0	;\n"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-    __asm__(
-	"addl %1, %0	;\n"
-	"adcl %2, %0	;\n"
-	"adcl %3, %0	;\n"
-	"adcl $0, %0	;\n"
-	: "=r" (sum)
-	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
-    return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-    return csum_fold (csum_partial(buff, len, 0));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-					  const struct in6_addr *daddr,
-					  __u32 len, unsigned short proto,
-					  __wsum sum)
-{
-	__asm__(
-		"addl 0(%1), %0		;\n"
-		"adcl 4(%1), %0		;\n"
-		"adcl 8(%1), %0		;\n"
-		"adcl 12(%1), %0	;\n"
-		"adcl 0(%2), %0		;\n"
-		"adcl 4(%2), %0		;\n"
-		"adcl 8(%2), %0		;\n"
-		"adcl 12(%2), %0	;\n"
-		"adcl %3, %0		;\n"
-		"adcl %4, %0		;\n"
-		"adcl $0, %0		;\n"
-		: "=&r" (sum)
-		: "r" (saddr), "r" (daddr),
-		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
-
-	return csum_fold(sum);
-}
-
-/*
- *	Copy and checksum to user
- */
-#define HAVE_CSUM_COPY_USER
-static __inline__ __wsum csum_and_copy_to_user(const void *src,
-						     void __user *dst,
-						     int len, __wsum sum, int *err_ptr)
-{
-	if (access_ok(VERIFY_WRITE, dst, len)) {
-		if (copy_to_user(dst, src, len)) {
-			*err_ptr = -EFAULT;
-			return (__force __wsum)-1;
-		}
-
-		return csum_partial(src, len, sum);
-	}
-
-	if (len)
-		*err_ptr = -EFAULT;
-
-	return (__force __wsum)-1; /* invalid checksum */
-}
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/faultinfo.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/faultinfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_I386_H
-#define __FAULTINFO_I386_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 0
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/host_ldt.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/host_ldt.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/host_ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/host_ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-#ifndef __ASM_HOST_LDT_I386_H
-#define __ASM_HOST_LDT_I386_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/kernel-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/ptrace.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_H
-#define __SYSDEP_I386_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-
-static inline void update_debugregs(int seq) {}
-
-/* syscall emulation path in ptrace */
-
-#ifndef PTRACE_SYSEMU
-#define PTRACE_SYSEMU 31
-#endif
-
-void set_using_sysemu(int value);
-int get_using_sysemu(void);
-extern int sysemu_supported;
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_EAX])
-#define REGS_EBX(r) ((r)[HOST_EBX])
-#define REGS_ECX(r) ((r)[HOST_ECX])
-#define REGS_EDX(r) ((r)[HOST_EDX])
-#define REGS_ESI(r) ((r)[HOST_ESI])
-#define REGS_EDI(r) ((r)[HOST_EDI])
-#define REGS_EBP(r) ((r)[HOST_EBP])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_SS(r) ((r)[HOST_SS])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#ifndef PTRACE_SYSEMU_SINGLESTEP
-#define PTRACE_SYSEMU_SINGLESTEP 32
-#endif
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FPX_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_EAX(r) REGS_EAX((r)->gp)
-#define UPT_EBX(r) REGS_EBX((r)->gp)
-#define UPT_ECX(r) REGS_ECX((r)->gp)
-#define UPT_EDX(r) REGS_EDX((r)->gp)
-#define UPT_ESI(r) REGS_ESI((r)->gp)
-#define UPT_EDI(r) REGS_EDI((r)->gp)
-#define UPT_EBP(r) REGS_EBP((r)->gp)
-#define UPT_ORIG_EAX(r) ((r)->syscall)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-
-#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
-#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
-#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
-#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
-#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	\
-				     UPT_SYSCALL_ARG2(r),	\
-				     UPT_SYSCALL_ARG3(r),	\
-				     UPT_SYSCALL_ARG4(r),	\
-				     UPT_SYSCALL_ARG5(r),	\
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({	unsigned long val; \
-		switch(reg){ \
-		case EIP: val = UPT_IP(regs); break; \
-		case UESP: val = UPT_SP(regs); break; \
-		case EAX: val = UPT_EAX(regs); break; \
-		case EBX: val = UPT_EBX(regs); break; \
-		case ECX: val = UPT_ECX(regs); break; \
-		case EDX: val = UPT_EDX(regs); break; \
-		case ESI: val = UPT_ESI(regs); break; \
-		case EDI: val = UPT_EDI(regs); break; \
-		case EBP: val = UPT_EBP(regs); break; \
-		case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \
-		case CS: val = UPT_CS(regs); break; \
-		case SS: val = UPT_SS(regs); break; \
-		case DS: val = UPT_DS(regs); break; \
-		case ES: val = UPT_ES(regs); break; \
-		case FS: val = UPT_FS(regs); break; \
-		case GS: val = UPT_GS(regs); break; \
-		case EFL: val = UPT_EFLAGS(regs); break; \
-		default :  \
-			panic("Bad register in UPT_REG : %d\n", reg);  \
-			val = -1; \
-		} \
-	        val; \
-	})
-
-#define UPT_SET(regs, reg, val) \
-	do { \
-		switch(reg){ \
-		case EIP: UPT_IP(regs) = val; break; \
-		case UESP: UPT_SP(regs) = val; break; \
-		case EAX: UPT_EAX(regs) = val; break; \
-		case EBX: UPT_EBX(regs) = val; break; \
-		case ECX: UPT_ECX(regs) = val; break; \
-		case EDX: UPT_EDX(regs) = val; break; \
-		case ESI: UPT_ESI(regs) = val; break; \
-		case EDI: UPT_EDI(regs) = val; break; \
-		case EBP: UPT_EBP(regs) = val; break; \
-		case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \
-		case CS: UPT_CS(regs) = val; break; \
-		case SS: UPT_SS(regs) = val; break; \
-		case DS: UPT_DS(regs) = val; break; \
-		case ES: UPT_ES(regs) = val; break; \
-		case FS: UPT_FS(regs) = val; break; \
-		case GS: UPT_GS(regs) = val; break; \
-		case EFL: UPT_EFLAGS(regs) = val; break; \
-		default :  \
-			panic("Bad register in UPT_SET : %d\n", reg);  \
-			break; \
-		} \
-	} while (0)
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
-#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
-#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-extern void arch_init_registers(int pid);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_USER_H__
-#define __SYSDEP_I386_PTRACE_USER_H__
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#include "user_constants.h"
-
-#define PT_OFFSET(r) ((r) * sizeof(long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX])
-#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX)
-
-#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX)
-#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX)
-#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
-#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
-#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
-#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
-
-#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
-
-#define REGS_SYSCALL_NR EAX /* This is used before a system call */
-#define REGS_SYSCALL_ARG1 EBX
-#define REGS_SYSCALL_ARG2 ECX
-#define REGS_SYSCALL_ARG3 EDX
-#define REGS_SYSCALL_ARG4 ESI
-#define REGS_SYSCALL_ARG5 EDI
-#define REGS_SYSCALL_ARG6 EBP
-
-#define REGS_IP_INDEX EIP
-#define REGS_SP_INDEX UESP
-
-#define PT_IP_OFFSET PT_OFFSET(EIP)
-#define PT_IP(regs) ((regs)[EIP])
-#define PT_SP_OFFSET PT_OFFSET(UESP)
-#define PT_SP(regs) ((regs)[UESP])
-
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-
-#ifndef FRAME_SIZE
-#define FRAME_SIZE (17)
-#endif
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/sc.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/sc.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/sc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/sc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-#ifndef __SYSDEP_I386_SC_H
-#define __SYSDEP_I386_SC_H
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (sc))[HOST_##field]))
-#define SC_FP_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-#define SC_FP_OFFSET_PTR(sc, field, type) \
-	((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX)
-#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX)
-#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX)
-#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX)
-#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI)
-#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI)
-#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW)
-#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW)
-#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG)
-#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF)
-#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL)
-#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF)
-#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL)
-#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate)
-#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/sigcontext.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/sigcontext.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYS_SIGCONTEXT_I386_H
-#define __SYS_SIGCONTEXT_I386_H
-
-#include "sysdep/sc.h"
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/skas_ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_SKAS_PTRACE_H
-#define __SYSDEP_I386_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/stub.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/stub.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/stub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET EAX
-#define STUB_MMAP_NR __NR_mmap2
-#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
-
-	return ret;
-}
-
-static inline long stub_syscall1(long syscall, long arg1)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2));
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3));
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4));
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(int fd, unsigned long offset)
-{
-	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
-			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
-			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
-			    "c" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
-			    "a" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : "memory");
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/syscalls.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/syscalls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "asm/unistd.h"
-#include "sysdep/ptrace.h"
-
-typedef long syscall_handler_t(struct pt_regs);
-
-/* Not declared on x86, incompatible declarations on x86_64, so these have
- * to go here rather than in sys_call_table.c
- */
-extern syscall_handler_t sys_rt_sigaction;
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	((long (*)(struct syscall_args)) \
-	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/system.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/system.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/tls.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/tls.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/tls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-
-#define GDT_ENTRY_TLS_MIN_I386 6
-#define GDT_ENTRY_TLS_MIN_X86_64 12
-
-#endif /* _SYSDEP_TLS_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/vm-flags.h linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/vm-flags.h
--- linux-libre-3.1-gnu1/arch/um/sys-i386/shared/sysdep/vm-flags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/shared/sysdep/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_I386_H
-#define __VM_FLAGS_I386_H
-
-#define VM_DATA_DEFAULT_FLAGS \
-	(VM_READ | VM_WRITE | \
-	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
-		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/signal.c linux-libre-3.2-gnu1/arch/um/sys-i386/signal.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/ptrace.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-	REGS_GS(regs->gp) = sc->gs;
-	REGS_FS(regs->gp) = sc->fs;
-	REGS_ES(regs->gp) = sc->es;
-	REGS_DS(regs->gp) = sc->ds;
-	REGS_EDI(regs->gp) = sc->di;
-	REGS_ESI(regs->gp) = sc->si;
-	REGS_EBP(regs->gp) = sc->bp;
-	REGS_SP(regs->gp) = sc->sp;
-	REGS_EBX(regs->gp) = sc->bx;
-	REGS_EDX(regs->gp) = sc->dx;
-	REGS_ECX(regs->gp) = sc->cx;
-	REGS_EAX(regs->gp) = sc->ax;
-	REGS_IP(regs->gp) = sc->ip;
-	REGS_CS(regs->gp) = sc->cs;
-	REGS_EFLAGS(regs->gp) = sc->flags;
-	REGS_SS(regs->gp) = sc->ss;
-}
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
-{
-	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
-	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
-	tmp = ~twd;
-	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
-	/* and move the valid bits to the lower byte. */
-	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
-	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
-	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
-	return tmp;
-}
-
-static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
-{
-	struct _fpxreg *st = NULL;
-	unsigned long twd = (unsigned long) fxsave->twd;
-	unsigned long tag;
-	unsigned long ret = 0xffff0000;
-	int i;
-
-#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
-
-	for (i = 0; i < 8; i++) {
-		if (twd & 0x1) {
-			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
-
-			switch (st->exponent & 0x7fff) {
-			case 0x7fff:
-				tag = 2;		/* Special */
-				break;
-			case 0x0000:
-				if ( !st->significand[0] &&
-				     !st->significand[1] &&
-				     !st->significand[2] &&
-				     !st->significand[3] ) {
-					tag = 1;	/* Zero */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			default:
-				if (st->significand[3] & 0x8000) {
-					tag = 0;	/* Valid */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			}
-		} else {
-			tag = 3;			/* Empty */
-		}
-		ret |= (tag << (2 * i));
-		twd = twd >> 1;
-	}
-	return ret;
-}
-
-static int convert_fxsr_to_user(struct _fpstate __user *buf,
-				struct user_fxsr_struct *fxsave)
-{
-	unsigned long env[7];
-	struct _fpreg __user *to;
-	struct _fpxreg *from;
-	int i;
-
-	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
-	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
-	env[2] = twd_fxsr_to_i387(fxsave);
-	env[3] = fxsave->fip;
-	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
-	env[5] = fxsave->foo;
-	env[6] = fxsave->fos;
-
-	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
-		return 1;
-
-	to = &buf->_st[0];
-	from = (struct _fpxreg *) &fxsave->st_space[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long __user *t = (unsigned long __user *)to;
-		unsigned long *f = (unsigned long *)from;
-
-		if (__put_user(*f, t) ||
-				__put_user(*(f + 1), t + 1) ||
-				__put_user(from->exponent, &to->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
-				  struct _fpstate __user *buf)
-{
-	unsigned long env[7];
-	struct _fpxreg *to;
-	struct _fpreg __user *from;
-	int i;
-
-	if (copy_from_user( env, buf, 7 * sizeof(long)))
-		return 1;
-
-	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
-	fxsave->swd = (unsigned short)(env[1] & 0xffff);
-	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
-	fxsave->fip = env[3];
-	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
-	fxsave->fcs = (env[4] & 0xffff);
-	fxsave->foo = env[5];
-	fxsave->fos = env[6];
-
-	to = (struct _fpxreg *) &fxsave->st_space[0];
-	from = &buf->_st[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long *t = (unsigned long *)to;
-		unsigned long __user *f = (unsigned long __user *)from;
-
-		if (__get_user(*t, f) ||
-		    __get_user(*(t + 1), f + 1) ||
-		    __get_user(to->exponent, &from->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-extern int have_fpx_regs;
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from)
-{
-	struct sigcontext sc;
-	int err, pid;
-
-	err = copy_from_user(&sc, from, sizeof(sc));
-	if (err)
-		return err;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	copy_sc(&regs->regs, &sc);
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = copy_from_user(&fpx,
-			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
-				     sizeof(struct user_fxsr_struct));
-		if (err)
-			return 1;
-
-		err = convert_fxsr_from_user(&fpx, sc.fpstate);
-		if (err)
-			return 1;
-
-		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fpx_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = copy_from_user(&fp, sc.fpstate,
-				     sizeof(struct user_i387_struct));
-		if (err)
-			return 1;
-
-		err = restore_fp_registers(pid, (unsigned long *) &fp);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fp_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long sp)
-{
-	struct sigcontext sc;
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	int err, pid;
-
-	sc.gs = REGS_GS(regs->regs.gp);
-	sc.fs = REGS_FS(regs->regs.gp);
-	sc.es = REGS_ES(regs->regs.gp);
-	sc.ds = REGS_DS(regs->regs.gp);
-	sc.di = REGS_EDI(regs->regs.gp);
-	sc.si = REGS_ESI(regs->regs.gp);
-	sc.bp = REGS_EBP(regs->regs.gp);
-	sc.sp = sp;
-	sc.bx = REGS_EBX(regs->regs.gp);
-	sc.dx = REGS_EDX(regs->regs.gp);
-	sc.cx = REGS_ECX(regs->regs.gp);
-	sc.ax = REGS_EAX(regs->regs.gp);
-	sc.ip = REGS_IP(regs->regs.gp);
-	sc.cs = REGS_CS(regs->regs.gp);
-	sc.flags = REGS_EFLAGS(regs->regs.gp);
-	sc.sp_at_signal = regs->regs.gp[UESP];
-	sc.ss = regs->regs.gp[SS];
-	sc.cr2 = fi->cr2;
-	sc.err = fi->error_code;
-	sc.trapno = fi->trap_no;
-
-	to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
-	sc.fpstate = to_fp;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = save_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0){
-			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
-			       "failed, errno = %d\n", err);
-			return 1;
-		}
-
-		err = convert_fxsr_to_user(to_fp, &fpx);
-		if (err)
-			return 1;
-
-		err |= __put_user(fpx.swd, &to_fp->status);
-		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
-		if (err)
-			return 1;
-
-		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
-				 sizeof(struct user_fxsr_struct)))
-			return 1;
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = save_fp_registers(pid, (unsigned long *) &fp);
-		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-			return 1;
-	}
-
-	return copy_to_user(to, &sc, sizeof(sc));
-}
-
-static int copy_ucontext_to_user(struct ucontext __user *uc,
-				 struct _fpstate __user *fp, sigset_t *set,
-				 unsigned long sp)
-{
-	int err = 0;
-
-	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
-	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
-	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
-	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
-	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
-	return err;
-}
-
-struct sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct sigcontext sc;
-	struct _fpstate fpstate;
-	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[8];
-};
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct siginfo __user *pinfo;
-	void __user *puc;
-	struct siginfo info;
-	struct ucontext uc;
-	struct _fpstate fpstate;
-	char retcode[8];
-};
-
-int setup_signal_stack_sc(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  sigset_t *mask)
-{
-	struct sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
-	stack_top = ((stack_top + 4) & -16UL) - 4;
-	frame = (struct sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(sig, &frame->sig);
-	err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
-	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
-	if (_NSIG_WORDS > 1)
-		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
-				      sizeof(frame->extramask));
-
-	/*
-	 * This is popl %eax ; movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
-	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
-
-	if (err)
-		goto err;
-
-	PT_REGS_SP(regs) = (unsigned long) frame;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) 0;
-	PT_REGS_ECX(regs) = (unsigned long) 0;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  siginfo_t *info, sigset_t *mask)
-{
-	struct rt_sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	stack_top &= -8UL;
-	frame = (struct rt_sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* See comment above about why this is here */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
-				     save_sp);
-
-	/*
-	 * This is movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
-	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
-
-	if (err)
-		goto err;
-
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
-	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-long sys_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
-	sigset_t set;
-	struct sigcontext __user *sc = &frame->sc;
-	unsigned long __user *oldmask = &sc->oldmask;
-	unsigned long __user *extramask = frame->extramask;
-	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-
-	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
-	    copy_from_user(&set.sig[1], extramask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, sc))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-long sys_rt_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *) (sp - 4);
-	sigset_t set;
-	struct ucontext __user *uc = &frame->uc;
-	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/stub.S linux-libre-3.2-gnu1/arch/um/sys-i386/stub.S
--- linux-libre-3.1-gnu1/arch/um/sys-i386/stub.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/stub.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	/* load pointer to first operation */
-	mov	$(STUB_DATA+8), %esp
-
-again:
-	/* load length of additional data */
-	mov	0x0(%esp), %eax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%eax, STUB_DATA+4
-	cmpl	$0, %eax
-	jz	done
-
-	/* save current pointer */
-	mov	%esp, STUB_DATA+4
-
-	/* skip additional data */
-	add	%eax, %esp
-
-	/* load syscall-# */
-	pop	%eax
-
-	/* load syscall params */
-	pop	%ebx
-	pop	%ecx
-	pop	%edx
-	pop	%esi
- 	pop	%edi
-	pop	%ebp
-
-	/* execute syscall */
-	int	$0x80
-
-	/* check return value */
-	pop	%ebx
-	cmp	%ebx, %eax
-	je	again
-
-done:
-	/* save return value */
-	mov	%eax, STUB_DATA
-
-	/* stop */
-	int3
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/stub_segv.c linux-libre-3.2-gnu1/arch/um/sys-i386/stub_segv.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/stub_segv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/stub.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
-
-	trap_myself();
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/syscalls.c linux-libre-3.2-gnu1/arch/um/sys-i386/syscalls.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/syscalls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
-
-/*
- * The prototype on i386 is:
- *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
- *
- * and the "newtls" arg. on i386 is read by copy_thread directly from the
- * register saved on the stack.
- */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       int __user *parent_tid, void *newtls, int __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-long sys_sigaction(int sig, const struct old_sigaction __user *act,
-			 struct old_sigaction __user *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/sys_call_table.S linux-libre-3.2-gnu1/arch/um/sys-i386/sys_call_table.S
--- linux-libre-3.1-gnu1/arch/um/sys-i386/sys_call_table.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/sys_call_table.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-#include <linux/linkage.h>
-/* Steal i386 syscall table for our purposes, but with some slight changes.*/
-
-#define sys_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-#define sys_vm86old sys_ni_syscall
-#define sys_vm86 sys_ni_syscall
-
-#define old_mmap sys_old_mmap
-
-#define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
-#define ptregs_iopl sys_iopl
-#define ptregs_vm86old sys_vm86old
-#define ptregs_sigreturn sys_sigreturn
-#define ptregs_clone sys_clone
-#define ptregs_vm86 sys_vm86
-#define ptregs_rt_sigreturn sys_rt_sigreturn
-#define ptregs_sigaltstack sys_sigaltstack
-#define ptregs_vfork sys_vfork
-
-.section .rodata,"a"
-
-#include "../../x86/kernel/syscall_table_32.S"
-
-ENTRY(syscall_table_size)
-.long .-sys_call_table
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/sysrq.c linux-libre-3.2-gnu1/arch/um/sys-i386/sysrq.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/sysrq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/sysrq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/smp.h"
-#include "linux/sched.h"
-#include "linux/kallsyms.h"
-#include "asm/ptrace.h"
-#include "sysrq.h"
-
-/* This is declared by <linux/sched.h> */
-void show_regs(struct pt_regs *regs)
-{
-        printk("\n");
-        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
-	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
-	       smp_processor_id(), print_tainted());
-        if (PT_REGS_CS(regs) & 3)
-                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
-		       PT_REGS_SP(regs));
-        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
-	       print_tainted());
-        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
-	       PT_REGS_ECX(regs), 
-	       PT_REGS_EDX(regs));
-        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
-	       PT_REGS_EBP(regs));
-        printk(" DS: %04lx ES: %04lx\n",
-	       0xffff & PT_REGS_DS(regs), 
-	       0xffff & PT_REGS_ES(regs));
-
-        show_trace(NULL, (unsigned long *) &regs);
-}
-
-/* Copied from i386. */
-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
-{
-	return	p > (void *)tinfo &&
-		p < (void *)tinfo + THREAD_SIZE - 3;
-}
-
-/* Adapted from i386 (we also print the address we read from). */
-static inline unsigned long print_context_stack(struct thread_info *tinfo,
-				unsigned long *stack, unsigned long ebp)
-{
-	unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
-	while (valid_stack_ptr(tinfo, (void *)ebp)) {
-		addr = *(unsigned long *)(ebp + 4);
-		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
-		print_symbol(" %s", addr);
-		printk("\n");
-		ebp = *(unsigned long *)ebp;
-	}
-#else
-	while (valid_stack_ptr(tinfo, stack)) {
-		addr = *stack;
-		if (__kernel_text_address(addr)) {
-			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
-			print_symbol(" %s", addr);
-			printk("\n");
-		}
-		stack++;
-	}
-#endif
-	return ebp;
-}
-
-void show_trace(struct task_struct* task, unsigned long * stack)
-{
-	unsigned long ebp;
-	struct thread_info *context;
-
-	/* Turn this into BUG_ON if possible. */
-	if (!stack) {
-		stack = (unsigned long*) &stack;
-		printk("show_trace: got NULL stack, implicit assumption task == current");
-		WARN_ON(1);
-	}
-
-	if (!task)
-		task = current;
-
-	if (task != current) {
-		ebp = (unsigned long) KSTK_EBP(task);
-	} else {
-		asm ("movl %%ebp, %0" : "=r" (ebp) : );
-	}
-
-	context = (struct thread_info *)
-		((unsigned long)stack & (~(THREAD_SIZE - 1)));
-	print_context_stack(context, stack, ebp);
-
-	printk("\n");
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/tls.c linux-libre-3.2-gnu1/arch/um/sys-i386/tls.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
- * Licensed under the GPL
- */
-
-#include "linux/percpu.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "os.h"
-#include "skas.h"
-#include "sysdep/tls.h"
-
-/*
- * If needed we can detect when it's uninitialized.
- *
- * These are initialized in an initcall and unchanged thereafter.
- */
-static int host_supports_tls = -1;
-int host_gdt_entry_tls_min;
-
-int do_set_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_set_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-int do_get_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_get_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-/*
- * sys_get_thread_area: get a yet unused TLS descriptor index.
- * XXX: Consider leaving one free slot for glibc usage at first place. This must
- * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
- *
- * Also, this must be tested when compiling in SKAS mode with dynamic linking
- * and running against NPTL.
- */
-static int get_free_idx(struct task_struct* task)
-{
-	struct thread_struct *t = &task->thread;
-	int idx;
-
-	if (!t->arch.tls_array)
-		return GDT_ENTRY_TLS_MIN;
-
-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (!t->arch.tls_array[idx].present)
-			return idx + GDT_ENTRY_TLS_MIN;
-	return -ESRCH;
-}
-
-static inline void clear_user_desc(struct user_desc* info)
-{
-	/* Postcondition: LDT_empty(info) returns true. */
-	memset(info, 0, sizeof(*info));
-
-	/*
-	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
-	 * indeed an empty user_desc.
-	 */
-	info->read_exec_only = 1;
-	info->seg_not_present = 1;
-}
-
-#define O_FORCE 1
-
-static int load_TLS(int flags, struct task_struct *to)
-{
-	int ret = 0;
-	int idx;
-
-	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
-		struct uml_tls_struct* curr =
-			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Actually, now if it wasn't flushed it gets cleared and
-		 * flushed to the host, which will clear it.
-		 */
-		if (!curr->present) {
-			if (!curr->flushed) {
-				clear_user_desc(&curr->tls);
-				curr->tls.entry_number = idx;
-			} else {
-				WARN_ON(!LDT_empty(&curr->tls));
-				continue;
-			}
-		}
-
-		if (!(flags & O_FORCE) && curr->flushed)
-			continue;
-
-		ret = do_set_thread_area(&curr->tls);
-		if (ret)
-			goto out;
-
-		curr->flushed = 1;
-	}
-out:
-	return ret;
-}
-
-/*
- * Verify if we need to do a flush for the new process, i.e. if there are any
- * present desc's, only if they haven't been flushed.
- */
-static inline int needs_TLS_update(struct task_struct *task)
-{
-	int i;
-	int ret = 0;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Can't test curr->present, we may need to clear a descriptor
-		 * which had a value.
-		 */
-		if (curr->flushed)
-			continue;
-		ret = 1;
-		break;
-	}
-	return ret;
-}
-
-/*
- * On a newly forked process, the TLS descriptors haven't yet been flushed. So
- * we mark them as such and the first switch_to will do the job.
- */
-void clear_flushed_tls(struct task_struct *task)
-{
-	int i;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Still correct to do this, if it wasn't present on the host it
-		 * will remain as flushed as it was.
-		 */
-		if (!curr->present)
-			continue;
-
-		curr->flushed = 0;
-	}
-}
-
-/*
- * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
- * common host process. So this is needed in SKAS0 too.
- *
- * However, if each thread had a different host process (and this was discussed
- * for SMP support) this won't be needed.
- *
- * And this will not need be used when (and if) we'll add support to the host
- * SKAS patch.
- */
-
-int arch_switch_tls(struct task_struct *to)
-{
-	if (!host_supports_tls)
-		return 0;
-
-	/*
-	 * We have no need whatsoever to switch TLS for kernel threads; beyond
-	 * that, that would also result in us calling os_set_thread_area with
-	 * userspace_pid[cpu] == 0, which gives an error.
-	 */
-	if (likely(to->mm))
-		return load_TLS(O_FORCE, to);
-
-	return 0;
-}
-
-static int set_tls_entry(struct task_struct* task, struct user_desc *info,
-			 int idx, int flushed)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
-
-	return 0;
-}
-
-int arch_copy_tls(struct task_struct *new)
-{
-	struct user_desc info;
-	int idx, ret = -EFAULT;
-
-	if (copy_from_user(&info,
-			   (void __user *) UPT_ESI(&new->thread.regs.regs),
-			   sizeof(info)))
-		goto out;
-
-	ret = -EINVAL;
-	if (LDT_empty(&info))
-		goto out;
-
-	idx = info.entry_number;
-
-	ret = set_tls_entry(new, &info, idx, 0);
-out:
-	return ret;
-}
-
-/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct *task, struct user_desc *info,
-			 int idx)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (!t->arch.tls_array)
-		goto clear;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
-		goto clear;
-
-	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
-
-out:
-	/*
-	 * Temporary debugging check, to make sure that things have been
-	 * flushed. This could be triggered if load_TLS() failed.
-	 */
-	if (unlikely(task == current &&
-		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
-		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
-				"without flushed TLS.", current->pid);
-	}
-
-	return 0;
-clear:
-	/*
-	 * When the TLS entry has not been set, the values read to user in the
-	 * tls_array are 0 (because it's cleared at boot, see
-	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
-	 */
-	clear_user_desc(info);
-	info->entry_number = idx;
-	goto out;
-}
-
-int sys_set_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	idx = info.entry_number;
-
-	if (idx == -1) {
-		idx = get_free_idx(current);
-		if (idx < 0)
-			return idx;
-		info.entry_number = idx;
-		/* Tell the user which slot we chose for him.*/
-		if (put_user(idx, &user_desc->entry_number))
-			return -EFAULT;
-	}
-
-	ret = do_set_thread_area(&info);
-	if (ret)
-		return ret;
-	return set_tls_entry(current, &info, idx, 1);
-}
-
-/*
- * Perform set_thread_area on behalf of the traced child.
- * Note: error handling is not done on the deferred load, and this differ from
- * i386. However the only possible error are caused by bugs.
- */
-int ptrace_set_thread_area(struct task_struct *child, int idx,
-			   struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	return set_tls_entry(child, &info, idx, 0);
-}
-
-int sys_get_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (get_user(idx, &user_desc->entry_number))
-		return -EFAULT;
-
-	ret = get_tls_entry(current, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-
-out:
-	return ret;
-}
-
-/*
- * Perform get_thread_area on behalf of the traced child.
- */
-int ptrace_get_thread_area(struct task_struct *child, int idx,
-		struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int ret;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	ret = get_tls_entry(child, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-out:
-	return ret;
-}
-
-/*
- * This code is really i386-only, but it detects and logs x86_64 GDT indexes
- * if a 32-bit UML is running on a 64-bit host.
- */
-static int __init __setup_host_supports_tls(void)
-{
-	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
-	if (host_supports_tls) {
-		printk(KERN_INFO "Host TLS support detected\n");
-		printk(KERN_INFO "Detected host type: ");
-		switch (host_gdt_entry_tls_min) {
-		case GDT_ENTRY_TLS_MIN_I386:
-			printk(KERN_CONT "i386");
-			break;
-		case GDT_ENTRY_TLS_MIN_X86_64:
-			printk(KERN_CONT "x86_64");
-			break;
-		}
-		printk(KERN_CONT " (GDT indexes %d to %d)\n",
-		       host_gdt_entry_tls_min,
-		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
-	} else
-		printk(KERN_ERR "  Host TLS support NOT detected! "
-				"TLS support inside UML will not work\n");
-	return 0;
-}
-
-__initcall(__setup_host_supports_tls);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-i386/user-offsets.c linux-libre-3.2-gnu1/arch/um/sys-i386/user-offsets.c
--- linux-libre-3.1-gnu1/arch/um/sys-i386/user-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-i386/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/user.h>
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-
-	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
-	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
-	DEFINE(HOST_IP, EIP);
-	DEFINE(HOST_SP, UESP);
-	DEFINE(HOST_EFLAGS, EFL);
-	DEFINE(HOST_EAX, EAX);
-	DEFINE(HOST_EBX, EBX);
-	DEFINE(HOST_ECX, ECX);
-	DEFINE(HOST_EDX, EDX);
-	DEFINE(HOST_ESI, ESI);
-	DEFINE(HOST_EDI, EDI);
-	DEFINE(HOST_EBP, EBP);
-	DEFINE(HOST_CS, CS);
-	DEFINE(HOST_SS, SS);
-	DEFINE(HOST_DS, DS);
-	DEFINE(HOST_FS, FS);
-	DEFINE(HOST_ES, ES);
-	DEFINE(HOST_GS, GS);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/archparam.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/archparam.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/archparam.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_X86_64_H
-#define __UM_ARCHPARAM_X86_64_H
-
-
-/* No user-accessible fixmap addresses, i.e. vsyscall */
-#define FIXADDR_USER_START	0
-#define FIXADDR_USER_END	0
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/elf.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/elf.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_X86_64_H
-#define __UM_ELF_X86_64_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-/* x86-64 relocation types, taken from asm-x86_64/elf.h */
-#define R_X86_64_NONE		0	/* No reloc */
-#define R_X86_64_64		1	/* Direct 64 bit  */
-#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
-#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
-#define R_X86_64_PLT32		4	/* 32 bit PLT address */
-#define R_X86_64_COPY		5	/* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
-#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
-#define R_X86_64_RELATIVE	8	/* Adjust by program base */
-#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
-					   offset to GOT */
-#define R_X86_64_32		10	/* Direct 32 bit zero extended */
-#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
-#define R_X86_64_16		12	/* Direct 16 bit zero extended */
-#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
-#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
-#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM		16
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	((x)->e_machine == EM_X86_64)
-
-#define ELF_CLASS	ELFCLASS64
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_X86_64
-
-#define ELF_PLAT_INIT(regs, load_addr)    do { \
-	PT_REGS_RBX(regs) = 0; \
-	PT_REGS_RCX(regs) = 0; \
-	PT_REGS_RDX(regs) = 0; \
-	PT_REGS_RSI(regs) = 0; \
-	PT_REGS_RDI(regs) = 0; \
-	PT_REGS_RBP(regs) = 0; \
-	PT_REGS_RAX(regs) = 0; \
-	PT_REGS_R8(regs) = 0; \
-	PT_REGS_R9(regs) = 0; \
-	PT_REGS_R10(regs) = 0; \
-	PT_REGS_R11(regs) = 0; \
-	PT_REGS_R12(regs) = 0; \
-	PT_REGS_R13(regs) = 0; \
-	PT_REGS_R14(regs) = 0; \
-	PT_REGS_R15(regs) = 0; \
-} while (0)
-
-#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
-	(pr_reg)[0] = (_regs)->regs.gp[0];			\
-	(pr_reg)[1] = (_regs)->regs.gp[1];			\
-	(pr_reg)[2] = (_regs)->regs.gp[2];			\
-	(pr_reg)[3] = (_regs)->regs.gp[3];			\
-	(pr_reg)[4] = (_regs)->regs.gp[4];			\
-	(pr_reg)[5] = (_regs)->regs.gp[5];			\
-	(pr_reg)[6] = (_regs)->regs.gp[6];			\
-	(pr_reg)[7] = (_regs)->regs.gp[7];			\
-	(pr_reg)[8] = (_regs)->regs.gp[8];			\
-	(pr_reg)[9] = (_regs)->regs.gp[9];			\
-	(pr_reg)[10] = (_regs)->regs.gp[10];			\
-	(pr_reg)[11] = (_regs)->regs.gp[11];			\
-	(pr_reg)[12] = (_regs)->regs.gp[12];			\
-	(pr_reg)[13] = (_regs)->regs.gp[13];			\
-	(pr_reg)[14] = (_regs)->regs.gp[14];			\
-	(pr_reg)[15] = (_regs)->regs.gp[15];			\
-	(pr_reg)[16] = (_regs)->regs.gp[16];			\
-	(pr_reg)[17] = (_regs)->regs.gp[17];			\
-	(pr_reg)[18] = (_regs)->regs.gp[18];			\
-	(pr_reg)[19] = (_regs)->regs.gp[19];			\
-	(pr_reg)[20] = (_regs)->regs.gp[20];			\
-	(pr_reg)[21] = current->thread.arch.fs;			\
-	(pr_reg)[22] = 0;					\
-	(pr_reg)[23] = 0;					\
-	(pr_reg)[24] = 0;					\
-	(pr_reg)[25] = 0;					\
-	(pr_reg)[26] = 0;
-
-#define task_pt_regs(t) (&(t)->thread.regs)
-
-struct task_struct;
-
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-#ifdef TIF_IA32 /* XXX */
-#error XXX, indeed
-        clear_thread_flag(TIF_IA32);
-#endif
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-#define ELF_PLATFORM "x86_64"
-
-#define SET_PERSONALITY(ex) do ; while(0)
-
-#define __HAVE_ARCH_GATE_AREA 1
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
-struct linux_binprm;
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
-	int uses_interp);
-
-extern unsigned long um_vdso_addr;
-#define AT_SYSINFO_EHDR 33
-#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/module.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/module.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/module.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_MODULE_X86_64_H
-#define __UM_MODULE_X86_64_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-
-#endif
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/processor.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/processor.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_X86_64_H
-#define __UM_PROCESSOR_X86_64_H
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct arch_thread {
-        unsigned long debugregs[8];
-        int debugregs_seq;
-        unsigned long fs;
-        struct faultinfo faultinfo;
-};
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()   rep_nop()
-
-#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
-			   .debugregs_seq	= 0, \
-			   .fs			= 0, \
-			   .faultinfo		= { 0, 0, 0 } }
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-	to->fs = from->fs;
-}
-
-#include <asm/user.h>
-
-#define current_text_addr() \
-	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-        (address + 128 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/ptrace.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_X86_64_H
-#define __UM_PTRACE_X86_64_H
-
-#include "linux/compiler.h"
-#include "asm/errno.h"
-
-#define __FRAME_OFFSETS /* Needed to get the R* macros */
-#include "asm/ptrace-generic.h"
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
-
-#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
-#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
-#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
-#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
-#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
-#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
-#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
-#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
-#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
-#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
-#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
-#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
-#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
-#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
-#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
-
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-
-#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
-#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
-#define PT_REGS_RSP(r) UPT_SP(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-/* XXX */
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
-
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-struct user_desc;
-
-static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-extern long arch_prctl(struct task_struct *task, int code,
-		       unsigned long __user *addr);
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/bug.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/bug.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/bug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-
-/*
- * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/bugs.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/bugs.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/bugs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/bugs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-void arch_check_bugs(void)
-{
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/delay.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/delay.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/delay.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.c
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/fault.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/fault.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/fault.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/ksyms.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/ksyms.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/ksyms.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-#include <linux/module.h>
-#include <asm/string.h>
-#include <asm/checksum.h>
-
-/*XXX: we need them because they would be exported by x86_64 */
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-EXPORT_SYMBOL(memcpy);
-#else
-EXPORT_SYMBOL(__memcpy);
-#endif
-EXPORT_SYMBOL(csum_partial);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/Makefile linux-libre-3.2-gnu1/arch/um/sys-x86_64/Makefile
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-#
-# Copyright 2003 PathScale, Inc.
-#
-# Licensed under the GPL
-#
-
-obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
-	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
-	sysrq.o ksyms.o tls.o
-
-obj-y += vdso/
-
-subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
-		lib/rwsem.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-ldt-y = ../sys-i386/ldt.o
-
-USER_OBJS := ptrace_user.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/mem.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/mem.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/mem.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/mman.h"
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
-		return "[vdso]";
-
-	return NULL;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/ptrace.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/ptrace.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/ptrace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,198 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-
-/*
- * determines which flags the user has access to.
- * 1 = access 0 = no access
- */
-#define FLAG_MASK 0x44dd5UL
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	unsigned long tmp;
-
-#ifdef TIF_IA32
-	/*
-	 * Some code in the 64bit emulation may not be 64bit clean.
-	 * Don't take any chances.
-	 */
-	if (test_tsk_thread_flag(child, TIF_IA32))
-		value &= 0xffffffff;
-#endif
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-
-	case FS_BASE:
-	case GS_BASE:
-		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-			return -EIO;
-		break;
-
-	case EFLAGS:
-		value &= FLAG_MASK;
-		tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
-		value |= tmp;
-		break;
-	}
-
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-#ifdef TIF_IA32
-		if (test_tsk_thread_flag(child, TIF_IA32))
-			retval &= 0xffffffff;
-#endif
-	}
-	return retval;
-}
-
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	/* read the word at location addr in the USER area. */
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET)
-		tmp = getreg(child, addr);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long *) data);
-}
-
-/* XXX Mostly copied from sys-i386 */
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/*
-		 * access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk("is_syscall : failed to read instruction from "
-			       "0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* sysenter */
-	return instr == 0x050f;
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	err = save_fp_registers(userspace_pid[cpu], fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, fpregs, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	n = copy_from_user(fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu], fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_ARCH_PRCTL:
-		/* XXX Calls ptrace on the host - needs some SMP thinking */
-		ret = arch_prctl(child, data, (void __user *) addr);
-		break;
-	}
-
-	return ret;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/ptrace_user.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/ptrace_user.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/ptrace_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include "ptrace_user.h"
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/setjmp.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/setjmp.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/setjmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/setjmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-#
-# arch/x86_64/setjmp.S
-#
-# setjmp/longjmp for the x86-64 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%rbx
-#	%rsp (post-return)
-#	%rbp
-#	%r12
-#	%r13
-#	%r14
-#	%r15
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-	pop  %rsi			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movq %rbx,(%rdi)
-	movq %rsp,8(%rdi)		# Post-return %rsp!
-	push %rsi			# Make the call/return stack happy
-	movq %rbp,16(%rdi)
-	movq %r12,24(%rdi)
-	movq %r13,32(%rdi)
-	movq %r14,40(%rdi)
-	movq %r15,48(%rdi)
-	movq %rsi,56(%rdi)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-	movl %esi,%eax			# Return value (int)
-	movq (%rdi),%rbx
-	movq 8(%rdi),%rsp
-	movq 16(%rdi),%rbp
-	movq 24(%rdi),%r12
-	movq 32(%rdi),%r13
-	movq 40(%rdi),%r14
-	movq 48(%rdi),%r15
-	jmp *56(%rdi)
-
-	.size longjmp,.-longjmp
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- * arch/um/include/sysdep-x86_64/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned long __rbx;
-	unsigned long __rsp;
-	unsigned long __rbp;
-	unsigned long __r12;
-	unsigned long __r13;
-	unsigned long __r14;
-	unsigned long __r15;
-	unsigned long __rip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __rip
-#define JB_SP __rsp
-
-#endif				/* _SETJMP_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/barrier.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/barrier.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/barrier.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/barrier.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __SYSDEP_X86_64_BARRIER_H
-#define __SYSDEP_X86_64_BARRIER_H
-
-/* Copied from include/asm-x86_64 for use by userspace. */
-#define mb() 	asm volatile("mfence":::"memory")
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/checksum.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/checksum.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-/*
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/string.h"
-#include "linux/in6.h"
-#include "asm/uaccess.h"
-
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return(csum_partial(dst, len, sum));
-}
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src,
-                                         void *dst, int len, __wsum sum,
-                                         int *err_ptr)
-{
-        if (copy_from_user(dst, src, len)) {
-                *err_ptr = -EFAULT;
-                return (__force __wsum)-1;
-        }
-        return csum_partial(dst, len, sum);
-}
-
-/**
- * csum_fold - Fold and invert a 32bit checksum.
- * sum: 32bit unfolded sum
- *
- * Fold a 32bit running checksum to 16bit and invert it. This is usually
- * the last step before putting a checksum into a packet.
- * Make sure not to mix with 64bit checksums.
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"  addl %1,%0\n"
-		"  adcl $0xffff,%0"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-/**
- * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
- * @saddr: source address
- * @daddr: destination address
- * @len: length of packet
- * @proto: ip protocol of packet
- * @sum: initial sum to be added in (32bit unfolded)
- *
- * Returns the pseudo header checksum the input data. Result is
- * 32bit unfolded.
- */
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		   unsigned short proto, __wsum sum)
-{
-	asm("  addl %1, %0\n"
-	    "  adcl %2, %0\n"
-	    "  adcl %3, %0\n"
-	    "  adcl $0, %0\n"
-		: "=r" (sum)
-	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
-	return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-					   unsigned short len,
-					   unsigned short proto,
-					   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/**
- * ip_fast_csum - Compute the IPv4 header checksum efficiently.
- * iph: ipv4 header
- * ihl: length of header / 4
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	asm(	"  movl (%1), %0\n"
-		"  subl $4, %2\n"
-		"  jbe 2f\n"
-		"  addl 4(%1), %0\n"
-		"  adcl 8(%1), %0\n"
-		"  adcl 12(%1), %0\n"
-		"1: adcl 16(%1), %0\n"
-		"  lea 4(%1), %1\n"
-		"  decl %2\n"
-		"  jne	1b\n"
-		"  adcl $0, %0\n"
-		"  movl %0, %2\n"
-		"  shrl $16, %0\n"
-		"  addw %w2, %w0\n"
-		"  adcl $0, %0\n"
-		"  notl %0\n"
-		"2:"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-static inline unsigned add32_with_carry(unsigned a, unsigned b)
-{
-        asm("addl %2,%0\n\t"
-            "adcl $0,%0"
-            : "=r" (a)
-            : "0" (a), "r" (b));
-        return a;
-}
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/faultinfo.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/faultinfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_X86_64_H
-#define __FAULTINFO_X86_64_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 1
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/host_ldt.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/host_ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/host_ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-#ifndef __ASM_HOST_LDT_X86_64_H
-#define __ASM_HOST_LDT_X86_64_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-x86_64/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-/* Don't allow setting of the lm bit. It is useless anyways because
- * 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	/* ((info)->lm << 21) | */ \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	&& \
-	(info)->lm              == 0)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_STR1(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,240 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_H
-#define __SYSDEP_X86_64_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-
-#define REGS_RBX(r) ((r)[HOST_RBX])
-#define REGS_RCX(r) ((r)[HOST_RCX])
-#define REGS_RDX(r) ((r)[HOST_RDX])
-#define REGS_RSI(r) ((r)[HOST_RSI])
-#define REGS_RDI(r) ((r)[HOST_RDI])
-#define REGS_RBP(r) ((r)[HOST_RBP])
-#define REGS_RAX(r) ((r)[HOST_RAX])
-#define REGS_R8(r) ((r)[HOST_R8])
-#define REGS_R9(r) ((r)[HOST_R9])
-#define REGS_R10(r) ((r)[HOST_R10])
-#define REGS_R11(r) ((r)[HOST_R11])
-#define REGS_R12(r) ((r)[HOST_R12])
-#define REGS_R13(r) ((r)[HOST_R13])
-#define REGS_R14(r) ((r)[HOST_R14])
-#define REGS_R15(r) ((r)[HOST_R15])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_SS(r) ((r)[HOST_SS])
-
-#define HOST_FS_BASE 21
-#define HOST_GS_BASE 22
-#define HOST_DS 23
-#define HOST_ES 24
-#define HOST_FS 25
-#define HOST_GS 26
-
-/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
- * are already defined for kernel code, but not for userspace code.
- */
-#ifndef FS_BASE
-/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
- * which is what x86_64 ptrace actually uses.
- */
-#define FS_BASE (HOST_FS_BASE * sizeof(long))
-#define GS_BASE (HOST_GS_BASE * sizeof(long))
-#define DS (HOST_DS * sizeof(long))
-#define ES (HOST_ES * sizeof(long))
-#define FS (HOST_FS * sizeof(long))
-#define GS (HOST_GS * sizeof(long))
-#endif
-
-#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
-#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
-#define REGS_TRAP(r) ((r)->trap_type)
-
-#define REGS_ERR(r) ((r)->fault_type)
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FP_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_RBX(r) REGS_RBX((r)->gp)
-#define UPT_RCX(r) REGS_RCX((r)->gp)
-#define UPT_RDX(r) REGS_RDX((r)->gp)
-#define UPT_RSI(r) REGS_RSI((r)->gp)
-#define UPT_RDI(r) REGS_RDI((r)->gp)
-#define UPT_RBP(r) REGS_RBP((r)->gp)
-#define UPT_RAX(r) REGS_RAX((r)->gp)
-#define UPT_R8(r) REGS_R8((r)->gp)
-#define UPT_R9(r) REGS_R9((r)->gp)
-#define UPT_R10(r) REGS_R10((r)->gp)
-#define UPT_R11(r) REGS_R11((r)->gp)
-#define UPT_R12(r) REGS_R12((r)->gp)
-#define UPT_R13(r) REGS_R13((r)->gp)
-#define UPT_R14(r) REGS_R14((r)->gp)
-#define UPT_R15(r) REGS_R15((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_SYSCALL_NR(r) ((r)->syscall)
-#define UPT_SYSCALL_RET(r) UPT_RAX(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
-#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
-#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
-#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
-#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	 \
-				     UPT_SYSCALL_ARG2(r),	 \
-				     UPT_SYSCALL_ARG3(r),	 \
-				     UPT_SYSCALL_ARG4(r),	 \
-				     UPT_SYSCALL_ARG5(r),	 \
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({      unsigned long val;		\
-		switch(reg){						\
-		case R8: val = UPT_R8(regs); break;			\
-		case R9: val = UPT_R9(regs); break;			\
-		case R10: val = UPT_R10(regs); break;			\
-		case R11: val = UPT_R11(regs); break;			\
-		case R12: val = UPT_R12(regs); break;			\
-		case R13: val = UPT_R13(regs); break;			\
-		case R14: val = UPT_R14(regs); break;			\
-		case R15: val = UPT_R15(regs); break;			\
-		case RIP: val = UPT_IP(regs); break;			\
-		case RSP: val = UPT_SP(regs); break;			\
-		case RAX: val = UPT_RAX(regs); break;			\
-		case RBX: val = UPT_RBX(regs); break;			\
-		case RCX: val = UPT_RCX(regs); break;			\
-		case RDX: val = UPT_RDX(regs); break;			\
-		case RSI: val = UPT_RSI(regs); break;			\
-		case RDI: val = UPT_RDI(regs); break;			\
-		case RBP: val = UPT_RBP(regs); break;			\
-		case ORIG_RAX: val = UPT_ORIG_RAX(regs); break;		\
-		case CS: val = UPT_CS(regs); break;			\
-		case SS: val = UPT_SS(regs); break;			\
-		case FS_BASE: val = UPT_FS_BASE(regs); break;		\
-		case GS_BASE: val = UPT_GS_BASE(regs); break;		\
-		case DS: val = UPT_DS(regs); break;			\
-		case ES: val = UPT_ES(regs); break;			\
-		case FS : val = UPT_FS (regs); break;			\
-		case GS: val = UPT_GS(regs); break;			\
-		case EFLAGS: val = UPT_EFLAGS(regs); break;		\
-		default :						\
-			panic("Bad register in UPT_REG : %d\n", reg);	\
-			val = -1;					\
-		}							\
-		val;							\
-	})
-
-
-#define UPT_SET(regs, reg, val) \
-	({      unsigned long __upt_val = val;	\
-		switch(reg){						\
-		case R8: UPT_R8(regs) = __upt_val; break;		\
-		case R9: UPT_R9(regs) = __upt_val; break;		\
-		case R10: UPT_R10(regs) = __upt_val; break;		\
-		case R11: UPT_R11(regs) = __upt_val; break;		\
-		case R12: UPT_R12(regs) = __upt_val; break;		\
-		case R13: UPT_R13(regs) = __upt_val; break;		\
-		case R14: UPT_R14(regs) = __upt_val; break;		\
-		case R15: UPT_R15(regs) = __upt_val; break;		\
-		case RIP: UPT_IP(regs) = __upt_val; break;		\
-		case RSP: UPT_SP(regs) = __upt_val; break;		\
-		case RAX: UPT_RAX(regs) = __upt_val; break;		\
-		case RBX: UPT_RBX(regs) = __upt_val; break;		\
-		case RCX: UPT_RCX(regs) = __upt_val; break;		\
-		case RDX: UPT_RDX(regs) = __upt_val; break;		\
-		case RSI: UPT_RSI(regs) = __upt_val; break;		\
-		case RDI: UPT_RDI(regs) = __upt_val; break;		\
-		case RBP: UPT_RBP(regs) = __upt_val; break;		\
-		case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break;	\
-		case CS: UPT_CS(regs) = __upt_val; break;		\
-		case SS: UPT_SS(regs) = __upt_val; break;		\
-		case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break;	\
-		case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break;	\
-		case DS: UPT_DS(regs) = __upt_val; break;		\
-		case ES: UPT_ES(regs) = __upt_val; break;		\
-		case FS: UPT_FS(regs) = __upt_val; break;		\
-		case GS: UPT_GS(regs) = __upt_val; break;		\
-		case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break;	\
-		default :						\
-			panic("Bad register in UPT_SET : %d\n", reg);	\
-			break;						\
-		}							\
-		__upt_val;						\
-	})
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-static inline void arch_init_registers(int pid)
-{
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_USER_H__
-#define __SYSDEP_X86_64_PTRACE_USER_H__
-
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#undef __FRAME_OFFSETS
-#include "user_constants.h"
-
-#define PT_INDEX(off) ((off) / sizeof(unsigned long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-#define PT_SYSCALL_NR_OFFSET (ORIG_RAX)
-
-#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)])
-#define PT_SYSCALL_ARG1_OFFSET (RDI)
-
-#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)])
-#define PT_SYSCALL_ARG2_OFFSET (RSI)
-
-#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)])
-#define PT_SYSCALL_ARG3_OFFSET (RDX)
-
-#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)])
-#define PT_SYSCALL_ARG4_OFFSET (RCX)
-
-#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)])
-#define PT_SYSCALL_ARG5_OFFSET (R8)
-
-#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)])
-#define PT_SYSCALL_ARG6_OFFSET (R9)
-
-#define PT_SYSCALL_RET_OFFSET (RAX)
-
-#define PT_IP_OFFSET (RIP)
-#define PT_IP(regs) ((regs)[PT_INDEX(RIP)])
-
-#define PT_SP_OFFSET (RSP)
-#define PT_SP(regs) ((regs)[PT_INDEX(RSP)])
-
-#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
-#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-
-/*
- * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
- * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
- * 2.4 name and value for 2.4 host compatibility.
- */
-#ifndef PTRACE_OLDSETOPTIONS
-#define PTRACE_OLDSETOPTIONS 21
-#endif
-
-/*
- * These are before the system call, so the system call number is RAX
- * rather than ORIG_RAX, and arg4 is R10 rather than RCX
- */
-#define REGS_SYSCALL_NR PT_INDEX(RAX)
-#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
-#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
-#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
-#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
-#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
-#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
-
-#define REGS_IP_INDEX PT_INDEX(RIP)
-#define REGS_SP_INDEX PT_INDEX(RSP)
-
-#define FP_SIZE (HOST_FP_SIZE)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/sc.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/sc.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/sc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/sc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-#ifndef __SYSDEP_X86_64_SC_H
-#define __SYSDEP_X86_64_SC_H
-
-/* Copyright (C) 2003 - 2004 PathScale, Inc
- * Released under the GPL
- */
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	 *((unsigned long *) &(((char *) (sc))[HOST_##field]))
-
-#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX)
-#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX)
-#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX)
-#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI)
-#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI)
-#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP)
-#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX)
-#define SC_R8(sc) SC_OFFSET(sc, SC_R8)
-#define SC_R9(sc) SC_OFFSET(sc, SC_R9)
-#define SC_R10(sc) SC_OFFSET(sc, SC_R10)
-#define SC_R11(sc) SC_OFFSET(sc, SC_R11)
-#define SC_R12(sc) SC_OFFSET(sc, SC_R12)
-#define SC_R13(sc) SC_OFFSET(sc, SC_R13)
-#define SC_R14(sc) SC_OFFSET(sc, SC_R14)
-#define SC_R15(sc) SC_OFFSET(sc, SC_R15)
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#if 0
-#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#endif
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/sigcontext.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
-#define __SYSDEP_X86_64_SIGCONTEXT_H
-
-#include <sysdep/sc.h>
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* No broken SKAS API, which doesn't pass trap_no, here. */
-#define SEGV_MAYBE_FIXABLE(fi)	0
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
-#define __SYSDEP_X86_64_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/stub.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/stub.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/stub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/unistd.h>
-#include <sysdep/ptrace_user.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET PT_INDEX(RAX)
-#define STUB_MMAP_NR __NR_mmap
-#define MMAP_OFFSET(o) (o)
-
-#define __syscall_clobber "r11","rcx","memory"
-#define __syscall "syscall"
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
-		: __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4)
-		: __syscall_clobber, "r10" );
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4), "g" (arg5)
-		: __syscall_clobber, "r10", "r8" );
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(long fd, unsigned long offset)
-{
-	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
-			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
-			  "movq %%rax, (%%rbx)":
-			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
-			    "S" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
-			    "g" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : __syscall_clobber, "r10", "r8", "r9" );
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/syscalls.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/syscalls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SYSCALLS_H__
-#define __SYSDEP_X86_64_SYSCALLS_H__
-
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <kern_constants.h>
-
-typedef long syscall_handler_t(void);
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	(((long (*)(long, long, long, long, long, long)) \
-	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
-		 		      UPT_SYSCALL_ARG2(&regs->regs), \
-				      UPT_SYSCALL_ARG3(&regs->regs), \
-				      UPT_SYSCALL_ARG4(&regs->regs), \
-				      UPT_SYSCALL_ARG5(&regs->regs), \
-				      UPT_SYSCALL_ARG6(&regs->regs)))
-
-extern long old_mmap(unsigned long addr, unsigned long len,
-		     unsigned long prot, unsigned long flags,
-		     unsigned long fd, unsigned long pgoff);
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t sys_arch_prctl;
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/system.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/system.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/tls.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/tls.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/tls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-	unsigned int  lm:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-#endif /* _SYSDEP_TLS_H */
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/vm-flags.h linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/shared/sysdep/vm-flags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/shared/sysdep/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_X86_64_H
-#define __VM_FLAGS_X86_64_H
-
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
-	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
-	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/signal.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/signal.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/personality.h>
-#include <linux/ptrace.h>
-#include <linux/kernel.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-#define GETREG(regs, regno, sc, regname)				\
-	(regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
-
-	GETREG(regs, R8, sc, r8);
-	GETREG(regs, R9, sc, r9);
-	GETREG(regs, R10, sc, r10);
-	GETREG(regs, R11, sc, r11);
-	GETREG(regs, R12, sc, r12);
-	GETREG(regs, R13, sc, r13);
-	GETREG(regs, R14, sc, r14);
-	GETREG(regs, R15, sc, r15);
-	GETREG(regs, RDI, sc, di);
-	GETREG(regs, RSI, sc, si);
-	GETREG(regs, RBP, sc, bp);
-	GETREG(regs, RBX, sc, bx);
-	GETREG(regs, RDX, sc, dx);
-	GETREG(regs, RAX, sc, ax);
-	GETREG(regs, RCX, sc, cx);
-	GETREG(regs, RSP, sc, sp);
-	GETREG(regs, RIP, sc, ip);
-	GETREG(regs, EFLAGS, sc, flags);
-	GETREG(regs, CS, sc, cs);
-
-#undef GETREG
-}
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from,
-			     struct _fpstate __user *fpp)
-{
-	struct user_i387_struct fp;
-	int err = 0;
-
-#define GETREG(regs, regno, sc, regname)				\
-	__get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= GETREG(regs, R8, from, r8);
-	err |= GETREG(regs, R9, from, r9);
-	err |= GETREG(regs, R10, from, r10);
-	err |= GETREG(regs, R11, from, r11);
-	err |= GETREG(regs, R12, from, r12);
-	err |= GETREG(regs, R13, from, r13);
-	err |= GETREG(regs, R14, from, r14);
-	err |= GETREG(regs, R15, from, r15);
-	err |= GETREG(regs, RDI, from, di);
-	err |= GETREG(regs, RSI, from, si);
-	err |= GETREG(regs, RBP, from, bp);
-	err |= GETREG(regs, RBX, from, bx);
-	err |= GETREG(regs, RDX, from, dx);
-	err |= GETREG(regs, RAX, from, ax);
-	err |= GETREG(regs, RCX, from, cx);
-	err |= GETREG(regs, RSP, from, sp);
-	err |= GETREG(regs, RIP, from, ip);
-	err |= GETREG(regs, EFLAGS, from, flags);
-	err |= GETREG(regs, CS, from, cs);
-	if (err)
-		return 1;
-
-#undef GETREG
-
-	err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
-	if (err)
-		return 1;
-
-	err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
-				   (unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - "
-		       "restore_fp_registers failed, errno = %d\n",
-		       -err);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long mask, unsigned long sp)
-{
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	struct user_i387_struct fp;
-	int err = 0;
-
-	err |= __put_user(0, &to->gs);
-	err |= __put_user(0, &to->fs);
-
-#define PUTREG(regs, regno, sc, regname)				\
-	__put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= PUTREG(regs, RDI, to, di);
-	err |= PUTREG(regs, RSI, to, si);
-	err |= PUTREG(regs, RBP, to, bp);
-	/*
-	 * Must use original RSP, which is passed in, rather than what's in
-	 * the pt_regs, because that's already been updated to point at the
-	 * signal frame.
-	 */
-	err |= __put_user(sp, &to->sp);
-	err |= PUTREG(regs, RBX, to, bx);
-	err |= PUTREG(regs, RDX, to, dx);
-	err |= PUTREG(regs, RCX, to, cx);
-	err |= PUTREG(regs, RAX, to, ax);
-	err |= PUTREG(regs, R8, to, r8);
-	err |= PUTREG(regs, R9, to, r9);
-	err |= PUTREG(regs, R10, to, r10);
-	err |= PUTREG(regs, R11, to, r11);
-	err |= PUTREG(regs, R12, to, r12);
-	err |= PUTREG(regs, R13, to, r13);
-	err |= PUTREG(regs, R14, to, r14);
-	err |= PUTREG(regs, R15, to, r15);
-	err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
-
-	err |= __put_user(fi->cr2, &to->cr2);
-	err |= __put_user(fi->error_code, &to->err);
-	err |= __put_user(fi->trap_no, &to->trapno);
-
-	err |= PUTREG(regs, RIP, to, ip);
-	err |= PUTREG(regs, EFLAGS, to, flags);
-#undef PUTREG
-
-	err |= __put_user(mask, &to->oldmask);
-	if (err)
-		return 1;
-
-	err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
-				(unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
-		       "failed, errno = %d\n", -err);
-		return 1;
-	}
-
-	if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-		return 1;
-
-	return err;
-}
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	struct ucontext uc;
-	struct siginfo info;
-	struct _fpstate fpstate;
-};
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs * regs,
-			  siginfo_t *info, sigset_t *set)
-{
-	struct rt_sigframe __user *frame;
-	unsigned long save_sp = PT_REGS_RSP(regs);
-	int err = 0;
-	struct task_struct *me = current;
-
-	frame = (struct rt_sigframe __user *)
-		round_down(stack_top - sizeof(struct rt_sigframe), 16);
-	/* Subtract 128 for a red zone and 8 for proper alignment */
-	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto out;
-
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
-		if (err)
-			goto out;
-	}
-
-	/*
-	 * Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_RSP(regs) = (unsigned long) frame;
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(save_sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
-			       set->sig[0], save_sp);
-	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
-	if (sizeof(*set) == 16) {
-		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
-		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
-	}
-	else
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
-				      sizeof(*set));
-
-	/*
-	 * Set up to return from userspace.  If provided, use a stub
-	 * already in userspace.
-	 */
-	/* x86-64 should always use SA_RESTORER. */
-	if (ka->sa.sa_flags & SA_RESTORER)
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
-	else
-		/* could use a vstub here */
-		goto restore_sp;
-
-	if (err)
-		goto restore_sp;
-
-	/* Set up registers for signal handler */
-	{
-		struct exec_domain *ed = current_thread_info()->exec_domain;
-		if (unlikely(ed && ed->signal_invmap && sig < 32))
-			sig = ed->signal_invmap[sig];
-	}
-
-	PT_REGS_RDI(regs) = sig;
-	/* In case the signal handler was declared without prototypes */
-	PT_REGS_RAX(regs) = 0;
-
-	/*
-	 * This also works for non SA_SIGINFO handlers because they expect the
-	 * next argument after the signal number on the stack.
-	 */
-	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
-	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
-	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
- out:
-	return err;
-
-restore_sp:
-	PT_REGS_RSP(regs) = save_sp;
-	return err;
-}
-
-long sys_rt_sigreturn(struct pt_regs *regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *)(sp - 8);
-	struct ucontext __user *uc = &frame->uc;
-	sigset_t set;
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
-			      &frame->fpstate))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/stub.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/stub.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/stub.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/stub.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-syscall_stub:
-	syscall
-	/* We don't have 64-bit constants, so this constructs the address
-	 * we need.
-	 */
-	movq	$(STUB_DATA >> 32), %rbx
-	salq	$32, %rbx
-	movq	$(STUB_DATA & 0xffffffff), %rcx
-	or	%rcx, %rbx
-	movq	%rax, (%rbx)
-	int3
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	mov	$(STUB_DATA >> 32), %rbx
-	sal	$32, %rbx
-	mov	$(STUB_DATA & 0xffffffff), %rax
-	or	%rax, %rbx
-	/* load pointer to first operation */
-	mov	%rbx, %rsp
-	add	$0x10, %rsp
-again:
-	/* load length of additional data */
-	mov	0x0(%rsp), %rax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%rax, 8(%rbx)
-	cmp	$0, %rax
-	jz	done
-
-	/* save current pointer */
-	mov	%rsp, 8(%rbx)
-
-	/* skip additional data */
-	add	%rax, %rsp
-
-	/* load syscall-# */
-	pop	%rax
-
-	/* load syscall params */
-	pop	%rdi
-	pop	%rsi
-	pop	%rdx
-	pop	%r10
- 	pop	%r8
-	pop	%r9
-
-	/* execute syscall */
-	syscall
-
-	/* check return value */
-	pop	%rcx
-	cmp	%rcx, %rax
-	je	again
-
-done:
-	/* save return value */
-	mov	%rax, (%rbx)
-
-	/* stop */
-	int3
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/stub_segv.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/stub_segv.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/stub_segv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "as-layout.h"
-#include "sysdep/stub.h"
-#include "sysdep/faultinfo.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct ucontext *uc;
-
-	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
-			      &uc->uc_mcontext);
-	trap_myself();
-}
-
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/syscalls.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/syscalls.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/syscalls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
-
-long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
-{
-	unsigned long *ptr = addr, tmp;
-	long ret;
-	int pid = task->mm->context.id.u.pid;
-
-	/*
-	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
-	 * be safe), we need to call arch_prctl on the host because
-	 * setting %fs may result in something else happening (like a
-	 * GDT or thread.fs being set instead).  So, we let the host
-	 * fiddle the registers and thread struct and restore the
-	 * registers afterwards.
-	 *
-	 * So, the saved registers are stored to the process (this
-	 * needed because a stub may have been the last thing to run),
-	 * arch_prctl is run on the host, then the registers are read
-	 * back.
-	 */
-	switch (code) {
-	case ARCH_SET_FS:
-	case ARCH_SET_GS:
-		ret = restore_registers(pid, &current->thread.regs.regs);
-		if (ret)
-			return ret;
-		break;
-	case ARCH_GET_FS:
-	case ARCH_GET_GS:
-		/*
-		 * With these two, we read to a local pointer and
-		 * put_user it to the userspace pointer that we were
-		 * given.  If addr isn't valid (because it hasn't been
-		 * faulted in or is just bogus), we want put_user to
-		 * fault it in (or return -EFAULT) instead of having
-		 * the host return -EFAULT.
-		 */
-		ptr = &tmp;
-	}
-
-	ret = os_arch_prctl(pid, code, ptr);
-	if (ret)
-		return ret;
-
-	switch (code) {
-	case ARCH_SET_FS:
-		current->thread.arch.fs = (unsigned long) ptr;
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_SET_GS:
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_GET_FS:
-		ret = put_user(tmp, addr);
-		break;
-	case ARCH_GET_GS:
-		ret = put_user(tmp, addr);
-		break;
-	}
-
-	return ret;
-}
-
-long sys_arch_prctl(int code, unsigned long addr)
-{
-	return arch_prctl(current, code, (unsigned long __user *) addr);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-void arch_switch_to(struct task_struct *to)
-{
-	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
-		return;
-
-	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/syscall_table.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/syscall_table.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/syscall_table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/syscall_table.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML.
- */
-
-#include <linux/linkage.h>
-#include <linux/sys.h>
-#include <linux/cache.h>
-#include <kern_constants.h>
-
-#define __NO_STUBS
-
-/*
- * Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table.
- */
-
-/* Not going to be implemented by UML, since we have no hardware. */
-#define stub_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-/*
- * The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility.
- */
-
-/* On UML we call it this way ("old" means it's not mmap2) */
-#define sys_mmap old_mmap
-
-#define stub_clone sys_clone
-#define stub_fork sys_fork
-#define stub_vfork sys_vfork
-#define stub_execve sys_execve
-#define stub_rt_sigsuspend sys_rt_sigsuspend
-#define stub_sigaltstack sys_sigaltstack
-#define stub_rt_sigreturn sys_rt_sigreturn
-
-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_UNISTD_64_H
-#include "../../x86/include/asm/unistd_64.h"
-
-#undef __SYSCALL
-#define __SYSCALL(nr, sym) [ nr ] = sym,
-#undef _ASM_X86_UNISTD_64_H
-
-typedef void (*sys_call_ptr_t)(void);
-
-extern void sys_ni_syscall(void);
-
-/*
- * We used to have a trick here which made sure that holes in the
- * x86_64 table were filled in with sys_ni_syscall, but a comment in
- * unistd_64.h says that holes aren't allowed, so the trick was
- * removed.
- * The trick looked like this
- *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
- * before including unistd_64.h - the later initializations overwrote
- * the sys_ni_syscall filler.
- */
-
-sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
-#include "../../x86/include/asm/unistd_64.h"
-};
-
-int syscall_table_size = sizeof(sys_call_table);
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/sysrq.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/sysrq.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/sysrq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/sysrq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/utsname.h>
-#include <asm/current.h>
-#include <asm/ptrace.h>
-#include "sysrq.h"
-
-void __show_regs(struct pt_regs *regs)
-{
-	printk("\n");
-	print_modules();
-	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
-		current->comm, print_tainted(), init_utsname()->release);
-	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
-	       PT_REGS_RIP(regs));
-	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_RSP(regs),
-	       PT_REGS_EFLAGS(regs));
-	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
-	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
-	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
-	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
-	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
-	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
-	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
-	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
-	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
-	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
-}
-
-void show_regs(struct pt_regs *regs)
-{
-	__show_regs(regs);
-	show_trace(current, (unsigned long *) &regs);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/tls.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/tls.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#include "linux/sched.h"
-
-void clear_flushed_tls(struct task_struct *task)
-{
-}
-
-int arch_copy_tls(struct task_struct *t)
-{
-	/*
-	 * If CLONE_SETTLS is set, we need to save the thread id
-	 * (which is argument 5, child_tid, of clone) so it can be set
-	 * during context switches.
-	 */
-	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
-
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/user-offsets.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/user-offsets.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/user-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/types.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-
-	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
-	DEFINE_LONGS(HOST_RBX, RBX);
-	DEFINE_LONGS(HOST_RCX, RCX);
-	DEFINE_LONGS(HOST_RDI, RDI);
-	DEFINE_LONGS(HOST_RSI, RSI);
-	DEFINE_LONGS(HOST_RDX, RDX);
-	DEFINE_LONGS(HOST_RBP, RBP);
-	DEFINE_LONGS(HOST_RAX, RAX);
-	DEFINE_LONGS(HOST_R8, R8);
-	DEFINE_LONGS(HOST_R9, R9);
-	DEFINE_LONGS(HOST_R10, R10);
-	DEFINE_LONGS(HOST_R11, R11);
-	DEFINE_LONGS(HOST_R12, R12);
-	DEFINE_LONGS(HOST_R13, R13);
-	DEFINE_LONGS(HOST_R14, R14);
-	DEFINE_LONGS(HOST_R15, R15);
-	DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX);
-	DEFINE_LONGS(HOST_CS, CS);
-	DEFINE_LONGS(HOST_SS, SS);
-	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
-#if 0
-	DEFINE_LONGS(HOST_FS, FS);
-	DEFINE_LONGS(HOST_GS, GS);
-	DEFINE_LONGS(HOST_DS, DS);
-	DEFINE_LONGS(HOST_ES, ES);
-#endif
-
-	DEFINE_LONGS(HOST_IP, RIP);
-	DEFINE_LONGS(HOST_SP, RSP);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/checkundef.sh linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/checkundef.sh
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/checkundef.sh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/checkundef.sh	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#!/bin/sh
-nm="$1"
-file="$2"
-$nm "$file" | grep '^ *U' > /dev/null 2>&1
-if [ $? -eq 1 ]; then
-    exit 0
-else
-    echo "$file: undefined symbols found" >&2
-    exit 1
-fi
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/Makefile linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/Makefile
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-#
-# Building vDSO images for x86.
-#
-
-VDSO64-y		:= y
-
-vdso-install-$(VDSO64-y)	+= vdso.so
-
-
-# files to link into the vdso
-vobjs-y := vdso-note.o um_vdso.o
-
-# files to link into kernel
-obj-$(VDSO64-y)			+= vdso.o vma.o
-
-vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
-
-$(obj)/vdso.o: $(obj)/vdso.so
-
-targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
-
-export CPPFLAGS_vdso.lds += -P -C
-
-VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
-       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-
-$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
-
-$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
-	$(call if_changed,vdso)
-
-$(obj)/%.so: OBJCOPYFLAGS := -S
-$(obj)/%.so: $(obj)/%.so.dbg FORCE
-	$(call if_changed,objcopy)
-
-#
-# Don't omit frame pointers for ease of userspace debugging, but do
-# optimize sibling calls.
-#
-CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
-       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
-       -fno-omit-frame-pointer -foptimize-sibling-calls
-
-$(vobjs): KBUILD_CFLAGS += $(CFL)
-
-#
-# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
-#
-CFLAGS_REMOVE_vdso-note.o = -pg
-CFLAGS_REMOVE_um_vdso.o = -pg
-
-targets += vdso-syms.lds
-obj-$(VDSO64-y)			+= vdso-syms.lds
-
-#
-# Match symbols in the DSO that look like VDSO*; produce a file of constants.
-#
-sed-vdsosym := -e 's/^00*/0/' \
-	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
-quiet_cmd_vdsosym = VDSOSYM $@
-define cmd_vdsosym
-	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
-endef
-
-$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
-	$(call if_changed,vdsosym)
-
-#
-# The DSO images are built using a special linker script.
-#
-quiet_cmd_vdso = VDSO    $@
-      cmd_vdso = $(CC) -nostdlib -o $@ \
-		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
-		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
-
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-GCOV_PROFILE := n
-
-#
-# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
-#
-quiet_cmd_vdso_install = INSTALL $@
-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
-	@mkdir -p $(MODLIB)/vdso
-	$(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso-install-y)
-vdso_install: $(vdso-install-y)
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/um_vdso.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/um_vdso.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/um_vdso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/um_vdso.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * 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.
- *
- * This vDSO turns all calls into a syscall so that UML can trap them.
- */
-
-
-/* Disable profiling for userspace code */
-#define DISABLE_BRANCH_PROFILING
-
-#include <linux/time.h>
-#include <linux/getcpu.h>
-#include <asm/unistd.h>
-
-int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
-
-	return ret;
-}
-int clock_gettime(clockid_t, struct timespec *)
-	__attribute__((weak, alias("__vdso_clock_gettime")));
-
-int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
-
-	return ret;
-}
-int gettimeofday(struct timeval *, struct timezone *)
-	__attribute__((weak, alias("__vdso_gettimeofday")));
-
-time_t __vdso_time(time_t *t)
-{
-	long secs;
-
-	asm volatile("syscall"
-		: "=a" (secs)
-		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
-
-	return secs;
-}
-int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
-
-long
-__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
-{
-	/*
-	 * UML does not support SMP, we can cheat here. :)
-	 */
-
-	if (cpu)
-		*cpu = 0;
-	if (node)
-		*node = 0;
-
-	return 0;
-}
-
-long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-	__attribute__((weak, alias("__vdso_getcpu")));
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso-layout.lds.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso-layout.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso-layout.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Linker script for vDSO.  This is an ELF shared object prelinked to
- * its virtual address, and with only one read-only segment.
- * This script controls its layout.
- */
-
-SECTIONS
-{
-	. = VDSO_PRELINK + SIZEOF_HEADERS;
-
-	.hash		: { *(.hash) }			:text
-	.gnu.hash	: { *(.gnu.hash) }
-	.dynsym		: { *(.dynsym) }
-	.dynstr		: { *(.dynstr) }
-	.gnu.version	: { *(.gnu.version) }
-	.gnu.version_d	: { *(.gnu.version_d) }
-	.gnu.version_r	: { *(.gnu.version_r) }
-
-	.note		: { *(.note.*) }		:text	:note
-
-	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
-	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
-
-	.dynamic	: { *(.dynamic) }		:text	:dynamic
-
-	.rodata		: { *(.rodata*) }		:text
-	.data		: {
-	      *(.data*)
-	      *(.sdata*)
-	      *(.got.plt) *(.got)
-	      *(.gnu.linkonce.d.*)
-	      *(.bss*)
-	      *(.dynbss*)
-	      *(.gnu.linkonce.b.*)
-	}
-
-	.altinstructions	: { *(.altinstructions) }
-	.altinstr_replacement	: { *(.altinstr_replacement) }
-
-	/*
-	 * Align the actual code well away from the non-instruction data.
-	 * This is the best thing for the I-cache.
-	 */
-	. = ALIGN(0x100);
-
-	.text		: { *(.text*) }			:text	=0x90909090
-}
-
-/*
- * Very old versions of ld do not recognize this name token; use the constant.
- */
-#define PT_GNU_EH_FRAME	0x6474e550
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
-	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
-	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
-	note		PT_NOTE		FLAGS(4);		/* PF_R */
-	eh_frame_hdr	PT_GNU_EH_FRAME;
-}
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso.lds.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso.lds.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * Linker script for 64-bit vDSO.
- * We #include the file to define the layout details.
- * Here we only choose the prelinked virtual address.
- *
- * This file defines the version script giving the user-exported symbols in
- * the DSO.  We can define local symbols here called VDSO* to make their
- * values visible using the asm-x86/vdso.h macros from the kernel proper.
- */
-
-#define VDSO_PRELINK 0xffffffffff700000
-#include "vdso-layout.lds.S"
-
-/*
- * This controls what userland symbols we export from the vDSO.
- */
-VERSION {
-	LINUX_2.6 {
-	global:
-		clock_gettime;
-		__vdso_clock_gettime;
-		gettimeofday;
-		__vdso_gettimeofday;
-		getcpu;
-		__vdso_getcpu;
-		time;
-		__vdso_time;
-	local: *;
-	};
-}
-
-VDSO64_PRELINK = VDSO_PRELINK;
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso-note.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso-note.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso-note.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso-note.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
- * Here we can supply some information useful to userland.
- */
-
-#include <linux/uts.h>
-#include <linux/version.h>
-#include <linux/elfnote.h>
-
-ELFNOTE_START(Linux, 0, "a")
-	.long LINUX_VERSION_CODE
-ELFNOTE_END
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso.S linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso.S
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vdso.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vdso.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#include <linux/init.h>
-
-__INITDATA
-
-	.globl vdso_start, vdso_end
-vdso_start:
-	.incbin "arch/um/sys-x86_64/vdso/vdso.so"
-vdso_end:
-
-__FINIT
diff -druNp linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vma.c linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vma.c
--- linux-libre-3.1-gnu1/arch/um/sys-x86_64/vdso/vma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/um/sys-x86_64/vdso/vma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * 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/slab.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/page.h>
-#include <linux/init.h>
-
-unsigned int __read_mostly vdso_enabled = 1;
-unsigned long um_vdso_addr;
-
-extern unsigned long task_size;
-extern char vdso_start[], vdso_end[];
-
-static struct page **vdsop;
-
-static int __init init_vdso(void)
-{
-	struct page *um_vdso;
-
-	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
-
-	um_vdso_addr = task_size - PAGE_SIZE;
-
-	vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
-	if (!vdsop)
-		goto oom;
-
-	um_vdso = alloc_page(GFP_KERNEL);
-	if (!um_vdso) {
-		kfree(vdsop);
-
-		goto oom;
-	}
-
-	copy_page(page_address(um_vdso), vdso_start);
-	*vdsop = um_vdso;
-
-	return 0;
-
-oom:
-	printk(KERN_ERR "Cannot allocate vdso\n");
-	vdso_enabled = 0;
-
-	return -ENOMEM;
-}
-subsys_initcall(init_vdso);
-
-int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
-{
-	int err;
-	struct mm_struct *mm = current->mm;
-
-	if (!vdso_enabled)
-		return 0;
-
-	down_write(&mm->mmap_sem);
-
-	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
-		VM_READ|VM_EXEC|
-		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-		VM_ALWAYSDUMP,
-		vdsop);
-
-	up_write(&mm->mmap_sem);
-
-	return err;
-}
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/boot/compressed/Makefile linux-libre-3.2-gnu1/arch/unicore32/boot/compressed/Makefile
--- linux-libre-3.1-gnu1/arch/unicore32/boot/compressed/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/boot/compressed/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,8 @@
 # Copyright (C) 2001~2010 GUAN Xue-tao
 #
 
-EXTRA_CFLAGS	:= -fpic -fno-builtin
-EXTRA_AFLAGS	:= -Wa,-march=all
+ccflags-y	:= -fpic -fno-builtin
+asflags-y	:= -Wa,-march=all
 
 OBJS		:= misc.o
 
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/include/asm/bitops.h linux-libre-3.2-gnu1/arch/unicore32/include/asm/bitops.h
--- linux-libre-3.1-gnu1/arch/unicore32/include/asm/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,6 @@
 #ifndef __UNICORE_BITOPS_H__
 #define __UNICORE_BITOPS_H__
 
-#define find_next_bit		__uc32_find_next_bit
-#define find_next_zero_bit	__uc32_find_next_zero_bit
-
-#define find_first_bit		__uc32_find_first_bit
-#define find_first_zero_bit	__uc32_find_first_zero_bit
-
 #define _ASM_GENERIC_BITOPS_FLS_H_
 #define _ASM_GENERIC_BITOPS___FLS_H_
 #define _ASM_GENERIC_BITOPS_FFS_H_
@@ -44,4 +38,10 @@ static inline int fls(int x)
 
 #include <asm-generic/bitops.h>
 
+/* following definitions: to avoid using codes in lib/find_*.c */
+#define find_next_bit		find_next_bit
+#define find_next_zero_bit	find_next_zero_bit
+#define find_first_bit		find_first_bit
+#define find_first_zero_bit	find_first_zero_bit
+
 #endif /* __UNICORE_BITOPS_H__ */
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/include/asm/io.h linux-libre-3.2-gnu1/arch/unicore32/include/asm/io.h
--- linux-libre-3.1-gnu1/arch/unicore32/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@ extern void __uc32_iounmap(volatile void
  * ioremap and friends.
  *
  * ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
  *
  */
 #define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/include/asm/processor.h linux-libre-3.2-gnu1/arch/unicore32/include/asm/processor.h
--- linux-libre-3.1-gnu1/arch/unicore32/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,6 @@ struct thread_struct {
 #define start_thread(regs, pc, sp)					\
 ({									\
 	unsigned long *stack = (unsigned long *)sp;			\
-	set_fs(USER_DS);						\
 	memset(regs->uregs, 0, sizeof(regs->uregs));			\
 	regs->UCreg_asr = USER_MODE;					\
 	regs->UCreg_pc = pc & ~1;	/* pc */                        \
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/Kconfig linux-libre-3.2-gnu1/arch/unicore32/Kconfig
--- linux-libre-3.1-gnu1/arch/unicore32/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -237,13 +237,13 @@ menu "PKUnity NetBook-0916 Features"
 
 config I2C_BATTERY_BQ27200
 	tristate "I2C Battery BQ27200 Support"
-	select PUV3_I2C
+	select I2C_PUV3
 	select POWER_SUPPLY
 	select BATTERY_BQ27x00
 
 config I2C_EEPROM_AT24
 	tristate "I2C EEPROMs AT24 support"
-	select PUV3_I2C
+	select I2C_PUV3
 	select MISC_DEVICES
 	select EEPROM_AT24
 
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/Kconfig.debug linux-libre-3.2-gnu1/arch/unicore32/Kconfig.debug
--- linux-libre-3.1-gnu1/arch/unicore32/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -44,18 +44,4 @@ config DEBUG_OCD
 	  Say Y here if you want the debug print routines to direct their
 	  output to the UniCore On-Chip-Debugger channel using CP #1.
 
-config DEBUG_OCD_BREAKPOINT
-	bool "Breakpoint support via On-Chip-Debugger"
-	depends on DEBUG_OCD
-
-config DEBUG_UART
-	int "Kernel low-level debugging messages via serial port"
-	depends on DEBUG_LL
-	range 0 1
-	default "0"
-	help
-	  Choice for UART for kernel low-level using PKUnity UARTS,
-	  should be between zero and one. The port must have been
-	  initialised by the boot-loader before use.
-
 endmenu
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/kernel/ksyms.c linux-libre-3.2-gnu1/arch/unicore32/kernel/ksyms.c
--- linux-libre-3.1-gnu1/arch/unicore32/kernel/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/kernel/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,8 @@
 
 #include "ksyms.h"
 
-EXPORT_SYMBOL(__uc32_find_next_zero_bit);
-EXPORT_SYMBOL(__uc32_find_next_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_next_bit);
 
 EXPORT_SYMBOL(__backtrace);
 
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/lib/findbit.S linux-libre-3.2-gnu1/arch/unicore32/lib/findbit.S
--- linux-libre-3.1-gnu1/arch/unicore32/lib/findbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/lib/findbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  * Purpose  : Find a 'zero' bit
  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
  */
-__uc32_find_first_zero_bit:
+ENTRY(find_first_zero_bit)
 		cxor.a	r1, #0
 		beq	3f
 		mov	r2, #0
@@ -29,13 +29,14 @@ __uc32_find_first_zero_bit:
 		bub	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(find_first_zero_bit)
 
 /*
  * Purpose  : Find next 'zero' bit
  * Prototype: int find_next_zero_bit
  *		(void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_zero_bit)
+ENTRY(find_next_zero_bit)
 		cxor.a	r1, #0
 		beq	3b
 		and.a	ip, r2, #7
@@ -47,14 +48,14 @@ ENTRY(__uc32_find_next_zero_bit)
 		or	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
-ENDPROC(__uc32_find_next_zero_bit)
+ENDPROC(find_next_zero_bit)
 
 /*
  * Purpose  : Find a 'one' bit
  * Prototype: int find_first_bit
  *		(const unsigned long *addr, unsigned int maxbit);
  */
-__uc32_find_first_bit:
+ENTRY(find_first_bit)
 		cxor.a	r1, #0
 		beq	3f
 		mov	r2, #0
@@ -66,13 +67,14 @@ __uc32_find_first_bit:
 		bub	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(find_first_bit)
 
 /*
  * Purpose  : Find next 'one' bit
  * Prototype: int find_next_zero_bit
  *		(void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_bit)
+ENTRY(find_next_bit)
 		cxor.a	r1, #0
 		beq	3b
 		and.a	ip, r2, #7
@@ -83,7 +85,7 @@ ENTRY(__uc32_find_next_bit)
 		or	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
-ENDPROC(__uc32_find_next_bit)
+ENDPROC(find_next_bit)
 
 /*
  * One or more bits in the LSB of r3 are assumed to be set.
diff -druNp linux-libre-3.1-gnu1/arch/unicore32/mm/init.c linux-libre-3.2-gnu1/arch/unicore32/mm/init.c
--- linux-libre-3.1-gnu1/arch/unicore32/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/unicore32/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/sections.h>
 #include <asm/setup.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/boot/header.S linux-libre-3.2-gnu1/arch/x86/boot/header.S
--- linux-libre-3.1-gnu1/arch/x86/boot/header.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/boot/header.S	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@ start_sys_seg:	.word	SYSSEG		# obsolete
 
 type_of_loader:	.byte	0		# 0 means ancient bootloader, newer
 					# bootloaders know to change this.
-					# See Documentation/i386/boot.txt for
+					# See Documentation/x86/boot.txt for
 					# assigned ids
 
 # flags, unused bits must be zero (RFU) bit within loadflags
diff -druNp linux-libre-3.1-gnu1/arch/x86/configs/x86_64_defconfig linux-libre-3.2-gnu1/arch/x86/configs/x86_64_defconfig
--- linux-libre-3.1-gnu1/arch/x86/configs/x86_64_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/configs/x86_64_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -67,8 +67,8 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_X86_ACPI_CPUFREQ=y
 CONFIG_PCI_MMCONFIG=y
-CONFIG_DMAR=y
-# CONFIG_DMAR_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU=y
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCCARD=y
 CONFIG_YENTA=y
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/aes_glue.c linux-libre-3.2-gnu1/arch/x86/crypto/aes_glue.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/aes_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/aes_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,9 @@
  *
  */
 
+#include <linux/module.h>
 #include <crypto/aes.h>
+#include <asm/aes.h>
 
 asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
 asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/aesni-intel_glue.c linux-libre-3.2-gnu1/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/aesni-intel_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/aesni-intel_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/hardirq.h>
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <linux/module.h>
 #include <linux/err.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/blowfish_glue.c linux-libre-3.2-gnu1/arch/x86/crypto/blowfish_glue.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/blowfish_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/blowfish_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,492 @@
+/*
+ * Glue Code for assembler optimized version of Blowfish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <crypto/blowfish.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+/* regular block cipher functions */
+asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src,
+				   bool xor);
+asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
+
+/* 4-way parallel cipher functions */
+asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src, bool xor);
+asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src);
+
+static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, true);
+}
+
+static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, true);
+}
+
+static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static struct crypto_alg bf_alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-asm",
+	.cra_priority		=	200,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(bf_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+			.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+			.cia_setkey		=	blowfish_setkey,
+			.cia_encrypt		=	blowfish_encrypt,
+			.cia_decrypt		=	blowfish_decrypt,
+		}
+	}
+};
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct bf_ctx *, u8 *, const u8 *),
+		     void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *))
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process four block batch */
+		if (nbytes >= bsize * 4) {
+			do {
+				fn_4way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 4;
+				wdst += bsize * 4;
+				nbytes -= bsize * 4;
+			} while (nbytes >= bsize * 4);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_enc_blk, blowfish_enc_blk_4way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_dec_blk, blowfish_dec_blk_4way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(blowfish)",
+	.cra_driver_name	= "ecb-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 *iv = (u64 *)walk->iv;
+
+	do {
+		*dst = *src ^ *iv;
+		blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	*(u64 *)walk->iv = *iv;
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ivs[4 - 1];
+	u64 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			nbytes -= bsize * 4 - bsize;
+			src -= 4 - 1;
+			dst -= 4 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+			ivs[2] = src[2];
+
+			blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src);
+
+			dst[1] ^= ivs[0];
+			dst[2] ^= ivs[1];
+			dst[3] ^= ivs[2];
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			*dst ^= *(src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		*dst ^= *(src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	*dst ^= *(u64 *)walk->iv;
+	*(u64 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(blowfish)",
+	.cra_driver_name	= "cbc-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk)
+{
+	u8 *ctrblk = walk->iv;
+	u8 keystream[BF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	blowfish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, BF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+	__be64 ctrblocks[4];
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+				dst[3] = src[3];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			ctrblocks[0] = cpu_to_be64(ctrblk++);
+			ctrblocks[1] = cpu_to_be64(ctrblk++);
+			ctrblocks[2] = cpu_to_be64(ctrblk++);
+			ctrblocks[3] = cpu_to_be64(ctrblk++);
+
+			blowfish_enc_blk_xor_4way(ctx, (u8 *)dst,
+						  (u8 *)ctrblocks);
+
+			src += 4;
+			dst += 4;
+		} while ((nbytes -= bsize * 4) >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+		blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+	} while ((nbytes -= bsize) >= bsize);
+
+done:
+	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(blowfish)",
+	.cra_driver_name	= "ctr-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+static int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&bf_alg);
+	if (err)
+		goto bf_err;
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	crypto_unregister_alg(&bf_alg);
+bf_err:
+	return err;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+	crypto_unregister_alg(&bf_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
+MODULE_ALIAS("blowfish");
+MODULE_ALIAS("blowfish-asm");
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/blowfish-x86_64-asm_64.S linux-libre-3.2-gnu1/arch/x86/crypto/blowfish-x86_64-asm_64.S
--- linux-libre-3.1-gnu1/arch/x86/crypto/blowfish-x86_64-asm_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/blowfish-x86_64-asm_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,390 @@
+/*
+ * Blowfish Cipher Algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "blowfish-x86_64-asm.S"
+.text
+
+/* structure of crypto context */
+#define p	0
+#define s0	((16 + 2) * 4)
+#define s1	((16 + 2 + (1 * 256)) * 4)
+#define s2	((16 + 2 + (2 * 256)) * 4)
+#define s3	((16 + 2 + (3 * 256)) * 4)
+
+/* register macros */
+#define CTX %rdi
+#define RIO %rsi
+
+#define RX0 %rax
+#define RX1 %rbx
+#define RX2 %rcx
+#define RX3 %rdx
+
+#define RX0d %eax
+#define RX1d %ebx
+#define RX2d %ecx
+#define RX3d %edx
+
+#define RX0bl %al
+#define RX1bl %bl
+#define RX2bl %cl
+#define RX3bl %dl
+
+#define RX0bh %ah
+#define RX1bh %bh
+#define RX2bh %ch
+#define RX3bh %dh
+
+#define RT0 %rbp
+#define RT1 %rsi
+#define RT2 %r8
+#define RT3 %r9
+
+#define RT0d %ebp
+#define RT1d %esi
+#define RT2d %r8d
+#define RT3d %r9d
+
+#define RKEY %r10
+
+/***********************************************************************
+ * 1-way blowfish
+ ***********************************************************************/
+#define F() \
+	rorq $16,		RX0; \
+	movzbl RX0bh,		RT0d; \
+	movzbl RX0bl,		RT1d; \
+	rolq $16,		RX0; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT1,4),	RT0d; \
+	movzbl RX0bh,		RT1d; \
+	movzbl RX0bl,		RT2d; \
+	rolq $32,		RX0; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT2,4),	RT0d; \
+	xorq RT0,		RX0;
+
+#define add_roundkey_enc(n) \
+	xorq p+4*(n)(CTX), 	RX0;
+
+#define round_enc(n) \
+	add_roundkey_enc(n); \
+	\
+	F(); \
+	F();
+
+#define add_roundkey_dec(n) \
+	movq p+4*(n-1)(CTX),	RT0; \
+	rorq $32,		RT0; \
+	xorq RT0,		RX0;
+
+#define round_dec(n) \
+	add_roundkey_dec(n); \
+	\
+	F(); \
+	F(); \
+
+#define read_block() \
+	movq (RIO), 		RX0; \
+	rorq $32, 		RX0; \
+	bswapq 			RX0;
+
+#define write_block() \
+	bswapq 			RX0; \
+	movq RX0, 		(RIO);
+
+#define xor_block() \
+	bswapq 			RX0; \
+	xorq RX0, 		(RIO);
+
+.align 8
+.global __blowfish_enc_blk
+.type   __blowfish_enc_blk,@function;
+
+__blowfish_enc_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_enc(0);
+	round_enc(2);
+	round_enc(4);
+	round_enc(6);
+	round_enc(8);
+	round_enc(10);
+	round_enc(12);
+	round_enc(14);
+	add_roundkey_enc(16);
+
+	movq %r11, %rbp;
+
+	movq %r10, RIO;
+	test %cl, %cl;
+	jnz __enc_xor;
+
+	write_block();
+	ret;
+__enc_xor:
+	xor_block();
+	ret;
+
+.align 8
+.global blowfish_dec_blk
+.type   blowfish_dec_blk,@function;
+
+blowfish_dec_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_dec(17);
+	round_dec(15);
+	round_dec(13);
+	round_dec(11);
+	round_dec(9);
+	round_dec(7);
+	round_dec(5);
+	round_dec(3);
+	add_roundkey_dec(1);
+
+	movq %r10, RIO;
+	write_block();
+
+	movq %r11, %rbp;
+
+	ret;
+
+/**********************************************************************
+  4-way blowfish, four blocks parallel
+ **********************************************************************/
+
+/* F() for 4-way. Slower when used alone/1-way, but faster when used
+ * parallel/4-way (tested on AMD Phenom II & Intel Xeon E7330).
+ */
+#define F4(x) \
+	movzbl x ## bh,		RT1d; \
+	movzbl x ## bl,		RT3d; \
+	rorq $16,		x; \
+	movzbl x ## bh,		RT0d; \
+	movzbl x ## bl,		RT2d; \
+	rorq $16,		x; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT2,4),	RT0d; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT3,4),	RT0d; \
+	xorq RT0,		x;
+
+#define add_preloaded_roundkey4() \
+	xorq RKEY,		RX0; \
+	xorq RKEY,		RX1; \
+	xorq RKEY,		RX2; \
+	xorq RKEY,		RX3;
+
+#define preload_roundkey_enc(n) \
+	movq p+4*(n)(CTX),	RKEY;
+
+#define add_roundkey_enc4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_enc(n + 2);
+
+#define round_enc4(n) \
+	add_roundkey_enc4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define preload_roundkey_dec(n) \
+	movq p+4*((n)-1)(CTX),	RKEY; \
+	rorq $32,		RKEY;
+
+#define add_roundkey_dec4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_dec(n - 2);
+
+#define round_dec4(n) \
+	add_roundkey_dec4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define read_block4() \
+	movq (RIO),		RX0; \
+	rorq $32,		RX0; \
+	bswapq 			RX0; \
+	\
+	movq 8(RIO),		RX1; \
+	rorq $32,		RX1; \
+	bswapq 			RX1; \
+	\
+	movq 16(RIO),		RX2; \
+	rorq $32,		RX2; \
+	bswapq 			RX2; \
+	\
+	movq 24(RIO),		RX3; \
+	rorq $32,		RX3; \
+	bswapq 			RX3;
+
+#define write_block4() \
+	bswapq 			RX0; \
+	movq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	movq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	movq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	movq RX3,		24(RIO);
+
+#define xor_block4() \
+	bswapq 			RX0; \
+	xorq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	xorq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	xorq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	xorq RX3,		24(RIO);
+
+.align 8
+.global __blowfish_enc_blk_4way
+.type   __blowfish_enc_blk_4way,@function;
+
+__blowfish_enc_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	pushq %rcx;
+
+	preload_roundkey_enc(0);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_enc4(0);
+	round_enc4(2);
+	round_enc4(4);
+	round_enc4(6);
+	round_enc4(8);
+	round_enc4(10);
+	round_enc4(12);
+	round_enc4(14);
+	add_preloaded_roundkey4();
+
+	popq %rbp;
+	movq %r11, RIO;
+
+	test %bpl, %bpl;
+	jnz __enc_xor4;
+
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+__enc_xor4:
+	xor_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+.align 8
+.global blowfish_dec_blk_4way
+.type   blowfish_dec_blk_4way,@function;
+
+blowfish_dec_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	preload_roundkey_dec(17);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_dec4(17);
+	round_dec4(15);
+	round_dec4(13);
+	round_dec4(11);
+	round_dec4(9);
+	round_dec4(7);
+	round_dec4(5);
+	round_dec4(3);
+	add_preloaded_roundkey4();
+
+	movq %r11, RIO;
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+
+	ret;
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/Makefile linux-libre-3.2-gnu1/arch/x86/crypto/Makefile
--- linux-libre-3.1-gnu1/arch/x86/crypto/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,21 +7,33 @@ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twof
 obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
+obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
 
 aes-i586-y := aes-i586-asm_32.o aes_glue.o
 twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
 salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+
+# enable AVX support only when $(AS) can actually assemble the instructions
+ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
+AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
+CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
+endif
+sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/sha1_ssse3_asm.S linux-libre-3.2-gnu1/arch/x86/crypto/sha1_ssse3_asm.S
--- linux-libre-3.1-gnu1/arch/x86/crypto/sha1_ssse3_asm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/sha1_ssse3_asm.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,558 @@
+/*
+ * This is a SIMD SHA-1 implementation. It requires the Intel(R) Supplemental
+ * SSE3 instruction set extensions introduced in Intel Core Microarchitecture
+ * processors. CPUs supporting Intel(R) AVX extensions will get an additional
+ * boost.
+ *
+ * This work was inspired by the vectorized implementation of Dean Gaudet.
+ * Additional information on it can be found at:
+ *    http://www.arctic.org/~dean/crypto/sha1.html
+ *
+ * It was improved upon with more efficient vectorization of the message
+ * scheduling. This implementation has also been optimized for all current and
+ * several future generations of Intel CPUs.
+ *
+ * See this article for more information about the implementation details:
+ *   http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/
+ *
+ * Copyright (C) 2010, Intel Corp.
+ *   Authors: Maxim Locktyukhin <maxim.locktyukhin@intel.com>
+ *            Ronen Zohar <ronen.zohar@intel.com>
+ *
+ * Converted to AT&T syntax and adapted for inclusion in the Linux kernel:
+ *   Author: Mathias Krause <minipli@googlemail.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.
+ */
+
+#define CTX	%rdi	// arg1
+#define BUF	%rsi	// arg2
+#define CNT	%rdx	// arg3
+
+#define REG_A	%ecx
+#define REG_B	%esi
+#define REG_C	%edi
+#define REG_D	%ebp
+#define REG_E	%edx
+
+#define REG_T1	%eax
+#define REG_T2	%ebx
+
+#define K_BASE		%r8
+#define HASH_PTR	%r9
+#define BUFFER_PTR	%r10
+#define BUFFER_END	%r11
+
+#define W_TMP1	%xmm0
+#define W_TMP2	%xmm9
+
+#define W0	%xmm1
+#define W4	%xmm2
+#define W8	%xmm3
+#define W12	%xmm4
+#define W16	%xmm5
+#define W20	%xmm6
+#define W24	%xmm7
+#define W28	%xmm8
+
+#define XMM_SHUFB_BSWAP	%xmm10
+
+/* we keep window of 64 w[i]+K pre-calculated values in a circular buffer */
+#define WK(t)	(((t) & 15) * 4)(%rsp)
+#define W_PRECALC_AHEAD	16
+
+/*
+ * This macro implements the SHA-1 function's body for single 64-byte block
+ * param: function's name
+ */
+.macro SHA1_VECTOR_ASM  name
+	.global	\name
+	.type	\name, @function
+	.align 32
+\name:
+	push	%rbx
+	push	%rbp
+	push	%r12
+
+	mov	%rsp, %r12
+	sub	$64, %rsp		# allocate workspace
+	and	$~15, %rsp		# align stack
+
+	mov	CTX, HASH_PTR
+	mov	BUF, BUFFER_PTR
+
+	shl	$6, CNT			# multiply by 64
+	add	BUF, CNT
+	mov	CNT, BUFFER_END
+
+	lea	K_XMM_AR(%rip), K_BASE
+	xmm_mov	BSWAP_SHUFB_CTL(%rip), XMM_SHUFB_BSWAP
+
+	SHA1_PIPELINED_MAIN_BODY
+
+	# cleanup workspace
+	mov	$8, %ecx
+	mov	%rsp, %rdi
+	xor	%rax, %rax
+	rep stosq
+
+	mov	%r12, %rsp		# deallocate workspace
+
+	pop	%r12
+	pop	%rbp
+	pop	%rbx
+	ret
+
+	.size	\name, .-\name
+.endm
+
+/*
+ * This macro implements 80 rounds of SHA-1 for one 64-byte block
+ */
+.macro SHA1_PIPELINED_MAIN_BODY
+	INIT_REGALLOC
+
+	mov	  (HASH_PTR), A
+	mov	 4(HASH_PTR), B
+	mov	 8(HASH_PTR), C
+	mov	12(HASH_PTR), D
+	mov	16(HASH_PTR), E
+
+  .set i, 0
+  .rept W_PRECALC_AHEAD
+	W_PRECALC i
+    .set i, (i+1)
+  .endr
+
+.align 4
+1:
+	RR F1,A,B,C,D,E,0
+	RR F1,D,E,A,B,C,2
+	RR F1,B,C,D,E,A,4
+	RR F1,E,A,B,C,D,6
+	RR F1,C,D,E,A,B,8
+
+	RR F1,A,B,C,D,E,10
+	RR F1,D,E,A,B,C,12
+	RR F1,B,C,D,E,A,14
+	RR F1,E,A,B,C,D,16
+	RR F1,C,D,E,A,B,18
+
+	RR F2,A,B,C,D,E,20
+	RR F2,D,E,A,B,C,22
+	RR F2,B,C,D,E,A,24
+	RR F2,E,A,B,C,D,26
+	RR F2,C,D,E,A,B,28
+
+	RR F2,A,B,C,D,E,30
+	RR F2,D,E,A,B,C,32
+	RR F2,B,C,D,E,A,34
+	RR F2,E,A,B,C,D,36
+	RR F2,C,D,E,A,B,38
+
+	RR F3,A,B,C,D,E,40
+	RR F3,D,E,A,B,C,42
+	RR F3,B,C,D,E,A,44
+	RR F3,E,A,B,C,D,46
+	RR F3,C,D,E,A,B,48
+
+	RR F3,A,B,C,D,E,50
+	RR F3,D,E,A,B,C,52
+	RR F3,B,C,D,E,A,54
+	RR F3,E,A,B,C,D,56
+	RR F3,C,D,E,A,B,58
+
+	add	$64, BUFFER_PTR		# move to the next 64-byte block
+	cmp	BUFFER_END, BUFFER_PTR	# if the current is the last one use
+	cmovae	K_BASE, BUFFER_PTR	# dummy source to avoid buffer overrun
+
+	RR F4,A,B,C,D,E,60
+	RR F4,D,E,A,B,C,62
+	RR F4,B,C,D,E,A,64
+	RR F4,E,A,B,C,D,66
+	RR F4,C,D,E,A,B,68
+
+	RR F4,A,B,C,D,E,70
+	RR F4,D,E,A,B,C,72
+	RR F4,B,C,D,E,A,74
+	RR F4,E,A,B,C,D,76
+	RR F4,C,D,E,A,B,78
+
+	UPDATE_HASH   (HASH_PTR), A
+	UPDATE_HASH  4(HASH_PTR), B
+	UPDATE_HASH  8(HASH_PTR), C
+	UPDATE_HASH 12(HASH_PTR), D
+	UPDATE_HASH 16(HASH_PTR), E
+
+	RESTORE_RENAMED_REGS
+	cmp	K_BASE, BUFFER_PTR	# K_BASE means, we reached the end
+	jne	1b
+.endm
+
+.macro INIT_REGALLOC
+  .set A, REG_A
+  .set B, REG_B
+  .set C, REG_C
+  .set D, REG_D
+  .set E, REG_E
+  .set T1, REG_T1
+  .set T2, REG_T2
+.endm
+
+.macro RESTORE_RENAMED_REGS
+	# order is important (REG_C is where it should be)
+	mov	B, REG_B
+	mov	D, REG_D
+	mov	A, REG_A
+	mov	E, REG_E
+.endm
+
+.macro SWAP_REG_NAMES  a, b
+  .set _T, \a
+  .set \a, \b
+  .set \b, _T
+.endm
+
+.macro F1  b, c, d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	xor	\d, T1
+	and	\b, T1
+	xor	\d, T1
+.endm
+
+.macro F2  b, c, d
+	mov	\d, T1
+	SWAP_REG_NAMES \d, T1
+	xor	\c, T1
+	xor	\b, T1
+.endm
+
+.macro F3  b, c ,d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	mov	\b, T2
+	or	\b, T1
+	and	\c, T2
+	and	\d, T1
+	or	T2, T1
+.endm
+
+.macro F4  b, c, d
+	F2 \b, \c, \d
+.endm
+
+.macro UPDATE_HASH  hash, val
+	add	\hash, \val
+	mov	\val, \hash
+.endm
+
+/*
+ * RR does two rounds of SHA-1 back to back with W[] pre-calc
+ *   t1 = F(b, c, d);   e += w(i)
+ *   e += t1;           b <<= 30;   d  += w(i+1);
+ *   t1 = F(a, b, c);
+ *   d += t1;           a <<= 5;
+ *   e += a;
+ *   t1 = e;            a >>= 7;
+ *   t1 <<= 5;
+ *   d += t1;
+ */
+.macro RR  F, a, b, c, d, e, round
+	add	WK(\round), \e
+	\F   \b, \c, \d		# t1 = F(b, c, d);
+	W_PRECALC (\round + W_PRECALC_AHEAD)
+	rol	$30, \b
+	add	T1, \e
+	add	WK(\round + 1), \d
+
+	\F   \a, \b, \c
+	W_PRECALC (\round + W_PRECALC_AHEAD + 1)
+	rol	$5, \a
+	add	\a, \e
+	add	T1, \d
+	ror	$7, \a		# (a <<r 5) >>r 7) => a <<r 30)
+
+	mov	\e, T1
+	SWAP_REG_NAMES \e, T1
+
+	rol	$5, T1
+	add	T1, \d
+
+	# write:  \a, \b
+	# rotate: \a<=\d, \b<=\e, \c<=\a, \d<=\b, \e<=\c
+.endm
+
+.macro W_PRECALC  r
+  .set i, \r
+
+  .if (i < 20)
+    .set K_XMM, 0
+  .elseif (i < 40)
+    .set K_XMM, 16
+  .elseif (i < 60)
+    .set K_XMM, 32
+  .elseif (i < 80)
+    .set K_XMM, 48
+  .endif
+
+  .if ((i < 16) || ((i >= 80) && (i < (80 + W_PRECALC_AHEAD))))
+    .set i, ((\r) % 80)	    # pre-compute for the next iteration
+    .if (i == 0)
+	W_PRECALC_RESET
+    .endif
+	W_PRECALC_00_15
+  .elseif (i<32)
+	W_PRECALC_16_31
+  .elseif (i < 80)   // rounds 32-79
+	W_PRECALC_32_79
+  .endif
+.endm
+
+.macro W_PRECALC_RESET
+  .set W,          W0
+  .set W_minus_04, W4
+  .set W_minus_08, W8
+  .set W_minus_12, W12
+  .set W_minus_16, W16
+  .set W_minus_20, W20
+  .set W_minus_24, W24
+  .set W_minus_28, W28
+  .set W_minus_32, W
+.endm
+
+.macro W_PRECALC_ROTATE
+  .set W_minus_32, W_minus_28
+  .set W_minus_28, W_minus_24
+  .set W_minus_24, W_minus_20
+  .set W_minus_20, W_minus_16
+  .set W_minus_16, W_minus_12
+  .set W_minus_12, W_minus_08
+  .set W_minus_08, W_minus_04
+  .set W_minus_04, W
+  .set W,          W_minus_32
+.endm
+
+.macro W_PRECALC_SSSE3
+
+.macro W_PRECALC_00_15
+	W_PRECALC_00_15_SSSE3
+.endm
+.macro W_PRECALC_16_31
+	W_PRECALC_16_31_SSSE3
+.endm
+.macro W_PRECALC_32_79
+	W_PRECALC_32_79_SSSE3
+.endm
+
+/* message scheduling pre-compute for rounds 0-15 */
+.macro W_PRECALC_00_15_SSSE3
+  .if ((i & 3) == 0)
+	movdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	pshufb	XMM_SHUFB_BSWAP, W_TMP1
+	movdqa	W_TMP1, W
+  .elseif ((i & 3) == 2)
+	paddd	(K_BASE), W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa  W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 16-31
+ *
+ * - calculating last 32 w[i] values in 8 XMM registers
+ * - pre-calculate K+w[i] values and store to mem, for later load by ALU add
+ *   instruction
+ *
+ * some "heavy-lifting" vectorization for rounds 16-31 due to w[i]->w[i-3]
+ * dependency, but improves for 32-79
+ */
+.macro W_PRECALC_16_31_SSSE3
+  # blended scheduling of vector and scalar instruction streams, one 4-wide
+  # vector iteration / 4 scalar rounds
+  .if ((i & 3) == 0)
+	movdqa	W_minus_12, W
+	palignr	$8, W_minus_16, W	# w[i-14]
+	movdqa	W_minus_04, W_TMP1
+	psrldq	$4, W_TMP1		# w[i-3]
+	pxor	W_minus_08, W
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W_TMP1
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP2
+	movdqa	W, W_TMP1
+	pslldq	$12, W_TMP2
+  .elseif ((i & 3) == 2)
+	psrld	$31, W
+	pslld	$1, W_TMP1
+	por	W, W_TMP1
+	movdqa	W_TMP2, W
+	psrld	$30, W_TMP2
+	pslld	$2, W
+  .elseif ((i & 3) == 3)
+	pxor	W, W_TMP1
+	pxor	W_TMP2, W_TMP1
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 32-79
+ *
+ * in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8]  ^ w[i-14] ^ w[i-16]) rol 1
+ * instead we do equal:    w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
+ * allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
+ */
+.macro W_PRECALC_32_79_SSSE3
+  .if ((i & 3) == 0)
+	movdqa	W_minus_04, W_TMP1
+	pxor	W_minus_28, W		# W is W_minus_32 before xor
+	palignr	$8, W_minus_08, W_TMP1
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP1
+  .elseif ((i & 3) == 2)
+	psrld	$30, W
+	pslld	$2, W_TMP1
+	por	W, W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm		// W_PRECALC_SSSE3
+
+
+#define K1	0x5a827999
+#define K2	0x6ed9eba1
+#define K3	0x8f1bbcdc
+#define K4	0xca62c1d6
+
+.section .rodata
+.align 16
+
+K_XMM_AR:
+	.long K1, K1, K1, K1
+	.long K2, K2, K2, K2
+	.long K3, K3, K3, K3
+	.long K4, K4, K4, K4
+
+BSWAP_SHUFB_CTL:
+	.long 0x00010203
+	.long 0x04050607
+	.long 0x08090a0b
+	.long 0x0c0d0e0f
+
+
+.section .text
+
+W_PRECALC_SSSE3
+.macro xmm_mov a, b
+	movdqu	\a,\b
+.endm
+
+/* SSSE3 optimized implementation:
+ *  extern "C" void sha1_transform_ssse3(u32 *digest, const char *data, u32 *ws,
+ *                                       unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_ssse3
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+
+.macro W_PRECALC_AVX
+
+.purgem W_PRECALC_00_15
+.macro  W_PRECALC_00_15
+    W_PRECALC_00_15_AVX
+.endm
+.purgem W_PRECALC_16_31
+.macro  W_PRECALC_16_31
+    W_PRECALC_16_31_AVX
+.endm
+.purgem W_PRECALC_32_79
+.macro  W_PRECALC_32_79
+    W_PRECALC_32_79_AVX
+.endm
+
+.macro W_PRECALC_00_15_AVX
+  .if ((i & 3) == 0)
+	vmovdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	vpshufb	XMM_SHUFB_BSWAP, W_TMP1, W
+  .elseif ((i & 3) == 2)
+	vpaddd	(K_BASE), W, W_TMP1
+  .elseif ((i & 3) == 3)
+	vmovdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_16_31_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_16, W_minus_12, W	# w[i-14]
+	vpsrldq	$4, W_minus_04, W_TMP1		# w[i-3]
+	vpxor	W_minus_08, W, W
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+  .elseif ((i & 3) == 1)
+	vpxor	W_TMP1, W, W
+	vpslldq	$12, W, W_TMP2
+	vpslld	$1, W, W_TMP1
+  .elseif ((i & 3) == 2)
+	vpsrld	$31, W, W
+	vpor	W, W_TMP1, W_TMP1
+	vpslld	$2, W_TMP2, W
+	vpsrld	$30, W_TMP2, W_TMP2
+  .elseif ((i & 3) == 3)
+	vpxor	W, W_TMP1, W_TMP1
+	vpxor	W_TMP2, W_TMP1, W
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_32_79_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_08, W_minus_04, W_TMP1
+	vpxor	W_minus_28, W, W		# W is W_minus_32 before xor
+  .elseif ((i & 3) == 1)
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+	vpxor	W_TMP1, W, W
+  .elseif ((i & 3) == 2)
+	vpslld	$2, W, W_TMP1
+	vpsrld	$30, W, W
+	vpor	W, W_TMP1, W
+  .elseif ((i & 3) == 3)
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm    // W_PRECALC_AVX
+
+W_PRECALC_AVX
+.purgem xmm_mov
+.macro xmm_mov a, b
+	vmovdqu	\a,\b
+.endm
+
+
+/* AVX optimized implementation:
+ *  extern "C" void sha1_transform_avx(u32 *digest, const char *data, u32 *ws,
+ *                                     unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_avx
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/sha1_ssse3_glue.c linux-libre-3.2-gnu1/arch/x86/crypto/sha1_ssse3_glue.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/sha1_ssse3_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/sha1_ssse3_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,240 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * Supplemental SSE3 instructions.
+ *
+ * This file is based on sha1_generic.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.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.
+ *
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+
+
+asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
+				     unsigned int rounds);
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
+				   unsigned int rounds);
+#endif
+
+static asmlinkage void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
+
+
+static int sha1_ssse3_init(struct shash_desc *desc)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
+	return 0;
+}
+
+static int __sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_transform_asm(sctx->state, sctx->buffer, 1);
+	}
+
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+		sha1_transform_asm(sctx->state, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buffer, data + done, len - done);
+
+	return 0;
+}
+
+static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buffer + partial, data, len);
+
+		return 0;
+	}
+
+	if (!irq_fpu_usable()) {
+		res = crypto_sha1_update(desc, data, len);
+	} else {
+		kernel_fpu_begin();
+		res = __sha1_ssse3_update(desc, data, len, partial);
+		kernel_fpu_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+	if (!irq_fpu_usable()) {
+		crypto_sha1_update(desc, padding, padlen);
+		crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_fpu_begin();
+		/* We need to fill a whole block for __sha1_ssse3_update() */
+		if (padlen <= 56) {
+			sctx->count += padlen;
+			memcpy(sctx->buffer + index, padding, padlen);
+		} else {
+			__sha1_ssse3_update(desc, padding, padlen, index);
+		}
+		__sha1_ssse3_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+		kernel_fpu_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_export(struct shash_desc *desc, void *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_import(struct shash_desc *desc, const void *in)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_ssse3_init,
+	.update		=	sha1_ssse3_update,
+	.final		=	sha1_ssse3_final,
+	.export		=	sha1_ssse3_export,
+	.import		=	sha1_ssse3_import,
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-ssse3",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+static bool __init avx_usable(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave)
+		return false;
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+static int __init sha1_ssse3_mod_init(void)
+{
+	/* test for SSSE3 first */
+	if (cpu_has_ssse3)
+		sha1_transform_asm = sha1_transform_ssse3;
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+	/* allow AVX to override SSSE3, it's a little faster */
+	if (avx_usable())
+		sha1_transform_asm = sha1_transform_avx;
+#endif
+
+	if (sha1_transform_asm) {
+		pr_info("Using %s optimized SHA-1 implementation\n",
+		        sha1_transform_asm == sha1_transform_ssse3 ? "SSSE3"
+		                                                   : "AVX");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+	return -ENODEV;
+}
+
+static void __exit sha1_ssse3_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_ssse3_mod_init);
+module_exit(sha1_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha1");
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/twofish_glue_3way.c linux-libre-3.2-gnu1/arch/x86/crypto/twofish_glue_3way.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/twofish_glue_3way.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/twofish_glue_3way.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,472 @@
+/*
+ * Glue Code for 3-way parallel assembler optimized version of Twofish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/twofish.h>
+#include <crypto/b128ops.h>
+
+/* regular block cipher functions from twofish_x86_64 module */
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				       const u8 *src, bool xor);
+asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				     const u8 *src);
+
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, false);
+}
+
+static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
+					    const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, true);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
+		     void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process three block batch */
+		if (nbytes >= bsize * 3) {
+			do {
+				fn_3way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 3;
+				wdst += bsize * 3;
+				nbytes -= bsize * 3;
+			} while (nbytes >= bsize * 3);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(twofish)",
+	.cra_driver_name	= "ecb-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 *iv = (u128 *)walk->iv;
+
+	do {
+		u128_xor(dst, src, iv);
+		twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ivs[3 - 1];
+	u128 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			nbytes -= bsize * (3 - 1);
+			src -= 3 - 1;
+			dst -= 3 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+
+			twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+			u128_xor(dst + 1, dst + 1, ivs + 0);
+			u128_xor(dst + 2, dst + 2, ivs + 1);
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			u128_xor(dst, dst, src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		u128_xor(dst, dst, src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	u128_xor(dst, dst, (u128 *)walk->iv);
+	*(u128 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(twofish)",
+	.cra_driver_name	= "cbc-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static inline void u128_to_be128(be128 *dst, const u128 *src)
+{
+	dst->a = cpu_to_be64(src->a);
+	dst->b = cpu_to_be64(src->b);
+}
+
+static inline void be128_to_u128(u128 *dst, const be128 *src)
+{
+	dst->a = be64_to_cpu(src->a);
+	dst->b = be64_to_cpu(src->b);
+}
+
+static inline void u128_inc(u128 *i)
+{
+	i->b++;
+	if (!i->b)
+		i->a++;
+}
+
+static void ctr_crypt_final(struct blkcipher_desc *desc,
+			    struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	u8 *ctrblk = walk->iv;
+	u8 keystream[TF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	twofish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, TF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ctrblk;
+	be128 ctrblocks[3];
+
+	be128_to_u128(&ctrblk, (be128 *)walk->iv);
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			u128_to_be128(&ctrblocks[0], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[1], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[2], &ctrblk);
+			u128_inc(&ctrblk);
+
+			twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
+						 (u8 *)ctrblocks);
+
+			src += 3;
+			dst += 3;
+			nbytes -= bsize * 3;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		u128_to_be128(&ctrblocks[0], &ctrblk);
+		u128_inc(&ctrblk);
+
+		twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+		u128_xor(dst, dst, (u128 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+done:
+	u128_to_be128((be128 *)walk->iv, &ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(twofish)",
+	.cra_driver_name	= "ctr-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	return err;
+}
+
+void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
+MODULE_ALIAS("twofish");
+MODULE_ALIAS("twofish-asm");
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/twofish_glue.c linux-libre-3.2-gnu1/arch/x86/crypto/twofish_glue.c
--- linux-libre-3.1-gnu1/arch/x86/crypto/twofish_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/twofish_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,17 +44,21 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_enc_blk);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_dec_blk);
 
 static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_enc_blk(tfm, dst, src);
+	twofish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_dec_blk(tfm, dst, src);
+	twofish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static struct crypto_alg alg = {
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/twofish-i586-asm_32.S linux-libre-3.2-gnu1/arch/x86/crypto/twofish-i586-asm_32.S
--- linux-libre-3.1-gnu1/arch/x86/crypto/twofish-i586-asm_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/twofish-i586-asm_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 
 #define in_blk    12  /* input byte array address parameter*/
 #define out_blk   8  /* output byte array address parameter*/
-#define tfm       4  /* Twofish context structure */
+#define ctx       4  /* Twofish context structure */
 
 #define a_offset	0
 #define b_offset	4
@@ -229,8 +229,8 @@ twofish_enc_blk:
 	push    %esi
 	push    %edi
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
@@ -285,8 +285,8 @@ twofish_dec_blk:
 	push    %edi
 
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/twofish-x86_64-asm_64-3way.S linux-libre-3.2-gnu1/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
--- linux-libre-3.1-gnu1/arch/x86/crypto/twofish-x86_64-asm_64-3way.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/crypto/twofish-x86_64-asm_64-3way.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,316 @@
+/*
+ * Twofish Cipher 3-way parallel algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "twofish-x86_64-asm-3way.S"
+.text
+
+/* structure of crypto context */
+#define s0	0
+#define s1	1024
+#define s2	2048
+#define s3	3072
+#define w	4096
+#define k	4128
+
+/**********************************************************************
+  3-way twofish
+ **********************************************************************/
+#define CTX %rdi
+#define RIO %rdx
+
+#define RAB0 %rax
+#define RAB1 %rbx
+#define RAB2 %rcx
+
+#define RAB0d %eax
+#define RAB1d %ebx
+#define RAB2d %ecx
+
+#define RAB0bh %ah
+#define RAB1bh %bh
+#define RAB2bh %ch
+
+#define RAB0bl %al
+#define RAB1bl %bl
+#define RAB2bl %cl
+
+#define RCD0 %r8
+#define RCD1 %r9
+#define RCD2 %r10
+
+#define RCD0d %r8d
+#define RCD1d %r9d
+#define RCD2d %r10d
+
+#define RX0 %rbp
+#define RX1 %r11
+#define RX2 %r12
+
+#define RX0d %ebp
+#define RX1d %r11d
+#define RX2d %r12d
+
+#define RY0 %r13
+#define RY1 %r14
+#define RY2 %r15
+
+#define RY0d %r13d
+#define RY1d %r14d
+#define RY2d %r15d
+
+#define RT0 %rdx
+#define RT1 %rsi
+
+#define RT0d %edx
+#define RT1d %esi
+
+#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
+	movzbl ab ## bl,		tmp2 ## d; \
+	movzbl ab ## bh,		tmp1 ## d; \
+	rorq $(rot),			ab; \
+	op1##l T0(CTX, tmp2, 4),	dst ## d; \
+	op2##l T1(CTX, tmp1, 4),	dst ## d;
+
+/*
+ * Combined G1 & G2 function. Reordered with help of rotates to have moves
+ * at begining.
+ */
+#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
+	/* G1,1 && G2,1 */ \
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
+	\
+	/* G1,2 && G2,2 */ \
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
+	xchgq cd ## 0, ab ## 0; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
+	xchgq cd ## 1, ab ## 1; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
+	xchgq cd ## 2, ab ## 2;
+
+#define enc_round_end(ab, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	xorl ab ## d,			x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	shrq $32,			ab; \
+	roll $1,			ab ## d; \
+	xorl y ## d,			ab ## d; \
+	shlq $32,			ab; \
+	rorl $1,			x ## d; \
+	orq x,				ab;
+
+#define dec_round_end(ba, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	xorl ba ## d,			y ## d; \
+	shrq $32,			ba; \
+	roll $1,			ba ## d; \
+	xorl x ## d,			ba ## d; \
+	shlq $32,			ba; \
+	rorl $1,			y ## d; \
+	orq y,				ba;
+
+#define encrypt_round3(ab, cd, n) \
+	g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
+	\
+	enc_round_end(ab ## 0, RX0, RY0, n); \
+	enc_round_end(ab ## 1, RX1, RY1, n); \
+	enc_round_end(ab ## 2, RX2, RY2, n);
+
+#define decrypt_round3(ba, dc, n) \
+	g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
+	\
+	dec_round_end(ba ## 0, RX0, RY0, n); \
+	dec_round_end(ba ## 1, RX1, RY1, n); \
+	dec_round_end(ba ## 2, RX2, RY2, n);
+
+#define encrypt_cycle3(ab, cd, n) \
+	encrypt_round3(ab, cd, n*2); \
+	encrypt_round3(ab, cd, (n*2)+1);
+
+#define decrypt_cycle3(ba, dc, n) \
+	decrypt_round3(ba, dc, (n*2)+1); \
+	decrypt_round3(ba, dc, (n*2));
+
+#define inpack3(in, n, xy, m) \
+	movq 4*(n)(in),			xy ## 0; \
+	xorq w+4*m(CTX),		xy ## 0; \
+	\
+	movq 4*(4+(n))(in),		xy ## 1; \
+	xorq w+4*m(CTX),		xy ## 1; \
+	\
+	movq 4*(8+(n))(in),		xy ## 2; \
+	xorq w+4*m(CTX),		xy ## 2;
+
+#define outunpack3(op, out, n, xy, m) \
+	xorq w+4*m(CTX),		xy ## 0; \
+	op ## q xy ## 0,		4*(n)(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 1; \
+	op ## q xy ## 1,		4*(4+(n))(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 2; \
+	op ## q xy ## 2,		4*(8+(n))(out);
+
+#define inpack_enc3() \
+	inpack3(RIO, 0, RAB, 0); \
+	inpack3(RIO, 2, RCD, 2);
+
+#define outunpack_enc3(op) \
+	outunpack3(op, RIO, 2, RAB, 6); \
+	outunpack3(op, RIO, 0, RCD, 4);
+
+#define inpack_dec3() \
+	inpack3(RIO, 0, RAB, 4); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	inpack3(RIO, 2, RCD, 6); \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2;
+
+#define outunpack_dec3() \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2; \
+	outunpack3(mov, RIO, 0, RCD, 0); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	outunpack3(mov, RIO, 2, RAB, 2);
+
+.align 8
+.global __twofish_enc_blk_3way
+.type   __twofish_enc_blk_3way,@function;
+
+__twofish_enc_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rcx; /* bool xor */
+	pushq %rsi; /* dst */
+
+	inpack_enc3();
+
+	encrypt_cycle3(RAB, RCD, 0);
+	encrypt_cycle3(RAB, RCD, 1);
+	encrypt_cycle3(RAB, RCD, 2);
+	encrypt_cycle3(RAB, RCD, 3);
+	encrypt_cycle3(RAB, RCD, 4);
+	encrypt_cycle3(RAB, RCD, 5);
+	encrypt_cycle3(RAB, RCD, 6);
+	encrypt_cycle3(RAB, RCD, 7);
+
+	popq RIO; /* dst */
+	popq %rbp; /* bool xor */
+
+	testb %bpl, %bpl;
+	jnz __enc_xor3;
+
+	outunpack_enc3(mov);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+__enc_xor3:
+	outunpack_enc3(xor);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+.global twofish_dec_blk_3way
+.type   twofish_dec_blk_3way,@function;
+
+twofish_dec_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rsi; /* dst */
+
+	inpack_dec3();
+
+	decrypt_cycle3(RAB, RCD, 7);
+	decrypt_cycle3(RAB, RCD, 6);
+	decrypt_cycle3(RAB, RCD, 5);
+	decrypt_cycle3(RAB, RCD, 4);
+	decrypt_cycle3(RAB, RCD, 3);
+	decrypt_cycle3(RAB, RCD, 2);
+	decrypt_cycle3(RAB, RCD, 1);
+	decrypt_cycle3(RAB, RCD, 0);
+
+	popq RIO; /* dst */
+
+	outunpack_dec3();
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/crypto/twofish-x86_64-asm_64.S linux-libre-3.2-gnu1/arch/x86/crypto/twofish-x86_64-asm_64.S
--- linux-libre-3.1-gnu1/arch/x86/crypto/twofish-x86_64-asm_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/crypto/twofish-x86_64-asm_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -221,10 +221,9 @@
 twofish_enc_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
@@ -274,10 +273,9 @@ twofish_enc_blk:
 twofish_dec_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
diff -druNp linux-libre-3.1-gnu1/arch/x86/ia32/ia32entry.S linux-libre-3.2-gnu1/arch/x86/ia32/ia32entry.S
--- linux-libre-3.1-gnu1/arch/x86/ia32/ia32entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/ia32/ia32entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -850,4 +850,6 @@ ia32_sys_call_table:
 	.quad sys_syncfs
 	.quad compat_sys_sendmmsg	/* 345 */
 	.quad sys_setns
+	.quad compat_sys_process_vm_readv
+	.quad compat_sys_process_vm_writev
 ia32_syscall_end:
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/amd_nb.h linux-libre-3.2-gnu1/arch/x86/include/asm/amd_nb.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/amd_nb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/amd_nb.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,9 +19,15 @@ extern int amd_numa_init(void);
 extern int amd_get_subcaches(int);
 extern int amd_set_subcaches(int, int);
 
+struct amd_l3_cache {
+	unsigned indices;
+	u8	 subcaches[4];
+};
+
 struct amd_northbridge {
 	struct pci_dev *misc;
 	struct pci_dev *link;
+	struct amd_l3_cache l3_cache;
 };
 
 struct amd_northbridge_info {
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/apicdef.h linux-libre-3.2-gnu1/arch/x86/include/asm/apicdef.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/apicdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/apicdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,9 @@
 #define		APIC_TIMER_BASE_CLKIN		0x0
 #define		APIC_TIMER_BASE_TMBASE		0x1
 #define		APIC_TIMER_BASE_DIV		0x2
+#define		APIC_LVT_TIMER_ONESHOT		(0 << 17)
 #define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
+#define		APIC_LVT_TIMER_TSCDEADLINE	(2 << 17)
 #define		APIC_LVT_MASKED			(1 << 16)
 #define		APIC_LVT_LEVEL_TRIGGER		(1 << 15)
 #define		APIC_LVT_REMOTE_IRR		(1 << 14)
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/apic.h linux-libre-3.2-gnu1/arch/x86/include/asm/apic.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/apic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/apic.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@ extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
+extern unsigned int lapic_timer_frequency;
 
 #ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
@@ -495,7 +496,7 @@ static inline void default_wait_for_init
 	return;
 }
 
-extern struct apic *generic_bigsmp_probe(void);
+extern void generic_bigsmp_probe(void);
 
 
 #ifdef CONFIG_X86_LOCAL_APIC
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/archrandom.h linux-libre-3.2-gnu1/arch/x86/include/asm/archrandom.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/archrandom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/archrandom.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ *          H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef ASM_X86_ARCHRANDOM_H
+#define ASM_X86_ARCHRANDOM_H
+
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+#define RDRAND_RETRY_LOOPS	10
+
+#define RDRAND_INT	".byte 0x0f,0xc7,0xf0"
+#ifdef CONFIG_X86_64
+# define RDRAND_LONG	".byte 0x48,0x0f,0xc7,0xf0"
+#else
+# define RDRAND_LONG	RDRAND_INT
+#endif
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#define GET_RANDOM(name, type, rdrand, nop)			\
+static inline int name(type *v)					\
+{								\
+	int ok;							\
+	alternative_io("movl $0, %0\n\t"			\
+		       nop,					\
+		       "\n1: " rdrand "\n\t"			\
+		       "jc 2f\n\t"				\
+		       "decl %0\n\t"                            \
+		       "jnz 1b\n\t"                             \
+		       "2:",                                    \
+		       X86_FEATURE_RDRAND,                      \
+		       ASM_OUTPUT2("=r" (ok), "=a" (*v)),       \
+		       "0" (RDRAND_RETRY_LOOPS));		\
+	return ok;						\
+}
+
+#ifdef CONFIG_X86_64
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
+
+#else
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
+
+#endif /* CONFIG_X86_64 */
+
+#endif  /* CONFIG_ARCH_RANDOM */
+
+extern void x86_init_rdrand(struct cpuinfo_x86 *c);
+
+#endif /* ASM_X86_ARCHRANDOM_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/atomic64_64.h linux-libre-3.2-gnu1/arch/x86/include/asm/atomic64_64.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/atomic64_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/atomic64_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -170,11 +170,7 @@ static inline int atomic64_add_negative(
  */
 static inline long atomic64_add_return(long i, atomic64_t *v)
 {
-	long __i = i;
-	asm volatile(LOCK_PREFIX "xaddq %0, %1;"
-		     : "+r" (i), "+m" (v->counter)
-		     : : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 }
 
 static inline long atomic64_sub_return(long i, atomic64_t *v)
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/atomic.h linux-libre-3.2-gnu1/arch/x86/include/asm/atomic.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -172,18 +172,14 @@ static inline int atomic_add_negative(in
  */
 static inline int atomic_add_return(int i, atomic_t *v)
 {
-	int __i;
 #ifdef CONFIG_M386
+	int __i;
 	unsigned long flags;
 	if (unlikely(boot_cpu_data.x86 <= 3))
 		goto no_xadd;
 #endif
 	/* Modern 486+ processor */
-	__i = i;
-	asm volatile(LOCK_PREFIX "xaddl %0, %1"
-		     : "+r" (i), "+m" (v->counter)
-		     : : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 
 #ifdef CONFIG_M386
 no_xadd: /* Legacy 386 processor */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg_32.h linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg_32.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,11 @@
 #ifndef _ASM_X86_CMPXCHG_32_H
 #define _ASM_X86_CMPXCHG_32_H
 
-#include <linux/bitops.h> /* for LOCK_PREFIX */
-
 /*
  * Note: if you use set64_bit(), __cmpxchg64(), or their variants, you
  *       you need to test for the feature in boot_cpu_data.
  */
 
-extern void __xchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size)						\
-({									\
-	__typeof(*(ptr)) __x = (x);					\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile("xchgb %0,%1"				\
-			     : "=q" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile("xchgw %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__xchg_wrong_size();					\
-	}								\
-	__x;								\
-})
-
-#define xchg(ptr, v)							\
-	__xchg((v), (ptr), sizeof(*ptr))
-
 /*
  * CMPXCHG8B only writes to the target if we had the previous
  * value in registers, otherwise it acts as a read and gives us the
@@ -84,72 +34,8 @@ static inline void set_64bit(volatile u6
 		     : "memory");
 }
 
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-#define __raw_cmpxchg(ptr, old, new, size, lock)			\
-({									\
-	__typeof__(*(ptr)) __ret;					\
-	__typeof__(*(ptr)) __old = (old);				\
-	__typeof__(*(ptr)) __new = (new);				\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile(lock "cmpxchgb %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "q" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile(lock "cmpxchgw %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile(lock "cmpxchgl %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__cmpxchg_wrong_size();					\
-	}								\
-	__ret;								\
-})
-
-#define __cmpxchg(ptr, old, new, size)					\
-	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "")
-
 #ifdef CONFIG_X86_CMPXCHG
 #define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, old, new)						\
-	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new)					\
-	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new)					\
-	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
 #endif
 
 #ifdef CONFIG_X86_CMPXCHG64
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg_64.h linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg_64.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,144 +1,13 @@
 #ifndef _ASM_X86_CMPXCHG_64_H
 #define _ASM_X86_CMPXCHG_64_H
 
-#include <asm/alternative.h> /* Provides LOCK_PREFIX */
-
 static inline void set_64bit(volatile u64 *ptr, u64 val)
 {
 	*ptr = val;
 }
 
-extern void __xchg_wrong_size(void);
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size)						\
-({									\
-	__typeof(*(ptr)) __x = (x);					\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile("xchgb %0,%1"				\
-			     : "=q" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile("xchgw %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 8:								\
-	{								\
-		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
-		asm volatile("xchgq %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__xchg_wrong_size();					\
-	}								\
-	__x;								\
-})
-
-#define xchg(ptr, v)							\
-	__xchg((v), (ptr), sizeof(*ptr))
-
 #define __HAVE_ARCH_CMPXCHG 1
 
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-#define __raw_cmpxchg(ptr, old, new, size, lock)			\
-({									\
-	__typeof__(*(ptr)) __ret;					\
-	__typeof__(*(ptr)) __old = (old);				\
-	__typeof__(*(ptr)) __new = (new);				\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile(lock "cmpxchgb %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "q" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile(lock "cmpxchgw %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile(lock "cmpxchgl %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 8:								\
-	{								\
-		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
-		asm volatile(lock "cmpxchgq %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__cmpxchg_wrong_size();					\
-	}								\
-	__ret;								\
-})
-
-#define __cmpxchg(ptr, old, new, size)					\
-	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "")
-
-#define cmpxchg(ptr, old, new)						\
-	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new)					\
-	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new)					\
-	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
-
 #define cmpxchg64(ptr, o, n)						\
 ({									\
 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg.h linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/cmpxchg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/cmpxchg.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,210 @@
+#ifndef ASM_X86_CMPXCHG_H
+#define ASM_X86_CMPXCHG_H
+
+#include <linux/compiler.h>
+#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+
+/*
+ * Non-existant functions to indicate usage errors at link time
+ * (or compile-time if the compiler implements __compiletime_error().
+ */
+extern void __xchg_wrong_size(void)
+	__compiletime_error("Bad argument size for xchg");
+extern void __cmpxchg_wrong_size(void)
+	__compiletime_error("Bad argument size for cmpxchg");
+extern void __xadd_wrong_size(void)
+	__compiletime_error("Bad argument size for xadd");
+
+/*
+ * Constants for operation sizes. On 32-bit, the 64-bit size it set to
+ * -1 because sizeof will never return -1, thereby making those switch
+ * case statements guaranteeed dead code which the compiler will
+ * eliminate, and allowing the "missing symbol in the default case" to
+ * indicate a usage error.
+ */
+#define __X86_CASE_B	1
+#define __X86_CASE_W	2
+#define __X86_CASE_L	4
+#ifdef CONFIG_64BIT
+#define __X86_CASE_Q	8
+#else
+#define	__X86_CASE_Q	-1		/* sizeof will never return -1 */
+#endif
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
+ * Since this is generally used to protect other memory information, we
+ * use "asm volatile" and "memory" clobbers to prevent gcc from moving
+ * information around.
+ */
+#define __xchg(x, ptr, size)						\
+({									\
+	__typeof(*(ptr)) __x = (x);					\
+	switch (size) {							\
+	case __X86_CASE_B:						\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile("xchgb %0,%1"				\
+			     : "=q" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_W:						\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile("xchgw %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_L:						\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
+		asm volatile("xchgl %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_Q:						\
+	{								\
+		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
+		asm volatile("xchgq %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	default:							\
+		__xchg_wrong_size();					\
+	}								\
+	__x;								\
+})
+
+#define xchg(ptr, v)							\
+	__xchg((v), (ptr), sizeof(*ptr))
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#define __raw_cmpxchg(ptr, old, new, size, lock)			\
+({									\
+	__typeof__(*(ptr)) __ret;					\
+	__typeof__(*(ptr)) __old = (old);				\
+	__typeof__(*(ptr)) __new = (new);				\
+	switch (size) {							\
+	case __X86_CASE_B:						\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile(lock "cmpxchgb %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "q" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_W:						\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile(lock "cmpxchgw %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_L:						\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
+		asm volatile(lock "cmpxchgl %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_Q:						\
+	{								\
+		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
+		asm volatile(lock "cmpxchgq %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	default:							\
+		__cmpxchg_wrong_size();					\
+	}								\
+	__ret;								\
+})
+
+#define __cmpxchg(ptr, old, new, size)					\
+	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+
+#define __sync_cmpxchg(ptr, old, new, size)				\
+	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
+
+#define __cmpxchg_local(ptr, old, new, size)				\
+	__raw_cmpxchg((ptr), (old), (new), (size), "")
+
 #ifdef CONFIG_X86_32
 # include "cmpxchg_32.h"
 #else
 # include "cmpxchg_64.h"
 #endif
+
+#ifdef __HAVE_ARCH_CMPXCHG
+#define cmpxchg(ptr, old, new)						\
+	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define sync_cmpxchg(ptr, old, new)					\
+	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define cmpxchg_local(ptr, old, new)					\
+	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+#endif
+
+#define __xadd(ptr, inc, lock)						\
+	({								\
+	        __typeof__ (*(ptr)) __ret = (inc);			\
+		switch (sizeof(*(ptr))) {				\
+		case __X86_CASE_B:					\
+			asm volatile (lock "xaddb %b0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_W:					\
+			asm volatile (lock "xaddw %w0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_L:					\
+			asm volatile (lock "xaddl %0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_Q:					\
+			asm volatile (lock "xaddq %q0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		default:						\
+			__xadd_wrong_size();				\
+		}							\
+		__ret;							\
+	})
+
+/*
+ * xadd() adds "inc" to "*ptr" and atomically returns the previous
+ * value of "*ptr".
+ *
+ * xadd() is locked when multiple CPUs are online
+ * xadd_sync() is always locked
+ * xadd_local() is never locked
+ */
+#define xadd(ptr, inc)		__xadd((ptr), (inc), LOCK_PREFIX)
+#define xadd_sync(ptr, inc)	__xadd((ptr), (inc), "lock; ")
+#define xadd_local(ptr, inc)	__xadd((ptr), (inc), "")
+
+#endif	/* ASM_X86_CMPXCHG_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/compat.h linux-libre-3.2-gnu1/arch/x86/include/asm/compat.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -108,7 +108,8 @@ struct compat_statfs {
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/cpufeature.h linux-libre-3.2-gnu1/arch/x86/include/asm/cpufeature.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/cpufeature.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/cpufeature.h	2012-01-04 18:55:44.000000000 -0500
@@ -114,12 +114,14 @@
 #define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
 #define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 #define X86_FEATURE_PDCM	(4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID	(4*32+17) /* Process Context Identifiers */
 #define X86_FEATURE_DCA		(4*32+18) /* Direct Cache Access */
 #define X86_FEATURE_XMM4_1	(4*32+19) /* "sse4_1" SSE-4.1 */
 #define X86_FEATURE_XMM4_2	(4*32+20) /* "sse4_2" SSE-4.2 */
 #define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
 #define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
 #define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER	(4*32+24) /* Tsc deadline timer */
 #define X86_FEATURE_AES		(4*32+25) /* AES instructions */
 #define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
@@ -257,7 +259,9 @@ extern const char * const x86_power_flag
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
 #define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
+#define cpu_has_ssse3		boot_cpu_has(X86_FEATURE_SSSE3)
 #define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES)
+#define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
@@ -285,6 +289,7 @@ extern const char * const x86_power_flag
 #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
+#define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/device.h linux-libre-3.2-gnu1/arch/x86/include/asm/device.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@ struct dev_archdata {
 #ifdef CONFIG_X86_64
 struct dma_map_ops *dma_ops;
 #endif
-#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
+#if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU)
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/dma-mapping.h linux-libre-3.2-gnu1/arch/x86/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #define _ASM_X86_DMA_MAPPING_H
 
 /*
- * IOMMU interface. See Documentation/PCI/PCI-DMA-mapping.txt and
+ * IOMMU interface. See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  */
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/dwarf2.h linux-libre-3.2-gnu1/arch/x86/include/asm/dwarf2.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/dwarf2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/dwarf2.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #define CFI_REMEMBER_STATE	.cfi_remember_state
 #define CFI_RESTORE_STATE	.cfi_restore_state
 #define CFI_UNDEFINED		.cfi_undefined
+#define CFI_ESCAPE		.cfi_escape
 
 #ifdef CONFIG_AS_CFI_SIGNAL_FRAME
 #define CFI_SIGNAL_FRAME	.cfi_signal_frame
@@ -68,6 +69,7 @@
 #define CFI_REMEMBER_STATE	cfi_ignore
 #define CFI_RESTORE_STATE	cfi_ignore
 #define CFI_UNDEFINED		cfi_ignore
+#define CFI_ESCAPE		cfi_ignore
 #define CFI_SIGNAL_FRAME	cfi_ignore
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/elf.h linux-libre-3.2-gnu1/arch/x86/include/asm/elf.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 /*
  * ELF register definitions..
  */
+#include <linux/thread_info.h>
 
 #include <asm/ptrace.h>
 #include <asm/user.h>
@@ -320,4 +321,34 @@ extern int syscall32_setup_pages(struct
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+/*
+ * True on X86_32 or when emulating IA32 on X86_64
+ */
+static inline int mmap_is_ia32(void)
+{
+#ifdef CONFIG_X86_32
+	return 1;
+#endif
+#ifdef CONFIG_IA32_EMULATION
+	if (test_thread_flag(TIF_IA32))
+		return 1;
+#endif
+	return 0;
+}
+
+/* The first two values are special, do not change. See align_addr() */
+enum align_flags {
+	ALIGN_VA_32	= BIT(0),
+	ALIGN_VA_64	= BIT(1),
+	ALIGN_VDSO	= BIT(2),
+	ALIGN_TOPDOWN	= BIT(3),
+};
+
+struct va_alignment {
+	int flags;
+	unsigned long mask;
+} ____cacheline_aligned;
+
+extern struct va_alignment va_align;
+extern unsigned long align_addr(unsigned long, struct file *, enum align_flags);
 #endif /* _ASM_X86_ELF_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/hw_irq.h linux-libre-3.2-gnu1/arch/x86/include/asm/hw_irq.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/hw_irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/hw_irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -119,7 +119,7 @@ struct irq_cfg {
 	cpumask_var_t		old_domain;
 	u8			vector;
 	u8			move_in_progress : 1;
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 	struct irq_2_iommu	irq_2_iommu;
 #endif
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/hyperv.h linux-libre-3.2-gnu1/arch/x86/include/asm/hyperv.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/hyperv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/hyperv.h	2012-01-04 18:55:44.000000000 -0500
@@ -189,5 +189,6 @@
 #define HV_STATUS_INVALID_HYPERCALL_CODE	2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT	3
 #define HV_STATUS_INVALID_ALIGNMENT		4
+#define HV_STATUS_INSUFFICIENT_BUFFERS		19
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/intel_scu_ipc.h linux-libre-3.2-gnu1/arch/x86/include/asm/intel_scu_ipc.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/intel_scu_ipc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/intel_scu_ipc.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,11 +1,17 @@
 #ifndef _ASM_X86_INTEL_SCU_IPC_H_
 #define  _ASM_X86_INTEL_SCU_IPC_H_
 
-#define IPCMSG_VRTC	0xFA	 /* Set vRTC device */
+#include <linux/notifier.h>
 
-/* Command id associated with message IPCMSG_VRTC */
-#define IPC_CMD_VRTC_SETTIME      1 /* Set time */
-#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */
+#define IPCMSG_WARM_RESET	0xF0
+#define IPCMSG_COLD_RESET	0xF1
+#define IPCMSG_SOFT_RESET	0xF2
+#define IPCMSG_COLD_BOOT	0xF3
+
+#define IPCMSG_VRTC		0xFA	 /* Set vRTC device */
+	/* Command id associated with message IPCMSG_VRTC */
+	#define IPC_CMD_VRTC_SETTIME      1 /* Set time */
+	#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */
 
 /* Read single register */
 int intel_scu_ipc_ioread8(u16 addr, u8 *data);
@@ -44,4 +50,24 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u3
 /* Update FW version */
 int intel_scu_ipc_fw_update(u8 *buffer, u32 length);
 
+extern struct blocking_notifier_head intel_scu_notifier;
+
+static inline void intel_scu_notifier_add(struct notifier_block *nb)
+{
+	blocking_notifier_chain_register(&intel_scu_notifier, nb);
+}
+
+static inline void intel_scu_notifier_remove(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
+}
+
+static inline int intel_scu_notifier_post(unsigned long v, void *p)
+{
+	return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
+}
+
+#define		SCU_AVAILABLE		1
+#define		SCU_DOWN		2
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/irq_remapping.h linux-libre-3.2-gnu1/arch/x86/include/asm/irq_remapping.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/irq_remapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/irq_remapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 
 #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
 static inline void prepare_irte(struct irte *irte, int vector,
 			        unsigned int dest)
 {
@@ -36,6 +37,9 @@ static inline bool irq_remapped(struct i
 {
 	return false;
 }
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+}
 #endif
 
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/irq_vectors.h linux-libre-3.2-gnu1/arch/x86/include/asm/irq_vectors.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/irq_vectors.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/irq_vectors.h	2012-01-04 18:55:44.000000000 -0500
@@ -160,19 +160,11 @@ static inline int invalid_vm86_irq(int i
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
-# ifdef CONFIG_SPARSE_IRQ
-#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
-#  define NR_IRQS					\
+# define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
+# define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# else
-#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
-#  define NR_IRQS					\
-	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
-		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
-		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/kvm_emulate.h linux-libre-3.2-gnu1/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/kvm_emulate.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/kvm_emulate.h	2012-01-04 18:55:44.000000000 -0500
@@ -262,7 +262,7 @@ struct x86_emulate_ctxt {
 	struct operand dst;
 	bool has_seg_override;
 	u8 seg_override;
-	unsigned int d;
+	u64 d;
 	int (*execute)(struct x86_emulate_ctxt *ctxt);
 	int (*check_perm)(struct x86_emulate_ctxt *ctxt);
 	/* modrm */
@@ -275,6 +275,8 @@ struct x86_emulate_ctxt {
 	unsigned long _eip;
 	/* Fields above regs are cleared together. */
 	unsigned long regs[NR_VCPU_REGS];
+	struct operand memop;
+	struct operand *memopp;
 	struct fetch_cache fetch;
 	struct read_cache io_read;
 	struct read_cache mem_read;
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/kvm_host.h linux-libre-3.2-gnu1/arch/x86/include/asm/kvm_host.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,8 @@
 #include <asm/mtrr.h>
 #include <asm/msr-index.h>
 
-#define KVM_MAX_VCPUS 64
+#define KVM_MAX_VCPUS 254
+#define KVM_SOFT_MAX_VCPUS 64
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
@@ -264,6 +265,7 @@ struct kvm_mmu {
 	void (*new_cr3)(struct kvm_vcpu *vcpu);
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
 	unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
+	u64 (*get_pdptr)(struct kvm_vcpu *vcpu, int index);
 	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err,
 			  bool prefault);
 	void (*inject_page_fault)(struct kvm_vcpu *vcpu,
@@ -411,8 +413,9 @@ struct kvm_vcpu_arch {
 	u32  tsc_catchup_mult;
 	s8   tsc_catchup_shift;
 
-	bool nmi_pending;
-	bool nmi_injected;
+	atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
+	unsigned nmi_pending; /* NMI queued after currently running handler */
+	bool nmi_injected;    /* Trying to inject an NMI this entry */
 
 	struct mtrr_state_type mtrr_state;
 	u32 pat;
@@ -628,14 +631,13 @@ struct kvm_x86_ops {
 	void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
 	u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
+	u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu);
 
 	void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
 
 	int (*check_intercept)(struct kvm_vcpu *vcpu,
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage);
-
-	const struct trace_print_flags *exit_reasons_str;
 };
 
 struct kvm_arch_async_pf {
@@ -672,6 +674,8 @@ u8 kvm_get_guest_memory_type(struct kvm_
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/mach_traps.h linux-libre-3.2-gnu1/arch/x86/include/asm/mach_traps.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/mach_traps.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/mach_traps.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #define NMI_REASON_CLEAR_IOCHK	0x08
 #define NMI_REASON_CLEAR_MASK	0x0f
 
-static inline unsigned char get_nmi_reason(void)
+static inline unsigned char default_get_nmi_reason(void)
 {
 	return inb(NMI_REASON_PORT);
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/mce.h linux-libre-3.2-gnu1/arch/x86/include/asm/mce.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/mce.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/mce.h	2012-01-04 18:55:44.000000000 -0500
@@ -201,7 +201,10 @@ int mce_notify_irq(void);
 void mce_notify_process(void);
 
 DECLARE_PER_CPU(struct mce, injectm);
-extern struct file_operations mce_chrdev_ops;
+
+extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
+				    const char __user *ubuf,
+				    size_t usize, loff_t *off));
 
 /*
  * Exception handler
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/mrst.h linux-libre-3.2-gnu1/arch/x86/include/asm/mrst.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/mrst.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/mrst.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,20 @@ enum mrst_cpu_type {
 };
 
 extern enum mrst_cpu_type __mrst_cpu_chip;
+
+#ifdef CONFIG_X86_INTEL_MID
+
 static inline enum mrst_cpu_type mrst_identify_cpu(void)
 {
 	return __mrst_cpu_chip;
 }
 
+#else /* !CONFIG_X86_INTEL_MID */
+
+#define mrst_identify_cpu()    (0)
+
+#endif /* !CONFIG_X86_INTEL_MID */
+
 enum mrst_timer_options {
 	MRST_TIMER_DEFAULT,
 	MRST_TIMER_APBT_ONLY,
@@ -44,6 +53,13 @@ enum mrst_timer_options {
 
 extern enum mrst_timer_options mrst_timer_options;
 
+/*
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * the same as reported by MSR based on SDM.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/msr.h linux-libre-3.2-gnu1/arch/x86/include/asm/msr.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/msr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/msr.h	2012-01-04 18:55:44.000000000 -0500
@@ -169,7 +169,14 @@ static inline int wrmsr_safe(unsigned ms
 	return native_write_msr_safe(msr, low, high);
 }
 
-/* rdmsr with exception handling */
+/*
+ * rdmsr with exception handling.
+ *
+ * Please note that the exception handling works only after we've
+ * switched to the "smart" #GP handler in trap_init() which knows about
+ * exception tables - using this macro earlier than that causes machine
+ * hangs on boxes which do not implement the @msr in the first argument.
+ */
 #define rdmsr_safe(msr, p1, p2)					\
 ({								\
 	int __err;						\
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/msr-index.h linux-libre-3.2-gnu1/arch/x86/include/asm/msr-index.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/msr-index.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/msr-index.h	2012-01-04 18:55:44.000000000 -0500
@@ -229,6 +229,8 @@
 #define MSR_IA32_APICBASE_ENABLE	(1<<11)
 #define MSR_IA32_APICBASE_BASE		(0xfffff<<12)
 
+#define MSR_IA32_TSCDEADLINE		0x000006e0
+
 #define MSR_IA32_UCODE_WRITE		0x00000079
 #define MSR_IA32_UCODE_REV		0x0000008b
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/nmi.h linux-libre-3.2-gnu1/arch/x86/include/asm/nmi.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/nmi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/nmi.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,27 +22,26 @@ void arch_trigger_all_cpu_backtrace(void
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
 #endif
 
-/*
- * Define some priorities for the nmi notifier call chain.
- *
- * Create a local nmi bit that has a higher priority than
- * external nmis, because the local ones are more frequent.
- *
- * Also setup some default high/normal/low settings for
- * subsystems to registers with.  Using 4 bits to separate
- * the priorities.  This can go a lot higher if needed be.
- */
+#define NMI_FLAG_FIRST	1
 
-#define NMI_LOCAL_SHIFT		16	/* randomly picked */
-#define NMI_LOCAL_BIT		(1ULL << NMI_LOCAL_SHIFT)
-#define NMI_HIGH_PRIOR		(1ULL << 8)
-#define NMI_NORMAL_PRIOR	(1ULL << 4)
-#define NMI_LOW_PRIOR		(1ULL << 0)
-#define NMI_LOCAL_HIGH_PRIOR	(NMI_LOCAL_BIT | NMI_HIGH_PRIOR)
-#define NMI_LOCAL_NORMAL_PRIOR	(NMI_LOCAL_BIT | NMI_NORMAL_PRIOR)
-#define NMI_LOCAL_LOW_PRIOR	(NMI_LOCAL_BIT | NMI_LOW_PRIOR)
+enum {
+	NMI_LOCAL=0,
+	NMI_UNKNOWN,
+	NMI_MAX
+};
+
+#define NMI_DONE	0
+#define NMI_HANDLED	1
+
+typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
+
+int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long,
+			 const char *);
+
+void unregister_nmi_handler(unsigned int, const char *);
 
 void stop_nmi(void);
 void restart_nmi(void);
+void local_touch_nmi(void);
 
 #endif /* _ASM_X86_NMI_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/pci_x86.h linux-libre-3.2-gnu1/arch/x86/include/asm/pci_x86.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/pci_x86.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/pci_x86.h	2012-01-04 18:55:44.000000000 -0500
@@ -99,10 +99,10 @@ struct pci_raw_ops {
 						int reg, int len, u32 val);
 };
 
-extern struct pci_raw_ops *raw_pci_ops;
-extern struct pci_raw_ops *raw_pci_ext_ops;
+extern const struct pci_raw_ops *raw_pci_ops;
+extern const struct pci_raw_ops *raw_pci_ext_ops;
 
-extern struct pci_raw_ops pci_direct_conf1;
+extern const struct pci_raw_ops pci_direct_conf1;
 extern bool port_cf9_safe;
 
 /* arch_initcall level */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/perf_event.h linux-libre-3.2-gnu1/arch/x86/include/asm/perf_event.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/perf_event.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
 #define ARCH_PERFMON_EVENTSEL_INV			(1ULL << 23)
 #define ARCH_PERFMON_EVENTSEL_CMASK			0xFF000000ULL
 
+#define AMD_PERFMON_EVENTSEL_GUESTONLY			(1ULL << 40)
+#define AMD_PERFMON_EVENTSEL_HOSTONLY			(1ULL << 41)
+
 #define AMD64_EVENTSEL_EVENT	\
 	(ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32))
 #define INTEL_ARCH_EVENT_MASK	\
@@ -43,14 +46,17 @@
 #define AMD64_RAW_EVENT_MASK		\
 	(X86_RAW_EVENT_MASK          |  \
 	 AMD64_EVENTSEL_EVENT)
+#define AMD64_NUM_COUNTERS				4
+#define AMD64_NUM_COUNTERS_F15H				6
+#define AMD64_NUM_COUNTERS_MAX				AMD64_NUM_COUNTERS_F15H
 
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		      0x3c
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK		(0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX			 0
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX		0
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
 		(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
 
-#define ARCH_PERFMON_BRANCH_MISSES_RETIRED			 6
+#define ARCH_PERFMON_BRANCH_MISSES_RETIRED		6
 
 /*
  * Intel "Architectural Performance Monitoring" CPUID
@@ -110,6 +116,35 @@ union cpuid10_edx {
  */
 #define X86_PMC_IDX_FIXED_BTS				(X86_PMC_IDX_FIXED + 16)
 
+/*
+ * IBS cpuid feature detection
+ */
+
+#define IBS_CPUID_FEATURES		0x8000001b
+
+/*
+ * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
+ * bit 0 is used to indicate the existence of IBS.
+ */
+#define IBS_CAPS_AVAIL			(1U<<0)
+#define IBS_CAPS_FETCHSAM		(1U<<1)
+#define IBS_CAPS_OPSAM			(1U<<2)
+#define IBS_CAPS_RDWROPCNT		(1U<<3)
+#define IBS_CAPS_OPCNT			(1U<<4)
+#define IBS_CAPS_BRNTRGT		(1U<<5)
+#define IBS_CAPS_OPCNTEXT		(1U<<6)
+
+#define IBS_CAPS_DEFAULT		(IBS_CAPS_AVAIL		\
+					 | IBS_CAPS_FETCHSAM	\
+					 | IBS_CAPS_OPSAM)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL				0x1cc
+#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK		0x0F
+
 /* IbsFetchCtl bits/masks */
 #define IBS_FETCH_RAND_EN	(1ULL<<57)
 #define IBS_FETCH_VAL		(1ULL<<49)
@@ -124,6 +159,8 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT		0x0000FFFFULL
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
+extern u32 get_ibs_caps(void);
+
 #ifdef CONFIG_PERF_EVENTS
 extern void perf_events_lapic_init(void);
 
@@ -159,7 +196,19 @@ extern unsigned long perf_misc_flags(str
 	);							\
 }
 
+struct perf_guest_switch_msr {
+	unsigned msr;
+	u64 host, guest;
+};
+
+extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
 #else
+static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+	*nr = 0;
+	return NULL;
+}
+
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/processor.h linux-libre-3.2-gnu1/arch/x86/include/asm/processor.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -111,6 +111,7 @@ struct cpuinfo_x86 {
 	/* Index into per_cpu list: */
 	u16			cpu_index;
 #endif
+	u32			microcode;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define X86_VENDOR_INTEL	0
@@ -179,7 +180,8 @@ static inline void native_cpuid(unsigned
 	      "=b" (*ebx),
 	      "=c" (*ecx),
 	      "=d" (*edx)
-	    : "0" (*eax), "2" (*ecx));
+	    : "0" (*eax), "2" (*ecx)
+	    : "memory");
 }
 
 static inline void load_cr3(pgd_t *pgdir)
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/reboot.h linux-libre-3.2-gnu1/arch/x86/include/asm/reboot.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/reboot.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/reboot.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@ void machine_real_restart(unsigned int t
 #define MRR_BIOS	0
 #define MRR_APM		1
 
-typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
 void nmi_shootdown_cpus(nmi_shootdown_cb callback);
 
 #endif /* _ASM_X86_REBOOT_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/rwsem.h linux-libre-3.2-gnu1/arch/x86/include/asm/rwsem.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/rwsem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/rwsem.h	2012-01-04 18:55:44.000000000 -0500
@@ -204,13 +204,7 @@ static inline void rwsem_atomic_add(long
  */
 static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-	long tmp = delta;
-
-	asm volatile(LOCK_PREFIX "xadd %0,%1"
-		     : "+r" (tmp), "+m" (sem->count)
-		     : : "memory");
-
-	return tmp + delta;
+	return delta + xadd(&sem->count, delta);
 }
 
 #endif /* __KERNEL__ */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/spinlock.h linux-libre-3.2-gnu1/arch/x86/include/asm/spinlock.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/spinlock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,109 +49,49 @@
  * issues and should be optimal for the uncontended case. Note the tail must be
  * in the high part, because a wide xadd increment of the low part would carry
  * up and contaminate the high part.
- *
- * With fewer than 2^8 possible CPUs, we can use x86's partial registers to
- * save some instructions and make the code more elegant. There really isn't
- * much between them in performance though, especially as locks are out of line.
  */
-#if (NR_CPUS < 256)
-#define TICKET_SHIFT 8
-
 static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
 {
-	short inc = 0x0100;
+	register struct __raw_tickets inc = { .tail = 1 };
 
-	asm volatile (
-		LOCK_PREFIX "xaddw %w0, %1\n"
-		"1:\t"
-		"cmpb %h0, %b0\n\t"
-		"je 2f\n\t"
-		"rep ; nop\n\t"
-		"movb %1, %b0\n\t"
-		/* don't need lfence here, because loads are in-order */
-		"jmp 1b\n"
-		"2:"
-		: "+Q" (inc), "+m" (lock->slock)
-		:
-		: "memory", "cc");
+	inc = xadd(&lock->tickets, inc);
+
+	for (;;) {
+		if (inc.head == inc.tail)
+			break;
+		cpu_relax();
+		inc.head = ACCESS_ONCE(lock->tickets.head);
+	}
+	barrier();		/* make sure nothing creeps before the lock is taken */
 }
 
 static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
 {
-	int tmp, new;
+	arch_spinlock_t old, new;
 
-	asm volatile("movzwl %2, %0\n\t"
-		     "cmpb %h0,%b0\n\t"
-		     "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
-		     "jne 1f\n\t"
-		     LOCK_PREFIX "cmpxchgw %w1,%2\n\t"
-		     "1:"
-		     "sete %b1\n\t"
-		     "movzbl %b1,%0\n\t"
-		     : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
-		     :
-		     : "memory", "cc");
+	old.tickets = ACCESS_ONCE(lock->tickets);
+	if (old.tickets.head != old.tickets.tail)
+		return 0;
 
-	return tmp;
+	new.head_tail = old.head_tail + (1 << TICKET_SHIFT);
+
+	/* cmpxchg is a full barrier, so nothing can move before it */
+	return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
 }
 
+#if (NR_CPUS < 256)
 static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
-		     : "+m" (lock->slock)
+		     : "+m" (lock->head_tail)
 		     :
 		     : "memory", "cc");
 }
 #else
-#define TICKET_SHIFT 16
-
-static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
-{
-	int inc = 0x00010000;
-	int tmp;
-
-	asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
-		     "movzwl %w0, %2\n\t"
-		     "shrl $16, %0\n\t"
-		     "1:\t"
-		     "cmpl %0, %2\n\t"
-		     "je 2f\n\t"
-		     "rep ; nop\n\t"
-		     "movzwl %1, %2\n\t"
-		     /* don't need lfence here, because loads are in-order */
-		     "jmp 1b\n"
-		     "2:"
-		     : "+r" (inc), "+m" (lock->slock), "=&r" (tmp)
-		     :
-		     : "memory", "cc");
-}
-
-static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
-{
-	int tmp;
-	int new;
-
-	asm volatile("movl %2,%0\n\t"
-		     "movl %0,%1\n\t"
-		     "roll $16, %0\n\t"
-		     "cmpl %0,%1\n\t"
-		     "leal 0x00010000(%" REG_PTR_MODE "0), %1\n\t"
-		     "jne 1f\n\t"
-		     LOCK_PREFIX "cmpxchgl %1,%2\n\t"
-		     "1:"
-		     "sete %b1\n\t"
-		     "movzbl %b1,%0\n\t"
-		     : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
-		     :
-		     : "memory", "cc");
-
-	return tmp;
-}
-
 static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
-		     : "+m" (lock->slock)
+		     : "+m" (lock->head_tail)
 		     :
 		     : "memory", "cc");
 }
@@ -159,16 +99,16 @@ static __always_inline void __ticket_spi
 
 static inline int __ticket_spin_is_locked(arch_spinlock_t *lock)
 {
-	int tmp = ACCESS_ONCE(lock->slock);
+	struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
 
-	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+	return !!(tmp.tail ^ tmp.head);
 }
 
 static inline int __ticket_spin_is_contended(arch_spinlock_t *lock)
 {
-	int tmp = ACCESS_ONCE(lock->slock);
+	struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
 
-	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+	return ((tmp.tail - tmp.head) & TICKET_MASK) > 1;
 }
 
 #ifndef CONFIG_PARAVIRT_SPINLOCKS
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/spinlock_types.h linux-libre-3.2-gnu1/arch/x86/include/asm/spinlock_types.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/spinlock_types.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/spinlock_types.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,11 +5,29 @@
 # error "please don't include this file directly"
 #endif
 
+#include <linux/types.h>
+
+#if (CONFIG_NR_CPUS < 256)
+typedef u8  __ticket_t;
+typedef u16 __ticketpair_t;
+#else
+typedef u16 __ticket_t;
+typedef u32 __ticketpair_t;
+#endif
+
+#define TICKET_SHIFT	(sizeof(__ticket_t) * 8)
+#define TICKET_MASK	((__ticket_t)((1 << TICKET_SHIFT) - 1))
+
 typedef struct arch_spinlock {
-	unsigned int slock;
+	union {
+		__ticketpair_t head_tail;
+		struct __raw_tickets {
+			__ticket_t head, tail;
+		} tickets;
+	};
 } arch_spinlock_t;
 
-#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ { 0 } }
 
 #include <asm/rwlock.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/system.h linux-libre-3.2-gnu1/arch/x86/include/asm/system.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -401,6 +401,7 @@ extern unsigned long arch_align_stack(un
 extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 
 void default_idle(void);
+bool set_pm_idle_to_default(void);
 
 void stop_this_cpu(void *dummy);
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/timer.h linux-libre-3.2-gnu1/arch/x86/include/asm/timer.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/timer.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,22 @@ extern int no_timer_check;
  *  (mathieu.desnoyers@polymtl.ca)
  *
  *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
+ *
+ * In:
+ *
+ * ns = cycles * cyc2ns_scale / SC
+ *
+ * Although we may still have enough bits to store the value of ns,
+ * in some cases, we may not have enough bits to store cycles * cyc2ns_scale,
+ * leading to an incorrect result.
+ *
+ * To avoid this, we can decompose 'cycles' into quotient and remainder
+ * of division by SC.  Then,
+ *
+ * ns = (quot * SC + rem) * cyc2ns_scale / SC
+ *    = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC
+ *
+ *			- sqazi@google.com
  */
 
 DECLARE_PER_CPU(unsigned long, cyc2ns);
@@ -41,9 +57,14 @@ DECLARE_PER_CPU(unsigned long long, cyc2
 
 static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
 {
+	unsigned long long quot;
+	unsigned long long rem;
 	int cpu = smp_processor_id();
 	unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
-	ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR;
+	quot = (cyc >> CYC2NS_SCALE_FACTOR);
+	rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
+	ns += quot * per_cpu(cyc2ns, cpu) +
+		((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
 	return ns;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/unistd_32.h linux-libre-3.2-gnu1/arch/x86/include/asm/unistd_32.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/unistd_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/unistd_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -352,10 +352,12 @@
 #define __NR_syncfs             344
 #define __NR_sendmmsg		345
 #define __NR_setns		346
+#define __NR_process_vm_readv	347
+#define __NR_process_vm_writev	348
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 347
+#define NR_syscalls 349
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/unistd_64.h linux-libre-3.2-gnu1/arch/x86/include/asm/unistd_64.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/unistd_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/unistd_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -624,7 +624,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)
 __SYSCALL(__NR_move_pages, sys_move_pages)
 #define __NR_utimensat				280
 __SYSCALL(__NR_utimensat, sys_utimensat)
-#define __IGNORE_getcpu		/* implemented as a vsyscall */
 #define __NR_epoll_pwait			281
 __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
 #define __NR_signalfd				282
@@ -683,6 +682,10 @@ __SYSCALL(__NR_sendmmsg, sys_sendmmsg)
 __SYSCALL(__NR_setns, sys_setns)
 #define __NR_getcpu				309
 __SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_process_vm_readv			310
+__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv)
+#define __NR_process_vm_writev			311
+__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_bau.h linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_bau.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_bau.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@
 #define UV_BAU_TUNABLES_DIR		"sgi_uv"
 #define UV_BAU_TUNABLES_FILE		"bau_tunables"
 #define WHITESPACE			" \t\n"
+#define uv_mmask			((1UL << uv_hub_info->m_val) - 1)
 #define uv_physnodeaddr(x)		((__pa((unsigned long)(x)) & uv_mmask))
 #define cpubit_isset(cpu, bau_local_cpumask) \
 	test_bit((cpu), (bau_local_cpumask).bits)
@@ -656,11 +657,7 @@ static inline int atomic_read_short(cons
  */
 static inline int atom_asr(short i, struct atomic_short *v)
 {
-	short __i = i;
-	asm volatile(LOCK_PREFIX "xaddw %0, %1"
-			: "+r" (i), "+m" (v->counter)
-			: : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_hub.h linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_hub.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_hub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_hub.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,13 @@
  *	PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
  *		  of the nasid for socket usage.
  *
+ *	GPA	- (global physical address) a socket physical address converted
+ *		  so that it can be used by the GRU as a global address. Socket
+ *		  physical addresses 1) need additional NASID (node) bits added
+ *		  to the high end of the address, and 2) unaliased if the
+ *		  partition does not have a physical address 0. In addition, on
+ *		  UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
+ *
  *
  *  NumaLink Global Physical Address Format:
  *  +--------------------------------+---------------------+
@@ -141,6 +148,8 @@ struct uv_hub_info_s {
 	unsigned int		gnode_extra;
 	unsigned char		hub_revision;
 	unsigned char		apic_pnode_shift;
+	unsigned char		m_shift;
+	unsigned char		n_lshift;
 	unsigned long		gnode_upper;
 	unsigned long		lowmem_remap_top;
 	unsigned long		lowmem_remap_base;
@@ -177,6 +186,16 @@ static inline int is_uv2_hub(void)
 	return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
 }
 
+static inline int is_uv2_1_hub(void)
+{
+	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
+}
+
+static inline int is_uv2_2_hub(void)
+{
+	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
+}
+
 union uvh_apicid {
     unsigned long       v;
     struct uvh_apicid_s {
@@ -276,7 +295,10 @@ static inline unsigned long uv_soc_phys_
 {
 	if (paddr < uv_hub_info->lowmem_remap_top)
 		paddr |= uv_hub_info->lowmem_remap_base;
-	return paddr | uv_hub_info->gnode_upper;
+	paddr |= uv_hub_info->gnode_upper;
+	paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+		((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
+	return paddr;
 }
 
 
@@ -300,16 +322,19 @@ static inline unsigned long uv_gpa_to_so
 	unsigned long remap_base = uv_hub_info->lowmem_remap_base;
 	unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
 
+	gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+		((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
+	gpa = gpa & uv_hub_info->gpa_mask;
 	if (paddr >= remap_base && paddr < remap_base + remap_top)
 		paddr -= remap_base;
 	return paddr;
 }
 
 
-/* gnode -> pnode */
+/* gpa -> pnode */
 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
 {
-	return gpa >> uv_hub_info->m_val;
+	return gpa >> uv_hub_info->n_lshift;
 }
 
 /* gpa -> pnode */
@@ -320,6 +345,12 @@ static inline int uv_gpa_to_pnode(unsign
 	return uv_gpa_to_gnode(gpa) & n_mask;
 }
 
+/* gpa -> node offset*/
+static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
+{
+	return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
+}
+
 /* pnode, offset --> socket virtual */
 static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
 {
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_mmrs.h linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_mmrs.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/uv/uv_mmrs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/uv/uv_mmrs.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 
 #define UV1_HUB_PART_NUMBER	0x88a5
 #define UV2_HUB_PART_NUMBER	0x8eb8
+#define UV2_HUB_PART_NUMBER_X	0x1111
 
 /* Compat: if this #define is present, UV headers support UV2 */
 #define UV2_HUB_IS_SUPPORTED	1
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/vmx.h linux-libre-3.2-gnu1/arch/x86/include/asm/vmx.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/vmx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/vmx.h	2012-01-04 18:55:44.000000000 -0500
@@ -350,6 +350,18 @@ enum vmcs_field {
 #define DEBUG_REG_ACCESS_REG(eq)        (((eq) >> 8) & 0xf) /* 11:8, general purpose reg. */
 
 
+/*
+ * Exit Qualifications for APIC-Access
+ */
+#define APIC_ACCESS_OFFSET              0xfff   /* 11:0, offset within the APIC page */
+#define APIC_ACCESS_TYPE                0xf000  /* 15:12, access type */
+#define TYPE_LINEAR_APIC_INST_READ      (0 << 12)
+#define TYPE_LINEAR_APIC_INST_WRITE     (1 << 12)
+#define TYPE_LINEAR_APIC_INST_FETCH     (2 << 12)
+#define TYPE_LINEAR_APIC_EVENT          (3 << 12)
+#define TYPE_PHYSICAL_APIC_EVENT        (10 << 12)
+#define TYPE_PHYSICAL_APIC_INST         (15 << 12)
+
 /* segment AR */
 #define SEGMENT_AR_L_MASK (1 << 13)
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/x86_init.h linux-libre-3.2-gnu1/arch/x86/include/asm/x86_init.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/x86_init.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/x86_init.h	2012-01-04 18:55:44.000000000 -0500
@@ -152,6 +152,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
+ * @wallclock_init:		init the wallclock device
  * @get_wallclock:		get time from HW clock like RTC etc.
  * @set_wallclock:		set time back to HW clock
  * @is_untracked_pat_range	exclude from PAT logic
@@ -160,11 +161,13 @@ struct x86_cpuinit_ops {
  */
 struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
+	void (*wallclock_init)(void);
 	unsigned long (*get_wallclock)(void);
 	int (*set_wallclock)(unsigned long nowtime);
 	void (*iommu_shutdown)(void);
 	bool (*is_untracked_pat_range)(u64 start, u64 end);
 	void (*nmi_init)(void);
+	unsigned char (*get_nmi_reason)(void);
 	int (*i8042_detect)(void);
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/xen/grant_table.h linux-libre-3.2-gnu1/arch/x86/include/asm/xen/grant_table.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/xen/grant_table.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/xen/grant_table.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _ASM_X86_XEN_GRANT_TABLE_H
-#define _ASM_X86_XEN_GRANT_TABLE_H
-
-#define xen_alloc_vm_area(size)	alloc_vm_area(size)
-#define xen_free_vm_area(area)	free_vm_area(area)
-
-#endif /* _ASM_X86_XEN_GRANT_TABLE_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/xen/hypercall.h linux-libre-3.2-gnu1/arch/x86/include/asm/xen/hypercall.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/xen/hypercall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/xen/hypercall.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/physdev.h>
+#include <xen/interface/platform.h>
 
 /*
  * The hypercall asms have to meet several constraints:
@@ -301,6 +302,13 @@ HYPERVISOR_set_timer_op(u64 timeout)
 }
 
 static inline int
+HYPERVISOR_dom0_op(struct xen_platform_op *platform_op)
+{
+	platform_op->interface_version = XENPF_INTERFACE_VERSION;
+	return _hypercall1(int, dom0_op, platform_op);
+}
+
+static inline int
 HYPERVISOR_set_debugreg(int reg, unsigned long value)
 {
 	return _hypercall2(int, set_debugreg, reg, value);
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/xen/interface.h linux-libre-3.2-gnu1/arch/x86/include/asm/xen/interface.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/xen/interface.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/xen/interface.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@ DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
 DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
+DEFINE_GUEST_HANDLE(uint64_t);
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
diff -druNp linux-libre-3.1-gnu1/arch/x86/include/asm/xen/page.h linux-libre-3.2-gnu1/arch/x86/include/asm/xen/page.h
--- linux-libre-3.1-gnu1/arch/x86/include/asm/xen/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/include/asm/xen/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <asm/pgtable.h>
 
 #include <xen/interface/xen.h>
+#include <xen/grant_table.h>
 #include <xen/features.h>
 
 /* Xen machine address */
@@ -48,14 +49,11 @@ extern unsigned long set_phys_range_iden
 					     unsigned long pfn_e);
 
 extern int m2p_add_override(unsigned long mfn, struct page *page,
-			    bool clear_pte);
+			    struct gnttab_map_grant_ref *kmap_op);
 extern int m2p_remove_override(struct page *page, bool clear_pte);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
-#ifdef CONFIG_XEN_DEBUG_FS
-extern int p2m_dump_show(struct seq_file *m, void *v);
-#endif
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
 	unsigned long mfn;
diff -druNp linux-libre-3.1-gnu1/arch/x86/Kconfig linux-libre-3.2-gnu1/arch/x86/Kconfig
--- linux-libre-3.1-gnu1/arch/x86/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -64,10 +64,12 @@ config X86
 	select HAVE_TEXT_POKE_SMP
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
 	select GENERIC_FIND_FIRST_BIT
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_IRQ_SHOW
+	select GENERIC_CLOCKEVENTS_MIN_ADJUST
 	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_BPF_JIT if (X86_64 && NET)
@@ -130,7 +132,7 @@ config SBUS
 	bool
 
 config NEED_DMA_MAP_STATE
-       def_bool (X86_64 || DMAR || DMA_API_DEBUG)
+       def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG)
 
 config NEED_SG_DMA_LENGTH
 	def_bool y
@@ -192,9 +194,6 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK
 config NEED_PER_CPU_PAGE_FIRST_CHUNK
 	def_bool y
 
-config HAVE_CPUMASK_OF_CPU_MAP
-	def_bool X86_64_SMP
-
 config ARCH_HIBERNATION_POSSIBLE
 	def_bool y
 
@@ -220,7 +219,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 
 config HAVE_INTEL_TXT
 	def_bool y
-	depends on EXPERIMENTAL && DMAR && ACPI
+	depends on EXPERIMENTAL && INTEL_IOMMU && ACPI
 
 config X86_32_SMP
 	def_bool y
@@ -279,7 +278,7 @@ config SMP
 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
 	  Management" code will be disabled if you say Y here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://www.tldp.org/docs.html#howto>.
 
@@ -287,7 +286,7 @@ config SMP
 
 config X86_X2APIC
 	bool "Support x2apic"
-	depends on X86_LOCAL_APIC && X86_64 && INTR_REMAP
+	depends on X86_LOCAL_APIC && X86_64 && IRQ_REMAP
 	---help---
 	  This enables x2apic support on CPUs that have this feature.
 
@@ -391,7 +390,7 @@ config X86_INTEL_CE
 	  This option compiles in support for the CE4100 SOC for settop
 	  boxes and media devices.
 
-config X86_INTEL_MID
+config X86_WANT_INTEL_MID
 	bool "Intel MID platform support"
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
@@ -400,7 +399,10 @@ config X86_INTEL_MID
 	  systems which do not have the PCI legacy interfaces (Moorestown,
 	  Medfield). If you are building for a PC class system say N here.
 
-if X86_INTEL_MID
+if X86_WANT_INTEL_MID
+
+config X86_INTEL_MID
+	bool
 
 config X86_MRST
        bool "Moorestown MID platform"
@@ -412,6 +414,7 @@ config X86_MRST
 	select SPI
 	select INTEL_SCU_IPC
 	select X86_PLATFORM_DEVICES
+	select X86_INTEL_MID
 	---help---
 	  Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
 	  Internet Device(MID) platform. Moorestown consists of two chips:
@@ -1452,6 +1455,15 @@ config ARCH_USES_PG_UNCACHED
 	def_bool y
 	depends on X86_PAT
 
+config ARCH_RANDOM
+	def_bool y
+	prompt "x86 architectural random number generator" if EXPERT
+	---help---
+	  Enable the x86 architectural RDRAND instruction
+	  (Intel Bull Mountain technology) to generate random numbers.
+	  If supported, this is a high bandwidth, cryptographically
+	  secure hardware random number generator.
+
 config EFI
 	bool "EFI runtime service support"
 	depends on ACPI
@@ -2064,6 +2076,20 @@ config OLPC_XO15_SCI
 	   - AC adapter status updates
 	   - Battery status updates
 
+config ALIX
+	bool "PCEngines ALIX System Support (LED setup)"
+	select GPIOLIB
+	---help---
+	  This option enables system support for the PCEngines ALIX.
+	  At present this just sets up LEDs for GPIO control on
+	  ALIX2/3/6 boards.  However, other system specific setup should
+	  get added here.
+
+	  Note: You must still enable the drivers for GPIO and LED support
+	  (GPIO_CS5535 & LEDS_GPIO) to actually use the LEDs
+
+	  Note: You have to set alix.force=1 for boards with Award BIOS.
+
 endif # X86_32
 
 config AMD_NB
diff -druNp linux-libre-3.1-gnu1/arch/x86/Kconfig.debug linux-libre-3.2-gnu1/arch/x86/Kconfig.debug
--- linux-libre-3.1-gnu1/arch/x86/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@ config IOMMU_DEBUG
 	  code. When you use it make sure you have a big enough
 	  IOMMU/AGP aperture.  Most of the options enabled by this can
 	  be set more finegrained using the iommu= command line
-	  options. See Documentation/x86_64/boot-options.txt for more
+	  options. See Documentation/x86/x86_64/boot-options.txt for more
 	  details.
 
 config IOMMU_STRESS
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/alternative.c linux-libre-3.2-gnu1/arch/x86/kernel/alternative.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/alternative.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/alternative.c	2012-01-04 18:55:44.000000000 -0500
@@ -738,5 +738,5 @@ void __kprobes text_poke_smp_batch(struc
 
 	atomic_set(&stop_machine_first, 1);
 	wrote_text = 0;
-	__stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+	__stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/amd_gart_64.c linux-libre-3.2-gnu1/arch/x86/kernel/amd_gart_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/amd_gart_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/amd_gart_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * This allows to use PCI devices that only support 32bit addresses on systems
  * with more than 4GB.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt for the interface specification.
+ * See Documentation/DMA-API-HOWTO.txt for the interface specification.
  *
  * Copyright 2002 Andi Kleen, SuSE Labs.
  * Subject to the GNU General Public License v2 only.
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/apic.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/apic.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/apic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/apic.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@ static struct resource lapic_resource =
 	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int lapic_timer_frequency = 0;
 
 static void apic_pm_activate(void);
 
@@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_ONESHOT:
-		__setup_APIC_LVTT(calibration_result,
+		__setup_APIC_LVTT(lapic_timer_frequency,
 				  mode != CLOCK_EVT_MODE_PERIODIC, 1);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
@@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(v
 	long delta, deltatsc;
 	int pm_referenced = 0;
 
+	/**
+	 * check if lapic timer has already been calibrated by platform
+	 * specific routine, such as tsc calibration code. if so, we just fill
+	 * in the clockevent structure and return.
+	 */
+
+	if (lapic_timer_frequency) {
+		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+				lapic_timer_frequency);
+		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
+					TICK_NSEC, lapic_clockevent.shift);
+		lapic_clockevent.max_delta_ns =
+			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+		lapic_clockevent.min_delta_ns =
+			clockevent_delta2ns(0xF, &lapic_clockevent);
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+		return 0;
+	}
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(v
 	lapic_clockevent.min_delta_ns =
 		clockevent_delta2ns(0xF, &lapic_clockevent);
 
-	calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+	lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
 	apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
 	apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
 	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
-		    calibration_result);
+		    lapic_timer_frequency);
 
 	if (cpu_has_tsc) {
 		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(v
 
 	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
 		    "%u.%04u MHz.\n",
-		    calibration_result / (1000000 / HZ),
-		    calibration_result % (1000000 / HZ));
+		    lapic_timer_frequency / (1000000 / HZ),
+		    lapic_timer_frequency % (1000000 / HZ));
 
 	/*
 	 * Do a sanity check on the APIC calibration result
 	 */
-	if (calibration_result < (1000000 / HZ)) {
+	if (lapic_timer_frequency < (1000000 / HZ)) {
 		local_irq_enable();
 		pr_warning("APIC frequency too slow, disabling apic timer\n");
 		return -1;
@@ -1437,27 +1456,21 @@ void enable_x2apic(void)
 
 int __init enable_IR(void)
 {
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 	if (!intr_remapping_supported()) {
 		pr_debug("intr-remapping not supported\n");
-		return 0;
+		return -1;
 	}
 
 	if (!x2apic_preenabled && skip_ioapic_setup) {
 		pr_info("Skipped enabling intr-remap because of skipping "
 			"io-apic setup\n");
-		return 0;
+		return -1;
 	}
 
-	if (enable_intr_remapping(x2apic_supported()))
-		return 0;
-
-	pr_info("Enabled Interrupt-remapping\n");
-
-	return 1;
-
+	return enable_intr_remapping();
 #endif
-	return 0;
+	return -1;
 }
 
 void __init enable_IR_x2apic(void)
@@ -1481,11 +1494,11 @@ void __init enable_IR_x2apic(void)
 	mask_ioapic_entries();
 
 	if (dmar_table_init_ret)
-		ret = 0;
+		ret = -1;
 	else
 		ret = enable_IR();
 
-	if (!ret) {
+	if (ret < 0) {
 		/* IR is required if there is APIC ID > 255 even when running
 		 * under KVM
 		 */
@@ -1499,6 +1512,9 @@ void __init enable_IR_x2apic(void)
 		x2apic_force_phys();
 	}
 
+	if (ret == IRQ_REMAP_XAPIC_MODE)
+		goto nox2apic;
+
 	x2apic_enabled = 1;
 
 	if (x2apic_supported() && !x2apic_mode) {
@@ -1508,19 +1524,21 @@ void __init enable_IR_x2apic(void)
 	}
 
 nox2apic:
-	if (!ret) /* IR enabling failed */
+	if (ret < 0) /* IR enabling failed */
 		restore_ioapic_entries();
 	legacy_pic->restore_mask();
 	local_irq_restore(flags);
 
 out:
-	if (x2apic_enabled)
+	if (x2apic_enabled || !x2apic_supported())
 		return;
 
 	if (x2apic_preenabled)
 		panic("x2apic: enabled by BIOS but kernel init failed.");
-	else if (cpu_has_x2apic)
-		pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
+	else if (ret == IRQ_REMAP_XAPIC_MODE)
+		pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
+	else if (ret < 0)
+		pr_info("x2apic not enabled, IRQ remapping init failed\n");
 }
 
 #ifdef CONFIG_X86_64
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/bigsmp_32.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/bigsmp_32.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/bigsmp_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/bigsmp_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -255,12 +255,24 @@ static struct apic apic_bigsmp = {
 	.x86_32_early_logical_apicid	= bigsmp_early_logical_apicid,
 };
 
-struct apic * __init generic_bigsmp_probe(void)
+void __init generic_bigsmp_probe(void)
 {
-	if (probe_bigsmp())
-		return &apic_bigsmp;
+	unsigned int cpu;
 
-	return NULL;
+	if (!probe_bigsmp())
+		return;
+
+	apic = &apic_bigsmp;
+
+	for_each_possible_cpu(cpu) {
+		if (early_per_cpu(x86_cpu_to_logical_apicid,
+				  cpu) == BAD_APICID)
+			continue;
+		early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+			bigsmp_early_logical_apicid(cpu);
+	}
+
+	pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
 }
 
 apic_driver(apic_bigsmp);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/hw_nmi.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/hw_nmi.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/hw_nmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/hw_nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,22 +60,10 @@ void arch_trigger_all_cpu_backtrace(void
 }
 
 static int __kprobes
-arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
-			 unsigned long cmd, void *__args)
+arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = __args;
-	struct pt_regs *regs;
 	int cpu;
 
-	switch (cmd) {
-	case DIE_NMI:
-		break;
-
-	default:
-		return NOTIFY_DONE;
-	}
-
-	regs = args->regs;
 	cpu = smp_processor_id();
 
 	if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
@@ -86,21 +74,16 @@ arch_trigger_all_cpu_backtrace_handler(s
 		show_regs(regs);
 		arch_spin_unlock(&lock);
 		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	}
 
-	return NOTIFY_DONE;
+	return NMI_DONE;
 }
 
-static __read_mostly struct notifier_block backtrace_notifier = {
-	.notifier_call          = arch_trigger_all_cpu_backtrace_handler,
-	.next                   = NULL,
-	.priority               = NMI_LOCAL_LOW_PRIOR,
-};
-
 static int __init register_trigger_all_cpu_backtrace(void)
 {
-	register_die_notifier(&backtrace_notifier);
+	register_nmi_handler(NMI_LOCAL, arch_trigger_all_cpu_backtrace_handler,
+				0, "arch_bt");
 	return 0;
 }
 early_initcall(register_trigger_all_cpu_backtrace);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/io_apic.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/io_apic.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/io_apic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/io_apic.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,21 +92,21 @@ static struct ioapic {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } ioapics[MAX_IO_APICS];
 
-#define mpc_ioapic_ver(id)		ioapics[id].mp_config.apicver
+#define mpc_ioapic_ver(ioapic_idx)	ioapics[ioapic_idx].mp_config.apicver
 
-int mpc_ioapic_id(int id)
+int mpc_ioapic_id(int ioapic_idx)
 {
-	return ioapics[id].mp_config.apicid;
+	return ioapics[ioapic_idx].mp_config.apicid;
 }
 
-unsigned int mpc_ioapic_addr(int id)
+unsigned int mpc_ioapic_addr(int ioapic_idx)
 {
-	return ioapics[id].mp_config.apicaddr;
+	return ioapics[ioapic_idx].mp_config.apicaddr;
 }
 
-struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id)
+struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
 {
-	return &ioapics[id].gsi_config;
+	return &ioapics[ioapic_idx].gsi_config;
 }
 
 int nr_ioapics;
@@ -186,21 +186,15 @@ static struct irq_pin_list *alloc_irq_pi
 
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-#ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-#else
-static struct irq_cfg irq_cfgx[NR_IRQS];
-#endif
 
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
 	int count, node, i;
 
-	if (!legacy_pic->nr_legacy_irqs) {
-		nr_irqs_gsi = 0;
+	if (!legacy_pic->nr_legacy_irqs)
 		io_apic_irqs = ~0UL;
-	}
 
 	for (i = 0; i < nr_ioapics; i++) {
 		ioapics[i].saved_registers =
@@ -234,7 +228,6 @@ int __init arch_early_irq_init(void)
 	return 0;
 }
 
-#ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg *irq_cfg(unsigned int irq)
 {
 	return irq_get_chip_data(irq);
@@ -269,22 +262,6 @@ static void free_irq_cfg(unsigned int at
 	kfree(cfg);
 }
 
-#else
-
-struct irq_cfg *irq_cfg(unsigned int irq)
-{
-	return irq < nr_irqs ? irq_cfgx + irq : NULL;
-}
-
-static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
-{
-	return irq_cfgx + irq;
-}
-
-static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
-
-#endif
-
 static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
 {
 	int res = irq_alloc_desc_at(at, node);
@@ -394,13 +371,21 @@ union entry_union {
 	struct IO_APIC_route_entry entry;
 };
 
+static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin)
+{
+	union entry_union eu;
+
+	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	return eu.entry;
+}
+
 static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
 {
 	union entry_union eu;
 	unsigned long flags;
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	eu.entry = __ioapic_read_entry(apic, pin);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 	return eu.entry;
 }
@@ -529,18 +514,6 @@ static void io_apic_modify_irq(struct ir
 		__io_apic_modify_irq(entry, mask_and, mask_or, final);
 }
 
-static void __mask_and_edge_IO_APIC_irq(struct irq_pin_list *entry)
-{
-	__io_apic_modify_irq(entry, ~IO_APIC_REDIR_LEVEL_TRIGGER,
-			     IO_APIC_REDIR_MASKED, NULL);
-}
-
-static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
-{
-	__io_apic_modify_irq(entry, ~IO_APIC_REDIR_MASKED,
-			     IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
-}
-
 static void io_apic_sync(struct irq_pin_list *entry)
 {
 	/*
@@ -585,6 +558,66 @@ static void unmask_ioapic_irq(struct irq
 	unmask_ioapic(data->chip_data);
 }
 
+/*
+ * IO-APIC versions below 0x20 don't support EOI register.
+ * For the record, here is the information about various versions:
+ *     0Xh     82489DX
+ *     1Xh     I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
+ *     2Xh     I/O(x)APIC which is PCI 2.2 Compliant
+ *     30h-FFh Reserved
+ *
+ * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
+ * version as 0x2. This is an error with documentation and these ICH chips
+ * use io-apic's of version 0x20.
+ *
+ * For IO-APIC's with EOI register, we use that to do an explicit EOI.
+ * Otherwise, we simulate the EOI message manually by changing the trigger
+ * mode to edge and then back to level, with RTE being masked during this.
+ */
+static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
+{
+	if (mpc_ioapic_ver(apic) >= 0x20) {
+		/*
+		 * Intr-remapping uses pin number as the virtual vector
+		 * in the RTE. Actual vector is programmed in
+		 * intr-remapping table entry. Hence for the io-apic
+		 * EOI we use the pin number.
+		 */
+		if (cfg && irq_remapped(cfg))
+			io_apic_eoi(apic, pin);
+		else
+			io_apic_eoi(apic, vector);
+	} else {
+		struct IO_APIC_route_entry entry, entry1;
+
+		entry = entry1 = __ioapic_read_entry(apic, pin);
+
+		/*
+		 * Mask the entry and change the trigger mode to edge.
+		 */
+		entry1.mask = 1;
+		entry1.trigger = IOAPIC_EDGE;
+
+		__ioapic_write_entry(apic, pin, entry1);
+
+		/*
+		 * Restore the previous level triggered entry.
+		 */
+		__ioapic_write_entry(apic, pin, entry);
+	}
+}
+
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+	struct irq_pin_list *entry;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	for_each_irq_pin(entry, cfg->irq_2_pin)
+		__eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
 	struct IO_APIC_route_entry entry;
@@ -593,10 +626,44 @@ static void clear_IO_APIC_pin(unsigned i
 	entry = ioapic_read_entry(apic, pin);
 	if (entry.delivery_mode == dest_SMI)
 		return;
+
 	/*
-	 * Disable it in the IO-APIC irq-routing table:
+	 * Make sure the entry is masked and re-read the contents to check
+	 * if it is a level triggered pin and if the remote-IRR is set.
+	 */
+	if (!entry.mask) {
+		entry.mask = 1;
+		ioapic_write_entry(apic, pin, entry);
+		entry = ioapic_read_entry(apic, pin);
+	}
+
+	if (entry.irr) {
+		unsigned long flags;
+
+		/*
+		 * Make sure the trigger mode is set to level. Explicit EOI
+		 * doesn't clear the remote-IRR if the trigger mode is not
+		 * set to level.
+		 */
+		if (!entry.trigger) {
+			entry.trigger = IOAPIC_LEVEL;
+			ioapic_write_entry(apic, pin, entry);
+		}
+
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
+		__eoi_ioapic_pin(apic, pin, entry.vector, NULL);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+
+	/*
+	 * Clear the rest of the bits in the IO-APIC RTE except for the mask
+	 * bit.
 	 */
 	ioapic_mask_entry(apic, pin);
+	entry = ioapic_read_entry(apic, pin);
+	if (entry.irr)
+		printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n",
+		       mpc_ioapic_id(apic), pin);
 }
 
 static void clear_IO_APIC (void)
@@ -712,13 +779,13 @@ int restore_ioapic_entries(void)
 /*
  * Find the IRQ entry number of a certain pin.
  */
-static int find_irq_entry(int apic, int pin, int type)
+static int find_irq_entry(int ioapic_idx, int pin, int type)
 {
 	int i;
 
 	for (i = 0; i < mp_irq_entries; i++)
 		if (mp_irqs[i].irqtype == type &&
-		    (mp_irqs[i].dstapic == mpc_ioapic_id(apic) ||
+		    (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) ||
 		     mp_irqs[i].dstapic == MP_APIC_ALL) &&
 		    mp_irqs[i].dstirq == pin)
 			return i;
@@ -757,12 +824,13 @@ static int __init find_isa_irq_apic(int
 		    (mp_irqs[i].srcbusirq == irq))
 			break;
 	}
+
 	if (i < mp_irq_entries) {
-		int apic;
-		for(apic = 0; apic < nr_ioapics; apic++) {
-			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic)
-				return apic;
-		}
+		int ioapic_idx;
+
+		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
+				return ioapic_idx;
 	}
 
 	return -1;
@@ -977,7 +1045,7 @@ static int pin_2_irq(int idx, int apic,
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
 				struct io_apic_irq_attr *irq_attr)
 {
-	int apic, i, best_guess = -1;
+	int ioapic_idx, i, best_guess = -1;
 
 	apic_printk(APIC_DEBUG,
 		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -990,8 +1058,8 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 	for (i = 0; i < mp_irq_entries; i++) {
 		int lbus = mp_irqs[i].srcbus;
 
-		for (apic = 0; apic < nr_ioapics; apic++)
-			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic ||
+		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
 			    mp_irqs[i].dstapic == MP_APIC_ALL)
 				break;
 
@@ -999,13 +1067,13 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 		    !mp_irqs[i].irqtype &&
 		    (bus == lbus) &&
 		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+			int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
 
-			if (!(apic || IO_APIC_IRQ(irq)))
+			if (!(ioapic_idx || IO_APIC_IRQ(irq)))
 				continue;
 
 			if (pin == (mp_irqs[i].srcbusirq & 3)) {
-				set_io_apic_irq_attr(irq_attr, apic,
+				set_io_apic_irq_attr(irq_attr, ioapic_idx,
 						     mp_irqs[i].dstirq,
 						     irq_trigger(i),
 						     irq_polarity(i));
@@ -1016,7 +1084,7 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 			 * best-guess fuzzy result for broken mptables.
 			 */
 			if (best_guess < 0) {
-				set_io_apic_irq_attr(irq_attr, apic,
+				set_io_apic_irq_attr(irq_attr, ioapic_idx,
 						     mp_irqs[i].dstirq,
 						     irq_trigger(i),
 						     irq_polarity(i));
@@ -1202,7 +1270,6 @@ void __setup_vector_irq(int cpu)
 }
 
 static struct irq_chip ioapic_chip;
-static struct irq_chip ir_ioapic_chip;
 
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
@@ -1246,7 +1313,7 @@ static void ioapic_register_intr(unsigne
 
 	if (irq_remapped(cfg)) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		chip = &ir_ioapic_chip;
+		irq_remap_modify_chip_defaults(chip);
 		fasteoi = trigger != 0;
 	}
 
@@ -1255,77 +1322,100 @@ static void ioapic_register_intr(unsigne
 				      fasteoi ? "fasteoi" : "edge");
 }
 
-static int setup_ioapic_entry(int apic_id, int irq,
-			      struct IO_APIC_route_entry *entry,
-			      unsigned int destination, int trigger,
-			      int polarity, int vector, int pin)
-{
-	/*
-	 * add it to the IO-APIC irq-routing table:
-	 */
-	memset(entry,0,sizeof(*entry));
 
-	if (intr_remapping_enabled) {
-		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
-		struct irte irte;
-		struct IR_IO_APIC_route_entry *ir_entry =
-			(struct IR_IO_APIC_route_entry *) entry;
-		int index;
+static int setup_ir_ioapic_entry(int irq,
+			      struct IR_IO_APIC_route_entry *entry,
+			      unsigned int destination, int vector,
+			      struct io_apic_irq_attr *attr)
+{
+	int index;
+	struct irte irte;
+	int ioapic_id = mpc_ioapic_id(attr->ioapic);
+	struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
 
-		if (!iommu)
-			panic("No mapping iommu for ioapic %d\n", apic_id);
+	if (!iommu) {
+		pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
+		return -ENODEV;
+	}
 
-		index = alloc_irte(iommu, irq, 1);
-		if (index < 0)
-			panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
+	index = alloc_irte(iommu, irq, 1);
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
+		return -ENOMEM;
+	}
 
-		prepare_irte(&irte, vector, destination);
+	prepare_irte(&irte, vector, destination);
 
-		/* Set source-id of interrupt request */
-		set_ioapic_sid(&irte, apic_id);
+	/* Set source-id of interrupt request */
+	set_ioapic_sid(&irte, ioapic_id);
 
-		modify_irte(irq, &irte);
+	modify_irte(irq, &irte);
 
-		ir_entry->index2 = (index >> 15) & 0x1;
-		ir_entry->zero = 0;
-		ir_entry->format = 1;
-		ir_entry->index = (index & 0x7fff);
-		/*
-		 * IO-APIC RTE will be configured with virtual vector.
-		 * irq handler will do the explicit EOI to the io-apic.
-		 */
-		ir_entry->vector = pin;
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+		"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+		"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+		"Avail:%X Vector:%02X Dest:%08X "
+		"SID:%04X SQ:%X SVT:%X)\n",
+		attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
+		irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+		irte.avail, irte.vector, irte.dest_id,
+		irte.sid, irte.sq, irte.svt);
 
-		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
-			"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
-			"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
-			"Avail:%X Vector:%02X Dest:%08X "
-			"SID:%04X SQ:%X SVT:%X)\n",
-			apic_id, irte.present, irte.fpd, irte.dst_mode,
-			irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
-			irte.avail, irte.vector, irte.dest_id,
-			irte.sid, irte.sq, irte.svt);
-	} else {
-		entry->delivery_mode = apic->irq_delivery_mode;
-		entry->dest_mode = apic->irq_dest_mode;
-		entry->dest = destination;
-		entry->vector = vector;
-	}
+	memset(entry, 0, sizeof(*entry));
 
-	entry->mask = 0;				/* enable IRQ */
-	entry->trigger = trigger;
-	entry->polarity = polarity;
+	entry->index2	= (index >> 15) & 0x1;
+	entry->zero	= 0;
+	entry->format	= 1;
+	entry->index	= (index & 0x7fff);
+	/*
+	 * IO-APIC RTE will be configured with virtual vector.
+	 * irq handler will do the explicit EOI to the io-apic.
+	 */
+	entry->vector	= attr->ioapic_pin;
+	entry->mask	= 0;			/* enable IRQ */
+	entry->trigger	= attr->trigger;
+	entry->polarity	= attr->polarity;
 
 	/* Mask level triggered irqs.
 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
 	 */
-	if (trigger)
+	if (attr->trigger)
 		entry->mask = 1;
+
 	return 0;
 }
 
-static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
-			     struct irq_cfg *cfg, int trigger, int polarity)
+static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
+			       unsigned int destination, int vector,
+			       struct io_apic_irq_attr *attr)
+{
+	if (intr_remapping_enabled)
+		return setup_ir_ioapic_entry(irq,
+			 (struct IR_IO_APIC_route_entry *)entry,
+			 destination, vector, attr);
+
+	memset(entry, 0, sizeof(*entry));
+
+	entry->delivery_mode = apic->irq_delivery_mode;
+	entry->dest_mode     = apic->irq_dest_mode;
+	entry->dest	     = destination;
+	entry->vector	     = vector;
+	entry->mask	     = 0;			/* enable IRQ */
+	entry->trigger	     = attr->trigger;
+	entry->polarity	     = attr->polarity;
+
+	/*
+	 * Mask level triggered irqs.
+	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+	 */
+	if (attr->trigger)
+		entry->mask = 1;
+
+	return 0;
+}
+
+static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
+				struct io_apic_irq_attr *attr)
 {
 	struct IO_APIC_route_entry entry;
 	unsigned int dest;
@@ -1348,49 +1438,48 @@ static void setup_ioapic_irq(int apic_id
 	apic_printk(APIC_VERBOSE,KERN_DEBUG
 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
 		    "IRQ %d Mode:%i Active:%i Dest:%d)\n",
-		    apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
-		    irq, trigger, polarity, dest);
-
+		    attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin,
+		    cfg->vector, irq, attr->trigger, attr->polarity, dest);
 
-	if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
-			       dest, trigger, polarity, cfg->vector, pin)) {
-		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
-		       mpc_ioapic_id(apic_id), pin);
+	if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
+		pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+			mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
 		__clear_irq_vector(irq, cfg);
+
 		return;
 	}
 
-	ioapic_register_intr(irq, cfg, trigger);
+	ioapic_register_intr(irq, cfg, attr->trigger);
 	if (irq < legacy_pic->nr_legacy_irqs)
 		legacy_pic->mask(irq);
 
-	ioapic_write_entry(apic_id, pin, entry);
+	ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
 }
 
-static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
+static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin)
 {
 	if (idx != -1)
 		return false;
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
-		    mpc_ioapic_id(apic_id), pin);
+		    mpc_ioapic_id(ioapic_idx), pin);
 	return true;
 }
 
-static void __init __io_apic_setup_irqs(unsigned int apic_id)
+static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
 {
 	int idx, node = cpu_to_node(0);
 	struct io_apic_irq_attr attr;
 	unsigned int pin, irq;
 
-	for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) {
-		idx = find_irq_entry(apic_id, pin, mp_INT);
-		if (io_apic_pin_not_connected(idx, apic_id, pin))
+	for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
+		idx = find_irq_entry(ioapic_idx, pin, mp_INT);
+		if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
 			continue;
 
-		irq = pin_2_irq(idx, apic_id, pin);
+		irq = pin_2_irq(idx, ioapic_idx, pin);
 
-		if ((apic_id > 0) && (irq > 16))
+		if ((ioapic_idx > 0) && (irq > 16))
 			continue;
 
 		/*
@@ -1398,10 +1487,10 @@ static void __init __io_apic_setup_irqs(
 		 * installed and if it returns 1:
 		 */
 		if (apic->multi_timer_check &&
-		    apic->multi_timer_check(apic_id, irq))
+		    apic->multi_timer_check(ioapic_idx, irq))
 			continue;
 
-		set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+		set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 				     irq_polarity(idx));
 
 		io_apic_setup_irq_pin(irq, node, &attr);
@@ -1410,12 +1499,12 @@ static void __init __io_apic_setup_irqs(
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	unsigned int apic_id;
+	unsigned int ioapic_idx;
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
-		__io_apic_setup_irqs(apic_id);
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		__io_apic_setup_irqs(ioapic_idx);
 }
 
 /*
@@ -1425,28 +1514,28 @@ static void __init setup_IO_APIC_irqs(vo
  */
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
-	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
+	int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
 	struct io_apic_irq_attr attr;
 
 	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
 	 */
-	apic_id = mp_find_ioapic(gsi);
-	if (apic_id < 0)
+	ioapic_idx = mp_find_ioapic(gsi);
+	if (ioapic_idx < 0)
 		return;
 
-	pin = mp_find_ioapic_pin(apic_id, gsi);
-	idx = find_irq_entry(apic_id, pin, mp_INT);
+	pin = mp_find_ioapic_pin(ioapic_idx, gsi);
+	idx = find_irq_entry(ioapic_idx, pin, mp_INT);
 	if (idx == -1)
 		return;
 
-	irq = pin_2_irq(idx, apic_id, pin);
+	irq = pin_2_irq(idx, ioapic_idx, pin);
 
 	/* Only handle the non legacy irqs on secondary ioapics */
-	if (apic_id == 0 || irq < NR_IRQS_LEGACY)
+	if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
 		return;
 
-	set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 			     irq_polarity(idx));
 
 	io_apic_setup_irq_pin_once(irq, node, &attr);
@@ -1455,8 +1544,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 /*
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
-static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
-					int vector)
+static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
+					 unsigned int pin, int vector)
 {
 	struct IO_APIC_route_entry entry;
 
@@ -1487,45 +1576,29 @@ static void __init setup_timer_IRQ0_pin(
 	/*
 	 * Add it to the IO-APIC irq-routing table:
 	 */
-	ioapic_write_entry(apic_id, pin, entry);
+	ioapic_write_entry(ioapic_idx, pin, entry);
 }
 
-
-__apicdebuginit(void) print_IO_APIC(void)
+__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
 {
-	int apic, i;
+	int i;
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
 	union IO_APIC_reg_02 reg_02;
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
-	struct irq_cfg *cfg;
-	unsigned int irq;
-
-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
-	for (i = 0; i < nr_ioapics; i++)
-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
-		       mpc_ioapic_id(i), ioapics[i].nr_registers);
-
-	/*
-	 * We are a bit conservative about what we expect.  We have to
-	 * know about every hardware change ASAP.
-	 */
-	printk(KERN_INFO "testing the IO APIC.......................\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(apic, 0);
-	reg_01.raw = io_apic_read(apic, 1);
+	reg_00.raw = io_apic_read(ioapic_idx, 0);
+	reg_01.raw = io_apic_read(ioapic_idx, 1);
 	if (reg_01.bits.version >= 0x10)
-		reg_02.raw = io_apic_read(apic, 2);
+		reg_02.raw = io_apic_read(ioapic_idx, 2);
 	if (reg_01.bits.version >= 0x20)
-		reg_03.raw = io_apic_read(apic, 3);
+		reg_03.raw = io_apic_read(ioapic_idx, 3);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
-	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic));
+	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx));
 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
@@ -1575,7 +1648,7 @@ __apicdebuginit(void) print_IO_APIC(void
 			struct IO_APIC_route_entry entry;
 			struct IR_IO_APIC_route_entry *ir_entry;
 
-			entry = ioapic_read_entry(apic, i);
+			entry = ioapic_read_entry(ioapic_idx, i);
 			ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
 			printk(KERN_DEBUG " %02x %04X ",
 				i,
@@ -1596,7 +1669,7 @@ __apicdebuginit(void) print_IO_APIC(void
 		} else {
 			struct IO_APIC_route_entry entry;
 
-			entry = ioapic_read_entry(apic, i);
+			entry = ioapic_read_entry(ioapic_idx, i);
 			printk(KERN_DEBUG " %02x %02X  ",
 				i,
 				entry.dest
@@ -1614,12 +1687,38 @@ __apicdebuginit(void) print_IO_APIC(void
 			);
 		}
 	}
-	}
+}
+
+__apicdebuginit(void) print_IO_APICs(void)
+{
+	int ioapic_idx;
+	struct irq_cfg *cfg;
+	unsigned int irq;
+	struct irq_chip *chip;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+		       mpc_ioapic_id(ioapic_idx),
+		       ioapics[ioapic_idx].nr_registers);
+
+	/*
+	 * We are a bit conservative about what we expect.  We have to
+	 * know about every hardware change ASAP.
+	 */
+	printk(KERN_INFO "testing the IO APIC.......................\n");
+
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		print_IO_APIC(ioapic_idx);
 
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
 	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
 
+		chip = irq_get_chip(irq);
+		if (chip != &ioapic_chip)
+			continue;
+
 		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
@@ -1633,8 +1732,6 @@ __apicdebuginit(void) print_IO_APIC(void
 	}
 
 	printk(KERN_INFO ".................................... done.\n");
-
-	return;
 }
 
 __apicdebuginit(void) print_APIC_field(int base)
@@ -1828,7 +1925,7 @@ __apicdebuginit(int) print_ICs(void)
 		return 0;
 
 	print_local_APICs(show_lapic);
-	print_IO_APIC();
+	print_IO_APICs();
 
 	return 0;
 }
@@ -1953,7 +2050,7 @@ void __init setup_ioapic_ids_from_mpc_no
 {
 	union IO_APIC_reg_00 reg_00;
 	physid_mask_t phys_id_present_map;
-	int apic_id;
+	int ioapic_idx;
 	int i;
 	unsigned char old_id;
 	unsigned long flags;
@@ -1967,21 +2064,20 @@ void __init setup_ioapic_ids_from_mpc_no
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
 	 */
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
-
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
 		/* Read the register 0 value */
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic_id, 0);
+		reg_00.raw = io_apic_read(ioapic_idx, 0);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
-		old_id = mpc_ioapic_id(apic_id);
+		old_id = mpc_ioapic_id(ioapic_idx);
 
-		if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) {
+		if (mpc_ioapic_id(ioapic_idx) >= get_physical_broadcast()) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
-				apic_id, mpc_ioapic_id(apic_id));
+				ioapic_idx, mpc_ioapic_id(ioapic_idx));
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				reg_00.bits.ID);
-			ioapics[apic_id].mp_config.apicid = reg_00.bits.ID;
+			ioapics[ioapic_idx].mp_config.apicid = reg_00.bits.ID;
 		}
 
 		/*
@@ -1990,9 +2086,9 @@ void __init setup_ioapic_ids_from_mpc_no
 		 * 'stuck on smp_invalidate_needed IPI wait' messages.
 		 */
 		if (apic->check_apicid_used(&phys_id_present_map,
-					    mpc_ioapic_id(apic_id))) {
+					    mpc_ioapic_id(ioapic_idx))) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-				apic_id, mpc_ioapic_id(apic_id));
+				ioapic_idx, mpc_ioapic_id(ioapic_idx));
 			for (i = 0; i < get_physical_broadcast(); i++)
 				if (!physid_isset(i, phys_id_present_map))
 					break;
@@ -2001,14 +2097,14 @@ void __init setup_ioapic_ids_from_mpc_no
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				i);
 			physid_set(i, phys_id_present_map);
-			ioapics[apic_id].mp_config.apicid = i;
+			ioapics[ioapic_idx].mp_config.apicid = i;
 		} else {
 			physid_mask_t tmp;
-			apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id),
+			apic->apicid_to_cpu_present(mpc_ioapic_id(ioapic_idx),
 						    &tmp);
 			apic_printk(APIC_VERBOSE, "Setting %d in the "
 					"phys_id_present_map\n",
-					mpc_ioapic_id(apic_id));
+					mpc_ioapic_id(ioapic_idx));
 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
 		}
 
@@ -2016,35 +2112,35 @@ void __init setup_ioapic_ids_from_mpc_no
 		 * We need to adjust the IRQ routing table
 		 * if the ID changed.
 		 */
-		if (old_id != mpc_ioapic_id(apic_id))
+		if (old_id != mpc_ioapic_id(ioapic_idx))
 			for (i = 0; i < mp_irq_entries; i++)
 				if (mp_irqs[i].dstapic == old_id)
 					mp_irqs[i].dstapic
-						= mpc_ioapic_id(apic_id);
+						= mpc_ioapic_id(ioapic_idx);
 
 		/*
 		 * Update the ID register according to the right value
 		 * from the MPC table if they are different.
 		 */
-		if (mpc_ioapic_id(apic_id) == reg_00.bits.ID)
+		if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID)
 			continue;
 
 		apic_printk(APIC_VERBOSE, KERN_INFO
 			"...changing IO-APIC physical APIC ID to %d ...",
-			mpc_ioapic_id(apic_id));
+			mpc_ioapic_id(ioapic_idx));
 
-		reg_00.bits.ID = mpc_ioapic_id(apic_id);
+		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(apic_id, 0, reg_00.raw);
+		io_apic_write(ioapic_idx, 0, reg_00.raw);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic_id, 0);
+		reg_00.raw = io_apic_read(ioapic_idx, 0);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-		if (reg_00.bits.ID != mpc_ioapic_id(apic_id))
+		if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx))
 			printk("could not set ID!\n");
 		else
 			apic_printk(APIC_VERBOSE, " ok.\n");
@@ -2255,7 +2351,7 @@ ioapic_set_affinity(struct irq_data *dat
 	return ret;
 }
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 
 /*
  * Migrate the IO-APIC irq in the presence of intr-remapping.
@@ -2267,6 +2363,9 @@ ioapic_set_affinity(struct irq_data *dat
  * updated vector information), by using a virtual vector (io-apic pin number).
  * Real vector that is used for interrupting cpu will be coming from
  * the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
  */
 static int
 ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -2291,10 +2390,16 @@ ir_ioapic_set_affinity(struct irq_data *
 	irte.dest_id = IRTE_DEST(dest);
 
 	/*
-	 * Modified the IRTE and flushes the Interrupt entry cache.
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
 	 */
 	modify_irte(irq, &irte);
 
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
 	if (cfg->move_in_progress)
 		send_cleanup_vector(cfg);
 
@@ -2407,48 +2512,6 @@ static void ack_apic_edge(struct irq_dat
 
 atomic_t irq_mis_count;
 
-/*
- * IO-APIC versions below 0x20 don't support EOI register.
- * For the record, here is the information about various versions:
- *     0Xh     82489DX
- *     1Xh     I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
- *     2Xh     I/O(x)APIC which is PCI 2.2 Compliant
- *     30h-FFh Reserved
- *
- * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
- * version as 0x2. This is an error with documentation and these ICH chips
- * use io-apic's of version 0x20.
- *
- * For IO-APIC's with EOI register, we use that to do an explicit EOI.
- * Otherwise, we simulate the EOI message manually by changing the trigger
- * mode to edge and then back to level, with RTE being masked during this.
-*/
-static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
-	struct irq_pin_list *entry;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	for_each_irq_pin(entry, cfg->irq_2_pin) {
-		if (mpc_ioapic_ver(entry->apic) >= 0x20) {
-			/*
-			 * Intr-remapping uses pin number as the virtual vector
-			 * in the RTE. Actual vector is programmed in
-			 * intr-remapping table entry. Hence for the io-apic
-			 * EOI we use the pin number.
-			 */
-			if (irq_remapped(cfg))
-				io_apic_eoi(entry->apic, entry->pin);
-			else
-				io_apic_eoi(entry->apic, cfg->vector);
-		} else {
-			__mask_and_edge_IO_APIC_irq(entry);
-			__unmask_and_level_IO_APIC_irq(entry);
-		}
-	}
-	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
 static void ack_apic_level(struct irq_data *data)
 {
 	struct irq_cfg *cfg = data->chip_data;
@@ -2552,7 +2615,7 @@ static void ack_apic_level(struct irq_da
 	}
 }
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 static void ir_ack_apic_edge(struct irq_data *data)
 {
 	ack_APIC_irq();
@@ -2563,7 +2626,23 @@ static void ir_ack_apic_level(struct irq
 	ack_APIC_irq();
 	eoi_ioapic_irq(data->irq, data->chip_data);
 }
-#endif /* CONFIG_INTR_REMAP */
+
+static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
+{
+	seq_printf(p, " IR-%s", data->chip->name);
+}
+
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+	chip->irq_print_chip = ir_print_prefix;
+	chip->irq_ack = ir_ack_apic_edge;
+	chip->irq_eoi = ir_ack_apic_level;
+
+#ifdef CONFIG_SMP
+	chip->irq_set_affinity = ir_ioapic_set_affinity;
+#endif
+}
+#endif /* CONFIG_IRQ_REMAP */
 
 static struct irq_chip ioapic_chip __read_mostly = {
 	.name			= "IO-APIC",
@@ -2578,21 +2657,6 @@ static struct irq_chip ioapic_chip __rea
 	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
-static struct irq_chip ir_ioapic_chip __read_mostly = {
-	.name			= "IR-IO-APIC",
-	.irq_startup		= startup_ioapic_irq,
-	.irq_mask		= mask_ioapic_irq,
-	.irq_unmask		= unmask_ioapic_irq,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-	.irq_eoi		= ir_ack_apic_level,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_ioapic_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 static inline void init_IO_APIC_traps(void)
 {
 	struct irq_cfg *cfg;
@@ -2944,27 +3008,26 @@ static int __init io_apic_bug_finalize(v
 
 late_initcall(io_apic_bug_finalize);
 
-static void resume_ioapic_id(int ioapic_id)
+static void resume_ioapic_id(int ioapic_idx)
 {
 	unsigned long flags;
 	union IO_APIC_reg_00 reg_00;
 
-
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(ioapic_id, 0);
-	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) {
-		reg_00.bits.ID = mpc_ioapic_id(ioapic_id);
-		io_apic_write(ioapic_id, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(ioapic_idx, 0);
+	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) {
+		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
+		io_apic_write(ioapic_idx, 0, reg_00.raw);
 	}
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void ioapic_resume(void)
 {
-	int ioapic_id;
+	int ioapic_idx;
 
-	for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
-		resume_ioapic_id(ioapic_id);
+	for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+		resume_ioapic_id(ioapic_idx);
 
 	restore_ioapic_entries();
 }
@@ -3144,45 +3207,6 @@ msi_set_affinity(struct irq_data *data,
 
 	return 0;
 }
-#ifdef CONFIG_INTR_REMAP
-/*
- * Migrate the MSI irq to another cpumask. This migration is
- * done in the process context using interrupt-remapping hardware.
- */
-static int
-ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
-		    bool force)
-{
-	struct irq_cfg *cfg = data->chip_data;
-	unsigned int dest, irq = data->irq;
-	struct irte irte;
-
-	if (get_irte(irq, &irte))
-		return -1;
-
-	if (__ioapic_set_affinity(data, mask, &dest))
-		return -1;
-
-	irte.vector = cfg->vector;
-	irte.dest_id = IRTE_DEST(dest);
-
-	/*
-	 * atomically update the IRTE with the new destination and vector.
-	 */
-	modify_irte(irq, &irte);
-
-	/*
-	 * After this point, all the interrupts will start arriving
-	 * at the new destination. So, time to cleanup the previous
-	 * vector allocation.
-	 */
-	if (cfg->move_in_progress)
-		send_cleanup_vector(cfg);
-
-	return 0;
-}
-
-#endif
 #endif /* CONFIG_SMP */
 
 /*
@@ -3200,19 +3224,6 @@ static struct irq_chip msi_chip = {
 	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
-static struct irq_chip msi_ir_chip = {
-	.name			= "IR-PCI-MSI",
-	.irq_unmask		= unmask_msi_irq,
-	.irq_mask		= mask_msi_irq,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_msi_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 /*
  * Map the PCI dev to the corresponding remapping hardware unit
  * and allocate 'nvec' consecutive interrupt-remapping table entries
@@ -3255,7 +3266,7 @@ static int setup_msi_irq(struct pci_dev
 
 	if (irq_remapped(irq_get_chip_data(irq))) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		chip = &msi_ir_chip;
+		irq_remap_modify_chip_defaults(chip);
 	}
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
@@ -3328,7 +3339,7 @@ void native_teardown_msi_irq(unsigned in
 	destroy_irq(irq);
 }
 
-#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+#ifdef CONFIG_DMAR_TABLE
 #ifdef CONFIG_SMP
 static int
 dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -3409,19 +3420,6 @@ static int hpet_msi_set_affinity(struct
 
 #endif /* CONFIG_SMP */
 
-static struct irq_chip ir_hpet_msi_type = {
-	.name			= "IR-HPET_MSI",
-	.irq_unmask		= hpet_msi_unmask,
-	.irq_mask		= hpet_msi_mask,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_msi_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 static struct irq_chip hpet_msi_type = {
 	.name = "HPET_MSI",
 	.irq_unmask = hpet_msi_unmask,
@@ -3458,7 +3456,7 @@ int arch_setup_hpet_msi(unsigned int irq
 	hpet_msi_write(irq_get_handler_data(irq), &msg);
 	irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 	if (irq_remapped(irq_get_chip_data(irq)))
-		chip = &ir_hpet_msi_type;
+		irq_remap_modify_chip_defaults(chip);
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 	return 0;
@@ -3566,26 +3564,25 @@ io_apic_setup_irq_pin(unsigned int irq,
 		return -EINVAL;
 	ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
 	if (!ret)
-		setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
-				 attr->trigger, attr->polarity);
+		setup_ioapic_irq(irq, cfg, attr);
 	return ret;
 }
 
 int io_apic_setup_irq_pin_once(unsigned int irq, int node,
 			       struct io_apic_irq_attr *attr)
 {
-	unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
+	unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
 	int ret;
 
 	/* Avoid redundant programming */
-	if (test_bit(pin, ioapics[id].pin_programmed)) {
+	if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
 		pr_debug("Pin %d-%d already programmed\n",
-			 mpc_ioapic_id(id), pin);
+			 mpc_ioapic_id(ioapic_idx), pin);
 		return 0;
 	}
 	ret = io_apic_setup_irq_pin(irq, node, attr);
 	if (!ret)
-		set_bit(pin, ioapics[id].pin_programmed);
+		set_bit(pin, ioapics[ioapic_idx].pin_programmed);
 	return ret;
 }
 
@@ -3621,7 +3618,6 @@ int get_nr_irqs_gsi(void)
 	return nr_irqs_gsi;
 }
 
-#ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
 	int nr;
@@ -3641,7 +3637,6 @@ int __init arch_probe_nr_irqs(void)
 
 	return NR_IRQS_LEGACY;
 }
-#endif
 
 int io_apic_set_pci_routing(struct device *dev, int irq,
 			    struct io_apic_irq_attr *irq_attr)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/probe_32.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/probe_32.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/probe_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/probe_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,14 +200,8 @@ void __init default_setup_apic_routing(v
 	 * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
 	 */
 
-	if (!cmdline_apic && apic == &apic_default) {
-		struct apic *bigsmp = generic_bigsmp_probe();
-		if (bigsmp) {
-			apic = bigsmp;
-			printk(KERN_INFO "Overriding APIC driver with %s\n",
-			       apic->name);
-		}
-	}
+	if (!cmdline_apic && apic == &apic_default)
+		generic_bigsmp_probe();
 #endif
 
 	if (apic->setup_apic_routing)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-3.2-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,6 +93,8 @@ static int __init early_get_pnodeid(void
 
 	if (node_id.s.part_number == UV2_HUB_PART_NUMBER)
 		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;
+	if (node_id.s.part_number == UV2_HUB_PART_NUMBER_X)
+		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;
 
 	uv_hub_info->hub_revision = uv_min_hub_revision_id;
 	pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
@@ -672,18 +674,11 @@ void __cpuinit uv_cpu_init(void)
 /*
  * When NMI is received, print a stack trace.
  */
-int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
 {
 	unsigned long real_uv_nmi;
 	int bid;
 
-	if (reason != DIE_NMIUNKNOWN)
-		return NOTIFY_OK;
-
-	if (in_crash_kexec)
-		/* do nothing if entering the crash kernel */
-		return NOTIFY_OK;
-
 	/*
 	 * Each blade has an MMR that indicates when an NMI has been sent
 	 * to cpus on the blade. If an NMI is detected, atomically
@@ -704,7 +699,7 @@ int uv_handle_nmi(struct notifier_block
 	}
 
 	if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
-		return NOTIFY_DONE;
+		return NMI_DONE;
 
 	__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
 
@@ -717,17 +712,12 @@ int uv_handle_nmi(struct notifier_block
 	dump_stack();
 	spin_unlock(&uv_nmi_lock);
 
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
 
-static struct notifier_block uv_dump_stack_nmi_nb = {
-	.notifier_call	= uv_handle_nmi,
-	.priority = NMI_LOCAL_LOW_PRIOR - 1,
-};
-
 void uv_register_nmi_notifier(void)
 {
-	if (register_die_notifier(&uv_dump_stack_nmi_nb))
+	if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
 		printk(KERN_WARNING "UV NMI handler failed to register\n");
 }
 
@@ -832,6 +822,10 @@ void __init uv_system_init(void)
 		uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
 		uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
 
+		uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
+		uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
+				(m_val == 40 ? 40 : 39) : m_val;
+
 		pnode = uv_apicid_to_pnode(apicid);
 		blade = boot_pnode_to_blade(pnode);
 		lcpu = uv_blade_info[blade].nr_possible_cpus;
@@ -862,8 +856,7 @@ void __init uv_system_init(void)
 		if (uv_node_to_blade[nid] >= 0)
 			continue;
 		paddr = node_start_pfn(nid) << PAGE_SHIFT;
-		paddr = uv_soc_phys_ram_to_gpa(paddr);
-		pnode = (paddr >> m_val) & pnode_mask;
+		pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
 		blade = boot_pnode_to_blade(pnode);
 		uv_node_to_blade[nid] = blade;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/apm_32.c linux-libre-3.2-gnu1/arch/x86/kernel/apm_32.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/apm_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/apm_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -249,8 +249,6 @@ extern int (*console_blank_hook)(int);
 #define	APM_MINOR_DEV	134
 
 /*
- * See Documentation/Config.help for the configuration options.
- *
  * Various options can be changed at boot time as follows:
  * (We allow underscores for compatibility with the modules code)
  *	apm=on/off			enable/disable APM
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/amd.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/amd.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,7 @@
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/elf.h>
 #include <linux/mm.h>
 
 #include <linux/io.h>
@@ -410,6 +412,34 @@ static void __cpuinit early_init_amd_mc(
 #endif
 }
 
+static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
+{
+	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+		if (c->x86 > 0x10 ||
+		    (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+			u64 val;
+
+			rdmsrl(MSR_K7_HWCR, val);
+			if (!(val & BIT(24)))
+				printk(KERN_WARNING FW_BUG "TSC doesn't count "
+					"with P0 frequency!\n");
+		}
+	}
+
+	if (c->x86 == 0x15) {
+		unsigned long upperbit;
+		u32 cpuid, assoc;
+
+		cpuid	 = cpuid_edx(0x80000005);
+		assoc	 = cpuid >> 16 & 0xff;
+		upperbit = ((cpuid >> 24) << 10) / assoc;
+
+		va_align.mask	  = (upperbit - 1) & PAGE_MASK;
+		va_align.flags    = ALIGN_VA_32 | ALIGN_VA_64;
+	}
+}
+
 static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
 {
 	early_init_amd_mc(c);
@@ -441,27 +471,12 @@ static void __cpuinit early_init_amd(str
 			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
 	}
 #endif
-
-	/* We need to do the following only once */
-	if (c != &boot_cpu_data)
-		return;
-
-	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
-
-		if (c->x86 > 0x10 ||
-		    (c->x86 == 0x10 && c->x86_model >= 0x2)) {
-			u64 val;
-
-			rdmsrl(MSR_K7_HWCR, val);
-			if (!(val & BIT(24)))
-				printk(KERN_WARNING FW_BUG "TSC doesn't count "
-					"with P0 frequency!\n");
-		}
-	}
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
+	u32 dummy;
+
 #ifdef CONFIG_SMP
 	unsigned long long value;
 
@@ -640,6 +655,8 @@ static void __cpuinit init_amd(struct cp
 			checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
 		}
 	}
+
+	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
 }
 
 #ifdef CONFIG_X86_32
@@ -679,6 +696,7 @@ static const struct cpu_dev __cpuinitcon
 	.c_size_cache	= amd_size_cache,
 #endif
 	.c_early_init   = early_init_amd,
+	.c_bsp_init	= bsp_init_amd,
 	.c_init		= init_amd,
 	.c_x86_vendor	= X86_VENDOR_AMD,
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/common.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/common.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <asm/stackprotector.h>
 #include <asm/perf_event.h>
 #include <asm/mmu_context.h>
+#include <asm/archrandom.h>
 #include <asm/hypervisor.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -681,6 +682,9 @@ static void __init early_identify_cpu(st
 	filter_cpuid_features(c, false);
 
 	setup_smep(c);
+
+	if (this_cpu->c_bsp_init)
+		this_cpu->c_bsp_init(c);
 }
 
 void __init early_cpu_init(void)
@@ -857,6 +861,7 @@ static void __cpuinit identify_cpu(struc
 #endif
 
 	init_hypervisor(c);
+	x86_init_rdrand(c);
 
 	/*
 	 * Clear/Set all flags overriden by options, need do it
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/cpu.h linux-libre-3.2-gnu1/arch/x86/kernel/cpu/cpu.h
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@ struct cpu_dev {
 	struct		cpu_model_info c_models[4];
 
 	void            (*c_early_init)(struct cpuinfo_x86 *);
+	void		(*c_bsp_init)(struct cpuinfo_x86 *);
 	void		(*c_init)(struct cpuinfo_x86 *);
 	void		(*c_identify)(struct cpuinfo_x86 *);
 	unsigned int	(*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/intel.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/intel.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,15 @@ static void __cpuinit early_init_intel(s
 		(c->x86 == 0x6 && c->x86_model >= 0x0e))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
+	if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
+		unsigned lower_word;
+
+		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+		/* Required by the SDM */
+		sync_core();
+		rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
+	}
+
 	/*
 	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
 	 *
@@ -55,17 +64,10 @@ static void __cpuinit early_init_intel(s
 	 * need the microcode to have already been loaded... so if it is
 	 * not, recommend a BIOS update and disable large pages.
 	 */
-	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) {
-		u32 ucode, junk;
-
-		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-		sync_core();
-		rdmsr(MSR_IA32_UCODE_REV, junk, ucode);
-
-		if (ucode < 0x20e) {
-			printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
-			clear_cpu_cap(c, X86_FEATURE_PSE);
-		}
+	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
+	    c->microcode < 0x20e) {
+		printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
+		clear_cpu_cap(c, X86_FEATURE_PSE);
 	}
 
 #ifdef CONFIG_X86_64
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,28 +151,17 @@ union _cpuid4_leaf_ecx {
 	u32 full;
 };
 
-struct amd_l3_cache {
-	struct	 amd_northbridge *nb;
-	unsigned indices;
-	u8	 subcaches[4];
-};
-
-struct _cpuid4_info {
+struct _cpuid4_info_regs {
 	union _cpuid4_leaf_eax eax;
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	struct amd_l3_cache *l3;
-	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
+	struct amd_northbridge *nb;
 };
 
-/* subset of above _cpuid4_info w/o shared_cpu_map */
-struct _cpuid4_info_regs {
-	union _cpuid4_leaf_eax eax;
-	union _cpuid4_leaf_ebx ebx;
-	union _cpuid4_leaf_ecx ecx;
-	unsigned long size;
-	struct amd_l3_cache *l3;
+struct _cpuid4_info {
+	struct _cpuid4_info_regs base;
+	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
 };
 
 unsigned short			num_cache_leaves;
@@ -314,16 +303,23 @@ struct _cache_attr {
 /*
  * L3 cache descriptors
  */
-static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
+static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb)
 {
+	struct amd_l3_cache *l3 = &nb->l3_cache;
 	unsigned int sc0, sc1, sc2, sc3;
 	u32 val = 0;
 
-	pci_read_config_dword(l3->nb->misc, 0x1C4, &val);
+	pci_read_config_dword(nb->misc, 0x1C4, &val);
 
 	/* calculate subcache sizes */
 	l3->subcaches[0] = sc0 = !(val & BIT(0));
 	l3->subcaches[1] = sc1 = !(val & BIT(4));
+
+	if (boot_cpu_data.x86 == 0x15) {
+		l3->subcaches[0] = sc0 += !(val & BIT(1));
+		l3->subcaches[1] = sc1 += !(val & BIT(5));
+	}
+
 	l3->subcaches[2] = sc2 = !(val & BIT(8))  + !(val & BIT(9));
 	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
@@ -333,33 +329,16 @@ static void __cpuinit amd_calc_l3_indice
 static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
 					int index)
 {
-	static struct amd_l3_cache *__cpuinitdata l3_caches;
 	int node;
 
 	/* only for L3, and not in virtualized environments */
-	if (index < 3 || amd_nb_num() == 0)
+	if (index < 3)
 		return;
 
-	/*
-	 * Strictly speaking, the amount in @size below is leaked since it is
-	 * never freed but this is done only on shutdown so it doesn't matter.
-	 */
-	if (!l3_caches) {
-		int size = amd_nb_num() * sizeof(struct amd_l3_cache);
-
-		l3_caches = kzalloc(size, GFP_ATOMIC);
-		if (!l3_caches)
-			return;
-	}
-
 	node = amd_get_nb_id(smp_processor_id());
-
-	if (!l3_caches[node].nb) {
-		l3_caches[node].nb = node_to_amd_nb(node);
-		amd_calc_l3_indices(&l3_caches[node]);
-	}
-
-	this_leaf->l3 = &l3_caches[node];
+	this_leaf->nb = node_to_amd_nb(node);
+	if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
+		amd_calc_l3_indices(this_leaf->nb);
 }
 
 /*
@@ -369,11 +348,11 @@ static void __cpuinit amd_init_l3_cache(
  *
  * @returns: the disabled index if used or negative value if slot free.
  */
-int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot)
+int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
 {
 	unsigned int reg = 0;
 
-	pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg);
+	pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
 
 	/* check whether this slot is activated already */
 	if (reg & (3UL << 30))
@@ -387,11 +366,10 @@ static ssize_t show_cache_disable(struct
 {
 	int index;
 
-	if (!this_leaf->l3 ||
-	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
-	index = amd_get_l3_disable_slot(this_leaf->l3, slot);
+	index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
 	if (index >= 0)
 		return sprintf(buf, "%d\n", index);
 
@@ -408,7 +386,7 @@ show_cache_disable_##slot(struct _cpuid4
 SHOW_CACHE_DISABLE(0)
 SHOW_CACHE_DISABLE(1)
 
-static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
 				 unsigned slot, unsigned long idx)
 {
 	int i;
@@ -421,10 +399,10 @@ static void amd_l3_disable_index(struct
 	for (i = 0; i < 4; i++) {
 		u32 reg = idx | (i << 20);
 
-		if (!l3->subcaches[i])
+		if (!nb->l3_cache.subcaches[i])
 			continue;
 
-		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
 
 		/*
 		 * We need to WBINVD on a core on the node containing the L3
@@ -434,7 +412,7 @@ static void amd_l3_disable_index(struct
 		wbinvd_on_cpu(cpu);
 
 		reg |= BIT(31);
-		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
 	}
 }
 
@@ -448,24 +426,24 @@ static void amd_l3_disable_index(struct
  *
  * @return: 0 on success, error status on failure
  */
-int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
+int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
 			    unsigned long index)
 {
 	int ret = 0;
 
 	/*  check if @slot is already used or the index is already disabled */
-	ret = amd_get_l3_disable_slot(l3, slot);
+	ret = amd_get_l3_disable_slot(nb, slot);
 	if (ret >= 0)
 		return -EINVAL;
 
-	if (index > l3->indices)
+	if (index > nb->l3_cache.indices)
 		return -EINVAL;
 
 	/* check whether the other slot has disabled the same index already */
-	if (index == amd_get_l3_disable_slot(l3, !slot))
+	if (index == amd_get_l3_disable_slot(nb, !slot))
 		return -EINVAL;
 
-	amd_l3_disable_index(l3, cpu, slot, index);
+	amd_l3_disable_index(nb, cpu, slot, index);
 
 	return 0;
 }
@@ -480,8 +458,7 @@ static ssize_t store_cache_disable(struc
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!this_leaf->l3 ||
-	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
 	cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -489,7 +466,7 @@ static ssize_t store_cache_disable(struc
 	if (strict_strtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 
-	err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val);
+	err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
 	if (err) {
 		if (err == -EEXIST)
 			printk(KERN_WARNING "L3 disable slot %d in use!\n",
@@ -518,7 +495,7 @@ static struct _cache_attr cache_disable_
 static ssize_t
 show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
 {
-	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
 		return -EINVAL;
 
 	return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
@@ -533,7 +510,7 @@ store_subcaches(struct _cpuid4_info *thi
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
 		return -EINVAL;
 
 	if (strict_strtoul(buf, 16, &val) < 0)
@@ -769,7 +746,7 @@ static void __cpuinit cache_shared_cpu_m
 		return;
 	}
 	this_leaf = CPUID4_INFO_IDX(cpu, index);
-	num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+	num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing;
 
 	if (num_threads_sharing == 1)
 		cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
@@ -820,29 +797,19 @@ static void __cpuinit free_cache_attribu
 	for (i = 0; i < num_cache_leaves; i++)
 		cache_remove_shared_cpu_map(cpu, i);
 
-	kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
 	kfree(per_cpu(ici_cpuid4_info, cpu));
 	per_cpu(ici_cpuid4_info, cpu) = NULL;
 }
 
-static int
-__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
-{
-	struct _cpuid4_info_regs *leaf_regs =
-		(struct _cpuid4_info_regs *)this_leaf;
-
-	return cpuid4_cache_lookup_regs(index, leaf_regs);
-}
-
 static void __cpuinit get_cpu_leaves(void *_retval)
 {
 	int j, *retval = _retval, cpu = smp_processor_id();
 
 	/* Do cpuid and store the results */
 	for (j = 0; j < num_cache_leaves; j++) {
-		struct _cpuid4_info *this_leaf;
-		this_leaf = CPUID4_INFO_IDX(cpu, j);
-		*retval = cpuid4_cache_lookup(j, this_leaf);
+		struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j);
+
+		*retval = cpuid4_cache_lookup_regs(j, &this_leaf->base);
 		if (unlikely(*retval < 0)) {
 			int i;
 
@@ -900,16 +867,16 @@ static ssize_t show_##file_name(struct _
 	return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
 }
 
-show_one_plus(level, eax.split.level, 0);
-show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
-show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
-show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
-show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+show_one_plus(level, base.eax.split.level, 0);
+show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1);
 
 static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
 			 unsigned int cpu)
 {
-	return sprintf(buf, "%luK\n", this_leaf->size / 1024);
+	return sprintf(buf, "%luK\n", this_leaf->base.size / 1024);
 }
 
 static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
@@ -946,7 +913,7 @@ static inline ssize_t show_shared_cpu_li
 static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
 			 unsigned int cpu)
 {
-	switch (this_leaf->eax.split.type) {
+	switch (this_leaf->base.eax.split.type) {
 	case CACHE_TYPE_DATA:
 		return sprintf(buf, "Data\n");
 	case CACHE_TYPE_INST:
@@ -1135,7 +1102,7 @@ static int __cpuinit cache_add_dev(struc
 
 		ktype_cache.default_attrs = default_attrs;
 #ifdef CONFIG_AMD_NB
-		if (this_leaf->l3)
+		if (this_leaf->base.nb)
 			ktype_cache.default_attrs = amd_l3_attrs();
 #endif
 		retval = kobject_init_and_add(&(this_object->kobj),
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/Makefile linux-libre-3.2-gnu1/arch/x86/kernel/cpu/Makefile
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@ CFLAGS_common.o		:= $(nostackp)
 obj-y			:= intel_cacheinfo.o scattered.o topology.o
 obj-y			+= proc.o capflags.o powerflags.o common.o
 obj-y			+= vmware.o hypervisor.o sched.o mshyperv.o
+obj-y			+= rdrand.o
 
 obj-$(CONFIG_X86_32)	+= bugs.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
@@ -28,10 +29,15 @@ obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
 obj-$(CONFIG_PERF_EVENTS)		+= perf_event.o
 
+ifdef CONFIG_PERF_EVENTS
+obj-$(CONFIG_CPU_SUP_AMD)		+= perf_event_amd.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+endif
+
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
 
-obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
+obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o perf_event_amd_ibs.o
 
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce-apei.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce-apei.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce-apei.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce-apei.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/cper.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,8 +36,8 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/debugfs.h>
-#include <linux/edac_mce.h>
 #include <linux/irq_work.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/mce.h>
@@ -144,23 +144,20 @@ static struct mce_log mcelog = {
 void mce_log(struct mce *mce)
 {
 	unsigned next, entry;
+	int ret = 0;
 
 	/* Emit the trace record: */
 	trace_mce_record(mce);
 
+	ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
+	if (ret == NOTIFY_STOP)
+		return;
+
 	mce->finished = 0;
 	wmb();
 	for (;;) {
 		entry = rcu_dereference_check_mce(mcelog.next);
 		for (;;) {
-			/*
-			 * If edac_mce is enabled, it will check the error type
-			 * and will process it, if it is a known error.
-			 * Otherwise, the error will be sent through mcelog
-			 * interface
-			 */
-			if (edac_mce_parse(mce))
-				return;
 
 			/*
 			 * When the buffer fills up discard new entries.
@@ -217,8 +214,13 @@ static void print_mce(struct mce *m)
 		pr_cont("MISC %llx ", m->misc);
 
 	pr_cont("\n");
-	pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
-		m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
+	/*
+	 * Note this output is parsed by external tools and old fields
+	 * should not be changed.
+	 */
+	pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
+		m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
+		cpu_data(m->extcpu).microcode);
 
 	/*
 	 * Print out human-readable details about the MCE error,
@@ -551,10 +553,8 @@ void machine_check_poll(enum mcp_flags f
 		 * Don't get the IP here because it's unlikely to
 		 * have anything to do with the actual error location.
 		 */
-		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
+		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
 			mce_log(&m);
-			atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
-		}
 
 		/*
 		 * Clear state for this bank.
@@ -908,9 +908,6 @@ void do_machine_check(struct pt_regs *re
 
 	percpu_inc(mce_exception_count);
 
-	if (notify_die(DIE_NMI, "machine check", regs, error_code,
-			   18, SIGKILL) == NOTIFY_STOP)
-		goto out;
 	if (!banks)
 		goto out;
 
@@ -1140,6 +1137,15 @@ static void mce_start_timer(unsigned lon
 	add_timer_on(t, smp_processor_id());
 }
 
+/* Must not be called in IRQ context where del_timer_sync() can deadlock */
+static void mce_timer_delete_all(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		del_timer_sync(&per_cpu(mce_timer, cpu));
+}
+
 static void mce_do_trigger(struct work_struct *work)
 {
 	call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
@@ -1628,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file
 	}
 }
 
-/* Modified in mce-inject.c, so not static or const */
-struct file_operations mce_chrdev_ops = {
+static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
+			    size_t usize, loff_t *off);
+
+void register_mce_write_callback(ssize_t (*fn)(struct file *filp,
+			     const char __user *ubuf,
+			     size_t usize, loff_t *off))
+{
+	mce_write = fn;
+}
+EXPORT_SYMBOL_GPL(register_mce_write_callback);
+
+ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
+			 size_t usize, loff_t *off)
+{
+	if (mce_write)
+		return mce_write(filp, ubuf, usize, off);
+	else
+		return -EINVAL;
+}
+
+static const struct file_operations mce_chrdev_ops = {
 	.open			= mce_chrdev_open,
 	.release		= mce_chrdev_release,
 	.read			= mce_chrdev_read,
+	.write			= mce_chrdev_write,
 	.poll			= mce_chrdev_poll,
 	.unlocked_ioctl		= mce_chrdev_ioctl,
 	.llseek			= no_llseek,
 };
-EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
 static struct miscdevice mce_chrdev_device = {
 	MISC_MCELOG_MINOR,
@@ -1750,7 +1775,6 @@ static struct syscore_ops mce_syscore_op
 
 static void mce_cpu_restart(void *data)
 {
-	del_timer_sync(&__get_cpu_var(mce_timer));
 	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 	__mcheck_cpu_init_generic();
@@ -1760,16 +1784,15 @@ static void mce_cpu_restart(void *data)
 /* Reinit MCEs after user configuration changes */
 static void mce_restart(void)
 {
+	mce_timer_delete_all();
 	on_each_cpu(mce_cpu_restart, NULL, 1);
 }
 
 /* Toggle features for corrected errors */
-static void mce_disable_ce(void *all)
+static void mce_disable_cmci(void *data)
 {
 	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
-	if (all)
-		del_timer_sync(&__get_cpu_var(mce_timer));
 	cmci_clear();
 }
 
@@ -1852,7 +1875,8 @@ static ssize_t set_ignore_ce(struct sys_
 	if (mce_ignore_ce ^ !!new) {
 		if (new) {
 			/* disable ce features */
-			on_each_cpu(mce_disable_ce, (void *)1, 1);
+			mce_timer_delete_all();
+			on_each_cpu(mce_disable_cmci, NULL, 1);
 			mce_ignore_ce = 1;
 		} else {
 			/* enable ce features */
@@ -1875,7 +1899,7 @@ static ssize_t set_cmci_disabled(struct
 	if (mce_cmci_disabled ^ !!new) {
 		if (new) {
 			/* disable cmci */
-			on_each_cpu(mce_disable_ce, NULL, 1);
+			on_each_cpu(mce_disable_cmci, NULL, 1);
 			mce_cmci_disabled = 1;
 		} else {
 			/* enable cmci */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,27 +78,20 @@ static void raise_exception(struct mce *
 
 static cpumask_var_t mce_inject_cpumask;
 
-static int mce_raise_notify(struct notifier_block *self,
-			    unsigned long val, void *data)
+static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
 	int cpu = smp_processor_id();
 	struct mce *m = &__get_cpu_var(injectm);
-	if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
-		return NOTIFY_DONE;
+	if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
+		return NMI_DONE;
 	cpumask_clear_cpu(cpu, mce_inject_cpumask);
 	if (m->inject_flags & MCJ_EXCEPTION)
-		raise_exception(m, args->regs);
+		raise_exception(m, regs);
 	else if (m->status)
 		raise_poll(m);
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
 
-static struct notifier_block mce_raise_nb = {
-	.notifier_call = mce_raise_notify,
-	.priority = NMI_LOCAL_NORMAL_PRIOR,
-};
-
 /* Inject mce on current CPU */
 static int raise_local(void)
 {
@@ -215,8 +208,9 @@ static int inject_init(void)
 	if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
 		return -ENOMEM;
 	printk(KERN_INFO "Machine check injector initialized\n");
-	mce_chrdev_ops.write = mce_write;
-	register_die_notifier(&mce_raise_nb);
+	register_mce_write_callback(mce_write);
+	register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
+				"mce_notify");
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_b
  * cmci_discover_lock protects against parallel discovery attempts
  * which could race against each other.
  */
-static DEFINE_SPINLOCK(cmci_discover_lock);
+static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
 
 #define CMCI_THRESHOLD 1
 
@@ -85,7 +85,7 @@ static void cmci_discover(int banks, int
 	int hdr = 0;
 	int i;
 
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++) {
 		u64 val;
 
@@ -116,7 +116,7 @@ static void cmci_discover(int banks, int
 			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
 		}
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 	if (hdr)
 		printk(KERN_CONT "\n");
 }
@@ -150,7 +150,7 @@ void cmci_clear(void)
 
 	if (!cmci_supported(&banks))
 		return;
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++) {
 		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
 			continue;
@@ -160,7 +160,7 @@ void cmci_clear(void)
 		wrmsrl(MSR_IA32_MCx_CTL2(i), val);
 		__clear_bit(i, __get_cpu_var(mce_banks_owned));
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/export.h>
 #include <linux/sysdev.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mshyperv.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mshyperv.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mshyperv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mshyperv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@
  */
 
 #include <linux/types.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
 #include <linux/module.h>
 #include <asm/processor.h>
 #include <asm/hypervisor.h>
@@ -36,6 +38,25 @@ static bool __init ms_hyperv_platform(vo
 		!memcmp("Microsoft Hv", hyp_signature, 12);
 }
 
+static cycle_t read_hv_clock(struct clocksource *arg)
+{
+	cycle_t current_tick;
+	/*
+	 * Read the partition counter to get the current tick count. This count
+	 * is set to 0 when the partition is created and is incremented in
+	 * 100 nanosecond units.
+	 */
+	rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+	return current_tick;
+}
+
+static struct clocksource hyperv_cs = {
+	.name		= "hyperv_clocksource",
+	.rating		= 400, /* use this when running on Hyperv*/
+	.read		= read_hv_clock,
+	.mask		= CLOCKSOURCE_MASK(64),
+};
+
 static void __init ms_hyperv_init_platform(void)
 {
 	/*
@@ -46,6 +67,8 @@ static void __init ms_hyperv_init_platfo
 
 	printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
 	       ms_hyperv.features, ms_hyperv.hints);
+
+	clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mtrr/generic.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mtrr/generic.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/mtrr/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/mtrr/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -547,6 +547,7 @@ static void generic_get_mtrr(unsigned in
 
 		if (tmp != mask_lo) {
 			printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
+			add_taint(TAINT_FIRMWARE_WORKAROUND);
 			mask_lo = tmp;
 		}
 	}
@@ -693,6 +694,7 @@ static void prepare_set(void) __acquires
 
 	/* Disable MTRRs, and set the default type to uncached */
 	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
+	wbinvd();
 }
 
 static void post_set(void) __releases(set_atomicity_lock)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_amd.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_amd.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_AMD
+#include <linux/perf_event.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/apicdef.h>
+
+#include "perf_event.h"
 
 static __initconst const u64 amd_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
@@ -132,6 +138,19 @@ static int amd_pmu_hw_config(struct perf
 	if (ret)
 		return ret;
 
+	if (event->attr.exclude_host && event->attr.exclude_guest)
+		/*
+		 * When HO == GO == 1 the hardware treats that as GO == HO == 0
+		 * and will count in both modes. We don't want to count in that
+		 * case so we emulate no-counting by setting US = OS = 0.
+		 */
+		event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
+				      ARCH_PERFMON_EVENTSEL_OS);
+	else if (event->attr.exclude_host)
+		event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY;
+	else if (event->attr.exclude_guest)
+		event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY;
+
 	if (event->attr.type != PERF_TYPE_RAW)
 		return 0;
 
@@ -350,7 +369,7 @@ static void amd_pmu_cpu_starting(int cpu
 			continue;
 
 		if (nb->nb_id == nb_id) {
-			kfree(cpuc->amd_nb);
+			cpuc->kfree_on_online = cpuc->amd_nb;
 			cpuc->amd_nb = nb;
 			break;
 		}
@@ -392,7 +411,7 @@ static __initconst const struct x86_pmu
 	.perfctr		= MSR_K7_PERFCTR0,
 	.event_map		= amd_pmu_event_map,
 	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
-	.num_counters		= 4,
+	.num_counters		= AMD64_NUM_COUNTERS,
 	.cntval_bits		= 48,
 	.cntval_mask		= (1ULL << 48) - 1,
 	.apic			= 1,
@@ -556,7 +575,7 @@ static __initconst const struct x86_pmu
 	.perfctr		= MSR_F15H_PERF_CTR,
 	.event_map		= amd_pmu_event_map,
 	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
-	.num_counters		= 6,
+	.num_counters		= AMD64_NUM_COUNTERS_F15H,
 	.cntval_bits		= 48,
 	.cntval_mask		= (1ULL << 48) - 1,
 	.apic			= 1,
@@ -573,7 +592,7 @@ static __initconst const struct x86_pmu
 #endif
 };
 
-static __init int amd_pmu_init(void)
+__init int amd_pmu_init(void)
 {
 	/* Performance-monitoring supported from K7 and later: */
 	if (boot_cpu_data.x86 < 6)
@@ -602,12 +621,3 @@ static __init int amd_pmu_init(void)
 
 	return 0;
 }
-
-#else /* CONFIG_CPU_SUP_AMD */
-
-static int amd_pmu_init(void)
-{
-	return 0;
-}
-
-#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_amd_ibs.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_amd_ibs.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_amd_ibs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_amd_ibs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Performance events - AMD IBS
+ *
+ *  Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/apic.h>
+
+static u32 ibs_caps;
+
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
+
+static struct pmu perf_ibs;
+
+static int perf_ibs_init(struct perf_event *event)
+{
+	if (perf_ibs.type != event->attr.type)
+		return -ENOENT;
+	return 0;
+}
+
+static int perf_ibs_add(struct perf_event *event, int flags)
+{
+	return 0;
+}
+
+static void perf_ibs_del(struct perf_event *event, int flags)
+{
+}
+
+static struct pmu perf_ibs = {
+	.event_init= perf_ibs_init,
+	.add= perf_ibs_add,
+	.del= perf_ibs_del,
+};
+
+static __init int perf_event_ibs_init(void)
+{
+	if (!ibs_caps)
+		return -ENODEV;	/* ibs not supported by the cpu */
+
+	perf_pmu_register(&perf_ibs, "ibs", -1);
+	printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
+
+	return 0;
+}
+
+#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
+
+static __init int perf_event_ibs_init(void) { return 0; }
+
+#endif
+
+/* IBS - apic initialization, for perf and oprofile */
+
+static __init u32 __get_ibs_caps(void)
+{
+	u32 caps;
+	unsigned int max_level;
+
+	if (!boot_cpu_has(X86_FEATURE_IBS))
+		return 0;
+
+	/* check IBS cpuid feature flags */
+	max_level = cpuid_eax(0x80000000);
+	if (max_level < IBS_CPUID_FEATURES)
+		return IBS_CAPS_DEFAULT;
+
+	caps = cpuid_eax(IBS_CPUID_FEATURES);
+	if (!(caps & IBS_CAPS_AVAIL))
+		/* cpuid flags not valid */
+		return IBS_CAPS_DEFAULT;
+
+	return caps;
+}
+
+u32 get_ibs_caps(void)
+{
+	return ibs_caps;
+}
+
+EXPORT_SYMBOL(get_ibs_caps);
+
+static inline int get_eilvt(int offset)
+{
+	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int put_eilvt(int offset)
+{
+	return !setup_APIC_eilvt(offset, 0, 0, 1);
+}
+
+/*
+ * Check and reserve APIC extended interrupt LVT offset for IBS if available.
+ */
+static inline int ibs_eilvt_valid(void)
+{
+	int offset;
+	u64 val;
+	int valid = 0;
+
+	preempt_disable();
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+		pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
+		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+		goto out;
+	}
+
+	if (!get_eilvt(offset)) {
+		pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
+		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+		goto out;
+	}
+
+	valid = 1;
+out:
+	preempt_enable();
+
+	return valid;
+}
+
+static int setup_ibs_ctl(int ibs_eilvt_off)
+{
+	struct pci_dev *cpu_cfg;
+	int nodes;
+	u32 value = 0;
+
+	nodes = 0;
+	cpu_cfg = NULL;
+	do {
+		cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
+					 PCI_DEVICE_ID_AMD_10H_NB_MISC,
+					 cpu_cfg);
+		if (!cpu_cfg)
+			break;
+		++nodes;
+		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+				       | IBSCTL_LVT_OFFSET_VALID);
+		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
+		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
+			pci_dev_put(cpu_cfg);
+			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
+			       "IBSCTL = 0x%08x\n", value);
+			return -EINVAL;
+		}
+	} while (1);
+
+	if (!nodes) {
+		printk(KERN_DEBUG "No CPU node configured for IBS\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * This runs only on the current cpu. We try to find an LVT offset and
+ * setup the local APIC. For this we must disable preemption. On
+ * success we initialize all nodes with this offset. This updates then
+ * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
+ * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
+ * is using the new offset.
+ */
+static int force_ibs_eilvt_setup(void)
+{
+	int offset;
+	int ret;
+
+	preempt_disable();
+	/* find the next free available EILVT entry, skip offset 0 */
+	for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
+		if (get_eilvt(offset))
+			break;
+	}
+	preempt_enable();
+
+	if (offset == APIC_EILVT_NR_MAX) {
+		printk(KERN_DEBUG "No EILVT entry available\n");
+		return -EBUSY;
+	}
+
+	ret = setup_ibs_ctl(offset);
+	if (ret)
+		goto out;
+
+	if (!ibs_eilvt_valid()) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	pr_info("IBS: LVT offset %d assigned\n", offset);
+
+	return 0;
+out:
+	preempt_disable();
+	put_eilvt(offset);
+	preempt_enable();
+	return ret;
+}
+
+static inline int get_ibs_lvt_offset(void)
+{
+	u64 val;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID))
+		return -EINVAL;
+
+	return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void *dummy)
+{
+	int offset;
+
+	offset = get_ibs_lvt_offset();
+	if (offset < 0)
+		goto failed;
+
+	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+		return;
+failed:
+	pr_warn("perf: IBS APIC setup failed on cpu #%d\n",
+		smp_processor_id());
+}
+
+static void clear_APIC_ibs(void *dummy)
+{
+	int offset;
+
+	offset = get_ibs_lvt_offset();
+	if (offset >= 0)
+		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
+static int __cpuinit
+perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		setup_APIC_ibs(NULL);
+		break;
+	case CPU_DYING:
+		clear_APIC_ibs(NULL);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static __init int amd_ibs_init(void)
+{
+	u32 caps;
+	int ret = -EINVAL;
+
+	caps = __get_ibs_caps();
+	if (!caps)
+		return -ENODEV;	/* ibs not supported by the cpu */
+
+	/*
+	 * Force LVT offset assignment for family 10h: The offsets are
+	 * not assigned by the BIOS for this family, so the OS is
+	 * responsible for doing it. If the OS assignment fails, fall
+	 * back to BIOS settings and try to setup this.
+	 */
+	if (boot_cpu_data.x86 == 0x10)
+		force_ibs_eilvt_setup();
+
+	if (!ibs_eilvt_valid())
+		goto out;
+
+	get_online_cpus();
+	ibs_caps = caps;
+	/* make ibs_caps visible to other cpus: */
+	smp_mb();
+	perf_cpu_notifier(perf_ibs_cpu_notifier);
+	smp_call_function(setup_APIC_ibs, NULL, 1);
+	put_online_cpus();
+
+	ret = perf_event_ibs_init();
+out:
+	if (ret)
+		pr_err("Failed to setup IBS, %d\n", ret);
+	return ret;
+}
+
+/* Since we need the pci subsystem to init ibs we can't do this earlier: */
+device_initcall(amd_ibs_init);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@
 #include <asm/smp.h>
 #include <asm/alternative.h>
 
+#include "perf_event.h"
+
 #if 0
 #undef wrmsrl
 #define wrmsrl(msr, val) 					\
@@ -43,283 +45,17 @@ do {								\
 } while (0)
 #endif
 
-/*
- *          |   NHM/WSM    |      SNB     |
- * register -------------------------------
- *          |  HT  | no HT |  HT  | no HT |
- *-----------------------------------------
- * offcore  | core | core  | cpu  | core  |
- * lbr_sel  | core | core  | cpu  | core  |
- * ld_lat   | cpu  | core  | cpu  | core  |
- *-----------------------------------------
- *
- * Given that there is a small number of shared regs,
- * we can pre-allocate their slot in the per-cpu
- * per-core reg tables.
- */
-enum extra_reg_type {
-	EXTRA_REG_NONE  = -1,	/* not used */
-
-	EXTRA_REG_RSP_0 = 0,	/* offcore_response_0 */
-	EXTRA_REG_RSP_1 = 1,	/* offcore_response_1 */
-
-	EXTRA_REG_MAX		/* number of entries needed */
-};
-
-struct event_constraint {
-	union {
-		unsigned long	idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-		u64		idxmsk64;
-	};
-	u64	code;
-	u64	cmask;
-	int	weight;
-};
-
-struct amd_nb {
-	int nb_id;  /* NorthBridge id */
-	int refcnt; /* reference count */
-	struct perf_event *owners[X86_PMC_IDX_MAX];
-	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
-};
-
-struct intel_percore;
-
-#define MAX_LBR_ENTRIES		16
-
-struct cpu_hw_events {
-	/*
-	 * Generic x86 PMC bits
-	 */
-	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
-	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-	int			enabled;
-
-	int			n_events;
-	int			n_added;
-	int			n_txn;
-	int			assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
-	u64			tags[X86_PMC_IDX_MAX];
-	struct perf_event	*event_list[X86_PMC_IDX_MAX]; /* in enabled order */
-
-	unsigned int		group_flag;
-
-	/*
-	 * Intel DebugStore bits
-	 */
-	struct debug_store	*ds;
-	u64			pebs_enabled;
-
-	/*
-	 * Intel LBR bits
-	 */
-	int				lbr_users;
-	void				*lbr_context;
-	struct perf_branch_stack	lbr_stack;
-	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
-
-	/*
-	 * manage shared (per-core, per-cpu) registers
-	 * used on Intel NHM/WSM/SNB
-	 */
-	struct intel_shared_regs	*shared_regs;
-
-	/*
-	 * AMD specific bits
-	 */
-	struct amd_nb		*amd_nb;
-};
-
-#define __EVENT_CONSTRAINT(c, n, m, w) {\
-	{ .idxmsk64 = (n) },		\
-	.code = (c),			\
-	.cmask = (m),			\
-	.weight = (w),			\
-}
-
-#define EVENT_CONSTRAINT(c, n, m)	\
-	__EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
-
-/*
- * Constraint on the Event code.
- */
-#define INTEL_EVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
-
-/*
- * Constraint on the Event code + UMask + fixed-mask
- *
- * filter mask to validate fixed counter events.
- * the following filters disqualify for fixed counters:
- *  - inv
- *  - edge
- *  - cnt-mask
- *  The other filters are supported by fixed counters.
- *  The any-thread option is supported starting with v3.
- */
-#define FIXED_EVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
-
-/*
- * Constraint on the Event code + UMask
- */
-#define INTEL_UEVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
-
-#define EVENT_CONSTRAINT_END		\
-	EVENT_CONSTRAINT(0, 0, 0)
-
-#define for_each_event_constraint(e, c)	\
-	for ((e) = (c); (e)->weight; (e)++)
-
-/*
- * Per register state.
- */
-struct er_account {
-	raw_spinlock_t		lock;	/* per-core: protect structure */
-	u64			config;	/* extra MSR config */
-	u64			reg;	/* extra MSR number */
-	atomic_t		ref;	/* reference count */
-};
-
-/*
- * Extra registers for specific events.
- *
- * Some events need large masks and require external MSRs.
- * Those extra MSRs end up being shared for all events on
- * a PMU and sometimes between PMU of sibling HT threads.
- * In either case, the kernel needs to handle conflicting
- * accesses to those extra, shared, regs. The data structure
- * to manage those registers is stored in cpu_hw_event.
- */
-struct extra_reg {
-	unsigned int		event;
-	unsigned int		msr;
-	u64			config_mask;
-	u64			valid_mask;
-	int			idx;  /* per_xxx->regs[] reg index */
-};
-
-#define EVENT_EXTRA_REG(e, ms, m, vm, i) {	\
-	.event = (e),		\
-	.msr = (ms),		\
-	.config_mask = (m),	\
-	.valid_mask = (vm),	\
-	.idx = EXTRA_REG_##i	\
-	}
-
-#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)	\
-	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
-
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
-
-union perf_capabilities {
-	struct {
-		u64	lbr_format    : 6;
-		u64	pebs_trap     : 1;
-		u64	pebs_arch_reg : 1;
-		u64	pebs_format   : 4;
-		u64	smm_freeze    : 1;
-	};
-	u64	capabilities;
-};
-
-/*
- * struct x86_pmu - generic x86 pmu
- */
-struct x86_pmu {
-	/*
-	 * Generic x86 PMC bits
-	 */
-	const char	*name;
-	int		version;
-	int		(*handle_irq)(struct pt_regs *);
-	void		(*disable_all)(void);
-	void		(*enable_all)(int added);
-	void		(*enable)(struct perf_event *);
-	void		(*disable)(struct perf_event *);
-	int		(*hw_config)(struct perf_event *event);
-	int		(*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
-	unsigned	eventsel;
-	unsigned	perfctr;
-	u64		(*event_map)(int);
-	int		max_events;
-	int		num_counters;
-	int		num_counters_fixed;
-	int		cntval_bits;
-	u64		cntval_mask;
-	int		apic;
-	u64		max_period;
-	struct event_constraint *
-			(*get_event_constraints)(struct cpu_hw_events *cpuc,
-						 struct perf_event *event);
-
-	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
-						 struct perf_event *event);
-	struct event_constraint *event_constraints;
-	void		(*quirks)(void);
-	int		perfctr_second_write;
-
-	int		(*cpu_prepare)(int cpu);
-	void		(*cpu_starting)(int cpu);
-	void		(*cpu_dying)(int cpu);
-	void		(*cpu_dead)(int cpu);
-
-	/*
-	 * Intel Arch Perfmon v2+
-	 */
-	u64			intel_ctrl;
-	union perf_capabilities intel_cap;
-
-	/*
-	 * Intel DebugStore bits
-	 */
-	int		bts, pebs;
-	int		bts_active, pebs_active;
-	int		pebs_record_size;
-	void		(*drain_pebs)(struct pt_regs *regs);
-	struct event_constraint *pebs_constraints;
-
-	/*
-	 * Intel LBR
-	 */
-	unsigned long	lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
-	int		lbr_nr;			   /* hardware stack size */
-
-	/*
-	 * Extra registers for events
-	 */
-	struct extra_reg *extra_regs;
-	unsigned int er_flags;
-};
-
-#define ERF_NO_HT_SHARING	1
-#define ERF_HAS_RSP_1		2
-
-static struct x86_pmu x86_pmu __read_mostly;
+struct x86_pmu x86_pmu __read_mostly;
 
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
 	.enabled = 1,
 };
 
-static int x86_perf_event_set_period(struct perf_event *event);
-
-/*
- * Generalized hw caching related hw_event table, filled
- * in on a per model basis. A value of 0 means
- * 'not supported', -1 means 'hw_event makes no sense on
- * this CPU', any other value means the raw hw_event
- * ID.
- */
-
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-static u64 __read_mostly hw_cache_event_ids
+u64 __read_mostly hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
-static u64 __read_mostly hw_cache_extra_regs
+u64 __read_mostly hw_cache_extra_regs
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
@@ -329,8 +65,7 @@ static u64 __read_mostly hw_cache_extra_
  * Can only be executed on the CPU where the event is active.
  * Returns the delta events processed.
  */
-static u64
-x86_perf_event_update(struct perf_event *event)
+u64 x86_perf_event_update(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	int shift = 64 - x86_pmu.cntval_bits;
@@ -373,30 +108,6 @@ again:
 	return new_raw_count;
 }
 
-static inline int x86_pmu_addr_offset(int index)
-{
-	int offset;
-
-	/* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
-	alternative_io(ASM_NOP2,
-		       "shll $1, %%eax",
-		       X86_FEATURE_PERFCTR_CORE,
-		       "=a" (offset),
-		       "a"  (index));
-
-	return offset;
-}
-
-static inline unsigned int x86_pmu_config_addr(int index)
-{
-	return x86_pmu.eventsel + x86_pmu_addr_offset(index);
-}
-
-static inline unsigned int x86_pmu_event_addr(int index)
-{
-	return x86_pmu.perfctr + x86_pmu_addr_offset(index);
-}
-
 /*
  * Find and validate any extra registers to set up.
  */
@@ -532,9 +243,6 @@ msr_fail:
 	return false;
 }
 
-static void reserve_ds_buffers(void);
-static void release_ds_buffers(void);
-
 static void hw_perf_event_destroy(struct perf_event *event)
 {
 	if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) {
@@ -583,7 +291,7 @@ set_ext_hw_attr(struct hw_perf_event *hw
 	return x86_pmu_extra_regs(val, event);
 }
 
-static int x86_setup_perfctr(struct perf_event *event)
+int x86_setup_perfctr(struct perf_event *event)
 {
 	struct perf_event_attr *attr = &event->attr;
 	struct hw_perf_event *hwc = &event->hw;
@@ -604,12 +312,8 @@ static int x86_setup_perfctr(struct perf
 			return -EOPNOTSUPP;
 	}
 
-	/*
-	 * Do not allow config1 (extended registers) to propagate,
-	 * there's no sane user-space generalization yet:
-	 */
 	if (attr->type == PERF_TYPE_RAW)
-		return 0;
+		return x86_pmu_extra_regs(event->attr.config, event);
 
 	if (attr->type == PERF_TYPE_HW_CACHE)
 		return set_ext_hw_attr(hwc, event);
@@ -647,7 +351,7 @@ static int x86_setup_perfctr(struct perf
 	return 0;
 }
 
-static int x86_pmu_hw_config(struct perf_event *event)
+int x86_pmu_hw_config(struct perf_event *event)
 {
 	if (event->attr.precise_ip) {
 		int precise = 0;
@@ -723,7 +427,7 @@ static int __x86_pmu_event_init(struct p
 	return x86_pmu.hw_config(event);
 }
 
-static void x86_pmu_disable_all(void)
+void x86_pmu_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
@@ -758,15 +462,7 @@ static void x86_pmu_disable(struct pmu *
 	x86_pmu.disable_all();
 }
 
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
-					  u64 enable_mask)
-{
-	if (hwc->extra_reg.reg)
-		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
-	wrmsrl(hwc->config_base, hwc->config | enable_mask);
-}
-
-static void x86_pmu_enable_all(int added)
+void x86_pmu_enable_all(int added)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
@@ -788,7 +484,7 @@ static inline int is_x86_event(struct pe
 	return event->pmu == &pmu;
 }
 
-static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
 {
 	struct event_constraint *c, *constraints[X86_PMC_IDX_MAX];
 	unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
@@ -888,7 +584,7 @@ done:
 				x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]);
 		}
 	}
-	return num ? -ENOSPC : 0;
+	return num ? -EINVAL : 0;
 }
 
 /*
@@ -907,7 +603,7 @@ static int collect_events(struct cpu_hw_
 
 	if (is_x86_event(leader)) {
 		if (n >= max_count)
-			return -ENOSPC;
+			return -EINVAL;
 		cpuc->event_list[n] = leader;
 		n++;
 	}
@@ -920,7 +616,7 @@ static int collect_events(struct cpu_hw_
 			continue;
 
 		if (n >= max_count)
-			return -ENOSPC;
+			return -EINVAL;
 
 		cpuc->event_list[n] = event;
 		n++;
@@ -959,7 +655,6 @@ static inline int match_prev_assignment(
 }
 
 static void x86_pmu_start(struct perf_event *event, int flags);
-static void x86_pmu_stop(struct perf_event *event, int flags);
 
 static void x86_pmu_enable(struct pmu *pmu)
 {
@@ -1031,21 +726,13 @@ static void x86_pmu_enable(struct pmu *p
 	x86_pmu.enable_all(added);
 }
 
-static inline void x86_pmu_disable_event(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	wrmsrl(hwc->config_base, hwc->config);
-}
-
 static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
 
 /*
  * Set the next IRQ period, based on the hwc->period_left value.
  * To be called with the event disabled in hw:
  */
-static int
-x86_perf_event_set_period(struct perf_event *event)
+int x86_perf_event_set_period(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	s64 left = local64_read(&hwc->period_left);
@@ -1105,7 +792,7 @@ x86_perf_event_set_period(struct perf_ev
 	return ret;
 }
 
-static void x86_pmu_enable_event(struct perf_event *event)
+void x86_pmu_enable_event(struct perf_event *event)
 {
 	if (__this_cpu_read(cpu_hw_events.enabled))
 		__x86_pmu_enable_event(&event->hw,
@@ -1244,7 +931,7 @@ void perf_event_print_debug(void)
 	local_irq_restore(flags);
 }
 
-static void x86_pmu_stop(struct perf_event *event, int flags)
+void x86_pmu_stop(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -1297,7 +984,7 @@ static void x86_pmu_del(struct perf_even
 	perf_event_update_userpage(event);
 }
 
-static int x86_pmu_handle_irq(struct pt_regs *regs)
+int x86_pmu_handle_irq(struct pt_regs *regs)
 {
 	struct perf_sample_data data;
 	struct cpu_hw_events *cpuc;
@@ -1367,109 +1054,28 @@ void perf_events_lapic_init(void)
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
-struct pmu_nmi_state {
-	unsigned int	marked;
-	int		handled;
-};
-
-static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi);
-
 static int __kprobes
-perf_event_nmi_handler(struct notifier_block *self,
-			 unsigned long cmd, void *__args)
+perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = __args;
-	unsigned int this_nmi;
-	int handled;
-
 	if (!atomic_read(&active_events))
-		return NOTIFY_DONE;
-
-	switch (cmd) {
-	case DIE_NMI:
-		break;
-	case DIE_NMIUNKNOWN:
-		this_nmi = percpu_read(irq_stat.__nmi_count);
-		if (this_nmi != __this_cpu_read(pmu_nmi.marked))
-			/* let the kernel handle the unknown nmi */
-			return NOTIFY_DONE;
-		/*
-		 * This one is a PMU back-to-back nmi. Two events
-		 * trigger 'simultaneously' raising two back-to-back
-		 * NMIs. If the first NMI handles both, the latter
-		 * will be empty and daze the CPU. So, we drop it to
-		 * avoid false-positive 'unknown nmi' messages.
-		 */
-		return NOTIFY_STOP;
-	default:
-		return NOTIFY_DONE;
-	}
-
-	handled = x86_pmu.handle_irq(args->regs);
-	if (!handled)
-		return NOTIFY_DONE;
-
-	this_nmi = percpu_read(irq_stat.__nmi_count);
-	if ((handled > 1) ||
-		/* the next nmi could be a back-to-back nmi */
-	    ((__this_cpu_read(pmu_nmi.marked) == this_nmi) &&
-	     (__this_cpu_read(pmu_nmi.handled) > 1))) {
-		/*
-		 * We could have two subsequent back-to-back nmis: The
-		 * first handles more than one counter, the 2nd
-		 * handles only one counter and the 3rd handles no
-		 * counter.
-		 *
-		 * This is the 2nd nmi because the previous was
-		 * handling more than one counter. We will mark the
-		 * next (3rd) and then drop it if unhandled.
-		 */
-		__this_cpu_write(pmu_nmi.marked, this_nmi + 1);
-		__this_cpu_write(pmu_nmi.handled, handled);
-	}
-
-	return NOTIFY_STOP;
-}
-
-static __read_mostly struct notifier_block perf_event_nmi_notifier = {
-	.notifier_call		= perf_event_nmi_handler,
-	.next			= NULL,
-	.priority		= NMI_LOCAL_LOW_PRIOR,
-};
-
-static struct event_constraint unconstrained;
-static struct event_constraint emptyconstraint;
-
-static struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
-{
-	struct event_constraint *c;
-
-	if (x86_pmu.event_constraints) {
-		for_each_event_constraint(c, x86_pmu.event_constraints) {
-			if ((event->hw.config & c->cmask) == c->code)
-				return c;
-		}
-	}
+		return NMI_DONE;
 
-	return &unconstrained;
+	return x86_pmu.handle_irq(regs);
 }
 
-#include "perf_event_amd.c"
-#include "perf_event_p6.c"
-#include "perf_event_p4.c"
-#include "perf_event_intel_lbr.c"
-#include "perf_event_intel_ds.c"
-#include "perf_event_intel.c"
+struct event_constraint emptyconstraint;
+struct event_constraint unconstrained;
 
 static int __cpuinit
 x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (long)hcpu;
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
 	int ret = NOTIFY_OK;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_UP_PREPARE:
+		cpuc->kfree_on_online = NULL;
 		if (x86_pmu.cpu_prepare)
 			ret = x86_pmu.cpu_prepare(cpu);
 		break;
@@ -1479,6 +1085,10 @@ x86_pmu_notifier(struct notifier_block *
 			x86_pmu.cpu_starting(cpu);
 		break;
 
+	case CPU_ONLINE:
+		kfree(cpuc->kfree_on_online);
+		break;
+
 	case CPU_DYING:
 		if (x86_pmu.cpu_dying)
 			x86_pmu.cpu_dying(cpu);
@@ -1557,7 +1167,7 @@ static int __init init_hw_perf_events(vo
 		((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
 
 	perf_events_lapic_init();
-	register_die_notifier(&perf_event_nmi_notifier);
+	register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
 
 	unconstrained = (struct event_constraint)
 		__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
@@ -1702,7 +1312,7 @@ static int validate_event(struct perf_ev
 	c = x86_pmu.get_event_constraints(fake_cpuc, event);
 
 	if (!c || !c->weight)
-		ret = -ENOSPC;
+		ret = -EINVAL;
 
 	if (x86_pmu.put_event_constraints)
 		x86_pmu.put_event_constraints(fake_cpuc, event);
@@ -1727,7 +1337,7 @@ static int validate_group(struct perf_ev
 {
 	struct perf_event *leader = event->group_leader;
 	struct cpu_hw_events *fake_cpuc;
-	int ret = -ENOSPC, n;
+	int ret = -EINVAL, n;
 
 	fake_cpuc = allocate_fake_cpuc();
 	if (IS_ERR(fake_cpuc))
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event.h linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event.h
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,505 @@
+/*
+ * Performance events x86 architecture header
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2009 Jaswinder Singh Rajput
+ *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ *  Copyright (C) 2009 Google, Inc., Stephane Eranian
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+
+/*
+ *          |   NHM/WSM    |      SNB     |
+ * register -------------------------------
+ *          |  HT  | no HT |  HT  | no HT |
+ *-----------------------------------------
+ * offcore  | core | core  | cpu  | core  |
+ * lbr_sel  | core | core  | cpu  | core  |
+ * ld_lat   | cpu  | core  | cpu  | core  |
+ *-----------------------------------------
+ *
+ * Given that there is a small number of shared regs,
+ * we can pre-allocate their slot in the per-cpu
+ * per-core reg tables.
+ */
+enum extra_reg_type {
+	EXTRA_REG_NONE  = -1,	/* not used */
+
+	EXTRA_REG_RSP_0 = 0,	/* offcore_response_0 */
+	EXTRA_REG_RSP_1 = 1,	/* offcore_response_1 */
+
+	EXTRA_REG_MAX		/* number of entries needed */
+};
+
+struct event_constraint {
+	union {
+		unsigned long	idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+		u64		idxmsk64;
+	};
+	u64	code;
+	u64	cmask;
+	int	weight;
+};
+
+struct amd_nb {
+	int nb_id;  /* NorthBridge id */
+	int refcnt; /* reference count */
+	struct perf_event *owners[X86_PMC_IDX_MAX];
+	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
+};
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS		4
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+	u64	bts_buffer_base;
+	u64	bts_index;
+	u64	bts_absolute_maximum;
+	u64	bts_interrupt_threshold;
+	u64	pebs_buffer_base;
+	u64	pebs_index;
+	u64	pebs_absolute_maximum;
+	u64	pebs_interrupt_threshold;
+	u64	pebs_event_reset[MAX_PEBS_EVENTS];
+};
+
+/*
+ * Per register state.
+ */
+struct er_account {
+	raw_spinlock_t		lock;	/* per-core: protect structure */
+	u64                 config;	/* extra MSR config */
+	u64                 reg;	/* extra MSR number */
+	atomic_t            ref;	/* reference count */
+};
+
+/*
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
+ */
+struct intel_shared_regs {
+	struct er_account       regs[EXTRA_REG_MAX];
+	int                     refcnt;		/* per-core: #HT threads */
+	unsigned                core_id;	/* per-core: core id */
+};
+
+#define MAX_LBR_ENTRIES		16
+
+struct cpu_hw_events {
+	/*
+	 * Generic x86 PMC bits
+	 */
+	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
+	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	int			enabled;
+
+	int			n_events;
+	int			n_added;
+	int			n_txn;
+	int			assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
+	u64			tags[X86_PMC_IDX_MAX];
+	struct perf_event	*event_list[X86_PMC_IDX_MAX]; /* in enabled order */
+
+	unsigned int		group_flag;
+
+	/*
+	 * Intel DebugStore bits
+	 */
+	struct debug_store	*ds;
+	u64			pebs_enabled;
+
+	/*
+	 * Intel LBR bits
+	 */
+	int				lbr_users;
+	void				*lbr_context;
+	struct perf_branch_stack	lbr_stack;
+	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
+
+	/*
+	 * Intel host/guest exclude bits
+	 */
+	u64				intel_ctrl_guest_mask;
+	u64				intel_ctrl_host_mask;
+	struct perf_guest_switch_msr	guest_switch_msrs[X86_PMC_IDX_MAX];
+
+	/*
+	 * manage shared (per-core, per-cpu) registers
+	 * used on Intel NHM/WSM/SNB
+	 */
+	struct intel_shared_regs	*shared_regs;
+
+	/*
+	 * AMD specific bits
+	 */
+	struct amd_nb		*amd_nb;
+
+	void				*kfree_on_online;
+};
+
+#define __EVENT_CONSTRAINT(c, n, m, w) {\
+	{ .idxmsk64 = (n) },		\
+	.code = (c),			\
+	.cmask = (m),			\
+	.weight = (w),			\
+}
+
+#define EVENT_CONSTRAINT(c, n, m)	\
+	__EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
+
+/*
+ * Constraint on the Event code.
+ */
+#define INTEL_EVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
+
+/*
+ * Constraint on the Event code + UMask + fixed-mask
+ *
+ * filter mask to validate fixed counter events.
+ * the following filters disqualify for fixed counters:
+ *  - inv
+ *  - edge
+ *  - cnt-mask
+ *  The other filters are supported by fixed counters.
+ *  The any-thread option is supported starting with v3.
+ */
+#define FIXED_EVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
+
+/*
+ * Constraint on the Event code + UMask
+ */
+#define INTEL_UEVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
+
+#define EVENT_CONSTRAINT_END		\
+	EVENT_CONSTRAINT(0, 0, 0)
+
+#define for_each_event_constraint(e, c)	\
+	for ((e) = (c); (e)->weight; (e)++)
+
+/*
+ * Extra registers for specific events.
+ *
+ * Some events need large masks and require external MSRs.
+ * Those extra MSRs end up being shared for all events on
+ * a PMU and sometimes between PMU of sibling HT threads.
+ * In either case, the kernel needs to handle conflicting
+ * accesses to those extra, shared, regs. The data structure
+ * to manage those registers is stored in cpu_hw_event.
+ */
+struct extra_reg {
+	unsigned int		event;
+	unsigned int		msr;
+	u64			config_mask;
+	u64			valid_mask;
+	int			idx;  /* per_xxx->regs[] reg index */
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm, i) {	\
+	.event = (e),		\
+	.msr = (ms),		\
+	.config_mask = (m),	\
+	.valid_mask = (vm),	\
+	.idx = EXTRA_REG_##i	\
+	}
+
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)	\
+	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
+
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
+
+union perf_capabilities {
+	struct {
+		u64	lbr_format:6;
+		u64	pebs_trap:1;
+		u64	pebs_arch_reg:1;
+		u64	pebs_format:4;
+		u64	smm_freeze:1;
+	};
+	u64	capabilities;
+};
+
+/*
+ * struct x86_pmu - generic x86 pmu
+ */
+struct x86_pmu {
+	/*
+	 * Generic x86 PMC bits
+	 */
+	const char	*name;
+	int		version;
+	int		(*handle_irq)(struct pt_regs *);
+	void		(*disable_all)(void);
+	void		(*enable_all)(int added);
+	void		(*enable)(struct perf_event *);
+	void		(*disable)(struct perf_event *);
+	int		(*hw_config)(struct perf_event *event);
+	int		(*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
+	unsigned	eventsel;
+	unsigned	perfctr;
+	u64		(*event_map)(int);
+	int		max_events;
+	int		num_counters;
+	int		num_counters_fixed;
+	int		cntval_bits;
+	u64		cntval_mask;
+	int		apic;
+	u64		max_period;
+	struct event_constraint *
+			(*get_event_constraints)(struct cpu_hw_events *cpuc,
+						 struct perf_event *event);
+
+	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
+						 struct perf_event *event);
+	struct event_constraint *event_constraints;
+	void		(*quirks)(void);
+	int		perfctr_second_write;
+
+	int		(*cpu_prepare)(int cpu);
+	void		(*cpu_starting)(int cpu);
+	void		(*cpu_dying)(int cpu);
+	void		(*cpu_dead)(int cpu);
+
+	/*
+	 * Intel Arch Perfmon v2+
+	 */
+	u64			intel_ctrl;
+	union perf_capabilities intel_cap;
+
+	/*
+	 * Intel DebugStore bits
+	 */
+	int		bts, pebs;
+	int		bts_active, pebs_active;
+	int		pebs_record_size;
+	void		(*drain_pebs)(struct pt_regs *regs);
+	struct event_constraint *pebs_constraints;
+
+	/*
+	 * Intel LBR
+	 */
+	unsigned long	lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
+	int		lbr_nr;			   /* hardware stack size */
+
+	/*
+	 * Extra registers for events
+	 */
+	struct extra_reg *extra_regs;
+	unsigned int er_flags;
+
+	/*
+	 * Intel host/guest support (KVM)
+	 */
+	struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+};
+
+#define ERF_NO_HT_SHARING	1
+#define ERF_HAS_RSP_1		2
+
+extern struct x86_pmu x86_pmu __read_mostly;
+
+DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+int x86_perf_event_set_period(struct perf_event *event);
+
+/*
+ * Generalized hw caching related hw_event table, filled
+ * in on a per model basis. A value of 0 means
+ * 'not supported', -1 means 'hw_event makes no sense on
+ * this CPU', any other value means the raw hw_event
+ * ID.
+ */
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+extern u64 __read_mostly hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+extern u64 __read_mostly hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+u64 x86_perf_event_update(struct perf_event *event);
+
+static inline int x86_pmu_addr_offset(int index)
+{
+	int offset;
+
+	/* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
+	alternative_io(ASM_NOP2,
+		       "shll $1, %%eax",
+		       X86_FEATURE_PERFCTR_CORE,
+		       "=a" (offset),
+		       "a"  (index));
+
+	return offset;
+}
+
+static inline unsigned int x86_pmu_config_addr(int index)
+{
+	return x86_pmu.eventsel + x86_pmu_addr_offset(index);
+}
+
+static inline unsigned int x86_pmu_event_addr(int index)
+{
+	return x86_pmu.perfctr + x86_pmu_addr_offset(index);
+}
+
+int x86_setup_perfctr(struct perf_event *event);
+
+int x86_pmu_hw_config(struct perf_event *event);
+
+void x86_pmu_disable_all(void);
+
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+					  u64 enable_mask)
+{
+	if (hwc->extra_reg.reg)
+		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
+	wrmsrl(hwc->config_base, hwc->config | enable_mask);
+}
+
+void x86_pmu_enable_all(int added);
+
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
+
+void x86_pmu_stop(struct perf_event *event, int flags);
+
+static inline void x86_pmu_disable_event(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	wrmsrl(hwc->config_base, hwc->config);
+}
+
+void x86_pmu_enable_event(struct perf_event *event);
+
+int x86_pmu_handle_irq(struct pt_regs *regs);
+
+extern struct event_constraint emptyconstraint;
+
+extern struct event_constraint unconstrained;
+
+#ifdef CONFIG_CPU_SUP_AMD
+
+int amd_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_AMD */
+
+static inline int amd_pmu_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_CPU_SUP_AMD */
+
+#ifdef CONFIG_CPU_SUP_INTEL
+
+int intel_pmu_save_and_restart(struct perf_event *event);
+
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event);
+
+struct intel_shared_regs *allocate_shared_regs(int cpu);
+
+int intel_pmu_init(void);
+
+void init_debug_store_on_cpu(int cpu);
+
+void fini_debug_store_on_cpu(int cpu);
+
+void release_ds_buffers(void);
+
+void reserve_ds_buffers(void);
+
+extern struct event_constraint bts_constraint;
+
+void intel_pmu_enable_bts(u64 config);
+
+void intel_pmu_disable_bts(void);
+
+int intel_pmu_drain_bts_buffer(void);
+
+extern struct event_constraint intel_core2_pebs_event_constraints[];
+
+extern struct event_constraint intel_atom_pebs_event_constraints[];
+
+extern struct event_constraint intel_nehalem_pebs_event_constraints[];
+
+extern struct event_constraint intel_westmere_pebs_event_constraints[];
+
+extern struct event_constraint intel_snb_pebs_event_constraints[];
+
+struct event_constraint *intel_pebs_constraints(struct perf_event *event);
+
+void intel_pmu_pebs_enable(struct perf_event *event);
+
+void intel_pmu_pebs_disable(struct perf_event *event);
+
+void intel_pmu_pebs_enable_all(void);
+
+void intel_pmu_pebs_disable_all(void);
+
+void intel_ds_init(void);
+
+void intel_pmu_lbr_reset(void);
+
+void intel_pmu_lbr_enable(struct perf_event *event);
+
+void intel_pmu_lbr_disable(struct perf_event *event);
+
+void intel_pmu_lbr_enable_all(void);
+
+void intel_pmu_lbr_disable_all(void);
+
+void intel_pmu_lbr_read(void);
+
+void intel_pmu_lbr_init_core(void);
+
+void intel_pmu_lbr_init_nhm(void);
+
+void intel_pmu_lbr_init_atom(void);
+
+int p4_pmu_init(void);
+
+int p6_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_INTEL */
+
+static inline void reserve_ds_buffers(void)
+{
+}
+
+static inline void release_ds_buffers(void)
+{
+}
+
+static inline int intel_pmu_init(void)
+{
+	return 0;
+}
+
+static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,16 +1,20 @@
-#ifdef CONFIG_CPU_SUP_INTEL
-
 /*
  * Per core/cpu state
  *
  * Used to coordinate shared registers between HT threads or
  * among events on a single PMU.
  */
-struct intel_shared_regs {
-	struct er_account       regs[EXTRA_REG_MAX];
-	int                     refcnt;		/* per-core: #HT threads */
-	unsigned                core_id;	/* per-core: core id */
-};
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
 
 /*
  * Intel PerfMon, used on Core and later.
@@ -746,7 +750,8 @@ static void intel_pmu_enable_all(int add
 
 	intel_pmu_pebs_enable_all();
 	intel_pmu_lbr_enable_all();
-	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
+	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
+			x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
 
 	if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
 		struct perf_event *event =
@@ -869,6 +874,7 @@ static void intel_pmu_disable_fixed(stru
 static void intel_pmu_disable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
 	if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
 		intel_pmu_disable_bts();
@@ -876,6 +882,9 @@ static void intel_pmu_disable_event(stru
 		return;
 	}
 
+	cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
+	cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+
 	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
 		intel_pmu_disable_fixed(hwc);
 		return;
@@ -921,6 +930,7 @@ static void intel_pmu_enable_fixed(struc
 static void intel_pmu_enable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
 	if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
 		if (!__this_cpu_read(cpu_hw_events.enabled))
@@ -930,6 +940,11 @@ static void intel_pmu_enable_event(struc
 		return;
 	}
 
+	if (event->attr.exclude_host)
+		cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
+	if (event->attr.exclude_guest)
+		cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
+
 	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
 		intel_pmu_enable_fixed(hwc);
 		return;
@@ -945,7 +960,7 @@ static void intel_pmu_enable_event(struc
  * Save and restart an expired event. Called by NMI contexts,
  * so it has to be careful about preempting normal event ops:
  */
-static int intel_pmu_save_and_restart(struct perf_event *event)
+int intel_pmu_save_and_restart(struct perf_event *event)
 {
 	x86_perf_event_update(event);
 	return x86_perf_event_set_period(event);
@@ -1154,7 +1169,7 @@ again:
 		 */
 		c = &unconstrained;
 	} else if (intel_try_alt_er(event, orig_idx)) {
-		raw_spin_unlock(&era->lock);
+		raw_spin_unlock_irqrestore(&era->lock, flags);
 		goto again;
 	}
 	raw_spin_unlock_irqrestore(&era->lock, flags);
@@ -1197,6 +1212,21 @@ intel_shared_regs_constraints(struct cpu
 	return c;
 }
 
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	struct event_constraint *c;
+
+	if (x86_pmu.event_constraints) {
+		for_each_event_constraint(c, x86_pmu.event_constraints) {
+			if ((event->hw.config & c->cmask) == c->code)
+				return c;
+		}
+	}
+
+	return &unconstrained;
+}
+
 static struct event_constraint *
 intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
@@ -1284,12 +1314,84 @@ static int intel_pmu_hw_config(struct pe
 	return 0;
 }
 
+struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+	if (x86_pmu.guest_get_msrs)
+		return x86_pmu.guest_get_msrs(nr);
+	*nr = 0;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(perf_guest_get_msrs);
+
+static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+
+	arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
+	arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
+	arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
+
+	*nr = 1;
+	return arr;
+}
+
+static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+	int idx;
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++)  {
+		struct perf_event *event = cpuc->events[idx];
+
+		arr[idx].msr = x86_pmu_config_addr(idx);
+		arr[idx].host = arr[idx].guest = 0;
+
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+
+		arr[idx].host = arr[idx].guest =
+			event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE;
+
+		if (event->attr.exclude_host)
+			arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+		else if (event->attr.exclude_guest)
+			arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+	}
+
+	*nr = x86_pmu.num_counters;
+	return arr;
+}
+
+static void core_pmu_enable_event(struct perf_event *event)
+{
+	if (!event->attr.exclude_host)
+		x86_pmu_enable_event(event);
+}
+
+static void core_pmu_enable_all(int added)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	int idx;
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+		if (!test_bit(idx, cpuc->active_mask) ||
+				cpuc->events[idx]->attr.exclude_host)
+			continue;
+
+		__x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+	}
+}
+
 static __initconst const struct x86_pmu core_pmu = {
 	.name			= "core",
 	.handle_irq		= x86_pmu_handle_irq,
 	.disable_all		= x86_pmu_disable_all,
-	.enable_all		= x86_pmu_enable_all,
-	.enable			= x86_pmu_enable_event,
+	.enable_all		= core_pmu_enable_all,
+	.enable			= core_pmu_enable_event,
 	.disable		= x86_pmu_disable_event,
 	.hw_config		= x86_pmu_hw_config,
 	.schedule_events	= x86_schedule_events,
@@ -1307,9 +1409,10 @@ static __initconst const struct x86_pmu
 	.get_event_constraints	= intel_get_event_constraints,
 	.put_event_constraints	= intel_put_event_constraints,
 	.event_constraints	= intel_core_event_constraints,
+	.guest_get_msrs		= core_guest_get_msrs,
 };
 
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
+struct intel_shared_regs *allocate_shared_regs(int cpu)
 {
 	struct intel_shared_regs *regs;
 	int i;
@@ -1362,7 +1465,7 @@ static void intel_pmu_cpu_starting(int c
 
 		pc = per_cpu(cpu_hw_events, i).shared_regs;
 		if (pc && pc->core_id == core_id) {
-			kfree(cpuc->shared_regs);
+			cpuc->kfree_on_online = cpuc->shared_regs;
 			cpuc->shared_regs = pc;
 			break;
 		}
@@ -1413,6 +1516,7 @@ static __initconst const struct x86_pmu
 	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
+	.guest_get_msrs		= intel_guest_get_msrs,
 };
 
 static void intel_clovertown_quirks(void)
@@ -1441,7 +1545,14 @@ static void intel_clovertown_quirks(void
 	x86_pmu.pebs_constraints = NULL;
 }
 
-static __init int intel_pmu_init(void)
+static void intel_sandybridge_quirks(void)
+{
+	printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
+	x86_pmu.pebs = 0;
+	x86_pmu.pebs_constraints = NULL;
+}
+
+__init int intel_pmu_init(void)
 {
 	union cpuid10_edx edx;
 	union cpuid10_eax eax;
@@ -1590,6 +1701,7 @@ static __init int intel_pmu_init(void)
 		break;
 
 	case 42: /* SandyBridge */
+		x86_pmu.quirks = intel_sandybridge_quirks;
 	case 45: /* SandyBridge, "Romely-EP" */
 		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
@@ -1597,7 +1709,7 @@ static __init int intel_pmu_init(void)
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_snb_event_constraints;
-		x86_pmu.pebs_constraints = intel_snb_pebs_events;
+		x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
 		x86_pmu.extra_regs = intel_snb_extra_regs;
 		/* all extra regs are per-cpu when HT is on */
 		x86_pmu.er_flags |= ERF_HAS_RSP_1;
@@ -1628,16 +1740,3 @@ static __init int intel_pmu_init(void)
 	}
 	return 0;
 }
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static int intel_pmu_init(void)
-{
-	return 0;
-}
-
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
-{
-	return NULL;
-}
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
 
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS		4
+#include <asm/perf_event.h>
+
+#include "perf_event.h"
 
 /* The size of a BTS record in bytes: */
 #define BTS_RECORD_SIZE		24
@@ -37,24 +40,7 @@ struct pebs_record_nhm {
 	u64 status, dla, dse, lat;
 };
 
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
-	u64	bts_buffer_base;
-	u64	bts_index;
-	u64	bts_absolute_maximum;
-	u64	bts_interrupt_threshold;
-	u64	pebs_buffer_base;
-	u64	pebs_index;
-	u64	pebs_absolute_maximum;
-	u64	pebs_interrupt_threshold;
-	u64	pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
-static void init_debug_store_on_cpu(int cpu)
+void init_debug_store_on_cpu(int cpu)
 {
 	struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
 
@@ -66,7 +52,7 @@ static void init_debug_store_on_cpu(int
 		     (u32)((u64)(unsigned long)ds >> 32));
 }
 
-static void fini_debug_store_on_cpu(int cpu)
+void fini_debug_store_on_cpu(int cpu)
 {
 	if (!per_cpu(cpu_hw_events, cpu).ds)
 		return;
@@ -175,7 +161,7 @@ static void release_ds_buffer(int cpu)
 	kfree(ds);
 }
 
-static void release_ds_buffers(void)
+void release_ds_buffers(void)
 {
 	int cpu;
 
@@ -194,7 +180,7 @@ static void release_ds_buffers(void)
 	put_online_cpus();
 }
 
-static void reserve_ds_buffers(void)
+void reserve_ds_buffers(void)
 {
 	int bts_err = 0, pebs_err = 0;
 	int cpu;
@@ -260,10 +246,10 @@ static void reserve_ds_buffers(void)
  * BTS
  */
 
-static struct event_constraint bts_constraint =
+struct event_constraint bts_constraint =
 	EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0);
 
-static void intel_pmu_enable_bts(u64 config)
+void intel_pmu_enable_bts(u64 config)
 {
 	unsigned long debugctlmsr;
 
@@ -282,7 +268,7 @@ static void intel_pmu_enable_bts(u64 con
 	update_debugctlmsr(debugctlmsr);
 }
 
-static void intel_pmu_disable_bts(void)
+void intel_pmu_disable_bts(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	unsigned long debugctlmsr;
@@ -299,7 +285,7 @@ static void intel_pmu_disable_bts(void)
 	update_debugctlmsr(debugctlmsr);
 }
 
-static int intel_pmu_drain_bts_buffer(void)
+int intel_pmu_drain_bts_buffer(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct debug_store *ds = cpuc->ds;
@@ -361,7 +347,7 @@ static int intel_pmu_drain_bts_buffer(vo
 /*
  * PEBS
  */
-static struct event_constraint intel_core2_pebs_event_constraints[] = {
+struct event_constraint intel_core2_pebs_event_constraints[] = {
 	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
 	INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
 	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
@@ -370,14 +356,14 @@ static struct event_constraint intel_cor
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_atom_pebs_event_constraints[] = {
+struct event_constraint intel_atom_pebs_event_constraints[] = {
 	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
 	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
 	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
+struct event_constraint intel_nehalem_pebs_event_constraints[] = {
 	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
 	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
 	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
@@ -392,7 +378,7 @@ static struct event_constraint intel_neh
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_westmere_pebs_event_constraints[] = {
+struct event_constraint intel_westmere_pebs_event_constraints[] = {
 	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
 	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
 	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
@@ -407,7 +393,7 @@ static struct event_constraint intel_wes
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_snb_pebs_events[] = {
+struct event_constraint intel_snb_pebs_event_constraints[] = {
 	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
 	INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
 	INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
@@ -428,8 +414,7 @@ static struct event_constraint intel_snb
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint *
-intel_pebs_constraints(struct perf_event *event)
+struct event_constraint *intel_pebs_constraints(struct perf_event *event)
 {
 	struct event_constraint *c;
 
@@ -446,7 +431,7 @@ intel_pebs_constraints(struct perf_event
 	return &emptyconstraint;
 }
 
-static void intel_pmu_pebs_enable(struct perf_event *event)
+void intel_pmu_pebs_enable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -460,7 +445,7 @@ static void intel_pmu_pebs_enable(struct
 		intel_pmu_lbr_enable(event);
 }
 
-static void intel_pmu_pebs_disable(struct perf_event *event)
+void intel_pmu_pebs_disable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -475,7 +460,7 @@ static void intel_pmu_pebs_disable(struc
 		intel_pmu_lbr_disable(event);
 }
 
-static void intel_pmu_pebs_enable_all(void)
+void intel_pmu_pebs_enable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -483,7 +468,7 @@ static void intel_pmu_pebs_enable_all(vo
 		wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
 }
 
-static void intel_pmu_pebs_disable_all(void)
+void intel_pmu_pebs_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -508,6 +493,7 @@ static int intel_pmu_pebs_fixup_ip(struc
 	unsigned long from = cpuc->lbr_entries[0].from;
 	unsigned long old_to, to = cpuc->lbr_entries[0].to;
 	unsigned long ip = regs->ip;
+	int is_64bit = 0;
 
 	/*
 	 * We don't need to fixup if the PEBS assist is fault like
@@ -559,7 +545,10 @@ static int intel_pmu_pebs_fixup_ip(struc
 		} else
 			kaddr = (void *)to;
 
-		kernel_insn_init(&insn, kaddr);
+#ifdef CONFIG_X86_64
+		is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
+#endif
+		insn_init(&insn, kaddr, is_64bit);
 		insn_get_length(&insn);
 		to += insn.length;
 	} while (to < ip);
@@ -576,8 +565,6 @@ static int intel_pmu_pebs_fixup_ip(struc
 	return 0;
 }
 
-static int intel_pmu_save_and_restart(struct perf_event *event);
-
 static void __intel_pmu_pebs_event(struct perf_event *event,
 				   struct pt_regs *iregs, void *__pebs)
 {
@@ -716,7 +703,7 @@ static void intel_pmu_drain_pebs_nhm(str
  * BTS, PEBS probe and setup
  */
 
-static void intel_ds_init(void)
+void intel_ds_init(void)
 {
 	/*
 	 * No support for 32bit formats
@@ -749,15 +736,3 @@ static void intel_ds_init(void)
 		}
 	}
 }
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static void reserve_ds_buffers(void)
-{
-}
-
-static void release_ds_buffers(void)
-{
-}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include <asm/perf_event.h>
+#include <asm/msr.h>
+
+#include "perf_event.h"
 
 enum {
 	LBR_FORMAT_32		= 0x00,
@@ -48,7 +54,7 @@ static void intel_pmu_lbr_reset_64(void)
 	}
 }
 
-static void intel_pmu_lbr_reset(void)
+void intel_pmu_lbr_reset(void)
 {
 	if (!x86_pmu.lbr_nr)
 		return;
@@ -59,7 +65,7 @@ static void intel_pmu_lbr_reset(void)
 		intel_pmu_lbr_reset_64();
 }
 
-static void intel_pmu_lbr_enable(struct perf_event *event)
+void intel_pmu_lbr_enable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -81,7 +87,7 @@ static void intel_pmu_lbr_enable(struct
 	cpuc->lbr_users++;
 }
 
-static void intel_pmu_lbr_disable(struct perf_event *event)
+void intel_pmu_lbr_disable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -95,7 +101,7 @@ static void intel_pmu_lbr_disable(struct
 		__intel_pmu_lbr_disable();
 }
 
-static void intel_pmu_lbr_enable_all(void)
+void intel_pmu_lbr_enable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -103,7 +109,7 @@ static void intel_pmu_lbr_enable_all(voi
 		__intel_pmu_lbr_enable();
 }
 
-static void intel_pmu_lbr_disable_all(void)
+void intel_pmu_lbr_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -178,7 +184,7 @@ static void intel_pmu_lbr_read_64(struct
 	cpuc->lbr_stack.nr = i;
 }
 
-static void intel_pmu_lbr_read(void)
+void intel_pmu_lbr_read(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -191,7 +197,7 @@ static void intel_pmu_lbr_read(void)
 		intel_pmu_lbr_read_64(cpuc);
 }
 
-static void intel_pmu_lbr_init_core(void)
+void intel_pmu_lbr_init_core(void)
 {
 	x86_pmu.lbr_nr     = 4;
 	x86_pmu.lbr_tos    = 0x01c9;
@@ -199,7 +205,7 @@ static void intel_pmu_lbr_init_core(void
 	x86_pmu.lbr_to     = 0x60;
 }
 
-static void intel_pmu_lbr_init_nhm(void)
+void intel_pmu_lbr_init_nhm(void)
 {
 	x86_pmu.lbr_nr     = 16;
 	x86_pmu.lbr_tos    = 0x01c9;
@@ -207,12 +213,10 @@ static void intel_pmu_lbr_init_nhm(void)
 	x86_pmu.lbr_to     = 0x6c0;
 }
 
-static void intel_pmu_lbr_init_atom(void)
+void intel_pmu_lbr_init_atom(void)
 {
 	x86_pmu.lbr_nr	   = 8;
 	x86_pmu.lbr_tos    = 0x01c9;
 	x86_pmu.lbr_from   = 0x40;
 	x86_pmu.lbr_to     = 0x60;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_p4.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_p4.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_p4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_p4.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,9 +7,13 @@
  *  For licencing details see kernel-base/COPYING
  */
 
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
 
 #include <asm/perf_event_p4.h>
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
 
 #define P4_CNTR_LIMIT 3
 /*
@@ -1264,7 +1268,7 @@ reserve:
 	}
 
 done:
-	return num ? -ENOSPC : 0;
+	return num ? -EINVAL : 0;
 }
 
 static __initconst const struct x86_pmu p4_pmu = {
@@ -1303,7 +1307,7 @@ static __initconst const struct x86_pmu
 	.perfctr_second_write	= 1,
 };
 
-static __init int p4_pmu_init(void)
+__init int p4_pmu_init(void)
 {
 	unsigned int low, high;
 
@@ -1326,5 +1330,3 @@ static __init int p4_pmu_init(void)
 
 	return 0;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_p6.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_p6.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/perf_event_p6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/perf_event_p6.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include "perf_event.h"
 
 /*
  * Not sure about some of these
@@ -114,7 +117,7 @@ static __initconst const struct x86_pmu
 	.event_constraints	= p6_event_constraints,
 };
 
-static __init int p6_pmu_init(void)
+__init int p6_pmu_init(void)
 {
 	switch (boot_cpu_data.x86_model) {
 	case 1:
@@ -138,5 +141,3 @@ static __init int p6_pmu_init(void)
 
 	return 0;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/proc.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/proc.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,8 @@ static int show_cpuinfo(struct seq_file
 		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
 	else
 		seq_printf(m, "stepping\t: unknown\n");
+	if (c->microcode)
+		seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
 
 	if (cpu_has(c, X86_FEATURE_TSC)) {
 		unsigned int freq = cpufreq_quick_get(cpu);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/cpu/rdrand.c linux-libre-3.2-gnu1/arch/x86/kernel/cpu/rdrand.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/cpu/rdrand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/kernel/cpu/rdrand.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ *          H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/archrandom.h>
+#include <asm/sections.h>
+
+static int __init x86_rdrand_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+	return 1;
+}
+__setup("nordrand", x86_rdrand_setup);
+
+/* We can't use arch_get_random_long() here since alternatives haven't run */
+static inline int rdrand_long(unsigned long *v)
+{
+	int ok;
+	asm volatile("1: " RDRAND_LONG "\n\t"
+		     "jc 2f\n\t"
+		     "decl %0\n\t"
+		     "jnz 1b\n\t"
+		     "2:"
+		     : "=r" (ok), "=a" (*v)
+		     : "0" (RDRAND_RETRY_LOOPS));
+	return ok;
+}
+
+/*
+ * Force a reseed cycle; we are architecturally guaranteed a reseed
+ * after no more than 512 128-bit chunks of random data.  This also
+ * acts as a test of the CPU capability.
+ */
+#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
+
+void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_ARCH_RANDOM
+	unsigned long tmp;
+	int i, count, ok;
+
+	if (!cpu_has(c, X86_FEATURE_RDRAND))
+		return;		/* Nothing to do */
+
+	for (count = i = 0; i < RESEED_LOOP; i++) {
+		ok = rdrand_long(&tmp);
+		if (ok)
+			count++;
+	}
+
+	if (count != RESEED_LOOP)
+		clear_cpu_cap(c, X86_FEATURE_RDRAND);
+#endif
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/crash.c linux-libre-3.2-gnu1/arch/x86/kernel/crash.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/crash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/crash.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,15 +32,12 @@ int in_crash_kexec;
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 
-static void kdump_nmi_callback(int cpu, struct die_args *args)
+static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
 {
-	struct pt_regs *regs;
 #ifdef CONFIG_X86_32
 	struct pt_regs fixed_regs;
 #endif
 
-	regs = args->regs;
-
 #ifdef CONFIG_X86_32
 	if (!user_mode_vm(regs)) {
 		crash_fixup_ss_esp(&fixed_regs, regs);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/devicetree.c linux-libre-3.2-gnu1/arch/x86/kernel/devicetree.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/devicetree.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/devicetree.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * Architecture specific OF callbacks.
  */
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/dumpstack_32.c linux-libre-3.2-gnu1/arch/x86/kernel/dumpstack_32.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/dumpstack_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/dumpstack_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs
 		for (i = 0; i < code_len; i++, ip++) {
 			if (ip < (u8 *)PAGE_OFFSET ||
 					probe_kernel_address(ip, c)) {
-				printk(" Bad EIP value.");
+				printk(KERN_CONT " Bad EIP value.");
 				break;
 			}
 			if (ip == (u8 *)regs->ip)
-				printk("<%02x> ", c);
+				printk(KERN_CONT "<%02x> ", c);
 			else
-				printk("%02x ", c);
+				printk(KERN_CONT "%02x ", c);
 		}
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/dumpstack_64.c linux-libre-3.2-gnu1/arch/x86/kernel/dumpstack_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/dumpstack_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/dumpstack_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs
 		for (i = 0; i < code_len; i++, ip++) {
 			if (ip < (u8 *)PAGE_OFFSET ||
 					probe_kernel_address(ip, c)) {
-				printk(" Bad RIP value.");
+				printk(KERN_CONT " Bad RIP value.");
 				break;
 			}
 			if (ip == (u8 *)regs->ip)
-				printk("<%02x> ", c);
+				printk(KERN_CONT "<%02x> ", c);
 			else
-				printk("%02x ", c);
+				printk(KERN_CONT "%02x ", c);
 		}
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/e820.c linux-libre-3.2-gnu1/arch/x86/kernel/e820.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/e820.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/e820.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/crash_dump.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/suspend.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/entry_64.S linux-libre-3.2-gnu1/arch/x86/kernel/entry_64.S
--- linux-libre-3.1-gnu1/arch/x86/kernel/entry_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/entry_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -331,10 +331,15 @@ ENDPROC(native_usergs_sysret64)
 1:	incl PER_CPU_VAR(irq_count)
 	jne 2f
 	mov PER_CPU_VAR(irq_stack_ptr),%rsp
-	EMPTY_FRAME 0
+	CFI_DEF_CFA_REGISTER	rsi
 
 2:	/* Store previous stack value */
 	pushq %rsi
+	CFI_ESCAPE	0x0f /* DW_CFA_def_cfa_expression */, 6, \
+			0x77 /* DW_OP_breg7 */, 0, \
+			0x06 /* DW_OP_deref */, \
+			0x08 /* DW_OP_const1u */, SS+8-RBP, \
+			0x22 /* DW_OP_plus */
 	/* We entered an interrupt context - irqs are off: */
 	TRACE_IRQS_OFF
 	.endm
@@ -788,7 +793,6 @@ END(interrupt)
 	subq $ORIG_RAX-RBP, %rsp
 	CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
 	SAVE_ARGS_IRQ
-	PARTIAL_FRAME 0
 	call \func
 	.endm
 
@@ -813,10 +817,10 @@ ret_from_intr:
 
 	/* Restore saved previous stack */
 	popq %rsi
-	leaq 16(%rsi), %rsp
-
+	CFI_DEF_CFA_REGISTER	rsi
+	leaq ARGOFFSET-RBP(%rsi), %rsp
 	CFI_DEF_CFA_REGISTER	rsp
-	CFI_ADJUST_CFA_OFFSET	-16
+	CFI_ADJUST_CFA_OFFSET	RBP-ARGOFFSET
 
 exit_intr:
 	GET_THREAD_INFO(%rcx)
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/hpet.c linux-libre-3.2-gnu1/arch/x86/kernel/hpet.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/hpet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/hpet.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/sysdev.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -1048,6 +1049,14 @@ int hpet_rtc_timer_init(void)
 }
 EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
 
+static void hpet_disable_rtc_channel(void)
+{
+	unsigned long cfg;
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg &= ~HPET_TN_ENABLE;
+	hpet_writel(cfg, HPET_T1_CFG);
+}
+
 /*
  * The functions below are called from rtc driver.
  * Return 0 if HPET is not being used.
@@ -1059,6 +1068,9 @@ int hpet_mask_rtc_irq_bit(unsigned long
 		return 0;
 
 	hpet_rtc_flags &= ~bit_mask;
+	if (unlikely(!hpet_rtc_flags))
+		hpet_disable_rtc_channel();
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit);
@@ -1124,15 +1136,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq);
 
 static void hpet_rtc_timer_reinit(void)
 {
-	unsigned int cfg, delta;
+	unsigned int delta;
 	int lost_ints = -1;
 
-	if (unlikely(!hpet_rtc_flags)) {
-		cfg = hpet_readl(HPET_T1_CFG);
-		cfg &= ~HPET_TN_ENABLE;
-		hpet_writel(cfg, HPET_T1_CFG);
-		return;
-	}
+	if (unlikely(!hpet_rtc_flags))
+		hpet_disable_rtc_channel();
 
 	if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
 		delta = hpet_default_delta;
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/irq_64.c linux-libre-3.2-gnu1/arch/x86/kernel/irq_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/irq_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/irq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,9 @@ static inline void stack_overflow_check(
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	u64 curbase = (u64)task_stack_page(current);
 
+	if (user_mode_vm(regs))
+		return;
+
 	WARN_ONCE(regs->sp >= curbase &&
 		  regs->sp <= curbase + THREAD_SIZE &&
 		  regs->sp <  curbase + sizeof(struct thread_info) +
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/irq.c linux-libre-3.2-gnu1/arch/x86/kernel/irq.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/smp.h>
 #include <linux/ftrace.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/apic.h>
 #include <asm/io_apic.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/jump_label.c linux-libre-3.2-gnu1/arch/x86/kernel/jump_label.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,9 @@ union jump_code_union {
 	} __attribute__((packed));
 };
 
-void arch_jump_label_transform(struct jump_entry *entry,
-			       enum jump_label_type type)
+static void __jump_label_transform(struct jump_entry *entry,
+				   enum jump_label_type type,
+				   void *(*poker)(void *, const void *, size_t))
 {
 	union jump_code_union code;
 
@@ -35,17 +36,24 @@ void arch_jump_label_transform(struct ju
 				(entry->code + JUMP_LABEL_NOP_SIZE);
 	} else
 		memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
+
+	(*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
 	get_online_cpus();
 	mutex_lock(&text_mutex);
-	text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	__jump_label_transform(entry, type, text_poke_smp);
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
 }
 
-void arch_jump_label_text_poke_early(jump_label_t addr)
+void arch_jump_label_transform_static(struct jump_entry *entry,
+				      enum jump_label_type type)
 {
-	text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5],
-			JUMP_LABEL_NOP_SIZE);
+	__jump_label_transform(entry, type, text_poke_early);
 }
 
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/kgdb.c linux-libre-3.2-gnu1/arch/x86/kernel/kgdb.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -511,28 +511,37 @@ single_step_cont(struct pt_regs *regs, s
 
 static int was_in_debug_nmi[NR_CPUS];
 
-static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+static int kgdb_nmi_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct pt_regs *regs = args->regs;
-
 	switch (cmd) {
-	case DIE_NMI:
+	case NMI_LOCAL:
 		if (atomic_read(&kgdb_active) != -1) {
 			/* KGDB CPU roundup */
 			kgdb_nmicallback(raw_smp_processor_id(), regs);
 			was_in_debug_nmi[raw_smp_processor_id()] = 1;
 			touch_nmi_watchdog();
-			return NOTIFY_STOP;
+			return NMI_HANDLED;
 		}
-		return NOTIFY_DONE;
+		break;
 
-	case DIE_NMIUNKNOWN:
+	case NMI_UNKNOWN:
 		if (was_in_debug_nmi[raw_smp_processor_id()]) {
 			was_in_debug_nmi[raw_smp_processor_id()] = 0;
-			return NOTIFY_STOP;
+			return NMI_HANDLED;
 		}
-		return NOTIFY_DONE;
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	return NMI_DONE;
+}
 
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	struct pt_regs *regs = args->regs;
+
+	switch (cmd) {
 	case DIE_DEBUG:
 		if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
 			if (user_mode(regs))
@@ -590,11 +599,6 @@ kgdb_notify(struct notifier_block *self,
 
 static struct notifier_block kgdb_notifier = {
 	.notifier_call	= kgdb_notify,
-
-	/*
-	 * Lowest-prio notifier priority, we want to be notified last:
-	 */
-	.priority	= NMI_LOCAL_LOW_PRIOR,
 };
 
 /**
@@ -605,7 +609,31 @@ static struct notifier_block kgdb_notifi
  */
 int kgdb_arch_init(void)
 {
-	return register_die_notifier(&kgdb_notifier);
+	int retval;
+
+	retval = register_die_notifier(&kgdb_notifier);
+	if (retval)
+		goto out;
+
+	retval = register_nmi_handler(NMI_LOCAL, kgdb_nmi_handler,
+					0, "kgdb");
+	if (retval)
+		goto out1;
+
+	retval = register_nmi_handler(NMI_UNKNOWN, kgdb_nmi_handler,
+					0, "kgdb");
+
+	if (retval)
+		goto out2;
+
+	return retval;
+
+out2:
+	unregister_nmi_handler(NMI_LOCAL, "kgdb");
+out1:
+	unregister_die_notifier(&kgdb_notifier);
+out:
+	return retval;
 }
 
 static void kgdb_hw_overflow_handler(struct perf_event *event,
@@ -673,6 +701,8 @@ void kgdb_arch_exit(void)
 			breakinfo[i].pev = NULL;
 		}
 	}
+	unregister_nmi_handler(NMI_UNKNOWN, "kgdb");
+	unregister_nmi_handler(NMI_LOCAL, "kgdb");
 	unregister_die_notifier(&kgdb_notifier);
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/kprobes.c linux-libre-3.2-gnu1/arch/x86/kernel/kprobes.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/kprobes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/kprobes.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,8 +75,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kpr
 	/*
 	 * Undefined/reserved opcodes, conditional jump, Opcode Extension
 	 * Groups, and some special opcodes can not boost.
+	 * This is non-const and volatile to keep gcc from statically
+	 * optimizing it out, as variable_test_bit makes gcc think only
+	 * *(unsigned long*) is used. 
 	 */
-static const u32 twobyte_is_boostable[256 / 32] = {
+static volatile u32 twobyte_is_boostable[256 / 32] = {
 	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
 	/*      ----------------------------------------------          */
 	W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/kvmclock.c linux-libre-3.2-gnu1/arch/x86/kernel/kvmclock.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/kvmclock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/kvmclock.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,9 +74,10 @@ static cycle_t kvm_clock_read(void)
 	struct pvclock_vcpu_time_info *src;
 	cycle_t ret;
 
-	src = &get_cpu_var(hv_clock);
+	preempt_disable_notrace();
+	src = &__get_cpu_var(hv_clock);
 	ret = pvclock_clocksource_read(src);
-	put_cpu_var(hv_clock);
+	preempt_enable_notrace();
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/Makefile linux-libre-3.2-gnu1/arch/x86/kernel/Makefile
--- linux-libre-3.1-gnu1/arch/x86/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@ endif
 
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
-obj-y			+= time.o ioport.o ldt.o dumpstack.o
+obj-y			+= time.o ioport.o ldt.o dumpstack.o nmi.o
 obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y			+= probe_roms.o
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/microcode_amd.c linux-libre-3.2-gnu1/arch/x86/kernel/microcode_amd.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/microcode_amd.c	2013-05-02 01:32:46.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/microcode_amd.c	2013-05-01 23:40:48.000000000 -0400
@@ -74,14 +74,13 @@ static struct equiv_cpu_entry *equiv_cpu
 static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	u32 dummy;
 
 	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
 		pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
 		return -1;
 	}
 
-	rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy);
+	csig->rev = c->microcode;
 	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
 
 	return 0;
@@ -130,6 +129,7 @@ static int apply_microcode_amd(int cpu)
 	int cpu_num = raw_smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 	struct microcode_amd *mc_amd = uci->mc;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	/* We should bind the task to the CPU */
 	BUG_ON(cpu_num != cpu);
@@ -150,6 +150,7 @@ static int apply_microcode_amd(int cpu)
 
 	pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
 	uci->cpu_sig.rev = rev;
+	c->microcode = rev;
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/microcode_core.c linux-libre-3.2-gnu1/arch/x86/kernel/microcode_core.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/microcode_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/microcode_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,7 +256,7 @@ static int __init microcode_dev_init(voi
 	return 0;
 }
 
-static void microcode_dev_exit(void)
+static void __exit microcode_dev_exit(void)
 {
 	misc_deregister(&microcode_dev);
 }
@@ -483,7 +483,13 @@ mc_cpu_callback(struct notifier_block *n
 		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
 		pr_debug("CPU%d removed\n", cpu);
 		break;
-	case CPU_DEAD:
+
+	/*
+	 * When a CPU goes offline, don't free up or invalidate the copy of
+	 * the microcode in kernel memory, so that we can reuse it when the
+	 * CPU comes back online without unnecessarily requesting the userspace
+	 * for it again.
+	 */
 	case CPU_UP_CANCELED_FROZEN:
 		/* The CPU refused to come up during a system resume */
 		microcode_fini_cpu(cpu);
@@ -513,10 +519,8 @@ static int __init microcode_init(void)
 
 	microcode_pdev = platform_device_register_simple("microcode", -1,
 							 NULL, 0);
-	if (IS_ERR(microcode_pdev)) {
-		microcode_dev_exit();
+	if (IS_ERR(microcode_pdev))
 		return PTR_ERR(microcode_pdev);
-	}
 
 	get_online_cpus();
 	mutex_lock(&microcode_mutex);
@@ -526,14 +530,12 @@ static int __init microcode_init(void)
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
 
-	if (error) {
-		platform_device_unregister(microcode_pdev);
-		return error;
-	}
+	if (error)
+		goto out_pdev;
 
 	error = microcode_dev_init();
 	if (error)
-		return error;
+		goto out_sysdev_driver;
 
 	register_syscore_ops(&mc_syscore_ops);
 	register_hotcpu_notifier(&mc_cpu_notifier);
@@ -542,6 +544,20 @@ static int __init microcode_init(void)
 		" <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
 
 	return 0;
+
+out_sysdev_driver:
+	get_online_cpus();
+	mutex_lock(&microcode_mutex);
+
+	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+
+	mutex_unlock(&microcode_mutex);
+	put_online_cpus();
+
+out_pdev:
+	platform_device_unregister(microcode_pdev);
+	return error;
+
 }
 module_init(microcode_init);
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/microcode_intel.c linux-libre-3.2-gnu1/arch/x86/kernel/microcode_intel.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/microcode_intel.c	2013-05-02 01:32:48.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/microcode_intel.c	2013-05-01 23:40:50.000000000 -0400
@@ -161,12 +161,7 @@ static int collect_cpu_info(int cpu_num,
 		csig->pf = 1 << ((val[1] >> 18) & 7);
 	}
 
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-	/* see notes above for revision 1.07.  Apparent chip bug */
-	sync_core();
-	/* get the current revision from MSR 0x8B */
-	rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
-
+	csig->rev = c->microcode;
 	pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
 		cpu_num, csig->sig, csig->pf, csig->rev);
 
@@ -299,9 +294,9 @@ static int apply_microcode(int cpu)
 	struct microcode_intel *mc_intel;
 	struct ucode_cpu_info *uci;
 	unsigned int val[2];
-	int cpu_num;
+	int cpu_num = raw_smp_processor_id();
+	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
 
-	cpu_num = raw_smp_processor_id();
 	uci = ucode_cpu_info + cpu;
 	mc_intel = uci->mc;
 
@@ -317,7 +312,7 @@ static int apply_microcode(int cpu)
 	      (unsigned long) mc_intel->bits >> 16 >> 16);
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 
-	/* see notes above for revision 1.07.  Apparent chip bug */
+	/* As documented in the SDM: Do a CPUID 1 here */
 	sync_core();
 
 	/* get the current revision from MSR 0x8B */
@@ -335,6 +330,7 @@ static int apply_microcode(int cpu)
 		(mc_intel->hdr.date >> 16) & 0xff);
 
 	uci->cpu_sig.rev = val[1];
+	c->microcode = val[1];
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/mpparse.c linux-libre-3.2-gnu1/arch/x86/kernel/mpparse.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/mpparse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/mpparse.c	2012-01-04 18:55:44.000000000 -0500
@@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mp
 	}
 #endif
 
+	set_bit(m->busid, mp_bus_not_pci);
 	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
-		set_bit(m->busid, mp_bus_not_pci);
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/nmi.c linux-libre-3.2-gnu1/arch/x86/kernel/nmi.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/nmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/kernel/nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,435 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *  Copyright (C) 2011	Don Zickus Red Hat, Inc.
+ *
+ *  Pentium III FXSR, SSE support
+ *	Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * Handle hardware traps and faults.
+ */
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/nmi.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <linux/mca.h>
+
+#if defined(CONFIG_EDAC)
+#include <linux/edac.h>
+#endif
+
+#include <linux/atomic.h>
+#include <asm/traps.h>
+#include <asm/mach_traps.h>
+#include <asm/nmi.h>
+#include <asm/x86_init.h>
+
+#define NMI_MAX_NAMELEN	16
+struct nmiaction {
+	struct list_head list;
+	nmi_handler_t handler;
+	unsigned int flags;
+	char *name;
+};
+
+struct nmi_desc {
+	spinlock_t lock;
+	struct list_head head;
+};
+
+static struct nmi_desc nmi_desc[NMI_MAX] = 
+{
+	{
+		.lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[0].lock),
+		.head = LIST_HEAD_INIT(nmi_desc[0].head),
+	},
+	{
+		.lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock),
+		.head = LIST_HEAD_INIT(nmi_desc[1].head),
+	},
+
+};
+
+struct nmi_stats {
+	unsigned int normal;
+	unsigned int unknown;
+	unsigned int external;
+	unsigned int swallow;
+};
+
+static DEFINE_PER_CPU(struct nmi_stats, nmi_stats);
+
+static int ignore_nmis;
+
+int unknown_nmi_panic;
+/*
+ * Prevent NMI reason port (0x61) being accessed simultaneously, can
+ * only be used in NMI handler.
+ */
+static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
+
+static int __init setup_unknown_nmi_panic(char *str)
+{
+	unknown_nmi_panic = 1;
+	return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
+#define nmi_to_desc(type) (&nmi_desc[type])
+
+static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	struct nmiaction *a;
+	int handled=0;
+
+	rcu_read_lock();
+
+	/*
+	 * NMIs are edge-triggered, which means if you have enough
+	 * of them concurrently, you can lose some because only one
+	 * can be latched at any given time.  Walk the whole list
+	 * to handle those situations.
+	 */
+	list_for_each_entry_rcu(a, &desc->head, list)
+		handled += a->handler(type, regs);
+
+	rcu_read_unlock();
+
+	/* return total number of NMI events handled */
+	return handled;
+}
+
+static int __setup_nmi(unsigned int type, struct nmiaction *action)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+
+	/*
+	 * most handlers of type NMI_UNKNOWN never return because
+	 * they just assume the NMI is theirs.  Just a sanity check
+	 * to manage expectations
+	 */
+	WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head));
+
+	/*
+	 * some handlers need to be executed first otherwise a fake
+	 * event confuses some handlers (kdump uses this flag)
+	 */
+	if (action->flags & NMI_FLAG_FIRST)
+		list_add_rcu(&action->list, &desc->head);
+	else
+		list_add_tail_rcu(&action->list, &desc->head);
+	
+	spin_unlock_irqrestore(&desc->lock, flags);
+	return 0;
+}
+
+static struct nmiaction *__free_nmi(unsigned int type, const char *name)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	struct nmiaction *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+
+	list_for_each_entry_rcu(n, &desc->head, list) {
+		/*
+		 * the name passed in to describe the nmi handler
+		 * is used as the lookup key
+		 */
+		if (!strcmp(n->name, name)) {
+			WARN(in_nmi(),
+				"Trying to free NMI (%s) from NMI context!\n", n->name);
+			list_del_rcu(&n->list);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&desc->lock, flags);
+	synchronize_rcu();
+	return (n);
+}
+
+int register_nmi_handler(unsigned int type, nmi_handler_t handler,
+			unsigned long nmiflags, const char *devname)
+{
+	struct nmiaction *action;
+	int retval = -ENOMEM;
+
+	if (!handler)
+		return -EINVAL;
+
+	action = kzalloc(sizeof(struct nmiaction), GFP_KERNEL);
+	if (!action)
+		goto fail_action;
+
+	action->handler = handler;
+	action->flags = nmiflags;
+	action->name = kstrndup(devname, NMI_MAX_NAMELEN, GFP_KERNEL);
+	if (!action->name)
+		goto fail_action_name;
+
+	retval = __setup_nmi(type, action);
+
+	if (retval)
+		goto fail_setup_nmi;
+
+	return retval;
+
+fail_setup_nmi:
+	kfree(action->name);
+fail_action_name:
+	kfree(action);
+fail_action:	
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(register_nmi_handler);
+
+void unregister_nmi_handler(unsigned int type, const char *name)
+{
+	struct nmiaction *a;
+
+	a = __free_nmi(type, name);
+	if (a) {
+		kfree(a->name);
+		kfree(a);
+	}
+}
+
+EXPORT_SYMBOL_GPL(unregister_nmi_handler);
+
+static notrace __kprobes void
+pci_serr_error(unsigned char reason, struct pt_regs *regs)
+{
+	pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+
+	/*
+	 * On some machines, PCI SERR line is used to report memory
+	 * errors. EDAC makes use of it.
+	 */
+#if defined(CONFIG_EDAC)
+	if (edac_handler_set()) {
+		edac_atomic_assert_error();
+		return;
+	}
+#endif
+
+	if (panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	pr_emerg("Dazed and confused, but trying to continue\n");
+
+	/* Clear and disable the PCI SERR error line. */
+	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
+	outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+io_check_error(unsigned char reason, struct pt_regs *regs)
+{
+	unsigned long i;
+
+	pr_emerg(
+	"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+	show_registers(regs);
+
+	if (panic_on_io_nmi)
+		panic("NMI IOCK error: Not continuing");
+
+	/* Re-enable the IOCK line, wait for a few seconds */
+	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
+
+	i = 20000;
+	while (--i) {
+		touch_nmi_watchdog();
+		udelay(100);
+	}
+
+	reason &= ~NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+{
+	int handled;
+
+	/*
+	 * Use 'false' as back-to-back NMIs are dealt with one level up.
+	 * Of course this makes having multiple 'unknown' handlers useless
+	 * as only the first one is ever run (unless it can actually determine
+	 * if it caused the NMI)
+	 */
+	handled = nmi_handle(NMI_UNKNOWN, regs, false);
+	if (handled) {
+		__this_cpu_add(nmi_stats.unknown, handled);
+		return;
+	}
+
+	__this_cpu_add(nmi_stats.unknown, 1);
+
+#ifdef CONFIG_MCA
+	/*
+	 * Might actually be able to figure out what the guilty party
+	 * is:
+	 */
+	if (MCA_bus) {
+		mca_handle_nmi();
+		return;
+	}
+#endif
+	pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+
+	pr_emerg("Do you have a strange power saving mode enabled?\n");
+	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	pr_emerg("Dazed and confused, but trying to continue\n");
+}
+
+static DEFINE_PER_CPU(bool, swallow_nmi);
+static DEFINE_PER_CPU(unsigned long, last_nmi_rip);
+
+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+{
+	unsigned char reason = 0;
+	int handled;
+	bool b2b = false;
+
+	/*
+	 * CPU-specific NMI must be processed before non-CPU-specific
+	 * NMI, otherwise we may lose it, because the CPU-specific
+	 * NMI can not be detected/processed on other CPUs.
+	 */
+
+	/*
+	 * Back-to-back NMIs are interesting because they can either
+	 * be two NMI or more than two NMIs (any thing over two is dropped
+	 * due to NMI being edge-triggered).  If this is the second half
+	 * of the back-to-back NMI, assume we dropped things and process
+	 * more handlers.  Otherwise reset the 'swallow' NMI behaviour
+	 */
+	if (regs->ip == __this_cpu_read(last_nmi_rip))
+		b2b = true;
+	else
+		__this_cpu_write(swallow_nmi, false);
+
+	__this_cpu_write(last_nmi_rip, regs->ip);
+
+	handled = nmi_handle(NMI_LOCAL, regs, b2b);
+	__this_cpu_add(nmi_stats.normal, handled);
+	if (handled) {
+		/*
+		 * There are cases when a NMI handler handles multiple
+		 * events in the current NMI.  One of these events may
+		 * be queued for in the next NMI.  Because the event is
+		 * already handled, the next NMI will result in an unknown
+		 * NMI.  Instead lets flag this for a potential NMI to
+		 * swallow.
+		 */
+		if (handled > 1)
+			__this_cpu_write(swallow_nmi, true);
+		return;
+	}
+
+	/* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
+	raw_spin_lock(&nmi_reason_lock);
+	reason = x86_platform.get_nmi_reason();
+
+	if (reason & NMI_REASON_MASK) {
+		if (reason & NMI_REASON_SERR)
+			pci_serr_error(reason, regs);
+		else if (reason & NMI_REASON_IOCHK)
+			io_check_error(reason, regs);
+#ifdef CONFIG_X86_32
+		/*
+		 * Reassert NMI in case it became active
+		 * meanwhile as it's edge-triggered:
+		 */
+		reassert_nmi();
+#endif
+		__this_cpu_add(nmi_stats.external, 1);
+		raw_spin_unlock(&nmi_reason_lock);
+		return;
+	}
+	raw_spin_unlock(&nmi_reason_lock);
+
+	/*
+	 * Only one NMI can be latched at a time.  To handle
+	 * this we may process multiple nmi handlers at once to
+	 * cover the case where an NMI is dropped.  The downside
+	 * to this approach is we may process an NMI prematurely,
+	 * while its real NMI is sitting latched.  This will cause
+	 * an unknown NMI on the next run of the NMI processing.
+	 *
+	 * We tried to flag that condition above, by setting the
+	 * swallow_nmi flag when we process more than one event.
+	 * This condition is also only present on the second half
+	 * of a back-to-back NMI, so we flag that condition too.
+	 *
+	 * If both are true, we assume we already processed this
+	 * NMI previously and we swallow it.  Otherwise we reset
+	 * the logic.
+	 *
+	 * There are scenarios where we may accidentally swallow
+	 * a 'real' unknown NMI.  For example, while processing
+	 * a perf NMI another perf NMI comes in along with a
+	 * 'real' unknown NMI.  These two NMIs get combined into
+	 * one (as descibed above).  When the next NMI gets
+	 * processed, it will be flagged by perf as handled, but
+	 * noone will know that there was a 'real' unknown NMI sent
+	 * also.  As a result it gets swallowed.  Or if the first
+	 * perf NMI returns two events handled then the second
+	 * NMI will get eaten by the logic below, again losing a
+	 * 'real' unknown NMI.  But this is the best we can do
+	 * for now.
+	 */
+	if (b2b && __this_cpu_read(swallow_nmi))
+		__this_cpu_add(nmi_stats.swallow, 1);
+	else
+		unknown_nmi_error(reason, regs);
+}
+
+dotraplinkage notrace __kprobes void
+do_nmi(struct pt_regs *regs, long error_code)
+{
+	nmi_enter();
+
+	inc_irq_stat(__nmi_count);
+
+	if (!ignore_nmis)
+		default_do_nmi(regs);
+
+	nmi_exit();
+}
+
+void stop_nmi(void)
+{
+	ignore_nmis++;
+}
+
+void restart_nmi(void)
+{
+	ignore_nmis--;
+}
+
+/* reset the back-to-back NMI logic */
+void local_touch_nmi(void)
+{
+	__this_cpu_write(last_nmi_rip, 0);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/pci-dma.c linux-libre-3.2-gnu1/arch/x86/kernel/pci-dma.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-debug.h>
 #include <linux/dmar.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
@@ -117,8 +118,8 @@ again:
 }
 
 /*
- * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
- * documentation.
+ * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel
+ * parameter documentation.
  */
 static __init int iommu_setup(char *p)
 {
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/probe_roms.c linux-libre-3.2-gnu1/arch/x86/kernel/probe_roms.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/probe_roms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/probe_roms.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,9 @@
 #include <linux/dmi.h>
 #include <linux/pfn.h>
 #include <linux/pci.h>
-#include <asm/pci-direct.h>
-
+#include <linux/export.h>
 
+#include <asm/pci-direct.h>
 #include <asm/e820.h>
 #include <asm/mmzone.h>
 #include <asm/setup.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/process_32.c linux-libre-3.2-gnu1/arch/x86/kernel/process_32.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/process_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/process_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
+#include <asm/nmi.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -107,6 +108,7 @@ void cpu_idle(void)
 			if (cpu_is_offline(cpu))
 				play_dead();
 
+			local_touch_nmi();
 			local_irq_disable();
 			/* Don't trace irqs off for idle */
 			stop_critical_timings();
@@ -262,7 +264,7 @@ EXPORT_SYMBOL_GPL(start_thread);
 
 
 /*
- *	switch_to(x,yn) should switch tasks from x to y.
+ *	switch_to(x,y) should switch tasks from x to y.
  *
  * We fsave/fwait so that an exception goes off at the right time
  * (as a call from the fsave or fwait in effect) rather than to
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/process_64.c linux-libre-3.2-gnu1/arch/x86/kernel/process_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/process_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/process_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,7 @@
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
+#include <asm/nmi.h>
 
 asmlinkage extern void ret_from_fork(void);
 
@@ -133,6 +134,7 @@ void cpu_idle(void)
 			 * from here on, until they go to idle.
 			 * Otherwise, idle callbacks can misfire.
 			 */
+			local_touch_nmi();
 			local_irq_disable();
 			enter_idle();
 			/* Don't trace irqs off for idle */
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/process.c linux-libre-3.2-gnu1/arch/x86/kernel/process.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,7 @@ void free_thread_xstate(struct task_stru
 void free_thread_info(struct thread_info *ti)
 {
 	free_thread_xstate(ti->task);
-	free_pages((unsigned long)ti, get_order(THREAD_SIZE));
+	free_pages((unsigned long)ti, THREAD_ORDER);
 }
 
 void arch_task_cache_init(void)
@@ -403,6 +403,14 @@ void default_idle(void)
 EXPORT_SYMBOL(default_idle);
 #endif
 
+bool set_pm_idle_to_default(void)
+{
+	bool ret = !!pm_idle;
+
+	pm_idle = default_idle;
+
+	return ret;
+}
 void stop_this_cpu(void *dummy)
 {
 	local_irq_disable();
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/quirks.c linux-libre-3.2-gnu1/arch/x86/kernel/quirks.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/quirks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/quirks.c	2012-01-04 18:55:44.000000000 -0500
@@ -553,4 +553,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AM
 			quirk_amd_nb_node);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
 			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5,
+			quirk_amd_nb_node);
+
 #endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/reboot.c linux-libre-3.2-gnu1/arch/x86/kernel/reboot.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/reboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/reboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@ __setup("reboot=", reboot_setup);
  */
 
 /*
- * Some machines require the "reboot=b"  commandline option,
+ * Some machines require the "reboot=b" or "reboot=k"  commandline options,
  * this quirk makes that automatic.
  */
 static int __init set_bios_reboot(const struct dmi_system_id *d)
@@ -136,6 +136,15 @@ static int __init set_bios_reboot(const
 	return 0;
 }
 
+static int __init set_kbd_reboot(const struct dmi_system_id *d)
+{
+	if (reboot_type != BOOT_KBD) {
+		reboot_type = BOOT_KBD;
+		printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident);
+	}
+	return 0;
+}
+
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
 	{	/* Handle problems with rebooting on Dell E520's */
 		.callback = set_bios_reboot,
@@ -295,7 +304,7 @@ static struct dmi_system_id __initdata r
 		},
 	},
 	{ /* Handle reboot issue on Acer Aspire one */
-		.callback = set_bios_reboot,
+		.callback = set_kbd_reboot,
 		.ident = "Acer Aspire One A110",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -443,6 +452,14 @@ static struct dmi_system_id __initdata p
 			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
 		},
 	},
+	{	/* Handle problems with rebooting on the OptiPlex 990. */
+		.callback = set_pci_reboot,
+		.ident = "Dell OptiPlex 990",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
+		},
+	},
 	{ }
 };
 
@@ -464,7 +481,7 @@ static inline void kb_wait(void)
 	}
 }
 
-static void vmxoff_nmi(int cpu, struct die_args *args)
+static void vmxoff_nmi(int cpu, struct pt_regs *regs)
 {
 	cpu_emergency_vmxoff();
 }
@@ -736,14 +753,10 @@ static nmi_shootdown_cb shootdown_callba
 
 static atomic_t waiting_for_crash_ipi;
 
-static int crash_nmi_callback(struct notifier_block *self,
-			unsigned long val, void *data)
+static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
 {
 	int cpu;
 
-	if (val != DIE_NMI)
-		return NOTIFY_OK;
-
 	cpu = raw_smp_processor_id();
 
 	/* Don't do anything if this handler is invoked on crashing cpu.
@@ -751,10 +764,10 @@ static int crash_nmi_callback(struct not
 	 * an NMI if system was initially booted with nmi_watchdog parameter.
 	 */
 	if (cpu == crashing_cpu)
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	local_irq_disable();
 
-	shootdown_callback(cpu, (struct die_args *)data);
+	shootdown_callback(cpu, regs);
 
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
@@ -762,7 +775,7 @@ static int crash_nmi_callback(struct not
 	for (;;)
 		cpu_relax();
 
-	return 1;
+	return NMI_HANDLED;
 }
 
 static void smp_send_nmi_allbutself(void)
@@ -770,12 +783,6 @@ static void smp_send_nmi_allbutself(void
 	apic->send_IPI_allbutself(NMI_VECTOR);
 }
 
-static struct notifier_block crash_nmi_nb = {
-	.notifier_call = crash_nmi_callback,
-	/* we want to be the first one called */
-	.priority = NMI_LOCAL_HIGH_PRIOR+1,
-};
-
 /* Halt all other CPUs, calling the specified function on each of them
  *
  * This function can be used to halt all other CPUs on crash
@@ -794,7 +801,8 @@ void nmi_shootdown_cpus(nmi_shootdown_cb
 
 	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
 	/* Would it be better to replace the trap vector here? */
-	if (register_die_notifier(&crash_nmi_nb))
+	if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
+				 NMI_FLAG_FIRST, "crash"))
 		return;		/* return what? */
 	/* Ensure the new callback function is set before sending
 	 * out the NMI
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/rtc.c linux-libre-3.2-gnu1/arch/x86/kernel/rtc.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,12 +5,14 @@
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
 #include <linux/bcd.h>
+#include <linux/export.h>
 #include <linux/pnp.h>
 #include <linux/of.h>
 
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
 #include <asm/time.h>
+#include <asm/mrst.h>
 
 #ifdef CONFIG_X86_32
 /*
@@ -241,6 +243,10 @@ static __init int add_rtc_cmos(void)
 	if (of_have_populated_dt())
 		return 0;
 
+	/* Intel MID platforms don't have ioport rtc */
+	if (mrst_identify_cpu())
+		return -ENODEV;
+
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
 		 "registered platform RTC device (no PNP device found)\n");
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/setup.c linux-libre-3.2-gnu1/arch/x86/kernel/setup.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -1045,6 +1045,8 @@ void __init setup_arch(char **cmdline_p)
 
 	x86_init.timers.wallclock_init();
 
+	x86_platform.wallclock_init();
+
 	mcheck_init();
 
 	arch_init_ideal_nops();
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/smp.c linux-libre-3.2-gnu1/arch/x86/kernel/smp.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/cache.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/syscall_table_32.S linux-libre-3.2-gnu1/arch/x86/kernel/syscall_table_32.S
--- linux-libre-3.1-gnu1/arch/x86/kernel/syscall_table_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/syscall_table_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -346,3 +346,5 @@ ENTRY(sys_call_table)
 	.long sys_syncfs
 	.long sys_sendmmsg		/* 345 */
 	.long sys_setns
+	.long sys_process_vm_readv
+	.long sys_process_vm_writev
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/sys_x86_64.c linux-libre-3.2-gnu1/arch/x86/kernel/sys_x86_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/sys_x86_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/sys_x86_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,73 @@
 #include <linux/personality.h>
 #include <linux/random.h>
 #include <linux/uaccess.h>
+#include <linux/elf.h>
 
 #include <asm/ia32.h>
 #include <asm/syscalls.h>
 
+/*
+ * Align a virtual address to avoid aliasing in the I$ on AMD F15h.
+ *
+ * @flags denotes the allocation direction - bottomup or topdown -
+ * or vDSO; see call sites below.
+ */
+unsigned long align_addr(unsigned long addr, struct file *filp,
+			 enum align_flags flags)
+{
+	unsigned long tmp_addr;
+
+	/* handle 32- and 64-bit case with a single conditional */
+	if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
+		return addr;
+
+	if (!(current->flags & PF_RANDOMIZE))
+		return addr;
+
+	if (!((flags & ALIGN_VDSO) || filp))
+		return addr;
+
+	tmp_addr = addr;
+
+	/*
+	 * We need an address which is <= than the original
+	 * one only when in topdown direction.
+	 */
+	if (!(flags & ALIGN_TOPDOWN))
+		tmp_addr += va_align.mask;
+
+	tmp_addr &= ~va_align.mask;
+
+	return tmp_addr;
+}
+
+static int __init control_va_addr_alignment(char *str)
+{
+	/* guard against enabling this on other CPU families */
+	if (va_align.flags < 0)
+		return 1;
+
+	if (*str == 0)
+		return 1;
+
+	if (*str == '=')
+		str++;
+
+	if (!strcmp(str, "32"))
+		va_align.flags = ALIGN_VA_32;
+	else if (!strcmp(str, "64"))
+		va_align.flags = ALIGN_VA_64;
+	else if (!strcmp(str, "off"))
+		va_align.flags = 0;
+	else if (!strcmp(str, "on"))
+		va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
+	else
+		return 0;
+
+	return 1;
+}
+__setup("align_va_addr", control_va_addr_alignment);
+
 SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
 		unsigned long, fd, unsigned long, off)
@@ -92,6 +155,9 @@ arch_get_unmapped_area(struct file *filp
 	start_addr = addr;
 
 full_search:
+
+	addr = align_addr(addr, filp, 0);
+
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
 		if (end - len < addr) {
@@ -117,6 +183,7 @@ full_search:
 			mm->cached_hole_size = vma->vm_start - addr;
 
 		addr = vma->vm_end;
+		addr = align_addr(addr, filp, 0);
 	}
 }
 
@@ -161,10 +228,13 @@ arch_get_unmapped_area_topdown(struct fi
 
 	/* make sure it can fit in the remaining address space */
 	if (addr > len) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start)
+		unsigned long tmp_addr = align_addr(addr - len, filp,
+						    ALIGN_TOPDOWN);
+
+		vma = find_vma(mm, tmp_addr);
+		if (!vma || tmp_addr + len <= vma->vm_start)
 			/* remember the address as a hint for next time */
-			return mm->free_area_cache = addr-len;
+			return mm->free_area_cache = tmp_addr;
 	}
 
 	if (mm->mmap_base < len)
@@ -173,6 +243,8 @@ arch_get_unmapped_area_topdown(struct fi
 	addr = mm->mmap_base-len;
 
 	do {
+		addr = align_addr(addr, filp, ALIGN_TOPDOWN);
+
 		/*
 		 * Lookup failure means no vma is above this address,
 		 * else if new region fits below vma->vm_start,
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/tboot.c linux-libre-3.2-gnu1/arch/x86/kernel/tboot.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/tboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/tboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/dma_remapping.h>
 #include <linux/init_task.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/time.c linux-libre-3.2-gnu1/arch/x86/kernel/time.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/i8253.h>
 #include <linux/time.h>
+#include <linux/export.h>
 #include <linux/mca.h>
 
 #include <asm/vsyscall.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/topology.c linux-libre-3.2-gnu1/arch/x86/kernel/topology.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
  * Send feedback to <colpatch@us.ibm.com>
  */
 #include <linux/nodemask.h>
+#include <linux/export.h>
 #include <linux/mmzone.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/traps.c linux-libre-3.2-gnu1/arch/x86/kernel/traps.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,15 +81,6 @@ gate_desc idt_table[NR_VECTORS] __page_a
 DECLARE_BITMAP(used_vectors, NR_VECTORS);
 EXPORT_SYMBOL_GPL(used_vectors);
 
-static int ignore_nmis;
-
-int unknown_nmi_panic;
-/*
- * Prevent NMI reason port (0x61) being accessed simultaneously, can
- * only be used in NMI handler.
- */
-static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
-
 static inline void conditional_sti(struct pt_regs *regs)
 {
 	if (regs->flags & X86_EFLAGS_IF)
@@ -307,152 +298,6 @@ gp_in_kernel:
 	die("general protection fault", regs, error_code);
 }
 
-static int __init setup_unknown_nmi_panic(char *str)
-{
-	unknown_nmi_panic = 1;
-	return 1;
-}
-__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
-
-static notrace __kprobes void
-pci_serr_error(unsigned char reason, struct pt_regs *regs)
-{
-	pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-
-	/*
-	 * On some machines, PCI SERR line is used to report memory
-	 * errors. EDAC makes use of it.
-	 */
-#if defined(CONFIG_EDAC)
-	if (edac_handler_set()) {
-		edac_atomic_assert_error();
-		return;
-	}
-#endif
-
-	if (panic_on_unrecovered_nmi)
-		panic("NMI: Not continuing");
-
-	pr_emerg("Dazed and confused, but trying to continue\n");
-
-	/* Clear and disable the PCI SERR error line. */
-	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
-	outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-io_check_error(unsigned char reason, struct pt_regs *regs)
-{
-	unsigned long i;
-
-	pr_emerg(
-	"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-	show_registers(regs);
-
-	if (panic_on_io_nmi)
-		panic("NMI IOCK error: Not continuing");
-
-	/* Re-enable the IOCK line, wait for a few seconds */
-	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
-	outb(reason, NMI_REASON_PORT);
-
-	i = 20000;
-	while (--i) {
-		touch_nmi_watchdog();
-		udelay(100);
-	}
-
-	reason &= ~NMI_REASON_CLEAR_IOCHK;
-	outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
-{
-	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
-			NOTIFY_STOP)
-		return;
-#ifdef CONFIG_MCA
-	/*
-	 * Might actually be able to figure out what the guilty party
-	 * is:
-	 */
-	if (MCA_bus) {
-		mca_handle_nmi();
-		return;
-	}
-#endif
-	pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-
-	pr_emerg("Do you have a strange power saving mode enabled?\n");
-	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
-		panic("NMI: Not continuing");
-
-	pr_emerg("Dazed and confused, but trying to continue\n");
-}
-
-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
-{
-	unsigned char reason = 0;
-
-	/*
-	 * CPU-specific NMI must be processed before non-CPU-specific
-	 * NMI, otherwise we may lose it, because the CPU-specific
-	 * NMI can not be detected/processed on other CPUs.
-	 */
-	if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
-		return;
-
-	/* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
-	raw_spin_lock(&nmi_reason_lock);
-	reason = get_nmi_reason();
-
-	if (reason & NMI_REASON_MASK) {
-		if (reason & NMI_REASON_SERR)
-			pci_serr_error(reason, regs);
-		else if (reason & NMI_REASON_IOCHK)
-			io_check_error(reason, regs);
-#ifdef CONFIG_X86_32
-		/*
-		 * Reassert NMI in case it became active
-		 * meanwhile as it's edge-triggered:
-		 */
-		reassert_nmi();
-#endif
-		raw_spin_unlock(&nmi_reason_lock);
-		return;
-	}
-	raw_spin_unlock(&nmi_reason_lock);
-
-	unknown_nmi_error(reason, regs);
-}
-
-dotraplinkage notrace __kprobes void
-do_nmi(struct pt_regs *regs, long error_code)
-{
-	nmi_enter();
-
-	inc_irq_stat(__nmi_count);
-
-	if (!ignore_nmis)
-		default_do_nmi(regs);
-
-	nmi_exit();
-}
-
-void stop_nmi(void)
-{
-	ignore_nmis++;
-}
-
-void restart_nmi(void)
-{
-	ignore_nmis--;
-}
-
 /* May run on IST stack. */
 dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/vsyscall_64.c linux-libre-3.2-gnu1/arch/x86/kernel/vsyscall_64.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/vsyscall_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/vsyscall_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/seqlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
+#include <linux/topology.h>
 #include <linux/clocksource.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/kernel/x86_init.c linux-libre-3.2-gnu1/arch/x86/kernel/x86_init.c
--- linux-libre-3.1-gnu1/arch/x86/kernel/x86_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kernel/x86_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,14 @@
 #include <asm/pat.h>
 #include <asm/tsc.h>
 #include <asm/iommu.h>
+#include <asm/mach_traps.h>
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -97,11 +99,13 @@ static int default_i8042_detect(void) {
 
 struct x86_platform_ops x86_platform = {
 	.calibrate_tsc			= native_calibrate_tsc,
+	.wallclock_init			= wallclock_init_noop,
 	.get_wallclock			= mach_get_cmos_time,
 	.set_wallclock			= mach_set_rtc_mmss,
 	.iommu_shutdown			= iommu_shutdown_noop,
 	.is_untracked_pat_range		= is_ISA_range,
 	.nmi_init			= default_nmi_init,
+	.get_nmi_reason			= default_get_nmi_reason,
 	.i8042_detect			= default_i8042_detect
 };
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/emulate.c linux-libre-3.2-gnu1/arch/x86/kvm/emulate.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/emulate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/emulate.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,39 @@
 #include "tss.h"
 
 /*
+ * Operand types
+ */
+#define OpNone             0ull
+#define OpImplicit         1ull  /* No generic decode */
+#define OpReg              2ull  /* Register */
+#define OpMem              3ull  /* Memory */
+#define OpAcc              4ull  /* Accumulator: AL/AX/EAX/RAX */
+#define OpDI               5ull  /* ES:DI/EDI/RDI */
+#define OpMem64            6ull  /* Memory, 64-bit */
+#define OpImmUByte         7ull  /* Zero-extended 8-bit immediate */
+#define OpDX               8ull  /* DX register */
+#define OpCL               9ull  /* CL register (for shifts) */
+#define OpImmByte         10ull  /* 8-bit sign extended immediate */
+#define OpOne             11ull  /* Implied 1 */
+#define OpImm             12ull  /* Sign extended immediate */
+#define OpMem16           13ull  /* Memory operand (16-bit). */
+#define OpMem32           14ull  /* Memory operand (32-bit). */
+#define OpImmU            15ull  /* Immediate operand, zero extended */
+#define OpSI              16ull  /* SI/ESI/RSI */
+#define OpImmFAddr        17ull  /* Immediate far address */
+#define OpMemFAddr        18ull  /* Far address in memory */
+#define OpImmU16          19ull  /* Immediate operand, 16 bits, zero extended */
+#define OpES              20ull  /* ES */
+#define OpCS              21ull  /* CS */
+#define OpSS              22ull  /* SS */
+#define OpDS              23ull  /* DS */
+#define OpFS              24ull  /* FS */
+#define OpGS              25ull  /* GS */
+
+#define OpBits             5  /* Width of operand field */
+#define OpMask             ((1ull << OpBits) - 1)
+
+/*
  * Opcode effective-address decode tables.
  * Note that we only emulate instructions that have at least one memory
  * operand (excluding implicit stack references). We assume that stack
@@ -40,37 +73,35 @@
 /* Operand sizes: 8-bit operands or specified/overridden size. */
 #define ByteOp      (1<<0)	/* 8-bit operands. */
 /* Destination operand type. */
-#define ImplicitOps (1<<1)	/* Implicit in opcode. No generic decode. */
-#define DstReg      (2<<1)	/* Register operand. */
-#define DstMem      (3<<1)	/* Memory operand. */
-#define DstAcc      (4<<1)	/* Destination Accumulator */
-#define DstDI       (5<<1)	/* Destination is in ES:(E)DI */
-#define DstMem64    (6<<1)	/* 64bit memory operand */
-#define DstImmUByte (7<<1)	/* 8-bit unsigned immediate operand */
-#define DstDX       (8<<1)	/* Destination is in DX register */
-#define DstMask     (0xf<<1)
+#define DstShift    1
+#define ImplicitOps (OpImplicit << DstShift)
+#define DstReg      (OpReg << DstShift)
+#define DstMem      (OpMem << DstShift)
+#define DstAcc      (OpAcc << DstShift)
+#define DstDI       (OpDI << DstShift)
+#define DstMem64    (OpMem64 << DstShift)
+#define DstImmUByte (OpImmUByte << DstShift)
+#define DstDX       (OpDX << DstShift)
+#define DstMask     (OpMask << DstShift)
 /* Source operand type. */
-#define SrcNone     (0<<5)	/* No source operand. */
-#define SrcReg      (1<<5)	/* Register operand. */
-#define SrcMem      (2<<5)	/* Memory operand. */
-#define SrcMem16    (3<<5)	/* Memory operand (16-bit). */
-#define SrcMem32    (4<<5)	/* Memory operand (32-bit). */
-#define SrcImm      (5<<5)	/* Immediate operand. */
-#define SrcImmByte  (6<<5)	/* 8-bit sign-extended immediate operand. */
-#define SrcOne      (7<<5)	/* Implied '1' */
-#define SrcImmUByte (8<<5)      /* 8-bit unsigned immediate operand. */
-#define SrcImmU     (9<<5)      /* Immediate operand, unsigned */
-#define SrcSI       (0xa<<5)	/* Source is in the DS:RSI */
-#define SrcImmFAddr (0xb<<5)	/* Source is immediate far address */
-#define SrcMemFAddr (0xc<<5)	/* Source is far address in memory */
-#define SrcAcc      (0xd<<5)	/* Source Accumulator */
-#define SrcImmU16   (0xe<<5)    /* Immediate operand, unsigned, 16 bits */
-#define SrcDX       (0xf<<5)	/* Source is in DX register */
-#define SrcMask     (0xf<<5)
-/* Generic ModRM decode. */
-#define ModRM       (1<<9)
-/* Destination is only written; never read. */
-#define Mov         (1<<10)
+#define SrcShift    6
+#define SrcNone     (OpNone << SrcShift)
+#define SrcReg      (OpReg << SrcShift)
+#define SrcMem      (OpMem << SrcShift)
+#define SrcMem16    (OpMem16 << SrcShift)
+#define SrcMem32    (OpMem32 << SrcShift)
+#define SrcImm      (OpImm << SrcShift)
+#define SrcImmByte  (OpImmByte << SrcShift)
+#define SrcOne      (OpOne << SrcShift)
+#define SrcImmUByte (OpImmUByte << SrcShift)
+#define SrcImmU     (OpImmU << SrcShift)
+#define SrcSI       (OpSI << SrcShift)
+#define SrcImmFAddr (OpImmFAddr << SrcShift)
+#define SrcMemFAddr (OpMemFAddr << SrcShift)
+#define SrcAcc      (OpAcc << SrcShift)
+#define SrcImmU16   (OpImmU16 << SrcShift)
+#define SrcDX       (OpDX << SrcShift)
+#define SrcMask     (OpMask << SrcShift)
 #define BitOp       (1<<11)
 #define MemAbs      (1<<12)      /* Memory operand is absolute displacement */
 #define String      (1<<13)     /* String instruction (rep capable) */
@@ -81,6 +112,10 @@
 #define Prefix      (3<<15)     /* Instruction varies with 66/f2/f3 prefix */
 #define RMExt       (4<<15)     /* Opcode extension in ModRM r/m if mod == 3 */
 #define Sse         (1<<18)     /* SSE Vector instruction */
+/* Generic ModRM decode. */
+#define ModRM       (1<<19)
+/* Destination is only written; never read. */
+#define Mov         (1<<20)
 /* Misc flags */
 #define Prot        (1<<21) /* instruction generates #UD if not in prot-mode */
 #define VendorSpecific (1<<22) /* Vendor specific instruction */
@@ -91,12 +126,19 @@
 #define Priv        (1<<27) /* instruction generates #GP if current CPL != 0 */
 #define No64	    (1<<28)
 /* Source 2 operand type */
-#define Src2None    (0<<29)
-#define Src2CL      (1<<29)
-#define Src2ImmByte (2<<29)
-#define Src2One     (3<<29)
-#define Src2Imm     (4<<29)
-#define Src2Mask    (7<<29)
+#define Src2Shift   (29)
+#define Src2None    (OpNone << Src2Shift)
+#define Src2CL      (OpCL << Src2Shift)
+#define Src2ImmByte (OpImmByte << Src2Shift)
+#define Src2One     (OpOne << Src2Shift)
+#define Src2Imm     (OpImm << Src2Shift)
+#define Src2ES      (OpES << Src2Shift)
+#define Src2CS      (OpCS << Src2Shift)
+#define Src2SS      (OpSS << Src2Shift)
+#define Src2DS      (OpDS << Src2Shift)
+#define Src2FS      (OpFS << Src2Shift)
+#define Src2GS      (OpGS << Src2Shift)
+#define Src2Mask    (OpMask << Src2Shift)
 
 #define X2(x...) x, x
 #define X3(x...) X2(x), x
@@ -108,8 +150,8 @@
 #define X16(x...) X8(x), X8(x)
 
 struct opcode {
-	u32 flags;
-	u8 intercept;
+	u64 flags : 56;
+	u64 intercept : 8;
 	union {
 		int (*execute)(struct x86_emulate_ctxt *ctxt);
 		struct opcode *group;
@@ -205,105 +247,100 @@ struct gprefix {
 #define ON64(x)
 #endif
 
-#define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix, _dsttype) \
+#define ____emulate_2op(ctxt, _op, _x, _y, _suffix, _dsttype)	\
 	do {								\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "4", "2")			\
 			_op _suffix " %"_x"3,%1; "			\
 			_POST_EFLAGS("0", "4", "2")			\
-			: "=m" (_eflags), "+q" (*(_dsttype*)&(_dst).val),\
+			: "=m" ((ctxt)->eflags),			\
+			  "+q" (*(_dsttype*)&(ctxt)->dst.val),		\
 			  "=&r" (_tmp)					\
-			: _y ((_src).val), "i" (EFLAGS_MASK));		\
+			: _y ((ctxt)->src.val), "i" (EFLAGS_MASK));	\
 	} while (0)
 
 
 /* Raw emulation: instruction has two explicit operands. */
-#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op_nobyte(ctxt,_op,_wx,_wy,_lx,_ly,_qx,_qy)		\
 	do {								\
 		unsigned long _tmp;					\
 									\
-		switch ((_dst).bytes) {					\
+		switch ((ctxt)->dst.bytes) {				\
 		case 2:							\
-			____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w",u16);\
+			____emulate_2op(ctxt,_op,_wx,_wy,"w",u16);	\
 			break;						\
 		case 4:							\
-			____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l",u32);\
+			____emulate_2op(ctxt,_op,_lx,_ly,"l",u32);	\
 			break;						\
 		case 8:							\
-			ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q",u64)); \
+			ON64(____emulate_2op(ctxt,_op,_qx,_qy,"q",u64)); \
 			break;						\
 		}							\
 	} while (0)
 
-#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op(ctxt,_op,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy)		     \
 	do {								     \
 		unsigned long _tmp;					     \
-		switch ((_dst).bytes) {				             \
+		switch ((ctxt)->dst.bytes) {				     \
 		case 1:							     \
-			____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b",u8); \
+			____emulate_2op(ctxt,_op,_bx,_by,"b",u8);	     \
 			break;						     \
 		default:						     \
-			__emulate_2op_nobyte(_op, _src, _dst, _eflags,	     \
+			__emulate_2op_nobyte(ctxt, _op,			     \
 					     _wx, _wy, _lx, _ly, _qx, _qy);  \
 			break;						     \
 		}							     \
 	} while (0)
 
 /* Source operand is byte-sized and may be restricted to just %cl. */
-#define emulate_2op_SrcB(_op, _src, _dst, _eflags)                      \
-	__emulate_2op(_op, _src, _dst, _eflags,				\
-		      "b", "c", "b", "c", "b", "c", "b", "c")
+#define emulate_2op_SrcB(ctxt, _op)					\
+	__emulate_2op(ctxt, _op, "b", "c", "b", "c", "b", "c", "b", "c")
 
 /* Source operand is byte, word, long or quad sized. */
-#define emulate_2op_SrcV(_op, _src, _dst, _eflags)                      \
-	__emulate_2op(_op, _src, _dst, _eflags,				\
-		      "b", "q", "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV(ctxt, _op)					\
+	__emulate_2op(ctxt, _op, "b", "q", "w", "r", _LO32, "r", "", "r")
 
 /* Source operand is word, long or quad sized. */
-#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags)               \
-	__emulate_2op_nobyte(_op, _src, _dst, _eflags,			\
-			     "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV_nobyte(ctxt, _op)				\
+	__emulate_2op_nobyte(ctxt, _op, "w", "r", _LO32, "r", "", "r")
 
 /* Instruction has three operands and one operand is stored in ECX register */
-#define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type)	\
+#define __emulate_2op_cl(ctxt, _op, _suffix, _type)		\
 	do {								\
 		unsigned long _tmp;					\
-		_type _clv  = (_cl).val;				\
-		_type _srcv = (_src).val;				\
-		_type _dstv = (_dst).val;				\
+		_type _clv  = (ctxt)->src2.val;				\
+		_type _srcv = (ctxt)->src.val;				\
+		_type _dstv = (ctxt)->dst.val;				\
 									\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "5", "2")			\
 			_op _suffix " %4,%1 \n"				\
 			_POST_EFLAGS("0", "5", "2")			\
-			: "=m" (_eflags), "+r" (_dstv), "=&r" (_tmp)	\
+			: "=m" ((ctxt)->eflags), "+r" (_dstv), "=&r" (_tmp) \
 			: "c" (_clv) , "r" (_srcv), "i" (EFLAGS_MASK)	\
 			);						\
 									\
-		(_cl).val  = (unsigned long) _clv;			\
-		(_src).val = (unsigned long) _srcv;			\
-		(_dst).val = (unsigned long) _dstv;			\
+		(ctxt)->src2.val  = (unsigned long) _clv;		\
+		(ctxt)->src2.val = (unsigned long) _srcv;		\
+		(ctxt)->dst.val = (unsigned long) _dstv;		\
 	} while (0)
 
-#define emulate_2op_cl(_op, _cl, _src, _dst, _eflags)			\
+#define emulate_2op_cl(ctxt, _op)					\
 	do {								\
-		switch ((_dst).bytes) {					\
+		switch ((ctxt)->dst.bytes) {				\
 		case 2:							\
-			__emulate_2op_cl(_op, _cl, _src, _dst, _eflags,	\
-					 "w", unsigned short);         	\
+			__emulate_2op_cl(ctxt, _op, "w", u16);		\
 			break;						\
 		case 4:							\
-			__emulate_2op_cl(_op, _cl, _src, _dst, _eflags,	\
-					 "l", unsigned int);           	\
+			__emulate_2op_cl(ctxt, _op, "l", u32);		\
 			break;						\
 		case 8:							\
-			ON64(__emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
-					      "q", unsigned long));	\
+			ON64(__emulate_2op_cl(ctxt, _op, "q", ulong));	\
 			break;						\
 		}							\
 	} while (0)
 
-#define __emulate_1op(_op, _dst, _eflags, _suffix)			\
+#define __emulate_1op(ctxt, _op, _suffix)				\
 	do {								\
 		unsigned long _tmp;					\
 									\
@@ -311,39 +348,27 @@ struct gprefix {
 			_PRE_EFLAGS("0", "3", "2")			\
 			_op _suffix " %1; "				\
 			_POST_EFLAGS("0", "3", "2")			\
-			: "=m" (_eflags), "+m" ((_dst).val),		\
+			: "=m" ((ctxt)->eflags), "+m" ((ctxt)->dst.val), \
 			  "=&r" (_tmp)					\
 			: "i" (EFLAGS_MASK));				\
 	} while (0)
 
 /* Instruction has only one explicit operand (no source operand). */
-#define emulate_1op(_op, _dst, _eflags)                                    \
+#define emulate_1op(ctxt, _op)						\
 	do {								\
-		switch ((_dst).bytes) {				        \
-		case 1:	__emulate_1op(_op, _dst, _eflags, "b"); break;	\
-		case 2:	__emulate_1op(_op, _dst, _eflags, "w"); break;	\
-		case 4:	__emulate_1op(_op, _dst, _eflags, "l"); break;	\
-		case 8:	ON64(__emulate_1op(_op, _dst, _eflags, "q")); break; \
+		switch ((ctxt)->dst.bytes) {				\
+		case 1:	__emulate_1op(ctxt, _op, "b"); break;		\
+		case 2:	__emulate_1op(ctxt, _op, "w"); break;		\
+		case 4:	__emulate_1op(ctxt, _op, "l"); break;		\
+		case 8:	ON64(__emulate_1op(ctxt, _op, "q")); break;	\
 		}							\
 	} while (0)
 
-#define __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, _suffix)		\
-	do {								\
-		unsigned long _tmp;					\
-									\
-		__asm__ __volatile__ (					\
-			_PRE_EFLAGS("0", "4", "1")			\
-			_op _suffix " %5; "				\
-			_POST_EFLAGS("0", "4", "1")			\
-			: "=m" (_eflags), "=&r" (_tmp),			\
-			  "+a" (_rax), "+d" (_rdx)			\
-			: "i" (EFLAGS_MASK), "m" ((_src).val),		\
-			  "a" (_rax), "d" (_rdx));			\
-	} while (0)
-
-#define __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _suffix, _ex) \
+#define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex)			\
 	do {								\
 		unsigned long _tmp;					\
+		ulong *rax = &(ctxt)->regs[VCPU_REGS_RAX];		\
+		ulong *rdx = &(ctxt)->regs[VCPU_REGS_RDX];		\
 									\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "5", "1")			\
@@ -356,53 +381,27 @@ struct gprefix {
 			"jmp 2b \n\t"					\
 			".popsection \n\t"				\
 			_ASM_EXTABLE(1b, 3b)				\
-			: "=m" (_eflags), "=&r" (_tmp),			\
-			  "+a" (_rax), "+d" (_rdx), "+qm"(_ex)		\
-			: "i" (EFLAGS_MASK), "m" ((_src).val),		\
-			  "a" (_rax), "d" (_rdx));			\
+			: "=m" ((ctxt)->eflags), "=&r" (_tmp),		\
+			  "+a" (*rax), "+d" (*rdx), "+qm"(_ex)		\
+			: "i" (EFLAGS_MASK), "m" ((ctxt)->src.val),	\
+			  "a" (*rax), "d" (*rdx));			\
 	} while (0)
 
 /* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
-#define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags)		\
-	do {								\
-		switch((_src).bytes) {					\
-		case 1:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "b");		\
-			break;						\
-		case 2:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "w");		\
-			break;						\
-		case 4:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "l");		\
-			break;						\
-		case 8:							\
-			ON64(__emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
-						   _eflags, "q"));	\
-			break;						\
-		}							\
-	} while (0)
-
-#define emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _ex)	\
+#define emulate_1op_rax_rdx(ctxt, _op, _ex)	\
 	do {								\
-		switch((_src).bytes) {					\
+		switch((ctxt)->src.bytes) {				\
 		case 1:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx,	\
-						 _eflags, "b", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "b", _ex);	\
 			break;						\
 		case 2:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "w", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "w", _ex);	\
 			break;						\
 		case 4:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "l", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "l", _ex);	\
 			break;						\
 		case 8: ON64(						\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "q", _ex));	\
+			__emulate_1op_rax_rdx(ctxt, _op, "q", _ex));	\
 			break;						\
 		}							\
 	} while (0)
@@ -651,41 +650,50 @@ static int segmented_read_std(struct x86
 	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
-static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt,
-			      unsigned long eip, u8 *dest)
+/*
+ * Fetch the next byte of the instruction being emulated which is pointed to
+ * by ctxt->_eip, then increment ctxt->_eip.
+ *
+ * Also prefetch the remaining bytes of the instruction without crossing page
+ * boundary if they are not in fetch_cache yet.
+ */
+static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt, u8 *dest)
 {
 	struct fetch_cache *fc = &ctxt->fetch;
 	int rc;
 	int size, cur_size;
 
-	if (eip == fc->end) {
+	if (ctxt->_eip == fc->end) {
 		unsigned long linear;
-		struct segmented_address addr = { .seg=VCPU_SREG_CS, .ea=eip};
+		struct segmented_address addr = { .seg = VCPU_SREG_CS,
+						  .ea  = ctxt->_eip };
 		cur_size = fc->end - fc->start;
-		size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
+		size = min(15UL - cur_size,
+			   PAGE_SIZE - offset_in_page(ctxt->_eip));
 		rc = __linearize(ctxt, addr, size, false, true, &linear);
-		if (rc != X86EMUL_CONTINUE)
+		if (unlikely(rc != X86EMUL_CONTINUE))
 			return rc;
 		rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
 				      size, &ctxt->exception);
-		if (rc != X86EMUL_CONTINUE)
+		if (unlikely(rc != X86EMUL_CONTINUE))
 			return rc;
 		fc->end += size;
 	}
-	*dest = fc->data[eip - fc->start];
+	*dest = fc->data[ctxt->_eip - fc->start];
+	ctxt->_eip++;
 	return X86EMUL_CONTINUE;
 }
 
 static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
-			 unsigned long eip, void *dest, unsigned size)
+			 void *dest, unsigned size)
 {
 	int rc;
 
 	/* x86 instructions are limited to 15 bytes. */
-	if (eip + size - ctxt->eip > 15)
+	if (unlikely(ctxt->_eip + size - ctxt->eip > 15))
 		return X86EMUL_UNHANDLEABLE;
 	while (size--) {
-		rc = do_insn_fetch_byte(ctxt, eip++, dest++);
+		rc = do_insn_fetch_byte(ctxt, dest++);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 	}
@@ -693,20 +701,18 @@ static int do_insn_fetch(struct x86_emul
 }
 
 /* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip)					\
+#define insn_fetch(_type, _ctxt)					\
 ({	unsigned long _x;						\
-	rc = do_insn_fetch(ctxt, (_eip), &_x, (_size));			\
+	rc = do_insn_fetch(_ctxt, &_x, sizeof(_type));			\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
-	(_eip) += (_size);						\
 	(_type)_x;							\
 })
 
-#define insn_fetch_arr(_arr, _size, _eip)				\
-({	rc = do_insn_fetch(ctxt, (_eip), _arr, (_size));		\
+#define insn_fetch_arr(_arr, _size, _ctxt)				\
+({	rc = do_insn_fetch(_ctxt, _arr, (_size));			\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
-	(_eip) += (_size);						\
 })
 
 /*
@@ -894,7 +900,7 @@ static int decode_modrm(struct x86_emula
 		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
 	}
 
-	ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+	ctxt->modrm = insn_fetch(u8, ctxt);
 	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
 	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
 	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
@@ -928,13 +934,13 @@ static int decode_modrm(struct x86_emula
 		switch (ctxt->modrm_mod) {
 		case 0:
 			if (ctxt->modrm_rm == 6)
-				modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+				modrm_ea += insn_fetch(u16, ctxt);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+			modrm_ea += insn_fetch(s8, ctxt);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+			modrm_ea += insn_fetch(u16, ctxt);
 			break;
 		}
 		switch (ctxt->modrm_rm) {
@@ -971,13 +977,13 @@ static int decode_modrm(struct x86_emula
 	} else {
 		/* 32/64-bit ModR/M decode. */
 		if ((ctxt->modrm_rm & 7) == 4) {
-			sib = insn_fetch(u8, 1, ctxt->_eip);
+			sib = insn_fetch(u8, ctxt);
 			index_reg |= (sib >> 3) & 7;
 			base_reg |= sib & 7;
 			scale = sib >> 6;
 
 			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
-				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+				modrm_ea += insn_fetch(s32, ctxt);
 			else
 				modrm_ea += ctxt->regs[base_reg];
 			if (index_reg != 4)
@@ -990,13 +996,13 @@ static int decode_modrm(struct x86_emula
 		switch (ctxt->modrm_mod) {
 		case 0:
 			if (ctxt->modrm_rm == 5)
-				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+				modrm_ea += insn_fetch(s32, ctxt);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+			modrm_ea += insn_fetch(s8, ctxt);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+			modrm_ea += insn_fetch(s32, ctxt);
 			break;
 		}
 	}
@@ -1013,13 +1019,13 @@ static int decode_abs(struct x86_emulate
 	op->type = OP_MEM;
 	switch (ctxt->ad_bytes) {
 	case 2:
-		op->addr.mem.ea = insn_fetch(u16, 2, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u16, ctxt);
 		break;
 	case 4:
-		op->addr.mem.ea = insn_fetch(u32, 4, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u32, ctxt);
 		break;
 	case 8:
-		op->addr.mem.ea = insn_fetch(u64, 8, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u64, ctxt);
 		break;
 	}
 done:
@@ -1452,15 +1458,18 @@ static int em_popf(struct x86_emulate_ct
 	return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
-static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
+
 	ctxt->src.val = get_segment_selector(ctxt, seg);
 
 	return em_push(ctxt);
 }
 
-static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_pop_sreg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
 	unsigned long selector;
 	int rc;
 
@@ -1674,64 +1683,74 @@ static int em_grp2(struct x86_emulate_ct
 {
 	switch (ctxt->modrm_reg) {
 	case 0:	/* rol */
-		emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rol");
 		break;
 	case 1:	/* ror */
-		emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "ror");
 		break;
 	case 2:	/* rcl */
-		emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rcl");
 		break;
 	case 3:	/* rcr */
-		emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rcr");
 		break;
 	case 4:	/* sal/shl */
 	case 6:	/* sal/shl */
-		emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "sal");
 		break;
 	case 5:	/* shr */
-		emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "shr");
 		break;
 	case 7:	/* sar */
-		emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "sar");
 		break;
 	}
 	return X86EMUL_CONTINUE;
 }
 
-static int em_grp3(struct x86_emulate_ctxt *ctxt)
+static int em_not(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->dst.val = ~ctxt->dst.val;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_neg(struct x86_emulate_ctxt *ctxt)
+{
+	emulate_1op(ctxt, "neg");
+	return X86EMUL_CONTINUE;
+}
+
+static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 ex = 0;
+
+	emulate_1op_rax_rdx(ctxt, "mul", ex);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_imul_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 ex = 0;
+
+	emulate_1op_rax_rdx(ctxt, "imul", ex);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_div_ex(struct x86_emulate_ctxt *ctxt)
 {
-	unsigned long *rax = &ctxt->regs[VCPU_REGS_RAX];
-	unsigned long *rdx = &ctxt->regs[VCPU_REGS_RDX];
 	u8 de = 0;
 
-	switch (ctxt->modrm_reg) {
-	case 0 ... 1:	/* test */
-		emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 2:	/* not */
-		ctxt->dst.val = ~ctxt->dst.val;
-		break;
-	case 3:	/* neg */
-		emulate_1op("neg", ctxt->dst, ctxt->eflags);
-		break;
-	case 4: /* mul */
-		emulate_1op_rax_rdx("mul", ctxt->src, *rax, *rdx, ctxt->eflags);
-		break;
-	case 5: /* imul */
-		emulate_1op_rax_rdx("imul", ctxt->src, *rax, *rdx, ctxt->eflags);
-		break;
-	case 6: /* div */
-		emulate_1op_rax_rdx_ex("div", ctxt->src, *rax, *rdx,
-				       ctxt->eflags, de);
-		break;
-	case 7: /* idiv */
-		emulate_1op_rax_rdx_ex("idiv", ctxt->src, *rax, *rdx,
-				       ctxt->eflags, de);
-		break;
-	default:
-		return X86EMUL_UNHANDLEABLE;
-	}
+	emulate_1op_rax_rdx(ctxt, "div", de);
+	if (de)
+		return emulate_de(ctxt);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_idiv_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 de = 0;
+
+	emulate_1op_rax_rdx(ctxt, "idiv", de);
 	if (de)
 		return emulate_de(ctxt);
 	return X86EMUL_CONTINUE;
@@ -1743,10 +1762,10 @@ static int em_grp45(struct x86_emulate_c
 
 	switch (ctxt->modrm_reg) {
 	case 0:	/* inc */
-		emulate_1op("inc", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "inc");
 		break;
 	case 1:	/* dec */
-		emulate_1op("dec", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "dec");
 		break;
 	case 2: /* call near abs */ {
 		long int old_eip;
@@ -1812,8 +1831,9 @@ static int em_ret_far(struct x86_emulate
 	return rc;
 }
 
-static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_lseg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
 	unsigned short sel;
 	int rc;
 
@@ -2452,7 +2472,7 @@ static int em_das(struct x86_emulate_ctx
 	ctxt->src.type = OP_IMM;
 	ctxt->src.val = 0;
 	ctxt->src.bytes = 1;
-	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "or");
 	ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
 	if (cf)
 		ctxt->eflags |= X86_EFLAGS_CF;
@@ -2502,49 +2522,49 @@ static int em_ret_near_imm(struct x86_em
 
 static int em_add(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "add");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_or(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "or");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_adc(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "adc");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sbb(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "sbb");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_and(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "and");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sub(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "sub");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_xor(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "xor");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_cmp(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "cmp");
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
@@ -2552,7 +2572,9 @@ static int em_cmp(struct x86_emulate_ctx
 
 static int em_test(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "test");
+	/* Disable writeback. */
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2570,7 +2592,7 @@ static int em_xchg(struct x86_emulate_ct
 
 static int em_imul(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV_nobyte(ctxt, "imul");
 	return X86EMUL_CONTINUE;
 }
 
@@ -3025,9 +3047,14 @@ static struct opcode group1A[] = {
 };
 
 static struct opcode group3[] = {
-	D(DstMem | SrcImm | ModRM), D(DstMem | SrcImm | ModRM),
-	D(DstMem | SrcNone | ModRM | Lock), D(DstMem | SrcNone | ModRM | Lock),
-	X4(D(SrcMem | ModRM)),
+	I(DstMem | SrcImm | ModRM, em_test),
+	I(DstMem | SrcImm | ModRM, em_test),
+	I(DstMem | SrcNone | ModRM | Lock, em_not),
+	I(DstMem | SrcNone | ModRM | Lock, em_neg),
+	I(SrcMem | ModRM, em_mul_ex),
+	I(SrcMem | ModRM, em_imul_ex),
+	I(SrcMem | ModRM, em_div_ex),
+	I(SrcMem | ModRM, em_idiv_ex),
 };
 
 static struct opcode group4[] = {
@@ -3090,16 +3117,20 @@ static struct gprefix pfx_0f_6f_0f_7f =
 static struct opcode opcode_table[256] = {
 	/* 0x00 - 0x07 */
 	I6ALU(Lock, em_add),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2ES, em_pop_sreg),
 	/* 0x08 - 0x0F */
 	I6ALU(Lock, em_or),
-	D(ImplicitOps | Stack | No64), N,
+	I(ImplicitOps | Stack | No64 | Src2CS, em_push_sreg),
+	N,
 	/* 0x10 - 0x17 */
 	I6ALU(Lock, em_adc),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2SS, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2SS, em_pop_sreg),
 	/* 0x18 - 0x1F */
 	I6ALU(Lock, em_sbb),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2DS, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2DS, em_pop_sreg),
 	/* 0x20 - 0x27 */
 	I6ALU(Lock, em_and), N, N,
 	/* 0x28 - 0x2F */
@@ -3167,7 +3198,8 @@ static struct opcode opcode_table[256] =
 	D2bv(DstMem | SrcImmByte | ModRM),
 	I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
 	I(ImplicitOps | Stack, em_ret),
-	D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64),
+	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
+	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
 	G(ByteOp, group11), G(0, group11),
 	/* 0xC8 - 0xCF */
 	N, N, N, I(ImplicitOps | Stack, em_ret_far),
@@ -3242,20 +3274,22 @@ static struct opcode twobyte_table[256]
 	/* 0x90 - 0x9F */
 	X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
 	/* 0xA0 - 0xA7 */
-	D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+	I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
 	DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp),
 	D(DstMem | SrcReg | Src2ImmByte | ModRM),
 	D(DstMem | SrcReg | Src2CL | ModRM), N, N,
 	/* 0xA8 - 0xAF */
-	D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+	I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg),
 	DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock),
 	D(DstMem | SrcReg | Src2ImmByte | ModRM),
 	D(DstMem | SrcReg | Src2CL | ModRM),
 	D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
 	/* 0xB0 - 0xB7 */
 	D2bv(DstMem | SrcReg | ModRM | Lock),
-	D(DstReg | SrcMemFAddr | ModRM), D(DstMem | SrcReg | ModRM | BitOp | Lock),
-	D(DstReg | SrcMemFAddr | ModRM), D(DstReg | SrcMemFAddr | ModRM),
+	I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
+	D(DstMem | SrcReg | ModRM | BitOp | Lock),
+	I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
+	I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
 	D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
 	/* 0xB8 - 0xBF */
 	N, N,
@@ -3309,13 +3343,13 @@ static int decode_imm(struct x86_emulate
 	/* NB. Immediates are sign-extended as necessary. */
 	switch (op->bytes) {
 	case 1:
-		op->val = insn_fetch(s8, 1, ctxt->_eip);
+		op->val = insn_fetch(s8, ctxt);
 		break;
 	case 2:
-		op->val = insn_fetch(s16, 2, ctxt->_eip);
+		op->val = insn_fetch(s16, ctxt);
 		break;
 	case 4:
-		op->val = insn_fetch(s32, 4, ctxt->_eip);
+		op->val = insn_fetch(s32, ctxt);
 		break;
 	}
 	if (!sign_extension) {
@@ -3335,6 +3369,125 @@ done:
 	return rc;
 }
 
+static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
+			  unsigned d)
+{
+	int rc = X86EMUL_CONTINUE;
+
+	switch (d) {
+	case OpReg:
+		decode_register_operand(ctxt, op,
+			 op == &ctxt->dst &&
+			 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
+		break;
+	case OpImmUByte:
+		rc = decode_imm(ctxt, op, 1, false);
+		break;
+	case OpMem:
+		ctxt->memop.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+	mem_common:
+		*op = ctxt->memop;
+		ctxt->memopp = op;
+		if ((ctxt->d & BitOp) && op == &ctxt->dst)
+			fetch_bit_operand(ctxt);
+		op->orig_val = op->val;
+		break;
+	case OpMem64:
+		ctxt->memop.bytes = 8;
+		goto mem_common;
+	case OpAcc:
+		op->type = OP_REG;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+		fetch_register_operand(op);
+		op->orig_val = op->val;
+		break;
+	case OpDI:
+		op->type = OP_MEM;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
+		op->addr.mem.seg = VCPU_SREG_ES;
+		op->val = 0;
+		break;
+	case OpDX:
+		op->type = OP_REG;
+		op->bytes = 2;
+		op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+		fetch_register_operand(op);
+		break;
+	case OpCL:
+		op->bytes = 1;
+		op->val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
+		break;
+	case OpImmByte:
+		rc = decode_imm(ctxt, op, 1, true);
+		break;
+	case OpOne:
+		op->bytes = 1;
+		op->val = 1;
+		break;
+	case OpImm:
+		rc = decode_imm(ctxt, op, imm_size(ctxt), true);
+		break;
+	case OpMem16:
+		ctxt->memop.bytes = 2;
+		goto mem_common;
+	case OpMem32:
+		ctxt->memop.bytes = 4;
+		goto mem_common;
+	case OpImmU16:
+		rc = decode_imm(ctxt, op, 2, false);
+		break;
+	case OpImmU:
+		rc = decode_imm(ctxt, op, imm_size(ctxt), false);
+		break;
+	case OpSI:
+		op->type = OP_MEM;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
+		op->addr.mem.seg = seg_override(ctxt);
+		op->val = 0;
+		break;
+	case OpImmFAddr:
+		op->type = OP_IMM;
+		op->addr.mem.ea = ctxt->_eip;
+		op->bytes = ctxt->op_bytes + 2;
+		insn_fetch_arr(op->valptr, op->bytes, ctxt);
+		break;
+	case OpMemFAddr:
+		ctxt->memop.bytes = ctxt->op_bytes + 2;
+		goto mem_common;
+	case OpES:
+		op->val = VCPU_SREG_ES;
+		break;
+	case OpCS:
+		op->val = VCPU_SREG_CS;
+		break;
+	case OpSS:
+		op->val = VCPU_SREG_SS;
+		break;
+	case OpDS:
+		op->val = VCPU_SREG_DS;
+		break;
+	case OpFS:
+		op->val = VCPU_SREG_FS;
+		break;
+	case OpGS:
+		op->val = VCPU_SREG_GS;
+		break;
+	case OpImplicit:
+		/* Special instructions do their own operand decoding. */
+	default:
+		op->type = OP_NONE; /* Disable writeback. */
+		break;
+	}
+
+done:
+	return rc;
+}
+
 int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 {
 	int rc = X86EMUL_CONTINUE;
@@ -3342,8 +3495,9 @@ int x86_decode_insn(struct x86_emulate_c
 	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
 	bool op_prefix = false;
 	struct opcode opcode;
-	struct operand memop = { .type = OP_NONE }, *memopp = NULL;
 
+	ctxt->memop.type = OP_NONE;
+	ctxt->memopp = NULL;
 	ctxt->_eip = ctxt->eip;
 	ctxt->fetch.start = ctxt->_eip;
 	ctxt->fetch.end = ctxt->fetch.start + insn_len;
@@ -3366,7 +3520,7 @@ int x86_decode_insn(struct x86_emulate_c
 		break;
 #endif
 	default:
-		return -1;
+		return EMULATION_FAILED;
 	}
 
 	ctxt->op_bytes = def_op_bytes;
@@ -3374,7 +3528,7 @@ int x86_decode_insn(struct x86_emulate_c
 
 	/* Legacy prefixes. */
 	for (;;) {
-		switch (ctxt->b = insn_fetch(u8, 1, ctxt->_eip)) {
+		switch (ctxt->b = insn_fetch(u8, ctxt)) {
 		case 0x66:	/* operand-size override */
 			op_prefix = true;
 			/* switch between 2/4 bytes */
@@ -3430,7 +3584,7 @@ done_prefixes:
 	/* Two-byte opcode? */
 	if (ctxt->b == 0x0f) {
 		ctxt->twobyte = 1;
-		ctxt->b = insn_fetch(u8, 1, ctxt->_eip);
+		ctxt->b = insn_fetch(u8, ctxt);
 		opcode = twobyte_table[ctxt->b];
 	}
 	ctxt->d = opcode.flags;
@@ -3438,13 +3592,13 @@ done_prefixes:
 	while (ctxt->d & GroupMask) {
 		switch (ctxt->d & GroupMask) {
 		case Group:
-			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			ctxt->modrm = insn_fetch(u8, ctxt);
 			--ctxt->_eip;
 			goffset = (ctxt->modrm >> 3) & 7;
 			opcode = opcode.u.group[goffset];
 			break;
 		case GroupDual:
-			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			ctxt->modrm = insn_fetch(u8, ctxt);
 			--ctxt->_eip;
 			goffset = (ctxt->modrm >> 3) & 7;
 			if ((ctxt->modrm >> 6) == 3)
@@ -3458,7 +3612,7 @@ done_prefixes:
 			break;
 		case Prefix:
 			if (ctxt->rep_prefix && op_prefix)
-				return X86EMUL_UNHANDLEABLE;
+				return EMULATION_FAILED;
 			simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
 			switch (simd_prefix) {
 			case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
@@ -3468,10 +3622,10 @@ done_prefixes:
 			}
 			break;
 		default:
-			return X86EMUL_UNHANDLEABLE;
+			return EMULATION_FAILED;
 		}
 
-		ctxt->d &= ~GroupMask;
+		ctxt->d &= ~(u64)GroupMask;
 		ctxt->d |= opcode.flags;
 	}
 
@@ -3481,10 +3635,10 @@ done_prefixes:
 
 	/* Unrecognised? */
 	if (ctxt->d == 0 || (ctxt->d & Undefined))
-		return -1;
+		return EMULATION_FAILED;
 
 	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
-		return -1;
+		return EMULATION_FAILED;
 
 	if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
 		ctxt->op_bytes = 8;
@@ -3501,96 +3655,27 @@ done_prefixes:
 
 	/* ModRM and SIB bytes. */
 	if (ctxt->d & ModRM) {
-		rc = decode_modrm(ctxt, &memop);
+		rc = decode_modrm(ctxt, &ctxt->memop);
 		if (!ctxt->has_seg_override)
 			set_seg_override(ctxt, ctxt->modrm_seg);
 	} else if (ctxt->d & MemAbs)
-		rc = decode_abs(ctxt, &memop);
+		rc = decode_abs(ctxt, &ctxt->memop);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
 	if (!ctxt->has_seg_override)
 		set_seg_override(ctxt, VCPU_SREG_DS);
 
-	memop.addr.mem.seg = seg_override(ctxt);
+	ctxt->memop.addr.mem.seg = seg_override(ctxt);
 
-	if (memop.type == OP_MEM && ctxt->ad_bytes != 8)
-		memop.addr.mem.ea = (u32)memop.addr.mem.ea;
+	if (ctxt->memop.type == OP_MEM && ctxt->ad_bytes != 8)
+		ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
 
 	/*
 	 * Decode and fetch the source operand: register, memory
 	 * or immediate.
 	 */
-	switch (ctxt->d & SrcMask) {
-	case SrcNone:
-		break;
-	case SrcReg:
-		decode_register_operand(ctxt, &ctxt->src, 0);
-		break;
-	case SrcMem16:
-		memop.bytes = 2;
-		goto srcmem_common;
-	case SrcMem32:
-		memop.bytes = 4;
-		goto srcmem_common;
-	case SrcMem:
-		memop.bytes = (ctxt->d & ByteOp) ? 1 :
-							   ctxt->op_bytes;
-	srcmem_common:
-		ctxt->src = memop;
-		memopp = &ctxt->src;
-		break;
-	case SrcImmU16:
-		rc = decode_imm(ctxt, &ctxt->src, 2, false);
-		break;
-	case SrcImm:
-		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), true);
-		break;
-	case SrcImmU:
-		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), false);
-		break;
-	case SrcImmByte:
-		rc = decode_imm(ctxt, &ctxt->src, 1, true);
-		break;
-	case SrcImmUByte:
-		rc = decode_imm(ctxt, &ctxt->src, 1, false);
-		break;
-	case SrcAcc:
-		ctxt->src.type = OP_REG;
-		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&ctxt->src);
-		break;
-	case SrcOne:
-		ctxt->src.bytes = 1;
-		ctxt->src.val = 1;
-		break;
-	case SrcSI:
-		ctxt->src.type = OP_MEM;
-		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->src.addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
-		ctxt->src.addr.mem.seg = seg_override(ctxt);
-		ctxt->src.val = 0;
-		break;
-	case SrcImmFAddr:
-		ctxt->src.type = OP_IMM;
-		ctxt->src.addr.mem.ea = ctxt->_eip;
-		ctxt->src.bytes = ctxt->op_bytes + 2;
-		insn_fetch_arr(ctxt->src.valptr, ctxt->src.bytes, ctxt->_eip);
-		break;
-	case SrcMemFAddr:
-		memop.bytes = ctxt->op_bytes + 2;
-		goto srcmem_common;
-		break;
-	case SrcDX:
-		ctxt->src.type = OP_REG;
-		ctxt->src.bytes = 2;
-		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&ctxt->src);
-		break;
-	}
-
+	rc = decode_operand(ctxt, &ctxt->src, (ctxt->d >> SrcShift) & OpMask);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
@@ -3598,85 +3683,18 @@ done_prefixes:
 	 * Decode and fetch the second source operand: register, memory
 	 * or immediate.
 	 */
-	switch (ctxt->d & Src2Mask) {
-	case Src2None:
-		break;
-	case Src2CL:
-		ctxt->src2.bytes = 1;
-		ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
-		break;
-	case Src2ImmByte:
-		rc = decode_imm(ctxt, &ctxt->src2, 1, true);
-		break;
-	case Src2One:
-		ctxt->src2.bytes = 1;
-		ctxt->src2.val = 1;
-		break;
-	case Src2Imm:
-		rc = decode_imm(ctxt, &ctxt->src2, imm_size(ctxt), true);
-		break;
-	}
-
+	rc = decode_operand(ctxt, &ctxt->src2, (ctxt->d >> Src2Shift) & OpMask);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
 	/* Decode and fetch the destination operand: register or memory. */
-	switch (ctxt->d & DstMask) {
-	case DstReg:
-		decode_register_operand(ctxt, &ctxt->dst,
-			 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
-		break;
-	case DstImmUByte:
-		ctxt->dst.type = OP_IMM;
-		ctxt->dst.addr.mem.ea = ctxt->_eip;
-		ctxt->dst.bytes = 1;
-		ctxt->dst.val = insn_fetch(u8, 1, ctxt->_eip);
-		break;
-	case DstMem:
-	case DstMem64:
-		ctxt->dst = memop;
-		memopp = &ctxt->dst;
-		if ((ctxt->d & DstMask) == DstMem64)
-			ctxt->dst.bytes = 8;
-		else
-			ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		if (ctxt->d & BitOp)
-			fetch_bit_operand(ctxt);
-		ctxt->dst.orig_val = ctxt->dst.val;
-		break;
-	case DstAcc:
-		ctxt->dst.type = OP_REG;
-		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&ctxt->dst);
-		ctxt->dst.orig_val = ctxt->dst.val;
-		break;
-	case DstDI:
-		ctxt->dst.type = OP_MEM;
-		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->dst.addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
-		ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
-		ctxt->dst.val = 0;
-		break;
-	case DstDX:
-		ctxt->dst.type = OP_REG;
-		ctxt->dst.bytes = 2;
-		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&ctxt->dst);
-		break;
-	case ImplicitOps:
-		/* Special instructions do their own operand decoding. */
-	default:
-		ctxt->dst.type = OP_NONE; /* Disable writeback. */
-		break;
-	}
+	rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
 done:
-	if (memopp && memopp->type == OP_MEM && ctxt->rip_relative)
-		memopp->addr.mem.ea += ctxt->_eip;
+	if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
+		ctxt->memopp->addr.mem.ea += ctxt->_eip;
 
-	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
+	return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
 static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
@@ -3825,32 +3843,11 @@ special_insn:
 		goto twobyte_insn;
 
 	switch (ctxt->b) {
-	case 0x06:		/* push es */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
-		break;
-	case 0x07:		/* pop es */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
-		break;
-	case 0x0e:		/* push cs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
-		break;
-	case 0x16:		/* push ss */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
-		break;
-	case 0x17:		/* pop ss */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
-		break;
-	case 0x1e:		/* push ds */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_DS);
-		break;
-	case 0x1f:		/* pop ds */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS);
-		break;
 	case 0x40 ... 0x47: /* inc r16/r32 */
-		emulate_1op("inc", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "inc");
 		break;
 	case 0x48 ... 0x4f: /* dec r16/r32 */
-		emulate_1op("dec", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "dec");
 		break;
 	case 0x63:		/* movsxd */
 		if (ctxt->mode != X86EMUL_MODE_PROT64)
@@ -3891,12 +3888,6 @@ special_insn:
 	case 0xc0 ... 0xc1:
 		rc = em_grp2(ctxt);
 		break;
-	case 0xc4:		/* les */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
-		break;
-	case 0xc5:		/* lds */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_DS);
-		break;
 	case 0xcc:		/* int3 */
 		rc = emulate_int(ctxt, 3);
 		break;
@@ -3953,9 +3944,6 @@ special_insn:
 		/* complement carry flag from eflags reg */
 		ctxt->eflags ^= EFLG_CF;
 		break;
-	case 0xf6 ... 0xf7:	/* Grp3 */
-		rc = em_grp3(ctxt);
-		break;
 	case 0xf8: /* clc */
 		ctxt->eflags &= ~EFLG_CF;
 		break;
@@ -4103,36 +4091,24 @@ twobyte_insn:
 	case 0x90 ... 0x9f:     /* setcc r/m8 */
 		ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
 		break;
-	case 0xa0:	  /* push fs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_FS);
-		break;
-	case 0xa1:	 /* pop fs */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS);
-		break;
 	case 0xa3:
 	      bt:		/* bt */
 		ctxt->dst.type = OP_NONE;
 		/* only subword offset */
 		ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
-		emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "bt");
 		break;
 	case 0xa4: /* shld imm8, r, r/m */
 	case 0xa5: /* shld cl, r, r/m */
-		emulate_2op_cl("shld", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 0xa8:	/* push gs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
-		break;
-	case 0xa9:	/* pop gs */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
+		emulate_2op_cl(ctxt, "shld");
 		break;
 	case 0xab:
 	      bts:		/* bts */
-		emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "bts");
 		break;
 	case 0xac: /* shrd imm8, r, r/m */
 	case 0xad: /* shrd cl, r, r/m */
-		emulate_2op_cl("shrd", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_cl(ctxt, "shrd");
 		break;
 	case 0xae:              /* clflush */
 		break;
@@ -4143,7 +4119,7 @@ twobyte_insn:
 		 */
 		ctxt->src.orig_val = ctxt->src.val;
 		ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
-		emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV(ctxt, "cmp");
 		if (ctxt->eflags & EFLG_ZF) {
 			/* Success: write back to memory. */
 			ctxt->dst.val = ctxt->src.orig_val;
@@ -4153,18 +4129,9 @@ twobyte_insn:
 			ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
 		}
 		break;
-	case 0xb2:		/* lss */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_SS);
-		break;
 	case 0xb3:
 	      btr:		/* btr */
-		emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 0xb4:		/* lfs */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
-		break;
-	case 0xb5:		/* lgs */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
+		emulate_2op_SrcV_nobyte(ctxt, "btr");
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
 		ctxt->dst.bytes = ctxt->op_bytes;
@@ -4185,7 +4152,7 @@ twobyte_insn:
 		break;
 	case 0xbb:
 	      btc:		/* btc */
-		emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "btc");
 		break;
 	case 0xbc: {		/* bsf */
 		u8 zf;
@@ -4217,7 +4184,7 @@ twobyte_insn:
 							(s16) ctxt->src.val;
 		break;
 	case 0xc0 ... 0xc1:	/* xadd */
-		emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV(ctxt, "add");
 		/* Write back the register source. */
 		ctxt->src.val = ctxt->dst.orig_val;
 		write_register_operand(&ctxt->src);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/i8254.c linux-libre-3.2-gnu1/arch/x86/kvm/i8254.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/i8254.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/i8254.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn
 		return HRTIMER_NORESTART;
 }
 
-static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
+static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
 {
+	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
 	struct kvm_timer *pt = &ps->pit_timer;
 	s64 interval;
 
+	if (!irqchip_in_kernel(kvm))
+		return;
+
 	interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
 
 	pr_debug("create pit timer, interval is %llu nsec\n", interval);
@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *k
         /* FIXME: enhance mode 4 precision */
 	case 4:
 		if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) {
-			create_pit_timer(ps, val, 0);
+			create_pit_timer(kvm, val, 0);
 		}
 		break;
 	case 2:
 	case 3:
 		if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){
-			create_pit_timer(ps, val, 1);
+			create_pit_timer(kvm, val, 1);
 		}
 		break;
 	default:
@@ -713,14 +717,16 @@ struct kvm_pit *kvm_create_pit(struct kv
 	kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
 
 	kvm_iodevice_init(&pit->dev, &pit_dev_ops);
-	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &pit->dev);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS,
+				      KVM_PIT_MEM_LENGTH, &pit->dev);
 	if (ret < 0)
 		goto fail;
 
 	if (flags & KVM_PIT_SPEAKER_DUMMY) {
 		kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
 		ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS,
-						&pit->speaker_dev);
+					      KVM_SPEAKER_BASE_ADDRESS, 4,
+					      &pit->speaker_dev);
 		if (ret < 0)
 			goto fail_unregister;
 	}
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/i8259.c linux-libre-3.2-gnu1/arch/x86/kvm/i8259.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/i8259.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/i8259.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,9 @@
 #include <linux/kvm_host.h>
 #include "trace.h"
 
+#define pr_pic_unimpl(fmt, ...)	\
+	pr_err_ratelimited("kvm: pic: " fmt, ## __VA_ARGS__)
+
 static void pic_irq_request(struct kvm *kvm, int level);
 
 static void pic_lock(struct kvm_pic *s)
@@ -306,10 +309,10 @@ static void pic_ioport_write(void *opaqu
 			}
 			s->init_state = 1;
 			if (val & 0x02)
-				printk(KERN_ERR "single mode not supported");
+				pr_pic_unimpl("single mode not supported");
 			if (val & 0x08)
-				printk(KERN_ERR
-				       "level sensitive irq not supported");
+				pr_pic_unimpl(
+					"level sensitive irq not supported");
 		} else if (val & 0x08) {
 			if (val & 0x04)
 				s->poll = 1;
@@ -459,22 +462,15 @@ static int picdev_in_range(gpa_t addr)
 	}
 }
 
-static inline struct kvm_pic *to_pic(struct kvm_io_device *dev)
-{
-	return container_of(dev, struct kvm_pic, dev);
-}
-
-static int picdev_write(struct kvm_io_device *this,
+static int picdev_write(struct kvm_pic *s,
 			 gpa_t addr, int len, const void *val)
 {
-	struct kvm_pic *s = to_pic(this);
 	unsigned char data = *(unsigned char *)val;
 	if (!picdev_in_range(addr))
 		return -EOPNOTSUPP;
 
 	if (len != 1) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "PIC: non byte write\n");
+		pr_pic_unimpl("non byte write\n");
 		return 0;
 	}
 	pic_lock(s);
@@ -494,17 +490,15 @@ static int picdev_write(struct kvm_io_de
 	return 0;
 }
 
-static int picdev_read(struct kvm_io_device *this,
+static int picdev_read(struct kvm_pic *s,
 		       gpa_t addr, int len, void *val)
 {
-	struct kvm_pic *s = to_pic(this);
 	unsigned char data = 0;
 	if (!picdev_in_range(addr))
 		return -EOPNOTSUPP;
 
 	if (len != 1) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "PIC: non byte read\n");
+		pr_pic_unimpl("non byte read\n");
 		return 0;
 	}
 	pic_lock(s);
@@ -525,6 +519,48 @@ static int picdev_read(struct kvm_io_dev
 	return 0;
 }
 
+static int picdev_master_write(struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_master),
+			    addr, len, val);
+}
+
+static int picdev_master_read(struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_master),
+			    addr, len, val);
+}
+
+static int picdev_slave_write(struct kvm_io_device *dev,
+			      gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_slave),
+			    addr, len, val);
+}
+
+static int picdev_slave_read(struct kvm_io_device *dev,
+			     gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_slave),
+			    addr, len, val);
+}
+
+static int picdev_eclr_write(struct kvm_io_device *dev,
+			     gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_eclr),
+			    addr, len, val);
+}
+
+static int picdev_eclr_read(struct kvm_io_device *dev,
+			    gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_eclr),
+			    addr, len, val);
+}
+
 /*
  * callback when PIC0 irq status changed
  */
@@ -537,9 +573,19 @@ static void pic_irq_request(struct kvm *
 	s->output = level;
 }
 
-static const struct kvm_io_device_ops picdev_ops = {
-	.read     = picdev_read,
-	.write    = picdev_write,
+static const struct kvm_io_device_ops picdev_master_ops = {
+	.read     = picdev_master_read,
+	.write    = picdev_master_write,
+};
+
+static const struct kvm_io_device_ops picdev_slave_ops = {
+	.read     = picdev_slave_read,
+	.write    = picdev_slave_write,
+};
+
+static const struct kvm_io_device_ops picdev_eclr_ops = {
+	.read     = picdev_eclr_read,
+	.write    = picdev_eclr_write,
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm)
@@ -560,16 +606,39 @@ struct kvm_pic *kvm_create_pic(struct kv
 	/*
 	 * Initialize PIO device
 	 */
-	kvm_iodevice_init(&s->dev, &picdev_ops);
+	kvm_iodevice_init(&s->dev_master, &picdev_master_ops);
+	kvm_iodevice_init(&s->dev_slave, &picdev_slave_ops);
+	kvm_iodevice_init(&s->dev_eclr, &picdev_eclr_ops);
 	mutex_lock(&kvm->slots_lock);
-	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x20, 2,
+				      &s->dev_master);
+	if (ret < 0)
+		goto fail_unlock;
+
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0xa0, 2, &s->dev_slave);
+	if (ret < 0)
+		goto fail_unreg_2;
+
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x4d0, 2, &s->dev_eclr);
+	if (ret < 0)
+		goto fail_unreg_1;
+
 	mutex_unlock(&kvm->slots_lock);
-	if (ret < 0) {
-		kfree(s);
-		return NULL;
-	}
 
 	return s;
+
+fail_unreg_1:
+	kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_slave);
+
+fail_unreg_2:
+	kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_master);
+
+fail_unlock:
+	mutex_unlock(&kvm->slots_lock);
+
+	kfree(s);
+
+	return NULL;
 }
 
 void kvm_destroy_pic(struct kvm *kvm)
@@ -577,7 +646,9 @@ void kvm_destroy_pic(struct kvm *kvm)
 	struct kvm_pic *vpic = kvm->arch.vpic;
 
 	if (vpic) {
-		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_master);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_slave);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_eclr);
 		kvm->arch.vpic = NULL;
 		kfree(vpic);
 	}
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/irq.h linux-libre-3.2-gnu1/arch/x86/kvm/irq.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,9 @@ struct kvm_pic {
 	struct kvm *kvm;
 	struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
 	int output;		/* intr from master PIC */
-	struct kvm_io_device dev;
+	struct kvm_io_device dev_master;
+	struct kvm_io_device dev_slave;
+	struct kvm_io_device dev_eclr;
 	void (*ack_notifier)(void *opaque, int irq);
 	unsigned long irq_states[16];
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/kvm_cache_regs.h linux-libre-3.2-gnu1/arch/x86/kvm/kvm_cache_regs.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/kvm_cache_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/kvm_cache_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,13 +45,6 @@ static inline u64 kvm_pdptr_read(struct
 	return vcpu->arch.walk_mmu->pdptrs[index];
 }
 
-static inline u64 kvm_pdptr_read_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, int index)
-{
-	load_pdptrs(vcpu, mmu, mmu->get_cr3(vcpu));
-
-	return mmu->pdptrs[index];
-}
-
 static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
 {
 	ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/kvm_timer.h linux-libre-3.2-gnu1/arch/x86/kvm/kvm_timer.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/kvm_timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/kvm_timer.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/lapic.c linux-libre-3.2-gnu1/arch/x86/kvm/lapic.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/lapic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/lapic.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,9 @@
 #define VEC_POS(v) ((v) & (32 - 1))
 #define REG_POS(v) (((v) >> 5) << 4)
 
+static unsigned int min_timer_period_us = 500;
+module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
+
 static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off)
 {
 	return *((u32 *) (apic->regs + reg_off));
@@ -135,9 +138,23 @@ static inline int apic_lvt_vector(struct
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +183,7 @@ static inline int apic_x2apic_mode(struc
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -316,8 +333,8 @@ int kvm_apic_match_logical_addr(struct k
 			result = 1;
 		break;
 	default:
-		printk(KERN_WARNING "Bad DFR vcpu %d: %08x\n",
-		       apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
+		apic_debug("Bad DFR vcpu %d: %08x\n",
+			   apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
 		break;
 	}
 
@@ -354,8 +371,8 @@ int kvm_apic_match_dest(struct kvm_vcpu
 		result = (target != source);
 		break;
 	default:
-		printk(KERN_WARNING "Bad dest shorthand value %x\n",
-		       short_hand);
+		apic_debug("kvm: apic: Bad dest shorthand value %x\n",
+			   short_hand);
 		break;
 	}
 
@@ -401,11 +418,11 @@ static int __apic_accept_irq(struct kvm_
 		break;
 
 	case APIC_DM_REMRD:
-		printk(KERN_DEBUG "Ignoring delivery mode 3\n");
+		apic_debug("Ignoring delivery mode 3\n");
 		break;
 
 	case APIC_DM_SMI:
-		printk(KERN_DEBUG "Ignoring guest SMI\n");
+		apic_debug("Ignoring guest SMI\n");
 		break;
 
 	case APIC_DM_NMI:
@@ -565,11 +582,13 @@ static u32 __apic_read(struct kvm_lapic
 			val = kvm_apic_id(apic) << 24;
 		break;
 	case APIC_ARBPRI:
-		printk(KERN_WARNING "Access APIC ARBPRI register "
-		       "which is for P6\n");
+		apic_debug("Access APIC ARBPRI register which is for P6\n");
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +683,40 @@ static void update_divide_count(struct k
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			s64 min_period = min_timer_period_us * 1000LL;
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+			if (apic->lapic_timer.period < min_period) {
+				pr_info_ratelimited(
+				    "kvm: vcpu %i: requested %lld ns "
+				    "lapic timer period limited to %lld ns\n",
+				    apic->vcpu->vcpu_id,
+				    apic->lapic_timer.period, min_period);
+				apic->lapic_timer.period = min_period;
+			}
+		}
+
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
+
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +725,30 @@ static void start_apic_timer(struct kvm_
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc)) {
+			ns = (tscdeadline - guest_tsc) * 1000000ULL;
+			do_div(ns, this_tsc_khz);
+		}
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +836,6 @@ static int apic_reg_write(struct kvm_lap
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +849,22 @@ static int apic_reg_write(struct kvm_lap
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+			hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+			val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -804,14 +872,14 @@ static int apic_reg_write(struct kvm_lap
 
 	case APIC_TDCR:
 		if (val & 4)
-			printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
+			apic_debug("KVM_WRITE:TDCR %x\n", val);
 		apic_set_reg(apic, APIC_TDCR, val);
 		update_divide_count(apic);
 		break;
 
 	case APIC_ESR:
 		if (apic_x2apic_mode(apic) && val != 0) {
-			printk(KERN_ERR "KVM_WRITE:ESR not zero %x\n", val);
+			apic_debug("KVM_WRITE:ESR not zero %x\n", val);
 			ret = 1;
 		}
 		break;
@@ -864,6 +932,15 @@ static int apic_mmio_write(struct kvm_io
 	return 0;
 }
 
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic)
+		apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
+
 void kvm_free_lapic(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->arch.apic)
@@ -883,6 +960,32 @@ void kvm_free_lapic(struct kvm_vcpu *vcp
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	if (!apic)
+		return 0;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	if (!apic)
+		return;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/lapic.h linux-libre-3.2-gnu1/arch/x86/kvm/lapic.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/lapic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/lapic.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@ int kvm_get_apic_interrupt(struct kvm_vc
 void kvm_lapic_reset(struct kvm_vcpu *vcpu);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
@@ -41,6 +42,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *v
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/mmu_audit.c linux-libre-3.2-gnu1/arch/x86/kvm/mmu_audit.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/mmu_audit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/mmu_audit.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,16 +121,16 @@ static void audit_mappings(struct kvm_vc
 
 static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
 {
+	static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
 	unsigned long *rmapp;
 	struct kvm_mmu_page *rev_sp;
 	gfn_t gfn;
 
-
 	rev_sp = page_header(__pa(sptep));
 	gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt);
 
 	if (!gfn_to_memslot(kvm, gfn)) {
-		if (!printk_ratelimit())
+		if (!__ratelimit(&ratelimit_state))
 			return;
 		audit_printk(kvm, "no memslot for gfn %llx\n", gfn);
 		audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",
@@ -141,7 +141,7 @@ static void inspect_spte_has_rmap(struct
 
 	rmapp = gfn_to_rmap(kvm, gfn, rev_sp->role.level);
 	if (!*rmapp) {
-		if (!printk_ratelimit())
+		if (!__ratelimit(&ratelimit_state))
 			return;
 		audit_printk(kvm, "no rmap for writable spte %llx\n",
 			     *sptep);
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/mmu.c linux-libre-3.2-gnu1/arch/x86/kvm/mmu.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -2770,7 +2770,7 @@ static int mmu_alloc_shadow_roots(struct
 
 		ASSERT(!VALID_PAGE(root));
 		if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) {
-			pdptr = kvm_pdptr_read_mmu(vcpu, &vcpu->arch.mmu, i);
+			pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i);
 			if (!is_present_gpte(pdptr)) {
 				vcpu->arch.mmu.pae_root[i] = 0;
 				continue;
@@ -3318,6 +3318,7 @@ static int init_kvm_tdp_mmu(struct kvm_v
 	context->direct_map = true;
 	context->set_cr3 = kvm_x86_ops->set_tdp_cr3;
 	context->get_cr3 = get_cr3;
+	context->get_pdptr = kvm_pdptr_read;
 	context->inject_page_fault = kvm_inject_page_fault;
 	context->nx = is_nx(vcpu);
 
@@ -3376,6 +3377,7 @@ static int init_kvm_softmmu(struct kvm_v
 
 	vcpu->arch.walk_mmu->set_cr3           = kvm_x86_ops->set_cr3;
 	vcpu->arch.walk_mmu->get_cr3           = get_cr3;
+	vcpu->arch.walk_mmu->get_pdptr         = kvm_pdptr_read;
 	vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
 
 	return r;
@@ -3386,6 +3388,7 @@ static int init_kvm_nested_mmu(struct kv
 	struct kvm_mmu *g_context = &vcpu->arch.nested_mmu;
 
 	g_context->get_cr3           = get_cr3;
+	g_context->get_pdptr         = kvm_pdptr_read;
 	g_context->inject_page_fault = kvm_inject_page_fault;
 
 	/*
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/paging_tmpl.h linux-libre-3.2-gnu1/arch/x86/kvm/paging_tmpl.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/paging_tmpl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/paging_tmpl.h	2012-01-04 18:55:44.000000000 -0500
@@ -147,7 +147,7 @@ static int FNAME(walk_addr_generic)(stru
 	gfn_t table_gfn;
 	unsigned index, pt_access, uninitialized_var(pte_access);
 	gpa_t pte_gpa;
-	bool eperm;
+	bool eperm, last_gpte;
 	int offset;
 	const int write_fault = access & PFERR_WRITE_MASK;
 	const int user_fault  = access & PFERR_USER_MASK;
@@ -163,7 +163,7 @@ retry_walk:
 
 #if PTTYPE == 64
 	if (walker->level == PT32E_ROOT_LEVEL) {
-		pte = kvm_pdptr_read_mmu(vcpu, mmu, (addr >> 30) & 3);
+		pte = mmu->get_pdptr(vcpu, (addr >> 30) & 3);
 		trace_kvm_mmu_paging_element(pte, walker->level);
 		if (!is_present_gpte(pte))
 			goto error;
@@ -221,6 +221,17 @@ retry_walk:
 			eperm = true;
 #endif
 
+		last_gpte = FNAME(is_last_gpte)(walker, vcpu, mmu, pte);
+		if (last_gpte) {
+			pte_access = pt_access &
+				     FNAME(gpte_access)(vcpu, pte, true);
+			/* check if the kernel is fetching from user page */
+			if (unlikely(pte_access & PT_USER_MASK) &&
+			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+				if (fetch_fault && !user_fault)
+					eperm = true;
+		}
+
 		if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
 			int ret;
 			trace_kvm_mmu_set_accessed_bit(table_gfn, index,
@@ -238,18 +249,12 @@ retry_walk:
 
 		walker->ptes[walker->level - 1] = pte;
 
-		if (FNAME(is_last_gpte)(walker, vcpu, mmu, pte)) {
+		if (last_gpte) {
 			int lvl = walker->level;
 			gpa_t real_gpa;
 			gfn_t gfn;
 			u32 ac;
 
-			/* check if the kernel is fetching from user page */
-			if (unlikely(pte_access & PT_USER_MASK) &&
-			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
-				if (fetch_fault && !user_fault)
-					eperm = true;
-
 			gfn = gpte_to_gfn_lvl(pte, lvl);
 			gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT;
 
@@ -295,7 +300,6 @@ retry_walk:
 		walker->ptes[walker->level - 1] = pte;
 	}
 
-	pte_access = pt_access & FNAME(gpte_access)(vcpu, pte, true);
 	walker->pt_access = pt_access;
 	walker->pte_access = pte_access;
 	pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/svm.c linux-libre-3.2-gnu1/arch/x86/kvm/svm.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/svm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/svm.c	2012-01-04 18:55:44.000000000 -0500
@@ -1084,7 +1084,6 @@ static void init_vmcb(struct vcpu_svm *s
 	if (npt_enabled) {
 		/* Setup VMCB for Nested Paging */
 		control->nested_ctl = 1;
-		clr_intercept(svm, INTERCEPT_TASK_SWITCH);
 		clr_intercept(svm, INTERCEPT_INVLPG);
 		clr_exception_intercept(svm, PF_VECTOR);
 		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
@@ -1844,6 +1843,20 @@ static unsigned long nested_svm_get_tdp_
 	return svm->nested.nested_cr3;
 }
 
+static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+	u64 cr3 = svm->nested.nested_cr3;
+	u64 pdpte;
+	int ret;
+
+	ret = kvm_read_guest_page(vcpu->kvm, gpa_to_gfn(cr3), &pdpte,
+				  offset_in_page(cr3) + index * 8, 8);
+	if (ret)
+		return 0;
+	return pdpte;
+}
+
 static void nested_svm_set_tdp_cr3(struct kvm_vcpu *vcpu,
 				   unsigned long root)
 {
@@ -1875,6 +1888,7 @@ static int nested_svm_init_mmu_context(s
 
 	vcpu->arch.mmu.set_cr3           = nested_svm_set_tdp_cr3;
 	vcpu->arch.mmu.get_cr3           = nested_svm_get_tdp_cr3;
+	vcpu->arch.mmu.get_pdptr         = nested_svm_get_tdp_pdptr;
 	vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
 	vcpu->arch.mmu.shadow_root_level = get_npt_level();
 	vcpu->arch.walk_mmu              = &vcpu->arch.nested_mmu;
@@ -2182,7 +2196,8 @@ static int nested_svm_vmexit(struct vcpu
 				       vmcb->control.exit_info_1,
 				       vmcb->control.exit_info_2,
 				       vmcb->control.exit_int_info,
-				       vmcb->control.exit_int_info_err);
+				       vmcb->control.exit_int_info_err,
+				       KVM_ISA_SVM);
 
 	nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, &page);
 	if (!nested_vmcb)
@@ -2894,15 +2909,20 @@ static int cr8_write_interception(struct
 	return 0;
 }
 
+u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+	struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
+	return vmcb->control.tsc_offset +
+		svm_scale_tsc(vcpu, native_read_tsc());
+}
+
 static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	switch (ecx) {
 	case MSR_IA32_TSC: {
-		struct vmcb *vmcb = get_host_vmcb(svm);
-
-		*data = vmcb->control.tsc_offset +
+		*data = svm->vmcb->control.tsc_offset +
 			svm_scale_tsc(vcpu, native_read_tsc());
 
 		break;
@@ -3314,8 +3334,6 @@ static int handle_exit(struct kvm_vcpu *
 	struct kvm_run *kvm_run = vcpu->run;
 	u32 exit_code = svm->vmcb->control.exit_code;
 
-	trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
-
 	if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
 	if (npt_enabled)
@@ -3335,7 +3353,8 @@ static int handle_exit(struct kvm_vcpu *
 					svm->vmcb->control.exit_info_1,
 					svm->vmcb->control.exit_info_2,
 					svm->vmcb->control.exit_int_info,
-					svm->vmcb->control.exit_int_info_err);
+					svm->vmcb->control.exit_int_info_err,
+					KVM_ISA_SVM);
 
 		vmexit = nested_svm_exit_special(svm);
 
@@ -3768,6 +3787,8 @@ static void svm_vcpu_run(struct kvm_vcpu
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
+	trace_kvm_exit(svm->vmcb->control.exit_code, vcpu, KVM_ISA_SVM);
+
 	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
 		kvm_before_handle_nmi(&svm->vcpu);
 
@@ -3897,60 +3918,6 @@ static void svm_set_supported_cpuid(u32
 	}
 }
 
-static const struct trace_print_flags svm_exit_reasons_str[] = {
-	{ SVM_EXIT_READ_CR0,			"read_cr0" },
-	{ SVM_EXIT_READ_CR3,			"read_cr3" },
-	{ SVM_EXIT_READ_CR4,			"read_cr4" },
-	{ SVM_EXIT_READ_CR8,			"read_cr8" },
-	{ SVM_EXIT_WRITE_CR0,			"write_cr0" },
-	{ SVM_EXIT_WRITE_CR3,			"write_cr3" },
-	{ SVM_EXIT_WRITE_CR4,			"write_cr4" },
-	{ SVM_EXIT_WRITE_CR8,			"write_cr8" },
-	{ SVM_EXIT_READ_DR0,			"read_dr0" },
-	{ SVM_EXIT_READ_DR1,			"read_dr1" },
-	{ SVM_EXIT_READ_DR2,			"read_dr2" },
-	{ SVM_EXIT_READ_DR3,			"read_dr3" },
-	{ SVM_EXIT_WRITE_DR0,			"write_dr0" },
-	{ SVM_EXIT_WRITE_DR1,			"write_dr1" },
-	{ SVM_EXIT_WRITE_DR2,			"write_dr2" },
-	{ SVM_EXIT_WRITE_DR3,			"write_dr3" },
-	{ SVM_EXIT_WRITE_DR5,			"write_dr5" },
-	{ SVM_EXIT_WRITE_DR7,			"write_dr7" },
-	{ SVM_EXIT_EXCP_BASE + DB_VECTOR,	"DB excp" },
-	{ SVM_EXIT_EXCP_BASE + BP_VECTOR,	"BP excp" },
-	{ SVM_EXIT_EXCP_BASE + UD_VECTOR,	"UD excp" },
-	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,	"PF excp" },
-	{ SVM_EXIT_EXCP_BASE + NM_VECTOR,	"NM excp" },
-	{ SVM_EXIT_EXCP_BASE + MC_VECTOR,	"MC excp" },
-	{ SVM_EXIT_INTR,			"interrupt" },
-	{ SVM_EXIT_NMI,				"nmi" },
-	{ SVM_EXIT_SMI,				"smi" },
-	{ SVM_EXIT_INIT,			"init" },
-	{ SVM_EXIT_VINTR,			"vintr" },
-	{ SVM_EXIT_CPUID,			"cpuid" },
-	{ SVM_EXIT_INVD,			"invd" },
-	{ SVM_EXIT_HLT,				"hlt" },
-	{ SVM_EXIT_INVLPG,			"invlpg" },
-	{ SVM_EXIT_INVLPGA,			"invlpga" },
-	{ SVM_EXIT_IOIO,			"io" },
-	{ SVM_EXIT_MSR,				"msr" },
-	{ SVM_EXIT_TASK_SWITCH,			"task_switch" },
-	{ SVM_EXIT_SHUTDOWN,			"shutdown" },
-	{ SVM_EXIT_VMRUN,			"vmrun" },
-	{ SVM_EXIT_VMMCALL,			"hypercall" },
-	{ SVM_EXIT_VMLOAD,			"vmload" },
-	{ SVM_EXIT_VMSAVE,			"vmsave" },
-	{ SVM_EXIT_STGI,			"stgi" },
-	{ SVM_EXIT_CLGI,			"clgi" },
-	{ SVM_EXIT_SKINIT,			"skinit" },
-	{ SVM_EXIT_WBINVD,			"wbinvd" },
-	{ SVM_EXIT_MONITOR,			"monitor" },
-	{ SVM_EXIT_MWAIT,			"mwait" },
-	{ SVM_EXIT_XSETBV,			"xsetbv" },
-	{ SVM_EXIT_NPF,				"npf" },
-	{ -1, NULL }
-};
-
 static int svm_get_lpage_level(void)
 {
 	return PT_PDPE_LEVEL;
@@ -4223,7 +4190,6 @@ static struct kvm_x86_ops svm_x86_ops =
 	.get_mt_mask = svm_get_mt_mask,
 
 	.get_exit_info = svm_get_exit_info,
-	.exit_reasons_str = svm_exit_reasons_str,
 
 	.get_lpage_level = svm_get_lpage_level,
 
@@ -4239,6 +4205,7 @@ static struct kvm_x86_ops svm_x86_ops =
 	.write_tsc_offset = svm_write_tsc_offset,
 	.adjust_tsc_offset = svm_adjust_tsc_offset,
 	.compute_tsc_offset = svm_compute_tsc_offset,
+	.read_l1_tsc = svm_read_l1_tsc,
 
 	.set_tdp_cr3 = set_tdp_cr3,
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/trace.h linux-libre-3.2-gnu1/arch/x86/kvm/trace.h
--- linux-libre-3.1-gnu1/arch/x86/kvm/trace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/trace.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,8 @@
 #define _TRACE_KVM_H
 
 #include <linux/tracepoint.h>
+#include <asm/vmx.h>
+#include <asm/svm.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
@@ -181,6 +183,95 @@ TRACE_EVENT(kvm_apic,
 #define KVM_ISA_VMX   1
 #define KVM_ISA_SVM   2
 
+#define VMX_EXIT_REASONS \
+	{ EXIT_REASON_EXCEPTION_NMI,		"EXCEPTION_NMI" }, \
+	{ EXIT_REASON_EXTERNAL_INTERRUPT,	"EXTERNAL_INTERRUPT" }, \
+	{ EXIT_REASON_TRIPLE_FAULT,		"TRIPLE_FAULT" }, \
+	{ EXIT_REASON_PENDING_INTERRUPT,	"PENDING_INTERRUPT" }, \
+	{ EXIT_REASON_NMI_WINDOW,		"NMI_WINDOW" }, \
+	{ EXIT_REASON_TASK_SWITCH,		"TASK_SWITCH" }, \
+	{ EXIT_REASON_CPUID,			"CPUID" }, \
+	{ EXIT_REASON_HLT,			"HLT" }, \
+	{ EXIT_REASON_INVLPG,			"INVLPG" }, \
+	{ EXIT_REASON_RDPMC,			"RDPMC" }, \
+	{ EXIT_REASON_RDTSC,			"RDTSC" }, \
+	{ EXIT_REASON_VMCALL,			"VMCALL" }, \
+	{ EXIT_REASON_VMCLEAR,			"VMCLEAR" }, \
+	{ EXIT_REASON_VMLAUNCH,			"VMLAUNCH" }, \
+	{ EXIT_REASON_VMPTRLD,			"VMPTRLD" }, \
+	{ EXIT_REASON_VMPTRST,			"VMPTRST" }, \
+	{ EXIT_REASON_VMREAD,			"VMREAD" }, \
+	{ EXIT_REASON_VMRESUME,			"VMRESUME" }, \
+	{ EXIT_REASON_VMWRITE,			"VMWRITE" }, \
+	{ EXIT_REASON_VMOFF,			"VMOFF" }, \
+	{ EXIT_REASON_VMON,			"VMON" }, \
+	{ EXIT_REASON_CR_ACCESS,		"CR_ACCESS" }, \
+	{ EXIT_REASON_DR_ACCESS,		"DR_ACCESS" }, \
+	{ EXIT_REASON_IO_INSTRUCTION,		"IO_INSTRUCTION" }, \
+	{ EXIT_REASON_MSR_READ,			"MSR_READ" }, \
+	{ EXIT_REASON_MSR_WRITE,		"MSR_WRITE" }, \
+	{ EXIT_REASON_MWAIT_INSTRUCTION,	"MWAIT_INSTRUCTION" }, \
+	{ EXIT_REASON_MONITOR_INSTRUCTION,	"MONITOR_INSTRUCTION" }, \
+	{ EXIT_REASON_PAUSE_INSTRUCTION,	"PAUSE_INSTRUCTION" }, \
+	{ EXIT_REASON_MCE_DURING_VMENTRY,	"MCE_DURING_VMENTRY" }, \
+	{ EXIT_REASON_TPR_BELOW_THRESHOLD,	"TPR_BELOW_THRESHOLD" },	\
+	{ EXIT_REASON_APIC_ACCESS,		"APIC_ACCESS" }, \
+	{ EXIT_REASON_EPT_VIOLATION,		"EPT_VIOLATION" }, \
+	{ EXIT_REASON_EPT_MISCONFIG,		"EPT_MISCONFIG" }, \
+	{ EXIT_REASON_WBINVD,			"WBINVD" }
+
+#define SVM_EXIT_REASONS \
+	{ SVM_EXIT_READ_CR0,			"read_cr0" }, \
+	{ SVM_EXIT_READ_CR3,			"read_cr3" }, \
+	{ SVM_EXIT_READ_CR4,			"read_cr4" }, \
+	{ SVM_EXIT_READ_CR8,			"read_cr8" }, \
+	{ SVM_EXIT_WRITE_CR0,			"write_cr0" }, \
+	{ SVM_EXIT_WRITE_CR3,			"write_cr3" }, \
+	{ SVM_EXIT_WRITE_CR4,			"write_cr4" }, \
+	{ SVM_EXIT_WRITE_CR8,			"write_cr8" }, \
+	{ SVM_EXIT_READ_DR0,			"read_dr0" }, \
+	{ SVM_EXIT_READ_DR1,			"read_dr1" }, \
+	{ SVM_EXIT_READ_DR2,			"read_dr2" }, \
+	{ SVM_EXIT_READ_DR3,			"read_dr3" }, \
+	{ SVM_EXIT_WRITE_DR0,			"write_dr0" }, \
+	{ SVM_EXIT_WRITE_DR1,			"write_dr1" }, \
+	{ SVM_EXIT_WRITE_DR2,			"write_dr2" }, \
+	{ SVM_EXIT_WRITE_DR3,			"write_dr3" }, \
+	{ SVM_EXIT_WRITE_DR5,			"write_dr5" }, \
+	{ SVM_EXIT_WRITE_DR7,			"write_dr7" }, \
+	{ SVM_EXIT_EXCP_BASE + DB_VECTOR,	"DB excp" }, \
+	{ SVM_EXIT_EXCP_BASE + BP_VECTOR,	"BP excp" }, \
+	{ SVM_EXIT_EXCP_BASE + UD_VECTOR,	"UD excp" }, \
+	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,	"PF excp" }, \
+	{ SVM_EXIT_EXCP_BASE + NM_VECTOR,	"NM excp" }, \
+	{ SVM_EXIT_EXCP_BASE + MC_VECTOR,	"MC excp" }, \
+	{ SVM_EXIT_INTR,			"interrupt" }, \
+	{ SVM_EXIT_NMI,				"nmi" }, \
+	{ SVM_EXIT_SMI,				"smi" }, \
+	{ SVM_EXIT_INIT,			"init" }, \
+	{ SVM_EXIT_VINTR,			"vintr" }, \
+	{ SVM_EXIT_CPUID,			"cpuid" }, \
+	{ SVM_EXIT_INVD,			"invd" }, \
+	{ SVM_EXIT_HLT,				"hlt" }, \
+	{ SVM_EXIT_INVLPG,			"invlpg" }, \
+	{ SVM_EXIT_INVLPGA,			"invlpga" }, \
+	{ SVM_EXIT_IOIO,			"io" }, \
+	{ SVM_EXIT_MSR,				"msr" }, \
+	{ SVM_EXIT_TASK_SWITCH,			"task_switch" }, \
+	{ SVM_EXIT_SHUTDOWN,			"shutdown" }, \
+	{ SVM_EXIT_VMRUN,			"vmrun" }, \
+	{ SVM_EXIT_VMMCALL,			"hypercall" }, \
+	{ SVM_EXIT_VMLOAD,			"vmload" }, \
+	{ SVM_EXIT_VMSAVE,			"vmsave" }, \
+	{ SVM_EXIT_STGI,			"stgi" }, \
+	{ SVM_EXIT_CLGI,			"clgi" }, \
+	{ SVM_EXIT_SKINIT,			"skinit" }, \
+	{ SVM_EXIT_WBINVD,			"wbinvd" }, \
+	{ SVM_EXIT_MONITOR,			"monitor" }, \
+	{ SVM_EXIT_MWAIT,			"mwait" }, \
+	{ SVM_EXIT_XSETBV,			"xsetbv" }, \
+	{ SVM_EXIT_NPF,				"npf" }
+
 /*
  * Tracepoint for kvm guest exit:
  */
@@ -205,8 +296,9 @@ TRACE_EVENT(kvm_exit,
 	),
 
 	TP_printk("reason %s rip 0x%lx info %llx %llx",
-		 ftrace_print_symbols_seq(p, __entry->exit_reason,
-					  kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_reason, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_reason, SVM_EXIT_REASONS),
 		 __entry->guest_rip, __entry->info1, __entry->info2)
 );
 
@@ -486,9 +578,9 @@ TRACE_EVENT(kvm_nested_intercepts,
 TRACE_EVENT(kvm_nested_vmexit,
 	    TP_PROTO(__u64 rip, __u32 exit_code,
 		     __u64 exit_info1, __u64 exit_info2,
-		     __u32 exit_int_info, __u32 exit_int_info_err),
+		     __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
 	    TP_ARGS(rip, exit_code, exit_info1, exit_info2,
-		    exit_int_info, exit_int_info_err),
+		    exit_int_info, exit_int_info_err, isa),
 
 	TP_STRUCT__entry(
 		__field(	__u64,		rip			)
@@ -497,6 +589,7 @@ TRACE_EVENT(kvm_nested_vmexit,
 		__field(	__u64,		exit_info2		)
 		__field(	__u32,		exit_int_info		)
 		__field(	__u32,		exit_int_info_err	)
+		__field(	__u32,		isa			)
 	),
 
 	TP_fast_assign(
@@ -506,12 +599,14 @@ TRACE_EVENT(kvm_nested_vmexit,
 		__entry->exit_info2		= exit_info2;
 		__entry->exit_int_info		= exit_int_info;
 		__entry->exit_int_info_err	= exit_int_info_err;
+		__entry->isa			= isa;
 	),
 	TP_printk("rip: 0x%016llx reason: %s ext_inf1: 0x%016llx "
 		  "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
 		  __entry->rip,
-		  ftrace_print_symbols_seq(p, __entry->exit_code,
-					   kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
 		  __entry->exit_info1, __entry->exit_info2,
 		  __entry->exit_int_info, __entry->exit_int_info_err)
 );
@@ -522,9 +617,9 @@ TRACE_EVENT(kvm_nested_vmexit,
 TRACE_EVENT(kvm_nested_vmexit_inject,
 	    TP_PROTO(__u32 exit_code,
 		     __u64 exit_info1, __u64 exit_info2,
-		     __u32 exit_int_info, __u32 exit_int_info_err),
+		     __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
 	    TP_ARGS(exit_code, exit_info1, exit_info2,
-		    exit_int_info, exit_int_info_err),
+		    exit_int_info, exit_int_info_err, isa),
 
 	TP_STRUCT__entry(
 		__field(	__u32,		exit_code		)
@@ -532,6 +627,7 @@ TRACE_EVENT(kvm_nested_vmexit_inject,
 		__field(	__u64,		exit_info2		)
 		__field(	__u32,		exit_int_info		)
 		__field(	__u32,		exit_int_info_err	)
+		__field(	__u32,		isa			)
 	),
 
 	TP_fast_assign(
@@ -540,12 +636,14 @@ TRACE_EVENT(kvm_nested_vmexit_inject,
 		__entry->exit_info2		= exit_info2;
 		__entry->exit_int_info		= exit_int_info;
 		__entry->exit_int_info_err	= exit_int_info_err;
+		__entry->isa			= isa;
 	),
 
 	TP_printk("reason: %s ext_inf1: 0x%016llx "
 		  "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
-		  ftrace_print_symbols_seq(p, __entry->exit_code,
-					   kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
 		__entry->exit_info1, __entry->exit_info2,
 		__entry->exit_int_info, __entry->exit_int_info_err)
 );
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/vmx.c linux-libre-3.2-gnu1/arch/x86/kvm/vmx.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/vmx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/vmx.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <asm/mce.h>
 #include <asm/i387.h>
 #include <asm/xcr.h>
+#include <asm/perf_event.h>
 
 #include "trace.h"
 
@@ -71,6 +72,9 @@ module_param(vmm_exclusive, bool, S_IRUG
 static int __read_mostly yield_on_hlt = 1;
 module_param(yield_on_hlt, bool, S_IRUGO);
 
+static int __read_mostly fasteoi = 1;
+module_param(fasteoi, bool, S_IRUGO);
+
 /*
  * If nested=1, nested virtualization is supported, i.e., guests may use
  * VMX and be a hypervisor for its own guests. If nested=0, guests may not
@@ -115,7 +119,7 @@ module_param(ple_gap, int, S_IRUGO);
 static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
-#define NR_AUTOLOAD_MSRS 1
+#define NR_AUTOLOAD_MSRS 8
 #define VMCS02_POOL_SIZE 1
 
 struct vmcs {
@@ -619,6 +623,7 @@ static unsigned long *vmx_msr_bitmap_leg
 static unsigned long *vmx_msr_bitmap_longmode;
 
 static bool cpu_has_load_ia32_efer;
+static bool cpu_has_load_perf_global_ctrl;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -1188,15 +1193,34 @@ static void update_exception_bitmap(stru
 	vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
+static void clear_atomic_switch_msr_special(unsigned long entry,
+		unsigned long exit)
+{
+	vmcs_clear_bits(VM_ENTRY_CONTROLS, entry);
+	vmcs_clear_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
 {
 	unsigned i;
 	struct msr_autoload *m = &vmx->msr_autoload;
 
-	if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-		vmcs_clear_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-		vmcs_clear_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-		return;
+	switch (msr) {
+	case MSR_EFER:
+		if (cpu_has_load_ia32_efer) {
+			clear_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+					VM_EXIT_LOAD_IA32_EFER);
+			return;
+		}
+		break;
+	case MSR_CORE_PERF_GLOBAL_CTRL:
+		if (cpu_has_load_perf_global_ctrl) {
+			clear_atomic_switch_msr_special(
+					VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+					VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+			return;
+		}
+		break;
 	}
 
 	for (i = 0; i < m->nr; ++i)
@@ -1212,25 +1236,55 @@ static void clear_atomic_switch_msr(stru
 	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
 }
 
+static void add_atomic_switch_msr_special(unsigned long entry,
+		unsigned long exit, unsigned long guest_val_vmcs,
+		unsigned long host_val_vmcs, u64 guest_val, u64 host_val)
+{
+	vmcs_write64(guest_val_vmcs, guest_val);
+	vmcs_write64(host_val_vmcs, host_val);
+	vmcs_set_bits(VM_ENTRY_CONTROLS, entry);
+	vmcs_set_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
 				  u64 guest_val, u64 host_val)
 {
 	unsigned i;
 	struct msr_autoload *m = &vmx->msr_autoload;
 
-	if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-		vmcs_write64(GUEST_IA32_EFER, guest_val);
-		vmcs_write64(HOST_IA32_EFER, host_val);
-		vmcs_set_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-		vmcs_set_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-		return;
+	switch (msr) {
+	case MSR_EFER:
+		if (cpu_has_load_ia32_efer) {
+			add_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+					VM_EXIT_LOAD_IA32_EFER,
+					GUEST_IA32_EFER,
+					HOST_IA32_EFER,
+					guest_val, host_val);
+			return;
+		}
+		break;
+	case MSR_CORE_PERF_GLOBAL_CTRL:
+		if (cpu_has_load_perf_global_ctrl) {
+			add_atomic_switch_msr_special(
+					VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+					VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
+					GUEST_IA32_PERF_GLOBAL_CTRL,
+					HOST_IA32_PERF_GLOBAL_CTRL,
+					guest_val, host_val);
+			return;
+		}
+		break;
 	}
 
 	for (i = 0; i < m->nr; ++i)
 		if (m->guest[i].index == msr)
 			break;
 
-	if (i == m->nr) {
+	if (i == NR_AUTOLOAD_MSRS) {
+		printk_once(KERN_WARNING"Not enough mst switch entries. "
+				"Can't add msr %x\n", msr);
+		return;
+	} else if (i == m->nr) {
 		++m->nr;
 		vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
 		vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
@@ -1748,6 +1802,21 @@ static u64 guest_read_tsc(void)
 }
 
 /*
+ * Like guest_read_tsc, but always returns L1's notion of the timestamp
+ * counter, even if a nested guest (L2) is currently running.
+ */
+u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+	u64 host_tsc, tsc_offset;
+
+	rdtscll(host_tsc);
+	tsc_offset = is_guest_mode(vcpu) ?
+		to_vmx(vcpu)->nested.vmcs01_tsc_offset :
+		vmcs_read64(TSC_OFFSET);
+	return host_tsc + tsc_offset;
+}
+
+/*
  * Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
  * ioctl. In this case the call-back should update internal vmx state to make
  * the changes effective.
@@ -1762,15 +1831,23 @@ static void vmx_set_tsc_khz(struct kvm_v
  */
 static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
-	vmcs_write64(TSC_OFFSET, offset);
-	if (is_guest_mode(vcpu))
+	if (is_guest_mode(vcpu)) {
 		/*
-		 * We're here if L1 chose not to trap the TSC MSR. Since
-		 * prepare_vmcs12() does not copy tsc_offset, we need to also
-		 * set the vmcs12 field here.
+		 * We're here if L1 chose not to trap WRMSR to TSC. According
+		 * to the spec, this should set L1's TSC; The offset that L1
+		 * set for L2 remains unchanged, and still needs to be added
+		 * to the newly set TSC to get L2's TSC.
 		 */
-		get_vmcs12(vcpu)->tsc_offset = offset -
-			to_vmx(vcpu)->nested.vmcs01_tsc_offset;
+		struct vmcs12 *vmcs12;
+		to_vmx(vcpu)->nested.vmcs01_tsc_offset = offset;
+		/* recalculate vmcs02.TSC_OFFSET: */
+		vmcs12 = get_vmcs12(vcpu);
+		vmcs_write64(TSC_OFFSET, offset +
+			(nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING) ?
+			 vmcs12->tsc_offset : 0));
+	} else {
+		vmcs_write64(TSC_OFFSET, offset);
+	}
 }
 
 static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
@@ -2429,6 +2506,42 @@ static __init int setup_vmcs_config(stru
 		&& allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
 				   VM_EXIT_LOAD_IA32_EFER);
 
+	cpu_has_load_perf_global_ctrl =
+		allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+				VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+		&& allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+				   VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+	/*
+	 * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
+	 * but due to arrata below it can't be used. Workaround is to use
+	 * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+	 *
+	 * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
+	 *
+	 * AAK155             (model 26)
+	 * AAP115             (model 30)
+	 * AAT100             (model 37)
+	 * BC86,AAY89,BD102   (model 44)
+	 * BA97               (model 46)
+	 *
+	 */
+	if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
+		switch (boot_cpu_data.x86_model) {
+		case 26:
+		case 30:
+		case 37:
+		case 44:
+		case 46:
+			cpu_has_load_perf_global_ctrl = false;
+			printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+					"does not work properly. Using workaround\n");
+			break;
+		default:
+			break;
+		}
+	}
+
 	return 0;
 }
 
@@ -2736,8 +2849,8 @@ static void enter_lmode(struct kvm_vcpu
 
 	guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
 	if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
-		printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
-		       __func__);
+		pr_debug_ratelimited("%s: tss fixup for long mode. \n",
+				     __func__);
 		vmcs_write32(GUEST_TR_AR_BYTES,
 			     (guest_tr_ar & ~AR_TYPE_MASK)
 			     | AR_TYPE_BUSY_64_TSS);
@@ -4115,8 +4228,7 @@ static int handle_exception(struct kvm_v
 		error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
 	if (is_page_fault(intr_info)) {
 		/* EPT won't cause page fault directly */
-		if (enable_ept)
-			BUG();
+		BUG_ON(enable_ept);
 		cr2 = vmcs_readl(EXIT_QUALIFICATION);
 		trace_kvm_page_fault(cr2, error_code);
 
@@ -4518,6 +4630,24 @@ static int handle_xsetbv(struct kvm_vcpu
 
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
+	if (likely(fasteoi)) {
+		unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+		int access_type, offset;
+
+		access_type = exit_qualification & APIC_ACCESS_TYPE;
+		offset = exit_qualification & APIC_ACCESS_OFFSET;
+		/*
+		 * Sane guest uses MOV to write EOI, with written value
+		 * not cared. So make a short-circuit here by avoiding
+		 * heavy instruction emulation.
+		 */
+		if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
+		    (offset == APIC_EOI)) {
+			kvm_lapic_set_eoi(vcpu);
+			skip_emulated_instruction(vcpu);
+			return 1;
+		}
+	}
 	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 }
 
@@ -5591,8 +5721,8 @@ static bool nested_vmx_exit_handled(stru
 		return 0;
 
 	if (unlikely(vmx->fail)) {
-		printk(KERN_INFO "%s failed vm entry %x\n",
-		       __func__, vmcs_read32(VM_INSTRUCTION_ERROR));
+		pr_info_ratelimited("%s failed vm entry %x\n", __func__,
+				    vmcs_read32(VM_INSTRUCTION_ERROR));
 		return 1;
 	}
 
@@ -5696,8 +5826,6 @@ static int vmx_handle_exit(struct kvm_vc
 	u32 exit_reason = vmx->exit_reason;
 	u32 vectoring_info = vmx->idt_vectoring_info;
 
-	trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
-
 	/* If guest state is invalid, start emulating */
 	if (vmx->emulation_required && emulate_invalid_guest_state)
 		return handle_invalid_guest_state(vcpu);
@@ -5927,6 +6055,24 @@ static void vmx_cancel_injection(struct
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
 }
 
+static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
+{
+	int i, nr_msrs;
+	struct perf_guest_switch_msr *msrs;
+
+	msrs = perf_guest_get_msrs(&nr_msrs);
+
+	if (!msrs)
+		return;
+
+	for (i = 0; i < nr_msrs; i++)
+		if (msrs[i].host == msrs[i].guest)
+			clear_atomic_switch_msr(vmx, msrs[i].msr);
+		else
+			add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
+					msrs[i].host);
+}
+
 #ifdef CONFIG_X86_64
 #define R "r"
 #define Q "q"
@@ -5976,6 +6122,8 @@ static void __noclone vmx_vcpu_run(struc
 	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
 		vmx_set_interrupt_shadow(vcpu, 0);
 
+	atomic_switch_perf_msrs(vmx);
+
 	vmx->__launched = vmx->loaded_vmcs->launched;
 	asm(
 		/* Store host registers */
@@ -6101,6 +6249,7 @@ static void __noclone vmx_vcpu_run(struc
 	vmx->loaded_vmcs->launched = 1;
 
 	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+	trace_kvm_exit(vmx->exit_reason, vcpu, KVM_ISA_VMX);
 
 	vmx_complete_atomic_exit(vmx);
 	vmx_recover_nmi_blocking(vmx);
@@ -6241,49 +6390,6 @@ static u64 vmx_get_mt_mask(struct kvm_vc
 	return ret;
 }
 
-#define _ER(x) { EXIT_REASON_##x, #x }
-
-static const struct trace_print_flags vmx_exit_reasons_str[] = {
-	_ER(EXCEPTION_NMI),
-	_ER(EXTERNAL_INTERRUPT),
-	_ER(TRIPLE_FAULT),
-	_ER(PENDING_INTERRUPT),
-	_ER(NMI_WINDOW),
-	_ER(TASK_SWITCH),
-	_ER(CPUID),
-	_ER(HLT),
-	_ER(INVLPG),
-	_ER(RDPMC),
-	_ER(RDTSC),
-	_ER(VMCALL),
-	_ER(VMCLEAR),
-	_ER(VMLAUNCH),
-	_ER(VMPTRLD),
-	_ER(VMPTRST),
-	_ER(VMREAD),
-	_ER(VMRESUME),
-	_ER(VMWRITE),
-	_ER(VMOFF),
-	_ER(VMON),
-	_ER(CR_ACCESS),
-	_ER(DR_ACCESS),
-	_ER(IO_INSTRUCTION),
-	_ER(MSR_READ),
-	_ER(MSR_WRITE),
-	_ER(MWAIT_INSTRUCTION),
-	_ER(MONITOR_INSTRUCTION),
-	_ER(PAUSE_INSTRUCTION),
-	_ER(MCE_DURING_VMENTRY),
-	_ER(TPR_BELOW_THRESHOLD),
-	_ER(APIC_ACCESS),
-	_ER(EPT_VIOLATION),
-	_ER(EPT_MISCONFIG),
-	_ER(WBINVD),
-	{ -1, NULL }
-};
-
-#undef _ER
-
 static int vmx_get_lpage_level(void)
 {
 	if (enable_ept && !cpu_has_vmx_ept_1g_page())
@@ -6514,8 +6620,11 @@ static void prepare_vmcs02(struct kvm_vc
 
 	set_cr4_guest_host_mask(vmx);
 
-	vmcs_write64(TSC_OFFSET,
-		vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+		vmcs_write64(TSC_OFFSET,
+			vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+	else
+		vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
 
 	if (enable_vpid) {
 		/*
@@ -6610,9 +6719,8 @@ static int nested_vmx_run(struct kvm_vcp
 	if (vmcs12->vm_entry_msr_load_count > 0 ||
 	    vmcs12->vm_exit_msr_load_count > 0 ||
 	    vmcs12->vm_exit_msr_store_count > 0) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING
-			  "%s: VMCS MSR_{LOAD,STORE} unsupported\n", __func__);
+		pr_warn_ratelimited("%s: VMCS MSR_{LOAD,STORE} unsupported\n",
+				    __func__);
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 		return 1;
 	}
@@ -6922,7 +7030,7 @@ static void nested_vmx_vmexit(struct kvm
 
 	load_vmcs12_host_state(vcpu, vmcs12);
 
-	/* Update TSC_OFFSET if vmx_adjust_tsc_offset() was used while L2 ran */
+	/* Update TSC_OFFSET if TSC was changed while L2 ran */
 	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
 
 	/* This is needed for same reason as it was needed in prepare_vmcs02 */
@@ -7039,7 +7147,6 @@ static struct kvm_x86_ops vmx_x86_ops =
 	.get_mt_mask = vmx_get_mt_mask,
 
 	.get_exit_info = vmx_get_exit_info,
-	.exit_reasons_str = vmx_exit_reasons_str,
 
 	.get_lpage_level = vmx_get_lpage_level,
 
@@ -7055,6 +7162,7 @@ static struct kvm_x86_ops vmx_x86_ops =
 	.write_tsc_offset = vmx_write_tsc_offset,
 	.adjust_tsc_offset = vmx_adjust_tsc_offset,
 	.compute_tsc_offset = vmx_compute_tsc_offset,
+	.read_l1_tsc = vmx_read_l1_tsc,
 
 	.set_tdp_cr3 = vmx_set_cr3,
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/kvm/x86.c linux-libre-3.2-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.1-gnu1/arch/x86/kvm/x86.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/kvm/x86.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,7 @@
 #include <linux/perf_event.h>
 #include <linux/uaccess.h>
 #include <linux/hash.h>
+#include <linux/pci.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -83,6 +84,7 @@ static u64 __read_mostly efer_reserved_b
 static void update_cr8_intercept(struct kvm_vcpu *vcpu);
 static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 				    struct kvm_cpuid_entry2 __user *entries);
+static void process_nmi(struct kvm_vcpu *vcpu);
 
 struct kvm_x86_ops *kvm_x86_ops;
 EXPORT_SYMBOL_GPL(kvm_x86_ops);
@@ -359,8 +361,8 @@ void kvm_propagate_fault(struct kvm_vcpu
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
 {
-	kvm_make_request(KVM_REQ_EVENT, vcpu);
-	vcpu->arch.nmi_pending = 1;
+	atomic_inc(&vcpu->arch.nmi_queued);
+	kvm_make_request(KVM_REQ_NMI, vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_inject_nmi);
 
@@ -599,6 +601,7 @@ static bool guest_cpuid_has_fsgsbase(str
 static void update_cpuid(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
+	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	best = kvm_find_cpuid_entry(vcpu, 1, 0);
 	if (!best)
@@ -610,6 +613,13 @@ static void update_cpuid(struct kvm_vcpu
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (apic) {
+		if (best->ecx & bit(X86_FEATURE_TSC_DEADLINE_TIMER))
+			apic->lapic_timer.timer_mode_mask = 3 << 17;
+		else
+			apic->lapic_timer.timer_mode_mask = 1 << 17;
+	}
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +835,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1011,7 @@ static inline int kvm_tsc_changes_freq(v
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1098,7 +1109,7 @@ static int kvm_guest_time_update(struct
 
 	/* Keep irq disabled to prevent changes to the clock */
 	local_irq_save(flags);
-	kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp);
+	tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
 	kernel_ns = get_kernel_ns();
 	this_tsc_khz = vcpu_tsc_khz(v);
 	if (unlikely(this_tsc_khz == 0)) {
@@ -1564,6 +1575,9 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1825,6 +1839,9 @@ static int get_msr_hyperv(struct kvm_vcp
 		return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
 	case HV_X64_MSR_TPR:
 		return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+	case HV_X64_MSR_APIC_ASSIST_PAGE:
+		data = vcpu->arch.hv_vapic;
+		break;
 	default:
 		pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
 		return 1;
@@ -1839,7 +1856,6 @@ int kvm_get_msr_common(struct kvm_vcpu *
 
 	switch (msr) {
 	case MSR_IA32_PLATFORM_ID:
-	case MSR_IA32_UCODE_REV:
 	case MSR_IA32_EBL_CR_POWERON:
 	case MSR_IA32_DEBUGCTLMSR:
 	case MSR_IA32_LASTBRANCHFROMIP:
@@ -1860,6 +1876,9 @@ int kvm_get_msr_common(struct kvm_vcpu *
 	case MSR_FAM10H_MMIO_CONF_BASE:
 		data = 0;
 		break;
+	case MSR_IA32_UCODE_REV:
+		data = 0x100000000ULL;
+		break;
 	case MSR_MTRRcap:
 		data = 0x500 | KVM_NR_VAR_MTRR;
 		break;
@@ -1888,6 +1907,9 @@ int kvm_get_msr_common(struct kvm_vcpu *
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
@@ -2086,6 +2108,9 @@ int kvm_dev_ioctl_check_extension(long e
 		r = !kvm_x86_ops->cpu_has_accelerated_tpr();
 		break;
 	case KVM_CAP_NR_VCPUS:
+		r = KVM_SOFT_MAX_VCPUS;
+		break;
+	case KVM_CAP_MAX_VCPUS:
 		r = KVM_MAX_VCPUS;
 		break;
 	case KVM_CAP_NR_MEMSLOTS:
@@ -2095,7 +2120,7 @@ int kvm_dev_ioctl_check_extension(long e
 		r = 0;
 		break;
 	case KVM_CAP_IOMMU:
-		r = iommu_found();
+		r = iommu_present(&pci_bus_type);
 		break;
 	case KVM_CAP_MCE:
 		r = KVM_MAX_MCE_BANKS;
@@ -2106,6 +2131,9 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_TSC_CONTROL:
 		r = kvm_has_tsc_control;
 		break;
+	case KVM_CAP_TSC_DEADLINE_TIMER:
+		r = boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER);
+		break;
 	default:
 		r = 0;
 		break;
@@ -2210,7 +2238,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 		s64 tsc_delta;
 		u64 tsc;
 
-		kvm_get_msr(vcpu, MSR_IA32_TSC, &tsc);
+		tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 		tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
 			     tsc - vcpu->arch.last_guest_tsc;
 
@@ -2234,7 +2262,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
 {
 	kvm_x86_ops->vcpu_put(vcpu);
 	kvm_put_guest_fpu(vcpu);
-	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+	vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 }
 
 static int is_efer_nx(void)
@@ -2819,6 +2847,7 @@ static int kvm_vcpu_ioctl_x86_set_mce(st
 static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
 					       struct kvm_vcpu_events *events)
 {
+	process_nmi(vcpu);
 	events->exception.injected =
 		vcpu->arch.exception.pending &&
 		!kvm_exception_is_soft(vcpu->arch.exception.nr);
@@ -2836,7 +2865,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_
 			KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI);
 
 	events->nmi.injected = vcpu->arch.nmi_injected;
-	events->nmi.pending = vcpu->arch.nmi_pending;
+	events->nmi.pending = vcpu->arch.nmi_pending != 0;
 	events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu);
 	events->nmi.pad = 0;
 
@@ -2856,6 +2885,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_e
 			      | KVM_VCPUEVENT_VALID_SHADOW))
 		return -EINVAL;
 
+	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
 	vcpu->arch.exception.has_error_code = events->exception.has_error_code;
@@ -3556,7 +3586,11 @@ long kvm_arch_vm_ioctl(struct file *filp
 			if (r) {
 				mutex_lock(&kvm->slots_lock);
 				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-							  &vpic->dev);
+							  &vpic->dev_master);
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev_slave);
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev_eclr);
 				mutex_unlock(&kvm->slots_lock);
 				kfree(vpic);
 				goto create_irqchip_unlock;
@@ -4045,84 +4079,105 @@ static int vcpu_mmio_gva_to_gpa(struct k
 	return 0;
 }
 
-static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
-				  unsigned long addr,
-				  void *val,
-				  unsigned int bytes,
-				  struct x86_exception *exception)
+int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+			const void *val, int bytes)
 {
-	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
-	gpa_t gpa;
-	int handled, ret;
+	int ret;
+
+	ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
+	if (ret < 0)
+		return 0;
+	kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
+	return 1;
+}
+
+struct read_write_emulator_ops {
+	int (*read_write_prepare)(struct kvm_vcpu *vcpu, void *val,
+				  int bytes);
+	int (*read_write_emulate)(struct kvm_vcpu *vcpu, gpa_t gpa,
+				  void *val, int bytes);
+	int (*read_write_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+			       int bytes, void *val);
+	int (*read_write_exit_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+				    void *val, int bytes);
+	bool write;
+};
 
+static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
+{
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
 			       vcpu->mmio_phys_addr, *(u64 *)val);
 		vcpu->mmio_read_completed = 0;
-		return X86EMUL_CONTINUE;
+		return 1;
 	}
 
-	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
-
-	if (ret < 0)
-		return X86EMUL_PROPAGATE_FAULT;
-
-	if (ret)
-		goto mmio;
-
-	if (kvm_read_guest_virt(ctxt, addr, val, bytes, exception)
-	    == X86EMUL_CONTINUE)
-		return X86EMUL_CONTINUE;
+	return 0;
+}
 
-mmio:
-	/*
-	 * Is this MMIO handled locally?
-	 */
-	handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
+static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+			void *val, int bytes)
+{
+	return !kvm_read_guest(vcpu->kvm, gpa, val, bytes);
+}
 
-	if (handled == bytes)
-		return X86EMUL_CONTINUE;
+static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+			 void *val, int bytes)
+{
+	return emulator_write_phys(vcpu, gpa, val, bytes);
+}
 
-	gpa += handled;
-	bytes -= handled;
-	val += handled;
+static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
+{
+	trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
+	return vcpu_mmio_write(vcpu, gpa, bytes, val);
+}
 
+static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+			  void *val, int bytes)
+{
 	trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
-
-	vcpu->mmio_needed = 1;
-	vcpu->run->exit_reason = KVM_EXIT_MMIO;
-	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
-	vcpu->mmio_size = bytes;
-	vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
-	vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
-	vcpu->mmio_index = 0;
-
 	return X86EMUL_IO_NEEDED;
 }
 
-int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
-			const void *val, int bytes)
+static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+			   void *val, int bytes)
 {
-	int ret;
-
-	ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
-	if (ret < 0)
-		return 0;
-	kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
-	return 1;
+	memcpy(vcpu->mmio_data, val, bytes);
+	memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+	return X86EMUL_CONTINUE;
 }
 
-static int emulator_write_emulated_onepage(unsigned long addr,
-					   const void *val,
-					   unsigned int bytes,
-					   struct x86_exception *exception,
-					   struct kvm_vcpu *vcpu)
+static struct read_write_emulator_ops read_emultor = {
+	.read_write_prepare = read_prepare,
+	.read_write_emulate = read_emulate,
+	.read_write_mmio = vcpu_mmio_read,
+	.read_write_exit_mmio = read_exit_mmio,
+};
+
+static struct read_write_emulator_ops write_emultor = {
+	.read_write_emulate = write_emulate,
+	.read_write_mmio = write_mmio,
+	.read_write_exit_mmio = write_exit_mmio,
+	.write = true,
+};
+
+static int emulator_read_write_onepage(unsigned long addr, void *val,
+				       unsigned int bytes,
+				       struct x86_exception *exception,
+				       struct kvm_vcpu *vcpu,
+				       struct read_write_emulator_ops *ops)
 {
 	gpa_t gpa;
 	int handled, ret;
+	bool write = ops->write;
 
-	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
+	if (ops->read_write_prepare &&
+		  ops->read_write_prepare(vcpu, val, bytes))
+		return X86EMUL_CONTINUE;
+
+	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
 
 	if (ret < 0)
 		return X86EMUL_PROPAGATE_FAULT;
@@ -4131,15 +4186,14 @@ static int emulator_write_emulated_onepa
 	if (ret)
 		goto mmio;
 
-	if (emulator_write_phys(vcpu, gpa, val, bytes))
+	if (ops->read_write_emulate(vcpu, gpa, val, bytes))
 		return X86EMUL_CONTINUE;
 
 mmio:
-	trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
 	/*
 	 * Is this MMIO handled locally?
 	 */
-	handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
+	handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
 	if (handled == bytes)
 		return X86EMUL_CONTINUE;
 
@@ -4148,23 +4202,20 @@ mmio:
 	val += handled;
 
 	vcpu->mmio_needed = 1;
-	memcpy(vcpu->mmio_data, val, bytes);
 	vcpu->run->exit_reason = KVM_EXIT_MMIO;
 	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
 	vcpu->mmio_size = bytes;
 	vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
-	vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
-	memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+	vcpu->run->mmio.is_write = vcpu->mmio_is_write = write;
 	vcpu->mmio_index = 0;
 
-	return X86EMUL_CONTINUE;
+	return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
 }
 
-int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
-			    unsigned long addr,
-			    const void *val,
-			    unsigned int bytes,
-			    struct x86_exception *exception)
+int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
+			void *val, unsigned int bytes,
+			struct x86_exception *exception,
+			struct read_write_emulator_ops *ops)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 
@@ -4173,16 +4224,38 @@ int emulator_write_emulated(struct x86_e
 		int rc, now;
 
 		now = -addr & ~PAGE_MASK;
-		rc = emulator_write_emulated_onepage(addr, val, now, exception,
-						     vcpu);
+		rc = emulator_read_write_onepage(addr, val, now, exception,
+						 vcpu, ops);
+
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		addr += now;
 		val += now;
 		bytes -= now;
 	}
-	return emulator_write_emulated_onepage(addr, val, bytes, exception,
-					       vcpu);
+
+	return emulator_read_write_onepage(addr, val, bytes, exception,
+					   vcpu, ops);
+}
+
+static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
+				  unsigned long addr,
+				  void *val,
+				  unsigned int bytes,
+				  struct x86_exception *exception)
+{
+	return emulator_read_write(ctxt, addr, val, bytes,
+				   exception, &read_emultor);
+}
+
+int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
+			    unsigned long addr,
+			    const void *val,
+			    unsigned int bytes,
+			    struct x86_exception *exception)
+{
+	return emulator_read_write(ctxt, addr, (void *)val, bytes,
+				   exception, &write_emultor);
 }
 
 #define CMPXCHG_TYPE(t, ptr, old, new) \
@@ -4712,7 +4785,7 @@ int kvm_inject_realmode_interrupt(struct
 	kvm_set_rflags(vcpu, ctxt->eflags);
 
 	if (irq == NMI_VECTOR)
-		vcpu->arch.nmi_pending = false;
+		vcpu->arch.nmi_pending = 0;
 	else
 		vcpu->arch.interrupt.pending = false;
 
@@ -4788,7 +4861,7 @@ int x86_emulate_instruction(struct kvm_v
 
 		trace_kvm_emulate_insn_start(vcpu);
 		++vcpu->stat.insn_emulation;
-		if (r)  {
+		if (r != EMULATION_OK)  {
 			if (emulation_type & EMULTYPE_TRAP_UD)
 				return EMULATE_FAIL;
 			if (reexecute_instruction(vcpu, cr2))
@@ -5521,7 +5594,7 @@ static void inject_pending_event(struct
 	/* try to inject new event if pending */
 	if (vcpu->arch.nmi_pending) {
 		if (kvm_x86_ops->nmi_allowed(vcpu)) {
-			vcpu->arch.nmi_pending = false;
+			--vcpu->arch.nmi_pending;
 			vcpu->arch.nmi_injected = true;
 			kvm_x86_ops->set_nmi(vcpu);
 		}
@@ -5553,10 +5626,26 @@ static void kvm_put_guest_xcr0(struct kv
 	}
 }
 
+static void process_nmi(struct kvm_vcpu *vcpu)
+{
+	unsigned limit = 2;
+
+	/*
+	 * x86 is limited to one NMI running, and one NMI pending after it.
+	 * If an NMI is already in progress, limit further NMIs to just one.
+	 * Otherwise, allow two (and we'll inject the first one immediately).
+	 */
+	if (kvm_x86_ops->get_nmi_mask(vcpu) || vcpu->arch.nmi_injected)
+		limit = 1;
+
+	vcpu->arch.nmi_pending += atomic_xchg(&vcpu->arch.nmi_queued, 0);
+	vcpu->arch.nmi_pending = min(vcpu->arch.nmi_pending, limit);
+	kvm_make_request(KVM_REQ_EVENT, vcpu);
+}
+
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 {
 	int r;
-	bool nmi_pending;
 	bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
 		vcpu->run->request_interrupt_window;
 
@@ -5596,6 +5685,8 @@ static int vcpu_enter_guest(struct kvm_v
 		}
 		if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
 			record_steal_time(vcpu);
+		if (kvm_check_request(KVM_REQ_NMI, vcpu))
+			process_nmi(vcpu);
 
 	}
 
@@ -5603,19 +5694,11 @@ static int vcpu_enter_guest(struct kvm_v
 	if (unlikely(r))
 		goto out;
 
-	/*
-	 * An NMI can be injected between local nmi_pending read and
-	 * vcpu->arch.nmi_pending read inside inject_pending_event().
-	 * But in that case, KVM_REQ_EVENT will be set, which makes
-	 * the race described above benign.
-	 */
-	nmi_pending = ACCESS_ONCE(vcpu->arch.nmi_pending);
-
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
 		inject_pending_event(vcpu);
 
 		/* enable NMI/IRQ window open exits if needed */
-		if (nmi_pending)
+		if (vcpu->arch.nmi_pending)
 			kvm_x86_ops->enable_nmi_window(vcpu);
 		else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
 			kvm_x86_ops->enable_irq_window(vcpu);
@@ -5678,7 +5761,7 @@ static int vcpu_enter_guest(struct kvm_v
 	if (hw_breakpoint_active())
 		hw_breakpoint_restore();
 
-	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+	vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
@@ -6323,7 +6406,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vc
 
 int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.nmi_pending = false;
+	atomic_set(&vcpu->arch.nmi_queued, 0);
+	vcpu->arch.nmi_pending = 0;
 	vcpu->arch.nmi_injected = false;
 
 	vcpu->arch.switch_db_regs = 0;
@@ -6598,7 +6682,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vc
 		!vcpu->arch.apf.halted)
 		|| !list_empty_careful(&vcpu->async_pf.done)
 		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
-		|| vcpu->arch.nmi_pending ||
+		|| atomic_read(&vcpu->arch.nmi_queued) ||
 		(kvm_arch_interrupt_allowed(vcpu) &&
 		 kvm_cpu_has_interrupt(vcpu));
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/lguest/boot.c linux-libre-3.2-gnu1/arch/x86/lguest/boot.c
--- linux-libre-3.1-gnu1/arch/x86/lguest/boot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/lguest/boot.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,7 @@
 #include <linux/lguest_launcher.h>
 #include <linux/virtio_console.h>
 #include <linux/pm.h>
+#include <linux/export.h>
 #include <asm/apic.h>
 #include <asm/lguest.h>
 #include <asm/paravirt.h>
@@ -70,6 +71,7 @@
 #include <asm/i387.h>
 #include <asm/stackprotector.h>
 #include <asm/reboot.h>		/* for struct machine_ops */
+#include <asm/kvm_para.h>
 
 /*G:010
  * Welcome to the Guest!
@@ -455,6 +457,15 @@ static void lguest_cpuid(unsigned int *a
 		*ax &= 0xFFFFF0FF;
 		*ax |= 0x00000500;
 		break;
+
+	/*
+	 * This is used to detect if we're running under KVM.  We might be,
+	 * but that's a Host matter, not us.  So say we're not.
+	 */
+	case KVM_CPUID_SIGNATURE:
+		*bx = *cx = *dx = 0;
+		break;
+
 	/*
 	 * 0x80000000 returns the highest Extended Function, so we futureproof
 	 * like we do above by limiting it to known fields.
diff -druNp linux-libre-3.1-gnu1/arch/x86/lib/insn.c linux-libre-3.2-gnu1/arch/x86/lib/insn.c
--- linux-libre-3.1-gnu1/arch/x86/lib/insn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/lib/insn.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,14 +22,23 @@
 #include <asm/inat.h>
 #include <asm/insn.h>
 
-#define get_next(t, insn)	\
-	({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+/* Verify next sizeof(t) bytes can be on the same instruction */
+#define validate_next(t, insn, n)	\
+	((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
 
-#define peek_next(t, insn)	\
-	({t r; r = *(t*)insn->next_byte; r; })
+#define __get_next(t, insn)	\
+	({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+
+#define __peek_nbyte_next(t, insn, n)	\
+	({ t r = *(t*)((insn)->next_byte + n); r; })
+
+#define get_next(t, insn)	\
+	({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
 
 #define peek_nbyte_next(t, insn, n)	\
-	({t r; r = *(t*)((insn)->next_byte + n); r; })
+	({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
+
+#define peek_next(t, insn)	peek_nbyte_next(t, insn, 0)
 
 /**
  * insn_init() - initialize struct insn
@@ -158,6 +167,8 @@ vex_end:
 	insn->vex_prefix.got = 1;
 
 	prefixes->got = 1;
+
+err_out:
 	return;
 }
 
@@ -208,6 +219,9 @@ void insn_get_opcode(struct insn *insn)
 		insn->attr = 0;	/* This instruction is bad */
 end:
 	opcode->got = 1;
+
+err_out:
+	return;
 }
 
 /**
@@ -241,6 +255,9 @@ void insn_get_modrm(struct insn *insn)
 	if (insn->x86_64 && inat_is_force64(insn->attr))
 		insn->opnd_bytes = 8;
 	modrm->got = 1;
+
+err_out:
+	return;
 }
 
 
@@ -290,6 +307,9 @@ void insn_get_sib(struct insn *insn)
 		}
 	}
 	insn->sib.got = 1;
+
+err_out:
+	return;
 }
 
 
@@ -351,6 +371,9 @@ void insn_get_displacement(struct insn *
 	}
 out:
 	insn->displacement.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode moffset16/32/64 */
@@ -373,6 +396,9 @@ static void __get_moffset(struct insn *i
 		break;
 	}
 	insn->moffset1.got = insn->moffset2.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode imm v32(Iz) */
@@ -389,6 +415,9 @@ static void __get_immv32(struct insn *in
 		insn->immediate.nbytes = 4;
 		break;
 	}
+
+err_out:
+	return;
 }
 
 /* Decode imm v64(Iv/Ov) */
@@ -411,6 +440,9 @@ static void __get_immv(struct insn *insn
 		break;
 	}
 	insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode ptr16:16/32(Ap) */
@@ -432,6 +464,9 @@ static void __get_immptr(struct insn *in
 	insn->immediate2.value = get_next(unsigned short, insn);
 	insn->immediate2.nbytes = 2;
 	insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+	return;
 }
 
 /**
@@ -496,6 +531,9 @@ void insn_get_immediate(struct insn *ins
 	}
 done:
 	insn->immediate.got = 1;
+
+err_out:
+	return;
 }
 
 /**
diff -druNp linux-libre-3.1-gnu1/arch/x86/Makefile.um linux-libre-3.2-gnu1/arch/x86/Makefile.um
--- linux-libre-3.1-gnu1/arch/x86/Makefile.um	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/Makefile.um	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+core-y += arch/x86/crypto/
+
+ifeq ($(CONFIG_X86_32),y)
+START := 0x8048000
+
+LDFLAGS			+= -m elf_i386
+ELF_ARCH		:= i386
+ELF_FORMAT 		:= elf32-i386
+CHECKFLAGS	+= -D__i386__
+
+ifeq ("$(origin SUBARCH)", "command line")
+ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
+KBUILD_CFLAGS		+= $(call cc-option,-m32)
+KBUILD_AFLAGS		+= $(call cc-option,-m32)
+LINK-y			+= $(call cc-option,-m32)
+
+export LDFLAGS
+endif
+endif
+
+# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
+include $(srctree)/arch/x86/Makefile_32.cpu
+
+# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
+cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
+
+# Prevent sprintf in nfsd from being converted to strcpy and resulting in
+# an unresolved reference.
+cflags-y += -ffreestanding
+
+# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
+# 4.3.0 needs -funit-at-a-time for extern inline functions.
+KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
+			echo $(call cc-option,-fno-unit-at-a-time); \
+			else echo $(call cc-option,-funit-at-a-time); fi ;)
+
+KBUILD_CFLAGS += $(cflags-y)
+
+else
+
+START := 0x60000000
+
+KBUILD_CFLAGS += -fno-builtin -m64 
+
+CHECKFLAGS  += -m64 -D__x86_64__
+KBUILD_AFLAGS += -m64
+LDFLAGS += -m elf_x86_64
+KBUILD_CPPFLAGS += -m64
+
+ELF_ARCH := i386:x86-64
+ELF_FORMAT := elf64-x86-64
+
+# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
+
+LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-y += -m64
+
+# Do unit-at-a-time unconditionally on x86_64, following the host
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
+endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/mm/fault.c linux-libre-3.2-gnu1/arch/x86/mm/fault.c
--- linux-libre-3.1-gnu1/arch/x86/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/traps.h>			/* dotraplinkage, ...		*/
 #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
 #include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
-#include <asm/vsyscall.h>
+#include <asm/fixmap.h>			/* VSYSCALL_START		*/
 
 /*
  * Page fault error code bits:
@@ -420,12 +420,14 @@ static noinline __kprobes int vmalloc_fa
 	return 0;
 }
 
+#ifdef CONFIG_CPU_SUP_AMD
 static const char errata93_warning[] =
 KERN_ERR 
 "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
 "******* Working around it, but it may cause SEGVs or burn power.\n"
 "******* Please consider a BIOS update.\n"
 "******* Disabling USB legacy in the BIOS may also help.\n";
+#endif
 
 /*
  * No vm86 mode in 64-bit mode:
@@ -505,7 +507,11 @@ bad:
  */
 static int is_errata93(struct pt_regs *regs, unsigned long address)
 {
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD)
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD
+	    || boot_cpu_data.x86 != 0xf)
+		return 0;
+
 	if (address != regs->ip)
 		return 0;
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/mm/gup.c linux-libre-3.2-gnu1/arch/x86/mm/gup.c
--- linux-libre-3.1-gnu1/arch/x86/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,16 +108,6 @@ static inline void get_head_page_multipl
 	SetPageReferenced(page);
 }
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
 		unsigned long end, int write, struct page **pages, int *nr)
 {
@@ -211,6 +201,8 @@ static noinline int gup_huge_pud(pud_t p
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
+		if (PageTail(page))
+			get_huge_page_tail(page);
 		(*nr)++;
 		page++;
 		refs++;
diff -druNp linux-libre-3.1-gnu1/arch/x86/mm/highmem_32.c linux-libre-3.2-gnu1/arch/x86/mm/highmem_32.c
--- linux-libre-3.1-gnu1/arch/x86/mm/highmem_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/mm/highmem_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@ void *kmap_atomic_prot(struct page *page
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	BUG_ON(!pte_none(*(kmap_pte-idx)));
 	set_pte(kmap_pte-idx, mk_pte(page, prot));
+	arch_flush_lazy_mmu_mode();
 
 	return (void *)vaddr;
 }
@@ -88,6 +89,7 @@ void __kunmap_atomic(void *kvaddr)
 		 */
 		kpte_clear_flush(kmap_pte-idx, vaddr);
 		kmap_atomic_idx_pop();
+		arch_flush_lazy_mmu_mode();
 	}
 #ifdef CONFIG_DEBUG_HIGHMEM
 	else {
diff -druNp linux-libre-3.1-gnu1/arch/x86/mm/mmap.c linux-libre-3.2-gnu1/arch/x86/mm/mmap.c
--- linux-libre-3.1-gnu1/arch/x86/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,10 @@
 #include <linux/sched.h>
 #include <asm/elf.h>
 
+struct __read_mostly va_alignment va_align = {
+	.flags = -1,
+};
+
 static unsigned int stack_maxrandom_size(void)
 {
 	unsigned int max = 0;
@@ -42,7 +46,6 @@ static unsigned int stack_maxrandom_size
 	return max;
 }
 
-
 /*
  * Top of mmap area (just below the process stack).
  *
@@ -51,21 +54,6 @@ static unsigned int stack_maxrandom_size
 #define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
 #define MAX_GAP (TASK_SIZE/6*5)
 
-/*
- * True on X86_32 or when emulating IA32 on X86_64
- */
-static int mmap_is_ia32(void)
-{
-#ifdef CONFIG_X86_32
-	return 1;
-#endif
-#ifdef CONFIG_IA32_EMULATION
-	if (test_thread_flag(TIF_IA32))
-		return 1;
-#endif
-	return 0;
-}
-
 static int mmap_is_legacy(void)
 {
 	if (current->personality & ADDR_COMPAT_LAYOUT)
diff -druNp linux-libre-3.1-gnu1/arch/x86/mm/mmio-mod.c linux-libre-3.2-gnu1/arch/x86/mm/mmio-mod.c
--- linux-libre-3.1-gnu1/arch/x86/mm/mmio-mod.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/mm/mmio-mod.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/version.h>
 #include <linux/kallsyms.h>
 #include <asm/pgtable.h>
 #include <linux/mmiotrace.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/net/bpf_jit_comp.c linux-libre-3.2-gnu1/arch/x86/net/bpf_jit_comp.c
--- linux-libre-3.1-gnu1/arch/x86/net/bpf_jit_comp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/net/bpf_jit_comp.c	2012-01-04 18:55:44.000000000 -0500
@@ -568,8 +568,8 @@ cond_branch:			f_offset = addrs[i + filt
 					break;
 				}
 				if (filter[i].jt != 0) {
-					if (filter[i].jf)
-						t_offset += is_near(f_offset) ? 2 : 6;
+					if (filter[i].jf && f_offset)
+						t_offset += is_near(f_offset) ? 2 : 5;
 					EMIT_COND_JMP(t_op, t_offset);
 					if (filter[i].jf)
 						EMIT_JMP(f_offset);
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/init.c linux-libre-3.2-gnu1/arch/x86/oprofile/init.c
--- linux-libre-3.1-gnu1/arch/x86/oprofile/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct opro
 extern void op_nmi_exit(void);
 extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
 
+static int nmi_timer;
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
@@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct opr
 #ifdef CONFIG_X86_LOCAL_APIC
 	ret = op_nmi_init(ops);
 #endif
+	nmi_timer = (ret != 0);
 #ifdef CONFIG_X86_IO_APIC
-	if (ret < 0)
+	if (nmi_timer)
 		ret = op_nmi_timer_init(ops);
 #endif
 	ops->backtrace = x86_backtrace;
@@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct opr
 void oprofile_arch_exit(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-	op_nmi_exit();
+	if (!nmi_timer)
+		op_nmi_exit();
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/nmi_int.c linux-libre-3.2-gnu1/arch/x86/oprofile/nmi_int.c
--- linux-libre-3.1-gnu1/arch/x86/oprofile/nmi_int.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/nmi_int.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,26 +61,15 @@ u64 op_x86_get_ctrl(struct op_x86_model_
 }
 
 
-static int profile_exceptions_notify(struct notifier_block *self,
-				     unsigned long val, void *data)
+static int profile_exceptions_notify(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
-	int ret = NOTIFY_DONE;
-
-	switch (val) {
-	case DIE_NMI:
-		if (ctr_running)
-			model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs));
-		else if (!nmi_enabled)
-			break;
-		else
-			model->stop(&__get_cpu_var(cpu_msrs));
-		ret = NOTIFY_STOP;
-		break;
-	default:
-		break;
-	}
-	return ret;
+	if (ctr_running)
+		model->check_ctrs(regs, &__get_cpu_var(cpu_msrs));
+	else if (!nmi_enabled)
+		return NMI_DONE;
+	else
+		model->stop(&__get_cpu_var(cpu_msrs));
+	return NMI_HANDLED;
 }
 
 static void nmi_cpu_save_registers(struct op_msrs *msrs)
@@ -355,20 +344,14 @@ static void nmi_cpu_setup(void *dummy)
 	int cpu = smp_processor_id();
 	struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
 	nmi_cpu_save_registers(msrs);
-	spin_lock(&oprofilefs_lock);
+	raw_spin_lock(&oprofilefs_lock);
 	model->setup_ctrs(model, msrs);
 	nmi_cpu_setup_mux(cpu, msrs);
-	spin_unlock(&oprofilefs_lock);
+	raw_spin_unlock(&oprofilefs_lock);
 	per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
-static struct notifier_block profile_exceptions_nb = {
-	.notifier_call = profile_exceptions_notify,
-	.next = NULL,
-	.priority = NMI_LOCAL_LOW_PRIOR,
-};
-
 static void nmi_cpu_restore_registers(struct op_msrs *msrs)
 {
 	struct op_msr *counters = msrs->counters;
@@ -402,8 +385,6 @@ static void nmi_cpu_shutdown(void *dummy
 	apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
 	apic_write(APIC_LVTERR, v);
 	nmi_cpu_restore_registers(msrs);
-	if (model->cpu_down)
-		model->cpu_down();
 }
 
 static void nmi_cpu_up(void *dummy)
@@ -508,7 +489,8 @@ static int nmi_setup(void)
 	ctr_running = 0;
 	/* make variables visible to the nmi handler: */
 	smp_mb();
-	err = register_die_notifier(&profile_exceptions_nb);
+	err = register_nmi_handler(NMI_LOCAL, profile_exceptions_notify,
+					0, "oprofile");
 	if (err)
 		goto fail;
 
@@ -538,7 +520,7 @@ static void nmi_shutdown(void)
 	put_online_cpus();
 	/* make variables visible to the nmi handler: */
 	smp_mb();
-	unregister_die_notifier(&profile_exceptions_nb);
+	unregister_nmi_handler(NMI_LOCAL, "oprofile");
 	msrs = &get_cpu_var(cpu_msrs);
 	model->shutdown(msrs);
 	free_msrs();
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/nmi_timer_int.c linux-libre-3.2-gnu1/arch/x86/oprofile/nmi_timer_int.c
--- linux-libre-3.1-gnu1/arch/x86/oprofile/nmi_timer_int.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/nmi_timer_int.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,32 +18,16 @@
 #include <asm/apic.h>
 #include <asm/ptrace.h>
 
-static int profile_timer_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
+static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
-	int ret = NOTIFY_DONE;
-
-	switch (val) {
-	case DIE_NMI:
-		oprofile_add_sample(args->regs, 0);
-		ret = NOTIFY_STOP;
-		break;
-	default:
-		break;
-	}
-	return ret;
+	oprofile_add_sample(regs, 0);
+	return NMI_HANDLED;
 }
 
-static struct notifier_block profile_timer_exceptions_nb = {
-	.notifier_call = profile_timer_exceptions_notify,
-	.next = NULL,
-	.priority = NMI_LOW_PRIOR,
-};
-
 static int timer_start(void)
 {
-	if (register_die_notifier(&profile_timer_exceptions_nb))
+	if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify,
+					0, "oprofile-timer"))
 		return 1;
 	return 0;
 }
@@ -51,7 +35,7 @@ static int timer_start(void)
 
 static void timer_stop(void)
 {
-	unregister_die_notifier(&profile_timer_exceptions_nb);
+	unregister_nmi_handler(NMI_LOCAL, "oprofile-timer");
 	synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/op_model_amd.c linux-libre-3.2-gnu1/arch/x86/oprofile/op_model_amd.c
--- linux-libre-3.1-gnu1/arch/x86/oprofile/op_model_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/op_model_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,8 +29,6 @@
 #include "op_x86_model.h"
 #include "op_counter.h"
 
-#define NUM_COUNTERS		4
-#define NUM_COUNTERS_F15H	6
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 #define NUM_VIRT_COUNTERS	32
 #else
@@ -70,62 +68,12 @@ static struct ibs_config ibs_config;
 static struct ibs_state ibs_state;
 
 /*
- * IBS cpuid feature detection
- */
-
-#define IBS_CPUID_FEATURES		0x8000001b
-
-/*
- * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
- * bit 0 is used to indicate the existence of IBS.
- */
-#define IBS_CAPS_AVAIL			(1U<<0)
-#define IBS_CAPS_FETCHSAM		(1U<<1)
-#define IBS_CAPS_OPSAM			(1U<<2)
-#define IBS_CAPS_RDWROPCNT		(1U<<3)
-#define IBS_CAPS_OPCNT			(1U<<4)
-#define IBS_CAPS_BRNTRGT		(1U<<5)
-#define IBS_CAPS_OPCNTEXT		(1U<<6)
-
-#define IBS_CAPS_DEFAULT		(IBS_CAPS_AVAIL		\
-					 | IBS_CAPS_FETCHSAM	\
-					 | IBS_CAPS_OPSAM)
-
-/*
- * IBS APIC setup
- */
-#define IBSCTL				0x1cc
-#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
-#define IBSCTL_LVT_OFFSET_MASK		0x0F
-
-/*
  * IBS randomization macros
  */
 #define IBS_RANDOM_BITS			12
 #define IBS_RANDOM_MASK			((1ULL << IBS_RANDOM_BITS) - 1)
 #define IBS_RANDOM_MAXCNT_OFFSET	(1ULL << (IBS_RANDOM_BITS - 5))
 
-static u32 get_ibs_caps(void)
-{
-	u32 ibs_caps;
-	unsigned int max_level;
-
-	if (!boot_cpu_has(X86_FEATURE_IBS))
-		return 0;
-
-	/* check IBS cpuid feature flags */
-	max_level = cpuid_eax(0x80000000);
-	if (max_level < IBS_CPUID_FEATURES)
-		return IBS_CAPS_DEFAULT;
-
-	ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
-	if (!(ibs_caps & IBS_CAPS_AVAIL))
-		/* cpuid flags not valid */
-		return IBS_CAPS_DEFAULT;
-
-	return ibs_caps;
-}
-
 /*
  * 16-bit Linear Feedback Shift Register (LFSR)
  *
@@ -316,81 +264,6 @@ static void op_amd_stop_ibs(void)
 		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
-static inline int get_eilvt(int offset)
-{
-	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
-}
-
-static inline int put_eilvt(int offset)
-{
-	return !setup_APIC_eilvt(offset, 0, 0, 1);
-}
-
-static inline int ibs_eilvt_valid(void)
-{
-	int offset;
-	u64 val;
-	int valid = 0;
-
-	preempt_disable();
-
-	rdmsrl(MSR_AMD64_IBSCTL, val);
-	offset = val & IBSCTL_LVT_OFFSET_MASK;
-
-	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
-		pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
-		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		goto out;
-	}
-
-	if (!get_eilvt(offset)) {
-		pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
-		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		goto out;
-	}
-
-	valid = 1;
-out:
-	preempt_enable();
-
-	return valid;
-}
-
-static inline int get_ibs_offset(void)
-{
-	u64 val;
-
-	rdmsrl(MSR_AMD64_IBSCTL, val);
-	if (!(val & IBSCTL_LVT_OFFSET_VALID))
-		return -EINVAL;
-
-	return val & IBSCTL_LVT_OFFSET_MASK;
-}
-
-static void setup_APIC_ibs(void)
-{
-	int offset;
-
-	offset = get_ibs_offset();
-	if (offset < 0)
-		goto failed;
-
-	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
-		return;
-failed:
-	pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
-		smp_processor_id());
-}
-
-static void clear_APIC_ibs(void)
-{
-	int offset;
-
-	offset = get_ibs_offset();
-	if (offset >= 0)
-		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
-}
-
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -439,7 +312,7 @@ static int op_amd_fill_in_addresses(stru
 			goto fail;
 		}
 		/* both registers must be reserved */
-		if (num_counters == NUM_COUNTERS_F15H) {
+		if (num_counters == AMD64_NUM_COUNTERS_F15H) {
 			msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
 			msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
 		} else {
@@ -504,15 +377,6 @@ static void op_amd_setup_ctrs(struct op_
 		val |= op_x86_get_ctrl(model, &counter_config[virt]);
 		wrmsrl(msrs->controls[i].addr, val);
 	}
-
-	if (ibs_caps)
-		setup_APIC_ibs();
-}
-
-static void op_amd_cpu_shutdown(void)
-{
-	if (ibs_caps)
-		clear_APIC_ibs();
 }
 
 static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -575,86 +439,6 @@ static void op_amd_stop(struct op_msrs c
 	op_amd_stop_ibs();
 }
 
-static int setup_ibs_ctl(int ibs_eilvt_off)
-{
-	struct pci_dev *cpu_cfg;
-	int nodes;
-	u32 value = 0;
-
-	nodes = 0;
-	cpu_cfg = NULL;
-	do {
-		cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
-					 PCI_DEVICE_ID_AMD_10H_NB_MISC,
-					 cpu_cfg);
-		if (!cpu_cfg)
-			break;
-		++nodes;
-		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-				       | IBSCTL_LVT_OFFSET_VALID);
-		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
-			pci_dev_put(cpu_cfg);
-			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-			       "IBSCTL = 0x%08x\n", value);
-			return -EINVAL;
-		}
-	} while (1);
-
-	if (!nodes) {
-		printk(KERN_DEBUG "No CPU node configured for IBS\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-/*
- * This runs only on the current cpu. We try to find an LVT offset and
- * setup the local APIC. For this we must disable preemption. On
- * success we initialize all nodes with this offset. This updates then
- * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
- * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_-
- * amd_cpu_shutdown() using the new offset.
- */
-static int force_ibs_eilvt_setup(void)
-{
-	int offset;
-	int ret;
-
-	preempt_disable();
-	/* find the next free available EILVT entry, skip offset 0 */
-	for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
-		if (get_eilvt(offset))
-			break;
-	}
-	preempt_enable();
-
-	if (offset == APIC_EILVT_NR_MAX) {
-		printk(KERN_DEBUG "No EILVT entry available\n");
-		return -EBUSY;
-	}
-
-	ret = setup_ibs_ctl(offset);
-	if (ret)
-		goto out;
-
-	if (!ibs_eilvt_valid()) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
-	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
-
-	return 0;
-out:
-	preempt_disable();
-	put_eilvt(offset);
-	preempt_enable();
-	return ret;
-}
-
 /*
  * check and reserve APIC extended interrupt LVT offset for IBS if
  * available
@@ -667,17 +451,6 @@ static void init_ibs(void)
 	if (!ibs_caps)
 		return;
 
-	if (ibs_eilvt_valid())
-		goto out;
-
-	if (!force_ibs_eilvt_setup())
-		goto out;
-
-	/* Failed to setup ibs */
-	ibs_caps = 0;
-	return;
-
-out:
 	printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
 }
 
@@ -741,9 +514,9 @@ static int op_amd_init(struct oprofile_o
 	ops->create_files = setup_ibs_files;
 
 	if (boot_cpu_data.x86 == 0x15) {
-		num_counters = NUM_COUNTERS_F15H;
+		num_counters = AMD64_NUM_COUNTERS_F15H;
 	} else {
-		num_counters = NUM_COUNTERS;
+		num_counters = AMD64_NUM_COUNTERS;
 	}
 
 	op_amd_spec.num_counters = num_counters;
@@ -760,7 +533,6 @@ struct op_x86_model_spec op_amd_spec = {
 	.init			= op_amd_init,
 	.fill_in_addresses	= &op_amd_fill_in_addresses,
 	.setup_ctrs		= &op_amd_setup_ctrs,
-	.cpu_down		= &op_amd_cpu_shutdown,
 	.check_ctrs		= &op_amd_check_ctrs,
 	.start			= &op_amd_start,
 	.stop			= &op_amd_stop,
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/op_model_ppro.c linux-libre-3.2-gnu1/arch/x86/oprofile/op_model_ppro.c
--- linux-libre-3.1-gnu1/arch/x86/oprofile/op_model_ppro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/op_model_ppro.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@ static int counter_width = 32;
 
 #define MSR_PPRO_EVENTSEL_RESERVED	((0xFFFFFFFFULL<<32)|(1ULL<<21))
 
-static u64 *reset_value;
+static u64 reset_value[OP_MAX_COUNTER];
 
 static void ppro_shutdown(struct op_msrs const * const msrs)
 {
@@ -40,10 +40,6 @@ static void ppro_shutdown(struct op_msrs
 		release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
 		release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
 	}
-	if (reset_value) {
-		kfree(reset_value);
-		reset_value = NULL;
-	}
 }
 
 static int ppro_fill_in_addresses(struct op_msrs * const msrs)
@@ -79,13 +75,6 @@ static void ppro_setup_ctrs(struct op_x8
 	u64 val;
 	int i;
 
-	if (!reset_value) {
-		reset_value = kzalloc(sizeof(reset_value[0]) * num_counters,
-					GFP_ATOMIC);
-		if (!reset_value)
-			return;
-	}
-
 	if (cpu_has_arch_perfmon) {
 		union cpuid10_eax eax;
 		eax.full = cpuid_eax(0xa);
@@ -141,13 +130,6 @@ static int ppro_check_ctrs(struct pt_reg
 	u64 val;
 	int i;
 
-	/*
-	 * This can happen if perf counters are in use when
-	 * we steal the die notifier NMI.
-	 */
-	if (unlikely(!reset_value))
-		goto out;
-
 	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[i])
 			continue;
@@ -158,7 +140,6 @@ static int ppro_check_ctrs(struct pt_reg
 		wrmsrl(msrs->counters[i].addr, -reset_value[i]);
 	}
 
-out:
 	/* Only P6 based Pentium M need to re-unmask the apic vector but it
 	 * doesn't hurt other P6 variant */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
@@ -179,8 +160,6 @@ static void ppro_start(struct op_msrs co
 	u64 val;
 	int i;
 
-	if (!reset_value)
-		return;
 	for (i = 0; i < num_counters; ++i) {
 		if (reset_value[i]) {
 			rdmsrl(msrs->controls[i].addr, val);
@@ -196,8 +175,6 @@ static void ppro_stop(struct op_msrs con
 	u64 val;
 	int i;
 
-	if (!reset_value)
-		return;
 	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[i])
 			continue;
@@ -242,7 +219,7 @@ static void arch_perfmon_setup_counters(
 		eax.split.bit_width = 40;
 	}
 
-	num_counters = eax.split.num_counters;
+	num_counters = min((int)eax.split.num_counters, OP_MAX_COUNTER);
 
 	op_arch_perfmon_spec.num_counters = num_counters;
 	op_arch_perfmon_spec.num_controls = num_counters;
diff -druNp linux-libre-3.1-gnu1/arch/x86/oprofile/op_x86_model.h linux-libre-3.2-gnu1/arch/x86/oprofile/op_x86_model.h
--- linux-libre-3.1-gnu1/arch/x86/oprofile/op_x86_model.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/oprofile/op_x86_model.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@ struct op_x86_model_spec {
 	int		(*fill_in_addresses)(struct op_msrs * const msrs);
 	void		(*setup_ctrs)(struct op_x86_model_spec const *model,
 				      struct op_msrs const * const msrs);
-	void		(*cpu_down)(void);
 	int		(*check_ctrs)(struct pt_regs * const regs,
 				      struct op_msrs const * const msrs);
 	void		(*start)(struct op_msrs const * const msrs);
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/ce4100.c linux-libre-3.2-gnu1/arch/x86/pci/ce4100.c
--- linux-libre-3.1-gnu1/arch/x86/pci/ce4100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/ce4100.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,7 +304,7 @@ static int ce4100_conf_write(unsigned in
 	return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
 }
 
-struct pci_raw_ops ce4100_pci_conf = {
+static const struct pci_raw_ops ce4100_pci_conf = {
 	.read =	ce4100_conf_read,
 	.write = ce4100_conf_write,
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/common.c linux-libre-3.2-gnu1/arch/x86/pci/common.c
--- linux-libre-3.1-gnu1/arch/x86/pci/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,8 @@ int noioapicreroute = 1;
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
 struct pci_bus *pci_root_bus;
-struct pci_raw_ops *raw_pci_ops;
-struct pci_raw_ops *raw_pci_ext_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
 
 int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
 						int reg, int len, u32 *val)
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/direct.c linux-libre-3.2-gnu1/arch/x86/pci/direct.c
--- linux-libre-3.1-gnu1/arch/x86/pci/direct.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/direct.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@ static int pci_conf1_write(unsigned int
 
 #undef PCI_CONF1_ADDRESS
 
-struct pci_raw_ops pci_direct_conf1 = {
+const struct pci_raw_ops pci_direct_conf1 = {
 	.read =		pci_conf1_read,
 	.write =	pci_conf1_write,
 };
@@ -175,7 +175,7 @@ static int pci_conf2_write(unsigned int
 
 #undef PCI_CONF2_ADDRESS
 
-struct pci_raw_ops pci_direct_conf2 = {
+static const struct pci_raw_ops pci_direct_conf2 = {
 	.read =		pci_conf2_read,
 	.write =	pci_conf2_write,
 };
@@ -191,7 +191,7 @@ struct pci_raw_ops pci_direct_conf2 = {
  * This should be close to trivial, but it isn't, because there are buggy
  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  */
-static int __init pci_sanity_check(struct pci_raw_ops *o)
+static int __init pci_sanity_check(const struct pci_raw_ops *o)
 {
 	u32 x = 0;
 	int year, devfn;
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/i386.c linux-libre-3.2-gnu1/arch/x86/pci/i386.c
--- linux-libre-3.1-gnu1/arch/x86/pci/i386.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/i386.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/legacy.c linux-libre-3.2-gnu1/arch/x86/pci/legacy.c
--- linux-libre-3.1-gnu1/arch/x86/pci/legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * legacy.c - traditional, old school PCI bus probing
  */
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/pci_x86.h>
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/mmconfig_32.c linux-libre-3.2-gnu1/arch/x86/pci/mmconfig_32.c
--- linux-libre-3.1-gnu1/arch/x86/pci/mmconfig_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/mmconfig_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@ static int pci_mmcfg_write(unsigned int
 	return 0;
 }
 
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/mmconfig_64.c linux-libre-3.2-gnu1/arch/x86/pci/mmconfig_64.c
--- linux-libre-3.1-gnu1/arch/x86/pci/mmconfig_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/mmconfig_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@ static int pci_mmcfg_write(unsigned int
 	return 0;
 }
 
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/numaq_32.c linux-libre-3.2-gnu1/arch/x86/pci/numaq_32.c
--- linux-libre-3.1-gnu1/arch/x86/pci/numaq_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/numaq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,7 @@ static int pci_conf1_mq_write(unsigned i
 
 #undef PCI_CONF1_MQ_ADDRESS
 
-static struct pci_raw_ops pci_direct_conf1_mq = {
+static const struct pci_raw_ops pci_direct_conf1_mq = {
 	.read	= pci_conf1_mq_read,
 	.write	= pci_conf1_mq_write
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/olpc.c linux-libre-3.2-gnu1/arch/x86/pci/olpc.c
--- linux-libre-3.1-gnu1/arch/x86/pci/olpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/olpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -301,7 +301,7 @@ static int pci_olpc_write(unsigned int s
 	return 0;
 }
 
-static struct pci_raw_ops pci_olpc_conf = {
+static const struct pci_raw_ops pci_olpc_conf = {
 	.read =	pci_olpc_read,
 	.write = pci_olpc_write,
 };
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/pcbios.c linux-libre-3.2-gnu1/arch/x86/pci/pcbios.c
--- linux-libre-3.1-gnu1/arch/x86/pci/pcbios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/pcbios.c	2012-01-04 18:55:44.000000000 -0500
@@ -303,7 +303,7 @@ static int pci_bios_write(unsigned int s
  * Function table for BIOS32 access
  */
 
-static struct pci_raw_ops pci_bios_access = {
+static const struct pci_raw_ops pci_bios_access = {
 	.read =		pci_bios_read,
 	.write =	pci_bios_write
 };
@@ -312,7 +312,7 @@ static struct pci_raw_ops pci_bios_acces
  * Try to find PCI BIOS.
  */
 
-static struct pci_raw_ops * __devinit pci_find_bios(void)
+static const struct pci_raw_ops * __devinit pci_find_bios(void)
 {
 	union bios32 *check;
 	unsigned char sum;
diff -druNp linux-libre-3.1-gnu1/arch/x86/pci/xen.c linux-libre-3.2-gnu1/arch/x86/pci/xen.c
--- linux-libre-3.1-gnu1/arch/x86/pci/xen.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/pci/xen.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,8 +175,10 @@ static int xen_setup_msi_irqs(struct pci
 					       "pcifront-msi-x" :
 					       "pcifront-msi",
 						DOMID_SELF);
-		if (irq < 0)
+		if (irq < 0) {
+			ret = irq;
 			goto free;
+		}
 		i++;
 	}
 	kfree(v);
@@ -221,8 +223,10 @@ static int xen_hvm_setup_msi_irqs(struct
 		if (msg.data != XEN_PIRQ_MSI_DATA ||
 		    xen_irq_from_pirq(pirq) < 0) {
 			pirq = xen_allocate_pirq_msi(dev, msidesc);
-			if (pirq < 0)
+			if (pirq < 0) {
+				irq = -ENODEV;
 				goto error;
+			}
 			xen_msi_compose_msg(dev, pirq, &msg);
 			__write_msi_msg(msidesc, &msg);
 			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
@@ -244,10 +248,12 @@ static int xen_hvm_setup_msi_irqs(struct
 error:
 	dev_err(&dev->dev,
 		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
-	return -ENODEV;
+	return irq;
 }
 
 #ifdef CONFIG_XEN_DOM0
+static bool __read_mostly pci_seg_supported = true;
+
 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	int ret = 0;
@@ -265,10 +271,11 @@ static int xen_initdom_setup_msi_irqs(st
 
 		memset(&map_irq, 0, sizeof(map_irq));
 		map_irq.domid = domid;
-		map_irq.type = MAP_PIRQ_TYPE_MSI;
+		map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
 		map_irq.index = -1;
 		map_irq.pirq = -1;
-		map_irq.bus = dev->bus->number;
+		map_irq.bus = dev->bus->number |
+			      (pci_domain_nr(dev->bus) << 16);
 		map_irq.devfn = dev->devfn;
 
 		if (type == PCI_CAP_ID_MSIX) {
@@ -285,7 +292,20 @@ static int xen_initdom_setup_msi_irqs(st
 			map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
 		}
 
-		ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+		ret = -EINVAL;
+		if (pci_seg_supported)
+			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+						    &map_irq);
+		if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
+			map_irq.type = MAP_PIRQ_TYPE_MSI;
+			map_irq.index = -1;
+			map_irq.pirq = -1;
+			map_irq.bus = dev->bus->number;
+			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+						    &map_irq);
+			if (ret != -EINVAL)
+				pci_seg_supported = false;
+		}
 		if (ret) {
 			dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
 				 ret, domid);
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/ce4100/ce4100.c linux-libre-3.2-gnu1/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-3.1-gnu1/arch/x86/platform/ce4100/ce4100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/ce4100/ce4100.c	2012-01-04 18:55:44.000000000 -0500
@@ -109,7 +109,7 @@ static __init void sdv_serial_fixup(void
 }
 
 #else
-static inline void sdv_serial_fixup(void);
+static inline void sdv_serial_fixup(void) {};
 #endif
 
 static void __init sdv_arch_setup(void)
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/efi/efi_32.c linux-libre-3.2-gnu1/arch/x86/platform/efi/efi_32.c
--- linux-libre-3.1-gnu1/arch/x86/platform/efi/efi_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/efi/efi_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/efi.h>
 
 #include <asm/io.h>
+#include <asm/desc.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -38,43 +39,14 @@
  */
 
 static unsigned long efi_rt_eflags;
-static pgd_t efi_bak_pg_dir_pointer[2];
 
 void efi_call_phys_prelog(void)
 {
-	unsigned long cr4;
-	unsigned long temp;
 	struct desc_ptr gdt_descr;
 
 	local_irq_save(efi_rt_eflags);
 
-	/*
-	 * If I don't have PAE, I should just duplicate two entries in page
-	 * directory. If I have PAE, I just need to duplicate one entry in
-	 * page directory.
-	 */
-	cr4 = read_cr4_safe();
-
-	if (cr4 & X86_CR4_PAE) {
-		efi_bak_pg_dir_pointer[0].pgd =
-		    swapper_pg_dir[pgd_index(0)].pgd;
-		swapper_pg_dir[0].pgd =
-		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
-	} else {
-		efi_bak_pg_dir_pointer[0].pgd =
-		    swapper_pg_dir[pgd_index(0)].pgd;
-		efi_bak_pg_dir_pointer[1].pgd =
-		    swapper_pg_dir[pgd_index(0x400000)].pgd;
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
-		temp = PAGE_OFFSET + 0x400000;
-		swapper_pg_dir[pgd_index(0x400000)].pgd =
-		    swapper_pg_dir[pgd_index(temp)].pgd;
-	}
-
-	/*
-	 * After the lock is released, the original page table is restored.
-	 */
+	load_cr3(initial_page_table);
 	__flush_tlb_all();
 
 	gdt_descr.address = __pa(get_cpu_gdt_table(0));
@@ -84,28 +56,13 @@ void efi_call_phys_prelog(void)
 
 void efi_call_phys_epilog(void)
 {
-	unsigned long cr4;
 	struct desc_ptr gdt_descr;
 
 	gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
 	gdt_descr.size = GDT_SIZE - 1;
 	load_gdt(&gdt_descr);
 
-	cr4 = read_cr4_safe();
-
-	if (cr4 & X86_CR4_PAE) {
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    efi_bak_pg_dir_pointer[0].pgd;
-	} else {
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    efi_bak_pg_dir_pointer[0].pgd;
-		swapper_pg_dir[pgd_index(0x400000)].pgd =
-		    efi_bak_pg_dir_pointer[1].pgd;
-	}
-
-	/*
-	 * After the lock is released, the original page table is restored.
-	 */
+	load_cr3(swapper_pg_dir);
 	__flush_tlb_all();
 
 	local_irq_restore(efi_rt_eflags);
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/efi/efi.c linux-libre-3.2-gnu1/arch/x86/platform/efi/efi.c
--- linux-libre-3.1-gnu1/arch/x86/platform/efi/efi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/efi/efi.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/geode/alix.c linux-libre-3.2-gnu1/arch/x86/platform/geode/alix.c
--- linux-libre-3.1-gnu1/arch/x86/platform/geode/alix.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/platform/geode/alix.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,142 @@
+/*
+ * System Specific setup for PCEngines ALIX.
+ * At the moment this means setup of GPIO control of LEDs
+ * on Alix.2/3/6 boards.
+ *
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to platform
+ *
+ * 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/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/geode.h>
+
+static int force = 0;
+module_param(force, bool, 0444);
+/* FIXME: Award bios is not automatically detected as Alix platform */
+MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform");
+
+static struct gpio_led alix_leds[] = {
+	{
+		.name = "alix:1",
+		.gpio = 6,
+		.default_trigger = "default-on",
+		.active_low = 1,
+	},
+	{
+		.name = "alix:2",
+		.gpio = 25,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+	{
+		.name = "alix:3",
+		.gpio = 27,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led_platform_data alix_leds_data = {
+	.num_leds = ARRAY_SIZE(alix_leds),
+	.leds = alix_leds,
+};
+
+static struct platform_device alix_leds_dev = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev.platform_data = &alix_leds_data,
+};
+
+static void __init register_alix(void)
+{
+	/* Setup LED control through leds-gpio driver */
+	platform_device_register(&alix_leds_dev);
+}
+
+static int __init alix_present(unsigned long bios_phys,
+				const char *alix_sig,
+				size_t alix_sig_len)
+{
+	const size_t bios_len = 0x00010000;
+	const char *bios_virt;
+	const char *scan_end;
+	const char *p;
+	char name[64];
+
+	if (force) {
+		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
+		       "assume system is ALIX.2/ALIX.3\n",
+		       KBUILD_MODNAME);
+		return 1;
+	}
+
+	bios_virt = phys_to_virt(bios_phys);
+	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
+	for (p = bios_virt; p < scan_end; p++) {
+		const char *tail;
+		char *a;
+
+		if (memcmp(p, alix_sig, alix_sig_len) != 0)
+			continue;
+
+		memcpy(name, p, sizeof(name));
+
+		/* remove the first \0 character from string */
+		a = strchr(name, '\0');
+		if (a)
+			*a = ' ';
+
+		/* cut the string at a newline */
+		a = strchr(name, '\r');
+		if (a)
+			*a = '\0';
+
+		tail = p + alix_sig_len;
+		if ((tail[0] == '2' || tail[0] == '3')) {
+			printk(KERN_INFO
+			       "%s: system is recognized as \"%s\"\n",
+			       KBUILD_MODNAME, name);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int __init alix_init(void)
+{
+	const char tinybios_sig[] = "PC Engines ALIX.";
+	const char coreboot_sig[] = "PC Engines\0ALIX.";
+
+	if (!is_geode())
+		return 0;
+
+	if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
+	    alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
+		register_alix();
+
+	return 0;
+}
+
+module_init(alix_init);
+
+MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
+MODULE_DESCRIPTION("PCEngines ALIX System Setup");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/geode/Makefile linux-libre-3.2-gnu1/arch/x86/platform/geode/Makefile
--- linux-libre-3.1-gnu1/arch/x86/platform/geode/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/platform/geode/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+obj-$(CONFIG_ALIX)		+= alix.o
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/Makefile linux-libre-3.2-gnu1/arch/x86/platform/Makefile
--- linux-libre-3.1-gnu1/arch/x86/platform/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 # Platform specific code goes here
 obj-y	+= ce4100/
 obj-y	+= efi/
+obj-y	+= geode/
 obj-y	+= iris/
 obj-y	+= mrst/
 obj-y	+= olpc/
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/mrst/mrst.c linux-libre-3.2-gnu1/arch/x86/platform/mrst/mrst.c
--- linux-libre-3.1-gnu1/arch/x86/platform/mrst/mrst.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/mrst/mrst.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
 #include <linux/sfi.h>
 #include <linux/intel_pmic_gpio.h>
 #include <linux/spi/spi.h>
@@ -24,6 +26,8 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/mfd/intel_msic.h>
 
 #include <asm/setup.h>
 #include <asm/mpspec_def.h>
@@ -72,6 +76,20 @@ struct sfi_rtc_table_entry sfi_mrtc_arra
 EXPORT_SYMBOL_GPL(sfi_mrtc_array);
 int sfi_mrtc_num;
 
+static void mrst_power_off(void)
+{
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
+		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1);
+}
+
+static void mrst_reboot(void)
+{
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
+		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0);
+	else
+		intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
+}
+
 /* parse all the mtimer info to a static mtimer array */
 static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 {
@@ -183,11 +201,34 @@ int __init sfi_parse_mrtc(struct sfi_tab
 static unsigned long __init mrst_calibrate_tsc(void)
 {
 	unsigned long flags, fast_calibrate;
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+		u32 lo, hi, ratio, fsb;
 
-	local_irq_save(flags);
-	fast_calibrate = apbt_quick_calibrate();
-	local_irq_restore(flags);
-
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+		ratio = (hi >> 8) & 0x1f;
+		pr_debug("ratio is %d\n", ratio);
+		if (!ratio) {
+			pr_err("read a zero ratio, should be incorrect!\n");
+			pr_err("force tsc ratio to 16 ...\n");
+			ratio = 16;
+		}
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		if ((lo & 0x7) == 0x7)
+			fsb = PENWELL_FSB_FREQ_83SKU;
+		else
+			fsb = PENWELL_FSB_FREQ_100SKU;
+		fast_calibrate = ratio * fsb;
+		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+		lapic_timer_frequency = fsb * 1000 / HZ;
+		/* mark tsc clocksource as reliable */
+		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	} else {
+		local_irq_save(flags);
+		fast_calibrate = apbt_quick_calibrate();
+		local_irq_restore(flags);
+	}
+	
 	if (fast_calibrate)
 		return fast_calibrate;
 
@@ -238,15 +279,15 @@ static int mrst_i8042_detect(void)
 	return 0;
 }
 
-/* Reboot and power off are handled by the SCU on a MID device */
-static void mrst_power_off(void)
-{
-	intel_scu_ipc_simple_command(0xf1, 1);
-}
-
-static void mrst_reboot(void)
+/*
+ * Moorestown does not have external NMI source nor port 0x61 to report
+ * NMI status. The possible NMI sources are from pmu as a result of NMI
+ * watchdog or lock debug. Reading io port 0x61 results in 0xff which
+ * misled NMI handler.
+ */
+static unsigned char mrst_get_nmi_reason(void)
 {
-	intel_scu_ipc_simple_command(0xf1, 0);
+	return 0;
 }
 
 /*
@@ -270,6 +311,8 @@ void __init x86_mrst_early_setup(void)
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
 	x86_init.timers.wallclock_init = mrst_rtc_init;
+	x86_platform.get_nmi_reason = mrst_get_nmi_reason;
+
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
@@ -392,6 +435,7 @@ static void __init *max3111_platform_dat
 	struct spi_board_info *spi_info = info;
 	int intr = get_gpio_by_name("max3111_int");
 
+	spi_info->mode = SPI_MODE_0;
 	if (intr == -1)
 		return NULL;
 	spi_info->irq = intr + MRST_IRQ_OFFSET;
@@ -443,6 +487,46 @@ static void __init *max7315_platform_dat
 	return max7315;
 }
 
+static void *tca6416_platform_data(void *info)
+{
+	static struct pca953x_platform_data tca6416;
+	struct i2c_board_info *i2c_info = info;
+	int gpio_base, intr;
+	char base_pin_name[SFI_NAME_LEN + 1];
+	char intr_pin_name[SFI_NAME_LEN + 1];
+
+	strcpy(i2c_info->type, "tca6416");
+	strcpy(base_pin_name, "tca6416_base");
+	strcpy(intr_pin_name, "tca6416_int");
+
+	gpio_base = get_gpio_by_name(base_pin_name);
+	intr = get_gpio_by_name(intr_pin_name);
+
+	if (gpio_base == -1)
+		return NULL;
+	tca6416.gpio_base = gpio_base;
+	if (intr != -1) {
+		i2c_info->irq = intr + MRST_IRQ_OFFSET;
+		tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET;
+	} else {
+		i2c_info->irq = -1;
+		tca6416.irq_base = -1;
+	}
+	return &tca6416;
+}
+
+static void *mpu3050_platform_data(void *info)
+{
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("mpu3050_int");
+
+	if (intr == -1)
+		return NULL;
+
+	i2c_info->irq = intr + MRST_IRQ_OFFSET;
+	return NULL;
+}
+
 static void __init *emc1403_platform_data(void *info)
 {
 	static short intr2nd_pdata;
@@ -480,15 +564,148 @@ static void __init *no_platform_data(voi
 	return NULL;
 }
 
+static struct resource msic_resources[] = {
+	{
+		.start	= INTEL_MSIC_IRQ_PHYS_BASE,
+		.end	= INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct intel_msic_platform_data msic_pdata;
+
+static struct platform_device msic_device = {
+	.name		= "intel_msic",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &msic_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(msic_resources),
+	.resource	= msic_resources,
+};
+
+static inline bool mrst_has_msic(void)
+{
+	return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
+}
+
+static int msic_scu_status_change(struct notifier_block *nb,
+				  unsigned long code, void *data)
+{
+	if (code == SCU_DOWN) {
+		platform_device_unregister(&msic_device);
+		return 0;
+	}
+
+	return platform_device_register(&msic_device);
+}
+
+static int __init msic_init(void)
+{
+	static struct notifier_block msic_scu_notifier = {
+		.notifier_call	= msic_scu_status_change,
+	};
+
+	/*
+	 * We need to be sure that the SCU IPC is ready before MSIC device
+	 * can be registered.
+	 */
+	if (mrst_has_msic())
+		intel_scu_notifier_add(&msic_scu_notifier);
+
+	return 0;
+}
+arch_initcall(msic_init);
+
+/*
+ * msic_generic_platform_data - sets generic platform data for the block
+ * @info: pointer to the SFI device table entry for this block
+ * @block: MSIC block
+ *
+ * Function sets IRQ number from the SFI table entry for given device to
+ * the MSIC platform data.
+ */
+static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
+{
+	struct sfi_device_table_entry *entry = info;
+
+	BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
+	msic_pdata.irq[block] = entry->irq;
+
+	return no_platform_data(info);
+}
+
+static void *msic_battery_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
+}
+
+static void *msic_gpio_platform_data(void *info)
+{
+	static struct intel_msic_gpio_pdata pdata;
+	int gpio = get_gpio_by_name("msic_gpio_base");
+
+	if (gpio < 0)
+		return NULL;
+
+	pdata.gpio_base = gpio;
+	msic_pdata.gpio = &pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
+}
+
+static void *msic_audio_platform_data(void *info)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		pr_err("failed to create audio platform device\n");
+		return NULL;
+	}
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
+}
+
+static void *msic_power_btn_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
+}
+
+static void *msic_ocd_platform_data(void *info)
+{
+	static struct intel_msic_ocd_pdata pdata;
+	int gpio = get_gpio_by_name("ocd_gpio");
+
+	if (gpio < 0)
+		return NULL;
+
+	pdata.gpio = gpio;
+	msic_pdata.ocd = &pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
+}
+
 static const struct devs_id __initconst device_ids[] = {
+	{"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
 	{"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
+	{"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},
 	{"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
 	{"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
 	{"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
+	{"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data},
 	{"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
 	{"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
 	{"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
-	{"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
+	{"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
+
+	/* MSIC subdevices */
+	{"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
+	{"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
+	{"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
+	{"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
+	{"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
+
 	{},
 };
 
@@ -555,6 +772,9 @@ static void __init intel_scu_i2c_device_
 	i2c_devs[i2c_next_dev++] = new_dev;
 }
 
+BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
+EXPORT_SYMBOL_GPL(intel_scu_notifier);
+
 /* Called by IPC driver */
 void intel_scu_devices_create(void)
 {
@@ -579,6 +799,7 @@ void intel_scu_devices_create(void)
 		} else
 			i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
 	}
+	intel_scu_notifier_post(SCU_AVAILABLE, 0L);
 }
 EXPORT_SYMBOL_GPL(intel_scu_devices_create);
 
@@ -587,6 +808,8 @@ void intel_scu_devices_destroy(void)
 {
 	int i;
 
+	intel_scu_notifier_post(SCU_DOWN, 0L);
+
 	for (i = 0; i < ipc_next_dev; i++)
 		platform_device_del(ipc_devs[i]);
 }
@@ -603,19 +826,37 @@ static void __init install_irq_resource(
 	platform_device_add_resources(pdev, &res, 1);
 }
 
-static void __init sfi_handle_ipc_dev(struct platform_device *pdev)
+static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
 {
 	const struct devs_id *dev = device_ids;
+	struct platform_device *pdev;
 	void *pdata = NULL;
 
 	while (dev->name[0]) {
 		if (dev->type == SFI_DEV_TYPE_IPC &&
-			!strncmp(dev->name, pdev->name, SFI_NAME_LEN)) {
-			pdata = dev->get_platform_data(pdev);
+			!strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
+			pdata = dev->get_platform_data(entry);
 			break;
 		}
 		dev++;
 	}
+
+	/*
+	 * On Medfield the platform device creation is handled by the MSIC
+	 * MFD driver so we don't need to do it here.
+	 */
+	if (mrst_has_msic())
+		return;
+
+	/* ID as IRQ is a hack that will go away */
+	pdev = platform_device_alloc(entry->name, entry->irq);
+	if (pdev == NULL) {
+		pr_err("out of memory for SFI platform device '%s'.\n",
+			entry->name);
+		return;
+	}
+	install_irq_resource(pdev, entry->irq);
+
 	pdev->dev.platform_data = pdata;
 	intel_scu_device_register(pdev);
 }
@@ -668,7 +909,6 @@ static int __init sfi_parse_devs(struct
 	struct sfi_device_table_entry *pentry;
 	struct spi_board_info spi_info;
 	struct i2c_board_info i2c_info;
-	struct platform_device *pdev;
 	int num, i, bus;
 	int ioapic;
 	struct io_apic_irq_attr irq_attr;
@@ -696,17 +936,9 @@ static int __init sfi_parse_devs(struct
 
 		switch (pentry->type) {
 		case SFI_DEV_TYPE_IPC:
-			/* ID as IRQ is a hack that will go away */
-			pdev = platform_device_alloc(pentry->name, irq);
-			if (pdev == NULL) {
-				pr_err("out of memory for SFI platform device '%s'.\n",
-							pentry->name);
-				continue;
-			}
-			install_irq_resource(pdev, irq);
 			pr_debug("info[%2d]: IPC bus, name = %16.16s, "
-				"irq = 0x%2x\n", i, pentry->name, irq);
-			sfi_handle_ipc_dev(pdev);
+				"irq = 0x%2x\n", i, pentry->name, pentry->irq);
+			sfi_handle_ipc_dev(pentry);
 			break;
 		case SFI_DEV_TYPE_SPI:
 			memset(&spi_info, 0, sizeof(spi_info));
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/mrst/pmu.c linux-libre-3.2-gnu1/arch/x86/platform/mrst/pmu.c
--- linux-libre-3.1-gnu1/arch/x86/platform/mrst/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/mrst/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@ static struct mrst_device mrst_devs[] =
 /* 24 */ { 0x4110, 0 },			/* Lincroft */
 };
 
-/* n.b. We ignore PCI-id 0x815 in LSS9 b/c MeeGo has no driver for it */
+/* n.b. We ignore PCI-id 0x815 in LSS9 b/c Linux has no driver for it */
 static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
 static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803,
 					0x0804, 0x0805, 0x080f, 0};
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/mrst/vrtc.c linux-libre-3.2-gnu1/arch/x86/platform/mrst/vrtc.c
--- linux-libre-3.1-gnu1/arch/x86/platform/mrst/vrtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/mrst/vrtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
@@ -75,8 +76,8 @@ unsigned long vrtc_get_time(void)
 
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
-	/* vRTC YEAR reg contains the offset to 1960 */
-	year += 1960;
+	/* vRTC YEAR reg contains the offset to 1972 */
+	year += 1972;
 
 	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
 		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/olpc/olpc-xo1-pm.c linux-libre-3.2-gnu1/arch/x86/platform/olpc/olpc-xo1-pm.c
--- linux-libre-3.1-gnu1/arch/x86/platform/olpc/olpc-xo1-pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/olpc/olpc-xo1-pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/cs5535.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 #include <linux/mfd/core.h>
 #include <linux/suspend.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/uv/bios_uv.c linux-libre-3.2-gnu1/arch/x86/platform/uv/bios_uv.c
--- linux-libre-3.1-gnu1/arch/x86/platform/uv/bios_uv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/uv/bios_uv.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <asm/efi.h>
 #include <linux/io.h>
 #include <asm/uv/bios.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/platform/uv/tlb_uv.c linux-libre-3.2-gnu1/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-3.1-gnu1/arch/x86/platform/uv/tlb_uv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/platform/uv/tlb_uv.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
 
 /* base pnode in this partition */
 static int uv_base_pnode __read_mostly;
-/* position of pnode (which is nasid>>1): */
-static int uv_nshift __read_mostly;
-static unsigned long uv_mmask __read_mostly;
 
 static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
 static DEFINE_PER_CPU(struct bau_control, bau_control);
@@ -1435,7 +1432,7 @@ static void activation_descriptor_init(i
 {
 	int i;
 	int cpu;
-	unsigned long pa;
+	unsigned long gpa;
 	unsigned long m;
 	unsigned long n;
 	size_t dsize;
@@ -1451,9 +1448,9 @@ static void activation_descriptor_init(i
 	bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
 	BUG_ON(!bau_desc);
 
-	pa = uv_gpa(bau_desc); /* need the real nasid*/
-	n = pa >> uv_nshift;
-	m = pa & uv_mmask;
+	gpa = uv_gpa(bau_desc);
+	n = uv_gpa_to_gnode(gpa);
+	m = uv_gpa_to_offset(gpa);
 
 	/* the 14-bit pnode */
 	write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
@@ -1525,9 +1522,9 @@ static void pq_init(int node, int pnode)
 		bcp->queue_last		= pqp + (DEST_Q_SIZE - 1);
 	}
 	/*
-	 * need the pnode of where the memory was really allocated
+	 * need the gnode of where the memory was really allocated
 	 */
-	pn = uv_gpa(pqp) >> uv_nshift;
+	pn = uv_gpa_to_gnode(uv_gpa(pqp));
 	first = uv_physnodeaddr(pqp);
 	pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
 	last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
@@ -1837,8 +1834,6 @@ static int __init uv_bau_init(void)
 		zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
 	}
 
-	uv_nshift = uv_hub_info->m_val;
-	uv_mmask = (1UL << uv_hub_info->m_val) - 1;
 	nuvhubs = uv_num_possible_blades();
 	spin_lock_init(&disable_lock);
 	congested_cycles = usec_2_cycles(congested_respns_us);
diff -druNp linux-libre-3.1-gnu1/arch/x86/power/cpu.c linux-libre-3.2-gnu1/arch/x86/power/cpu.c
--- linux-libre-3.1-gnu1/arch/x86/power/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/power/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/suspend.h>
+#include <linux/export.h>
 #include <linux/smp.h>
 
 #include <asm/pgtable.h>
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/apic.h linux-libre-3.2-gnu1/arch/x86/um/asm/apic.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/apic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/apic.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#ifndef __UM_APIC_H
+#define __UM_APIC_H
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/arch_hweight.h linux-libre-3.2-gnu1/arch/x86/um/asm/arch_hweight.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/arch_hweight.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/arch_hweight.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/archparam.h linux-libre-3.2-gnu1/arch/x86/um/asm/archparam.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/archparam.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_ARCHPARAM_H
+#define __UM_ARCHPARAM_H
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_X86_PAE
+#define LAST_PKMAP 512
+#else
+#define LAST_PKMAP 1024
+#endif
+
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/checksum_32.h linux-libre-3.2-gnu1/arch/x86/um/asm/checksum_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/checksum_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/checksum_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,201 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/in6.h"
+#include "linux/string.h"
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+					 int len, __wsum sum, int *err_ptr)
+{
+	if (copy_from_user(dst, src, len)) {
+		*err_ptr = -EFAULT;
+		return (__force __wsum)-1;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ *	Arnt Gulbrandsen.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	__asm__ __volatile__(
+	    "movl (%1), %0	;\n"
+	    "subl $4, %2	;\n"
+	    "jbe 2f		;\n"
+	    "addl 4(%1), %0	;\n"
+	    "adcl 8(%1), %0	;\n"
+	    "adcl 12(%1), %0	;\n"
+"1:	    adcl 16(%1), %0	;\n"
+	    "lea 4(%1), %1	;\n"
+	    "decl %2		;\n"
+	    "jne 1b		;\n"
+	    "adcl $0, %0	;\n"
+	    "movl %0, %2	;\n"
+	    "shrl $16, %0	;\n"
+	    "addw %w2, %w0	;\n"
+	    "adcl $0, %0	;\n"
+	    "notl %0		;\n"
+"2:				;\n"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+/*
+ *	Fold a partial checksum
+ */
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"addl %1, %0		;\n"
+		"adcl $0xffff, %0	;\n"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+    __asm__(
+	"addl %1, %0	;\n"
+	"adcl %2, %0	;\n"
+	"adcl %3, %0	;\n"
+	"adcl $0, %0	;\n"
+	: "=r" (sum)
+	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
+    return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+    return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+					  const struct in6_addr *daddr,
+					  __u32 len, unsigned short proto,
+					  __wsum sum)
+{
+	__asm__(
+		"addl 0(%1), %0		;\n"
+		"adcl 4(%1), %0		;\n"
+		"adcl 8(%1), %0		;\n"
+		"adcl 12(%1), %0	;\n"
+		"adcl 0(%2), %0		;\n"
+		"adcl 4(%2), %0		;\n"
+		"adcl 8(%2), %0		;\n"
+		"adcl 12(%2), %0	;\n"
+		"adcl %3, %0		;\n"
+		"adcl %4, %0		;\n"
+		"adcl $0, %0		;\n"
+		: "=&r" (sum)
+		: "r" (saddr), "r" (daddr),
+		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
+
+	return csum_fold(sum);
+}
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+						     void __user *dst,
+						     int len, __wsum sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (copy_to_user(dst, src, len)) {
+			*err_ptr = -EFAULT;
+			return (__force __wsum)-1;
+		}
+
+		return csum_partial(src, len, sum);
+	}
+
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return (__force __wsum)-1; /* invalid checksum */
+}
+
+#endif
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/checksum_64.h linux-libre-3.2-gnu1/arch/x86/um/asm/checksum_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/checksum_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/checksum_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,144 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/string.h"
+#include "linux/in6.h"
+#include "asm/uaccess.h"
+
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return(csum_partial(dst, len, sum));
+}
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src,
+                                         void *dst, int len, __wsum sum,
+                                         int *err_ptr)
+{
+        if (copy_from_user(dst, src, len)) {
+                *err_ptr = -EFAULT;
+                return (__force __wsum)-1;
+        }
+        return csum_partial(dst, len, sum);
+}
+
+/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"  addl %1,%0\n"
+		"  adcl $0xffff,%0"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded)
+ *
+ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		   unsigned short proto, __wsum sum)
+{
+	asm("  addl %1, %0\n"
+	    "  adcl %2, %0\n"
+	    "  adcl %3, %0\n"
+	    "  adcl $0, %0\n"
+		: "=r" (sum)
+	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+					   unsigned short len,
+					   unsigned short proto,
+					   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	asm(	"  movl (%1), %0\n"
+		"  subl $4, %2\n"
+		"  jbe 2f\n"
+		"  addl 4(%1), %0\n"
+		"  adcl 8(%1), %0\n"
+		"  adcl 12(%1), %0\n"
+		"1: adcl 16(%1), %0\n"
+		"  lea 4(%1), %1\n"
+		"  decl %2\n"
+		"  jne	1b\n"
+		"  adcl $0, %0\n"
+		"  movl %0, %2\n"
+		"  shrl $16, %0\n"
+		"  addw %w2, %w0\n"
+		"  adcl $0, %0\n"
+		"  notl %0\n"
+		"2:"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+static inline unsigned add32_with_carry(unsigned a, unsigned b)
+{
+        asm("addl %2,%0\n\t"
+            "adcl $0,%0"
+            : "=r" (a)
+            : "0" (a), "r" (b));
+        return a;
+}
+
+extern __sum16 ip_compute_csum(const void *buff, int len);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/checksum.h linux-libre-3.2-gnu1/arch/x86/um/asm/checksum.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/checksum.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#ifndef __UM_CHECKSUM_H
+#define __UM_CHECKSUM_H
+
+#ifdef CONFIG_X86_32
+# include "checksum_32.h"
+#else
+# include "checksum_64.h"
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/desc.h linux-libre-3.2-gnu1/arch/x86/um/asm/desc.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/desc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+#ifndef __UM_DESC_H
+#define __UM_DESC_H
+
+/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
+ * compile, and has never been used. */
+#define LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/elf.h linux-libre-3.2-gnu1/arch/x86/um/asm/elf.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_X86_H
+#define __UM_ELF_X86_H
+
+#include <asm/user.h>
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+	PT_REGS_EBX(regs) = 0; \
+	PT_REGS_ECX(regs) = 0; \
+	PT_REGS_EDX(regs) = 0; \
+	PT_REGS_ESI(regs) = 0; \
+	PT_REGS_EDI(regs) = 0; \
+	PT_REGS_EBP(regs) = 0; \
+	PT_REGS_EAX(regs) = 0; \
+} while (0)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
+	pr_reg[0] = PT_REGS_EBX(regs);		\
+	pr_reg[1] = PT_REGS_ECX(regs);		\
+	pr_reg[2] = PT_REGS_EDX(regs);		\
+	pr_reg[3] = PT_REGS_ESI(regs);		\
+	pr_reg[4] = PT_REGS_EDI(regs);		\
+	pr_reg[5] = PT_REGS_EBP(regs);		\
+	pr_reg[6] = PT_REGS_EAX(regs);		\
+	pr_reg[7] = PT_REGS_DS(regs);		\
+	pr_reg[8] = PT_REGS_ES(regs);		\
+	/* fake once used fs and gs selectors? */	\
+	pr_reg[9] = PT_REGS_DS(regs);		\
+	pr_reg[10] = PT_REGS_DS(regs);		\
+	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
+	pr_reg[12] = PT_REGS_IP(regs);		\
+	pr_reg[13] = PT_REGS_CS(regs);		\
+	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
+	pr_reg[15] = PT_REGS_SP(regs);		\
+	pr_reg[16] = PT_REGS_SS(regs);		\
+} while (0);
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START      vsyscall_ehdr
+#define FIXADDR_USER_END        vsyscall_end
+
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+	if ( vsyscall_ehdr ) {					\
+		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
+	}							\
+} while (0)
+
+#else
+
+/* x86-64 relocation types, taken from asm-x86_64/elf.h */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM		16
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == EM_X86_64)
+
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr)    do { \
+	PT_REGS_RBX(regs) = 0; \
+	PT_REGS_RCX(regs) = 0; \
+	PT_REGS_RDX(regs) = 0; \
+	PT_REGS_RSI(regs) = 0; \
+	PT_REGS_RDI(regs) = 0; \
+	PT_REGS_RBP(regs) = 0; \
+	PT_REGS_RAX(regs) = 0; \
+	PT_REGS_R8(regs) = 0; \
+	PT_REGS_R9(regs) = 0; \
+	PT_REGS_R10(regs) = 0; \
+	PT_REGS_R11(regs) = 0; \
+	PT_REGS_R12(regs) = 0; \
+	PT_REGS_R13(regs) = 0; \
+	PT_REGS_R14(regs) = 0; \
+	PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
+	(pr_reg)[0] = (_regs)->regs.gp[0];			\
+	(pr_reg)[1] = (_regs)->regs.gp[1];			\
+	(pr_reg)[2] = (_regs)->regs.gp[2];			\
+	(pr_reg)[3] = (_regs)->regs.gp[3];			\
+	(pr_reg)[4] = (_regs)->regs.gp[4];			\
+	(pr_reg)[5] = (_regs)->regs.gp[5];			\
+	(pr_reg)[6] = (_regs)->regs.gp[6];			\
+	(pr_reg)[7] = (_regs)->regs.gp[7];			\
+	(pr_reg)[8] = (_regs)->regs.gp[8];			\
+	(pr_reg)[9] = (_regs)->regs.gp[9];			\
+	(pr_reg)[10] = (_regs)->regs.gp[10];			\
+	(pr_reg)[11] = (_regs)->regs.gp[11];			\
+	(pr_reg)[12] = (_regs)->regs.gp[12];			\
+	(pr_reg)[13] = (_regs)->regs.gp[13];			\
+	(pr_reg)[14] = (_regs)->regs.gp[14];			\
+	(pr_reg)[15] = (_regs)->regs.gp[15];			\
+	(pr_reg)[16] = (_regs)->regs.gp[16];			\
+	(pr_reg)[17] = (_regs)->regs.gp[17];			\
+	(pr_reg)[18] = (_regs)->regs.gp[18];			\
+	(pr_reg)[19] = (_regs)->regs.gp[19];			\
+	(pr_reg)[20] = (_regs)->regs.gp[20];			\
+	(pr_reg)[21] = current->thread.arch.fs;			\
+	(pr_reg)[22] = 0;					\
+	(pr_reg)[23] = 0;					\
+	(pr_reg)[24] = 0;					\
+	(pr_reg)[25] = 0;					\
+	(pr_reg)[26] = 0;
+
+#define ELF_PLATFORM "x86_64"
+
+/* No user-accessible fixmap addresses, i.e. vsyscall */
+#define FIXADDR_USER_START      0
+#define FIXADDR_USER_END        0
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+	int uses_interp);
+
+extern unsigned long um_vdso_addr;
+#define AT_SYSINFO_EHDR 33
+#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
+
+#endif
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+#define task_pt_regs(t) (&(t)->thread.regs)
+
+struct task_struct;
+
+extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
+
+#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define SET_PERSONALITY(ex) do ; while(0)
+#define __HAVE_ARCH_GATE_AREA 1
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/irq_vectors.h linux-libre-3.2-gnu1/arch/x86/um/asm/irq_vectors.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/irq_vectors.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/irq_vectors.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+/* 
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_IRQ_VECTORS_H
+#define __UM_IRQ_VECTORS_H
+
+#endif
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/mm_context.h linux-libre-3.2-gnu1/arch/x86/um/asm/mm_context.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/mm_context.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/mm_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include <linux/mutex.h>
+#include <asm/ldt.h>
+
+extern void ldt_host_info(void);
+
+#define LDT_PAGES_MAX \
+	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+	(PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+	__u32 a;
+	__u32 b;
+};
+
+typedef struct uml_ldt {
+	int entry_count;
+	struct mutex lock;
+	union {
+		struct ldt_entry * pages[LDT_PAGES_MAX];
+		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+	} u;
+} uml_ldt_t;
+
+#define LDT_entry_a(info) \
+	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+	(((info)->base_addr & 0xff000000) | \
+	(((info)->base_addr & 0x00ff0000) >> 16) | \
+	((info)->limit & 0xf0000) | \
+	(((info)->read_exec_only ^ 1) << 9) | \
+	((info)->contents << 10) | \
+	(((info)->seg_not_present ^ 1) << 15) | \
+	((info)->seg_32bit << 22) | \
+	((info)->limit_in_pages << 23) | \
+	((info)->useable << 20) | \
+	0x7000)
+
+#define _LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+struct uml_arch_mm_context {
+	uml_ldt_t ldt;
+};
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/module.h linux-libre-3.2-gnu1/arch/x86/um/asm/module.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/module.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+#ifndef __UM_MODULE_H
+#define __UM_MODULE_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#ifdef CONFIG_X86_32
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#else
+
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/processor_32.h linux-libre-3.2-gnu1/arch/x86/um/asm/processor_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/processor_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/processor_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_I386_H
+#define __UM_PROCESSOR_I386_H
+
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/ldt.h>
+
+extern int host_has_cmov;
+
+struct uml_tls_struct {
+	struct user_desc tls;
+	unsigned flushed:1;
+	unsigned present:1;
+};
+
+struct arch_thread {
+	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+	unsigned long debugregs[8];
+	int debugregs_seq;
+	struct faultinfo faultinfo;
+};
+
+#define INIT_ARCH_THREAD { \
+	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
+				    { .present = 0, .flushed = 0 } }, \
+	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
+	.debugregs_seq		= 0, \
+	.faultinfo		= { 0, 0, 0 } \
+}
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+	/* Clear any TLS still hanging */
+	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
+}
+
+#include <asm/user.h>
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()	rep_nop()
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter"). Stolen
+ * from asm-i386/processor.h
+ */
+#define current_text_addr() \
+	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/processor_64.h linux-libre-3.2-gnu1/arch/x86/um/asm/processor_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/processor_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/processor_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_X86_64_H
+#define __UM_PROCESSOR_X86_64_H
+
+struct arch_thread {
+        unsigned long debugregs[8];
+        int debugregs_seq;
+        unsigned long fs;
+        struct faultinfo faultinfo;
+};
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()   rep_nop()
+
+#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
+			   .debugregs_seq	= 0, \
+			   .fs			= 0, \
+			   .faultinfo		= { 0, 0, 0 } }
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+	to->fs = from->fs;
+}
+
+#include <asm/user.h>
+
+#define current_text_addr() \
+	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/processor.h linux-libre-3.2-gnu1/arch/x86/um/asm/processor.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+#ifndef __UM_PROCESSOR_H
+#define __UM_PROCESSOR_H
+
+/* include faultinfo structure */
+#include <sysdep/faultinfo.h>
+
+#ifdef CONFIG_X86_32
+# include "processor_32.h"
+#else
+# include "processor_64.h"
+#endif
+
+#define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP)
+#define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
+
+#define ARCH_IS_STACKGROW(address) \
+       (address + 65536 + 32 * sizeof(unsigned long) >= UPT_SP(&current->thread.regs.regs))
+
+#include <asm/processor-generic.h>
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace_32.h linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,51 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_I386_H
+#define __UM_PTRACE_I386_H
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
+#include "linux/compiler.h"
+#include "asm/ptrace-generic.h"
+
+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
+
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+
+/*
+ * Forward declaration to avoid including sysdep/tls.h, which causes a
+ * circular include, and compilation failures.
+ */
+struct user_desc;
+
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace_64.h linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_X86_64_H
+#define __UM_PTRACE_X86_64_H
+
+#include "linux/compiler.h"
+#include "asm/errno.h"
+
+#define __FRAME_OFFSETS /* Needed to get the R* macros */
+#include "asm/ptrace-generic.h"
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
+#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
+#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
+#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
+#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
+#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
+#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
+#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
+#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
+#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
+#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
+#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
+#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
+#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
+#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
+#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
+
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+
+#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
+#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
+#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+/* XXX */
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
+
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+struct user_desc;
+
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+extern long arch_prctl(struct task_struct *task, int code,
+		       unsigned long __user *addr);
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace.h linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "ptrace_32.h"
+#else
+# include "ptrace_64.h"
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/required-features.h linux-libre-3.2-gnu1/arch/x86/um/asm/required-features.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/required-features.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/required-features.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+#ifndef __UM_REQUIRED_FEATURES_H
+#define __UM_REQUIRED_FEATURES_H
+
+/*
+ * Nothing to see, just need something for the i386 and x86_64 asm
+ * headers to include.
+ */
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/segment.h linux-libre-3.2-gnu1/arch/x86/um/asm/segment.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/segment.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/segment.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#ifndef __UM_SEGMENT_H
+#define __UM_SEGMENT_H
+
+extern int host_gdt_entry_tls_min;
+
+#define GDT_ENTRY_TLS_ENTRIES 3
+#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
+#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/system.h linux-libre-3.2-gnu1/arch/x86/um/asm/system.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,135 @@
+#ifndef _ASM_X86_SYSTEM_H_
+#define _ASM_X86_SYSTEM_H_
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/* entries in ARCH_DLINFO: */
+#ifdef CONFIG_IA32_EMULATION
+# define AT_VECTOR_SIZE_ARCH 2
+#else
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+void default_idle(void);
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb() 	asm volatile("mfence":::"memory")
+#define rmb()	asm volatile("lfence":::"memory")
+#define wmb()	asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()	rmb()
+#else
+# define smp_rmb()	barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb() 	wmb()
+#else
+# define smp_wmb()	barrier()
+#endif
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static inline void rdtsc_barrier(void)
+{
+	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/asm/vm-flags.h linux-libre-3.2-gnu1/arch/x86/um/asm/vm-flags.h
--- linux-libre-3.1-gnu1/arch/x86/um/asm/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/asm/vm-flags.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __VM_FLAGS_X86_H
+#define __VM_FLAGS_X86_H
+
+#ifdef CONFIG_X86_32
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#else
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/bug.c linux-libre-3.2-gnu1/arch/x86/um/bug.c
--- linux-libre-3.1-gnu1/arch/x86/um/bug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/bug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevant in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+	unsigned short ud2;
+
+	if (probe_kernel_address((unsigned short __user *)eip, ud2))
+		return 0;
+
+	return ud2 == 0x0b0f;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/bugs_32.c linux-libre-3.2-gnu1/arch/x86/um/bugs_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/bugs_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/bugs_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include "kern_util.h"
+#include "longjmp.h"
+#include "sysdep/ptrace.h"
+#include <generated/asm-offsets.h>
+
+/* Set during early boot */
+static int host_has_cmov = 1;
+static jmp_buf cmov_test_return;
+
+#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
+
+static void cmov_sigill_test_handler(int sig)
+{
+	host_has_cmov = 0;
+	longjmp(cmov_test_return, 1);
+}
+
+void arch_check_bugs(void)
+{
+	struct sigaction old, new;
+
+	printk(UM_KERN_INFO "Checking for host processor cmov support...");
+	new.sa_handler = cmov_sigill_test_handler;
+
+	/* Make sure that SIGILL is enabled after the handler longjmps back */
+	new.sa_flags = SA_NODEFER;
+	sigemptyset(&new.sa_mask);
+	sigaction(SIGILL, &new, &old);
+
+	if (setjmp(cmov_test_return) == 0) {
+		unsigned long foo = 0;
+		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+		printk(UM_KERN_CONT "Yes\n");
+	} else
+		printk(UM_KERN_CONT "No\n");
+
+	sigaction(SIGILL, &old, &new);
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+	unsigned char tmp[2];
+
+	/*
+	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
+	 * SIGILL in init.
+	 */
+	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+		return;
+
+	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+		printk(UM_KERN_ERR "SIGILL in init, could not read "
+		       "instructions!\n");
+		return;
+	}
+
+	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
+		return;
+
+	if (host_has_cmov == 0)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor doesn't implement.  Boot a filesystem "
+		       "compiled for older processors");
+	else if (host_has_cmov == 1)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor claims to implement");
+	else
+		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+			host_has_cmov);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/bugs_64.c linux-libre-3.2-gnu1/arch/x86/um/bugs_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/bugs_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/bugs_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+void arch_check_bugs(void)
+{
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/checksum_32.S linux-libre-3.2-gnu1/arch/x86/um/checksum_32.S
--- linux-libre-3.1-gnu1/arch/x86/um/checksum_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/checksum_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,458 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *
+ *		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 <asm/errno.h>
+				
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*	
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+		
+.text
+.align 4
+.globl csum_partial
+		
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+	  /*		
+	   * Experiments with Ethernet and SLIP connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	   * alignment for the unrolled loop.
+	   */		
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg: unsigned char *buff
+	testl $2, %esi		# Check alignment.
+	jz 2f			# Jump if alignment is ok.
+	subl $2, %ecx		# Alignment uses up two bytes.
+	jae 1f			# Jump if we had at least two bytes.
+	addl $2, %ecx		# ecx was < 2.  Deal with it.
+	jmp 4f
+1:	movw (%esi), %bx
+	addl $2, %esi
+	addw %bx, %ax
+	adcl $0, %eax
+2:
+	movl %ecx, %edx
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+1:	movl (%esi), %ebx
+	adcl %ebx, %eax
+	movl 4(%esi), %ebx
+	adcl %ebx, %eax
+	movl 8(%esi), %ebx
+	adcl %ebx, %eax
+	movl 12(%esi), %ebx
+	adcl %ebx, %eax
+	movl 16(%esi), %ebx
+	adcl %ebx, %eax
+	movl 20(%esi), %ebx
+	adcl %ebx, %eax
+	movl 24(%esi), %ebx
+	adcl %ebx, %eax
+	movl 28(%esi), %ebx
+	adcl %ebx, %eax
+	lea 32(%esi), %esi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx		# This clears CF
+3:	adcl (%esi), %eax
+	lea 4(%esi), %esi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+	movw (%esi),%cx
+	leal 2(%esi),%esi
+	je 6f
+	shll $16,%ecx
+5:	movb (%esi),%cl
+6:	addl %ecx,%eax
+	adcl $0, %eax 
+7:	
+	popl %ebx
+	popl %esi
+	ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
+
+	testl $2, %esi         
+	jnz 30f                 
+10:
+	movl %ecx, %edx
+	movl %ecx, %ebx
+	andl $0x7c, %ebx
+	shrl $7, %ecx
+	addl %ebx,%esi
+	shrl $2, %ebx  
+	negl %ebx
+	lea 45f(%ebx,%ebx,2), %ebx
+	testl %esi, %esi
+	jmp *%ebx
+
+	# Handle 2-byte-aligned regions
+20:	addw (%esi), %ax
+	lea 2(%esi), %esi
+	adcl $0, %eax
+	jmp 10b
+
+30:	subl $2, %ecx          
+	ja 20b                 
+	je 32f
+	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
+	addl %ebx, %eax
+	adcl $0, %eax
+	jmp 80f
+32:
+	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
+	adcl $0, %eax
+	jmp 80f
+
+40: 
+	addl -128(%esi), %eax
+	adcl -124(%esi), %eax
+	adcl -120(%esi), %eax
+	adcl -116(%esi), %eax   
+	adcl -112(%esi), %eax   
+	adcl -108(%esi), %eax
+	adcl -104(%esi), %eax
+	adcl -100(%esi), %eax
+	adcl -96(%esi), %eax
+	adcl -92(%esi), %eax
+	adcl -88(%esi), %eax
+	adcl -84(%esi), %eax
+	adcl -80(%esi), %eax
+	adcl -76(%esi), %eax
+	adcl -72(%esi), %eax
+	adcl -68(%esi), %eax
+	adcl -64(%esi), %eax     
+	adcl -60(%esi), %eax     
+	adcl -56(%esi), %eax     
+	adcl -52(%esi), %eax   
+	adcl -48(%esi), %eax   
+	adcl -44(%esi), %eax
+	adcl -40(%esi), %eax
+	adcl -36(%esi), %eax
+	adcl -32(%esi), %eax
+	adcl -28(%esi), %eax
+	adcl -24(%esi), %eax
+	adcl -20(%esi), %eax
+	adcl -16(%esi), %eax
+	adcl -12(%esi), %eax
+	adcl -8(%esi), %eax
+	adcl -4(%esi), %eax
+45:
+	lea 128(%esi), %esi
+	adcl $0, %eax
+	dec %ecx
+	jge 40b
+	movl %edx, %ecx
+50:	andl $3, %ecx
+	jz 80f
+
+	# Handle the last 1-3 bytes without jumping
+	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
+	movl $0xffffff,%ebx	# by the shll and shrl instructions
+	shll $3,%ecx
+	shrl %cl,%ebx
+	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
+	addl %ebx,%eax
+	adcl $0,%eax
+80: 
+	popl %ebx
+	popl %esi
+	ret
+				
+#endif
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */ 
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *	  them all but there's no guarantee.
+ */
+
+#define SRC(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6001f	;	\
+	.previous
+
+#define DST(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6002f	;	\
+	.previous
+
+.align 4
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+#define ARGBASE 16		
+#define FP		12
+
+csum_partial_copy_generic_i386:
+	subl  $4,%esp	
+	pushl %edi
+	pushl %esi
+	pushl %ebx
+	movl ARGBASE+16(%esp),%eax	# sum
+	movl ARGBASE+12(%esp),%ecx	# len
+	movl ARGBASE+4(%esp),%esi	# src
+	movl ARGBASE+8(%esp),%edi	# dst
+
+	testl $2, %edi			# Check alignment. 
+	jz 2f				# Jump if alignment is ok.
+	subl $2, %ecx			# Alignment uses up two bytes.
+	jae 1f				# Jump if we had at least two bytes.
+	addl $2, %ecx			# ecx was < 2.  Deal with it.
+	jmp 4f
+SRC(1:	movw (%esi), %bx	)
+	addl $2, %esi
+DST(	movw %bx, (%edi)	)
+	addl $2, %edi
+	addw %bx, %ax	
+	adcl $0, %eax
+2:
+	movl %ecx, FP(%esp)
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+SRC(1:	movl (%esi), %ebx	)
+SRC(	movl 4(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 4(%edi)	)
+
+SRC(	movl 8(%esi), %ebx	)
+SRC(	movl 12(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 8(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 12(%edi)	)
+
+SRC(	movl 16(%esi), %ebx 	)
+SRC(	movl 20(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 16(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 20(%edi)	)
+
+SRC(	movl 24(%esi), %ebx	)
+SRC(	movl 28(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 24(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 28(%edi)	)
+
+	lea 32(%esi), %esi
+	lea 32(%edi), %edi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl FP(%esp), %edx
+	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx			# This clears CF
+SRC(3:	movl (%esi), %ebx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	lea 4(%esi), %esi
+	lea 4(%edi), %edi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+SRC(	movw (%esi), %cx	)
+	leal 2(%esi), %esi
+DST(	movw %cx, (%edi)	)
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%ecx
+SRC(5:	movb (%esi), %cl	)
+DST(	movb %cl, (%edi)	)
+6:	addl %ecx, %eax
+	adcl $0, %eax
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"							
+
+6001:
+	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
+	movl $-EFAULT, (%ebx)
+
+	# zero the complete destination - computing the rest
+	# is too much work 
+	movl ARGBASE+8(%esp), %edi	# dst
+	movl ARGBASE+12(%esp), %ecx	# len
+	xorl %eax,%eax
+	rep ; stosb
+
+	jmp 5000b
+
+6002:
+	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT,(%ebx)
+	jmp 5000b
+
+.previous
+
+	popl %ebx
+	popl %esi
+	popl %edi
+	popl %ecx			# equivalent to addl $4,%esp
+	ret	
+
+#else
+
+/* Version for PentiumII/PPro */
+
+#define ROUND1(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	addl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	; 
+
+#define ROUND(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	adcl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	;
+
+#define ARGBASE 12
+		
+csum_partial_copy_generic_i386:
+	pushl %ebx
+	pushl %edi
+	pushl %esi
+	movl ARGBASE+4(%esp),%esi	#src
+	movl ARGBASE+8(%esp),%edi	#dst	
+	movl ARGBASE+12(%esp),%ecx	#len
+	movl ARGBASE+16(%esp),%eax	#sum
+#	movl %ecx, %edx  
+	movl %ecx, %ebx  
+	movl %esi, %edx
+	shrl $6, %ecx     
+	andl $0x3c, %ebx  
+	negl %ebx
+	subl %ebx, %esi  
+	subl %ebx, %edi  
+	lea  -1(%esi),%edx
+	andl $-32,%edx
+	lea 3f(%ebx,%ebx), %ebx
+	testl %esi, %esi 
+	jmp *%ebx
+1:	addl $64,%esi
+	addl $64,%edi 
+	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
+	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
+	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
+	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
+	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
+3:	adcl $0,%eax
+	addl $64, %edx
+	dec %ecx
+	jge 1b
+4:	movl ARGBASE+12(%esp),%edx	#len
+	andl $3, %edx
+	jz 7f
+	cmpl $2, %edx
+	jb 5f
+SRC(	movw (%esi), %dx         )
+	leal 2(%esi), %esi
+DST(	movw %dx, (%edi)         )
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%edx
+5:
+SRC(	movb (%esi), %dl         )
+DST(	movb %dl, (%edi)         )
+6:	addl %edx, %eax
+	adcl $0, %eax
+7:
+.section .fixup, "ax"
+6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
+	movl $-EFAULT, (%ebx)
+	# zero the complete destination (computing the rest is too much work)
+	movl ARGBASE+8(%esp),%edi	# dst
+	movl ARGBASE+12(%esp),%ecx	# len
+	xorl %eax,%eax
+	rep; stosb
+	jmp 7b
+6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT, (%ebx)
+	jmp  7b			
+.previous				
+
+	popl %esi
+	popl %edi
+	popl %ebx
+	ret
+				
+#undef ROUND
+#undef ROUND1		
+		
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/delay.c linux-libre-3.2-gnu1/arch/x86/um/delay.c
--- linux-libre-3.1-gnu1/arch/x86/um/delay.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/delay.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.c
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
+
+void __delay(unsigned long loops)
+{
+	asm volatile(
+		"test %0,%0\n"
+		"jz 3f\n"
+		"jmp 1f\n"
+
+		".align 16\n"
+		"1: jmp 2f\n"
+
+		".align 16\n"
+		"2: dec %0\n"
+		" jnz 2b\n"
+		"3: dec %0\n"
+
+		: /* we don't need output */
+		: "a" (loops)
+	);
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+	int d0;
+
+	xloops *= 4;
+	asm("mull %%edx"
+		: "=d" (xloops), "=&a" (d0)
+		: "1" (xloops), "0"
+		(loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/elfcore.c linux-libre-3.2-gnu1/arch/x86/um/elfcore.c
--- linux-libre-3.1-gnu1/arch/x86/um/elfcore.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/elfcore.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,83 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf32_Half elf_core_extra_phdrs(void)
+{
+	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+			       unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+		Elf32_Off ofs = 0;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			struct elf_phdr phdr = phdrp[i];
+
+			if (phdr.p_type == PT_LOAD) {
+				ofs = phdr.p_offset = offset;
+				offset += phdr.p_filesz;
+			} else {
+				phdr.p_offset += ofs;
+			}
+			phdr.p_paddr = 0; /* match other core phdrs */
+			*size += sizeof(phdr);
+			if (*size > limit
+			    || !dump_write(file, &phdr, sizeof(phdr)))
+				return 0;
+		}
+	}
+	return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+			      unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			if (phdrp[i].p_type == PT_LOAD) {
+				void *addr = (void *) phdrp[i].p_vaddr;
+				size_t filesz = phdrp[i].p_filesz;
+
+				*size += filesz;
+				if (*size > limit
+				    || !dump_write(file, addr, filesz))
+					return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *)vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i)
+			if (phdrp[i].p_type == PT_LOAD)
+				return (size_t) phdrp[i].p_filesz;
+	}
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/fault.c linux-libre-3.2-gnu1/arch/x86/um/fault.c
--- linux-libre-3.1-gnu1/arch/x86/um/fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/* 
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
+
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
+int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(address);
+	if (fixup != 0) {
+		UPT_IP(regs) = fixup->fixup;
+		return 1;
+	}
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/Kconfig linux-libre-3.2-gnu1/arch/x86/um/Kconfig
--- linux-libre-3.1-gnu1/arch/x86/um/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
+
+source "arch/um/Kconfig.common"
+
+menu "UML-specific options"
+
+menu "Host processor type and features"
+
+config CMPXCHG_LOCAL
+	bool
+	default n
+
+config CMPXCHG_DOUBLE
+	bool
+	default n
+
+source "arch/x86/Kconfig.cpu"
+
+endmenu
+
+config UML_X86
+	def_bool y
+	select GENERIC_FIND_FIRST_BIT
+
+config 64BIT
+	bool
+	default SUBARCH = "x86_64"
+
+config X86_32
+	def_bool !64BIT
+	select HAVE_AOUT
+
+config X86_64
+	def_bool 64BIT
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool X86_XADD && 64BIT
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool !RWSEM_XCHGADD_ALGORITHM
+
+config 3_LEVEL_PGTABLES
+	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
+	default 64BIT
+	depends on EXPERIMENTAL
+	help
+	Three-level pagetables will let UML have more than 4G of physical
+	memory.  All the memory that can't be mapped directly will be treated
+	as high memory.
+
+	However, this it experimental on 32-bit architectures, so if unsure say
+	N (on x86-64 it's automatically enabled, instead, as it's safe there).
+
+config ARCH_HAS_SC_SIGNALS
+	def_bool !64BIT
+
+config ARCH_REUSE_HOST_VSYSCALL_AREA
+	def_bool !64BIT
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+source "arch/um/Kconfig.um"
+
+endmenu
+
+source "arch/um/Kconfig.rest"
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/ksyms.c linux-libre-3.2-gnu1/arch/x86/um/ksyms.c
--- linux-libre-3.1-gnu1/arch/x86/um/ksyms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+#include <linux/module.h>
+#include <asm/string.h>
+#include <asm/checksum.h>
+
+#ifndef CONFIG_X86_32
+/*XXX: we need them because they would be exported by x86_64 */
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+EXPORT_SYMBOL(memcpy);
+#else
+EXPORT_SYMBOL(__memcpy);
+#endif
+#endif
+EXPORT_SYMBOL(csum_partial);
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/ldt.c linux-libre-3.2-gnu1/arch/x86/um/ldt.c
--- linux-libre-3.1-gnu1/arch/x86/um/ldt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/ldt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/unistd.h>
+#include "os.h"
+#include "proc_mm.h"
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "sysdep/tls.h"
+
+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+
+static long write_ldt_entry(struct mm_id *mm_idp, int func,
+		     struct user_desc *desc, void **addr, int done)
+{
+	long res;
+
+	if (proc_mm) {
+		/*
+		 * This is a special handling for the case, that the mm to
+		 * modify isn't current->active_mm.
+		 * If this is called directly by modify_ldt,
+		 *     (current->active_mm->context.skas.u == mm_idp)
+		 * will be true. So no call to __switch_mm(mm_idp) is done.
+		 * If this is called in case of init_new_ldt or PTRACE_LDT,
+		 * mm_idp won't belong to current->active_mm, but child->mm.
+		 * So we need to switch child's mm into our userspace, then
+		 * later switch back.
+		 *
+		 * Note: I'm unsure: should interrupts be disabled here?
+		 */
+		if (!current->active_mm || current->active_mm == &init_mm ||
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(mm_idp);
+	}
+
+	if (ptrace_ldt) {
+		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+			.func = func,
+			.ptr = desc,
+			.bytecount = sizeof(*desc)};
+		u32 cpu;
+		int pid;
+
+		if (!proc_mm)
+			pid = mm_idp->u.pid;
+		else {
+			cpu = get_cpu();
+			pid = userspace_pid[cpu];
+		}
+
+		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
+
+		if (proc_mm)
+			put_cpu();
+	}
+	else {
+		void *stub_addr;
+		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+					(sizeof(*desc) + sizeof(long) - 1) &
+					    ~(sizeof(long) - 1),
+					addr, &stub_addr);
+		if (!res) {
+			unsigned long args[] = { func,
+						 (unsigned long)stub_addr,
+						 sizeof(*desc),
+						 0, 0, 0 };
+			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+					       0, addr, done);
+		}
+	}
+
+	if (proc_mm) {
+		/*
+		 * This is the second part of special handling, that makes
+		 * PTRACE_LDT possible to implement.
+		 */
+		if (current->active_mm && current->active_mm != &init_mm &&
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(&current->active_mm->context.id);
+	}
+
+	return res;
+}
+
+static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
+{
+	int res, n;
+	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
+			.func = 0,
+			.bytecount = bytecount,
+			.ptr = kmalloc(bytecount, GFP_KERNEL)};
+	u32 cpu;
+
+	if (ptrace_ldt.ptr == NULL)
+		return -ENOMEM;
+
+	/*
+	 * This is called from sys_modify_ldt only, so userspace_pid gives
+	 * us the right number
+	 */
+
+	cpu = get_cpu();
+	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
+	put_cpu();
+	if (res < 0)
+		goto out;
+
+	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
+	if (n != 0)
+		res = -EFAULT;
+
+  out:
+	kfree(ptrace_ldt.ptr);
+
+	return res;
+}
+
+/*
+ * In skas mode, we hold our own ldt data in UML.
+ * Thus, the code implementing sys_modify_ldt_skas
+ * is very similar to (and mostly stolen from) sys_modify_ldt
+ * for arch/i386/kernel/ldt.c
+ * The routines copied and modified in part are:
+ * - read_ldt
+ * - read_default_ldt
+ * - write_ldt
+ * - sys_modify_ldt_skas
+ */
+
+static int read_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int i, err = 0;
+	unsigned long size;
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+
+	if (!ldt->entry_count)
+		goto out;
+	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+	err = bytecount;
+
+	if (ptrace_ldt)
+		return read_ldt_from_host(ptr, bytecount);
+
+	mutex_lock(&ldt->lock);
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
+		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+		if (size > bytecount)
+			size = bytecount;
+		if (copy_to_user(ptr, ldt->u.entries, size))
+			err = -EFAULT;
+		bytecount -= size;
+		ptr += size;
+	}
+	else {
+		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+		     i++) {
+			size = PAGE_SIZE;
+			if (size > bytecount)
+				size = bytecount;
+			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
+				err = -EFAULT;
+				break;
+			}
+			bytecount -= size;
+			ptr += size;
+		}
+	}
+	mutex_unlock(&ldt->lock);
+
+	if (bytecount == 0 || err == -EFAULT)
+		goto out;
+
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+out:
+	return err;
+}
+
+static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int err;
+
+	if (bytecount > 5*LDT_ENTRY_SIZE)
+		bytecount = 5*LDT_ENTRY_SIZE;
+
+	err = bytecount;
+	/*
+	 * UML doesn't support lcall7 and lcall27.
+	 * So, we don't really have a default ldt, but emulate
+	 * an empty ldt of common host default ldt size.
+	 */
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+	return err;
+}
+
+static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+{
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+	struct mm_id * mm_idp = &current->mm->context.id;
+	int i, err;
+	struct user_desc ldt_info;
+	struct ldt_entry entry0, *ldt_p;
+	void *addr = NULL;
+
+	err = -EINVAL;
+	if (bytecount != sizeof(ldt_info))
+		goto out;
+	err = -EFAULT;
+	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+		goto out;
+
+	err = -EINVAL;
+	if (ldt_info.entry_number >= LDT_ENTRIES)
+		goto out;
+	if (ldt_info.contents == 3) {
+		if (func == 1)
+			goto out;
+		if (ldt_info.seg_not_present == 0)
+			goto out;
+	}
+
+	if (!ptrace_ldt)
+		mutex_lock(&ldt->lock);
+
+	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+	if (err)
+		goto out_unlock;
+	else if (ptrace_ldt) {
+		/* With PTRACE_LDT available, this is used as a flag only */
+		ldt->entry_count = 1;
+		goto out;
+	}
+
+	if (ldt_info.entry_number >= ldt->entry_count &&
+	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
+		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+		     i++) {
+			if (i == 0)
+				memcpy(&entry0, ldt->u.entries,
+				       sizeof(entry0));
+			ldt->u.pages[i] = (struct ldt_entry *)
+				__get_free_page(GFP_KERNEL|__GFP_ZERO);
+			if (!ldt->u.pages[i]) {
+				err = -ENOMEM;
+				/* Undo the change in host */
+				memset(&ldt_info, 0, sizeof(ldt_info));
+				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
+				goto out_unlock;
+			}
+			if (i == 0) {
+				memcpy(ldt->u.pages[0], &entry0,
+				       sizeof(entry0));
+				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
+				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
+			}
+			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
+		}
+	}
+	if (ldt->entry_count <= ldt_info.entry_number)
+		ldt->entry_count = ldt_info.entry_number + 1;
+
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
+		ldt_p = ldt->u.entries + ldt_info.entry_number;
+	else
+		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
+			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
+
+	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+	   (func == 1 || LDT_empty(&ldt_info))) {
+		ldt_p->a = 0;
+		ldt_p->b = 0;
+	}
+	else{
+		if (func == 1)
+			ldt_info.useable = 0;
+		ldt_p->a = LDT_entry_a(&ldt_info);
+		ldt_p->b = LDT_entry_b(&ldt_info);
+	}
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&ldt->lock);
+out:
+	return err;
+}
+
+static long do_modify_ldt_skas(int func, void __user *ptr,
+			       unsigned long bytecount)
+{
+	int ret = -ENOSYS;
+
+	switch (func) {
+		case 0:
+			ret = read_ldt(ptr, bytecount);
+			break;
+		case 1:
+		case 0x11:
+			ret = write_ldt(ptr, bytecount, func);
+			break;
+		case 2:
+			ret = read_default_ldt(ptr, bytecount);
+			break;
+	}
+	return ret;
+}
+
+static DEFINE_SPINLOCK(host_ldt_lock);
+static short dummy_list[9] = {0, -1};
+static short * host_ldt_entries = NULL;
+
+static void ldt_get_host_info(void)
+{
+	long ret;
+	struct ldt_entry * ldt;
+	short *tmp;
+	int i, size, k, order;
+
+	spin_lock(&host_ldt_lock);
+
+	if (host_ldt_entries != NULL) {
+		spin_unlock(&host_ldt_lock);
+		return;
+	}
+	host_ldt_entries = dummy_list+1;
+
+	spin_unlock(&host_ldt_lock);
+
+	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
+		;
+
+	ldt = (struct ldt_entry *)
+	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
+	if (ldt == NULL) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
+		       "for host ldt\n");
+		return;
+	}
+
+	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
+	if (ret < 0) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
+		goto out_free;
+	}
+	if (ret == 0) {
+		/* default_ldt is active, simply write an empty entry 0 */
+		host_ldt_entries = dummy_list;
+		goto out_free;
+	}
+
+	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			size++;
+	}
+
+	if (size < ARRAY_SIZE(dummy_list))
+		host_ldt_entries = dummy_list;
+	else {
+		size = (size + 1) * sizeof(dummy_list[0]);
+		tmp = kmalloc(size, GFP_KERNEL);
+		if (tmp == NULL) {
+			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
+			       "host ldt list\n");
+			goto out_free;
+		}
+		host_ldt_entries = tmp;
+	}
+
+	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			host_ldt_entries[k++] = i;
+	}
+	host_ldt_entries[k] = -1;
+
+out_free:
+	free_pages((unsigned long)ldt, order);
+}
+
+long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+{
+	struct user_desc desc;
+	short * num_p;
+	int i;
+	long page, err=0;
+	void *addr = NULL;
+	struct proc_mm_op copy;
+
+
+	if (!ptrace_ldt)
+		mutex_init(&new_mm->arch.ldt.lock);
+
+	if (!from_mm) {
+		memset(&desc, 0, sizeof(desc));
+		/*
+		 * We have to initialize a clean ldt.
+		 */
+		if (proc_mm) {
+			/*
+			 * If the new mm was created using proc_mm, host's
+			 * default-ldt currently is assigned, which normally
+			 * contains the call-gates for lcall7 and lcall27.
+			 * To remove these gates, we simply write an empty
+			 * entry as number 0 to the host.
+			 */
+			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
+		}
+		else{
+			/*
+			 * Now we try to retrieve info about the ldt, we
+			 * inherited from the host. All ldt-entries found
+			 * will be reset in the following loop
+			 */
+			ldt_get_host_info();
+			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
+				desc.entry_number = *num_p;
+				err = write_ldt_entry(&new_mm->id, 1, &desc,
+						      &addr, *(num_p + 1) == -1);
+				if (err)
+					break;
+			}
+		}
+		new_mm->arch.ldt.entry_count = 0;
+
+		goto out;
+	}
+
+	if (proc_mm) {
+		/*
+		 * We have a valid from_mm, so we now have to copy the LDT of
+		 * from_mm to new_mm, because using proc_mm an new mm with
+		 * an empty/default LDT was created in new_mm()
+		 */
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments =
+							from_mm->id.u.mm_fd } } );
+		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
+		if (i != sizeof(copy))
+			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
+			       "failed, err = %d\n", -i);
+	}
+
+	if (!ptrace_ldt) {
+		/*
+		 * Our local LDT is used to supply the data for
+		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+		 * i.e., we have to use the stub for modify_ldt, which
+		 * can't handle the big read buffer of up to 64kB.
+		 */
+		mutex_lock(&from_mm->arch.ldt.lock);
+		if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
+			memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
+			       sizeof(new_mm->arch.ldt.u.entries));
+		else {
+			i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+			while (i-->0) {
+				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+				if (!page) {
+					err = -ENOMEM;
+					break;
+				}
+				new_mm->arch.ldt.u.pages[i] =
+					(struct ldt_entry *) page;
+				memcpy(new_mm->arch.ldt.u.pages[i],
+				       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
+			}
+		}
+		new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
+		mutex_unlock(&from_mm->arch.ldt.lock);
+	}
+
+    out:
+	return err;
+}
+
+
+void free_ldt(struct mm_context *mm)
+{
+	int i;
+
+	if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
+		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+		while (i-- > 0)
+			free_page((long) mm->arch.ldt.u.pages[i]);
+	}
+	mm->arch.ldt.entry_count = 0;
+}
+
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+	return do_modify_ldt_skas(func, ptr, bytecount);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/Makefile linux-libre-3.2-gnu1/arch/x86/um/Makefile
--- linux-libre-3.1-gnu1/arch/x86/um/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+#
+
+ifeq ($(CONFIG_X86_32),y)
+	BITS := 32
+else
+	BITS := 64
+endif
+
+obj-y = bug.o bugs_$(BITS).o delay.o fault.o ksyms.o ldt.o \
+	ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+	stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \
+	sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
+	mem_$(BITS).o subarch.o os-$(OS)/
+
+ifeq ($(CONFIG_X86_32),y)
+
+obj-y += checksum_32.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
+subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o
+subarch-$(CONFIG_HIGHMEM) += ../mm/highmem_32.o
+
+else
+
+obj-y += vdso/
+
+subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../lib/thunk_64.o \
+		../lib/rwsem.o
+
+endif
+
+subarch-$(CONFIG_MODULES) += ../kernel/module.o
+
+USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
+
+extra-y += user-offsets.s
+$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS)
+
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/mem_32.c linux-libre-3.2-gnu1/arch/x86/um/mem_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/mem_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/mem_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * 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/mm.h>
+#include <asm/page.h>
+#include <asm/mman.h>
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
+	return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return FIXADDR_USER_START ? &gate_vma : NULL;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+		return 1;
+
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma = get_gate_vma(mm);
+
+	if (!vma)
+		return 0;
+
+	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/mem_64.c linux-libre-3.2-gnu1/arch/x86/um/mem_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/mem_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/mem_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/mman.h"
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
+		return "[vdso]";
+
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/Makefile linux-libre-3.2-gnu1/arch/x86/um/os-Linux/Makefile
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+# Licensed under the GPL
+#
+
+obj-y = registers.o task_size.o mcontext.o
+
+obj-$(CONFIG_X86_32) += tls.o
+obj-$(CONFIG_64BIT) += prctl.o
+
+USER_OBJS := $(obj-y)
+
+include arch/um/scripts/Makefile.rules
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/mcontext.c linux-libre-3.2-gnu1/arch/x86/um/os-Linux/mcontext.c
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/mcontext.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/mcontext.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+#include <sys/ucontext.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <sysdep/ptrace.h>
+
+void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
+{
+#ifdef __i386__
+#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
+#define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff;
+#define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3;
+	COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
+	COPY(EDI); COPY(ESI); COPY(EBP);
+	COPY2(UESP, ESP); /* sic */
+	COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
+	COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#else
+#define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
+	COPY(R8); COPY(R9); COPY(R10); COPY(R11);
+	COPY(R12); COPY(R13); COPY(R14); COPY(R15);
+	COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
+	COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
+	COPY(RIP);
+	COPY2(EFLAGS, EFL);
+	COPY2(CS, CSGSFS);
+	regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
+	regs->gp[CS / sizeof(unsigned long)] |= 3;
+#endif
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/prctl.c linux-libre-3.2-gnu1/arch/x86/um/os-Linux/prctl.c
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/prctl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/prctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
+ * Licensed under the GPL
+ */
+
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+
+int os_arch_prctl(int pid, int code, unsigned long *addr)
+{
+        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/registers.c linux-libre-3.2-gnu1/arch/x86/um/os-Linux/registers.c
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/registers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/registers.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <sys/ptrace.h>
+#ifdef __i386__
+#include <sys/user.h>
+#endif
+#include "longjmp.h"
+#include "sysdep/ptrace_user.h"
+
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+#ifdef __i386__
+int have_fpx_regs = 1;
+int save_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return save_fpx_registers(pid, regs);
+	else
+		return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return restore_fpx_registers(pid, regs);
+	else
+		return restore_fp_registers(pid, regs);
+}
+
+void arch_init_registers(int pid)
+{
+	struct user_fpxregs_struct fpx_regs;
+	int err;
+
+	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
+	if (!err)
+		return;
+
+	if (errno != EIO)
+		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+		      errno);
+
+	have_fpx_regs = 0;
+}
+#else
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	return restore_fp_registers(pid, regs);
+}
+
+#endif
+
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
+{
+	switch (reg) {
+#ifdef __i386__
+	case HOST_IP:
+		return buf[0]->__eip;
+	case HOST_SP:
+		return buf[0]->__esp;
+	case HOST_BP:
+		return buf[0]->__ebp;
+#else
+	case HOST_IP:
+		return buf[0]->__rip;
+	case HOST_SP:
+		return buf[0]->__rsp;
+	case HOST_BP:
+		return buf[0]->__rbp;
+#endif
+	default:
+		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+		       reg);
+		return 0;
+	}
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/task_size.c linux-libre-3.2-gnu1/arch/x86/um/os-Linux/task_size.c
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/task_size.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/task_size.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include "longjmp.h"
+
+#ifdef __i386__
+
+static jmp_buf buf;
+
+static void segfault(int sig)
+{
+	longjmp(buf, 1);
+}
+
+static int page_ok(unsigned long page)
+{
+	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
+	unsigned long n = ~0UL;
+	void *mapped = NULL;
+	int ok = 0;
+
+	/*
+	 * First see if the page is readable.  If it is, it may still
+	 * be a VDSO, so we go on to see if it's writable.  If not
+	 * then try mapping memory there.  If that fails, then we're
+	 * still in the kernel area.  As a sanity check, we'll fail if
+	 * the mmap succeeds, but gives us an address different from
+	 * what we wanted.
+	 */
+	if (setjmp(buf) == 0)
+		n = *address;
+	else {
+		mapped = mmap(address, UM_KERN_PAGE_SIZE,
+			      PROT_READ | PROT_WRITE,
+			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		if (mapped == MAP_FAILED)
+			return 0;
+		if (mapped != address)
+			goto out;
+	}
+
+	/*
+	 * Now, is it writeable?  If so, then we're in user address
+	 * space.  If not, then try mprotecting it and try the write
+	 * again.
+	 */
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+		goto out;
+	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
+			    PROT_READ | PROT_WRITE) != 0)
+		goto out;
+
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+	}
+
+ out:
+	if (mapped != NULL)
+		munmap(mapped, UM_KERN_PAGE_SIZE);
+	return ok;
+}
+
+unsigned long os_get_top_address(void)
+{
+	struct sigaction sa, old;
+	unsigned long bottom = 0;
+	/*
+	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
+	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
+	 * and written.  However, exec discovers later that it can't be
+	 * unmapped.  So, just set the highest address to be checked to just
+	 * below it.  This might waste some address space on 4G/4G 32-bit
+	 * hosts, but shouldn't hurt otherwise.
+	 */
+	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
+	unsigned long test, original;
+
+	printf("Locating the bottom of the address space ... ");
+	fflush(stdout);
+
+	/*
+	 * We're going to be longjmping out of the signal handler, so
+	 * SA_DEFER needs to be set.
+	 */
+	sa.sa_handler = segfault;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_NODEFER;
+	if (sigaction(SIGSEGV, &sa, &old)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+
+	/* Manually scan the address space, bottom-up, until we find
+	 * the first valid page (or run out of them).
+	 */
+	for (bottom = 0; bottom < top; bottom++) {
+		if (page_ok(bottom))
+			break;
+	}
+
+	/* If we've got this far, we ran out of pages. */
+	if (bottom == top) {
+		fprintf(stderr, "Unable to determine bottom of address "
+			"space.\n");
+		exit(1);
+	}
+
+	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
+	printf("Locating the top of the address space ... ");
+	fflush(stdout);
+
+	original = bottom;
+
+	/* This could happen with a 4G/4G split */
+	if (page_ok(top))
+		goto out;
+
+	do {
+		test = bottom + (top - bottom) / 2;
+		if (page_ok(test))
+			bottom = test;
+		else
+			top = test;
+	} while (top - bottom > 1);
+
+out:
+	/* Restore the old SIGSEGV handling */
+	if (sigaction(SIGSEGV, &old, NULL)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+	top <<= UM_KERN_PAGE_SHIFT;
+	printf("0x%x\n", top);
+
+	return top;
+}
+
+#else
+
+unsigned long os_get_top_address(void)
+{
+	/* The old value of CONFIG_TOP_ADDR */
+	return 0x7fc0000000;
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/os-Linux/tls.c linux-libre-3.2-gnu1/arch/x86/um/os-Linux/tls.c
--- linux-libre-3.1-gnu1/arch/x86/um/os-Linux/tls.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/os-Linux/tls.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+#include <errno.h>
+#include <linux/unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "sysdep/tls.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+/* Checks whether host supports TLS, and sets *tls_min according to the value
+ * valid on the host.
+ * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
+void check_host_supports_tls(int *supports_tls, int *tls_min)
+{
+	/* Values for x86 and x86_64.*/
+	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(val); i++) {
+		user_desc_t info;
+		info.entry_number = val[i];
+
+		if (syscall(__NR_get_thread_area, &info) == 0) {
+			*tls_min = val[i];
+			*supports_tls = 1;
+			return;
+		} else {
+			if (errno == EINVAL)
+				continue;
+			else if (errno == ENOSYS)
+				*supports_tls = 0;
+				return;
+		}
+	}
+
+	*supports_tls = 0;
+}
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/ptrace_32.c linux-libre-3.2-gnu1/arch/x86/um/ptrace_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/ptrace_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/ptrace_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "skas.h"
+
+extern int arch_switch_tls(struct task_struct *to);
+
+void arch_switch_to(struct task_struct *to)
+{
+	int err = arch_switch_tls(to);
+	if (!err)
+		return;
+
+	if (err != -EINVAL)
+		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
+		       "not EINVAL\n", -err);
+	else
+		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
+}
+
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/* access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk(KERN_ERR "is_syscall : failed to read "
+			       "instruction from 0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* int 0x80 or sysenter */
+	return (instr == 0x80cd) || (instr == 0x340f);
+}
+
+/* determines which flags the user has access to. */
+/* 1 = access 0 = no access */
+#define FLAG_MASK 0x00044dd5
+
+static const int reg_offsets[] = {
+	[EBX] = HOST_BX,
+	[ECX] = HOST_CX,
+	[EDX] = HOST_DX,
+	[ESI] = HOST_SI,
+	[EDI] = HOST_DI,
+	[EBP] = HOST_BP,
+	[EAX] = HOST_AX,
+	[DS] = HOST_DS,
+	[ES] = HOST_ES,
+	[FS] = HOST_FS,
+	[GS] = HOST_GS,
+	[EIP] = HOST_IP,
+	[CS] = HOST_CS,
+	[EFL] = HOST_EFLAGS,
+	[UESP] = HOST_SP,
+	[SS] = HOST_SS,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+	regno >>= 2;
+	switch (regno) {
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EAX:
+	case EIP:
+	case UESP:
+		break;
+	case FS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case GS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case DS:
+	case ES:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case SS:
+	case CS:
+		if ((value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case EFL:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+	case ORIG_EAX:
+		child->thread.regs.regs.syscall = value;
+		return 0;
+	default :
+		panic("Bad register in putreg() : %d\n", regno);
+	}
+	child->thread.regs.regs.gp[reg_offsets[regno]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+
+	regno >>= 2;
+	switch (regno) {
+	case ORIG_EAX:
+		return child->thread.regs.regs.syscall;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	case EIP:
+	case UESP:
+	case EAX:
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EFL:
+		break;
+	default:
+		panic("Bad register in getreg() : %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
+}
+
+/* read the word at location addr in the USER area. */
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET) {
+		tmp = getreg(child, addr);
+	}
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long __user *) data);
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu],
+				    (unsigned long *) &fpregs);
+}
+
+static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fpx_registers(userspace_pid[cpu],
+				     (unsigned long *) &fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
+		ret = get_fpxregs(datap, child);
+		break;
+	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
+		ret = set_fpxregs(datap, child);
+		break;
+	default:
+		ret = -EIO;
+	}
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/ptrace_64.c linux-libre-3.2-gnu1/arch/x86/um/ptrace_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/ptrace_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/ptrace_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * determines which flags the user has access to.
+ * 1 = access 0 = no access
+ */
+#define FLAG_MASK 0x44dd5UL
+
+static const int reg_offsets[] =
+{
+	[R8 >> 3] = HOST_R8,
+	[R9 >> 3] = HOST_R9,
+	[R10 >> 3] = HOST_R10,
+	[R11 >> 3] = HOST_R11,
+	[R12 >> 3] = HOST_R12,
+	[R13 >> 3] = HOST_R13,
+	[R14 >> 3] = HOST_R14,
+	[R15 >> 3] = HOST_R15,
+	[RIP >> 3] = HOST_IP,
+	[RSP >> 3] = HOST_SP,
+	[RAX >> 3] = HOST_AX,
+	[RBX >> 3] = HOST_BX,
+	[RCX >> 3] = HOST_CX,
+	[RDX >> 3] = HOST_DX,
+	[RSI >> 3] = HOST_SI,
+	[RDI >> 3] = HOST_DI,
+	[RBP >> 3] = HOST_BP,
+	[CS >> 3] = HOST_CS,
+	[SS >> 3] = HOST_SS,
+	[FS_BASE >> 3] = HOST_FS_BASE,
+	[GS_BASE >> 3] = HOST_GS_BASE,
+	[DS >> 3] = HOST_DS,
+	[ES >> 3] = HOST_ES,
+	[FS >> 3] = HOST_FS,
+	[GS >> 3] = HOST_GS,
+	[EFLAGS >> 3] = HOST_EFLAGS,
+	[ORIG_RAX >> 3] = HOST_ORIG_AX,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+#ifdef TIF_IA32
+	/*
+	 * Some code in the 64bit emulation may not be 64bit clean.
+	 * Don't take any chances.
+	 */
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		value &= 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+		break;
+
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+
+	case FS_BASE:
+	case GS_BASE:
+		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+			return -EIO;
+		break;
+
+	case EFLAGS:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+
+	default:
+		panic("Bad register in putreg(): %d\n", regno);
+	}
+
+	child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+#ifdef TIF_IA32
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		mask = 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+	case EFLAGS:
+	case FS_BASE:
+	case GS_BASE:
+		break;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	default:
+		panic("Bad register in getreg: %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
+}
+
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	/* read the word at location addr in the USER area. */
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET)
+		tmp = getreg(child, addr);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long *) data);
+}
+
+/* XXX Mostly copied from sys-i386 */
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/*
+		 * access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk("is_syscall : failed to read instruction from "
+			       "0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* sysenter */
+	return instr == 0x050f;
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	err = save_fp_registers(userspace_pid[cpu], fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, fpregs, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	n = copy_from_user(fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu], fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_ARCH_PRCTL:
+		/* XXX Calls ptrace on the host - needs some SMP thinking */
+		ret = arch_prctl(child, data, (void __user *) addr);
+		break;
+	}
+
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/ptrace_user.c linux-libre-3.2-gnu1/arch/x86/um/ptrace_user.c
--- linux-libre-3.1-gnu1/arch/x86/um/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/ptrace_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include "ptrace_user.h"
+
+int ptrace_getregs(long pid, unsigned long *regs_out)
+{
+	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+		return -errno;
+	return 0;
+}
+
+int ptrace_setregs(long pid, unsigned long *regs)
+{
+	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
+		return -errno;
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/setjmp_32.S linux-libre-3.2-gnu1/arch/x86/um/setjmp_32.S
--- linux-libre-3.1-gnu1/arch/x86/um/setjmp_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/setjmp_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%ebx
+#	%esp
+#	%ebp
+#	%esi
+#	%edi
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+	movl %eax,%edx
+#else
+	movl 4(%esp),%edx
+#endif
+	popl %ecx			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movl %ebx,(%edx)
+	movl %esp,4(%edx)		# Post-return %esp!
+	pushl %ecx			# Make the call/return stack happy
+	movl %ebp,8(%edx)
+	movl %esi,12(%edx)
+	movl %edi,16(%edx)
+	movl %ecx,20(%edx)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+	xchgl %eax,%edx
+#else
+	movl 4(%esp),%edx		# jmp_ptr address
+	movl 8(%esp),%eax		# Return value
+#endif
+	movl (%edx),%ebx
+	movl 4(%edx),%esp
+	movl 8(%edx),%ebp
+	movl 12(%edx),%esi
+	movl 16(%edx),%edi
+	jmp *20(%edx)
+
+	.size longjmp,.-longjmp
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/setjmp_64.S linux-libre-3.2-gnu1/arch/x86/um/setjmp_64.S
--- linux-libre-3.1-gnu1/arch/x86/um/setjmp_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/setjmp_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%rbx
+#	%rsp (post-return)
+#	%rbp
+#	%r12
+#	%r13
+#	%r14
+#	%r15
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+	pop  %rsi			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movq %rbx,(%rdi)
+	movq %rsp,8(%rdi)		# Post-return %rsp!
+	push %rsi			# Make the call/return stack happy
+	movq %rbp,16(%rdi)
+	movq %r12,24(%rdi)
+	movq %r13,32(%rdi)
+	movq %r14,40(%rdi)
+	movq %r15,48(%rdi)
+	movq %rsi,56(%rdi)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	movl %esi,%eax			# Return value (int)
+	movq (%rdi),%rbx
+	movq 8(%rdi),%rsp
+	movq 16(%rdi),%rbp
+	movq 24(%rdi),%r12
+	movq 32(%rdi),%r13
+	movq 40(%rdi),%r14
+	movq 48(%rdi),%r15
+	jmp *56(%rdi)
+
+	.size longjmp,.-longjmp
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp_32.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * arch/um/include/sysdep-i386/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned int __ebx;
+	unsigned int __esp;
+	unsigned int __ebp;
+	unsigned int __esi;
+	unsigned int __edi;
+	unsigned int __eip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __eip
+#define JB_SP __esp
+
+#endif				/* _SETJMP_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp_64.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * arch/um/include/sysdep-x86_64/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned long __rbx;
+	unsigned long __rsp;
+	unsigned long __rbp;
+	unsigned long __r12;
+	unsigned long __r13;
+	unsigned long __r14;
+	unsigned long __r15;
+	unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __rip
+#define JB_SP __rsp
+
+#endif				/* _SETJMP_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/archsetjmp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "archsetjmp_32.h"
+#else
+#include "archsetjmp_64.h"
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo_32.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
+#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo_64.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* No broken SKAS API, which doesn't pass trap_no, here. */
+#define SEGV_MAYBE_FIXABLE(fi)	0
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/faultinfo.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "faultinfo_32.h"
+#else
+#include "faultinfo_64.h"
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/kernel-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/elf.h>
+#include <linux/crypto.h>
+#include <asm/mman.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define STR(x) #x
+#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+#include <common-offsets.h>
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/mcontext.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/mcontext.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/mcontext.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/mcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYS_SIGCONTEXT_X86_H
+#define __SYS_SIGCONTEXT_X86_H
+
+extern void get_regs_from_mc(struct uml_pt_regs *, mcontext_t *);
+
+#ifdef __i386__
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->cr2; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#else
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->gregs[REG_CR2]; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_32.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_PTRACE_H
+#define __SYSDEP_I386_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+
+static inline void update_debugregs(int seq) {}
+
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_EAX(r) ((r)[HOST_AX])
+#define REGS_EBX(r) ((r)[HOST_BX])
+#define REGS_ECX(r) ((r)[HOST_CX])
+#define REGS_EDX(r) ((r)[HOST_DX])
+#define REGS_ESI(r) ((r)[HOST_SI])
+#define REGS_EDI(r) ((r)[HOST_DI])
+#define REGS_EBP(r) ((r)[HOST_BP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#ifndef PTRACE_SYSEMU_SINGLESTEP
+#define PTRACE_SYSEMU_SINGLESTEP 32
+#endif
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FPX_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_EAX(r) REGS_EAX((r)->gp)
+#define UPT_EBX(r) REGS_EBX((r)->gp)
+#define UPT_ECX(r) REGS_ECX((r)->gp)
+#define UPT_EDX(r) REGS_EDX((r)->gp)
+#define UPT_ESI(r) REGS_ESI((r)->gp)
+#define UPT_EDI(r) REGS_EDI((r)->gp)
+#define UPT_EBP(r) REGS_EBP((r)->gp)
+#define UPT_ORIG_EAX(r) ((r)->syscall)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+
+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	\
+				     UPT_SYSCALL_ARG2(r),	\
+				     UPT_SYSCALL_ARG3(r),	\
+				     UPT_SYSCALL_ARG4(r),	\
+				     UPT_SYSCALL_ARG5(r),	\
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
+#define UPT_SYSCALL_RET(r) UPT_EAX(r)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+extern void arch_init_registers(int pid);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_64.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_PTRACE_H
+#define __SYSDEP_X86_64_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+
+#define REGS_RBX(r) ((r)[HOST_BX])
+#define REGS_RCX(r) ((r)[HOST_CX])
+#define REGS_RDX(r) ((r)[HOST_DX])
+#define REGS_RSI(r) ((r)[HOST_SI])
+#define REGS_RDI(r) ((r)[HOST_DI])
+#define REGS_RBP(r) ((r)[HOST_BP])
+#define REGS_RAX(r) ((r)[HOST_AX])
+#define REGS_R8(r) ((r)[HOST_R8])
+#define REGS_R9(r) ((r)[HOST_R9])
+#define REGS_R10(r) ((r)[HOST_R10])
+#define REGS_R11(r) ((r)[HOST_R11])
+#define REGS_R12(r) ((r)[HOST_R12])
+#define REGS_R13(r) ((r)[HOST_R13])
+#define REGS_R14(r) ((r)[HOST_R14])
+#define REGS_R15(r) ((r)[HOST_R15])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_SS(r) ((r)[HOST_SS])
+
+#define HOST_FS_BASE 21
+#define HOST_GS_BASE 22
+#define HOST_DS 23
+#define HOST_ES 24
+#define HOST_FS 25
+#define HOST_GS 26
+
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
+#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
+#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_AX])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
+#define REGS_TRAP(r) ((r)->trap_type)
+
+#define REGS_ERR(r) ((r)->fault_type)
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FP_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_RBX(r) REGS_RBX((r)->gp)
+#define UPT_RCX(r) REGS_RCX((r)->gp)
+#define UPT_RDX(r) REGS_RDX((r)->gp)
+#define UPT_RSI(r) REGS_RSI((r)->gp)
+#define UPT_RDI(r) REGS_RDI((r)->gp)
+#define UPT_RBP(r) REGS_RBP((r)->gp)
+#define UPT_RAX(r) REGS_RAX((r)->gp)
+#define UPT_R8(r) REGS_R8((r)->gp)
+#define UPT_R9(r) REGS_R9((r)->gp)
+#define UPT_R10(r) REGS_R10((r)->gp)
+#define UPT_R11(r) REGS_R11((r)->gp)
+#define UPT_R12(r) REGS_R12((r)->gp)
+#define UPT_R13(r) REGS_R13((r)->gp)
+#define UPT_R14(r) REGS_R14((r)->gp)
+#define UPT_R15(r) REGS_R15((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
+#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
+#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
+#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
+#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	 \
+				     UPT_SYSCALL_ARG2(r),	 \
+				     UPT_SYSCALL_ARG3(r),	 \
+				     UPT_SYSCALL_ARG4(r),	 \
+				     UPT_SYSCALL_ARG5(r),	 \
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+static inline void arch_init_registers(int pid)
+{
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "ptrace_32.h"
+#else
+#include "ptrace_64.h"
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/ptrace_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+#include <generated/user_constants.h>
+
+#define PT_OFFSET(r) ((r) * sizeof(long))
+
+#define PT_SYSCALL_NR(regs) ((regs)[HOST_ORIG_AX])
+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(HOST_ORIG_AX)
+
+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(HOST_AX)
+
+#define REGS_IP_INDEX HOST_IP
+#define REGS_SP_INDEX HOST_SP
+
+#ifdef __i386__
+#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
+#else
+#define FP_SIZE HOST_FP_SIZE
+
+/*
+ * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+ * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
+ * 2.4 name and value for 2.4 host compatibility.
+ */
+#ifndef PTRACE_OLDSETOPTIONS
+#define PTRACE_OLDSETOPTIONS 21
+#endif
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/skas_ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_SKAS_PTRACE_H
+#define __SYSDEP_X86_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub_32.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <asm/ptrace.h>
+
+#define STUB_SYSCALL_RET EAX
+#define STUB_MMAP_NR __NR_mmap2
+#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
+
+	return ret;
+}
+
+static inline long stub_syscall1(long syscall, long arg1)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2));
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3));
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4));
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(int fd, unsigned long offset)
+{
+	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
+			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
+			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
+			    "c" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
+			    "a" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : "memory");
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub_64.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <sysdep/ptrace_user.h>
+
+#define STUB_SYSCALL_RET PT_INDEX(RAX)
+#define STUB_MMAP_NR __NR_mmap
+#define MMAP_OFFSET(o) (o)
+
+#define __syscall_clobber "r11","rcx","memory"
+#define __syscall "syscall"
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
+		: __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4)
+		: __syscall_clobber, "r10" );
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4), "g" (arg5)
+		: __syscall_clobber, "r10", "r8" );
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(long fd, unsigned long offset)
+{
+	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
+			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
+			  "movq %%rax, (%%rbx)":
+			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
+			    "S" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
+			    "g" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : __syscall_clobber, "r10", "r8", "r9" );
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/stub.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+#include <asm/unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include "as-layout.h"
+#include "stub-data.h"
+
+#ifdef __i386__
+#include "stub_32.h"
+#else
+#include "stub_64.h"
+#endif
+
+extern void stub_segv_handler(int, siginfo_t *, void *);
+extern void stub_clone_handler(void);
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls_32.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls_32.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "asm/unistd.h"
+#include "sysdep/ptrace.h"
+
+typedef long syscall_handler_t(struct pt_regs);
+
+/* Not declared on x86, incompatible declarations on x86_64, so these have
+ * to go here rather than in sys_call_table.c
+ */
+extern syscall_handler_t sys_rt_sigaction;
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	((long (*)(struct syscall_args)) \
+	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls_64.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls_64.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SYSCALLS_H__
+#define __SYSDEP_X86_64_SYSCALLS_H__
+
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+typedef long syscall_handler_t(void);
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	(((long (*)(long, long, long, long, long, long)) \
+	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+		 		      UPT_SYSCALL_ARG2(&regs->regs), \
+				      UPT_SYSCALL_ARG3(&regs->regs), \
+				      UPT_SYSCALL_ARG4(&regs->regs), \
+				      UPT_SYSCALL_ARG5(&regs->regs), \
+				      UPT_SYSCALL_ARG6(&regs->regs)))
+
+extern long old_mmap(unsigned long addr, unsigned long len,
+		     unsigned long prot, unsigned long flags,
+		     unsigned long fd, unsigned long pgoff);
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_arch_prctl;
+
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/syscalls.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "syscalls_32.h"
+#else
+#include "syscalls_64.h"
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/tls.h linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/tls.h
--- linux-libre-3.1-gnu1/arch/x86/um/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/shared/sysdep/tls.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+	unsigned int  entry_number;
+	unsigned int  base_addr;
+	unsigned int  limit;
+	unsigned int  seg_32bit:1;
+	unsigned int  contents:2;
+	unsigned int  read_exec_only:1;
+	unsigned int  limit_in_pages:1;
+	unsigned int  seg_not_present:1;
+	unsigned int  useable:1;
+#ifdef __x86_64__
+	unsigned int  lm:1;
+#endif
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+#ifdef __i386__
+#define GDT_ENTRY_TLS_MIN_I386 6
+#define GDT_ENTRY_TLS_MIN_X86_64 12
+#endif
+
+#endif /* _SYSDEP_TLS_H */
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/signal.c linux-libre-3.2-gnu1/arch/x86/um/signal.c
--- linux-libre-3.1-gnu1/arch/x86/um/signal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/kernel.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include "frame_kern.h"
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+{
+	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
+	tmp = ~twd;
+	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+	/* and move the valid bits to the lower byte. */
+	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+	return tmp;
+}
+
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+	struct _fpxreg *st = NULL;
+	unsigned long twd = (unsigned long) fxsave->twd;
+	unsigned long tag;
+	unsigned long ret = 0xffff0000;
+	int i;
+
+#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
+
+	for (i = 0; i < 8; i++) {
+		if (twd & 0x1) {
+			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+			switch (st->exponent & 0x7fff) {
+			case 0x7fff:
+				tag = 2;		/* Special */
+				break;
+			case 0x0000:
+				if ( !st->significand[0] &&
+				     !st->significand[1] &&
+				     !st->significand[2] &&
+				     !st->significand[3] ) {
+					tag = 1;	/* Zero */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			default:
+				if (st->significand[3] & 0x8000) {
+					tag = 0;	/* Valid */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			}
+		} else {
+			tag = 3;			/* Empty */
+		}
+		ret |= (tag << (2 * i));
+		twd = twd >> 1;
+	}
+	return ret;
+}
+
+static int convert_fxsr_to_user(struct _fpstate __user *buf,
+				struct user_fxsr_struct *fxsave)
+{
+	unsigned long env[7];
+	struct _fpreg __user *to;
+	struct _fpxreg *from;
+	int i;
+
+	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
+	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
+	env[2] = twd_fxsr_to_i387(fxsave);
+	env[3] = fxsave->fip;
+	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
+	env[5] = fxsave->foo;
+	env[6] = fxsave->fos;
+
+	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
+		return 1;
+
+	to = &buf->_st[0];
+	from = (struct _fpxreg *) &fxsave->st_space[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long __user *t = (unsigned long __user *)to;
+		unsigned long *f = (unsigned long *)from;
+
+		if (__put_user(*f, t) ||
+				__put_user(*(f + 1), t + 1) ||
+				__put_user(from->exponent, &to->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
+				  struct _fpstate __user *buf)
+{
+	unsigned long env[7];
+	struct _fpxreg *to;
+	struct _fpreg __user *from;
+	int i;
+
+	if (copy_from_user( env, buf, 7 * sizeof(long)))
+		return 1;
+
+	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
+	fxsave->swd = (unsigned short)(env[1] & 0xffff);
+	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
+	fxsave->fip = env[3];
+	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
+	fxsave->fcs = (env[4] & 0xffff);
+	fxsave->foo = env[5];
+	fxsave->fos = env[6];
+
+	to = (struct _fpxreg *) &fxsave->st_space[0];
+	from = &buf->_st[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long *t = (unsigned long *)to;
+		unsigned long __user *f = (unsigned long __user *)from;
+
+		if (__get_user(*t, f) ||
+		    __get_user(*(t + 1), f + 1) ||
+		    __get_user(to->exponent, &from->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+extern int have_fpx_regs;
+
+#endif
+
+static int copy_sc_from_user(struct pt_regs *regs,
+			     struct sigcontext __user *from)
+{
+	struct sigcontext sc;
+	int err, pid;
+
+	err = copy_from_user(&sc, from, sizeof(sc));
+	if (err)
+		return err;
+
+#define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname
+
+#ifdef CONFIG_X86_32
+	GETREG(GS, gs);
+	GETREG(FS, fs);
+	GETREG(ES, es);
+	GETREG(DS, ds);
+#endif
+	GETREG(DI, di);
+	GETREG(SI, si);
+	GETREG(BP, bp);
+	GETREG(SP, sp);
+	GETREG(BX, bx);
+	GETREG(DX, dx);
+	GETREG(CX, cx);
+	GETREG(AX, ax);
+	GETREG(IP, ip);
+
+#ifdef CONFIG_X86_64
+	GETREG(R8, r8);
+	GETREG(R9, r9);
+	GETREG(R10, r10);
+	GETREG(R11, r11);
+	GETREG(R12, r12);
+	GETREG(R13, r13);
+	GETREG(R14, r14);
+	GETREG(R15, r15);
+#endif
+
+	GETREG(CS, cs);
+	GETREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	GETREG(SS, ss);
+#endif
+
+#undef GETREG
+
+	pid = userspace_pid[current_thread_info()->cpu];
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = copy_from_user(&fpx,
+			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
+				     sizeof(struct user_fxsr_struct));
+		if (err)
+			return 1;
+
+		err = convert_fxsr_from_user(&fpx, sc.fpstate);
+		if (err)
+			return 1;
+
+		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fpx_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = copy_from_user(&fp, sc.fpstate,
+				     sizeof(struct user_i387_struct));
+		if (err)
+			return 1;
+
+		err = restore_fp_registers(pid, (unsigned long *) &fp);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fp_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int copy_sc_to_user(struct sigcontext __user *to,
+			   struct _fpstate __user *to_fp, struct pt_regs *regs,
+			   unsigned long mask)
+{
+	struct sigcontext sc;
+	struct faultinfo * fi = &current->thread.arch.faultinfo;
+	int err, pid;
+	memset(&sc, 0, sizeof(struct sigcontext));
+
+#define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno]
+
+#ifdef CONFIG_X86_32
+	PUTREG(GS, gs);
+	PUTREG(FS, fs);
+	PUTREG(ES, es);
+	PUTREG(DS, ds);
+#endif
+	PUTREG(DI, di);
+	PUTREG(SI, si);
+	PUTREG(BP, bp);
+	PUTREG(SP, sp);
+	PUTREG(BX, bx);
+	PUTREG(DX, dx);
+	PUTREG(CX, cx);
+	PUTREG(AX, ax);
+#ifdef CONFIG_X86_64
+	PUTREG(R8, r8);
+	PUTREG(R9, r9);
+	PUTREG(R10, r10);
+	PUTREG(R11, r11);
+	PUTREG(R12, r12);
+	PUTREG(R13, r13);
+	PUTREG(R14, r14);
+	PUTREG(R15, r15);
+#endif
+
+	sc.cr2 = fi->cr2;
+	sc.err = fi->error_code;
+	sc.trapno = fi->trap_no;
+	PUTREG(IP, ip);
+	PUTREG(CS, cs);
+	PUTREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	PUTREG(SP, sp_at_signal);
+	PUTREG(SS, ss);
+#endif
+#undef PUTREG
+	sc.oldmask = mask;
+	sc.fpstate = to_fp;
+
+	err = copy_to_user(to, &sc, sizeof(struct sigcontext));
+	if (err)
+		return 1;
+
+	pid = userspace_pid[current_thread_info()->cpu];
+
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = save_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0){
+			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
+			       "failed, errno = %d\n", err);
+			return 1;
+		}
+
+		err = convert_fxsr_to_user(to_fp, &fpx);
+		if (err)
+			return 1;
+
+		err |= __put_user(fpx.swd, &to_fp->status);
+		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+		if (err)
+			return 1;
+
+		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+				 sizeof(struct user_fxsr_struct)))
+			return 1;
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = save_fp_registers(pid, (unsigned long *) &fp);
+		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+			return 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+static int copy_ucontext_to_user(struct ucontext __user *uc,
+				 struct _fpstate __user *fp, sigset_t *set,
+				 unsigned long sp)
+{
+	int err = 0;
+
+	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
+	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
+	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
+	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
+	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
+	return err;
+}
+
+struct sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct sigcontext sc;
+	struct _fpstate fpstate;
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[8];
+};
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	struct _fpstate fpstate;
+	char retcode[8];
+};
+
+int setup_signal_stack_sc(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  sigset_t *mask)
+{
+	struct sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
+	stack_top = ((stack_top + 4) & -16UL) - 4;
+	frame = (struct sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(sig, &frame->sig);
+	err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
+	if (_NSIG_WORDS > 1)
+		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
+				      sizeof(frame->extramask));
+
+	/*
+	 * This is popl %eax ; movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
+	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) 0;
+	PT_REGS_ECX(regs) = (unsigned long) 0;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  siginfo_t *info, sigset_t *mask)
+{
+	struct rt_sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	stack_top &= -8UL;
+	frame = (struct rt_sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(sig, &frame->sig);
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
+					PT_REGS_SP(regs));
+
+	/*
+	 * This is movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
+	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
+	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+long sys_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
+	sigset_t set;
+	struct sigcontext __user *sc = &frame->sc;
+	unsigned long __user *oldmask = &sc->oldmask;
+	unsigned long __user *extramask = frame->extramask;
+	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+
+	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
+	    copy_from_user(&set.sig[1], extramask, sig_size))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, sc))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#else
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	struct ucontext uc;
+	struct siginfo info;
+	struct _fpstate fpstate;
+};
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs * regs,
+			  siginfo_t *info, sigset_t *set)
+{
+	struct rt_sigframe __user *frame;
+	int err = 0;
+	struct task_struct *me = current;
+
+	frame = (struct rt_sigframe __user *)
+		round_down(stack_top - sizeof(struct rt_sigframe), 16);
+	/* Subtract 128 for a red zone and 8 for proper alignment */
+	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto out;
+
+	if (ka->sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, info);
+		if (err)
+			goto out;
+	}
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
+			       set->sig[0]);
+	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+	if (sizeof(*set) == 16) {
+		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
+		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
+	}
+	else
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
+				      sizeof(*set));
+
+	/*
+	 * Set up to return from userspace.  If provided, use a stub
+	 * already in userspace.
+	 */
+	/* x86-64 should always use SA_RESTORER. */
+	if (ka->sa.sa_flags & SA_RESTORER)
+		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+	else
+		/* could use a vstub here */
+		return err;
+
+	if (err)
+		return err;
+
+	/* Set up registers for signal handler */
+	{
+		struct exec_domain *ed = current_thread_info()->exec_domain;
+		if (unlikely(ed && ed->signal_invmap && sig < 32))
+			sig = ed->signal_invmap[sig];
+	}
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_RDI(regs) = sig;
+	/* In case the signal handler was declared without prototypes */
+	PT_REGS_RAX(regs) = 0;
+
+	/*
+	 * This also works for non SA_SIGINFO handlers because they expect the
+	 * next argument after the signal number on the stack.
+	 */
+	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
+	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
+	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
+ out:
+	return err;
+}
+#endif
+
+long sys_rt_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct rt_sigframe __user *frame =
+		(struct rt_sigframe __user *)(sp - sizeof(long));
+	struct ucontext __user *uc = &frame->uc;
+	sigset_t set;
+
+	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+long ptregs_sigreturn(void)
+{
+	return sys_sigreturn(NULL);
+}
+long ptregs_rt_sigreturn(void)
+{
+	return sys_rt_sigreturn(NULL);
+}
+#endif
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/stub_32.S linux-libre-3.2-gnu1/arch/x86/um/stub_32.S
--- linux-libre-3.1-gnu1/arch/x86/um/stub_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/stub_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,51 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	/* load pointer to first operation */
+	mov	$(STUB_DATA+8), %esp
+
+again:
+	/* load length of additional data */
+	mov	0x0(%esp), %eax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%eax, STUB_DATA+4
+	cmpl	$0, %eax
+	jz	done
+
+	/* save current pointer */
+	mov	%esp, STUB_DATA+4
+
+	/* skip additional data */
+	add	%eax, %esp
+
+	/* load syscall-# */
+	pop	%eax
+
+	/* load syscall params */
+	pop	%ebx
+	pop	%ecx
+	pop	%edx
+	pop	%esi
+ 	pop	%edi
+	pop	%ebp
+
+	/* execute syscall */
+	int	$0x80
+
+	/* check return value */
+	pop	%ebx
+	cmp	%ebx, %eax
+	je	again
+
+done:
+	/* save return value */
+	mov	%eax, STUB_DATA
+
+	/* stop */
+	int3
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/stub_64.S linux-libre-3.2-gnu1/arch/x86/um/stub_64.S
--- linux-libre-3.1-gnu1/arch/x86/um/stub_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/stub_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+syscall_stub:
+	syscall
+	/* We don't have 64-bit constants, so this constructs the address
+	 * we need.
+	 */
+	movq	$(STUB_DATA >> 32), %rbx
+	salq	$32, %rbx
+	movq	$(STUB_DATA & 0xffffffff), %rcx
+	or	%rcx, %rbx
+	movq	%rax, (%rbx)
+	int3
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	mov	$(STUB_DATA >> 32), %rbx
+	sal	$32, %rbx
+	mov	$(STUB_DATA & 0xffffffff), %rax
+	or	%rax, %rbx
+	/* load pointer to first operation */
+	mov	%rbx, %rsp
+	add	$0x10, %rsp
+again:
+	/* load length of additional data */
+	mov	0x0(%rsp), %rax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%rax, 8(%rbx)
+	cmp	$0, %rax
+	jz	done
+
+	/* save current pointer */
+	mov	%rsp, 8(%rbx)
+
+	/* skip additional data */
+	add	%rax, %rsp
+
+	/* load syscall-# */
+	pop	%rax
+
+	/* load syscall params */
+	pop	%rdi
+	pop	%rsi
+	pop	%rdx
+	pop	%r10
+ 	pop	%r8
+	pop	%r9
+
+	/* execute syscall */
+	syscall
+
+	/* check return value */
+	pop	%rcx
+	cmp	%rcx, %rax
+	je	again
+
+done:
+	/* save return value */
+	mov	%rax, (%rbx)
+
+	/* stop */
+	int3
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/stub_segv.c linux-libre-3.2-gnu1/arch/x86/um/stub_segv.c
--- linux-libre-3.1-gnu1/arch/x86/um/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/stub_segv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/stub.h"
+#include "sysdep/faultinfo.h"
+#include "sysdep/mcontext.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig, siginfo_t *info, void *p)
+{
+	struct ucontext *uc = p;
+
+	GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA),
+			      &uc->uc_mcontext);
+	trap_myself();
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/syscalls_32.c linux-libre-3.2-gnu1/arch/x86/um/syscalls_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/syscalls_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/syscalls_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/shm.h"
+#include "linux/ipc.h"
+#include "linux/syscalls.h"
+#include "asm/mman.h"
+#include "asm/uaccess.h"
+#include "asm/unistd.h"
+
+/*
+ * The prototype on i386 is:
+ *
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *
+ * and the "newtls" arg. on i386 is read by copy_thread directly from the
+ * register saved on the stack.
+ */
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       int __user *parent_tid, void *newtls, int __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+long sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/syscalls_64.c linux-libre-3.2-gnu1/arch/x86/um/syscalls_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/syscalls_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/syscalls_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/linkage.h"
+#include "linux/personality.h"
+#include "linux/utsname.h"
+#include "asm/prctl.h" /* XXX This should get the constants from libc */
+#include "asm/uaccess.h"
+#include "os.h"
+
+long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+{
+	unsigned long *ptr = addr, tmp;
+	long ret;
+	int pid = task->mm->context.id.u.pid;
+
+	/*
+	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
+	 * be safe), we need to call arch_prctl on the host because
+	 * setting %fs may result in something else happening (like a
+	 * GDT or thread.fs being set instead).  So, we let the host
+	 * fiddle the registers and thread struct and restore the
+	 * registers afterwards.
+	 *
+	 * So, the saved registers are stored to the process (this
+	 * needed because a stub may have been the last thing to run),
+	 * arch_prctl is run on the host, then the registers are read
+	 * back.
+	 */
+	switch (code) {
+	case ARCH_SET_FS:
+	case ARCH_SET_GS:
+		ret = restore_registers(pid, &current->thread.regs.regs);
+		if (ret)
+			return ret;
+		break;
+	case ARCH_GET_FS:
+	case ARCH_GET_GS:
+		/*
+		 * With these two, we read to a local pointer and
+		 * put_user it to the userspace pointer that we were
+		 * given.  If addr isn't valid (because it hasn't been
+		 * faulted in or is just bogus), we want put_user to
+		 * fault it in (or return -EFAULT) instead of having
+		 * the host return -EFAULT.
+		 */
+		ptr = &tmp;
+	}
+
+	ret = os_arch_prctl(pid, code, ptr);
+	if (ret)
+		return ret;
+
+	switch (code) {
+	case ARCH_SET_FS:
+		current->thread.arch.fs = (unsigned long) ptr;
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_SET_GS:
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_GET_FS:
+		ret = put_user(tmp, addr);
+		break;
+	case ARCH_GET_GS:
+		ret = put_user(tmp, addr);
+		break;
+	}
+
+	return ret;
+}
+
+long sys_arch_prctl(int code, unsigned long addr)
+{
+	return arch_prctl(current, code, (unsigned long __user *) addr);
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       void __user *parent_tid, void __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+void arch_switch_to(struct task_struct *to)
+{
+	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
+		return;
+
+	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/sys_call_table_32.S linux-libre-3.2-gnu1/arch/x86/um/sys_call_table_32.S
--- linux-libre-3.1-gnu1/arch/x86/um/sys_call_table_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/sys_call_table_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+#include <linux/linkage.h>
+/* Steal i386 syscall table for our purposes, but with some slight changes.*/
+
+#define sys_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+#define sys_vm86old sys_ni_syscall
+#define sys_vm86 sys_ni_syscall
+
+#define old_mmap sys_old_mmap
+
+#define ptregs_fork sys_fork
+#define ptregs_execve sys_execve
+#define ptregs_iopl sys_iopl
+#define ptregs_vm86old sys_vm86old
+#define ptregs_clone sys_clone
+#define ptregs_vm86 sys_vm86
+#define ptregs_sigaltstack sys_sigaltstack
+#define ptregs_vfork sys_vfork
+
+.section .rodata,"a"
+
+#include "../kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/sys_call_table_64.c linux-libre-3.2-gnu1/arch/x86/um/sys_call_table_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/sys_call_table_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/sys_call_table_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+
+#define __NO_STUBS
+
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
+
+/* Not going to be implemented by UML, since we have no hardware. */
+#define stub_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
+
+/* On UML we call it this way ("old" means it's not mmap2) */
+#define sys_mmap old_mmap
+
+#define stub_clone sys_clone
+#define stub_fork sys_fork
+#define stub_vfork sys_vfork
+#define stub_execve sys_execve
+#define stub_rt_sigsuspend sys_rt_sigsuspend
+#define stub_sigaltstack sys_sigaltstack
+#define stub_rt_sigreturn sys_rt_sigreturn
+
+#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+#undef _ASM_X86_UNISTD_64_H
+#include "../../x86/include/asm/unistd_64.h"
+
+#undef __SYSCALL
+#define __SYSCALL(nr, sym) [ nr ] = sym,
+#undef _ASM_X86_UNISTD_64_H
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void sys_ni_syscall(void);
+
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+#include <asm/unistd_64.h>
+};
+
+int syscall_table_size = sizeof(sys_call_table);
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/sysrq_32.c linux-libre-3.2-gnu1/arch/x86/um/sysrq_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/sysrq_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/sysrq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/smp.h"
+#include "linux/sched.h"
+#include "linux/kallsyms.h"
+#include "asm/ptrace.h"
+#include "sysrq.h"
+
+/* This is declared by <linux/sched.h> */
+void show_regs(struct pt_regs *regs)
+{
+        printk("\n");
+        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
+	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
+	       smp_processor_id(), print_tainted());
+        if (PT_REGS_CS(regs) & 3)
+                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
+		       PT_REGS_SP(regs));
+        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
+	       print_tainted());
+        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
+	       PT_REGS_ECX(regs), 
+	       PT_REGS_EDX(regs));
+        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
+	       PT_REGS_EBP(regs));
+        printk(" DS: %04lx ES: %04lx\n",
+	       0xffff & PT_REGS_DS(regs), 
+	       0xffff & PT_REGS_ES(regs));
+
+        show_trace(NULL, (unsigned long *) &regs);
+}
+
+/* Copied from i386. */
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+	return	p > (void *)tinfo &&
+		p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+/* Adapted from i386 (we also print the address we read from). */
+static inline unsigned long print_context_stack(struct thread_info *tinfo,
+				unsigned long *stack, unsigned long ebp)
+{
+	unsigned long addr;
+
+#ifdef CONFIG_FRAME_POINTER
+	while (valid_stack_ptr(tinfo, (void *)ebp)) {
+		addr = *(unsigned long *)(ebp + 4);
+		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
+		print_symbol(" %s", addr);
+		printk("\n");
+		ebp = *(unsigned long *)ebp;
+	}
+#else
+	while (valid_stack_ptr(tinfo, stack)) {
+		addr = *stack;
+		if (__kernel_text_address(addr)) {
+			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+			print_symbol(" %s", addr);
+			printk("\n");
+		}
+		stack++;
+	}
+#endif
+	return ebp;
+}
+
+void show_trace(struct task_struct* task, unsigned long * stack)
+{
+	unsigned long ebp;
+	struct thread_info *context;
+
+	/* Turn this into BUG_ON if possible. */
+	if (!stack) {
+		stack = (unsigned long*) &stack;
+		printk("show_trace: got NULL stack, implicit assumption task == current");
+		WARN_ON(1);
+	}
+
+	if (!task)
+		task = current;
+
+	if (task != current) {
+		ebp = (unsigned long) KSTK_EBP(task);
+	} else {
+		asm ("movl %%ebp, %0" : "=r" (ebp) : );
+	}
+
+	context = (struct thread_info *)
+		((unsigned long)stack & (~(THREAD_SIZE - 1)));
+	print_context_stack(context, stack, ebp);
+
+	printk("\n");
+}
+
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/sysrq_64.c linux-libre-3.2-gnu1/arch/x86/um/sysrq_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/sysrq_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/sysrq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
+#include "sysrq.h"
+
+void __show_regs(struct pt_regs *regs)
+{
+	printk("\n");
+	print_modules();
+	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+		current->comm, print_tainted(), init_utsname()->release);
+	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
+	       PT_REGS_RIP(regs));
+	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_SP(regs),
+	       PT_REGS_EFLAGS(regs));
+	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
+	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	__show_regs(regs);
+	show_trace(current, (unsigned long *) &regs);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/tls_32.c linux-libre-3.2-gnu1/arch/x86/um/tls_32.c
--- linux-libre-3.1-gnu1/arch/x86/um/tls_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/tls_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#include "linux/percpu.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "os.h"
+#include "skas.h"
+#include "sysdep/tls.h"
+
+/*
+ * If needed we can detect when it's uninitialized.
+ *
+ * These are initialized in an initcall and unchanged thereafter.
+ */
+static int host_supports_tls = -1;
+int host_gdt_entry_tls_min;
+
+int do_set_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_set_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+int do_get_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_get_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+/*
+ * sys_get_thread_area: get a yet unused TLS descriptor index.
+ * XXX: Consider leaving one free slot for glibc usage at first place. This must
+ * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
+ *
+ * Also, this must be tested when compiling in SKAS mode with dynamic linking
+ * and running against NPTL.
+ */
+static int get_free_idx(struct task_struct* task)
+{
+	struct thread_struct *t = &task->thread;
+	int idx;
+
+	if (!t->arch.tls_array)
+		return GDT_ENTRY_TLS_MIN;
+
+	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+		if (!t->arch.tls_array[idx].present)
+			return idx + GDT_ENTRY_TLS_MIN;
+	return -ESRCH;
+}
+
+static inline void clear_user_desc(struct user_desc* info)
+{
+	/* Postcondition: LDT_empty(info) returns true. */
+	memset(info, 0, sizeof(*info));
+
+	/*
+	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+	 * indeed an empty user_desc.
+	 */
+	info->read_exec_only = 1;
+	info->seg_not_present = 1;
+}
+
+#define O_FORCE 1
+
+static int load_TLS(int flags, struct task_struct *to)
+{
+	int ret = 0;
+	int idx;
+
+	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
+		struct uml_tls_struct* curr =
+			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Actually, now if it wasn't flushed it gets cleared and
+		 * flushed to the host, which will clear it.
+		 */
+		if (!curr->present) {
+			if (!curr->flushed) {
+				clear_user_desc(&curr->tls);
+				curr->tls.entry_number = idx;
+			} else {
+				WARN_ON(!LDT_empty(&curr->tls));
+				continue;
+			}
+		}
+
+		if (!(flags & O_FORCE) && curr->flushed)
+			continue;
+
+		ret = do_set_thread_area(&curr->tls);
+		if (ret)
+			goto out;
+
+		curr->flushed = 1;
+	}
+out:
+	return ret;
+}
+
+/*
+ * Verify if we need to do a flush for the new process, i.e. if there are any
+ * present desc's, only if they haven't been flushed.
+ */
+static inline int needs_TLS_update(struct task_struct *task)
+{
+	int i;
+	int ret = 0;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Can't test curr->present, we may need to clear a descriptor
+		 * which had a value.
+		 */
+		if (curr->flushed)
+			continue;
+		ret = 1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * On a newly forked process, the TLS descriptors haven't yet been flushed. So
+ * we mark them as such and the first switch_to will do the job.
+ */
+void clear_flushed_tls(struct task_struct *task)
+{
+	int i;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Still correct to do this, if it wasn't present on the host it
+		 * will remain as flushed as it was.
+		 */
+		if (!curr->present)
+			continue;
+
+		curr->flushed = 0;
+	}
+}
+
+/*
+ * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
+ * SKAS patch.
+ */
+
+int arch_switch_tls(struct task_struct *to)
+{
+	if (!host_supports_tls)
+		return 0;
+
+	/*
+	 * We have no need whatsoever to switch TLS for kernel threads; beyond
+	 * that, that would also result in us calling os_set_thread_area with
+	 * userspace_pid[cpu] == 0, which gives an error.
+	 */
+	if (likely(to->mm))
+		return load_TLS(O_FORCE, to);
+
+	return 0;
+}
+
+static int set_tls_entry(struct task_struct* task, struct user_desc *info,
+			 int idx, int flushed)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
+
+	return 0;
+}
+
+int arch_copy_tls(struct task_struct *new)
+{
+	struct user_desc info;
+	int idx, ret = -EFAULT;
+
+	if (copy_from_user(&info,
+			   (void __user *) UPT_ESI(&new->thread.regs.regs),
+			   sizeof(info)))
+		goto out;
+
+	ret = -EINVAL;
+	if (LDT_empty(&info))
+		goto out;
+
+	idx = info.entry_number;
+
+	ret = set_tls_entry(new, &info, idx, 0);
+out:
+	return ret;
+}
+
+/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+			 int idx)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (!t->arch.tls_array)
+		goto clear;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
+		goto clear;
+
+	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
+
+out:
+	/*
+	 * Temporary debugging check, to make sure that things have been
+	 * flushed. This could be triggered if load_TLS() failed.
+	 */
+	if (unlikely(task == current &&
+		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
+				"without flushed TLS.", current->pid);
+	}
+
+	return 0;
+clear:
+	/*
+	 * When the TLS entry has not been set, the values read to user in the
+	 * tls_array are 0 (because it's cleared at boot, see
+	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
+	 */
+	clear_user_desc(info);
+	info->entry_number = idx;
+	goto out;
+}
+
+int sys_set_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	idx = info.entry_number;
+
+	if (idx == -1) {
+		idx = get_free_idx(current);
+		if (idx < 0)
+			return idx;
+		info.entry_number = idx;
+		/* Tell the user which slot we chose for him.*/
+		if (put_user(idx, &user_desc->entry_number))
+			return -EFAULT;
+	}
+
+	ret = do_set_thread_area(&info);
+	if (ret)
+		return ret;
+	return set_tls_entry(current, &info, idx, 1);
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ * Note: error handling is not done on the deferred load, and this differ from
+ * i386. However the only possible error are caused by bugs.
+ */
+int ptrace_set_thread_area(struct task_struct *child, int idx,
+			   struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	return set_tls_entry(child, &info, idx, 0);
+}
+
+int sys_get_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (get_user(idx, &user_desc->entry_number))
+		return -EFAULT;
+
+	ret = get_tls_entry(current, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+
+out:
+	return ret;
+}
+
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+int ptrace_get_thread_area(struct task_struct *child, int idx,
+		struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int ret;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	ret = get_tls_entry(child, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+out:
+	return ret;
+}
+
+/*
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
+ */
+static int __init __setup_host_supports_tls(void)
+{
+	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
+	if (host_supports_tls) {
+		printk(KERN_INFO "Host TLS support detected\n");
+		printk(KERN_INFO "Detected host type: ");
+		switch (host_gdt_entry_tls_min) {
+		case GDT_ENTRY_TLS_MIN_I386:
+			printk(KERN_CONT "i386");
+			break;
+		case GDT_ENTRY_TLS_MIN_X86_64:
+			printk(KERN_CONT "x86_64");
+			break;
+		}
+		printk(KERN_CONT " (GDT indexes %d to %d)\n",
+		       host_gdt_entry_tls_min,
+		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
+	} else
+		printk(KERN_ERR "  Host TLS support NOT detected! "
+				"TLS support inside UML will not work\n");
+	return 0;
+}
+
+__initcall(__setup_host_supports_tls);
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/tls_64.c linux-libre-3.2-gnu1/arch/x86/um/tls_64.c
--- linux-libre-3.1-gnu1/arch/x86/um/tls_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/tls_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+#include "linux/sched.h"
+
+void clear_flushed_tls(struct task_struct *task)
+{
+}
+
+int arch_copy_tls(struct task_struct *t)
+{
+	/*
+	 * If CLONE_SETTLS is set, we need to save the thread id
+	 * (which is argument 5, child_tid, of clone) so it can be set
+	 * during context switches.
+	 */
+	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/user-offsets.c linux-libre-3.2-gnu1/arch/x86/um/user-offsets.c
--- linux-libre-3.1-gnu1/arch/x86/um/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/user-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define DEFINE_LONGS(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+
+void foo(void)
+{
+#ifdef __i386__
+	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
+	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
+
+	DEFINE(HOST_IP, EIP);
+	DEFINE(HOST_SP, UESP);
+	DEFINE(HOST_EFLAGS, EFL);
+	DEFINE(HOST_AX, EAX);
+	DEFINE(HOST_BX, EBX);
+	DEFINE(HOST_CX, ECX);
+	DEFINE(HOST_DX, EDX);
+	DEFINE(HOST_SI, ESI);
+	DEFINE(HOST_DI, EDI);
+	DEFINE(HOST_BP, EBP);
+	DEFINE(HOST_CS, CS);
+	DEFINE(HOST_SS, SS);
+	DEFINE(HOST_DS, DS);
+	DEFINE(HOST_FS, FS);
+	DEFINE(HOST_ES, ES);
+	DEFINE(HOST_GS, GS);
+	DEFINE(HOST_ORIG_AX, ORIG_EAX);
+#else
+	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
+	DEFINE_LONGS(HOST_BX, RBX);
+	DEFINE_LONGS(HOST_CX, RCX);
+	DEFINE_LONGS(HOST_DI, RDI);
+	DEFINE_LONGS(HOST_SI, RSI);
+	DEFINE_LONGS(HOST_DX, RDX);
+	DEFINE_LONGS(HOST_BP, RBP);
+	DEFINE_LONGS(HOST_AX, RAX);
+	DEFINE_LONGS(HOST_R8, R8);
+	DEFINE_LONGS(HOST_R9, R9);
+	DEFINE_LONGS(HOST_R10, R10);
+	DEFINE_LONGS(HOST_R11, R11);
+	DEFINE_LONGS(HOST_R12, R12);
+	DEFINE_LONGS(HOST_R13, R13);
+	DEFINE_LONGS(HOST_R14, R14);
+	DEFINE_LONGS(HOST_R15, R15);
+	DEFINE_LONGS(HOST_ORIG_AX, ORIG_RAX);
+	DEFINE_LONGS(HOST_CS, CS);
+	DEFINE_LONGS(HOST_SS, SS);
+	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
+#if 0
+	DEFINE_LONGS(HOST_FS, FS);
+	DEFINE_LONGS(HOST_GS, GS);
+	DEFINE_LONGS(HOST_DS, DS);
+	DEFINE_LONGS(HOST_ES, ES);
+#endif
+
+	DEFINE_LONGS(HOST_IP, RIP);
+	DEFINE_LONGS(HOST_SP, RSP);
+#endif
+
+	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+	DEFINE(UM_POLLIN, POLLIN);
+	DEFINE(UM_POLLPRI, POLLPRI);
+	DEFINE(UM_POLLOUT, POLLOUT);
+
+	DEFINE(UM_PROT_READ, PROT_READ);
+	DEFINE(UM_PROT_WRITE, PROT_WRITE);
+	DEFINE(UM_PROT_EXEC, PROT_EXEC);
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/checkundef.sh linux-libre-3.2-gnu1/arch/x86/um/vdso/checkundef.sh
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/checkundef.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/checkundef.sh	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+$nm "$file" | grep '^ *U' > /dev/null 2>&1
+if [ $? -eq 1 ]; then
+    exit 0
+else
+    echo "$file: undefined symbols found" >&2
+    exit 1
+fi
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/Makefile linux-libre-3.2-gnu1/arch/x86/um/vdso/Makefile
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+#
+# Building vDSO images for x86.
+#
+
+VDSO64-y		:= y
+
+vdso-install-$(VDSO64-y)	+= vdso.so
+
+
+# files to link into the vdso
+vobjs-y := vdso-note.o um_vdso.o
+
+# files to link into kernel
+obj-$(VDSO64-y)			+= vdso.o vma.o
+
+vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+
+$(obj)/vdso.o: $(obj)/vdso.so
+
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+
+export CPPFLAGS_vdso.lds += -P -C
+
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+
+$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
+	$(call if_changed,vdso)
+
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+#
+# Don't omit frame pointers for ease of userspace debugging, but do
+# optimize sibling calls.
+#
+CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+       -fno-omit-frame-pointer -foptimize-sibling-calls
+
+$(vobjs): KBUILD_CFLAGS += $(CFL)
+
+#
+# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+#
+CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage
+CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
+
+targets += vdso-syms.lds
+obj-$(VDSO64-y)			+= vdso-syms.lds
+
+#
+# Match symbols in the DSO that look like VDSO*; produce a file of constants.
+#
+sed-vdsosym := -e 's/^00*/0/' \
+	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
+endef
+
+$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+#
+# The DSO images are built using a special linker script.
+#
+quiet_cmd_vdso = VDSO    $@
+      cmd_vdso = $(CC) -nostdlib -o $@ \
+		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
+
+#
+# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+#
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+PHONY += vdso_install $(vdso-install-y)
+vdso_install: $(vdso-install-y)
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/um_vdso.c linux-libre-3.2-gnu1/arch/x86/um/vdso/um_vdso.c
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/um_vdso.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/um_vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * 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.
+ *
+ * This vDSO turns all calls into a syscall so that UML can trap them.
+ */
+
+
+/* Disable profiling for userspace code */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/getcpu.h>
+#include <asm/unistd.h>
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+
+	return ret;
+}
+int clock_gettime(clockid_t, struct timespec *)
+	__attribute__((weak, alias("__vdso_clock_gettime")));
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+
+	return ret;
+}
+int gettimeofday(struct timeval *, struct timezone *)
+	__attribute__((weak, alias("__vdso_gettimeofday")));
+
+time_t __vdso_time(time_t *t)
+{
+	long secs;
+
+	asm volatile("syscall"
+		: "=a" (secs)
+		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
+
+	return secs;
+}
+int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+
+long
+__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+	/*
+	 * UML does not support SMP, we can cheat here. :)
+	 */
+
+	if (cpu)
+		*cpu = 0;
+	if (node)
+		*node = 0;
+
+	return 0;
+}
+
+long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+	__attribute__((weak, alias("__vdso_getcpu")));
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso-layout.lds.S linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso-layout.lds.S
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso-layout.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso-layout.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Linker script for vDSO.  This is an ELF shared object prelinked to
+ * its virtual address, and with only one read-only segment.
+ * This script controls its layout.
+ */
+
+SECTIONS
+{
+	. = VDSO_PRELINK + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+	.data		: {
+	      *(.data*)
+	      *(.sdata*)
+	      *(.got.plt) *(.got)
+	      *(.gnu.linkonce.d.*)
+	      *(.bss*)
+	      *(.dynbss*)
+	      *(.gnu.linkonce.b.*)
+	}
+
+	.altinstructions	: { *(.altinstructions) }
+	.altinstr_replacement	: { *(.altinstr_replacement) }
+
+	/*
+	 * Align the actual code well away from the non-instruction data.
+	 * This is the best thing for the I-cache.
+	 */
+	. = ALIGN(0x100);
+
+	.text		: { *(.text*) }			:text	=0x90909090
+}
+
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME	0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso.lds.S linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso.lds.S
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Linker script for 64-bit vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO.  We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0xffffffffff700000
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+		time;
+		__vdso_time;
+	local: *;
+	};
+}
+
+VDSO64_PRELINK = VDSO_PRELINK;
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso-note.S linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso-note.S
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso-note.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso-note.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso.S linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso.S
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/vdso.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/vdso.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+	.globl vdso_start, vdso_end
+vdso_start:
+	.incbin "arch/x86/um/vdso/vdso.so"
+vdso_end:
+
+__FINIT
diff -druNp linux-libre-3.1-gnu1/arch/x86/um/vdso/vma.c linux-libre-3.2-gnu1/arch/x86/um/vdso/vma.c
--- linux-libre-3.1-gnu1/arch/x86/um/vdso/vma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/arch/x86/um/vdso/vma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * 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/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+	struct page *um_vdso;
+
+	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+	um_vdso_addr = task_size - PAGE_SIZE;
+
+	vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
+	if (!vdsop)
+		goto oom;
+
+	um_vdso = alloc_page(GFP_KERNEL);
+	if (!um_vdso) {
+		kfree(vdsop);
+
+		goto oom;
+	}
+
+	copy_page(page_address(um_vdso), vdso_start);
+	*vdsop = um_vdso;
+
+	return 0;
+
+oom:
+	printk(KERN_ERR "Cannot allocate vdso\n");
+	vdso_enabled = 0;
+
+	return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int err;
+	struct mm_struct *mm = current->mm;
+
+	if (!vdso_enabled)
+		return 0;
+
+	down_write(&mm->mmap_sem);
+
+	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+		VM_READ|VM_EXEC|
+		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+		VM_ALWAYSDUMP,
+		vdsop);
+
+	up_write(&mm->mmap_sem);
+
+	return err;
+}
diff -druNp linux-libre-3.1-gnu1/arch/x86/vdso/vma.c linux-libre-3.2-gnu1/arch/x86/vdso/vma.c
--- linux-libre-3.1-gnu1/arch/x86/vdso/vma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/vdso/vma.c	2012-01-04 18:55:44.000000000 -0500
@@ -89,6 +89,15 @@ static unsigned long vdso_addr(unsigned
 	addr = start + (offset << PAGE_SHIFT);
 	if (addr >= end)
 		addr = end;
+
+	/*
+	 * page-align it here so that get_unmapped_area doesn't
+	 * align it wrongfully again to the next page. addr can come in 4K
+	 * unaligned here as a result of stack start randomization.
+	 */
+	addr = PAGE_ALIGN(addr);
+	addr = align_addr(addr, NULL, ALIGN_VDSO);
+
 	return addr;
 }
 
diff -druNp linux-libre-3.1-gnu1/arch/x86/video/fbdev.c linux-libre-3.2-gnu1/arch/x86/video/fbdev.c
--- linux-libre-3.1-gnu1/arch/x86/video/fbdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/video/fbdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 #include <linux/fb.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 
 int fb_is_primary_device(struct fb_info *info)
 {
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/enlighten.c linux-libre-3.2-gnu1/arch/x86/xen/enlighten.c
--- linux-libre-3.1-gnu1/arch/x86/xen/enlighten.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/enlighten.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,6 +251,7 @@ static void __init xen_init_cpuid_mask(v
 			~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
 			  (1 << X86_FEATURE_ACPI));  /* disable ACPI */
 	ax = 1;
+	cx = 0;
 	xen_cpuid(&ax, &bx, &cx, &dx);
 
 	xsave_mask =
@@ -1355,7 +1356,7 @@ static int __cpuinit xen_hvm_cpu_notify(
 	int cpu = (long)hcpu;
 	switch (action) {
 	case CPU_UP_PREPARE:
-		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+		xen_vcpu_setup(cpu);
 		if (xen_have_vector_callback)
 			xen_init_lock_cpu(cpu);
 		break;
@@ -1385,7 +1386,6 @@ static void __init xen_hvm_guest_init(vo
 	xen_hvm_smp_init();
 	register_cpu_notifier(&xen_hvm_cpu_notifier);
 	xen_unplug_emulated_devices();
-	have_vcpu_info_placement = 0;
 	x86_init.irqs.intr_init = xen_init_IRQ;
 	xen_hvm_init_time_ops();
 	xen_hvm_init_mmu_ops();
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/grant-table.c linux-libre-3.2-gnu1/arch/x86/xen/grant-table.c
--- linux-libre-3.1-gnu1/arch/x86/xen/grant-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/grant-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long
 
 	if (shared == NULL) {
 		struct vm_struct *area =
-			xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
+			alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
 		BUG_ON(area == NULL);
 		shared = area->addr;
 		*__shared = shared;
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/Kconfig linux-libre-3.2-gnu1/arch/x86/xen/Kconfig
--- linux-libre-3.1-gnu1/arch/x86/xen/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -25,8 +25,7 @@ config XEN_PRIVILEGED_GUEST
 
 config XEN_PVHVM
 	def_bool y
-	depends on XEN
-	depends on X86_LOCAL_APIC
+	depends on XEN && PCI && X86_LOCAL_APIC
 
 config XEN_MAX_DOMAIN_MEMORY
        int
@@ -49,11 +48,3 @@ config XEN_DEBUG_FS
 	help
 	  Enable statistics output and various tuning options in debugfs.
 	  Enabling this option may incur a significant performance overhead.
-
-config XEN_DEBUG
-	bool "Enable Xen debug checks"
-	depends on XEN
-	default n
-	help
-	  Enable various WARN_ON checks in the Xen MMU code.
-	  Enabling this option WILL incur a significant performance overhead.
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/mmu.c linux-libre-3.2-gnu1/arch/x86/xen/mmu.c
--- linux-libre-3.1-gnu1/arch/x86/xen/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -495,41 +495,6 @@ static pte_t xen_make_pte(pteval_t pte)
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);
 
-#ifdef CONFIG_XEN_DEBUG
-pte_t xen_make_pte_debug(pteval_t pte)
-{
-	phys_addr_t addr = (pte & PTE_PFN_MASK);
-	phys_addr_t other_addr;
-	bool io_page = false;
-	pte_t _pte;
-
-	if (pte & _PAGE_IOMAP)
-		io_page = true;
-
-	_pte = xen_make_pte(pte);
-
-	if (!addr)
-		return _pte;
-
-	if (io_page &&
-	    (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
-		other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
-		WARN_ONCE(addr != other_addr,
-			"0x%lx is using VM_IO, but it is 0x%lx!\n",
-			(unsigned long)addr, (unsigned long)other_addr);
-	} else {
-		pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
-		other_addr = (_pte.pte & PTE_PFN_MASK);
-		WARN_ONCE((addr == other_addr) && (!io_page) && (!iomap_set),
-			"0x%lx is missing VM_IO (and wasn't fixed)!\n",
-			(unsigned long)addr);
-	}
-
-	return _pte;
-}
-PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug);
-#endif
-
 static pgd_t xen_make_pgd(pgdval_t pgd)
 {
 	pgd = pte_pfn_to_mfn(pgd);
@@ -1992,9 +1957,6 @@ void __init xen_ident_map_ISA(void)
 
 static void __init xen_post_allocator_init(void)
 {
-#ifdef CONFIG_XEN_DEBUG
-	pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
-#endif
 	pv_mmu_ops.set_pte = xen_set_pte;
 	pv_mmu_ops.set_pmd = xen_set_pmd;
 	pv_mmu_ops.set_pud = xen_set_pud;
@@ -2404,17 +2366,3 @@ out:
 	return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
-
-#ifdef CONFIG_XEN_DEBUG_FS
-static int p2m_dump_open(struct inode *inode, struct file *filp)
-{
-	return single_open(filp, p2m_dump_show, NULL);
-}
-
-static const struct file_operations p2m_dump_fops = {
-	.open		= p2m_dump_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-#endif /* CONFIG_XEN_DEBUG_FS */
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/p2m.c linux-libre-3.2-gnu1/arch/x86/xen/p2m.c
--- linux-libre-3.1-gnu1/arch/x86/xen/p2m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/p2m.c	2012-01-04 18:55:44.000000000 -0500
@@ -161,7 +161,9 @@
 #include <asm/xen/page.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
+#include <xen/grant_table.h>
 
+#include "multicalls.h"
 #include "xen-ops.h"
 
 static void __init m2p_override_init(void);
@@ -676,7 +678,8 @@ static unsigned long mfn_hash(unsigned l
 }
 
 /* Add an MFN override for a particular page */
-int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
+int m2p_add_override(unsigned long mfn, struct page *page,
+		struct gnttab_map_grant_ref *kmap_op)
 {
 	unsigned long flags;
 	unsigned long pfn;
@@ -692,16 +695,28 @@ int m2p_add_override(unsigned long mfn,
 					"m2p_add_override: pfn %lx not mapped", pfn))
 			return -EINVAL;
 	}
-
-	page->private = mfn;
+	WARN_ON(PagePrivate(page));
+	SetPagePrivate(page);
+	set_page_private(page, mfn);
 	page->index = pfn_to_mfn(pfn);
 
 	if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
 		return -ENOMEM;
 
-	if (clear_pte && !PageHighMem(page))
-		/* Just zap old mapping for now */
-		pte_clear(&init_mm, address, ptep);
+	if (kmap_op != NULL) {
+		if (!PageHighMem(page)) {
+			struct multicall_space mcs =
+				xen_mc_entry(sizeof(*kmap_op));
+
+			MULTI_grant_table_op(mcs.mc,
+					GNTTABOP_map_grant_ref, kmap_op, 1);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
+		}
+		/* let's use dev_bus_addr to record the old mfn instead */
+		kmap_op->dev_bus_addr = page->index;
+		page->index = (unsigned long) kmap_op;
+	}
 	spin_lock_irqsave(&m2p_override_lock, flags);
 	list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
 	spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -735,13 +750,56 @@ int m2p_remove_override(struct page *pag
 	spin_lock_irqsave(&m2p_override_lock, flags);
 	list_del(&page->lru);
 	spin_unlock_irqrestore(&m2p_override_lock, flags);
-	set_phys_to_machine(pfn, page->index);
+	WARN_ON(!PagePrivate(page));
+	ClearPagePrivate(page);
 
-	if (clear_pte && !PageHighMem(page))
-		set_pte_at(&init_mm, address, ptep,
-				pfn_pte(pfn, PAGE_KERNEL));
-		/* No tlb flush necessary because the caller already
-		 * left the pte unmapped. */
+	if (clear_pte) {
+		struct gnttab_map_grant_ref *map_op =
+			(struct gnttab_map_grant_ref *) page->index;
+		set_phys_to_machine(pfn, map_op->dev_bus_addr);
+		if (!PageHighMem(page)) {
+			struct multicall_space mcs;
+			struct gnttab_unmap_grant_ref *unmap_op;
+
+			/*
+			 * It might be that we queued all the m2p grant table
+			 * hypercalls in a multicall, then m2p_remove_override
+			 * get called before the multicall has actually been
+			 * issued. In this case handle is going to -1 because
+			 * it hasn't been modified yet.
+			 */
+			if (map_op->handle == -1)
+				xen_mc_flush();
+			/*
+			 * Now if map_op->handle is negative it means that the
+			 * hypercall actually returned an error.
+			 */
+			if (map_op->handle == GNTST_general_error) {
+				printk(KERN_WARNING "m2p_remove_override: "
+						"pfn %lx mfn %lx, failed to modify kernel mappings",
+						pfn, mfn);
+				return -1;
+			}
+
+			mcs = xen_mc_entry(
+					sizeof(struct gnttab_unmap_grant_ref));
+			unmap_op = mcs.args;
+			unmap_op->host_addr = map_op->host_addr;
+			unmap_op->handle = map_op->handle;
+			unmap_op->dev_bus_addr = 0;
+
+			MULTI_grant_table_op(mcs.mc,
+					GNTTABOP_unmap_grant_ref, unmap_op, 1);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+			set_pte_at(&init_mm, address, ptep,
+					pfn_pte(pfn, PAGE_KERNEL));
+			__flush_tlb_single(address);
+			map_op->host_addr = 0;
+		}
+	} else
+		set_phys_to_machine(pfn, page->index);
 
 	return 0;
 }
@@ -758,7 +816,7 @@ struct page *m2p_find_override(unsigned
 	spin_lock_irqsave(&m2p_override_lock, flags);
 
 	list_for_each_entry(p, bucket, lru) {
-		if (p->private == mfn) {
+		if (page_private(p) == mfn) {
 			ret = p;
 			break;
 		}
@@ -782,17 +840,21 @@ unsigned long m2p_find_override_pfn(unsi
 EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
 
 #ifdef CONFIG_XEN_DEBUG_FS
-
-int p2m_dump_show(struct seq_file *m, void *v)
+#include <linux/debugfs.h>
+#include "debugfs.h"
+static int p2m_dump_show(struct seq_file *m, void *v)
 {
 	static const char * const level_name[] = { "top", "middle",
-						"entry", "abnormal" };
-	static const char * const type_name[] = { "identity", "missing",
-						"pfn", "abnormal"};
+						"entry", "abnormal", "error"};
 #define TYPE_IDENTITY 0
 #define TYPE_MISSING 1
 #define TYPE_PFN 2
 #define TYPE_UNKNOWN 3
+	static const char * const type_name[] = {
+				[TYPE_IDENTITY] = "identity",
+				[TYPE_MISSING] = "missing",
+				[TYPE_PFN] = "pfn",
+				[TYPE_UNKNOWN] = "abnormal"};
 	unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
 	unsigned int uninitialized_var(prev_level);
 	unsigned int uninitialized_var(prev_type);
@@ -856,4 +918,32 @@ int p2m_dump_show(struct seq_file *m, vo
 #undef TYPE_PFN
 #undef TYPE_UNKNOWN
 }
-#endif
+
+static int p2m_dump_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, p2m_dump_show, NULL);
+}
+
+static const struct file_operations p2m_dump_fops = {
+	.open		= p2m_dump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct dentry *d_mmu_debug;
+
+static int __init xen_p2m_debugfs(void)
+{
+	struct dentry *d_xen = xen_init_debugfs();
+
+	if (d_xen == NULL)
+		return -ENOMEM;
+
+	d_mmu_debug = debugfs_create_dir("mmu", d_xen);
+
+	debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
+	return 0;
+}
+fs_initcall(xen_p2m_debugfs);
+#endif /* CONFIG_XEN_DEBUG_FS */
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/setup.c linux-libre-3.2-gnu1/arch/x86/xen/setup.c
--- linux-libre-3.1-gnu1/arch/x86/xen/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,10 @@ extern void xen_syscall_target(void);
 extern void xen_syscall32_target(void);
 
 /* Amount of extra memory space we add to the e820 ranges */
-phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+
+/* Number of pages released from the initial allocation. */
+unsigned long xen_released_pages;
 
 /* 
  * The maximum amount of extra memory compared to the base size.  The
@@ -51,48 +54,47 @@ phys_addr_t xen_extra_mem_start, xen_ext
  */
 #define EXTRA_MEM_RATIO		(10)
 
-static void __init xen_add_extra_mem(unsigned long pages)
+static void __init xen_add_extra_mem(u64 start, u64 size)
 {
 	unsigned long pfn;
+	int i;
 
-	u64 size = (u64)pages * PAGE_SIZE;
-	u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
-
-	if (!pages)
-		return;
-
-	e820_add_region(extra_start, size, E820_RAM);
-	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
-	memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA");
+	for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
+		/* Add new region. */
+		if (xen_extra_mem[i].size == 0) {
+			xen_extra_mem[i].start = start;
+			xen_extra_mem[i].size  = size;
+			break;
+		}
+		/* Append to existing region. */
+		if (xen_extra_mem[i].start + xen_extra_mem[i].size == start) {
+			xen_extra_mem[i].size += size;
+			break;
+		}
+	}
+	if (i == XEN_EXTRA_MEM_MAX_REGIONS)
+		printk(KERN_WARNING "Warning: not enough extra memory regions\n");
 
-	xen_extra_mem_size += size;
+	memblock_x86_reserve_range(start, start + size, "XEN EXTRA");
 
-	xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+	xen_max_p2m_pfn = PFN_DOWN(start + size);
 
-	for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+	for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++)
 		__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 }
 
-static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
-					      phys_addr_t end_addr)
+static unsigned long __init xen_release_chunk(unsigned long start,
+					      unsigned long end)
 {
 	struct xen_memory_reservation reservation = {
 		.address_bits = 0,
 		.extent_order = 0,
 		.domid        = DOMID_SELF
 	};
-	unsigned long start, end;
 	unsigned long len = 0;
 	unsigned long pfn;
 	int ret;
 
-	start = PFN_UP(start_addr);
-	end = PFN_DOWN(end_addr);
-
-	if (end <= start)
-		return 0;
-
 	for(pfn = start; pfn < end; pfn++) {
 		unsigned long mfn = pfn_to_mfn(pfn);
 
@@ -117,72 +119,52 @@ static unsigned long __init xen_release_
 	return len;
 }
 
-static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
-						     const struct e820map *e820)
+static unsigned long __init xen_set_identity_and_release(
+	const struct e820entry *list, size_t map_size, unsigned long nr_pages)
 {
-	phys_addr_t max_addr = PFN_PHYS(max_pfn);
-	phys_addr_t last_end = ISA_END_ADDRESS;
+	phys_addr_t start = 0;
 	unsigned long released = 0;
-	int i;
-
-	/* Free any unused memory above the low 1Mbyte. */
-	for (i = 0; i < e820->nr_map && last_end < max_addr; i++) {
-		phys_addr_t end = e820->map[i].addr;
-		end = min(max_addr, end);
-
-		if (last_end < end)
-			released += xen_release_chunk(last_end, end);
-		last_end = max(last_end, e820->map[i].addr + e820->map[i].size);
-	}
-
-	if (last_end < max_addr)
-		released += xen_release_chunk(last_end, max_addr);
-
-	printk(KERN_INFO "released %lu pages of unused memory\n", released);
-	return released;
-}
-
-static unsigned long __init xen_set_identity(const struct e820entry *list,
-					     ssize_t map_size)
-{
-	phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
-	phys_addr_t start_pci = last;
-	const struct e820entry *entry;
 	unsigned long identity = 0;
+	const struct e820entry *entry;
 	int i;
 
+	/*
+	 * Combine non-RAM regions and gaps until a RAM region (or the
+	 * end of the map) is reached, then set the 1:1 map and
+	 * release the pages (if available) in those non-RAM regions.
+	 *
+	 * The combined non-RAM regions are rounded to a whole number
+	 * of pages so any partial pages are accessible via the 1:1
+	 * mapping.  This is needed for some BIOSes that put (for
+	 * example) the DMI tables in a reserved region that begins on
+	 * a non-page boundary.
+	 */
 	for (i = 0, entry = list; i < map_size; i++, entry++) {
-		phys_addr_t start = entry->addr;
-		phys_addr_t end = start + entry->size;
+		phys_addr_t end = entry->addr + entry->size;
 
-		if (start < last)
-			start = last;
+		if (entry->type == E820_RAM || i == map_size - 1) {
+			unsigned long start_pfn = PFN_DOWN(start);
+			unsigned long end_pfn = PFN_UP(end);
 
-		if (end <= start)
-			continue;
+			if (entry->type == E820_RAM)
+				end_pfn = PFN_UP(entry->addr);
 
-		/* Skip over the 1MB region. */
-		if (last > end)
-			continue;
+			if (start_pfn < end_pfn) {
+				if (start_pfn < nr_pages)
+					released += xen_release_chunk(
+						start_pfn, min(end_pfn, nr_pages));
 
-		if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) {
-			if (start > start_pci)
 				identity += set_phys_range_identity(
-						PFN_UP(start_pci), PFN_DOWN(start));
-
-			/* Without saving 'last' we would gooble RAM too
-			 * at the end of the loop. */
-			last = end;
-			start_pci = end;
-			continue;
+					start_pfn, end_pfn);
+			}
+			start = end;
 		}
-		start_pci = min(start, start_pci);
-		last = end;
 	}
-	if (last > start_pci)
-		identity += set_phys_range_identity(
-					PFN_UP(start_pci), PFN_DOWN(last));
-	return identity;
+
+	printk(KERN_INFO "Released %lu pages of unused memory\n", released);
+	printk(KERN_INFO "Set %ld page(s) to 1-1 mapping\n", identity);
+
+	return released;
 }
 
 static unsigned long __init xen_get_max_pages(void)
@@ -191,27 +173,50 @@ static unsigned long __init xen_get_max_
 	domid_t domid = DOMID_SELF;
 	int ret;
 
-	ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
-	if (ret > 0)
-		max_pages = ret;
+	/*
+	 * For the initial domain we use the maximum reservation as
+	 * the maximum page.
+	 *
+	 * For guest domains the current maximum reservation reflects
+	 * the current maximum rather than the static maximum. In this
+	 * case the e820 map provided to us will cover the static
+	 * maximum region.
+	 */
+	if (xen_initial_domain()) {
+		ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
+		if (ret > 0)
+			max_pages = ret;
+	}
+
 	return min(max_pages, MAX_DOMAIN_PAGES);
 }
 
+static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
+{
+	u64 end = start + size;
+
+	/* Align RAM regions to page boundaries. */
+	if (type == E820_RAM) {
+		start = PAGE_ALIGN(start);
+		end &= ~((u64)PAGE_SIZE - 1);
+	}
+
+	e820_add_region(start, end - start, type);
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
 char * __init xen_memory_setup(void)
 {
 	static struct e820entry map[E820MAX] __initdata;
-	static struct e820entry map_raw[E820MAX] __initdata;
 
 	unsigned long max_pfn = xen_start_info->nr_pages;
 	unsigned long long mem_end;
 	int rc;
 	struct xen_memory_map memmap;
+	unsigned long max_pages;
 	unsigned long extra_pages = 0;
-	unsigned long extra_limit;
-	unsigned long identity_pages = 0;
 	int i;
 	int op;
 
@@ -237,58 +242,65 @@ char * __init xen_memory_setup(void)
 	}
 	BUG_ON(rc);
 
-	memcpy(map_raw, map, sizeof(map));
-	e820.nr_map = 0;
-	xen_extra_mem_start = mem_end;
-	for (i = 0; i < memmap.nr_entries; i++) {
-		unsigned long long end;
+	/* Make sure the Xen-supplied memory map is well-ordered. */
+	sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
-		/* Guard against non-page aligned E820 entries. */
-		if (map[i].type == E820_RAM)
-			map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
+	max_pages = xen_get_max_pages();
+	if (max_pages > max_pfn)
+		extra_pages += max_pages - max_pfn;
 
-		end = map[i].addr + map[i].size;
-		if (map[i].type == E820_RAM && end > mem_end) {
-			/* RAM off the end - may be partially included */
-			u64 delta = min(map[i].size, end - mem_end);
+	/*
+	 * Set P2M for all non-RAM pages and E820 gaps to be identity
+	 * type PFNs.  Any RAM pages that would be made inaccesible by
+	 * this are first released.
+	 */
+	xen_released_pages = xen_set_identity_and_release(
+		map, memmap.nr_entries, max_pfn);
+	extra_pages += xen_released_pages;
 
-			map[i].size -= delta;
-			end -= delta;
+	/*
+	 * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
+	 * factor the base size.  On non-highmem systems, the base
+	 * size is the full initial memory allocation; on highmem it
+	 * is limited to the max size of lowmem, so that it doesn't
+	 * get completely filled.
+	 *
+	 * In principle there could be a problem in lowmem systems if
+	 * the initial memory is also very large with respect to
+	 * lowmem, but we won't try to deal with that here.
+	 */
+	extra_pages = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
+			  extra_pages);
 
-			extra_pages += PFN_DOWN(delta);
-			/*
-			 * Set RAM below 4GB that is not for us to be unusable.
-			 * This prevents "System RAM" address space from being
-			 * used as potential resource for I/O address (happens
-			 * when 'allocate_resource' is called).
-			 */
-			if (delta &&
-				(xen_initial_domain() && end < 0x100000000ULL))
-				e820_add_region(end, delta, E820_UNUSABLE);
+	i = 0;
+	while (i < memmap.nr_entries) {
+		u64 addr = map[i].addr;
+		u64 size = map[i].size;
+		u32 type = map[i].type;
+
+		if (type == E820_RAM) {
+			if (addr < mem_end) {
+				size = min(size, mem_end - addr);
+			} else if (extra_pages) {
+				size = min(size, (u64)extra_pages * PAGE_SIZE);
+				extra_pages -= size / PAGE_SIZE;
+				xen_add_extra_mem(addr, size);
+			} else
+				type = E820_UNUSABLE;
 		}
 
-		if (map[i].size > 0 && end > xen_extra_mem_start)
-			xen_extra_mem_start = end;
+		xen_align_and_add_e820_region(addr, size, type);
 
-		/* Add region if any remains */
-		if (map[i].size > 0)
-			e820_add_region(map[i].addr, map[i].size, map[i].type);
+		map[i].addr += size;
+		map[i].size -= size;
+		if (map[i].size == 0)
+			i++;
 	}
-	/* Align the balloon area so that max_low_pfn does not get set
-	 * to be at the _end_ of the PCI gap at the far end (fee01000).
-	 * Note that xen_extra_mem_start gets set in the loop above to be
-	 * past the last E820 region. */
-	if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32)))
-		xen_extra_mem_start = (1ULL<<32);
 
 	/*
 	 * In domU, the ISA region is normal, usable memory, but we
 	 * reserve ISA memory anyway because too many things poke
 	 * about in there.
-	 *
-	 * In Dom0, the host E820 information can leave gaps in the
-	 * ISA range, which would cause us to release those pages.  To
-	 * avoid this, we unconditionally reserve them here.
 	 */
 	e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
 			E820_RESERVED);
@@ -305,44 +317,6 @@ char * __init xen_memory_setup(void)
 
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
-	extra_limit = xen_get_max_pages();
-	if (max_pfn + extra_pages > extra_limit) {
-		if (extra_limit > max_pfn)
-			extra_pages = extra_limit - max_pfn;
-		else
-			extra_pages = 0;
-	}
-
-	extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
-
-	/*
-	 * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
-	 * factor the base size.  On non-highmem systems, the base
-	 * size is the full initial memory allocation; on highmem it
-	 * is limited to the max size of lowmem, so that it doesn't
-	 * get completely filled.
-	 *
-	 * In principle there could be a problem in lowmem systems if
-	 * the initial memory is also very large with respect to
-	 * lowmem, but we won't try to deal with that here.
-	 */
-	extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
-			  max_pfn + extra_pages);
-
-	if (extra_limit >= max_pfn)
-		extra_pages = extra_limit - max_pfn;
-	else
-		extra_pages = 0;
-
-	xen_add_extra_mem(extra_pages);
-
-	/*
-	 * Set P2M for all non-RAM pages and E820 gaps to be identity
-	 * type PFNs. We supply it with the non-sanitized version
-	 * of the E820.
-	 */
-	identity_pages = xen_set_identity(map_raw, memmap.nr_entries);
-	printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
 	return "Xen";
 }
 
@@ -448,6 +422,6 @@ void __init xen_arch_setup(void)
 #endif
 	disable_cpuidle();
 	boot_option_idle_override = IDLE_HALT;
-
+	WARN_ON(set_pm_idle_to_default());
 	fiddle_vdso();
 }
diff -druNp linux-libre-3.1-gnu1/arch/x86/xen/time.c linux-libre-3.2-gnu1/arch/x86/xen/time.c
--- linux-libre-3.1-gnu1/arch/x86/xen/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/x86/xen/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,8 +201,22 @@ static unsigned long xen_get_wallclock(v
 
 static int xen_set_wallclock(unsigned long now)
 {
+	struct xen_platform_op op;
+	int rc;
+
 	/* do nothing for domU */
-	return -1;
+	if (!xen_initial_domain())
+		return -1;
+
+	op.cmd = XENPF_settime;
+	op.u.settime.secs = now;
+	op.u.settime.nsecs = 0;
+	op.u.settime.system_time = xen_clocksource_read();
+
+	rc = HYPERVISOR_dom0_op(&op);
+	WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now);
+
+	return rc;
 }
 
 static struct clocksource xen_clocksource __read_mostly = {
diff -druNp linux-libre-3.1-gnu1/arch/xtensa/configs/iss_defconfig linux-libre-3.2-gnu1/arch/xtensa/configs/iss_defconfig
--- linux-libre-3.1-gnu1/arch/xtensa/configs/iss_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/xtensa/configs/iss_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
 CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_CONSTRUCTORS=y
 
diff -druNp linux-libre-3.1-gnu1/arch/xtensa/configs/s6105_defconfig linux-libre-3.2-gnu1/arch/xtensa/configs/s6105_defconfig
--- linux-libre-3.1-gnu1/arch/xtensa/configs/s6105_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/xtensa/configs/s6105_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
 CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
diff -druNp linux-libre-3.1-gnu1/arch/xtensa/platforms/iss/network.c linux-libre-3.2-gnu1/arch/xtensa/platforms/iss/network.c
--- linux-libre-3.1-gnu1/arch/xtensa/platforms/iss/network.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/arch/xtensa/platforms/iss/network.c	2012-01-04 18:55:44.000000000 -0500
@@ -633,7 +633,7 @@ static const struct net_device_ops iss_n
 	.ndo_set_mac_address	= iss_net_set_mac,
 	//.ndo_do_ioctl		= iss_net_ioctl,
 	.ndo_tx_timeout		= iss_net_tx_timeout,
-	.ndo_set_multicast_list = iss_net_set_multicast_list,
+	.ndo_set_rx_mode	= iss_net_set_multicast_list,
 };
 
 static int iss_net_configure(int index, char *init)
diff -druNp linux-libre-3.1-gnu1/block/blk-cgroup.c linux-libre-3.2-gnu1/block/blk-cgroup.c
--- linux-libre-3.1-gnu1/block/blk-cgroup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-cgroup.c	2012-01-04 18:55:44.000000000 -0500
@@ -768,25 +768,14 @@ static uint64_t blkio_get_stat(struct bl
 	return disk_total;
 }
 
-static int blkio_check_dev_num(dev_t dev)
-{
-	int part = 0;
-	struct gendisk *disk;
-
-	disk = get_gendisk(dev, &part);
-	if (!disk || part)
-		return -ENODEV;
-
-	return 0;
-}
-
 static int blkio_policy_parse_and_set(char *buf,
 	struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
 {
+	struct gendisk *disk = NULL;
 	char *s[4], *p, *major_s = NULL, *minor_s = NULL;
-	int ret;
 	unsigned long major, minor;
-	int i = 0;
+	int i = 0, ret = -EINVAL;
+	int part;
 	dev_t dev;
 	u64 temp;
 
@@ -804,37 +793,36 @@ static int blkio_policy_parse_and_set(ch
 	}
 
 	if (i != 2)
-		return -EINVAL;
+		goto out;
 
 	p = strsep(&s[0], ":");
 	if (p != NULL)
 		major_s = p;
 	else
-		return -EINVAL;
+		goto out;
 
 	minor_s = s[0];
 	if (!minor_s)
-		return -EINVAL;
+		goto out;
 
-	ret = strict_strtoul(major_s, 10, &major);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoul(major_s, 10, &major))
+		goto out;
 
-	ret = strict_strtoul(minor_s, 10, &minor);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoul(minor_s, 10, &minor))
+		goto out;
 
 	dev = MKDEV(major, minor);
 
-	ret = strict_strtoull(s[1], 10, &temp);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoull(s[1], 10, &temp))
+		goto out;
 
 	/* For rule removal, do not check for device presence. */
 	if (temp) {
-		ret = blkio_check_dev_num(dev);
-		if (ret)
-			return ret;
+		disk = get_gendisk(dev, &part);
+		if (!disk || part) {
+			ret = -ENODEV;
+			goto out;
+		}
 	}
 
 	newpn->dev = dev;
@@ -843,7 +831,7 @@ static int blkio_policy_parse_and_set(ch
 	case BLKIO_POLICY_PROP:
 		if ((temp < BLKIO_WEIGHT_MIN && temp > 0) ||
 		     temp > BLKIO_WEIGHT_MAX)
-			return -EINVAL;
+			goto out;
 
 		newpn->plid = plid;
 		newpn->fileid = fileid;
@@ -860,7 +848,7 @@ static int blkio_policy_parse_and_set(ch
 		case BLKIO_THROTL_read_iops_device:
 		case BLKIO_THROTL_write_iops_device:
 			if (temp > THROTL_IOPS_MAX)
-				return -EINVAL;
+				goto out;
 
 			newpn->plid = plid;
 			newpn->fileid = fileid;
@@ -871,68 +859,96 @@ static int blkio_policy_parse_and_set(ch
 	default:
 		BUG();
 	}
-
-	return 0;
+	ret = 0;
+out:
+	put_disk(disk);
+	return ret;
 }
 
 unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
 			      dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int weight;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
 				BLKIO_PROP_weight_device);
 	if (pn)
-		return pn->val.weight;
+		weight = pn->val.weight;
 	else
-		return blkcg->weight;
+		weight = blkcg->weight;
+
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return weight;
 }
 EXPORT_SYMBOL_GPL(blkcg_get_weight);
 
 uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	uint64_t bps = -1;
 
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_read_bps_device);
 	if (pn)
-		return pn->val.bps;
-	else
-		return -1;
+		bps = pn->val.bps;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return bps;
 }
 
 uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	uint64_t bps = -1;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_write_bps_device);
 	if (pn)
-		return pn->val.bps;
-	else
-		return -1;
+		bps = pn->val.bps;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return bps;
 }
 
 unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int iops = -1;
 
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_read_iops_device);
 	if (pn)
-		return pn->val.iops;
-	else
-		return -1;
+		iops = pn->val.iops;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return iops;
 }
 
 unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int iops = -1;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_write_iops_device);
 	if (pn)
-		return pn->val.iops;
-	else
-		return -1;
+		iops = pn->val.iops;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return iops;
 }
 
 /* Checks whether user asked for deleting a policy rule */
@@ -1085,6 +1101,7 @@ static int blkiocg_file_write(struct cgr
 
 	if (blkio_delete_rule_command(newpn)) {
 		blkio_policy_delete_node(pn);
+		kfree(pn);
 		spin_unlock_irq(&blkcg->lock);
 		goto update_io_group;
 	}
diff -druNp linux-libre-3.1-gnu1/block/blk-cgroup.h linux-libre-3.2-gnu1/block/blk-cgroup.h
--- linux-libre-3.1-gnu1/block/blk-cgroup.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-cgroup.h	2012-01-04 18:55:44.000000000 -0500
@@ -188,7 +188,7 @@ struct blkio_policy_node {
 	union {
 		unsigned int weight;
 		/*
-		 * Rate read/write in terms of byptes per second
+		 * Rate read/write in terms of bytes per second
 		 * Whether this rate represents read or write is determined
 		 * by file type "fileid".
 		 */
diff -druNp linux-libre-3.1-gnu1/block/blk-core.c linux-libre-3.2-gnu1/block/blk-core.c
--- linux-libre-3.1-gnu1/block/blk-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/fault-inject.h>
 #include <linux/list_sort.h>
+#include <linux/delay.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -38,8 +39,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_r
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
-static int __make_request(struct request_queue *q, struct bio *bio);
-
 /*
  * For the allocated request tables
  */
@@ -347,30 +346,87 @@ void blk_put_queue(struct request_queue
 }
 EXPORT_SYMBOL(blk_put_queue);
 
-/*
- * Note: If a driver supplied the queue lock, it is disconnected
- * by this function. The actual state of the lock doesn't matter
- * here as the request_queue isn't accessible after this point
- * (QUEUE_FLAG_DEAD is set) and no other requests will be queued.
+/**
+ * blk_drain_queue - drain requests from request_queue
+ * @q: queue to drain
+ * @drain_all: whether to drain all requests or only the ones w/ ELVPRIV
+ *
+ * Drain requests from @q.  If @drain_all is set, all requests are drained.
+ * If not, only ELVPRIV requests are drained.  The caller is responsible
+ * for ensuring that no new requests which need to be drained are queued.
+ */
+void blk_drain_queue(struct request_queue *q, bool drain_all)
+{
+	while (true) {
+		int nr_rqs;
+
+		spin_lock_irq(q->queue_lock);
+
+		elv_drain_elevator(q);
+		if (drain_all)
+			blk_throtl_drain(q);
+
+		/*
+		 * This function might be called on a queue which failed
+		 * driver init after queue creation.  Some drivers
+		 * (e.g. fd) get unhappy in such cases.  Kick queue iff
+		 * dispatch queue has something on it.
+		 */
+		if (!list_empty(&q->queue_head))
+			__blk_run_queue(q);
+
+		if (drain_all)
+			nr_rqs = q->rq.count[0] + q->rq.count[1];
+		else
+			nr_rqs = q->rq.elvpriv;
+
+		spin_unlock_irq(q->queue_lock);
+
+		if (!nr_rqs)
+			break;
+		msleep(10);
+	}
+}
+
+/**
+ * blk_cleanup_queue - shutdown a request queue
+ * @q: request queue to shutdown
+ *
+ * Mark @q DEAD, drain all pending requests, destroy and put it.  All
+ * future requests will be failed immediately with -ENODEV.
  */
 void blk_cleanup_queue(struct request_queue *q)
 {
-	/*
-	 * We know we have process context here, so we can be a little
-	 * cautious and ensure that pending block actions on this device
-	 * are done before moving on. Going into this function, we should
-	 * not have processes doing IO to this device.
-	 */
-	blk_sync_queue(q);
+	spinlock_t *lock = q->queue_lock;
 
-	del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+	/* mark @q DEAD, no new request or merges will be allowed afterwards */
 	mutex_lock(&q->sysfs_lock);
 	queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
-	mutex_unlock(&q->sysfs_lock);
+
+	spin_lock_irq(lock);
+	queue_flag_set(QUEUE_FLAG_NOMERGES, q);
+	queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+	queue_flag_set(QUEUE_FLAG_DEAD, q);
 
 	if (q->queue_lock != &q->__queue_lock)
 		q->queue_lock = &q->__queue_lock;
 
+	spin_unlock_irq(lock);
+	mutex_unlock(&q->sysfs_lock);
+
+	/*
+	 * Drain all requests queued before DEAD marking.  The caller might
+	 * be trying to tear down @q before its elevator is initialized, in
+	 * which case we don't want to call into draining.
+	 */
+	if (q->elevator)
+		blk_drain_queue(q, true);
+
+	/* @q won't process any more request, flush async actions */
+	del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+	blk_sync_queue(q);
+
+	/* @q is and will stay empty, shutdown and put */
 	blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
@@ -418,6 +474,7 @@ struct request_queue *blk_alloc_queue_no
 	q->backing_dev_info.state = 0;
 	q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
 	q->backing_dev_info.name = "block";
+	q->node = node_id;
 
 	err = bdi_init(&q->backing_dev_info);
 	if (err) {
@@ -502,7 +559,7 @@ blk_init_queue_node(request_fn_proc *rfn
 	if (!uninit_q)
 		return NULL;
 
-	q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id);
+	q = blk_init_allocated_queue(uninit_q, rfn, lock);
 	if (!q)
 		blk_cleanup_queue(uninit_q);
 
@@ -514,18 +571,9 @@ struct request_queue *
 blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
 			 spinlock_t *lock)
 {
-	return blk_init_allocated_queue_node(q, rfn, lock, -1);
-}
-EXPORT_SYMBOL(blk_init_allocated_queue);
-
-struct request_queue *
-blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
-			      spinlock_t *lock, int node_id)
-{
 	if (!q)
 		return NULL;
 
-	q->node = node_id;
 	if (blk_init_free_list(q))
 		return NULL;
 
@@ -541,7 +589,7 @@ blk_init_allocated_queue_node(struct req
 	/*
 	 * This also sets hw/phys segments, boundary and size
 	 */
-	blk_queue_make_request(q, __make_request);
+	blk_queue_make_request(q, blk_queue_bio);
 
 	q->sg_reserved_size = INT_MAX;
 
@@ -555,7 +603,7 @@ blk_init_allocated_queue_node(struct req
 
 	return NULL;
 }
-EXPORT_SYMBOL(blk_init_allocated_queue_node);
+EXPORT_SYMBOL(blk_init_allocated_queue);
 
 int blk_get_queue(struct request_queue *q)
 {
@@ -576,7 +624,7 @@ static inline void blk_free_request(stru
 }
 
 static struct request *
-blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
+blk_alloc_request(struct request_queue *q, unsigned int flags, gfp_t gfp_mask)
 {
 	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -587,12 +635,10 @@ blk_alloc_request(struct request_queue *
 
 	rq->cmd_flags = flags | REQ_ALLOCED;
 
-	if (priv) {
-		if (unlikely(elv_set_request(q, rq, gfp_mask))) {
-			mempool_free(rq, q->rq.rq_pool);
-			return NULL;
-		}
-		rq->cmd_flags |= REQ_ELVPRIV;
+	if ((flags & REQ_ELVPRIV) &&
+	    unlikely(elv_set_request(q, rq, gfp_mask))) {
+		mempool_free(rq, q->rq.rq_pool);
+		return NULL;
 	}
 
 	return rq;
@@ -651,12 +697,13 @@ static void __freed_request(struct reque
  * A request has just been released.  Account for it, update the full and
  * congestion status, wake up any waiters.   Called under q->queue_lock.
  */
-static void freed_request(struct request_queue *q, int sync, int priv)
+static void freed_request(struct request_queue *q, unsigned int flags)
 {
 	struct request_list *rl = &q->rq;
+	int sync = rw_is_sync(flags);
 
 	rl->count[sync]--;
-	if (priv)
+	if (flags & REQ_ELVPRIV)
 		rl->elvpriv--;
 
 	__freed_request(q, sync);
@@ -684,10 +731,19 @@ static bool blk_rq_should_init_elevator(
 	return true;
 }
 
-/*
- * Get a free request, queue_lock must be held.
- * Returns NULL on failure, with queue_lock held.
- * Returns !NULL on success, with queue_lock *not held*.
+/**
+ * get_request - get a free request
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
+ * @gfp_mask: allocation mask
+ *
+ * Get a free request from @q.  This function may fail under memory
+ * pressure or if @q is dead.
+ *
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request(struct request_queue *q, int rw_flags,
 				   struct bio *bio, gfp_t gfp_mask)
@@ -696,7 +752,10 @@ static struct request *get_request(struc
 	struct request_list *rl = &q->rq;
 	struct io_context *ioc = NULL;
 	const bool is_sync = rw_is_sync(rw_flags) != 0;
-	int may_queue, priv = 0;
+	int may_queue;
+
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+		return NULL;
 
 	may_queue = elv_may_queue(q, rw_flags);
 	if (may_queue == ELV_MQUEUE_NO)
@@ -740,17 +799,17 @@ static struct request *get_request(struc
 	rl->count[is_sync]++;
 	rl->starved[is_sync] = 0;
 
-	if (blk_rq_should_init_elevator(bio)) {
-		priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-		if (priv)
-			rl->elvpriv++;
+	if (blk_rq_should_init_elevator(bio) &&
+	    !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags)) {
+		rw_flags |= REQ_ELVPRIV;
+		rl->elvpriv++;
 	}
 
 	if (blk_queue_io_stat(q))
 		rw_flags |= REQ_IO_STAT;
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
+	rq = blk_alloc_request(q, rw_flags, gfp_mask);
 	if (unlikely(!rq)) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
@@ -760,7 +819,7 @@ static struct request *get_request(struc
 		 * wait queue, but this is pretty rare.
 		 */
 		spin_lock_irq(q->queue_lock);
-		freed_request(q, is_sync, priv);
+		freed_request(q, rw_flags);
 
 		/*
 		 * in the very unlikely event that allocation failed and no
@@ -790,11 +849,18 @@ out:
 	return rq;
 }
 
-/*
- * No available requests for this queue, wait for some requests to become
- * available.
+/**
+ * get_request_wait - get a free request with retry
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
  *
- * Called with q->queue_lock held, and returns with it unlocked.
+ * Get a free request from @q.  This function keeps retrying under memory
+ * pressure and fails iff @q is dead.
+ *
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 					struct bio *bio)
@@ -808,6 +874,9 @@ static struct request *get_request_wait(
 		struct io_context *ioc;
 		struct request_list *rl = &q->rq;
 
+		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+			return NULL;
+
 		prepare_to_wait_exclusive(&rl->wait[is_sync], &wait,
 				TASK_UNINTERRUPTIBLE);
 
@@ -838,19 +907,15 @@ struct request *blk_get_request(struct r
 {
 	struct request *rq;
 
-	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-		return NULL;
-
 	BUG_ON(rw != READ && rw != WRITE);
 
 	spin_lock_irq(q->queue_lock);
-	if (gfp_mask & __GFP_WAIT) {
+	if (gfp_mask & __GFP_WAIT)
 		rq = get_request_wait(q, rw, NULL);
-	} else {
+	else
 		rq = get_request(q, rw, NULL, gfp_mask);
-		if (!rq)
-			spin_unlock_irq(q->queue_lock);
-	}
+	if (!rq)
+		spin_unlock_irq(q->queue_lock);
 	/* q->queue_lock is unlocked at this point */
 
 	return rq;
@@ -1052,14 +1117,13 @@ void __blk_put_request(struct request_qu
 	 * it didn't come out of our reserved rq pools
 	 */
 	if (req->cmd_flags & REQ_ALLOCED) {
-		int is_sync = rq_is_sync(req) != 0;
-		int priv = req->cmd_flags & REQ_ELVPRIV;
+		unsigned int flags = req->cmd_flags;
 
 		BUG_ON(!list_empty(&req->queuelist));
 		BUG_ON(!hlist_unhashed(&req->hash));
 
 		blk_free_request(q, req);
-		freed_request(q, is_sync, priv);
+		freed_request(q, flags);
 	}
 }
 EXPORT_SYMBOL_GPL(__blk_put_request);
@@ -1161,18 +1225,32 @@ static bool bio_attempt_front_merge(stru
 	return true;
 }
 
-/*
- * Attempts to merge with the plugged list in the current process. Returns
- * true if merge was successful, otherwise false.
+/**
+ * attempt_plug_merge - try to merge with %current's plugged list
+ * @q: request_queue new bio is being queued at
+ * @bio: new bio being queued
+ * @request_count: out parameter for number of traversed plugged requests
+ *
+ * Determine whether @bio being queued on @q can be merged with a request
+ * on %current's plugged list.  Returns %true if merge was successful,
+ * otherwise %false.
+ *
+ * This function is called without @q->queue_lock; however, elevator is
+ * accessed iff there already are requests on the plugged list which in
+ * turn guarantees validity of the elevator.
+ *
+ * Note that, on successful merge, elevator operation
+ * elevator_bio_merged_fn() will be called without queue lock.  Elevator
+ * must be ready for this.
  */
-static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q,
-			       struct bio *bio, unsigned int *request_count)
+static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
+			       unsigned int *request_count)
 {
 	struct blk_plug *plug;
 	struct request *rq;
 	bool ret = false;
 
-	plug = tsk->plug;
+	plug = current->plug;
 	if (!plug)
 		goto out;
 	*request_count = 0;
@@ -1202,7 +1280,6 @@ out:
 
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
-	req->cpu = bio->bi_comp_cpu;
 	req->cmd_type = REQ_TYPE_FS;
 
 	req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK;
@@ -1215,7 +1292,7 @@ void init_request_from_bio(struct reques
 	blk_rq_bio_prep(req->q, req, bio);
 }
 
-static int __make_request(struct request_queue *q, struct bio *bio)
+void blk_queue_bio(struct request_queue *q, struct bio *bio)
 {
 	const bool sync = !!(bio->bi_rw & REQ_SYNC);
 	struct blk_plug *plug;
@@ -1240,8 +1317,8 @@ static int __make_request(struct request
 	 * Check if we can merge with the plugged list before grabbing
 	 * any locks.
 	 */
-	if (attempt_plug_merge(current, q, bio, &request_count))
-		goto out;
+	if (attempt_plug_merge(q, bio, &request_count))
+		return;
 
 	spin_lock_irq(q->queue_lock);
 
@@ -1275,6 +1352,10 @@ get_rq:
 	 * Returns with the queue unlocked.
 	 */
 	req = get_request_wait(q, rw_flags, bio);
+	if (unlikely(!req)) {
+		bio_endio(bio, -ENODEV);	/* @q is dead */
+		goto out_unlock;
+	}
 
 	/*
 	 * After dropping the lock and possibly sleeping here, our request
@@ -1284,8 +1365,7 @@ get_rq:
 	 */
 	init_request_from_bio(req, bio);
 
-	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
-	    bio_flagged(bio, BIO_CPU_AFFINE))
+	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
 		req->cpu = raw_smp_processor_id();
 
 	plug = current->plug;
@@ -1298,15 +1378,19 @@ get_rq:
 		 */
 		if (list_empty(&plug->list))
 			trace_block_plug(q);
-		else if (!plug->should_sort) {
-			struct request *__rq;
+		else {
+			if (!plug->should_sort) {
+				struct request *__rq;
 
-			__rq = list_entry_rq(plug->list.prev);
-			if (__rq->q != q)
-				plug->should_sort = 1;
+				__rq = list_entry_rq(plug->list.prev);
+				if (__rq->q != q)
+					plug->should_sort = 1;
+			}
+			if (request_count >= BLK_MAX_REQUEST_COUNT) {
+				blk_flush_plug_list(plug, false);
+				trace_block_plug(q);
+			}
 		}
-		if (request_count >= BLK_MAX_REQUEST_COUNT)
-			blk_flush_plug_list(plug, false);
 		list_add_tail(&req->queuelist, &plug->list);
 		drive_stat_acct(req, 1);
 	} else {
@@ -1316,9 +1400,8 @@ get_rq:
 out_unlock:
 		spin_unlock_irq(q->queue_lock);
 	}
-out:
-	return 0;
 }
+EXPORT_SYMBOL_GPL(blk_queue_bio);	/* for device mapper only */
 
 /*
  * If bio->bi_dev is a partition, remap the location
@@ -1417,165 +1500,135 @@ static inline int bio_check_eod(struct b
 	return 0;
 }
 
-/**
- * generic_make_request - hand a buffer to its device driver for I/O
- * @bio:  The bio describing the location in memory and on the device.
- *
- * generic_make_request() is used to make I/O requests of block
- * devices. It is passed a &struct bio, which describes the I/O that needs
- * to be done.
- *
- * generic_make_request() does not return any status.  The
- * success/failure status of the request, along with notification of
- * completion, is delivered asynchronously through the bio->bi_end_io
- * function described (one day) else where.
- *
- * The caller of generic_make_request must make sure that bi_io_vec
- * are set to describe the memory buffer, and that bi_dev and bi_sector are
- * set to describe the device address, and the
- * bi_end_io and optionally bi_private are set to describe how
- * completion notification should be signaled.
- *
- * generic_make_request and the drivers it calls may use bi_next if this
- * bio happens to be merged with someone else, and may change bi_dev and
- * bi_sector for remaps as it sees fit.  So the values of these fields
- * should NOT be depended on after the call to generic_make_request.
- */
-static inline void __generic_make_request(struct bio *bio)
+static noinline_for_stack bool
+generic_make_request_checks(struct bio *bio)
 {
 	struct request_queue *q;
-	sector_t old_sector;
-	int ret, nr_sectors = bio_sectors(bio);
-	dev_t old_dev;
+	int nr_sectors = bio_sectors(bio);
 	int err = -EIO;
+	char b[BDEVNAME_SIZE];
+	struct hd_struct *part;
 
 	might_sleep();
 
 	if (bio_check_eod(bio, nr_sectors))
 		goto end_io;
 
-	/*
-	 * Resolve the mapping until finished. (drivers are
-	 * still free to implement/resolve their own stacking
-	 * by explicitly returning 0)
-	 *
-	 * NOTE: we don't repeat the blk_size check for each new device.
-	 * Stacking drivers are expected to know what they are doing.
-	 */
-	old_sector = -1;
-	old_dev = 0;
-	do {
-		char b[BDEVNAME_SIZE];
-		struct hd_struct *part;
-
-		q = bdev_get_queue(bio->bi_bdev);
-		if (unlikely(!q)) {
-			printk(KERN_ERR
-			       "generic_make_request: Trying to access "
-				"nonexistent block-device %s (%Lu)\n",
-				bdevname(bio->bi_bdev, b),
-				(long long) bio->bi_sector);
-			goto end_io;
-		}
-
-		if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
-			     nr_sectors > queue_max_hw_sectors(q))) {
-			printk(KERN_ERR "bio too big device %s (%u > %u)\n",
-			       bdevname(bio->bi_bdev, b),
-			       bio_sectors(bio),
-			       queue_max_hw_sectors(q));
-			goto end_io;
-		}
-
-		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-			goto end_io;
-
-		part = bio->bi_bdev->bd_part;
-		if (should_fail_request(part, bio->bi_size) ||
-		    should_fail_request(&part_to_disk(part)->part0,
-					bio->bi_size))
-			goto end_io;
-
-		/*
-		 * If this device has partitions, remap block n
-		 * of partition p to block n+start(p) of the disk.
-		 */
-		blk_partition_remap(bio);
+	q = bdev_get_queue(bio->bi_bdev);
+	if (unlikely(!q)) {
+		printk(KERN_ERR
+		       "generic_make_request: Trying to access "
+			"nonexistent block-device %s (%Lu)\n",
+			bdevname(bio->bi_bdev, b),
+			(long long) bio->bi_sector);
+		goto end_io;
+	}
 
-		if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
-			goto end_io;
+	if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
+		     nr_sectors > queue_max_hw_sectors(q))) {
+		printk(KERN_ERR "bio too big device %s (%u > %u)\n",
+		       bdevname(bio->bi_bdev, b),
+		       bio_sectors(bio),
+		       queue_max_hw_sectors(q));
+		goto end_io;
+	}
 
-		if (old_sector != -1)
-			trace_block_bio_remap(q, bio, old_dev, old_sector);
+	part = bio->bi_bdev->bd_part;
+	if (should_fail_request(part, bio->bi_size) ||
+	    should_fail_request(&part_to_disk(part)->part0,
+				bio->bi_size))
+		goto end_io;
 
-		old_sector = bio->bi_sector;
-		old_dev = bio->bi_bdev->bd_dev;
+	/*
+	 * If this device has partitions, remap block n
+	 * of partition p to block n+start(p) of the disk.
+	 */
+	blk_partition_remap(bio);
 
-		if (bio_check_eod(bio, nr_sectors))
-			goto end_io;
+	if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
+		goto end_io;
 
-		/*
-		 * Filter flush bio's early so that make_request based
-		 * drivers without flush support don't have to worry
-		 * about them.
-		 */
-		if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
-			bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
-			if (!nr_sectors) {
-				err = 0;
-				goto end_io;
-			}
-		}
+	if (bio_check_eod(bio, nr_sectors))
+		goto end_io;
 
-		if ((bio->bi_rw & REQ_DISCARD) &&
-		    (!blk_queue_discard(q) ||
-		     ((bio->bi_rw & REQ_SECURE) &&
-		      !blk_queue_secdiscard(q)))) {
-			err = -EOPNOTSUPP;
+	/*
+	 * Filter flush bio's early so that make_request based
+	 * drivers without flush support don't have to worry
+	 * about them.
+	 */
+	if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+		bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+		if (!nr_sectors) {
+			err = 0;
 			goto end_io;
 		}
+	}
 
-		if (blk_throtl_bio(q, &bio))
-			goto end_io;
-
-		/*
-		 * If bio = NULL, bio has been throttled and will be submitted
-		 * later.
-		 */
-		if (!bio)
-			break;
-
-		trace_block_bio_queue(q, bio);
+	if ((bio->bi_rw & REQ_DISCARD) &&
+	    (!blk_queue_discard(q) ||
+	     ((bio->bi_rw & REQ_SECURE) &&
+	      !blk_queue_secdiscard(q)))) {
+		err = -EOPNOTSUPP;
+		goto end_io;
+	}
 
-		ret = q->make_request_fn(q, bio);
-	} while (ret);
+	if (blk_throtl_bio(q, bio))
+		return false;	/* throttled, will be resubmitted later */
 
-	return;
+	trace_block_bio_queue(q, bio);
+	return true;
 
 end_io:
 	bio_endio(bio, err);
+	return false;
 }
 
-/*
- * We only want one ->make_request_fn to be active at a time,
- * else stack usage with stacked devices could be a problem.
- * So use current->bio_list to keep a list of requests
- * submited by a make_request_fn function.
- * current->bio_list is also used as a flag to say if
- * generic_make_request is currently active in this task or not.
- * If it is NULL, then no make_request is active.  If it is non-NULL,
- * then a make_request is active, and new requests should be added
- * at the tail
+/**
+ * generic_make_request - hand a buffer to its device driver for I/O
+ * @bio:  The bio describing the location in memory and on the device.
+ *
+ * generic_make_request() is used to make I/O requests of block
+ * devices. It is passed a &struct bio, which describes the I/O that needs
+ * to be done.
+ *
+ * generic_make_request() does not return any status.  The
+ * success/failure status of the request, along with notification of
+ * completion, is delivered asynchronously through the bio->bi_end_io
+ * function described (one day) else where.
+ *
+ * The caller of generic_make_request must make sure that bi_io_vec
+ * are set to describe the memory buffer, and that bi_dev and bi_sector are
+ * set to describe the device address, and the
+ * bi_end_io and optionally bi_private are set to describe how
+ * completion notification should be signaled.
+ *
+ * generic_make_request and the drivers it calls may use bi_next if this
+ * bio happens to be merged with someone else, and may resubmit the bio to
+ * a lower device by calling into generic_make_request recursively, which
+ * means the bio should NOT be touched after the call to ->make_request_fn.
  */
 void generic_make_request(struct bio *bio)
 {
 	struct bio_list bio_list_on_stack;
 
+	if (!generic_make_request_checks(bio))
+		return;
+
+	/*
+	 * We only want one ->make_request_fn to be active at a time, else
+	 * stack usage with stacked devices could be a problem.  So use
+	 * current->bio_list to keep a list of requests submited by a
+	 * make_request_fn function.  current->bio_list is also used as a
+	 * flag to say if generic_make_request is currently active in this
+	 * task or not.  If it is NULL, then no make_request is active.  If
+	 * it is non-NULL, then a make_request is active, and new requests
+	 * should be added at the tail
+	 */
 	if (current->bio_list) {
-		/* make_request is active */
 		bio_list_add(current->bio_list, bio);
 		return;
 	}
+
 	/* following loop may be a bit non-obvious, and so deserves some
 	 * explanation.
 	 * Before entering the loop, bio->bi_next is NULL (as all callers
@@ -1583,22 +1636,21 @@ void generic_make_request(struct bio *bi
 	 * We pretend that we have just taken it off a longer list, so
 	 * we assign bio_list to a pointer to the bio_list_on_stack,
 	 * thus initialising the bio_list of new bios to be
-	 * added.  __generic_make_request may indeed add some more bios
+	 * added.  ->make_request() may indeed add some more bios
 	 * through a recursive call to generic_make_request.  If it
 	 * did, we find a non-NULL value in bio_list and re-enter the loop
 	 * from the top.  In this case we really did just take the bio
 	 * of the top of the list (no pretending) and so remove it from
-	 * bio_list, and call into __generic_make_request again.
-	 *
-	 * The loop was structured like this to make only one call to
-	 * __generic_make_request (which is important as it is large and
-	 * inlined) and to keep the structure simple.
+	 * bio_list, and call into ->make_request() again.
 	 */
 	BUG_ON(bio->bi_next);
 	bio_list_init(&bio_list_on_stack);
 	current->bio_list = &bio_list_on_stack;
 	do {
-		__generic_make_request(bio);
+		struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+
+		q->make_request_fn(q, bio);
+
 		bio = bio_list_pop(current->bio_list);
 	} while (bio);
 	current->bio_list = NULL; /* deactivate */
@@ -1725,6 +1777,8 @@ int blk_insert_cloned_request(struct req
 		where = ELEVATOR_INSERT_FLUSH;
 
 	add_acct_request(q, rq, where);
+	if (where == ELEVATOR_INSERT_FLUSH)
+		__blk_run_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	return 0;
@@ -2628,6 +2682,20 @@ EXPORT_SYMBOL(kblockd_schedule_delayed_w
 
 #define PLUG_MAGIC	0x91827364
 
+/**
+ * blk_start_plug - initialize blk_plug and track it inside the task_struct
+ * @plug:	The &struct blk_plug that needs to be initialized
+ *
+ * Description:
+ *   Tracking blk_plug inside the task_struct will help with auto-flushing the
+ *   pending I/O should the task end up blocking between blk_start_plug() and
+ *   blk_finish_plug(). This is important from a performance perspective, but
+ *   also ensures that we don't deadlock. For instance, if the task is blocking
+ *   for a memory allocation, memory reclaim could end up wanting to free a
+ *   page belonging to that request that is currently residing in our private
+ *   plug. By flushing the pending I/O when the process goes to sleep, we avoid
+ *   this kind of deadlock.
+ */
 void blk_start_plug(struct blk_plug *plug)
 {
 	struct task_struct *tsk = current;
diff -druNp linux-libre-3.1-gnu1/block/blk-flush.c linux-libre-3.2-gnu1/block/blk-flush.c
--- linux-libre-3.1-gnu1/block/blk-flush.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-flush.c	2012-01-04 18:55:44.000000000 -0500
@@ -320,7 +320,7 @@ void blk_insert_flush(struct request *rq
 		return;
 	}
 
-	BUG_ON(!rq->bio || rq->bio != rq->biotail);
+	BUG_ON(rq->bio != rq->biotail); /*assumes zero or single bio rq */
 
 	/*
 	 * If there's data but flush is not necessary, the request can be
@@ -330,7 +330,6 @@ void blk_insert_flush(struct request *rq
 	if ((policy & REQ_FSEQ_DATA) &&
 	    !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
 		list_add_tail(&rq->queuelist, &q->queue_head);
-		blk_run_queue_async(q);
 		return;
 	}
 
diff -druNp linux-libre-3.1-gnu1/block/blk.h linux-libre-3.2-gnu1/block/blk.h
--- linux-libre-3.1-gnu1/block/blk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@ void blk_rq_bio_prep(struct request_queu
 			struct bio *bio);
 int blk_rq_append_bio(struct request_queue *q, struct request *rq,
 		      struct bio *bio);
+void blk_drain_queue(struct request_queue *q, bool drain_all);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 bool __blk_end_bidi_request(struct request *rq, int error,
@@ -188,4 +189,21 @@ static inline int blk_do_io_stat(struct
 	        (rq->cmd_flags & REQ_DISCARD));
 }
 
-#endif
+#ifdef CONFIG_BLK_DEV_THROTTLING
+extern bool blk_throtl_bio(struct request_queue *q, struct bio *bio);
+extern void blk_throtl_drain(struct request_queue *q);
+extern int blk_throtl_init(struct request_queue *q);
+extern void blk_throtl_exit(struct request_queue *q);
+extern void blk_throtl_release(struct request_queue *q);
+#else /* CONFIG_BLK_DEV_THROTTLING */
+static inline bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
+{
+	return false;
+}
+static inline void blk_throtl_drain(struct request_queue *q) { }
+static inline int blk_throtl_init(struct request_queue *q) { return 0; }
+static inline void blk_throtl_exit(struct request_queue *q) { }
+static inline void blk_throtl_release(struct request_queue *q) { }
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
+#endif /* BLK_INTERNAL_H */
diff -druNp linux-libre-3.1-gnu1/block/blk-integrity.c linux-libre-3.2-gnu1/block/blk-integrity.c
--- linux-libre-3.1-gnu1/block/blk-integrity.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-integrity.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/mempool.h>
 #include <linux/bio.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include "blk.h"
diff -druNp linux-libre-3.1-gnu1/block/blk-map.c linux-libre-3.2-gnu1/block/blk-map.c
--- linux-libre-3.1-gnu1/block/blk-map.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-map.c	2012-01-04 18:55:44.000000000 -0500
@@ -204,10 +204,11 @@ int blk_rq_map_user_iov(struct request_q
 		if (!iov[i].iov_len)
 			return -EINVAL;
 
-		if (uaddr & queue_dma_alignment(q)) {
+		/*
+		 * Keep going so we check length of all segments
+		 */
+		if (uaddr & queue_dma_alignment(q))
 			unaligned = 1;
-			break;
-		}
 	}
 
 	if (unaligned || (q->dma_pad_mask & len) || map_data)
@@ -310,7 +311,7 @@ int blk_rq_map_kern(struct request_queue
 	if (IS_ERR(bio))
 		return PTR_ERR(bio);
 
-	if (rq_data_dir(rq) == WRITE)
+	if (!reading)
 		bio->bi_rw |= REQ_WRITE;
 
 	if (do_copy)
diff -druNp linux-libre-3.1-gnu1/block/blk-sysfs.c linux-libre-3.2-gnu1/block/blk-sysfs.c
--- linux-libre-3.1-gnu1/block/blk-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,11 +457,11 @@ queue_attr_store(struct kobject *kobj, s
 }
 
 /**
- * blk_cleanup_queue: - release a &struct request_queue when it is no longer needed
- * @kobj:    the kobj belonging of the request queue to be released
+ * blk_release_queue: - release a &struct request_queue when it is no longer needed
+ * @kobj:    the kobj belonging to the request queue to be released
  *
  * Description:
- *     blk_cleanup_queue is the pair to blk_init_queue() or
+ *     blk_release_queue is the pair to blk_init_queue() or
  *     blk_queue_make_request().  It should be called when a request queue is
  *     being released; typically when a block device is being de-registered.
  *     Currently, its primary task it to free all the &struct request
@@ -490,6 +490,7 @@ static void blk_release_queue(struct kob
 	if (q->queue_tags)
 		__blk_queue_free_tags(q);
 
+	blk_throtl_release(q);
 	blk_trace_shutdown(q);
 
 	bdi_destroy(&q->backing_dev_info);
diff -druNp linux-libre-3.1-gnu1/block/blk-tag.c linux-libre-3.2-gnu1/block/blk-tag.c
--- linux-libre-3.1-gnu1/block/blk-tag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-tag.c	2012-01-04 18:55:44.000000000 -0500
@@ -282,16 +282,9 @@ EXPORT_SYMBOL(blk_queue_resize_tags);
 void blk_queue_end_tag(struct request_queue *q, struct request *rq)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
-	int tag = rq->tag;
-
-	BUG_ON(tag == -1);
+	unsigned tag = rq->tag; /* negative tags invalid */
 
-	if (unlikely(tag >= bqt->real_max_depth))
-		/*
-		 * This can happen after tag depth has been reduced.
-		 * FIXME: how about a warning or info message here?
-		 */
-		return;
+	BUG_ON(tag >= bqt->real_max_depth);
 
 	list_del_init(&rq->queuelist);
 	rq->cmd_flags &= ~REQ_QUEUED;
diff -druNp linux-libre-3.1-gnu1/block/blk-throttle.c linux-libre-3.2-gnu1/block/blk-throttle.c
--- linux-libre-3.1-gnu1/block/blk-throttle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/blk-throttle.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/bio.h>
 #include <linux/blktrace_api.h>
 #include "blk-cgroup.h"
+#include "blk.h"
 
 /* Max dispatch from a group in 1 round */
 static int throtl_grp_quantum = 8;
@@ -302,16 +303,16 @@ throtl_grp *throtl_find_tg(struct throtl
 	return tg;
 }
 
-/*
- * This function returns with queue lock unlocked in case of error, like
- * request queue is no more
- */
 static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
 {
 	struct throtl_grp *tg = NULL, *__tg = NULL;
 	struct blkio_cgroup *blkcg;
 	struct request_queue *q = td->queue;
 
+	/* no throttling for dead queue */
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+		return NULL;
+
 	rcu_read_lock();
 	blkcg = task_blkio_cgroup(current);
 	tg = throtl_find_tg(td, blkcg);
@@ -323,32 +324,22 @@ static struct throtl_grp * throtl_get_tg
 	/*
 	 * Need to allocate a group. Allocation of group also needs allocation
 	 * of per cpu stats which in-turn takes a mutex() and can block. Hence
-	 * we need to drop rcu lock and queue_lock before we call alloc
-	 *
-	 * Take the request queue reference to make sure queue does not
-	 * go away once we return from allocation.
+	 * we need to drop rcu lock and queue_lock before we call alloc.
 	 */
-	blk_get_queue(q);
 	rcu_read_unlock();
 	spin_unlock_irq(q->queue_lock);
 
 	tg = throtl_alloc_tg(td);
-	/*
-	 * We might have slept in group allocation. Make sure queue is not
-	 * dead
-	 */
-	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
-		blk_put_queue(q);
-		if (tg)
-			kfree(tg);
-
-		return ERR_PTR(-ENODEV);
-	}
-	blk_put_queue(q);
 
 	/* Group allocated and queue is still alive. take the lock */
 	spin_lock_irq(q->queue_lock);
 
+	/* Make sure @q is still alive */
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+		kfree(tg);
+		return NULL;
+	}
+
 	/*
 	 * Initialize the new group. After sleeping, read the blkcg again.
 	 */
@@ -1014,11 +1005,6 @@ static void throtl_release_tgs(struct th
 	}
 }
 
-static void throtl_td_free(struct throtl_data *td)
-{
-	kfree(td);
-}
-
 /*
  * Blk cgroup controller notification saying that blkio_group object is being
  * delinked as associated cgroup object is going away. That also means that
@@ -1123,17 +1109,17 @@ static struct blkio_policy_type blkio_po
 	.plid = BLKIO_POLICY_THROTL,
 };
 
-int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
 {
 	struct throtl_data *td = q->td;
 	struct throtl_grp *tg;
-	struct bio *bio = *biop;
 	bool rw = bio_data_dir(bio), update_disptime = true;
 	struct blkio_cgroup *blkcg;
+	bool throttled = false;
 
 	if (bio->bi_rw & REQ_THROTTLED) {
 		bio->bi_rw &= ~REQ_THROTTLED;
-		return 0;
+		goto out;
 	}
 
 	/*
@@ -1152,7 +1138,7 @@ int blk_throtl_bio(struct request_queue
 			blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size,
 					rw, rw_is_sync(bio->bi_rw));
 			rcu_read_unlock();
-			return 0;
+			goto out;
 		}
 	}
 	rcu_read_unlock();
@@ -1161,18 +1147,10 @@ int blk_throtl_bio(struct request_queue
 	 * Either group has not been allocated yet or it is not an unlimited
 	 * IO group
 	 */
-
 	spin_lock_irq(q->queue_lock);
 	tg = throtl_get_tg(td);
-
-	if (IS_ERR(tg)) {
-		if (PTR_ERR(tg)	== -ENODEV) {
-			/*
-			 * Queue is gone. No queue lock held here.
-			 */
-			return -ENODEV;
-		}
-	}
+	if (unlikely(!tg))
+		goto out_unlock;
 
 	if (tg->nr_queued[rw]) {
 		/*
@@ -1200,7 +1178,7 @@ int blk_throtl_bio(struct request_queue
 		 * So keep on trimming slice even if bio is not queued.
 		 */
 		throtl_trim_slice(td, tg, rw);
-		goto out;
+		goto out_unlock;
 	}
 
 queue_bio:
@@ -1212,16 +1190,52 @@ queue_bio:
 			tg->nr_queued[READ], tg->nr_queued[WRITE]);
 
 	throtl_add_bio_tg(q->td, tg, bio);
-	*biop = NULL;
+	throttled = true;
 
 	if (update_disptime) {
 		tg_update_disptime(td, tg);
 		throtl_schedule_next_dispatch(td);
 	}
 
+out_unlock:
+	spin_unlock_irq(q->queue_lock);
 out:
+	return throttled;
+}
+
+/**
+ * blk_throtl_drain - drain throttled bios
+ * @q: request_queue to drain throttled bios for
+ *
+ * Dispatch all currently throttled bios on @q through ->make_request_fn().
+ */
+void blk_throtl_drain(struct request_queue *q)
+	__releases(q->queue_lock) __acquires(q->queue_lock)
+{
+	struct throtl_data *td = q->td;
+	struct throtl_rb_root *st = &td->tg_service_tree;
+	struct throtl_grp *tg;
+	struct bio_list bl;
+	struct bio *bio;
+
+	WARN_ON_ONCE(!queue_is_locked(q));
+
+	bio_list_init(&bl);
+
+	while ((tg = throtl_rb_first(st))) {
+		throtl_dequeue_tg(td, tg);
+
+		while ((bio = bio_list_peek(&tg->bio_lists[READ])))
+			tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+		while ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+			tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+	}
 	spin_unlock_irq(q->queue_lock);
-	return 0;
+
+	while ((bio = bio_list_pop(&bl)))
+		generic_make_request(bio);
+
+	spin_lock_irq(q->queue_lock);
 }
 
 int blk_throtl_init(struct request_queue *q)
@@ -1296,7 +1310,11 @@ void blk_throtl_exit(struct request_queu
 	 * it.
 	 */
 	throtl_shutdown_wq(q);
-	throtl_td_free(td);
+}
+
+void blk_throtl_release(struct request_queue *q)
+{
+	kfree(q->td);
 }
 
 static int __init throtl_init(void)
diff -druNp linux-libre-3.1-gnu1/block/bsg-lib.c linux-libre-3.2-gnu1/block/bsg-lib.c
--- linux-libre-3.1-gnu1/block/bsg-lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/bsg-lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/bsg-lib.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <scsi/scsi_cmnd.h>
 
 /**
diff -druNp linux-libre-3.1-gnu1/block/cfq-iosched.c linux-libre-3.2-gnu1/block/cfq-iosched.c
--- linux-libre-3.1-gnu1/block/cfq-iosched.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/cfq-iosched.c	2012-01-04 18:55:44.000000000 -0500
@@ -1655,6 +1655,8 @@ cfq_merged_requests(struct request_queue
 		    struct request *next)
 {
 	struct cfq_queue *cfqq = RQ_CFQQ(rq);
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+
 	/*
 	 * reposition in fifo if next is older than rq
 	 */
@@ -1669,6 +1671,16 @@ cfq_merged_requests(struct request_queue
 	cfq_remove_request(next);
 	cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
 					rq_data_dir(next), rq_is_sync(next));
+
+	cfqq = RQ_CFQQ(next);
+	/*
+	 * all requests of this queue are merged to other queues, delete it
+	 * from the service tree. If it's the active_queue,
+	 * cfq_dispatch_requests() will choose to expire it or do idle
+	 */
+	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list) &&
+	    cfqq != cfqd->active_queue)
+		cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
 static int cfq_allow_merge(struct request_queue *q, struct request *rq,
@@ -3184,7 +3196,7 @@ static int cfq_cic_link(struct cfq_data
 		}
 	}
 
-	if (ret)
+	if (ret && ret != -EEXIST)
 		printk(KERN_ERR "cfq: cic link failed!\n");
 
 	return ret;
@@ -3200,6 +3212,7 @@ cfq_get_io_context(struct cfq_data *cfqd
 {
 	struct io_context *ioc = NULL;
 	struct cfq_io_context *cic;
+	int ret;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
@@ -3207,6 +3220,7 @@ cfq_get_io_context(struct cfq_data *cfqd
 	if (!ioc)
 		return NULL;
 
+retry:
 	cic = cfq_cic_lookup(cfqd, ioc);
 	if (cic)
 		goto out;
@@ -3215,7 +3229,12 @@ cfq_get_io_context(struct cfq_data *cfqd
 	if (cic == NULL)
 		goto err;
 
-	if (cfq_cic_link(cfqd, ioc, cic, gfp_mask))
+	ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask);
+	if (ret == -EEXIST) {
+		/* someone has linked cic to ioc already */
+		cfq_cic_free(cic);
+		goto retry;
+	} else if (ret)
 		goto err_free;
 
 out:
@@ -4036,6 +4055,11 @@ static void *cfq_init_queue(struct reque
 
 	if (blkio_alloc_blkg_stats(&cfqg->blkg)) {
 		kfree(cfqg);
+
+		spin_lock(&cic_index_lock);
+		ida_remove(&cic_index_ida, cfqd->cic_index);
+		spin_unlock(&cic_index_lock);
+
 		kfree(cfqd);
 		return NULL;
 	}
diff -druNp linux-libre-3.1-gnu1/block/elevator.c linux-libre-3.2-gnu1/block/elevator.c
--- linux-libre-3.1-gnu1/block/elevator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/elevator.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
-#include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
@@ -182,7 +181,7 @@ static void elevator_attach(struct reque
 	eq->elevator_data = data;
 }
 
-static char chosen_elevator[16];
+static char chosen_elevator[ELV_NAME_MAX];
 
 static int __init elevator_setup(char *str)
 {
@@ -606,43 +605,35 @@ void elv_requeue_request(struct request_
 void elv_drain_elevator(struct request_queue *q)
 {
 	static int printed;
+
+	lockdep_assert_held(q->queue_lock);
+
 	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
 		;
-	if (q->nr_sorted == 0)
-		return;
-	if (printed++ < 10) {
+	if (q->nr_sorted && printed++ < 10) {
 		printk(KERN_ERR "%s: forced dispatching is broken "
 		       "(nr_sorted=%u), please report this\n",
 		       q->elevator->elevator_type->elevator_name, q->nr_sorted);
 	}
 }
 
-/*
- * Call with queue lock held, interrupts disabled
- */
 void elv_quiesce_start(struct request_queue *q)
 {
 	if (!q->elevator)
 		return;
 
+	spin_lock_irq(q->queue_lock);
 	queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
+	spin_unlock_irq(q->queue_lock);
 
-	/*
-	 * make sure we don't have any requests in flight
-	 */
-	elv_drain_elevator(q);
-	while (q->rq.elvpriv) {
-		__blk_run_queue(q);
-		spin_unlock_irq(q->queue_lock);
-		msleep(10);
-		spin_lock_irq(q->queue_lock);
-		elv_drain_elevator(q);
-	}
+	blk_drain_queue(q, false);
 }
 
 void elv_quiesce_end(struct request_queue *q)
 {
+	spin_lock_irq(q->queue_lock);
 	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+	spin_unlock_irq(q->queue_lock);
 }
 
 void __elv_add_request(struct request_queue *q, struct request *rq, int where)
@@ -972,7 +963,6 @@ static int elevator_switch(struct reques
 	/*
 	 * Turn on BYPASS and drain all requests w/ elevator private data
 	 */
-	spin_lock_irq(q->queue_lock);
 	elv_quiesce_start(q);
 
 	/*
@@ -983,8 +973,8 @@ static int elevator_switch(struct reques
 	/*
 	 * attach and start new elevator
 	 */
+	spin_lock_irq(q->queue_lock);
 	elevator_attach(q, e, data);
-
 	spin_unlock_irq(q->queue_lock);
 
 	if (old_elevator->registered) {
@@ -999,9 +989,7 @@ static int elevator_switch(struct reques
 	 * finally exit old elevator and turn off BYPASS.
 	 */
 	elevator_exit(old_elevator);
-	spin_lock_irq(q->queue_lock);
 	elv_quiesce_end(q);
-	spin_unlock_irq(q->queue_lock);
 
 	blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
 
@@ -1015,10 +1003,7 @@ fail_register:
 	elevator_exit(e);
 	q->elevator = old_elevator;
 	elv_register_queue(q);
-
-	spin_lock_irq(q->queue_lock);
-	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
-	spin_unlock_irq(q->queue_lock);
+	elv_quiesce_end(q);
 
 	return err;
 }
diff -druNp linux-libre-3.1-gnu1/block/genhd.c linux-libre-3.2-gnu1/block/genhd.c
--- linux-libre-3.1-gnu1/block/genhd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/genhd.c	2012-01-04 18:55:44.000000000 -0500
@@ -536,7 +536,7 @@ void register_disk(struct gendisk *disk)
 	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
 	/* No minors to use for partitions */
-	if (!disk_partitionable(disk))
+	if (!disk_part_scan_enabled(disk))
 		goto exit;
 
 	/* No such device (e.g., media were just removed) */
@@ -611,6 +611,12 @@ void add_disk(struct gendisk *disk)
 	register_disk(disk);
 	blk_register_queue(disk);
 
+	/*
+	 * Take an extra ref on queue which will be put on disk_release()
+	 * so that it sticks around as long as @disk is there.
+	 */
+	WARN_ON_ONCE(blk_get_queue(disk->queue));
+
 	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 				   "bdi");
 	WARN_ON(retval);
@@ -841,7 +847,7 @@ static int show_partition(struct seq_fil
 	char buf[BDEVNAME_SIZE];
 
 	/* Don't show non-partitionable removeable devices or empty devices */
-	if (!get_capacity(sgp) || (!disk_partitionable(sgp) &&
+	if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
 				   (sgp->flags & GENHD_FL_REMOVABLE)))
 		return 0;
 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
@@ -1095,6 +1101,8 @@ static void disk_release(struct device *
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
 	free_part_info(&disk->part0);
+	if (disk->queue)
+		blk_put_queue(disk->queue);
 	kfree(disk);
 }
 struct class block_class = {
diff -druNp linux-libre-3.1-gnu1/block/ioctl.c linux-libre-3.2-gnu1/block/ioctl.c
--- linux-libre-3.1-gnu1/block/ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/capability.h>
 #include <linux/blkdev.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/blkpg.h>
 #include <linux/hdreg.h>
@@ -101,7 +102,7 @@ static int blkdev_reread_part(struct blo
 	struct gendisk *disk = bdev->bd_disk;
 	int res;
 
-	if (!disk_partitionable(disk) || bdev != bdev->bd_contains)
+	if (!disk_part_scan_enabled(disk) || bdev != bdev->bd_contains)
 		return -EINVAL;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
diff -druNp linux-libre-3.1-gnu1/block/scsi_ioctl.c linux-libre-3.2-gnu1/block/scsi_ioctl.c
--- linux-libre-3.1-gnu1/block/scsi_ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/block/scsi_ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -565,7 +565,7 @@ int scsi_cmd_ioctl(struct request_queue
 {
 	int err;
 
-	if (!q || blk_get_queue(q))
+	if (!q)
 		return -ENXIO;
 
 	switch (cmd) {
@@ -686,7 +686,6 @@ int scsi_cmd_ioctl(struct request_queue
 			err = -ENOTTY;
 	}
 
-	blk_put_queue(q);
 	return err;
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
diff -druNp linux-libre-3.1-gnu1/CREDITS linux-libre-3.2-gnu1/CREDITS
--- linux-libre-3.1-gnu1/CREDITS	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/CREDITS	2012-01-04 18:55:44.000000000 -0500
@@ -688,10 +688,13 @@ S: Oxfordshire, UK.
 
 N: Kees Cook
 E: kees@outflux.net
-W: http://outflux.net/
-P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
-D: Minor updates to SCSI types, added /proc/pid/maps protection
+E: kees@ubuntu.com
+E: keescook@chromium.org
+W: http://outflux.net/blog/
+P: 4096R/DC6DC026 A5C3 F68F 229D D60F 723E  6E13 8972 F4DF DC6D C026
+D: Various security things, bug fixes, and documentation.
 S: (ask for current address)
+S: Portland, Oregon
 S: USA
 
 N: Robin Cornelius
diff -druNp linux-libre-3.1-gnu1/crypto/ablkcipher.c linux-libre-3.2-gnu1/crypto/ablkcipher.c
--- linux-libre-3.1-gnu1/crypto/ablkcipher.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/ablkcipher.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/scatterwalk.h>
 
@@ -381,6 +383,35 @@ static int crypto_init_ablkcipher_ops(st
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -403,6 +434,7 @@ const struct crypto_type crypto_ablkciph
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ablkcipher_show,
 #endif
+	.report = crypto_ablkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
 
@@ -432,6 +464,35 @@ static int crypto_init_givcipher_ops(str
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<built-in>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -454,6 +515,7 @@ const struct crypto_type crypto_givciphe
 #ifdef CONFIG_PROC_FS
 	.show = crypto_givcipher_show,
 #endif
+	.report = crypto_givcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_givcipher_type);
 
diff -druNp linux-libre-3.1-gnu1/crypto/aead.c linux-libre-3.2-gnu1/crypto/aead.c
--- linux-libre-3.1-gnu1/crypto/aead.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/aead.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -109,6 +111,35 @@ static int crypto_init_aead_ops(struct c
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 aead->geniv ?: "<built-in>");
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -130,6 +161,7 @@ const struct crypto_type crypto_aead_typ
 #ifdef CONFIG_PROC_FS
 	.show = crypto_aead_show,
 #endif
+	.report = crypto_aead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_aead_type);
 
@@ -165,6 +197,35 @@ static int crypto_init_nivaead_ops(struc
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
+
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -186,6 +247,7 @@ const struct crypto_type crypto_nivaead_
 #ifdef CONFIG_PROC_FS
 	.show = crypto_nivaead_show,
 #endif
+	.report = crypto_nivaead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_nivaead_type);
 
diff -druNp linux-libre-3.1-gnu1/crypto/ahash.c linux-libre-3.2-gnu1/crypto/ahash.c
--- linux-libre-3.1-gnu1/crypto/ahash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/ahash.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -397,6 +399,31 @@ static unsigned int crypto_ahash_extsize
 	return sizeof(struct crypto_shash *);
 }
 
+#ifdef CONFIG_NET
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -415,6 +442,7 @@ const struct crypto_type crypto_ahash_ty
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ahash_show,
 #endif
+	.report = crypto_ahash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
 	.type = CRYPTO_ALG_TYPE_AHASH,
diff -druNp linux-libre-3.1-gnu1/crypto/algapi.c linux-libre-3.2-gnu1/crypto/algapi.c
--- linux-libre-3.1-gnu1/crypto/algapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/algapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,6 @@
 
 #include "internal.h"
 
-static void crypto_remove_final(struct list_head *list);
-
 static LIST_HEAD(crypto_template_list);
 
 void crypto_larval_error(const char *name, u32 type, u32 mask)
@@ -129,9 +127,8 @@ static void crypto_remove_spawn(struct c
 	BUG_ON(!list_empty(&inst->alg.cra_users));
 }
 
-static void crypto_remove_spawns(struct crypto_alg *alg,
-				 struct list_head *list,
-				 struct crypto_alg *nalg)
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg)
 {
 	u32 new_type = (nalg ?: alg)->cra_flags;
 	struct crypto_spawn *spawn, *n;
@@ -177,6 +174,7 @@ static void crypto_remove_spawns(struct
 			crypto_remove_spawn(spawn, list);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_spawns);
 
 static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
 {
@@ -321,7 +319,7 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(crypto_alg_tested);
 
-static void crypto_remove_final(struct list_head *list)
+void crypto_remove_final(struct list_head *list)
 {
 	struct crypto_alg *alg;
 	struct crypto_alg *n;
@@ -331,6 +329,7 @@ static void crypto_remove_final(struct l
 		crypto_alg_put(alg);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_final);
 
 static void crypto_wait_for_test(struct crypto_larval *larval)
 {
@@ -493,6 +492,7 @@ int crypto_register_instance(struct cryp
 		goto err;
 
 	inst->alg.cra_module = tmpl->module;
+	inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
 
 	down_write(&crypto_alg_sem);
 
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/async_memcpy.c linux-libre-3.2-gnu1/crypto/async_tx/async_memcpy.c
--- linux-libre-3.1-gnu1/crypto/async_tx/async_memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/async_memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/async_tx.h>
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/async_pq.c linux-libre-3.2-gnu1/crypto/async_tx/async_pq.c
--- linux-libre-3.1-gnu1/crypto/async_tx/async_pq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/async_pq.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/async_raid6_recov.c linux-libre-3.2-gnu1/crypto/async_tx/async_raid6_recov.c
--- linux-libre-3.1-gnu1/crypto/async_tx/async_raid6_recov.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/async_raid6_recov.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/async_tx.c linux-libre-3.2-gnu1/crypto/async_tx/async_tx.c
--- linux-libre-3.1-gnu1/crypto/async_tx/async_tx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/async_tx.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  *
  */
 #include <linux/rculist.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/async_tx.h>
 
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/async_xor.c linux-libre-3.2-gnu1/crypto/async_tx/async_xor.c
--- linux-libre-3.1-gnu1/crypto/async_tx/async_xor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/async_xor.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/xor.h>
diff -druNp linux-libre-3.1-gnu1/crypto/async_tx/raid6test.c linux-libre-3.2-gnu1/crypto/async_tx/raid6test.c
--- linux-libre-3.1-gnu1/crypto/async_tx/raid6test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/async_tx/raid6test.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/gfp.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/module.h>
 
 #undef pr
 #define pr(fmt, args...) pr_info("raid6test: " fmt, ##args)
diff -druNp linux-libre-3.1-gnu1/crypto/blkcipher.c linux-libre-3.2-gnu1/crypto/blkcipher.c
--- linux-libre-3.1-gnu1/crypto/blkcipher.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/blkcipher.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -492,6 +494,35 @@ static int crypto_init_blkcipher_ops(str
 		return crypto_init_blkcipher_ops_async(tfm);
 }
 
+#ifdef CONFIG_NET
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_blkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -511,6 +542,7 @@ const struct crypto_type crypto_blkciphe
 #ifdef CONFIG_PROC_FS
 	.show = crypto_blkcipher_show,
 #endif
+	.report = crypto_blkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
 
diff -druNp linux-libre-3.1-gnu1/crypto/blowfish.c linux-libre-3.2-gnu1/crypto/blowfish.c
--- linux-libre-3.1-gnu1/crypto/blowfish.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/blowfish.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,482 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Blowfish Cipher Algorithm, by Bruce Schneier.
- * http://www.counterpane.com/blowfish.html
- *
- * Adapted from Kerneli implementation.
- *
- * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
- * Copyright (c) Kyle McMartin <kyle@debian.org>
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <asm/byteorder.h>
-#include <linux/crypto.h>
-#include <linux/types.h>
-
-#define BF_BLOCK_SIZE 8
-#define BF_MIN_KEY_SIZE 4
-#define BF_MAX_KEY_SIZE 56
-
-struct bf_ctx {
-	u32 p[18];
-	u32 s[1024];
-};
-
-static const u32 bf_pbox[16 + 2] = {
-	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
-	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
-	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
-	0x9216d5d9, 0x8979fb1b,
-};
-
-static const u32 bf_sbox[256 * 4] = {
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
-	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
-	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
-	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
-	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
-	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
-	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
-	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
-	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
-	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
-	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
-	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
-	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
-	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
-	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
-	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
-	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
-	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
-	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
-	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
-	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
-	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
-	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
-	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
-	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
-	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
-	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
-	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
-	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
-	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
-	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
-	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
-	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
-	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
-	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
-	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
-	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
-	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
-	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
-	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
-	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
-	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
-	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
-	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
-	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
-	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
-	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
-	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
-	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
-	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
-	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
-	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
-	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
-	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
-	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
-	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
-	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
-	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
-	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
-	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
-	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
-	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
-	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
-	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
-	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
-	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
-	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
-	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
-	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
-	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
-	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
-	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
-	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
-	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
-	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
-	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
-	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
-	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
-	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
-	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
-	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
-	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
-	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
-	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
-	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
-	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
-	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
-	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
-	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
-	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
-	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
-	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
-	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
-	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
-	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
-	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
-	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
-	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
-	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
-	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
-	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
-	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
-	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
-	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
-	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
-	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
-	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
-	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
-	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
-	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
-	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
-	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
-	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
-	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
-	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
-	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
-	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
-	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
-	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
-	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
-	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
-	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
-	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
-	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
-	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
-	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
-	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
-	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
-	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
-	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
-	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
-	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
-	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
-	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
-	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
-	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
-	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
-	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
-	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
-	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
-	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
-	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
-	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
-	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
-	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
-	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
-	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
-	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
-	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
-	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
-	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
-	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
-	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
-	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
-	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
-	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
-	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
-	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
-	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
-	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
-	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
-	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
-	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
-	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
-	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
-	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
-	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
-	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
-	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-};
-
-/*
- * Round loop unrolling macros, S is a pointer to a S-Box array
- * organized in 4 unsigned longs at a row.
- */
-#define GET32_3(x) (((x) & 0xff))
-#define GET32_2(x) (((x) >> (8)) & (0xff))
-#define GET32_1(x) (((x) >> (16)) & (0xff))
-#define GET32_0(x) (((x) >> (24)) & (0xff))
-
-#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
-          S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
-
-#define ROUND(a, b, n)  b ^= P[n]; a ^= bf_F (b)
-
-/*
- * The blowfish encipher, processes 64-bit blocks.
- * NOTE: This function MUSTN'T respect endianess
- */
-static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
-{
-	const u32 *P = bctx->p;
-	const u32 *S = bctx->s;
-	u32 yl = src[0];
-	u32 yr = src[1];
-
-	ROUND(yr, yl, 0);
-	ROUND(yl, yr, 1);
-	ROUND(yr, yl, 2);
-	ROUND(yl, yr, 3);
-	ROUND(yr, yl, 4);
-	ROUND(yl, yr, 5);
-	ROUND(yr, yl, 6);
-	ROUND(yl, yr, 7);
-	ROUND(yr, yl, 8);
-	ROUND(yl, yr, 9);
-	ROUND(yr, yl, 10);
-	ROUND(yl, yr, 11);
-	ROUND(yr, yl, 12);
-	ROUND(yl, yr, 13);
-	ROUND(yr, yl, 14);
-	ROUND(yl, yr, 15);
-
-	yl ^= P[16];
-	yr ^= P[17];
-
-	dst[0] = yr;
-	dst[1] = yl;
-}
-
-static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	u32 in32[2], out32[2];
-
-	in32[0] = be32_to_cpu(in_blk[0]);
-	in32[1] = be32_to_cpu(in_blk[1]);
-	encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
-	out_blk[0] = cpu_to_be32(out32[0]);
-	out_blk[1] = cpu_to_be32(out32[1]);
-}
-
-static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	const u32 *P = ctx->p;
-	const u32 *S = ctx->s;
-	u32 yl = be32_to_cpu(in_blk[0]);
-	u32 yr = be32_to_cpu(in_blk[1]);
-
-	ROUND(yr, yl, 17);
-	ROUND(yl, yr, 16);
-	ROUND(yr, yl, 15);
-	ROUND(yl, yr, 14);
-	ROUND(yr, yl, 13);
-	ROUND(yl, yr, 12);
-	ROUND(yr, yl, 11);
-	ROUND(yl, yr, 10);
-	ROUND(yr, yl, 9);
-	ROUND(yl, yr, 8);
-	ROUND(yr, yl, 7);
-	ROUND(yl, yr, 6);
-	ROUND(yr, yl, 5);
-	ROUND(yl, yr, 4);
-	ROUND(yr, yl, 3);
-	ROUND(yl, yr, 2);
-
-	yl ^= P[1];
-	yr ^= P[0];
-
-	out_blk[0] = cpu_to_be32(yr);
-	out_blk[1] = cpu_to_be32(yl);
-}
-
-/*
- * Calculates the blowfish S and P boxes for encryption and decryption.
- */
-static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	u32 *P = ctx->p;
-	u32 *S = ctx->s;
-	short i, j, count;
-	u32 data[2], temp;
-
-	/* Copy the initialization s-boxes */
-	for (i = 0, count = 0; i < 256; i++)
-		for (j = 0; j < 4; j++, count++)
-			S[count] = bf_sbox[count];
-
-	/* Set the p-boxes */
-	for (i = 0; i < 16 + 2; i++)
-		P[i] = bf_pbox[i];
-
-	/* Actual subkey generation */
-	for (j = 0, i = 0; i < 16 + 2; i++) {
-		temp = (((u32)key[j] << 24) |
-			((u32)key[(j + 1) % keylen] << 16) |
-			((u32)key[(j + 2) % keylen] << 8) |
-			((u32)key[(j + 3) % keylen]));
-
-		P[i] = P[i] ^ temp;
-		j = (j + 4) % keylen;
-	}
-
-	data[0] = 0x00000000;
-	data[1] = 0x00000000;
-
-	for (i = 0; i < 16 + 2; i += 2) {
-		encrypt_block((struct bf_ctx *)ctx, data, data);
-
-		P[i] = data[0];
-		P[i + 1] = data[1];
-	}
-
-	for (i = 0; i < 4; i++) {
-		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
-			encrypt_block((struct bf_ctx *)ctx, data, data);
-
-			S[count] = data[0];
-			S[count + 1] = data[1];
-		}
-	}
-
-	/* Bruce says not to bother with the weak key check. */
-	return 0;
-}
-
-static struct crypto_alg alg = {
-	.cra_name		=	"blowfish",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	BF_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct bf_ctx),
-	.cra_alignmask		=	3,
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
-	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
-	.cia_setkey   		= 	bf_setkey,
-	.cia_encrypt 		=	bf_encrypt,
-	.cia_decrypt  		=	bf_decrypt } }
-};
-
-static int __init blowfish_mod_init(void)
-{
-	return crypto_register_alg(&alg);
-}
-
-static void __exit blowfish_mod_fini(void)
-{
-	crypto_unregister_alg(&alg);
-}
-
-module_init(blowfish_mod_init);
-module_exit(blowfish_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
diff -druNp linux-libre-3.1-gnu1/crypto/blowfish_common.c linux-libre-3.2-gnu1/crypto/blowfish_common.c
--- linux-libre-3.1-gnu1/crypto/blowfish_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/crypto/blowfish_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,402 @@
+/*
+ * Cryptographic API.
+ *
+ * Common Blowfish algorithm parts shared between the c and assembler
+ * implementations.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+static const u32 bf_pbox[16 + 2] = {
+	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+	0x9216d5d9, 0x8979fb1b,
+};
+
+static const u32 bf_sbox[256 * 4] = {
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+};
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+/*
+ * The blowfish encipher, processes 64-bit blocks.
+ * NOTE: This function MUSTN'T respect endianess
+ */
+static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
+{
+	const u32 *P = bctx->p;
+	const u32 *S = bctx->s;
+	u32 yl = src[0];
+	u32 yr = src[1];
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	dst[0] = yr;
+	dst[1] = yl;
+}
+
+/*
+ * Calculates the blowfish S and P boxes for encryption and decryption.
+ */
+int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *P = ctx->p;
+	u32 *S = ctx->s;
+	short i, j, count;
+	u32 data[2], temp;
+
+	/* Copy the initialization s-boxes */
+	for (i = 0, count = 0; i < 256; i++)
+		for (j = 0; j < 4; j++, count++)
+			S[count] = bf_sbox[count];
+
+	/* Set the p-boxes */
+	for (i = 0; i < 16 + 2; i++)
+		P[i] = bf_pbox[i];
+
+	/* Actual subkey generation */
+	for (j = 0, i = 0; i < 16 + 2; i++) {
+		temp = (((u32)key[j] << 24) |
+			((u32)key[(j + 1) % keylen] << 16) |
+			((u32)key[(j + 2) % keylen] << 8) |
+			((u32)key[(j + 3) % keylen]));
+
+		P[i] = P[i] ^ temp;
+		j = (j + 4) % keylen;
+	}
+
+	data[0] = 0x00000000;
+	data[1] = 0x00000000;
+
+	for (i = 0; i < 16 + 2; i += 2) {
+		encrypt_block((struct bf_ctx *)ctx, data, data);
+
+		P[i] = data[0];
+		P[i + 1] = data[1];
+	}
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
+			encrypt_block((struct bf_ctx *)ctx, data, data);
+
+			S[count] = data[0];
+			S[count + 1] = data[1];
+		}
+	}
+
+	/* Bruce says not to bother with the weak key check. */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blowfish_setkey);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher common functions");
diff -druNp linux-libre-3.1-gnu1/crypto/blowfish_generic.c linux-libre-3.2-gnu1/crypto/blowfish_generic.c
--- linux-libre-3.1-gnu1/crypto/blowfish_generic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/crypto/blowfish_generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,142 @@
+/*
+ * Cryptographic API.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 17);
+	ROUND(yl, yr, 16);
+	ROUND(yr, yl, 15);
+	ROUND(yl, yr, 14);
+	ROUND(yr, yl, 13);
+	ROUND(yl, yr, 12);
+	ROUND(yr, yl, 11);
+	ROUND(yl, yr, 10);
+	ROUND(yr, yl, 9);
+	ROUND(yl, yr, 8);
+	ROUND(yr, yl, 7);
+	ROUND(yl, yr, 6);
+	ROUND(yr, yl, 5);
+	ROUND(yl, yr, 4);
+	ROUND(yr, yl, 3);
+	ROUND(yl, yr, 2);
+
+	yl ^= P[1];
+	yr ^= P[0];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static struct crypto_alg alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+	.cia_setkey		=	blowfish_setkey,
+	.cia_encrypt		=	bf_encrypt,
+	.cia_decrypt		=	bf_decrypt } }
+};
+
+static int __init blowfish_mod_init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit blowfish_mod_fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(blowfish_mod_init);
+module_exit(blowfish_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+MODULE_ALIAS("blowfish");
diff -druNp linux-libre-3.1-gnu1/crypto/cryptd.c linux-libre-3.2-gnu1/crypto/cryptd.c
--- linux-libre-3.1-gnu1/crypto/cryptd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/cryptd.c	2012-01-04 18:55:44.000000000 -0500
@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void)
 	crypto_unregister_template(&cryptd_tmpl);
 }
 
-module_init(cryptd_init);
+subsys_initcall(cryptd_init);
 module_exit(cryptd_exit);
 
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/crypto/crypto_user.c linux-libre-3.2-gnu1/crypto/crypto_user.c
--- linux-libre-3.1-gnu1/crypto/crypto_user.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/crypto/crypto_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,435 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <linux/security.h>
+#include <net/net_namespace.h>
+#include "internal.h"
+
+DEFINE_MUTEX(crypto_cfg_mutex);
+
+/* The crypto netlink socket */
+static struct sock *crypto_nlsk;
+
+struct crypto_dump_info {
+	struct sk_buff *in_skb;
+	struct sk_buff *out_skb;
+	u32 nlmsg_seq;
+	u16 nlmsg_flags;
+};
+
+static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
+{
+	struct crypto_alg *q, *alg = NULL;
+
+	down_read(&crypto_alg_sem);
+
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		int match = 0;
+
+		if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
+			continue;
+
+		if (strlen(p->cru_driver_name))
+			match = !strcmp(q->cra_driver_name,
+					p->cru_driver_name);
+		else if (!exact)
+			match = !strcmp(q->cra_name, p->cru_name);
+
+		if (match) {
+			alg = q;
+			break;
+		}
+	}
+
+	up_read(&crypto_alg_sem);
+
+	return alg;
+}
+
+static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_cipher rcipher;
+
+	snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+
+	rcipher.blocksize = alg->cra_blocksize;
+	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+	rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
+		sizeof(struct crypto_report_cipher), &rcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rcomp;
+
+	snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_one(struct crypto_alg *alg,
+			     struct crypto_user_alg *ualg, struct sk_buff *skb)
+{
+	memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
+	memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
+	       sizeof(ualg->cru_driver_name));
+	memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
+	       CRYPTO_MAX_ALG_NAME);
+
+	ualg->cru_flags = alg->cra_flags;
+	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
+
+	NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
+
+	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
+		struct crypto_report_larval rl;
+
+		snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
+
+		NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
+			sizeof(struct crypto_report_larval), &rl);
+
+		goto out;
+	}
+
+	if (alg->cra_type && alg->cra_type->report) {
+		if (alg->cra_type->report(skb, alg))
+			goto nla_put_failure;
+
+		goto out;
+	}
+
+	switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		if (crypto_report_cipher(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		if (crypto_report_comp(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	}
+
+out:
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_alg(struct crypto_alg *alg,
+			     struct crypto_dump_info *info)
+{
+	struct sk_buff *in_skb = info->in_skb;
+	struct sk_buff *skb = info->out_skb;
+	struct nlmsghdr *nlh;
+	struct crypto_user_alg *ualg;
+	int err = 0;
+
+	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
+			CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
+	if (!nlh) {
+		err = -EMSGSIZE;
+		goto out;
+	}
+
+	ualg = nlmsg_data(nlh);
+
+	err = crypto_report_one(alg, ualg, skb);
+	if (err) {
+		nlmsg_cancel(skb, nlh);
+		goto out;
+	}
+
+	nlmsg_end(skb, nlh);
+
+out:
+	return err;
+}
+
+static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+			 struct nlattr **attrs)
+{
+	struct crypto_user_alg *p = nlmsg_data(in_nlh);
+	struct crypto_alg *alg;
+	struct sk_buff *skb;
+	struct crypto_dump_info info;
+	int err;
+
+	if (!p->cru_driver_name)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	info.in_skb = in_skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = in_nlh->nlmsg_seq;
+	info.nlmsg_flags = 0;
+
+	err = crypto_report_alg(alg, &info);
+	if (err)
+		return err;
+
+	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
+}
+
+static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct crypto_alg *alg;
+	struct crypto_dump_info info;
+	int err;
+
+	if (cb->args[0])
+		goto out;
+
+	cb->args[0] = 1;
+
+	info.in_skb = cb->skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.nlmsg_flags = NLM_F_MULTI;
+
+	list_for_each_entry(alg, &crypto_alg_list, cra_list) {
+		err = crypto_report_alg(alg, &info);
+		if (err)
+			goto out_err;
+	}
+
+out:
+	return skb->len;
+out_err:
+	return err;
+}
+
+static int crypto_dump_report_done(struct netlink_callback *cb)
+{
+	return 0;
+}
+
+static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			     struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+	LIST_HEAD(list);
+
+	if (priority && !strlen(p->cru_driver_name))
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	down_write(&crypto_alg_sem);
+
+	crypto_remove_spawns(alg, &list, NULL);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_remove_final(&list);
+
+	return 0;
+}
+
+static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	/* We can not unregister core algorithms such as aes-generic.
+	 * We would loose the reference in the crypto_alg_list to this algorithm
+	 * if we try to unregister. Unregistering such an algorithm without
+	 * removing the module is not possible, so we restrict to crypto
+	 * instances that are build from templates. */
+	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
+		return -EINVAL;
+
+	if (atomic_read(&alg->cra_refcnt) != 1)
+		return -EBUSY;
+
+	return crypto_unregister_alg(alg);
+}
+
+static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	int exact;
+	const char *name;
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+
+	if (strlen(p->cru_driver_name))
+		exact = 1;
+
+	if (priority && !exact)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, exact);
+	if (alg)
+		return -EEXIST;
+
+	if (strlen(p->cru_driver_name))
+		name = p->cru_driver_name;
+	else
+		name = p->cru_name;
+
+	alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+	if (IS_ERR(alg))
+		return PTR_ERR(alg);
+
+	down_write(&crypto_alg_sem);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_mod_put(alg);
+
+	return 0;
+}
+
+#define MSGSIZE(type) sizeof(struct type)
+
+static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+};
+
+static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
+	[CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
+};
+
+#undef MSGSIZE
+
+static struct crypto_link {
+	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+	int (*dump)(struct sk_buff *, struct netlink_callback *);
+	int (*done)(struct netlink_callback *);
+} crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
+						       .dump = crypto_dump_report,
+						       .done = crypto_dump_report_done},
+};
+
+static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
+	struct crypto_link *link;
+	int type, err;
+
+	type = nlh->nlmsg_type;
+	if (type > CRYPTO_MSG_MAX)
+		return -EINVAL;
+
+	type -= CRYPTO_MSG_BASE;
+	link = &crypto_dispatch[type];
+
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
+	    (nlh->nlmsg_flags & NLM_F_DUMP))) {
+		if (link->dump == NULL)
+			return -EINVAL;
+
+		return netlink_dump_start(crypto_nlsk, skb, nlh,
+					  link->dump, link->done, 0);
+	}
+
+	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+			  crypto_policy);
+	if (err < 0)
+		return err;
+
+	if (link->doit == NULL)
+		return -EINVAL;
+
+	return link->doit(skb, nlh, attrs);
+}
+
+static void crypto_netlink_rcv(struct sk_buff *skb)
+{
+	mutex_lock(&crypto_cfg_mutex);
+	netlink_rcv_skb(skb, &crypto_user_rcv_msg);
+	mutex_unlock(&crypto_cfg_mutex);
+}
+
+static int __init crypto_user_init(void)
+{
+	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
+					    0, crypto_netlink_rcv,
+					    NULL, THIS_MODULE);
+	if (!crypto_nlsk)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void __exit crypto_user_exit(void)
+{
+	netlink_kernel_release(crypto_nlsk);
+}
+
+module_init(crypto_user_init);
+module_exit(crypto_user_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("Crypto userspace configuration API");
diff -druNp linux-libre-3.1-gnu1/crypto/crypto_wq.c linux-libre-3.2-gnu1/crypto/crypto_wq.c
--- linux-libre-3.1-gnu1/crypto/crypto_wq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/crypto_wq.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <crypto/algapi.h>
 #include <crypto/crypto_wq.h>
 
diff -druNp linux-libre-3.1-gnu1/crypto/internal.h linux-libre-3.2-gnu1/crypto/internal.h
--- linux-libre-3.1-gnu1/crypto/internal.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,9 @@ struct crypto_alg *crypto_larval_lookup(
 void crypto_larval_error(const char *name, u32 type, u32 mask);
 void crypto_alg_tested(const char *name, int err);
 
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg);
+void crypto_remove_final(struct list_head *list);
 void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
diff -druNp linux-libre-3.1-gnu1/crypto/Kconfig linux-libre-3.2-gnu1/crypto/Kconfig
--- linux-libre-3.1-gnu1/crypto/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -100,6 +100,14 @@ config CRYPTO_MANAGER2
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_PCOMP2
 
+config CRYPTO_USER
+	tristate "Userspace cryptographic algorithm configuration"
+	depends on NET
+	select CRYPTO_MANAGER
+	help
+	  Userapace configuration for cryptographic instantiations such as
+	  cbc(aes).
+
 config CRYPTO_MANAGER_DISABLE_TESTS
 	bool "Disable run-time self tests"
 	default y
@@ -407,6 +415,16 @@ config CRYPTO_SHA1
 	help
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
+config CRYPTO_SHA1_SSSE3
+	tristate "SHA1 digest algorithm (SSSE3/AVX)"
+	depends on X86 && 64BIT
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
+	  Extensions (AVX), when available.
+
 config CRYPTO_SHA256
 	tristate "SHA224 and SHA256 digest algorithm"
 	select CRYPTO_HASH
@@ -590,6 +608,7 @@ config CRYPTO_ARC4
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
 	help
 	  Blowfish cipher algorithm, by Bruce Schneier.
 
@@ -600,6 +619,30 @@ config CRYPTO_BLOWFISH
 	  See also:
 	  <http://www.schneier.com/blowfish.html>
 
+config CRYPTO_BLOWFISH_COMMON
+	tristate
+	help
+	  Common parts of the Blowfish cipher algorithm shared by the
+	  generic c and the assembler implementations.
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
+config CRYPTO_BLOWFISH_X86_64
+	tristate "Blowfish cipher algorithm (x86_64)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
+	help
+	  Blowfish cipher algorithm (x86_64), by Bruce Schneier.
+
+	  This is a variable key length cipher which can use keys from 32
+	  bits to 448 bits in length.  It's fast, simple and specifically
+	  designed for use on "large microprocessors".
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
 config CRYPTO_CAMELLIA
 	tristate "Camellia cipher algorithms"
 	depends on CRYPTO
@@ -792,6 +835,26 @@ config CRYPTO_TWOFISH_X86_64
 
 	  See also:
 	  <http://www.schneier.com/twofish.html>
+
+config CRYPTO_TWOFISH_X86_64_3WAY
+	tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_TWOFISH_COMMON
+	select CRYPTO_TWOFISH_X86_64
+	help
+	  Twofish cipher algorithm (x86_64, 3-way parallel).
+
+	  Twofish was submitted as an AES (Advanced Encryption Standard)
+	  candidate cipher by researchers at CounterPane Systems.  It is a
+	  16 round block cipher supporting key sizes of 128, 192, and 256
+	  bits.
+
+	  This module provides Twofish cipher algorithm that processes three
+	  blocks parallel, utilizing resources of out-of-order CPUs better.
+
+	  See also:
+	  <http://www.schneier.com/twofish.html>
 
 comment "Compression"
 
diff -druNp linux-libre-3.1-gnu1/crypto/Makefile linux-libre-3.2-gnu1/crypto/Makefile
--- linux-libre-3.1-gnu1/crypto/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@ obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
+obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
 obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
@@ -60,7 +61,8 @@ obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des_generic.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
-obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
+obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
diff -druNp linux-libre-3.1-gnu1/crypto/md4.c linux-libre-3.2-gnu1/crypto/md4.c
--- linux-libre-3.1-gnu1/crypto/md4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/md4.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
diff -druNp linux-libre-3.1-gnu1/crypto/pcompress.c linux-libre-3.2-gnu1/crypto/pcompress.c
--- linux-libre-3.1-gnu1/crypto/pcompress.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/pcompress.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/compress.h>
 #include <crypto/internal/compress.h>
@@ -46,6 +48,28 @@ static int crypto_pcomp_init_tfm(struct
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rpcomp;
+
+	snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rpcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
@@ -60,6 +84,7 @@ static const struct crypto_type crypto_p
 #ifdef CONFIG_PROC_FS
 	.show		= crypto_pcomp_show,
 #endif
+	.report		= crypto_pcomp_report,
 	.maskclear	= ~CRYPTO_ALG_TYPE_MASK,
 	.maskset	= CRYPTO_ALG_TYPE_MASK,
 	.type		= CRYPTO_ALG_TYPE_PCOMPRESS,
diff -druNp linux-libre-3.1-gnu1/crypto/proc.c linux-libre-3.2-gnu1/crypto/proc.c
--- linux-libre-3.1-gnu1/crypto/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/atomic.h>
 #include <linux/init.h>
 #include <linux/crypto.h>
+#include <linux/module.h>	/* for module_name() */
 #include <linux/rwsem.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
diff -druNp linux-libre-3.1-gnu1/crypto/rng.c linux-libre-3.2-gnu1/crypto/rng.c
--- linux-libre-3.1-gnu1/crypto/rng.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 static DEFINE_MUTEX(crypto_default_rng_lock);
 struct crypto_rng *crypto_default_rng;
@@ -58,6 +60,30 @@ static int crypto_init_rng_ops(struct cr
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_rng rrng;
+
+	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+
+	rrng.seedsize = alg->cra_rng.seedsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
+		sizeof(struct crypto_report_rng), &rrng);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
@@ -78,6 +104,7 @@ const struct crypto_type crypto_rng_type
 #ifdef CONFIG_PROC_FS
 	.show = crypto_rng_show,
 #endif
+	.report = crypto_rng_report,
 };
 EXPORT_SYMBOL_GPL(crypto_rng_type);
 
diff -druNp linux-libre-3.1-gnu1/crypto/sha1_generic.c linux-libre-3.2-gnu1/crypto/sha1_generic.c
--- linux-libre-3.1-gnu1/crypto/sha1_generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/sha1_generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@ static int sha1_init(struct shash_desc *
 	return 0;
 }
 
-static int sha1_update(struct shash_desc *desc, const u8 *data,
+int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
 			unsigned int len)
 {
 	struct sha1_state *sctx = shash_desc_ctx(desc);
@@ -71,6 +71,7 @@ static int sha1_update(struct shash_desc
 
 	return 0;
 }
+EXPORT_SYMBOL(crypto_sha1_update);
 
 
 /* Add padding and return the message digest. */
@@ -87,10 +88,10 @@ static int sha1_final(struct shash_desc
 	/* Pad out to 56 mod 64 */
 	index = sctx->count & 0x3f;
 	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha1_update(desc, padding, padlen);
+	crypto_sha1_update(desc, padding, padlen);
 
 	/* Append length */
-	sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 5; i++)
@@ -121,7 +122,7 @@ static int sha1_import(struct shash_desc
 static struct shash_alg alg = {
 	.digestsize	=	SHA1_DIGEST_SIZE,
 	.init		=	sha1_init,
-	.update		=	sha1_update,
+	.update		=	crypto_sha1_update,
 	.final		=	sha1_final,
 	.export		=	sha1_export,
 	.import		=	sha1_import,
diff -druNp linux-libre-3.1-gnu1/crypto/shash.c linux-libre-3.2-gnu1/crypto/shash.c
--- linux-libre-3.1-gnu1/crypto/shash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/shash.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -522,6 +524,31 @@ static unsigned int crypto_shash_extsize
 	return alg->cra_ctxsize;
 }
 
+#ifdef CONFIG_NET
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+	struct shash_alg *salg = __crypto_shash_alg(alg);
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = salg->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -541,6 +568,7 @@ static const struct crypto_type crypto_s
 #ifdef CONFIG_PROC_FS
 	.show = crypto_shash_show,
 #endif
+	.report = crypto_shash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_MASK,
 	.type = CRYPTO_ALG_TYPE_SHASH,
diff -druNp linux-libre-3.1-gnu1/crypto/tcrypt.c linux-libre-3.2-gnu1/crypto/tcrypt.c
--- linux-libre-3.1-gnu1/crypto/tcrypt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/tcrypt.c	2012-01-04 18:55:44.000000000 -0500
@@ -782,11 +782,13 @@ static int do_test(int m)
 	case 7:
 		ret += tcrypt_test("ecb(blowfish)");
 		ret += tcrypt_test("cbc(blowfish)");
+		ret += tcrypt_test("ctr(blowfish)");
 		break;
 
 	case 8:
 		ret += tcrypt_test("ecb(twofish)");
 		ret += tcrypt_test("cbc(twofish)");
+		ret += tcrypt_test("ctr(twofish)");
 		break;
 
 	case 9:
@@ -1039,6 +1041,10 @@ static int do_test(int m)
 				speed_template_16_24_32);
 		test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
 				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
 		break;
 
 	case 203:
@@ -1050,6 +1056,10 @@ static int do_test(int m)
 				  speed_template_8_32);
 		test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
 				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_32);
 		break;
 
 	case 204:
diff -druNp linux-libre-3.1-gnu1/crypto/testmgr.c linux-libre-3.2-gnu1/crypto/testmgr.c
--- linux-libre-3.1-gnu1/crypto/testmgr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/testmgr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1756,6 +1756,36 @@ static const struct alg_test_desc alg_te
 			}
 		}
 	}, {
+		.alg = "ctr(blowfish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = bf_ctr_enc_tv_template,
+					.count = BF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = bf_ctr_dec_tv_template,
+					.count = BF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "ctr(twofish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = tf_ctr_enc_tv_template,
+					.count = TF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = tf_ctr_dec_tv_template,
+					.count = TF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "cts(cbc(aes))",
 		.test = alg_test_skcipher,
 		.suite = {
diff -druNp linux-libre-3.1-gnu1/crypto/testmgr.h linux-libre-3.2-gnu1/crypto/testmgr.h
--- linux-libre-3.1-gnu1/crypto/testmgr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/testmgr.h	2012-01-04 18:55:44.000000000 -0500
@@ -2391,10 +2391,12 @@ static struct cipher_testvec des3_ede_cb
 /*
  * Blowfish test vectors.
  */
-#define BF_ENC_TEST_VECTORS	6
-#define BF_DEC_TEST_VECTORS	6
-#define BF_CBC_ENC_TEST_VECTORS	1
-#define BF_CBC_DEC_TEST_VECTORS	1
+#define BF_ENC_TEST_VECTORS	7
+#define BF_DEC_TEST_VECTORS	7
+#define BF_CBC_ENC_TEST_VECTORS	2
+#define BF_CBC_DEC_TEST_VECTORS	2
+#define BF_CTR_ENC_TEST_VECTORS	2
+#define BF_CTR_DEC_TEST_VECTORS	2
 
 static struct cipher_testvec bf_enc_tv_template[] = {
 	{ /* DES test vectors from OpenSSL */
@@ -2448,6 +2450,24 @@ static struct cipher_testvec bf_enc_tv_t
 		.ilen	= 8,
 		.result	= "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.rlen	= 40,
 	},
 };
 
@@ -2503,6 +2523,24 @@ static struct cipher_testvec bf_dec_tv_t
 		.ilen	= 8,
 		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
 	},
 };
 
@@ -2522,6 +2560,25 @@ static struct cipher_testvec bf_cbc_enc_
 			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
 			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.rlen	= 40,
 	},
 };
 
@@ -2541,16 +2598,125 @@ static struct cipher_testvec bf_cbc_dec_
 			  "\x68\x65\x20\x74\x69\x6d\x65\x20"
 			  "\x66\x6f\x72\x20\x00\x00\x00\x00",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	},
+};
+
+static struct cipher_testvec bf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.ilen	= 43,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.rlen	= 43,
+	},
+};
+
+static struct cipher_testvec bf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.ilen	= 43,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.rlen	= 43,
 	},
 };
 
 /*
  * Twofish test vectors.
  */
-#define TF_ENC_TEST_VECTORS		3
-#define TF_DEC_TEST_VECTORS		3
-#define TF_CBC_ENC_TEST_VECTORS		4
-#define TF_CBC_DEC_TEST_VECTORS		4
+#define TF_ENC_TEST_VECTORS		4
+#define TF_DEC_TEST_VECTORS		4
+#define TF_CBC_ENC_TEST_VECTORS		5
+#define TF_CBC_DEC_TEST_VECTORS		5
+#define TF_CTR_ENC_TEST_VECTORS		2
+#define TF_CTR_DEC_TEST_VECTORS		2
 
 static struct cipher_testvec tf_enc_tv_template[] = {
 	{
@@ -2582,6 +2748,30 @@ static struct cipher_testvec tf_enc_tv_t
 		.result	= "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
 			  "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.rlen	= 64,
 	},
 };
 
@@ -2615,6 +2805,30 @@ static struct cipher_testvec tf_dec_tv_t
 		.ilen	= 16,
 		.result	= zeroed_string,
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
 	},
 };
 
@@ -2661,6 +2875,32 @@ static struct cipher_testvec tf_cbc_enc_
 			  "\x05\xef\x8c\x61\xa8\x11\x58\x26"
 			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.rlen	= 64,
 	},
 };
 
@@ -2707,6 +2947,148 @@ static struct cipher_testvec tf_cbc_dec_
 		.ilen	= 48,
 		.result	= zeroed_string,
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	},
+};
+
+static struct cipher_testvec tf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.ilen	= 67,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.rlen	= 67,
+	},
+};
+
+static struct cipher_testvec tf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.ilen	= 67,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.rlen	= 67,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/crypto/vmac.c linux-libre-3.2-gnu1/crypto/vmac.c
--- linux-libre-3.1-gnu1/crypto/vmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/vmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <asm/byteorder.h>
 #include <crypto/scatterwalk.h>
diff -druNp linux-libre-3.1-gnu1/crypto/wp512.c linux-libre-3.2-gnu1/crypto/wp512.c
--- linux-libre-3.1-gnu1/crypto/wp512.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/wp512.c	2012-01-04 18:55:44.000000000 -0500
@@ -762,11 +762,17 @@ static const u64 C7[256] = {
 	0x86228644a411c286ULL,
 };
 
-static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
-	0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
-	0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
-	0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
-	0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+static const u64 rc[WHIRLPOOL_ROUNDS] = {
+	0x1823c6e887b8014fULL,
+	0x36a6d2f5796f9152ULL,
+	0x60bc9b8ea30c7b35ULL,
+	0x1de0d7c22e4bfe57ULL,
+	0x157737e59ff04adaULL,
+	0x58c9290ab1a06b85ULL,
+	0xbd5d10f4cb3e0567ULL,
+	0xe427418ba77d95d8ULL,
+	0xfbee7c66dd17479eULL,
+	0xca2dbf07ad5a8333ULL,
 };
 
 /**
@@ -793,7 +799,7 @@ static void wp512_process_buffer(struct
 	state[6] = block[6] ^ (K[6] = wctx->hash[6]);
 	state[7] = block[7] ^ (K[7] = wctx->hash[7]);
 
-	for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+	for (r = 0; r < WHIRLPOOL_ROUNDS; r++) {
 
 		L[0] = C0[(int)(K[0] >> 56)       ] ^
 			   C1[(int)(K[7] >> 48) & 0xff] ^
diff -druNp linux-libre-3.1-gnu1/crypto/xcbc.c linux-libre-3.2-gnu1/crypto/xcbc.c
--- linux-libre-3.1-gnu1/crypto/xcbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/crypto/xcbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
 			   0x02020202, 0x02020202, 0x02020202, 0x02020202,
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/removed/o2cb linux-libre-3.2-gnu1/Documentation/ABI/removed/o2cb
--- linux-libre-3.1-gnu1/Documentation/ABI/removed/o2cb	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/removed/o2cb	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 What:		/sys/o2cb symlink
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	ocfs2-devel@oss.oracle.com
 Description:	This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is
 		removed when new versions of ocfs2-tools which know to look
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/removed/raw1394 linux-libre-3.2-gnu1/Documentation/ABI/removed/raw1394
--- linux-libre-3.1-gnu1/Documentation/ABI/removed/raw1394	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/removed/raw1394	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@ Description:
 	/dev/raw1394 was a character device file that allowed low-level
 	access to FireWire buses.  Its major drawbacks were its inability
 	to implement sensible device security policies, and its low level
-	of abstraction that required userspace clients do duplicate much
+	of abstraction that required userspace clients to duplicate much
 	of the kernel's ieee1394 core functionality.
 	Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
 	firewire-core.
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/stable/sysfs-acpi-pmprofile linux-libre-3.2-gnu1/Documentation/ABI/stable/sysfs-acpi-pmprofile
--- linux-libre-3.1-gnu1/Documentation/ABI/stable/sysfs-acpi-pmprofile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/stable/sysfs-acpi-pmprofile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+What: 		/sys/firmware/acpi/pm_profile
+Date:		03-Nov-2011
+KernelVersion:	v3.2
+Contact:	linux-acpi@vger.kernel.org
+Description: 	The ACPI pm_profile sysfs interface exports the platform
+		power management (and performance) requirement expectations
+		as provided by BIOS. The integer value is directly passed as
+		retrieved from the FADT ACPI table.
+Values:         For possible values see ACPI specification:
+		5.2.9 Fixed ACPI Description Table (FADT)
+		Field: Preferred_PM_Profile
+
+		Currently these values are defined by spec:
+		0 Unspecified
+		1 Desktop
+		2 Mobile
+		3 Workstation
+		4 Enterprise Server
+		5 SOHO Server
+		6 Appliance PC
+		7 Performance Server
+		>7 Reserved
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/debugfs-ideapad linux-libre-3.2-gnu1/Documentation/ABI/testing/debugfs-ideapad
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/debugfs-ideapad	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/debugfs-ideapad	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+What:		/sys/kernel/debug/ideapad/cfg
+Date:		Sep 2011
+KernelVersion:	3.2
+Contact:	Ike Panhc <ike.pan@canonical.com>
+Description:
+
+cfg shows the return value of _CFG method in VPC2004 device. It tells machine
+capability and what graphic component within the machine.
+
+
+What:		/sys/kernel/debug/ideapad/status
+Date:		Sep 2011
+KernelVersion:	3.2
+Contact:	Ike Panhc <ike.pan@canonical.com>
+Description:
+
+status shows infos we can read and tells its meaning and value.
+
+
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/evm linux-libre-3.2-gnu1/Documentation/ABI/testing/evm
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/evm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/evm	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+What:		security/evm
+Date:		March 2011
+Contact:	Mimi Zohar <zohar@us.ibm.com>
+Description:
+		EVM protects a file's security extended attributes(xattrs)
+		against integrity attacks. The initial method maintains an
+		HMAC-sha1 value across the extended attributes, storing the
+		value as the extended attribute 'security.evm'.
+
+		EVM depends on the Kernel Key Retention System to provide it
+		with a trusted/encrypted key for the HMAC-sha1 operation.
+		The key is loaded onto the root's keyring using keyctl.  Until
+		EVM receives notification that the key has been successfully
+		loaded onto the keyring (echo 1 > <securityfs>/evm), EVM
+		can not create or validate the 'security.evm' xattr, but
+		returns INTEGRITY_UNKNOWN.  Loading the key and signaling EVM
+		should be done as early as possible.  Normally this is done
+		in the initramfs, which has already been measured as part
+		of the trusted boot.  For more information on creating and
+		loading existing trusted/encrypted keys, refer to:
+		Documentation/keys-trusted-encrypted.txt.  (A sample dracut
+		patch, which loads the trusted/encrypted key and enables
+		EVM, is available from http://linux-ima.sourceforge.net/#EVM.)
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-bcma linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-bcma
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-bcma	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-bcma	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 What:		/sys/bus/bcma/devices/.../manuf
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		Each BCMA core has it's manufacturer id. See
@@ -8,7 +8,7 @@ Description:
 
 What:		/sys/bus/bcma/devices/.../id
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		There are a few types of BCMA cores, they can be identified by
@@ -16,7 +16,7 @@ Description:
 
 What:		/sys/bus/bcma/devices/.../rev
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		BCMA cores of the same type can still slightly differ depending
@@ -24,7 +24,7 @@ Description:
 
 What:		/sys/bus/bcma/devices/.../class
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		Each BCMA core is identified by few fields, including class it
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2012-01-04 18:55:44.000000000 -0500
@@ -71,3 +71,10 @@ Description:	Value of 1 indicates the co
 		a dump device, as kdump requires resetting the device in order
 		to work reliably.
 
+Where:		/sys/bus/pci/devices/<dev>/ccissX/transport_mode
+Date:		July 2011
+Kernel Version:	3.0
+Contact:	iss_storagedev@hp.com
+Description:	Value of "simple" indicates that the controller has been placed
+		in "simple mode". Value of "performant" indicates that the
+		controller has been placed in "performant mode".
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,46 @@
+What:		/sys/bus/pci/drivers/ehci_hcd/.../companion
+		/sys/bus/usb/devices/usbN/../companion
+Date:		January 2007
+KernelVersion:	2.6.21
+Contact:	Alan Stern <stern@rowland.harvard.edu>
+Description:
+		PCI-based EHCI USB controllers (i.e., high-speed USB-2.0
+		controllers) are often implemented along with a set of
+		"companion" full/low-speed USB-1.1 controllers.  When a
+		high-speed device is plugged in, the connection is routed
+		to the EHCI controller; when a full- or low-speed device
+		is plugged in, the connection is routed to the companion
+		controller.
+
+		Sometimes you want to force a high-speed device to connect
+		at full speed, which can be accomplished by forcing the
+		connection to be routed to the companion controller.
+		That's what this file does.  Writing a port number to the
+		file causes connections on that port to be routed to the
+		companion controller, and writing the negative of a port
+		number returns the port to normal operation.
+
+		For example: To force the high-speed device attached to
+		port 4 on bus 2 to run at full speed:
+
+			echo 4 >/sys/bus/usb/devices/usb2/../companion
+
+		To return the port to high-speed operation:
+
+			echo -4 >/sys/bus/usb/devices/usb2/../companion
+
+		Reading the file gives the list of ports currently forced
+		to the companion controller.
+
+		Note: Some EHCI controllers do not have companions; they
+		may contain an internal "transaction translator" or they
+		may be attached directly to a "rate-matching hub".  This
+		mechanism will not work with such controllers.  Also, it
+		cannot be used to force a port on a high-speed hub to
+		connect at full speed.
+
+		Note: When this file was first added, it appeared in a
+		different sysfs directory.  The location given above is
+		correct for 2.6.35 (and probably several earlier kernel
+		versions as well).
+
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-rbd linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-rbd
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-rbd	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-rbd	2012-01-04 18:55:44.000000000 -0500
@@ -57,13 +57,6 @@ create_snap
 
 	 $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_create
 
-rollback_snap
-
-	Rolls back data to the specified snapshot. This goes over the entire
-	list of rados blocks and sends a rollback command to each.
-
-	 $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_rollback
-
 snap_*
 
 	A directory per each snapshot
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-usb linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-usb
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-bus-usb	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-bus-usb	2012-01-04 18:55:44.000000000 -0500
@@ -142,3 +142,18 @@ Description:
 		such devices.
 Users:
 		usb_modeswitch
+
+What:		/sys/bus/usb/devices/.../power/usb2_hardware_lpm
+Date:		September 2011
+Contact:	Andiry Xu <andiry.xu@amd.com>
+Description:
+		If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
+		is plugged in to a xHCI host which support link PM, it will
+		perform a LPM test; if the test is passed and host supports
+		USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
+		be enabled for the device and the USB device directory will
+		contain a file named power/usb2_hardware_lpm.  The file holds
+		a string value (enable or disable) indicating whether or not
+		USB2 hardware LPM is enabled for the device. Developer can
+		write y/Y/1 or n/N/0 to the file to enable/disable the
+		feature.
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@ What:		/sys/class/backlight/<backlight>/
 What:		/sys/class/backlight/<backlight>/l3_office_max
 What:		/sys/class/backlight/<backlight>/l4_indoor_max
 What:		/sys/class/backlight/<backlight>/l5_dark_max
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Control the maximum brightness for <ambient light zone>
@@ -18,8 +18,8 @@ What:		/sys/class/backlight/<backlight>/
 What:		/sys/class/backlight/<backlight>/l3_office_dim
 What:		/sys/class/backlight/<backlight>/l4_indoor_dim
 What:		/sys/class/backlight/<backlight>/l5_dark_dim
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Control the dim brightness for <ambient light zone>
@@ -29,8 +29,8 @@ Description:
 		this <ambient light zone>.
 
 What:		/sys/class/backlight/<backlight>/ambient_light_level
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Get conversion value of the light sensor.
@@ -39,8 +39,8 @@ Description:
 		8000 (max ambient brightness)
 
 What:		/sys/class/backlight/<backlight>/ambient_light_zone
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Get/Set current ambient light zone. Reading returns
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-devfreq linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-devfreq
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-devfreq	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-devfreq	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+What:		/sys/class/devfreq/.../
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		Provide a place in sysfs for the devfreq objects.
+		This allows accessing various devfreq specific variables.
+		The name of devfreq object denoted as ... is same as the
+		name of device using devfreq.
+
+What:		/sys/class/devfreq/.../governor
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../governor shows the name of the
+		governor used by the corresponding devfreq object.
+
+What:		/sys/class/devfreq/.../cur_freq
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../cur_freq shows the current
+		frequency of the corresponding devfreq object.
+
+What:		/sys/class/devfreq/.../central_polling
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../central_polling shows whether
+		the devfreq ojbect is using devfreq-provided central
+		polling mechanism or not.
+
+What:		/sys/class/devfreq/.../polling_interval
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../polling_interval shows and sets
+		the requested polling interval of the corresponding devfreq
+		object. The values are represented in ms. If the value is
+		less than 1 jiffy, it is considered to be 0, which means
+		no polling. This value is meaningless if the governor is
+		not polling; thus. If the governor is not using
+		devfreq-provided central polling
+		(/sys/class/devfreq/.../central_polling is 0), this value
+		may be useless.
+
+What:		/sys/class/devfreq/.../userspace/set_freq
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../userspace/set_freq shows and
+		sets the requested frequency for the devfreq object if
+		userspace governor is in effect.
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,14 @@ Description:
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
+What:		/sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:		May 2011
+Contact:	Antonio Quartulli <ordex@autistici.org>
+Description:
+		Indicates whether the data traffic going from a
+		wireless client to another wireless client will be
+		silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+What:		/sys/module/hid_logitech/drivers/hid:logitech/<dev>/range.
+Date:		July 2011
+KernelVersion:	3.2
+Contact:	Michal Malý <madcatxster@gmail.com>
+Description:	Display minimum, maximum and current range of the steering
+		wheel. Writing a value within min and max boundaries sets the
+		range of the wheel.
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-driver-wacom linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-driver-wacom
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-driver-wacom	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-driver-wacom	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+What:		/sys/class/hidraw/hidraw*/device/speed
+Date:		April 2010
+Kernel Version:	2.6.35
+Contact:	linux-bluetooth@vger.kernel.org
+Description:
+		The /sys/class/hidraw/hidraw*/device/speed file controls
+		reporting speed of Wacom bluetooth tablet. Reading from
+		this file returns 1 if tablet reports in high speed mode
+		or 0 otherwise. Writing to this file one of these values
+		switches reporting speed.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Attribute group for control of the status LEDs and the OLEDs.
+		This attribute group is only available for Intuos 4 M, L,
+		and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only).
+		Therefore its presence implicitly signifies the presence of
+		said LEDs and OLEDs on the tablet device.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the status LED luminance (1..127)
+		when the stylus does not touch the tablet surface, and no
+		button is pressed on the stylus. This luminance level is
+		normally lower than the level when a button is pressed.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the status LED luminance (1..127)
+		when the stylus touches the tablet surface, or any button is
+		pressed on the stylus.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets which one of the four (for Intuos 4)
+		or of the right four (for Cintiq 21UX2) status LEDs is active (0..3).
+		The other three LEDs on the same side are always inactive.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
+Date:		September 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets which one of the left four (for Cintiq 21UX2)
+		status LEDs is active (0..3). The other three LEDs on the left are always
+		inactive.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the overall luminance level (0..15)
+		of all eight button OLED displays.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		When writing a 1024 byte raw image in Wacom Intuos 4
+		interleaving format to the file, the image shows up on Button N
+		of the device. The image is a 64x32 pixel 4-bit gray image. The
+		1024 byte binary is split up into 16x 64 byte chunks. Each 64
+		byte chunk encodes the image data for two consecutive lines on
+		the display. The low nibble of each byte contains the first
+		line, and the high nibble contains the second line.
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	2012-01-04 18:55:44.000000000 -0500
@@ -5,19 +5,4 @@ Contact:	"Ike Panhc <ike.pan@canonical.c
 Description:
 		Control the power of camera module. 1 means on, 0 means off.
 
-What:		/sys/devices/platform/ideapad/cfg
-Date:		Jun 2011
-KernelVersion:	3.1
-Contact:	"Ike Panhc <ike.pan@canonical.com>"
-Description:
-		Ideapad capability bits.
-		Bit 8-10: 1 - Intel graphic only
-		          2 - ATI graphic only
-		          3 - Nvidia graphic only
-		          4 - Intel and ATI graphic
-		          5 - Intel and Nvidia graphic
-		Bit 16: Bluetooth exist (1 for exist)
-		Bit 17: 3G exist (1 for exist)
-		Bit 18: Wifi exist (1 for exist)
-		Bit 19: Camera exist (1 for exist)
 
diff -druNp linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-wacom linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-wacom
--- linux-libre-3.1-gnu1/Documentation/ABI/testing/sysfs-wacom	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/ABI/testing/sysfs-wacom	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-What:		/sys/class/hidraw/hidraw*/device/speed
-Date:		April 2010
-Kernel Version:	2.6.35
-Contact:	linux-bluetooth@vger.kernel.org
-Description:
-		The /sys/class/hidraw/hidraw*/device/speed file controls
-		reporting speed of wacom bluetooth tablet. Reading from
-		this file returns 1 if tablet reports in high speed mode
-		or 0 otherwise. Writing to this file one of these values
-		switches reporting speed.
diff -druNp linux-libre-3.1-gnu1/Documentation/blackfin/bfin-gpio-notes.txt linux-libre-3.2-gnu1/Documentation/blackfin/bfin-gpio-notes.txt
--- linux-libre-3.1-gnu1/Documentation/blackfin/bfin-gpio-notes.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/blackfin/bfin-gpio-notes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * File:         Documentation/blackfin/bfin-gpio-note.txt
+ * File:         Documentation/blackfin/bfin-gpio-notes.txt
  * Based on:
  * Author:
  *
diff -druNp linux-libre-3.1-gnu1/Documentation/block/biodoc.txt linux-libre-3.2-gnu1/Documentation/block/biodoc.txt
--- linux-libre-3.1-gnu1/Documentation/block/biodoc.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/block/biodoc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@ a virtual address mapping (unlike the ea
 do not have a corresponding kernel virtual address space mapping) and
 low-memory pages.
 
-Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
+Note: Please refer to Documentation/DMA-API-HOWTO.txt for a discussion
 on PCI high mem DMA aspects and mapping of scatter gather lists, and support
 for 64 bit PCI.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/block/switching-sched.txt linux-libre-3.2-gnu1/Documentation/block/switching-sched.txt
--- linux-libre-3.1-gnu1/Documentation/block/switching-sched.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/block/switching-sched.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
-assigned globally at boot time only presently.
+'noop' and 'cfq' (the default) are also available. IO schedulers are assigned
+globally at boot time only presently.
 
 Each io queue has a set of io scheduler tunables associated with it. These
 tunables control how the io scheduler works. You can find these entries
diff -druNp linux-libre-3.1-gnu1/Documentation/blockdev/cciss.txt linux-libre-3.2-gnu1/Documentation/blockdev/cciss.txt
--- linux-libre-3.1-gnu1/Documentation/blockdev/cciss.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/blockdev/cciss.txt	2012-01-04 18:55:44.000000000 -0500
@@ -78,6 +78,16 @@ The device naming scheme is:
 /dev/cciss/c1d1p2		Controller 1, disk 1, partition 2
 /dev/cciss/c1d1p3		Controller 1, disk 1, partition 3
 
+CCISS simple mode support
+-------------------------
+
+The "cciss_simple_mode=1" boot parameter may be used to prevent the driver
+from putting the controller into "performant" mode. The difference is that
+with simple mode, each command completion requires an interrupt, while with
+"performant mode" (the default, and ordinarily better performing) it is
+possible to have multiple command completions indicated by a single
+interrupt.
+
 SCSI tape drive and medium changer support
 ------------------------------------------
 
@@ -88,14 +98,12 @@ You must enable "SCSI tape drive support
 "SCSI support" in your kernel configuration to be able to use SCSI
 tape drives with your Smart Array 5xxx controller.
 
-Additionally, note that the driver will not engage the SCSI core at init 
-time.  The driver must be directed to dynamically engage the SCSI core via 
-the /proc filesystem entry which the "block" side of the driver creates as 
-/proc/driver/cciss/cciss* at runtime.  This is because at driver init time, 
-the SCSI core may not yet be initialized (because the driver is a block 
-driver) and attempting to register it with the SCSI core in such a case 
-would cause a hang.  This is best done via an initialization script 
-(typically in /etc/init.d, but could vary depending on distribution). 
+Additionally, note that the driver will engage the SCSI core at init
+time if any tape drives or medium changers are detected.  The driver may
+also be directed to dynamically engage the SCSI core via the /proc filesystem
+entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime.  This is best done via a script.
+
 For example:
 
 	for x in /proc/driver/cciss/cciss[0-9]*
diff -druNp linux-libre-3.1-gnu1/Documentation/bus-virt-phys-mapping.txt linux-libre-3.2-gnu1/Documentation/bus-virt-phys-mapping.txt
--- linux-libre-3.1-gnu1/Documentation/bus-virt-phys-mapping.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/bus-virt-phys-mapping.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 [ NOTE: The virt_to_bus() and bus_to_virt() functions have been
 	superseded by the functionality provided by the PCI DMA interface
-	(see Documentation/PCI/PCI-DMA-mapping.txt).  They continue
+	(see Documentation/DMA-API-HOWTO.txt).  They continue
 	to be documented below for historical purposes, but new code
 	must not use them. --davidm 00/12/12 ]
 
diff -druNp linux-libre-3.1-gnu1/Documentation/cdrom/packet-writing.txt linux-libre-3.2-gnu1/Documentation/cdrom/packet-writing.txt
--- linux-libre-3.1-gnu1/Documentation/cdrom/packet-writing.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/cdrom/packet-writing.txt	2012-01-04 18:55:44.000000000 -0500
@@ -109,7 +109,7 @@ this interface. (see http://tom.ist-im-w
 
 For a description of the sysfs interface look into the file:
 
-  Documentation/ABI/testing/sysfs-block-pktcdvd
+  Documentation/ABI/testing/sysfs-class-pktcdvd
 
 
 Using the pktcdvd debugfs interface
diff -druNp linux-libre-3.1-gnu1/Documentation/cgroups/cgroups.txt linux-libre-3.2-gnu1/Documentation/cgroups/cgroups.txt
--- linux-libre-3.1-gnu1/Documentation/cgroups/cgroups.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/cgroups/cgroups.txt	2012-01-04 18:55:44.000000000 -0500
@@ -454,8 +454,8 @@ mounted hierarchy, to remove a task from
 move it into a new cgroup (possibly the root cgroup) by writing to the
 new cgroup's tasks file.
 
-Note: If the ns cgroup is active, moving a process to another cgroup can
-fail.
+Note: Due to some restrictions enforced by some cgroup subsystems, moving
+a process to another cgroup can fail.
 
 2.3 Mounting hierarchies by name
 --------------------------------
diff -druNp linux-libre-3.1-gnu1/Documentation/cgroups/freezer-subsystem.txt linux-libre-3.2-gnu1/Documentation/cgroups/freezer-subsystem.txt
--- linux-libre-3.1-gnu1/Documentation/cgroups/freezer-subsystem.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/cgroups/freezer-subsystem.txt	2012-01-04 18:55:44.000000000 -0500
@@ -33,9 +33,9 @@ demonstrate this problem using nested ba
 
 	From a second, unrelated bash shell:
 	$ kill -SIGSTOP 16690
-	$ kill -SIGCONT 16990
+	$ kill -SIGCONT 16690
 
-	<at this point 16990 exits and causes 16644 to exit too>
+	<at this point 16690 exits and causes 16644 to exit too>
 
 This happens because bash can observe both signals and choose how it
 responds to them.
diff -druNp linux-libre-3.1-gnu1/Documentation/cgroups/memory.txt linux-libre-3.2-gnu1/Documentation/cgroups/memory.txt
--- linux-libre-3.1-gnu1/Documentation/cgroups/memory.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/cgroups/memory.txt	2012-01-04 18:55:44.000000000 -0500
@@ -418,7 +418,6 @@ total_unevictable	- sum of all children'
 
 # The following additional stats are dependent on CONFIG_DEBUG_VM.
 
-inactive_ratio		- VM internal parameter. (see mm/page_alloc.c)
 recent_rotated_anon	- VM internal parameter. (see mm/vmscan.c)
 recent_rotated_file	- VM internal parameter. (see mm/vmscan.c)
 recent_scanned_anon	- VM internal parameter. (see mm/vmscan.c)
diff -druNp linux-libre-3.1-gnu1/Documentation/CodingStyle linux-libre-3.2-gnu1/Documentation/CodingStyle
--- linux-libre-3.1-gnu1/Documentation/CodingStyle	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/CodingStyle	2012-01-04 18:55:44.000000000 -0500
@@ -166,8 +166,8 @@ if (condition)
 else
 	do_that();
 
-This does not apply if one branch of a conditional statement is a single
-statement. Use braces in both branches.
+This does not apply if only one branch of a conditional statement is a single
+statement; in the latter case use braces in both branches:
 
 if (condition) {
 	do_this();
diff -druNp linux-libre-3.1-gnu1/Documentation/cpu-freq/governors.txt linux-libre-3.2-gnu1/Documentation/cpu-freq/governors.txt
--- linux-libre-3.1-gnu1/Documentation/cpu-freq/governors.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/cpu-freq/governors.txt	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@ The sampling rate is limited by the HW t
 transition_latency * 100
 Or by kernel restrictions:
 If CONFIG_NO_HZ is set, the limit is 10ms fixed.
-If CONFIG_NO_HZ is not set or no_hz=off boot parameter is used, the
+If CONFIG_NO_HZ is not set or nohz=off boot parameter is used, the
 limits depend on the CONFIG_HZ option:
 HZ=1000: min=20000us  (20ms)
 HZ=250:  min=80000us  (80ms)
diff -druNp linux-libre-3.1-gnu1/Documentation/development-process/4.Coding linux-libre-3.2-gnu1/Documentation/development-process/4.Coding
--- linux-libre-3.1-gnu1/Documentation/development-process/4.Coding	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/development-process/4.Coding	2012-01-04 18:55:44.000000000 -0500
@@ -278,7 +278,7 @@ enabled, a configurable percentage of me
 fail; these failures can be restricted to a specific range of code.
 Running with fault injection enabled allows the programmer to see how the
 code responds when things go badly.  See
-Documentation/fault-injection/fault-injection.text for more information on
+Documentation/fault-injection/fault-injection.txt for more information on
 how to use this facility.
 
 Other kinds of errors can be found with the "sparse" static analysis tool.
diff -druNp linux-libre-3.1-gnu1/Documentation/device-mapper/dm-log.txt linux-libre-3.2-gnu1/Documentation/device-mapper/dm-log.txt
--- linux-libre-3.1-gnu1/Documentation/device-mapper/dm-log.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/device-mapper/dm-log.txt	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,7 @@ kernel and userspace, 'connector' is use
 communication.
 
 There are currently two userspace log implementations that leverage this
-framework - "clustered_disk" and "clustered_core".  These implementations
+framework - "clustered-disk" and "clustered-core".  These implementations
 provide a cluster-coherent log for shared-storage.  Device-mapper mirroring
 can be used in a shared-storage environment when the cluster log implementations
 are employed.
diff -druNp linux-libre-3.1-gnu1/Documentation/device-mapper/persistent-data.txt linux-libre-3.2-gnu1/Documentation/device-mapper/persistent-data.txt
--- linux-libre-3.1-gnu1/Documentation/device-mapper/persistent-data.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/device-mapper/persistent-data.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,84 @@
+Introduction
+============
+
+The more-sophisticated device-mapper targets require complex metadata
+that is managed in kernel.  In late 2010 we were seeing that various
+different targets were rolling their own data strutures, for example:
+
+- Mikulas Patocka's multisnap implementation
+- Heinz Mauelshagen's thin provisioning target
+- Another btree-based caching target posted to dm-devel
+- Another multi-snapshot target based on a design of Daniel Phillips
+
+Maintaining these data structures takes a lot of work, so if possible
+we'd like to reduce the number.
+
+The persistent-data library is an attempt to provide a re-usable
+framework for people who want to store metadata in device-mapper
+targets.  It's currently used by the thin-provisioning target and an
+upcoming hierarchical storage target.
+
+Overview
+========
+
+The main documentation is in the header files which can all be found
+under drivers/md/persistent-data.
+
+The block manager
+-----------------
+
+dm-block-manager.[hc]
+
+This provides access to the data on disk in fixed sized-blocks.  There
+is a read/write locking interface to prevent concurrent accesses, and
+keep data that is being used in the cache.
+
+Clients of persistent-data are unlikely to use this directly.
+
+The transaction manager
+-----------------------
+
+dm-transaction-manager.[hc]
+
+This restricts access to blocks and enforces copy-on-write semantics.
+The only way you can get hold of a writable block through the
+transaction manager is by shadowing an existing block (ie. doing
+copy-on-write) or allocating a fresh one.  Shadowing is elided within
+the same transaction so performance is reasonable.  The commit method
+ensures that all data is flushed before it writes the superblock.
+On power failure your metadata will be as it was when last committed.
+
+The Space Maps
+--------------
+
+dm-space-map.h
+dm-space-map-metadata.[hc]
+dm-space-map-disk.[hc]
+
+On-disk data structures that keep track of reference counts of blocks.
+Also acts as the allocator of new blocks.  Currently two
+implementations: a simpler one for managing blocks on a different
+device (eg. thinly-provisioned data blocks); and one for managing
+the metadata space.  The latter is complicated by the need to store
+its own data within the space it's managing.
+
+The data structures
+-------------------
+
+dm-btree.[hc]
+dm-btree-remove.c
+dm-btree-spine.c
+dm-btree-internal.h
+
+Currently there is only one data structure, a hierarchical btree.
+There are plans to add more.  For example, something with an
+array-like interface would see a lot of use.
+
+The btree is 'hierarchical' in that you can define it to be composed
+of nested btrees, and take multiple keys.  For example, the
+thin-provisioning target uses a btree with two levels of nesting.
+The first maps a device id to a mapping tree, and that in turn maps a
+virtual block to a physical block.
+
+Values stored in the btrees can have arbitrary size.  Keys are always
+64bits, although nesting allows you to use multiple keys.
diff -druNp linux-libre-3.1-gnu1/Documentation/device-mapper/thin-provisioning.txt linux-libre-3.2-gnu1/Documentation/device-mapper/thin-provisioning.txt
--- linux-libre-3.1-gnu1/Documentation/device-mapper/thin-provisioning.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/device-mapper/thin-provisioning.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,285 @@
+Introduction
+============
+
+This document descibes a collection of device-mapper targets that
+between them implement thin-provisioning and snapshots.
+
+The main highlight of this implementation, compared to the previous
+implementation of snapshots, is that it allows many virtual devices to
+be stored on the same data volume.  This simplifies administration and
+allows the sharing of data between volumes, thus reducing disk usage.
+
+Another significant feature is support for an arbitrary depth of
+recursive snapshots (snapshots of snapshots of snapshots ...).  The
+previous implementation of snapshots did this by chaining together
+lookup tables, and so performance was O(depth).  This new
+implementation uses a single data structure to avoid this degradation
+with depth.  Fragmentation may still be an issue, however, in some
+scenarios.
+
+Metadata is stored on a separate device from data, giving the
+administrator some freedom, for example to:
+
+- Improve metadata resilience by storing metadata on a mirrored volume
+  but data on a non-mirrored one.
+
+- Improve performance by storing the metadata on SSD.
+
+Status
+======
+
+These targets are very much still in the EXPERIMENTAL state.  Please
+do not yet rely on them in production.  But do experiment and offer us
+feedback.  Different use cases will have different performance
+characteristics, for example due to fragmentation of the data volume.
+
+If you find this software is not performing as expected please mail
+dm-devel@redhat.com with details and we'll try our best to improve
+things for you.
+
+Userspace tools for checking and repairing the metadata are under
+development.
+
+Cookbook
+========
+
+This section describes some quick recipes for using thin provisioning.
+They use the dmsetup program to control the device-mapper driver
+directly.  End users will be advised to use a higher-level volume
+manager such as LVM2 once support has been added.
+
+Pool device
+-----------
+
+The pool device ties together the metadata volume and the data volume.
+It maps I/O linearly to the data volume and updates the metadata via
+two mechanisms:
+
+- Function calls from the thin targets
+
+- Device-mapper 'messages' from userspace which control the creation of new
+  virtual devices amongst other things.
+
+Setting up a fresh pool device
+------------------------------
+
+Setting up a pool device requires a valid metadata device, and a
+data device.  If you do not have an existing metadata device you can
+make one by zeroing the first 4k to indicate empty metadata.
+
+    dd if=/dev/zero of=$metadata_dev bs=4096 count=1
+
+The amount of metadata you need will vary according to how many blocks
+are shared between thin devices (i.e. through snapshots).  If you have
+less sharing than average you'll need a larger-than-average metadata device.
+
+As a guide, we suggest you calculate the number of bytes to use in the
+metadata device as 48 * $data_dev_size / $data_block_size but round it up
+to 2MB if the answer is smaller.  The largest size supported is 16GB.
+
+If you're creating large numbers of snapshots which are recording large
+amounts of change, you may need find you need to increase this.
+
+Reloading a pool table
+----------------------
+
+You may reload a pool's table, indeed this is how the pool is resized
+if it runs out of space.  (N.B. While specifying a different metadata
+device when reloading is not forbidden at the moment, things will go
+wrong if it does not route I/O to exactly the same on-disk location as
+previously.)
+
+Using an existing pool device
+-----------------------------
+
+    dmsetup create pool \
+	--table "0 20971520 thin-pool $metadata_dev $data_dev \
+		 $data_block_size $low_water_mark"
+
+$data_block_size gives the smallest unit of disk space that can be
+allocated at a time expressed in units of 512-byte sectors.  People
+primarily interested in thin provisioning may want to use a value such
+as 1024 (512KB).  People doing lots of snapshotting may want a smaller value
+such as 128 (64KB).  If you are not zeroing newly-allocated data,
+a larger $data_block_size in the region of 256000 (128MB) is suggested.
+$data_block_size must be the same for the lifetime of the
+metadata device.
+
+$low_water_mark is expressed in blocks of size $data_block_size.  If
+free space on the data device drops below this level then a dm event
+will be triggered which a userspace daemon should catch allowing it to
+extend the pool device.  Only one such event will be sent.
+Resuming a device with a new table itself triggers an event so the
+userspace daemon can use this to detect a situation where a new table
+already exceeds the threshold.
+
+Thin provisioning
+-----------------
+
+i) Creating a new thinly-provisioned volume.
+
+  To create a new thinly- provisioned volume you must send a message to an
+  active pool device, /dev/mapper/pool in this example.
+
+    dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+  Here '0' is an identifier for the volume, a 24-bit number.  It's up
+  to the caller to allocate and manage these identifiers.  If the
+  identifier is already in use, the message will fail with -EEXIST.
+
+ii) Using a thinly-provisioned volume.
+
+  Thinly-provisioned volumes are activated using the 'thin' target:
+
+    dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
+
+  The last parameter is the identifier for the thinp device.
+
+Internal snapshots
+------------------
+
+i) Creating an internal snapshot.
+
+  Snapshots are created with another message to the pool.
+
+  N.B.  If the origin device that you wish to snapshot is active, you
+  must suspend it before creating the snapshot to avoid corruption.
+  This is NOT enforced at the moment, so please be careful!
+
+    dmsetup suspend /dev/mapper/thin
+    dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
+    dmsetup resume /dev/mapper/thin
+
+  Here '1' is the identifier for the volume, a 24-bit number.  '0' is the
+  identifier for the origin device.
+
+ii) Using an internal snapshot.
+
+  Once created, the user doesn't have to worry about any connection
+  between the origin and the snapshot.  Indeed the snapshot is no
+  different from any other thinly-provisioned device and can be
+  snapshotted itself via the same method.  It's perfectly legal to
+  have only one of them active, and there's no ordering requirement on
+  activating or removing them both.  (This differs from conventional
+  device-mapper snapshots.)
+
+  Activate it exactly the same way as any other thinly-provisioned volume:
+
+    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
+
+Deactivation
+------------
+
+All devices using a pool must be deactivated before the pool itself
+can be.
+
+    dmsetup remove thin
+    dmsetup remove snap
+    dmsetup remove pool
+
+Reference
+=========
+
+'thin-pool' target
+------------------
+
+i) Constructor
+
+    thin-pool <metadata dev> <data dev> <data block size (sectors)> \
+	      <low water mark (blocks)> [<number of feature args> [<arg>]*]
+
+    Optional feature arguments:
+    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+    Data block size must be between 64KB (128 sectors) and 1GB
+    (2097152 sectors) inclusive.
+
+
+ii) Status
+
+    <transaction id> <used metadata blocks>/<total metadata blocks>
+    <used data blocks>/<total data blocks> <held metadata root>
+
+
+    transaction id:
+	A 64-bit number used by userspace to help synchronise with metadata
+	from volume managers.
+
+    used data blocks / total data blocks
+	If the number of free blocks drops below the pool's low water mark a
+	dm event will be sent to userspace.  This event is edge-triggered and
+	it will occur only once after each resume so volume manager writers
+	should register for the event and then check the target's status.
+
+    held metadata root:
+	The location, in sectors, of the metadata root that has been
+	'held' for userspace read access.  '-' indicates there is no
+	held root.  This feature is not yet implemented so '-' is
+	always returned.
+
+iii) Messages
+
+    create_thin <dev id>
+
+	Create a new thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+
+    create_snap <dev id> <origin id>
+
+	Create a new snapshot of another thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+	<origin id> is the identifier of the thinly-provisioned device
+	of which the new device will be a snapshot.
+
+    delete <dev id>
+
+	Deletes a thin device.  Irreversible.
+
+    trim <dev id> <new size in sectors>
+
+	Delete mappings from the end of a thin device.  Irreversible.
+	You might want to use this if you're reducing the size of
+	your thinly-provisioned device.  In many cases, due to the
+	sharing of blocks between devices, it is not possible to
+	determine in advance how much space 'trim' will release.  (In
+	future a userspace tool might be able to perform this
+	calculation.)
+
+    set_transaction_id <current id> <new id>
+
+	Userland volume managers, such as LVM, need a way to
+	synchronise their external metadata with the internal metadata of the
+	pool target.  The thin-pool target offers to store an
+	arbitrary 64-bit transaction id and return it on the target's
+	status line.  To avoid races you must provide what you think
+	the current transaction id is when you change it with this
+	compare-and-swap message.
+
+'thin' target
+-------------
+
+i) Constructor
+
+    thin <pool dev> <dev id>
+
+    pool dev:
+	the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
+
+    dev id:
+	the internal device identifier of the device to be
+	activated.
+
+The pool doesn't store any size against the thin devices.  If you
+load a thin target that is smaller than you've been using previously,
+then you'll have no access to blocks mapped beyond the end.  If you
+load a target that is bigger than before, then extra blocks will be
+provisioned as and when needed.
+
+If you wish to reduce the size of your thin device and potentially
+regain some space then send the 'trim' message to the pool.
+
+ii) Status
+
+     <nr mapped sectors> <highest mapped sector>
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/calxeda.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/calxeda.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/calxeda.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/calxeda.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+Calxeda Highbank Platforms Device Tree Bindings
+-----------------------------------------------
+
+Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
+properties.
+
+Required root node properties:
+    - compatible = "calxeda,highbank";
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/fsl.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/fsl.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/fsl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/fsl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+Freescale i.MX Platforms Device Tree Bindings
+-----------------------------------------------
+
+i.MX51 Babbage Board
+Required root node properties:
+    - compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+i.MX53 Automotive Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-ard", "fsl,imx53";
+
+i.MX53 Evaluation Kit
+Required root node properties:
+    - compatible = "fsl,imx53-evk", "fsl,imx53";
+
+i.MX53 Quick Start Board
+Required root node properties:
+    - compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+i.MX53 Smart Mobile Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-smd", "fsl,imx53";
+
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+    - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/gic.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/gic.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/gic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/gic.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/l2cc.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/l2cc.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/l2cc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/l2cc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+* ARM L2 Cache Controller
+
+ARM cores often have a separate level 2 cache controller. There are various
+implementations of the L2 cache controller with compatible programming models.
+The ARM L2 cache representation in the device tree should be done as follows:
+
+Required properties:
+
+- compatible : should be one of:
+	"arm,pl310-cache"
+	"arm,l220-cache"
+	"arm,l210-cache"
+- cache-unified : Specifies the cache is a unified cache.
+- cache-level : Should be set to 2 for a level 2 cache.
+- reg : Physical base address and size of cache controller's memory mapped
+  registers.
+
+Optional properties:
+
+- arm,data-latency : Cycles of latency for Data RAM accesses. Specifies 3 cells of
+  read, write and setup latencies. Minimum valid values are 1. Controllers
+  without setup latency control should use a value of 0.
+- arm,tag-latency : Cycles of latency for Tag RAM accesses. Specifies 3 cells of
+  read, write and setup latencies. Controllers without setup latency control
+  should use 0. Controllers without separate read and write Tag RAM latency
+  values should only use the first cell.
+- arm,dirty-latency : Cycles of latency for Dirty RAMs. This is a single cell.
+- arm,filter-ranges : <start length> Starting address and length of window to
+  filter. Addresses in the filter window are directed to the M1 port. Other
+  addresses will go to the M0 port.
+- interrupts : 1 combined interrupt.
+
+Example:
+
+L2: cache-controller {
+        compatible = "arm,pl310-cache";
+        reg = <0xfff12000 0x1000>;
+        arm,data-latency = <1 1 1>;
+        arm,tag-latency = <2 2 2>;
+        arm,filter-latency = <0x80000000 0x8000000>;
+        cache-unified;
+        cache-level = <2>;
+	interrupts = <45>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/dsp.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/dsp.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/dsp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/dsp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+* TI - DSP (Digital Signal Processor)
+
+TI DSP included in OMAP SoC
+
+Required properties:
+- compatible : Should be "ti,omap3-c64" for OMAP3 & 4
+- ti,hwmods: "dsp"
+
+Examples:
+
+dsp {
+    compatible = "ti,omap3-c64";
+    ti,hwmods = "dsp";
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/iva.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/iva.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/iva.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/iva.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+* TI - IVA (Imaging and Video Accelerator) subsystem
+
+The IVA contain various audio, video or imaging HW accelerator
+depending of the version.
+
+Required properties:
+- compatible : Should be:
+  - "ti,ivahd" for OMAP4
+  - "ti,iva2.2" for OMAP3
+  - "ti,iva2.1" for OMAP2430
+  - "ti,iva1" for OMAP2420
+- ti,hwmods: "iva"
+
+Examples:
+
+iva {
+    compatible = "ti,ivahd", "ti,iva";
+    ti,hwmods = "iva";
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/l3-noc.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/l3-noc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/l3-noc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+* TI - L3 Network On Chip (NoC)
+
+This version is an implementation of the generic NoC IP
+provided by Arteris.
+
+Required properties:
+- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
+               Should be "ti,omap4-l3-noc" for OMAP4 family
+- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.
+
+Examples:
+
+ocp {
+	compatible = "ti,omap4-l3-noc", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/mpu.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/mpu.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/mpu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/mpu.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* TI - MPU (Main Processor Unit) subsystem
+
+The MPU subsystem contain one or several ARM cores
+depending of the version.
+The MPU contain CPUs, GIC, L2 cache and a local PRCM.
+
+Required properties:
+- compatible : Should be "ti,omap3-mpu" for OMAP3
+               Should be "ti,omap4-mpu" for OMAP4
+- ti,hwmods: "mpu"
+
+Examples:
+
+- For an OMAP4 SMP system:
+
+mpu {
+    compatible = "ti,omap4-mpu";
+    ti,hwmods = "mpu";
+};
+
+
+- For an OMAP3 monocore system:
+
+mpu {
+    compatible = "ti,omap3-mpu";
+    ti,hwmods = "mpu";
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/omap.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/omap/omap.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/omap/omap.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+  form: "ti,XXX"
+- ti,hwmods: list of hwmod names (ascii strings), that comes from the OMAP
+  HW documentation, attached to a device. Must contain at least
+  one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+  during suspend.
+
+
+Example:
+
+spinlock@1 {
+    compatible = "ti,omap4-spinlock";
+    ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+  compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+  compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+  compatible = "ti,omap4-panda", "ti,omap4430"
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/picoxcell.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/picoxcell.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/picoxcell.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/picoxcell.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+Picochip picoXcell device tree bindings.
+========================================
+
+Required root node properties:
+    - compatible:
+	- "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device.
+	- "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device.
+	- "picochip,pc3x3" : picoXcell PC3X3 device based board.
+	- "picochip,pc3x2" : picoXcell PC3X2 device based board.
+
+Timers required properties:
+    - compatible = "picochip,pc3x2-timer"
+    - interrupts : The single IRQ line for the timer.
+    - clock-freq : The frequency in HZ of the timer.
+    - reg : The register bank for the timer.
+
+Note: two timers are required - one for the scheduler clock and one for the
+event tick/NOHZ.
+
+VIC required properties:
+    - compatible = "arm,pl192-vic".
+    - interrupt-controller.
+    - reg : The register bank for the device.
+    - #interrupt-cells : Must be 1.
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/primecell.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/primecell.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/arm/primecell.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/arm/primecell.txt	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,9 @@ driver matching.
 
 Required properties:
 
-- compatible : should be a specific value for peripheral and "arm,primecell"
+- compatible : should be a specific name for the peripheral and
+               "arm,primecell".  The specific name will match the ARM
+               engineering name for the logic block in the form: "arm,pl???"
 
 Optional properties:
 
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/ata/calxeda-sata.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/ata/calxeda-sata.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/ata/calxeda-sata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/ata/calxeda-sata.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+* Calxeda SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "calxeda,hb-ahci"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- reg               : <registers mapping>
+
+Example:
+        sata@ffe08000 {
+		compatible = "calxeda,hb-ahci";
+                reg = <0xffe08000 0x1000>;
+                interrupts = <115>;
+        };
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/crypto/picochip-spacc.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/crypto/picochip-spacc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/crypto/picochip-spacc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings
+
+Picochip picoXcell devices contain crypto offload engines that may be used for
+IPSEC and femtocell layer 2 ciphering.
+
+Required properties:
+  - compatible : "picochip,spacc-ipsec" for the IPSEC offload engine
+    "picochip,spacc-l2" for the femtocell layer 2 ciphering engine.
+  - reg : Offset and length of the register set for this device
+  - interrupt-parent : The interrupt controller that controls the SPAcc
+    interrupt.
+  - interrupts : The interrupt line from the SPAcc.
+  - ref-clock : The input clock that drives the SPAcc.
+
+Example SPAcc node:
+
+spacc@10000 {
+	compatible = "picochip,spacc-ipsec";
+	reg = <0x100000 0x10000>;
+	interrupt-parent = <&vic0>;
+	interrupts = <24>;
+	ref-clock = <&ipsec_clk>, "ref";
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/gpio/led.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/gpio/led.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/gpio/led.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/gpio/led.txt	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@ node's name represents the name of the c
 
 LED sub-node properties:
 - gpios :  Should specify the LED's GPIO, see "Specifying GPIO information
-  for devices" in Documentation/powerpc/booting-without-of.txt.  Active
+  for devices" in Documentation/devicetree/booting-without-of.txt.  Active
   low LEDs should be indicated using flags in the GPIO specifier.
 - label :  (optional) The label for this LED.  If omitted, the label is
   taken from the node name (excluding the unit address).
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/gpio/pl061-gpio.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/gpio/pl061-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/gpio/pl061-gpio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+ARM PL061 GPIO controller
+
+Required properties:
+- compatible : "arm,pl061", "arm,primecell"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupts : Interrupt mapping for GPIO IRQ.
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x83fc4000 0x4000>;
+	interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x70038000 0x4000>;
+	interrupts = <64>;
+	clock-frequency = <400000>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/i2c/samsung-i2c.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/i2c/samsung-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/i2c/samsung-i2c.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+* Samsung's I2C controller
+
+The Samsung's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
+      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
+  - reg: physical base address of the controller and length of memory mapped
+    region.
+  - interrupts: interrupt number to the cpu.
+  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
+  - gpios: The order of the gpios should be the following: <SDA, SCL>.
+    The gpio specifier depends on the gpio controller.
+
+Optional properties:
+  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
+    specified, default value is 0.
+  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
+    specified, the default value in Hz is 100000.
+
+Example:
+
+	i2c@13870000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13870000 0x100>;
+		interrupts = <345>;
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <100000>;
+		gpios = <&gpd1 2 0 /* SDA */
+			 &gpd1 3 0 /* SCL */>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wm8994@1a {
+			compatible = "wlf,wm8994";
+			reg = <0x1a>;
+		};
+	};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* NVIDIA Tegra Secure Digital Host Controller
+
+This controller on Tegra family SoCs provides an interface for MMC, SD,
+and SDIO types of memory cards.
+
+Required properties:
+- compatible : Should be "nvidia,<chip>-sdhci"
+- reg : Should contain SD/MMC registers location and length
+- interrupts : Should contain SD/MMC interrupt
+
+Optional properties:
+- cd-gpios : Specify GPIOs for card detection
+- wp-gpios : Specify GPIOs for write protection
+- power-gpios : Specify GPIOs for power control
+- support-8bit : Boolean, indicates if 8-bit mode should be used.
+
+Example:
+
+sdhci@c8000200 {
+	compatible = "nvidia,tegra20-sdhci";
+	reg = <0xc8000200 0x200>;
+	interrupts = <47>;
+	cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+	wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+	power-gpios = <&gpio 155 0>; /* gpio PT3 */
+	support-8bit;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+* Atmel Data Flash
+
+Required properties:
+- compatible : "atmel,<model>", "atmel,<series>", "atmel,dataflash".
+
+Example:
+
+flash@1 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+	spi-max-frequency = <25000000>;
+	reg = <1>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,24 @@
-CAN Device Tree Bindings
-------------------------
-2011 Freescale Semiconductor, Inc.
-
-fsl,flexcan-v1.0 nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source shall be used for the controller.
+Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
 
-CPI Clock- Can Protocol Interface Clock
-	This CLK_SRC bit of CTRL(control register) selects the clock source to
-	the CAN Protocol Interface(CPI) to be either the peripheral clock
-	(driven by the PLL) or the crystal oscillator clock. The selected clock
-	is the one fed to the prescaler to generate the Serial Clock (Sclock).
-	The PRESDIV field of CTRL(control register) controls a prescaler that
-	generates the Serial Clock (Sclock), whose period defines the
-	time quantum used to compose the CAN waveform.
+Required properties:
 
-Can Engine Clock Source
-	There are two sources for CAN clock
-	- Platform Clock  It represents the bus clock
-	- Oscillator Clock
+- compatible : Should be "fsl,<processor>-flexcan"
 
-	Peripheral Clock (PLL)
-	--------------
-		     |
-		    ---------		      -------------
-		    |       |CPI Clock	      | Prescaler |       Sclock
-		    |       |---------------->| (1.. 256) |------------>
-		    ---------		      -------------
-                     |  |
-	--------------  ---------------------CLK_SRC
-	Oscillator Clock
+  An implementation should also claim any of the following compatibles
+  that it is fully backwards compatible with:
 
-- fsl,flexcan-clock-source : CAN Engine Clock Source.This property selects
-			     the peripheral clock. PLL clock is fed to the
-			     prescaler to generate the Serial Clock (Sclock).
-			     Valid values are "oscillator" and "platform"
-			     "oscillator": CAN engine clock source is oscillator clock.
-			     "platform" The CAN engine clock source is the bus clock
-		             (platform clock).
+  - fsl,p1010-flexcan
 
-- fsl,flexcan-clock-divider : for the reference and system clock, an additional
-			      clock divider can be specified.
-- clock-frequency: frequency required to calculate the bitrate for FlexCAN.
+- reg : Offset and length of the register set for this device
+- interrupts : Interrupt tuple for this device
+- clock-frequency : The oscillator frequency driving the flexcan device
 
-Note:
-	- v1.0 of flexcan-v1.0 represent the IP block version for P1010 SOC.
-	- P1010 does not have oscillator as the Clock Source.So the default
-	  Clock Source is platform clock.
-Examples:
+Example:
 
-	can0@1c000 {
-		compatible = "fsl,flexcan-v1.0";
+	can@1c000 {
+		compatible = "fsl,p1010-flexcan";
 		reg = <0x1c000 0x1000>;
 		interrupts = <48 0x2>;
 		interrupt-parent = <&mpic>;
-		fsl,flexcan-clock-source = "platform";
-		fsl,flexcan-clock-divider = <2>;
-		clock-frequency = <fixed by u-boot>;
+		clock-frequency = <200000000>; // filled in by bootloader
 	};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/net/smsc911x.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/net/smsc911x.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/net/smsc911x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/net/smsc911x.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,38 @@
+* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller
+
+Required properties:
+- compatible : Should be "smsc,lan<model>", "smsc,lan9115"
+- reg : Address and length of the io space for SMSC LAN
+- interrupts : Should contain SMSC LAN interrupt line
+- interrupt-parent : Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- phy-mode : String, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+
+Optional properties:
+- reg-shift : Specify the quantity to shift the register offsets by
+- reg-io-width : Specify the size (in bytes) of the IO accesses that
+  should be performed on the device.  Valid value for SMSC LAN is
+  2 or 4.  If it's omitted or invalid, the size would be 2.
+- smsc,irq-active-high : Indicates the IRQ polarity is active-high
+- smsc,irq-push-pull : Indicates the IRQ type is push-pull
+- smsc,force-internal-phy : Forces SMSC LAN controller to use
+  internal PHY
+- smsc,force-external-phy : Forces SMSC LAN controller to use
+  external PHY
+- smsc,save-mac-address : Indicates that mac address needs to be saved
+  before resetting the controller
+- local-mac-address : 6 bytes, mac address
+
+Examples:
+
+lan9220@f4000000 {
+	compatible = "smsc,lan9220", "smsc,lan9115";
+	reg = <0xf4000000 0x2000000>;
+	phy-mode = "mii";
+	interrupt-parent = <&gpio1>;
+	interrupts = <31>;
+	reg-io-width = <4>;
+	smsc,irq-push-pull;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,8 @@
+Freescale Reference Board Bindings
+
+This document describes device tree bindings for various devices that
+exist on some Freescale reference boards.
+
 * Board Control and Status (BCSR)
 
 Required properties:
@@ -12,25 +17,26 @@ Example:
 		reg = <f8000000 8000>;
 	};
 
-* Freescale on board FPGA
+* Freescale on-board FPGA
 
 This is the memory-mapped registers for on board FPGA.
 
 Required properities:
-- compatible : should be "fsl,fpga-pixis".
-- reg : should contain the address and the length of the FPPGA register
-  set.
+- compatible: should be a board-specific string followed by a string
+  indicating the type of FPGA.  Example:
+	"fsl,<board>-fpga", "fsl,fpga-pixis"
+- reg: should contain the address and the length of the FPGA register set.
 - interrupt-parent: should specify phandle for the interrupt controller.
-- interrupts : should specify event (wakeup) IRQ.
+- interrupts: should specify event (wakeup) IRQ.
 
-Example (MPC8610HPCD):
+Example (P1022DS):
 
-	board-control@e8000000 {
-		compatible = "fsl,fpga-pixis";
-		reg = <0xe8000000 32>;
-		interrupt-parent = <&mpic>;
-		interrupts = <8 8>;
-	};
+	 board-control@3,0 {
+		 compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
+		 reg = <3 0 0x30>;
+		 interrupt-parent = <&mpic>;
+		 interrupts = <8 8 0 0>;
+	 };
 
 * Freescale BCSR GPIO banks
 
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,395 @@
+===================================================================
+Debug Control and Status Register (DCSR) Binding
+Copyright 2011 Freescale Semiconductor Inc.
+
+NOTE: The bindings described in this document are preliminary and subject
+to change.  Some of the compatible strings that contain only generic names
+may turn out to be inappropriate, or need additional properties to describe
+the integration of the block with the rest of the chip.
+
+=====================================================================
+Debug Control and Status Register Memory Map
+
+Description
+
+This node defines the base address and range for the
+defined DCSR Memory Map. Child nodes will describe the individual
+debug blocks defined within this memory space.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr" and "simple-bus".
+	The DCSR space exists in the memory-mapped bus.
+
+	- #address-cells
+	Usage: required
+	Value type: <u32>
+	Definition: A standard property.  Defines the number of cells
+	or representing physical addresses in child nodes.
+
+	- #size-cells
+	Usage: required
+	Value type: <u32>
+	Definition: A standard property.  Defines the number of cells
+	or representing the size of physical addresses in
+	child nodes.
+
+	- ranges
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property. Specifies the physical address
+	range of the DCSR space.
+
+EXAMPLE
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+=====================================================================
+Event Processing Unit
+
+This node represents the region of DCSR space allocated to the EPU
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-epu"
+
+	- interrupts
+	Usage: required
+	Value type: <prop_encoded-array>
+	Definition:  Specifies the interrupts generated by the EPU.
+	The value of the interrupts property consists of three
+	interrupt specifiers. The format of the specifier is defined
+	by the binding document describing the node's interrupt parent.
+
+	The EPU counters can be configured to assert the performance
+	monitor interrupt signal based on either counter overflow or value
+	match. Which counter asserted the interrupt is captured in an EPU
+	Counter Interrupt Status Register (EPCPUISR).
+
+	The EPU unit can also be configured to assert either or both of
+	two interrupt signals based on debug event sources within the SoC.
+	The interrupt signals are epu_xt_int0 and epu_xt_int1.
+	Which event source asserted the interrupt is captured in an EPU
+	Interrupt Status Register (EPISR0,EPISR1).
+
+	Interrupt numbers are lised in order (perfmon, event0, event1).
+
+	- interrupt-parent
+	Usage: required
+	Value type: <phandle>
+	Definition: A single <phandle> value that points
+	to the interrupt parent to which the child domain
+	is being mapped. Value must be "&mpic"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+	dcsr-epu@0 {
+		compatible = "fsl,dcsr-epu";
+		interrupts = <52 2 0 0
+			      84 2 0 0
+			      85 2 0 0>;
+		interrupt-parent = <&mpic>;
+		reg = <0x0 0x1000>;
+	};
+
+=======================================================================
+Nexus Port Controller
+
+This node represents the region of DCSR space allocated to the NPC
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-npc"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+	The Nexus Port controller occupies two regions in the DCSR space
+	with distinct functionality.
+
+	The first register range describes the Nexus Port Controller
+	control and status registers.
+
+	The second register range describes the Nexus Port Controller
+	internal trace buffer. The NPC trace buffer is a small memory buffer
+	which stages the nexus trace data for transmission via the Aurora port
+	or to a DDR based trace buffer. In some configurations the NPC trace
+	buffer can be the only trace buffer used.
+
+
+EXAMPLE
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+
+=======================================================================
+Nexus Concentrator
+
+This node represents the region of DCSR space allocated to the NXC
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-nxc"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+=======================================================================
+CoreNet Debug Controller
+
+This node represents the region of DCSR space allocated to
+the CoreNet Debug controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-corenet"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+	The CoreNet Debug controller occupies two regions in the DCSR space
+	with distinct functionality.
+
+	The first register range describes the CoreNet Debug Controller
+	functionalty to perform transaction and transaction attribute matches.
+
+	The second register range describes the CoreNet Debug Controller
+	functionalty to trigger event notifications and debug traces.
+
+EXAMPLE
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+
+=======================================================================
+Data Path Debug controller
+
+This node represents the region of DCSR space allocated to
+the DPAA Debug Controller. This controller controls debug configuration
+for the QMAN and FMAN blocks.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-dpaa" in addition to the
+	generic compatible string "fsl,dcsr-dpaa".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+
+=======================================================================
+OCeaN Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-ocn" in addition to the
+	generic compatible string "fsl,dcsr-ocn".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-ocn@11000 {
+			compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+
+=======================================================================
+DDR Controller Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-ddr"
+
+	- dev-handle
+	Usage: required
+	Definition: A phandle to associate this debug node with its
+	component controller.
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+
+=======================================================================
+Nexus Aurora Link Controller
+
+This node represents the region of DCSR space allocated to
+the NAL Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-nal" in addition to the
+	generic compatible string "fsl,dcsr-nal".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-nal@18000 {
+			compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+
+
+=======================================================================
+Run Control and Power Management
+
+This node represents the region of DCSR space allocated to
+the RCPM Debug Controller. This functionlity is limited to the
+control the debug operations of the SoC and cores.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-rcpm" in addition to the
+	generic compatible string "fsl,dcsr-rcpm".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+
+=======================================================================
+Core Service Bridge Proxy
+
+This node represents the region of DCSR space allocated to
+the Core Service Bridge Proxies.
+There is one Core Service Bridge Proxy device for each CPU in the system.
+This functionlity provides access to the debug operations of the CPU.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the cpu
+	of the form "fsl,dcsr-<cpu>-sb-proxy" in addition to the
+	generic compatible string "fsl,dcsr-cpu-sb-proxy".
+
+	- cpu-handle
+	Usage: required
+	Definition: A phandle to associate this debug node with its cpu.
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy",
+				     "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy",
+				     "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+
+=======================================================================
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,16 @@ Required properties:
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
   to MPIC.
 
+Optional properties:
+- msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register
+  is used for MSI messaging.  The address of MSIIR in PCI address space is
+  the MSI message address.
+
+  This property may be used in virtualized environments where the hypervisor
+  has created an alternate mapping for the MSIR block.  See below for an
+  explanation.
+
+
 Example:
 	msi@41600 {
 		compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
@@ -41,3 +51,35 @@ Example:
 			0xe7 0>;
 		interrupt-parent = <&mpic>;
 	};
+
+The Freescale hypervisor and msi-address-64
+-------------------------------------------
+Normally, PCI devices have access to all of CCSR via an ATMU mapping.  The
+Freescale MSI driver calculates the address of MSIIR (in the MSI register
+block) and sets that address as the MSI message address.
+
+In a virtualized environment, the hypervisor may need to create an IOMMU
+mapping for MSIIR.  The Freescale ePAPR hypervisor has this requirement
+because of hardware limitations of the Peripheral Access Management Unit
+(PAMU), which is currently the only IOMMU that the hypervisor supports.
+The ATMU is programmed with the guest physical address, and the PAMU
+intercepts transactions and reroutes them to the true physical address.
+
+In the PAMU, each PCI controller is given only one primary window.  The
+PAMU restricts DMA operations so that they can only occur within a window.
+Because PCI devices must be able to DMA to memory, the primary window must
+be used to cover all of the guest's memory space.
+
+PAMU primary windows can be divided into 256 subwindows, and each
+subwindow can have its own address mapping ("guest physical" to "true
+physical").  However, each subwindow has to have the same alignment, which
+means they cannot be located at just any address.  Because of these
+restrictions, it is usually impossible to create a 4KB subwindow that
+covers MSIIR where it's normally located.
+
+Therefore, the hypervisor has to create a subwindow inside the same
+primary window used for memory, but mapped to the MSIR block (where MSIIR
+lives).  The first subwindow after the end of guest memory is used for
+this.  The address specified in the msi-address-64 property is the PCI
+address of MSIIR.  The hypervisor configures the PAMU to map that address to
+the true physical address of MSIIR.
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/serial/rs485.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/serial/rs485.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/serial/rs485.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/serial/rs485.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+* RS485 serial communications
+
+The RTS signal is capable of automatically controlling line direction for
+the built-in half-duplex mode.
+The properties described hereafter shall be given to a half-duplex capable
+UART node.
+
+Required properties:
+- rs485-rts-delay: prop-encoded-array <a b> where:
+  * a is the delay beteween rts signal and beginning of data sent in milliseconds.
+      it corresponds to the delay before sending data.
+  * b is the delay between end of data sent and rts signal in milliseconds
+      it corresponds to the delay after sending data and actual release of the line.
+
+Optional properties:
+- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
+  feature at boot time. It can be disabled later with proper ioctl.
+- rs485-rx-during-tx: empty property that enables the receiving of data even
+  whilst sending data.
+
+RS485 example for Atmel USART:
+	usart0: serial@fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+		linux,rs485-enabled-at-boot-time;
+		rs485-rts-delay = <0 200>;		// in milliseconds
+	};
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+* Freescale SGTL5000 Stereo Codec
+
+Required properties:
+- compatible : "fsl,sgtl5000".
+
+Example:
+
+codec: sgtl5000@0a {
+	compatible = "fsl,sgtl5000";
+	reg = <0x0a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8510.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8510.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8510.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8510.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8510 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8510"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8510@1a {
+	compatible = "wlf,wm8510";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8523.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8523.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8523.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8523.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8523 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8523"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8523@1a {
+	compatible = "wlf,wm8523";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8580.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8580.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8580.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8580.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8580 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8580"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8580@1a {
+	compatible = "wlf,wm8580";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8711.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8711.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8711.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8711.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8711 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8711"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8711@1a {
+	compatible = "wlf,wm8711";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8728.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8728.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8728.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8728.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8728 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8728"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8728@1a {
+	compatible = "wlf,wm8728";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8731.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8731.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8731.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8731.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8731 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8731"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8731@1a {
+	compatible = "wlf,wm8731";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8737.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8737.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8737.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8737.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8737 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8737"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+	compatible = "wlf,wm8737";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8741.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8741.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8741.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8741.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8741 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8741"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8741@1a {
+	compatible = "wlf,wm8741";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8750.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8750.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8750.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8750.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8750 and WM8987 audio CODECs
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8750" or "wlf,wm8987"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8750@1a {
+	compatible = "wlf,wm8750";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8753.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8753.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8753.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8753.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8753 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8753"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+	compatible = "wlf,wm8753";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8770.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8770.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8770.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8770.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8770 audio CODEC
+
+This device supports SPI.
+
+Required properties:
+
+  - compatible : "wlf,wm8770"
+
+  - reg : the chip select number.
+
+Example:
+
+codec: wm8770@1 {
+	compatible = "wlf,wm8770";
+	reg = <1>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8776.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8776.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8776.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8776.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8776 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8776"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8776@1a {
+	compatible = "wlf,wm8776";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8804.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8804.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/sound/wm8804.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/sound/wm8804.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8804 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8804"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8804@1a {
+	compatible = "wlf,wm8804";
+	reg = <0x1a>;
+};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/spi/spi_pl022.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/spi/spi_pl022.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/spi/spi_pl022.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/spi/spi_pl022.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+ARM PL022 SPI controller
+
+Required properties:
+- compatible : "arm,pl022", "arm,primecell"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain SPI controller interrupt
+
+Optional properties:
+- cs-gpios : should specify GPIOs used for chipselects.
+  The gpios will be referred to as reg = <index> in the SPI child nodes.
+  If unspecified, a single SPI device without a chip select can be used.
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-usart"
+  The compatible <chip> indicated will be the first SoC to support an
+  additional mode or an USART new feature.
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Optional properties:
+- atmel,use-dma-rx: use of PDC or DMA for receiving data
+- atmel,use-dma-tx: use of PDC or DMA for transmitting data
+
+<chip> compatible description:
+- at91rm9200:  legacy USART support
+- at91sam9260: generic USART implementation for SAM9 SoCs
+
+Example:
+
+	usart0: serial@fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+	};
+
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/msm_serial.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/msm_serial.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/msm_serial.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* Qualcomm MSM UART
+
+Required properties:
+- compatible :
+	- "qcom,msm-uart", and one of "qcom,msm-hsuart" or
+	  "qcom,msm-lsuart".
+- reg : offset and length of the register set for the device
+	for the hsuart operating in compatible mode, there should be a
+	second pair describing the gsbi registers.
+- interrupts : should contain the uart interrupt.
+
+There are two different UART blocks used in MSM devices,
+"qcom,msm-hsuart" and "qcom,msm-lsuart".  The msm-serial driver is
+able to handle both of these, and matches against the "qcom,msm-uart"
+as the compatibility.
+
+The registers for the "qcom,msm-hsuart" device need to specify both
+register blocks, even for the common driver.
+
+Example:
+
+	uart@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+* Synopsys DesignWare ABP UART
+
+Required properties:
+- compatible : "snps,dw-apb-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clock-frequency : the input clock frequency for the UART.
+
+Optional properties:
+- reg-shift : quantity to shift the register offsets by.  If this property is
+  not present then the register offsets are not shifted.
+- reg-io-width : the size (in bytes) of the IO accesses that should be
+  performed on the device.  If this property is not present then single byte
+  accesses are used.
+
+Example:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clock-frequency = <3686400>;
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/vendor-prefixes.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/vendor-prefixes.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/vendor-prefixes.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/vendor-prefixes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+Device tree binding vendor prefix registry.  Keep list in alphabetical order.
+
+This isn't an exhaustive list, but you should add new prefixes to it before
+using them to avoid name-space collisions.
+
+adi	Analog Devices, Inc.
+amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
+apm	Applied Micro Circuits Corporation (APM)
+arm	ARM Ltd.
+atmel	Atmel Corporation
+chrp	Common Hardware Reference Platform
+dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
+denx	Denx Software Engineering
+epson	Seiko Epson Corp.
+est	ESTeem Wireless Modems
+fsl	Freescale Semiconductor
+GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+hp	Hewlett Packard
+ibm	International Business Machines (IBM)
+idt	Integrated Device Technologies, Inc.
+intercontrol	Inter Control Group
+linux	Linux-specific binding
+marvell	Marvell Technology Group Ltd.
+maxim	Maxim Integrated Products
+mosaixtech	Mosaix Technologies, Inc.
+national	National Semiconductor
+nintendo	Nintendo
+nvidia	NVIDIA
+nxp	NXP Semiconductors
+powervr	Imagination Technologies
+qcom	Qualcomm, Inc.
+ramtron	Ramtron International
+samsung	Samsung Semiconductor
+schindler	Schindler
+sil	Silicon Image
+simtek
+sirf	SiRF Technology, Inc.
+stericsson	ST-Ericsson
+ti	Texas Instruments
+xlnx	Xilinx
diff -druNp linux-libre-3.1-gnu1/Documentation/devicetree/bindings/virtio/mmio.txt linux-libre-3.2-gnu1/Documentation/devicetree/bindings/virtio/mmio.txt
--- linux-libre-3.1-gnu1/Documentation/devicetree/bindings/virtio/mmio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/devicetree/bindings/virtio/mmio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block@3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff -druNp linux-libre-3.1-gnu1/Documentation/DMA-API.txt linux-libre-3.2-gnu1/Documentation/DMA-API.txt
--- linux-libre-3.1-gnu1/Documentation/DMA-API.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DMA-API.txt	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,13 @@ specify the GFP_ flags (see kmalloc) for
 implementation may choose to ignore flags that affect the location of
 the returned memory, like GFP_DMA).
 
+void *
+dma_zalloc_coherent(struct device *dev, size_t size,
+			     dma_addr_t *dma_handle, gfp_t flag)
+
+Wraps dma_alloc_coherent() and also zeroes the returned memory if the
+allocation attempt succeeded.
+
 void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 			   dma_addr_t dma_handle)
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/80211.tmpl linux-libre-3.2-gnu1/Documentation/DocBook/80211.tmpl
--- linux-libre-3.1-gnu1/Documentation/DocBook/80211.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/80211.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -433,8 +433,18 @@
           Insert notes about VLAN interfaces with hw crypto here or
           in the hw crypto chapter.
         </para>
+      <section id="ps-client">
+        <title>support for powersaving clients</title>
+!Pinclude/net/mac80211.h AP support for powersaving clients
+      </section>
 !Finclude/net/mac80211.h ieee80211_get_buffered_bc
 !Finclude/net/mac80211.h ieee80211_beacon_get
+!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
+!Finclude/net/mac80211.h ieee80211_frame_release_type
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
+!Finclude/net/mac80211.h ieee80211_sta_set_buffered
+!Finclude/net/mac80211.h ieee80211_sta_block_awake
       </chapter>
 
       <chapter id="multi-iface">
@@ -460,7 +470,6 @@
 !Finclude/net/mac80211.h sta_notify_cmd
 !Finclude/net/mac80211.h ieee80211_find_sta
 !Finclude/net/mac80211.h ieee80211_find_sta_by_ifaddr
-!Finclude/net/mac80211.h ieee80211_sta_block_awake
       </chapter>
 
       <chapter id="hardware-scan-offload">
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/drm.tmpl linux-libre-3.2-gnu1/Documentation/DocBook/drm.tmpl
--- linux-libre-3.1-gnu1/Documentation/DocBook/drm.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/drm.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
       The Linux DRM layer contains code intended to support the needs
       of complex graphics devices, usually containing programmable
       pipelines well suited to 3D graphics acceleration.  Graphics
-      drivers in the kernel can make use of DRM functions to make
+      drivers in the kernel may make use of DRM functions to make
       tasks like memory management, interrupt handling and DMA easier,
       and provide a uniform interface to applications.
     </para>
@@ -57,10 +57,10 @@
       existing drivers.
     </para>
     <para>
-      First, we'll go over some typical driver initialization
+      First, we go over some typical driver initialization
       requirements, like setting up command buffers, creating an
       initial output configuration, and initializing core services.
-      Subsequent sections will cover core internals in more detail,
+      Subsequent sections cover core internals in more detail,
       providing implementation notes and examples.
     </para>
     <para>
@@ -74,7 +74,7 @@
     </para>
     <para>
       The core of every DRM driver is struct drm_driver.  Drivers
-      will typically statically initialize a drm_driver structure,
+      typically statically initialize a drm_driver structure,
       then pass it to drm_init() at load time.
     </para>
 
@@ -88,8 +88,8 @@
     </para>
     <programlisting>
       static struct drm_driver driver = {
-	/* don't use mtrr's here, the Xserver or user space app should
-	 * deal with them for intel hardware.
+	/* Don't use MTRRs here; the Xserver or userspace app should
+	 * deal with them for Intel hardware.
 	 */
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
@@ -154,8 +154,8 @@
     </programlisting>
     <para>
       In the example above, taken from the i915 DRM driver, the driver
-      sets several flags indicating what core features it supports.
-      We'll go over the individual callbacks in later sections.  Since
+      sets several flags indicating what core features it supports;
+      we go over the individual callbacks in later sections.  Since
       flags indicate which features your driver supports to the DRM
       core, you need to set most of them prior to calling drm_init().  Some,
       like DRIVER_MODESET can be set later based on user supplied parameters,
@@ -203,8 +203,8 @@
 	<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
 	<listitem>
 	  <para>
-	    DRIVER_HAVE_IRQ indicates whether the driver has a IRQ
-	    handler, DRIVER_IRQ_SHARED indicates whether the device &amp;
+	    DRIVER_HAVE_IRQ indicates whether the driver has an IRQ
+	    handler.  DRIVER_IRQ_SHARED indicates whether the device &amp;
 	    handler support shared IRQs (note that this is required of
 	    PCI drivers).
 	  </para>
@@ -214,8 +214,8 @@
 	<term>DRIVER_DMA_QUEUE</term>
 	<listitem>
 	  <para>
-	    If the driver queues DMA requests and completes them
-	    asynchronously, this flag should be set.  Deprecated.
+	    Should be set if the driver queues DMA requests and completes them
+	    asynchronously.  Deprecated.
 	  </para>
 	</listitem>
       </varlistentry>
@@ -238,7 +238,7 @@
     </variablelist>
     <para>
       In this specific case, the driver requires AGP and supports
-      IRQs.  DMA, as we'll see, is handled by device specific ioctls
+      IRQs.  DMA, as discussed later, is handled by device-specific ioctls
       in this case.  It also supports the kernel mode setting APIs, though
       unlike in the actual i915 driver source, this example unconditionally
       exports KMS capability.
@@ -269,36 +269,34 @@
       initial output configuration.
     </para>
     <para>
-      Note that the tasks performed at driver load time must not
-      conflict with DRM client requirements.  For instance, if user
+      If compatibility is a concern (e.g. with drivers converted over
+      to the new interfaces from the old ones), care must be taken to
+      prevent device initialization and control that is incompatible with
+      currently active userspace drivers.  For instance, if user
       level mode setting drivers are in use, it would be problematic
       to perform output discovery &amp; configuration at load time.
-      Likewise, if pre-memory management aware user level drivers are
+      Likewise, if user-level drivers unaware of memory management are
       in use, memory management and command buffer setup may need to
-      be omitted.  These requirements are driver specific, and care
+      be omitted.  These requirements are driver-specific, and care
       needs to be taken to keep both old and new applications and
       libraries working.  The i915 driver supports the "modeset"
       module parameter to control whether advanced features are
-      enabled at load time or in legacy fashion.  If compatibility is
-      a concern (e.g. with drivers converted over to the new interfaces
-      from the old ones), care must be taken to prevent incompatible
-      device initialization and control with the currently active
-      userspace drivers.
+      enabled at load time or in legacy fashion.
     </para>
 
     <sect2>
       <title>Driver private &amp; performance counters</title>
       <para>
 	The driver private hangs off the main drm_device structure and
-	can be used for tracking various device specific bits of
+	can be used for tracking various device-specific bits of
 	information, like register offsets, command buffer status,
 	register state for suspend/resume, etc.  At load time, a
-	driver can simply allocate one and set drm_device.dev_priv
-	appropriately; at unload the driver can free it and set
-	drm_device.dev_priv to NULL.
+	driver may simply allocate one and set drm_device.dev_priv
+	appropriately; it should be freed and drm_device.dev_priv set
+	to NULL when the driver is unloaded.
       </para>
       <para>
-	The DRM supports several counters which can be used for rough
+	The DRM supports several counters which may be used for rough
 	performance characterization.  Note that the DRM stat counter
 	system is not often used by applications, and supporting
 	additional counters is completely optional.
@@ -307,15 +305,15 @@
 	These interfaces are deprecated and should not be used.  If performance
 	monitoring is desired, the developer should investigate and
 	potentially enhance the kernel perf and tracing infrastructure to export
-	GPU related performance information to performance monitoring
-	tools and applications.
+	GPU related performance information for consumption by performance
+	monitoring tools and applications.
       </para>
     </sect2>
 
     <sect2>
       <title>Configuring the device</title>
       <para>
-	Obviously, device configuration will be device specific.
+	Obviously, device configuration is device-specific.
 	However, there are several common operations: finding a
 	device's PCI resources, mapping them, and potentially setting
 	up an IRQ handler.
@@ -323,10 +321,10 @@
       <para>
 	Finding &amp; mapping resources is fairly straightforward.  The
 	DRM wrapper functions, drm_get_resource_start() and
-	drm_get_resource_len() can be used to find BARs on the given
+	drm_get_resource_len(), may be used to find BARs on the given
 	drm_device struct.  Once those values have been retrieved, the
 	driver load function can call drm_addmap() to create a new
-	mapping for the BAR in question.  Note you'll probably want a
+	mapping for the BAR in question.  Note that you probably want a
 	drm_local_map_t in your driver private structure to track any
 	mappings you create.
 <!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
@@ -335,20 +333,20 @@
       <para>
 	if compatibility with other operating systems isn't a concern
 	(DRM drivers can run under various BSD variants and OpenSolaris),
-	native Linux calls can be used for the above, e.g. pci_resource_*
+	native Linux calls may be used for the above, e.g. pci_resource_*
 	and iomap*/iounmap.  See the Linux device driver book for more
 	info.
       </para>
       <para>
-	Once you have a register map, you can use the DRM_READn() and
+	Once you have a register map, you may use the DRM_READn() and
 	DRM_WRITEn() macros to access the registers on your device, or
-	use driver specific versions to offset into your MMIO space
-	relative to a driver specific base pointer (see I915_READ for
-	example).
+	use driver-specific versions to offset into your MMIO space
+	relative to a driver-specific base pointer (see I915_READ for
+	an example).
       </para>
       <para>
 	If your device supports interrupt generation, you may want to
-	setup an interrupt handler at driver load time as well.  This
+	set up an interrupt handler when the driver is loaded.  This
 	is done using the drm_irq_install() function.  If your device
 	supports vertical blank interrupts, it should call
 	drm_vblank_init() to initialize the core vblank handling code before
@@ -357,7 +355,7 @@
       </para>
 <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
       <para>
-	Once your interrupt handler is registered (it'll use your
+	Once your interrupt handler is registered (it uses your
 	drm_driver.irq_handler as the actual interrupt handling
 	function), you can safely enable interrupts on your device,
 	assuming any other state your interrupt handler uses is also
@@ -371,10 +369,10 @@
 	using the pci_map_rom() call, a convenience function that
 	takes care of mapping the actual ROM, whether it has been
 	shadowed into memory (typically at address 0xc0000) or exists
-	on the PCI device in the ROM BAR.  Note that once you've
-	mapped the ROM and extracted any necessary information, be
-	sure to unmap it; on many devices the ROM address decoder is
-	shared with other BARs, so leaving it mapped can cause
+	on the PCI device in the ROM BAR.  Note that after the ROM
+	has been mapped and any necessary information has been extracted,
+	it should be unmapped; on many devices, the ROM address decoder is
+	shared with other BARs, so leaving it mapped could cause
 	undesired behavior like hangs or memory corruption.
 <!--!Fdrivers/pci/rom.c pci_map_rom-->
       </para>
@@ -389,9 +387,9 @@
 	should support a memory manager.
       </para>
       <para>
-	If your driver supports memory management (it should!), you'll
+	If your driver supports memory management (it should!), you
 	need to set that up at load time as well.  How you initialize
-	it depends on which memory manager you're using, TTM or GEM.
+	it depends on which memory manager you're using: TTM or GEM.
       </para>
       <sect3>
 	<title>TTM initialization</title>
@@ -401,7 +399,7 @@
 	  and devices with dedicated video RAM (VRAM), i.e. most discrete
 	  graphics devices.  If your device has dedicated RAM, supporting
 	  TTM is desirable.  TTM also integrates tightly with your
-	  driver specific buffer execution function.  See the radeon
+	  driver-specific buffer execution function.  See the radeon
 	  driver for examples.
 	</para>
 	<para>
@@ -429,21 +427,21 @@
 	  created by the memory manager at runtime.  Your global TTM should
 	  have a type of TTM_GLOBAL_TTM_MEM.  The size field for the global
 	  object should be sizeof(struct ttm_mem_global), and the init and
-	  release hooks should point at your driver specific init and
-	  release routines, which will probably eventually call
-	  ttm_mem_global_init and ttm_mem_global_release respectively.
+	  release hooks should point at your driver-specific init and
+	  release routines, which probably eventually call
+	  ttm_mem_global_init and ttm_mem_global_release, respectively.
 	</para>
 	<para>
 	  Once your global TTM accounting structure is set up and initialized
-	  (done by calling ttm_global_item_ref on the global object you
-	  just created), you'll need to create a buffer object TTM to
+	  by calling ttm_global_item_ref() on it,
+	  you need to create a buffer object TTM to
 	  provide a pool for buffer object allocation by clients and the
 	  kernel itself.  The type of this object should be TTM_GLOBAL_TTM_BO,
 	  and its size should be sizeof(struct ttm_bo_global).  Again,
-	  driver specific init and release functions can be provided,
-	  likely eventually calling ttm_bo_global_init and
-	  ttm_bo_global_release, respectively.  Also like the previous
-	  object, ttm_global_item_ref is used to create an initial reference
+	  driver-specific init and release functions may be provided,
+	  likely eventually calling ttm_bo_global_init() and
+	  ttm_bo_global_release(), respectively.  Also, like the previous
+	  object, ttm_global_item_ref() is used to create an initial reference
 	  count for the TTM, which will call your initialization function.
 	</para>
       </sect3>
@@ -453,27 +451,26 @@
 	  GEM is an alternative to TTM, designed specifically for UMA
 	  devices.  It has simpler initialization and execution requirements
 	  than TTM, but has no VRAM management capability.  Core GEM
-	  initialization is comprised of a basic drm_mm_init call to create
+	  is initialized by calling drm_mm_init() to create
 	  a GTT DRM MM object, which provides an address space pool for
-	  object allocation.  In a KMS configuration, the driver will
-	  need to allocate and initialize a command ring buffer following
-	  basic GEM initialization.  Most UMA devices have a so-called
+	  object allocation.  In a KMS configuration, the driver
+	  needs to allocate and initialize a command ring buffer following
+	  core GEM initialization.  A UMA device usually has what is called a
 	  "stolen" memory region, which provides space for the initial
 	  framebuffer and large, contiguous memory regions required by the
-	  device.  This space is not typically managed by GEM, and must
+	  device.  This space is not typically managed by GEM, and it must
 	  be initialized separately into its own DRM MM object.
 	</para>
 	<para>
-	  Initialization will be driver specific, and will depend on
-	  the architecture of the device.  In the case of Intel
+	  Initialization is driver-specific. In the case of Intel
 	  integrated graphics chips like 965GM, GEM initialization can
 	  be done by calling the internal GEM init function,
 	  i915_gem_do_init().  Since the 965GM is a UMA device
-	  (i.e. it doesn't have dedicated VRAM), GEM will manage
+	  (i.e. it doesn't have dedicated VRAM), GEM manages
 	  making regular RAM available for GPU operations.  Memory set
 	  aside by the BIOS (called "stolen" memory by the i915
-	  driver) will be managed by the DRM memrange allocator; the
-	  rest of the aperture will be managed by GEM.
+	  driver) is managed by the DRM memrange allocator; the
+	  rest of the aperture is managed by GEM.
 	  <programlisting>
 	    /* Basic memrange allocator for stolen space (aka vram) */
 	    drm_memrange_init(&amp;dev_priv->vram, 0, prealloc_size);
@@ -483,7 +480,7 @@
 <!--!Edrivers/char/drm/drm_memrange.c-->
 	</para>
 	<para>
-	  Once the memory manager has been set up, we can allocate the
+	  Once the memory manager has been set up, we may allocate the
 	  command buffer.  In the i915 case, this is also done with a
 	  GEM function, i915_gem_init_ringbuffer().
 	</para>
@@ -493,16 +490,25 @@
     <sect2>
       <title>Output configuration</title>
       <para>
-	The final initialization task is output configuration.  This involves
-	finding and initializing the CRTCs, encoders and connectors
-	for your device, creating an initial configuration and
-	registering a framebuffer console driver.
+	The final initialization task is output configuration.  This involves:
+	<itemizedlist>
+	  <listitem>
+	    Finding and initializing the CRTCs, encoders, and connectors
+	    for the device.
+	  </listitem>
+	  <listitem>
+	    Creating an initial configuration.
+	  </listitem>
+	  <listitem>
+	    Registering a framebuffer console driver.
+	  </listitem>
+	</itemizedlist>
       </para>
       <sect3>
 	<title>Output discovery and initialization</title>
 	<para>
-	  Several core functions exist to create CRTCs, encoders and
-	  connectors, namely drm_crtc_init(), drm_connector_init() and
+	  Several core functions exist to create CRTCs, encoders, and
+	  connectors, namely: drm_crtc_init(), drm_connector_init(), and
 	  drm_encoder_init(), along with several "helper" functions to
 	  perform common tasks.
 	</para>
@@ -555,10 +561,10 @@ void intel_crt_init(struct drm_device *d
 	</programlisting>
 	<para>
 	  In the example above (again, taken from the i915 driver), a
-	  CRT connector and encoder combination is created.  A device
-	  specific i2c bus is also created, for fetching EDID data and
+	  CRT connector and encoder combination is created.  A device-specific
+	  i2c bus is also created for fetching EDID data and
 	  performing monitor detection.  Once the process is complete,
-	  the new connector is registered with sysfs, to make its
+	  the new connector is registered with sysfs to make its
 	  properties available to applications.
 	</para>
 	<sect4>
@@ -567,12 +573,12 @@ void intel_crt_init(struct drm_device *d
 	    Since many PC-class graphics devices have similar display output
 	    designs, the DRM provides a set of helper functions to make
 	    output management easier.  The core helper routines handle
-	    encoder re-routing and disabling of unused functions following
-	    mode set.  Using the helpers is optional, but recommended for
+	    encoder re-routing and the disabling of unused functions following
+	    mode setting.  Using the helpers is optional, but recommended for
 	    devices with PC-style architectures (i.e. a set of display planes
 	    for feeding pixels to encoders which are in turn routed to
 	    connectors).  Devices with more complex requirements needing
-	    finer grained management can opt to use the core callbacks
+	    finer grained management may opt to use the core callbacks
 	    directly.
 	  </para>
 	  <para>
@@ -580,17 +586,25 @@ void intel_crt_init(struct drm_device *d
 	  </para>
 	</sect4>
 	<para>
-	  For each encoder, CRTC and connector, several functions must
-	  be provided, depending on the object type.  Encoder objects
-	  need to provide a DPMS (basically on/off) function, mode fixup
-	  (for converting requested modes into native hardware timings),
-	  and prepare, set and commit functions for use by the core DRM
-	  helper functions.  Connector helpers need to provide mode fetch and
-	  validity functions as well as an encoder matching function for
-	  returning an ideal encoder for a given connector.  The core
-	  connector functions include a DPMS callback, (deprecated)
-	  save/restore routines, detection, mode probing, property handling,
-	  and cleanup functions.
+	  Each encoder object needs to provide:
+	  <itemizedlist>
+	    <listitem>
+	      A DPMS (basically on/off) function.
+	    </listitem>
+	    <listitem>
+	      A mode-fixup function (for converting requested modes into
+	      native hardware timings).
+	    </listitem>
+	    <listitem>
+	      Functions (prepare, set, and commit) for use by the core DRM
+	      helper functions.
+	    </listitem>
+	  </itemizedlist>
+	  Connector helpers need to provide functions (mode-fetch, validity,
+	  and encoder-matching) for returning an ideal encoder for a given
+	  connector.  The core connector functions include a DPMS callback,
+	  save/restore routines (deprecated), detection, mode probing,
+	  property handling, and cleanup functions.
 	</para>
 <!--!Edrivers/char/drm/drm_crtc.h-->
 <!--!Edrivers/char/drm/drm_crtc.c-->
@@ -605,23 +619,34 @@ void intel_crt_init(struct drm_device *d
     <title>VBlank event handling</title>
     <para>
       The DRM core exposes two vertical blank related ioctls:
-      DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL.
+      <variablelist>
+        <varlistentry>
+          <term>DRM_IOCTL_WAIT_VBLANK</term>
+          <listitem>
+            <para>
+              This takes a struct drm_wait_vblank structure as its argument,
+              and it is used to block or request a signal when a specified
+              vblank event occurs.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_IOCTL_MODESET_CTL</term>
+          <listitem>
+            <para>
+              This should be called by application level drivers before and
+              after mode setting, since on many devices the vertical blank
+              counter is reset at that time.  Internally, the DRM snapshots
+              the last vblank count when the ioctl is called with the
+              _DRM_PRE_MODESET command, so that the counter won't go backwards
+              (which is dealt with when _DRM_POST_MODESET is used).
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
 <!--!Edrivers/char/drm/drm_irq.c-->
     </para>
     <para>
-      DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure
-      as its argument, and is used to block or request a signal when a
-      specified vblank event occurs.
-    </para>
-    <para>
-      DRM_IOCTL_MODESET_CTL should be called by application level
-      drivers before and after mode setting, since on many devices the
-      vertical blank counter will be reset at that time.  Internally,
-      the DRM snapshots the last vblank count when the ioctl is called
-      with the _DRM_PRE_MODESET command so that the counter won't go
-      backwards (which is dealt with when _DRM_POST_MODESET is used).
-    </para>
-    <para>
       To support the functions above, the DRM core provides several
       helper functions for tracking vertical blank counters, and
       requires drivers to provide several callbacks:
@@ -632,24 +657,24 @@ void intel_crt_init(struct drm_device *d
       register.  The enable and disable vblank callbacks should enable
       and disable vertical blank interrupts, respectively.  In the
       absence of DRM clients waiting on vblank events, the core DRM
-      code will use the disable_vblank() function to disable
-      interrupts, which saves power.  They'll be re-enabled again when
+      code uses the disable_vblank() function to disable
+      interrupts, which saves power.  They are re-enabled again when
       a client calls the vblank wait ioctl above.
     </para>
     <para>
-      Devices that don't provide a count register can simply use an
+      A device that doesn't provide a count register may simply use an
       internal atomic counter incremented on every vertical blank
-      interrupt, and can make their enable and disable vblank
-      functions into no-ops.
+      interrupt (and then treat the enable_vblank() and disable_vblank()
+      callbacks as no-ops).
     </para>
   </sect1>
 
   <sect1>
     <title>Memory management</title>
     <para>
-      The memory manager lies at the heart of many DRM operations, and
-      is also required to support advanced client features like OpenGL
-      pbuffers.  The DRM currently contains two memory managers, TTM
+      The memory manager lies at the heart of many DRM operations; it
+      is required to support advanced client features like OpenGL
+      pbuffers.  The DRM currently contains two memory managers: TTM
       and GEM.
     </para>
 
@@ -679,41 +704,46 @@ void intel_crt_init(struct drm_device *d
       <para>
 	GEM-enabled drivers must provide gem_init_object() and
 	gem_free_object() callbacks to support the core memory
-	allocation routines.  They should also provide several driver
-	specific ioctls to support command execution, pinning, buffer
+	allocation routines.  They should also provide several driver-specific
+	ioctls to support command execution, pinning, buffer
 	read &amp; write, mapping, and domain ownership transfers.
       </para>
       <para>
-	On a fundamental level, GEM involves several operations: memory
-	allocation and freeing, command execution, and aperture management
-	at command execution time.  Buffer object allocation is relatively
+	On a fundamental level, GEM involves several operations:
+	<itemizedlist>
+	  <listitem>Memory allocation and freeing</listitem>
+	  <listitem>Command execution</listitem>
+	  <listitem>Aperture management at command execution time</listitem>
+	</itemizedlist>
+	Buffer object allocation is relatively
 	straightforward and largely provided by Linux's shmem layer, which
 	provides memory to back each object.  When mapped into the GTT
 	or used in a command buffer, the backing pages for an object are
 	flushed to memory and marked write combined so as to be coherent
-	with the GPU.  Likewise, when the GPU finishes rendering to an object,
-	if the CPU accesses it, it must be made coherent with the CPU's view
+	with the GPU.  Likewise, if the CPU accesses an object after the GPU
+	has finished rendering to the object, then the object must be made
+	coherent with the CPU's view
 	of memory, usually involving GPU cache flushing of various kinds.
-	This core CPU&lt;-&gt;GPU coherency management is provided by the GEM
-	set domain function, which evaluates an object's current domain and
+	This core CPU&lt;-&gt;GPU coherency management is provided by a
+	device-specific ioctl, which evaluates an object's current domain and
 	performs any necessary flushing or synchronization to put the object
 	into the desired coherency domain (note that the object may be busy,
-	i.e. an active render target; in that case the set domain function
-	will block the client and wait for rendering to complete before
+	i.e. an active render target; in that case, setting the domain
+	blocks the client and waits for rendering to complete before
 	performing any necessary flushing operations).
       </para>
       <para>
 	Perhaps the most important GEM function is providing a command
 	execution interface to clients.  Client programs construct command
-	buffers containing references to previously allocated memory objects
-	and submit them to GEM.  At that point, GEM will take care to bind
+	buffers containing references to previously allocated memory objects,
+	and then submit them to GEM.  At that point, GEM takes care to bind
 	all the objects into the GTT, execute the buffer, and provide
 	necessary synchronization between clients accessing the same buffers.
 	This often involves evicting some objects from the GTT and re-binding
 	others (a fairly expensive operation), and providing relocation
 	support which hides fixed GTT offsets from clients.  Clients must
 	take care not to submit command buffers that reference more objects
-	than can fit in the GTT or GEM will reject them and no rendering
+	than can fit in the GTT; otherwise, GEM will reject them and no rendering
 	will occur.  Similarly, if several objects in the buffer require
 	fence registers to be allocated for correct rendering (e.g. 2D blits
 	on pre-965 chips), care must be taken not to require more fence
@@ -729,7 +759,7 @@ void intel_crt_init(struct drm_device *d
     <title>Output management</title>
     <para>
       At the core of the DRM output management code is a set of
-      structures representing CRTCs, encoders and connectors.
+      structures representing CRTCs, encoders, and connectors.
     </para>
     <para>
       A CRTC is an abstraction representing a part of the chip that
@@ -765,21 +795,19 @@ void intel_crt_init(struct drm_device *d
   <sect1>
     <title>Framebuffer management</title>
     <para>
-      In order to set a mode on a given CRTC, encoder and connector
-      configuration, clients need to provide a framebuffer object which
-      will provide a source of pixels for the CRTC to deliver to the encoder(s)
-      and ultimately the connector(s) in the configuration.  A framebuffer
-      is fundamentally a driver specific memory object, made into an opaque
-      handle by the DRM addfb function.  Once an fb has been created this
-      way it can be passed to the KMS mode setting routines for use in
-      a configuration.
+      Clients need to provide a framebuffer object which provides a source
+      of pixels for a CRTC to deliver to the encoder(s) and ultimately the
+      connector(s). A framebuffer is fundamentally a driver-specific memory
+      object, made into an opaque handle by the DRM's addfb() function.
+      Once a framebuffer has been created this way, it may be passed to the
+      KMS mode setting routines for use in a completed configuration.
     </para>
   </sect1>
 
   <sect1>
     <title>Command submission &amp; fencing</title>
     <para>
-      This should cover a few device specific command submission
+      This should cover a few device-specific command submission
       implementations.
     </para>
   </sect1>
@@ -789,7 +817,7 @@ void intel_crt_init(struct drm_device *d
     <para>
       The DRM core provides some suspend/resume code, but drivers
       wanting full suspend/resume support should provide save() and
-      restore() functions.  These will be called at suspend,
+      restore() functions.  These are called at suspend,
       hibernate, or resume time, and should perform any state save or
       restore required by your device across suspend or hibernate
       states.
@@ -812,8 +840,8 @@ void intel_crt_init(struct drm_device *d
     <para>
       The DRM core exports several interfaces to applications,
       generally intended to be used through corresponding libdrm
-      wrapper functions.  In addition, drivers export device specific
-      interfaces for use by userspace drivers &amp; device aware
+      wrapper functions.  In addition, drivers export device-specific
+      interfaces for use by userspace drivers &amp; device-aware
       applications through ioctls and sysfs files.
     </para>
     <para>
@@ -822,8 +850,8 @@ void intel_crt_init(struct drm_device *d
       management, memory management, and output management.
     </para>
     <para>
-      Cover generic ioctls and sysfs layout here.  Only need high
-      level info, since man pages will cover the rest.
+      Cover generic ioctls and sysfs layout here.  We only need high-level
+      info, since man pages should cover the rest.
     </para>
   </chapter>
 
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/dvb/dvbproperty.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/dvb/dvbproperty.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/dvb/dvbproperty.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/dvb/dvbproperty.xml	2012-01-04 18:55:44.000000000 -0500
@@ -352,6 +352,7 @@ typedef enum fe_delivery_system {
 	SYS_CMMB,
 	SYS_DAB,
 	SYS_DVBT2,
+	SYS_TURBO,
 } fe_delivery_system_t;
 </programlisting>
 		</section>
@@ -809,6 +810,8 @@ typedef enum fe_hierarchy {
 			<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
 		</itemizedlist>
 		<para>Future implementations might add those two missing parameters:</para>
 		<itemizedlist mark='opencircle'>
@@ -818,25 +821,18 @@ typedef enum fe_hierarchy {
 	</section>
 	<section id="dvbs2-params">
 		<title>DVB-S2 delivery system</title>
-		<para>The following parameters are valid for DVB-S2:</para>
+		<para>In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters:</para>
 		<itemizedlist mark='opencircle'>
-			<listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
 		</itemizedlist>
-		<para>Future implementations might add those two missing parameters:</para>
+	</section>
+	<section id="turbo-params">
+		<title>Turbo code delivery system</title>
+		<para>In addition to all parameters valid for DVB-S, turbo code supports the following parameters:</para>
 		<itemizedlist mark='opencircle'>
-			<listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="isdbs-params">
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/dvb/intro.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/dvb/intro.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/dvb/intro.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/dvb/intro.xml	2012-01-04 18:55:44.000000000 -0500
@@ -205,7 +205,7 @@ a partial path like:</para>
 additional include file <emphasis
 role="tt">linux/dvb/version.h</emphasis> exists, which defines the
 constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
-describes <emphasis role="tt">DVB_API_VERSION&#x00A0;3</emphasis>.
+describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
 </para>
 
 </section>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/compat.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/compat.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/compat.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/compat.xml	2012-01-04 18:55:44.000000000 -0500
@@ -2370,6 +2370,14 @@ that used it. It was originally schedule
         </listitem>
       </orderedlist>
     </section>
+    <section>
+      <title>V4L2 in Linux 3.2</title>
+      <orderedlist>
+        <listitem>
+	  <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
+        </listitem>
+      </orderedlist>
+    </section>
 
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
@@ -2478,6 +2486,9 @@ ioctls.</para>
         <listitem>
 	  <para>Flash API. <xref linkend="flash-controls" /></para>
         </listitem>
+        <listitem>
+	  <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/controls.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/controls.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/controls.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/controls.xml	2012-01-04 18:55:44.000000000 -0500
@@ -232,8 +232,9 @@ control is deprecated. New drivers and a
 	    <entry>Enables a power line frequency filter to avoid
 flicker. Possible values for <constant>enum v4l2_power_line_frequency</constant> are:
 <constant>V4L2_CID_POWER_LINE_FREQUENCY_DISABLED</constant> (0),
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1) and
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2).</entry>
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1),
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2) and
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_AUTO</constant> (3).</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CID_HUE_AUTO</constant></entry>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/dev-subdev.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/dev-subdev.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/dev-subdev.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/dev-subdev.xml	2012-01-04 18:55:44.000000000 -0500
@@ -266,7 +266,7 @@
 
       <para>When satisfied with the try results, applications can set the active
       formats by setting the <structfield>which</structfield> argument to
-      <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
+      <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. Active formats are changed
       exactly as try formats by drivers. To avoid modifying the hardware state
       during format negotiation, applications should negotiate try formats first
       and then modify the active settings using the try formats returned during
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/io.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/io.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/io.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/io.xml	2012-01-04 18:55:44.000000000 -0500
@@ -927,6 +927,33 @@ ioctl is called.</entry>
 Applications set or clear this flag before calling the
 <constant>VIDIOC_QBUF</constant> ioctl.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
+	    <entry>0x0400</entry>
+	    <entry>The buffer has been prepared for I/O and can be queued by the
+application. Drivers set or clear this flag when the
+<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
+	  linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link>, <link
+	  linkend="vidioc-qbuf">VIDIOC_QBUF</link> or <link
+	  linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
+	    <entry>0x0400</entry>
+	    <entry>Caches do not have to be invalidated for this buffer.
+Typically applications shall use this flag if the data captured in the buffer
+is not going to be touched by the CPU, instead the buffer will, probably, be
+passed on to a DMA-capable hardware unit for further processing or output.
+</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
+	    <entry>0x0800</entry>
+	    <entry>Caches do not have to be cleaned for this buffer.
+Typically applications shall use this flag for output buffers if the data
+in this buffer has not been created by the CPU but by some DMA-capable unit,
+in which case caches have not been used.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/v4l2.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/v4l2.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/v4l2.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/v4l2.xml	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,13 @@ structs, ioctls) must be noted in more d
 applications. -->
 
       <revision>
+	<revnumber>3.2</revnumber>
+	<date>2011-08-26</date>
+	<authorinitials>hv</authorinitials>
+	<revremark>Added V4L2_CTRL_FLAG_VOLATILE.</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.1</revnumber>
 	<date>2011-06-27</date>
 	<authorinitials>mcc, po, hv</authorinitials>
@@ -410,7 +417,7 @@ and discussions on the V4L mailing list.
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.1</subtitle>
+ <subtitle>Revision 3.2</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -462,6 +469,7 @@ and discussions on the V4L mailing list.
     &sub-close;
     &sub-ioctl;
     <!-- All ioctls go here. -->
+    &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
     &sub-dbg-g-register;
@@ -504,6 +512,7 @@ and discussions on the V4L mailing list.
     &sub-queryctrl;
     &sub-query-dv-preset;
     &sub-querystd;
+    &sub-prepare-buf;
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
     &sub-streamon;
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+<refentry id="vidioc-create-bufs">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_CREATE_BUFS</refname>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_create_buffers *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_CREATE_BUFS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
+mapped</link> or <link linkend="userp">user pointer</link>
+I/O. It can be used as an alternative or in addition to the
+<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
+is required. This ioctl can be called multiple times to create buffers of
+different sizes.</para>
+
+    <para>To allocate device buffers applications initialize relevant fields of
+the <structname>v4l2_create_buffers</structname> structure. They set the
+<structfield>type</structfield> field in the
+<structname>v4l2_format</structname> structure, embedded in this
+structure, to the respective stream or buffer type.
+<structfield>count</structfield> must be set to the number of required buffers.
+<structfield>memory</structfield> specifies the required I/O method. The
+<structfield>format</structfield> field shall typically be filled in using
+either the <constant>VIDIOC_TRY_FMT</constant> or
+<constant>VIDIOC_G_FMT</constant> ioctl(). Additionally, applications can adjust
+<structfield>sizeimage</structfield> fields to fit their specific needs. The
+<structfield>reserved</structfield> array must be zeroed.</para>
+
+    <para>When the ioctl is called with a pointer to this structure the driver
+will attempt to allocate up to the requested number of buffers and store the
+actual number allocated and the starting index in the
+<structfield>count</structfield> and the <structfield>index</structfield> fields
+respectively. On return <structfield>count</structfield> can be smaller than
+the number requested. The driver may also increase buffer sizes if required,
+however, it will not update <structfield>sizeimage</structfield> field values.
+The user has to use <constant>VIDIOC_QUERYBUF</constant> to retrieve that
+information.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-create-buffers">
+      <title>struct <structname>v4l2_create_buffers</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>The starting buffer index, returned by the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>count</structfield></entry>
+	    <entry>The number of buffers requested or granted.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-memory;</entry>
+	    <entry><structfield>memory</structfield></entry>
+	    <entry>Applications set this field to
+<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-format;</entry>
+	    <entry><structfield>format</structfield></entry>
+	    <entry>Filled in by the application, preserved by the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
+	    <entry>A place holder for future extensions.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>ENOMEM</errorcode></term>
+	<listitem>
+	  <para>No memory to allocate buffers for <link linkend="mmap">memory
+mapped</link> I/O.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer type (<structfield>type</structfield> field) or the
+requested I/O method (<structfield>memory</structfield>) is not
+supported.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-dqevent.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,12 @@
 	  </row>
 	  <row>
 	    <entry></entry>
+	    <entry>&v4l2-event-frame-sync;</entry>
+            <entry><structfield>frame</structfield></entry>
+	    <entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
 	    <entry>__u8</entry>
             <entry><structfield>data</structfield>[64]</entry>
 	    <entry>Event data. Defined by the event type. The union
@@ -135,6 +141,129 @@
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="v4l2-event-vsync">
+      <title>struct <structname>v4l2_event_vsync</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u8</entry>
+	    <entry><structfield>field</structfield></entry>
+	    <entry>The upcoming field. See &v4l2-field;.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-ctrl">
+      <title>struct <structname>v4l2_event_ctrl</structname></title>
+      <tgroup cols="4">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>changes</structfield></entry>
+	    <entry></entry>
+	    <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry></entry>
+	    <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
+	  </row>
+	  <row>
+	    <entry>union (anonymous)</entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__s32</entry>
+	    <entry><structfield>value</structfield></entry>
+	    <entry>The 32-bit value of the control for 32-bit control types.
+		This is 0 for string controls since the value of a string
+		cannot be passed using &VIDIOC-DQEVENT;.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__s64</entry>
+	    <entry><structfield>value64</structfield></entry>
+	    <entry>The 64-bit value of the control for 64-bit control types.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry></entry>
+	    <entry>The control flags. See <xref linkend="control-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>minimum</structfield></entry>
+	    <entry></entry>
+	    <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>maximum</structfield></entry>
+	    <entry></entry>
+	    <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>step</structfield></entry>
+	    <entry></entry>
+	    <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>default_value</structfield></entry>
+	    <entry></entry>
+	    <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-frame-sync">
+      <title>struct <structname>v4l2_event_frame_sync</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>frame_sequence</structfield></entry>
+	    <entry>
+	      The sequence number of the frame being received.
+	    </entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="changes-flags">
+      <title>Changes</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
+	    <entry>0x0001</entry>
+	    <entry>This control event was triggered because the value of the control
+		changed. Special case: if a button control is pressed, then this
+		event is sent as well, even though there is not explicit value
+		associated with a button control.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
+	    <entry>0x0002</entry>
+	    <entry>This control event was triggered because the control flags
+		changed.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
   </refsect1>
   <refsect1>
     &return-value;
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+<refentry id="vidioc-prepare-buf">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_PREPARE_BUF</refname>
+    <refpurpose>Prepare a buffer for I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_buffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_PREPARE_BUF</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Applications can optionally call the
+<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
+to the driver before actually enqueuing it, using the
+<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
+Such preparations may include cache invalidation or cleaning. Performing them
+in advance saves time during the actual I/O. In case such cache operations are
+not required, the application can use one of
+<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
+<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
+step.</para>
+
+    <para>The <structname>v4l2_buffer</structname> structure is
+specified in <xref linkend="buffer" />.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>File I/O is in progress.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer <structfield>type</structfield> is not
+supported, or the <structfield>index</structfield> is out of bounds,
+or no buffers have been allocated yet, or the
+<structfield>userptr</structfield> or
+<structfield>length</structfield> are invalid.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2012-01-04 18:55:44.000000000 -0500
@@ -406,6 +406,15 @@ flag is typically present for relative c
 writing a value will cause the device to carry out a given action
 (&eg; motor control) but no meaningful value can be returned.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_VOLATILE</constant></entry>
+	    <entry>0x0080</entry>
+	    <entry>This control is volatile, which means that the value of the control
+changes continuously. A typical example would be the current gain value if the device
+is in auto-gain mode. In such a case the hardware calculates the gain value based on
+the lighting conditions which can change over time. Note that setting a new value for
+a volatile control will have no effect. The new value will just be ignored.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
--- linux-libre-3.1-gnu1/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2012-01-04 18:55:44.000000000 -0500
@@ -139,6 +139,22 @@
 	    </entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
+	    <entry>4</entry>
+	    <entry>
+	      <para>Triggered immediately when the reception of a
+	      frame has begun. This event has a
+	      &v4l2-event-frame-sync; associated with it.</para>
+
+	      <para>If the hardware needs to be stopped in the case of a
+	      buffer underrun it might not be able to generate this event.
+	      In such cases the <structfield>frame_sequence</structfield>
+	      field in &v4l2-event-frame-sync; will not be incremented. This
+	      causes two consecutive frame sequence numbers to have n times
+	      frame interval in between them.</para>
+	    </entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
 	    <entry>0x08000000</entry>
 	    <entry>Base event number for driver-private events.</entry>
@@ -183,113 +199,6 @@
       </tgroup>
     </table>
 
-    <table frame="none" pgwide="1" id="v4l2-event-vsync">
-      <title>struct <structname>v4l2_event_vsync</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u8</entry>
-	    <entry><structfield>field</structfield></entry>
-	    <entry>The upcoming field. See &v4l2-field;.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table frame="none" pgwide="1" id="v4l2-event-ctrl">
-      <title>struct <structname>v4l2_event_ctrl</structname></title>
-      <tgroup cols="4">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>changes</structfield></entry>
-	    <entry></entry>
-	    <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>type</structfield></entry>
-	    <entry></entry>
-	    <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
-	  </row>
-	  <row>
-	    <entry>union (anonymous)</entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>__s32</entry>
-	    <entry><structfield>value</structfield></entry>
-	    <entry>The 32-bit value of the control for 32-bit control types.
-		This is 0 for string controls since the value of a string
-		cannot be passed using &VIDIOC-DQEVENT;.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>__s64</entry>
-	    <entry><structfield>value64</structfield></entry>
-	    <entry>The 64-bit value of the control for 64-bit control types.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>flags</structfield></entry>
-	    <entry></entry>
-	    <entry>The control flags. See <xref linkend="control-flags" />.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>minimum</structfield></entry>
-	    <entry></entry>
-	    <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>maximum</structfield></entry>
-	    <entry></entry>
-	    <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>step</structfield></entry>
-	    <entry></entry>
-	    <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>default_value</structfield></entry>
-	    <entry></entry>
-	    <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table pgwide="1" frame="none" id="changes-flags">
-      <title>Changes</title>
-      <tgroup cols="3">
-	&cs-def;
-	<tbody valign="top">
-	  <row>
-	    <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
-	    <entry>0x0001</entry>
-	    <entry>This control event was triggered because the value of the control
-		changed. Special case: if a button control is pressed, then this
-		event is sent as well, even though there is not explicit value
-		associated with a button control.</entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
-	    <entry>0x0002</entry>
-	    <entry>This control event was triggered because the control flags
-		changed.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
   </refsect1>
   <refsect1>
     &return-value;
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/mtdnand.tmpl linux-libre-3.2-gnu1/Documentation/DocBook/mtdnand.tmpl
--- linux-libre-3.1-gnu1/Documentation/DocBook/mtdnand.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/mtdnand.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -572,7 +572,7 @@ static void board_select_chip (struct mt
 			</para>
 			<para>
 				The simplest way to activate the FLASH based bad block table support 
-				is to set the option NAND_USE_FLASH_BBT in the option field of
+				is to set the option NAND_BBT_USE_FLASH in the bbt_option field of
 				the nand chip structure before calling nand_scan(). For AG-AND
 				chips is this done by default.
 				This activates the default FLASH based bad block table functionality 
@@ -773,20 +773,6 @@ struct nand_oobinfo {
 				done according to the default builtin scheme.
 			</para>
 		</sect2>
-		<sect2 id="User_space_placement_selection">
-			<title>User space placement selection</title>
-		<para>
-			All non ecc functions like mtd->read and mtd->write use an internal 
-			structure, which can be set by an ioctl. This structure is preset 
-			to the autoplacement default.
-	     		<programlisting>
-	ioctl (fd, MEMSETOOBSEL, oobsel);
-	     		</programlisting>
-			oobsel is a pointer to a user supplied structure of type
-			nand_oobconfig. The contents of this structure must match the 
-			criteria of the filesystem, which will be used. See an example in utils/nandwrite.c.
-		</para>
-		</sect2>
 	</sect1>	
 	<sect1 id="Spare_area_autoplacement_default">
 		<title>Spare area autoplacement default schemes</title>
@@ -1158,9 +1144,6 @@ in this page</entry>
 		These constants are defined in nand.h. They are ored together to describe
 		the functionality.
      		<programlisting>
-/* Use a flash based bad block table. This option is parsed by the
- * default bad block table function (nand_default_bbt). */
-#define NAND_USE_FLASH_BBT	0x00010000
 /* The hw ecc generator provides a syndrome instead a ecc value on read 
  * This can only work if we have the ecc bytes directly behind the 
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/uio-howto.tmpl linux-libre-3.2-gnu1/Documentation/DocBook/uio-howto.tmpl
--- linux-libre-3.1-gnu1/Documentation/DocBook/uio-howto.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/uio-howto.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -521,6 +521,11 @@ Here's a description of the fields of <v
 
 <itemizedlist>
 <listitem><para>
+<varname>const char *name</varname>: Optional. Set this to help identify
+the memory region, it will show up in the corresponding sysfs node.
+</para></listitem>
+
+<listitem><para>
 <varname>int memtype</varname>: Required if the mapping is used. Set this to
 <varname>UIO_MEM_PHYS</varname> if you you have physical memory on your
 card to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logical
@@ -529,7 +534,7 @@ memory (e.g. allocated with <function>km
 </para></listitem>
 
 <listitem><para>
-<varname>unsigned long addr</varname>: Required if the mapping is used.
+<varname>phys_addr_t addr</varname>: Required if the mapping is used.
 Fill in the address of your memory block. This address is the one that
 appears in sysfs.
 </para></listitem>
@@ -553,7 +558,7 @@ instead to remember such an address.
 </itemizedlist>
 
 <para>
-Please do not touch the <varname>kobj</varname> element of
+Please do not touch the <varname>map</varname> element of
 <varname>struct uio_mem</varname>! It is used by the UIO framework
 to set up sysfs files for this mapping. Simply leave it alone.
 </para>
diff -druNp linux-libre-3.1-gnu1/Documentation/DocBook/writing-an-alsa-driver.tmpl linux-libre-3.2-gnu1/Documentation/DocBook/writing-an-alsa-driver.tmpl
--- linux-libre-3.1-gnu1/Documentation/DocBook/writing-an-alsa-driver.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/DocBook/writing-an-alsa-driver.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime {
 <![CDATA[
   struct snd_rawmidi *rmidi;
   snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
-                      irq, irq_flags, &rmidi);
+                      irq, &rmidi);
 ]]>
           </programlisting>
         </informalexample>
@@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime {
 	by itself to start processing the output stream in the irq handler.
 	</para>
 
+	<para>
+	If the MPU-401 interface shares its interrupt with the other logical
+	devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
+	(see <link linkend="midi-interface-interrupt-handler"><citetitle>
+	below</citetitle></link>).
+	</para>
+
       <para>
         Usually, the port address corresponds to the command port and
         port + 1 corresponds to the data port. If not, you may change
@@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime {
       </para>
 
       <para>
-        The 6th argument specifies the irq number for UART. If the irq
-      is already allocated, pass 0 to the 7th argument
-      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
-      for irq allocation 
-      (<constant>SA_XXX</constant> bits) to it, and the irq will be
-      reserved by the mpu401-uart layer. If the card doesn't generate
-      UART interrupts, pass -1 as the irq number. Then a timer
-      interrupt will be invoked for polling. 
+	The 6th argument specifies the ISA irq number that will be
+	allocated.  If no interrupt is to be allocated (because your
+	code is already allocating a shared interrupt, or because the
+	device does not use interrupts), pass -1 instead.
+	For a MPU-401 device without an interrupt, a polling timer
+	will be used instead.
       </para>
     </section>
 
@@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime {
       <title>Interrupt Handler</title>
       <para>
         When the interrupt is allocated in
-      <function>snd_mpu401_uart_new()</function>, the private
-      interrupt handler is used, hence you don't have anything else to do
-      than creating the mpu401 stuff. Otherwise, you have to call
-      <function>snd_mpu401_uart_interrupt()</function> explicitly when
-      a UART interrupt is invoked and checked in your own interrupt
-      handler.  
+      <function>snd_mpu401_uart_new()</function>, an exclusive ISA
+      interrupt handler is automatically used, hence you don't have
+      anything else to do than creating the mpu401 stuff.  Otherwise, you
+      have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
+      <function>snd_mpu401_uart_interrupt()</function> explicitly from your
+      own interrupt handler when it has determined that a UART interrupt
+      has occurred.
       </para>
 
       <para>
diff -druNp linux-libre-3.1-gnu1/Documentation/driver-model/binding.txt linux-libre-3.2-gnu1/Documentation/driver-model/binding.txt
--- linux-libre-3.1-gnu1/Documentation/driver-model/binding.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/driver-model/binding.txt	2012-01-04 18:55:44.000000000 -0500
@@ -48,10 +48,6 @@ devclass_add_device is called to enumera
 and actually register it with the class, which happens with the
 class's register_dev callback.
 
-NOTE: The device class structures and core routines to manipulate them
-are not in the mainline kernel, so the discussion is still a bit
-speculative. 
-
 
 Driver
 ~~~~~~
diff -druNp linux-libre-3.1-gnu1/Documentation/driver-model/device.txt linux-libre-3.2-gnu1/Documentation/driver-model/device.txt
--- linux-libre-3.1-gnu1/Documentation/driver-model/device.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/driver-model/device.txt	2012-01-04 18:55:44.000000000 -0500
@@ -45,33 +45,52 @@ struct device_attribute {
 			 const char *buf, size_t count);
 };
 
-Attributes of devices can be exported via drivers using a simple
-procfs-like interface. 
+Attributes of devices can be exported by a device driver through sysfs.
 
 Please see Documentation/filesystems/sysfs.txt for more information
 on how sysfs works.
 
+As explained in Documentation/kobject.txt, device attributes must be be
+created before the KOBJ_ADD uevent is generated. The only way to realize
+that is by defining an attribute group.
+
 Attributes are declared using a macro called DEVICE_ATTR:
 
 #define DEVICE_ATTR(name,mode,show,store)
 
 Example:
 
-DEVICE_ATTR(power,0644,show_power,store_power);
+static DEVICE_ATTR(type, 0444, show_type, NULL);
+static DEVICE_ATTR(power, 0644, show_power, store_power);
 
-This declares a structure of type struct device_attribute named
-'dev_attr_power'. This can then be added and removed to the device's
-directory using:
+This declares two structures of type struct device_attribute with respective
+names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
+organized as follows into a group:
 
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+static struct attribute *dev_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_power.attr,
+	NULL,
+};
 
-Example:
+static struct attribute_group dev_attr_group = {
+	.attrs = dev_attrs,
+};
 
-device_create_file(dev,&dev_attr_power);
-device_remove_file(dev,&dev_attr_power);
+static const struct attribute_group *dev_attr_groups[] = {
+	&dev_attr_group,
+	NULL,
+};
 
-The file name will be 'power' with a mode of 0644 (-rw-r--r--).
+This array of groups can then be associated with a device by setting the
+group pointer in struct device before device_register() is invoked:
+
+      dev->groups = dev_attr_groups;
+      device_register(dev);
+
+The device_register() function will use the 'groups' pointer to create the
+device attributes and the device_unregister() function will use this pointer
+to remove the device attributes.
 
 Word of warning:  While the kernel allows device_create_file() and
 device_remove_file() to be called on a device at any time, userspace has
@@ -84,24 +103,4 @@ not know about the new attributes.
 This is important for device driver that need to publish additional
 attributes for a device at driver probe time.  If the device driver simply
 calls device_create_file() on the device structure passed to it, then
-userspace will never be notified of the new attributes.  Instead, it should
-probably use class_create() and class->dev_attrs to set up a list of
-desired attributes in the modules_init function, and then in the .probe()
-hook, and then use device_create() to create a new device as a child
-of the probed device.  The new device will generate a new uevent and
-properly advertise the new attributes to userspace.
-
-For example, if a driver wanted to add the following attributes:
-struct device_attribute mydriver_attribs[] = {
-	__ATTR(port_count, 0444, port_count_show),
-	__ATTR(serial_number, 0444, serial_number_show),
-	NULL
-};
-
-Then in the module init function is would do:
-	mydriver_class = class_create(THIS_MODULE, "my_attrs");
-	mydriver_class.dev_attr = mydriver_attribs;
-
-And assuming 'dev' is the struct device passed into the probe hook, the driver
-probe function would do something like:
-	device_create(&mydriver_class, dev, chrdev, &private_data, "my_name");
+userspace will never be notified of the new attributes.
diff -druNp linux-libre-3.1-gnu1/Documentation/fault-injection/fault-injection.txt linux-libre-3.2-gnu1/Documentation/fault-injection/fault-injection.txt
--- linux-libre-3.1-gnu1/Documentation/fault-injection/fault-injection.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/fault-injection/fault-injection.txt	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,11 @@ o fail_make_request
   /sys/block/<device>/make-it-fail or
   /sys/block/<device>/<partition>/make-it-fail. (generic_make_request())
 
+o fail_mmc_request
+
+  injects MMC data errors on devices permitted by setting
+  debugfs entries under /sys/kernel/debug/mmc0/fail_mmc_request
+
 Configure fault-injection capabilities behavior
 -----------------------------------------------
 
@@ -115,7 +120,8 @@ use the boot option:
 
 	failslab=
 	fail_page_alloc=
-	fail_make_request=<interval>,<probability>,<space>,<times>
+	fail_make_request=
+	mmc_core.fail_request=<interval>,<probability>,<space>,<times>
 
 How to add new fault injection capability
 -----------------------------------------
diff -druNp linux-libre-3.1-gnu1/Documentation/fb/udlfb.txt linux-libre-3.2-gnu1/Documentation/fb/udlfb.txt
--- linux-libre-3.1-gnu1/Documentation/fb/udlfb.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/fb/udlfb.txt	2012-01-04 18:55:44.000000000 -0500
@@ -87,23 +87,38 @@ Special configuration for udlfb is usual
 options, however.
 
 From the command line, pass options to modprobe
-modprobe udlfb defio=1 console=1
+modprobe udlfb fb_defio=0 console=1 shadow=1
 
-Or for permanent option, create file like /etc/modprobe.d/options with text
-options udlfb defio=1 console=1
+Or modify options on the fly at /sys/module/udlfb/parameters directory via
+sudo nano fb_defio
+change the parameter in place, and save the file.
 
-Accepted options:
+Unplug/replug USB device to apply with new settings
+
+Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text
+options udlfb fb_defio=0 console=1 shadow=1
+
+Accepted boolean options:
 
 fb_defio	Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel
 		module to track changed areas of the framebuffer by page faults.
-        	Standard fbdev applications that use mmap but that do not
-		report damage, may be able to work with this enabled.
-		Disabled by default because of overhead and other issues.
+		Standard fbdev applications that use mmap but that do not
+		report damage, should be able to work with this enabled.
+		Disable when running with X server that supports reporting
+		changed regions via ioctl, as this method is simpler,
+		more stable, and higher performance.
+		default: fb_defio=1
 
-console		Allow fbcon to attach to udlfb provided framebuffers. This
-		is disabled by default because fbcon will aggressively consume
-		the first framebuffer it finds, which isn't usually what the
-		user wants in the case of USB displays.
+console	Allow fbcon to attach to udlfb provided framebuffers.
+		Can be disabled if fbcon and other clients
+		(e.g. X with --shared-vt) are in conflict.
+		default: console=1
+
+shadow		Allocate a 2nd framebuffer to shadow what's currently across
+		the USB bus in device memory. If any pixels are unchanged,
+		do not transmit. Spends host memory to save USB transfers.
+		Enabled by default. Only disable on very low memory systems.
+		default: shadow=1
 
 Sysfs Attributes
 ================
diff -druNp linux-libre-3.1-gnu1/Documentation/feature-removal-schedule.txt linux-libre-3.2-gnu1/Documentation/feature-removal-schedule.txt
--- linux-libre-3.1-gnu1/Documentation/feature-removal-schedule.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/feature-removal-schedule.txt	2012-01-04 18:55:44.000000000 -0500
@@ -133,41 +133,6 @@ Who:	Pavel Machek <pavel@ucw.cz>
 
 ---------------------------
 
-What:	sys_sysctl
-When:	September 2010
-Option: CONFIG_SYSCTL_SYSCALL
-Why:	The same information is available in a more convenient from
-	/proc/sys, and none of the sysctl variables appear to be
-	important performance wise.
-
-	Binary sysctls are a long standing source of subtle kernel
-	bugs and security issues.
-
-	When I looked several months ago all I could find after
-	searching several distributions were 5 user space programs and
-	glibc (which falls back to /proc/sys) using this syscall.
-
-	The man page for sysctl(2) documents it as unusable for user
-	space programs.
-
-	sysctl(2) is not generally ABI compatible to a 32bit user
-	space application on a 64bit and a 32bit kernel.
-
-	For the last several months the policy has been no new binary
-	sysctls and no one has put forward an argument to use them.
-
-	Binary sysctls issues seem to keep happening appearing so
-	properly deprecating them (with a warning to user space) and a
-	2 year grace warning period will mean eventually we can kill
-	them and end the pain.
-
-	In the mean time individual binary sysctls can be dealt with
-	in a piecewise fashion.
-
-Who:	Eric Biederman <ebiederm@xmission.com>
-
----------------------------
-
 What:	/proc/<pid>/oom_adj
 When:	August 2012
 Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
@@ -495,29 +460,6 @@ Who:	Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
 
-What:	Support for UVCIOC_CTRL_ADD in the uvcvideo driver
-When:	3.2
-Why:	The information passed to the driver by this ioctl is now queried
-	dynamically from the device.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What:	Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
-When:	3.2
-Why:	Used only by applications compiled against older driver versions.
-	Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What:	Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
-When:	3.2
-Why:	Superseded by the UVCIOC_CTRL_QUERY ioctl.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
 What:	Support for driver specific ioctls in the pwc driver (everything
 	defined in media/pwc-ioctl.h)
 When:	3.3
@@ -594,9 +536,18 @@ Why:    In 3.0, we can now autodetect in
 Who:    Lee, Chun-Yi <jlee@novell.com>
 
 ----------------------------
+
 What:	The XFS nodelaylog mount option
 When:	3.3
 Why:	The delaylog mode that has been the default since 2.6.39 has proven
 	stable, and the old code is in the way of additional improvements in
 	the log code.
 Who:	Christoph Hellwig <hch@lst.de>
+
+----------------------------
+
+What:	iwlagn alias support
+When:	3.5
+Why:	The iwlagn module has been renamed iwlwifi.  The alias will be around
+	for backward compatibility for several cycles and then dropped.
+Who:	Don Fry <donald.h.fry@intel.com>
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/9p.txt linux-libre-3.2-gnu1/Documentation/filesystems/9p.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/9p.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/9p.txt	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@ OPTIONS
 
   wfdno=n	the file descriptor for writing with trans=fd
 
-  maxdata=n	the number of bytes to use for 9p packet payload (msize)
+  msize=n	the number of bytes to use for 9p packet payload
 
   port=n	port to connect to on the remote server
 
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/btrfs.txt linux-libre-3.2-gnu1/Documentation/filesystems/btrfs.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/btrfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/btrfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -63,8 +63,8 @@ IRC network.
 Userspace tools for creating and manipulating Btrfs file systems are
 available from the git repository at the following location:
 
- http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
- git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git
+ http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git
+ git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git
 
 These include the following tools:
 
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/caching/object.txt linux-libre-3.2-gnu1/Documentation/filesystems/caching/object.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/caching/object.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/caching/object.txt	2012-01-04 18:55:44.000000000 -0500
@@ -127,9 +127,9 @@ fscache_enqueue_object()).
 PROVISION OF CPU TIME
 ---------------------
 
-The work to be done by the various states is given CPU time by the threads of
-the slow work facility (see Documentation/slow-work.txt).  This is used in
-preference to the workqueue facility because:
+The work to be done by the various states was given CPU time by the threads of
+the slow work facility.  This was used in preference to the workqueue facility
+because:
 
  (1) Threads may be completely occupied for very long periods of time by a
      particular work item.  These state actions may be doing sequences of
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/ext3.txt linux-libre-3.2-gnu1/Documentation/filesystems/ext3.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/ext3.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/ext3.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,14 +73,6 @@ nobarrier	(*)	This also requires an IO s
 			also be used to enable or disable barriers, for
 			consistency with other ext3 mount options.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
 user_xattr		Enables Extended User Attributes.  Additionally, you
 			need to have extended attribute support enabled in the
 			kernel configuration (CONFIG_EXT3_FS_XATTR).  See the
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/ext4.txt linux-libre-3.2-gnu1/Documentation/filesystems/ext4.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/ext4.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/ext4.txt	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,9 @@ noload			if the filesystem was not unmou
                      	lead to any number of problems.
 
 data=journal		All data are committed into the journal prior to being
-			written into the main file system.
+			written into the main file system.  Enabling
+			this mode will disable delayed allocation and
+			O_DIRECT support.
 
 data=ordered	(*)	All data are forced directly out to the main file
 			system prior to its metadata being committed to the
@@ -201,30 +203,19 @@ inode_readahead_blks=n	This tuning param
 			table readahead algorithm will pre-read into
 			the buffer cache.  The default value is 32 blocks.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
-user_xattr		Enables Extended User Attributes.  Additionally, you
-			need to have extended attribute support enabled in the
-			kernel configuration (CONFIG_EXT4_FS_XATTR).  See the
-			attr(5) manual page and http://acl.bestbits.at/ to
-			learn more about extended attributes.
-
-nouser_xattr		Disables Extended User Attributes.
-
-acl			Enables POSIX Access Control Lists support.
-			Additionally, you need to have ACL support enabled in
-			the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
-			See the acl(5) manual page and http://acl.bestbits.at/
-			for more information.
+nouser_xattr		Disables Extended User Attributes. If you have extended
+			attribute support enabled in the kernel configuration
+			(CONFIG_EXT4_FS_XATTR), extended attribute support
+			is enabled by default on mount. See the attr(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about extended attributes.
 
 noacl			This option disables POSIX Access Control List
-			support.
+			support. If ACL support is enabled in the kernel
+			configuration (CONFIG_EXT4_FS_POSIX_ACL), ACL is
+			enabled by default on mount. See the acl(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about acl.
 
 bsddf		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
@@ -419,8 +410,8 @@ written to the journal first, and then t
 In the event of a crash, the journal can be replayed, bringing both data and
 metadata into a consistent state.  This mode is the slowest except when data
 needs to be read from and written to disk at the same time where it
-outperforms all others modes.  Currently ext4 does not have delayed
-allocation support if this data journalling mode is selected.
+outperforms all others modes.  Enabling this mode will disable delayed
+allocation and O_DIRECT support.
 
 /proc entries
 =============
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/hfs.txt linux-libre-3.2-gnu1/Documentation/filesystems/hfs.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/hfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/hfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
+Note: This filesystem doesn't have a maintainer.
 
 Macintosh HFS Filesystem for Linux
 ==================================
@@ -76,8 +77,6 @@ hformat that can be used to create HFS f
 Credits
 =======
 
-The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU)
-and is now maintained by Roman Zippel (roman@ardistech.com) at Ardis
-Technologies.
-Roman rewrote large parts of the code and brought in btree routines derived
-from Brad Boyer's hfsplus driver (also maintained by Roman now).
+The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU).
+Roman Zippel (roman@ardistech.com) rewrote large parts of the code and brought
+in btree routines derived from Brad Boyer's hfsplus driver.
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/inotify.txt linux-libre-3.2-gnu1/Documentation/filesystems/inotify.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/inotify.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/inotify.txt	2012-01-04 18:55:44.000000000 -0500
@@ -194,7 +194,8 @@ associated with the inotify_handle, and
 Each watch is associated with an inotify_watch structure.  Watches are chained
 off of each associated inotify_handle and each associated inode.
 
-See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules.
+See fs/notify/inotify/inotify_fsnotify.c and fs/notify/inotify/inotify_user.c
+for the locking and lifetime rules.
 
 
 (vi) Rationale
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/Locking linux-libre-3.2-gnu1/Documentation/filesystems/Locking
--- linux-libre-3.1-gnu1/Documentation/filesystems/Locking	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/Locking	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@ d_hash		no		no		no		maybe
 d_compare:	yes		no		no		maybe
 d_delete:	no		yes		no		no
 d_release:	no		no		yes		no
+d_prune:        no              yes             no              no
 d_iput:		no		no		yes		no
 d_dname:	no		no		no		no
 d_automount:	no		no		yes		no
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/locks.txt linux-libre-3.2-gnu1/Documentation/filesystems/locks.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/locks.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/locks.txt	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,12 @@ fcntl(), with all the problems that impl
 1.3 Mandatory Locking As A Mount Option
 ---------------------------------------
 
-Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt'
-was prior to this release a general configuration option that was valid for
-all mounted filesystems.  This had a number of inherent dangers, not the
-least of which was the ability to freeze an NFS server by asking it to read
-a file for which a mandatory lock existed.
+Mandatory locking, as described in
+'Documentation/filesystems/mandatory-locking.txt' was prior to this release a
+general configuration option that was valid for all mounted filesystems.  This
+had a number of inherent dangers, not the least of which was the ability to
+freeze an NFS server by asking it to read a file for which a mandatory lock
+existed.
 
 From this release of the kernel, mandatory locking can be turned on and off
 on a per-filesystem basis, using the mount options 'mand' and 'nomand'.
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/nfs/idmapper.txt linux-libre-3.2-gnu1/Documentation/filesystems/nfs/idmapper.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/nfs/idmapper.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/nfs/idmapper.txt	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@ request-key will find the first matching
 this case, /some/other/program will handle all uid lookups and
 /usr/sbin/nfs.idmap will handle gid, user, and group lookups.
 
-See <file:Documentation/security/keys-request-keys.txt> for more information
+See <file:Documentation/security/keys-request-key.txt> for more information
 about the request-key function.
 
 
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/pohmelfs/design_notes.txt linux-libre-3.2-gnu1/Documentation/filesystems/pohmelfs/design_notes.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/pohmelfs/design_notes.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/pohmelfs/design_notes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -58,8 +58,9 @@ data transfers.
 POHMELFS clients operate with a working set of servers and are capable of balancing read-only
 operations (like lookups or directory listings) between them according to IO priorities.
 Administrators can add or remove servers from the set at run-time via special commands (described
-in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected
-with write permission turned on. IO priority and permissions can be changed in run-time.
+in Documentation/filesystems/pohmelfs/info.txt file). Writes are replicated to all servers, which
+are connected with write permission turned on. IO priority and permissions can be changed in
+run-time.
 
 POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
 One can select any kernel supported cipher, encryption mode, hash type and operation mode
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/proc.txt linux-libre-3.2-gnu1/Documentation/filesystems/proc.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/proc.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/proc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1263,7 +1263,7 @@ review the kernel documentation in the d
 This chapter  is  heavily  based  on the documentation included in the pre 2.2
 kernels, and became part of it in version 2.2.1 of the Linux kernel.
 
-Please see: Documentation/sysctls/ directory for descriptions of these
+Please see: Documentation/sysctl/ directory for descriptions of these
 entries.
 
 ------------------------------------------------------------------------------
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/sysfs.txt linux-libre-3.2-gnu1/Documentation/filesystems/sysfs.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/sysfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/sysfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting k
 Patrick Mochel	<mochel@osdl.org>
 Mike Murphy <mamurph@cs.clemson.edu>
 
-Revised:    15 July 2010
+Revised:    16 August 2011
 Original:   10 January 2003
 
 
@@ -370,3 +370,11 @@ int driver_create_file(struct device_dri
 void driver_remove_file(struct device_driver *, const struct driver_attribute *);
 
 
+Documentation
+~~~~~~~~~~~~~
+
+The sysfs directory structure and the attributes in each directory define an
+ABI between the kernel and user space. As for any ABI, it is important that
+this ABI is stable and properly documented. All new sysfs attributes must be
+documented in Documentation/ABI. See also Documentation/ABI/README for more
+information.
diff -druNp linux-libre-3.1-gnu1/Documentation/filesystems/vfs.txt linux-libre-3.2-gnu1/Documentation/filesystems/vfs.txt
--- linux-libre-3.1-gnu1/Documentation/filesystems/vfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/filesystems/vfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1053,9 +1053,6 @@ manipulate dentries:
 	and the dentry is returned. The caller must use dput()
 	to free the dentry when it finishes using it.
 
-For further information on dentry locking, please refer to the document
-Documentation/filesystems/dentry-locking.txt.
-
 Mount Options
 =============
 
diff -druNp linux-libre-3.1-gnu1/Documentation/frv/booting.txt linux-libre-3.2-gnu1/Documentation/frv/booting.txt
--- linux-libre-3.1-gnu1/Documentation/frv/booting.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/frv/booting.txt	2012-01-04 18:55:44.000000000 -0500
@@ -180,9 +180,3 @@ separated by spaces:
 
       This tells the kernel what program to run initially. By default this is
       /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
-
-  (*) vdc=...
-
-      This option configures the MB93493 companion chip visual display
-      driver. Please see Documentation/frv/mb93493/vdc.txt for more
-      information.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/ad7314 linux-libre-3.2-gnu1/Documentation/hwmon/ad7314
--- linux-libre-3.1-gnu1/Documentation/hwmon/ad7314	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/hwmon/ad7314	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+Kernel driver ad7314
+====================
+
+Supported chips:
+   * Analog Devices AD7314
+     Prefix: 'ad7314'
+     Datasheet: Publicly available at Analog Devices website.
+   * Analog Devices ADT7301
+     Prefix: 'adt7301'
+     Datasheet: Publicly available at Analog Devices website.
+   * Analog Devices ADT7302
+     Prefix: 'adt7302'
+     Datasheet: Publicly available at Analog Devices website.
+
+Description
+-----------
+
+Driver supports the above parts.  The ad7314 has a 10 bit
+sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and
+adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade.
+
+Notes
+-----
+
+Currently power down mode is not supported.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/adm1275 linux-libre-3.2-gnu1/Documentation/hwmon/adm1275
--- linux-libre-3.1-gnu1/Documentation/hwmon/adm1275	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/hwmon/adm1275	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,10 @@ Supported chips:
     Prefix: 'adm1275'
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf
+  * Analog Devices ADM1276
+    Prefix: 'adm1276'
+    Addresses scanned: -
+    Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
 
 Author: Guenter Roeck <guenter.roeck@ericsson.com>
 
@@ -13,13 +17,13 @@ Author: Guenter Roeck <guenter.roeck@eri
 Description
 -----------
 
-This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap
-Controller and Digital Power Monitor.
+This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
+Hot-Swap Controller and Digital Power Monitor.
 
-The ADM1275 is a hot-swap controller that allows a circuit board to be removed
-from or inserted into a live backplane. It also features current and voltage
-readback via an integrated 12-bit analog-to-digital converter (ADC), accessed
-using a PMBus. interface.
+ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be
+removed from or inserted into a live backplane. They also feature current and
+voltage readback via an integrated 12-bit analog-to-digital converter (ADC),
+accessed using a PMBus interface.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -48,17 +52,25 @@ attributes are write-only, all other att
 
 in1_label		"vin1" or "vout1" depending on chip variant and
 			configuration.
-in1_input		Measured voltage. From READ_VOUT register.
-in1_min			Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
-in1_max			Maximum voltage. From VOUT_OV_WARN_LIMIT register.
-in1_min_alarm		Voltage low alarm. From VOLTAGE_UV_WARNING status.
-in1_max_alarm		Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_input		Measured voltage.
+in1_min			Minumum Voltage.
+in1_max			Maximum voltage.
+in1_min_alarm		Voltage low alarm.
+in1_max_alarm		Voltage high alarm.
 in1_highest		Historical maximum voltage.
 in1_reset_history	Write any value to reset history.
 
 curr1_label		"iout1"
-curr1_input		Measured current. From READ_IOUT register.
-curr1_max		Maximum current. From IOUT_OC_WARN_LIMIT register.
-curr1_max_alarm		Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_input		Measured current.
+curr1_max		Maximum current.
+curr1_max_alarm		Current high alarm.
+curr1_lcrit		Critical minimum current. Depending on the chip
+			configuration, either curr1_lcrit or curr1_crit is
+			supported, but not both.
+curr1_lcrit_alarm	Critical current low alarm.
+curr1_crit		Critical maximum current. Depending on the chip
+			configuration, either curr1_lcrit or curr1_crit is
+			supported, but not both.
+curr1_crit_alarm	Critical current high alarm.
 curr1_highest		Historical maximum current.
 curr1_reset_history	Write any value to reset history.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/exynos4_tmu linux-libre-3.2-gnu1/Documentation/hwmon/exynos4_tmu
--- linux-libre-3.1-gnu1/Documentation/hwmon/exynos4_tmu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/hwmon/exynos4_tmu	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+Kernel driver exynos4_tmu
+=================
+
+Supported chips:
+* ARM SAMSUNG EXYNOS4 series of SoC
+  Prefix: 'exynos4-tmu'
+  Datasheet: Not publicly available
+
+Authors: Donggeun Kim <dg77.kim@samsung.com>
+
+Description
+-----------
+
+This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
+
+The chip only exposes the measured 8-bit temperature code value
+through a register.
+Temperature can be taken from the temperature code.
+There are three equations converting from temperature to temperature code.
+
+The three equations are:
+  1. Two point trimming
+	Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1
+
+  2. One point trimming
+	Tc = T + TI1 - 25
+
+  3. No trimming
+	Tc = T + 50
+
+  Tc: Temperature code, T: Temperature,
+  TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 25 degree Celsius which is unchanged
+  TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 85 degree Celsius which is unchanged
+
+TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
+when temperature exceeds pre-defined levels.
+The maximum number of configurable threshold is four.
+The threshold levels are defined as follows:
+  Level_0: current temperature > trigger_level_0 + threshold
+  Level_1: current temperature > trigger_level_1 + threshold
+  Level_2: current temperature > trigger_level_2 + threshold
+  Level_3: current temperature > trigger_level_3 + threshold
+
+  The threshold and each trigger_level are set
+  through the corresponding registers.
+
+When an interrupt occurs, this driver notify user space of
+one of four threshold levels for the interrupt
+through kobject_uevent_env and sysfs_notify functions.
+Although an interrupt condition for level_0 can be set,
+it is not notified to user space through sysfs_notify function.
+
+Sysfs Interface
+---------------
+name		name of the temperature sensor
+		RO
+
+temp1_input	temperature
+		RO
+
+temp1_max	temperature for level_1 interrupt
+		RO
+
+temp1_crit	temperature for level_2 interrupt
+		RO
+
+temp1_emergency	temperature for level_3 interrupt
+		RO
+
+temp1_max_alarm	alarm for level_1 interrupt
+		RO
+
+temp1_crit_alarm
+		alarm for level_2 interrupt
+		RO
+
+temp1_emergency_alarm
+		alarm for level_3 interrupt
+		RO
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/lm75 linux-libre-3.2-gnu1/Documentation/hwmon/lm75
--- linux-libre-3.1-gnu1/Documentation/hwmon/lm75	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/hwmon/lm75	2012-01-04 18:55:44.000000000 -0500
@@ -12,26 +12,46 @@ Supported chips:
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
-  * Dallas Semiconductor DS75
-    Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4f
-    Datasheet: Publicly available at the Dallas Semiconductor website
-               http://www.maxim-ic.com/
-  * Dallas Semiconductor DS1775
-    Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4f
+  * Dallas Semiconductor DS75, DS1775
+    Prefixes: 'ds75', 'ds1775'
+    Addresses scanned: none
     Datasheet: Publicly available at the Dallas Semiconductor website
                http://www.maxim-ic.com/
   * Maxim MAX6625, MAX6626
-    Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4b
+    Prefixes: 'max6625', 'max6626'
+    Addresses scanned: none
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/
   * Microchip (TelCom) TCN75
     Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4f
+    Addresses scanned: none
+    Datasheet: Publicly available at the Microchip website
+               http://www.microchip.com/
+  * Microchip MCP9800, MCP9801, MCP9802, MCP9803
+    Prefix: 'mcp980x'
+    Addresses scanned: none
     Datasheet: Publicly available at the Microchip website
                http://www.microchip.com/
+  * Analog Devices ADT75
+    Prefix: 'adt75'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/adt75
+  * ST Microelectronics STDS75
+    Prefix: 'stds75'
+    Addresses scanned: none
+    Datasheet: Publicly available at the ST website
+               http://www.st.com/internet/analog/product/121769.jsp
+  * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275
+    Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/product/tmp100
+               http://www.ti.com/product/tmp101
+               http://www.ti.com/product/tmp105
+               http://www.ti.com/product/tmp75
+               http://www.ti.com/product/tmp175
+               http://www.ti.com/product/tmp275
 
 Author: Frodo Looijaard <frodol@dds.nl>
 
@@ -50,21 +70,16 @@ range of -55 to +125 degrees.
 The LM75 only updates its values each 1.5 seconds; reading it more often
 will do no harm, but will return 'old' values.
 
-The LM75 is usually used in combination with LM78-like chips, to measure
-the temperature of the processor(s).
-
-The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
-They are not distinguished from an LM75. While most of these chips
-have three additional bits of accuracy (12 vs. 9 for the LM75),
-the additional bits are not supported. Not only that, but these chips will
-not be detected if not in 9-bit precision mode (use the force parameter if
-needed).
-
-The TCN75 is supported as well, and is not distinguished from an LM75.
+The original LM75 was typically used in combination with LM78-like chips
+on PC motherboards, to measure the temperature of the processor(s). Clones
+are now used in various embedded designs.
 
 The LM75 is essentially an industry standard; there may be other
 LM75 clones not listed here, with or without various enhancements,
-that are supported.
+that are supported. The clones are not detected by the driver, unless
+they reproduce the exact register tricks of the original LM75, and must
+therefore be instantiated explicitly. The specific enhancements (such as
+higher resolution) are not currently supported by the driver.
 
 The LM77 is not supported, contrary to what we pretended for a long time.
 Both chips are simply not compatible, value encoding differs.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/ltc2978 linux-libre-3.2-gnu1/Documentation/hwmon/ltc2978
--- linux-libre-3.1-gnu1/Documentation/hwmon/ltc2978	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/hwmon/ltc2978	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,103 @@
+Kernel driver ltc2978
+=====================
+
+Supported chips:
+  * Linear Technology LTC2978
+    Prefix: 'ltc2978'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+  * Linear Technology LTC3880
+    Prefix: 'ltc3880'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC2978 is an octal power supply monitor, supervisor, sequencer and
+margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous
+step-down switching regulator controller.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices. You will have to instantiate
+devices explicitly.
+
+Example: the following commands will load the driver for an LTC2978 at address
+0x60 on I2C bus #1:
+
+# modprobe ltc2978
+# echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs attributes
+----------------
+
+in1_label		"vin"
+in1_input		Measured input voltage.
+in1_min			Minimum input voltage.
+in1_max			Maximum input voltage.
+in1_lcrit		Critical minimum input voltage.
+in1_crit		Critical maximum input voltage.
+in1_min_alarm		Input voltage low alarm.
+in1_max_alarm		Input voltage high alarm.
+in1_lcrit_alarm		Input voltage critical low alarm.
+in1_crit_alarm		Input voltage critical high alarm.
+in1_lowest		Lowest input voltage. LTC2978 only.
+in1_highest		Highest input voltage.
+in1_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+in[2-9]_label		"vout[1-8]". Channels 3 to 9 on LTC2978 only.
+in[2-9]_input		Measured output voltage.
+in[2-9]_min		Minimum output voltage.
+in[2-9]_max		Maximum output voltage.
+in[2-9]_lcrit		Critical minimum output voltage.
+in[2-9]_crit		Critical maximum output voltage.
+in[2-9]_min_alarm	Output voltage low alarm.
+in[2-9]_max_alarm	Output voltage high alarm.
+in[2-9]_lcrit_alarm	Output voltage critical low alarm.
+in[2-9]_crit_alarm	Output voltage critical high alarm.
+in[2-9]_lowest		Lowest output voltage. LTC2978 only.
+in[2-9]_highest		Lowest output voltage.
+in[2-9]_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+temp[1-3]_input		Measured temperature.
+			On LTC2978, only one temperature measurement is
+			supported and reflects the internal temperature.
+			On LTC3880, temp1 and temp2 report external
+			temperatures, and temp3 reports the internal
+			temperature.
+temp[1-3]_min		Mimimum temperature.
+temp[1-3]_max		Maximum temperature.
+temp[1-3]_lcrit		Critical low temperature.
+temp[1-3]_crit		Critical high temperature.
+temp[1-3]_min_alarm	Chip temperature low alarm.
+temp[1-3]_max_alarm	Chip temperature high alarm.
+temp[1-3]_lcrit_alarm	Chip temperature critical low alarm.
+temp[1-3]_crit_alarm	Chip temperature critical high alarm.
+temp[1-3]_lowest	Lowest measured temperature. LTC2978 only.
+temp[1-3]_highest	Highest measured temperature.
+temp[1-3]_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+power[1-2]_label	"pout[1-2]". LTC3880 only.
+power[1-2]_input	Measured power.
+
+curr1_label		"iin". LTC3880 only.
+curr1_input		Measured input current.
+curr1_max		Maximum input current.
+curr1_max_alarm		Input current high alarm.
+
+curr[2-3]_label		"iout[1-2]". LTC3880 only.
+curr[2-3]_input		Measured input current.
+curr[2-3]_max		Maximum input current.
+curr[2-3]_crit		Critical input current.
+curr[2-3]_max_alarm	Input current high alarm.
+curr[2-3]_crit_alarm	Input current critical high alarm.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/pmbus linux-libre-3.2-gnu1/Documentation/hwmon/pmbus
--- linux-libre-3.1-gnu1/Documentation/hwmon/pmbus	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/hwmon/pmbus	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,6 @@ Supported chips:
     Addresses scanned: -
     Datasheet:
  http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
-  * Linear Technology LTC2978
-    Octal PMBus Power Supply Monitor and Controller
-    Prefix: 'ltc2978'
-    Addresses scanned: -
-    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
   * ON Semiconductor ADP4000, NCP4200, NCP4208
     Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
     Addresses scanned: -
@@ -20,6 +15,14 @@ Supported chips:
 	http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
 	http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
 	http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
+  * Lineage Power
+    Prefixes: 'pdt003', 'pdt006', 'pdt012', 'udt020'
+    Addresses scanned: -
+    Datasheets:
+	http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf
+	http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf
+	http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
+	http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/pmbus-core linux-libre-3.2-gnu1/Documentation/hwmon/pmbus-core
--- linux-libre-3.1-gnu1/Documentation/hwmon/pmbus-core	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/hwmon/pmbus-core	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,283 @@
+PMBus core driver and internal API
+==================================
+
+Introduction
+============
+
+[from pmbus.org] The Power Management Bus (PMBus) is an open standard
+power-management protocol with a fully defined command language that facilitates
+communication with power converters and other devices in a power system. The
+protocol is implemented over the industry-standard SMBus serial interface and
+enables programming, control, and real-time monitoring of compliant power
+conversion products. This flexible and highly versatile standard allows for
+communication between devices based on both analog and digital technologies, and
+provides true interoperability which will reduce design complexity and shorten
+time to market for power system designers. Pioneered by leading power supply and
+semiconductor companies, this open power system standard is maintained and
+promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
+with the objective to provide support to, and facilitate adoption among, users.
+
+Unfortunately, while PMBus commands are standardized, there are no mandatory
+commands, and manufacturers can add as many non-standard commands as they like.
+Also, different PMBUs devices act differently if non-supported commands are
+executed. Some devices return an error, some devices return 0xff or 0xffff and
+set a status error flag, and some devices may simply hang up.
+
+Despite all those difficulties, a generic PMBus device driver is still useful
+and supported since kernel version 2.6.39. However, it was necessary to support
+device specific extensions in addition to the core PMBus driver, since it is
+simply unknown what new device specific functionality PMBus device developers
+come up with next.
+
+To make device specific extensions as scalable as possible, and to avoid having
+to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
+split into core, generic, and device specific code. The core code (in
+pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
+provides support for generic PMBus devices. Device specific code is responsible
+for device specific initialization and, if needed, maps device specific
+functionality into generic functionality. This is to some degree comparable
+to PCI code, where generic code is augmented as needed with quirks for all kinds
+of devices.
+
+PMBus device capabilities auto-detection
+========================================
+
+For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
+PMBus commands. Auto-detection is somewhat limited, since there are simply too
+many variables to consider. For example, it is almost impossible to autodetect
+which PMBus commands are paged and which commands are replicated across all
+pages (see the PMBus specification for details on multi-page PMBus devices).
+
+For this reason, it often makes sense to provide a device specific driver if not
+all commands can be auto-detected. The data structures in this driver can be
+used to inform the core driver about functionality supported by individual
+chips.
+
+Some commands are always auto-detected. This applies to all limit commands
+(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
+Limits and alarm attributes are auto-detected because there are simply too many
+possible combinations to provide a manual configuration interface.
+
+PMBus internal API
+==================
+
+The API between core and device specific PMBus code is defined in
+drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
+standard PMBus commands and virtual PMBus commands.
+
+Standard PMBus commands
+-----------------------
+
+Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
+specification.
+
+Virtual PMBus commands
+----------------------
+
+Virtual PMBus commands are provided to enable support for non-standard
+functionality which has been implemented by several chip vendors and is thus
+desirable to support.
+
+Virtual PMBus commands start with command value 0x100 and can thus easily be
+distinguished from standard PMBus commands (which can not have values larger
+than 0xff). Support for virtual PMBus commands is device specific and thus has
+to be implemented in device specific code.
+
+Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
+virtual commands are word sized.
+
+There are currently two types of virtual commands.
+
+- READ commands are read-only; writes are either ignored or return an error.
+- RESET commands are read/write. Reading reset registers returns zero
+  (used for detection), writing any value causes the associated history to be
+  reset.
+
+Virtual commands have to be handled in device specific driver code. Chip driver
+code returns non-negative values if a virtual command is supported, or a
+negative error code if not. The chip driver may return -ENODATA or any other
+Linux error code in this case, though an error code other than -ENODATA is
+handled more efficiently and thus preferred. Either case, the calling PMBus
+core code will abort if the chip driver returns an error code when reading
+or writing virtual registers (in other words, the PMBus core code will never
+send a virtual command to a chip).
+
+PMBus driver information
+------------------------
+
+PMBus driver information, defined in struct pmbus_driver_info, is the main means
+for device specific drivers to pass information to the core PMBus driver.
+Specifically, it provides the following information.
+
+- For devices supporting its data in Direct Data Format, it provides coefficients
+  for converting register values into normalized data. This data is usually
+  provided by chip manufacturers in device datasheets.
+- Supported chip functionality can be provided to the core driver. This may be
+  necessary for chips which react badly if non-supported commands are executed,
+  and/or to speed up device detection and initialization.
+- Several function entry points are provided to support overriding and/or
+  augmenting generic command execution. This functionality can be used to map
+  non-standard PMBus commands to standard commands, or to augment standard
+  command return values with device specific information.
+
+  API functions
+  -------------
+
+  Functions provided by chip driver
+  ---------------------------------
+
+  All functions return the command return value (read) or zero (write) if
+  successful. A return value of -ENODATA indicates that there is no manufacturer
+  specific command, but that a standard PMBus command may exist. Any other
+  negative return value indicates that the commands does not exist for this
+  chip, and that no attempt should be made to read or write the standard
+  command.
+
+  As mentioned above, an exception to this rule applies to virtual commands,
+  which  _must_ be handled in driver specific code. See "Virtual PMBus Commands"
+  above for more details.
+
+  Command execution in the core PMBus driver code is as follows.
+
+	if (chip_access_function) {
+		status = chip_access_function();
+		if (status != -ENODATA)
+			return status;
+	}
+	if (command >= PMBUS_VIRT_BASE)	/* For word commands/registers only */
+		return -EINVAL;
+	return generic_access();
+
+  Chip drivers may provide pointers to the following functions in struct
+  pmbus_driver_info. All functions are optional.
+
+  int (*read_byte_data)(struct i2c_client *client, int page, int reg);
+
+  Read byte from page <page>, register <reg>.
+  <page> may be -1, which means "current page".
+
+  int (*read_word_data)(struct i2c_client *client, int page, int reg);
+
+  Read word from page <page>, register <reg>.
+
+  int (*write_word_data)(struct i2c_client *client, int page, int reg,
+		         u16 word);
+
+  Write word to page <page>, register <reg>.
+
+  int (*write_byte)(struct i2c_client *client, int page, u8 value);
+
+  Write byte to page <page>, register <reg>.
+  <page> may be -1, which means "current page".
+
+  int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
+
+  Determine supported PMBus functionality. This function is only necessary
+  if a chip driver supports multiple chips, and the chip functionality is not
+  pre-determined. It is currently only used by the generic pmbus driver
+  (pmbus.c).
+
+  Functions exported by core driver
+  ---------------------------------
+
+  Chip drivers are expected to use the following functions to read or write
+  PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
+  commands are used, the chip driver code must not directly modify the current
+  page, since the selected page is cached in the core driver and the core driver
+  will assume that it is selected. Using pmbus_set_page() to select a new page
+  is mandatory.
+
+  int pmbus_set_page(struct i2c_client *client, u8 page);
+
+  Set PMBus page register to <page> for subsequent commands.
+
+  int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+
+  Read word data from <page>, <reg>. Similar to i2c_smbus_read_word_data(), but
+  selects page first.
+
+  int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
+			    u16 word);
+
+  Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
+  selects page first.
+
+  int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
+
+  Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
+  selects page first. <page> may be -1, which means "current page".
+
+  int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
+
+  Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
+  selects page first. <page> may be -1, which means "current page".
+
+  void pmbus_clear_faults(struct i2c_client *client);
+
+  Execute PMBus "Clear Fault" command on all chip pages.
+  This function calls the device specific write_byte function if defined.
+  Therefore, it must _not_ be called from that function.
+
+  bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
+
+  Check if byte register exists. Return true if the register exists, false
+  otherwise.
+  This function calls the device specific write_byte function if defined to
+  obtain the chip status. Therefore, it must _not_ be called from that function.
+
+  bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
+
+  Check if word register exists. Return true if the register exists, false
+  otherwise.
+  This function calls the device specific write_byte function if defined to
+  obtain the chip status. Therefore, it must _not_ be called from that function.
+
+  int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+                     struct pmbus_driver_info *info);
+
+  Execute probe function. Similar to standard probe function for other drivers,
+  with the pointer to struct pmbus_driver_info as additional argument. Calls
+  identify function if supported. Must only be called from device probe
+  function.
+
+  void pmbus_do_remove(struct i2c_client *client);
+
+  Execute driver remove function. Similar to standard driver remove function.
+
+  const struct pmbus_driver_info
+	*pmbus_get_driver_info(struct i2c_client *client);
+
+  Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
+
+
+PMBus driver platform data
+==========================
+
+PMBus platform data is defined in include/linux/i2c/pmbus.h. Platform data
+currently only provides a flag field with a single bit used.
+
+#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
+
+struct pmbus_platform_data {
+        u32 flags;              /* Device specific flags */
+};
+
+
+Flags
+-----
+
+PMBUS_SKIP_STATUS_CHECK
+
+During register detection, skip checking the status register for
+communication or command errors.
+
+Some PMBus chips respond with valid data when trying to read an unsupported
+register. For such chips, checking the status register is mandatory when
+trying to determine if a chip register exists or not.
+Other PMBus chips don't support the STATUS_CML register, or report
+communication errors for no explicable reason. For such chips, checking the
+status register must be disabled.
+
+Some i2c controllers do not support single-byte commands (write commands with
+no data, i2c_smbus_write_byte()). With such controllers, clearing the status
+register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/w83627ehf linux-libre-3.2-gnu1/Documentation/hwmon/w83627ehf
--- linux-libre-3.1-gnu1/Documentation/hwmon/w83627ehf	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/hwmon/w83627ehf	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,10 @@ Supported chips:
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: not available
+  * Winbond W83627UHG
+    Prefix: 'w83627uhg'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: available from www.nuvoton.com
   * Winbond W83667HG
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -42,14 +46,13 @@ Description
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
-and NCT6776F super I/O chips. We will refer to them collectively as
-Winbond chips.
+W83627DHG, W83627DHG-P, W83627UHG, W83667HG, W83667HG-B, W83667HG-I
+(NCT6775F), and NCT6776F super I/O chips. We will refer to them collectively
+as Winbond chips.
 
-The chips implement three temperature sensors (up to four for 667HG-B, and nine
-for NCT6775F and NCT6776F), five fan rotation speed sensors, ten analog voltage
-sensors (only nine for the 627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins
-for the 627DHG and 667HG), alarms with beep warnings (control unimplemented),
+The chips implement 2 to 4 temperature sensors (9 for NCT6775F and NCT6776F),
+2 to 5 fan rotation speed sensors, 8 to 10 analog voltage sensors, one VID
+(except for 627UHG), alarms with beep warnings (control unimplemented),
 and some automatic fan regulation strategies (plus manual fan control mode).
 
 The temperature sensor sources on W82677HG-B, NCT6775F, and NCT6776F are
@@ -86,17 +89,16 @@ follows:
 
 temp1 -> pwm1
 temp2 -> pwm2
-temp3 -> pwm3
+temp3 -> pwm3 (not on 627UHG)
 prog  -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
 	       supported by the driver)
 
 /sys files
 ----------
 
-name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
-       it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
-       for the W83667HG and W83667HG-B it is set to "w83667hg", for NCT6775F it
-       is set to "nct6775", and for NCT6776F it is set to "nct6776".
+name - this is a standard hwmon device entry, it contains the name of
+       the device (see the prefix in the list of supported devices at
+       the top of this file)
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
diff -druNp linux-libre-3.1-gnu1/Documentation/hwmon/zl6100 linux-libre-3.2-gnu1/Documentation/hwmon/zl6100
--- linux-libre-3.1-gnu1/Documentation/hwmon/zl6100	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/hwmon/zl6100	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,125 @@
+Kernel driver zl6100
+====================
+
+Supported chips:
+  * Intersil / Zilker Labs ZL2004
+    Prefix: 'zl2004'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6847.pdf
+  * Intersil / Zilker Labs ZL2006
+    Prefix: 'zl2006'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6850.pdf
+  * Intersil / Zilker Labs ZL2008
+    Prefix: 'zl2008'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6859.pdf
+  * Intersil / Zilker Labs ZL2105
+    Prefix: 'zl2105'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6851.pdf
+  * Intersil / Zilker Labs ZL2106
+    Prefix: 'zl2106'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6852.pdf
+  * Intersil / Zilker Labs ZL6100
+    Prefix: 'zl6100'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6876.pdf
+  * Intersil / Zilker Labs ZL6105
+    Prefix: 'zl6105'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6906.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Intersil / Zilker Labs ZL6100 and
+compatible digital DC-DC controllers.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus and Documentation.hwmon/pmbus-core for details
+on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+WARNING: Do not access chip registers using the i2cdump command, and do not use
+any of the i2ctools commands on a command register used to save and restore
+configuration data (0x11, 0x12, 0x15, 0x16, and 0xf4). The chips supported by
+this driver interpret any access to those command registers (including read
+commands) as request to execute the command in question. Unless write accesses
+to those registers are protected, this may result in power loss, board resets,
+and/or Flash corruption. Worst case, your board may turn into a brick.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Module parameters
+-----------------
+
+delay
+-----
+
+Some Intersil/Zilker Labs DC-DC controllers require a minimum interval between
+I2C bus accesses. According to Intersil, the minimum interval is 2 ms, though
+1 ms appears to be sufficient and has not caused any problems in testing.
+The problem is known to affect ZL6100, ZL2105, and ZL2008. It is known not to
+affect ZL2004 and ZL6105. The driver automatically sets the interval to 1 ms
+except for ZL2004 and ZL6105. To enable manual override, the driver provides a
+writeable module parameter, 'delay', which can be used to set the interval to
+a value between 0 and 65,535 microseconds.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label		"vin"
+in1_input		Measured input voltage.
+in1_min			Minimum input voltage.
+in1_max			Maximum input voltage.
+in1_lcrit		Critical minumum input voltage.
+in1_crit		Critical maximum input voltage.
+in1_min_alarm		Input voltage low alarm.
+in1_max_alarm		Input voltage high alarm.
+in1_lcrit_alarm		Input voltage critical low alarm.
+in1_crit_alarm		Input voltage critical high alarm.
+
+in2_label		"vout1"
+in2_input		Measured output voltage.
+in2_lcrit		Critical minumum output Voltage.
+in2_crit		Critical maximum output voltage.
+in2_lcrit_alarm		Critical output voltage critical low alarm.
+in2_crit_alarm		Critical output voltage critical high alarm.
+
+curr1_label		"iout1"
+curr1_input		Measured output current.
+curr1_lcrit		Critical minimum output current.
+curr1_crit		Critical maximum output current.
+curr1_lcrit_alarm	Output current critical low alarm.
+curr1_crit_alarm	Output current critical high alarm.
+
+temp[12]_input		Measured temperature.
+temp[12]_min		Minimum temperature.
+temp[12]_max		Maximum temperature.
+temp[12]_lcrit		Critical low temperature.
+temp[12]_crit		Critical high temperature.
+temp[12]_min_alarm	Chip temperature low alarm.
+temp[12]_max_alarm	Chip temperature high alarm.
+temp[12]_lcrit_alarm	Chip temperature critical low alarm.
+temp[12]_crit_alarm	Chip temperature critical high alarm.
diff -druNp linux-libre-3.1-gnu1/Documentation/hwspinlock.txt linux-libre-3.2-gnu1/Documentation/hwspinlock.txt
--- linux-libre-3.1-gnu1/Documentation/hwspinlock.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/hwspinlock.txt	2012-01-04 18:55:44.000000000 -0500
@@ -39,23 +39,20 @@ independent, drivers.
      in case an unused hwspinlock isn't available. Users of this
      API will usually want to communicate the lock's id to the remote core
      before it can be used to achieve synchronization.
-     Can be called from an atomic context (this function will not sleep) but
-     not from within interrupt context.
+     Should be called from a process context (might sleep).
 
   struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
    - assign a specific hwspinlock id and return its address, or NULL
      if that hwspinlock is already in use. Usually board code will
      be calling this function in order to reserve specific hwspinlock
      ids for predefined purposes.
-     Can be called from an atomic context (this function will not sleep) but
-     not from within interrupt context.
+     Should be called from a process context (might sleep).
 
   int hwspin_lock_free(struct hwspinlock *hwlock);
    - free a previously-assigned hwspinlock; returns 0 on success, or an
      appropriate error code on failure (e.g. -EINVAL if the hwspinlock
      is already free).
-     Can be called from an atomic context (this function will not sleep) but
-     not from within interrupt context.
+     Should be called from a process context (might sleep).
 
   int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
    - lock a previously-assigned hwspinlock with a timeout limit (specified in
@@ -230,45 +227,62 @@ int hwspinlock_example2(void)
 
 4. API for implementors
 
-  int hwspin_lock_register(struct hwspinlock *hwlock);
+  int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+		const struct hwspinlock_ops *ops, int base_id, int num_locks);
    - to be called from the underlying platform-specific implementation, in
-     order to register a new hwspinlock instance. Can be called from an atomic
-     context (this function will not sleep) but not from within interrupt
-     context. Returns 0 on success, or appropriate error code on failure.
+     order to register a new hwspinlock device (which is usually a bank of
+     numerous locks). Should be called from a process context (this function
+     might sleep).
+     Returns 0 on success, or appropriate error code on failure.
 
-  struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+  int hwspin_lock_unregister(struct hwspinlock_device *bank);
    - to be called from the underlying vendor-specific implementation, in order
-     to unregister an existing (and unused) hwspinlock instance.
-     Can be called from an atomic context (will not sleep) but not from
-     within interrupt context.
+     to unregister an hwspinlock device (which is usually a bank of numerous
+     locks).
+     Should be called from a process context (this function might sleep).
      Returns the address of hwspinlock on success, or NULL on error (e.g.
      if the hwspinlock is sill in use).
 
-5. struct hwspinlock
+5. Important structs
 
-This struct represents an hwspinlock instance. It is registered by the
-underlying hwspinlock implementation using the hwspin_lock_register() API.
+struct hwspinlock_device is a device which usually contains a bank
+of hardware locks. It is registered by the underlying hwspinlock
+implementation using the hwspin_lock_register() API.
 
 /**
- * struct hwspinlock - vendor-specific hwspinlock implementation
- *
- * @dev: underlying device, will be used with runtime PM api
- * @ops: vendor-specific hwspinlock handlers
- * @id: a global, unique, system-wide, index of the lock.
- * @lock: initialized and used by hwspinlock core
- * @owner: underlying implementation module, used to maintain module ref count
+ * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
  */
-struct hwspinlock {
+struct hwspinlock_device {
 	struct device *dev;
 	const struct hwspinlock_ops *ops;
-	int id;
+	int base_id;
+	int num_locks;
+	struct hwspinlock lock[0];
+};
+
+struct hwspinlock_device contains an array of hwspinlock structs, each
+of which represents a single hardware lock:
+
+/**
+ * struct hwspinlock - this struct represents a single hwspinlock instance
+ * @bank: the hwspinlock_device structure which owns this lock
+ * @lock: initialized and used by hwspinlock core
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
+ */
+struct hwspinlock {
+	struct hwspinlock_device *bank;
 	spinlock_t lock;
-	struct module *owner;
+	void *priv;
 };
 
-The underlying implementation is responsible to assign the dev, ops, id and
-owner members. The lock member, OTOH, is initialized and used by the hwspinlock
-core.
+When registering a bank of locks, the hwspinlock driver only needs to
+set the priv members of the locks. The rest of the members are set and
+initialized by the hwspinlock core itself.
 
 6. Implementation callbacks
 
diff -druNp linux-libre-3.1-gnu1/Documentation/i2c/smbus-protocol linux-libre-3.2-gnu1/Documentation/i2c/smbus-protocol
--- linux-libre-3.1-gnu1/Documentation/i2c/smbus-protocol	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/i2c/smbus-protocol	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,10 @@ byte. But this time, the data is a compl
 
 S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
 
+Note the convenience function i2c_smbus_read_word_swapped is
+available for reads where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
 
 SMBus Write Byte:  i2c_smbus_write_byte_data()
 ==============================================
@@ -108,6 +112,10 @@ specified through the Comm byte.
 
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
 
+Note the convenience function i2c_smbus_write_word_swapped is
+available for writes where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
 
 SMBus Process Call:  i2c_smbus_process_call()
 =============================================
diff -druNp linux-libre-3.1-gnu1/Documentation/i2c/ten-bit-addresses linux-libre-3.2-gnu1/Documentation/i2c/ten-bit-addresses
--- linux-libre-3.1-gnu1/Documentation/i2c/ten-bit-addresses	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/i2c/ten-bit-addresses	2012-01-04 18:55:44.000000000 -0500
@@ -1,22 +1,24 @@
 The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
-address 0x10 (though a single device could respond to both of them). You
-select a 10 bit address by adding an extra byte after the address
-byte:
-  S Addr7 Rd/Wr ....
-becomes
-  S 11110 Addr10 Rd/Wr
-S is the start bit, Rd/Wr the read/write bit, and if you count the number
-of bits, you will see the there are 8 after the S bit for 7 bit addresses,
-and 16 after the S bit for 10 bit addresses.
+address 0x10 (though a single device could respond to both of them).
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are
-several places in the code that will cause SEVERE PROBLEMS with 10 bit
-addresses, even though there is some basic handling and hooks. Also,
-almost no supported adapter handles the 10 bit addresses correctly.
+I2C messages to and from 10-bit address devices have a different format.
+See the I2C specification for the details.
 
-As soon as a real 10 bit address device is spotted 'in the wild', we
-can and will add proper support. Right now, 10 bit address devices
-are defined by the I2C protocol, but we have never seen a single device
-which supports them.
+The current 10 bit address support is minimal. It should work, however
+you can expect some problems along the way:
+* Not all bus drivers support 10-bit addresses. Some don't because the
+  hardware doesn't support them (SMBus doesn't require 10-bit address
+  support for example), some don't because nobody bothered adding the
+  code (or it's there but not working properly.) Software implementation
+  (i2c-algo-bit) is known to work.
+* Some optional features do not support 10-bit addresses. This is the
+  case of automatic detection and instantiation of devices by their,
+  drivers, for example.
+* Many user-space packages (for example i2c-tools) lack support for
+  10-bit addresses.
+
+Note that 10-bit address devices are still pretty rare, so the limitations
+listed above could stay for a long time, maybe even forever if nobody
+needs them to be fixed.
diff -druNp linux-libre-3.1-gnu1/Documentation/input/elantech.txt linux-libre-3.2-gnu1/Documentation/input/elantech.txt
--- linux-libre-3.1-gnu1/Documentation/input/elantech.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/input/elantech.txt	2012-01-04 18:55:44.000000000 -0500
@@ -16,15 +16,28 @@ Contents
 
  1. Introduction
  2. Extra knobs
- 3. Hardware version 1
-    3.1 Registers
-    3.2 Native relative mode 4 byte packet format
-    3.3 Native absolute mode 4 byte packet format
- 4. Hardware version 2
+ 3. Differentiating hardware versions
+ 4. Hardware version 1
     4.1 Registers
-    4.2 Native absolute mode 6 byte packet format
-        4.2.1 One finger touch
-        4.2.2 Two finger touch
+    4.2 Native relative mode 4 byte packet format
+    4.3 Native absolute mode 4 byte packet format
+ 5. Hardware version 2
+    5.1 Registers
+    5.2 Native absolute mode 6 byte packet format
+        5.2.1 Parity checking and packet re-synchronization
+        5.2.2 One/Three finger touch
+        5.2.3 Two finger touch
+ 6. Hardware version 3
+    6.1 Registers
+    6.2 Native absolute mode 6 byte packet format
+        6.2.1 One/Three finger touch
+        6.2.2 Two finger touch
+ 7. Hardware version 4
+    7.1 Registers
+    7.2 Native absolute mode 6 byte packet format
+        7.2.1 Status packet
+        7.2.2 Head packet
+        7.2.3 Motion packet
 
 
 
@@ -375,7 +388,7 @@ For all the other ones, there are just a
 
 In case an error is detected, all the packets are shifted by one (and packet[0] is discarded).
 
-5.2.1 One/Three finger touch
+5.2.2 One/Three finger touch
       ~~~~~~~~~~~~~~~~
 
 byte 0:
@@ -384,19 +397,19 @@ byte 0:
 	 n1  n0  w3  w2   .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
    bit   7   6   5   4   3   2   1   0
-	 p7  p6  p5  p4  .  x10 x9  x8
+	 p7  p6  p5  p4 x11 x10 x9  x8
 
 byte 2:
 
    bit   7   6   5   4   3   2   1   0
 	 x7  x6  x5  x4  x3  x2  x1  x0
 
-         x10..x0 = absolute x value (horizontal)
+         x11..x0 = absolute x value (horizontal)
 
 byte 3:
 
@@ -420,7 +433,7 @@ byte 3:
 byte 4:
 
    bit   7   6   5   4   3   2   1   0
-        p3  p1  p2  p0   .   .  y9  y8
+        p3  p1  p2  p0  y11 y10 y9  y8
 
 	 p7..p0 = pressure (not EF113)
 
@@ -429,10 +442,10 @@ byte 5:
    bit   7   6   5   4   3   2   1   0
         y7  y6  y5  y4  y3  y2  y1  y0
 
-         y9..y0 = absolute y value (vertical)
+         y11..y0 = absolute y value (vertical)
 
 
-4.2.2 Two finger touch
+5.2.3 Two finger touch
       ~~~~~~~~~~~~~~~~
 
 Note that the two pairs of coordinates are not exactly the coordinates of the
@@ -446,7 +459,7 @@ byte 0:
         n1  n0  ay8 ax8  .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
@@ -480,3 +493,253 @@ byte 5:
         by7 by8 by5 by4 by3 by2 by1 by0
 
          by8..by0 = upper-right finger absolute y value
+
+/////////////////////////////////////////////////////////////////////////////
+
+6. Hardware version 3
+   ==================
+
+6.1 Registers
+    ~~~~~~~~~
+* reg_10
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+6.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 and 3 finger touch shares the same 6-byte packet format, except that
+3 finger touch only reports the position of the center of all three fingers.
+
+Firmware would send 12 bytes of data for 2 finger touch.
+
+Note on debounce:
+In case the box has unstable power supply or other electricity issues, or
+when number of finger changes, F/W would send "debounce packet" to inform
+driver that the hardware is in debounce status.
+The debouce packet has the following signature:
+    byte 0: 0xc4
+    byte 1: 0xff
+    byte 2: 0xff
+    byte 3: 0x02
+    byte 4: 0xff
+    byte 5: 0xff
+When we encounter this kind of packet, we just ignore it.
+
+6.2.1 One/Three finger touch
+      ~~~~~~~~~~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        n1  n0  w3  w2   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        n1..n0 = number of fingers on touchpad
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         0   0  w1  w0   0   0   1   0
+
+         w3..w0 = width of the finger touch
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+6.2.2 Two finger touch
+      ~~~~~~~~~~~~~~~~
+
+The packet format is exactly the same for two finger touch, except the hardware
+sends two 6 byte packets. The first packet contains data for the first finger,
+the second packet has data for the second finger. So for two finger touch a
+total of 12 bytes are sent.
+
+/////////////////////////////////////////////////////////////////////////////
+
+7. Hardware version 4
+   ==================
+
+7.1 Registers
+    ~~~~~~~~~
+* reg_07
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+7.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
+complex.
+
+Whenever the numbers or identities of the fingers changes, the hardware sends a
+status packet to indicate how many and which fingers is on touchpad, followed by
+head packets or motion packets. A head packet contains data of finger id, finger
+position (absolute x, y values), width, and pressure. A motion packet contains
+two fingers' position delta.
+
+For example, when status packet tells there are 2 fingers on touchpad, then we
+can expect two following head packets. If the finger status doesn't change,
+the following packets would be motion packets, only sending delta of finger
+position, until we receive a status packet.
+
+One exception is one finger touch. when a status packet tells us there is only
+one finger, the hardware would just send head packets afterwards.
+
+7.2.1 Status packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   .   0   1   R   L
+
+         L, R = 1 when Left, Right mouse button pressed
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   . ft4 ft3 ft2 ft1 ft0
+
+         ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
+
+byte 2: not used
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   1   0   0   0   0
+
+         constant bits
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+         p   .   .   .   .   .   .   .
+
+         p = 1 for palm
+
+byte 5: not used
+
+7.2.2 Head packet
+      ~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        w3  w2  w1  w0   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        w3..w0 = finger width (spans how many trace lines)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   0   1
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+7.2.3 Motion packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   w   0   1   R   L
+
+       L, R = 1 when Left, Right mouse button pressed
+       id2..id0 = finger id
+       w = 1 when delta overflows (> 127 or < -128), in this case
+       firmware sends us (delta x / 5) and (delta y  / 5)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   1   0
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+        byte 0 ~ 2 for one finger
+        byte 3 ~ 5 for another
diff -druNp linux-libre-3.1-gnu1/Documentation/input/input.txt linux-libre-3.2-gnu1/Documentation/input/input.txt
--- linux-libre-3.1-gnu1/Documentation/input/input.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/input/input.txt	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@ LCDs and many other purposes.
 
  The monitor and speaker controls should be easy to add to the hid/input
 interface, but for the UPSs and LCDs it doesn't make much sense. For this,
-the hiddev interface was designed. See Documentation/usb/hiddev.txt
+the hiddev interface was designed. See Documentation/hid/hiddev.txt
 for more information about it.
 
   The usage of the usbhid module is very simple, it takes no parameters,
diff -druNp linux-libre-3.1-gnu1/Documentation/input/multi-touch-protocol.txt linux-libre-3.2-gnu1/Documentation/input/multi-touch-protocol.txt
--- linux-libre-3.1-gnu1/Documentation/input/multi-touch-protocol.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/input/multi-touch-protocol.txt	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,20 @@ the full state of each initiated contact
 end.  Upon receiving an MT event, one simply updates the appropriate
 attribute of the current slot.
 
+Some devices identify and/or track more contacts than they can report to the
+driver.  A driver for such a device should associate one type B slot with each
+contact that is reported by the hardware.  Whenever the identity of the
+contact associated with a slot changes, the driver should invalidate that
+slot by changing its ABS_MT_TRACKING_ID.  If the hardware signals that it is
+tracking more contacts than it is currently reporting, the driver should use
+a BTN_TOOL_*TAP event to inform userspace of the total number of contacts
+being tracked by the hardware at that moment.  The driver should do this by
+explicitly sending the corresponding BTN_TOOL_*TAP event and setting
+use_count to false when calling input_mt_report_pointer_emulation().
+The driver should only advertise as many slots as the hardware can report.
+Userspace can detect that a driver can report more total contacts than slots
+by noting that the largest supported BTN_TOOL_*TAP event is larger than the
+total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis.
 
 Protocol Example A
 ------------------
diff -druNp linux-libre-3.1-gnu1/Documentation/kernel-docs.txt linux-libre-3.2-gnu1/Documentation/kernel-docs.txt
--- linux-libre-3.1-gnu1/Documentation/kernel-docs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/kernel-docs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -300,7 +300,7 @@
        
      * Title: "The Kernel Hacking HOWTO"
        Author: Various Talented People, and Rusty.
-       Location: in kernel tree, Documentation/DocBook/kernel-hacking/
+       Location: in kernel tree, Documentation/DocBook/kernel-hacking.tmpl
        (must be built as "make {htmldocs | psdocs | pdfdocs})
        Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
        symbols, return conventions.
@@ -351,7 +351,7 @@
        
      * Title: "Linux Kernel Locking HOWTO"
        Author: Various Talented People, and Rusty.
-       Location: in kernel tree, Documentation/DocBook/kernel-locking/
+       Location: in kernel tree, Documentation/DocBook/kernel-locking.tmpl
        (must be built as "make {htmldocs | psdocs | pdfdocs})
        Keywords: locks, locking, spinlock, semaphore, atomic, race
        condition, bottom halves, tasklets, softirqs.
diff -druNp linux-libre-3.1-gnu1/Documentation/kernel-parameters.txt linux-libre-3.2-gnu1/Documentation/kernel-parameters.txt
--- linux-libre-3.1-gnu1/Documentation/kernel-parameters.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/kernel-parameters.txt	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@ parameter is applicable:
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
+	EVM	Extended Verification Module
 	FB	The frame buffer device is enabled.
 	FTRACE	Function tracing enabled.
 	GCOV	GCOV profiling is enabled.
@@ -163,7 +164,7 @@ bytes respectively. Such letter suffixes
 			rsdt -- prefer RSDT over (default) XSDT
 			copy_dsdt -- copy DSDT to memory
 
-			See also Documentation/power/pm.txt, pci=noacpi
+			See also Documentation/power/runtime_pm.txt, pci=noacpi
 
 	acpi_rsdp=	[ACPI,EFI,KEXEC]
 			Pass the RSDP address to the kernel, mostly used
@@ -306,7 +307,20 @@ bytes respectively. Such letter suffixes
 			behaviour to be specified.  Bit 0 enables warnings,
 			bit 1 enables fixups, and bit 2 sends a segfault.
 
-	amd_iommu=	[HW,X86-84]
+	align_va_addr=	[X86-64]
+			Align virtual addresses by clearing slice [14:12] when
+			allocating a VMA at process creation time. This option
+			gives you up to 3% performance improvement on AMD F15h
+			machines (where it is enabled by default) for a
+			CPU-intensive style benchmark, and it can vary highly in
+			a microbenchmark depending on workload and compiler.
+
+			32: only for 32-bit processes
+			64: only for 64-bit processes
+			on: enable for both 32- and 64-bit processes
+			off: disable for both 32- and 64-bit processes
+
+	amd_iommu=	[HW,X86-64]
 			Pass parameters to the AMD IOMMU driver in the system.
 			Possible values are:
 			fullflush - enable flushing of IO/TLB entries when
@@ -319,7 +333,7 @@ bytes respectively. Such letter suffixes
 	amijoy.map=	[HW,JOY] Amiga joystick support
 			Map of devices attached to JOY0DAT and JOY1DAT
 			Format: <a>,<b>
-			See also Documentation/kernel/input/joystick.txt
+			See also Documentation/input/joystick.txt
 
 	analog.map=	[HW,JOY] Analog joystick and gamepad support
 			Specifies type or capabilities of an analog joystick
@@ -408,7 +422,7 @@ bytes respectively. Such letter suffixes
 	bttv.radio=	Most important insmod options are available as
 			kernel args too.
 	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
-	bttv.tuner=	and Documentation/video4linux/bttv/CARDLIST
+	bttv.tuner=
 
 	bulk_remove=off	[PPC]  This parameter disables the use of the pSeries
 			firmware feature for flushing multiple hpte entries
@@ -724,13 +738,13 @@ bytes respectively. Such letter suffixes
 
 	elevator=	[IOSCHED]
 			Format: {"cfq" | "deadline" | "noop"}
-			See Documentation/block/as-iosched.txt and
+			See Documentation/block/cfq-iosched.txt and
 			Documentation/block/deadline-iosched.txt for details.
 
-	elfcorehdr=	[IA-64,PPC,SH,X86]
+	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
 			Specifies physical address of start of kernel core
-			image elf header. Generally kexec loader will
-			pass this option to capture kernel.
+			image elf header and optionally the size. Generally
+			kexec loader will pass this option to capture kernel.
 			See Documentation/kdump/kdump.txt for details.
 
 	enable_mtrr_cleanup [X86]
@@ -760,12 +774,17 @@ bytes respectively. Such letter suffixes
 			This option is obsoleted by the "netdev=" option, which
 			has equivalent usage. See its documentation for details.
 
+	evm=		[EVM]
+			Format: { "fix" }
+			Permit 'security.evm' to be updated regardless of
+			current integrity status.
+
 	failslab=
 	fail_page_alloc=
 	fail_make_request=[KNL]
 			General fault injection mechanism.
 			Format: <interval>,<probability>,<space>,<times>
-			See also /Documentation/fault-injection/.
+			See also Documentation/fault-injection/.
 
 	floppy=		[HW]
 			See Documentation/blockdev/floppy.txt.
@@ -954,6 +973,9 @@ bytes respectively. Such letter suffixes
 	ignore_loglevel	[KNL]
 			Ignore loglevel setting - this will print /all/
 			kernel messages to the console. Useful for debugging.
+			We also add it as printk module parameter, so users
+			could change it dynamically, usually by
+			/sys/module/printk/parameters/ignore_loglevel.
 
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
@@ -1014,10 +1036,11 @@ bytes respectively. Such letter suffixes
 			has the capability. With this option, super page will
 			not be supported.
 	intremap=	[X86-64, Intel-IOMMU]
-			Format: { on (default) | off | nosid }
 			on	enable Interrupt Remapping (default)
 			off	disable Interrupt Remapping
 			nosid	disable Source ID checking
+			no_x2apic_optout
+				BIOS x2APIC opt-out request will be ignored
 
 	inttest=	[IA-64]
 
@@ -1181,6 +1204,10 @@ bytes respectively. Such letter suffixes
 			[KVM,Intel] Disable FlexPriority feature (TPR shadow).
 			Default is 1 (enabled)
 
+	kvm-intel.nested=
+			[KVM,Intel] Enable VMX nesting (nVMX).
+			Default is 0 (disabled)
+
 	kvm-intel.unrestricted_guest=
 			[KVM,Intel] Disable unrestricted guest feature
 			(virtualized real and unpaged mode) on capable
@@ -1642,6 +1669,11 @@ bytes respectively. Such letter suffixes
 			debugging driver suspend/resume hooks).  This may
 			not work reliably with all consoles, but is known
 			to work with serial and VGA consoles.
+			To facilitate more flexible debugging, we also add
+			console_suspend, a printk module parameter to control
+			it. Users could use console_suspend (usually
+			/sys/module/printk/parameters/console_suspend) to
+			turn on/off it dynamically.
 
 	noaliencache	[MM, NUMA, SLAB] Disables the allocation of alien
 			caches in the slab allocator.  Saves per-node memory,
@@ -1777,6 +1809,11 @@ bytes respectively. Such letter suffixes
 
 	noresidual	[PPC] Don't use residual data on PReP machines.
 
+	nordrand	[X86] Disable the direct use of the RDRAND
+			instruction even if it is supported by the
+			processor.  RDRAND is still available to user
+			space applications.
+
 	noresume	[SWSUSP] Disables resume and restores original swap
 			space.
 
@@ -2240,6 +2277,13 @@ bytes respectively. Such letter suffixes
 			in <PAGE_SIZE> units (needed only for swap files).
 			See  Documentation/power/swsusp-and-swap-files.txt
 
+	resumedelay=	[HIBERNATION] Delay (in seconds) to pause before attempting to
+			read the resume files
+
+	resumewait	[HIBERNATION] Wait (indefinitely) for resume device to show up.
+			Useful for devices that are detected asynchronously
+			(e.g. USB and MMC devices).
+
 	hibernate=	[HIBERNATION]
 		noresume	Don't check if there's a hibernation image
 				present during boot.
@@ -2375,7 +2419,7 @@ bytes respectively. Such letter suffixes
 			Format: <integer>
 
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
-			See Documentation/sonypi.txt
+			See Documentation/laptops/sonypi.txt
 
 	specialix=	[HW,SERIAL] Specialix multi-serial port adapter
 			See Documentation/serial/specialix.txt.
diff -druNp linux-libre-3.1-gnu1/Documentation/laptops/thinkpad-acpi.txt linux-libre-3.2-gnu1/Documentation/laptops/thinkpad-acpi.txt
--- linux-libre-3.1-gnu1/Documentation/laptops/thinkpad-acpi.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/laptops/thinkpad-acpi.txt	2012-01-04 18:55:44.000000000 -0500
@@ -411,9 +411,9 @@ event	code	Key		Notes
 
 0x1004	0x03	FN+F4		Sleep button (ACPI sleep button
 				semantics, i.e. sleep-to-RAM).
-				It is always generate some kind
+				It always generates some kind
 				of event, either the hot key
-				event or a ACPI sleep button
+				event or an ACPI sleep button
 				event. The firmware may
 				refuse to generate further FN+F4
 				key presses until a S3 or S4 ACPI
@@ -736,7 +736,7 @@ status as "unknown". The available comma
 sysfs notes:
 
 The ThinkLight sysfs interface is documented by the LED class
-documentation, in Documentation/leds-class.txt.  The ThinkLight LED name
+documentation, in Documentation/leds/leds-class.txt.  The ThinkLight LED name
 is "tpacpi::thinklight".
 
 Due to limitations in the sysfs LED class, if the status of the ThinkLight
@@ -833,7 +833,7 @@ All of the above can be turned on and of
 sysfs notes:
 
 The ThinkPad LED sysfs interface is described in detail by the LED class
-documentation, in Documentation/leds-class.txt.
+documentation, in Documentation/leds/leds-class.txt.
 
 The LEDs are named (in LED ID order, from 0 to 12):
 "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
diff -druNp linux-libre-3.1-gnu1/Documentation/leds/leds-class.txt linux-libre-3.2-gnu1/Documentation/leds/leds-class.txt
--- linux-libre-3.1-gnu1/Documentation/leds/leds-class.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/leds/leds-class.txt	2012-01-04 18:55:44.000000000 -0500
@@ -61,8 +61,8 @@ Hardware accelerated blink of LEDs
 Some LEDs can be programmed to blink without any CPU interaction. To
 support this feature, a LED driver can optionally implement the
 blink_set() function (see <linux/leds.h>). To set an LED to blinking,
-however, it is better to use use the API function led_blink_set(),
-as it will check and implement software fallback if necessary.
+however, it is better to use the API function led_blink_set(), as it
+will check and implement software fallback if necessary.
 
 To turn off blinking again, use the API function led_brightness_set()
 as that will not just set the LED brightness but also stop any software
diff -druNp linux-libre-3.1-gnu1/Documentation/media-framework.txt linux-libre-3.2-gnu1/Documentation/media-framework.txt
--- linux-libre-3.1-gnu1/Documentation/media-framework.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/media-framework.txt	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,8 @@ Introduction
 ------------
 
 The media controller API is documented in DocBook format in
-Documentation/DocBook/v4l/media-controller.xml. This document will focus on
-the kernel-side implementation of the media framework.
+Documentation/DocBook/media/v4l/media-controller.xml. This document will focus
+on the kernel-side implementation of the media framework.
 
 
 Abstract media device model
diff -druNp linux-libre-3.1-gnu1/Documentation/memory-barriers.txt linux-libre-3.2-gnu1/Documentation/memory-barriers.txt
--- linux-libre-3.1-gnu1/Documentation/memory-barriers.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/memory-barriers.txt	2012-01-04 18:55:44.000000000 -0500
@@ -438,7 +438,7 @@ There are certain things that the Linux
 	[*] For information on bus mastering DMA and coherency please read:
 
 	    Documentation/PCI/pci.txt
-	    Documentation/PCI/PCI-DMA-mapping.txt
+	    Documentation/DMA-API-HOWTO.txt
 	    Documentation/DMA-API.txt
 
 
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/batman-adv.txt linux-libre-3.2-gnu1/Documentation/networking/batman-adv.txt
--- linux-libre-3.1-gnu1/Documentation/networking/batman-adv.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/batman-adv.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-[state: 17-04-2011]
+[state: 21-08-2011]
 
 BATMAN-ADV
 ----------
@@ -68,9 +68,9 @@ All  mesh  wide  settings  can be found
 folder:
 
 #  ls  /sys/class/net/bat0/mesh/
-#  aggregated_ogms  gw_bandwidth  hop_penalty
-#  bonding          gw_mode       orig_interval
-#  fragmentation    gw_sel_class  vis_mode
+# aggregated_ogms   fragmentation gw_sel_class   vis_mode
+# ap_isolation      gw_bandwidth  hop_penalty
+# bonding           gw_mode       orig_interval
 
 
 There is a special folder for debugging information:
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/ip-sysctl.txt linux-libre-3.2-gnu1/Documentation/networking/ip-sysctl.txt
--- linux-libre-3.1-gnu1/Documentation/networking/ip-sysctl.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/ip-sysctl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@ ip_no_pmtu_disc - BOOLEAN
 	default FALSE
 
 min_pmtu - INTEGER
-	default 562 - minimum discovered Path MTU
+	default 552 - minimum discovered Path MTU
 
 route/max_size - INTEGER
 	Maximum number of routes allowed in the kernel.  Increase
@@ -282,11 +282,11 @@ tcp_max_ssthresh - INTEGER
 	Default: 0 (off)
 
 tcp_max_syn_backlog - INTEGER
-	Maximal number of remembered connection requests, which are
-	still did not receive an acknowledgment from connecting client.
-	Default value is 1024 for systems with more than 128Mb of memory,
-	and 128 for low memory machines. If server suffers of overload,
-	try to increase this number.
+	Maximal number of remembered connection requests, which have not
+	received an acknowledgment from connecting client.
+	The minimal value is 128 for low memory machines, and it will
+	increase in proportion to the memory of machine.
+	If server suffers from overload, try increasing this number.
 
 tcp_max_tw_buckets - INTEGER
 	Maximal number of timewait sockets held by system simultaneously.
@@ -1045,6 +1045,11 @@ conf/interface/*:
 accept_ra - INTEGER
 	Accept Router Advertisements; autoconfigure using them.
 
+	It also determines whether or not to transmit Router
+	Solicitations. If and only if the functional setting is to
+	accept Router Advertisements, Router Solicitations will be
+	transmitted.
+
 	Possible values are:
 		0 Do not accept Router Advertisements.
 		1 Accept Router Advertisements if forwarding is disabled.
@@ -1115,14 +1120,14 @@ forwarding - INTEGER
 	Possible values are:
 		0 Forwarding disabled
 		1 Forwarding enabled
-		2 Forwarding enabled (Hybrid Mode)
 
 	FALSE (0):
 
 	By default, Host behaviour is assumed.  This means:
 
 	1. IsRouter flag is not set in Neighbour Advertisements.
-	2. Router Solicitations are being sent when necessary.
+	2. If accept_ra is TRUE (default), transmit Router
+	   Solicitations.
 	3. If accept_ra is TRUE (default), accept Router
 	   Advertisements (and do autoconfiguration).
 	4. If accept_redirects is TRUE (default), accept Redirects.
@@ -1133,16 +1138,10 @@ forwarding - INTEGER
 	This means exactly the reverse from the above:
 
 	1. IsRouter flag is set in Neighbour Advertisements.
-	2. Router Solicitations are not sent.
+	2. Router Solicitations are not sent unless accept_ra is 2.
 	3. Router Advertisements are ignored unless accept_ra is 2.
 	4. Redirects are ignored.
 
-	TRUE (2):
-
-	Hybrid mode. Same behaviour as TRUE, except for:
-
-	2. Router Solicitations are being sent when necessary.
-
 	Default: 0 (disabled) if global forwarding is disabled (default),
 		 otherwise 1 (enabled).
 
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/ipvs-sysctl.txt linux-libre-3.2-gnu1/Documentation/networking/ipvs-sysctl.txt
--- linux-libre-3.1-gnu1/Documentation/networking/ipvs-sysctl.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/ipvs-sysctl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,23 @@ amemthresh - INTEGER
         enabled and the variable is automatically set to 2, otherwise
         the strategy is disabled and the variable is  set  to 1.
 
+conntrack - BOOLEAN
+	0 - disabled (default)
+	not 0 - enabled
+
+	If set, maintain connection tracking entries for
+	connections handled by IPVS.
+
+	This should be enabled if connections handled by IPVS are to be
+	also handled by stateful firewall rules. That is, iptables rules
+	that make use of connection tracking.  It is a performance
+	optimisation to disable this setting otherwise.
+
+	Connections handled by the IPVS FTP application module
+	will have connection tracking entries regardless of this setting.
+
+	Only available when IPVS is compiled with CONFIG_IP_VS_NFCT enabled.
+
 cache_bypass - BOOLEAN
         0 - disabled (default)
         not 0 - enabled
@@ -39,7 +56,7 @@ debug_level - INTEGER
 	11         - IPVS packet handling (ip_vs_in/ip_vs_out)
 	12 or more - packet traversal
 
-	Only available when IPVS is compiled with the CONFIG_IPVS_DEBUG
+	Only available when IPVS is compiled with CONFIG_IP_VS_DEBUG enabled.
 
 	Higher debugging levels include the messages for lower debugging
 	levels, so setting debug level 2, includes level 0, 1 and 2
@@ -123,13 +140,11 @@ nat_icmp_send - BOOLEAN
 secure_tcp - INTEGER
         0  - disabled (default)
 
-        The secure_tcp defense is to use a more complicated state
-        transition table and some possible short timeouts of each
-        state. In the VS/NAT, it delays the entering the ESTABLISHED
-        until the real server starts to send data and ACK packet
-        (after 3-way handshake).
+	The secure_tcp defense is to use a more complicated TCP state
+	transition table. For VS/NAT, it also delays entering the
+	TCP ESTABLISHED state until the three way handshake is completed.
 
-        The value definition is the same as that of drop_entry or
+        The value definition is the same as that of drop_entry and
         drop_packet.
 
 sync_threshold - INTEGER
@@ -141,3 +156,36 @@ sync_threshold - INTEGER
         synchronized, every time the number of its incoming packets
         modulus 50 equals the threshold. The range of the threshold is
         from 0 to 49.
+
+snat_reroute - BOOLEAN
+	0 - disabled
+	not 0 - enabled (default)
+
+	If enabled, recalculate the route of SNATed packets from
+	realservers so that they are routed as if they originate from the
+	director. Otherwise they are routed as if they are forwarded by the
+	director.
+
+	If policy routing is in effect then it is possible that the route
+	of a packet originating from a director is routed differently to a
+	packet being forwarded by the director.
+
+	If policy routing is not in effect then the recalculated route will
+	always be the same as the original route so it is an optimisation
+	to disable snat_reroute and avoid the recalculation.
+
+sync_version - INTEGER
+	default 1
+
+	The version of the synchronisation protocol used when sending
+	synchronisation messages.
+
+	0 selects the original synchronisation protocol (version 0). This
+	should be used when sending synchronisation messages to a legacy
+	system that only understands the original synchronisation protocol.
+
+	1 selects the current synchronisation protocol (version 1). This
+	should be used where possible.
+
+	Kernels with this sync_version entry are able to receive messages
+	of both version 1 and version 2 of the synchronisation protocol.
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/LICENSE.qlcnic linux-libre-3.2-gnu1/Documentation/networking/LICENSE.qlcnic
--- linux-libre-3.1-gnu1/Documentation/networking/LICENSE.qlcnic	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/LICENSE.qlcnic	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,22 @@
-Copyright (c) 2009-2010 QLogic Corporation
+Copyright (c) 2009-2011 QLogic Corporation
 QLogic Linux qlcnic NIC Driver
 
-This program includes a device driver for Linux 2.6 that may be
-distributed with QLogic hardware specific firmware binary file.
 You may modify and redistribute the device driver code under the
 GNU General Public License (a copy of which is attached hereto as
 Exhibit A) published by the Free Software Foundation (version 2).
 
-You may redistribute the hardware specific firmware binary file
-under the following terms:
-
-       1. Redistribution of source code (only if applicable),
-          must retain the above copyright notice, this list of
-          conditions and the following disclaimer.
-
-       2. Redistribution in binary form must reproduce the above
-          copyright notice, this list of conditions and the
-          following disclaimer in the documentation and/or other
-          materials provided with the distribution.
-
-       3. The name of QLogic Corporation may not be used to
-          endorse or promote products derived from this software
-          without specific prior written permission
-
-REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
-THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
-CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
-OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
-TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
-ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
-COMBINATION WITH THIS PROGRAM.
-
 
 EXHIBIT A
 
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-                           Preamble
+			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -105,7 +66,7 @@ patent must be licensed for everyone's f
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-                   GNU GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -304,7 +265,7 @@ make exceptions for this.  Our decision
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-                           NO WARRANTY
+			    NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/mac80211-injection.txt linux-libre-3.2-gnu1/Documentation/networking/mac80211-injection.txt
--- linux-libre-3.1-gnu1/Documentation/networking/mac80211-injection.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/mac80211-injection.txt	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,10 @@ radiotap headers and used to control inj
    IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
 			      current fragmentation threshold.
 
+ * IEEE80211_RADIOTAP_TX_FLAGS
+
+   IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for
+				  an ACK even if it is a unicast frame
 
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/netdevices.txt linux-libre-3.2-gnu1/Documentation/networking/netdevices.txt
--- linux-libre-3.1-gnu1/Documentation/networking/netdevices.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/netdevices.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@ dev->hard_start_xmit:
 	has to lock by itself when needed. It is recommended to use a try lock
 	for this and return NETDEV_TX_LOCKED when the spin lock fails.
 	The locking there should also properly protect against 
-	set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
+	set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated.
 	Don't use it for new drivers.
 
 	Context: Process with BHs disabled or BH (timer),
@@ -92,7 +92,7 @@ dev->tx_timeout:
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed true
 
-dev->set_multicast_list:
+dev->set_rx_mode:
 	Synchronization: netif_tx_lock spinlock.
 	Context: BHs disabled
 
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/scaling.txt linux-libre-3.2-gnu1/Documentation/networking/scaling.txt
--- linux-libre-3.1-gnu1/Documentation/networking/scaling.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/scaling.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@ of queues to IRQs can be determined from
 an IRQ may be handled on any CPU. Because a non-negligible part of packet
 processing takes place in receive interrupt handling, it is advantageous
 to spread receive interrupts between CPUs. To manually adjust the IRQ
-affinity of each interrupt see Documentation/IRQ-affinity. Some systems
+affinity of each interrupt see Documentation/IRQ-affinity.txt. Some systems
 will be running irqbalance, a daemon that dynamically optimizes IRQ
 assignments and as a result may override any manual settings.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/networking/stmmac.txt linux-libre-3.2-gnu1/Documentation/networking/stmmac.txt
--- linux-libre-3.1-gnu1/Documentation/networking/stmmac.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/networking/stmmac.txt	2012-01-04 18:55:44.000000000 -0500
@@ -76,7 +76,16 @@ core.
 
 4.5) DMA descriptors
 Driver handles both normal and enhanced descriptors. The latter has been only
-tested on DWC Ether MAC 10/100/1000 Universal version 3.41a.
+tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later.
+
+STMMAC supports DMA descriptor to operate both in dual buffer (RING)
+and linked-list(CHAINED) mode. In RING each descriptor points to two
+data buffer pointers whereas in CHAINED mode they point to only one data
+buffer pointer. RING mode is the default.
+
+In CHAINED mode each descriptor will have pointer to next descriptor in
+the list, hence creating the explicit chaining in the descriptor itself,
+whereas such explicit chaining is not possible in RING mode.
 
 4.6) Ethtool support
 Ethtool is supported. Driver statistics and internal errors can be taken using:
@@ -235,7 +244,38 @@ reset procedure etc).
  o enh_desc.c: functions for handling enhanced descriptors
  o norm_desc.c: functions for handling normal descriptors
 
-5) TODO:
+5) Debug Information
+
+The driver exports many information i.e. internal statistics,
+debug information, MAC and DMA registers etc.
+
+These can be read in several ways depending on the
+type of the information actually needed.
+
+For example a user can be use the ethtool support
+to get statistics: e.g. using: ethtool -S ethX
+(that shows the Management counters (MMC) if supported)
+or sees the MAC/DMA registers: e.g. using: ethtool -d ethX
+
+Compiling the Kernel with CONFIG_DEBUG_FS and enabling the
+STMMAC_DEBUG_FS option the driver will export the following
+debugfs entries:
+
+/sys/kernel/debug/stmmaceth/descriptors_status
+  To show the DMA TX/RX descriptor rings
+
+Developer can also use the "debug" module parameter to get
+further debug information.
+
+In the end, there are other macros (that cannot be enabled
+via menuconfig) to turn-on the RX/TX DMA debugging,
+specific MAC core debug printk etc. Others to enable the
+debug in the TX and RX processes.
+All these are only useful during the developing stage
+and should never enabled inside the code for general usage.
+In fact, these can generate an huge amount of debug messages.
+
+6) TODO:
  o XGMAC is not supported.
  o Review the timer optimisation code to use an embedded device that will be
   available in new chip generations.
diff -druNp linux-libre-3.1-gnu1/Documentation/oops-tracing.txt linux-libre-3.2-gnu1/Documentation/oops-tracing.txt
--- linux-libre-3.1-gnu1/Documentation/oops-tracing.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/oops-tracing.txt	2012-01-04 18:55:44.000000000 -0500
@@ -263,6 +263,8 @@ characters, each representing a particul
  12: 'I' if the kernel is working around a severe bug in the platform
      firmware (BIOS or similar).
 
+ 13: 'O' if an externally-built ("out-of-tree") module has been loaded.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff -druNp linux-libre-3.1-gnu1/Documentation/PCI/pci.txt linux-libre-3.2-gnu1/Documentation/PCI/pci.txt
--- linux-libre-3.1-gnu1/Documentation/PCI/pci.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/PCI/pci.txt	2012-01-04 18:55:44.000000000 -0500
@@ -314,7 +314,7 @@ from the PCI device config space. Use th
 as the PCI "bus address" might have been remapped to a "host physical"
 address by the arch/chip-set specific kernel support.
 
-See Documentation/IO-mapping.txt for how to access device registers
+See Documentation/io-mapping.txt for how to access device registers
 or device memory.
 
 The device driver needs to call pci_request_region() to verify
diff -druNp linux-libre-3.1-gnu1/Documentation/pinctrl.txt linux-libre-3.2-gnu1/Documentation/pinctrl.txt
--- linux-libre-3.1-gnu1/Documentation/pinctrl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/pinctrl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,950 @@
+PINCTRL (PIN CONTROL) subsystem
+This document outlines the pin control subsystem in Linux
+
+This subsystem deals with:
+
+- Enumerating and naming controllable pins
+
+- Multiplexing of pins, pads, fingers (etc) see below for details
+
+The intention is to also deal with:
+
+- Software-controlled biasing and driving mode specific pins, such as
+  pull-up/down, open drain etc, load capacitance configuration when controlled
+  by software, etc.
+
+
+Top-level interface
+===================
+
+Definition of PIN CONTROLLER:
+
+- A pin controller is a piece of hardware, usually a set of registers, that
+  can control PINs. It may be able to multiplex, bias, set load capacitance,
+  set drive strength etc for individual pins or groups of pins.
+
+Definition of PIN:
+
+- PINS are equal to pads, fingers, balls or whatever packaging input or
+  output line you want to control and these are denoted by unsigned integers
+  in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so
+  there may be several such number spaces in a system. This pin space may
+  be sparse - i.e. there may be gaps in the space with numbers where no
+  pin exists.
+
+When a PIN CONTROLLER is instatiated, it will register a descriptor to the
+pin control framework, and this descriptor contains an array of pin descriptors
+describing the pins handled by this specific pin controller.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+        A   B   C   D   E   F   G   H
+
+   8    o   o   o   o   o   o   o   o
+
+   7    o   o   o   o   o   o   o   o
+
+   6    o   o   o   o   o   o   o   o
+
+   5    o   o   o   o   o   o   o   o
+
+   4    o   o   o   o   o   o   o   o
+
+   3    o   o   o   o   o   o   o   o
+
+   2    o   o   o   o   o   o   o   o
+
+   1    o   o   o   o   o   o   o   o
+
+To register a pin controller and name all the pins on this package we can do
+this in our driver:
+
+#include <linux/pinctrl/pinctrl.h>
+
+const struct pinctrl_pin_desc __refdata foo_pins[] = {
+      PINCTRL_PIN(0, "A1"),
+      PINCTRL_PIN(1, "A2"),
+      PINCTRL_PIN(2, "A3"),
+      ...
+      PINCTRL_PIN(61, "H6"),
+      PINCTRL_PIN(62, "H7"),
+      PINCTRL_PIN(63, "H8"),
+};
+
+static struct pinctrl_desc foo_desc = {
+	.name = "foo",
+	.pins = foo_pins,
+	.npins = ARRAY_SIZE(foo_pins),
+	.maxpin = 63,
+	.owner = THIS_MODULE,
+};
+
+int __init foo_probe(void)
+{
+	struct pinctrl_dev *pctl;
+
+	pctl = pinctrl_register(&foo_desc, <PARENT>, NULL);
+	if (IS_ERR(pctl))
+		pr_err("could not register foo pin driver\n");
+}
+
+Pins usually have fancier names than this. You can find these in the dataheet
+for your chip. Notice that the core pinctrl.h file provides a fancy macro
+called PINCTRL_PIN() to create the struct entries. As you can see I enumerated
+the pins from 0 in the upper left corner to 63 in the lower right corner,
+this enumeration was arbitrarily chosen, in practice you need to think
+through your numbering system so that it matches the layout of registers
+and such things in your driver, or the code may become complicated. You must
+also consider matching of offsets to the GPIO ranges that may be handled by
+the pin controller.
+
+For a padring with 467 pads, as opposed to actual pins, I used an enumeration
+like this, walking around the edge of the chip, which seems to be industry
+standard too (all these pads had names, too):
+
+
+     0 ..... 104
+   466        105
+     .        .
+     .        .
+   358        224
+    357 .... 225
+
+
+Pin groups
+==========
+
+Many controllers need to deal with groups of pins, so the pin controller
+subsystem has a mechanism for enumerating groups of pins and retrieving the
+actual enumerated pins that are part of a certain group.
+
+For example, say that we have a group of pins dealing with an SPI interface
+on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins
+on { 24, 25 }.
+
+These two groups are presented to the pin control subsystem by implementing
+some generic pinctrl_ops like this:
+
+#include <linux/pinctrl/pinctrl.h>
+
+struct foo_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned num_pins;
+};
+
+static unsigned int spi0_pins[] = { 0, 8, 16, 24 };
+static unsigned int i2c0_pins[] = { 24, 25 };
+
+static const struct foo_group foo_groups[] = {
+	{
+		.name = "spi0_grp",
+		.pins = spi0_pins,
+		.num_pins = ARRAY_SIZE(spi0_pins),
+	},
+	{
+		.name = "i2c0_grp",
+		.pins = i2c0_pins,
+		.num_pins = ARRAY_SIZE(i2c0_pins),
+	},
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_groups))
+		return -EINVAL;
+	return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       unsigned ** const pins,
+			       unsigned * const num_pins)
+{
+	*pins = (unsigned *) foo_groups[selector].pins;
+	*num_pins = foo_groups[selector].num_pins;
+	return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+	.list_groups = foo_list_groups,
+	.get_group_name = foo_get_group_name,
+	.get_group_pins = foo_get_group_pins,
+};
+
+
+static struct pinctrl_desc foo_desc = {
+       ...
+       .pctlops = &foo_pctrl_ops,
+};
+
+The pin control subsystem will call the .list_groups() function repeatedly
+beginning on 0 until it returns non-zero to determine legal selectors, then
+it will call the other functions to retrieve the name and pins of the group.
+Maintaining the data structure of the groups is up to the driver, this is
+just a simple example - in practice you may need more entries in your group
+structure, for example specific register ranges associated with each group
+and so on.
+
+
+Interaction with the GPIO subsystem
+===================================
+
+The GPIO drivers may want to perform operations of various types on the same
+physical pins that are also registered as pin controller pins.
+
+Since the pin controller subsystem have its pinspace local to the pin
+controller we need a mapping so that the pin control subsystem can figure out
+which pin controller handles control of a certain GPIO pin. Since a single
+pin controller may be muxing several GPIO ranges (typically SoCs that have
+one set of pins but internally several GPIO silicon blocks, each modeled as
+a struct gpio_chip) any number of GPIO ranges can be added to a pin controller
+instance like this:
+
+struct gpio_chip chip_a;
+struct gpio_chip chip_b;
+
+static struct pinctrl_gpio_range gpio_range_a = {
+	.name = "chip a",
+	.id = 0,
+	.base = 32,
+	.npins = 16,
+	.gc = &chip_a;
+};
+
+static struct pinctrl_gpio_range gpio_range_a = {
+	.name = "chip b",
+	.id = 0,
+	.base = 48,
+	.npins = 8,
+	.gc = &chip_b;
+};
+
+
+{
+	struct pinctrl_dev *pctl;
+	...
+	pinctrl_add_gpio_range(pctl, &gpio_range_a);
+	pinctrl_add_gpio_range(pctl, &gpio_range_b);
+}
+
+So this complex system has one pin controller handling two different
+GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in
+the global GPIO pin space at:
+
+chip a: [32 .. 47]
+chip b: [48 .. 55]
+
+When GPIO-specific functions in the pin control subsystem are called, these
+ranges will be used to look up the apropriate pin controller by inspecting
+and matching the pin to the pin ranges across all controllers. When a
+pin controller handling the matching range is found, GPIO-specific functions
+will be called on that specific pin controller.
+
+For all functionalities dealing with pin biasing, pin muxing etc, the pin
+controller subsystem will subtract the range's .base offset from the passed
+in gpio pin number, and pass that on to the pin control driver, so the driver
+will get an offset into its handled number range. Further it is also passed
+the range ID value, so that the pin controller knows which range it should
+deal with.
+
+For example: if a user issues pinctrl_gpio_set_foo(50), the pin control
+subsystem will find that the second range on this pin controller matches,
+subtract the base 48 and call the
+pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has
+this signature:
+
+int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev,
+    struct pinctrl_gpio_range *rangeid,
+    unsigned offset);
+
+Now the driver knows that we want to do some GPIO-specific operation on the
+second GPIO range handled by "chip b", at offset 2 in that specific range.
+
+(If the GPIO subsystem is ever refactored to use a local per-GPIO controller
+pin space, this mapping will need to be augmented accordingly.)
+
+
+PINMUX interfaces
+=================
+
+These calls use the pinmux_* naming prefix.  No other calls should use that
+prefix.
+
+
+What is pinmuxing?
+==================
+
+PINMUX, also known as padmux, ballmux, alternate functions or mission modes
+is a way for chip vendors producing some kind of electrical packages to use
+a certain physical pin (ball, pad, finger, etc) for multiple mutually exclusive
+functions, depending on the application. By "application" in this context
+we usually mean a way of soldering or wiring the package into an electronic
+system, even though the framework makes it possible to also change the function
+at runtime.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+        A   B   C   D   E   F   G   H
+      +---+
+   8  | o | o   o   o   o   o   o   o
+      |   |
+   7  | o | o   o   o   o   o   o   o
+      |   |
+   6  | o | o   o   o   o   o   o   o
+      +---+---+
+   5  | o | o | o   o   o   o   o   o
+      +---+---+               +---+
+   4    o   o   o   o   o   o | o | o
+                              |   |
+   3    o   o   o   o   o   o | o | o
+                              |   |
+   2    o   o   o   o   o   o | o | o
+      +-------+-------+-------+---+---+
+   1  | o   o | o   o | o   o | o | o |
+      +-------+-------+-------+---+---+
+
+This is not tetris. The game to think of is chess. Not all PGA/BGA packages
+are chessboard-like, big ones have "holes" in some arrangement according to
+different design patterns, but we're using this as a simple example. Of the
+pins you see some will be taken by things like a few VCC and GND to feed power
+to the chip, and quite a few will be taken by large ports like an external
+memory interface. The remaining pins will often be subject to pin multiplexing.
+
+The example 8x8 PGA package above will have pin numbers 0 thru 63 assigned to
+its physical pins. It will name the pins { A1, A2, A3 ... H6, H7, H8 } using
+pinctrl_register_pins() and a suitable data set as shown earlier.
+
+In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port
+(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as
+some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can
+be used as an I2C port (these are just two pins: SCL, SDA). Needless to say,
+we cannot use the SPI port and I2C port at the same time. However in the inside
+of the package the silicon performing the SPI logic can alternatively be routed
+out on pins { G4, G3, G2, G1 }.
+
+On the botton row at { A1, B1, C1, D1, E1, F1, G1, H1 } we have something
+special - it's an external MMC bus that can be 2, 4 or 8 bits wide, and it will
+consume 2, 4 or 8 pins respectively, so either { A1, B1 } are taken or
+{ A1, B1, C1, D1 } or all of them. If we use all 8 bits, we cannot use the SPI
+port on pins { G4, G3, G2, G1 } of course.
+
+This way the silicon blocks present inside the chip can be multiplexed "muxed"
+out on different pin ranges. Often contemporary SoC (systems on chip) will
+contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to
+different pins by pinmux settings.
+
+Since general-purpose I/O pins (GPIO) are typically always in shortage, it is
+common to be able to use almost any pin as a GPIO pin if it is not currently
+in use by some other I/O port.
+
+
+Pinmux conventions
+==================
+
+The purpose of the pinmux functionality in the pin controller subsystem is to
+abstract and provide pinmux settings to the devices you choose to instantiate
+in your machine configuration. It is inspired by the clk, GPIO and regulator
+subsystems, so devices will request their mux setting, but it's also possible
+to request a single pin for e.g. GPIO.
+
+Definitions:
+
+- FUNCTIONS can be switched in and out by a driver residing with the pin
+  control subsystem in the drivers/pinctrl/* directory of the kernel. The
+  pin control driver knows the possible functions. In the example above you can
+  identify three pinmux functions, one for spi, one for i2c and one for mmc.
+
+- FUNCTIONS are assumed to be enumerable from zero in a one-dimensional array.
+  In this case the array could be something like: { spi0, i2c0, mmc0 }
+  for the three available functions.
+
+- FUNCTIONS have PIN GROUPS as defined on the generic level - so a certain
+  function is *always* associated with a certain set of pin groups, could
+  be just a single one, but could also be many. In the example above the
+  function i2c is associated with the pins { A5, B5 }, enumerated as
+  { 24, 25 } in the controller pin space.
+
+  The Function spi is associated with pin groups { A8, A7, A6, A5 }
+  and { G4, G3, G2, G1 }, which are enumerated as { 0, 8, 16, 24 } and
+  { 38, 46, 54, 62 } respectively.
+
+  Group names must be unique per pin controller, no two groups on the same
+  controller may have the same name.
+
+- The combination of a FUNCTION and a PIN GROUP determine a certain function
+  for a certain set of pins. The knowledge of the functions and pin groups
+  and their machine-specific particulars are kept inside the pinmux driver,
+  from the outside only the enumerators are known, and the driver core can:
+
+  - Request the name of a function with a certain selector (>= 0)
+  - A list of groups associated with a certain function
+  - Request that a certain group in that list to be activated for a certain
+    function
+
+  As already described above, pin groups are in turn self-descriptive, so
+  the core will retrieve the actual pin range in a certain group from the
+  driver.
+
+- FUNCTIONS and GROUPS on a certain PIN CONTROLLER are MAPPED to a certain
+  device by the board file, device tree or similar machine setup configuration
+  mechanism, similar to how regulators are connected to devices, usually by
+  name. Defining a pin controller, function and group thus uniquely identify
+  the set of pins to be used by a certain device. (If only one possible group
+  of pins is available for the function, no group name need to be supplied -
+  the core will simply select the first and only group available.)
+
+  In the example case we can define that this particular machine shall
+  use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function
+  fi2c0 group gi2c0, on the primary pin controller, we get mappings
+  like these:
+
+  {
+    {"map-spi0", spi0, pinctrl0, fspi0, gspi0},
+    {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0}
+  }
+
+  Every map must be assigned a symbolic name, pin controller and function.
+  The group is not compulsory - if it is omitted the first group presented by
+  the driver as applicable for the function will be selected, which is
+  useful for simple cases.
+
+  The device name is present in map entries tied to specific devices. Maps
+  without device names are referred to as SYSTEM pinmuxes, such as can be taken
+  by the machine implementation on boot and not tied to any specific device.
+
+  It is possible to map several groups to the same combination of device,
+  pin controller and function. This is for cases where a certain function on
+  a certain pin controller may use different sets of pins in different
+  configurations.
+
+- PINS for a certain FUNCTION using a certain PIN GROUP on a certain
+  PIN CONTROLLER are provided on a first-come first-serve basis, so if some
+  other device mux setting or GPIO pin request has already taken your physical
+  pin, you will be denied the use of it. To get (activate) a new setting, the
+  old one has to be put (deactivated) first.
+
+Sometimes the documentation and hardware registers will be oriented around
+pads (or "fingers") rather than pins - these are the soldering surfaces on the
+silicon inside the package, and may or may not match the actual number of
+pins/balls underneath the capsule. Pick some enumeration that makes sense to
+you. Define enumerators only for the pins you can control if that makes sense.
+
+Assumptions:
+
+We assume that the number possible function maps to pin groups is limited by
+the hardware. I.e. we assume that there is no system where any function can be
+mapped to any pin, like in a phone exchange. So the available pins groups for
+a certain function will be limited to a few choices (say up to eight or so),
+not hundreds or any amount of choices. This is the characteristic we have found
+by inspecting available pinmux hardware, and a necessary assumption since we
+expect pinmux drivers to present *all* possible function vs pin group mappings
+to the subsystem.
+
+
+Pinmux drivers
+==============
+
+The pinmux core takes care of preventing conflicts on pins and calling
+the pin controller driver to execute different settings.
+
+It is the responsibility of the pinmux driver to impose further restrictions
+(say for example infer electronic limitations due to load etc) to determine
+whether or not the requested function can actually be allowed, and in case it
+is possible to perform the requested mux setting, poke the hardware so that
+this happens.
+
+Pinmux drivers are required to supply a few callback functions, some are
+optional. Usually the enable() and disable() functions are implemented,
+writing values into some certain registers to activate a certain mux setting
+for a certain pin.
+
+A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4
+into some register named MUX to select a certain function with a certain
+group of pins would work something like this:
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned num_pins;
+};
+
+static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 };
+static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 };
+static const unsigned i2c0_pins[] = { 24, 25 };
+static const unsigned mmc0_1_pins[] = { 56, 57 };
+static const unsigned mmc0_2_pins[] = { 58, 59 };
+static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 };
+
+static const struct foo_group foo_groups[] = {
+	{
+		.name = "spi0_0_grp",
+		.pins = spi0_0_pins,
+		.num_pins = ARRAY_SIZE(spi0_0_pins),
+	},
+	{
+		.name = "spi0_1_grp",
+		.pins = spi0_1_pins,
+		.num_pins = ARRAY_SIZE(spi0_1_pins),
+	},
+	{
+		.name = "i2c0_grp",
+		.pins = i2c0_pins,
+		.num_pins = ARRAY_SIZE(i2c0_pins),
+	},
+	{
+		.name = "mmc0_1_grp",
+		.pins = mmc0_1_pins,
+		.num_pins = ARRAY_SIZE(mmc0_1_pins),
+	},
+	{
+		.name = "mmc0_2_grp",
+		.pins = mmc0_2_pins,
+		.num_pins = ARRAY_SIZE(mmc0_2_pins),
+	},
+	{
+		.name = "mmc0_3_grp",
+		.pins = mmc0_3_pins,
+		.num_pins = ARRAY_SIZE(mmc0_3_pins),
+	},
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_groups))
+		return -EINVAL;
+	return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       unsigned ** const pins,
+			       unsigned * const num_pins)
+{
+	*pins = (unsigned *) foo_groups[selector].pins;
+	*num_pins = foo_groups[selector].num_pins;
+	return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+	.list_groups = foo_list_groups,
+	.get_group_name = foo_get_group_name,
+	.get_group_pins = foo_get_group_pins,
+};
+
+struct foo_pmx_func {
+	const char *name;
+	const char * const *groups;
+	const unsigned num_groups;
+};
+
+static const char * const spi0_groups[] = { "spi0_1_grp" };
+static const char * const i2c0_groups[] = { "i2c0_grp" };
+static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
+					"mmc0_3_grp" };
+
+static const struct foo_pmx_func foo_functions[] = {
+	{
+		.name = "spi0",
+		.groups = spi0_groups,
+		.num_groups = ARRAY_SIZE(spi0_groups),
+	},
+	{
+		.name = "i2c0",
+		.groups = i2c0_groups,
+		.num_groups = ARRAY_SIZE(i2c0_groups),
+	},
+	{
+		.name = "mmc0",
+		.groups = mmc0_groups,
+		.num_groups = ARRAY_SIZE(mmc0_groups),
+	},
+};
+
+int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_functions))
+		return -EINVAL;
+	return 0;
+}
+
+const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	return myfuncs[selector].name;
+}
+
+static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+			  const char * const **groups,
+			  unsigned * const num_groups)
+{
+	*groups = foo_functions[selector].groups;
+	*num_groups = foo_functions[selector].num_groups;
+	return 0;
+}
+
+int foo_enable(struct pinctrl_dev *pctldev, unsigned selector,
+		unsigned group)
+{
+	u8 regbit = (1 << group);
+
+	writeb((readb(MUX)|regbit), MUX)
+	return 0;
+}
+
+int foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
+		unsigned group)
+{
+	u8 regbit = (1 << group);
+
+	writeb((readb(MUX) & ~(regbit)), MUX)
+	return 0;
+}
+
+struct pinmux_ops foo_pmxops = {
+	.list_functions = foo_list_funcs,
+	.get_function_name = foo_get_fname,
+	.get_function_groups = foo_get_groups,
+	.enable = foo_enable,
+	.disable = foo_disable,
+};
+
+/* Pinmux operations are handled by some pin controller */
+static struct pinctrl_desc foo_desc = {
+	...
+	.pctlops = &foo_pctrl_ops,
+	.pmxops = &foo_pmxops,
+};
+
+In the example activating muxing 0 and 1 at the same time setting bits
+0 and 1, uses one pin in common so they would collide.
+
+The beauty of the pinmux subsystem is that since it keeps track of all
+pins and who is using them, it will already have denied an impossible
+request like that, so the driver does not need to worry about such
+things - when it gets a selector passed in, the pinmux subsystem makes
+sure no other device or GPIO assignment is already using the selected
+pins. Thus bits 0 and 1 in the control register will never be set at the
+same time.
+
+All the above functions are mandatory to implement for a pinmux driver.
+
+
+Pinmux interaction with the GPIO subsystem
+==========================================
+
+The function list could become long, especially if you can convert every
+individual pin into a GPIO pin independent of any other pins, and then try
+the approach to define every pin as a function.
+
+In this case, the function array would become 64 entries for each GPIO
+setting and then the device functions.
+
+For this reason there is an additional function a pinmux driver can implement
+to enable only GPIO on an individual pin: .gpio_request_enable(). The same
+.free() function as for other functions is assumed to be usable also for
+GPIO pins.
+
+This function will pass in the affected GPIO range identified by the pin
+controller core, so you know which GPIO pins are being affected by the request
+operation.
+
+Alternatively it is fully allowed to use named functions for each GPIO
+pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN"
+where "N" is the global GPIO pin number if no special GPIO-handler is
+registered.
+
+
+Pinmux board/machine configuration
+==================================
+
+Boards and machines define how a certain complete running system is put
+together, including how GPIOs and devices are muxed, how regulators are
+constrained and how the clock tree looks. Of course pinmux settings are also
+part of this.
+
+A pinmux config for a machine looks pretty much like a simple regulator
+configuration, so for the example array above we want to enable i2c and
+spi on the second function mapping:
+
+#include <linux/pinctrl/machine.h>
+
+static struct pinmux_map pmx_mapping[] = {
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "spi0",
+		.dev_name = "foo-spi.0",
+	},
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "i2c0",
+		.dev_name = "foo-i2c.0",
+	},
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "mmc0",
+		.dev_name = "foo-mmc.0",
+	},
+};
+
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+
+As you can see we may have several pin controllers on the system and thus
+we need to specify which one of them that contain the functions we wish
+to map. The map can also use struct device * directly, so there is no
+inherent need to use strings to specify .dev_name or .ctrl_dev_name, these
+are for the situation where you do not have a handle to the struct device *,
+for example if they are not yet instantiated or cumbersome to obtain.
+
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+       ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact which assumes you want to use pinctrl.0 and position
+0 for mapping, for example:
+
+static struct pinmux_map pmx_mapping[] = {
+       PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"),
+};
+
+
+Complex mappings
+================
+
+As it is possible to map a function to different groups of pins an optional
+.group can be specified like this:
+
+...
+{
+	.name = "spi0-pos-A",
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "spi0",
+	.group = "spi0_0_grp",
+	.dev_name = "foo-spi.0",
+},
+{
+	.name = "spi0-pos-B",
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "spi0",
+	.group = "spi0_1_grp",
+	.dev_name = "foo-spi.0",
+},
+...
+
+This example mapping is used to switch between two positions for spi0 at
+runtime, as described further below under the heading "Runtime pinmuxing".
+
+Further it is possible to match several groups of pins to the same function
+for a single device, say for example in the mmc0 example above, where you can
+additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all
+three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the
+case), we define a mapping like this:
+
+...
+{
+	.name "2bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "4bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "4bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_1_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_1_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_2_grp",
+	.dev_name = "foo-mmc.0",
+},
+...
+
+The result of grabbing this mapping from the device with something like
+this (see next paragraph):
+
+	pmx = pinmux_get(&device, "8bit");
+
+Will be that you activate all the three bottom records in the mapping at
+once. Since they share the same name, pin controller device, funcion and
+device, and since we allow multiple groups to match to a single device, they
+all get selected, and they all get enabled and disable simultaneously by the
+pinmux core.
+
+
+Pinmux requests from drivers
+============================
+
+Generally it is discouraged to let individual drivers get and enable pinmuxes.
+So if possible, handle the pinmuxes in platform code or some other place where
+you have access to all the affected struct device * pointers. In some cases
+where a driver needs to switch between different mux mappings at runtime
+this is not possible.
+
+A driver may request a certain mux to be activated, usually just the default
+mux like this:
+
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_state {
+       struct pinmux *pmx;
+       ...
+};
+
+foo_probe()
+{
+	/* Allocate a state holder named "state" etc */
+	struct pinmux pmx;
+
+	pmx = pinmux_get(&device, NULL);
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+
+	state->pmx = pmx;
+}
+
+foo_remove()
+{
+	pinmux_disable(state->pmx);
+	pinmux_put(state->pmx);
+}
+
+If you want to grab a specific mux mapping and not just the first one found for
+this device you can specify a specific mapping name, for example in the above
+example the second i2c0 setting: pinmux_get(&device, "spi0-pos-B");
+
+This get/enable/disable/put sequence can just as well be handled by bus drivers
+if you don't want each and every driver to handle it and you know the
+arrangement on your bus.
+
+The semantics of the get/enable respective disable/put is as follows:
+
+- pinmux_get() is called in process context to reserve the pins affected with
+  a certain mapping and set up the pinmux core and the driver. It will allocate
+  a struct from the kernel memory to hold the pinmux state.
+
+- pinmux_enable()/pinmux_disable() is quick and can be called from fastpath
+  (irq context) when you quickly want to set up/tear down the hardware muxing
+  when running a device driver. Usually it will just poke some values into a
+  register.
+
+- pinmux_disable() is called in process context to tear down the pin requests
+  and release the state holder struct for the mux setting.
+
+Usually the pinmux core handled the get/put pair and call out to the device
+drivers bookkeeping operations, like checking available functions and the
+associated pins, whereas the enable/disable pass on to the pin controller
+driver which takes care of activating and/or deactivating the mux setting by
+quickly poking some registers.
+
+The pins are allocated for your device when you issue the pinmux_get() call,
+after this you should be able to see this in the debugfs listing of all pins.
+
+
+System pinmux hogging
+=====================
+
+A system pinmux map entry, i.e. a pinmux setting that does not have a device
+associated with it, can be hogged by the core when the pin controller is
+registered. This means that the core will attempt to call pinmux_get() and
+pinmux_enable() on it immediately after the pin control device has been
+registered.
+
+This is enabled by simply setting the .hog_on_boot field in the map to true,
+like this:
+
+{
+	.name "POWERMAP"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "power_func",
+	.hog_on_boot = true,
+},
+
+Since it may be common to request the core to hog a few always-applicable
+mux settings on the primary pin controller, there is a convenience macro for
+this:
+
+PINMUX_MAP_PRIMARY_SYS_HOG("POWERMAP", "power_func")
+
+This gives the exact same result as the above construction.
+
+
+Runtime pinmuxing
+=================
+
+It is possible to mux a certain function in and out at runtime, say to move
+an SPI port from one set of pins to another set of pins. Say for example for
+spi0 in the example above, we expose two different groups of pins for the same
+function, but with different named in the mapping as described under
+"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and
+"spi0-pos-B".
+
+This snippet first muxes the function in the pins defined by group A, enables
+it, disables and releases it, and muxes it in on the pins defined by group B:
+
+foo_switch()
+{
+	struct pinmux pmx;
+
+	/* Enable on position A */
+	pmx = pinmux_get(&device, "spi0-pos-A");
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+
+	/* This releases the pins again */
+	pinmux_disable(pmx);
+	pinmux_put(pmx);
+
+	/* Enable on position B */
+	pmx = pinmux_get(&device, "spi0-pos-B");
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+	...
+}
+
+The above has to be done from process context.
diff -druNp linux-libre-3.1-gnu1/Documentation/power/00-INDEX linux-libre-3.2-gnu1/Documentation/power/00-INDEX
--- linux-libre-3.1-gnu1/Documentation/power/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@ s2ram.txt
 	- How to get suspend to ram working (and debug it when it isn't)
 states.txt
 	- System power management states
+suspend-and-cpuhotplug.txt
+	- Explains the interaction between Suspend-to-RAM (S3) and CPU hotplug
 swsusp-and-swap-files.txt
 	- Using swap files with software suspend (to disk)
 swsusp-dmcrypt.txt
diff -druNp linux-libre-3.1-gnu1/Documentation/power/basic-pm-debugging.txt linux-libre-3.2-gnu1/Documentation/power/basic-pm-debugging.txt
--- linux-libre-3.1-gnu1/Documentation/power/basic-pm-debugging.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/basic-pm-debugging.txt	2012-01-04 18:55:44.000000000 -0500
@@ -173,7 +173,7 @@ kernel messages using the serial console
 information about the reasons of the suspend (resume) failure.  Alternatively,
 it may be possible to use a FireWire port for debugging with firescope
 (ftp://ftp.firstfloor.org/pub/ak/firescope/).  On x86 it is also possible to
-use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
+use the PM_TRACE mechanism documented in Documentation/power/s2ram.txt .
 
 2. Testing suspend to RAM (STR)
 
@@ -201,3 +201,27 @@ case, you may be able to search for fail
 analogous to the one described in section 1.  If you find some failing drivers,
 you will have to unload them every time before an STR transition (ie. before
 you run s2ram), and please report the problems with them.
+
+There is a debugfs entry which shows the suspend to RAM statistics. Here is an
+example of its output.
+	# mount -t debugfs none /sys/kernel/debug
+	# cat /sys/kernel/debug/suspend_stats
+	success: 20
+	fail: 5
+	failed_freeze: 0
+	failed_prepare: 0
+	failed_suspend: 5
+	failed_suspend_noirq: 0
+	failed_resume: 0
+	failed_resume_noirq: 0
+	failures:
+	  last_failed_dev:	alarm
+				adc
+	  last_failed_errno:	-16
+				-16
+	  last_failed_step:	suspend
+				suspend
+Field success means the success number of suspend to RAM, and field fail means
+the failure number. Others are the failure number of different steps of suspend
+to RAM. suspend_stats just lists the last 2 failed devices, error number and
+failed step of suspend.
diff -druNp linux-libre-3.1-gnu1/Documentation/power/devices.txt linux-libre-3.2-gnu1/Documentation/power/devices.txt
--- linux-libre-3.1-gnu1/Documentation/power/devices.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/devices.txt	2012-01-04 18:55:44.000000000 -0500
@@ -123,9 +123,10 @@ please refer directly to the source code
 Subsystem-Level Methods
 -----------------------
 The core methods to suspend and resume devices reside in struct dev_pm_ops
-pointed to by the pm member of struct bus_type, struct device_type and
-struct class.  They are mostly of interest to the people writing infrastructure
-for buses, like PCI or USB, or device type and device class drivers.
+pointed to by the ops member of struct dev_pm_domain, or by the pm member of
+struct bus_type, struct device_type and struct class.  They are mostly of
+interest to the people writing infrastructure for platforms and buses, like PCI
+or USB, or device type and device class drivers.
 
 Bus drivers implement these methods as appropriate for the hardware and the
 drivers using it; PCI works differently from USB, and so on.  Not many people
@@ -139,39 +140,57 @@ sequencing in the driver model tree.
 
 /sys/devices/.../power/wakeup files
 -----------------------------------
-All devices in the driver model have two flags to control handling of wakeup
-events (hardware signals that can force the device and/or system out of a low
-power state).  These flags are initialized by bus or device driver code using
+All device objects in the driver model contain fields that control the handling
+of system wakeup events (hardware signals that can force the system out of a
+sleep state).  These fields are initialized by bus or device driver code using
 device_set_wakeup_capable() and device_set_wakeup_enable(), defined in
 include/linux/pm_wakeup.h.
 
-The "can_wakeup" flag just records whether the device (and its driver) can
+The "power.can_wakeup" flag just records whether the device (and its driver) can
 physically support wakeup events.  The device_set_wakeup_capable() routine
-affects this flag.  The "should_wakeup" flag controls whether the device should
-try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
-for the most part drivers should not change its value.  The initial value of
-should_wakeup is supposed to be false for the majority of devices; the major
-exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
-(wake-on-LAN) feature has been set up with ethtool.
+affects this flag.  The "power.wakeup" field is a pointer to an object of type
+struct wakeup_source used for controlling whether or not the device should use
+its system wakeup mechanism and for notifying the PM core of system wakeup
+events signaled by the device.  This object is only present for wakeup-capable
+devices (i.e. devices whose "can_wakeup" flags are set) and is created (or
+removed) by device_set_wakeup_capable().
 
 Whether or not a device is capable of issuing wakeup events is a hardware
 matter, and the kernel is responsible for keeping track of it.  By contrast,
 whether or not a wakeup-capable device should issue wakeup events is a policy
 decision, and it is managed by user space through a sysfs attribute: the
-power/wakeup file.  User space can write the strings "enabled" or "disabled" to
-set or clear the "should_wakeup" flag, respectively.  This file is only present
-for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
-and is created (or removed) by device_set_wakeup_capable().  Reads from the
-file will return the corresponding string.
+"power/wakeup" file.  User space can write the strings "enabled" or "disabled"
+to it to indicate whether or not, respectively, the device is supposed to signal
+system wakeup.  This file is only present if the "power.wakeup" object exists
+for the given device and is created (or removed) along with that object, by
+device_set_wakeup_capable().  Reads from the file will return the corresponding
+string.
 
-The device_may_wakeup() routine returns true only if both flags are set.
+The "power/wakeup" file is supposed to contain the "disabled" string initially
+for the majority of devices; the major exceptions are power buttons, keyboards,
+and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with
+ethtool.  It should also default to "enabled" for devices that don't generate
+wakeup requests on their own but merely forward wakeup requests from one bus to
+another (like PCI Express ports).
+
+The device_may_wakeup() routine returns true only if the "power.wakeup" object
+exists and the corresponding "power/wakeup" file contains the string "enabled".
 This information is used by subsystems, like the PCI bus type code, to see
 whether or not to enable the devices' wakeup mechanisms.  If device wakeup
 mechanisms are enabled or disabled directly by drivers, they also should use
 device_may_wakeup() to decide what to do during a system sleep transition.
-However for runtime power management, wakeup events should be enabled whenever
-the device and driver both support them, regardless of the should_wakeup flag.
+Device drivers, however, are not supposed to call device_set_wakeup_enable()
+directly in any case.
 
+It ought to be noted that system wakeup is conceptually different from "remote
+wakeup" used by runtime power management, although it may be supported by the
+same physical mechanism.  Remote wakeup is a feature allowing devices in
+low-power states to trigger specific interrupts to signal conditions in which
+they should be put into the full-power state.  Those interrupts may or may not
+be used to signal system wakeup events, depending on the hardware design.  On
+some systems it is impossible to trigger them from system sleep states.  In any
+case, remote wakeup should always be enabled for runtime power management for
+all devices and drivers that support it.
 
 /sys/devices/.../power/control files
 ------------------------------------
@@ -247,20 +266,31 @@ for every device before the next phase b
 support all these callbacks and not all drivers use all the callbacks.  The
 various phases always run after tasks have been frozen and before they are
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
-been disabled (except for those marked with the IRQ_WAKEUP flag).
+been disabled (except for those marked with the IRQF_NO_SUSPEND flag).
 
-All phases use bus, type, or class callbacks (that is, methods defined in
-dev->bus->pm, dev->type->pm, or dev->class->pm).  These callbacks are mutually
-exclusive, so if the device type provides a struct dev_pm_ops object pointed to
-by its pm field (i.e. both dev->type and dev->type->pm are defined), the
-callbacks included in that object (i.e. dev->type->pm) will be used.  Otherwise,
-if the class provides a struct dev_pm_ops object pointed to by its pm field
-(i.e. both dev->class and dev->class->pm are defined), the PM core will use the
-callbacks from that object (i.e. dev->class->pm).  Finally, if the pm fields of
-both the device type and class objects are NULL (or those objects do not exist),
-the callbacks provided by the bus (that is, the callbacks from dev->bus->pm)
-will be used (this allows device types to override callbacks provided by bus
-types or classes if necessary).
+All phases use PM domain, bus, type, or class callbacks (that is, methods
+defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm).
+These callbacks are regarded by the PM core as mutually exclusive.  Moreover,
+PM domain callbacks always take precedence over bus, type and class callbacks,
+while type callbacks take precedence over bus and class callbacks, and class
+callbacks take precedence over bus callbacks.  To be precise, the following
+rules are used to determine which callback to execute in the given phase:
+
+    1.	If dev->pm_domain is present, the PM core will attempt to execute the
+	callback included in dev->pm_domain->ops.  If that callback is not
+	present, no action will be carried out for the given device.
+
+    2.	Otherwise, if both dev->type and dev->type->pm are present, the callback
+	included in dev->type->pm will be executed.
+
+    3.	Otherwise, if both dev->class and dev->class->pm are present, the
+	callback included in dev->class->pm will be executed.
+
+    4.	Otherwise, if both dev->bus and dev->bus->pm are present, the callback
+	included in dev->bus->pm will be executed.
+
+This allows PM domains and device types to override callbacks provided by bus
+types or device classes if necessary.
 
 These callbacks may in turn invoke device- or driver-specific methods stored in
 dev->driver->pm, but they don't have to.
@@ -279,15 +309,10 @@ When the system goes into the standby or
 	time.)  Unlike the other suspend-related phases, during the prepare
 	phase the device tree is traversed top-down.
 
-	In addition to that, if device drivers need to allocate additional
-	memory to be able to hadle device suspend correctly, that should be
-	done in the prepare phase.
-
 	After the prepare callback method returns, no new children may be
 	registered below the device.  The method may also prepare the device or
-	driver in some way for the upcoming system power transition (for
-	example, by allocating additional memory required for this purpose), but
-	it should not put the device into a low-power state.
+	driver in some way for the upcoming system power transition, but it
+	should not put the device into a low-power state.
 
     2.	The suspend methods should quiesce the device to stop it from performing
 	I/O.  They also may save the device registers and put it into the
diff -druNp linux-libre-3.1-gnu1/Documentation/power/freezing-of-tasks.txt linux-libre-3.2-gnu1/Documentation/power/freezing-of-tasks.txt
--- linux-libre-3.1-gnu1/Documentation/power/freezing-of-tasks.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/freezing-of-tasks.txt	2012-01-04 18:55:44.000000000 -0500
@@ -22,12 +22,12 @@ try_to_freeze_tasks() that sets TIF_FREE
 either wakes them up, if they are kernel threads, or sends fake signals to them,
 if they are user space processes.  A task that has TIF_FREEZE set, should react
 to it by calling the function called refrigerator() (defined in
-kernel/power/process.c), which sets the task's PF_FROZEN flag, changes its state
+kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
 to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
 Then, we say that the task is 'frozen' and therefore the set of functions
 handling this mechanism is referred to as 'the freezer' (these functions are
-defined in kernel/power/process.c and include/linux/freezer.h).  User space
-processes are generally frozen before kernel threads.
+defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
+User space processes are generally frozen before kernel threads.
 
 It is not recommended to call refrigerator() directly.  Instead, it is
 recommended to use the try_to_freeze() function (defined in
@@ -95,7 +95,7 @@ after the memory for the image has been
 additional memory and we prevent them from doing that by freezing them earlier.
 [Of course, this also means that device drivers should not allocate substantial
 amounts of memory from their .suspend() callbacks before hibernation, but this
-is e separate issue.]
+is a separate issue.]
 
 3. The third reason is to prevent user space processes and some kernel threads
 from interfering with the suspending and resuming of devices.  A user space
diff -druNp linux-libre-3.1-gnu1/Documentation/power/pm_qos_interface.txt linux-libre-3.2-gnu1/Documentation/power/pm_qos_interface.txt
--- linux-libre-3.1-gnu1/Documentation/power/pm_qos_interface.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/pm_qos_interface.txt	2012-01-04 18:55:44.000000000 -0500
@@ -4,14 +4,19 @@ This interface provides a kernel and use
 performance expectations by drivers, subsystems and user space applications on
 one of the parameters.
 
-Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
-initial set of pm_qos parameters.
+Two different PM QoS frameworks are available:
+1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
+2. the per-device PM QoS framework provides the API to manage the per-device latency
+constraints.
 
 Each parameters have defined units:
  * latency: usec
  * timeout: usec
  * throughput: kbs (kilo bit / sec)
 
+
+1. PM QoS framework
+
 The infrastructure exposes multiple misc device nodes one per implemented
 parameter.  The set of parameters implement is defined by pm_qos_power_init()
 and pm_qos_params.h.  This is done because having the available parameters
@@ -23,14 +28,18 @@ an aggregated target value.  The aggrega
 changes to the request list or elements of the list.  Typically the
 aggregated target value is simply the max or min of the request values held
 in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
 
 From kernel mode the use of this interface is simple:
 
-handle = pm_qos_add_request(param_class, target_value):
-Will insert an element into the list for that identified PM_QOS class with the
+void pm_qos_add_request(handle, param_class, target_value):
+Will insert an element into the list for that identified PM QoS class with the
 target value.  Upon change to this list the new target is recomputed and any
 registered notifiers are called only if the target value is now different.
-Clients of pm_qos need to save the returned handle.
+Clients of pm_qos need to save the returned handle for future use in other
+pm_qos API functions.
 
 void pm_qos_update_request(handle, new_target_value):
 Will update the list element pointed to by the handle with the new target value
@@ -42,6 +51,20 @@ Will remove the element.  After removal
 call the notification tree if the target was changed as a result of removing
 the request.
 
+int pm_qos_request(param_class):
+Returns the aggregated value for a given PM QoS class.
+
+int pm_qos_request_active(handle):
+Returns if the request is still active, i.e. it has not been removed from a
+PM QoS class constraints list.
+
+int pm_qos_add_notifier(param_class, notifier):
+Adds a notification callback function to the PM QoS class. The callback is
+called when the aggregated value for the PM QoS class is changed.
+
+int pm_qos_remove_notifier(int param_class, notifier):
+Removes the notification callback function for the PM QoS class.
+
 
 From user mode:
 Only processes can register a pm_qos request.  To provide for automatic
@@ -63,4 +86,63 @@ To remove the user mode request for a ta
 node.
 
 
+2. PM QoS per-device latency framework
+
+For each device a list of performance requests is maintained along with
+an aggregated target value.  The aggregated target value is updated with
+changes to the request list or elements of the list.  Typically the
+aggregated target value is simply the max or min of the request values held
+in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
+
+From kernel mode the use of this interface is the following:
+
+int dev_pm_qos_add_request(device, handle, value):
+Will insert an element into the list for that identified device with the
+target value.  Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of dev_pm_qos need to save the handle for future use in other
+dev_pm_qos API functions.
+
+int dev_pm_qos_update_request(handle, new_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification trees if the
+target is changed.
+
+int dev_pm_qos_remove_request(handle):
+Will remove the element.  After removal it will update the aggregate target and
+call the notification trees if the target was changed as a result of removing
+the request.
+
+s32 dev_pm_qos_read_value(device):
+Returns the aggregated value for a given device's constraints list.
+
+
+Notification mechanisms:
+The per-device PM QoS framework has 2 different and distinct notification trees:
+a per-device notification tree and a global notification tree.
+
+int dev_pm_qos_add_notifier(device, notifier):
+Adds a notification callback function for the device.
+The callback is called when the aggregated value of the device constraints list
+is changed.
+
+int dev_pm_qos_remove_notifier(device, notifier):
+Removes the notification callback function for the device.
+
+int dev_pm_qos_add_global_notifier(notifier):
+Adds a notification callback function in the global notification tree of the
+framework.
+The callback is called when the aggregated value for any device is changed.
+
+int dev_pm_qos_remove_global_notifier(notifier):
+Removes the notification callback function from the global notification tree
+of the framework.
+
+
+From user mode:
+No API for user space access to the per-device latency constraints is provided
+yet - still under discussion.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/power/regulator/machine.txt linux-libre-3.2-gnu1/Documentation/power/regulator/machine.txt
--- linux-libre-3.1-gnu1/Documentation/power/regulator/machine.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/regulator/machine.txt	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@ initialisation code by creating a struct
 each regulator.
 
 struct regulator_consumer_supply {
-	struct device *dev;	/* consumer */
+	const char *dev_name;	/* consumer dev_name() */
 	const char *supply;	/* consumer supply - e.g. "vcc" */
 };
 
@@ -24,13 +24,13 @@ e.g. for the machine above
 
 static struct regulator_consumer_supply regulator1_consumers[] = {
 {
-	.dev	= &platform_consumerB_device.dev,
-	.supply	= "Vcc",
+	.dev_name	= "dev_name(consumer B)",
+	.supply		= "Vcc",
 },};
 
 static struct regulator_consumer_supply regulator2_consumers[] = {
 {
-	.dev	= &platform_consumerA_device.dev,
+	.dev	= "dev_name(consumer A"),
 	.supply	= "Vcc",
 },};
 
@@ -43,6 +43,7 @@ to their supply regulator :-
 
 static struct regulator_init_data regulator1_data = {
 	.constraints = {
+		.name = "Regulator-1",
 		.min_uV = 3300000,
 		.max_uV = 3300000,
 		.valid_modes_mask = REGULATOR_MODE_NORMAL,
@@ -51,13 +52,19 @@ static struct regulator_init_data regula
 	.consumer_supplies = regulator1_consumers,
 };
 
+The name field should be set to something that is usefully descriptive
+for the board for configuration of supplies for other regulators and
+for use in logging and other diagnostic output.  Normally the name
+used for the supply rail in the schematic is a good choice.  If no
+name is provided then the subsystem will choose one.
+
 Regulator-1 supplies power to Regulator-2. This relationship must be registered
 with the core so that Regulator-1 is also enabled when Consumer A enables its
 supply (Regulator-2). The supply regulator is set by the supply_regulator
-field below:-
+field below and co:-
 
 static struct regulator_init_data regulator2_data = {
-	.supply_regulator = "regulator_name",
+	.supply_regulator = "Regulator-1",
 	.constraints = {
 		.min_uV = 1800000,
 		.max_uV = 2000000,
diff -druNp linux-libre-3.1-gnu1/Documentation/power/runtime_pm.txt linux-libre-3.2-gnu1/Documentation/power/runtime_pm.txt
--- linux-libre-3.1-gnu1/Documentation/power/runtime_pm.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/runtime_pm.txt	2012-01-04 18:55:44.000000000 -0500
@@ -43,21 +43,34 @@ struct dev_pm_ops {
 	...
 };
 
-The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
-executed by the PM core for either the device type, or the class (if the device
-type's struct dev_pm_ops object does not exist), or the bus type (if the
-device type's and class' struct dev_pm_ops objects do not exist) of the given
-device (this allows device types to override callbacks provided by bus types or
-classes if necessary).  The bus type, device type and class callbacks are
-referred to as subsystem-level callbacks in what follows.
+The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
+are executed by the PM core for the device's subsystem that may be either of
+the following:
+
+  1. PM domain of the device, if the device's PM domain object, dev->pm_domain,
+     is present.
+
+  2. Device type of the device, if both dev->type and dev->type->pm are present.
+
+  3. Device class of the device, if both dev->class and dev->class->pm are
+     present.
+
+  4. Bus type of the device, if both dev->bus and dev->bus->pm are present.
+
+The PM core always checks which callback to use in the order given above, so the
+priority order of callbacks from high to low is: PM domain, device type, class
+and bus type.  Moreover, the high-priority one will always take precedence over
+a low-priority one.  The PM domain, bus type, device type and class callbacks
+are referred to as subsystem-level callbacks in what follows.
 
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
-to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled.
-This implies that these callback routines must not block or sleep, but it also
-means that the synchronous helper functions listed at the end of Section 4 can
-be used within an interrupt handler or in an atomic context.
+to tell the PM core that their ->runtime_suspend(), ->runtime_resume() and
+->runtime_idle() callbacks may be invoked in atomic context with interrupts
+disabled for a given device.  This implies that the callback routines in
+question must not block or sleep, but it also means that the synchronous helper
+functions listed at the end of Section 4 may be used for that device within an
+interrupt handler or generally in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
@@ -477,12 +490,14 @@ pm_runtime_autosuspend_expiration()
 If pm_runtime_irq_safe() has been called for a device then the following helper
 functions may also be used in interrupt context:
 
+pm_runtime_idle()
 pm_runtime_suspend()
 pm_runtime_autosuspend()
 pm_runtime_resume()
 pm_runtime_get_sync()
 pm_runtime_put_sync()
 pm_runtime_put_sync_suspend()
+pm_runtime_put_sync_autosuspend()
 
 5. Runtime PM Initialization, Device Probing and Removal
 
@@ -782,6 +797,16 @@ will behave normally, not taking the aut
 Similarly, if the power.use_autosuspend field isn't set then the autosuspend
 helper functions will behave just like the non-autosuspend counterparts.
 
+Under some circumstances a driver or subsystem may want to prevent a device
+from autosuspending immediately, even though the usage counter is zero and the
+autosuspend delay time has expired.  If the ->runtime_suspend() callback
+returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is
+in the future (as it normally would be if the callback invoked
+pm_runtime_mark_last_busy()), the PM core will automatically reschedule the
+autosuspend.  The ->runtime_suspend() callback can't do this rescheduling
+itself because no suspend requests of any kind are accepted while the device is
+suspending (i.e., while the callback is running).
+
 The implementation is well suited for asynchronous use in interrupt contexts.
 However such use inevitably involves races, because the PM core can't
 synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
diff -druNp linux-libre-3.1-gnu1/Documentation/power/suspend-and-cpuhotplug.txt linux-libre-3.2-gnu1/Documentation/power/suspend-and-cpuhotplug.txt
--- linux-libre-3.1-gnu1/Documentation/power/suspend-and-cpuhotplug.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/power/suspend-and-cpuhotplug.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,275 @@
+Interaction of Suspend code (S3) with the CPU hotplug infrastructure
+
+     (C) 2011 Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
+
+
+I. How does the regular CPU hotplug code differ from how the Suspend-to-RAM
+   infrastructure uses it internally? And where do they share common code?
+
+Well, a picture is worth a thousand words... So ASCII art follows :-)
+
+[This depicts the current design in the kernel, and focusses only on the
+interactions involving the freezer and CPU hotplug and also tries to explain
+the locking involved. It outlines the notifications involved as well.
+But please note that here, only the call paths are illustrated, with the aim
+of describing where they take different paths and where they share code.
+What happens when regular CPU hotplug and Suspend-to-RAM race with each other
+is not depicted here.]
+
+On a high level, the suspend-resume cycle goes like this:
+
+|Freeze| -> |Disable nonboot| -> |Do suspend| -> |Enable nonboot| -> |Thaw |
+|tasks |    |     cpus      |    |          |    |     cpus     |    |tasks|
+
+
+More details follow:
+
+                                Suspend call path
+                                -----------------
+
+                                  Write 'mem' to
+                                /sys/power/state
+                                    syfs file
+                                        |
+                                        v
+                               Acquire pm_mutex lock
+                                        |
+                                        v
+                             Send PM_SUSPEND_PREPARE
+                                   notifications
+                                        |
+                                        v
+                                   Freeze tasks
+                                        |
+                                        |
+                                        v
+                              disable_nonboot_cpus()
+                                   /* start */
+                                        |
+                                        v
+                            Acquire cpu_add_remove_lock
+                                        |
+                                        v
+                             Iterate over CURRENTLY
+                                   online CPUs
+                                        |
+                                        |
+                                        |                ----------
+                                        v                          | L
+             ======>               _cpu_down()                     |
+            |              [This takes cpuhotplug.lock             |
+  Common    |               before taking down the CPU             |
+   code     |               and releases it when done]             | O
+            |            While it is at it, notifications          |
+            |            are sent when notable events occur,       |
+             ======>     by running all registered callbacks.      |
+                                        |                          | O
+                                        |                          |
+                                        |                          |
+                                        v                          |
+                            Note down these cpus in                | P
+                                frozen_cpus mask         ----------
+                                        |
+                                        v
+                           Disable regular cpu hotplug
+                        by setting cpu_hotplug_disabled=1
+                                        |
+                                        v
+                            Release cpu_add_remove_lock
+                                        |
+                                        v
+                       /* disable_nonboot_cpus() complete */
+                                        |
+                                        v
+                                   Do suspend
+
+
+
+Resuming back is likewise, with the counterparts being (in the order of
+execution during resume):
+* enable_nonboot_cpus() which involves:
+   |  Acquire cpu_add_remove_lock
+   |  Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug
+   |  Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop]
+   |  Release cpu_add_remove_lock
+   v
+
+* thaw tasks
+* send PM_POST_SUSPEND notifications
+* Release pm_mutex lock.
+
+
+It is to be noted here that the pm_mutex lock is acquired at the very
+beginning, when we are just starting out to suspend, and then released only
+after the entire cycle is complete (i.e., suspend + resume).
+
+
+
+                          Regular CPU hotplug call path
+                          -----------------------------
+
+                                Write 0 (or 1) to
+                       /sys/devices/system/cpu/cpu*/online
+                                    sysfs file
+                                        |
+                                        |
+                                        v
+                                    cpu_down()
+                                        |
+                                        v
+                           Acquire cpu_add_remove_lock
+                                        |
+                                        v
+                          If cpu_hotplug_disabled is 1
+                                return gracefully
+                                        |
+                                        |
+                                        v
+             ======>                _cpu_down()
+            |              [This takes cpuhotplug.lock
+  Common    |               before taking down the CPU
+   code     |               and releases it when done]
+            |            While it is at it, notifications
+            |           are sent when notable events occur,
+             ======>    by running all registered callbacks.
+                                        |
+                                        |
+                                        v
+                          Release cpu_add_remove_lock
+                               [That's it!, for
+                              regular CPU hotplug]
+
+
+
+So, as can be seen from the two diagrams (the parts marked as "Common code"),
+regular CPU hotplug and the suspend code path converge at the _cpu_down() and
+_cpu_up() functions. They differ in the arguments passed to these functions,
+in that during regular CPU hotplug, 0 is passed for the 'tasks_frozen'
+argument. But during suspend, since the tasks are already frozen by the time
+the non-boot CPUs are offlined or onlined, the _cpu_*() functions are called
+with the 'tasks_frozen' argument set to 1.
+[See below for some known issues regarding this.]
+
+
+Important files and functions/entry points:
+------------------------------------------
+
+kernel/power/process.c : freeze_processes(), thaw_processes()
+kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish()
+kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](), [disable|enable]_nonboot_cpus()
+
+
+
+II. What are the issues involved in CPU hotplug?
+    -------------------------------------------
+
+There are some interesting situations involving CPU hotplug and microcode
+update on the CPUs, as discussed below:
+
+[Please bear in mind that the kernel requests the microcode images from
+userspace, using the request_firmware() function defined in
+drivers/base/firmware_class.c]
+
+
+a. When all the CPUs are identical:
+
+   This is the most common situation and it is quite straightforward: we want
+   to apply the same microcode revision to each of the CPUs.
+   To give an example of x86, the collect_cpu_info() function defined in
+   arch/x86/kernel/microcode_core.c helps in discovering the type of the CPU
+   and thereby in applying the correct microcode revision to it.
+   But note that the kernel does not maintain a common microcode image for the
+   all CPUs, in order to handle case 'b' described below.
+
+
+b. When some of the CPUs are different than the rest:
+
+   In this case since we probably need to apply different microcode revisions
+   to different CPUs, the kernel maintains a copy of the correct microcode
+   image for each CPU (after appropriate CPU type/model discovery using
+   functions such as collect_cpu_info()).
+
+
+c. When a CPU is physically hot-unplugged and a new (and possibly different
+   type of) CPU is hot-plugged into the system:
+
+   In the current design of the kernel, whenever a CPU is taken offline during
+   a regular CPU hotplug operation, upon receiving the CPU_DEAD notification
+   (which is sent by the CPU hotplug code), the microcode update driver's
+   callback for that event reacts by freeing the kernel's copy of the
+   microcode image for that CPU.
+
+   Hence, when a new CPU is brought online, since the kernel finds that it
+   doesn't have the microcode image, it does the CPU type/model discovery
+   afresh and then requests the userspace for the appropriate microcode image
+   for that CPU, which is subsequently applied.
+
+   For example, in x86, the mc_cpu_callback() function (which is the microcode
+   update driver's callback registered for CPU hotplug events) calls
+   microcode_update_cpu() which would call microcode_init_cpu() in this case,
+   instead of microcode_resume_cpu() when it finds that the kernel doesn't
+   have a valid microcode image. This ensures that the CPU type/model
+   discovery is performed and the right microcode is applied to the CPU after
+   getting it from userspace.
+
+
+d. Handling microcode update during suspend/hibernate:
+
+   Strictly speaking, during a CPU hotplug operation which does not involve
+   physically removing or inserting CPUs, the CPUs are not actually powered
+   off during a CPU offline. They are just put to the lowest C-states possible.
+   Hence, in such a case, it is not really necessary to re-apply microcode
+   when the CPUs are brought back online, since they wouldn't have lost the
+   image during the CPU offline operation.
+
+   This is the usual scenario encountered during a resume after a suspend.
+   However, in the case of hibernation, since all the CPUs are completely
+   powered off, during restore it becomes necessary to apply the microcode
+   images to all the CPUs.
+
+   [Note that we don't expect someone to physically pull out nodes and insert
+   nodes with a different type of CPUs in-between a suspend-resume or a
+   hibernate/restore cycle.]
+
+   In the current design of the kernel however, during a CPU offline operation
+   as part of the suspend/hibernate cycle (the CPU_DEAD_FROZEN notification),
+   the existing copy of microcode image in the kernel is not freed up.
+   And during the CPU online operations (during resume/restore), since the
+   kernel finds that it already has copies of the microcode images for all the
+   CPUs, it just applies them to the CPUs, avoiding any re-discovery of CPU
+   type/model and the need for validating whether the microcode revisions are
+   right for the CPUs or not (due to the above assumption that physical CPU
+   hotplug will not be done in-between suspend/resume or hibernate/restore
+   cycles).
+
+
+III. Are there any known problems when regular CPU hotplug and suspend race
+     with each other?
+
+Yes, they are listed below:
+
+1. When invoking regular CPU hotplug, the 'tasks_frozen' argument passed to
+   the _cpu_down() and _cpu_up() functions is *always* 0.
+   This might not reflect the true current state of the system, since the
+   tasks could have been frozen by an out-of-band event such as a suspend
+   operation in progress. Hence, it will lead to wrong notifications being
+   sent during the cpu online/offline events (eg, CPU_ONLINE notification
+   instead of CPU_ONLINE_FROZEN) which in turn will lead to execution of
+   inappropriate code by the callbacks registered for such CPU hotplug events.
+
+2. If a regular CPU hotplug stress test happens to race with the freezer due
+   to a suspend operation in progress at the same time, then we could hit the
+   situation described below:
+
+    * A regular cpu online operation continues its journey from userspace
+      into the kernel, since the freezing has not yet begun.
+    * Then freezer gets to work and freezes userspace.
+    * If cpu online has not yet completed the microcode update stuff by now,
+      it will now start waiting on the frozen userspace in the
+      TASK_UNINTERRUPTIBLE state, in order to get the microcode image.
+    * Now the freezer continues and tries to freeze the remaining tasks. But
+      due to this wait mentioned above, the freezer won't be able to freeze
+      the cpu online hotplug task and hence freezing of tasks fails.
+
+   As a result of this task freezing failure, the suspend operation gets
+   aborted.
diff -druNp linux-libre-3.1-gnu1/Documentation/power/userland-swsusp.txt linux-libre-3.2-gnu1/Documentation/power/userland-swsusp.txt
--- linux-libre-3.1-gnu1/Documentation/power/userland-swsusp.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/power/userland-swsusp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,8 @@ SNAPSHOT_SET_SWAP_AREA - set the resume
 	resume_swap_area, as defined in kernel/power/suspend_ioctls.h,
 	containing the resume device specification and the offset); for swap
 	partitions the offset is always 0, but it is different from zero for
-	swap files (see Documentation/swsusp-and-swap-files.txt for details).
+	swap files (see Documentation/power/swsusp-and-swap-files.txt for
+	details).
 
 SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support,
 	depending on the argument value (enable, if the argument is nonzero)
diff -druNp linux-libre-3.1-gnu1/Documentation/rapidio/rapidio.txt linux-libre-3.2-gnu1/Documentation/rapidio/rapidio.txt
--- linux-libre-3.1-gnu1/Documentation/rapidio/rapidio.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/rapidio/rapidio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -144,7 +144,7 @@ and the default device ID in order to ac
 
 After the host has completed enumeration of the entire network it releases
 devices by clearing device ID locks (calls rio_clear_locks()). For each endpoint
-in the system, it sets the Master Enable bit in the Port General Control CSR
+in the system, it sets the Discovered bit in the Port General Control CSR
 to indicate that enumeration is completed and agents are allowed to execute
 passive discovery of the network.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/rapidio/tsi721.txt linux-libre-3.2-gnu1/Documentation/rapidio/tsi721.txt
--- linux-libre-3.1-gnu1/Documentation/rapidio/tsi721.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/rapidio/tsi721.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+RapidIO subsystem mport driver for IDT Tsi721 PCI Express-to-SRIO bridge.
+=========================================================================
+
+I. Overview
+
+This driver implements all currently defined RapidIO mport callback functions.
+It supports maintenance read and write operations, inbound and outbound RapidIO
+doorbells, inbound maintenance port-writes and RapidIO messaging.
+
+To generate SRIO maintenance transactions this driver uses one of Tsi721 DMA
+channels. This mechanism provides access to larger range of hop counts and
+destination IDs without need for changes in outbound window translation.
+
+RapidIO messaging support uses dedicated messaging channels for each mailbox.
+For inbound messages this driver uses destination ID matching to forward messages
+into the corresponding message queue. Messaging callbacks are implemented to be
+fully compatible with RIONET driver (Ethernet over RapidIO messaging services).
+
+II. Known problems
+
+  None.
+
+III. To do
+
+ Add DMA data transfers (non-messaging).
+ Add inbound region (SRIO-to-PCIe) mapping.
+
+IV. Version History
+
+  1.0.0 - Initial driver release.
+
+V.  License
+-----------------------------------------------
+
+  Copyright(c) 2011 Integrated Device Technology, Inc. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the Free
+  Software Foundation; either version 2 of the License, or (at your option)
+  any later version.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
diff -druNp linux-libre-3.1-gnu1/Documentation/RCU/lockdep-splat.txt linux-libre-3.2-gnu1/Documentation/RCU/lockdep-splat.txt
--- linux-libre-3.1-gnu1/Documentation/RCU/lockdep-splat.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/RCU/lockdep-splat.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,110 @@
+Lockdep-RCU was added to the Linux kernel in early 2010
+(http://lwn.net/Articles/371986/).  This facility checks for some common
+misuses of the RCU API, most notably using one of the rcu_dereference()
+family to access an RCU-protected pointer without the proper protection.
+When such misuse is detected, an lockdep-RCU splat is emitted.
+
+The usual cause of a lockdep-RCU slat is someone accessing an
+RCU-protected data structure without either (1) being in the right kind of
+RCU read-side critical section or (2) holding the right update-side lock.
+This problem can therefore be serious: it might result in random memory
+overwriting or worse.  There can of course be false positives, this
+being the real world and all that.
+
+So let's look at an example RCU lockdep splat from 3.0-rc5, one that
+has long since been fixed:
+
+===============================
+[ INFO: suspicious RCU usage. ]
+-------------------------------
+block/cfq-iosched.c:2776 suspicious rcu_dereference_protected() usage!
+
+other info that might help us debug this:
+
+
+rcu_scheduler_active = 1, debug_locks = 0
+3 locks held by scsi_scan_6/1552:
+ #0:  (&shost->scan_mutex){+.+.+.}, at: [<ffffffff8145efca>]
+scsi_scan_host_selected+0x5a/0x150
+ #1:  (&eq->sysfs_lock){+.+...}, at: [<ffffffff812a5032>]
+elevator_exit+0x22/0x60
+ #2:  (&(&q->__queue_lock)->rlock){-.-...}, at: [<ffffffff812b6233>]
+cfq_exit_queue+0x43/0x190
+
+stack backtrace:
+Pid: 1552, comm: scsi_scan_6 Not tainted 3.0.0-rc5 #17
+Call Trace:
+ [<ffffffff810abb9b>] lockdep_rcu_dereference+0xbb/0xc0
+ [<ffffffff812b6139>] __cfq_exit_single_io_context+0xe9/0x120
+ [<ffffffff812b626c>] cfq_exit_queue+0x7c/0x190
+ [<ffffffff812a5046>] elevator_exit+0x36/0x60
+ [<ffffffff812a802a>] blk_cleanup_queue+0x4a/0x60
+ [<ffffffff8145cc09>] scsi_free_queue+0x9/0x10
+ [<ffffffff81460944>] __scsi_remove_device+0x84/0xd0
+ [<ffffffff8145dca3>] scsi_probe_and_add_lun+0x353/0xb10
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff817d98ed>] ? _raw_spin_unlock_irqrestore+0x3d/0x80
+ [<ffffffff8145e722>] __scsi_scan_target+0x112/0x680
+ [<ffffffff812c690d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff812bcc60>] ? kobject_del+0x40/0x40
+ [<ffffffff8145ed16>] scsi_scan_channel+0x86/0xb0
+ [<ffffffff8145f0b0>] scsi_scan_host_selected+0x140/0x150
+ [<ffffffff8145f149>] do_scsi_scan_host+0x89/0x90
+ [<ffffffff8145f170>] do_scan_async+0x20/0x160
+ [<ffffffff8145f150>] ? do_scsi_scan_host+0x90/0x90
+ [<ffffffff810975b6>] kthread+0xa6/0xb0
+ [<ffffffff817db154>] kernel_thread_helper+0x4/0x10
+ [<ffffffff81066430>] ? finish_task_switch+0x80/0x110
+ [<ffffffff817d9c04>] ? retint_restore_args+0xe/0xe
+ [<ffffffff81097510>] ? __init_kthread_worker+0x70/0x70
+ [<ffffffff817db150>] ? gs_change+0xb/0xb
+
+Line 2776 of block/cfq-iosched.c in v3.0-rc5 is as follows:
+
+	if (rcu_dereference(ioc->ioc_data) == cic) {
+
+This form says that it must be in a plain vanilla RCU read-side critical
+section, but the "other info" list above shows that this is not the
+case.  Instead, we hold three locks, one of which might be RCU related.
+And maybe that lock really does protect this reference.  If so, the fix
+is to inform RCU, perhaps by changing __cfq_exit_single_io_context() to
+take the struct request_queue "q" from cfq_exit_queue() as an argument,
+which would permit us to invoke rcu_dereference_protected as follows:
+
+	if (rcu_dereference_protected(ioc->ioc_data,
+				      lockdep_is_held(&q->queue_lock)) == cic) {
+
+With this change, there would be no lockdep-RCU splat emitted if this
+code was invoked either from within an RCU read-side critical section
+or with the ->queue_lock held.  In particular, this would have suppressed
+the above lockdep-RCU splat because ->queue_lock is held (see #2 in the
+list above).
+
+On the other hand, perhaps we really do need an RCU read-side critical
+section.  In this case, the critical section must span the use of the
+return value from rcu_dereference(), or at least until there is some
+reference count incremented or some such.  One way to handle this is to
+add rcu_read_lock() and rcu_read_unlock() as follows:
+
+	rcu_read_lock();
+	if (rcu_dereference(ioc->ioc_data) == cic) {
+		spin_lock(&ioc->lock);
+		rcu_assign_pointer(ioc->ioc_data, NULL);
+		spin_unlock(&ioc->lock);
+	}
+	rcu_read_unlock();
+
+With this change, the rcu_dereference() is always within an RCU
+read-side critical section, which again would have suppressed the
+above lockdep-RCU splat.
+
+But in this particular case, we don't actually deference the pointer
+returned from rcu_dereference().  Instead, that pointer is just compared
+to the cic pointer, which means that the rcu_dereference() can be replaced
+by rcu_access_pointer() as follows:
+
+	if (rcu_access_pointer(ioc->ioc_data) == cic) {
+
+Because it is legal to invoke rcu_access_pointer() without protection,
+this change would also suppress the above lockdep-RCU splat.
diff -druNp linux-libre-3.1-gnu1/Documentation/RCU/lockdep.txt linux-libre-3.2-gnu1/Documentation/RCU/lockdep.txt
--- linux-libre-3.1-gnu1/Documentation/RCU/lockdep.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/RCU/lockdep.txt	2012-01-04 18:55:44.000000000 -0500
@@ -32,9 +32,27 @@ checking of rcu_dereference() primitives
 	srcu_dereference(p, sp):
 		Check for SRCU read-side critical section.
 	rcu_dereference_check(p, c):
-		Use explicit check expression "c".  This is useful in
-		code that is invoked by both readers and updaters.
-	rcu_dereference_raw(p)
+		Use explicit check expression "c" along with
+		rcu_read_lock_held().  This is useful in code that is
+		invoked by both RCU readers and updaters.
+	rcu_dereference_bh_check(p, c):
+		Use explicit check expression "c" along with
+		rcu_read_lock_bh_held().  This is useful in code that
+		is invoked by both RCU-bh readers and updaters.
+	rcu_dereference_sched_check(p, c):
+		Use explicit check expression "c" along with
+		rcu_read_lock_sched_held().  This is useful in code that
+		is invoked by both RCU-sched readers and updaters.
+	srcu_dereference_check(p, c):
+		Use explicit check expression "c" along with
+		srcu_read_lock_held()().  This is useful in code that
+		is invoked by both SRCU readers and updaters.
+	rcu_dereference_index_check(p, c):
+		Use explicit check expression "c", but the caller
+		must supply one of the rcu_read_lock_held() functions.
+		This is useful in code that uses RCU-protected arrays
+		that is invoked by both RCU readers and updaters.
+	rcu_dereference_raw(p):
 		Don't check.  (Use sparingly, if at all.)
 	rcu_dereference_protected(p, c):
 		Use explicit check expression "c", and omit all barriers
@@ -48,13 +66,11 @@ checking of rcu_dereference() primitives
 		value of the pointer itself, for example, against NULL.
 
 The rcu_dereference_check() check expression can be any boolean
-expression, but would normally include one of the rcu_read_lock_held()
-family of functions and a lockdep expression.  However, any boolean
-expression can be used.  For a moderately ornate example, consider
-the following:
+expression, but would normally include a lockdep expression.  However,
+any boolean expression can be used.  For a moderately ornate example,
+consider the following:
 
 	file = rcu_dereference_check(fdt->fd[fd],
-				     rcu_read_lock_held() ||
 				     lockdep_is_held(&files->file_lock) ||
 				     atomic_read(&files->count) == 1);
 
@@ -62,7 +78,7 @@ This expression picks up the pointer "fd
 and, if CONFIG_PROVE_RCU is configured, verifies that this expression
 is used in:
 
-1.	An RCU read-side critical section, or
+1.	An RCU read-side critical section (implicit), or
 2.	with files->file_lock held, or
 3.	on an unshared files_struct.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/RCU/NMI-RCU.txt linux-libre-3.2-gnu1/Documentation/RCU/NMI-RCU.txt
--- linux-libre-3.1-gnu1/Documentation/RCU/NMI-RCU.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/RCU/NMI-RCU.txt	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@ not to return until all ongoing NMI hand
 to free up the handler's data as soon as synchronize_sched() returns.
 
 Important note: for this to work, the architecture in question must
-invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
+invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.
 
 
 Answer to Quick Quiz
diff -druNp linux-libre-3.1-gnu1/Documentation/RCU/torture.txt linux-libre-3.2-gnu1/Documentation/RCU/torture.txt
--- linux-libre-3.1-gnu1/Documentation/RCU/torture.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/RCU/torture.txt	2012-01-04 18:55:44.000000000 -0500
@@ -42,7 +42,7 @@ fqs_holdoff	Holdoff time (in microsecond
 fqs_stutter	Wait time (in seconds) between consecutive bursts
 		of calls to force_quiescent_state().
 
-irqreaders	Says to invoke RCU readers from irq level.  This is currently
+irqreader	Says to invoke RCU readers from irq level.  This is currently
 		done via timers.  Defaults to "1" for variants of RCU that
 		permit this.  (Or, more accurately, variants of RCU that do
 		-not- permit this know to ignore this variable.)
@@ -79,19 +79,68 @@ stutter		The length of time to run the t
 		Specifying "stutter=0" causes the test to run continuously
 		without pausing, which is the old default behavior.
 
+test_boost	Whether or not to test the ability of RCU to do priority
+		boosting.  Defaults to "test_boost=1", which performs
+		RCU priority-inversion testing only if the selected
+		RCU implementation supports priority boosting.  Specifying
+		"test_boost=0" never performs RCU priority-inversion
+		testing.  Specifying "test_boost=2" performs RCU
+		priority-inversion testing even if the selected RCU
+		implementation does not support RCU priority boosting,
+		which can be used to test rcutorture's ability to
+		carry out RCU priority-inversion testing.
+
+test_boost_interval
+		The number of seconds in an RCU priority-inversion test
+		cycle.	Defaults to "test_boost_interval=7".  It is
+		usually wise for this value to be relatively prime to
+		the value selected for "stutter".
+
+test_boost_duration
+		The number of seconds to do RCU priority-inversion testing
+		within any given "test_boost_interval".  Defaults to
+		"test_boost_duration=4".
+
 test_no_idle_hz	Whether or not to test the ability of RCU to operate in
 		a kernel that disables the scheduling-clock interrupt to
 		idle CPUs.  Boolean parameter, "1" to test, "0" otherwise.
 		Defaults to omitting this test.
 
-torture_type	The type of RCU to test: "rcu" for the rcu_read_lock() API,
-		"rcu_sync" for rcu_read_lock() with synchronous reclamation,
-		"rcu_bh" for the rcu_read_lock_bh() API, "rcu_bh_sync" for
-		rcu_read_lock_bh() with synchronous reclamation, "srcu" for
-		the "srcu_read_lock()" API, "sched" for the use of
-		preempt_disable() together with synchronize_sched(),
-		and "sched_expedited" for the use of preempt_disable()
-		with synchronize_sched_expedited().
+torture_type	The type of RCU to test, with string values as follows:
+
+		"rcu":  rcu_read_lock(), rcu_read_unlock() and call_rcu().
+
+		"rcu_sync":  rcu_read_lock(), rcu_read_unlock(), and
+			synchronize_rcu().
+
+		"rcu_expedited": rcu_read_lock(), rcu_read_unlock(), and
+			synchronize_rcu_expedited().
+
+		"rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and
+			call_rcu_bh().
+
+		"rcu_bh_sync": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+			and synchronize_rcu_bh().
+
+		"rcu_bh_expedited": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+			and synchronize_rcu_bh_expedited().
+
+		"srcu": srcu_read_lock(), srcu_read_unlock() and
+			synchronize_srcu().
+
+		"srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
+			synchronize_srcu_expedited().
+
+		"sched": preempt_disable(), preempt_enable(), and
+			call_rcu_sched().
+
+		"sched_sync": preempt_disable(), preempt_enable(), and
+			synchronize_sched().
+
+		"sched_expedited": preempt_disable(), preempt_enable(), and
+			synchronize_sched_expedited().
+
+		Defaults to "rcu".
 
 verbose		Enable debug printk()s.  Default is disabled.
 
@@ -100,12 +149,12 @@ OUTPUT
 
 The statistics output is as follows:
 
-	rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
-	rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
-	rcu-torture: Reader Pipe:  1466408 9747 0 0 0 0 0 0 0 0 0
-	rcu-torture: Reader Batch:  1464477 11678 0 0 0 0 0 0 0 0
-	rcu-torture: Free-Block Circulation:  1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
-	rcu-torture: --- End of test
+	rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
+	rcu-torture: rtc:           (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
+	rcu-torture: Reader Pipe:  727860534 34213 0 0 0 0 0 0 0 0 0
+	rcu-torture: Reader Batch:  727877838 17003 0 0 0 0 0 0 0 0 0
+	rcu-torture: Free-Block Circulation:  155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
+	rcu-torture:--- End of test: SUCCESS: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
 
 The command "dmesg | grep torture:" will extract this information on
 most systems.  On more esoteric configurations, it may be necessary to
@@ -113,26 +162,55 @@ use other commands to access the output
 the RCU torture test.  The printk()s use KERN_ALERT, so they should
 be evident.  ;-)
 
+The first and last lines show the rcutorture module parameters, and the
+last line shows either "SUCCESS" or "FAILURE", based on rcutorture's
+automatic determination as to whether RCU operated correctly.
+
 The entries are as follows:
 
 o	"rtc": The hexadecimal address of the structure currently visible
 	to readers.
 
-o	"ver": The number of times since boot that the rcutw writer task
+o	"ver": The number of times since boot that the RCU writer task
 	has changed the structure visible to readers.
 
 o	"tfle": If non-zero, indicates that the "torture freelist"
-	containing structure to be placed into the "rtc" area is empty.
+	containing structures to be placed into the "rtc" area is empty.
 	This condition is important, since it can fool you into thinking
 	that RCU is working when it is not.  :-/
 
 o	"rta": Number of structures allocated from the torture freelist.
 
 o	"rtaf": Number of allocations from the torture freelist that have
-	failed due to the list being empty.
+	failed due to the list being empty.  It is not unusual for this
+	to be non-zero, but it is bad for it to be a large fraction of
+	the value indicated by "rta".
 
 o	"rtf": Number of frees into the torture freelist.
 
+o	"rtmbe": A non-zero value indicates that rcutorture believes that
+	rcu_assign_pointer() and rcu_dereference() are not working
+	correctly.  This value should be zero.
+
+o	"rtbke": rcutorture was unable to create the real-time kthreads
+	used to force RCU priority inversion.  This value should be zero.
+
+o	"rtbre": Although rcutorture successfully created the kthreads
+	used to force RCU priority inversion, it was unable to set them
+	to the real-time priority level of 1.  This value should be zero.
+
+o	"rtbf": The number of times that RCU priority boosting failed
+	to resolve RCU priority inversion.
+
+o	"rtb": The number of times that rcutorture attempted to force
+	an RCU priority inversion condition.  If you are testing RCU
+	priority boosting via the "test_boost" module parameter, this
+	value should be non-zero.
+
+o	"nt": The number of times rcutorture ran RCU read-side code from
+	within a timer handler.  This value should be non-zero only
+	if you specified the "irqreader" module parameter.
+
 o	"Reader Pipe": Histogram of "ages" of structures seen by readers.
 	If any entries past the first two are non-zero, RCU is broken.
 	And rcutorture prints the error flag string "!!!" to make sure
@@ -162,26 +240,15 @@ o	"Free-Block Circulation": Shows the nu
 	somehow gets incremented farther than it should.
 
 Different implementations of RCU can provide implementation-specific
-additional information.  For example, SRCU provides the following:
+additional information.  For example, SRCU provides the following
+additional line:
 
-	srcu-torture: rtc: f8cf46a8 ver: 355 tfle: 0 rta: 356 rtaf: 0 rtf: 346 rtmbe: 0
-	srcu-torture: Reader Pipe:  559738 939 0 0 0 0 0 0 0 0 0
-	srcu-torture: Reader Batch:  560434 243 0 0 0 0 0 0 0 0
-	srcu-torture: Free-Block Circulation:  355 354 353 352 351 350 349 348 347 346 0
 	srcu-torture: per-CPU(idx=1): 0(0,1) 1(0,1) 2(0,0) 3(0,1)
 
-The first four lines are similar to those for RCU.  The last line shows
-the per-CPU counter state.  The numbers in parentheses are the values
-of the "old" and "current" counters for the corresponding CPU.  The
-"idx" value maps the "old" and "current" values to the underlying array,
-and is useful for debugging.
-
-Similarly, sched_expedited RCU provides the following:
-
-	sched_expedited-torture: rtc: d0000000016c1880 ver: 1090796 tfle: 0 rta: 1090796 rtaf: 0 rtf: 1090787 rtmbe: 0 nt: 27713319
-	sched_expedited-torture: Reader Pipe:  12660320201 95875 0 0 0 0 0 0 0 0 0
-	sched_expedited-torture: Reader Batch:  12660424885 0 0 0 0 0 0 0 0 0 0
-	sched_expedited-torture: Free-Block Circulation:  1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0
+This line shows the per-CPU counter state.  The numbers in parentheses are
+the values of the "old" and "current" counters for the corresponding CPU.
+The "idx" value maps the "old" and "current" values to the underlying
+array, and is useful for debugging.
 
 
 USAGE
diff -druNp linux-libre-3.1-gnu1/Documentation/RCU/trace.txt linux-libre-3.2-gnu1/Documentation/RCU/trace.txt
--- linux-libre-3.1-gnu1/Documentation/RCU/trace.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/RCU/trace.txt	2012-01-04 18:55:44.000000000 -0500
@@ -33,23 +33,23 @@ rcu/rcuboost:
 The output of "cat rcu/rcudata" looks as follows:
 
 rcu_sched:
-  0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
-  1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
-  2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
-  3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
-  4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
-  5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
-  6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
-  7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
+  0 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
+  1 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
+  2 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
+  3 c=20942 g=20943 pq=1 pgp=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
+  4 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
+  5 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
+  6 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
+  7 c=20897 g=20897 pq=1 pgp=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
 rcu_bh:
-  0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
-  1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
-  2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
-  3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
-  4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
-  5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
-  6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
-  7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
+  0 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
+  1 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
+  2 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
+  3 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
+  4 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
+  5 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
+  6 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
+  7 c=1474 g=1474 pq=1 pgp=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
 
 The first section lists the rcu_data structures for rcu_sched, the second
 for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -84,7 +84,7 @@ o	"pq" indicates that this CPU has passe
 	CPU has not yet reported that fact, (2) some other CPU has not
 	yet reported for this grace period, or (3) both.
 
-o	"pqc" indicates which grace period the last-observed quiescent
+o	"pgp" indicates which grace period the last-observed quiescent
 	state for this CPU corresponds to.  This is important for handling
 	the race between CPU 0 reporting an extended dynticks-idle
 	quiescent state for CPU 1 and CPU 1 suddenly waking up and
@@ -184,10 +184,14 @@ o	"kt" is the per-CPU kernel-thread stat
 	The number after the final slash is the CPU that the kthread
 	is actually running on.
 
+	This field is displayed only for CONFIG_RCU_BOOST kernels.
+
 o	"ktl" is the low-order 16 bits (in hexadecimal) of the count of
 	the number of times that this CPU's per-CPU kthread has gone
 	through its loop servicing invoke_rcu_cpu_kthread() requests.
 
+	This field is displayed only for CONFIG_RCU_BOOST kernels.
+
 o	"b" is the batch limit for this CPU.  If more than this number
 	of RCU callbacks is ready to invoke, then the remainder will
 	be deferred.
diff -druNp linux-libre-3.1-gnu1/Documentation/rfkill.txt linux-libre-3.2-gnu1/Documentation/rfkill.txt
--- linux-libre-3.1-gnu1/Documentation/rfkill.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/rfkill.txt	2012-01-04 18:55:44.000000000 -0500
@@ -117,5 +117,4 @@ The contents of these variables correspo
 "type" sysfs files explained above.
 
 
-For further details consult Documentation/ABI/stable/dev-rfkill and
-Documentation/ABI/stable/sysfs-class-rfkill.
+For further details consult Documentation/ABI/stable/sysfs-class-rfkill.
diff -druNp linux-libre-3.1-gnu1/Documentation/scheduler/sched-bwc.txt linux-libre-3.2-gnu1/Documentation/scheduler/sched-bwc.txt
--- linux-libre-3.1-gnu1/Documentation/scheduler/sched-bwc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/scheduler/sched-bwc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,122 @@
+CFS Bandwidth Control
+=====================
+
+[ This document only discusses CPU bandwidth control for SCHED_NORMAL.
+  The SCHED_RT case is covered in Documentation/scheduler/sched-rt-group.txt ]
+
+CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the
+specification of the maximum CPU bandwidth available to a group or hierarchy.
+
+The bandwidth allowed for a group is specified using a quota and period. Within
+each given "period" (microseconds), a group is allowed to consume only up to
+"quota" microseconds of CPU time.  When the CPU bandwidth consumption of a
+group exceeds this limit (for that period), the tasks belonging to its
+hierarchy will be throttled and are not allowed to run again until the next
+period.
+
+A group's unused runtime is globally tracked, being refreshed with quota units
+above at each period boundary.  As threads consume this bandwidth it is
+transferred to cpu-local "silos" on a demand basis.  The amount transferred
+within each of these updates is tunable and described as the "slice".
+
+Management
+----------
+Quota and period are managed within the cpu subsystem via cgroupfs.
+
+cpu.cfs_quota_us: the total available run-time within a period (in microseconds)
+cpu.cfs_period_us: the length of a period (in microseconds)
+cpu.stat: exports throttling statistics [explained further below]
+
+The default values are:
+	cpu.cfs_period_us=100ms
+	cpu.cfs_quota=-1
+
+A value of -1 for cpu.cfs_quota_us indicates that the group does not have any
+bandwidth restriction in place, such a group is described as an unconstrained
+bandwidth group.  This represents the traditional work-conserving behavior for
+CFS.
+
+Writing any (valid) positive value(s) will enact the specified bandwidth limit.
+The minimum quota allowed for the quota or period is 1ms.  There is also an
+upper bound on the period length of 1s.  Additional restrictions exist when
+bandwidth limits are used in a hierarchical fashion, these are explained in
+more detail below.
+
+Writing any negative value to cpu.cfs_quota_us will remove the bandwidth limit
+and return the group to an unconstrained state once more.
+
+Any updates to a group's bandwidth specification will result in it becoming
+unthrottled if it is in a constrained state.
+
+System wide settings
+--------------------
+For efficiency run-time is transferred between the global pool and CPU local
+"silos" in a batch fashion.  This greatly reduces global accounting pressure
+on large systems.  The amount transferred each time such an update is required
+is described as the "slice".
+
+This is tunable via procfs:
+	/proc/sys/kernel/sched_cfs_bandwidth_slice_us (default=5ms)
+
+Larger slice values will reduce transfer overheads, while smaller values allow
+for more fine-grained consumption.
+
+Statistics
+----------
+A group's bandwidth statistics are exported via 3 fields in cpu.stat.
+
+cpu.stat:
+- nr_periods: Number of enforcement intervals that have elapsed.
+- nr_throttled: Number of times the group has been throttled/limited.
+- throttled_time: The total time duration (in nanoseconds) for which entities
+  of the group have been throttled.
+
+This interface is read-only.
+
+Hierarchical considerations
+---------------------------
+The interface enforces that an individual entity's bandwidth is always
+attainable, that is: max(c_i) <= C. However, over-subscription in the
+aggregate case is explicitly allowed to enable work-conserving semantics
+within a hierarchy.
+  e.g. \Sum (c_i) may exceed C
+[ Where C is the parent's bandwidth, and c_i its children ]
+
+
+There are two ways in which a group may become throttled:
+	a. it fully consumes its own quota within a period
+	b. a parent's quota is fully consumed within its period
+
+In case b) above, even though the child may have runtime remaining it will not
+be allowed to until the parent's runtime is refreshed.
+
+Examples
+--------
+1. Limit a group to 1 CPU worth of runtime.
+
+	If period is 250ms and quota is also 250ms, the group will get
+	1 CPU worth of runtime every 250ms.
+
+	# echo 250000 > cpu.cfs_quota_us /* quota = 250ms */
+	# echo 250000 > cpu.cfs_period_us /* period = 250ms */
+
+2. Limit a group to 2 CPUs worth of runtime on a multi-CPU machine.
+
+	With 500ms period and 1000ms quota, the group can get 2 CPUs worth of
+	runtime every 500ms.
+
+	# echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */
+	# echo 500000 > cpu.cfs_period_us /* period = 500ms */
+
+	The larger period here allows for increased burst capacity.
+
+3. Limit a group to 20% of 1 CPU.
+
+	With 50ms period, 10ms quota will be equivalent to 20% of 1 CPU.
+
+	# echo 10000 > cpu.cfs_quota_us /* quota = 10ms */
+	# echo 50000 > cpu.cfs_period_us /* period = 50ms */
+
+	By using a small period here we are ensuring a consistent latency
+	response at the expense of burst capacity.
+
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/00-INDEX linux-libre-3.2-gnu1/Documentation/scsi/00-INDEX
--- linux-libre-3.1-gnu1/Documentation/scsi/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/scsi/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@ LICENSE.FlashPoint
 	- Licence of the Flashpoint driver
 LICENSE.qla2xxx
 	- License for QLogic Linux Fibre Channel HBA Driver firmware.
+LICENSE.qla4xxx
+	- License for QLogic Linux iSCSI HBA Driver.
 Mylex.txt
 	- info on driver for Mylex adapters
 NinjaSCSI.txt
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/aic7xxx_old.txt linux-libre-3.2-gnu1/Documentation/scsi/aic7xxx_old.txt
--- linux-libre-3.1-gnu1/Documentation/scsi/aic7xxx_old.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/scsi/aic7xxx_old.txt	2012-01-04 18:55:44.000000000 -0500
@@ -444,7 +444,7 @@ linux-1.1.x and fairly stable since linu
   Kernel Compile options
   ------------------------------
     The various kernel compile time options for this driver are now fairly
-    well documented in the file Documentation/Configure.help.  In order to
+    well documented in the file drivers/scsi/Kconfig.  In order to
     see this documentation, you need to use one of the advanced configuration
     programs (menuconfig and xconfig).  If you are using the "make menuconfig"
     method of configuring your kernel, then you would simply highlight the
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/bnx2fc.txt linux-libre-3.2-gnu1/Documentation/scsi/bnx2fc.txt
--- linux-libre-3.1-gnu1/Documentation/scsi/bnx2fc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/scsi/bnx2fc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,75 @@
+Operating FCoE using bnx2fc
+===========================
+Broadcom FCoE offload through bnx2fc is full stateful hardware offload that
+cooperates with all interfaces provided by the Linux ecosystem for FC/FCoE and
+SCSI controllers.  As such, FCoE functionality, once enabled is largely
+transparent. Devices discovered on the SAN will be registered and unregistered
+automatically with the upper storage layers.
+
+Despite the fact that the Broadcom's FCoE offload is fully offloaded, it does
+depend on the state of the network interfaces to operate. As such, the network
+interface (e.g. eth0) associated with the FCoE offload initiator must be 'up'.
+It is recommended that the network interfaces be configured to be brought up
+automatically at boot time.
+
+Furthermore, the Broadcom FCoE offload solution creates VLAN interfaces to
+support the VLANs that have been discovered for FCoE operation (e.g.
+eth0.1001-fcoe).  Do not delete or disable these interfaces or FCoE operation
+will be disrupted.
+
+Driver Usage Model:
+===================
+
+1. Ensure that fcoe-utils package is installed.
+
+2. Configure the interfaces on which bnx2fc driver has to operate on.
+Here are the steps to configure:
+	a. cd /etc/fcoe
+	b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5.
+	c. Repeat this for all the interfaces where FCoE has to be enabled.
+	d. Edit all the cfg-eth files to set "no" for DCB_REQUIRED** field, and
+	   "yes" for AUTO_VLAN.
+	e. Other configuration parameters should be left as default
+
+3. Ensure that "bnx2fc" is in SUPPORTED_DRIVERS list in /etc/fcoe/config.
+
+4. Start fcoe service. (service fcoe start). If Broadcom devices are present in
+the system, bnx2fc driver would automatically claim the interfaces, starts vlan
+discovery and log into the targets.
+
+5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed
+the interface.
+Eg:
+[root@bh2 ~]# fcoeadm -i
+    Description:      NetXtreme II BCM57712 10 Gigabit Ethernet
+    Revision:         01
+    Manufacturer:     Broadcom Corporation
+    Serial Number:    0010186FD558
+    Driver:           bnx2x 1.70.00-0
+    Number of Ports:  2
+
+        Symbolic Name:     bnx2fc v1.0.5 over eth5.4
+        OS Device Name:    host11
+        Node Name:         0x10000010186FD559
+        Port Name:         0x20000010186FD559
+        FabricName:        0x2001000DECB3B681
+        Speed:             10 Gbit
+        Supported Speed:   10 Gbit
+        MaxFrameSize:      2048
+        FC-ID (Port ID):   0x0F0377
+        State:             Online
+
+6. Verify the vlan discovery is performed by running ifconfig and notice
+<INTERFACE>.<VLAN>-fcoe interfaces are automatically created.
+
+Refer to fcoeadm manpage for more information on fcoeadm operations to
+create/destroy interfaces or to display lun/target information.
+
+NOTE:
+====
+** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one
+LLDP client is allowed per interface. For proper operation all host software
+based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a
+given interface, run the following command:
+
+lldptool set-lldp -i <interface_name> adminStatus=disabled
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/ChangeLog.megaraid_sas linux-libre-3.2-gnu1/Documentation/scsi/ChangeLog.megaraid_sas
--- linux-libre-3.1-gnu1/Documentation/scsi/ChangeLog.megaraid_sas	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/scsi/ChangeLog.megaraid_sas	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,18 @@
+Release Date    : Wed. Oct 5, 2011 17:00:00 PST 2010 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford
+Current Version : 00.00.06.12-rc1
+Old Version     : 00.00.05.40-rc1
+    1. Continue booting immediately if FW in FAULT at driver load time.
+    2. Increase default cmds per lun to 256.
+    3. Fix mismatch in megasas_reset_fusion() mutex lock-unlock.
+    4. Remove some un-necessary code.
+    5. Clear state change interrupts for Fusion/Invader.
+    6. Clear FUSION_IN_RESET before enabling interrupts.
+    7. Add support for MegaRAID 9360/9380 12GB/s controllers.
+    8. Add multiple MSI-X vector/multiple reply queue support.
+    9. Add driver workaround for PERC5/1068 kdump kernel panic.
+-------------------------------------------------------------------------------
 Release Date    : Tue. Jul 26, 2011 17:00:00 PST 2010 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Adam Radford
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/LICENSE.qla4xxx linux-libre-3.2-gnu1/Documentation/scsi/LICENSE.qla4xxx
--- linux-libre-3.1-gnu1/Documentation/scsi/LICENSE.qla4xxx	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/scsi/LICENSE.qla4xxx	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,310 @@
+Copyright (c) 2003-2011 QLogic Corporation
+QLogic Linux iSCSI HBA Driver
+
+This program includes a device driver for Linux 3.x.
+You may modify and redistribute the device driver code under the
+GNU General Public License (a copy of which is attached hereto as
+Exhibit A) published by the Free Software Foundation (version 2).
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
+
+EXHIBIT A
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff -druNp linux-libre-3.1-gnu1/Documentation/scsi/scsi_mid_low_api.txt linux-libre-3.2-gnu1/Documentation/scsi/scsi_mid_low_api.txt
--- linux-libre-3.1-gnu1/Documentation/scsi/scsi_mid_low_api.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/scsi/scsi_mid_low_api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -55,11 +55,6 @@ or in the same directory as the C source
 about the USB mass storage driver see the 
 /usr/src/linux/drivers/usb/storage directory.
 
-The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
-refers to this file. With the appropriate DocBook tool-set, this permits
-users to generate html, ps and pdf renderings of information within this
-file (e.g. the interface functions).
-
 Driver structure
 ================
 Traditionally an LLD for the SCSI subsystem has been at least two files in
diff -druNp linux-libre-3.1-gnu1/Documentation/security/keys-trusted-encrypted.txt linux-libre-3.2-gnu1/Documentation/security/keys-trusted-encrypted.txt
--- linux-libre-3.1-gnu1/Documentation/security/keys-trusted-encrypted.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/security/keys-trusted-encrypted.txt	2012-01-04 18:55:44.000000000 -0500
@@ -156,4 +156,5 @@ Load an encrypted key "evm" from saved b
 Other uses for trusted and encrypted keys, such as for disk and file encryption
 are anticipated.  In particular the new format 'ecryptfs' has been defined in
 in order to use encrypted keys to mount an eCryptfs filesystem.  More details
-about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
+about the usage can be found in the file
+'Documentation/security/keys-ecryptfs.txt'.
diff -druNp linux-libre-3.1-gnu1/Documentation/serial/computone.txt linux-libre-3.2-gnu1/Documentation/serial/computone.txt
--- linux-libre-3.1-gnu1/Documentation/serial/computone.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/serial/computone.txt	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@ Version: 1.2.14
 Date: 11/01/2001
 Historical Author: Andrew Manison <amanison@america.net>
 Primary Author: Doug McNash
-Support: support@computone.com
-Fixes and Updates: Mike Warfield <mhw@wittsend.com>
 
 This file assumes that you are using the Computone drivers which are
 integrated into the kernel sources.  For updating the drivers or installing
diff -druNp linux-libre-3.1-gnu1/Documentation/serial/serial-rs485.txt linux-libre-3.2-gnu1/Documentation/serial/serial-rs485.txt
--- linux-libre-3.1-gnu1/Documentation/serial/serial-rs485.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/serial/serial-rs485.txt	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,10 @@
    RS485 communications. This data structure is used to set and configure RS485
    parameters in the platform data and in ioctls.
 
+   The device tree can also provide RS485 boot time parameters (see [2]
+   for bindings). The driver is in charge of filling this data structure from
+   the values given by the device tree.
+
    Any driver for devices capable of working both as RS232 and RS485 should
    provide at least the following ioctls:
 
@@ -93,17 +97,28 @@
 
 	struct serial_rs485 rs485conf;
 
-	/* Set RS485 mode: */
+	/* Enable RS485 mode: */
 	rs485conf.flags |= SER_RS485_ENABLED;
 
+	/* Set logical level for RTS pin equal to 1 when sending: */
+	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+	/* or, set logical level for RTS pin equal to 0 when sending: */
+	rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
+
+	/* Set logical level for RTS pin equal to 1 after sending: */
+	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
+	/* or, set logical level for RTS pin equal to 0 after sending: */
+	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
+
 	/* Set rts delay before send, if needed: */
-	rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;
 	rs485conf.delay_rts_before_send = ...;
 
 	/* Set rts delay after send, if needed: */
-	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
 	rs485conf.delay_rts_after_send = ...;
 
+	/* Set this flag if you want to receive data even whilst sending data */
+	rs485conf.flags |= SER_RS485_RX_DURING_TX;
+
 	if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
 		/* Error handling. See errno. */
 	}
@@ -118,3 +133,4 @@
 5. REFERENCES
 
  [1]	include/linux/serial.h
+ [2]	Documentation/devicetree/bindings/serial/rs485.txt
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-3.2-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-3.1-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt	2013-05-02 01:48:41.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt	2013-05-01 23:53:15.000000000 -0400
@@ -886,6 +886,12 @@ Prior to version 0.9.0rc4 options had a
 		disable)
     power_save_controller - Reset HD-audio controller in power-saving mode
 		(default = on)
+    align_buffer_size - Force rounding of buffer/period sizes to multiples
+    		      of 128 bytes. This is more efficient in terms of memory
+		      access but isn't required by the HDA spec and prevents
+		      users from specifying exact period/buffer sizes.
+		      (default = on)
+    snoop	- Enable/disable snooping (default = on)
 
     This module supports multiple cards and autoprobe.
     
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio-Controls.txt linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio-Controls.txt
--- linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio-Controls.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio-Controls.txt	2012-01-04 18:55:44.000000000 -0500
@@ -98,3 +98,19 @@ Conexant codecs
 
 * Auto-Mute Mode
   See Reatek codecs.
+
+
+Analog codecs
+--------------
+
+* Channel Mode
+  This is an enum control to change the surround-channel setup,
+  appears only when the surround channels are available.
+  It gives the number of channels to be used, "2ch", "4ch" and "6ch".
+  According to the configuration, this also controls the
+  jack-retasking of multi-I/O jacks.
+
+* Independent HP
+  When this enum control is enabled, the headphone output is routed
+  from an individual stream (the third PCM such as hw:0,2) instead of
+  the primary stream.
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt	2012-01-04 18:55:44.000000000 -0500
@@ -29,9 +29,6 @@ ALC880
 
 ALC260
 ======
-  hp		HP machines
-  hp-3013	HP machines (3013-variant)
-  hp-dc7600	HP DC7600
   fujitsu	Fujitsu S7020
   acer		Acer TravelMate
   will		Will laptops (PB V7900)
@@ -46,15 +43,10 @@ ALC260
 ALC262
 ======
   fujitsu	Fujitsu Laptop
-  hp-bpc	HP xw4400/6400/8400/9400 laptops
-  hp-bpc-d7000	HP BPC D7000
-  hp-tc-t5735	HP Thin Client T5735
-  hp-rp5700	HP RP5700
   benq		Benq ED8
   benq-t31	Benq T31
   hippo		Hippo (ATI) with jack detection, Sony UX-90s
   hippo_1	Hippo (Benq) with jack detection
-  sony-assamd	Sony ASSAMD
   toshiba-s06	Toshiba S06
   toshiba-rx1	Toshiba RX1
   tyan		Tyan Thunder n6650W (S2915-E)
@@ -66,43 +58,15 @@ ALC262
 
 ALC267/268
 ==========
-  quanta-il1	Quanta IL1 mini-notebook
-  3stack	3-stack model
-  toshiba	Toshiba A205
-  acer		Acer laptops
-  acer-dmic	Acer laptops with digital-mic
-  acer-aspire	Acer Aspire One
-  dell		Dell OEM laptops (Vostro 1200)
-  zepto		Zepto laptops
-  test		for testing/debugging purpose, almost all controls can
-		adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC269
 ======
-  basic		Basic preset
-  quanta	Quanta FL1
   laptop-amic	Laptops with analog-mic input
   laptop-dmic	Laptops with digital-mic input
-  fujitsu	FSC Amilo
-  lifebook	Fujitsu Lifebook S6420
-  auto		auto-config reading BIOS (default)
 
 ALC662/663/272
 ==============
-  3stack-dig	3-stack (2-channel) with SPDIF
-  3stack-6ch	 3-stack (6-channel)
-  3stack-6ch-dig 3-stack (6-channel) with SPDIF
-  5stack-dig	 5-stack with SPDIF
-  lenovo-101e	 Lenovo laptop
-  eeepc-p701	ASUS Eeepc P701
-  eeepc-ep20	ASUS Eeepc EP20
-  ecs		ECS/Foxconn mobo
-  m51va		ASUS M51VA
-  g71v		ASUS G71V
-  h13		ASUS H13
-  g50v		ASUS G50V
   asus-mode1	ASUS
   asus-mode2	ASUS
   asus-mode3	ASUS
@@ -111,15 +75,10 @@ ALC662/663/272
   asus-mode6	ASUS
   asus-mode7	ASUS
   asus-mode8	ASUS
-  dell		Dell with ALC272
-  dell-zm1	Dell ZM1 with ALC272
-  samsung-nc10	Samsung NC10 mini notebook
-  auto		auto-config reading BIOS (default)
 
 ALC680
 ======
-  base		Base model (ASUS NX90)
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC882/883/885/888/889
 ======================
@@ -175,28 +134,11 @@ ALC882/883/885/888/889
 
 ALC861/660
 ==========
-  3stack	3-jack
-  3stack-dig	3-jack with SPDIF I/O
-  6stack-dig	6-jack with SPDIF I/O
-  3stack-660	3-jack (for ALC660)
-  uniwill-m31	Uniwill M31 laptop
-  toshiba	Toshiba laptop support
-  asus		Asus laptop support
-  asus-laptop	ASUS F2/F3 laptops
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC861VD/660VD
 ==============
-  3stack	3-jack
-  3stack-dig	3-jack with SPDIF OUT
-  6stack-dig	6-jack with SPDIF OUT
-  3stack-660	3-jack (for ALC660VD)
-  3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
-  lenovo	Lenovo 3000 C200
-  dallas	Dallas laptops
-  hp		HP TX1000
-  asus-v1s	ASUS V1Sn
-  auto		auto-config reading BIOS (default)
+  N/A
 
 CMI9880
 =======
@@ -289,7 +231,6 @@ Conexant 5051
   hp-dv6736	HP dv6736
   hp-f700	HP Compaq Presario F700
   ideapad	Lenovo IdeaPad laptop
-  lenovo-x200	Lenovo X200 laptop
   toshiba	Toshiba Satellite M300
 
 Conexant 5066
@@ -408,6 +349,7 @@ STAC92HD83*
   ref		Reference board
   mic-ref	Reference board with power management for ports
   dell-s14	Dell laptop
+  dell-vostro-3500	Dell Vostro 3500 laptop
   hp		HP laptops with (inverted) mute-LED
   hp-dv7-4000	HP dv-7 4000
   auto		BIOS setup (default)
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio.txt linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio.txt
--- linux-libre-3.1-gnu1/Documentation/sound/alsa/HD-Audio.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/alsa/HD-Audio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -447,7 +447,10 @@ The file needs to have a line `[codec]`.
 three numbers indicating the codec vendor-id (0x12345678 in the
 example), the codec subsystem-id (0xabcd1234) and the address (2) of
 the codec.  The rest patch entries are applied to this specified codec
-until another codec entry is given.
+until another codec entry is given.  Passing 0 or a negative number to
+the first or the second value will make the check of the corresponding
+field be skipped.  It'll be useful for really broken devices that don't
+initialize SSID properly.
 
 The `[model]` line allows to change the model name of the each codec.
 In the example above, it will be changed to model=auto.
@@ -491,7 +494,7 @@ Also, the codec chip name can be rewritt
 The hd-audio driver reads the file via request_firmware().  Thus,
 a patch file has to be located on the appropriate firmware path,
 typically, /lib/firmware.  For example, when you pass the option
-`patch=hda-init.fw`, the file /lib/firmware/hda-init-fw must be
+`patch=hda-init.fw`, the file /lib/firmware/hda-init.fw must be
 present.
 
 The patch module option is specific to each card instance, and you
@@ -524,11 +527,59 @@ power-saving.  See /sys/module/snd_hda_i
 check the current value.  If it's non-zero, the feature is turned on.
 
 
+Tracepoints
+~~~~~~~~~~~
+The hd-audio driver gives a few basic tracepoints.
+`hda:hda_send_cmd` traces each CORB write while `hda:hda_get_response`
+traces the response from RIRB (only when read from the codec driver).
+`hda:hda_bus_reset` traces the bus-reset due to fatal error, etc,
+`hda:hda_unsol_event` traces the unsolicited events, and
+`hda:hda_power_down` and `hda:hda_power_up` trace the power down/up
+via power-saving behavior.
+
+Enabling all tracepoints can be done like
+------------------------------------------------------------------------
+  # echo 1 > /sys/kernel/debug/tracing/events/hda/enable
+------------------------------------------------------------------------
+then after some commands, you can traces from
+/sys/kernel/debug/tracing/trace file.  For example, when you want to
+trace what codec command is sent, enable the tracepoint like:
+------------------------------------------------------------------------
+  # cat /sys/kernel/debug/tracing/trace
+  # tracer: nop
+  #
+  #       TASK-PID    CPU#    TIMESTAMP  FUNCTION
+  #          | |       |          |         |
+         <...>-7807  [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
+         <...>-7807  [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
+         <...>-7807  [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
+         <...>-7807  [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
+         <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
+         <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
+         <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
+         <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
+------------------------------------------------------------------------
+Here `[0:0]` indicates the card number and the codec address, and
+`val` shows the value sent to the codec, respectively.  The value is
+a packed value, and you can decode it via hda-decode-verb program
+included in hda-emu package below.  For example, the value e3a019 is
+to set the left output-amp value to 25.
+------------------------------------------------------------------------
+  % hda-decode-verb 0xe3a019
+  raw value = 0x00e3a019
+  cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
+  raw value: verb = 0x3a0, parm = 0x19
+  verbname = set_amp_gain_mute
+  amp raw val = 0xa019
+  output, left, idx=0, mute=0, val=25
+------------------------------------------------------------------------
+
+
 Development Tree
 ~~~~~~~~~~~~~~~~
 The latest development codes for HD-audio are found on sound git tree:
 
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 
 The master branch or for-next branches can be used as the main
 development branches in general while the HD-audio specific patches
@@ -543,7 +594,7 @@ is, installed via the usual spells: conf
 install(-modules).  See INSTALL in the package.  The snapshot tarballs
 are found at:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/
+- ftp://ftp.suse.com/pub/people/tiwai/snapshot/
 
 
 Sending a Bug Report
@@ -645,7 +696,7 @@ via hda-verb won't change the mixer valu
 
 The hda-verb program is found in the ftp directory:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 Also a git repository is available:
 
@@ -713,7 +764,7 @@ operation, the jack plugging simulation,
 
 The package is found in:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 A git repository is available:
 
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/alsa/soc/machine.txt linux-libre-3.2-gnu1/Documentation/sound/alsa/soc/machine.txt
--- linux-libre-3.1-gnu1/Documentation/sound/alsa/soc/machine.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/alsa/soc/machine.txt	2012-01-04 18:55:44.000000000 -0500
@@ -50,8 +50,7 @@ Machine DAI Configuration
 The machine DAI configuration glues all the codec and CPU DAIs together. It can
 also be used to set up the DAI system clock and for any machine related DAI
 initialisation e.g. the machine audio map can be connected to the codec audio
-map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c
-for examples.
+map, unconnected codec pins can be set as such.
 
 struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
 
@@ -83,8 +82,7 @@ Machine Power Map
 The machine driver can optionally extend the codec power map and to become an
 audio power map of the audio subsystem. This allows for automatic power up/down
 of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
-sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
-details.
+sockets in the machine init function.
 
 
 Machine Controls
diff -druNp linux-libre-3.1-gnu1/Documentation/sound/oss/PAS16 linux-libre-3.2-gnu1/Documentation/sound/oss/PAS16
--- linux-libre-3.1-gnu1/Documentation/sound/oss/PAS16	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sound/oss/PAS16	2012-01-04 18:55:44.000000000 -0500
@@ -60,8 +60,7 @@ With PAS16 you can use two audio device
 
 The new stuff for 2.3.99 and later
 ============================================================================
-The following configuration options from Documentation/Configure.help
-are relevant to configuring the PAS16:
+The following configuration options are relevant to configuring the PAS16:
 
 Sound card support
 CONFIG_SOUND
diff -druNp linux-libre-3.1-gnu1/Documentation/spi/pxa2xx linux-libre-3.2-gnu1/Documentation/spi/pxa2xx
--- linux-libre-3.1-gnu1/Documentation/spi/pxa2xx	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/spi/pxa2xx	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@ PXA2xx SPI on SSP driver HOWTO
 ===================================================
 This a mini howto on the pxa2xx_spi driver.  The driver turns a PXA2xx
 synchronous serial port into a SPI master controller
-(see Documentation/spi/spi_summary). The driver has the following features
+(see Documentation/spi/spi-summary). The driver has the following features
 
 - Support for any PXA2xx SSP
 - SSP PIO and SSP DMA data transfers.
@@ -85,7 +85,7 @@ Declaring Slave Devices
 -----------------------
 Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
 using the "spi_board_info" structure found in "linux/spi/spi.h". See
-"Documentation/spi/spi_summary" for additional information.
+"Documentation/spi/spi-summary" for additional information.
 
 Each slave device attached to the PXA must provide slave specific configuration
 information via the structure "pxa2xx_spi_chip" found in
diff -druNp linux-libre-3.1-gnu1/Documentation/stable_kernel_rules.txt linux-libre-3.2-gnu1/Documentation/stable_kernel_rules.txt
--- linux-libre-3.1-gnu1/Documentation/stable_kernel_rules.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/stable_kernel_rules.txt	2012-01-04 18:55:44.000000000 -0500
@@ -24,10 +24,10 @@ Rules on what kind of patches are accept
 Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
-   stable@kernel.org.  You must note the upstream commit ID in the changelog
-   of your submission.
+   stable@vger.kernel.org.  You must note the upstream commit ID in the
+   changelog of your submission.
  - To have the patch automatically included in the stable tree, add the tag
-     Cc: stable@kernel.org
+     Cc: stable@vger.kernel.org
    in the sign-off area. Once the patch is merged it will be applied to
    the stable tree without anything else needing to be done by the author
    or subsystem maintainer.
@@ -35,10 +35,10 @@ Procedure for submitting patches to the
    cherry-picked than this can be specified in the following format in
    the sign-off area:
 
-     Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
-     Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
-     Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
-     Cc: <stable@kernel.org> # .32.x
+     Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
+     Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
+     Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
+     Cc: <stable@vger.kernel.org> # .32.x
     Signed-off-by: Ingo Molnar <mingo@elte.hu>
 
    The tag sequence has the meaning of:
diff -druNp linux-libre-3.1-gnu1/Documentation/sysctl/kernel.txt linux-libre-3.2-gnu1/Documentation/sysctl/kernel.txt
--- linux-libre-3.1-gnu1/Documentation/sysctl/kernel.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/sysctl/kernel.txt	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@ show up in /proc/sys/kernel:
 - bootloader_type	     [ X86 only ]
 - bootloader_version	     [ X86 only ]
 - callhome		     [ S390 only ]
+- cap_last_cap
 - core_pattern
 - core_pipe_limit
 - core_uses_pid
@@ -155,6 +156,13 @@ on has a service contract with IBM.
 
 ==============================================================
 
+cap_last_cap
+
+Highest valid capability of the running kernel.  Exports
+CAP_LAST_CAP from the kernel.
+
+==============================================================
+
 core_pattern:
 
 core_pattern is used to specify a core dumpfile pattern name.
diff -druNp linux-libre-3.1-gnu1/Documentation/timers/highres.txt linux-libre-3.2-gnu1/Documentation/timers/highres.txt
--- linux-libre-3.1-gnu1/Documentation/timers/highres.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/timers/highres.txt	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@ hrtimer base infrastructure
 ---------------------------
 
 The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
-the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+the base implementation are covered in Documentation/timers/hrtimers.txt. See
 also figure #2 (OLS slides p. 15)
 
 The main differences to the timer wheel, which holds the armed timer_list type
diff -druNp linux-libre-3.1-gnu1/Documentation/trace/postprocess/trace-vmscan-postprocess.pl linux-libre-3.2-gnu1/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
--- linux-libre-3.1-gnu1/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2012-01-04 18:55:44.000000000 -0500
@@ -379,10 +379,10 @@ EVENT_PROCESS:
 
 			# To closer match vmstat scanning statistics, only count isolate_both
 			# and isolate_inactive as scanning. isolate_active is rotation
-			# isolate_inactive == 0
-			# isolate_active   == 1
-			# isolate_both     == 2
-			if ($isolate_mode != 1) {
+			# isolate_inactive == 1
+			# isolate_active   == 2
+			# isolate_both     == 3
+			if ($isolate_mode != 2) {
 				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
 			}
 			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
diff -druNp linux-libre-3.1-gnu1/Documentation/usb/dma.txt linux-libre-3.2-gnu1/Documentation/usb/dma.txt
--- linux-libre-3.1-gnu1/Documentation/usb/dma.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/usb/dma.txt	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@ API OVERVIEW
 
 The big picture is that USB drivers can continue to ignore most DMA issues,
 though they still must provide DMA-ready buffers (see
-Documentation/PCI/PCI-DMA-mapping.txt).  That's how they've worked through
+Documentation/DMA-API-HOWTO.txt).  That's how they've worked through
 the 2.4 (and earlier) kernels.
 
 OR:  they can now be DMA-aware.
@@ -57,7 +57,7 @@ and effects like cache-trashing can impo
   force a consistent memory access ordering by using memory barriers.  It's
   not using a streaming DMA mapping, so it's good for small transfers on
   systems where the I/O would otherwise thrash an IOMMU mapping.  (See
-  Documentation/PCI/PCI-DMA-mapping.txt for definitions of "coherent" and
+  Documentation/DMA-API-HOWTO.txt for definitions of "coherent" and
   "streaming" DMA mappings.)
 
   Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
@@ -88,7 +88,7 @@ WORKING WITH EXISTING BUFFERS
 Existing buffers aren't usable for DMA without first being mapped into the
 DMA address space of the device.  However, most buffers passed to your
 driver can safely be used with such DMA mapping.  (See the first section
-of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
+of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
 
 - When you're using scatterlists, you can map everything at once.  On some
   systems, this kicks in an IOMMU and turns the scatterlists into single
diff -druNp linux-libre-3.1-gnu1/Documentation/usb/dwc3.txt linux-libre-3.2-gnu1/Documentation/usb/dwc3.txt
--- linux-libre-3.1-gnu1/Documentation/usb/dwc3.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/usb/dwc3.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+
+ TODO
+~~~~~~
+Please pick something while reading :)
+
+- Convert interrupt handler to per-ep-thread-irq
+
+  As it turns out some DWC3-commands ~1ms to complete. Currently we spin
+  until the command completes which is bad.
+
+  Implementation idea:
+  - dwc core implements a demultiplexing irq chip for interrupts per
+    endpoint. The interrupt numbers are allocated during probe and belong
+    to the device. If MSI provides per-endpoint interrupt this dummy
+    interrupt chip can be replaced with "real" interrupts.
+  - interrupts are requested / allocated on usb_ep_enable() and removed on
+    usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two
+    for ep0/1.
+  - dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout()
+    until the command completes.
+  - the interrupt handler is split into the following pieces:
+    - primary handler of the device
+      goes through every event and calls generic_handle_irq() for event
+      it. On return from generic_handle_irq() in acknowledges the event
+      counter so interrupt goes away (eventually).
+
+    - threaded handler of the device
+      none
+
+    - primary handler of the EP-interrupt
+      reads the event and tries to process it. Everything that requries
+      sleeping is handed over to the Thread. The event is saved in an
+      per-endpoint data-structure.
+      We probably have to pay attention not to process events once we
+      handed something to thread so we don't process event X prio Y
+      where X > Y.
+
+    - threaded handler of the EP-interrupt
+      handles the remaining EP work which might sleep such as waiting
+      for command completion.
+
+  Latency:
+   There should be no increase in latency since the interrupt-thread has a
+   high priority and will be run before an average task in user land
+   (except the user changed priorities).
diff -druNp linux-libre-3.1-gnu1/Documentation/usb/linux-cdc-acm.inf linux-libre-3.2-gnu1/Documentation/usb/linux-cdc-acm.inf
--- linux-libre-3.1-gnu1/Documentation/usb/linux-cdc-acm.inf	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/usb/linux-cdc-acm.inf	2012-01-04 18:55:44.000000000 -0500
@@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys
 [SourceDisksFiles]
 [SourceDisksNames]
 [DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
 
 [DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
 
 
 ;------------------------------------------------------------------------------
diff -druNp linux-libre-3.1-gnu1/Documentation/usb/power-management.txt linux-libre-3.2-gnu1/Documentation/usb/power-management.txt
--- linux-libre-3.1-gnu1/Documentation/usb/power-management.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/usb/power-management.txt	2012-01-04 18:55:44.000000000 -0500
@@ -439,10 +439,10 @@ cause autosuspends to fail with -EBUSY i
 device.
 
 External suspend calls should never be allowed to fail in this way,
-only autosuspend calls.  The driver can tell them apart by checking
-the PM_EVENT_AUTO bit in the message.event argument to the suspend
-method; this bit will be set for internal PM events (autosuspend) and
-clear for external PM events.
+only autosuspend calls.  The driver can tell them apart by applying
+the PMSG_IS_AUTO() macro to the message argument to the suspend
+method; it will return True for internal PM events (autosuspend) and
+False for external PM events.
 
 
 	Mutual exclusion
@@ -487,3 +487,29 @@ succeed, it may still remain active and
 resume as soon as the system suspend is complete.  Or the remote
 wakeup may fail and get lost.  Which outcome occurs depends on timing
 and on the hardware and firmware design.
+
+
+	xHCI hardware link PM
+	---------------------
+
+xHCI host controller provides hardware link power management to usb2.0
+(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
+enabling hardware LPM, the host can automatically put the device into
+lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
+which state device can enter and resume very quickly.
+
+The user interface for controlling USB2 hardware LPM is located in the
+power/ subdirectory of each USB device's sysfs directory, that is, in
+/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
+relevant attribute files is usb2_hardware_lpm.
+
+	power/usb2_hardware_lpm
+
+		When a USB2 device which support LPM is plugged to a
+		xHCI host root hub which support software LPM, the
+		host will run a software LPM test for it; if the device
+		enters L1 state and resume successfully and the host
+		supports USB2 hardware LPM, this file will show up and
+		driver will enable hardware LPM	for the device. You
+		can write y/Y/1 or n/N/0 to the file to	enable/disable
+		USB2 hardware LPM manually. This is for	test purpose mainly.
diff -druNp linux-libre-3.1-gnu1/Documentation/video4linux/CARDLIST.tm6000 linux-libre-3.2-gnu1/Documentation/video4linux/CARDLIST.tm6000
--- linux-libre-3.1-gnu1/Documentation/video4linux/CARDLIST.tm6000	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/video4linux/CARDLIST.tm6000	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+  1 -> Generic tm5600 board                   (tm5600)          [6000:0001]
+  2 -> Generic tm6000 board                   (tm6000)          [6000:0001]
+  3 -> Generic tm6010 board                   (tm6010)          [6000:0002]
+  4 -> 10Moons UT821                          (tm5600)          [6000:0001]
+  5 -> 10Moons UT330                          (tm5600)
+  6 -> ADSTech Dual TV                        (tm6000)          [06e1:f332]
+  7 -> FreeCom and similar                    (tm6000)          [14aa:0620]
+  8 -> ADSTech Mini Dual TV                   (tm6000)          [06e1:b339]
+  9 -> Hauppauge WinTV HVR-900H/USB2 Stick    (tm6010)          [2040:6600,2040:6601,2040:6610,2040:6611]
+ 10 -> Beholder Wander                        (tm6010)          [6000:dec0]
+ 11 -> Beholder Voyager                       (tm6010)          [6000:dec1]
+ 12 -> TerraTec Cinergy Hybrid XE/Cinergy Hybrid Stick (tm6010) [0ccd:0086,0ccd:00a5]
+ 13 -> TwinHan TU501                          (tm6010)          [13d3:3240,13d3:3241,13d3:3243,13d3:3264]
+ 14 -> Beholder Wander Lite                   (tm6010)          [6000:dec2]
+ 15 -> Beholder Voyager Lite                  (tm6010)          [6000:dec3]
+
diff -druNp linux-libre-3.1-gnu1/Documentation/video4linux/gspca.txt linux-libre-3.2-gnu1/Documentation/video4linux/gspca.txt
--- linux-libre-3.1-gnu1/Documentation/video4linux/gspca.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/video4linux/gspca.txt	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@ xxxx		vend:prod
 ----
 spca501		0000:0000	MystFromOri Unknown Camera
 spca508		0130:0130	Clone Digital Webcam 11043
+zc3xx		03f0:1b07	HP Premium Starter Cam
 m5602		0402:5602	ALi Video Camera Controller
 spca501		040a:0002	Kodak DVC-325
 spca500		040a:0300	Kodak EZ200
@@ -190,6 +191,7 @@ ov519		05a9:0519	OV519 Microphone
 ov519		05a9:0530	OmniVision
 ov519		05a9:2800	OmniVision SuperCAM
 ov519		05a9:4519	Webcam Classic
+ov534_9		05a9:8065	OmniVision test kit ov538+ov9712
 ov519		05a9:8519	OmniVision
 ov519		05a9:a511	D-Link USB Digital Video Camera
 ov519		05a9:a518	D-Link DSB-C310 Webcam
@@ -199,6 +201,8 @@ gl860		05e3:0503	Genesys Logic PC Camera
 gl860		05e3:f191	Genesys Logic PC Camera
 spca561		060b:a001	Maxell Compact Pc PM3
 zc3xx		0698:2003	CTX M730V built in
+topro		06a2:0003	TP6800 PC Camera, CmoX CX0342 webcam
+topro		06a2:6810	Creative Qmax
 nw80x		06a5:0000	Typhoon Webcam 100 USB
 nw80x		06a5:d001	Divio based webcams
 nw80x		06a5:d800	Divio Chicony TwinkleCam, Trust SpaceCam
diff -druNp linux-libre-3.1-gnu1/Documentation/video4linux/omap3isp.txt linux-libre-3.2-gnu1/Documentation/video4linux/omap3isp.txt
--- linux-libre-3.1-gnu1/Documentation/video4linux/omap3isp.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/video4linux/omap3isp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -70,10 +70,11 @@ Events
 The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and
 statistics (AEWB, AF and histogram) subdevs.
 
-The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS
-interrupt which is used to signal frame start. The event is triggered exactly
-when the reception of the first line of the frame starts in the CCDC module.
-The event can be subscribed on the CCDC subdev.
+The CCDC subdev produces V4L2_EVENT_FRAME_SYNC type event on HS_VS
+interrupt which is used to signal frame start. Earlier version of this
+driver used V4L2_EVENT_OMAP3ISP_HS_VS for this purpose. The event is
+triggered exactly when the reception of the first line of the frame starts
+in the CCDC module. The event can be subscribed on the CCDC subdev.
 
 (When using parallel interface one must pay account to correct configuration
 of the VS signal polarity. This is automatically correct when using the serial
diff -druNp linux-libre-3.1-gnu1/Documentation/video4linux/v4l2-controls.txt linux-libre-3.2-gnu1/Documentation/video4linux/v4l2-controls.txt
--- linux-libre-3.1-gnu1/Documentation/video4linux/v4l2-controls.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/video4linux/v4l2-controls.txt	2012-01-04 18:55:44.000000000 -0500
@@ -285,11 +285,11 @@ implement g_volatile_ctrl like this:
 Note that you use the 'new value' union as well in g_volatile_ctrl. In general
 controls that need to implement g_volatile_ctrl are read-only controls.
 
-To mark a control as volatile you have to set the is_volatile flag:
+To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
 
 	ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 For try/s_ctrl the new values (i.e. as passed by the user) are filled in and
 you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union
@@ -367,8 +367,7 @@ Driver specific controls can be created
 The last argument is the priv pointer which can be set to driver-specific
 private data.
 
-The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile
-flags.
+The v4l2_ctrl_config struct also has a field to set the is_private flag.
 
 If the name field is not set, then the framework will assume this is a standard
 control and will fill in the name, type and flags fields accordingly.
@@ -496,18 +495,20 @@ Handling autogain/gain-type Controls wit
 
 A common type of control cluster is one that handles 'auto-foo/foo'-type
 controls. Typical examples are autogain/gain, autoexposure/exposure,
-autowhitebalance/red balance/blue balance. In all cases you have one controls
+autowhitebalance/red balance/blue balance. In all cases you have one control
 that determines whether another control is handled automatically by the hardware,
 or whether it is under manual control from the user.
 
 If the cluster is in automatic mode, then the manual controls should be
-marked inactive. When the volatile controls are read the g_volatile_ctrl
-operation should return the value that the hardware's automatic mode set up
-automatically.
+marked inactive and volatile. When the volatile controls are read the
+g_volatile_ctrl operation should return the value that the hardware's automatic
+mode set up automatically.
 
 If the cluster is put in manual mode, then the manual controls should become
-active again and the is_volatile flag should be ignored (so g_volatile_ctrl is
-no longer called while in manual mode).
+active again and the volatile flag is cleared (so g_volatile_ctrl is no longer
+called while in manual mode). In addition just before switching to manual mode
+the current values as determined by the auto mode are copied as the new manual
+values.
 
 Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since
 changing that control affects the control flags of the manual controls.
@@ -520,7 +521,11 @@ void v4l2_ctrl_auto_cluster(unsigned nco
 
 The first two arguments are identical to v4l2_ctrl_cluster. The third argument
 tells the framework which value switches the cluster into manual mode. The
-last argument will optionally set the is_volatile flag for the non-auto controls.
+last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls.
+If it is false, then the manual controls are never volatile. You would typically
+use that if the hardware does not give you the option to read back to values as
+determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow
+you to obtain the current gain value).
 
 The first control of the cluster is assumed to be the 'auto' control.
 
@@ -681,16 +686,6 @@ if there are no controls at all.
 count if nothing was done yet. If it is less than count then only the controls
 up to error_idx-1 were successfully applied.
 
-3) When attempting to read a button control the framework will return -EACCES
-instead of -EINVAL as stated in the spec. It seems to make more sense since
-button controls are write-only controls.
-
-4) Attempting to write to a read-only control will return -EACCES instead of
--EINVAL as the spec says.
-
-5) The spec does not mention what should happen when you try to set/get a
-control class controls. The framework will return -EACCES.
-
 
 Proposals for Extensions
 ========================
@@ -703,9 +698,3 @@ decimal. Useful for e.g. video_mute_yuv.
 2) It is possible to mark in the controls array which controls have been
 successfully written and which failed by for example adding a bit to the
 control ID. Not sure if it is worth the effort, though.
-
-3) Trying to set volatile inactive controls should result in -EACCESS.
-
-4) Add a new flag to mark volatile controls. Any application that wants
-to store the state of the controls can then skip volatile inactive controls.
-Currently it is not possible to detect such controls.
diff -druNp linux-libre-3.1-gnu1/Documentation/virtual/kvm/api.txt linux-libre-3.2-gnu1/Documentation/virtual/kvm/api.txt
--- linux-libre-3.1-gnu1/Documentation/virtual/kvm/api.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/virtual/kvm/api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -175,10 +175,30 @@ Parameters: vcpu id (apic id on x86)
 Returns: vcpu fd on success, -1 on error
 
 This API adds a vcpu to a virtual machine.  The vcpu id is a small integer
-in the range [0, max_vcpus).  You can use KVM_CAP_NR_VCPUS of the
-KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time.
+in the range [0, max_vcpus).
+
+The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
+the KVM_CHECK_EXTENSION ioctl() at run-time.
+The maximum possible value for max_vcpus can be retrieved using the
+KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
 If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
 cpus max.
+If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
+same as the value returned from KVM_CAP_NR_VCPUS.
+
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores.  (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore).  The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids.  For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
 
 On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
 threads in one or more virtual CPU cores.  (This is because the
@@ -1080,6 +1100,15 @@ emulate them efficiently. The fields in
    eax, ebx, ecx, edx: the values returned by the cpuid instruction for
          this function/index combination
 
+The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
+as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
+support.  Instead it is reported via
+
+  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
+
+if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
+feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
+
 4.47 KVM_PPC_GET_PVINFO
 
 Capability: KVM_CAP_PPC_GET_PVINFO
@@ -1131,6 +1160,13 @@ following flags are specified:
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 
+The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
+isolation of the device.  Usages not specifying this flag are deprecated.
+
+Only PCI header type 0 devices with PCI BAR resources are supported by
+device assignment.  The user requesting this ioctl must have read/write
+access to the PCI sysfs resource files associated with the device.
+
 4.49 KVM_DEASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_DEASSIGNMENT
@@ -1633,3 +1669,50 @@ developer registration required to acces
 		char padding[256];
 	};
 };
+
+6. Capabilities that can be enabled
+
+There are certain capabilities that change the behavior of the virtual CPU when
+enabled. To enable them, please see section 4.37. Below you can find a list of
+capabilities and what their effect on the vCPU is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+6.1 KVM_CAP_PPC_OSI
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of OSI hypercalls that otherwise would
+be treated as normal system calls to be injected into the guest. OSI hypercalls
+were invented by Mac-on-Linux to have a standardized communication mechanism
+between the guest and the host.
+
+When this capability is enabled, KVM_EXIT_OSI can occur.
+
+6.2 KVM_CAP_PPC_PAPR
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of PAPR hypercalls. PAPR hypercalls are
+done using the hypercall instruction "sc 1".
+
+It also sets the guest privilege level to "supervisor" mode. Usually the guest
+runs in "hypervisor" privilege mode with a few missing features.
+
+In addition to the above, it changes the semantics of SDR1. In this mode, the
+HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
+HTAB invisible to the guest.
+
+When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
diff -druNp linux-libre-3.1-gnu1/Documentation/virtual/lguest/lguest.c linux-libre-3.2-gnu1/Documentation/virtual/lguest/lguest.c
--- linux-libre-3.1-gnu1/Documentation/virtual/lguest/lguest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/virtual/lguest/lguest.c	2012-01-04 18:55:44.000000000 -0500
@@ -436,7 +436,7 @@ static unsigned long load_bzimage(int fd
 
 	/*
 	 * Go back to the start of the file and read the header.  It should be
-	 * a Linux boot header (see Documentation/x86/i386/boot.txt)
+	 * a Linux boot header (see Documentation/x86/boot.txt)
 	 */
 	lseek(fd, 0, SEEK_SET);
 	read(fd, &boot, sizeof(boot));
diff -druNp linux-libre-3.1-gnu1/Documentation/virtual/uml/UserModeLinux-HOWTO.txt linux-libre-3.2-gnu1/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
--- linux-libre-3.1-gnu1/Documentation/virtual/uml/UserModeLinux-HOWTO.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/virtual/uml/UserModeLinux-HOWTO.txt	2012-01-04 18:55:44.000000000 -0500
@@ -134,13 +134,13 @@
 
   ______________________________________________________________________
 
-  11..  IInnttrroodduuccttiioonn
+  1.  Introduction
 
   Welcome to User Mode Linux.  It's going to be fun.
 
 
 
-  11..11..  HHooww iiss UUsseerr MMooddee LLiinnuuxx DDiiffffeerreenntt??
+  1.1.  How is User Mode Linux Different?
 
   Normally, the Linux Kernel talks straight to your hardware (video
   card, keyboard, hard drives, etc), and any programs which run ask the
@@ -181,7 +181,7 @@
 
 
 
-  11..22..  WWhhyy WWoouulldd II WWaanntt UUsseerr MMooddee LLiinnuuxx??
+  1.2.  Why Would I Want User Mode Linux?
 
 
   1. If User Mode Linux crashes, your host kernel is still fine.
@@ -206,12 +206,12 @@
 
 
 
-  22..  CCoommppiilliinngg tthhee kkeerrnneell aanndd mmoodduulleess
+  2.  Compiling the kernel and modules
 
 
 
 
-  22..11..  CCoommppiilliinngg tthhee kkeerrnneell
+  2.1.  Compiling the kernel
 
 
   Compiling the user mode kernel is just like compiling any other
@@ -322,7 +322,7 @@
   bug fixes and enhancements that have gone into subsequent releases.
 
 
-  22..22..  CCoommppiilliinngg aanndd iinnssttaalllliinngg kkeerrnneell mmoodduulleess
+  2.2.  Compiling and installing kernel modules
 
   UML modules are built in the same way as the native kernel (with the
   exception of the 'ARCH=um' that you always need for UML):
@@ -386,19 +386,19 @@
 
 
 
-  22..33..  CCoommppiilliinngg aanndd iinnssttaalllliinngg uummll__uuttiilliittiieess
+  2.3.  Compiling and installing uml_utilities
 
   Many features of the UML kernel require a user-space helper program,
   so a uml_utilities package is distributed separately from the kernel
   patch which provides these helpers. Included within this is:
 
-  +o  port-helper - Used by consoles which connect to xterms or ports
+  o  port-helper - Used by consoles which connect to xterms or ports
 
-  +o  tunctl - Configuration tool to create and delete tap devices
+  o  tunctl - Configuration tool to create and delete tap devices
 
-  +o  uml_net - Setuid binary for automatic tap device configuration
+  o  uml_net - Setuid binary for automatic tap device configuration
 
-  +o  uml_switch - User-space virtual switch required for daemon
+  o  uml_switch - User-space virtual switch required for daemon
      transport
 
      The uml_utilities tree is compiled with:
@@ -423,11 +423,11 @@
 
 
 
-  33..  RRuunnnniinngg UUMMLL aanndd llooggggiinngg iinn
+  3.  Running UML and logging in
 
 
 
-  33..11..  RRuunnnniinngg UUMMLL
+  3.1.  Running UML
 
   It runs on 2.2.15 or later, and all 2.4 kernels.
 
@@ -454,7 +454,7 @@
 
 
 
-  33..22..  LLooggggiinngg iinn
+  3.2.  Logging in
 
 
 
@@ -468,7 +468,7 @@
 
   There are a couple of other ways to log in:
 
-  +o  On a virtual console
+  o  On a virtual console
 
 
 
@@ -480,7 +480,7 @@
 
 
 
-  +o  Over the serial line
+  o  Over the serial line
 
 
      In the boot output, find a line that looks like:
@@ -503,7 +503,7 @@
 
 
 
-  +o  Over the net
+  o  Over the net
 
 
      If the network is running, then you can telnet to the virtual
@@ -514,13 +514,13 @@
   down and the process will exit.
 
 
-  33..33..  EExxaammpplleess
+  3.3.  Examples
 
   Here are some examples of UML in action:
 
-  +o  A login session <http://user-mode-linux.sourceforge.net/login.html>
+  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
 
-  +o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
 
 
 
@@ -528,12 +528,12 @@
 
 
 
-  44..  UUMMLL oonn 22GG//22GG hhoossttss
+  4.  UML on 2G/2G hosts
 
 
 
 
-  44..11..  IInnttrroodduuccttiioonn
+  4.1.  Introduction
 
 
   Most Linux machines are configured so that the kernel occupies the
@@ -546,7 +546,7 @@
 
 
 
-  44..22..  TThhee pprroobblleemm
+  4.2.  The problem
 
 
   The prebuilt UML binaries on this site will not run on 2G/2G hosts
@@ -558,7 +558,7 @@
 
 
 
-  44..33..  TThhee ssoolluuttiioonn
+  4.3.  The solution
 
 
   The fix for this is to rebuild UML from source after enabling
@@ -576,7 +576,7 @@
 
 
 
-  55..  SSeettttiinngg uupp sseerriiaall lliinneess aanndd ccoonnssoolleess
+  5.  Setting up serial lines and consoles
 
 
   It is possible to attach UML serial lines and consoles to many types
@@ -586,12 +586,12 @@
   You can attach them to host ptys, ttys, file descriptors, and ports.
   This allows you to do things like
 
-  +o  have a UML console appear on an unused host console,
+  o  have a UML console appear on an unused host console,
 
-  +o  hook two virtual machines together by having one attach to a pty
+  o  hook two virtual machines together by having one attach to a pty
      and having the other attach to the corresponding tty
 
-  +o  make a virtual machine accessible from the net by attaching a
+  o  make a virtual machine accessible from the net by attaching a
      console to a port on the host.
 
 
@@ -599,7 +599,7 @@
 
 
 
-  55..11..  SSppeecciiffyyiinngg tthhee ddeevviiccee
+  5.1.  Specifying the device
 
   Devices are specified with "con" or "ssl" (console or serial line,
   respectively), optionally with a device number if you are talking
@@ -626,13 +626,13 @@
 
 
 
-  55..22..  SSppeecciiffyyiinngg tthhee cchhaannnneell
+  5.2.  Specifying the channel
 
   There are a number of different types of channels to attach a UML
   device to, each with a different way of specifying exactly what to
   attach to.
 
-  +o  pseudo-terminals - device=pty pts terminals - device=pts
+  o  pseudo-terminals - device=pty pts terminals - device=pts
 
 
      This will cause UML to allocate a free host pseudo-terminal for the
@@ -640,20 +640,20 @@
      log.  You access it by attaching a terminal program to the
      corresponding tty:
 
-  +o  screen /dev/pts/n
+  o  screen /dev/pts/n
 
-  +o  screen /dev/ttyxx
+  o  screen /dev/ttyxx
 
-  +o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
      devices
 
-  +o  kermit - start it up, 'open' the device, then 'connect'
+  o  kermit - start it up, 'open' the device, then 'connect'
 
 
 
 
 
-  +o  terminals - device=tty:tty device file
+  o  terminals - device=tty:tty device file
 
 
      This will make UML attach the device to the specified tty (i.e
@@ -672,7 +672,7 @@
 
 
 
-  +o  xterms - device=xterm
+  o  xterms - device=xterm
 
 
      UML will run an xterm and the device will be attached to it.
@@ -681,7 +681,7 @@
 
 
 
-  +o  Port - device=port:port number
+  o  Port - device=port:port number
 
 
      This will attach the UML devices to the specified host port.
@@ -725,7 +725,7 @@
 
 
 
-  +o  already-existing file descriptors - device=file descriptor
+  o  already-existing file descriptors - device=file descriptor
 
 
      If you set up a file descriptor on the UML command line, you can
@@ -743,7 +743,7 @@
 
 
 
-  +o  Nothing - device=null
+  o  Nothing - device=null
 
 
      This allows the device to be opened, in contrast to 'none', but
@@ -754,7 +754,7 @@
 
 
 
-  +o  None - device=none
+  o  None - device=none
 
 
      This causes the device to disappear.
@@ -770,7 +770,7 @@
 
 
 
-  will cause serial line 3 to accept input on the host's /dev/tty3 and
+  will cause serial line 3 to accept input on the host's /dev/tty2 and
   display output on an xterm.  That's a silly example - the most common
   use of this syntax is to reattach the main console to stdin and stdout
   as shown above.
@@ -785,7 +785,7 @@
 
 
 
-  55..33..  EExxaammpplleess
+  5.3.  Examples
 
   There are a number of interesting things you can do with this
   capability.
@@ -838,7 +838,7 @@
   prompt of the other virtual machine.
 
 
-  66..  SSeettttiinngg uupp tthhee nneettwwoorrkk
+  6.  Setting up the network
 
 
 
@@ -858,19 +858,19 @@
   There are currently five transport types available for a UML virtual
   machine to exchange packets with other hosts:
 
-  +o  ethertap
+  o  ethertap
 
-  +o  TUN/TAP
+  o  TUN/TAP
 
-  +o  Multicast
+  o  Multicast
 
-  +o  a switch daemon
+  o  a switch daemon
 
-  +o  slip
+  o  slip
 
-  +o  slirp
+  o  slirp
 
-  +o  pcap
+  o  pcap
 
      The TUN/TAP, ethertap, slip, and slirp transports allow a UML
      instance to exchange packets with the host.  They may be directed
@@ -893,28 +893,28 @@
   With so many host transports, which one should you use?  Here's when
   you should use each one:
 
-  +o  ethertap - if you want access to the host networking and it is
+  o  ethertap - if you want access to the host networking and it is
      running 2.2
 
-  +o  TUN/TAP - if you want access to the host networking and it is
+  o  TUN/TAP - if you want access to the host networking and it is
      running 2.4.  Also, the TUN/TAP transport is able to use a
      preconfigured device, allowing it to avoid using the setuid uml_net
      helper, which is a security advantage.
 
-  +o  Multicast - if you want a purely virtual network and you don't want
+  o  Multicast - if you want a purely virtual network and you don't want
      to set up anything but the UML
 
-  +o  a switch daemon - if you want a purely virtual network and you
+  o  a switch daemon - if you want a purely virtual network and you
      don't mind running the daemon in order to get somewhat better
      performance
 
-  +o  slip - there is no particular reason to run the slip backend unless
+  o  slip - there is no particular reason to run the slip backend unless
      ethertap and TUN/TAP are just not available for some reason
 
-  +o  slirp - if you don't have root access on the host to setup
+  o  slirp - if you don't have root access on the host to setup
      networking, or if you don't want to allocate an IP to your UML
 
-  +o  pcap - not much use for actual network connectivity, but great for
+  o  pcap - not much use for actual network connectivity, but great for
      monitoring traffic on the host
 
      Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
@@ -926,7 +926,7 @@
      exploit the helper's root privileges.
 
 
-  66..11..  GGeenneerraall sseettuupp
+  6.1.  General setup
 
   First, you must have the virtual network enabled in your UML.  If are
   running a prebuilt kernel from this site, everything is already
@@ -995,7 +995,7 @@
 
 
 
-  66..22..  UUsseerrssppaaccee ddaaeemmoonnss
+  6.2.  Userspace daemons
 
   You will likely need the setuid helper, or the switch daemon, or both.
   They are both installed with the RPM and deb, so if you've installed
@@ -1011,7 +1011,7 @@
 
 
 
-  66..33..  SSppeecciiffyyiinngg eetthheerrnneett aaddddrreesssseess
+  6.3.  Specifying ethernet addresses
 
   Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
   allow you to specify hardware addresses for the virtual ethernet
@@ -1023,11 +1023,11 @@
   sufficient to guarantee a unique hardware address for the device.  A
   couple of exceptions are:
 
-  +o  Another set of virtual ethernet devices are on the same network and
+  o  Another set of virtual ethernet devices are on the same network and
      they are assigned hardware addresses using a different scheme which
      may conflict with the UML IP address-based scheme
 
-  +o  You aren't going to use the device for IP networking, so you don't
+  o  You aren't going to use the device for IP networking, so you don't
      assign the device an IP address
 
      If you let the driver provide the hardware address, you should make
@@ -1049,7 +1049,7 @@
 
 
 
-  66..44..  UUMMLL iinntteerrffaaccee sseettuupp
+  6.4.  UML interface setup
 
   Once the network devices have been described on the command line, you
   should boot UML and log in.
@@ -1131,7 +1131,7 @@
 
 
 
-  66..55..  MMuullttiiccaasstt
+  6.5.  Multicast
 
   The simplest way to set up a virtual network between multiple UMLs is
   to use the mcast transport.  This was written by Harald Welte and is
@@ -1194,7 +1194,7 @@
 
 
 
-  66..66..  TTUUNN//TTAAPP wwiitthh tthhee uummll__nneett hheellppeerr
+  6.6.  TUN/TAP with the uml_net helper
 
   TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
   host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
@@ -1247,10 +1247,10 @@
   There are a couple potential problems with running the TUN/TAP
   transport on a 2.4 host kernel
 
-  +o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
+  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
      kernel or use the ethertap transport.
 
-  +o  With an upgraded kernel, TUN/TAP may fail with
+  o  With an upgraded kernel, TUN/TAP may fail with
 
 
        File descriptor in bad state
@@ -1269,7 +1269,7 @@
 
 
 
-  66..77..  TTUUNN//TTAAPP wwiitthh aa pprreeccoonnffiigguurreedd ttaapp ddeevviiccee
+  6.7.  TUN/TAP with a preconfigured tap device
 
   If you prefer not to have UML use uml_net (which is somewhat
   insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
@@ -1277,7 +1277,7 @@
   there is no need for root assistance.  Setting up the device is done
   as follows:
 
-  +o  Create the device with tunctl (available from the UML utilities
+  o  Create the device with tunctl (available from the UML utilities
      tarball)
 
 
@@ -1291,7 +1291,7 @@
   where uid is the user id or username that UML will be run as.  This
   will tell you what device was created.
 
-  +o  Configure the device IP (change IP addresses and device name to
+  o  Configure the device IP (change IP addresses and device name to
      suit)
 
 
@@ -1303,7 +1303,7 @@
 
 
 
-  +o  Set up routing and arping if desired - this is my recipe, there are
+  o  Set up routing and arping if desired - this is my recipe, there are
      other ways of doing the same thing
 
 
@@ -1338,7 +1338,7 @@
   utility which reads the information from a config file and sets up
   devices at boot time.
 
-  +o  Rather than using up two IPs and ARPing for one of them, you can
+  o  Rather than using up two IPs and ARPing for one of them, you can
      also provide direct access to your LAN by the UML by using a
      bridge.
 
@@ -1417,7 +1417,7 @@
   Note that 'br0' should be setup using ifconfig with the existing IP
   address of eth0, as eth0 no longer has its own IP.
 
-  +o
+  o
 
 
      Also, the /dev/net/tun device must be writable by the user running
@@ -1438,11 +1438,11 @@
   devices and chgrp /dev/net/tun to that group with mode 664 or 660.
 
 
-  +o  Once the device is set up, run UML with 'eth0=tuntap,device name'
+  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
      (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
      mconsole config command).
 
-  +o  Bring the eth device up in UML and you're in business.
+  o  Bring the eth device up in UML and you're in business.
 
      If you don't want that tap device any more, you can make it non-
      persistent with
@@ -1465,7 +1465,7 @@
 
 
 
-  66..88..  EEtthheerrttaapp
+  6.8.  Ethertap
 
   Ethertap is the general mechanism on 2.2 for userspace processes to
   exchange packets with the kernel.
@@ -1561,9 +1561,9 @@
 
 
 
-  66..99..  TThhee sswwiittcchh ddaaeemmoonn
+  6.9.  The switch daemon
 
-  NNoottee: This is the daemon formerly known as uml_router, but which was
+  Note: This is the daemon formerly known as uml_router, but which was
   renamed so the network weenies of the world would stop growling at me.
 
 
@@ -1649,7 +1649,7 @@
 
 
 
-  66..1100..  SSlliipp
+  6.10.  Slip
 
   Slip is another, less general, mechanism for a process to communicate
   with the host networking.  In contrast to the ethertap interface,
@@ -1681,7 +1681,7 @@
 
 
 
-  66..1111..  SSlliirrpp
+  6.11.  Slirp
 
   slirp uses an external program, usually /usr/bin/slirp, to provide IP
   only networking connectivity through the host. This is similar to IP
@@ -1737,7 +1737,7 @@
 
 
 
-  66..1122..  ppccaapp
+  6.12.  pcap
 
   The pcap transport is attached to a UML ethernet device on the command
   line or with uml_mconsole with the following syntax:
@@ -1777,7 +1777,7 @@
 
 
 
-  66..1133..  SSeettttiinngg uupp tthhee hhoosstt yyoouurrsseellff
+  6.13.  Setting up the host yourself
 
   If you don't specify an address for the host side of the ethertap or
   slip device, UML won't do any setup on the host.  So this is what is
@@ -1785,7 +1785,7 @@
   192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
   own network):
 
-  +o  The device needs to be configured with its IP address.  Tap devices
+  o  The device needs to be configured with its IP address.  Tap devices
      are also configured with an mtu of 1484.  Slip devices are
      configured with a point-to-point address pointing at the UML ip
      address.
@@ -1805,7 +1805,7 @@
 
 
 
-  +o  If a tap device is being set up, a route is set to the UML IP.
+  o  If a tap device is being set up, a route is set to the UML IP.
 
 
        UML# route add -host 192.168.0.250 gw 192.168.0.251
@@ -1814,7 +1814,7 @@
 
 
 
-  +o  To allow other hosts on your network to see the virtual machine,
+  o  To allow other hosts on your network to see the virtual machine,
      proxy arp is set up for it.
 
 
@@ -1824,7 +1824,7 @@
 
 
 
-  +o  Finally, the host is set up to route packets.
+  o  Finally, the host is set up to route packets.
 
 
        host#  echo 1 > /proc/sys/net/ipv4/ip_forward
@@ -1838,12 +1838,12 @@
 
 
 
-  77..  SShhaarriinngg FFiilleessyysstteemmss bbeettwweeeenn VViirrttuuaall MMaacchhiinneess
+  7.  Sharing Filesystems between Virtual Machines
 
 
 
 
-  77..11..  AA wwaarrnniinngg
+  7.1.  A warning
 
   Don't attempt to share filesystems simply by booting two UMLs from the
   same file.  That's the same thing as booting two physical machines
@@ -1851,7 +1851,7 @@
 
 
 
-  77..22..  UUssiinngg llaayyeerreedd bblloocckk ddeevviicceess
+  7.2.  Using layered block devices
 
   The way to share a filesystem between two virtual machines is to use
   the copy-on-write (COW) layering capability of the ubd block driver.
@@ -1896,7 +1896,7 @@
 
 
 
-  77..33..  NNoottee!!
+  7.3.  Note!
 
   When checking the size of the COW file in order to see the gobs of
   space that you're saving, make sure you use 'ls -ls' to see the actual
@@ -1926,7 +1926,7 @@
 
 
 
-  77..44..  AAnnootthheerr wwaarrnniinngg
+  7.4.  Another warning
 
   Once a filesystem is being used as a readonly backing file for a COW
   file, do not boot directly from it or modify it in any way.  Doing so
@@ -1952,7 +1952,7 @@
 
 
 
-  77..55..  uummll__mmoooo :: MMeerrggiinngg aa CCOOWW ffiillee wwiitthh iittss bbaacckkiinngg ffiillee
+  7.5.  uml_moo : Merging a COW file with its backing file
 
   Depending on how you use UML and COW devices, it may be advisable to
   merge the changes in the COW file into the backing file every once in
@@ -2001,7 +2001,7 @@
 
 
 
-  88..  CCrreeaattiinngg ffiilleessyysstteemmss
+  8.  Creating filesystems
 
 
   You may want to create and mount new UML filesystems, either because
@@ -2015,7 +2015,7 @@
   should be easy to translate to the filesystem of your choice.
 
 
-  88..11..  CCrreeaattee tthhee ffiilleessyysstteemm ffiillee
+  8.1.  Create the filesystem file
 
   dd is your friend.  All you need to do is tell dd to create an empty
   file of the appropriate size.  I usually make it sparse to save time
@@ -2032,7 +2032,7 @@
 
 
 
-  88..22..  AAssssiiggnn tthhee ffiillee ttoo aa UUMMLL ddeevviiccee
+  8.2.  Assign the file to a UML device
 
   Add an argument like the following to the UML command line:
 
@@ -2045,7 +2045,7 @@
 
 
 
-  88..33..  CCrreeaattiinngg aanndd mmoouunnttiinngg tthhee ffiilleessyysstteemm
+  8.3.  Creating and mounting the filesystem
 
   Make sure that the filesystem is available, either by being built into
   the kernel, or available as a module, then boot up UML and log in.  If
@@ -2096,7 +2096,7 @@
 
 
 
-  99..  HHoosstt ffiillee aacccceessss
+  9.  Host file access
 
 
   If you want to access files on the host machine from inside UML, you
@@ -2112,7 +2112,7 @@
   files contained in it just as you would on the host.
 
 
-  99..11..  UUssiinngg hhoossttffss
+  9.1.  Using hostfs
 
   To begin with, make sure that hostfs is available inside the virtual
   machine with
@@ -2151,7 +2151,7 @@
 
 
 
-  99..22..  hhoossttffss aass tthhee rroooott ffiilleessyysstteemm
+  9.2.  hostfs as the root filesystem
 
   It's possible to boot from a directory hierarchy on the host using
   hostfs rather than using the standard filesystem in a file.
@@ -2194,20 +2194,20 @@
   UML should then boot as it does normally.
 
 
-  99..33..  BBuuiillddiinngg hhoossttffss
+  9.3.  Building hostfs
 
   If you need to build hostfs because it's not in your kernel, you have
   two choices:
 
 
 
-  +o  Compiling hostfs into the kernel:
+  o  Compiling hostfs into the kernel:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
 
 
-  +o  Compiling hostfs as a module:
+  o  Compiling hostfs as a module:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
@@ -2228,7 +2228,7 @@
 
 
 
-  1100..  TThhee MMaannaaggeemmeenntt CCoonnssoollee
+  10.  The Management Console
 
 
 
@@ -2240,15 +2240,15 @@
 
   There are a number of things you can do with the mconsole interface:
 
-  +o  get the kernel version
+  o  get the kernel version
 
-  +o  add and remove devices
+  o  add and remove devices
 
-  +o  halt or reboot the machine
+  o  halt or reboot the machine
 
-  +o  Send SysRq commands
+  o  Send SysRq commands
 
-  +o  Pause and resume the UML
+  o  Pause and resume the UML
 
 
   You need the mconsole client (uml_mconsole) which is present in CVS
@@ -2300,28 +2300,28 @@
 
   You'll get a prompt, at which you can run one of these commands:
 
-  +o  version
+  o  version
 
-  +o  halt
+  o  halt
 
-  +o  reboot
+  o  reboot
 
-  +o  config
+  o  config
 
-  +o  remove
+  o  remove
 
-  +o  sysrq
+  o  sysrq
 
-  +o  help
+  o  help
 
-  +o  cad
+  o  cad
 
-  +o  stop
+  o  stop
 
-  +o  go
+  o  go
 
 
-  1100..11..  vveerrssiioonn
+  10.1.  version
 
   This takes no arguments.  It prints the UML version.
 
@@ -2342,7 +2342,7 @@
 
 
 
-  1100..22..  hhaalltt aanndd rreebboooott
+  10.2.  halt and reboot
 
   These take no arguments.  They shut the machine down immediately, with
   no syncing of disks and no clean shutdown of userspace.  So, they are
@@ -2357,7 +2357,7 @@
 
 
 
-  1100..33..  ccoonnffiigg
+  10.3.  config
 
   "config" adds a new device to the virtual machine.  Currently the ubd
   and network drivers support this.  It takes one argument, which is the
@@ -2378,7 +2378,7 @@
 
 
 
-  1100..44..  rreemmoovvee
+  10.4.  remove
 
   "remove" deletes a device from the system.  Its argument is just the
   name of the device to be removed. The device must be idle in whatever
@@ -2397,7 +2397,7 @@
 
 
 
-  1100..55..  ssyyssrrqq
+  10.5.  sysrq
 
   This takes one argument, which is a single letter.  It calls the
   generic kernel's SysRq driver, which does whatever is called for by
@@ -2407,14 +2407,14 @@
 
 
 
-  1100..66..  hheellpp
+  10.6.  help
 
   "help" returns a string listing the valid commands and what each one
   does.
 
 
 
-  1100..77..  ccaadd
+  10.7.  cad
 
   This invokes the Ctl-Alt-Del action on init.  What exactly this ends
   up doing is up to /etc/inittab.  Normally, it reboots the machine.
@@ -2432,7 +2432,7 @@
 
 
 
-  1100..88..  ssttoopp
+  10.8.  stop
 
   This puts the UML in a loop reading mconsole requests until a 'go'
   mconsole command is received. This is very useful for making backups
@@ -2448,7 +2448,7 @@
 
 
 
-  1100..99..  ggoo
+  10.9.  go
 
   This resumes a UML after being paused by a 'stop' command. Note that
   when the UML has resumed, TCP connections may have timed out and if
@@ -2462,10 +2462,10 @@
 
 
 
-  1111..  KKeerrnneell ddeebbuuggggiinngg
+  11.  Kernel debugging
 
 
-  NNoottee:: The interface that makes debugging, as described here, possible
+  Note: The interface that makes debugging, as described here, possible
   is present in 2.4.0-test6 kernels and later.
 
 
@@ -2485,7 +2485,7 @@
 
 
 
-  1111..11..  SSttaarrttiinngg tthhee kkeerrnneell uunnddeerr ggddbb
+  11.1.  Starting the kernel under gdb
 
   You can have the kernel running under the control of gdb from the
   beginning by putting 'debug' on the command line.  You will get an
@@ -2498,7 +2498,7 @@
   There is a transcript of a debugging session  here <debug-
   session.html> , with breakpoints being set in the scheduler and in an
   interrupt handler.
-  1111..22..  EExxaammiinniinngg sslleeeeppiinngg pprroocceesssseess
+  11.2.  Examining sleeping processes
 
   Not every bug is evident in the currently running process.  Sometimes,
   processes hang in the kernel when they shouldn't because they've
@@ -2516,7 +2516,7 @@
 
   Now what you do is this:
 
-  +o  detach from the current thread
+  o  detach from the current thread
 
 
        (UML gdb)  det
@@ -2525,7 +2525,7 @@
 
 
 
-  +o  attach to the thread you are interested in
+  o  attach to the thread you are interested in
 
 
        (UML gdb)  att <host pid>
@@ -2534,7 +2534,7 @@
 
 
 
-  +o  look at its stack and anything else of interest
+  o  look at its stack and anything else of interest
 
 
        (UML gdb)  bt
@@ -2545,7 +2545,7 @@
   Note that you can't do anything at this point that requires that a
   process execute, e.g. calling a function
 
-  +o  when you're done looking at that process, reattach to the current
+  o  when you're done looking at that process, reattach to the current
      thread and continue it
 
 
@@ -2569,12 +2569,12 @@
 
 
 
-  1111..33..  RRuunnnniinngg dddddd oonn UUMMLL
+  11.3.  Running ddd on UML
 
   ddd works on UML, but requires a special kludge.  The process goes
   like this:
 
-  +o  Start ddd
+  o  Start ddd
 
 
        host% ddd linux
@@ -2583,14 +2583,14 @@
 
 
 
-  +o  With ps, get the pid of the gdb that ddd started.  You can ask the
+  o  With ps, get the pid of the gdb that ddd started.  You can ask the
      gdb to tell you, but for some reason that confuses things and
      causes a hang.
 
-  +o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
      - it will just sit there after you hit return
 
-  +o  type 'att 1' to the ddd gdb and you will see something like
+  o  type 'att 1' to the ddd gdb and you will see something like
 
 
        0xa013dc51 in __kill ()
@@ -2602,12 +2602,12 @@
 
 
 
-  +o  At this point, type 'c', UML will boot up, and you can use ddd just
+  o  At this point, type 'c', UML will boot up, and you can use ddd just
      as you do on any other process.
 
 
 
-  1111..44..  DDeebbuuggggiinngg mmoodduulleess
+  11.4.  Debugging modules
 
   gdb has support for debugging code which is dynamically loaded into
   the process.  This support is what is needed to debug kernel modules
@@ -2823,7 +2823,7 @@
 
 
 
-  1111..55..  AAttttaacchhiinngg ggddbb ttoo tthhee kkeerrnneell
+  11.5.  Attaching gdb to the kernel
 
   If you don't have the kernel running under gdb, you can attach gdb to
   it later by sending the tracing thread a SIGUSR1.  The first line of
@@ -2857,7 +2857,7 @@
 
 
 
-  1111..66..  UUssiinngg aalltteerrnnaattee ddeebbuuggggeerrss
+  11.6.  Using alternate debuggers
 
   UML has support for attaching to an already running debugger rather
   than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
@@ -2886,7 +2886,7 @@
   An example of an alternate debugger is strace.  You can strace the
   actual kernel as follows:
 
-  +o  Run the following in a shell
+  o  Run the following in a shell
 
 
        host%
@@ -2894,10 +2894,10 @@
 
 
 
-  +o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
      by the previous command
 
-  +o  Hit return in the shell, and UML will start running, and strace
+  o  Hit return in the shell, and UML will start running, and strace
      output will start accumulating in the output file.
 
      Note that this is different from running
@@ -2917,9 +2917,9 @@
 
 
 
-  1122..  KKeerrnneell ddeebbuuggggiinngg eexxaammpplleess
+  12.  Kernel debugging examples
 
-  1122..11..  TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.1.  The case of the hung fsck
 
   When booting up the kernel, fsck failed, and dropped me into a shell
   to fix things up.  I ran fsck -y, which hung:
@@ -3154,9 +3154,9 @@
 
   The interesting things here are :
 
-  +o  There are two segfaults on this stack (frames 9 and 14)
+  o  There are two segfaults on this stack (frames 9 and 14)
 
-  +o  The first faulting address (frame 11) is 0x50000800
+  o  The first faulting address (frame 11) is 0x50000800
 
   (gdb) p (void *)1342179328
   $16 = (void *) 0x50000800
@@ -3399,7 +3399,7 @@
   on will be somewhat clearer.
 
 
-  1122..22..  EEppiissooddee 22:: TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.2.  Episode 2: The case of the hung fsck
 
   After setting a trap in the SEGV handler for accesses to the signal
   thread's stack, I reran the kernel.
@@ -3788,12 +3788,12 @@
 
 
 
-  1133..  WWhhaatt ttoo ddoo wwhheenn UUMMLL ddooeessnn''tt wwoorrkk
+  13.  What to do when UML doesn't work
 
 
 
 
-  1133..11..  SSttrraannggee ccoommppiillaattiioonn eerrrroorrss wwhheenn yyoouu bbuuiilldd ffrroomm ssoouurrccee
+  13.1.  Strange compilation errors when you build from source
 
   As of test11, it is necessary to have "ARCH=um" in the environment or
   on the make command line for all steps in building UML, including
@@ -3824,8 +3824,8 @@
 
 
 
-  1133..33..  AA vvaarriieettyy ooff ppaanniiccss aanndd hhaannggss wwiitthh //ttmmpp oonn aa rreeiisseerrffss  ffiilleessyyss--
-  tteemm
+  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
+  tem
 
   I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
   Panics preceded by
@@ -3842,8 +3842,8 @@
 
 
 
-  1133..44..  TThhee ccoommppiillee ffaaiillss wwiitthh eerrrroorrss aabboouutt ccoonnfflliiccttiinngg ttyyppeess ffoorr
-  ''ooppeenn'',, ''dduupp'',, aanndd ''wwaaiittppiidd''
+  13.4.  The compile fails with errors about conflicting types for
+  'open', 'dup', and 'waitpid'
 
   This happens when you build in /usr/src/linux.  The UML build makes
   the include/asm link point to include/asm-um.  /usr/include/asm points
@@ -3854,14 +3854,14 @@
 
 
 
-  1133..55..  UUMMLL ddooeessnn''tt wwoorrkk wwhheenn //ttmmpp iiss aann NNFFSS ffiilleessyysstteemm
+  13.5.  UML doesn't work when /tmp is an NFS filesystem
 
   This seems to be a similar situation with the ReiserFS problem above.
   Some versions of NFS seems not to handle mmap correctly, which UML
   depends on.  The workaround is have /tmp be a non-NFS directory.
 
 
-  1133..66..  UUMMLL hhaannggss oonn bboooott wwhheenn ccoommppiilleedd wwiitthh ggpprrooff ssuuppppoorrtt
+  13.6.  UML hangs on boot when compiled with gprof support
 
   If you build UML with gprof support and, early in the boot, it does
   this
@@ -3878,7 +3878,7 @@
 
 
 
-  1133..77..  ssyyssllooggdd ddiieess wwiitthh aa SSIIGGTTEERRMM oonn ssttaarrttuupp
+  13.7.  syslogd dies with a SIGTERM on startup
 
   The exact boot error depends on the distribution that you're booting,
   but Debian produces this:
@@ -3897,17 +3897,17 @@
 
 
 
-  1133..88..  TTUUNN//TTAAPP nneettwwoorrkkiinngg ddooeessnn''tt wwoorrkk oonn aa 22..44 hhoosstt
+  13.8.  TUN/TAP networking doesn't work on a 2.4 host
 
   There are a couple of problems which were
   <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
   out">  by Tim Robinson <timro at trkr dot net>
 
-  +o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
      The fix is to upgrade to something more recent and then read the
      next item.
 
-  +o  If you see
+  o  If you see
 
 
        File descriptor in bad state
@@ -3921,8 +3921,8 @@
 
 
 
-  1133..99..  YYoouu ccaann nneettwwoorrkk ttoo tthhee hhoosstt bbuutt nnoott ttoo ootthheerr mmaacchhiinneess oonn tthhee
-  nneett
+  13.9.  You can network to the host but not to other machines on the
+  net
 
   If you can connect to the host, and the host can connect to UML, but
   you cannot connect to any other machines, then you may need to enable
@@ -3972,7 +3972,7 @@
 
 
 
-  1133..1100..  II hhaavvee nnoo rroooott aanndd II wwaanntt ttoo ssccrreeaamm
+  13.10.  I have no root and I want to scream
 
   Thanks to Birgit Wahlich for telling me about this strange one.  It
   turns out that there's a limit of six environment variables on the
@@ -3987,7 +3987,7 @@
 
 
 
-  1133..1111..  UUMMLL bbuuiilldd ccoonnfflliicctt bbeettwweeeenn ppttrraaccee..hh aanndd uuccoonntteexxtt..hh
+  13.11.  UML build conflict between ptrace.h and ucontext.h
 
   On some older systems, /usr/include/asm/ptrace.h and
   /usr/include/sys/ucontext.h define the same names.  So, when they're
@@ -4007,7 +4007,7 @@
 
 
 
-  1133..1122..  TThhee UUMMLL BBooggooMMiippss iiss eexxaaccttllyy hhaallff tthhee hhoosstt''ss BBooggooMMiippss
+  13.12.  The UML BogoMips is exactly half the host's BogoMips
 
   On i386 kernels, there are two ways of running the loop that is used
   to calculate the BogoMips rating, using the TSC if it's there or using
@@ -4019,7 +4019,7 @@
 
 
 
-  1133..1133..  WWhheenn yyoouu rruunn UUMMLL,, iitt iimmmmeeddiiaatteellyy sseeggffaauullttss
+  13.13.  When you run UML, it immediately segfaults
 
   If the host is configured with the 2G/2G address space split, that's
   why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
@@ -4027,7 +4027,7 @@
 
 
 
-  1133..1144..  xxtteerrmmss aappppeeaarr,, tthheenn iimmmmeeddiiaatteellyy ddiissaappppeeaarr
+  13.14.  xterms appear, then immediately disappear
 
   If you're running an up to date kernel with an old release of
   uml_utilities, the port-helper program will not work properly, so
@@ -4039,7 +4039,7 @@
 
 
 
-  1133..1155..  AAnnyy ootthheerr ppaanniicc,, hhaanngg,, oorr ssttrraannggee bbeehhaavviioorr
+  13.15.  Any other panic, hang, or strange behavior
 
   If you're seeing truly strange behavior, such as hangs or panics that
   happen in random places, or you try running the debugger to see what's
@@ -4059,7 +4059,7 @@
 
   If you want to be super-helpful, read ``Diagnosing Problems'' and
   follow the instructions contained therein.
-  1144..  DDiiaaggnnoossiinngg PPrroobblleemmss
+  14.  Diagnosing Problems
 
 
   If you get UML to crash, hang, or otherwise misbehave, you should
@@ -4078,7 +4078,7 @@
   ``Kernel debugging''  UML first.
 
 
-  1144..11..  CCaassee 11 :: NNoorrmmaall kkeerrnneell ppaanniiccss
+  14.1.  Case 1 : Normal kernel panics
 
   The most common case is for a normal thread to panic.  To debug this,
   you will need to run it under the debugger (add 'debug' to the command
@@ -4128,7 +4128,7 @@
   to get that information from the faulting ip.
 
 
-  1144..22..  CCaassee 22 :: TTrraacciinngg tthhrreeaadd ppaanniiccss
+  14.2.  Case 2 : Tracing thread panics
 
   The less common and more painful case is when the tracing thread
   panics.  In this case, the kernel debugger will be useless because it
@@ -4161,7 +4161,7 @@
   backtrace in and wait for our crack debugging team to fix the problem.
 
 
-  1144..33..  CCaassee 33 :: TTrraacciinngg tthhrreeaadd ppaanniiccss ccaauusseedd bbyy ootthheerr tthhrreeaaddss
+  14.3.  Case 3 : Tracing thread panics caused by other threads
 
   However, there are cases where the misbehavior of another thread
   caused the problem.  The most common panic of this type is:
@@ -4227,7 +4227,7 @@
 
 
 
-  1144..44..  CCaassee 44 :: HHaannggss
+  14.4.  Case 4 : Hangs
 
   Hangs seem to be fairly rare, but they sometimes happen.  When a hang
   happens, we need a backtrace from the offending process.  Run the
@@ -4257,7 +4257,7 @@
 
 
 
-  1155..  TThhaannkkss
+  15.  Thanks
 
 
   A number of people have helped this project in various ways, and this
@@ -4274,20 +4274,20 @@
   bookkeeping lapses and I forget about contributions.
 
 
-  1155..11..  CCooddee aanndd DDooccuummeennttaattiioonn
+  15.1.  Code and Documentation
 
   Rusty Russell <rusty at linuxcare.com.au>  -
 
-  +o  wrote the  HOWTO <http://user-mode-
+  o  wrote the  HOWTO <http://user-mode-
      linux.sourceforge.net/UserModeLinux-HOWTO.html>
 
-  +o  prodded me into making this project official and putting it on
+  o  prodded me into making this project official and putting it on
      SourceForge
 
-  +o  came up with the way cool UML logo <http://user-mode-
+  o  came up with the way cool UML logo <http://user-mode-
      linux.sourceforge.net/uml-small.png>
 
-  +o  redid the config process
+  o  redid the config process
 
 
   Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
@@ -4296,18 +4296,18 @@
 
   Bill Stearns <wstearns at pobox.com>  -
 
-  +o  HOWTO updates
+  o  HOWTO updates
 
-  +o  lots of bug reports
+  o  lots of bug reports
 
-  +o  lots of testing
+  o  lots of testing
 
-  +o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
+  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
 
-  +o  wrote the mkrootfs script, which allows bootable filesystems of
+  o  wrote the mkrootfs script, which allows bootable filesystems of
      RPM-based distributions to be cranked out
 
-  +o  cranked out a large number of filesystems with said script
+  o  cranked out a large number of filesystems with said script
 
 
   Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
@@ -4375,176 +4375,176 @@
 
   David Coulson <http://davidcoulson.net>  -
 
-  +o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
+  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
      which is a great way of keeping the UML user community on top of
      UML goings-on.
 
-  +o  Site documentation and updates
+  o  Site documentation and updates
 
-  +o  Nifty little UML management daemon  UMLd
+  o  Nifty little UML management daemon  UMLd
      <http://uml.openconsultancy.com/umld/>
 
-  +o  Lots of testing and bug reports
+  o  Lots of testing and bug reports
 
 
 
 
-  1155..22..  FFlluusshhiinngg oouutt bbuuggss
+  15.2.  Flushing out bugs
 
 
 
-  +o  Yuri Pudgorodsky
+  o  Yuri Pudgorodsky
 
-  +o  Gerald Britton
+  o  Gerald Britton
 
-  +o  Ian Wehrman
+  o  Ian Wehrman
 
-  +o  Gord Lamb
+  o  Gord Lamb
 
-  +o  Eugene Koontz
+  o  Eugene Koontz
 
-  +o  John H. Hartman
+  o  John H. Hartman
 
-  +o  Anders Karlsson
+  o  Anders Karlsson
 
-  +o  Daniel Phillips
+  o  Daniel Phillips
 
-  +o  John Fremlin
+  o  John Fremlin
 
-  +o  Rainer Burgstaller
+  o  Rainer Burgstaller
 
-  +o  James Stevenson
+  o  James Stevenson
 
-  +o  Matt Clay
+  o  Matt Clay
 
-  +o  Cliff Jefferies
+  o  Cliff Jefferies
 
-  +o  Geoff Hoff
+  o  Geoff Hoff
 
-  +o  Lennert Buytenhek
+  o  Lennert Buytenhek
 
-  +o  Al Viro
+  o  Al Viro
 
-  +o  Frank Klingenhoefer
+  o  Frank Klingenhoefer
 
-  +o  Livio Baldini Soares
+  o  Livio Baldini Soares
 
-  +o  Jon Burgess
+  o  Jon Burgess
 
-  +o  Petru Paler
+  o  Petru Paler
 
-  +o  Paul
+  o  Paul
 
-  +o  Chris Reahard
+  o  Chris Reahard
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  Gong Su
+  o  Gong Su
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  Bjorn Eriksson
+  o  Bjorn Eriksson
 
-  +o  Lorenzo Allegrucci
+  o  Lorenzo Allegrucci
 
-  +o  Muli Ben-Yehuda
+  o  Muli Ben-Yehuda
 
-  +o  David Mansfield
+  o  David Mansfield
 
-  +o  Howard Goff
+  o  Howard Goff
 
-  +o  Mike Anderson
+  o  Mike Anderson
 
-  +o  John Byrne
+  o  John Byrne
 
-  +o  Sapan J. Batia
+  o  Sapan J. Batia
 
-  +o  Iris Huang
+  o  Iris Huang
 
-  +o  Jan Hudec
+  o  Jan Hudec
 
-  +o  Voluspa
+  o  Voluspa
 
 
 
 
-  1155..33..  BBuugglleettss aanndd cclleeaann--uuppss
+  15.3.  Buglets and clean-ups
 
 
 
-  +o  Dave Zarzycki
+  o  Dave Zarzycki
 
-  +o  Adam Lazur
+  o  Adam Lazur
 
-  +o  Boria Feigin
+  o  Boria Feigin
 
-  +o  Brian J. Murrell
+  o  Brian J. Murrell
 
-  +o  JS
+  o  JS
 
-  +o  Roman Zippel
+  o  Roman Zippel
 
-  +o  Wil Cooley
+  o  Wil Cooley
 
-  +o  Ayelet Shemesh
+  o  Ayelet Shemesh
 
-  +o  Will Dyson
+  o  Will Dyson
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  dvorak
+  o  dvorak
 
-  +o  v.naga srinivas
+  o  v.naga srinivas
 
-  +o  Shlomi Fish
+  o  Shlomi Fish
 
-  +o  Roger Binns
+  o  Roger Binns
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  MrChuoi
+  o  MrChuoi
 
-  +o  Peter Cleve
+  o  Peter Cleve
 
-  +o  Vincent Guffens
+  o  Vincent Guffens
 
-  +o  Nathan Scott
+  o  Nathan Scott
 
-  +o  Patrick Caulfield
+  o  Patrick Caulfield
 
-  +o  jbearce
+  o  jbearce
 
-  +o  Catalin Marinas
+  o  Catalin Marinas
 
-  +o  Shane Spencer
+  o  Shane Spencer
 
-  +o  Zou Min
+  o  Zou Min
 
 
-  +o  Ryan Boder
+  o  Ryan Boder
 
-  +o  Lorenzo Colitti
+  o  Lorenzo Colitti
 
-  +o  Gwendal Grignou
+  o  Gwendal Grignou
 
-  +o  Andre' Breiler
+  o  Andre' Breiler
 
-  +o  Tsutomu Yasuda
+  o  Tsutomu Yasuda
 
 
 
-  1155..44..  CCaassee SSttuuddiieess
+  15.4.  Case Studies
 
 
-  +o  Jon Wright
+  o  Jon Wright
 
-  +o  William McEwan
+  o  William McEwan
 
-  +o  Michael Richardson
+  o  Michael Richardson
 
 
 
-  1155..55..  OOtthheerr ccoonnttrriibbuuttiioonnss
+  15.5.  Other contributions
 
 
   Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
diff -druNp linux-libre-3.1-gnu1/Documentation/vm/00-INDEX linux-libre-3.2-gnu1/Documentation/vm/00-INDEX
--- linux-libre-3.1-gnu1/Documentation/vm/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/vm/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -30,8 +30,6 @@ page_migration
 	- description of page migration in NUMA systems.
 pagemap.txt
 	- pagemap, from the userspace perspective
-slabinfo.c
-	- source code for a tool to get reports about slabs.
 slub.txt
 	- a short users guide for SLUB.
 unevictable-lru.txt
diff -druNp linux-libre-3.1-gnu1/Documentation/vm/numa linux-libre-3.2-gnu1/Documentation/vm/numa
--- linux-libre-3.1-gnu1/Documentation/vm/numa	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/vm/numa	2012-01-04 18:55:44.000000000 -0500
@@ -109,11 +109,11 @@ to improve NUMA locality using various C
 such as taskset(1) and numactl(1), and program interfaces such as
 sched_setaffinity(2).  Further, one can modify the kernel's default local
 allocation behavior using Linux NUMA memory policy.
-[see Documentation/vm/numa_memory_policy.]
+[see Documentation/vm/numa_memory_policy.txt.]
 
 System administrators can restrict the CPUs and nodes' memories that a non-
 privileged user can specify in the scheduling or NUMA commands and functions
-using control groups and CPUsets.  [see Documentation/cgroups/CPUsets.txt]
+using control groups and CPUsets.  [see Documentation/cgroups/cpusets.txt]
 
 On architectures that do not hide memoryless nodes, Linux will include only
 zones [nodes] with memory in the zonelists.  This means that for a memoryless
diff -druNp linux-libre-3.1-gnu1/Documentation/vm/slub.txt linux-libre-3.2-gnu1/Documentation/vm/slub.txt
--- linux-libre-3.1-gnu1/Documentation/vm/slub.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/vm/slub.txt	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@ data and perform operation on the slabs.
 slabs that have data in them. See "slabinfo -h" for more options when
 running the command. slabinfo can be compiled with
 
-gcc -o slabinfo Documentation/vm/slabinfo.c
+gcc -o slabinfo tools/slub/slabinfo.c
 
 Some of the modes of operation of slabinfo require that slub debugging
 be enabled on the command line. F.e. no tracking information will be
diff -druNp linux-libre-3.1-gnu1/Documentation/watchdog/convert_drivers_to_kernel_api.txt linux-libre-3.2-gnu1/Documentation/watchdog/convert_drivers_to_kernel_api.txt
--- linux-libre-3.1-gnu1/Documentation/watchdog/convert_drivers_to_kernel_api.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/Documentation/watchdog/convert_drivers_to_kernel_api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,195 @@
+Converting old watchdog drivers to the watchdog framework
+by Wolfram Sang <w.sang@pengutronix.de>
+=========================================================
+
+Before the watchdog framework came into the kernel, every driver had to
+implement the API on its own. Now, as the framework factored out the common
+components, those drivers can be lightened making it a user of the framework.
+This document shall guide you for this task. The necessary steps are described
+as well as things to look out for.
+
+
+Remove the file_operations struct
+---------------------------------
+
+Old drivers define their own file_operations for actions like open(), write(),
+etc... These are now handled by the framework and just call the driver when
+needed. So, in general, the 'file_operations' struct and assorted functions can
+go. Only very few driver-specific details have to be moved to other functions.
+Here is a overview of the functions and probably needed actions:
+
+- open: Everything dealing with resource management (file-open checks, magic
+  close preparations) can simply go. Device specific stuff needs to go to the
+  driver specific start-function. Note that for some drivers, the start-function
+  also serves as the ping-function. If that is the case and you need start/stop
+  to be balanced (clocks!), you are better off refactoring a separate start-function.
+
+- close: Same hints as for open apply.
+
+- write: Can simply go, all defined behaviour is taken care of by the framework,
+  i.e. ping on write and magic char ('V') handling.
+
+- ioctl: While the driver is allowed to have extensions to the IOCTL interface,
+  the most common ones are handled by the framework, supported by some assistance
+  from the driver:
+
+	WDIOC_GETSUPPORT:
+		Returns the mandatory watchdog_info struct from the driver
+
+	WDIOC_GETSTATUS:
+		Needs the status-callback defined, otherwise returns 0
+
+	WDIOC_GETBOOTSTATUS:
+		Needs the bootstatus member properly set. Make sure it is 0 if you
+		don't have further support!
+
+	WDIOC_SETOPTIONS:
+		No preparations needed
+
+	WDIOC_KEEPALIVE:
+		If wanted, options in watchdog_info need to have WDIOF_KEEPALIVEPING
+		set
+
+	WDIOC_SETTIMEOUT:
+		Options in watchdog_info need to have WDIOF_SETTIMEOUT set
+		and a set_timeout-callback has to be defined. The core will also
+		do limit-checking, if min_timeout and max_timeout in the watchdog
+		device are set. All is optional.
+
+	WDIOC_GETTIMEOUT:
+		No preparations needed
+
+  Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
+  intended for porting old drivers; new drivers should not invent private IOCTLs.
+  Private IOCTLs are processed first. When the callback returns with
+  -ENOIOCTLCMD, the IOCTLs of the framework will be tried, too. Any other error
+  is directly given to the user.
+
+Example conversion:
+
+-static const struct file_operations s3c2410wdt_fops = {
+-       .owner          = THIS_MODULE,
+-       .llseek         = no_llseek,
+-       .write          = s3c2410wdt_write,
+-       .unlocked_ioctl = s3c2410wdt_ioctl,
+-       .open           = s3c2410wdt_open,
+-       .release        = s3c2410wdt_release,
+-};
+
+Check the functions for device-specific stuff and keep it for later
+refactoring. The rest can go.
+
+
+Remove the miscdevice
+---------------------
+
+Since the file_operations are gone now, you can also remove the 'struct
+miscdevice'. The framework will create it on watchdog_dev_register() called by
+watchdog_register_device().
+
+-static struct miscdevice s3c2410wdt_miscdev = {
+-       .minor          = WATCHDOG_MINOR,
+-       .name           = "watchdog",
+-       .fops           = &s3c2410wdt_fops,
+-};
+
+
+Remove obsolete includes and defines
+------------------------------------
+
+Because of the simplifications, a few defines are probably unused now. Remove
+them. Includes can be removed, too. For example:
+
+- #include <linux/fs.h>
+- #include <linux/miscdevice.h> (if MODULE_ALIAS_MISCDEV is not used)
+- #include <linux/uaccess.h> (if no custom IOCTLs are used)
+
+
+Add the watchdog operations
+---------------------------
+
+All possible callbacks are defined in 'struct watchdog_ops'. You can find it
+explained in 'watchdog-kernel-api.txt' in this directory. start(), stop() and
+owner must be set, the rest are optional. You will easily find corresponding
+functions in the old driver. Note that you will now get a pointer to the
+watchdog_device as a parameter to these functions, so you probably have to
+change the function header. Other changes are most likely not needed, because
+here simply happens the direct hardware access. If you have device-specific
+code left from the above steps, it should be refactored into these callbacks.
+
+Here is a simple example:
+
++static struct watchdog_ops s3c2410wdt_ops = {
++       .owner = THIS_MODULE,
++       .start = s3c2410wdt_start,
++       .stop = s3c2410wdt_stop,
++       .ping = s3c2410wdt_keepalive,
++       .set_timeout = s3c2410wdt_set_heartbeat,
++};
+
+A typical function-header change looks like:
+
+-static void s3c2410wdt_keepalive(void)
++static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
+ {
+...
++
++       return 0;
+ }
+
+...
+
+-       s3c2410wdt_keepalive();
++       s3c2410wdt_keepalive(&s3c2410_wdd);
+
+
+Add the watchdog device
+-----------------------
+
+Now we need to create a 'struct watchdog_device' and populate it with the
+necessary information for the framework. The struct is also explained in detail
+in 'watchdog-kernel-api.txt' in this directory. We pass it the mandatory
+watchdog_info struct and the newly created watchdog_ops. Often, old drivers
+have their own record-keeping for things like bootstatus and timeout using
+static variables. Those have to be converted to use the members in
+watchdog_device. Note that the timeout values are unsigned int. Some drivers
+use signed int, so this has to be converted, too.
+
+Here is a simple example for a watchdog device:
+
++static struct watchdog_device s3c2410_wdd = {
++       .info = &s3c2410_wdt_ident,
++       .ops = &s3c2410wdt_ops,
++};
+
+
+Register the watchdog device
+----------------------------
+
+Replace misc_register(&miscdev) with watchdog_register_device(&watchdog_dev).
+Make sure the return value gets checked and the error message, if present,
+still fits. Also convert the unregister case.
+
+-       ret = misc_register(&s3c2410wdt_miscdev);
++       ret = watchdog_register_device(&s3c2410_wdd);
+
+...
+
+-       misc_deregister(&s3c2410wdt_miscdev);
++       watchdog_unregister_device(&s3c2410_wdd);
+
+
+Update the Kconfig-entry
+------------------------
+
+The entry for the driver now needs to select WATCHDOG_CORE:
+
++       select WATCHDOG_CORE
+
+
+Create a patch and send it to upstream
+--------------------------------------
+
+Make sure you understood Documentation/SubmittingPatches and send your patch to
+linux-watchdog@vger.kernel.org. We are looking forward to it :)
+
diff -druNp linux-libre-3.1-gnu1/Documentation/x86/entry_64.txt linux-libre-3.2-gnu1/Documentation/x86/entry_64.txt
--- linux-libre-3.1-gnu1/Documentation/x86/entry_64.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/x86/entry_64.txt	2012-01-04 18:55:44.000000000 -0500
@@ -27,9 +27,6 @@ Some of these entries are:
    magically-generated functions that make their way to do_IRQ with
    the interrupt number as a parameter.
 
- - emulate_vsyscall: int 0xcc, a special non-ABI entry used by
-   vsyscall emulation.
-
  - APIC interrupts: Various special-purpose interrupts for things
    like TLB shootdown.
 
diff -druNp linux-libre-3.1-gnu1/Documentation/zh_CN/SubmitChecklist linux-libre-3.2-gnu1/Documentation/zh_CN/SubmitChecklist
--- linux-libre-3.1-gnu1/Documentation/zh_CN/SubmitChecklist	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/Documentation/zh_CN/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-Chinese translated version of Documentation/SubmitChecklist
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
----------------------------------------------------------------------
-Documentation/SubmitChecklist µÄÖÐÎÄ·­Òë
-
-Èç¹ûÏëÆÀÂÛ»ò¸üÐÂ±¾ÎÄµÄÄÚÈÝ£¬ÇëÖ±½ÓÁªÏµÔ­ÎÄµµµÄÎ¬»¤Õß¡£Èç¹ûÄãÊ¹ÓÃÓ¢ÎÄ
-½»Á÷ÓÐÀ§ÄÑµÄ»°£¬Ò²¿ÉÒÔÏòÖÐÎÄ°æÎ¬»¤ÕßÇóÖú¡£Èç¹û±¾·­Òë¸üÐÂ²»¼°Ê±»òÕß·­
-Òë´æÔÚÎÊÌâ£¬ÇëÁªÏµÖÐÎÄ°æÎ¬»¤Õß¡£
-
-ÖÐÎÄ°æÎ¬»¤Õß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-ÖÐÎÄ°æ·­ÒëÕß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-ÖÐÎÄ°æÐ£ÒëÕß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-
-
-ÒÔÏÂÎªÕýÎÄ
----------------------------------------------------------------------
-LinuxÄÚºËÌá½»Çåµ¥
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-ÕâÀïÓÐÒ»Ð©ÄÚºË¿ª·¢ÕßÓ¦¸Ã×öµÄ»ù±¾ÊÂÇé£¬Èç¹ûËûÃÇÏë¿´µ½×Ô¼ºµÄÄÚºË²¹¶¡Ìá½»
-±»½ÓÊÜµÄ¸ü¿ì¡£
-
-ÕâÐ©¶¼ÊÇ³¬³öDocumentation/SubmittingPatchesÎÄµµÀïËùÌá¹©µÄÒÔ¼°ÆäËû
-¹ØÓÚÌá½»LinuxÄÚºË²¹¶¡µÄËµÃ÷¡£
-
-1£ºÈç¹ûÄãÊ¹ÓÃÁËÒ»¸ö¹¦ÄÜÄÇÃ´¾Í#include¶¨Òå/ÉùÃ÷ÄÇ¸ö¹¦ÄÜµÄÄÇ¸öÎÄ¼þ¡£
-   ²»ÒªÒÀ¿¿ÆäËû¼ä½ÓÒýÈë¶¨Òå/ÉùÃ÷ÄÇ¸ö¹¦ÄÜµÄÍ·ÎÄ¼þ¡£
-
-2£º¹¹½¨¼ò½àÊÊÓÃ»òÕß¸ü¸ÄCONFIGÑ¡Ïî =y£¬=m£¬»òÕß=n¡£
-   ²»ÒªÓÐ±àÒë¾¯¸æ/´íÎó£¬ ²»ÒªÓÐÁ´½Ó¾¯¸æ/´íÎó¡£
-
-2b£ºÍ¨¹ý allnoconfig, allmodconfig
-
-2c£ºµ±Ê¹ÓÃ 0=builddir ³É¹¦µØ¹¹½¨
-
-3£ºÍ¨¹ýÊ¹ÓÃ±¾µØ½»²æ±àÒë¹¤¾ß»òÕßÆäËûÒ»Ð©¹¹½¨²úËù£¬ÔÚ¶àCPU¿ò¼ÜÉÏ¹¹½¨¡£
-
-4£ºppc64 ÊÇÒ»¸öºÜºÃµÄ¼ì²é½»²æ±àÒëµÄ¿ò¼Ü£¬ÒòÎªËüÍùÍù°Ñ¡®unsigned long¡¯
-   µ±64Î»ÖµÀ´Ê¹ÓÃ¡£
-
-5£º°´ÕÕDocumentation/CodingStyleÎÄ¼þÀïµÄÏêÏ¸ÃèÊö£¬¼ì²éÄã²¹¶¡µÄÕûÌå·ç¸ñ¡£
-   Ê¹ÓÃ²¹¶¡·ç¸ñ¼ì²éËöËéµÄÎ¥¹æ(scripts/checkpatch.pl)£¬ÉóºËÔ±ÓÅÏÈÌá½»¡£
-   ÄãÓ¦¸Ãµ÷ÕûÒÅÁôÔÚÄã²¹¶¡ÖÐµÄËùÓÐÎ¥¹æ¡£
-
-6£ºÈÎºÎ¸üÐÂ»òÕß¸Ä¶¯CONFIGÑ¡Ïî¶¼²»ÄÜ´òÂÒÅäÖÃ²Ëµ¥¡£
-
-7£ºËùÓÐµÄKconfigÑ¡Ïî¸üÐÂ¶¼ÒªÓÐËµÃ÷ÎÄ×Ö¡£
-
-8£ºÒÑ¾­ÈÏÕæµØ×Ü½áÁËÏà¹ØµÄKconfig×éºÏ¡£ÕâÊÇºÜÄÑÍ¨¹ý²âÊÔ×öºÃµÄ--ÄÔÁ¦ÔÚÕâÀïÏÂ½µ¡£
-
-9£º¼ì²é¾ßÓÐ¼ò½àÐÔ¡£
-
-10£ºÊ¹ÓÃ'make checkstack'ºÍ'make namespacecheck'¼ì²é£¬È»ºóÐÞ¸ÄËùÕÒµ½µÄÎÊÌâ¡£
-    ×¢Òâ£º¶ÑÕ»¼ì²é²»»áÃ÷È·µØ³öÏÖÎÊÌâ£¬µ«ÊÇÈÎºÎµÄÒ»¸öº¯ÊýÔÚ¶ÑÕ»ÉÏÊ¹ÓÃ¶àÓÚ512×Ö½Ú
-    ¶¼Òª×¼±¸ÐÞ¸Ä¡£
-
-11£º°üº¬kernel-docµ½È«¾ÖÄÚºËAPIsÎÄ¼þ¡££¨²»ÒªÇó¾²Ì¬µÄº¯Êý£¬µ«ÊÇ°üº¬Ò²ÎÞËùÎ½¡££©
-    Ê¹ÓÃ'make htmldocs'»òÕß'make mandocs'À´¼ì²ékernel-doc£¬È»ºóÐÞ¸ÄÈÎºÎ
-    ·¢ÏÖµÄÎÊÌâ¡£
-
-12£ºÒÑ¾­Í¨¹ýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
-    CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
-    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP²âÊÔ£¬²¢ÇÒÍ¬Ê±¶¼
-    Ê¹ÄÜ¡£
-
-13£ºÒÑ¾­¶¼¹¹½¨²¢ÇÒÊ¹ÓÃ»òÕß²»Ê¹ÓÃ CONFIG_SMP ºÍ CONFIG_PREEMPT²âÊÔÖ´ÐÐÊ±¼ä¡£
-
-14£ºÈç¹û²¹¶¡Ó°ÏìIO/Disk£¬µÈµÈ£ºÒÑ¾­Í¨¹ýÊ¹ÓÃ»òÕß²»Ê¹ÓÃ CONFIG_LBDAF ²âÊÔ¡£
-
-15£ºËùÓÐµÄcodepathsÒÑ¾­ÐÐÊ¹ËùÓÐlockdepÆôÓÃ¹¦ÄÜ¡£
-
-16£ºËùÓÐµÄ/proc¼ÇÂ¼¸üÐÂ¶¼Òª×÷³ÉÎÄ¼þ·ÅÔÚDocumentation/Ä¿Â¼ÏÂ¡£
-
-17£ºËùÓÐµÄÄÚºËÆô¶¯²ÎÊý¸üÐÂ¶¼±»¼ÇÂ¼µ½Documentation/kernel-parameters.txtÎÄ¼þÖÐ¡£
-
-18£ºËùÓÐµÄÄ£¿é²ÎÊý¸üÐÂ¶¼ÓÃMODULE_PARM_DESC()¼ÇÂ¼¡£
-
-19£ºËùÓÐµÄÓÃ»§¿Õ¼ä½Ó¿Ú¸üÐÂ¶¼±»¼ÇÂ¼µ½Documentation/ABI/¡£²é¿´Documentation/ABI/README
-    ¿ÉÒÔ»ñµÃ¸ü¶àµÄÐÅÏ¢¡£¸Ä±äÓÃ»§¿Õ¼ä½Ó¿ÚµÄ²¹¶¡Ó¦¸Ã±»ÓÊ¼þ³­ËÍ¸ølinux-api@vger.kernel.org¡£
-
-20£º¼ì²éËüÊÇ²»ÊÇ¶¼Í¨¹ý`make headers_check'¡£
-
-21£ºÒÑ¾­Í¨¹ýÖÁÉÙÒýÈëslabºÍpage-allocationÊ§°Ü¼ì²é¡£²é¿´Documentation/fault-injection/¡£
-
-22£ºÐÂ¼ÓÈëµÄÔ´ÂëÒÑ¾­Í¨¹ý`gcc -W'£¨Ê¹ÓÃ"make EXTRA_CFLAGS=-W"£©±àÒë¡£ÕâÑù½«²úÉúºÜ¶à·³ÄÕ£¬
-    µ«ÊÇ¶ÔÓÚÑ°ÕÒÂ©¶´ºÜÓÐÒæ´¦£¬ÀýÈç:"warning: comparison between signed and unsigned"¡£
-
-23£ºµ±Ëü±»ºÏ²¢µ½-mm²¹¶¡¼¯ºóÔÙ²âÊÔ£¬ÓÃÀ´È·¶¨ËüÊÇ·ñ»¹ºÍ²¹¶¡¶ÓÁÐÖÐµÄÆäËû²¹¶¡Ò»Æð¹¤×÷ÒÔ¼°ÔÚVM£¬VFS
-    ºÍÆäËû×ÓÏµÍ³ÖÐ¸÷¸ö±ä»¯¡£
-
-24£ºËùÓÐµÄÄÚ´æÆÁÕÏ{e.g., barrier(), rmb(), wmb()}ÐèÒªÔÚÔ´´úÂëÖÐµÄÒ»¸ö×¢ÊÍÀ´½âÊÍËûÃÇ¶¼ÊÇ¸ÉÊ²Ã´µÄ
-    ÒÔ¼°Ô­Òò¡£
-
-25£ºÈç¹ûÓÐÈÎºÎÊäÈëÊä³ö¿ØÖÆµÄ²¹¶¡±»Ìí¼Ó£¬Ò²Òª¸üÐÂDocumentation/ioctl/ioctl-number.txt¡£
-
-26£ºÈç¹ûÄãµÄ¸ü¸Ä´úÂëÒÀ¿¿»òÕßÊ¹ÓÃÈÎºÎµÄÄÚºËAPIs»òÕßÓëÏÂÃæµÄkconfig·ûºÅÓÐ¹ØÏµµÄ¹¦ÄÜ£¬Äã¾ÍÒª
-    Ê¹ÓÃÏà¹ØµÄkconfig·ûºÅ¹Ø±Õ£¬ and/or =m£¨Èç¹ûÑ¡ÏîÌá¹©£©[ÔÚÍ¬Ò»Ê±¼ä²»ÊÇËùÓÃµÄ¶¼ÆôÓÃ£¬½ö½ö¸÷¸ö»òÕß×ÔÓÉ
-    ×éºÏËûÃÇ]£º
-
-    CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
-    CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
-    CONFIG_NET, CONFIG_INET=n (ºóÒ»¸öÊ¹ÓÃ CONFIG_NET=y)
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/evxface.c linux-libre-3.2-gnu1/drivers/acpi/acpica/evxface.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/evxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/evxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfevnt.c linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfevnt.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfevnt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfevnt.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "actables.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfgpe.c linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfgpe.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfgpe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfgpe.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfregn.c linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfregn.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/evxfregn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/evxfregn.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/hwregs.c linux-libre-3.2-gnu1/drivers/acpi/acpica/hwregs.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/hwregs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/hwregs.c	2012-01-04 18:55:44.000000000 -0500
@@ -269,16 +269,17 @@ acpi_status acpi_hw_clear_acpi_status(vo
 
 	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
 					ACPI_BITMASK_ALL_FIXED_STATUS);
-	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
-	}
+
+	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+
+	if (ACPI_FAILURE(status))
+		goto exit;
 
 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 
-      unlock_and_exit:
-	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+exit:
 	return_ACPI_STATUS(status);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/hwsleep.c linux-libre-3.2-gnu1/drivers/acpi/acpica/hwsleep.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/hwsleep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/hwsleep.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include "accommon.h"
 #include "actables.h"
 #include <linux/tboot.h>
+#include <linux/module.h>
 
 #define _COMPONENT          ACPI_HARDWARE
 ACPI_MODULE_NAME("hwsleep")
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/hwtimer.c linux-libre-3.2-gnu1/drivers/acpi/acpica/hwtimer.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/hwtimer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/hwtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/hwxface.c linux-libre-3.2-gnu1/drivers/acpi/acpica/hwxface.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/hwxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/hwxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfeval.c linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfeval.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfeval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfeval.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfname.c linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfname.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfname.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfname.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfobj.c linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfobj.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/nsxfobj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/nsxfobj.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/rsxface.c linux-libre-3.2-gnu1/drivers/acpi/acpica/rsxface.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/rsxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/rsxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acresrc.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/tbxface.c linux-libre-3.2-gnu1/drivers/acpi/acpica/tbxface.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/tbxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/tbxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/utdebug.c linux-libre-3.2-gnu1/drivers/acpi/acpica/utdebug.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/utdebug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/utdebug.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/utdecode.c linux-libre-3.2-gnu1/drivers/acpi/acpica/utdecode.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/utdecode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/utdecode.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/utglobal.c linux-libre-3.2-gnu1/drivers/acpi/acpica/utglobal.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/utglobal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/utglobal.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 
 #define DEFINE_ACPI_GLOBALS
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/utxface.c linux-libre-3.2-gnu1/drivers/acpi/acpica/utxface.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/utxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/utxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/acpica/utxferror.c linux-libre-3.2-gnu1/drivers/acpi/acpica/utxferror.c
--- linux-libre-3.1-gnu1/drivers/acpi/acpica/utxferror.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/acpica/utxferror.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/apei/erst.c linux-libre-3.2-gnu1/drivers/acpi/apei/erst.c
--- linux-libre-3.1-gnu1/drivers/acpi/apei/erst.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/apei/erst.c	2012-01-04 18:55:44.000000000 -0500
@@ -932,8 +932,9 @@ static int erst_check_table(struct acpi_
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-			   struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+			   struct timespec *time, char **buf,
+			   struct pstore_info *psi);
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
@@ -986,17 +987,23 @@ static int erst_close_pstore(struct psto
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-			   struct timespec *time, struct pstore_info *psi)
+			   struct timespec *time, char **buf,
+			   struct pstore_info *psi)
 {
 	int rc;
 	ssize_t len = 0;
 	u64 record_id;
-	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
-					(erst_info.buf - sizeof(*rcd));
+	struct cper_pstore_record *rcd;
+	size_t rcd_len = sizeof(*rcd) + erst_info.bufsize;
 
 	if (erst_disable)
 		return -ENODEV;
 
+	rcd = kmalloc(rcd_len, GFP_KERNEL);
+	if (!rcd) {
+		rc = -ENOMEM;
+		goto out;
+	}
 skip:
 	rc = erst_get_record_id_next(&reader_pos, &record_id);
 	if (rc)
@@ -1004,22 +1011,27 @@ skip:
 
 	/* no more record */
 	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-		rc = -1;
+		rc = -EINVAL;
 		goto out;
 	}
 
-	len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
-			erst_info.bufsize);
+	len = erst_read(record_id, &rcd->hdr, rcd_len);
 	/* The record may be cleared by others, try read next record */
 	if (len == -ENOENT)
 		goto skip;
-	else if (len < 0) {
-		rc = -1;
+	else if (len < sizeof(*rcd)) {
+		rc = -EIO;
 		goto out;
 	}
 	if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
 		goto skip;
 
+	*buf = kmalloc(len, GFP_KERNEL);
+	if (*buf == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memcpy(*buf, rcd->data, len - sizeof(*rcd));
 	*id = record_id;
 	if (uuid_le_cmp(rcd->sec_hdr.section_type,
 			CPER_SECTION_TYPE_DMESG) == 0)
@@ -1037,14 +1049,16 @@ skip:
 	time->tv_nsec = 0;
 
 out:
+	kfree(rcd);
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
 					(erst_info.buf - sizeof(*rcd));
+	int ret;
 
 	memset(rcd, 0, sizeof(*rcd));
 	memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
@@ -1079,9 +1093,10 @@ static u64 erst_writer(enum pstore_type_
 	}
 	rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
 
-	erst_write(&rcd->hdr);
+	ret = erst_write(&rcd->hdr);
+	*id = rcd->hdr.record_id;
 
-	return rcd->hdr.record_id;
+	return ret;
 }
 
 static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -1165,7 +1180,7 @@ static int __init erst_init(void)
 		goto err_release_erange;
 
 	buf = kmalloc(erst_erange.size, GFP_KERNEL);
-	mutex_init(&erst_info.buf_mutex);
+	spin_lock_init(&erst_info.buf_lock);
 	if (buf) {
 		erst_info.buf = buf + sizeof(struct cper_pstore_record);
 		erst_info.bufsize = erst_erange.size -
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/apei/ghes.c linux-libre-3.2-gnu1/drivers/acpi/apei/ghes.c
--- linux-libre-3.1-gnu1/drivers/acpi/apei/ghes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/apei/ghes.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@
 #include <acpi/hed.h>
 #include <asm/mce.h>
 #include <asm/tlbflush.h>
+#include <asm/nmi.h>
 
 #include "apei-internal.h"
 
@@ -749,15 +750,11 @@ static void ghes_proc_in_irq(struct irq_
 	}
 }
 
-static int ghes_notify_nmi(struct notifier_block *this,
-				  unsigned long cmd, void *data)
+static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
 {
 	struct ghes *ghes, *ghes_global = NULL;
 	int sev, sev_global = -1;
-	int ret = NOTIFY_DONE;
-
-	if (cmd != DIE_NMI)
-		return ret;
+	int ret = NMI_DONE;
 
 	raw_spin_lock(&ghes_nmi_lock);
 	list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
@@ -770,10 +767,10 @@ static int ghes_notify_nmi(struct notifi
 			sev_global = sev;
 			ghes_global = ghes;
 		}
-		ret = NOTIFY_STOP;
+		ret = NMI_HANDLED;
 	}
 
-	if (ret == NOTIFY_DONE)
+	if (ret == NMI_DONE)
 		goto out;
 
 	if (sev_global >= GHES_SEV_PANIC) {
@@ -825,10 +822,6 @@ static struct notifier_block ghes_notifi
 	.notifier_call = ghes_notify_sci,
 };
 
-static struct notifier_block ghes_notifier_nmi = {
-	.notifier_call = ghes_notify_nmi,
-};
-
 static unsigned long ghes_esource_prealloc_size(
 	const struct acpi_hest_generic *generic)
 {
@@ -918,7 +911,8 @@ static int __devinit ghes_probe(struct p
 		ghes_estatus_pool_expand(len);
 		mutex_lock(&ghes_list_mutex);
 		if (list_empty(&ghes_nmi))
-			register_die_notifier(&ghes_notifier_nmi);
+			register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
+						"ghes");
 		list_add_rcu(&ghes->list, &ghes_nmi);
 		mutex_unlock(&ghes_list_mutex);
 		break;
@@ -964,7 +958,7 @@ static int __devexit ghes_remove(struct
 		mutex_lock(&ghes_list_mutex);
 		list_del_rcu(&ghes->list);
 		if (list_empty(&ghes_nmi))
-			unregister_die_notifier(&ghes_notifier_nmi);
+			unregister_nmi_handler(NMI_LOCAL, "ghes");
 		mutex_unlock(&ghes_list_mutex);
 		/*
 		 * To synchronize with NMI handler, ghes can only be
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/apei/Kconfig linux-libre-3.2-gnu1/drivers/acpi/apei/Kconfig
--- linux-libre-3.1-gnu1/drivers/acpi/apei/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/apei/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@ config ACPI_APEI_GHES
 	depends on ACPI_APEI && X86
 	select ACPI_HED
 	select IRQ_WORK
-	select LLIST
 	select GENERIC_ALLOCATOR
 	help
 	  Generic Hardware Error Source provides a way to report
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/atomicio.c linux-libre-3.2-gnu1/drivers/acpi/atomicio.c
--- linux-libre-3.1-gnu1/drivers/acpi/atomicio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/atomicio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
@@ -76,7 +76,7 @@ static void __iomem *__acpi_ioremap_fast
 {
 	struct acpi_iomap *map;
 
-	map = __acpi_find_iomap(paddr, size);
+	map = __acpi_find_iomap(paddr, size/8);
 	if (map)
 		return map->vaddr + (paddr - map->paddr);
 	else
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/blacklist.c linux-libre-3.2-gnu1/drivers/acpi/blacklist.c
--- linux-libre-3.1-gnu1/drivers/acpi/blacklist.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/blacklist.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/bus.c linux-libre-3.2-gnu1/drivers/acpi/bus.c
--- linux-libre-3.1-gnu1/drivers/acpi/bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -911,10 +911,7 @@ void __init acpi_early_init(void)
 	}
 #endif
 
-	status =
-	    acpi_enable_subsystem(~
-				  (ACPI_NO_HARDWARE_INIT |
-				   ACPI_NO_ACPI_ENABLE));
+	status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
 		goto error0;
@@ -935,8 +932,7 @@ static int __init acpi_bus_init(void)
 
 	acpi_os_initialize1();
 
-	status =
-	    acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
+	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX
 		       "Unable to start the ACPI Interpreter\n");
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/debugfs.c linux-libre-3.2-gnu1/drivers/acpi/debugfs.c
--- linux-libre-3.1-gnu1/drivers/acpi/debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * debugfs.c - ACPI debugfs interface to userspace.
  */
 
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/debugfs.h>
 #include <acpi/acpi_drivers.h>
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/ec_sys.c linux-libre-3.2-gnu1/drivers/acpi/ec_sys.c
--- linux-libre-3.1-gnu1/drivers/acpi/ec_sys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/ec_sys.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/debugfs.h>
+#include <linux/module.h>
 #include "internal.h"
 
 MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/event.c linux-libre-3.2-gnu1/drivers/acpi/event.c
--- linux-libre-3.1-gnu1/drivers/acpi/event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/event.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/poll.h>
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/glue.c linux-libre-3.2-gnu1/drivers/acpi/glue.c
--- linux-libre-3.1-gnu1/drivers/acpi/glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  *
  * This file is released under the GPLv2.
  */
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/device.h>
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/osl.c linux-libre-3.2-gnu1/drivers/acpi/osl.c
--- linux-libre-3.1-gnu1/drivers/acpi/osl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/osl.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,7 +80,8 @@ static acpi_osd_handler acpi_irq_handler
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
-static struct workqueue_struct *kacpi_hotplug_wq;
+struct workqueue_struct *kacpi_hotplug_wq;
+EXPORT_SYMBOL(kacpi_hotplug_wq);
 
 struct acpi_res_list {
 	resource_size_t start;
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/proc.c linux-libre-3.2-gnu1/drivers/acpi/proc.c
--- linux-libre-3.1-gnu1/drivers/acpi/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/bcd.h>
 #include <asm/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/processor_core.c linux-libre-3.2-gnu1/drivers/acpi/processor_core.c
--- linux-libre-3.1-gnu1/drivers/acpi/processor_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/processor_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  *	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
  *	- Added _PDC for platforms with Intel CPUs
  */
+#include <linux/export.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/processor_driver.c linux-libre-3.2-gnu1/drivers/acpi/processor_driver.c
--- linux-libre-3.1-gnu1/drivers/acpi/processor_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/processor_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -426,7 +426,7 @@ static int acpi_cpu_soft_notify(struct n
 
 	if (action == CPU_ONLINE && pr) {
 		acpi_processor_ppc_has_changed(pr, 0);
-		acpi_processor_cst_has_changed(pr);
+		acpi_processor_hotplug(pr);
 		acpi_processor_reevaluate_tstate(pr, action);
 		acpi_processor_tstate_has_changed(pr);
 	}
@@ -503,8 +503,7 @@ static int __cpuinit acpi_processor_add(
 	acpi_processor_get_throttling_info(pr);
 	acpi_processor_get_limit_info(pr);
 
-
-	if (cpuidle_get_driver() == &acpi_idle_driver)
+	if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
 		acpi_processor_power_init(pr, device);
 
 	pr->cdev = thermal_cooling_device_register("Processor", device,
@@ -800,17 +799,9 @@ static int __init acpi_processor_init(vo
 
 	memset(&errata, 0, sizeof(errata));
 
-	if (!cpuidle_register_driver(&acpi_idle_driver)) {
-		printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
-			acpi_idle_driver.name);
-	} else {
-		printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
-			cpuidle_get_driver()->name);
-	}
-
 	result = acpi_bus_register_driver(&acpi_processor_driver);
 	if (result < 0)
-		goto out_cpuidle;
+		return result;
 
 	acpi_processor_install_hotplug_notify();
 
@@ -821,11 +812,6 @@ static int __init acpi_processor_init(vo
 	acpi_processor_throttling_init();
 
 	return 0;
-
-out_cpuidle:
-	cpuidle_unregister_driver(&acpi_idle_driver);
-
-	return result;
 }
 
 static void __exit acpi_processor_exit(void)
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/processor_idle.c linux-libre-3.2-gnu1/drivers/acpi/processor_idle.c
--- linux-libre-3.1-gnu1/drivers/acpi/processor_idle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/processor_idle.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/sched.h>	/* need_resched() */
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/irqflags.h>
@@ -224,7 +224,6 @@ static void lapic_timer_state_broadcast(
 /*
  * Suspend / resume control
  */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -243,21 +242,13 @@ static void acpi_idle_bm_rld_restore(voi
 
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
 {
-	if (acpi_idle_suspend == 1)
-		return 0;
-
 	acpi_idle_bm_rld_save();
-	acpi_idle_suspend = 1;
 	return 0;
 }
 
 int acpi_processor_resume(struct acpi_device * device)
 {
-	if (acpi_idle_suspend == 0)
-		return 0;
-
 	acpi_idle_bm_rld_restore();
-	acpi_idle_suspend = 0;
 	return 0;
 }
 
@@ -741,66 +732,65 @@ static inline void acpi_idle_do_entry(st
 /**
  * acpi_idle_enter_c1 - enters an ACPI C1 state-type
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing cpuidle state info
+ * @index: index of target state
  *
  * This is equivalent to the HALT instruction.
  */
 static int acpi_idle_enter_c1(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	ktime_t  kt1, kt2;
 	s64 idle_time;
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
+		return -EINVAL;
 
 	local_irq_disable();
 
-	/* Do not access any ACPI IO ports in suspend path */
-	if (acpi_idle_suspend) {
-		local_irq_enable();
-		cpu_relax();
-		return 0;
-	}
-
 	lapic_timer_state_broadcast(pr, cx, 1);
 	kt1 = ktime_get_real();
 	acpi_idle_do_entry(cx);
 	kt2 = ktime_get_real();
 	idle_time =  ktime_to_us(ktime_sub(kt2, kt1));
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	local_irq_enable();
 	cx->usage++;
 	lapic_timer_state_broadcast(pr, cx, 0);
 
-	return idle_time;
+	return index;
 }
 
 /**
  * acpi_idle_enter_simple - enters an ACPI state without BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver with cpuidle state information
+ * @index: the index of suggested state
  */
 static int acpi_idle_enter_simple(struct cpuidle_device *dev,
-				  struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 	ktime_t  kt1, kt2;
 	s64 idle_time_ns;
 	s64 idle_time;
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
-
-	if (acpi_idle_suspend)
-		return(acpi_idle_enter_c1(dev, state));
+		return -EINVAL;
 
 	local_irq_disable();
 
@@ -815,7 +805,7 @@ static int acpi_idle_enter_simple(struct
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -837,6 +827,9 @@ static int acpi_idle_enter_simple(struct
 	idle_time = idle_time_ns;
 	do_div(idle_time, NSEC_PER_USEC);
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	/* Tell the scheduler how much we idled: */
 	sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -848,46 +841,46 @@ static int acpi_idle_enter_simple(struct
 
 	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += idle_time;
-	return idle_time;
+	return index;
 }
 
 static int c3_cpu_count;
-static DEFINE_SPINLOCK(c3_lock);
+static DEFINE_RAW_SPINLOCK(c3_lock);
 
 /**
  * acpi_idle_enter_bm - enters C3 with proper BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing state data
+ * @index: the index of suggested state
  *
  * If BM is detected, the deepest non-C3 idle state is entered instead.
  */
 static int acpi_idle_enter_bm(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 	ktime_t  kt1, kt2;
 	s64 idle_time_ns;
 	s64 idle_time;
 
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
-
-	if (acpi_idle_suspend)
-		return(acpi_idle_enter_c1(dev, state));
+		return -EINVAL;
 
 	if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
-		if (dev->safe_state) {
-			dev->last_state = dev->safe_state;
-			return dev->safe_state->enter(dev, dev->safe_state);
+		if (drv->safe_state_index >= 0) {
+			return drv->states[drv->safe_state_index].enter(dev,
+						drv, drv->safe_state_index);
 		} else {
 			local_irq_disable();
 			acpi_safe_halt();
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -904,7 +897,7 @@ static int acpi_idle_enter_bm(struct cpu
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -930,12 +923,12 @@ static int acpi_idle_enter_bm(struct cpu
 	 * without doing anything.
 	 */
 	if (pr->flags.bm_check && pr->flags.bm_control) {
-		spin_lock(&c3_lock);
+		raw_spin_lock(&c3_lock);
 		c3_cpu_count++;
 		/* Disable bus master arbitration when all CPUs are in C3 */
 		if (c3_cpu_count == num_online_cpus())
 			acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
-		spin_unlock(&c3_lock);
+		raw_spin_unlock(&c3_lock);
 	} else if (!pr->flags.bm_check) {
 		ACPI_FLUSH_CPU_CACHE();
 	}
@@ -944,16 +937,19 @@ static int acpi_idle_enter_bm(struct cpu
 
 	/* Re-enable bus master arbitration */
 	if (pr->flags.bm_check && pr->flags.bm_control) {
-		spin_lock(&c3_lock);
+		raw_spin_lock(&c3_lock);
 		acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
 		c3_cpu_count--;
-		spin_unlock(&c3_lock);
+		raw_spin_unlock(&c3_lock);
 	}
 	kt2 = ktime_get_real();
 	idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
 	idle_time = idle_time_ns;
 	do_div(idle_time, NSEC_PER_USEC);
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	/* Tell the scheduler how much we idled: */
 	sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -965,7 +961,7 @@ static int acpi_idle_enter_bm(struct cpu
 
 	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += idle_time;
-	return idle_time;
+	return index;
 }
 
 struct cpuidle_driver acpi_idle_driver = {
@@ -974,14 +970,16 @@ struct cpuidle_driver acpi_idle_driver =
 };
 
 /**
- * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE
+ * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
+ * device i.e. per-cpu data
+ *
  * @pr: the ACPI processor
  */
-static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
 {
 	int i, count = CPUIDLE_DRIVER_STATE_START;
 	struct acpi_processor_cx *cx;
-	struct cpuidle_state *state;
+	struct cpuidle_state_usage *state_usage;
 	struct cpuidle_device *dev = &pr->power.dev;
 
 	if (!pr->flags.power_setup_done)
@@ -992,9 +990,62 @@ static int acpi_processor_setup_cpuidle(
 	}
 
 	dev->cpu = pr->id;
+
+	if (max_cstate == 0)
+		max_cstate = 1;
+
+	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+		cx = &pr->power.states[i];
+		state_usage = &dev->states_usage[count];
+
+		if (!cx->valid)
+			continue;
+
+#ifdef CONFIG_HOTPLUG_CPU
+		if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+		    !pr->flags.has_cst &&
+		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+			continue;
+#endif
+
+		cpuidle_set_statedata(state_usage, cx);
+
+		count++;
+		if (count == CPUIDLE_STATE_MAX)
+			break;
+	}
+
+	dev->state_count = count;
+
+	if (!count)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * acpi_processor_setup_cpuidle states- prepares and configures cpuidle
+ * global state data i.e. idle routines
+ *
+ * @pr: the ACPI processor
+ */
+static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
+{
+	int i, count = CPUIDLE_DRIVER_STATE_START;
+	struct acpi_processor_cx *cx;
+	struct cpuidle_state *state;
+	struct cpuidle_driver *drv = &acpi_idle_driver;
+
+	if (!pr->flags.power_setup_done)
+		return -EINVAL;
+
+	if (pr->flags.power == 0)
+		return -EINVAL;
+
+	drv->safe_state_index = -1;
 	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
+		drv->states[i].name[0] = '\0';
+		drv->states[i].desc[0] = '\0';
 	}
 
 	if (max_cstate == 0)
@@ -1002,7 +1053,6 @@ static int acpi_processor_setup_cpuidle(
 
 	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
 		cx = &pr->power.states[i];
-		state = &dev->states[count];
 
 		if (!cx->valid)
 			continue;
@@ -1013,8 +1063,8 @@ static int acpi_processor_setup_cpuidle(
 		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
 			continue;
 #endif
-		cpuidle_set_statedata(state, cx);
 
+		state = &drv->states[count];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
 		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
 		state->exit_latency = cx->latency;
@@ -1027,13 +1077,13 @@ static int acpi_processor_setup_cpuidle(
 				state->flags |= CPUIDLE_FLAG_TIME_VALID;
 
 			state->enter = acpi_idle_enter_c1;
-			dev->safe_state = state;
+			drv->safe_state_index = count;
 			break;
 
 			case ACPI_STATE_C2:
 			state->flags |= CPUIDLE_FLAG_TIME_VALID;
 			state->enter = acpi_idle_enter_simple;
-			dev->safe_state = state;
+			drv->safe_state_index = count;
 			break;
 
 			case ACPI_STATE_C3:
@@ -1049,7 +1099,7 @@ static int acpi_processor_setup_cpuidle(
 			break;
 	}
 
-	dev->state_count = count;
+	drv->state_count = count;
 
 	if (!count)
 		return -EINVAL;
@@ -1057,7 +1107,7 @@ static int acpi_processor_setup_cpuidle(
 	return 0;
 }
 
-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+int acpi_processor_hotplug(struct acpi_processor *pr)
 {
 	int ret = 0;
 
@@ -1078,7 +1128,7 @@ int acpi_processor_cst_has_changed(struc
 	cpuidle_disable_device(&pr->power.dev);
 	acpi_processor_get_power_info(pr);
 	if (pr->flags.power) {
-		acpi_processor_setup_cpuidle(pr);
+		acpi_processor_setup_cpuidle_cx(pr);
 		ret = cpuidle_enable_device(&pr->power.dev);
 	}
 	cpuidle_resume_and_unlock();
@@ -1086,10 +1136,72 @@ int acpi_processor_cst_has_changed(struc
 	return ret;
 }
 
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+	int cpu;
+	struct acpi_processor *_pr;
+
+	if (disabled_by_idle_boot_param())
+		return 0;
+
+	if (!pr)
+		return -EINVAL;
+
+	if (nocst)
+		return -ENODEV;
+
+	if (!pr->flags.power_setup_done)
+		return -ENODEV;
+
+	/*
+	 * FIXME:  Design the ACPI notification to make it once per
+	 * system instead of once per-cpu.  This condition is a hack
+	 * to make the code that updates C-States be called once.
+	 */
+
+	if (smp_processor_id() == 0 &&
+			cpuidle_get_driver() == &acpi_idle_driver) {
+
+		cpuidle_pause_and_lock();
+		/* Protect against cpu-hotplug */
+		get_online_cpus();
+
+		/* Disable all cpuidle devices */
+		for_each_online_cpu(cpu) {
+			_pr = per_cpu(processors, cpu);
+			if (!_pr || !_pr->flags.power_setup_done)
+				continue;
+			cpuidle_disable_device(&_pr->power.dev);
+		}
+
+		/* Populate Updated C-state information */
+		acpi_processor_setup_cpuidle_states(pr);
+
+		/* Enable all cpuidle devices */
+		for_each_online_cpu(cpu) {
+			_pr = per_cpu(processors, cpu);
+			if (!_pr || !_pr->flags.power_setup_done)
+				continue;
+			acpi_processor_get_power_info(_pr);
+			if (_pr->flags.power) {
+				acpi_processor_setup_cpuidle_cx(_pr);
+				cpuidle_enable_device(&_pr->power.dev);
+			}
+		}
+		put_online_cpus();
+		cpuidle_resume_and_unlock();
+	}
+
+	return 0;
+}
+
+static int acpi_processor_registered;
+
 int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			      struct acpi_device *device)
 {
 	acpi_status status = 0;
+	int retval;
 	static int first_run;
 
 	if (disabled_by_idle_boot_param())
@@ -1126,9 +1238,26 @@ int __cpuinit acpi_processor_power_init(
 	 * platforms that only support C1.
 	 */
 	if (pr->flags.power) {
-		acpi_processor_setup_cpuidle(pr);
-		if (cpuidle_register_device(&pr->power.dev))
-			return -EIO;
+		/* Register acpi_idle_driver if not already registered */
+		if (!acpi_processor_registered) {
+			acpi_processor_setup_cpuidle_states(pr);
+			retval = cpuidle_register_driver(&acpi_idle_driver);
+			if (retval)
+				return retval;
+			printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
+					acpi_idle_driver.name);
+		}
+		/* Register per-cpu cpuidle_device. Cpuidle driver
+		 * must already be registered before registering device
+		 */
+		acpi_processor_setup_cpuidle_cx(pr);
+		retval = cpuidle_register_device(&pr->power.dev);
+		if (retval) {
+			if (acpi_processor_registered == 0)
+				cpuidle_unregister_driver(&acpi_idle_driver);
+			return retval;
+		}
+		acpi_processor_registered++;
 	}
 	return 0;
 }
@@ -1139,8 +1268,13 @@ int acpi_processor_power_exit(struct acp
 	if (disabled_by_idle_boot_param())
 		return 0;
 
-	cpuidle_unregister_device(&pr->power.dev);
-	pr->flags.power_setup_done = 0;
+	if (pr->flags.power) {
+		cpuidle_unregister_device(&pr->power.dev);
+		acpi_processor_registered--;
+		if (acpi_processor_registered == 0)
+			cpuidle_unregister_driver(&acpi_idle_driver);
+	}
 
+	pr->flags.power_setup_done = 0;
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/sbshc.c linux-libre-3.2-gnu1/drivers/acpi/sbshc.c
--- linux-libre-3.1-gnu1/drivers/acpi/sbshc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/sbshc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "sbshc.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/scan.c linux-libre-3.2-gnu1/drivers/acpi/scan.c
--- linux-libre-3.1-gnu1/drivers/acpi/scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -1062,13 +1062,12 @@ static void acpi_add_id(struct acpi_devi
 	if (!id)
 		return;
 
-	id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
+	id->id = kstrdup(dev_id, GFP_KERNEL);
 	if (!id->id) {
 		kfree(id);
 		return;
 	}
 
-	strcpy(id->id, dev_id);
 	list_add_tail(&id->list, &device->pnp.ids);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/sleep.c linux-libre-3.2-gnu1/drivers/acpi/sleep.c
--- linux-libre-3.1-gnu1/drivers/acpi/sleep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/sleep.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,6 +390,22 @@ static struct dmi_system_id __initdata a
 	},
 	{
 	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-FW21E",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VPCEB17FX",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
 	.ident = "Sony Vaio VGN-SR11M",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
@@ -444,6 +460,22 @@ static struct dmi_system_id __initdata a
 		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
 		},
 	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-SR26GN_P",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-FW520F",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/sysfs.c linux-libre-3.2-gnu1/drivers/acpi/sysfs.c
--- linux-libre-3.1-gnu1/drivers/acpi/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -706,11 +706,23 @@ static void __exit interrupt_stats_exit(
 	return;
 }
 
+static ssize_t
+acpi_show_profile(struct device *dev, struct device_attribute *attr,
+		  char *buf)
+{
+	return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
+}
+
+static const struct device_attribute pm_profile_attr =
+	__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
+
 int __init acpi_sysfs_init(void)
 {
 	int result;
 
 	result = acpi_tables_sysfs_init();
-
+	if (result)
+		return result;
+	result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
 	return result;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/acpi/video_detect.c linux-libre-3.2-gnu1/drivers/acpi/video_detect.c
--- linux-libre-3.1-gnu1/drivers/acpi/video_detect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/acpi/video_detect.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
  *
  */
 
+#include <linux/export.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/pci.h>
diff -druNp linux-libre-3.1-gnu1/drivers/amba/bus.c linux-libre-3.2-gnu1/drivers/amba/bus.c
--- linux-libre-3.1-gnu1/drivers/amba/bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/amba/bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -365,6 +365,40 @@ static int amba_pm_restore_noirq(struct
 
 #endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
+ * enable/disable the bus clock at runtime PM suspend/resume as this
+ * does not result in loss of context.  However, disabling vcore power
+ * would do, so we leave that to the driver.
+ */
+static int amba_pm_runtime_suspend(struct device *dev)
+{
+	struct amba_device *pcdev = to_amba_device(dev);
+	int ret = pm_generic_runtime_suspend(dev);
+
+	if (ret == 0 && dev->driver)
+		clk_disable(pcdev->pclk);
+
+	return ret;
+}
+
+static int amba_pm_runtime_resume(struct device *dev)
+{
+	struct amba_device *pcdev = to_amba_device(dev);
+	int ret;
+
+	if (dev->driver) {
+		ret = clk_enable(pcdev->pclk);
+		/* Failure is probably fatal to the system, but... */
+		if (ret)
+			return ret;
+	}
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
 #ifdef CONFIG_PM
 
 static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@ static const struct dev_pm_ops amba_pm =
 	.poweroff_noirq	= amba_pm_poweroff_noirq,
 	.restore_noirq	= amba_pm_restore_noirq,
 	SET_RUNTIME_PM_OPS(
-		pm_generic_runtime_suspend,
-		pm_generic_runtime_resume,
+		amba_pm_runtime_suspend,
+		amba_pm_runtime_resume,
 		pm_generic_runtime_idle
 	)
 };
@@ -426,9 +460,17 @@ static int amba_get_enable_pclk(struct a
 	if (IS_ERR(pclk))
 		return PTR_ERR(pclk);
 
+	ret = clk_prepare(pclk);
+	if (ret) {
+		clk_put(pclk);
+		return ret;
+	}
+
 	ret = clk_enable(pclk);
-	if (ret)
+	if (ret) {
+		clk_unprepare(pclk);
 		clk_put(pclk);
+	}
 
 	return ret;
 }
@@ -438,6 +480,7 @@ static void amba_put_disable_pclk(struct
 	struct clk *pclk = pcdev->pclk;
 
 	clk_disable(pclk);
+	clk_unprepare(pclk);
 	clk_put(pclk);
 }
 
@@ -494,10 +537,18 @@ static int amba_probe(struct device *dev
 		if (ret)
 			break;
 
+		pm_runtime_get_noresume(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+
 		ret = pcdrv->probe(pcdev, id);
 		if (ret == 0)
 			break;
 
+		pm_runtime_disable(dev);
+		pm_runtime_set_suspended(dev);
+		pm_runtime_put_noidle(dev);
+
 		amba_put_disable_pclk(pcdev);
 		amba_put_disable_vcore(pcdev);
 	} while (0);
@@ -509,7 +560,16 @@ static int amba_remove(struct device *de
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = drv->remove(pcdev);
+	int ret;
+
+	pm_runtime_get_sync(dev);
+	ret = drv->remove(pcdev);
+	pm_runtime_put_noidle(dev);
+
+	/* Undo the runtime PM settings in amba_probe() */
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	amba_put_disable_pclk(pcdev);
 	amba_put_disable_vcore(pcdev);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/ahci.c linux-libre-3.2-gnu1/drivers/ata/ahci.c
--- linux-libre-3.1-gnu1/drivers/ata/ahci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/ahci.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,6 +390,9 @@ static const struct pci_device_id ahci_p
 	/* Promise */
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
 
+	/* Asmedia */
+	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1061 */
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
diff -druNp linux-libre-3.1-gnu1/drivers/ata/ahci_platform.c linux-libre-3.2-gnu1/drivers/ata/ahci_platform.c
--- linux-libre-3.1-gnu1/drivers/ata/ahci_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/ahci_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,41 @@
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
+enum ahci_type {
+	AHCI,		/* standard platform ahci */
+	IMX53_AHCI,	/* ahci on i.mx53 */
+};
+
+static struct platform_device_id ahci_devtype[] = {
+	{
+		.name = "ahci",
+		.driver_data = AHCI,
+	}, {
+		.name = "imx53-ahci",
+		.driver_data = IMX53_AHCI,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, ahci_devtype);
+
+
+static const struct ata_port_info ahci_port_info[] = {
+	/* by features */
+	[AHCI] = {
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
+	[IMX53_AHCI] = {
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_pmp_retry_srst_ops,
+	},
+};
+
 static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT("ahci_platform"),
 };
@@ -30,13 +65,9 @@ static struct scsi_host_template ahci_pl
 static int __init ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev->platform_data;
-	struct ata_port_info pi = {
-		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= ATA_PIO4,
-		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_ops,
-	};
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct platform_device_id *id = platform_get_device_id(pdev);
+	struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 	struct ahci_host_priv *hpriv;
 	struct ata_host *host;
@@ -160,7 +191,7 @@ err0:
 static int __devexit ahci_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev->platform_data;
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 
 	ata_host_detach(host);
@@ -171,12 +202,20 @@ static int __devexit ahci_remove(struct
 	return 0;
 }
 
+static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "calxeda,hb-ahci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
 static struct platform_driver ahci_driver = {
 	.remove = __devexit_p(ahci_remove),
 	.driver = {
 		.name = "ahci",
 		.owner = THIS_MODULE,
+		.of_match_table = ahci_of_match,
 	},
+	.id_table	= ahci_devtype,
 };
 
 static int __init ahci_init(void)
diff -druNp linux-libre-3.1-gnu1/drivers/ata/ata_piix.c linux-libre-3.2-gnu1/drivers/ata/ata_piix.c
--- linux-libre-3.1-gnu1/drivers/ata/ata_piix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/ata_piix.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,8 @@ enum {
 	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
 	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
 
+	PIIX_FLAG_PIO16		= (1 << 30), /*support 16bit PIO only*/
+
 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
 
@@ -147,6 +149,7 @@ enum piix_controller_ids {
 	ich8m_apple_sata,	/* locks up on second port enable */
 	tolapai_sata,
 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
+	ich8_sata_snb,
 };
 
 struct piix_map_db {
@@ -177,6 +180,7 @@ static int piix_sidpr_scr_write(struct a
 static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 			      unsigned hints);
 static bool piix_irq_check(struct ata_port *ap);
+static int piix_port_start(struct ata_port *ap);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -298,21 +302,21 @@ static const struct pci_device_id piix_p
 	/* SATA Controller IDE (PCH) */
 	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
 	/* SATA Controller IDE (CPT) */
-	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (CPT) */
-	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (CPT) */
 	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (CPT) */
 	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (PBG) */
-	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (PBG) */
 	{ 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (Panther Point) */
-	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Panther Point) */
-	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Panther Point) */
 	{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (Panther Point) */
@@ -338,6 +342,7 @@ static struct scsi_host_template piix_sh
 static struct ata_port_operations piix_sata_ops = {
 	.inherits		= &ata_bmdma32_port_ops,
 	.sff_irq_check		= piix_irq_check,
+	.port_start		= piix_port_start,
 };
 
 static struct ata_port_operations piix_pata_ops = {
@@ -478,6 +483,7 @@ static const struct piix_map_db *piix_ma
 	[ich8_2port_sata]	= &ich8_2port_map_db,
 	[ich8m_apple_sata]	= &ich8m_apple_map_db,
 	[tolapai_sata]		= &tolapai_map_db,
+	[ich8_sata_snb]		= &ich8_map_db,
 };
 
 static struct ata_port_info piix_port_info[] = {
@@ -606,6 +612,19 @@ static struct ata_port_info piix_port_in
 		.port_ops	= &piix_vmw_ops,
 	},
 
+	/*
+	 * some Sandybridge chipsets have broken 32 mode up to now,
+	 * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
+	 */
+	[ich8_sata_snb] =
+	{
+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &piix_sata_ops,
+	},
+
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -649,6 +668,14 @@ static const struct ich_laptop ich_lapto
 	{ 0, }
 };
 
+static int piix_port_start(struct ata_port *ap)
+{
+	if (!(ap->flags & PIIX_FLAG_PIO16))
+		ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
+
+	return ata_bmdma_port_start(ap);
+}
+
 /**
  *	ich_pata_cable_detect - Probe host controller cable detect info
  *	@ap: Port for which cable detect info is desired
@@ -704,22 +731,11 @@ static int piix_pata_prereset(struct ata
 
 static DEFINE_SPINLOCK(piix_lock);
 
-/**
- *	piix_set_piomode - Initialize host controller PATA PIO timings
- *	@ap: Port whose timings we are configuring
- *	@adev: um
- *
- *	Set PIO mode for device, in host controller PCI config space.
- *
- *	LOCKING:
- *	None (inherited from caller).
- */
-
-static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void piix_set_timings(struct ata_port *ap, struct ata_device *adev,
+			     u8 pio)
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
 	unsigned long flags;
-	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
@@ -744,10 +760,16 @@ static void piix_set_piomode(struct ata_
 		control |= 1;	/* TIME1 enable */
 	if (ata_pio_need_iordy(adev))
 		control |= 2;	/* IE enable */
-
 	/* Intel specifies that the PPE functionality is for disk only */
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
+	/*
+	 * If the drive MWDMA is faster than it can do PIO then
+	 * we must force PIO into PIO0
+	 */
+	if (adev->pio_mode < XFER_PIO_0 + pio)
+		/* Enable DMA timing only */
+		control |= 8;	/* PIO cycles in PIO0 */
 
 	spin_lock_irqsave(&piix_lock, flags);
 
@@ -759,8 +781,6 @@ static void piix_set_piomode(struct ata_
 	if (is_slave) {
 		/* clear TIME1|IE1|PPE1|DTE1 */
 		master_data &= 0xff0f;
-		/* Enable SITRE (separate slave timing register) */
-		master_data |= 0x4000;
 		/* enable PPE1, IE1 and TIME1 as needed */
 		master_data |= (control << 4);
 		pci_read_config_byte(dev, slave_port, &slave_data);
@@ -778,6 +798,9 @@ static void piix_set_piomode(struct ata_
 			(timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	}
+
+	/* Enable SITRE (separate slave timing register) */
+	master_data |= 0x4000;
 	pci_write_config_word(dev, master_port, master_data);
 	if (is_slave)
 		pci_write_config_byte(dev, slave_port, slave_data);
@@ -795,6 +818,22 @@ static void piix_set_piomode(struct ata_
 }
 
 /**
+ *	piix_set_piomode - Initialize host controller PATA PIO timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: Drive in question
+ *
+ *	Set PIO mode for device, in host controller PCI config space.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0);
+}
+
+/**
  *	do_pata_set_dmamode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
  *	@adev: Drive in question
@@ -810,31 +849,20 @@ static void do_pata_set_dmamode(struct a
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
 	unsigned long flags;
-	u8 master_port		= ap->port_no ? 0x42 : 0x40;
-	u16 master_data;
 	u8 speed		= adev->dma_mode;
 	int devid		= adev->devno + 2 * ap->port_no;
 	u8 udma_enable		= 0;
 
-	static const	 /* ISP  RTC */
-	u8 timings[][2]	= { { 0, 0 },
-			    { 0, 0 },
-			    { 1, 0 },
-			    { 2, 1 },
-			    { 2, 3 }, };
-
-	spin_lock_irqsave(&piix_lock, flags);
-
-	pci_read_config_word(dev, master_port, &master_data);
-	if (ap->udma_mask)
-		pci_read_config_byte(dev, 0x48, &udma_enable);
-
 	if (speed >= XFER_UDMA_0) {
-		unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+		unsigned int udma = speed - XFER_UDMA_0;
 		u16 udma_timing;
 		u16 ideconf;
 		int u_clock, u_speed;
 
+		spin_lock_irqsave(&piix_lock, flags);
+
+		pci_read_config_byte(dev, 0x48, &udma_enable);
+
 		/*
 		 * UDMA is handled by a combination of clock switching and
 		 * selection of dividers
@@ -867,56 +895,21 @@ static void do_pata_set_dmamode(struct a
 			   performance (WR_PingPong_En) */
 			pci_write_config_word(dev, 0x54, ideconf);
 		}
+
+		pci_write_config_byte(dev, 0x48, udma_enable);
+
+		spin_unlock_irqrestore(&piix_lock, flags);
 	} else {
-		/*
-		 * MWDMA is driven by the PIO timings. We must also enable
-		 * IORDY unconditionally along with TIME1. PPE has already
-		 * been set when the PIO timing was set.
-		 */
-		unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0;
-		unsigned int control;
-		u8 slave_data;
+		/* MWDMA is driven by the PIO timings. */
+		unsigned int mwdma = speed - XFER_MW_DMA_0;
 		const unsigned int needed_pio[3] = {
 			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
 		};
 		int pio = needed_pio[mwdma] - XFER_PIO_0;
 
-		control = 3;	/* IORDY|TIME1 */
-
-		/* If the drive MWDMA is faster than it can do PIO then
-		   we must force PIO into PIO0 */
-
-		if (adev->pio_mode < needed_pio[mwdma])
-			/* Enable DMA timing only */
-			control |= 8;	/* PIO cycles in PIO0 */
-
-		if (adev->devno) {	/* Slave */
-			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
-			master_data |= control << 4;
-			pci_read_config_byte(dev, 0x44, &slave_data);
-			slave_data &= (ap->port_no ? 0x0f : 0xf0);
-			/* Load the matching timing */
-			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
-			pci_write_config_byte(dev, 0x44, slave_data);
-		} else { 	/* Master */
-			master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY
-						   and master timing bits */
-			master_data |= control;
-			master_data |=
-				(timings[pio][0] << 12) |
-				(timings[pio][1] << 8);
-		}
-
-		if (ap->udma_mask)
-			udma_enable &= ~(1 << devid);
-
-		pci_write_config_word(dev, master_port, master_data);
+		/* XFER_PIO_0 is never used currently */
+		piix_set_timings(ap, adev, pio);
 	}
-	/* Don't scribble on 0x48 if the controller does not support UDMA */
-	if (ap->udma_mask)
-		pci_write_config_byte(dev, 0x48, udma_enable);
-
-	spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/ata/Kconfig linux-libre-3.2-gnu1/drivers/ata/Kconfig
--- linux-libre-3.1-gnu1/drivers/ata/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -820,7 +820,7 @@ config PATA_PLATFORM
 
 config PATA_OF_PLATFORM
 	tristate "OpenFirmware platform device PATA support"
-	depends on PATA_PLATFORM && PPC_OF
+	depends on PATA_PLATFORM && OF && OF_IRQ
 	help
 	  This option enables support for generic directly connected ATA
 	  devices commonly found on embedded systems with OpenFirmware
@@ -831,6 +831,7 @@ config PATA_OF_PLATFORM
 config PATA_QDI
 	tristate "QDI VLB PATA support"
 	depends on ISA
+	select PATA_LEGACY
 	help
 	  Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
 
diff -druNp linux-libre-3.1-gnu1/drivers/ata/libata-core.c linux-libre-3.2-gnu1/drivers/ata/libata-core.c
--- linux-libre-3.1-gnu1/drivers/ata/libata-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/libata-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -2938,7 +2938,7 @@ int ata_timing_compute(struct ata_device
 	if (id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
 		memset(&p, 0, sizeof(p));
 
-		if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+		if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
 			if (speed <= XFER_PIO_2)
 				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
 			else if ((speed <= XFER_PIO_4) ||
@@ -6713,6 +6713,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+EXPORT_SYMBOL_GPL(__ata_change_queue_depth);
 EXPORT_SYMBOL_GPL(sata_scr_valid);
 EXPORT_SYMBOL_GPL(sata_scr_read);
 EXPORT_SYMBOL_GPL(sata_scr_write);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/libata-eh.c linux-libre-3.2-gnu1/drivers/ata/libata-eh.c
--- linux-libre-3.1-gnu1/drivers/ata/libata-eh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/libata-eh.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -2532,8 +2533,7 @@ static int ata_do_reset(struct ata_link
 	return reset(link, classes, deadline);
 }
 
-static int ata_eh_followup_srst_needed(struct ata_link *link,
-				       int rc, const unsigned int *classes)
+static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)
 {
 	if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
 		return 0;
@@ -2726,7 +2726,7 @@ int ata_eh_reset(struct ata_link *link,
 
 		/* perform follow-up SRST if necessary */
 		if (reset == hardreset &&
-		    ata_eh_followup_srst_needed(link, rc, classes)) {
+		    ata_eh_followup_srst_needed(link, rc)) {
 			reset = softreset;
 
 			if (!reset) {
@@ -2883,7 +2883,7 @@ int ata_eh_reset(struct ata_link *link,
 	    sata_scr_read(link, SCR_STATUS, &sstatus))
 		rc = -ERESTART;
 
-	if (rc == -ERESTART || try >= max_tries) {
+	if (try >= max_tries) {
 		/*
 		 * Thaw host port even if reset failed, so that the port
 		 * can be retried on the next phy event.  This risks
@@ -2909,6 +2909,16 @@ int ata_eh_reset(struct ata_link *link,
 		ata_eh_acquire(ap);
 	}
 
+	/*
+	 * While disks spinup behind PMP, some controllers fail sending SRST.
+	 * They need to be reset - as well as the PMP - before retrying.
+	 */
+	if (rc == -ERESTART) {
+		if (ata_is_host_link(link))
+			ata_eh_thaw_port(ap);
+		goto out;
+	}
+
 	if (try == max_tries - 1) {
 		sata_down_spd_limit(link, 0);
 		if (slave)
diff -druNp linux-libre-3.1-gnu1/drivers/ata/libata-pmp.c linux-libre-3.2-gnu1/drivers/ata/libata-pmp.c
--- linux-libre-3.1-gnu1/drivers/ata/libata-pmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/libata-pmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/libata.h>
 #include <linux/slab.h>
 #include "libata.h"
@@ -388,12 +389,9 @@ static void sata_pmp_quirks(struct ata_p
 			/* link reports offline after LPM */
 			link->flags |= ATA_LFLAG_NO_LPM;
 
-			/* Class code report is unreliable and SRST
-			 * times out under certain configurations.
-			 */
+			/* Class code report is unreliable. */
 			if (link->pmp < 5)
-				link->flags |= ATA_LFLAG_NO_SRST |
-					       ATA_LFLAG_ASSUME_ATA;
+				link->flags |= ATA_LFLAG_ASSUME_ATA;
 
 			/* port 5 is for SEMB device and it doesn't like SRST */
 			if (link->pmp == 5)
diff -druNp linux-libre-3.1-gnu1/drivers/ata/libata-scsi.c linux-libre-3.2-gnu1/drivers/ata/libata-scsi.c
--- linux-libre-3.1-gnu1/drivers/ata/libata-scsi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/libata-scsi.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
@@ -1215,25 +1216,19 @@ void ata_scsi_slave_destroy(struct scsi_
 }
 
 /**
- *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *	__ata_change_queue_depth - helper for ata_scsi_change_queue_depth
+ *	@ap: ATA port to which the device change the queue depth
  *	@sdev: SCSI device to configure queue depth for
  *	@queue_depth: new queue depth
  *	@reason: calling context
  *
- *	This is libata standard hostt->change_queue_depth callback.
- *	SCSI will call into this callback when user tries to set queue
- *	depth via sysfs.
- *
- *	LOCKING:
- *	SCSI layer (we don't care)
+ *	libsas and libata have different approaches for associating a sdev to
+ *	its ata_port.
  *
- *	RETURNS:
- *	Newly configured queue depth.
  */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-				int reason)
+int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
+			     int queue_depth, int reason)
 {
-	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct ata_device *dev;
 	unsigned long flags;
 
@@ -1269,6 +1264,30 @@ int ata_scsi_change_queue_depth(struct s
 }
 
 /**
+ *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *	@sdev: SCSI device to configure queue depth for
+ *	@queue_depth: new queue depth
+ *	@reason: calling context
+ *
+ *	This is libata standard hostt->change_queue_depth callback.
+ *	SCSI will call into this callback when user tries to set queue
+ *	depth via sysfs.
+ *
+ *	LOCKING:
+ *	SCSI layer (we don't care)
+ *
+ *	RETURNS:
+ *	Newly configured queue depth.
+ */
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				int reason)
+{
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+
+	return __ata_change_queue_depth(ap, sdev, queue_depth, reason);
+}
+
+/**
  *	ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
  *	@qc: Storage for translated ATA taskfile
  *
diff -druNp linux-libre-3.1-gnu1/drivers/ata/libata-sff.c linux-libre-3.2-gnu1/drivers/ata/libata-sff.c
--- linux-libre-3.1-gnu1/drivers/ata/libata-sff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/libata-sff.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 #include <linux/libata.h>
 #include <linux/highmem.h>
 
@@ -569,7 +570,7 @@ unsigned int ata_sff_data_xfer(struct at
 
 	/* Transfer trailing byte, if any. */
 	if (unlikely(buflen & 0x01)) {
-		unsigned char pad[2];
+		unsigned char pad[2] = { };
 
 		/* Point buf to the tail of buffer */
 		buf += buflen - 1;
@@ -628,7 +629,7 @@ unsigned int ata_sff_data_xfer32(struct
 
 	/* Transfer trailing bytes, if any */
 	if (unlikely(slop)) {
-		unsigned char pad[4];
+		unsigned char pad[4] = { };
 
 		/* Point buf to the tail of buffer */
 		buf += buflen - slop;
@@ -678,7 +679,7 @@ unsigned int ata_sff_data_xfer_noirq(str
 	unsigned int consumed;
 
 	local_irq_save(flags);
-	consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
+	consumed = ata_sff_data_xfer32(dev, buf, buflen, rw);
 	local_irq_restore(flags);
 
 	return consumed;
@@ -2507,31 +2508,10 @@ static const struct ata_port_info *ata_s
 	return NULL;
 }
 
-/**
- *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
- *	@pdev: Controller to be initialized
- *	@ppi: array of port_info, must be enough for two ports
- *	@sht: scsi_host_template to use when registering the host
- *	@host_priv: host private_data
- *	@hflag: host flags
- *
- *	This is a helper function which can be called from a driver's
- *	xxx_init_one() probe function if the hardware uses traditional
- *	IDE taskfile registers and is PIO only.
- *
- *	ASSUMPTION:
- *	Nobody makes a single channel controller that appears solely as
- *	the secondary legacy port on PCI.
- *
- *	LOCKING:
- *	Inherited from PCI layer (may sleep).
- *
- *	RETURNS:
- *	Zero on success, negative on errno-based value on error.
- */
-int ata_pci_sff_init_one(struct pci_dev *pdev,
-		 const struct ata_port_info * const *ppi,
-		 struct scsi_host_template *sht, void *host_priv, int hflag)
+static int ata_pci_init_one(struct pci_dev *pdev,
+		const struct ata_port_info * const *ppi,
+		struct scsi_host_template *sht, void *host_priv,
+		int hflags, bool bmdma)
 {
 	struct device *dev = &pdev->dev;
 	const struct ata_port_info *pi;
@@ -2553,14 +2533,26 @@ int ata_pci_sff_init_one(struct pci_dev
 	if (rc)
 		goto out;
 
-	/* prepare and activate SFF host */
-	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+#ifdef CONFIG_ATA_BMDMA
+	if (bmdma)
+		/* prepare and activate BMDMA host */
+		rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
+	else
+#endif
+		/* prepare and activate SFF host */
+		rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
 	if (rc)
 		goto out;
 	host->private_data = host_priv;
-	host->flags |= hflag;
+	host->flags |= hflags;
 
-	rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+#ifdef CONFIG_ATA_BMDMA
+	if (bmdma) {
+		pci_set_master(pdev);
+		rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
+	} else
+#endif
+		rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
 	if (rc == 0)
 		devres_remove_group(&pdev->dev, NULL);
@@ -2569,6 +2561,35 @@ out:
 
 	return rc;
 }
+
+/**
+ *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
+ *	@pdev: Controller to be initialized
+ *	@ppi: array of port_info, must be enough for two ports
+ *	@sht: scsi_host_template to use when registering the host
+ *	@host_priv: host private_data
+ *	@hflag: host flags
+ *
+ *	This is a helper function which can be called from a driver's
+ *	xxx_init_one() probe function if the hardware uses traditional
+ *	IDE taskfile registers and is PIO only.
+ *
+ *	ASSUMPTION:
+ *	Nobody makes a single channel controller that appears solely as
+ *	the secondary legacy port on PCI.
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, negative on errno-based value on error.
+ */
+int ata_pci_sff_init_one(struct pci_dev *pdev,
+		 const struct ata_port_info * const *ppi,
+		 struct scsi_host_template *sht, void *host_priv, int hflag)
+{
+	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflag, 0);
+}
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
@@ -3286,42 +3307,7 @@ int ata_pci_bmdma_init_one(struct pci_de
 			   struct scsi_host_template *sht, void *host_priv,
 			   int hflags)
 {
-	struct device *dev = &pdev->dev;
-	const struct ata_port_info *pi;
-	struct ata_host *host = NULL;
-	int rc;
-
-	DPRINTK("ENTER\n");
-
-	pi = ata_sff_find_valid_pi(ppi);
-	if (!pi) {
-		dev_err(&pdev->dev, "no valid port_info specified\n");
-		return -EINVAL;
-	}
-
-	if (!devres_open_group(dev, NULL, GFP_KERNEL))
-		return -ENOMEM;
-
-	rc = pcim_enable_device(pdev);
-	if (rc)
-		goto out;
-
-	/* prepare and activate BMDMA host */
-	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
-	if (rc)
-		goto out;
-	host->private_data = host_priv;
-	host->flags |= hflags;
-
-	pci_set_master(pdev);
-	rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
- out:
-	if (rc == 0)
-		devres_remove_group(&pdev->dev, NULL);
-	else
-		devres_release_group(&pdev->dev, NULL);
-
-	return rc;
+	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflags, 1);
 }
 EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
 
diff -druNp linux-libre-3.1-gnu1/drivers/ata/Makefile linux-libre-3.2-gnu1/drivers/ata/Makefile
--- linux-libre-3.1-gnu1/drivers/ata/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,6 @@ obj-$(CONFIG_PATA_PCMCIA)	+= pata_pcmcia
 obj-$(CONFIG_PATA_PALMLD)	+= pata_palmld.o
 obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
 obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
-obj-$(CONFIG_PATA_QDI)		+= pata_qdi.o
 obj-$(CONFIG_PATA_RB532)	+= pata_rb532_cf.o
 obj-$(CONFIG_PATA_RZ1000)	+= pata_rz1000.o
 obj-$(CONFIG_PATA_SAMSUNG_CF)	+= pata_samsung_cf.o
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_ali.c linux-libre-3.2-gnu1/drivers/ata/pata_ali.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_ali.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_ali.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@ static const struct dmi_system_id cable_
 		},
 	},
 	{
-		.ident = "Toshiba Satelite S1800-814",
+		.ident = "Toshiba Satellite S1800-814",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_arasan_cf.c linux-libre-3.2-gnu1/drivers/ata/pata_arasan_cf.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_arasan_cf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_arasan_cf.c	2012-01-04 18:55:44.000000000 -0500
@@ -922,8 +922,7 @@ static int __devexit arasan_cf_remove(st
 #ifdef CONFIG_PM
 static int arasan_cf_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = dev_get_drvdata(dev);
 	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
 
 	if (acdev->dma_chan) {
@@ -937,8 +936,7 @@ static int arasan_cf_suspend(struct devi
 
 static int arasan_cf_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = dev_get_drvdata(dev);
 	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
 
 	cf_init(acdev);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_artop.c linux-libre-3.2-gnu1/drivers/ata/pata_artop.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_artop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_artop.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  *    pata_artop.c - ARTOP ATA controller driver
  *
  *	(C) 2006 Red Hat
- *	(C) 2007 Bartlomiej Zolnierkiewicz
+ *	(C) 2007,2011 Bartlomiej Zolnierkiewicz
  *
  *    Based in part on drivers/ide/pci/aec62xx.c
  *	Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_artop"
-#define DRV_VERSION	"0.4.5"
+#define DRV_VERSION	"0.4.6"
 
 /*
  *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -39,31 +39,15 @@
 
 static int clock = 0;
 
-static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
-{
-	struct ata_port *ap = link->ap;
-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	const struct pci_bits artop_enable_bits[] = {
-		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */
-		{ 0x4AU, 1U, 0x04UL, 0x04UL },	/* port 1 */
-	};
-
-	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
-		return -ENOENT;
-
-	return ata_sff_prereset(link, deadline);
-}
-
 /**
- *	artop6260_pre_reset	-	check for 40/80 pin
+ *	artop62x0_pre_reset	-	probe begin
  *	@link: link
  *	@deadline: deadline jiffies for the operation
  *
- *	The ARTOP hardware reports the cable detect bits in register 0x49.
  *	Nothing complicated needed here.
  */
 
-static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
+static int artop62x0_pre_reset(struct ata_link *link, unsigned long deadline)
 {
 	static const struct pci_bits artop_enable_bits[] = {
 		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */
@@ -73,7 +57,7 @@ static int artop6260_pre_reset(struct at
 	struct ata_port *ap = link->ap;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	/* Odd numbered device ids are the units with enable bits (the -R cards) */
+	/* Odd numbered device ids are the units with enable bits. */
 	if ((pdev->device & 1) &&
 	    !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
 		return -ENOENT;
@@ -317,7 +301,7 @@ static struct ata_port_operations artop6
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= artop6210_set_piomode,
 	.set_dmamode		= artop6210_set_dmamode,
-	.prereset		= artop6210_pre_reset,
+	.prereset		= artop62x0_pre_reset,
 	.qc_defer		= artop6210_qc_defer,
 };
 
@@ -326,9 +310,36 @@ static struct ata_port_operations artop6
 	.cable_detect		= artop6260_cable_detect,
 	.set_piomode		= artop6260_set_piomode,
 	.set_dmamode		= artop6260_set_dmamode,
-	.prereset		= artop6260_pre_reset,
+	.prereset		= artop62x0_pre_reset,
 };
 
+static void atp8xx_fixup(struct pci_dev *pdev)
+{
+	if (pdev->device == 0x0005)
+		/* BIOS may have left us in UDMA, clear it before libata probe */
+		pci_write_config_byte(pdev, 0x54, 0);
+	else if (pdev->device == 0x0008 || pdev->device == 0x0009) {
+		u8 reg;
+
+		/* Mac systems come up with some registers not set as we
+		   will need them */
+
+		/* Clear reset & test bits */
+		pci_read_config_byte(pdev, 0x49, &reg);
+		pci_write_config_byte(pdev, 0x49, reg & ~0x30);
+
+		/* PCI latency must be > 0x80 for burst mode, tweak it
+		 * if required.
+		 */
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
+		if (reg <= 0x80)
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
+
+		/* Enable IRQ output and burst mode */
+		pci_read_config_byte(pdev, 0x4a, &reg);
+		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
+	}
+}
 
 /**
  *	artop_init_one - Register ARTOP ATA PCI device with kernel services
@@ -383,42 +394,22 @@ static int artop_init_one (struct pci_de
 	if (rc)
 		return rc;
 
-	if (id->driver_data == 0) {	/* 6210 variant */
+	if (id->driver_data == 0)	/* 6210 variant */
 		ppi[0] = &info_6210;
-		/* BIOS may have left us in UDMA, clear it before libata probe */
-		pci_write_config_byte(pdev, 0x54, 0);
-	}
 	else if (id->driver_data == 1)	/* 6260 */
 		ppi[0] = &info_626x;
 	else if (id->driver_data == 2)	{ /* 6280 or 6280 + fast */
 		unsigned long io = pci_resource_start(pdev, 4);
-		u8 reg;
 
 		ppi[0] = &info_628x;
 		if (inb(io) & 0x10)
 			ppi[0] = &info_628x_fast;
-		/* Mac systems come up with some registers not set as we
-		   will need them */
-
-		/* Clear reset & test bits */
-		pci_read_config_byte(pdev, 0x49, &reg);
-		pci_write_config_byte(pdev, 0x49, reg & ~ 0x30);
-
-		/* PCI latency must be > 0x80 for burst mode, tweak it
-		 * if required.
-		 */
-		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
-		if (reg <= 0x80)
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
-
-		/* Enable IRQ output and burst mode */
-		pci_read_config_byte(pdev, 0x4a, &reg);
-		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
-
 	}
 
 	BUG_ON(ppi[0] == NULL);
 
+	atp8xx_fixup(pdev);
+
 	return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
 }
 
@@ -432,11 +423,32 @@ static const struct pci_device_id artop_
 	{ }	/* terminate list */
 };
 
+#ifdef CONFIG_PM
+static int atp8xx_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	atp8xx_fixup(pdev);
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 static struct pci_driver artop_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= artop_pci_tbl,
 	.probe			= artop_init_one,
 	.remove			= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= atp8xx_reinit_one,
+#endif
 };
 
 static int __init artop_init(void)
@@ -452,9 +464,8 @@ static void __exit artop_exit(void)
 module_init(artop_init);
 module_exit(artop_exit);
 
-MODULE_AUTHOR("Alan Cox");
+MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, artop_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
-
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_at91.c linux-libre-3.2-gnu1/drivers/ata/pata_at91.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_at91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_at91.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #include <mach/at91sam9_smc.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 #define DRV_NAME		"pata_at91"
 #define DRV_VERSION		"0.3"
@@ -414,10 +414,13 @@ static int __devinit pata_at91_probe(str
 
 	host->private_data = info;
 
-	return ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
+	ret = ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
 			irq ? ata_sff_interrupt : NULL,
 			irq_flags, &pata_at91_sht);
 
+	if (!ret)
+		return 0;
+
 err_put:
 	clk_put(info->mck);
 	return ret;
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_atiixp.c linux-libre-3.2-gnu1/drivers/ata/pata_atiixp.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_atiixp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_atiixp.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,31 @@ static int atiixp_cable_detect(struct at
 static DEFINE_SPINLOCK(atiixp_lock);
 
 /**
+ *	atiixp_prereset	-	perform reset handling
+ *	@link: ATA link
+ *	@deadline: deadline jiffies for the operation
+ *
+ *	Reset sequence checking enable bits to see which ports are
+ *	active.
+ */
+
+static int atiixp_prereset(struct ata_link *link, unsigned long deadline)
+{
+	static const struct pci_bits atiixp_enable_bits[] = {
+		{ 0x48, 1, 0x01, 0x00 },
+		{ 0x48, 1, 0x08, 0x00 }
+	};
+
+	struct ata_port *ap = link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+		return -ENOENT;
+
+	return ata_sff_prereset(link, deadline);
+}
+
+/**
  *	atiixp_set_pio_timing	-	set initial PIO mode data
  *	@ap: ATA interface
  *	@adev: ATA device
@@ -221,6 +246,7 @@ static struct ata_port_operations atiixp
 	.bmdma_start 	= atiixp_bmdma_start,
 	.bmdma_stop	= atiixp_bmdma_stop,
 
+	.prereset	= atiixp_prereset,
 	.cable_detect	= atiixp_cable_detect,
 	.set_piomode	= atiixp_set_piomode,
 	.set_dmamode	= atiixp_set_dmamode,
@@ -235,16 +261,7 @@ static int atiixp_init_one(struct pci_de
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &atiixp_port_ops
 	};
-	static const struct pci_bits atiixp_enable_bits[] = {
-		{ 0x48, 1, 0x01, 0x00 },
-		{ 0x48, 1, 0x08, 0x00 }
-	};
 	const struct ata_port_info *ppi[] = { &info, &info };
-	int i;
-
-	for (i = 0; i < 2; i++)
-		if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
-			ppi[i] = &ata_dummy_port_info;
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
 				      ATA_HOST_PARALLEL_SCAN);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_cmd64x.c linux-libre-3.2-gnu1/drivers/ata/pata_cmd64x.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_cmd64x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_cmd64x.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,7 +82,7 @@ static int cmd648_cable_detect(struct at
 }
 
 /**
- *	cmd64x_set_piomode	-	set PIO and MWDMA timing
+ *	cmd64x_set_timing	-	set PIO and MWDMA timing
  *	@ap: ATA interface
  *	@adev: ATA device
  *	@mode: mode
@@ -288,6 +288,22 @@ static struct ata_port_operations cmd648
 	.cable_detect	= cmd648_cable_detect,
 };
 
+static void cmd64x_fixup(struct pci_dev *pdev)
+{
+	u8 mrdmode;
+
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+	mrdmode &= ~0x30;	/* IRQ set up */
+	mrdmode |= 0x02;	/* Memory read line enable */
+	pci_write_config_byte(pdev, MRDMODE, mrdmode);
+
+	/* PPC specific fixup copied from old driver */
+#ifdef CONFIG_PPC
+	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+#endif
+}
+
 static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info cmd_info[6] = {
@@ -336,7 +352,7 @@ static int cmd64x_init_one(struct pci_de
 		&cmd_info[id->driver_data],
 		NULL
 	};
-	u8 mrdmode, reg;
+	u8 reg;
 	int rc;
 	struct pci_dev *bridge = pdev->bus->self;
 	/* mobility split bridges don't report enabled ports correctly */
@@ -368,11 +384,7 @@ static int cmd64x_init_one(struct pci_de
 			cntrl_ch0_ok = 0;
 	}
 
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
-	mrdmode &= ~ 0x30;	/* IRQ set up */
-	mrdmode |= 0x02;	/* Memory read line enable */
-	pci_write_config_byte(pdev, MRDMODE, mrdmode);
+	cmd64x_fixup(pdev);
 
 	/* check for enabled ports */
 	pci_read_config_byte(pdev, CNTRL, &reg);
@@ -388,13 +400,6 @@ static int cmd64x_init_one(struct pci_de
 		ppi[1] = &ata_dummy_port_info;
 	}
 
-	/* Force PIO 0 here.. */
-
-	/* PPC specific fixup copied from old driver */
-#ifdef CONFIG_PPC
-	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
-
 	return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
 }
 
@@ -402,21 +407,14 @@ static int cmd64x_init_one(struct pci_de
 static int cmd64x_reinit_one(struct pci_dev *pdev)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	u8 mrdmode;
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
 	if (rc)
 		return rc;
 
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
-	mrdmode &= ~ 0x30;	/* IRQ set up */
-	mrdmode |= 0x02;	/* Memory read line enable */
-	pci_write_config_byte(pdev, MRDMODE, mrdmode);
-#ifdef CONFIG_PPC
-	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
+	cmd64x_fixup(pdev);
+
 	ata_host_resume(host);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_cs5535.c linux-libre-3.2-gnu1/drivers/ata/pata_cs5535.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_cs5535.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_cs5535.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/libata.h>
 #include <asm/msr.h>
 
-#define DRV_NAME	"cs5535"
+#define DRV_NAME	"pata_cs5535"
 #define DRV_VERSION	"0.2.12"
 
 /*
@@ -67,8 +67,6 @@
 
 #define CS5535_CABLE_DETECT    0x48
 
-#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 )
-
 /**
  *	cs5535_cable_detect	-	detect cable type
  *	@ap: Port to detect on
@@ -188,16 +186,6 @@ static int cs5535_init_one(struct pci_de
 	};
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
 
-	u32 timings, dummy;
-
-	/* Check the BIOS set the initial timing clock. If not set the
-	   timings for PIO0 */
-	rdmsr(ATAC_CH0D0_PIO, timings, dummy);
-	if (CS5535_BAD_PIO(timings))
-		wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0);
-	rdmsr(ATAC_CH0D1_PIO, timings, dummy);
-	if (CS5535_BAD_PIO(timings))
-		wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
 	return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);
 }
 
@@ -230,7 +218,7 @@ static void __exit cs5535_exit(void)
 }
 
 MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch");
-MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530");
+MODULE_DESCRIPTION("low-level driver for the NS/AMD 5535");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, cs5535);
 MODULE_VERSION(DRV_VERSION);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_efar.c linux-libre-3.2-gnu1/drivers/ata/pata_efar.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_efar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_efar.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(efar_lock);
 /**
  *	efar_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
- *	@adev: um
+ *	@adev: Device to program
  *
  *	Set PIO mode for device, in host controller PCI config space.
  *
@@ -85,9 +85,9 @@ static void efar_set_piomode (struct ata
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
-	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
 	unsigned long flags;
-	u16 idetm_data;
+	u16 master_data;
 	u8 udma_enable;
 	int control = 0;
 
@@ -113,20 +113,20 @@ static void efar_set_piomode (struct ata
 
 	spin_lock_irqsave(&efar_lock, flags);
 
-	pci_read_config_word(dev, idetm_port, &idetm_data);
+	pci_read_config_word(dev, master_port, &master_data);
 
 	/* Set PPE, IE, and TIME as appropriate */
 	if (adev->devno == 0) {
-		idetm_data &= 0xCCF0;
-		idetm_data |= control;
-		idetm_data |= (timings[pio][0] << 12) |
+		master_data &= 0xCCF0;
+		master_data |= control;
+		master_data |= (timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	} else {
 		int shift = 4 * ap->port_no;
 		u8 slave_data;
 
-		idetm_data &= 0xFF0F;
-		idetm_data |= (control << 4);
+		master_data &= 0xFF0F;
+		master_data |= (control << 4);
 
 		/* Slave timing in separate register */
 		pci_read_config_byte(dev, 0x44, &slave_data);
@@ -135,8 +135,8 @@ static void efar_set_piomode (struct ata
 		pci_write_config_byte(dev, 0x44, slave_data);
 	}
 
-	idetm_data |= 0x4000;	/* Ensure SITRE is set */
-	pci_write_config_word(dev, idetm_port, idetm_data);
+	master_data |= 0x4000;	/* Ensure SITRE is set */
+	pci_write_config_word(dev, master_port, master_data);
 
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_hpt366.c linux-libre-3.2-gnu1/drivers/ata/pata_hpt366.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_hpt366.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_hpt366.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,6 +111,28 @@ static const struct hpt_clock hpt366_25[
 	{	0,		0x01208585	}
 };
 
+/**
+ *	hpt36x_find_mode	-	find the hpt36x timing
+ *	@ap: ATA port
+ *	@speed: transfer mode
+ *
+ *	Return the 32bit register programming information for this channel
+ *	that matches the speed provided.
+ */
+
+static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
+{
+	struct hpt_clock *clocks = ap->host->private_data;
+
+	while (clocks->xfer_mode) {
+		if (clocks->xfer_mode == speed)
+			return clocks->timing;
+		clocks++;
+	}
+	BUG();
+	return 0xffffffffU;	/* silence compiler warning */
+}
+
 static const char * const bad_ata33[] = {
 	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
 	"Maxtor 90845U3", "Maxtor 90650U2",
@@ -210,10 +232,9 @@ static int hpt36x_cable_detect(struct at
 static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
 			    u8 mode)
 {
-	struct hpt_clock *clocks = ap->host->private_data;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 addr = 0x40 + 4 * adev->devno;
-	u32 mask, reg;
+	u32 mask, reg, t;
 
 	/* determine timing mask and find matching clock entry */
 	if (mode < XFER_MW_DMA_0)
@@ -223,13 +244,7 @@ static void hpt366_set_mode(struct ata_p
 	else
 		mask = 0x30070000;
 
-	while (clocks->xfer_mode) {
-		if (clocks->xfer_mode == mode)
-			break;
-		clocks++;
-	}
-	if (!clocks->xfer_mode)
-		BUG();
+	t = hpt36x_find_mode(ap, mode);
 
 	/*
 	 * Combine new mode bits with old config bits and disable
@@ -237,7 +252,7 @@ static void hpt366_set_mode(struct ata_p
 	 * problems handling I/O errors later.
 	 */
 	pci_read_config_dword(pdev, addr, &reg);
-	reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
+	reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;
 	pci_write_config_dword(pdev, addr, reg);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_it8213.c linux-libre-3.2-gnu1/drivers/ata/pata_it8213.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_it8213.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_it8213.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,8 +76,8 @@ static void it8213_set_piomode (struct a
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
-	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
-	u16 idetm_data;
+	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
+	u16 master_data;
 	int control = 0;
 
 	/*
@@ -100,19 +100,19 @@ static void it8213_set_piomode (struct a
 	if (adev->class != ATA_DEV_ATA)
 		control |= 4;	/* PPE */
 
-	pci_read_config_word(dev, idetm_port, &idetm_data);
+	pci_read_config_word(dev, master_port, &master_data);
 
 	/* Set PPE, IE, and TIME as appropriate */
 	if (adev->devno == 0) {
-		idetm_data &= 0xCCF0;
-		idetm_data |= control;
-		idetm_data |= (timings[pio][0] << 12) |
+		master_data &= 0xCCF0;
+		master_data |= control;
+		master_data |= (timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	} else {
 		u8 slave_data;
 
-		idetm_data &= 0xFF0F;
-		idetm_data |= (control << 4);
+		master_data &= 0xFF0F;
+		master_data |= (control << 4);
 
 		/* Slave timing in separate register */
 		pci_read_config_byte(dev, 0x44, &slave_data);
@@ -121,8 +121,8 @@ static void it8213_set_piomode (struct a
 		pci_write_config_byte(dev, 0x44, slave_data);
 	}
 
-	idetm_data |= 0x4000;	/* Ensure SITRE is set */
-	pci_write_config_word(dev, idetm_port, idetm_data);
+	master_data |= 0x4000;	/* Ensure SITRE is set */
+	pci_write_config_word(dev, master_port, master_data);
 }
 
 /**
@@ -163,7 +163,7 @@ static void it8213_set_dmamode (struct a
 
 		/* Clocks follow the PIIX style */
 		u_speed = min(2 - (udma & 1), udma);
-		if (udma == 5)
+		if (udma > 4)
 			u_clock = 0x1000;	/* 100Mhz */
 		else if (udma > 2)
 			u_clock = 1;		/* 66Mhz */
@@ -262,7 +262,7 @@ static int it8213_init_one (struct pci_d
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA12_ONLY,
-		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &it8213_ops,
 	};
 	/* Current IT8213 stuff is single port */
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_legacy.c linux-libre-3.2-gnu1/drivers/ata/pata_legacy.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,15 +79,6 @@ static int all;
 module_param(all, int, 0444);
 MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
 
-struct legacy_data {
-	unsigned long timing;
-	u8 clock[2];
-	u8 last;
-	int fast;
-	struct platform_device *platform_dev;
-
-};
-
 enum controller {
 	BIOS = 0,
 	SNOOP = 1,
@@ -104,6 +95,14 @@ enum controller {
 	UNKNOWN = -1
 };
 
+struct legacy_data {
+	unsigned long timing;
+	u8 clock[2];
+	u8 last;
+	int fast;
+	enum controller type;
+	struct platform_device *platform_dev;
+};
 
 struct legacy_probe {
 	unsigned char *name;
@@ -137,11 +136,17 @@ static int ht6560a;		/* HT 6560A on prim
 static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
 static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
 static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
-static int qdi;			/* Set to probe QDI controllers */
 static int autospeed;		/* Chip present which snoops speed changes */
 static int pio_mask = ATA_PIO4;	/* PIO range for autospeed devices */
 static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 
+/* Set to probe QDI controllers */
+#ifdef CONFIG_PATA_QDI_MODULE
+static int qdi = 1;
+#else
+static int qdi;
+#endif
+
 #ifdef CONFIG_PATA_WINBOND_VLB_MODULE
 static int winbond = 1;		/* Set to probe Winbond controllers,
 					give I/O port if non standard */
@@ -631,40 +636,20 @@ static struct ata_port_operations opti82
 	.qc_issue	= opti82c46x_qc_issue,
 };
 
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct legacy_data *ld_qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (ld_qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	ld_qdi->clock[adev->devno] = timing;
-
-	outb(timing, ld_qdi->timing);
-}
-
 /**
- *	qdi6580dp_set_piomode		-	PIO setup for dual channel
+ *	qdi65x0_set_piomode		-	PIO setup for QDI65x0
  *	@ap: Port
  *	@adev: Device
  *
+ *	In single channel mode the 6580 has one clock per device and we can
+ *	avoid the requirement to clock switch. We also have to load the timing
+ *	into the right clock according to whether we are master or slave.
+ *
  *	In dual channel mode the 6580 has one clock per channel and we have
  *	to software clockswitch in qc_issue.
  */
 
-static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
 	struct ata_timing t;
 	struct legacy_data *ld_qdi = ap->host->private_data;
@@ -682,47 +667,15 @@ static void qdi6580dp_set_piomode(struct
 		recovery = 15 - clamp_val(t.recover, 0, 15);
 	}
 	timing = (recovery << 4) | active | 0x08;
-
 	ld_qdi->clock[adev->devno] = timing;
 
-	outb(timing, ld_qdi->timing + 2 * ap->port_no);
-	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
-		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- *	qdi6580_set_piomode		-	PIO setup for single channel
- *	@ap: Port
- *	@adev: Device
- *
- *	In single channel mode the 6580 has one clock per device and we can
- *	avoid the requirement to clock switch. We also have to load the timing
- *	into the right clock according to whether we are master or slave.
- */
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct legacy_data *ld_qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
+	if (ld_qdi->type == QDI6580)
+		outb(timing, ld_qdi->timing + 2 * adev->devno);
+	else
+		outb(timing, ld_qdi->timing + 2 * ap->port_no);
 
-	if (ld_qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-	ld_qdi->clock[adev->devno] = timing;
-	outb(timing, ld_qdi->timing + 2 * adev->devno);
 	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
+	if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA)
 		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
 }
 
@@ -789,20 +742,20 @@ static int qdi_port(struct platform_devi
 
 static struct ata_port_operations qdi6500_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6500_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.qc_issue	= qdi_qc_issue,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
 
 static struct ata_port_operations qdi6580_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6580_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
 
 static struct ata_port_operations qdi6580dp_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6580dp_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.qc_issue	= qdi_qc_issue,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
@@ -879,29 +832,29 @@ static struct ata_port_operations winbon
 };
 
 static struct legacy_controller controllers[] = {
-	{"BIOS",	&legacy_port_ops, 	0x1F,
+	{"BIOS",	&legacy_port_ops, 	ATA_PIO4,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"Snooping", 	&simple_port_ops, 	0x1F,
+	{"Snooping", 	&simple_port_ops, 	ATA_PIO4,
 			0,			0,			NULL },
-	{"PDC20230",	&pdc20230_port_ops,	0x7,
+	{"PDC20230",	&pdc20230_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,
 			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,	NULL },
-	{"HT6560A",	&ht6560a_port_ops,	0x07,
+	{"HT6560A",	&ht6560a_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"HT6560B",	&ht6560b_port_ops,	0x1F,
+	{"HT6560B",	&ht6560b_port_ops,	ATA_PIO4,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F,
+	{"OPTI82C611A",	&opti82c611a_port_ops,	ATA_PIO3,
 			0,			0,			NULL },
-	{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F,
+	{"OPTI82C46X",	&opti82c46x_port_ops,	ATA_PIO3,
 			0,			0,			NULL },
-	{"QDI6500",	&qdi6500_port_ops,	0x07,
+	{"QDI6500",	&qdi6500_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,
 			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,    qdi_port },
-	{"QDI6580",	&qdi6580_port_ops,	0x1F,
+	{"QDI6580",	&qdi6580_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
-	{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F,
+	{"QDI6580DP",	&qdi6580dp_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
-	{"W83759A",	&winbond_port_ops,	0x1F,
+	{"W83759A",	&winbond_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,
 								winbond_port }
 };
@@ -1022,6 +975,7 @@ static __init int legacy_init_one(struct
 	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
 	if (!io_addr || !ctrl_addr)
 		goto fail;
+	ld->type = probe->type;
 	if (controller->setup)
 		if (controller->setup(pdev, probe, ld) < 0)
 			goto fail;
@@ -1306,6 +1260,7 @@ MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for legacy ATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("pata_qdi");
 MODULE_ALIAS("pata_winbond");
 
 module_param(probe_all, int, 0);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_mpc52xx.c linux-libre-3.2-gnu1/drivers/ata/pata_mpc52xx.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_mpc52xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_mpc52xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -780,7 +780,7 @@ mpc52xx_ata_probe(struct platform_device
 	}
 
 	task_irq = bcom_get_task_irq(dmatsk);
-	ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED,
+	ret = request_irq(task_irq, &mpc52xx_ata_task_irq, 0,
 				"ATA task", priv);
 	if (ret) {
 		dev_err(&op->dev, "error requesting DMA IRQ\n");
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_of_platform.c linux-libre-3.2-gnu1/drivers/ata/pata_of_platform.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_of_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_of_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/ata_platform.h>
 
@@ -50,18 +52,18 @@ static int __devinit pata_of_platform_pr
 	}
 
 	ret = of_irq_to_resource(dn, 0, &irq_res);
-	if (ret == NO_IRQ)
+	if (!ret)
 		irq_res.start = irq_res.end = 0;
 	else
 		irq_res.flags = 0;
 
 	prop = of_get_property(dn, "reg-shift", NULL);
 	if (prop)
-		reg_shift = *prop;
+		reg_shift = be32_to_cpup(prop);
 
 	prop = of_get_property(dn, "pio-mode", NULL);
 	if (prop) {
-		pio_mode = *prop;
+		pio_mode = be32_to_cpup(prop);
 		if (pio_mode > 6) {
 			dev_err(&ofdev->dev, "invalid pio-mode\n");
 			return -EINVAL;
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_pdc2027x.c linux-libre-3.2-gnu1/drivers/ata/pata_pdc2027x.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_pdc2027x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_pdc2027x.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@ enum {
 };
 
 static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int pdc2027x_reinit_one(struct pci_dev *pdev);
 static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -126,6 +127,10 @@ static struct pci_driver pdc2027x_pci_dr
 	.id_table		= pdc2027x_pci_tbl,
 	.probe			= pdc2027x_init_one,
 	.remove			= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= pdc2027x_reinit_one,
+#endif
 };
 
 static struct scsi_host_template pdc2027x_sht = {
@@ -754,6 +759,31 @@ static int __devinit pdc2027x_init_one(s
 				 IRQF_SHARED, &pdc2027x_sht);
 }
 
+#ifdef CONFIG_PM
+static int pdc2027x_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	unsigned int board_idx;
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 ||
+	    pdev->device == PCI_DEVICE_ID_PROMISE_20270)
+		board_idx = PDC_UDMA_100;
+	else
+		board_idx = PDC_UDMA_133;
+
+	if (pdc_hardware_init(host, board_idx))
+		return -EIO;
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 /**
  * pdc2027x_init - Called after this module is loaded into the kernel.
  */
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_qdi.c linux-libre-3.2-gnu1/drivers/ata/pata_qdi.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_qdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_qdi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,366 +0,0 @@
-/*
- *    pata_qdi.c - QDI VLB ATA controllers
- *	(C) 2006 Red Hat
- *
- * This driver mostly exists as a proof of concept for non PCI devices under
- * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly
- * useful.
- *
- * Tuning code written from the documentation at
- * http://www.ryston.cz/petr/vlb/qd6500.html
- * http://www.ryston.cz/petr/vlb/qd6580.html
- *
- * Probe code based on drivers/ide/legacy/qd65xx.c
- * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@ens-lyon.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/platform_device.h>
-
-#define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.3.1"
-
-#define NR_HOST 4	/* Two 6580s */
-
-struct qdi_data {
-	unsigned long timing;
-	u8 clock[2];
-	u8 last;
-	int fast;
-	struct platform_device *platform_dev;
-
-};
-
-static struct ata_host *qdi_host[NR_HOST];
-static struct qdi_data qdi_data[NR_HOST];
-static int nr_qdi_host;
-
-#ifdef MODULE
-static int probe_qdi = 1;
-#else
-static int probe_qdi;
-#endif
-
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct qdi_data *qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	qdi->clock[adev->devno] = timing;
-
-	outb(timing, qdi->timing);
-}
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct qdi_data *qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	qdi->clock[adev->devno] = timing;
-
-	outb(timing, qdi->timing);
-
-	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
-		outb(0x5F, (qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- *	qdi_qc_issue		-	command issue
- *	@qc: command pending
- *
- *	Called when the libata layer is about to issue a command. We wrap
- *	this interface so that we can load the correct ATA timings.
- */
-
-static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	struct ata_device *adev = qc->dev;
-	struct qdi_data *qdi = ap->host->private_data;
-
-	if (qdi->clock[adev->devno] != qdi->last) {
-		if (adev->pio_mode) {
-			qdi->last = qdi->clock[adev->devno];
-			outb(qdi->clock[adev->devno], qdi->timing);
-		}
-	}
-	return ata_sff_qc_issue(qc);
-}
-
-static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
-				  unsigned int buflen, int rw)
-{
-	if (ata_id_has_dword_io(dev->id)) {
-		struct ata_port *ap = dev->link->ap;
-		int slop = buflen & 3;
-
-		if (rw == READ)
-			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-		else
-			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-
-		if (unlikely(slop)) {
-			__le32 pad;
-			if (rw == READ) {
-				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
-				memcpy(buf + buflen - slop, &pad, slop);
-			} else {
-				memcpy(&pad, buf + buflen - slop, slop);
-				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-			}
-			buflen += 4 - slop;
-		}
-	} else
-		buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
-
-	return buflen;
-}
-
-static struct scsi_host_template qdi_sht = {
-	ATA_PIO_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations qdi6500_port_ops = {
-	.inherits	= &ata_sff_port_ops,
-	.qc_issue	= qdi_qc_issue,
-	.sff_data_xfer	= qdi_data_xfer,
-	.cable_detect	= ata_cable_40wire,
-	.set_piomode	= qdi6500_set_piomode,
-};
-
-static struct ata_port_operations qdi6580_port_ops = {
-	.inherits	= &qdi6500_port_ops,
-	.set_piomode	= qdi6580_set_piomode,
-};
-
-/**
- *	qdi_init_one		-	attach a qdi interface
- *	@type: Type to display
- *	@io: I/O port start
- *	@irq: interrupt line
- *	@fast: True if on a > 33Mhz VLB
- *
- *	Register an ISA bus IDE interface. Such interfaces are PIO and we
- *	assume do not support IRQ sharing.
- */
-
-static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast)
-{
-	unsigned long ctl = io + 0x206;
-	struct platform_device *pdev;
-	struct ata_host *host;
-	struct ata_port *ap;
-	void __iomem *io_addr, *ctl_addr;
-	int ret;
-
-	/*
-	 *	Fill in a probe structure first of all
-	 */
-
-	pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	ret = -ENOMEM;
-	io_addr = devm_ioport_map(&pdev->dev, io, 8);
-	ctl_addr = devm_ioport_map(&pdev->dev, ctl, 1);
-	if (!io_addr || !ctl_addr)
-		goto fail;
-
-	ret = -ENOMEM;
-	host = ata_host_alloc(&pdev->dev, 1);
-	if (!host)
-		goto fail;
-	ap = host->ports[0];
-
-	if (type == 6580) {
-		ap->ops = &qdi6580_port_ops;
-		ap->pio_mask = ATA_PIO4;
-		ap->flags |= ATA_FLAG_SLAVE_POSS;
-	} else {
-		ap->ops = &qdi6500_port_ops;
-		ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */
-		ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
-	}
-
-	ap->ioaddr.cmd_addr = io_addr;
-	ap->ioaddr.altstatus_addr = ctl_addr;
-	ap->ioaddr.ctl_addr = ctl_addr;
-	ata_sff_std_ports(&ap->ioaddr);
-
-	ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
-
-	/*
-	 *	Hook in a private data structure per channel
-	 */
-	ap->private_data = &qdi_data[nr_qdi_host];
-
-	qdi_data[nr_qdi_host].timing = port;
-	qdi_data[nr_qdi_host].fast = fast;
-	qdi_data[nr_qdi_host].platform_dev = pdev;
-
-	printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
-
-	/* activate */
-	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
-	if (ret)
-		goto fail;
-
-	qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev);
-	return 0;
-
- fail:
-	platform_device_unregister(pdev);
-	return ret;
-}
-
-/**
- *	qdi_init		-	attach qdi interfaces
- *
- *	Attach qdi IDE interfaces by scanning the ports it may occupy.
- */
-
-static __init int qdi_init(void)
-{
-	unsigned long flags;
-	static const unsigned long qd_port[2] = { 0x30, 0xB0 };
-	static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
-	static const int ide_irq[2] = { 14, 15 };
-
-	int ct = 0;
-	int i;
-
-	if (probe_qdi == 0)
-		return -ENODEV;
-
-	/*
- 	 *	Check each possible QD65xx base address
-	 */
-
-	for (i = 0; i < 2; i++) {
-		unsigned long port = qd_port[i];
-		u8 r, res;
-
-
-		if (request_region(port, 2, "pata_qdi")) {
-			/* Check for a card */
-			local_irq_save(flags);
-			r = inb_p(port);
-			outb_p(0x19, port);
-			res = inb_p(port);
-			outb_p(r, port);
-			local_irq_restore(flags);
-
-			/* Fail */
-			if (res == 0x19)
-			{
-				release_region(port, 2);
-				continue;
-			}
-
-			/* Passes the presence test */
-			r = inb_p(port + 1);	/* Check port agrees with port set */
-			if ((r & 2) >> 1 != i) {
-				release_region(port, 2);
-				continue;
-			}
-
-			/* Check card type */
-			if ((r & 0xF0) == 0xC0) {
-				/* QD6500: single channel */
-				if (r & 8) {
-					/* Disabled ? */
-					release_region(port, 2);
-					continue;
-				}
-				if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
-					ct++;
-			}
-			if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
-				/* QD6580: dual channel */
-				if (!request_region(port + 2 , 2, "pata_qdi"))
-				{
-					release_region(port, 2);
-					continue;
-				}
-				res = inb(port + 3);
-				if (res & 1) {
-					/* Single channel mode */
-					if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
-						ct++;
-				} else {
-					/* Dual channel mode */
-					if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0)
-						ct++;
-					if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0)
-						ct++;
-				}
-			}
-		}
-	}
-	if (ct != 0)
-		return 0;
-	return -ENODEV;
-}
-
-static __exit void qdi_exit(void)
-{
-	int i;
-
-	for (i = 0; i < nr_qdi_host; i++) {
-		ata_host_detach(qdi_host[i]);
-		/* Free the control resource. The 6580 dual channel has the resources
-		 * claimed as a pair of 2 byte resources so we need no special cases...
-		 */
-		release_region(qdi_data[i].timing, 2);
-		platform_device_unregister(qdi_data[i].platform_dev);
-	}
-}
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for qdi ATA");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_init(qdi_init);
-module_exit(qdi_exit);
-
-module_param(probe_qdi, int, 0);
-
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_rdc.c linux-libre-3.2-gnu1/drivers/ata/pata_rdc.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_rdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_rdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,8 @@ static int rdc_pata_prereset(struct ata_
 	return ata_sff_prereset(link, deadline);
 }
 
+static DEFINE_SPINLOCK(rdc_lock);
+
 /**
  *	rdc_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
@@ -101,6 +103,7 @@ static void rdc_set_piomode(struct ata_p
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
 	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
@@ -124,6 +127,8 @@ static void rdc_set_piomode(struct ata_p
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
 
+	spin_lock_irqsave(&rdc_lock, flags);
+
 	/* PIO configuration clears DTE unconditionally.  It will be
 	 * programmed in set_dmamode which is guaranteed to be called
 	 * after set_piomode if any DMA mode is available.
@@ -161,6 +166,8 @@ static void rdc_set_piomode(struct ata_p
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
 	pci_write_config_byte(dev, 0x48, udma_enable);
+
+	spin_unlock_irqrestore(&rdc_lock, flags);
 }
 
 /**
@@ -177,6 +184,7 @@ static void rdc_set_piomode(struct ata_p
 static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
 	u8 master_port		= ap->port_no ? 0x42 : 0x40;
 	u16 master_data;
 	u8 speed		= adev->dma_mode;
@@ -190,6 +198,8 @@ static void rdc_set_dmamode(struct ata_p
 			    { 2, 1 },
 			    { 2, 3 }, };
 
+	spin_lock_irqsave(&rdc_lock, flags);
+
 	pci_read_config_word(dev, master_port, &master_data);
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 
@@ -271,6 +281,8 @@ static void rdc_set_dmamode(struct ata_p
 		pci_write_config_word(dev, master_port, master_data);
 	}
 	pci_write_config_byte(dev, 0x48, udma_enable);
+
+	spin_unlock_irqrestore(&rdc_lock, flags);
 }
 
 static struct ata_port_operations rdc_pata_ops = {
@@ -375,6 +387,10 @@ static struct pci_driver rdc_pci_driver
 	.id_table		= rdc_pci_tbl,
 	.probe			= rdc_init_one,
 	.remove			= rdc_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= ata_pci_device_resume,
+#endif
 };
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_sc1200.c linux-libre-3.2-gnu1/drivers/ata/pata_sc1200.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_sc1200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_sc1200.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
-#define DRV_NAME	"sc1200"
+#define DRV_NAME	"pata_sc1200"
 #define DRV_VERSION	"0.2.6"
 
 #define SC1200_REV_A	0x00
@@ -86,10 +86,14 @@ static int sc1200_clock(void)
 static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
 	static const u32 pio_timings[4][5] = {
-		{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},	// format0  33Mhz
-		{0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},	// format1, 33Mhz
-		{0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},	// format1, 48Mhz
-		{0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}	// format1, 66Mhz
+		/* format0, 33Mhz */
+		{ 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 },
+		/* format1, 33Mhz */
+		{ 0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010 },
+		/* format1, 48Mhz */
+		{ 0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021 },
+		/* format1, 66Mhz */
+		{ 0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131 }
 	};
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_scc.c linux-libre-3.2-gnu1/drivers/ata/pata_scc.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_scc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_scc.c	2012-01-04 18:55:44.000000000 -0500
@@ -826,18 +826,6 @@ static unsigned int scc_data_xfer (struc
 }
 
 /**
- *	scc_pata_prereset - prepare for reset
- *	@ap: ATA port to be reset
- *	@deadline: deadline jiffies for the operation
- */
-
-static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
-{
-	link->ap->cbl = ATA_CBL_PATA80;
-	return ata_sff_prereset(link, deadline);
-}
-
-/**
  *	scc_postreset - standard postreset callback
  *	@ap: the target ata_port
  *	@classes: classes of attached devices
@@ -946,7 +934,7 @@ static struct ata_port_operations scc_pa
 	.bmdma_status		= scc_bmdma_status,
 	.sff_data_xfer		= scc_data_xfer,
 
-	.prereset		= scc_pata_prereset,
+	.cable_detect		= ata_cable_80wire,
 	.softreset		= scc_softreset,
 	.postreset		= scc_postreset,
 
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_serverworks.c linux-libre-3.2-gnu1/drivers/ata/pata_serverworks.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_serverworks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_serverworks.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,31 +58,15 @@ static const char *csb_bad_ata100[] = {
 };
 
 /**
- *	dell_cable	-	Dell serverworks cable detection
+ *	oem_cable	-	Dell/Sun serverworks cable detection
  *	@ap: ATA port to do cable detect
  *
- *	Dell hide the 40/80 pin select for their interfaces in the top two
- *	bits of the subsystem ID.
- */
-
-static int dell_cable(struct ata_port *ap) {
-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
-	if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
-		return ATA_CBL_PATA80;
-	return ATA_CBL_PATA40;
-}
-
-/**
- *	sun_cable	-	Sun Cobalt 'Alpine' cable detection
- *	@ap: ATA port to do cable select
- *
- *	Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the
- *	subsystem ID the same as dell. We could use one function but we may
- *	need to extend the Dell one in future
+ *	Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select
+ *	for their interfaces in the top two bits of the subsystem ID.
  */
 
-static int sun_cable(struct ata_port *ap) {
+static int oem_cable(struct ata_port *ap)
+{
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
 	if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
@@ -90,49 +74,21 @@ static int sun_cable(struct ata_port *ap
 	return ATA_CBL_PATA40;
 }
 
-/**
- *	osb4_cable	-	OSB4 cable detect
- *	@ap: ATA port to check
- *
- *	The OSB4 isn't UDMA66 capable so this is easy
- */
-
-static int osb4_cable(struct ata_port *ap) {
-	return ATA_CBL_PATA40;
-}
-
-/**
- *	csb_cable	-	CSB5/6 cable detect
- *	@ap: ATA port to check
- *
- *	Serverworks default arrangement is to use the drive side detection
- *	only.
- */
-
-static int csb_cable(struct ata_port *ap) {
-	return ATA_CBL_PATA_UNK;
-}
-
 struct sv_cable_table {
 	int device;
 	int subvendor;
 	int (*cable_detect)(struct ata_port *ap);
 };
 
-/*
- *	Note that we don't copy the old serverworks code because the old
- *	code contains obvious mistakes
- */
-
 static struct sv_cable_table cable_detect[] = {
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN,  sun_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_DELL, oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_VENDOR_ID_DELL, oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_SUN,  oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,   PCI_ANY_ID, ata_cable_40wire  },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,  PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },
 	{ }
 };
 
@@ -393,6 +349,31 @@ static void serverworks_fixup_ht1000(str
 	pci_write_config_byte(pdev, 0x5A, btr);
 }
 
+static int serverworks_fixup(struct pci_dev *pdev)
+{
+	int rc = 0;
+
+	/* Force master latency timer to 64 PCI clocks */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+		rc = serverworks_fixup_osb4(pdev);
+		break;
+	case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+		ata_pci_bmdma_clear_simplex(pdev);
+		/* fall through */
+	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+		rc = serverworks_fixup_csb(pdev);
+		break;
+	case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
+		serverworks_fixup_ht1000(pdev);
+		break;
+	}
+
+	return rc;
+}
 
 static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -430,13 +411,12 @@ static int serverworks_init_one(struct p
 	if (rc)
 		return rc;
 
-	/* Force master latency timer to 64 PCI clocks */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+	rc = serverworks_fixup(pdev);
 
 	/* OSB4 : South Bridge and IDE */
 	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
 		/* Select non UDMA capable OSB4 if we can't do fixups */
-		if ( serverworks_fixup_osb4(pdev) < 0)
+		if (rc < 0)
 			ppi[0] = &info[1];
 	}
 	/* setup CSB5/CSB6 : South Bridge and IDE option RAID */
@@ -446,19 +426,13 @@ static int serverworks_init_one(struct p
 
 		 /* If the returned btr is the newer revision then
 		    select the right info block */
-		 if (serverworks_fixup_csb(pdev) == 3)
+		 if (rc == 3)
 		 	ppi[0] = &info[3];
 
 		/* Is this the 3rd channel CSB6 IDE ? */
 		if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)
 			ppi[1] = &ata_dummy_port_info;
 	}
-	/* setup HT1000E */
-	else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
-		serverworks_fixup_ht1000(pdev);
-
-	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		ata_pci_bmdma_clear_simplex(pdev);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
 }
@@ -473,24 +447,7 @@ static int serverworks_reinit_one(struct
 	if (rc)
 		return rc;
 
-	/* Force master latency timer to 64 PCI clocks */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
-
-	switch (pdev->device) {
-		case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
-			serverworks_fixup_osb4(pdev);
-			break;
-		case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
-			ata_pci_bmdma_clear_simplex(pdev);
-			/* fall through */
-		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
-		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
-			serverworks_fixup_csb(pdev);
-			break;
-		case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
-			serverworks_fixup_ht1000(pdev);
-			break;
-	}
+	(void)serverworks_fixup(pdev);
 
 	ata_host_resume(host);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_sil680.c linux-libre-3.2-gnu1/drivers/ata/pata_sil680.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_sil680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_sil680.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,11 +38,12 @@
 
 /**
  *	sil680_selreg		-	return register base
- *	@hwif: interface
+ *	@ap: ATA interface
  *	@r: config offset
  *
- *	Turn a config register offset into the right address in either
- *	PCI space or MMIO space to access the control register in question
+ *	Turn a config register offset into the right address in PCI space
+ *	to access the control register in question.
+ *
  *	Thankfully this is a configuration operation so isn't performance
  *	criticial.
  */
@@ -56,12 +57,12 @@ static unsigned long sil680_selreg(struc
 
 /**
  *	sil680_seldev		-	return register base
- *	@hwif: interface
+ *	@ap: ATA interface
  *	@r: config offset
  *
- *	Turn a config register offset into the right address in either
- *	PCI space or MMIO space to access the control register in question
- *	including accounting for the unit shift.
+ *	Turn a config register offset into the right address in PCI space
+ *	to access the control register in question including accounting for
+ *	the unit shift.
  */
 
 static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r)
@@ -81,7 +82,8 @@ static unsigned long sil680_seldev(struc
  *	space for us.
  */
 
-static int sil680_cable_detect(struct ata_port *ap) {
+static int sil680_cable_detect(struct ata_port *ap)
+{
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	unsigned long addr = sil680_selreg(ap, 0);
 	u8 ata66;
@@ -93,7 +95,7 @@ static int sil680_cable_detect(struct at
 }
 
 /**
- *	sil680_set_piomode	-	set initial PIO mode data
+ *	sil680_set_piomode	-	set PIO mode data
  *	@ap: ATA interface
  *	@adev: ATA device
  *
@@ -104,8 +106,12 @@ static int sil680_cable_detect(struct at
 
 static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 };
-	static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 };
+	static const u16 speed_p[5] = {
+		0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1
+	};
+	static const u16 speed_t[5] = {
+		0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1
+	};
 
 	unsigned long tfaddr = sil680_selreg(ap, 0x02);
 	unsigned long addr = sil680_seldev(ap, adev, 0x04);
@@ -140,22 +146,23 @@ static void sil680_set_piomode(struct at
 }
 
 /**
- *	sil680_set_dmamode	-	set initial DMA mode data
+ *	sil680_set_dmamode	-	set DMA mode data
  *	@ap: ATA interface
  *	@adev: ATA device
  *
- *	Program the MWDMA/UDMA modes for the sil680 k
- *	chipset. The MWDMA mode values are pulled from a lookup table
+ *	Program the MWDMA/UDMA modes for the sil680 chipset.
+ *
+ *	The MWDMA mode values are pulled from a lookup table
  *	while the chipset uses mode number for UDMA.
  */
 
 static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	static u8 ultra_table[2][7] = {
+	static const u8 ultra_table[2][7] = {
 		{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF },	/* 100MHz */
 		{ 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 },	/* 133Mhz */
 	};
-	static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
+	static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	unsigned long ma = sil680_seldev(ap, adev, 0x08);
@@ -175,7 +182,7 @@ static void sil680_set_dmamode(struct at
 	mode &= ~(0x03 << port_shift);
 
 	/* Extract scsc */
-	scsc = (scsc & 0x30) ? 1: 0;
+	scsc = (scsc & 0x30) ? 1 : 0;
 
 	if (adev->dma_mode >= XFER_UDMA_0) {
 		multi = 0x10C1;
@@ -248,7 +255,7 @@ static u8 sil680_init_chip(struct pci_de
 {
 	u8 tmpbyte	= 0;
 
-        /* FIXME: double check */
+	/* FIXME: double check */
 	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
 			      pdev->revision ? 1 : 255);
 
@@ -266,22 +273,22 @@ static u8 sil680_init_chip(struct pci_de
 		*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
 #endif
 
-	switch(tmpbyte & 0x30) {
-		case 0x00:
-			/* 133 clock attempt to force it on */
-			pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
-			break;
-		case 0x30:
-			/* if clocking is disabled */
-			/* 133 clock attempt to force it on */
-			pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
-			break;
-		case 0x10:
-			/* 133 already */
-			break;
-		case 0x20:
-			/* BIOS set PCI x2 clocking */
-			break;
+	switch (tmpbyte & 0x30) {
+	case 0x00:
+		/* 133 clock attempt to force it on */
+		pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
+		break;
+	case 0x30:
+		/* if clocking is disabled */
+		/* 133 clock attempt to force it on */
+		pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
+		break;
+	case 0x10:
+		/* 133 already */
+		break;
+	case 0x20:
+		/* BIOS set PCI x2 clocking */
+		break;
 	}
 
 	pci_read_config_byte(pdev,   0x8A, &tmpbyte);
@@ -299,12 +306,19 @@ static u8 sil680_init_chip(struct pci_de
 	pci_write_config_dword(pdev, 0xB8, 0x43924392);
 	pci_write_config_dword(pdev, 0xBC, 0x40094009);
 
-	switch(tmpbyte & 0x30) {
-		case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break;
-		case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break;
-		case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
-		/* This last case is _NOT_ ok */
-		case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
+	switch (tmpbyte & 0x30) {
+	case 0x00:
+		printk(KERN_INFO "sil680: 100MHz clock.\n");
+		break;
+	case 0x10:
+		printk(KERN_INFO "sil680: 133MHz clock.\n");
+		break;
+	case 0x20:
+		printk(KERN_INFO "sil680: Using PCI clock.\n");
+		break;
+	/* This last case is _NOT_ ok */
+	case 0x30:
+		printk(KERN_ERR "sil680: Clock disabled ?\n");
 	}
 	return tmpbyte & 0x30;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_sis.c linux-libre-3.2-gnu1/drivers/ata/pata_sis.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_sis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_sis.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@ static const struct sis_laptop sis_lapto
 	/* devid, subvendor, subdev */
 	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
 	{ 0x5513, 0x1734, 0x105F },	/* FSC Amilo A1630 */
-	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
+	{ 0x5513, 0x1071, 0x8640 },	/* EasyNote K5305 */
 	/* end marker */
 	{ 0, }
 };
@@ -76,7 +76,7 @@ static int sis_short_ata40(struct pci_de
 }
 
 /**
- *	sis_old_port_base		-	return PCI configuration base for dev
+ *	sis_old_port_base - return PCI configuration base for dev
  *	@adev: device
  *
  *	Returns the base of the PCI configuration registers for this port
@@ -85,11 +85,34 @@ static int sis_short_ata40(struct pci_de
 
 static int sis_old_port_base(struct ata_device *adev)
 {
-	return  0x40 + (4 * adev->link->ap->port_no) +  (2 * adev->devno);
+	return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);
 }
 
 /**
- *	sis_133_cable_detect	-	check for 40/80 pin
+ *	sis_port_base - return PCI configuration base for dev
+ *	@adev: device
+ *
+ *	Returns the base of the PCI configuration registers for this port
+ *	number.
+ */
+
+static int sis_port_base(struct ata_device *adev)
+{
+	struct ata_port *ap = adev->link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port = 0x40;
+	u32 reg54;
+
+	/* If bit 30 is set then the registers are mapped at 0x70 not 0x40 */
+	pci_read_config_dword(pdev, 0x54, &reg54);
+	if (reg54 & 0x40000000)
+		port = 0x70;
+
+	return port + (8 * ap->port_no) + (4 * adev->devno);
+}
+
+/**
+ *	sis_133_cable_detect - check for 40/80 pin
  *	@ap: Port
  *	@deadline: deadline jiffies for the operation
  *
@@ -110,7 +133,7 @@ static int sis_133_cable_detect(struct a
 }
 
 /**
- *	sis_66_cable_detect	-	check for 40/80 pin
+ *	sis_66_cable_detect - check for 40/80 pin
  *	@ap: Port
  *
  *	Perform cable detection on the UDMA66, UDMA100 and early UDMA133
@@ -132,7 +155,7 @@ static int sis_66_cable_detect(struct at
 
 
 /**
- *	sis_pre_reset		-	probe begin
+ *	sis_pre_reset - probe begin
  *	@link: ATA link
  *	@deadline: deadline jiffies for the operation
  *
@@ -160,7 +183,7 @@ static int sis_pre_reset(struct ata_link
 
 
 /**
- *	sis_set_fifo	-	Set RWP fifo bits for this device
+ *	sis_set_fifo - Set RWP fifo bits for this device
  *	@ap: Port
  *	@adev: Device
  *
@@ -203,13 +226,13 @@ static void sis_set_fifo(struct ata_port
 
 static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int port = sis_old_port_base(adev);
 	u8 t1, t2;
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 };
-	const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
+	static const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 };
+	static const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
 
 	sis_set_fifo(ap, adev);
 
@@ -240,11 +263,11 @@ static void sis_old_set_piomode (struct
 
 static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int port = sis_old_port_base(adev);
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
+	static const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
 
 	sis_set_fifo(ap, adev);
 
@@ -265,20 +288,19 @@ static void sis_100_set_piomode (struct
 
 static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int port = 0x40;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port;
 	u32 t1;
-	u32 reg54;
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u32 timing133[] = {
+	static const u32 timing133[] = {
 		0x28269000,	/* Recovery << 24 | Act << 16 | Ini << 12 */
 		0x0C266000,
 		0x04263000,
 		0x0C0A3000,
 		0x05093000
 	};
-	const u32 timing100[] = {
+	static const u32 timing100[] = {
 		0x1E1C6000,	/* Recovery << 24 | Act << 16 | Ini << 12 */
 		0x091C4000,
 		0x031C2000,
@@ -288,12 +310,7 @@ static void sis_133_set_piomode (struct
 
 	sis_set_fifo(ap, adev);
 
-	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
-	pci_read_config_dword(pdev, 0x54, &reg54);
-	if (reg54 & 0x40000000)
-		port = 0x70;
-	port += 8 * ap->port_no +  4 * adev->devno;
-
+	port = sis_port_base(adev);
 	pci_read_config_dword(pdev, port, &t1);
 	t1 &= 0xC0C00FFF;	/* Mask out timing */
 
@@ -319,13 +336,13 @@ static void sis_133_set_piomode (struct
 
 static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
-	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
-	const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 };
+	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+	static const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 };
 
 	pci_read_config_word(pdev, drive_pci, &timing);
 
@@ -358,14 +375,14 @@ static void sis_old_set_dmamode (struct
 
 static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
 	/* MWDMA 0-2 and UDMA 0-5 */
-	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
-	const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
+	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+	static const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
 
 	pci_read_config_word(pdev, drive_pci, &timing);
 
@@ -397,12 +414,12 @@ static void sis_66_set_dmamode (struct a
 
 static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u8 timing;
 
-	const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
+	static const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
 
 	pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
@@ -431,7 +448,7 @@ static void sis_100_set_dmamode (struct
 
 static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u8 timing;
@@ -464,32 +481,34 @@ static void sis_133_early_set_dmamode (s
 
 static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int port = 0x40;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port;
 	u32 t1;
-	u32 reg54;
-
-	/* bits 4- cycle time 8 - cvs time */
-	static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
-	static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
-
-	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
-	pci_read_config_dword(pdev, 0x54, &reg54);
-	if (reg54 & 0x40000000)
-		port = 0x70;
-	port += (8 * ap->port_no) +  (4 * adev->devno);
 
+	port = sis_port_base(adev);
 	pci_read_config_dword(pdev, port, &t1);
 
 	if (adev->dma_mode < XFER_UDMA_0) {
+		/* Recovery << 24 | Act << 16 | Ini << 12, like PIO modes */
+		static const u32 timing_u100[] = { 0x19154000, 0x06072000, 0x04062000 };
+		static const u32 timing_u133[] = { 0x221C6000, 0x0C0A3000, 0x05093000 };
+		int speed = adev->dma_mode - XFER_MW_DMA_0;
+
+		t1 &= 0xC0C00FFF;
+		/* disable UDMA */
 		t1 &= ~0x00000004;
-		/* FIXME: need data sheet to add MWDMA here. Also lacking on
-		   ide/pci driver */
+		if (t1 & 0x08)
+			t1 |= timing_u133[speed];
+		else
+			t1 |= timing_u100[speed];
 	} else {
-		speed = adev->dma_mode - XFER_UDMA_0;
-		/* if & 8 no UDMA133 - need info for ... */
+		/* bits 4- cycle time 8 - cvs time */
+		static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
+		static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
+		int speed = adev->dma_mode - XFER_UDMA_0;
+
 		t1 &= ~0x00000FF0;
+		/* enable UDMA */
 		t1 |= 0x00000004;
 		if (t1 & 0x08)
 			t1 |= timing_u133[speed];
@@ -499,6 +518,27 @@ static void sis_133_set_dmamode (struct
 	pci_write_config_dword(pdev, port, t1);
 }
 
+/**
+ *	sis_133_mode_filter - mode selection filter
+ *	@adev: ATA device
+ *
+ *	Block UDMA6 on devices that do not support it.
+ */
+
+static unsigned long sis_133_mode_filter(struct ata_device *adev, unsigned long mask)
+{
+	struct ata_port *ap = adev->link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port = sis_port_base(adev);
+	u32 t1;
+
+	pci_read_config_dword(pdev, port, &t1);
+	/* if ATA133 is disabled, mask it out */
+	if (!(t1 & 0x08))
+		mask &= ~(0xC0 << ATA_SHIFT_UDMA);
+	return mask;
+}
+
 static struct scsi_host_template sis_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -520,6 +560,7 @@ static struct ata_port_operations sis_13
 	.set_piomode		= sis_133_set_piomode,
 	.set_dmamode		= sis_133_set_dmamode,
 	.cable_detect		= sis_133_cable_detect,
+	.mode_filter		= sis_133_mode_filter,
 };
 
 static struct ata_port_operations sis_133_early_ops = {
@@ -588,7 +629,7 @@ static const struct ata_port_info sis_in
 static const struct ata_port_info sis_info133 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
-	/* No MWDMA */
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_ops,
 };
@@ -669,7 +710,7 @@ static void sis_fixup(struct pci_dev *pd
  *	@pdev: PCI device to register
  *	@ent: Entry in sis_pci_tbl matching with @pdev
  *
- *	Called from kernel PCI layer.  We probe for combined mode (sigh),
+ *	Called from kernel PCI layer. We probe for combined mode (sigh),
  *	and then hand over control to libata, for it to do the rest.
  *
  *	LOCKING:
@@ -769,17 +810,20 @@ static int sis_init_one (struct pci_dev
 
 		switch(trueid) {
 		case 0x5518:	/* SIS 962/963 */
+			dev_info(&pdev->dev,
+				 "SiS 962/963 MuTIOL IDE UDMA133 controller\n");
 			chipset = &sis133;
 			if ((idemisc & 0x40000000) == 0) {
 				pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000);
-				printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+				dev_info(&pdev->dev,
+					 "Switching to 5513 register mapping\n");
 			}
 			break;
 		case 0x0180:	/* SIS 965/965L */
-			chipset =  &sis133;
+			chipset = &sis133;
 			break;
 		case 0x1180:	/* SIS 966/966L */
-			chipset =  &sis133;
+			chipset = &sis133;
 			break;
 		}
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_sl82c105.c linux-libre-3.2-gnu1/drivers/ata/pata_sl82c105.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_sl82c105.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_sl82c105.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 /*
  * pata_sl82c105.c 	- SL82C105 PATA for new ATA layer
  *			  (C) 2005 Red Hat Inc
+ *			  (C) 2011 Bartlomiej Zolnierkiewicz
  *
  * Based in part on linux/drivers/ide/pci/sl82c105.c
  * 		SL82C105/Winbond 553 IDE driver
@@ -289,6 +290,14 @@ static int sl82c105_bridge_revision(stru
 	return bridge->revision;
 }
 
+static void sl82c105_fixup(struct pci_dev *pdev)
+{
+	u32 val;
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+	pci_write_config_dword(pdev, 0x40, val);
+}
 
 static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
@@ -306,7 +315,6 @@ static int sl82c105_init_one(struct pci_
 	/* for now use only the first port */
 	const struct ata_port_info *ppi[] = { &info_early,
 					       NULL };
-	u32 val;
 	int rev;
 	int rc;
 
@@ -325,13 +333,28 @@ static int sl82c105_init_one(struct pci_
 	else
 		ppi[0] = &info_dma;
 
-	pci_read_config_dword(dev, 0x40, &val);
-	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
-	pci_write_config_dword(dev, 0x40, val);
+	sl82c105_fixup(dev);
 
 	return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
 }
 
+#ifdef CONFIG_PM
+static int sl82c105_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	sl82c105_fixup(pdev);
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 static const struct pci_device_id sl82c105[] = {
 	{ PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), },
 
@@ -342,7 +365,11 @@ static struct pci_driver sl82c105_pci_dr
 	.name 		= DRV_NAME,
 	.id_table	= sl82c105,
 	.probe 		= sl82c105_init_one,
-	.remove		= ata_pci_remove_one
+	.remove		= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend	= ata_pci_device_suspend,
+	.resume		= sl82c105_reinit_one,
+#endif
 };
 
 static int __init sl82c105_init(void)
diff -druNp linux-libre-3.1-gnu1/drivers/ata/pata_via.c linux-libre-3.2-gnu1/drivers/ata/pata_via.c
--- linux-libre-3.1-gnu1/drivers/ata/pata_via.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/pata_via.c	2012-01-04 18:55:44.000000000 -0500
@@ -509,6 +509,27 @@ static void via_config_fifo(struct pci_d
 	}
 }
 
+static void via_fixup(struct pci_dev *pdev, const struct via_isa_bridge *config)
+{
+	u32 timing;
+
+	/* Initialise the FIFO for the enabled channels. */
+	via_config_fifo(pdev, config->flags);
+
+	if (config->udma_mask == ATA_UDMA4) {
+		/* The 66 MHz devices require we enable the clock */
+		pci_read_config_dword(pdev, 0x50, &timing);
+		timing |= 0x80008;
+		pci_write_config_dword(pdev, 0x50, timing);
+	}
+	if (config->flags & VIA_BAD_CLK66) {
+		/* Disable the 66MHz clock on problem devices */
+		pci_read_config_dword(pdev, 0x50, &timing);
+		timing &= ~0x80008;
+		pci_write_config_dword(pdev, 0x50, timing);
+	}
+}
+
 /**
  *	via_init_one		-	discovery callback
  *	@pdev: PCI device
@@ -570,7 +591,6 @@ static int via_init_one(struct pci_dev *
 	struct pci_dev *isa;
 	const struct via_isa_bridge *config;
 	u8 enable;
-	u32 timing;
 	unsigned long flags = id->driver_data;
 	int rc;
 
@@ -609,9 +629,6 @@ static int via_init_one(struct pci_dev *
 			return -ENODEV;
 	}
 
-	/* Initialise the FIFO for the enabled channels. */
-	via_config_fifo(pdev, config->flags);
-
 	/* Clock set up */
 	switch (config->udma_mask) {
 	case 0x00:
@@ -637,12 +654,7 @@ static int via_init_one(struct pci_dev *
 		return -ENODEV;
  	}
 
-	if (config->flags & VIA_BAD_CLK66) {
-		/* Disable the 66MHz clock on problem devices */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing &= ~0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
+	via_fixup(pdev, config);
 
 	/* We have established the device type, now fire it up */
 	return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);
@@ -661,29 +673,14 @@ static int via_init_one(struct pci_dev *
 
 static int via_reinit_one(struct pci_dev *pdev)
 {
-	u32 timing;
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	const struct via_isa_bridge *config = host->private_data;
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
 	if (rc)
 		return rc;
 
-	via_config_fifo(pdev, config->flags);
-
-	if (config->udma_mask == ATA_UDMA4) {
-		/* The 66 MHz devices require we enable the clock */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing |= 0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
-	if (config->flags & VIA_BAD_CLK66) {
-		/* Disable the 66MHz clock on problem devices */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing &= ~0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
+	via_fixup(pdev, host->private_data);
 
 	ata_host_resume(host);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/ata/sata_mv.c linux-libre-3.2-gnu1/drivers/ata/sata_mv.c
--- linux-libre-3.1-gnu1/drivers/ata/sata_mv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/sata_mv.c	2012-01-04 18:55:44.000000000 -0500
@@ -4087,8 +4087,11 @@ static int mv_platform_probe(struct plat
 	dev_info(&pdev->dev, "slots %u ports %d\n",
 		 (unsigned)MV_MAX_Q_DEPTH, host->n_ports);
 
-	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
-				 IRQF_SHARED, &mv6_sht);
+	rc = ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
+			       IRQF_SHARED, &mv6_sht);
+	if (!rc)
+		return 0;
+
 err:
 #if defined(CONFIG_HAVE_CLK)
 	if (!IS_ERR(hpriv->clk)) {
@@ -4110,8 +4113,7 @@ err:
  */
 static int __devexit mv_platform_remove(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-	struct ata_host *host = dev_get_drvdata(dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 #if defined(CONFIG_HAVE_CLK)
 	struct mv_host_priv *hpriv = host->private_data;
 #endif
@@ -4129,7 +4131,7 @@ static int __devexit mv_platform_remove(
 #ifdef CONFIG_PM
 static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 	if (host)
 		return ata_host_suspend(host, state);
 	else
@@ -4138,7 +4140,7 @@ static int mv_platform_suspend(struct pl
 
 static int mv_platform_resume(struct platform_device *pdev)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 	int ret;
 
 	if (host) {
@@ -4353,7 +4355,7 @@ static int mv_pci_init_one(struct pci_de
 #ifdef CONFIG_PM
 static int mv_pci_device_resume(struct pci_dev *pdev)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = pci_get_drvdata(pdev);
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
diff -druNp linux-libre-3.1-gnu1/drivers/ata/sata_sil24.c linux-libre-3.2-gnu1/drivers/ata/sata_sil24.c
--- linux-libre-3.1-gnu1/drivers/ata/sata_sil24.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/sata_sil24.c	2012-01-04 18:55:44.000000000 -0500
@@ -268,7 +268,7 @@ union sil24_cmd_block {
 	struct sil24_atapi_block atapi;
 };
 
-static struct sil24_cerr_info {
+static const struct sil24_cerr_info {
 	unsigned int err_mask, action;
 	const char *desc;
 } sil24_cerr_db[] = {
@@ -1019,7 +1019,7 @@ static void sil24_error_intr(struct ata_
 
 	/* deal with command error */
 	if (irq_stat & PORT_IRQ_ERROR) {
-		struct sil24_cerr_info *ci = NULL;
+		const struct sil24_cerr_info *ci = NULL;
 		unsigned int err_mask = 0, action = 0;
 		u32 context, cerr;
 		int pmp;
diff -druNp linux-libre-3.1-gnu1/drivers/ata/sata_sis.c linux-libre-3.2-gnu1/drivers/ata/sata_sis.c
--- linux-libre-3.1-gnu1/drivers/ata/sata_sis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ata/sata_sis.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@ static const struct ata_port_info sis_po
 };
 
 MODULE_AUTHOR("Uwe Koziolek");
-MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
diff -druNp linux-libre-3.1-gnu1/drivers/atm/eni.c linux-libre-3.2-gnu1/drivers/atm/eni.c
--- linux-libre-3.1-gnu1/drivers/atm/eni.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/atm/eni.c	2012-01-04 18:55:44.000000000 -0500
@@ -1134,8 +1134,9 @@ DPRINTK("doing direct send\n"); /* @@@ w
 				    skb_headlen(skb));
 			else
 				put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
-				    skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
-				    skb_shinfo(skb)->frags[i].size);
+				    skb_frag_page(&skb_shinfo(skb)->frags[i]) +
+					skb_shinfo(skb)->frags[i].page_offset,
+				    skb_frag_size(&skb_shinfo(skb)->frags[i]));
 	}
 	if (skb->len & 3)
 		put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
diff -druNp linux-libre-3.1-gnu1/drivers/atm/idt77252.c linux-libre-3.2-gnu1/drivers/atm/idt77252.c
--- linux-libre-3.1-gnu1/drivers/atm/idt77252.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/atm/idt77252.c	2012-01-04 18:55:44.000000000 -0500
@@ -3416,27 +3416,28 @@ init_card(struct atm_dev *dev)
 
 	size = sizeof(struct vc_map *) * card->tct_size;
 	IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
-	if (NULL == (card->vcs = vmalloc(size))) {
+	card->vcs = vzalloc(size);
+	if (!card->vcs) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
-	memset(card->vcs, 0, size);
 
 	size = sizeof(struct vc_map *) * card->scd_size;
 	IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
 	        card->name, size);
-	if (NULL == (card->scd2vc = vmalloc(size))) {
+	card->scd2vc = vzalloc(size);
+	if (!card->scd2vc) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
-	memset(card->scd2vc, 0, size);
 
 	size = sizeof(struct tst_info) * (card->tst_size - 2);
 	IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
 		card->name, size);
-	if (NULL == (card->soft_tst = vmalloc(size))) {
+	card->soft_tst = vmalloc(size);
+	if (!card->soft_tst) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
diff -druNp linux-libre-3.1-gnu1/drivers/atm/iphase.c linux-libre-3.2-gnu1/drivers/atm/iphase.c
--- linux-libre-3.1-gnu1/drivers/atm/iphase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/atm/iphase.c	2012-01-04 18:55:44.000000000 -0500
@@ -818,127 +818,152 @@ static void ia_hw_type(IADEV *iadev) {
 
 }
 
-static void IaFrontEndIntr(IADEV *iadev) {
-  volatile IA_SUNI *suni;
-  volatile ia_mb25_t *mb25;
-  volatile suni_pm7345_t *suni_pm7345;
+static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg)
+{
+	return readl(ia->phy + (reg >> 2));
+}
 
-  if(iadev->phy_type & FE_25MBIT_PHY) {
-     mb25 = (ia_mb25_t*)iadev->phy;
-     iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
-  } else if (iadev->phy_type & FE_DS3_PHY) {
-     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-     /* clear FRMR interrupts */
-     (void) suni_pm7345->suni_ds3_frm_intr_stat; 
-     iadev->carrier_detect =  
-           Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
-  } else if (iadev->phy_type & FE_E3_PHY ) {
-     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-     (void) suni_pm7345->suni_e3_frm_maint_intr_ind;
-     iadev->carrier_detect =
-           Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS));
-  }
-  else { 
-     suni = (IA_SUNI *)iadev->phy;
-     (void) suni->suni_rsop_status;
-     iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV));
-  }
-  if (iadev->carrier_detect)
-    printk("IA: SUNI carrier detected\n");
-  else
-    printk("IA: SUNI carrier lost signal\n"); 
-  return;
+static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val)
+{
+	writel(val, ia->phy + (reg >> 2));
 }
 
-static void ia_mb25_init (IADEV *iadev)
+static void ia_frontend_intr(struct iadev_priv *iadev)
+{
+	u32 status;
+
+	if (iadev->phy_type & FE_25MBIT_PHY) {
+		status = ia_phy_read32(iadev, MB25_INTR_STATUS);
+		iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0;
+	} else if (iadev->phy_type & FE_DS3_PHY) {
+		ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT);
+		status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+		iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+	} else if (iadev->phy_type & FE_E3_PHY) {
+		ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND);
+		status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+		iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+	} else {
+		status = ia_phy_read32(iadev, SUNI_RSOP_STATUS);
+		iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1;
+	}
+
+	printk(KERN_INFO "IA: SUNI carrier %s\n",
+		iadev->carrier_detect ? "detected" : "lost signal");
+}
+
+static void ia_mb25_init(struct iadev_priv *iadev)
 {
-   volatile ia_mb25_t  *mb25 = (ia_mb25_t*)iadev->phy;
 #if 0
    mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
 #endif
-   mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC;
-   mb25->mb25_diag_control = 0;
-   /*
-    * Initialize carrier detect state
-    */
-   iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
-   return;
-}                   
+	ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC);
+	ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0);
 
-static void ia_suni_pm7345_init (IADEV *iadev)
+	iadev->carrier_detect =
+		(ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0;
+}
+
+struct ia_reg {
+	u16 reg;
+	u16 val;
+};
+
+static void ia_phy_write(struct iadev_priv *iadev,
+			 const struct ia_reg *regs, int len)
 {
-   volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-   if (iadev->phy_type & FE_DS3_PHY)
-   {
-      iadev->carrier_detect = 
-          Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); 
-      suni_pm7345->suni_ds3_frm_intr_enbl = 0x17;
-      suni_pm7345->suni_ds3_frm_cfg = 1;
-      suni_pm7345->suni_ds3_tran_cfg = 1;
-      suni_pm7345->suni_config = 0;
-      suni_pm7345->suni_splr_cfg = 0;
-      suni_pm7345->suni_splt_cfg = 0;
-   }
-   else 
-   {
-      iadev->carrier_detect = 
-          Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS));
-      suni_pm7345->suni_e3_frm_fram_options = 0x4;
-      suni_pm7345->suni_e3_frm_maint_options = 0x20;
-      suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d;
-      suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30;
-      suni_pm7345->suni_e3_tran_stat_diag_options = 0x0;
-      suni_pm7345->suni_e3_tran_fram_options = 0x1;
-      suni_pm7345->suni_config = SUNI_PM7345_E3ENBL;
-      suni_pm7345->suni_splr_cfg = 0x41;
-      suni_pm7345->suni_splt_cfg = 0x41;
-   } 
-   /*
-    * Enable RSOP loss of signal interrupt.
-    */
-   suni_pm7345->suni_intr_enbl = 0x28;
- 
-   /*
-    * Clear error counters
-    */
-   suni_pm7345->suni_id_reset = 0;
+	while (len--) {
+		ia_phy_write32(iadev, regs->reg, regs->val);
+		regs++;
+	}
+}
 
-   /*
-    * Clear "PMCTST" in master test register.
-    */
-   suni_pm7345->suni_master_test = 0;
+static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_ds3_init [] = {
+		{ SUNI_DS3_FRM_INTR_ENBL,	0x17 },
+		{ SUNI_DS3_FRM_CFG,		0x01 },
+		{ SUNI_DS3_TRAN_CFG,		0x01 },
+		{ SUNI_CONFIG,			0 },
+		{ SUNI_SPLR_CFG,		0 },
+		{ SUNI_SPLT_CFG,		0 }
+	};
+	u32 status;
 
-   suni_pm7345->suni_rxcp_ctrl = 0x2c;
-   suni_pm7345->suni_rxcp_fctrl = 0x81;
- 
-   suni_pm7345->suni_rxcp_idle_pat_h1 =
-   	suni_pm7345->suni_rxcp_idle_pat_h2 =
-   	suni_pm7345->suni_rxcp_idle_pat_h3 = 0;
-   suni_pm7345->suni_rxcp_idle_pat_h4 = 1;
- 
-   suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe;
- 
-   suni_pm7345->suni_rxcp_cell_pat_h1 =
-   	suni_pm7345->suni_rxcp_cell_pat_h2 =
-   	suni_pm7345->suni_rxcp_cell_pat_h3 = 0;
-   suni_pm7345->suni_rxcp_cell_pat_h4 = 1;
- 
-   suni_pm7345->suni_rxcp_cell_mask_h1 =
-   	suni_pm7345->suni_rxcp_cell_mask_h2 =
-   	suni_pm7345->suni_rxcp_cell_mask_h3 =
-   	suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff;
- 
-   suni_pm7345->suni_txcp_ctrl = 0xa4;
-   suni_pm7345->suni_txcp_intr_en_sts = 0x10;
-   suni_pm7345->suni_txcp_idle_pat_h5 = 0x55;
- 
-   suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB |
-                                 SUNI_PM7345_CLB |
-                                 SUNI_PM7345_DLB |
-                                  SUNI_PM7345_PLB);
+	status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+	iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+
+	ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init));
+}
+
+static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_e3_init [] = {
+		{ SUNI_E3_FRM_FRAM_OPTIONS,		0x04 },
+		{ SUNI_E3_FRM_MAINT_OPTIONS,		0x20 },
+		{ SUNI_E3_FRM_FRAM_INTR_ENBL,		0x1d },
+		{ SUNI_E3_FRM_MAINT_INTR_ENBL,		0x30 },
+		{ SUNI_E3_TRAN_STAT_DIAG_OPTIONS,	0 },
+		{ SUNI_E3_TRAN_FRAM_OPTIONS,		0x01 },
+		{ SUNI_CONFIG,				SUNI_PM7345_E3ENBL },
+		{ SUNI_SPLR_CFG,			0x41 },
+		{ SUNI_SPLT_CFG,			0x41 }
+	};
+	u32 status;
+
+	status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+	iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+	ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init));
+}
+
+static void ia_suni_pm7345_init(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_init [] = {
+		/* Enable RSOP loss of signal interrupt. */
+		{ SUNI_INTR_ENBL,		0x28 },
+		/* Clear error counters. */
+		{ SUNI_ID_RESET,		0 },
+		/* Clear "PMCTST" in master test register. */
+		{ SUNI_MASTER_TEST,		0 },
+
+		{ SUNI_RXCP_CTRL,		0x2c },
+		{ SUNI_RXCP_FCTRL,		0x81 },
+
+		{ SUNI_RXCP_IDLE_PAT_H1,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H2,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H3,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H4,	0x01 },
+
+		{ SUNI_RXCP_IDLE_MASK_H1,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H2,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H3,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H4,	0xfe },
+
+		{ SUNI_RXCP_CELL_PAT_H1,	0 },
+		{ SUNI_RXCP_CELL_PAT_H2,	0 },
+		{ SUNI_RXCP_CELL_PAT_H3,	0 },
+		{ SUNI_RXCP_CELL_PAT_H4,	0x01 },
+
+		{ SUNI_RXCP_CELL_MASK_H1,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H2,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H3,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H4,	0xff },
+
+		{ SUNI_TXCP_CTRL,		0xa4 },
+		{ SUNI_TXCP_INTR_EN_STS,	0x10 },
+		{ SUNI_TXCP_IDLE_PAT_H5,	0x55 }
+	};
+
+	if (iadev->phy_type & FE_DS3_PHY)
+		ia_suni_pm7345_init_ds3(iadev);
+	else
+		ia_suni_pm7345_init_e3(iadev);
+
+	ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init));
+
+	ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) &
+		~(SUNI_PM7345_LLB | SUNI_PM7345_CLB |
+		  SUNI_PM7345_DLB | SUNI_PM7345_PLB));
 #ifdef __SNMP__
    suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
 #endif /* __SNMP__ */
@@ -1425,10 +1450,10 @@ static int rx_init(struct atm_dev *dev)
 	       iadev->dma + IPHASE5575_RX_LIST_ADDR);  
 	IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
                       iadev->dma+IPHASE5575_TX_LIST_ADDR,
-                      *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));  
+                      readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
 	printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
                       iadev->dma+IPHASE5575_RX_LIST_ADDR,
-                      *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));)  
+                      readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
   
 	writew(0xffff, iadev->reass_reg+REASS_MASK_REG);  
 	writew(0, iadev->reass_reg+MODE_REG);  
@@ -2208,7 +2233,7 @@ static irqreturn_t ia_int(int irq, void
 	if (status & STAT_DLERINT)  
 	{  
 	   /* Clear this bit by writing a 1 to it. */  
-	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT;
+	   writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
 	   rx_dle_intr(dev);  
 	}  
 	if (status & STAT_SEGINT)  
@@ -2219,13 +2244,13 @@ static irqreturn_t ia_int(int irq, void
 	}  
 	if (status & STAT_DLETINT)  
 	{  
-	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT;  
+	   writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
 	   tx_dle_intr(dev);  
 	}  
 	if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))  
 	{  
            if (status & STAT_FEINT) 
-               IaFrontEndIntr(iadev);
+               ia_frontend_intr(iadev);
 	}  
    }
    return IRQ_RETVAL(handled);
@@ -2556,7 +2581,7 @@ static int __devinit ia_start(struct atm
 				goto err_free_rx;
 		}
 		/* Get iadev->carrier_detect status */
-		IaFrontEndIntr(iadev);
+		ia_frontend_intr(iadev);
 	}
 	return 0;
 
@@ -2827,7 +2852,7 @@ static int ia_ioctl(struct atm_dev *dev,
 
          case 0xb:
 	    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-            IaFrontEndIntr(iadev);
+            ia_frontend_intr(iadev);
             break;
          case 0xa:
 	    if (!capable(CAP_NET_ADMIN)) return -EPERM;
diff -druNp linux-libre-3.1-gnu1/drivers/atm/iphase.h linux-libre-3.2-gnu1/drivers/atm/iphase.h
--- linux-libre-3.1-gnu1/drivers/atm/iphase.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/atm/iphase.h	2012-01-04 18:55:44.000000000 -0500
@@ -889,79 +889,71 @@ typedef struct ia_rtn_q {
 } IARTN_Q;
 
 #define SUNI_LOSV   	0x04
-typedef struct {
-        u32   suni_master_reset;      /* SUNI Master Reset and Identity     */
-        u32   suni_master_config;     /* SUNI Master Configuration          */
-        u32   suni_master_intr_stat;  /* SUNI Master Interrupt Status       */
-        u32   suni_reserved1;         /* Reserved                           */
-        u32   suni_master_clk_monitor;/* SUNI Master Clock Monitor          */
-        u32   suni_master_control;    /* SUNI Master Clock Monitor          */
-        u32   suni_reserved2[10];     /* Reserved                           */
-
-        u32   suni_rsop_control;      /* RSOP Control/Interrupt Enable      */
-        u32   suni_rsop_status;       /* RSOP Status/Interrupt States       */
-        u32   suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB             */
-        u32   suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB             */
-
-        u32   suni_tsop_control;      /* TSOP Control                       */
-        u32   suni_tsop_diag;         /* TSOP Disgnostics                   */
-        u32   suni_tsop_reserved[2];  /* TSOP Reserved                      */
-
-        u32   suni_rlop_cs;           /* RLOP Control/Status                */
-        u32   suni_rlop_intr;         /* RLOP Interrupt Enable/Status       */
-        u32   suni_rlop_line_bip24l;  /* RLOP Line BIP-24 LSB               */
-        u32   suni_rlop_line_bip24;   /* RLOP Line BIP-24                   */
-        u32   suni_rlop_line_bip24m;  /* RLOP Line BIP-24 MSB               */
-        u32   suni_rlop_line_febel;   /* RLOP Line FEBE LSB                 */
-        u32   suni_rlop_line_febe;    /* RLOP Line FEBE                     */
-        u32   suni_rlop_line_febem;   /* RLOP Line FEBE MSB                 */
-
-        u32   suni_tlop_control;      /* TLOP Control                       */
-        u32   suni_tlop_disg;         /* TLOP Disgnostics                   */
-        u32   suni_tlop_reserved[14]; /* TLOP Reserved                      */
-
-        u32   suni_rpop_cs;           /* RPOP Status/Control                */
-        u32   suni_rpop_intr;         /* RPOP Interrupt/Status              */
-        u32   suni_rpop_reserved;     /* RPOP Reserved                      */
-        u32   suni_rpop_intr_ena;     /* RPOP Interrupt Enable              */
-        u32   suni_rpop_reserved1[3]; /* RPOP Reserved                      */
-        u32   suni_rpop_path_sig;     /* RPOP Path Signal Label             */
-        u32   suni_rpop_bip8l;        /* RPOP Path BIP-8 LSB                */
-        u32   suni_rpop_bip8m;        /* RPOP Path BIP-8 MSB                */
-        u32   suni_rpop_febel;        /* RPOP Path FEBE LSB                 */
-        u32   suni_rpop_febem;        /* RPOP Path FEBE MSB                 */
-        u32   suni_rpop_reserved2[4]; /* RPOP Reserved                      */
-
-        u32   suni_tpop_cntrl_daig;   /* TPOP Control/Disgnostics           */
-        u32   suni_tpop_pointer_ctrl; /* TPOP Pointer Control               */
-        u32   suni_tpop_sourcer_ctrl; /* TPOP Source Control                */
-        u32   suni_tpop_reserved1[2]; /* TPOP Reserved                      */
-        u32   suni_tpop_arb_prtl;     /* TPOP Arbitrary Pointer LSB         */
-        u32   suni_tpop_arb_prtm;     /* TPOP Arbitrary Pointer MSB         */
-        u32   suni_tpop_reserved2;    /* TPOP Reserved                      */
-        u32   suni_tpop_path_sig;     /* TPOP Path Signal Lable             */
-        u32   suni_tpop_path_status;  /* TPOP Path Status                   */
-        u32   suni_tpop_reserved3[6]; /* TPOP Reserved                      */              
-
-        u32   suni_racp_cs;           /* RACP Control/Status                */
-        u32   suni_racp_intr;         /* RACP Interrupt Enable/Status       */
-        u32   suni_racp_hdr_pattern;  /* RACP Match Header Pattern          */
-        u32   suni_racp_hdr_mask;     /* RACP Match Header Mask             */
-        u32   suni_racp_corr_hcs;     /* RACP Correctable HCS Error Count   */
-        u32   suni_racp_uncorr_hcs;   /* RACP Uncorrectable HCS Error Count */
-        u32   suni_racp_reserved[10]; /* RACP Reserved                      */
-
-        u32   suni_tacp_control;      /* TACP Control                       */
-        u32   suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern      */
-        u32   suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */
-        u32   suni_tacp_reserved[5];  /* TACP Reserved                      */
-
-        u32   suni_reserved3[24];     /* Reserved                           */
+enum ia_suni {
+	SUNI_MASTER_RESET	= 0x000, /* SUNI Master Reset and Identity   */
+	SUNI_MASTER_CONFIG	= 0x004, /* SUNI Master Configuration        */
+	SUNI_MASTER_INTR_STAT	= 0x008, /* SUNI Master Interrupt Status     */
+	SUNI_RESERVED1		= 0x00c, /* Reserved                         */
+	SUNI_MASTER_CLK_MONITOR	= 0x010, /* SUNI Master Clock Monitor        */
+	SUNI_MASTER_CONTROL	= 0x014, /* SUNI Master Clock Monitor        */
+					 /* Reserved (10)                    */
+	SUNI_RSOP_CONTROL	= 0x040, /* RSOP Control/Interrupt Enable    */
+	SUNI_RSOP_STATUS	= 0x044, /* RSOP Status/Interrupt States     */
+	SUNI_RSOP_SECTION_BIP8L	= 0x048, /* RSOP Section BIP-8 LSB           */
+	SUNI_RSOP_SECTION_BIP8M	= 0x04c, /* RSOP Section BIP-8 MSB           */
 
-        u32   suni_master_test;       /* SUNI Master Test                   */
-        u32   suni_reserved_test;     /* SUNI Reserved for Test             */
-} IA_SUNI;
+	SUNI_TSOP_CONTROL	= 0x050, /* TSOP Control                     */
+	SUNI_TSOP_DIAG		= 0x054, /* TSOP Disgnostics                 */
+					 /* Reserved (2)                     */
+	SUNI_RLOP_CS		= 0x060, /* RLOP Control/Status              */
+	SUNI_RLOP_INTR		= 0x064, /* RLOP Interrupt Enable/Status     */
+	SUNI_RLOP_LINE_BIP24L	= 0x068, /* RLOP Line BIP-24 LSB             */
+	SUNI_RLOP_LINE_BIP24	= 0x06c, /* RLOP Line BIP-24                 */
+	SUNI_RLOP_LINE_BIP24M	= 0x070, /* RLOP Line BIP-24 MSB             */
+	SUNI_RLOP_LINE_FEBEL	= 0x074, /* RLOP Line FEBE LSB               */
+	SUNI_RLOP_LINE_FEBE	= 0x078, /* RLOP Line FEBE                   */
+	SUNI_RLOP_LINE_FEBEM	= 0x07c, /* RLOP Line FEBE MSB               */
 
+	SUNI_TLOP_CONTROL	= 0x080, /* TLOP Control                     */
+	SUNI_TLOP_DISG		= 0x084, /* TLOP Disgnostics                 */
+					 /* Reserved (14)                    */
+	SUNI_RPOP_CS		= 0x0c0, /* RPOP Status/Control              */
+	SUNI_RPOP_INTR		= 0x0c4, /* RPOP Interrupt/Status            */
+	SUNI_RPOP_RESERVED	= 0x0c8, /* RPOP Reserved                    */
+	SUNI_RPOP_INTR_ENA	= 0x0cc, /* RPOP Interrupt Enable            */
+					 /* Reserved (3)                     */
+	SUNI_RPOP_PATH_SIG	= 0x0dc, /* RPOP Path Signal Label           */
+	SUNI_RPOP_BIP8L		= 0x0e0, /* RPOP Path BIP-8 LSB              */
+	SUNI_RPOP_BIP8M		= 0x0e4, /* RPOP Path BIP-8 MSB              */
+	SUNI_RPOP_FEBEL		= 0x0e8, /* RPOP Path FEBE LSB               */
+	SUNI_RPOP_FEBEM		= 0x0ec, /* RPOP Path FEBE MSB               */
+					 /* Reserved (4)                     */
+	SUNI_TPOP_CNTRL_DAIG	= 0x100, /* TPOP Control/Disgnostics         */
+	SUNI_TPOP_POINTER_CTRL	= 0x104, /* TPOP Pointer Control             */
+	SUNI_TPOP_SOURCER_CTRL	= 0x108, /* TPOP Source Control              */
+					 /* Reserved (2)                     */
+	SUNI_TPOP_ARB_PRTL	= 0x114, /* TPOP Arbitrary Pointer LSB       */
+	SUNI_TPOP_ARB_PRTM	= 0x118, /* TPOP Arbitrary Pointer MSB       */
+	SUNI_TPOP_RESERVED2	= 0x11c, /* TPOP Reserved                    */
+	SUNI_TPOP_PATH_SIG	= 0x120, /* TPOP Path Signal Lable           */
+	SUNI_TPOP_PATH_STATUS	= 0x124, /* TPOP Path Status                 */
+					 /* Reserved (6)                     */
+	SUNI_RACP_CS		= 0x140, /* RACP Control/Status              */
+	SUNI_RACP_INTR		= 0x144, /* RACP Interrupt Enable/Status     */
+	SUNI_RACP_HDR_PATTERN	= 0x148, /* RACP Match Header Pattern        */
+	SUNI_RACP_HDR_MASK	= 0x14c, /* RACP Match Header Mask           */
+	SUNI_RACP_CORR_HCS	= 0x150, /* RACP Correctable HCS Error Count */
+	SUNI_RACP_UNCORR_HCS	= 0x154, /* RACP Uncorrectable HCS Err Count */
+					 /* Reserved (10)                    */
+	SUNI_TACP_CONTROL	= 0x180, /* TACP Control                     */
+	SUNI_TACP_IDLE_HDR_PAT	= 0x184, /* TACP Idle Cell Header Pattern    */
+	SUNI_TACP_IDLE_PAY_PAY	= 0x188, /* TACP Idle Cell Payld Octet Patrn */
+					 /* Reserved (5)                     */
+					 /* Reserved (24)                    */
+	/* FIXME: unused but name conflicts.
+	 * SUNI_MASTER_TEST	= 0x200,    SUNI Master Test                 */
+	SUNI_RESERVED_TEST	= 0x204  /* SUNI Reserved for Test           */
+};
 
 typedef struct _SUNI_STATS_
 {
@@ -993,13 +985,11 @@ typedef struct _SUNI_STATS_
    u32 racp_uchcs_count;            // uncorrectable HCS error count
 } IA_SUNI_STATS; 
 
-typedef struct iadev_t {  
+typedef struct iadev_priv {
 	/*-----base pointers into (i)chipSAR+ address space */   
-	u32 __iomem *phy;		/* base pointer into phy(SUNI) */  
-	u32 __iomem *dma;		/* base pointer into DMA control   
-						registers */  
-	u32 __iomem *reg;		/* base pointer to SAR registers  
-					   - Bus Interface Control Regs */  
+	u32 __iomem *phy;	/* Base pointer into phy (SUNI). */
+	u32 __iomem *dma;	/* Base pointer into DMA control registers. */
+	u32 __iomem *reg;	/* Base pointer to SAR registers. */
 	u32 __iomem *seg_reg;		/* base pointer to segmentation engine  
 						internal registers */  
 	u32 __iomem *reass_reg;		/* base pointer to reassemble engine  
@@ -1071,14 +1061,14 @@ typedef struct iadev_t {
 #define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data)  
 
 /******************* IDT77105 25MB/s PHY DEFINE *****************************/
-typedef struct {
-	u_int	mb25_master_ctrl;	/* Master control		     */
-	u_int	mb25_intr_status;	/* Interrupt status		     */
-	u_int	mb25_diag_control;	/* Diagnostic control		     */
-	u_int	mb25_led_hec;		/* LED driver and HEC status/control */
-	u_int	mb25_low_byte_counter;	/* Low byte counter		     */
-	u_int	mb25_high_byte_counter;	/* High byte counter		     */
-} ia_mb25_t;
+enum ia_mb25 {
+	MB25_MASTER_CTRL	= 0x00, /* Master control		     */
+	MB25_INTR_STATUS	= 0x04,	/* Interrupt status		     */
+	MB25_DIAG_CONTROL	= 0x08,	/* Diagnostic control		     */
+	MB25_LED_HEC		= 0x0c,	/* LED driver and HEC status/control */
+	MB25_LOW_BYTE_COUNTER	= 0x10,
+	MB25_HIGH_BYTE_COUNTER	= 0x14
+};
 
 /*
  * Master Control
@@ -1127,122 +1117,121 @@ typedef struct {
 #define FE_E3_PHY       0x0090          /* E3 */
 		     
 /*********************** SUNI_PM7345 PHY DEFINE HERE *********************/
-typedef struct _suni_pm7345_t
-{
-    u_int suni_config;     /* SUNI Configuration */
-    u_int suni_intr_enbl;  /* SUNI Interrupt Enable */
-    u_int suni_intr_stat;  /* SUNI Interrupt Status */
-    u_int suni_control;    /* SUNI Control */
-    u_int suni_id_reset;   /* SUNI Reset and Identity */
-    u_int suni_data_link_ctrl;
-    u_int suni_rboc_conf_intr_enbl;
-    u_int suni_rboc_stat;
-    u_int suni_ds3_frm_cfg;
-    u_int suni_ds3_frm_intr_enbl;
-    u_int suni_ds3_frm_intr_stat;
-    u_int suni_ds3_frm_stat;
-    u_int suni_rfdl_cfg;
-    u_int suni_rfdl_enbl_stat;
-    u_int suni_rfdl_stat;
-    u_int suni_rfdl_data;
-    u_int suni_pmon_chng;
-    u_int suni_pmon_intr_enbl_stat;
-    u_int suni_reserved1[0x13-0x11];
-    u_int suni_pmon_lcv_evt_cnt_lsb;
-    u_int suni_pmon_lcv_evt_cnt_msb;
-    u_int suni_pmon_fbe_evt_cnt_lsb;
-    u_int suni_pmon_fbe_evt_cnt_msb;
-    u_int suni_pmon_sez_det_cnt_lsb;
-    u_int suni_pmon_sez_det_cnt_msb;
-    u_int suni_pmon_pe_evt_cnt_lsb;
-    u_int suni_pmon_pe_evt_cnt_msb;
-    u_int suni_pmon_ppe_evt_cnt_lsb;
-    u_int suni_pmon_ppe_evt_cnt_msb;
-    u_int suni_pmon_febe_evt_cnt_lsb;
-    u_int suni_pmon_febe_evt_cnt_msb;
-    u_int suni_ds3_tran_cfg;
-    u_int suni_ds3_tran_diag;
-    u_int suni_reserved2[0x23-0x21];
-    u_int suni_xfdl_cfg;
-    u_int suni_xfdl_intr_st;
-    u_int suni_xfdl_xmit_data;
-    u_int suni_xboc_code;
-    u_int suni_splr_cfg;
-    u_int suni_splr_intr_en;
-    u_int suni_splr_intr_st;
-    u_int suni_splr_status;
-    u_int suni_splt_cfg;
-    u_int suni_splt_cntl;
-    u_int suni_splt_diag_g1;
-    u_int suni_splt_f1;
-    u_int suni_cppm_loc_meters;
-    u_int suni_cppm_chng_of_cppm_perf_meter;
-    u_int suni_cppm_b1_err_cnt_lsb;
-    u_int suni_cppm_b1_err_cnt_msb;
-    u_int suni_cppm_framing_err_cnt_lsb;
-    u_int suni_cppm_framing_err_cnt_msb;
-    u_int suni_cppm_febe_cnt_lsb;
-    u_int suni_cppm_febe_cnt_msb;
-    u_int suni_cppm_hcs_err_cnt_lsb;
-    u_int suni_cppm_hcs_err_cnt_msb;
-    u_int suni_cppm_idle_un_cell_cnt_lsb;
-    u_int suni_cppm_idle_un_cell_cnt_msb;
-    u_int suni_cppm_rcv_cell_cnt_lsb;
-    u_int suni_cppm_rcv_cell_cnt_msb;
-    u_int suni_cppm_xmit_cell_cnt_lsb;
-    u_int suni_cppm_xmit_cell_cnt_msb;
-    u_int suni_rxcp_ctrl;
-    u_int suni_rxcp_fctrl;
-    u_int suni_rxcp_intr_en_sts;
-    u_int suni_rxcp_idle_pat_h1;
-    u_int suni_rxcp_idle_pat_h2;
-    u_int suni_rxcp_idle_pat_h3;
-    u_int suni_rxcp_idle_pat_h4;
-    u_int suni_rxcp_idle_mask_h1;
-    u_int suni_rxcp_idle_mask_h2;
-    u_int suni_rxcp_idle_mask_h3;
-    u_int suni_rxcp_idle_mask_h4;
-    u_int suni_rxcp_cell_pat_h1;
-    u_int suni_rxcp_cell_pat_h2;
-    u_int suni_rxcp_cell_pat_h3;
-    u_int suni_rxcp_cell_pat_h4;
-    u_int suni_rxcp_cell_mask_h1;
-    u_int suni_rxcp_cell_mask_h2;
-    u_int suni_rxcp_cell_mask_h3;
-    u_int suni_rxcp_cell_mask_h4;
-    u_int suni_rxcp_hcs_cs;
-    u_int suni_rxcp_lcd_cnt_threshold;
-    u_int suni_reserved3[0x57-0x54];
-    u_int suni_txcp_ctrl;
-    u_int suni_txcp_intr_en_sts;
-    u_int suni_txcp_idle_pat_h1;
-    u_int suni_txcp_idle_pat_h2;
-    u_int suni_txcp_idle_pat_h3;
-    u_int suni_txcp_idle_pat_h4;
-    u_int suni_txcp_idle_pat_h5;
-    u_int suni_txcp_idle_payload;
-    u_int suni_e3_frm_fram_options;
-    u_int suni_e3_frm_maint_options;
-    u_int suni_e3_frm_fram_intr_enbl;
-    u_int suni_e3_frm_fram_intr_ind_stat;
-    u_int suni_e3_frm_maint_intr_enbl;
-    u_int suni_e3_frm_maint_intr_ind;
-    u_int suni_e3_frm_maint_stat;
-    u_int suni_reserved4;
-    u_int suni_e3_tran_fram_options;
-    u_int suni_e3_tran_stat_diag_options;
-    u_int suni_e3_tran_bip_8_err_mask;
-    u_int suni_e3_tran_maint_adapt_options;
-    u_int suni_ttb_ctrl;
-    u_int suni_ttb_trail_trace_id_stat;
-    u_int suni_ttb_ind_addr;
-    u_int suni_ttb_ind_data;
-    u_int suni_ttb_exp_payload_type;
-    u_int suni_ttb_payload_type_ctrl_stat;
-    u_int suni_pad5[0x7f-0x71];
-    u_int suni_master_test;
-    u_int suni_pad6[0xff-0x80];
-}suni_pm7345_t;
+enum suni_pm7345 {
+	SUNI_CONFIG			= 0x000, /* SUNI Configuration */
+	SUNI_INTR_ENBL			= 0x004, /* SUNI Interrupt Enable */
+	SUNI_INTR_STAT			= 0x008, /* SUNI Interrupt Status */
+	SUNI_CONTROL			= 0x00c, /* SUNI Control */
+	SUNI_ID_RESET			= 0x010, /* SUNI Reset and Identity */
+	SUNI_DATA_LINK_CTRL		= 0x014,
+	SUNI_RBOC_CONF_INTR_ENBL	= 0x018,
+	SUNI_RBOC_STAT			= 0x01c,
+	SUNI_DS3_FRM_CFG		= 0x020,
+	SUNI_DS3_FRM_INTR_ENBL		= 0x024,
+	SUNI_DS3_FRM_INTR_STAT		= 0x028,
+	SUNI_DS3_FRM_STAT		= 0x02c,
+	SUNI_RFDL_CFG			= 0x030,
+	SUNI_RFDL_ENBL_STAT		= 0x034,
+	SUNI_RFDL_STAT			= 0x038,
+	SUNI_RFDL_DATA			= 0x03c,
+	SUNI_PMON_CHNG			= 0x040,
+	SUNI_PMON_INTR_ENBL_STAT	= 0x044,
+	/* SUNI_RESERVED1 (0x13 - 0x11) */
+	SUNI_PMON_LCV_EVT_CNT_LSB	= 0x050,
+	SUNI_PMON_LCV_EVT_CNT_MSB	= 0x054,
+	SUNI_PMON_FBE_EVT_CNT_LSB	= 0x058,
+	SUNI_PMON_FBE_EVT_CNT_MSB	= 0x05c,
+	SUNI_PMON_SEZ_DET_CNT_LSB	= 0x060,
+	SUNI_PMON_SEZ_DET_CNT_MSB	= 0x064,
+	SUNI_PMON_PE_EVT_CNT_LSB	= 0x068,
+	SUNI_PMON_PE_EVT_CNT_MSB	= 0x06c,
+	SUNI_PMON_PPE_EVT_CNT_LSB	= 0x070,
+	SUNI_PMON_PPE_EVT_CNT_MSB	= 0x074,
+	SUNI_PMON_FEBE_EVT_CNT_LSB	= 0x078,
+	SUNI_PMON_FEBE_EVT_CNT_MSB	= 0x07c,
+	SUNI_DS3_TRAN_CFG		= 0x080,
+	SUNI_DS3_TRAN_DIAG		= 0x084,
+	/* SUNI_RESERVED2 (0x23 - 0x21) */
+	SUNI_XFDL_CFG			= 0x090,
+	SUNI_XFDL_INTR_ST		= 0x094,
+	SUNI_XFDL_XMIT_DATA		= 0x098,
+	SUNI_XBOC_CODE			= 0x09c,
+	SUNI_SPLR_CFG			= 0x0a0,
+	SUNI_SPLR_INTR_EN		= 0x0a4,
+	SUNI_SPLR_INTR_ST		= 0x0a8,
+	SUNI_SPLR_STATUS		= 0x0ac,
+	SUNI_SPLT_CFG			= 0x0b0,
+	SUNI_SPLT_CNTL			= 0x0b4,
+	SUNI_SPLT_DIAG_G1		= 0x0b8,
+	SUNI_SPLT_F1			= 0x0bc,
+	SUNI_CPPM_LOC_METERS		= 0x0c0,
+	SUNI_CPPM_CHG_OF_CPPM_PERF_METR	= 0x0c4,
+	SUNI_CPPM_B1_ERR_CNT_LSB	= 0x0c8,
+	SUNI_CPPM_B1_ERR_CNT_MSB	= 0x0cc,
+	SUNI_CPPM_FRAMING_ERR_CNT_LSB	= 0x0d0,
+	SUNI_CPPM_FRAMING_ERR_CNT_MSB	= 0x0d4,
+	SUNI_CPPM_FEBE_CNT_LSB		= 0x0d8,
+	SUNI_CPPM_FEBE_CNT_MSB		= 0x0dc,
+	SUNI_CPPM_HCS_ERR_CNT_LSB	= 0x0e0,
+	SUNI_CPPM_HCS_ERR_CNT_MSB	= 0x0e4,
+	SUNI_CPPM_IDLE_UN_CELL_CNT_LSB	= 0x0e8,
+	SUNI_CPPM_IDLE_UN_CELL_CNT_MSB	= 0x0ec,
+	SUNI_CPPM_RCV_CELL_CNT_LSB	= 0x0f0,
+	SUNI_CPPM_RCV_CELL_CNT_MSB	= 0x0f4,
+	SUNI_CPPM_XMIT_CELL_CNT_LSB	= 0x0f8,
+	SUNI_CPPM_XMIT_CELL_CNT_MSB	= 0x0fc,
+	SUNI_RXCP_CTRL			= 0x100,
+	SUNI_RXCP_FCTRL			= 0x104,
+	SUNI_RXCP_INTR_EN_STS		= 0x108,
+	SUNI_RXCP_IDLE_PAT_H1		= 0x10c,
+	SUNI_RXCP_IDLE_PAT_H2		= 0x110,
+	SUNI_RXCP_IDLE_PAT_H3		= 0x114,
+	SUNI_RXCP_IDLE_PAT_H4		= 0x118,
+	SUNI_RXCP_IDLE_MASK_H1		= 0x11c,
+	SUNI_RXCP_IDLE_MASK_H2		= 0x120,
+	SUNI_RXCP_IDLE_MASK_H3		= 0x124,
+	SUNI_RXCP_IDLE_MASK_H4		= 0x128,
+	SUNI_RXCP_CELL_PAT_H1		= 0x12c,
+	SUNI_RXCP_CELL_PAT_H2		= 0x130,
+	SUNI_RXCP_CELL_PAT_H3		= 0x134,
+	SUNI_RXCP_CELL_PAT_H4		= 0x138,
+	SUNI_RXCP_CELL_MASK_H1		= 0x13c,
+	SUNI_RXCP_CELL_MASK_H2		= 0x140,
+	SUNI_RXCP_CELL_MASK_H3		= 0x144,
+	SUNI_RXCP_CELL_MASK_H4		= 0x148,
+	SUNI_RXCP_HCS_CS		= 0x14c,
+	SUNI_RXCP_LCD_CNT_THRESHOLD	= 0x150,
+	/* SUNI_RESERVED3 (0x57 - 0x54) */
+	SUNI_TXCP_CTRL			= 0x160,
+	SUNI_TXCP_INTR_EN_STS		= 0x164,
+	SUNI_TXCP_IDLE_PAT_H1		= 0x168,
+	SUNI_TXCP_IDLE_PAT_H2		= 0x16c,
+	SUNI_TXCP_IDLE_PAT_H3		= 0x170,
+	SUNI_TXCP_IDLE_PAT_H4		= 0x174,
+	SUNI_TXCP_IDLE_PAT_H5		= 0x178,
+	SUNI_TXCP_IDLE_PAYLOAD		= 0x17c,
+	SUNI_E3_FRM_FRAM_OPTIONS	= 0x180,
+	SUNI_E3_FRM_MAINT_OPTIONS	= 0x184,
+	SUNI_E3_FRM_FRAM_INTR_ENBL	= 0x188,
+	SUNI_E3_FRM_FRAM_INTR_IND_STAT	= 0x18c,
+	SUNI_E3_FRM_MAINT_INTR_ENBL	= 0x190,
+	SUNI_E3_FRM_MAINT_INTR_IND	= 0x194,
+	SUNI_E3_FRM_MAINT_STAT		= 0x198,
+	SUNI_RESERVED4			= 0x19c,
+	SUNI_E3_TRAN_FRAM_OPTIONS	= 0x1a0,
+	SUNI_E3_TRAN_STAT_DIAG_OPTIONS	= 0x1a4,
+	SUNI_E3_TRAN_BIP_8_ERR_MASK	= 0x1a8,
+	SUNI_E3_TRAN_MAINT_ADAPT_OPTS	= 0x1ac,
+	SUNI_TTB_CTRL			= 0x1b0,
+	SUNI_TTB_TRAIL_TRACE_ID_STAT	= 0x1b4,
+	SUNI_TTB_IND_ADDR		= 0x1b8,
+	SUNI_TTB_IND_DATA		= 0x1bc,
+	SUNI_TTB_EXP_PAYLOAD_TYPE	= 0x1c0,
+	SUNI_TTB_PAYLOAD_TYPE_CTRL_STAT	= 0x1c4,
+	/* SUNI_PAD5 (0x7f - 0x71) */
+	SUNI_MASTER_TEST		= 0x200,
+	/* SUNI_PAD6 (0xff - 0x80) */
+};
 
 #define SUNI_PM7345_T suni_pm7345_t
 #define SUNI_PM7345     0x20            /* Suni chip type */
diff -druNp linux-libre-3.1-gnu1/drivers/atm/lanai.c linux-libre-3.2-gnu1/drivers/atm/lanai.c
--- linux-libre-3.1-gnu1/drivers/atm/lanai.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/atm/lanai.c	2012-01-04 18:55:44.000000000 -0500
@@ -1457,10 +1457,9 @@ static int __devinit vcc_table_allocate(
 	return (lanai->vccs == NULL) ? -ENOMEM : 0;
 #else
 	int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *);
-	lanai->vccs = (struct lanai_vcc **) vmalloc(bytes);
+	lanai->vccs = vzalloc(bytes);
 	if (unlikely(lanai->vccs == NULL))
 		return -ENOMEM;
-	memset(lanai->vccs, 0, bytes);
 	return 0;
 #endif
 }
diff -druNp linux-libre-3.1-gnu1/drivers/base/base.h linux-libre-3.2-gnu1/drivers/base/base.h
--- linux-libre-3.1-gnu1/drivers/base/base.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/base.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
+#include <linux/notifier.h>
 
 /**
  * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
diff -druNp linux-libre-3.1-gnu1/drivers/base/class.c linux-libre-3.2-gnu1/drivers/base/class.c
--- linux-libre-3.1-gnu1/drivers/base/class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/class.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,18 @@ static ssize_t class_attr_store(struct k
 	return ret;
 }
 
+static const void *class_attr_namespace(struct kobject *kobj,
+					const struct attribute *attr)
+{
+	struct class_attribute *class_attr = to_class_attr(attr);
+	struct subsys_private *cp = to_subsys_private(kobj);
+	const void *ns = NULL;
+
+	if (class_attr->namespace)
+		ns = class_attr->namespace(cp->class, class_attr);
+	return ns;
+}
+
 static void class_release(struct kobject *kobj)
 {
 	struct subsys_private *cp = to_subsys_private(kobj);
@@ -72,8 +84,9 @@ static const struct kobj_ns_type_operati
 }
 
 static const struct sysfs_ops class_sysfs_ops = {
-	.show	= class_attr_show,
-	.store	= class_attr_store,
+	.show	   = class_attr_show,
+	.store	   = class_attr_store,
+	.namespace = class_attr_namespace,
 };
 
 static struct kobj_type class_ktype = {
diff -druNp linux-libre-3.1-gnu1/drivers/base/core.c linux-libre-3.2-gnu1/drivers/base/core.c
--- linux-libre-3.1-gnu1/drivers/base/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -1743,6 +1744,10 @@ void device_shutdown(void)
 		list_del_init(&dev->kobj.entry);
 		spin_unlock(&devices_kset->list_lock);
 
+		/* Don't allow any more runtime suspends */
+		pm_runtime_get_noresume(dev);
+		pm_runtime_barrier(dev);
+
 		if (dev->bus && dev->bus->shutdown) {
 			dev_dbg(dev, "shutdown\n");
 			dev->bus->shutdown(dev);
@@ -1764,8 +1769,8 @@ void device_shutdown(void)
 
 #ifdef CONFIG_PRINTK
 
-static int __dev_printk(const char *level, const struct device *dev,
-			struct va_format *vaf)
+int __dev_printk(const char *level, const struct device *dev,
+		 struct va_format *vaf)
 {
 	if (!dev)
 		return printk("%s(NULL device *): %pV", level, vaf);
@@ -1773,6 +1778,7 @@ static int __dev_printk(const char *leve
 	return printk("%s%s %s: %pV",
 		      level, dev_driver_string(dev), dev_name(dev), vaf);
 }
+EXPORT_SYMBOL(__dev_printk);
 
 int dev_printk(const char *level, const struct device *dev,
 	       const char *fmt, ...)
diff -druNp linux-libre-3.1-gnu1/drivers/base/dd.c linux-libre-3.2-gnu1/drivers/base/dd.c
--- linux-libre-3.1-gnu1/drivers/base/dd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/dd.c	2012-01-04 18:55:44.000000000 -0500
@@ -147,6 +147,9 @@ probe_failed:
 		printk(KERN_WARNING
 		       "%s: probe of %s failed with error %d\n",
 		       drv->name, dev_name(dev), ret);
+	} else {
+		pr_debug("%s: probe of %s rejects match %d\n",
+		       drv->name, dev_name(dev), ret);
 	}
 	/*
 	 * Ignore errors returned by ->probe so that the next driver can try
diff -druNp linux-libre-3.1-gnu1/drivers/base/dma-coherent.c linux-libre-3.2-gnu1/drivers/base/dma-coherent.c
--- linux-libre-3.1-gnu1/drivers/base/dma-coherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/dma-coherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 
 struct dma_coherent_mem {
diff -druNp linux-libre-3.1-gnu1/drivers/base/dma-mapping.c linux-libre-3.2-gnu1/drivers/base/dma-mapping.c
--- linux-libre-3.1-gnu1/drivers/base/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/base/hypervisor.c linux-libre-3.2-gnu1/drivers/base/hypervisor.c
--- linux-libre-3.1-gnu1/drivers/base/hypervisor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/hypervisor.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/export.h>
 #include "base.h"
 
 struct kobject *hypervisor_kobj;
diff -druNp linux-libre-3.1-gnu1/drivers/base/memory.c linux-libre-3.2-gnu1/drivers/base/memory.c
--- linux-libre-3.1-gnu1/drivers/base/memory.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/memory.c	2012-01-04 18:55:44.000000000 -0500
@@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long
 }
 
 /*
+ * The probe routines leave the pages reserved, just as the bootmem code does.
+ * Make sure they're still that way.
+ */
+static bool pages_correctly_reserved(unsigned long start_pfn,
+					unsigned long nr_pages)
+{
+	int i, j;
+	struct page *page;
+	unsigned long pfn = start_pfn;
+
+	/*
+	 * memmap between sections is not contiguous except with
+	 * SPARSEMEM_VMEMMAP. We lookup the page once per section
+	 * and assume memmap is contiguous within each section
+	 */
+	for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
+		if (WARN_ON_ONCE(!pfn_valid(pfn)))
+			return false;
+		page = pfn_to_page(pfn);
+
+		for (j = 0; j < PAGES_PER_SECTION; j++) {
+			if (PageReserved(page + j))
+				continue;
+
+			printk(KERN_WARNING "section number %ld page number %d "
+				"not reserved, was it already online?\n",
+				pfn_to_section_nr(pfn), j);
+
+			return false;
+		}
+	}
+
+	return true;
+}
+
+/*
  * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
  * OK to have direct references to sparsemem variables in here.
  */
 static int
 memory_block_action(unsigned long phys_index, unsigned long action)
 {
-	int i;
 	unsigned long start_pfn, start_paddr;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
 	struct page *first_page;
@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_i
 
 	first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
 
-	/*
-	 * The probe routines leave the pages reserved, just
-	 * as the bootmem code does.  Make sure they're still
-	 * that way.
-	 */
-	if (action == MEM_ONLINE) {
-		for (i = 0; i < nr_pages; i++) {
-			if (PageReserved(first_page+i))
-				continue;
-
-			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online?\n",
-				phys_index, i);
-			return -EBUSY;
-		}
-	}
-
 	switch (action) {
 		case MEM_ONLINE:
 			start_pfn = page_to_pfn(first_page);
+
+			if (!pages_correctly_reserved(start_pfn, nr_pages))
+				return -EBUSY;
+
 			ret = online_pages(start_pfn, nr_pages);
 			break;
 		case MEM_OFFLINE:
@@ -380,9 +402,13 @@ memory_probe_store(struct class *class,
 	u64 phys_addr;
 	int nid;
 	int i, ret;
+	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
+	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
+		return -EINVAL;
+
 	for (i = 0; i < sections_per_block; i++) {
 		nid = memory_add_physaddr_to_nid(phys_addr);
 		ret = add_memory(nid, phys_addr,
diff -druNp linux-libre-3.1-gnu1/drivers/base/node.c linux-libre-3.2-gnu1/drivers/base/node.c
--- linux-libre-3.1-gnu1/drivers/base/node.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/node.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,12 +127,13 @@ static ssize_t node_read_meminfo(struct
 		       nid, K(node_page_state(nid, NR_WRITEBACK)),
 		       nid, K(node_page_state(nid, NR_FILE_PAGES)),
 		       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
-		       nid, K(node_page_state(nid, NR_ANON_PAGES)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		       nid, K(node_page_state(nid, NR_ANON_PAGES)
 			+ node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR
+			HPAGE_PMD_NR),
+#else
+		       nid, K(node_page_state(nid, NR_ANON_PAGES)),
 #endif
-		       ),
 		       nid, K(node_page_state(nid, NR_SHMEM)),
 		       nid, node_page_state(nid, NR_KERNEL_STACK) *
 				THREAD_SIZE / 1024,
@@ -143,13 +144,14 @@ static ssize_t node_read_meminfo(struct
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
 				node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
-		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 			, nid,
 			K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR)
+			HPAGE_PMD_NR));
+#else
+		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
 #endif
-		       );
 	n += hugetlb_report_node_meminfo(nid, buf + n);
 	return n;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/base/platform.c linux-libre-3.2-gnu1/drivers/base/platform.c
--- linux-libre-3.1-gnu1/drivers/base/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -375,52 +375,64 @@ void platform_device_unregister(struct p
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
- * platform_device_register_resndata - add a platform-level device with
+ * platform_device_register_full - add a platform-level device with
  * resources and platform-specific data
  *
- * @parent: parent device for the device we're adding
- * @name: base name of the device we're adding
- * @id: instance id
- * @res: set of resources that needs to be allocated for the device
- * @num: number of resources
- * @data: platform specific data for this platform device
- * @size: size of platform specific data
+ * @pdevinfo: data used to create device
  *
  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
  */
-struct platform_device *platform_device_register_resndata(
-		struct device *parent,
-		const char *name, int id,
-		const struct resource *res, unsigned int num,
-		const void *data, size_t size)
+struct platform_device *platform_device_register_full(
+		struct platform_device_info *pdevinfo)
 {
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
 
-	pdev = platform_device_alloc(name, id);
+	pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
 	if (!pdev)
-		goto err;
+		goto err_alloc;
 
-	pdev->dev.parent = parent;
+	pdev->dev.parent = pdevinfo->parent;
 
-	ret = platform_device_add_resources(pdev, res, num);
+	if (pdevinfo->dma_mask) {
+		/*
+		 * This memory isn't freed when the device is put,
+		 * I don't have a nice idea for that though.  Conceptually
+		 * dma_mask in struct device should not be a pointer.
+		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
+		 */
+		pdev->dev.dma_mask =
+			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+		if (!pdev->dev.dma_mask)
+			goto err;
+
+		*pdev->dev.dma_mask = pdevinfo->dma_mask;
+		pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
+	}
+
+	ret = platform_device_add_resources(pdev,
+			pdevinfo->res, pdevinfo->num_res);
 	if (ret)
 		goto err;
 
-	ret = platform_device_add_data(pdev, data, size);
+	ret = platform_device_add_data(pdev,
+			pdevinfo->data, pdevinfo->size_data);
 	if (ret)
 		goto err;
 
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		kfree(pdev->dev.dma_mask);
+
+err_alloc:
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
 
 	return pdev;
 }
-EXPORT_SYMBOL_GPL(platform_device_register_resndata);
+EXPORT_SYMBOL_GPL(platform_device_register_full);
 
 static int platform_drv_probe(struct device *_dev)
 {
@@ -614,7 +626,7 @@ static int platform_uevent(struct device
 		return rc;
 
 	add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
-		(pdev->id_entry) ? pdev->id_entry->name : pdev->name);
+			pdev->name);
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/clock_ops.c linux-libre-3.2-gnu1/drivers/base/power/clock_ops.c
--- linux-libre-3.1-gnu1/drivers/base/power/clock_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/clock_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,18 +10,13 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
 #ifdef CONFIG_PM
 
-struct pm_clk_data {
-	struct list_head clock_list;
-	spinlock_t lock;
-};
-
 enum pce_status {
 	PCE_STATUS_NONE = 0,
 	PCE_STATUS_ACQUIRED,
@@ -36,11 +31,6 @@ struct pm_clock_entry {
 	enum pce_status status;
 };
 
-static struct pm_clk_data *__to_pcd(struct device *dev)
-{
-	return dev ? dev->power.subsys_data : NULL;
-}
-
 /**
  * pm_clk_acquire - Acquire a device clock.
  * @dev: Device whose clock is to be acquired.
@@ -67,10 +57,10 @@ static void pm_clk_acquire(struct device
  */
 int pm_clk_add(struct device *dev, const char *con_id)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!pcd)
+	if (!psd)
 		return -EINVAL;
 
 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -91,9 +81,9 @@ int pm_clk_add(struct device *dev, const
 
 	pm_clk_acquire(dev, ce);
 
-	spin_lock_irq(&pcd->lock);
-	list_add_tail(&ce->node, &pcd->clock_list);
-	spin_unlock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
+	list_add_tail(&ce->node, &psd->clock_list);
+	spin_unlock_irq(&psd->lock);
 	return 0;
 }
 
@@ -114,9 +104,7 @@ static void __pm_clk_remove(struct pm_cl
 			clk_put(ce->clk);
 	}
 
-	if (ce->con_id)
-		kfree(ce->con_id);
-
+	kfree(ce->con_id);
 	kfree(ce);
 }
 
@@ -130,15 +118,15 @@ static void __pm_clk_remove(struct pm_cl
  */
 void pm_clk_remove(struct device *dev, const char *con_id)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!pcd)
+	if (!psd)
 		return;
 
-	spin_lock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
 
-	list_for_each_entry(ce, &pcd->clock_list, node) {
+	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (!con_id && !ce->con_id)
 			goto remove;
 		else if (!con_id || !ce->con_id)
@@ -147,12 +135,12 @@ void pm_clk_remove(struct device *dev, c
 			goto remove;
 	}
 
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 	return;
 
  remove:
 	list_del(&ce->node);
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 
 	__pm_clk_remove(ce);
 }
@@ -161,23 +149,27 @@ void pm_clk_remove(struct device *dev, c
  * pm_clk_init - Initialize a device's list of power management clocks.
  * @dev: Device to initialize the list of PM clocks for.
  *
- * Allocate a struct pm_clk_data object, initialize its lock member and
- * make the @dev's power.subsys_data field point to it.
+ * Initialize the lock and clock_list members of the device's pm_subsys_data
+ * object.
  */
-int pm_clk_init(struct device *dev)
+void pm_clk_init(struct device *dev)
 {
-	struct pm_clk_data *pcd;
-
-	pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
-	if (!pcd) {
-		dev_err(dev, "Not enough memory for PM clock data.\n");
-		return -ENOMEM;
-	}
+	struct pm_subsys_data *psd = dev_to_psd(dev);
+	if (psd)
+		INIT_LIST_HEAD(&psd->clock_list);
+}
 
-	INIT_LIST_HEAD(&pcd->clock_list);
-	spin_lock_init(&pcd->lock);
-	dev->power.subsys_data = pcd;
-	return 0;
+/**
+ * pm_clk_create - Create and initialize a device's list of PM clocks.
+ * @dev: Device to create and initialize the list of PM clocks for.
+ *
+ * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
+ * members and make the @dev's power.subsys_data field point to it.
+ */
+int pm_clk_create(struct device *dev)
+{
+	int ret = dev_pm_get_subsys_data(dev);
+	return ret < 0 ? ret : 0;
 }
 
 /**
@@ -185,29 +177,28 @@ int pm_clk_init(struct device *dev)
  * @dev: Device to destroy the list of PM clocks for.
  *
  * Clear the @dev's power.subsys_data field, remove the list of clock entries
- * from the struct pm_clk_data object pointed to by it before and free
+ * from the struct pm_subsys_data object pointed to by it before and free
  * that object.
  */
 void pm_clk_destroy(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce, *c;
 	struct list_head list;
 
-	if (!pcd)
+	if (!psd)
 		return;
 
-	dev->power.subsys_data = NULL;
 	INIT_LIST_HEAD(&list);
 
-	spin_lock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
 
-	list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
+	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
 		list_move(&ce->node, &list);
 
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 
-	kfree(pcd);
+	dev_pm_put_subsys_data(dev);
 
 	list_for_each_entry_safe_reverse(ce, c, &list, node) {
 		list_del(&ce->node);
@@ -225,25 +216,26 @@ void pm_clk_destroy(struct device *dev)
  */
 int pm_clk_suspend(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!pcd)
+	if (!psd)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
+	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
 		if (ce->status < PCE_STATUS_ERROR) {
-			clk_disable(ce->clk);
+			if (ce->status == PCE_STATUS_ENABLED)
+				clk_disable(ce->clk);
 			ce->status = PCE_STATUS_ACQUIRED;
 		}
 	}
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -254,25 +246,25 @@ int pm_clk_suspend(struct device *dev)
  */
 int pm_clk_resume(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!pcd)
+	if (!psd)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry(ce, &pcd->clock_list, node) {
+	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (ce->status < PCE_STATUS_ERROR) {
 			clk_enable(ce->clk);
 			ce->status = PCE_STATUS_ENABLED;
 		}
 	}
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -310,7 +302,7 @@ static int pm_clk_notify(struct notifier
 		if (dev->pm_domain)
 			break;
 
-		error = pm_clk_init(dev);
+		error = pm_clk_create(dev);
 		if (error)
 			break;
 
@@ -345,22 +337,22 @@ static int pm_clk_notify(struct notifier
  */
 int pm_clk_suspend(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	/* If there is no driver, the clocks are already disabled. */
-	if (!pcd || !dev->driver)
+	if (!psd || !dev->driver)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry_reverse(ce, &pcd->clock_list, node)
+	list_for_each_entry_reverse(ce, &psd->clock_list, node)
 		clk_disable(ce->clk);
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -371,22 +363,22 @@ int pm_clk_suspend(struct device *dev)
  */
 int pm_clk_resume(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	/* If there is no driver, the clocks should remain disabled. */
-	if (!pcd || !dev->driver)
+	if (!psd || !dev->driver)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry(ce, &pcd->clock_list, node)
+	list_for_each_entry(ce, &psd->clock_list, node)
 		clk_enable(ce->clk);
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/common.c linux-libre-3.2-gnu1/drivers/base/power/common.c
--- linux-libre-3.1-gnu1/drivers/base/power/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/power/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ * drivers/base/power/common.c - Common device power management code.
+ *
+ * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/pm_clock.h>
+
+/**
+ * dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
+ * @dev: Device to handle.
+ *
+ * If power.subsys_data is NULL, point it to a new object, otherwise increment
+ * its reference counter.  Return 1 if a new object has been created, otherwise
+ * return 0 or error code.
+ */
+int dev_pm_get_subsys_data(struct device *dev)
+{
+	struct pm_subsys_data *psd;
+	int ret = 0;
+
+	psd = kzalloc(sizeof(*psd), GFP_KERNEL);
+	if (!psd)
+		return -ENOMEM;
+
+	spin_lock_irq(&dev->power.lock);
+
+	if (dev->power.subsys_data) {
+		dev->power.subsys_data->refcount++;
+	} else {
+		spin_lock_init(&psd->lock);
+		psd->refcount = 1;
+		dev->power.subsys_data = psd;
+		pm_clk_init(dev);
+		psd = NULL;
+		ret = 1;
+	}
+
+	spin_unlock_irq(&dev->power.lock);
+
+	/* kfree() verifies that its argument is nonzero. */
+	kfree(psd);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data);
+
+/**
+ * dev_pm_put_subsys_data - Drop reference to power.subsys_data.
+ * @dev: Device to handle.
+ *
+ * If the reference counter of power.subsys_data is zero after dropping the
+ * reference, power.subsys_data is removed.  Return 1 if that happens or 0
+ * otherwise.
+ */
+int dev_pm_put_subsys_data(struct device *dev)
+{
+	struct pm_subsys_data *psd;
+	int ret = 0;
+
+	spin_lock_irq(&dev->power.lock);
+
+	psd = dev_to_psd(dev);
+	if (!psd) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (--psd->refcount == 0) {
+		dev->power.subsys_data = NULL;
+		kfree(psd);
+		ret = 1;
+	}
+
+ out:
+	spin_unlock_irq(&dev->power.lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/domain.c linux-libre-3.2-gnu1/drivers/base/power/domain.c
--- linux-libre-3.1-gnu1/drivers/base/power/domain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/domain.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,10 +29,20 @@ static struct generic_pm_domain *dev_to_
 	return pd_to_genpd(dev->pm_domain);
 }
 
-static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
+static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
 {
-	if (!WARN_ON(genpd->sd_count == 0))
-			genpd->sd_count--;
+	bool ret = false;
+
+	if (!WARN_ON(atomic_read(&genpd->sd_count) == 0))
+		ret = !!atomic_dec_and_test(&genpd->sd_count);
+
+	return ret;
+}
+
+static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
+{
+	atomic_inc(&genpd->sd_count);
+	smp_mb__after_atomic_inc();
 }
 
 static void genpd_acquire_lock(struct generic_pm_domain *genpd)
@@ -71,60 +81,97 @@ static void genpd_set_active(struct gene
 }
 
 /**
- * pm_genpd_poweron - Restore power to a given PM domain and its parents.
+ * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
  * @genpd: PM domain to power up.
  *
- * Restore power to @genpd and all of its parents so that it is possible to
+ * Restore power to @genpd and all of its masters so that it is possible to
  * resume a device belonging to it.
  */
-int pm_genpd_poweron(struct generic_pm_domain *genpd)
+int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct generic_pm_domain *parent = genpd->parent;
+	struct gpd_link *link;
+	DEFINE_WAIT(wait);
 	int ret = 0;
 
- start:
-	if (parent) {
-		genpd_acquire_lock(parent);
-		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
-	} else {
+	/* If the domain's master is being waited for, we have to wait too. */
+	for (;;) {
+		prepare_to_wait(&genpd->status_wait_queue, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if (genpd->status != GPD_STATE_WAIT_MASTER)
+			break;
+		mutex_unlock(&genpd->lock);
+
+		schedule();
+
 		mutex_lock(&genpd->lock);
 	}
+	finish_wait(&genpd->status_wait_queue, &wait);
 
 	if (genpd->status == GPD_STATE_ACTIVE
 	    || (genpd->prepared_count > 0 && genpd->suspend_power_off))
-		goto out;
+		return 0;
 
 	if (genpd->status != GPD_STATE_POWER_OFF) {
 		genpd_set_active(genpd);
-		goto out;
+		return 0;
 	}
 
-	if (parent && parent->status != GPD_STATE_ACTIVE) {
+	/*
+	 * The list is guaranteed not to change while the loop below is being
+	 * executed, unless one of the masters' .power_on() callbacks fiddles
+	 * with it.
+	 */
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_inc(link->master);
+		genpd->status = GPD_STATE_WAIT_MASTER;
+
 		mutex_unlock(&genpd->lock);
-		genpd_release_lock(parent);
 
-		ret = pm_genpd_poweron(parent);
-		if (ret)
-			return ret;
+		ret = pm_genpd_poweron(link->master);
 
-		goto start;
+		mutex_lock(&genpd->lock);
+
+		/*
+		 * The "wait for parent" status is guaranteed not to change
+		 * while the master is powering on.
+		 */
+		genpd->status = GPD_STATE_POWER_OFF;
+		wake_up_all(&genpd->status_wait_queue);
+		if (ret) {
+			genpd_sd_counter_dec(link->master);
+			goto err;
+		}
 	}
 
 	if (genpd->power_on) {
 		ret = genpd->power_on(genpd);
 		if (ret)
-			goto out;
+			goto err;
 	}
 
 	genpd_set_active(genpd);
-	if (parent)
-		parent->sd_count++;
 
- out:
-	mutex_unlock(&genpd->lock);
-	if (parent)
-		genpd_release_lock(parent);
+	return 0;
+
+ err:
+	list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node)
+		genpd_sd_counter_dec(link->master);
+
+	return ret;
+}
 
+/**
+ * pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * @genpd: PM domain to power up.
+ */
+int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+	int ret;
+
+	mutex_lock(&genpd->lock);
+	ret = __pm_genpd_poweron(genpd);
+	mutex_unlock(&genpd->lock);
 	return ret;
 }
 
@@ -134,18 +181,19 @@ int pm_genpd_poweron(struct generic_pm_d
 
 /**
  * __pm_genpd_save_device - Save the pre-suspend state of a device.
- * @dle: Device list entry of the device to save the state of.
+ * @pdd: Domain data of the device to save the state of.
  * @genpd: PM domain the device belongs to.
  */
-static int __pm_genpd_save_device(struct dev_list_entry *dle,
+static int __pm_genpd_save_device(struct pm_domain_data *pdd,
 				  struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct device *dev = dle->dev;
+	struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+	struct device *dev = pdd->dev;
 	struct device_driver *drv = dev->driver;
 	int ret = 0;
 
-	if (dle->need_restore)
+	if (gpd_data->need_restore)
 		return 0;
 
 	mutex_unlock(&genpd->lock);
@@ -163,24 +211,25 @@ static int __pm_genpd_save_device(struct
 	mutex_lock(&genpd->lock);
 
 	if (!ret)
-		dle->need_restore = true;
+		gpd_data->need_restore = true;
 
 	return ret;
 }
 
 /**
  * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
- * @dle: Device list entry of the device to restore the state of.
+ * @pdd: Domain data of the device to restore the state of.
  * @genpd: PM domain the device belongs to.
  */
-static void __pm_genpd_restore_device(struct dev_list_entry *dle,
+static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
 				      struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct device *dev = dle->dev;
+	struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+	struct device *dev = pdd->dev;
 	struct device_driver *drv = dev->driver;
 
-	if (!dle->need_restore)
+	if (!gpd_data->need_restore)
 		return;
 
 	mutex_unlock(&genpd->lock);
@@ -197,7 +246,7 @@ static void __pm_genpd_restore_device(st
 
 	mutex_lock(&genpd->lock);
 
-	dle->need_restore = false;
+	gpd_data->need_restore = false;
 }
 
 /**
@@ -211,7 +260,8 @@ static void __pm_genpd_restore_device(st
  */
 static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
 {
-	return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
+	return genpd->status == GPD_STATE_WAIT_MASTER
+		|| genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
 }
 
 /**
@@ -238,8 +288,8 @@ void genpd_queue_power_off_work(struct g
 static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct generic_pm_domain *parent;
-	struct dev_list_entry *dle;
+	struct pm_domain_data *pdd;
+	struct gpd_link *link;
 	unsigned int not_suspended;
 	int ret = 0;
 
@@ -247,19 +297,22 @@ static int pm_genpd_poweroff(struct gene
 	/*
 	 * Do not try to power off the domain in the following situations:
 	 * (1) The domain is already in the "power off" state.
-	 * (2) System suspend is in progress.
+	 * (2) The domain is waiting for its master to power up.
 	 * (3) One of the domain's devices is being resumed right now.
+	 * (4) System suspend is in progress.
 	 */
-	if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
-	    || genpd->resume_count > 0)
+	if (genpd->status == GPD_STATE_POWER_OFF
+	    || genpd->status == GPD_STATE_WAIT_MASTER
+	    || genpd->resume_count > 0 || genpd->prepared_count > 0)
 		return 0;
 
-	if (genpd->sd_count > 0)
+	if (atomic_read(&genpd->sd_count) > 0)
 		return -EBUSY;
 
 	not_suspended = 0;
-	list_for_each_entry(dle, &genpd->dev_list, node)
-		if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
+	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
+		    || pdd->dev->power.irq_safe))
 			not_suspended++;
 
 	if (not_suspended > genpd->in_progress)
@@ -282,54 +335,50 @@ static int pm_genpd_poweroff(struct gene
 	genpd->status = GPD_STATE_BUSY;
 	genpd->poweroff_task = current;
 
-	list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
-		ret = __pm_genpd_save_device(dle, genpd);
+	list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
+		ret = atomic_read(&genpd->sd_count) == 0 ?
+			__pm_genpd_save_device(pdd, genpd) : -EBUSY;
+
+		if (genpd_abort_poweroff(genpd))
+			goto out;
+
 		if (ret) {
 			genpd_set_active(genpd);
 			goto out;
 		}
 
-		if (genpd_abort_poweroff(genpd))
-			goto out;
-
 		if (genpd->status == GPD_STATE_REPEAT) {
 			genpd->poweroff_task = NULL;
 			goto start;
 		}
 	}
 
-	parent = genpd->parent;
-	if (parent) {
-		mutex_unlock(&genpd->lock);
-
-		genpd_acquire_lock(parent);
-		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
-
-		if (genpd_abort_poweroff(genpd)) {
-			genpd_release_lock(parent);
+	if (genpd->power_off) {
+		if (atomic_read(&genpd->sd_count) > 0) {
+			ret = -EBUSY;
 			goto out;
 		}
-	}
 
-	if (genpd->power_off) {
+		/*
+		 * If sd_count > 0 at this point, one of the subdomains hasn't
+		 * managed to call pm_genpd_poweron() for the master yet after
+		 * incrementing it.  In that case pm_genpd_poweron() will wait
+		 * for us to drop the lock, so we can call .power_off() and let
+		 * the pm_genpd_poweron() restore power for us (this shouldn't
+		 * happen very often).
+		 */
 		ret = genpd->power_off(genpd);
 		if (ret == -EBUSY) {
 			genpd_set_active(genpd);
-			if (parent)
-				genpd_release_lock(parent);
-
 			goto out;
 		}
 	}
 
 	genpd->status = GPD_STATE_POWER_OFF;
 
-	if (parent) {
-		genpd_sd_counter_dec(parent);
-		if (parent->sd_count == 0)
-			genpd_queue_power_off_work(parent);
-
-		genpd_release_lock(parent);
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_dec(link->master);
+		genpd_queue_power_off_work(link->master);
 	}
 
  out:
@@ -371,12 +420,21 @@ static int pm_genpd_runtime_suspend(stru
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
+	might_sleep_if(!genpd->dev_irq_safe);
+
 	if (genpd->stop_device) {
 		int ret = genpd->stop_device(dev);
 		if (ret)
 			return ret;
 	}
 
+	/*
+	 * If power.irq_safe is set, this routine will be run with interrupts
+	 * off, so it can't use mutexes.
+	 */
+	if (dev->power.irq_safe)
+		return 0;
+
 	mutex_lock(&genpd->lock);
 	genpd->in_progress++;
 	pm_genpd_poweroff(genpd);
@@ -387,24 +445,6 @@ static int pm_genpd_runtime_suspend(stru
 }
 
 /**
- * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
- * @dev: Device to resume.
- * @genpd: PM domain the device belongs to.
- */
-static void __pm_genpd_runtime_resume(struct device *dev,
-				      struct generic_pm_domain *genpd)
-{
-	struct dev_list_entry *dle;
-
-	list_for_each_entry(dle, &genpd->dev_list, node) {
-		if (dle->dev == dev) {
-			__pm_genpd_restore_device(dle, genpd);
-			break;
-		}
-	}
-}
-
-/**
  * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
  * @dev: Device to resume.
  *
@@ -424,11 +464,18 @@ static int pm_genpd_runtime_resume(struc
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	ret = pm_genpd_poweron(genpd);
-	if (ret)
-		return ret;
+	might_sleep_if(!genpd->dev_irq_safe);
+
+	/* If power.irq_safe, the PM domain is never powered off. */
+	if (dev->power.irq_safe)
+		goto out;
 
 	mutex_lock(&genpd->lock);
+	ret = __pm_genpd_poweron(genpd);
+	if (ret) {
+		mutex_unlock(&genpd->lock);
+		return ret;
+	}
 	genpd->status = GPD_STATE_BUSY;
 	genpd->resume_count++;
 	for (;;) {
@@ -448,12 +495,13 @@ static int pm_genpd_runtime_resume(struc
 		mutex_lock(&genpd->lock);
 	}
 	finish_wait(&genpd->status_wait_queue, &wait);
-	__pm_genpd_runtime_resume(dev, genpd);
+	__pm_genpd_restore_device(dev->power.subsys_data->domain_data, genpd);
 	genpd->resume_count--;
 	genpd_set_active(genpd);
 	wake_up_all(&genpd->status_wait_queue);
 	mutex_unlock(&genpd->lock);
 
+ out:
 	if (genpd->start_device)
 		genpd->start_device(dev);
 
@@ -478,8 +526,6 @@ void pm_genpd_poweroff_unused(void)
 #else
 
 static inline void genpd_power_off_work_fn(struct work_struct *work) {}
-static inline void __pm_genpd_runtime_resume(struct device *dev,
-					     struct generic_pm_domain *genpd) {}
 
 #define pm_genpd_runtime_suspend	NULL
 #define pm_genpd_runtime_resume		NULL
@@ -489,11 +535,11 @@ static inline void __pm_genpd_runtime_re
 #ifdef CONFIG_PM_SLEEP
 
 /**
- * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
+ * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
  * @genpd: PM domain to power off, if possible.
  *
  * Check if the given PM domain can be powered off (during system suspend or
- * hibernation) and do that if so.  Also, in that case propagate to its parent.
+ * hibernation) and do that if so.  Also, in that case propagate to its masters.
  *
  * This function is only called in "noirq" stages of system power transitions,
  * so it need not acquire locks (all of the "noirq" callbacks are executed
@@ -501,21 +547,23 @@ static inline void __pm_genpd_runtime_re
  */
 static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
 {
-	struct generic_pm_domain *parent = genpd->parent;
+	struct gpd_link *link;
 
 	if (genpd->status == GPD_STATE_POWER_OFF)
 		return;
 
-	if (genpd->suspended_count != genpd->device_count || genpd->sd_count > 0)
+	if (genpd->suspended_count != genpd->device_count
+	    || atomic_read(&genpd->sd_count) > 0)
 		return;
 
 	if (genpd->power_off)
 		genpd->power_off(genpd);
 
 	genpd->status = GPD_STATE_POWER_OFF;
-	if (parent) {
-		genpd_sd_counter_dec(parent);
-		pm_genpd_sync_poweroff(parent);
+
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_dec(link->master);
+		pm_genpd_sync_poweroff(link->master);
 	}
 }
 
@@ -666,7 +714,7 @@ static int pm_genpd_suspend_noirq(struct
 	if (ret)
 		return ret;
 
-	if (device_may_wakeup(dev)
+	if (dev->power.wakeup_path
 	    && genpd->active_wakeup && genpd->active_wakeup(dev))
 		return 0;
 
@@ -890,7 +938,7 @@ static int pm_genpd_dev_poweroff_noirq(s
 	if (ret)
 		return ret;
 
-	if (device_may_wakeup(dev)
+	if (dev->power.wakeup_path
 	    && genpd->active_wakeup && genpd->active_wakeup(dev))
 		return 0;
 
@@ -1034,7 +1082,8 @@ static void pm_genpd_complete(struct dev
  */
 int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
 {
-	struct dev_list_entry *dle;
+	struct generic_pm_domain_data *gpd_data;
+	struct pm_domain_data *pdd;
 	int ret = 0;
 
 	dev_dbg(dev, "%s()\n", __func__);
@@ -1054,26 +1103,26 @@ int pm_genpd_add_device(struct generic_p
 		goto out;
 	}
 
-	list_for_each_entry(dle, &genpd->dev_list, node)
-		if (dle->dev == dev) {
+	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+		if (pdd->dev == dev) {
 			ret = -EINVAL;
 			goto out;
 		}
 
-	dle = kzalloc(sizeof(*dle), GFP_KERNEL);
-	if (!dle) {
+	gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+	if (!gpd_data) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	dle->dev = dev;
-	dle->need_restore = false;
-	list_add_tail(&dle->node, &genpd->dev_list);
 	genpd->device_count++;
 
-	spin_lock_irq(&dev->power.lock);
 	dev->pm_domain = &genpd->domain;
-	spin_unlock_irq(&dev->power.lock);
+	dev_pm_get_subsys_data(dev);
+	dev->power.subsys_data->domain_data = &gpd_data->base;
+	gpd_data->base.dev = dev;
+	gpd_data->need_restore = false;
+	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 
  out:
 	genpd_release_lock(genpd);
@@ -1089,7 +1138,7 @@ int pm_genpd_add_device(struct generic_p
 int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 			   struct device *dev)
 {
-	struct dev_list_entry *dle;
+	struct pm_domain_data *pdd;
 	int ret = -EINVAL;
 
 	dev_dbg(dev, "%s()\n", __func__);
@@ -1104,17 +1153,17 @@ int pm_genpd_remove_device(struct generi
 		goto out;
 	}
 
-	list_for_each_entry(dle, &genpd->dev_list, node) {
-		if (dle->dev != dev)
+	list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+		if (pdd->dev != dev)
 			continue;
 
-		spin_lock_irq(&dev->power.lock);
+		list_del_init(&pdd->list_node);
+		pdd->dev = NULL;
+		dev_pm_put_subsys_data(dev);
 		dev->pm_domain = NULL;
-		spin_unlock_irq(&dev->power.lock);
+		kfree(to_gpd_data(pdd));
 
 		genpd->device_count--;
-		list_del(&dle->node);
-		kfree(dle);
 
 		ret = 0;
 		break;
@@ -1129,48 +1178,55 @@ int pm_genpd_remove_device(struct generi
 /**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
  * @genpd: Master PM domain to add the subdomain to.
- * @new_subdomain: Subdomain to be added.
+ * @subdomain: Subdomain to be added.
  */
 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
-			   struct generic_pm_domain *new_subdomain)
+			   struct generic_pm_domain *subdomain)
 {
-	struct generic_pm_domain *subdomain;
+	struct gpd_link *link;
 	int ret = 0;
 
-	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
  start:
 	genpd_acquire_lock(genpd);
-	mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
+	mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
 
-	if (new_subdomain->status != GPD_STATE_POWER_OFF
-	    && new_subdomain->status != GPD_STATE_ACTIVE) {
-		mutex_unlock(&new_subdomain->lock);
+	if (subdomain->status != GPD_STATE_POWER_OFF
+	    && subdomain->status != GPD_STATE_ACTIVE) {
+		mutex_unlock(&subdomain->lock);
 		genpd_release_lock(genpd);
 		goto start;
 	}
 
 	if (genpd->status == GPD_STATE_POWER_OFF
-	    &&  new_subdomain->status != GPD_STATE_POWER_OFF) {
+	    &&  subdomain->status != GPD_STATE_POWER_OFF) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
-		if (subdomain == new_subdomain) {
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		if (link->slave == subdomain && link->master == genpd) {
 			ret = -EINVAL;
 			goto out;
 		}
 	}
 
-	list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
-	new_subdomain->parent = genpd;
+	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	if (!link) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	link->master = genpd;
+	list_add_tail(&link->master_node, &genpd->master_links);
+	link->slave = subdomain;
+	list_add_tail(&link->slave_node, &subdomain->slave_links);
 	if (subdomain->status != GPD_STATE_POWER_OFF)
-		genpd->sd_count++;
+		genpd_sd_counter_inc(genpd);
 
  out:
-	mutex_unlock(&new_subdomain->lock);
+	mutex_unlock(&subdomain->lock);
 	genpd_release_lock(genpd);
 
 	return ret;
@@ -1179,22 +1235,22 @@ int pm_genpd_add_subdomain(struct generi
 /**
  * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
  * @genpd: Master PM domain to remove the subdomain from.
- * @target: Subdomain to be removed.
+ * @subdomain: Subdomain to be removed.
  */
 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
-			      struct generic_pm_domain *target)
+			      struct generic_pm_domain *subdomain)
 {
-	struct generic_pm_domain *subdomain;
+	struct gpd_link *link;
 	int ret = -EINVAL;
 
-	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
  start:
 	genpd_acquire_lock(genpd);
 
-	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
-		if (subdomain != target)
+	list_for_each_entry(link, &genpd->master_links, master_node) {
+		if (link->slave != subdomain)
 			continue;
 
 		mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
@@ -1206,8 +1262,9 @@ int pm_genpd_remove_subdomain(struct gen
 			goto start;
 		}
 
-		list_del(&subdomain->sd_node);
-		subdomain->parent = NULL;
+		list_del(&link->master_node);
+		list_del(&link->slave_node);
+		kfree(link);
 		if (subdomain->status != GPD_STATE_POWER_OFF)
 			genpd_sd_counter_dec(genpd);
 
@@ -1234,15 +1291,14 @@ void pm_genpd_init(struct generic_pm_dom
 	if (IS_ERR_OR_NULL(genpd))
 		return;
 
-	INIT_LIST_HEAD(&genpd->sd_node);
-	genpd->parent = NULL;
+	INIT_LIST_HEAD(&genpd->master_links);
+	INIT_LIST_HEAD(&genpd->slave_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
-	INIT_LIST_HEAD(&genpd->sd_list);
 	mutex_init(&genpd->lock);
 	genpd->gov = gov;
 	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
 	genpd->in_progress = 0;
-	genpd->sd_count = 0;
+	atomic_set(&genpd->sd_count, 0);
 	genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
 	init_waitqueue_head(&genpd->status_wait_queue);
 	genpd->poweroff_task = NULL;
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/generic_ops.c linux-libre-3.2-gnu1/drivers/base/power/generic_ops.c
--- linux-libre-3.1-gnu1/drivers/base/power/generic_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/generic_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/export.h>
 
 #ifdef CONFIG_PM_RUNTIME
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/main.c linux-libre-3.2-gnu1/drivers/base/power/main.c
--- linux-libre-3.1-gnu1/drivers/base/power/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 
 #include <linux/device.h>
 #include <linux/kallsyms.h>
+#include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -46,6 +47,7 @@ LIST_HEAD(dpm_prepared_list);
 LIST_HEAD(dpm_suspended_list);
 LIST_HEAD(dpm_noirq_list);
 
+struct suspend_stats suspend_stats;
 static DEFINE_MUTEX(dpm_list_mtx);
 static pm_message_t pm_transition;
 
@@ -65,6 +67,7 @@ void device_pm_init(struct device *dev)
 	spin_lock_init(&dev->power.lock);
 	pm_runtime_init(dev);
 	INIT_LIST_HEAD(&dev->power.entry);
+	dev->power.power_state = PMSG_INVALID;
 }
 
 /**
@@ -96,6 +99,7 @@ void device_pm_add(struct device *dev)
 		dev_warn(dev, "parent %s should not be sleeping\n",
 			dev_name(dev->parent));
 	list_add_tail(&dev->power.entry, &dpm_list);
+	dev_pm_qos_constraints_init(dev);
 	mutex_unlock(&dpm_list_mtx);
 }
 
@@ -109,6 +113,7 @@ void device_pm_remove(struct device *dev
 		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
 	complete_all(&dev->power.completion);
 	mutex_lock(&dpm_list_mtx);
+	dev_pm_qos_constraints_destroy(dev);
 	list_del_init(&dev->power.entry);
 	mutex_unlock(&dpm_list_mtx);
 	device_wakeup_disable(dev);
@@ -464,8 +469,12 @@ void dpm_resume_noirq(pm_message_t state
 		mutex_unlock(&dpm_list_mtx);
 
 		error = device_resume_noirq(dev, state);
-		if (error)
+		if (error) {
+			suspend_stats.failed_resume_noirq++;
+			dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+			dpm_save_failed_dev(dev_name(dev));
 			pm_dev_err(dev, state, " early", error);
+		}
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
@@ -626,8 +635,12 @@ void dpm_resume(pm_message_t state)
 			mutex_unlock(&dpm_list_mtx);
 
 			error = device_resume(dev, state, false);
-			if (error)
+			if (error) {
+				suspend_stats.failed_resume++;
+				dpm_save_failed_step(SUSPEND_RESUME);
+				dpm_save_failed_dev(dev_name(dev));
 				pm_dev_err(dev, state, "", error);
+			}
 
 			mutex_lock(&dpm_list_mtx);
 		}
@@ -802,6 +815,9 @@ int dpm_suspend_noirq(pm_message_t state
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
+			suspend_stats.failed_suspend_noirq++;
+			dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
+			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
@@ -902,7 +918,12 @@ static int __device_suspend(struct devic
 	}
 
  End:
-	dev->power.is_suspended = !error;
+	if (!error) {
+		dev->power.is_suspended = true;
+		if (dev->power.wakeup_path
+		    && dev->parent && !dev->parent->power.ignore_children)
+			dev->parent->power.wakeup_path = true;
+	}
 
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -923,8 +944,10 @@ static void async_suspend(void *data, as
 	int error;
 
 	error = __device_suspend(dev, pm_transition, true);
-	if (error)
+	if (error) {
+		dpm_save_failed_dev(dev_name(dev));
 		pm_dev_err(dev, pm_transition, " async", error);
+	}
 
 	put_device(dev);
 }
@@ -967,6 +990,7 @@ int dpm_suspend(pm_message_t state)
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, "", error);
+			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
@@ -980,7 +1004,10 @@ int dpm_suspend(pm_message_t state)
 	async_synchronize_full();
 	if (!error)
 		error = async_error;
-	if (!error)
+	if (error) {
+		suspend_stats.failed_suspend++;
+		dpm_save_failed_step(SUSPEND_SUSPEND);
+	} else
 		dpm_show_time(starttime, state, NULL);
 	return error;
 }
@@ -999,6 +1026,8 @@ static int device_prepare(struct device
 
 	device_lock(dev);
 
+	dev->power.wakeup_path = device_may_wakeup(dev);
+
 	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "preparing power domain ");
 		if (dev->pm_domain->ops.prepare)
@@ -1088,7 +1117,10 @@ int dpm_suspend_start(pm_message_t state
 	int error;
 
 	error = dpm_prepare(state);
-	if (!error)
+	if (error) {
+		suspend_stats.failed_prepare++;
+		dpm_save_failed_step(SUSPEND_PREPARE);
+	} else
 		error = dpm_suspend(state);
 	return error;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/Makefile linux-libre-3.2-gnu1/drivers/base/power/Makefile
--- linux-libre-3.1-gnu1/drivers/base/power/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o
+obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o common.o qos.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
@@ -6,4 +6,4 @@ obj-$(CONFIG_PM_OPP)	+= opp.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS)	+=  domain.o
 obj-$(CONFIG_HAVE_CLK)	+= clock_ops.o
 
-ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
\ No newline at end of file
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/opp.c linux-libre-3.2-gnu1/drivers/base/power/opp.c
--- linux-libre-3.1-gnu1/drivers/base/power/opp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/opp.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,6 +73,7 @@ struct opp {
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
  * @dev:	device pointer
+ * @head:	notifier head to notify the OPP availability changes.
  * @opp_list:	list of opps
  *
  * This is an internal data structure maintaining the link to opps attached to
@@ -83,6 +84,7 @@ struct device_opp {
 	struct list_head node;
 
 	struct device *dev;
+	struct srcu_notifier_head head;
 	struct list_head opp_list;
 };
 
@@ -404,6 +406,7 @@ int opp_add(struct device *dev, unsigned
 		}
 
 		dev_opp->dev = dev;
+		srcu_init_notifier_head(&dev_opp->head);
 		INIT_LIST_HEAD(&dev_opp->opp_list);
 
 		/* Secure the device list modification */
@@ -428,6 +431,11 @@ int opp_add(struct device *dev, unsigned
 	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
 
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
 	return 0;
 }
 
@@ -504,6 +512,14 @@ static int opp_set_availability(struct d
 	mutex_unlock(&dev_opp_list_lock);
 	synchronize_rcu();
 
+	/* Notify the change of the OPP availability */
+	if (availability_req)
+		srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE,
+					 new_opp);
+	else
+		srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
+					 new_opp);
+
 	/* clean up old opp */
 	new_opp = opp;
 	goto out;
@@ -643,3 +659,17 @@ void opp_free_cpufreq_table(struct devic
 	*table = NULL;
 }
 #endif		/* CONFIG_CPU_FREQ */
+
+/**
+ * opp_get_notifier() - find notifier_head of the device with opp
+ * @dev:	device pointer used to lookup device OPPs.
+ */
+struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+{
+	struct device_opp *dev_opp = find_device_opp(dev);
+
+	if (IS_ERR(dev_opp))
+		return ERR_CAST(dev_opp); /* matching type */
+
+	return &dev_opp->head;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/power.h linux-libre-3.2-gnu1/drivers/base/power/power.h
--- linux-libre-3.1-gnu1/drivers/base/power/power.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/power.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,5 @@
+#include <linux/pm_qos.h>
+
 #ifdef CONFIG_PM_RUNTIME
 
 extern void pm_runtime_init(struct device *dev);
@@ -35,15 +37,21 @@ extern void device_pm_move_last(struct d
 static inline void device_pm_init(struct device *dev)
 {
 	spin_lock_init(&dev->power.lock);
+	dev->power.power_state = PMSG_INVALID;
 	pm_runtime_init(dev);
 }
 
+static inline void device_pm_add(struct device *dev)
+{
+	dev_pm_qos_constraints_init(dev);
+}
+
 static inline void device_pm_remove(struct device *dev)
 {
+	dev_pm_qos_constraints_destroy(dev);
 	pm_runtime_remove(dev);
 }
 
-static inline void device_pm_add(struct device *dev) {}
 static inline void device_pm_move_before(struct device *deva,
 					 struct device *devb) {}
 static inline void device_pm_move_after(struct device *deva,
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/qos.c linux-libre-3.2-gnu1/drivers/base/power/qos.c
--- linux-libre-3.1-gnu1/drivers/base/power/qos.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/power/qos.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,414 @@
+/*
+ * Devices PM QoS constraints management
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * 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.
+ *
+ *
+ * This module exposes the interface to kernel space for specifying
+ * per-device PM QoS dependencies. It provides infrastructure for registration
+ * of:
+ *
+ * Dependents on a QoS value : register requests
+ * Watchers of QoS value : get notified when target QoS value changes
+ *
+ * This QoS design is best effort based. Dependents register their QoS needs.
+ * Watchers register to keep track of the current QoS needs of the system.
+ * Watchers can register different types of notification callbacks:
+ *  . a per-device notification callback using the dev_pm_qos_*_notifier API.
+ *    The notification chain data is stored in the per-device constraint
+ *    data struct.
+ *  . a system-wide notification callback using the dev_pm_qos_*_global_notifier
+ *    API. The notification chain data is stored in a static variable.
+ *
+ * Note about the per-device constraint data struct allocation:
+ * . The per-device constraints data struct ptr is tored into the device
+ *    dev_pm_info.
+ * . To minimize the data usage by the per-device constraints, the data struct
+ *   is only allocated at the first call to dev_pm_qos_add_request.
+ * . The data is later free'd when the device is removed from the system.
+ *  . A global mutex protects the constraints users from the data being
+ *     allocated and free'd.
+ */
+
+#include <linux/pm_qos.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/export.h>
+
+
+static DEFINE_MUTEX(dev_pm_qos_mtx);
+
+static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
+
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ */
+s32 dev_pm_qos_read_value(struct device *dev)
+{
+	struct pm_qos_constraints *c;
+	unsigned long flags;
+	s32 ret = 0;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	c = dev->power.constraints;
+	if (c)
+		ret = pm_qos_read_value(c);
+
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
+	return ret;
+}
+
+/*
+ * apply_constraint
+ * @req: constraint request to apply
+ * @action: action to perform add/update/remove, of type enum pm_qos_req_action
+ * @value: defines the qos request
+ *
+ * Internal function to update the constraints list using the PM QoS core
+ * code and if needed call the per-device and the global notification
+ * callbacks
+ */
+static int apply_constraint(struct dev_pm_qos_request *req,
+			    enum pm_qos_req_action action, int value)
+{
+	int ret, curr_value;
+
+	ret = pm_qos_update_target(req->dev->power.constraints,
+				   &req->node, action, value);
+
+	if (ret) {
+		/* Call the global callbacks if needed */
+		curr_value = pm_qos_read_value(req->dev->power.constraints);
+		blocking_notifier_call_chain(&dev_pm_notifiers,
+					     (unsigned long)curr_value,
+					     req);
+	}
+
+	return ret;
+}
+
+/*
+ * dev_pm_qos_constraints_allocate
+ * @dev: device to allocate data for
+ *
+ * Called at the first call to add_request, for constraint data allocation
+ * Must be called with the dev_pm_qos_mtx mutex held
+ */
+static int dev_pm_qos_constraints_allocate(struct device *dev)
+{
+	struct pm_qos_constraints *c;
+	struct blocking_notifier_head *n;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return -ENOMEM;
+
+	n = kzalloc(sizeof(*n), GFP_KERNEL);
+	if (!n) {
+		kfree(c);
+		return -ENOMEM;
+	}
+	BLOCKING_INIT_NOTIFIER_HEAD(n);
+
+	plist_head_init(&c->list);
+	c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	c->type = PM_QOS_MIN;
+	c->notifiers = n;
+
+	spin_lock_irq(&dev->power.lock);
+	dev->power.constraints = c;
+	spin_unlock_irq(&dev->power.lock);
+
+	return 0;
+}
+
+/**
+ * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
+ * @dev: target device
+ *
+ * Called from the device PM subsystem during device insertion under
+ * device_pm_lock().
+ */
+void dev_pm_qos_constraints_init(struct device *dev)
+{
+	mutex_lock(&dev_pm_qos_mtx);
+	dev->power.constraints = NULL;
+	dev->power.power_state = PMSG_ON;
+	mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_constraints_destroy
+ * @dev: target device
+ *
+ * Called from the device PM subsystem on device removal under device_pm_lock().
+ */
+void dev_pm_qos_constraints_destroy(struct device *dev)
+{
+	struct dev_pm_qos_request *req, *tmp;
+	struct pm_qos_constraints *c;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	dev->power.power_state = PMSG_INVALID;
+	c = dev->power.constraints;
+	if (!c)
+		goto out;
+
+	/* Flush the constraints list for the device */
+	plist_for_each_entry_safe(req, tmp, &c->list, node) {
+		/*
+		 * Update constraints list and call the notification
+		 * callbacks if needed
+		 */
+		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	}
+
+	spin_lock_irq(&dev->power.lock);
+	dev->power.constraints = NULL;
+	spin_unlock_irq(&dev->power.lock);
+
+	kfree(c->notifiers);
+	kfree(c);
+
+ out:
+	mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_add_request - inserts new qos request into the list
+ * @dev: target device for the constraint
+ * @req: pointer to a preallocated handle
+ * @value: defines the qos request
+ *
+ * This function inserts a new entry in the device constraints list of
+ * requested qos performance characteristics. It recomputes the aggregate
+ * QoS expectations of parameters and initializes the dev_pm_qos_request
+ * handle.  Caller needs to save this handle for later use in updates and
+ * removal.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
+ * to allocate for data structures, -ENODEV if the device has just been removed
+ * from the system.
+ */
+int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
+			   s32 value)
+{
+	int ret = 0;
+
+	if (!dev || !req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(dev_pm_qos_request_active(req),
+		 "%s() called for already added request\n", __func__))
+		return -EINVAL;
+
+	req->dev = dev;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (!dev->power.constraints) {
+		if (dev->power.power_state.event == PM_EVENT_INVALID) {
+			/* The device has been removed from the system. */
+			req->dev = NULL;
+			ret = -ENODEV;
+			goto out;
+		} else {
+			/*
+			 * Allocate the constraints data on the first call to
+			 * add_request, i.e. only if the data is not already
+			 * allocated and if the device has not been removed.
+			 */
+			ret = dev_pm_qos_constraints_allocate(dev);
+		}
+	}
+
+	if (!ret)
+		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+
+ out:
+	mutex_unlock(&dev_pm_qos_mtx);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
+
+/**
+ * dev_pm_qos_update_request - modifies an existing qos request
+ * @req : handle to list element holding a dev_pm_qos request to use
+ * @new_value: defines the qos request
+ *
+ * Updates an existing dev PM qos request along with updating the
+ * target value.
+ *
+ * Attempts are made to make this code callable on hot code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+			      s32 new_value)
+{
+	int ret = 0;
+
+	if (!req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(!dev_pm_qos_request_active(req),
+		 "%s() called for unknown object\n", __func__))
+		return -EINVAL;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (req->dev->power.constraints) {
+		if (new_value != req->node.prio)
+			ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
+					       new_value);
+	} else {
+		/* Return if the device has been removed */
+		ret = -ENODEV;
+	}
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
+
+/**
+ * dev_pm_qos_remove_request - modifies an existing qos request
+ * @req: handle to request list element
+ *
+ * Will remove pm qos request from the list of constraints and
+ * recompute the current target value. Call this on slow code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
+{
+	int ret = 0;
+
+	if (!req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(!dev_pm_qos_request_active(req),
+		 "%s() called for unknown object\n", __func__))
+		return -EINVAL;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (req->dev->power.constraints) {
+		ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
+				       PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	} else {
+		/* Return if the device has been removed */
+		ret = -ENODEV;
+	}
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
+
+/**
+ * dev_pm_qos_add_notifier - sets notification entry for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for the device.
+ */
+int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
+{
+	int retval = 0;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	/* Silently return if the constraints object is not present. */
+	if (dev->power.constraints)
+		retval = blocking_notifier_chain_register(
+				dev->power.constraints->notifiers,
+				notifier);
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
+
+/**
+ * dev_pm_qos_remove_notifier - deletes notification for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value.
+ */
+int dev_pm_qos_remove_notifier(struct device *dev,
+			       struct notifier_block *notifier)
+{
+	int retval = 0;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	/* Silently return if the constraints object is not present. */
+	if (dev->power.constraints)
+		retval = blocking_notifier_chain_unregister(
+				dev->power.constraints->notifiers,
+				notifier);
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
+
+/**
+ * dev_pm_qos_add_global_notifier - sets notification entry for changes to
+ * target value of the PM QoS constraints for any device
+ *
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
+{
+	return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
+
+/**
+ * dev_pm_qos_remove_global_notifier - deletes notification for changes to
+ * target value of PM QoS constraints for any device
+ *
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
+{
+	return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/runtime.c linux-libre-3.2-gnu1/drivers/base/power/runtime.c
--- linux-libre-3.1-gnu1/drivers/base/power/runtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/runtime.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,9 @@
  */
 
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/pm_runtime.h>
+#include <trace/events/rpm.h>
 #include "power.h"
 
 static int rpm_resume(struct device *dev, int rpmflags);
@@ -28,13 +30,10 @@ static int rpm_suspend(struct device *de
 void update_pm_runtime_accounting(struct device *dev)
 {
 	unsigned long now = jiffies;
-	int delta;
+	unsigned long delta;
 
 	delta = now - dev->power.accounting_timestamp;
 
-	if (delta < 0)
-		delta = 0;
-
 	dev->power.accounting_timestamp = now;
 
 	if (dev->power.disable_depth > 0)
@@ -155,6 +154,31 @@ static int rpm_check_suspend_allowed(str
 }
 
 /**
+ * __rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+	int retval;
+
+	if (dev->power.irq_safe)
+		spin_unlock(&dev->power.lock);
+	else
+		spin_unlock_irq(&dev->power.lock);
+
+	retval = cb(dev);
+
+	if (dev->power.irq_safe)
+		spin_lock(&dev->power.lock);
+	else
+		spin_lock_irq(&dev->power.lock);
+
+	return retval;
+}
+
+/**
  * rpm_idle - Notify device bus type if the device can be suspended.
  * @dev: Device to notify the bus type about.
  * @rpmflags: Flag bits.
@@ -171,6 +195,7 @@ static int rpm_idle(struct device *dev,
 	int (*callback)(struct device *);
 	int retval;
 
+	trace_rpm_idle(dev, rpmflags);
 	retval = rpm_check_suspend_allowed(dev);
 	if (retval < 0)
 		;	/* Conditions are wrong. */
@@ -225,24 +250,14 @@ static int rpm_idle(struct device *dev,
 	else
 		callback = NULL;
 
-	if (callback) {
-		if (dev->power.irq_safe)
-			spin_unlock(&dev->power.lock);
-		else
-			spin_unlock_irq(&dev->power.lock);
-
-		callback(dev);
-
-		if (dev->power.irq_safe)
-			spin_lock(&dev->power.lock);
-		else
-			spin_lock_irq(&dev->power.lock);
-	}
+	if (callback)
+		__rpm_callback(callback, dev);
 
 	dev->power.idle_notification = false;
 	wake_up_all(&dev->power.wait_queue);
 
  out:
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 	return retval;
 }
 
@@ -252,22 +267,14 @@ static int rpm_idle(struct device *dev,
  * @dev: Device to run the callback for.
  */
 static int rpm_callback(int (*cb)(struct device *), struct device *dev)
-	__releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
 	int retval;
 
 	if (!cb)
 		return -ENOSYS;
 
-	if (dev->power.irq_safe) {
-		retval = cb(dev);
-	} else {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = cb(dev);
+	retval = __rpm_callback(cb, dev);
 
-		spin_lock_irq(&dev->power.lock);
-	}
 	dev->power.runtime_error = retval;
 	return retval != -EACCES ? retval : -EIO;
 }
@@ -277,14 +284,19 @@ static int rpm_callback(int (*cb)(struct
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
- * Check if the device's runtime PM status allows it to be suspended.  If
- * another suspend has been started earlier, either return immediately or wait
- * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
- * pending idle notification.  If the RPM_ASYNC flag is set then queue a
- * suspend request; otherwise run the ->runtime_suspend() callback directly.
- * If a deferred resume was requested while the callback was running then carry
- * it out; otherwise send an idle notification for the device (if the suspend
- * failed) or for its parent (if the suspend succeeded).
+ * Check if the device's runtime PM status allows it to be suspended.
+ * Cancel a pending idle notification, autosuspend or suspend. If
+ * another suspend has been started earlier, either return immediately
+ * or wait for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC
+ * flags. If the RPM_ASYNC flag is set then queue a suspend request;
+ * otherwise run the ->runtime_suspend() callback directly. When
+ * ->runtime_suspend succeeded, if a deferred resume was requested while
+ * the callback was running then carry it out, otherwise send an idle
+ * notification for its parent (if the suspend succeeded and both
+ * ignore_children of parent->power and irq_safe of dev->power are not set).
+ * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
+ * flag is set and the next autosuspend-delay expiration time is in the
+ * future, schedule another autosuspend attempt.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
@@ -295,7 +307,7 @@ static int rpm_suspend(struct device *de
 	struct device *parent = NULL;
 	int retval;
 
-	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+	trace_rpm_suspend(dev, rpmflags);
 
  repeat:
 	retval = rpm_check_suspend_allowed(dev);
@@ -347,6 +359,15 @@ static int rpm_suspend(struct device *de
 			goto out;
 		}
 
+		if (dev->power.irq_safe) {
+			spin_unlock(&dev->power.lock);
+
+			cpu_relax();
+
+			spin_lock(&dev->power.lock);
+			goto repeat;
+		}
+
 		/* Wait for the other suspend running in parallel with us. */
 		for (;;) {
 			prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -396,19 +417,31 @@ static int rpm_suspend(struct device *de
 	if (retval) {
 		__update_runtime_status(dev, RPM_ACTIVE);
 		dev->power.deferred_resume = false;
-		if (retval == -EAGAIN || retval == -EBUSY)
+		if (retval == -EAGAIN || retval == -EBUSY) {
 			dev->power.runtime_error = 0;
-		else
+
+			/*
+			 * If the callback routine failed an autosuspend, and
+			 * if the last_busy time has been updated so that there
+			 * is a new autosuspend expiration time, automatically
+			 * reschedule another autosuspend.
+			 */
+			if ((rpmflags & RPM_AUTO) &&
+			    pm_runtime_autosuspend_expiration(dev) != 0)
+				goto repeat;
+		} else {
 			pm_runtime_cancel_pending(dev);
-	} else {
+		}
+		wake_up_all(&dev->power.wait_queue);
+		goto out;
+	}
  no_callback:
-		__update_runtime_status(dev, RPM_SUSPENDED);
-		pm_runtime_deactivate_timer(dev);
+	__update_runtime_status(dev, RPM_SUSPENDED);
+	pm_runtime_deactivate_timer(dev);
 
-		if (dev->parent) {
-			parent = dev->parent;
-			atomic_add_unless(&parent->power.child_count, -1, 0);
-		}
+	if (dev->parent) {
+		parent = dev->parent;
+		atomic_add_unless(&parent->power.child_count, -1, 0);
 	}
 	wake_up_all(&dev->power.wait_queue);
 
@@ -430,7 +463,7 @@ static int rpm_suspend(struct device *de
 	}
 
  out:
-	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 
 	return retval;
 }
@@ -459,7 +492,7 @@ static int rpm_resume(struct device *dev
 	struct device *parent = NULL;
 	int retval = 0;
 
-	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+	trace_rpm_resume(dev, rpmflags);
 
  repeat:
 	if (dev->power.runtime_error)
@@ -496,6 +529,15 @@ static int rpm_resume(struct device *dev
 			goto out;
 		}
 
+		if (dev->power.irq_safe) {
+			spin_unlock(&dev->power.lock);
+
+			cpu_relax();
+
+			spin_lock(&dev->power.lock);
+			goto repeat;
+		}
+
 		/* Wait for the operation carried out in parallel with us. */
 		for (;;) {
 			prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -615,7 +657,7 @@ static int rpm_resume(struct device *dev
 		spin_lock_irq(&dev->power.lock);
 	}
 
-	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 
 	return retval;
 }
@@ -732,13 +774,16 @@ EXPORT_SYMBOL_GPL(pm_schedule_suspend);
  * return immediately if it is larger than zero.  Then carry out an idle
  * notification, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_idle(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
@@ -761,13 +806,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle);
  * return immediately if it is larger than zero.  Then carry out a suspend,
  * either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_suspend(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
@@ -789,13 +837,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
  * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
  * carry out a resume, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_resume(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT)
 		atomic_inc(&dev->power.usage_count);
 
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/sysfs.c linux-libre-3.2-gnu1/drivers/base/power/sysfs.c
--- linux-libre-3.1-gnu1/drivers/base/power/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 
 #include <linux/device.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/pm_runtime.h>
 #include <linux/atomic.h>
 #include <linux/jiffies.h>
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/trace.c linux-libre-3.2-gnu1/drivers/base/power/trace.c
--- linux-libre-3.1-gnu1/drivers/base/power/trace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/trace.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/resume-trace.h>
+#include <linux/export.h>
 #include <linux/rtc.h>
 
 #include <asm/rtc.h>
diff -druNp linux-libre-3.1-gnu1/drivers/base/power/wakeup.c linux-libre-3.2-gnu1/drivers/base/power/wakeup.c
--- linux-libre-3.1-gnu1/drivers/base/power/wakeup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/power/wakeup.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/capability.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
@@ -276,7 +277,9 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_capa
  *
  * By default, most devices should leave wakeup disabled.  The exceptions are
  * devices that everyone expects to be wakeup sources: keyboards, power buttons,
- * possibly network interfaces, etc.
+ * possibly network interfaces, etc.  Also, devices that don't generate their
+ * own wakeup requests but merely forward requests from one bus to another
+ * (like PCI bridges) should have wakeup enabled by default.
  */
 int device_init_wakeup(struct device *dev, bool enable)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/internal.h linux-libre-3.2-gnu1/drivers/base/regmap/internal.h
--- linux-libre-3.1-gnu1/drivers/base/regmap/internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Register map access API internal header
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGMAP_INTERNAL_H
+#define _REGMAP_INTERNAL_H
+
+#include <linux/regmap.h>
+#include <linux/fs.h>
+
+struct regmap;
+struct regcache_ops;
+
+struct regmap_format {
+	size_t buf_size;
+	size_t reg_bytes;
+	size_t val_bytes;
+	void (*format_write)(struct regmap *map,
+			     unsigned int reg, unsigned int val);
+	void (*format_reg)(void *buf, unsigned int reg);
+	void (*format_val)(void *buf, unsigned int val);
+	unsigned int (*parse_val)(void *buf);
+};
+
+struct regmap {
+	struct mutex lock;
+
+	struct device *dev; /* Device we do I/O on */
+	void *work_buf;     /* Scratch buffer used to format I/O */
+	struct regmap_format format;  /* Buffer format */
+	const struct regmap_bus *bus;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+
+	unsigned int max_register;
+	bool (*writeable_reg)(struct device *dev, unsigned int reg);
+	bool (*readable_reg)(struct device *dev, unsigned int reg);
+	bool (*volatile_reg)(struct device *dev, unsigned int reg);
+	bool (*precious_reg)(struct device *dev, unsigned int reg);
+
+	u8 read_flag_mask;
+	u8 write_flag_mask;
+
+	/* regcache specific members */
+	const struct regcache_ops *cache_ops;
+	enum regcache_type cache_type;
+
+	/* number of bytes in reg_defaults_raw */
+	unsigned int cache_size_raw;
+	/* number of bytes per word in reg_defaults_raw */
+	unsigned int cache_word_size;
+	/* number of entries in reg_defaults */
+	unsigned int num_reg_defaults;
+	/* number of entries in reg_defaults_raw */
+	unsigned int num_reg_defaults_raw;
+
+	/* if set, only the cache is modified not the HW */
+	unsigned int cache_only:1;
+	/* if set, only the HW is modified not the cache */
+	unsigned int cache_bypass:1;
+	/* if set, remember to free reg_defaults_raw */
+	unsigned int cache_free:1;
+
+	struct reg_default *reg_defaults;
+	const void *reg_defaults_raw;
+	void *cache;
+};
+
+struct regcache_ops {
+	const char *name;
+	enum regcache_type type;
+	int (*init)(struct regmap *map);
+	int (*exit)(struct regmap *map);
+	int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
+	int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
+	int (*sync)(struct regmap *map);
+};
+
+bool regmap_writeable(struct regmap *map, unsigned int reg);
+bool regmap_readable(struct regmap *map, unsigned int reg);
+bool regmap_volatile(struct regmap *map, unsigned int reg);
+bool regmap_precious(struct regmap *map, unsigned int reg);
+
+int _regmap_write(struct regmap *map, unsigned int reg,
+		  unsigned int val);
+
+#ifdef CONFIG_DEBUG_FS
+extern void regmap_debugfs_initcall(void);
+extern void regmap_debugfs_init(struct regmap *map);
+extern void regmap_debugfs_exit(struct regmap *map);
+#else
+static inline void regmap_debugfs_initcall(void) { }
+static inline void regmap_debugfs_init(struct regmap *map) { }
+static inline void regmap_debugfs_exit(struct regmap *map) { }
+#endif
+
+/* regcache core declarations */
+int regcache_init(struct regmap *map);
+void regcache_exit(struct regmap *map);
+int regcache_read(struct regmap *map,
+		       unsigned int reg, unsigned int *value);
+int regcache_write(struct regmap *map,
+			unsigned int reg, unsigned int value);
+int regcache_sync(struct regmap *map);
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+			      unsigned int word_size);
+bool regcache_set_val(void *base, unsigned int idx,
+		      unsigned int val, unsigned int word_size);
+int regcache_lookup_reg(struct regmap *map, unsigned int reg);
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+			unsigned int val);
+
+extern struct regcache_ops regcache_indexed_ops;
+extern struct regcache_ops regcache_rbtree_ops;
+extern struct regcache_ops regcache_lzo_ops;
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/Kconfig linux-libre-3.2-gnu1/drivers/base/regmap/Kconfig
--- linux-libre-3.1-gnu1/drivers/base/regmap/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/regmap/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,8 @@
 
 config REGMAP
 	default y if (REGMAP_I2C || REGMAP_SPI)
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
 	bool
 
 config REGMAP_I2C
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/Makefile linux-libre-3.2-gnu1/drivers/base/regmap/Makefile
--- linux-libre-3.1-gnu1/drivers/base/regmap/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/regmap/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
-obj-$(CONFIG_REGMAP) += regmap.o
+obj-$(CONFIG_REGMAP) += regmap.o regcache.o regcache-indexed.o regcache-rbtree.o regcache-lzo.o
+obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
 obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
 obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regcache.c linux-libre-3.2-gnu1/drivers/base/regmap/regcache.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regcache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regcache.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,402 @@
+/*
+ * Register cache access API
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <trace/events/regmap.h>
+#include <linux/bsearch.h>
+#include <linux/sort.h>
+
+#include "internal.h"
+
+static const struct regcache_ops *cache_types[] = {
+	&regcache_indexed_ops,
+	&regcache_rbtree_ops,
+	&regcache_lzo_ops,
+};
+
+static int regcache_hw_init(struct regmap *map)
+{
+	int i, j;
+	int ret;
+	int count;
+	unsigned int val;
+	void *tmp_buf;
+
+	if (!map->num_reg_defaults_raw)
+		return -EINVAL;
+
+	if (!map->reg_defaults_raw) {
+		dev_warn(map->dev, "No cache defaults, reading back from HW\n");
+		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
+		if (!tmp_buf)
+			return -EINVAL;
+		ret = regmap_bulk_read(map, 0, tmp_buf,
+				       map->num_reg_defaults_raw);
+		if (ret < 0) {
+			kfree(tmp_buf);
+			return ret;
+		}
+		map->reg_defaults_raw = tmp_buf;
+		map->cache_free = 1;
+	}
+
+	/* calculate the size of reg_defaults */
+	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
+		val = regcache_get_val(map->reg_defaults_raw,
+				       i, map->cache_word_size);
+		if (!val)
+			continue;
+		count++;
+	}
+
+	map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
+				      GFP_KERNEL);
+	if (!map->reg_defaults)
+		return -ENOMEM;
+
+	/* fill the reg_defaults */
+	map->num_reg_defaults = count;
+	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
+		val = regcache_get_val(map->reg_defaults_raw,
+				       i, map->cache_word_size);
+		if (!val)
+			continue;
+		map->reg_defaults[j].reg = i;
+		map->reg_defaults[j].def = val;
+		j++;
+	}
+
+	return 0;
+}
+
+int regcache_init(struct regmap *map)
+{
+	int ret;
+	int i;
+	void *tmp_buf;
+
+	if (map->cache_type == REGCACHE_NONE) {
+		map->cache_bypass = true;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cache_types); i++)
+		if (cache_types[i]->type == map->cache_type)
+			break;
+
+	if (i == ARRAY_SIZE(cache_types)) {
+		dev_err(map->dev, "Could not match compress type: %d\n",
+			map->cache_type);
+		return -EINVAL;
+	}
+
+	map->cache = NULL;
+	map->cache_ops = cache_types[i];
+
+	if (!map->cache_ops->read ||
+	    !map->cache_ops->write ||
+	    !map->cache_ops->name)
+		return -EINVAL;
+
+	/* We still need to ensure that the reg_defaults
+	 * won't vanish from under us.  We'll need to make
+	 * a copy of it.
+	 */
+	if (map->reg_defaults) {
+		if (!map->num_reg_defaults)
+			return -EINVAL;
+		tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
+				  sizeof(struct reg_default), GFP_KERNEL);
+		if (!tmp_buf)
+			return -ENOMEM;
+		map->reg_defaults = tmp_buf;
+	} else if (map->num_reg_defaults_raw) {
+		/* Some devices such as PMICs don't have cache defaults,
+		 * we cope with this by reading back the HW registers and
+		 * crafting the cache defaults by hand.
+		 */
+		ret = regcache_hw_init(map);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (!map->max_register)
+		map->max_register = map->num_reg_defaults_raw;
+
+	if (map->cache_ops->init) {
+		dev_dbg(map->dev, "Initializing %s cache\n",
+			map->cache_ops->name);
+		return map->cache_ops->init(map);
+	}
+	return 0;
+}
+
+void regcache_exit(struct regmap *map)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return;
+
+	BUG_ON(!map->cache_ops);
+
+	kfree(map->reg_defaults);
+	if (map->cache_free)
+		kfree(map->reg_defaults_raw);
+
+	if (map->cache_ops->exit) {
+		dev_dbg(map->dev, "Destroying %s cache\n",
+			map->cache_ops->name);
+		map->cache_ops->exit(map);
+	}
+}
+
+/**
+ * regcache_read: Fetch the value of a given register from the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The value to be returned.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_read(struct regmap *map,
+		  unsigned int reg, unsigned int *value)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return -ENOSYS;
+
+	BUG_ON(!map->cache_ops);
+
+	if (!regmap_readable(map, reg))
+		return -EIO;
+
+	if (!regmap_volatile(map, reg))
+		return map->cache_ops->read(map, reg, value);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regcache_read);
+
+/**
+ * regcache_write: Set the value of a given register in the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The new register value.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_write(struct regmap *map,
+		   unsigned int reg, unsigned int value)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return 0;
+
+	BUG_ON(!map->cache_ops);
+
+	if (!regmap_writeable(map, reg))
+		return -EIO;
+
+	if (!regmap_volatile(map, reg))
+		return map->cache_ops->write(map, reg, value);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(regcache_write);
+
+/**
+ * regcache_sync: Sync the register cache with the hardware.
+ *
+ * @map: map to configure.
+ *
+ * Any registers that should not be synced should be marked as
+ * volatile.  In general drivers can choose not to use the provided
+ * syncing functionality if they so require.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_sync(struct regmap *map)
+{
+	int ret = 0;
+	unsigned int val;
+	unsigned int i;
+	const char *name;
+	unsigned int bypass;
+
+	BUG_ON(!map->cache_ops);
+
+	mutex_lock(&map->lock);
+	/* Remember the initial bypass state */
+	bypass = map->cache_bypass;
+	dev_dbg(map->dev, "Syncing %s cache\n",
+		map->cache_ops->name);
+	name = map->cache_ops->name;
+	trace_regcache_sync(map->dev, name, "start");
+	if (map->cache_ops->sync) {
+		ret = map->cache_ops->sync(map);
+	} else {
+		for (i = 0; i < map->num_reg_defaults; i++) {
+			ret = regcache_read(map, i, &val);
+			if (ret < 0)
+				goto out;
+			map->cache_bypass = 1;
+			ret = _regmap_write(map, i, val);
+			map->cache_bypass = 0;
+			if (ret < 0)
+				goto out;
+			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+				map->reg_defaults[i].reg,
+				map->reg_defaults[i].def);
+		}
+
+	}
+out:
+	trace_regcache_sync(map->dev, name, "stop");
+	/* Restore the bypass state */
+	map->cache_bypass = bypass;
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regcache_sync);
+
+/**
+ * regcache_cache_only: Put a register map into cache only mode
+ *
+ * @map: map to configure
+ * @cache_only: flag if changes should be written to the hardware
+ *
+ * When a register map is marked as cache only writes to the register
+ * map API will only update the register cache, they will not cause
+ * any hardware changes.  This is useful for allowing portions of
+ * drivers to act as though the device were functioning as normal when
+ * it is disabled for power saving reasons.
+ */
+void regcache_cache_only(struct regmap *map, bool enable)
+{
+	mutex_lock(&map->lock);
+	WARN_ON(map->cache_bypass && enable);
+	map->cache_only = enable;
+	mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_only);
+
+/**
+ * regcache_cache_bypass: Put a register map into cache bypass mode
+ *
+ * @map: map to configure
+ * @cache_bypass: flag if changes should not be written to the hardware
+ *
+ * When a register map is marked with the cache bypass option, writes
+ * to the register map API will only update the hardware and not the
+ * the cache directly.  This is useful when syncing the cache back to
+ * the hardware.
+ */
+void regcache_cache_bypass(struct regmap *map, bool enable)
+{
+	mutex_lock(&map->lock);
+	WARN_ON(map->cache_only && enable);
+	map->cache_bypass = enable;
+	mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_bypass);
+
+bool regcache_set_val(void *base, unsigned int idx,
+		      unsigned int val, unsigned int word_size)
+{
+	switch (word_size) {
+	case 1: {
+		u8 *cache = base;
+		if (cache[idx] == val)
+			return true;
+		cache[idx] = val;
+		break;
+	}
+	case 2: {
+		u16 *cache = base;
+		if (cache[idx] == val)
+			return true;
+		cache[idx] = val;
+		break;
+	}
+	default:
+		BUG();
+	}
+	/* unreachable */
+	return false;
+}
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+			      unsigned int word_size)
+{
+	if (!base)
+		return -EINVAL;
+
+	switch (word_size) {
+	case 1: {
+		const u8 *cache = base;
+		return cache[idx];
+	}
+	case 2: {
+		const u16 *cache = base;
+		return cache[idx];
+	}
+	default:
+		BUG();
+	}
+	/* unreachable */
+	return -1;
+}
+
+static int regcache_default_cmp(const void *a, const void *b)
+{
+	const struct reg_default *_a = a;
+	const struct reg_default *_b = b;
+
+	return _a->reg - _b->reg;
+}
+
+int regcache_lookup_reg(struct regmap *map, unsigned int reg)
+{
+	struct reg_default key;
+	struct reg_default *r;
+
+	key.reg = reg;
+	key.def = 0;
+
+	r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
+		    sizeof(struct reg_default), regcache_default_cmp);
+
+	if (r)
+		return r - map->reg_defaults;
+	else
+		return -ENOENT;
+}
+
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+			unsigned int val)
+{
+	void *tmp;
+
+	tmp = krealloc(map->reg_defaults,
+		       (map->num_reg_defaults + 1) * sizeof(struct reg_default),
+		       GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+	map->reg_defaults = tmp;
+	map->num_reg_defaults++;
+	map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
+	map->reg_defaults[map->num_reg_defaults - 1].def = val;
+	sort(map->reg_defaults, map->num_reg_defaults,
+	     sizeof(struct reg_default), regcache_default_cmp, NULL);
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regcache-indexed.c linux-libre-3.2-gnu1/drivers/base/regmap/regcache-indexed.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regcache-indexed.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regcache-indexed.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Register cache access API - indexed caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+
+#include "internal.h"
+
+static int regcache_indexed_read(struct regmap *map, unsigned int reg,
+				 unsigned int *value)
+{
+	int ret;
+
+	ret = regcache_lookup_reg(map, reg);
+	if (ret >= 0)
+		*value = map->reg_defaults[ret].def;
+
+	return ret;
+}
+
+static int regcache_indexed_write(struct regmap *map, unsigned int reg,
+				  unsigned int value)
+{
+	int ret;
+
+	ret = regcache_lookup_reg(map, reg);
+	if (ret < 0)
+		return regcache_insert_reg(map, reg, value);
+	map->reg_defaults[ret].def = value;
+	return 0;
+}
+
+static int regcache_indexed_sync(struct regmap *map)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < map->num_reg_defaults; i++) {
+		ret = _regmap_write(map, map->reg_defaults[i].reg,
+				    map->reg_defaults[i].def);
+		if (ret < 0)
+			return ret;
+		dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+			map->reg_defaults[i].reg,
+			map->reg_defaults[i].def);
+	}
+	return 0;
+}
+
+struct regcache_ops regcache_indexed_ops = {
+	.type = REGCACHE_INDEXED,
+	.name = "indexed",
+	.read = regcache_indexed_read,
+	.write = regcache_indexed_write,
+	.sync = regcache_indexed_sync
+};
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regcache-lzo.c linux-libre-3.2-gnu1/drivers/base/regmap/regcache-lzo.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regcache-lzo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regcache-lzo.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,361 @@
+/*
+ * Register cache access API - LZO caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/lzo.h>
+
+#include "internal.h"
+
+struct regcache_lzo_ctx {
+	void *wmem;
+	void *dst;
+	const void *src;
+	size_t src_len;
+	size_t dst_len;
+	size_t decompressed_size;
+	unsigned long *sync_bmp;
+	int sync_bmp_nbits;
+};
+
+#define LZO_BLOCK_NUM 8
+static int regcache_lzo_block_count(void)
+{
+	return LZO_BLOCK_NUM;
+}
+
+static int regcache_lzo_prepare(struct regcache_lzo_ctx *lzo_ctx)
+{
+	lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+	if (!lzo_ctx->wmem)
+		return -ENOMEM;
+	return 0;
+}
+
+static int regcache_lzo_compress(struct regcache_lzo_ctx *lzo_ctx)
+{
+	size_t compress_size;
+	int ret;
+
+	ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
+			       lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
+	if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
+		return -EINVAL;
+	lzo_ctx->dst_len = compress_size;
+	return 0;
+}
+
+static int regcache_lzo_decompress(struct regcache_lzo_ctx *lzo_ctx)
+{
+	size_t dst_len;
+	int ret;
+
+	dst_len = lzo_ctx->dst_len;
+	ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
+				    lzo_ctx->dst, &dst_len);
+	if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
+		return -EINVAL;
+	return 0;
+}
+
+static int regcache_lzo_compress_cache_block(struct regmap *map,
+		struct regcache_lzo_ctx *lzo_ctx)
+{
+	int ret;
+
+	lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
+	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+	if (!lzo_ctx->dst) {
+		lzo_ctx->dst_len = 0;
+		return -ENOMEM;
+	}
+
+	ret = regcache_lzo_compress(lzo_ctx);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int regcache_lzo_decompress_cache_block(struct regmap *map,
+		struct regcache_lzo_ctx *lzo_ctx)
+{
+	int ret;
+
+	lzo_ctx->dst_len = lzo_ctx->decompressed_size;
+	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+	if (!lzo_ctx->dst) {
+		lzo_ctx->dst_len = 0;
+		return -ENOMEM;
+	}
+
+	ret = regcache_lzo_decompress(lzo_ctx);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int regcache_lzo_get_blkindex(struct regmap *map,
+					    unsigned int reg)
+{
+	return (reg * map->cache_word_size) /
+		DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static inline int regcache_lzo_get_blkpos(struct regmap *map,
+					  unsigned int reg)
+{
+	return reg % (DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()) /
+		      map->cache_word_size);
+}
+
+static inline int regcache_lzo_get_blksize(struct regmap *map)
+{
+	return DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static int regcache_lzo_init(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	size_t bmp_size;
+	int ret, i, blksize, blkcount;
+	const char *p, *end;
+	unsigned long *sync_bmp;
+
+	ret = 0;
+
+	blkcount = regcache_lzo_block_count();
+	map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
+			     GFP_KERNEL);
+	if (!map->cache)
+		return -ENOMEM;
+	lzo_blocks = map->cache;
+
+	/*
+	 * allocate a bitmap to be used when syncing the cache with
+	 * the hardware.  Each time a register is modified, the corresponding
+	 * bit is set in the bitmap, so we know that we have to sync
+	 * that register.
+	 */
+	bmp_size = map->num_reg_defaults_raw;
+	sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
+			   GFP_KERNEL);
+	if (!sync_bmp) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	bitmap_zero(sync_bmp, bmp_size);
+
+	/* allocate the lzo blocks and initialize them */
+	for (i = 0; i < blkcount; i++) {
+		lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
+					GFP_KERNEL);
+		if (!lzo_blocks[i]) {
+			kfree(sync_bmp);
+			ret = -ENOMEM;
+			goto err;
+		}
+		lzo_blocks[i]->sync_bmp = sync_bmp;
+		lzo_blocks[i]->sync_bmp_nbits = bmp_size;
+		/* alloc the working space for the compressed block */
+		ret = regcache_lzo_prepare(lzo_blocks[i]);
+		if (ret < 0)
+			goto err;
+	}
+
+	blksize = regcache_lzo_get_blksize(map);
+	p = map->reg_defaults_raw;
+	end = map->reg_defaults_raw + map->cache_size_raw;
+	/* compress the register map and fill the lzo blocks */
+	for (i = 0; i < blkcount; i++, p += blksize) {
+		lzo_blocks[i]->src = p;
+		if (p + blksize > end)
+			lzo_blocks[i]->src_len = end - p;
+		else
+			lzo_blocks[i]->src_len = blksize;
+		ret = regcache_lzo_compress_cache_block(map,
+						       lzo_blocks[i]);
+		if (ret < 0)
+			goto err;
+		lzo_blocks[i]->decompressed_size =
+			lzo_blocks[i]->src_len;
+	}
+
+	return 0;
+err:
+	regcache_exit(map);
+	return ret;
+}
+
+static int regcache_lzo_exit(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	int i, blkcount;
+
+	lzo_blocks = map->cache;
+	if (!lzo_blocks)
+		return 0;
+
+	blkcount = regcache_lzo_block_count();
+	/*
+	 * the pointer to the bitmap used for syncing the cache
+	 * is shared amongst all lzo_blocks.  Ensure it is freed
+	 * only once.
+	 */
+	if (lzo_blocks[0])
+		kfree(lzo_blocks[0]->sync_bmp);
+	for (i = 0; i < blkcount; i++) {
+		if (lzo_blocks[i]) {
+			kfree(lzo_blocks[i]->wmem);
+			kfree(lzo_blocks[i]->dst);
+		}
+		/* each lzo_block is a pointer returned by kmalloc or NULL */
+		kfree(lzo_blocks[i]);
+	}
+	kfree(lzo_blocks);
+	map->cache = NULL;
+	return 0;
+}
+
+static int regcache_lzo_read(struct regmap *map,
+			     unsigned int reg, unsigned int *value)
+{
+	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+	int ret, blkindex, blkpos;
+	size_t blksize, tmp_dst_len;
+	void *tmp_dst;
+
+	/* index of the compressed lzo block */
+	blkindex = regcache_lzo_get_blkindex(map, reg);
+	/* register index within the decompressed block */
+	blkpos = regcache_lzo_get_blkpos(map, reg);
+	/* size of the compressed block */
+	blksize = regcache_lzo_get_blksize(map);
+	lzo_blocks = map->cache;
+	lzo_block = lzo_blocks[blkindex];
+
+	/* save the pointer and length of the compressed block */
+	tmp_dst = lzo_block->dst;
+	tmp_dst_len = lzo_block->dst_len;
+
+	/* prepare the source to be the compressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* decompress the block */
+	ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+	if (ret >= 0)
+		/* fetch the value from the cache */
+		*value = regcache_get_val(lzo_block->dst, blkpos,
+					  map->cache_word_size);
+
+	kfree(lzo_block->dst);
+	/* restore the pointer and length of the compressed block */
+	lzo_block->dst = tmp_dst;
+	lzo_block->dst_len = tmp_dst_len;
+
+	return ret;
+}
+
+static int regcache_lzo_write(struct regmap *map,
+			      unsigned int reg, unsigned int value)
+{
+	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+	int ret, blkindex, blkpos;
+	size_t blksize, tmp_dst_len;
+	void *tmp_dst;
+
+	/* index of the compressed lzo block */
+	blkindex = regcache_lzo_get_blkindex(map, reg);
+	/* register index within the decompressed block */
+	blkpos = regcache_lzo_get_blkpos(map, reg);
+	/* size of the compressed block */
+	blksize = regcache_lzo_get_blksize(map);
+	lzo_blocks = map->cache;
+	lzo_block = lzo_blocks[blkindex];
+
+	/* save the pointer and length of the compressed block */
+	tmp_dst = lzo_block->dst;
+	tmp_dst_len = lzo_block->dst_len;
+
+	/* prepare the source to be the compressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* decompress the block */
+	ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+	if (ret < 0) {
+		kfree(lzo_block->dst);
+		goto out;
+	}
+
+	/* write the new value to the cache */
+	if (regcache_set_val(lzo_block->dst, blkpos, value,
+			     map->cache_word_size)) {
+		kfree(lzo_block->dst);
+		goto out;
+	}
+
+	/* prepare the source to be the decompressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* compress the block */
+	ret = regcache_lzo_compress_cache_block(map, lzo_block);
+	if (ret < 0) {
+		kfree(lzo_block->dst);
+		kfree(lzo_block->src);
+		goto out;
+	}
+
+	/* set the bit so we know we have to sync this register */
+	set_bit(reg, lzo_block->sync_bmp);
+	kfree(tmp_dst);
+	kfree(lzo_block->src);
+	return 0;
+out:
+	lzo_block->dst = tmp_dst;
+	lzo_block->dst_len = tmp_dst_len;
+	return ret;
+}
+
+static int regcache_lzo_sync(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	unsigned int val;
+	int i;
+	int ret;
+
+	lzo_blocks = map->cache;
+	for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
+		ret = regcache_read(map, i, &val);
+		if (ret)
+			return ret;
+		map->cache_bypass = 1;
+		ret = _regmap_write(map, i, val);
+		map->cache_bypass = 0;
+		if (ret)
+			return ret;
+		dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+			i, val);
+	}
+
+	return 0;
+}
+
+struct regcache_ops regcache_lzo_ops = {
+	.type = REGCACHE_LZO,
+	.name = "lzo",
+	.init = regcache_lzo_init,
+	.exit = regcache_lzo_exit,
+	.read = regcache_lzo_read,
+	.write = regcache_lzo_write,
+	.sync = regcache_lzo_sync
+};
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regcache-rbtree.c linux-libre-3.2-gnu1/drivers/base/regmap/regcache-rbtree.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regcache-rbtree.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regcache-rbtree.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,345 @@
+/*
+ * Register cache access API - rbtree caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/rbtree.h>
+
+#include "internal.h"
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+				 unsigned int value);
+
+struct regcache_rbtree_node {
+	/* the actual rbtree node holding this block */
+	struct rb_node node;
+	/* base register handled by this block */
+	unsigned int base_reg;
+	/* block of adjacent registers */
+	void *block;
+	/* number of registers available in the block */
+	unsigned int blklen;
+} __attribute__ ((packed));
+
+struct regcache_rbtree_ctx {
+	struct rb_root root;
+	struct regcache_rbtree_node *cached_rbnode;
+};
+
+static inline void regcache_rbtree_get_base_top_reg(
+	struct regcache_rbtree_node *rbnode,
+	unsigned int *base, unsigned int *top)
+{
+	*base = rbnode->base_reg;
+	*top = rbnode->base_reg + rbnode->blklen - 1;
+}
+
+static unsigned int regcache_rbtree_get_register(
+	struct regcache_rbtree_node *rbnode, unsigned int idx,
+	unsigned int word_size)
+{
+	return regcache_get_val(rbnode->block, idx, word_size);
+}
+
+static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode,
+					 unsigned int idx, unsigned int val,
+					 unsigned int word_size)
+{
+	regcache_set_val(rbnode->block, idx, val, word_size);
+}
+
+static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
+	unsigned int reg)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
+	struct rb_node *node;
+	struct regcache_rbtree_node *rbnode;
+	unsigned int base_reg, top_reg;
+
+	rbnode = rbtree_ctx->cached_rbnode;
+	if (rbnode) {
+		regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg)
+			return rbnode;
+	}
+
+	node = rbtree_ctx->root.rb_node;
+	while (node) {
+		rbnode = container_of(node, struct regcache_rbtree_node, node);
+		regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg) {
+			rbtree_ctx->cached_rbnode = rbnode;
+			return rbnode;
+		} else if (reg > top_reg) {
+			node = node->rb_right;
+		} else if (reg < base_reg) {
+			node = node->rb_left;
+		}
+	}
+
+	return NULL;
+}
+
+static int regcache_rbtree_insert(struct rb_root *root,
+				  struct regcache_rbtree_node *rbnode)
+{
+	struct rb_node **new, *parent;
+	struct regcache_rbtree_node *rbnode_tmp;
+	unsigned int base_reg_tmp, top_reg_tmp;
+	unsigned int base_reg;
+
+	parent = NULL;
+	new = &root->rb_node;
+	while (*new) {
+		rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
+					  node);
+		/* base and top registers of the current rbnode */
+		regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+						 &top_reg_tmp);
+		/* base register of the rbnode to be added */
+		base_reg = rbnode->base_reg;
+		parent = *new;
+		/* if this register has already been inserted, just return */
+		if (base_reg >= base_reg_tmp &&
+		    base_reg <= top_reg_tmp)
+			return 0;
+		else if (base_reg > top_reg_tmp)
+			new = &((*new)->rb_right);
+		else if (base_reg < base_reg_tmp)
+			new = &((*new)->rb_left);
+	}
+
+	/* insert the node into the rbtree */
+	rb_link_node(&rbnode->node, parent, new);
+	rb_insert_color(&rbnode->node, root);
+
+	return 1;
+}
+
+static int regcache_rbtree_init(struct regmap *map)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	int i;
+	int ret;
+
+	map->cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
+	if (!map->cache)
+		return -ENOMEM;
+
+	rbtree_ctx = map->cache;
+	rbtree_ctx->root = RB_ROOT;
+	rbtree_ctx->cached_rbnode = NULL;
+
+	for (i = 0; i < map->num_reg_defaults; i++) {
+		ret = regcache_rbtree_write(map,
+					    map->reg_defaults[i].reg,
+					    map->reg_defaults[i].def);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	regcache_exit(map);
+	return ret;
+}
+
+static int regcache_rbtree_exit(struct regmap *map)
+{
+	struct rb_node *next;
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct regcache_rbtree_node *rbtree_node;
+
+	/* if we've already been called then just return */
+	rbtree_ctx = map->cache;
+	if (!rbtree_ctx)
+		return 0;
+
+	/* free up the rbtree */
+	next = rb_first(&rbtree_ctx->root);
+	while (next) {
+		rbtree_node = rb_entry(next, struct regcache_rbtree_node, node);
+		next = rb_next(&rbtree_node->node);
+		rb_erase(&rbtree_node->node, &rbtree_ctx->root);
+		kfree(rbtree_node->block);
+		kfree(rbtree_node);
+	}
+
+	/* release the resources */
+	kfree(map->cache);
+	map->cache = NULL;
+
+	return 0;
+}
+
+static int regcache_rbtree_read(struct regmap *map,
+				unsigned int reg, unsigned int *value)
+{
+	struct regcache_rbtree_node *rbnode;
+	unsigned int reg_tmp;
+
+	rbnode = regcache_rbtree_lookup(map, reg);
+	if (rbnode) {
+		reg_tmp = reg - rbnode->base_reg;
+		*value = regcache_rbtree_get_register(rbnode, reg_tmp,
+						      map->cache_word_size);
+	} else {
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+
+static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
+					   unsigned int pos, unsigned int reg,
+					   unsigned int value, unsigned int word_size)
+{
+	u8 *blk;
+
+	blk = krealloc(rbnode->block,
+		       (rbnode->blklen + 1) * word_size, GFP_KERNEL);
+	if (!blk)
+		return -ENOMEM;
+
+	/* insert the register value in the correct place in the rbnode block */
+	memmove(blk + (pos + 1) * word_size,
+		blk + pos * word_size,
+		(rbnode->blklen - pos) * word_size);
+
+	/* update the rbnode block, its size and the base register */
+	rbnode->block = blk;
+	rbnode->blklen++;
+	if (!pos)
+		rbnode->base_reg = reg;
+
+	regcache_rbtree_set_register(rbnode, pos, value, word_size);
+	return 0;
+}
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+				 unsigned int value)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct regcache_rbtree_node *rbnode, *rbnode_tmp;
+	struct rb_node *node;
+	unsigned int val;
+	unsigned int reg_tmp;
+	unsigned int pos;
+	int i;
+	int ret;
+
+	rbtree_ctx = map->cache;
+	/* if we can't locate it in the cached rbnode we'll have
+	 * to traverse the rbtree looking for it.
+	 */
+	rbnode = regcache_rbtree_lookup(map, reg);
+	if (rbnode) {
+		reg_tmp = reg - rbnode->base_reg;
+		val = regcache_rbtree_get_register(rbnode, reg_tmp,
+						   map->cache_word_size);
+		if (val == value)
+			return 0;
+		regcache_rbtree_set_register(rbnode, reg_tmp, value,
+					     map->cache_word_size);
+	} else {
+		/* look for an adjacent register to the one we are about to add */
+		for (node = rb_first(&rbtree_ctx->root); node;
+		     node = rb_next(node)) {
+			rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
+			for (i = 0; i < rbnode_tmp->blklen; i++) {
+				reg_tmp = rbnode_tmp->base_reg + i;
+				if (abs(reg_tmp - reg) != 1)
+					continue;
+				/* decide where in the block to place our register */
+				if (reg_tmp + 1 == reg)
+					pos = i + 1;
+				else
+					pos = i;
+				ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
+								      reg, value,
+								      map->cache_word_size);
+				if (ret)
+					return ret;
+				rbtree_ctx->cached_rbnode = rbnode_tmp;
+				return 0;
+			}
+		}
+		/* we did not manage to find a place to insert it in an existing
+		 * block so create a new rbnode with a single register in its block.
+		 * This block will get populated further if any other adjacent
+		 * registers get modified in the future.
+		 */
+		rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
+		if (!rbnode)
+			return -ENOMEM;
+		rbnode->blklen = 1;
+		rbnode->base_reg = reg;
+		rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
+					GFP_KERNEL);
+		if (!rbnode->block) {
+			kfree(rbnode);
+			return -ENOMEM;
+		}
+		regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
+		regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
+		rbtree_ctx->cached_rbnode = rbnode;
+	}
+
+	return 0;
+}
+
+static int regcache_rbtree_sync(struct regmap *map)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct rb_node *node;
+	struct regcache_rbtree_node *rbnode;
+	unsigned int regtmp;
+	unsigned int val;
+	int ret;
+	int i;
+
+	rbtree_ctx = map->cache;
+	for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
+		rbnode = rb_entry(node, struct regcache_rbtree_node, node);
+		for (i = 0; i < rbnode->blklen; i++) {
+			regtmp = rbnode->base_reg + i;
+			val = regcache_rbtree_get_register(rbnode, i,
+							   map->cache_word_size);
+
+			/* Is this the hardware default?  If so skip. */
+			ret = regcache_lookup_reg(map, i);
+			if (ret > 0 && val == map->reg_defaults[ret].def)
+				continue;
+
+			map->cache_bypass = 1;
+			ret = _regmap_write(map, regtmp, val);
+			map->cache_bypass = 0;
+			if (ret)
+				return ret;
+			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+				regtmp, val);
+		}
+	}
+
+	return 0;
+}
+
+struct regcache_ops regcache_rbtree_ops = {
+	.type = REGCACHE_RBTREE,
+	.name = "rbtree",
+	.init = regcache_rbtree_init,
+	.exit = regcache_rbtree_exit,
+	.read = regcache_rbtree_read,
+	.write = regcache_rbtree_write,
+	.sync = regcache_rbtree_sync
+};
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regmap.c linux-libre-3.2-gnu1/drivers/base/regmap/regmap.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,29 +15,54 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 
-#include <linux/regmap.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/regmap.h>
 
-struct regmap;
+#include "internal.h"
 
-struct regmap_format {
-	size_t buf_size;
-	size_t reg_bytes;
-	size_t val_bytes;
-	void (*format_write)(struct regmap *map,
-			     unsigned int reg, unsigned int val);
-	void (*format_reg)(void *buf, unsigned int reg);
-	void (*format_val)(void *buf, unsigned int val);
-	unsigned int (*parse_val)(void *buf);
-};
+bool regmap_writeable(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
 
-struct regmap {
-	struct mutex lock;
+	if (map->writeable_reg)
+		return map->writeable_reg(map->dev, reg);
 
-	struct device *dev; /* Device we do I/O on */
-	void *work_buf;     /* Scratch buffer used to format I/O */
-	struct regmap_format format;  /* Buffer format */
-	const struct regmap_bus *bus;
-};
+	return true;
+}
+
+bool regmap_readable(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->readable_reg)
+		return map->readable_reg(map->dev, reg);
+
+	return true;
+}
+
+bool regmap_volatile(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->volatile_reg)
+		return map->volatile_reg(map->dev, reg);
+
+	return true;
+}
+
+bool regmap_precious(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->precious_reg)
+		return map->precious_reg(map->dev, reg);
+
+	return false;
+}
 
 static void regmap_format_4_12_write(struct regmap *map,
 				     unsigned int reg, unsigned int val)
@@ -116,6 +141,25 @@ struct regmap *regmap_init(struct device
 	map->format.val_bytes = config->val_bits / 8;
 	map->dev = dev;
 	map->bus = bus;
+	map->max_register = config->max_register;
+	map->writeable_reg = config->writeable_reg;
+	map->readable_reg = config->readable_reg;
+	map->volatile_reg = config->volatile_reg;
+	map->precious_reg = config->precious_reg;
+	map->cache_type = config->cache_type;
+	map->reg_defaults = config->reg_defaults;
+	map->num_reg_defaults = config->num_reg_defaults;
+	map->num_reg_defaults_raw = config->num_reg_defaults_raw;
+	map->reg_defaults_raw = config->reg_defaults_raw;
+	map->cache_size_raw = (config->val_bits / 8) * config->num_reg_defaults_raw;
+	map->cache_word_size = config->val_bits / 8;
+
+	if (config->read_flag_mask || config->write_flag_mask) {
+		map->read_flag_mask = config->read_flag_mask;
+		map->write_flag_mask = config->write_flag_mask;
+	} else {
+		map->read_flag_mask = bus->read_flag_mask;
+	}
 
 	switch (config->reg_bits) {
 	case 4:
@@ -171,6 +215,12 @@ struct regmap *regmap_init(struct device
 		goto err_map;
 	}
 
+	ret = regcache_init(map);
+	if (ret < 0)
+		goto err_map;
+
+	regmap_debugfs_init(map);
+
 	return map;
 
 err_map:
@@ -185,6 +235,8 @@ EXPORT_SYMBOL_GPL(regmap_init);
  */
 void regmap_exit(struct regmap *map)
 {
+	regcache_exit(map);
+	regmap_debugfs_exit(map);
 	kfree(map->work_buf);
 	kfree(map);
 }
@@ -193,19 +245,38 @@ EXPORT_SYMBOL_GPL(regmap_exit);
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 			     const void *val, size_t val_len)
 {
+	u8 *u8 = map->work_buf;
 	void *buf;
 	int ret = -ENOTSUPP;
 	size_t len;
+	int i;
+
+	/* Check for unwritable registers before we start */
+	if (map->writeable_reg)
+		for (i = 0; i < val_len / map->format.val_bytes; i++)
+			if (!map->writeable_reg(map->dev, reg + i))
+				return -EINVAL;
 
 	map->format.format_reg(map->work_buf, reg);
 
-	/* Try to do a gather write if we can */
-	if (map->bus->gather_write)
+	u8[0] |= map->write_flag_mask;
+
+	trace_regmap_hw_write_start(map->dev, reg,
+				    val_len / map->format.val_bytes);
+
+	/* If we're doing a single register write we can probably just
+	 * send the work_buf directly, otherwise try to do a gather
+	 * write.
+	 */
+	if (val == map->work_buf + map->format.reg_bytes)
+		ret = map->bus->write(map->dev, map->work_buf,
+				      map->format.reg_bytes + val_len);
+	else if (map->bus->gather_write)
 		ret = map->bus->gather_write(map->dev, map->work_buf,
 					     map->format.reg_bytes,
 					     val, val_len);
 
-	/* Otherwise fall back on linearising by hand. */
+	/* If that didn't work fall back on linearising by hand. */
 	if (ret == -ENOTSUPP) {
 		len = map->format.reg_bytes + val_len;
 		buf = kmalloc(len, GFP_KERNEL);
@@ -219,19 +290,39 @@ static int _regmap_raw_write(struct regm
 		kfree(buf);
 	}
 
+	trace_regmap_hw_write_done(map->dev, reg,
+				   val_len / map->format.val_bytes);
+
 	return ret;
 }
 
-static int _regmap_write(struct regmap *map, unsigned int reg,
-			 unsigned int val)
+int _regmap_write(struct regmap *map, unsigned int reg,
+		  unsigned int val)
 {
+	int ret;
 	BUG_ON(!map->format.format_write && !map->format.format_val);
 
+	if (!map->cache_bypass) {
+		ret = regcache_write(map, reg, val);
+		if (ret != 0)
+			return ret;
+		if (map->cache_only)
+			return 0;
+	}
+
+	trace_regmap_reg_write(map->dev, reg, val);
+
 	if (map->format.format_write) {
 		map->format.format_write(map, reg, val);
 
-		return map->bus->write(map->dev, map->work_buf,
-				       map->format.buf_size);
+		trace_regmap_hw_write_start(map->dev, reg, 1);
+
+		ret = map->bus->write(map->dev, map->work_buf,
+				      map->format.buf_size);
+
+		trace_regmap_hw_write_done(map->dev, reg, 1);
+
+		return ret;
 	} else {
 		map->format.format_val(map->work_buf + map->format.reg_bytes,
 				       val);
@@ -286,6 +377,8 @@ int regmap_raw_write(struct regmap *map,
 {
 	int ret;
 
+	WARN_ON(map->cache_type != REGCACHE_NONE);
+
 	mutex_lock(&map->lock);
 
 	ret = _regmap_raw_write(map, reg, val, val_len);
@@ -305,20 +398,23 @@ static int _regmap_raw_read(struct regma
 	map->format.format_reg(map->work_buf, reg);
 
 	/*
-	 * Some buses flag reads by setting the high bits in the
+	 * Some buses or devices flag reads by setting the high bits in the
 	 * register addresss; since it's always the high bits for all
 	 * current formats we can do this here rather than in
 	 * formatting.  This may break if we get interesting formats.
 	 */
-	if (map->bus->read_flag_mask)
-		u8[0] |= map->bus->read_flag_mask;
+	u8[0] |= map->read_flag_mask;
+
+	trace_regmap_hw_read_start(map->dev, reg,
+				   val_len / map->format.val_bytes);
 
 	ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
 			     val, val_len);
-	if (ret != 0)
-		return ret;
 
-	return 0;
+	trace_regmap_hw_read_done(map->dev, reg,
+				  val_len / map->format.val_bytes);
+
+	return ret;
 }
 
 static int _regmap_read(struct regmap *map, unsigned int reg,
@@ -329,9 +425,20 @@ static int _regmap_read(struct regmap *m
 	if (!map->format.parse_val)
 		return -EINVAL;
 
+	if (!map->cache_bypass) {
+		ret = regcache_read(map, reg, val);
+		if (ret == 0)
+			return 0;
+	}
+
+	if (map->cache_only)
+		return -EBUSY;
+
 	ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
-	if (ret == 0)
+	if (ret == 0) {
 		*val = map->format.parse_val(map->work_buf);
+		trace_regmap_reg_read(map->dev, reg, *val);
+	}
 
 	return ret;
 }
@@ -375,6 +482,14 @@ int regmap_raw_read(struct regmap *map,
 		    size_t val_len)
 {
 	int ret;
+	int i;
+	bool vol = true;
+
+	for (i = 0; i < val_len / map->format.val_bytes; i++)
+		if (!regmap_volatile(map, reg + i))
+			vol = false;
+
+	WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
 
 	mutex_lock(&map->lock);
 
@@ -402,16 +517,30 @@ int regmap_bulk_read(struct regmap *map,
 {
 	int ret, i;
 	size_t val_bytes = map->format.val_bytes;
+	bool vol = true;
 
 	if (!map->format.parse_val)
 		return -EINVAL;
 
-	ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
-	if (ret != 0)
-		return ret;
+	/* Is this a block of volatile registers? */
+	for (i = 0; i < val_count; i++)
+		if (!regmap_volatile(map, reg + i))
+			vol = false;
 
-	for (i = 0; i < val_count * val_bytes; i += val_bytes)
-		map->format.parse_val(val + i);
+	if (vol || map->cache_type == REGCACHE_NONE) {
+		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+		if (ret != 0)
+			return ret;
+
+		for (i = 0; i < val_count * val_bytes; i += val_bytes)
+			map->format.parse_val(val + i);
+	} else {
+		for (i = 0; i < val_count; i++) {
+			ret = regmap_read(map, reg + i, val + (i * val_bytes));
+			if (ret != 0)
+				return ret;
+		}
+	}
 
 	return 0;
 }
@@ -450,3 +579,11 @@ out:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits);
+
+static int __init regmap_initcall(void)
+{
+	regmap_debugfs_initcall();
+
+	return 0;
+}
+postcore_initcall(regmap_initcall);
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regmap-debugfs.c linux-libre-3.2-gnu1/drivers/base/regmap/regmap-debugfs.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regmap-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regmap-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,209 @@
+/*
+ * Register map access API - debugfs
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include "internal.h"
+
+static struct dentry *regmap_debugfs_root;
+
+/* Calculate the length of a fixed format  */
+static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
+{
+	snprintf(buf, buf_size, "%x", max_val);
+	return strlen(buf);
+}
+
+static int regmap_open_file(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	int reg_len, val_len, tot_len;
+	size_t buf_pos = 0;
+	loff_t p = 0;
+	ssize_t ret;
+	int i;
+	struct regmap *map = file->private_data;
+	char *buf;
+	unsigned int val;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Calculate the length of a fixed format  */
+	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+	val_len = 2 * map->format.val_bytes;
+	tot_len = reg_len + val_len + 3;      /* : \n */
+
+	for (i = 0; i < map->max_register + 1; i++) {
+		if (!regmap_readable(map, i))
+			continue;
+
+		if (regmap_precious(map, i))
+			continue;
+
+		/* If we're in the region the user is trying to read */
+		if (p >= *ppos) {
+			/* ...but not beyond it */
+			if (buf_pos >= count - 1 - tot_len)
+				break;
+
+			/* Format the register */
+			snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
+				 reg_len, i);
+			buf_pos += reg_len + 2;
+
+			/* Format the value, write all X if we can't read */
+			ret = regmap_read(map, i, &val);
+			if (ret == 0)
+				snprintf(buf + buf_pos, count - buf_pos,
+					 "%.*x", val_len, val);
+			else
+				memset(buf + buf_pos, 'X', val_len);
+			buf_pos += 2 * map->format.val_bytes;
+
+			buf[buf_pos++] = '\n';
+		}
+		p += tot_len;
+	}
+
+	ret = buf_pos;
+
+	if (copy_to_user(user_buf, buf, buf_pos)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	*ppos += buf_pos;
+
+out:
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations regmap_map_fops = {
+	.open = regmap_open_file,
+	.read = regmap_map_read_file,
+	.llseek = default_llseek,
+};
+
+static ssize_t regmap_access_read_file(struct file *file,
+				       char __user *user_buf, size_t count,
+				       loff_t *ppos)
+{
+	int reg_len, tot_len;
+	size_t buf_pos = 0;
+	loff_t p = 0;
+	ssize_t ret;
+	int i;
+	struct regmap *map = file->private_data;
+	char *buf;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Calculate the length of a fixed format  */
+	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+	tot_len = reg_len + 10; /* ': R W V P\n' */
+
+	for (i = 0; i < map->max_register + 1; i++) {
+		/* Ignore registers which are neither readable nor writable */
+		if (!regmap_readable(map, i) && !regmap_writeable(map, i))
+			continue;
+
+		/* If we're in the region the user is trying to read */
+		if (p >= *ppos) {
+			/* ...but not beyond it */
+			if (buf_pos >= count - 1 - tot_len)
+				break;
+
+			/* Format the register */
+			snprintf(buf + buf_pos, count - buf_pos,
+				 "%.*x: %c %c %c %c\n",
+				 reg_len, i,
+				 regmap_readable(map, i) ? 'y' : 'n',
+				 regmap_writeable(map, i) ? 'y' : 'n',
+				 regmap_volatile(map, i) ? 'y' : 'n',
+				 regmap_precious(map, i) ? 'y' : 'n');
+
+			buf_pos += tot_len;
+		}
+		p += tot_len;
+	}
+
+	ret = buf_pos;
+
+	if (copy_to_user(user_buf, buf, buf_pos)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	*ppos += buf_pos;
+
+out:
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations regmap_access_fops = {
+	.open = regmap_open_file,
+	.read = regmap_access_read_file,
+	.llseek = default_llseek,
+};
+
+void regmap_debugfs_init(struct regmap *map)
+{
+	map->debugfs = debugfs_create_dir(dev_name(map->dev),
+					  regmap_debugfs_root);
+	if (!map->debugfs) {
+		dev_warn(map->dev, "Failed to create debugfs directory\n");
+		return;
+	}
+
+	if (map->max_register) {
+		debugfs_create_file("registers", 0400, map->debugfs,
+				    map, &regmap_map_fops);
+		debugfs_create_file("access", 0400, map->debugfs,
+				    map, &regmap_access_fops);
+	}
+}
+
+void regmap_debugfs_exit(struct regmap *map)
+{
+	debugfs_remove_recursive(map->debugfs);
+}
+
+void regmap_debugfs_initcall(void)
+{
+	regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
+	if (!regmap_debugfs_root) {
+		pr_warn("regmap: Failed to create debugfs root\n");
+		return;
+	}
+}
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regmap-i2c.c linux-libre-3.2-gnu1/drivers/base/regmap/regmap-i2c.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regmap-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regmap-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,11 +90,9 @@ static int regmap_i2c_read(struct device
 }
 
 static struct regmap_bus regmap_i2c = {
-	.type = &i2c_bus_type,
 	.write = regmap_i2c_write,
 	.gather_write = regmap_i2c_gather_write,
 	.read = regmap_i2c_read,
-	.owner = THIS_MODULE,
 };
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/base/regmap/regmap-spi.c linux-libre-3.2-gnu1/drivers/base/regmap/regmap-spi.c
--- linux-libre-3.1-gnu1/drivers/base/regmap/regmap-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/regmap/regmap-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,11 +48,9 @@ static int regmap_spi_read(struct device
 }
 
 static struct regmap_bus regmap_spi = {
-	.type = &spi_bus_type,
 	.write = regmap_spi_write,
 	.gather_write = regmap_spi_gather_write,
 	.read = regmap_spi_read,
-	.owner = THIS_MODULE,
 	.read_flag_mask = 0x80,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/base/transport_class.c linux-libre-3.2-gnu1/drivers/base/transport_class.c
--- linux-libre-3.1-gnu1/drivers/base/transport_class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/base/transport_class.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
  * transport class is framed entirely in terms of generic devices to
  * allow it to be used by any physical HBA in the system.
  */
+#include <linux/export.h>
 #include <linux/attribute_container.h>
 #include <linux/transport_class.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/bcma_private.h linux-libre-3.2-gnu1/drivers/bcma/bcma_private.h
--- linux-libre-3.1-gnu1/drivers/bcma/bcma_private.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/bcma_private.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,13 +15,29 @@ struct bcma_bus;
 /* main.c */
 int bcma_bus_register(struct bcma_bus *bus);
 void bcma_bus_unregister(struct bcma_bus *bus);
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+				   struct bcma_device *core_cc,
+				   struct bcma_device *core_mips);
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+			       struct bcma_device_id *match,
+			       struct bcma_device *core);
+void bcma_init_bus(struct bcma_bus *bus);
 
 /* sprom.c */
 int bcma_sprom_get(struct bcma_bus *bus);
 
+/* driver_chipcommon.c */
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
+
+/* driver_chipcommon_pmu.c */
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/core.c linux-libre-3.2-gnu1/drivers/bcma/core.c
--- linux-libre-3.1-gnu1/drivers/bcma/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 bool bcma_core_is_enabled(struct bcma_device *core)
@@ -110,6 +111,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
 u32 bcma_core_dma_translation(struct bcma_device *core)
 {
 	switch (core->bus->hosttype) {
+	case BCMA_HOSTTYPE_SOC:
+		return 0;
 	case BCMA_HOSTTYPE_PCI:
 		if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
 			return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/driver_chipcommon.c linux-libre-3.2-gnu1/drivers/bcma/driver_chipcommon.c
--- linux-libre-3.1-gnu1/drivers/bcma/driver_chipcommon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/driver_chipcommon.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
@@ -26,6 +27,9 @@ void bcma_core_chipcommon_init(struct bc
 	u32 leddc_on = 10;
 	u32 leddc_off = 90;
 
+	if (cc->setup_done)
+		return;
+
 	if (cc->core->id.rev >= 11)
 		cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 	cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -52,6 +56,8 @@ void bcma_core_chipcommon_init(struct bc
 			((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
 			 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
 	}
+
+	cc->setup_done = true;
 }
 
 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
@@ -101,3 +107,51 @@ u32 bcma_chipco_gpio_polarity(struct bcm
 {
 	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
 }
+
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
+{
+	unsigned int irq;
+	u32 baud_base;
+	u32 i;
+	unsigned int ccrev = cc->core->id.rev;
+	struct bcma_serial_port *ports = cc->serial_ports;
+
+	if (ccrev >= 11 && ccrev != 15) {
+		/* Fixed ALP clock */
+		baud_base = bcma_pmu_alp_clock(cc);
+		if (ccrev >= 21) {
+			/* Turn off UART clock before switching clocksource. */
+			bcma_cc_write32(cc, BCMA_CC_CORECTL,
+				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+				       & ~BCMA_CC_CORECTL_UARTCLKEN);
+		}
+		/* Set the override bit so we don't divide it */
+		bcma_cc_write32(cc, BCMA_CC_CORECTL,
+			       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+			       | BCMA_CC_CORECTL_UARTCLK0);
+		if (ccrev >= 21) {
+			/* Re-enable the UART clock. */
+			bcma_cc_write32(cc, BCMA_CC_CORECTL,
+				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+				       | BCMA_CC_CORECTL_UARTCLKEN);
+		}
+	} else {
+		pr_err("serial not supported on this device ccrev: 0x%x\n",
+		       ccrev);
+		return;
+	}
+
+	irq = bcma_core_mips_irq(cc->core);
+
+	/* Determine the registers of the UARTs */
+	cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
+	for (i = 0; i < cc->nr_serial_ports; i++) {
+		ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
+				(i * 256);
+		ports[i].irq = irq;
+		ports[i].baud_base = baud_base;
+		ports[i].reg_shift = 0;
+	}
+}
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/driver_chipcommon_pmu.c linux-libre-3.2-gnu1/drivers/bcma/driver_chipcommon_pmu.c
--- linux-libre-3.1-gnu1/drivers/bcma/driver_chipcommon_pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/driver_chipcommon_pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,22 +9,50 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
-static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
-					u32 offset, u32 mask, u32 set)
+static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
 {
-	u32 value;
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+}
 
-	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
+void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
+{
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
+
+void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+			     u32 set)
+{
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
+
+void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
+				 u32 offset, u32 mask, u32 set)
+{
 	bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
 	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
-	value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
-	value &= mask;
-	value |= set;
-	bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
-	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
+	bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
+
+void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+				u32 set)
+{
+	bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
+	bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
 
 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
 {
@@ -83,6 +111,24 @@ void bcma_pmu_swreg_init(struct bcma_drv
 	}
 }
 
+/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
+{
+	struct bcma_bus *bus = cc->core->bus;
+	u32 val;
+
+	val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
+	if (enable) {
+		val |= BCMA_CHIPCTL_4331_EXTPA_EN;
+		if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
+			val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+	} else {
+		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
+		val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+	}
+	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
+}
+
 void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
@@ -92,7 +138,7 @@ void bcma_pmu_workarounds(struct bcma_dr
 		bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
 		break;
 	case 0x4331:
-		pr_err("Enabling Ext PA lines not implemented\n");
+		/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
 		break;
 	case 43224:
 		if (bus->chipinfo.rev == 0) {
@@ -136,3 +182,129 @@ void bcma_pmu_init(struct bcma_drv_cc *c
 	bcma_pmu_swreg_init(cc);
 	bcma_pmu_workarounds(cc);
 }
+
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	switch (bus->chipinfo.id) {
+	case 0x4716:
+	case 0x4748:
+	case 47162:
+	case 0x4313:
+	case 0x5357:
+	case 0x4749:
+	case 53572:
+		/* always 20Mhz */
+		return 20000 * 1000;
+	case 0x5356:
+	case 0x5300:
+		/* always 25Mhz */
+		return 25000 * 1000;
+	default:
+		pr_warn("No ALP clock specified for %04X device, "
+			"pmu rev. %d, using default %d Hz\n",
+			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+	}
+	return BCMA_CC_PMU_ALP_CLOCK;
+}
+
+/* Find the output of the "m" pll divider given pll controls that start with
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
+ */
+static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+{
+	u32 tmp, div, ndiv, p1, p2, fc;
+	struct bcma_bus *bus = cc->core->bus;
+
+	BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
+
+	BUG_ON(!m || m > 4);
+
+	if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
+		/* Detect failure in clock setting */
+		tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+		if (tmp & 0x40000)
+			return 133 * 1000000;
+	}
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
+	p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
+	p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
+	div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
+		BCMA_CC_PPL_MDIV_MASK;
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
+	ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
+
+	/* Do calculation in Mhz */
+	fc = bcma_pmu_alp_clock(cc) / 1000000;
+	fc = (p1 * ndiv * fc) / p2;
+
+	/* Return clock in Hertz */
+	return (fc / div) * 1000000;
+}
+
+/* query bus clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	switch (bus->chipinfo.id) {
+	case 0x4716:
+	case 0x4748:
+	case 47162:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5356:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5357:
+	case 0x4749:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5300:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 53572:
+		return 75000000;
+	default:
+		pr_warn("No backplane clock specified for %04X device, "
+			"pmu rev. %d, using default %d Hz\n",
+			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+	}
+	return BCMA_CC_PMU_HT_CLOCK;
+}
+
+/* query cpu clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	if (bus->chipinfo.id == 53572)
+		return 300000000;
+
+	if (cc->pmu.rev >= 5) {
+		u32 pll;
+		switch (bus->chipinfo.id) {
+		case 0x5356:
+			pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
+			break;
+		case 0x5357:
+		case 0x4749:
+			pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
+			break;
+		default:
+			pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
+			break;
+		}
+
+		/* TODO: if (bus->chipinfo.id == 0x5300)
+		  return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
+		return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
+	}
+
+	return bcma_pmu_get_clockcontrol(cc);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/driver_mips.c linux-libre-3.2-gnu1/drivers/bcma/driver_mips.c
--- linux-libre-3.1-gnu1/drivers/bcma/driver_mips.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/bcma/driver_mips.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,256 @@
+/*
+ * Broadcom specific AMBA
+ * Broadcom MIPS32 74K core driver
+ *
+ * Copyright 2009, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+
+/* The 47162a0 hangs when reading MIPS DMP registers registers */
+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
+{
+	return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
+	       dev->id.id == BCMA_CORE_MIPS_74K;
+}
+
+/* The 5357b0 hangs when reading USB20H DMP registers */
+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
+{
+	return (dev->bus->chipinfo.id == 0x5357 ||
+		dev->bus->chipinfo.id == 0x4749) &&
+	       dev->bus->chipinfo.pkg == 11 &&
+	       dev->id.id == BCMA_CORE_USB20_HOST;
+}
+
+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
+			      u16 offset)
+{
+	return bcma_read32(mcore->core, offset);
+}
+
+static inline void mips_write32(struct bcma_drv_mips *mcore,
+				u16 offset,
+				u32 value)
+{
+	bcma_write32(mcore->core, offset, value);
+}
+
+static const u32 ipsflag_irq_mask[] = {
+	0,
+	BCMA_MIPS_IPSFLAG_IRQ1,
+	BCMA_MIPS_IPSFLAG_IRQ2,
+	BCMA_MIPS_IPSFLAG_IRQ3,
+	BCMA_MIPS_IPSFLAG_IRQ4,
+};
+
+static const u32 ipsflag_irq_shift[] = {
+	0,
+	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+};
+
+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
+{
+	u32 flag;
+
+	if (bcma_core_mips_bcm47162a0_quirk(dev))
+		return dev->core_index;
+	if (bcma_core_mips_bcm5357b0_quirk(dev))
+		return dev->core_index;
+	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+	return flag & 0x1F;
+}
+
+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ */
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+	struct bcma_device *mdev = dev->bus->drv_mips.core;
+	u32 irqflag;
+	unsigned int irq;
+
+	irqflag = bcma_core_mips_irqflag(dev);
+
+	for (irq = 1; irq <= 4; irq++)
+		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+		    (1 << irqflag))
+			return irq;
+
+	return 0;
+}
+EXPORT_SYMBOL(bcma_core_mips_irq);
+
+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+{
+	unsigned int oldirq = bcma_core_mips_irq(dev);
+	struct bcma_bus *bus = dev->bus;
+	struct bcma_device *mdev = bus->drv_mips.core;
+	u32 irqflag;
+
+	irqflag = bcma_core_mips_irqflag(dev);
+	BUG_ON(oldirq == 6);
+
+	dev->irq = irq + 2;
+
+	/* clear the old irq */
+	if (oldirq == 0)
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+			    ~(1 << irqflag));
+	else
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
+
+	/* assign the new one */
+	if (irq == 0) {
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+			    (1 << irqflag));
+	} else {
+		u32 oldirqflag = bcma_read32(mdev,
+					     BCMA_MIPS_MIPS74K_INTMASK(irq));
+		if (oldirqflag) {
+			struct bcma_device *core;
+
+			/* backplane irq line is in use, find out who uses
+			 * it and set user to irq 0
+			 */
+			list_for_each_entry_reverse(core, &bus->cores, list) {
+				if ((1 << bcma_core_mips_irqflag(core)) ==
+				    oldirqflag) {
+					bcma_core_mips_set_irq(core, 0);
+					break;
+				}
+			}
+		}
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
+			     1 << irqflag);
+	}
+
+	pr_info("set_irq: core 0x%04x, irq %d => %d\n",
+		dev->id.id, oldirq + 2, irq + 2);
+}
+
+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
+{
+	int i;
+	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+	printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+	for (i = 0; i <= 6; i++)
+		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
+	printk("\n");
+}
+
+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
+{
+	struct bcma_device *core;
+
+	list_for_each_entry_reverse(core, &bus->cores, list) {
+		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
+	}
+}
+
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+		return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+	pr_err("No PMU available, need this to get the cpu clock\n");
+	return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);
+
+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+	case BCMA_CC_FLASHT_STSER:
+	case BCMA_CC_FLASHT_ATSER:
+		pr_err("Serial flash not supported.\n");
+		break;
+	case BCMA_CC_FLASHT_PARA:
+		pr_info("found parallel flash.\n");
+		bus->drv_cc.pflash.window = 0x1c000000;
+		bus->drv_cc.pflash.window_size = 0x02000000;
+
+		if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+		     BCMA_CC_FLASH_CFG_DS) == 0)
+			bus->drv_cc.pflash.buswidth = 1;
+		else
+			bus->drv_cc.pflash.buswidth = 2;
+		break;
+	default:
+		pr_err("flash not supported.\n");
+	}
+}
+
+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus;
+	struct bcma_device *core;
+	bus = mcore->core->bus;
+
+	pr_info("Initializing MIPS core...\n");
+
+	if (!mcore->setup_done)
+		mcore->assigned_irqs = 1;
+
+	/* Assign IRQs to all cores on the bus */
+	list_for_each_entry_reverse(core, &bus->cores, list) {
+		int mips_irq;
+		if (core->irq)
+			continue;
+
+		mips_irq = bcma_core_mips_irq(core);
+		if (mips_irq > 4)
+			core->irq = 0;
+		else
+			core->irq = mips_irq + 2;
+		if (core->irq > 5)
+			continue;
+		switch (core->id.id) {
+		case BCMA_CORE_PCI:
+		case BCMA_CORE_PCIE:
+		case BCMA_CORE_ETHERNET:
+		case BCMA_CORE_ETHERNET_GBIT:
+		case BCMA_CORE_MAC_GBIT:
+		case BCMA_CORE_80211:
+		case BCMA_CORE_USB20_HOST:
+			/* These devices get their own IRQ line if available,
+			 * the rest goes on IRQ0
+			 */
+			if (mcore->assigned_irqs <= 4)
+				bcma_core_mips_set_irq(core,
+						       mcore->assigned_irqs++);
+			break;
+		}
+	}
+	pr_info("IRQ reconfiguration done\n");
+	bcma_core_mips_dump_irq(bus);
+
+	if (mcore->setup_done)
+		return;
+
+	bcma_chipco_serial_init(&bus->drv_cc);
+	bcma_core_mips_flash_detect(mcore);
+	mcore->setup_done = true;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/driver_pci.c linux-libre-3.2-gnu1/drivers/bcma/driver_pci.c
--- linux-libre-3.1-gnu1/drivers/bcma/driver_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/driver_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 /**************************************************
@@ -173,7 +174,7 @@ static bool bcma_core_pci_is_in_hostmode
 		return false;
 
 #ifdef CONFIG_SSB_DRIVER_PCICORE
-	if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+	if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
 		return false;
 #endif /* CONFIG_SSB_DRIVER_PCICORE */
 
@@ -189,6 +190,9 @@ static bool bcma_core_pci_is_in_hostmode
 
 void bcma_core_pci_init(struct bcma_drv_pci *pc)
 {
+	if (pc->setup_done)
+		return;
+
 	if (bcma_core_pci_is_in_hostmode(pc)) {
 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
 		bcma_core_pci_hostmode_init(pc);
@@ -198,6 +202,8 @@ void bcma_core_pci_init(struct bcma_drv_
 	} else {
 		bcma_core_pci_clientmode_init(pc);
 	}
+
+	pc->setup_done = true;
 }
 
 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
@@ -205,7 +211,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr
 {
 	struct pci_dev *pdev = pc->core->bus->host_pci;
 	u32 coremask, tmp;
-	int err;
+	int err = 0;
+
+	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
+		/* This bcma device is not on a PCI host-bus. So the IRQs are
+		 * not routed through the PCI core.
+		 * So we must not enable routing through the PCI core. */
+		goto out;
+	}
 
 	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
 	if (err)
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/host_pci.c linux-libre-3.2-gnu1/drivers/bcma/host_pci.c
--- linux-libre-3.1-gnu1/drivers/bcma/host_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/host_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/bcma/bcma.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 
 static void bcma_host_pci_switch_core(struct bcma_device *core)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/host_soc.c linux-libre-3.2-gnu1/drivers/bcma/host_soc.c
--- linux-libre-3.1-gnu1/drivers/bcma/host_soc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/bcma/host_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,183 @@
+/*
+ * Broadcom specific AMBA
+ * System on Chip (SoC) Host
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include "scan.h"
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
+{
+	return readb(core->io_addr + offset);
+}
+
+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
+{
+	return readw(core->io_addr + offset);
+}
+
+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
+{
+	return readl(core->io_addr + offset);
+}
+
+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
+				 u8 value)
+{
+	writeb(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
+				 u16 value)
+{
+	writew(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
+				 u32 value)
+{
+	writel(value, core->io_addr + offset);
+}
+
+#ifdef CONFIG_BCMA_BLOCKIO
+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
+				     size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->io_addr + offset;
+
+	switch (reg_width) {
+	case sizeof(u8): {
+		u8 *buf = buffer;
+
+		while (count) {
+			*buf = __raw_readb(addr);
+			buf++;
+			count--;
+		}
+		break;
+	}
+	case sizeof(u16): {
+		__le16 *buf = buffer;
+
+		WARN_ON(count & 1);
+		while (count) {
+			*buf = (__force __le16)__raw_readw(addr);
+			buf++;
+			count -= 2;
+		}
+		break;
+	}
+	case sizeof(u32): {
+		__le32 *buf = buffer;
+
+		WARN_ON(count & 3);
+		while (count) {
+			*buf = (__force __le32)__raw_readl(addr);
+			buf++;
+			count -= 4;
+		}
+		break;
+	}
+	default:
+		WARN_ON(1);
+	}
+}
+
+static void bcma_host_soc_block_write(struct bcma_device *core,
+				      const void *buffer,
+				      size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->io_addr + offset;
+
+	switch (reg_width) {
+	case sizeof(u8): {
+		const u8 *buf = buffer;
+
+		while (count) {
+			__raw_writeb(*buf, addr);
+			buf++;
+			count--;
+		}
+		break;
+	}
+	case sizeof(u16): {
+		const __le16 *buf = buffer;
+
+		WARN_ON(count & 1);
+		while (count) {
+			__raw_writew((__force u16)(*buf), addr);
+			buf++;
+			count -= 2;
+		}
+		break;
+	}
+	case sizeof(u32): {
+		const __le32 *buf = buffer;
+
+		WARN_ON(count & 3);
+		while (count) {
+			__raw_writel((__force u32)(*buf), addr);
+			buf++;
+			count -= 4;
+		}
+		break;
+	}
+	default:
+		WARN_ON(1);
+	}
+}
+#endif /* CONFIG_BCMA_BLOCKIO */
+
+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
+{
+	return readl(core->io_wrap + offset);
+}
+
+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
+				  u32 value)
+{
+	writel(value, core->io_wrap + offset);
+}
+
+const struct bcma_host_ops bcma_host_soc_ops = {
+	.read8		= bcma_host_soc_read8,
+	.read16		= bcma_host_soc_read16,
+	.read32		= bcma_host_soc_read32,
+	.write8		= bcma_host_soc_write8,
+	.write16	= bcma_host_soc_write16,
+	.write32	= bcma_host_soc_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+	.block_read	= bcma_host_soc_block_read,
+	.block_write	= bcma_host_soc_block_write,
+#endif
+	.aread32	= bcma_host_soc_aread32,
+	.awrite32	= bcma_host_soc_awrite32,
+};
+
+int __init bcma_host_soc_register(struct bcma_soc *soc)
+{
+	struct bcma_bus *bus = &soc->bus;
+	int err;
+
+	/* iomap only first core. We have to read some register on this core
+	 * to scan the bus.
+	 */
+	bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+	if (!bus->mmio)
+		return -ENOMEM;
+
+	/* Host specific */
+	bus->hosttype = BCMA_HOSTTYPE_SOC;
+	bus->ops = &bcma_host_soc_ops;
+
+	/* Register */
+	err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
+	if (err)
+		iounmap(bus->mmio);
+
+	return err;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/Kconfig linux-libre-3.2-gnu1/drivers/bcma/Kconfig
--- linux-libre-3.1-gnu1/drivers/bcma/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,19 @@ config BCMA_DRIVER_PCI_HOSTMODE
 	help
 	  PCI core hostmode operation (external PCI bus).
 
+config BCMA_HOST_SOC
+	bool
+	depends on BCMA_DRIVER_MIPS
+
+config BCMA_DRIVER_MIPS
+	bool "BCMA Broadcom MIPS core driver"
+	depends on BCMA && MIPS
+	help
+	  Driver for the Broadcom MIPS core attached to Broadcom specific
+	  Advanced Microcontroller Bus.
+
+	  If unsure, say N
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/main.c linux-libre-3.2-gnu1/drivers/bcma/main.c
--- linux-libre-3.1-gnu1/drivers/bcma/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/module.h>
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
 
@@ -68,6 +69,10 @@ static struct bcma_device *bcma_find_cor
 static void bcma_release_core_dev(struct device *dev)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+	if (core->io_addr)
+		iounmap(core->io_addr);
+	if (core->io_wrap)
+		iounmap(core->io_wrap);
 	kfree(core);
 }
 
@@ -82,6 +87,7 @@ static int bcma_register_cores(struct bc
 		case BCMA_CORE_CHIPCOMMON:
 		case BCMA_CORE_PCI:
 		case BCMA_CORE_PCIE:
+		case BCMA_CORE_MIPS_74K:
 			continue;
 		}
 
@@ -95,7 +101,10 @@ static int bcma_register_cores(struct bc
 			core->dma_dev = &bus->host_pci->dev;
 			core->irq = bus->host_pci->irq;
 			break;
-		case BCMA_HOSTTYPE_NONE:
+		case BCMA_HOSTTYPE_SOC:
+			core->dev.dma_mask = &core->dev.coherent_dma_mask;
+			core->dma_dev = &core->dev;
+			break;
 		case BCMA_HOSTTYPE_SDIO:
 			break;
 		}
@@ -142,6 +151,13 @@ int bcma_bus_register(struct bcma_bus *b
 		bcma_core_chipcommon_init(&bus->drv_cc);
 	}
 
+	/* Init MIPS core */
+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+	if (core) {
+		bus->drv_mips.core = core;
+		bcma_core_mips_init(&bus->drv_mips);
+	}
+
 	/* Init PCIE core */
 	core = bcma_find_core(bus, BCMA_CORE_PCIE);
 	if (core) {
@@ -171,6 +187,59 @@ void bcma_bus_unregister(struct bcma_bus
 	bcma_unregister_cores(bus);
 }
 
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+				   struct bcma_device *core_cc,
+				   struct bcma_device *core_mips)
+{
+	int err;
+	struct bcma_device *core;
+	struct bcma_device_id match;
+
+	bcma_init_bus(bus);
+
+	match.manuf = BCMA_MANUF_BCM;
+	match.id = BCMA_CORE_CHIPCOMMON;
+	match.class = BCMA_CL_SIM;
+	match.rev = BCMA_ANY_REV;
+
+	/* Scan for chip common core */
+	err = bcma_bus_scan_early(bus, &match, core_cc);
+	if (err) {
+		pr_err("Failed to scan for common core: %d\n", err);
+		return -1;
+	}
+
+	match.manuf = BCMA_MANUF_MIPS;
+	match.id = BCMA_CORE_MIPS_74K;
+	match.class = BCMA_CL_SIM;
+	match.rev = BCMA_ANY_REV;
+
+	/* Scan for mips core */
+	err = bcma_bus_scan_early(bus, &match, core_mips);
+	if (err) {
+		pr_err("Failed to scan for mips core: %d\n", err);
+		return -1;
+	}
+
+	/* Init CC core */
+	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+	if (core) {
+		bus->drv_cc.core = core;
+		bcma_core_chipcommon_init(&bus->drv_cc);
+	}
+
+	/* Init MIPS core */
+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+	if (core) {
+		bus->drv_mips.core = core;
+		bcma_core_mips_init(&bus->drv_mips);
+	}
+
+	pr_info("Early bus registered\n");
+
+	return 0;
+}
+
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
 	drv->drv.name = drv->name;
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/Makefile linux-libre-3.2-gnu1/drivers/bcma/Makefile
--- linux-libre-3.1-gnu1/drivers/bcma/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,9 @@ bcma-y					+= main.o scan.o core.o sprom
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
+bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
+bcma-$(CONFIG_BCMA_HOST_SOC)		+= host_soc.o
 obj-$(CONFIG_BCMA)			+= bcma.o
 
 ccflags-$(CONFIG_BCMA_DEBUG)		:= -DDEBUG
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/scan.c linux-libre-3.2-gnu1/drivers/bcma/scan.c
--- linux-libre-3.1-gnu1/drivers/bcma/scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,18 +200,162 @@ static s32 bcma_erom_get_addr_desc(struc
 	return addrl;
 }
 
-int bcma_bus_scan(struct bcma_bus *bus)
+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
+						   u16 index)
 {
-	u32 erombase;
-	u32 __iomem *eromptr, *eromend;
+	struct bcma_device *core;
+
+	list_for_each_entry(core, &bus->cores, list) {
+		if (core->core_index == index)
+			return core;
+	}
+	return NULL;
+}
 
+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+			      struct bcma_device_id *match, int core_num,
+			      struct bcma_device *core)
+{
+	s32 tmp;
+	u8 i, j;
 	s32 cia, cib;
 	u8 ports[2], wrappers[2];
 
+	/* get CIs */
+	cia = bcma_erom_get_ci(bus, eromptr);
+	if (cia < 0) {
+		bcma_erom_push_ent(eromptr);
+		if (bcma_erom_is_end(bus, eromptr))
+			return -ESPIPE;
+		return -EILSEQ;
+	}
+	cib = bcma_erom_get_ci(bus, eromptr);
+	if (cib < 0)
+		return -EILSEQ;
+
+	/* parse CIs */
+	core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
+	core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
+	core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
+	ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
+	ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
+	wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
+	wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
+	core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+
+	if (((core->id.manuf == BCMA_MANUF_ARM) &&
+	     (core->id.id == 0xFFF)) ||
+	    (ports[1] == 0)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	/* check if component is a core at all */
+	if (wrappers[0] + wrappers[1] == 0) {
+		/* we could save addrl of the router
+		if (cid == BCMA_CORE_OOB_ROUTER)
+		 */
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	if (bcma_erom_is_bridge(bus, eromptr)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	if (bcma_find_core_by_index(bus, core_num)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENODEV;
+	}
+
+	if (match && ((match->manuf != BCMA_ANY_MANUF &&
+	      match->manuf != core->id.manuf) ||
+	     (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
+	     (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
+	     (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
+	    )) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENODEV;
+	}
+
+	/* get & parse master ports */
+	for (i = 0; i < ports[0]; i++) {
+		s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
+		if (mst_port_d < 0)
+			return -EILSEQ;
+	}
+
+	/* get & parse slave ports */
+	for (i = 0; i < ports[1]; i++) {
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_SLAVE, i);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: slave port %d "
+				 * "has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (i == 0 && j == 0)
+					core->addr = tmp;
+			}
+		}
+	}
+
+	/* get & parse master wrappers */
+	for (i = 0; i < wrappers[0]; i++) {
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_MWRAP, i);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: master wrapper %d "
+				 * "has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (i == 0 && j == 0)
+					core->wrap = tmp;
+			}
+		}
+	}
+
+	/* get & parse slave wrappers */
+	for (i = 0; i < wrappers[1]; i++) {
+		u8 hack = (ports[1] == 1) ? 0 : 1;
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_SWRAP, i + hack);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: master wrapper %d "
+				 * has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (wrappers[0] == 0 && !i && !j)
+					core->wrap = tmp;
+			}
+		}
+	}
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
+		if (!core->io_addr)
+			return -ENOMEM;
+		core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
+		if (!core->io_wrap) {
+			iounmap(core->io_addr);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+void bcma_init_bus(struct bcma_bus *bus)
+{
 	s32 tmp;
-	u8 i, j;
 
-	int err;
+	if (bus->init_done)
+		return;
 
 	INIT_LIST_HEAD(&bus->cores);
 	bus->nr_cores = 0;
@@ -222,9 +366,27 @@ int bcma_bus_scan(struct bcma_bus *bus)
 	bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
 	bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
 	bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+	bus->init_done = true;
+}
+
+int bcma_bus_scan(struct bcma_bus *bus)
+{
+	u32 erombase;
+	u32 __iomem *eromptr, *eromend;
+
+	int err, core_num = 0;
+
+	bcma_init_bus(bus);
 
 	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-	eromptr = bus->mmio;
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+		if (!eromptr)
+			return -ENOMEM;
+	} else {
+		eromptr = bus->mmio;
+	}
+
 	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 
 	bcma_scan_switch_core(bus, erombase);
@@ -236,125 +398,89 @@ int bcma_bus_scan(struct bcma_bus *bus)
 		INIT_LIST_HEAD(&core->list);
 		core->bus = bus;
 
-		/* get CIs */
-		cia = bcma_erom_get_ci(bus, &eromptr);
-		if (cia < 0) {
-			bcma_erom_push_ent(&eromptr);
-			if (bcma_erom_is_end(bus, &eromptr))
-				break;
-			err= -EILSEQ;
-			goto out;
-		}
-		cib = bcma_erom_get_ci(bus, &eromptr);
-		if (cib < 0) {
-			err= -EILSEQ;
-			goto out;
-		}
+		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
+		if (err == -ENODEV) {
+			core_num++;
+			continue;
+		} else if (err == -ENXIO)
+			continue;
+		else if (err == -ESPIPE)
+			break;
+		else if (err < 0)
+			return err;
 
-		/* parse CIs */
-		core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
-		core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
-		core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
-		ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
-		ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
-		wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
-		wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
-		core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+		core->core_index = core_num++;
+		bus->nr_cores++;
 
-		if (((core->id.manuf == BCMA_MANUF_ARM) &&
-		     (core->id.id == 0xFFF)) ||
-		    (ports[1] == 0)) {
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+		pr_info("Core %d found: %s "
+			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+			core->core_index, bcma_device_name(&core->id),
+			core->id.manuf, core->id.id, core->id.rev,
+			core->id.class);
 
-		/* check if component is a core at all */
-		if (wrappers[0] + wrappers[1] == 0) {
-			/* we could save addrl of the router
-			if (cid == BCMA_CORE_OOB_ROUTER)
-			 */
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+		list_add(&core->list, &bus->cores);
+	}
 
-		if (bcma_erom_is_bridge(bus, &eromptr)) {
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+		iounmap(eromptr);
 
-		/* get & parse master ports */
-		for (i = 0; i < ports[0]; i++) {
-			u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
-			if (mst_port_d < 0) {
-				err= -EILSEQ;
-				goto out;
-			}
-		}
+	return 0;
+}
 
-		/* get & parse slave ports */
-		for (i = 0; i < ports[1]; i++) {
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_SLAVE, i);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: slave port %d "
-					 * "has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (i == 0 && j == 0)
-						core->addr = tmp;
-				}
-			}
-		}
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+			       struct bcma_device_id *match,
+			       struct bcma_device *core)
+{
+	u32 erombase;
+	u32 __iomem *eromptr, *eromend;
 
-		/* get & parse master wrappers */
-		for (i = 0; i < wrappers[0]; i++) {
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_MWRAP, i);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: master wrapper %d "
-					 * "has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (i == 0 && j == 0)
-						core->wrap = tmp;
-				}
-			}
-		}
+	int err = -ENODEV;
+	int core_num = 0;
 
-		/* get & parse slave wrappers */
-		for (i = 0; i < wrappers[1]; i++) {
-			u8 hack = (ports[1] == 1) ? 0 : 1;
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_SWRAP, i + hack);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: master wrapper %d "
-					 * has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (wrappers[0] == 0 && !i && !j)
-						core->wrap = tmp;
-				}
-			}
-		}
+	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+		if (!eromptr)
+			return -ENOMEM;
+	} else {
+		eromptr = bus->mmio;
+	}
+
+	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
+
+	bcma_scan_switch_core(bus, erombase);
+
+	while (eromptr < eromend) {
+		memset(core, 0, sizeof(*core));
+		INIT_LIST_HEAD(&core->list);
+		core->bus = bus;
 
+		err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
+		if (err == -ENODEV) {
+			core_num++;
+			continue;
+		} else if (err == -ENXIO)
+			continue;
+		else if (err == -ESPIPE)
+			break;
+		else if (err < 0)
+			return err;
+
+		core->core_index = core_num++;
+		bus->nr_cores++;
 		pr_info("Core %d found: %s "
 			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-			bus->nr_cores, bcma_device_name(&core->id),
+			core->core_index, bcma_device_name(&core->id),
 			core->id.manuf, core->id.id, core->id.rev,
 			core->id.class);
 
-		core->core_index = bus->nr_cores++;
 		list_add(&core->list, &bus->cores);
-		continue;
-out:
-		return err;
+		err = 0;
+		break;
 	}
 
-	return 0;
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+		iounmap(eromptr);
+
+	return err;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/bcma/sprom.c linux-libre-3.2-gnu1/drivers/bcma/sprom.c
--- linux-libre-3.1-gnu1/drivers/bcma/sprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bcma/sprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -133,6 +133,15 @@ static void bcma_sprom_extract_r8(struct
 		v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
 		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
 	}
+
+	bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
+
+	bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
+	bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
+	bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
+	bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
+
+	bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
 }
 
 int bcma_sprom_get(struct bcma_bus *bus)
@@ -152,6 +161,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
 	if (!sprom)
 		return -ENOMEM;
 
+	if (bus->chipinfo.id == 0x4331)
+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
+
 	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
 	 * According to brcm80211 this applies to cards with PCIe rev >= 6
 	 * TODO: understand this condition and use it */
@@ -159,6 +171,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
 		BCMA_CC_SPROM_PCIE6;
 	bcma_sprom_read(bus, offset, sprom);
 
+	if (bus->chipinfo.id == 0x4331)
+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
+
 	err = bcma_sprom_valid(sprom);
 	if (err)
 		goto out;
diff -druNp linux-libre-3.1-gnu1/drivers/block/aoe/aoeblk.c linux-libre-3.2-gnu1/drivers/block/aoe/aoeblk.c
--- linux-libre-3.1-gnu1/drivers/block/aoe/aoeblk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/aoe/aoeblk.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/genhd.h>
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
+#include <linux/export.h>
 #include "aoe.h"
 
 static DEFINE_MUTEX(aoeblk_mutex);
@@ -159,7 +160,7 @@ aoeblk_release(struct gendisk *disk, fmo
 	return 0;
 }
 
-static int
+static void
 aoeblk_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct sk_buff_head queue;
@@ -172,25 +173,25 @@ aoeblk_make_request(struct request_queue
 	if (bio == NULL) {
 		printk(KERN_ERR "aoe: bio is NULL\n");
 		BUG();
-		return 0;
+		return;
 	}
 	d = bio->bi_bdev->bd_disk->private_data;
 	if (d == NULL) {
 		printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
 		BUG();
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	} else if (bio->bi_io_vec == NULL) {
 		printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
 		BUG();
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	}
 	buf = mempool_alloc(d->bufpool, GFP_NOIO);
 	if (buf == NULL) {
 		printk(KERN_INFO "aoe: buf allocation failure\n");
 		bio_endio(bio, -ENOMEM);
-		return 0;
+		return;
 	}
 	memset(buf, 0, sizeof(*buf));
 	INIT_LIST_HEAD(&buf->bufs);
@@ -211,7 +212,7 @@ aoeblk_make_request(struct request_queue
 		spin_unlock_irqrestore(&d->lock, flags);
 		mempool_free(buf, d->bufpool);
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	}
 
 	list_add_tail(&buf->bufs, &d->bufq);
@@ -222,8 +223,6 @@ aoeblk_make_request(struct request_queue
 
 	spin_unlock_irqrestore(&d->lock, flags);
 	aoenet_xmit(&queue);
-
-	return 0;
 }
 
 static int
diff -druNp linux-libre-3.1-gnu1/drivers/block/aoe/aoechr.c linux-libre-3.2-gnu1/drivers/block/aoe/aoechr.c
--- linux-libre-3.1-gnu1/drivers/block/aoe/aoechr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/aoe/aoechr.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/skbuff.h>
+#include <linux/export.h>
 #include "aoe.h"
 
 enum {
diff -druNp linux-libre-3.1-gnu1/drivers/block/brd.c linux-libre-3.2-gnu1/drivers/block/brd.c
--- linux-libre-3.1-gnu1/drivers/block/brd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/brd.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@ out:
 	return err;
 }
 
-static int brd_make_request(struct request_queue *q, struct bio *bio)
+static void brd_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct block_device *bdev = bio->bi_bdev;
 	struct brd_device *brd = bdev->bd_disk->private_data;
@@ -359,8 +359,6 @@ static int brd_make_request(struct reque
 
 out:
 	bio_endio(bio, err);
-
-	return 0;
 }
 
 #ifdef CONFIG_BLK_DEV_XIP
diff -druNp linux-libre-3.1-gnu1/drivers/block/cciss.c linux-libre-3.2-gnu1/drivers/block/cciss.c
--- linux-libre-3.1-gnu1/drivers/block/cciss.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/cciss.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -68,6 +69,10 @@ static int cciss_tape_cmds = 6;
 module_param(cciss_tape_cmds, int, 0644);
 MODULE_PARM_DESC(cciss_tape_cmds,
 	"number of commands to allocate for tape devices (default: 6)");
+static int cciss_simple_mode;
+module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cciss_simple_mode,
+	"Use 'simple mode' rather than 'performant mode'");
 
 static DEFINE_MUTEX(cciss_mutex);
 static struct proc_dir_entry *proc_cciss;
@@ -176,6 +181,7 @@ static void cciss_geometry_inquiry(ctlr_
 			unsigned int block_size, InquiryData_struct *inq_buff,
 				   drive_info_struct *drv);
 static void __devinit cciss_interrupt_mode(ctlr_info_t *);
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
 static void start_io(ctlr_info_t *h);
 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
 			__u8 page_code, unsigned char scsi3addr[],
@@ -388,7 +394,7 @@ static void cciss_seq_show_header(struct
 		h->product_name,
 		(unsigned long)h->board_id,
 		h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
-		h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT],
+		h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
 		h->num_luns,
 		h->Qdepth, h->commands_outstanding,
 		h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -636,6 +642,18 @@ static ssize_t host_store_rescan(struct
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 
+static ssize_t host_show_transport_mode(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct ctlr_info *h = to_hba(dev);
+
+	return snprintf(buf, 20, "%s\n",
+		h->transMethod & CFGTBL_Trans_Performant ?
+			"performant" : "simple");
+}
+static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL);
+
 static ssize_t dev_show_unique_id(struct device *dev,
 				 struct device_attribute *attr,
 				 char *buf)
@@ -808,6 +826,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO,
 static struct attribute *cciss_host_attrs[] = {
 	&dev_attr_rescan.attr,
 	&dev_attr_resettable.attr,
+	&dev_attr_transport_mode.attr,
 	NULL
 };
 
@@ -2582,6 +2601,8 @@ static int fill_cmd(ctlr_info_t *h, Comm
 			c->Request.Timeout = 0;
 			c->Request.CDB[0] = BMIC_WRITE;
 			c->Request.CDB[6] = BMIC_CACHE_FLUSH;
+			c->Request.CDB[7] = (size >> 8) & 0xFF;
+			c->Request.CDB[8] = size & 0xFF;
 			break;
 		case TEST_UNIT_READY:
 			c->Request.CDBLen = 6;
@@ -3984,6 +4005,9 @@ static void __devinit cciss_put_controll
 {
 	__u32 trans_support;
 
+	if (cciss_simple_mode)
+		return;
+
 	dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
 	/* Attempt to put controller into performant mode if supported */
 	/* Does board support performant mode? */
@@ -4081,7 +4105,7 @@ static void __devinit cciss_interrupt_mo
 default_int_mode:
 #endif				/* CONFIG_PCI_MSI */
 	/* if we get here we're going to use the default interrupt mode */
-	h->intr[PERF_MODE_INT] = h->pdev->irq;
+	h->intr[h->intr_mode] = h->pdev->irq;
 	return;
 }
 
@@ -4298,6 +4322,10 @@ static int __devinit cciss_pci_init(ctlr
 		dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
 		return -ENODEV;
 	}
+
+	pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+				PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
 	err = pci_enable_device(h->pdev);
 	if (err) {
 		dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n");
@@ -4341,6 +4369,9 @@ static int __devinit cciss_pci_init(ctlr
 	}
 	cciss_enable_scsi_prefetch(h);
 	cciss_p600_dma_prefetch_quirk(h);
+	err = cciss_enter_simple_mode(h);
+	if (err)
+		goto err_out_free_res;
 	cciss_put_controller_into_performant_mode(h);
 	return 0;
 
@@ -4533,6 +4564,13 @@ static int cciss_controller_hard_reset(s
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
 		pmcsr |= PCI_D0;
 		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+		/*
+		 * The P600 requires a small delay when changing states.
+		 * Otherwise we may think the board did not reset and we bail.
+		 * This for kdump only and is particular to the P600.
+		 */
+		msleep(500);
 	}
 	return 0;
 }
@@ -4843,20 +4881,20 @@ static int cciss_request_irq(ctlr_info_t
 	irqreturn_t (*intxhandler)(int, void *))
 {
 	if (h->msix_vector || h->msi_vector) {
-		if (!request_irq(h->intr[PERF_MODE_INT], msixhandler,
-				IRQF_DISABLED, h->devname, h))
+		if (!request_irq(h->intr[h->intr_mode], msixhandler,
+				0, h->devname, h))
 			return 0;
 		dev_err(&h->pdev->dev, "Unable to get msi irq %d"
-			" for %s\n", h->intr[PERF_MODE_INT],
+			" for %s\n", h->intr[h->intr_mode],
 			h->devname);
 		return -1;
 	}
 
-	if (!request_irq(h->intr[PERF_MODE_INT], intxhandler,
-			IRQF_DISABLED, h->devname, h))
+	if (!request_irq(h->intr[h->intr_mode], intxhandler,
+			IRQF_SHARED, h->devname, h))
 		return 0;
 	dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
-		h->intr[PERF_MODE_INT], h->devname);
+		h->intr[h->intr_mode], h->devname);
 	return -1;
 }
 
@@ -4887,7 +4925,7 @@ static void cciss_undo_allocations_after
 {
 	int ctlr = h->ctlr;
 
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 #ifdef CONFIG_PCI_MSI
 	if (h->msix_vector)
 		pci_disable_msix(h->pdev);
@@ -4953,6 +4991,7 @@ reinit_after_soft_reset:
 	h = hba[i];
 	h->pdev = pdev;
 	h->busy_initializing = 1;
+	h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
 	INIT_LIST_HEAD(&h->cmpQ);
 	INIT_LIST_HEAD(&h->reqQ);
 	mutex_init(&h->busy_shutting_down);
@@ -5009,7 +5048,7 @@ reinit_after_soft_reset:
 
 	dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
 	       h->devname, pdev->device, pci_name(pdev),
-	       h->intr[PERF_MODE_INT], dac ? "" : " not");
+	       h->intr[h->intr_mode], dac ? "" : " not");
 
 	if (cciss_allocate_cmd_pool(h))
 		goto clean4;
@@ -5056,7 +5095,7 @@ reinit_after_soft_reset:
 		spin_lock_irqsave(&h->lock, flags);
 		h->access.set_intr_mask(h, CCISS_INTR_OFF);
 		spin_unlock_irqrestore(&h->lock, flags);
-		free_irq(h->intr[PERF_MODE_INT], h);
+		free_irq(h->intr[h->intr_mode], h);
 		rc = cciss_request_irq(h, cciss_msix_discard_completions,
 					cciss_intx_discard_completions);
 		if (rc) {
@@ -5126,6 +5165,7 @@ reinit_after_soft_reset:
 	h->cciss_max_sectors = 8192;
 
 	rebuild_lun_table(h, 1, 0);
+	cciss_engage_scsi(h);
 	h->busy_initializing = 0;
 	return 1;
 
@@ -5133,7 +5173,7 @@ clean4:
 	cciss_free_cmd_pool(h);
 	cciss_free_scatterlists(h);
 	cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 clean2:
 	unregister_blkdev(h->major, h->devname);
 clean1:
@@ -5172,9 +5212,31 @@ static void cciss_shutdown(struct pci_de
 	if (return_code != IO_OK)
 		dev_warn(&h->pdev->dev, "Error flushing cache\n");
 	h->access.set_intr_mask(h, CCISS_INTR_OFF);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 }
 
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
+{
+	u32 trans_support;
+
+	trans_support = readl(&(h->cfgtable->TransportSupport));
+	if (!(trans_support & SIMPLE_MODE))
+		return -ENOTSUPP;
+
+	h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+	writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+	cciss_wait_for_mode_change_ack(h);
+	print_cfg_table(h);
+	if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+		dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
+		return -ENODEV;
+	}
+	h->transMethod = CFGTBL_Trans_Simple;
+	return 0;
+}
+
+
 static void __devexit cciss_remove_one(struct pci_dev *pdev)
 {
 	ctlr_info_t *h;
diff -druNp linux-libre-3.1-gnu1/drivers/block/cciss.h linux-libre-3.2-gnu1/drivers/block/cciss.h
--- linux-libre-3.1-gnu1/drivers/block/cciss.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/cciss.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,6 +92,7 @@ struct ctlr_info
 	unsigned int intr[4];
 	unsigned int msix_vector;
 	unsigned int msi_vector;
+	int	intr_mode;
 	int 	cciss_max_sectors;
 	BYTE	cciss_read;
 	BYTE	cciss_write;
diff -druNp linux-libre-3.1-gnu1/drivers/block/cciss_scsi.c linux-libre-3.2-gnu1/drivers/block/cciss_scsi.c
--- linux-libre-3.1-gnu1/drivers/block/cciss_scsi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/cciss_scsi.c	2012-01-04 18:55:44.000000000 -0500
@@ -1720,5 +1720,6 @@ static int  cciss_eh_abort_handler(struc
 /* If no tape support, then these become defined out of existence */
 
 #define cciss_scsi_setup(cntl_num)
+#define cciss_engage_scsi(h)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */
diff -druNp linux-libre-3.1-gnu1/drivers/block/cpqarray.c linux-libre-3.2-gnu1/drivers/block/cpqarray.c
--- linux-libre-3.1-gnu1/drivers/block/cpqarray.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/cpqarray.c	2012-01-04 18:55:44.000000000 -0500
@@ -620,6 +620,7 @@ static int cpqarray_pci_init(ctlr_info_t
 	}
 	vendor_id = pdev->vendor;
 	device_id = pdev->device;
+	revision  = pdev->revision;
 	irq = pdev->irq;
 
 	for(i=0; i<6; i++)
@@ -632,7 +633,6 @@ static int cpqarray_pci_init(ctlr_info_t
 	}
 
 	pci_read_config_word(pdev, PCI_COMMAND, &command);
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
 
diff -druNp linux-libre-3.1-gnu1/drivers/block/drbd/drbd_bitmap.c linux-libre-3.2-gnu1/drivers/block/drbd/drbd_bitmap.c
--- linux-libre-3.1-gnu1/drivers/block/drbd/drbd_bitmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/drbd/drbd_bitmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -378,15 +378,14 @@ static struct page **bm_realloc_pages(st
 	 * thread.  As we have no disk yet, we are not in the IO path,
 	 * not even the IO path of the peer. */
 	bytes = sizeof(struct page *)*want;
-	new_pages = kmalloc(bytes, GFP_KERNEL);
+	new_pages = kzalloc(bytes, GFP_KERNEL);
 	if (!new_pages) {
-		new_pages = vmalloc(bytes);
+		new_pages = vzalloc(bytes);
 		if (!new_pages)
 			return NULL;
 		vmalloced = 1;
 	}
 
-	memset(new_pages, 0, bytes);
 	if (want >= have) {
 		for (i = 0; i < have; i++)
 			new_pages[i] = old_pages[i];
diff -druNp linux-libre-3.1-gnu1/drivers/block/drbd/drbd_int.h linux-libre-3.2-gnu1/drivers/block/drbd/drbd_int.h
--- linux-libre-3.1-gnu1/drivers/block/drbd/drbd_int.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/drbd/drbd_int.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -928,7 +927,7 @@ struct drbd_md {
 #define NL_INT64(pn,pr,member) __u64 member;
 #define NL_BIT(pn,pr,member)   unsigned member:1;
 #define NL_STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 struct drbd_backing_dev {
 	struct block_device *backing_bdev;
@@ -1507,7 +1506,7 @@ extern void drbd_free_mdev(struct drbd_c
 extern int proc_details;
 
 /* drbd_req */
-extern int drbd_make_request(struct request_queue *q, struct bio *bio);
+extern void drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
diff -druNp linux-libre-3.1-gnu1/drivers/block/drbd/drbd_nl.c linux-libre-3.2-gnu1/drivers/block/drbd/drbd_nl.c
--- linux-libre-3.1-gnu1/drivers/block/drbd/drbd_nl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/drbd/drbd_nl.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,7 +94,7 @@ static int name ## _from_tags(struct drb
 		 arg->member ## _len = dlen; \
 		 memcpy(arg->member, tags, min_t(size_t, dlen, len)); \
 		 break;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 /* Generate the struct to tag_list functions */
 #define NL_PACKET(name, number, fields) \
@@ -129,7 +129,7 @@ name ## _to_tags(struct drbd_conf *mdev,
 	put_unaligned(arg->member ## _len, tags++);	\
 	memcpy(tags, arg->member, arg->member ## _len); \
 	tags = (unsigned short *)((char *)tags + arg->member ## _len);
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name);
 void drbd_nl_send_reply(struct cn_msg *, int);
diff -druNp linux-libre-3.1-gnu1/drivers/block/drbd/drbd_req.c linux-libre-3.2-gnu1/drivers/block/drbd/drbd_req.c
--- linux-libre-3.1-gnu1/drivers/block/drbd/drbd_req.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/drbd/drbd_req.c	2012-01-04 18:55:44.000000000 -0500
@@ -1073,7 +1073,7 @@ static int drbd_fail_request_early(struc
 	return 0;
 }
 
-int drbd_make_request(struct request_queue *q, struct bio *bio)
+void drbd_make_request(struct request_queue *q, struct bio *bio)
 {
 	unsigned int s_enr, e_enr;
 	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
@@ -1081,7 +1081,7 @@ int drbd_make_request(struct request_que
 
 	if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
 		bio_endio(bio, -EPERM);
-		return 0;
+		return;
 	}
 
 	start_time = jiffies;
@@ -1100,7 +1100,8 @@ int drbd_make_request(struct request_que
 
 	if (likely(s_enr == e_enr)) {
 		inc_ap_bio(mdev, 1);
-		return drbd_make_request_common(mdev, bio, start_time);
+		drbd_make_request_common(mdev, bio, start_time);
+		return;
 	}
 
 	/* can this bio be split generically?
@@ -1148,7 +1149,6 @@ int drbd_make_request(struct request_que
 
 		bio_pair_release(bp);
 	}
-	return 0;
 }
 
 /* This is called by bio_add_page().  With this function we reduce
diff -druNp linux-libre-3.1-gnu1/drivers/block/loop.c linux-libre-3.2-gnu1/drivers/block/loop.c
--- linux-libre-3.1-gnu1/drivers/block/loop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/loop.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@
 #include <linux/splice.h>
 #include <linux/sysfs.h>
 #include <linux/miscdevice.h>
+#include <linux/falloc.h>
+
 #include <asm/uaccess.h>
 
 static DEFINE_IDR(loop_index_idr);
@@ -159,17 +161,19 @@ static struct loop_func_table *xfer_func
 	&xor_funcs
 };
 
-static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
 {
-	loff_t size, offset, loopsize;
+	loff_t size, loopsize;
 
 	/* Compute loopsize in bytes */
 	size = i_size_read(file->f_mapping->host);
-	offset = lo->lo_offset;
 	loopsize = size - offset;
-	if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
-		loopsize = lo->lo_sizelimit;
+	/* offset is beyond i_size, wierd but possible */
+	if (loopsize < 0)
+		return 0;
 
+	if (sizelimit > 0 && sizelimit < loopsize)
+		loopsize = sizelimit;
 	/*
 	 * Unfortunately, if we want to do I/O on the device,
 	 * the number of 512-byte sectors has to fit into a sector_t.
@@ -177,17 +181,25 @@ static loff_t get_loop_size(struct loop_
 	return loopsize >> 9;
 }
 
+static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+{
+	return get_size(lo->lo_offset, lo->lo_sizelimit, file);
+}
+
 static int
-figure_loop_size(struct loop_device *lo)
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 {
-	loff_t size = get_loop_size(lo, lo->lo_backing_file);
+	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
 	sector_t x = (sector_t)size;
 
 	if (unlikely((loff_t)x != size))
 		return -EFBIG;
-
+	if (lo->lo_offset != offset)
+		lo->lo_offset = offset;
+	if (lo->lo_sizelimit != sizelimit)
+		lo->lo_sizelimit = sizelimit;
 	set_capacity(lo->lo_disk, x);
-	return 0;					
+	return 0;
 }
 
 static inline int
@@ -203,74 +215,6 @@ lo_do_transfer(struct loop_device *lo, i
 }
 
 /**
- * do_lo_send_aops - helper for writing data to a loop device
- *
- * This is the fast version for backing filesystems which implement the address
- * space operations write_begin and write_end.
- */
-static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
-		loff_t pos, struct page *unused)
-{
-	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
-	struct address_space *mapping = file->f_mapping;
-	pgoff_t index;
-	unsigned offset, bv_offs;
-	int len, ret;
-
-	mutex_lock(&mapping->host->i_mutex);
-	index = pos >> PAGE_CACHE_SHIFT;
-	offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
-	bv_offs = bvec->bv_offset;
-	len = bvec->bv_len;
-	while (len > 0) {
-		sector_t IV;
-		unsigned size, copied;
-		int transfer_result;
-		struct page *page;
-		void *fsdata;
-
-		IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
-		size = PAGE_CACHE_SIZE - offset;
-		if (size > len)
-			size = len;
-
-		ret = pagecache_write_begin(file, mapping, pos, size, 0,
-							&page, &fsdata);
-		if (ret)
-			goto fail;
-
-		file_update_time(file);
-
-		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
-				bvec->bv_page, bv_offs, size, IV);
-		copied = size;
-		if (unlikely(transfer_result))
-			copied = 0;
-
-		ret = pagecache_write_end(file, mapping, pos, size, copied,
-							page, fsdata);
-		if (ret < 0 || ret != copied)
-			goto fail;
-
-		if (unlikely(transfer_result))
-			goto fail;
-
-		bv_offs += copied;
-		len -= copied;
-		offset = 0;
-		index++;
-		pos += copied;
-	}
-	ret = 0;
-out:
-	mutex_unlock(&mapping->host->i_mutex);
-	return ret;
-fail:
-	ret = -1;
-	goto out;
-}
-
-/**
  * __do_lo_send_write - helper for writing data to a loop device
  *
  * This helper just factors out common code between do_lo_send_direct_write()
@@ -297,10 +241,8 @@ static int __do_lo_send_write(struct fil
 /**
  * do_lo_send_direct_write - helper for writing data to a loop device
  *
- * This is the fast, non-transforming version for backing filesystems which do
- * not implement the address space operations write_begin and write_end.
- * It uses the write file operation which should be present on all writeable
- * filesystems.
+ * This is the fast, non-transforming version that does not need double
+ * buffering.
  */
 static int do_lo_send_direct_write(struct loop_device *lo,
 		struct bio_vec *bvec, loff_t pos, struct page *page)
@@ -316,15 +258,9 @@ static int do_lo_send_direct_write(struc
 /**
  * do_lo_send_write - helper for writing data to a loop device
  *
- * This is the slow, transforming version for filesystems which do not
- * implement the address space operations write_begin and write_end.  It
- * uses the write file operation which should be present on all writeable
- * filesystems.
- *
- * Using fops->write is slower than using aops->{prepare,commit}_write in the
- * transforming case because we need to double buffer the data as we cannot do
- * the transformations in place as we do not have direct access to the
- * destination pages of the backing file.
+ * This is the slow, transforming version that needs to double buffer the
+ * data as it cannot do the transformations in place without having direct
+ * access to the destination pages of the backing file.
  */
 static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
 		loff_t pos, struct page *page)
@@ -350,17 +286,16 @@ static int lo_send(struct loop_device *l
 	struct page *page = NULL;
 	int i, ret = 0;
 
-	do_lo_send = do_lo_send_aops;
-	if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+	if (lo->transfer != transfer_none) {
+		page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+		if (unlikely(!page))
+			goto fail;
+		kmap(page);
+		do_lo_send = do_lo_send_write;
+	} else {
 		do_lo_send = do_lo_send_direct_write;
-		if (lo->transfer != transfer_none) {
-			page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
-			if (unlikely(!page))
-				goto fail;
-			kmap(page);
-			do_lo_send = do_lo_send_write;
-		}
 	}
+
 	bio_for_each_segment(bvec, bio, i) {
 		ret = do_lo_send(lo, bvec, pos, page);
 		if (ret < 0)
@@ -447,7 +382,8 @@ do_lo_receive(struct loop_device *lo,
 
 	if (retval < 0)
 		return retval;
-
+	if (retval != bvec->bv_len)
+		return -EIO;
 	return 0;
 }
 
@@ -484,6 +420,29 @@ static int do_bio_filebacked(struct loop
 			}
 		}
 
+		/*
+		 * We use punch hole to reclaim the free space used by the
+		 * image a.k.a. discard. However we do not support discard if
+		 * encryption is enabled, because it may give an attacker
+		 * useful information.
+		 */
+		if (bio->bi_rw & REQ_DISCARD) {
+			struct file *file = lo->lo_backing_file;
+			int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+
+			if ((!file->f_op->fallocate) ||
+			    lo->lo_encrypt_key_size) {
+				ret = -EOPNOTSUPP;
+				goto out;
+			}
+			ret = file->f_op->fallocate(file, mode, pos,
+						    bio->bi_size);
+			if (unlikely(ret && ret != -EINVAL &&
+				     ret != -EOPNOTSUPP))
+				ret = -EIO;
+			goto out;
+		}
+
 		ret = lo_send(lo, bio, pos);
 
 		if ((bio->bi_rw & REQ_FUA) && !ret) {
@@ -514,7 +473,7 @@ static struct bio *loop_get_bio(struct l
 	return bio_list_pop(&lo->lo_bio_list);
 }
 
-static int loop_make_request(struct request_queue *q, struct bio *old_bio)
+static void loop_make_request(struct request_queue *q, struct bio *old_bio)
 {
 	struct loop_device *lo = q->queuedata;
 	int rw = bio_rw(old_bio);
@@ -532,12 +491,11 @@ static int loop_make_request(struct requ
 	loop_add_bio(lo, old_bio);
 	wake_up(&lo->lo_event);
 	spin_unlock_irq(&lo->lo_lock);
-	return 0;
+	return;
 
 out:
 	spin_unlock_irq(&lo->lo_lock);
 	bio_io_error(old_bio);
-	return 0;
 }
 
 struct switch_request {
@@ -700,7 +658,7 @@ static int loop_change_fd(struct loop_de
 		goto out_putf;
 
 	fput(old_file);
-	if (max_part > 0)
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
 	return 0;
 
@@ -777,16 +735,25 @@ static ssize_t loop_attr_autoclear_show(
 	return sprintf(buf, "%s\n", autoclear ? "1" : "0");
 }
 
+static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
+{
+	int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN);
+
+	return sprintf(buf, "%s\n", partscan ? "1" : "0");
+}
+
 LOOP_ATTR_RO(backing_file);
 LOOP_ATTR_RO(offset);
 LOOP_ATTR_RO(sizelimit);
 LOOP_ATTR_RO(autoclear);
+LOOP_ATTR_RO(partscan);
 
 static struct attribute *loop_attrs[] = {
 	&loop_attr_backing_file.attr,
 	&loop_attr_offset.attr,
 	&loop_attr_sizelimit.attr,
 	&loop_attr_autoclear.attr,
+	&loop_attr_partscan.attr,
 	NULL,
 };
 
@@ -807,6 +774,35 @@ static void loop_sysfs_exit(struct loop_
 			   &loop_attribute_group);
 }
 
+static void loop_config_discard(struct loop_device *lo)
+{
+	struct file *file = lo->lo_backing_file;
+	struct inode *inode = file->f_mapping->host;
+	struct request_queue *q = lo->lo_queue;
+
+	/*
+	 * We use punch hole to reclaim the free space used by the
+	 * image a.k.a. discard. However we do support discard if
+	 * encryption is enabled, because it may give an attacker
+	 * useful information.
+	 */
+	if ((!file->f_op->fallocate) ||
+	    lo->lo_encrypt_key_size) {
+		q->limits.discard_granularity = 0;
+		q->limits.discard_alignment = 0;
+		q->limits.max_discard_sectors = 0;
+		q->limits.discard_zeroes_data = 0;
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+		return;
+	}
+
+	q->limits.discard_granularity = inode->i_sb->s_blocksize;
+	q->limits.discard_alignment = 0;
+	q->limits.max_discard_sectors = UINT_MAX >> 9;
+	q->limits.discard_zeroes_data = 1;
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
@@ -849,35 +845,23 @@ static int loop_set_fd(struct loop_devic
 	mapping = file->f_mapping;
 	inode = mapping->host;
 
-	if (!(file->f_mode & FMODE_WRITE))
-		lo_flags |= LO_FLAGS_READ_ONLY;
-
 	error = -EINVAL;
-	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-		const struct address_space_operations *aops = mapping->a_ops;
-
-		if (aops->write_begin)
-			lo_flags |= LO_FLAGS_USE_AOPS;
-		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
-			lo_flags |= LO_FLAGS_READ_ONLY;
+	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
+		goto out_putf;
 
-		lo_blocksize = S_ISBLK(inode->i_mode) ?
-			inode->i_bdev->bd_block_size : PAGE_SIZE;
+	if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
+	    !file->f_op->write)
+		lo_flags |= LO_FLAGS_READ_ONLY;
 
-		error = 0;
-	} else {
-		goto out_putf;
-	}
+	lo_blocksize = S_ISBLK(inode->i_mode) ?
+		inode->i_bdev->bd_block_size : PAGE_SIZE;
 
+	error = -EFBIG;
 	size = get_loop_size(lo, file);
-
-	if ((loff_t)(sector_t)size != size) {
-		error = -EFBIG;
+	if ((loff_t)(sector_t)size != size)
 		goto out_putf;
-	}
 
-	if (!(mode & FMODE_WRITE))
-		lo_flags |= LO_FLAGS_READ_ONLY;
+	error = 0;
 
 	set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
 
@@ -919,7 +903,9 @@ static int loop_set_fd(struct loop_devic
 	}
 	lo->lo_state = Lo_bound;
 	wake_up_process(lo->lo_thread);
-	if (max_part > 0)
+	if (part_shift)
+		lo->lo_flags |= LO_FLAGS_PARTSCAN;
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
 	return 0;
 
@@ -980,10 +966,11 @@ loop_init_xfer(struct loop_device *lo, s
 	return err;
 }
 
-static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+static int loop_clr_fd(struct loop_device *lo)
 {
 	struct file *filp = lo->lo_backing_file;
 	gfp_t gfp = lo->old_gfp_mask;
+	struct block_device *bdev = lo->lo_device;
 
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
@@ -1012,7 +999,6 @@ static int loop_clr_fd(struct loop_devic
 	lo->lo_offset = 0;
 	lo->lo_sizelimit = 0;
 	lo->lo_encrypt_key_size = 0;
-	lo->lo_flags = 0;
 	lo->lo_thread = NULL;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
@@ -1030,8 +1016,11 @@ static int loop_clr_fd(struct loop_devic
 	lo->lo_state = Lo_unbound;
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
-	if (max_part > 0 && bdev)
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
+	lo->lo_flags = 0;
+	if (!part_shift)
+		lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
 	mutex_unlock(&lo->lo_ctl_mutex);
 	/*
 	 * Need not hold lo_ctl_mutex to fput backing file.
@@ -1080,11 +1069,10 @@ loop_set_status(struct loop_device *lo,
 
 	if (lo->lo_offset != info->lo_offset ||
 	    lo->lo_sizelimit != info->lo_sizelimit) {
-		lo->lo_offset = info->lo_offset;
-		lo->lo_sizelimit = info->lo_sizelimit;
-		if (figure_loop_size(lo))
+		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
 			return -EFBIG;
 	}
+	loop_config_discard(lo);
 
 	memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
 	memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
@@ -1100,6 +1088,13 @@ loop_set_status(struct loop_device *lo,
 	     (info->lo_flags & LO_FLAGS_AUTOCLEAR))
 		lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
 
+	if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
+	     !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
+		lo->lo_flags |= LO_FLAGS_PARTSCAN;
+		lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+		ioctl_by_bdev(lo->lo_device, BLKRRPART, 0);
+	}
+
 	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
 	lo->lo_init[0] = info->lo_init[0];
 	lo->lo_init[1] = info->lo_init[1];
@@ -1260,7 +1255,7 @@ static int loop_set_capacity(struct loop
 	err = -ENXIO;
 	if (unlikely(lo->lo_state != Lo_bound))
 		goto out;
-	err = figure_loop_size(lo);
+	err = figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
 	if (unlikely(err))
 		goto out;
 	sec = get_capacity(lo->lo_disk);
@@ -1293,18 +1288,24 @@ static int lo_ioctl(struct block_device
 		break;
 	case LOOP_CLR_FD:
 		/* loop_clr_fd would have unlocked lo_ctl_mutex on success */
-		err = loop_clr_fd(lo, bdev);
+		err = loop_clr_fd(lo);
 		if (!err)
 			goto out_unlocked;
 		break;
 	case LOOP_SET_STATUS:
-		err = loop_set_status_old(lo, (struct loop_info __user *) arg);
+		err = -EPERM;
+		if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+			err = loop_set_status_old(lo,
+					(struct loop_info __user *)arg);
 		break;
 	case LOOP_GET_STATUS:
 		err = loop_get_status_old(lo, (struct loop_info __user *) arg);
 		break;
 	case LOOP_SET_STATUS64:
-		err = loop_set_status64(lo, (struct loop_info64 __user *) arg);
+		err = -EPERM;
+		if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+			err = loop_set_status64(lo,
+					(struct loop_info64 __user *) arg);
 		break;
 	case LOOP_GET_STATUS64:
 		err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
@@ -1513,7 +1514,7 @@ static int lo_release(struct gendisk *di
 		 * In autoclear mode, stop the loop thread
 		 * and remove configuration after last close.
 		 */
-		err = loop_clr_fd(lo, NULL);
+		err = loop_clr_fd(lo);
 		if (!err)
 			goto out_unlocked;
 	} else {
@@ -1635,6 +1636,27 @@ static int loop_add(struct loop_device *
 	if (!disk)
 		goto out_free_queue;
 
+	/*
+	 * Disable partition scanning by default. The in-kernel partition
+	 * scanning can be requested individually per-device during its
+	 * setup. Userspace can always add and remove partitions from all
+	 * devices. The needed partition minors are allocated from the
+	 * extended minor space, the main loop device numbers will continue
+	 * to match the loop minors, regardless of the number of partitions
+	 * used.
+	 *
+	 * If max_part is given, partition scanning is globally enabled for
+	 * all loop devices. The minors for the main loop devices will be
+	 * multiples of max_part.
+	 *
+	 * Note: Global-for-all-devices, set-only-at-init, read-only module
+	 * parameteters like 'max_loop' and 'max_part' make things needlessly
+	 * complicated, are too static, inflexible and may surprise
+	 * userspace tools. Parameters like this in general should be avoided.
+	 */
+	if (!part_shift)
+		disk->flags |= GENHD_FL_NO_PART_SCAN;
+	disk->flags |= GENHD_FL_EXT_DEVT;
 	mutex_init(&lo->lo_ctl_mutex);
 	lo->lo_number		= i;
 	lo->lo_thread		= NULL;
diff -druNp linux-libre-3.1-gnu1/drivers/block/nbd.c linux-libre-3.2-gnu1/drivers/block/nbd.c
--- linux-libre-3.1-gnu1/drivers/block/nbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/nbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,8 +127,7 @@ static void sock_shutdown(struct nbd_dev
 	if (lock)
 		mutex_lock(&lo->tx_lock);
 	if (lo->sock) {
-		printk(KERN_WARNING "%s: shutting down socket\n",
-			lo->disk->disk_name);
+		dev_warn(disk_to_dev(lo->disk), "shutting down socket\n");
 		kernel_sock_shutdown(lo->sock, SHUT_RDWR);
 		lo->sock = NULL;
 	}
@@ -158,8 +157,9 @@ static int sock_xmit(struct nbd_device *
 	sigset_t blocked, oldset;
 
 	if (unlikely(!sock)) {
-		printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
-		       lo->disk->disk_name, (send ? "send" : "recv"));
+		dev_err(disk_to_dev(lo->disk),
+			"Attempted %s on closed socket in sock_xmit\n",
+			(send ? "send" : "recv"));
 		return -EINVAL;
 	}
 
@@ -250,8 +250,8 @@ static int nbd_send_req(struct nbd_devic
 	result = sock_xmit(lo, 1, &request, sizeof(request),
 			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
 	if (result <= 0) {
-		printk(KERN_ERR "%s: Send control failed (result %d)\n",
-				lo->disk->disk_name, result);
+		dev_err(disk_to_dev(lo->disk),
+			"Send control failed (result %d)\n", result);
 		goto error_out;
 	}
 
@@ -270,8 +270,9 @@ static int nbd_send_req(struct nbd_devic
 					lo->disk->disk_name, req, bvec->bv_len);
 			result = sock_send_bvec(lo, bvec, flags);
 			if (result <= 0) {
-				printk(KERN_ERR "%s: Send data failed (result %d)\n",
-						lo->disk->disk_name, result);
+				dev_err(disk_to_dev(lo->disk),
+					"Send data failed (result %d)\n",
+					result);
 				goto error_out;
 			}
 		}
@@ -328,14 +329,13 @@ static struct request *nbd_read_stat(str
 	reply.magic = 0;
 	result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0) {
-		printk(KERN_ERR "%s: Receive control failed (result %d)\n",
-				lo->disk->disk_name, result);
+		dev_err(disk_to_dev(lo->disk),
+			"Receive control failed (result %d)\n", result);
 		goto harderror;
 	}
 
 	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
-				lo->disk->disk_name,
+		dev_err(disk_to_dev(lo->disk), "Wrong magic (0x%lx)\n",
 				(unsigned long)ntohl(reply.magic));
 		result = -EPROTO;
 		goto harderror;
@@ -347,15 +347,15 @@ static struct request *nbd_read_stat(str
 		if (result != -ENOENT)
 			goto harderror;
 
-		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
-				lo->disk->disk_name, reply.handle);
+		dev_err(disk_to_dev(lo->disk), "Unexpected reply (%p)\n",
+			reply.handle);
 		result = -EBADR;
 		goto harderror;
 	}
 
 	if (ntohl(reply.error)) {
-		printk(KERN_ERR "%s: Other side returned error (%d)\n",
-				lo->disk->disk_name, ntohl(reply.error));
+		dev_err(disk_to_dev(lo->disk), "Other side returned error (%d)\n",
+			ntohl(reply.error));
 		req->errors++;
 		return req;
 	}
@@ -369,8 +369,8 @@ static struct request *nbd_read_stat(str
 		rq_for_each_segment(bvec, req, iter) {
 			result = sock_recv_bvec(lo, bvec);
 			if (result <= 0) {
-				printk(KERN_ERR "%s: Receive data failed (result %d)\n",
-						lo->disk->disk_name, result);
+				dev_err(disk_to_dev(lo->disk), "Receive data failed (result %d)\n",
+					result);
 				req->errors++;
 				return req;
 			}
@@ -405,10 +405,10 @@ static int nbd_do_it(struct nbd_device *
 
 	BUG_ON(lo->magic != LO_MAGIC);
 
-	lo->pid = current->pid;
-	ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+	lo->pid = task_pid_nr(current);
+	ret = device_create_file(disk_to_dev(lo->disk), &pid_attr);
 	if (ret) {
-		printk(KERN_ERR "nbd: sysfs_create_file failed!");
+		dev_err(disk_to_dev(lo->disk), "device_create_file failed!\n");
 		lo->pid = 0;
 		return ret;
 	}
@@ -416,7 +416,7 @@ static int nbd_do_it(struct nbd_device *
 	while ((req = nbd_read_stat(lo)) != NULL)
 		nbd_end_request(req);
 
-	sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+	device_remove_file(disk_to_dev(lo->disk), &pid_attr);
 	lo->pid = 0;
 	return 0;
 }
@@ -457,8 +457,8 @@ static void nbd_handle_req(struct nbd_de
 	if (rq_data_dir(req) == WRITE) {
 		nbd_cmd(req) = NBD_CMD_WRITE;
 		if (lo->flags & NBD_READ_ONLY) {
-			printk(KERN_ERR "%s: Write on read-only\n",
-					lo->disk->disk_name);
+			dev_err(disk_to_dev(lo->disk),
+				"Write on read-only\n");
 			goto error_out;
 		}
 	}
@@ -468,16 +468,15 @@ static void nbd_handle_req(struct nbd_de
 	mutex_lock(&lo->tx_lock);
 	if (unlikely(!lo->sock)) {
 		mutex_unlock(&lo->tx_lock);
-		printk(KERN_ERR "%s: Attempted send on closed socket\n",
-		       lo->disk->disk_name);
+		dev_err(disk_to_dev(lo->disk),
+			"Attempted send on closed socket\n");
 		goto error_out;
 	}
 
 	lo->active_req = req;
 
 	if (nbd_send_req(lo, req) != 0) {
-		printk(KERN_ERR "%s: Request send failed\n",
-				lo->disk->disk_name);
+		dev_err(disk_to_dev(lo->disk), "Request send failed\n");
 		req->errors++;
 		nbd_end_request(req);
 	} else {
@@ -549,8 +548,8 @@ static void do_nbd_request(struct reques
 		BUG_ON(lo->magic != LO_MAGIC);
 
 		if (unlikely(!lo->sock)) {
-			printk(KERN_ERR "%s: Attempted send on closed socket\n",
-				lo->disk->disk_name);
+			dev_err(disk_to_dev(lo->disk),
+				"Attempted send on closed socket\n");
 			req->errors++;
 			nbd_end_request(req);
 			spin_lock_irq(q->queue_lock);
@@ -576,7 +575,7 @@ static int __nbd_ioctl(struct block_devi
 	case NBD_DISCONNECT: {
 		struct request sreq;
 
-	        printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+		dev_info(disk_to_dev(lo->disk), "NBD_DISCONNECT\n");
 
 		blk_rq_init(NULL, &sreq);
 		sreq.cmd_type = REQ_TYPE_SPECIAL;
@@ -674,7 +673,7 @@ static int __nbd_ioctl(struct block_devi
 		file = lo->file;
 		lo->file = NULL;
 		nbd_clear_que(lo);
-		printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
+		dev_warn(disk_to_dev(lo->disk), "queue cleared\n");
 		if (file)
 			fput(file);
 		lo->bytesize = 0;
@@ -694,8 +693,8 @@ static int __nbd_ioctl(struct block_devi
 		return 0;
 
 	case NBD_PRINT_DEBUG:
-		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
-			bdev->bd_disk->disk_name,
+		dev_info(disk_to_dev(lo->disk),
+			"next = %p, prev = %p, head = %p\n",
 			lo->queue_head.next, lo->queue_head.prev,
 			&lo->queue_head);
 		return 0;
@@ -745,7 +744,7 @@ static int __init nbd_init(void)
 	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
 	if (max_part < 0) {
-		printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+		printk(KERN_ERR "nbd: max_part must be >= 0\n");
 		return -EINVAL;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/block/paride/pg.c linux-libre-3.2-gnu1/drivers/block/paride/pg.c
--- linux-libre-3.1-gnu1/drivers/block/paride/pg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/paride/pg.c	2012-01-04 18:55:44.000000000 -0500
@@ -630,6 +630,7 @@ static ssize_t pg_read(struct file *filp
 		if (dev->status & 0x10)
 			return -ETIME;
 
+	memset(&hdr, 0, sizeof(hdr));
 	hdr.magic = PG_MAGIC;
 	hdr.dlen = dev->dlen;
 	copy = 0;
diff -druNp linux-libre-3.1-gnu1/drivers/block/pktcdvd.c linux-libre-3.2-gnu1/drivers/block/pktcdvd.c
--- linux-libre-3.1-gnu1/drivers/block/pktcdvd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/pktcdvd.c	2012-01-04 18:55:44.000000000 -0500
@@ -2444,7 +2444,7 @@ static void pkt_end_io_read_cloned(struc
 	pkt_bio_finished(pd);
 }
 
-static int pkt_make_request(struct request_queue *q, struct bio *bio)
+static void pkt_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct pktcdvd_device *pd;
 	char b[BDEVNAME_SIZE];
@@ -2473,7 +2473,7 @@ static int pkt_make_request(struct reque
 		cloned_bio->bi_end_io = pkt_end_io_read_cloned;
 		pd->stats.secs_r += bio->bi_size >> 9;
 		pkt_queue_bio(pd, cloned_bio);
-		return 0;
+		return;
 	}
 
 	if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
@@ -2509,7 +2509,7 @@ static int pkt_make_request(struct reque
 			pkt_make_request(q, &bp->bio1);
 			pkt_make_request(q, &bp->bio2);
 			bio_pair_release(bp);
-			return 0;
+			return;
 		}
 	}
 
@@ -2533,7 +2533,7 @@ static int pkt_make_request(struct reque
 				}
 				spin_unlock(&pkt->lock);
 				spin_unlock(&pd->cdrw.active_list_lock);
-				return 0;
+				return;
 			} else {
 				blocked_bio = 1;
 			}
@@ -2584,10 +2584,9 @@ static int pkt_make_request(struct reque
 		 */
 		wake_up(&pd->wqueue);
 	}
-	return 0;
+	return;
 end_io:
 	bio_io_error(bio);
-	return 0;
 }
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/block/ps3disk.c linux-libre-3.2-gnu1/drivers/block/ps3disk.c
--- linux-libre-3.1-gnu1/drivers/block/ps3disk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/ps3disk.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/ata.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/lv1call.h>
 #include <asm/ps3stor.h>
diff -druNp linux-libre-3.1-gnu1/drivers/block/ps3vram.c linux-libre-3.2-gnu1/drivers/block/ps3vram.c
--- linux-libre-3.1-gnu1/drivers/block/ps3vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/ps3vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -596,7 +597,7 @@ out:
 	return next;
 }
 
-static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct ps3_system_bus_device *dev = q->queuedata;
 	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
@@ -610,13 +611,11 @@ static int ps3vram_make_request(struct r
 	spin_unlock_irq(&priv->lock);
 
 	if (busy)
-		return 0;
+		return;
 
 	do {
 		bio = ps3vram_do_bio(dev, bio);
 	} while (bio);
-
-	return 0;
 }
 
 static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
diff -druNp linux-libre-3.1-gnu1/drivers/block/rbd.c linux-libre-3.2-gnu1/drivers/block/rbd.c
--- linux-libre-3.1-gnu1/drivers/block/rbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/rbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,16 +183,12 @@ static LIST_HEAD(rbd_client_list);
 
 static int __rbd_init_snaps_header(struct rbd_device *rbd_dev);
 static void rbd_dev_release(struct device *dev);
-static ssize_t rbd_snap_rollback(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf,
-				 size_t size);
 static ssize_t rbd_snap_add(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf,
 			    size_t count);
 static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev,
-				  struct rbd_snap *snap);;
+				  struct rbd_snap *snap);
 
 
 static struct rbd_device *dev_to_rbd(struct device *dev)
@@ -260,7 +256,7 @@ static struct rbd_client *rbd_client_cre
 	kref_init(&rbdc->kref);
 	INIT_LIST_HEAD(&rbdc->node);
 
-	rbdc->client = ceph_create_client(opt, rbdc);
+	rbdc->client = ceph_create_client(opt, rbdc, 0, 0);
 	if (IS_ERR(rbdc->client))
 		goto out_rbdc;
 	opt = NULL; /* Now rbdc->client is responsible for opt */
@@ -461,6 +457,10 @@ static int rbd_header_from_disk(struct r
 	u32 snap_count = le32_to_cpu(ondisk->snap_count);
 	int ret = -ENOMEM;
 
+	if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) {
+		return -ENXIO;
+	}
+
 	init_rwsem(&header->snap_rwsem);
 	header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
 	header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
@@ -1356,32 +1356,6 @@ fail:
 }
 
 /*
- * Request sync osd rollback
- */
-static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
-				     u64 snapid,
-				     const char *obj)
-{
-	struct ceph_osd_req_op *ops;
-	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0);
-	if (ret < 0)
-		return ret;
-
-	ops[0].snap.snapid = snapid;
-
-	ret = rbd_req_sync_op(dev, NULL,
-			       CEPH_NOSNAP,
-			       0,
-			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
-			       ops,
-			       1, obj, 0, 0, NULL, NULL, NULL);
-
-	rbd_destroy_ops(ops);
-
-	return ret;
-}
-
-/*
  * Request sync osd read
  */
 static int rbd_req_sync_exec(struct rbd_device *dev,
@@ -1610,8 +1584,13 @@ static int rbd_read_header(struct rbd_de
 			goto out_dh;
 
 		rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL);
-		if (rc < 0)
+		if (rc < 0) {
+			if (rc == -ENXIO) {
+				pr_warning("unrecognized header format"
+					   " for image %s", rbd_dev->obj);
+			}
 			goto out_dh;
+		}
 
 		if (snap_count != header->total_snaps) {
 			snap_count = header->total_snaps;
@@ -1882,7 +1861,6 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_na
 static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh);
 static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL);
 static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add);
-static DEVICE_ATTR(rollback_snap, S_IWUSR, NULL, rbd_snap_rollback);
 
 static struct attribute *rbd_attrs[] = {
 	&dev_attr_size.attr,
@@ -1893,7 +1871,6 @@ static struct attribute *rbd_attrs[] = {
 	&dev_attr_current_snap.attr,
 	&dev_attr_refresh.attr,
 	&dev_attr_create_snap.attr,
-	&dev_attr_rollback_snap.attr,
 	NULL
 };
 
@@ -2424,64 +2401,6 @@ err_unlock:
 	return ret;
 }
 
-static ssize_t rbd_snap_rollback(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf,
-				 size_t count)
-{
-	struct rbd_device *rbd_dev = dev_to_rbd(dev);
-	int ret;
-	u64 snapid;
-	u64 cur_ofs;
-	char *seg_name = NULL;
-	char *snap_name = kmalloc(count + 1, GFP_KERNEL);
-	ret = -ENOMEM;
-	if (!snap_name)
-		return ret;
-
-	/* parse snaps add command */
-	snprintf(snap_name, count, "%s", buf);
-	seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
-	if (!seg_name)
-		goto done;
-
-	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
-	ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
-	if (ret < 0)
-		goto done_unlock;
-
-	dout("snapid=%lld\n", snapid);
-
-	cur_ofs = 0;
-	while (cur_ofs < rbd_dev->header.image_size) {
-		cur_ofs += rbd_get_segment(&rbd_dev->header,
-					   rbd_dev->obj,
-					   cur_ofs, (u64)-1,
-					   seg_name, NULL);
-		dout("seg_name=%s\n", seg_name);
-
-		ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name);
-		if (ret < 0)
-			pr_warning("could not roll back obj %s err=%d\n",
-				   seg_name, ret);
-	}
-
-	ret = __rbd_update_snaps(rbd_dev);
-	if (ret < 0)
-		goto done_unlock;
-
-	ret = count;
-
-done_unlock:
-	mutex_unlock(&ctl_mutex);
-done:
-	kfree(seg_name);
-	kfree(snap_name);
-
-	return ret;
-}
-
 static struct bus_attribute rbd_bus_attrs[] = {
 	__ATTR(add, S_IWUSR, NULL, rbd_add),
 	__ATTR(remove, S_IWUSR, NULL, rbd_remove),
diff -druNp linux-libre-3.1-gnu1/drivers/block/swim3.c linux-libre-3.2-gnu1/drivers/block/swim3.c
--- linux-libre-3.1-gnu1/drivers/block/swim3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/swim3.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  * handle GCR disks
  */
 
+#undef DEBUG
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -36,13 +38,11 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 
-static DEFINE_MUTEX(swim3_mutex);
-static struct request_queue *swim3_queue;
-static struct gendisk *disks[2];
-static struct request *fd_req;
-
 #define MAX_FLOPPIES	2
 
+static DEFINE_MUTEX(swim3_mutex);
+static struct gendisk *disks[MAX_FLOPPIES];
+
 enum swim_state {
 	idle,
 	locating,
@@ -177,7 +177,6 @@ struct swim3 {
 
 struct floppy_state {
 	enum swim_state	state;
-	spinlock_t lock;
 	struct swim3 __iomem *swim3;	/* hardware registers */
 	struct dbdma_regs __iomem *dma;	/* DMA controller registers */
 	int	swim3_intr;	/* interrupt number for SWIM3 */
@@ -204,8 +203,20 @@ struct floppy_state {
 	int	wanted;
 	struct macio_dev *mdev;
 	char	dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
+	int	index;
+	struct request *cur_req;
 };
 
+#define swim3_err(fmt, arg...)	dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#define swim3_warn(fmt, arg...)	dev_warn(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#define swim3_info(fmt, arg...)	dev_info(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+
+#ifdef DEBUG
+#define swim3_dbg(fmt, arg...)	dev_dbg(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#else
+#define swim3_dbg(fmt, arg...)	do { } while(0)
+#endif
+
 static struct floppy_state floppy_states[MAX_FLOPPIES];
 static int floppy_count = 0;
 static DEFINE_SPINLOCK(swim3_lock);
@@ -224,17 +235,8 @@ static unsigned short write_postamble[]
 	0, 0, 0, 0, 0, 0
 };
 
-static void swim3_select(struct floppy_state *fs, int sel);
-static void swim3_action(struct floppy_state *fs, int action);
-static int swim3_readbit(struct floppy_state *fs, int bit);
-static void do_fd_request(struct request_queue * q);
-static void start_request(struct floppy_state *fs);
-static void set_timeout(struct floppy_state *fs, int nticks,
-			void (*proc)(unsigned long));
-static void scan_track(struct floppy_state *fs);
 static void seek_track(struct floppy_state *fs, int n);
 static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count);
-static void setup_transfer(struct floppy_state *fs);
 static void act(struct floppy_state *fs);
 static void scan_timeout(unsigned long data);
 static void seek_timeout(unsigned long data);
@@ -254,18 +256,21 @@ static unsigned int floppy_check_events(
 					unsigned int clearing);
 static int floppy_revalidate(struct gendisk *disk);
 
-static bool swim3_end_request(int err, unsigned int nr_bytes)
+static bool swim3_end_request(struct floppy_state *fs, int err, unsigned int nr_bytes)
 {
-	if (__blk_end_request(fd_req, err, nr_bytes))
-		return true;
+	struct request *req = fs->cur_req;
+	int rc;
 
-	fd_req = NULL;
-	return false;
-}
+	swim3_dbg("  end request, err=%d nr_bytes=%d, cur_req=%p\n",
+		  err, nr_bytes, req);
 
-static bool swim3_end_request_cur(int err)
-{
-	return swim3_end_request(err, blk_rq_cur_bytes(fd_req));
+	if (err)
+		nr_bytes = blk_rq_cur_bytes(req);
+	rc = __blk_end_request(req, err, nr_bytes);
+	if (rc)
+		return true;
+	fs->cur_req = NULL;
+	return false;
 }
 
 static void swim3_select(struct floppy_state *fs, int sel)
@@ -303,50 +308,53 @@ static int swim3_readbit(struct floppy_s
 	return (stat & DATA) == 0;
 }
 
-static void do_fd_request(struct request_queue * q)
-{
-	int i;
-
-	for(i=0; i<floppy_count; i++) {
-		struct floppy_state *fs = &floppy_states[i];
-		if (fs->mdev->media_bay &&
-		    check_media_bay(fs->mdev->media_bay) != MB_FD)
-			continue;
-		start_request(fs);
-	}
-}
-
 static void start_request(struct floppy_state *fs)
 {
 	struct request *req;
 	unsigned long x;
 
+	swim3_dbg("start request, initial state=%d\n", fs->state);
+
 	if (fs->state == idle && fs->wanted) {
 		fs->state = available;
 		wake_up(&fs->wait);
 		return;
 	}
 	while (fs->state == idle) {
-		if (!fd_req) {
-			fd_req = blk_fetch_request(swim3_queue);
-			if (!fd_req)
+		swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req);
+		if (!fs->cur_req) {
+			fs->cur_req = blk_fetch_request(disks[fs->index]->queue);
+			swim3_dbg("  fetched request %p\n", fs->cur_req);
+			if (!fs->cur_req)
 				break;
 		}
-		req = fd_req;
-#if 0
-		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
-		       req->rq_disk->disk_name, req->cmd,
-		       (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
-		printk("           errors=%d current_nr_sectors=%u\n",
-		       req->errors, blk_rq_cur_sectors(req));
+		req = fs->cur_req;
+
+		if (fs->mdev->media_bay &&
+		    check_media_bay(fs->mdev->media_bay) != MB_FD) {
+			swim3_dbg("%s", "  media bay absent, dropping req\n");
+			swim3_end_request(fs, -ENODEV, 0);
+			continue;
+		}
+
+#if 0 /* This is really too verbose */
+		swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
+			  req->rq_disk->disk_name, req->cmd,
+			  (long)blk_rq_pos(req), blk_rq_sectors(req),
+			  req->buffer);
+		swim3_dbg("           errors=%d current_nr_sectors=%u\n",
+			  req->errors, blk_rq_cur_sectors(req));
 #endif
 
 		if (blk_rq_pos(req) >= fs->total_secs) {
-			swim3_end_request_cur(-EIO);
+			swim3_dbg("  pos out of bounds (%ld, max is %ld)\n",
+				  (long)blk_rq_pos(req), (long)fs->total_secs);
+			swim3_end_request(fs, -EIO, 0);
 			continue;
 		}
 		if (fs->ejected) {
-			swim3_end_request_cur(-EIO);
+			swim3_dbg("%s", "  disk ejected\n");
+			swim3_end_request(fs, -EIO, 0);
 			continue;
 		}
 
@@ -354,7 +362,8 @@ static void start_request(struct floppy_
 			if (fs->write_prot < 0)
 				fs->write_prot = swim3_readbit(fs, WRITE_PROT);
 			if (fs->write_prot) {
-				swim3_end_request_cur(-EIO);
+				swim3_dbg("%s", "  try to write, disk write protected\n");
+				swim3_end_request(fs, -EIO, 0);
 				continue;
 			}
 		}
@@ -369,7 +378,6 @@ static void start_request(struct floppy_
 		x = ((long)blk_rq_pos(req)) % fs->secpercyl;
 		fs->head = x / fs->secpertrack;
 		fs->req_sector = x % fs->secpertrack + 1;
-		fd_req = req;
 		fs->state = do_transfer;
 		fs->retries = 0;
 
@@ -377,12 +385,14 @@ static void start_request(struct floppy_
 	}
 }
 
+static void do_fd_request(struct request_queue * q)
+{
+	start_request(q->queuedata);
+}
+
 static void set_timeout(struct floppy_state *fs, int nticks,
 			void (*proc)(unsigned long))
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&fs->lock, flags);
 	if (fs->timeout_pending)
 		del_timer(&fs->timeout);
 	fs->timeout.expires = jiffies + nticks;
@@ -390,7 +400,6 @@ static void set_timeout(struct floppy_st
 	fs->timeout.data = (unsigned long) fs;
 	add_timer(&fs->timeout);
 	fs->timeout_pending = 1;
-	spin_unlock_irqrestore(&fs->lock, flags);
 }
 
 static inline void scan_track(struct floppy_state *fs)
@@ -442,40 +451,45 @@ static inline void setup_transfer(struct
 	struct swim3 __iomem *sw = fs->swim3;
 	struct dbdma_cmd *cp = fs->dma_cmd;
 	struct dbdma_regs __iomem *dr = fs->dma;
+	struct request *req = fs->cur_req;
 
-	if (blk_rq_cur_sectors(fd_req) <= 0) {
-		printk(KERN_ERR "swim3: transfer 0 sectors?\n");
+	if (blk_rq_cur_sectors(req) <= 0) {
+		swim3_warn("%s", "Transfer 0 sectors ?\n");
 		return;
 	}
-	if (rq_data_dir(fd_req) == WRITE)
+	if (rq_data_dir(req) == WRITE)
 		n = 1;
 	else {
 		n = fs->secpertrack - fs->req_sector + 1;
-		if (n > blk_rq_cur_sectors(fd_req))
-			n = blk_rq_cur_sectors(fd_req);
+		if (n > blk_rq_cur_sectors(req))
+			n = blk_rq_cur_sectors(req);
 	}
+
+	swim3_dbg("  setup xfer at sect %d (of %d) head %d for %d\n",
+		  fs->req_sector, fs->secpertrack, fs->head, n);
+
 	fs->scount = n;
 	swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0);
 	out_8(&sw->sector, fs->req_sector);
 	out_8(&sw->nsect, n);
 	out_8(&sw->gap3, 0);
 	out_le32(&dr->cmdptr, virt_to_bus(cp));
-	if (rq_data_dir(fd_req) == WRITE) {
+	if (rq_data_dir(req) == WRITE) {
 		/* Set up 3 dma commands: write preamble, data, postamble */
 		init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble));
 		++cp;
-		init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512);
+		init_dma(cp, OUTPUT_MORE, req->buffer, 512);
 		++cp;
 		init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble));
 	} else {
-		init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512);
+		init_dma(cp, INPUT_LAST, req->buffer, n * 512);
 	}
 	++cp;
 	out_le16(&cp->command, DBDMA_STOP);
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
 	in_8(&sw->error);
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
-	if (rq_data_dir(fd_req) == WRITE)
+	if (rq_data_dir(req) == WRITE)
 		out_8(&sw->control_bis, WRITE_SECTORS);
 	in_8(&sw->intr);
 	out_le32(&dr->control, (RUN << 16) | RUN);
@@ -488,12 +502,16 @@ static inline void setup_transfer(struct
 static void act(struct floppy_state *fs)
 {
 	for (;;) {
+		swim3_dbg("  act loop, state=%d, req_cyl=%d, cur_cyl=%d\n",
+			  fs->state, fs->req_cyl, fs->cur_cyl);
+
 		switch (fs->state) {
 		case idle:
 			return;		/* XXX shouldn't get here */
 
 		case locating:
 			if (swim3_readbit(fs, TRACK_ZERO)) {
+				swim3_dbg("%s", "    locate track 0\n");
 				fs->cur_cyl = 0;
 				if (fs->req_cyl == 0)
 					fs->state = do_transfer;
@@ -511,7 +529,7 @@ static void act(struct floppy_state *fs)
 				break;
 			}
 			if (fs->req_cyl == fs->cur_cyl) {
-				printk("whoops, seeking 0\n");
+				swim3_warn("%s", "Whoops, seeking 0\n");
 				fs->state = do_transfer;
 				break;
 			}
@@ -527,7 +545,9 @@ static void act(struct floppy_state *fs)
 		case do_transfer:
 			if (fs->cur_cyl != fs->req_cyl) {
 				if (fs->retries > 5) {
-					swim3_end_request_cur(-EIO);
+					swim3_err("Wrong cylinder in transfer, want: %d got %d\n",
+						  fs->req_cyl, fs->cur_cyl);
+					swim3_end_request(fs, -EIO, 0);
 					fs->state = idle;
 					return;
 				}
@@ -542,7 +562,7 @@ static void act(struct floppy_state *fs)
 			return;
 
 		default:
-			printk(KERN_ERR"swim3: unknown state %d\n", fs->state);
+			swim3_err("Unknown state %d\n", fs->state);
 			return;
 		}
 	}
@@ -552,59 +572,75 @@ static void scan_timeout(unsigned long d
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
+
+	swim3_dbg("* scan timeout, state=%d\n", fs->state);
 
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
 	fs->cur_cyl = -1;
 	if (fs->retries > 5) {
-		swim3_end_request_cur(-EIO);
+		swim3_end_request(fs, -EIO, 0);
 		fs->state = idle;
 		start_request(fs);
 	} else {
 		fs->state = jogging;
 		act(fs);
 	}
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void seek_timeout(unsigned long data)
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
 
+	swim3_dbg("* seek timeout, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_8(&sw->control_bic, DO_SEEK);
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
-	printk(KERN_ERR "swim3: seek timeout\n");
-	swim3_end_request_cur(-EIO);
+	swim3_err("%s", "Seek timeout\n");
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void settle_timeout(unsigned long data)
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
+
+	swim3_dbg("* settle timeout, state=%d\n", fs->state);
 
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	if (swim3_readbit(fs, SEEK_COMPLETE)) {
 		out_8(&sw->select, RELAX);
 		fs->state = locating;
 		act(fs);
-		return;
+		goto unlock;
 	}
 	out_8(&sw->select, RELAX);
 	if (fs->settle_time < 2*HZ) {
 		++fs->settle_time;
 		set_timeout(fs, 1, settle_timeout);
-		return;
+		goto unlock;
 	}
-	printk(KERN_ERR "swim3: seek settle timeout\n");
-	swim3_end_request_cur(-EIO);
+	swim3_err("%s", "Seek settle timeout\n");
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+ unlock:
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void xfer_timeout(unsigned long data)
@@ -612,8 +648,12 @@ static void xfer_timeout(unsigned long d
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
 	struct dbdma_regs __iomem *dr = fs->dma;
+	unsigned long flags;
 	int n;
 
+	swim3_dbg("* xfer timeout, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_le32(&dr->control, RUN << 16);
 	/* We must wait a bit for dbdma to stop */
@@ -622,12 +662,13 @@ static void xfer_timeout(unsigned long d
 	out_8(&sw->intr_enable, 0);
 	out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
 	out_8(&sw->select, RELAX);
-	printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
-	       (rq_data_dir(fd_req)==WRITE? "writ": "read"),
-	       (long)blk_rq_pos(fd_req));
-	swim3_end_request_cur(-EIO);
+	swim3_err("Timeout %sing sector %ld\n",
+	       (rq_data_dir(fs->cur_req)==WRITE? "writ": "read"),
+	       (long)blk_rq_pos(fs->cur_req));
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static irqreturn_t swim3_interrupt(int irq, void *dev_id)
@@ -638,12 +679,17 @@ static irqreturn_t swim3_interrupt(int i
 	int stat, resid;
 	struct dbdma_regs __iomem *dr;
 	struct dbdma_cmd *cp;
+	unsigned long flags;
+	struct request *req = fs->cur_req;
 
+	swim3_dbg("* interrupt, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	intr = in_8(&sw->intr);
 	err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
 	if ((intr & ERROR_INTR) && fs->state != do_transfer)
-		printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
-		       fs->state, rq_data_dir(fd_req), intr, err);
+		swim3_err("Non-transfer error interrupt: state=%d, dir=%x, intr=%x, err=%x\n",
+			  fs->state, rq_data_dir(req), intr, err);
 	switch (fs->state) {
 	case locating:
 		if (intr & SEEN_SECTOR) {
@@ -653,10 +699,10 @@ static irqreturn_t swim3_interrupt(int i
 			del_timer(&fs->timeout);
 			fs->timeout_pending = 0;
 			if (sw->ctrack == 0xff) {
-				printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
+				swim3_err("%s", "Seen sector but cyl=ff?\n");
 				fs->cur_cyl = -1;
 				if (fs->retries > 5) {
-					swim3_end_request_cur(-EIO);
+					swim3_end_request(fs, -EIO, 0);
 					fs->state = idle;
 					start_request(fs);
 				} else {
@@ -668,8 +714,8 @@ static irqreturn_t swim3_interrupt(int i
 			fs->cur_cyl = sw->ctrack;
 			fs->cur_sector = sw->csect;
 			if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl)
-				printk(KERN_ERR "swim3: expected cyl %d, got %d\n",
-				       fs->expect_cyl, fs->cur_cyl);
+				swim3_err("Expected cyl %d, got %d\n",
+					  fs->expect_cyl, fs->cur_cyl);
 			fs->state = do_transfer;
 			act(fs);
 		}
@@ -704,7 +750,7 @@ static irqreturn_t swim3_interrupt(int i
 		fs->timeout_pending = 0;
 		dr = fs->dma;
 		cp = fs->dma_cmd;
-		if (rq_data_dir(fd_req) == WRITE)
+		if (rq_data_dir(req) == WRITE)
 			++cp;
 		/*
 		 * Check that the main data transfer has finished.
@@ -729,31 +775,32 @@ static irqreturn_t swim3_interrupt(int i
 		if (intr & ERROR_INTR) {
 			n = fs->scount - 1 - resid / 512;
 			if (n > 0) {
-				blk_update_request(fd_req, 0, n << 9);
+				blk_update_request(req, 0, n << 9);
 				fs->req_sector += n;
 			}
 			if (fs->retries < 5) {
 				++fs->retries;
 				act(fs);
 			} else {
-				printk("swim3: error %sing block %ld (err=%x)\n",
-				       rq_data_dir(fd_req) == WRITE? "writ": "read",
-				       (long)blk_rq_pos(fd_req), err);
-				swim3_end_request_cur(-EIO);
+				swim3_err("Error %sing block %ld (err=%x)\n",
+				       rq_data_dir(req) == WRITE? "writ": "read",
+				       (long)blk_rq_pos(req), err);
+				swim3_end_request(fs, -EIO, 0);
 				fs->state = idle;
 			}
 		} else {
 			if ((stat & ACTIVE) == 0 || resid != 0) {
 				/* musta been an error */
-				printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
-				printk(KERN_ERR "  state=%d, dir=%x, intr=%x, err=%x\n",
-				       fs->state, rq_data_dir(fd_req), intr, err);
-				swim3_end_request_cur(-EIO);
+				swim3_err("fd dma error: stat=%x resid=%d\n", stat, resid);
+				swim3_err("  state=%d, dir=%x, intr=%x, err=%x\n",
+					  fs->state, rq_data_dir(req), intr, err);
+				swim3_end_request(fs, -EIO, 0);
 				fs->state = idle;
 				start_request(fs);
 				break;
 			}
-			if (swim3_end_request(0, fs->scount << 9)) {
+			fs->retries = 0;
+			if (swim3_end_request(fs, 0, fs->scount << 9)) {
 				fs->req_sector += fs->scount;
 				if (fs->req_sector > fs->secpertrack) {
 					fs->req_sector -= fs->secpertrack;
@@ -770,8 +817,9 @@ static irqreturn_t swim3_interrupt(int i
 			start_request(fs);
 		break;
 	default:
-		printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state);
+		swim3_err("Don't know what to do in state %d\n", fs->state);
 	}
+	spin_unlock_irqrestore(&swim3_lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -781,26 +829,31 @@ static void fd_dma_interrupt(int irq, vo
 }
 */
 
+/* Called under the mutex to grab exclusive access to a drive */
 static int grab_drive(struct floppy_state *fs, enum swim_state state,
 		      int interruptible)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&fs->lock, flags);
-	if (fs->state != idle) {
+	swim3_dbg("%s", "-> grab drive\n");
+
+	spin_lock_irqsave(&swim3_lock, flags);
+	if (fs->state != idle && fs->state != available) {
 		++fs->wanted;
 		while (fs->state != available) {
+			spin_unlock_irqrestore(&swim3_lock, flags);
 			if (interruptible && signal_pending(current)) {
 				--fs->wanted;
-				spin_unlock_irqrestore(&fs->lock, flags);
 				return -EINTR;
 			}
 			interruptible_sleep_on(&fs->wait);
+			spin_lock_irqsave(&swim3_lock, flags);
 		}
 		--fs->wanted;
 	}
 	fs->state = state;
-	spin_unlock_irqrestore(&fs->lock, flags);
+	spin_unlock_irqrestore(&swim3_lock, flags);
+
 	return 0;
 }
 
@@ -808,10 +861,12 @@ static void release_drive(struct floppy_
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&fs->lock, flags);
+	swim3_dbg("%s", "-> release drive\n");
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->state = idle;
 	start_request(fs);
-	spin_unlock_irqrestore(&fs->lock, flags);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static int fd_eject(struct floppy_state *fs)
@@ -966,6 +1021,7 @@ static int floppy_release(struct gendisk
 {
 	struct floppy_state *fs = disk->private_data;
 	struct swim3 __iomem *sw = fs->swim3;
+
 	mutex_lock(&swim3_mutex);
 	if (fs->ref_count > 0 && --fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
@@ -1031,30 +1087,48 @@ static const struct block_device_operati
 	.revalidate_disk= floppy_revalidate,
 };
 
+static void swim3_mb_event(struct macio_dev* mdev, int mb_state)
+{
+	struct floppy_state *fs = macio_get_drvdata(mdev);
+	struct swim3 __iomem *sw = fs->swim3;
+
+	if (!fs)
+		return;
+	if (mb_state != MB_FD)
+		return;
+
+	/* Clear state */
+	out_8(&sw->intr_enable, 0);
+	in_8(&sw->intr);
+	in_8(&sw->error);
+}
+
 static int swim3_add_device(struct macio_dev *mdev, int index)
 {
 	struct device_node *swim = mdev->ofdev.dev.of_node;
 	struct floppy_state *fs = &floppy_states[index];
 	int rc = -EBUSY;
 
+	/* Do this first for message macros */
+	memset(fs, 0, sizeof(*fs));
+	fs->mdev = mdev;
+	fs->index = index;
+
 	/* Check & Request resources */
 	if (macio_resource_count(mdev) < 2) {
-		printk(KERN_WARNING "ifd%d: no address for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "No address in device-tree\n");
 		return -ENXIO;
 	}
-	if (macio_irq_count(mdev) < 2) {
-		printk(KERN_WARNING "fd%d: no intrs for device %s\n",
-			index, swim->full_name);
+	if (macio_irq_count(mdev) < 1) {
+		swim3_err("%s", "No interrupt in device-tree\n");
+		return -ENXIO;
 	}
 	if (macio_request_resource(mdev, 0, "swim3 (mmio)")) {
-		printk(KERN_ERR "fd%d: can't request mmio resource for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Can't request mmio resource\n");
 		return -EBUSY;
 	}
 	if (macio_request_resource(mdev, 1, "swim3 (dma)")) {
-		printk(KERN_ERR "fd%d: can't request dma resource for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Can't request dma resource\n");
 		macio_release_resource(mdev, 0);
 		return -EBUSY;
 	}
@@ -1063,22 +1137,18 @@ static int swim3_add_device(struct macio
 	if (mdev->media_bay == NULL)
 		pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1);
 	
-	memset(fs, 0, sizeof(*fs));
-	spin_lock_init(&fs->lock);
 	fs->state = idle;
 	fs->swim3 = (struct swim3 __iomem *)
 		ioremap(macio_resource_start(mdev, 0), 0x200);
 	if (fs->swim3 == NULL) {
-		printk("fd%d: couldn't map registers for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Couldn't map mmio registers\n");
 		rc = -ENOMEM;
 		goto out_release;
 	}
 	fs->dma = (struct dbdma_regs __iomem *)
 		ioremap(macio_resource_start(mdev, 1), 0x200);
 	if (fs->dma == NULL) {
-		printk("fd%d: couldn't map DMA for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Couldn't map dma registers\n");
 		iounmap(fs->swim3);
 		rc = -ENOMEM;
 		goto out_release;
@@ -1090,31 +1160,25 @@ static int swim3_add_device(struct macio
 	fs->secpercyl = 36;
 	fs->secpertrack = 18;
 	fs->total_secs = 2880;
-	fs->mdev = mdev;
 	init_waitqueue_head(&fs->wait);
 
 	fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
 	memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
 	st_le16(&fs->dma_cmd[1].command, DBDMA_STOP);
 
+	if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD)
+		swim3_mb_event(mdev, MB_FD);
+
 	if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {
-		printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n",
-		       index, fs->swim3_intr, swim->full_name);
+		swim3_err("%s", "Couldn't request interrupt\n");
 		pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0);
 		goto out_unmap;
 		return -EBUSY;
 	}
-/*
-	if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {
-		printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",
-		       fs->dma_intr);
-		return -EBUSY;
-	}
-*/
 
 	init_timer(&fs->timeout);
 
-	printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
+	swim3_info("SWIM3 floppy controller %s\n",
 		mdev->media_bay ? "in media bay" : "");
 
 	return 0;
@@ -1132,41 +1196,42 @@ static int swim3_add_device(struct macio
 
 static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match)
 {
-	int i, rc;
 	struct gendisk *disk;
+	int index, rc;
+
+	index = floppy_count++;
+	if (index >= MAX_FLOPPIES)
+		return -ENXIO;
 
 	/* Add the drive */
-	rc = swim3_add_device(mdev, floppy_count);
+	rc = swim3_add_device(mdev, index);
 	if (rc)
 		return rc;
+	/* Now register that disk. Same comment about failure handling */
+	disk = disks[index] = alloc_disk(1);
+	if (disk == NULL)
+		return -ENOMEM;
+	disk->queue = blk_init_queue(do_fd_request, &swim3_lock);
+	if (disk->queue == NULL) {
+		put_disk(disk);
+		return -ENOMEM;
+	}
+	disk->queue->queuedata = &floppy_states[index];
 
-	/* Now create the queue if not there yet */
-	if (swim3_queue == NULL) {
+	if (index == 0) {
 		/* If we failed, there isn't much we can do as the driver is still
 		 * too dumb to remove the device, just bail out
 		 */
 		if (register_blkdev(FLOPPY_MAJOR, "fd"))
 			return 0;
-		swim3_queue = blk_init_queue(do_fd_request, &swim3_lock);
-		if (swim3_queue == NULL) {
-			unregister_blkdev(FLOPPY_MAJOR, "fd");
-			return 0;
-		}
 	}
 
-	/* Now register that disk. Same comment about failure handling */
-	i = floppy_count++;
-	disk = disks[i] = alloc_disk(1);
-	if (disk == NULL)
-		return 0;
-
 	disk->major = FLOPPY_MAJOR;
-	disk->first_minor = i;
+	disk->first_minor = index;
 	disk->fops = &floppy_fops;
-	disk->private_data = &floppy_states[i];
-	disk->queue = swim3_queue;
+	disk->private_data = &floppy_states[index];
 	disk->flags |= GENHD_FL_REMOVABLE;
-	sprintf(disk->disk_name, "fd%d", i);
+	sprintf(disk->disk_name, "fd%d", index);
 	set_capacity(disk, 2880);
 	add_disk(disk);
 
@@ -1194,6 +1259,9 @@ static struct macio_driver swim3_driver
 		.of_match_table	= swim3_match,
 	},
 	.probe		= swim3_attach,
+#ifdef CONFIG_PMAC_MEDIABAY
+	.mediabay_event	= swim3_mb_event,
+#endif
 #if 0
 	.suspend	= swim3_suspend,
 	.resume		= swim3_resume,
diff -druNp linux-libre-3.1-gnu1/drivers/block/umem.c linux-libre-3.2-gnu1/drivers/block/umem.c
--- linux-libre-3.1-gnu1/drivers/block/umem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/umem.c	2012-01-04 18:55:44.000000000 -0500
@@ -513,7 +513,7 @@ static void process_page(unsigned long d
 	}
 }
 
-static int mm_make_request(struct request_queue *q, struct bio *bio)
+static void mm_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct cardinfo *card = q->queuedata;
 	pr_debug("mm_make_request %llu %u\n",
@@ -525,7 +525,7 @@ static int mm_make_request(struct reques
 	card->biotail = &bio->bi_next;
 	spin_unlock_irq(&card->lock);
 
-	return 0;
+	return;
 }
 
 static irqreturn_t mm_interrupt(int irq, void *__card)
diff -druNp linux-libre-3.1-gnu1/drivers/block/virtio_blk.c linux-libre-3.2-gnu1/drivers/block/virtio_blk.c
--- linux-libre-3.1-gnu1/drivers/block/virtio_blk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/virtio_blk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,15 +3,19 @@
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/module.h>
 #include <linux/virtio.h>
 #include <linux/virtio_blk.h>
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 #include <scsi/scsi_cmnd.h>
+#include <linux/idr.h>
 
 #define PART_BITS 4
 
-static int major, index;
+static int major;
+static DEFINE_IDA(vd_index_ida);
+
 struct workqueue_struct *virtblk_wq;
 
 struct virtio_blk
@@ -35,6 +39,9 @@ struct virtio_blk
 	/* What host tells us, plus 2 for header & tailer. */
 	unsigned int sg_elems;
 
+	/* Ida index - used to track minor number allocations. */
+	int index;
+
 	/* Scatterlist: can be too big for stack. */
 	struct scatterlist sg[/*sg_elems*/];
 };
@@ -276,6 +283,11 @@ static int index_to_minor(int index)
 	return index << PART_BITS;
 }
 
+static int minor_to_index(int minor)
+{
+	return minor >> PART_BITS;
+}
+
 static ssize_t virtblk_serial_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -341,14 +353,17 @@ static int __devinit virtblk_probe(struc
 {
 	struct virtio_blk *vblk;
 	struct request_queue *q;
-	int err;
+	int err, index;
 	u64 cap;
 	u32 v, blk_size, sg_elems, opt_io_size;
 	u16 min_io_size;
 	u8 physical_block_exp, alignment_offset;
 
-	if (index_to_minor(index) >= 1 << MINORBITS)
-		return -ENOSPC;
+	err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
+			     GFP_KERNEL);
+	if (err < 0)
+		goto out;
+	index = err;
 
 	/* We need to know how many segments before we allocate. */
 	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
@@ -365,7 +380,7 @@ static int __devinit virtblk_probe(struc
 				    sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL);
 	if (!vblk) {
 		err = -ENOMEM;
-		goto out;
+		goto out_free_index;
 	}
 
 	INIT_LIST_HEAD(&vblk->reqs);
@@ -421,7 +436,7 @@ static int __devinit virtblk_probe(struc
 	vblk->disk->private_data = vblk;
 	vblk->disk->fops = &virtblk_fops;
 	vblk->disk->driverfs_dev = &vdev->dev;
-	index++;
+	vblk->index = index;
 
 	/* configure queue flush support */
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
@@ -516,6 +531,8 @@ out_free_vq:
 	vdev->config->del_vqs(vdev);
 out_free_vblk:
 	kfree(vblk);
+out_free_index:
+	ida_simple_remove(&vd_index_ida, index);
 out:
 	return err;
 }
@@ -523,6 +540,7 @@ out:
 static void __devexit virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
+	int index = vblk->index;
 
 	flush_work(&vblk->config_work);
 
@@ -538,6 +556,7 @@ static void __devexit virtblk_remove(str
 	mempool_destroy(vblk->pool);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk);
+	ida_simple_remove(&vd_index_ida, index);
 }
 
 static const struct virtio_device_id id_table[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/block/xen-blkback/blkback.c linux-libre-3.2-gnu1/drivers/block/xen-blkback/blkback.c
--- linux-libre-3.1-gnu1/drivers/block/xen-blkback/blkback.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/xen-blkback/blkback.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
+#include <linux/loop.h>
+#include <linux/falloc.h>
+#include <linux/fs.h>
 
 #include <xen/events.h>
 #include <xen/page.h>
@@ -258,13 +261,16 @@ irqreturn_t xen_blkif_be_int(int irq, vo
 
 static void print_stats(struct xen_blkif *blkif)
 {
-	pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d\n",
+	pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d"
+		 "  |  ds %4d\n",
 		 current->comm, blkif->st_oo_req,
-		 blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req);
+		 blkif->st_rd_req, blkif->st_wr_req,
+		 blkif->st_f_req, blkif->st_ds_req);
 	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
 	blkif->st_rd_req = 0;
 	blkif->st_wr_req = 0;
 	blkif->st_oo_req = 0;
+	blkif->st_ds_req = 0;
 }
 
 int xen_blkif_schedule(void *arg)
@@ -396,7 +402,7 @@ static int xen_blkbk_map(struct blkif_re
 			continue;
 
 		ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
-			blkbk->pending_page(pending_req, i), false);
+			blkbk->pending_page(pending_req, i), NULL);
 		if (ret) {
 			pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
 				 (unsigned long)map[i].dev_bus_addr, ret);
@@ -410,6 +416,59 @@ static int xen_blkbk_map(struct blkif_re
 	return ret;
 }
 
+static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+{
+	int err = 0;
+	int status = BLKIF_RSP_OKAY;
+	struct block_device *bdev = blkif->vbd.bdev;
+
+	if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
+		/* just forward the discard request */
+		err = blkdev_issue_discard(bdev,
+				req->u.discard.sector_number,
+				req->u.discard.nr_sectors,
+				GFP_KERNEL, 0);
+	else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+		/* punch a hole in the backing file */
+		struct loop_device *lo = bdev->bd_disk->private_data;
+		struct file *file = lo->lo_backing_file;
+
+		if (file->f_op->fallocate)
+			err = file->f_op->fallocate(file,
+				FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+				req->u.discard.sector_number << 9,
+				req->u.discard.nr_sectors << 9);
+		else
+			err = -EOPNOTSUPP;
+	} else
+		err = -EOPNOTSUPP;
+
+	if (err == -EOPNOTSUPP) {
+		pr_debug(DRV_PFX "discard op failed, not supported\n");
+		status = BLKIF_RSP_EOPNOTSUPP;
+	} else if (err)
+		status = BLKIF_RSP_ERROR;
+
+	make_response(blkif, req->id, req->operation, status);
+}
+
+static void xen_blk_drain_io(struct xen_blkif *blkif)
+{
+	atomic_set(&blkif->drain, 1);
+	do {
+		/* The initial value is one, and one refcnt taken at the
+		 * start of the xen_blkif_schedule thread. */
+		if (atomic_read(&blkif->refcnt) <= 2)
+			break;
+		wait_for_completion_interruptible_timeout(
+				&blkif->drain_complete, HZ);
+
+		if (!atomic_read(&blkif->drain))
+			break;
+	} while (!kthread_should_stop());
+	atomic_set(&blkif->drain, 0);
+}
+
 /*
  * Completion callback on the bio's. Called as bh->b_end_io()
  */
@@ -422,6 +481,11 @@ static void __end_block_io_op(struct pen
 		pr_debug(DRV_PFX "flush diskcache op failed, not supported\n");
 		xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
 		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
+	} else if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
+		    (error == -EOPNOTSUPP)) {
+		pr_debug(DRV_PFX "write barrier op failed, not supported\n");
+		xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0);
+		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
 	} else if (error) {
 		pr_debug(DRV_PFX "Buffer not up-to-date at end of operation,"
 			 " error=%d\n", error);
@@ -438,6 +502,10 @@ static void __end_block_io_op(struct pen
 		make_response(pending_req->blkif, pending_req->id,
 			      pending_req->operation, pending_req->status);
 		xen_blkif_put(pending_req->blkif);
+		if (atomic_read(&pending_req->blkif->refcnt) <= 2) {
+			if (atomic_read(&pending_req->blkif->drain))
+				complete(&pending_req->blkif->drain_complete);
+		}
 		free_req(pending_req);
 	}
 }
@@ -532,7 +600,6 @@ do_block_io_op(struct xen_blkif *blkif)
 
 	return more_to_do;
 }
-
 /*
  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
  * and call the 'submit_bio' to pass it to the underlying storage.
@@ -549,6 +616,7 @@ static int dispatch_rw_block_io(struct x
 	int i, nbio = 0;
 	int operation;
 	struct blk_plug plug;
+	bool drain = false;
 
 	switch (req->operation) {
 	case BLKIF_OP_READ:
@@ -559,11 +627,16 @@ static int dispatch_rw_block_io(struct x
 		blkif->st_wr_req++;
 		operation = WRITE_ODIRECT;
 		break;
+	case BLKIF_OP_WRITE_BARRIER:
+		drain = true;
 	case BLKIF_OP_FLUSH_DISKCACHE:
 		blkif->st_f_req++;
 		operation = WRITE_FLUSH;
 		break;
-	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_DISCARD:
+		blkif->st_ds_req++;
+		operation = REQ_DISCARD;
+		break;
 	default:
 		operation = 0; /* make gcc happy */
 		goto fail_response;
@@ -572,7 +645,8 @@ static int dispatch_rw_block_io(struct x
 
 	/* Check that the number of segments is sane. */
 	nseg = req->nr_segments;
-	if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
+	if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
+				operation != REQ_DISCARD) ||
 	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
 		pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
 			 nseg);
@@ -621,16 +695,25 @@ static int dispatch_rw_block_io(struct x
 		}
 	}
 
+	/* Wait on all outstanding I/O's and once that has been completed
+	 * issue the WRITE_FLUSH.
+	 */
+	if (drain)
+		xen_blk_drain_io(pending_req->blkif);
+
 	/*
 	 * If we have failed at this point, we need to undo the M2P override,
 	 * set gnttab_set_unmap_op on all of the grant references and perform
 	 * the hypercall to unmap the grants - that is all done in
 	 * xen_blkbk_unmap.
 	 */
-	if (xen_blkbk_map(req, pending_req, seg))
+	if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
 		goto fail_flush;
 
-	/* This corresponding xen_blkif_put is done in __end_block_io_op */
+	/*
+	 * This corresponding xen_blkif_put is done in __end_block_io_op, or
+	 * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
+	 */
 	xen_blkif_get(blkif);
 
 	for (i = 0; i < nseg; i++) {
@@ -654,18 +737,25 @@ static int dispatch_rw_block_io(struct x
 		preq.sector_number += seg[i].nsec;
 	}
 
-	/* This will be hit if the operation was a flush. */
+	/* This will be hit if the operation was a flush or discard. */
 	if (!bio) {
-		BUG_ON(operation != WRITE_FLUSH);
+		BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
 
-		bio = bio_alloc(GFP_KERNEL, 0);
-		if (unlikely(bio == NULL))
-			goto fail_put_bio;
+		if (operation == WRITE_FLUSH) {
+			bio = bio_alloc(GFP_KERNEL, 0);
+			if (unlikely(bio == NULL))
+				goto fail_put_bio;
 
-		biolist[nbio++] = bio;
-		bio->bi_bdev    = preq.bdev;
-		bio->bi_private = pending_req;
-		bio->bi_end_io  = end_block_io_op;
+			biolist[nbio++] = bio;
+			bio->bi_bdev    = preq.bdev;
+			bio->bi_private = pending_req;
+			bio->bi_end_io  = end_block_io_op;
+		} else if (operation == REQ_DISCARD) {
+			xen_blk_discard(blkif, req);
+			xen_blkif_put(blkif);
+			free_req(pending_req);
+			return 0;
+		}
 	}
 
 	/*
@@ -685,7 +775,7 @@ static int dispatch_rw_block_io(struct x
 
 	if (operation == READ)
 		blkif->st_rd_sect += preq.nr_sects;
-	else if (operation == WRITE || operation == WRITE_FLUSH)
+	else if (operation & WRITE)
 		blkif->st_wr_sect += preq.nr_sects;
 
 	return 0;
@@ -765,9 +855,9 @@ static int __init xen_blkif_init(void)
 
 	mmap_pages = xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
 
-	blkbk->pending_reqs          = kmalloc(sizeof(blkbk->pending_reqs[0]) *
+	blkbk->pending_reqs          = kzalloc(sizeof(blkbk->pending_reqs[0]) *
 					xen_blkif_reqs, GFP_KERNEL);
-	blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) *
+	blkbk->pending_grant_handles = kmalloc(sizeof(blkbk->pending_grant_handles[0]) *
 					mmap_pages, GFP_KERNEL);
 	blkbk->pending_pages         = kzalloc(sizeof(blkbk->pending_pages[0]) *
 					mmap_pages, GFP_KERNEL);
@@ -790,8 +880,6 @@ static int __init xen_blkif_init(void)
 	if (rc)
 		goto failed_init;
 
-	memset(blkbk->pending_reqs, 0, sizeof(blkbk->pending_reqs));
-
 	INIT_LIST_HEAD(&blkbk->pending_free);
 	spin_lock_init(&blkbk->pending_free_lock);
 	init_waitqueue_head(&blkbk->pending_free_wq);
diff -druNp linux-libre-3.1-gnu1/drivers/block/xen-blkback/common.h linux-libre-3.2-gnu1/drivers/block/xen-blkback/common.h
--- linux-libre-3.1-gnu1/drivers/block/xen-blkback/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/xen-blkback/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 #ifndef __XEN_BLKIF__BACKEND__COMMON_H__
 #define __XEN_BLKIF__BACKEND__COMMON_H__
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -63,13 +62,26 @@ struct blkif_common_response {
 
 /* i386 protocol version */
 #pragma pack(push, 4)
+
+struct blkif_x86_32_request_rw {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_32_request_discard {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	uint64_t nr_sectors;
+};
+
 struct blkif_x86_32_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
 	uint64_t       id;           /* private guest value, echoed in resp  */
-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	union {
+		struct blkif_x86_32_request_rw rw;
+		struct blkif_x86_32_request_discard discard;
+	} u;
 };
 struct blkif_x86_32_response {
 	uint64_t        id;              /* copied from request */
@@ -79,13 +91,26 @@ struct blkif_x86_32_response {
 #pragma pack(pop)
 
 /* x86_64 protocol version */
+
+struct blkif_x86_64_request_rw {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_64_request_discard {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	uint64_t nr_sectors;
+};
+
 struct blkif_x86_64_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
 	uint64_t       __attribute__((__aligned__(8))) id;
-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	union {
+		struct blkif_x86_64_request_rw rw;
+		struct blkif_x86_64_request_discard discard;
+	} u;
 };
 struct blkif_x86_64_response {
 	uint64_t       __attribute__((__aligned__(8))) id;
@@ -113,6 +138,11 @@ enum blkif_protocol {
 	BLKIF_PROTOCOL_X86_64 = 3,
 };
 
+enum blkif_backend_type {
+	BLKIF_BACKEND_PHY  = 1,
+	BLKIF_BACKEND_FILE = 2,
+};
+
 struct xen_vbd {
 	/* What the domain refers to this vbd as. */
 	blkif_vdev_t		handle;
@@ -138,8 +168,9 @@ struct xen_blkif {
 	unsigned int		irq;
 	/* Comms information. */
 	enum blkif_protocol	blk_protocol;
+	enum blkif_backend_type blk_backend_type;
 	union blkif_back_rings	blk_rings;
-	struct vm_struct	*blk_ring_area;
+	void			*blk_ring;
 	/* The VBD attached to this interface. */
 	struct xen_vbd		vbd;
 	/* Back pointer to the backend_info. */
@@ -149,6 +180,9 @@ struct xen_blkif {
 	atomic_t		refcnt;
 
 	wait_queue_head_t	wq;
+	/* for barrier (drain) requests */
+	struct completion	drain_complete;
+	atomic_t		drain;
 	/* One thread per one blkif. */
 	struct task_struct	*xenblkd;
 	unsigned int		waiting_reqs;
@@ -159,13 +193,11 @@ struct xen_blkif {
 	int			st_wr_req;
 	int			st_oo_req;
 	int			st_f_req;
+	int			st_ds_req;
 	int			st_rd_sect;
 	int			st_wr_sect;
 
 	wait_queue_head_t	waiting_to_free;
-
-	grant_handle_t		shmem_handle;
-	grant_ref_t		shmem_ref;
 };
 
 
@@ -182,7 +214,7 @@ struct xen_blkif {
 
 struct phys_req {
 	unsigned short		dev;
-	unsigned short		nr_sects;
+	blkif_sector_t		nr_sects;
 	struct block_device	*bdev;
 	blkif_sector_t		sector_number;
 };
@@ -196,6 +228,8 @@ int xen_blkif_schedule(void *arg);
 int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
 			      struct backend_info *be, int state);
 
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+		      struct backend_info *be, int state);
 struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
 
 static inline void blkif_get_x86_32_req(struct blkif_request *dst,
@@ -206,12 +240,25 @@ static inline void blkif_get_x86_32_req(
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
-	dst->u.rw.sector_number = src->sector_number;
-	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->u.rw.seg[i] = src->seg[i];
+	switch (src->operation) {
+	case BLKIF_OP_READ:
+	case BLKIF_OP_WRITE:
+	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_FLUSH_DISKCACHE:
+		dst->u.rw.sector_number = src->u.rw.sector_number;
+		barrier();
+		if (n > dst->nr_segments)
+			n = dst->nr_segments;
+		for (i = 0; i < n; i++)
+			dst->u.rw.seg[i] = src->u.rw.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		dst->u.discard.sector_number = src->u.discard.sector_number;
+		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+		break;
+	default:
+		break;
+	}
 }
 
 static inline void blkif_get_x86_64_req(struct blkif_request *dst,
@@ -222,12 +269,25 @@ static inline void blkif_get_x86_64_req(
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
-	dst->u.rw.sector_number = src->sector_number;
-	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->u.rw.seg[i] = src->seg[i];
+	switch (src->operation) {
+	case BLKIF_OP_READ:
+	case BLKIF_OP_WRITE:
+	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_FLUSH_DISKCACHE:
+		dst->u.rw.sector_number = src->u.rw.sector_number;
+		barrier();
+		if (n > dst->nr_segments)
+			n = dst->nr_segments;
+		for (i = 0; i < n; i++)
+			dst->u.rw.seg[i] = src->u.rw.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		dst->u.discard.sector_number = src->u.discard.sector_number;
+		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+		break;
+	default:
+		break;
+	}
 }
 
 #endif /* __XEN_BLKIF__BACKEND__COMMON_H__ */
diff -druNp linux-libre-3.1-gnu1/drivers/block/xen-blkback/xenbus.c linux-libre-3.2-gnu1/drivers/block/xen-blkback/xenbus.c
--- linux-libre-3.1-gnu1/drivers/block/xen-blkback/xenbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/xen-blkback/xenbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,44 +114,14 @@ static struct xen_blkif *xen_blkif_alloc
 	spin_lock_init(&blkif->blk_ring_lock);
 	atomic_set(&blkif->refcnt, 1);
 	init_waitqueue_head(&blkif->wq);
+	init_completion(&blkif->drain_complete);
+	atomic_set(&blkif->drain, 0);
 	blkif->st_print = jiffies;
 	init_waitqueue_head(&blkif->waiting_to_free);
 
 	return blkif;
 }
 
-static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page)
-{
-	struct gnttab_map_grant_ref op;
-
-	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
-			  GNTMAP_host_map, shared_page, blkif->domid);
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
-		BUG();
-
-	if (op.status) {
-		DPRINTK("Grant table operation failure !\n");
-		return op.status;
-	}
-
-	blkif->shmem_ref = shared_page;
-	blkif->shmem_handle = op.handle;
-
-	return 0;
-}
-
-static void unmap_frontend_page(struct xen_blkif *blkif)
-{
-	struct gnttab_unmap_grant_ref op;
-
-	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
-			    GNTMAP_host_map, blkif->shmem_handle);
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
-		BUG();
-}
-
 static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page,
 			 unsigned int evtchn)
 {
@@ -161,35 +131,29 @@ static int xen_blkif_map(struct xen_blki
 	if (blkif->irq)
 		return 0;
 
-	blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE);
-	if (!blkif->blk_ring_area)
-		return -ENOMEM;
-
-	err = map_frontend_page(blkif, shared_page);
-	if (err) {
-		free_vm_area(blkif->blk_ring_area);
+	err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring);
+	if (err < 0)
 		return err;
-	}
 
 	switch (blkif->blk_protocol) {
 	case BLKIF_PROTOCOL_NATIVE:
 	{
 		struct blkif_sring *sring;
-		sring = (struct blkif_sring *)blkif->blk_ring_area->addr;
+		sring = (struct blkif_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
 		break;
 	}
 	case BLKIF_PROTOCOL_X86_32:
 	{
 		struct blkif_x86_32_sring *sring_x86_32;
-		sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr;
+		sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
 		break;
 	}
 	case BLKIF_PROTOCOL_X86_64:
 	{
 		struct blkif_x86_64_sring *sring_x86_64;
-		sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr;
+		sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
 		break;
 	}
@@ -201,8 +165,7 @@ static int xen_blkif_map(struct xen_blki
 						    xen_blkif_be_int, 0,
 						    "blkif-backend", blkif);
 	if (err < 0) {
-		unmap_frontend_page(blkif);
-		free_vm_area(blkif->blk_ring_area);
+		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
 		blkif->blk_rings.common.sring = NULL;
 		return err;
 	}
@@ -228,8 +191,7 @@ static void xen_blkif_disconnect(struct
 	}
 
 	if (blkif->blk_rings.common.sring) {
-		unmap_frontend_page(blkif);
-		free_vm_area(blkif->blk_ring_area);
+		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
 		blkif->blk_rings.common.sring = NULL;
 	}
 }
@@ -272,6 +234,7 @@ VBD_SHOW(oo_req,  "%d\n", be->blkif->st_
 VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
 VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
 VBD_SHOW(f_req,  "%d\n", be->blkif->st_f_req);
+VBD_SHOW(ds_req,  "%d\n", be->blkif->st_ds_req);
 VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
 VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
 
@@ -280,6 +243,7 @@ static struct attribute *xen_vbdstat_att
 	&dev_attr_rd_req.attr,
 	&dev_attr_wr_req.attr,
 	&dev_attr_f_req.attr,
+	&dev_attr_ds_req.attr,
 	&dev_attr_rd_sect.attr,
 	&dev_attr_wr_sect.attr,
 	NULL
@@ -419,6 +383,73 @@ int xen_blkbk_flush_diskcache(struct xen
 	return err;
 }
 
+int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	struct xen_blkif *blkif = be->blkif;
+	char *type;
+	int err;
+	int state = 0;
+
+	type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
+	if (!IS_ERR(type)) {
+		if (strncmp(type, "file", 4) == 0) {
+			state = 1;
+			blkif->blk_backend_type = BLKIF_BACKEND_FILE;
+		}
+		if (strncmp(type, "phy", 3) == 0) {
+			struct block_device *bdev = be->blkif->vbd.bdev;
+			struct request_queue *q = bdev_get_queue(bdev);
+			if (blk_queue_discard(q)) {
+				err = xenbus_printf(xbt, dev->nodename,
+					"discard-granularity", "%u",
+					q->limits.discard_granularity);
+				if (err) {
+					xenbus_dev_fatal(dev, err,
+						"writing discard-granularity");
+					goto kfree;
+				}
+				err = xenbus_printf(xbt, dev->nodename,
+					"discard-alignment", "%u",
+					q->limits.discard_alignment);
+				if (err) {
+					xenbus_dev_fatal(dev, err,
+						"writing discard-alignment");
+					goto kfree;
+				}
+				state = 1;
+				blkif->blk_backend_type = BLKIF_BACKEND_PHY;
+			}
+		}
+	} else {
+		err = PTR_ERR(type);
+		xenbus_dev_fatal(dev, err, "reading type");
+		goto out;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-discard",
+			    "%d", state);
+	if (err)
+		xenbus_dev_fatal(dev, err, "writing feature-discard");
+kfree:
+	kfree(type);
+out:
+	return err;
+}
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+		      struct backend_info *be, int state)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+			    "%d", state);
+	if (err)
+		xenbus_dev_fatal(dev, err, "writing feature-barrier");
+
+	return err;
+}
+
 /*
  * Entry point to this code when a new device is created.  Allocate the basic
  * structures, and watch the store waiting for the hotplug scripts to tell us
@@ -650,6 +681,11 @@ again:
 	if (err)
 		goto abort;
 
+	err = xen_blkbk_discard(xbt, be);
+
+	/* If we can't advertise it is OK. */
+	err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
+
 	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
 			    (unsigned long long)vbd_sz(&be->blkif->vbd));
 	if (err) {
diff -druNp linux-libre-3.1-gnu1/drivers/block/xen-blkfront.c linux-libre-3.2-gnu1/drivers/block/xen-blkfront.c
--- linux-libre-3.1-gnu1/drivers/block/xen-blkfront.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/block/xen-blkfront.c	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,9 @@ struct blkfront_info
 	unsigned long shadow_free;
 	unsigned int feature_flush;
 	unsigned int flush_op;
+	unsigned int feature_discard;
+	unsigned int discard_granularity;
+	unsigned int discard_alignment;
 	int is_ready;
 };
 
@@ -302,29 +305,36 @@ static int blkif_queue_request(struct re
 		ring_req->operation = info->flush_op;
 	}
 
-	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
-	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+		/* id, sector_number and handle are set above. */
+		ring_req->operation = BLKIF_OP_DISCARD;
+		ring_req->nr_segments = 0;
+		ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+	} else {
+		ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+		BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-	for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
-		buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
-		fsect = sg->offset >> 9;
-		lsect = fsect + (sg->length >> 9) - 1;
-		/* install a grant reference. */
-		ref = gnttab_claim_grant_reference(&gref_head);
-		BUG_ON(ref == -ENOSPC);
+		for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+			buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
+			fsect = sg->offset >> 9;
+			lsect = fsect + (sg->length >> 9) - 1;
+			/* install a grant reference. */
+			ref = gnttab_claim_grant_reference(&gref_head);
+			BUG_ON(ref == -ENOSPC);
 
-		gnttab_grant_foreign_access_ref(
-				ref,
-				info->xbdev->otherend_id,
-				buffer_mfn,
-				rq_data_dir(req) );
+			gnttab_grant_foreign_access_ref(
+					ref,
+					info->xbdev->otherend_id,
+					buffer_mfn,
+					rq_data_dir(req));
 
-		info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
-		ring_req->u.rw.seg[i] =
-				(struct blkif_request_segment) {
-					.gref       = ref,
-					.first_sect = fsect,
-					.last_sect  = lsect };
+			info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+			ring_req->u.rw.seg[i] =
+					(struct blkif_request_segment) {
+						.gref       = ref,
+						.first_sect = fsect,
+						.last_sect  = lsect };
+		}
 	}
 
 	info->ring.req_prod_pvt++;
@@ -370,7 +380,9 @@ static void do_blkif_request(struct requ
 
 		blk_start_request(req);
 
-		if (req->cmd_type != REQ_TYPE_FS) {
+		if ((req->cmd_type != REQ_TYPE_FS) ||
+		    ((req->cmd_flags & (REQ_FLUSH | REQ_FUA)) &&
+		    !info->flush_op)) {
 			__blk_end_request_all(req, -EIO);
 			continue;
 		}
@@ -399,6 +411,7 @@ wait:
 static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
 {
 	struct request_queue *rq;
+	struct blkfront_info *info = gd->private_data;
 
 	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
 	if (rq == NULL)
@@ -406,6 +419,13 @@ static int xlvbd_init_blk_queue(struct g
 
 	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
+	if (info->feature_discard) {
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq);
+		blk_queue_max_discard_sectors(rq, get_capacity(gd));
+		rq->limits.discard_granularity = info->discard_granularity;
+		rq->limits.discard_alignment = info->discard_alignment;
+	}
+
 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
 	blk_queue_logical_block_size(rq, sector_size);
 	blk_queue_max_hw_sectors(rq, 512);
@@ -722,6 +742,17 @@ static irqreturn_t blkif_interrupt(int i
 
 		error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
 		switch (bret->operation) {
+		case BLKIF_OP_DISCARD:
+			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+				struct request_queue *rq = info->rq;
+				printk(KERN_WARNING "blkfront: %s: discard op failed\n",
+					   info->gd->disk_name);
+				error = -EOPNOTSUPP;
+				info->feature_discard = 0;
+				queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+			}
+			__blk_end_request_all(req, error);
+			break;
 		case BLKIF_OP_FLUSH_DISKCACHE:
 		case BLKIF_OP_WRITE_BARRIER:
 			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
@@ -1098,6 +1129,33 @@ blkfront_closing(struct blkfront_info *i
 	bdput(bdev);
 }
 
+static void blkfront_setup_discard(struct blkfront_info *info)
+{
+	int err;
+	char *type;
+	unsigned int discard_granularity;
+	unsigned int discard_alignment;
+
+	type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
+	if (IS_ERR(type))
+		return;
+
+	if (strncmp(type, "phy", 3) == 0) {
+		err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			"discard-granularity", "%u", &discard_granularity,
+			"discard-alignment", "%u", &discard_alignment,
+			NULL);
+		if (!err) {
+			info->feature_discard = 1;
+			info->discard_granularity = discard_granularity;
+			info->discard_alignment = discard_alignment;
+		}
+	} else if (strncmp(type, "file", 4) == 0)
+		info->feature_discard = 1;
+
+	kfree(type);
+}
+
 /*
  * Invoked when the backend is finally 'ready' (and has told produced
  * the details about the physical device - #sectors, size, etc).
@@ -1108,7 +1166,7 @@ static void blkfront_connect(struct blkf
 	unsigned long sector_size;
 	unsigned int binfo;
 	int err;
-	int barrier, flush;
+	int barrier, flush, discard;
 
 	switch (info->connected) {
 	case BLKIF_STATE_CONNECTED:
@@ -1178,7 +1236,14 @@ static void blkfront_connect(struct blkf
 		info->feature_flush = REQ_FLUSH;
 		info->flush_op = BLKIF_OP_FLUSH_DISKCACHE;
 	}
-		
+
+	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			    "feature-discard", "%d", &discard,
+			    NULL);
+
+	if (!err && discard)
+		blkfront_setup_discard(info);
+
 	err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
 	if (err) {
 		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
@@ -1385,6 +1450,8 @@ static struct xenbus_driver blkfront = {
 
 static int __init xlblk_init(void)
 {
+	int ret;
+
 	if (!xen_domain())
 		return -ENODEV;
 
@@ -1394,7 +1461,13 @@ static int __init xlblk_init(void)
 		return -ENODEV;
 	}
 
-	return xenbus_register_frontend(&blkfront);
+	ret = xenbus_register_frontend(&blkfront);
+	if (ret) {
+		unregister_blkdev(XENVBD_MAJOR, DEV_NAME);
+		return ret;
+	}
+
+	return 0;
 }
 module_init(xlblk_init);
 
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/ath3k.c linux-libre-3.2-gnu1/drivers/bluetooth/ath3k.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/ath3k.c	2013-05-02 01:42:23.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/ath3k.c	2013-05-01 23:49:25.000000000 -0400
@@ -105,7 +105,7 @@ static int ath3k_load_firmware(struct us
 
 	pipe = usb_sndctrlpipe(udev, 0);
 
-	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
 	if (!send_buf) {
 		BT_ERR("Can't allocate memory chunk for firmware");
 		return -ENOMEM;
@@ -176,7 +176,7 @@ static int ath3k_load_fwfile(struct usb_
 
 	count = firmware->size;
 
-	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
 	if (!send_buf) {
 		BT_ERR("Can't allocate memory chunk for firmware");
 		return -ENOMEM;
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/bcm203x.c linux-libre-3.2-gnu1/drivers/bluetooth/bcm203x.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/bcm203x.c	2013-05-02 01:42:26.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/bcm203x.c	2013-05-01 23:49:27.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -65,6 +66,7 @@ struct bcm203x_data {
 	unsigned long		state;
 
 	struct work_struct	work;
+	atomic_t		shutdown;
 
 	struct urb		*urb;
 	unsigned char		*buffer;
@@ -97,6 +99,7 @@ static void bcm203x_complete(struct urb
 
 		data->state = BCM203X_SELECT_MEMORY;
 
+		/* use workqueue to have a small delay */
 		schedule_work(&data->work);
 		break;
 
@@ -155,7 +158,10 @@ static void bcm203x_work(struct work_str
 	struct bcm203x_data *data =
 		container_of(work, struct bcm203x_data, work);
 
-	if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
+	if (atomic_read(&data->shutdown))
+		return;
+
+	if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)
 		BT_ERR("Can't submit URB");
 }
 
@@ -243,6 +249,7 @@ static int bcm203x_probe(struct usb_inte
 
 	usb_set_intfdata(intf, data);
 
+	/* use workqueue to have a small delay */
 	schedule_work(&data->work);
 
 	return 0;
@@ -254,6 +261,9 @@ static void bcm203x_disconnect(struct us
 
 	BT_DBG("intf %p", intf);
 
+	atomic_inc(&data->shutdown);
+	cancel_work_sync(&data->work);
+
 	usb_kill_urb(data->urb);
 
 	usb_set_intfdata(intf, NULL);
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/bfusb.c linux-libre-3.2-gnu1/drivers/bluetooth/bfusb.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/bfusb.c	2013-05-02 01:42:28.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/bfusb.c	2013-05-01 23:49:29.000000000 -0400
@@ -568,22 +568,23 @@ static int bfusb_load_firmware(struct bf
 
 	BT_INFO("BlueFRITZ! USB loading firmware");
 
+	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
+	if (!buf) {
+		BT_ERR("Can't allocate memory chunk for firmware");
+		return -ENOMEM;
+	}
+
 	pipe = usb_sndctrlpipe(data->udev, 0);
 
 	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
 		BT_ERR("Can't change to loading configuration");
+		kfree(buf);
 		return -EBUSY;
 	}
 
 	data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
-	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
-	if (!buf) {
-		BT_ERR("Can't allocate memory chunk for firmware");
-		return -ENOMEM;
-	}
-
 	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
 	while (count) {
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/btmrvl_main.c linux-libre-3.2-gnu1/drivers/bluetooth/btmrvl_main.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/btmrvl_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/btmrvl_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * this warranty disclaimer.
  **/
 
+#include <linux/module.h>
+
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/btmrvl_sdio.c linux-libre-3.2-gnu1/drivers/bluetooth/btmrvl_sdio.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/btmrvl_sdio.c	2013-05-02 01:42:40.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/btmrvl_sdio.c	2013-05-01 23:49:33.000000000 -0400
@@ -23,6 +23,7 @@
 
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
+#include <linux/module.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -64,7 +65,7 @@ static const struct btmrvl_sdio_card_reg
 	.io_port_1 = 0x01,
 	.io_port_2 = 0x02,
 };
-static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
+static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
 	.cfg = 0x00,
 	.host_int_mask = 0x02,
 	.host_intstatus = 0x03,
@@ -81,7 +82,7 @@ static const struct btmrvl_sdio_card_reg
 	.io_port_2 = 0x7a,
 };
 
-static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
 	.helper		= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_8688,
 	.sd_blksz_fw_dl	= 64,
@@ -90,17 +91,27 @@ static const struct btmrvl_sdio_device b
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
 	.helper		= NULL,
 	.firmware	= "/*(DEBLOBBED)*/",
-	.reg		= &btmrvl_reg_8787,
+	.reg		= &btmrvl_reg_87xx,
+	.sd_blksz_fw_dl	= 256,
+};
+
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
+	.helper		= NULL,
+	.firmware	= "/*(DEBLOBBED)*/",
+	.reg		= &btmrvl_reg_87xx,
 	.sd_blksz_fw_dl	= 256,
 };
 
 static const struct sdio_device_id btmrvl_sdio_ids[] = {
 	/* Marvell SD8688 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
-			.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
+			.driver_data = (unsigned long) &btmrvl_sdio_sd8688 },
 	/* Marvell SD8787 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
 			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+	/* Marvell SD8797 Bluetooth device */
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
+			.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
 
 	{ }	/* Terminating entry */
 };
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/btusb.c linux-libre-3.2-gnu1/drivers/bluetooth/btusb.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/btusb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/btusb.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[
 	/* Generic Bluetooth USB device */
 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+	/* Broadcom SoftSailing reporting vendor specific */
+	{ USB_DEVICE(0x05ac, 0x21e1) },
+
 	/* Apple MacBookPro 7,1 */
 	{ USB_DEVICE(0x05ac, 0x8213) },
 
@@ -97,6 +100,9 @@ static struct usb_device_id btusb_table[
 	/* Canyon CN-BTU1 with HID interfaces */
 	{ USB_DEVICE(0x0c10, 0x0000) },
 
+	/* Broadcom BCM20702A0 */
+	{ USB_DEVICE(0x413c, 0x8197) },
+
 	{ }	/* Terminating entry */
 };
 
@@ -708,8 +714,7 @@ static int btusb_send_frame(struct sk_bu
 		break;
 
 	case HCI_ACLDATA_PKT:
-		if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
-						hdev->conn_hash.le_num < 1))
+		if (!data->bulk_tx_ep)
 			return -ENODEV;
 
 		urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -772,9 +777,8 @@ skip_waking:
 		usb_mark_last_busy(data->udev);
 	}
 
-	usb_free_urb(urb);
-
 done:
+	usb_free_urb(urb);
 	return err;
 }
 
@@ -1116,7 +1120,7 @@ static int btusb_suspend(struct usb_inte
 		return 0;
 
 	spin_lock_irq(&data->txlock);
-	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
 		set_bit(BTUSB_SUSPENDING, &data->flags);
 		spin_unlock_irq(&data->txlock);
 	} else {
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/btwilink.c linux-libre-3.2-gnu1/drivers/bluetooth/btwilink.c
--- linux-libre-3.1-gnu1/drivers/bluetooth/btwilink.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/btwilink.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <net/bluetooth/hci.h>
 
 #include <linux/ti_wilink_st.h>
+#include <linux/module.h>
 
 /* Bluetooth Driver Version */
 #define VERSION               "1.0"
diff -druNp linux-libre-3.1-gnu1/drivers/bluetooth/Kconfig linux-libre-3.2-gnu1/drivers/bluetooth/Kconfig
--- linux-libre-3.1-gnu1/drivers/bluetooth/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/bluetooth/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -188,7 +188,7 @@ config BT_MRVL
 	  The core driver to support Marvell Bluetooth devices.
 
 	  This driver is required if you want to support
-	  Marvell Bluetooth devices, such as 8688/8787.
+	  Marvell Bluetooth devices, such as 8688/8787/8797.
 
 	  Say Y here to compile Marvell Bluetooth driver
 	  into the kernel or say M to compile it as module.
@@ -201,8 +201,8 @@ config BT_MRVL_SDIO
 	  The driver for Marvell Bluetooth chipsets with SDIO interface.
 
 	  This driver is required if you want to use Marvell Bluetooth
-	  devices with SDIO interface. Currently SD8688/SD8787 chipsets are
-	  supported.
+	  devices with SDIO interface. Currently SD8688/SD8787/SD8797
+	  chipsets are supported.
 
 	  Say Y here to compile support for Marvell BT-over-SDIO driver
 	  into the kernel or say M to compile it as module.
diff -druNp linux-libre-3.1-gnu1/drivers/char/agp/backend.c linux-libre-3.2-gnu1/drivers/char/agp/backend.c
--- linux-libre-3.1-gnu1/drivers/char/agp/backend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/agp/backend.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,7 @@ static int agp_backend_initialize(struct
 	}
 	got_gatt = 1;
 
-	bridge->key_list = vmalloc(PAGE_SIZE * 4);
+	bridge->key_list = vzalloc(PAGE_SIZE * 4);
 	if (bridge->key_list == NULL) {
 		dev_err(&bridge->dev->dev,
 			"can't allocate memory for key lists\n");
@@ -181,7 +181,6 @@ static int agp_backend_initialize(struct
 	got_keylist = 1;
 
 	/* FIXME vmalloc'd memory not guaranteed contiguous */
-	memset(bridge->key_list, 0, PAGE_SIZE * 4);
 
 	if (bridge->driver->configure()) {
 		dev_err(&bridge->dev->dev, "error configuring host chipset\n");
diff -druNp linux-libre-3.1-gnu1/drivers/char/agp/hp-agp.c linux-libre-3.2-gnu1/drivers/char/agp/hp-agp.c
--- linux-libre-3.1-gnu1/drivers/char/agp/hp-agp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/agp/hp-agp.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,7 +336,8 @@ hp_zx1_insert_memory (struct agp_memory
 	off_t j, io_pg_start;
 	int io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
@@ -380,7 +381,8 @@ hp_zx1_remove_memory (struct agp_memory
 	struct _hp_private *hp = &hp_private;
 	int i, io_pg_start, io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/char/agp/intel-gtt.c linux-libre-3.2-gnu1/drivers/char/agp/intel-gtt.c
--- linux-libre-3.1-gnu1/drivers/char/agp/intel-gtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/agp/intel-gtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,10 +30,10 @@
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
- * on the Intel IOMMU support (CONFIG_DMAR).
+ * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
  * Only newer chipsets need to bother with this, of course.
  */
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 #define USE_PCI_DMA_API 1
 #else
 #define USE_PCI_DMA_API 0
@@ -923,6 +923,9 @@ static int intel_fake_agp_insert_entries
 {
 	int ret = -EINVAL;
 
+	if (intel_private.base.do_idle_maps)
+		return -ENODEV;
+
 	if (intel_private.clear_fake_agp) {
 		int start = intel_private.base.stolen_size / PAGE_SIZE;
 		int end = intel_private.base.gtt_mappable_entries;
@@ -985,6 +988,9 @@ static int intel_fake_agp_remove_entries
 	if (mem->page_count == 0)
 		return 0;
 
+	if (intel_private.base.do_idle_maps)
+		return -ENODEV;
+
 	intel_gtt_clear_range(pg_start, mem->page_count);
 
 	if (intel_private.base.needs_dmar) {
@@ -1177,6 +1183,26 @@ static void gen6_cleanup(void)
 {
 }
 
+/* Certain Gen5 chipsets require require idling the GPU before
+ * unmapping anything from the GTT when VT-d is enabled.
+ */
+static inline int needs_idle_maps(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+	const unsigned short gpu_devid = intel_private.pcidev->device;
+	extern int intel_iommu_gfx_mapped;
+
+	/* Query intel_iommu to see if we need the workaround. Presumably that
+	 * was loaded first.
+	 */
+	if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
+	     gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
+	     intel_iommu_gfx_mapped)
+		return 1;
+#endif
+	return 0;
+}
+
 static int i9xx_setup(void)
 {
 	u32 reg_addr;
@@ -1211,6 +1237,9 @@ static int i9xx_setup(void)
 		intel_private.gtt_bus_addr = reg_addr + gtt_offset;
 	}
 
+	if (needs_idle_maps())
+		intel_private.base.do_idle_maps = 1;
+
 	intel_i9xx_setup_flush();
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/char/apm-emulation.c linux-libre-3.2-gnu1/drivers/char/apm-emulation.c
--- linux-libre-3.1-gnu1/drivers/char/apm-emulation.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/apm-emulation.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,10 +40,7 @@
 #define APM_MINOR_DEV	134
 
 /*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
+ * One option can be changed at boot time as follows:
  *	apm=on/off			enable/disable APM
  */
 
@@ -300,17 +297,13 @@ apm_ioctl(struct file *filp, u_int cmd,
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
+			 * wait_event_freezable() is interruptible and pending
+			 * signal can cause busy looping.  We aren't doing
+			 * anything critical, chill a bit on each iteration.
 			 */
-			freezer_do_not_count();
-
-			wait_event(apm_suspend_waitqueue,
-				   as->suspend_state == SUSPEND_DONE);
-
-			/*
-			 * Since we are waiting until the suspend is done, the
-			 * try_to_freeze() in freezer_count() will not trigger
-			 */
-			freezer_count();
+			while (wait_event_freezable(apm_suspend_waitqueue,
+					as->suspend_state == SUSPEND_DONE))
+				msleep(10);
 			break;
 		case SUSPEND_ACKTO:
 			as->suspend_result = -ETIMEDOUT;
diff -druNp linux-libre-3.1-gnu1/drivers/char/hw_random/atmel-rng.c linux-libre-3.2-gnu1/drivers/char/hw_random/atmel-rng.c
--- linux-libre-3.1-gnu1/drivers/char/hw_random/atmel-rng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/char/hw_random/atmel-rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/hw_random.h>
+#include <linux/platform_device.h>
+
+#define TRNG_CR		0x00
+#define TRNG_ISR	0x1c
+#define TRNG_ODATA	0x50
+
+#define TRNG_KEY	0x524e4700 /* RNG */
+
+struct atmel_trng {
+	struct clk *clk;
+	void __iomem *base;
+	struct hwrng rng;
+};
+
+static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
+			   bool wait)
+{
+	struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
+	u32 *data = buf;
+
+	/* data ready? */
+	if (readl(trng->base + TRNG_ODATA) & 1) {
+		*data = readl(trng->base + TRNG_ODATA);
+		return 4;
+	} else
+		return 0;
+}
+
+static int atmel_trng_probe(struct platform_device *pdev)
+{
+	struct atmel_trng *trng;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+	if (!trng)
+		return -ENOMEM;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name))
+		return -EBUSY;
+
+	trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!trng->base)
+		return -EBUSY;
+
+	trng->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(trng->clk))
+		return PTR_ERR(trng->clk);
+
+	ret = clk_enable(trng->clk);
+	if (ret)
+		goto err_enable;
+
+	writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+	trng->rng.name = pdev->name;
+	trng->rng.read = atmel_trng_read;
+
+	ret = hwrng_register(&trng->rng);
+	if (ret)
+		goto err_register;
+
+	platform_set_drvdata(pdev, trng);
+
+	return 0;
+
+err_register:
+	clk_disable(trng->clk);
+err_enable:
+	clk_put(trng->clk);
+
+	return ret;
+}
+
+static int __devexit atmel_trng_remove(struct platform_device *pdev)
+{
+	struct atmel_trng *trng = platform_get_drvdata(pdev);
+
+	hwrng_unregister(&trng->rng);
+
+	writel(TRNG_KEY, trng->base + TRNG_CR);
+	clk_disable(trng->clk);
+	clk_put(trng->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_trng_suspend(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	clk_disable(trng->clk);
+
+	return 0;
+}
+
+static int atmel_trng_resume(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	return clk_enable(trng->clk);
+}
+
+static const struct dev_pm_ops atmel_trng_pm_ops = {
+	.suspend	= atmel_trng_suspend,
+	.resume		= atmel_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver atmel_trng_driver = {
+	.probe		= atmel_trng_probe,
+	.remove		= __devexit_p(atmel_trng_remove),
+	.driver		= {
+		.name	= "atmel-trng",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &atmel_trng_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init atmel_trng_init(void)
+{
+	return platform_driver_register(&atmel_trng_driver);
+}
+module_init(atmel_trng_init);
+
+static void __exit atmel_trng_exit(void)
+{
+	platform_driver_unregister(&atmel_trng_driver);
+}
+module_exit(atmel_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Atmel true random number generator driver");
diff -druNp linux-libre-3.1-gnu1/drivers/char/hw_random/Kconfig linux-libre-3.2-gnu1/drivers/char/hw_random/Kconfig
--- linux-libre-3.1-gnu1/drivers/char/hw_random/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/hw_random/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,19 @@ config HW_RANDOM_AMD
 
 	  If unsure, say Y.
 
+config HW_RANDOM_ATMEL
+	tristate "Atmel Random Number Generator support"
+	depends on HW_RANDOM && ARCH_AT91SAM9G45
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Atmel AT91 devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_GEODE
 	tristate "AMD Geode HW Random Number Generator support"
 	depends on HW_RANDOM && X86_32 && PCI
@@ -222,3 +235,18 @@ config HW_RANDOM_PPC4XX
 	 module will be called ppc4xx-rng.
 
 	 If unsure, say N.
+
+config UML_RANDOM
+	depends on UML
+	tristate "Hardware random number generator"
+	help
+	  This option enables UML's "hardware" random number generator.  It
+	  attaches itself to the host's /dev/random, supplying as much entropy
+	  as the host has, rather than the small amount the UML gets from its
+	  own drivers.  It registers itself as a standard hardware random number
+	  generator, major 10, minor 183, and the canonical device name is
+	  /dev/hwrng.
+	  The way to make use of this is to install the rng-tools package
+	  (check your distro, or download from
+	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
+	  /dev/hwrng and injects the entropy into /dev/random.
diff -druNp linux-libre-3.1-gnu1/drivers/char/hw_random/Makefile linux-libre-3.2-gnu1/drivers/char/hw_random/Makefile
--- linux-libre-3.1-gnu1/drivers/char/hw_random/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/hw_random/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@ rng-core-y := core.o
 obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
 obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
 n2-rng-y := n2-drv.o n2-asm.o
diff -druNp linux-libre-3.1-gnu1/drivers/char/hw_random/virtio-rng.c linux-libre-3.2-gnu1/drivers/char/hw_random/virtio-rng.c
--- linux-libre-3.1-gnu1/drivers/char/hw_random/virtio-rng.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/hw_random/virtio-rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/virtio.h>
 #include <linux/virtio_rng.h>
+#include <linux/module.h>
 
 static struct virtqueue *vq;
 static unsigned int data_avail;
diff -druNp linux-libre-3.1-gnu1/drivers/char/ipmi/ipmi_watchdog.c linux-libre-3.2-gnu1/drivers/char/ipmi/ipmi_watchdog.c
--- linux-libre-3.1-gnu1/drivers/char/ipmi/ipmi_watchdog.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/ipmi/ipmi_watchdog.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@
  * mechanism for it at that time.
  */
 #include <asm/kdebug.h>
+#include <asm/nmi.h>
 #define HAVE_DIE_NMI
 #endif
 
@@ -138,6 +139,8 @@
 #define IPMI_WDOG_SET_TIMER		0x24
 #define IPMI_WDOG_GET_TIMER		0x25
 
+#define IPMI_WDOG_TIMER_NOT_INIT_RESP	0x80
+
 /* These are here until the real ones get into the watchdog.h interface. */
 #ifndef WDIOC_GETTIMEOUT
 #define	WDIOC_GETTIMEOUT        _IOW(WATCHDOG_IOCTL_BASE, 20, int)
@@ -595,6 +598,7 @@ static int ipmi_heartbeat(void)
 	struct kernel_ipmi_msg            msg;
 	int                               rv;
 	struct ipmi_system_interface_addr addr;
+	int				  timeout_retries = 0;
 
 	if (ipmi_ignore_heartbeat)
 		return 0;
@@ -615,6 +619,7 @@ static int ipmi_heartbeat(void)
 
 	mutex_lock(&heartbeat_lock);
 
+restart:
 	atomic_set(&heartbeat_tofree, 2);
 
 	/*
@@ -652,7 +657,33 @@ static int ipmi_heartbeat(void)
 	/* Wait for the heartbeat to be sent. */
 	wait_for_completion(&heartbeat_wait);
 
-	if (heartbeat_recv_msg.msg.data[0] != 0) {
+	if (heartbeat_recv_msg.msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP)  {
+		timeout_retries++;
+		if (timeout_retries > 3) {
+			printk(KERN_ERR PFX ": Unable to restore the IPMI"
+			       " watchdog's settings, giving up.\n");
+			rv = -EIO;
+			goto out_unlock;
+		}
+
+		/*
+		 * The timer was not initialized, that means the BMC was
+		 * probably reset and lost the watchdog information.  Attempt
+		 * to restore the timer's info.  Note that we still hold
+		 * the heartbeat lock, to keep a heartbeat from happening
+		 * in this process, so must say no heartbeat to avoid a
+		 * deadlock on this mutex.
+		 */
+		rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+		if (rv) {
+			printk(KERN_ERR PFX ": Unable to send the command to"
+			       " set the watchdog's settings, giving up.\n");
+			goto out_unlock;
+		}
+
+		/* We might need a new heartbeat, so do it now */
+		goto restart;
+	} else if (heartbeat_recv_msg.msg.data[0] != 0) {
 		/*
 		 * Got an error in the heartbeat response.  It was already
 		 * reported in ipmi_wdog_msg_handler, but we should return
@@ -661,6 +692,7 @@ static int ipmi_heartbeat(void)
 		rv = -EINVAL;
 	}
 
+out_unlock:
 	mutex_unlock(&heartbeat_lock);
 
 	return rv;
@@ -921,11 +953,15 @@ static struct miscdevice ipmi_wdog_miscd
 static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
 				  void                 *handler_data)
 {
-	if (msg->msg.data[0] != 0) {
+	if (msg->msg.cmd == IPMI_WDOG_RESET_TIMER &&
+			msg->msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP)
+		printk(KERN_INFO PFX "response: The IPMI controller appears"
+		       " to have been reset, will attempt to reinitialize"
+		       " the watchdog timer\n");
+	else if (msg->msg.data[0] != 0)
 		printk(KERN_ERR PFX "response: Error %x on cmd %x\n",
 		       msg->msg.data[0],
 		       msg->msg.cmd);
-	}
 
 	ipmi_free_recv_msg(msg);
 }
@@ -1077,17 +1113,8 @@ static void ipmi_unregister_watchdog(int
 
 #ifdef HAVE_DIE_NMI
 static int
-ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
+ipmi_nmi(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = data;
-
-	if (val != DIE_NMIUNKNOWN)
-		return NOTIFY_OK;
-
-	/* Hack, if it's a memory or I/O error, ignore it. */
-	if (args->err & 0xc0)
-		return NOTIFY_OK;
-
 	/*
 	 * If we get here, it's an NMI that's not a memory or I/O
 	 * error.  We can't truly tell if it's from IPMI or not
@@ -1097,15 +1124,15 @@ ipmi_nmi(struct notifier_block *self, un
 
 	if (testing_nmi) {
 		testing_nmi = 2;
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	}
 
 	/* If we are not expecting a timeout, ignore it. */
 	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
-		return NOTIFY_OK;
+		return NMI_DONE;
 
 	if (preaction_val != WDOG_PRETIMEOUT_NMI)
-		return NOTIFY_OK;
+		return NMI_DONE;
 
 	/*
 	 * If no one else handled the NMI, we assume it was the IPMI
@@ -1120,12 +1147,8 @@ ipmi_nmi(struct notifier_block *self, un
 			panic(PFX "pre-timeout");
 	}
 
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
-
-static struct notifier_block ipmi_nmi_handler = {
-	.notifier_call = ipmi_nmi
-};
 #endif
 
 static int wdog_reboot_handler(struct notifier_block *this,
@@ -1290,7 +1313,8 @@ static void check_parms(void)
 		}
 	}
 	if (do_nmi && !nmi_handler_registered) {
-		rv = register_die_notifier(&ipmi_nmi_handler);
+		rv = register_nmi_handler(NMI_UNKNOWN, ipmi_nmi, 0,
+						"ipmi");
 		if (rv) {
 			printk(KERN_WARNING PFX
 			       "Can't register nmi handler\n");
@@ -1298,7 +1322,7 @@ static void check_parms(void)
 		} else
 			nmi_handler_registered = 1;
 	} else if (!do_nmi && nmi_handler_registered) {
-		unregister_die_notifier(&ipmi_nmi_handler);
+		unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 		nmi_handler_registered = 0;
 	}
 #endif
@@ -1336,7 +1360,7 @@ static int __init ipmi_wdog_init(void)
 	if (rv) {
 #ifdef HAVE_DIE_NMI
 		if (nmi_handler_registered)
-			unregister_die_notifier(&ipmi_nmi_handler);
+			unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 #endif
 		atomic_notifier_chain_unregister(&panic_notifier_list,
 						 &wdog_panic_notifier);
@@ -1357,7 +1381,7 @@ static void __exit ipmi_wdog_exit(void)
 
 #ifdef HAVE_DIE_NMI
 	if (nmi_handler_registered)
-		unregister_die_notifier(&ipmi_nmi_handler);
+		unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 #endif
 
 	atomic_notifier_chain_unregister(&panic_notifier_list,
diff -druNp linux-libre-3.1-gnu1/drivers/char/Kconfig linux-libre-3.2-gnu1/drivers/char/Kconfig
--- linux-libre-3.1-gnu1/drivers/char/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -298,7 +298,7 @@ if RTC_LIB=n
 config RTC
 	tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
 	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
-			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN
+			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -346,7 +346,7 @@ config JS_RTC
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
+	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -490,7 +490,7 @@ config SCx200_GPIO
 
 config PC8736x_GPIO
 	tristate "NatSemi PC8736x GPIO Support"
-	depends on X86_32
+	depends on X86_32 && !UML
 	default SCx200_GPIO	# mostly N
 	select NSC_GPIO		# needed for support routines
 	help
diff -druNp linux-libre-3.1-gnu1/drivers/char/mem.c linux-libre-3.2-gnu1/drivers/char/mem.c
--- linux-libre-3.1-gnu1/drivers/char/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/bootmem.h>
 #include <linux/splice.h>
 #include <linux/pfn.h>
+#include <linux/export.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -druNp linux-libre-3.1-gnu1/drivers/char/ps3flash.c linux-libre-3.2-gnu1/drivers/char/ps3flash.c
--- linux-libre-3.1-gnu1/drivers/char/ps3flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/ps3flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 
 #include <asm/lv1call.h>
 #include <asm/ps3stor.h>
diff -druNp linux-libre-3.1-gnu1/drivers/char/ramoops.c linux-libre-3.2-gnu1/drivers/char/ramoops.c
--- linux-libre-3.1-gnu1/drivers/char/ramoops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/ramoops.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/kmsg_dump.h>
 #include <linux/time.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
diff -druNp linux-libre-3.1-gnu1/drivers/char/random.c linux-libre-3.2-gnu1/drivers/char/random.c
--- linux-libre-3.1-gnu1/drivers/char/random.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/random.c	2012-01-04 18:55:44.000000000 -0500
@@ -932,7 +932,21 @@ static ssize_t extract_entropy_user(stru
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+	char *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min(nbytes, (int)sizeof(unsigned long));
+		
+		if (!arch_get_random_long(&v))
+			break;
+		
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
 }
 EXPORT_SYMBOL(get_random_bytes);
 
@@ -1318,9 +1332,14 @@ late_initcall(random_int_secret_init);
 DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-	__u32 *hash = get_cpu_var(get_random_int_hash);
+	__u32 *hash;
 	unsigned int ret;
 
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	hash = get_cpu_var(get_random_int_hash);
+
 	hash[0] += current->pid + jiffies + get_cycles();
 	md5_transform(hash, random_int_secret);
 	ret = hash[0];
diff -druNp linux-libre-3.1-gnu1/drivers/char/raw.c linux-libre-3.2-gnu1/drivers/char/raw.c
--- linux-libre-3.1-gnu1/drivers/char/raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -324,13 +324,12 @@ static int __init raw_init(void)
 		max_raw_minors = MAX_RAW_MINORS;
 	}
 
-	raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors);
+	raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors);
 	if (!raw_devices) {
 		printk(KERN_ERR "Not enough memory for raw device structures\n");
 		ret = -ENOMEM;
 		goto error;
 	}
-	memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors);
 
 	ret = register_chrdev_region(dev, max_raw_minors, "raw");
 	if (ret)
diff -druNp linux-libre-3.1-gnu1/drivers/char/rtc.c linux-libre-3.2-gnu1/drivers/char/rtc.c
--- linux-libre-3.1-gnu1/drivers/char/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 #include <linux/bcd.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
+#include <linux/ratelimit.h>
 
 #include <asm/current.h>
 #include <asm/system.h>
@@ -1195,10 +1196,8 @@ static void rtc_dropped_irq(unsigned lon
 
 	spin_unlock_irq(&rtc_lock);
 
-	if (printk_ratelimit()) {
-		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-			freq);
-	}
+	printk_ratelimited(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+			   freq);
 
 	/* Now we have new data */
 	wake_up_interruptible(&rtc_wait);
diff -druNp linux-libre-3.1-gnu1/drivers/char/scc.h linux-libre-3.2-gnu1/drivers/char/scc.h
--- linux-libre-3.1-gnu1/drivers/char/scc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/scc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,613 +0,0 @@
-/*
- * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-
-#ifndef _SCC_H
-#define _SCC_H
-
-#include <linux/delay.h>
-
-/* Special configuration ioctls for the Atari SCC5380 Serial
- * Communications Controller
- */
-
-/* ioctl command codes */
-
-#define TIOCGATSCC	0x54c0	/* get SCC configuration */
-#define TIOCSATSCC	0x54c1	/* set SCC configuration */
-#define TIOCDATSCC	0x54c2	/* reset configuration to defaults */
-
-/* Clock sources */
-
-#define CLK_RTxC	0
-#define CLK_TRxC	1
-#define CLK_PCLK	2
-
-/* baud_bases for the common clocks in the Atari. These are the real
- * frequencies divided by 16.
- */
-   
-#define SCC_BAUD_BASE_TIMC	19200	/* 0.3072 MHz from TT-MFP, Timer C */
-#define SCC_BAUD_BASE_BCLK	153600	/* 2.4576 MHz */
-#define SCC_BAUD_BASE_PCLK4	229500	/* 3.6720 MHz */
-#define SCC_BAUD_BASE_PCLK	503374	/* 8.0539763 MHz */
-#define SCC_BAUD_BASE_NONE	0	/* for not connected or unused
-					 * clock sources */
-
-/* The SCC clock configuration structure */
-
-struct scc_clock_config {
-	unsigned	RTxC_base;	/* base_baud of RTxC */
-	unsigned	TRxC_base;	/* base_baud of TRxC */
-	unsigned	PCLK_base;	/* base_baud of PCLK, both channels! */
-	struct {
-		unsigned clksrc;	/* CLK_RTxC, CLK_TRxC or CLK_PCLK */
-		unsigned divisor;	/* divisor for base baud, valid values:
-					 * see below */
-	} baud_table[17];		/* For 50, 75, 110, 135, 150, 200, 300,
-					 * 600, 1200, 1800, 2400, 4800, 9600,
-					 * 19200, 38400, 57600 and 115200 bps.
-					 * The last two could be replaced by
-					 * other rates > 38400 if they're not
-					 * possible.
-					 */
-};
-
-/* The following divisors are valid:
- *
- *   - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
- *               the BRG)
- *
- *   - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
- *
- *   - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
- *
- */
-
-struct scc_port {
-	struct gs_port		gs;
-	volatile unsigned char	*ctrlp;
-	volatile unsigned char	*datap;
-	int			x_char;		/* xon/xoff character */
-	int			c_dcd;
-	int			channel;
-	struct scc_port		*port_a;	/* Reference to port A and B */
-	struct scc_port		*port_b;	/*   structs for reg access  */
-};
-
-#define SCC_MAGIC	0x52696368
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Names                          */
-/*                                                                     */
-/***********************************************************************/
-
-/* The SCC documentation gives no explicit names to the registers,
- * they're just called WR0..15 and RR0..15. To make the source code
- * better readable and make the transparent write reg read access (see
- * below) possible, I christen them here with self-invented names.
- * Note that (real) read registers are assigned numbers 16..31. WR7'
- * has number 33.
- */
-
-#define	COMMAND_REG		0	/* wo */
-#define	INT_AND_DMA_REG		1	/* wo */
-#define	INT_VECTOR_REG		2	/* rw, common to both channels */
-#define	RX_CTRL_REG		3	/* rw */
-#define	AUX1_CTRL_REG		4	/* rw */
-#define	TX_CTRL_REG		5	/* rw */
-#define	SYNC_ADR_REG		6	/* wo */
-#define	SYNC_CHAR_REG		7	/* wo */
-#define	SDLC_OPTION_REG		33	/* wo */
-#define	TX_DATA_REG		8	/* wo */
-#define	MASTER_INT_CTRL		9	/* wo, common to both channels */
-#define	AUX2_CTRL_REG		10	/* rw */
-#define	CLK_CTRL_REG		11	/* wo */
-#define	TIMER_LOW_REG		12	/* rw */
-#define	TIMER_HIGH_REG		13	/* rw */
-#define	DPLL_CTRL_REG		14	/* wo */
-#define	INT_CTRL_REG		15	/* rw */
-
-#define	STATUS_REG		16	/* ro */
-#define	SPCOND_STATUS_REG	17	/* wo */
-/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
-#define	CURR_VECTOR_REG		18	/* Ch. B only, Ch. A for rw */
-#define	INT_PENDING_REG		19	/* Channel A only! */
-/* RR4 is WR4, if b6(MR7') == 1 */
-/* RR5 is WR5, if b6(MR7') == 1 */
-#define	FS_FIFO_LOW_REG		22	/* ro */
-#define	FS_FIFO_HIGH_REG	23	/* ro */
-#define	RX_DATA_REG		24	/* ro */
-/* RR9 is WR3, if b6(MR7') == 1 */
-#define	DPLL_STATUS_REG		26	/* ro */
-/* RR11 is WR10, if b6(MR7') == 1 */
-/* RR12 is WR12 */
-/* RR13 is WR13 */
-/* RR14 not present */
-/* RR15 is WR15 */
-
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Values                         */
-/*                                                                     */
-/***********************************************************************/
-
-
-/* WR0: COMMAND_REG "CR" */
-
-#define	CR_RX_CRC_RESET		0x40
-#define	CR_TX_CRC_RESET		0x80
-#define	CR_TX_UNDERRUN_RESET	0xc0
-
-#define	CR_EXTSTAT_RESET	0x10
-#define	CR_SEND_ABORT		0x18
-#define	CR_ENAB_INT_NEXT_RX	0x20
-#define	CR_TX_PENDING_RESET	0x28
-#define	CR_ERROR_RESET		0x30
-#define	CR_HIGHEST_IUS_RESET	0x38
-
-
-/* WR1: INT_AND_DMA_REG "IDR" */
-
-#define	IDR_EXTSTAT_INT_ENAB	0x01
-#define	IDR_TX_INT_ENAB		0x02
-#define	IDR_PARERR_AS_SPCOND	0x04
-
-#define	IDR_RX_INT_DISAB	0x00
-#define	IDR_RX_INT_FIRST	0x08
-#define	IDR_RX_INT_ALL		0x10
-#define	IDR_RX_INT_SPCOND	0x18
-#define	IDR_RX_INT_MASK		0x18
-
-#define	IDR_WAITREQ_RX		0x20
-#define	IDR_WAITREQ_IS_REQ	0x40
-#define	IDR_WAITREQ_ENAB	0x80
-
-
-/* WR3: RX_CTRL_REG "RCR" */
-
-#define	RCR_RX_ENAB		0x01
-#define	RCR_DISCARD_SYNC_CHARS	0x02
-#define	RCR_ADDR_SEARCH		0x04
-#define	RCR_CRC_ENAB		0x08
-#define	RCR_SEARCH_MODE		0x10
-#define	RCR_AUTO_ENAB_MODE	0x20
-
-#define	RCR_CHSIZE_MASK		0xc0
-#define	RCR_CHSIZE_5		0x00
-#define	RCR_CHSIZE_6		0x40
-#define	RCR_CHSIZE_7		0x80
-#define	RCR_CHSIZE_8		0xc0
-
-
-/* WR4: AUX1_CTRL_REG "A1CR" */
-
-#define	A1CR_PARITY_MASK	0x03
-#define	A1CR_PARITY_NONE	0x00
-#define	A1CR_PARITY_ODD		0x01
-#define	A1CR_PARITY_EVEN	0x03
-
-#define	A1CR_MODE_MASK		0x0c
-#define	A1CR_MODE_SYNCR		0x00
-#define	A1CR_MODE_ASYNC_1	0x04
-#define	A1CR_MODE_ASYNC_15	0x08
-#define	A1CR_MODE_ASYNC_2	0x0c
-
-#define	A1CR_SYNCR_MODE_MASK	0x30
-#define	A1CR_SYNCR_MONOSYNC	0x00
-#define	A1CR_SYNCR_BISYNC	0x10
-#define	A1CR_SYNCR_SDLC		0x20
-#define	A1CR_SYNCR_EXTCSYNC	0x30
-
-#define	A1CR_CLKMODE_MASK	0xc0
-#define	A1CR_CLKMODE_x1		0x00
-#define	A1CR_CLKMODE_x16	0x40
-#define	A1CR_CLKMODE_x32	0x80
-#define	A1CR_CLKMODE_x64	0xc0
-
-
-/* WR5: TX_CTRL_REG "TCR" */
-
-#define	TCR_TX_CRC_ENAB		0x01
-#define	TCR_RTS			0x02
-#define	TCR_USE_CRC_CCITT	0x00
-#define	TCR_USE_CRC_16		0x04
-#define	TCR_TX_ENAB		0x08
-#define	TCR_SEND_BREAK		0x10
-
-#define	TCR_CHSIZE_MASK		0x60
-#define	TCR_CHSIZE_5		0x00
-#define	TCR_CHSIZE_6		0x20
-#define	TCR_CHSIZE_7		0x40
-#define	TCR_CHSIZE_8		0x60
-
-#define	TCR_DTR			0x80
-
-
-/* WR7': SLDC_OPTION_REG "SOR" */
-
-#define	SOR_AUTO_TX_ENAB	0x01
-#define	SOR_AUTO_EOM_RESET	0x02
-#define	SOR_AUTO_RTS_MODE	0x04
-#define	SOR_NRZI_DISAB_HIGH	0x08
-#define	SOR_ALT_DTRREQ_TIMING	0x10
-#define	SOR_READ_CRC_CHARS	0x20
-#define	SOR_EXTENDED_REG_ACCESS	0x40
-
-
-/* WR9: MASTER_INT_CTRL "MIC" */
-
-#define	MIC_VEC_INCL_STAT	0x01
-#define	MIC_NO_VECTOR		0x02
-#define	MIC_DISAB_LOWER_CHAIN	0x04
-#define	MIC_MASTER_INT_ENAB	0x08
-#define	MIC_STATUS_HIGH		0x10
-#define	MIC_IGN_INTACK		0x20
-
-#define	MIC_NO_RESET		0x00
-#define	MIC_CH_A_RESET		0x40
-#define	MIC_CH_B_RESET		0x80
-#define	MIC_HARD_RESET		0xc0
-
-
-/* WR10: AUX2_CTRL_REG "A2CR" */
-
-#define	A2CR_SYNC_6		0x01
-#define	A2CR_LOOP_MODE		0x02
-#define	A2CR_ABORT_ON_UNDERRUN	0x04
-#define	A2CR_MARK_IDLE		0x08
-#define	A2CR_GO_ACTIVE_ON_POLL	0x10
-
-#define	A2CR_CODING_MASK	0x60
-#define	A2CR_CODING_NRZ		0x00
-#define	A2CR_CODING_NRZI	0x20
-#define	A2CR_CODING_FM1		0x40
-#define	A2CR_CODING_FM0		0x60
-
-#define	A2CR_PRESET_CRC_1	0x80
-
-
-/* WR11: CLK_CTRL_REG "CCR" */
-
-#define	CCR_TRxCOUT_MASK	0x03
-#define	CCR_TRxCOUT_XTAL	0x00
-#define	CCR_TRxCOUT_TXCLK	0x01
-#define	CCR_TRxCOUT_BRG		0x02
-#define	CCR_TRxCOUT_DPLL	0x03
-
-#define	CCR_TRxC_OUTPUT		0x04
-
-#define	CCR_TXCLK_MASK		0x18
-#define	CCR_TXCLK_RTxC		0x00
-#define	CCR_TXCLK_TRxC		0x08
-#define	CCR_TXCLK_BRG		0x10
-#define	CCR_TXCLK_DPLL		0x18
-
-#define	CCR_RXCLK_MASK		0x60
-#define	CCR_RXCLK_RTxC		0x00
-#define	CCR_RXCLK_TRxC		0x20
-#define	CCR_RXCLK_BRG		0x40
-#define	CCR_RXCLK_DPLL		0x60
-
-#define	CCR_RTxC_XTAL		0x80
-
-
-/* WR14: DPLL_CTRL_REG "DCR" */
-
-#define	DCR_BRG_ENAB		0x01
-#define	DCR_BRG_USE_PCLK	0x02
-#define	DCR_DTRREQ_IS_REQ	0x04
-#define	DCR_AUTO_ECHO		0x08
-#define	DCR_LOCAL_LOOPBACK	0x10
-
-#define	DCR_DPLL_EDGE_SEARCH	0x20
-#define	DCR_DPLL_ERR_RESET	0x40
-#define	DCR_DPLL_DISAB		0x60
-#define	DCR_DPLL_CLK_BRG	0x80
-#define	DCR_DPLL_CLK_RTxC	0xa0
-#define	DCR_DPLL_FM		0xc0
-#define	DCR_DPLL_NRZI		0xe0
-
-
-/* WR15: INT_CTRL_REG "ICR" */
-
-#define	ICR_OPTIONREG_SELECT	0x01
-#define	ICR_ENAB_BRG_ZERO_INT	0x02
-#define	ICR_USE_FS_FIFO		0x04
-#define	ICR_ENAB_DCD_INT	0x08
-#define	ICR_ENAB_SYNC_INT	0x10
-#define	ICR_ENAB_CTS_INT	0x20
-#define	ICR_ENAB_UNDERRUN_INT	0x40
-#define	ICR_ENAB_BREAK_INT	0x80
-
-
-/* RR0: STATUS_REG "SR" */
-
-#define	SR_CHAR_AVAIL		0x01
-#define	SR_BRG_ZERO		0x02
-#define	SR_TX_BUF_EMPTY		0x04
-#define	SR_DCD			0x08
-#define	SR_SYNC_ABORT		0x10
-#define	SR_CTS			0x20
-#define	SR_TX_UNDERRUN		0x40
-#define	SR_BREAK		0x80
-
-
-/* RR1: SPCOND_STATUS_REG "SCSR" */
-
-#define	SCSR_ALL_SENT		0x01
-#define	SCSR_RESIDUAL_MASK	0x0e
-#define	SCSR_PARITY_ERR		0x10
-#define	SCSR_RX_OVERRUN		0x20
-#define	SCSR_CRC_FRAME_ERR	0x40
-#define	SCSR_END_OF_FRAME	0x80
-
-
-/* RR3: INT_PENDING_REG "IPR" */
-
-#define	IPR_B_EXTSTAT		0x01
-#define	IPR_B_TX		0x02
-#define	IPR_B_RX		0x04
-#define	IPR_A_EXTSTAT		0x08
-#define	IPR_A_TX		0x10
-#define	IPR_A_RX		0x20
-
-
-/* RR7: FS_FIFO_HIGH_REG "FFHR" */
-
-#define	FFHR_CNT_MASK		0x3f
-#define	FFHR_IS_FROM_FIFO	0x40
-#define	FFHR_FIFO_OVERRUN	0x80
-
-
-/* RR10: DPLL_STATUS_REG "DSR" */
-
-#define	DSR_ON_LOOP		0x02
-#define	DSR_ON_LOOP_SENDING	0x10
-#define	DSR_TWO_CLK_MISSING	0x40
-#define	DSR_ONE_CLK_MISSING	0x80
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Access                         */
-/*                                                                     */
-/***********************************************************************/
-
-
-/* The SCC needs 3.5 PCLK cycles recovery time between to register
- * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
- * 125 ns = 437.5 ns. This is too short for udelay().
- * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
- * quite right
- */
-
-#define scc_reg_delay() \
-    do {			\
-	if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)	\
-		__asm__ __volatile__ ( " nop; nop");			\
-	else if (MACH_IS_ATARI)						\
-		__asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
-    } while (0)
-
-static unsigned char scc_shadow[2][16];
-
-/* The following functions should relax the somehow complicated
- * register access of the SCC. _SCCwrite() stores all written values
- * (except for WR0 and WR8) in shadow registers for later recall. This
- * removes the burden of remembering written values as needed. The
- * extra work of storing the value doesn't count, since a delay is
- * needed after a SCC access anyway. Additionally, _SCCwrite() manages
- * writes to WR0 and WR8 differently, because these can be accessed
- * directly with less overhead. Another special case are WR7 and WR7'.
- * _SCCwrite automatically checks what of this registers is selected
- * and changes b0 of WR15 if needed.
- * 
- * _SCCread() for standard read registers is straightforward, except
- * for RR2 (split into two "virtual" registers: one for the value
- * written to WR2 (from the shadow) and one for the vector including
- * status from RR2, Ch. B) and RR3. The latter must be read from
- * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
- * be accessed directly as before.
- * 
- * The two inline function contain complicated switch statements. But
- * I rely on regno and final_delay being constants, so gcc can reduce
- * the whole stuff to just some assembler statements.
- * 
- * _SCCwrite and _SCCread aren't intended to be used directly under
- * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
- * for that purpose. They assume that a local variable 'port' is
- * declared and pointing to the port's scc_struct entry. The
- * variants with "_NB" appended should be used if no other SCC
- * accesses follow immediately (within 0.5 usecs). They just skip the
- * final delay nops.
- * 
- * Please note that accesses to SCC registers should only take place
- * when interrupts are turned off (at least if SCC interrupts are
- * enabled). Otherwise, an interrupt could interfere with the
- * two-stage accessing process.
- *
- */
-
-
-static __inline__ void _SCCwrite(
-	struct scc_port *port,
-	unsigned char *shadow,
-	volatile unsigned char *_scc_del,
-	int regno,
-	unsigned char val, int final_delay )
-{
-	switch( regno ) {
-
-	  case COMMAND_REG:
-		/* WR0 can be written directly without pointing */
-		*port->ctrlp = val;
-		break;
-
-	  case SYNC_CHAR_REG:
-		/* For WR7, first set b0 of WR15 to 0, if needed */
-		if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
-			*port->ctrlp = 15;
-			shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
-			scc_reg_delay();
-			*port->ctrlp = shadow[INT_CTRL_REG];
-			scc_reg_delay();
-		}
-		goto normal_case;
-		
-	  case SDLC_OPTION_REG:
-		/* For WR7', first set b0 of WR15 to 1, if needed */
-		if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
-			*port->ctrlp = 15;
-			shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
-			scc_reg_delay();
-			*port->ctrlp = shadow[INT_CTRL_REG];
-			scc_reg_delay();
-		}
-		*port->ctrlp = 7;
-		shadow[8] = val;	/* WR7' shadowed at WR8 */
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case TX_DATA_REG:		/* WR8 */
-		/* TX_DATA_REG can be accessed directly on some h/w */
-		if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
-		{
-			*port->ctrlp = regno;
-			scc_reg_delay();
-			*port->ctrlp = val;
-		}
-		else
-			*port->datap = val;
-		break;
-
-	  case MASTER_INT_CTRL:
-		*port->ctrlp = regno;
-		val &= 0x3f;	/* bits 6..7 are the reset commands */
-		scc_shadow[0][regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case DPLL_CTRL_REG:
-		*port->ctrlp = regno;
-		val &= 0x1f;			/* bits 5..7 are the DPLL commands */
-		shadow[regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case 1 ... 6:	
-	  case 10 ... 13:
-	  case 15:
-	  normal_case:
-		*port->ctrlp = regno;
-		shadow[regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-		
-	  default:
-		printk( "Bad SCC write access to WR%d\n", regno );
-		break;
-		
-	}
-
-	if (final_delay)
-		scc_reg_delay();
-}
-
-
-static __inline__ unsigned char _SCCread(
-	struct scc_port *port,
-	unsigned char *shadow,
-	volatile unsigned char *_scc_del,
-	int regno, int final_delay )
-{
-	unsigned char rv;
-
-	switch( regno ) {
-
-		/* --- real read registers --- */
-	  case STATUS_REG:
-		rv = *port->ctrlp;
-		break;
-
-	  case INT_PENDING_REG:
-		/* RR3: read only from Channel A! */
-		port = port->port_a;
-		goto normal_case;
-
-	  case RX_DATA_REG:
-		/* RR8 can be accessed directly on some h/w */
-		if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
-		{
-			*port->ctrlp = 8;
-			scc_reg_delay();
-			rv = *port->ctrlp;
-		}
-		else
-			rv = *port->datap;
-		break;
-
-	  case CURR_VECTOR_REG:
-		/* RR2 (vector including status) from Ch. B */
-		port = port->port_b;
-		goto normal_case;
-		
-		/* --- reading write registers: access the shadow --- */
-	  case 1 ... 7:
-	  case 10 ... 15:
-		return shadow[regno]; /* no final delay! */
-
-		/* WR7' is special, because it is shadowed at the place of WR8 */
-	  case SDLC_OPTION_REG:
-		return shadow[8]; /* no final delay! */
-
-		/* WR9 is special too, because it is common for both channels */
-	  case MASTER_INT_CTRL:
-		return scc_shadow[0][9]; /* no final delay! */
-
-	  default:
-		printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
-				regno & ~16 );
-		break;
-		
-	  case SPCOND_STATUS_REG:
-	  case FS_FIFO_LOW_REG:
-	  case FS_FIFO_HIGH_REG:
-	  case DPLL_STATUS_REG:
-	  normal_case:
-		*port->ctrlp = regno & 0x0f;
-		scc_reg_delay();
-		rv = *port->ctrlp;
-		break;
-		
-	}
-
-	if (final_delay)
-		scc_reg_delay();
-	return rv;
-}
-
-#define SCC_ACCESS_INIT(port)						\
-	unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
-
-#define	SCCwrite(reg,val)	_SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
-#define	SCCwrite_NB(reg,val)	_SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
-#define	SCCread(reg)		_SCCread(port,_scc_shadow,scc_del,(reg),1)
-#define	SCCread_NB(reg)		_SCCread(port,_scc_shadow,scc_del,(reg),0)
-
-#define SCCmod(reg,and,or)	SCCwrite((reg),(SCCread(reg)&(and))|(or))
-
-#endif /* _SCC_H */
diff -druNp linux-libre-3.1-gnu1/drivers/char/tpm/tpm.c linux-libre-3.2-gnu1/drivers/char/tpm/tpm.c
--- linux-libre-3.1-gnu1/drivers/char/tpm/tpm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/tpm/tpm.c	2012-01-04 18:55:44.000000000 -0500
@@ -966,6 +966,9 @@ ssize_t tpm_show_durations(struct device
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 
+	if (chip->vendor.duration[TPM_LONG] == 0)
+		return 0;
+
 	return sprintf(buf, "%d %d %d [%s]\n",
 		       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
 		       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
diff -druNp linux-libre-3.1-gnu1/drivers/char/ttyprintk.c linux-libre-3.2-gnu1/drivers/char/ttyprintk.c
--- linux-libre-3.1-gnu1/drivers/char/ttyprintk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/ttyprintk.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
+#include <linux/export.h>
 
 struct ttyprintk_port {
 	struct tty_port port;
@@ -170,7 +171,7 @@ static const struct tty_operations ttypr
 	.ioctl = tpk_ioctl,
 };
 
-struct tty_port_operations null_ops = { };
+static struct tty_port_operations null_ops = { };
 
 static struct tty_driver *ttyprintk_driver;
 
diff -druNp linux-libre-3.1-gnu1/drivers/char/virtio_console.c linux-libre-3.2-gnu1/drivers/char/virtio_console.c
--- linux-libre-3.1-gnu1/drivers/char/virtio_console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/char/virtio_console.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,8 +19,10 @@
  */
 #include <linux/cdev.h>
 #include <linux/debugfs.h>
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/list.h>
@@ -32,6 +34,7 @@
 #include <linux/virtio_console.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -73,6 +76,7 @@ struct ports_driver_data {
 static struct ports_driver_data pdrvdata;
 
 DEFINE_SPINLOCK(pdrvdata_lock);
+DECLARE_COMPLETION(early_console_added);
 
 /* This struct holds information that's relevant only for console ports */
 struct console {
@@ -151,6 +155,10 @@ struct ports_device {
 	int chr_major;
 };
 
+struct port_stats {
+	unsigned long bytes_sent, bytes_received, bytes_discarded;
+};
+
 /* This struct holds the per-port data */
 struct port {
 	/* Next port in the list, head is in the ports_device */
@@ -179,6 +187,13 @@ struct port {
 	struct dentry *debugfs_file;
 
 	/*
+	 * Keep count of the bytes sent, received and discarded for
+	 * this port for accounting and debugging purposes.  These
+	 * counts are not reset across port open / close events.
+	 */
+	struct port_stats stats;
+
+	/*
 	 * The entries in this struct will be valid if this port is
 	 * hooked up to an hvc console
 	 */
@@ -347,17 +362,19 @@ fail:
 }
 
 /* Callers should take appropriate locks */
-static void *get_inbuf(struct port *port)
+static struct port_buffer *get_inbuf(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
 	unsigned int len;
 
-	vq = port->in_vq;
-	buf = virtqueue_get_buf(vq, &len);
+	if (port->inbuf)
+		return port->inbuf;
+
+	buf = virtqueue_get_buf(port->in_vq, &len);
 	if (buf) {
 		buf->len = len;
 		buf->offset = 0;
+		port->stats.bytes_received += len;
 	}
 	return buf;
 }
@@ -384,32 +401,27 @@ static int add_inbuf(struct virtqueue *v
 static void discard_port_data(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
-	unsigned int len;
-	int ret;
+	unsigned int err;
 
 	if (!port->portdev) {
 		/* Device has been unplugged.  vqs are already gone. */
 		return;
 	}
-	vq = port->in_vq;
-	if (port->inbuf)
-		buf = port->inbuf;
-	else
-		buf = virtqueue_get_buf(vq, &len);
+	buf = get_inbuf(port);
 
-	ret = 0;
+	err = 0;
 	while (buf) {
-		if (add_inbuf(vq, buf) < 0) {
-			ret++;
+		port->stats.bytes_discarded += buf->len - buf->offset;
+		if (add_inbuf(port->in_vq, buf) < 0) {
+			err++;
 			free_buf(buf);
 		}
-		buf = virtqueue_get_buf(vq, &len);
+		port->inbuf = NULL;
+		buf = get_inbuf(port);
 	}
-	port->inbuf = NULL;
-	if (ret)
+	if (err)
 		dev_warn(port->dev, "Errors adding %d buffers back to vq\n",
-			 ret);
+			 err);
 }
 
 static bool port_has_data(struct port *port)
@@ -417,18 +429,12 @@ static bool port_has_data(struct port *p
 	unsigned long flags;
 	bool ret;
 
+	ret = false;
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (port->inbuf) {
-		ret = true;
-		goto out;
-	}
 	port->inbuf = get_inbuf(port);
-	if (port->inbuf) {
+	if (port->inbuf)
 		ret = true;
-		goto out;
-	}
-	ret = false;
-out:
+
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
 	return ret;
 }
@@ -529,6 +535,8 @@ static ssize_t send_buf(struct port *por
 		cpu_relax();
 done:
 	spin_unlock_irqrestore(&port->outvq_lock, flags);
+
+	port->stats.bytes_sent += in_count;
 	/*
 	 * We're expected to return the amount of data we wrote -- all
 	 * of it
@@ -633,8 +641,8 @@ static ssize_t port_fops_read(struct fil
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_read_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_read_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -677,8 +685,8 @@ static ssize_t port_fops_write(struct fi
 		if (nonblock)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_write_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_write_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -1059,6 +1067,14 @@ static ssize_t debugfs_read(struct file
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "outvq_full: %d\n", port->outvq_full);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_sent: %lu\n", port->stats.bytes_sent);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_received: %lu\n",
+			       port->stats.bytes_received);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_discarded: %lu\n",
+			       port->stats.bytes_discarded);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "is_console: %s\n",
 			       is_console_port(port) ? "yes" : "no");
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -1143,6 +1159,7 @@ static int add_port(struct ports_device
 	port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
 
 	port->host_connected = port->guest_connected = false;
+	port->stats = (struct port_stats) { 0 };
 
 	port->outvq_full = false;
 
@@ -1352,6 +1369,7 @@ static void handle_control_message(struc
 			break;
 
 		init_port_console(port);
+		complete(&early_console_added);
 		/*
 		 * Could remove the port here in case init fails - but
 		 * have to notify the host first.
@@ -1394,6 +1412,13 @@ static void handle_control_message(struc
 		break;
 	case VIRTIO_CONSOLE_PORT_NAME:
 		/*
+		 * If we woke up after hibernation, we can get this
+		 * again.  Skip it in that case.
+		 */
+		if (port->name)
+			break;
+
+		/*
 		 * Skip the size of the header and the cpkt to get the size
 		 * of the name that was sent
 		 */
@@ -1481,8 +1506,7 @@ static void in_intr(struct virtqueue *vq
 		return;
 
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (!port->inbuf)
-		port->inbuf = get_inbuf(port);
+	port->inbuf = get_inbuf(port);
 
 	/*
 	 * Don't queue up data when port is closed.  This condition
@@ -1563,7 +1587,7 @@ static int init_vqs(struct ports_device
 	portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
 				   GFP_KERNEL);
 	if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
-			!portdev->out_vqs) {
+	    !portdev->out_vqs) {
 		err = -ENOMEM;
 		goto free;
 	}
@@ -1648,6 +1672,10 @@ static int __devinit virtcons_probe(stru
 	struct ports_device *portdev;
 	int err;
 	bool multiport;
+	bool early = early_put_chars != NULL;
+
+	/* Ensure to read early_put_chars now */
+	barrier();
 
 	portdev = kmalloc(sizeof(*portdev), GFP_KERNEL);
 	if (!portdev) {
@@ -1675,13 +1703,11 @@ static int __devinit virtcons_probe(stru
 
 	multiport = false;
 	portdev->config.max_nr_ports = 1;
-	if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
+	if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+			      offsetof(struct virtio_console_config,
+				       max_nr_ports),
+			      &portdev->config.max_nr_ports) == 0)
 		multiport = true;
-		vdev->config->get(vdev, offsetof(struct virtio_console_config,
-						 max_nr_ports),
-				  &portdev->config.max_nr_ports,
-				  sizeof(portdev->config.max_nr_ports));
-	}
 
 	err = init_vqs(portdev);
 	if (err < 0) {
@@ -1719,6 +1745,19 @@ static int __devinit virtcons_probe(stru
 
 	__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
 			   VIRTIO_CONSOLE_DEVICE_READY, 1);
+
+	/*
+	 * If there was an early virtio console, assume that there are no
+	 * other consoles. We need to wait until the hvc_alloc matches the
+	 * hvc_instantiate, otherwise tty_open will complain, resulting in
+	 * a "Warning: unable to open an initial console" boot failure.
+	 * Without multiport this is done in add_port above. With multiport
+	 * this might take some host<->guest communication - thus we have to
+	 * wait.
+	 */
+	if (multiport && early)
+		wait_for_completion(&early_console_added);
+
 	return 0;
 
 free_vqs:
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/clksrc-dbx500-prcmu.c linux-libre-3.2-gnu1/drivers/clocksource/clksrc-dbx500-prcmu.c
--- linux-libre-3.1-gnu1/drivers/clocksource/clksrc-dbx500-prcmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/clocksource/clksrc-dbx500-prcmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer for ST-Ericsson
+ * sched_clock implementation is based on:
+ * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * DBx500-PRCMU Timer
+ * The PRCMU has 5 timers which are available in a always-on
+ * power domain.  We use the Timer 4 for our always-on clock
+ * source on DB8500 and Timer 3 on DB5500.
+ */
+#include <linux/clockchips.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/sched_clock.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#define RATE_32K		32768
+
+#define TIMER_MODE_CONTINOUS	0x1
+#define TIMER_DOWNCOUNT_VAL	0xffffffff
+
+#define PRCMU_TIMER_REF		0
+#define PRCMU_TIMER_DOWNCOUNT	0x4
+#define PRCMU_TIMER_MODE	0x8
+
+#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
+
+static void __iomem *clksrc_dbx500_timer_base;
+
+static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs)
+{
+	u32 count, count2;
+
+	do {
+		count = readl(clksrc_dbx500_timer_base +
+			      PRCMU_TIMER_DOWNCOUNT);
+		count2 = readl(clksrc_dbx500_timer_base +
+			       PRCMU_TIMER_DOWNCOUNT);
+	} while (count2 != count);
+
+	/* Negate because the timer is a decrementing counter */
+	return ~count;
+}
+
+static struct clocksource clocksource_dbx500_prcmu = {
+	.name		= "dbx500-prcmu-timer",
+	.rating		= 300,
+	.read		= clksrc_dbx500_prcmu_read,
+	.shift		= 10,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc;
+
+	if (unlikely(!clksrc_dbx500_timer_base))
+		return 0;
+
+	cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace clksrc_dbx500_prcmu_update_sched_clock(void)
+{
+	u32 cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+#endif
+
+void __init clksrc_dbx500_prcmu_init(void __iomem *base)
+{
+	clksrc_dbx500_timer_base = base;
+
+	/*
+	 * The A9 sub system expects the timer to be configured as
+	 * a continous looping timer.
+	 * The PRCMU should configure it but if it for some reason
+	 * don't we do it here.
+	 */
+	if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
+	    TIMER_MODE_CONTINOUS) {
+		writel(TIMER_MODE_CONTINOUS,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
+		writel(TIMER_DOWNCOUNT_VAL,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
+	}
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	init_sched_clock(&cd, clksrc_dbx500_prcmu_update_sched_clock,
+			 32, RATE_32K);
+#endif
+	clocksource_calc_mult_shift(&clocksource_dbx500_prcmu,
+				    RATE_32K, SCHED_CLOCK_MIN_WRAP);
+	clocksource_register(&clocksource_dbx500_prcmu);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/dw_apb_timer.c linux-libre-3.2-gnu1/drivers/clocksource/dw_apb_timer.c
--- linux-libre-3.1-gnu1/drivers/clocksource/dw_apb_timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/dw_apb_timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -348,7 +348,7 @@ static void apbt_restart_clocksource(str
  * dw_apb_clocksource_register() as the next step.
  */
 struct dw_apb_clocksource *
-dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base,
 			unsigned long freq)
 {
 	struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/Kconfig linux-libre-3.2-gnu1/drivers/clocksource/Kconfig
--- linux-libre-3.1-gnu1/drivers/clocksource/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,3 +15,18 @@ config CLKSRC_MMIO
 
 config DW_APB_TIMER
 	bool
+
+config CLKSRC_DBX500_PRCMU
+	bool "Clocksource PRCMU Timer"
+	depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
+	default y
+	help
+	  Use the always on PRCMU Timer as clocksource
+
+config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	bool "Clocksource PRCMU Timer sched_clock"
+	depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+	select HAVE_SCHED_CLOCK
+	default y
+	help
+	  Use the always on PRCMU Timer as sched_clock
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/Makefile linux-libre-3.2-gnu1/drivers/clocksource/Makefile
--- linux-libre-3.1-gnu1/drivers/clocksource/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -9,3 +9,4 @@ obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
\ No newline at end of file
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/sh_cmt.c linux-libre-3.2-gnu1/drivers/clocksource/sh_cmt.c
--- linux-libre-3.1-gnu1/drivers/clocksource/sh_cmt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/sh_cmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/sh_mtu2.c linux-libre-3.2-gnu1/drivers/clocksource/sh_mtu2.c
--- linux-libre-3.1-gnu1/drivers/clocksource/sh_mtu2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/sh_mtu2.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
diff -druNp linux-libre-3.1-gnu1/drivers/clocksource/sh_tmu.c linux-libre-3.2-gnu1/drivers/clocksource/sh_tmu.c
--- linux-libre-3.1-gnu1/drivers/clocksource/sh_tmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/clocksource/sh_tmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
diff -druNp linux-libre-3.1-gnu1/drivers/connector/cn_proc.c linux-libre-3.2-gnu1/drivers/connector/cn_proc.c
--- linux-libre-3.1-gnu1/drivers/connector/cn_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/connector/cn_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -205,6 +205,32 @@ void proc_ptrace_connector(struct task_s
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
+void proc_comm_connector(struct task_struct *task)
+{
+	struct cn_msg *msg;
+	struct proc_event *ev;
+	struct timespec ts;
+	__u8 buffer[CN_PROC_MSG_SIZE];
+
+	if (atomic_read(&proc_event_num_listeners) < 1)
+		return;
+
+	msg = (struct cn_msg *)buffer;
+	ev = (struct proc_event *)msg->data;
+	get_seq(&msg->seq, &ev->cpu);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->what = PROC_EVENT_COMM;
+	ev->event_data.comm.process_pid  = task->pid;
+	ev->event_data.comm.process_tgid = task->tgid;
+	get_task_comm(ev->event_data.comm.comm, task);
+
+	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+	msg->ack = 0; /* not used */
+	msg->len = sizeof(*ev);
+	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
 void proc_exit_connector(struct task_struct *task)
 {
 	struct cn_msg *msg;
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_conservative.c linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_conservative.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_conservative.c	2012-01-04 18:55:44.000000000 -0500
@@ -120,10 +120,12 @@ static inline cputime64_t get_cpu_idle_t
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
 
 	if (idle_time == -1ULL)
 		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
 
 	return idle_time;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_ondemand.c linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_ondemand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_ondemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,10 +144,12 @@ static inline cputime64_t get_cpu_idle_t
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
 
 	if (idle_time == -1ULL)
 		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
 
 	return idle_time;
 }
@@ -725,7 +727,7 @@ static int __init cpufreq_gov_dbs_init(v
 		dbs_tuners_ins.down_differential =
 					MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
 		/*
-		 * In no_hz/micro accounting case we set the minimum frequency
+		 * In nohz/micro accounting case we set the minimum frequency
 		 * not depending on HZ, but fixed (very low). The deferred
 		 * timer might skip some samples if idle/sleeping as needed.
 		*/
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_stats.c linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_stats.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/cpufreq_stats.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/cpufreq_stats.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/cpu.h>
 #include <linux/sysfs.h>
 #include <linux/cpufreq.h>
+#include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/percpu.h>
 #include <linux/kobject.h>
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/db8500-cpufreq.c linux-libre-3.2-gnu1/drivers/cpufreq/db8500-cpufreq.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/db8500-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/db8500-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,30 +12,35 @@
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <mach/id.h>
 
 static struct cpufreq_frequency_table freq_table[] = {
 	[0] = {
 		.index = 0,
-		.frequency = 300000,
+		.frequency = 200000,
 	},
 	[1] = {
 		.index = 1,
-		.frequency = 600000,
+		.frequency = 300000,
 	},
 	[2] = {
-		/* Used for MAX_OPP, if available */
 		.index = 2,
-		.frequency = CPUFREQ_TABLE_END,
+		.frequency = 600000,
 	},
 	[3] = {
+		/* Used for MAX_OPP, if available */
 		.index = 3,
 		.frequency = CPUFREQ_TABLE_END,
 	},
+	[4] = {
+		.index = 4,
+		.frequency = CPUFREQ_TABLE_END,
+	},
 };
 
 static enum arm_opp idx2opp[] = {
+	ARM_EXTCLK,
 	ARM_50_OPP,
 	ARM_100_OPP,
 	ARM_MAX_OPP
@@ -72,13 +77,13 @@ static int db8500_cpufreq_target(struct
 
 	freqs.old = policy->cur;
 	freqs.new = freq_table[idx].frequency;
-	freqs.cpu = policy->cpu;
 
 	if (freqs.old == freqs.new)
 		return 0;
 
 	/* pre-change notification */
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* request the PRCM unit for opp change */
 	if (prcmu_set_arm_opp(idx2opp[idx])) {
@@ -87,7 +92,8 @@ static int db8500_cpufreq_target(struct
 	}
 
 	/* post change notification */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
@@ -103,17 +109,19 @@ static unsigned int db8500_cpufreq_getsp
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-	int res;
-	int i;
+	int i, res;
 
 	BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
-	if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
-		freq_table[0].frequency = 400000;
-		freq_table[1].frequency = 800000;
+	if (!prcmu_is_u8400()) {
+		freq_table[1].frequency = 400000;
+		freq_table[2].frequency = 800000;
 		if (prcmu_has_arm_maxopp())
-			freq_table[2].frequency = 1000000;
+			freq_table[3].frequency = 1000000;
 	}
+	pr_info("db8500-cpufreq : Available frequencies:\n");
+	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+		pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
 
 	/* get policy fields based on the table */
 	res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -127,10 +135,6 @@ static int __cpuinit db8500_cpufreq_init
 	policy->min = policy->cpuinfo.min_freq;
 	policy->max = policy->cpuinfo.max_freq;
 	policy->cur = db8500_cpufreq_getspeed(policy->cpu);
-
-	for (i = 0; freq_table[i].frequency != policy->cur; i++)
-		;
-
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
 	/*
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/e_powersaver.c linux-libre-3.2-gnu1/drivers/cpufreq/e_powersaver.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/e_powersaver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/e_powersaver.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,11 @@
 #include <asm/msr.h>
 #include <asm/tsc.h>
 
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#endif
+
 #define EPS_BRAND_C7M	0
 #define EPS_BRAND_C7	1
 #define EPS_BRAND_EDEN	2
@@ -27,11 +32,59 @@
 
 struct eps_cpu_data {
 	u32 fsb;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	u32 bios_limit;
+#endif
 	struct cpufreq_frequency_table freq_table[];
 };
 
 static struct eps_cpu_data *eps_cpu[NR_CPUS];
 
+/* Module parameters */
+static int freq_failsafe_off;
+static int voltage_failsafe_off;
+static int set_max_voltage;
+
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+static int ignore_acpi_limit;
+
+static struct acpi_processor_performance *eps_acpi_cpu_perf;
+
+/* Minimum necessary to get acpi_processor_get_bios_limit() working */
+static int eps_acpi_init(void)
+{
+	eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
+				      GFP_KERNEL);
+	if (!eps_acpi_cpu_perf)
+		return -ENOMEM;
+
+	if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map,
+								GFP_KERNEL)) {
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+		return -ENOMEM;
+	}
+
+	if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) {
+		free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+		return -EIO;
+	}
+	return 0;
+}
+
+static int eps_acpi_exit(struct cpufreq_policy *policy)
+{
+	if (eps_acpi_cpu_perf) {
+		acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0);
+		free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+	}
+	return 0;
+}
+#endif
 
 static unsigned int eps_get(unsigned int cpu)
 {
@@ -164,6 +217,9 @@ static int eps_cpu_init(struct cpufreq_p
 	int k, step, voltage;
 	int ret;
 	int states;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	unsigned int limit;
+#endif
 
 	if (policy->cpu != 0)
 		return -ENODEV;
@@ -244,11 +300,62 @@ static int eps_cpu_init(struct cpufreq_p
 		return -EINVAL;
 	if (current_voltage > 0x1f || max_voltage > 0x1f)
 		return -EINVAL;
-	if (max_voltage < min_voltage)
+	if (max_voltage < min_voltage
+	    || current_voltage < min_voltage
+	    || current_voltage > max_voltage)
 		return -EINVAL;
 
+	/* Check for systems using underclocked CPU */
+	if (!freq_failsafe_off && max_multiplier != current_multiplier) {
+		printk(KERN_INFO "eps: Your processor is running at different "
+			"frequency then its maximum. Aborting.\n");
+		printk(KERN_INFO "eps: You can use freq_failsafe_off option "
+			"to disable this check.\n");
+		return -EINVAL;
+	}
+	if (!voltage_failsafe_off && max_voltage != current_voltage) {
+		printk(KERN_INFO "eps: Your processor is running at different "
+			"voltage then its maximum. Aborting.\n");
+		printk(KERN_INFO "eps: You can use voltage_failsafe_off "
+			"option to disable this check.\n");
+		return -EINVAL;
+	}
+
 	/* Calc FSB speed */
 	fsb = cpu_khz / current_multiplier;
+
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	/* Check for ACPI processor speed limit */
+	if (!ignore_acpi_limit && !eps_acpi_init()) {
+		if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
+			printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
+				limit/1000000,
+				(limit%1000000)/10000);
+			eps_acpi_exit(policy);
+			/* Check if max_multiplier is in BIOS limits */
+			if (limit && max_multiplier * fsb > limit) {
+				printk(KERN_INFO "eps: Aborting.\n");
+				return -EINVAL;
+			}
+		}
+	}
+#endif
+
+	/* Allow user to set lower maximum voltage then that reported
+	 * by processor */
+	if (brand == EPS_BRAND_C7M && set_max_voltage) {
+		u32 v;
+
+		/* Change mV to something hardware can use */
+		v = (set_max_voltage - 700) / 16;
+		/* Check if voltage is within limits */
+		if (v >= min_voltage && v <= max_voltage) {
+			printk(KERN_INFO "eps: Setting %dmV as maximum.\n",
+				v * 16 + 700);
+			max_voltage = v;
+		}
+	}
+
 	/* Calc number of p-states supported */
 	if (brand == EPS_BRAND_C7M)
 		states = max_multiplier - min_multiplier + 1;
@@ -265,6 +372,9 @@ static int eps_cpu_init(struct cpufreq_p
 
 	/* Copy basic values */
 	centaur->fsb = fsb;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	centaur->bios_limit = limit;
+#endif
 
 	/* Fill frequency and MSR value table */
 	f_table = &centaur->freq_table[0];
@@ -303,17 +413,7 @@ static int eps_cpu_init(struct cpufreq_p
 static int eps_cpu_exit(struct cpufreq_policy *policy)
 {
 	unsigned int cpu = policy->cpu;
-	struct eps_cpu_data *centaur;
-	u32 lo, hi;
-
-	if (eps_cpu[cpu] == NULL)
-		return -ENODEV;
-	centaur = eps_cpu[cpu];
 
-	/* Get max frequency */
-	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
-	/* Set max frequency */
-	eps_set_state(centaur, cpu, hi & 0xffff);
 	/* Bye */
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	kfree(eps_cpu[cpu]);
@@ -359,6 +459,19 @@ static void __exit eps_exit(void)
 	cpufreq_unregister_driver(&eps_driver);
 }
 
+/* Allow user to overclock his machine or to change frequency to higher after
+ * unloading module */
+module_param(freq_failsafe_off, int, 0644);
+MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
+module_param(voltage_failsafe_off, int, 0644);
+MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+module_param(ignore_acpi_limit, int, 0644);
+MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
+#endif
+module_param(set_max_voltage, int, 0644);
+MODULE_PARM_DESC(set_max_voltage, "Set maximum CPU voltage (mV) C7-M only");
+
 MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
 MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/exynos4210-cpufreq.c linux-libre-3.2-gnu1/drivers/cpufreq/exynos4210-cpufreq.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/exynos4210-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/exynos4210-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/cpufreq.h>
+#include <linux/notifier.h>
+#include <linux/suspend.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
@@ -36,6 +38,10 @@ static struct regulator *int_regulator;
 static struct cpufreq_freqs freqs;
 static unsigned int memtype;
 
+static unsigned int locking_frequency;
+static bool frequency_locked;
+static DEFINE_MUTEX(cpufreq_lock);
+
 enum exynos4_memory_type {
 	DDR2 = 4,
 	LPDDR2,
@@ -405,22 +411,32 @@ static int exynos4_target(struct cpufreq
 {
 	unsigned int index, old_index;
 	unsigned int arm_volt, int_volt;
+	int err = -EINVAL;
 
 	freqs.old = exynos4_getspeed(policy->cpu);
 
+	mutex_lock(&cpufreq_lock);
+
+	if (frequency_locked && target_freq != locking_frequency) {
+		err = -EAGAIN;
+		goto out;
+	}
+
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
 					   freqs.old, relation, &old_index))
-		return -EINVAL;
+		goto out;
 
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
 					   target_freq, relation, &index))
-		return -EINVAL;
+		goto out;
+
+	err = 0;
 
 	freqs.new = exynos4_freq_table[index].frequency;
 	freqs.cpu = policy->cpu;
 
 	if (freqs.new == freqs.old)
-		return 0;
+		goto out;
 
 	/* get the voltage value */
 	arm_volt = exynos4_volt_table[index].arm_volt;
@@ -447,10 +463,16 @@ static int exynos4_target(struct cpufreq
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+out:
+	mutex_unlock(&cpufreq_lock);
+	return err;
 }
 
 #ifdef CONFIG_PM
+/*
+ * These suspend/resume are used as syscore_ops, it is already too
+ * late to set regulator voltages at this stage.
+ */
 static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	return 0;
@@ -462,8 +484,82 @@ static int exynos4_cpufreq_resume(struct
 }
 #endif
 
+/**
+ * exynos4_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
+ *			context
+ * @notifier
+ * @pm_event
+ * @v
+ *
+ * While frequency_locked == true, target() ignores every frequency but
+ * locking_frequency. The locking_frequency value is the initial frequency,
+ * which is set by the bootloader. In order to eliminate possible
+ * inconsistency in clock values, we save and restore frequencies during
+ * suspend and resume and block CPUFREQ activities. Note that the standard
+ * suspend/resume cannot be used as they are too deep (syscore_ops) for
+ * regulator actions.
+ */
+static int exynos4_cpufreq_pm_notifier(struct notifier_block *notifier,
+				       unsigned long pm_event, void *v)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+	static unsigned int saved_frequency;
+	unsigned int temp;
+
+	mutex_lock(&cpufreq_lock);
+	switch (pm_event) {
+	case PM_SUSPEND_PREPARE:
+		if (frequency_locked)
+			goto out;
+		frequency_locked = true;
+
+		if (locking_frequency) {
+			saved_frequency = exynos4_getspeed(0);
+
+			mutex_unlock(&cpufreq_lock);
+			exynos4_target(policy, locking_frequency,
+				       CPUFREQ_RELATION_H);
+			mutex_lock(&cpufreq_lock);
+		}
+
+		break;
+	case PM_POST_SUSPEND:
+
+		if (saved_frequency) {
+			/*
+			 * While frequency_locked, only locking_frequency
+			 * is valid for target(). In order to use
+			 * saved_frequency while keeping frequency_locked,
+			 * we temporarly overwrite locking_frequency.
+			 */
+			temp = locking_frequency;
+			locking_frequency = saved_frequency;
+
+			mutex_unlock(&cpufreq_lock);
+			exynos4_target(policy, locking_frequency,
+				       CPUFREQ_RELATION_H);
+			mutex_lock(&cpufreq_lock);
+
+			locking_frequency = temp;
+		}
+
+		frequency_locked = false;
+		break;
+	}
+out:
+	mutex_unlock(&cpufreq_lock);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block exynos4_cpufreq_nb = {
+	.notifier_call = exynos4_cpufreq_pm_notifier,
+};
+
 static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
+	int ret;
+
 	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
 
 	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
@@ -479,16 +575,35 @@ static int exynos4_cpufreq_cpu_init(stru
 	 */
 	cpumask_setall(policy->cpus);
 
-	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+	ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+	if (ret)
+		return ret;
+
+	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
+
+	return 0;
+}
+
+static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
 }
 
+static struct freq_attr *exynos4_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
 static struct cpufreq_driver exynos4_driver = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= exynos4_verify_speed,
 	.target		= exynos4_target,
 	.get		= exynos4_getspeed,
 	.init		= exynos4_cpufreq_cpu_init,
+	.exit		= exynos4_cpufreq_cpu_exit,
 	.name		= "exynos4_cpufreq",
+	.attr		= exynos4_cpufreq_attr,
 #ifdef CONFIG_PM
 	.suspend	= exynos4_cpufreq_suspend,
 	.resume		= exynos4_cpufreq_resume,
@@ -501,6 +616,8 @@ static int __init exynos4_cpufreq_init(v
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
+	locking_frequency = exynos4_getspeed(0);
+
 	moutcore = clk_get(NULL, "moutcore");
 	if (IS_ERR(moutcore))
 		goto out;
@@ -540,6 +657,8 @@ static int __init exynos4_cpufreq_init(v
 		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
 	}
 
+	register_pm_notifier(&exynos4_cpufreq_nb);
+
 	return cpufreq_register_driver(&exynos4_driver);
 
 out:
diff -druNp linux-libre-3.1-gnu1/drivers/cpufreq/s3c64xx-cpufreq.c linux-libre-3.2-gnu1/drivers/cpufreq/s3c64xx-cpufreq.c
--- linux-libre-3.1-gnu1/drivers/cpufreq/s3c64xx-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpufreq/s3c64xx-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 static struct clk *armclk;
 static struct regulator *vddarm;
diff -druNp linux-libre-3.1-gnu1/drivers/cpuidle/cpuidle.c linux-libre-3.2-gnu1/drivers/cpuidle/cpuidle.c
--- linux-libre-3.1-gnu1/drivers/cpuidle/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpuidle/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
 #include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/cpu.h>
 #include <linux/cpuidle.h>
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
+#include <linux/module.h>
 #include <trace/events/power.h>
 
 #include "cpuidle.h"
@@ -61,8 +62,9 @@ static int __cpuidle_register_device(str
 int cpuidle_idle_call(void)
 {
 	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+	struct cpuidle_driver *drv = cpuidle_get_driver();
 	struct cpuidle_state *target_state;
-	int next_state;
+	int next_state, entered_state;
 
 	if (off)
 		return -ENODEV;
@@ -83,45 +85,36 @@ int cpuidle_idle_call(void)
 	hrtimer_peek_ahead_timers();
 #endif
 
-	/*
-	 * Call the device's prepare function before calling the
-	 * governor's select function.  ->prepare gives the device's
-	 * cpuidle driver a chance to update any dynamic information
-	 * of its cpuidle states for the current idle period, e.g.
-	 * state availability, latencies, residencies, etc.
-	 */
-	if (dev->prepare)
-		dev->prepare(dev);
-
 	/* ask the governor for the next state */
-	next_state = cpuidle_curr_governor->select(dev);
+	next_state = cpuidle_curr_governor->select(drv, dev);
 	if (need_resched()) {
 		local_irq_enable();
 		return 0;
 	}
 
-	target_state = &dev->states[next_state];
-
-	/* enter the state and update stats */
-	dev->last_state = target_state;
+	target_state = &drv->states[next_state];
 
 	trace_power_start(POWER_CSTATE, next_state, dev->cpu);
 	trace_cpu_idle(next_state, dev->cpu);
 
-	dev->last_residency = target_state->enter(dev, target_state);
+	entered_state = target_state->enter(dev, drv, next_state);
 
 	trace_power_end(dev->cpu);
 	trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
 
-	if (dev->last_state)
-		target_state = dev->last_state;
-
-	target_state->time += (unsigned long long)dev->last_residency;
-	target_state->usage++;
+	if (entered_state >= 0) {
+		/* Update cpuidle counters */
+		/* This can be moved to within driver enter routine
+		 * but that results in multiple copies of same code.
+		 */
+		dev->states_usage[entered_state].time +=
+				(unsigned long long)dev->last_residency;
+		dev->states_usage[entered_state].usage++;
+	}
 
 	/* give the governor an opportunity to reflect on the outcome */
 	if (cpuidle_curr_governor->reflect)
-		cpuidle_curr_governor->reflect(dev);
+		cpuidle_curr_governor->reflect(dev, entered_state);
 
 	return 0;
 }
@@ -172,11 +165,11 @@ void cpuidle_resume_and_unlock(void)
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+static int poll_idle(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index)
 {
 	ktime_t	t1, t2;
 	s64 diff;
-	int ret;
 
 	t1 = ktime_get();
 	local_irq_enable();
@@ -188,15 +181,14 @@ static int poll_idle(struct cpuidle_devi
 	if (diff > INT_MAX)
 		diff = INT_MAX;
 
-	ret = (int) diff;
-	return ret;
+	dev->last_residency = (int) diff;
+
+	return index;
 }
 
-static void poll_idle_init(struct cpuidle_device *dev)
+static void poll_idle_init(struct cpuidle_driver *drv)
 {
-	struct cpuidle_state *state = &dev->states[0];
-
-	cpuidle_set_statedata(state, NULL);
+	struct cpuidle_state *state = &drv->states[0];
 
 	snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
 	snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -207,7 +199,7 @@ static void poll_idle_init(struct cpuidl
 	state->enter = poll_idle;
 }
 #else
-static void poll_idle_init(struct cpuidle_device *dev) {}
+static void poll_idle_init(struct cpuidle_driver *drv) {}
 #endif /* CONFIG_ARCH_HAS_CPU_RELAX */
 
 /**
@@ -234,21 +226,20 @@ int cpuidle_enable_device(struct cpuidle
 			return ret;
 	}
 
-	poll_idle_init(dev);
+	poll_idle_init(cpuidle_get_driver());
 
 	if ((ret = cpuidle_add_state_sysfs(dev)))
 		return ret;
 
 	if (cpuidle_curr_governor->enable &&
-	    (ret = cpuidle_curr_governor->enable(dev)))
+	    (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
 		goto fail_sysfs;
 
 	for (i = 0; i < dev->state_count; i++) {
-		dev->states[i].usage = 0;
-		dev->states[i].time = 0;
+		dev->states_usage[i].usage = 0;
+		dev->states_usage[i].time = 0;
 	}
 	dev->last_residency = 0;
-	dev->last_state = NULL;
 
 	smp_wmb();
 
@@ -282,7 +273,7 @@ void cpuidle_disable_device(struct cpuid
 	dev->enabled = 0;
 
 	if (cpuidle_curr_governor->disable)
-		cpuidle_curr_governor->disable(dev);
+		cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
 
 	cpuidle_remove_state_sysfs(dev);
 	enabled_devices--;
@@ -310,26 +301,6 @@ static int __cpuidle_register_device(str
 
 	init_completion(&dev->kobj_unregister);
 
-	/*
-	 * cpuidle driver should set the dev->power_specified bit
-	 * before registering the device if the driver provides
-	 * power_usage numbers.
-	 *
-	 * For those devices whose ->power_specified is not set,
-	 * we fill in power_usage with decreasing values as the
-	 * cpuidle code has an implicit assumption that state Cn
-	 * uses less power than C(n-1).
-	 *
-	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
-	 * an power value of -1.  So we use -2, -3, etc, for other
-	 * c-states.
-	 */
-	if (!dev->power_specified) {
-		int i;
-		for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
-			dev->states[i].power_usage = -1 - i;
-	}
-
 	per_cpu(cpuidle_devices, dev->cpu) = dev;
 	list_add(&dev->device_list, &cpuidle_detected_devices);
 	if ((ret = cpuidle_add_sysfs(sys_dev))) {
diff -druNp linux-libre-3.1-gnu1/drivers/cpuidle/driver.c linux-libre-3.2-gnu1/drivers/cpuidle/driver.c
--- linux-libre-3.1-gnu1/drivers/cpuidle/driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpuidle/driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,30 @@
 static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
 
+static void __cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+	int i;
+	/*
+	 * cpuidle driver should set the drv->power_specified bit
+	 * before registering if the driver provides
+	 * power_usage numbers.
+	 *
+	 * If power_specified is not set,
+	 * we fill in power_usage with decreasing values as the
+	 * cpuidle code has an implicit assumption that state Cn
+	 * uses less power than C(n-1).
+	 *
+	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
+	 * an power value of -1.  So we use -2, -3, etc, for other
+	 * c-states.
+	 */
+	if (!drv->power_specified) {
+		for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
+			drv->states[i].power_usage = -1 - i;
+	}
+}
+
+
 /**
  * cpuidle_register_driver - registers a driver
  * @drv: the driver
@@ -34,6 +58,7 @@ int cpuidle_register_driver(struct cpuid
 		spin_unlock(&cpuidle_driver_lock);
 		return -EBUSY;
 	}
+	__cpuidle_register_driver(drv);
 	cpuidle_curr_driver = drv;
 	spin_unlock(&cpuidle_driver_lock);
 
diff -druNp linux-libre-3.1-gnu1/drivers/cpuidle/governors/ladder.c linux-libre-3.2-gnu1/drivers/cpuidle/governors/ladder.c
--- linux-libre-3.1-gnu1/drivers/cpuidle/governors/ladder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpuidle/governors/ladder.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,8 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
-#include <linux/moduleparam.h>
+#include <linux/pm_qos.h>
+#include <linux/module.h>
 #include <linux/jiffies.h>
 
 #include <asm/io.h>
@@ -60,9 +60,11 @@ static inline void ladder_do_selection(s
 
 /**
  * ladder_select_state - selects the next state to enter
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_select_state(struct cpuidle_device *dev)
+static int ladder_select_state(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
 	struct ladder_device_state *last_state;
@@ -77,15 +79,17 @@ static int ladder_select_state(struct cp
 
 	last_state = &ldev->states[last_idx];
 
-	if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
-		last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+	if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) {
+		last_residency = cpuidle_get_last_residency(dev) - \
+					 drv->states[last_idx].exit_latency;
+	}
 	else
 		last_residency = last_state->threshold.promotion_time + 1;
 
 	/* consider promotion */
-	if (last_idx < dev->state_count - 1 &&
+	if (last_idx < drv->state_count - 1 &&
 	    last_residency > last_state->threshold.promotion_time &&
-	    dev->states[last_idx + 1].exit_latency <= latency_req) {
+	    drv->states[last_idx + 1].exit_latency <= latency_req) {
 		last_state->stats.promotion_count++;
 		last_state->stats.demotion_count = 0;
 		if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -96,11 +100,11 @@ static int ladder_select_state(struct cp
 
 	/* consider demotion */
 	if (last_idx > CPUIDLE_DRIVER_STATE_START &&
-	    dev->states[last_idx].exit_latency > latency_req) {
+	    drv->states[last_idx].exit_latency > latency_req) {
 		int i;
 
 		for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
-			if (dev->states[i].exit_latency <= latency_req)
+			if (drv->states[i].exit_latency <= latency_req)
 				break;
 		}
 		ladder_do_selection(ldev, last_idx, i);
@@ -123,9 +127,11 @@ static int ladder_select_state(struct cp
 
 /**
  * ladder_enable_device - setup for the governor
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_enable_device(struct cpuidle_device *dev)
+static int ladder_enable_device(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	int i;
 	struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
@@ -134,8 +140,8 @@ static int ladder_enable_device(struct c
 
 	ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-	for (i = 0; i < dev->state_count; i++) {
-		state = &dev->states[i];
+	for (i = 0; i < drv->state_count; i++) {
+		state = &drv->states[i];
 		lstate = &ldev->states[i];
 
 		lstate->stats.promotion_count = 0;
@@ -144,7 +150,7 @@ static int ladder_enable_device(struct c
 		lstate->threshold.promotion_count = PROMOTION_COUNT;
 		lstate->threshold.demotion_count = DEMOTION_COUNT;
 
-		if (i < dev->state_count - 1)
+		if (i < drv->state_count - 1)
 			lstate->threshold.promotion_time = state->exit_latency;
 		if (i > 0)
 			lstate->threshold.demotion_time = state->exit_latency;
@@ -153,11 +159,24 @@ static int ladder_enable_device(struct c
 	return 0;
 }
 
+/**
+ * ladder_reflect - update the correct last_state_idx
+ * @dev: the CPU
+ * @index: the index of actual state entered
+ */
+static void ladder_reflect(struct cpuidle_device *dev, int index)
+{
+	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
+	if (index > 0)
+		ldev->last_state_idx = index;
+}
+
 static struct cpuidle_governor ladder_governor = {
 	.name =		"ladder",
 	.rating =	10,
 	.enable =	ladder_enable_device,
 	.select =	ladder_select_state,
+	.reflect =	ladder_reflect,
 	.owner =	THIS_MODULE,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/cpuidle/governors/menu.c linux-libre-3.2-gnu1/drivers/cpuidle/governors/menu.c
--- linux-libre-3.1-gnu1/drivers/cpuidle/governors/menu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpuidle/governors/menu.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,13 +12,14 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/time.h>
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/sched.h>
 #include <linux/math64.h>
+#include <linux/module.h>
 
 #define BUCKETS 12
 #define INTERVALS 8
@@ -182,7 +183,7 @@ static inline int performance_multiplier
 
 static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
-static void menu_update(struct cpuidle_device *dev);
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
 
 /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
 static u64 div_round64(u64 dividend, u32 divisor)
@@ -228,9 +229,10 @@ static void detect_repeating_patterns(st
 
 /**
  * menu_select - selects the next idle state to enter
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static int menu_select(struct cpuidle_device *dev)
+static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
@@ -240,7 +242,7 @@ static int menu_select(struct cpuidle_de
 	struct timespec t;
 
 	if (data->needs_update) {
-		menu_update(dev);
+		menu_update(drv, dev);
 		data->needs_update = 0;
 	}
 
@@ -285,11 +287,9 @@ static int menu_select(struct cpuidle_de
 	 * Find the idle state with the lowest power while satisfying
 	 * our constraints.
 	 */
-	for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
-		struct cpuidle_state *s = &dev->states[i];
+	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
+		struct cpuidle_state *s = &drv->states[i];
 
-		if (s->flags & CPUIDLE_FLAG_IGNORE)
-			continue;
 		if (s->target_residency > data->predicted_us)
 			continue;
 		if (s->exit_latency > latency_req)
@@ -310,26 +310,30 @@ static int menu_select(struct cpuidle_de
 /**
  * menu_reflect - records that data structures need update
  * @dev: the CPU
+ * @index: the index of actual entered state
  *
  * NOTE: it's important to be fast here because this operation will add to
  *       the overall exit latency.
  */
-static void menu_reflect(struct cpuidle_device *dev)
+static void menu_reflect(struct cpuidle_device *dev, int index)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
-	data->needs_update = 1;
+	data->last_state_idx = index;
+	if (index >= 0)
+		data->needs_update = 1;
 }
 
 /**
  * menu_update - attempts to guess what happened after entry
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static void menu_update(struct cpuidle_device *dev)
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int last_idx = data->last_state_idx;
 	unsigned int last_idle_us = cpuidle_get_last_residency(dev);
-	struct cpuidle_state *target = &dev->states[last_idx];
+	struct cpuidle_state *target = &drv->states[last_idx];
 	unsigned int measured_us;
 	u64 new_factor;
 
@@ -383,9 +387,11 @@ static void menu_update(struct cpuidle_d
 
 /**
  * menu_enable_device - scans a CPU's states and does setup
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int menu_enable_device(struct cpuidle_device *dev)
+static int menu_enable_device(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
 
diff -druNp linux-libre-3.1-gnu1/drivers/cpuidle/sysfs.c linux-libre-3.2-gnu1/drivers/cpuidle/sysfs.c
--- linux-libre-3.1-gnu1/drivers/cpuidle/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/cpuidle/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,7 +216,8 @@ static struct kobj_type ktype_cpuidle =
 
 struct cpuidle_state_attr {
 	struct attribute attr;
-	ssize_t (*show)(struct cpuidle_state *, char *);
+	ssize_t (*show)(struct cpuidle_state *, \
+					struct cpuidle_state_usage *, char *);
 	ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
 };
 
@@ -224,19 +225,22 @@ struct cpuidle_state_attr {
 static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
 
 #define define_show_state_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			 struct cpuidle_state_usage *state_usage, char *buf) \
 { \
 	return sprintf(buf, "%u\n", state->_name);\
 }
 
 #define define_show_state_ull_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			struct cpuidle_state_usage *state_usage, char *buf) \
 { \
-	return sprintf(buf, "%llu\n", state->_name);\
+	return sprintf(buf, "%llu\n", state_usage->_name);\
 }
 
 #define define_show_state_str_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			struct cpuidle_state_usage *state_usage, char *buf) \
 { \
 	if (state->_name[0] == '\0')\
 		return sprintf(buf, "<null>\n");\
@@ -269,16 +273,18 @@ static struct attribute *cpuidle_state_d
 
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
+#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 static ssize_t cpuidle_state_show(struct kobject * kobj,
 	struct attribute * attr ,char * buf)
 {
 	int ret = -EIO;
 	struct cpuidle_state *state = kobj_to_state(kobj);
+	struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
 	struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
 
 	if (cattr->show)
-		ret = cattr->show(state, buf);
+		ret = cattr->show(state, state_usage, buf);
 
 	return ret;
 }
@@ -316,13 +322,15 @@ int cpuidle_add_state_sysfs(struct cpuid
 {
 	int i, ret = -ENOMEM;
 	struct cpuidle_state_kobj *kobj;
+	struct cpuidle_driver *drv = cpuidle_get_driver();
 
 	/* state statistics */
 	for (i = 0; i < device->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
-		kobj->state = &device->states[i];
+		kobj->state = &drv->states[i];
+		kobj->state_usage = &device->states_usage[i];
 		init_completion(&kobj->kobj_unregister);
 
 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/hifn_795x.c linux-libre-3.2-gnu1/drivers/crypto/hifn_795x.c
--- linux-libre-3.1-gnu1/drivers/crypto/hifn_795x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/hifn_795x.c	2012-01-04 18:55:44.000000000 -0500
@@ -2744,10 +2744,8 @@ static int __init hifn_init(void)
 	unsigned int freq;
 	int err;
 
-	if (sizeof(dma_addr_t) > 4) {
-		printk(KERN_INFO "HIFN supports only 32-bit addresses.\n");
-		return -EINVAL;
-	}
+	/* HIFN supports only 32-bit addresses */
+	BUILD_BUG_ON(sizeof(dma_addr_t) != 4);
 
 	if (strncmp(hifn_pll_ref, "ext", 3) &&
 	    strncmp(hifn_pll_ref, "pci", 3)) {
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/Kconfig linux-libre-3.2-gnu1/drivers/crypto/Kconfig
--- linux-libre-3.1-gnu1/drivers/crypto/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -200,6 +200,7 @@ config CRYPTO_DEV_HIFN_795X
 	select CRYPTO_BLKCIPHER
 	select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
 	depends on PCI
+	depends on !ARCH_DMA_ADDR_T_64BIT
 	help
 	  This option allows you to have support for HIFN 795x crypto adapters.
 
@@ -266,7 +267,7 @@ config CRYPTO_DEV_OMAP_AES
 
 config CRYPTO_DEV_PICOXCELL
 	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
-	depends on ARCH_PICOXCELL
+	depends on ARCH_PICOXCELL && HAVE_CLK
 	select CRYPTO_AES
 	select CRYPTO_AUTHENC
 	select CRYPTO_ALGAPI
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/mv_cesa.c linux-libre-3.2-gnu1/drivers/crypto/mv_cesa.c
--- linux-libre-3.1-gnu1/drivers/crypto/mv_cesa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/mv_cesa.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <crypto/internal/hash.h>
 #include <crypto/sha.h>
 
@@ -342,11 +343,13 @@ static void mv_process_hash_current(int
 		else
 			op.config |= CFG_MID_FRAG;
 
-		writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
-		writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
-		writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
-		writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
-		writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+		if (first_block) {
+			writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
+			writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
+			writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
+			writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
+			writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+		}
 	}
 
 	memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config));
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/n2_core.c linux-libre-3.2-gnu1/drivers/crypto/n2_core.c
--- linux-libre-3.1-gnu1/drivers/crypto/n2_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/n2_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1006,9 +1006,9 @@ static int n2_do_ecb(struct ablkcipher_r
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, NULL);
 	return err;
 }
@@ -1096,9 +1096,9 @@ static int n2_do_chaining(struct ablkcip
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, err ? NULL : final_iv_addr);
 	return err;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/padlock-aes.c linux-libre-3.2-gnu1/drivers/crypto/padlock-aes.c
--- linux-libre-3.1-gnu1/drivers/crypto/padlock-aes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/padlock-aes.c	2012-01-04 18:55:44.000000000 -0500
@@ -508,10 +508,8 @@ static int __init padlock_init(void)
 	int ret;
 	struct cpuinfo_x86 *c = &cpu_data(0);
 
-	if (!cpu_has_xcrypt) {
-		printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
+	if (!cpu_has_xcrypt)
 		return -ENODEV;
-	}
 
 	if (!cpu_has_xcrypt_enabled) {
 		printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/picoxcell_crypto.c linux-libre-3.2-gnu1/drivers/crypto/picoxcell_crypto.c
--- linux-libre-3.1-gnu1/drivers/crypto/picoxcell_crypto.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/picoxcell_crypto.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/rtnetlink.h>
@@ -1241,8 +1242,8 @@ static void spacc_spacc_complete(unsigne
 	spin_unlock_irqrestore(&engine->hw_lock, flags);
 
 	list_for_each_entry_safe(req, tmp, &completed, list) {
-		req->complete(req);
 		list_del(&req->list);
+		req->complete(req);
 	}
 }
 
@@ -1657,10 +1658,33 @@ static struct spacc_alg l2_engine_algs[]
 	},
 };
 
-static int __devinit spacc_probe(struct platform_device *pdev,
-				 unsigned max_ctxs, size_t cipher_pg_sz,
-				 size_t hash_pg_sz, size_t fifo_sz,
-				 struct spacc_alg *algs, size_t num_algs)
+#ifdef CONFIG_OF
+static const struct of_device_id spacc_of_id_table[] = {
+	{ .compatible = "picochip,spacc-ipsec" },
+	{ .compatible = "picochip,spacc-l2" },
+	{}
+};
+#else /* CONFIG_OF */
+#define spacc_of_id_table NULL
+#endif /* CONFIG_OF */
+
+static bool spacc_is_compatible(struct platform_device *pdev,
+				const char *spacc_type)
+{
+	const struct platform_device_id *platid = platform_get_device_id(pdev);
+
+	if (platid && !strcmp(platid->name, spacc_type))
+		return true;
+
+#ifdef CONFIG_OF
+	if (of_device_is_compatible(pdev->dev.of_node, spacc_type))
+		return true;
+#endif /* CONFIG_OF */
+
+	return false;
+}
+
+static int __devinit spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret = -EINVAL;
 	struct resource *mem, *irq;
@@ -1669,13 +1693,25 @@ static int __devinit spacc_probe(struct
 	if (!engine)
 		return -ENOMEM;
 
-	engine->max_ctxs	= max_ctxs;
-	engine->cipher_pg_sz	= cipher_pg_sz;
-	engine->hash_pg_sz	= hash_pg_sz;
-	engine->fifo_sz		= fifo_sz;
-	engine->algs		= algs;
-	engine->num_algs	= num_algs;
-	engine->name		= dev_name(&pdev->dev);
+	if (spacc_is_compatible(pdev, "picochip,spacc-ipsec")) {
+		engine->max_ctxs	= SPACC_CRYPTO_IPSEC_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_IPSEC_FIFO_SZ;
+		engine->algs		= ipsec_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(ipsec_engine_algs);
+	} else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
+		engine->max_ctxs	= SPACC_CRYPTO_L2_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_L2_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_L2_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_L2_FIFO_SZ;
+		engine->algs		= l2_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(l2_engine_algs);
+	} else {
+		return -EINVAL;
+	}
+
+	engine->name = dev_name(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -1711,7 +1747,7 @@ static int __devinit spacc_probe(struct
 
 	spin_lock_init(&engine->hw_lock);
 
-	engine->clk = clk_get(&pdev->dev, NULL);
+	engine->clk = clk_get(&pdev->dev, "ref");
 	if (IS_ERR(engine->clk)) {
 		dev_info(&pdev->dev, "clk unavailable\n");
 		device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
@@ -1800,72 +1836,33 @@ static int __devexit spacc_remove(struct
 	return 0;
 }
 
-static int __devinit ipsec_probe(struct platform_device *pdev)
-{
-	return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
-			   SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
-			   SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
-			   SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
-			   ARRAY_SIZE(ipsec_engine_algs));
-}
-
-static struct platform_driver ipsec_driver = {
-	.probe		= ipsec_probe,
-	.remove		= __devexit_p(spacc_remove),
-	.driver		= {
-		.name	= "picoxcell-ipsec",
-#ifdef CONFIG_PM
-		.pm	= &spacc_pm_ops,
-#endif /* CONFIG_PM */
-	},
+static const struct platform_device_id spacc_id_table[] = {
+	{ "picochip,spacc-ipsec", },
+	{ "picochip,spacc-l2", },
 };
 
-static int __devinit l2_probe(struct platform_device *pdev)
-{
-	return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
-			   SPACC_CRYPTO_L2_CIPHER_PG_SZ,
-			   SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
-			   l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
-}
-
-static struct platform_driver l2_driver = {
-	.probe		= l2_probe,
+static struct platform_driver spacc_driver = {
+	.probe		= spacc_probe,
 	.remove		= __devexit_p(spacc_remove),
 	.driver		= {
-		.name	= "picoxcell-l2",
+		.name	= "picochip,spacc",
 #ifdef CONFIG_PM
 		.pm	= &spacc_pm_ops,
 #endif /* CONFIG_PM */
+		.of_match_table	= spacc_of_id_table,
 	},
+	.id_table	= spacc_id_table,
 };
 
 static int __init spacc_init(void)
 {
-	int ret = platform_driver_register(&ipsec_driver);
-	if (ret) {
-		pr_err("failed to register ipsec spacc driver");
-		goto out;
-	}
-
-	ret = platform_driver_register(&l2_driver);
-	if (ret) {
-		pr_err("failed to register l2 spacc driver");
-		goto l2_failed;
-	}
-
-	return 0;
-
-l2_failed:
-	platform_driver_unregister(&ipsec_driver);
-out:
-	return ret;
+	return platform_driver_register(&spacc_driver);
 }
 module_init(spacc_init);
 
 static void __exit spacc_exit(void)
 {
-	platform_driver_unregister(&ipsec_driver);
-	platform_driver_unregister(&l2_driver);
+	platform_driver_unregister(&spacc_driver);
 }
 module_exit(spacc_exit);
 
diff -druNp linux-libre-3.1-gnu1/drivers/crypto/talitos.c linux-libre-3.2-gnu1/drivers/crypto/talitos.c
--- linux-libre-3.1-gnu1/drivers/crypto/talitos.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/crypto/talitos.c	2012-01-04 18:55:44.000000000 -0500
@@ -416,7 +416,7 @@ static void talitos_done(unsigned long d
 /*
  * locate current (offending) descriptor
  */
-static struct talitos_desc *current_desc(struct device *dev, int ch)
+static u32 current_desc_hdr(struct device *dev, int ch)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int tail = priv->chan[ch].tail;
@@ -428,23 +428,25 @@ static struct talitos_desc *current_desc
 		tail = (tail + 1) & (priv->fifo_len - 1);
 		if (tail == priv->chan[ch].tail) {
 			dev_err(dev, "couldn't locate current descriptor\n");
-			return NULL;
+			return 0;
 		}
 	}
 
-	return priv->chan[ch].fifo[tail].desc;
+	return priv->chan[ch].fifo[tail].desc->hdr;
 }
 
 /*
  * user diagnostics; report root cause of error based on execution unit status
  */
-static void report_eu_error(struct device *dev, int ch,
-			    struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int i;
 
-	switch (desc->hdr & DESC_HDR_SEL0_MASK) {
+	if (!desc_hdr)
+		desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+
+	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
 	case DESC_HDR_SEL0_AFEU:
 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
 			in_be32(priv->reg + TALITOS_AFEUISR),
@@ -488,7 +490,7 @@ static void report_eu_error(struct devic
 		break;
 	}
 
-	switch (desc->hdr & DESC_HDR_SEL1_MASK) {
+	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
 	case DESC_HDR_SEL1_MDEUA:
 	case DESC_HDR_SEL1_MDEUB:
 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
@@ -550,7 +552,7 @@ static void talitos_error(unsigned long
 		if (v_lo & TALITOS_CCPSR_LO_IEU)
 			dev_err(dev, "invalid execution unit error\n");
 		if (v_lo & TALITOS_CCPSR_LO_EU)
-			report_eu_error(dev, ch, current_desc(dev, ch));
+			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
 		if (v_lo & TALITOS_CCPSR_LO_GB)
 			dev_err(dev, "gather boundary error\n");
 		if (v_lo & TALITOS_CCPSR_LO_GRL)
diff -druNp linux-libre-3.1-gnu1/drivers/dca/dca-core.c linux-libre-3.2-gnu1/drivers/dca/dca-core.c
--- linux-libre-3.1-gnu1/drivers/dca/dca-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dca/dca-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/dca.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DCA_VERSION "1.12.1"
 
@@ -35,7 +36,7 @@ MODULE_VERSION(DCA_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Intel Corporation");
 
-static DEFINE_SPINLOCK(dca_lock);
+static DEFINE_RAW_SPINLOCK(dca_lock);
 
 static LIST_HEAD(dca_domains);
 
@@ -101,10 +102,10 @@ static void unregister_dca_providers(voi
 
 	INIT_LIST_HEAD(&unregistered_providers);
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	if (list_empty(&dca_domains)) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return;
 	}
 
@@ -116,7 +117,7 @@ static void unregister_dca_providers(voi
 
 	dca_free_domain(domain);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) {
 		dca_sysfs_remove_provider(dca);
@@ -144,13 +145,8 @@ static struct dca_domain *dca_get_domain
 	domain = dca_find_domain(rc);
 
 	if (!domain) {
-		if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) {
+		if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains))
 			dca_providers_blocked = 1;
-		} else {
-			domain = dca_allocate_domain(rc);
-			if (domain)
-				list_add(&domain->node, &dca_domains);
-		}
 	}
 
 	return domain;
@@ -198,19 +194,19 @@ int dca_add_requester(struct device *dev
 	if (!dev)
 		return -EFAULT;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	/* check if the requester has not been added already */
 	dca = dca_find_provider_by_dev(dev);
 	if (dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -EEXIST;
 	}
 
 	pci_rc = dca_pci_rc_from_dev(dev);
 	domain = dca_find_domain(pci_rc);
 	if (!domain) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 
@@ -220,17 +216,17 @@ int dca_add_requester(struct device *dev
 			break;
 	}
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	if (slot < 0)
 		return slot;
 
 	err = dca_sysfs_add_req(dca, dev, slot);
 	if (err) {
-		spin_lock_irqsave(&dca_lock, flags);
+		raw_spin_lock_irqsave(&dca_lock, flags);
 		if (dca == dca_find_provider_by_dev(dev))
 			dca->ops->remove_requester(dca, dev);
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return err;
 	}
 
@@ -251,14 +247,14 @@ int dca_remove_requester(struct device *
 	if (!dev)
 		return -EFAULT;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	dca = dca_find_provider_by_dev(dev);
 	if (!dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 	slot = dca->ops->remove_requester(dca, dev);
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	if (slot < 0)
 		return slot;
@@ -280,16 +276,16 @@ u8 dca_common_get_tag(struct device *dev
 	u8 tag;
 	unsigned long flags;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	dca = dca_find_provider_by_dev(dev);
 	if (!dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 	tag = dca->ops->get_tag(dca, dev, cpu);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 	return tag;
 }
 
@@ -360,36 +356,51 @@ int register_dca_provider(struct dca_pro
 {
 	int err;
 	unsigned long flags;
-	struct dca_domain *domain;
+	struct dca_domain *domain, *newdomain = NULL;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	if (dca_providers_blocked) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	err = dca_sysfs_add_provider(dca, dev);
 	if (err)
 		return err;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	domain = dca_get_domain(dev);
 	if (!domain) {
+		struct pci_bus *rc;
+
 		if (dca_providers_blocked) {
-			spin_unlock_irqrestore(&dca_lock, flags);
+			raw_spin_unlock_irqrestore(&dca_lock, flags);
 			dca_sysfs_remove_provider(dca);
 			unregister_dca_providers();
-		} else {
-			spin_unlock_irqrestore(&dca_lock, flags);
+			return -ENODEV;
+		}
+
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
+		rc = dca_pci_rc_from_dev(dev);
+		newdomain = dca_allocate_domain(rc);
+		if (!newdomain)
+			return -ENODEV;
+		raw_spin_lock_irqsave(&dca_lock, flags);
+		/* Recheck, we might have raced after dropping the lock */
+		domain = dca_get_domain(dev);
+		if (!domain) {
+			domain = newdomain;
+			newdomain = NULL;
+			list_add(&domain->node, &dca_domains);
 		}
-		return -ENODEV;
 	}
 	list_add(&dca->node, &domain->dca_providers);
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_ADD, NULL);
+	kfree(newdomain);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(register_dca_provider);
@@ -407,7 +418,7 @@ void unregister_dca_provider(struct dca_
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_REMOVE, NULL);
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	list_del(&dca->node);
 
@@ -416,7 +427,7 @@ void unregister_dca_provider(struct dca_
 	if (list_empty(&domain->dca_providers))
 		dca_free_domain(domain);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	dca_sysfs_remove_provider(dca);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/dca/dca-sysfs.c linux-libre-3.2-gnu1/drivers/dca/dca-sysfs.c
--- linux-libre-3.1-gnu1/drivers/dca/dca-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dca/dca-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/dca.h>
 #include <linux/gfp.h>
+#include <linux/export.h>
 
 static struct class *dca_class;
 static struct idr dca_idr;
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/devfreq.c linux-libre-3.2-gnu1/drivers/devfreq/devfreq.c
--- linux-libre-3.1-gnu1/drivers/devfreq/devfreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/devfreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,607 @@
+/*
+ * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework
+ *	    for Non-CPU Devices.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/opp.h>
+#include <linux/devfreq.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/printk.h>
+#include <linux/hrtimer.h>
+#include "governor.h"
+
+struct class *devfreq_class;
+
+/*
+ * devfreq_work periodically monitors every registered device.
+ * The minimum polling interval is one jiffy. The polling interval is
+ * determined by the minimum polling period among all polling devfreq
+ * devices. The resolution of polling interval is one jiffy.
+ */
+static bool polling;
+static struct workqueue_struct *devfreq_wq;
+static struct delayed_work devfreq_work;
+
+/* wait removing if this is to be removed */
+static struct devfreq *wait_remove_device;
+
+/* The list of all device-devfreq */
+static LIST_HEAD(devfreq_list);
+static DEFINE_MUTEX(devfreq_list_lock);
+
+/**
+ * find_device_devfreq() - find devfreq struct using device pointer
+ * @dev:	device pointer used to lookup device devfreq.
+ *
+ * Search the list of device devfreqs and return the matched device's
+ * devfreq info. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq *find_device_devfreq(struct device *dev)
+{
+	struct devfreq *tmp_devfreq;
+
+	if (unlikely(IS_ERR_OR_NULL(dev))) {
+		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+	WARN(!mutex_is_locked(&devfreq_list_lock),
+	     "devfreq_list_lock must be locked.");
+
+	list_for_each_entry(tmp_devfreq, &devfreq_list, node) {
+		if (tmp_devfreq->dev.parent == dev)
+			return tmp_devfreq;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+/**
+ * update_devfreq() - Reevaluate the device and configure frequency.
+ * @devfreq:	the devfreq instance.
+ *
+ * Note: Lock devfreq->lock before calling update_devfreq
+ *	 This function is exported for governors.
+ */
+int update_devfreq(struct devfreq *devfreq)
+{
+	unsigned long freq;
+	int err = 0;
+
+	if (!mutex_is_locked(&devfreq->lock)) {
+		WARN(true, "devfreq->lock must be locked by the caller.\n");
+		return -EINVAL;
+	}
+
+	/* Reevaluate the proper frequency */
+	err = devfreq->governor->get_target_freq(devfreq, &freq);
+	if (err)
+		return err;
+
+	err = devfreq->profile->target(devfreq->dev.parent, &freq);
+	if (err)
+		return err;
+
+	devfreq->previous_freq = freq;
+	return err;
+}
+
+/**
+ * devfreq_notifier_call() - Notify that the device frequency requirements
+ *			   has been changed out of devfreq framework.
+ * @nb		the notifier_block (supposed to be devfreq->nb)
+ * @type	not used
+ * @devp	not used
+ *
+ * Called by a notifier that uses devfreq->nb.
+ */
+static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
+				 void *devp)
+{
+	struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
+	int ret;
+
+	mutex_lock(&devfreq->lock);
+	ret = update_devfreq(devfreq);
+	mutex_unlock(&devfreq->lock);
+
+	return ret;
+}
+
+/**
+ * _remove_devfreq() - Remove devfreq from the device.
+ * @devfreq:	the devfreq struct
+ * @skip:	skip calling device_unregister().
+ *
+ * Note that the caller should lock devfreq->lock before calling
+ * this. _remove_devfreq() will unlock it and free devfreq
+ * internally. devfreq_list_lock should be locked by the caller
+ * as well (not relased at return)
+ *
+ * Lock usage:
+ * devfreq->lock: locked before call.
+ *		  unlocked at return (and freed)
+ * devfreq_list_lock: locked before call.
+ *		      kept locked at return.
+ *		      if devfreq is centrally polled.
+ *
+ * Freed memory:
+ * devfreq
+ */
+static void _remove_devfreq(struct devfreq *devfreq, bool skip)
+{
+	if (!mutex_is_locked(&devfreq->lock)) {
+		WARN(true, "devfreq->lock must be locked by the caller.\n");
+		return;
+	}
+	if (!devfreq->governor->no_central_polling &&
+	    !mutex_is_locked(&devfreq_list_lock)) {
+		WARN(true, "devfreq_list_lock must be locked by the caller.\n");
+		return;
+	}
+
+	if (devfreq->being_removed)
+		return;
+
+	devfreq->being_removed = true;
+
+	if (devfreq->profile->exit)
+		devfreq->profile->exit(devfreq->dev.parent);
+
+	if (devfreq->governor->exit)
+		devfreq->governor->exit(devfreq);
+
+	if (!skip && get_device(&devfreq->dev)) {
+		device_unregister(&devfreq->dev);
+		put_device(&devfreq->dev);
+	}
+
+	if (!devfreq->governor->no_central_polling)
+		list_del(&devfreq->node);
+
+	mutex_unlock(&devfreq->lock);
+	mutex_destroy(&devfreq->lock);
+
+	kfree(devfreq);
+}
+
+/**
+ * devfreq_dev_release() - Callback for struct device to release the device.
+ * @dev:	the devfreq device
+ *
+ * This calls _remove_devfreq() if _remove_devfreq() is not called.
+ * Note that devfreq_dev_release() could be called by _remove_devfreq() as
+ * well as by others unregistering the device.
+ */
+static void devfreq_dev_release(struct device *dev)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	bool central_polling = !devfreq->governor->no_central_polling;
+
+	/*
+	 * If devfreq_dev_release() was called by device_unregister() of
+	 * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
+	 * being_removed is already set. This also partially checks the case
+	 * where devfreq_dev_release() is called from a thread other than
+	 * the one called _remove_devfreq(); however, this case is
+	 * dealt completely with another following being_removed check.
+	 *
+	 * Because being_removed is never being
+	 * unset, we do not need to worry about race conditions on
+	 * being_removed.
+	 */
+	if (devfreq->being_removed)
+		return;
+
+	if (central_polling)
+		mutex_lock(&devfreq_list_lock);
+
+	mutex_lock(&devfreq->lock);
+
+	/*
+	 * Check being_removed flag again for the case where
+	 * devfreq_dev_release() was called in a thread other than the one
+	 * possibly called _remove_devfreq().
+	 */
+	if (devfreq->being_removed) {
+		mutex_unlock(&devfreq->lock);
+		goto out;
+	}
+
+	/* devfreq->lock is unlocked and removed in _removed_devfreq() */
+	_remove_devfreq(devfreq, true);
+
+out:
+	if (central_polling)
+		mutex_unlock(&devfreq_list_lock);
+}
+
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work: the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+	static unsigned long last_polled_at;
+	struct devfreq *devfreq, *tmp;
+	int error;
+	unsigned long jiffies_passed;
+	unsigned long next_jiffies = ULONG_MAX, now = jiffies;
+	struct device *dev;
+
+	/* Initially last_polled_at = 0, polling every device at bootup */
+	jiffies_passed = now - last_polled_at;
+	last_polled_at = now;
+	if (jiffies_passed == 0)
+		jiffies_passed = 1;
+
+	mutex_lock(&devfreq_list_lock);
+	list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
+		mutex_lock(&devfreq->lock);
+		dev = devfreq->dev.parent;
+
+		/* Do not remove tmp for a while */
+		wait_remove_device = tmp;
+
+		if (devfreq->governor->no_central_polling ||
+		    devfreq->next_polling == 0) {
+			mutex_unlock(&devfreq->lock);
+			continue;
+		}
+		mutex_unlock(&devfreq_list_lock);
+
+		/*
+		 * Reduce more next_polling if devfreq_wq took an extra
+		 * delay. (i.e., CPU has been idled.)
+		 */
+		if (devfreq->next_polling <= jiffies_passed) {
+			error = update_devfreq(devfreq);
+
+			/* Remove a devfreq with an error. */
+			if (error && error != -EAGAIN) {
+
+				dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
+					error, devfreq->governor->name);
+
+				/*
+				 * Unlock devfreq before locking the list
+				 * in order to avoid deadlock with
+				 * find_device_devfreq or others
+				 */
+				mutex_unlock(&devfreq->lock);
+				mutex_lock(&devfreq_list_lock);
+				/* Check if devfreq is already removed */
+				if (IS_ERR(find_device_devfreq(dev)))
+					continue;
+				mutex_lock(&devfreq->lock);
+				/* This unlocks devfreq->lock and free it */
+				_remove_devfreq(devfreq, false);
+				continue;
+			}
+			devfreq->next_polling = devfreq->polling_jiffies;
+		} else {
+			devfreq->next_polling -= jiffies_passed;
+		}
+
+		if (devfreq->next_polling)
+			next_jiffies = (next_jiffies > devfreq->next_polling) ?
+					devfreq->next_polling : next_jiffies;
+
+		mutex_unlock(&devfreq->lock);
+		mutex_lock(&devfreq_list_lock);
+	}
+	wait_remove_device = NULL;
+	mutex_unlock(&devfreq_list_lock);
+
+	if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
+	} else {
+		polling = false;
+	}
+}
+
+/**
+ * devfreq_add_device() - Add devfreq feature to the device
+ * @dev:	the device to add devfreq feature.
+ * @profile:	device-specific profile to run devfreq.
+ * @governor:	the policy to choose frequency.
+ * @data:	private data for the governor. The devfreq framework does not
+ *		touch this value.
+ */
+struct devfreq *devfreq_add_device(struct device *dev,
+				   struct devfreq_dev_profile *profile,
+				   const struct devfreq_governor *governor,
+				   void *data)
+{
+	struct devfreq *devfreq;
+	int err = 0;
+
+	if (!dev || !profile || !governor) {
+		dev_err(dev, "%s: Invalid parameters.\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+
+	if (!governor->no_central_polling) {
+		mutex_lock(&devfreq_list_lock);
+		devfreq = find_device_devfreq(dev);
+		mutex_unlock(&devfreq_list_lock);
+		if (!IS_ERR(devfreq)) {
+			dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
+	devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
+	if (!devfreq) {
+		dev_err(dev, "%s: Unable to create devfreq for the device\n",
+			__func__);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	mutex_init(&devfreq->lock);
+	mutex_lock(&devfreq->lock);
+	devfreq->dev.parent = dev;
+	devfreq->dev.class = devfreq_class;
+	devfreq->dev.release = devfreq_dev_release;
+	devfreq->profile = profile;
+	devfreq->governor = governor;
+	devfreq->previous_freq = profile->initial_freq;
+	devfreq->data = data;
+	devfreq->next_polling = devfreq->polling_jiffies
+			      = msecs_to_jiffies(devfreq->profile->polling_ms);
+	devfreq->nb.notifier_call = devfreq_notifier_call;
+
+	dev_set_name(&devfreq->dev, dev_name(dev));
+	err = device_register(&devfreq->dev);
+	if (err) {
+		put_device(&devfreq->dev);
+		goto err_dev;
+	}
+
+	if (governor->init)
+		err = governor->init(devfreq);
+	if (err)
+		goto err_init;
+
+	mutex_unlock(&devfreq->lock);
+
+	if (governor->no_central_polling)
+		goto out;
+
+	mutex_lock(&devfreq_list_lock);
+
+	list_add(&devfreq->node, &devfreq_list);
+
+	if (devfreq_wq && devfreq->next_polling && !polling) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work,
+				   devfreq->next_polling);
+	}
+	mutex_unlock(&devfreq_list_lock);
+	goto out;
+err_init:
+	device_unregister(&devfreq->dev);
+err_dev:
+	mutex_unlock(&devfreq->lock);
+	kfree(devfreq);
+out:
+	if (err)
+		return ERR_PTR(err);
+	else
+		return devfreq;
+}
+
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @devfreq	the devfreq instance to be removed
+ */
+int devfreq_remove_device(struct devfreq *devfreq)
+{
+	bool central_polling;
+
+	if (!devfreq)
+		return -EINVAL;
+
+	central_polling = !devfreq->governor->no_central_polling;
+
+	if (central_polling) {
+		mutex_lock(&devfreq_list_lock);
+		while (wait_remove_device == devfreq) {
+			mutex_unlock(&devfreq_list_lock);
+			schedule();
+			mutex_lock(&devfreq_list_lock);
+		}
+	}
+
+	mutex_lock(&devfreq->lock);
+	_remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+
+	if (central_polling)
+		mutex_unlock(&devfreq_list_lock);
+
+	return 0;
+}
+
+static ssize_t show_governor(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
+}
+
+static ssize_t show_freq(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
+}
+
+static ssize_t show_polling_interval(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
+}
+
+static ssize_t store_polling_interval(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct devfreq *df = to_devfreq(dev);
+	unsigned int value;
+	int ret;
+
+	ret = sscanf(buf, "%u", &value);
+	if (ret != 1)
+		goto out;
+
+	mutex_lock(&df->lock);
+	df->profile->polling_ms = value;
+	df->next_polling = df->polling_jiffies
+			 = msecs_to_jiffies(value);
+	mutex_unlock(&df->lock);
+
+	ret = count;
+
+	if (df->governor->no_central_polling)
+		goto out;
+
+	mutex_lock(&devfreq_list_lock);
+	if (df->next_polling > 0 && !polling) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work,
+				   df->next_polling);
+	}
+	mutex_unlock(&devfreq_list_lock);
+out:
+	return ret;
+}
+
+static ssize_t show_central_polling(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",
+		       !to_devfreq(dev)->governor->no_central_polling);
+}
+
+static struct device_attribute devfreq_attrs[] = {
+	__ATTR(governor, S_IRUGO, show_governor, NULL),
+	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
+	__ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+	__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
+	       store_polling_interval),
+	{ },
+};
+
+/**
+ * devfreq_start_polling() - Initialize data structure for devfreq framework and
+ *			   start polling registered devfreq devices.
+ */
+static int __init devfreq_start_polling(void)
+{
+	mutex_lock(&devfreq_list_lock);
+	polling = false;
+	devfreq_wq = create_freezable_workqueue("devfreq_wq");
+	INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
+	mutex_unlock(&devfreq_list_lock);
+
+	devfreq_monitor(&devfreq_work.work);
+	return 0;
+}
+late_initcall(devfreq_start_polling);
+
+static int __init devfreq_init(void)
+{
+	devfreq_class = class_create(THIS_MODULE, "devfreq");
+	if (IS_ERR(devfreq_class)) {
+		pr_err("%s: couldn't create class\n", __FILE__);
+		return PTR_ERR(devfreq_class);
+	}
+	devfreq_class->dev_attrs = devfreq_attrs;
+	return 0;
+}
+subsys_initcall(devfreq_init);
+
+static void __exit devfreq_exit(void)
+{
+	class_destroy(devfreq_class);
+}
+module_exit(devfreq_exit);
+
+/*
+ * The followings are helper functions for devfreq user device drivers with
+ * OPP framework.
+ */
+
+/**
+ * devfreq_recommended_opp() - Helper function to get proper OPP for the
+ *			     freq value given to target callback.
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @freq	The frequency given to target function
+ *
+ */
+struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
+{
+	struct opp *opp = opp_find_freq_ceil(dev, freq);
+
+	if (opp == ERR_PTR(-ENODEV))
+		opp = opp_find_freq_floor(dev, freq);
+	return opp;
+}
+
+/**
+ * devfreq_register_opp_notifier() - Helper function to get devfreq notified
+ *				   for any changes in the OPP availability
+ *				   changes
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @devfreq	The devfreq object.
+ */
+int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+	struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+	if (IS_ERR(nh))
+		return PTR_ERR(nh);
+	return srcu_notifier_chain_register(nh, &devfreq->nb);
+}
+
+/**
+ * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
+ *				     notified for any changes in the OPP
+ *				     availability changes anymore.
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @devfreq	The devfreq object.
+ *
+ * At exit() callback of devfreq_dev_profile, this must be included if
+ * devfreq_recommended_opp is used.
+ */
+int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+	struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+	if (IS_ERR(nh))
+		return PTR_ERR(nh);
+	return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+}
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("devfreq class support");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/governor.h linux-libre-3.2-gnu1/drivers/devfreq/governor.h
--- linux-libre-3.1-gnu1/drivers/devfreq/governor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/governor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * governor.h - internal header for devfreq governors.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ *
+ * This header is for devfreq governors in drivers/devfreq/
+ */
+
+#ifndef _GOVERNOR_H
+#define _GOVERNOR_H
+
+#include <linux/devfreq.h>
+
+#define to_devfreq(DEV)	container_of((DEV), struct devfreq, dev)
+
+/* Caution: devfreq->lock must be locked before calling update_devfreq */
+extern int update_devfreq(struct devfreq *devfreq);
+
+#endif /* _GOVERNOR_H */
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/governor_performance.c linux-libre-3.2-gnu1/drivers/devfreq/governor_performance.c
--- linux-libre-3.1-gnu1/drivers/devfreq/governor_performance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/governor_performance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ *  linux/drivers/devfreq/governor_performance.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/devfreq.h>
+
+static int devfreq_performance_func(struct devfreq *df,
+				    unsigned long *freq)
+{
+	/*
+	 * target callback should be able to get floor value as
+	 * said in devfreq.h
+	 */
+	*freq = UINT_MAX;
+	return 0;
+}
+
+const struct devfreq_governor devfreq_performance = {
+	.name = "performance",
+	.get_target_freq = devfreq_performance_func,
+	.no_central_polling = true,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/governor_powersave.c linux-libre-3.2-gnu1/drivers/devfreq/governor_powersave.c
--- linux-libre-3.1-gnu1/drivers/devfreq/governor_powersave.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/governor_powersave.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ *  linux/drivers/devfreq/governor_powersave.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/devfreq.h>
+
+static int devfreq_powersave_func(struct devfreq *df,
+				  unsigned long *freq)
+{
+	/*
+	 * target callback should be able to get ceiling value as
+	 * said in devfreq.h
+	 */
+	*freq = 0;
+	return 0;
+}
+
+const struct devfreq_governor devfreq_powersave = {
+	.name = "powersave",
+	.get_target_freq = devfreq_powersave_func,
+	.no_central_polling = true,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/governor_simpleondemand.c linux-libre-3.2-gnu1/drivers/devfreq/governor_simpleondemand.c
--- linux-libre-3.1-gnu1/drivers/devfreq/governor_simpleondemand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/governor_simpleondemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ *  linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/devfreq.h>
+#include <linux/math64.h>
+
+/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
+#define DFSO_UPTHRESHOLD	(90)
+#define DFSO_DOWNDIFFERENCTIAL	(5)
+static int devfreq_simple_ondemand_func(struct devfreq *df,
+					unsigned long *freq)
+{
+	struct devfreq_dev_status stat;
+	int err = df->profile->get_dev_status(df->dev.parent, &stat);
+	unsigned long long a, b;
+	unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
+	unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
+	struct devfreq_simple_ondemand_data *data = df->data;
+
+	if (err)
+		return err;
+
+	if (data) {
+		if (data->upthreshold)
+			dfso_upthreshold = data->upthreshold;
+		if (data->downdifferential)
+			dfso_downdifferential = data->downdifferential;
+	}
+	if (dfso_upthreshold > 100 ||
+	    dfso_upthreshold < dfso_downdifferential)
+		return -EINVAL;
+
+	/* Assume MAX if it is going to be divided by zero */
+	if (stat.total_time == 0) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Prevent overflow */
+	if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
+		stat.busy_time >>= 7;
+		stat.total_time >>= 7;
+	}
+
+	/* Set MAX if it's busy enough */
+	if (stat.busy_time * 100 >
+	    stat.total_time * dfso_upthreshold) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Set MAX if we do not know the initial frequency */
+	if (stat.current_frequency == 0) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Keep the current frequency */
+	if (stat.busy_time * 100 >
+	    stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
+		*freq = stat.current_frequency;
+		return 0;
+	}
+
+	/* Set the desired frequency based on the load */
+	a = stat.busy_time;
+	a *= stat.current_frequency;
+	b = div_u64(a, stat.total_time);
+	b *= 100;
+	b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
+	*freq = (unsigned long) b;
+
+	return 0;
+}
+
+const struct devfreq_governor devfreq_simple_ondemand = {
+	.name = "simple_ondemand",
+	.get_target_freq = devfreq_simple_ondemand_func,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/governor_userspace.c linux-libre-3.2-gnu1/drivers/devfreq/governor_userspace.c
--- linux-libre-3.1-gnu1/drivers/devfreq/governor_userspace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/governor_userspace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/*
+ *  linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	MyungJoo Ham <myungjoo.ham@samsung.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/devfreq.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include "governor.h"
+
+struct userspace_data {
+	unsigned long user_frequency;
+	bool valid;
+};
+
+static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
+{
+	struct userspace_data *data = df->data;
+
+	if (!data->valid)
+		*freq = df->previous_freq; /* No user freq specified yet */
+	else
+		*freq = data->user_frequency;
+	return 0;
+}
+
+static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	struct userspace_data *data;
+	unsigned long wanted;
+	int err = 0;
+
+
+	mutex_lock(&devfreq->lock);
+	data = devfreq->data;
+
+	sscanf(buf, "%lu", &wanted);
+	data->user_frequency = wanted;
+	data->valid = true;
+	err = update_devfreq(devfreq);
+	if (err == 0)
+		err = count;
+	mutex_unlock(&devfreq->lock);
+	return err;
+}
+
+static ssize_t show_freq(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	struct userspace_data *data;
+	int err = 0;
+
+	mutex_lock(&devfreq->lock);
+	data = devfreq->data;
+
+	if (data->valid)
+		err = sprintf(buf, "%lu\n", data->user_frequency);
+	else
+		err = sprintf(buf, "undefined\n");
+	mutex_unlock(&devfreq->lock);
+	return err;
+}
+
+static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq);
+static struct attribute *dev_entries[] = {
+	&dev_attr_set_freq.attr,
+	NULL,
+};
+static struct attribute_group dev_attr_group = {
+	.name	= "userspace",
+	.attrs	= dev_entries,
+};
+
+static int userspace_init(struct devfreq *devfreq)
+{
+	int err = 0;
+	struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
+					      GFP_KERNEL);
+
+	if (!data) {
+		err = -ENOMEM;
+		goto out;
+	}
+	data->valid = false;
+	devfreq->data = data;
+
+	err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
+out:
+	return err;
+}
+
+static void userspace_exit(struct devfreq *devfreq)
+{
+	sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
+	kfree(devfreq->data);
+	devfreq->data = NULL;
+}
+
+const struct devfreq_governor devfreq_userspace = {
+	.name = "userspace",
+	.get_target_freq = devfreq_userspace_func,
+	.init = userspace_init,
+	.exit = userspace_exit,
+	.no_central_polling = true,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/Kconfig linux-libre-3.2-gnu1/drivers/devfreq/Kconfig
--- linux-libre-3.1-gnu1/drivers/devfreq/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,68 @@
+menuconfig PM_DEVFREQ
+	bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support"
+	help
+	  A device may have a list of frequencies and voltages available.
+	  devfreq, a generic DVFS framework can be registered for a device
+	  in order to let the governor provided to devfreq choose an
+	  operating frequency based on the device driver's policy.
+
+	  Each device may have its own governor and policy. Devfreq can
+	  reevaluate the device state periodically and/or based on the
+	  notification to "nb", a notifier block, of devfreq.
+
+	  Like some CPUs with CPUfreq, a device may have multiple clocks.
+	  However, because the clock frequencies of a single device are
+	  determined by the single device's state, an instance of devfreq
+	  is attached to a single device and returns a "representative"
+	  clock frequency of the device, which is also attached
+	  to a device by 1-to-1. The device registering devfreq takes the
+	  responsiblity to "interpret" the representative frequency and
+	  to set its every clock accordingly with the "target" callback
+	  given to devfreq.
+
+	  When OPP is used with the devfreq device, it is recommended to
+	  register devfreq's nb to the OPP's notifier head.  If OPP is
+	  used with the devfreq device, you may use OPP helper
+	  functions defined in devfreq.h.
+
+if PM_DEVFREQ
+
+comment "DEVFREQ Governors"
+
+config DEVFREQ_GOV_SIMPLE_ONDEMAND
+	bool "Simple Ondemand"
+	help
+	  Chooses frequency based on the recent load on the device. Works
+	  similar as ONDEMAND governor of CPUFREQ does. A device with
+	  Simple-Ondemand should be able to provide busy/total counter
+	  values that imply the usage rate. A device may provide tuned
+	  values to the governor with data field at devfreq_add_device().
+
+config DEVFREQ_GOV_PERFORMANCE
+	bool "Performance"
+	help
+	  Sets the frequency at the maximum available frequency.
+	  This governor always returns UINT_MAX as frequency so that
+	  the DEVFREQ framework returns the highest frequency available
+	  at any time.
+
+config DEVFREQ_GOV_POWERSAVE
+	bool "Powersave"
+	help
+	  Sets the frequency at the minimum available frequency.
+	  This governor always returns 0 as frequency so that
+	  the DEVFREQ framework returns the lowest frequency available
+	  at any time.
+
+config DEVFREQ_GOV_USERSPACE
+	bool "Userspace"
+	help
+	  Sets the frequency at the user specified one.
+	  This governor returns the user configured frequency if there
+	  has been an input to /sys/devices/.../power/devfreq_set_freq.
+	  Otherwise, the governor does not change the frequnecy
+	  given at the initialization.
+
+comment "DEVFREQ Drivers"
+
+endif # PM_DEVFREQ
diff -druNp linux-libre-3.1-gnu1/drivers/devfreq/Makefile linux-libre-3.2-gnu1/drivers/devfreq/Makefile
--- linux-libre-3.1-gnu1/drivers/devfreq/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/devfreq/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PM_DEVFREQ)	+= devfreq.o
+obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)	+= governor_simpleondemand.o
+obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE)	+= governor_performance.o
+obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE)	+= governor_powersave.o
+obj-$(CONFIG_DEVFREQ_GOV_USERSPACE)	+= governor_userspace.o
diff -druNp linux-libre-3.1-gnu1/drivers/dma/amba-pl08x.c linux-libre-3.2-gnu1/drivers/dma/amba-pl08x.c
--- linux-libre-3.1-gnu1/drivers/dma/amba-pl08x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/amba-pl08x.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,32 +66,29 @@
  *    after the final transfer signalled by LBREQ or LSREQ.  The DMAC
  *    will then move to the next LLI entry.
  *
- * Only the former works sanely with scatter lists, so we only implement
- * the DMAC flow control method.  However, peripherals which use the LBREQ
- * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
- * these hardware restrictions prevents them from using scatter DMA.
- *
  * Global TODO:
  * - Break out common code from arch/arm/mach-s3c64xx and share
  */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
-
+#include <linux/slab.h>
 #include <asm/hardware/pl080.h>
 
 #define DRIVER_NAME	"pl08xdmac"
 
+static struct amba_driver pl08x_amba_driver;
+
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
@@ -126,7 +123,8 @@ struct pl08x_lli {
  * @phy_chans: array of data for the physical channels
  * @pool: a pool for the LLI descriptors
  * @pool_ctr: counter of LLIs in the pool
- * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches
+ * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
+ * fetches
  * @mem_buses: set to indicate memory transfers on AHB2.
  * @lock: a spinlock for this struct
  */
@@ -149,14 +147,6 @@ struct pl08x_driver_data {
  * PL08X specific defines
  */
 
-/*
- * Memory boundaries: the manual for PL08x says that the controller
- * cannot read past a 1KiB boundary, so these defines are used to
- * create transfer LLIs that do not cross such boundaries.
- */
-#define PL08X_BOUNDARY_SHIFT		(10)	/* 1KB 0x400 */
-#define PL08X_BOUNDARY_SIZE		(1 << PL08X_BOUNDARY_SHIFT)
-
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE	0x2000
 
@@ -272,7 +262,6 @@ static void pl08x_resume_phy_chan(struct
 	writel(val, ch->base + PL080_CH_CONFIG);
 }
 
-
 /*
  * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
  * clears any pending interrupt status.  This should not be used for
@@ -363,7 +352,9 @@ static u32 pl08x_getbytes_chan(struct pl
 	if (!list_empty(&plchan->pend_list)) {
 		struct pl08x_txd *txdi;
 		list_for_each_entry(txdi, &plchan->pend_list, node) {
-			bytes += txdi->len;
+			struct pl08x_sg *dsg;
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				bytes += dsg->len;
 		}
 	}
 
@@ -407,6 +398,7 @@ pl08x_get_phy_channel(struct pl08x_drive
 		return NULL;
 	}
 
+	pm_runtime_get_sync(&pl08x->adev->dev);
 	return ch;
 }
 
@@ -420,6 +412,8 @@ static inline void pl08x_put_phy_channel
 	/* Stop the channel and clear its interrupts */
 	pl08x_terminate_phy_chan(pl08x, ch);
 
+	pm_runtime_put(&pl08x->adev->dev);
+
 	/* Mark it as free */
 	ch->serving = NULL;
 	spin_unlock_irqrestore(&ch->lock, flags);
@@ -499,36 +493,30 @@ struct pl08x_lli_build_data {
 };
 
 /*
- * Autoselect a master bus to use for the transfer this prefers the
- * destination bus if both available if fixed address on one bus the
- * other will be chosen
+ * Autoselect a master bus to use for the transfer. Slave will be the chosen as
+ * victim in case src & dest are not similarly aligned. i.e. If after aligning
+ * masters address with width requirements of transfer (by sending few byte by
+ * byte data), slave is still not aligned, then its width will be reduced to
+ * BYTE.
+ * - prefers the destination bus if both available
+ * - prefers bus with fixed address (i.e. peripheral)
  */
 static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
 	struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
 {
 	if (!(cctl & PL080_CONTROL_DST_INCR)) {
-		*mbus = &bd->srcbus;
-		*sbus = &bd->dstbus;
-	} else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
 		*mbus = &bd->dstbus;
 		*sbus = &bd->srcbus;
+	} else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
+		*mbus = &bd->srcbus;
+		*sbus = &bd->dstbus;
 	} else {
-		if (bd->dstbus.buswidth == 4) {
-			*mbus = &bd->dstbus;
-			*sbus = &bd->srcbus;
-		} else if (bd->srcbus.buswidth == 4) {
-			*mbus = &bd->srcbus;
-			*sbus = &bd->dstbus;
-		} else if (bd->dstbus.buswidth == 2) {
+		if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
 			*mbus = &bd->dstbus;
 			*sbus = &bd->srcbus;
-		} else if (bd->srcbus.buswidth == 2) {
+		} else {
 			*mbus = &bd->srcbus;
 			*sbus = &bd->dstbus;
-		} else {
-			/* bd->srcbus.buswidth == 1 */
-			*mbus = &bd->dstbus;
-			*sbus = &bd->srcbus;
 		}
 	}
 }
@@ -547,7 +535,8 @@ static void pl08x_fill_lli_for_desc(stru
 	llis_va[num_llis].cctl = cctl;
 	llis_va[num_llis].src = bd->srcbus.addr;
 	llis_va[num_llis].dst = bd->dstbus.addr;
-	llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
+	llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
+		sizeof(struct pl08x_lli);
 	llis_va[num_llis].lli |= bd->lli_bus;
 
 	if (cctl & PL080_CONTROL_SRC_INCR)
@@ -560,16 +549,12 @@ static void pl08x_fill_lli_for_desc(stru
 	bd->remainder -= len;
 }
 
-/*
- * Return number of bytes to fill to boundary, or len.
- * This calculation works for any value of addr.
- */
-static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
+static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
+		u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
 {
-	size_t boundary_len = PL08X_BOUNDARY_SIZE -
-			(addr & (PL08X_BOUNDARY_SIZE - 1));
-
-	return min(boundary_len, len);
+	*cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
+	pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
+	(*total_bytes) += len;
 }
 
 /*
@@ -583,13 +568,12 @@ static int pl08x_fill_llis_for_desc(stru
 	struct pl08x_bus_data *mbus, *sbus;
 	struct pl08x_lli_build_data bd;
 	int num_llis = 0;
-	u32 cctl;
-	size_t max_bytes_per_lli;
-	size_t total_bytes = 0;
+	u32 cctl, early_bytes = 0;
+	size_t max_bytes_per_lli, total_bytes;
 	struct pl08x_lli *llis_va;
+	struct pl08x_sg *dsg;
 
-	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
-				      &txd->llis_bus);
+	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
 	if (!txd->llis_va) {
 		dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
 		return 0;
@@ -597,13 +581,9 @@ static int pl08x_fill_llis_for_desc(stru
 
 	pl08x->pool_ctr++;
 
-	/* Get the default CCTL */
-	cctl = txd->cctl;
-
 	bd.txd = txd;
-	bd.srcbus.addr = txd->src_addr;
-	bd.dstbus.addr = txd->dst_addr;
 	bd.lli_bus = (pl08x->lli_buses & PL08X_AHB2) ? PL080_LLI_LM_AHB2 : 0;
+	cctl = txd->cctl;
 
 	/* Find maximum width of the source bus */
 	bd.srcbus.maxwidth =
@@ -615,215 +595,179 @@ static int pl08x_fill_llis_for_desc(stru
 		pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
 				       PL080_CONTROL_DWIDTH_SHIFT);
 
-	/* Set up the bus widths to the maximum */
-	bd.srcbus.buswidth = bd.srcbus.maxwidth;
-	bd.dstbus.buswidth = bd.dstbus.maxwidth;
-
-	/*
-	 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
-	 */
-	max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
-		PL080_CONTROL_TRANSFER_SIZE_MASK;
-
-	/* We need to count this down to zero */
-	bd.remainder = txd->len;
+	list_for_each_entry(dsg, &txd->dsg_list, node) {
+		total_bytes = 0;
+		cctl = txd->cctl;
 
-	/*
-	 * Choose bus to align to
-	 * - prefers destination bus if both available
-	 * - if fixed address on one bus chooses other
-	 */
-	pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
+		bd.srcbus.addr = dsg->src_addr;
+		bd.dstbus.addr = dsg->dst_addr;
+		bd.remainder = dsg->len;
+		bd.srcbus.buswidth = bd.srcbus.maxwidth;
+		bd.dstbus.buswidth = bd.dstbus.maxwidth;
 
-	dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n",
-		 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
-		 bd.srcbus.buswidth,
-		 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
-		 bd.dstbus.buswidth,
-		 bd.remainder, max_bytes_per_lli);
-	dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
-		 mbus == &bd.srcbus ? "src" : "dst",
-		 sbus == &bd.srcbus ? "src" : "dst");
+		pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
-	if (txd->len < mbus->buswidth) {
-		/* Less than a bus width available - send as single bytes */
-		while (bd.remainder) {
-			dev_vdbg(&pl08x->adev->dev,
-				 "%s single byte LLIs for a transfer of "
-				 "less than a bus width (remain 0x%08x)\n",
-				 __func__, bd.remainder);
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
-		}
-	} else {
-		/* Make one byte LLIs until master bus is aligned */
-		while ((mbus->addr) % (mbus->buswidth)) {
-			dev_vdbg(&pl08x->adev->dev,
-				"%s adjustment lli for less than bus width "
-				 "(remain 0x%08x)\n",
-				 __func__, bd.remainder);
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
-		}
+		dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
+			bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
+			bd.srcbus.buswidth,
+			bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
+			bd.dstbus.buswidth,
+			bd.remainder);
+		dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
+			mbus == &bd.srcbus ? "src" : "dst",
+			sbus == &bd.srcbus ? "src" : "dst");
 
 		/*
-		 * Master now aligned
-		 * - if slave is not then we must set its width down
+		 * Zero length is only allowed if all these requirements are
+		 * met:
+		 * - flow controller is peripheral.
+		 * - src.addr is aligned to src.width
+		 * - dst.addr is aligned to dst.width
+		 *
+		 * sg_len == 1 should be true, as there can be two cases here:
+		 *
+		 * - Memory addresses are contiguous and are not scattered.
+		 *   Here, Only one sg will be passed by user driver, with
+		 *   memory address and zero length. We pass this to controller
+		 *   and after the transfer it will receive the last burst
+		 *   request from peripheral and so transfer finishes.
+		 *
+		 * - Memory addresses are scattered and are not contiguous.
+		 *   Here, Obviously as DMA controller doesn't know when a lli's
+		 *   transfer gets over, it can't load next lli. So in this
+		 *   case, there has to be an assumption that only one lli is
+		 *   supported. Thus, we can't have scattered addresses.
 		 */
-		if (sbus->addr % sbus->buswidth) {
-			dev_dbg(&pl08x->adev->dev,
-				"%s set down bus width to one byte\n",
-				 __func__);
+		if (!bd.remainder) {
+			u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
+				PL080_CONFIG_FLOW_CONTROL_SHIFT;
+			if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
+					(fc <= PL080_FLOW_SRC2DST_SRC))) {
+				dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
+					__func__);
+				return 0;
+			}
 
-			sbus->buswidth = 1;
+			if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
+					(bd.srcbus.addr % bd.srcbus.buswidth)) {
+				dev_err(&pl08x->adev->dev,
+					"%s src & dst address must be aligned to src"
+					" & dst width if peripheral is flow controller",
+					__func__);
+				return 0;
+			}
+
+			cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+					bd.dstbus.buswidth, 0);
+			pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
+			break;
 		}
 
 		/*
-		 * Make largest possible LLIs until less than one bus
-		 * width left
+		 * Send byte by byte for following cases
+		 * - Less than a bus width available
+		 * - until master bus is aligned
 		 */
-		while (bd.remainder > (mbus->buswidth - 1)) {
-			size_t lli_len, target_len, tsize, odd_bytes;
+		if (bd.remainder < mbus->buswidth)
+			early_bytes = bd.remainder;
+		else if ((mbus->addr) % (mbus->buswidth)) {
+			early_bytes = mbus->buswidth - (mbus->addr) %
+				(mbus->buswidth);
+			if ((bd.remainder - early_bytes) < mbus->buswidth)
+				early_bytes = bd.remainder;
+		}
 
-			/*
-			 * If enough left try to send max possible,
-			 * otherwise try to send the remainder
-			 */
-			target_len = min(bd.remainder, max_bytes_per_lli);
+		if (early_bytes) {
+			dev_vdbg(&pl08x->adev->dev,
+				"%s byte width LLIs (remain 0x%08x)\n",
+				__func__, bd.remainder);
+			prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
+				&total_bytes);
+		}
 
+		if (bd.remainder) {
 			/*
-			 * Set bus lengths for incrementing buses to the
-			 * number of bytes which fill to next memory boundary,
-			 * limiting on the target length calculated above.
+			 * Master now aligned
+			 * - if slave is not then we must set its width down
 			 */
-			if (cctl & PL080_CONTROL_SRC_INCR)
-				bd.srcbus.fill_bytes =
-					pl08x_pre_boundary(bd.srcbus.addr,
-						target_len);
-			else
-				bd.srcbus.fill_bytes = target_len;
-
-			if (cctl & PL080_CONTROL_DST_INCR)
-				bd.dstbus.fill_bytes =
-					pl08x_pre_boundary(bd.dstbus.addr,
-						target_len);
-			else
-				bd.dstbus.fill_bytes = target_len;
+			if (sbus->addr % sbus->buswidth) {
+				dev_dbg(&pl08x->adev->dev,
+					"%s set down bus width to one byte\n",
+					__func__);
 
-			/* Find the nearest */
-			lli_len	= min(bd.srcbus.fill_bytes,
-				      bd.dstbus.fill_bytes);
+				sbus->buswidth = 1;
+			}
 
-			BUG_ON(lli_len > bd.remainder);
+			/*
+			 * Bytes transferred = tsize * src width, not
+			 * MIN(buswidths)
+			 */
+			max_bytes_per_lli = bd.srcbus.buswidth *
+				PL080_CONTROL_TRANSFER_SIZE_MASK;
+			dev_vdbg(&pl08x->adev->dev,
+				"%s max bytes per lli = %zu\n",
+				__func__, max_bytes_per_lli);
 
-			if (lli_len <= 0) {
-				dev_err(&pl08x->adev->dev,
-					"%s lli_len is %zu, <= 0\n",
-						__func__, lli_len);
-				return 0;
-			}
+			/*
+			 * Make largest possible LLIs until less than one bus
+			 * width left
+			 */
+			while (bd.remainder > (mbus->buswidth - 1)) {
+				size_t lli_len, tsize, width;
 
-			if (lli_len == target_len) {
-				/*
-				 * Can send what we wanted.
-				 * Maintain alignment
-				 */
-				lli_len	= (lli_len/mbus->buswidth) *
-							mbus->buswidth;
-				odd_bytes = 0;
-			} else {
 				/*
-				 * So now we know how many bytes to transfer
-				 * to get to the nearest boundary.  The next
-				 * LLI will past the boundary.  However, we
-				 * may be working to a boundary on the slave
-				 * bus.  We need to ensure the master stays
-				 * aligned, and that we are working in
-				 * multiples of the bus widths.
+				 * If enough left try to send max possible,
+				 * otherwise try to send the remainder
 				 */
-				odd_bytes = lli_len % mbus->buswidth;
-				lli_len -= odd_bytes;
-
-			}
+				lli_len = min(bd.remainder, max_bytes_per_lli);
 
-			if (lli_len) {
 				/*
-				 * Check against minimum bus alignment:
-				 * Calculate actual transfer size in relation
-				 * to bus width an get a maximum remainder of
-				 * the smallest bus width - 1
+				 * Check against maximum bus alignment:
+				 * Calculate actual transfer size in relation to
+				 * bus width an get a maximum remainder of the
+				 * highest bus width - 1
 				 */
-				/* FIXME: use round_down()? */
-				tsize = lli_len / min(mbus->buswidth,
-						      sbus->buswidth);
-				lli_len	= tsize * min(mbus->buswidth,
-						      sbus->buswidth);
-
-				if (target_len != lli_len) {
-					dev_vdbg(&pl08x->adev->dev,
-					"%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
-					__func__, target_len, lli_len, txd->len);
-				}
-
-				cctl = pl08x_cctl_bits(cctl,
-						       bd.srcbus.buswidth,
-						       bd.dstbus.buswidth,
-						       tsize);
+				width = max(mbus->buswidth, sbus->buswidth);
+				lli_len = (lli_len / width) * width;
+				tsize = lli_len / bd.srcbus.buswidth;
 
 				dev_vdbg(&pl08x->adev->dev,
-					"%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
+					"%s fill lli with single lli chunk of "
+					"size 0x%08zx (remainder 0x%08zx)\n",
 					__func__, lli_len, bd.remainder);
+
+				cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+					bd.dstbus.buswidth, tsize);
 				pl08x_fill_lli_for_desc(&bd, num_llis++,
-					lli_len, cctl);
+						lli_len, cctl);
 				total_bytes += lli_len;
 			}
 
-
-			if (odd_bytes) {
-				/*
-				 * Creep past the boundary, maintaining
-				 * master alignment
-				 */
-				int j;
-				for (j = 0; (j < mbus->buswidth)
-						&& (bd.remainder); j++) {
-					cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-					dev_vdbg(&pl08x->adev->dev,
-						"%s align with boundary, single byte (remain 0x%08zx)\n",
-						__func__, bd.remainder);
-					pl08x_fill_lli_for_desc(&bd,
-						num_llis++, 1, cctl);
-					total_bytes++;
-				}
+			/*
+			 * Send any odd bytes
+			 */
+			if (bd.remainder) {
+				dev_vdbg(&pl08x->adev->dev,
+					"%s align with boundary, send odd bytes (remain %zu)\n",
+					__func__, bd.remainder);
+				prep_byte_width_lli(&bd, &cctl, bd.remainder,
+						num_llis++, &total_bytes);
 			}
 		}
 
-		/*
-		 * Send any odd bytes
-		 */
-		while (bd.remainder) {
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			dev_vdbg(&pl08x->adev->dev,
-				"%s align with boundary, single odd byte (remain %zu)\n",
-				__func__, bd.remainder);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
+		if (total_bytes != dsg->len) {
+			dev_err(&pl08x->adev->dev,
+				"%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
+				__func__, total_bytes, dsg->len);
+			return 0;
 		}
-	}
-	if (total_bytes != txd->len) {
-		dev_err(&pl08x->adev->dev,
-			"%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
-			__func__, total_bytes, txd->len);
-		return 0;
-	}
 
-	if (num_llis >= MAX_NUM_TSFR_LLIS) {
-		dev_err(&pl08x->adev->dev,
-			"%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
-			__func__, (u32) MAX_NUM_TSFR_LLIS);
-		return 0;
+		if (num_llis >= MAX_NUM_TSFR_LLIS) {
+			dev_err(&pl08x->adev->dev,
+				"%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
+				__func__, (u32) MAX_NUM_TSFR_LLIS);
+			return 0;
+		}
 	}
 
 	llis_va = txd->llis_va;
@@ -856,11 +800,19 @@ static int pl08x_fill_llis_for_desc(stru
 static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
 			   struct pl08x_txd *txd)
 {
+	struct pl08x_sg *dsg, *_dsg;
+
 	/* Free the LLI */
-	dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
+	if (txd->llis_va)
+		dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
 
 	pl08x->pool_ctr--;
 
+	list_for_each_entry_safe(dsg, _dsg, &txd->dsg_list, node) {
+		list_del(&dsg->node);
+		kfree(dsg);
+	}
+
 	kfree(txd);
 }
 
@@ -917,9 +869,7 @@ static int prep_phy_channel(struct pl08x
 	 * need, but for slaves the physical signals may be muxed!
 	 * Can the platform allow us to use this channel?
 	 */
-	if (plchan->slave &&
-	    ch->signal < 0 &&
-	    pl08x->pd->get_signal) {
+	if (plchan->slave && pl08x->pd->get_signal) {
 		ret = pl08x->pd->get_signal(plchan);
 		if (ret < 0) {
 			dev_dbg(&pl08x->adev->dev,
@@ -1008,10 +958,8 @@ static struct dma_async_tx_descriptor *p
  * If slaves are relying on interrupts to signal completion this function
  * must not be called with interrupts disabled.
  */
-static enum dma_status
-pl08x_dma_tx_status(struct dma_chan *chan,
-		    dma_cookie_t cookie,
-		    struct dma_tx_state *txstate)
+static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
+		dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	dma_cookie_t last_used;
@@ -1253,7 +1201,9 @@ static int pl08x_prep_channel_resources(
 
 	num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
 	if (!num_llis) {
-		kfree(txd);
+		spin_lock_irqsave(&plchan->lock, flags);
+		pl08x_free_txd(pl08x, txd);
+		spin_unlock_irqrestore(&plchan->lock, flags);
 		return -EINVAL;
 	}
 
@@ -1301,13 +1251,14 @@ static int pl08x_prep_channel_resources(
 static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
 	unsigned long flags)
 {
-	struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+	struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
 
 	if (txd) {
 		dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
 		txd->tx.flags = flags;
 		txd->tx.tx_submit = pl08x_tx_submit;
 		INIT_LIST_HEAD(&txd->node);
+		INIT_LIST_HEAD(&txd->dsg_list);
 
 		/* Always enable error and terminal interrupts */
 		txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
@@ -1326,6 +1277,7 @@ static struct dma_async_tx_descriptor *p
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
+	struct pl08x_sg *dsg;
 	int ret;
 
 	txd = pl08x_get_txd(plchan, flags);
@@ -1335,10 +1287,19 @@ static struct dma_async_tx_descriptor *p
 		return NULL;
 	}
 
+	dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+	if (!dsg) {
+		pl08x_free_txd(pl08x, txd);
+		dev_err(&pl08x->adev->dev, "%s no memory for pl080 sg\n",
+				__func__);
+		return NULL;
+	}
+	list_add_tail(&dsg->node, &txd->dsg_list);
+
 	txd->direction = DMA_NONE;
-	txd->src_addr = src;
-	txd->dst_addr = dest;
-	txd->len = len;
+	dsg->src_addr = src;
+	dsg->dst_addr = dest;
+	dsg->len = len;
 
 	/* Set platform data for m2m */
 	txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
@@ -1367,19 +1328,13 @@ static struct dma_async_tx_descriptor *p
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
-	int ret;
-
-	/*
-	 * Current implementation ASSUMES only one sg
-	 */
-	if (sg_len != 1) {
-		dev_err(&pl08x->adev->dev, "%s prepared too long sglist\n",
-			__func__);
-		BUG();
-	}
+	struct pl08x_sg *dsg;
+	struct scatterlist *sg;
+	dma_addr_t slave_addr;
+	int ret, tmp;
 
 	dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
-		__func__, sgl->length, plchan->name);
+			__func__, sgl->length, plchan->name);
 
 	txd = pl08x_get_txd(plchan, flags);
 	if (!txd) {
@@ -1398,24 +1353,49 @@ static struct dma_async_tx_descriptor *p
 	 * channel target address dynamically at runtime.
 	 */
 	txd->direction = direction;
-	txd->len = sgl->length;
 
 	if (direction == DMA_TO_DEVICE) {
-		txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		txd->cctl = plchan->dst_cctl;
-		txd->src_addr = sgl->dma_address;
-		txd->dst_addr = plchan->dst_addr;
+		slave_addr = plchan->dst_addr;
 	} else if (direction == DMA_FROM_DEVICE) {
-		txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		txd->cctl = plchan->src_cctl;
-		txd->src_addr = plchan->src_addr;
-		txd->dst_addr = sgl->dma_address;
+		slave_addr = plchan->src_addr;
 	} else {
+		pl08x_free_txd(pl08x, txd);
 		dev_err(&pl08x->adev->dev,
 			"%s direction unsupported\n", __func__);
 		return NULL;
 	}
 
+	if (plchan->cd->device_fc)
+		tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+			PL080_FLOW_PER2MEM_PER;
+	else
+		tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+			PL080_FLOW_PER2MEM;
+
+	txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+
+	for_each_sg(sgl, sg, sg_len, tmp) {
+		dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+		if (!dsg) {
+			pl08x_free_txd(pl08x, txd);
+			dev_err(&pl08x->adev->dev, "%s no mem for pl080 sg\n",
+					__func__);
+			return NULL;
+		}
+		list_add_tail(&dsg->node, &txd->dsg_list);
+
+		dsg->len = sg_dma_len(sg);
+		if (direction == DMA_TO_DEVICE) {
+			dsg->src_addr = sg_phys(sg);
+			dsg->dst_addr = slave_addr;
+		} else {
+			dsg->src_addr = slave_addr;
+			dsg->dst_addr = sg_phys(sg);
+		}
+	}
+
 	ret = pl08x_prep_channel_resources(plchan, txd);
 	if (ret)
 		return NULL;
@@ -1489,9 +1469,15 @@ static int pl08x_control(struct dma_chan
 
 bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
 {
-	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+	struct pl08x_dma_chan *plchan;
 	char *name = chan_id;
 
+	/* Reject channels for devices not bound to this driver */
+	if (chan->device->dev->driver != &pl08x_amba_driver.drv)
+		return false;
+
+	plchan = to_pl08x_chan(chan);
+
 	/* Check that the channel is not taken! */
 	if (!strcmp(plchan->name, name))
 		return true;
@@ -1507,34 +1493,34 @@ bool pl08x_filter_id(struct dma_chan *ch
  */
 static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 {
-	u32 val;
-
-	val = readl(pl08x->base + PL080_CONFIG);
-	val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
-	/* We implicitly clear bit 1 and that means little-endian mode */
-	val |= PL080_CONFIG_ENABLE;
-	writel(val, pl08x->base + PL080_CONFIG);
+	writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
 }
 
 static void pl08x_unmap_buffers(struct pl08x_txd *txd)
 {
 	struct device *dev = txd->tx.chan->device->dev;
+	struct pl08x_sg *dsg;
 
 	if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
 		if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-			dma_unmap_single(dev, txd->src_addr, txd->len,
-				DMA_TO_DEVICE);
-		else
-			dma_unmap_page(dev, txd->src_addr, txd->len,
-				DMA_TO_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		else {
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		}
 	}
 	if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
 		if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-			dma_unmap_single(dev, txd->dst_addr, txd->len,
-				DMA_FROM_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
 		else
-			dma_unmap_page(dev, txd->dst_addr, txd->len,
-				DMA_FROM_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
 	}
 }
 
@@ -1589,8 +1575,8 @@ static void pl08x_tasklet(unsigned long
 		 */
 		list_for_each_entry(waiting, &pl08x->memcpy.channels,
 				    chan.device_node) {
-		  if (waiting->state == PL08X_CHAN_WAITING &&
-			    waiting->waiting != NULL) {
+			if (waiting->state == PL08X_CHAN_WAITING &&
+				waiting->waiting != NULL) {
 				int ret;
 
 				/* This should REALLY not fail now */
@@ -1630,38 +1616,40 @@ static void pl08x_tasklet(unsigned long
 static irqreturn_t pl08x_irq(int irq, void *dev)
 {
 	struct pl08x_driver_data *pl08x = dev;
-	u32 mask = 0;
-	u32 val;
-	int i;
+	u32 mask = 0, err, tc, i;
 
-	val = readl(pl08x->base + PL080_ERR_STATUS);
-	if (val) {
-		/* An error interrupt (on one or more channels) */
-		dev_err(&pl08x->adev->dev,
-			"%s error interrupt, register value 0x%08x\n",
-				__func__, val);
-		/*
-		 * Simply clear ALL PL08X error interrupts,
-		 * regardless of channel and cause
-		 * FIXME: should be 0x00000003 on PL081 really.
-		 */
-		writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
+	/* check & clear - ERR & TC interrupts */
+	err = readl(pl08x->base + PL080_ERR_STATUS);
+	if (err) {
+		dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
+			__func__, err);
+		writel(err, pl08x->base + PL080_ERR_CLEAR);
 	}
-	val = readl(pl08x->base + PL080_INT_STATUS);
+	tc = readl(pl08x->base + PL080_INT_STATUS);
+	if (tc)
+		writel(tc, pl08x->base + PL080_TC_CLEAR);
+
+	if (!err && !tc)
+		return IRQ_NONE;
+
 	for (i = 0; i < pl08x->vd->channels; i++) {
-		if ((1 << i) & val) {
+		if (((1 << i) & err) || ((1 << i) & tc)) {
 			/* Locate physical channel */
 			struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
 			struct pl08x_dma_chan *plchan = phychan->serving;
 
+			if (!plchan) {
+				dev_err(&pl08x->adev->dev,
+					"%s Error TC interrupt on unused channel: 0x%08x\n",
+					__func__, i);
+				continue;
+			}
+
 			/* Schedule tasklet on this channel */
 			tasklet_schedule(&plchan->tasklet);
-
 			mask |= (1 << i);
 		}
 	}
-	/* Clear only the terminal interrupts on channels we processed */
-	writel(mask, pl08x->base + PL080_TC_CLEAR);
 
 	return mask ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -1685,9 +1673,7 @@ static void pl08x_dma_slave_init(struct
  * Make a local wrapper to hold required data
  */
 static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
-					   struct dma_device *dmadev,
-					   unsigned int channels,
-					   bool slave)
+		struct dma_device *dmadev, unsigned int channels, bool slave)
 {
 	struct pl08x_dma_chan *chan;
 	int i;
@@ -1700,7 +1686,7 @@ static int pl08x_dma_init_virtual_channe
 	 * to cope with that situation.
 	 */
 	for (i = 0; i < channels; i++) {
-		chan = kzalloc(sizeof(struct pl08x_dma_chan), GFP_KERNEL);
+		chan = kzalloc(sizeof(*chan), GFP_KERNEL);
 		if (!chan) {
 			dev_err(&pl08x->adev->dev,
 				"%s no memory for channel\n", __func__);
@@ -1728,7 +1714,7 @@ static int pl08x_dma_init_virtual_channe
 			kfree(chan);
 			continue;
 		}
-		dev_info(&pl08x->adev->dev,
+		dev_dbg(&pl08x->adev->dev,
 			 "initialize virtual channel \"%s\"\n",
 			 chan->name);
 
@@ -1837,9 +1823,9 @@ static const struct file_operations pl08
 static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 {
 	/* Expose a simple debugfs interface to view all clocks */
-	(void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO,
-				   NULL, pl08x,
-				   &pl08x_debugfs_operations);
+	(void) debugfs_create_file(dev_name(&pl08x->adev->dev),
+			S_IFREG | S_IRUGO, NULL, pl08x,
+			&pl08x_debugfs_operations);
 }
 
 #else
@@ -1860,12 +1846,15 @@ static int pl08x_probe(struct amba_devic
 		return ret;
 
 	/* Create the driver state holder */
-	pl08x = kzalloc(sizeof(struct pl08x_driver_data), GFP_KERNEL);
+	pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
 	if (!pl08x) {
 		ret = -ENOMEM;
 		goto out_no_pl08x;
 	}
 
+	pm_runtime_set_active(&adev->dev);
+	pm_runtime_enable(&adev->dev);
+
 	/* Initialize memcpy engine */
 	dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
 	pl08x->memcpy.dev = &adev->dev;
@@ -1939,7 +1928,7 @@ static int pl08x_probe(struct amba_devic
 	}
 
 	/* Initialize physical channels */
-	pl08x->phy_chans = kmalloc((vd->channels * sizeof(struct pl08x_phy_chan)),
+	pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
 			GFP_KERNEL);
 	if (!pl08x->phy_chans) {
 		dev_err(&adev->dev, "%s failed to allocate "
@@ -1956,9 +1945,8 @@ static int pl08x_probe(struct amba_devic
 		spin_lock_init(&ch->lock);
 		ch->serving = NULL;
 		ch->signal = -1;
-		dev_info(&adev->dev,
-			 "physical channel %d is %s\n", i,
-			 pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
+		dev_dbg(&adev->dev, "physical channel %d is %s\n",
+			i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
 	}
 
 	/* Register as many memcpy channels as there are physical channels */
@@ -1974,8 +1962,7 @@ static int pl08x_probe(struct amba_devic
 
 	/* Register slave channels */
 	ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
-					      pl08x->pd->num_slave_channels,
-					      true);
+			pl08x->pd->num_slave_channels, true);
 	if (ret <= 0) {
 		dev_warn(&pl08x->adev->dev,
 			"%s failed to enumerate slave channels - %d\n",
@@ -2005,6 +1992,8 @@ static int pl08x_probe(struct amba_devic
 	dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
 		 amba_part(adev), amba_rev(adev),
 		 (unsigned long long)adev->res.start, adev->irq[0]);
+
+	pm_runtime_put(&adev->dev);
 	return 0;
 
 out_no_slave_reg:
@@ -2023,6 +2012,9 @@ out_no_ioremap:
 	dma_pool_destroy(pl08x->pool);
 out_no_lli_pool:
 out_no_platdata:
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+
 	kfree(pl08x);
 out_no_pl08x:
 	amba_release_regions(adev);
diff -druNp linux-libre-3.1-gnu1/drivers/dma/at_hdmac.c linux-libre-3.2-gnu1/drivers/dma/at_hdmac.c
--- linux-libre-3.1-gnu1/drivers/dma/at_hdmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/at_hdmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,10 +107,11 @@ static struct at_desc *atc_desc_get(stru
 {
 	struct at_desc *desc, *_desc;
 	struct at_desc *ret = NULL;
+	unsigned long flags;
 	unsigned int i = 0;
 	LIST_HEAD(tmp_list);
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
 		i++;
 		if (async_tx_test_ack(&desc->txd)) {
@@ -121,7 +122,7 @@ static struct at_desc *atc_desc_get(stru
 		dev_dbg(chan2dev(&atchan->chan_common),
 				"desc %p not ACKed\n", desc);
 	}
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 	dev_vdbg(chan2dev(&atchan->chan_common),
 		"scanned %u descriptors on freelist\n", i);
 
@@ -129,9 +130,9 @@ static struct at_desc *atc_desc_get(stru
 	if (!ret) {
 		ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
 		if (ret) {
-			spin_lock_bh(&atchan->lock);
+			spin_lock_irqsave(&atchan->lock, flags);
 			atchan->descs_allocated++;
-			spin_unlock_bh(&atchan->lock);
+			spin_unlock_irqrestore(&atchan->lock, flags);
 		} else {
 			dev_err(chan2dev(&atchan->chan_common),
 					"not enough descriptors available\n");
@@ -150,8 +151,9 @@ static void atc_desc_put(struct at_dma_c
 {
 	if (desc) {
 		struct at_desc *child;
+		unsigned long flags;
 
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 		list_for_each_entry(child, &desc->tx_list, desc_node)
 			dev_vdbg(chan2dev(&atchan->chan_common),
 					"moving child desc %p to freelist\n",
@@ -160,7 +162,7 @@ static void atc_desc_put(struct at_dma_c
 		dev_vdbg(chan2dev(&atchan->chan_common),
 			 "moving desc %p to freelist\n", desc);
 		list_add(&desc->desc_node, &atchan->free_list);
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	}
 }
 
@@ -299,7 +301,7 @@ atc_chain_complete(struct at_dma_chan *a
 
 	/* for cyclic transfers,
 	 * no need to replay callback function while stopping */
-	if (!test_bit(ATC_IS_CYCLIC, &atchan->status)) {
+	if (!atc_chan_is_cyclic(atchan)) {
 		dma_async_tx_callback	callback = txd->callback;
 		void			*param = txd->callback_param;
 
@@ -471,16 +473,17 @@ static void atc_handle_cyclic(struct at_
 static void atc_tasklet(unsigned long data)
 {
 	struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+	unsigned long flags;
 
-	spin_lock(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
 		atc_handle_error(atchan);
-	else if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+	else if (atc_chan_is_cyclic(atchan))
 		atc_handle_cyclic(atchan);
 	else
 		atc_advance_work(atchan);
 
-	spin_unlock(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
@@ -539,8 +542,9 @@ static dma_cookie_t atc_tx_submit(struct
 	struct at_desc		*desc = txd_to_at_desc(tx);
 	struct at_dma_chan	*atchan = to_at_dma_chan(tx->chan);
 	dma_cookie_t		cookie;
+	unsigned long		flags;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	cookie = atc_assign_cookie(atchan, desc);
 
 	if (list_empty(&atchan->active_list)) {
@@ -554,7 +558,7 @@ static dma_cookie_t atc_tx_submit(struct
 		list_add_tail(&desc->desc_node, &atchan->queue);
 	}
 
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	return cookie;
 }
@@ -927,28 +931,29 @@ static int atc_control(struct dma_chan *
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	struct at_dma		*atdma = to_at_dma(chan->device);
 	int			chan_id = atchan->chan_common.chan_id;
+	unsigned long		flags;
 
 	LIST_HEAD(list);
 
 	dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd);
 
 	if (cmd == DMA_PAUSE) {
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
 		set_bit(ATC_IS_PAUSED, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else if (cmd == DMA_RESUME) {
-		if (!test_bit(ATC_IS_PAUSED, &atchan->status))
+		if (!atc_chan_is_paused(atchan))
 			return 0;
 
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
 		clear_bit(ATC_IS_PAUSED, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else if (cmd == DMA_TERMINATE_ALL) {
 		struct at_desc	*desc, *_desc;
 		/*
@@ -957,7 +962,7 @@ static int atc_control(struct dma_chan *
 		 * channel. We still have to poll the channel enable bit due
 		 * to AHB/HSB limitations.
 		 */
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		/* disabling channel: must also remove suspend state */
 		dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
@@ -978,7 +983,7 @@ static int atc_control(struct dma_chan *
 		/* if channel dedicated to cyclic operations, free it */
 		clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else {
 		return -ENXIO;
 	}
@@ -1004,9 +1009,10 @@ atc_tx_status(struct dma_chan *chan,
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	dma_cookie_t		last_used;
 	dma_cookie_t		last_complete;
+	unsigned long		flags;
 	enum dma_status		ret;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 
 	last_complete = atchan->completed_cookie;
 	last_used = chan->cookie;
@@ -1021,7 +1027,7 @@ atc_tx_status(struct dma_chan *chan,
 		ret = dma_async_is_complete(cookie, last_complete, last_used);
 	}
 
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	if (ret != DMA_SUCCESS)
 		dma_set_tx_state(txstate, last_complete, last_used,
@@ -1029,7 +1035,7 @@ atc_tx_status(struct dma_chan *chan,
 	else
 		dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-	if (test_bit(ATC_IS_PAUSED, &atchan->status))
+	if (atc_chan_is_paused(atchan))
 		ret = DMA_PAUSED;
 
 	dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n",
@@ -1046,18 +1052,19 @@ atc_tx_status(struct dma_chan *chan,
 static void atc_issue_pending(struct dma_chan *chan)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	unsigned long		flags;
 
 	dev_vdbg(chan2dev(chan), "issue_pending\n");
 
 	/* Not needed for cyclic transfers */
-	if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+	if (atc_chan_is_cyclic(atchan))
 		return;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	if (!atc_chan_is_enabled(atchan)) {
 		atc_advance_work(atchan);
 	}
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 /**
@@ -1073,6 +1080,7 @@ static int atc_alloc_chan_resources(stru
 	struct at_dma		*atdma = to_at_dma(chan->device);
 	struct at_desc		*desc;
 	struct at_dma_slave	*atslave;
+	unsigned long		flags;
 	int			i;
 	u32			cfg;
 	LIST_HEAD(tmp_list);
@@ -1116,11 +1124,11 @@ static int atc_alloc_chan_resources(stru
 		list_add_tail(&desc->desc_node, &tmp_list);
 	}
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	atchan->descs_allocated = i;
 	list_splice(&tmp_list, &atchan->free_list);
 	atchan->completed_cookie = chan->cookie = 1;
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	/* channel parameters */
 	channel_writel(atchan, CFG, cfg);
@@ -1260,12 +1268,11 @@ static int __init at_dma_probe(struct pl
 
 	/* initialize channels related values */
 	INIT_LIST_HEAD(&atdma->dma_common.channels);
-	for (i = 0; i < pdata->nr_channels; i++, atdma->dma_common.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct at_dma_chan	*atchan = &atdma->chan[i];
 
 		atchan->chan_common.device = &atdma->dma_common;
 		atchan->chan_common.cookie = atchan->completed_cookie = 1;
-		atchan->chan_common.chan_id = i;
 		list_add_tail(&atchan->chan_common.device_node,
 				&atdma->dma_common.channels);
 
@@ -1293,22 +1300,20 @@ static int __init at_dma_probe(struct pl
 	if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
 		atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
 
-	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask))
+	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
 		atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
-
-	if (dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
+		/* controller can do slave DMA: can trigger cyclic transfers */
+		dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
 		atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
-
-	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ||
-	    dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
 		atdma->dma_common.device_control = atc_control;
+	}
 
 	dma_writel(atdma, EN, AT_DMA_ENABLE);
 
 	dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
 	  dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
 	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
-	  atdma->dma_common.chancnt);
+	  pdata->nr_channels);
 
 	dma_async_device_register(&atdma->dma_common);
 
@@ -1377,27 +1382,112 @@ static void at_dma_shutdown(struct platf
 	clk_disable(atdma->clk);
 }
 
+static int at_dma_prepare(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
+
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+		/* wait for transaction completion (except in cyclic case) */
+		if (atc_chan_is_enabled(atchan) && !atc_chan_is_cyclic(atchan))
+			return -EAGAIN;
+	}
+	return 0;
+}
+
+static void atc_suspend_cyclic(struct at_dma_chan *atchan)
+{
+	struct dma_chan	*chan = &atchan->chan_common;
+
+	/* Channel should be paused by user
+	 * do it anyway even if it is not done already */
+	if (!atc_chan_is_paused(atchan)) {
+		dev_warn(chan2dev(chan),
+		"cyclic channel not paused, should be done by channel user\n");
+		atc_control(chan, DMA_PAUSE, 0);
+	}
+
+	/* now preserve additional data for cyclic operations */
+	/* next descriptor address in the cyclic list */
+	atchan->save_dscr = channel_readl(atchan, DSCR);
+
+	vdbg_dump_regs(atchan);
+}
+
 static int at_dma_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
 
-	at_dma_off(platform_get_drvdata(pdev));
+	/* preserve data */
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+		if (atc_chan_is_cyclic(atchan))
+			atc_suspend_cyclic(atchan);
+		atchan->save_cfg = channel_readl(atchan, CFG);
+	}
+	atdma->save_imr = dma_readl(atdma, EBCIMR);
+
+	/* disable DMA controller */
+	at_dma_off(atdma);
 	clk_disable(atdma->clk);
 	return 0;
 }
 
+static void atc_resume_cyclic(struct at_dma_chan *atchan)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+
+	/* restore channel status for cyclic descriptors list:
+	 * next descriptor in the cyclic list at the time of suspend */
+	channel_writel(atchan, SADDR, 0);
+	channel_writel(atchan, DADDR, 0);
+	channel_writel(atchan, CTRLA, 0);
+	channel_writel(atchan, CTRLB, 0);
+	channel_writel(atchan, DSCR, atchan->save_dscr);
+	dma_writel(atdma, CHER, atchan->mask);
+
+	/* channel pause status should be removed by channel user
+	 * We cannot take the initiative to do it here */
+
+	vdbg_dump_regs(atchan);
+}
+
 static int at_dma_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
 
+	/* bring back DMA controller */
 	clk_enable(atdma->clk);
 	dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+	/* clear any pending interrupt */
+	while (dma_readl(atdma, EBCISR))
+		cpu_relax();
+
+	/* restore saved data */
+	dma_writel(atdma, EBCIER, atdma->save_imr);
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+		channel_writel(atchan, CFG, atchan->save_cfg);
+		if (atc_chan_is_cyclic(atchan))
+			atc_resume_cyclic(atchan);
+	}
 	return 0;
 }
 
 static const struct dev_pm_ops at_dma_dev_pm_ops = {
+	.prepare = at_dma_prepare,
 	.suspend_noirq = at_dma_suspend_noirq,
 	.resume_noirq = at_dma_resume_noirq,
 };
diff -druNp linux-libre-3.1-gnu1/drivers/dma/at_hdmac_regs.h linux-libre-3.2-gnu1/drivers/dma/at_hdmac_regs.h
--- linux-libre-3.1-gnu1/drivers/dma/at_hdmac_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/at_hdmac_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -204,6 +204,9 @@ enum atc_status {
  * @status: transmit status information from irq/prep* functions
  *                to tasklet (use atomic operations)
  * @tasklet: bottom half to finish transaction work
+ * @save_cfg: configuration register that is saved on suspend/resume cycle
+ * @save_dscr: for cyclic operations, preserve next descriptor address in
+ *             the cyclic list on suspend/resume cycle
  * @lock: serializes enqueue/dequeue operations to descriptors lists
  * @completed_cookie: identifier for the most recently completed operation
  * @active_list: list of descriptors dmaengine is being running on
@@ -218,6 +221,8 @@ struct at_dma_chan {
 	u8			mask;
 	unsigned long		status;
 	struct tasklet_struct	tasklet;
+	u32			save_cfg;
+	u32			save_dscr;
 
 	spinlock_t		lock;
 
@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_
  * @chan_common: common dmaengine dma_device object members
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
+ * @save_imr: interrupt mask register that is saved on suspend/resume cycle
  * @all_chan_mask: all channels availlable in a mask
  * @dma_desc_pool: base of DMA descriptor region (DMA address)
  * @chan: channels table to store at_dma_chan structures
@@ -256,6 +262,7 @@ struct at_dma {
 	struct dma_device	dma_common;
 	void __iomem		*regs;
 	struct clk		*clk;
+	u32			save_imr;
 
 	u8			all_chan_mask;
 
@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(st
 	return !!(dma_readl(atdma, CHSR) & atchan->mask);
 }
 
+/**
+ * atc_chan_is_paused - test channel pause/resume status
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
+{
+	return test_bit(ATC_IS_PAUSED, &atchan->status);
+}
+
+/**
+ * atc_chan_is_cyclic - test if given channel has cyclic property set
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
+{
+	return test_bit(ATC_IS_CYCLIC, &atchan->status);
+}
 
 /**
  * set_desc_eol - set end-of-link to descriptor so it will end transfer
diff -druNp linux-libre-3.1-gnu1/drivers/dma/dmatest.c linux-libre-3.2-gnu1/drivers/dma/dmatest.c
--- linux-libre-3.1-gnu1/drivers/dma/dmatest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/dmatest.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/freezer.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -251,6 +252,7 @@ static int dmatest_func(void *data)
 	int			i;
 
 	thread_name = current->comm;
+	set_freezable_with_signal();
 
 	ret = -ENOMEM;
 
@@ -305,7 +307,8 @@ static int dmatest_func(void *data)
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
 		struct completion cmp;
-		unsigned long tmo = msecs_to_jiffies(timeout);
+		unsigned long start, tmo, end = 0 /* compiler... */;
+		bool reload = true;
 		u8 align = 0;
 
 		total_tests++;
@@ -404,7 +407,17 @@ static int dmatest_func(void *data)
 		}
 		dma_async_issue_pending(chan);
 
-		tmo = wait_for_completion_timeout(&cmp, tmo);
+		do {
+			start = jiffies;
+			if (reload)
+				end = start + msecs_to_jiffies(timeout);
+			else if (end <= start)
+				end = start + 1;
+			tmo = wait_for_completion_interruptible_timeout(&cmp,
+								end - start);
+			reload = try_to_freeze();
+		} while (tmo == -ERESTARTSYS);
+
 		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
 		if (tmo == 0) {
@@ -477,6 +490,8 @@ err_srcs:
 	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
 			thread_name, total_tests, failed_tests, ret);
 
+	/* terminate all transfers on specified channels */
+	chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
 	if (iterations > 0)
 		while (!kthread_should_stop()) {
 			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(stru
 		list_del(&thread->node);
 		kfree(thread);
 	}
+
+	/* terminate all transfers on specified channels */
+	dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
+
 	kfree(dtc);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/dma/dw_dmac.c linux-libre-3.2-gnu1/drivers/dma/dw_dmac.c
--- linux-libre-3.1-gnu1/drivers/dma/dw_dmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/dw_dmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -1407,12 +1407,11 @@ static int __init dw_probe(struct platfo
 	dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
 
 	INIT_LIST_HEAD(&dw->dma.channels);
-	for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct dw_dma_chan	*dwc = &dw->chan[i];
 
 		dwc->chan.device = &dw->dma;
 		dwc->chan.cookie = dwc->completed = 1;
-		dwc->chan.chan_id = i;
 		if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
 			list_add_tail(&dwc->chan.device_node,
 					&dw->dma.channels);
@@ -1468,7 +1467,7 @@ static int __init dw_probe(struct platfo
 	dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
 	printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-			dev_name(&pdev->dev), dw->dma.chancnt);
+			dev_name(&pdev->dev), pdata->nr_channels);
 
 	dma_async_device_register(&dw->dma);
 
diff -druNp linux-libre-3.1-gnu1/drivers/dma/ep93xx_dma.c linux-libre-3.2-gnu1/drivers/dma/ep93xx_dma.c
--- linux-libre-3.1-gnu1/drivers/dma/ep93xx_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/ep93xx_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/dma/imx-dma.c linux-libre-3.2-gnu1/drivers/dma/imx-dma.c
--- linux-libre-3.1-gnu1/drivers/dma/imx-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/imx-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -23,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/dmaengine.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <mach/dma-v1.h>
diff -druNp linux-libre-3.1-gnu1/drivers/dma/imx-sdma.c linux-libre-3.2-gnu1/drivers/dma/imx-sdma.c
--- linux-libre-3.1-gnu1/drivers/dma/imx-sdma.c	2013-05-02 01:33:46.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/imx-sdma.c	2013-05-01 23:41:48.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -34,6 +35,7 @@
 #include <linux/dmaengine.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <mach/sdma.h>
@@ -318,6 +320,7 @@ struct sdma_engine {
 	dma_addr_t			context_phys;
 	struct dma_device		dma_device;
 	struct clk			*clk;
+	struct mutex			channel_0_lock;
 	struct sdma_script_start_addrs	*script_addrs;
 };
 
@@ -415,11 +418,15 @@ static int sdma_load_script(struct sdma_
 	dma_addr_t buf_phys;
 	int ret;
 
+	mutex_lock(&sdma->channel_0_lock);
+
 	buf_virt = dma_alloc_coherent(NULL,
 			size,
 			&buf_phys, GFP_KERNEL);
-	if (!buf_virt)
-		return -ENOMEM;
+	if (!buf_virt) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
 
 	bd0->mode.command = C0_SETPM;
 	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -433,6 +440,9 @@ static int sdma_load_script(struct sdma_
 
 	dma_free_coherent(NULL, size, buf_virt, buf_phys);
 
+err_out:
+	mutex_unlock(&sdma->channel_0_lock);
+
 	return ret;
 }
 
@@ -656,6 +666,8 @@ static int sdma_load_context(struct sdma
 	dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
 	dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
 
+	mutex_lock(&sdma->channel_0_lock);
+
 	memset(context, 0, sizeof(*context));
 	context->channel_state.pc = load_address;
 
@@ -676,6 +688,8 @@ static int sdma_load_context(struct sdma
 
 	ret = sdma_run_channel(&sdma->channel[0]);
 
+	mutex_unlock(&sdma->channel_0_lock);
+
 	return ret;
 }
 
@@ -1131,18 +1145,17 @@ static void sdma_add_scripts(struct sdma
 			saddr_arr[i] = addr_arr[i];
 }
 
-static int __init sdma_get_firmware(struct sdma_engine *sdma,
-		const char *fw_name)
+static void sdma_load_firmware(const struct firmware *fw, void *context)
 {
-	const struct firmware *fw;
+	struct sdma_engine *sdma = context;
 	const struct sdma_firmware_header *header;
-	int ret;
 	const struct sdma_script_start_addrs *addr;
 	unsigned short *ram_code;
 
-	ret = reject_firmware(&fw, fw_name, sdma->dev);
-	if (ret)
-		return ret;
+	if (!fw) {
+		dev_err(sdma->dev, "firmware not found\n");
+		return;
+	}
 
 	if (fw->size < sizeof(*header))
 		goto err_firmware;
@@ -1172,6 +1185,16 @@ static int __init sdma_get_firmware(stru
 
 err_firmware:
 	release_firmware(fw);
+}
+
+static int __init sdma_get_firmware(struct sdma_engine *sdma,
+		const char *fw_name)
+{
+	int ret;
+
+	ret = reject_firmware_nowait(THIS_MODULE,
+			FW_ACTION_HOTPLUG, fw_name, sdma->dev,
+			GFP_KERNEL, sdma, sdma_load_firmware);
 
 	return ret;
 }
@@ -1269,11 +1292,14 @@ static int __init sdma_probe(struct plat
 	struct sdma_platform_data *pdata = pdev->dev.platform_data;
 	int i;
 	struct sdma_engine *sdma;
+	s32 *saddr_arr;
 
 	sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
 	if (!sdma)
 		return -ENOMEM;
 
+	mutex_init(&sdma->channel_0_lock);
+
 	sdma->dev = &pdev->dev;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1310,6 +1336,11 @@ static int __init sdma_probe(struct plat
 		goto err_alloc;
 	}
 
+	/* initially no scripts available */
+	saddr_arr = (s32 *)sdma->script_addrs;
+	for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+		saddr_arr[i] = -EINVAL;
+
 	if (of_id)
 		pdev->id_entry = of_id->data;
 	sdma->devtype = pdev->id_entry->driver_data;
diff -druNp linux-libre-3.1-gnu1/drivers/dma/intel_mid_dma.c linux-libre-3.2-gnu1/drivers/dma/intel_mid_dma.c
--- linux-libre-3.1-gnu1/drivers/dma/intel_mid_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/intel_mid_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/intel_mid_dma.h>
+#include <linux/module.h>
 
 #define MAX_CHAN	4 /*max ch across controllers*/
 #include "intel_mid_dma_regs.h"
@@ -115,16 +116,15 @@ DMAC1 interrupt Functions*/
 
 /**
  * dmac1_mask_periphral_intr -	mask the periphral interrupt
- * @midc: dma channel for which masking is required
+ * @mid: dma device for which masking is required
  *
  * Masks the DMA periphral interrupt
  * this is valid for DMAC1 family controllers only
  * This controller should have periphral mask registers already mapped
  */
-static void dmac1_mask_periphral_intr(struct intel_mid_dma_chan *midc)
+static void dmac1_mask_periphral_intr(struct middma_device *mid)
 {
 	u32 pimr;
-	struct middma_device *mid = to_middma_device(midc->chan.device);
 
 	if (mid->pimr_mask) {
 		pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK);
@@ -184,7 +184,6 @@ static void enable_dma_interrupt(struct
 static void disable_dma_interrupt(struct intel_mid_dma_chan *midc)
 {
 	/*Check LPE PISR, make sure fwd is disabled*/
-	dmac1_mask_periphral_intr(midc);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_BLOCK);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR);
@@ -1114,7 +1113,6 @@ static int mid_setup_dma(struct pci_dev
 
 		midch->chan.device = &dma->common;
 		midch->chan.cookie =  1;
-		midch->chan.chan_id = i;
 		midch->ch_id = dma->chan_base + i;
 		pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id);
 
@@ -1150,7 +1148,6 @@ static int mid_setup_dma(struct pci_dev
 	dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
 	dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
 	dma->common.dev = &pdev->dev;
-	dma->common.chancnt = dma->max_chan;
 
 	dma->common.device_alloc_chan_resources =
 					intel_mid_dma_alloc_chan_resources;
@@ -1350,6 +1347,7 @@ int dma_suspend(struct pci_dev *pci, pm_
 		if (device->ch[i].in_use)
 			return -EAGAIN;
 	}
+	dmac1_mask_periphral_intr(device);
 	device->state = SUSPENDED;
 	pci_save_state(pci);
 	pci_disable_device(pci);
diff -druNp linux-libre-3.1-gnu1/drivers/dma/ipu/ipu_idmac.c linux-libre-3.2-gnu1/drivers/dma/ipu/ipu_idmac.c
--- linux-libre-3.1-gnu1/drivers/dma/ipu/ipu_idmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/ipu/ipu_idmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/ipu.h>
 
@@ -1307,6 +1308,7 @@ static irqreturn_t idmac_interrupt(int i
 	    ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) {
 		callback = descnew->txd.callback;
 		callback_param = descnew->txd.callback_param;
+		list_del_init(&descnew->list);
 		spin_unlock(&ichan->lock);
 		if (callback)
 			callback(callback_param);
@@ -1428,39 +1430,58 @@ static int __idmac_control(struct dma_ch
 {
 	struct idmac_channel *ichan = to_idmac_chan(chan);
 	struct idmac *idmac = to_idmac(chan->device);
+	struct ipu *ipu = to_ipu(idmac);
+	struct list_head *list, *tmp;
 	unsigned long flags;
 	int i;
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
+	switch (cmd) {
+	case DMA_PAUSE:
+		spin_lock_irqsave(&ipu->lock, flags);
+		ipu_ic_disable_task(ipu, chan->chan_id);
 
-	ipu_disable_channel(idmac, ichan,
-			    ichan->status >= IPU_CHANNEL_ENABLED);
+		/* Return all descriptors into "prepared" state */
+		list_for_each_safe(list, tmp, &ichan->queue)
+			list_del_init(list);
 
-	tasklet_disable(&to_ipu(idmac)->tasklet);
+		ichan->sg[0] = NULL;
+		ichan->sg[1] = NULL;
 
-	/* ichan->queue is modified in ISR, have to spinlock */
-	spin_lock_irqsave(&ichan->lock, flags);
-	list_splice_init(&ichan->queue, &ichan->free_list);
+		spin_unlock_irqrestore(&ipu->lock, flags);
 
-	if (ichan->desc)
-		for (i = 0; i < ichan->n_tx_desc; i++) {
-			struct idmac_tx_desc *desc = ichan->desc + i;
-			if (list_empty(&desc->list))
-				/* Descriptor was prepared, but not submitted */
-				list_add(&desc->list, &ichan->free_list);
+		ichan->status = IPU_CHANNEL_INITIALIZED;
+		break;
+	case DMA_TERMINATE_ALL:
+		ipu_disable_channel(idmac, ichan,
+				    ichan->status >= IPU_CHANNEL_ENABLED);
 
-			async_tx_clear_ack(&desc->txd);
-		}
+		tasklet_disable(&ipu->tasklet);
 
-	ichan->sg[0] = NULL;
-	ichan->sg[1] = NULL;
-	spin_unlock_irqrestore(&ichan->lock, flags);
+		/* ichan->queue is modified in ISR, have to spinlock */
+		spin_lock_irqsave(&ichan->lock, flags);
+		list_splice_init(&ichan->queue, &ichan->free_list);
 
-	tasklet_enable(&to_ipu(idmac)->tasklet);
+		if (ichan->desc)
+			for (i = 0; i < ichan->n_tx_desc; i++) {
+				struct idmac_tx_desc *desc = ichan->desc + i;
+				if (list_empty(&desc->list))
+					/* Descriptor was prepared, but not submitted */
+					list_add(&desc->list, &ichan->free_list);
 
-	ichan->status = IPU_CHANNEL_INITIALIZED;
+				async_tx_clear_ack(&desc->txd);
+			}
+
+		ichan->sg[0] = NULL;
+		ichan->sg[1] = NULL;
+		spin_unlock_irqrestore(&ichan->lock, flags);
+
+		tasklet_enable(&ipu->tasklet);
+
+		ichan->status = IPU_CHANNEL_INITIALIZED;
+		break;
+	default:
+		return -ENOSYS;
+	}
 
 	return 0;
 }
@@ -1663,7 +1684,6 @@ static void __exit ipu_idmac_exit(struct
 		struct idmac_channel *ichan = ipu->channel + i;
 
 		idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0);
-		idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0);
 	}
 
 	dma_async_device_unregister(&idmac->dma);
diff -druNp linux-libre-3.1-gnu1/drivers/dma/ipu/ipu_irq.c linux-libre-3.2-gnu1/drivers/dma/ipu/ipu_irq.c
--- linux-libre-3.1-gnu1/drivers/dma/ipu/ipu_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/ipu/ipu_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@ static struct ipu_irq_map irq_map[CONFIG
 /* Protects allocations from the above array of maps */
 static DEFINE_MUTEX(map_lock);
 /* Protects register accesses and individual mappings */
-static DEFINE_SPINLOCK(bank_lock);
+static DEFINE_RAW_SPINLOCK(bank_lock);
 
 static struct ipu_irq_map *src2map(unsigned int src)
 {
@@ -101,11 +101,11 @@ static void ipu_irq_unmask(struct irq_da
 	uint32_t reg;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
@@ -114,7 +114,7 @@ static void ipu_irq_unmask(struct irq_da
 	reg |= (1UL << (map->source & 31));
 	ipu_write_reg(bank->ipu, reg, bank->control);
 
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 static void ipu_irq_mask(struct irq_data *d)
@@ -124,11 +124,11 @@ static void ipu_irq_mask(struct irq_data
 	uint32_t reg;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
@@ -137,7 +137,7 @@ static void ipu_irq_mask(struct irq_data
 	reg &= ~(1UL << (map->source & 31));
 	ipu_write_reg(bank->ipu, reg, bank->control);
 
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 static void ipu_irq_ack(struct irq_data *d)
@@ -146,17 +146,17 @@ static void ipu_irq_ack(struct irq_data
 	struct ipu_irq_bank *bank;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
 
 	ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 /**
@@ -172,11 +172,11 @@ bool ipu_irq_status(unsigned int irq)
 	unsigned long lock_flags;
 	bool ret;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 	bank = map->bank;
 	ret = bank && ipu_read_reg(bank->ipu, bank->status) &
 		(1UL << (map->source & 31));
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 	return ret;
 }
@@ -213,10 +213,10 @@ int ipu_irq_map(unsigned int source)
 		if (irq_map[i].source < 0) {
 			unsigned long lock_flags;
 
-			spin_lock_irqsave(&bank_lock, lock_flags);
+			raw_spin_lock_irqsave(&bank_lock, lock_flags);
 			irq_map[i].source = source;
 			irq_map[i].bank = irq_bank + source / 32;
-			spin_unlock_irqrestore(&bank_lock, lock_flags);
+			raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 			ret = irq_map[i].irq;
 			pr_debug("IPU: mapped source %u to IRQ %u\n",
@@ -252,10 +252,10 @@ int ipu_irq_unmap(unsigned int source)
 			pr_debug("IPU: unmapped source %u from IRQ %u\n",
 				 source, irq_map[i].irq);
 
-			spin_lock_irqsave(&bank_lock, lock_flags);
+			raw_spin_lock_irqsave(&bank_lock, lock_flags);
 			irq_map[i].source = -EINVAL;
 			irq_map[i].bank = NULL;
-			spin_unlock_irqrestore(&bank_lock, lock_flags);
+			raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 			ret = 0;
 			break;
@@ -276,7 +276,7 @@ static void ipu_irq_err(unsigned int irq
 	for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
 		struct ipu_irq_bank *bank = irq_bank + i;
 
-		spin_lock(&bank_lock);
+		raw_spin_lock(&bank_lock);
 		status = ipu_read_reg(ipu, bank->status);
 		/*
 		 * Don't think we have to clear all interrupts here, they will
@@ -284,18 +284,18 @@ static void ipu_irq_err(unsigned int irq
 		 * might want to clear unhandled interrupts after the loop...
 		 */
 		status &= ipu_read_reg(ipu, bank->control);
-		spin_unlock(&bank_lock);
+		raw_spin_unlock(&bank_lock);
 		while ((line = ffs(status))) {
 			struct ipu_irq_map *map;
 
 			line--;
 			status &= ~(1UL << line);
 
-			spin_lock(&bank_lock);
+			raw_spin_lock(&bank_lock);
 			map = src2map(32 * i + line);
 			if (map)
 				irq = map->irq;
-			spin_unlock(&bank_lock);
+			raw_spin_unlock(&bank_lock);
 
 			if (!map) {
 				pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
@@ -317,22 +317,22 @@ static void ipu_irq_fn(unsigned int irq,
 	for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) {
 		struct ipu_irq_bank *bank = irq_bank + i;
 
-		spin_lock(&bank_lock);
+		raw_spin_lock(&bank_lock);
 		status = ipu_read_reg(ipu, bank->status);
 		/* Not clearing all interrupts, see above */
 		status &= ipu_read_reg(ipu, bank->control);
-		spin_unlock(&bank_lock);
+		raw_spin_unlock(&bank_lock);
 		while ((line = ffs(status))) {
 			struct ipu_irq_map *map;
 
 			line--;
 			status &= ~(1UL << line);
 
-			spin_lock(&bank_lock);
+			raw_spin_lock(&bank_lock);
 			map = src2map(32 * i + line);
 			if (map)
 				irq = map->irq;
-			spin_unlock(&bank_lock);
+			raw_spin_unlock(&bank_lock);
 
 			if (!map) {
 				pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
diff -druNp linux-libre-3.1-gnu1/drivers/dma/Kconfig linux-libre-3.2-gnu1/drivers/dma/Kconfig
--- linux-libre-3.1-gnu1/drivers/dma/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@ config MV_XOR
 
 config MX3_IPU
 	bool "MX3x Image Processing Unit support"
-	depends on ARCH_MX3
+	depends on SOC_IMX31 ||Â SOC_IMX35
 	select DMA_ENGINE
 	default y
 	help
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 config PL330_DMA
 	tristate "DMA API Driver for PL330"
 	select DMA_ENGINE
-	depends on PL330
+	depends on ARM_AMBA
+	select PL330
 	help
 	  Select if your platform has one or more PL330 DMACs.
 	  You need to provide platform specific settings via
@@ -215,7 +216,7 @@ config PCH_DMA
 
 config IMX_SDMA
 	tristate "i.MX SDMA support"
-	depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5
+	depends on ARCH_MX25 || SOC_IMX31 ||Â SOC_IMX35 || ARCH_MX5
 	select DMA_ENGINE
 	help
 	  Support the i.MX SDMA engine. This engine is integrated into
diff -druNp linux-libre-3.1-gnu1/drivers/dma/mpc512x_dma.c linux-libre-3.2-gnu1/drivers/dma/mpc512x_dma.c
--- linux-libre-3.1-gnu1/drivers/dma/mpc512x_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/mpc512x_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -741,7 +741,6 @@ static int __devinit mpc_dma_probe(struc
 		mchan = &mdma->channels[i];
 
 		mchan->chan.device = dma;
-		mchan->chan.chan_id = i;
 		mchan->chan.cookie = 1;
 		mchan->completed_cookie = mchan->chan.cookie;
 
diff -druNp linux-libre-3.1-gnu1/drivers/dma/mxs-dma.c linux-libre-3.2-gnu1/drivers/dma/mxs-dma.c
--- linux-libre-3.1-gnu1/drivers/dma/mxs-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/mxs-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -130,6 +130,23 @@ struct mxs_dma_engine {
 	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
 };
 
+static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+	int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
+
+	/* enable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+	}
+}
+
 static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
 {
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -148,38 +165,21 @@ static void mxs_dma_enable_chan(struct m
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
 	int chan_id = mxs_chan->chan.chan_id;
 
+	/* clkgate needs to be enabled before writing other registers */
+	mxs_dma_clkgate(mxs_chan, 1);
+
 	/* set cmd_addr up */
 	writel(mxs_chan->ccw_phys,
 		mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
 
-	/* enable apbh channel clock */
-	if (dma_is_apbh()) {
-		if (apbh_is_old())
-			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-		else
-			writel(1 << chan_id,
-				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-	}
-
 	/* write 1 to SEMA to kick off the channel */
 	writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
 }
 
 static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
 {
-	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
-	int chan_id = mxs_chan->chan.chan_id;
-
 	/* disable apbh channel clock */
-	if (dma_is_apbh()) {
-		if (apbh_is_old())
-			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-		else
-			writel(1 << chan_id,
-				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-	}
+	mxs_dma_clkgate(mxs_chan, 0);
 
 	mxs_chan->status = DMA_SUCCESS;
 }
@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(
 	if (ret)
 		goto err_clk;
 
+	/* clkgate needs to be enabled for reset to finish */
+	mxs_dma_clkgate(mxs_chan, 1);
 	mxs_dma_reset_chan(mxs_chan);
+	mxs_dma_clkgate(mxs_chan, 0);
 
 	dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
 	mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
diff -druNp linux-libre-3.1-gnu1/drivers/dma/pch_dma.c linux-libre-3.2-gnu1/drivers/dma/pch_dma.c
--- linux-libre-3.1-gnu1/drivers/dma/pch_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/pch_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@
 #define DMA_DESC_FOLLOW_WITHOUT_IRQ	0x2
 #define DMA_DESC_FOLLOW_WITH_IRQ	0x3
 
-#define MAX_CHAN_NR			8
+#define MAX_CHAN_NR			12
 
 #define DMA_MASK_CTL0_MODE	0x33333333
 #define DMA_MASK_CTL2_MODE	0x00003333
@@ -872,8 +872,7 @@ static int __devinit pch_dma_probe(struc
 	int i;
 
 	nr_channels = id->driver_data;
-	pd = kzalloc(sizeof(struct pch_dma)+
-		sizeof(struct pch_dma_chan) * nr_channels, GFP_KERNEL);
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 	if (!pd)
 		return -ENOMEM;
 
@@ -926,7 +925,6 @@ static int __devinit pch_dma_probe(struc
 	}
 
 	pd->dma.dev = &pdev->dev;
-	pd->dma.chancnt = nr_channels;
 
 	INIT_LIST_HEAD(&pd->dma.channels);
 
@@ -935,7 +933,6 @@ static int __devinit pch_dma_probe(struc
 
 		pd_chan->chan.device = &pd->dma;
 		pd_chan->chan.cookie = 1;
-		pd_chan->chan.chan_id = i;
 
 		pd_chan->membase = &regs->desc[i];
 
diff -druNp linux-libre-3.1-gnu1/drivers/dma/pl330.c linux-libre-3.2-gnu1/drivers/dma/pl330.c
--- linux-libre-3.1-gnu1/drivers/dma/pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/pl330.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
 
 #define NR_DEFAULT_DESC	16
 
@@ -68,6 +70,14 @@ struct dma_pl330_chan {
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* For D-to-M and M-to-D channels */
+	int burst_sz; /* the peripheral fifo width */
+	int burst_len; /* the number of burst */
+	dma_addr_t fifo_addr;
+
+	/* for cyclic capability */
+	bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -83,6 +93,8 @@ struct dma_pl330_dmac {
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan *peripherals; /* keep at end */
+
+	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -152,6 +164,31 @@ static inline void free_desc_list(struct
 	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch;
+	unsigned long flags;
+
+	if (list_empty(list))
+		return;
+
+	list_for_each_entry(desc, list, node) {
+		dma_async_tx_callback callback;
+
+		/* Change status to reload it */
+		desc->status = PREP;
+		pch = desc->pchan;
+		callback = desc->txd.callback;
+		if (callback)
+			callback(desc->txd.callback_param);
+	}
+
+	spin_lock_irqsave(&pch->lock, flags);
+	list_splice_tail_init(list, &pch->work_list);
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
 	struct dma_pl330_desc *desc;
@@ -205,7 +242,10 @@ static void pl330_tasklet(unsigned long
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	free_desc_list(&list);
+	if (pch->cyclic)
+		handle_cyclic_desc_list(&list);
+	else
+		free_desc_list(&list);
 }
 
 static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -236,6 +276,7 @@ static int pl330_alloc_chan_resources(st
 	spin_lock_irqsave(&pch->lock, flags);
 
 	pch->completed = chan->cookie = 1;
+	pch->cyclic = false;
 
 	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
 	if (!pch->pl330_chid) {
@@ -253,25 +294,52 @@ static int pl330_alloc_chan_resources(st
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_desc *desc;
+	struct dma_pl330_desc *desc, *_dt;
 	unsigned long flags;
+	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct dma_slave_config *slave_config;
+	LIST_HEAD(list);
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
-
-	spin_lock_irqsave(&pch->lock, flags);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&pch->lock, flags);
 
-	/* FLUSH the PL330 Channel thread */
-	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+		/* FLUSH the PL330 Channel thread */
+		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-	/* Mark all desc done */
-	list_for_each_entry(desc, &pch->work_list, node)
-		desc->status = DONE;
+		/* Mark all desc done */
+		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+			desc->status = DONE;
+			pch->completed = desc->txd.cookie;
+			list_move_tail(&desc->node, &list);
+		}
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+		list_splice_tail_init(&list, &pdmac->desc_pool);
+		spin_unlock_irqrestore(&pch->lock, flags);
+		break;
+	case DMA_SLAVE_CONFIG:
+		slave_config = (struct dma_slave_config *)arg;
 
-	pl330_tasklet((unsigned long) pch);
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				pch->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				pch->burst_sz = __ffs(slave_config->dst_addr_width);
+			if (slave_config->dst_maxburst)
+				pch->burst_len = slave_config->dst_maxburst;
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				pch->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				pch->burst_sz = __ffs(slave_config->src_addr_width);
+			if (slave_config->src_maxburst)
+				pch->burst_len = slave_config->src_maxburst;
+		}
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+		return -ENXIO;
+	}
 
 	return 0;
 }
@@ -288,6 +356,9 @@ static void pl330_free_chan_resources(st
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic)
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -453,7 +524,7 @@ static struct dma_pl330_desc *pl330_get_
 
 	if (peri) {
 		desc->req.rqtype = peri->rqtype;
-		desc->req.peri = peri->peri_id;
+		desc->req.peri = pch->chan.chan_id;
 	} else {
 		desc->req.rqtype = MEMTOMEM;
 		desc->req.peri = 0;
@@ -524,6 +595,51 @@ static inline int get_burst_len(struct d
 	return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	desc = pl330_get_desc(pch);
+	if (!desc) {
+		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+			__func__, __LINE__);
+		return NULL;
+	}
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		desc->rqcfg.src_inc = 1;
+		desc->rqcfg.dst_inc = 0;
+		src = dma_addr;
+		dst = pch->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = pch->fifo_addr;
+		dst = dma_addr;
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+		__func__, __LINE__);
+		return NULL;
+	}
+
+	desc->rqcfg.brst_size = pch->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	pch->cyclic = true;
+
+	fill_px(&desc->px, dst, src, period_len);
+
+	return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 		dma_addr_t src, size_t len, unsigned long flags)
@@ -579,7 +695,7 @@ pl330_prep_slave_sg(struct dma_chan *cha
 	struct dma_pl330_peri *peri = chan->private;
 	struct scatterlist *sg;
 	unsigned long flags;
-	int i, burst_size;
+	int i;
 	dma_addr_t addr;
 
 	if (unlikely(!pch || !sgl || !sg_len || !peri))
@@ -595,8 +711,7 @@ pl330_prep_slave_sg(struct dma_chan *cha
 		return NULL;
 	}
 
-	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
+	addr = pch->fifo_addr;
 
 	first = NULL;
 
@@ -644,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *cha
 				sg_dma_address(sg), addr, sg_dma_len(sg));
 		}
 
-		desc->rqcfg.brst_size = burst_size;
+		desc->rqcfg.brst_size = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
@@ -696,6 +811,30 @@ pl330_probe(struct amba_device *adev, co
 		goto probe_err1;
 	}
 
+	pdmac->clk = clk_get(&adev->dev, "dma");
+	if (IS_ERR(pdmac->clk)) {
+		dev_err(&adev->dev, "Cannot get operation clock.\n");
+		ret = -EINVAL;
+		goto probe_err1;
+	}
+
+	amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+	/* to use the runtime PM helper functions */
+	pm_runtime_enable(&adev->dev);
+
+	/* enable the power domain */
+	if (pm_runtime_get_sync(&adev->dev)) {
+		dev_err(&adev->dev, "failed to get runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err1;
+	}
+#else
+	/* enable dma clk */
+	clk_enable(pdmac->clk);
+#endif
+
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
@@ -732,6 +871,7 @@ pl330_probe(struct amba_device *adev, co
 			case MEMTODEV:
 			case DEVTOMEM:
 				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				dma_cap_set(DMA_CYCLIC, pd->cap_mask);
 				break;
 			default:
 				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -747,11 +887,9 @@ pl330_probe(struct amba_device *adev, co
 		spin_lock_init(&pch->lock);
 		pch->pl330_chid = NULL;
 		pch->chan.device = pd;
-		pch->chan.chan_id = i;
 		pch->dmac = pdmac;
 
 		/* Add the channel to the DMAC list */
-		pd->chancnt++;
 		list_add_tail(&pch->chan.device_node, &pd->channels);
 	}
 
@@ -760,6 +898,7 @@ pl330_probe(struct amba_device *adev, co
 	pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
 	pd->device_free_chan_resources = pl330_free_chan_resources;
 	pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+	pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
 	pd->device_tx_status = pl330_tx_status;
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_control = pl330_control;
@@ -771,8 +910,6 @@ pl330_probe(struct amba_device *adev, co
 		goto probe_err4;
 	}
 
-	amba_set_drvdata(adev, pdmac);
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -833,6 +970,13 @@ static int __devexit pl330_remove(struct
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
+
 	kfree(pdmac);
 
 	return 0;
@@ -846,10 +990,49 @@ static struct amba_id pl330_ids[] = {
 	{ 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_disable(pdmac->clk);
+
+	return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_enable(pdmac->clk);
+
+	return 0;
+}
+#else
+#define pl330_runtime_suspend	NULL
+#define pl330_runtime_resume	NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+	.runtime_suspend = pl330_runtime_suspend,
+	.runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
+		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
diff -druNp linux-libre-3.1-gnu1/drivers/dma/shdma.c linux-libre-3.2-gnu1/drivers/dma/shdma.c
--- linux-libre-3.1-gnu1/drivers/dma/shdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/shdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -259,14 +259,23 @@ static int dmae_set_dmars(struct sh_dmae
 	return 0;
 }
 
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
 	struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
+	struct sh_dmae_slave *param = tx->chan->private;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
+	bool power_up;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
+
+	if (list_empty(&sh_chan->ld_queue))
+		power_up = true;
+	else
+		power_up = false;
 
 	cookie = sh_chan->common.cookie;
 	cookie++;
@@ -302,7 +311,38 @@ static dma_cookie_t sh_dmae_tx_submit(st
 		tx->cookie, &last->async_tx, sh_chan->id,
 		desc->hw.sar, desc->hw.tcr, desc->hw.dar);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	if (power_up) {
+		sh_chan->pm_state = DMAE_PM_BUSY;
+
+		pm_runtime_get(sh_chan->dev);
+
+		spin_unlock_irq(&sh_chan->desc_lock);
+
+		pm_runtime_barrier(sh_chan->dev);
+
+		spin_lock_irq(&sh_chan->desc_lock);
+
+		/* Have we been reset, while waiting? */
+		if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) {
+			dev_dbg(sh_chan->dev, "Bring up channel %d\n",
+				sh_chan->id);
+			if (param) {
+				const struct sh_dmae_slave_config *cfg =
+					param->config;
+
+				dmae_set_dmars(sh_chan, cfg->mid_rid);
+				dmae_set_chcr(sh_chan, cfg->chcr);
+			} else {
+				dmae_init(sh_chan);
+			}
+
+			if (sh_chan->pm_state == DMAE_PM_PENDING)
+				sh_chan_xfer_ld_queue(sh_chan);
+			sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+		}
+	}
+
+	spin_unlock_irq(&sh_chan->desc_lock);
 
 	return cookie;
 }
@@ -346,8 +386,6 @@ static int sh_dmae_alloc_chan_resources(
 	struct sh_dmae_slave *param = chan->private;
 	int ret;
 
-	pm_runtime_get_sync(sh_chan->dev);
-
 	/*
 	 * This relies on the guarantee from dmaengine that alloc_chan_resources
 	 * never runs concurrently with itself or free_chan_resources.
@@ -367,31 +405,20 @@ static int sh_dmae_alloc_chan_resources(
 		}
 
 		param->config = cfg;
-
-		dmae_set_dmars(sh_chan, cfg->mid_rid);
-		dmae_set_chcr(sh_chan, cfg->chcr);
-	} else {
-		dmae_init(sh_chan);
 	}
 
-	spin_lock_bh(&sh_chan->desc_lock);
 	while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
-		spin_unlock_bh(&sh_chan->desc_lock);
 		desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);
-		if (!desc) {
-			spin_lock_bh(&sh_chan->desc_lock);
+		if (!desc)
 			break;
-		}
 		dma_async_tx_descriptor_init(&desc->async_tx,
 					&sh_chan->common);
 		desc->async_tx.tx_submit = sh_dmae_tx_submit;
 		desc->mark = DESC_IDLE;
 
-		spin_lock_bh(&sh_chan->desc_lock);
 		list_add(&desc->node, &sh_chan->ld_free);
 		sh_chan->descs_allocated++;
 	}
-	spin_unlock_bh(&sh_chan->desc_lock);
 
 	if (!sh_chan->descs_allocated) {
 		ret = -ENOMEM;
@@ -405,7 +432,7 @@ edescalloc:
 		clear_bit(param->slave_id, sh_dmae_slave_used);
 etestused:
 efindslave:
-	pm_runtime_put(sh_chan->dev);
+	chan->private = NULL;
 	return ret;
 }
 
@@ -417,7 +444,6 @@ static void sh_dmae_free_chan_resources(
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 	struct sh_desc *desc, *_desc;
 	LIST_HEAD(list);
-	int descs = sh_chan->descs_allocated;
 
 	/* Protect against ISR */
 	spin_lock_irq(&sh_chan->desc_lock);
@@ -437,15 +463,12 @@ static void sh_dmae_free_chan_resources(
 		chan->private = NULL;
 	}
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
 
 	list_splice_init(&sh_chan->ld_free, &list);
 	sh_chan->descs_allocated = 0;
 
-	spin_unlock_bh(&sh_chan->desc_lock);
-
-	if (descs > 0)
-		pm_runtime_put(sh_chan->dev);
+	spin_unlock_irq(&sh_chan->desc_lock);
 
 	list_for_each_entry_safe(desc, _desc, &list, node)
 		kfree(desc);
@@ -534,6 +557,7 @@ static struct dma_async_tx_descriptor *s
 	struct sh_desc *first = NULL, *new = NULL /* compiler... */;
 	LIST_HEAD(tx_list);
 	int chunks = 0;
+	unsigned long irq_flags;
 	int i;
 
 	if (!sg_len)
@@ -544,7 +568,7 @@ static struct dma_async_tx_descriptor *s
 			(SH_DMA_TCR_MAX + 1);
 
 	/* Have to lock the whole loop to protect against concurrent release */
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, irq_flags);
 
 	/*
 	 * Chaining:
@@ -590,7 +614,7 @@ static struct dma_async_tx_descriptor *s
 	/* Put them back on the free list, so, they don't get lost */
 	list_splice_tail(&tx_list, &sh_chan->ld_free);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
 	return &first->async_tx;
 
@@ -599,7 +623,7 @@ err_get_desc:
 		new->mark = DESC_IDLE;
 	list_splice(&tx_list, &sh_chan->ld_free);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
 	return NULL;
 }
@@ -661,6 +685,7 @@ static int sh_dmae_control(struct dma_ch
 			   unsigned long arg)
 {
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+	unsigned long flags;
 
 	/* Only supports DMA_TERMINATE_ALL */
 	if (cmd != DMA_TERMINATE_ALL)
@@ -669,7 +694,7 @@ static int sh_dmae_control(struct dma_ch
 	if (!chan)
 		return -EINVAL;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 	dmae_halt(sh_chan);
 
 	if (!list_empty(&sh_chan->ld_queue)) {
@@ -678,9 +703,8 @@ static int sh_dmae_control(struct dma_ch
 						  struct sh_desc, node);
 		desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
 			sh_chan->xmit_shift;
-
 	}
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	sh_dmae_chan_ld_cleanup(sh_chan, true);
 
@@ -695,8 +719,9 @@ static dma_async_tx_callback __ld_cleanu
 	dma_cookie_t cookie = 0;
 	dma_async_tx_callback callback = NULL;
 	void *param = NULL;
+	unsigned long flags;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 	list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
 		struct dma_async_tx_descriptor *tx = &desc->async_tx;
 
@@ -762,7 +787,13 @@ static dma_async_tx_callback __ld_cleanu
 		     async_tx_test_ack(&desc->async_tx)) || all) {
 			/* Remove from ld_queue list */
 			desc->mark = DESC_IDLE;
+
 			list_move(&desc->node, &sh_chan->ld_free);
+
+			if (list_empty(&sh_chan->ld_queue)) {
+				dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+				pm_runtime_put(sh_chan->dev);
+			}
 		}
 	}
 
@@ -773,7 +804,7 @@ static dma_async_tx_callback __ld_cleanu
 		 */
 		sh_chan->completed_cookie = sh_chan->common.cookie;
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	if (callback)
 		callback(param);
@@ -792,14 +823,14 @@ static void sh_dmae_chan_ld_cleanup(stru
 		;
 }
 
+/* Called under spin_lock_irq(&sh_chan->desc_lock) */
 static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 {
 	struct sh_desc *desc;
 
-	spin_lock_bh(&sh_chan->desc_lock);
 	/* DMA work check */
 	if (dmae_is_busy(sh_chan))
-		goto sh_chan_xfer_ld_queue_end;
+		return;
 
 	/* Find the first not transferred descriptor */
 	list_for_each_entry(desc, &sh_chan->ld_queue, node)
@@ -812,15 +843,18 @@ static void sh_chan_xfer_ld_queue(struct
 			dmae_start(sh_chan);
 			break;
 		}
-
-sh_chan_xfer_ld_queue_end:
-	spin_unlock_bh(&sh_chan->desc_lock);
 }
 
 static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
 {
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-	sh_chan_xfer_ld_queue(sh_chan);
+
+	spin_lock_irq(&sh_chan->desc_lock);
+	if (sh_chan->pm_state == DMAE_PM_ESTABLISHED)
+		sh_chan_xfer_ld_queue(sh_chan);
+	else
+		sh_chan->pm_state = DMAE_PM_PENDING;
+	spin_unlock_irq(&sh_chan->desc_lock);
 }
 
 static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
@@ -831,6 +865,7 @@ static enum dma_status sh_dmae_tx_status
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
 	enum dma_status status;
+	unsigned long flags;
 
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 
@@ -841,7 +876,7 @@ static enum dma_status sh_dmae_tx_status
 	BUG_ON(last_complete < 0);
 	dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 
 	status = dma_async_is_complete(cookie, last_complete, last_used);
 
@@ -859,7 +894,7 @@ static enum dma_status sh_dmae_tx_status
 			}
 	}
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	return status;
 }
@@ -912,6 +947,12 @@ static bool sh_dmae_reset(struct sh_dmae
 
 		list_splice_init(&sh_chan->ld_queue, &dl);
 
+		if (!list_empty(&dl)) {
+			dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+			pm_runtime_put(sh_chan->dev);
+		}
+		sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
 		spin_unlock(&sh_chan->desc_lock);
 
 		/* Complete all  */
@@ -952,7 +993,7 @@ static void dmae_do_tasklet(unsigned lon
 	u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
 	u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
 
-	spin_lock(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
 	list_for_each_entry(desc, &sh_chan->ld_queue, node) {
 		if (desc->mark == DESC_SUBMITTED &&
 		    ((desc->direction == DMA_FROM_DEVICE &&
@@ -965,10 +1006,10 @@ static void dmae_do_tasklet(unsigned lon
 			break;
 		}
 	}
-	spin_unlock(&sh_chan->desc_lock);
-
 	/* Next desc */
 	sh_chan_xfer_ld_queue(sh_chan);
+	spin_unlock_irq(&sh_chan->desc_lock);
+
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
@@ -1036,7 +1077,9 @@ static int __devinit sh_dmae_chan_probe(
 		return -ENOMEM;
 	}
 
-	/* copy struct dma_device */
+	new_sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
+	/* reference struct dma_device */
 	new_sh_chan->common.device = &shdev->common;
 
 	new_sh_chan->dev = shdev->common.dev;
diff -druNp linux-libre-3.1-gnu1/drivers/dma/shdma.h linux-libre-3.2-gnu1/drivers/dma/shdma.h
--- linux-libre-3.1-gnu1/drivers/dma/shdma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/shdma.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,12 @@
 
 struct device;
 
+enum dmae_pm_state {
+	DMAE_PM_ESTABLISHED,
+	DMAE_PM_BUSY,
+	DMAE_PM_PENDING,
+};
+
 struct sh_dmae_chan {
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
@@ -38,6 +44,7 @@ struct sh_dmae_chan {
 	u32 __iomem *base;
 	char dev_id[16];		/* unique name per DMAC of channel */
 	int pm_error;
+	enum dmae_pm_state pm_state;
 };
 
 struct sh_dmae_device {
diff -druNp linux-libre-3.1-gnu1/drivers/dma/ste_dma40.c linux-libre-3.2-gnu1/drivers/dma/ste_dma40.c
--- linux-libre-3.1-gnu1/drivers/dma/ste_dma40.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/ste_dma40.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dmaengine.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
diff -druNp linux-libre-3.1-gnu1/drivers/dma/timb_dma.c linux-libre-3.2-gnu1/drivers/dma/timb_dma.c
--- linux-libre-3.1-gnu1/drivers/dma/timb_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/dma/timb_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,7 +753,7 @@ static int __devinit td_probe(struct pla
 
 	INIT_LIST_HEAD(&td->dma.channels);
 
-	for (i = 0; i < pdata->nr_channels; i++, td->dma.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct timb_dma_chan *td_chan = &td->channels[i];
 		struct timb_dma_platform_data_channel *pchan =
 			pdata->channels + i;
@@ -762,12 +762,11 @@ static int __devinit td_probe(struct pla
 		if ((i % 2) == pchan->rx) {
 			dev_err(&pdev->dev, "Wrong channel configuration\n");
 			err = -EINVAL;
-			goto err_tasklet_kill;
+			goto err_free_irq;
 		}
 
 		td_chan->chan.device = &td->dma;
 		td_chan->chan.cookie = 1;
-		td_chan->chan.chan_id = i;
 		spin_lock_init(&td_chan->lock);
 		INIT_LIST_HEAD(&td_chan->active_list);
 		INIT_LIST_HEAD(&td_chan->queue);
diff -druNp linux-libre-3.1-gnu1/drivers/edac/amd64_edac.c linux-libre-3.2-gnu1/drivers/edac/amd64_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/amd64_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/amd64_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,10 +114,22 @@ static int f10_read_dct_pci_cfg(struct a
 	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
 }
 
+/*
+ * Select DCT to which PCI cfg accesses are routed
+ */
+static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct)
+{
+	u32 reg = 0;
+
+	amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
+	reg &= 0xfffffffe;
+	reg |= dct;
+	amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+}
+
 static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
 				 const char *func)
 {
-	u32 reg = 0;
 	u8 dct  = 0;
 
 	if (addr >= 0x140 && addr <= 0x1a0) {
@@ -125,10 +137,7 @@ static int f15_read_dct_pci_cfg(struct a
 		addr -= 0x100;
 	}
 
-	amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
-	reg &= 0xfffffffe;
-	reg |= dct;
-	amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+	f15h_select_dct(pvt, dct);
 
 	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
 }
@@ -198,6 +207,10 @@ static int amd64_set_scrub_rate(struct m
 	if (boot_cpu_data.x86 == 0xf)
 		min_scrubrate = 0x0;
 
+	/* F15h Erratum #505 */
+	if (boot_cpu_data.x86 == 0x15)
+		f15h_select_dct(pvt, 0);
+
 	return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
 }
 
@@ -207,6 +220,10 @@ static int amd64_get_scrub_rate(struct m
 	u32 scrubval = 0;
 	int i, retval = -EINVAL;
 
+	/* F15h Erratum #505 */
+	if (boot_cpu_data.x86 == 0x15)
+		f15h_select_dct(pvt, 0);
+
 	amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
 
 	scrubval = scrubval & 0x001F;
@@ -751,10 +768,10 @@ static int get_channel_from_ecc_syndrome
  * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
  * are ECC capable.
  */
-static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
+static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
 {
 	u8 bit;
-	enum dev_type edac_cap = EDAC_FLAG_NONE;
+	unsigned long edac_cap = EDAC_FLAG_NONE;
 
 	bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F)
 		? 19
@@ -1953,11 +1970,9 @@ static inline void __amd64_decode_bus_er
 		amd64_handle_ue(mci, m);
 }
 
-void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
+void amd64_decode_bus_error(int node_id, struct mce *m)
 {
-	struct mem_ctl_info *mci = mcis[node_id];
-
-	__amd64_decode_bus_error(mci, m);
+	__amd64_decode_bus_error(mcis[node_id], m);
 }
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/edac/cpc925_edac.c linux-libre-3.2-gnu1/drivers/edac/cpc925_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/cpc925_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/cpc925_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,6 +90,7 @@ enum apimask_bits {
 	ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H |
 			   APIMASK_ECC_UE_L | APIMASK_ECC_CE_L),
 };
+#define APIMASK_ADI(n)		CPC925_BIT(((n)+1))
 
 /************************************************************
  *	Processor Interface Exception Register (APIEXCP)
@@ -581,16 +582,73 @@ static void cpc925_mc_check(struct mem_c
 }
 
 /******************** CPU err device********************************/
+static u32 cpc925_cpu_mask_disabled(void)
+{
+	struct device_node *cpus;
+	struct device_node *cpunode = NULL;
+	static u32 mask = 0;
+
+	/* use cached value if available */
+	if (mask != 0)
+		return mask;
+
+	mask = APIMASK_ADI0 | APIMASK_ADI1;
+
+	cpus = of_find_node_by_path("/cpus");
+	if (cpus == NULL) {
+		cpc925_printk(KERN_DEBUG, "No /cpus node !\n");
+		return 0;
+	}
+
+	while ((cpunode = of_get_next_child(cpus, cpunode)) != NULL) {
+		const u32 *reg = of_get_property(cpunode, "reg", NULL);
+
+		if (strcmp(cpunode->type, "cpu")) {
+			cpc925_printk(KERN_ERR, "Not a cpu node in /cpus: %s\n", cpunode->name);
+			continue;
+		}
+
+		if (reg == NULL || *reg > 2) {
+			cpc925_printk(KERN_ERR, "Bad reg value at %s\n", cpunode->full_name);
+			continue;
+		}
+
+		mask &= ~APIMASK_ADI(*reg);
+	}
+
+	if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) {
+		/* We assume that each CPU sits on it's own PI and that
+		 * for present CPUs the reg property equals to the PI
+		 * interface id */
+		cpc925_printk(KERN_WARNING,
+				"Assuming PI id is equal to CPU MPIC id!\n");
+	}
+
+	of_node_put(cpunode);
+	of_node_put(cpus);
+
+	return mask;
+}
+
 /* Enable CPU Errors detection */
 static void cpc925_cpu_init(struct cpc925_dev_info *dev_info)
 {
 	u32 apimask;
+	u32 cpumask;
 
 	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
-	if ((apimask & CPU_MASK_ENABLE) == 0) {
-		apimask |= CPU_MASK_ENABLE;
-		__raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
+
+	cpumask = cpc925_cpu_mask_disabled();
+	if (apimask & cpumask) {
+		cpc925_printk(KERN_WARNING, "CPU(s) not present, "
+				"but enabled in APIMASK, disabling\n");
+		apimask &= ~cpumask;
 	}
+
+	if ((apimask & CPU_MASK_ENABLE) == 0)
+		apimask |= CPU_MASK_ENABLE;
+
+	__raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
 }
 
 /* Disable CPU Errors detection */
@@ -622,6 +680,9 @@ static void cpc925_cpu_check(struct edac
 	if ((apiexcp & CPU_EXCP_DETECTED) == 0)
 		return;
 
+	if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0)
+		return;
+
 	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
 	cpc925_printk(KERN_INFO, "Processor Interface Fault\n"
 				 "Processor Interface register dump:\n");
diff -druNp linux-libre-3.1-gnu1/drivers/edac/edac_core.h linux-libre-3.2-gnu1/drivers/edac/edac_core.h
--- linux-libre-3.1-gnu1/drivers/edac/edac_core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/edac_core.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,11 +34,10 @@
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/workqueue.h>
+#include <linux/edac.h>
 
-#define EDAC_MC_LABEL_LEN	31
 #define EDAC_DEVICE_NAME_LEN	31
 #define EDAC_ATTRIB_VALUE_LEN	15
-#define MC_PROC_NAME_MAX_LEN	7
 
 #if PAGE_SHIFT < 20
 #define PAGES_TO_MiB(pages)	((pages) >> (20 - PAGE_SHIFT))
@@ -101,353 +100,6 @@ extern int edac_debug_level;
 
 #define edac_dev_name(dev) (dev)->dev_name
 
-/* memory devices */
-enum dev_type {
-	DEV_UNKNOWN = 0,
-	DEV_X1,
-	DEV_X2,
-	DEV_X4,
-	DEV_X8,
-	DEV_X16,
-	DEV_X32,		/* Do these parts exist? */
-	DEV_X64			/* Do these parts exist? */
-};
-
-#define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
-#define DEV_FLAG_X1		BIT(DEV_X1)
-#define DEV_FLAG_X2		BIT(DEV_X2)
-#define DEV_FLAG_X4		BIT(DEV_X4)
-#define DEV_FLAG_X8		BIT(DEV_X8)
-#define DEV_FLAG_X16		BIT(DEV_X16)
-#define DEV_FLAG_X32		BIT(DEV_X32)
-#define DEV_FLAG_X64		BIT(DEV_X64)
-
-/* memory types */
-enum mem_type {
-	MEM_EMPTY = 0,		/* Empty csrow */
-	MEM_RESERVED,		/* Reserved csrow type */
-	MEM_UNKNOWN,		/* Unknown csrow type */
-	MEM_FPM,		/* Fast page mode */
-	MEM_EDO,		/* Extended data out */
-	MEM_BEDO,		/* Burst Extended data out */
-	MEM_SDR,		/* Single data rate SDRAM */
-	MEM_RDR,		/* Registered single data rate SDRAM */
-	MEM_DDR,		/* Double data rate SDRAM */
-	MEM_RDDR,		/* Registered Double data rate SDRAM */
-	MEM_RMBS,		/* Rambus DRAM */
-	MEM_DDR2,		/* DDR2 RAM */
-	MEM_FB_DDR2,		/* fully buffered DDR2 */
-	MEM_RDDR2,		/* Registered DDR2 RAM */
-	MEM_XDR,		/* Rambus XDR */
-	MEM_DDR3,		/* DDR3 RAM */
-	MEM_RDDR3,		/* Registered DDR3 RAM */
-};
-
-#define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
-#define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
-#define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
-#define MEM_FLAG_FPM		BIT(MEM_FPM)
-#define MEM_FLAG_EDO		BIT(MEM_EDO)
-#define MEM_FLAG_BEDO		BIT(MEM_BEDO)
-#define MEM_FLAG_SDR		BIT(MEM_SDR)
-#define MEM_FLAG_RDR		BIT(MEM_RDR)
-#define MEM_FLAG_DDR		BIT(MEM_DDR)
-#define MEM_FLAG_RDDR		BIT(MEM_RDDR)
-#define MEM_FLAG_RMBS		BIT(MEM_RMBS)
-#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
-#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
-#define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
-#define MEM_FLAG_XDR            BIT(MEM_XDR)
-#define MEM_FLAG_DDR3		 BIT(MEM_DDR3)
-#define MEM_FLAG_RDDR3		 BIT(MEM_RDDR3)
-
-/* chipset Error Detection and Correction capabilities and mode */
-enum edac_type {
-	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
-	EDAC_NONE,		/* Doesn't support ECC */
-	EDAC_RESERVED,		/* Reserved ECC type */
-	EDAC_PARITY,		/* Detects parity errors */
-	EDAC_EC,		/* Error Checking - no correction */
-	EDAC_SECDED,		/* Single bit error correction, Double detection */
-	EDAC_S2ECD2ED,		/* Chipkill x2 devices - do these exist? */
-	EDAC_S4ECD4ED,		/* Chipkill x4 devices */
-	EDAC_S8ECD8ED,		/* Chipkill x8 devices */
-	EDAC_S16ECD16ED,	/* Chipkill x16 devices */
-};
-
-#define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
-#define EDAC_FLAG_NONE		BIT(EDAC_NONE)
-#define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
-#define EDAC_FLAG_EC		BIT(EDAC_EC)
-#define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
-#define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
-#define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
-#define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
-#define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
-
-/* scrubbing capabilities */
-enum scrub_type {
-	SCRUB_UNKNOWN = 0,	/* Unknown if scrubber is available */
-	SCRUB_NONE,		/* No scrubber */
-	SCRUB_SW_PROG,		/* SW progressive (sequential) scrubbing */
-	SCRUB_SW_SRC,		/* Software scrub only errors */
-	SCRUB_SW_PROG_SRC,	/* Progressive software scrub from an error */
-	SCRUB_SW_TUNABLE,	/* Software scrub frequency is tunable */
-	SCRUB_HW_PROG,		/* HW progressive (sequential) scrubbing */
-	SCRUB_HW_SRC,		/* Hardware scrub only errors */
-	SCRUB_HW_PROG_SRC,	/* Progressive hardware scrub from an error */
-	SCRUB_HW_TUNABLE	/* Hardware scrub frequency is tunable */
-};
-
-#define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
-#define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC)
-#define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC)
-#define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
-#define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
-#define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC)
-#define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC)
-#define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
-
-/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
-
-/* EDAC internal operation states */
-#define	OP_ALLOC		0x100
-#define OP_RUNNING_POLL		0x201
-#define OP_RUNNING_INTERRUPT	0x202
-#define OP_RUNNING_POLL_INTR	0x203
-#define OP_OFFLINE		0x300
-
-/*
- * There are several things to be aware of that aren't at all obvious:
- *
- *
- * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
- *
- * These are some of the many terms that are thrown about that don't always
- * mean what people think they mean (Inconceivable!).  In the interest of
- * creating a common ground for discussion, terms and their definitions
- * will be established.
- *
- * Memory devices:	The individual chip on a memory stick.  These devices
- *			commonly output 4 and 8 bits each.  Grouping several
- *			of these in parallel provides 64 bits which is common
- *			for a memory stick.
- *
- * Memory Stick:	A printed circuit board that aggregates multiple
- *			memory devices in parallel.  This is the atomic
- *			memory component that is purchaseable by Joe consumer
- *			and loaded into a memory socket.
- *
- * Socket:		A physical connector on the motherboard that accepts
- *			a single memory stick.
- *
- * Channel:		Set of memory devices on a memory stick that must be
- *			grouped in parallel with one or more additional
- *			channels from other memory sticks.  This parallel
- *			grouping of the output from multiple channels are
- *			necessary for the smallest granularity of memory access.
- *			Some memory controllers are capable of single channel -
- *			which means that memory sticks can be loaded
- *			individually.  Other memory controllers are only
- *			capable of dual channel - which means that memory
- *			sticks must be loaded as pairs (see "socket set").
- *
- * Chip-select row:	All of the memory devices that are selected together.
- *			for a single, minimum grain of memory access.
- *			This selects all of the parallel memory devices across
- *			all of the parallel channels.  Common chip-select rows
- *			for single channel are 64 bits, for dual channel 128
- *			bits.
- *
- * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memory.
- *			Motherboards commonly drive two chip-select pins to
- *			a memory stick. A single-ranked stick, will occupy
- *			only one of those rows. The other will be unused.
- *
- * Double-Ranked stick:	A double-ranked stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.
- *
- * Double-sided stick:	DEPRECATED TERM, see Double-Ranked stick.
- *			A double-sided stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.  "Double-sided"
- *			is irrespective of the memory devices being mounted
- *			on both sides of the memory stick.
- *
- * Socket set:		All of the memory sticks that are required for
- *			a single memory access or all of the memory sticks
- *			spanned by a chip-select row.  A single socket set
- *			has two chip-select rows and if double-sided sticks
- *			are used these will occupy those chip-select rows.
- *
- * Bank:		This term is avoided because it is unclear when
- *			needing to distinguish between chip-select rows and
- *			socket sets.
- *
- * Controller pages:
- *
- * Physical pages:
- *
- * Virtual pages:
- *
- *
- * STRUCTURE ORGANIZATION AND CHOICES
- *
- *
- *
- * PS - I enjoyed writing all that about as much as you enjoyed reading it.
- */
-
-struct channel_info {
-	int chan_idx;		/* channel index */
-	u32 ce_count;		/* Correctable Errors for this CHANNEL */
-	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
-	struct csrow_info *csrow;	/* the parent */
-};
-
-struct csrow_info {
-	unsigned long first_page;	/* first page number in dimm */
-	unsigned long last_page;	/* last page number in dimm */
-	unsigned long page_mask;	/* used for interleaving -
-					 * 0UL for non intlv
-					 */
-	u32 nr_pages;		/* number of pages in csrow */
-	u32 grain;		/* granularity of reported error in bytes */
-	int csrow_idx;		/* the chip-select row */
-	enum dev_type dtype;	/* memory device type */
-	u32 ue_count;		/* Uncorrectable Errors for this csrow */
-	u32 ce_count;		/* Correctable Errors for this csrow */
-	enum mem_type mtype;	/* memory csrow type */
-	enum edac_type edac_mode;	/* EDAC mode for this csrow */
-	struct mem_ctl_info *mci;	/* the parent */
-
-	struct kobject kobj;	/* sysfs kobject for this csrow */
-
-	/* channel information for this csrow */
-	u32 nr_channels;
-	struct channel_info *channels;
-};
-
-struct mcidev_sysfs_group {
-	const char *name;				/* group name */
-	const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
-};
-
-struct mcidev_sysfs_group_kobj {
-	struct list_head list;		/* list for all instances within a mc */
-
-	struct kobject kobj;		/* kobj for the group */
-
-	const struct mcidev_sysfs_group *grp;	/* group description table */
-	struct mem_ctl_info *mci;	/* the parent */
-};
-
-/* mcidev_sysfs_attribute structure
- *	used for driver sysfs attributes and in mem_ctl_info
- * 	sysfs top level entries
- */
-struct mcidev_sysfs_attribute {
-	/* It should use either attr or grp */
-	struct attribute attr;
-	const struct mcidev_sysfs_group *grp;	/* Points to a group of attributes */
-
-	/* Ops for show/store values at the attribute - not used on group */
-        ssize_t (*show)(struct mem_ctl_info *,char *);
-        ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
-};
-
-/* MEMORY controller information structure
- */
-struct mem_ctl_info {
-	struct list_head link;	/* for global list of mem_ctl_info structs */
-
-	struct module *owner;	/* Module owner of this control struct */
-
-	unsigned long mtype_cap;	/* memory types supported by mc */
-	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
-	unsigned long edac_cap;	/* configuration capabilities - this is
-				 * closely related to edac_ctl_cap.  The
-				 * difference is that the controller may be
-				 * capable of s4ecd4ed which would be listed
-				 * in edac_ctl_cap, but if channels aren't
-				 * capable of s4ecd4ed then the edac_cap would
-				 * not have that capability.
-				 */
-	unsigned long scrub_cap;	/* chipset scrub capabilities */
-	enum scrub_type scrub_mode;	/* current scrub mode */
-
-	/* Translates sdram memory scrub rate given in bytes/sec to the
-	   internal representation and configures whatever else needs
-	   to be configured.
-	 */
-	int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
-
-	/* Get the current sdram memory scrub rate from the internal
-	   representation and converts it to the closest matching
-	   bandwidth in bytes/sec.
-	 */
-	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
-
-
-	/* pointer to edac checking routine */
-	void (*edac_check) (struct mem_ctl_info * mci);
-
-	/*
-	 * Remaps memory pages: controller pages to physical pages.
-	 * For most MC's, this will be NULL.
-	 */
-	/* FIXME - why not send the phys page to begin with? */
-	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
-					   unsigned long page);
-	int mc_idx;
-	int nr_csrows;
-	struct csrow_info *csrows;
-	/*
-	 * FIXME - what about controllers on other busses? - IDs must be
-	 * unique.  dev pointer should be sufficiently unique, but
-	 * BUS:SLOT.FUNC numbers may not be unique.
-	 */
-	struct device *dev;
-	const char *mod_name;
-	const char *mod_ver;
-	const char *ctl_name;
-	const char *dev_name;
-	char proc_name[MC_PROC_NAME_MAX_LEN + 1];
-	void *pvt_info;
-	u32 ue_noinfo_count;	/* Uncorrectable Errors w/o info */
-	u32 ce_noinfo_count;	/* Correctable Errors w/o info */
-	u32 ue_count;		/* Total Uncorrectable Errors for this MC */
-	u32 ce_count;		/* Total Correctable Errors for this MC */
-	unsigned long start_time;	/* mci load start time (in jiffies) */
-
-	struct completion complete;
-
-	/* edac sysfs device control */
-	struct kobject edac_mci_kobj;
-
-	/* list for all grp instances within a mc */
-	struct list_head grp_kobj_list;
-
-	/* Additional top controller level attributes, but specified
-	 * by the low level driver.
-	 *
-	 * Set by the low level driver to provide attributes at the
-	 * controller level, same level as 'ue_count' and 'ce_count' above.
-	 * An array of structures, NULL terminated
-	 *
-	 * If attributes are desired, then set to array of attributes
-	 * If no attributes are desired, leave NULL
-	 */
-	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
-
-	/* work struct for this MC */
-	struct delayed_work work;
-
-	/* the internal state of this controller instance */
-	int op_state;
-};
-
 /*
  * The following are the structures to provide for a generic
  * or abstract 'edac_device'. This set of structures and the
diff -druNp linux-libre-3.1-gnu1/drivers/edac/edac_mce.c linux-libre-3.2-gnu1/drivers/edac/edac_mce.c
--- linux-libre-3.1-gnu1/drivers/edac/edac_mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/edac_mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* Provides edac interface to mcelog events
- *
- * This file may be distributed under the terms of the
- * GNU General Public License version 2.
- *
- * Copyright (c) 2009 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Red Hat Inc. http://www.redhat.com
- */
-
-#include <linux/module.h>
-#include <linux/edac_mce.h>
-#include <asm/mce.h>
-
-int edac_mce_enabled;
-EXPORT_SYMBOL_GPL(edac_mce_enabled);
-
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(edac_mce_list);
-static DEFINE_MUTEX(edac_mce_lock);
-
-int edac_mce_register(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_add_tail(&edac_mce->list, &edac_mce_list);
-	mutex_unlock(&edac_mce_lock);
-	return 0;
-}
-EXPORT_SYMBOL(edac_mce_register);
-
-void edac_mce_unregister(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_del(&edac_mce->list);
-	mutex_unlock(&edac_mce_lock);
-}
-EXPORT_SYMBOL(edac_mce_unregister);
-
-int edac_mce_parse(struct mce *mce)
-{
-	struct edac_mce *edac_mce;
-
-	list_for_each_entry(edac_mce, &edac_mce_list, list) {
-		if (edac_mce->check_error(edac_mce->priv, mce))
-			return 1;
-	}
-
-	/* Nobody queued the error */
-	return 0;
-}
-EXPORT_SYMBOL_GPL(edac_mce_parse);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff -druNp linux-libre-3.1-gnu1/drivers/edac/i7300_edac.c linux-libre-3.2-gnu1/drivers/edac/i7300_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/i7300_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/i7300_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -372,7 +372,7 @@ static const char *get_err_from_table(co
 static void i7300_process_error_global(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, error_reg;
 	unsigned long errors;
 	const char *specific;
 	bool is_fatal;
@@ -381,9 +381,9 @@ static void i7300_process_error_global(s
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_HI, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_HI, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_hi_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
@@ -391,15 +391,15 @@ static void i7300_process_error_global(s
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_HI, value);
+				       FERR_GLOBAL_HI, error_reg);
 
 		goto error_global;
 	}
 
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_LO, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_LO, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_lo_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
@@ -407,7 +407,7 @@ static void i7300_process_error_global(s
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+				       FERR_GLOBAL_LO, error_reg);
 
 		goto error_global;
 	}
@@ -427,7 +427,7 @@ error_global:
 static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, value, error_reg;
 	u16 val16;
 	unsigned branch, channel, bank, rank, cas, ras;
 	u32 syndrome;
@@ -440,14 +440,14 @@ static void i7300_process_fbd_error(stru
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_FAT_FBD, &value);
-	if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) {
-		errors = value & FERR_FAT_FBD_ERR_MASK ;
+			      FERR_FAT_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_fat_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     NRECMEMA, &val16);
 		bank = NRECMEMA_BANK(val16);
@@ -455,11 +455,14 @@ static void i7300_process_fbd_error(stru
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				NRECMEMB, &value);
-
 		is_wr = NRECMEMB_IS_WR(value);
 		cas = NRECMEMB_CAS(value);
 		ras = NRECMEMB_RAS(value);
 
+		/* Clean the error register */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_FAT_FBD, error_reg);
+
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"FATAL (Branch=%d DRAM-Bank=%d %s "
 			"RAS=%d CAS=%d Err=0x%lx (%s))",
@@ -476,21 +479,17 @@ static void i7300_process_fbd_error(stru
 
 	/* read in the 1st NON-FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_NF_FBD, &value);
-	if (unlikely(value & FERR_NF_FBD_ERR_MASK)) {
-		errors = value & FERR_NF_FBD_ERR_MASK;
+			      FERR_NF_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_NF_FBD_ERR_MASK;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_nf_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-
-		/* Clear the error bit */
-		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 			REDMEMA, &syndrome);
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     RECMEMA, &val16);
 		bank = RECMEMA_BANK(val16);
@@ -498,18 +497,20 @@ static void i7300_process_fbd_error(stru
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				RECMEMB, &value);
-
 		is_wr = RECMEMB_IS_WR(value);
 		cas = RECMEMB_CAS(value);
 		ras = RECMEMB_RAS(value);
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				     REDMEMB, &value);
-
 		channel = (branch << 1);
 		if (IS_SECOND_CH(value))
 			channel++;
 
+		/* Clear the error bit */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_NF_FBD, error_reg);
+
 		/* Form out message */
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"Corrected error (Branch=%d, Channel %d), "
diff -druNp linux-libre-3.1-gnu1/drivers/edac/i7core_edac.c linux-libre-3.2-gnu1/drivers/edac/i7core_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/i7core_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/i7core_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,13 @@
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/edac.h>
 #include <linux/mmzone.h>
-#include <linux/edac_mce.h>
 #include <linux/smp.h>
+#include <asm/mce.h>
 #include <asm/processor.h>
+#include <asm/div64.h>
 
 #include "edac_core.h"
 
@@ -78,6 +80,8 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable
 	/* OFFSETS for Device 0 Function 0 */
 
 #define MC_CFG_CONTROL	0x90
+  #define MC_CFG_UNLOCK		0x02
+  #define MC_CFG_LOCK		0x00
 
 	/* OFFSETS for Device 3 Function 0 */
 
@@ -98,6 +102,15 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable
   #define DIMM0_COR_ERR(r)			((r) & 0x7fff)
 
 /* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_SSRCONTROL		0x48
+  #define SSR_MODE_DISABLE	0x00
+  #define SSR_MODE_ENABLE	0x01
+  #define SSR_MODE_MASK		0x03
+
+#define MC_SCRUB_CONTROL	0x4c
+  #define STARTSCRUB		(1 << 24)
+  #define SCRUBINTERVAL_MASK    0xffffff
+
 #define MC_COR_ECC_CNT_0	0x80
 #define MC_COR_ECC_CNT_1	0x84
 #define MC_COR_ECC_CNT_2	0x88
@@ -253,10 +266,7 @@ struct i7core_pvt {
 	unsigned long	rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
 	int		rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
 
-	unsigned int	is_registered;
-
-	/* mcelog glue */
-	struct edac_mce		edac_mce;
+	bool		is_registered, enable_scrub;
 
 	/* Fifo double buffers */
 	struct mce		mce_entry[MCE_LOG_LEN];
@@ -268,6 +278,9 @@ struct i7core_pvt {
 	/* Count indicator to show errors not got */
 	unsigned		mce_overrun;
 
+	/* DCLK Frequency used for computing scrub rate */
+	int			dclk_freq;
+
 	/* Struct to control EDAC polling */
 	struct edac_pci_ctl_info *i7core_pci;
 };
@@ -281,8 +294,7 @@ static const struct pci_id_descr pci_dev
 		/* Memory controller */
 	{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
 	{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
-
-		/* Exists only for RDIMM */
+			/* Exists only for RDIMM */
 	{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1  },
 	{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
 
@@ -303,6 +315,16 @@ static const struct pci_id_descr pci_dev
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
+
+		/* Generic Non-core registers */
+	/*
+	 * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+	 * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+	 * the probing code needs to test for the other address in case of
+	 * failure of this one
+	 */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE)  },
+
 };
 
 static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
@@ -319,6 +341,12 @@ static const struct pci_id_descr pci_dev
 	{ PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
 	{ PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
 	{ PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC)   },
+
+	/*
+	 * This is the PCI device has an alternate address on some
+	 * processors like Core i7 860
+	 */
+	{ PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)     },
 };
 
 static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
@@ -346,6 +374,10 @@ static const struct pci_id_descr pci_dev
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2)   },
+
+		/* Generic Non-core registers */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2)  },
+
 };
 
 #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -714,6 +746,10 @@ static int get_dimm_config(const struct
 
 			csr->edac_mode = mode;
 			csr->mtype = mtype;
+			snprintf(csr->channels[0].label,
+					sizeof(csr->channels[0].label),
+					"CPU#%uChannel#%u_DIMM#%u",
+					pvt->i7core_dev->socket, i, j);
 
 			csrow++;
 		}
@@ -731,7 +767,7 @@ static int get_dimm_config(const struct
 			debugf1("\t\t%#x\t%#x\t%#x\n",
 				(value[j] >> 27) & 0x1,
 				(value[j] >> 24) & 0x7,
-				(value[j] && ((1 << 24) - 1)));
+				(value[j] & ((1 << 24) - 1)));
 	}
 
 	return 0;
@@ -1324,6 +1360,20 @@ static int i7core_get_onedevice(struct p
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 			      dev_descr->dev_id, *prev);
 
+	/*
+	 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+	 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+	 * to probe for the alternate address in case of failure
+	 */
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+				      *prev);
+
 	if (!pdev) {
 		if (*prev) {
 			*prev = pdev;
@@ -1444,8 +1494,10 @@ static int mci_bind_devs(struct mem_ctl_
 	struct i7core_pvt *pvt = mci->pvt_info;
 	struct pci_dev *pdev;
 	int i, func, slot;
+	char *family;
 
-	pvt->is_registered = 0;
+	pvt->is_registered = false;
+	pvt->enable_scrub  = false;
 	for (i = 0; i < i7core_dev->n_devs; i++) {
 		pdev = i7core_dev->pdev[i];
 		if (!pdev)
@@ -1461,9 +1513,37 @@ static int mci_bind_devs(struct mem_ctl_
 			if (unlikely(func > MAX_CHAN_FUNC))
 				goto error;
 			pvt->pci_ch[slot - 4][func] = pdev;
-		} else if (!slot && !func)
+		} else if (!slot && !func) {
 			pvt->pci_noncore = pdev;
-		else
+
+			/* Detect the processor family */
+			switch (pdev->device) {
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE:
+				family = "Xeon 35xx/ i7core";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT:
+				family = "i7-800/i5-700";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE:
+				family = "Xeon 34xx";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT:
+				family = "Xeon 55xx";
+				pvt->enable_scrub = true;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2:
+				family = "Xeon 56xx / i7-900";
+				pvt->enable_scrub = true;
+				break;
+			default:
+				family = "unknown";
+				pvt->enable_scrub = false;
+			}
+			debugf0("Detected a processor type %s\n", family);
+		} else
 			goto error;
 
 		debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
@@ -1472,7 +1552,7 @@ static int mci_bind_devs(struct mem_ctl_
 
 		if (PCI_SLOT(pdev->devfn) == 3 &&
 			PCI_FUNC(pdev->devfn) == 2)
-			pvt->is_registered = 1;
+			pvt->is_registered = true;
 	}
 
 	return 0;
@@ -1826,33 +1906,43 @@ check_ce_error:
  * WARNING: As this routine should be called at NMI time, extra care should
  * be taken to avoid deadlocks, and to be as fast as possible.
  */
-static int i7core_mce_check_error(void *priv, struct mce *mce)
+static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
+				  void *data)
 {
-	struct mem_ctl_info *mci = priv;
-	struct i7core_pvt *pvt = mci->pvt_info;
+	struct mce *mce = (struct mce *)data;
+	struct i7core_dev *i7_dev;
+	struct mem_ctl_info *mci;
+	struct i7core_pvt *pvt;
+
+	i7_dev = get_i7core_dev(mce->socketid);
+	if (!i7_dev)
+		return NOTIFY_BAD;
+
+	mci = i7_dev->mci;
+	pvt = mci->pvt_info;
 
 	/*
 	 * Just let mcelog handle it if the error is
 	 * outside the memory controller
 	 */
 	if (((mce->status & 0xffff) >> 7) != 1)
-		return 0;
+		return NOTIFY_DONE;
 
 	/* Bank 8 registers are the only ones that we know how to handle */
 	if (mce->bank != 8)
-		return 0;
+		return NOTIFY_DONE;
 
 #ifdef CONFIG_SMP
 	/* Only handle if it is the right mc controller */
-	if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
-		return 0;
+	if (mce->socketid != pvt->i7core_dev->socket)
+		return NOTIFY_DONE;
 #endif
 
 	smp_rmb();
 	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
 		smp_wmb();
 		pvt->mce_overrun++;
-		return 0;
+		return NOTIFY_DONE;
 	}
 
 	/* Copy memory error at the ringbuffer */
@@ -1865,7 +1955,240 @@ static int i7core_mce_check_error(void *
 		i7core_check_error(mci);
 
 	/* Advise mcelog that the errors were handled */
-	return 1;
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block i7_mce_dec = {
+	.notifier_call	= i7core_mce_check_error,
+};
+
+struct memdev_dmi_entry {
+	u8 type;
+	u8 length;
+	u16 handle;
+	u16 phys_mem_array_handle;
+	u16 mem_err_info_handle;
+	u16 total_width;
+	u16 data_width;
+	u16 size;
+	u8 form;
+	u8 device_set;
+	u8 device_locator;
+	u8 bank_locator;
+	u8 memory_type;
+	u16 type_detail;
+	u16 speed;
+	u8 manufacturer;
+	u8 serial_number;
+	u8 asset_tag;
+	u8 part_number;
+	u8 attributes;
+	u32 extended_size;
+	u16 conf_mem_clk_speed;
+} __attribute__((__packed__));
+
+
+/*
+ * Decode the DRAM Clock Frequency, be paranoid, make sure that all
+ * memory devices show the same speed, and if they don't then consider
+ * all speeds to be invalid.
+ */
+static void decode_dclk(const struct dmi_header *dh, void *_dclk_freq)
+{
+	int *dclk_freq = _dclk_freq;
+	u16 dmi_mem_clk_speed;
+
+	if (*dclk_freq == -1)
+		return;
+
+	if (dh->type == DMI_ENTRY_MEM_DEVICE) {
+		struct memdev_dmi_entry *memdev_dmi_entry =
+			(struct memdev_dmi_entry *)dh;
+		unsigned long conf_mem_clk_speed_offset =
+			(unsigned long)&memdev_dmi_entry->conf_mem_clk_speed -
+			(unsigned long)&memdev_dmi_entry->type;
+		unsigned long speed_offset =
+			(unsigned long)&memdev_dmi_entry->speed -
+			(unsigned long)&memdev_dmi_entry->type;
+
+		/* Check that a DIMM is present */
+		if (memdev_dmi_entry->size == 0)
+			return;
+
+		/*
+		 * Pick the configured speed if it's available, otherwise
+		 * pick the DIMM speed, or we don't have a speed.
+		 */
+		if (memdev_dmi_entry->length > conf_mem_clk_speed_offset) {
+			dmi_mem_clk_speed =
+				memdev_dmi_entry->conf_mem_clk_speed;
+		} else if (memdev_dmi_entry->length > speed_offset) {
+			dmi_mem_clk_speed = memdev_dmi_entry->speed;
+		} else {
+			*dclk_freq = -1;
+			return;
+		}
+
+		if (*dclk_freq == 0) {
+			/* First pass, speed was 0 */
+			if (dmi_mem_clk_speed > 0) {
+				/* Set speed if a valid speed is read */
+				*dclk_freq = dmi_mem_clk_speed;
+			} else {
+				/* Otherwise we don't have a valid speed */
+				*dclk_freq = -1;
+			}
+		} else if (*dclk_freq > 0 &&
+			   *dclk_freq != dmi_mem_clk_speed) {
+			/*
+			 * If we have a speed, check that all DIMMS are the same
+			 * speed, otherwise set the speed as invalid.
+			 */
+			*dclk_freq = -1;
+		}
+	}
+}
+
+/*
+ * The default DCLK frequency is used as a fallback if we
+ * fail to find anything reliable in the DMI. The value
+ * is taken straight from the datasheet.
+ */
+#define DEFAULT_DCLK_FREQ 800
+
+static int get_dclk_freq(void)
+{
+	int dclk_freq = 0;
+
+	dmi_walk(decode_dclk, (void *)&dclk_freq);
+
+	if (dclk_freq < 1)
+		return DEFAULT_DCLK_FREQ;
+
+	return dclk_freq;
+}
+
+/*
+ * set_sdram_scrub_rate		This routine sets byte/sec bandwidth scrub rate
+ *				to hardware according to SCRUBINTERVAL formula
+ *				found in datasheet.
+ */
+static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	u32 dw_scrub;
+	u32 dw_ssr;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &dw_scrub);
+
+	if (new_bw == 0) {
+		/* Prepare to disable petrol scrub */
+		dw_scrub &= ~STARTSCRUB;
+		/* Stop the patrol scrub engine */
+		write_and_test(pdev, MC_SCRUB_CONTROL,
+			       dw_scrub & ~SCRUBINTERVAL_MASK);
+
+		/* Get current status of scrub rate and set bit to disable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_DISABLE;
+	} else {
+		const int cache_line_size = 64;
+		const u32 freq_dclk_mhz = pvt->dclk_freq;
+		unsigned long long scrub_interval;
+		/*
+		 * Translate the desired scrub rate to a register value and
+		 * program the corresponding register value.
+		 */
+		scrub_interval = (unsigned long long)freq_dclk_mhz *
+			cache_line_size * 1000000;
+		do_div(scrub_interval, new_bw);
+
+		if (!scrub_interval || scrub_interval > SCRUBINTERVAL_MASK)
+			return -EINVAL;
+
+		dw_scrub = SCRUBINTERVAL_MASK & scrub_interval;
+
+		/* Start the patrol scrub engine */
+		pci_write_config_dword(pdev, MC_SCRUB_CONTROL,
+				       STARTSCRUB | dw_scrub);
+
+		/* Get current status of scrub rate and set bit to enable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_ENABLE;
+	}
+	/* Disable or enable scrubbing */
+	pci_write_config_dword(pdev, MC_SSRCONTROL, dw_ssr);
+
+	return new_bw;
+}
+
+/*
+ * get_sdram_scrub_rate		This routine convert current scrub rate value
+ *				into byte/sec bandwidth accourding to
+ *				SCRUBINTERVAL formula found in datasheet.
+ */
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	const u32 cache_line_size = 64;
+	const u32 freq_dclk_mhz = pvt->dclk_freq;
+	unsigned long long scrub_rate;
+	u32 scrubval;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	/* Get current scrub control data */
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &scrubval);
+
+	/* Mask highest 8-bits to 0 */
+	scrubval &=  SCRUBINTERVAL_MASK;
+	if (!scrubval)
+		return 0;
+
+	/* Calculate scrub rate value into byte/sec bandwidth */
+	scrub_rate =  (unsigned long long)freq_dclk_mhz *
+		1000000 * cache_line_size;
+	do_div(scrub_rate, scrubval);
+	return (int)scrub_rate;
+}
+
+static void enable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Unlock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_UNLOCK);
+
+	mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
+	mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
+}
+
+static void disable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Lock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_LOCK);
 }
 
 static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
@@ -1874,7 +2197,8 @@ static void i7core_pci_ctl_create(struct
 						&pvt->i7core_dev->pdev[0]->dev,
 						EDAC_MOD_STR);
 	if (unlikely(!pvt->i7core_pci))
-		pr_warn("Unable to setup PCI error report via EDAC\n");
+		i7core_printk(KERN_WARNING,
+			      "Unable to setup PCI error report via EDAC\n");
 }
 
 static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
@@ -1906,8 +2230,11 @@ static void i7core_unregister_mci(struct
 	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
 		__func__, mci, &i7core_dev->pdev[0]->dev);
 
-	/* Disable MCE NMI handler */
-	edac_mce_unregister(&pvt->edac_mce);
+	/* Disable scrubrate setting */
+	if (pvt->enable_scrub)
+		disable_sdram_scrub_setting(mci);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	/* Disable EDAC polling */
 	i7core_pci_ctl_release(pvt);
@@ -1979,6 +2306,10 @@ static int i7core_register_mci(struct i7
 	/* Set the function pointer to an actual operation function */
 	mci->edac_check = i7core_check_error;
 
+	/* Enable scrubrate setting */
+	if (pvt->enable_scrub)
+		enable_sdram_scrub_setting(mci);
+
 	/* add this new MC control structure to EDAC's list of MCs */
 	if (unlikely(edac_mc_add_mc(mci))) {
 		debugf0("MC: " __FILE__
@@ -2002,21 +2333,13 @@ static int i7core_register_mci(struct i7
 	/* allocating generic PCI control info */
 	i7core_pci_ctl_create(pvt);
 
-	/* Registers on edac_mce in order to receive memory errors */
-	pvt->edac_mce.priv = mci;
-	pvt->edac_mce.check_error = i7core_mce_check_error;
-	rc = edac_mce_register(&pvt->edac_mce);
-	if (unlikely(rc < 0)) {
-		debugf0("MC: " __FILE__
-			": %s(): failed edac_mce_register()\n", __func__);
-		goto fail1;
-	}
+	/* DCLK for scrub rate setting */
+	pvt->dclk_freq = get_dclk_freq();
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	return 0;
 
-fail1:
-	i7core_pci_ctl_release(pvt);
-	edac_mc_del_mc(mci->dev);
 fail0:
 	kfree(mci->ctl_name);
 	edac_mc_free(mci);
@@ -2035,7 +2358,7 @@ fail0:
 static int __devinit i7core_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
-	int rc;
+	int rc, count = 0;
 	struct i7core_dev *i7core_dev;
 
 	/* get the pci devices we want to reserve for our use */
@@ -2055,12 +2378,28 @@ static int __devinit i7core_probe(struct
 		goto fail0;
 
 	list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+		count++;
 		rc = i7core_register_mci(i7core_dev);
 		if (unlikely(rc < 0))
 			goto fail1;
 	}
 
-	i7core_printk(KERN_INFO, "Driver loaded.\n");
+	/*
+	 * Nehalem-EX uses a different memory controller. However, as the
+	 * memory controller is not visible on some Nehalem/Nehalem-EP, we
+	 * need to indirectly probe via a X58 PCI device. The same devices
+	 * are found on (some) Nehalem-EX. So, on those machines, the
+	 * probe routine needs to return -ENODEV, as the actual Memory
+	 * Controller registers won't be detected.
+	 */
+	if (!count) {
+		rc = -ENODEV;
+		goto fail1;
+	}
+
+	i7core_printk(KERN_INFO,
+		      "Driver loaded, %d memory controller(s) found.\n",
+		      count);
 
 	mutex_unlock(&i7core_edac_lock);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/edac/Kconfig linux-libre-3.2-gnu1/drivers/edac/Kconfig
--- linux-libre-3.1-gnu1/drivers/edac/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,7 @@ config EDAC_DEBUG
 
 config EDAC_DECODE_MCE
 	tristate "Decode MCEs in human-readable form (only on AMD for now)"
-	depends on CPU_SUP_AMD && X86_MCE
+	depends on CPU_SUP_AMD && X86_MCE_AMD
 	default y
 	---help---
 	  Enable this option if you want to decode Machine Check Exceptions
@@ -71,9 +71,6 @@ config EDAC_MM_EDAC
 	  occurred so that a particular failing memory module can be
 	  replaced.  If unsure, select 'Y'.
 
-config EDAC_MCE
-	bool
-
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
 	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
@@ -173,8 +170,7 @@ config EDAC_I5400
 
 config EDAC_I7CORE
 	tristate "Intel i7 Core (Nehalem) processors"
-	depends on EDAC_MM_EDAC && PCI && X86
-	select EDAC_MCE
+	depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
 	help
 	  Support for error detection and correction the Intel
 	  i7 Core (Nehalem) Integrated Memory Controller that exists on
@@ -216,6 +212,14 @@ config EDAC_I7300
 	  Support for error detection and correction the Intel
 	  Clarksboro MCH (Intel 7300 chipset).
 
+config EDAC_SBRIDGE
+	tristate "Intel Sandy-Bridge Integrated MC"
+	depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
+	depends on EXPERIMENTAL
+	help
+	  Support for error detection and correction the Intel
+	  Sandy Bridge Integrated Memory Controller.
+
 config EDAC_MPC85XX
 	tristate "Freescale MPC83xx / MPC85xx"
 	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
diff -druNp linux-libre-3.1-gnu1/drivers/edac/Makefile linux-libre-3.2-gnu1/drivers/edac/Makefile
--- linux-libre-3.1-gnu1/drivers/edac/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
 
 obj-$(CONFIG_EDAC)			:= edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o
-obj-$(CONFIG_EDAC_MCE)			+= edac_mce.o
 
 edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
 edac_core-y	+= edac_module.o edac_device_sysfs.o
@@ -29,6 +28,7 @@ obj-$(CONFIG_EDAC_I5100)		+= i5100_edac.
 obj-$(CONFIG_EDAC_I5400)		+= i5400_edac.o
 obj-$(CONFIG_EDAC_I7300)		+= i7300_edac.o
 obj-$(CONFIG_EDAC_I7CORE)		+= i7core_edac.o
+obj-$(CONFIG_EDAC_SBRIDGE)		+= sb_edac.o
 obj-$(CONFIG_EDAC_E7XXX)		+= e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)		+= e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)		+= i82443bxgx_edac.o
diff -druNp linux-libre-3.1-gnu1/drivers/edac/mce_amd.c linux-libre-3.2-gnu1/drivers/edac/mce_amd.c
--- linux-libre-3.1-gnu1/drivers/edac/mce_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/mce_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@ static u8 xec_mask	 = 0xf;
 static u8 nb_err_cpumask = 0xf;
 
 static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+static void (*nb_bus_decoder)(int node_id, struct mce *m);
 
 void amd_report_gart_errors(bool v)
 {
@@ -17,13 +17,13 @@ void amd_report_gart_errors(bool v)
 }
 EXPORT_SYMBOL_GPL(amd_report_gart_errors);
 
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_register_ecc_decoder(void (*f)(int, struct mce *))
 {
 	nb_bus_decoder = f;
 }
 EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
 
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
 {
 	if (nb_bus_decoder) {
 		WARN_ON(nb_bus_decoder != f);
@@ -592,31 +592,14 @@ static bool nb_noop_mce(u16 ec, u8 xec)
 	return false;
 }
 
-void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+void amd_decode_nb_mce(struct mce *m)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
-	u16 ec   = EC(m->status);
-	u8 xec   = XEC(m->status, 0x1f);
-	u32 nbsh = (u32)(m->status >> 32);
-	int core = -1;
-
-	pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
-
-	/* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
-	if (c->x86 == 0x10 && c->x86_model > 7) {
-		if (nbsh & NBSH_ERR_CPU_VAL)
-			core = nbsh & nb_err_cpumask;
-	} else {
-		u8 assoc_cpus = nbsh & nb_err_cpumask;
-
-		if (assoc_cpus > 0)
-			core = fls(assoc_cpus) - 1;
-	}
+	int node_id = amd_get_nb_id(m->extcpu);
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, 0x1f);
 
-	if (core >= 0)
-		pr_cont(", core %d): ", core);
-	else
-		pr_cont("): ");
+	pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
 
 	switch (xec) {
 	case 0x2:
@@ -648,7 +631,7 @@ void amd_decode_nb_mce(int node_id, stru
 
 	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15)
 		if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
-			nb_bus_decoder(node_id, m, nbcfg);
+			nb_bus_decoder(node_id, m);
 
 	return;
 
@@ -764,13 +747,13 @@ int amd_decode_mce(struct notifier_block
 {
 	struct mce *m = (struct mce *)data;
 	struct cpuinfo_x86 *c = &boot_cpu_data;
-	int node, ecc;
+	int ecc;
 
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
 
-	pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s",
-		m->bank,
+	pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
+		m->extcpu, m->bank,
 		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
 		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
 		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
@@ -789,6 +772,8 @@ int amd_decode_mce(struct notifier_block
 
 	pr_cont("]: 0x%016llx\n", m->status);
 
+	if (m->status & MCI_STATUS_ADDRV)
+		pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
 
 	switch (m->bank) {
 	case 0:
@@ -811,8 +796,7 @@ int amd_decode_mce(struct notifier_block
 		break;
 
 	case 4:
-		node = amd_get_nb_id(m->extcpu);
-		amd_decode_nb_mce(node, m, 0);
+		amd_decode_nb_mce(m);
 		break;
 
 	case 5:
diff -druNp linux-libre-3.1-gnu1/drivers/edac/mce_amd.h linux-libre-3.2-gnu1/drivers/edac/mce_amd.h
--- linux-libre-3.1-gnu1/drivers/edac/mce_amd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/mce_amd.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,9 +86,9 @@ struct amd_decoder_ops {
 };
 
 void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_decode_nb_mce(int, struct mce *, u32);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
+void amd_decode_nb_mce(struct mce *);
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
 
 #endif /* _EDAC_MCE_AMD_H */
diff -druNp linux-libre-3.1-gnu1/drivers/edac/mce_amd_inj.c linux-libre-3.2-gnu1/drivers/edac/mce_amd_inj.c
--- linux-libre-3.1-gnu1/drivers/edac/mce_amd_inj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/mce_amd_inj.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kobject.h>
 #include <linux/sysdev.h>
 #include <linux/edac.h>
+#include <linux/module.h>
 #include <asm/mce.h>
 
 #include "mce_amd.h"
diff -druNp linux-libre-3.1-gnu1/drivers/edac/mpc85xx_edac.c linux-libre-3.2-gnu1/drivers/edac/mpc85xx_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/mpc85xx_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/mpc85xx_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -1128,7 +1128,7 @@ static struct of_device_id mpc85xx_mc_er
 	{ .compatible = "fsl,p1020-memory-controller", },
 	{ .compatible = "fsl,p1021-memory-controller", },
 	{ .compatible = "fsl,p2020-memory-controller", },
-	{ .compatible = "fsl,p4080-memory-controller", },
+	{ .compatible = "fsl,qoriq-memory-controller", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
diff -druNp linux-libre-3.1-gnu1/drivers/edac/ppc4xx_edac.c linux-libre-3.2-gnu1/drivers/edac/ppc4xx_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/ppc4xx_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/edac/ppc4xx_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -205,7 +205,7 @@ static struct platform_driver ppc4xx_eda
 	.remove			= ppc4xx_edac_remove,
 	.driver = {
 		.owner = THIS_MODULE,
-		.name = PPC4XX_EDAC_MODULE_NAME
+		.name = PPC4XX_EDAC_MODULE_NAME,
 		.of_match_table = ppc4xx_edac_match,
 	},
 };
diff -druNp linux-libre-3.1-gnu1/drivers/edac/sb_edac.c linux-libre-3.2-gnu1/drivers/edac/sb_edac.c
--- linux-libre-3.1-gnu1/drivers/edac/sb_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/edac/sb_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1893 @@
+/* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
+ *
+ * This driver supports the memory controllers found on the Intel
+ * processor family Sandy Bridge.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2011 by:
+ *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/smp.h>
+#include <linux/bitmap.h>
+#include <asm/processor.h>
+#include <asm/mce.h>
+
+#include "edac_core.h"
+
+/* Static vars */
+static LIST_HEAD(sbridge_edac_list);
+static DEFINE_MUTEX(sbridge_edac_lock);
+static int probed;
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define SBRIDGE_REVISION    " Ver: 1.0.0 "
+#define EDAC_MOD_STR      "sbridge_edac"
+
+/*
+ * Debug macros
+ */
+#define sbridge_printk(level, fmt, arg...)			\
+	edac_printk(level, "sbridge", fmt, ##arg)
+
+#define sbridge_mc_printk(mci, level, fmt, arg...)		\
+	edac_mc_chipset_printk(mci, level, "sbridge", fmt, ##arg)
+
+/*
+ * Get a bit field at register value <v>, from bit <lo> to bit <hi>
+ */
+#define GET_BITFIELD(v, lo, hi)	\
+	(((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
+
+/*
+ * sbridge Memory Controller Registers
+ */
+
+/*
+ * FIXME: For now, let's order by device function, as it makes
+ * easier for driver's development proccess. This table should be
+ * moved to pci_id.h when submitted upstream
+ */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0	0x3cf4	/* 12.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1	0x3cf6	/* 12.7 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR		0x3cf5	/* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0	0x3ca0	/* 14.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA	0x3ca8	/* 15.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS	0x3c71	/* 15.1 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0	0x3caa	/* 15.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1	0x3cab	/* 15.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2	0x3cac	/* 15.4 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3	0x3cad	/* 15.5 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO	0x3cb8	/* 17.0 */
+
+	/*
+	 * Currently, unused, but will be needed in the future
+	 * implementations, as they hold the error counters
+	 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0	0x3c72	/* 16.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1	0x3c73	/* 16.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR2	0x3c76	/* 16.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3	0x3c77	/* 16.7 */
+
+/* Devices 12 Function 6, Offsets 0x80 to 0xcc */
+static const u32 dram_rule[] = {
+	0x80, 0x88, 0x90, 0x98, 0xa0,
+	0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
+};
+#define MAX_SAD		ARRAY_SIZE(dram_rule)
+
+#define SAD_LIMIT(reg)		((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
+#define DRAM_ATTR(reg)		GET_BITFIELD(reg, 2,  3)
+#define INTERLEAVE_MODE(reg)	GET_BITFIELD(reg, 1,  1)
+#define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
+
+static char *get_dram_attr(u32 reg)
+{
+	switch(DRAM_ATTR(reg)) {
+		case 0:
+			return "DRAM";
+		case 1:
+			return "MMCFG";
+		case 2:
+			return "NXM";
+		default:
+			return "unknown";
+	}
+}
+
+static const u32 interleave_list[] = {
+	0x84, 0x8c, 0x94, 0x9c, 0xa4,
+	0xac, 0xb4, 0xbc, 0xc4, 0xcc,
+};
+#define MAX_INTERLEAVE	ARRAY_SIZE(interleave_list)
+
+#define SAD_PKG0(reg)		GET_BITFIELD(reg, 0, 2)
+#define SAD_PKG1(reg)		GET_BITFIELD(reg, 3, 5)
+#define SAD_PKG2(reg)		GET_BITFIELD(reg, 8, 10)
+#define SAD_PKG3(reg)		GET_BITFIELD(reg, 11, 13)
+#define SAD_PKG4(reg)		GET_BITFIELD(reg, 16, 18)
+#define SAD_PKG5(reg)		GET_BITFIELD(reg, 19, 21)
+#define SAD_PKG6(reg)		GET_BITFIELD(reg, 24, 26)
+#define SAD_PKG7(reg)		GET_BITFIELD(reg, 27, 29)
+
+static inline int sad_pkg(u32 reg, int interleave)
+{
+	switch (interleave) {
+	case 0:
+		return SAD_PKG0(reg);
+	case 1:
+		return SAD_PKG1(reg);
+	case 2:
+		return SAD_PKG2(reg);
+	case 3:
+		return SAD_PKG3(reg);
+	case 4:
+		return SAD_PKG4(reg);
+	case 5:
+		return SAD_PKG5(reg);
+	case 6:
+		return SAD_PKG6(reg);
+	case 7:
+		return SAD_PKG7(reg);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Devices 12 Function 7 */
+
+#define TOLM		0x80
+#define	TOHM		0x84
+
+#define GET_TOLM(reg)		((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ffffff)
+#define GET_TOHM(reg)		((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
+
+/* Device 13 Function 6 */
+
+#define SAD_TARGET	0xf0
+
+#define SOURCE_ID(reg)		GET_BITFIELD(reg, 9, 11)
+
+#define SAD_CONTROL	0xf4
+
+#define NODE_ID(reg)		GET_BITFIELD(reg, 0, 2)
+
+/* Device 14 function 0 */
+
+static const u32 tad_dram_rule[] = {
+	0x40, 0x44, 0x48, 0x4c,
+	0x50, 0x54, 0x58, 0x5c,
+	0x60, 0x64, 0x68, 0x6c,
+};
+#define MAX_TAD	ARRAY_SIZE(tad_dram_rule)
+
+#define TAD_LIMIT(reg)		((GET_BITFIELD(reg, 12, 31) << 26) | 0x3ffffff)
+#define TAD_SOCK(reg)		GET_BITFIELD(reg, 10, 11)
+#define TAD_CH(reg)		GET_BITFIELD(reg,  8,  9)
+#define TAD_TGT3(reg)		GET_BITFIELD(reg,  6,  7)
+#define TAD_TGT2(reg)		GET_BITFIELD(reg,  4,  5)
+#define TAD_TGT1(reg)		GET_BITFIELD(reg,  2,  3)
+#define TAD_TGT0(reg)		GET_BITFIELD(reg,  0,  1)
+
+/* Device 15, function 0 */
+
+#define MCMTR			0x7c
+
+#define IS_ECC_ENABLED(mcmtr)		GET_BITFIELD(mcmtr, 2, 2)
+#define IS_LOCKSTEP_ENABLED(mcmtr)	GET_BITFIELD(mcmtr, 1, 1)
+#define IS_CLOSE_PG(mcmtr)		GET_BITFIELD(mcmtr, 0, 0)
+
+/* Device 15, function 1 */
+
+#define RASENABLES		0xac
+#define IS_MIRROR_ENABLED(reg)		GET_BITFIELD(reg, 0, 0)
+
+/* Device 15, functions 2-5 */
+
+static const int mtr_regs[] = {
+	0x80, 0x84, 0x88,
+};
+
+#define RANK_DISABLE(mtr)		GET_BITFIELD(mtr, 16, 19)
+#define IS_DIMM_PRESENT(mtr)		GET_BITFIELD(mtr, 14, 14)
+#define RANK_CNT_BITS(mtr)		GET_BITFIELD(mtr, 12, 13)
+#define RANK_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 2, 4)
+#define COL_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 0, 1)
+
+static const u32 tad_ch_nilv_offset[] = {
+	0x90, 0x94, 0x98, 0x9c,
+	0xa0, 0xa4, 0xa8, 0xac,
+	0xb0, 0xb4, 0xb8, 0xbc,
+};
+#define CHN_IDX_OFFSET(reg)		GET_BITFIELD(reg, 28, 29)
+#define TAD_OFFSET(reg)			(GET_BITFIELD(reg,  6, 25) << 26)
+
+static const u32 rir_way_limit[] = {
+	0x108, 0x10c, 0x110, 0x114, 0x118,
+};
+#define MAX_RIR_RANGES ARRAY_SIZE(rir_way_limit)
+
+#define IS_RIR_VALID(reg)	GET_BITFIELD(reg, 31, 31)
+#define RIR_WAY(reg)		GET_BITFIELD(reg, 28, 29)
+#define RIR_LIMIT(reg)		((GET_BITFIELD(reg,  1, 10) << 29)| 0x1fffffff)
+
+#define MAX_RIR_WAY	8
+
+static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
+	{ 0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c },
+	{ 0x140, 0x144, 0x148, 0x14c, 0x150, 0x154, 0x158, 0x15c },
+	{ 0x160, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c },
+	{ 0x180, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c },
+	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
+};
+
+#define RIR_RNK_TGT(reg)		GET_BITFIELD(reg, 16, 19)
+#define RIR_OFFSET(reg)		GET_BITFIELD(reg,  2, 14)
+
+/* Device 16, functions 2-7 */
+
+/*
+ * FIXME: Implement the error count reads directly
+ */
+
+static const u32 correrrcnt[] = {
+	0x104, 0x108, 0x10c, 0x110,
+};
+
+#define RANK_ODD_OV(reg)		GET_BITFIELD(reg, 31, 31)
+#define RANK_ODD_ERR_CNT(reg)		GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_OV(reg)		GET_BITFIELD(reg, 15, 15)
+#define RANK_EVEN_ERR_CNT(reg)		GET_BITFIELD(reg,  0, 14)
+
+static const u32 correrrthrsld[] = {
+	0x11c, 0x120, 0x124, 0x128,
+};
+
+#define RANK_ODD_ERR_THRSLD(reg)	GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_ERR_THRSLD(reg)	GET_BITFIELD(reg,  0, 14)
+
+
+/* Device 17, function 0 */
+
+#define RANK_CFG_A		0x0328
+
+#define IS_RDIMM_ENABLED(reg)		GET_BITFIELD(reg, 11, 11)
+
+/*
+ * sbridge structs
+ */
+
+#define NUM_CHANNELS	4
+#define MAX_DIMMS	3		/* Max DIMMS per channel */
+
+struct sbridge_info {
+	u32	mcmtr;
+};
+
+struct sbridge_channel {
+	u32		ranks;
+	u32		dimms;
+};
+
+struct pci_id_descr {
+	int			dev;
+	int			func;
+	int 			dev_id;
+	int			optional;
+};
+
+struct pci_id_table {
+	const struct pci_id_descr	*descr;
+	int				n_devs;
+};
+
+struct sbridge_dev {
+	struct list_head	list;
+	u8			bus, mc;
+	u8			node_id, source_id;
+	struct pci_dev		**pdev;
+	int			n_devs;
+	struct mem_ctl_info	*mci;
+};
+
+struct sbridge_pvt {
+	struct pci_dev		*pci_ta, *pci_ddrio, *pci_ras;
+	struct pci_dev		*pci_sad0, *pci_sad1, *pci_ha0;
+	struct pci_dev		*pci_br;
+	struct pci_dev		*pci_tad[NUM_CHANNELS];
+
+	struct sbridge_dev	*sbridge_dev;
+
+	struct sbridge_info	info;
+	struct sbridge_channel	channel[NUM_CHANNELS];
+
+	int 			csrow_map[NUM_CHANNELS][MAX_DIMMS];
+
+	/* Memory type detection */
+	bool			is_mirrored, is_lockstep, is_close_pg;
+
+	/* Fifo double buffers */
+	struct mce		mce_entry[MCE_LOG_LEN];
+	struct mce		mce_outentry[MCE_LOG_LEN];
+
+	/* Fifo in/out counters */
+	unsigned		mce_in, mce_out;
+
+	/* Count indicator to show errors not got */
+	unsigned		mce_overrun;
+
+	/* Memory description */
+	u64			tolm, tohm;
+};
+
+#define PCI_DESCR(device, function, device_id)	\
+	.dev = (device),			\
+	.func = (function),			\
+	.dev_id = (device_id)
+
+static const struct pci_id_descr pci_dev_descr_sbridge[] = {
+		/* Processor Home Agent */
+	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)		},
+
+		/* Memory controller */
+	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)		},
+	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS)		},
+	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0)	},
+	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1)	},
+	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2)	},
+	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3)	},
+	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO)	},
+
+		/* System Address Decoder */
+	{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0)		},
+	{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1)		},
+
+		/* Broadcast Registers */
+	{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR)		},
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+	{0,}			/* 0 terminated list. */
+};
+
+/*
+ *	pci_device_id	table for which devices we are looking for
+ */
+static const struct pci_device_id sbridge_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
+	{0,}			/* 0 terminated list. */
+};
+
+
+/****************************************************************************
+			Anciliary status routines
+ ****************************************************************************/
+
+static inline int numrank(u32 mtr)
+{
+	int ranks = (1 << RANK_CNT_BITS(mtr));
+
+	if (ranks > 4) {
+		debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)",
+			ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return ranks;
+}
+
+static inline int numrow(u32 mtr)
+{
+	int rows = (RANK_WIDTH_BITS(mtr) + 12);
+
+	if (rows < 13 || rows > 18) {
+		debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)",
+			rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << rows;
+}
+
+static inline int numcol(u32 mtr)
+{
+	int cols = (COL_WIDTH_BITS(mtr) + 10);
+
+	if (cols > 12) {
+		debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)",
+			cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << cols;
+}
+
+static struct sbridge_dev *get_sbridge_dev(u8 bus)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->bus == bus)
+			return sbridge_dev;
+	}
+
+	return NULL;
+}
+
+static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
+					   const struct pci_id_table *table)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
+	if (!sbridge_dev)
+		return NULL;
+
+	sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
+				   GFP_KERNEL);
+	if (!sbridge_dev->pdev) {
+		kfree(sbridge_dev);
+		return NULL;
+	}
+
+	sbridge_dev->bus = bus;
+	sbridge_dev->n_devs = table->n_devs;
+	list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
+
+	return sbridge_dev;
+}
+
+static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
+{
+	list_del(&sbridge_dev->list);
+	kfree(sbridge_dev->pdev);
+	kfree(sbridge_dev);
+}
+
+/****************************************************************************
+			Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
+					  unsigned func)
+{
+	struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
+	int i;
+
+	if (!sbridge_dev)
+		return NULL;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		if (!sbridge_dev->pdev[i])
+			continue;
+
+		if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
+		    PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
+			debugf1("Associated %02x.%02x.%d with %p\n",
+				bus, slot, func, sbridge_dev->pdev[i]);
+			return sbridge_dev->pdev[i];
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * sbridge_get_active_channels() - gets the number of channels and csrows
+ * bus:		Device bus
+ * @channels:	Number of channels that will be returned
+ * @csrows:	Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket, identified
+ * by the associated PCI bus.
+ * this is used in order to properly allocate the size of mci components.
+ * Note: one csrow is one dimm.
+ */
+static int sbridge_get_active_channels(const u8 bus, unsigned *channels,
+				      unsigned *csrows)
+{
+	struct pci_dev *pdev = NULL;
+	int i, j;
+	u32 mcmtr;
+
+	*channels = 0;
+	*csrows = 0;
+
+	pdev = get_pdev_slot_func(bus, 15, 0);
+	if (!pdev) {
+		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+					"%2x.%02d.%d!!!\n",
+					bus, 15, 0);
+		return -ENODEV;
+	}
+
+	pci_read_config_dword(pdev, MCMTR, &mcmtr);
+	if (!IS_ECC_ENABLED(mcmtr)) {
+		sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		/* Device 15 functions 2 - 5  */
+		pdev = get_pdev_slot_func(bus, 15, 2 + i);
+		if (!pdev) {
+			sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+						 "%2x.%02d.%d!!!\n",
+						 bus, 15, 2 + i);
+			return -ENODEV;
+		}
+		(*channels)++;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pdev, mtr_regs[j], &mtr);
+			debugf1("Bus#%02x channel #%d  MTR%d = %x\n", bus, i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr))
+				(*csrows)++;
+		}
+	}
+
+	debugf0("Number of active channels: %d, number of active dimms: %d\n",
+		*channels, *csrows);
+
+	return 0;
+}
+
+static int get_dimm_config(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct csrow_info *csr;
+	int i, j, banks, ranks, rows, cols, size, npages;
+	int csrow = 0;
+	unsigned long last_page = 0;
+	u32 reg;
+	enum edac_type mode;
+	enum mem_type mtype;
+
+	pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
+	pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+
+	pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);
+	pvt->sbridge_dev->node_id = NODE_ID(reg);
+	debugf0("mc#%d: Node ID: %d, source ID: %d\n",
+		pvt->sbridge_dev->mc,
+		pvt->sbridge_dev->node_id,
+		pvt->sbridge_dev->source_id);
+
+	pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+	if (IS_MIRROR_ENABLED(reg)) {
+		debugf0("Memory mirror is enabled\n");
+		pvt->is_mirrored = true;
+	} else {
+		debugf0("Memory mirror is disabled\n");
+		pvt->is_mirrored = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+	if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+		debugf0("Lockstep is enabled\n");
+		mode = EDAC_S8ECD8ED;
+		pvt->is_lockstep = true;
+	} else {
+		debugf0("Lockstep is disabled\n");
+		mode = EDAC_S4ECD4ED;
+		pvt->is_lockstep = false;
+	}
+	if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+		debugf0("address map is on closed page mode\n");
+		pvt->is_close_pg = true;
+	} else {
+		debugf0("address map is on open page mode\n");
+		pvt->is_close_pg = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, &reg);
+	if (IS_RDIMM_ENABLED(reg)) {
+		/* FIXME: Can also be LRDIMM */
+		debugf0("Memory is registered\n");
+		mtype = MEM_RDDR3;
+	} else {
+		debugf0("Memory is unregistered\n");
+		mtype = MEM_DDR3;
+	}
+
+	/* On all supported DDR3 DIMM types, there are 8 banks available */
+	banks = 8;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      mtr_regs[j], &mtr);
+			debugf4("Channel #%d  MTR%d = %x\n", i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr)) {
+				pvt->channel[i].dimms++;
+
+				ranks = numrank(mtr);
+				rows = numrow(mtr);
+				cols = numcol(mtr);
+
+				/* DDR3 has 8 I/O banks */
+				size = (rows * cols * banks * ranks) >> (20 - 3);
+				npages = MiB_TO_PAGES(size);
+
+				debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+					pvt->sbridge_dev->mc, i, j,
+					size, npages,
+					banks, ranks, rows, cols);
+				csr = &mci->csrows[csrow];
+
+				csr->first_page = last_page;
+				csr->last_page = last_page + npages - 1;
+				csr->page_mask = 0UL;	/* Unused */
+				csr->nr_pages = npages;
+				csr->grain = 32;
+				csr->csrow_idx = csrow;
+				csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+				csr->ce_count = 0;
+				csr->ue_count = 0;
+				csr->mtype = mtype;
+				csr->edac_mode = mode;
+				csr->nr_channels = 1;
+				csr->channels[0].chan_idx = i;
+				csr->channels[0].ce_count = 0;
+				pvt->csrow_map[i][j] = csrow;
+				snprintf(csr->channels[0].label,
+					 sizeof(csr->channels[0].label),
+					 "CPU_SrcID#%u_Channel#%u_DIMM#%u",
+					 pvt->sbridge_dev->source_id, i, j);
+				last_page += npages;
+				csrow++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void get_memory_layout(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i, j, k, n_sads, n_tads, sad_interl;
+	u32 reg;
+	u64 limit, prv = 0;
+	u64 tmp_mb;
+	u32 rir_way;
+
+	/*
+	 * Step 1) Get TOLM/TOHM ranges
+	 */
+
+	/* Address range is 32:28 */
+	pci_read_config_dword(pvt->pci_sad1, TOLM,
+			      &reg);
+	pvt->tolm = GET_TOLM(reg);
+	tmp_mb = (1 + pvt->tolm) >> 20;
+
+	debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+
+	/* Address range is already 45:25 */
+	pci_read_config_dword(pvt->pci_sad1, TOHM,
+			      &reg);
+	pvt->tohm = GET_TOHM(reg);
+	tmp_mb = (1 + pvt->tohm) >> 20;
+
+	debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+
+	/*
+	 * Step 2) Get SAD range and SAD Interleave list
+	 * TAD registers contain the interleave wayness. However, it
+	 * seems simpler to just discover it indirectly, with the
+	 * algorithm bellow.
+	 */
+	prv = 0;
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		/* SAD_LIMIT Address range is 45:26 */
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+		limit = SAD_LIMIT(reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		if (limit <= prv)
+			break;
+
+		tmp_mb = (limit + 1) >> 20;
+		debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+			n_sads,
+			get_dram_attr(reg),
+			tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
+			reg);
+		prv = limit;
+
+		pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+				      &reg);
+		sad_interl = sad_pkg(reg, 0);
+		for (j = 0; j < 8; j++) {
+			if (j > 0 && sad_interl == sad_pkg(reg, j))
+				break;
+
+			debugf0("SAD#%d, interleave #%d: %d\n",
+			n_sads, j, sad_pkg(reg, j));
+		}
+	}
+
+	/*
+	 * Step 3) Get TAD range
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv)
+			break;
+		tmp_mb = (limit + 1) >> 20;
+
+		debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+			n_tads, tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			(u32)TAD_SOCK(reg),
+			(u32)TAD_CH(reg),
+			(u32)TAD_TGT0(reg),
+			(u32)TAD_TGT1(reg),
+			(u32)TAD_TGT2(reg),
+			(u32)TAD_TGT3(reg),
+			reg);
+		prv = tmp_mb;
+	}
+
+	/*
+	 * Step 4) Get TAD offsets, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < n_tads; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      tad_ch_nilv_offset[j],
+					      &reg);
+			tmp_mb = TAD_OFFSET(reg) >> 20;
+			debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				reg);
+		}
+	}
+
+	/*
+	 * Step 6) Get RIR Wayness/Limit, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < MAX_RIR_RANGES; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      rir_way_limit[j],
+					      &reg);
+
+			if (!IS_RIR_VALID(reg))
+				continue;
+
+			tmp_mb = RIR_LIMIT(reg) >> 20;
+			rir_way = 1 << RIR_WAY(reg);
+			debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				rir_way,
+				reg);
+
+			for (k = 0; k < rir_way; k++) {
+				pci_read_config_dword(pvt->pci_tad[i],
+						      rir_offset[j][k],
+						      &reg);
+				tmp_mb = RIR_OFFSET(reg) << 6;
+
+				debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+					i, j, k,
+					tmp_mb / 1000, tmp_mb % 1000,
+					((u64)tmp_mb) << 20L,
+					(u32)RIR_RNK_TGT(reg),
+					reg);
+			}
+		}
+	}
+}
+
+struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->node_id == node_id)
+			return sbridge_dev->mci;
+	}
+	return NULL;
+}
+
+static int get_memory_error_data(struct mem_ctl_info *mci,
+				 u64 addr,
+				 u8 *socket,
+				 long *channel_mask,
+				 u8 *rank,
+				 char *area_type)
+{
+	struct mem_ctl_info	*new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char			msg[256];
+	int 			n_rir, n_sads, n_tads, sad_way, sck_xch;
+	int			sad_interl, idx, base_ch;
+	int			interleave_mode;
+	unsigned		sad_interleave[MAX_INTERLEAVE];
+	u32			reg;
+	u8			ch_way,sck_way;
+	u32			tad_offset;
+	u32			rir_way;
+	u64			ch_addr, offset, limit, prv = 0;
+
+
+	/*
+	 * Step 0) Check if the address is at special memory ranges
+	 * The check bellow is probably enough to fill all cases where
+	 * the error is not inside a memory, except for the legacy
+	 * range (e. g. VGA addresses). It is unlikely, however, that the
+	 * memory controller would generate an error on that range.
+	 */
+	if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+		sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	if (addr >= (u64)pvt->tohm) {
+		sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+
+	/*
+	 * Step 1) Get socket
+	 */
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		limit = SAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory socket");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	if (n_sads == MAX_SAD) {
+		sprintf(msg, "Can't discover the memory socket");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	area_type = get_dram_attr(reg);
+	interleave_mode = INTERLEAVE_MODE(reg);
+
+	pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+			      &reg);
+	sad_interl = sad_pkg(reg, 0);
+	for (sad_way = 0; sad_way < 8; sad_way++) {
+		if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way))
+			break;
+		sad_interleave[sad_way] = sad_pkg(reg, sad_way);
+		debugf0("SAD interleave #%d: %d\n",
+			sad_way, sad_interleave[sad_way]);
+	}
+	debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
+		pvt->sbridge_dev->mc,
+		n_sads,
+		addr,
+		limit,
+		sad_way + 7,
+		INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+	if (interleave_mode)
+		idx = ((addr >> 6) ^ (addr >> 16)) & 7;
+	else
+		idx = (addr >> 6) & 7;
+	switch (sad_way) {
+	case 1:
+		idx = 0;
+		break;
+	case 2:
+		idx = idx & 1;
+		break;
+	case 4:
+		idx = idx & 3;
+		break;
+	case 8:
+		break;
+	default:
+		sprintf(msg, "Can't discover socket interleave");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*socket = sad_interleave[idx];
+	debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n",
+		idx, sad_way, *socket);
+
+	/*
+	 * Move to the proper node structure, in order to access the
+	 * right PCI registers
+	 */
+	new_mci = get_mci_for_node_id(*socket);
+	if (!new_mci) {
+		sprintf(msg, "Struct for socket #%u wasn't initialized",
+			*socket);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Step 2) Get memory channel
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory channel");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	ch_way = TAD_CH(reg) + 1;
+	sck_way = TAD_SOCK(reg) + 1;
+	/*
+	 * FIXME: Is it right to always use channel 0 for offsets?
+	 */
+	pci_read_config_dword(pvt->pci_tad[0],
+				tad_ch_nilv_offset[n_tads],
+				&tad_offset);
+
+	if (ch_way == 3)
+		idx = addr >> 6;
+	else
+		idx = addr >> (6 + sck_way);
+	idx = idx % ch_way;
+
+	/*
+	 * FIXME: Shouldn't we use CHN_IDX_OFFSET() here, when ch_way == 3 ???
+	 */
+	switch (idx) {
+	case 0:
+		base_ch = TAD_TGT0(reg);
+		break;
+	case 1:
+		base_ch = TAD_TGT1(reg);
+		break;
+	case 2:
+		base_ch = TAD_TGT2(reg);
+		break;
+	case 3:
+		base_ch = TAD_TGT3(reg);
+		break;
+	default:
+		sprintf(msg, "Can't discover the TAD target");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*channel_mask = 1 << base_ch;
+
+	if (pvt->is_mirrored) {
+		*channel_mask |= 1 << ((base_ch + 2) % 4);
+		switch(ch_way) {
+		case 2:
+		case 4:
+			sck_xch = 1 << sck_way * (ch_way >> 1);
+			break;
+		default:
+			sprintf(msg, "Invalid mirror set. Can't decode addr");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+	} else
+		sck_xch = (1 << sck_way) * ch_way;
+
+	if (pvt->is_lockstep)
+		*channel_mask |= 1 << ((base_ch + 1) % 4);
+
+	offset = TAD_OFFSET(tad_offset);
+
+	debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n",
+		n_tads,
+		addr,
+		limit,
+		(u32)TAD_SOCK(reg),
+		ch_way,
+		offset,
+		idx,
+		base_ch,
+		*channel_mask);
+
+	/* Calculate channel address */
+	/* Remove the TAD offset */
+
+	if (offset > addr) {
+		sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!",
+			offset, addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	addr -= offset;
+	/* Store the low bits [0:6] of the addr */
+	ch_addr = addr & 0x7f;
+	/* Remove socket wayness and remove 6 bits */
+	addr >>= 6;
+	addr /= sck_xch;
+#if 0
+	/* Divide by channel way */
+	addr = addr / ch_way;
+#endif
+	/* Recover the last 6 bits */
+	ch_addr |= addr << 6;
+
+	/*
+	 * Step 3) Decode rank
+	 */
+	for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
+		pci_read_config_dword(pvt->pci_tad[base_ch],
+				      rir_way_limit[n_rir],
+				      &reg);
+
+		if (!IS_RIR_VALID(reg))
+			continue;
+
+		limit = RIR_LIMIT(reg);
+
+		debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+			n_rir,
+			(limit >> 20) / 1000, (limit >> 20) % 1000,
+			limit,
+			1 << RIR_WAY(reg));
+		if  (ch_addr <= limit)
+			break;
+	}
+	if (n_rir == MAX_RIR_RANGES) {
+		sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx",
+			ch_addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	rir_way = RIR_WAY(reg);
+	if (pvt->is_close_pg)
+		idx = (ch_addr >> 6);
+	else
+		idx = (ch_addr >> 13);	/* FIXME: Datasheet says to shift by 15 */
+	idx %= 1 << rir_way;
+
+	pci_read_config_dword(pvt->pci_tad[base_ch],
+			      rir_offset[n_rir][idx],
+			      &reg);
+	*rank = RIR_RNK_TGT(reg);
+
+	debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
+		n_rir,
+		ch_addr,
+		limit,
+		rir_way,
+		idx);
+
+	return 0;
+}
+
+/****************************************************************************
+	Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ *	sbridge_put_all_devices	'put' all the devices that we have
+ *				reserved via 'get'
+ */
+static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
+{
+	int i;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		struct pci_dev *pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		debugf0("Removing dev %02x:%02x.%d\n",
+			pdev->bus->number,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+		pci_dev_put(pdev);
+	}
+}
+
+static void sbridge_put_all_devices(void)
+{
+	struct sbridge_dev *sbridge_dev, *tmp;
+
+	list_for_each_entry_safe(sbridge_dev, tmp, &sbridge_edac_list, list) {
+		sbridge_put_devices(sbridge_dev);
+		free_sbridge_dev(sbridge_dev);
+	}
+}
+
+/*
+ *	sbridge_get_all_devices	Find and perform 'get' operation on the MCH's
+ *			device/functions we want to reference for this driver
+ *
+ *			Need to 'get' device 16 func 1 and func 2
+ */
+static int sbridge_get_onedevice(struct pci_dev **prev,
+				 u8 *num_mc,
+				 const struct pci_id_table *table,
+				 const unsigned devno)
+{
+	struct sbridge_dev *sbridge_dev;
+	const struct pci_id_descr *dev_descr = &table->descr[devno];
+
+	struct pci_dev *pdev = NULL;
+	u8 bus = 0;
+
+	sbridge_printk(KERN_INFO,
+		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
+		dev_descr->dev, dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			      dev_descr->dev_id, *prev);
+
+	if (!pdev) {
+		if (*prev) {
+			*prev = pdev;
+			return 0;
+		}
+
+		if (dev_descr->optional)
+			return 0;
+
+		if (devno == 0)
+			return -ENODEV;
+
+		sbridge_printk(KERN_INFO,
+			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+			dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+		/* End of list, leave */
+		return -ENODEV;
+	}
+	bus = pdev->bus->number;
+
+	sbridge_dev = get_sbridge_dev(bus);
+	if (!sbridge_dev) {
+		sbridge_dev = alloc_sbridge_dev(bus, table);
+		if (!sbridge_dev) {
+			pci_dev_put(pdev);
+			return -ENOMEM;
+		}
+		(*num_mc)++;
+	}
+
+	if (sbridge_dev->pdev[devno]) {
+		sbridge_printk(KERN_ERR,
+			"Duplicated device for "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		pci_dev_put(pdev);
+		return -ENODEV;
+	}
+
+	sbridge_dev->pdev[devno] = pdev;
+
+	/* Sanity check */
+	if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+			PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+		sbridge_printk(KERN_ERR,
+			"Device PCI ID %04x:%04x "
+			"has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+			bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			bus, dev_descr->dev, dev_descr->func);
+		return -ENODEV;
+	}
+
+	/* Be sure that the device is enabled */
+	if (unlikely(pci_enable_device(pdev) < 0)) {
+		sbridge_printk(KERN_ERR,
+			"Couldn't enable "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		return -ENODEV;
+	}
+
+	debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
+		bus, dev_descr->dev,
+		dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	/*
+	 * As stated on drivers/pci/search.c, the reference count for
+	 * @from is always decremented if it is not %NULL. So, as we need
+	 * to get all devices up to null, we need to do a get for the device
+	 */
+	pci_dev_get(pdev);
+
+	*prev = pdev;
+
+	return 0;
+}
+
+static int sbridge_get_all_devices(u8 *num_mc)
+{
+	int i, rc;
+	struct pci_dev *pdev = NULL;
+	const struct pci_id_table *table = pci_dev_descr_sbridge_table;
+
+	while (table && table->descr) {
+		for (i = 0; i < table->n_devs; i++) {
+			pdev = NULL;
+			do {
+				rc = sbridge_get_onedevice(&pdev, num_mc,
+							   table, i);
+				if (rc < 0) {
+					if (i == 0) {
+						i = table->n_devs;
+						break;
+					}
+					sbridge_put_all_devices();
+					return -ENODEV;
+				}
+			} while (pdev);
+		}
+		table++;
+	}
+
+	return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+			 struct sbridge_dev *sbridge_dev)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	int i, func, slot;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		slot = PCI_SLOT(pdev->devfn);
+		func = PCI_FUNC(pdev->devfn);
+		switch (slot) {
+		case 12:
+			switch (func) {
+			case 6:
+				pvt->pci_sad0 = pdev;
+				break;
+			case 7:
+				pvt->pci_sad1 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 13:
+			switch (func) {
+			case 6:
+				pvt->pci_br = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 14:
+			switch (func) {
+			case 0:
+				pvt->pci_ha0 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 15:
+			switch (func) {
+			case 0:
+				pvt->pci_ta = pdev;
+				break;
+			case 1:
+				pvt->pci_ras = pdev;
+				break;
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				pvt->pci_tad[func - 2] = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 17:
+			switch (func) {
+			case 0:
+				pvt->pci_ddrio = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		default:
+			goto error;
+		}
+
+		debugf0("Associated PCI %02x.%02d.%d with dev = %p\n",
+			sbridge_dev->bus,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			pdev);
+	}
+
+	/* Check if everything were registered */
+	if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
+	    !pvt-> pci_tad || !pvt->pci_ras  || !pvt->pci_ta ||
+	    !pvt->pci_ddrio)
+		goto enodev;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->pci_tad[i])
+			goto enodev;
+	}
+	return 0;
+
+enodev:
+	sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+	return -ENODEV;
+
+error:
+	sbridge_printk(KERN_ERR, "Device %d, function %d "
+		      "is out of the expected range\n",
+		      slot, func);
+	return -EINVAL;
+}
+
+/****************************************************************************
+			Error check routines
+ ****************************************************************************/
+
+/*
+ * While Sandy Bridge has error count registers, SMI BIOS read values from
+ * and resets the counters. So, they are not reliable for the OS to read
+ * from them. So, we have no option but to just trust on whatever MCE is
+ * telling us about the errors.
+ */
+static void sbridge_mce_output_error(struct mem_ctl_info *mci,
+				    const struct mce *m)
+{
+	struct mem_ctl_info *new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char *type, *optype, *msg, *recoverable_msg;
+	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
+	bool overflow = GET_BITFIELD(m->status, 62, 62);
+	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
+	bool recoverable = GET_BITFIELD(m->status, 56, 56);
+	u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
+	u32 mscod = GET_BITFIELD(m->status, 16, 31);
+	u32 errcode = GET_BITFIELD(m->status, 0, 15);
+	u32 channel = GET_BITFIELD(m->status, 0, 3);
+	u32 optypenum = GET_BITFIELD(m->status, 4, 6);
+	long channel_mask, first_channel;
+	u8  rank, socket;
+	int csrow, rc, dimm;
+	char *area_type = "Unknown";
+
+	if (ripv)
+		type = "NON_FATAL";
+	else
+		type = "FATAL";
+
+	/*
+	 * According with Table 15-9 of the Intel Archictecture spec vol 3A,
+	 * memory errors should fit in this mask:
+	 *	000f 0000 1mmm cccc (binary)
+	 * where:
+	 *	f = Correction Report Filtering Bit. If 1, subsequent errors
+	 *	    won't be shown
+	 *	mmm = error type
+	 *	cccc = channel
+	 * If the mask doesn't match, report an error to the parsing logic
+	 */
+	if (! ((errcode & 0xef80) == 0x80)) {
+		optype = "Can't parse: it is not a mem";
+	} else {
+		switch (optypenum) {
+		case 0:
+			optype = "generic undef request";
+			break;
+		case 1:
+			optype = "memory read";
+			break;
+		case 2:
+			optype = "memory write";
+			break;
+		case 3:
+			optype = "addr/cmd";
+			break;
+		case 4:
+			optype = "memory scrubbing";
+			break;
+		default:
+			optype = "reserved";
+			break;
+		}
+	}
+
+	rc = get_memory_error_data(mci, m->addr, &socket,
+				   &channel_mask, &rank, area_type);
+	if (rc < 0)
+		return;
+	new_mci = get_mci_for_node_id(socket);
+	if (!new_mci) {
+		edac_mc_handle_ce_no_info(mci, "Error: socket got corrupted!");
+		return;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
+
+	if (rank < 4)
+		dimm = 0;
+	else if (rank < 8)
+		dimm = 1;
+	else
+		dimm = 2;
+
+	csrow = pvt->csrow_map[first_channel][dimm];
+
+	if (uncorrected_error && recoverable)
+		recoverable_msg = " recoverable";
+	else
+		recoverable_msg = "";
+
+	/*
+	 * FIXME: What should we do with "channel" information on mcelog?
+	 * Probably, we can just discard it, as the channel information
+	 * comes from the get_memory_error_data() address decoding
+	 */
+	msg = kasprintf(GFP_ATOMIC,
+			"%d %s error(s): %s on %s area %s%s: cpu=%d Err=%04x:%04x (ch=%d), "
+			"addr = 0x%08llx => socket=%d, Channel=%ld(mask=%ld), rank=%d\n",
+			core_err_cnt,
+			area_type,
+			optype,
+			type,
+			recoverable_msg,
+			overflow ? "OVERFLOW" : "",
+			m->cpu,
+			mscod, errcode,
+			channel,		/* 1111b means not specified */
+			(long long) m->addr,
+			socket,
+			first_channel,		/* This is the real channel on SB */
+			channel_mask,
+			rank);
+
+	debugf0("%s", msg);
+
+	/* Call the helper to output message */
+	if (uncorrected_error)
+		edac_mc_handle_fbd_ue(mci, csrow, 0, 0, msg);
+	else
+		edac_mc_handle_fbd_ce(mci, csrow, 0, msg);
+
+	kfree(msg);
+}
+
+/*
+ *	sbridge_check_error	Retrieve and process errors reported by the
+ *				hardware. Called by the Core module.
+ */
+static void sbridge_check_error(struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i;
+	unsigned count = 0;
+	struct mce *m;
+
+	/*
+	 * MCE first step: Copy all mce errors into a temporary buffer
+	 * We use a double buffering here, to reduce the risk of
+	 * loosing an error.
+	 */
+	smp_rmb();
+	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+		% MCE_LOG_LEN;
+	if (!count)
+		return;
+
+	m = pvt->mce_outentry;
+	if (pvt->mce_in + count > MCE_LOG_LEN) {
+		unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+		memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+		smp_wmb();
+		pvt->mce_in = 0;
+		count -= l;
+		m += l;
+	}
+	memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+	smp_wmb();
+	pvt->mce_in += count;
+
+	smp_rmb();
+	if (pvt->mce_overrun) {
+		sbridge_printk(KERN_ERR, "Lost %d memory errors\n",
+			      pvt->mce_overrun);
+		smp_wmb();
+		pvt->mce_overrun = 0;
+	}
+
+	/*
+	 * MCE second step: parse errors and display
+	 */
+	for (i = 0; i < count; i++)
+		sbridge_mce_output_error(mci, &pvt->mce_outentry[i]);
+}
+
+/*
+ * sbridge_mce_check_error	Replicates mcelog routine to get errors
+ *				This routine simply queues mcelog errors, and
+ *				return. The error itself should be handled later
+ *				by sbridge_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
+				   void *data)
+{
+	struct mce *mce = (struct mce *)data;
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+
+	mci = get_mci_for_node_id(mce->socketid);
+	if (!mci)
+		return NOTIFY_BAD;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Just let mcelog handle it if the error is
+	 * outside the memory controller. A memory error
+	 * is indicated by bit 7 = 1 and bits = 8-11,13-15 = 0.
+	 * bit 12 has an special meaning.
+	 */
+	if ((mce->status & 0xefff) >> 7 != 1)
+		return NOTIFY_DONE;
+
+	printk("sbridge: HANDLING MCE MEMORY ERROR\n");
+
+	printk("CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
+	       mce->extcpu, mce->mcgstatus, mce->bank, mce->status);
+	printk("TSC %llx ", mce->tsc);
+	printk("ADDR %llx ", mce->addr);
+	printk("MISC %llx ", mce->misc);
+
+	printk("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+		mce->cpuvendor, mce->cpuid, mce->time,
+		mce->socketid, mce->apicid);
+
+#ifdef CONFIG_SMP
+	/* Only handle if it is the right mc controller */
+	if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
+		return NOTIFY_DONE;
+#endif
+
+	smp_rmb();
+	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
+		smp_wmb();
+		pvt->mce_overrun++;
+		return NOTIFY_DONE;
+	}
+
+	/* Copy memory error at the ringbuffer */
+	memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+	smp_wmb();
+	pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+	/* Handle fatal errors immediately */
+	if (mce->mcgstatus & 1)
+		sbridge_check_error(mci);
+
+	/* Advice mcelog that the error were handled */
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block sbridge_mce_dec = {
+	.notifier_call      = sbridge_mce_check_error,
+};
+
+/****************************************************************************
+			EDAC register/unregister logic
+ ****************************************************************************/
+
+static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci = sbridge_dev->mci;
+	struct sbridge_pvt *pvt;
+
+	if (unlikely(!mci || !mci->pvt_info)) {
+		debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+			__func__, &sbridge_dev->pdev[0]->dev);
+
+		sbridge_printk(KERN_ERR, "Couldn't find mci handler\n");
+		return;
+	}
+
+	pvt = mci->pvt_info;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
+					 &sbridge_mce_dec);
+
+	/* Remove MC sysfs nodes */
+	edac_mc_del_mc(mci->dev);
+
+	debugf1("%s: free mci struct\n", mci->ctl_name);
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+}
+
+static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+	int rc, channels, csrows;
+
+	/* Check the number of active and not disabled channels */
+	rc = sbridge_get_active_channels(sbridge_dev->bus, &channels, &csrows);
+	if (unlikely(rc < 0))
+		return rc;
+
+	/* allocate a new MC control structure */
+	mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, sbridge_dev->mc);
+	if (unlikely(!mci))
+		return -ENOMEM;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	pvt = mci->pvt_info;
+	memset(pvt, 0, sizeof(*pvt));
+
+	/* Associate sbridge_dev and mci for future usage */
+	pvt->sbridge_dev = sbridge_dev;
+	sbridge_dev->mci = mci;
+
+	mci->mtype_cap = MEM_FLAG_DDR3;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE;
+	mci->edac_cap = EDAC_FLAG_NONE;
+	mci->mod_name = "sbridge_edac.c";
+	mci->mod_ver = SBRIDGE_REVISION;
+	mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
+	mci->dev_name = pci_name(sbridge_dev->pdev[0]);
+	mci->ctl_page_to_phys = NULL;
+
+	/* Set the function pointer to an actual operation function */
+	mci->edac_check = sbridge_check_error;
+
+	/* Store pci devices at mci for faster access */
+	rc = mci_bind_devs(mci, sbridge_dev);
+	if (unlikely(rc < 0))
+		goto fail0;
+
+	/* Get dimm basic config and the memory layout */
+	get_dimm_config(mci);
+	get_memory_layout(mci);
+
+	/* record ptr to the generic device */
+	mci->dev = &sbridge_dev->pdev[0]->dev;
+
+	/* add this new MC control structure to EDAC's list of MCs */
+	if (unlikely(edac_mc_add_mc(mci))) {
+		debugf0("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		rc = -EINVAL;
+		goto fail0;
+	}
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain,
+				       &sbridge_mce_dec);
+	return 0;
+
+fail0:
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+	return rc;
+}
+
+/*
+ *	sbridge_probe	Probe for ONE instance of device to see if it is
+ *			present.
+ *	return:
+ *		0 for FOUND a device
+ *		< 0 for error code
+ */
+
+static int __devinit sbridge_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	int rc;
+	u8 mc, num_mc = 0;
+	struct sbridge_dev *sbridge_dev;
+
+	/* get the pci devices we want to reserve for our use */
+	mutex_lock(&sbridge_edac_lock);
+
+	/*
+	 * All memory controllers are allocated at the first pass.
+	 */
+	if (unlikely(probed >= 1)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return -ENODEV;
+	}
+	probed++;
+
+	rc = sbridge_get_all_devices(&num_mc);
+	if (unlikely(rc < 0))
+		goto fail0;
+	mc = 0;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc);
+		sbridge_dev->mc = mc++;
+		rc = sbridge_register_mci(sbridge_dev);
+		if (unlikely(rc < 0))
+			goto fail1;
+	}
+
+	sbridge_printk(KERN_INFO, "Driver loaded.\n");
+
+	mutex_unlock(&sbridge_edac_lock);
+	return 0;
+
+fail1:
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	sbridge_put_all_devices();
+fail0:
+	mutex_unlock(&sbridge_edac_lock);
+	return rc;
+}
+
+/*
+ *	sbridge_remove	destructor for one instance of device
+ *
+ */
+static void __devexit sbridge_remove(struct pci_dev *pdev)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	/*
+	 * we have a trouble here: pdev value for removal will be wrong, since
+	 * it will point to the X58 register used to detect that the machine
+	 * is a Nehalem or upper design. However, due to the way several PCI
+	 * devices are grouped together to provide MC functionality, we need
+	 * to use a different method for releasing the devices
+	 */
+
+	mutex_lock(&sbridge_edac_lock);
+
+	if (unlikely(!probed)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return;
+	}
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	/* Release PCI resources */
+	sbridge_put_all_devices();
+
+	probed--;
+
+	mutex_unlock(&sbridge_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
+
+/*
+ *	sbridge_driver	pci_driver structure for this module
+ *
+ */
+static struct pci_driver sbridge_driver = {
+	.name     = "sbridge_edac",
+	.probe    = sbridge_probe,
+	.remove   = __devexit_p(sbridge_remove),
+	.id_table = sbridge_pci_tbl,
+};
+
+/*
+ *	sbridge_init		Module entry function
+ *			Try to initialize this module for its devices
+ */
+static int __init sbridge_init(void)
+{
+	int pci_rc;
+
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
+	opstate_init();
+
+	pci_rc = pci_register_driver(&sbridge_driver);
+
+	if (pci_rc >= 0)
+		return 0;
+
+	sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n",
+		      pci_rc);
+
+	return pci_rc;
+}
+
+/*
+ *	sbridge_exit()	Module exit function
+ *			Unregister the driver
+ */
+static void __exit sbridge_exit(void)
+{
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+	pci_unregister_driver(&sbridge_driver);
+}
+
+module_init(sbridge_init);
+module_exit(sbridge_exit);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - "
+		   SBRIDGE_REVISION);
diff -druNp linux-libre-3.1-gnu1/drivers/firewire/core-iso.c linux-libre-3.2-gnu1/drivers/firewire/core-iso.c
--- linux-libre-3.1-gnu1/drivers/firewire/core-iso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firewire/core-iso.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 
 #include <asm/byteorder.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/firewire/core-transaction.c linux-libre-3.2-gnu1/drivers/firewire/core-transaction.c
--- linux-libre-3.1-gnu1/drivers/firewire/core-transaction.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firewire/core-transaction.c	2012-01-04 18:55:44.000000000 -0500
@@ -1046,8 +1046,8 @@ static void update_split_timeout(struct
 
 	cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);
 
-	cycles = max(cycles, 800u); /* minimum as per the spec */
-	cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */
+	/* minimum per IEEE 1394, maximum which doesn't overflow OHCI */
+	cycles = clamp(cycles, 800u, 3u * 8000u);
 
 	card->split_timeout_cycles = cycles;
 	card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);
diff -druNp linux-libre-3.1-gnu1/drivers/firewire/net.c linux-libre-3.2-gnu1/drivers/firewire/net.c
--- linux-libre-3.1-gnu1/drivers/firewire/net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firewire/net.c	2012-01-04 18:55:44.000000000 -0500
@@ -502,11 +502,7 @@ static struct fwnet_peer *fwnet_peer_fin
 static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
 {
 	max_rec = min(max_rec, speed + 8);
-	max_rec = min(max_rec, 0xbU); /* <= 4096 */
-	if (max_rec < 8) {
-		fw_notify("max_rec %x out of range\n", max_rec);
-		max_rec = 8;
-	}
+	max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */
 
 	return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
 }
@@ -1125,17 +1121,12 @@ static int fwnet_broadcast_start(struct
 	unsigned u;
 
 	if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
-		/* outside OHCI posted write area? */
-		static const struct fw_address_region region = {
-			.start = 0xffff00000000ULL,
-			.end   = CSR_REGISTER_BASE,
-		};
-
 		dev->handler.length = 4096;
 		dev->handler.address_callback = fwnet_receive_packet;
 		dev->handler.callback_data = dev;
 
-		retval = fw_core_add_address_handler(&dev->handler, &region);
+		retval = fw_core_add_address_handler(&dev->handler,
+					&fw_high_memory_region);
 		if (retval < 0)
 			goto failed_initial;
 
diff -druNp linux-libre-3.1-gnu1/drivers/firewire/ohci.c linux-libre-3.2-gnu1/drivers/firewire/ohci.c
--- linux-libre-3.1-gnu1/drivers/firewire/ohci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firewire/ohci.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 #include <linux/string.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -125,6 +126,7 @@ struct context {
 	struct fw_ohci *ohci;
 	u32 regs;
 	int total_allocation;
+	u32 current_bus;
 	bool running;
 	bool flushing;
 
@@ -226,7 +228,7 @@ struct fw_ohci {
 
 	__le32    *self_id_cpu;
 	dma_addr_t self_id_bus;
-	struct tasklet_struct bus_reset_tasklet;
+	struct work_struct bus_reset_work;
 
 	u32 self_id_buffer[512];
 };
@@ -263,6 +265,8 @@ static char ohci_driver_name[] = KBUILD_
 #define PCI_DEVICE_ID_AGERE_FW643	0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW	0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22	0x8009
+#define PCI_DEVICE_ID_TI_TSB12LV26	0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2	0x8025
 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS	0x11bd
 
 #define QUIRK_CYCLE_TIMER		1
@@ -270,6 +274,7 @@ static char ohci_driver_name[] = KBUILD_
 #define QUIRK_BE_HEADERS		4
 #define QUIRK_NO_1394A			8
 #define QUIRK_NO_MSI			16
+#define QUIRK_TI_SLLZ059		32
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
@@ -299,6 +304,12 @@ static const struct {
 	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
 		QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
 
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
 	{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
 		QUIRK_RESET_PACKET},
 
@@ -315,6 +326,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (d
 	", AR/selfID endianess = "	__stringify(QUIRK_BE_HEADERS)
 	", no 1394a enhancements = "	__stringify(QUIRK_NO_1394A)
 	", disable MSI = "		__stringify(QUIRK_NO_MSI)
+	", TI SLLZ059 erratum = "	__stringify(QUIRK_TI_SLLZ059)
 	")");
 
 #define OHCI_PARAM_DEBUG_AT_AR		1
@@ -859,7 +871,7 @@ static __le32 *handle_ar_packet(struct a
 	 *
 	 * Alas some chips sometimes emit bus reset packets with a
 	 * wrong generation.  We set the correct generation for these
-	 * at a slightly incorrect time (in bus_reset_tasklet).
+	 * at a slightly incorrect time (in bus_reset_work).
 	 */
 	if (evt == OHCI1394_evt_bus_reset) {
 		if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -1046,6 +1058,7 @@ static void context_tasklet(unsigned lon
 		address = le32_to_cpu(last->branch_address);
 		z = address & 0xf;
 		address &= ~0xf;
+		ctx->current_bus = address;
 
 		/* If the branch address points to a buffer outside of the
 		 * current buffer, advance to the next buffer. */
@@ -1713,9 +1726,94 @@ static u32 update_bus_time(struct fw_ohc
 	return ohci->bus_time | cycle_time_seconds;
 }
 
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
 {
-	struct fw_ohci *ohci = (struct fw_ohci *)data;
+	int reg;
+
+	mutex_lock(&ohci->phy_reg_mutex);
+	reg = write_phy_reg(ohci, 7, port_index);
+	if (reg >= 0)
+		reg = read_phy_reg(ohci, 8);
+	mutex_unlock(&ohci->phy_reg_mutex);
+	if (reg < 0)
+		return reg;
+
+	switch (reg & 0x0f) {
+	case 0x06:
+		return 2;	/* is child node (connected to parent node) */
+	case 0x0e:
+		return 3;	/* is parent node (connected to child node) */
+	}
+	return 1;		/* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+	int self_id_count)
+{
+	int i;
+	u32 entry;
+
+	for (i = 0; i < self_id_count; i++) {
+		entry = ohci->self_id_buffer[i];
+		if ((self_id & 0xff000000) == (entry & 0xff000000))
+			return -1;
+		if ((self_id & 0xff000000) < (entry & 0xff000000))
+			return i;
+	}
+	return i;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ * FIXME:  How to determine the selfID.i flag?
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+	int reg, i, pos, status;
+	/* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+	u32 self_id = 0x8040c800;
+
+	reg = reg_read(ohci, OHCI1394_NodeID);
+	if (!(reg & OHCI1394_NodeID_idValid)) {
+		fw_notify("node ID not valid, new bus reset in progress\n");
+		return -EBUSY;
+	}
+	self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+	reg = ohci_read_phy_reg(&ohci->card, 4);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x07) << 8); /* power class */
+
+	reg = ohci_read_phy_reg(&ohci->card, 1);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+	for (i = 0; i < 3; i++) {
+		status = get_status_for_port(ohci, i);
+		if (status < 0)
+			return status;
+		self_id |= ((status & 0x3) << (6 - (i * 2)));
+	}
+
+	pos = get_self_id_pos(ohci, self_id, self_id_count);
+	if (pos >= 0) {
+		memmove(&(ohci->self_id_buffer[pos+1]),
+			&(ohci->self_id_buffer[pos]),
+			(self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+		ohci->self_id_buffer[pos] = self_id;
+		self_id_count++;
+	}
+	return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
+{
+	struct fw_ohci *ohci =
+		container_of(work, struct fw_ohci, bus_reset_work);
 	int self_id_count, i, j, reg;
 	int generation, new_generation;
 	unsigned long flags;
@@ -1753,21 +1851,50 @@ static void bus_reset_tasklet(unsigned l
 	 * bit extra to get the actual number of self IDs.
 	 */
 	self_id_count = (reg >> 3) & 0xff;
-	if (self_id_count == 0 || self_id_count > 252) {
+
+	if (self_id_count > 252) {
 		fw_notify("inconsistent self IDs\n");
 		return;
 	}
+
 	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
 	rmb();
 
 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
 		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
-			fw_notify("inconsistent self IDs\n");
-			return;
+			/*
+			 * If the invalid data looks like a cycle start packet,
+			 * it's likely to be the result of the cycle master
+			 * having a wrong gap count.  In this case, the self IDs
+			 * so far are valid and should be processed so that the
+			 * bus manager can then correct the gap count.
+			 */
+			if (cond_le32_to_cpu(ohci->self_id_cpu[i])
+							== 0xffff008f) {
+				fw_notify("ignoring spurious self IDs\n");
+				self_id_count = j;
+				break;
+			} else {
+				fw_notify("inconsistent self IDs\n");
+				return;
+			}
 		}
 		ohci->self_id_buffer[j] =
 				cond_le32_to_cpu(ohci->self_id_cpu[i]);
 	}
+
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		self_id_count = find_and_insert_self_id(ohci, self_id_count);
+		if (self_id_count < 0) {
+			fw_notify("could not construct local self ID\n");
+			return;
+		}
+	}
+
+	if (self_id_count == 0) {
+		fw_notify("inconsistent self IDs\n");
+		return;
+	}
 	rmb();
 
 	/*
@@ -1887,7 +2014,7 @@ static irqreturn_t irq_handler(int irq,
 	log_irqs(event);
 
 	if (event & OHCI1394_selfIDComplete)
-		tasklet_schedule(&ohci->bus_reset_tasklet);
+		queue_work(fw_workqueue, &ohci->bus_reset_work);
 
 	if (event & OHCI1394_RQPkt)
 		tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1934,7 +2061,8 @@ static irqreturn_t irq_handler(int irq,
 		reg_read(ohci, OHCI1394_PostedWriteAddressLo);
 		reg_write(ohci, OHCI1394_IntEventClear,
 			  OHCI1394_postedWriteErr);
-		fw_error("PCI posted write error\n");
+		if (printk_ratelimit())
+			fw_error("PCI posted write error\n");
 	}
 
 	if (unlikely(event & OHCI1394_cycleTooLong)) {
@@ -2048,6 +2176,28 @@ static int configure_1394a_enhancements(
 	return 0;
 }
 
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+	/* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+	static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+	int reg, i;
+
+	reg = read_phy_reg(ohci, 2);
+	if (reg < 0)
+		return reg;
+	if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+		return 0;
+
+	for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+		reg = read_paged_phy_reg(ohci, 1, i + 10);
+		if (reg < 0)
+			return reg;
+		if (reg != id[i])
+			return 0;
+	}
+	return 1;
+}
+
 static int ohci_enable(struct fw_card *card,
 		       const __be32 *config_rom, size_t length)
 {
@@ -2085,6 +2235,16 @@ static int ohci_enable(struct fw_card *c
 		return -EIO;
 	}
 
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		ret = probe_tsb41ba3d(ohci);
+		if (ret < 0)
+			return ret;
+		if (ret)
+			fw_notify("local TSB41BA3D phy\n");
+		else
+			ohci->quirks &= ~QUIRK_TI_SLLZ059;
+	}
+
 	reg_write(ohci, OHCI1394_HCControlClear,
 		  OHCI1394_HCControl_noByteSwapData);
 
@@ -2260,7 +2420,7 @@ static int ohci_set_config_rom(struct fw
 	 * then set up the real values for the two registers.
 	 *
 	 * We use ohci->lock to avoid racing with the code that sets
-	 * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+	 * ohci->next_config_rom to NULL (see bus_reset_work).
 	 */
 
 	next_config_rom =
@@ -2539,6 +2699,7 @@ static int handle_ir_packet_per_buffer(s
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
 	struct descriptor *pd;
+	u32 buffer_dma;
 	__le32 *ir_header;
 	void *p;
 
@@ -2549,6 +2710,16 @@ static int handle_ir_packet_per_buffer(s
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+		d++;
+		buffer_dma = le32_to_cpu(d->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(d->req_count),
+					      DMA_FROM_DEVICE);
+	}
+
 	p = last + 1;
 	copy_iso_headers(ctx, p);
 
@@ -2571,11 +2742,19 @@ static int handle_ir_buffer_fill(struct
 {
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
+	u32 buffer_dma;
 
 	if (!last->transfer_status)
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	buffer_dma = le32_to_cpu(last->data_address);
+	dma_sync_single_range_for_cpu(context->ohci->card.device,
+				      buffer_dma & PAGE_MASK,
+				      buffer_dma & ~PAGE_MASK,
+				      le16_to_cpu(last->req_count),
+				      DMA_FROM_DEVICE);
+
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
 		ctx->base.callback.mc(&ctx->base,
 				      le32_to_cpu(last->data_address) +
@@ -2586,6 +2765,43 @@ static int handle_ir_buffer_fill(struct
 	return 1;
 }
 
+static inline void sync_it_packet_for_cpu(struct context *context,
+					  struct descriptor *pd)
+{
+	__le16 control;
+	u32 buffer_dma;
+
+	/* only packets beginning with OUTPUT_MORE* have data buffers */
+	if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+		return;
+
+	/* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+	pd += 2;
+
+	/*
+	 * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+	 * data buffer is in the context program's coherent page and must not
+	 * be synced.
+	 */
+	if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+	    (context->current_bus          & PAGE_MASK)) {
+		if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+			return;
+		pd++;
+	}
+
+	do {
+		buffer_dma = le32_to_cpu(pd->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(pd->req_count),
+					      DMA_TO_DEVICE);
+		control = pd->control;
+		pd++;
+	} while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
 static int handle_it_packet(struct context *context,
 			    struct descriptor *d,
 			    struct descriptor *last)
@@ -2602,6 +2818,8 @@ static int handle_it_packet(struct conte
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	sync_it_packet_for_cpu(context, d);
+
 	i = ctx->header_length;
 	if (i + 4 < PAGE_SIZE) {
 		/* Present this value as big-endian to match the receive code */
@@ -2971,6 +3189,10 @@ static int queue_iso_transmit(struct iso
 		page_bus = page_private(buffer->pages[page]);
 		pd[i].data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_TO_DEVICE);
+
 		payload_index += length;
 	}
 
@@ -2995,6 +3217,7 @@ static int queue_iso_packet_per_buffer(s
 				       struct fw_iso_buffer *buffer,
 				       unsigned long payload)
 {
+	struct device *device = ctx->context.ohci->card.device;
 	struct descriptor *d, *pd;
 	dma_addr_t d_bus, page_bus;
 	u32 z, header_z, rest;
@@ -3049,6 +3272,10 @@ static int queue_iso_packet_per_buffer(s
 			page_bus = page_private(buffer->pages[page]);
 			pd->data_address = cpu_to_le32(page_bus + offset);
 
+			dma_sync_single_range_for_device(device, page_bus,
+							 offset, length,
+							 DMA_FROM_DEVICE);
+
 			offset = (offset + length) & ~PAGE_MASK;
 			rest -= length;
 			if (offset == 0)
@@ -3108,6 +3335,10 @@ static int queue_iso_buffer_fill(struct
 		page_bus = page_private(buffer->pages[page]);
 		d->data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_FROM_DEVICE);
+
 		rest -= length;
 		offset = 0;
 		page++;
@@ -3239,8 +3470,7 @@ static int __devinit pci_probe(struct pc
 	spin_lock_init(&ohci->lock);
 	mutex_init(&ohci->phy_reg_mutex);
 
-	tasklet_init(&ohci->bus_reset_tasklet,
-		     bus_reset_tasklet, (unsigned long)ohci);
+	INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
 
 	err = pci_request_region(dev, 0, ohci_driver_name);
 	if (err) {
@@ -3382,6 +3612,7 @@ static void pci_remove(struct pci_dev *d
 	ohci = pci_get_drvdata(dev);
 	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
 	flush_writes(ohci);
+	cancel_work_sync(&ohci->bus_reset_work);
 	fw_core_remove_card(&ohci->card);
 
 	/*
diff -druNp linux-libre-3.1-gnu1/drivers/firewire/sbp2.c linux-libre-3.2-gnu1/drivers/firewire/sbp2.c
--- linux-libre-3.1-gnu1/drivers/firewire/sbp2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firewire/sbp2.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,12 +154,16 @@ struct sbp2_logical_unit {
 	bool blocked;
 };
 
+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
+{
+	queue_delayed_work(fw_workqueue, &lu->work, delay);
+}
+
 /*
  * We create one struct sbp2_target per IEEE 1212 Unit Directory
  * and one struct Scsi_Host per sbp2_target.
  */
 struct sbp2_target {
-	struct kref kref;
 	struct fw_unit *unit;
 	const char *bus_id;
 	struct list_head lu_list;
@@ -772,71 +776,6 @@ static int sbp2_lun2int(u16 lun)
 	return scsilun_to_int(&eight_bytes_lun);
 }
 
-static void sbp2_release_target(struct kref *kref)
-{
-	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
-	struct sbp2_logical_unit *lu, *next;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	struct scsi_device *sdev;
-	struct fw_device *device = target_device(tgt);
-
-	/* prevent deadlocks */
-	sbp2_unblock(tgt);
-
-	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
-		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
-		if (sdev) {
-			scsi_remove_device(sdev);
-			scsi_device_put(sdev);
-		}
-		if (lu->login_id != INVALID_LOGIN_ID) {
-			int generation, node_id;
-			/*
-			 * tgt->node_id may be obsolete here if we failed
-			 * during initial login or after a bus reset where
-			 * the topology changed.
-			 */
-			generation = device->generation;
-			smp_rmb(); /* node_id vs. generation */
-			node_id    = device->node_id;
-			sbp2_send_management_orb(lu, node_id, generation,
-						 SBP2_LOGOUT_REQUEST,
-						 lu->login_id, NULL);
-		}
-		fw_core_remove_address_handler(&lu->address_handler);
-		list_del(&lu->link);
-		kfree(lu);
-	}
-	scsi_remove_host(shost);
-	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
-
-	fw_unit_put(tgt->unit);
-	scsi_host_put(shost);
-	fw_device_put(device);
-}
-
-static void sbp2_target_get(struct sbp2_target *tgt)
-{
-	kref_get(&tgt->kref);
-}
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
-	kref_put(&tgt->kref, sbp2_release_target);
-}
-
-/*
- * Always get the target's kref when scheduling work on one its units.
- * Each workqueue job is responsible to call sbp2_target_put() upon return.
- */
-static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-{
-	sbp2_target_get(lu->tgt);
-	if (!queue_delayed_work(fw_workqueue, &lu->work, delay))
-		sbp2_target_put(lu->tgt);
-}
-
 /*
  * Write retransmit retry values into the BUSY_TIMEOUT register.
  * - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -877,7 +816,7 @@ static void sbp2_login(struct work_struc
 	int generation, node_id, local_node_id;
 
 	if (fw_device_is_shutdown(device))
-		goto out;
+		return;
 
 	generation    = device->generation;
 	smp_rmb();    /* node IDs must not be older than generation */
@@ -899,7 +838,7 @@ static void sbp2_login(struct work_struc
 			/* Let any waiting I/O fail from now on. */
 			sbp2_unblock(lu->tgt);
 		}
-		goto out;
+		return;
 	}
 
 	tgt->node_id	  = node_id;
@@ -925,7 +864,8 @@ static void sbp2_login(struct work_struc
 	if (lu->has_sdev) {
 		sbp2_cancel_orbs(lu);
 		sbp2_conditionally_unblock(lu);
-		goto out;
+
+		return;
 	}
 
 	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
@@ -957,7 +897,8 @@ static void sbp2_login(struct work_struc
 	lu->has_sdev = true;
 	scsi_device_put(sdev);
 	sbp2_allow_block(lu);
-	goto out;
+
+	return;
 
  out_logout_login:
 	smp_rmb(); /* generation may have changed */
@@ -971,8 +912,57 @@ static void sbp2_login(struct work_struc
 	 * lu->work already.  Reset the work from reconnect to login.
 	 */
 	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- out:
-	sbp2_target_put(tgt);
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+	struct sbp2_logical_unit *lu =
+		container_of(work, struct sbp2_logical_unit, work.work);
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_device *device = target_device(tgt);
+	int generation, node_id, local_node_id;
+
+	if (fw_device_is_shutdown(device))
+		return;
+
+	generation    = device->generation;
+	smp_rmb();    /* node IDs must not be older than generation */
+	node_id       = device->node_id;
+	local_node_id = device->card->node_id;
+
+	if (sbp2_send_management_orb(lu, node_id, generation,
+				     SBP2_RECONNECT_REQUEST,
+				     lu->login_id, NULL) < 0) {
+		/*
+		 * If reconnect was impossible even though we are in the
+		 * current generation, fall back and try to log in again.
+		 *
+		 * We could check for "Function rejected" status, but
+		 * looking at the bus generation as simpler and more general.
+		 */
+		smp_rmb(); /* get current card generation */
+		if (generation == device->card->generation ||
+		    lu->retries++ >= 5) {
+			fw_error("%s: failed to reconnect\n", tgt->bus_id);
+			lu->retries = 0;
+			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+		}
+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
+		return;
+	}
+
+	tgt->node_id      = node_id;
+	tgt->address_high = local_node_id << 16;
+	smp_wmb();	  /* node IDs must not be older than generation */
+	lu->generation	  = generation;
+
+	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
+		  tgt->bus_id, lu->lun, lu->retries);
+
+	sbp2_agent_reset(lu);
+	sbp2_cancel_orbs(lu);
+	sbp2_conditionally_unblock(lu);
 }
 
 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
@@ -1120,6 +1110,7 @@ static void sbp2_init_workarounds(struct
 }
 
 static struct scsi_host_template scsi_driver_template;
+static int sbp2_remove(struct device *dev);
 
 static int sbp2_probe(struct device *dev)
 {
@@ -1141,7 +1132,6 @@ static int sbp2_probe(struct device *dev
 	tgt = (struct sbp2_target *)shost->hostdata;
 	dev_set_drvdata(&unit->device, tgt);
 	tgt->unit = unit;
-	kref_init(&tgt->kref);
 	INIT_LIST_HEAD(&tgt->lu_list);
 	tgt->bus_id = dev_name(&unit->device);
 	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
@@ -1154,9 +1144,6 @@ static int sbp2_probe(struct device *dev
 	if (scsi_add_host(shost, &unit->device) < 0)
 		goto fail_shost_put;
 
-	fw_device_get(device);
-	fw_unit_get(unit);
-
 	/* implicit directory ID */
 	tgt->directory_id = ((unit->directory - device->config_rom) * 4
 			     + CSR_CONFIG_ROM) & 0xffffff;
@@ -1166,7 +1153,7 @@ static int sbp2_probe(struct device *dev
 
 	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
 			       &firmware_revision) < 0)
-		goto fail_tgt_put;
+		goto fail_remove;
 
 	sbp2_clamp_management_orb_timeout(tgt);
 	sbp2_init_workarounds(tgt, model, firmware_revision);
@@ -1177,16 +1164,17 @@ static int sbp2_probe(struct device *dev
 	 * specifies the max payload size as 2 ^ (max_payload + 2), so
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
-	tgt->max_payload = min(device->max_speed + 7, 10U);
-	tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+	tgt->max_payload = min3(device->max_speed + 7, 10U,
+				device->card->max_receive - 1);
 
 	/* Do the login in a workqueue so we can easily reschedule retries. */
 	list_for_each_entry(lu, &tgt->lu_list, link)
 		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
 	return 0;
 
- fail_tgt_put:
-	sbp2_target_put(tgt);
+ fail_remove:
+	sbp2_remove(dev);
 	return -ENOMEM;
 
  fail_shost_put:
@@ -1194,71 +1182,6 @@ static int sbp2_probe(struct device *dev
 	return -ENOMEM;
 }
 
-static int sbp2_remove(struct device *dev)
-{
-	struct fw_unit *unit = fw_unit(dev);
-	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
-	struct sbp2_logical_unit *lu;
-
-	list_for_each_entry(lu, &tgt->lu_list, link)
-		cancel_delayed_work_sync(&lu->work);
-
-	sbp2_target_put(tgt);
-	return 0;
-}
-
-static void sbp2_reconnect(struct work_struct *work)
-{
-	struct sbp2_logical_unit *lu =
-		container_of(work, struct sbp2_logical_unit, work.work);
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_device *device = target_device(tgt);
-	int generation, node_id, local_node_id;
-
-	if (fw_device_is_shutdown(device))
-		goto out;
-
-	generation    = device->generation;
-	smp_rmb();    /* node IDs must not be older than generation */
-	node_id       = device->node_id;
-	local_node_id = device->card->node_id;
-
-	if (sbp2_send_management_orb(lu, node_id, generation,
-				     SBP2_RECONNECT_REQUEST,
-				     lu->login_id, NULL) < 0) {
-		/*
-		 * If reconnect was impossible even though we are in the
-		 * current generation, fall back and try to log in again.
-		 *
-		 * We could check for "Function rejected" status, but
-		 * looking at the bus generation as simpler and more general.
-		 */
-		smp_rmb(); /* get current card generation */
-		if (generation == device->card->generation ||
-		    lu->retries++ >= 5) {
-			fw_error("%s: failed to reconnect\n", tgt->bus_id);
-			lu->retries = 0;
-			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-		}
-		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-		goto out;
-	}
-
-	tgt->node_id      = node_id;
-	tgt->address_high = local_node_id << 16;
-	smp_wmb();	  /* node IDs must not be older than generation */
-	lu->generation	  = generation;
-
-	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
-		  tgt->bus_id, lu->lun, lu->retries);
-
-	sbp2_agent_reset(lu);
-	sbp2_cancel_orbs(lu);
-	sbp2_conditionally_unblock(lu);
- out:
-	sbp2_target_put(tgt);
-}
-
 static void sbp2_update(struct fw_unit *unit)
 {
 	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
@@ -1277,6 +1200,51 @@ static void sbp2_update(struct fw_unit *
 	}
 }
 
+static int sbp2_remove(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device = fw_parent_device(unit);
+	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+	struct sbp2_logical_unit *lu, *next;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	struct scsi_device *sdev;
+
+	/* prevent deadlocks */
+	sbp2_unblock(tgt);
+
+	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+		cancel_delayed_work_sync(&lu->work);
+		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		}
+		if (lu->login_id != INVALID_LOGIN_ID) {
+			int generation, node_id;
+			/*
+			 * tgt->node_id may be obsolete here if we failed
+			 * during initial login or after a bus reset where
+			 * the topology changed.
+			 */
+			generation = device->generation;
+			smp_rmb(); /* node_id vs. generation */
+			node_id    = device->node_id;
+			sbp2_send_management_orb(lu, node_id, generation,
+						 SBP2_LOGOUT_REQUEST,
+						 lu->login_id, NULL);
+		}
+		fw_core_remove_address_handler(&lu->address_handler);
+		list_del(&lu->link);
+		kfree(lu);
+	}
+	scsi_remove_host(shost);
+	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
+
+	scsi_host_put(shost);
+	return 0;
+}
+
 #define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
 #define SBP2_SW_VERSION_ENTRY	0x00010483
 
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/dmi_scan.c linux-libre-3.2-gnu1/drivers/firmware/dmi_scan.c
--- linux-libre-3.1-gnu1/drivers/firmware/dmi_scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/dmi_scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -585,14 +585,12 @@ int dmi_name_in_serial(const char *str)
 }
 
 /**
- *	dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
+ *	dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
  *	@str: 	Case sensitive Name
  */
 int dmi_name_in_vendors(const char *str)
 {
-	static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
-				DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
-				DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
+	static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
 	int i;
 	for (i = 0; fields[i] != DMI_NONE; i++) {
 		int f = fields[i];
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/edd.c linux-libre-3.2-gnu1/drivers/firmware/edd.c
--- linux-libre-3.1-gnu1/drivers/firmware/edd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/edd.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,8 @@ edd_show_host_bus(struct edd_device *ede
 		p += scnprintf(p, left, "\tbase_address: %x\n",
 			     info->params.interface_path.isa.base_address);
 	} else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
-		   !strncmp(info->params.host_bus_type, "PCI", 3)) {
+		   !strncmp(info->params.host_bus_type, "PCI", 3) ||
+		   !strncmp(info->params.host_bus_type, "XPRS", 4)) {
 		p += scnprintf(p, left,
 			     "\t%02x:%02x.%d  channel: %u\n",
 			     info->params.interface_path.pci.bus,
@@ -159,7 +160,6 @@ edd_show_host_bus(struct edd_device *ede
 			     info->params.interface_path.pci.function,
 			     info->params.interface_path.pci.channel);
 	} else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
-		   !strncmp(info->params.host_bus_type, "XPRS", 4) ||
 		   !strncmp(info->params.host_bus_type, "HTPT", 4)) {
 		p += scnprintf(p, left,
 			     "\tTBD: %llx\n",
@@ -668,7 +668,7 @@ edd_get_pci_dev(struct edd_device *edev)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 
-	if (edd_dev_is_type(edev, "PCI")) {
+	if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) {
 		return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
 				     PCI_DEVFN(info->params.interface_path.pci.slot,
 					       info->params.interface_path.pci.
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/efivars.c linux-libre-3.2-gnu1/drivers/firmware/efivars.c
--- linux-libre-3.1-gnu1/drivers/firmware/efivars.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/efivars.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,7 +457,8 @@ static int efi_pstore_close(struct pstor
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-			       struct timespec *timespec, struct pstore_info *psi)
+			       struct timespec *timespec,
+			       char **buf, struct pstore_info *psi)
 {
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
@@ -478,7 +479,11 @@ static ssize_t efi_pstore_read(u64 *id,
 				timespec->tv_nsec = 0;
 				get_var_data_locked(efivars, &efivars->walk_entry->var);
 				size = efivars->walk_entry->var.DataSize;
-				memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+				*buf = kmalloc(size, GFP_KERNEL);
+				if (*buf == NULL)
+					return -ENOMEM;
+				memcpy(*buf, efivars->walk_entry->var.Data,
+				       size);
 				efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
 					           struct efivar_entry, list);
 				return size;
@@ -490,8 +495,8 @@ static ssize_t efi_pstore_read(u64 *id,
 	return 0;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	char name[DUMP_NAME_LEN];
 	char stub_name[DUMP_NAME_LEN];
@@ -499,7 +504,7 @@ static u64 efi_pstore_write(enum pstore_
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
 	struct efivar_entry *entry, *found = NULL;
-	int i;
+	int i, ret = 0;
 
 	sprintf(stub_name, "dump-type%u-%u-", type, part);
 	sprintf(name, "%s%lu", stub_name, get_seconds());
@@ -548,18 +553,19 @@ static u64 efi_pstore_write(enum pstore_
 		efivar_unregister(found);
 
 	if (size)
-		efivar_create_sysfs_entry(efivars,
+		ret = efivar_create_sysfs_entry(efivars,
 					  utf16_strsize(efi_name,
 							DUMP_NAME_LEN * 2),
 					  efi_name, &vendor);
 
-	return part;
+	*id = part;
+	return ret;
 };
 
 static int efi_pstore_erase(enum pstore_type_id type, u64 id,
 			    struct pstore_info *psi)
 {
-	efi_pstore_write(type, id, 0, psi);
+	efi_pstore_write(type, &id, (unsigned int)id, 0, psi);
 
 	return 0;
 }
@@ -575,13 +581,14 @@ static int efi_pstore_close(struct pstor
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-			       struct timespec *time, struct pstore_info *psi)
+			       struct timespec *timespec,
+			       char **buf, struct pstore_info *psi)
 {
 	return -1;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	return 0;
 }
@@ -978,7 +985,7 @@ int register_efivars(struct efivars *efi
 	if (efivars->efi_pstore_info.buf) {
 		efivars->efi_pstore_info.bufsize = 1024;
 		efivars->efi_pstore_info.data = efivars;
-		mutex_init(&efivars->efi_pstore_info.buf_mutex);
+		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
 		pstore_register(&efivars->efi_pstore_info);
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/google/gsmi.c linux-libre-3.2-gnu1/drivers/firmware/google/gsmi.c
--- linux-libre-3.1-gnu1/drivers/firmware/google/gsmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/google/gsmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kdebug.h>
 #include <linux/reboot.h>
 #include <linux/efi.h>
+#include <linux/module.h>
 
 #define GSMI_SHUTDOWN_CLEAN	0	/* Clean Shutdown */
 /* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/iscsi_ibft.c linux-libre-3.2-gnu1/drivers/firmware/iscsi_ibft.c
--- linux-libre-3.1-gnu1/drivers/firmware/iscsi_ibft.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/iscsi_ibft.c	2012-01-04 18:55:44.000000000 -0500
@@ -746,6 +746,37 @@ static void __exit ibft_exit(void)
 	ibft_cleanup();
 }
 
+#ifdef CONFIG_ACPI
+static const struct {
+	char *sign;
+} ibft_signs[] = {
+	/*
+	 * One spec says "IBFT", the other says "iBFT". We have to check
+	 * for both.
+	 */
+	{ ACPI_SIG_IBFT },
+	{ "iBFT" },
+};
+
+static void __init acpi_find_ibft_region(void)
+{
+	int i;
+	struct acpi_table_header *table = NULL;
+
+	if (acpi_disabled)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) {
+		acpi_get_table(ibft_signs[i].sign, 0, &table);
+		ibft_addr = (struct acpi_table_ibft *)table;
+	}
+}
+#else
+static void __init acpi_find_ibft_region(void)
+{
+}
+#endif
+
 /*
  * ibft_init() - creates sysfs tree entries for the iBFT data.
  */
@@ -753,9 +784,16 @@ static int __init ibft_init(void)
 {
 	int rc = 0;
 
+	/*
+	   As on UEFI systems the setup_arch()/find_ibft_region()
+	   is called before ACPI tables are parsed and it only does
+	   legacy finding.
+	*/
+	if (!ibft_addr)
+		acpi_find_ibft_region();
+
 	if (ibft_addr) {
-		printk(KERN_INFO "iBFT detected at 0x%llx.\n",
-		       (u64)isa_virt_to_bus(ibft_addr));
+		pr_info("iBFT detected.\n");
 
 		rc = ibft_check_device();
 		if (rc)
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/iscsi_ibft_find.c linux-libre-3.2-gnu1/drivers/firmware/iscsi_ibft_find.c
--- linux-libre-3.1-gnu1/drivers/firmware/iscsi_ibft_find.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/iscsi_ibft_find.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,13 +45,6 @@ EXPORT_SYMBOL_GPL(ibft_addr);
 static const struct {
 	char *sign;
 } ibft_signs[] = {
-#ifdef CONFIG_ACPI
-	/*
-	 * One spec says "IBFT", the other says "iBFT". We have to check
-	 * for both.
-	 */
-	{ ACPI_SIG_IBFT },
-#endif
 	{ "iBFT" },
 	{ "BIFT" },	/* Broadcom iSCSI Offload */
 };
@@ -62,14 +55,6 @@ static const struct {
 #define VGA_MEM 0xA0000 /* VGA buffer */
 #define VGA_SIZE 0x20000 /* 128kB */
 
-#ifdef CONFIG_ACPI
-static int __init acpi_find_ibft(struct acpi_table_header *header)
-{
-	ibft_addr = (struct acpi_table_ibft *)header;
-	return 0;
-}
-#endif /* CONFIG_ACPI */
-
 static int __init find_ibft_in_mem(void)
 {
 	unsigned long pos;
@@ -94,6 +79,7 @@ static int __init find_ibft_in_mem(void)
 				 * the table cannot be valid. */
 				if (pos + len <= (IBFT_END-1)) {
 					ibft_addr = (struct acpi_table_ibft *)virt;
+					pr_info("iBFT found at 0x%lx.\n", pos);
 					goto done;
 				}
 			}
@@ -108,20 +94,12 @@ done:
  */
 unsigned long __init find_ibft_region(unsigned long *sizep)
 {
-#ifdef CONFIG_ACPI
-	int i;
-#endif
 	ibft_addr = NULL;
 
-#ifdef CONFIG_ACPI
-	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)
-		acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);
-#endif /* CONFIG_ACPI */
-
 	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
 	 * only use ACPI for this */
 
-	if (!ibft_addr && !efi_enabled)
+	if (!efi_enabled)
 		find_ibft_in_mem();
 
 	if (ibft_addr) {
diff -druNp linux-libre-3.1-gnu1/drivers/firmware/sigma.c linux-libre-3.2-gnu1/drivers/firmware/sigma.c
--- linux-libre-3.1-gnu1/drivers/firmware/sigma.c	2013-05-02 01:48:08.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/firmware/sigma.c	2013-05-01 23:52:54.000000000 -0400
@@ -14,13 +14,34 @@
 #include <linux/module.h>
 #include <linux/sigma.h>
 
-/* Return: 0==OK, <0==error, =1 ==no more actions */
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+	size_t payload = 0;
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		payload = sigma_action_len(sa);
+		break;
+	default:
+		break;
+	}
+
+	payload = ALIGN(payload, 2);
+
+	return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
 static int
-process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
+process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
 {
-	struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
 	size_t len = sigma_action_len(sa);
-	int ret = 0;
+	int ret;
 
 	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
 		sa->instr, sa->addr, len);
@@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *
 	case SIGMA_ACTION_WRITEXBYTES:
 	case SIGMA_ACTION_WRITESINGLE:
 	case SIGMA_ACTION_WRITESAFELOAD:
-		if (ssfw->fw->size < ssfw->pos + len)
-			return -EINVAL;
 		ret = i2c_master_send(client, (void *)&sa->addr, len);
 		if (ret < 0)
 			return -EINVAL;
 		break;
-
 	case SIGMA_ACTION_DELAY:
-		ret = 0;
 		udelay(len);
 		len = 0;
 		break;
-
 	case SIGMA_ACTION_END:
-		return 1;
-
+		return 0;
 	default:
 		return -EINVAL;
 	}
 
-	/* when arrive here ret=0 or sent data */
-	ssfw->pos += sigma_action_size(sa, len);
-	return ssfw->pos == ssfw->fw->size;
+	return 1;
 }
 
 static int
 process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
 {
-	pr_debug("%s: processing %p\n", __func__, ssfw);
+	struct sigma_action *sa;
+	size_t size;
+	int ret;
+
+	while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+		sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+		size = sigma_action_size(sa);
+		ssfw->pos += size;
+		if (ssfw->pos > ssfw->fw->size || size == 0)
+			break;
+
+		ret = process_sigma_action(client, sa);
 
-	while (1) {
-		int ret = process_sigma_action(client, ssfw);
 		pr_debug("%s: action returned %i\n", __func__, ret);
-		if (ret == 1)
-			return 0;
-		else if (ret)
+
+		if (ret <= 0)
 			return ret;
 	}
+
+	if (ssfw->pos != ssfw->fw->size)
+		return -EINVAL;
+
+	return 0;
 }
 
 int process_sigma_firmware(struct i2c_client *client, const char *name)
@@ -89,16 +116,24 @@ int process_sigma_firmware(struct i2c_cl
 
 	/* then verify the header */
 	ret = -EINVAL;
-	if (fw->size < sizeof(*ssfw_head))
+
+	/*
+	 * Reject too small or unreasonable large files. The upper limit has been
+	 * chosen a bit arbitrarily, but it should be enough for all practical
+	 * purposes and having the limit makes it easier to avoid integer
+	 * overflows later in the loading process.
+	 */
+	if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
 		goto done;
 
 	ssfw_head = (void *)fw->data;
 	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
 		goto done;
 
-	crc = crc32(0, fw->data, fw->size);
+	crc = crc32(0, fw->data + sizeof(*ssfw_head),
+			fw->size - sizeof(*ssfw_head));
 	pr_debug("%s: crc=%x\n", __func__, crc);
-	if (crc != ssfw_head->crc)
+	if (crc != le32_to_cpu(ssfw_head->crc))
 		goto done;
 
 	ssfw.pos = sizeof(*ssfw_head);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-74x164.c linux-libre-3.2-gnu1/drivers/gpio/gpio-74x164.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-74x164.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-74x164.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/spi/74x164.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct gen_74x164_chip {
 	struct spi_device	*spi;
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-da9052.c linux-libre-3.2-gnu1/drivers/gpio/gpio-da9052.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-da9052.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-da9052.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/mfd/da9052/da9052.h>
 #include <linux/mfd/da9052/reg.h>
 #include <linux/mfd/da9052/pdata.h>
-#include <linux/mfd/da9052/gpio.h>
 
 #define DA9052_INPUT				1
 #define DA9052_OUTPUT_OPENDRAIN		2
@@ -43,6 +42,9 @@
 #define DA9052_GPIO_MASK_UPPER_NIBBLE		0xF0
 #define DA9052_GPIO_MASK_LOWER_NIBBLE		0x0F
 #define DA9052_GPIO_NIBBLE_SHIFT		4
+#define DA9052_IRQ_GPI0			16
+#define DA9052_GPIO_ODD_SHIFT			7
+#define DA9052_GPIO_EVEN_SHIFT			3
 
 struct da9052_gpio {
 	struct da9052 *da9052;
@@ -104,33 +106,26 @@ static int da9052_gpio_get(struct gpio_c
 static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
 	struct da9052_gpio *gpio = to_da9052_gpio(gc);
-	unsigned char register_value = 0;
 	int ret;
 
 	if (da9052_gpio_port_odd(offset)) {
-		if (value) {
-			register_value = DA9052_GPIO_ODD_PORT_MODE;
 			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 						DA9052_GPIO_0_1_REG,
 						DA9052_GPIO_ODD_PORT_MODE,
-						register_value);
+						value << DA9052_GPIO_ODD_SHIFT);
 			if (ret != 0)
 				dev_err(gpio->da9052->dev,
 					"Failed to updated gpio odd reg,%d",
 					ret);
-		}
 	} else {
-		if (value) {
-			register_value = DA9052_GPIO_EVEN_PORT_MODE;
 			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 						DA9052_GPIO_0_1_REG,
 						DA9052_GPIO_EVEN_PORT_MODE,
-						register_value);
+						value << DA9052_GPIO_EVEN_SHIFT);
 			if (ret != 0)
 				dev_err(gpio->da9052->dev,
 					"Failed to updated gpio even reg,%d",
 					ret);
-		}
 	}
 }
 
@@ -201,9 +196,9 @@ static struct gpio_chip reference_gp __d
 	.direction_input = da9052_gpio_direction_input,
 	.direction_output = da9052_gpio_direction_output,
 	.to_irq = da9052_gpio_to_irq,
-	.can_sleep = 1;
-	.ngpio = 16;
-	.base = -1;
+	.can_sleep = 1,
+	.ngpio = 16,
+	.base = -1,
 };
 
 static int __devinit da9052_gpio_probe(struct platform_device *pdev)
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-davinci.c linux-libre-3.2-gnu1/drivers/gpio/gpio-davinci.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-davinci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-davinci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,455 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006-2007 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/gpio.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+
+struct davinci_gpio_regs {
+	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;
+};
+
+#define chip2controller(chip)	\
+	container_of(chip, struct davinci_gpio_controller, chip)
+
+static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
+static void __iomem *gpio_base;
+
+static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
+{
+	void __iomem *ptr;
+
+	if (gpio < 32 * 1)
+		ptr = gpio_base + 0x10;
+	else if (gpio < 32 * 2)
+		ptr = gpio_base + 0x38;
+	else if (gpio < 32 * 3)
+		ptr = gpio_base + 0x60;
+	else if (gpio < 32 * 4)
+		ptr = gpio_base + 0x88;
+	else if (gpio < 32 * 5)
+		ptr = gpio_base + 0xb0;
+	else
+		ptr = NULL;
+	return ptr;
+}
+
+static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
+{
+	struct davinci_gpio_regs __iomem *g;
+
+	g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
+
+	return g;
+}
+
+static int __init davinci_gpio_irq_setup(void);
+
+/*--------------------------------------------------------------------------*/
+
+/* board setup code *MUST* setup pinmux and enable the GPIO clock. */
+static inline int __davinci_direction(struct gpio_chip *chip,
+			unsigned offset, bool out, int value)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+	unsigned long flags;
+	u32 temp;
+	u32 mask = 1 << offset;
+
+	spin_lock_irqsave(&d->lock, flags);
+	temp = __raw_readl(&g->dir);
+	if (out) {
+		temp &= ~mask;
+		__raw_writel(mask, value ? &g->set_data : &g->clr_data);
+	} else {
+		temp |= mask;
+	}
+	__raw_writel(temp, &g->dir);
+	spin_unlock_irqrestore(&d->lock, flags);
+
+	return 0;
+}
+
+static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	return __davinci_direction(chip, offset, false, 0);
+}
+
+static int
+davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+	return __davinci_direction(chip, offset, true, value);
+}
+
+/*
+ * 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.
+ */
+static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+
+	return (1 << offset) & __raw_readl(&g->in_data);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+static void
+davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+
+	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
+}
+
+static int __init davinci_gpio_setup(void)
+{
+	int i, base;
+	unsigned ngpio;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_gpio_regs *regs;
+
+	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI)
+		return 0;
+
+	/*
+	 * The gpio banks conceptually expose a segmented bitmap,
+	 * and "ngpio" is one more than the largest zero-based
+	 * bit index that's valid.
+	 */
+	ngpio = soc_info->gpio_num;
+	if (ngpio == 0) {
+		pr_err("GPIO setup:  how many GPIOs?\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(DAVINCI_N_GPIO < ngpio))
+		ngpio = DAVINCI_N_GPIO;
+
+	gpio_base = ioremap(soc_info->gpio_base, SZ_4K);
+	if (WARN_ON(!gpio_base))
+		return -ENOMEM;
+
+	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
+		chips[i].chip.label = "DaVinci";
+
+		chips[i].chip.direction_input = davinci_direction_in;
+		chips[i].chip.get = davinci_gpio_get;
+		chips[i].chip.direction_output = davinci_direction_out;
+		chips[i].chip.set = davinci_gpio_set;
+
+		chips[i].chip.base = base;
+		chips[i].chip.ngpio = ngpio - base;
+		if (chips[i].chip.ngpio > 32)
+			chips[i].chip.ngpio = 32;
+
+		spin_lock_init(&chips[i].lock);
+
+		regs = gpio2regs(base);
+		chips[i].regs = regs;
+		chips[i].set_data = &regs->set_data;
+		chips[i].clr_data = &regs->clr_data;
+		chips[i].in_data = &regs->in_data;
+
+		gpiochip_add(&chips[i].chip);
+	}
+
+	soc_info->gpio_ctlrs = chips;
+	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
+
+	davinci_gpio_irq_setup();
+	return 0;
+}
+pure_initcall(davinci_gpio_setup);
+
+/*--------------------------------------------------------------------------*/
+/*
+ * 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:  The first few GPIOs also have direct INTC hookups in addition
+ * to their GPIOBNK0 irq, with a bit less overhead.
+ *
+ * All those INTC hookups (direct, plus several IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(struct irq_data *d)
+{
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
+
+	__raw_writel(mask, &g->clr_falling);
+	__raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(struct irq_data *d)
+{
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
+	unsigned status = irqd_get_trigger_type(d);
+
+	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+	if (!status)
+		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+
+	if (status & IRQ_TYPE_EDGE_FALLING)
+		__raw_writel(mask, &g->set_falling);
+	if (status & IRQ_TYPE_EDGE_RISING)
+		__raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned trigger)
+{
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_enable	= gpio_irq_enable,
+	.irq_disable	= gpio_irq_disable,
+	.irq_set_type	= gpio_irq_type,
+	.flags		= IRQCHIP_SET_TYPE_MASKED,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct davinci_gpio_regs __iomem *g;
+	u32 mask = 0xffff;
+	struct davinci_gpio_controller *d;
+
+	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
+	g = (struct davinci_gpio_regs __iomem *)d->regs;
+
+	/* we only care about one bank */
+	if (irq & 1)
+		mask <<= 16;
+
+	/* temporarily mask (level sensitive) parent IRQ */
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	while (1) {
+		u32		status;
+		int		n;
+		int		res;
+
+		/* ack any irqs */
+		status = __raw_readl(&g->intstat) & mask;
+		if (!status)
+			break;
+		__raw_writel(status, &g->intstat);
+
+		/* now demux them to the right lowlevel handler */
+		n = d->irq_base;
+		if (irq & 1) {
+			n += 16;
+			status >>= 16;
+		}
+
+		while (status) {
+			res = ffs(status);
+			n += res;
+			generic_handle_irq(n - 1);
+			status >>= res;
+		}
+	}
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	/* now it may re-trigger */
+}
+
+static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+
+	if (d->irq_base >= 0)
+		return d->irq_base + offset;
+	else
+		return -ENODEV;
+}
+
+static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	/* NOTE:  we assume for now that only irqs in the first gpio_chip
+	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
+	 */
+	if (offset < soc_info->gpio_unbanked)
+		return soc_info->gpio_irq + offset;
+	else
+		return -ENODEV;
+}
+
+static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
+{
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
+
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	__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;
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a platform_device with
+ * suspend_late/resume_resume calls hooking into 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
+ * (dm6446) can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+	unsigned	gpio, irq, bank;
+	struct clk	*clk;
+	u32		binten = 0;
+	unsigned	ngpio, bank_irq;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_gpio_regs	__iomem *g;
+
+	ngpio = soc_info->gpio_num;
+
+	bank_irq = soc_info->gpio_irq;
+	if (bank_irq == 0) {
+		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
+		return -EINVAL;
+	}
+
+	clk = clk_get(NULL, "gpio");
+	if (IS_ERR(clk)) {
+		printk(KERN_ERR "Error %ld getting gpio clock?\n",
+		       PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+	clk_enable(clk);
+
+	/* Arrange gpio_to_irq() support, handling either direct IRQs or
+	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
+	 * IRQs, while the others use banked IRQs, would need some setup
+	 * tweaks to recognize hardware which can do that.
+	 */
+	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
+		chips[bank].chip.to_irq = gpio_to_irq_banked;
+		chips[bank].irq_base = soc_info->gpio_unbanked
+			? -EINVAL
+			: (soc_info->intc_irq_num + gpio);
+	}
+
+	/*
+	 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
+	 * controller only handling trigger modes.  We currently assume no
+	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
+	 */
+	if (soc_info->gpio_unbanked) {
+		static struct irq_chip gpio_irqchip_unbanked;
+
+		/* pass "bank 0" GPIO IRQs to AINTC */
+		chips[0].chip.to_irq = gpio_to_irq_unbanked;
+		binten = BIT(0);
+
+		/* AINTC handles mask/unmask; GPIO handles triggering */
+		irq = bank_irq;
+		gpio_irqchip_unbanked = *irq_get_chip(irq);
+		gpio_irqchip_unbanked.name = "GPIO-AINTC";
+		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
+
+		/* default trigger: both edges */
+		g = gpio2regs(0);
+		__raw_writel(~0, &g->set_falling);
+		__raw_writel(~0, &g->set_rising);
+
+		/* set the direct IRQs up to use that irqchip */
+		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
+			irq_set_chip(irq, &gpio_irqchip_unbanked);
+			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+			irq_set_chip_data(irq, (__force void *)g);
+			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
+		}
+
+		goto done;
+	}
+
+	/*
+	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
+	 * then chain through our own handler.
+	 */
+	for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
+			gpio < ngpio;
+			bank++, bank_irq++) {
+		unsigned		i;
+
+		/* disabled by default, enabled only as needed */
+		g = gpio2regs(gpio);
+		__raw_writel(~0, &g->clr_falling);
+		__raw_writel(~0, &g->clr_rising);
+
+		/* set up all irqs in this bank */
+		irq_set_chained_handler(bank_irq, gpio_irq_handler);
+
+		/*
+		 * Each chip handles 32 gpios, and each irq bank consists of 16
+		 * gpio irqs. Pass the irq bank's corresponding controller to
+		 * the chained irq handler.
+		 */
+		irq_set_handler_data(bank_irq, &chips[gpio / 32]);
+
+		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
+			irq_set_chip(irq, &gpio_irqchip);
+			irq_set_chip_data(irq, (__force void *)g);
+			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+			irq_set_handler(irq, handle_simple_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+
+		binten |= BIT(bank);
+	}
+
+done:
+	/* BINTEN -- per-bank interrupt enable. genirq would also let these
+	 * bits be set/cleared dynamically.
+	 */
+	__raw_writel(binten, gpio_base + 0x08);
+
+	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-ep93xx.c linux-libre-3.2-gnu1/drivers/gpio/gpio-ep93xx.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-ep93xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-ep93xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -23,6 +24,9 @@
 #include <linux/basic_mmio_gpio.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio-ep93xx.h>
+
+#define irq_to_gpio(irq)	((irq) - gpio_to_irq(0))
 
 struct ep93xx_gpio {
 	void __iomem		*mmio_base;
@@ -307,6 +311,21 @@ static int ep93xx_gpio_set_debounce(stru
 	return 0;
 }
 
+/*
+ * Map GPIO A0..A7  (0..7)  to irq 64..71,
+ *          B0..B7  (7..15) to irq 72..79, and
+ *          F0..F7 (16..24) to irq 80..87.
+ */
+static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	if (gpio > EP93XX_GPIO_LINE_MAX_IRQ)
+		return -EINVAL;
+
+	return 64 + gpio;
+}
+
 static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
 	void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
 {
@@ -321,8 +340,10 @@ static int ep93xx_gpio_add_bank(struct b
 	bgc->gc.label = bank->label;
 	bgc->gc.base = bank->base;
 
-	if (bank->has_debounce)
+	if (bank->has_debounce) {
 		bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
+		bgc->gc.to_irq = ep93xx_gpio_to_irq;
+	}
 
 	return gpiochip_add(&bgc->gc);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-exynos4.c linux-libre-3.2-gnu1/drivers/gpio/gpio-exynos4.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-exynos4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-exynos4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,385 +0,0 @@
-/*
- * EXYNOS4 - GPIOlib support
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull)
-{
-	if (pull == S3C_GPIO_PULL_UP)
-		pull = 3;
-
-	return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
-						unsigned int off)
-{
-	s3c_gpio_pull_t pull;
-
-	pull = s3c_gpio_getpull_updown(chip, off);
-	if (pull == 3)
-		pull = S3C_GPIO_PULL_UP;
-
-	return pull;
-}
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_exynos4,
-	.get_pull	= s3c_gpio_getpull_exynos4,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_exynos4,
-	.get_pull	= s3c_gpio_getpull_exynos4,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
-	{
-		.chip	= {
-			.base	= EXYNOS4_GPA0(0),
-			.ngpio	= EXYNOS4_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPA1(0),
-			.ngpio	= EXYNOS4_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPB(0),
-			.ngpio	= EXYNOS4_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPC0(0),
-			.ngpio	= EXYNOS4_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPC1(0),
-			.ngpio	= EXYNOS4_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPD0(0),
-			.ngpio	= EXYNOS4_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPD1(0),
-			.ngpio	= EXYNOS4_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPE0(0),
-			.ngpio	= EXYNOS4_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPE1(0),
-			.ngpio	= EXYNOS4_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPE2(0),
-			.ngpio	= EXYNOS4_GPIO_E2_NR,
-			.label	= "GPE2",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPE3(0),
-			.ngpio	= EXYNOS4_GPIO_E3_NR,
-			.label	= "GPE3",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPE4(0),
-			.ngpio	= EXYNOS4_GPIO_E4_NR,
-			.label	= "GPE4",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPF0(0),
-			.ngpio	= EXYNOS4_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPF1(0),
-			.ngpio	= EXYNOS4_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPF2(0),
-			.ngpio	= EXYNOS4_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPF3(0),
-			.ngpio	= EXYNOS4_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	},
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
-	{
-		.chip	= {
-			.base	= EXYNOS4_GPJ0(0),
-			.ngpio	= EXYNOS4_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPJ1(0),
-			.ngpio	= EXYNOS4_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPK0(0),
-			.ngpio	= EXYNOS4_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPK1(0),
-			.ngpio	= EXYNOS4_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPK2(0),
-			.ngpio	= EXYNOS4_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPK3(0),
-			.ngpio	= EXYNOS4_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPL0(0),
-			.ngpio	= EXYNOS4_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPL1(0),
-			.ngpio	= EXYNOS4_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.chip	= {
-			.base	= EXYNOS4_GPL2(0),
-			.ngpio	= EXYNOS4_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY0(0),
-			.ngpio	= EXYNOS4_GPIO_Y0_NR,
-			.label	= "GPY0",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY1(0),
-			.ngpio	= EXYNOS4_GPIO_Y1_NR,
-			.label	= "GPY1",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY2(0),
-			.ngpio	= EXYNOS4_GPIO_Y2_NR,
-			.label	= "GPY2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY3(0),
-			.ngpio	= EXYNOS4_GPIO_Y3_NR,
-			.label	= "GPY3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY4(0),
-			.ngpio	= EXYNOS4_GPIO_Y4_NR,
-			.label	= "GPY4",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY5(0),
-			.ngpio	= EXYNOS4_GPIO_Y5_NR,
-			.label	= "GPY5",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= EXYNOS4_GPY6(0),
-			.ngpio	= EXYNOS4_GPIO_Y6_NR,
-			.label	= "GPY6",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC00),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= EXYNOS4_GPX0(0),
-			.ngpio	= EXYNOS4_GPIO_X0_NR,
-			.label	= "GPX0",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC20),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= EXYNOS4_GPX1(0),
-			.ngpio	= EXYNOS4_GPIO_X1_NR,
-			.label	= "GPX1",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC40),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= EXYNOS4_GPX2(0),
-			.ngpio	= EXYNOS4_GPIO_X2_NR,
-			.label	= "GPX2",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC60),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= EXYNOS4_GPX3(0),
-			.ngpio	= EXYNOS4_GPIO_X3_NR,
-			.label	= "GPX3",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
-	{
-		.chip	= {
-			.base	= EXYNOS4_GPZ(0),
-			.ngpio	= EXYNOS4_GPIO_Z_NR,
-			.label	= "GPZ",
-		},
-	},
-};
-
-static __init int exynos4_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip;
-	int i;
-	int group = 0;
-	int nr_chips;
-
-	/* GPIO part 1 */
-
-	chip = exynos4_gpio_part1_4bit;
-	nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			/* Assign the GPIO interrupt group */
-			chip->group = group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
-
-	/* GPIO part 2 */
-
-	chip = exynos4_gpio_part2_4bit;
-	nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			/* Assign the GPIO interrupt group */
-			chip->group = group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
-
-	/* GPIO part 3 */
-
-	chip = exynos4_gpio_part3_4bit;
-	nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			/* Assign the GPIO interrupt group */
-			chip->group = group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
-	s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-	s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-
-	return 0;
-}
-core_initcall(exynos4_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-ks8695.c linux-libre-3.2-gnu1/drivers/gpio/gpio-ks8695.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-ks8695.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-ks8695.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,319 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
+ *                     Daniel Silverstone <dsilvers@simtec.co.uk>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/gpio-ks8695.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
+		return;
+
+	local_irq_save(flags);
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+	if (gpio)			/* GPIO: set bit to 0 */
+		x &= ~enable[pin];
+	else				/* Internal function: set bit to 1 */
+		x |= enable[pin];
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+	local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	/* Set IRQ triggering type */
+	irq_set_irq_type(gpio_irq[pin], type);
+
+	/* enable interrupt mode */
+	ks8695_gpio_mode(pin, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+static int ks8695_gpio_direction_output(struct gpio_chip *gc,
+					unsigned int pin, int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= IOPD(pin);
+	else
+		x &= ~IOPD(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	/* set pin as output */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x |= IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+static void ks8695_gpio_set_value(struct gpio_chip *gc,
+				  unsigned int pin, int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return;
+
+	local_irq_save(flags);
+
+	/* set output line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= IOPD(pin);
+	else
+		x &= ~IOPD(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	local_irq_restore(flags);
+}
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
+{
+	unsigned long x;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	return (x & IOPD(pin)) != 0;
+}
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
+{
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	return gpio_irq[pin];
+}
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+		return -EINVAL;
+
+	return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
+/* GPIOLIB interface */
+
+static struct gpio_chip ks8695_gpio_chip = {
+	.label			= "KS8695",
+	.direction_input	= ks8695_gpio_direction_input,
+	.direction_output	= ks8695_gpio_direction_output,
+	.get			= ks8695_gpio_get_value,
+	.set			= ks8695_gpio_set_value,
+	.to_irq			= ks8695_gpio_to_irq,
+	.base			= 0,
+	.ngpio			= 16,
+	.can_sleep		= 0,
+};
+
+/* Register the GPIOs */
+void ks8695_register_gpios(void)
+{
+	if (gpiochip_add(&ks8695_gpio_chip))
+		printk(KERN_ERR "Unable to register core GPIOs\n");
+}
+
+/* .... Debug interface ..................................................... */
+
+#ifdef CONFIG_DEBUG_FS
+
+static int ks8695_gpio_show(struct seq_file *s, void *unused)
+{
+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
+	unsigned long mode, ctrl, data;
+	int i;
+
+	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+
+	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
+
+	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
+		seq_printf(s, "%i:\t", i);
+
+		seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
+
+		if (i <= KS8695_GPIO_3) {
+			if (ctrl & enable[i]) {
+				seq_printf(s, "EXT%i ", i);
+
+				switch ((ctrl & intmask[i]) >> (4 * i)) {
+					case IOPC_TM_LOW:
+						seq_printf(s, "(Low)");		break;
+					case IOPC_TM_HIGH:
+						seq_printf(s, "(High)");	break;
+					case IOPC_TM_RISING:
+						seq_printf(s, "(Rising)");	break;
+					case IOPC_TM_FALLING:
+						seq_printf(s, "(Falling)");	break;
+					case IOPC_TM_EDGE:
+						seq_printf(s, "(Edges)");	break;
+				}
+			}
+			else
+				seq_printf(s, "GPIO\t");
+		}
+		else if (i <= KS8695_GPIO_5) {
+			if (ctrl & enable[i])
+				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
+			else
+				seq_printf(s, "GPIO\t");
+		}
+		else
+			seq_printf(s, "GPIO\t");
+
+		seq_printf(s, "\t");
+
+		seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
+	}
+	return 0;
+}
+
+static int ks8695_gpio_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ks8695_gpio_show, NULL);
+}
+
+static const struct file_operations ks8695_gpio_operations = {
+	.open		= ks8695_gpio_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init ks8695_gpio_debugfs_init(void)
+{
+	/* /sys/kernel/debug/ks8695_gpio */
+	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
+	return 0;
+}
+postcore_initcall(ks8695_gpio_debugfs_init);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-langwell.c linux-libre-3.2-gnu1/drivers/gpio/gpio-langwell.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-langwell.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-langwell.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@ enum GPIO_REG {
 	GRER,		/* rising edge detect */
 	GFER,		/* falling edge detect */
 	GEDR,		/* edge detect result */
+	GAFR,		/* alt function */
 };
 
 struct lnw_gpio {
@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpi
 	return ptr;
 }
 
+static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
+				   enum GPIO_REG reg_type)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	unsigned nreg = chip->ngpio / 32;
+	u8 reg = offset / 16;
+	void __iomem *ptr;
+
+	ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+	return ptr;
+}
+
+static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
+	u32 value = readl(gafr);
+	int shift = (offset % 16) << 1, af = (value >> shift) & 3;
+
+	if (af) {
+		value &= ~(3 << shift);
+		writel(value, gafr);
+	}
+	return 0;
+}
+
 static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(stru
 	lnw->reg_base = base;
 	lnw->irq_base = irq_base;
 	lnw->chip.label = dev_name(&pdev->dev);
+	lnw->chip.request = lnw_gpio_request;
 	lnw->chip.direction_input = lnw_gpio_direction_input;
 	lnw->chip.direction_output = lnw_gpio_direction_output;
 	lnw->chip.get = lnw_gpio_get;
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-lpc32xx.c linux-libre-3.2-gnu1/drivers/gpio/gpio-lpc32xx.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-lpc32xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-lpc32xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,446 @@
+/*
+ * arch/arm/mach-lpc32xx/gpiolib.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/gpio-lpc32xx.h>
+
+#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
+#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
+#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
+#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
+#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
+#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
+#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
+#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
+#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
+#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
+#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
+#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
+#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
+#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
+#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
+#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
+#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
+#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
+#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
+#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
+#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
+#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
+#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
+#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
+#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
+#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
+#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
+
+#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
+#define GPO3_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
+#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
+#define GPIO3_PIN_IN_SEL(x, y)			((x) >> GPIO3_PIN_IN_SHIFT(y))
+#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
+#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
+
+struct gpio_regs {
+	void __iomem *inp_state;
+	void __iomem *outp_set;
+	void __iomem *outp_clr;
+	void __iomem *dir_set;
+	void __iomem *dir_clr;
+};
+
+/*
+ * GPIO names
+ */
+static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
+	"p0.0", "p0.1", "p0.2", "p0.3",
+	"p0.4", "p0.5", "p0.6", "p0.7"
+};
+
+static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
+	"p1.0", "p1.1", "p1.2", "p1.3",
+	"p1.4", "p1.5", "p1.6", "p1.7",
+	"p1.8", "p1.9", "p1.10", "p1.11",
+	"p1.12", "p1.13", "p1.14", "p1.15",
+	"p1.16", "p1.17", "p1.18", "p1.19",
+	"p1.20", "p1.21", "p1.22", "p1.23",
+};
+
+static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
+	"p2.0", "p2.1", "p2.2", "p2.3",
+	"p2.4", "p2.5", "p2.6", "p2.7",
+	"p2.8", "p2.9", "p2.10", "p2.11",
+	"p2.12"
+};
+
+static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
+	"gpi000", "gpio01", "gpio02", "gpio03",
+	"gpio04", "gpio05"
+};
+
+static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
+	"gpi00", "gpi01", "gpi02", "gpi03",
+	"gpi04", "gpi05", "gpi06", "gpi07",
+	"gpi08", "gpi09",  NULL,    NULL,
+	 NULL,    NULL,    NULL,   "gpi15",
+	"gpi16", "gpi17", "gpi18", "gpi19",
+	"gpi20", "gpi21", "gpi22", "gpi23",
+	"gpi24", "gpi25", "gpi26", "gpi27"
+};
+
+static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
+	"gpo00", "gpo01", "gpo02", "gpo03",
+	"gpo04", "gpo05", "gpo06", "gpo07",
+	"gpo08", "gpo09", "gpo10", "gpo11",
+	"gpo12", "gpo13", "gpo14", "gpo15",
+	"gpo16", "gpo17", "gpo18", "gpo19",
+	"gpo20", "gpo21", "gpo22", "gpo23"
+};
+
+static struct gpio_regs gpio_grp_regs_p0 = {
+	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p1 = {
+	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p2 = {
+	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p3 = {
+	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+struct lpc32xx_gpio_chip {
+	struct gpio_chip	chip;
+	struct gpio_regs	*gpio_grp;
+};
+
+static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
+	struct gpio_chip *gpc)
+{
+	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
+}
+
+static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	if (input)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_clr);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (input)
+		__raw_writel(u, group->gpio_grp->dir_clr);
+	else
+		__raw_writel(u, group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_clr);
+}
+
+static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (high)
+		__raw_writel(u, group->gpio_grp->outp_set);
+	else
+		__raw_writel(u, group->gpio_grp->outp_clr);
+}
+
+static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
+}
+
+static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
+		pin);
+}
+
+static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	int state = __raw_readl(group->gpio_grp->inp_state);
+
+	/*
+	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
+	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
+	 */
+	return GPIO3_PIN_IN_SEL(state, pin);
+}
+
+static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
+}
+
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
+	unsigned pin)
+{
+	return 0;
+}
+
+static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p012(group, pin);
+}
+
+static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p3(group, pin);
+}
+
+static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpi_state_p3(group, pin);
+}
+
+static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	return 0;
+}
+
+static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p012(group, pin, value);
+}
+
+static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p3(group, pin, value);
+}
+
+static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpo_level_p3(group, pin, value);
+}
+
+static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	if (pin < chip->ngpio)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
+	{
+		.chip = {
+			.label			= "gpio_p0",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P0_GRP,
+			.ngpio			= LPC32XX_GPIO_P0_MAX,
+			.names			= gpio_p0_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p0,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p1",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P1_GRP,
+			.ngpio			= LPC32XX_GPIO_P1_MAX,
+			.names			= gpio_p1_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p1,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p2",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P2_GRP,
+			.ngpio			= LPC32XX_GPIO_P2_MAX,
+			.names			= gpio_p2_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p2,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p3",
+			.direction_input	= lpc32xx_gpio_dir_input_p3,
+			.get			= lpc32xx_gpio_get_value_p3,
+			.direction_output	= lpc32xx_gpio_dir_output_p3,
+			.set			= lpc32xx_gpio_set_value_p3,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P3_GRP,
+			.ngpio			= LPC32XX_GPIO_P3_MAX,
+			.names			= gpio_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpi_p3",
+			.direction_input	= lpc32xx_gpio_dir_in_always,
+			.get			= lpc32xx_gpi_get_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPI_P3_GRP,
+			.ngpio			= LPC32XX_GPI_P3_MAX,
+			.names			= gpi_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpo_p3",
+			.direction_output	= lpc32xx_gpio_dir_out_always,
+			.set			= lpc32xx_gpo_set_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPO_P3_GRP,
+			.ngpio			= LPC32XX_GPO_P3_MAX,
+			.names			= gpo_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+};
+
+void __init lpc32xx_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
+		gpiochip_add(&lpc32xx_gpiochip[i].chip);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mc33880.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mc33880.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mc33880.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mc33880.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/spi/mc33880.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "mc33880"
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mcp23s08.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mcp23s08.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mcp23s08.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mcp23s08.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-ml-ioh.c linux-libre-3.2-gnu1/drivers/gpio/gpio-ml-ioh.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-ml-ioh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-ml-ioh.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,22 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#define IOH_EDGE_FALLING	0
+#define IOH_EDGE_RISING		BIT(0)
+#define IOH_LEVEL_L		BIT(1)
+#define IOH_LEVEL_H		(BIT(0) | BIT(1))
+#define IOH_EDGE_BOTH		BIT(2)
+#define IOH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
+
+#define IOH_IRQ_BASE		0
 
 #define PCI_VENDOR_ID_ROHM             0x10DB
 
@@ -46,12 +58,22 @@ struct ioh_regs {
 
 /**
  * struct ioh_gpio_reg_data - The register store data.
+ * @ien_reg	To store contents of interrupt enable register.
+ * @imask_reg:	To store contents of interrupt mask regist
  * @po_reg:	To store contents of PO register.
  * @pm_reg:	To store contents of PM register.
+ * @im0_reg:	To store contents of interrupt mode regist0
+ * @im1_reg:	To store contents of interrupt mode regist1
+ * @use_sel_reg: To store contents of GPIO_USE_SEL0~3
  */
 struct ioh_gpio_reg_data {
+	u32 ien_reg;
+	u32 imask_reg;
 	u32 po_reg;
 	u32 pm_reg;
+	u32 im0_reg;
+	u32 im1_reg;
+	u32 use_sel_reg;
 };
 
 /**
@@ -62,7 +84,11 @@ struct ioh_gpio_reg_data {
  * @gpio:			Data for GPIO infrastructure.
  * @ioh_gpio_reg:		Memory mapped Register data is saved here
  *				when suspend.
+ * @gpio_use_sel:		Save GPIO_USE_SEL1~4 register for PM
  * @ch:				Indicate GPIO channel
+ * @irq_base:		Save base of IRQ number for interrupt
+ * @spinlock:		Used for register access protection in
+ *				interrupt context ioh_irq_type and PM;
  */
 struct ioh_gpio {
 	void __iomem *base;
@@ -70,8 +96,11 @@ struct ioh_gpio {
 	struct device *dev;
 	struct gpio_chip gpio;
 	struct ioh_gpio_reg_data ioh_gpio_reg;
+	u32 gpio_use_sel;
 	struct mutex lock;
 	int ch;
+	int irq_base;
+	spinlock_t spinlock;
 };
 
 static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -145,8 +174,25 @@ static int ioh_gpio_direction_input(stru
  */
 static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
 {
-	chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
-	chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+	int i;
+
+	for (i = 0; i < 8; i ++, chip++) {
+		chip->ioh_gpio_reg.po_reg =
+					ioread32(&chip->reg->regs[chip->ch].po);
+		chip->ioh_gpio_reg.pm_reg =
+					ioread32(&chip->reg->regs[chip->ch].pm);
+		chip->ioh_gpio_reg.ien_reg =
+				       ioread32(&chip->reg->regs[chip->ch].ien);
+		chip->ioh_gpio_reg.imask_reg =
+				     ioread32(&chip->reg->regs[chip->ch].imask);
+		chip->ioh_gpio_reg.im0_reg =
+				      ioread32(&chip->reg->regs[chip->ch].im_0);
+		chip->ioh_gpio_reg.im1_reg =
+				      ioread32(&chip->reg->regs[chip->ch].im_1);
+		if (i < 4)
+			chip->ioh_gpio_reg.use_sel_reg =
+					   ioread32(&chip->reg->ioh_sel_reg[i]);
+	}
 }
 
 /*
@@ -154,13 +200,34 @@ static void ioh_gpio_save_reg_conf(struc
  */
 static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
 {
-	/* to store contents of PO register */
-	iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
-	/* to store contents of PM register */
-	iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+	int i;
+
+	for (i = 0; i < 8; i ++, chip++) {
+		iowrite32(chip->ioh_gpio_reg.po_reg,
+			  &chip->reg->regs[chip->ch].po);
+		iowrite32(chip->ioh_gpio_reg.pm_reg,
+			  &chip->reg->regs[chip->ch].pm);
+		iowrite32(chip->ioh_gpio_reg.ien_reg,
+			  &chip->reg->regs[chip->ch].ien);
+		iowrite32(chip->ioh_gpio_reg.imask_reg,
+			  &chip->reg->regs[chip->ch].imask);
+		iowrite32(chip->ioh_gpio_reg.im0_reg,
+			  &chip->reg->regs[chip->ch].im_0);
+		iowrite32(chip->ioh_gpio_reg.im1_reg,
+			  &chip->reg->regs[chip->ch].im_1);
+		if (i < 4)
+			iowrite32(chip->ioh_gpio_reg.use_sel_reg,
+				  &chip->reg->ioh_sel_reg[i]);
+	}
 }
 #endif
 
+static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+	return chip->irq_base + offset;
+}
+
 static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
 {
 	struct gpio_chip *gpio = &chip->gpio;
@@ -175,16 +242,178 @@ static void ioh_gpio_setup(struct ioh_gp
 	gpio->base = -1;
 	gpio->ngpio = num_port;
 	gpio->can_sleep = 0;
+	gpio->to_irq = ioh_gpio_to_irq;
+}
+
+static int ioh_irq_type(struct irq_data *d, unsigned int type)
+{
+	u32 im;
+	u32 *im_reg;
+	u32 ien;
+	u32 im_pos;
+	int ch;
+	unsigned long flags;
+	u32 val;
+	int irq = d->irq;
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	ch = irq - chip->irq_base;
+	if (irq <= chip->irq_base + 7) {
+		im_reg = &chip->reg->regs[chip->ch].im_0;
+		im_pos = ch;
+	} else {
+		im_reg = &chip->reg->regs[chip->ch].im_1;
+		im_pos = ch - 8;
+	}
+	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
+		__func__, irq, type, ch, im_pos, type);
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		val = IOH_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		val = IOH_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = IOH_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		val = IOH_LEVEL_H;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		val = IOH_LEVEL_L;
+		break;
+	case IRQ_TYPE_PROBE:
+		goto end;
+	default:
+		dev_warn(chip->dev, "%s: unknown type(%dd)",
+			__func__, type);
+		goto end;
+	}
+
+	/* Set interrupt mode */
+	im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
+	iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+	/* iclr */
+	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
+
+	/* IMASKCLR */
+	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
+
+	/* Enable interrupt */
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
+end:
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+
+	return 0;
+}
+
+static void ioh_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base),
+		  &chip->reg->regs[chip->ch].imaskclr);
+}
+
+static void ioh_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base),
+		  &chip->reg->regs[chip->ch].imask);
+}
+
+static void ioh_irq_disable(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+	unsigned long flags;
+	u32 ien;
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	ien &= ~(1 << (d->irq - chip->irq_base));
+	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+}
+
+static void ioh_irq_enable(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+	unsigned long flags;
+	u32 ien;
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	ien |= 1 << (d->irq - chip->irq_base);
+	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+}
+
+static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
+{
+	struct ioh_gpio *chip = dev_id;
+	u32 reg_val;
+	int i, j;
+	int ret = IRQ_NONE;
+
+	for (i = 0; i < 8; i++, chip++) {
+		reg_val = ioread32(&chip->reg->regs[i].istatus);
+		for (j = 0; j < num_ports[i]; j++) {
+			if (reg_val & BIT(j)) {
+				dev_dbg(chip->dev,
+					"%s:[%d]:irq=%d status=0x%x\n",
+					__func__, j, irq, reg_val);
+				iowrite32(BIT(j),
+					  &chip->reg->regs[chip->ch].iclr);
+				generic_handle_irq(chip->irq_base + j);
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
+	return ret;
+}
+
+static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+				unsigned int irq_start, unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
+				    handle_simple_irq);
+	gc->private = chip;
+	ct = gc->chip_types;
+
+	ct->chip.irq_mask = ioh_irq_mask;
+	ct->chip.irq_unmask = ioh_irq_unmask;
+	ct->chip.irq_set_type = ioh_irq_type;
+	ct->chip.irq_disable = ioh_irq_disable;
+	ct->chip.irq_enable = ioh_irq_enable;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	int ret;
-	int i;
+	int i, j;
 	struct ioh_gpio *chip;
 	void __iomem *base;
 	void __iomem *chip_save;
+	int irq_base;
 
 	ret = pci_enable_device(pdev);
 	if (ret) {
@@ -228,10 +457,41 @@ static int __devinit ioh_gpio_probe(stru
 	}
 
 	chip = chip_save;
+	for (j = 0; j < 8; j++, chip++) {
+		irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
+					   NUMA_NO_NODE);
+		if (irq_base < 0) {
+			dev_warn(&pdev->dev,
+				"ml_ioh_gpio: Failed to get IRQ base num\n");
+			chip->irq_base = -1;
+			goto err_irq_alloc_descs;
+		}
+		chip->irq_base = irq_base;
+		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
+	}
+
+	chip = chip_save;
+	ret = request_irq(pdev->irq, ioh_gpio_handler,
+			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+
 	pci_set_drvdata(pdev, chip);
 
 	return 0;
 
+err_request_irq:
+	chip = chip_save;
+err_irq_alloc_descs:
+	while (--j >= 0) {
+		chip--;
+		irq_free_descs(chip->irq_base, num_ports[j]);
+	}
+
+	chip = chip_save;
 err_gpiochip_add:
 	while (--i >= 0) {
 		chip--;
@@ -264,7 +524,11 @@ static void __devexit ioh_gpio_remove(st
 	void __iomem *chip_save;
 
 	chip_save = chip;
+
+	free_irq(pdev->irq, chip);
+
 	for (i = 0; i < 8; i++, chip++) {
+		irq_free_descs(chip->irq_base, num_ports[i]);
 		err = gpiochip_remove(&chip->gpio);
 		if (err)
 			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -282,9 +546,11 @@ static int ioh_gpio_suspend(struct pci_d
 {
 	s32 ret;
 	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	ioh_gpio_save_reg_conf(chip);
-	ioh_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	ret = pci_save_state(pdev);
 	if (ret) {
@@ -304,6 +570,7 @@ static int ioh_gpio_resume(struct pci_de
 {
 	s32 ret;
 	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
 	ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -315,9 +582,11 @@ static int ioh_gpio_resume(struct pci_de
 	}
 	pci_restore_state(pdev);
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	iowrite32(0x01, &chip->reg->srst);
 	iowrite32(0x00, &chip->reg->srst);
 	ioh_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mpc5200.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mpc5200.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mpc5200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mpc5200.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/of_gpio.h>
 #include <linux/io.h>
 #include <linux/of_platform.h>
+#include <linux/module.h>
 
 #include <asm/gpio.h>
 #include <asm/mpc52xx.h>
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mpc8xxx.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mpc8xxx.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mpc8xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mpc8xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,406 @@
+/*
+ * GPIOs on MPC512x/8349/8572/8610 and compatible
+ *
+ * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+
+#define MPC8XXX_GPIO_PINS	32
+
+#define GPIO_DIR		0x00
+#define GPIO_ODR		0x04
+#define GPIO_DAT		0x08
+#define GPIO_IER		0x0c
+#define GPIO_IMR		0x10
+#define GPIO_ICR		0x14
+#define GPIO_ICR2		0x18
+
+struct mpc8xxx_gpio_chip {
+	struct of_mm_gpio_chip mm_gc;
+	spinlock_t lock;
+
+	/*
+	 * shadowed data register to be able to clear/set output pins in
+	 * open drain mode safely
+	 */
+	u32 data;
+	struct irq_host *irq;
+	void *of_dev_id_data;
+};
+
+static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
+{
+	return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
+}
+
+static inline struct mpc8xxx_gpio_chip *
+to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
+{
+	return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
+}
+
+static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
+}
+
+/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
+ * defined as output cannot be determined by reading GPDAT register,
+ * so we use shadow data register instead. The status of input pins
+ * is determined by reading GPDAT register.
+ */
+static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	u32 val;
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+
+	return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+}
+
+static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+
+	return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
+}
+
+static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	if (val)
+		mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
+	else
+		mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
+
+	out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+	return 0;
+}
+
+static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	mpc8xxx_gpio_set(gc, gpio, val);
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+	return 0;
+}
+
+static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	/* GPIO 28..31 are input only on MPC5121 */
+	if (gpio >= 28)
+		return -EINVAL;
+
+	return mpc8xxx_gpio_dir_out(gc, gpio, val);
+}
+
+static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
+		return irq_create_mapping(mpc8xxx_gc->irq, offset);
+	else
+		return -ENXIO;
+}
+
+static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned int mask;
+
+	mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
+	if (mask)
+		generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
+						     32 - ffs(mask)));
+	chip->irq_eoi(&desc->irq_data);
+}
+
+static void mpc8xxx_irq_unmask(struct irq_data *d)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static void mpc8xxx_irq_mask(struct irq_data *d)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static void mpc8xxx_irq_ack(struct irq_data *d)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+
+	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+}
+
+static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned long flags;
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_FALLING:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		setbits32(mm->regs + GPIO_ICR,
+			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrbits32(mm->regs + GPIO_ICR,
+			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned long gpio = irqd_to_hwirq(d);
+	void __iomem *reg;
+	unsigned int shift;
+	unsigned long flags;
+
+	if (gpio < 16) {
+		reg = mm->regs + GPIO_ICR;
+		shift = (15 - gpio) * 2;
+	} else {
+		reg = mm->regs + GPIO_ICR2;
+		shift = (15 - (gpio % 16)) * 2;
+	}
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_LEVEL_LOW:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrsetbits_be32(reg, 3 << shift, 2 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_LEVEL_HIGH:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrsetbits_be32(reg, 3 << shift, 1 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrbits32(reg, 3 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct irq_chip mpc8xxx_irq_chip = {
+	.name		= "mpc8xxx-gpio",
+	.irq_unmask	= mpc8xxx_irq_unmask,
+	.irq_mask	= mpc8xxx_irq_mask,
+	.irq_ack	= mpc8xxx_irq_ack,
+	.irq_set_type	= mpc8xxx_irq_set_type,
+};
+
+static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
+
+	if (mpc8xxx_gc->of_dev_id_data)
+		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
+
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
+				  const u32 *intspec, unsigned int intsize,
+				  irq_hw_number_t *out_hwirq,
+				  unsigned int *out_flags)
+
+{
+	/* interrupt sense values coming from the device tree equal either
+	 * EDGE_FALLING or EDGE_BOTH
+	 */
+	*out_hwirq = intspec[0];
+	*out_flags = intspec[1];
+
+	return 0;
+}
+
+static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
+	.map	= mpc8xxx_gpio_irq_map,
+	.xlate	= mpc8xxx_gpio_irq_xlate,
+};
+
+static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
+	{ .compatible = "fsl,mpc8349-gpio", },
+	{ .compatible = "fsl,mpc8572-gpio", },
+	{ .compatible = "fsl,mpc8610-gpio", },
+	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+	{ .compatible = "fsl,pq3-gpio",     },
+	{ .compatible = "fsl,qoriq-gpio",   },
+	{}
+};
+
+static void __init mpc8xxx_add_controller(struct device_node *np)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc;
+	struct of_mm_gpio_chip *mm_gc;
+	struct gpio_chip *gc;
+	const struct of_device_id *id;
+	unsigned hwirq;
+	int ret;
+
+	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
+	if (!mpc8xxx_gc) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	spin_lock_init(&mpc8xxx_gc->lock);
+
+	mm_gc = &mpc8xxx_gc->mm_gc;
+	gc = &mm_gc->gc;
+
+	mm_gc->save_regs = mpc8xxx_gpio_save_regs;
+	gc->ngpio = MPC8XXX_GPIO_PINS;
+	gc->direction_input = mpc8xxx_gpio_dir_in;
+	gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
+		mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
+	gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
+		mpc8572_gpio_get : mpc8xxx_gpio_get;
+	gc->set = mpc8xxx_gpio_set;
+	gc->to_irq = mpc8xxx_gpio_to_irq;
+
+	ret = of_mm_gpiochip_add(np, mm_gc);
+	if (ret)
+		goto err;
+
+	hwirq = irq_of_parse_and_map(np, 0);
+	if (hwirq == NO_IRQ)
+		goto skip_irq;
+
+	mpc8xxx_gc->irq =
+		irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
+			       &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
+	if (!mpc8xxx_gc->irq)
+		goto skip_irq;
+
+	id = of_match_node(mpc8xxx_gpio_ids, np);
+	if (id)
+		mpc8xxx_gc->of_dev_id_data = id->data;
+
+	mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
+
+	/* ack and mask all irqs */
+	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
+	out_be32(mm_gc->regs + GPIO_IMR, 0);
+
+	irq_set_handler_data(hwirq, mpc8xxx_gc);
+	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
+
+skip_irq:
+	return;
+
+err:
+	pr_err("%s: registration failed with status %d\n",
+	       np->full_name, ret);
+	kfree(mpc8xxx_gc);
+
+	return;
+}
+
+static int __init mpc8xxx_add_gpiochips(void)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, mpc8xxx_gpio_ids)
+		mpc8xxx_add_controller(np);
+
+	return 0;
+}
+arch_initcall(mpc8xxx_add_gpiochips);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mxc.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mxc.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mxc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mxc.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,11 @@
 #include <linux/basic_mmio_gpio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 #include <asm-generic/bug.h>
+#include <asm/mach/irq.h>
+
+#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
 
 enum mxc_gpio_hwtype {
 	IMX1_GPIO,	/* runs on i.mx1 */
@@ -232,10 +236,15 @@ static void mx3_gpio_irq_handler(u32 irq
 {
 	u32 irq_stat;
 	struct mxc_gpio_port *port = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chained_irq_enter(chip, desc);
 
 	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
 
 	mxc_gpio_irq_handler(port, irq_stat);
+
+	chained_irq_exit(chip, desc);
 }
 
 /* MX2 has one interrupt *for all* gpio ports */
@@ -337,6 +346,15 @@ static void __devinit mxc_gpio_get_hw(st
 	mxc_gpio_hwtype = hwtype;
 }
 
+static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	struct mxc_gpio_port *port =
+		container_of(bgc, struct mxc_gpio_port, bgc);
+
+	return port->virtual_irq_start + offset;
+}
+
 static int __devinit mxc_gpio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -403,6 +421,7 @@ static int __devinit mxc_gpio_probe(stru
 	if (err)
 		goto out_iounmap;
 
+	port->bgc.gc.to_irq = mxc_gpio_to_irq;
 	port->bgc.gc.base = pdev->id * 32;
 	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
 	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-mxs.c linux-libre-3.2-gnu1/drivers/gpio/gpio-mxs.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-mxs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-mxs.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/basic_mmio_gpio.h>
+#include <linux/module.h>
 #include <mach/mxs.h>
 
 #define MXS_SET		0x4
@@ -49,6 +50,8 @@
 #define GPIO_INT_LEV_MASK	(1 << 0)
 #define GPIO_INT_POL_MASK	(1 << 1)
 
+#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
+
 struct mxs_gpio_port {
 	void __iomem *base;
 	int id;
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-nomadik.c linux-libre-3.2-gnu1/drivers/gpio/gpio-nomadik.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-nomadik.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-nomadik.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,9 @@
 #include <asm/mach/irq.h>
 
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
@@ -58,7 +59,6 @@ struct nmk_gpio_chip {
 	u32 rwimsc;
 	u32 fwimsc;
 	u32 slpm;
-	u32 enabled;
 	u32 pull_up;
 };
 
@@ -276,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(un
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
 		writel(temp, chip->addr + NMK_GPIO_SLPC);
 	}
@@ -292,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore
 			break;
 
 		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -336,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *
 			break;
 		}
 
+		clk_enable(nmk_chip->clk);
 		spin_lock(&nmk_chip->lock);
 		__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
 				 cfgs[i], sleep, glitch ? slpm : NULL);
 		spin_unlock(&nmk_chip->lock);
+		clk_disable(nmk_chip->clk);
 	}
 
 	if (glitch)
@@ -424,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
@@ -431,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -457,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 	__nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -483,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 	__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -502,9 +514,13 @@ int nmk_gpio_get_mode(int gpio)
 
 	bit = 1 << (gpio - nmk_chip->chip.base);
 
+	clk_enable(nmk_chip->clk);
+
 	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
 	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
 
+	clk_disable(nmk_chip->clk);
+
 	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
 }
 EXPORT_SYMBOL(nmk_gpio_get_mode);
@@ -525,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return;
+
+	clk_enable(nmk_chip->clk);
 	writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+	clk_disable(nmk_chip->clk);
 }
 
 enum nmk_gpio_irq_type {
@@ -586,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struc
 	if (!nmk_chip)
 		return -EINVAL;
 
-	if (enable)
-		nmk_chip->enabled |= bitmask;
-	else
-		nmk_chip->enabled &= ~bitmask;
-
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
@@ -601,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struc
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -628,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct
 		return -EINVAL;
 	bitmask = nmk_gpio_get_bitmask(gpio);
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
-	if (!(nmk_chip->enabled & bitmask))
+	if (irqd_irq_disabled(d))
 		__nmk_gpio_set_wake(nmk_chip, gpio, on);
 
 	if (on)
@@ -641,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
 
 static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	bool enabled, wake = irqd_is_wakeup_set(d);
+	bool enabled = !irqd_irq_disabled(d);
+	bool wake = irqd_is_wakeup_set(d);
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
@@ -664,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct
 	if (type & IRQ_TYPE_LEVEL_LOW)
 		return -EINVAL;
 
-	enabled = nmk_chip->enabled & bitmask;
-
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 
 	if (enabled)
@@ -689,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
 
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
 
+static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	clk_enable(nmk_chip->clk);
+	nmk_gpio_irq_unmask(d);
+	return 0;
+}
+
+static void nmk_gpio_irq_shutdown(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	nmk_gpio_irq_mask(d);
+	clk_disable(nmk_chip->clk);
+}
+
 static struct irq_chip nmk_gpio_irq_chip = {
 	.name		= "Nomadik-GPIO",
 	.irq_ack	= nmk_gpio_irq_ack,
@@ -700,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip
 	.irq_unmask	= nmk_gpio_irq_unmask,
 	.irq_set_type	= nmk_gpio_irq_set_type,
 	.irq_set_wake	= nmk_gpio_irq_set_wake,
+	.irq_startup	= nmk_gpio_irq_startup,
+	.irq_shutdown	= nmk_gpio_irq_shutdown,
 };
 
 static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
@@ -726,7 +764,11 @@ static void __nmk_gpio_irq_handler(unsig
 static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
-	u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+	u32 status;
+
+	clk_enable(nmk_chip->clk);
+	status = readl(nmk_chip->addr + NMK_GPIO_IS);
+	clk_disable(nmk_chip->clk);
 
 	__nmk_gpio_irq_handler(irq, desc, status);
 }
@@ -772,7 +814,12 @@ static int nmk_gpio_make_input(struct gp
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+
+	clk_disable(nmk_chip->clk);
+
 	return 0;
 }
 
@@ -781,8 +828,15 @@ static int nmk_gpio_get_input(struct gpi
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 	u32 bit = 1 << offset;
+	int value;
 
-	return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+	clk_enable(nmk_chip->clk);
+
+	value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+
+	clk_disable(nmk_chip->clk);
+
+	return value;
 }
 
 static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
@@ -791,7 +845,11 @@ static void nmk_gpio_set_output(struct g
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	__nmk_gpio_set_output(nmk_chip, offset, val);
+
+	clk_disable(nmk_chip->clk);
 }
 
 static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -800,8 +858,12 @@ static int nmk_gpio_make_output(struct g
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	__nmk_gpio_make_output(nmk_chip, offset, val);
 
+	clk_disable(nmk_chip->clk);
+
 	return 0;
 }
 
@@ -832,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq
 		[NMK_GPIO_ALT_C]	= "altC",
 	};
 
+	clk_enable(nmk_chip->clk);
+
 	for (i = 0; i < chip->ngpio; i++, gpio++) {
 		const char *label = gpiochip_is_requested(chip, i);
 		bool pull;
@@ -876,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq
 
 		seq_printf(s, "\n");
 	}
+
+	clk_disable(nmk_chip->clk);
 }
 
 #else
@@ -893,6 +959,34 @@ static struct gpio_chip nmk_gpio_templat
 	.can_sleep		= 0,
 };
 
+void nmk_gpio_clocks_enable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_enable(chip->clk);
+	}
+}
+
+void nmk_gpio_clocks_disable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_disable(chip->clk);
+	}
+}
+
 /*
  * Called from the suspend/resume path to only keep the real wakeup interrupts
  * (those that have had set_irq_wake() called on them) as wakeup interrupts,
@@ -912,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void)
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
 		chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
 
@@ -926,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void)
 			/* 0 -> wakeup enable */
 			writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
 		}
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -939,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void)
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
 		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
 
 		if (chip->sleepmode)
 			writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -1010,8 +1112,6 @@ static int __devinit nmk_gpio_probe(stru
 		goto out_release;
 	}
 
-	clk_enable(clk);
-
 	nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
 	if (!nmk_chip) {
 		ret = -ENOMEM;
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-omap.c linux-libre-3.2-gnu1/drivers/gpio/gpio-omap.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-omap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-omap.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <asm/mach/irq.h>
 
 struct gpio_bank {
@@ -148,13 +148,17 @@ static int _get_gpio_dataout(struct gpio
 	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
 }
 
-#define MOD_REG_BIT(reg, bit_mask, set)	\
-do {	\
-	int l = __raw_readl(base + reg); \
-	if (set) l |= bit_mask; \
-	else l &= ~bit_mask; \
-	__raw_writel(l, base + reg); \
-} while(0)
+static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+{
+	int l = __raw_readl(base + reg);
+
+	if (set) 
+		l |= mask;
+	else
+		l &= ~mask;
+
+	__raw_writel(l, base + reg);
+}
 
 /**
  * _set_gpio_debounce - low level gpio debounce time
@@ -210,28 +214,28 @@ static inline void set_24xx_gpio_trigger
 	u32 gpio_bit = 1 << gpio;
 
 	if (cpu_is_omap44xx()) {
-		MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_LOW);
-		MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_HIGH);
-		MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_RISING);
-		MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_FALLING);
+		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_LOW);
+		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_HIGH);
+		_gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_RISING);
+		_gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_FALLING);
 	} else {
-		MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_LOW);
-		MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_HIGH);
-		MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_RISING);
-		MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_FALLING);
+		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_LOW);
+		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_HIGH);
+		_gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_RISING);
+		_gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_FALLING);
 	}
 	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
 		if (cpu_is_omap44xx()) {
-			MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
-				trigger != 0);
+			_gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit,
+				  trigger != 0);
 		} else {
 			/*
 			 * GPIO wakeup request can only be generated on edge
@@ -1086,6 +1090,11 @@ omap_mpuio_alloc_gc(struct gpio_bank *ba
 
 	gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
 				    handle_simple_irq);
+	if (!gc) {
+		dev_err(bank->dev, "Memory alloc failed for gc\n");
+		return;
+	}
+
 	ct = gc->chip_types;
 
 	/* NOTE: No ack required, reading IRQ status clears it. */
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-pca953x.c linux-libre-3.2-gnu1/drivers/gpio/gpio-pca953x.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-pca953x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-pca953x.c	2012-01-04 18:55:44.000000000 -0500
@@ -546,7 +546,7 @@ static void pca953x_irq_teardown(struct
  * Translate OpenFirmware node properties into platform_data
  * WARNING: This is DEPRECATED and will be removed eventually!
  */
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
 	struct device_node *node;
@@ -574,7 +574,7 @@ pca953x_get_alt_pdata(struct i2c_client
 		*invert = *val;
 }
 #else
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
 	*gpio_base = -1;
@@ -596,9 +596,6 @@ static int __devinit device_pca953x_init
 
 	/* set platform specific polarity inversion */
 	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-	if (ret)
-		goto out;
-	return 0;
 out:
 	return ret;
 }
@@ -640,7 +637,7 @@ static int __devinit pca953x_probe(struc
 	struct pca953x_platform_data *pdata;
 	struct pca953x_chip *chip;
 	int irq_base=0, invert=0;
-	int ret = 0;
+	int ret;
 
 	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
 	if (chip == NULL)
@@ -673,10 +670,10 @@ static int __devinit pca953x_probe(struc
 	pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
 
 	if (chip->chip_type == PCA953X_TYPE)
-		device_pca953x_init(chip, invert);
-	else if (chip->chip_type == PCA957X_TYPE)
-		device_pca957x_init(chip, invert);
+		ret = device_pca953x_init(chip, invert);
 	else
+		ret = device_pca957x_init(chip, invert);
+	if (ret)
 		goto out_failed;
 
 	ret = pca953x_irq_setup(chip, id, irq_base);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-pcf857x.c linux-libre-3.2-gnu1/drivers/gpio/gpio-pcf857x.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-pcf857x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-pcf857x.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/module.h>
 
 
 static const struct i2c_device_id pcf857x_id[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-pch.c linux-libre-3.2-gnu1/drivers/gpio/gpio-pch.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-pch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-pch.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,12 +14,21 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#define PCH_GPIO_ALL_PINS	0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS	12	/* Specifies number of GPIO PINS GPIO0-GPIO11 */
+#define PCH_EDGE_FALLING	0
+#define PCH_EDGE_RISING		BIT(0)
+#define PCH_LEVEL_L		BIT(1)
+#define PCH_LEVEL_H		(BIT(0) | BIT(1))
+#define PCH_EDGE_BOTH		BIT(2)
+#define PCH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
+
+#define PCH_IRQ_BASE		24
 
 struct pch_regs {
 	u32	ien;
@@ -33,18 +42,43 @@ struct pch_regs {
 	u32	pm;
 	u32	im0;
 	u32	im1;
-	u32	reserved[4];
+	u32	reserved[3];
+	u32	gpio_use_sel;
 	u32	reset;
 };
 
+enum pch_type_t {
+	INTEL_EG20T_PCH,
+	OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
+	OKISEMI_ML7223n_IOH  /* OKISEMI ML7223 IOH PCIe Bus-n */
+};
+
+/* Specifies number of GPIO PINS */
+static int gpio_pins[] = {
+	[INTEL_EG20T_PCH] = 12,
+	[OKISEMI_ML7223m_IOH] = 8,
+	[OKISEMI_ML7223n_IOH] = 8,
+};
+
 /**
  * struct pch_gpio_reg_data - The register store data.
+ * @ien_reg:	To store contents of IEN register.
+ * @imask_reg:	To store contents of IMASK register.
  * @po_reg:	To store contents of PO register.
  * @pm_reg:	To store contents of PM register.
+ * @im0_reg:	To store contents of IM0 register.
+ * @im1_reg:	To store contents of IM1 register.
+ * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
+ *		       (Only ML7223 Bus-n)
  */
 struct pch_gpio_reg_data {
+	u32 ien_reg;
+	u32 imask_reg;
 	u32 po_reg;
 	u32 pm_reg;
+	u32 im0_reg;
+	u32 im1_reg;
+	u32 gpio_use_sel_reg;
 };
 
 /**
@@ -55,6 +89,12 @@ struct pch_gpio_reg_data {
  * @gpio:			Data for GPIO infrastructure.
  * @pch_gpio_reg:		Memory mapped Register data is saved here
  *				when suspend.
+ * @lock:			Used for register access protection
+ * @irq_base:		Save base of IRQ number for interrupt
+ * @ioh:		IOH ID
+ * @spinlock:		Used for register access protection in
+ *				interrupt context pch_irq_mask,
+ *				pch_irq_unmask and pch_irq_type;
  */
 struct pch_gpio {
 	void __iomem *base;
@@ -63,6 +103,9 @@ struct pch_gpio {
 	struct gpio_chip gpio;
 	struct pch_gpio_reg_data pch_gpio_reg;
 	struct mutex lock;
+	int irq_base;
+	enum pch_type_t ioh;
+	spinlock_t spinlock;
 };
 
 static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
@@ -96,7 +139,7 @@ static int pch_gpio_direction_output(str
 	u32 reg_val;
 
 	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm |= (1 << nr);
 	iowrite32(pm, &chip->reg->pm);
 
@@ -118,7 +161,7 @@ static int pch_gpio_direction_input(stru
 	u32 pm;
 
 	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm &= ~(1 << nr);
 	iowrite32(pm, &chip->reg->pm);
 	mutex_unlock(&chip->lock);
@@ -131,8 +174,16 @@ static int pch_gpio_direction_input(stru
  */
 static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
 {
+	chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
+	chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
 	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
 	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+	chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
+	if (chip->ioh == INTEL_EG20T_PCH)
+		chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
+	if (chip->ioh == OKISEMI_ML7223n_IOH)
+		chip->pch_gpio_reg.gpio_use_sel_reg =\
+					    ioread32(&chip->reg->gpio_use_sel);
 }
 
 /*
@@ -140,10 +191,24 @@ static void pch_gpio_save_reg_conf(struc
  */
 static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
 {
+	iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
+	iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
 	/* to store contents of PO register */
 	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
 	/* to store contents of PM register */
 	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+	iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
+	if (chip->ioh == INTEL_EG20T_PCH)
+		iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
+	if (chip->ioh == OKISEMI_ML7223n_IOH)
+		iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
+			  &chip->reg->gpio_use_sel);
+}
+
+static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+	return chip->irq_base + offset;
 }
 
 static void pch_gpio_setup(struct pch_gpio *chip)
@@ -158,8 +223,132 @@ static void pch_gpio_setup(struct pch_gp
 	gpio->set = pch_gpio_set;
 	gpio->dbg_show = NULL;
 	gpio->base = -1;
-	gpio->ngpio = GPIO_NUM_PINS;
+	gpio->ngpio = gpio_pins[chip->ioh];
 	gpio->can_sleep = 0;
+	gpio->to_irq = pch_gpio_to_irq;
+}
+
+static int pch_irq_type(struct irq_data *d, unsigned int type)
+{
+	u32 im;
+	u32 *im_reg;
+	u32 ien;
+	u32 im_pos;
+	int ch;
+	unsigned long flags;
+	u32 val;
+	int irq = d->irq;
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	ch = irq - chip->irq_base;
+	if (irq <= chip->irq_base + 7) {
+		im_reg = &chip->reg->im0;
+		im_pos = ch;
+	} else {
+		im_reg = &chip->reg->im1;
+		im_pos = ch - 8;
+	}
+	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
+		__func__, irq, type, ch, im_pos);
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		val = PCH_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		val = PCH_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = PCH_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		val = PCH_LEVEL_H;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		val = PCH_LEVEL_L;
+		break;
+	case IRQ_TYPE_PROBE:
+		goto end;
+	default:
+		dev_warn(chip->dev, "%s: unknown type(%dd)",
+			__func__, type);
+		goto end;
+	}
+
+	/* Set interrupt mode */
+	im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
+	iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+	/* iclr */
+	iowrite32(BIT(ch), &chip->reg->iclr);
+
+	/* IMASKCLR */
+	iowrite32(BIT(ch), &chip->reg->imaskclr);
+
+	/* Enable interrupt */
+	ien = ioread32(&chip->reg->ien);
+	iowrite32(ien | BIT(ch), &chip->reg->ien);
+end:
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+
+	return 0;
+}
+
+static void pch_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
+}
+
+static void pch_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
+}
+
+static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
+{
+	struct pch_gpio *chip = dev_id;
+	u32 reg_val = ioread32(&chip->reg->istatus);
+	int i;
+	int ret = IRQ_NONE;
+
+	for (i = 0; i < gpio_pins[chip->ioh]; i++) {
+		if (reg_val & BIT(i)) {
+			dev_dbg(chip->dev, "%s:[%d]:irq=%d  status=0x%x\n",
+				__func__, i, irq, reg_val);
+			iowrite32(BIT(i), &chip->reg->iclr);
+			generic_handle_irq(chip->irq_base + i);
+			ret = IRQ_HANDLED;
+		}
+	}
+	return ret;
+}
+
+static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+				unsigned int irq_start, unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
+				    handle_simple_irq);
+	gc->private = chip;
+	ct = gc->chip_types;
+
+	ct->chip.irq_mask = pch_irq_mask;
+	ct->chip.irq_unmask = pch_irq_unmask;
+	ct->chip.irq_set_type = pch_irq_type;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@@ -167,6 +356,7 @@ static int __devinit pch_gpio_probe(stru
 {
 	s32 ret;
 	struct pch_gpio *chip;
+	int irq_base;
 
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
@@ -192,6 +382,13 @@ static int __devinit pch_gpio_probe(stru
 		goto err_iomap;
 	}
 
+	if (pdev->device == 0x8803)
+		chip->ioh = INTEL_EG20T_PCH;
+	else if (pdev->device == 0x8014)
+		chip->ioh = OKISEMI_ML7223m_IOH;
+	else if (pdev->device == 0x8043)
+		chip->ioh = OKISEMI_ML7223n_IOH;
+
 	chip->reg = chip->base;
 	pci_set_drvdata(pdev, chip);
 	mutex_init(&chip->lock);
@@ -202,8 +399,36 @@ static int __devinit pch_gpio_probe(stru
 		goto err_gpiochip_add;
 	}
 
+	irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
+	if (irq_base < 0) {
+		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
+		chip->irq_base = -1;
+		goto end;
+	}
+	chip->irq_base = irq_base;
+
+	ret = request_irq(pdev->irq, pch_gpio_handler,
+			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+
+	pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
+
+	/* Initialize interrupt ien register */
+	iowrite32(0, &chip->reg->ien);
+end:
 	return 0;
 
+err_request_irq:
+	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
+
+	ret = gpiochip_remove(&chip->gpio);
+	if (ret)
+		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+
 err_gpiochip_add:
 	pci_iounmap(pdev, chip->base);
 
@@ -224,6 +449,12 @@ static void __devexit pch_gpio_remove(st
 	int err;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
 
+	if (chip->irq_base != -1) {
+		free_irq(pdev->irq, chip);
+
+		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
+	}
+
 	err = gpiochip_remove(&chip->gpio);
 	if (err)
 		dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -239,9 +470,11 @@ static int pch_gpio_suspend(struct pci_d
 {
 	s32 ret;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pch_gpio_save_reg_conf(chip);
-	pch_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	ret = pci_save_state(pdev);
 	if (ret) {
@@ -261,6 +494,7 @@ static int pch_gpio_resume(struct pci_de
 {
 	s32 ret;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
 	ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -272,9 +506,11 @@ static int pch_gpio_resume(struct pci_de
 	}
 	pci_restore_state(pdev);
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	iowrite32(0x01, &chip->reg->reset);
 	iowrite32(0x00, &chip->reg->reset);
 	pch_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -287,6 +523,7 @@ static int pch_gpio_resume(struct pci_de
 static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-pl061.c linux-libre-3.2-gnu1/drivers/gpio/gpio-pl061.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-pl061.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-pl061.c	2012-01-04 18:55:44.000000000 -0500
@@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip
 {
 	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
 
-	if (chip->irq_base == (unsigned) -1)
+	if (chip->irq_base == NO_IRQ)
 		return -EINVAL;
 
 	return chip->irq_base + offset;
@@ -238,14 +238,22 @@ static int pl061_probe(struct amba_devic
 	int ret, irq, i;
 	static DECLARE_BITMAP(init_irq, NR_IRQS);
 
-	pdata = dev->dev.platform_data;
-	if (pdata == NULL)
-		return -ENODEV;
-
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
+	pdata = dev->dev.platform_data;
+	if (pdata) {
+		chip->gc.base = pdata->gpio_base;
+		chip->irq_base = pdata->irq_base;
+	} else if (dev->dev.of_node) {
+		chip->gc.base = -1;
+		chip->irq_base = NO_IRQ;
+	} else {
+		ret = -ENODEV;
+		goto free_mem;
+	}
+
 	if (!request_mem_region(dev->res.start,
 				resource_size(&dev->res), "pl061")) {
 		ret = -EBUSY;
@@ -267,14 +275,11 @@ static int pl061_probe(struct amba_devic
 	chip->gc.get = pl061_get_value;
 	chip->gc.set = pl061_set_value;
 	chip->gc.to_irq = pl061_to_irq;
-	chip->gc.base = pdata->gpio_base;
 	chip->gc.ngpio = PL061_GPIO_NR;
 	chip->gc.label = dev_name(&dev->dev);
 	chip->gc.dev = &dev->dev;
 	chip->gc.owner = THIS_MODULE;
 
-	chip->irq_base = pdata->irq_base;
-
 	ret = gpiochip_add(&chip->gc);
 	if (ret)
 		goto iounmap;
@@ -283,7 +288,7 @@ static int pl061_probe(struct amba_devic
 	 * irq_chip support
 	 */
 
-	if (chip->irq_base == (unsigned) -1)
+	if (chip->irq_base == NO_IRQ)
 		return 0;
 
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
@@ -307,11 +312,13 @@ static int pl061_probe(struct amba_devic
 	list_add(&chip->list, chip_list);
 
 	for (i = 0; i < PL061_GPIO_NR; i++) {
-		if (pdata->directions & (1 << i))
-			pl061_direction_output(&chip->gc, i,
-					pdata->values & (1 << i));
-		else
-			pl061_direction_input(&chip->gc, i);
+		if (pdata) {
+			if (pdata->directions & (1 << i))
+				pl061_direction_output(&chip->gc, i,
+						pdata->values & (1 << i));
+			else
+				pl061_direction_input(&chip->gc, i);
+		}
 
 		irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
 					 handle_simple_irq);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-plat-samsung.c linux-libre-3.2-gnu1/drivers/gpio/gpio-plat-samsung.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-plat-samsung.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-plat-samsung.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * SAMSUNG - GPIOlib support
- *
- * 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/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The samsung_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
-				      unsigned int offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-
-	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, base + GPIOCON_OFF);
-
-	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-	return 0;
-}
-
-static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
-				       unsigned int offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-	unsigned long dat;
-
-	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
-	con |= 0x1 << con_4bit_shift(offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + GPIODAT_OFF);
-	__raw_writel(con, base + GPIOCON_OFF);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
- */
-
-static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
-				       unsigned int offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-
-	if (offset > 7)
-		offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-	return 0;
-}
-
-static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
-					unsigned int offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long dat;
-	unsigned con_offset = offset;
-
-	if (con_offset > 7)
-		con_offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(con_offset));
-	con |= 0x1 << con_4bit_shift(con_offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + GPIODAT_OFF);
-	__raw_writel(con, regcon);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = samsung_gpiolib_4bit_input;
-	chip->chip.direction_output = samsung_gpiolib_4bit_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = samsung_gpiolib_4bit2_input;
-	chip->chip.direction_output = samsung_gpiolib_4bit2_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		samsung_gpiolib_add_4bit(chip);
-		s3c_gpiolib_add(chip);
-	}
-}
-
-void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-					    int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		samsung_gpiolib_add_4bit2(chip);
-		s3c_gpiolib_add(chip);
-	}
-}
-
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++)
-		s3c_gpiolib_add(chip);
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-pxa.c linux-libre-3.2-gnu1/drivers/gpio/gpio-pxa.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-pxa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-pxa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,338 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  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/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+#include <linux/slab.h>
+
+#include <mach/gpio-pxa.h>
+
+int pxa_last_gpio;
+
+struct pxa_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem	*regbase;
+	char label[10];
+
+	unsigned long	irq_mask;
+	unsigned long	irq_edge_rise;
+	unsigned long	irq_edge_fall;
+
+#ifdef CONFIG_PM
+	unsigned long	saved_gplr;
+	unsigned long	saved_gpdr;
+	unsigned long	saved_grer;
+	unsigned long	saved_gfer;
+#endif
+};
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = GPIO_BANK(i);
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+	uint32_t grer, gfer;
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+	grer |= c->irq_edge_rise & c->irq_mask;
+	gfer |= c->irq_edge_fall & c->irq_mask;
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = irq_to_gpio(d->irq);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_pxachip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (__gpio_is_occupied(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	update_edge_detect(c);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				generic_handle_irq(gpio_to_irq(gpio_base + n));
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(c);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.irq_ack	= pxa_ack_muxed_gpio,
+	.irq_mask	= pxa_mask_muxed_gpio,
+	.irq_unmask	= pxa_unmask_muxed_gpio,
+	.irq_set_type	= pxa_gpio_irq_type,
+};
+
+void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
+{
+	struct pxa_gpio_chip *c;
+	int gpio, irq;
+
+	pxa_last_gpio = end;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(end);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Install handler for GPIO>=2 edge detect interrupts */
+	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
+	pxa_muxed_gpio_chip.irq_set_wake = fn;
+}
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static void pxa_gpio_resume(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct syscore_ops pxa_gpio_syscore_ops = {
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-s5pc100.c linux-libre-3.2-gnu1/drivers/gpio/gpio-s5pc100.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-s5pc100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-s5pc100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,354 +0,0 @@
-/*
- * S5PC100 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- *  Copyright 2009 Samsung Electronics Co
- *  Kyungmin Park <kyungmin.park@samsung.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* S5PC100 GPIO bank summary:
- *
- * Bank	GPIOs	Style	INT Type
- * A0	8	4Bit	GPIO_INT0
- * A1	5	4Bit	GPIO_INT1
- * B	8	4Bit	GPIO_INT2
- * C	5	4Bit	GPIO_INT3
- * D	7	4Bit	GPIO_INT4
- * E0	8	4Bit	GPIO_INT5
- * E1	6	4Bit	GPIO_INT6
- * F0	8	4Bit	GPIO_INT7
- * F1	8	4Bit	GPIO_INT8
- * F2	8	4Bit	GPIO_INT9
- * F3	4	4Bit	GPIO_INT10
- * G0	8	4Bit	GPIO_INT11
- * G1	3	4Bit	GPIO_INT12
- * G2	7	4Bit	GPIO_INT13
- * G3	7	4Bit	GPIO_INT14
- * H0	8	4Bit	WKUP_INT
- * H1	8	4Bit	WKUP_INT
- * H2	8	4Bit	WKUP_INT
- * H3	8	4Bit	WKUP_INT
- * I	8	4Bit	GPIO_INT15
- * J0	8	4Bit	GPIO_INT16
- * J1	5	4Bit	GPIO_INT17
- * J2	8	4Bit	GPIO_INT18
- * J3	8	4Bit	GPIO_INT19
- * J4	4	4Bit	GPIO_INT20
- * K0	8	4Bit	None
- * K1	6	4Bit	None
- * K2	8	4Bit	None
- * K3	8	4Bit	None
- * L0	8	4Bit	None
- * L1	8	4Bit	None
- * L2	8	4Bit	None
- * L3	8	4Bit	None
- */
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_eint = {
-	.cfg_eint	= 0xf,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-/*
- * GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PC100_BANK_BASE(bank_nr)	(S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in S5PC100.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
-	{
-		.chip	= {
-			.base	= S5PC100_GPA0(0),
-			.ngpio	= S5PC100_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPA1(0),
-			.ngpio	= S5PC100_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPB(0),
-			.ngpio	= S5PC100_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPC(0),
-			.ngpio	= S5PC100_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPD(0),
-			.ngpio	= S5PC100_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE0(0),
-			.ngpio	= S5PC100_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE1(0),
-			.ngpio	= S5PC100_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF0(0),
-			.ngpio	= S5PC100_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF1(0),
-			.ngpio	= S5PC100_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF2(0),
-			.ngpio	= S5PC100_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF3(0),
-			.ngpio	= S5PC100_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG0(0),
-			.ngpio	= S5PC100_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG1(0),
-			.ngpio	= S5PC100_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG2(0),
-			.ngpio	= S5PC100_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG3(0),
-			.ngpio	= S5PC100_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPI(0),
-			.ngpio	= S5PC100_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ0(0),
-			.ngpio	= S5PC100_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ1(0),
-			.ngpio	= S5PC100_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ2(0),
-			.ngpio	= S5PC100_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ3(0),
-			.ngpio	= S5PC100_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ4(0),
-			.ngpio	= S5PC100_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK0(0),
-			.ngpio	= S5PC100_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK1(0),
-			.ngpio	= S5PC100_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK2(0),
-			.ngpio	= S5PC100_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK3(0),
-			.ngpio	= S5PC100_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL0(0),
-			.ngpio	= S5PC100_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL1(0),
-			.ngpio	= S5PC100_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL2(0),
-			.ngpio	= S5PC100_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL3(0),
-			.ngpio	= S5PC100_GPIO_L3_NR,
-			.label	= "GPL3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL4(0),
-			.ngpio	= S5PC100_GPIO_L4_NR,
-			.label	= "GPL4",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PC100_GPH0(0),
-			.ngpio	= S5PC100_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PC100_GPH1(0),
-			.ngpio	= S5PC100_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PC100_GPH2(0),
-			.ngpio	= S5PC100_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PC100_GPH3(0),
-			.ngpio	= S5PC100_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static __init int s5pc100_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
-	int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
-	int gpioint_group = 0;
-	int i;
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			chip->group = gpioint_group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5PC100_BANK_BASE(i);
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
-	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-	return 0;
-}
-core_initcall(s5pc100_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-s5pv210.c linux-libre-3.2-gnu1/drivers/gpio/gpio-s5pv210.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-s5pv210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-s5pv210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,287 +0,0 @@
-/*
- * S5PV210 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/map.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-/* GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PV210_BANK_BASE(bank_nr)	(S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in v210.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV210_GPA0(0),
-			.ngpio	= S5PV210_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPA1(0),
-			.ngpio	= S5PV210_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPB(0),
-			.ngpio	= S5PV210_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC0(0),
-			.ngpio	= S5PV210_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC1(0),
-			.ngpio	= S5PV210_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD0(0),
-			.ngpio	= S5PV210_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD1(0),
-			.ngpio	= S5PV210_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE0(0),
-			.ngpio	= S5PV210_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE1(0),
-			.ngpio	= S5PV210_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF0(0),
-			.ngpio	= S5PV210_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF1(0),
-			.ngpio	= S5PV210_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF2(0),
-			.ngpio	= S5PV210_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF3(0),
-			.ngpio	= S5PV210_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG0(0),
-			.ngpio	= S5PV210_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG1(0),
-			.ngpio	= S5PV210_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG2(0),
-			.ngpio	= S5PV210_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG3(0),
-			.ngpio	= S5PV210_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_GPI(0),
-			.ngpio	= S5PV210_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ0(0),
-			.ngpio	= S5PV210_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ1(0),
-			.ngpio	= S5PV210_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ2(0),
-			.ngpio	= S5PV210_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ3(0),
-			.ngpio	= S5PV210_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ4(0),
-			.ngpio	= S5PV210_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP01(0),
-			.ngpio	= S5PV210_GPIO_MP01_NR,
-			.label	= "MP01",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP02(0),
-			.ngpio	= S5PV210_GPIO_MP02_NR,
-			.label	= "MP02",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP03(0),
-			.ngpio	= S5PV210_GPIO_MP03_NR,
-			.label	= "MP03",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP04(0),
-			.ngpio	= S5PV210_GPIO_MP04_NR,
-			.label	= "MP04",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP05(0),
-			.ngpio	= S5PV210_GPIO_MP05_NR,
-			.label	= "MP05",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PV210_GPH0(0),
-			.ngpio	= S5PV210_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PV210_GPH1(0),
-			.ngpio	= S5PV210_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PV210_GPH2(0),
-			.ngpio	= S5PV210_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PV210_GPH3(0),
-			.ngpio	= S5PV210_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static __init int s5pv210_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
-	int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
-	int gpioint_group = 0;
-	int i = 0;
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			chip->group = gpioint_group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5PV210_BANK_BASE(i);
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
-	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-	return 0;
-}
-core_initcall(s5pv210_gpiolib_init);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-sa1100.c linux-libre-3.2-gnu1/drivers/gpio/gpio-sa1100.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-sa1100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-sa1100.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/arm/mach-sa1100/gpio.c
+ *
+ * Generic SA-1100 GPIO handling
+ *
+ * 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/gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <mach/hardware.h>
+
+static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return GPLR & GPIO_GPIO(offset);
+}
+
+static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (value)
+		GPSR = GPIO_GPIO(offset);
+	else
+		GPCR = GPIO_GPIO(offset);
+}
+
+static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	GPDR &= ~GPIO_GPIO(offset);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	sa1100_gpio_set(chip, offset, value);
+	GPDR |= GPIO_GPIO(offset);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static struct gpio_chip sa1100_gpio_chip = {
+	.label			= "gpio",
+	.direction_input	= sa1100_direction_input,
+	.direction_output	= sa1100_direction_output,
+	.set			= sa1100_gpio_set,
+	.get			= sa1100_gpio_get,
+	.base			= 0,
+	.ngpio			= GPIO_MAX + 1,
+};
+
+void __init sa1100_init_gpio(void)
+{
+	gpiochip_add(&sa1100_gpio_chip);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-samsung.c linux-libre-3.2-gnu1/drivers/gpio/gpio-samsung.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-samsung.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-samsung.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2712 @@
+/*
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * SAMSUNG - GPIOlib support
+ *
+ * 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/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-fns.h>
+#include <plat/pm.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup;
+
+	pup = __raw_readl(reg);
+	pup &= ~(3 << shift);
+	pup |= pull << shift;
+	__raw_writel(pup, reg);
+
+	return 0;
+}
+
+samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+						unsigned int off)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup = __raw_readl(reg);
+
+	pup >>= shift;
+	pup &= 0x3;
+
+	return (__force samsung_gpio_pull_t)pup;
+}
+
+int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+			 unsigned int off, samsung_gpio_pull_t pull)
+{
+	switch (pull) {
+	case S3C_GPIO_PULL_NONE:
+		pull = 0x01;
+		break;
+	case S3C_GPIO_PULL_UP:
+		pull = 0x00;
+		break;
+	case S3C_GPIO_PULL_DOWN:
+		pull = 0x02;
+		break;
+	}
+	return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
+					 unsigned int off)
+{
+	samsung_gpio_pull_t pull;
+
+	pull = samsung_gpio_getpull_updown(chip, off);
+
+	switch (pull) {
+	case 0x00:
+		pull = S3C_GPIO_PULL_UP;
+		break;
+	case 0x01:
+	case 0x03:
+		pull = S3C_GPIO_PULL_NONE;
+		break;
+	case 0x02:
+		pull = S3C_GPIO_PULL_DOWN;
+		break;
+	}
+
+	return pull;
+}
+
+static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
+				  unsigned int off, samsung_gpio_pull_t pull,
+				  samsung_gpio_pull_t updown)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	if (pull == updown)
+		pup &= ~(1 << off);
+	else if (pull == S3C_GPIO_PULL_NONE)
+		pup |= (1 << off);
+	else
+		return -EINVAL;
+
+	__raw_writel(pup, reg);
+	return 0;
+}
+
+static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
+						  unsigned int off,
+						  samsung_gpio_pull_t updown)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	pup &= (1 << off);
+	return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+					     unsigned int off)
+{
+	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+			     unsigned int off, samsung_gpio_pull_t pull)
+{
+	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+					       unsigned int off)
+{
+	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+			       unsigned int off, samsung_gpio_pull_t pull)
+{
+	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+
+static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull)
+{
+	if (pull == S3C_GPIO_PULL_UP)
+		pull = 3;
+
+	return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
+						unsigned int off)
+{
+	samsung_gpio_pull_t pull;
+
+	pull = samsung_gpio_getpull_updown(chip, off);
+
+	if (pull == 3)
+		pull = S3C_GPIO_PULL_UP;
+
+	return pull;
+}
+
+/*
+ * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ *	00 = input
+ *	01 = output
+ *	1x = special function
+ */
+
+static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
+				    unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off * 2;
+	u32 con;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		if (cfg > 3)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x3 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
+ * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
+ * S3C_GPIO_SPECIAL() macro.
+ */
+
+static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
+					     unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off * 2;
+	con &= 3;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
+
+/*
+ * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ *	0000 = Input
+ *	0001 = Output
+ *	others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of functions for
+ * each case.
+ */
+
+static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
+				    unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
+ * register setting into a value the software can use, such as could be passed
+ * to samsung_gpio_setcfg_4bit().
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ */
+
+static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
+					 unsigned int off)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	con = __raw_readl(reg);
+	con >>= shift;
+	con &= 0xf;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/*
+ * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+ */
+
+static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
+				     unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off;
+	u32 con;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+
+		/* Map output to 0, and SFN2 to 1 */
+		cfg -= 1;
+		if (cfg > 1)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x1 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
+ * GPIO configuration value.
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ * @sa samsung_gpio_getcfg_4bit
+ */
+
+static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
+					  unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off;
+	con &= 1;
+	con++;
+
+	return S3C_GPIO_SFN(con);
+}
+#endif
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
+				     unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift;
+	u32 con;
+
+	switch (off) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		shift = (off & 7) * 4;
+		reg -= 4;
+		break;
+	case 6:
+		shift = ((off + 1) & 7) * 4;
+		reg -= 4;
+	default:
+		shift = ((off + 1) & 7) * 4;
+		break;
+	}
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+#endif
+
+static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
+					   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chipcfg++) {
+		if (!chipcfg->set_config)
+			chipcfg->set_config = samsung_gpio_setcfg_4bit;
+		if (!chipcfg->get_config)
+			chipcfg->get_config = samsung_gpio_getcfg_4bit;
+		if (!chipcfg->set_pull)
+			chipcfg->set_pull = samsung_gpio_setpull_updown;
+		if (!chipcfg->get_pull)
+			chipcfg->get_pull = samsung_gpio_getpull_updown;
+	}
+}
+
+struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
+	.set_config	= samsung_gpio_setcfg_2bit,
+	.get_config	= samsung_gpio_getcfg_2bit,
+};
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
+	.set_config	= s3c24xx_gpio_setcfg_abank,
+	.get_config	= s3c24xx_gpio_getcfg_abank,
+};
+#endif
+
+static struct samsung_gpio_cfg exynos4_gpio_cfg = {
+	.set_pull	= exynos4_gpio_setpull,
+	.get_pull	= exynos4_gpio_getpull,
+	.set_config	= samsung_gpio_setcfg_4bit,
+	.get_config	= samsung_gpio_getcfg_4bit,
+};
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
+	.cfg_eint	= 0x3,
+	.set_config	= s5p64x0_gpio_setcfg_rbank,
+	.get_config	= samsung_gpio_getcfg_4bit,
+	.set_pull	= samsung_gpio_setpull_updown,
+	.get_pull	= samsung_gpio_getpull_updown,
+};
+#endif
+
+static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
+	{
+		.cfg_eint	= 0x0,
+	}, {
+		.cfg_eint	= 0x3,
+	}, {
+		.cfg_eint	= 0x7,
+	}, {
+		.cfg_eint	= 0xF,
+	}, {
+		.cfg_eint	= 0x0,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.cfg_eint	= 0x2,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.cfg_eint	= 0x3,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.set_pull	= exynos4_gpio_setpull,
+		.get_pull	= exynos4_gpio_getpull,
+	}, {
+		.cfg_eint	= 0x3,
+		.set_pull	= exynos4_gpio_setpull,
+		.get_pull	= exynos4_gpio_getpull,
+	}
+};
+
+/*
+ * Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *	        gpio n: 2 bits starting at (2*n)
+ *		00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+*/
+
+static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long con;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+
+	__raw_writel(con, base + 0x00);
+
+	samsung_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
+static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
+				       unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+	con |= 1 << (offset * 2);
+
+	__raw_writel(con, base + 0x00);
+	__raw_writel(dat, base + 0x04);
+
+	samsung_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
+/*
+ * The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
+ * state of the output.
+ */
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, base + GPIOCON_OFF);
+
+	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+				       unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+	unsigned long dat;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	con |= 0x1 << con_4bit_shift(offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, base + GPIOCON_OFF);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+/*
+ * The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
+ * routines we store the 'base + 0x4' address so that these routines see
+ * the data register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+
+	if (offset > 7)
+		offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+					unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned con_offset = offset;
+
+	if (con_offset > 7)
+		con_offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/* The next set of routines are for the case of s3c24xx bank a */
+
+static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
+{
+	return -EINVAL;
+}
+
+static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	local_irq_save(flags);
+
+	con = __raw_readl(base + 0x00);
+	dat = __raw_readl(base + 0x04);
+
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+
+	__raw_writel(dat, base + 0x04);
+
+	con &= ~(1 << offset);
+
+	__raw_writel(con, base + 0x00);
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+	return 0;
+}
+#endif
+
+/* The next set of routines are for the case of s5p64x0 bank r */
+
+static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long flags;
+
+	switch (offset) {
+	case 6:
+		offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		offset -= 7;
+		break;
+	}
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	samsung_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
+					unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned long flags;
+	unsigned con_offset  = offset;
+
+	switch (con_offset) {
+	case 6:
+		con_offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		con_offset -= 7;
+		break;
+	}
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	samsung_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static void samsung_gpiolib_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	samsung_gpio_unlock(ourchip, flags);
+}
+
+static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	unsigned long val;
+
+	val = __raw_readl(ourchip->base + 0x04);
+	val >>= offset;
+	val &= 1;
+
+	return val;
+}
+
+/*
+ * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
+ * for use with the configuration calls, and other parts of the s3c gpiolib
+ * support code.
+ *
+ * Not all s3c support code will need this, as some configurations of cpu
+ * may only support one or two different configuration options and have an
+ * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
+ * the machine support file should provide its own samsung_gpiolib_getchip()
+ * and any other necessary functions.
+ */
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
+{
+	unsigned int gpn;
+	int i;
+
+	gpn = chip->chip.base;
+	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+		s3c_gpios[gpn] = chip;
+	}
+}
+#endif /* CONFIG_S3C_GPIO_TRACK */
+
+/*
+ * samsung_gpiolib_add() - add the Samsung gpio_chip.
+ * @chip: The chip to register
+ *
+ * This is a wrapper to gpiochip_add() that takes our specific gpio chip
+ * information and makes the necessary alterations for the platform and
+ * notes the information for use with the configuration systems and any
+ * other parts of the system.
+ */
+
+static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
+{
+	struct gpio_chip *gc = &chip->chip;
+	int ret;
+
+	BUG_ON(!chip->base);
+	BUG_ON(!gc->label);
+	BUG_ON(!gc->ngpio);
+
+	spin_lock_init(&chip->lock);
+
+	if (!gc->direction_input)
+		gc->direction_input = samsung_gpiolib_2bit_input;
+	if (!gc->direction_output)
+		gc->direction_output = samsung_gpiolib_2bit_output;
+	if (!gc->set)
+		gc->set = samsung_gpiolib_set;
+	if (!gc->get)
+		gc->get = samsung_gpiolib_get;
+
+#ifdef CONFIG_PM
+	if (chip->pm != NULL) {
+		if (!chip->pm->save || !chip->pm->resume)
+			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			       gc->label);
+	} else
+		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+	/* gpiochip_add() prints own failure message on error. */
+	ret = gpiochip_add(gc);
+	if (ret >= 0)
+		s3c_gpiolib_track(chip);
+}
+
+static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
+					     int nr_chips, void __iomem *base)
+{
+	int i;
+	struct gpio_chip *gc = &chip->chip;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		/* skip banks not present on SoC */
+		if (chip->chip.base >= S3C_GPIO_END)
+			continue;
+
+		if (!chip->config)
+			chip->config = &s3c24xx_gpiocfg_default;
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * 0x10);
+
+		if (!gc->direction_input)
+			gc->direction_input = samsung_gpiolib_2bit_input;
+		if (!gc->direction_output)
+			gc->direction_output = samsung_gpiolib_2bit_output;
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
+						  int nr_chips, void __iomem *base,
+						  unsigned int offset)
+{
+	int i;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_2bit_input;
+		chip->chip.direction_output = samsung_gpiolib_2bit_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[7];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * offset);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+/*
+ * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of function
+ * (samsung_gpiolib_add_4bit2_chips)for each case.
+ */
+
+static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
+						  int nr_chips, void __iomem *base)
+{
+	int i;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_4bit_input;
+		chip->chip.direction_output = samsung_gpiolib_4bit_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[2];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * 0x20);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
+						   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+		chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[2];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
+					     int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
+		chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
+
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
+
+	return samsung_chip->irq_base + offset;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset < 4)
+		return IRQ_EINT0 + offset;
+
+	if (offset < 8)
+		return IRQ_EINT4 + offset - 4;
+
+	return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
+}
+
+static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
+}
+#endif
+
+struct samsung_gpio_chip s3c24xx_gpios[] = {
+#ifdef CONFIG_PLAT_S3C24XX
+	{
+		.config	= &s3c24xx_gpiocfg_banka,
+		.chip	= {
+			.base			= S3C2410_GPA(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOA",
+			.ngpio			= 24,
+			.direction_input	= s3c24xx_gpiolib_banka_input,
+			.direction_output	= s3c24xx_gpiolib_banka_output,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPB(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOB",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPC(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOC",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPD(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOD",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPE(0),
+			.label	= "GPIOE",
+			.owner	= THIS_MODULE,
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPF(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOF",
+			.ngpio	= 8,
+			.to_irq	= s3c24xx_gpiolib_fbank_to_irq,
+		},
+	}, {
+		.irq_base = IRQ_EINT8,
+		.chip	= {
+			.base	= S3C2410_GPG(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOG",
+			.ngpio	= 16,
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPH(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOH",
+			.ngpio	= 11,
+		},
+	},
+		/* GPIOS for the S3C2443 and later devices. */
+	{
+		.base	= S3C2440_GPJCON,
+		.chip	= {
+			.base	= S3C2410_GPJ(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOJ",
+			.ngpio	= 16,
+		},
+	}, {
+		.base	= S3C2443_GPKCON,
+		.chip	= {
+			.base	= S3C2410_GPK(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOK",
+			.ngpio	= 16,
+		},
+	}, {
+		.base	= S3C2443_GPLCON,
+		.chip	= {
+			.base	= S3C2410_GPL(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOL",
+			.ngpio	= 15,
+		},
+	}, {
+		.base	= S3C2443_GPMCON,
+		.chip	= {
+			.base	= S3C2410_GPM(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOM",
+			.ngpio	= 2,
+		},
+	},
+#endif
+};
+
+/*
+ * GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	8	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * D	5	4Bit	Yes	3
+ * E	5	4Bit	Yes	None
+ * F	16	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * K	16	4Bit[2]	No	None
+ * L	15	4Bit[2] No	None
+ * M	6	4Bit	No	IRQ_EINT
+ * N	16	2Bit	No	IRQ_EINT
+ * O	16	2Bit	Yes	7
+ * P	15	2Bit	Yes	8
+ * Q	9	2Bit	Yes	9
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.chip	= {
+			.base	= S3C64XX_GPA(0),
+			.ngpio	= S3C64XX_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPB(0),
+			.ngpio	= S3C64XX_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPC(0),
+			.ngpio	= S3C64XX_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPD(0),
+			.ngpio	= S3C64XX_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[0],
+		.chip	= {
+			.base	= S3C64XX_GPE(0),
+			.ngpio	= S3C64XX_GPIO_E_NR,
+			.label	= "GPE",
+		},
+	}, {
+		.base	= S3C64XX_GPG_BASE,
+		.chip	= {
+			.base	= S3C64XX_GPG(0),
+			.ngpio	= S3C64XX_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S3C64XX_GPM_BASE,
+		.config	= &samsung_gpio_cfgs[1],
+		.chip	= {
+			.base	= S3C64XX_GPM(0),
+			.ngpio	= S3C64XX_GPIO_M_NR,
+			.label	= "GPM",
+			.to_irq = s3c64xx_gpiolib_mbank_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.base	= S3C64XX_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S3C64XX_GPH(0),
+			.ngpio	= S3C64XX_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	}, {
+		.base	= S3C64XX_GPK_BASE + 0x4,
+		.config	= &samsung_gpio_cfgs[0],
+		.chip	= {
+			.base	= S3C64XX_GPK(0),
+			.ngpio	= S3C64XX_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	}, {
+		.base	= S3C64XX_GPL_BASE + 0x4,
+		.config	= &samsung_gpio_cfgs[1],
+		.chip	= {
+			.base	= S3C64XX_GPL(0),
+			.ngpio	= S3C64XX_GPIO_L_NR,
+			.label	= "GPL",
+			.to_irq = s3c64xx_gpiolib_lbank_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.base	= S3C64XX_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPF(0),
+			.ngpio	= S3C64XX_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[7],
+		.chip	= {
+			.base	= S3C64XX_GPI(0),
+			.ngpio	= S3C64XX_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[7],
+		.chip	= {
+			.base	= S3C64XX_GPJ(0),
+			.ngpio	= S3C64XX_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPO(0),
+			.ngpio	= S3C64XX_GPIO_O_NR,
+			.label	= "GPO",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPP(0),
+			.ngpio	= S3C64XX_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPQ(0),
+			.ngpio	= S3C64XX_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	}, {
+		.base	= S3C64XX_GPN_BASE,
+		.irq_base = IRQ_EINT(0),
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S3C64XX_GPN(0),
+			.ngpio	= S3C64XX_GPIO_N_NR,
+			.label	= "GPN",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	6	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * F	2	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * N	16	2Bit	No	IRQ_EINT
+ * P	8	2Bit	Yes	8
+ * R	15	4Bit[2]	Yes	8
+ */
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.chip	= {
+			.base	= S5P6440_GPA(0),
+			.ngpio	= S5P6440_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6440_GPB(0),
+			.ngpio	= S5P6440_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6440_GPC(0),
+			.ngpio	= S5P6440_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P64X0_GPG_BASE,
+		.chip	= {
+			.base	= S5P6440_GPG(0),
+			.ngpio	= S5P6440_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6440_GPH(0),
+			.ngpio	= S5P6440_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfg_rbank,
+		.chip	= {
+			.base	= S5P6440_GPR(0),
+			.ngpio	= S5P6440_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6440_GPF(0),
+			.ngpio	= S5P6440_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPI(0),
+			.ngpio	= S5P6440_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPJ(0),
+			.ngpio	= S5P6440_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPN(0),
+			.ngpio	= S5P6440_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6440_GPP(0),
+			.ngpio	= S5P6440_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	},
+#endif
+};
+
+/*
+ * S5P6450 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	6	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * D	8	4Bit	Yes	None
+ * F	2	2Bit	Yes	None
+ * G	14	4Bit[2]	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * K	5	4Bit	Yes	None
+ * N	16	2Bit	No	IRQ_EINT
+ * P	11	2Bit	Yes	8
+ * Q	14	2Bit	Yes	None
+ * R	15	4Bit[2]	Yes	None
+ * S	8	2Bit	Yes	None
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.chip	= {
+			.base	= S5P6450_GPA(0),
+			.ngpio	= S5P6450_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPB(0),
+			.ngpio	= S5P6450_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPC(0),
+			.ngpio	= S5P6450_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPD(0),
+			.ngpio	= S5P6450_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.base	= S5P6450_GPK_BASE,
+		.chip	= {
+			.base	= S5P6450_GPK(0),
+			.ngpio	= S5P6450_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPG_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6450_GPG(0),
+			.ngpio	= S5P6450_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6450_GPH(0),
+			.ngpio	= S5P6450_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfg_rbank,
+		.chip	= {
+			.base	= S5P6450_GPR(0),
+			.ngpio	= S5P6450_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPF(0),
+			.ngpio	= S5P6450_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPI(0),
+			.ngpio	= S5P6450_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPJ(0),
+			.ngpio	= S5P6450_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPN(0),
+			.ngpio	= S5P6450_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPP(0),
+			.ngpio	= S5P6450_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.base	= S5P6450_GPQ_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPQ(0),
+			.ngpio	= S5P6450_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	}, {
+		.base	= S5P6450_GPS_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPS(0),
+			.ngpio	= S5P6450_GPIO_S_NR,
+			.label	= "GPS",
+		},
+	},
+#endif
+};
+
+/*
+ * S5PC100 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	INT Type
+ * A0	8	4Bit	GPIO_INT0
+ * A1	5	4Bit	GPIO_INT1
+ * B	8	4Bit	GPIO_INT2
+ * C	5	4Bit	GPIO_INT3
+ * D	7	4Bit	GPIO_INT4
+ * E0	8	4Bit	GPIO_INT5
+ * E1	6	4Bit	GPIO_INT6
+ * F0	8	4Bit	GPIO_INT7
+ * F1	8	4Bit	GPIO_INT8
+ * F2	8	4Bit	GPIO_INT9
+ * F3	4	4Bit	GPIO_INT10
+ * G0	8	4Bit	GPIO_INT11
+ * G1	3	4Bit	GPIO_INT12
+ * G2	7	4Bit	GPIO_INT13
+ * G3	7	4Bit	GPIO_INT14
+ * H0	8	4Bit	WKUP_INT
+ * H1	8	4Bit	WKUP_INT
+ * H2	8	4Bit	WKUP_INT
+ * H3	8	4Bit	WKUP_INT
+ * I	8	4Bit	GPIO_INT15
+ * J0	8	4Bit	GPIO_INT16
+ * J1	5	4Bit	GPIO_INT17
+ * J2	8	4Bit	GPIO_INT18
+ * J3	8	4Bit	GPIO_INT19
+ * J4	4	4Bit	GPIO_INT20
+ * K0	8	4Bit	None
+ * K1	6	4Bit	None
+ * K2	8	4Bit	None
+ * K3	8	4Bit	None
+ * L0	8	4Bit	None
+ * L1	8	4Bit	None
+ * L2	8	4Bit	None
+ * L3	8	4Bit	None
+ */
+
+static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PC100
+	{
+		.chip	= {
+			.base	= S5PC100_GPA0(0),
+			.ngpio	= S5PC100_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPA1(0),
+			.ngpio	= S5PC100_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPB(0),
+			.ngpio	= S5PC100_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPC(0),
+			.ngpio	= S5PC100_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPD(0),
+			.ngpio	= S5PC100_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPE0(0),
+			.ngpio	= S5PC100_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPE1(0),
+			.ngpio	= S5PC100_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF0(0),
+			.ngpio	= S5PC100_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF1(0),
+			.ngpio	= S5PC100_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF2(0),
+			.ngpio	= S5PC100_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF3(0),
+			.ngpio	= S5PC100_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG0(0),
+			.ngpio	= S5PC100_GPIO_G0_NR,
+			.label	= "GPG0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG1(0),
+			.ngpio	= S5PC100_GPIO_G1_NR,
+			.label	= "GPG1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG2(0),
+			.ngpio	= S5PC100_GPIO_G2_NR,
+			.label	= "GPG2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG3(0),
+			.ngpio	= S5PC100_GPIO_G3_NR,
+			.label	= "GPG3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPI(0),
+			.ngpio	= S5PC100_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ0(0),
+			.ngpio	= S5PC100_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ1(0),
+			.ngpio	= S5PC100_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ2(0),
+			.ngpio	= S5PC100_GPIO_J2_NR,
+			.label	= "GPJ2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ3(0),
+			.ngpio	= S5PC100_GPIO_J3_NR,
+			.label	= "GPJ3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ4(0),
+			.ngpio	= S5PC100_GPIO_J4_NR,
+			.label	= "GPJ4",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK0(0),
+			.ngpio	= S5PC100_GPIO_K0_NR,
+			.label	= "GPK0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK1(0),
+			.ngpio	= S5PC100_GPIO_K1_NR,
+			.label	= "GPK1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK2(0),
+			.ngpio	= S5PC100_GPIO_K2_NR,
+			.label	= "GPK2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK3(0),
+			.ngpio	= S5PC100_GPIO_K3_NR,
+			.label	= "GPK3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL0(0),
+			.ngpio	= S5PC100_GPIO_L0_NR,
+			.label	= "GPL0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL1(0),
+			.ngpio	= S5PC100_GPIO_L1_NR,
+			.label	= "GPL1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL2(0),
+			.ngpio	= S5PC100_GPIO_L2_NR,
+			.label	= "GPL2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL3(0),
+			.ngpio	= S5PC100_GPIO_L3_NR,
+			.label	= "GPL3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL4(0),
+			.ngpio	= S5PC100_GPIO_L4_NR,
+			.label	= "GPL4",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC00),
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= S5PC100_GPH0(0),
+			.ngpio	= S5PC100_GPIO_H0_NR,
+			.label	= "GPH0",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC20),
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= S5PC100_GPH1(0),
+			.ngpio	= S5PC100_GPIO_H1_NR,
+			.label	= "GPH1",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC40),
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= S5PC100_GPH2(0),
+			.ngpio	= S5PC100_GPIO_H2_NR,
+			.label	= "GPH2",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC60),
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= S5PC100_GPH3(0),
+			.ngpio	= S5PC100_GPIO_H3_NR,
+			.label	= "GPH3",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * Followings are the gpio banks in S5PV210/S5PC110
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PV210
+	{
+		.chip	= {
+			.base	= S5PV210_GPA0(0),
+			.ngpio	= S5PV210_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPA1(0),
+			.ngpio	= S5PV210_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPB(0),
+			.ngpio	= S5PV210_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC0(0),
+			.ngpio	= S5PV210_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC1(0),
+			.ngpio	= S5PV210_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD0(0),
+			.ngpio	= S5PV210_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD1(0),
+			.ngpio	= S5PV210_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE0(0),
+			.ngpio	= S5PV210_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE1(0),
+			.ngpio	= S5PV210_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF0(0),
+			.ngpio	= S5PV210_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF1(0),
+			.ngpio	= S5PV210_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF2(0),
+			.ngpio	= S5PV210_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF3(0),
+			.ngpio	= S5PV210_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG0(0),
+			.ngpio	= S5PV210_GPIO_G0_NR,
+			.label	= "GPG0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG1(0),
+			.ngpio	= S5PV210_GPIO_G1_NR,
+			.label	= "GPG1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG2(0),
+			.ngpio	= S5PV210_GPIO_G2_NR,
+			.label	= "GPG2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG3(0),
+			.ngpio	= S5PV210_GPIO_G3_NR,
+			.label	= "GPG3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPI(0),
+			.ngpio	= S5PV210_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ0(0),
+			.ngpio	= S5PV210_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ1(0),
+			.ngpio	= S5PV210_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ2(0),
+			.ngpio	= S5PV210_GPIO_J2_NR,
+			.label	= "GPJ2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ3(0),
+			.ngpio	= S5PV210_GPIO_J3_NR,
+			.label	= "GPJ3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ4(0),
+			.ngpio	= S5PV210_GPIO_J4_NR,
+			.label	= "GPJ4",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP01(0),
+			.ngpio	= S5PV210_GPIO_MP01_NR,
+			.label	= "MP01",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP02(0),
+			.ngpio	= S5PV210_GPIO_MP02_NR,
+			.label	= "MP02",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP03(0),
+			.ngpio	= S5PV210_GPIO_MP03_NR,
+			.label	= "MP03",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP04(0),
+			.ngpio	= S5PV210_GPIO_MP04_NR,
+			.label	= "MP04",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP05(0),
+			.ngpio	= S5PV210_GPIO_MP05_NR,
+			.label	= "MP05",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC00),
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= S5PV210_GPH0(0),
+			.ngpio	= S5PV210_GPIO_H0_NR,
+			.label	= "GPH0",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC20),
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= S5PV210_GPH1(0),
+			.ngpio	= S5PV210_GPIO_H1_NR,
+			.label	= "GPH1",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC40),
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= S5PV210_GPH2(0),
+			.ngpio	= S5PV210_GPIO_H2_NR,
+			.label	= "GPH2",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC60),
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= S5PV210_GPH3(0),
+			.ngpio	= S5PV210_GPIO_H3_NR,
+			.label	= "GPH3",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * Followings are the gpio banks in EXYNOS4210
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPA0(0),
+			.ngpio	= EXYNOS4_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPA1(0),
+			.ngpio	= EXYNOS4_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPB(0),
+			.ngpio	= EXYNOS4_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC0(0),
+			.ngpio	= EXYNOS4_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC1(0),
+			.ngpio	= EXYNOS4_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD0(0),
+			.ngpio	= EXYNOS4_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD1(0),
+			.ngpio	= EXYNOS4_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE0(0),
+			.ngpio	= EXYNOS4_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE1(0),
+			.ngpio	= EXYNOS4_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE2(0),
+			.ngpio	= EXYNOS4_GPIO_E2_NR,
+			.label	= "GPE2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE3(0),
+			.ngpio	= EXYNOS4_GPIO_E3_NR,
+			.label	= "GPE3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE4(0),
+			.ngpio	= EXYNOS4_GPIO_E4_NR,
+			.label	= "GPE4",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF0(0),
+			.ngpio	= EXYNOS4_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF1(0),
+			.ngpio	= EXYNOS4_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF2(0),
+			.ngpio	= EXYNOS4_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF3(0),
+			.ngpio	= EXYNOS4_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPJ0(0),
+			.ngpio	= EXYNOS4_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPJ1(0),
+			.ngpio	= EXYNOS4_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK0(0),
+			.ngpio	= EXYNOS4_GPIO_K0_NR,
+			.label	= "GPK0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK1(0),
+			.ngpio	= EXYNOS4_GPIO_K1_NR,
+			.label	= "GPK1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK2(0),
+			.ngpio	= EXYNOS4_GPIO_K2_NR,
+			.label	= "GPK2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK3(0),
+			.ngpio	= EXYNOS4_GPIO_K3_NR,
+			.label	= "GPK3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL0(0),
+			.ngpio	= EXYNOS4_GPIO_L0_NR,
+			.label	= "GPL0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL1(0),
+			.ngpio	= EXYNOS4_GPIO_L1_NR,
+			.label	= "GPL1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL2(0),
+			.ngpio	= EXYNOS4_GPIO_L2_NR,
+			.label	= "GPL2",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY0(0),
+			.ngpio	= EXYNOS4_GPIO_Y0_NR,
+			.label	= "GPY0",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY1(0),
+			.ngpio	= EXYNOS4_GPIO_Y1_NR,
+			.label	= "GPY1",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY2(0),
+			.ngpio	= EXYNOS4_GPIO_Y2_NR,
+			.label	= "GPY2",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY3(0),
+			.ngpio	= EXYNOS4_GPIO_Y3_NR,
+			.label	= "GPY3",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY4(0),
+			.ngpio	= EXYNOS4_GPIO_Y4_NR,
+			.label	= "GPY4",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY5(0),
+			.ngpio	= EXYNOS4_GPIO_Y5_NR,
+			.label	= "GPY5",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY6(0),
+			.ngpio	= EXYNOS4_GPIO_Y6_NR,
+			.label	= "GPY6",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC00),
+		.config	= &samsung_gpio_cfgs[9],
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= EXYNOS4_GPX0(0),
+			.ngpio	= EXYNOS4_GPIO_X0_NR,
+			.label	= "GPX0",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC20),
+		.config	= &samsung_gpio_cfgs[9],
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= EXYNOS4_GPX1(0),
+			.ngpio	= EXYNOS4_GPIO_X1_NR,
+			.label	= "GPX1",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC40),
+		.config	= &samsung_gpio_cfgs[9],
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= EXYNOS4_GPX2(0),
+			.ngpio	= EXYNOS4_GPIO_X2_NR,
+			.label	= "GPX2",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC60),
+		.config	= &samsung_gpio_cfgs[9],
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= EXYNOS4_GPX3(0),
+			.ngpio	= EXYNOS4_GPIO_X3_NR,
+			.label	= "GPX3",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPZ(0),
+			.ngpio	= EXYNOS4_GPIO_Z_NR,
+			.label	= "GPZ",
+		},
+	},
+#endif
+};
+
+/* TODO: cleanup soc_is_* */
+static __init int samsung_gpiolib_init(void)
+{
+	struct samsung_gpio_chip *chip;
+	int i, nr_chips;
+	int group = 0;
+
+	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
+
+	if (soc_is_s3c24xx()) {
+		s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
+				ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
+	} else if (soc_is_s3c64xx()) {
+		samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
+				ARRAY_SIZE(s3c64xx_gpios_2bit),
+				S3C64XX_VA_GPIO + 0xE0, 0x20);
+		samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
+				ARRAY_SIZE(s3c64xx_gpios_4bit),
+				S3C64XX_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
+				ARRAY_SIZE(s3c64xx_gpios_4bit2));
+	} else if (soc_is_s5p6440()) {
+		samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
+				ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
+		samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
+				ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
+				ARRAY_SIZE(s5p6440_gpios_4bit2));
+		s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
+				ARRAY_SIZE(s5p6440_gpios_rbank));
+	} else if (soc_is_s5p6450()) {
+		samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
+				ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
+		samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
+				ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
+				ARRAY_SIZE(s5p6450_gpios_4bit2));
+		s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
+				ARRAY_SIZE(s5p6450_gpios_rbank));
+	} else if (soc_is_s5pc100()) {
+		group = 0;
+		chip = s5pc100_gpios_4bit;
+		nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &samsung_gpio_cfgs[3];
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
+		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+	} else if (soc_is_s5pv210()) {
+		group = 0;
+		chip = s5pv210_gpios_4bit;
+		nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &samsung_gpio_cfgs[3];
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
+		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+	} else if (soc_is_exynos4210()) {
+		group = 0;
+
+		/* gpio part1 */
+		chip = exynos4_gpios_1;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
+
+		/* gpio part2 */
+		chip = exynos4_gpios_2;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
+
+		/* gpio part3 */
+		chip = exynos4_gpios_3;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+		s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+		s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+#endif
+	} else {
+		WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+core_initcall(samsung_gpiolib_init);
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset;
+	int ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	samsung_gpio_lock(chip, flags);
+	ret = samsung_gpio_do_setcfg(chip, offset, config);
+	samsung_gpio_unlock(chip, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
+
+int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
+			  unsigned int cfg)
+{
+	int ret;
+
+	for (; nr > 0; nr--, start++) {
+		ret = s3c_gpio_cfgpin(start, cfg);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
+
+int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
+			  unsigned int cfg, samsung_gpio_pull_t pull)
+{
+	int ret;
+
+	for (; nr > 0; nr--, start++) {
+		s3c_gpio_setpull(start, pull);
+		ret = s3c_gpio_cfgpin(start, cfg);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
+
+unsigned s3c_gpio_getcfg(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	unsigned ret = 0;
+	int offset;
+
+	if (chip) {
+		offset = pin - chip->chip.base;
+
+		samsung_gpio_lock(chip, flags);
+		ret = samsung_gpio_do_getcfg(chip, offset);
+		samsung_gpio_unlock(chip, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_getcfg);
+
+int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset, ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	samsung_gpio_lock(chip, flags);
+	ret = samsung_gpio_do_setpull(chip, offset, pull);
+	samsung_gpio_unlock(chip, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_setpull);
+
+samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset;
+	u32 pup = 0;
+
+	if (chip) {
+		offset = pin - chip->chip.base;
+
+		samsung_gpio_lock(chip, flags);
+		pup = samsung_gpio_do_getpull(chip, offset);
+		samsung_gpio_unlock(chip, flags);
+	}
+
+	return (__force samsung_gpio_pull_t)pup;
+}
+EXPORT_SYMBOL(s3c_gpio_getpull);
+
+/* gpiolib wrappers until these are totally eliminated */
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+	int ret;
+
+	WARN_ON(to);	/* should be none of these left */
+
+	if (!to) {
+		/* if pull is enabled, try first with up, and if that
+		 * fails, try using down */
+
+		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
+		if (ret)
+			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
+	} else {
+		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
+	}
+}
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+	/* do this via gpiolib until all users removed */
+
+	gpio_request(pin, "temporary");
+	gpio_set_value(pin, to);
+	gpio_free(pin);
+}
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
+
+	return __raw_readl(chip->base + 0x04) & (1 << offs);
+}
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+#ifdef CONFIG_S5P_GPIO_DRVSTR
+s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned int off;
+	void __iomem *reg;
+	int shift;
+	u32 drvstr;
+
+	if (!chip)
+		return -EINVAL;
+
+	off = pin - chip->chip.base;
+	shift = off * 2;
+	reg = chip->base + 0x0C;
+
+	drvstr = __raw_readl(reg);
+	drvstr = drvstr >> shift;
+	drvstr &= 0x3;
+
+	return (__force s5p_gpio_drvstr_t)drvstr;
+}
+EXPORT_SYMBOL(s5p_gpio_get_drvstr);
+
+int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned int off;
+	void __iomem *reg;
+	int shift;
+	u32 tmp;
+
+	if (!chip)
+		return -EINVAL;
+
+	off = pin - chip->chip.base;
+	shift = off * 2;
+	reg = chip->base + 0x0C;
+
+	tmp = __raw_readl(reg);
+	tmp &= ~(0x3 << shift);
+	tmp |= drvstr << shift;
+
+	__raw_writel(tmp, reg);
+
+	return 0;
+}
+EXPORT_SYMBOL(s5p_gpio_set_drvstr);
+#endif	/* CONFIG_S5P_GPIO_DRVSTR */
+
+#ifdef CONFIG_PLAT_S3C24XX
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C24XX_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C24XX_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-tegra.c linux-libre-3.2-gnu1/drivers/gpio/gpio-tegra.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,13 +20,15 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include <asm/mach/irq.h>
 
+#include <mach/gpio-tegra.h>
 #include <mach/iomap.h>
 #include <mach/suspend.h>
 
@@ -34,9 +36,7 @@
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
 
-#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
-				 GPIO_BANK(x) * 0x80 +		\
-				 GPIO_PORT(x) * 4)
+#define GPIO_REG(x)		(GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
 
 #define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
 #define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
@@ -75,15 +75,18 @@ struct tegra_gpio_bank {
 };
 
 
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
-	{.bank = 0, .irq = INT_GPIO1},
-	{.bank = 1, .irq = INT_GPIO2},
-	{.bank = 2, .irq = INT_GPIO3},
-	{.bank = 3, .irq = INT_GPIO4},
-	{.bank = 4, .irq = INT_GPIO5},
-	{.bank = 5, .irq = INT_GPIO6},
-	{.bank = 6, .irq = INT_GPIO7},
-};
+static void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7];
+
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+	__raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+	return __raw_readl(regs + reg);
+}
 
 static int tegra_gpio_compose(int bank, int port, int bit)
 {
@@ -97,7 +100,7 @@ static void tegra_gpio_mask_write(u32 re
 	val = 0x100 << GPIO_BIT(gpio);
 	if (value)
 		val |= 1 << GPIO_BIT(gpio);
-	__raw_writel(val, reg);
+	tegra_gpio_writel(val, reg);
 }
 
 void tegra_gpio_enable(int gpio)
@@ -117,7 +120,7 @@ static void tegra_gpio_set(struct gpio_c
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
 }
 
 static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -134,7 +137,10 @@ static int tegra_gpio_direction_output(s
 	return 0;
 }
 
-
+static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return TEGRA_GPIO_TO_IRQ(offset);
+}
 
 static struct gpio_chip tegra_gpio_chip = {
 	.label			= "tegra-gpio",
@@ -142,6 +148,7 @@ static struct gpio_chip tegra_gpio_chip
 	.get			= tegra_gpio_get,
 	.direction_output	= tegra_gpio_direction_output,
 	.set			= tegra_gpio_set,
+	.to_irq			= tegra_gpio_to_irq,
 	.base			= 0,
 	.ngpio			= TEGRA_NR_GPIOS,
 };
@@ -150,7 +157,7 @@ static void tegra_gpio_irq_ack(struct ir
 {
 	int gpio = d->irq - INT_GPIO_BASE;
 
-	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+	tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
 }
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -203,10 +210,10 @@ static int tegra_gpio_irq_set_type(struc
 
 	spin_lock_irqsave(&bank->lvl_lock[port], flags);
 
-	val = __raw_readl(GPIO_INT_LVL(gpio));
+	val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
 	val |= lvl_type << GPIO_BIT(gpio);
-	__raw_writel(val, GPIO_INT_LVL(gpio));
+	tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
 
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
@@ -232,12 +239,12 @@ static void tegra_gpio_irq_handler(unsig
 
 	for (port = 0; port < 4; port++) {
 		int gpio = tegra_gpio_compose(bank->bank, port, 0);
-		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
-			__raw_readl(GPIO_INT_ENB(gpio));
-		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+		unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+			tegra_gpio_readl(GPIO_INT_ENB(gpio));
+		u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 
 		for_each_set_bit(pin, &sta, 8) {
-			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+			tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
 
 			/* if gpio is edge triggered, clear condition
 			 * before executing the hander so that we don't
@@ -271,11 +278,11 @@ void tegra_gpio_resume(void)
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
-			__raw_writel(bank->out[p], GPIO_OUT(gpio));
-			__raw_writel(bank->oe[p], GPIO_OE(gpio));
-			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
-			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+			tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+			tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+			tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+			tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
 		}
 	}
 
@@ -294,11 +301,11 @@ void tegra_gpio_suspend(void)
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
-			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
-			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
-			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
-			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+			bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+			bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+			bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+			bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+			bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 		}
 	}
 	local_irq_restore(flags);
@@ -328,38 +335,69 @@ static struct irq_chip tegra_gpio_irq_ch
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __init tegra_gpio_init(void)
+static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	struct tegra_gpio_bank *bank;
+	int gpio;
 	int i;
 	int j;
 
+	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing IRQ resource\n");
+			return -ENODEV;
+		}
+
+		bank = &tegra_gpio_banks[i];
+		bank->bank = i;
+		bank->irq = res->start;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Missing MEM resource\n");
+		return -ENODEV;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+		return -ENODEV;
+	}
+
+	regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!regs) {
+		dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+		return -ENODEV;
+	}
+
 	for (i = 0; i < 7; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
-			__raw_writel(0x00, GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
 		}
 	}
 
 #ifdef CONFIG_OF_GPIO
-	/*
-	 * This isn't ideal, but it gets things hooked up until this
-	 * driver is converted into a platform_device
-	 */
-	tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
-						"nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+	tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
 
 	gpiochip_add(&tegra_gpio_chip);
 
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+	for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) {
+		int irq = TEGRA_GPIO_TO_IRQ(gpio);
+		/* No validity check; all Tegra GPIOs are valid IRQs */
 
-		irq_set_lockdep_class(i, &gpio_lock_class);
-		irq_set_chip_data(i, bank);
-		irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+		bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
+
+		irq_set_lockdep_class(irq, &gpio_lock_class);
+		irq_set_chip_data(irq, bank);
+		irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
 					 handle_simple_irq);
-		set_irq_flags(i, IRQF_VALID);
+		set_irq_flags(irq, IRQF_VALID);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
@@ -375,6 +413,24 @@ static int __init tegra_gpio_init(void)
 	return 0;
 }
 
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-gpio", },
+	{ },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+	.driver		= {
+		.name	= "tegra-gpio",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_gpio_of_match,
+	},
+	.probe		= tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+	return platform_driver_register(&tegra_gpio_driver);
+}
 postcore_initcall(tegra_gpio_init);
 
 void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -407,13 +463,13 @@ static int dbg_gpio_show(struct seq_file
 			seq_printf(s,
 				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
 				i, j,
-				__raw_readl(GPIO_CNF(gpio)),
-				__raw_readl(GPIO_OE(gpio)),
-				__raw_readl(GPIO_OUT(gpio)),
-				__raw_readl(GPIO_IN(gpio)),
-				__raw_readl(GPIO_INT_STA(gpio)),
-				__raw_readl(GPIO_INT_ENB(gpio)),
-				__raw_readl(GPIO_INT_LVL(gpio)));
+				tegra_gpio_readl(GPIO_CNF(gpio)),
+				tegra_gpio_readl(GPIO_OE(gpio)),
+				tegra_gpio_readl(GPIO_OUT(gpio)),
+				tegra_gpio_readl(GPIO_IN(gpio)),
+				tegra_gpio_readl(GPIO_INT_STA(gpio)),
+				tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+				tegra_gpio_readl(GPIO_INT_LVL(gpio)));
 		}
 	}
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-tnetv107x.c linux-libre-3.2-gnu1/drivers/gpio/gpio-tnetv107x.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-tnetv107x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,205 @@
+/*
+ * Texas Instruments TNETV107X GPIO Controller
+ *
+ * Copyright (C) 2010 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/tnetv107x.h>
+
+struct tnetv107x_gpio_regs {
+	u32	idver;
+	u32	data_in[3];
+	u32	data_out[3];
+	u32	direction[3];
+	u32	enable[3];
+};
+
+#define gpio_reg_index(gpio)	((gpio) >> 5)
+#define gpio_reg_bit(gpio)	BIT((gpio) & 0x1f)
+
+#define gpio_reg_rmw(reg, mask, val)	\
+	__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
+
+#define gpio_reg_set_bit(reg, gpio)	\
+	gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
+
+#define gpio_reg_clear_bit(reg, gpio)	\
+	gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
+
+#define gpio_reg_get_bit(reg, gpio)	\
+	(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
+
+#define chip2controller(chip)		\
+	container_of(chip, struct davinci_gpio_controller, chip)
+
+#define TNETV107X_GPIO_CTLRS	DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
+
+static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
+
+static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_set_bit(regs->enable, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_clear_bit(regs->enable, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+}
+
+static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_set_bit(regs->direction, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	if (value)
+		gpio_reg_set_bit(regs->data_out, gpio);
+	else
+		gpio_reg_clear_bit(regs->data_out, gpio);
+
+	gpio_reg_clear_bit(regs->direction, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	int ret;
+
+	ret = gpio_reg_get_bit(regs->data_in, gpio);
+
+	return ret ? 1 : 0;
+}
+
+static void tnetv107x_gpio_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	if (value)
+		gpio_reg_set_bit(regs->data_out, gpio);
+	else
+		gpio_reg_clear_bit(regs->data_out, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+}
+
+static int __init tnetv107x_gpio_setup(void)
+{
+	int i, base;
+	unsigned ngpio;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct tnetv107x_gpio_regs *regs;
+	struct davinci_gpio_controller *ctlr;
+
+	if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
+		return 0;
+
+	ngpio = soc_info->gpio_num;
+	if (ngpio == 0) {
+		pr_err("GPIO setup:  how many GPIOs?\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(TNETV107X_N_GPIO < ngpio))
+		ngpio = TNETV107X_N_GPIO;
+
+	regs = ioremap(soc_info->gpio_base, SZ_4K);
+	if (WARN_ON(!regs))
+		return -EINVAL;
+
+	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
+		ctlr = &chips[i];
+
+		ctlr->chip.label	= "tnetv107x";
+		ctlr->chip.can_sleep	= 0;
+		ctlr->chip.base		= base;
+		ctlr->chip.ngpio	= ngpio - base;
+		if (ctlr->chip.ngpio > 32)
+			ctlr->chip.ngpio = 32;
+
+		ctlr->chip.request		= tnetv107x_gpio_request;
+		ctlr->chip.free			= tnetv107x_gpio_free;
+		ctlr->chip.direction_input	= tnetv107x_gpio_dir_in;
+		ctlr->chip.get			= tnetv107x_gpio_get;
+		ctlr->chip.direction_output	= tnetv107x_gpio_dir_out;
+		ctlr->chip.set			= tnetv107x_gpio_set;
+
+		spin_lock_init(&ctlr->lock);
+
+		ctlr->regs	= regs;
+		ctlr->set_data	= &regs->data_out[i];
+		ctlr->clr_data	= &regs->data_out[i];
+		ctlr->in_data	= &regs->data_in[i];
+
+		gpiochip_add(&ctlr->chip);
+	}
+
+	soc_info->gpio_ctlrs = chips;
+	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
+	return 0;
+}
+pure_initcall(tnetv107x_gpio_setup);
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-u300.c linux-libre-3.2-gnu1/drivers/gpio/gpio-u300.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-u300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-u300.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,18 +1,17 @@
 /*
  * U300 GPIO module.
  *
- * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Copyright (C) 2007-2011 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
  * This can driver either of the two basic GPIO cores
  * available in the U300 platforms:
  * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
  * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
- * Notice that you also have inline macros in <asm-arch/gpio.h>
- * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
  */
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -21,677 +20,898 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <mach/gpio-u300.h>
 
-/* Reference to GPIO block clock */
-static struct clk *clk;
+/*
+ * Bias modes for U300 GPIOs
+ *
+ * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us
+ * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state
+ *	is not controlled by software
+ * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high
+ *	impedance to VDD)
+ */
+#define GPIO_U300_CONFIG_BIAS_UNKNOWN	0x1000
+#define GPIO_U300_CONFIG_BIAS_FLOAT	0x1001
+#define GPIO_U300_CONFIG_BIAS_PULL_UP	0x1002
 
-/* Memory resource */
-static struct resource *memres;
-static void __iomem *virtbase;
-static struct device *gpiodev;
+/*
+ * Drive modes for U300 GPIOs (output)
+ *
+ * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and
+ *	low, this is the most typical case and is typically achieved with two
+ *	active transistors on the output
+ * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain
+ *	(open collector) which means it is usually wired with other output
+ *	ports which are then pulled up with an external resistor
+ * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain
+ *	(open emitter) which is the same as open drain mutatis mutandis but
+ *	pulled to ground
+ */
+#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL	0x2000
+#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN	0x2001
+#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE	0x2002
+
+/*
+ * Register definitions for COH 901 335 variant
+ */
+#define U300_335_PORT_STRIDE				(0x1C)
+/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
+#define U300_335_PXPDIR					(0x00)
+#define U300_335_PXPDOR					(0x00)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_335_PXPCR					(0x04)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_335_PXIEV					(0x08)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_335_PXIEN					(0x0C)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_335_PXIFR					(0x10)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_335_PXICR					(0x14)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_335_PXPER					(0x18)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
+/* Control Register 32bit (R/W) */
+#define U300_335_CR					(0x54)
+#define U300_335_CR_BLOCK_CLOCK_ENABLE			(0x00000001UL)
+
+/*
+ * Register definitions for COH 901 571 / 3 variant
+ */
+#define U300_571_PORT_STRIDE				(0x30)
+/*
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2  (mask 0x000001FC) contains the core version ID.
+ */
+#define U300_571_CR					(0x00)
+#define U300_571_CR_SYNC_SEL_ENABLE			(0x00000002UL)
+#define U300_571_CR_BLOCK_CLKRQ_ENABLE			(0x00000001UL)
+/*
+ * These registers have the same layout and function as the corresponding
+ * COH 901 335 registers, just at different offset.
+ */
+#define U300_571_PXPDIR					(0x04)
+#define U300_571_PXPDOR					(0x08)
+#define U300_571_PXPCR					(0x0C)
+#define U300_571_PXPER					(0x10)
+#define U300_571_PXIEV					(0x14)
+#define U300_571_PXIEN					(0x18)
+#define U300_571_PXIFR					(0x1C)
+#define U300_571_PXICR					(0x20)
+
+/* 8 bits per port, no version has more than 7 ports */
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7)
+
+struct u300_gpio {
+	struct gpio_chip chip;
+	struct list_head port_list;
+	struct clk *clk;
+	struct resource *memres;
+	void __iomem *base;
+	struct device *dev;
+	int irq_base;
+	u32 stride;
+	/* Register offsets */
+	u32 pcr;
+	u32 dor;
+	u32 dir;
+	u32 per;
+	u32 icr;
+	u32 ien;
+	u32 iev;
+};
 
 struct u300_gpio_port {
-	const char *name;
+	struct list_head node;
+	struct u300_gpio *gpio;
+	char name[8];
 	int irq;
 	int number;
+	u8 toggle_edge_mode;
 };
 
+/*
+ * Macro to expand to read a specific register found in the "gpio"
+ * struct. It requires the struct u300_gpio *gpio variable to exist in
+ * its context. It calculates the port offset from the given pin
+ * offset, muliplies by the port stride and adds the register offset
+ * so it provides a pointer to the desired register.
+ */
+#define U300_PIN_REG(pin, reg) \
+	(gpio->base + (pin >> 3) * gpio->stride + gpio->reg)
 
-static struct u300_gpio_port gpio_ports[] = {
-	{
-		.name = "gpio0",
-		.number = 0,
-	},
-	{
-		.name = "gpio1",
-		.number = 1,
-	},
-	{
-		.name = "gpio2",
-		.number = 2,
-	},
-#ifdef U300_COH901571_3
-	{
-		.name = "gpio3",
-		.number = 3,
-	},
-	{
-		.name = "gpio4",
-		.number = 4,
-	},
-#ifdef CONFIG_MACH_U300_BS335
-	{
-		.name = "gpio5",
-		.number = 5,
-	},
-	{
-		.name = "gpio6",
-		.number = 6,
-	},
-#endif
-#endif
+/*
+ * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO
+ * register.
+ */
+#define U300_PIN_BIT(pin) \
+	(1 << (pin & 0x07))
 
+struct u300_gpio_confdata {
+	u16 bias_mode;
+	bool output;
+	int outval;
 };
 
+/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */
+#define BS335_GPIO_NUM_PORTS 7
+/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */
+#define BS365_GPIO_NUM_PORTS 5
 
-#ifdef U300_COH901571_3
+#define U300_FLOATING_INPUT { \
+	.bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \
+	.output = false, \
+}
 
-/* Default input value */
-#define DEFAULT_OUTPUT_LOW   0
-#define DEFAULT_OUTPUT_HIGH  1
+#define U300_PULL_UP_INPUT { \
+	.bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \
+	.output = false, \
+}
 
-/* GPIO Pull-Up status */
-#define DISABLE_PULL_UP  0
-#define ENABLE_PULL_UP  1
+#define U300_OUTPUT_LOW { \
+	.output = true, \
+	.outval = 0, \
+}
 
-#define GPIO_NOT_USED 0
-#define GPIO_IN       1
-#define GPIO_OUT      2
+#define U300_OUTPUT_HIGH { \
+	.output = true, \
+	.outval = 1, \
+}
 
-struct u300_gpio_configuration_data {
-	unsigned char pin_usage;
-	unsigned char default_output_value;
-	unsigned char pull_up;
-};
 
 /* Initial configuration */
-const struct u300_gpio_configuration_data
-u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
-#ifdef CONFIG_MACH_U300_BS335
+static const struct __initdata u300_gpio_confdata
+bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
 	/* Port 0, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 1, pins 0-7 */
 	{
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 2, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 3, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 4, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 5, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 6, pind 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	}
-#endif
+};
 
-#ifdef CONFIG_MACH_U300_BS365
+static const struct __initdata u300_gpio_confdata
+bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
 	/* Port 0, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 1, pins 0-7 */
 	{
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 2, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 3, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 4, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 		/* These 4 pins doesn't exist on DB3210 */
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	}
-#endif
-};
-#endif
-
-
-/* No users == we can power down GPIO */
-static int gpio_users;
-
-struct gpio_struct {
-	int (*callback)(void *);
-	void *data;
-	int users;
 };
 
-static struct gpio_struct gpio_pin[U300_GPIO_MAX];
-
-/*
- * Let drivers register callback in order to get notified when there is
- * an interrupt on the gpio pin
+/**
+ * to_u300_gpio() - get the pointer to u300_gpio
+ * @chip: the gpio chip member of the structure u300_gpio
  */
-int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
 {
-	if (gpio_pin[gpio].callback)
-		dev_warn(gpiodev, "%s: WARNING: callback already "
-			 "registered for gpio pin#%d\n", __func__, gpio);
-	gpio_pin[gpio].callback = func;
-	gpio_pin[gpio].data = data;
-
-	return 0;
+	return container_of(chip, struct u300_gpio, chip);
 }
-EXPORT_SYMBOL(gpio_register_callback);
 
-int gpio_unregister_callback(unsigned gpio)
+static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	if (!gpio_pin[gpio].callback)
-		dev_warn(gpiodev, "%s: WARNING: callback already "
-			 "unregistered for gpio pin#%d\n", __func__, gpio);
-	gpio_pin[gpio].callback = NULL;
-	gpio_pin[gpio].data = NULL;
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 
-	return 0;
+	return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset);
 }
-EXPORT_SYMBOL(gpio_unregister_callback);
 
-/* Non-zero means valid */
-int gpio_is_valid(int number)
+static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	if (number >= 0 &&
-	    number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
-		return 1;
-	return 0;
-}
-EXPORT_SYMBOL(gpio_is_valid);
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	unsigned long flags;
+	u32 val;
 
-int gpio_request(unsigned gpio, const char *label)
-{
-	if (gpio_pin[gpio].users)
-		return -EINVAL;
-	else
-		gpio_pin[gpio].users++;
+	local_irq_save(flags);
 
-	gpio_users++;
+	val = readl(U300_PIN_REG(offset, dor));
+	if (value)
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
+	else
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
 
-	return 0;
+	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(gpio_request);
 
-void gpio_free(unsigned gpio)
+static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	gpio_users--;
-	gpio_pin[gpio].users--;
-	if (unlikely(gpio_pin[gpio].users < 0)) {
-		dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
-			 gpio);
-		gpio_pin[gpio].users = 0;
-	}
-
-	return;
-}
-EXPORT_SYMBOL(gpio_free);
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	unsigned long flags;
+	u32 val;
 
-/* This returns zero or nonzero */
-int gpio_get_value(unsigned gpio)
-{
-	return readl(virtbase + U300_GPIO_PXPDIR +
-	  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+	local_irq_save(flags);
+	val = readl(U300_PIN_REG(offset, pcr));
+	/* Mask out this pin, note 2 bits per setting */
+	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
+	writel(val, U300_PIN_REG(offset, pcr));
+	local_irq_restore(flags);
+	return 0;
 }
-EXPORT_SYMBOL(gpio_get_value);
 
-/*
- * We hope that the compiler will optimize away the unused branch
- * in case "value" is a constant
- */
-void gpio_set_value(unsigned gpio, int value)
+static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				      int value)
 {
-	u32 val;
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 	unsigned long flags;
+	u32 oldmode;
+	u32 val;
 
 	local_irq_save(flags);
-	if (value) {
-		/* set */
-		val = readl(virtbase + U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-		  & (1 << (gpio & 0x07));
-		writel(val | (1 << (gpio & 0x07)), virtbase +
-		  U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	} else {
-		/* clear */
-		val = readl(virtbase + U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-		  & (1 << (gpio & 0x07));
-		writel(val & ~(1 << (gpio & 0x07)), virtbase +
-		  U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(offset, pcr));
+	/*
+	 * Drive mode must be set by the special mode set function, set
+	 * push/pull mode by default if no mode has been selected.
+	 */
+	oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK <<
+			 ((offset & 0x07) << 1));
+	/* mode = 0 means input, else some mode is already set */
+	if (oldmode == 0) {
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK <<
+			 ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
 	}
+	u300_gpio_set(chip, offset, value);
 	local_irq_restore(flags);
+	return 0;
 }
-EXPORT_SYMBOL(gpio_set_value);
 
-int gpio_direction_input(unsigned gpio)
+static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	int retirq = gpio->irq_base + offset;
+
+	dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
+		retirq);
+	return retirq;
+}
+
+static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
+		     u16 param, unsigned long *data)
 {
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 	unsigned long flags;
 	u32 val;
 
-	if (gpio > U300_GPIO_MAX)
-		return -EINVAL;
-
 	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask out this pin*/
-	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-	/* This is not needed since it sets the bits to zero.*/
-	/* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
-	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
+	switch (param) {
+	case GPIO_U300_CONFIG_BIAS_UNKNOWN:
+	case GPIO_U300_CONFIG_BIAS_FLOAT:
+		val = readl(U300_PIN_REG(offset, per));
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+		break;
+	case GPIO_U300_CONFIG_BIAS_PULL_UP:
+		val = readl(U300_PIN_REG(offset, per));
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_PUSH_PULL:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	default:
+		local_irq_restore(flags);
+		dev_err(gpio->dev, "illegal configuration requested\n");
+		return -EINVAL;
+	}
 	local_irq_restore(flags);
 	return 0;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-int gpio_direction_output(unsigned gpio, int value)
+static struct gpio_chip u300_gpio_chip = {
+	.label			= "u300-gpio-chip",
+	.owner			= THIS_MODULE,
+	.get			= u300_gpio_get,
+	.set			= u300_gpio_set,
+	.direction_input	= u300_gpio_direction_input,
+	.direction_output	= u300_gpio_direction_output,
+	.to_irq			= u300_gpio_to_irq,
+};
+
+static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
 {
-	unsigned long flags;
 	u32 val;
 
-	if (gpio > U300_GPIO_MAX)
-		return -EINVAL;
-
-	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask out this pin */
-	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-	/*
-	 * FIXME: configure for push/pull, open drain or open source per pin
-	 * in setup. The current driver will only support push/pull.
-	 */
-	val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
-			<< ((gpio & 0x07) << 1));
-	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	gpio_set_value(gpio, value);
-	local_irq_restore(flags);
-	return 0;
+	val = readl(U300_PIN_REG(offset, icr));
+	/* Set mode depending on state */
+	if (u300_gpio_get(&gpio->chip, offset)) {
+		/* High now, let's trigger on falling edge next then */
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n",
+			offset);
+	} else {
+		/* Low now, let's trigger on rising edge next then */
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n",
+			offset);
+	}
 }
-EXPORT_SYMBOL(gpio_direction_output);
 
-/*
- * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
- */
-void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
-	unsigned long flags;
-	local_irq_save(flags);
 
-	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val |= (1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	if (edge)
-		val |= (1 << (gpio & 0x07));
-	else
-		val &= ~(1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	local_irq_restore(flags);
+	if ((trigger & IRQF_TRIGGER_RISING) &&
+	    (trigger & IRQF_TRIGGER_FALLING)) {
+		/*
+		 * The GPIO block can only trigger on falling OR rising edges,
+		 * not both. So we need to toggle the mode whenever the pin
+		 * goes from one state to the other with a special state flag
+		 */
+		dev_dbg(gpio->dev,
+			"trigger on both rising and falling edge on pin %d\n",
+			offset);
+		port->toggle_edge_mode |= U300_PIN_BIT(offset);
+		u300_toggle_trigger(gpio, offset);
+	} else if (trigger & IRQF_TRIGGER_RISING) {
+		dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n",
+			offset);
+		val = readl(U300_PIN_REG(offset, icr));
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+	} else if (trigger & IRQF_TRIGGER_FALLING) {
+		dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n",
+			offset);
+		val = readl(U300_PIN_REG(offset, icr));
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+	}
+
+	return 0;
 }
-EXPORT_SYMBOL(enable_irq_on_gpio_pin);
 
-void disable_irq_on_gpio_pin(unsigned gpio)
+static void u300_gpio_irq_enable(struct irq_data *d)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val &= ~(1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(offset, ien));
+	writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
 	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(disable_irq_on_gpio_pin);
 
-/* Enable (value == 0) or disable (value == 1) internal pullup */
-void gpio_pullup(unsigned gpio, int value)
+static void u300_gpio_irq_disable(struct irq_data *d)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	if (value) {
-		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-					U300_GPIO_PORTX_SPACING);
-		writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	} else {
-		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-					U300_GPIO_PORTX_SPACING);
-		writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	}
+	val = readl(U300_PIN_REG(offset, ien));
+	writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
 	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(gpio_pullup);
 
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+static struct irq_chip u300_gpio_irqchip = {
+	.name			= "u300-gpio-irqchip",
+	.irq_enable		= u300_gpio_irq_enable,
+	.irq_disable		= u300_gpio_irq_disable,
+	.irq_set_type		= u300_gpio_irq_type,
+
+};
+
+static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct u300_gpio_port *port = dev_id;
-	u32 val;
-	int pin;
+	struct u300_gpio_port *port = irq_get_handler_data(irq);
+	struct u300_gpio *gpio = port->gpio;
+	int pinoffset = port->number << 3; /* get the right stride */
+	unsigned long val;
 
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	/* Read event register */
-	val = readl(virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask with enable register */
-	val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(pinoffset, iev));
 	/* Mask relevant bits */
-	val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+	val &= 0xFFU; /* 8 bits per port */
 	/* ACK IRQ (clear event) */
-	writel(val, virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
-	/* Print message */
-	while (val != 0) {
-		unsigned gpio;
+	writel(val, U300_PIN_REG(pinoffset, iev));
 
-		pin = __ffs(val);
-		/* mask off this pin */
-		val &= ~(1 << pin);
-		gpio = (port->number << 3) + pin;
+	/* Call IRQ handler */
+	if (val != 0) {
+		int irqoffset;
 
-		if (gpio_pin[gpio].callback)
-			(void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
-		else
-			dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
-			       gpio);
+		for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
+			int pin_irq = gpio->irq_base + (port->number << 3)
+				+ irqoffset;
+			int offset = pinoffset + irqoffset;
+
+			dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
+				pin_irq, offset);
+			generic_handle_irq(pin_irq);
+			/*
+			 * Triggering IRQ on both rising and falling edge
+			 * needs mockery
+			 */
+			if (port->toggle_edge_mode & U300_PIN_BIT(offset))
+				u300_toggle_trigger(gpio, offset);
+		}
 	}
-	return IRQ_HANDLED;
+
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-static void gpio_set_initial_values(void)
+static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
+				      int offset,
+				      const struct u300_gpio_confdata *conf)
 {
-#ifdef U300_COH901571_3
-	int i, j;
-	unsigned long flags;
-	u32 val;
+	/* Set mode: input or output */
+	if (conf->output) {
+		u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
 
-	/* Write default values to all pins */
-	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-		val = 0;
-		for (j = 0; j < 8; j++)
-			val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
-		local_irq_save(flags);
-		writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
-		local_irq_restore(flags);
+		/* Deactivate bias mode for output */
+		u300_gpio_config(&gpio->chip, offset,
+				 GPIO_U300_CONFIG_BIAS_FLOAT,
+				 NULL);
+
+		/* Set drive mode for output */
+		u300_gpio_config(&gpio->chip, offset,
+				 GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL);
+
+		dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
+			offset, conf->outval);
+	} else {
+		u300_gpio_direction_input(&gpio->chip, offset);
+
+		/* Always set output low on input pins */
+		u300_gpio_set(&gpio->chip, offset, 0);
+
+		/* Set bias mode for input */
+		u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL);
+
+		dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
+			offset, conf->bias_mode);
 	}
+}
 
-	/*
-	 * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
-	 * to output and 'GPIO_IN' to input for each port. And initialize
-	 * default value on outputs.
-	 */
-	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-		for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
-			local_irq_save(flags);
-			val = readl(virtbase + U300_GPIO_PXPCR +
-					 i * U300_GPIO_PORTX_SPACING);
-			/* Mask out this pin */
-			val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
+static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio,
+				     struct u300_gpio_platform *plat)
+{
+	int i, j;
 
-			if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
-				val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
-			writel(val, virtbase + U300_GPIO_PXPCR +
-					 i * U300_GPIO_PORTX_SPACING);
-			local_irq_restore(flags);
+	/* Write default config and values to all pins */
+	for (i = 0; i < plat->ports; i++) {
+		for (j = 0; j < 8; j++) {
+			const struct u300_gpio_confdata *conf;
+			int offset = (i*8) + j;
+
+			if (plat->variant == U300_GPIO_COH901571_3_BS335)
+				conf = &bs335_gpio_config[i][j];
+			else if (plat->variant == U300_GPIO_COH901571_3_BS365)
+				conf = &bs365_gpio_config[i][j];
+			else
+				break;
+
+			u300_gpio_init_pin(gpio, offset, conf);
 		}
 	}
+}
 
-	/* Enable or disable the internal pull-ups in the GPIO ASIC block */
-	for (i = 0; i < U300_GPIO_MAX; i++) {
-		val = 0;
-		for (j = 0; j < 8; j++)
-			val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
-		local_irq_save(flags);
-		writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
-		local_irq_restore(flags);
+static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
+{
+	struct u300_gpio_port *port;
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &gpio->port_list) {
+		port = list_entry(p, struct u300_gpio_port, node);
+		list_del(&port->node);
+		free_irq(port->irq, port);
+		kfree(port);
 	}
-#endif
 }
 
-static int __init gpio_probe(struct platform_device *pdev)
+static int __init u300_gpio_probe(struct platform_device *pdev)
 {
-	u32 val;
+	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+	struct u300_gpio *gpio;
 	int err = 0;
+	int portno;
+	u32 val;
+	u32 ifr;
 	int i;
-	int num_irqs;
 
-	gpiodev = &pdev->dev;
-	memset(gpio_pin, 0, sizeof(gpio_pin));
+	gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
+	if (gpio == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	gpio->chip = u300_gpio_chip;
+	gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
+	gpio->irq_base = plat->gpio_irq_base;
+	gpio->chip.dev = &pdev->dev;
+	gpio->chip.base = plat->gpio_base;
+	gpio->dev = &pdev->dev;
 
 	/* Get GPIO clock */
-	clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
-		err = PTR_ERR(clk);
-		dev_err(gpiodev, "could not get GPIO clock\n");
+	gpio->clk = clk_get(gpio->dev, NULL);
+	if (IS_ERR(gpio->clk)) {
+		err = PTR_ERR(gpio->clk);
+		dev_err(gpio->dev, "could not get GPIO clock\n");
 		goto err_no_clk;
 	}
-	err = clk_enable(clk);
+	err = clk_enable(gpio->clk);
 	if (err) {
-		dev_err(gpiodev, "could not enable GPIO clock\n");
+		dev_err(gpio->dev, "could not enable GPIO clock\n");
 		goto err_no_clk_enable;
 	}
 
-	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!memres)
+	gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!gpio->memres) {
+		dev_err(gpio->dev, "could not get GPIO memory resource\n");
+		err = -ENODEV;
 		goto err_no_resource;
+	}
 
-	if (!request_mem_region(memres->start, resource_size(memres),
+	if (!request_mem_region(gpio->memres->start,
+				resource_size(gpio->memres),
 				"GPIO Controller")) {
 		err = -ENODEV;
 		goto err_no_ioregion;
 	}
 
-	virtbase = ioremap(memres->start, resource_size(memres));
-	if (!virtbase) {
+	gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
+	if (!gpio->base) {
 		err = -ENOMEM;
 		goto err_no_ioremap;
 	}
-	dev_info(gpiodev, "remapped 0x%08x to %p\n",
-		 memres->start, virtbase);
 
-#ifdef U300_COH901335
-	dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
-	/* Turn on the GPIO block */
-	writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
-#endif
+	if (plat->variant == U300_GPIO_COH901335) {
+		dev_info(gpio->dev,
+			 "initializing GPIO Controller COH 901 335\n");
+		gpio->stride = U300_335_PORT_STRIDE;
+		gpio->pcr = U300_335_PXPCR;
+		gpio->dor = U300_335_PXPDOR;
+		gpio->dir = U300_335_PXPDIR;
+		gpio->per = U300_335_PXPER;
+		gpio->icr = U300_335_PXICR;
+		gpio->ien = U300_335_PXIEN;
+		gpio->iev = U300_335_PXIEV;
+		ifr = U300_335_PXIFR;
 
-#ifdef U300_COH901571_3
-	dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
-	val = readl(virtbase + U300_GPIO_CR);
-	dev_info(gpiodev, "COH901571/3 block version: %d, " \
-	       "number of cores: %d\n",
-	       ((val & 0x0000FE00) >> 9),
-	       ((val & 0x000001FC) >> 2));
-	writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
-#endif
+		/* Turn on the GPIO block */
+		writel(U300_335_CR_BLOCK_CLOCK_ENABLE,
+		       gpio->base + U300_335_CR);
+	} else if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+		   plat->variant == U300_GPIO_COH901571_3_BS365) {
+		dev_info(gpio->dev,
+			 "initializing GPIO Controller COH 901 571/3\n");
+		gpio->stride = U300_571_PORT_STRIDE;
+		gpio->pcr = U300_571_PXPCR;
+		gpio->dor = U300_571_PXPDOR;
+		gpio->dir = U300_571_PXPDIR;
+		gpio->per = U300_571_PXPER;
+		gpio->icr = U300_571_PXICR;
+		gpio->ien = U300_571_PXIEN;
+		gpio->iev = U300_571_PXIEV;
+		ifr = U300_571_PXIFR;
 
-	gpio_set_initial_values();
+		val = readl(gpio->base + U300_571_CR);
+		dev_info(gpio->dev, "COH901571/3 block version: %d, " \
+			 "number of cores: %d totalling %d pins\n",
+			 ((val & 0x000001FC) >> 2),
+			 ((val & 0x0000FE00) >> 9),
+			 ((val & 0x0000FE00) >> 9) * 8);
+		writel(U300_571_CR_BLOCK_CLKRQ_ENABLE,
+		       gpio->base + U300_571_CR);
+		u300_gpio_init_coh901571(gpio, plat);
+	} else {
+		dev_err(gpio->dev, "unknown block variant\n");
+		err = -ENODEV;
+		goto err_unknown_variant;
+	}
 
-	for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
+	/* Add each port with its IRQ separately */
+	INIT_LIST_HEAD(&gpio->port_list);
+	for (portno = 0 ; portno < plat->ports; portno++) {
+		struct u300_gpio_port *port =
+			kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL);
 
-		gpio_ports[num_irqs].irq =
-			platform_get_irq_byname(pdev,
-						gpio_ports[num_irqs].name);
+		if (!port) {
+			dev_err(gpio->dev, "out of memory\n");
+			err = -ENOMEM;
+			goto err_no_port;
+		}
 
-		err = request_irq(gpio_ports[num_irqs].irq,
-				  gpio_irq_handler, IRQF_DISABLED,
-				  gpio_ports[num_irqs].name,
-				  &gpio_ports[num_irqs]);
-		if (err) {
-			dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
-				gpio_ports[num_irqs].name);
-			goto err_no_irq;
+		snprintf(port->name, 8, "gpio%d", portno);
+		port->number = portno;
+		port->gpio = gpio;
+
+		port->irq = platform_get_irq_byname(pdev,
+						    port->name);
+
+		dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+			port->name);
+
+		irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
+		irq_set_handler_data(port->irq, port);
+
+		/* For each GPIO pin set the unique IRQ handler */
+		for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
+			int irqno = gpio->irq_base + (portno << 3) + i;
+
+			dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
+				irqno, port->name);
+			irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
+						 handle_simple_irq);
+			set_irq_flags(irqno, IRQF_VALID);
+			irq_set_chip_data(irqno, port);
 		}
-		/* Turns off PortX_irq_force */
-		writel(0x0, virtbase + U300_GPIO_PXIFR +
-				 num_irqs * U300_GPIO_PORTX_SPACING);
+
+		/* Turns off irq force (test register) for this port */
+		writel(0x0, gpio->base + portno * gpio->stride + ifr);
+
+		list_add_tail(&port->node, &gpio->port_list);
+	}
+	dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno);
+
+	err = gpiochip_add(&gpio->chip);
+	if (err) {
+		dev_err(gpio->dev, "unable to add gpiochip: %d\n", err);
+		goto err_no_chip;
 	}
 
+	platform_set_drvdata(pdev, gpio);
+
 	return 0;
 
- err_no_irq:
-	for (i = 0; i < num_irqs; i++)
-		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-	iounmap(virtbase);
- err_no_ioremap:
-	release_mem_region(memres->start, resource_size(memres));
- err_no_ioregion:
- err_no_resource:
-	clk_disable(clk);
- err_no_clk_enable:
-	clk_put(clk);
- err_no_clk:
-	dev_info(gpiodev, "module ERROR:%d\n", err);
+err_no_chip:
+err_no_port:
+	u300_gpio_free_ports(gpio);
+err_unknown_variant:
+	iounmap(gpio->base);
+err_no_ioremap:
+	release_mem_region(gpio->memres->start, resource_size(gpio->memres));
+err_no_ioregion:
+err_no_resource:
+	clk_disable(gpio->clk);
+err_no_clk_enable:
+	clk_put(gpio->clk);
+err_no_clk:
+	kfree(gpio);
+	dev_info(&pdev->dev, "module ERROR:%d\n", err);
 	return err;
 }
 
-static int __exit gpio_remove(struct platform_device *pdev)
+static int __exit u300_gpio_remove(struct platform_device *pdev)
 {
-	int i;
+	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+	struct u300_gpio *gpio = platform_get_drvdata(pdev);
+	int err;
 
 	/* Turn off the GPIO block */
-	writel(0x00000000U, virtbase + U300_GPIO_CR);
-	for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
-		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-	iounmap(virtbase);
-	release_mem_region(memres->start, resource_size(memres));
-	clk_disable(clk);
-	clk_put(clk);
+	if (plat->variant == U300_GPIO_COH901335)
+		writel(0x00000000U, gpio->base + U300_335_CR);
+	if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+	    plat->variant == U300_GPIO_COH901571_3_BS365)
+		writel(0x00000000U, gpio->base + U300_571_CR);
+
+	err = gpiochip_remove(&gpio->chip);
+	if (err < 0) {
+		dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
+		return err;
+	}
+	u300_gpio_free_ports(gpio);
+	iounmap(gpio->base);
+	release_mem_region(gpio->memres->start,
+			   resource_size(gpio->memres));
+	clk_disable(gpio->clk);
+	clk_put(gpio->clk);
+	platform_set_drvdata(pdev, NULL);
+	kfree(gpio);
 	return 0;
 }
 
-static struct platform_driver gpio_driver = {
+static struct platform_driver u300_gpio_driver = {
 	.driver		= {
 		.name	= "u300-gpio",
 	},
-	.remove		= __exit_p(gpio_remove),
+	.remove		= __exit_p(u300_gpio_remove),
 };
 
 
 static int __init u300_gpio_init(void)
 {
-	return platform_driver_probe(&gpio_driver, gpio_probe);
+	return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
 }
 
 static void __exit u300_gpio_exit(void)
 {
-	platform_driver_unregister(&gpio_driver);
+	platform_driver_unregister(&u300_gpio_driver);
 }
 
 arch_initcall(u300_gpio_init);
 module_exit(u300_gpio_exit);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-
-#ifdef U300_COH901571_3
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
-#endif
-
-#ifdef U300_COH901335
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
-#endif
-
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver");
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/gpio-xilinx.c linux-libre-3.2-gnu1/drivers/gpio/gpio-xilinx.c
--- linux-libre-3.1-gnu1/drivers/gpio/gpio-xilinx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/gpio-xilinx.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/Kconfig linux-libre-3.2-gnu1/drivers/gpio/Kconfig
--- linux-libre-3.1-gnu1/drivers/gpio/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -95,14 +95,18 @@ config GPIO_EP93XX
 	depends on ARCH_EP93XX
 	select GPIO_GENERIC
 
-config GPIO_EXYNOS4
-	def_bool y
-	depends on CPU_EXYNOS4210
-
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
 
+config GPIO_MPC8XXX
+	bool "MPC512x/MPC8xxx GPIO support"
+	depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
+		   FSL_SOC_BOOKE || PPC_86xx
+	help
+	  Say Y here if you're going to use hardware that connects to the
+	  MPC512x/831x/834x/837x/8572/8610 GPIOs.
+
 config GPIO_MSM_V1
 	tristate "Qualcomm MSM GPIO v1"
 	depends on GPIOLIB && ARCH_MSM
@@ -131,18 +135,6 @@ config GPIO_MXS
 	select GPIO_GENERIC
 	select GENERIC_IRQ_CHIP
 
-config GPIO_PLAT_SAMSUNG
-	def_bool y
-	depends on SAMSUNG_GPIOLIB_4BIT
-
-config GPIO_S5PC100
-	def_bool y
-	depends on CPU_S5PC100
-
-config GPIO_S5PV210
-	def_bool y
-	depends on CPU_S5PV210
-
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
 	depends on ARM_AMBA
@@ -178,9 +170,18 @@ config GPIO_SCH
 	  The Intel Tunnel Creek processor has 5 GPIOs powered by the
 	  core power rail and 9 from suspend power supply.
 
+config GPIO_U300
+	bool "ST-Ericsson U300 COH 901 335/571 GPIO"
+	depends on GPIOLIB && ARCH_U300
+	help
+	  Say yes here to support GPIO interface on ST-Ericsson U300.
+	  The names of the two IP block variants supported are
+	  COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
+	  ports of 8 GPIO pins each.
+
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
-	depends on MFD_SUPPORT && PCI
+	depends on PCI
 	select MFD_CORE
 	select MFD_VX855
 	help
@@ -388,6 +389,7 @@ config GPIO_LANGWELL
 config GPIO_PCH
 	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
 	depends on PCI && X86
+	select GENERIC_IRQ_CHIP
 	help
 	  This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -402,6 +404,7 @@ config GPIO_PCH
 config GPIO_ML_IOH
 	tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
 	depends on PCI
+	select GENERIC_IRQ_CHIP
 	help
 	  ML7213 is companion chip for Intel Atom E6xx series.
 	  This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
@@ -417,7 +420,6 @@ config GPIO_TIMBERDALE
 config GPIO_RDC321X
 	tristate "RDC R-321x GPIO support"
 	depends on PCI
-	select MFD_SUPPORT
 	select MFD_CORE
 	select MFD_RDC321X
 	help
diff -druNp linux-libre-3.1-gnu1/drivers/gpio/Makefile linux-libre-3.2-gnu1/drivers/gpio/Makefile
--- linux-libre-3.1-gnu1/drivers/gpio/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpio/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,13 @@ obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp55
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
+obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
-obj-$(CONFIG_GPIO_EXYNOS4)	+= gpio-exynos4.o
 obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
+obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
 obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o
+obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
@@ -27,6 +29,7 @@ obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc338
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)	+= gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)	+= gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
@@ -37,18 +40,17 @@ obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca95
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_PLAT_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
-
-obj-$(CONFIG_GPIO_PLAT_SAMSUNG)	+= gpio-plat-samsung.o
-obj-$(CONFIG_GPIO_S5PC100)	+= gpio-s5pc100.o
-obj-$(CONFIG_GPIO_S5PV210)	+= gpio-s5pv210.o
-
+obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
+obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/ati_pcigart.c linux-libre-3.2-gnu1/drivers/gpu/drm/ati_pcigart.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/ati_pcigart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/ati_pcigart.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 # define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_buffer.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_buffer.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_buffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
  * Pauli Nieminen <suokkos-at-gmail-dot-com>
  */
 
+#include <linux/export.h>
 #include "drm_buffer.h"
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_bufs.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_bufs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_bufs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_bufs.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/log2.h>
+#include <linux/export.h>
 #include <asm/shmparam.h>
 #include "drmP.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_cache.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_cache.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_cache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  * Authors: Thomas HellstrÃ¶m <thomas-at-tungstengraphics-dot-com>
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 #if defined(CONFIG_X86)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_crtc.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_crtc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  */
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drm.h"
 #include "drmP.h"
 #include "drm_crtc.h"
@@ -162,6 +163,7 @@ static struct drm_conn_prop_enum_list dr
 	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
 	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
 	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -170,6 +172,7 @@ static struct drm_prop_enum_list drm_enc
 	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
 	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
 	{ DRM_MODE_ENCODER_TVDAC, "TV" },
+	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 };
 
 char *drm_get_encoder_name(struct drm_encoder *encoder)
@@ -463,8 +466,10 @@ void drm_connector_init(struct drm_devic
 	list_add_tail(&connector->head, &dev->mode_config.connector_list);
 	dev->mode_config.num_connector++;
 
-	drm_connector_attach_property(connector,
-				      dev->mode_config.edid_property, 0);
+	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+		drm_connector_attach_property(connector,
+					      dev->mode_config.edid_property,
+					      0);
 
 	drm_connector_attach_property(connector,
 				      dev->mode_config.dpms_property, 0);
@@ -1868,6 +1873,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_de
 	}
 
 	if (num_clips && clips_ptr) {
+		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+			ret = -EINVAL;
+			goto out_err1;
+		}
 		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
 		if (!clips) {
 			ret = -ENOMEM;
@@ -2113,8 +2122,10 @@ struct drm_property *drm_property_create
 	property->num_values = num_values;
 	INIT_LIST_HEAD(&property->enum_blob_list);
 
-	if (name)
+	if (name) {
 		strncpy(property->name, name, DRM_PROP_NAME_LEN);
+		property->name[DRM_PROP_NAME_LEN-1] = '\0';
+	}
 
 	list_add_tail(&property->head, &dev->mode_config.property_list);
 	return property;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_crtc_helper.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_crtc_helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_crtc_helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
 
+#include <linux/export.h>
+#include <linux/moduleparam.h>
+
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
@@ -372,11 +375,13 @@ bool drm_crtc_helper_set_mode(struct drm
 		encoder_funcs = encoder->helper_private;
 		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
 						      adjusted_mode))) {
+			DRM_DEBUG_KMS("Encoder fixup failed\n");
 			goto done;
 		}
 	}
 
 	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+		DRM_DEBUG_KMS("CRTC fixup failed\n");
 		goto done;
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
@@ -451,6 +456,30 @@ done:
 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
 
 
+static int
+drm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	/* Decouple all encoders and their attached connectors from this crtc */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc != crtc)
+			continue;
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			connector->encoder = NULL;
+		}
+	}
+
+	drm_helper_disable_unused_functions(dev);
+	return 0;
+}
+
 /**
  * drm_crtc_helper_set_config - set a new config from userspace
  * @crtc: CRTC to setup
@@ -479,6 +508,7 @@ int drm_crtc_helper_set_config(struct dr
 	struct drm_connector *save_connectors, *connector;
 	int count = 0, ro, fail = 0;
 	struct drm_crtc_helper_funcs *crtc_funcs;
+	struct drm_mode_set save_set;
 	int ret = 0;
 	int i;
 
@@ -504,8 +534,7 @@ int drm_crtc_helper_set_config(struct dr
 				(int)set->num_connectors, set->x, set->y);
 	} else {
 		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-		set->mode = NULL;
-		set->num_connectors = 0;
+		return drm_crtc_helper_disable(set->crtc);
 	}
 
 	dev = set->crtc->dev;
@@ -551,6 +580,12 @@ int drm_crtc_helper_set_config(struct dr
 		save_connectors[count++] = *connector;
 	}
 
+	save_set.crtc = set->crtc;
+	save_set.mode = &set->crtc->mode;
+	save_set.x = set->crtc->x;
+	save_set.y = set->crtc->y;
+	save_set.fb = set->crtc->fb;
+
 	/* We should be able to check here if the fb has the same properties
 	 * and then just flip_or_move it */
 	if (set->crtc->fb != set->fb) {
@@ -716,6 +751,12 @@ fail:
 		*connector = save_connectors[count++];
 	}
 
+	/* Try to restore the config */
+	if (mode_changed &&
+	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+				      save_set.y, save_set.fb))
+		DRM_ERROR("failed to restore config after modeset failure\n");
+
 	kfree(save_connectors);
 	kfree(save_encoders);
 	kfree(save_crtcs);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_debugfs.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_debugfs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 #if defined(CONFIG_DEBUG_FS)
@@ -107,11 +108,8 @@ int drm_debugfs_create_files(struct drm_
 		ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
 					  root, tmp, &drm_debugfs_fops);
 		if (!ent) {
-			char name[64];
-			strncpy(name, root->d_name.name,
-						min(root->d_name.len, 64U));
 			DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
-				  name, files[i].name);
+				  root->d_name.name, files[i].name);
 			kfree(tmp);
 			ret = -1;
 			goto fail;
@@ -120,7 +118,10 @@ int drm_debugfs_create_files(struct drm_
 		tmp->minor = minor;
 		tmp->dent = ent;
 		tmp->info_ent = &files[i];
-		list_add(&(tmp->list), &(minor->debugfs_nodes.list));
+
+		mutex_lock(&minor->debugfs_lock);
+		list_add(&tmp->list, &minor->debugfs_list);
+		mutex_unlock(&minor->debugfs_lock);
 	}
 	return 0;
 
@@ -148,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *m
 	char name[64];
 	int ret;
 
-	INIT_LIST_HEAD(&minor->debugfs_nodes.list);
+	INIT_LIST_HEAD(&minor->debugfs_list);
+	mutex_init(&minor->debugfs_lock);
 	sprintf(name, "%d", minor_id);
 	minor->debugfs_root = debugfs_create_dir(name, root);
 	if (!minor->debugfs_root) {
@@ -194,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_
 	struct drm_info_node *tmp;
 	int i;
 
+	mutex_lock(&minor->debugfs_lock);
 	for (i = 0; i < count; i++) {
-		list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
+		list_for_each_safe(pos, q, &minor->debugfs_list) {
 			tmp = list_entry(pos, struct drm_info_node, list);
 			if (tmp->info_ent == &files[i]) {
 				debugfs_remove(tmp->dent);
@@ -204,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_
 			}
 		}
 	}
+	mutex_unlock(&minor->debugfs_lock);
 	return 0;
 }
 EXPORT_SYMBOL(drm_debugfs_remove_files);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_dma.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_dma.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm_core.h"
 
@@ -124,7 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
 
@@ -438,6 +439,8 @@ long drm_ioctl(struct file *filp,
 					goto err_i1;
 				}
 			}
+			if (asize > usize)
+				memset(kdata + usize, 0, asize - usize);
 		}
 
 		if (cmd & IOC_IN) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_edid.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_edid.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_edid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_edid.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm_edid.h"
 #include "drm_edid_modes.h"
@@ -1319,6 +1320,7 @@ add_detailed_modes(struct drm_connector
 #define HDMI_IDENTIFIER 0x000C03
 #define AUDIO_BLOCK	0x01
 #define VENDOR_BLOCK    0x03
+#define SPEAKER_BLOCK	0x04
 #define EDID_BASIC_AUDIO	(1 << 6)
 
 /**
@@ -1347,6 +1349,176 @@ u8 *drm_find_cea_extension(struct edid *
 }
 EXPORT_SYMBOL(drm_find_cea_extension);
 
+static void
+parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
+{
+	connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
+
+	connector->dvi_dual = db[6] & 1;
+	connector->max_tmds_clock = db[7] * 5;
+
+	connector->latency_present[0] = db[8] >> 7;
+	connector->latency_present[1] = (db[8] >> 6) & 1;
+	connector->video_latency[0] = db[9];
+	connector->audio_latency[0] = db[10];
+	connector->video_latency[1] = db[11];
+	connector->audio_latency[1] = db[12];
+
+	DRM_LOG_KMS("HDMI: DVI dual %d, "
+		    "max TMDS clock %d, "
+		    "latency present %d %d, "
+		    "video latency %d %d, "
+		    "audio latency %d %d\n",
+		    connector->dvi_dual,
+		    connector->max_tmds_clock,
+	      (int) connector->latency_present[0],
+	      (int) connector->latency_present[1],
+		    connector->video_latency[0],
+		    connector->video_latency[1],
+		    connector->audio_latency[0],
+		    connector->audio_latency[1]);
+}
+
+static void
+monitor_name(struct detailed_timing *t, void *data)
+{
+	if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
+		*(u8 **)data = t->data.other_data.data.str.str;
+}
+
+/**
+ * drm_edid_to_eld - build ELD from EDID
+ * @connector: connector corresponding to the HDMI/DP sink
+ * @edid: EDID to parse
+ *
+ * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
+ * Some ELD fields are left to the graphics driver caller:
+ * - Conn_Type
+ * - HDCP
+ * - Port_ID
+ */
+void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
+{
+	uint8_t *eld = connector->eld;
+	u8 *cea;
+	u8 *name;
+	u8 *db;
+	int sad_count = 0;
+	int mnl;
+	int dbl;
+
+	memset(eld, 0, sizeof(connector->eld));
+
+	cea = drm_find_cea_extension(edid);
+	if (!cea) {
+		DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
+		return;
+	}
+
+	name = NULL;
+	drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
+	for (mnl = 0; name && mnl < 13; mnl++) {
+		if (name[mnl] == 0x0a)
+			break;
+		eld[20 + mnl] = name[mnl];
+	}
+	eld[4] = (cea[1] << 5) | mnl;
+	DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
+
+	eld[0] = 2 << 3;		/* ELD version: 2 */
+
+	eld[16] = edid->mfg_id[0];
+	eld[17] = edid->mfg_id[1];
+	eld[18] = edid->prod_code[0];
+	eld[19] = edid->prod_code[1];
+
+	for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
+		dbl = db[0] & 0x1f;
+
+		switch ((db[0] & 0xe0) >> 5) {
+		case AUDIO_BLOCK:	/* Audio Data Block, contains SADs */
+			sad_count = dbl / 3;
+			memcpy(eld + 20 + mnl, &db[1], dbl);
+			break;
+		case SPEAKER_BLOCK:	/* Speaker Allocation Data Block */
+			eld[7] = db[1];
+			break;
+		case VENDOR_BLOCK:
+			/* HDMI Vendor-Specific Data Block */
+			if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
+				parse_hdmi_vsdb(connector, db);
+			break;
+		default:
+			break;
+		}
+	}
+	eld[5] |= sad_count << 4;
+	eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
+
+	DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
+}
+EXPORT_SYMBOL(drm_edid_to_eld);
+
+/**
+ * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
+ * @connector: connector associated with the HDMI/DP sink
+ * @mode: the display mode
+ */
+int drm_av_sync_delay(struct drm_connector *connector,
+		      struct drm_display_mode *mode)
+{
+	int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	int a, v;
+
+	if (!connector->latency_present[0])
+		return 0;
+	if (!connector->latency_present[1])
+		i = 0;
+
+	a = connector->audio_latency[i];
+	v = connector->video_latency[i];
+
+	/*
+	 * HDMI/DP sink doesn't support audio or video?
+	 */
+	if (a == 255 || v == 255)
+		return 0;
+
+	/*
+	 * Convert raw EDID values to millisecond.
+	 * Treat unknown latency as 0ms.
+	 */
+	if (a)
+		a = min(2 * (a - 1), 500);
+	if (v)
+		v = min(2 * (v - 1), 500);
+
+	return max(v - a, 0);
+}
+EXPORT_SYMBOL(drm_av_sync_delay);
+
+/**
+ * drm_select_eld - select one ELD from multiple HDMI/DP sinks
+ * @encoder: the encoder just changed display mode
+ * @mode: the adjusted display mode
+ *
+ * It's possible for one encoder to be associated with multiple HDMI/DP sinks.
+ * The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
+ */
+struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode)
+{
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		if (connector->encoder == encoder && connector->eld[0])
+			return connector;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_select_eld);
+
 /**
  * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
  * @edid: monitor EDID information
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_encoder_slave.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_encoder_slave.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_encoder_slave.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_encoder_slave.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drm_encoder_slave.h"
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_fb_helper.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_fb_helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_fb_helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/sysrq.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_fb_helper.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_fops.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_fops.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_fops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_fops.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include "drmP.h"
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 /* from BKL pushdown: note that nothing else serializes idr_find() */
 DEFINE_MUTEX(drm_global_mutex);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_gem.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_gem.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_gem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -285,6 +285,94 @@ again:
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
 
+
+/**
+ * drm_gem_free_mmap_offset - release a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * This routine frees fake offsets allocated by drm_gem_create_mmap_offset().
+ */
+void
+drm_gem_free_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list = &obj->map_list;
+
+	drm_ht_remove_item(&mm->offset_hash, &list->hash);
+	drm_mm_put_block(list->file_offset_node);
+	kfree(list->map);
+	list->map = NULL;
+}
+EXPORT_SYMBOL(drm_gem_free_mmap_offset);
+
+/**
+ * drm_gem_create_mmap_offset - create a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * GEM memory mapping works by handing back to userspace a fake mmap offset
+ * it can use in a subsequent mmap(2) call.  The DRM core code then looks
+ * up the object based on the offset and sets up the various memory mapping
+ * structures.
+ *
+ * This routine allocates and attaches a fake offset for @obj.
+ */
+int
+drm_gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list;
+	struct drm_local_map *map;
+	int ret = 0;
+
+	/* Set the object up for mmap'ing */
+	list = &obj->map_list;
+	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+	if (!list->map)
+		return -ENOMEM;
+
+	map = list->map;
+	map->type = _DRM_GEM;
+	map->size = obj->size;
+	map->handle = obj;
+
+	/* Get a DRM GEM mmap offset allocated... */
+	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+			obj->size / PAGE_SIZE, 0, 0);
+
+	if (!list->file_offset_node) {
+		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+		ret = -ENOSPC;
+		goto out_free_list;
+	}
+
+	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+			obj->size / PAGE_SIZE, 0);
+	if (!list->file_offset_node) {
+		ret = -ENOMEM;
+		goto out_free_list;
+	}
+
+	list->hash.key = list->file_offset_node->start;
+	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+	if (ret) {
+		DRM_ERROR("failed to add to map hash\n");
+		goto out_free_mm;
+	}
+
+	return 0;
+
+out_free_mm:
+	drm_mm_put_block(list->file_offset_node);
+out_free_list:
+	kfree(list->map);
+	list->map = NULL;
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_gem_create_mmap_offset);
+
 /** Returns a reference to the object named by the handle. */
 struct drm_gem_object *
 drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_hashtab.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_hashtab.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_hashtab.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_hashtab.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include "drm_hashtab.h"
 #include <linux/hash.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_ioc32.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_ioc32.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_ioc32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_ioc32.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
  */
 #include <linux/compat.h>
 #include <linux/ratelimit.h>
+#include <linux/export.h>
 
 #include "drmP.h"
 #include "drm_core.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_irq.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_irq.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 
 #include <linux/vgaarb.h>
+#include <linux/export.h>
 
 /* Access macro for slots in vblank timestamp ringbuffer. */
 #define vblanktimestamp(dev, crtc, count) ( \
@@ -109,10 +110,7 @@ static void vblank_disable_and_save(stru
 	/* Prevent vblank irq processing while disabling vblank irqs,
 	 * so no updates of timestamps or count can happen after we've
 	 * disabled. Needed to prevent races in case of delayed irq's.
-	 * Disable preemption, so vblank_time_lock is held as short as
-	 * possible, even under a kernel with PREEMPT_RT patches.
 	 */
-	preempt_disable();
 	spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
 
 	dev->driver->disable_vblank(dev, crtc);
@@ -163,7 +161,6 @@ static void vblank_disable_and_save(stru
 	clear_vblank_timestamps(dev, crtc);
 
 	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-	preempt_enable();
 }
 
 static void vblank_disable_fn(unsigned long arg)
@@ -406,13 +403,16 @@ int drm_irq_uninstall(struct drm_device
 	/*
 	 * Wake up any waiters so they don't hang.
 	 */
-	spin_lock_irqsave(&dev->vbl_lock, irqflags);
-	for (i = 0; i < dev->num_crtcs; i++) {
-		DRM_WAKEUP(&dev->vbl_queue[i]);
-		dev->vblank_enabled[i] = 0;
-		dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
+	if (dev->num_crtcs) {
+		spin_lock_irqsave(&dev->vbl_lock, irqflags);
+		for (i = 0; i < dev->num_crtcs; i++) {
+			DRM_WAKEUP(&dev->vbl_queue[i]);
+			dev->vblank_enabled[i] = 0;
+			dev->last_vblank[i] =
+				dev->driver->get_vblank_counter(dev, i);
+		}
+		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 	}
-	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
 	if (!irq_enabled)
 		return -EINVAL;
@@ -885,10 +885,6 @@ int drm_vblank_get(struct drm_device *de
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	/* Going from 0->1 means we have to enable interrupts again */
 	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
-		/* Disable preemption while holding vblank_time_lock. Do
-		 * it explicitely to guard against PREEMPT_RT kernel.
-		 */
-		preempt_disable();
 		spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
 		if (!dev->vblank_enabled[crtc]) {
 			/* Enable vblank irqs under vblank_time_lock protection.
@@ -908,7 +904,6 @@ int drm_vblank_get(struct drm_device *de
 			}
 		}
 		spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
-		preempt_enable();
 	} else {
 		if (!dev->vblank_enabled[crtc]) {
 			atomic_dec(&dev->vblank_refcount[crtc]);
@@ -1124,6 +1119,7 @@ static int drm_queue_vblank_event(struct
 		trace_drm_vblank_event_delivered(current->pid, pipe,
 						 vblwait->request.sequence);
 	} else {
+		/* drm_handle_vblank_events will call drm_vblank_put */
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
 		vblwait->reply.sequence = vblwait->request.sequence;
 	}
@@ -1204,8 +1200,12 @@ int drm_wait_vblank(struct drm_device *d
 		goto done;
 	}
 
-	if (flags & _DRM_VBLANK_EVENT)
+	if (flags & _DRM_VBLANK_EVENT) {
+		/* must hold on to the vblank ref until the event fires
+		 * drm_vblank_put will be called asynchronously
+		 */
 		return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+	}
 
 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
 	    (seq - vblwait->request.sequence) <= (1<<23)) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_memory.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_memory.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_memory.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_memory.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include <linux/highmem.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_mm.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_mm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include "drm_mm.h"
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 
 #define MM_UNUSED_TARGET 4
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_modes.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_modes.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_modes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_modes.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #include <linux/list.h>
 #include <linux/list_sort.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_pci.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_pci.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /**********************************************************************/
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_platform.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_platform.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_proc.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_proc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /***************************************************
@@ -95,7 +96,6 @@ int drm_proc_create_files(struct drm_inf
 	struct drm_device *dev = minor->dev;
 	struct proc_dir_entry *ent;
 	struct drm_info_node *tmp;
-	char name[64];
 	int i, ret;
 
 	for (i = 0; i < count; i++) {
@@ -118,7 +118,7 @@ int drm_proc_create_files(struct drm_inf
 				       &drm_proc_fops, tmp);
 		if (!ent) {
 			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-				  name, files[i].name);
+				  root->name, files[i].name);
 			list_del(&tmp->list);
 			kfree(tmp);
 			ret = -1;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_sman.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_sman.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_sman.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_sman.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
  * Thomas HellstrÃ¶m <thomas-at-tungstengraphics-dot-com>
  */
 
+#include <linux/export.h>
 #include "drm_sman.h"
 
 struct drm_owner_item {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_sysfs.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/kdev_t.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include "drm_sysfs.h"
 #include "drm_core.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_usb.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_usb.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include "drmP.h"
 #include <linux/usb.h>
+#include <linux/export.h>
 
 #ifdef CONFIG_USB
 int drm_get_usb_dev(struct usb_interface *interface,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/drm_vm.c linux-libre-3.2-gnu1/drivers/gpu/drm/drm_vm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/drm_vm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/drm_vm.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include "drmP.h"
+#include <linux/export.h>
 #if defined(__ia64__)
 #include <linux/efi.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/* exynos_drm_buf.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+static int lowlevel_buffer_allocate(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size,
+			&buffer->dma_addr, GFP_KERNEL);
+	if (!buffer->kvaddr) {
+		DRM_ERROR("failed to allocate buffer.\n");
+		return -ENOMEM;
+	}
+
+	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
+			(unsigned long)buffer->kvaddr,
+			(unsigned long)buffer->dma_addr,
+			buffer->size);
+
+	return 0;
+}
+
+static void lowlevel_buffer_deallocate(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+	if (buffer->dma_addr && buffer->size)
+		dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr,
+				(dma_addr_t)buffer->dma_addr);
+	else
+		DRM_DEBUG_KMS("buffer data are invalid.\n");
+}
+
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
+		unsigned int size)
+{
+	struct exynos_drm_gem_buf *buffer;
+
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+	DRM_DEBUG_KMS("desired size = 0x%x\n", size);
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer) {
+		DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	buffer->size = size;
+
+	/*
+	 * allocate memory region with size and set the memory information
+	 * to vaddr and dma_addr of a buffer object.
+	 */
+	if (lowlevel_buffer_allocate(dev, buffer) < 0) {
+		kfree(buffer);
+		buffer = NULL;
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return buffer;
+}
+
+void exynos_drm_buf_destroy(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+	if (!buffer) {
+		DRM_DEBUG_KMS("buffer is null.\n");
+		return;
+	}
+
+	lowlevel_buffer_deallocate(dev, buffer);
+
+	kfree(buffer);
+	buffer = NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_buf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/* exynos_drm_buf.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_BUF_H_
+#define _EXYNOS_DRM_BUF_H_
+
+/* allocate physical memory. */
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
+		unsigned int size);
+
+/* get memory information of a drm framebuffer. */
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
+
+/* remove allocated physical memory. */
+void exynos_drm_buf_destroy(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+
+#define MAX_EDID 256
+#define to_exynos_connector(x)	container_of(x, struct exynos_drm_connector,\
+				drm_connector)
+
+struct exynos_drm_connector {
+	struct drm_connector	drm_connector;
+	uint32_t		encoder_id;
+	struct exynos_drm_manager *manager;
+};
+
+/* convert exynos_video_timings to drm_display_mode */
+static inline void
+convert_to_display_mode(struct drm_display_mode *mode,
+			struct fb_videomode *timing)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode->clock = timing->pixclock / 1000;
+	mode->vrefresh = timing->refresh;
+
+	mode->hdisplay = timing->xres;
+	mode->hsync_start = mode->hdisplay + timing->left_margin;
+	mode->hsync_end = mode->hsync_start + timing->hsync_len;
+	mode->htotal = mode->hsync_end + timing->right_margin;
+
+	mode->vdisplay = timing->yres;
+	mode->vsync_start = mode->vdisplay + timing->upper_margin;
+	mode->vsync_end = mode->vsync_start + timing->vsync_len;
+	mode->vtotal = mode->vsync_end + timing->lower_margin;
+
+	if (timing->vmode & FB_VMODE_INTERLACED)
+		mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+	if (timing->vmode & FB_VMODE_DOUBLE)
+		mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+}
+
+/* convert drm_display_mode to exynos_video_timings */
+static inline void
+convert_to_video_timing(struct fb_videomode *timing,
+			struct drm_display_mode *mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	memset(timing, 0, sizeof(*timing));
+
+	timing->pixclock = mode->clock * 1000;
+	timing->refresh = drm_mode_vrefresh(mode);
+
+	timing->xres = mode->hdisplay;
+	timing->left_margin = mode->hsync_start - mode->hdisplay;
+	timing->hsync_len = mode->hsync_end - mode->hsync_start;
+	timing->right_margin = mode->htotal - mode->hsync_end;
+
+	timing->yres = mode->vdisplay;
+	timing->upper_margin = mode->vsync_start - mode->vdisplay;
+	timing->vsync_len = mode->vsync_end - mode->vsync_start;
+	timing->lower_margin = mode->vtotal - mode->vsync_end;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		timing->vmode = FB_VMODE_INTERLACED;
+	else
+		timing->vmode = FB_VMODE_NONINTERLACED;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		timing->vmode |= FB_VMODE_DOUBLE;
+}
+
+static int exynos_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	unsigned int count;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!display_ops) {
+		DRM_DEBUG_KMS("display_ops is null.\n");
+		return 0;
+	}
+
+	/*
+	 * if get_edid() exists then get_edid() callback of hdmi side
+	 * is called to get edid data through i2c interface else
+	 * get timing from the FIMD driver(display controller).
+	 *
+	 * P.S. in case of lcd panel, count is always 1 if success
+	 * because lcd panel has only one mode.
+	 */
+	if (display_ops->get_edid) {
+		int ret;
+		void *edid;
+
+		edid = kzalloc(MAX_EDID, GFP_KERNEL);
+		if (!edid) {
+			DRM_ERROR("failed to allocate edid\n");
+			return 0;
+		}
+
+		ret = display_ops->get_edid(manager->dev, connector,
+						edid, MAX_EDID);
+		if (ret < 0) {
+			DRM_ERROR("failed to get edid data.\n");
+			kfree(edid);
+			edid = NULL;
+			return 0;
+		}
+
+		drm_mode_connector_update_edid_property(connector, edid);
+		count = drm_add_edid_modes(connector, edid);
+
+		kfree(connector->display_info.raw_edid);
+		connector->display_info.raw_edid = edid;
+	} else {
+		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		struct fb_videomode *timing;
+
+		if (display_ops->get_timing)
+			timing = display_ops->get_timing(manager->dev);
+		else {
+			drm_mode_destroy(connector->dev, mode);
+			return 0;
+		}
+
+		convert_to_display_mode(mode, timing);
+
+		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+		drm_mode_set_name(mode);
+		drm_mode_probed_add(connector, mode);
+
+		count = 1;
+	}
+
+	return count;
+}
+
+static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
+					    struct drm_display_mode *mode)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	struct fb_videomode timing;
+	int ret = MODE_BAD;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	convert_to_video_timing(&timing, mode);
+
+	if (display_ops && display_ops->check_timing)
+		if (!display_ops->check_timing(manager->dev, (void *)&timing))
+			ret = MODE_OK;
+
+	return ret;
+}
+
+struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
+				   DRM_MODE_OBJECT_ENCODER);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
+				exynos_connector->encoder_id);
+		return NULL;
+	}
+
+	encoder = obj_to_encoder(obj);
+
+	return encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
+	.get_modes	= exynos_drm_connector_get_modes,
+	.mode_valid	= exynos_drm_connector_mode_valid,
+	.best_encoder	= exynos_drm_best_encoder,
+};
+
+/* get detection status of display device. */
+static enum drm_connector_status
+exynos_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops =
+					manager->display_ops;
+	enum drm_connector_status status = connector_status_disconnected;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (display_ops && display_ops->is_connected) {
+		if (display_ops->is_connected(manager->dev))
+			status = connector_status_connected;
+		else
+			status = connector_status_disconnected;
+	}
+
+	return status;
+}
+
+static void exynos_drm_connector_destroy(struct drm_connector *connector)
+{
+	struct exynos_drm_connector *exynos_connector =
+		to_exynos_connector(connector);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(exynos_connector);
+}
+
+static struct drm_connector_funcs exynos_connector_funcs = {
+	.dpms		= drm_helper_connector_dpms,
+	.fill_modes	= drm_helper_probe_single_connector_modes,
+	.detect		= exynos_drm_connector_detect,
+	.destroy	= exynos_drm_connector_destroy,
+};
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+						   struct drm_encoder *encoder)
+{
+	struct exynos_drm_connector *exynos_connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct drm_connector *connector;
+	int type;
+	int err;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
+	if (!exynos_connector) {
+		DRM_ERROR("failed to allocate connector\n");
+		return NULL;
+	}
+
+	connector = &exynos_connector->drm_connector;
+
+	switch (manager->display_ops->type) {
+	case EXYNOS_DISPLAY_TYPE_HDMI:
+		type = DRM_MODE_CONNECTOR_HDMIA;
+		connector->interlace_allowed = true;
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	default:
+		type = DRM_MODE_CONNECTOR_Unknown;
+		break;
+	}
+
+	drm_connector_init(dev, connector, &exynos_connector_funcs, type);
+	drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
+
+	err = drm_sysfs_connector_add(connector);
+	if (err)
+		goto err_connector;
+
+	exynos_connector->encoder_id = encoder->base.id;
+	exynos_connector->manager = manager;
+	connector->encoder = encoder;
+
+	err = drm_mode_connector_attach_encoder(connector, encoder);
+	if (err) {
+		DRM_ERROR("failed to attach a connector to a encoder\n");
+		goto err_sysfs;
+	}
+
+	DRM_DEBUG_KMS("connector has been created\n");
+
+	return connector;
+
+err_sysfs:
+	drm_sysfs_connector_remove(connector);
+err_connector:
+	drm_connector_cleanup(connector);
+	kfree(exynos_connector);
+	return NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_connector.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_CONNECTOR_H_
+#define _EXYNOS_DRM_CONNECTOR_H_
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+						   struct drm_encoder *encoder);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_core.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_core.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,272 @@
+/* exynos_drm_core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_connector.h"
+#include "exynos_drm_fbdev.h"
+
+static DEFINE_MUTEX(exynos_drm_mutex);
+static LIST_HEAD(exynos_drm_subdrv_list);
+static struct drm_device *drm_dev;
+
+static int exynos_drm_subdrv_probe(struct drm_device *dev,
+					struct exynos_drm_subdrv *subdrv)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (subdrv->probe) {
+		int ret;
+
+		/*
+		 * this probe callback would be called by sub driver
+		 * after setting of all resources to this sub driver,
+		 * such as clock, irq and register map are done or by load()
+		 * of exynos drm driver.
+		 *
+		 * P.S. note that this driver is considered for modularization.
+		 */
+		ret = subdrv->probe(dev, subdrv->manager.dev);
+		if (ret)
+			return ret;
+	}
+
+	/* create and initialize a encoder for this sub driver. */
+	encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
+			(1 << MAX_CRTC) - 1);
+	if (!encoder) {
+		DRM_ERROR("failed to create encoder\n");
+		return -EFAULT;
+	}
+
+	/*
+	 * create and initialize a connector for this sub driver and
+	 * attach the encoder created above to the connector.
+	 */
+	connector = exynos_drm_connector_create(dev, encoder);
+	if (!connector) {
+		DRM_ERROR("failed to create connector\n");
+		encoder->funcs->destroy(encoder);
+		return -EFAULT;
+	}
+
+	subdrv->encoder = encoder;
+	subdrv->connector = connector;
+
+	return 0;
+}
+
+static void exynos_drm_subdrv_remove(struct drm_device *dev,
+				      struct exynos_drm_subdrv *subdrv)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (subdrv->remove)
+		subdrv->remove(dev);
+
+	if (subdrv->encoder) {
+		struct drm_encoder *encoder = subdrv->encoder;
+		encoder->funcs->destroy(encoder);
+		subdrv->encoder = NULL;
+	}
+
+	if (subdrv->connector) {
+		struct drm_connector *connector = subdrv->connector;
+		connector->funcs->destroy(connector);
+		subdrv->connector = NULL;
+	}
+}
+
+int exynos_drm_device_register(struct drm_device *dev)
+{
+	struct exynos_drm_subdrv *subdrv, *n;
+	int err;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!dev)
+		return -EINVAL;
+
+	if (drm_dev) {
+		DRM_ERROR("Already drm device were registered\n");
+		return -EBUSY;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
+		err = exynos_drm_subdrv_probe(dev, subdrv);
+		if (err) {
+			DRM_DEBUG("exynos drm subdrv probe failed.\n");
+			list_del(&subdrv->list);
+		}
+	}
+
+	drm_dev = dev;
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_register);
+
+int exynos_drm_device_unregister(struct drm_device *dev)
+{
+	struct exynos_drm_subdrv *subdrv;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!dev || dev != drm_dev) {
+		WARN(1, "Unexpected drm device unregister!\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
+		exynos_drm_subdrv_remove(dev, subdrv);
+
+	drm_dev = NULL;
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
+
+static int exynos_drm_mode_group_reinit(struct drm_device *dev)
+{
+	struct drm_mode_group *group = &dev->primary->mode_group;
+	uint32_t *id_list = group->id_list;
+	int ret;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	ret = drm_mode_group_init_legacy_group(dev, group);
+	if (ret < 0)
+		return ret;
+
+	kfree(id_list);
+	return 0;
+}
+
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
+{
+	int err;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!subdrv)
+		return -EINVAL;
+
+	mutex_lock(&exynos_drm_mutex);
+	if (drm_dev) {
+		err = exynos_drm_subdrv_probe(drm_dev, subdrv);
+		if (err) {
+			DRM_ERROR("failed to probe exynos drm subdrv\n");
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+
+		/*
+		 * if any specific driver such as fimd or hdmi driver called
+		 * exynos_drm_subdrv_register() later than drm_load(),
+		 * the fb helper should be re-initialized and re-configured.
+		 */
+		err = exynos_drm_fbdev_reinit(drm_dev);
+		if (err) {
+			DRM_ERROR("failed to reinitialize exynos drm fbdev\n");
+			exynos_drm_subdrv_remove(drm_dev, subdrv);
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+
+		err = exynos_drm_mode_group_reinit(drm_dev);
+		if (err) {
+			DRM_ERROR("failed to reinitialize mode group\n");
+			exynos_drm_fbdev_fini(drm_dev);
+			exynos_drm_subdrv_remove(drm_dev, subdrv);
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+	}
+
+	subdrv->drm_dev = drm_dev;
+
+	list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
+
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
+{
+	int ret = -EFAULT;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!subdrv) {
+		DRM_DEBUG("Unexpected exynos drm subdrv unregister!\n");
+		return ret;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	if (drm_dev) {
+		exynos_drm_subdrv_remove(drm_dev, subdrv);
+		list_del(&subdrv->list);
+
+		/*
+		 * fb helper should be updated once a sub driver is released
+		 * to re-configure crtc and connector and also to re-setup
+		 * drm framebuffer.
+		 */
+		ret = exynos_drm_fbdev_reinit(drm_dev);
+		if (ret < 0) {
+			DRM_ERROR("failed fb helper reinit.\n");
+			goto fail;
+		}
+
+		ret = exynos_drm_mode_group_reinit(drm_dev);
+		if (ret < 0) {
+			DRM_ERROR("failed drm mode group reinit.\n");
+			goto fail;
+		}
+	}
+
+fail:
+	mutex_unlock(&exynos_drm_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Core Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,383 @@
+/* exynos_drm_crtc.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc,\
+				drm_crtc)
+
+/*
+ * Exynos specific crtc structure.
+ *
+ * @drm_crtc: crtc object.
+ * @overlay: contain information common to display controller and hdmi and
+ *	contents of this overlay object would be copied to sub driver size.
+ * @pipe: a crtc index created at load() with a new crtc object creation
+ *	and the crtc object would be set to private->crtc array
+ *	to get a crtc object corresponding to this pipe from private->crtc
+ *	array when irq interrupt occured. the reason of using this pipe is that
+ *	drm framework doesn't support multiple irq yet.
+ *	we can refer to the crtc to current hardware interrupt occured through
+ *	this pipe value.
+ */
+struct exynos_drm_crtc {
+	struct drm_crtc			drm_crtc;
+	struct exynos_drm_overlay	overlay;
+	unsigned int			pipe;
+};
+
+static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
+
+	exynos_drm_fn_encoder(crtc, overlay,
+			exynos_drm_encoder_crtc_mode_set);
+	exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+			exynos_drm_encoder_crtc_commit);
+}
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+			      struct drm_framebuffer *fb,
+			      struct drm_display_mode *mode,
+			      struct exynos_drm_crtc_pos *pos)
+{
+	struct exynos_drm_gem_buf *buffer;
+	unsigned int actual_w;
+	unsigned int actual_h;
+
+	buffer = exynos_drm_fb_get_buf(fb);
+	if (!buffer) {
+		DRM_LOG_KMS("buffer is null.\n");
+		return -EFAULT;
+	}
+
+	overlay->dma_addr = buffer->dma_addr;
+	overlay->vaddr = buffer->kvaddr;
+
+	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+			(unsigned long)overlay->vaddr,
+			(unsigned long)overlay->dma_addr);
+
+	actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
+	actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
+
+	/* set drm framebuffer data. */
+	overlay->fb_x = pos->fb_x;
+	overlay->fb_y = pos->fb_y;
+	overlay->fb_width = fb->width;
+	overlay->fb_height = fb->height;
+	overlay->bpp = fb->bits_per_pixel;
+	overlay->pitch = fb->pitch;
+
+	/* set overlay range to be displayed. */
+	overlay->crtc_x = pos->crtc_x;
+	overlay->crtc_y = pos->crtc_y;
+	overlay->crtc_width = actual_w;
+	overlay->crtc_height = actual_h;
+
+	/* set drm mode data. */
+	overlay->mode_width = mode->hdisplay;
+	overlay->mode_height = mode->vdisplay;
+	overlay->refresh = mode->vrefresh;
+	overlay->scan_flag = mode->flags;
+
+	DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
+			overlay->crtc_x, overlay->crtc_y,
+			overlay->crtc_width, overlay->crtc_height);
+
+	return 0;
+}
+
+static int exynos_drm_crtc_update(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc;
+	struct exynos_drm_overlay *overlay;
+	struct exynos_drm_crtc_pos pos;
+	struct drm_display_mode *mode = &crtc->mode;
+	struct drm_framebuffer *fb = crtc->fb;
+
+	if (!mode || !fb)
+		return -EINVAL;
+
+	exynos_crtc = to_exynos_crtc(crtc);
+	overlay = &exynos_crtc->overlay;
+
+	memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
+
+	/* it means the offset of framebuffer to be displayed. */
+	pos.fb_x = crtc->x;
+	pos.fb_y = crtc->y;
+
+	/* OSD position to be displayed. */
+	pos.crtc_x = 0;
+	pos.crtc_y = 0;
+	pos.crtc_w = fb->width - crtc->x;
+	pos.crtc_h = fb->height - crtc->y;
+
+	return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
+}
+
+static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+				exynos_drm_encoder_crtc_commit);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		/* TODO */
+		exynos_drm_fn_encoder(crtc, NULL,
+				exynos_drm_encoder_crtc_disable);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+}
+
+static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+			exynos_drm_encoder_crtc_commit);
+}
+
+static bool
+exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL */
+	return true;
+}
+
+static int
+exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+			  struct drm_display_mode *adjusted_mode, int x, int y,
+			  struct drm_framebuffer *old_fb)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode = adjusted_mode;
+
+	return exynos_drm_crtc_update(crtc);
+}
+
+static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+					  struct drm_framebuffer *old_fb)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	ret = exynos_drm_crtc_update(crtc);
+	if (ret)
+		return ret;
+
+	exynos_drm_crtc_apply(crtc);
+
+	return ret;
+}
+
+static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+	/* drm framework doesn't check NULL */
+}
+
+static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
+	.dpms		= exynos_drm_crtc_dpms,
+	.prepare	= exynos_drm_crtc_prepare,
+	.commit		= exynos_drm_crtc_commit,
+	.mode_fixup	= exynos_drm_crtc_mode_fixup,
+	.mode_set	= exynos_drm_crtc_mode_set,
+	.mode_set_base	= exynos_drm_crtc_mode_set_base,
+	.load_lut	= exynos_drm_crtc_load_lut,
+};
+
+static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
+				      struct drm_framebuffer *fb,
+				      struct drm_pending_vblank_event *event)
+{
+	struct drm_device *dev = crtc->dev;
+	struct exynos_drm_private *dev_priv = dev->dev_private;
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_framebuffer *old_fb = crtc->fb;
+	int ret = -EINVAL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (event) {
+		/*
+		 * the pipe from user always is 0 so we can set pipe number
+		 * of current owner to event.
+		 */
+		event->pipe = exynos_crtc->pipe;
+
+		list_add_tail(&event->base.link,
+				&dev_priv->pageflip_event_list);
+
+		ret = drm_vblank_get(dev, exynos_crtc->pipe);
+		if (ret) {
+			DRM_DEBUG("failed to acquire vblank counter\n");
+			list_del(&event->base.link);
+
+			goto out;
+		}
+
+		crtc->fb = fb;
+		ret = exynos_drm_crtc_update(crtc);
+		if (ret) {
+			crtc->fb = old_fb;
+			drm_vblank_put(dev, exynos_crtc->pipe);
+			list_del(&event->base.link);
+
+			goto out;
+		}
+
+		/*
+		 * the values related to a buffer of the drm framebuffer
+		 * to be applied should be set at here. because these values
+		 * first, are set to shadow registers and then to
+		 * real registers at vsync front porch period.
+		 */
+		exynos_drm_crtc_apply(crtc);
+	}
+out:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_private *private = crtc->dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	private->crtc[exynos_crtc->pipe] = NULL;
+
+	drm_crtc_cleanup(crtc);
+	kfree(exynos_crtc);
+}
+
+static struct drm_crtc_funcs exynos_crtc_funcs = {
+	.set_config	= drm_crtc_helper_set_config,
+	.page_flip	= exynos_drm_crtc_page_flip,
+	.destroy	= exynos_drm_crtc_destroy,
+};
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+		struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	return &exynos_crtc->overlay;
+}
+
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
+{
+	struct exynos_drm_crtc *exynos_crtc;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_crtc *crtc;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
+	if (!exynos_crtc) {
+		DRM_ERROR("failed to allocate exynos crtc\n");
+		return -ENOMEM;
+	}
+
+	exynos_crtc->pipe = nr;
+	crtc = &exynos_crtc->drm_crtc;
+
+	private->crtc[nr] = crtc;
+
+	drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
+	drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
+
+	return 0;
+}
+
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+			exynos_drm_enable_vblank);
+
+	return 0;
+}
+
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+			exynos_drm_disable_vblank);
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM CRTC Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_crtc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/* exynos_drm_crtc.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_CRTC_H_
+#define _EXYNOS_DRM_CRTC_H_
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+		struct drm_crtc *crtc);
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+
+/*
+ * Exynos specific crtc postion structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displyed
+ *	- the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed
+ *	- the unit is screen coordinates.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_w: width of hardware screen.
+ * @crtc_h: height of hardware screen.
+ */
+struct exynos_drm_crtc_pos {
+	unsigned int fb_x;
+	unsigned int fb_y;
+	unsigned int crtc_x;
+	unsigned int crtc_y;
+	unsigned int crtc_w;
+	unsigned int crtc_h;
+};
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+			      struct drm_framebuffer *fb,
+			      struct drm_display_mode *mode,
+			      struct exynos_drm_crtc_pos *pos);
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+
+#define DRIVER_NAME	"exynos-drm"
+#define DRIVER_DESC	"Samsung SoC DRM"
+#define DRIVER_DATE	"20110530"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	struct exynos_drm_private *private;
+	int ret;
+	int nr;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
+	if (!private) {
+		DRM_ERROR("failed to allocate private\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&private->pageflip_event_list);
+	dev->dev_private = (void *)private;
+
+	drm_mode_config_init(dev);
+
+	/* init kms poll for handling hpd */
+	drm_kms_helper_poll_init(dev);
+
+	exynos_drm_mode_config_init(dev);
+
+	/*
+	 * EXYNOS4 is enough to have two CRTCs and each crtc would be used
+	 * without dependency of hardware.
+	 */
+	for (nr = 0; nr < MAX_CRTC; nr++) {
+		ret = exynos_drm_crtc_create(dev, nr);
+		if (ret)
+			goto err_crtc;
+	}
+
+	ret = drm_vblank_init(dev, MAX_CRTC);
+	if (ret)
+		goto err_crtc;
+
+	/*
+	 * probe sub drivers such as display controller and hdmi driver,
+	 * that were registered at probe() of platform driver
+	 * to the sub driver and create encoder and connector for them.
+	 */
+	ret = exynos_drm_device_register(dev);
+	if (ret)
+		goto err_vblank;
+
+	/*
+	 * create and configure fb helper and also exynos specific
+	 * fbdev object.
+	 */
+	ret = exynos_drm_fbdev_init(dev);
+	if (ret) {
+		DRM_ERROR("failed to initialize drm fbdev\n");
+		goto err_drm_device;
+	}
+
+	return 0;
+
+err_drm_device:
+	exynos_drm_device_unregister(dev);
+err_vblank:
+	drm_vblank_cleanup(dev);
+err_crtc:
+	drm_mode_config_cleanup(dev);
+	kfree(private);
+
+	return ret;
+}
+
+static int exynos_drm_unload(struct drm_device *dev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_fbdev_fini(dev);
+	exynos_drm_device_unregister(dev);
+	drm_vblank_cleanup(dev);
+	drm_kms_helper_poll_fini(dev);
+	drm_mode_config_cleanup(dev);
+	kfree(dev->dev_private);
+
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static void exynos_drm_preclose(struct drm_device *dev,
+					struct drm_file *file_priv)
+{
+	struct exynos_drm_private *dev_priv = dev->dev_private;
+
+	/*
+	 * drm framework frees all events at release time,
+	 * so private event list should be cleared.
+	 */
+	if (!list_empty(&dev_priv->pageflip_event_list))
+		INIT_LIST_HEAD(&dev_priv->pageflip_event_list);
+}
+
+static void exynos_drm_lastclose(struct drm_device *dev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_fbdev_restore_mode(dev);
+}
+
+static struct vm_operations_struct exynos_drm_gem_vm_ops = {
+	.fault = exynos_drm_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static struct drm_ioctl_desc exynos_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
+			DRM_UNLOCKED | DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
+			exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
+			DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
+			exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
+};
+
+static struct drm_driver exynos_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
+				  DRIVER_MODESET | DRIVER_GEM,
+	.load			= exynos_drm_load,
+	.unload			= exynos_drm_unload,
+	.preclose		= exynos_drm_preclose,
+	.lastclose		= exynos_drm_lastclose,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= exynos_drm_crtc_enable_vblank,
+	.disable_vblank		= exynos_drm_crtc_disable_vblank,
+	.gem_init_object	= exynos_drm_gem_init_object,
+	.gem_free_object	= exynos_drm_gem_free_object,
+	.gem_vm_ops		= &exynos_drm_gem_vm_ops,
+	.dumb_create		= exynos_drm_gem_dumb_create,
+	.dumb_map_offset	= exynos_drm_gem_dumb_map_offset,
+	.dumb_destroy		= exynos_drm_gem_dumb_destroy,
+	.ioctls			= exynos_ioctls,
+	.fops = {
+		.owner		= THIS_MODULE,
+		.open		= drm_open,
+		.mmap		= exynos_drm_gem_mmap,
+		.poll		= drm_poll,
+		.read		= drm_read,
+		.unlocked_ioctl	= drm_ioctl,
+		.release	= drm_release,
+	},
+	.name	= DRIVER_NAME,
+	.desc	= DRIVER_DESC,
+	.date	= DRIVER_DATE,
+	.major	= DRIVER_MAJOR,
+	.minor	= DRIVER_MINOR,
+};
+
+static int exynos_drm_platform_probe(struct platform_device *pdev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
+
+	return drm_platform_init(&exynos_drm_driver, pdev);
+}
+
+static int exynos_drm_platform_remove(struct platform_device *pdev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	drm_platform_exit(&exynos_drm_driver, pdev);
+
+	return 0;
+}
+
+static struct platform_driver exynos_drm_platform_driver = {
+	.probe		= exynos_drm_platform_probe,
+	.remove		= __devexit_p(exynos_drm_platform_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init exynos_drm_init(void)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	return platform_driver_register(&exynos_drm_platform_driver);
+}
+
+static void __exit exynos_drm_exit(void)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	platform_driver_unregister(&exynos_drm_platform_driver);
+}
+
+module_init(exynos_drm_init);
+module_exit(exynos_drm_exit);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,257 @@
+/* exynos_drm_drv.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_DRV_H_
+#define _EXYNOS_DRM_DRV_H_
+
+#include <linux/module.h>
+#include "drm.h"
+
+#define MAX_CRTC	2
+
+struct drm_device;
+struct exynos_drm_overlay;
+struct drm_connector;
+
+/* this enumerates display type. */
+enum exynos_drm_output_type {
+	EXYNOS_DISPLAY_TYPE_NONE,
+	/* RGB or CPU Interface. */
+	EXYNOS_DISPLAY_TYPE_LCD,
+	/* HDMI Interface. */
+	EXYNOS_DISPLAY_TYPE_HDMI,
+};
+
+/*
+ * Exynos drm overlay ops structure.
+ *
+ * @mode_set: copy drm overlay info to hw specific overlay info.
+ * @commit: apply hardware specific overlay data to registers.
+ * @disable: disable hardware specific overlay.
+ */
+struct exynos_drm_overlay_ops {
+	void (*mode_set)(struct device *subdrv_dev,
+			 struct exynos_drm_overlay *overlay);
+	void (*commit)(struct device *subdrv_dev);
+	void (*disable)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common overlay structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displayed.
+ *	- the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed.
+ *	- the unit is screen coordinates.
+ * @fb_width: width of a framebuffer.
+ * @fb_height: height of a framebuffer.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_width: window width to be displayed (hardware screen).
+ * @crtc_height: window height to be displayed (hardware screen).
+ * @mode_width: width of screen mode.
+ * @mode_height: height of screen mode.
+ * @refresh: refresh rate.
+ * @scan_flag: interlace or progressive way.
+ *	(it could be DRM_MODE_FLAG_*)
+ * @bpp: pixel size.(in bit)
+ * @dma_addr: bus(accessed by dma) address to the memory region allocated
+ *	for a overlay.
+ * @vaddr: virtual memory addresss to this overlay.
+ * @default_win: a window to be enabled.
+ * @color_key: color key on or off.
+ * @index_color: if using color key feature then this value would be used
+ *			as index color.
+ * @local_path: in case of lcd type, local path mode on or off.
+ * @transparency: transparency on or off.
+ * @activated: activated or not.
+ *
+ * this structure is common to exynos SoC and its contents would be copied
+ * to hardware specific overlay info.
+ */
+struct exynos_drm_overlay {
+	unsigned int fb_x;
+	unsigned int fb_y;
+	unsigned int fb_width;
+	unsigned int fb_height;
+	unsigned int crtc_x;
+	unsigned int crtc_y;
+	unsigned int crtc_width;
+	unsigned int crtc_height;
+	unsigned int mode_width;
+	unsigned int mode_height;
+	unsigned int refresh;
+	unsigned int scan_flag;
+	unsigned int bpp;
+	unsigned int pitch;
+	dma_addr_t dma_addr;
+	void __iomem *vaddr;
+
+	bool default_win;
+	bool color_key;
+	unsigned int index_color;
+	bool local_path;
+	bool transparency;
+	bool activated;
+};
+
+/*
+ * Exynos DRM Display Structure.
+ *	- this structure is common to analog tv, digital tv and lcd panel.
+ *
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @is_connected: check for that display is connected or not.
+ * @get_edid: get edid modes from display driver.
+ * @get_timing: get timing object from display driver.
+ * @check_timing: check if timing is valid or not.
+ * @power_on: display device on or off.
+ */
+struct exynos_drm_display_ops {
+	enum exynos_drm_output_type type;
+	bool (*is_connected)(struct device *dev);
+	int (*get_edid)(struct device *dev, struct drm_connector *connector,
+				u8 *edid, int len);
+	void *(*get_timing)(struct device *dev);
+	int (*check_timing)(struct device *dev, void *timing);
+	int (*power_on)(struct device *dev, int mode);
+};
+
+/*
+ * Exynos drm manager ops
+ *
+ * @mode_set: convert drm_display_mode to hw specific display mode and
+ *	      would be called by encoder->mode_set().
+ * @commit: set current hw specific display mode to hw.
+ * @disable: disable hardware specific display mode.
+ * @enable_vblank: specific driver callback for enabling vblank interrupt.
+ * @disable_vblank: specific driver callback for disabling vblank interrupt.
+ */
+struct exynos_drm_manager_ops {
+	void (*mode_set)(struct device *subdrv_dev, void *mode);
+	void (*commit)(struct device *subdrv_dev);
+	void (*disable)(struct device *subdrv_dev);
+	int (*enable_vblank)(struct device *subdrv_dev);
+	void (*disable_vblank)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common manager structure.
+ *
+ * @dev: pointer to device object for subdrv device driver.
+ *	sub drivers such as display controller or hdmi driver,
+ *	have their own device object.
+ * @ops: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control hardware global registers.
+ * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control hardware overlay reigsters.
+ * @display: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control display devices such as
+ *	analog tv, digital tv and lcd panel and also get timing data for them.
+ */
+struct exynos_drm_manager {
+	struct device *dev;
+	int pipe;
+	struct exynos_drm_manager_ops *ops;
+	struct exynos_drm_overlay_ops *overlay_ops;
+	struct exynos_drm_display_ops *display_ops;
+};
+
+/*
+ * Exynos drm private structure.
+ */
+struct exynos_drm_private {
+	struct drm_fb_helper *fb_helper;
+
+	/* list head for new event to be added. */
+	struct list_head pageflip_event_list;
+
+	/*
+	 * created crtc object would be contained at this array and
+	 * this array is used to be aware of which crtc did it request vblank.
+	 */
+	struct drm_crtc *crtc[MAX_CRTC];
+};
+
+/*
+ * Exynos drm sub driver structure.
+ *
+ * @list: sub driver has its own list object to register to exynos drm driver.
+ * @drm_dev: pointer to drm_device and this pointer would be set
+ *	when sub driver calls exynos_drm_subdrv_register().
+ * @probe: this callback would be called by exynos drm driver after
+ *	subdrv is registered to it.
+ * @remove: this callback is used to release resources created
+ *	by probe callback.
+ * @manager: subdrv has its own manager to control a hardware appropriately
+ *	and we can access a hardware drawing on this manager.
+ * @encoder: encoder object owned by this sub driver.
+ * @connector: connector object owned by this sub driver.
+ */
+struct exynos_drm_subdrv {
+	struct list_head list;
+	struct drm_device *drm_dev;
+
+	int (*probe)(struct drm_device *drm_dev, struct device *dev);
+	void (*remove)(struct drm_device *dev);
+
+	struct exynos_drm_manager manager;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+};
+
+/*
+ * this function calls a probe callback registered to sub driver list and
+ * create its own encoder and connector and then set drm_device object
+ * to global one.
+ */
+int exynos_drm_device_register(struct drm_device *dev);
+/*
+ * this function calls a remove callback registered to sub driver list and
+ * destroy its own encoder and connetor.
+ */
+int exynos_drm_device_unregister(struct drm_device *dev);
+
+/*
+ * this function would be called by sub drivers such as display controller
+ * or hdmi driver to register this sub driver object to exynos drm driver
+ * and when a sub driver is registered to exynos drm driver a probe callback
+ * of the sub driver is called and creates its own encoder and connector
+ * and then fb helper and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv);
+
+/*
+ * this function removes subdrv list from exynos drm driver and fb helper
+ * and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,332 @@
+/* exynos_drm_encoder.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_encoder.h"
+
+#define to_exynos_encoder(x)	container_of(x, struct exynos_drm_encoder,\
+				drm_encoder)
+
+/*
+ * exynos specific encoder structure.
+ *
+ * @drm_encoder: encoder object.
+ * @manager: specific encoder has its own manager to control a hardware
+ *	appropriately and we can access a hardware drawing on this manager.
+ */
+struct exynos_drm_encoder {
+	struct drm_encoder		drm_encoder;
+	struct exynos_drm_manager	*manager;
+};
+
+static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+
+	DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		if (manager_ops && manager_ops->commit)
+			manager_ops->commit(manager->dev);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		/* TODO */
+		if (manager_ops && manager_ops->disable)
+			manager_ops->disable(manager->dev);
+		break;
+	default:
+		DRM_ERROR("unspecified mode %d\n", mode);
+		break;
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			struct exynos_drm_display_ops *display_ops =
+							manager->display_ops;
+
+			DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
+					connector->base.id, mode);
+			if (display_ops && display_ops->power_on)
+				display_ops->power_on(manager->dev, mode);
+		}
+	}
+}
+
+static bool
+exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+
+	return true;
+}
+
+static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
+					 struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
+						encoder->crtc);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode = adjusted_mode;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			if (manager_ops && manager_ops->mode_set)
+				manager_ops->mode_set(manager->dev, mode);
+
+			if (overlay_ops && overlay_ops->mode_set)
+				overlay_ops->mode_set(manager->dev, overlay);
+		}
+	}
+}
+
+static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
+{
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (manager_ops && manager_ops->commit)
+		manager_ops->commit(manager->dev);
+}
+
+static struct drm_crtc *
+exynos_drm_encoder_get_crtc(struct drm_encoder *encoder)
+{
+	return encoder->crtc;
+}
+
+static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
+	.dpms		= exynos_drm_encoder_dpms,
+	.mode_fixup	= exynos_drm_encoder_mode_fixup,
+	.mode_set	= exynos_drm_encoder_mode_set,
+	.prepare	= exynos_drm_encoder_prepare,
+	.commit		= exynos_drm_encoder_commit,
+	.get_crtc	= exynos_drm_encoder_get_crtc,
+};
+
+static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct exynos_drm_encoder *exynos_encoder =
+		to_exynos_encoder(encoder);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_encoder->manager->pipe = -1;
+
+	drm_encoder_cleanup(encoder);
+	encoder->dev->mode_config.num_encoder--;
+	kfree(exynos_encoder);
+}
+
+static struct drm_encoder_funcs exynos_encoder_funcs = {
+	.destroy = exynos_drm_encoder_destroy,
+};
+
+struct drm_encoder *
+exynos_drm_encoder_create(struct drm_device *dev,
+			   struct exynos_drm_manager *manager,
+			   unsigned int possible_crtcs)
+{
+	struct drm_encoder *encoder;
+	struct exynos_drm_encoder *exynos_encoder;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!manager || !possible_crtcs)
+		return NULL;
+
+	if (!manager->dev)
+		return NULL;
+
+	exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
+	if (!exynos_encoder) {
+		DRM_ERROR("failed to allocate encoder\n");
+		return NULL;
+	}
+
+	exynos_encoder->manager = manager;
+	encoder = &exynos_encoder->drm_encoder;
+	encoder->possible_crtcs = possible_crtcs;
+
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
+			DRM_MODE_ENCODER_TMDS);
+
+	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
+
+	DRM_DEBUG_KMS("encoder has been created\n");
+
+	return encoder;
+}
+
+struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
+{
+	return to_exynos_encoder(encoder)->manager;
+}
+
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+			    void (*fn)(struct drm_encoder *, void *))
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct exynos_drm_manager *manager;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		/*
+		 * if crtc is detached from encoder, check pipe,
+		 * otherwise check crtc attached to encoder
+		 */
+		if (!encoder->crtc) {
+			manager = to_exynos_encoder(encoder)->manager;
+			if (manager->pipe < 0 ||
+					private->crtc[manager->pipe] != crtc)
+				continue;
+		} else {
+			if (encoder->crtc != crtc)
+				continue;
+		}
+
+		fn(encoder, data);
+	}
+}
+
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	int crtc = *(int *)data;
+
+	if (manager->pipe == -1)
+		manager->pipe = crtc;
+
+	if (manager_ops->enable_vblank)
+		manager_ops->enable_vblank(manager->dev);
+}
+
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	int crtc = *(int *)data;
+
+	if (manager->pipe == -1)
+		manager->pipe = crtc;
+
+	if (manager_ops->disable_vblank)
+		manager_ops->disable_vblank(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	int crtc = *(int *)data;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * when crtc is detached from encoder, this pipe is used
+	 * to select manager operation
+	 */
+	manager->pipe = crtc;
+
+	if (overlay_ops && overlay_ops->commit)
+		overlay_ops->commit(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_overlay *overlay = data;
+
+	if (overlay_ops && overlay_ops->mode_set)
+		overlay_ops->mode_set(manager->dev, overlay);
+}
+
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+	DRM_DEBUG_KMS("\n");
+
+	if (overlay_ops && overlay_ops->disable)
+		overlay_ops->disable(manager->dev);
+
+	/*
+	 * crtc is already detached from encoder and last
+	 * function for detaching is properly done, so
+	 * clear pipe from manager to prevent repeated call
+	 */
+	if (!encoder->crtc)
+		manager->pipe = -1;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_encoder.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_ENCODER_H_
+#define _EXYNOS_DRM_ENCODER_H_
+
+struct exynos_drm_manager;
+
+struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
+					       struct exynos_drm_manager *mgr,
+					       unsigned int possible_crtcs);
+struct exynos_drm_manager *
+exynos_drm_get_manager(struct drm_encoder *encoder);
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+			    void (*fn)(struct drm_encoder *, void *));
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,277 @@
+/* exynos_drm_fb.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_buf.h"
+#include "exynos_drm_gem.h"
+
+#define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
+
+/*
+ * exynos specific framebuffer structure.
+ *
+ * @fb: drm framebuffer obejct.
+ * @exynos_gem_obj: exynos specific gem object containing a gem object.
+ * @buffer: pointer to exynos_drm_gem_buffer object.
+ *	- contain the memory information to memory region allocated
+ *	at default framebuffer creation.
+ */
+struct exynos_drm_fb {
+	struct drm_framebuffer		fb;
+	struct exynos_drm_gem_obj	*exynos_gem_obj;
+	struct exynos_drm_gem_buf	*buffer;
+};
+
+static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	drm_framebuffer_cleanup(fb);
+
+	/*
+	 * default framebuffer has no gem object so
+	 * a buffer of the default framebuffer should be released at here.
+	 */
+	if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
+		exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);
+
+	kfree(exynos_fb);
+	exynos_fb = NULL;
+}
+
+static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
+					struct drm_file *file_priv,
+					unsigned int *handle)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return drm_gem_handle_create(file_priv,
+			&exynos_fb->exynos_gem_obj->base, handle);
+}
+
+static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
+				struct drm_file *file_priv, unsigned flags,
+				unsigned color, struct drm_clip_rect *clips,
+				unsigned num_clips)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO */
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
+	.destroy	= exynos_drm_fb_destroy,
+	.create_handle	= exynos_drm_fb_create_handle,
+	.dirty		= exynos_drm_fb_dirty,
+};
+
+static struct drm_framebuffer *
+exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
+		    struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct exynos_drm_fb *exynos_fb;
+	struct drm_framebuffer *fb;
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+	struct drm_gem_object *obj;
+	unsigned int size;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode_cmd->pitch = max(mode_cmd->pitch,
+			mode_cmd->width * (mode_cmd->bpp >> 3));
+
+	DRM_LOG_KMS("drm fb create(%dx%d)\n",
+			mode_cmd->width, mode_cmd->height);
+
+	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
+	if (!exynos_fb) {
+		DRM_ERROR("failed to allocate exynos drm framebuffer.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	fb = &exynos_fb->fb;
+	ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs);
+	if (ret) {
+		DRM_ERROR("failed to initialize framebuffer.\n");
+		goto err_init;
+	}
+
+	DRM_LOG_KMS("create: fb id: %d\n", fb->base.id);
+
+	size = mode_cmd->pitch * mode_cmd->height;
+
+	/*
+	 * mode_cmd->handle could be NULL at booting time or
+	 * with user request. if NULL, a new buffer or a gem object
+	 * would be allocated.
+	 */
+	if (!mode_cmd->handle) {
+		if (!file_priv) {
+			struct exynos_drm_gem_buf *buffer;
+
+			/*
+			 * in case that file_priv is NULL, it allocates
+			 * only buffer and this buffer would be used
+			 * for default framebuffer.
+			 */
+			buffer = exynos_drm_buf_create(dev, size);
+			if (IS_ERR(buffer)) {
+				ret = PTR_ERR(buffer);
+				goto err_buffer;
+			}
+
+			exynos_fb->buffer = buffer;
+
+			DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
+					(unsigned long)buffer->dma_addr, size);
+
+			goto out;
+		} else {
+			exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+							&mode_cmd->handle,
+							size);
+			if (IS_ERR(exynos_gem_obj)) {
+				ret = PTR_ERR(exynos_gem_obj);
+				goto err_buffer;
+			}
+		}
+	} else {
+		obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
+		if (!obj) {
+			DRM_ERROR("failed to lookup gem object.\n");
+			goto err_buffer;
+		}
+
+		exynos_gem_obj = to_exynos_gem_obj(obj);
+
+		drm_gem_object_unreference_unlocked(obj);
+	}
+
+	/*
+	 * if got a exynos_gem_obj from either a handle or
+	 * a new creation then exynos_fb->exynos_gem_obj is NULL
+	 * so that default framebuffer has no its own gem object,
+	 * only its own buffer object.
+	 */
+	exynos_fb->buffer = exynos_gem_obj->buffer;
+
+	DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
+			(unsigned long)exynos_fb->buffer->dma_addr, size,
+			(unsigned int)&exynos_gem_obj->base);
+
+out:
+	exynos_fb->exynos_gem_obj = exynos_gem_obj;
+
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+	return fb;
+
+err_buffer:
+	drm_framebuffer_cleanup(fb);
+
+err_init:
+	kfree(exynos_fb);
+
+	return ERR_PTR(ret);
+}
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+					      struct drm_file *file_priv,
+					      struct drm_mode_fb_cmd *mode_cmd)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return exynos_drm_fb_init(file_priv, dev, mode_cmd);
+}
+
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+	struct exynos_drm_gem_buf *buffer;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	buffer = exynos_fb->buffer;
+	if (!buffer)
+		return NULL;
+
+	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+			(unsigned long)buffer->kvaddr,
+			(unsigned long)buffer->dma_addr);
+
+	return buffer;
+}
+
+static void exynos_drm_output_poll_changed(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *fb_helper = private->fb_helper;
+
+	if (fb_helper)
+		drm_fb_helper_hotplug_event(fb_helper);
+}
+
+static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
+	.fb_create = exynos_drm_fb_create,
+	.output_poll_changed = exynos_drm_output_poll_changed,
+};
+
+void exynos_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	/*
+	 * set max width and height as default value(4096x4096).
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	dev->mode_config.max_width = 4096;
+	dev->mode_config.max_height = 4096;
+
+	dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FB Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,468 @@
+/* exynos_drm_fbdev.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+#define MAX_CONNECTOR		4
+#define PREFERRED_BPP		32
+
+#define to_exynos_fbdev(x)	container_of(x, struct exynos_drm_fbdev,\
+				drm_fb_helper)
+
+struct exynos_drm_fbdev {
+	struct drm_fb_helper	drm_fb_helper;
+	struct drm_framebuffer	*fb;
+};
+
+static int exynos_drm_fbdev_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 24:
+	case 18:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	return drm_fb_helper_set_par(info);
+}
+
+
+static struct fb_ops exynos_drm_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= exynos_drm_fbdev_set_par,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+};
+
+static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
+				     struct drm_framebuffer *fb)
+{
+	struct fb_info *fbi = helper->fbdev;
+	struct drm_device *dev = helper->dev;
+	struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
+	struct exynos_drm_gem_buf *buffer;
+	unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
+	unsigned long offset;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_fb->fb = fb;
+
+	drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+
+	buffer = exynos_drm_fb_get_buf(fb);
+	if (!buffer) {
+		DRM_LOG_KMS("buffer is null.\n");
+		return -EFAULT;
+	}
+
+	offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
+	offset += fbi->var.yoffset * fb->pitch;
+
+	dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+	fbi->screen_base = buffer->kvaddr + offset;
+	fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+
+	return 0;
+}
+
+static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
+				    struct drm_fb_helper_surface_size *sizes)
+{
+	struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+	struct drm_device *dev = helper->dev;
+	struct fb_info *fbi;
+	struct drm_mode_fb_cmd mode_cmd = { 0 };
+	struct platform_device *pdev = dev->platformdev;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+			sizes->surface_width, sizes->surface_height,
+			sizes->surface_bpp);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+	mode_cmd.depth = sizes->surface_depth;
+
+	mutex_lock(&dev->struct_mutex);
+
+	fbi = framebuffer_alloc(0, &pdev->dev);
+	if (!fbi) {
+		DRM_ERROR("failed to allocate fb info.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+	if (IS_ERR_OR_NULL(exynos_fbdev->fb)) {
+		DRM_ERROR("failed to create drm framebuffer.\n");
+		ret = PTR_ERR(exynos_fbdev->fb);
+		goto out;
+	}
+
+	helper->fb = exynos_fbdev->fb;
+	helper->fbdev = fbi;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &exynos_drm_fb_ops;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret) {
+		DRM_ERROR("failed to allocate cmap.\n");
+		goto out;
+	}
+
+	ret = exynos_drm_fbdev_update(helper, helper->fb);
+	if (ret < 0)
+		fb_dealloc_cmap(&fbi->cmap);
+
+/*
+ * if failed, all resources allocated above would be released by
+ * drm_mode_config_cleanup() when drm_load() had been called prior
+ * to any specific driver such as fimd or hdmi driver.
+ */
+out:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static bool
+exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb,
+			    struct drm_fb_helper_surface_size *sizes)
+{
+	if (fb->width != sizes->surface_width)
+		return false;
+	if (fb->height != sizes->surface_height)
+		return false;
+	if (fb->bits_per_pixel != sizes->surface_bpp)
+		return false;
+	if (fb->depth != sizes->surface_depth)
+		return false;
+
+	return true;
+}
+
+static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
+				      struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = helper->dev;
+	struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+	struct drm_framebuffer *fb = exynos_fbdev->fb;
+	struct drm_mode_fb_cmd mode_cmd = { 0 };
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (helper->fb != fb) {
+		DRM_ERROR("drm framebuffer is different\n");
+		return -EINVAL;
+	}
+
+	if (exynos_drm_fbdev_is_samefb(fb, sizes))
+		return 0;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+	mode_cmd.depth = sizes->surface_depth;
+
+	if (fb->funcs->destroy)
+		fb->funcs->destroy(fb);
+
+	exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+	if (IS_ERR(exynos_fbdev->fb)) {
+		DRM_ERROR("failed to allocate fb.\n");
+		return PTR_ERR(exynos_fbdev->fb);
+	}
+
+	helper->fb = exynos_fbdev->fb;
+	return exynos_drm_fbdev_update(helper, helper->fb);
+}
+
+static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
+				   struct drm_fb_helper_surface_size *sizes)
+{
+	int ret = 0;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!helper->fb) {
+		ret = exynos_drm_fbdev_create(helper, sizes);
+		if (ret < 0) {
+			DRM_ERROR("failed to create fbdev.\n");
+			return ret;
+		}
+
+		/*
+		 * fb_helper expects a value more than 1 if succeed
+		 * because register_framebuffer() should be called.
+		 */
+		ret = 1;
+	} else {
+		ret = exynos_drm_fbdev_recreate(helper, sizes);
+		if (ret < 0) {
+			DRM_ERROR("failed to reconfigure fbdev\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+	.fb_probe =	exynos_drm_fbdev_probe,
+};
+
+int exynos_drm_fbdev_init(struct drm_device *dev)
+{
+	struct exynos_drm_fbdev *fbdev;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *helper;
+	unsigned int num_crtc;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+		return 0;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		DRM_ERROR("failed to allocate drm fbdev.\n");
+		return -ENOMEM;
+	}
+
+	private->fb_helper = helper = &fbdev->drm_fb_helper;
+	helper->funcs = &exynos_drm_fb_helper_funcs;
+
+	num_crtc = dev->mode_config.num_crtc;
+
+	ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR);
+	if (ret < 0) {
+		DRM_ERROR("failed to initialize drm fb helper.\n");
+		goto err_init;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret < 0) {
+		DRM_ERROR("failed to register drm_fb_helper_connector.\n");
+		goto err_setup;
+
+	}
+
+	ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
+	if (ret < 0) {
+		DRM_ERROR("failed to set up hw configuration.\n");
+		goto err_setup;
+	}
+
+	return 0;
+
+err_setup:
+	drm_fb_helper_fini(helper);
+
+err_init:
+	private->fb_helper = NULL;
+	kfree(fbdev);
+
+	return ret;
+}
+
+static void exynos_drm_fbdev_destroy(struct drm_device *dev,
+				      struct drm_fb_helper *fb_helper)
+{
+	struct drm_framebuffer *fb;
+
+	/* release drm framebuffer and real buffer */
+	if (fb_helper->fb && fb_helper->fb->funcs) {
+		fb = fb_helper->fb;
+		if (fb && fb->funcs->destroy)
+			fb->funcs->destroy(fb);
+	}
+
+	/* release linux framebuffer */
+	if (fb_helper->fbdev) {
+		struct fb_info *info;
+		int ret;
+
+		info = fb_helper->fbdev;
+		ret = unregister_framebuffer(info);
+		if (ret < 0)
+			DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
+
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+
+		framebuffer_release(info);
+	}
+
+	drm_fb_helper_fini(fb_helper);
+}
+
+void exynos_drm_fbdev_fini(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct exynos_drm_fbdev *fbdev;
+
+	if (!private || !private->fb_helper)
+		return;
+
+	fbdev = to_exynos_fbdev(private->fb_helper);
+
+	exynos_drm_fbdev_destroy(dev, private->fb_helper);
+	kfree(fbdev);
+	private->fb_helper = NULL;
+}
+
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	if (!private || !private->fb_helper)
+		return;
+
+	drm_fb_helper_restore_fbdev_mode(private->fb_helper);
+}
+
+int exynos_drm_fbdev_reinit(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *fb_helper;
+	int ret;
+
+	if (!private)
+		return -EINVAL;
+
+	/*
+	 * if all sub drivers were unloaded then num_connector is 0
+	 * so at this time, the framebuffers also should be destroyed.
+	 */
+	if (!dev->mode_config.num_connector) {
+		exynos_drm_fbdev_fini(dev);
+		return 0;
+	}
+
+	fb_helper = private->fb_helper;
+
+	if (fb_helper) {
+		struct list_head temp_list;
+
+		INIT_LIST_HEAD(&temp_list);
+
+		/*
+		 * fb_helper is reintialized but kernel fb is reused
+		 * so kernel_fb_list need to be backuped and restored
+		 */
+		if (!list_empty(&fb_helper->kernel_fb_list))
+			list_replace_init(&fb_helper->kernel_fb_list,
+					&temp_list);
+
+		drm_fb_helper_fini(fb_helper);
+
+		ret = drm_fb_helper_init(dev, fb_helper,
+				dev->mode_config.num_crtc, MAX_CONNECTOR);
+		if (ret < 0) {
+			DRM_ERROR("failed to initialize drm fb helper\n");
+			return ret;
+		}
+
+		if (!list_empty(&temp_list))
+			list_replace(&temp_list, &fb_helper->kernel_fb_list);
+
+		ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+		if (ret < 0) {
+			DRM_ERROR("failed to add fb helper to connectors\n");
+			goto err;
+		}
+
+		ret = drm_fb_helper_initial_config(fb_helper, PREFERRED_BPP);
+		if (ret < 0) {
+			DRM_ERROR("failed to set up hw configuration.\n");
+			goto err;
+		}
+	} else {
+		/*
+		 * if drm_load() failed whem drm load() was called prior
+		 * to specific drivers, fb_helper must be NULL and so
+		 * this fuction should be called again to re-initialize and
+		 * re-configure the fb helper. it means that this function
+		 * has been called by the specific drivers.
+		 */
+		ret = exynos_drm_fbdev_init(dev);
+	}
+
+	return ret;
+
+err:
+	/*
+	 * if drm_load() failed when drm load() was called prior
+	 * to specific drivers, the fb_helper must be NULL and so check it.
+	 */
+	if (fb_helper)
+		drm_fb_helper_fini(fb_helper);
+
+	return ret;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FBDEV Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fbdev.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_FBDEV_H_
+#define _EXYNOS_DRM_FBDEV_H_
+
+int exynos_drm_fbdev_init(struct drm_device *dev);
+int exynos_drm_fbdev_reinit(struct drm_device *dev);
+void exynos_drm_fbdev_fini(struct drm_device *dev);
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_FB_H_
+#define _EXYNOS_DRM_FB_H
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+					      struct drm_file *filp,
+					      struct drm_mode_fb_cmd *mode_cmd);
+
+void exynos_drm_mode_config_init(struct drm_device *dev);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fimd.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fimd.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_fimd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,846 @@
+/* exynos_drm_fimd.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Inki Dae <inki.dae@samsung.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 "drmP.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <drm/exynos_drm.h>
+#include <plat/regs-fb-v4.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_crtc.h"
+
+/*
+ * FIMD is stand for Fully Interactive Mobile Display and
+ * as a display controller, it transfers contents drawn on memory
+ * to a LCD Panel through Display Interfaces such as RGB or
+ * CPU Interface.
+ */
+
+/* position control register for hardware window 0, 2 ~ 4.*/
+#define VIDOSD_A(win)		(VIDOSD_BASE + 0x00 + (win) * 16)
+#define VIDOSD_B(win)		(VIDOSD_BASE + 0x04 + (win) * 16)
+/* size control register for hardware window 0. */
+#define VIDOSD_C_SIZE_W0	(VIDOSD_BASE + 0x08)
+/* alpha control register for hardware window 1 ~ 4. */
+#define VIDOSD_C(win)		(VIDOSD_BASE + 0x18 + (win) * 16)
+/* size control register for hardware window 1 ~ 4. */
+#define VIDOSD_D(win)		(VIDOSD_BASE + 0x0C + (win) * 16)
+
+#define VIDWx_BUF_START(win, buf)	(VIDW_BUF_START(buf) + (win) * 8)
+#define VIDWx_BUF_END(win, buf)		(VIDW_BUF_END(buf) + (win) * 8)
+#define VIDWx_BUF_SIZE(win, buf)	(VIDW_BUF_SIZE(buf) + (win) * 4)
+
+/* color key control register for hardware window 1 ~ 4. */
+#define WKEYCON0_BASE(x)		((WKEYCON0 + 0x140) + (x * 8))
+/* color key value register for hardware window 1 ~ 4. */
+#define WKEYCON1_BASE(x)		((WKEYCON1 + 0x140) + (x * 8))
+
+/* FIMD has totally five hardware windows. */
+#define WINDOWS_NR	5
+
+#define get_fimd_context(dev)	platform_get_drvdata(to_platform_device(dev))
+
+struct fimd_win_data {
+	unsigned int		offset_x;
+	unsigned int		offset_y;
+	unsigned int		ovl_width;
+	unsigned int		ovl_height;
+	unsigned int		fb_width;
+	unsigned int		fb_height;
+	unsigned int		bpp;
+	dma_addr_t		dma_addr;
+	void __iomem		*vaddr;
+	unsigned int		buf_offsize;
+	unsigned int		line_size;	/* bytes */
+};
+
+struct fimd_context {
+	struct exynos_drm_subdrv	subdrv;
+	int				irq;
+	struct drm_crtc			*crtc;
+	struct clk			*bus_clk;
+	struct clk			*lcd_clk;
+	struct resource			*regs_res;
+	void __iomem			*regs;
+	struct fimd_win_data		win_data[WINDOWS_NR];
+	unsigned int			clkdiv;
+	unsigned int			default_win;
+	unsigned long			irq_flags;
+	u32				vidcon0;
+	u32				vidcon1;
+
+	struct fb_videomode		*timing;
+};
+
+static bool fimd_display_is_connected(struct device *dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return true;
+}
+
+static void *fimd_get_timing(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return ctx->timing;
+}
+
+static int fimd_check_timing(struct device *dev, void *timing)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return 0;
+}
+
+static int fimd_display_power_on(struct device *dev, int mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return 0;
+}
+
+static struct exynos_drm_display_ops fimd_display_ops = {
+	.type = EXYNOS_DISPLAY_TYPE_LCD,
+	.is_connected = fimd_display_is_connected,
+	.get_timing = fimd_get_timing,
+	.check_timing = fimd_check_timing,
+	.power_on = fimd_display_power_on,
+};
+
+static void fimd_commit(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fb_videomode *timing = ctx->timing;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* setup polarity values from machine code. */
+	writel(ctx->vidcon1, ctx->regs + VIDCON1);
+
+	/* setup vertical timing values. */
+	val = VIDTCON0_VBPD(timing->upper_margin - 1) |
+	       VIDTCON0_VFPD(timing->lower_margin - 1) |
+	       VIDTCON0_VSPW(timing->vsync_len - 1);
+	writel(val, ctx->regs + VIDTCON0);
+
+	/* setup horizontal timing values.  */
+	val = VIDTCON1_HBPD(timing->left_margin - 1) |
+	       VIDTCON1_HFPD(timing->right_margin - 1) |
+	       VIDTCON1_HSPW(timing->hsync_len - 1);
+	writel(val, ctx->regs + VIDTCON1);
+
+	/* setup horizontal and vertical display size. */
+	val = VIDTCON2_LINEVAL(timing->yres - 1) |
+	       VIDTCON2_HOZVAL(timing->xres - 1);
+	writel(val, ctx->regs + VIDTCON2);
+
+	/* setup clock source, clock divider, enable dma. */
+	val = ctx->vidcon0;
+	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+	if (ctx->clkdiv > 1)
+		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
+	else
+		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
+
+	/*
+	 * fields of register with prefix '_F' would be updated
+	 * at vsync(same as dma start)
+	 */
+	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+	writel(val, ctx->regs + VIDCON0);
+}
+
+static void fimd_disable(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+	struct drm_device *drm_dev = subdrv->drm_dev;
+	struct exynos_drm_manager *manager = &subdrv->manager;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* fimd dma off */
+	val = readl(ctx->regs + VIDCON0);
+	val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
+	writel(val, ctx->regs + VIDCON0);
+
+	/*
+	 * if vblank is enabled status with dma off then
+	 * it disables vsync interrupt.
+	 */
+	if (drm_dev->vblank_enabled[manager->pipe] &&
+		atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
+		drm_vblank_put(drm_dev, manager->pipe);
+
+		/*
+		 * if vblank_disable_allowed is 0 then disable
+		 * vsync interrupt right now else the vsync interrupt
+		 * would be disabled by drm timer once a current process
+		 * gives up ownershop of vblank event.
+		 */
+		if (!drm_dev->vblank_disable_allowed)
+			drm_vblank_off(drm_dev, manager->pipe);
+	}
+}
+
+static int fimd_enable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!test_and_set_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val |= VIDINTCON0_INT_ENABLE;
+		val |= VIDINTCON0_INT_FRAME;
+
+		val &= ~VIDINTCON0_FRAMESEL0_MASK;
+		val |= VIDINTCON0_FRAMESEL0_VSYNC;
+		val &= ~VIDINTCON0_FRAMESEL1_MASK;
+		val |= VIDINTCON0_FRAMESEL1_NONE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+
+	return 0;
+}
+
+static void fimd_disable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (test_and_clear_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val &= ~VIDINTCON0_INT_FRAME;
+		val &= ~VIDINTCON0_INT_ENABLE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+}
+
+static struct exynos_drm_manager_ops fimd_manager_ops = {
+	.commit = fimd_commit,
+	.disable = fimd_disable,
+	.enable_vblank = fimd_enable_vblank,
+	.disable_vblank = fimd_disable_vblank,
+};
+
+static void fimd_win_mode_set(struct device *dev,
+			      struct exynos_drm_overlay *overlay)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data;
+	unsigned long offset;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!overlay) {
+		dev_err(dev, "overlay is NULL\n");
+		return;
+	}
+
+	offset = overlay->fb_x * (overlay->bpp >> 3);
+	offset += overlay->fb_y * overlay->pitch;
+
+	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
+
+	win_data = &ctx->win_data[ctx->default_win];
+
+	win_data->offset_x = overlay->crtc_x;
+	win_data->offset_y = overlay->crtc_y;
+	win_data->ovl_width = overlay->crtc_width;
+	win_data->ovl_height = overlay->crtc_height;
+	win_data->fb_width = overlay->fb_width;
+	win_data->fb_height = overlay->fb_height;
+	win_data->dma_addr = overlay->dma_addr + offset;
+	win_data->vaddr = overlay->vaddr + offset;
+	win_data->bpp = overlay->bpp;
+	win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
+				(overlay->bpp >> 3);
+	win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
+
+	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
+			win_data->offset_x, win_data->offset_y);
+	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+			win_data->ovl_width, win_data->ovl_height);
+	DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
+			(unsigned long)win_data->dma_addr,
+			(unsigned long)win_data->vaddr);
+	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
+			overlay->fb_width, overlay->crtc_width);
+}
+
+static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data = &ctx->win_data[win];
+	unsigned long val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	val = WINCONx_ENWIN;
+
+	switch (win_data->bpp) {
+	case 1:
+		val |= WINCON0_BPPMODE_1BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_4WORD;
+		break;
+	case 2:
+		val |= WINCON0_BPPMODE_2BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 4:
+		val |= WINCON0_BPPMODE_4BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 8:
+		val |= WINCON0_BPPMODE_8BPP_PALETTE;
+		val |= WINCONx_BURSTLEN_8WORD;
+		val |= WINCONx_BYTSWP;
+		break;
+	case 16:
+		val |= WINCON0_BPPMODE_16BPP_565;
+		val |= WINCONx_HAWSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	case 24:
+		val |= WINCON0_BPPMODE_24BPP_888;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	case 32:
+		val |= WINCON1_BPPMODE_28BPP_A4888
+			| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	default:
+		DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
+
+		val |= WINCON0_BPPMODE_24BPP_888;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	}
+
+	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+
+	writel(val, ctx->regs + WINCON(win));
+}
+
+static void fimd_win_set_colkey(struct device *dev, unsigned int win)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	unsigned int keycon0 = 0, keycon1 = 0;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
+			WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
+
+	keycon1 = WxKEYCON1_COLVAL(0xffffffff);
+
+	writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
+	writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
+}
+
+static void fimd_win_commit(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data;
+	int win = ctx->default_win;
+	unsigned long val, alpha, size;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (win < 0 || win > WINDOWS_NR)
+		return;
+
+	win_data = &ctx->win_data[win];
+
+	/*
+	 * SHADOWCON register is used for enabling timing.
+	 *
+	 * for example, once only width value of a register is set,
+	 * if the dma is started then fimd hardware could malfunction so
+	 * with protect window setting, the register fields with prefix '_F'
+	 * wouldn't be updated at vsync also but updated once unprotect window
+	 * is set.
+	 */
+
+	/* protect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+
+	/* buffer start address */
+	val = (unsigned long)win_data->dma_addr;
+	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
+
+	/* buffer end address */
+	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
+	val = (unsigned long)(win_data->dma_addr + size);
+	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
+
+	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
+			(unsigned long)win_data->dma_addr, val, size);
+	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+			win_data->ovl_width, win_data->ovl_height);
+
+	/* buffer size */
+	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
+		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
+	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
+
+	/* OSD position */
+	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
+		VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
+	writel(val, ctx->regs + VIDOSD_A(win));
+
+	val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
+					win_data->ovl_width - 1) |
+		VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
+					win_data->ovl_height - 1);
+	writel(val, ctx->regs + VIDOSD_B(win));
+
+	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
+			win_data->offset_x, win_data->offset_y,
+			win_data->offset_x + win_data->ovl_width - 1,
+			win_data->offset_y + win_data->ovl_height - 1);
+
+	/* hardware window 0 doesn't support alpha channel. */
+	if (win != 0) {
+		/* OSD alpha */
+		alpha = VIDISD14C_ALPHA1_R(0xf) |
+			VIDISD14C_ALPHA1_G(0xf) |
+			VIDISD14C_ALPHA1_B(0xf);
+
+		writel(alpha, ctx->regs + VIDOSD_C(win));
+	}
+
+	/* OSD size */
+	if (win != 3 && win != 4) {
+		u32 offset = VIDOSD_D(win);
+		if (win == 0)
+			offset = VIDOSD_C_SIZE_W0;
+		val = win_data->ovl_width * win_data->ovl_height;
+		writel(val, ctx->regs + offset);
+
+		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
+	}
+
+	fimd_win_set_pixfmt(dev, win);
+
+	/* hardware window 0 doesn't support color key. */
+	if (win != 0)
+		fimd_win_set_colkey(dev, win);
+
+	/* Enable DMA channel and unprotect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_CHx_ENABLE(win);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static void fimd_win_disable(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	int win = ctx->default_win;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (win < 0 || win > WINDOWS_NR)
+		return;
+
+	/* protect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+
+	/* wincon */
+	val = readl(ctx->regs + WINCON(win));
+	val &= ~WINCONx_ENWIN;
+	writel(val, ctx->regs + WINCON(win));
+
+	/* unprotect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val &= ~SHADOWCON_CHx_ENABLE(win);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static struct exynos_drm_overlay_ops fimd_overlay_ops = {
+	.mode_set = fimd_win_mode_set,
+	.commit = fimd_win_commit,
+	.disable = fimd_win_disable,
+};
+
+static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
+{
+	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	struct timeval now;
+	unsigned long flags;
+	bool is_checked = false;
+
+	spin_lock_irqsave(&drm_dev->event_lock, flags);
+
+	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
+			base.link) {
+		/* if event's pipe isn't same as crtc then ignore it. */
+		if (crtc != e->pipe)
+			continue;
+
+		is_checked = true;
+
+		do_gettimeofday(&now);
+		e->event.sequence = 0;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+
+		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+
+	if (is_checked)
+		drm_vblank_put(drm_dev, crtc);
+
+	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+}
+
+static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
+{
+	struct fimd_context *ctx = (struct fimd_context *)dev_id;
+	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+	struct drm_device *drm_dev = subdrv->drm_dev;
+	struct exynos_drm_manager *manager = &subdrv->manager;
+	u32 val;
+
+	val = readl(ctx->regs + VIDINTCON1);
+
+	if (val & VIDINTCON1_INT_FRAME)
+		/* VSYNC interrupt */
+		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+
+	/*
+	 * in case that vblank_disable_allowed is 1, it could induce
+	 * the problem that manager->pipe could be -1 because with
+	 * disable callback, vsync interrupt isn't disabled and at this moment,
+	 * vsync interrupt could occur. the vsync interrupt would be disabled
+	 * by timer handler later.
+	 */
+	if (manager->pipe == -1)
+		return IRQ_HANDLED;
+
+	drm_handle_vblank(drm_dev, manager->pipe);
+	fimd_finish_pageflip(drm_dev, manager->pipe);
+
+	return IRQ_HANDLED;
+}
+
+static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * enable drm irq mode.
+	 * - with irq_enabled = 1, we can use the vblank feature.
+	 *
+	 * P.S. note that we wouldn't use drm irq handler but
+	 *	just specific driver own one instead because
+	 *	drm framework supports only one irq handler.
+	 */
+	drm_dev->irq_enabled = 1;
+
+	return 0;
+}
+
+static void fimd_subdrv_remove(struct drm_device *drm_dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+}
+
+static int fimd_calc_clkdiv(struct fimd_context *ctx,
+			    struct fb_videomode *timing)
+{
+	unsigned long clk = clk_get_rate(ctx->lcd_clk);
+	u32 retrace;
+	u32 clkdiv;
+	u32 best_framerate = 0;
+	u32 framerate;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	retrace = timing->left_margin + timing->hsync_len +
+				timing->right_margin + timing->xres;
+	retrace *= timing->upper_margin + timing->vsync_len +
+				timing->lower_margin + timing->yres;
+
+	/* default framerate is 60Hz */
+	if (!timing->refresh)
+		timing->refresh = 60;
+
+	clk /= retrace;
+
+	for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
+		int tmp;
+
+		/* get best framerate */
+		framerate = clk / clkdiv;
+		tmp = timing->refresh - framerate;
+		if (tmp < 0) {
+			best_framerate = framerate;
+			continue;
+		} else {
+			if (!best_framerate)
+				best_framerate = framerate;
+			else if (tmp < (best_framerate - framerate))
+				best_framerate = framerate;
+			break;
+		}
+	}
+
+	return clkdiv;
+}
+
+static void fimd_clear_win(struct fimd_context *ctx, int win)
+{
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	writel(0, ctx->regs + WINCON(win));
+	writel(0, ctx->regs + VIDOSD_A(win));
+	writel(0, ctx->regs + VIDOSD_B(win));
+	writel(0, ctx->regs + VIDOSD_C(win));
+
+	if (win == 1 || win == 2)
+		writel(0, ctx->regs + VIDOSD_D(win));
+
+	val = readl(ctx->regs + SHADOWCON);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static int __devinit fimd_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fimd_context *ctx;
+	struct exynos_drm_subdrv *subdrv;
+	struct exynos_drm_fimd_pdata *pdata;
+	struct fb_videomode *timing;
+	struct resource *res;
+	int win;
+	int ret = -EINVAL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	timing = &pdata->timing;
+	if (!timing) {
+		dev_err(dev, "timing is null.\n");
+		return -EINVAL;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->bus_clk = clk_get(dev, "fimd");
+	if (IS_ERR(ctx->bus_clk)) {
+		dev_err(dev, "failed to get bus clock\n");
+		ret = PTR_ERR(ctx->bus_clk);
+		goto err_clk_get;
+	}
+
+	clk_enable(ctx->bus_clk);
+
+	ctx->lcd_clk = clk_get(dev, "sclk_fimd");
+	if (IS_ERR(ctx->lcd_clk)) {
+		dev_err(dev, "failed to get lcd clock\n");
+		ret = PTR_ERR(ctx->lcd_clk);
+		goto err_bus_clk;
+	}
+
+	clk_enable(ctx->lcd_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to find registers\n");
+		ret = -ENOENT;
+		goto err_clk;
+	}
+
+	ctx->regs_res = request_mem_region(res->start, resource_size(res),
+					   dev_name(dev));
+	if (!ctx->regs_res) {
+		dev_err(dev, "failed to claim register region\n");
+		ret = -ENOENT;
+		goto err_clk;
+	}
+
+	ctx->regs = ioremap(res->start, resource_size(res));
+	if (!ctx->regs) {
+		dev_err(dev, "failed to map registers\n");
+		ret = -ENXIO;
+		goto err_req_region_io;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "irq request failed.\n");
+		goto err_req_region_irq;
+	}
+
+	ctx->irq = res->start;
+
+	for (win = 0; win < WINDOWS_NR; win++)
+		fimd_clear_win(ctx, win);
+
+	ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
+	if (ret < 0) {
+		dev_err(dev, "irq request failed.\n");
+		goto err_req_irq;
+	}
+
+	ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
+	ctx->vidcon0 = pdata->vidcon0;
+	ctx->vidcon1 = pdata->vidcon1;
+	ctx->default_win = pdata->default_win;
+	ctx->timing = timing;
+
+	timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
+
+	DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
+			timing->pixclock, ctx->clkdiv);
+
+	subdrv = &ctx->subdrv;
+
+	subdrv->probe = fimd_subdrv_probe;
+	subdrv->remove = fimd_subdrv_remove;
+	subdrv->manager.pipe = -1;
+	subdrv->manager.ops = &fimd_manager_ops;
+	subdrv->manager.overlay_ops = &fimd_overlay_ops;
+	subdrv->manager.display_ops = &fimd_display_ops;
+	subdrv->manager.dev = dev;
+
+	platform_set_drvdata(pdev, ctx);
+	exynos_drm_subdrv_register(subdrv);
+
+	return 0;
+
+err_req_irq:
+err_req_region_irq:
+	iounmap(ctx->regs);
+
+err_req_region_io:
+	release_resource(ctx->regs_res);
+	kfree(ctx->regs_res);
+
+err_clk:
+	clk_disable(ctx->lcd_clk);
+	clk_put(ctx->lcd_clk);
+
+err_bus_clk:
+	clk_disable(ctx->bus_clk);
+	clk_put(ctx->bus_clk);
+
+err_clk_get:
+	kfree(ctx);
+	return ret;
+}
+
+static int __devexit fimd_remove(struct platform_device *pdev)
+{
+	struct fimd_context *ctx = platform_get_drvdata(pdev);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_subdrv_unregister(&ctx->subdrv);
+
+	clk_disable(ctx->lcd_clk);
+	clk_disable(ctx->bus_clk);
+	clk_put(ctx->lcd_clk);
+	clk_put(ctx->bus_clk);
+
+	iounmap(ctx->regs);
+	release_resource(ctx->regs_res);
+	kfree(ctx->regs_res);
+	free_irq(ctx->irq, ctx);
+
+	kfree(ctx);
+
+	return 0;
+}
+
+static struct platform_driver fimd_driver = {
+	.probe		= fimd_probe,
+	.remove		= __devexit_p(fimd_remove),
+	.driver		= {
+		.name	= "exynos4-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init fimd_init(void)
+{
+	return platform_driver_register(&fimd_driver);
+}
+
+static void __exit fimd_exit(void)
+{
+	platform_driver_unregister(&fimd_driver);
+}
+
+module_init(fimd_init);
+module_exit(fimd_exit);
+
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung DRM FIMD Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.c linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,430 @@
+/* exynos_drm_gem.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+static unsigned int convert_to_vm_err_msg(int msg)
+{
+	unsigned int out_msg;
+
+	switch (msg) {
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+		out_msg = VM_FAULT_NOPAGE;
+		break;
+
+	case -ENOMEM:
+		out_msg = VM_FAULT_OOM;
+		break;
+
+	default:
+		out_msg = VM_FAULT_SIGBUS;
+		break;
+	}
+
+	return out_msg;
+}
+
+static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+static struct exynos_drm_gem_obj
+		*exynos_drm_gem_init(struct drm_device *drm_dev,
+			struct drm_file *file_priv, unsigned int *handle,
+			unsigned int size)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+	struct drm_gem_object *obj;
+	int ret;
+
+	exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
+	if (!exynos_gem_obj) {
+		DRM_ERROR("failed to allocate exynos gem object.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	obj = &exynos_gem_obj->base;
+
+	ret = drm_gem_object_init(drm_dev, obj, size);
+	if (ret < 0) {
+		DRM_ERROR("failed to initialize gem object.\n");
+		ret = -EINVAL;
+		goto err_object_init;
+	}
+
+	DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
+
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret < 0) {
+		DRM_ERROR("failed to allocate mmap offset.\n");
+		goto err_create_mmap_offset;
+	}
+
+	/*
+	 * allocate a id of idr table where the obj is registered
+	 * and handle has the id what user can see.
+	 */
+	ret = drm_gem_handle_create(file_priv, obj, handle);
+	if (ret)
+		goto err_handle_create;
+
+	DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
+
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_unreference_unlocked(obj);
+
+	return exynos_gem_obj;
+
+err_handle_create:
+	drm_gem_free_mmap_offset(obj);
+
+err_create_mmap_offset:
+	drm_gem_object_release(obj);
+
+err_object_init:
+	kfree(exynos_gem_obj);
+
+	return ERR_PTR(ret);
+}
+
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+				struct drm_file *file_priv,
+				unsigned int *handle, unsigned long size)
+{
+
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+	struct exynos_drm_gem_buf *buffer;
+
+	size = roundup(size, PAGE_SIZE);
+
+	DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+
+	buffer = exynos_drm_buf_create(dev, size);
+	if (IS_ERR(buffer)) {
+		return ERR_CAST(buffer);
+	}
+
+	exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size);
+	if (IS_ERR(exynos_gem_obj)) {
+		exynos_drm_buf_destroy(dev, buffer);
+		return exynos_gem_obj;
+	}
+
+	exynos_gem_obj->buffer = buffer;
+
+	return exynos_gem_obj;
+}
+
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_create *args = data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+						&args->handle, args->size);
+	if (IS_ERR(exynos_gem_obj))
+		return PTR_ERR(exynos_gem_obj);
+
+	return 0;
+}
+
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_map_off *args = data;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
+			args->handle, (unsigned long)args->offset);
+
+	if (!(dev->driver->driver_features & DRIVER_GEM)) {
+		DRM_ERROR("does not support GEM.\n");
+		return -ENODEV;
+	}
+
+	return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
+			&args->offset);
+}
+
+static int exynos_drm_gem_mmap_buffer(struct file *filp,
+		struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj = filp->private_data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+	struct exynos_drm_gem_buf *buffer;
+	unsigned long pfn, vm_size;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	vma->vm_flags |= (VM_IO | VM_RESERVED);
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_file = filp;
+
+	vm_size = vma->vm_end - vma->vm_start;
+	/*
+	 * a buffer contains information to physically continuous memory
+	 * allocated by user request or at framebuffer creation.
+	 */
+	buffer = exynos_gem_obj->buffer;
+
+	/* check if user-requested size is valid. */
+	if (vm_size > buffer->size)
+		return -EINVAL;
+
+	/*
+	 * get page frame number to physical memory to be mapped
+	 * to user space.
+	 */
+	pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT;
+
+	DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
+
+	if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
+				vma->vm_page_prot)) {
+		DRM_ERROR("failed to remap pfn range.\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static const struct file_operations exynos_drm_gem_fops = {
+	.mmap = exynos_drm_gem_mmap_buffer,
+};
+
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_mmap *args = data;
+	struct drm_gem_object *obj;
+	unsigned int addr;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!(dev->driver->driver_features & DRIVER_GEM)) {
+		DRM_ERROR("does not support GEM.\n");
+		return -ENODEV;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object.\n");
+		return -EINVAL;
+	}
+
+	obj->filp->f_op = &exynos_drm_gem_fops;
+	obj->filp->private_data = obj;
+
+	down_write(&current->mm->mmap_sem);
+	addr = do_mmap(obj->filp, 0, args->size,
+			PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+	up_write(&current->mm->mmap_sem);
+
+	drm_gem_object_unreference_unlocked(obj);
+
+	if (IS_ERR((void *)addr))
+		return PTR_ERR((void *)addr);
+
+	args->mapped = addr;
+
+	DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
+
+	return 0;
+}
+
+int exynos_drm_gem_init_object(struct drm_gem_object *obj)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return 0;
+}
+
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("handle count = %d\n",
+			atomic_read(&gem_obj->handle_count));
+
+	if (gem_obj->map_list.map)
+		drm_gem_free_mmap_offset(gem_obj);
+
+	/* release file pointer to gem object. */
+	drm_gem_object_release(gem_obj);
+
+	exynos_gem_obj = to_exynos_gem_obj(gem_obj);
+
+	exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer);
+
+	kfree(exynos_gem_obj);
+}
+
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * alocate memory to be used for framebuffer.
+	 * - this callback would be called by user application
+	 *	with DRM_IOCTL_MODE_CREATE_DUMB command.
+	 */
+
+	args->pitch = args->width * args->bpp >> 3;
+	args->size = args->pitch * args->height;
+
+	exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle,
+							args->size);
+	if (IS_ERR(exynos_gem_obj))
+		return PTR_ERR(exynos_gem_obj);
+
+	return 0;
+}
+
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *dev, uint32_t handle, uint64_t *offset)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+	struct drm_gem_object *obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mutex_lock(&dev->struct_mutex);
+
+	/*
+	 * get offset of memory allocated for drm framebuffer.
+	 * - this callback would be called by user application
+	 *	with DRM_IOCTL_MODE_MAP_DUMB command.
+	 */
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object.\n");
+		mutex_unlock(&dev->struct_mutex);
+		return -EINVAL;
+	}
+
+	exynos_gem_obj = to_exynos_gem_obj(obj);
+
+	*offset = get_gem_mmap_offset(&exynos_gem_obj->base);
+
+	drm_gem_object_unreference(obj);
+
+	DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+	struct drm_device *dev = obj->dev;
+	unsigned long pfn;
+	pgoff_t page_offset;
+	int ret;
+
+	page_offset = ((unsigned long)vmf->virtual_address -
+			vma->vm_start) >> PAGE_SHIFT;
+
+	mutex_lock(&dev->struct_mutex);
+
+	pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
+			PAGE_SHIFT) + page_offset;
+
+	ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return convert_to_vm_err_msg(ret);
+}
+
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* set vm_area_struct. */
+	ret = drm_gem_mmap(filp, vma);
+	if (ret < 0) {
+		DRM_ERROR("failed to mmap.\n");
+		return ret;
+	}
+
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	return ret;
+}
+
+
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *dev, unsigned int handle)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * obj->refcount and obj->handle_count are decreased and
+	 * if both them are 0 then exynos_drm_gem_free_object()
+	 * would be called by callback to release resources.
+	 */
+	ret = drm_gem_handle_delete(file_priv, handle);
+	if (ret < 0) {
+		DRM_ERROR("failed to delete drm_gem_handle.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM GEM Module");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.h linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/exynos_drm_gem.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/* exynos_drm_gem.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authoer: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_GEM_H_
+#define _EXYNOS_DRM_GEM_H_
+
+#define to_exynos_gem_obj(x)	container_of(x,\
+			struct exynos_drm_gem_obj, base)
+
+/*
+ * exynos drm gem buffer structure.
+ *
+ * @kvaddr: kernel virtual address to allocated memory region.
+ * @dma_addr: bus address(accessed by dma) to allocated memory region.
+ *	- this address could be physical address without IOMMU and
+ *	device address with IOMMU.
+ * @size: size of allocated memory region.
+ */
+struct exynos_drm_gem_buf {
+	void __iomem		*kvaddr;
+	dma_addr_t		dma_addr;
+	unsigned long		size;
+};
+
+/*
+ * exynos drm buffer structure.
+ *
+ * @base: a gem object.
+ *	- a new handle to this gem object would be created
+ *	by drm_gem_handle_create().
+ * @buffer: a pointer to exynos_drm_gem_buffer object.
+ *	- contain the information to memory region allocated
+ *	by user request or at framebuffer creation.
+ *	continuous memory region allocated by user request
+ *	or at framebuffer creation.
+ *
+ * P.S. this object would be transfered to user as kms_bo.handle so
+ *	user can access the buffer through kms_bo.handle.
+ */
+struct exynos_drm_gem_obj {
+	struct drm_gem_object base;
+	struct exynos_drm_gem_buf *buffer;
+};
+
+/* create a new buffer and get a new gem handle. */
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+		struct drm_file *file_priv,
+		unsigned int *handle, unsigned long size);
+
+/*
+ * request gem object creation and buffer allocation as the size
+ * that it is calculated with framebuffer information such as width,
+ * height and bpp.
+ */
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* get buffer offset to map to user space. */
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* unmap a buffer from user space. */
+int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* initialize gem object. */
+int exynos_drm_gem_init_object(struct drm_gem_object *obj);
+
+/* free gem object. */
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
+
+/* create memory region for drm framebuffer. */
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args);
+
+/* map memory region for drm framebuffer to user space. */
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *dev, uint32_t handle, uint64_t *offset);
+
+/* page fault handler and mmap fault address(virtual) to physical memory. */
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+
+/*
+ * mmap the physically continuous memory that a gem object contains
+ * to user space.
+ */
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* set vm_flags and we can change the vm attribute to other one at here. */
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/*
+ * destroy memory region allocated.
+ *	- a gem handle and physical memory region pointed by a gem object
+ *	would be released by drm_gem_handle_delete().
+ */
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *dev, unsigned int handle);
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/Kconfig linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/Kconfig
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+config DRM_EXYNOS
+	tristate "DRM Support for Samsung SoC EXYNOS Series"
+	depends on DRM && PLAT_SAMSUNG
+	default	n
+	select DRM_KMS_HELPER
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+	help
+	  Choose this option if you have a Samsung SoC EXYNOS chipset.
+	  If M is selected the module will be called exynosdrm.
+
+config DRM_EXYNOS_FIMD
+	tristate "Exynos DRM FIMD"
+	depends on DRM_EXYNOS
+	default n
+	help
+	  Choose this option if you want to use Exynos FIMD for DRM.
+	  If M is selected, the module will be called exynos_drm_fimd
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/Makefile linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/Makefile
--- linux-libre-3.1-gnu1/drivers/gpu/drm/exynos/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/exynos/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
+exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
+		exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
+		exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o
+
+obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
+obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i2c/ch7006_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/i2c/ch7006_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i2c/ch7006_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i2c/ch7006_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "ch7006_priv.h"
 
 /* DRM encoder functions */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i2c/sil164_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/i2c/sil164_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i2c/sil164_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i2c/sil164_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm_crtc_helper.h"
 #include "drm_encoder_slave.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i810/i810_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/i810/i810_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i810/i810_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i810/i810_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "i810_drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ch7017.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ch7017.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ch7017.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ch7017.c	2012-01-04 18:55:44.000000000 -0500
@@ -227,7 +227,7 @@ static bool ch7017_init(struct intel_dvo
 	default:
 		DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
 			      "slave %d.\n",
-			      val, adapter->name,dvo->slave_addr);
+			      val, adapter->name, dvo->slave_addr);
 		goto fail;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ch7xxx.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ch7xxx.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ch7xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ch7xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@ static char *ch7xxx_get_id(uint8_t vid)
 /** Reads an 8 bit register */
 static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
-	struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
+	struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
 	struct i2c_adapter *adapter = dvo->i2c_bus;
 	u8 out_buf[2];
 	u8 in_buf[2];
@@ -303,7 +303,7 @@ static void ch7xxx_dump_regs(struct inte
 
 	for (i = 0; i < CH7xxx_NUM_REGS; i++) {
 		uint8_t val;
-		if ((i % 8) == 0 )
+		if ((i % 8) == 0)
 			DRM_LOG_KMS("\n %02X: ", i);
 		ch7xxx_readb(dvo, i, &val);
 		DRM_LOG_KMS("%02X ", val);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ivch.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ivch.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_ivch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_ivch.c	2012-01-04 18:55:44.000000000 -0500
@@ -344,8 +344,8 @@ static void ivch_mode_set(struct intel_d
 			   (adjusted_mode->hdisplay - 1)) >> 2;
 		y_ratio = (((mode->vdisplay - 1) << 16) /
 			   (adjusted_mode->vdisplay - 1)) >> 2;
-		ivch_write (dvo, VR42, x_ratio);
-		ivch_write (dvo, VR41, y_ratio);
+		ivch_write(dvo, VR42, x_ratio);
+		ivch_write(dvo, VR41, y_ratio);
 	} else {
 		vr01 &= ~VR01_PANEL_FIT_ENABLE;
 		vr40 &= ~VR40_CLOCK_GATING_ENABLE;
@@ -410,7 +410,7 @@ static void ivch_destroy(struct intel_dv
 	}
 }
 
-struct intel_dvo_dev_ops ivch_ops= {
+struct intel_dvo_dev_ops ivch_ops = {
 	.init = ivch_init,
 	.dpms = ivch_dpms,
 	.mode_valid = ivch_mode_valid,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_sil164.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_sil164.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_sil164.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_sil164.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@ static bool sil164_readb(struct intel_dv
 
 static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
-	struct sil164_priv *sil= dvo->dev_priv;
+	struct sil164_priv *sil = dvo->dev_priv;
 	struct i2c_adapter *adapter = dvo->i2c_bus;
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_tfp410.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_tfp410.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/dvo_tfp410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/dvo_tfp410.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 #define TFP410_CTL_2_MDI	(1<<0)
 
 #define TFP410_CTL_3		0x0A
-#define TFP410_CTL_3_DK_MASK 	(0x7<<5)
+#define TFP410_CTL_3_DK_MASK	(0x7<<5)
 #define TFP410_CTL_3_DK		(1<<5)
 #define TFP410_CTL_3_DKEN	(1<<4)
 #define TFP410_CTL_3_CTL_MASK	(0x7<<1)
@@ -225,12 +225,12 @@ static void tfp410_mode_set(struct intel
 			    struct drm_display_mode *mode,
 			    struct drm_display_mode *adjusted_mode)
 {
-    /* As long as the basics are set up, since we don't have clock dependencies
-     * in the mode setup, we can just leave the registers alone and everything
-     * will work fine.
-     */
-    /* don't do much */
-    return;
+	/* As long as the basics are set up, since we don't have clock dependencies
+	* in the mode setup, we can just leave the registers alone and everything
+	* will work fine.
+	*/
+	/* don't do much */
+	return;
 }
 
 /* set the tfp410 power state */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "intel_drv.h"
@@ -61,6 +62,7 @@ static int i915_capabilities(struct seq_
 	const struct intel_device_info *info = INTEL_INFO(dev);
 
 	seq_printf(m, "gen: %d\n", info->gen);
+	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
 #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
 	B(is_mobile);
 	B(is_i85x);
@@ -98,12 +100,12 @@ static const char *get_pin_flag(struct d
 
 static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
 {
-    switch (obj->tiling_mode) {
-    default:
-    case I915_TILING_NONE: return " ";
-    case I915_TILING_X: return "X";
-    case I915_TILING_Y: return "Y";
-    }
+	switch (obj->tiling_mode) {
+	default:
+	case I915_TILING_NONE: return " ";
+	case I915_TILING_X: return "X";
+	case I915_TILING_Y: return "Y";
+	}
 }
 
 static const char *cache_level_str(int type)
@@ -217,7 +219,7 @@ static int i915_gem_object_list_info(str
 			++mappable_count; \
 		} \
 	} \
-} while(0)
+} while (0)
 
 static int i915_gem_object_info(struct seq_file *m, void* data)
 {
@@ -635,11 +637,16 @@ static int i915_ringbuffer_info(struct s
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
+	int ret;
 
 	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
 	if (ring->size == 0)
 		return 0;
 
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	seq_printf(m, "Ring %s:\n", ring->name);
 	seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
 	seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
@@ -653,6 +660,8 @@ static int i915_ringbuffer_info(struct s
 	seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
 	seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -841,7 +850,16 @@ static int i915_rstdby_delays(struct seq
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	u16 crstanddelay = I915_READ16(CRSTANDVID);
+	u16 crstanddelay;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	crstanddelay = I915_READ16(CRSTANDVID);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
 
@@ -939,7 +957,11 @@ static int i915_delayfreq_table(struct s
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 delayfreq;
-	int i;
+	int ret, i;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	for (i = 0; i < 16; i++) {
 		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -947,6 +969,8 @@ static int i915_delayfreq_table(struct s
 			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -961,13 +985,19 @@ static int i915_inttoext_table(struct se
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 inttoext;
-	int i;
+	int ret, i;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	for (i = 1; i <= 32; i++) {
 		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
 		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -976,9 +1006,19 @@ static int i915_drpc_info(struct seq_fil
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	u32 rgvmodectl = I915_READ(MEMMODECTL);
-	u32 rstdbyctl = I915_READ(RSTDBYCTL);
-	u16 crstandvid = I915_READ16(CRSTANDVID);
+	u32 rgvmodectl, rstdbyctl;
+	u16 crstandvid;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	rgvmodectl = I915_READ(MEMMODECTL);
+	rstdbyctl = I915_READ(RSTDBYCTL);
+	crstandvid = I915_READ16(CRSTANDVID);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
 		   "yes" : "no");
@@ -1166,9 +1206,16 @@ static int i915_gfxec(struct seq_file *m
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -1293,12 +1340,12 @@ i915_wedged_read(struct file *filp,
 	char buf[80];
 	int len;
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "wedged :  %d\n",
 		       atomic_read(&dev_priv->mm.wedged));
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1314,7 +1361,7 @@ i915_wedged_write(struct file *filp,
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1357,11 +1404,11 @@ i915_max_freq_read(struct file *filp,
 	char buf[80];
 	int len;
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "max freq: %d\n", dev_priv->max_delay * 50);
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1378,7 +1425,7 @@ i915_max_freq_write(struct file *filp,
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1432,12 +1479,12 @@ i915_cache_sharing_read(struct file *fil
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
 		       GEN6_MBC_SNPCR_SHIFT);
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1455,7 +1502,7 @@ i915_cache_sharing_write(struct file *fi
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1505,7 +1552,10 @@ drm_add_fake_info_node(struct drm_minor
 	node->minor = minor;
 	node->dent = ent;
 	node->info_ent = (void *) key;
-	list_add(&node->list, &minor->debugfs_nodes.list);
+
+	mutex_lock(&minor->debugfs_lock);
+	list_add(&node->list, &minor->debugfs_list);
+	mutex_unlock(&minor->debugfs_lock);
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_dma.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/pnp.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <acpi/video.h>
 
 static void i915_write_hws_pga(struct drm_device *dev)
@@ -884,7 +885,7 @@ static int i915_get_bridge_dev(struct dr
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
 	if (!dev_priv->bridge_dev) {
 		DRM_ERROR("bridge device not found\n");
 		return -1;
@@ -1453,6 +1454,14 @@ unsigned long i915_chipset_val(struct dr
 
 	diff1 = now - dev_priv->last_time1;
 
+	/* Prevent division-by-zero if we are asking too fast.
+	 * Also, we don't get interesting results if we are polling
+	 * faster than once in 10ms, so just return the saved value
+	 * in such cases.
+	 */
+	if (diff1 <= 10)
+		return dev_priv->chipset_power;
+
 	count1 = I915_READ(DMIEC);
 	count2 = I915_READ(DDREC);
 	count3 = I915_READ(CSIEC);
@@ -1483,6 +1492,8 @@ unsigned long i915_chipset_val(struct dr
 	dev_priv->last_count1 = total_count;
 	dev_priv->last_time1 = now;
 
+	dev_priv->chipset_power = ret;
+
 	return ret;
 }
 
@@ -1730,10 +1741,10 @@ static DEFINE_SPINLOCK(mchdev_lock);
  */
 unsigned long i915_read_mch_val(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	unsigned long chipset_val, graphics_val, ret = 0;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
@@ -1744,9 +1755,9 @@ unsigned long i915_read_mch_val(void)
 	ret = chipset_val + graphics_val;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_read_mch_val);
 
@@ -1757,10 +1768,10 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
  */
 bool i915_gpu_raise(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1771,9 +1782,9 @@ bool i915_gpu_raise(void)
 		dev_priv->max_delay--;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_raise);
 
@@ -1785,10 +1796,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
  */
 bool i915_gpu_lower(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1799,9 +1810,9 @@ bool i915_gpu_lower(void)
 		dev_priv->max_delay++;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_lower);
 
@@ -1812,10 +1823,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
  */
 bool i915_gpu_busy(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = false;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
@@ -1823,9 +1834,9 @@ bool i915_gpu_busy(void)
 	ret = dev_priv->busy;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_busy);
 
@@ -1837,10 +1848,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
  */
 bool i915_gpu_turbo_disable(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1853,9 +1864,9 @@ bool i915_gpu_turbo_disable(void)
 		ret = false;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
@@ -1948,7 +1959,7 @@ int i915_driver_load(struct drm_device *
 
 	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
-        dev_priv->mm.gtt_mapping =
+	dev_priv->mm.gtt_mapping =
 		io_mapping_create_wc(dev->agp->base, agp_size);
 	if (dev_priv->mm.gtt_mapping == NULL) {
 		ret = -EIO;
@@ -2035,7 +2046,9 @@ int i915_driver_load(struct drm_device *
 	spin_lock_init(&dev_priv->error_lock);
 	spin_lock_init(&dev_priv->rps_lock);
 
-	if (IS_MOBILE(dev) || !IS_GEN2(dev))
+	if (IS_IVYBRIDGE(dev))
+		dev_priv->num_pipe = 3;
+	else if (IS_MOBILE(dev) || !IS_GEN2(dev))
 		dev_priv->num_pipe = 2;
 	else
 		dev_priv->num_pipe = 1;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "intel_drv.h"
 
 #include <linux/console.h>
+#include <linux/module.h>
 #include "drm_crtc_helper.h"
 
 static int i915_modeset __read_mostly = -1;
@@ -57,17 +58,17 @@ module_param_named(powersave, i915_power
 MODULE_PARM_DESC(powersave,
 		"Enable powersavings, fbc, downclocking, etc. (default: true)");
 
-unsigned int i915_semaphores __read_mostly = 0;
+int i915_semaphores __read_mostly = -1;
 module_param_named(semaphores, i915_semaphores, int, 0600);
 MODULE_PARM_DESC(semaphores,
-		"Use semaphores for inter-ring sync (default: false)");
+		"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
 
-unsigned int i915_enable_rc6 __read_mostly = 0;
+int i915_enable_rc6 __read_mostly = -1;
 module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
 MODULE_PARM_DESC(i915_enable_rc6,
-		"Enable power-saving render C-state 6 (default: true)");
+		"Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
 
-unsigned int i915_enable_fbc __read_mostly = -1;
+int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
 MODULE_PARM_DESC(i915_enable_fbc,
 		"Enable frame buffer compression for power savings "
@@ -79,11 +80,11 @@ MODULE_PARM_DESC(lvds_downclock,
 		"Use panel (LVDS/eDP) downclocking for power savings "
 		"(default: false)");
 
-unsigned int i915_panel_use_ssc __read_mostly = 1;
+int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
 		"Use Spread Spectrum Clock with panels [LVDS/eDP] "
-		"(default: true)");
+		"(default: auto from VBT)");
 
 int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
@@ -106,7 +107,7 @@ static struct drm_driver driver;
 extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {		\
-	.class = PCI_CLASS_DISPLAY_VGA << 8,	\
+	.class = PCI_BASE_CLASS_DISPLAY << 16,	\
 	.class_mask = 0xff0000,			\
 	.vendor = 0x8086,			\
 	.device = id,				\
@@ -294,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00
 #define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00
 
-void intel_detect_pch (struct drm_device *dev)
+void intel_detect_pch(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct pci_dev *pch;
@@ -327,7 +328,7 @@ void intel_detect_pch (struct drm_device
 	}
 }
 
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	int count;
 
@@ -343,6 +344,22 @@ static void __gen6_gt_force_wake_get(str
 		udelay(10);
 }
 
+void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+{
+	int count;
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
+		udelay(10);
+
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
+	POSTING_READ(FORCEWAKE_MT);
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
+		udelay(10);
+}
+
 /*
  * Generally this is called implicitly by the register read function. However,
  * if some sequence requires the GT to not power down then this function should
@@ -355,15 +372,21 @@ void gen6_gt_force_wake_get(struct drm_i
 
 	/* Forcewake is atomic in case we get in here without the lock */
 	if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
-		__gen6_gt_force_wake_get(dev_priv);
+		dev_priv->display.force_wake_get(dev_priv);
 }
 
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE, 0);
 	POSTING_READ(FORCEWAKE);
 }
 
+void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
+	POSTING_READ(FORCEWAKE_MT);
+}
+
 /*
  * see gen6_gt_force_wake_get()
  */
@@ -372,12 +395,12 @@ void gen6_gt_force_wake_put(struct drm_i
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
 	if (atomic_dec_and_test(&dev_priv->forcewake_count))
-		__gen6_gt_force_wake_put(dev_priv);
+		dev_priv->display.force_wake_put(dev_priv);
 }
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
-	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) {
+	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
 		int loop = 500;
 		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
 		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
@@ -471,6 +494,9 @@ static int i915_drm_thaw(struct drm_devi
 		error = i915_gem_init_ringbuffer(dev);
 		mutex_unlock(&dev->struct_mutex);
 
+		if (HAS_PCH_SPLIT(dev))
+			ironlake_init_pch_refclk(dev);
+
 		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 
@@ -770,12 +796,12 @@ static int i915_pm_poweroff(struct devic
 }
 
 static const struct dev_pm_ops i915_pm_ops = {
-     .suspend = i915_pm_suspend,
-     .resume = i915_pm_resume,
-     .freeze = i915_pm_freeze,
-     .thaw = i915_pm_thaw,
-     .poweroff = i915_pm_poweroff,
-     .restore = i915_pm_resume,
+	.suspend = i915_pm_suspend,
+	.resume = i915_pm_resume,
+	.freeze = i915_pm_freeze,
+	.thaw = i915_pm_thaw,
+	.poweroff = i915_pm_poweroff,
+	.restore = i915_pm_resume,
 };
 
 static struct vm_operations_struct i915_gem_vm_ops = {
@@ -785,8 +811,8 @@ static struct vm_operations_struct i915_
 };
 
 static struct drm_driver driver = {
-	/* don't use mtrr's here, the Xserver or user space app should
-	 * deal with them for intel hardware.
+	/* Don't use MTRRs here; the Xserver or userspace app should
+	 * deal with them for Intel hardware.
 	 */
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
@@ -895,3 +921,44 @@ module_exit(i915_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
+
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+	(((dev_priv)->info->gen >= 6) && \
+	 ((reg) < 0x40000) &&		 \
+	 ((reg) != FORCEWAKE) &&	 \
+	 ((reg) != ECOBUS))
+
+#define __i915_read(x, y) \
+u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+	u##x val = 0; \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		gen6_gt_force_wake_get(dev_priv); \
+		val = read##y(dev_priv->regs + reg); \
+		gen6_gt_force_wake_put(dev_priv); \
+	} else { \
+		val = read##y(dev_priv->regs + reg); \
+	} \
+	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
+	return val; \
+}
+
+__i915_read(8, b)
+__i915_read(16, w)
+__i915_read(32, l)
+__i915_read(64, q)
+#undef __i915_read
+
+#define __i915_write(x, y) \
+void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		__gen6_gt_wait_for_fifo(dev_priv); \
+	} \
+	write##y(val, dev_priv->regs + reg); \
+}
+__i915_write(8, b)
+__i915_write(16, w)
+__i915_write(32, l)
+__i915_write(64, q)
+#undef __i915_write
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_drv.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,7 @@ struct opregion_header;
 struct opregion_acpi;
 struct opregion_swsci;
 struct opregion_asle;
+struct drm_i915_private;
 
 struct intel_opregion {
 	struct opregion_header *header;
@@ -126,6 +127,9 @@ struct drm_i915_master_private {
 	struct _drm_i915_sarea *sarea_priv;
 };
 #define I915_FENCE_REG_NONE -1
+#define I915_MAX_NUM_FENCES 16
+/* 16 fences + sign bit for FENCE_REG_NONE */
+#define I915_MAX_NUM_FENCE_BITS 5
 
 struct drm_i915_fence_reg {
 	struct list_head lru_list;
@@ -139,7 +143,6 @@ struct sdvo_device_mapping {
 	u8 slave_addr;
 	u8 dvo_wiring;
 	u8 i2c_pin;
-	u8 i2c_speed;
 	u8 ddc_pin;
 };
 
@@ -169,7 +172,7 @@ struct drm_i915_error_state {
 	u32 instdone1;
 	u32 seqno;
 	u64 bbaddr;
-	u64 fence[16];
+	u64 fence[I915_MAX_NUM_FENCES];
 	struct timeval time;
 	struct drm_i915_error_object {
 		int page_count;
@@ -183,7 +186,7 @@ struct drm_i915_error_state {
 		u32 gtt_offset;
 		u32 read_domains;
 		u32 write_domain;
-		s32 fence_reg:5;
+		s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
 		s32 pinned:2;
 		u32 tiling:2;
 		u32 dirty:1;
@@ -209,6 +212,8 @@ struct drm_i915_display_funcs {
 			     struct drm_display_mode *adjusted_mode,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
+	void (*write_eld)(struct drm_connector *connector,
+			  struct drm_crtc *crtc);
 	void (*fdi_link_train)(struct drm_crtc *crtc);
 	void (*init_clock_gating)(struct drm_device *dev);
 	void (*init_pch_clock_gating)(struct drm_device *dev);
@@ -217,6 +222,8 @@ struct drm_i915_display_funcs {
 			  struct drm_i915_gem_object *obj);
 	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			    int x, int y);
+	void (*force_wake_get)(struct drm_i915_private *dev_priv);
+	void (*force_wake_put)(struct drm_i915_private *dev_priv);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
@@ -226,26 +233,26 @@ struct drm_i915_display_funcs {
 
 struct intel_device_info {
 	u8 gen;
-	u8 is_mobile : 1;
-	u8 is_i85x : 1;
-	u8 is_i915g : 1;
-	u8 is_i945gm : 1;
-	u8 is_g33 : 1;
-	u8 need_gfx_hws : 1;
-	u8 is_g4x : 1;
-	u8 is_pineview : 1;
-	u8 is_broadwater : 1;
-	u8 is_crestline : 1;
-	u8 is_ivybridge : 1;
-	u8 has_fbc : 1;
-	u8 has_pipe_cxsr : 1;
-	u8 has_hotplug : 1;
-	u8 cursor_needs_physical : 1;
-	u8 has_overlay : 1;
-	u8 overlay_needs_physical : 1;
-	u8 supports_tv : 1;
-	u8 has_bsd_ring : 1;
-	u8 has_blt_ring : 1;
+	u8 is_mobile:1;
+	u8 is_i85x:1;
+	u8 is_i915g:1;
+	u8 is_i945gm:1;
+	u8 is_g33:1;
+	u8 need_gfx_hws:1;
+	u8 is_g4x:1;
+	u8 is_pineview:1;
+	u8 is_broadwater:1;
+	u8 is_crestline:1;
+	u8 is_ivybridge:1;
+	u8 has_fbc:1;
+	u8 has_pipe_cxsr:1;
+	u8 has_hotplug:1;
+	u8 cursor_needs_physical:1;
+	u8 has_overlay:1;
+	u8 overlay_needs_physical:1;
+	u8 supports_tv:1;
+	u8 has_bsd_ring:1;
+	u8 has_blt_ring:1;
 };
 
 enum no_fbc_reason {
@@ -347,7 +354,6 @@ typedef struct drm_i915_private {
 	/* LVDS info */
 	int backlight_level;  /* restore backlight to this value */
 	bool backlight_enabled;
-	struct drm_display_mode *panel_fixed_mode;
 	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
 	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
 
@@ -357,6 +363,7 @@ typedef struct drm_i915_private {
 	unsigned int lvds_vbt:1;
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
+	unsigned int display_clock_mode:1;
 	int lvds_ssc_freq;
 	struct {
 		int rate;
@@ -374,7 +381,7 @@ typedef struct drm_i915_private {
 	struct notifier_block lid_notifier;
 
 	int crt_ddc_pin;
-	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
+	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
@@ -505,7 +512,7 @@ typedef struct drm_i915_private {
 	u8 saveAR[21];
 	u8 saveDACMASK;
 	u8 saveCR[37];
-	uint64_t saveFENCE[16];
+	uint64_t saveFENCE[I915_MAX_NUM_FENCES];
 	u32 saveCURACNTR;
 	u32 saveCURAPOS;
 	u32 saveCURABASE;
@@ -672,10 +679,9 @@ typedef struct drm_i915_private {
 	unsigned int lvds_border_bits;
 	/* Panel fitter placement and size for Ironlake+ */
 	u32 pch_pf_pos, pch_pf_size;
-	int panel_t3, panel_t12;
 
-	struct drm_crtc *plane_to_crtc_mapping[2];
-	struct drm_crtc *pipe_to_crtc_mapping[2];
+	struct drm_crtc *plane_to_crtc_mapping[3];
+	struct drm_crtc *pipe_to_crtc_mapping[3];
 	wait_queue_head_t pending_flip_queue;
 	bool flip_pending_is_done;
 
@@ -707,6 +713,7 @@ typedef struct drm_i915_private {
 
 	u64 last_count1;
 	unsigned long last_time1;
+	unsigned long chipset_power;
 	u64 last_count2;
 	struct timespec last_time2;
 	unsigned long gfx_power;
@@ -759,39 +766,37 @@ struct drm_i915_gem_object {
 	 * (has pending rendering), and is not set if it's on inactive (ready
 	 * to be unbound).
 	 */
-	unsigned int active : 1;
+	unsigned int active:1;
 
 	/**
 	 * This is set if the object has been written to since last bound
 	 * to the GTT
 	 */
-	unsigned int dirty : 1;
+	unsigned int dirty:1;
 
 	/**
 	 * This is set if the object has been written to since the last
 	 * GPU flush.
 	 */
-	unsigned int pending_gpu_write : 1;
+	unsigned int pending_gpu_write:1;
 
 	/**
 	 * Fence register bits (if any) for this object.  Will be set
 	 * as needed when mapped into the GTT.
 	 * Protected by dev->struct_mutex.
-	 *
-	 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
 	 */
-	signed int fence_reg : 5;
+	signed int fence_reg:I915_MAX_NUM_FENCE_BITS;
 
 	/**
 	 * Advice: are the backing pages purgeable?
 	 */
-	unsigned int madv : 2;
+	unsigned int madv:2;
 
 	/**
 	 * Current tiling mode for the object.
 	 */
-	unsigned int tiling_mode : 2;
-	unsigned int tiling_changed : 1;
+	unsigned int tiling_mode:2;
+	unsigned int tiling_changed:1;
 
 	/** How many users have pinned this object in GTT space. The following
 	 * users can each hold at most one reference: pwrite/pread, pin_ioctl
@@ -802,22 +807,22 @@ struct drm_i915_gem_object {
 	 *
 	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
 	 * bits with absolutely no headroom. So use 4 bits. */
-	unsigned int pin_count : 4;
+	unsigned int pin_count:4;
 #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 
 	/**
 	 * Is the object at the current location in the gtt mappable and
 	 * fenceable? Used to avoid costly recalculations.
 	 */
-	unsigned int map_and_fenceable : 1;
+	unsigned int map_and_fenceable:1;
 
 	/**
 	 * Whether the current gtt mapping needs to be mappable (and isn't just
 	 * mappable by accident). Track pin and fault separate for a more
 	 * accurate mappable working set.
 	 */
-	unsigned int fault_mappable : 1;
-	unsigned int pin_mappable : 1;
+	unsigned int fault_mappable:1;
+	unsigned int pin_mappable:1;
 
 	/*
 	 * Is the GPU currently using a fence to access this buffer,
@@ -997,12 +1002,12 @@ extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc __always_unused;
 extern int i915_panel_ignore_lid __read_mostly;
 extern unsigned int i915_powersave __read_mostly;
-extern unsigned int i915_semaphores __read_mostly;
+extern int i915_semaphores __read_mostly;
 extern unsigned int i915_lvds_downclock __read_mostly;
-extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
-extern unsigned int i915_enable_rc6 __read_mostly;
-extern unsigned int i915_enable_fbc __read_mostly;
+extern int i915_enable_rc6 __read_mostly;
+extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
@@ -1056,7 +1061,7 @@ i915_enable_pipestat(drm_i915_private_t
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
-void intel_enable_asle (struct drm_device *dev);
+void intel_enable_asle(struct drm_device *dev);
 
 #ifdef CONFIG_DEBUG_FS
 extern void i915_destroy_error_state(struct drm_device *dev);
@@ -1146,7 +1151,7 @@ int i915_gem_dumb_create(struct drm_file
 int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
 		      uint32_t handle, uint64_t *offset);
 int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
-			  uint32_t handle);			  
+			  uint32_t handle);
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1301,10 +1306,16 @@ extern int intel_modeset_vga_set_state(s
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
+extern void ironlake_init_pch_refclk(struct drm_device *dev);
 extern void ironlake_enable_rc6(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
-extern void intel_detect_pch (struct drm_device *dev);
-extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
+extern void intel_detect_pch(struct drm_device *dev);
+extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
+
+extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
 
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
@@ -1350,22 +1361,12 @@ void __gen6_gt_wait_for_fifo(struct drm_
 /* We give fast paths for the really cool registers */
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	(((dev_priv)->info->gen >= 6) && \
-	((reg) < 0x40000) && \
-	((reg) != FORCEWAKE))
+	 ((reg) < 0x40000) &&		 \
+	 ((reg) != FORCEWAKE) &&	 \
+	 ((reg) != ECOBUS))
 
 #define __i915_read(x, y) \
-static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
-	u##x val = 0; \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		gen6_gt_force_wake_get(dev_priv); \
-		val = read##y(dev_priv->regs + reg); \
-		gen6_gt_force_wake_put(dev_priv); \
-	} else { \
-		val = read##y(dev_priv->regs + reg); \
-	} \
-	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
-	return val; \
-}
+	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
 
 __i915_read(8, b)
 __i915_read(16, w)
@@ -1374,13 +1375,8 @@ __i915_read(64, q)
 #undef __i915_read
 
 #define __i915_write(x, y) \
-static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
-	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		__gen6_gt_wait_for_fifo(dev_priv); \
-	} \
-	write##y(val, dev_priv->regs + reg); \
-}
+	void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
+
 __i915_write(8, b)
 __i915_write(16, w)
 __i915_write(32, l)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,7 +179,7 @@ i915_gem_get_aperture_ioctl(struct drm_d
 	mutex_unlock(&dev->struct_mutex);
 
 	args->aper_size = dev_priv->mm.gtt_total;
-	args->aper_available_size = args->aper_size -pinned;
+	args->aper_available_size = args->aper_size - pinned;
 
 	return 0;
 }
@@ -195,6 +195,8 @@ i915_gem_create(struct drm_file *file,
 	u32 handle;
 
 	size = roundup(size, PAGE_SIZE);
+	if (size == 0)
+		return -EINVAL;
 
 	/* Allocate the new object */
 	obj = i915_gem_alloc_object(dev, size);
@@ -800,11 +802,11 @@ i915_gem_shmem_pwrite_fast(struct drm_de
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
-		vaddr = kmap_atomic(page, KM_USER0);
+		vaddr = kmap_atomic(page);
 		ret = __copy_from_user_inatomic(vaddr + page_offset,
 						user_data,
 						page_length);
-		kunmap_atomic(vaddr, KM_USER0);
+		kunmap_atomic(vaddr);
 
 		set_page_dirty(page);
 		mark_page_accessed(page);
@@ -1265,74 +1267,6 @@ out:
 }
 
 /**
- * i915_gem_create_mmap_offset - create a fake mmap offset for an object
- * @obj: obj in question
- *
- * GEM memory mapping works by handing back to userspace a fake mmap offset
- * it can use in a subsequent mmap(2) call.  The DRM core code then looks
- * up the object based on the offset and sets up the various memory mapping
- * structures.
- *
- * This routine allocates and attaches a fake offset for @obj.
- */
-static int
-i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret = 0;
-
-	/* Set the object up for mmap'ing */
-	list = &obj->base.map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (!list->map)
-		return -ENOMEM;
-
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->base.size;
-	map->handle = obj;
-
-	/* Get a DRM GEM mmap offset allocated... */
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-						    obj->base.size / PAGE_SIZE,
-						    0, 0);
-	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n",
-			  obj->base.name);
-		ret = -ENOSPC;
-		goto out_free_list;
-	}
-
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-						  obj->base.size / PAGE_SIZE,
-						  0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto out_free_list;
-	}
-
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
-		goto out_free_mm;
-	}
-
-	return 0;
-
-out_free_mm:
-	drm_mm_put_block(list->file_offset_node);
-out_free_list:
-	kfree(list->map);
-	list->map = NULL;
-
-	return ret;
-}
-
-/**
  * i915_gem_release_mmap - remove physical page mappings
  * @obj: obj in question
  *
@@ -1360,19 +1294,6 @@ i915_gem_release_mmap(struct drm_i915_ge
 	obj->fault_mappable = false;
 }
 
-static void
-i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list = &obj->base.map_list;
-
-	drm_ht_remove_item(&mm->offset_hash, &list->hash);
-	drm_mm_put_block(list->file_offset_node);
-	kfree(list->map);
-	list->map = NULL;
-}
-
 static uint32_t
 i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
 {
@@ -1475,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 
 	if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
 		ret = -E2BIG;
-		goto unlock;
+		goto out;
 	}
 
 	if (obj->madv != I915_MADV_WILLNEED) {
@@ -1485,7 +1406,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 	}
 
 	if (!obj->base.map_list.map) {
-		ret = i915_gem_create_mmap_offset(obj);
+		ret = drm_gem_create_mmap_offset(&obj->base);
 		if (ret)
 			goto out;
 	}
@@ -1557,7 +1478,7 @@ i915_gem_object_get_pages_gtt(struct drm
 		obj->pages[i] = page;
 	}
 
-	if (obj->tiling_mode != I915_TILING_NONE)
+	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_do_bit_17_swizzle(obj);
 
 	return 0;
@@ -1579,7 +1500,7 @@ i915_gem_object_put_pages_gtt(struct drm
 
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
-	if (obj->tiling_mode != I915_TILING_NONE)
+	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_save_bit_17_swizzle(obj);
 
 	if (obj->madv == I915_MADV_DONTNEED)
@@ -1824,7 +1745,7 @@ static void i915_gem_reset_fences(struct
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < dev_priv->num_fence_regs; i++) {
 		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
 		struct drm_i915_gem_object *obj = reg->obj;
 
@@ -1856,7 +1777,7 @@ void i915_gem_reset(struct drm_device *d
 	 * lost bo to the inactive list.
 	 */
 	while (!list_empty(&dev_priv->mm.flushing_list)) {
-		obj= list_first_entry(&dev_priv->mm.flushing_list,
+		obj = list_first_entry(&dev_priv->mm.flushing_list,
 				      struct drm_i915_gem_object,
 				      mm_list);
 
@@ -1922,7 +1843,7 @@ i915_gem_retire_requests_ring(struct int
 	while (!list_empty(&ring->active_list)) {
 		struct drm_i915_gem_object *obj;
 
-		obj= list_first_entry(&ring->active_list,
+		obj = list_first_entry(&ring->active_list,
 				      struct drm_i915_gem_object,
 				      ring_list);
 
@@ -2272,14 +2193,8 @@ int
 i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	bool lists_empty;
 	int ret, i;
 
-	lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
-		       list_empty(&dev_priv->mm.active_list));
-	if (lists_empty)
-		return 0;
-
 	/* Flush everything onto the inactive list. */
 	for (i = 0; i < I915_NUM_RINGS; i++) {
 		ret = i915_ring_idle(&dev_priv->ring[i]);
@@ -2882,7 +2797,7 @@ i915_gem_object_bind_to_gtt(struct drm_i
 
 	fenceable =
 		obj->gtt_space->size == fence_size &&
-		(obj->gtt_space->start & (fence_alignment -1)) == 0;
+		(obj->gtt_space->start & (fence_alignment - 1)) == 0;
 
 	mappable =
 		obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
@@ -3597,9 +3512,11 @@ i915_gem_busy_ioctl(struct drm_device *d
 			 * so emit a request to do so.
 			 */
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
-			if (request)
-				ret = i915_add_request(obj->ring, NULL,request);
-			else
+			if (request) {
+				ret = i915_add_request(obj->ring, NULL, request);
+				if (ret)
+					kfree(request);
+			} else
 				ret = -ENOMEM;
 		}
 
@@ -3623,7 +3540,7 @@ int
 i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-    return i915_gem_ring_throttle(dev, file_priv);
+	return i915_gem_ring_throttle(dev, file_priv);
 }
 
 int
@@ -3698,7 +3615,7 @@ struct drm_i915_gem_object *i915_gem_all
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-	if (IS_GEN6(dev)) {
+	if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		/* On Gen6, we can have the GPU use the LLC (the CPU
 		 * cache) for about a 10% performance improvement
 		 * compared to uncached.  Graphics requests other than
@@ -3752,7 +3669,7 @@ static void i915_gem_free_object_tail(st
 	trace_i915_gem_object_destroy(obj);
 
 	if (obj->base.map_list.map)
-		i915_gem_free_mmap_offset(obj);
+		drm_gem_free_mmap_offset(&obj->base);
 
 	drm_gem_object_release(&obj->base);
 	i915_gem_info_remove_obj(dev_priv, obj->base.size);
@@ -3962,7 +3879,7 @@ i915_gem_load(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
 	for (i = 0; i < I915_NUM_RINGS; i++)
 		init_ring_lists(&dev_priv->ring[i]);
-	for (i = 0; i < 16; i++)
+	for (i = 0; i < I915_MAX_NUM_FENCES; i++)
 		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
 			  i915_gem_retire_work_handler);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,7 +72,7 @@ i915_verify_lists(struct drm_device *dev
 			break;
 		} else if (!obj->active ||
 			   (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 ||
-			   list_empty(&obj->gpu_write_list)){
+			   list_empty(&obj->gpu_write_list)) {
 			DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n",
 				  obj,
 				  obj->active,
@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct d
 	for (page = 0; page < obj->size / PAGE_SIZE; page++) {
 		int i;
 
-		backing_map = kmap_atomic(obj->pages[page], KM_USER0);
+		backing_map = kmap_atomic(obj->pages[page]);
 
 		if (backing_map == NULL) {
 			DRM_ERROR("failed to map backing page\n");
@@ -181,13 +181,13 @@ i915_gem_object_check_coherency(struct d
 				}
 			}
 		}
-		kunmap_atomic(backing_map, KM_USER0);
+		kunmap_atomic(backing_map);
 		backing_map = NULL;
 	}
 
  out:
 	if (backing_map != NULL)
-		kunmap_atomic(backing_map, KM_USER0);
+		kunmap_atomic(backing_map);
 	iounmap(gtt_mapping);
 
 	/* give syslog time to catch up */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c	2012-01-04 18:55:44.000000000 -0500
@@ -122,7 +122,7 @@ i915_gem_evict_something(struct drm_devi
 			goto found;
 	}
 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		if (! obj->base.write_domain || obj->pin_count)
+		if (!obj->base.write_domain || obj->pin_count)
 			continue;
 
 		if (mark_free(obj, &unwind_list))
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/dma_remapping.h>
 
 struct change_domains {
 	uint32_t invalidate_domains;
@@ -746,6 +747,22 @@ i915_gem_execbuffer_flush(struct drm_dev
 	return 0;
 }
 
+static bool
+intel_enable_semaphores(struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen < 6)
+		return 0;
+
+	if (i915_semaphores >= 0)
+		return i915_semaphores;
+
+	/* Disable semaphores on SNB */
+	if (INTEL_INFO(dev)->gen == 6)
+		return 0;
+
+	return 1;
+}
+
 static int
 i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
 			       struct intel_ring_buffer *to)
@@ -758,7 +775,7 @@ i915_gem_execbuffer_sync_rings(struct dr
 		return 0;
 
 	/* XXX gpu semaphores are implicated in various hard hangs on SNB */
-	if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
+	if (!intel_enable_semaphores(obj->base.dev))
 		return i915_gem_object_wait_rendering(obj);
 
 	idx = intel_ring_sync_index(from, to);
@@ -784,7 +801,8 @@ i915_gem_execbuffer_sync_rings(struct dr
 	}
 
 	from->sync_seqno[idx] = seqno;
-	return intel_ring_sync(to, from, seqno - 1);
+
+	return to->sync_to(to, from, seqno - 1);
 }
 
 static int
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,28 @@ static unsigned int cache_level_to_agp_t
 	}
 }
 
+static bool do_idling(struct drm_i915_private *dev_priv)
+{
+	bool ret = dev_priv->mm.interruptible;
+
+	if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
+		dev_priv->mm.interruptible = false;
+		if (i915_gpu_idle(dev_priv->dev)) {
+			DRM_ERROR("Couldn't idle GPU\n");
+			/* Wait a bit, in hopes it avoids the hang */
+			udelay(10);
+		}
+	}
+
+	return ret;
+}
+
+static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
+{
+	if (unlikely(dev_priv->mm.gtt->do_idle_maps))
+		dev_priv->mm.interruptible = interruptible;
+}
+
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -117,6 +139,12 @@ void i915_gem_gtt_rebind_object(struct d
 
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool interruptible;
+
+	interruptible = do_idling(dev_priv);
+
 	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
 			      obj->base.size >> PAGE_SHIFT);
 
@@ -124,4 +152,6 @@ void i915_gem_gtt_unbind_object(struct d
 		intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
 		obj->sg_list = NULL;
 	}
+
+	undo_idling(dev_priv, interruptible);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,10 @@ i915_gem_detect_bit_6_swizzle(struct drm
 	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 
-	if (INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_INFO(dev)->gen >= 6) {
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	} else if (IS_GEN5(dev)) {
 		/* On Ironlake whatever DRAM config, GPU always do
 		 * same swizzling setup.
 		 */
@@ -440,14 +443,9 @@ i915_gem_swizzle_page(struct page *page)
 void
 i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int page_count = obj->base.size >> PAGE_SHIFT;
 	int i;
 
-	if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-		return;
-
 	if (obj->bit_17 == NULL)
 		return;
 
@@ -464,14 +462,9 @@ i915_gem_object_do_bit_17_swizzle(struct
 void
 i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int page_count = obj->base.size >> PAGE_SHIFT;
 	int i;
 
-	if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-		return;
-
 	if (obj->bit_17 == NULL) {
 		obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
 					   sizeof(long), GFP_KERNEL);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_irq.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -383,6 +383,7 @@ static void gen6_pm_rps_work(struct work
 	pm_iir = dev_priv->pm_iir;
 	dev_priv->pm_iir = 0;
 	pm_imr = I915_READ(GEN6_PMIMR);
+	I915_WRITE(GEN6_PMIMR, 0);
 	spin_unlock_irq(&dev_priv->rps_lock);
 
 	if (!pm_iir)
@@ -420,7 +421,6 @@ static void gen6_pm_rps_work(struct work
 	 * an *extremely* unlikely race with gen6_rps_enable() that is prevented
 	 * by holding struct_mutex for the duration of the write.
 	 */
-	I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
@@ -536,8 +536,9 @@ static irqreturn_t ivybridge_irq_handler
 		unsigned long flags;
 		spin_lock_irqsave(&dev_priv->rps_lock, flags);
 		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-		I915_WRITE(GEN6_PMIMR, pm_iir);
 		dev_priv->pm_iir |= pm_iir;
+		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+		POSTING_READ(GEN6_PMIMR);
 		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
 		queue_work(dev_priv->wq, &dev_priv->rps_work);
 	}
@@ -649,8 +650,9 @@ static irqreturn_t ironlake_irq_handler(
 		unsigned long flags;
 		spin_lock_irqsave(&dev_priv->rps_lock, flags);
 		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-		I915_WRITE(GEN6_PMIMR, pm_iir);
 		dev_priv->pm_iir |= pm_iir;
+		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+		POSTING_READ(GEN6_PMIMR);
 		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
 		queue_work(dev_priv->wq, &dev_priv->rps_work);
 	}
@@ -711,7 +713,7 @@ i915_error_object_create(struct drm_i915
 
 	page_count = src->base.size / PAGE_SIZE;
 
-	dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
+	dst = kmalloc(sizeof(*dst) + page_count * sizeof(u32 *), GFP_ATOMIC);
 	if (dst == NULL)
 		return NULL;
 
@@ -822,6 +824,7 @@ static void i915_gem_record_fences(struc
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -1493,7 +1496,7 @@ static int ironlake_enable_vblank(struct
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
-				    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+				    DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -1541,7 +1544,7 @@ static void ironlake_disable_vblank(stru
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
-				     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+				     DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -1777,6 +1780,26 @@ static void ironlake_irq_preinstall(stru
 	POSTING_READ(SDEIER);
 }
 
+/*
+ * Enable digital hotplug on the PCH, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec)
+ *
+ * This register is the same on all known PCH chips.
+ */
+
+static void ironlake_enable_pch_hotplug(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32	hotplug;
+
+	hotplug = I915_READ(PCH_PORT_HOTPLUG);
+	hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
+	hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
+	hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
+	hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+	I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+}
+
 static int ironlake_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1839,6 +1862,8 @@ static int ironlake_irq_postinstall(stru
 	I915_WRITE(SDEIER, hotplug_mask);
 	POSTING_READ(SDEIER);
 
+	ironlake_enable_pch_hotplug(dev);
+
 	if (IS_IRONLAKE_M(dev)) {
 		/* Clear & enable PCU event interrupts */
 		I915_WRITE(DEIIR, DE_PCU_EVENT);
@@ -1896,6 +1921,8 @@ static int ivybridge_irq_postinstall(str
 	I915_WRITE(SDEIER, hotplug_mask);
 	POSTING_READ(SDEIER);
 
+	ironlake_enable_pch_hotplug(dev);
+
 	return 0;
 }
 
@@ -2020,6 +2047,10 @@ static void ironlake_irq_uninstall(struc
 	I915_WRITE(GTIMR, 0xffffffff);
 	I915_WRITE(GTIER, 0x0);
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
+
+	I915_WRITE(SDEIMR, 0xffffffff);
+	I915_WRITE(SDEIER, 0x0);
+	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
 }
 
 static void i915_driver_irq_uninstall(struct drm_device * dev)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_mem.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_mem.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -202,7 +202,7 @@ static int init_heap(struct mem_block **
 	blocks->next = blocks->prev = *heap;
 
 	memset(*heap, 0, sizeof(**heap));
-	(*heap)->file_priv = (struct drm_file *) - 1;
+	(*heap)->file_priv = (struct drm_file *) -1;
 	(*heap)->next = (*heap)->prev = blocks;
 	return 0;
 }
@@ -359,19 +359,19 @@ int i915_mem_init_heap(struct drm_device
 	return init_heap(heap, initheap->start, initheap->size);
 }
 
-int i915_mem_destroy_heap( struct drm_device *dev, void *data,
-			   struct drm_file *file_priv )
+int i915_mem_destroy_heap(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_mem_destroy_heap_t *destroyheap = data;
 	struct mem_block **heap;
 
-	if ( !dev_priv ) {
-		DRM_ERROR( "called with no initialization\n" );
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	heap = get_heap( dev_priv, destroyheap->region );
+	heap = get_heap(dev_priv, destroyheap->region);
 	if (!heap) {
 		DRM_ERROR("get_heap failed");
 		return -EFAULT;
@@ -382,6 +382,6 @@ int i915_mem_destroy_heap( struct drm_de
 		return -EFAULT;
 	}
 
-	i915_mem_takedown( heap );
+	i915_mem_takedown(heap);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -156,7 +156,7 @@
 #define MI_SUSPEND_FLUSH	MI_INSTR(0x0b, 0)
 #define   MI_SUSPEND_FLUSH_EN	(1<<0)
 #define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
-#define MI_OVERLAY_FLIP		MI_INSTR(0x11,0)
+#define MI_OVERLAY_FLIP		MI_INSTR(0x11, 0)
 #define   MI_OVERLAY_CONTINUE	(0x0<<21)
 #define   MI_OVERLAY_ON		(0x1<<21)
 #define   MI_OVERLAY_OFF	(0x2<<21)
@@ -194,6 +194,13 @@
 #define  MI_SEMAPHORE_UPDATE	    (1<<21)
 #define  MI_SEMAPHORE_COMPARE	    (1<<20)
 #define  MI_SEMAPHORE_REGISTER	    (1<<18)
+#define  MI_SEMAPHORE_SYNC_RV	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_RB	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_VR	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_VB	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_BR	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_BV	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_INVALID  (1<<0)
 /*
  * 3D instructions used by the kernel
  */
@@ -235,16 +242,22 @@
 #define   ASYNC_FLIP                (1<<22)
 #define   DISPLAY_PLANE_A           (0<<20)
 #define   DISPLAY_PLANE_B           (1<<20)
-#define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
-#define   PIPE_CONTROL_QW_WRITE	(1<<14)
-#define   PIPE_CONTROL_DEPTH_STALL (1<<13)
-#define   PIPE_CONTROL_WC_FLUSH	(1<<12)
-#define   PIPE_CONTROL_IS_FLUSH	(1<<11) /* MBZ on Ironlake */
-#define   PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
-#define   PIPE_CONTROL_ISP_DIS	(1<<9)
-#define   PIPE_CONTROL_NOTIFY	(1<<8)
+#define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
+#define   PIPE_CONTROL_CS_STALL				(1<<20)
+#define   PIPE_CONTROL_QW_WRITE				(1<<14)
+#define   PIPE_CONTROL_DEPTH_STALL			(1<<13)
+#define   PIPE_CONTROL_WRITE_FLUSH			(1<<12)
+#define   PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH	(1<<12) /* gen6+ */
+#define   PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE	(1<<11) /* MBZ on Ironlake */
+#define   PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE		(1<<10) /* GM45+ only */
+#define   PIPE_CONTROL_INDIRECT_STATE_DISABLE		(1<<9)
+#define   PIPE_CONTROL_NOTIFY				(1<<8)
+#define   PIPE_CONTROL_VF_CACHE_INVALIDATE		(1<<4)
+#define   PIPE_CONTROL_CONST_CACHE_INVALIDATE		(1<<3)
+#define   PIPE_CONTROL_STATE_CACHE_INVALIDATE		(1<<2)
+#define   PIPE_CONTROL_STALL_AT_SCOREBOARD		(1<<1)
+#define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
-#define   PIPE_CONTROL_STALL_EN	(1<<1) /* in addr word, Ironlake+ only */
 
 
 /*
@@ -296,6 +309,12 @@
 #define RING_CTL(base)		((base)+0x3c)
 #define RING_SYNC_0(base)	((base)+0x40)
 #define RING_SYNC_1(base)	((base)+0x44)
+#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
+#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
+#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE))
+#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE))
+#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE))
+#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE))
 #define RING_MAX_IDLE(base)	((base)+0x54)
 #define RING_HWS_PGA(base)	((base)+0x80)
 #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
@@ -470,7 +489,7 @@
 
 /* Enables non-sequential data reads through arbiter
  */
-#define   MI_ARB_DUAL_DATA_PHASE_DISABLE       	(1 << 9)
+#define   MI_ARB_DUAL_DATA_PHASE_DISABLE	(1 << 9)
 
 /* Disable FSB snooping of cacheable write cycles from binner/render
  * command stream
@@ -626,7 +645,7 @@
 
 #define ILK_DISPLAY_CHICKEN1	0x42000
 #define   ILK_FBCQ_DIS		(1<<22)
-#define   ILK_PABSTRETCH_DIS 	(1<<21)
+#define	  ILK_PABSTRETCH_DIS	(1<<21)
 
 
 /*
@@ -1534,12 +1553,21 @@
  */
 #define   PP_READY		(1 << 30)
 #define   PP_SEQUENCE_NONE	(0 << 28)
-#define   PP_SEQUENCE_ON	(1 << 28)
-#define   PP_SEQUENCE_OFF	(2 << 28)
-#define   PP_SEQUENCE_MASK	0x30000000
+#define   PP_SEQUENCE_POWER_UP	(1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
+#define   PP_SEQUENCE_MASK	(3 << 28)
+#define   PP_SEQUENCE_SHIFT	28
 #define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
-#define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
 #define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_3	(0x3 << 0)
+#define   PP_SEQUENCE_STATE_ON_IDLE	(0x8 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_0	(0x9 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
+#define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
 #define PP_CONTROL	0x61204
 #define   POWER_TARGET_ON	(1 << 0)
 #define PP_ON_DELAYS	0x61208
@@ -2358,7 +2386,7 @@
 
 #define DSPFW1			0x70034
 #define   DSPFW_SR_SHIFT	23
-#define   DSPFW_SR_MASK 	(0x1ff<<23)
+#define   DSPFW_SR_MASK		(0x1ff<<23)
 #define   DSPFW_CURSORB_SHIFT	16
 #define   DSPFW_CURSORB_MASK	(0x3f<<16)
 #define   DSPFW_PLANEB_SHIFT	8
@@ -2416,6 +2444,7 @@
 #define  WM0_PIPE_CURSOR_MASK	(0x1f)
 
 #define WM0_PIPEB_ILK		0x45104
+#define WM0_PIPEC_IVB		0x45200
 #define WM1_LP_ILK		0x45108
 #define  WM1_LP_SR_EN		(1<<31)
 #define  WM1_LP_LATENCY_SHIFT	24
@@ -2554,10 +2583,18 @@
 #define _CURBBASE		0x700c4
 #define _CURBPOS			0x700c8
 
+#define _CURBCNTR_IVB		0x71080
+#define _CURBBASE_IVB		0x71084
+#define _CURBPOS_IVB		0x71088
+
 #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
 #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
 #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
 
+#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB)
+#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB)
+#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
+
 /* Display A control */
 #define _DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
@@ -2903,12 +2940,13 @@
 #define SDEIER  0xc400c
 
 /* digital port hotplug */
-#define PCH_PORT_HOTPLUG        0xc4030
+#define PCH_PORT_HOTPLUG        0xc4030		/* SHOTPLUG_CTL */
 #define PORTD_HOTPLUG_ENABLE            (1 << 20)
 #define PORTD_PULSE_DURATION_2ms        (0)
 #define PORTD_PULSE_DURATION_4_5ms      (1 << 18)
 #define PORTD_PULSE_DURATION_6ms        (2 << 18)
 #define PORTD_PULSE_DURATION_100ms      (3 << 18)
+#define PORTD_PULSE_DURATION_MASK	(3 << 18)
 #define PORTD_HOTPLUG_NO_DETECT         (0)
 #define PORTD_HOTPLUG_SHORT_DETECT      (1 << 16)
 #define PORTD_HOTPLUG_LONG_DETECT       (1 << 17)
@@ -2917,6 +2955,7 @@
 #define PORTC_PULSE_DURATION_4_5ms      (1 << 10)
 #define PORTC_PULSE_DURATION_6ms        (2 << 10)
 #define PORTC_PULSE_DURATION_100ms      (3 << 10)
+#define PORTC_PULSE_DURATION_MASK	(3 << 10)
 #define PORTC_HOTPLUG_NO_DETECT         (0)
 #define PORTC_HOTPLUG_SHORT_DETECT      (1 << 8)
 #define PORTC_HOTPLUG_LONG_DETECT       (1 << 9)
@@ -2925,6 +2964,7 @@
 #define PORTB_PULSE_DURATION_4_5ms      (1 << 2)
 #define PORTB_PULSE_DURATION_6ms        (2 << 2)
 #define PORTB_PULSE_DURATION_100ms      (3 << 2)
+#define PORTB_PULSE_DURATION_MASK	(3 << 2)
 #define PORTB_HOTPLUG_NO_DETECT         (0)
 #define PORTB_HOTPLUG_SHORT_DETECT      (1 << 0)
 #define PORTB_HOTPLUG_LONG_DETECT       (1 << 1)
@@ -2945,15 +2985,15 @@
 
 #define _PCH_DPLL_A              0xc6014
 #define _PCH_DPLL_B              0xc6018
-#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B)
+#define PCH_DPLL(pipe) (pipe == 0 ?  _PCH_DPLL_A : _PCH_DPLL_B)
 
 #define _PCH_FPA0                0xc6040
 #define  FP_CB_TUNE		(0x3<<22)
 #define _PCH_FPA1                0xc6044
 #define _PCH_FPB0                0xc6048
 #define _PCH_FPB1                0xc604c
-#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0)
-#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1)
+#define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
+#define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
 
 #define PCH_DPLL_TEST           0xc606c
 
@@ -3167,6 +3207,7 @@
 #define  FDI_LINK_TRAIN_NONE_IVB            (3<<8)
 
 /* both Tx and Rx */
+#define  FDI_COMPOSITE_SYNC		(1<<11)
 #define  FDI_LINK_TRAIN_AUTO		(1<<10)
 #define  FDI_SCRAMBLING_ENABLE          (0<<7)
 #define  FDI_SCRAMBLING_DISABLE         (1<<7)
@@ -3262,10 +3303,10 @@
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
-#define  TRANSCODER_A   (0)
-#define  TRANSCODER_B   (1 << 30)
-#define  TRANSCODER(pipe)	((pipe) << 30)
-#define  TRANSCODER_MASK   (1 << 30)
+#define  TRANSCODER(pipe)       ((pipe) << 30)
+#define  TRANSCODER_CPT(pipe)   ((pipe) << 29)
+#define  TRANSCODER_MASK        (1 << 30)
+#define  TRANSCODER_MASK_CPT    (3 << 29)
 #define  COLOR_FORMAT_8bpc      (0)
 #define  COLOR_FORMAT_12bpc     (3 << 26)
 #define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
@@ -3308,15 +3349,35 @@
 #define PCH_PP_STATUS		0xc7200
 #define PCH_PP_CONTROL		0xc7204
 #define  PANEL_UNLOCK_REGS	(0xabcd << 16)
+#define  PANEL_UNLOCK_MASK	(0xffff << 16)
 #define  EDP_FORCE_VDD		(1 << 3)
 #define  EDP_BLC_ENABLE		(1 << 2)
 #define  PANEL_POWER_RESET	(1 << 1)
 #define  PANEL_POWER_OFF	(0 << 0)
 #define  PANEL_POWER_ON		(1 << 0)
 #define PCH_PP_ON_DELAYS	0xc7208
+#define  PANEL_PORT_SELECT_MASK	(3 << 30)
+#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
+#define  PANEL_PORT_SELECT_DPA	(1 << 30)
 #define  EDP_PANEL		(1 << 30)
+#define  PANEL_PORT_SELECT_DPC	(2 << 30)
+#define  PANEL_PORT_SELECT_DPD	(3 << 30)
+#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
+#define  PANEL_POWER_UP_DELAY_SHIFT	16
+#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
+#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
+
 #define PCH_PP_OFF_DELAYS	0xc720c
+#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
+#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
+#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
+#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
+
 #define PCH_PP_DIVISOR		0xc7210
+#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
+#define  PP_REFERENCE_DIVIDER_SHIFT	8
+#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
+#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
 
 #define PCH_DP_B		0xe4100
 #define PCH_DPB_AUX_CH_CTL	0xe4110
@@ -3386,12 +3447,38 @@
 #define  EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B	(0x38<<22)
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_SNB	(0x3f<<22)
 
+/* IVB */
+#define EDP_LINK_TRAIN_400MV_0DB_IVB		(0x24 <<22)
+#define EDP_LINK_TRAIN_400MV_3_5DB_IVB		(0x2a <<22)
+#define EDP_LINK_TRAIN_400MV_6DB_IVB		(0x2f <<22)
+#define EDP_LINK_TRAIN_600MV_0DB_IVB		(0x30 <<22)
+#define EDP_LINK_TRAIN_600MV_3_5DB_IVB		(0x36 <<22)
+#define EDP_LINK_TRAIN_800MV_0DB_IVB		(0x38 <<22)
+#define EDP_LINK_TRAIN_800MV_3_5DB_IVB		(0x33 <<22)
+
+/* legacy values */
+#define EDP_LINK_TRAIN_500MV_0DB_IVB		(0x00 <<22)
+#define EDP_LINK_TRAIN_1000MV_0DB_IVB		(0x20 <<22)
+#define EDP_LINK_TRAIN_500MV_3_5DB_IVB		(0x02 <<22)
+#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB		(0x22 <<22)
+#define EDP_LINK_TRAIN_1000MV_6DB_IVB		(0x23 <<22)
+
+#define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
+
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_ACK				0x130090
+#define  FORCEWAKE_MT				0xa188 /* multi-threaded */
+#define  FORCEWAKE_MT_ACK			0x130040
+#define  ECOBUS					0xa180
+#define    FORCEWAKE_MT_ENABLE			(1<<5)
 
 #define  GT_FIFO_FREE_ENTRIES			0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES		20
 
+#define GEN6_UCGCTL2				0x9404
+# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
+# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
+
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
@@ -3470,4 +3557,29 @@
 #define GEN6_PCODE_DATA				0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
+#define G4X_AUD_VID_DID			0x62020
+#define INTEL_AUDIO_DEVCL		0x808629FB
+#define INTEL_AUDIO_DEVBLC		0x80862801
+#define INTEL_AUDIO_DEVCTG		0x80862802
+
+#define G4X_AUD_CNTL_ST			0x620B4
+#define G4X_ELDV_DEVCL_DEVBLC		(1 << 13)
+#define G4X_ELDV_DEVCTG			(1 << 14)
+#define G4X_ELD_ADDR			(0xf << 5)
+#define G4X_ELD_ACK			(1 << 4)
+#define G4X_HDMIW_HDMIEDID		0x6210C
+
+#define GEN5_HDMIW_HDMIEDID_A		0xE2050
+#define GEN5_AUD_CNTL_ST_A		0xE20B4
+#define GEN5_ELD_BUFFER_SIZE		(0x1f << 10)
+#define GEN5_ELD_ADDRESS		(0x1f << 5)
+#define GEN5_ELD_ACK			(1 << 4)
+#define GEN5_AUD_CNTL_ST2		0xE20C0
+#define GEN5_ELD_VALIDB			(1 << 0)
+#define GEN5_CP_READYB			(1 << 1)
+
+#define GEN7_HDMIW_HDMIEDID_A		0xE5050
+#define GEN7_AUD_CNTRL_ST_A		0xE50B4
+#define GEN7_AUD_CNTRL_ST2		0xE50C0
+
 #endif /* _I915_REG_H_ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_suspend.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@ static void i915_save_palette(struct drm
 	else
 		array = dev_priv->save_palette_b;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 		array[i] = I915_READ(reg + (i << 2));
 }
 
@@ -82,7 +82,7 @@ static void i915_restore_palette(struct
 	else
 		array = dev_priv->save_palette_b;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 		I915_WRITE(reg + (i << 2), array[i]);
 }
 
@@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(str
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
@@ -887,10 +889,10 @@ int i915_restore_state(struct drm_device
 	mutex_lock(&dev->struct_mutex);
 
 	/* Cache mode state */
-	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+	I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
 
 	/* Memory arbitration state */
-	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+	I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
 
 	for (i = 0; i < 16; i++) {
 		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_trace.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/i915_trace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/i915_trace.h	2012-01-04 18:55:44.000000000 -0500
@@ -385,29 +385,29 @@ TRACE_EVENT(i915_flip_complete,
 );
 
 TRACE_EVENT(i915_reg_rw,
-           TP_PROTO(bool write, u32 reg, u64 val, int len),
+	TP_PROTO(bool write, u32 reg, u64 val, int len),
 
-           TP_ARGS(write, reg, val, len),
+	TP_ARGS(write, reg, val, len),
 
-           TP_STRUCT__entry(
-                   __field(u64, val)
-                   __field(u32, reg)
-                   __field(u16, write)
-                   __field(u16, len)
-                   ),
+	TP_STRUCT__entry(
+		__field(u64, val)
+		__field(u32, reg)
+		__field(u16, write)
+		__field(u16, len)
+		),
 
-           TP_fast_assign(
-                   __entry->val = (u64)val;
-                   __entry->reg = reg;
-                   __entry->write = write;
-                   __entry->len = len;
-                   ),
+	TP_fast_assign(
+		__entry->val = (u64)val;
+		__entry->reg = reg;
+		__entry->write = write;
+		__entry->len = len;
+		),
 
-           TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
-                     __entry->write ? "write" : "read",
-		     __entry->reg, __entry->len,
-		     (u32)(__entry->val & 0xffffffff),
-		     (u32)(__entry->val >> 32))
+	TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
+		__entry->write ? "write" : "read",
+		__entry->reg, __entry->len,
+		(u32)(__entry->val & 0xffffffff),
+		(u32)(__entry->val >> 32))
 );
 
 #endif /* _I915_TRACE_H_ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_acpi.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_acpi.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@ static int intel_dsm(acpi_handle handle,
 
 	case ACPI_TYPE_BUFFER:
 		if (obj->buffer.length == 4) {
-			result =(obj->buffer.pointer[0] |
+			result = (obj->buffer.pointer[0] |
 				(obj->buffer.pointer[1] <<  8) |
 				(obj->buffer.pointer[2] << 16) |
 				(obj->buffer.pointer[3] << 24));
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_bios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_bios.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright Â© 2006 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_p
 		dev_priv->lvds_use_ssc = general->enable_ssc;
 		dev_priv->lvds_ssc_freq =
 			intel_bios_ssc_frequency(dev, general->ssc_freq);
+		dev_priv->display_clock_mode = general->display_clock_mode;
+		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
+			      dev_priv->int_tv_support,
+			      dev_priv->int_crt_support,
+			      dev_priv->lvds_use_ssc,
+			      dev_priv->lvds_ssc_freq,
+			      dev_priv->display_clock_mode);
 	}
 }
 
@@ -381,7 +388,7 @@ parse_sdvo_device_mapping(struct drm_i91
 		if (p_child->dvo_port != DEVICE_PORT_DVOB &&
 			p_child->dvo_port != DEVICE_PORT_DVOC) {
 			/* skip the incorrect SDVO port */
-			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");
+			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
 			continue;
 		}
 		DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
@@ -396,15 +403,13 @@ parse_sdvo_device_mapping(struct drm_i91
 			p_mapping->dvo_wiring = p_child->dvo_wiring;
 			p_mapping->ddc_pin = p_child->ddc_pin;
 			p_mapping->i2c_pin = p_child->i2c_pin;
-			p_mapping->i2c_speed = p_child->i2c_speed;
 			p_mapping->initialized = 1;
-			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n",
+			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
 				      p_mapping->dvo_port,
 				      p_mapping->slave_addr,
 				      p_mapping->dvo_wiring,
 				      p_mapping->ddc_pin,
-				      p_mapping->i2c_pin,
-				      p_mapping->i2c_speed);
+				      p_mapping->i2c_pin);
 		} else {
 			DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
 					 "two SDVO device.\n");
@@ -564,7 +569,7 @@ parse_device_mapping(struct drm_i915_pri
 		count++;
 	}
 	if (!count) {
-		DRM_DEBUG_KMS("no child dev is parsed from VBT \n");
+		DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
 		return;
 	}
 	dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
@@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_privat
 	/* Default to using SSC */
 	dev_priv->lvds_use_ssc = 1;
 	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
-	DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
+	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
 
 	/* eDP data */
 	dev_priv->edp.bpp = 18;
@@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev)
 	if (dev_priv->opregion.vbt) {
 		struct vbt_header *vbt = dev_priv->opregion.vbt;
 		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
-			DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
+			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
 					 vbt->signature);
 			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
 		} else
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_bios.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_bios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_bios.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright Â© 2006 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -120,7 +120,9 @@ struct bdb_general_features {
 	u8 ssc_freq:1;
 	u8 enable_lfp_on_override:1;
 	u8 disable_ssc_ddt:1;
-	u8 rsvd8:3; /* finish byte */
+	u8 rsvd7:1;
+	u8 display_clock_mode:1;
+	u8 rsvd8:1; /* finish byte */
 
         /* bits 3 */
 	u8 disable_smooth_vision:1;
@@ -133,7 +135,10 @@ struct bdb_general_features {
         /* bits 5 */
 	u8 int_crt_support:1;
 	u8 int_tv_support:1;
-	u8 rsvd11:6; /* finish byte */
+	u8 int_efp_support:1;
+	u8 dp_ssc_enb:1;	/* PCH attached eDP supports SSC */
+	u8 dp_ssc_freq:1;	/* SSC freq for PCH attached eDP */
+	u8 rsvd11:3; /* finish byte */
 } __attribute__((packed));
 
 /* pre-915 */
@@ -197,8 +202,7 @@ struct bdb_general_features {
 struct child_device_config {
 	u16 handle;
 	u16 device_type;
-	u8  i2c_speed;
-	u8  rsvd[9];
+	u8  device_id[10]; /* ascii string */
 	u16 addin_offset;
 	u8  dvo_port; /* See Device_PORT_* above */
 	u8  i2c_pin;
@@ -240,7 +244,7 @@ struct bdb_general_definitions {
 	 * And the device num is related with the size of general definition
 	 * block. It is obtained by using the following formula:
 	 * number = (block_size - sizeof(bdb_general_definitions))/
-	 * 		sizeof(child_device_config);
+	 *	     sizeof(child_device_config);
 	 */
 	struct child_device_config devices[0];
 } __attribute__((packed));
@@ -446,11 +450,11 @@ struct bdb_driver_features {
 #define EDP_VSWING_1_2V		3
 
 struct edp_power_seq {
-	u16 t3;
-	u16 t7;
+	u16 t1_t3;
+	u16 t8;
 	u16 t9;
 	u16 t10;
-	u16 t12;
+	u16 t11_t12;
 } __attribute__ ((packed));
 
 struct edp_link_params {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_crt.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_crt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_crt.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ static void intel_crt_dpms(struct drm_en
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
-	switch(mode) {
+	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		temp |= ADPA_DAC_ENABLE;
 		break;
@@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct dr
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
-	if (intel_crtc->pipe == 0) {
-		if (HAS_PCH_CPT(dev))
-			adpa |= PORT_TRANS_A_SEL_CPT;
-		else
-			adpa |= ADPA_PIPE_A_SELECT;
-	} else {
-		if (HAS_PCH_CPT(dev))
-			adpa |= PORT_TRANS_B_SEL_CPT;
-		else
-			adpa |= ADPA_PIPE_B_SELECT;
-	}
+	/* For CPT allow 3 pipe config, for others just use A or B */
+	if (HAS_PCH_CPT(dev))
+		adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+	else if (intel_crtc->pipe == 0)
+		adpa |= ADPA_PIPE_A_SELECT;
+	else
+		adpa |= ADPA_PIPE_B_SELECT;
 
 	if (!HAS_PCH_SPLIT(dev))
 		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,50 +31,51 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vgaarb.h>
+#include <drm/drm_edid.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "drm_dp_helper.h"
-
 #include "drm_crtc_helper.h"
+#include <linux/dma_remapping.h>
 
 #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
 
-bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
 static void intel_update_watermarks(struct drm_device *dev);
 static void intel_increase_pllclock(struct drm_crtc *crtc);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
 typedef struct {
-    /* given values */
-    int n;
-    int m1, m2;
-    int p1, p2;
-    /* derived values */
-    int	dot;
-    int	vco;
-    int	m;
-    int	p;
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int	dot;
+	int	vco;
+	int	m;
+	int	p;
 } intel_clock_t;
 
 typedef struct {
-    int	min, max;
+	int	min, max;
 } intel_range_t;
 
 typedef struct {
-    int	dot_limit;
-    int	p2_slow, p2_fast;
+	int	dot_limit;
+	int	p2_slow, p2_fast;
 } intel_p2_t;
 
 #define INTEL_P2_NUM		      2
 typedef struct intel_limit intel_limit_t;
 struct intel_limit {
-    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
-    intel_p2_t	    p2;
-    bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
-		      int, int, intel_clock_t *);
+	intel_range_t   dot, vco, n, m, m1, m2, p, p1;
+	intel_p2_t	    p2;
+	bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
+			int, int, intel_clock_t *);
 };
 
 /* FDI */
@@ -105,56 +106,56 @@ intel_fdi_link_freq(struct drm_device *d
 }
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 930000, .max = 1400000 },
-        .n = { .min = 3, .max = 16 },
-        .m = { .min = 96, .max = 140 },
-        .m1 = { .min = 18, .max = 26 },
-        .m2 = { .min = 6, .max = 16 },
-        .p = { .min = 4, .max = 128 },
-        .p1 = { .min = 2, .max = 33 },
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 930000, .max = 1400000 },
+	.n = { .min = 3, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 2, .max = 33 },
 	.p2 = { .dot_limit = 165000,
 		.p2_slow = 4, .p2_fast = 2 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 930000, .max = 1400000 },
-        .n = { .min = 3, .max = 16 },
-        .m = { .min = 96, .max = 140 },
-        .m1 = { .min = 18, .max = 26 },
-        .m2 = { .min = 6, .max = 16 },
-        .p = { .min = 4, .max = 128 },
-        .p1 = { .min = 1, .max = 6 },
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 930000, .max = 1400000 },
+	.n = { .min = 3, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 1, .max = 6 },
 	.p2 = { .dot_limit = 165000,
 		.p2_slow = 14, .p2_fast = 7 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_sdvo = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1400000, .max = 2800000 },
-        .n = { .min = 1, .max = 6 },
-        .m = { .min = 70, .max = 120 },
-        .m1 = { .min = 10, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 5, .max = 80 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 10, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 200000,
 		.p2_slow = 10, .p2_fast = 5 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_lvds = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1400000, .max = 2800000 },
-        .n = { .min = 1, .max = 6 },
-        .m = { .min = 70, .max = 120 },
-        .m1 = { .min = 10, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 7, .max = 98 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 10, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 7, .max = 98 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 112000,
 		.p2_slow = 14, .p2_fast = 7 },
 	.find_pll = intel_find_best_PLL,
@@ -222,44 +223,44 @@ static const intel_limit_t intel_limits_
 };
 
 static const intel_limit_t intel_limits_g4x_display_port = {
-        .dot = { .min = 161670, .max = 227000 },
-        .vco = { .min = 1750000, .max = 3500000},
-        .n = { .min = 1, .max = 2 },
-        .m = { .min = 97, .max = 108 },
-        .m1 = { .min = 0x10, .max = 0x12 },
-        .m2 = { .min = 0x05, .max = 0x06 },
-        .p = { .min = 10, .max = 20 },
-        .p1 = { .min = 1, .max = 2},
-        .p2 = { .dot_limit = 0,
+	.dot = { .min = 161670, .max = 227000 },
+	.vco = { .min = 1750000, .max = 3500000},
+	.n = { .min = 1, .max = 2 },
+	.m = { .min = 97, .max = 108 },
+	.m1 = { .min = 0x10, .max = 0x12 },
+	.m2 = { .min = 0x05, .max = 0x06 },
+	.p = { .min = 10, .max = 20 },
+	.p1 = { .min = 1, .max = 2},
+	.p2 = { .dot_limit = 0,
 		.p2_slow = 10, .p2_fast = 10 },
-        .find_pll = intel_find_pll_g4x_dp,
+	.find_pll = intel_find_pll_g4x_dp,
 };
 
 static const intel_limit_t intel_limits_pineview_sdvo = {
-        .dot = { .min = 20000, .max = 400000},
-        .vco = { .min = 1700000, .max = 3500000 },
+	.dot = { .min = 20000, .max = 400000},
+	.vco = { .min = 1700000, .max = 3500000 },
 	/* Pineview's Ncounter is a ring counter */
-        .n = { .min = 3, .max = 6 },
-        .m = { .min = 2, .max = 256 },
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
 	/* Pineview only has one combined m divider, which we treat as m2. */
-        .m1 = { .min = 0, .max = 0 },
-        .m2 = { .min = 0, .max = 254 },
-        .p = { .min = 5, .max = 80 },
-        .p1 = { .min = 1, .max = 8 },
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 200000,
 		.p2_slow = 10, .p2_fast = 5 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_pineview_lvds = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1700000, .max = 3500000 },
-        .n = { .min = 3, .max = 6 },
-        .m = { .min = 2, .max = 256 },
-        .m1 = { .min = 0, .max = 0 },
-        .m2 = { .min = 0, .max = 254 },
-        .p = { .min = 7, .max = 112 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1700000, .max = 3500000 },
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 7, .max = 112 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 112000,
 		.p2_slow = 14, .p2_fast = 14 },
 	.find_pll = intel_find_best_PLL,
@@ -321,7 +322,7 @@ static const intel_limit_t intel_limits_
 	.m1 = { .min = 12, .max = 22 },
 	.m2 = { .min = 5, .max = 9 },
 	.p = { .min = 28, .max = 112 },
-	.p1 = { .min = 2,.max = 8 },
+	.p1 = { .min = 2, .max = 8 },
 	.p2 = { .dot_limit = 225000,
 		.p2_slow = 14, .p2_fast = 14 },
 	.find_pll = intel_g4x_find_best_PLL,
@@ -335,24 +336,24 @@ static const intel_limit_t intel_limits_
 	.m1 = { .min = 12, .max = 22 },
 	.m2 = { .min = 5, .max = 9 },
 	.p = { .min = 14, .max = 42 },
-	.p1 = { .min = 2,.max = 6 },
+	.p1 = { .min = 2, .max = 6 },
 	.p2 = { .dot_limit = 225000,
 		.p2_slow = 7, .p2_fast = 7 },
 	.find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_display_port = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 1760000, .max = 3510000},
-        .n = { .min = 1, .max = 2 },
-        .m = { .min = 81, .max = 90 },
-        .m1 = { .min = 12, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 10, .max = 20 },
-        .p1 = { .min = 1, .max = 2},
-        .p2 = { .dot_limit = 0,
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000},
+	.n = { .min = 1, .max = 2 },
+	.m = { .min = 81, .max = 90 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 10, .max = 20 },
+	.p1 = { .min = 1, .max = 2},
+	.p2 = { .dot_limit = 0,
 		.p2_slow = 10, .p2_fast = 10 },
-        .find_pll = intel_find_pll_ironlake_dp,
+	.find_pll = intel_find_pll_ironlake_dp,
 };
 
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
@@ -404,7 +405,7 @@ static const intel_limit_t *intel_g4x_li
 		limit = &intel_limits_g4x_hdmi;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
 		limit = &intel_limits_g4x_sdvo;
-	} else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
 		limit = &intel_limits_g4x_display_port;
 	} else /* The option is for other outputs */
 		limit = &intel_limits_i9xx_sdvo;
@@ -488,26 +489,26 @@ static bool intel_PLL_is_valid(struct dr
 			       const intel_clock_t *clock)
 {
 	if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
-		INTELPllInvalid ("p1 out of range\n");
+		INTELPllInvalid("p1 out of range\n");
 	if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
-		INTELPllInvalid ("p out of range\n");
+		INTELPllInvalid("p out of range\n");
 	if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
-		INTELPllInvalid ("m2 out of range\n");
+		INTELPllInvalid("m2 out of range\n");
 	if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
-		INTELPllInvalid ("m1 out of range\n");
+		INTELPllInvalid("m1 out of range\n");
 	if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev))
-		INTELPllInvalid ("m1 <= m2\n");
+		INTELPllInvalid("m1 <= m2\n");
 	if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
-		INTELPllInvalid ("m out of range\n");
+		INTELPllInvalid("m out of range\n");
 	if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
-		INTELPllInvalid ("n out of range\n");
+		INTELPllInvalid("n out of range\n");
 	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
-		INTELPllInvalid ("vco out of range\n");
+		INTELPllInvalid("vco out of range\n");
 	/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
 	 * connector, etc., rather than just a single range.
 	 */
 	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
-		INTELPllInvalid ("dot out of range\n");
+		INTELPllInvalid("dot out of range\n");
 
 	return true;
 }
@@ -542,7 +543,7 @@ intel_find_best_PLL(const intel_limit_t
 			clock.p2 = limit->p2.p2_fast;
 	}
 
-	memset (best_clock, 0, sizeof (*best_clock));
+	memset(best_clock, 0, sizeof(*best_clock));
 
 	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
 	     clock.m1++) {
@@ -802,6 +803,19 @@ static void assert_pch_pll(struct drm_i9
 	u32 val;
 	bool cur_state;
 
+	if (HAS_PCH_CPT(dev_priv->dev)) {
+		u32 pch_dpll;
+
+		pch_dpll = I915_READ(PCH_DPLL_SEL);
+
+		/* Make sure the selected PLL is enabled to the transcoder */
+		WARN(!((pch_dpll >> (4 * pipe)) & 8),
+		     "transcoder %d PLL not enabled\n", pipe);
+
+		/* Convert the transcoder pipe number to a pll pipe number */
+		pipe = (pch_dpll >> (4 * pipe)) & 1;
+	}
+
 	reg = PCH_DPLL(pipe);
 	val = I915_READ(reg);
 	cur_state = !!(val & DPLL_VCO_ENABLE);
@@ -1171,6 +1185,9 @@ static void intel_enable_pch_pll(struct
 	int reg;
 	u32 val;
 
+	if (pipe > 1)
+		return;
+
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
 
@@ -1191,6 +1208,9 @@ static void intel_disable_pch_pll(struct
 	int reg;
 	u32 val;
 
+	if (pipe > 1)
+		return;
+
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
 
@@ -1256,7 +1276,7 @@ static void intel_disable_transcoder(str
 	I915_WRITE(reg, val);
 	/* wait for PCH transcoder off, transcoder state */
 	if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
-		DRM_ERROR("failed to disable transcoder\n");
+		DRM_ERROR("failed to disable transcoder %d\n", pipe);
 }
 
 /**
@@ -2085,6 +2105,7 @@ static int ironlake_update_plane(struct
 	switch (plane) {
 	case 0:
 	case 1:
+	case 2:
 		break;
 	default:
 		DRM_ERROR("Can't update plane %d in SAREA\n", plane);
@@ -2184,6 +2205,10 @@ intel_pipe_set_base(struct drm_crtc *crt
 	case 0:
 	case 1:
 		break;
+	case 2:
+		if (IS_IVYBRIDGE(dev))
+			break;
+		/* fall through otherwise */
 	default:
 		DRM_ERROR("no plane for crtc\n");
 		return -EINVAL;
@@ -2440,7 +2465,7 @@ static void ironlake_fdi_link_train(stru
 
 }
 
-static const int snb_b_fdi_train_param [] = {
+static const int snb_b_fdi_train_param[] = {
 	FDI_LINK_TRAIN_400MV_0DB_SNB_B,
 	FDI_LINK_TRAIN_400MV_6DB_SNB_B,
 	FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
@@ -2496,7 +2521,7 @@ static void gen6_fdi_link_train(struct d
 	if (HAS_PCH_CPT(dev))
 		cpt_phase_pointer_enable(dev, pipe);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2545,7 +2570,7 @@ static void gen6_fdi_link_train(struct d
 	POSTING_READ(reg);
 	udelay(150);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2600,6 +2625,7 @@ static void ivb_manual_fdi_link_train(st
 	temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
 	temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
 	temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+	temp |= FDI_COMPOSITE_SYNC;
 	I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
 	reg = FDI_RX_CTL(pipe);
@@ -2607,6 +2633,7 @@ static void ivb_manual_fdi_link_train(st
 	temp &= ~FDI_LINK_TRAIN_AUTO;
 	temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 	temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	temp |= FDI_COMPOSITE_SYNC;
 	I915_WRITE(reg, temp | FDI_RX_ENABLE);
 
 	POSTING_READ(reg);
@@ -2615,7 +2642,7 @@ static void ivb_manual_fdi_link_train(st
 	if (HAS_PCH_CPT(dev))
 		cpt_phase_pointer_enable(dev, pipe);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2657,7 +2684,7 @@ static void ivb_manual_fdi_link_train(st
 	POSTING_READ(reg);
 	udelay(150);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2866,7 +2893,7 @@ static void ironlake_pch_enable(struct d
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	u32 reg, temp;
+	u32 reg, temp, transc_sel;
 
 	/* For PCH output, training FDI link */
 	dev_priv->display.fdi_link_train(crtc);
@@ -2874,12 +2901,21 @@ static void ironlake_pch_enable(struct d
 	intel_enable_pch_pll(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
+		transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
+			TRANSC_DPLLB_SEL;
+
 		/* Be sure PCH DPLL SEL is set */
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0)
+		if (pipe == 0) {
+			temp &= ~(TRANSA_DPLLB_SEL);
 			temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
-		else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
+		} else if (pipe == 1) {
+			temp &= ~(TRANSB_DPLLB_SEL);
 			temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
+		} else if (pipe == 2) {
+			temp &= ~(TRANSC_DPLLB_SEL);
+			temp |= (TRANSC_DPLL_ENABLE | transc_sel);
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
@@ -2897,7 +2933,8 @@ static void ironlake_pch_enable(struct d
 
 	/* For PCH DP, enable TRANS_DP_CTL */
 	if (HAS_PCH_CPT(dev) &&
-	    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
 		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
@@ -2935,6 +2972,24 @@ static void ironlake_pch_enable(struct d
 	intel_enable_transcoder(dev_priv, pipe);
 }
 
+void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe);
+	u32 temp;
+
+	temp = I915_READ(dslreg);
+	udelay(500);
+	if (wait_for(I915_READ(dslreg) != temp, 5)) {
+		/* Without this, mode sets may fail silently on FDI */
+		I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
+		udelay(250);
+		I915_WRITE(tc2reg, 0);
+		if (wait_for(I915_READ(dslreg) != temp, 5))
+			DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
+	}
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3045,13 +3100,13 @@ static void ironlake_crtc_disable(struct
 		temp = I915_READ(PCH_DPLL_SEL);
 		switch (pipe) {
 		case 0:
-			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
+			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
 			break;
 		case 1:
 			temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
 			break;
 		case 2:
-			/* FIXME: manage transcoder PLLs? */
+			/* C shares PLL A or B */
 			temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
 			break;
 		default:
@@ -3061,7 +3116,8 @@ static void ironlake_crtc_disable(struct
 	}
 
 	/* disable PCH DPLL */
-	intel_disable_pch_pll(dev_priv, pipe);
+	if (!intel_crtc->no_pll)
+		intel_disable_pch_pll(dev_priv, pipe);
 
 	/* Switch from PCDclk to Rawclk */
 	reg = FDI_RX_CTL(pipe);
@@ -3293,18 +3349,25 @@ static void ironlake_crtc_commit(struct
 	ironlake_crtc_enable(crtc);
 }
 
-void intel_encoder_prepare (struct drm_encoder *encoder)
+void intel_encoder_prepare(struct drm_encoder *encoder)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 	/* lvds has its own version of prepare see intel_lvds_prepare */
 	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
-void intel_encoder_commit (struct drm_encoder *encoder)
+void intel_encoder_commit(struct drm_encoder *encoder)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+	struct drm_device *dev = encoder->dev;
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
 	/* lvds has its own version of commit see intel_lvds_commit */
 	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 void intel_encoder_destroy(struct drm_encoder *encoder)
@@ -4478,6 +4541,20 @@ static void sandybridge_update_wm(struct
 		enabled |= 2;
 	}
 
+	/* IVB has 3 pipes */
+	if (IS_IVYBRIDGE(dev) &&
+	    g4x_compute_wm0(dev, 2,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEC_IVB,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
+			      " plane %d, cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled |= 3;
+	}
+
 	/*
 	 * Calculate and update the self-refresh watermark only when one
 	 * display plane is used.
@@ -4584,13 +4661,16 @@ static void intel_update_watermarks(stru
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
-	return dev_priv->lvds_use_ssc && i915_panel_use_ssc
+	if (i915_panel_use_ssc >= 0)
+		return i915_panel_use_ssc != 0;
+	return dev_priv->lvds_use_ssc
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
 /**
  * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
  * @crtc: CRTC structure
+ * @mode: requested mode
  *
  * A pipe may be connected to one or more outputs.  Based on the depth of the
  * attached framebuffer, choose a good color depth to use on the pipe.
@@ -4602,13 +4682,15 @@ static inline bool intel_panel_use_ssc(s
  *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
  *    Displays may support a restricted set as well, check EDID and clamp as
  *      appropriate.
+ *    DP may want to dither down to 6bpc to fit larger modes
  *
  * RETURNS:
  * Dithering requirement (i.e. false if display bpc and pipe bpc match,
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
-					 unsigned int *pipe_bpp)
+					 unsigned int *pipe_bpp,
+					 struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4633,7 +4715,7 @@ static bool intel_choose_pipe_bpp_dither
 				lvds_bpc = 6;
 
 			if (lvds_bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
 				display_bpc = lvds_bpc;
 			}
 			continue;
@@ -4644,7 +4726,7 @@ static bool intel_choose_pipe_bpp_dither
 			unsigned int edp_bpc = dev_priv->edp.bpp / 3;
 
 			if (edp_bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
 				display_bpc = edp_bpc;
 			}
 			continue;
@@ -4659,7 +4741,7 @@ static bool intel_choose_pipe_bpp_dither
 			/* Don't use an invalid EDID bpc value */
 			if (connector->display_info.bpc &&
 			    connector->display_info.bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
 				display_bpc = connector->display_info.bpc;
 			}
 		}
@@ -4670,15 +4752,20 @@ static bool intel_choose_pipe_bpp_dither
 		 */
 		if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
 			if (display_bpc > 8 && display_bpc < 12) {
-				DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+				DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
 				display_bpc = 12;
 			} else {
-				DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+				DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
 				display_bpc = 8;
 			}
 		}
 	}
 
+	if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+		DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
+		display_bpc = 6;
+	}
+
 	/*
 	 * We could just drive the pipe at the highest bpc all the time and
 	 * enable dithering as needed, but that costs bandwidth.  So choose
@@ -4711,8 +4798,8 @@ static bool intel_choose_pipe_bpp_dither
 
 	display_bpc = min(display_bpc, bpc);
 
-	DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
-			 bpc, display_bpc);
+	DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+		      bpc, display_bpc);
 
 	*pipe_bpp = display_bpc * 3;
 
@@ -4940,6 +5027,16 @@ static int i9xx_crtc_mode_set(struct drm
 			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
 	}
 
+	/* default to 8bpc */
+	pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
+	if (is_dp) {
+		if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+			pipeconf |= PIPECONF_BPP_6 |
+				    PIPECONF_DITHER_EN |
+				    PIPECONF_DITHER_TYPE_SP;
+		}
+	}
+
 	dpll |= DPLL_VCO_ENABLE;
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
@@ -5107,36 +5204,52 @@ static int i9xx_crtc_mode_set(struct drm
 	return ret;
 }
 
-static void ironlake_update_pch_refclk(struct drm_device *dev)
+/*
+ * Initialize reference clocks when the driver loads
+ */
+void ironlake_init_pch_refclk(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_mode_config *mode_config = &dev->mode_config;
-	struct drm_crtc *crtc;
 	struct intel_encoder *encoder;
-	struct intel_encoder *has_edp_encoder = NULL;
 	u32 temp;
 	bool has_lvds = false;
+	bool has_cpu_edp = false;
+	bool has_pch_edp = false;
+	bool has_panel = false;
+	bool has_ck505 = false;
+	bool can_ssc = false;
 
 	/* We need to take the global config into account */
-	list_for_each_entry(crtc, &mode_config->crtc_list, head) {
-		if (!crtc->enabled)
-			continue;
-
-		list_for_each_entry(encoder, &mode_config->encoder_list,
-				    base.head) {
-			if (encoder->base.crtc != crtc)
-				continue;
-
-			switch (encoder->type) {
-			case INTEL_OUTPUT_LVDS:
-				has_lvds = true;
-			case INTEL_OUTPUT_EDP:
-				has_edp_encoder = encoder;
-				break;
-			}
+	list_for_each_entry(encoder, &mode_config->encoder_list,
+			    base.head) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			has_panel = true;
+			has_lvds = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			has_panel = true;
+			if (intel_encoder_is_pch_edp(&encoder->base))
+				has_pch_edp = true;
+			else
+				has_cpu_edp = true;
+			break;
 		}
 	}
 
+	if (HAS_PCH_IBX(dev)) {
+		has_ck505 = dev_priv->display_clock_mode;
+		can_ssc = has_ck505;
+	} else {
+		has_ck505 = false;
+		can_ssc = true;
+	}
+
+	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
+		      has_panel, has_lvds, has_pch_edp, has_cpu_edp,
+		      has_ck505);
+
 	/* Ironlake: try to setup display ref clock before DPLL
 	 * enabling. This is only under driver's control after
 	 * PCH B stepping, previous chipset stepping should be
@@ -5145,43 +5258,102 @@ static void ironlake_update_pch_refclk(s
 	temp = I915_READ(PCH_DREF_CONTROL);
 	/* Always enable nonspread source */
 	temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-	temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-	temp &= ~DREF_SSC_SOURCE_MASK;
-	temp |= DREF_SSC_SOURCE_ENABLE;
-	I915_WRITE(PCH_DREF_CONTROL, temp);
 
-	POSTING_READ(PCH_DREF_CONTROL);
-	udelay(200);
+	if (has_ck505)
+		temp |= DREF_NONSPREAD_CK505_ENABLE;
+	else
+		temp |= DREF_NONSPREAD_SOURCE_ENABLE;
 
-	if (has_edp_encoder) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			temp |= DREF_SSC1_ENABLE;
-			I915_WRITE(PCH_DREF_CONTROL, temp);
+	if (has_panel) {
+		temp &= ~DREF_SSC_SOURCE_MASK;
+		temp |= DREF_SSC_SOURCE_ENABLE;
 
-			POSTING_READ(PCH_DREF_CONTROL);
-			udelay(200);
+		/* SSC must be turned on before enabling the CPU output  */
+		if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+			DRM_DEBUG_KMS("Using SSC on panel\n");
+			temp |= DREF_SSC1_ENABLE;
 		}
+
+		/* Get SSC going before enabling the outputs */
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+
 		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
 		/* Enable CPU source on CPU attached eDP */
-		if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-			if (intel_panel_use_ssc(dev_priv))
+		if (has_cpu_edp) {
+			if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+				DRM_DEBUG_KMS("Using SSC on eDP\n");
 				temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+			}
 			else
 				temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-		} else {
-			/* Enable SSC on PCH eDP if needed */
-			if (intel_panel_use_ssc(dev_priv)) {
-				DRM_ERROR("enabling SSC on PCH\n");
-				temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-			}
-		}
+		} else
+			temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+	} else {
+		DRM_DEBUG_KMS("Disabling SSC entirely\n");
+
+		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+		/* Turn off CPU output */
+		temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+
+		/* Turn off the SSC source */
+		temp &= ~DREF_SSC_SOURCE_MASK;
+		temp |= DREF_SSC_SOURCE_DISABLE;
+
+		/* Turn off SSC1 */
+		temp &= ~ DREF_SSC1_ENABLE;
+
 		I915_WRITE(PCH_DREF_CONTROL, temp);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	}
 }
 
+static int ironlake_get_refclk(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *edp_encoder = NULL;
+	int num_connectors = 0;
+	bool is_lvds = false;
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+		if (encoder->base.crtc != crtc)
+			continue;
+
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			edp_encoder = encoder;
+			break;
+		}
+		num_connectors++;
+	}
+
+	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+			      dev_priv->lvds_ssc_freq);
+		return dev_priv->lvds_ssc_freq * 1000;
+	}
+
+	return 120000;
+}
+
 static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
@@ -5241,16 +5413,7 @@ static int ironlake_crtc_mode_set(struct
 		num_connectors++;
 	}
 
-	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-		refclk = dev_priv->lvds_ssc_freq * 1000;
-		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-			      refclk / 1000);
-	} else {
-		refclk = 96000;
-		if (!has_edp_encoder ||
-		    intel_encoder_is_pch_edp(&has_edp_encoder->base))
-			refclk = 120000; /* 120Mhz refclk */
-	}
+	refclk = ironlake_get_refclk(crtc);
 
 	/*
 	 * Returns a set of divisors for the desired target clock with the given
@@ -5335,7 +5498,7 @@ static int ironlake_crtc_mode_set(struct
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -5377,8 +5540,6 @@ static int ironlake_crtc_mode_set(struct
 	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
 			     &m_n);
 
-	ironlake_update_pch_refclk(dev);
-
 	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 	if (has_reduced_clock)
 		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
@@ -5450,39 +5611,32 @@ static int ironlake_crtc_mode_set(struct
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
 	/* PCH eDP needs FDI, but CPU eDP does not */
-	if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-		I915_WRITE(PCH_FP0(pipe), fp);
-		I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-
-		POSTING_READ(PCH_DPLL(pipe));
-		udelay(150);
-	}
+	if (!intel_crtc->no_pll) {
+		if (!has_edp_encoder ||
+		    intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+			I915_WRITE(PCH_FP0(pipe), fp);
+			I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
 
-	/* enable transcoder DPLL */
-	if (HAS_PCH_CPT(dev)) {
-		temp = I915_READ(PCH_DPLL_SEL);
-		switch (pipe) {
-		case 0:
-			temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
-			break;
-		case 1:
-			temp |=	TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
-			break;
-		case 2:
-			/* FIXME: manage transcoder PLLs? */
-			temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
-			break;
-		default:
-			BUG();
+			POSTING_READ(PCH_DPLL(pipe));
+			udelay(150);
+		}
+	} else {
+		if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
+		    fp == I915_READ(PCH_FP0(0))) {
+			intel_crtc->use_pll_a = true;
+			DRM_DEBUG_KMS("using pipe a dpll\n");
+		} else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
+			   fp == I915_READ(PCH_FP0(1))) {
+			intel_crtc->use_pll_a = false;
+			DRM_DEBUG_KMS("using pipe b dpll\n");
+		} else {
+			DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n");
+			return -EINVAL;
 		}
-		I915_WRITE(PCH_DPLL_SEL, temp);
-
-		POSTING_READ(PCH_DPLL_SEL);
-		udelay(150);
 	}
 
 	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
@@ -5492,17 +5646,13 @@ static int ironlake_crtc_mode_set(struct
 	if (is_lvds) {
 		temp = I915_READ(PCH_LVDS);
 		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-		if (pipe == 1) {
-			if (HAS_PCH_CPT(dev))
-				temp |= PORT_TRANS_B_SEL_CPT;
-			else
-				temp |= LVDS_PIPEB_SELECT;
-		} else {
-			if (HAS_PCH_CPT(dev))
-				temp &= ~PORT_TRANS_SEL_MASK;
-			else
-				temp &= ~LVDS_PIPEB_SELECT;
-		}
+		if (HAS_PCH_CPT(dev))
+			temp |= PORT_TRANS_SEL_CPT(pipe);
+		else if (pipe == 1)
+			temp |= LVDS_PIPEB_SELECT;
+		else
+			temp &= ~LVDS_PIPEB_SELECT;
+
 		/* set the corresponsding LVDS_BORDER bit */
 		temp |= dev_priv->lvds_border_bits;
 		/* Set the B0-B3 data pairs corresponding to whether we're going to
@@ -5540,7 +5690,7 @@ static int ironlake_crtc_mode_set(struct
 	pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
 	if ((is_lvds && dev_priv->lvds_dither) || dither) {
 		pipeconf |= PIPECONF_DITHER_EN;
-		pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+		pipeconf |= PIPECONF_DITHER_TYPE_SP;
 	}
 	if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -5552,8 +5702,9 @@ static int ironlake_crtc_mode_set(struct
 		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
 	}
 
-	if (!has_edp_encoder ||
-	    intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+	if (!intel_crtc->no_pll &&
+	    (!has_edp_encoder ||
+	     intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
 		I915_WRITE(PCH_DPLL(pipe), dpll);
 
 		/* Wait for the clocks to stabilize. */
@@ -5569,18 +5720,20 @@ static int ironlake_crtc_mode_set(struct
 	}
 
 	intel_crtc->lowfreq_avail = false;
-	if (is_lvds && has_reduced_clock && i915_powersave) {
-		I915_WRITE(PCH_FP1(pipe), fp2);
-		intel_crtc->lowfreq_avail = true;
-		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-		}
-	} else {
-		I915_WRITE(PCH_FP1(pipe), fp);
-		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+	if (!intel_crtc->no_pll) {
+		if (is_lvds && has_reduced_clock && i915_powersave) {
+			I915_WRITE(PCH_FP1(pipe), fp2);
+			intel_crtc->lowfreq_avail = true;
+			if (HAS_PIPE_CXSR(dev)) {
+				DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+				pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+			}
+		} else {
+			I915_WRITE(PCH_FP1(pipe), fp);
+			if (HAS_PIPE_CXSR(dev)) {
+				DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+				pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+			}
 		}
 	}
 
@@ -5677,6 +5830,131 @@ static int intel_crtc_mode_set(struct dr
 	return ret;
 }
 
+static void g4x_write_eld(struct drm_connector *connector,
+			  struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	uint8_t *eld = connector->eld;
+	uint32_t eldv;
+	uint32_t len;
+	uint32_t i;
+
+	i = I915_READ(G4X_AUD_VID_DID);
+
+	if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
+		eldv = G4X_ELDV_DEVCL_DEVBLC;
+	else
+		eldv = G4X_ELDV_DEVCTG;
+
+	i = I915_READ(G4X_AUD_CNTL_ST);
+	i &= ~(eldv | G4X_ELD_ADDR);
+	len = (i >> 9) & 0x1f;		/* ELD buffer size */
+	I915_WRITE(G4X_AUD_CNTL_ST, i);
+
+	if (!eld[0])
+		return;
+
+	len = min_t(uint8_t, eld[2], len);
+	DRM_DEBUG_DRIVER("ELD size %d\n", len);
+	for (i = 0; i < len; i++)
+		I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
+
+	i = I915_READ(G4X_AUD_CNTL_ST);
+	i |= eldv;
+	I915_WRITE(G4X_AUD_CNTL_ST, i);
+}
+
+static void ironlake_write_eld(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	uint8_t *eld = connector->eld;
+	uint32_t eldv;
+	uint32_t i;
+	int len;
+	int hdmiw_hdmiedid;
+	int aud_cntl_st;
+	int aud_cntrl_st2;
+
+	if (IS_IVYBRIDGE(connector->dev)) {
+		hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A;
+		aud_cntl_st = GEN7_AUD_CNTRL_ST_A;
+		aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2;
+	} else {
+		hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A;
+		aud_cntl_st = GEN5_AUD_CNTL_ST_A;
+		aud_cntrl_st2 = GEN5_AUD_CNTL_ST2;
+	}
+
+	i = to_intel_crtc(crtc)->pipe;
+	hdmiw_hdmiedid += i * 0x100;
+	aud_cntl_st += i * 0x100;
+
+	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
+
+	i = I915_READ(aud_cntl_st);
+	i = (i >> 29) & 0x3;		/* DIP_Port_Select, 0x1 = PortB */
+	if (!i) {
+		DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
+		/* operate blindly on all ports */
+		eldv = GEN5_ELD_VALIDB;
+		eldv |= GEN5_ELD_VALIDB << 4;
+		eldv |= GEN5_ELD_VALIDB << 8;
+	} else {
+		DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
+		eldv = GEN5_ELD_VALIDB << ((i - 1) * 4);
+	}
+
+	i = I915_READ(aud_cntrl_st2);
+	i &= ~eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+
+	if (!eld[0])
+		return;
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+		DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
+		eld[5] |= (1 << 2);	/* Conn_Type, 0x1 = DisplayPort */
+	}
+
+	i = I915_READ(aud_cntl_st);
+	i &= ~GEN5_ELD_ADDRESS;
+	I915_WRITE(aud_cntl_st, i);
+
+	len = min_t(uint8_t, eld[2], 21);	/* 84 bytes of hw ELD buffer */
+	DRM_DEBUG_DRIVER("ELD size %d\n", len);
+	for (i = 0; i < len; i++)
+		I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
+
+	i = I915_READ(aud_cntrl_st2);
+	i |= eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+}
+
+void intel_write_eld(struct drm_encoder *encoder,
+		     struct drm_display_mode *mode)
+{
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	connector = drm_select_eld(encoder, mode);
+	if (!connector)
+		return;
+
+	DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+			 connector->base.id,
+			 drm_get_connector_name(connector),
+			 connector->encoder->base.id,
+			 drm_get_encoder_name(connector->encoder));
+
+	connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
+
+	if (dev_priv->display.write_eld)
+		dev_priv->display.write_eld(connector, crtc);
+}
+
 /** Loads the palette/gamma unit for the CRTC with the prepared values */
 void intel_crtc_load_lut(struct drm_crtc *crtc)
 {
@@ -5758,6 +6036,31 @@ static void i9xx_update_cursor(struct dr
 	I915_WRITE(CURBASE(pipe), base);
 }
 
+static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	bool visible = base != 0;
+
+	if (intel_crtc->cursor_visible != visible) {
+		uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+		if (base) {
+			cntl &= ~CURSOR_MODE;
+			cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+		} else {
+			cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+			cntl |= CURSOR_MODE_DISABLE;
+		}
+		I915_WRITE(CURCNTR_IVB(pipe), cntl);
+
+		intel_crtc->cursor_visible = visible;
+	}
+	/* and commit changes on next vblank */
+	I915_WRITE(CURBASE_IVB(pipe), base);
+}
+
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
 static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 				     bool on)
@@ -5805,11 +6108,16 @@ static void intel_crtc_update_cursor(str
 	if (!visible && !intel_crtc->cursor_visible)
 		return;
 
-	I915_WRITE(CURPOS(pipe), pos);
-	if (IS_845G(dev) || IS_I865G(dev))
-		i845_update_cursor(crtc, base);
-	else
-		i9xx_update_cursor(crtc, base);
+	if (IS_IVYBRIDGE(dev)) {
+		I915_WRITE(CURPOS_IVB(pipe), pos);
+		ivb_update_cursor(crtc, base);
+	} else {
+		I915_WRITE(CURPOS(pipe), pos);
+		if (IS_845G(dev) || IS_I865G(dev))
+			i845_update_cursor(crtc, base);
+		else
+			i9xx_update_cursor(crtc, base);
+	}
 
 	if (visible)
 		intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
@@ -6899,11 +7207,16 @@ static int intel_crtc_page_flip(struct d
 	work->old_fb_obj = intel_fb->obj;
 	INIT_WORK(&work->work, intel_unpin_work_fn);
 
+	ret = drm_vblank_get(dev, intel_crtc->pipe);
+	if (ret)
+		goto free_work;
+
 	/* We borrow the event spin lock for protecting unpin_work */
 	spin_lock_irqsave(&dev->event_lock, flags);
 	if (intel_crtc->unpin_work) {
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 		kfree(work);
+		drm_vblank_put(dev, intel_crtc->pipe);
 
 		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 		return -EBUSY;
@@ -6922,10 +7235,6 @@ static int intel_crtc_page_flip(struct d
 
 	crtc->fb = fb;
 
-	ret = drm_vblank_get(dev, intel_crtc->pipe);
-	if (ret)
-		goto cleanup_objs;
-
 	work->pending_flip_obj = obj;
 
 	work->enable_stall_check = true;
@@ -6948,7 +7257,6 @@ static int intel_crtc_page_flip(struct d
 
 cleanup_pending:
 	atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
-cleanup_objs:
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
@@ -6957,6 +7265,8 @@ cleanup_objs:
 	intel_crtc->unpin_work = NULL;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
+	drm_vblank_put(dev, intel_crtc->pipe);
+free_work:
 	kfree(work);
 
 	return ret;
@@ -7071,6 +7381,8 @@ static void intel_crtc_init(struct drm_d
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
 	if (HAS_PCH_SPLIT(dev)) {
+		if (pipe == 2 && IS_IVYBRIDGE(dev))
+			intel_crtc->no_pll = true;
 		intel_helper_funcs.prepare = ironlake_crtc_prepare;
 		intel_helper_funcs.commit = ironlake_crtc_commit;
 	} else {
@@ -7250,6 +7562,9 @@ static void intel_setup_outputs(struct d
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
 	drm_helper_disable_unused_functions(dev);
+
+	if (HAS_PCH_SPLIT(dev))
+		ironlake_init_pch_refclk(dev);
 }
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -7494,6 +7809,10 @@ void gen6_disable_rps(struct drm_device
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 	I915_WRITE(GEN6_PMIER, 0);
+	/* Complete PM interrupt masking here doesn't race with the rps work
+	 * item again unmasking PM interrupts because that is using a different
+	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
 	spin_lock_irq(&dev_priv->rps_lock);
 	dev_priv->pm_iir = 0;
@@ -7588,6 +7907,31 @@ void intel_init_emon(struct drm_device *
 	dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
 }
 
+static bool intel_enable_rc6(struct drm_device *dev)
+{
+	/*
+	 * Respect the kernel parameter if it is set
+	 */
+	if (i915_enable_rc6 >= 0)
+		return i915_enable_rc6;
+
+	/*
+	 * Disable RC6 on Ironlake
+	 */
+	if (INTEL_INFO(dev)->gen == 5)
+		return 0;
+
+	/*
+	 * Disable rc6 on Sandybridge
+	 */
+	if (INTEL_INFO(dev)->gen == 6) {
+		DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n");
+		return 0;
+	}
+	DRM_DEBUG_DRIVER("RC6 enabled\n");
+	return 1;
+}
+
 void gen6_enable_rps(struct drm_i915_private *dev_priv)
 {
 	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -7624,7 +7968,7 @@ void gen6_enable_rps(struct drm_i915_pri
 	I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
 	I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
 
-	if (i915_enable_rc6)
+	if (intel_enable_rc6(dev_priv->dev))
 		rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
 			GEN6_RC_CTL_RC6_ENABLE;
 
@@ -7850,6 +8194,20 @@ static void gen6_init_clock_gating(struc
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
+	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+	 * gating disable must be set.  Failure to set it results in
+	 * flickering pixels due to Z write ordering failures after
+	 * some amount of runtime in the Mesa "fire" demo, and Unigine
+	 * Sanctuary and Tropics, and apparently anything else with
+	 * alpha test or pixel discard.
+	 *
+	 * According to the spec, bit 11 (RCCUNIT) must also be set,
+	 * but we didn't debug actual testcases to find it out.
+	 */
+	I915_WRITE(GEN6_UCGCTL2,
+		   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
 	/*
 	 * According to the spec the following bits should be
 	 * set in order to enable memory self-refresh and fbc:
@@ -8059,7 +8417,7 @@ void ironlake_enable_rc6(struct drm_devi
 	/* rc6 disabled by default due to repeated reports of hanging during
 	 * boot and resume.
 	 */
-	if (!i915_enable_rc6)
+	if (!intel_enable_rc6(dev))
 		return;
 
 	mutex_lock(&dev->struct_mutex);
@@ -8154,7 +8512,7 @@ static void intel_init_display(struct dr
 	}
 
 	/* Returns the core display clock speed */
-	if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev)))
+	if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
 		dev_priv->display.get_display_clock_speed =
 			i945_get_display_clock_speed;
 	else if (IS_I915G(dev))
@@ -8178,6 +8536,28 @@ static void intel_init_display(struct dr
 
 	/* For FIFO watermark updates */
 	if (HAS_PCH_SPLIT(dev)) {
+		dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
+		dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
+
+		/* IVB configs may use multi-threaded forcewake */
+		if (IS_IVYBRIDGE(dev)) {
+			u32	ecobus;
+
+			mutex_lock(&dev->struct_mutex);
+			__gen6_gt_force_wake_mt_get(dev_priv);
+			ecobus = I915_READ(ECOBUS);
+			__gen6_gt_force_wake_mt_put(dev_priv);
+			mutex_unlock(&dev->struct_mutex);
+
+			if (ecobus & FORCEWAKE_MT_ENABLE) {
+				DRM_DEBUG_KMS("Using MT version of forcewake\n");
+				dev_priv->display.force_wake_get =
+					__gen6_gt_force_wake_mt_get;
+				dev_priv->display.force_wake_put =
+					__gen6_gt_force_wake_mt_put;
+			}
+		}
+
 		if (HAS_PCH_IBX(dev))
 			dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
 		else if (HAS_PCH_CPT(dev))
@@ -8193,6 +8573,7 @@ static void intel_init_display(struct dr
 			}
 			dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
 			dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else if (IS_GEN6(dev)) {
 			if (SNB_READ_WM0_LATENCY()) {
 				dev_priv->display.update_wm = sandybridge_update_wm;
@@ -8203,6 +8584,7 @@ static void intel_init_display(struct dr
 			}
 			dev_priv->display.fdi_link_train = gen6_fdi_link_train;
 			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else if (IS_IVYBRIDGE(dev)) {
 			/* FIXME: detect B0+ stepping and use auto training */
 			dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
@@ -8214,7 +8596,7 @@ static void intel_init_display(struct dr
 				dev_priv->display.update_wm = NULL;
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_PINEVIEW(dev)) {
@@ -8225,7 +8607,7 @@ static void intel_init_display(struct dr
 			DRM_INFO("failed to find known CxSR latency "
 				 "(found ddr%s fsb freq %d, mem freq %d), "
 				 "disabling CxSR\n",
-				 (dev_priv->is_ddr3 == 1) ? "3": "2",
+				 (dev_priv->is_ddr3 == 1) ? "3" : "2",
 				 dev_priv->fsb_freq, dev_priv->mem_freq);
 			/* Disable CxSR and never update its watermark again */
 			pineview_disable_cxsr(dev);
@@ -8234,6 +8616,7 @@ static void intel_init_display(struct dr
 			dev_priv->display.update_wm = pineview_update_wm;
 		dev_priv->display.init_clock_gating = gen3_init_clock_gating;
 	} else if (IS_G4X(dev)) {
+		dev_priv->display.write_eld = g4x_write_eld;
 		dev_priv->display.update_wm = g4x_update_wm;
 		dev_priv->display.init_clock_gating = g4x_init_clock_gating;
 	} else if (IS_GEN4(dev)) {
@@ -8294,7 +8677,7 @@ static void intel_init_display(struct dr
  * resume, or other times.  This quirk makes sure that's the case for
  * affected systems.
  */
-static void quirk_pipea_force (struct drm_device *dev)
+static void quirk_pipea_force(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -8322,7 +8705,7 @@ struct intel_quirk intel_quirks[] = {
 	/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
 	{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
 	/* HP Mini needs pipe A force quirk (LP: #322104) */
-	{ 0x27ae,0x103c, 0x361a, quirk_pipea_force },
+	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
 
 	/* Thinkpad R31 needs pipe A force quirk */
 	{ 0x3577, 0x1014, 0x0505, quirk_pipea_force },
@@ -8488,6 +8871,7 @@ void intel_modeset_cleanup(struct drm_de
 	 * enqueue unpin/hotplug work. */
 	drm_irq_uninstall(dev);
 	cancel_work_sync(&dev_priv->hotplug_work);
+	cancel_work_sync(&dev_priv->rps_work);
 
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
@@ -8573,7 +8957,7 @@ struct intel_display_error_state {
 struct intel_display_error_state *
 intel_display_capture_error_state(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_display_error_state *error;
 	int i;
 
@@ -8589,7 +8973,7 @@ intel_display_capture_error_state(struct
 		error->plane[i].control = I915_READ(DSPCNTR(i));
 		error->plane[i].stride = I915_READ(DSPSTRIDE(i));
 		error->plane[i].size = I915_READ(DSPSIZE(i));
-		error->plane[i].pos= I915_READ(DSPPOS(i));
+		error->plane[i].pos = I915_READ(DSPPOS(i));
 		error->plane[i].addr = I915_READ(DSPADDR(i));
 		if (INTEL_INFO(dev)->gen >= 4) {
 			error->plane[i].surface = I915_READ(DSPSURF(i));
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_dp.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
@@ -36,7 +37,7 @@
 #include "i915_drv.h"
 #include "drm_dp_helper.h"
 
-
+#define DP_RECEIVER_CAP_SIZE	0xf
 #define DP_LINK_STATUS_SIZE	6
 #define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
 
@@ -53,12 +54,19 @@ struct intel_dp {
 	int dpms_mode;
 	uint8_t link_bw;
 	uint8_t lane_count;
-	uint8_t dpcd[8];
+	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
 	bool is_pch_edp;
 	uint8_t	train_set[4];
-	uint8_t link_status[DP_LINK_STATUS_SIZE];
+	int panel_power_up_delay;
+	int panel_power_down_delay;
+	int panel_power_cycle_delay;
+	int backlight_on_delay;
+	int backlight_off_delay;
+	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
+	struct delayed_work panel_vdd_work;
+	bool want_panel_vdd;
 };
 
 /**
@@ -86,6 +94,17 @@ static bool is_pch_edp(struct intel_dp *
 	return intel_dp->is_pch_edp;
 }
 
+/**
+ * is_cpu_edp - is the port on the CPU and attached to an eDP panel?
+ * @intel_dp: DP struct
+ *
+ * Returns true if the given DP struct corresponds to a CPU eDP port.
+ */
+static bool is_cpu_edp(struct intel_dp *intel_dp)
+{
+	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
+}
+
 static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 {
 	return container_of(encoder, struct intel_dp, base.base);
@@ -121,7 +140,7 @@ static void intel_dp_complete_link_train
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
-intel_edp_link_config (struct intel_encoder *intel_encoder,
+intel_edp_link_config(struct intel_encoder *intel_encoder,
 		       int *lane_num, int *link_bw)
 {
 	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
@@ -136,16 +155,12 @@ intel_edp_link_config (struct intel_enco
 static int
 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
-	int max_lane_count = 4;
-
-	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
-		max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
-		switch (max_lane_count) {
-		case 1: case 2: case 4:
-			break;
-		default:
-			max_lane_count = 4;
-		}
+	int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
+	switch (max_lane_count) {
+	case 1: case 2: case 4:
+		break;
+	default:
+		max_lane_count = 4;
 	}
 	return max_lane_count;
 }
@@ -175,18 +190,36 @@ intel_dp_link_clock(uint8_t link_bw)
 		return 162000;
 }
 
-/* I think this is a fiction */
+/*
+ * The units on the numbers in the next two are... bizarre.  Examples will
+ * make it clearer; this one parallels an example in the eDP spec.
+ *
+ * intel_dp_max_data_rate for one lane of 2.7GHz evaluates as:
+ *
+ *     270000 * 1 * 8 / 10 == 216000
+ *
+ * The actual data capacity of that configuration is 2.16Gbit/s, so the
+ * units are decakilobits.  ->clock in a drm_display_mode is in kilohertz -
+ * or equivalently, kilopixels per second - so for 1680x1050R it'd be
+ * 119000.  At 18bpp that's 2142000 kilobits per second.
+ *
+ * Thus the strange-looking division by 10 in intel_dp_link_required, to
+ * get the result in decakilobits instead of kilobits.
+ */
+
 static int
-intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
+intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
 {
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int bpp = 24;
 
-	if (intel_crtc)
+	if (check_bpp)
+		bpp = check_bpp;
+	else if (intel_crtc)
 		bpp = intel_crtc->bpp;
 
-	return (pixel_clock * bpp + 7) / 8;
+	return (pixel_clock * bpp + 9) / 10;
 }
 
 static int
@@ -200,25 +233,29 @@ intel_dp_mode_valid(struct drm_connector
 		    struct drm_display_mode *mode)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
 	int max_lanes = intel_dp_max_lane_count(intel_dp);
+	int max_rate, mode_rate;
 
-	if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
-		if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
+	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+		if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
 			return MODE_PANEL;
 
-		if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay)
+		if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
 			return MODE_PANEL;
 	}
 
-	/* only refuse the mode on non eDP since we have seen some weird eDP panels
-	   which are outside spec tolerances but somehow work by magic */
-	if (!is_edp(intel_dp) &&
-	    (intel_dp_link_required(connector->dev, intel_dp, mode->clock)
-	     > intel_dp_max_data_rate(max_link_clock, max_lanes)))
-		return MODE_CLOCK_HIGH;
+	mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
+	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+
+	if (mode_rate > max_rate) {
+			mode_rate = intel_dp_link_required(intel_dp,
+							   mode->clock, 18);
+			if (mode_rate > max_rate)
+				return MODE_CLOCK_HIGH;
+			else
+				mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
+	}
 
 	if (mode->clock < 10000)
 		return MODE_CLOCK_LOW;
@@ -279,6 +316,38 @@ intel_hrawclk(struct drm_device *dev)
 	}
 }
 
+static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+}
+
+static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
+}
+
+static void
+intel_dp_check_edp(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!is_edp(intel_dp))
+		return;
+	if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
+		WARN(1, "eDP powered off while attempting aux channel communication.\n");
+		DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
+			      I915_READ(PCH_PP_STATUS),
+			      I915_READ(PCH_PP_CONTROL));
+	}
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *send, int send_bytes,
@@ -295,6 +364,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 	uint32_t aux_clock_divider;
 	int try, precharge;
 
+	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
 	 * hrawclk value and divide by 2 and use that
@@ -302,9 +372,9 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 	 * Note that PCH attached eDP panels should use a 125MHz input
 	 * clock divider.
 	 */
-	if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
-		if (IS_GEN6(dev))
-			aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
+	if (is_cpu_edp(intel_dp)) {
+		if (IS_GEN6(dev) || IS_GEN7(dev))
+			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
 	} else if (HAS_PCH_SPLIT(dev))
@@ -337,7 +407,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 		for (i = 0; i < send_bytes; i += 4)
 			I915_WRITE(ch_data + i,
 				   pack_aux(send + i, send_bytes - i));
-	
+
 		/* Send the command and wait for it to complete */
 		I915_WRITE(ch_ctl,
 			   DP_AUX_CH_CTL_SEND_BUSY |
@@ -354,7 +424,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 				break;
 			udelay(100);
 		}
-	
+
 		/* Clear done status and any errors */
 		I915_WRITE(ch_ctl,
 			   status |
@@ -390,7 +460,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
 	if (recv_bytes > recv_size)
 		recv_bytes = recv_size;
-	
+
 	for (i = 0; i < recv_bytes; i += 4)
 		unpack_aux(I915_READ(ch_data + i),
 			   recv + i, recv_bytes - i);
@@ -408,6 +478,7 @@ intel_dp_aux_native_write(struct intel_d
 	int msg_bytes;
 	uint8_t	ack;
 
+	intel_dp_check_edp(intel_dp);
 	if (send_bytes > 16)
 		return -1;
 	msg[0] = AUX_NATIVE_WRITE << 4;
@@ -450,6 +521,7 @@ intel_dp_aux_native_read(struct intel_dp
 	uint8_t ack;
 	int ret;
 
+	intel_dp_check_edp(intel_dp);
 	msg[0] = AUX_NATIVE_READ << 4;
 	msg[1] = address >> 8;
 	msg[2] = address & 0xff;
@@ -493,6 +565,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *
 	int reply_bytes;
 	int ret;
 
+	intel_dp_check_edp(intel_dp);
 	/* Set up the command byte */
 	if (mode & MODE_I2C_READ)
 		msg[0] = AUX_I2C_READ << 4;
@@ -573,24 +646,32 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *
 	return -EREMOTEIO;
 }
 
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
 		  struct intel_connector *intel_connector, const char *name)
 {
+	int	ret;
+
 	DRM_DEBUG_KMS("i2c_init %s\n", name);
 	intel_dp->algo.running = false;
 	intel_dp->algo.address = 0;
 	intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
 
-	memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
+	memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter));
 	intel_dp->adapter.owner = THIS_MODULE;
 	intel_dp->adapter.class = I2C_CLASS_DDC;
-	strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
+	strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
 	intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
 	intel_dp->adapter.algo_data = &intel_dp->algo;
 	intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
 
-	return i2c_dp_aux_add_bus(&intel_dp->adapter);
+	ironlake_edp_panel_vdd_on(intel_dp);
+	ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return ret;
 }
 
 static bool
@@ -598,29 +679,29 @@ intel_dp_mode_fixup(struct drm_encoder *
 		    struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	int lane_count, clock;
 	int max_lane_count = intel_dp_max_lane_count(intel_dp);
 	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
+	int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
-	if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
-		intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
+	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+		intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
 		intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
 					mode, adjusted_mode);
 		/*
 		 * the mode->clock is used to calculate the Data&Link M/N
 		 * of the pipe. For the eDP the fixed clock should be used.
 		 */
-		mode->clock = dev_priv->panel_fixed_mode->clock;
+		mode->clock = intel_dp->panel_fixed_mode->clock;
 	}
 
 	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 		for (clock = 0; clock <= max_clock; clock++) {
 			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-			if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock)
+			if (intel_dp_link_required(intel_dp, mode->clock, bpp)
 					<= link_avail) {
 				intel_dp->link_bw = bws[clock];
 				intel_dp->lane_count = lane_count;
@@ -634,19 +715,6 @@ intel_dp_mode_fixup(struct drm_encoder *
 		}
 	}
 
-	if (is_edp(intel_dp)) {
-		/* okay we failed just pick the highest */
-		intel_dp->lane_count = max_lane_count;
-		intel_dp->link_bw = bws[max_clock];
-		adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
-		DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
-			      "count %d clock %d\n",
-			      intel_dp->link_bw, intel_dp->lane_count,
-			      adjusted_mode->clock);
-
-		return true;
-	}
-
 	return false;
 }
 
@@ -706,12 +774,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc,
 			continue;
 
 		intel_dp = enc_to_intel_dp(encoder);
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		{
 			lane_count = intel_dp->lane_count;
 			break;
-		} else if (is_edp(intel_dp)) {
-			lane_count = dev_priv->edp.lanes;
-			break;
 		}
 	}
 
@@ -740,27 +807,53 @@ intel_dp_set_m_n(struct drm_crtc *crtc,
 	}
 }
 
+static void ironlake_edp_pll_on(struct drm_encoder *encoder);
+static void ironlake_edp_pll_off(struct drm_encoder *encoder);
+
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-	intel_dp->DP |= intel_dp->color_range;
+	/* Turn on the eDP PLL if needed */
+	if (is_edp(intel_dp)) {
+		if (!is_pch_edp(intel_dp))
+			ironlake_edp_pll_on(encoder);
+		else
+			ironlake_edp_pll_off(encoder);
+	}
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		intel_dp->DP |= DP_SYNC_HS_HIGH;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		intel_dp->DP |= DP_SYNC_VS_HIGH;
+	/*
+	 * There are four kinds of DP registers:
+	 *
+	 * 	IBX PCH
+	 * 	SNB CPU
+	 *	IVB CPU
+	 * 	CPT PCH
+	 *
+	 * IBX PCH and CPU are the same for almost everything,
+	 * except that the CPU DP PLL is configured in this
+	 * register
+	 *
+	 * CPT PCH is quite different, having many bits moved
+	 * to the TRANS_DP_CTL register instead. That
+	 * configuration happens (oddly) in ironlake_pch_enable
+	 */
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
-		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-	else
-		intel_dp->DP |= DP_LINK_TRAIN_OFF;
+	/* Preserve the BIOS-computed detected bit. This is
+	 * supposed to be read-only.
+	 */
+	intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
+	intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+
+	/* Handle DP bits in common between all three register formats */
+
+	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
 	switch (intel_dp->lane_count) {
 	case 1:
@@ -773,135 +866,297 @@ intel_dp_mode_set(struct drm_encoder *en
 		intel_dp->DP |= DP_PORT_WIDTH_4;
 		break;
 	}
-	if (intel_dp->has_audio)
+	if (intel_dp->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+				 pipe_name(intel_crtc->pipe));
 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
-
+		intel_write_eld(encoder, adjusted_mode);
+	}
 	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
 	intel_dp->link_configuration[0] = intel_dp->link_bw;
 	intel_dp->link_configuration[1] = intel_dp->lane_count;
 	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-
 	/*
 	 * Check for DPCD version > 1.1 and enhanced framing support
 	 */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
 		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-		intel_dp->DP |= DP_ENHANCED_FRAMING;
 	}
 
-	/* CPT DP's pipe select is decided in TRANS_DP_CTL */
-	if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
-		intel_dp->DP |= DP_PIPEB_SELECT;
+	/* Split out the IBX/CPU vs CPT settings */
+
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
+
+		if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+		intel_dp->DP |= intel_crtc->pipe << 29;
 
-	if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
 		/* don't miss out required setting for eDP */
 		intel_dp->DP |= DP_PLL_ENABLE;
 		if (adjusted_mode->clock < 200000)
 			intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 		else
 			intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+		intel_dp->DP |= intel_dp->color_range;
+
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF;
+
+		if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+		if (intel_crtc->pipe == 1)
+			intel_dp->DP |= DP_PIPEB_SELECT;
+
+		if (is_cpu_edp(intel_dp)) {
+			/* don't miss out required setting for eDP */
+			intel_dp->DP |= DP_PLL_ENABLE;
+			if (adjusted_mode->clock < 200000)
+				intel_dp->DP |= DP_PLL_FREQ_160MHZ;
+			else
+				intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+		}
+	} else {
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
 	}
 }
 
+#define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE   	(PP_ON | 0 	  | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+
+#define IDLE_OFF_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_OFF_VALUE		(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+#define IDLE_CYCLE_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE	(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
+				       u32 mask,
+				       u32 value)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
+		      mask, value,
+		      I915_READ(PCH_PP_STATUS),
+		      I915_READ(PCH_PP_CONTROL));
+
+	if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+		DRM_ERROR("Panel status timeout: status %08x control %08x\n",
+			  I915_READ(PCH_PP_STATUS),
+			  I915_READ(PCH_PP_CONTROL));
+	}
+}
+
+static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power on\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+}
+
+static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power off time\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+}
+
+static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power cycle\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+}
+
+
+/* Read the current pp_control value, unlocking the register if it
+ * is locked
+ */
+
+static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+{
+	u32	control = I915_READ(PCH_PP_CONTROL);
+
+	control &= ~PANEL_UNLOCK_MASK;
+	control |= PANEL_UNLOCK_REGS;
+	return control;
+}
+
 static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
-	/*
-	 * If the panel wasn't on, make sure there's not a currently
-	 * active PP sequence before enabling AUX VDD.
-	 */
-	if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
-		msleep(dev_priv->panel_t3);
+	if (!is_edp(intel_dp))
+		return;
+	DRM_DEBUG_KMS("Turn eDP VDD on\n");
 
-	pp = I915_READ(PCH_PP_CONTROL);
+	WARN(intel_dp->want_panel_vdd,
+	     "eDP VDD already requested on\n");
+
+	intel_dp->want_panel_vdd = true;
+
+	if (ironlake_edp_have_panel_vdd(intel_dp)) {
+		DRM_DEBUG_KMS("eDP VDD already on\n");
+		return;
+	}
+
+	if (!ironlake_edp_have_panel_power(intel_dp))
+		ironlake_wait_panel_power_cycle(intel_dp);
+
+	pp = ironlake_get_pp_control(dev_priv);
 	pp |= EDP_FORCE_VDD;
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+		      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+
+	/*
+	 * If the panel wasn't on, delay before accessing aux channel
+	 */
+	if (!ironlake_edp_have_panel_power(intel_dp)) {
+		DRM_DEBUG_KMS("eDP was not running\n");
+		msleep(intel_dp->panel_power_up_delay);
+	}
 }
 
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
-	pp = I915_READ(PCH_PP_CONTROL);
-	pp &= ~EDP_FORCE_VDD;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
+		pp = ironlake_get_pp_control(dev_priv);
+		pp &= ~EDP_FORCE_VDD;
+		I915_WRITE(PCH_PP_CONTROL, pp);
+		POSTING_READ(PCH_PP_CONTROL);
 
-	/* Make sure sequencer is idle before allowing subsequent activity */
-	msleep(dev_priv->panel_t12);
+		/* Make sure sequencer is idle before allowing subsequent activity */
+		DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+			      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+
+		msleep(intel_dp->panel_power_down_delay);
+	}
 }
 
-/* Returns true if the panel was already on when called */
-static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
+static void ironlake_panel_vdd_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+						 struct intel_dp, panel_vdd_work);
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	mutex_lock(&dev->mode_config.mutex);
+	ironlake_panel_vdd_off_sync(intel_dp);
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+	if (!is_edp(intel_dp))
+		return;
+
+	DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
+	WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
+
+	intel_dp->want_panel_vdd = false;
+
+	if (sync) {
+		ironlake_panel_vdd_off_sync(intel_dp);
+	} else {
+		/*
+		 * Queue the timer to fire a long
+		 * time from now (relative to the power down delay)
+		 * to keep the panel power up across a sequence of operations
+		 */
+		schedule_delayed_work(&intel_dp->panel_vdd_work,
+				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+	}
+}
+
+static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
+	u32 pp;
 
-	if (I915_READ(PCH_PP_STATUS) & PP_ON)
-		return true;
+	if (!is_edp(intel_dp))
+		return;
 
-	pp = I915_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("Turn eDP power on\n");
 
-	/* ILK workaround: disable reset around power sequence */
-	pp &= ~PANEL_POWER_RESET;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	if (ironlake_edp_have_panel_power(intel_dp)) {
+		DRM_DEBUG_KMS("eDP power already on\n");
+		return;
+	}
 
-	pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	ironlake_wait_panel_power_cycle(intel_dp);
 
-	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
-		     5000))
-		DRM_ERROR("panel on wait timed out: 0x%08x\n",
-			  I915_READ(PCH_PP_STATUS));
+	pp = ironlake_get_pp_control(dev_priv);
+	if (IS_GEN5(dev)) {
+		/* ILK workaround: disable reset around power sequence */
+		pp &= ~PANEL_POWER_RESET;
+		I915_WRITE(PCH_PP_CONTROL, pp);
+		POSTING_READ(PCH_PP_CONTROL);
+	}
+
+	pp |= POWER_TARGET_ON;
+	if (!IS_GEN5(dev))
+		pp |= PANEL_POWER_RESET;
 
-	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
 
-	return false;
+	ironlake_wait_panel_on(intel_dp);
+
+	if (IS_GEN5(dev)) {
+		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+		I915_WRITE(PCH_PP_CONTROL, pp);
+		POSTING_READ(PCH_PP_CONTROL);
+	}
 }
 
-static void ironlake_edp_panel_off (struct drm_device *dev)
+static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
-		PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
-
-	pp = I915_READ(PCH_PP_CONTROL);
+	u32 pp;
 
-	/* ILK workaround: disable reset around power sequence */
-	pp &= ~PANEL_POWER_RESET;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	if (!is_edp(intel_dp))
+		return;
 
-	pp &= ~POWER_TARGET_ON;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
-		DRM_ERROR("panel off wait timed out: 0x%08x\n",
-			  I915_READ(PCH_PP_STATUS));
+	WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n");
 
-	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+	pp = ironlake_get_pp_control(dev_priv);
+	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
+
+	ironlake_wait_panel_off(intel_dp);
 }
 
-static void ironlake_edp_backlight_on (struct drm_device *dev)
+static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
+	if (!is_edp(intel_dp))
+		return;
+
 	DRM_DEBUG_KMS("\n");
 	/*
 	 * If we enable the backlight right away following a panel power
@@ -909,21 +1164,28 @@ static void ironlake_edp_backlight_on (s
 	 * link.  So delay a bit to make sure the image is solid before
 	 * allowing it to appear.
 	 */
-	msleep(300);
-	pp = I915_READ(PCH_PP_CONTROL);
+	msleep(intel_dp->backlight_on_delay);
+	pp = ironlake_get_pp_control(dev_priv);
 	pp |= EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
 }
 
-static void ironlake_edp_backlight_off (struct drm_device *dev)
+static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
+	if (!is_edp(intel_dp))
+		return;
+
 	DRM_DEBUG_KMS("\n");
-	pp = I915_READ(PCH_PP_CONTROL);
+	pp = ironlake_get_pp_control(dev_priv);
 	pp &= ~EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+	msleep(intel_dp->backlight_off_delay);
 }
 
 static void ironlake_edp_pll_on(struct drm_encoder *encoder)
@@ -986,43 +1248,39 @@ static void intel_dp_sink_dpms(struct in
 static void intel_dp_prepare(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
+
+	ironlake_edp_backlight_off(intel_dp);
+	ironlake_edp_panel_off(intel_dp);
 
 	/* Wake up the sink first */
+	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-
-	if (is_edp(intel_dp)) {
-		ironlake_edp_backlight_off(dev);
-		ironlake_edp_panel_off(dev);
-		if (!is_pch_edp(intel_dp))
-			ironlake_edp_pll_on(encoder);
-		else
-			ironlake_edp_pll_off(encoder);
-	}
 	intel_dp_link_down(intel_dp);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+
+	/* Make sure the panel is off before trying to
+	 * change the mode
+	 */
 }
 
 static void intel_dp_commit(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
 
-	if (is_edp(intel_dp))
-		ironlake_edp_panel_vdd_on(intel_dp);
-
+	ironlake_edp_panel_vdd_on(intel_dp);
+	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
-
-	if (is_edp(intel_dp)) {
-		ironlake_edp_panel_on(intel_dp);
-		ironlake_edp_panel_vdd_off(intel_dp);
-	}
-
+	ironlake_edp_panel_on(intel_dp);
+	ironlake_edp_panel_vdd_off(intel_dp, true);
 	intel_dp_complete_link_train(intel_dp);
-
-	if (is_edp(intel_dp))
-		ironlake_edp_backlight_on(dev);
+	ironlake_edp_backlight_on(intel_dp);
 
 	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void
@@ -1034,28 +1292,30 @@ intel_dp_dpms(struct drm_encoder *encode
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		if (is_edp(intel_dp))
-			ironlake_edp_backlight_off(dev);
+		ironlake_edp_backlight_off(intel_dp);
+		ironlake_edp_panel_off(intel_dp);
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		intel_dp_sink_dpms(intel_dp, mode);
 		intel_dp_link_down(intel_dp);
-		if (is_edp(intel_dp))
-			ironlake_edp_panel_off(dev);
-		if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+
+		if (is_cpu_edp(intel_dp))
 			ironlake_edp_pll_off(encoder);
 	} else {
-		if (is_edp(intel_dp))
-			ironlake_edp_panel_vdd_on(intel_dp);
+		if (is_cpu_edp(intel_dp))
+			ironlake_edp_pll_on(encoder);
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		intel_dp_sink_dpms(intel_dp, mode);
 		if (!(dp_reg & DP_PORT_EN)) {
 			intel_dp_start_link_train(intel_dp);
-			if (is_edp(intel_dp)) {
-				ironlake_edp_panel_on(intel_dp);
-				ironlake_edp_panel_vdd_off(intel_dp);
-			}
+			ironlake_edp_panel_on(intel_dp);
+			ironlake_edp_panel_vdd_off(intel_dp, true);
 			intel_dp_complete_link_train(intel_dp);
-		}
-		if (is_edp(intel_dp))
-			ironlake_edp_backlight_on(dev);
+		} else
+			ironlake_edp_panel_vdd_off(intel_dp, false);
+		ironlake_edp_backlight_on(intel_dp);
 	}
 	intel_dp->dpms_mode = mode;
 }
@@ -1090,11 +1350,11 @@ intel_dp_aux_native_read_retry(struct in
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_dp *intel_dp)
+intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	return intel_dp_aux_native_read_retry(intel_dp,
 					      DP_LANE0_1_STATUS,
-					      intel_dp->link_status,
+					      link_status,
 					      DP_LINK_STATUS_SIZE);
 }
 
@@ -1106,27 +1366,25 @@ intel_dp_link_status(uint8_t link_status
 }
 
 static uint8_t
-intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_voltage(uint8_t adjust_request[2],
 				 int lane)
 {
-	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
 	int	    s = ((lane & 1) ?
 			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
 			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = adjust_request[lane>>1];
 
 	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
 }
 
 static uint8_t
-intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],
 				      int lane)
 {
-	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
 	int	    s = ((lane & 1) ?
 			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
 			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = adjust_request[lane>>1];
 
 	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
 }
@@ -1148,34 +1406,63 @@ static char	*link_train_names[] = {
  * These are source-specific values; current Intel hardware supports
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
  */
-#define I830_DP_VOLTAGE_MAX	    DP_TRAIN_VOLTAGE_SWING_800
 
 static uint8_t
-intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
-	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-	case DP_TRAIN_VOLTAGE_SWING_400:
-		return DP_TRAIN_PRE_EMPHASIS_6;
-	case DP_TRAIN_VOLTAGE_SWING_600:
-		return DP_TRAIN_PRE_EMPHASIS_6;
-	case DP_TRAIN_VOLTAGE_SWING_800:
-		return DP_TRAIN_PRE_EMPHASIS_3_5;
-	case DP_TRAIN_VOLTAGE_SWING_1200:
-	default:
-		return DP_TRAIN_PRE_EMPHASIS_0;
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
+		return DP_TRAIN_VOLTAGE_SWING_800;
+	else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+		return DP_TRAIN_VOLTAGE_SWING_1200;
+	else
+		return DP_TRAIN_VOLTAGE_SWING_800;
+}
+
+static uint8_t
+intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
+	} else {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		case DP_TRAIN_VOLTAGE_SWING_1200:
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
 	}
 }
 
 static void
-intel_get_adjust_train(struct intel_dp *intel_dp)
+intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	uint8_t v = 0;
 	uint8_t p = 0;
 	int lane;
+	uint8_t	*adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
+	uint8_t voltage_max;
+	uint8_t preemph_max;
 
 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
-		uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
+		uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
+		uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);
 
 		if (this_v > v)
 			v = this_v;
@@ -1183,18 +1470,20 @@ intel_get_adjust_train(struct intel_dp *
 			p = this_p;
 	}
 
-	if (v >= I830_DP_VOLTAGE_MAX)
-		v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+	voltage_max = intel_dp_voltage_max(intel_dp);
+	if (v >= voltage_max)
+		v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
 
-	if (p >= intel_dp_pre_emphasis_max(v))
-		p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+	preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+	if (p >= preemph_max)
+		p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
 
 	for (lane = 0; lane < 4; lane++)
 		intel_dp->train_set[lane] = v | p;
 }
 
 static uint32_t
-intel_dp_signal_levels(uint8_t train_set, int lane_count)
+intel_dp_signal_levels(uint8_t train_set)
 {
 	uint32_t	signal_levels = 0;
 
@@ -1259,13 +1548,43 @@ intel_gen6_edp_signal_levels(uint8_t tra
 	}
 }
 
+/* Gen7's DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_gen7_edp_signal_levels(uint8_t train_set)
+{
+	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+					 DP_TRAIN_PRE_EMPHASIS_MASK);
+	switch (signal_levels) {
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_400MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+		return EDP_LINK_TRAIN_400MV_6DB_IVB;
+
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_600MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
+
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_800MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
+
+	default:
+		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+			      "0x%x\n", signal_levels);
+		return EDP_LINK_TRAIN_500MV_0DB_IVB;
+	}
+}
+
 static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
 		      int lane)
 {
-	int i = DP_LANE0_1_STATUS + (lane >> 1);
 	int s = (lane & 1) * 4;
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = link_status[lane>>1];
 
 	return (l >> s) & 0xf;
 }
@@ -1290,18 +1609,18 @@ intel_clock_recovery_ok(uint8_t link_sta
 			 DP_LANE_CHANNEL_EQ_DONE|\
 			 DP_LANE_SYMBOL_LOCKED)
 static bool
-intel_channel_eq_ok(struct intel_dp *intel_dp)
+intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	uint8_t lane_align;
 	uint8_t lane_status;
 	int lane;
 
-	lane_align = intel_dp_link_status(intel_dp->link_status,
+	lane_align = intel_dp_link_status(link_status,
 					  DP_LANE_ALIGN_STATUS_UPDATED);
 	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
 		return false;
 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		lane_status = intel_get_lane_status(intel_dp->link_status, lane);
+		lane_status = intel_get_lane_status(link_status, lane);
 		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
 			return false;
 	}
@@ -1326,8 +1645,9 @@ intel_dp_set_link_train(struct intel_dp
 
 	ret = intel_dp_aux_native_write(intel_dp,
 					DP_TRAINING_LANE0_SET,
-					intel_dp->train_set, 4);
-	if (ret != 4)
+					intel_dp->train_set,
+					intel_dp->lane_count);
+	if (ret != intel_dp->lane_count)
 		return false;
 
 	return true;
@@ -1343,7 +1663,7 @@ intel_dp_start_link_train(struct intel_d
 	int i;
 	uint8_t voltage;
 	bool clock_recovery = false;
-	int tries;
+	int voltage_tries, loop_tries;
 	u32 reg;
 	uint32_t DP = intel_dp->DP;
 
@@ -1364,26 +1684,35 @@ intel_dp_start_link_train(struct intel_d
 				  DP_LINK_CONFIGURATION_SIZE);
 
 	DP |= DP_PORT_EN;
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 	else
 		DP &= ~DP_LINK_TRAIN_MASK;
 	memset(intel_dp->train_set, 0, 4);
 	voltage = 0xff;
-	tries = 0;
+	voltage_tries = 0;
+	loop_tries = 0;
 	clock_recovery = false;
 	for (;;) {
 		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 		uint32_t    signal_levels;
-		if (IS_GEN6(dev) && is_edp(intel_dp)) {
+
+
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
+			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
+		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
-			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
+			DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 			reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
 		else
 			reg = DP | DP_LINK_TRAIN_PAT_1;
@@ -1395,10 +1724,13 @@ intel_dp_start_link_train(struct intel_d
 		/* Set training pattern 1 */
 
 		udelay(100);
-		if (!intel_dp_get_link_status(intel_dp))
+		if (!intel_dp_get_link_status(intel_dp, link_status)) {
+			DRM_ERROR("failed to get link status\n");
 			break;
+		}
 
-		if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+		if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+			DRM_DEBUG_KMS("clock recovery OK\n");
 			clock_recovery = true;
 			break;
 		}
@@ -1407,20 +1739,30 @@ intel_dp_start_link_train(struct intel_d
 		for (i = 0; i < intel_dp->lane_count; i++)
 			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
 				break;
-		if (i == intel_dp->lane_count)
-			break;
+		if (i == intel_dp->lane_count) {
+			++loop_tries;
+			if (loop_tries == 5) {
+				DRM_DEBUG_KMS("too many full retries, give up\n");
+				break;
+			}
+			memset(intel_dp->train_set, 0, 4);
+			voltage_tries = 0;
+			continue;
+		}
 
 		/* Check to see if we've tried the same voltage 5 times */
 		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-			++tries;
-			if (tries == 5)
+			++voltage_tries;
+			if (voltage_tries == 5) {
+				DRM_DEBUG_KMS("too many voltage retries, give up\n");
 				break;
+			}
 		} else
-			tries = 0;
+			voltage_tries = 0;
 		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
 		/* Compute new intel_dp->train_set as requested by target */
-		intel_get_adjust_train(intel_dp);
+		intel_get_adjust_train(intel_dp, link_status);
 	}
 
 	intel_dp->DP = DP;
@@ -1443,6 +1785,7 @@ intel_dp_complete_link_train(struct inte
 	for (;;) {
 		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
 		uint32_t    signal_levels;
+		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 
 		if (cr_tries > 5) {
 			DRM_ERROR("failed to train DP, aborting\n");
@@ -1450,15 +1793,18 @@ intel_dp_complete_link_train(struct inte
 			break;
 		}
 
-		if (IS_GEN6(dev) && is_edp(intel_dp)) {
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
+			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
+		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
-			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 			reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
 		else
 			reg = DP | DP_LINK_TRAIN_PAT_2;
@@ -1470,17 +1816,17 @@ intel_dp_complete_link_train(struct inte
 			break;
 
 		udelay(400);
-		if (!intel_dp_get_link_status(intel_dp))
+		if (!intel_dp_get_link_status(intel_dp, link_status))
 			break;
 
 		/* Make sure clock is still ok */
-		if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+		if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			intel_dp_start_link_train(intel_dp);
 			cr_tries++;
 			continue;
 		}
 
-		if (intel_channel_eq_ok(intel_dp)) {
+		if (intel_channel_eq_ok(intel_dp, link_status)) {
 			channel_eq = true;
 			break;
 		}
@@ -1495,11 +1841,11 @@ intel_dp_complete_link_train(struct inte
 		}
 
 		/* Compute new intel_dp->train_set as requested by target */
-		intel_get_adjust_train(intel_dp);
+		intel_get_adjust_train(intel_dp, link_status);
 		++tries;
 	}
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 		reg = DP | DP_LINK_TRAIN_OFF_CPT;
 	else
 		reg = DP | DP_LINK_TRAIN_OFF;
@@ -1529,7 +1875,7 @@ intel_dp_link_down(struct intel_dp *inte
 		udelay(100);
 	}
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) {
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
 	} else {
@@ -1540,8 +1886,12 @@ intel_dp_link_down(struct intel_dp *inte
 
 	msleep(17);
 
-	if (is_edp(intel_dp))
-		DP |= DP_LINK_TRAIN_OFF;
+	if (is_edp(intel_dp)) {
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
+			DP |= DP_LINK_TRAIN_OFF_CPT;
+		else
+			DP |= DP_LINK_TRAIN_OFF;
+	}
 
 	if (!HAS_PCH_CPT(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
@@ -1578,13 +1928,14 @@ intel_dp_link_down(struct intel_dp *inte
 
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
 	POSTING_READ(intel_dp->output_reg);
+	msleep(intel_dp->panel_power_down_delay);
 }
 
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
 	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
-					   sizeof (intel_dp->dpcd)) &&
+					   sizeof(intel_dp->dpcd)) &&
 	    (intel_dp->dpcd[DP_DPCD_REV] != 0)) {
 		return true;
 	}
@@ -1592,6 +1943,27 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	return false;
 }
 
+static bool
+intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+{
+	int ret;
+
+	ret = intel_dp_aux_native_read_retry(intel_dp,
+					     DP_DEVICE_SERVICE_IRQ_VECTOR,
+					     sink_irq_vector, 1);
+	if (!ret)
+		return false;
+
+	return true;
+}
+
+static void
+intel_dp_handle_test_request(struct intel_dp *intel_dp)
+{
+	/* NAK by default */
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK);
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -1604,6 +1976,9 @@ intel_dp_get_dpcd(struct intel_dp *intel
 static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
+	u8 sink_irq_vector;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+
 	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
 		return;
 
@@ -1611,7 +1986,7 @@ intel_dp_check_link_status(struct intel_
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
-	if (!intel_dp_get_link_status(intel_dp)) {
+	if (!intel_dp_get_link_status(intel_dp, link_status)) {
 		intel_dp_link_down(intel_dp);
 		return;
 	}
@@ -1622,7 +1997,21 @@ intel_dp_check_link_status(struct intel_
 		return;
 	}
 
-	if (!intel_channel_eq_ok(intel_dp)) {
+	/* Try to read the source of the interrupt */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
+		/* Clear interrupt source */
+		intel_dp_aux_native_write_1(intel_dp,
+					    DP_DEVICE_SERVICE_IRQ_VECTOR,
+					    sink_irq_vector);
+
+		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
+			intel_dp_handle_test_request(intel_dp);
+		if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
+			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
+	}
+
+	if (!intel_channel_eq_ok(intel_dp, link_status)) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
 			      drm_get_encoder_name(&intel_dp->base.base));
 		intel_dp_start_link_train(intel_dp);
@@ -1683,6 +2072,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 	return intel_dp_detect_dpcd(intel_dp);
 }
 
+static struct edid *
+intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct edid	*edid;
+
+	ironlake_edp_panel_vdd_on(intel_dp);
+	edid = drm_get_edid(connector, adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return edid;
+}
+
+static int
+intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	int	ret;
+
+	ironlake_edp_panel_vdd_on(intel_dp);
+	ret = intel_ddc_get_modes(connector, adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return ret;
+}
+
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
  *
@@ -1715,7 +2129,7 @@ intel_dp_detect(struct drm_connector *co
 	if (intel_dp->force_audio) {
 		intel_dp->has_audio = intel_dp->force_audio > 0;
 	} else {
-		edid = drm_get_edid(connector, &intel_dp->adapter);
+		edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 		if (edid) {
 			intel_dp->has_audio = drm_detect_monitor_audio(edid);
 			connector->display_info.raw_edid = NULL;
@@ -1736,28 +2150,36 @@ static int intel_dp_get_modes(struct drm
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
-	ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
+	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
 	if (ret) {
-		if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) {
+		if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
 			struct drm_display_mode *newmode;
 			list_for_each_entry(newmode, &connector->probed_modes,
 					    head) {
-				if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
-					dev_priv->panel_fixed_mode =
+				if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) {
+					intel_dp->panel_fixed_mode =
 						drm_mode_duplicate(dev, newmode);
 					break;
 				}
 			}
 		}
-
 		return ret;
 	}
 
 	/* if eDP has no EDID, try to use fixed panel mode from VBT */
 	if (is_edp(intel_dp)) {
-		if (dev_priv->panel_fixed_mode != NULL) {
+		/* initialize panel mode from VBT if available for eDP */
+		if (intel_dp->panel_fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode != NULL) {
+			intel_dp->panel_fixed_mode =
+				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+			if (intel_dp->panel_fixed_mode) {
+				intel_dp->panel_fixed_mode->type |=
+					DRM_MODE_TYPE_PREFERRED;
+			}
+		}
+		if (intel_dp->panel_fixed_mode) {
 			struct drm_display_mode *mode;
-			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+			mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
 			drm_mode_probed_add(connector, mode);
 			return 1;
 		}
@@ -1772,7 +2194,7 @@ intel_dp_detect_audio(struct drm_connect
 	struct edid *edid;
 	bool has_audio = false;
 
-	edid = drm_get_edid(connector, &intel_dp->adapter);
+	edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 	if (edid) {
 		has_audio = drm_detect_monitor_audio(edid);
 
@@ -1839,7 +2261,7 @@ done:
 }
 
 static void
-intel_dp_destroy (struct drm_connector *connector)
+intel_dp_destroy(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 
@@ -1857,6 +2279,10 @@ static void intel_dp_encoder_destroy(str
 
 	i2c_del_adapter(&intel_dp->adapter);
 	drm_encoder_cleanup(encoder);
+	if (is_edp(intel_dp)) {
+		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+		ironlake_panel_vdd_off_sync(intel_dp);
+	}
 	kfree(intel_dp);
 }
 
@@ -1896,7 +2322,7 @@ intel_dp_hot_plug(struct intel_encoder *
 
 /* Return which DP Port should be selected for Transcoder DP control */
 int
-intel_trans_dp_port_sel (struct drm_crtc *crtc)
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *mode_config = &dev->mode_config;
@@ -1909,7 +2335,8 @@ intel_trans_dp_port_sel (struct drm_crtc
 			continue;
 
 		intel_dp = enc_to_intel_dp(encoder);
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_dp->base.type == INTEL_OUTPUT_EDP)
 			return intel_dp->output_reg;
 	}
 
@@ -1993,10 +2420,13 @@ intel_dp_init(struct drm_device *dev, in
 	else if (output_reg == DP_D || output_reg == PCH_DP_D)
 		intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-	if (is_edp(intel_dp))
+	if (is_edp(intel_dp)) {
 		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+		INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+				  ironlake_panel_vdd_work);
+	}
 
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
@@ -2032,25 +2462,59 @@ intel_dp_init(struct drm_device *dev, in
 			break;
 	}
 
-	intel_dp_i2c_init(intel_dp, intel_connector, name);
-
 	/* Cache some DPCD data in the eDP case */
 	if (is_edp(intel_dp)) {
 		bool ret;
-		u32 pp_on, pp_div;
+		struct edp_power_seq	cur, vbt;
+		u32 pp_on, pp_off, pp_div;
 
 		pp_on = I915_READ(PCH_PP_ON_DELAYS);
+		pp_off = I915_READ(PCH_PP_OFF_DELAYS);
 		pp_div = I915_READ(PCH_PP_DIVISOR);
 
-		/* Get T3 & T12 values (note: VESA not bspec terminology) */
-		dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16;
-		dev_priv->panel_t3 /= 10; /* t3 in 100us units */
-		dev_priv->panel_t12 = pp_div & 0xf;
-		dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
+		/* Pull timing values out of registers */
+		cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+			PANEL_POWER_UP_DELAY_SHIFT;
+
+		cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+			PANEL_LIGHT_ON_DELAY_SHIFT;
+
+		cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+			PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+		cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+			PANEL_POWER_DOWN_DELAY_SHIFT;
+
+		cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+			       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+
+		DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+			      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+		vbt = dev_priv->edp.pps;
+
+		DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+			      vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
+
+#define get_delay(field)	((max(cur.field, vbt.field) + 9) / 10)
+
+		intel_dp->panel_power_up_delay = get_delay(t1_t3);
+		intel_dp->backlight_on_delay = get_delay(t8);
+		intel_dp->backlight_off_delay = get_delay(t9);
+		intel_dp->panel_power_down_delay = get_delay(t10);
+		intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+
+		DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+			      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+			      intel_dp->panel_power_cycle_delay);
+
+		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
 
 		ironlake_edp_panel_vdd_on(intel_dp);
 		ret = intel_dp_get_dpcd(intel_dp);
-		ironlake_edp_panel_vdd_off(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+
 		if (ret) {
 			if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
 				dev_priv->no_aux_handshake =
@@ -2065,18 +2529,11 @@ intel_dp_init(struct drm_device *dev, in
 		}
 	}
 
+	intel_dp_i2c_init(intel_dp, intel_connector, name);
+
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
 	if (is_edp(intel_dp)) {
-		/* initialize panel mode from VBT if available for eDP */
-		if (dev_priv->lfp_lvds_vbt_mode) {
-			dev_priv->panel_fixed_mode =
-				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
-			if (dev_priv->panel_fixed_mode) {
-				dev_priv->panel_fixed_mode->type |=
-					DRM_MODE_TYPE_PREFERRED;
-			}
-		}
 		dev_priv->int_edp_connector = connector;
 		intel_panel_setup_backlight(dev);
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_drv.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #define _wait_for(COND, MS, W) ({ \
 	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
 	int ret__ = 0;							\
-	while (! (COND)) {						\
+	while (!(COND)) {						\
 		if (time_after(jiffies, timeout__)) {			\
 			ret__ = -ETIMEDOUT;				\
 			break;						\
@@ -49,10 +49,10 @@
 
 #define MSLEEP(x) do { \
 	if (in_dbg_master()) \
-	       	mdelay(x); \
+		mdelay(x); \
 	else \
 		msleep(x); \
-} while(0)
+} while (0)
 
 #define KHz(x) (1000*x)
 #define MHz(x) KHz(1000*x)
@@ -110,6 +110,7 @@
 /* drm_display_mode->private_flags */
 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
+#define INTEL_MODE_DP_FORCE_6BPC (0x10)
 
 static inline void
 intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@@ -171,6 +172,9 @@ struct intel_crtc {
 	int16_t cursor_width, cursor_height;
 	bool cursor_visible;
 	unsigned int bpp;
+
+	bool no_pll; /* tertiary pipe for IVB */
+	bool use_pll_a;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -184,7 +188,7 @@ struct intel_crtc {
 #define DIP_VERSION_AVI 0x2
 #define DIP_LEN_AVI     13
 
-#define DIP_TYPE_SPD	0x3
+#define DIP_TYPE_SPD	0x83
 #define DIP_VERSION_SPD	0x1
 #define DIP_LEN_SPD	25
 #define DIP_SPD_UNKNOWN	0
@@ -284,7 +288,7 @@ void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
-extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
+extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 
 /* intel_panel.c */
@@ -304,8 +308,8 @@ extern void intel_panel_destroy_backligh
 extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void intel_encoder_prepare (struct drm_encoder *encoder);
-extern void intel_encoder_commit (struct drm_encoder *encoder);
+extern void intel_encoder_prepare(struct drm_encoder *encoder);
+extern void intel_encoder_commit(struct drm_encoder *encoder);
 extern void intel_encoder_destroy(struct drm_encoder *encoder);
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
@@ -377,4 +381,8 @@ extern void intel_fb_output_poll_changed
 extern void intel_fb_restore_mode(struct drm_device *dev);
 
 extern void intel_init_clock_gating(struct drm_device *dev);
+extern void intel_write_eld(struct drm_encoder *encoder,
+			    struct drm_display_mode *mode);
+extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
+
 #endif /* __INTEL_DRV_H__ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_hdmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_hdmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip
 	frame->checksum = 0;
 	frame->ecc = 0;
 
-	/* Header isn't part of the checksum */
-	for (i = 5; i < frame->len; i++)
+	for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
 		sum += data[i];
 
 	frame->checksum = 0x100 - sum;
@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct
 		flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
 		break;
 	case DIP_TYPE_SPD:
-		flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
+		flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
 		break;
 	default:
 		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(str
 
 	flags = intel_infoframe_index(frame);
 
-	val &= ~VIDEO_DIP_SELECT_MASK;
+	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
 
-	I915_WRITE(reg, val | flags);
+	I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
 
 	for (i = 0; i < len; i += 4) {
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
@@ -245,16 +244,17 @@ static void intel_hdmi_mode_set(struct d
 		sdvox |= HDMI_MODE_SELECT;
 
 	if (intel_hdmi->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
+				 pipe_name(intel_crtc->pipe));
 		sdvox |= SDVO_AUDIO_ENABLE;
 		sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
+		intel_write_eld(encoder, adjusted_mode);
 	}
 
-	if (intel_crtc->pipe == 1) {
-		if (HAS_PCH_CPT(dev))
-			sdvox |= PORT_TRANS_B_SEL_CPT;
-		else
-			sdvox |= SDVO_PIPE_B_SELECT;
-	}
+	if (HAS_PCH_CPT(dev))
+		sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+	else if (intel_crtc->pipe == 1)
+		sdvox |= SDVO_PIPE_B_SELECT;
 
 	I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
 	POSTING_READ(intel_hdmi->sdvox_reg);
@@ -486,6 +486,7 @@ void intel_hdmi_init(struct drm_device *
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
 	struct intel_hdmi *intel_hdmi;
+	int i;
 
 	intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
 	if (!intel_hdmi)
@@ -511,7 +512,7 @@ void intel_hdmi_init(struct drm_device *
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
 	/* Set up the DDC bus. */
 	if (sdvox_reg == SDVOB) {
@@ -538,10 +539,14 @@ void intel_hdmi_init(struct drm_device *
 
 	intel_hdmi->sdvox_reg = sdvox_reg;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (!HAS_PCH_SPLIT(dev)) {
 		intel_hdmi->write_infoframe = i9xx_write_infoframe;
-	else
+		I915_WRITE(VIDEO_DIP_CTL, 0);
+	} else {
 		intel_hdmi->write_infoframe = ironlake_write_infoframe;
+		for_each_pipe(i)
+			I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+	}
 
 	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_i2c.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  */
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "intel_drv.h"
@@ -422,13 +423,7 @@ void intel_gmbus_set_speed(struct i2c_ad
 {
 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
 
-	/* speed:
-	 * 0x0 = 100 KHz
-	 * 0x1 = 50 KHz
-	 * 0x2 = 400 KHz
-	 * 0x3 = 1000 Khz
-	 */
-	bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
+	bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed;
 }
 
 void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2012-01-04 18:55:44.000000000 -0500
@@ -715,6 +715,14 @@ static const struct dmi_system_id intel_
 			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Asus AT5NM10T-I",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
@@ -888,9 +896,11 @@ bool intel_lvds_init(struct drm_device *
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
 	intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
-	intel_encoder->crtc_mask = (1 << 1);
-	if (INTEL_INFO(dev)->gen >= 5)
-		intel_encoder->crtc_mask |= (1 << 0);
+	if (HAS_PCH_SPLIT(dev))
+		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+	else
+		intel_encoder->crtc_mask = (1 << 1);
+
 	drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
 	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_modes.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_modes.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_modes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_modes.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/fb.h>
+#include <drm/drm_edid.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drv.h"
@@ -74,6 +75,7 @@ int intel_ddc_get_modes(struct drm_conne
 	if (edid) {
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
+		drm_edid_to_eld(connector, edid);
 		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_opregion.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_opregion.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_opregion.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,61 +51,61 @@
 #define MBOX_ASLE      (1<<2)
 
 struct opregion_header {
-       u8 signature[16];
-       u32 size;
-       u32 opregion_ver;
-       u8 bios_ver[32];
-       u8 vbios_ver[16];
-       u8 driver_ver[16];
-       u32 mboxes;
-       u8 reserved[164];
+	u8 signature[16];
+	u32 size;
+	u32 opregion_ver;
+	u8 bios_ver[32];
+	u8 vbios_ver[16];
+	u8 driver_ver[16];
+	u32 mboxes;
+	u8 reserved[164];
 } __attribute__((packed));
 
 /* OpRegion mailbox #1: public ACPI methods */
 struct opregion_acpi {
-       u32 drdy;       /* driver readiness */
-       u32 csts;       /* notification status */
-       u32 cevt;       /* current event */
-       u8 rsvd1[20];
-       u32 didl[8];    /* supported display devices ID list */
-       u32 cpdl[8];    /* currently presented display list */
-       u32 cadl[8];    /* currently active display list */
-       u32 nadl[8];    /* next active devices list */
-       u32 aslp;       /* ASL sleep time-out */
-       u32 tidx;       /* toggle table index */
-       u32 chpd;       /* current hotplug enable indicator */
-       u32 clid;       /* current lid state*/
-       u32 cdck;       /* current docking state */
-       u32 sxsw;       /* Sx state resume */
-       u32 evts;       /* ASL supported events */
-       u32 cnot;       /* current OS notification */
-       u32 nrdy;       /* driver status */
-       u8 rsvd2[60];
+	u32 drdy;       /* driver readiness */
+	u32 csts;       /* notification status */
+	u32 cevt;       /* current event */
+	u8 rsvd1[20];
+	u32 didl[8];    /* supported display devices ID list */
+	u32 cpdl[8];    /* currently presented display list */
+	u32 cadl[8];    /* currently active display list */
+	u32 nadl[8];    /* next active devices list */
+	u32 aslp;       /* ASL sleep time-out */
+	u32 tidx;       /* toggle table index */
+	u32 chpd;       /* current hotplug enable indicator */
+	u32 clid;       /* current lid state*/
+	u32 cdck;       /* current docking state */
+	u32 sxsw;       /* Sx state resume */
+	u32 evts;       /* ASL supported events */
+	u32 cnot;       /* current OS notification */
+	u32 nrdy;       /* driver status */
+	u8 rsvd2[60];
 } __attribute__((packed));
 
 /* OpRegion mailbox #2: SWSCI */
 struct opregion_swsci {
-       u32 scic;       /* SWSCI command|status|data */
-       u32 parm;       /* command parameters */
-       u32 dslp;       /* driver sleep time-out */
-       u8 rsvd[244];
+	u32 scic;       /* SWSCI command|status|data */
+	u32 parm;       /* command parameters */
+	u32 dslp;       /* driver sleep time-out */
+	u8 rsvd[244];
 } __attribute__((packed));
 
 /* OpRegion mailbox #3: ASLE */
 struct opregion_asle {
-       u32 ardy;       /* driver readiness */
-       u32 aslc;       /* ASLE interrupt command */
-       u32 tche;       /* technology enabled indicator */
-       u32 alsi;       /* current ALS illuminance reading */
-       u32 bclp;       /* backlight brightness to set */
-       u32 pfit;       /* panel fitting state */
-       u32 cblv;       /* current brightness level */
-       u16 bclm[20];   /* backlight level duty cycle mapping table */
-       u32 cpfm;       /* current panel fitting mode */
-       u32 epfm;       /* enabled panel fitting modes */
-       u8 plut[74];    /* panel LUT and identifier */
-       u32 pfmb;       /* PWM freq and min brightness */
-       u8 rsvd[102];
+	u32 ardy;       /* driver readiness */
+	u32 aslc;       /* ASLE interrupt command */
+	u32 tche;       /* technology enabled indicator */
+	u32 alsi;       /* current ALS illuminance reading */
+	u32 bclp;       /* backlight brightness to set */
+	u32 pfit;       /* panel fitting state */
+	u32 cblv;       /* current brightness level */
+	u16 bclm[20];   /* backlight level duty cycle mapping table */
+	u32 cpfm;       /* current panel fitting mode */
+	u32 epfm;       /* enabled panel fitting modes */
+	u8 plut[74];    /* panel LUT and identifier */
+	u32 pfmb;       /* PWM freq and min brightness */
+	u8 rsvd[102];
 } __attribute__((packed));
 
 /* ASLE irq request bits */
@@ -361,7 +361,7 @@ static void intel_didl_outputs(struct dr
 
 	list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
 		if (i >= 8) {
-			dev_printk (KERN_ERR, &dev->pdev->dev,
+			dev_printk(KERN_ERR, &dev->pdev->dev,
 				    "More than 8 outputs detected\n");
 			return;
 		}
@@ -387,7 +387,7 @@ blind_set:
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		int output_type = ACPI_OTHER_OUTPUT;
 		if (i >= 8) {
-			dev_printk (KERN_ERR, &dev->pdev->dev,
+			dev_printk(KERN_ERR, &dev->pdev->dev,
 				    "More than 8 outputs detected\n");
 			return;
 		}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_overlay.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_overlay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_overlay.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,57 +117,57 @@
 
 /* memory bufferd overlay registers */
 struct overlay_registers {
-    u32 OBUF_0Y;
-    u32 OBUF_1Y;
-    u32 OBUF_0U;
-    u32 OBUF_0V;
-    u32 OBUF_1U;
-    u32 OBUF_1V;
-    u32 OSTRIDE;
-    u32 YRGB_VPH;
-    u32 UV_VPH;
-    u32 HORZ_PH;
-    u32 INIT_PHS;
-    u32 DWINPOS;
-    u32 DWINSZ;
-    u32 SWIDTH;
-    u32 SWIDTHSW;
-    u32 SHEIGHT;
-    u32 YRGBSCALE;
-    u32 UVSCALE;
-    u32 OCLRC0;
-    u32 OCLRC1;
-    u32 DCLRKV;
-    u32 DCLRKM;
-    u32 SCLRKVH;
-    u32 SCLRKVL;
-    u32 SCLRKEN;
-    u32 OCONFIG;
-    u32 OCMD;
-    u32 RESERVED1; /* 0x6C */
-    u32 OSTART_0Y;
-    u32 OSTART_1Y;
-    u32 OSTART_0U;
-    u32 OSTART_0V;
-    u32 OSTART_1U;
-    u32 OSTART_1V;
-    u32 OTILEOFF_0Y;
-    u32 OTILEOFF_1Y;
-    u32 OTILEOFF_0U;
-    u32 OTILEOFF_0V;
-    u32 OTILEOFF_1U;
-    u32 OTILEOFF_1V;
-    u32 FASTHSCALE; /* 0xA0 */
-    u32 UVSCALEV; /* 0xA4 */
-    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
-    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
-    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
-    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
-    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
-    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
-    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
-    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
-    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+	u32 OBUF_0Y;
+	u32 OBUF_1Y;
+	u32 OBUF_0U;
+	u32 OBUF_0V;
+	u32 OBUF_1U;
+	u32 OBUF_1V;
+	u32 OSTRIDE;
+	u32 YRGB_VPH;
+	u32 UV_VPH;
+	u32 HORZ_PH;
+	u32 INIT_PHS;
+	u32 DWINPOS;
+	u32 DWINSZ;
+	u32 SWIDTH;
+	u32 SWIDTHSW;
+	u32 SHEIGHT;
+	u32 YRGBSCALE;
+	u32 UVSCALE;
+	u32 OCLRC0;
+	u32 OCLRC1;
+	u32 DCLRKV;
+	u32 DCLRKM;
+	u32 SCLRKVH;
+	u32 SCLRKVL;
+	u32 SCLRKEN;
+	u32 OCONFIG;
+	u32 OCMD;
+	u32 RESERVED1; /* 0x6C */
+	u32 OSTART_0Y;
+	u32 OSTART_1Y;
+	u32 OSTART_0U;
+	u32 OSTART_0V;
+	u32 OSTART_1U;
+	u32 OSTART_1V;
+	u32 OTILEOFF_0Y;
+	u32 OTILEOFF_1Y;
+	u32 OTILEOFF_0U;
+	u32 OTILEOFF_0V;
+	u32 OTILEOFF_1U;
+	u32 OTILEOFF_1V;
+	u32 FASTHSCALE; /* 0xA0 */
+	u32 UVSCALEV; /* 0xA4 */
+	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
+	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
+	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
+	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
+	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
+	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 };
 
 struct intel_overlay {
@@ -192,7 +192,7 @@ struct intel_overlay {
 static struct overlay_registers *
 intel_overlay_map_regs(struct intel_overlay *overlay)
 {
-        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
+	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
 	struct overlay_registers *regs;
 
 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@@ -264,7 +264,7 @@ i830_activate_pipe_a(struct drm_device *
 
 	mode = drm_mode_duplicate(dev, &vesa_640x480);
 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-	if(!drm_crtc_helper_set_mode(&crtc->base, mode,
+	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
 				       crtc->base.x, crtc->base.y,
 				       crtc->base.fb))
 		return 0;
@@ -332,7 +332,7 @@ static int intel_overlay_continue(struct
 				  bool load_polyphase_filter)
 {
 	struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_request *request;
 	u32 flip_addr = overlay->flip_addr;
 	u32 tmp;
@@ -359,7 +359,7 @@ static int intel_overlay_continue(struct
 	}
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
-        ADVANCE_LP_RING();
+	ADVANCE_LP_RING();
 
 	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
@@ -583,7 +583,7 @@ static u32 calc_swidthsw(struct drm_devi
 	ret = ((offset + width + mask) >> shift) - (offset >> shift);
 	if (!IS_GEN2(dev))
 		ret <<= 1;
-	ret -=1;
+	ret -= 1;
 	return ret << 2;
 }
 
@@ -817,7 +817,7 @@ static int intel_overlay_do_put_image(st
 	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
 				       params->offset_Y, tmp_width);
 	regs->SHEIGHT = params->src_h;
-	regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
+	regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
 	regs->OSTRIDE = params->stride_Y;
 
 	if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -917,7 +917,7 @@ static void update_pfit_vscale_ratio(str
 	 * line with the intel documentation for the i965
 	 */
 	if (INTEL_INFO(dev)->gen >= 4) {
-	       	/* on i965 use the PGM reg to read out the autoscaler values */
+		/* on i965 use the PGM reg to read out the autoscaler values */
 		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
 	} else {
 		if (pfit_control & VERT_AUTO_SCALE)
@@ -1098,7 +1098,7 @@ static int intel_panel_fitter_pipe(struc
 }
 
 int intel_overlay_put_image(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv)
+			    struct drm_file *file_priv)
 {
 	struct drm_intel_overlay_put_image *put_image_rec = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -1301,10 +1301,10 @@ static int check_gamma(struct drm_intel_
 }
 
 int intel_overlay_attrs(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
+			struct drm_file *file_priv)
 {
 	struct drm_intel_overlay_attrs *attrs = data;
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
 	struct overlay_registers *regs;
 	int ret;
@@ -1393,7 +1393,7 @@ out_unlock:
 
 void intel_setup_overlay(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
 	struct drm_i915_gem_object *reg_bo;
 	struct overlay_registers *regs;
@@ -1421,24 +1421,24 @@ void intel_setup_overlay(struct drm_devi
 		ret = i915_gem_attach_phys_object(dev, reg_bo,
 						  I915_GEM_PHYS_OVERLAY_REGS,
 						  PAGE_SIZE);
-                if (ret) {
-                        DRM_ERROR("failed to attach phys overlay regs\n");
-                        goto out_free_bo;
-                }
+		if (ret) {
+			DRM_ERROR("failed to attach phys overlay regs\n");
+			goto out_free_bo;
+		}
 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
 		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
 		if (ret) {
-                        DRM_ERROR("failed to pin overlay register bo\n");
-                        goto out_free_bo;
-                }
+			DRM_ERROR("failed to pin overlay register bo\n");
+			goto out_free_bo;
+		}
 		overlay->flip_addr = reg_bo->gtt_offset;
 
 		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
 		if (ret) {
-                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
-                        goto out_unpin_bo;
-                }
+			DRM_ERROR("failed to move overlay register bo into the GTT\n");
+			goto out_unpin_bo;
+		}
 	}
 
 	/* init all values */
@@ -1525,7 +1525,7 @@ static void intel_overlay_unmap_regs_ato
 struct intel_overlay_error_state *
 intel_overlay_capture_error_state(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay = dev_priv->overlay;
 	struct intel_overlay_error_state *error;
 	struct overlay_registers __iomem *regs;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_panel.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_panel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_panel.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@ intel_pch_panel_fitting(struct drm_devic
 			if (scaled_width > scaled_height) { /* pillar */
 				width = scaled_height / mode->vdisplay;
 				if (width & 1)
-				    	width++;
+					width++;
 				x = (adjusted_mode->hdisplay - width + 1) / 2;
 				y = 0;
 				height = adjusted_mode->vdisplay;
@@ -178,13 +178,10 @@ u32 intel_panel_get_max_backlight(struct
 	if (HAS_PCH_SPLIT(dev)) {
 		max >>= 16;
 	} else {
-		if (IS_PINEVIEW(dev)) {
+		if (INTEL_INFO(dev)->gen < 4)
 			max >>= 17;
-		} else {
+		else
 			max >>= 16;
-			if (INTEL_INFO(dev)->gen < 4)
-				max &= ~1;
-		}
 
 		if (is_backlight_combination_mode(dev))
 			max *= 0xff;
@@ -203,13 +200,12 @@ u32 intel_panel_get_backlight(struct drm
 		val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 	} else {
 		val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-		if (IS_PINEVIEW(dev))
+		if (INTEL_INFO(dev)->gen < 4)
 			val >>= 1;
 
-		if (is_backlight_combination_mode(dev)){
+		if (is_backlight_combination_mode(dev)) {
 			u8 lbpc;
 
-			val &= ~1;
 			pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
 			val *= lbpc;
 		}
@@ -226,7 +222,7 @@ static void intel_pch_panel_set_backligh
 	I915_WRITE(BLC_PWM_CPU_CTL, val | level);
 }
 
-void intel_panel_set_backlight(struct drm_device *dev, u32 level)
+static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 tmp;
@@ -236,7 +232,7 @@ void intel_panel_set_backlight(struct dr
 	if (HAS_PCH_SPLIT(dev))
 		return intel_pch_panel_set_backlight(dev, level);
 
-	if (is_backlight_combination_mode(dev)){
+	if (is_backlight_combination_mode(dev)) {
 		u32 max = intel_panel_get_max_backlight(dev);
 		u8 lbpc;
 
@@ -246,24 +242,27 @@ void intel_panel_set_backlight(struct dr
 	}
 
 	tmp = I915_READ(BLC_PWM_CTL);
-	if (IS_PINEVIEW(dev)) {
-		tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
+	if (INTEL_INFO(dev)->gen < 4) 
 		level <<= 1;
-	} else
-		tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+	tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
 	I915_WRITE(BLC_PWM_CTL, tmp | level);
 }
 
-void intel_panel_disable_backlight(struct drm_device *dev)
+void intel_panel_set_backlight(struct drm_device *dev, u32 level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->backlight_enabled) {
-		dev_priv->backlight_level = intel_panel_get_backlight(dev);
-		dev_priv->backlight_enabled = false;
-	}
+	dev_priv->backlight_level = level;
+	if (dev_priv->backlight_enabled)
+		intel_panel_actually_set_backlight(dev, level);
+}
 
-	intel_panel_set_backlight(dev, 0);
+void intel_panel_disable_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->backlight_enabled = false;
+	intel_panel_actually_set_backlight(dev, 0);
 }
 
 void intel_panel_enable_backlight(struct drm_device *dev)
@@ -273,8 +272,8 @@ void intel_panel_enable_backlight(struct
 	if (dev_priv->backlight_level == 0)
 		dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
 
-	intel_panel_set_backlight(dev, dev_priv->backlight_level);
 	dev_priv->backlight_enabled = true;
+	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
 }
 
 static void intel_panel_init_backlight(struct drm_device *dev)
@@ -321,7 +320,8 @@ static int intel_panel_update_status(str
 static int intel_panel_get_brightness(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
-	return intel_panel_get_backlight(dev);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	return dev_priv->backlight_level;
 }
 
 static const struct backlight_ops intel_panel_bl_ops = {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,16 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+/*
+ * 965+ support PIPE_CONTROL commands, which provide finer grained control
+ * over cache flushing.
+ */
+struct pipe_control {
+	struct drm_i915_gem_object *obj;
+	volatile u32 *cpu_page;
+	u32 gtt_offset;
+};
+
 static inline int ring_space(struct intel_ring_buffer *ring)
 {
 	int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
@@ -123,6 +133,118 @@ render_ring_flush(struct intel_ring_buff
 	return 0;
 }
 
+/**
+ * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
+ * implementing two workarounds on gen6.  From section 1.4.7.1
+ * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
+ *
+ * [DevSNB-C+{W/A}] Before any depth stall flush (including those
+ * produced by non-pipelined state commands), software needs to first
+ * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
+ * 0.
+ *
+ * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
+ * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
+ *
+ * And the workaround for these two requires this workaround first:
+ *
+ * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
+ * BEFORE the pipe-control with a post-sync op and no write-cache
+ * flushes.
+ *
+ * And this last workaround is tricky because of the requirements on
+ * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
+ * volume 2 part 1:
+ *
+ *     "1 of the following must also be set:
+ *      - Render Target Cache Flush Enable ([12] of DW1)
+ *      - Depth Cache Flush Enable ([0] of DW1)
+ *      - Stall at Pixel Scoreboard ([1] of DW1)
+ *      - Depth Stall ([13] of DW1)
+ *      - Post-Sync Operation ([13] of DW1)
+ *      - Notify Enable ([8] of DW1)"
+ *
+ * The cache flushes require the workaround flush that triggered this
+ * one, so we can't use it.  Depth stall would trigger the same.
+ * Post-sync nonzero is what triggered this second workaround, so we
+ * can't use that one either.  Notify enable is IRQs, which aren't
+ * really our business.  That leaves only stall at scoreboard.
+ */
+static int
+intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
+{
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
+
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+			PIPE_CONTROL_STALL_AT_SCOREBOARD);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(ring, 0); /* low dword */
+	intel_ring_emit(ring, 0); /* high dword */
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int
+gen6_render_ring_flush(struct intel_ring_buffer *ring,
+                         u32 invalidate_domains, u32 flush_domains)
+{
+	u32 flags = 0;
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
+
+	/* Force SNB workarounds for PIPE_CONTROL flushes */
+	intel_emit_post_sync_nonzero_flush(ring);
+
+	/* Just flush everything.  Experiments have shown that reducing the
+	 * number of bits based on the write domains has little performance
+	 * impact.
+	 */
+	flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+	flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+	flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, flags);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(ring, 0); /* lower dword */
+	intel_ring_emit(ring, 0); /* uppwer dword */
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
 static void ring_write_tail(struct intel_ring_buffer *ring,
 			    u32 value)
 {
@@ -206,16 +328,6 @@ static int init_ring_common(struct intel
 	return 0;
 }
 
-/*
- * 965+ support PIPE_CONTROL commands, which provide finer grained control
- * over cache flushing.
- */
-struct pipe_control {
-	struct drm_i915_gem_object *obj;
-	volatile u32 *cpu_page;
-	u32 gtt_offset;
-};
-
 static int
 init_pipe_control(struct intel_ring_buffer *ring)
 {
@@ -296,8 +408,7 @@ static int init_render_ring(struct intel
 				   GFX_MODE_ENABLE(GFX_REPLAY_MODE));
 	}
 
-	if (INTEL_INFO(dev)->gen >= 6) {
-	} else if (IS_GEN5(dev)) {
+	if (INTEL_INFO(dev)->gen >= 5) {
 		ret = init_pipe_control(ring);
 		if (ret)
 			return ret;
@@ -315,83 +426,131 @@ static void render_ring_cleanup(struct i
 }
 
 static void
-update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)
+update_mboxes(struct intel_ring_buffer *ring,
+	    u32 seqno,
+	    u32 mmio_offset)
 {
-	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int id;
-
-	/*
-	 * cs -> 1 = vcs, 0 = bcs
-	 * vcs -> 1 = bcs, 0 = cs,
-	 * bcs -> 1 = cs, 0 = vcs.
-	 */
-	id = ring - dev_priv->ring;
-	id += 2 - i;
-	id %= 3;
-
-	intel_ring_emit(ring,
-			MI_SEMAPHORE_MBOX |
-			MI_SEMAPHORE_REGISTER |
-			MI_SEMAPHORE_UPDATE);
+	intel_ring_emit(ring, MI_SEMAPHORE_MBOX |
+			      MI_SEMAPHORE_GLOBAL_GTT |
+			      MI_SEMAPHORE_REGISTER |
+			      MI_SEMAPHORE_UPDATE);
 	intel_ring_emit(ring, seqno);
-	intel_ring_emit(ring,
-			RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);
+	intel_ring_emit(ring, mmio_offset);
 }
 
+/**
+ * gen6_add_request - Update the semaphore mailbox registers
+ * 
+ * @ring - ring that is adding a request
+ * @seqno - return seqno stuck into the ring
+ *
+ * Update the mailbox registers in the *other* rings with the current seqno.
+ * This acts like a signal in the canonical semaphore.
+ */
 static int
 gen6_add_request(struct intel_ring_buffer *ring,
-		 u32 *result)
+		 u32 *seqno)
 {
-	u32 seqno;
+	u32 mbox1_reg;
+	u32 mbox2_reg;
 	int ret;
 
 	ret = intel_ring_begin(ring, 10);
 	if (ret)
 		return ret;
 
-	seqno = i915_gem_get_seqno(ring->dev);
-	update_semaphore(ring, 0, seqno);
-	update_semaphore(ring, 1, seqno);
+	mbox1_reg = ring->signal_mbox[0];
+	mbox2_reg = ring->signal_mbox[1];
 
+	*seqno = i915_gem_get_seqno(ring->dev);
+
+	update_mboxes(ring, *seqno, mbox1_reg);
+	update_mboxes(ring, *seqno, mbox2_reg);
 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(ring, seqno);
+	intel_ring_emit(ring, *seqno);
 	intel_ring_emit(ring, MI_USER_INTERRUPT);
 	intel_ring_advance(ring);
 
-	*result = seqno;
 	return 0;
 }
 
-int
-intel_ring_sync(struct intel_ring_buffer *ring,
-		struct intel_ring_buffer *to,
+/**
+ * intel_ring_sync - sync the waiter to the signaller on seqno
+ *
+ * @waiter - ring that is waiting
+ * @signaller - ring which has, or will signal
+ * @seqno - seqno which the waiter will block on
+ */
+static int
+intel_ring_sync(struct intel_ring_buffer *waiter,
+		struct intel_ring_buffer *signaller,
+		int ring,
 		u32 seqno)
 {
 	int ret;
+	u32 dw1 = MI_SEMAPHORE_MBOX |
+		  MI_SEMAPHORE_COMPARE |
+		  MI_SEMAPHORE_REGISTER;
 
-	ret = intel_ring_begin(ring, 4);
+	ret = intel_ring_begin(waiter, 4);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring,
-			MI_SEMAPHORE_MBOX |
-			MI_SEMAPHORE_REGISTER |
-			intel_ring_sync_index(ring, to) << 17 |
-			MI_SEMAPHORE_COMPARE);
-	intel_ring_emit(ring, seqno);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
+	intel_ring_emit(waiter, seqno);
+	intel_ring_emit(waiter, 0);
+	intel_ring_emit(waiter, MI_NOOP);
+	intel_ring_advance(waiter);
 
 	return 0;
 }
 
+/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
+int
+render_ring_sync_to(struct intel_ring_buffer *waiter,
+		    struct intel_ring_buffer *signaller,
+		    u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       RCS,
+			       seqno);
+}
+
+/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
+int
+gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
+		      struct intel_ring_buffer *signaller,
+		      u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       VCS,
+			       seqno);
+}
+
+/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
+int
+gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
+		      struct intel_ring_buffer *signaller,
+		      u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       BCS,
+			       seqno);
+}
+
+
+
 #define PIPE_CONTROL_FLUSH(ring__, addr__)					\
 do {									\
-	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
-		 PIPE_CONTROL_DEPTH_STALL | 2);				\
+	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |		\
+		 PIPE_CONTROL_DEPTH_STALL);				\
 	intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT);			\
 	intel_ring_emit(ring__, 0);							\
 	intel_ring_emit(ring__, 0);							\
@@ -419,8 +578,9 @@ pc_render_add_request(struct intel_ring_
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+			PIPE_CONTROL_WRITE_FLUSH |
+			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
 	intel_ring_emit(ring, seqno);
 	intel_ring_emit(ring, 0);
@@ -435,8 +595,9 @@ pc_render_add_request(struct intel_ring_
 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
 	scratch_addr += 128;
 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+			PIPE_CONTROL_WRITE_FLUSH |
+			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
 			PIPE_CONTROL_NOTIFY);
 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
 	intel_ring_emit(ring, seqno);
@@ -1026,7 +1187,12 @@ static const struct intel_ring_buffer re
 	.irq_get		= render_ring_get_irq,
 	.irq_put		= render_ring_put_irq,
 	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
-       .cleanup			= render_ring_cleanup,
+	.cleanup		= render_ring_cleanup,
+	.sync_to		= render_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_INVALID,
+				   MI_SEMAPHORE_SYNC_RV,
+				   MI_SEMAPHORE_SYNC_RB},
+	.signal_mbox		= {GEN6_VRSYNC, GEN6_BRSYNC},
 };
 
 /* ring buffer for bit-stream decoder */
@@ -1050,23 +1216,23 @@ static const struct intel_ring_buffer bs
 static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
 				     u32 value)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 
        /* Every tail move must follow the sequence below */
-       I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
-       I915_WRITE(GEN6_BSD_RNCID, 0x0);
+	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
+	I915_WRITE(GEN6_BSD_RNCID, 0x0);
 
-       if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
-                               GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
-                       50))
-               DRM_ERROR("timed out waiting for IDLE Indicator\n");
+	if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
+		GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
+		50))
+	DRM_ERROR("timed out waiting for IDLE Indicator\n");
 
-       I915_WRITE_TAIL(ring, value);
-       I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
+	I915_WRITE_TAIL(ring, value);
+	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
 }
 
 static int gen6_ring_flush(struct intel_ring_buffer *ring,
@@ -1094,18 +1260,18 @@ static int
 gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 			      u32 offset, u32 len)
 {
-       int ret;
+	int ret;
 
-       ret = intel_ring_begin(ring, 2);
-       if (ret)
-	       return ret;
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
 
-       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
-       /* bit0-7 is the length on GEN6+ */
-       intel_ring_emit(ring, offset);
-       intel_ring_advance(ring);
+	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+	/* bit0-7 is the length on GEN6+ */
+	intel_ring_emit(ring, offset);
+	intel_ring_advance(ring);
 
-       return 0;
+	return 0;
 }
 
 static bool
@@ -1154,6 +1320,11 @@ static const struct intel_ring_buffer ge
 	.irq_get		= gen6_bsd_ring_get_irq,
 	.irq_put		= gen6_bsd_ring_put_irq,
 	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
+	.sync_to		= gen6_bsd_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_VR,
+				   MI_SEMAPHORE_SYNC_INVALID,
+				   MI_SEMAPHORE_SYNC_VB},
+	.signal_mbox		= {GEN6_RVSYNC, GEN6_BVSYNC},
 };
 
 /* Blitter support (SandyBridge+) */
@@ -1272,19 +1443,24 @@ static void blt_ring_cleanup(struct inte
 }
 
 static const struct intel_ring_buffer gen6_blt_ring = {
-       .name			= "blt ring",
-       .id			= RING_BLT,
-       .mmio_base		= BLT_RING_BASE,
-       .size			= 32 * PAGE_SIZE,
-       .init			= blt_ring_init,
-       .write_tail		= ring_write_tail,
-       .flush			= blt_ring_flush,
-       .add_request		= gen6_add_request,
-       .get_seqno		= ring_get_seqno,
-       .irq_get			= blt_ring_get_irq,
-       .irq_put			= blt_ring_put_irq,
-       .dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
-       .cleanup			= blt_ring_cleanup,
+	.name			= "blt ring",
+	.id			= RING_BLT,
+	.mmio_base		= BLT_RING_BASE,
+	.size			= 32 * PAGE_SIZE,
+	.init			= blt_ring_init,
+	.write_tail		= ring_write_tail,
+	.flush			= blt_ring_flush,
+	.add_request		= gen6_add_request,
+	.get_seqno		= ring_get_seqno,
+	.irq_get		= blt_ring_get_irq,
+	.irq_put		= blt_ring_put_irq,
+	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
+	.cleanup		= blt_ring_cleanup,
+	.sync_to		= gen6_blt_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_BR,
+				   MI_SEMAPHORE_SYNC_BV,
+				   MI_SEMAPHORE_SYNC_INVALID},
+	.signal_mbox		= {GEN6_RBSYNC, GEN6_VBSYNC},
 };
 
 int intel_init_render_ring_buffer(struct drm_device *dev)
@@ -1295,6 +1471,7 @@ int intel_init_render_ring_buffer(struct
 	*ring = render_ring;
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ring->add_request = gen6_add_request;
+		ring->flush = gen6_render_ring_flush;
 		ring->irq_get = gen6_render_ring_get_irq;
 		ring->irq_put = gen6_render_ring_put_irq;
 	} else if (IS_GEN5(dev)) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,10 +2,10 @@
 #define _INTEL_RINGBUFFER_H_
 
 enum {
-    RCS = 0x0,
-    VCS,
-    BCS,
-    I915_NUM_RINGS,
+	RCS = 0x0,
+	VCS,
+	BCS,
+	I915_NUM_RINGS,
 };
 
 struct  intel_hw_status_page {
@@ -75,7 +75,12 @@ struct  intel_ring_buffer {
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
 					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
+	int		(*sync_to)(struct intel_ring_buffer *ring,
+				   struct intel_ring_buffer *to,
+				   u32 seqno);
 
+	u32		semaphore_register[3]; /*our mbox written by others */
+	u32		signal_mbox[2]; /* mboxes this ring signals to */
 	/**
 	 * List of objects currently involved in rendering from the
 	 * ringbuffer.
@@ -180,9 +185,6 @@ static inline void intel_ring_emit(struc
 void intel_ring_advance(struct intel_ring_buffer *ring);
 
 u32 intel_ring_get_seqno(struct intel_ring_buffer *ring);
-int intel_ring_sync(struct intel_ring_buffer *ring,
-		    struct intel_ring_buffer *to,
-		    u32 seqno);
 
 int intel_init_render_ring_buffer(struct drm_device *dev);
 int intel_init_bsd_ring_buffer(struct drm_device *dev);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
@@ -43,12 +44,13 @@
 #define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
 
 #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
-                         SDVO_TV_MASK)
+			SDVO_TV_MASK)
 
 #define IS_TV(c)	(c->output_flag & SDVO_TV_MASK)
 #define IS_TMDS(c)	(c->output_flag & SDVO_TMDS_MASK)
 #define IS_LVDS(c)	(c->output_flag & SDVO_LVDS_MASK)
 #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
+#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
 
 
 static const char *tv_format_names[] = {
@@ -288,117 +290,117 @@ static const struct _sdvo_cmd_name {
 	u8 cmd;
 	const char *name;
 } sdvo_cmd_names[] = {
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
 
-    /* Add the op code for SDVO enhancements */
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
+	/* Add the op code for SDVO enhancements */
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
 
-    /* HDMI op code */
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
+	/* HDMI op code */
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
 };
 
 #define IS_SDVOB(reg)	(reg == SDVOB || reg == PCH_SDVOB)
@@ -1085,8 +1087,12 @@ static void intel_sdvo_mode_set(struct d
 		}
 		sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
 	}
-	if (intel_crtc->pipe == 1)
-		sdvox |= SDVO_PIPE_B_SELECT;
+
+	if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
+		sdvox |= TRANSCODER_CPT(intel_crtc->pipe);
+	else
+		sdvox |= TRANSCODER(intel_crtc->pipe);
+
 	if (intel_sdvo->has_hdmi_audio)
 		sdvox |= SDVO_AUDIO_ENABLE;
 
@@ -1232,8 +1238,7 @@ static bool
 intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
 {
 	/* Is there more than one type of output? */
-	int caps = intel_sdvo->caps.output_flags & 0xf;
-	return caps & -caps;
+	return hweight16(intel_sdvo->caps.output_flags) > 1;
 }
 
 static struct edid *
@@ -1254,7 +1259,7 @@ intel_sdvo_get_analog_edid(struct drm_co
 }
 
 enum drm_connector_status
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
 {
 	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 	enum drm_connector_status status;
@@ -1314,6 +1319,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_c
 	return status;
 }
 
+static bool
+intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
+				  struct edid *edid)
+{
+	bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
+	bool connector_is_digital = !!IS_DIGITAL(sdvo);
+
+	DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
+		      connector_is_digital, monitor_is_digital);
+	return connector_is_digital == monitor_is_digital;
+}
+
 static enum drm_connector_status
 intel_sdvo_detect(struct drm_connector *connector, bool force)
 {
@@ -1349,7 +1366,7 @@ intel_sdvo_detect(struct drm_connector *
 	if ((intel_sdvo_connector->output_flag & response) == 0)
 		ret = connector_status_disconnected;
 	else if (IS_TMDS(intel_sdvo_connector))
-		ret = intel_sdvo_hdmi_sink_detect(connector);
+		ret = intel_sdvo_tmds_sink_detect(connector);
 	else {
 		struct edid *edid;
 
@@ -1358,10 +1375,12 @@ intel_sdvo_detect(struct drm_connector *
 		if (edid == NULL)
 			edid = intel_sdvo_get_analog_edid(connector);
 		if (edid != NULL) {
-			if (edid->input & DRM_EDID_INPUT_DIGITAL)
-				ret = connector_status_disconnected;
-			else
+			if (intel_sdvo_connector_matches_edid(intel_sdvo_connector,
+							      edid))
 				ret = connector_status_connected;
+			else
+				ret = connector_status_disconnected;
+
 			connector->display_info.raw_edid = NULL;
 			kfree(edid);
 		} else
@@ -1402,11 +1421,8 @@ static void intel_sdvo_get_ddc_modes(str
 		edid = intel_sdvo_get_analog_edid(connector);
 
 	if (edid != NULL) {
-		struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
-		bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
-		bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector);
-
-		if (connector_is_digital == monitor_is_digital) {
+		if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
+						      edid)) {
 			drm_mode_connector_update_edid_property(connector, edid);
 			drm_add_edid_modes(connector, edid);
 		}
@@ -1896,7 +1912,7 @@ intel_sdvo_select_i2c_bus(struct drm_i91
 			  struct intel_sdvo *sdvo, u32 reg)
 {
 	struct sdvo_device_mapping *mapping;
-	u8 pin, speed;
+	u8 pin;
 
 	if (IS_SDVOB(reg))
 		mapping = &dev_priv->sdvo_mappings[0];
@@ -1904,18 +1920,16 @@ intel_sdvo_select_i2c_bus(struct drm_i91
 		mapping = &dev_priv->sdvo_mappings[1];
 
 	pin = GMBUS_PORT_DPB;
-	speed = GMBUS_RATE_1MHZ >> 8;
-	if (mapping->initialized) {
+	if (mapping->initialized)
 		pin = mapping->i2c_pin;
-		speed = mapping->i2c_speed;
-	}
 
 	if (pin < GMBUS_NUM_PORTS) {
 		sdvo->i2c = &dev_priv->gmbus[pin].adapter;
-		intel_gmbus_set_speed(sdvo->i2c, speed);
+		intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
 		intel_gmbus_force_bit(sdvo->i2c, true);
-	} else
+	} else {
 		sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
+	}
 }
 
 static bool
@@ -2206,7 +2220,7 @@ intel_sdvo_output_setup(struct intel_sdv
 			      bytes[0], bytes[1]);
 		return false;
 	}
-	intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1);
+	intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
 	return true;
 }
@@ -2275,7 +2289,7 @@ static bool intel_sdvo_tv_create_propert
 		DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \
 			      data_value[0], data_value[1], response); \
 	} \
-} while(0)
+} while (0)
 
 static bool
 intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
@@ -2442,7 +2456,7 @@ static bool intel_sdvo_create_enhance_pr
 
 	if (IS_TV(intel_sdvo_connector))
 		return intel_sdvo_create_enhance_property_tv(intel_sdvo, intel_sdvo_connector, enhancements.reply);
-	else if(IS_LVDS(intel_sdvo_connector))
+	else if (IS_LVDS(intel_sdvo_connector))
 		return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply);
 	else
 		return true;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_sdvo_regs.h linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_sdvo_regs.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_sdvo_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_sdvo_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,63 +46,63 @@
 #define SDVO_OUTPUT_LAST    (14)
 
 struct intel_sdvo_caps {
-    u8 vendor_id;
-    u8 device_id;
-    u8 device_rev_id;
-    u8 sdvo_version_major;
-    u8 sdvo_version_minor;
-    unsigned int sdvo_inputs_mask:2;
-    unsigned int smooth_scaling:1;
-    unsigned int sharp_scaling:1;
-    unsigned int up_scaling:1;
-    unsigned int down_scaling:1;
-    unsigned int stall_support:1;
-    unsigned int pad:1;
-    u16 output_flags;
+	u8 vendor_id;
+	u8 device_id;
+	u8 device_rev_id;
+	u8 sdvo_version_major;
+	u8 sdvo_version_minor;
+	unsigned int sdvo_inputs_mask:2;
+	unsigned int smooth_scaling:1;
+	unsigned int sharp_scaling:1;
+	unsigned int up_scaling:1;
+	unsigned int down_scaling:1;
+	unsigned int stall_support:1;
+	unsigned int pad:1;
+	u16 output_flags;
 } __attribute__((packed));
 
 /** This matches the EDID DTD structure, more or less */
 struct intel_sdvo_dtd {
-    struct {
-	u16 clock;		/**< pixel clock, in 10kHz units */
-	u8 h_active;		/**< lower 8 bits (pixels) */
-	u8 h_blank;		/**< lower 8 bits (pixels) */
-	u8 h_high;		/**< upper 4 bits each h_active, h_blank */
-	u8 v_active;		/**< lower 8 bits (lines) */
-	u8 v_blank;		/**< lower 8 bits (lines) */
-	u8 v_high;		/**< upper 4 bits each v_active, v_blank */
-    } part1;
+	struct {
+		u16 clock;	/**< pixel clock, in 10kHz units */
+		u8 h_active;	/**< lower 8 bits (pixels) */
+		u8 h_blank;	/**< lower 8 bits (pixels) */
+		u8 h_high;	/**< upper 4 bits each h_active, h_blank */
+		u8 v_active;	/**< lower 8 bits (lines) */
+		u8 v_blank;	/**< lower 8 bits (lines) */
+		u8 v_high;	/**< upper 4 bits each v_active, v_blank */
+	} part1;
 
-    struct {
-	u8 h_sync_off;	/**< lower 8 bits, from hblank start */
-	u8 h_sync_width;	/**< lower 8 bits (pixels) */
-	/** lower 4 bits each vsync offset, vsync width */
-	u8 v_sync_off_width;
-	/**
-	 * 2 high bits of hsync offset, 2 high bits of hsync width,
-	 * bits 4-5 of vsync offset, and 2 high bits of vsync width.
-	 */
-	u8 sync_off_width_high;
-	u8 dtd_flags;
-	u8 sdvo_flags;
-	/** bits 6-7 of vsync offset at bits 6-7 */
-	u8 v_sync_off_high;
-	u8 reserved;
-    } part2;
+	struct {
+		u8 h_sync_off;	/**< lower 8 bits, from hblank start */
+		u8 h_sync_width;	/**< lower 8 bits (pixels) */
+		/** lower 4 bits each vsync offset, vsync width */
+		u8 v_sync_off_width;
+		/**
+		* 2 high bits of hsync offset, 2 high bits of hsync width,
+		* bits 4-5 of vsync offset, and 2 high bits of vsync width.
+		*/
+		u8 sync_off_width_high;
+		u8 dtd_flags;
+		u8 sdvo_flags;
+		/** bits 6-7 of vsync offset at bits 6-7 */
+		u8 v_sync_off_high;
+		u8 reserved;
+	} part2;
 } __attribute__((packed));
 
 struct intel_sdvo_pixel_clock_range {
-    u16 min;			/**< pixel clock, in 10kHz units */
-    u16 max;			/**< pixel clock, in 10kHz units */
+	u16 min;	/**< pixel clock, in 10kHz units */
+	u16 max;	/**< pixel clock, in 10kHz units */
 } __attribute__((packed));
 
 struct intel_sdvo_preferred_input_timing_args {
-    u16 clock;
-    u16 width;
-    u16 height;
-    u8	interlace:1;
-    u8	scaled:1;
-    u8	pad:6;
+	u16 clock;
+	u16 width;
+	u16 height;
+	u8	interlace:1;
+	u8	scaled:1;
+	u8	pad:6;
 } __attribute__((packed));
 
 /* I2C registers for SDVO */
@@ -154,9 +154,9 @@ struct intel_sdvo_preferred_input_timing
  */
 #define SDVO_CMD_GET_TRAINED_INPUTS			0x03
 struct intel_sdvo_get_trained_inputs_response {
-    unsigned int input0_trained:1;
-    unsigned int input1_trained:1;
-    unsigned int pad:6;
+	unsigned int input0_trained:1;
+	unsigned int input1_trained:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 /** Returns a struct intel_sdvo_output_flags of active outputs. */
@@ -177,7 +177,7 @@ struct intel_sdvo_get_trained_inputs_res
  */
 #define SDVO_CMD_GET_IN_OUT_MAP				0x06
 struct intel_sdvo_in_out_map {
-    u16 in0, in1;
+	u16 in0, in1;
 };
 
 /**
@@ -210,10 +210,10 @@ struct intel_sdvo_in_out_map {
 
 #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
 struct intel_sdvo_get_interrupt_event_source_response {
-    u16 interrupt_status;
-    unsigned int ambient_light_interrupt:1;
-    unsigned int hdmi_audio_encrypt_change:1;
-    unsigned int pad:6;
+	u16 interrupt_status;
+	unsigned int ambient_light_interrupt:1;
+	unsigned int hdmi_audio_encrypt_change:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 /**
@@ -225,8 +225,8 @@ struct intel_sdvo_get_interrupt_event_so
  */
 #define SDVO_CMD_SET_TARGET_INPUT			0x10
 struct intel_sdvo_set_target_input_args {
-    unsigned int target_1:1;
-    unsigned int pad:7;
+	unsigned int target_1:1;
+	unsigned int pad:7;
 } __attribute__((packed));
 
 /**
@@ -314,57 +314,57 @@ struct intel_sdvo_set_target_input_args
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 /** 6 bytes of bit flags for TV formats shared by all TV format functions */
 struct intel_sdvo_tv_format {
-    unsigned int ntsc_m:1;
-    unsigned int ntsc_j:1;
-    unsigned int ntsc_443:1;
-    unsigned int pal_b:1;
-    unsigned int pal_d:1;
-    unsigned int pal_g:1;
-    unsigned int pal_h:1;
-    unsigned int pal_i:1;
+	unsigned int ntsc_m:1;
+	unsigned int ntsc_j:1;
+	unsigned int ntsc_443:1;
+	unsigned int pal_b:1;
+	unsigned int pal_d:1;
+	unsigned int pal_g:1;
+	unsigned int pal_h:1;
+	unsigned int pal_i:1;
 
-    unsigned int pal_m:1;
-    unsigned int pal_n:1;
-    unsigned int pal_nc:1;
-    unsigned int pal_60:1;
-    unsigned int secam_b:1;
-    unsigned int secam_d:1;
-    unsigned int secam_g:1;
-    unsigned int secam_k:1;
+	unsigned int pal_m:1;
+	unsigned int pal_n:1;
+	unsigned int pal_nc:1;
+	unsigned int pal_60:1;
+	unsigned int secam_b:1;
+	unsigned int secam_d:1;
+	unsigned int secam_g:1;
+	unsigned int secam_k:1;
 
-    unsigned int secam_k1:1;
-    unsigned int secam_l:1;
-    unsigned int secam_60:1;
-    unsigned int hdtv_std_smpte_240m_1080i_59:1;
-    unsigned int hdtv_std_smpte_240m_1080i_60:1;
-    unsigned int hdtv_std_smpte_260m_1080i_59:1;
-    unsigned int hdtv_std_smpte_260m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080i_50:1;
+	unsigned int secam_k1:1;
+	unsigned int secam_l:1;
+	unsigned int secam_60:1;
+	unsigned int hdtv_std_smpte_240m_1080i_59:1;
+	unsigned int hdtv_std_smpte_240m_1080i_60:1;
+	unsigned int hdtv_std_smpte_260m_1080i_59:1;
+	unsigned int hdtv_std_smpte_260m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080i_50:1;
 
-    unsigned int hdtv_std_smpte_274m_1080i_59:1;
-    unsigned int hdtv_std_smpte_274m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080p_23:1;
-    unsigned int hdtv_std_smpte_274m_1080p_24:1;
-    unsigned int hdtv_std_smpte_274m_1080p_25:1;
-    unsigned int hdtv_std_smpte_274m_1080p_29:1;
-    unsigned int hdtv_std_smpte_274m_1080p_30:1;
-    unsigned int hdtv_std_smpte_274m_1080p_50:1;
+	unsigned int hdtv_std_smpte_274m_1080i_59:1;
+	unsigned int hdtv_std_smpte_274m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080p_23:1;
+	unsigned int hdtv_std_smpte_274m_1080p_24:1;
+	unsigned int hdtv_std_smpte_274m_1080p_25:1;
+	unsigned int hdtv_std_smpte_274m_1080p_29:1;
+	unsigned int hdtv_std_smpte_274m_1080p_30:1;
+	unsigned int hdtv_std_smpte_274m_1080p_50:1;
 
-    unsigned int hdtv_std_smpte_274m_1080p_59:1;
-    unsigned int hdtv_std_smpte_274m_1080p_60:1;
-    unsigned int hdtv_std_smpte_295m_1080i_50:1;
-    unsigned int hdtv_std_smpte_295m_1080p_50:1;
-    unsigned int hdtv_std_smpte_296m_720p_59:1;
-    unsigned int hdtv_std_smpte_296m_720p_60:1;
-    unsigned int hdtv_std_smpte_296m_720p_50:1;
-    unsigned int hdtv_std_smpte_293m_480p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_60:1;
+	unsigned int hdtv_std_smpte_295m_1080i_50:1;
+	unsigned int hdtv_std_smpte_295m_1080p_50:1;
+	unsigned int hdtv_std_smpte_296m_720p_59:1;
+	unsigned int hdtv_std_smpte_296m_720p_60:1;
+	unsigned int hdtv_std_smpte_296m_720p_50:1;
+	unsigned int hdtv_std_smpte_293m_480p_59:1;
 
-    unsigned int hdtv_std_smpte_170m_480i_59:1;
-    unsigned int hdtv_std_iturbt601_576i_50:1;
-    unsigned int hdtv_std_iturbt601_576p_50:1;
-    unsigned int hdtv_std_eia_7702a_480i_60:1;
-    unsigned int hdtv_std_eia_7702a_480p_60:1;
-    unsigned int pad:3;
+	unsigned int hdtv_std_smpte_170m_480i_59:1;
+	unsigned int hdtv_std_iturbt601_576i_50:1;
+	unsigned int hdtv_std_iturbt601_576p_50:1;
+	unsigned int hdtv_std_eia_7702a_480i_60:1;
+	unsigned int hdtv_std_eia_7702a_480p_60:1;
+	unsigned int pad:3;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_TV_FORMAT				0x28
@@ -374,53 +374,53 @@ struct intel_sdvo_tv_format {
 /** Returns the resolutiosn that can be used with the given TV format */
 #define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT		0x83
 struct intel_sdvo_sdtv_resolution_request {
-    unsigned int ntsc_m:1;
-    unsigned int ntsc_j:1;
-    unsigned int ntsc_443:1;
-    unsigned int pal_b:1;
-    unsigned int pal_d:1;
-    unsigned int pal_g:1;
-    unsigned int pal_h:1;
-    unsigned int pal_i:1;
+	unsigned int ntsc_m:1;
+	unsigned int ntsc_j:1;
+	unsigned int ntsc_443:1;
+	unsigned int pal_b:1;
+	unsigned int pal_d:1;
+	unsigned int pal_g:1;
+	unsigned int pal_h:1;
+	unsigned int pal_i:1;
 
-    unsigned int pal_m:1;
-    unsigned int pal_n:1;
-    unsigned int pal_nc:1;
-    unsigned int pal_60:1;
-    unsigned int secam_b:1;
-    unsigned int secam_d:1;
-    unsigned int secam_g:1;
-    unsigned int secam_k:1;
+	unsigned int pal_m:1;
+	unsigned int pal_n:1;
+	unsigned int pal_nc:1;
+	unsigned int pal_60:1;
+	unsigned int secam_b:1;
+	unsigned int secam_d:1;
+	unsigned int secam_g:1;
+	unsigned int secam_k:1;
 
-    unsigned int secam_k1:1;
-    unsigned int secam_l:1;
-    unsigned int secam_60:1;
-    unsigned int pad:5;
+	unsigned int secam_k1:1;
+	unsigned int secam_l:1;
+	unsigned int secam_60:1;
+	unsigned int pad:5;
 } __attribute__((packed));
 
 struct intel_sdvo_sdtv_resolution_reply {
-    unsigned int res_320x200:1;
-    unsigned int res_320x240:1;
-    unsigned int res_400x300:1;
-    unsigned int res_640x350:1;
-    unsigned int res_640x400:1;
-    unsigned int res_640x480:1;
-    unsigned int res_704x480:1;
-    unsigned int res_704x576:1;
+	unsigned int res_320x200:1;
+	unsigned int res_320x240:1;
+	unsigned int res_400x300:1;
+	unsigned int res_640x350:1;
+	unsigned int res_640x400:1;
+	unsigned int res_640x480:1;
+	unsigned int res_704x480:1;
+	unsigned int res_704x576:1;
 
-    unsigned int res_720x350:1;
-    unsigned int res_720x400:1;
-    unsigned int res_720x480:1;
-    unsigned int res_720x540:1;
-    unsigned int res_720x576:1;
-    unsigned int res_768x576:1;
-    unsigned int res_800x600:1;
-    unsigned int res_832x624:1;
+	unsigned int res_720x350:1;
+	unsigned int res_720x400:1;
+	unsigned int res_720x480:1;
+	unsigned int res_720x540:1;
+	unsigned int res_720x576:1;
+	unsigned int res_768x576:1;
+	unsigned int res_800x600:1;
+	unsigned int res_832x624:1;
 
-    unsigned int res_920x766:1;
-    unsigned int res_1024x768:1;
-    unsigned int res_1280x1024:1;
-    unsigned int pad:5;
+	unsigned int res_920x766:1;
+	unsigned int res_1024x768:1;
+	unsigned int res_1280x1024:1;
+	unsigned int pad:5;
 } __attribute__((packed));
 
 /* Get supported resolution with squire pixel aspect ratio that can be
@@ -428,90 +428,90 @@ struct intel_sdvo_sdtv_resolution_reply
 #define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT		0x85
 
 struct intel_sdvo_hdtv_resolution_request {
-    unsigned int hdtv_std_smpte_240m_1080i_59:1;
-    unsigned int hdtv_std_smpte_240m_1080i_60:1;
-    unsigned int hdtv_std_smpte_260m_1080i_59:1;
-    unsigned int hdtv_std_smpte_260m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080i_50:1;
-    unsigned int hdtv_std_smpte_274m_1080i_59:1;
-    unsigned int hdtv_std_smpte_274m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080p_23:1;
+	unsigned int hdtv_std_smpte_240m_1080i_59:1;
+	unsigned int hdtv_std_smpte_240m_1080i_60:1;
+	unsigned int hdtv_std_smpte_260m_1080i_59:1;
+	unsigned int hdtv_std_smpte_260m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080i_50:1;
+	unsigned int hdtv_std_smpte_274m_1080i_59:1;
+	unsigned int hdtv_std_smpte_274m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080p_23:1;
 
-    unsigned int hdtv_std_smpte_274m_1080p_24:1;
-    unsigned int hdtv_std_smpte_274m_1080p_25:1;
-    unsigned int hdtv_std_smpte_274m_1080p_29:1;
-    unsigned int hdtv_std_smpte_274m_1080p_30:1;
-    unsigned int hdtv_std_smpte_274m_1080p_50:1;
-    unsigned int hdtv_std_smpte_274m_1080p_59:1;
-    unsigned int hdtv_std_smpte_274m_1080p_60:1;
-    unsigned int hdtv_std_smpte_295m_1080i_50:1;
+	unsigned int hdtv_std_smpte_274m_1080p_24:1;
+	unsigned int hdtv_std_smpte_274m_1080p_25:1;
+	unsigned int hdtv_std_smpte_274m_1080p_29:1;
+	unsigned int hdtv_std_smpte_274m_1080p_30:1;
+	unsigned int hdtv_std_smpte_274m_1080p_50:1;
+	unsigned int hdtv_std_smpte_274m_1080p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_60:1;
+	unsigned int hdtv_std_smpte_295m_1080i_50:1;
 
-    unsigned int hdtv_std_smpte_295m_1080p_50:1;
-    unsigned int hdtv_std_smpte_296m_720p_59:1;
-    unsigned int hdtv_std_smpte_296m_720p_60:1;
-    unsigned int hdtv_std_smpte_296m_720p_50:1;
-    unsigned int hdtv_std_smpte_293m_480p_59:1;
-    unsigned int hdtv_std_smpte_170m_480i_59:1;
-    unsigned int hdtv_std_iturbt601_576i_50:1;
-    unsigned int hdtv_std_iturbt601_576p_50:1;
+	unsigned int hdtv_std_smpte_295m_1080p_50:1;
+	unsigned int hdtv_std_smpte_296m_720p_59:1;
+	unsigned int hdtv_std_smpte_296m_720p_60:1;
+	unsigned int hdtv_std_smpte_296m_720p_50:1;
+	unsigned int hdtv_std_smpte_293m_480p_59:1;
+	unsigned int hdtv_std_smpte_170m_480i_59:1;
+	unsigned int hdtv_std_iturbt601_576i_50:1;
+	unsigned int hdtv_std_iturbt601_576p_50:1;
 
-    unsigned int hdtv_std_eia_7702a_480i_60:1;
-    unsigned int hdtv_std_eia_7702a_480p_60:1;
-    unsigned int pad:6;
+	unsigned int hdtv_std_eia_7702a_480i_60:1;
+	unsigned int hdtv_std_eia_7702a_480p_60:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 struct intel_sdvo_hdtv_resolution_reply {
-    unsigned int res_640x480:1;
-    unsigned int res_800x600:1;
-    unsigned int res_1024x768:1;
-    unsigned int res_1280x960:1;
-    unsigned int res_1400x1050:1;
-    unsigned int res_1600x1200:1;
-    unsigned int res_1920x1440:1;
-    unsigned int res_2048x1536:1;
+	unsigned int res_640x480:1;
+	unsigned int res_800x600:1;
+	unsigned int res_1024x768:1;
+	unsigned int res_1280x960:1;
+	unsigned int res_1400x1050:1;
+	unsigned int res_1600x1200:1;
+	unsigned int res_1920x1440:1;
+	unsigned int res_2048x1536:1;
 
-    unsigned int res_2560x1920:1;
-    unsigned int res_3200x2400:1;
-    unsigned int res_3840x2880:1;
-    unsigned int pad1:5;
+	unsigned int res_2560x1920:1;
+	unsigned int res_3200x2400:1;
+	unsigned int res_3840x2880:1;
+	unsigned int pad1:5;
 
-    unsigned int res_848x480:1;
-    unsigned int res_1064x600:1;
-    unsigned int res_1280x720:1;
-    unsigned int res_1360x768:1;
-    unsigned int res_1704x960:1;
-    unsigned int res_1864x1050:1;
-    unsigned int res_1920x1080:1;
-    unsigned int res_2128x1200:1;
+	unsigned int res_848x480:1;
+	unsigned int res_1064x600:1;
+	unsigned int res_1280x720:1;
+	unsigned int res_1360x768:1;
+	unsigned int res_1704x960:1;
+	unsigned int res_1864x1050:1;
+	unsigned int res_1920x1080:1;
+	unsigned int res_2128x1200:1;
 
-    unsigned int res_2560x1400:1;
-    unsigned int res_2728x1536:1;
-    unsigned int res_3408x1920:1;
-    unsigned int res_4264x2400:1;
-    unsigned int res_5120x2880:1;
-    unsigned int pad2:3;
+	unsigned int res_2560x1400:1;
+	unsigned int res_2728x1536:1;
+	unsigned int res_3408x1920:1;
+	unsigned int res_4264x2400:1;
+	unsigned int res_5120x2880:1;
+	unsigned int pad2:3;
 
-    unsigned int res_768x480:1;
-    unsigned int res_960x600:1;
-    unsigned int res_1152x720:1;
-    unsigned int res_1124x768:1;
-    unsigned int res_1536x960:1;
-    unsigned int res_1680x1050:1;
-    unsigned int res_1728x1080:1;
-    unsigned int res_1920x1200:1;
+	unsigned int res_768x480:1;
+	unsigned int res_960x600:1;
+	unsigned int res_1152x720:1;
+	unsigned int res_1124x768:1;
+	unsigned int res_1536x960:1;
+	unsigned int res_1680x1050:1;
+	unsigned int res_1728x1080:1;
+	unsigned int res_1920x1200:1;
 
-    unsigned int res_2304x1440:1;
-    unsigned int res_2456x1536:1;
-    unsigned int res_3072x1920:1;
-    unsigned int res_3840x2400:1;
-    unsigned int res_4608x2880:1;
-    unsigned int pad3:3;
+	unsigned int res_2304x1440:1;
+	unsigned int res_2456x1536:1;
+	unsigned int res_3072x1920:1;
+	unsigned int res_3840x2400:1;
+	unsigned int res_4608x2880:1;
+	unsigned int pad3:3;
 
-    unsigned int res_1280x1024:1;
-    unsigned int pad4:7;
+	unsigned int res_1280x1024:1;
+	unsigned int pad4:7;
 
-    unsigned int res_1280x768:1;
-    unsigned int pad5:7;
+	unsigned int res_1280x768:1;
+	unsigned int pad5:7;
 } __attribute__((packed));
 
 /* Get supported power state returns info for encoder and monitor, rely on
@@ -539,25 +539,25 @@ struct intel_sdvo_hdtv_resolution_reply
  * The high fields are bits 8:9 of the 10-bit values.
  */
 struct sdvo_panel_power_sequencing {
-    u8 t0;
-    u8 t1;
-    u8 t2;
-    u8 t3;
-    u8 t4;
+	u8 t0;
+	u8 t1;
+	u8 t2;
+	u8 t3;
+	u8 t4;
 
-    unsigned int t0_high:2;
-    unsigned int t1_high:2;
-    unsigned int t2_high:2;
-    unsigned int t3_high:2;
+	unsigned int t0_high:2;
+	unsigned int t1_high:2;
+	unsigned int t2_high:2;
+	unsigned int t3_high:2;
 
-    unsigned int t4_high:2;
-    unsigned int pad:6;
+	unsigned int t4_high:2;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL		0x30
 struct sdvo_max_backlight_reply {
-    u8 max_value;
-    u8 default_value;
+	u8 max_value;
+	u8 default_value;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_BACKLIGHT_LEVEL			0x31
@@ -565,16 +565,16 @@ struct sdvo_max_backlight_reply {
 
 #define SDVO_CMD_GET_AMBIENT_LIGHT			0x33
 struct sdvo_get_ambient_light_reply {
-    u16 trip_low;
-    u16 trip_high;
-    u16 value;
+	u16 trip_low;
+	u16 trip_high;
+	u16 value;
 } __attribute__((packed));
 #define SDVO_CMD_SET_AMBIENT_LIGHT			0x34
 struct sdvo_set_ambient_light_reply {
-    u16 trip_low;
-    u16 trip_high;
-    unsigned int enable:1;
-    unsigned int pad:7;
+	u16 trip_low;
+	u16 trip_high;
+	unsigned int enable:1;
+	unsigned int pad:7;
 } __attribute__((packed));
 
 /* Set display power state */
@@ -586,23 +586,23 @@ struct sdvo_set_ambient_light_reply {
 
 #define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS		0x84
 struct intel_sdvo_enhancements_reply {
-    unsigned int flicker_filter:1;
-    unsigned int flicker_filter_adaptive:1;
-    unsigned int flicker_filter_2d:1;
-    unsigned int saturation:1;
-    unsigned int hue:1;
-    unsigned int brightness:1;
-    unsigned int contrast:1;
-    unsigned int overscan_h:1;
+	unsigned int flicker_filter:1;
+	unsigned int flicker_filter_adaptive:1;
+	unsigned int flicker_filter_2d:1;
+	unsigned int saturation:1;
+	unsigned int hue:1;
+	unsigned int brightness:1;
+	unsigned int contrast:1;
+	unsigned int overscan_h:1;
 
-    unsigned int overscan_v:1;
-    unsigned int hpos:1;
-    unsigned int vpos:1;
-    unsigned int sharpness:1;
-    unsigned int dot_crawl:1;
-    unsigned int dither:1;
-    unsigned int tv_chroma_filter:1;
-    unsigned int tv_luma_filter:1;
+	unsigned int overscan_v:1;
+	unsigned int hpos:1;
+	unsigned int vpos:1;
+	unsigned int sharpness:1;
+	unsigned int dot_crawl:1;
+	unsigned int dither:1;
+	unsigned int tv_chroma_filter:1;
+	unsigned int tv_luma_filter:1;
 } __attribute__((packed));
 
 /* Picture enhancement limits below are dependent on the current TV format,
@@ -623,8 +623,8 @@ struct intel_sdvo_enhancements_reply {
 #define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER		0x74
 #define SDVO_CMD_GET_MAX_TV_LUMA_FILTER			0x77
 struct intel_sdvo_enhancement_limits_reply {
-    u16 max_value;
-    u16 default_value;
+	u16 max_value;
+	u16 default_value;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION		0x7f
@@ -665,8 +665,8 @@ struct intel_sdvo_enhancement_limits_rep
 #define SDVO_CMD_GET_TV_LUMA_FILTER			0x78
 #define SDVO_CMD_SET_TV_LUMA_FILTER			0x79
 struct intel_sdvo_enhancements_arg {
-    u16 value;
-}__attribute__((packed));
+	u16 value;
+} __attribute__((packed));
 
 #define SDVO_CMD_GET_DOT_CRAWL				0x70
 #define SDVO_CMD_SET_DOT_CRAWL				0x71
@@ -717,7 +717,7 @@ struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_GET_AUDIO_TX_INFO	0x9c
 #define SDVO_NEED_TO_STALL  (1 << 7)
 
-struct intel_sdvo_encode{
-    u8 dvi_rev;
-    u8 hdmi_rev;
+struct intel_sdvo_encode {
+	u8 dvi_rev;
+	u8 hdmi_rev;
 } __attribute__ ((packed));
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_tv.c linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/i915/intel_tv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/i915/intel_tv.c	2012-01-04 18:55:44.000000000 -0500
@@ -194,10 +194,10 @@ static const u32 filter_table[] = {
  *
  *     if (f >= 1) {
  *         exp = 0x7;
- * 	   mant = 1 << 8;
+ *	   mant = 1 << 8;
  *     } else {
  *         for (exp = 0; exp < 3 && f < 0.5; exp++)
- * 	       f *= 2.0;
+ *	   f *= 2.0;
  *         mant = (f * (1 << 9) + 0.5);
  *         if (mant >= (1 << 9))
  *             mant = (1 << 9) - 1;
@@ -430,7 +430,7 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -472,7 +472,7 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1 = 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -515,7 +515,7 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1	= 6,	    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena      = true,	    .veq_start_f1	= 0,
 		.veq_start_f2 = 1,	    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -558,7 +558,7 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -602,14 +602,14 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1	= 6,	   .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 24,		    .vi_end_f2		= 25,
 		.nbr_end	= 286,
 
 		.burst_ena	= true,
-		.hburst_start = 73,	    	    .hburst_len		= 34,
+		.hburst_start = 73,	    .hburst_len		= 34,
 		.vburst_start_f1 = 8,	    .vburst_end_f1	= 285,
 		.vburst_start_f2 = 8,	    .vburst_end_f2	= 286,
 		.vburst_start_f3 = 9,	    .vburst_end_f3	= 286,
@@ -646,7 +646,7 @@ static const struct tv_mode tv_modes[] =
 		.vsync_start_f1	= 5,	    .vsync_start_f2	= 6,
 		.vsync_len	= 5,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,	    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,	    .veq_len		= 15,
 
 		.vi_end_f1	= 24,		    .vi_end_f2		= 25,
@@ -675,7 +675,7 @@ static const struct tv_mode tv_modes[] =
 	},
 	{
 		.name       = "480p@59.94Hz",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 59940,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -683,7 +683,7 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 64,               .hblank_end         = 122,
 		.hblank_start   = 842,              .htotal             = 857,
 
-		.progressive    = true,.trilevel_sync = false,
+		.progressive    = true,		    .trilevel_sync = false,
 
 		.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 		.vsync_len      = 12,
@@ -699,7 +699,7 @@ static const struct tv_mode tv_modes[] =
 	},
 	{
 		.name       = "480p@60Hz",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 60000,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -707,7 +707,7 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 64,               .hblank_end         = 122,
 		.hblank_start   = 842,              .htotal             = 856,
 
-		.progressive    = true,.trilevel_sync = false,
+		.progressive    = true,		    .trilevel_sync = false,
 
 		.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 		.vsync_len      = 12,
@@ -723,7 +723,7 @@ static const struct tv_mode tv_modes[] =
 	},
 	{
 		.name       = "576p",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 50000,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -755,7 +755,7 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1649,
 
-		.progressive    = true, 	    .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -779,7 +779,7 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1651,
 
-		.progressive    = true, 	    .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -803,7 +803,7 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1979,
 
-		.progressive    = true, 	        .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -828,12 +828,12 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2639,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	  .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,              .vsync_start_f2     = 5,
 		.vsync_len      = 10,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 4,
+		.veq_ena	= true,	    .veq_start_f1	= 4,
 		.veq_start_f2   = 4,	    .veq_len		= 10,
 
 
@@ -854,12 +854,12 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2199,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	    .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,               .vsync_start_f2     = 5,
 		.vsync_len      = 10,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 4,
+		.veq_ena	= true,		    .veq_start_f1	= 4,
 		.veq_start_f2	= 4,		    .veq_len		= 10,
 
 
@@ -880,16 +880,16 @@ static const struct tv_mode tv_modes[] =
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2201,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	    .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,            .vsync_start_f2    = 5,
 		.vsync_len      = 10,
 
 		.veq_ena	= true,		    .veq_start_f1	= 4,
-		.veq_start_f2 = 4,	    	    .veq_len = 10,
+		.veq_start_f2	= 4,		.veq_len	  = 10,
 
 
-		.vi_end_f1      = 21,           .vi_end_f2         	= 22,
+		.vi_end_f1	= 21,		.vi_end_f2	  = 22,
 		.nbr_end        = 539,
 
 		.burst_ena      = false,
@@ -916,7 +916,7 @@ intel_tv_dpms(struct drm_encoder *encode
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	switch(mode) {
+	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 		break;
@@ -933,7 +933,7 @@ intel_tv_mode_lookup(const char *tv_form
 {
 	int i;
 
-	for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) {
+	for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); i++) {
 		const struct tv_mode *tv_mode = &tv_modes[i];
 
 		if (!strcmp(tv_format, tv_mode->name))
@@ -1128,7 +1128,7 @@ intel_tv_mode_set(struct drm_encoder *en
 	if (color_conversion) {
 		I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
 			   color_conversion->gy);
-		I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
+		I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
 			   color_conversion->ay);
 		I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
 			   color_conversion->gu);
@@ -1232,7 +1232,7 @@ static const struct drm_display_mode rep
  * \return false if TV is disconnected.
  */
 static int
-intel_tv_detect_type (struct intel_tv *intel_tv,
+intel_tv_detect_type(struct intel_tv *intel_tv,
 		      struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &intel_tv->base.base;
@@ -1486,7 +1486,7 @@ intel_tv_get_modes(struct drm_connector
 }
 
 static void
-intel_tv_destroy (struct drm_connector *connector)
+intel_tv_destroy(struct drm_connector *connector)
 {
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/Kconfig linux-libre-3.2-gnu1/drivers/gpu/drm/Kconfig
--- linux-libre-3.1-gnu1/drivers/gpu/drm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@ menuconfig DRM
 	depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
 	select I2C
 	select I2C_ALGOBIT
-	select SLOW_WORK
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
@@ -96,6 +95,7 @@ config DRM_I915
 	select FB_CFB_IMAGEBLIT
 	# i915 depends on ACPI_VIDEO when ACPI is enabled
 	# but for select to work, need to select ACPI_VIDEO's dependencies, ick
+	select BACKLIGHT_LCD_SUPPORT if ACPI
 	select BACKLIGHT_CLASS_DEVICE if ACPI
 	select VIDEO_OUTPUT_CONTROL if ACPI
 	select INPUT if ACPI
@@ -158,3 +158,7 @@ config DRM_SAVAGE
 	help
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  chipset. If M is selected the module will be called savage.
+
+source "drivers/gpu/drm/exynos/Kconfig"
+
+source "drivers/gpu/drm/vmwgfx/Kconfig"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/Makefile linux-libre-3.2-gnu1/drivers/gpu/drm/Makefile
--- linux-libre-3.1-gnu1/drivers/gpu/drm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -35,4 +35,5 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/
 obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VIA)	+=via/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-y			+= i2c/
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/mga/mga_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/mga/mga_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/mga/mga_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/mga/mga_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "mga_drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/mga/mga_warp.c linux-libre-3.2-gnu1/drivers/gpu/drm/mga/mga_warp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/mga/mga_warp.c	2013-05-02 01:33:23.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/mga/mga_warp.c	2013-05-01 23:41:24.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/firmware.h>
 #include <linux/ihex.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/Makefile linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/Makefile
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,16 +21,17 @@ nouveau-y := nouveau_drv.o nouveau_state
              nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
              nv84_crypt.o \
              nva3_copy.o nvc0_copy.o \
-             nv40_mpeg.o nv50_mpeg.o \
+             nv31_mpeg.o nv50_mpeg.o \
              nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
-             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
-             nv50_cursor.o nv50_display.o \
              nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
              nv04_crtc.o nv04_display.o nv04_cursor.o \
+             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
+             nv50_cursor.o nv50_display.o \
+             nvd0_display.o \
              nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
              nv10_gpio.o nv50_gpio.o \
 	     nv50_calc.o \
-	     nv04_pm.o nv50_pm.o nva3_pm.o \
+	     nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
 	     nv50_vram.o nvc0_vram.o \
 	     nv50_vm.o nvc0_vm.o
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,10 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_reg.h"
+#include "nouveau_encoder.h"
 
-static int nv40_get_intensity(struct backlight_device *bd)
+static int
+nv40_get_intensity(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
 	int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)
@@ -47,7 +49,8 @@ static int nv40_get_intensity(struct bac
 	return val;
 }
 
-static int nv40_set_intensity(struct backlight_device *bd)
+static int
+nv40_set_intensity(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
 	int val = bd->props.brightness;
@@ -65,30 +68,8 @@ static const struct backlight_ops nv40_b
 	.update_status = nv40_set_intensity,
 };
 
-static int nv50_get_intensity(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(bd);
-
-	return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT);
-}
-
-static int nv50_set_intensity(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(bd);
-	int val = bd->props.brightness;
-
-	nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT,
-		val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);
-	return 0;
-}
-
-static const struct backlight_ops nv50_bl_ops = {
-	.options = BL_CORE_SUSPENDRESUME,
-	.get_brightness = nv50_get_intensity,
-	.update_status = nv50_set_intensity,
-};
-
-static int nouveau_nv40_backlight_init(struct drm_connector *connector)
+static int
+nv40_backlight_init(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -113,34 +94,129 @@ static int nouveau_nv40_backlight_init(s
 	return 0;
 }
 
-static int nouveau_nv50_backlight_init(struct drm_connector *connector)
+static int
+nv50_get_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div = 1025;
+	u32 val;
+
+	val  = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+	val &= NV50_PDISP_SOR_PWM_CTL_VAL;
+	return ((val * 100) + (div / 2)) / div;
+}
+
+static int
+nv50_set_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div = 1025;
+	u32 val = (bd->props.brightness * div) / 100;
+
+	nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or),
+		     NV50_PDISP_SOR_PWM_CTL_NEW | val);
+	return 0;
+}
+
+static const struct backlight_ops nv50_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nv50_get_intensity,
+	.update_status = nv50_set_intensity,
+};
+
+static int
+nva3_get_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div, val;
+
+	div  = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+	val  = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+	val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
+	if (div && div >= val)
+		return ((val * 100) + (div / 2)) / div;
+
+	return 100;
+}
+
+static int
+nva3_set_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div, val;
+
+	div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+	val = (bd->props.brightness * div) / 100;
+	if (div) {
+		nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val |
+			     NV50_PDISP_SOR_PWM_CTL_NEW |
+			     NVA3_PDISP_SOR_PWM_CTL_UNK);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct backlight_ops nva3_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nva3_get_intensity,
+	.update_status = nva3_set_intensity,
+};
+
+static int
+nv50_backlight_init(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_encoder *nv_encoder;
 	struct backlight_properties props;
 	struct backlight_device *bd;
+	const struct backlight_ops *ops;
 
-	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
+	nv_encoder = find_encoder(connector, OUTPUT_LVDS);
+	if (!nv_encoder) {
+		nv_encoder = find_encoder(connector, OUTPUT_DP);
+		if (!nv_encoder)
+			return -ENODEV;
+	}
+
+	if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
 		return 0;
 
+	if (dev_priv->chipset <= 0xa0 ||
+	    dev_priv->chipset == 0xaa ||
+	    dev_priv->chipset == 0xac)
+		ops = &nv50_bl_ops;
+	else
+		ops = &nva3_bl_ops;
+
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 1025;
-	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
-				       &nv50_bl_ops, &props);
+	props.max_brightness = 100;
+	bd = backlight_device_register("nv_backlight", &connector->kdev,
+				       nv_encoder, ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
 
 	dev_priv->backlight = bd;
-	bd->props.brightness = nv50_get_intensity(bd);
+	bd->props.brightness = bd->ops->get_brightness(bd);
 	backlight_update_status(bd);
 	return 0;
 }
 
-int nouveau_backlight_init(struct drm_connector *connector)
+int
+nouveau_backlight_init(struct drm_device *dev)
 {
-	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
 
 #ifdef CONFIG_ACPI
 	if (acpi_video_backlight_support()) {
@@ -150,21 +226,28 @@ int nouveau_backlight_init(struct drm_co
 	}
 #endif
 
-	switch (dev_priv->card_type) {
-	case NV_40:
-		return nouveau_nv40_backlight_init(connector);
-	case NV_50:
-		return nouveau_nv50_backlight_init(connector);
-	default:
-		break;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+			continue;
+
+		switch (dev_priv->card_type) {
+		case NV_40:
+			return nv40_backlight_init(connector);
+		case NV_50:
+			return nv50_backlight_init(connector);
+		default:
+			break;
+		}
 	}
 
+
 	return 0;
 }
 
-void nouveau_backlight_exit(struct drm_connector *connector)
+void
+nouveau_backlight_exit(struct drm_device *dev)
 {
-	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->backlight) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c	2012-01-04 18:55:44.000000000 -0500
@@ -296,6 +296,11 @@ munge_reg(struct nvbios *bios, uint32_t
 	if (dev_priv->card_type < NV_50)
 		return reg;
 
+	if (reg & 0x80000000) {
+		BUG_ON(bios->display.crtc < 0);
+		reg += bios->display.crtc * 0x800;
+	}
+
 	if (reg & 0x40000000) {
 		BUG_ON(!dcbent);
 
@@ -304,7 +309,7 @@ munge_reg(struct nvbios *bios, uint32_t
 			reg += 0x00000080;
 	}
 
-	reg &= ~0x60000000;
+	reg &= ~0xe0000000;
 	return reg;
 }
 
@@ -635,10 +640,9 @@ static int
 nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t reg0 = nv_rd32(dev, reg + 0);
-	uint32_t reg1 = nv_rd32(dev, reg + 4);
 	struct nouveau_pll_vals pll;
 	struct pll_lims pll_limits;
+	u32 ctrl, mask, coef;
 	int ret;
 
 	ret = get_pll_limits(dev, reg, &pll_limits);
@@ -649,15 +653,20 @@ nv50_pll_set(struct drm_device *dev, uin
 	if (!clk)
 		return -ERANGE;
 
-	reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
-	reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
-
-	if (dev_priv->vbios.execute) {
-		still_alive();
-		nv_wr32(dev, reg + 4, reg1);
-		nv_wr32(dev, reg + 0, reg0);
+	coef = pll.N1 << 8 | pll.M1;
+	ctrl = pll.log2P << 16;
+	mask = 0x00070000;
+	if (reg == 0x004008) {
+		mask |= 0x01f80000;
+		ctrl |= (pll_limits.log2p_bias << 19);
+		ctrl |= (pll.log2P << 22);
 	}
 
+	if (!dev_priv->vbios.execute)
+		return 0;
+
+	nv_mask(dev, reg + 0, mask, ctrl);
+	nv_wr32(dev, reg + 4, coef);
 	return 0;
 }
 
@@ -1174,22 +1183,19 @@ init_dp_condition(struct nvbios *bios, u
 	 *
 	 */
 
-	struct bit_displayport_encoder_table *dpe = NULL;
 	struct dcb_entry *dcb = bios->display.output;
 	struct drm_device *dev = bios->dev;
 	uint8_t cond = bios->data[offset + 1];
-	int dummy;
+	uint8_t *table, *entry;
 
 	BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
 
 	if (!iexec->execute)
 		return 3;
 
-	dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
-	if (!dpe) {
-		NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
+	table = nouveau_dp_bios_data(dev, dcb, &entry);
+	if (!table)
 		return 3;
-	}
 
 	switch (cond) {
 	case 0:
@@ -1203,7 +1209,7 @@ init_dp_condition(struct nvbios *bios, u
 		break;
 	case 1:
 	case 2:
-		if (!(dpe->unknown & cond))
+		if (!(entry[5] & cond))
 			iexec->execute = false;
 		break;
 	case 5:
@@ -3221,6 +3227,49 @@ init_8d(struct nvbios *bios, uint16_t of
 	return 1;
 }
 
+static void
+init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
+	u32 r, s, v;
+
+	/* Not a clue, needs de-magicing */
+	r = nv50_gpio_ctl[gpio->line >> 4];
+	s = (gpio->line & 0x0f);
+	v = bios_rd32(bios, r) & ~(0x00010001 << s);
+	switch ((gpio->entry & 0x06000000) >> 25) {
+	case 1:
+		v |= (0x00000001 << s);
+		break;
+	case 2:
+		v |= (0x00010000 << s);
+		break;
+	default:
+		break;
+	}
+
+	bios_wr32(bios, r, v);
+}
+
+static void
+init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+	u32 v, i;
+
+	v  = bios_rd32(bios, 0x00d610 + (gpio->line * 4));
+	v &= 0xffffff00;
+	v |= (gpio->entry & 0x00ff0000) >> 16;
+	bios_wr32(bios, 0x00d610 + (gpio->line * 4), v);
+
+	i = (gpio->entry & 0x1f000000) >> 24;
+	if (i) {
+		v  = bios_rd32(bios, 0x00d640 + ((i - 1) * 4));
+		v &= 0xffffff00;
+		v |= gpio->line;
+		bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v);
+	}
+}
+
 static int
 init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
@@ -3235,7 +3284,6 @@ init_gpio(struct nvbios *bios, uint16_t
 
 	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
 	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
 	int i;
 
 	if (dev_priv->card_type < NV_50) {
@@ -3248,33 +3296,20 @@ init_gpio(struct nvbios *bios, uint16_t
 
 	for (i = 0; i < bios->dcb.gpio.entries; i++) {
 		struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
-		uint32_t r, s, v;
 
 		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
 		BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
 			offset, gpio->tag, gpio->state_default);
-		if (bios->execute)
-			pgpio->set(bios->dev, gpio->tag, gpio->state_default);
 
-		/* The NVIDIA binary driver doesn't appear to actually do
-		 * any of this, my VBIOS does however.
-		 */
-		/* Not a clue, needs de-magicing */
-		r = nv50_gpio_ctl[gpio->line >> 4];
-		s = (gpio->line & 0x0f);
-		v = bios_rd32(bios, r) & ~(0x00010001 << s);
-		switch ((gpio->entry & 0x06000000) >> 25) {
-		case 1:
-			v |= (0x00000001 << s);
-			break;
-		case 2:
-			v |= (0x00010000 << s);
-			break;
-		default:
-			break;
-		}
-		bios_wr32(bios, r, v);
+		if (!bios->execute)
+			continue;
+
+		pgpio->set(bios->dev, gpio->tag, gpio->state_default);
+		if (dev_priv->card_type < NV_D0)
+			init_gpio_unknv50(bios, gpio);
+		else
+			init_gpio_unknvd0(bios, gpio);
 	}
 
 	return 1;
@@ -3737,6 +3772,10 @@ parse_init_table(struct nvbios *bios, ui
 	int count = 0, i, ret;
 	uint8_t id;
 
+	/* catch NULL script pointers */
+	if (offset == 0)
+		return 0;
+
 	/*
 	 * Loop until INIT_DONE causes us to break out of the loop
 	 * (or until offset > bios length just in case... )
@@ -4389,86 +4428,37 @@ int nouveau_bios_parse_lvds_table(struct
 	return 0;
 }
 
-static uint8_t *
-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
-			 uint16_t record, int record_len, int record_nr,
-			 bool match_link)
+/* BIT 'U'/'d' table encoder subtables have hashes matching them to
+ * a particular set of encoders.
+ *
+ * This function returns true if a particular DCB entry matches.
+ */
+bool
+bios_encoder_match(struct dcb_entry *dcb, u32 hash)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->vbios;
-	uint32_t entry;
-	uint16_t table;
-	int i, v;
+	if ((hash & 0x000000f0) != (dcb->location << 4))
+		return false;
+	if ((hash & 0x0000000f) != dcb->type)
+		return false;
+	if (!(hash & (dcb->or << 16)))
+		return false;
 
-	switch (dcbent->type) {
+	switch (dcb->type) {
 	case OUTPUT_TMDS:
 	case OUTPUT_LVDS:
 	case OUTPUT_DP:
-		break;
-	default:
-		match_link = false;
-		break;
-	}
-
-	for (i = 0; i < record_nr; i++, record += record_len) {
-		table = ROM16(bios->data[record]);
-		if (!table)
-			continue;
-		entry = ROM32(bios->data[table]);
-
-		if (match_link) {
-			v = (entry & 0x00c00000) >> 22;
-			if (!(v & dcbent->sorconf.link))
-				continue;
+		if (hash & 0x00c00000) {
+			if (!(hash & (dcb->sorconf.link << 22)))
+				return false;
 		}
-
-		v = (entry & 0x000f0000) >> 16;
-		if (!(v & dcbent->or))
-			continue;
-
-		v = (entry & 0x000000f0) >> 4;
-		if (v != dcbent->location)
-			continue;
-
-		v = (entry & 0x0000000f);
-		if (v != dcbent->type)
-			continue;
-
-		return &bios->data[table];
-	}
-
-	return NULL;
-}
-
-void *
-nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
-		      int *length)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->vbios;
-	uint8_t *table;
-
-	if (!bios->display.dp_table_ptr) {
-		NV_ERROR(dev, "No pointer to DisplayPort table\n");
-		return NULL;
-	}
-	table = &bios->data[bios->display.dp_table_ptr];
-
-	if (table[0] != 0x20 && table[0] != 0x21) {
-		NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
-			 table[0]);
-		return NULL;
+	default:
+		return true;
 	}
-
-	*length = table[4];
-	return bios_output_config_match(dev, dcbent,
-					bios->display.dp_table_ptr + table[1],
-					table[2], table[3], table[0] >= 0x21);
 }
 
 int
-nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
-			       uint32_t sub, int pxclk)
+nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
+			       struct dcb_entry *dcbent, int crtc)
 {
 	/*
 	 * The display script table is located by the BIT 'U' table.
@@ -4498,7 +4488,7 @@ nouveau_bios_run_display_table(struct dr
 	uint8_t *table = &bios->data[bios->display.script_table_ptr];
 	uint8_t *otable = NULL;
 	uint16_t script;
-	int i = 0;
+	int i;
 
 	if (!bios->display.script_table_ptr) {
 		NV_ERROR(dev, "No pointer to output script table\n");
@@ -4550,30 +4540,33 @@ nouveau_bios_run_display_table(struct dr
 
 	NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
 			dcbent->type, dcbent->location, dcbent->or);
-	otable = bios_output_config_match(dev, dcbent, table[1] +
-					  bios->display.script_table_ptr,
-					  table[2], table[3], table[0] >= 0x21);
+	for (i = 0; i < table[3]; i++) {
+		otable = ROMPTR(bios, table[table[1] + (i * table[2])]);
+		if (otable && bios_encoder_match(dcbent, ROM32(otable[0])))
+			break;
+	}
+
 	if (!otable) {
 		NV_DEBUG_KMS(dev, "failed to match any output table\n");
 		return 1;
 	}
 
-	if (pxclk < -2 || pxclk > 0) {
+	if (pclk < -2 || pclk > 0) {
 		/* Try to find matching script table entry */
 		for (i = 0; i < otable[5]; i++) {
-			if (ROM16(otable[table[4] + i*6]) == sub)
+			if (ROM16(otable[table[4] + i*6]) == type)
 				break;
 		}
 
 		if (i == otable[5]) {
 			NV_ERROR(dev, "Table 0x%04x not found for %d/%d, "
 				      "using first\n",
-				 sub, dcbent->type, dcbent->or);
+				 type, dcbent->type, dcbent->or);
 			i = 0;
 		}
 	}
 
-	if (pxclk == 0) {
+	if (pclk == 0) {
 		script = ROM16(otable[6]);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "output script 0 not found\n");
@@ -4581,9 +4574,9 @@ nouveau_bios_run_display_table(struct dr
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk == -1) {
+	if (pclk == -1) {
 		script = ROM16(otable[8]);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "output script 1 not found\n");
@@ -4591,9 +4584,9 @@ nouveau_bios_run_display_table(struct dr
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk == -2) {
+	if (pclk == -2) {
 		if (table[4] >= 12)
 			script = ROM16(otable[10]);
 		else
@@ -4604,31 +4597,31 @@ nouveau_bios_run_display_table(struct dr
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk > 0) {
+	if (pclk > 0) {
 		script = ROM16(otable[table[4] + i*6 + 2]);
 		if (script)
-			script = clkcmptable(bios, script, pxclk);
+			script = clkcmptable(bios, script, pclk);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "clock script 0 not found\n");
 			return 1;
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk < 0) {
+	if (pclk < 0) {
 		script = ROM16(otable[table[4] + i*6 + 4]);
 		if (script)
-			script = clkcmptable(bios, script, -pxclk);
+			script = clkcmptable(bios, script, -pclk);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "clock script 1 not found\n");
 			return 1;
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	}
 
 	return 0;
@@ -5478,14 +5471,6 @@ parse_bit_U_tbl_entry(struct drm_device
 	return 0;
 }
 
-static int
-parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios,
-				struct bit_entry *bitentry)
-{
-	bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]);
-	return 0;
-}
-
 struct bit_table {
 	const char id;
 	int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *);
@@ -5559,7 +5544,6 @@ parse_bit_structure(struct nvbios *bios,
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U));
-	parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport));
 
 	return 0;
 }
@@ -5884,9 +5868,15 @@ parse_dcb_gpio_table(struct nvbios *bios
 			}
 
 			e->line = (e->entry & 0x0000001f) >> 0;
-			e->state_default = (e->entry & 0x01000000) >> 24;
-			e->state[0] = (e->entry & 0x18000000) >> 27;
-			e->state[1] = (e->entry & 0x60000000) >> 29;
+			if (gpio[0] == 0x40) {
+				e->state_default = (e->entry & 0x01000000) >> 24;
+				e->state[0] = (e->entry & 0x18000000) >> 27;
+				e->state[1] = (e->entry & 0x60000000) >> 29;
+			} else {
+				e->state_default = (e->entry & 0x00000080) >> 7;
+				e->state[0] = (entry[4] >> 4) & 3;
+				e->state[1] = (entry[4] >> 6) & 3;
+			}
 		}
 	}
 
@@ -6156,7 +6146,14 @@ parse_dcb20_entry(struct drm_device *dev
 	}
 	case OUTPUT_DP:
 		entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
-		entry->dpconf.link_bw = (conf & 0x00e00000) >> 21;
+		switch ((conf & 0x00e00000) >> 21) {
+		case 0:
+			entry->dpconf.link_bw = 162000;
+			break;
+		default:
+			entry->dpconf.link_bw = 270000;
+			break;
+		}
 		switch ((conf & 0x0f000000) >> 24) {
 		case 0xf:
 			entry->dpconf.link_nr = 4;
@@ -6769,7 +6766,7 @@ uint8_t *nouveau_bios_embedded_edid(stru
 
 void
 nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
-			    struct dcb_entry *dcbent)
+			    struct dcb_entry *dcbent, int crtc)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nvbios *bios = &dev_priv->vbios;
@@ -6777,11 +6774,22 @@ nouveau_bios_run_init_table(struct drm_d
 
 	spin_lock_bh(&bios->lock);
 	bios->display.output = dcbent;
+	bios->display.crtc = crtc;
 	parse_init_table(bios, table, &iexec);
 	bios->display.output = NULL;
 	spin_unlock_bh(&bios->lock);
 }
 
+void
+nouveau_bios_init_exec(struct drm_device *dev, uint16_t table)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	struct init_exec iexec = { true, false };
+
+	parse_init_table(bios, table, &iexec);
+}
+
 static bool NVInitVBIOS(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -6863,9 +6871,8 @@ nouveau_run_vbios_init(struct drm_device
 
 	if (dev_priv->card_type >= NV_50) {
 		for (i = 0; i < bios->dcb.entries; i++) {
-			nouveau_bios_run_display_table(dev,
-						       &bios->dcb.entry[i],
-						       0, 0);
+			nouveau_bios_run_display_table(dev, 0, 0,
+						       &bios->dcb.entry[i], -1);
 		}
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.h	2012-01-04 18:55:44.000000000 -0500
@@ -289,8 +289,8 @@ struct nvbios {
 
 	struct {
 		struct dcb_entry *output;
+		int crtc;
 		uint16_t script_table_ptr;
-		uint16_t dp_table_ptr;
 	} display;
 
 	struct {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@ set_placement_range(struct nouveau_bo *n
 
 	if (dev_priv->card_type == NV_10 &&
 	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
-	    nvbo->bo.mem.num_pages < vram_pages / 2) {
+	    nvbo->bo.mem.num_pages < vram_pages / 4) {
 		/*
 		 * Make sure that the color and depth buffers are handled
 		 * by independent memory controller units. Up to a 9x
@@ -956,7 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 			break;
 		}
 
-		if (dev_priv->card_type == NV_C0)
+		if (dev_priv->card_type >= NV_C0)
 			page_shift = node->page_shift;
 		else
 			page_shift = 12;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
 
 	/* setup channel's memory and vm */
 	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
@@ -411,13 +412,17 @@ nouveau_ioctl_fifo_alloc(struct drm_devi
 		return ret;
 	init->channel  = chan->id;
 
-	if (chan->dma.ib_max)
-		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
-					NOUVEAU_GEM_DOMAIN_GART;
-	else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+	if (nouveau_vram_pushbuf == 0) {
+		if (chan->dma.ib_max)
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+						NOUVEAU_GEM_DOMAIN_GART;
+		else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
+		else
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+	} else {
 		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
-	else
-		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+	}
 
 	if (dev_priv->card_type < NV_C0) {
 		init->subchan[0].handle = NvM2MF;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 static void nouveau_connector_hotplug(void *, int);
 
-static struct nouveau_encoder *
+struct nouveau_encoder *
 find_encoder(struct drm_connector *connector, int type)
 {
 	struct drm_device *dev = connector->dev;
@@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_con
 				      nouveau_connector_hotplug, connector);
 	}
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
-	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-		nouveau_backlight_exit(connector);
-
 	kfree(nv_connector->edid);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -712,12 +708,9 @@ nouveau_connector_mode_valid(struct drm_
 	case OUTPUT_TV:
 		return get_slave_funcs(encoder)->mode_valid(encoder, mode);
 	case OUTPUT_DP:
-		if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
-			max_clock = nv_encoder->dp.link_nr * 270000;
-		else
-			max_clock = nv_encoder->dp.link_nr * 162000;
-
-		clock = clock * nouveau_connector_bpp(connector) / 8;
+		max_clock  = nv_encoder->dp.link_nr;
+		max_clock *= nv_encoder->dp.link_bw;
+		clock = clock * nouveau_connector_bpp(connector) / 10;
 		break;
 	default:
 		BUG_ON(1);
@@ -871,7 +864,6 @@ nouveau_connector_create(struct drm_devi
 					dev->mode_config.scaling_mode_property,
 					nv_connector->scaling_mode);
 		}
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 		/* fall-through */
 	case DCB_CONNECTOR_TV_0:
 	case DCB_CONNECTOR_TV_1:
@@ -888,27 +880,20 @@ nouveau_connector_create(struct drm_devi
 				dev->mode_config.dithering_mode_property,
 				nv_connector->use_dithering ?
 				DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
-
-		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) {
-			if (dev_priv->card_type >= NV_50)
-				connector->polled = DRM_CONNECTOR_POLL_HPD;
-			else
-				connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-		}
 		break;
 	}
 
-	if (pgpio->irq_register) {
+	if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) {
 		pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
 				    nouveau_connector_hotplug, connector);
+
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	} else {
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 	}
 
 	drm_sysfs_connector_add(connector);
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
-	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-		nouveau_backlight_init(connector);
-
 	dcb->drm = connector;
 	return dcb->drm;
 
@@ -925,22 +910,13 @@ nouveau_connector_hotplug(void *data, in
 	struct drm_connector *connector = data;
 	struct drm_device *dev = connector->dev;
 
-	NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
-		drm_get_connector_name(connector));
-
-	if (connector->encoder && connector->encoder->crtc &&
-	    connector->encoder->crtc->enabled) {
-		struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder);
-		struct drm_encoder_helper_funcs *helper =
-			connector->encoder->helper_private;
+	NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un",
+		 drm_get_connector_name(connector));
 
-		if (nv_encoder->dcb->type == OUTPUT_DP) {
-			if (plugged)
-				helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
-			else
-				helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
-		}
-	}
+	if (plugged)
+		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+	else
+		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
 
 	drm_helper_hpd_irq_event(dev);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_crtc.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_crtc.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_crtc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_crtc.h	2012-01-04 18:55:44.000000000 -0500
@@ -82,14 +82,13 @@ static inline struct drm_crtc *to_drm_cr
 }
 
 int nv50_crtc_create(struct drm_device *dev, int index);
-int nv50_cursor_init(struct nouveau_crtc *);
-void nv50_cursor_fini(struct nouveau_crtc *);
 int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
 			 uint32_t buffer_handle, uint32_t width,
 			 uint32_t height);
 int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
 
 int nv04_cursor_init(struct nouveau_crtc *);
+int nv50_cursor_init(struct nouveau_crtc *);
 
 struct nouveau_connector *
 nouveau_crtc_connector_get(struct nouveau_crtc *crtc);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,9 +105,12 @@ nouveau_framebuffer_init(struct drm_devi
 		if (dev_priv->chipset == 0x50)
 			nv_fb->r_format |= (tile_flags << 8);
 
-		if (!tile_flags)
-			nv_fb->r_pitch = 0x00100000 | fb->pitch;
-		else {
+		if (!tile_flags) {
+			if (dev_priv->card_type < NV_D0)
+				nv_fb->r_pitch = 0x00100000 | fb->pitch;
+			else
+				nv_fb->r_pitch = 0x01000000 | fb->pitch;
+		} else {
 			u32 mode = nvbo->tile_mode;
 			if (dev_priv->card_type >= NV_C0)
 				mode >>= 4;
@@ -366,3 +369,48 @@ nouveau_finish_page_flip(struct nouveau_
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 	return 0;
 }
+
+int
+nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
+			    struct drm_mode_create_dumb *args)
+{
+	struct nouveau_bo *bo;
+	int ret;
+
+	args->pitch = roundup(args->width * (args->bpp / 8), 256);
+	args->size = args->pitch * args->height;
+	args->size = roundup(args->size, PAGE_SIZE);
+
+	ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
+	if (ret)
+		return ret;
+
+	ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle);
+	drm_gem_object_unreference_unlocked(bo->gem);
+	return ret;
+}
+
+int
+nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+			     uint32_t handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
+
+int
+nouveau_display_dumb_map_offset(struct drm_file *file_priv,
+				struct drm_device *dev,
+				uint32_t handle, uint64_t *poffset)
+{
+	struct drm_gem_object *gem;
+
+	gem = drm_gem_object_lookup(dev, file_priv, handle);
+	if (gem) {
+		struct nouveau_bo *bo = gem->driver_private;
+		*poffset = bo->bo.addr_space_offset;
+		drm_gem_object_unreference_unlocked(gem);
+		return 0;
+	}
+
+	return -ENOENT;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,557 +28,669 @@
 #include "nouveau_i2c.h"
 #include "nouveau_connector.h"
 #include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
 
-static int
-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_i2c_chan *auxch;
-	int ret;
-
-	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-	if (!auxch)
-		return -ENODEV;
-
-	ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
-	if (ret)
-		return ret;
+/******************************************************************************
+ * aux channel util functions
+ *****************************************************************************/
+#define AUX_DBG(fmt, args...) do {                                             \
+	if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) {                     \
+		NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args);     \
+	}                                                                      \
+} while (0)
+#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args)
 
-	return 0;
+static void
+auxch_fini(struct drm_device *dev, int ch)
+{
+	nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
 }
 
 static int
-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+auxch_init(struct drm_device *dev, int ch)
 {
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_i2c_chan *auxch;
-	int ret;
+	const u32 unksel = 1; /* nfi which to use, or if it matters.. */
+	const u32 ureq = unksel ? 0x00100000 : 0x00200000;
+	const u32 urep = unksel ? 0x01000000 : 0x02000000;
+	u32 ctrl, timeout;
 
-	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-	if (!auxch)
-		return -ENODEV;
+	/* wait up to 1ms for any previous transaction to be done... */
+	timeout = 1000;
+	do {
+		ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+		udelay(1);
+		if (!timeout--) {
+			AUX_ERR("begin idle timeout 0x%08x", ctrl);
+			return -EBUSY;
+		}
+	} while (ctrl & 0x03010000);
 
-	ret = nouveau_dp_auxch(auxch, 8, address, buf, size);
-	return ret;
+	/* set some magic, and wait up to 1ms for it to appear */
+	nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
+	timeout = 1000;
+	do {
+		ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+		udelay(1);
+		if (!timeout--) {
+			AUX_ERR("magic wait 0x%08x\n", ctrl);
+			auxch_fini(dev, ch);
+			return -EBUSY;
+		}
+	} while ((ctrl & 0x03000000) != urep);
+
+	return 0;
 }
 
 static int
-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd)
+auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
 {
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
+	u32 ctrl, stat, timeout, retries;
+	u32 xbuf[4] = {};
+	int ret, i;
 
-	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-	tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED |
-		 NV50_SOR_DP_CTRL_LANE_MASK);
-	tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16;
-	if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN)
-		tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED;
-	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+	AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
 
-	return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1);
-}
+	ret = auxch_init(dev, ch);
+	if (ret)
+		goto out;
 
-static int
-nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	int reg = 0x614300 + (nv_encoder->or * 0x800);
+	stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50));
+	if (!(stat & 0x10000000)) {
+		AUX_DBG("sink not detected\n");
+		ret = -ENXIO;
+		goto out;
+	}
 
-	tmp  = nv_rd32(dev, reg);
-	tmp &= 0xfff3ffff;
-	if (cmd == DP_LINK_BW_2_7)
-		tmp |= 0x00040000;
-	nv_wr32(dev, reg, tmp);
+	if (!(type & 1)) {
+		memcpy(xbuf, data, size);
+		for (i = 0; i < 16; i += 4) {
+			AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
+			nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
+		}
+	}
 
-	return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1);
-}
+	ctrl  = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+	ctrl &= ~0x0001f0ff;
+	ctrl |= type << 12;
+	ctrl |= size - 1;
+	nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr);
 
-static int
-nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	uint8_t cmd;
-	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
-	int ret;
+	/* retry transaction a number of times on failure... */
+	ret = -EREMOTEIO;
+	for (retries = 0; retries < 32; retries++) {
+		/* reset, and delay a while if this is a retry */
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
+		if (retries)
+			udelay(400);
 
-	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-	tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN;
-	tmp |= (pattern << 24);
-	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+		/* transaction request, wait up to 1ms for it to complete */
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
 
-	ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
-	if (ret)
-		return ret;
-	cmd &= ~DP_TRAINING_PATTERN_MASK;
-	cmd |= (pattern & DP_TRAINING_PATTERN_MASK);
-	return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
-}
+		timeout = 1000;
+		do {
+			ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+			udelay(1);
+			if (!timeout--) {
+				AUX_ERR("tx req timeout 0x%08x\n", ctrl);
+				goto out;
+			}
+		} while (ctrl & 0x00010000);
 
-static int
-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder)
-{
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table_entry *dpse;
-	struct bit_displayport_encoder_table *dpe;
-	int i, dpe_headerlen, max_vs = 0;
+		/* read status, and check if transaction completed ok */
+		stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0);
+		if (!(stat & 0x000f0f00)) {
+			ret = 0;
+			break;
+		}
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
+		AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
+	}
 
-	for (i = 0; i < dpe_headerlen; i++, dpse++) {
-		if (dpse->vs_level > max_vs)
-			max_vs = dpse->vs_level;
+	if (type & 1) {
+		for (i = 0; i < 16; i += 4) {
+			xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i);
+			AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
+		}
+		memcpy(data, xbuf, size);
 	}
 
-	return max_vs;
+out:
+	auxch_fini(dev, ch);
+	return ret;
 }
 
-static int
-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs)
+static u32
+dp_link_bw_get(struct drm_device *dev, int or, int link)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table_entry *dpse;
-	struct bit_displayport_encoder_table *dpe;
-	int i, dpe_headerlen, max_pre = 0;
-
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
-
-	for (i = 0; i < dpe_headerlen; i++, dpse++) {
-		if (dpse->vs_level != vs)
-			continue;
+	u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800));
+	if (!(ctrl & 0x000c0000))
+		return 162000;
+	return 270000;
+}
 
-		if (dpse->pre_level > max_pre)
-			max_pre = dpse->pre_level;
+static int
+dp_lane_count_get(struct drm_device *dev, int or, int link)
+{
+	u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
+	switch (ctrl & 0x000f0000) {
+	case 0x00010000: return 1;
+	case 0x00030000: return 2;
+	default:
+		return 4;
 	}
-
-	return max_pre;
 }
 
-static bool
-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
+void
+nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table *dpe;
-	int ret, i, dpe_headerlen, vs = 0, pre = 0;
-	uint8_t request[2];
+	const u32 symbol = 100000;
+	int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
+	int TU, VTUi, VTUf, VTUa;
+	u64 link_data_rate, link_ratio, unk;
+	u32 best_diff = 64 * symbol;
+	u32 link_nr, link_bw, r;
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
+	/* calculate packed data rate for each lane */
+	link_nr = dp_lane_count_get(dev, or, link);
+	link_data_rate = (clk * bpp / 8) / link_nr;
 
-	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
-	if (ret)
-		return false;
+	/* calculate ratio of packed data rate to link symbol rate */
+	link_bw = dp_link_bw_get(dev, or, link);
+	link_ratio = link_data_rate * symbol;
+	r = do_div(link_ratio, link_bw);
 
-	NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
+	for (TU = 64; TU >= 32; TU--) {
+		/* calculate average number of valid symbols in each TU */
+		u32 tu_valid = link_ratio * TU;
+		u32 calc, diff;
 
-	/* Keep all lanes at the same level.. */
-	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-		int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf;
-		int lane_vs = lane_req & 3;
-		int lane_pre = (lane_req >> 2) & 3;
+		/* find a hw representation for the fraction.. */
+		VTUi = tu_valid / symbol;
+		calc = VTUi * symbol;
+		diff = tu_valid - calc;
+		if (diff) {
+			if (diff >= (symbol / 2)) {
+				VTUf = symbol / (symbol - diff);
+				if (symbol - (VTUf * diff))
+					VTUf++;
 
-		if (lane_vs > vs)
-			vs = lane_vs;
-		if (lane_pre > pre)
-			pre = lane_pre;
-	}
+				if (VTUf <= 15) {
+					VTUa  = 1;
+					calc += symbol - (symbol / VTUf);
+				} else {
+					VTUa  = 0;
+					VTUf  = 1;
+					calc += symbol;
+				}
+			} else {
+				VTUa  = 0;
+				VTUf  = min((int)(symbol / diff), 15);
+				calc += symbol / VTUf;
+			}
 
-	if (vs >= nouveau_dp_max_voltage_swing(encoder)) {
-		vs  = nouveau_dp_max_voltage_swing(encoder);
-		vs |= 4;
+			diff = calc - tu_valid;
+		} else {
+			/* no remainder, but the hw doesn't like the fractional
+			 * part to be zero.  decrement the integer part and
+			 * have the fraction add a whole symbol back
+			 */
+			VTUa = 0;
+			VTUf = 1;
+			VTUi--;
+		}
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			bestTU = TU;
+			bestVTUa = VTUa;
+			bestVTUf = VTUf;
+			bestVTUi = VTUi;
+			if (diff == 0)
+				break;
+		}
 	}
 
-	if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) {
-		pre  = nouveau_dp_max_pre_emphasis(encoder, vs & 3);
-		pre |= 4;
+	if (!bestTU) {
+		NV_ERROR(dev, "DP: unable to find suitable config\n");
+		return;
 	}
 
-	/* Update the configuration for all lanes.. */
-	for (i = 0; i < nv_encoder->dp.link_nr; i++)
-		config[i] = (pre << 3) | vs;
+	/* XXX close to vbios numbers, but not right */
+	unk  = (symbol - link_ratio) * bestTU;
+	unk *= link_ratio;
+	r = do_div(unk, symbol);
+	r = do_div(unk, symbol);
+	unk += 6;
 
-	return true;
+	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2);
+	nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 |
+							     bestVTUf << 16 |
+							     bestVTUi << 8 |
+							     unk);
 }
 
-static bool
-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config)
+u8 *
+nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table_entry *dpse;
-	struct bit_displayport_encoder_table *dpe;
-	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
-	int dpe_headerlen, ret, i;
-
-	NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		 config[0], config[1], config[2], config[3]);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	struct bit_entry d;
+	u8 *table;
+	int i;
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
+	if (bit_table(dev, 'd', &d)) {
+		NV_ERROR(dev, "BIT 'd' table not found\n");
+		return NULL;
+	}
 
-	for (i = 0; i < dpe->record_nr; i++, dpse++) {
-		if (dpse->vs_level == (config[0] & 3) &&
-		    dpse->pre_level == ((config[0] >> 3) & 3))
-			break;
+	if (d.version != 1) {
+		NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version);
+		return NULL;
 	}
-	BUG_ON(i == dpe->record_nr);
 
-	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-		const int shift[4] = { 16, 8, 0, 24 };
-		uint32_t mask = 0xff << shift[i];
-		uint32_t reg0, reg1, reg2;
+	table = ROMPTR(bios, d.data[0]);
+	if (!table) {
+		NV_ERROR(dev, "displayport table pointer invalid\n");
+		return NULL;
+	}
 
-		reg0  = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask;
-		reg0 |= (dpse->reg0 << shift[i]);
-		reg1  = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask;
-		reg1 |= (dpse->reg1 << shift[i]);
-		reg2  = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff;
-		reg2 |= (dpse->reg2 << 8);
-		nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0);
-		nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1);
-		nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2);
+	switch (table[0]) {
+	case 0x20:
+	case 0x21:
+	case 0x30:
+		break;
+	default:
+		NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]);
+		return NULL;
 	}
 
-	ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4);
-	if (ret)
-		return false;
+	for (i = 0; i < table[3]; i++) {
+		*entry = ROMPTR(bios, table[table[1] + (i * table[2])]);
+		if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
+			return table;
+	}
 
-	return true;
+	NV_ERROR(dev, "displayport encoder table not found\n");
+	return NULL;
 }
 
-bool
-nouveau_dp_link_train(struct drm_encoder *encoder)
+/******************************************************************************
+ * link training
+ *****************************************************************************/
+struct dp_state {
+	struct dcb_entry *dcb;
+	u8 *table;
+	u8 *entry;
+	int auxch;
+	int crtc;
+	int or;
+	int link;
+	u8 *dpcd;
+	int link_nr;
+	u32 link_bw;
+	u8  stat[6];
+	u8  conf[4];
+};
+
+static void
+dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
 {
-	struct drm_device *dev = encoder->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_connector *nv_connector;
-	struct bit_displayport_encoder_table *dpe;
-	int dpe_headerlen;
-	uint8_t config[4], status[3];
-	bool cr_done, cr_max_vs, eq_done, hpd_state;
-	int ret = 0, i, tries, voltage;
-
-	NV_DEBUG_KMS(dev, "link training!!\n");
+	int or = dp->or, link = dp->link;
+	u8 *entry, sink[2];
+	u32 dp_ctrl;
+	u16 script;
 
-	nv_connector = nouveau_encoder_connector_get(nv_encoder);
-	if (!nv_connector)
-		return false;
+	NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe) {
-		NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
-		return false;
+	/* set selected link rate on source */
+	switch (dp->link_bw) {
+	case 270000:
+		nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000);
+		sink[0] = DP_LINK_BW_2_7;
+		break;
+	default:
+		nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000);
+		sink[0] = DP_LINK_BW_1_62;
+		break;
 	}
 
-	/* disable hotplug detect, this flips around on some panels during
-	 * link training.
+	/* offset +0x0a of each dp encoder table entry is a pointer to another
+	 * table, that has (among other things) pointers to more scripts that
+	 * need to be executed, this time depending on link speed.
 	 */
-	hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+	entry = ROMPTR(&dev_priv->vbios, dp->entry[10]);
+	if (entry) {
+		if (dp->table[0] < 0x30) {
+			while (dp->link_bw < (ROM16(entry[0]) * 10))
+				entry += 4;
+			script = ROM16(entry[2]);
+		} else {
+			while (dp->link_bw < (entry[0] * 27000))
+				entry += 3;
+			script = ROM16(entry[1]);
+		}
 
-	if (dpe->script0) {
-		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
-		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
-					    nv_encoder->dcb);
+		nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
 	}
 
-train:
-	cr_done = eq_done = false;
+	/* configure lane count on the source */
+	dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
+	sink[1] = dp->link_nr;
+	if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
+		dp_ctrl |= 0x00004000;
+		sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
 
-	/* set link configuration */
-	NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n",
-		 nv_encoder->dp.link_bw, nv_encoder->dp.link_nr);
+	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl);
 
-	ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw);
-	if (ret)
-		return false;
+	/* inform the sink of the new configuration */
+	auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2);
+}
 
-	config[0] = nv_encoder->dp.link_nr;
-	if (nv_encoder->dp.dpcd_version >= 0x11 &&
-	    nv_encoder->dp.enhanced_frame)
-		config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+static void
+dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp)
+{
+	u8 sink_tp;
 
-	ret = nouveau_dp_lane_count_set(encoder, config[0]);
-	if (ret)
-		return false;
+	NV_DEBUG_KMS(dev, "training pattern %d\n", tp);
 
-	/* clock recovery */
-	NV_DEBUG_KMS(dev, "\tbegin cr\n");
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1);
-	if (ret)
-		goto stop;
+	nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24);
 
-	tries = 0;
-	voltage = -1;
-	memset(config, 0x00, sizeof(config));
-	for (;;) {
-		if (!nouveau_dp_link_train_commit(encoder, config))
-			break;
+	auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+	sink_tp &= ~DP_TRAINING_PATTERN_MASK;
+	sink_tp |= tp;
+	auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+}
 
-		udelay(100);
+static const u8 nv50_lane_map[] = { 16, 8, 0, 24 };
+static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 };
 
-		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2);
-		if (ret)
-			break;
-		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
-			 status[0], status[1]);
+static int
+dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 mask = 0, drv = 0, pre = 0, unk = 0;
+	const u8 *shifts;
+	int link = dp->link;
+	int or = dp->or;
+	int i;
 
-		cr_done = true;
-		cr_max_vs = false;
-		for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+	if (dev_priv->chipset != 0xaf)
+		shifts = nv50_lane_map;
+	else
+		shifts = nvaf_lane_map;
 
-			if (!(lane & DP_LANE_CR_DONE)) {
-				cr_done = false;
-				if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED)
-					cr_max_vs = true;
-				break;
+	for (i = 0; i < dp->link_nr; i++) {
+		u8 *conf = dp->entry + dp->table[4];
+		u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
+		u8 lpre = (lane & 0x0c) >> 2;
+		u8 lvsw = (lane & 0x03) >> 0;
+
+		mask |= 0xff << shifts[i];
+		unk |= 1 << (shifts[i] >> 3);
+
+		dp->conf[i] = (lpre << 3) | lvsw;
+		if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200)
+			dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED;
+		if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5)
+			dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+		NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]);
+
+		if (dp->table[0] < 0x30) {
+			u8 *last = conf + (dp->entry[4] * dp->table[5]);
+			while (lvsw != conf[0] || lpre != conf[1]) {
+				conf += dp->table[5];
+				if (conf >= last)
+					return -EINVAL;
 			}
-		}
 
-		if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-			voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-			tries = 0;
-		}
+			conf += 2;
+		} else {
+			/* no lookup table anymore, set entries for each
+			 * combination of voltage swing and pre-emphasis
+			 * level allowed by the DP spec.
+			 */
+			switch (lvsw) {
+			case 0: lpre += 0; break;
+			case 1: lpre += 4; break;
+			case 2: lpre += 7; break;
+			case 3: lpre += 9; break;
+			}
 
-		if (cr_done || cr_max_vs || (++tries == 5))
-			break;
+			conf = conf + (lpre * dp->table[5]);
+			conf++;
+		}
 
-		if (!nouveau_dp_link_train_adjust(encoder, config))
-			break;
+		drv |= conf[0] << shifts[i];
+		pre |= conf[1] << shifts[i];
+		unk  = (unk & ~0x0000ff00) | (conf[2] << 8);
 	}
 
-	if (!cr_done)
-		goto stop;
+	nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv);
+	nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre);
+	nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk);
 
-	/* channel equalisation */
-	NV_DEBUG_KMS(dev, "\tbegin eq\n");
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2);
+	return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4);
+}
+
+static int
+dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
+{
+	int ret;
+
+	udelay(delay);
+
+	ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6);
 	if (ret)
-		goto stop;
+		return ret;
 
-	for (tries = 0; tries <= 5; tries++) {
-		udelay(400);
+	NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n",
+		     dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3],
+		     dp->stat[4], dp->stat[5]);
+	return 0;
+}
 
-		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3);
-		if (ret)
-			break;
-		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
-			 status[0], status[1]);
+static int
+dp_link_train_cr(struct drm_device *dev, struct dp_state *dp)
+{
+	bool cr_done = false, abort = false;
+	int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+	int tries = 0, i;
 
-		eq_done = true;
-		if (!(status[2] & DP_INTERLANE_ALIGN_DONE))
-			eq_done = false;
+	dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1);
 
-		for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) {
-			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+	do {
+		if (dp_link_train_commit(dev, dp) ||
+		    dp_link_train_update(dev, dp, 100))
+			break;
 
+		cr_done = true;
+		for (i = 0; i < dp->link_nr; i++) {
+			u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
 			if (!(lane & DP_LANE_CR_DONE)) {
 				cr_done = false;
+				if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED)
+					abort = true;
 				break;
 			}
+		}
 
-			if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
-			    !(lane & DP_LANE_SYMBOL_LOCKED)) {
-				eq_done = false;
-				break;
-			}
+		if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
+			voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+			tries = 0;
 		}
+	} while (!cr_done && !abort && ++tries < 5);
 
-		if (eq_done || !cr_done)
-			break;
+	return cr_done ? 0 : -1;
+}
 
-		if (!nouveau_dp_link_train_adjust(encoder, config) ||
-		    !nouveau_dp_link_train_commit(encoder, config))
-			break;
-	}
+static int
+dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
+{
+	bool eq_done, cr_done = true;
+	int tries = 0, i;
 
-stop:
-	/* end link training */
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE);
-	if (ret)
-		return false;
+	dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2);
 
-	/* retry at a lower setting, if possible */
-	if (!ret && !(eq_done && cr_done)) {
-		NV_DEBUG_KMS(dev, "\twe failed\n");
-		if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) {
-			NV_DEBUG_KMS(dev, "retry link training at low rate\n");
-			nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
-			goto train;
-		}
-	}
+	do {
+		if (dp_link_train_update(dev, dp, 400))
+			break;
 
-	if (dpe->script1) {
-		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
-		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
-					    nv_encoder->dcb);
-	}
+		eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE);
+		for (i = 0; i < dp->link_nr && eq_done; i++) {
+			u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
+			if (!(lane & DP_LANE_CR_DONE))
+				cr_done = false;
+			if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
+			    !(lane & DP_LANE_SYMBOL_LOCKED))
+				eq_done = false;
+		}
 
-	/* re-enable hotplug detect */
-	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state);
+		if (dp_link_train_commit(dev, dp))
+			break;
+	} while (!eq_done && cr_done && ++tries <= 5);
 
-	return eq_done;
+	return eq_done ? 0 : -1;
 }
 
 bool
-nouveau_dp_detect(struct drm_encoder *encoder)
+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
 {
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector =
+		nouveau_encoder_connector_get(nv_encoder);
 	struct drm_device *dev = encoder->dev;
-	uint8_t dpcd[4];
-	int ret;
+	struct nouveau_i2c_chan *auxch;
+	const u32 bw_list[] = { 270000, 162000, 0 };
+	const u32 *link_bw = bw_list;
+	struct dp_state dp;
 
-	ret = auxch_rd(encoder, 0x0000, dpcd, 4);
-	if (ret)
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
 		return false;
 
-	NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n"
-		      "display: link_bw %d, link_nr %d version 0x%02x\n",
-		 nv_encoder->dcb->dpconf.link_bw,
-		 nv_encoder->dcb->dpconf.link_nr,
-		 dpcd[1], dpcd[2] & 0x0f, dpcd[0]);
+	dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry);
+	if (!dp.table)
+		return -EINVAL;
 
-	nv_encoder->dp.dpcd_version = dpcd[0];
+	dp.dcb = nv_encoder->dcb;
+	dp.crtc = nv_crtc->index;
+	dp.auxch = auxch->rd;
+	dp.or = nv_encoder->or;
+	dp.link = !(nv_encoder->dcb->sorconf.link & 1);
+	dp.dpcd = nv_encoder->dp.dpcd;
 
-	nv_encoder->dp.link_bw = dpcd[1];
-	if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 &&
-	    !nv_encoder->dcb->dpconf.link_bw)
-		nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+	/* some sinks toggle hotplug in response to some of the actions
+	 * we take during link training (DP_SET_POWER is one), we need
+	 * to ignore them for the moment to avoid races.
+	 */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
 
-	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
-	if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
-		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+	/* enable down-spreading, if possible */
+	if (dp.table[1] >= 16) {
+		u16 script = ROM16(dp.entry[14]);
+		if (nv_encoder->dp.dpcd[3] & 1)
+			script = ROM16(dp.entry[12]);
 
-	nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP);
+		nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
+	}
 
-	return true;
-}
+	/* execute pre-train script from vbios */
+	nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc);
 
-int
-nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
-		 uint8_t *data, int data_nr)
-{
-	struct drm_device *dev = auxch->dev;
-	uint32_t tmp, ctrl, stat = 0, data32[4] = {};
-	int ret = 0, i, index = auxch->rd;
+	/* start off at highest link rate supported by encoder and display */
+	while (*link_bw > nv_encoder->dp.link_bw)
+		link_bw++;
 
-	NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
+	while (link_bw[0]) {
+		/* find minimum required lane count at this link rate */
+		dp.link_nr = nv_encoder->dp.link_nr;
+		while ((dp.link_nr >> 1) * link_bw[0] > datarate)
+			dp.link_nr >>= 1;
 
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000);
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	if (!(tmp & 0x01000000)) {
-		NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp);
-		ret = -EIO;
-		goto out;
-	}
+		/* drop link rate to minimum with this lane count */
+		while ((link_bw[1] * dp.link_nr) > datarate)
+			link_bw++;
+		dp.link_bw = link_bw[0];
 
-	for (i = 0; i < 3; i++) {
-		tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd));
-		if (tmp & NV50_AUXCH_STAT_STATE_READY)
+		/* program selected link configuration */
+		dp_set_link_config(dev, &dp);
+
+		/* attempt to train the link at this configuration */
+		memset(dp.stat, 0x00, sizeof(dp.stat));
+		if (!dp_link_train_cr(dev, &dp) &&
+		    !dp_link_train_eq(dev, &dp))
 			break;
-		udelay(100);
-	}
 
-	if (i == 3) {
-		ret = -EBUSY;
-		goto out;
+		/* retry at lower rate */
+		link_bw++;
 	}
 
-	if (!(cmd & 1)) {
-		memcpy(data32, data, data_nr);
-		for (i = 0; i < 4; i++) {
-			NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]);
-			nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]);
-		}
-	}
+	/* finish link training */
+	dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE);
 
-	nv_wr32(dev, NV50_AUXCH_ADDR(index), addr);
-	ctrl  = nv_rd32(dev, NV50_AUXCH_CTRL(index));
-	ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN);
-	ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT);
-	ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT);
+	/* execute post-train script from vbios */
+	nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc);
 
-	for (i = 0; i < 16; i++) {
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
-		if (!nv_wait(dev, NV50_AUXCH_CTRL(index),
-			     0x00010000, 0x00000000)) {
-			NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
-				 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
-			ret = -EBUSY;
-			goto out;
-		}
+	/* re-enable hotplug detect */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
+	return true;
+}
 
-		udelay(400);
+bool
+nouveau_dp_detect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_i2c_chan *auxch;
+	u8 *dpcd = nv_encoder->dp.dpcd;
+	int ret;
 
-		stat = nv_rd32(dev, NV50_AUXCH_STAT(index));
-		if ((stat & NV50_AUXCH_STAT_REPLY_AUX) !=
-			    NV50_AUXCH_STAT_REPLY_AUX_DEFER)
-			break;
-	}
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
+		return false;
 
-	if (i == 16) {
-		NV_ERROR(dev, "auxch DEFER too many times, bailing\n");
-		ret = -EREMOTEIO;
-		goto out;
-	}
+	ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
+	if (ret)
+		return false;
 
-	if (cmd & 1) {
-		if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
-			ret = -EREMOTEIO;
-			goto out;
-		}
+	nv_encoder->dp.link_bw = 27000 * dpcd[1];
+	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
 
-		for (i = 0; i < 4; i++) {
-			data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
-			NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
-		}
-		memcpy(data, data32, data_nr);
-	}
+	NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
+		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
+	NV_DEBUG_KMS(dev, "encoder: %dx%d\n",
+		     nv_encoder->dcb->dpconf.link_nr,
+		     nv_encoder->dcb->dpconf.link_bw);
 
-out:
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000);
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	if (tmp & 0x01000000) {
-		NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp);
-		ret = -EIO;
-	}
+	if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr)
+		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+	if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
+		nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
 
-	udelay(400);
+	NV_DEBUG_KMS(dev, "maximum: %dx%d\n",
+		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
-	return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY);
+	return true;
+}
+
+int
+nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
+		 uint8_t *data, int data_nr)
+{
+	return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr);
 }
 
 static int
 nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap;
-	struct drm_device *dev = auxch->dev;
 	struct i2c_msg *msg = msgs;
 	int ret, mcnt = num;
 
@@ -602,19 +714,6 @@ nouveau_dp_i2c_xfer(struct i2c_adapter *
 			if (ret < 0)
 				return ret;
 
-			switch (ret & NV50_AUXCH_STAT_REPLY_I2C) {
-			case NV50_AUXCH_STAT_REPLY_I2C_ACK:
-				break;
-			case NV50_AUXCH_STAT_REPLY_I2C_NACK:
-				return -EREMOTEIO;
-			case NV50_AUXCH_STAT_REPLY_I2C_DEFER:
-				udelay(100);
-				continue;
-			default:
-				NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret);
-				return -EREMOTEIO;
-			}
-
 			ptr += cnt;
 			remaining -= cnt;
 		}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
  */
 
 #include <linux/console.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -41,7 +42,7 @@ int nouveau_agpmode = -1;
 module_param_named(agpmode, nouveau_agpmode, int, 0400);
 
 MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
-static int nouveau_modeset = -1; /* kms */
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 MODULE_PARM_DESC(vbios, "Override default VBIOS location");
@@ -432,6 +433,10 @@ static struct drm_driver driver = {
 	.gem_open_object = nouveau_gem_object_open,
 	.gem_close_object = nouveau_gem_object_close,
 
+	.dumb_create = nouveau_display_dumb_create,
+	.dumb_map_offset = nouveau_display_dumb_map_offset,
+	.dumb_destroy = nouveau_display_dumb_destroy,
+
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 #ifdef GIT_REVISION
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -414,12 +414,13 @@ struct nouveau_gpio_engine {
 };
 
 struct nouveau_pm_voltage_level {
-	u8 voltage;
-	u8 vid;
+	u32 voltage; /* microvolts */
+	u8  vid;
 };
 
 struct nouveau_pm_voltage {
 	bool supported;
+	u8 version;
 	u8 vid_mask;
 
 	struct nouveau_pm_voltage_level *level;
@@ -428,17 +429,48 @@ struct nouveau_pm_voltage {
 
 struct nouveau_pm_memtiming {
 	int id;
-	u32 reg_100220;
-	u32 reg_100224;
-	u32 reg_100228;
-	u32 reg_10022c;
-	u32 reg_100230;
-	u32 reg_100234;
-	u32 reg_100238;
-	u32 reg_10023c;
-	u32 reg_100240;
+	u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */
+	u32 reg_1;
+	u32 reg_2;
+	u32 reg_3;
+	u32 reg_4;
+	u32 reg_5;
+	u32 reg_6;
+	u32 reg_7;
+	u32 reg_8;
+	/* To be written to 0x1002c0 */
+	u8 CL;
+	u8 WR;
+};
+
+struct nouveau_pm_tbl_header{
+	u8 version;
+	u8 header_len;
+	u8 entry_cnt;
+	u8 entry_len;
+};
+
+struct nouveau_pm_tbl_entry{
+	u8 tWR;
+	u8 tUNK_1;
+	u8 tCL;
+	u8 tRP;		/* Byte 3 */
+	u8 empty_4;
+	u8 tRAS;	/* Byte 5 */
+	u8 empty_6;
+	u8 tRFC;	/* Byte 7 */
+	u8 empty_8;
+	u8 tRC;		/* Byte 9 */
+	u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
+	u8 empty_15,empty_16,empty_17;
+	u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
 };
 
+/* nouveau_mem.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing);
+
 #define NOUVEAU_PM_MAX_LEVEL 8
 struct nouveau_pm_level {
 	struct device_attribute dev_attr;
@@ -448,11 +480,19 @@ struct nouveau_pm_level {
 	u32 core;
 	u32 memory;
 	u32 shader;
-	u32 unk05;
-	u32 unk0a;
+	u32 rop;
+	u32 copy;
+	u32 daemon;
+	u32 vdec;
+	u32 unk05;	/* nv50:nva3, roughly.. */
+	u32 unka0;	/* nva3:nvc0 */
+	u32 hub01;	/* nvc0- */
+	u32 hub06;	/* nvc0- */
+	u32 hub07;	/* nvc0- */
 
-	u8 voltage;
-	u8 fanspeed;
+	u32 volt_min; /* microvolts */
+	u32 volt_max;
+	u8  fanspeed;
 
 	u16 memscript;
 	struct nouveau_pm_memtiming *timing;
@@ -496,6 +536,11 @@ struct nouveau_pm_engine {
 	void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *,
 			   u32 id, int khz);
 	void (*clock_set)(struct drm_device *, void *);
+
+	int  (*clocks_get)(struct drm_device *, struct nouveau_pm_level *);
+	void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *);
+	void (*clocks_set)(struct drm_device *, void *);
+
 	int (*voltage_get)(struct drm_device *);
 	int (*voltage_set)(struct drm_device *, int voltage);
 	int (*fanspeed_get)(struct drm_device *);
@@ -504,7 +549,7 @@ struct nouveau_pm_engine {
 };
 
 struct nouveau_vram_engine {
-	struct nouveau_mm *mm;
+	struct nouveau_mm mm;
 
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *dev);
@@ -623,6 +668,7 @@ enum nouveau_card_type {
 	NV_40      = 0x40,
 	NV_50      = 0x50,
 	NV_C0      = 0xc0,
+	NV_D0      = 0xd0
 };
 
 struct drm_nouveau_private {
@@ -633,8 +679,8 @@ struct drm_nouveau_private {
 	enum nouveau_card_type card_type;
 	/* exact chipset, derived from NV_PMC_BOOT_0 */
 	int chipset;
-	int stepping;
 	int flags;
+	u32 crystal;
 
 	void __iomem *mmio;
 
@@ -721,7 +767,6 @@ struct drm_nouveau_private {
 	uint64_t vram_size;
 	uint64_t vram_sys_base;
 
-	uint64_t fb_phys;
 	uint64_t fb_available_size;
 	uint64_t fb_mappable_pages;
 	uint64_t fb_aper_free;
@@ -784,6 +829,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, s
 }
 
 /* nouveau_drv.c */
+extern int nouveau_modeset;
 extern int nouveau_agpmode;
 extern int nouveau_duallink;
 extern int nouveau_uscript_lvds;
@@ -824,6 +870,8 @@ extern bool nouveau_wait_eq(struct drm_d
 			    uint32_t reg, uint32_t mask, uint32_t val);
 extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
 			    uint32_t reg, uint32_t mask, uint32_t val);
+extern bool nouveau_wait_cb(struct drm_device *, u64 timeout,
+			    bool (*cond)(void *), void *);
 extern bool nouveau_wait_for_idle(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
 
@@ -1006,15 +1054,15 @@ static inline int nouveau_acpi_edid(stru
 
 /* nouveau_backlight.c */
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_connector *);
-extern void nouveau_backlight_exit(struct drm_connector *);
+extern int nouveau_backlight_init(struct drm_device *);
+extern void nouveau_backlight_exit(struct drm_device *);
 #else
-static inline int nouveau_backlight_init(struct drm_connector *dev)
+static inline int nouveau_backlight_init(struct drm_device *dev)
 {
 	return 0;
 }
 
-static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
+static inline void nouveau_backlight_exit(struct drm_device *dev) { }
 #endif
 
 /* nouveau_bios.c */
@@ -1022,7 +1070,8 @@ extern int nouveau_bios_init(struct drm_
 extern void nouveau_bios_takedown(struct drm_device *dev);
 extern int nouveau_run_vbios_init(struct drm_device *);
 extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
-					struct dcb_entry *);
+					struct dcb_entry *, int crtc);
+extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table);
 extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
 						      enum dcb_gpio_tag);
 extern struct dcb_connector_table_entry *
@@ -1030,11 +1079,8 @@ nouveau_bios_connector_entry(struct drm_
 extern u32 get_pll_register(struct drm_device *, enum pll_types);
 extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
 			  struct pll_lims *);
-extern int nouveau_bios_run_display_table(struct drm_device *,
-					  struct dcb_entry *,
-					  uint32_t script, int pxclk);
-extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
-				   int *length);
+extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk,
+					  struct dcb_entry *, int crtc);
 extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
 extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
 extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
@@ -1043,6 +1089,7 @@ extern int run_tmds_table(struct drm_dev
 			  int head, int pxclk);
 extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
 			    enum LVDS_script, int pxclk);
+bool bios_encoder_match(struct dcb_entry *, u32 hash);
 
 /* nouveau_ttm.c */
 int nouveau_ttm_global_init(struct drm_nouveau_private *);
@@ -1053,7 +1100,9 @@ int nouveau_ttm_mmap(struct file *, stru
 int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
 		     uint8_t *data, int data_nr);
 bool nouveau_dp_detect(struct drm_encoder *);
-bool nouveau_dp_link_train(struct drm_encoder *);
+bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate);
+void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32);
+u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);
 
 /* nv04_fb.c */
 extern int  nv04_fb_init(struct drm_device *);
@@ -1179,8 +1228,8 @@ extern int  nva3_copy_create(struct drm_
 /* nvc0_copy.c */
 extern int  nvc0_copy_create(struct drm_device *dev, int engine);
 
-/* nv40_mpeg.c */
-extern int  nv40_mpeg_create(struct drm_device *dev);
+/* nv31_mpeg.c */
+extern int  nv31_mpeg_create(struct drm_device *dev);
 
 /* nv50_mpeg.c */
 extern int  nv50_mpeg_create(struct drm_device *dev);
@@ -1265,6 +1314,11 @@ extern int nv04_display_create(struct dr
 extern int nv04_display_init(struct drm_device *);
 extern void nv04_display_destroy(struct drm_device *);
 
+/* nvd0_display.c */
+extern int nvd0_display_create(struct drm_device *);
+extern int nvd0_display_init(struct drm_device *);
+extern void nvd0_display_destroy(struct drm_device *);
+
 /* nv04_crtc.c */
 extern int nv04_crtc_create(struct drm_device *, int index);
 
@@ -1364,6 +1418,12 @@ int nouveau_crtc_page_flip(struct drm_cr
 			   struct drm_pending_vblank_event *event);
 int nouveau_finish_page_flip(struct nouveau_channel *,
 			     struct nouveau_page_flip_state *);
+int nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
+				struct drm_mode_create_dumb *args);
+int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
+				    uint32_t handle, uint64_t *offset);
+int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
+				 uint32_t handle);
 
 /* nv10_gpio.c */
 int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
@@ -1374,6 +1434,8 @@ int nv50_gpio_init(struct drm_device *de
 void nv50_gpio_fini(struct drm_device *dev);
 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 int  nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag,
 			    void (*)(void *, int), void *);
 void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag,
@@ -1448,6 +1510,8 @@ static inline void nv_wr08(struct drm_de
 	nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
 #define nv_wait_ne(dev, reg, mask, val) \
 	nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
+#define nv_wait_cb(dev, func, data) \
+	nouveau_wait_cb(dev, 2000000000ULL, (func), (data))
 
 /* PRAMIN access */
 static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
@@ -1514,6 +1578,7 @@ enum {
 	NOUVEAU_REG_DEBUG_RMVIO          = 0x80,
 	NOUVEAU_REG_DEBUG_VGAATTR        = 0x100,
 	NOUVEAU_REG_DEBUG_EVO            = 0x200,
+	NOUVEAU_REG_DEBUG_AUXCH          = 0x400
 };
 
 #define NV_REG_DEBUG(type, dev, fmt, arg...) do { \
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_encoder.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_encoder.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_encoder.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,17 +49,17 @@ struct nouveau_encoder {
 
 	union {
 		struct {
-			int mc_unknown;
-			uint32_t unk0;
-			uint32_t unk1;
-			int dpcd_version;
+			u8  dpcd[8];
 			int link_nr;
 			int link_bw;
-			bool enhanced_frame;
+			u32 datarate;
 		} dp;
 	};
 };
 
+struct nouveau_encoder *
+find_encoder(struct drm_connector *connector, int type);
+
 static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
 {
 	struct drm_encoder_slave *slave = to_encoder_slave(enc);
@@ -83,21 +83,4 @@ nouveau_encoder_connector_get(struct nou
 int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
 int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
 
-struct bit_displayport_encoder_table {
-	uint32_t match;
-	uint8_t  record_nr;
-	uint8_t  unknown;
-	uint16_t script0;
-	uint16_t script1;
-	uint16_t unknown_table;
-} __attribute__ ((packed));
-
-struct bit_displayport_encoder_table_entry {
-	uint8_t vs_level;
-	uint8_t pre_level;
-	uint8_t reg0;
-	uint8_t reg1;
-	uint8_t reg2;
-} __attribute__ ((packed));
-
 #endif /* __NOUVEAU_ENCODER_H__ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2012-01-04 18:55:44.000000000 -0500
@@ -487,6 +487,7 @@ int nouveau_fbcon_init(struct drm_device
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_fbdev *nfbdev;
+	int preferred_bpp;
 	int ret;
 
 	nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
@@ -505,7 +506,15 @@ int nouveau_fbcon_init(struct drm_device
 	}
 
 	drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
-	drm_fb_helper_initial_config(&nfbdev->helper, 32);
+
+	if (dev_priv->vram_size <= 32 * 1024 * 1024)
+		preferred_bpp = 8;
+	else if (dev_priv->vram_size <= 64 * 1024 * 1024)
+		preferred_bpp = 16;
+	else
+		preferred_bpp = 32;
+
+	drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouvea
 	if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
 		struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
 
-		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY,
 					     mem->start << PAGE_SHIFT,
 					     mem->size, NV_MEM_ACCESS_RW,
 					     NV_MEM_TARGET_VRAM, &obj);
@@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouvea
 			return ret;
 	}
 
-	INIT_LIST_HEAD(&chan->fence.pending);
-	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_i2c.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "nouveau_drv.h"
 #include "nouveau_i2c.h"
@@ -107,6 +109,13 @@ nv4e_i2c_getsda(void *data)
 	return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
 }
 
+static const uint32_t nv50_i2c_port[] = {
+	0x00e138, 0x00e150, 0x00e168, 0x00e180,
+	0x00e254, 0x00e274, 0x00e764, 0x00e780,
+	0x00e79c, 0x00e7b8
+};
+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+
 static int
 nv50_i2c_getscl(void *data)
 {
@@ -130,28 +139,32 @@ static void
 nv50_i2c_setscl(void *data, int state)
 {
 	struct nouveau_i2c_chan *i2c = data;
-	struct drm_device *dev = i2c->dev;
 
-	nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
+	nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
 }
 
 static void
 nv50_i2c_setsda(void *data, int state)
 {
 	struct nouveau_i2c_chan *i2c = data;
-	struct drm_device *dev = i2c->dev;
 
-	nv_wr32(dev, i2c->wr,
-			(nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
+	nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0));
 	i2c->data = state;
 }
 
-static const uint32_t nv50_i2c_port[] = {
-	0x00e138, 0x00e150, 0x00e168, 0x00e180,
-	0x00e254, 0x00e274, 0x00e764, 0x00e780,
-	0x00e79c, 0x00e7b8
-};
-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+static int
+nvd0_i2c_getscl(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10);
+}
+
+static int
+nvd0_i2c_getsda(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
+}
 
 int
 nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
@@ -163,7 +176,8 @@ nouveau_i2c_init(struct drm_device *dev,
 	if (entry->chan)
 		return -EEXIST;
 
-	if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
+	if (dev_priv->card_type >= NV_50 &&
+	    dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) {
 		NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
 		return -EINVAL;
 	}
@@ -192,10 +206,17 @@ nouveau_i2c_init(struct drm_device *dev,
 	case 5:
 		i2c->bit.setsda = nv50_i2c_setsda;
 		i2c->bit.setscl = nv50_i2c_setscl;
-		i2c->bit.getsda = nv50_i2c_getsda;
-		i2c->bit.getscl = nv50_i2c_getscl;
-		i2c->rd = nv50_i2c_port[entry->read];
-		i2c->wr = i2c->rd;
+		if (dev_priv->card_type < NV_D0) {
+			i2c->bit.getsda = nv50_i2c_getsda;
+			i2c->bit.getscl = nv50_i2c_getscl;
+			i2c->rd = nv50_i2c_port[entry->read];
+			i2c->wr = i2c->rd;
+		} else {
+			i2c->bit.getsda = nvd0_i2c_getsda;
+			i2c->bit.getscl = nvd0_i2c_getscl;
+			i2c->rd = 0x00d014 + (entry->read * 0x20);
+			i2c->wr = i2c->rd;
+		}
 		break;
 	case 6:
 		i2c->rd = entry->read;
@@ -267,7 +288,10 @@ nouveau_i2c_find(struct drm_device *dev,
 			val  = 0xe001;
 		}
 
-		nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
+		/* nfi, but neither auxch or i2c work if it's 1 */
+		nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
+		/* nfi, but switches auxch vs normal i2c */
+		nv_mask(dev, reg + 0x00, 0x0000f003, val);
 	}
 
 	if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
@@ -309,7 +333,7 @@ nouveau_i2c_identify(struct drm_device *
 
 	NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
 
-	for (i = 0; info[i].addr; i++) {
+	for (i = 0; i2c && info[i].addr; i++) {
 		if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
 		    (!match || match(i2c, &info[i]))) {
 			NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -408,8 +408,6 @@ nouveau_mem_vram_init(struct drm_device
 	if (ret)
 		return ret;
 
-	dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
-
 	ret = nouveau_ttm_global_init(dev_priv);
 	if (ret)
 		return ret;
@@ -504,35 +502,146 @@ nouveau_mem_gart_init(struct drm_device
 	return 0;
 }
 
+/* XXX: For now a dummy. More samples required, possibly even a card
+ * Called from nouveau_perf.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing) {
+
+	NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers");
+}
+
+void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing) {
+
+	timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+	/* XXX: I don't trust the -1's and +1's... they must come
+	 *      from somewhere! */
+	timing->reg_1 = (e->tWR + 2 + magic_number) << 24 |
+				  1 << 16 |
+				  (e->tUNK_1 + 2 + magic_number) << 8 |
+				  (e->tCL + 2 - magic_number);
+	timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+	timing->reg_2 |= 0x20200000;
+
+	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,timing->reg_2);
+}
+
+void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	uint8_t unk18 = 1,
+		unk19 = 1,
+		unk20 = 0,
+		unk21 = 0;
+
+	switch (min(hdr->entry_len, (u8) 22)) {
+	case 22:
+		unk21 = e->tUNK_21;
+	case 21:
+		unk20 = e->tUNK_20;
+	case 20:
+		unk19 = e->tUNK_19;
+	case 19:
+		unk18 = e->tUNK_18;
+		break;
+	}
+
+	timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+	/* XXX: I don't trust the -1's and +1's... they must come
+	 *      from somewhere! */
+	timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 |
+				  max(unk18, (u8) 1) << 16 |
+				  (e->tUNK_1 + unk19 + 1 + magic_number) << 8;
+	if (dev_priv->chipset == 0xa8) {
+		timing->reg_1 |= (e->tCL - 1);
+	} else {
+		timing->reg_1 |= (e->tCL + 2 - magic_number);
+	}
+	timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+
+	timing->reg_5 = (e->tRAS << 24 | e->tRC);
+	timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16;
+
+	if (P->version == 1) {
+		timing->reg_2 |= magic_number << 24;
+		timing->reg_3 = (0x14 + e->tCL) << 24 |
+						0x16 << 16 |
+						(e->tCL - 1) << 8 |
+						(e->tCL - 1);
+		timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8  | e->tUNK_13;
+		timing->reg_5 |= (e->tCL + 2) << 8;
+		timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16;
+	} else {
+		timing->reg_2 |= (unk19 - 1) << 24;
+		/* XXX: reg_10022c for recentish cards pretty much unknown*/
+		timing->reg_3 = e->tCL - 1;
+		timing->reg_4 = (unk20 << 24 | unk21 << 16 |
+							e->tUNK_13 << 8  | e->tUNK_13);
+		/* XXX: +6? */
+		timing->reg_5 |= (unk19 + 6) << 8;
+
+		/* XXX: reg_10023c currently unknown
+		 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
+		timing->reg_7 = 0x202;
+	}
+
+	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,
+		 timing->reg_2, timing->reg_3);
+	NV_DEBUG(dev, "         230: %08x %08x %08x %08x\n",
+		 timing->reg_4, timing->reg_5,
+		 timing->reg_6, timing->reg_7);
+	NV_DEBUG(dev, "         240: %08x\n", timing->reg_8);
+}
+
+void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) {
+	timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP);
+	timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f);
+	timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8;
+	timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13;
+	timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15;
+	NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,
+		 timing->reg_2, timing->reg_3);
+	NV_DEBUG(dev, "         2a0: %08x %08x %08x %08x\n",
+		 timing->reg_4, timing->reg_5,
+		 timing->reg_6, timing->reg_7);
+}
+
+/**
+ * Processes the Memory Timing BIOS table, stores generated
+ * register values
+ * @pre init scripts were run, memtiming regs are initialized
+ */
 void
 nouveau_mem_timing_init(struct drm_device *dev)
 {
-	/* cards < NVC0 only */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
 	struct nvbios *bios = &dev_priv->vbios;
 	struct bit_entry P;
-	u8 tUNK_0, tUNK_1, tUNK_2;
-	u8 tRP;		/* Byte 3 */
-	u8 tRAS;	/* Byte 5 */
-	u8 tRFC;	/* Byte 7 */
-	u8 tRC;		/* Byte 9 */
-	u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
-	u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
-	u8 magic_number = 0; /* Yeah... sorry*/
-	u8 *mem = NULL, *entry;
-	int i, recordlen, entries;
+	struct nouveau_pm_tbl_header *hdr = NULL;
+	uint8_t magic_number;
+	u8 *entry;
+	int i;
 
 	if (bios->type == NVBIOS_BIT) {
 		if (bit_table(dev, 'P', &P))
 			return;
 
 		if (P.version == 1)
-			mem = ROMPTR(bios, P.data[4]);
+			hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]);
 		else
 		if (P.version == 2)
-			mem = ROMPTR(bios, P.data[8]);
+			hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]);
 		else {
 			NV_WARN(dev, "unknown mem for BIT P %d\n", P.version);
 		}
@@ -541,150 +650,56 @@ nouveau_mem_timing_init(struct drm_devic
 		return;
 	}
 
-	if (!mem) {
+	if (!hdr) {
 		NV_DEBUG(dev, "memory timing table pointer invalid\n");
 		return;
 	}
 
-	if (mem[0] != 0x10) {
-		NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]);
+	if (hdr->version != 0x10) {
+		NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version);
 		return;
 	}
 
 	/* validate record length */
-	entries   = mem[2];
-	recordlen = mem[3];
-	if (recordlen < 15) {
-		NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]);
+	if (hdr->entry_len < 15) {
+		NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len);
 		return;
 	}
 
 	/* parse vbios entries into common format */
 	memtimings->timing =
-		kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+		kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL);
 	if (!memtimings->timing)
 		return;
 
 	/* Get "some number" from the timing reg for NV_40 and NV_50
-	 * Used in calculations later */
-	if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) {
+	 * Used in calculations later... source unknown */
+	magic_number = 0;
+	if (P.version == 1) {
 		magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24;
 	}
 
-	entry = mem + mem[1];
-	for (i = 0; i < entries; i++, entry += recordlen) {
+	entry = (u8*) hdr + hdr->header_len;
+	for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) {
 		struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
 		if (entry[0] == 0)
 			continue;
 
-		tUNK_18 = 1;
-		tUNK_19 = 1;
-		tUNK_20 = 0;
-		tUNK_21 = 0;
-		switch (min(recordlen, 22)) {
-		case 22:
-			tUNK_21 = entry[21];
-		case 21:
-			tUNK_20 = entry[20];
-		case 20:
-			tUNK_19 = entry[19];
-		case 19:
-			tUNK_18 = entry[18];
-		default:
-			tUNK_0  = entry[0];
-			tUNK_1  = entry[1];
-			tUNK_2  = entry[2];
-			tRP     = entry[3];
-			tRAS    = entry[5];
-			tRFC    = entry[7];
-			tRC     = entry[9];
-			tUNK_10 = entry[10];
-			tUNK_11 = entry[11];
-			tUNK_12 = entry[12];
-			tUNK_13 = entry[13];
-			tUNK_14 = entry[14];
-			break;
-		}
-
-		timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP);
-
-		/* XXX: I don't trust the -1's and +1's... they must come
-		 *      from somewhere! */
-		timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
-				      max(tUNK_18, (u8) 1) << 16 |
-				      (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
-		if (dev_priv->chipset == 0xa8) {
-			timing->reg_100224 |= (tUNK_2 - 1);
-		} else {
-			timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
-		}
-
-		timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
-		if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa)
-			timing->reg_100228 |= (tUNK_19 - 1) << 24;
-		else
-			timing->reg_100228 |= magic_number << 24;
-
-		if (dev_priv->card_type == NV_40) {
-			/* NV40: don't know what the rest of the regs are..
-			 * And don't need to know either */
-			timing->reg_100228 |= 0x20200000;
-		} else if (dev_priv->card_type >= NV_50) {
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_10022c = (0x14 + tUNK_2) << 24 |
-						     0x16 << 16 |
-						     (tUNK_2 - 1) << 8 |
-						     (tUNK_2 - 1);
-			} else {
-				/* XXX: reg_10022c for recentish cards */
-				timing->reg_10022c = tUNK_2 - 1;
-			}
-
-			timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
-						  tUNK_13 << 8  | tUNK_13);
-
-			timing->reg_100234 = (tRAS << 24 | tRC);
-			timing->reg_100234 += max(tUNK_10, tUNK_11) << 16;
-
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_100234 |= (tUNK_2 + 2) << 8;
-			} else {
-				/* XXX: +6? */
-				timing->reg_100234 |= (tUNK_19 + 6) << 8;
-			}
-
-			/* XXX; reg_100238
-			 * reg_100238: 0x00?????? */
-			timing->reg_10023c = 0x202;
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
-			} else {
-				/* XXX: reg_10023c
-				 * currently unknown
-				 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
-			}
-
-			/* XXX: reg_100240? */
-		}
 		timing->id = i;
+		timing->WR = entry[0];
+		timing->CL = entry[2];
 
-		NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
-			 timing->reg_100220, timing->reg_100224,
-			 timing->reg_100228, timing->reg_10022c);
-		NV_DEBUG(dev, "         230: %08x %08x %08x %08x\n",
-			 timing->reg_100230, timing->reg_100234,
-			 timing->reg_100238, timing->reg_10023c);
-		NV_DEBUG(dev, "         240: %08x\n", timing->reg_100240);
+		if(dev_priv->card_type <= NV_40) {
+			nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+		} else if(dev_priv->card_type == NV_50){
+			nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+		} else if(dev_priv->card_type == NV_C0) {
+			nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]);
+		}
 	}
 
-	memtimings->nr_timing = entries;
-	memtimings->supported = (dev_priv->chipset <= 0x98);
+	memtimings->nr_timing = hdr->entry_cnt;
+	memtimings->supported = P.version == 1;
 }
 
 void
@@ -693,7 +708,10 @@ nouveau_mem_timing_fini(struct drm_devic
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings;
 
-	kfree(mem->timing);
+	if(mem->timing) {
+		kfree(mem->timing);
+		mem->timing = NULL;
+	}
 }
 
 static int
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include "nouveau_mm.h"
 
 static inline void
-region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
+region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a)
 {
 	list_del(&a->nl_entry);
 	list_del(&a->fl_entry);
@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struc
 }
 
 static struct nouveau_mm_node *
-region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
+region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
 {
 	struct nouveau_mm_node *b;
 
@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, str
 	return b;
 }
 
-#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \
+#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \
 	list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)
 
 void
-nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this)
+nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this)
 {
 	struct nouveau_mm_node *prev = node(this, prev);
 	struct nouveau_mm_node *next = node(this, next);
 
-	list_add(&this->fl_entry, &rmm->free);
+	list_add(&this->fl_entry, &mm->free);
 	this->type = 0;
 
 	if (prev && prev->type == 0) {
 		prev->length += this->length;
-		region_put(rmm, this);
+		region_put(mm, this);
 		this = prev;
 	}
 
 	if (next && next->type == 0) {
 		next->offset  = this->offset;
 		next->length += this->length;
-		region_put(rmm, this);
+		region_put(mm, this);
 	}
 }
 
 int
-nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
+nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
 	       u32 align, struct nouveau_mm_node **pnode)
 {
 	struct nouveau_mm_node *prev, *this, *next;
@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, i
 	u32 splitoff;
 	u32 s, e;
 
-	list_for_each_entry(this, &rmm->free, fl_entry) {
+	list_for_each_entry(this, &mm->free, fl_entry) {
 		e = this->offset + this->length;
 		s = this->offset;
 
 		prev = node(this, prev);
 		if (prev && prev->type != type)
-			s = roundup(s, rmm->block_size);
+			s = roundup(s, mm->block_size);
 
 		next = node(this, next);
 		if (next && next->type != type)
-			e = rounddown(e, rmm->block_size);
+			e = rounddown(e, mm->block_size);
 
 		s  = (s + align_mask) & ~align_mask;
 		e &= ~align_mask;
@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, i
 			continue;
 
 		splitoff = s - this->offset;
-		if (splitoff && !region_split(rmm, this, splitoff))
+		if (splitoff && !region_split(mm, this, splitoff))
 			return -ENOMEM;
 
-		this = region_split(rmm, this, min(size, e - s));
+		this = region_split(mm, this, min(size, e - s));
 		if (!this)
 			return -ENOMEM;
 
@@ -127,52 +127,49 @@ nouveau_mm_get(struct nouveau_mm *rmm, i
 }
 
 int
-nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
+nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
 {
-	struct nouveau_mm *rmm;
-	struct nouveau_mm_node *heap;
+	struct nouveau_mm_node *node;
 
-	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
-	if (!heap)
-		return -ENOMEM;
-	heap->offset = roundup(offset, block);
-	heap->length = rounddown(offset + length, block) - heap->offset;
+	if (block) {
+		mutex_init(&mm->mutex);
+		INIT_LIST_HEAD(&mm->nodes);
+		INIT_LIST_HEAD(&mm->free);
+		mm->block_size = block;
+		mm->heap_nodes = 0;
+	}
 
-	rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
-	if (!rmm) {
-		kfree(heap);
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
 		return -ENOMEM;
-	}
-	rmm->block_size = block;
-	mutex_init(&rmm->mutex);
-	INIT_LIST_HEAD(&rmm->nodes);
-	INIT_LIST_HEAD(&rmm->free);
-	list_add(&heap->nl_entry, &rmm->nodes);
-	list_add(&heap->fl_entry, &rmm->free);
+	node->offset = roundup(offset, mm->block_size);
+	node->length = rounddown(offset + length, mm->block_size) - node->offset;
 
-	*prmm = rmm;
+	list_add_tail(&node->nl_entry, &mm->nodes);
+	list_add_tail(&node->fl_entry, &mm->free);
+	mm->heap_nodes++;
 	return 0;
 }
 
 int
-nouveau_mm_fini(struct nouveau_mm **prmm)
+nouveau_mm_fini(struct nouveau_mm *mm)
 {
-	struct nouveau_mm *rmm = *prmm;
 	struct nouveau_mm_node *node, *heap =
-		list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
+		list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);
+	int nodes = 0;
 
-	if (!list_is_singular(&rmm->nodes)) {
-		printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
-		list_for_each_entry(node, &rmm->nodes, nl_entry) {
-			printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
-			       node->type, node->offset, node->length);
+	list_for_each_entry(node, &mm->nodes, nl_entry) {
+		if (nodes++ == mm->heap_nodes) {
+			printk(KERN_ERR "nouveau_mm in use at destroy time!\n");
+			list_for_each_entry(node, &mm->nodes, nl_entry) {
+				printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+				       node->type, node->offset, node->length);
+			}
+			WARN_ON(1);
+			return -EBUSY;
 		}
-		WARN_ON(1);
-		return -EBUSY;
 	}
 
 	kfree(heap);
-	kfree(rmm);
-	*prmm = NULL;
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,10 +42,11 @@ struct nouveau_mm {
 	struct mutex mutex;
 
 	u32 block_size;
+	int heap_nodes;
 };
 
-int  nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block);
-int  nouveau_mm_fini(struct nouveau_mm **);
+int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
+int  nouveau_mm_fini(struct nouveau_mm *);
 int  nouveau_mm_pre(struct nouveau_mm *);
 int  nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
 		    u32 align, struct nouveau_mm_node **);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c	2012-01-04 18:55:44.000000000 -0500
@@ -680,7 +680,7 @@ nouveau_gpuobj_channel_init_pramin(struc
 		return ret;
 	}
 
-	ret = drm_mm_init(&chan->ramin_heap, base, size);
+	ret = drm_mm_init(&chan->ramin_heap, base, size - base);
 	if (ret) {
 		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
 		nouveau_gpuobj_ref(NULL, &chan->ramin);
@@ -693,6 +693,7 @@ nouveau_gpuobj_channel_init_pramin(struc
 static int
 nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
 	struct nouveau_gpuobj *pgd = NULL;
 	struct nouveau_vm_pgd *vpgd;
@@ -722,6 +723,9 @@ nvc0_gpuobj_channel_init(struct nouveau_
 	nv_wo32(chan->ramin, 0x020c, 0x000000ff);
 
 	/* map display semaphore buffers into channel's vm */
+	if (dev_priv->card_type >= NV_D0)
+		return 0;
+
 	for (i = 0; i < 2; i++) {
 		struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
 
@@ -746,7 +750,7 @@ nouveau_gpuobj_channel_init(struct nouve
 	int ret, i;
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
-	if (dev_priv->card_type == NV_C0)
+	if (dev_priv->card_type >= NV_C0)
 		return nvc0_gpuobj_channel_init(chan, vm);
 
 	/* Allocate a chunk of memory for per-channel object storage */
@@ -793,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouve
 			return ret;
 
 		/* dma objects for display sync channel semaphore blocks */
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < dev->mode_config.num_crtc; i++) {
 			struct nouveau_gpuobj *sem = NULL;
 			struct nv50_display_crtc *dispc =
 				&nv50_display(dev)->crtc[i];
@@ -875,18 +879,18 @@ nouveau_gpuobj_channel_takedown(struct n
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	if (dev_priv->card_type >= NV_50) {
+	if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) {
 		struct nv50_display *disp = nv50_display(dev);
 
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < dev->mode_config.num_crtc; i++) {
 			struct nv50_display_crtc *dispc = &disp->crtc[i];
 			nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
 		}
-
-		nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
-		nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 	}
 
+	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
+	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+
 	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_perf.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_perf.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_perf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_perf.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,13 +127,57 @@ nouveau_perf_timing(struct drm_device *d
 
 	entry += ramcfg * recordlen;
 	if (entry[1] >= pm->memtimings.nr_timing) {
-		NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
+		if (entry[1] != 0xff)
+			NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
 		return NULL;
 	}
 
 	return &pm->memtimings.timing[entry[1]];
 }
 
+static void
+nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P,
+		     struct nouveau_pm_level *perflvl)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	u8 *vmap;
+	int id;
+
+	id = perflvl->volt_min;
+	perflvl->volt_min = 0;
+
+	/* boards using voltage table version <0x40 store the voltage
+	 * level directly in the perflvl entry as a multiple of 10mV
+	 */
+	if (dev_priv->engine.pm.voltage.version < 0x40) {
+		perflvl->volt_min = id * 10000;
+		perflvl->volt_max = perflvl->volt_min;
+		return;
+	}
+
+	/* on newer ones, the perflvl stores an index into yet another
+	 * vbios table containing a min/max voltage value for the perflvl
+	 */
+	if (P->version != 2 || P->length < 34) {
+		NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n",
+			 P->version, P->length);
+		return;
+	}
+
+	vmap = ROMPTR(bios, P->data[32]);
+	if (!vmap) {
+		NV_DEBUG(dev, "volt map table pointer invalid\n");
+		return;
+	}
+
+	if (id < vmap[3]) {
+		vmap += vmap[1] + (vmap[2] * id);
+		perflvl->volt_min = ROM32(vmap[0]);
+		perflvl->volt_max = ROM32(vmap[4]);
+	}
+}
+
 void
 nouveau_perf_init(struct drm_device *dev)
 {
@@ -141,6 +185,8 @@ nouveau_perf_init(struct drm_device *dev
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nvbios *bios = &dev_priv->vbios;
 	struct bit_entry P;
+	struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
+	struct nouveau_pm_tbl_header mt_hdr;
 	u8 version, headerlen, recordlen, entries;
 	u8 *perf, *entry;
 	int vid, i;
@@ -188,6 +234,22 @@ nouveau_perf_init(struct drm_device *dev
 	}
 
 	entry = perf + headerlen;
+
+	/* For version 0x15, initialize memtiming table */
+	if(version == 0x15) {
+		memtimings->timing =
+				kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+		if (!memtimings->timing) {
+			NV_WARN(dev,"Could not allocate memtiming table\n");
+			return;
+		}
+
+		mt_hdr.entry_cnt = entries;
+		mt_hdr.entry_len = 14;
+		mt_hdr.version = version;
+		mt_hdr.header_len = 4;
+	}
+
 	for (i = 0; i < entries; i++) {
 		struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
 
@@ -203,7 +265,8 @@ nouveau_perf_init(struct drm_device *dev
 		case 0x13:
 		case 0x15:
 			perflvl->fanspeed = entry[55];
-			perflvl->voltage = (recordlen > 56) ? entry[56] : 0;
+			if (recordlen > 56)
+				perflvl->volt_min = entry[56];
 			perflvl->core = ROM32(entry[1]) * 10;
 			perflvl->memory = ROM32(entry[5]) * 20;
 			break;
@@ -211,9 +274,10 @@ nouveau_perf_init(struct drm_device *dev
 		case 0x23:
 		case 0x24:
 			perflvl->fanspeed = entry[4];
-			perflvl->voltage = entry[5];
-			perflvl->core = ROM16(entry[6]) * 1000;
-
+			perflvl->volt_min = entry[5];
+			perflvl->shader = ROM16(entry[6]) * 1000;
+			perflvl->core = perflvl->shader;
+			perflvl->core += (signed char)entry[8] * 1000;
 			if (dev_priv->chipset == 0x49 ||
 			    dev_priv->chipset == 0x4b)
 				perflvl->memory = ROM16(entry[11]) * 1000;
@@ -223,7 +287,7 @@ nouveau_perf_init(struct drm_device *dev
 			break;
 		case 0x25:
 			perflvl->fanspeed = entry[4];
-			perflvl->voltage = entry[5];
+			perflvl->volt_min = entry[5];
 			perflvl->core = ROM16(entry[6]) * 1000;
 			perflvl->shader = ROM16(entry[10]) * 1000;
 			perflvl->memory = ROM16(entry[12]) * 1000;
@@ -232,7 +296,7 @@ nouveau_perf_init(struct drm_device *dev
 			perflvl->memscript = ROM16(entry[2]);
 		case 0x35:
 			perflvl->fanspeed = entry[6];
-			perflvl->voltage = entry[7];
+			perflvl->volt_min = entry[7];
 			perflvl->core = ROM16(entry[8]) * 1000;
 			perflvl->shader = ROM16(entry[10]) * 1000;
 			perflvl->memory = ROM16(entry[12]) * 1000;
@@ -240,30 +304,34 @@ nouveau_perf_init(struct drm_device *dev
 			perflvl->unk05 = ROM16(entry[16]) * 1000;
 			break;
 		case 0x40:
-#define subent(n) entry[perf[2] + ((n) * perf[3])]
+#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000
 			perflvl->fanspeed = 0; /*XXX*/
-			perflvl->voltage = entry[2];
+			perflvl->volt_min = entry[2];
 			if (dev_priv->card_type == NV_50) {
-				perflvl->core = ROM16(subent(0)) & 0xfff;
-				perflvl->shader = ROM16(subent(1)) & 0xfff;
-				perflvl->memory = ROM16(subent(2)) & 0xfff;
+				perflvl->core   = subent(0);
+				perflvl->shader = subent(1);
+				perflvl->memory = subent(2);
+				perflvl->vdec   = subent(3);
+				perflvl->unka0  = subent(4);
 			} else {
-				perflvl->shader = ROM16(subent(3)) & 0xfff;
+				perflvl->hub06  = subent(0);
+				perflvl->hub01  = subent(1);
+				perflvl->copy   = subent(2);
+				perflvl->shader = subent(3);
+				perflvl->rop    = subent(4);
+				perflvl->memory = subent(5);
+				perflvl->vdec   = subent(6);
+				perflvl->daemon = subent(10);
+				perflvl->hub07  = subent(11);
 				perflvl->core   = perflvl->shader / 2;
-				perflvl->unk0a  = ROM16(subent(4)) & 0xfff;
-				perflvl->memory = ROM16(subent(5)) & 0xfff;
 			}
-
-			perflvl->core *= 1000;
-			perflvl->shader *= 1000;
-			perflvl->memory *= 1000;
-			perflvl->unk0a *= 1000;
 			break;
 		}
 
 		/* make sure vid is valid */
-		if (pm->voltage.supported && perflvl->voltage) {
-			vid = nouveau_volt_vid_lookup(dev, perflvl->voltage);
+		nouveau_perf_voltage(dev, &P, perflvl);
+		if (pm->voltage.supported && perflvl->volt_min) {
+			vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min);
 			if (vid < 0) {
 				NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i);
 				entry += recordlen;
@@ -272,7 +340,11 @@ nouveau_perf_init(struct drm_device *dev
 		}
 
 		/* get the corresponding memory timings */
-		if (version > 0x15) {
+		if (version == 0x15) {
+			memtimings->timing[i].id = i;
+			nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]);
+			perflvl->timing = &memtimings->timing[i];
+		} else if (version > 0x15) {
 			/* last 3 args are for < 0x40, ignored for >= 0x40 */
 			perflvl->timing =
 				nouveau_perf_timing(dev, &P,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,18 +64,26 @@ nouveau_pm_perflvl_set(struct drm_device
 	if (perflvl == pm->cur)
 		return 0;
 
-	if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) {
-		ret = pm->voltage_set(dev, perflvl->voltage);
+	if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) {
+		ret = pm->voltage_set(dev, perflvl->volt_min);
 		if (ret) {
 			NV_ERROR(dev, "voltage_set %d failed: %d\n",
-				 perflvl->voltage, ret);
+				 perflvl->volt_min, ret);
 		}
 	}
 
-	nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
-	nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
-	nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
-	nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+	if (pm->clocks_pre) {
+		void *state = pm->clocks_pre(dev, perflvl);
+		if (IS_ERR(state))
+			return PTR_ERR(state);
+		pm->clocks_set(dev, state);
+	} else
+	if (pm->clock_set) {
+		nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
+		nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
+		nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
+		nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+	}
 
 	pm->cur = perflvl;
 	return 0;
@@ -92,9 +100,6 @@ nouveau_pm_profile_set(struct drm_device
 	if (nouveau_perflvl_wr != 7777)
 		return -EPERM;
 
-	if (!pm->clock_set)
-		return -EINVAL;
-
 	if (!strncmp(profile, "boot", 4))
 		perflvl = &pm->boot;
 	else {
@@ -123,31 +128,37 @@ nouveau_pm_perflvl_get(struct drm_device
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	int ret;
 
-	if (!pm->clock_get)
-		return -EINVAL;
-
 	memset(perflvl, 0, sizeof(*perflvl));
 
-	ret = pm->clock_get(dev, PLL_CORE);
-	if (ret > 0)
-		perflvl->core = ret;
+	if (pm->clocks_get) {
+		ret = pm->clocks_get(dev, perflvl);
+		if (ret)
+			return ret;
+	} else
+	if (pm->clock_get) {
+		ret = pm->clock_get(dev, PLL_CORE);
+		if (ret > 0)
+			perflvl->core = ret;
 
-	ret = pm->clock_get(dev, PLL_MEMORY);
-	if (ret > 0)
-		perflvl->memory = ret;
+		ret = pm->clock_get(dev, PLL_MEMORY);
+		if (ret > 0)
+			perflvl->memory = ret;
 
-	ret = pm->clock_get(dev, PLL_SHADER);
-	if (ret > 0)
-		perflvl->shader = ret;
+		ret = pm->clock_get(dev, PLL_SHADER);
+		if (ret > 0)
+			perflvl->shader = ret;
 
-	ret = pm->clock_get(dev, PLL_UNK05);
-	if (ret > 0)
-		perflvl->unk05 = ret;
+		ret = pm->clock_get(dev, PLL_UNK05);
+		if (ret > 0)
+			perflvl->unk05 = ret;
+	}
 
 	if (pm->voltage.supported && pm->voltage_get) {
 		ret = pm->voltage_get(dev);
-		if (ret > 0)
-			perflvl->voltage = ret;
+		if (ret > 0) {
+			perflvl->volt_min = ret;
+			perflvl->volt_max = ret;
+		}
 	}
 
 	return 0;
@@ -156,7 +167,7 @@ nouveau_pm_perflvl_get(struct drm_device
 static void
 nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
 {
-	char c[16], s[16], v[16], f[16], t[16];
+	char c[16], s[16], v[32], f[16], t[16], m[16];
 
 	c[0] = '\0';
 	if (perflvl->core)
@@ -166,9 +177,19 @@ nouveau_pm_perflvl_info(struct nouveau_p
 	if (perflvl->shader)
 		snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000);
 
+	m[0] = '\0';
+	if (perflvl->memory)
+		snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000);
+
 	v[0] = '\0';
-	if (perflvl->voltage)
-		snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10);
+	if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) {
+		snprintf(v, sizeof(v), " voltage %dmV-%dmV",
+			 perflvl->volt_min / 1000, perflvl->volt_max / 1000);
+	} else
+	if (perflvl->volt_min) {
+		snprintf(v, sizeof(v), " voltage %dmV",
+			 perflvl->volt_min / 1000);
+	}
 
 	f[0] = '\0';
 	if (perflvl->fanspeed)
@@ -178,8 +199,7 @@ nouveau_pm_perflvl_info(struct nouveau_p
 	if (perflvl->timing)
 		snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
 
-	snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000,
-		 c, s, v, f, t);
+	snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f);
 }
 
 static ssize_t
@@ -190,7 +210,7 @@ nouveau_pm_get_perflvl_info(struct devic
 	char *ptr = buf;
 	int len = PAGE_SIZE;
 
-	snprintf(ptr, len, "%d: ", perflvl->id);
+	snprintf(ptr, len, "%d:", perflvl->id);
 	ptr += strlen(buf);
 	len -= strlen(buf);
 
@@ -211,9 +231,9 @@ nouveau_pm_get_perflvl(struct device *d,
 	if (!pm->cur)
 		snprintf(ptr, len, "setting: boot\n");
 	else if (pm->cur == &pm->boot)
-		snprintf(ptr, len, "setting: boot\nc: ");
+		snprintf(ptr, len, "setting: boot\nc:");
 	else
-		snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id);
+		snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id);
 	ptr += strlen(buf);
 	len -= strlen(buf);
 
@@ -292,7 +312,7 @@ nouveau_sysfs_fini(struct drm_device *de
 	}
 }
 
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 static ssize_t
 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
 {
@@ -409,7 +429,7 @@ static const struct attribute_group hwmo
 static int
 nouveau_hwmon_init(struct drm_device *dev)
 {
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct device *hwmon_dev;
@@ -442,7 +462,7 @@ nouveau_hwmon_init(struct drm_device *de
 static void
 nouveau_hwmon_fini(struct drm_device *dev)
 {
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 
@@ -488,7 +508,7 @@ nouveau_pm_init(struct drm_device *dev)
 	NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
 	for (i = 0; i < pm->nr_perflvl; i++) {
 		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info));
-		NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info);
+		NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info);
 	}
 
 	/* determine current ("boot") performance level */
@@ -498,7 +518,7 @@ nouveau_pm_init(struct drm_device *dev)
 		pm->cur = &pm->boot;
 
 		nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
-		NV_INFO(dev, "c: %s", info);
+		NV_INFO(dev, "c:%s", info);
 	}
 
 	/* switch performance levels now if requested */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -52,6 +52,11 @@ void *nv04_pm_clock_pre(struct drm_devic
 			u32 id, int khz);
 void nv04_pm_clock_set(struct drm_device *, void *);
 
+/* nv40_pm.c */
+int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nv40_pm_clocks_set(struct drm_device *, void *);
+
 /* nv50_pm.c */
 int nv50_pm_clock_get(struct drm_device *, u32 id);
 void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
@@ -59,10 +64,12 @@ void *nv50_pm_clock_pre(struct drm_devic
 void nv50_pm_clock_set(struct drm_device *, void *);
 
 /* nva3_pm.c */
-int nva3_pm_clock_get(struct drm_device *, u32 id);
-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
-			u32 id, int khz);
-void nva3_pm_clock_set(struct drm_device *, void *);
+int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nva3_pm_clocks_set(struct drm_device *, void *);
+
+/* nvc0_pm.c */
+int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
 
 /* nouveau_temp.c */
 void nouveau_temp_init(struct drm_device *dev);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -826,9 +826,12 @@
 #define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE                          0x00030000
 #define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED                         0x00080000
 #define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT                            0x10000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT                                  0x0061c084
-#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE                           0x80000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL                            0x00000fff
+#define NV50_PDISP_SOR_PWM_DIV(i)                     (0x0061c080 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL(i)                     (0x0061c084 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL_NEW                                   0x80000000
+#define NVA3_PDISP_SOR_PWM_CTL_UNK                                   0x40000000
+#define NV50_PDISP_SOR_PWM_CTL_VAL                                   0x000007ff
+#define NVA3_PDISP_SOR_PWM_CTL_VAL                                   0x00ffffff
 #define NV50_SOR_DP_CTRL(i, l)           (0x0061c10c + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_CTRL_ENABLED                                     0x00000001
 #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED                      0x00004000
@@ -843,7 +846,7 @@
 #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2                          0x02000000
 #define NV50_SOR_DP_UNK118(i, l)         (0x0061c118 + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_UNK120(i, l)         (0x0061c120 + (i) * 0x800 + (l) * 0x80)
-#define NV50_SOR_DP_UNK128(i, l)         (0x0061c128 + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_SCFG(i, l)           (0x0061c128 + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_UNK130(i, l)         (0x0061c130 + (i) * 0x800 + (l) * 0x80)
 
 #define NV50_PDISPLAY_USER(i)                        ((i) * 0x1000 + 0x00640000)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,8 @@ struct nouveau_sgdma_be {
 	struct drm_device *dev;
 
 	dma_addr_t *pages;
-	bool *ttm_alloced;
 	unsigned nr_pages;
+	bool unmap_pages;
 
 	u64 offset;
 	bool bound;
@@ -26,43 +26,28 @@ nouveau_sgdma_populate(struct ttm_backen
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
+	int i;
 
 	NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages);
 
-	if (nvbe->pages)
-		return -EINVAL;
-
-	nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL);
-	if (!nvbe->pages)
-		return -ENOMEM;
+	nvbe->pages = dma_addrs;
+	nvbe->nr_pages = num_pages;
+	nvbe->unmap_pages = true;
 
-	nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
-	if (!nvbe->ttm_alloced) {
-		kfree(nvbe->pages);
-		nvbe->pages = NULL;
-		return -ENOMEM;
+	/* this code path isn't called and is incorrect anyways */
+	if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */
+		nvbe->unmap_pages = false;
+		return 0;
 	}
 
-	nvbe->nr_pages = 0;
-	while (num_pages--) {
-		/* this code path isn't called and is incorrect anyways */
-		if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/
-			nvbe->pages[nvbe->nr_pages] =
-					dma_addrs[nvbe->nr_pages];
-		 	nvbe->ttm_alloced[nvbe->nr_pages] = true;
-		} else {
-			nvbe->pages[nvbe->nr_pages] =
-				pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
-				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-			if (pci_dma_mapping_error(dev->pdev,
-						  nvbe->pages[nvbe->nr_pages])) {
-				be->func->clear(be);
-				return -EFAULT;
-			}
-			nvbe->ttm_alloced[nvbe->nr_pages] = false;
+	for (i = 0; i < num_pages; i++) {
+		nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0,
+					      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) {
+			nvbe->nr_pages = --i;
+			be->func->clear(be);
+			return -EFAULT;
 		}
-
-		nvbe->nr_pages++;
 	}
 
 	return 0;
@@ -72,26 +57,20 @@ static void
 nouveau_sgdma_clear(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
-	struct drm_device *dev;
-
-	if (nvbe && nvbe->pages) {
-		dev = nvbe->dev;
-		NV_DEBUG(dev, "\n");
+	struct drm_device *dev = nvbe->dev;
 
-		if (nvbe->bound)
-			be->func->unbind(be);
+	if (nvbe->bound)
+		be->func->unbind(be);
 
+	if (nvbe->unmap_pages) {
 		while (nvbe->nr_pages--) {
-			if (!nvbe->ttm_alloced[nvbe->nr_pages])
-				pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
 				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 		}
-		kfree(nvbe->pages);
-		kfree(nvbe->ttm_alloced);
-		nvbe->pages = NULL;
-		nvbe->ttm_alloced = NULL;
-		nvbe->nr_pages = 0;
+		nvbe->unmap_pages = false;
 	}
+
+	nvbe->pages = NULL;
 }
 
 static void
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c	2012-01-04 18:55:44.000000000 -0500
@@ -286,9 +286,9 @@ static int nouveau_init_engine_ptrs(stru
 		engine->gpio.get		= nv10_gpio_get;
 		engine->gpio.set		= nv10_gpio_set;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv40_pm_clocks_get;
+		engine->pm.clocks_pre		= nv40_pm_clocks_pre;
+		engine->pm.clocks_set		= nv40_pm_clocks_set;
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->pm.temp_get		= nv40_temp_get;
@@ -299,7 +299,7 @@ static int nouveau_init_engine_ptrs(stru
 	case 0x50:
 	case 0x80: /* gotta love NVIDIA's consistency.. */
 	case 0x90:
-	case 0xA0:
+	case 0xa0:
 		engine->instmem.init		= nv50_instmem_init;
 		engine->instmem.takedown	= nv50_instmem_takedown;
 		engine->instmem.suspend		= nv50_instmem_suspend;
@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(stru
 			engine->pm.clock_set	= nv50_pm_clock_set;
 			break;
 		default:
-			engine->pm.clock_get	= nva3_pm_clock_get;
-			engine->pm.clock_pre	= nva3_pm_clock_pre;
-			engine->pm.clock_set	= nva3_pm_clock_set;
+			engine->pm.clocks_get	= nva3_pm_clocks_get;
+			engine->pm.clocks_pre	= nva3_pm_clocks_pre;
+			engine->pm.clocks_set	= nva3_pm_clocks_set;
 			break;
 		}
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
@@ -376,7 +376,7 @@ static int nouveau_init_engine_ptrs(stru
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nv50_vram_flags_valid;
 		break;
-	case 0xC0:
+	case 0xc0:
 		engine->instmem.init		= nvc0_instmem_init;
 		engine->instmem.takedown	= nvc0_instmem_takedown;
 		engine->instmem.suspend		= nvc0_instmem_suspend;
@@ -422,12 +422,73 @@ static int nouveau_init_engine_ptrs(stru
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nvc0_vram_flags_valid;
 		engine->pm.temp_get		= nv84_temp_get;
+		engine->pm.clocks_get		= nvc0_pm_clocks_get;
+		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
+		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
+		break;
+	case 0xd0:
+		engine->instmem.init		= nvc0_instmem_init;
+		engine->instmem.takedown	= nvc0_instmem_takedown;
+		engine->instmem.suspend		= nvc0_instmem_suspend;
+		engine->instmem.resume		= nvc0_instmem_resume;
+		engine->instmem.get		= nv50_instmem_get;
+		engine->instmem.put		= nv50_instmem_put;
+		engine->instmem.map		= nv50_instmem_map;
+		engine->instmem.unmap		= nv50_instmem_unmap;
+		engine->instmem.flush		= nv84_instmem_flush;
+		engine->mc.init			= nv50_mc_init;
+		engine->mc.takedown		= nv50_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nvc0_fb_init;
+		engine->fb.takedown		= nvc0_fb_takedown;
+		engine->fifo.channels		= 128;
+		engine->fifo.init		= nvc0_fifo_init;
+		engine->fifo.takedown		= nvc0_fifo_takedown;
+		engine->fifo.disable		= nvc0_fifo_disable;
+		engine->fifo.enable		= nvc0_fifo_enable;
+		engine->fifo.reassign		= nvc0_fifo_reassign;
+		engine->fifo.channel_id		= nvc0_fifo_channel_id;
+		engine->fifo.create_context	= nvc0_fifo_create_context;
+		engine->fifo.destroy_context	= nvc0_fifo_destroy_context;
+		engine->fifo.load_context	= nvc0_fifo_load_context;
+		engine->fifo.unload_context	= nvc0_fifo_unload_context;
+		engine->display.early_init	= nouveau_stub_init;
+		engine->display.late_takedown	= nouveau_stub_takedown;
+		engine->display.create		= nvd0_display_create;
+		engine->display.init		= nvd0_display_init;
+		engine->display.destroy		= nvd0_display_destroy;
+		engine->gpio.init		= nv50_gpio_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nvd0_gpio_get;
+		engine->gpio.set		= nvd0_gpio_set;
+		engine->gpio.irq_register	= nv50_gpio_irq_register;
+		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
+		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
+		engine->vram.init		= nvc0_vram_init;
+		engine->vram.takedown		= nv50_vram_fini;
+		engine->vram.get		= nvc0_vram_new;
+		engine->vram.put		= nv50_vram_del;
+		engine->vram.flags_valid	= nvc0_vram_flags_valid;
+		engine->pm.clocks_get		= nvc0_pm_clocks_get;
+		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
+		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		break;
 	default:
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
 		return 1;
 	}
 
+	/* headless mode */
+	if (nouveau_modeset == 2) {
+		engine->display.early_init = nouveau_stub_init;
+		engine->display.late_takedown = nouveau_stub_takedown;
+		engine->display.create = nouveau_stub_init;
+		engine->display.init = nouveau_stub_init;
+		engine->display.destroy = nouveau_stub_takedown;
+	}
+
 	return 0;
 }
 
@@ -449,21 +510,6 @@ nouveau_vga_set_decode(void *priv, bool
 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
-static int
-nouveau_card_init_channel(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int ret;
-
-	ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
-				    NvDmaFB, NvDmaTT);
-	if (ret)
-		return ret;
-
-	mutex_unlock(&dev_priv->channel->mutex);
-	return 0;
-}
-
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
 					 enum vga_switcheroo_state state)
 {
@@ -533,6 +579,14 @@ nouveau_card_init(struct drm_device *dev
 	if (ret)
 		goto out_display_early;
 
+	/* workaround an odd issue on nvc1 by disabling the device's
+	 * nosnoop capability.  hopefully won't cause issues until a
+	 * better fix is found - assuming there is one...
+	 */
+	if (dev_priv->chipset == 0xc1) {
+		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
+	}
+
 	nouveau_pm_init(dev);
 
 	ret = engine->vram.init(dev);
@@ -630,8 +684,11 @@ nouveau_card_init(struct drm_device *dev
 			break;
 		}
 
-		if (dev_priv->card_type == NV_40)
-			nv40_mpeg_create(dev);
+		if (dev_priv->card_type == NV_40 ||
+		    dev_priv->chipset == 0x31 ||
+		    dev_priv->chipset == 0x34 ||
+		    dev_priv->chipset == 0x36)
+			nv31_mpeg_create(dev);
 		else
 		if (dev_priv->card_type == NV_50 &&
 		    (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
@@ -651,41 +708,69 @@ nouveau_card_init(struct drm_device *dev
 			goto out_engine;
 	}
 
-	ret = engine->display.create(dev);
+	ret = nouveau_irq_init(dev);
 	if (ret)
 		goto out_fifo;
 
-	ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
-	if (ret)
-		goto out_vblank;
+	/* initialise general modesetting */
+	drm_mode_config_init(dev);
+	drm_mode_create_scaling_mode_property(dev);
+	drm_mode_create_dithering_property(dev);
+	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
+	dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+	if (dev_priv->card_type < NV_10) {
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+	} else
+	if (dev_priv->card_type < NV_50) {
+		dev->mode_config.max_width = 4096;
+		dev->mode_config.max_height = 4096;
+	} else {
+		dev->mode_config.max_width = 8192;
+		dev->mode_config.max_height = 8192;
+	}
 
-	ret = nouveau_irq_init(dev);
+	ret = engine->display.create(dev);
 	if (ret)
-		goto out_vblank;
+		goto out_irq;
 
-	/* what about PVIDEO/PCRTC/PRAMDAC etc? */
+	nouveau_backlight_init(dev);
 
 	if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
 		ret = nouveau_fence_init(dev);
 		if (ret)
-			goto out_irq;
+			goto out_disp;
 
-		ret = nouveau_card_init_channel(dev);
+		ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+					    NvDmaFB, NvDmaTT);
 		if (ret)
 			goto out_fence;
+
+		mutex_unlock(&dev_priv->channel->mutex);
+	}
+
+	if (dev->mode_config.num_crtc) {
+		ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+		if (ret)
+			goto out_chan;
+
+		nouveau_fbcon_init(dev);
+		drm_kms_helper_poll_init(dev);
 	}
 
-	nouveau_fbcon_init(dev);
-	drm_kms_helper_poll_init(dev);
 	return 0;
 
+out_chan:
+	nouveau_channel_put_unlocked(&dev_priv->channel);
 out_fence:
 	nouveau_fence_fini(dev);
+out_disp:
+	nouveau_backlight_exit(dev);
+	engine->display.destroy(dev);
 out_irq:
 	nouveau_irq_fini(dev);
-out_vblank:
-	drm_vblank_cleanup(dev);
-	engine->display.destroy(dev);
 out_fifo:
 	if (!dev_priv->noaccel)
 		engine->fifo.takedown(dev);
@@ -732,15 +817,20 @@ static void nouveau_card_takedown(struct
 	struct nouveau_engine *engine = &dev_priv->engine;
 	int e;
 
-	drm_kms_helper_poll_fini(dev);
-	nouveau_fbcon_fini(dev);
+	if (dev->mode_config.num_crtc) {
+		drm_kms_helper_poll_fini(dev);
+		nouveau_fbcon_fini(dev);
+		drm_vblank_cleanup(dev);
+	}
 
 	if (dev_priv->channel) {
 		nouveau_channel_put_unlocked(&dev_priv->channel);
 		nouveau_fence_fini(dev);
 	}
 
+	nouveau_backlight_exit(dev);
 	engine->display.destroy(dev);
+	drm_mode_config_cleanup(dev);
 
 	if (!dev_priv->noaccel) {
 		engine->fifo.takedown(dev);
@@ -774,7 +864,6 @@ static void nouveau_card_takedown(struct
 	engine->vram.takedown(dev);
 
 	nouveau_irq_fini(dev);
-	drm_vblank_cleanup(dev);
 
 	nouveau_pm_fini(dev);
 	nouveau_bios_takedown(dev);
@@ -907,7 +996,7 @@ static int nouveau_remove_conflicting_dr
 int nouveau_load(struct drm_device *dev, unsigned long flags)
 {
 	struct drm_nouveau_private *dev_priv;
-	uint32_t reg0;
+	uint32_t reg0, strap;
 	resource_size_t mmio_start_offs;
 	int ret;
 
@@ -951,13 +1040,11 @@ int nouveau_load(struct drm_device *dev,
 
 	/* Time to determine the card architecture */
 	reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
-	dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */
 
 	/* We're dealing with >=NV10 */
 	if ((reg0 & 0x0f000000) > 0) {
 		/* Bit 27-20 contain the architecture in hex */
 		dev_priv->chipset = (reg0 & 0xff00000) >> 20;
-		dev_priv->stepping = (reg0 & 0xff);
 	/* NV04 or NV05 */
 	} else if ((reg0 & 0xff00fff0) == 0x20004000) {
 		if (reg0 & 0x00f00000)
@@ -987,6 +1074,9 @@ int nouveau_load(struct drm_device *dev,
 	case 0xc0:
 		dev_priv->card_type = NV_C0;
 		break;
+	case 0xd0:
+		dev_priv->card_type = NV_D0;
+		break;
 	default:
 		NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
 		ret = -EINVAL;
@@ -996,6 +1086,23 @@ int nouveau_load(struct drm_device *dev,
 	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
 		dev_priv->card_type, reg0);
 
+	/* determine frequency of timing crystal */
+	strap = nv_rd32(dev, 0x101000);
+	if ( dev_priv->chipset < 0x17 ||
+	    (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25))
+		strap &= 0x00000040;
+	else
+		strap &= 0x00400040;
+
+	switch (strap) {
+	case 0x00000000: dev_priv->crystal = 13500; break;
+	case 0x00000040: dev_priv->crystal = 14318; break;
+	case 0x00400000: dev_priv->crystal = 27000; break;
+	case 0x00400040: dev_priv->crystal = 25000; break;
+	}
+
+	NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal);
+
 	/* Determine whether we'll attempt acceleration or not, some
 	 * cards are disabled by default here due to them being known
 	 * non-functional, or never been tested due to lack of hw.
@@ -1003,12 +1110,13 @@ int nouveau_load(struct drm_device *dev,
 	dev_priv->noaccel = !!nouveau_noaccel;
 	if (nouveau_noaccel == -1) {
 		switch (dev_priv->chipset) {
-		case 0xc1: /* known broken */
-		case 0xc8: /* never tested */
+#if 0
+		case 0xXX: /* known broken */
 			NV_INFO(dev, "acceleration disabled by default, pass "
 				     "noaccel=0 to force enable\n");
 			dev_priv->noaccel = true;
 			break;
+#endif
 		default:
 			dev_priv->noaccel = false;
 			break;
@@ -1030,7 +1138,7 @@ int nouveau_load(struct drm_device *dev,
 			ioremap(pci_resource_start(dev->pdev, ramin_bar),
 				dev_priv->ramin_size);
 		if (!dev_priv->ramin) {
-			NV_ERROR(dev, "Failed to PRAMIN BAR");
+			NV_ERROR(dev, "Failed to map PRAMIN BAR\n");
 			ret = -ENOMEM;
 			goto err_mmio;
 		}
@@ -1130,7 +1238,7 @@ int nouveau_ioctl_getparam(struct drm_de
 		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
-		getparam->value = 1;
+		getparam->value = dev_priv->card_type < NV_D0;
 		break;
 	case NOUVEAU_GETPARAM_GRAPH_UNITS:
 		/* NV40 and NV50 versions are quite different, but register
@@ -1195,6 +1303,23 @@ nouveau_wait_ne(struct drm_device *dev,
 			return true;
 	} while (ptimer->read(dev) - start < timeout);
 
+	return false;
+}
+
+/* Wait until cond(data) == true, up until timeout has hit */
+bool
+nouveau_wait_cb(struct drm_device *dev, u64 timeout,
+		bool (*cond)(void *), void *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	u64 start = ptimer->read(dev);
+
+	do {
+		if (cond(data) == true)
+			return true;
+	} while (ptimer->read(dev) - start < timeout);
+
 	return false;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * Authors: Martin Peres
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 
 #include "nouveau_drv.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *
 			vm->map_pgt(vpgd->obj, pde, vpgt->obj);
 		}
 
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		nouveau_gpuobj_ref(NULL, &pgt);
-		mutex_lock(&vm->mm->mutex);
+		mutex_lock(&vm->mm.mutex);
 	}
 }
 
@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm
 	pgt_size  = (1 << (vm->pgt_bits + 12)) >> type;
 	pgt_size *= 8;
 
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 	ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000,
 				 NVOBJ_FLAG_ZERO_ALLOC, &pgt);
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	if (unlikely(ret))
 		return ret;
 
 	/* someone beat us to filling the PDE while we didn't have the lock */
 	if (unlikely(vpgt->refcount[big]++)) {
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		nouveau_gpuobj_ref(NULL, &pgt);
-		mutex_lock(&vm->mm->mutex);
+		mutex_lock(&vm->mm.mutex);
 		return 0;
 	}
 
@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u6
 	u32 fpde, lpde, pde;
 	int ret;
 
-	mutex_lock(&vm->mm->mutex);
-	ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node);
+	mutex_lock(&vm->mm.mutex);
+	ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node);
 	if (unlikely(ret != 0)) {
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		return ret;
 	}
 
@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u6
 		if (ret) {
 			if (pde != fpde)
 				nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
-			nouveau_mm_put(vm->mm, vma->node);
-			mutex_unlock(&vm->mm->mutex);
+			nouveau_mm_put(&vm->mm, vma->node);
+			mutex_unlock(&vm->mm.mutex);
 			vma->node = NULL;
 			return ret;
 		}
 	}
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 
 	vma->vm     = vm;
 	vma->offset = (u64)vma->node->offset << 12;
@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma)
 	fpde = (vma->node->offset >> vm->pgt_bits);
 	lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
-	nouveau_mm_put(vm->mm, vma->node);
+	nouveau_mm_put(&vm->mm, vma->node);
 	vma->node = NULL;
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 }
 
 int
@@ -306,7 +306,7 @@ nouveau_vm_new(struct drm_device *dev, u
 			block = length;
 
 	} else
-	if (dev_priv->card_type == NV_C0) {
+	if (dev_priv->card_type >= NV_C0) {
 		vm->map_pgt = nvc0_vm_map_pgt;
 		vm->map = nvc0_vm_map;
 		vm->map_sg = nvc0_vm_map_sg;
@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, s
 
 	nouveau_gpuobj_ref(pgd, &vpgd->obj);
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	for (i = vm->fpde; i <= vm->lpde; i++)
 		vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
 	list_add(&vpgd->head, &vm->pgd_list);
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 	return 0;
 }
 
@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm,
 	if (!mpgd)
 		return;
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
 		if (vpgd->obj == mpgd) {
 			pgd = vpgd->obj;
@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm,
 			break;
 		}
 	}
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 
 	nouveau_gpuobj_ref(NULL, &pgd);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@ struct nouveau_vma {
 
 struct nouveau_vm {
 	struct drm_device *dev;
-	struct nouveau_mm *mm;
+	struct nouveau_mm mm;
 	int refcount;
 
 	struct list_head pgd_list;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_volt.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_volt.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nouveau_volt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nouveau_volt.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
 
-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a };
+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 };
 static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]);
 
 int
@@ -170,6 +170,13 @@ nouveau_volt_init(struct drm_device *dev
 		 */
 		vidshift  = 2;
 		break;
+	case 0x40:
+		headerlen = volt[1];
+		recordlen = volt[2];
+		entries   = volt[3]; /* not a clue what the entries are for.. */
+		vidmask   = volt[11]; /* guess.. */
+		vidshift  = 0;
+		break;
 	default:
 		NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]);
 		return;
@@ -197,16 +204,37 @@ nouveau_volt_init(struct drm_device *dev
 	}
 
 	/* parse vbios entries into common format */
-	voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
-	if (!voltage->level)
-		return;
+	voltage->version = volt[0];
+	if (voltage->version < 0x40) {
+		voltage->nr_level = entries;
+		voltage->level =
+			kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
+		if (!voltage->level)
+			return;
 
-	entry = volt + headerlen;
-	for (i = 0; i < entries; i++, entry += recordlen) {
-		voltage->level[i].voltage = entry[0];
-		voltage->level[i].vid     = entry[1] >> vidshift;
+		entry = volt + headerlen;
+		for (i = 0; i < entries; i++, entry += recordlen) {
+			voltage->level[i].voltage = entry[0] * 10000;
+			voltage->level[i].vid     = entry[1] >> vidshift;
+		}
+	} else {
+		u32 volt_uv = ROM32(volt[4]);
+		s16 step_uv = ROM16(volt[8]);
+		u8 vid;
+
+		voltage->nr_level = voltage->vid_mask + 1;
+		voltage->level = kcalloc(voltage->nr_level,
+					 sizeof(*voltage->level), GFP_KERNEL);
+		if (!voltage->level)
+			return;
+
+		for (vid = 0; vid <= voltage->vid_mask; vid++) {
+			voltage->level[vid].voltage = volt_uv;
+			voltage->level[vid].vid = vid;
+			volt_uv += step_uv;
+		}
 	}
-	voltage->nr_level  = entries;
+
 	voltage->supported = true;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -126,27 +126,6 @@ nv04_display_create(struct drm_device *d
 
 	nouveau_hw_save_vga_fonts(dev, 1);
 
-	drm_mode_config_init(dev);
-	drm_mode_create_scaling_mode_property(dev);
-	drm_mode_create_dithering_property(dev);
-
-	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-	switch (dev_priv->card_type) {
-	case NV_04:
-		dev->mode_config.max_width = 2048;
-		dev->mode_config.max_height = 2048;
-		break;
-	default:
-		dev->mode_config.max_width = 4096;
-		dev->mode_config.max_height = 4096;
-		break;
-	}
-
-	dev->mode_config.fb_base = dev_priv->fb_phys;
-
 	nv04_crtc_create(dev, 0);
 	if (nv_two_heads(dev))
 		nv04_crtc_create(dev, 1);
@@ -235,8 +214,6 @@ nv04_display_destroy(struct drm_device *
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		crtc->funcs->restore(crtc);
 
-	drm_mode_config_cleanup(dev);
-
 	nouveau_hw_save_vga_fonts(dev, 0);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,7 @@ void
 nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
 	struct nv04_pm_state *state = pre_state;
 	u32 reg = state->pll.reg;
 
@@ -85,6 +86,9 @@ nv04_pm_clock_set(struct drm_device *dev
 		nv_mask(dev, 0x1002c0, 0, 1 << 8);
 	}
 
+	if (reg == NV_PRAMDAC_NVPLL_COEFF)
+		ptimer->init(dev);
+
 	kfree(state);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_timer.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_timer.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv04_timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv04_timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,43 +6,75 @@
 int
 nv04_timer_init(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 m, n, d;
+
 	nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
 	nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
 
-	/* Just use the pre-existing values when possible for now; these regs
-	 * are not written in nv (driver writer missed a /4 on the address), and
-	 * writing 8 and 3 to the correct regs breaks the timings on the LVDS
-	 * hardware sequencing microcode.
-	 * A correct solution (involving calculations with the GPU PLL) can
-	 * be done when kernel modesetting lands
-	 */
-	if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
-				!nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
-		nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008);
-		nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003);
+	/* aim for 31.25MHz, which gives us nanosecond timestamps */
+	d = 1000000 / 32;
+
+	/* determine base clock for timer source */
+	if (dev_priv->chipset < 0x40) {
+		n = dev_priv->engine.pm.clock_get(dev, PLL_CORE);
+	} else
+	if (dev_priv->chipset == 0x40) {
+		/*XXX: figure this out */
+		n = 0;
+	} else {
+		n = dev_priv->crystal;
+		m = 1;
+		while (n < (d * 2)) {
+			n += (n / m);
+			m++;
+		}
+
+		nv_wr32(dev, 0x009220, m - 1);
+	}
+
+	if (!n) {
+		NV_WARN(dev, "PTIMER: unknown input clock freq\n");
+		if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
+		    !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
+			nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1);
+			nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1);
+		}
+		return 0;
 	}
 
+	/* reduce ratio to acceptable values */
+	while (((n % 5) == 0) && ((d % 5) == 0)) {
+		n /= 5;
+		d /= 5;
+	}
+
+	while (((n % 2) == 0) && ((d % 2) == 0)) {
+		n /= 2;
+		d /= 2;
+	}
+
+	while (n > 0xffff || d > 0xffff) {
+		n >>= 1;
+		d >>= 1;
+	}
+
+	nv_wr32(dev, NV04_PTIMER_NUMERATOR, n);
+	nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d);
 	return 0;
 }
 
-uint64_t
+u64
 nv04_timer_read(struct drm_device *dev)
 {
-	uint32_t low;
-	/* From kmmio dumps on nv28 this looks like how the blob does this.
-	 * It reads the high dword twice, before and after.
-	 * The only explanation seems to be that the 64-bit timer counter
-	 * advances between high and low dword reads and may corrupt the
-	 * result. Not confirmed.
-	 */
-	uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
-	uint32_t high1;
+	u32 hi, lo;
+
 	do {
-		high1 = high2;
-		low = nv_rd32(dev, NV04_PTIMER_TIME_0);
-		high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
-	} while (high1 != high2);
-	return (((uint64_t)high2) << 32) | (uint64_t)low;
+		hi = nv_rd32(dev, NV04_PTIMER_TIME_1);
+		lo = nv_rd32(dev, NV04_PTIMER_TIME_0);
+	} while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1));
+
+	return ((u64)hi << 32 | lo);
 }
 
 void
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv31_mpeg.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv31_mpeg.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv31_mpeg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv31_mpeg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_ramht.h"
+
+struct nv31_mpeg_engine {
+	struct nouveau_exec_engine base;
+	atomic_t refcount;
+};
+
+
+static int
+nv31_mpeg_context_new(struct nouveau_channel *chan, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+
+	if (!atomic_add_unless(&pmpeg->refcount, 1, 1))
+		return -EBUSY;
+
+	chan->engctx[engine] = (void *)0xdeadcafe;
+	return 0;
+}
+
+static void
+nv31_mpeg_context_del(struct nouveau_channel *chan, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+	atomic_dec(&pmpeg->refcount);
+	chan->engctx[engine] = NULL;
+}
+
+static int
+nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ctx = NULL;
+	unsigned long flags;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
+				 NVOBJ_FLAG_ZERO_FREE, &ctx);
+	if (ret)
+		return ret;
+
+	nv_wo32(ctx, 0x78, 0x02001ec1);
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
+		nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
+	nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	chan->engctx[engine] = ctx;
+	return 0;
+}
+
+static void
+nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_gpuobj *ctx = chan->engctx[engine];
+	struct drm_device *dev = chan->dev;
+	unsigned long flags;
+	u32 inst = 0x80000000 | (ctx->pinst >> 4);
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
+	if (nv_rd32(dev, 0x00b318) == inst)
+		nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	nouveau_gpuobj_ref(NULL, &ctx);
+	chan->engctx[engine] = NULL;
+}
+
+static int
+nv31_mpeg_object_new(struct nouveau_channel *chan, int engine,
+		      u32 handle, u16 class)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_gpuobj *obj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
+				 NVOBJ_FLAG_ZERO_FREE, &obj);
+	if (ret)
+		return ret;
+	obj->engine = 2;
+	obj->class  = class;
+
+	nv_wo32(obj, 0x00, class);
+
+	ret = nouveau_ramht_insert(chan, handle, obj);
+	nouveau_gpuobj_ref(NULL, &obj);
+	return ret;
+}
+
+static int
+nv31_mpeg_init(struct drm_device *dev, int engine)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
+	int i;
+
+	/* VPE init */
+	nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
+	nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
+	nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
+
+	for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
+		pmpeg->base.set_tile_region(dev, i);
+
+	/* PMPEG init */
+	nv_wr32(dev, 0x00b32c, 0x00000000);
+	nv_wr32(dev, 0x00b314, 0x00000100);
+	nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031);
+	nv_wr32(dev, 0x00b300, 0x02001ec1);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
+
+	nv_wr32(dev, 0x00b100, 0xffffffff);
+	nv_wr32(dev, 0x00b140, 0xffffffff);
+
+	if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int
+nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
+{
+	/*XXX: context save? */
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
+	nv_wr32(dev, 0x00b140, 0x00000000);
+	return 0;
+}
+
+static int
+nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
+{
+	struct drm_device *dev = chan->dev;
+	u32 inst = data << 4;
+	u32 dma0 = nv_ri32(dev, inst + 0);
+	u32 dma1 = nv_ri32(dev, inst + 4);
+	u32 dma2 = nv_ri32(dev, inst + 8);
+	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
+	u32 size = dma1 + 1;
+
+	/* only allow linear DMA objects */
+	if (!(dma0 & 0x00002000))
+		return -EINVAL;
+
+	if (mthd == 0x0190) {
+		/* DMA_CMD */
+		nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
+		nv_wr32(dev, 0x00b334, base);
+		nv_wr32(dev, 0x00b324, size);
+	} else
+	if (mthd == 0x01a0) {
+		/* DMA_DATA */
+		nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
+		nv_wr32(dev, 0x00b360, base);
+		nv_wr32(dev, 0x00b364, size);
+	} else {
+		/* DMA_IMAGE, VRAM only */
+		if (dma0 & 0x000c0000)
+			return -EINVAL;
+
+		nv_wr32(dev, 0x00b370, base);
+		nv_wr32(dev, 0x00b374, size);
+	}
+
+	return 0;
+}
+
+static int
+nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ctx;
+	unsigned long flags;
+	int i;
+
+	/* hardcode drm channel id on nv3x, so swmthd lookup works */
+	if (dev_priv->card_type < NV_40)
+		return 0;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		if (!dev_priv->channels.ptr[i])
+			continue;
+
+		ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
+		if (ctx && ctx->pinst == inst)
+			break;
+	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return i;
+}
+
+static void
+nv31_vpe_set_tile_region(struct drm_device *dev, int i)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+
+	nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
+	nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
+	nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
+}
+
+static void
+nv31_mpeg_isr(struct drm_device *dev)
+{
+	u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
+	u32 chid = nv31_mpeg_isr_chid(dev, inst);
+	u32 stat = nv_rd32(dev, 0x00b100);
+	u32 type = nv_rd32(dev, 0x00b230);
+	u32 mthd = nv_rd32(dev, 0x00b234);
+	u32 data = nv_rd32(dev, 0x00b238);
+	u32 show = stat;
+
+	if (stat & 0x01000000) {
+		/* happens on initial binding of the object */
+		if (type == 0x00000020 && mthd == 0x0000) {
+			nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
+			show &= ~0x01000000;
+		}
+
+		if (type == 0x00000010) {
+			if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
+				show &= ~0x01000000;
+		}
+	}
+
+	nv_wr32(dev, 0x00b100, stat);
+	nv_wr32(dev, 0x00b230, 0x00000001);
+
+	if (show && nouveau_ratelimit()) {
+		NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			chid, inst, stat, type, mthd, data);
+	}
+}
+
+static void
+nv31_vpe_isr(struct drm_device *dev)
+{
+	if (nv_rd32(dev, 0x00b100))
+		nv31_mpeg_isr(dev);
+
+	if (nv_rd32(dev, 0x00b800)) {
+		u32 stat = nv_rd32(dev, 0x00b800);
+		NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
+		nv_wr32(dev, 0xb800, stat);
+	}
+}
+
+static void
+nv31_mpeg_destroy(struct drm_device *dev, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
+
+	nouveau_irq_unregister(dev, 0);
+
+	NVOBJ_ENGINE_DEL(dev, MPEG);
+	kfree(pmpeg);
+}
+
+int
+nv31_mpeg_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv31_mpeg_engine *pmpeg;
+
+	pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
+	if (!pmpeg)
+		return -ENOMEM;
+	atomic_set(&pmpeg->refcount, 0);
+
+	pmpeg->base.destroy = nv31_mpeg_destroy;
+	pmpeg->base.init = nv31_mpeg_init;
+	pmpeg->base.fini = nv31_mpeg_fini;
+	if (dev_priv->card_type < NV_40) {
+		pmpeg->base.context_new = nv31_mpeg_context_new;
+		pmpeg->base.context_del = nv31_mpeg_context_del;
+	} else {
+		pmpeg->base.context_new = nv40_mpeg_context_new;
+		pmpeg->base.context_del = nv40_mpeg_context_del;
+	}
+	pmpeg->base.object_new = nv31_mpeg_object_new;
+
+	/* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
+	 * all VPE engines, for this driver's purposes the PMPEG engine
+	 * will be treated as the "master" and handle the global VPE
+	 * bits too
+	 */
+	pmpeg->base.set_tile_region = nv31_vpe_set_tile_region;
+	nouveau_irq_register(dev, 0, nv31_vpe_isr);
+
+	NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
+	NVOBJ_CLASS(dev, 0x3174, MPEG);
+	NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma);
+	NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma);
+	NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma);
+
+#if 0
+	NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
+	NVOBJ_CLASS(dev, 0x4075, ME);
+#endif
+	return 0;
+
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv40_mpeg.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv40_mpeg.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv40_mpeg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv40_mpeg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-/*
- * Copyright 2011 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include "drmP.h"
-#include "nouveau_drv.h"
-#include "nouveau_ramht.h"
-
-struct nv40_mpeg_engine {
-	struct nouveau_exec_engine base;
-};
-
-static int
-nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
-{
-	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *ctx = NULL;
-	unsigned long flags;
-	int ret;
-
-	NV_DEBUG(dev, "ch%d\n", chan->id);
-
-	ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
-				 NVOBJ_FLAG_ZERO_FREE, &ctx);
-	if (ret)
-		return ret;
-
-	nv_wo32(ctx, 0x78, 0x02001ec1);
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
-	if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
-		nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
-	nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	chan->engctx[engine] = ctx;
-	return 0;
-}
-
-static void
-nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
-{
-	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
-	struct nouveau_gpuobj *ctx = chan->engctx[engine];
-	struct drm_device *dev = chan->dev;
-	unsigned long flags;
-	u32 inst = 0x80000000 | (ctx->pinst >> 4);
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
-	if (nv_rd32(dev, 0x00b318) == inst)
-		nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	nouveau_gpuobj_ref(NULL, &ctx);
-	chan->engctx[engine] = NULL;
-}
-
-static int
-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
-		      u32 handle, u16 class)
-{
-	struct drm_device *dev = chan->dev;
-	struct nouveau_gpuobj *obj = NULL;
-	int ret;
-
-	ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
-				 NVOBJ_FLAG_ZERO_FREE, &obj);
-	if (ret)
-		return ret;
-	obj->engine = 2;
-	obj->class  = class;
-
-	nv_wo32(obj, 0x00, class);
-
-	ret = nouveau_ramht_insert(chan, handle, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	return ret;
-}
-
-static int
-nv40_mpeg_init(struct drm_device *dev, int engine)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
-	int i;
-
-	/* VPE init */
-	nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
-	nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
-	nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
-	nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
-
-	for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
-		pmpeg->base.set_tile_region(dev, i);
-
-	/* PMPEG init */
-	nv_wr32(dev, 0x00b32c, 0x00000000);
-	nv_wr32(dev, 0x00b314, 0x00000100);
-	nv_wr32(dev, 0x00b220, 0x00000044);
-	nv_wr32(dev, 0x00b300, 0x02001ec1);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
-
-	nv_wr32(dev, 0x00b100, 0xffffffff);
-	nv_wr32(dev, 0x00b140, 0xffffffff);
-
-	if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int
-nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
-{
-	/*XXX: context save? */
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
-	nv_wr32(dev, 0x00b140, 0x00000000);
-	return 0;
-}
-
-static int
-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
-{
-	struct drm_device *dev = chan->dev;
-	u32 inst = data << 4;
-	u32 dma0 = nv_ri32(dev, inst + 0);
-	u32 dma1 = nv_ri32(dev, inst + 4);
-	u32 dma2 = nv_ri32(dev, inst + 8);
-	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
-	u32 size = dma1 + 1;
-
-	/* only allow linear DMA objects */
-	if (!(dma0 & 0x00002000))
-		return -EINVAL;
-
-	if (mthd == 0x0190) {
-		/* DMA_CMD */
-		nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
-		nv_wr32(dev, 0x00b334, base);
-		nv_wr32(dev, 0x00b324, size);
-	} else
-	if (mthd == 0x01a0) {
-		/* DMA_DATA */
-		nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
-		nv_wr32(dev, 0x00b360, base);
-		nv_wr32(dev, 0x00b364, size);
-	} else {
-		/* DMA_IMAGE, VRAM only */
-		if (dma0 & 0x000c0000)
-			return -EINVAL;
-
-		nv_wr32(dev, 0x00b370, base);
-		nv_wr32(dev, 0x00b374, size);
-	}
-
-	return 0;
-}
-
-static int
-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *ctx;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&dev_priv->channels.lock, flags);
-	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (!dev_priv->channels.ptr[i])
-			continue;
-
-		ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
-		if (ctx && ctx->pinst == inst)
-			break;
-	}
-	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
-	return i;
-}
-
-static void
-nv40_vpe_set_tile_region(struct drm_device *dev, int i)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
-
-	nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
-	nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
-	nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
-}
-
-static void
-nv40_mpeg_isr(struct drm_device *dev)
-{
-	u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
-	u32 chid = nv40_mpeg_isr_chid(dev, inst);
-	u32 stat = nv_rd32(dev, 0x00b100);
-	u32 type = nv_rd32(dev, 0x00b230);
-	u32 mthd = nv_rd32(dev, 0x00b234);
-	u32 data = nv_rd32(dev, 0x00b238);
-	u32 show = stat;
-
-	if (stat & 0x01000000) {
-		/* happens on initial binding of the object */
-		if (type == 0x00000020 && mthd == 0x0000) {
-			nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
-			show &= ~0x01000000;
-		}
-
-		if (type == 0x00000010) {
-			if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
-				show &= ~0x01000000;
-		}
-	}
-
-	nv_wr32(dev, 0x00b100, stat);
-	nv_wr32(dev, 0x00b230, 0x00000001);
-
-	if (show && nouveau_ratelimit()) {
-		NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			chid, inst, stat, type, mthd, data);
-	}
-}
-
-static void
-nv40_vpe_isr(struct drm_device *dev)
-{
-	if (nv_rd32(dev, 0x00b100))
-		nv40_mpeg_isr(dev);
-
-	if (nv_rd32(dev, 0x00b800)) {
-		u32 stat = nv_rd32(dev, 0x00b800);
-		NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
-		nv_wr32(dev, 0xb800, stat);
-	}
-}
-
-static void
-nv40_mpeg_destroy(struct drm_device *dev, int engine)
-{
-	struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
-
-	nouveau_irq_unregister(dev, 0);
-
-	NVOBJ_ENGINE_DEL(dev, MPEG);
-	kfree(pmpeg);
-}
-
-int
-nv40_mpeg_create(struct drm_device *dev)
-{
-	struct nv40_mpeg_engine *pmpeg;
-
-	pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
-	if (!pmpeg)
-		return -ENOMEM;
-
-	pmpeg->base.destroy = nv40_mpeg_destroy;
-	pmpeg->base.init = nv40_mpeg_init;
-	pmpeg->base.fini = nv40_mpeg_fini;
-	pmpeg->base.context_new = nv40_mpeg_context_new;
-	pmpeg->base.context_del = nv40_mpeg_context_del;
-	pmpeg->base.object_new = nv40_mpeg_object_new;
-
-	/* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
-	 * all VPE engines, for this driver's purposes the PMPEG engine
-	 * will be treated as the "master" and handle the global VPE
-	 * bits too
-	 */
-	pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
-	nouveau_irq_register(dev, 0, nv40_vpe_isr);
-
-	NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
-	NVOBJ_CLASS(dev, 0x3174, MPEG);
-	NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
-	NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
-	NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
-
-#if 0
-	NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
-	NVOBJ_CLASS(dev, 0x4075, ME);
-#endif
-	return 0;
-
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv40_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv40_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv40_pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv40_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+#include "nouveau_hw.h"
+
+#define min2(a,b) ((a) < (b) ? (a) : (b))
+
+static u32
+read_pll_1(struct drm_device *dev, u32 reg)
+{
+	u32 ctrl = nv_rd32(dev, reg + 0x00);
+	int P = (ctrl & 0x00070000) >> 16;
+	int N = (ctrl & 0x0000ff00) >> 8;
+	int M = (ctrl & 0x000000ff) >> 0;
+	u32 ref = 27000, clk = 0;
+
+	if (ctrl & 0x80000000)
+		clk = ref * N / M;
+
+	return clk >> P;
+}
+
+static u32
+read_pll_2(struct drm_device *dev, u32 reg)
+{
+	u32 ctrl = nv_rd32(dev, reg + 0x00);
+	u32 coef = nv_rd32(dev, reg + 0x04);
+	int N2 = (coef & 0xff000000) >> 24;
+	int M2 = (coef & 0x00ff0000) >> 16;
+	int N1 = (coef & 0x0000ff00) >> 8;
+	int M1 = (coef & 0x000000ff) >> 0;
+	int P = (ctrl & 0x00070000) >> 16;
+	u32 ref = 27000, clk = 0;
+
+	if ((ctrl & 0x80000000) && M1) {
+		clk = ref * N1 / M1;
+		if ((ctrl & 0x40000100) == 0x40000000) {
+			if (M2)
+				clk = clk * N2 / M2;
+			else
+				clk = 0;
+		}
+	}
+
+	return clk >> P;
+}
+
+static u32
+read_clk(struct drm_device *dev, u32 src)
+{
+	switch (src) {
+	case 3:
+		return read_pll_2(dev, 0x004000);
+	case 2:
+		return read_pll_1(dev, 0x004008);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int
+nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	u32 ctrl = nv_rd32(dev, 0x00c040);
+
+	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0);
+	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4);
+	perflvl->memory = read_pll_2(dev, 0x4020);
+	return 0;
+}
+
+struct nv40_pm_state {
+	u32 ctrl;
+	u32 npll_ctrl;
+	u32 npll_coef;
+	u32 spll;
+	u32 mpll_ctrl;
+	u32 mpll_coef;
+};
+
+static int
+nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll,
+	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P)
+{
+	struct nouveau_pll_vals coef;
+	int ret;
+
+	ret = get_pll_limits(dev, reg, pll);
+	if (ret)
+		return ret;
+
+	if (clk < pll->vco1.maxfreq)
+		pll->vco2.maxfreq = 0;
+
+	ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef);
+	if (ret == 0)
+		return -ERANGE;
+
+	*N1 = coef.N1;
+	*M1 = coef.M1;
+	if (N2 && M2) {
+		if (pll->vco2.maxfreq) {
+			*N2 = coef.N2;
+			*M2 = coef.M2;
+		} else {
+			*N2 = 1;
+			*M2 = 1;
+		}
+	}
+	*log2P = coef.log2P;
+	return 0;
+}
+
+void *
+nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	struct nv40_pm_state *info;
+	struct pll_lims pll;
+	int N1, N2, M1, M2, log2P;
+	int ret;
+
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return ERR_PTR(-ENOMEM);
+
+	/* core/geometric clock */
+	ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core,
+			    &N1, &M1, &N2, &M2, &log2P);
+	if (ret < 0)
+		goto out;
+
+	if (N2 == M2) {
+		info->npll_ctrl = 0x80000100 | (log2P << 16);
+		info->npll_coef = (N1 << 8) | M1;
+	} else {
+		info->npll_ctrl = 0xc0000000 | (log2P << 16);
+		info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+	}
+
+	/* use the second PLL for shader/rop clock, if it differs from core */
+	if (perflvl->shader && perflvl->shader != perflvl->core) {
+		ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader,
+				    &N1, &M1, NULL, NULL, &log2P);
+		if (ret < 0)
+			goto out;
+
+		info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
+		info->ctrl = 0x00000223;
+	} else {
+		info->spll = 0x00000000;
+		info->ctrl = 0x00000333;
+	}
+
+	/* memory clock */
+	if (!perflvl->memory) {
+		info->mpll_ctrl = 0x00000000;
+		goto out;
+	}
+
+	ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
+			    &N1, &M1, &N2, &M2, &log2P);
+	if (ret < 0)
+		goto out;
+
+	info->mpll_ctrl  = 0x80000000 | (log2P << 16);
+	info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20;
+	if (N2 == M2) {
+		info->mpll_ctrl |= 0x00000100;
+		info->mpll_coef  = (N1 << 8) | M1;
+	} else {
+		info->mpll_ctrl |= 0x40000000;
+		info->mpll_coef  = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+	}
+
+out:
+	if (ret < 0) {
+		kfree(info);
+		info = ERR_PTR(ret);
+	}
+	return info;
+}
+
+static bool
+nv40_pm_gr_idle(void *data)
+{
+	struct drm_device *dev = data;
+
+	if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 !=
+	    (nv_rd32(dev, 0x400760) & 0x0000000f))
+		return false;
+
+	if (nv_rd32(dev, 0x400700))
+		return false;
+
+	return true;
+}
+
+void
+nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv40_pm_state *info = pre_state;
+	unsigned long flags;
+	struct bit_entry M;
+	u32 crtc_mask = 0;
+	u8 sr1[2];
+	int i;
+
+	/* determine which CRTCs are active, fetch VGA_SR1 for each */
+	for (i = 0; i < 2; i++) {
+		u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000));
+		u32 cnt = 0;
+		do {
+			if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) {
+				nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+				sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000));
+				if (!(sr1[i] & 0x20))
+					crtc_mask |= (1 << i);
+				break;
+			}
+			udelay(1);
+		} while (cnt++ < 32);
+	}
+
+	/* halt and idle engines */
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000))
+		goto resume;
+	nv_mask(dev, 0x003220, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000))
+		goto resume;
+	nv_mask(dev, 0x003200, 0x00000001, 0x00000000);
+	nv04_fifo_cache_pull(dev, false);
+
+	if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev))
+		goto resume;
+
+	/* set engine clocks */
+	nv_mask(dev, 0x00c040, 0x00000333, 0x00000000);
+	nv_wr32(dev, 0x004004, info->npll_coef);
+	nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl);
+	nv_mask(dev, 0x004008, 0xc007ffff, info->spll);
+	mdelay(5);
+	nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
+
+	if (!info->mpll_ctrl)
+		goto resume;
+
+	/* wait for vblank start on active crtcs, disable memory access */
+	for (i = 0; i < 2; i++) {
+		if (!(crtc_mask & (1 << i)))
+			continue;
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000);
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20);
+	}
+
+	/* prepare ram for reclocking */
+	nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */
+	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+	nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */
+	nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */
+
+	/* change the PLL of each memory partition */
+	nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000);
+	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x45:
+	case 0x41:
+	case 0x42:
+	case 0x47:
+		nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl);
+		nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x004048, info->mpll_coef);
+		nv_wr32(dev, 0x004030, info->mpll_coef);
+	case 0x43:
+	case 0x49:
+	case 0x4b:
+		nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x00403c, info->mpll_coef);
+	default:
+		nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x004024, info->mpll_coef);
+		break;
+	}
+	udelay(100);
+	nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000);
+
+	/* re-enable normal operation of memory controller */
+	nv_wr32(dev, 0x1002dc, 0x00000000);
+	nv_mask(dev, 0x100210, 0x80000000, 0x80000000);
+	udelay(100);
+
+	/* execute memory reset script from vbios */
+	if (!bit_table(dev, 'M', &M))
+		nouveau_bios_init_exec(dev, ROM16(M.data[0]));
+
+	/* make sure we're in vblank (hopefully the same one as before), and
+	 * then re-enable crtc memory access
+	 */
+	for (i = 0; i < 2; i++) {
+		if (!(crtc_mask & (1 << i)))
+			continue;
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]);
+	}
+
+	/* resume engines */
+resume:
+	nv_wr32(dev, 0x003250, 0x00000001);
+	nv_mask(dev, 0x003220, 0x00000001, 0x00000001);
+	nv_wr32(dev, 0x003200, 0x00000001);
+	nv_wr32(dev, 0x002500, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	kfree(info);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -329,8 +329,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
 
 	drm_crtc_cleanup(&nv_crtc->base);
 
-	nv50_cursor_fini(nv_crtc);
-
 	nouveau_bo_unmap(nv_crtc->lut.nvbo);
 	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
 	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_cursor.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_cursor.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_cursor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_cursor.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,21 +137,3 @@ nv50_cursor_init(struct nouveau_crtc *nv
 	nv_crtc->cursor.show = nv50_cursor_show;
 	return 0;
 }
-
-void
-nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
-{
-	struct drm_device *dev = nv_crtc->base.dev;
-	int idx = nv_crtc->index;
-
-	NV_DEBUG_KMS(dev, "\n");
-
-	nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
-	if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
-		     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
-		NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
-		NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
-			 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
-	}
-}
-
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -247,6 +247,16 @@ static int nv50_display_disable(struct d
 		}
 	}
 
+	for (i = 0; i < 2; i++) {
+		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0);
+		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
+			NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
+			NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
+				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)));
+		}
+	}
+
 	nv50_evo_fini(dev);
 
 	for (i = 0; i < 3; i++) {
@@ -286,23 +296,6 @@ int nv50_display_create(struct drm_devic
 		return -ENOMEM;
 	dev_priv->engine.display.priv = priv;
 
-	/* init basic kernel modesetting */
-	drm_mode_config_init(dev);
-
-	/* Initialise some optional connector properties. */
-	drm_mode_create_scaling_mode_property(dev);
-	drm_mode_create_dithering_property(dev);
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
-	dev->mode_config.max_width = 8192;
-	dev->mode_config.max_height = 8192;
-
-	dev->mode_config.fb_base = dev_priv->fb_phys;
-
 	/* Create CRTC objects */
 	for (i = 0; i < 2; i++)
 		nv50_crtc_create(dev, i);
@@ -364,8 +357,6 @@ nv50_display_destroy(struct drm_device *
 
 	NV_DEBUG_KMS(dev, "\n");
 
-	drm_mode_config_cleanup(dev);
-
 	nv50_display_disable(dev);
 	nouveau_irq_unregister(dev, 26);
 	kfree(disp);
@@ -625,7 +616,7 @@ nv50_display_unk10_handler(struct drm_de
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nv50_display *disp = nv50_display(dev);
 	u32 unk30 = nv_rd32(dev, 0x610030), mc;
-	int i, crtc, or, type = OUTPUT_ANY;
+	int i, crtc, or = 0, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
 	disp->irq.dcb = NULL;
@@ -698,7 +689,7 @@ nv50_display_unk10_handler(struct drm_de
 		struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
 
 		if (dcb->type == type && (dcb->or & (1 << or))) {
-			nouveau_bios_run_display_table(dev, dcb, 0, -1);
+			nouveau_bios_run_display_table(dev, 0, -1, dcb, -1);
 			disp->irq.dcb = dcb;
 			goto ack;
 		}
@@ -711,49 +702,18 @@ ack:
 }
 
 static void
-nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb)
-{
-	int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1);
-	struct drm_encoder *encoder;
-	uint32_t tmp, unk0 = 0, unk1 = 0;
-
-	if (dcb->type != OUTPUT_DP)
-		return;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
-		if (nv_encoder->dcb == dcb) {
-			unk0 = nv_encoder->dp.unk0;
-			unk1 = nv_encoder->dp.unk1;
-			break;
-		}
-	}
-
-	if (unk0 || unk1) {
-		tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-		tmp &= 0xfffffe03;
-		nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0);
-
-		tmp  = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
-		tmp &= 0xfef080c0;
-		nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1);
-	}
-}
-
-static void
 nv50_display_unk20_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nv50_display *disp = nv50_display(dev);
 	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0;
 	struct dcb_entry *dcb;
-	int i, crtc, or, type = OUTPUT_ANY;
+	int i, crtc, or = 0, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
 	dcb = disp->irq.dcb;
 	if (dcb) {
-		nouveau_bios_run_display_table(dev, dcb, 0, -2);
+		nouveau_bios_run_display_table(dev, 0, -2, dcb, -1);
 		disp->irq.dcb = NULL;
 	}
 
@@ -837,9 +797,15 @@ nv50_display_unk20_handler(struct drm_de
 	}
 
 	script = nv50_display_script_select(dev, dcb, mc, pclk);
-	nouveau_bios_run_display_table(dev, dcb, script, pclk);
+	nouveau_bios_run_display_table(dev, script, pclk, dcb, -1);
 
-	nv50_display_unk20_dp_hack(dev, dcb);
+	if (type == OUTPUT_DP) {
+		int link = !(dcb->dpconf.sor.link & 1);
+		if ((mc & 0x000f0000) == 0x00020000)
+			nouveau_dp_tu_update(dev, or, link, pclk, 18);
+		else
+			nouveau_dp_tu_update(dev, or, link, pclk, 24);
+	}
 
 	if (dcb->type != OUTPUT_ANALOG) {
 		tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or));
@@ -904,7 +870,7 @@ nv50_display_unk40_handler(struct drm_de
 	if (!dcb)
 		goto ack;
 
-	nouveau_bios_run_display_table(dev, dcb, script, -pclk);
+	nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1);
 	nv50_display_unk40_dp_set_tmds(dev, dcb);
 
 ack:
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, en
 }
 
 int
+nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
+{
+	struct dcb_gpio_entry *gpio;
+	u32 v;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return -ENOENT;
+
+	v  = nv_rd32(dev, 0x00d610 + (gpio->line * 4));
+	v &= 0x00004000;
+	return (!!v == (gpio->state[1] & 1));
+}
+
+int
+nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
+{
+	struct dcb_gpio_entry *gpio;
+	u32 v;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return -ENOENT;
+
+	v = gpio->state[state] ^ 2;
+
+	nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12);
+	return 0;
+}
+
+int
 nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag,
 		       void (*handler)(void *, int), void *data)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c	2012-01-04 18:55:44.000000000 -0500
@@ -120,70 +120,62 @@ nv50_graph_unload_context(struct drm_dev
 	return 0;
 }
 
-static void
-nv50_graph_init_reset(struct drm_device *dev)
-{
-	uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
-	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |  pmc_e);
-}
-
-static void
-nv50_graph_init_intr(struct drm_device *dev)
-{
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
-	nv_wr32(dev, 0x400138, 0xffffffff);
-	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
-}
-
-static void
-nv50_graph_init_regs__nv(struct drm_device *dev)
+static int
+nv50_graph_init(struct drm_device *dev, int engine)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t units = nv_rd32(dev, 0x1540);
+	struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
+	u32 units = nv_rd32(dev, 0x001540);
 	int i;
 
 	NV_DEBUG(dev, "\n");
 
+	/* master reset */
+	nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
+	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
+
+	/* reset/enable traps and interrupts */
 	nv_wr32(dev, 0x400804, 0xc0000000);
 	nv_wr32(dev, 0x406800, 0xc0000000);
 	nv_wr32(dev, 0x400c04, 0xc0000000);
 	nv_wr32(dev, 0x401800, 0xc0000000);
 	nv_wr32(dev, 0x405018, 0xc0000000);
 	nv_wr32(dev, 0x402000, 0xc0000000);
-
 	for (i = 0; i < 16; i++) {
-		if (units & 1 << i) {
-			if (dev_priv->chipset < 0xa0) {
-				nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
-				nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
-				nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
-			} else {
-				nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
-				nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
-				nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
-			}
+		if (!(units & (1 << i)))
+			continue;
+
+		if (dev_priv->chipset < 0xa0) {
+			nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
+			nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
+			nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
+		} else {
+			nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
+			nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
+			nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
 		}
 	}
 
 	nv_wr32(dev, 0x400108, 0xffffffff);
-
-	nv_wr32(dev, 0x400824, 0x00004000);
+	nv_wr32(dev, 0x400138, 0xffffffff);
+	nv_wr32(dev, 0x400100, 0xffffffff);
+	nv_wr32(dev, 0x40013c, 0xffffffff);
 	nv_wr32(dev, 0x400500, 0x00010001);
-}
 
-static void
-nv50_graph_init_zcull(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int i;
-
-	NV_DEBUG(dev, "\n");
+	/* upload context program, initialise ctxctl defaults */
+	nv_wr32(dev, 0x400324, 0x00000000);
+	for (i = 0; i < pgraph->ctxprog_size; i++)
+		nv_wr32(dev, 0x400328, pgraph->ctxprog[i]);
+	nv_wr32(dev, 0x400824, 0x00000000);
+	nv_wr32(dev, 0x400828, 0x00000000);
+	nv_wr32(dev, 0x40082c, 0x00000000);
+	nv_wr32(dev, 0x400830, 0x00000000);
+	nv_wr32(dev, 0x400724, 0x00000000);
+	nv_wr32(dev, 0x40032c, 0x00000000);
+	nv_wr32(dev, 0x400320, 4);	/* CTXCTL_CMD = NEWCTXDMA */
 
+	/* some unknown zcull magic */
 	switch (dev_priv->chipset & 0xf0) {
 	case 0x50:
 	case 0x80:
@@ -212,43 +204,7 @@ nv50_graph_init_zcull(struct drm_device
 		nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
 		nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
 	}
-}
-
-static int
-nv50_graph_init_ctxctl(struct drm_device *dev)
-{
-	struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR);
-	int i;
 
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
-	for (i = 0; i < pgraph->ctxprog_size; i++)
-		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]);
-
-	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
-	nv_wr32(dev, 0x400320, 4);
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
-	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
-	return 0;
-}
-
-static int
-nv50_graph_init(struct drm_device *dev, int engine)
-{
-	int ret;
-
-	NV_DEBUG(dev, "\n");
-
-	nv50_graph_init_reset(dev);
-	nv50_graph_init_regs__nv(dev);
-	nv50_graph_init_zcull(dev);
-
-	ret = nv50_graph_init_ctxctl(dev);
-	if (ret)
-		return ret;
-
-	nv50_graph_init_intr(dev);
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_grctx.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_grctx.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_grctx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_grctx.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,12 @@
 #define CP_FLAG_UNK0B                 ((0 * 32) + 0xb)
 #define CP_FLAG_UNK0B_CLEAR           0
 #define CP_FLAG_UNK0B_SET             1
+#define CP_FLAG_XFER_SWITCH           ((0 * 32) + 0xe)
+#define CP_FLAG_XFER_SWITCH_DISABLE   0
+#define CP_FLAG_XFER_SWITCH_ENABLE    1
+#define CP_FLAG_STATE                 ((0 * 32) + 0x1c)
+#define CP_FLAG_STATE_STOPPED         0
+#define CP_FLAG_STATE_RUNNING         1
 #define CP_FLAG_UNK1D                 ((0 * 32) + 0x1d)
 #define CP_FLAG_UNK1D_CLEAR           0
 #define CP_FLAG_UNK1D_SET             1
@@ -194,6 +200,9 @@ nv50_grctx_init(struct nouveau_grctx *ct
 				   "the devs.\n");
 		return -ENOSYS;
 	}
+
+	cp_set (ctx, STATE, RUNNING);
+	cp_set (ctx, XFER_SWITCH, ENABLE);
 	/* decide whether we're loading/unloading the context */
 	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
 	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
@@ -260,6 +269,8 @@ nv50_grctx_init(struct nouveau_grctx *ct
 	cp_name(ctx, cp_exit);
 	cp_set (ctx, USER_SAVE, NOT_PENDING);
 	cp_set (ctx, USER_LOAD, NOT_PENDING);
+	cp_set (ctx, XFER_SWITCH, DISABLE);
+	cp_set (ctx, STATE, STOPPED);
 	cp_out (ctx, CP_END);
 	ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
 
@@ -590,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau
 					gr_def(ctx, offset + 0x1c, 0x00880000);
 					break;
 				case 0x86:
-					gr_def(ctx, offset + 0x1c, 0x008c0000);
+					gr_def(ctx, offset + 0x1c, 0x018c0000);
 					break;
 				case 0x92:
 				case 0x96:
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,15 +115,15 @@ nv50_pm_clock_set(struct drm_device *dev
 	    BIT_M.version == 1 && BIT_M.length >= 0x0b) {
 		script = ROM16(BIT_M.data[0x05]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 		script = ROM16(BIT_M.data[0x07]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 		script = ROM16(BIT_M.data[0x09]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 
-		nouveau_bios_run_init_table(dev, perflvl->memscript, NULL);
+		nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1);
 	}
 
 	if (state->type == PLL_MEMORY) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_sor.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_sor.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_sor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_sor.c	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@ nv50_sor_dpms(struct drm_encoder *encode
 		if (mode == DRM_MODE_DPMS_ON) {
 			u8 status = DP_SET_POWER_D0;
 			nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
-			nouveau_dp_link_train(encoder);
+			nouveau_dp_link_train(encoder, nv_encoder->dp.datarate);
 		} else {
 			u8 status = DP_SET_POWER_D3;
 			nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
@@ -187,14 +187,13 @@ nv50_sor_mode_set(struct drm_encoder *en
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector;
 	uint32_t mode_ctl = 0;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n",
 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index);
 
-	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
-
 	switch (nv_encoder->dcb->type) {
 	case OUTPUT_TMDS:
 		if (nv_encoder->dcb->sorconf.link & 1) {
@@ -206,7 +205,15 @@ nv50_sor_mode_set(struct drm_encoder *en
 			mode_ctl = 0x0200;
 		break;
 	case OUTPUT_DP:
-		mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
+		nv_connector = nouveau_encoder_connector_get(nv_encoder);
+		if (nv_connector && nv_connector->base.display_info.bpc == 6) {
+			nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8;
+			mode_ctl |= 0x00020000;
+		} else {
+			nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8;
+			mode_ctl |= 0x00050000;
+		}
+
 		if (nv_encoder->dcb->sorconf.link & 1)
 			mode_ctl |= 0x00000800;
 		else
@@ -227,6 +234,8 @@ nv50_sor_mode_set(struct drm_encoder *en
 	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
 		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
 
+	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
 	ret = RING_SPACE(evo, 2);
 	if (ret) {
 		NV_ERROR(dev, "no space while connecting SOR\n");
@@ -313,31 +322,6 @@ nv50_sor_create(struct drm_connector *co
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 
-	if (nv_encoder->dcb->type == OUTPUT_DP) {
-		int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
-		uint32_t tmp;
-
-		tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
-		if (!tmp)
-			tmp = nv_rd32(dev, 0x610798 + (or * 8));
-
-		switch ((tmp & 0x00000f00) >> 8) {
-		case 8:
-		case 9:
-			nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16;
-			tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-			nv_encoder->dp.unk0 = tmp & 0x000001fc;
-			tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
-			nv_encoder->dp.unk1 = tmp & 0x010f7f3f;
-			break;
-		default:
-			break;
-		}
-
-		if (!nv_encoder->dp.mc_unknown)
-			nv_encoder->dp.mc_unknown = 5;
-	}
-
 	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@ void
 nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *this;
 	struct nouveau_mem *mem;
 
@@ -82,7 +82,7 @@ nv50_vram_new(struct drm_device *dev, u6
 	      u32 memtype, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int comp = (memtype & 0x300) >> 8;
@@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev)
 	colbits  =  (r4 & 0x0000f000) >> 12;
 	rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
 	rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-	banks    = ((r4 & 0x01000000) ? 8 : 4);
+	banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
 
 	rowsize = parts * banks * (1 << colbits) * 8;
 	predicted = rowsize << rowbitsa;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nva3_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nva3_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nva3_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nva3_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,178 +27,316 @@
 #include "nouveau_bios.h"
 #include "nouveau_pm.h"
 
-/* This is actually a lot more complex than it appears here, but hopefully
- * this should be able to deal with what the VBIOS leaves for us..
- *
- * If not, well, I'll jump off that bridge when I come to it.
- */
+static u32 read_clk(struct drm_device *, int, bool);
+static u32 read_pll(struct drm_device *, int, u32);
 
-struct nva3_pm_state {
-	enum pll_types type;
-	u32 src0;
-	u32 src1;
-	u32 ctrl;
-	u32 coef;
-	u32 old_pnm;
-	u32 new_pnm;
-	u32 new_div;
-};
+static u32
+read_vco(struct drm_device *dev, int clk)
+{
+	u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+	if ((sctl & 0x00000030) != 0x00000030)
+		return read_pll(dev, 0x41, 0x00e820);
+	return read_pll(dev, 0x42, 0x00e8a0);
+}
 
-static int
-nva3_pm_pll_offset(u32 id)
+static u32
+read_clk(struct drm_device *dev, int clk, bool ignore_en)
 {
-	static const u32 pll_map[] = {
-		0x00, PLL_CORE,
-		0x01, PLL_SHADER,
-		0x02, PLL_MEMORY,
-		0x00, 0x00
-	};
-	const u32 *map = pll_map;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 sctl, sdiv, sclk;
 
-	while (map[1]) {
-		if (id == map[1])
-			return map[0];
-		map += 2;
+	/* refclk for the 0xe8xx plls is a fixed frequency */
+	if (clk >= 0x40) {
+		if (dev_priv->chipset == 0xaf) {
+			/* no joke.. seriously.. sigh.. */
+			return nv_rd32(dev, 0x00471c) * 1000;
+		}
+
+		return dev_priv->crystal;
 	}
 
-	return -ENOENT;
+	sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+	if (!ignore_en && !(sctl & 0x00000100))
+		return 0;
+
+	switch (sctl & 0x00003000) {
+	case 0x00000000:
+		return dev_priv->crystal;
+	case 0x00002000:
+		if (sctl & 0x00000040)
+			return 108000;
+		return 100000;
+	case 0x00003000:
+		sclk = read_vco(dev, clk);
+		sdiv = ((sctl & 0x003f0000) >> 16) + 2;
+		return (sclk * 2) / sdiv;
+	default:
+		return 0;
+	}
 }
 
-int
-nva3_pm_clock_get(struct drm_device *dev, u32 id)
+static u32
+read_pll(struct drm_device *dev, int clk, u32 pll)
 {
-	u32 src0, src1, ctrl, coef;
-	struct pll_lims pll;
-	int ret, off;
-	int P, N, M;
+	u32 ctrl = nv_rd32(dev, pll + 0);
+	u32 sclk = 0, P = 1, N = 1, M = 1;
 
-	ret = get_pll_limits(dev, id, &pll);
+	if (!(ctrl & 0x00000008)) {
+		if (ctrl & 0x00000001) {
+			u32 coef = nv_rd32(dev, pll + 4);
+			M = (coef & 0x000000ff) >> 0;
+			N = (coef & 0x0000ff00) >> 8;
+			P = (coef & 0x003f0000) >> 16;
+
+			/* no post-divider on these.. */
+			if ((pll & 0x00ff00) == 0x00e800)
+				P = 1;
+
+			sclk = read_clk(dev, 0x00 + clk, false);
+		}
+	} else {
+		sclk = read_clk(dev, 0x10 + clk, false);
+	}
+
+	return sclk * N / (M * P);
+}
+
+struct creg {
+	u32 clk;
+	u32 pll;
+};
+
+static int
+calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg)
+{
+	struct pll_lims limits;
+	u32 oclk, sclk, sdiv;
+	int P, N, M, diff;
+	int ret;
+
+	reg->pll = 0;
+	reg->clk = 0;
+	if (!khz) {
+		NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk);
+		return 0;
+	}
+
+	switch (khz) {
+	case 27000:
+		reg->clk = 0x00000100;
+		return khz;
+	case 100000:
+		reg->clk = 0x00002100;
+		return khz;
+	case 108000:
+		reg->clk = 0x00002140;
+		return khz;
+	default:
+		sclk = read_vco(dev, clk);
+		sdiv = min((sclk * 2) / (khz - 2999), (u32)65);
+		/* if the clock has a PLL attached, and we can get a within
+		 * [-2, 3) MHz of a divider, we'll disable the PLL and use
+		 * the divider instead.
+		 *
+		 * divider can go as low as 2, limited here because NVIDIA
+		 * and the VBIOS on my NVA8 seem to prefer using the PLL
+		 * for 810MHz - is there a good reason?
+		 */
+		if (sdiv > 4) {
+			oclk = (sclk * 2) / sdiv;
+			diff = khz - oclk;
+			if (!pll || (diff >= -2000 && diff < 3000)) {
+				reg->clk = (((sdiv - 2) << 16) | 0x00003100);
+				return oclk;
+			}
+		}
+
+		if (!pll) {
+			NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk);
+			return -ERANGE;
+		}
+
+		break;
+	}
+
+	ret = get_pll_limits(dev, pll, &limits);
 	if (ret)
 		return ret;
 
-	off = nva3_pm_pll_offset(id);
-	if (off < 0)
-		return off;
+	limits.refclk = read_clk(dev, clk - 0x10, true);
+	if (!limits.refclk)
+		return -EINVAL;
 
-	src0 = nv_rd32(dev, 0x4120 + (off * 4));
-	src1 = nv_rd32(dev, 0x4160 + (off * 4));
-	ctrl = nv_rd32(dev, pll.reg + 0);
-	coef = nv_rd32(dev, pll.reg + 4);
-	NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-		      id, src0, src1, ctrl, coef);
+	ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
+	if (ret >= 0) {
+		reg->clk = nv_rd32(dev, 0x4120 + (clk * 4));
+		reg->pll = (P << 16) | (N << 8) | M;
+	}
+	return ret;
+}
 
-	if (ctrl & 0x00000008) {
-		u32 div = ((src1 & 0x003c0000) >> 18) + 1;
-		return (pll.refclk * 2) / div;
+static void
+prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg)
+{
+	const u32 src0 = 0x004120 + (clk * 4);
+	const u32 src1 = 0x004160 + (clk * 4);
+	const u32 ctrl = pll + 0;
+	const u32 coef = pll + 4;
+	u32 cntl;
+
+	if (!reg->clk && !reg->pll) {
+		NV_DEBUG(dev, "no clock for %02x\n", clk);
+		return;
 	}
 
-	P = (coef & 0x003f0000) >> 16;
-	N = (coef & 0x0000ff00) >> 8;
-	M = (coef & 0x000000ff);
-	return pll.refclk * N / M / P;
+	cntl = nv_rd32(dev, ctrl) & 0xfffffff2;
+	if (reg->pll) {
+		nv_mask(dev, src0, 0x00000101, 0x00000101);
+		nv_wr32(dev, coef, reg->pll);
+		nv_wr32(dev, ctrl, cntl | 0x00000015);
+		nv_mask(dev, src1, 0x00000100, 0x00000000);
+		nv_mask(dev, src1, 0x00000001, 0x00000000);
+	} else {
+		nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk);
+		nv_wr32(dev, ctrl, cntl | 0x0000001d);
+		nv_mask(dev, ctrl, 0x00000001, 0x00000000);
+		nv_mask(dev, src0, 0x00000100, 0x00000000);
+		nv_mask(dev, src0, 0x00000001, 0x00000000);
+	}
 }
 
-void *
-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
-		  u32 id, int khz)
+static void
+prog_clk(struct drm_device *dev, int clk, struct creg *reg)
 {
-	struct nva3_pm_state *pll;
-	struct pll_lims limits;
-	int N, M, P, diff;
-	int ret, off;
+	if (!reg->clk) {
+		NV_DEBUG(dev, "no clock for %02x\n", clk);
+		return;
+	}
 
-	ret = get_pll_limits(dev, id, &limits);
-	if (ret < 0)
-		return (ret == -ENOENT) ? NULL : ERR_PTR(ret);
+	nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk);
+}
 
-	off = nva3_pm_pll_offset(id);
-	if (id < 0)
-		return ERR_PTR(-EINVAL);
+int
+nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	perflvl->core   = read_pll(dev, 0x00, 0x4200);
+	perflvl->shader = read_pll(dev, 0x01, 0x4220);
+	perflvl->memory = read_pll(dev, 0x02, 0x4000);
+	perflvl->unka0  = read_clk(dev, 0x20, false);
+	perflvl->vdec   = read_clk(dev, 0x21, false);
+	perflvl->daemon = read_clk(dev, 0x25, false);
+	perflvl->copy   = perflvl->core;
+	return 0;
+}
+
+struct nva3_pm_state {
+	struct creg nclk;
+	struct creg sclk;
+	struct creg mclk;
+	struct creg vdec;
+	struct creg unka0;
+};
 
+void *
+nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	struct nva3_pm_state *info;
+	int ret;
 
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll)
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
 		return ERR_PTR(-ENOMEM);
-	pll->type = id;
-	pll->src0 = 0x004120 + (off * 4);
-	pll->src1 = 0x004160 + (off * 4);
-	pll->ctrl = limits.reg + 0;
-	pll->coef = limits.reg + 4;
 
-	/* If target clock is within [-2, 3) MHz of a divisor, we'll
-	 * use that instead of calculating MNP values
-	 */
-	pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16);
-	if (pll->new_div) {
-		diff = khz - ((limits.refclk * 2) / pll->new_div);
-		if (diff < -2000 || diff >= 3000)
-			pll->new_div = 0;
-	}
+	ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk);
+	if (ret < 0)
+		goto out;
 
-	if (!pll->new_div) {
-		ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
-		if (ret < 0)
-			return ERR_PTR(ret);
+	ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk);
+	if (ret < 0)
+		goto out;
 
-		pll->new_pnm = (P << 16) | (N << 8) | M;
-		pll->new_div = 2 - 1;
-	} else {
-		pll->new_pnm = 0;
-		pll->new_div--;
+	ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk);
+	if (ret < 0)
+		goto out;
+
+	ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0);
+	if (ret < 0)
+		goto out;
+
+	ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec);
+	if (ret < 0)
+		goto out;
+
+out:
+	if (ret < 0) {
+		kfree(info);
+		info = ERR_PTR(ret);
 	}
+	return info;
+}
 
-	if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101)
-		pll->old_pnm = nv_rd32(dev, pll->coef);
-	return pll;
+static bool
+nva3_pm_grcp_idle(void *data)
+{
+	struct drm_device *dev = data;
+
+	if (!(nv_rd32(dev, 0x400304) & 0x00000001))
+		return true;
+	if (nv_rd32(dev, 0x400308) == 0x0050001c)
+		return true;
+	return false;
 }
 
 void
-nva3_pm_clock_set(struct drm_device *dev, void *pre_state)
+nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
 {
-	struct nva3_pm_state *pll = pre_state;
-	u32 ctrl = 0;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nva3_pm_state *info = pre_state;
+	unsigned long flags;
 
-	/* For the memory clock, NVIDIA will build a "script" describing
-	 * the reclocking process and ask PDAEMON to execute it.
-	 */
-	if (pll->type == PLL_MEMORY) {
-		nv_wr32(dev, 0x100210, 0);
-		nv_wr32(dev, 0x1002dc, 1);
-		nv_wr32(dev, 0x004018, 0x00001000);
-		ctrl = 0x18000100;
+	/* prevent any new grctx switches from starting */
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_wr32(dev, 0x400324, 0x00000000);
+	nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */
+	/* wait for any pending grctx switches to complete */
+	if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) {
+		NV_ERROR(dev, "pm: ctxprog didn't go idle\n");
+		goto cleanup;
 	}
-
-	if (pll->old_pnm || !pll->new_pnm) {
-		nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 |
-						    (pll->new_div << 18));
-		nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
-		nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
+	/* freeze PFIFO */
+	nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
+	if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) {
+		NV_ERROR(dev, "pm: fifo didn't go idle\n");
+		goto cleanup;
 	}
 
-	if (pll->new_pnm) {
-		nv_mask(dev, pll->src0, 0x00000101, 0x00000101);
-		nv_wr32(dev, pll->coef, pll->new_pnm);
-		nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
-		nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000);
-		nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010);
-		nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl);
-		nv_mask(dev, pll->src1, 0x00000100, 0x00000000);
-		nv_mask(dev, pll->src1, 0x00000001, 0x00000000);
-		if (pll->type == PLL_MEMORY)
-			nv_wr32(dev, 0x4018, 0x10005000);
-	} else {
-		nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
-		nv_mask(dev, pll->src0, 0x00000100, 0x00000000);
-		nv_mask(dev, pll->src0, 0x00000001, 0x00000000);
-		if (pll->type == PLL_MEMORY)
-			nv_wr32(dev, 0x4018, 0x1000d000);
-	}
+	prog_pll(dev, 0x00, 0x004200, &info->nclk);
+	prog_pll(dev, 0x01, 0x004220, &info->sclk);
+	prog_clk(dev, 0x20, &info->unka0);
+	prog_clk(dev, 0x21, &info->vdec);
 
-	if (pll->type == PLL_MEMORY) {
+	if (info->mclk.clk || info->mclk.pll) {
+		nv_wr32(dev, 0x100210, 0);
+		nv_wr32(dev, 0x1002dc, 1);
+		nv_wr32(dev, 0x004018, 0x00001000);
+		prog_pll(dev, 0x02, 0x004000, &info->mclk);
+		if (nv_rd32(dev, 0x4000) & 0x00000008)
+			nv_wr32(dev, 0x004018, 0x1000d000);
+		else
+			nv_wr32(dev, 0x004018, 0x10005000);
 		nv_wr32(dev, 0x1002dc, 0);
 		nv_wr32(dev, 0x100210, 0x80000000);
 	}
 
-	kfree(pll);
+cleanup:
+	/* unfreeze PFIFO */
+	nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
+	/* restore ctxprog to normal */
+	nv_wr32(dev, 0x400324, 0x00000000);
+	nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */
+	/* unblock it if necessary */
+	if (nv_rd32(dev, 0x400308) == 0x0050001c)
+		nv_mask(dev, 0x400824, 0x10000000, 0x10000000);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+	kfree(info);
 }
-
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_fb.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_fb.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,30 @@ struct nvc0_fb_priv {
 	dma_addr_t r100c10;
 };
 
+static inline void
+nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp)
+{
+	u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
+	u32 stat = nv_rd32(dev, subp_base + 0x020);
+
+	if (stat) {
+		NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat);
+		nv_wr32(dev, subp_base + 0x020, stat);
+	}
+}
+
+static void
+nvc0_mfb_isr(struct drm_device *dev)
+{
+	u32 units = nv_rd32(dev, 0x00017c);
+	while (units) {
+		u32 subp, unit = ffs(units) - 1;
+		for (subp = 0; subp < 2; subp++)
+			nvc0_mfb_subp_isr(dev, unit, subp);
+		units &= ~(1 << unit);
+	}
+}
+
 static void
 nvc0_fb_destroy(struct drm_device *dev)
 {
@@ -39,6 +63,8 @@ nvc0_fb_destroy(struct drm_device *dev)
 	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nvc0_fb_priv *priv = pfb->priv;
 
+	nouveau_irq_unregister(dev, 25);
+
 	if (priv->r100c10_page) {
 		pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
 			       PCI_DMA_BIDIRECTIONAL);
@@ -74,6 +100,7 @@ nvc0_fb_create(struct drm_device *dev)
 		return -EFAULT;
 	}
 
+	nouveau_irq_register(dev, 25, nvc0_mfb_isr);
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -322,7 +322,7 @@ nvc0_fifo_init(struct drm_device *dev)
 	}
 
 	/* PSUBFIFO[n] */
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < priv->spoon_nr; i++) {
 		nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
 		nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
 		nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c	2013-05-02 01:33:21.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c	2013-05-01 23:41:22.000000000 -0400
@@ -23,6 +23,7 @@
  */
 
 #include <linux/firmware.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 
@@ -156,8 +157,8 @@ nvc0_graph_create_context_mmio_list(stru
 	struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
 	struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	int i = 0, gpc, tp, ret;
-	u32 magic;
 
 	ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
 				 &grch->unk408004);
@@ -206,14 +207,37 @@ nvc0_graph_create_context_mmio_list(stru
 	nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
 	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
-	magic = 0x02180000;
-	nv_wo32(grch->mmio, i++ * 4, 0x00405830);
-	nv_wo32(grch->mmio, i++ * 4, magic);
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
-			u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
-			nv_wo32(grch->mmio, i++ * 4, reg);
-			nv_wo32(grch->mmio, i++ * 4, magic);
+	if (dev_priv->chipset != 0xc1) {
+		u32 magic = 0x02180000;
+		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+		nv_wo32(grch->mmio, i++ * 4, magic);
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x520);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, magic);
+				magic += 0x0324;
+			}
+		}
+	} else {
+		u32 magic = 0x02180000;
+		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+		nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
+		nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
+		nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x520);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
+				magic += 0x0324;
+			}
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x544);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, magic);
+				magic += 0x0324;
+			}
 		}
 	}
 
@@ -357,6 +381,8 @@ nvc0_graph_init_gpc_0(struct drm_device
 	u8  tpnr[GPC_MAX];
 	int i, gpc, tpc;
 
+	nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */
+
 	/*
 	 *      TP      ROP UNKVAL(magic_not_rop_nr)
 	 * 450: 4/0/0/0 2        3
@@ -390,7 +416,7 @@ nvc0_graph_init_gpc_0(struct drm_device
 	}
 
 	nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
-	nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
+	nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800));
 }
 
 static void
@@ -700,22 +726,6 @@ nvc0_graph_isr(struct drm_device *dev)
 	nv_wr32(dev, 0x400500, 0x00010001);
 }
 
-static void
-nvc0_runk140_isr(struct drm_device *dev)
-{
-	u32 units = nv_rd32(dev, 0x00017c) & 0x1f;
-
-	while (units) {
-		u32 unit = ffs(units) - 1;
-		u32 reg = 0x140000 + unit * 0x2000;
-		u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
-		u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
-
-		NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
-		units &= ~(1 << unit);
-	}
-}
-
 static int
 nvc0_graph_create_fw(struct drm_device *dev, const char *fwname,
 		     struct nvc0_graph_fuc *fuc)
@@ -764,7 +774,6 @@ nvc0_graph_destroy(struct drm_device *de
 	}
 
 	nouveau_irq_unregister(dev, 12);
-	nouveau_irq_unregister(dev, 25);
 
 	nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
 	nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
@@ -803,7 +812,6 @@ nvc0_graph_create(struct drm_device *dev
 
 	NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
 	nouveau_irq_register(dev, 12, nvc0_graph_isr);
-	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 
 	if (nouveau_ctxfw) {
 		NV_INFO(dev, "PGRAPH: using external firmware\n");
@@ -864,6 +872,9 @@ nvc0_graph_create(struct drm_device *dev
 	case 0xce: /* 4/4/0/0, 4 */
 		priv->magic_not_rop_nr = 0x03;
 		break;
+	case 0xcf: /* 4/0/0/0, 3 */
+		priv->magic_not_rop_nr = 0x03;
+		break;
 	}
 
 	if (!priv->magic_not_rop_nr) {
@@ -889,5 +900,3 @@ error:
 	nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR);
 	return ret;
 }
-
-/*(DEBLOBBED)*/
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h	2012-01-04 18:55:44.000000000 -0500
@@ -82,6 +82,7 @@ nvc0_graph_class(struct drm_device *dev)
 	case 0xc3:
 	case 0xc4:
 	case 0xce: /* guess, mmio trace shows only 0x9097 state */
+	case 0xcf: /* guess, mmio trace shows only 0x9097 state */
 		return 0x9097;
 	case 0xc1:
 		return 0x9197;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1678,7 +1678,10 @@ nvc0_grctx_generate_tp(struct drm_device
 	nv_wr32(dev, 0x419c04, 0x00000006);
 	nv_wr32(dev, 0x419c08, 0x00000002);
 	nv_wr32(dev, 0x419c20, 0x00000000);
-	nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
+	if (chipset == 0xce || chipset == 0xcf)
+		nv_wr32(dev, 0x419cb0, 0x00020048);
+	else
+		nv_wr32(dev, 0x419cb0, 0x00060048);
 	nv_wr32(dev, 0x419ce8, 0x00000000);
 	nv_wr32(dev, 0x419cf4, 0x00000183);
 	nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
@@ -1783,11 +1786,7 @@ nvc0_grctx_generate(struct nouveau_chann
 	nv_wr32(dev, 0x40587c, 0x00000000);
 
 	if (1) {
-		const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
-					      16, 0, 0, 0, 0, 0, 8, 0 };
-		u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
-		u8 tpnr[GPC_MAX];
-		u8 data[TP_MAX];
+		u8 tpnr[GPC_MAX], data[TP_MAX];
 
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 		memset(data, 0x1f, sizeof(data));
@@ -1801,7 +1800,7 @@ nvc0_grctx_generate(struct nouveau_chann
 			data[tp] = gpc;
 		}
 
-		for (i = 0; i < max / 4; i++)
+		for (i = 0; i < 4; i++)
 			nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]);
 	}
 
@@ -1813,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_chann
 		/* calculate first set of magics */
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 
+		gpc = -1;
 		for (tp = 0; tp < priv->tp_total; tp++) {
 			do {
 				gpc = (gpc + 1) % priv->gpc_nr;
@@ -1862,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_chann
 
 	if (1) {
 		u32 tp_mask = 0, tp_set = 0;
-		u8  tpnr[GPC_MAX];
+		u8  tpnr[GPC_MAX], a, b;
 
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 		for (gpc = 0; gpc < priv->gpc_nr; gpc++)
 			tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
 
-		gpc = -1;
-		for (i = 0, gpc = -1; i < 32; i++) {
-			int ltp = i * (priv->tp_total - 1) / 32;
-
-			do {
-				gpc = (gpc + 1) % priv->gpc_nr;
-			} while (!tpnr[gpc]);
-			tp = priv->tp_nr[gpc] - tpnr[gpc]--;
+		for (i = 0, gpc = -1, b = -1; i < 32; i++) {
+			a = (i * (priv->tp_total - 1)) / 32;
+			if (a != b) {
+				b = a;
+				do {
+					gpc = (gpc + 1) % priv->gpc_nr;
+				} while (!tpnr[gpc]);
+				tp = priv->tp_nr[gpc] - tpnr[gpc]--;
 
-			tp_set |= 1 << ((gpc * 8) + tp);
+				tp_set |= 1 << ((gpc * 8) + tp);
+			}
 
-			do {
-				nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
-				tp_set ^= tp_mask;
-				nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
-				tp_set ^= tp_mask;
-			} while (ltp == (++i * (priv->tp_total - 1) / 32));
-			i--;
+			nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
+			nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
 		}
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,11 @@ chipsets:
 .b16 nvc0_gpc_mmio_tail
 .b16 nvc0_tpc_mmio_head
 .b16 nvc3_tpc_mmio_tail
+.b8  0xcf 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvcf_tpc_mmio_tail
 .b8  0 0 0 0
 
 // GPC mmio lists
@@ -134,8 +139,9 @@ mmctx_data(0x000750, 2)
 nvc0_tpc_mmio_tail:
 mmctx_data(0x000758, 1)
 mmctx_data(0x0002c4, 1)
-mmctx_data(0x0004bc, 1)
 mmctx_data(0x0006e0, 1)
+nvcf_tpc_mmio_tail:
+mmctx_data(0x0004bc, 1)
 nvc3_tpc_mmio_tail:
 mmctx_data(0x000544, 1)
 nvc1_tpc_mmio_tail:
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,23 +25,26 @@ uint32_t nvc0_grgpc_data[] = {
 	0x00000000,
 	0x00000000,
 	0x000000c0,
-	0x011000b0,
-	0x01640114,
+	0x011c00bc,
+	0x01700120,
 	0x000000c1,
-	0x011400b0,
-	0x01780114,
+	0x012000bc,
+	0x01840120,
 	0x000000c3,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
 	0x000000c4,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
 	0x000000c8,
-	0x011000b0,
-	0x01640114,
+	0x011c00bc,
+	0x01700120,
 	0x000000ce,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
+	0x000000cf,
+	0x011c00bc,
+	0x017c0120,
 	0x00000000,
 	0x00000380,
 	0x14000400,
@@ -90,8 +93,8 @@ uint32_t nvc0_grgpc_data[] = {
 	0x04000750,
 	0x00000758,
 	0x000002c4,
-	0x000004bc,
 	0x000006e0,
+	0x000004bc,
 	0x00000544,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,9 @@ chipsets:
 .b8  0xce 0 0 0
 .b16 nvc0_hub_mmio_head
 .b16 nvc0_hub_mmio_tail
+.b8  0xcf 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
 .b8  0 0 0 0
 
 nvc0_hub_mmio_head:
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,19 @@ uint32_t nvc0_grhub_data[] = {
 	0x00000000,
 	0x00000000,
 	0x000000c0,
-	0x012c0090,
+	0x01340098,
 	0x000000c1,
-	0x01300090,
+	0x01380098,
 	0x000000c3,
-	0x012c0090,
+	0x01340098,
 	0x000000c4,
-	0x012c0090,
+	0x01340098,
 	0x000000c8,
-	0x012c0090,
+	0x01340098,
 	0x000000ce,
-	0x012c0090,
+	0x01340098,
+	0x000000cf,
+	0x01340098,
 	0x00000000,
 	0x0417e91c,
 	0x04400204,
@@ -78,8 +80,6 @@ uint32_t nvc0_grhub_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x00000000,
-	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+
+static u32 read_div(struct drm_device *, int, u32, u32);
+static u32 read_pll(struct drm_device *, u32);
+
+static u32
+read_vco(struct drm_device *dev, u32 dsrc)
+{
+	u32 ssrc = nv_rd32(dev, dsrc);
+	if (!(ssrc & 0x00000100))
+		return read_pll(dev, 0x00e800);
+	return read_pll(dev, 0x00e820);
+}
+
+static u32
+read_pll(struct drm_device *dev, u32 pll)
+{
+	u32 ctrl = nv_rd32(dev, pll + 0);
+	u32 coef = nv_rd32(dev, pll + 4);
+	u32 P = (coef & 0x003f0000) >> 16;
+	u32 N = (coef & 0x0000ff00) >> 8;
+	u32 M = (coef & 0x000000ff) >> 0;
+	u32 sclk, doff;
+
+	if (!(ctrl & 0x00000001))
+		return 0;
+
+	switch (pll & 0xfff000) {
+	case 0x00e000:
+		sclk = 27000;
+		P = 1;
+		break;
+	case 0x137000:
+		doff = (pll - 0x137000) / 0x20;
+		sclk = read_div(dev, doff, 0x137120, 0x137140);
+		break;
+	case 0x132000:
+		switch (pll) {
+		case 0x132000:
+			sclk = read_pll(dev, 0x132020);
+			break;
+		case 0x132020:
+			sclk = read_div(dev, 0, 0x137320, 0x137330);
+			break;
+		default:
+			return 0;
+		}
+		break;
+	default:
+		return 0;
+	}
+
+	return sclk * N / M / P;
+}
+
+static u32
+read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl)
+{
+	u32 ssrc = nv_rd32(dev, dsrc + (doff * 4));
+	u32 sctl = nv_rd32(dev, dctl + (doff * 4));
+
+	switch (ssrc & 0x00000003) {
+	case 0:
+		if ((ssrc & 0x00030000) != 0x00030000)
+			return 27000;
+		return 108000;
+	case 2:
+		return 100000;
+	case 3:
+		if (sctl & 0x80000000) {
+			u32 sclk = read_vco(dev, dsrc + (doff * 4));
+			u32 sdiv = (sctl & 0x0000003f) + 2;
+			return (sclk * 2) / sdiv;
+		}
+
+		return read_vco(dev, dsrc + (doff * 4));
+	default:
+		return 0;
+	}
+}
+
+static u32
+read_mem(struct drm_device *dev)
+{
+	u32 ssel = nv_rd32(dev, 0x1373f0);
+	if (ssel & 0x00000001)
+		return read_div(dev, 0, 0x137300, 0x137310);
+	return read_pll(dev, 0x132000);
+}
+
+static u32
+read_clk(struct drm_device *dev, int clk)
+{
+	u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4));
+	u32 ssel = nv_rd32(dev, 0x137100);
+	u32 sclk, sdiv;
+
+	if (ssel & (1 << clk)) {
+		if (clk < 7)
+			sclk = read_pll(dev, 0x137000 + (clk * 0x20));
+		else
+			sclk = read_pll(dev, 0x1370e0);
+		sdiv = ((sctl & 0x00003f00) >> 8) + 2;
+	} else {
+		sclk = read_div(dev, clk, 0x137160, 0x1371d0);
+		sdiv = ((sctl & 0x0000003f) >> 0) + 2;
+	}
+
+	if (sctl & 0x80000000)
+		return (sclk * 2) / sdiv;
+	return sclk;
+}
+
+int
+nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	perflvl->shader = read_clk(dev, 0x00);
+	perflvl->core   = perflvl->shader / 2;
+	perflvl->memory = read_mem(dev);
+	perflvl->rop    = read_clk(dev, 0x01);
+	perflvl->hub07  = read_clk(dev, 0x02);
+	perflvl->hub06  = read_clk(dev, 0x07);
+	perflvl->hub01  = read_clk(dev, 0x08);
+	perflvl->copy   = read_clk(dev, 0x09);
+	perflvl->daemon = read_clk(dev, 0x0c);
+	perflvl->vdec   = read_clk(dev, 0x0e);
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@ static const u8 types[256] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-	3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
+	3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
 	3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
 	3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
@@ -61,7 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u6
 	      u32 type, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int ret;
@@ -106,12 +106,54 @@ nvc0_vram_init(struct drm_device *dev)
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
 	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
-	u32 length;
+	u32 parts = nv_rd32(dev, 0x121c74);
+	u32 bsize = nv_rd32(dev, 0x10f20c);
+	u32 offset, length;
+	bool uniform = true;
+	int ret, part;
 
-	dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
-	dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
+	NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
+	NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
 
-	length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+	/* read amount of vram attached to each memory controller */
+	part = 0;
+	while (parts) {
+		u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
+		if (psize == 0)
+			continue;
+		parts--;
 
-	return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
+		if (psize != bsize) {
+			if (psize < bsize)
+				bsize = psize;
+			uniform = false;
+		}
+
+		NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
+		dev_priv->vram_size += (u64)psize << 20;
+	}
+
+	/* if all controllers have the same amount attached, there's no holes */
+	if (uniform) {
+		offset = rsvd_head;
+		length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+		return nouveau_mm_init(&vram->mm, offset, length, 1);
+	}
+
+	/* otherwise, address lowest common amount from 0GiB */
+	ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
+	if (ret)
+		return ret;
+
+	/* and the rest starting from (8GiB + common_size) */
+	offset = (0x0200000000ULL >> 12) + (bsize << 8);
+	length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
+
+	ret = nouveau_mm_init(&vram->mm, offset, length, 0);
+	if (ret) {
+		nouveau_mm_fini(&vram->mm);
+		return ret;
+	}
+
+	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvd0_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvd0_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/nouveau/nvd0_display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/nouveau/nvd0_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1473 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <linux/dma-mapping.h>
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_connector.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_dma.h"
+#include "nouveau_fb.h"
+#include "nv50_display.h"
+
+struct nvd0_display {
+	struct nouveau_gpuobj *mem;
+	struct {
+		dma_addr_t handle;
+		u32 *ptr;
+	} evo[1];
+
+	struct tasklet_struct tasklet;
+	u32 modeset;
+};
+
+static struct nvd0_display *
+nvd0_display(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return dev_priv->engine.display.priv;
+}
+
+static inline int
+evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
+{
+	int ret = 0;
+	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
+	nv_wr32(dev, 0x610704 + (id * 0x10), data);
+	nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
+	if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
+		ret = -EBUSY;
+	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
+	return ret;
+}
+
+static u32 *
+evo_wait(struct drm_device *dev, int id, int nr)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
+
+	if (put + nr >= (PAGE_SIZE / 4)) {
+		disp->evo[id].ptr[put] = 0x20000000;
+
+		nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
+		if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
+			NV_ERROR(dev, "evo %d dma stalled\n", id);
+			return NULL;
+		}
+
+		put = 0;
+	}
+
+	return disp->evo[id].ptr + put;
+}
+
+static void
+evo_kick(u32 *push, struct drm_device *dev, int id)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
+}
+
+#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
+#define evo_data(p,d)   *((p)++) = (d)
+
+static struct drm_crtc *
+nvd0_display_crtc_get(struct drm_encoder *encoder)
+{
+	return nouveau_encoder(encoder)->crtc;
+}
+
+/******************************************************************************
+ * CRTC
+ *****************************************************************************/
+static int
+nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	u32 *push, mode;
+
+	mode = 0x00000000;
+	if (on) {
+		/* 0x11: 6bpc dynamic 2x2
+		 * 0x13: 8bpc dynamic 2x2
+		 * 0x19: 6bpc static 2x2
+		 * 0x1b: 8bpc static 2x2
+		 * 0x21: 6bpc temporal
+		 * 0x23: 8bpc temporal
+		 */
+		mode = 0x00000011;
+	}
+
+	push = evo_wait(dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, mode);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, dev, 0);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update)
+{
+	struct drm_display_mode *mode = &nv_crtc->base.mode;
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct nouveau_connector *nv_connector;
+	u32 *push, outX, outY;
+
+	outX = mode->hdisplay;
+	outY = mode->vdisplay;
+
+	nv_connector = nouveau_crtc_connector_get(nv_crtc);
+	if (nv_connector && nv_connector->native_mode) {
+		struct drm_display_mode *native = nv_connector->native_mode;
+		u32 xratio = (native->hdisplay << 19) / mode->hdisplay;
+		u32 yratio = (native->vdisplay << 19) / mode->vdisplay;
+
+		switch (type) {
+		case DRM_MODE_SCALE_ASPECT:
+			if (xratio > yratio) {
+				outX = (mode->hdisplay * yratio) >> 19;
+				outY = (mode->vdisplay * yratio) >> 19;
+			} else {
+				outX = (mode->hdisplay * xratio) >> 19;
+				outY = (mode->vdisplay * xratio) >> 19;
+			}
+			break;
+		case DRM_MODE_SCALE_FULLSCREEN:
+			outX = native->hdisplay;
+			outY = native->vdisplay;
+			break;
+		default:
+			break;
+		}
+	}
+
+	push = evo_wait(dev, 0, 16);
+	if (push) {
+		evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
+		evo_data(push, (outY << 16) | outX);
+		evo_data(push, (outY << 16) | outX);
+		evo_data(push, (outY << 16) | outX);
+		evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, (mode->vdisplay << 16) | mode->hdisplay);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, dev, 0);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
+		    int x, int y, bool update)
+{
+	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
+	u32 *push;
+
+	push = evo_wait(fb->dev, 0, 16);
+	if (push) {
+		evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, nvfb->nvbo->bo.offset >> 8);
+		evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
+		evo_data(push, (fb->height << 16) | fb->width);
+		evo_data(push, nvfb->r_pitch);
+		evo_data(push, nvfb->r_format);
+		evo_data(push, nvfb->r_dma);
+		evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, (y << 16) | x);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, fb->dev, 0);
+	}
+
+	nv_crtc->fb.tile_flags = nvfb->r_dma;
+	return 0;
+}
+
+static void
+nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	u32 *push = evo_wait(dev, 0, 16);
+	if (push) {
+		if (show) {
+			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
+			evo_data(push, 0x85000000);
+			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
+			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+			evo_data(push, NvEvoVRAM);
+		} else {
+			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
+			evo_data(push, 0x05000000);
+			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+			evo_data(push, 0x00000000);
+		}
+
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+
+		evo_kick(push, dev, 0);
+	}
+}
+
+static void
+nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static void
+nvd0_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 *push;
+
+	push = evo_wait(crtc->dev, 0, 2);
+	if (push) {
+		evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x03000000);
+		evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nvd0_crtc_cursor_show(nv_crtc, false, false);
+}
+
+static void
+nvd0_crtc_commit(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 *push;
+
+	push = evo_wait(crtc->dev, 0, 32);
+	if (push) {
+		evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, nv_crtc->fb.tile_flags);
+		evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
+		evo_data(push, 0x83000000);
+		evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+		evo_data(push, 0x00000000);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, NvEvoVRAM);
+		evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0xffffff00);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
+}
+
+static bool
+nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		     struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static int
+nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+	int ret;
+
+	ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	if (old_fb) {
+		nvfb = nouveau_framebuffer(old_fb);
+		nouveau_bo_unpin(nvfb->nvbo);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
+		   struct drm_display_mode *mode, int x, int y,
+		   struct drm_framebuffer *old_fb)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nouveau_connector *nv_connector;
+	u32 htotal = mode->htotal;
+	u32 vtotal = mode->vtotal;
+	u32 hsyncw = mode->hsync_end - mode->hsync_start - 1;
+	u32 vsyncw = mode->vsync_end - mode->vsync_start - 1;
+	u32 hfrntp = mode->hsync_start - mode->hdisplay;
+	u32 vfrntp = mode->vsync_start - mode->vdisplay;
+	u32 hbackp = mode->htotal - mode->hsync_end;
+	u32 vbackp = mode->vtotal - mode->vsync_end;
+	u32 hss2be = hsyncw + hbackp;
+	u32 vss2be = vsyncw + vbackp;
+	u32 hss2de = htotal - hfrntp;
+	u32 vss2de = vtotal - vfrntp;
+	u32 syncs, *push;
+	int ret;
+
+	syncs = 0x00000001;
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		syncs |= 0x00000008;
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		syncs |= 0x00000010;
+
+	ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+	if (ret)
+		return ret;
+
+	push = evo_wait(crtc->dev, 0, 64);
+	if (push) {
+		evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5);
+		evo_data(push, 0x00000000);
+		evo_data(push, (vtotal << 16) | htotal);
+		evo_data(push, (vsyncw << 16) | hsyncw);
+		evo_data(push, (vss2be << 16) | hss2be);
+		evo_data(push, (vss2de << 16) | hss2de);
+		evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000); /* ??? */
+		evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
+		evo_data(push, mode->clock * 1000);
+		evo_data(push, 0x00200000); /* ??? */
+		evo_data(push, mode->clock * 1000);
+		evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, syncs);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nv_connector = nouveau_crtc_connector_get(nv_crtc);
+	nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false);
+	nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false);
+	nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			struct drm_framebuffer *old_fb)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	int ret;
+
+	if (!crtc->fb) {
+		NV_DEBUG_KMS(crtc->dev, "No FB bound\n");
+		return 0;
+	}
+
+	ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+	if (ret)
+		return ret;
+
+	nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
+			       struct drm_framebuffer *fb, int x, int y,
+			       enum mode_set_atomic state)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
+	return 0;
+}
+
+static void
+nvd0_crtc_lut_load(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
+	int i;
+
+	for (i = 0; i < 256; i++) {
+		writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0);
+		writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2);
+		writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4);
+	}
+}
+
+static int
+nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+		     uint32_t handle, uint32_t width, uint32_t height)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *nvbo;
+	bool visible = (handle != 0);
+	int i, ret = 0;
+
+	if (visible) {
+		if (width != 64 || height != 64)
+			return -EINVAL;
+
+		gem = drm_gem_object_lookup(dev, file_priv, handle);
+		if (unlikely(!gem))
+			return -ENOENT;
+		nvbo = nouveau_gem_object(gem);
+
+		ret = nouveau_bo_map(nvbo);
+		if (ret == 0) {
+			for (i = 0; i < 64 * 64; i++) {
+				u32 v = nouveau_bo_rd32(nvbo, i);
+				nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v);
+			}
+			nouveau_bo_unmap(nvbo);
+		}
+
+		drm_gem_object_unreference_unlocked(gem);
+	}
+
+	if (visible != nv_crtc->cursor.visible) {
+		nvd0_crtc_cursor_show(nv_crtc, visible, true);
+		nv_crtc->cursor.visible = visible;
+	}
+
+	return ret;
+}
+
+static int
+nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	const u32 data = (y << 16) | x;
+
+	nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data);
+	nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000);
+	return 0;
+}
+
+static void
+nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+		    uint32_t start, uint32_t size)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 end = max(start + size, (u32)256);
+	u32 i;
+
+	for (i = start; i < end; i++) {
+		nv_crtc->lut.r[i] = r[i];
+		nv_crtc->lut.g[i] = g[i];
+		nv_crtc->lut.b[i] = b[i];
+	}
+
+	nvd0_crtc_lut_load(crtc);
+}
+
+static void
+nvd0_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	nouveau_bo_unmap(nv_crtc->lut.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	drm_crtc_cleanup(crtc);
+	kfree(crtc);
+}
+
+static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = {
+	.dpms = nvd0_crtc_dpms,
+	.prepare = nvd0_crtc_prepare,
+	.commit = nvd0_crtc_commit,
+	.mode_fixup = nvd0_crtc_mode_fixup,
+	.mode_set = nvd0_crtc_mode_set,
+	.mode_set_base = nvd0_crtc_mode_set_base,
+	.mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic,
+	.load_lut = nvd0_crtc_lut_load,
+};
+
+static const struct drm_crtc_funcs nvd0_crtc_func = {
+	.cursor_set = nvd0_crtc_cursor_set,
+	.cursor_move = nvd0_crtc_cursor_move,
+	.gamma_set = nvd0_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = nvd0_crtc_destroy,
+};
+
+static void
+nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+}
+
+static void
+nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
+{
+}
+
+static int
+nvd0_crtc_create(struct drm_device *dev, int index)
+{
+	struct nouveau_crtc *nv_crtc;
+	struct drm_crtc *crtc;
+	int ret, i;
+
+	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
+	if (!nv_crtc)
+		return -ENOMEM;
+
+	nv_crtc->index = index;
+	nv_crtc->set_dither = nvd0_crtc_set_dither;
+	nv_crtc->set_scale = nvd0_crtc_set_scale;
+	nv_crtc->cursor.set_offset = nvd0_cursor_set_offset;
+	nv_crtc->cursor.set_pos = nvd0_cursor_set_pos;
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = i << 8;
+		nv_crtc->lut.g[i] = i << 8;
+		nv_crtc->lut.b[i] = i << 8;
+	}
+
+	crtc = &nv_crtc->base;
+	drm_crtc_init(dev, crtc, &nvd0_crtc_func);
+	drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc);
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
+	ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	}
+
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, &nv_crtc->lut.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->lut.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	}
+
+	if (ret)
+		goto out;
+
+	nvd0_crtc_lut_load(crtc);
+
+out:
+	if (ret)
+		nvd0_crtc_destroy(crtc);
+	return ret;
+}
+
+/******************************************************************************
+ * DAC
+ *****************************************************************************/
+static void
+nvd0_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	int or = nv_encoder->or;
+	u32 dpms_ctrl;
+
+	dpms_ctrl = 0x80000000;
+	if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
+		dpms_ctrl |= 0x00000001;
+	if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
+		dpms_ctrl |= 0x00000004;
+
+	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl);
+	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+}
+
+static bool
+nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *nv_connector;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	if (nv_connector && nv_connector->native_mode) {
+		if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+			int id = adjusted_mode->base.id;
+			*adjusted_mode = *nv_connector->native_mode;
+			adjusted_mode->base.id = id;
+		}
+	}
+
+	return true;
+}
+
+static void
+nvd0_dac_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	u32 *push;
+
+	nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	push = evo_wait(encoder->dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2);
+		evo_data(push, 1 << nv_crtc->index);
+		evo_data(push, 0x00ff);
+		evo_kick(push, encoder->dev, 0);
+	}
+
+	nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_dac_disconnect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		nvd0_crtc_prepare(nv_encoder->crtc);
+
+		push = evo_wait(dev, 0, 4);
+		if (push) {
+			evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+			evo_kick(push, dev, 0);
+		}
+
+		nv_encoder->crtc = NULL;
+	}
+}
+
+static enum drm_connector_status
+nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	enum drm_connector_status status = connector_status_disconnected;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	int or = nv_encoder->or;
+	u32 load;
+
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000);
+	udelay(9500);
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000);
+
+	load = nv_rd32(dev, 0x61a00c + (or * 0x800));
+	if ((load & 0x38000000) == 0x38000000)
+		status = connector_status_connected;
+
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000);
+	return status;
+}
+
+static void
+nvd0_dac_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = {
+	.dpms = nvd0_dac_dpms,
+	.mode_fixup = nvd0_dac_mode_fixup,
+	.prepare = nvd0_dac_prepare,
+	.commit = nvd0_dac_commit,
+	.mode_set = nvd0_dac_mode_set,
+	.disable = nvd0_dac_disconnect,
+	.get_crtc = nvd0_display_crtc_get,
+	.detect = nvd0_dac_detect
+};
+
+static const struct drm_encoder_funcs nvd0_dac_func = {
+	.destroy = nvd0_dac_destroy,
+};
+
+static int
+nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	nv_encoder->dcb = dcbe;
+	nv_encoder->or = ffs(dcbe->or) - 1;
+
+	encoder = to_drm_encoder(nv_encoder);
+	encoder->possible_crtcs = dcbe->heads;
+	encoder->possible_clones = 0;
+	drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC);
+	drm_encoder_helper_add(encoder, &nvd0_dac_hfunc);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+	return 0;
+}
+
+/******************************************************************************
+ * SOR
+ *****************************************************************************/
+static void
+nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_encoder *partner;
+	int or = nv_encoder->or;
+	u32 dpms_ctrl;
+
+	nv_encoder->last_dpms = mode;
+
+	list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
+
+		if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
+			continue;
+
+		if (nv_partner != nv_encoder &&
+		    nv_partner->dcb->or == nv_encoder->dcb->or) {
+			if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
+				return;
+			break;
+		}
+	}
+
+	dpms_ctrl  = (mode == DRM_MODE_DPMS_ON);
+	dpms_ctrl |= 0x80000000;
+
+	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
+	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
+}
+
+static bool
+nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *nv_connector;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	if (nv_connector && nv_connector->native_mode) {
+		if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+			int id = adjusted_mode->base.id;
+			*adjusted_mode = *nv_connector->native_mode;
+			adjusted_mode->base.id = id;
+		}
+	}
+
+	return true;
+}
+
+static void
+nvd0_sor_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
+		  struct drm_display_mode *mode)
+{
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector;
+	struct nvbios *bios = &dev_priv->vbios;
+	u32 mode_ctrl = (1 << nv_crtc->index);
+	u32 *push, or_config;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	switch (nv_encoder->dcb->type) {
+	case OUTPUT_TMDS:
+		if (nv_encoder->dcb->sorconf.link & 1) {
+			if (mode->clock < 165000)
+				mode_ctrl |= 0x00000100;
+			else
+				mode_ctrl |= 0x00000500;
+		} else {
+			mode_ctrl |= 0x00000200;
+		}
+
+		or_config = (mode_ctrl & 0x00000f00) >> 8;
+		if (mode->clock >= 165000)
+			or_config |= 0x0100;
+		break;
+	case OUTPUT_LVDS:
+		or_config = (mode_ctrl & 0x00000f00) >> 8;
+		if (bios->fp_no_ddc) {
+			if (bios->fp.dual_link)
+				or_config |= 0x0100;
+			if (bios->fp.if_is_24bit)
+				or_config |= 0x0200;
+		} else {
+			if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
+				if (((u8 *)nv_connector->edid)[121] == 2)
+					or_config |= 0x0100;
+			} else
+			if (mode->clock >= bios->fp.duallink_transition_clk) {
+				or_config |= 0x0100;
+			}
+
+			if (or_config & 0x0100) {
+				if (bios->fp.strapless_is_24bit & 2)
+					or_config |= 0x0200;
+			} else {
+				if (bios->fp.strapless_is_24bit & 1)
+					or_config |= 0x0200;
+			}
+
+			if (nv_connector->base.display_info.bpc == 8)
+				or_config |= 0x0200;
+
+		}
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	push = evo_wait(encoder->dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2);
+		evo_data(push, mode_ctrl);
+		evo_data(push, or_config);
+		evo_kick(push, encoder->dev, 0);
+	}
+
+	nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_sor_disconnect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		nvd0_crtc_prepare(nv_encoder->crtc);
+
+		push = evo_wait(dev, 0, 4);
+		if (push) {
+			evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+			evo_kick(push, dev, 0);
+		}
+
+		nv_encoder->crtc = NULL;
+		nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+	}
+}
+
+static void
+nvd0_sor_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = {
+	.dpms = nvd0_sor_dpms,
+	.mode_fixup = nvd0_sor_mode_fixup,
+	.prepare = nvd0_sor_prepare,
+	.commit = nvd0_sor_commit,
+	.mode_set = nvd0_sor_mode_set,
+	.disable = nvd0_sor_disconnect,
+	.get_crtc = nvd0_display_crtc_get,
+};
+
+static const struct drm_encoder_funcs nvd0_sor_func = {
+	.destroy = nvd0_sor_destroy,
+};
+
+static int
+nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	nv_encoder->dcb = dcbe;
+	nv_encoder->or = ffs(dcbe->or) - 1;
+	nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+
+	encoder = to_drm_encoder(nv_encoder);
+	encoder->possible_crtcs = dcbe->heads;
+	encoder->possible_clones = 0;
+	drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &nvd0_sor_hfunc);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+	return 0;
+}
+
+/******************************************************************************
+ * IRQ
+ *****************************************************************************/
+static struct dcb_entry *
+lookup_dcb(struct drm_device *dev, int id, u32 mc)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int type, or, i;
+
+	if (id < 4) {
+		type = OUTPUT_ANALOG;
+		or   = id;
+	} else {
+		switch (mc & 0x00000f00) {
+		case 0x00000000: type = OUTPUT_LVDS; break;
+		case 0x00000100: type = OUTPUT_TMDS; break;
+		case 0x00000200: type = OUTPUT_TMDS; break;
+		case 0x00000500: type = OUTPUT_TMDS; break;
+		default:
+			NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc);
+			return NULL;
+		}
+
+		or = id - 4;
+	}
+
+	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
+		struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
+		if (dcb->type == type && (dcb->or & (1 << or)))
+			return dcb;
+	}
+
+	NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc);
+	return NULL;
+}
+
+static void
+nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	int i;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+		if (!(mcc & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcc);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc);
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	u32 or, tmp, pclk;
+	int i;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+		if (!(mcc & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcc);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc);
+	}
+
+	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+	if (mask & 0x00010000) {
+		nv50_crtc_set_clock(dev, crtc, pclk);
+	}
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+		if (!(mcp & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcp);
+		if (!dcb)
+			continue;
+		or = ffs(dcb->or) - 1;
+
+		nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc);
+
+		nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000);
+		switch (dcb->type) {
+		case OUTPUT_ANALOG:
+			nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000);
+			break;
+		case OUTPUT_TMDS:
+		case OUTPUT_LVDS:
+			if (cfg & 0x00000100)
+				tmp = 0x00000101;
+			else
+				tmp = 0x00000000;
+
+			nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	int pclk, i;
+
+	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+		if (!(mcp & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcp);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc);
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_bh(unsigned long data)
+{
+	struct drm_device *dev = (struct drm_device *)data;
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 mask, crtc;
+	int i;
+
+	if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) {
+		NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset);
+		NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n",
+			 nv_rd32(dev, 0x6101d0),
+			 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
+		for (i = 0; i < 8; i++) {
+			NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n",
+				i < 4 ? "DAC" : "SOR", i,
+				nv_rd32(dev, 0x640180 + (i * 0x20)),
+				nv_rd32(dev, 0x660180 + (i * 0x20)));
+		}
+	}
+
+	mask = nv_rd32(dev, 0x6101d4);
+	crtc = 0;
+	if (!mask) {
+		mask = nv_rd32(dev, 0x6109d4);
+		crtc = 1;
+	}
+
+	if (disp->modeset & 0x00000001)
+		nvd0_display_unk1_handler(dev, crtc, mask);
+	if (disp->modeset & 0x00000002)
+		nvd0_display_unk2_handler(dev, crtc, mask);
+	if (disp->modeset & 0x00000004)
+		nvd0_display_unk4_handler(dev, crtc, mask);
+}
+
+static void
+nvd0_display_intr(struct drm_device *dev)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 intr = nv_rd32(dev, 0x610088);
+
+	if (intr & 0x00000002) {
+		u32 stat = nv_rd32(dev, 0x61009c);
+		int chid = ffs(stat) - 1;
+		if (chid >= 0) {
+			u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12));
+			u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12));
+			u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12));
+
+			NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x "
+				     "0x%08x 0x%08x\n",
+				chid, (mthd & 0x0000ffc), data, mthd, unkn);
+			nv_wr32(dev, 0x61009c, (1 << chid));
+			nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000);
+		}
+
+		intr &= ~0x00000002;
+	}
+
+	if (intr & 0x00100000) {
+		u32 stat = nv_rd32(dev, 0x6100ac);
+
+		if (stat & 0x00000007) {
+			disp->modeset = stat;
+			tasklet_schedule(&disp->tasklet);
+
+			nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
+			stat &= ~0x00000007;
+		}
+
+		if (stat) {
+			NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat);
+			nv_wr32(dev, 0x6100ac, stat);
+		}
+
+		intr &= ~0x00100000;
+	}
+
+	if (intr & 0x01000000) {
+		u32 stat = nv_rd32(dev, 0x6100bc);
+		nv_wr32(dev, 0x6100bc, stat);
+		intr &= ~0x01000000;
+	}
+
+	if (intr & 0x02000000) {
+		u32 stat = nv_rd32(dev, 0x6108bc);
+		nv_wr32(dev, 0x6108bc, stat);
+		intr &= ~0x02000000;
+	}
+
+	if (intr)
+		NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr);
+}
+
+/******************************************************************************
+ * Init
+ *****************************************************************************/
+static void
+nvd0_display_fini(struct drm_device *dev)
+{
+	int i;
+
+	/* fini cursors */
+	for (i = 14; i >= 13; i--) {
+		if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001))
+			continue;
+
+		nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000);
+		nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000);
+		nv_mask(dev, 0x610090, 1 << i, 0x00000000);
+		nv_mask(dev, 0x6100a0, 1 << i, 0x00000000);
+	}
+
+	/* fini master */
+	if (nv_rd32(dev, 0x610490) & 0x00000010) {
+		nv_mask(dev, 0x610490, 0x00000010, 0x00000000);
+		nv_mask(dev, 0x610490, 0x00000003, 0x00000000);
+		nv_wait(dev, 0x610490, 0x80000000, 0x00000000);
+		nv_mask(dev, 0x610090, 0x00000001, 0x00000000);
+		nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000);
+	}
+}
+
+int
+nvd0_display_init(struct drm_device *dev)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 *push;
+	int i;
+
+	if (nv_rd32(dev, 0x6100ac) & 0x00000100) {
+		nv_wr32(dev, 0x6100ac, 0x00000100);
+		nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000);
+		if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) {
+			NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n",
+				 nv_rd32(dev, 0x6194e8));
+			return -EBUSY;
+		}
+	}
+
+	/* nfi what these are exactly, i do know that SOR_MODE_CTRL won't
+	 * work at all unless you do the SOR part below.
+	 */
+	for (i = 0; i < 3; i++) {
+		u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800));
+		nv_wr32(dev, 0x6101c0 + (i * 0x800), dac);
+	}
+
+	for (i = 0; i < 4; i++) {
+		u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800));
+		nv_wr32(dev, 0x6301c4 + (i * 0x800), sor);
+	}
+
+	for (i = 0; i < 2; i++) {
+		u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800));
+		u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800));
+		u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800));
+		nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0);
+		nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1);
+		nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2);
+	}
+
+	/* point at our hash table / objects, enable interrupts */
+	nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9);
+	nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307);
+
+	/* init master */
+	nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3);
+	nv_wr32(dev, 0x610498, 0x00010000);
+	nv_wr32(dev, 0x61049c, 0x00000001);
+	nv_mask(dev, 0x610490, 0x00000010, 0x00000010);
+	nv_wr32(dev, 0x640000, 0x00000000);
+	nv_wr32(dev, 0x610490, 0x01000013);
+	if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) {
+		NV_ERROR(dev, "PDISP: master 0x%08x\n",
+			 nv_rd32(dev, 0x610490));
+		return -EBUSY;
+	}
+	nv_mask(dev, 0x610090, 0x00000001, 0x00000001);
+	nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001);
+
+	/* init cursors */
+	for (i = 13; i <= 14; i++) {
+		nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001);
+		if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) {
+			NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i,
+				 nv_rd32(dev, 0x610490 + (i * 0x10)));
+			return -EBUSY;
+		}
+
+		nv_mask(dev, 0x610090, 1 << i, 1 << i);
+		nv_mask(dev, 0x6100a0, 1 << i, 1 << i);
+	}
+
+	push = evo_wait(dev, 0, 32);
+	if (!push)
+		return -EBUSY;
+	evo_mthd(push, 0x0088, 1);
+	evo_data(push, NvEvoSync);
+	evo_mthd(push, 0x0084, 1);
+	evo_data(push, 0x00000000);
+	evo_mthd(push, 0x0084, 1);
+	evo_data(push, 0x80000000);
+	evo_mthd(push, 0x008c, 1);
+	evo_data(push, 0x00000000);
+	evo_kick(push, dev, 0);
+
+	return 0;
+}
+
+void
+nvd0_display_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvd0_display *disp = nvd0_display(dev);
+	struct pci_dev *pdev = dev->pdev;
+
+	nvd0_display_fini(dev);
+
+	pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle);
+	nouveau_gpuobj_ref(NULL, &disp->mem);
+	nouveau_irq_unregister(dev, 26);
+
+	dev_priv->engine.display.priv = NULL;
+	kfree(disp);
+}
+
+int
+nvd0_display_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
+	struct drm_connector *connector, *tmp;
+	struct pci_dev *pdev = dev->pdev;
+	struct nvd0_display *disp;
+	struct dcb_entry *dcbe;
+	int ret, i;
+
+	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp)
+		return -ENOMEM;
+	dev_priv->engine.display.priv = disp;
+
+	/* create crtc objects to represent the hw heads */
+	for (i = 0; i < 2; i++) {
+		ret = nvd0_crtc_create(dev, i);
+		if (ret)
+			goto out;
+	}
+
+	/* create encoder/connector objects based on VBIOS DCB table */
+	for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
+		connector = nouveau_connector_create(dev, dcbe->connector);
+		if (IS_ERR(connector))
+			continue;
+
+		if (dcbe->location != DCB_LOC_ON_CHIP) {
+			NV_WARN(dev, "skipping off-chip encoder %d/%d\n",
+				dcbe->type, ffs(dcbe->or) - 1);
+			continue;
+		}
+
+		switch (dcbe->type) {
+		case OUTPUT_TMDS:
+		case OUTPUT_LVDS:
+			nvd0_sor_create(connector, dcbe);
+			break;
+		case OUTPUT_ANALOG:
+			nvd0_dac_create(connector, dcbe);
+			break;
+		default:
+			NV_WARN(dev, "skipping unsupported encoder %d/%d\n",
+				dcbe->type, ffs(dcbe->or) - 1);
+			continue;
+		}
+	}
+
+	/* cull any connectors we created that don't have an encoder */
+	list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
+		if (connector->encoder_ids[0])
+			continue;
+
+		NV_WARN(dev, "%s has no encoders, removing\n",
+			drm_get_connector_name(connector));
+		connector->funcs->destroy(connector);
+	}
+
+	/* setup interrupt handling */
+	tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
+	nouveau_irq_register(dev, 26, nvd0_display_intr);
+
+	/* hash table and dma objects for the memory areas we care about */
+	ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000,
+				 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem);
+	if (ret)
+		goto out;
+
+	nv_wo32(disp->mem, 0x1000, 0x00000049);
+	nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8);
+	nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8);
+	nv_wo32(disp->mem, 0x100c, 0x00000000);
+	nv_wo32(disp->mem, 0x1010, 0x00000000);
+	nv_wo32(disp->mem, 0x1014, 0x00000000);
+	nv_wo32(disp->mem, 0x0000, NvEvoSync);
+	nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1020, 0x00000049);
+	nv_wo32(disp->mem, 0x1024, 0x00000000);
+	nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x102c, 0x00000000);
+	nv_wo32(disp->mem, 0x1030, 0x00000000);
+	nv_wo32(disp->mem, 0x1034, 0x00000000);
+	nv_wo32(disp->mem, 0x0008, NvEvoVRAM);
+	nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1040, 0x00000009);
+	nv_wo32(disp->mem, 0x1044, 0x00000000);
+	nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x104c, 0x00000000);
+	nv_wo32(disp->mem, 0x1050, 0x00000000);
+	nv_wo32(disp->mem, 0x1054, 0x00000000);
+	nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP);
+	nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1060, 0x0fe00009);
+	nv_wo32(disp->mem, 0x1064, 0x00000000);
+	nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x106c, 0x00000000);
+	nv_wo32(disp->mem, 0x1070, 0x00000000);
+	nv_wo32(disp->mem, 0x1074, 0x00000000);
+	nv_wo32(disp->mem, 0x0018, NvEvoFB32);
+	nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001);
+
+	pinstmem->flush(dev);
+
+	/* push buffers for evo channels */
+	disp->evo[0].ptr =
+		pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle);
+	if (!disp->evo[0].ptr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = nvd0_display_init(dev);
+	if (ret)
+		goto out;
+
+out:
+	if (ret)
+		nvd0_display_destroy(dev);
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/r128/r128_cce.c linux-libre-3.2-gnu1/drivers/gpu/drm/r128/r128_cce.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/r128/r128_cce.c	2013-05-02 01:33:25.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/r128/r128_cce.c	2013-05-01 23:41:26.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/r128/r128_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/r128/r128_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/r128/r128_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/r128/r128_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "r128_drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -558,7 +558,7 @@ static u32 atombios_adjust_pll(struct dr
 				bpc = connector->display_info.bpc;
 			encoder_mode = atombios_get_encoder_mode(encoder);
 			if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
-			    radeon_encoder_is_dp_bridge(encoder)) {
+			    (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
 				if (connector) {
 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 					struct radeon_connector_atom_dig *dig_connector =
@@ -638,44 +638,29 @@ static u32 atombios_adjust_pll(struct dr
 				if (ss_enabled && ss->percentage)
 					args.v3.sInput.ucDispPllConfig |=
 						DISPPLL_CONFIG_SS_ENABLE;
-				if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) ||
-				    radeon_encoder_is_dp_bridge(encoder)) {
+				if (ENCODER_MODE_IS_DP(encoder_mode)) {
+					args.v3.sInput.ucDispPllConfig |=
+						DISPPLL_CONFIG_COHERENT_MODE;
+					/* 16200 or 27000 */
+					args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
+				} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
 					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+					if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
+						/* deep color support */
+						args.v3.sInput.usPixelClock =
+							cpu_to_le16((mode->clock * bpc / 8) / 10);
+					if (dig->coherent_mode)
 						args.v3.sInput.ucDispPllConfig |=
 							DISPPLL_CONFIG_COHERENT_MODE;
-						/* 16200 or 27000 */
-						args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-					} else {
-						if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
-							/* deep color support */
-							args.v3.sInput.usPixelClock =
-								cpu_to_le16((mode->clock * bpc / 8) / 10);
-						}
-						if (dig->coherent_mode)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_COHERENT_MODE;
-						if (mode->clock > 165000)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_DUAL_LINK;
-					}
-				} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+					if (mode->clock > 165000)
 						args.v3.sInput.ucDispPllConfig |=
-							DISPPLL_CONFIG_COHERENT_MODE;
-						/* 16200 or 27000 */
-						args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-					} else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) {
-						if (mode->clock > 165000)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_DUAL_LINK;
-					}
+							DISPPLL_CONFIG_DUAL_LINK;
 				}
-				if (radeon_encoder_is_dp_bridge(encoder)) {
-					struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-					struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-					args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
-				} else
+				if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+				    ENCODER_OBJECT_ID_NONE)
+					args.v3.sInput.ucExtTransmitterID =
+						radeon_encoder_get_dp_bridge_encoder_id(encoder);
+				else
 					args.v3.sInput.ucExtTransmitterID = 0;
 
 				atom_execute_table(rdev->mode_info.atom_context,
@@ -945,6 +930,7 @@ static void atombios_crtc_set_pll(struct
 		bpc = connector->display_info.bpc;
 
 		switch (encoder_mode) {
+		case ATOM_ENCODER_MODE_DP_MST:
 		case ATOM_ENCODER_MODE_DP:
 			/* DP/eDP */
 			dp_clock = dig_connector->dp_clock / 10;
@@ -1121,9 +1107,40 @@ static int dce4_crtc_do_set_base(struct
 		return -EINVAL;
 	}
 
-	if (tiling_flags & RADEON_TILING_MACRO)
+	if (tiling_flags & RADEON_TILING_MACRO) {
+		if (rdev->family >= CHIP_CAYMAN)
+			tmp = rdev->config.cayman.tile_config;
+		else
+			tmp = rdev->config.evergreen.tile_config;
+
+		switch ((tmp & 0xf0) >> 4) {
+		case 0: /* 4 banks */
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+			break;
+		case 1: /* 8 banks */
+		default:
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+			break;
+		case 2: /* 16 banks */
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+			break;
+		}
+
+		switch ((tmp & 0xf000) >> 12) {
+		case 0: /* 1KB rows */
+		default:
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB);
+			break;
+		case 1: /* 2KB rows */
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB);
+			break;
+		case 2: /* 4KB rows */
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB);
+			break;
+		}
+
 		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-	else if (tiling_flags & RADEON_TILING_MICRO)
+	} else if (tiling_flags & RADEON_TILING_MICRO)
 		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
 	switch (radeon_crtc->crtc_id) {
@@ -1450,7 +1467,7 @@ static int radeon_atom_pick_pll(struct d
 				 * PPLL/DCPLL programming and only program the DP DTO for the
 				 * crtc virtual pixel clock.
 				 */
-				if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) {
+				if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
 					if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk)
 						return ATOM_PPLL_INVALID;
 				}
@@ -1536,12 +1553,6 @@ static bool atombios_crtc_mode_fixup(str
 				     struct drm_display_mode *mode,
 				     struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* adjust pm to upcoming mode change */
-	radeon_pm_compute_clocks(rdev);
-
 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 		return false;
 	return true;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_dp.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_dp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -283,7 +283,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adap
 		}
 	}
 
-	DRM_ERROR("aux i2c too many retries, giving up\n");
+	DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
 	return -EREMOTEIO;
 }
 
@@ -482,7 +482,8 @@ static int radeon_dp_get_dp_link_clock(s
 	int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
 	int lane_num, max_pix_clock;
 
-	if (radeon_connector_encoder_is_dp_bridge(connector))
+	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+	    ENCODER_OBJECT_ID_NUTMEG)
 		return 270000;
 
 	lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
@@ -553,17 +554,32 @@ static void radeon_dp_set_panel_mode(str
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
 
 	if (!ASIC_IS_DCE4(rdev))
 		return;
 
-	if (radeon_connector_encoder_is_dp_bridge(connector))
+	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+	    ENCODER_OBJECT_ID_NUTMEG)
 		panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+	else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+		 ENCODER_OBJECT_ID_TRAVIS)
+		panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+	else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+		u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+		if (tmp & 1)
+			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+	}
 
 	atombios_dig_encoder_setup(encoder,
 				   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
 				   panel_mode);
+
+	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+	    (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+		radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+	}
 }
 
 void radeon_dp_set_link_config(struct drm_connector *connector,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/atombios_encoders.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/atombios_encoders.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2369 @@
+/*
+ * Copyright 2007-11 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+extern int atom_debug;
+
+/* evil but including atombios.h is much worse */
+bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
+				struct drm_display_mode *mode);
+
+
+static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		if (radeon_encoder->devices & radeon_connector->devices)
+			return connector;
+	}
+	return NULL;
+}
+
+static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* set the active encoder to connector routing */
+	radeon_encoder_set_active_device(encoder);
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	/* hw bug */
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
+		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
+
+	/* get the native mode for LVDS */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+		radeon_panel_mode_fixup(encoder, adjusted_mode);
+
+	/* get the native mode for TV */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
+		if (tv_dac) {
+			if (tv_dac->tv_std == TV_STD_NTSC ||
+			    tv_dac->tv_std == TV_STD_NTSC_J ||
+			    tv_dac->tv_std == TV_STD_PAL_M)
+				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
+			else
+				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
+		}
+	}
+
+	if (ASIC_IS_DCE3(rdev) &&
+	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
+		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+		radeon_dp_set_link_config(connector, mode);
+	}
+
+	return true;
+}
+
+static void
+atombios_dac_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
+		break;
+	}
+
+	args.ucAction = action;
+
+	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_PS2;
+	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_CV;
+	else {
+		switch (dac_info->tv_std) {
+		case TV_STD_PAL:
+		case TV_STD_PAL_M:
+		case TV_STD_SCART_PAL:
+		case TV_STD_SECAM:
+		case TV_STD_PAL_CN:
+			args.ucDacStandard = ATOM_DAC1_PAL;
+			break;
+		case TV_STD_NTSC:
+		case TV_STD_NTSC_J:
+		case TV_STD_PAL_60:
+		default:
+			args.ucDacStandard = ATOM_DAC1_NTSC;
+			break;
+		}
+	}
+	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_tv_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	TV_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
+
+	args.sTVEncoder.ucAction = action;
+
+	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
+	else {
+		switch (dac_info->tv_std) {
+		case TV_STD_NTSC:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		case TV_STD_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
+			break;
+		case TV_STD_PAL_M:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
+			break;
+		case TV_STD_PAL_60:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
+			break;
+		case TV_STD_NTSC_J:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
+			break;
+		case TV_STD_SCART_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
+			break;
+		case TV_STD_SECAM:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
+			break;
+		case TV_STD_PAL_CN:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
+			break;
+		default:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		}
+	}
+
+	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dvo_encoder_control {
+	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
+	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
+	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
+};
+
+void
+atombios_dvo_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	union dvo_encoder_control args;
+	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+	uint8_t frev, crev;
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			/* R4xx, R5xx */
+			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
+
+			if (radeon_encoder->pixel_clock > 165000)
+				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+
+			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			break;
+		case 2:
+			/* RS600/690/740 */
+			args.dvo.sDVOEncoder.ucAction = action;
+			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			/* DFP1, CRT1, TV1 depending on the type of port */
+			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
+
+			if (radeon_encoder->pixel_clock > 165000)
+				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
+			break;
+		case 3:
+			/* R6xx */
+			args.dvo_v3.ucAction = action;
+			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.dvo_v3.ucDVOConfig = 0; /* XXX */
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+union lvds_encoder_control {
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
+};
+
+void
+atombios_digital_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	union lvds_encoder_control args;
+	int index = 0;
+	int hdmi_detected = 0;
+	uint8_t frev, crev;
+
+	if (!dig)
+		return;
+
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+		hdmi_detected = 1;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
+		break;
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+	case 2:
+		switch (crev) {
+		case 1:
+			args.v1.ucMisc = 0;
+			args.v1.ucAction = action;
+			if (hdmi_detected)
+				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			} else {
+				if (dig->linkb)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				/*if (pScrn->rgbBits == 8) */
+				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			}
+			break;
+		case 2:
+		case 3:
+			args.v2.ucMisc = 0;
+			args.v2.ucAction = action;
+			if (crev == 3) {
+				if (dig->coherent_mode)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+			}
+			if (hdmi_detected)
+				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v2.ucTruncate = 0;
+			args.v2.ucSpatial = 0;
+			args.v2.ucTemporal = 0;
+			args.v2.ucFRC = 0;
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
+					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+				}
+				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
+					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
+				}
+			} else {
+				if (dig->linkb)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+int
+atombios_get_encoder_mode(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	/* dp bridges are always DP */
+	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
+		return ATOM_ENCODER_MODE_DP;
+
+	/* DVO is always DVO */
+	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
+		return ATOM_ENCODER_MODE_DVO;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	/* if we don't have an active device yet, just use one of
+	 * the connectors tied to the encoder.
+	 */
+	if (!connector)
+		connector = radeon_get_connector_for_encoder_init(encoder);
+	radeon_connector = to_radeon_connector(connector);
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else if (radeon_connector->use_digital)
+			return ATOM_ENCODER_MODE_DVI;
+		else
+			return ATOM_ENCODER_MODE_CRT;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	default:
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		dig_connector = radeon_connector->con_priv;
+		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+			return ATOM_ENCODER_MODE_DP;
+		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case DRM_MODE_CONNECTOR_eDP:
+		return ATOM_ENCODER_MODE_DP;
+	case DRM_MODE_CONNECTOR_DVIA:
+	case DRM_MODE_CONNECTOR_VGA:
+		return ATOM_ENCODER_MODE_CRT;
+		break;
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_9PinDIN:
+		/* fix me */
+		return ATOM_ENCODER_MODE_TV;
+		/*return ATOM_ENCODER_MODE_CV;*/
+		break;
+	}
+}
+
+/*
+ * DIG Encoder/Transmitter Setup
+ *
+ * DCE 3.0/3.1
+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
+ * Supports up to 3 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1 can drive UNIPHY link A or link B
+ * DIG2 can drive UNIPHY link B or LVTMA
+ *
+ * DCE 3.2
+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
+ * Supports up to 5 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * DCE 4.0/5.0
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 6 DIG encoder blocks.
+ * - DIG to PHY mapping is hardcoded
+ * DIG1 drives UNIPHY0 link A, A+B
+ * DIG2 drives UNIPHY0 link B
+ * DIG3 drives UNIPHY1 link A, A+B
+ * DIG4 drives UNIPHY1 link B
+ * DIG5 drives UNIPHY2 link A, A+B
+ * DIG6 drives UNIPHY2 link B
+ *
+ * DCE 4.1
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * Routing
+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
+ * Examples:
+ * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
+ * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
+ * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
+ * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
+ */
+
+union dig_encoder_control {
+	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
+	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	union dig_encoder_control args;
+	int index = 0;
+	uint8_t frev, crev;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int hpd_id = RADEON_HPD_NONE;
+	int bpc = 8;
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		hpd_id = radeon_connector->hpd.hpd;
+		bpc = connector->display_info.bpc;
+	}
+
+	/* no dig encoder assigned */
+	if (dig->dig_encoder == -1)
+		return;
+
+	memset(&args, 0, sizeof(args));
+
+	if (ASIC_IS_DCE4(rdev))
+		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
+	else {
+		if (dig->dig_encoder)
+			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			args.v1.ucAction = action;
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v3.ucPanelMode = panel_mode;
+			else
+				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v1.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v1.ucLaneNum = 8;
+			else
+				args.v1.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
+				break;
+			}
+			if (dig->linkb)
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+			else
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
+			break;
+		case 2:
+		case 3:
+			args.v3.ucAction = action;
+			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v3.ucPanelMode = panel_mode;
+			else
+				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v3.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.ucLaneNum = 8;
+			else
+				args.v3.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+			args.v3.acConfig.ucDigSel = dig->dig_encoder;
+			switch (bpc) {
+			case 0:
+				args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			break;
+		case 4:
+			args.v4.ucAction = action;
+			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v4.ucPanelMode = panel_mode;
+			else
+				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v4.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v4.ucLaneNum = 8;
+			else
+				args.v4.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
+				else if (dp_clock == 540000)
+					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
+			}
+			args.v4.acConfig.ucDigSel = dig->dig_encoder;
+			switch (bpc) {
+			case 0:
+				args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			if (hpd_id == RADEON_HPD_NONE)
+				args.v4.ucHPD_ID = 0;
+			else
+				args.v4.ucHPD_ID = hpd_id + 1;
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dig_transmitter_control {
+	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector;
+	union dig_transmitter_control args;
+	int index = 0;
+	uint8_t frev, crev;
+	bool is_dp = false;
+	int pll_id = 0;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int connector_object_id = 0;
+	int igp_lane_info = 0;
+	int dig_encoder = dig->dig_encoder;
+
+	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+		connector = radeon_get_connector_for_encoder_init(encoder);
+		/* just needed to avoid bailing in the encoder check.  the encoder
+		 * isn't used for init
+		 */
+		dig_encoder = 0;
+	} else
+		connector = radeon_get_connector_for_encoder(encoder);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		connector_object_id =
+			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+		igp_lane_info = dig_connector->igp_lane_info;
+	}
+
+	if (encoder->crtc) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+		pll_id = radeon_crtc->pll_id;
+	}
+
+	/* no dig encoder assigned */
+	if (dig_encoder == -1)
+		return;
+
+	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
+		is_dp = true;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
+		break;
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			args.v1.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v1.asMode.ucLaneSel = lane_num;
+				args.v1.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v1.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
+
+			if (dig_encoder)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+			else
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+
+			if ((rdev->flags & RADEON_IS_IGP) &&
+			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
+				if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+					if (igp_lane_info & 0x1)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+					else if (igp_lane_info & 0x2)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
+					else if (igp_lane_info & 0x4)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
+					else if (igp_lane_info & 0x8)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
+				} else {
+					if (igp_lane_info & 0x3)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
+					else if (igp_lane_info & 0xc)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
+				}
+			}
+
+			if (dig->linkb)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
+			else
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
+
+			if (is_dp)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
+			}
+			break;
+		case 2:
+			args.v2.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v2.asMode.ucLaneSel = lane_num;
+				args.v2.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v2.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			args.v2.acConfig.ucEncoderSel = dig_encoder;
+			if (dig->linkb)
+				args.v2.acConfig.ucLinkSel = 1;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v2.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v2.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v2.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp) {
+				args.v2.acConfig.fCoherentMode = 1;
+				args.v2.acConfig.fDPConnector = 1;
+			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v2.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v2.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		case 3:
+			args.v3.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v3.asMode.ucLaneSel = lane_num;
+				args.v3.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v3.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			if (is_dp)
+				args.v3.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.ucLaneNum = 8;
+			else
+				args.v3.ucLaneNum = 4;
+
+			if (dig->linkb)
+				args.v3.acConfig.ucLinkSel = 1;
+			if (dig_encoder & 1)
+				args.v3.acConfig.ucEncoderSel = 1;
+
+			/* Select the PLL for the PHY
+			 * DP PHY should be clocked from external src if there is
+			 * one.
+			 */
+			/* On DCE4, if there is an external clock, it generates the DP ref clock */
+			if (is_dp && rdev->clock.dp_extclk)
+				args.v3.acConfig.ucRefClkSource = 2; /* external src */
+			else
+				args.v3.acConfig.ucRefClkSource = pll_id;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v3.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v3.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v3.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp)
+				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v3.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v3.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		case 4:
+			args.v4.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v4.asMode.ucLaneSel = lane_num;
+				args.v4.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v4.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			if (is_dp)
+				args.v4.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v4.ucLaneNum = 8;
+			else
+				args.v4.ucLaneNum = 4;
+
+			if (dig->linkb)
+				args.v4.acConfig.ucLinkSel = 1;
+			if (dig_encoder & 1)
+				args.v4.acConfig.ucEncoderSel = 1;
+
+			/* Select the PLL for the PHY
+			 * DP PHY should be clocked from external src if there is
+			 * one.
+			 */
+			/* On DCE5 DCPLL usually generates the DP ref clock */
+			if (is_dp) {
+				if (rdev->clock.dp_extclk)
+					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
+				else
+					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
+			} else
+				args.v4.acConfig.ucRefClkSource = pll_id;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v4.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v4.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v4.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp)
+				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v4.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v4.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+bool
+atombios_set_edp_panel_power(struct drm_connector *connector, int action)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_device *dev = radeon_connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	union dig_transmitter_control args;
+	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+	uint8_t frev, crev;
+
+	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+		goto done;
+
+	if (!ASIC_IS_DCE4(rdev))
+		goto done;
+
+	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
+	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
+		goto done;
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		goto done;
+
+	memset(&args, 0, sizeof(args));
+
+	args.v1.ucAction = action;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	/* wait for the panel to power up */
+	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
+		int i;
+
+		for (i = 0; i < 300; i++) {
+			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+				return true;
+			mdelay(1);
+		}
+		return false;
+	}
+done:
+	return true;
+}
+
+union external_encoder_control {
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
+};
+
+static void
+atombios_external_encoder_setup(struct drm_encoder *encoder,
+				struct drm_encoder *ext_encoder,
+				int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
+	union external_encoder_control args;
+	struct drm_connector *connector;
+	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
+	u8 frev, crev;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int connector_object_id = 0;
+	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	int bpc = 8;
+
+	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+		connector = radeon_get_connector_for_encoder_init(encoder);
+	else
+		connector = radeon_get_connector_for_encoder(encoder);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		connector_object_id =
+			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+		bpc = connector->display_info.bpc;
+	}
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		/* no params on frev 1 */
+		break;
+	case 2:
+		switch (crev) {
+		case 1:
+		case 2:
+			args.v1.sDigEncoder.ucAction = action;
+			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
+			} else if (radeon_encoder->pixel_clock > 165000)
+				args.v1.sDigEncoder.ucLaneNum = 8;
+			else
+				args.v1.sDigEncoder.ucLaneNum = 4;
+			break;
+		case 3:
+			args.v3.sExtEncoder.ucAction = action;
+			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
+			else
+				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+				else if (dp_clock == 540000)
+					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
+				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
+			} else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.sExtEncoder.ucLaneNum = 8;
+			else
+				args.v3.sExtEncoder.ucLaneNum = 4;
+			switch (ext_enum) {
+			case GRAPH_OBJECT_ENUM_ID1:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
+				break;
+			case GRAPH_OBJECT_ENUM_ID2:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
+				break;
+			case GRAPH_OBJECT_ENUM_ID3:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
+				break;
+			}
+			switch (bpc) {
+			case 0:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+			return;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+		return;
+	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void
+atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	ENABLE_YUV_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
+	uint32_t temp, reg;
+
+	memset(&args, 0, sizeof(args));
+
+	if (rdev->family >= CHIP_R600)
+		reg = R600_BIOS_3_SCRATCH;
+	else
+		reg = RADEON_BIOS_3_SCRATCH;
+
+	/* XXX: fix up scratch reg handling */
+	temp = RREG32(reg);
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
+			     (radeon_crtc->crtc_id << 18)));
+	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
+	else
+		WREG32(reg, 0);
+
+	if (enable)
+		args.ucEnable = ATOM_ENABLE;
+	args.ucCRTC = radeon_crtc->crtc_id;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	WREG32(reg, temp);
+}
+
+static void
+radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
+		break;
+	default:
+		return;
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		args.ucAction = ATOM_ENABLE;
+		/* workaround for DVOOutputControl on some RS690 systems */
+		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
+			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
+			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+			WREG32(RADEON_BIOS_3_SCRATCH, reg);
+		} else
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			args.ucAction = ATOM_LCD_BLON;
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		}
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		args.ucAction = ATOM_DISABLE;
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			args.ucAction = ATOM_LCD_BLOFF;
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		}
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	struct radeon_connector *radeon_connector = NULL;
+	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+
+	if (connector) {
+		radeon_connector = to_radeon_connector(connector);
+		radeon_dig_connector = radeon_connector->con_priv;
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		/* some early dce3.2 boards have a bug in their transmitter control table */
+		if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		else
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+				atombios_set_edp_panel_power(connector,
+							     ATOM_TRANSMITTER_ACTION_POWER_ON);
+				radeon_dig_connector->edp_on = true;
+			}
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+			radeon_dp_link_train(encoder, connector);
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
+		}
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+				atombios_set_edp_panel_power(connector,
+							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
+				radeon_dig_connector->edp_on = false;
+			}
+		}
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
+			     struct drm_encoder *ext_encoder,
+			     int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	default:
+		if (ASIC_IS_DCE41(rdev)) {
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
+		} else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		if (ASIC_IS_DCE41(rdev)) {
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
+		} else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
+		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
+		  radeon_encoder->active_device);
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		radeon_atom_encoder_dpms_dig(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		if (ASIC_IS_DCE5(rdev)) {
+			switch (mode) {
+			case DRM_MODE_DPMS_ON:
+				atombios_dvo_setup(encoder, ATOM_ENABLE);
+				break;
+			case DRM_MODE_DPMS_STANDBY:
+			case DRM_MODE_DPMS_SUSPEND:
+			case DRM_MODE_DPMS_OFF:
+				atombios_dvo_setup(encoder, ATOM_DISABLE);
+				break;
+			}
+		} else if (ASIC_IS_DCE3(rdev))
+			radeon_atom_encoder_dpms_dig(encoder, mode);
+		else
+			radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		if (ASIC_IS_DCE5(rdev)) {
+			switch (mode) {
+			case DRM_MODE_DPMS_ON:
+				atombios_dac_setup(encoder, ATOM_ENABLE);
+				break;
+			case DRM_MODE_DPMS_STANDBY:
+			case DRM_MODE_DPMS_SUSPEND:
+			case DRM_MODE_DPMS_OFF:
+				atombios_dac_setup(encoder, ATOM_DISABLE);
+				break;
+			}
+		} else
+			radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	default:
+		return;
+	}
+
+	if (ext_encoder)
+		radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
+
+	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+}
+
+union crtc_source_param {
+	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
+};
+
+static void
+atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	union crtc_source_param args;
+	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+		default:
+			if (ASIC_IS_AVIVO(rdev))
+				args.v1.ucCRTC = radeon_crtc->crtc_id;
+			else {
+				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
+					args.v1.ucCRTC = radeon_crtc->crtc_id;
+				} else {
+					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
+				}
+			}
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
+					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+			case ENCODER_OBJECT_ID_INTERNAL_DDI:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
+				break;
+			}
+			break;
+		case 2:
+			args.v2.ucCRTC = radeon_crtc->crtc_id;
+			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
+				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
+				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
+					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
+				else
+					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+			} else
+				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				dig = radeon_encoder->enc_priv;
+				switch (dig->dig_encoder) {
+				case 0:
+					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+					break;
+				case 1:
+					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+					break;
+				case 2:
+					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+					break;
+				case 3:
+					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+					break;
+				case 4:
+					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+					break;
+				case 5:
+					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+					break;
+				}
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
+				break;
+			}
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+		return;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	/* update scratch regs with new routing */
+	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static void
+atombios_apply_encoder_quirks(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+
+	/* Funky macbooks */
+	if ((dev->pdev->device == 0x71C5) &&
+	    (dev->pdev->subsystem_vendor == 0x106b) &&
+	    (dev->pdev->subsystem_device == 0x0080)) {
+		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
+
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
+
+			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
+		}
+	}
+
+	/* set scaler clears this on some chips */
+	if (ASIC_IS_AVIVO(rdev) &&
+	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
+		if (ASIC_IS_DCE4(rdev)) {
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
+				       EVERGREEN_INTERLEAVE_EN);
+			else
+				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+		} else {
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+				       AVIVO_D1MODE_INTERLEAVE_EN);
+			else
+				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+		}
+	}
+}
+
+static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *test_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	uint32_t dig_enc_in_use = 0;
+
+	/* DCE4/5 */
+	if (ASIC_IS_DCE4(rdev)) {
+		dig = radeon_encoder->enc_priv;
+		if (ASIC_IS_DCE41(rdev)) {
+			/* ontario follows DCE4 */
+			if (rdev->family == CHIP_PALM) {
+				if (dig->linkb)
+					return 1;
+				else
+					return 0;
+			} else
+				/* llano follows DCE3.2 */
+				return radeon_crtc->crtc_id;
+		} else {
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				if (dig->linkb)
+					return 1;
+				else
+					return 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				if (dig->linkb)
+					return 3;
+				else
+					return 2;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				if (dig->linkb)
+					return 5;
+				else
+					return 4;
+				break;
+			}
+		}
+	}
+
+	/* on DCE32 and encoder can driver any block so just crtc id */
+	if (ASIC_IS_DCE32(rdev)) {
+		return radeon_crtc->crtc_id;
+	}
+
+	/* on DCE3 - LVTMA can only be driven by DIGB */
+	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_test_encoder;
+
+		if (encoder == test_encoder)
+			continue;
+
+		if (!radeon_encoder_is_digital(test_encoder))
+			continue;
+
+		radeon_test_encoder = to_radeon_encoder(test_encoder);
+		dig = radeon_test_encoder->enc_priv;
+
+		if (dig->dig_encoder >= 0)
+			dig_enc_in_use |= (1 << dig->dig_encoder);
+	}
+
+	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
+		if (dig_enc_in_use & 0x2)
+			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
+		return 1;
+	}
+	if (!(dig_enc_in_use & 1))
+		return 0;
+	return 1;
+}
+
+/* This only needs to be called once at startup */
+void
+radeon_atom_encoder_init(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+			break;
+		default:
+			break;
+		}
+
+		if (ext_encoder && ASIC_IS_DCE41(rdev))
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
+	}
+}
+
+static void
+radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	radeon_encoder->pixel_clock = adjusted_mode->clock;
+
+	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
+		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
+			atombios_yuv_setup(encoder, true);
+		else
+			atombios_yuv_setup(encoder, false);
+	}
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		if (ASIC_IS_DCE4(rdev)) {
+			/* disable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			/* setup and enable the encoder */
+			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+
+			/* enable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		} else {
+			/* disable the encoder and transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+
+			/* setup and enable the encoder and transmitter */
+			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		}
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		atombios_dvo_setup(encoder, ATOM_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		atombios_dac_setup(encoder, ATOM_ENABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+				atombios_tv_setup(encoder, ATOM_ENABLE);
+			else
+				atombios_tv_setup(encoder, ATOM_DISABLE);
+		}
+		break;
+	}
+
+	if (ext_encoder) {
+		if (ASIC_IS_DCE41(rdev))
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
+		else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+	}
+
+	atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
+		r600_hdmi_enable(encoder);
+		r600_hdmi_setmode(encoder, adjusted_mode);
+	}
+}
+
+static bool
+atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
+				       ATOM_DEVICE_CV_SUPPORT |
+				       ATOM_DEVICE_CRT_SUPPORT)) {
+		DAC_LOAD_DETECTION_PS_ALLOCATION args;
+		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
+		uint8_t frev, crev;
+
+		memset(&args, 0, sizeof(args));
+
+		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+			return false;
+
+		args.sDacload.ucMisc = 0;
+
+		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
+		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
+			args.sDacload.ucDacType = ATOM_DAC_A;
+		else
+			args.sDacload.ucDacType = ATOM_DAC_B;
+
+		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		}
+
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+		return true;
+	} else
+		return false;
+}
+
+static enum drm_connector_status
+radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	uint32_t bios_0_scratch;
+
+	if (!atombios_dac_load_detect(encoder, connector)) {
+		DRM_DEBUG_KMS("detect returned false \n");
+		return connector_status_unknown;
+	}
+
+	if (rdev->family >= CHIP_R600)
+		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+	else
+		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+
+	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+			return connector_status_connected; /* CTV */
+		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+			return connector_status_connected; /* STV */
+	}
+	return connector_status_disconnected;
+}
+
+static enum drm_connector_status
+radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+	u32 bios_0_scratch;
+
+	if (!ASIC_IS_DCE4(rdev))
+		return connector_status_unknown;
+
+	if (!ext_encoder)
+		return connector_status_unknown;
+
+	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
+		return connector_status_unknown;
+
+	/* load detect on the dp bridge */
+	atombios_external_encoder_setup(encoder, ext_encoder,
+					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
+
+	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+
+	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+			return connector_status_connected; /* CTV */
+		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+			return connector_status_connected; /* STV */
+	}
+	return connector_status_disconnected;
+}
+
+void
+radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
+{
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	if (ext_encoder)
+		/* ddc_setup on the dp bridge */
+		atombios_external_encoder_setup(encoder, ext_encoder,
+						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
+
+}
+
+static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+	if ((radeon_encoder->active_device &
+	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+	     ENCODER_OBJECT_ID_NONE)) {
+		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+		if (dig)
+			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
+	}
+
+	radeon_atom_output_lock(encoder, true);
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+		/* select the clock/data port if it uses a router */
+		if (radeon_connector->router.cd_valid)
+			radeon_router_select_cd_port(radeon_connector);
+
+		/* turn eDP panel on for mode set */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+			atombios_set_edp_panel_power(connector,
+						     ATOM_TRANSMITTER_ACTION_POWER_ON);
+	}
+
+	/* this is needed for the pll/ss setup to work correctly in some cases */
+	atombios_set_encoder_crtc_source(encoder);
+}
+
+static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
+{
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+	radeon_atom_output_lock(encoder, false);
+}
+
+static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig;
+
+	/* check for pre-DCE3 cards with shared encoders;
+	 * can't really use the links individually, so don't disable
+	 * the encoder if it's in use by another connector
+	 */
+	if (!ASIC_IS_DCE3(rdev)) {
+		struct drm_encoder *other_encoder;
+		struct radeon_encoder *other_radeon_encoder;
+
+		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
+			other_radeon_encoder = to_radeon_encoder(other_encoder);
+			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
+			    drm_helper_encoder_in_use(other_encoder))
+				goto disable_done;
+		}
+	}
+
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		if (ASIC_IS_DCE4(rdev))
+			/* disable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+		else {
+			/* disable the encoder and transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+		}
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		atombios_dvo_setup(encoder, ATOM_DISABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		atombios_dac_setup(encoder, ATOM_DISABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+			atombios_tv_setup(encoder, ATOM_DISABLE);
+		break;
+	}
+
+disable_done:
+	if (radeon_encoder_is_digital(encoder)) {
+		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+			r600_hdmi_disable(encoder);
+		dig = radeon_encoder->enc_priv;
+		dig->dig_encoder = -1;
+	}
+	radeon_encoder->active_device = 0;
+}
+
+/* these are handled by the primary encoders */
+static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
+{
+
+}
+
+static void radeon_atom_ext_commit(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_mode_set(struct drm_encoder *encoder,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
+{
+
+}
+
+static void radeon_atom_ext_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
+{
+
+}
+
+static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
+	.dpms = radeon_atom_ext_dpms,
+	.mode_fixup = radeon_atom_ext_mode_fixup,
+	.prepare = radeon_atom_ext_prepare,
+	.mode_set = radeon_atom_ext_mode_set,
+	.commit = radeon_atom_ext_commit,
+	.disable = radeon_atom_ext_disable,
+	/* no detect for TMDS/LVDS yet */
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	.disable = radeon_atom_encoder_disable,
+	.detect = radeon_atom_dig_detect,
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	.detect = radeon_atom_dac_detect,
+};
+
+void radeon_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	kfree(radeon_encoder->enc_priv);
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
+
+static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+struct radeon_encoder_atom_dac *
+radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
+
+	if (!dac)
+		return NULL;
+
+	dac->tv_std = radeon_atombios_get_tv_info(rdev);
+	return dac;
+}
+
+struct radeon_encoder_atom_dig *
+radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
+{
+	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
+
+	if (!dig)
+		return NULL;
+
+	/* coherent mode by default */
+	dig->coherent_mode = true;
+	dig->dig_encoder = -1;
+
+	if (encoder_enum == 2)
+		dig->linkb = true;
+	else
+		dig->linkb = false;
+
+	return dig;
+}
+
+void
+radeon_add_atom_encoder(struct drm_device *dev,
+			uint32_t encoder_enum,
+			uint32_t supported_device,
+			u16 caps)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+
+	/* see if we already added it */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		radeon_encoder = to_radeon_encoder(encoder);
+		if (radeon_encoder->encoder_enum == encoder_enum) {
+			radeon_encoder->devices |= supported_device;
+			return;
+		}
+
+	}
+
+	/* add a new one */
+	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+	if (!radeon_encoder)
+		return;
+
+	encoder = &radeon_encoder->base;
+	switch (rdev->num_crtc) {
+	case 1:
+		encoder->possible_crtcs = 0x1;
+		break;
+	case 2:
+	default:
+		encoder->possible_crtcs = 0x3;
+		break;
+	case 4:
+		encoder->possible_crtcs = 0xf;
+		break;
+	case 6:
+		encoder->possible_crtcs = 0x3f;
+		break;
+	}
+
+	radeon_encoder->enc_priv = NULL;
+
+	radeon_encoder->encoder_enum = encoder_enum;
+	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+	radeon_encoder->devices = supported_device;
+	radeon_encoder->rmx_type = RMX_OFF;
+	radeon_encoder->underscan_type = UNDERSCAN_OFF;
+	radeon_encoder->is_ext_encoder = false;
+	radeon_encoder->caps = caps;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			radeon_encoder->rmx_type = RMX_FULL;
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		} else {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		}
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
+		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			radeon_encoder->rmx_type = RMX_FULL;
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		} else {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		}
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_SI170B:
+	case ENCODER_OBJECT_ID_CH7303:
+	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
+	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
+	case ENCODER_OBJECT_ID_TITFP513:
+	case ENCODER_OBJECT_ID_VT1623:
+	case ENCODER_OBJECT_ID_HDMI_SI1930:
+	case ENCODER_OBJECT_ID_TRAVIS:
+	case ENCODER_OBJECT_ID_NUTMEG:
+		/* these are handled by the primary encoders */
+		radeon_encoder->is_ext_encoder = true;
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+		else
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
+		break;
+	}
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,9 @@ set_render_target(struct radeon_device *
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 24) | (1 << 8));
+	cb_color_info = CB_FORMAT(format) |
+		CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+		CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -67,7 +69,7 @@ set_render_target(struct radeon_device *
 	radeon_ring_write(rdev, slice);
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, cb_color_info);
-	radeon_ring_write(rdev, (1 << 4));
+	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, (w - 1) | ((h - 1) << 16));
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
@@ -92,6 +94,15 @@ cp_set_surface_sync(struct radeon_device
 	else
 		cp_coher_size = ((size + 255) >> 8);
 
+	if (rdev->family >= CHIP_CAYMAN) {
+		/* CP_COHER_CNTL2 has to be set manually when submitting a surface_sync
+		 * to the RB directly. For IBs, the CP programs this as part of the
+		 * surface_sync packet.
+		 */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+		radeon_ring_write(rdev, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2);
+		radeon_ring_write(rdev, 0); /* CP_COHER_CNTL2 */
+	}
 	radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
 	radeon_ring_write(rdev, sync_type);
 	radeon_ring_write(rdev, cp_coher_size);
@@ -133,12 +144,16 @@ set_vtx_resource(struct radeon_device *r
 	u32 sq_vtx_constant_word2, sq_vtx_constant_word3;
 
 	/* high addr, stride */
-	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+	sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+		SQ_VTXC_STRIDE(16);
 #ifdef __BIG_ENDIAN
-	sq_vtx_constant_word2 |= (2 << 30);
+	sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
 #endif
 	/* xyzw swizzles */
-	sq_vtx_constant_word3 = (0 << 3) | (1 << 6) | (2 << 9) | (3 << 12);
+	sq_vtx_constant_word3 = SQ_VTCX_SEL_X(SQ_SEL_X) |
+		SQ_VTCX_SEL_Y(SQ_SEL_Y) |
+		SQ_VTCX_SEL_Z(SQ_SEL_Z) |
+		SQ_VTCX_SEL_W(SQ_SEL_W);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
 	radeon_ring_write(rdev, 0x580);
@@ -149,7 +164,7 @@ set_vtx_resource(struct radeon_device *r
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
-	radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30);
+	radeon_ring_write(rdev, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER));
 
 	if ((rdev->family == CHIP_CEDAR) ||
 	    (rdev->family == CHIP_PALM) ||
@@ -168,7 +183,7 @@ set_vtx_resource(struct radeon_device *r
 static void
 set_tex_resource(struct radeon_device *rdev,
 		 int format, int w, int h, int pitch,
-		 u64 gpu_addr)
+		 u64 gpu_addr, u32 size)
 {
 	u32 sq_tex_resource_word0, sq_tex_resource_word1;
 	u32 sq_tex_resource_word4, sq_tex_resource_word7;
@@ -176,14 +191,22 @@ set_tex_resource(struct radeon_device *r
 	if (h < 1)
 		h = 1;
 
-	sq_tex_resource_word0 = (1 << 0); /* 2D */
+	sq_tex_resource_word0 = TEX_DIM(SQ_TEX_DIM_2D);
 	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) |
 				  ((w - 1) << 18));
-	sq_tex_resource_word1 = ((h - 1) << 0) | (1 << 28);
+	sq_tex_resource_word1 = ((h - 1) << 0) |
+				TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	/* xyzw swizzles */
-	sq_tex_resource_word4 = (0 << 16) | (1 << 19) | (2 << 22) | (3 << 25);
+	sq_tex_resource_word4 = TEX_DST_SEL_X(SQ_SEL_X) |
+				TEX_DST_SEL_Y(SQ_SEL_Y) |
+				TEX_DST_SEL_Z(SQ_SEL_Z) |
+				TEX_DST_SEL_W(SQ_SEL_W);
 
-	sq_tex_resource_word7 = format | (SQ_TEX_VTX_VALID_TEXTURE << 30);
+	sq_tex_resource_word7 = format |
+		S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE);
+
+	cp_set_surface_sync(rdev,
+			    PACKET3_TC_ACTION_ENA, size, gpu_addr);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
 	radeon_ring_write(rdev, 0);
@@ -584,31 +607,6 @@ set_default_state(struct radeon_device *
 
 }
 
-static inline uint32_t i2f(uint32_t input)
-{
-	u32 result, i, exponent, fraction;
-
-	if ((input & 0x3fff) == 0)
-		result = 0; /* 0 is a special case */
-	else {
-		exponent = 140; /* exponent biased by 127; */
-		fraction = (input & 0x3fff) << 10; /* cheat and only
-						      handle numbers below 2^^15 */
-		for (i = 0; i < 14; i++) {
-			if (fraction & 0x800000)
-				break;
-			else {
-				fraction = fraction << 1; /* keep
-							     shifting left until top bit = 1 */
-				exponent = exponent - 1;
-			}
-		}
-		result = exponent << 23 | (fraction & 0x7fffff); /* mask
-								    off top bit; assumed 1 */
-	}
-	return result;
-}
-
 int evergreen_blit_init(struct radeon_device *rdev)
 {
 	u32 obj_size;
@@ -617,6 +615,26 @@ int evergreen_blit_init(struct radeon_de
 	u32 packet2s[16];
 	int num_packet2s = 0;
 
+	rdev->r600_blit.primitives.set_render_target = set_render_target;
+	rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+	rdev->r600_blit.primitives.set_shaders = set_shaders;
+	rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+	rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+	rdev->r600_blit.primitives.set_scissors = set_scissors;
+	rdev->r600_blit.primitives.draw_auto = draw_auto;
+	rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+	rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
+	rdev->r600_blit.ring_size_common += 5; /* done copy */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
+
+	rdev->r600_blit.ring_size_per_loop = 74;
+	if (rdev->family >= CHIP_CAYMAN)
+		rdev->r600_blit.ring_size_per_loop += 9; /* additional DWs for surface sync */
+
+	rdev->r600_blit.max_dim = 16384;
+
 	/* pin copy shader into vram if already initialized */
 	if (rdev->r600_blit.shader_obj)
 		goto done;
@@ -712,277 +730,3 @@ done:
 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 	return 0;
 }
-
-void evergreen_blit_fini(struct radeon_device *rdev)
-{
-	int r;
-
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-	if (rdev->r600_blit.shader_obj == NULL)
-		return;
-	/* If we can't reserve the bo, unref should be enough to destroy
-	 * it when it becomes idle.
-	 */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (!r) {
-		radeon_bo_unpin(rdev->r600_blit.shader_obj);
-		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-	}
-	radeon_bo_unref(&rdev->r600_blit.shader_obj);
-}
-
-static int evergreen_vb_ib_get(struct radeon_device *rdev)
-{
-	int r;
-	r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib);
-	if (r) {
-		DRM_ERROR("failed to get IB for vertex buffer\n");
-		return r;
-	}
-
-	rdev->r600_blit.vb_total = 64*1024;
-	rdev->r600_blit.vb_used = 0;
-	return 0;
-}
-
-static void evergreen_vb_ib_put(struct radeon_device *rdev)
-{
-	radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
-	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-}
-
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
-{
-	int r;
-	int ring_size, line_size;
-	int max_size;
-	/* loops of emits + fence emit possible */
-	int dwords_per_loop = 74, num_loops;
-
-	r = evergreen_vb_ib_get(rdev);
-	if (r)
-		return r;
-
-	/* 8 bpp vs 32 bpp for xfer unit */
-	if (size_bytes & 3)
-		line_size = 8192;
-	else
-		line_size = 8192 * 4;
-
-	max_size = 8192 * line_size;
-
-	/* major loops cover the max size transfer */
-	num_loops = ((size_bytes + max_size) / max_size);
-	/* minor loops cover the extra non aligned bits */
-	num_loops += ((size_bytes % line_size) ? 1 : 0);
-	/* calculate number of loops correctly */
-	ring_size = num_loops * dwords_per_loop;
-	/* set default  + shaders */
-	ring_size += 55; /* shaders + def state */
-	ring_size += 10; /* fence emit for VB IB */
-	ring_size += 5; /* done copy */
-	ring_size += 10; /* fence emit for done copy */
-	r = radeon_ring_lock(rdev, ring_size);
-	if (r)
-		return r;
-
-	set_default_state(rdev); /* 36 */
-	set_shaders(rdev); /* 16 */
-	return 0;
-}
-
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
-{
-	int r;
-
-	if (rdev->r600_blit.vb_ib)
-		evergreen_vb_ib_put(rdev);
-
-	if (fence)
-		r = radeon_fence_emit(rdev, fence);
-
-	radeon_ring_unlock_commit(rdev);
-}
-
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
-			     u64 src_gpu_addr, u64 dst_gpu_addr,
-			     int size_bytes)
-{
-	int max_bytes;
-	u64 vb_gpu_addr;
-	u32 *vb;
-
-	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
-		  size_bytes, rdev->r600_blit.vb_used);
-	vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
-	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
-		max_bytes = 8192;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = src_gpu_addr & 255;
-			int dst_x = dst_gpu_addr & 255;
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x);
-			vb[1] = 0;
-			vb[2] = i2f(src_x);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f(dst_x + cur_size);
-			vb[9] = i2f(h);
-			vb[10] = i2f(src_x + cur_size);
-			vb[11] = i2f(h);
-
-			/* src 10 */
-			set_tex_resource(rdev, FMT_8,
-					 src_x + cur_size, h, src_x + cur_size,
-					 src_gpu_addr);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-
-			/* dst 17 */
-			set_render_target(rdev, COLOR_8,
-					  dst_x + cur_size, h,
-					  dst_gpu_addr);
-
-			/* scissors 12 */
-			set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
-
-			/* 15 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	} else {
-		max_bytes = 8192 * 4;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = (src_gpu_addr & 255);
-			int dst_x = (dst_gpu_addr & 255);
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x / 4);
-			vb[1] = 0;
-			vb[2] = i2f(src_x / 4);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x / 4);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x / 4);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f((dst_x + cur_size) / 4);
-			vb[9] = i2f(h);
-			vb[10] = i2f((src_x + cur_size) / 4);
-			vb[11] = i2f(h);
-
-			/* src 10 */
-			set_tex_resource(rdev, FMT_8_8_8_8,
-					 (src_x + cur_size) / 4,
-					 h, (src_x + cur_size) / 4,
-					 src_gpu_addr);
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst 17 */
-			set_render_target(rdev, COLOR_8_8_8_8,
-					  (dst_x + cur_size) / 4, h,
-					  dst_gpu_addr);
-
-			/* scissors 12  */
-			set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
-			/* Vertex buffer setup 15 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			/* 74 ring dwords per loop */
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	}
-}
-
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 static void evergreen_gpu_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
@@ -82,6 +82,7 @@ u32 evergreen_page_flip(struct radeon_de
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
@@ -99,7 +100,11 @@ u32 evergreen_page_flip(struct radeon_de
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -157,6 +162,57 @@ int sumo_get_temp(struct radeon_device *
 	return actual_temp * 1000;
 }
 
+void sumo_pm_init_profile(struct radeon_device *rdev)
+{
+	int idx;
+
+	/* default */
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
+
+	/* low,mid sh/mh */
+	if (rdev->flags & RADEON_IS_MOBILITY)
+		idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+	else
+		idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
+
+	/* high sh/mh */
+	idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx =
+		rdev->pm.power_state[idx].num_clock_modes - 1;
+
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx =
+		rdev->pm.power_state[idx].num_clock_modes - 1;
+}
+
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
 	int req_ps_idx = rdev->pm.requested_power_state_index;
@@ -353,6 +409,7 @@ void evergreen_hpd_init(struct radeon_de
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		evergreen_irq_set(rdev);
@@ -893,7 +950,7 @@ int evergreen_pcie_gart_enable(struct ra
 	u32 tmp;
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -935,6 +992,9 @@ int evergreen_pcie_gart_enable(struct ra
 	WREG32(VM_CONTEXT1_CNTL, 0);
 
 	evergreen_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -942,7 +1002,6 @@ int evergreen_pcie_gart_enable(struct ra
 void evergreen_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
@@ -962,14 +1021,7 @@ void evergreen_pcie_gart_disable(struct
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void evergreen_pcie_gart_fini(struct radeon_device *rdev)
@@ -1223,7 +1275,7 @@ void evergreen_mc_program(struct radeon_
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
 			rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	if (rdev->flags & RADEON_IS_IGP) {
 		tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF;
 		tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24;
@@ -2586,7 +2638,7 @@ int evergreen_irq_set(struct radeon_devi
 	return 0;
 }
 
-static inline void evergreen_irq_ack(struct radeon_device *rdev)
+static void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
@@ -2697,7 +2749,7 @@ void evergreen_irq_suspend(struct radeon
 	r600_rlc_stop(rdev);
 }
 
-static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
+static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 {
 	u32 wptr, tmp;
 
@@ -3003,8 +3055,7 @@ static int evergreen_startup(struct rade
 	int r;
 
 	/* enable pcie gen2 link */
-	if (!ASIC_IS_DCE5(rdev))
-		evergreen_pcie_gen2_enable(rdev);
+	evergreen_pcie_gen2_enable(rdev);
 
 	if (ASIC_IS_DCE5(rdev)) {
 		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
@@ -3029,6 +3080,10 @@ static int evergreen_startup(struct rade
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	evergreen_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		evergreen_agp_enable(rdev);
@@ -3041,7 +3096,7 @@ static int evergreen_startup(struct rade
 
 	r = evergreen_blit_init(rdev);
 	if (r) {
-		evergreen_blit_fini(rdev);
+		r600_blit_fini(rdev);
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
@@ -3107,45 +3162,14 @@ int evergreen_resume(struct radeon_devic
 
 int evergreen_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
 	rdev->cp.ready = false;
 	evergreen_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	evergreen_pcie_gart_disable(rdev);
+	r600_blit_suspend(rdev);
 
-	/* unpin shaders bo */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (likely(r == 0)) {
-		radeon_bo_unpin(rdev->r600_blit.shader_obj);
-		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-	}
-
-	return 0;
-}
-
-int evergreen_copy_blit(struct radeon_device *rdev,
-			uint64_t src_offset,
-			uint64_t dst_offset,
-			unsigned num_gpu_pages,
-			struct radeon_fence *fence)
-{
-	int r;
-
-	mutex_lock(&rdev->r600_blit.mutex);
-	rdev->r600_blit.vb_ib = NULL;
-	r = evergreen_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
-	if (r) {
-		if (rdev->r600_blit.vb_ib)
-			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-		mutex_unlock(&rdev->r600_blit.mutex);
-		return r;
-	}
-	evergreen_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
-	evergreen_blit_done_copy(rdev, fence);
-	mutex_unlock(&rdev->r600_blit.mutex);
 	return 0;
 }
 
@@ -3252,18 +3276,31 @@ int evergreen_init(struct radeon_device
 			rdev->accel_working = false;
 		}
 	}
+
+	/* Don't start up if the MC ucode is missing on BTC parts.
+	 * The default clocks and voltages before the MC ucode
+	 * is loaded are not suffient for advanced operations.
+	 */
+	if (ASIC_IS_DCE5(rdev)) {
+		if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
+			DRM_ERROR("radeon: MC ucode required for NI+.\n");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
 void evergreen_fini(struct radeon_device *rdev)
 {
-	evergreen_blit_fini(rdev);
+	r600_blit_fini(rdev);
 	r700_cp_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	evergreen_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_agp_fini(rdev);
@@ -3273,7 +3310,7 @@ void evergreen_fini(struct radeon_device
 	rdev->bios = NULL;
 }
 
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
 {
 	u32 link_width_cntl, speed_cntl;
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@ struct evergreen_cs_track {
 	u32			group_size;
 	u32			nbanks;
 	u32			npipes;
+	u32			row_size;
 	/* value we track */
 	u32			nsamples;
 	u32			cb_color_base_last[12];
@@ -77,6 +78,44 @@ struct evergreen_cs_track {
 	struct radeon_bo	*db_s_write_bo;
 };
 
+static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
+{
+	if (tiling_flags & RADEON_TILING_MACRO)
+		return ARRAY_2D_TILED_THIN1;
+	else if (tiling_flags & RADEON_TILING_MICRO)
+		return ARRAY_1D_TILED_THIN1;
+	else
+		return ARRAY_LINEAR_GENERAL;
+}
+
+static u32 evergreen_cs_get_num_banks(u32 nbanks)
+{
+	switch (nbanks) {
+	case 2:
+		return ADDR_SURF_2_BANK;
+	case 4:
+		return ADDR_SURF_4_BANK;
+	case 8:
+	default:
+		return ADDR_SURF_8_BANK;
+	case 16:
+		return ADDR_SURF_16_BANK;
+	}
+}
+
+static u32 evergreen_cs_get_tile_split(u32 row_size)
+{
+	switch (row_size) {
+	case 1:
+	default:
+		return ADDR_SURF_TILE_SPLIT_1KB;
+	case 2:
+		return ADDR_SURF_TILE_SPLIT_2KB;
+	case 4:
+		return ADDR_SURF_TILE_SPLIT_4KB;
+	}
+}
+
 static void evergreen_cs_track_init(struct evergreen_cs_track *track)
 {
 	int i;
@@ -122,12 +161,6 @@ static void evergreen_cs_track_init(stru
 	track->db_s_write_bo = NULL;
 }
 
-static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
-{
-	/* XXX fill in */
-	return 0;
-}
-
 static int evergreen_cs_track_check(struct radeon_cs_parser *p)
 {
 	struct evergreen_cs_track *track = p->track;
@@ -236,28 +269,6 @@ static int evergreen_cs_packet_next_relo
 }
 
 /**
- * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
- * @parser:		parser structure holding parsing context.
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
-{
-	struct radeon_cs_packet p3reloc;
-	int r;
-
-	r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-	if (r) {
-		return 0;
-	}
-	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-		return 0;
-	}
-	return 1;
-}
-
-/**
  * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -414,7 +425,7 @@ static int evergreen_cs_parse_packet0(st
  * if register is safe. If register is not flag as safe this function
  * will test it against a list of register needind special handling.
  */
-static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 {
 	struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
@@ -508,21 +519,22 @@ static inline int evergreen_cs_check_reg
 		}
 		break;
 	case DB_Z_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		track->db_z_info = radeon_get_ib_value(p, idx);
-		ib[idx] &= ~Z_ARRAY_MODE(0xf);
-		track->db_z_info &= ~Z_ARRAY_MODE(0xf);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else {
-			ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			r = evergreen_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				dev_warn(p->dev, "bad SET_CONTEXT_REG "
+						"0x%04X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] &= ~Z_ARRAY_MODE(0xf);
+			track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+			ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+				ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+				ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+			}
 		}
 		break;
 	case DB_STENCIL_INFO:
@@ -635,40 +647,34 @@ static inline int evergreen_cs_check_reg
 	case CB_COLOR5_INFO:
 	case CB_COLOR6_INFO:
 	case CB_COLOR7_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		tmp = (reg - CB_COLOR0_INFO) / 0x3c;
 		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			r = evergreen_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				dev_warn(p->dev, "bad SET_CONTEXT_REG "
+						"0x%04X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
 		}
 		break;
 	case CB_COLOR8_INFO:
 	case CB_COLOR9_INFO:
 	case CB_COLOR10_INFO:
 	case CB_COLOR11_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
 		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			r = evergreen_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				dev_warn(p->dev, "bad SET_CONTEXT_REG "
+						"0x%04X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
 		}
 		break;
 	case CB_COLOR0_PITCH:
@@ -723,6 +729,16 @@ static inline int evergreen_cs_check_reg
 	case CB_COLOR9_ATTRIB:
 	case CB_COLOR10_ATTRIB:
 	case CB_COLOR11_ATTRIB:
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+			ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+			ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+		}
 		break;
 	case CB_COLOR0_DIM:
 	case CB_COLOR1_DIM:
@@ -990,7 +1006,7 @@ static inline int evergreen_cs_check_reg
  * This function will check that the resource has valid field and that
  * the texture and mipmap bo object are big enough to cover this resource.
  */
-static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+static int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 						   struct radeon_bo *texture,
 						   struct radeon_bo *mipmap)
 {
@@ -1339,10 +1355,16 @@ static int evergreen_packet3_check(struc
 					return -EINVAL;
 				}
 				ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+				if (!p->keep_tiling_flags) {
+					ib[idx+1+(i*8)+1] |=
+						TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+						ib[idx+1+(i*8)+6] |=
+							TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+						ib[idx+1+(i*8)+7] |=
+							TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+					}
+				}
 				texture = reloc->robj;
 				/* tex mip base */
 				r = evergreen_cs_packet_next_reloc(p, &reloc);
@@ -1442,6 +1464,7 @@ int evergreen_cs_parse(struct radeon_cs_
 {
 	struct radeon_cs_packet pkt;
 	struct evergreen_cs_track *track;
+	u32 tmp;
 	int r;
 
 	if (p->track == NULL) {
@@ -1450,9 +1473,63 @@ int evergreen_cs_parse(struct radeon_cs_
 		if (track == NULL)
 			return -ENOMEM;
 		evergreen_cs_track_init(track);
-		track->npipes = p->rdev->config.evergreen.tiling_npipes;
-		track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
-		track->group_size = p->rdev->config.evergreen.tiling_group_size;
+		if (p->rdev->family >= CHIP_CAYMAN)
+			tmp = p->rdev->config.cayman.tile_config;
+		else
+			tmp = p->rdev->config.evergreen.tile_config;
+
+		switch (tmp & 0xf) {
+		case 0:
+			track->npipes = 1;
+			break;
+		case 1:
+		default:
+			track->npipes = 2;
+			break;
+		case 2:
+			track->npipes = 4;
+			break;
+		case 3:
+			track->npipes = 8;
+			break;
+		}
+
+		switch ((tmp & 0xf0) >> 4) {
+		case 0:
+			track->nbanks = 4;
+			break;
+		case 1:
+		default:
+			track->nbanks = 8;
+			break;
+		case 2:
+			track->nbanks = 16;
+			break;
+		}
+
+		switch ((tmp & 0xf00) >> 8) {
+		case 0:
+			track->group_size = 256;
+			break;
+		case 1:
+		default:
+			track->group_size = 512;
+			break;
+		}
+
+		switch ((tmp & 0xf000) >> 12) {
+		case 0:
+			track->row_size = 1;
+			break;
+		case 1:
+		default:
+			track->row_size = 2;
+			break;
+		case 2:
+			track->row_size = 4;
+			break;
+		}
+
 		p->track = track;
 	}
 	do {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreend.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreend.h	2012-01-04 18:55:44.000000000 -0500
@@ -899,6 +899,10 @@
 #define DB_HTILE_DATA_BASE				0x28014
 #define DB_Z_INFO					0x28040
 #       define Z_ARRAY_MODE(x)                          ((x) << 4)
+#       define DB_TILE_SPLIT(x)                         (((x) & 0x7) << 8)
+#       define DB_NUM_BANKS(x)                          (((x) & 0x3) << 12)
+#       define DB_BANK_WIDTH(x)                         (((x) & 0x3) << 16)
+#       define DB_BANK_HEIGHT(x)                        (((x) & 0x3) << 20)
 #define DB_STENCIL_INFO					0x28044
 #define DB_Z_READ_BASE					0x28048
 #define DB_STENCIL_READ_BASE				0x2804c
@@ -941,12 +945,39 @@
 #define	CB_COLOR0_SLICE					0x28c68
 #define	CB_COLOR0_VIEW					0x28c6c
 #define	CB_COLOR0_INFO					0x28c70
+#	define CB_FORMAT(x)				((x) << 2)
 #       define CB_ARRAY_MODE(x)                         ((x) << 8)
 #       define ARRAY_LINEAR_GENERAL                     0
 #       define ARRAY_LINEAR_ALIGNED                     1
 #       define ARRAY_1D_TILED_THIN1                     2
 #       define ARRAY_2D_TILED_THIN1                     4
+#	define CB_SOURCE_FORMAT(x)			((x) << 24)
+#	define CB_SF_EXPORT_FULL			0
+#	define CB_SF_EXPORT_NORM			1
 #define	CB_COLOR0_ATTRIB				0x28c74
+#       define CB_TILE_SPLIT(x)                         (((x) & 0x7) << 5)
+#       define ADDR_SURF_TILE_SPLIT_64B                 0
+#       define ADDR_SURF_TILE_SPLIT_128B                1
+#       define ADDR_SURF_TILE_SPLIT_256B                2
+#       define ADDR_SURF_TILE_SPLIT_512B                3
+#       define ADDR_SURF_TILE_SPLIT_1KB                 4
+#       define ADDR_SURF_TILE_SPLIT_2KB                 5
+#       define ADDR_SURF_TILE_SPLIT_4KB                 6
+#       define CB_NUM_BANKS(x)                          (((x) & 0x3) << 10)
+#       define ADDR_SURF_2_BANK                         0
+#       define ADDR_SURF_4_BANK                         1
+#       define ADDR_SURF_8_BANK                         2
+#       define ADDR_SURF_16_BANK                        3
+#       define CB_BANK_WIDTH(x)                         (((x) & 0x3) << 13)
+#       define ADDR_SURF_BANK_WIDTH_1                   0
+#       define ADDR_SURF_BANK_WIDTH_2                   1
+#       define ADDR_SURF_BANK_WIDTH_4                   2
+#       define ADDR_SURF_BANK_WIDTH_8                   3
+#       define CB_BANK_HEIGHT(x)                        (((x) & 0x3) << 16)
+#       define ADDR_SURF_BANK_HEIGHT_1                  0
+#       define ADDR_SURF_BANK_HEIGHT_2                  1
+#       define ADDR_SURF_BANK_HEIGHT_4                  2
+#       define ADDR_SURF_BANK_HEIGHT_8                  3
 #define	CB_COLOR0_DIM					0x28c78
 /* only CB0-7 blocks have these regs */
 #define	CB_COLOR0_CMASK					0x28c7c
@@ -1107,14 +1138,56 @@
 #define	CB_COLOR7_CLEAR_WORD3				0x28e3c
 
 #define SQ_TEX_RESOURCE_WORD0_0                         0x30000
+#	define TEX_DIM(x)				((x) << 0)
+#	define SQ_TEX_DIM_1D				0
+#	define SQ_TEX_DIM_2D				1
+#	define SQ_TEX_DIM_3D				2
+#	define SQ_TEX_DIM_CUBEMAP			3
+#	define SQ_TEX_DIM_1D_ARRAY			4
+#	define SQ_TEX_DIM_2D_ARRAY			5
+#	define SQ_TEX_DIM_2D_MSAA			6
+#	define SQ_TEX_DIM_2D_ARRAY_MSAA			7
 #define SQ_TEX_RESOURCE_WORD1_0                         0x30004
 #       define TEX_ARRAY_MODE(x)                        ((x) << 28)
 #define SQ_TEX_RESOURCE_WORD2_0                         0x30008
 #define SQ_TEX_RESOURCE_WORD3_0                         0x3000C
 #define SQ_TEX_RESOURCE_WORD4_0                         0x30010
+#	define TEX_DST_SEL_X(x)				((x) << 16)
+#	define TEX_DST_SEL_Y(x)				((x) << 19)
+#	define TEX_DST_SEL_Z(x)				((x) << 22)
+#	define TEX_DST_SEL_W(x)				((x) << 25)
+#	define SQ_SEL_X					0
+#	define SQ_SEL_Y					1
+#	define SQ_SEL_Z					2
+#	define SQ_SEL_W					3
+#	define SQ_SEL_0					4
+#	define SQ_SEL_1					5
 #define SQ_TEX_RESOURCE_WORD5_0                         0x30014
 #define SQ_TEX_RESOURCE_WORD6_0                         0x30018
+#       define TEX_TILE_SPLIT(x)                        (((x) & 0x7) << 29)
 #define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
+#       define TEX_BANK_WIDTH(x)                        (((x) & 0x3) << 8)
+#       define TEX_BANK_HEIGHT(x)                       (((x) & 0x3) << 10)
+#       define TEX_NUM_BANKS(x)                         (((x) & 0x3) << 16)
+
+#define SQ_VTX_CONSTANT_WORD0_0				0x30000
+#define SQ_VTX_CONSTANT_WORD1_0				0x30004
+#define SQ_VTX_CONSTANT_WORD2_0				0x30008
+#	define SQ_VTXC_BASE_ADDR_HI(x)			((x) << 0)
+#	define SQ_VTXC_STRIDE(x)			((x) << 8)
+#	define SQ_VTXC_ENDIAN_SWAP(x)			((x) << 30)
+#	define SQ_ENDIAN_NONE				0
+#	define SQ_ENDIAN_8IN16				1
+#	define SQ_ENDIAN_8IN32				2
+#define SQ_VTX_CONSTANT_WORD3_0				0x3000C
+#	define SQ_VTCX_SEL_X(x)				((x) << 3)
+#	define SQ_VTCX_SEL_Y(x)				((x) << 6)
+#	define SQ_VTCX_SEL_Z(x)				((x) << 9)
+#	define SQ_VTCX_SEL_W(x)				((x) << 12)
+#define SQ_VTX_CONSTANT_WORD4_0				0x30010
+#define SQ_VTX_CONSTANT_WORD5_0                         0x30014
+#define SQ_VTX_CONSTANT_WORD6_0                         0x30018
+#define SQ_VTX_CONSTANT_WORD7_0                         0x3001c
 
 /* cayman 3D regs */
 #define CAYMAN_VGT_OFFCHIP_LDS_BASE			0x89B0
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,17 @@
 #       define EVERGREEN_GRPH_DEPTH_8BPP                0
 #       define EVERGREEN_GRPH_DEPTH_16BPP               1
 #       define EVERGREEN_GRPH_DEPTH_32BPP               2
+#       define EVERGREEN_GRPH_NUM_BANKS(x)              (((x) & 0x3) << 2)
+#       define EVERGREEN_ADDR_SURF_2_BANK               0
+#       define EVERGREEN_ADDR_SURF_4_BANK               1
+#       define EVERGREEN_ADDR_SURF_8_BANK               2
+#       define EVERGREEN_ADDR_SURF_16_BANK              3
+#       define EVERGREEN_GRPH_Z(x)                      (((x) & 0x3) << 4)
+#       define EVERGREEN_GRPH_BANK_WIDTH(x)             (((x) & 0x3) << 6)
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_1         0
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_2         1
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_4         2
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_8         3
 #       define EVERGREEN_GRPH_FORMAT(x)                 (((x) & 0x7) << 8)
 /* 8 BPP */
 #       define EVERGREEN_GRPH_FORMAT_INDEXED            0
@@ -61,6 +72,24 @@
 #       define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102     5
 #       define EVERGREEN_GRPH_FORMAT_RGB111110          6
 #       define EVERGREEN_GRPH_FORMAT_BGR101111          7
+#       define EVERGREEN_GRPH_BANK_HEIGHT(x)            (((x) & 0x3) << 11)
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1        0
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2        1
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4        2
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8        3
+#       define EVERGREEN_GRPH_TILE_SPLIT(x)             (((x) & 0x7) << 13)
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B       0
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B      1
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B      2
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B      3
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB       4
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB       5
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB       6
+#       define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x)      (((x) & 0x3) << 18)
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1  0
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2  1
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4  2
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8  3
 #       define EVERGREEN_GRPH_ARRAY_MODE(x)             (((x) & 0x7) << 20)
 #       define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL      0
 #       define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED      1
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/Makefile linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/Makefile
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@ radeon-y += radeon_device.o radeon_asic.
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
 	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
-	radeon_trace_points.o ni.o cayman_blit_shaders.o
+	radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/ni.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/ni.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/ni.c	2013-05-02 01:33:46.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/ni.c	2013-05-01 23:41:48.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_asic.h"
@@ -40,6 +41,7 @@ extern void evergreen_mc_program(struct
 extern void evergreen_irq_suspend(struct radeon_device *rdev);
 extern int evergreen_mc_init(struct radeon_device *rdev);
 extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
+extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
@@ -219,8 +221,11 @@ int ni_mc_load_microcode(struct radeon_d
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
 
 		/* wait for training to complete */
-		while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
-			udelay(10);
+		for (i = 0; i < rdev->usec_timeout; i++) {
+			if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
+				break;
+			udelay(1);
+		}
 
 		if (running)
 			WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
@@ -890,7 +895,7 @@ int cayman_pcie_gart_enable(struct radeo
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -926,14 +931,15 @@ int cayman_pcie_gart_enable(struct radeo
 	WREG32(VM_CONTEXT1_CNTL, 0);
 
 	cayman_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
 
 void cayman_pcie_gart_disable(struct radeon_device *rdev)
 {
-	int r;
-
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
 	WREG32(VM_CONTEXT1_CNTL, 0);
@@ -949,14 +955,7 @@ void cayman_pcie_gart_disable(struct rad
 	WREG32(VM_L2_CNTL2, 0);
 	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
 	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void cayman_pcie_gart_fini(struct radeon_device *rdev)
@@ -1300,6 +1299,9 @@ static int cayman_startup(struct radeon_
 {
 	int r;
 
+	/* enable pcie gen2 link */
+	evergreen_pcie_gen2_enable(rdev);
+
 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
 		r = ni_init_microcode(rdev);
 		if (r) {
@@ -1313,6 +1315,10 @@ static int cayman_startup(struct radeon_
 		return r;
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	evergreen_mc_program(rdev);
 	r = cayman_pcie_gart_enable(rdev);
 	if (r)
@@ -1321,7 +1327,7 @@ static int cayman_startup(struct radeon_
 
 	r = evergreen_blit_init(rdev);
 	if (r) {
-		evergreen_blit_fini(rdev);
+		r600_blit_fini(rdev);
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
@@ -1382,21 +1388,13 @@ int cayman_resume(struct radeon_device *
 
 int cayman_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	/* FIXME: we should wait for ring to be empty */
 	cayman_cp_enable(rdev, false);
 	rdev->cp.ready = false;
 	evergreen_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	cayman_pcie_gart_disable(rdev);
-
-	/* unpin shaders bo */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (likely(r == 0)) {
-		radeon_bo_unpin(rdev->r600_blit.shader_obj);
-		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-	}
+	r600_blit_suspend(rdev);
 
 	return 0;
 }
@@ -1509,13 +1507,14 @@ int cayman_init(struct radeon_device *rd
 
 void cayman_fini(struct radeon_device *rdev)
 {
-	evergreen_blit_fini(rdev);
+	r600_blit_fini(rdev);
 	cayman_cp_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	cayman_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_bo_fini(rdev);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r100.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r100.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-02 01:33:32.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-01 23:41:33.000000000 -0400
@@ -41,6 +41,7 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "r100_reg_safe.h"
 #include "rn50_reg_safe.h"
@@ -62,6 +63,108 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+			    struct radeon_cs_packet *pkt,
+			    unsigned idx,
+			    unsigned reg)
+{
+	int r;
+	u32 tile_flags = 0;
+	u32 tmp;
+	struct radeon_cs_reloc *reloc;
+	u32 value;
+
+	r = r100_cs_packet_next_reloc(p, &reloc);
+	if (r) {
+		DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+			  idx, reg);
+		r100_cs_dump_packet(p, pkt);
+		return r;
+	}
+	value = radeon_get_ib_value(p, idx);
+	tmp = value & 0x003fffff;
+	tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+	if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+		tile_flags |= RADEON_DST_TILE_MACRO;
+	if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+		if (reg == RADEON_SRC_PITCH_OFFSET) {
+			DRM_ERROR("Cannot src blit from microtiled surface\n");
+			r100_cs_dump_packet(p, pkt);
+			return -EINVAL;
+		}
+		tile_flags |= RADEON_DST_TILE_MICRO;
+	}
+
+	tmp |= tile_flags;
+	p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
+	return 0;
+}
+
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+			     struct radeon_cs_packet *pkt,
+			     int idx)
+{
+	unsigned c, i;
+	struct radeon_cs_reloc *reloc;
+	struct r100_cs_track *track;
+	int r = 0;
+	volatile uint32_t *ib;
+	u32 idx_value;
+
+	ib = p->ib->ptr;
+	track = (struct r100_cs_track *)p->track;
+	c = radeon_get_ib_value(p, idx++) & 0x1F;
+	if (c > 16) {
+	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
+		      pkt->opcode);
+	    r100_cs_dump_packet(p, pkt);
+	    return -EINVAL;
+	}
+	track->num_arrays = c;
+	for (i = 0; i < (c - 1); i+=2, idx+=3) {
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+				  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		idx_value = radeon_get_ib_value(p, idx);
+		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+
+		track->arrays[i + 0].esize = idx_value >> 8;
+		track->arrays[i + 0].robj = reloc->robj;
+		track->arrays[i + 0].esize &= 0x7F;
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+				  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
+		track->arrays[i + 1].robj = reloc->robj;
+		track->arrays[i + 1].esize = idx_value >> 24;
+		track->arrays[i + 1].esize &= 0x7F;
+	}
+	if (c & 1) {
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		idx_value = radeon_get_ib_value(p, idx);
+		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+		track->arrays[i + 0].robj = reloc->robj;
+		track->arrays[i + 0].esize = idx_value >> 8;
+		track->arrays[i + 0].esize &= 0x7F;
+	}
+	return r;
+}
+
 void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
 	/* enable the pflip int */
@@ -78,13 +181,18 @@ u32 r100_page_flip(struct radeon_device
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
+	int i;
 
 	/* Lock the graphics update lock */
 	/* update the scanout addresses */
 	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -428,6 +536,7 @@ void r100_hpd_init(struct radeon_device
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		r100_irq_set(rdev);
@@ -468,7 +577,7 @@ int r100_pci_gart_init(struct radeon_dev
 {
 	int r;
 
-	if (rdev->gart.table.ram.ptr) {
+	if (rdev->gart.ptr) {
 		WARN(1, "R100 PCI GART already initialized\n");
 		return 0;
 	}
@@ -507,6 +616,9 @@ int r100_pci_gart_enable(struct radeon_d
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
 	WREG32(RADEON_AIC_CNTL, tmp);
 	r100_pci_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -524,10 +636,12 @@ void r100_pci_gart_disable(struct radeon
 
 int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
+	u32 *gtt = rdev->gart.ptr;
+
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
 	}
-	rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+	gtt[i] = cpu_to_le32(lower_32_bits(addr));
 	return 0;
 }
 
@@ -582,7 +696,7 @@ void r100_irq_disable(struct radeon_devi
 	WREG32(R_000044_GEN_INT_STATUS, tmp);
 }
 
-static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+static uint32_t r100_irq_ack(struct radeon_device *rdev)
 {
 	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
 	uint32_t irq_mask = RADEON_SW_INT_TEST |
@@ -3141,7 +3255,7 @@ void r100_bandwidth_update(struct radeon
 	}
 }
 
-static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
+static void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
 {
 	DRM_ERROR("pitch                      %d\n", t->pitch);
 	DRM_ERROR("use_pitch                  %d\n", t->use_pitch);
@@ -3959,3 +4073,43 @@ int r100_init(struct radeon_device *rdev
 	}
 	return 0;
 }
+
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	if (reg < rdev->rmmio_size)
+		return readl(((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	if (reg < rdev->rmmio_size)
+		writel(v, ((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
+{
+	if (reg < rdev->rio_mem_size)
+		return ioread32(rdev->rio_mem + reg);
+	else {
+		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+		return ioread32(rdev->rio_mem + RADEON_MM_DATA);
+	}
+}
+
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+	if (reg < rdev->rio_mem_size)
+		iowrite32(v, rdev->rio_mem + reg);
+	else {
+		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+		iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
+	}
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r100_track.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r100_track.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r100_track.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r100_track.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,106 +92,10 @@ int r200_packet0_check(struct radeon_cs_
 		       struct radeon_cs_packet *pkt,
 		       unsigned idx, unsigned reg);
 
-
-
-static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
-					  struct radeon_cs_packet *pkt,
-					  unsigned idx,
-					  unsigned reg)
-{
-	int r;
-	u32 tile_flags = 0;
-	u32 tmp;
-	struct radeon_cs_reloc *reloc;
-	u32 value;
-
-	r = r100_cs_packet_next_reloc(p, &reloc);
-	if (r) {
-		DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-			  idx, reg);
-		r100_cs_dump_packet(p, pkt);
-		return r;
-	}
-	value = radeon_get_ib_value(p, idx);
-	tmp = value & 0x003fffff;
-	tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-
-	if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-		tile_flags |= RADEON_DST_TILE_MACRO;
-	if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-		if (reg == RADEON_SRC_PITCH_OFFSET) {
-			DRM_ERROR("Cannot src blit from microtiled surface\n");
-			r100_cs_dump_packet(p, pkt);
-			return -EINVAL;
-		}
-		tile_flags |= RADEON_DST_TILE_MICRO;
-	}
-
-	tmp |= tile_flags;
-	p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
-	return 0;
-}
-
-static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
-					   struct radeon_cs_packet *pkt,
-					   int idx)
-{
-	unsigned c, i;
-	struct radeon_cs_reloc *reloc;
-	struct r100_cs_track *track;
-	int r = 0;
-	volatile uint32_t *ib;
-	u32 idx_value;
-
-	ib = p->ib->ptr;
-	track = (struct r100_cs_track *)p->track;
-	c = radeon_get_ib_value(p, idx++) & 0x1F;
-	if (c > 16) {
-	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
-		      pkt->opcode);
-	    r100_cs_dump_packet(p, pkt);
-	    return -EINVAL;
-	}
-	track->num_arrays = c;
-	for (i = 0; i < (c - 1); i+=2, idx+=3) {
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-				  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		idx_value = radeon_get_ib_value(p, idx);
-		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
-
-		track->arrays[i + 0].esize = idx_value >> 8;
-		track->arrays[i + 0].robj = reloc->robj;
-		track->arrays[i + 0].esize &= 0x7F;
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-				  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
-		track->arrays[i + 1].robj = reloc->robj;
-		track->arrays[i + 1].esize = idx_value >> 24;
-		track->arrays[i + 1].esize &= 0x7F;
-	}
-	if (c & 1) {
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-					  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		idx_value = radeon_get_ib_value(p, idx);
-		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
-		track->arrays[i + 0].robj = reloc->robj;
-		track->arrays[i + 0].esize = idx_value >> 8;
-		track->arrays[i + 0].esize &= 0x7F;
-	}
-	return r;
-}
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+			    struct radeon_cs_packet *pkt,
+			    unsigned idx,
+			    unsigned reg);
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+			     struct radeon_cs_packet *pkt,
+			     int idx);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r300.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r300.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r300.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@ void rv370_pcie_gart_tlb_flush(struct ra
 
 int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+	void __iomem *ptr = rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
@@ -93,7 +93,7 @@ int rv370_pcie_gart_init(struct radeon_d
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "RV370 PCIE GART already initialized\n");
 		return 0;
 	}
@@ -116,7 +116,7 @@ int rv370_pcie_gart_enable(struct radeon
 	uint32_t tmp;
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -144,8 +144,9 @@ int rv370_pcie_gart_enable(struct radeon
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
 	rv370_pcie_gart_tlb_flush(rdev);
-	DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
-		 (unsigned)(rdev->mc.gtt_size >> 20), table_addr);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -153,7 +154,6 @@ int rv370_pcie_gart_enable(struct radeon
 void rv370_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
@@ -162,14 +162,7 @@ void rv370_pcie_gart_disable(struct rade
 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv370_pcie_gart_fini(struct radeon_device *rdev)
@@ -708,16 +701,21 @@ static int r300_packet0_check(struct rad
 			return r;
 		}
 
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_TXO_MACRO_TILE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_TXO_MICRO_TILE;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
+		if (p->keep_tiling_flags) {
+			ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */
+				  ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset);
+		} else {
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_TXO_MACRO_TILE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_TXO_MICRO_TILE;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
 
-		tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		track->textures[i].robj = reloc->robj;
 		track->tex_dirty = true;
 		break;
@@ -767,24 +765,26 @@ static int r300_packet0_check(struct rad
 		/* RB3D_COLORPITCH1 */
 		/* RB3D_COLORPITCH2 */
 		/* RB3D_COLORPITCH3 */
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-				  idx, reg);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
+		if (!p->keep_tiling_flags) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
 
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_COLOR_TILE_ENABLE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_COLOR_MICROTILE_ENABLE;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_COLOR_TILE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
 
-		tmp = idx_value & ~(0x7 << 16);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			tmp = idx_value & ~(0x7 << 16);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		i = (reg - 0x4E38) >> 2;
 		track->cb[i].pitch = idx_value & 0x3FFE;
 		switch (((idx_value >> 21) & 0xF)) {
@@ -850,25 +850,26 @@ static int r300_packet0_check(struct rad
 		break;
 	case 0x4F24:
 		/* ZB_DEPTHPITCH */
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-				  idx, reg);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_DEPTHMACROTILE_ENABLE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_DEPTHMICROTILE_TILED;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
+		if (!p->keep_tiling_flags) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
 
-		tmp = idx_value & ~(0x7 << 16);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_DEPTHMACROTILE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_DEPTHMICROTILE_TILED;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
 
+			tmp = idx_value & ~(0x7 << 16);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		track->zb.pitch = idx_value & 0x3FFC;
 		track->zb_dirty = true;
 		break;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r300_cmdbuf.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r300_cmdbuf.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r300_cmdbuf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r300_cmdbuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -791,7 +791,7 @@ static __inline__ int r300_emit_packet3(
 /**
  * Emit the sequence to pacify R300.
  */
-static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
+static void r300_pacify(drm_radeon_private_t *dev_priv)
 {
 	uint32_t cache_z, cache_3d, cache_2d;
 	RING_LOCALS;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_blit.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_blit.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_blit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_blit.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,7 @@
 #define COLOR_5_6_5           0x8
 #define COLOR_8_8_8_8         0x1a
 
-static inline void
+static void
 set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
 {
 	u32 cb_color_info;
@@ -99,7 +99,7 @@ set_render_target(drm_radeon_private_t *
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 cp_set_surface_sync(drm_radeon_private_t *dev_priv,
 		    u32 sync_type, u32 size, u64 mc_addr)
 {
@@ -121,7 +121,7 @@ cp_set_surface_sync(drm_radeon_private_t
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 set_shaders(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -184,7 +184,7 @@ set_shaders(struct drm_device *dev)
 			    R600_SH_ACTION_ENA, 512, gpu_addr);
 }
 
-static inline void
+static void
 set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
 {
 	uint32_t sq_vtx_constant_word2;
@@ -220,7 +220,7 @@ set_vtx_resource(drm_radeon_private_t *d
 				    R600_VC_ACTION_ENA, 48, gpu_addr);
 }
 
-static inline void
+static void
 set_tex_resource(drm_radeon_private_t *dev_priv,
 		 int format, int w, int h, int pitch, u64 gpu_addr)
 {
@@ -258,7 +258,7 @@ set_tex_resource(drm_radeon_private_t *d
 
 }
 
-static inline void
+static void
 set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
 {
 	RING_LOCALS;
@@ -282,7 +282,7 @@ set_scissors(drm_radeon_private_t *dev_p
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 draw_auto(drm_radeon_private_t *dev_priv)
 {
 	RING_LOCALS;
@@ -311,7 +311,7 @@ draw_auto(drm_radeon_private_t *dev_priv
 	COMMIT_RING();
 }
 
-static inline void
+static void
 set_default_state(drm_radeon_private_t *dev_priv)
 {
 	int i;
@@ -489,7 +489,7 @@ set_default_state(drm_radeon_private_t *
 	ADVANCE_RING();
 }
 
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
 {
 	u32 result, i, exponent, fraction;
 
@@ -515,7 +515,7 @@ static inline uint32_t i2f(uint32_t inpu
 }
 
 
-static inline int r600_nomm_get_vb(struct drm_device *dev)
+static int r600_nomm_get_vb(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	dev_priv->blit_vb = radeon_freelist_get(dev);
@@ -526,7 +526,7 @@ static inline int r600_nomm_get_vb(struc
 	return 0;
 }
 
-static inline void r600_nomm_put_vb(struct drm_device *dev)
+static void r600_nomm_put_vb(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -534,7 +534,7 @@ static inline void r600_nomm_put_vb(stru
 	radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
 }
 
-static inline void *r600_nomm_get_vb_ptr(struct drm_device *dev)
+static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	return (((char *)dev->agp_buffer_map->handle +
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@
 #define COLOR_5_6_5           0x8
 #define COLOR_8_8_8_8         0x1a
 
+#define RECT_UNIT_H           32
+#define RECT_UNIT_W           (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H)
+
 /* emits 21 on rv770+, 23 on r600 */
 static void
 set_render_target(struct radeon_device *rdev, int format,
@@ -54,7 +57,9 @@ set_render_target(struct radeon_device *
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 27) | (1 << 8));
+	cb_color_info = CB_FORMAT(format) |
+		CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+		CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -164,9 +169,10 @@ set_vtx_resource(struct radeon_device *r
 {
 	u32 sq_vtx_constant_word2;
 
-	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+	sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+		SQ_VTXC_STRIDE(16);
 #ifdef __BIG_ENDIAN
-	sq_vtx_constant_word2 |= (2 << 30);
+	sq_vtx_constant_word2 |=  SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
 #endif
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
@@ -195,25 +201,29 @@ set_vtx_resource(struct radeon_device *r
 static void
 set_tex_resource(struct radeon_device *rdev,
 		 int format, int w, int h, int pitch,
-		 u64 gpu_addr)
+		 u64 gpu_addr, u32 size)
 {
 	uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
 
 	if (h < 1)
 		h = 1;
 
-	sq_tex_resource_word0 = (1 << 0) | (1 << 3);
-	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
-				  ((w - 1) << 19));
+	sq_tex_resource_word0 = S_038000_DIM(V_038000_SQ_TEX_DIM_2D) |
+		S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	sq_tex_resource_word0 |= S_038000_PITCH((pitch >> 3) - 1) |
+		S_038000_TEX_WIDTH(w - 1);
 
-	sq_tex_resource_word1 = (format << 26);
-	sq_tex_resource_word1 |= ((h - 1) << 0);
+	sq_tex_resource_word1 = S_038004_DATA_FORMAT(format);
+	sq_tex_resource_word1 |= S_038004_TEX_HEIGHT(h - 1);
 
-	sq_tex_resource_word4 = ((1 << 14) |
-				 (0 << 16) |
-				 (1 << 19) |
-				 (2 << 22) |
-				 (3 << 25));
+	sq_tex_resource_word4 = S_038010_REQUEST_SIZE(1) |
+		S_038010_DST_SEL_X(SQ_SEL_X) |
+		S_038010_DST_SEL_Y(SQ_SEL_Y) |
+		S_038010_DST_SEL_Z(SQ_SEL_Z) |
+		S_038010_DST_SEL_W(SQ_SEL_W);
+
+	cp_set_surface_sync(rdev,
+			    PACKET3_TC_ACTION_ENA, size, gpu_addr);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
 	radeon_ring_write(rdev, 0);
@@ -450,7 +460,7 @@ set_default_state(struct radeon_device *
 	radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
 }
 
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
 {
 	u32 result, i, exponent, fraction;
 
@@ -483,6 +493,27 @@ int r600_blit_init(struct radeon_device
 	u32 packet2s[16];
 	int num_packet2s = 0;
 
+	rdev->r600_blit.primitives.set_render_target = set_render_target;
+	rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+	rdev->r600_blit.primitives.set_shaders = set_shaders;
+	rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+	rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+	rdev->r600_blit.primitives.set_scissors = set_scissors;
+	rdev->r600_blit.primitives.draw_auto = draw_auto;
+	rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+	rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
+	rdev->r600_blit.ring_size_common += 5; /* done copy */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
+
+	rdev->r600_blit.ring_size_per_loop = 76;
+	/* set_render_target emits 2 extra dwords on rv6xx */
+	if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
+		rdev->r600_blit.ring_size_per_loop += 2;
+
+	rdev->r600_blit.max_dim = 8192;
+
 	/* pin copy shader into vram if already initialized */
 	if (rdev->r600_blit.shader_obj)
 		goto done;
@@ -600,47 +631,80 @@ static void r600_vb_ib_put(struct radeon
 	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
 }
 
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
+static unsigned r600_blit_create_rect(unsigned num_gpu_pages,
+				      int *width, int *height, int max_dim)
+{
+	unsigned max_pages;
+	unsigned pages = num_gpu_pages;
+	int w, h;
+
+	if (num_gpu_pages == 0) {
+		/* not supposed to be called with no pages, but just in case */
+		h = 0;
+		w = 0;
+		pages = 0;
+		WARN_ON(1);
+	} else {
+		int rect_order = 2;
+		h = RECT_UNIT_H;
+		while (num_gpu_pages / rect_order) {
+			h *= 2;
+			rect_order *= 4;
+			if (h >= max_dim) {
+				h = max_dim;
+				break;
+			}
+		}
+		max_pages = (max_dim * h) / (RECT_UNIT_W * RECT_UNIT_H);
+		if (pages > max_pages)
+			pages = max_pages;
+		w = (pages * RECT_UNIT_W * RECT_UNIT_H) / h;
+		w = (w / RECT_UNIT_W) * RECT_UNIT_W;
+		pages = (w * h) / (RECT_UNIT_W * RECT_UNIT_H);
+		BUG_ON(pages == 0);
+	}
+
+
+	DRM_DEBUG("blit_rectangle: h=%d, w=%d, pages=%d\n", h, w, pages);
+
+	/* return width and height only of the caller wants it */
+	if (height)
+		*height = h;
+	if (width)
+		*width = w;
+
+	return pages;
+}
+
+
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
 {
 	int r;
-	int ring_size, line_size;
-	int max_size;
-	/* loops of emits 64 + fence emit possible */
-	int dwords_per_loop = 76, num_loops;
+	int ring_size;
+	int num_loops = 0;
+	int dwords_per_loop = rdev->r600_blit.ring_size_per_loop;
 
 	r = r600_vb_ib_get(rdev);
 	if (r)
 		return r;
 
-	/* set_render_target emits 2 extra dwords on rv6xx */
-	if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
-		dwords_per_loop += 2;
-
-	/* 8 bpp vs 32 bpp for xfer unit */
-	if (size_bytes & 3)
-		line_size = 8192;
-	else
-		line_size = 8192*4;
-
-	max_size = 8192 * line_size;
+	/* num loops */
+	while (num_gpu_pages) {
+		num_gpu_pages -=
+			r600_blit_create_rect(num_gpu_pages, NULL, NULL,
+					      rdev->r600_blit.max_dim);
+		num_loops++;
+	}
 
-	/* major loops cover the max size transfer */
-	num_loops = ((size_bytes + max_size) / max_size);
-	/* minor loops cover the extra non aligned bits */
-	num_loops += ((size_bytes % line_size) ? 1 : 0);
 	/* calculate number of loops correctly */
 	ring_size = num_loops * dwords_per_loop;
-	/* set default  + shaders */
-	ring_size += 40; /* shaders + def state */
-	ring_size += 10; /* fence emit for VB IB */
-	ring_size += 5; /* done copy */
-	ring_size += 10; /* fence emit for done copy */
+	ring_size += rdev->r600_blit.ring_size_common;
 	r = radeon_ring_lock(rdev, ring_size);
 	if (r)
 		return r;
 
-	set_default_state(rdev); /* 14 */
-	set_shaders(rdev); /* 26 */
+	rdev->r600_blit.primitives.set_default_state(rdev);
+	rdev->r600_blit.primitives.set_shaders(rdev);
 	return 0;
 }
 
@@ -659,182 +723,61 @@ void r600_blit_done_copy(struct radeon_d
 
 void r600_kms_blit_copy(struct radeon_device *rdev,
 			u64 src_gpu_addr, u64 dst_gpu_addr,
-			int size_bytes)
+			unsigned num_gpu_pages)
 {
-	int max_bytes;
 	u64 vb_gpu_addr;
 	u32 *vb;
 
-	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
-		  size_bytes, rdev->r600_blit.vb_used);
+	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n",
+		  src_gpu_addr, dst_gpu_addr,
+		  num_gpu_pages, rdev->r600_blit.vb_used);
 	vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
-	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
-		max_bytes = 8192;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = src_gpu_addr & 255;
-			int dst_x = dst_gpu_addr & 255;
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
 
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x);
-			vb[1] = 0;
-			vb[2] = i2f(src_x);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f(dst_x + cur_size);
-			vb[9] = i2f(h);
-			vb[10] = i2f(src_x + cur_size);
-			vb[11] = i2f(h);
-
-			/* src 9 */
-			set_tex_resource(rdev, FMT_8,
-					 src_x + cur_size, h, src_x + cur_size,
-					 src_gpu_addr);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst 23 */
-			set_render_target(rdev, COLOR_8,
-					  dst_x + cur_size, h,
-					  dst_gpu_addr);
-
-			/* scissors 12 */
-			set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
-
-			/* 14 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
+	while (num_gpu_pages) {
+		int w, h;
+		unsigned size_in_bytes;
+		unsigned pages_per_loop =
+			r600_blit_create_rect(num_gpu_pages, &w, &h,
+					      rdev->r600_blit.max_dim);
 
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
+		size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE;
+		DRM_DEBUG("rectangle w=%d h=%d\n", w, h);
 
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
+		if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
+			WARN_ON(1);
 		}
-	} else {
-		max_bytes = 8192 * 4;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = (src_gpu_addr & 255);
-			int dst_x = (dst_gpu_addr & 255);
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x / 4);
-			vb[1] = 0;
-			vb[2] = i2f(src_x / 4);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x / 4);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x / 4);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f((dst_x + cur_size) / 4);
-			vb[9] = i2f(h);
-			vb[10] = i2f((src_x + cur_size) / 4);
-			vb[11] = i2f(h);
-
-			/* src 9 */
-			set_tex_resource(rdev, FMT_8_8_8_8,
-					 (src_x + cur_size) / 4,
-					 h, (src_x + cur_size) / 4,
-					 src_gpu_addr);
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
 
-			/* dst 23 */
-			set_render_target(rdev, COLOR_8_8_8_8,
-					  (dst_x + cur_size) / 4, h,
-					  dst_gpu_addr);
-
-			/* scissors 12  */
-			set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
-			/* Vertex buffer setup 14 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
+		vb[0] = 0;
+		vb[1] = 0;
+		vb[2] = 0;
+		vb[3] = 0;
 
-			/* draw 10 */
-			draw_auto(rdev);
+		vb[4] = 0;
+		vb[5] = i2f(h);
+		vb[6] = 0;
+		vb[7] = i2f(h);
 
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
+		vb[8] = i2f(w);
+		vb[9] = i2f(h);
+		vb[10] = i2f(w);
+		vb[11] = i2f(h);
 
-			/* 78 ring dwords per loop */
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
+		rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
+							    w, h, w, src_gpu_addr, size_in_bytes);
+		rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
+							     w, h, dst_gpu_addr);
+		rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
+		vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
+		rdev->r600_blit.primitives.set_vtx_resource(rdev, vb_gpu_addr);
+		rdev->r600_blit.primitives.draw_auto(rdev);
+		rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
+				    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
+				    size_in_bytes, dst_gpu_addr);
 
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
+		vb += 12;
+		rdev->r600_blit.vb_used += 4*12;
+		src_gpu_addr += size_in_bytes;
+		dst_gpu_addr += size_in_bytes;
+		num_gpu_pages -= pages_per_loop;
 	}
 }
-
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600.c	2013-05-02 01:33:41.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600.c	2013-05-01 23:41:43.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
@@ -247,24 +248,6 @@ void r600_pm_get_dynpm_state(struct rade
 		  pcie_lanes);
 }
 
-static int r600_pm_get_type_index(struct radeon_device *rdev,
-				  enum radeon_pm_state_type ps_type,
-				  int instance)
-{
-	int i;
-	int found_instance = -1;
-
-	for (i = 0; i < rdev->pm.num_power_states; i++) {
-		if (rdev->pm.power_state[i].type == ps_type) {
-			found_instance++;
-			if (found_instance == instance)
-				return i;
-		}
-	}
-	/* return default if no match */
-	return rdev->pm.default_power_state_index;
-}
-
 void rs780_pm_init_profile(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states == 2) {
@@ -380,6 +363,8 @@ void rs780_pm_init_profile(struct radeon
 
 void r600_pm_init_profile(struct radeon_device *rdev)
 {
+	int idx;
+
 	if (rdev->family == CHIP_R600) {
 		/* XXX */
 		/* default */
@@ -461,81 +446,43 @@ void r600_pm_init_profile(struct radeon_
 			rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
 			/* low sh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-			}
+			if (rdev->flags & RADEON_IS_MOBILITY)
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+			else
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
 			/* mid sh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-			}
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
 			/* high sh */
-			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
 			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
 			/* low mh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-			}
+			if (rdev->flags & RADEON_IS_MOBILITY)
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+			else
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
 			/* mid mh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-			}
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
 			/* high mh */
-			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
 			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
 		}
@@ -722,13 +669,14 @@ void r600_hpd_init(struct radeon_device
 	struct drm_device *dev = rdev->ddev;
 	struct drm_connector *connector;
 
-	if (ASIC_IS_DCE3(rdev)) {
-		u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
-		if (ASIC_IS_DCE32(rdev))
-			tmp |= DC_HPDx_EN;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+		if (ASIC_IS_DCE3(rdev)) {
+			u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
+			if (ASIC_IS_DCE32(rdev))
+				tmp |= DC_HPDx_EN;
 
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 			switch (radeon_connector->hpd.hpd) {
 			case RADEON_HPD_1:
 				WREG32(DC_HPD1_CONTROL, tmp);
@@ -758,10 +706,7 @@ void r600_hpd_init(struct radeon_device
 			default:
 				break;
 			}
-		}
-	} else {
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		} else {
 			switch (radeon_connector->hpd.hpd) {
 			case RADEON_HPD_1:
 				WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
@@ -779,6 +724,7 @@ void r600_hpd_init(struct radeon_device
 				break;
 			}
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		r600_irq_set(rdev);
@@ -856,7 +802,7 @@ void r600_pcie_gart_tlb_flush(struct rad
 	/* flush hdp cache so updates hit vram */
 	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
 	    !(rdev->flags & RADEON_IS_AGP)) {
-		void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+		void __iomem *ptr = (void *)rdev->gart.ptr;
 		u32 tmp;
 
 		/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
@@ -891,7 +837,7 @@ int r600_pcie_gart_init(struct radeon_de
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "R600 PCIE GART already initialized\n");
 		return 0;
 	}
@@ -908,7 +854,7 @@ int r600_pcie_gart_enable(struct radeon_
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -953,6 +899,9 @@ int r600_pcie_gart_enable(struct radeon_
 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
 
 	r600_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -960,7 +909,7 @@ int r600_pcie_gart_enable(struct radeon_
 void r600_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i, r;
+	int i;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -987,14 +936,7 @@ void r600_pcie_gart_disable(struct radeo
 	WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
 	WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
 	WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void r600_pcie_gart_fini(struct radeon_device *rdev)
@@ -1094,7 +1036,7 @@ static void r600_mc_program(struct radeo
 		WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 	WREG32(MC_VM_FB_LOCATION, tmp);
@@ -1233,6 +1175,53 @@ int r600_mc_init(struct radeon_device *r
 	return 0;
 }
 
+int r600_vram_scratch_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
+				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+				     &rdev->vram_scratch.robj);
+		if (r) {
+			return r;
+		}
+	}
+
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rdev->vram_scratch.robj,
+			  RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
+	if (r) {
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+		return r;
+	}
+	r = radeon_bo_kmap(rdev->vram_scratch.robj,
+				(void **)&rdev->vram_scratch.ptr);
+	if (r)
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+	radeon_bo_unreserve(rdev->vram_scratch.robj);
+
+	return r;
+}
+
+void r600_vram_scratch_fini(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		return;
+	}
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (likely(r == 0)) {
+		radeon_bo_kunmap(rdev->vram_scratch.robj);
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+	}
+	radeon_bo_unref(&rdev->vram_scratch.robj);
+}
+
 /* We doesn't check that the GPU really needs a reset we simply do the
  * reset, it's up to the caller to determine if the GPU needs one. We
  * might add an helper function to check that.
@@ -2288,6 +2277,14 @@ void r600_fence_ring_emit(struct radeon_
 	if (rdev->wb.use_event) {
 		u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
 			(u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base);
+		/* flush read cache over gart */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+		radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+					PACKET3_VC_ACTION_ENA |
+					PACKET3_SH_ACTION_ENA);
+		radeon_ring_write(rdev, 0xFFFFFFFF);
+		radeon_ring_write(rdev, 0);
+		radeon_ring_write(rdev, 10); /* poll interval */
 		/* EVENT_WRITE_EOP - flush caches, send int */
 		radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
 		radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
@@ -2296,6 +2293,14 @@ void r600_fence_ring_emit(struct radeon_
 		radeon_ring_write(rdev, fence->seq);
 		radeon_ring_write(rdev, 0);
 	} else {
+		/* flush read cache over gart */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+		radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+					PACKET3_VC_ACTION_ENA |
+					PACKET3_SH_ACTION_ENA);
+		radeon_ring_write(rdev, 0xFFFFFFFF);
+		radeon_ring_write(rdev, 0);
+		radeon_ring_write(rdev, 10); /* poll interval */
 		radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
 		radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0));
 		/* wait for 3D idle clean */
@@ -2322,19 +2327,33 @@ int r600_copy_blit(struct radeon_device
 
 	mutex_lock(&rdev->r600_blit.mutex);
 	rdev->r600_blit.vb_ib = NULL;
-	r = r600_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+	r = r600_blit_prepare_copy(rdev, num_gpu_pages);
 	if (r) {
 		if (rdev->r600_blit.vb_ib)
 			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
 		mutex_unlock(&rdev->r600_blit.mutex);
 		return r;
 	}
-	r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+	r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages);
 	r600_blit_done_copy(rdev, fence);
 	mutex_unlock(&rdev->r600_blit.mutex);
 	return 0;
 }
 
+void r600_blit_suspend(struct radeon_device *rdev)
+{
+	int r;
+
+	/* unpin shaders bo */
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (!r) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
+	}
+}
+
 int r600_set_surface_reg(struct radeon_device *rdev, int reg,
 			 uint32_t tiling_flags, uint32_t pitch,
 			 uint32_t offset, uint32_t obj_size)
@@ -2363,6 +2382,10 @@ int r600_startup(struct radeon_device *r
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	r600_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		r600_agp_enable(rdev);
@@ -2454,8 +2477,6 @@ int r600_resume(struct radeon_device *rd
 
 int r600_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	r600_audio_fini(rdev);
 	/* FIXME: we should wait for ring to be empty */
 	r600_cp_stop(rdev);
@@ -2463,14 +2484,8 @@ int r600_suspend(struct radeon_device *r
 	r600_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	r600_pcie_gart_disable(rdev);
-	/* unpin shaders bo */
-	if (rdev->r600_blit.shader_obj) {
-		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-		if (!r) {
-			radeon_bo_unpin(rdev->r600_blit.shader_obj);
-			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-		}
-	}
+	r600_blit_suspend(rdev);
+
 	return 0;
 }
 
@@ -2591,6 +2606,7 @@ void r600_fini(struct radeon_device *rde
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	r600_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_agp_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
@@ -3097,7 +3113,7 @@ int r600_irq_set(struct radeon_device *r
 	return 0;
 }
 
-static inline void r600_irq_ack(struct radeon_device *rdev)
+static void r600_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
@@ -3198,7 +3214,7 @@ void r600_irq_disable(struct radeon_devi
 	r600_disable_interrupt_state(rdev);
 }
 
-static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
+static u32 r600_get_ih_wptr(struct radeon_device *rdev)
 {
 	u32 wptr, tmp;
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_cp.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_cp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_cp.c	2013-05-02 01:33:44.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_cp.c	2013-05-01 23:41:46.000000000 -0400
@@ -26,6 +26,8 @@
  *     Alex Deucher <alexander.deucher@amd.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "radeon_drm.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_cs.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,7 @@ static const struct gpu_formats color_fo
 	[V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
 };
 
-static inline bool fmt_is_valid_color(u32 format)
+static bool fmt_is_valid_color(u32 format)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return false;
@@ -173,7 +173,7 @@ static inline bool fmt_is_valid_color(u3
 	return false;
 }
 
-static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family)
+static bool fmt_is_valid_texture(u32 format, enum radeon_family family)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return false;
@@ -187,7 +187,7 @@ static inline bool fmt_is_valid_texture(
 	return false;
 }
 
-static inline int fmt_get_blocksize(u32 format)
+static int fmt_get_blocksize(u32 format)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return 0;
@@ -195,7 +195,7 @@ static inline int fmt_get_blocksize(u32
 	return color_formats_table[format].blocksize;
 }
 
-static inline int fmt_get_nblocksx(u32 format, u32 w)
+static int fmt_get_nblocksx(u32 format, u32 w)
 {
 	unsigned bw;
 
@@ -209,7 +209,7 @@ static inline int fmt_get_nblocksx(u32 f
 	return (w + bw - 1) / bw;
 }
 
-static inline int fmt_get_nblocksy(u32 format, u32 h)
+static int fmt_get_nblocksy(u32 format, u32 h)
 {
 	unsigned bh;
 
@@ -223,25 +223,6 @@ static inline int fmt_get_nblocksy(u32 f
 	return (h + bh - 1) / bh;
 }
 
-static inline int r600_bpe_from_format(u32 *bpe, u32 format)
-{
- 	unsigned res;
-
-	if (format >= ARRAY_SIZE(color_formats_table))
-		goto fail;
-
-	res = color_formats_table[format].blocksize;
-	if (res == 0)
-		goto fail;
-
-	*bpe = res;
-	return 0;
-
-fail:
-	*bpe = 16;
-	return -EINVAL;
-}
-
 struct array_mode_checker {
 	int array_mode;
 	u32 group_size;
@@ -252,7 +233,7 @@ struct array_mode_checker {
 };
 
 /* returns alignment in pixels for pitch/height/depth and bytes for base */
-static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
+static int r600_get_array_mode_alignment(struct array_mode_checker *values,
 						u32 *pitch_align,
 						u32 *height_align,
 						u32 *depth_align,
@@ -331,7 +312,7 @@ static void r600_cs_track_init(struct r6
 	track->db_depth_control = 0xFFFFFFFF;
 }
 
-static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 {
 	struct r600_cs_track *track = p->track;
 	u32 slice_tile_max, size, tmp;
@@ -737,7 +718,7 @@ static int r600_cs_packet_next_reloc_nom
  * Check next packet is relocation packet3, do bo validation and compute
  * GPU offset using the provided start.
  **/
-static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
 {
 	struct radeon_cs_packet p3reloc;
 	int r;
@@ -911,7 +892,7 @@ static int r600_cs_parse_packet0(struct
  * if register is safe. If register is not flag as safe this function
  * will test it against a list of register needind special handling.
  */
-static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 {
 	struct r600_cs_track *track = (struct r600_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
@@ -960,7 +941,8 @@ static inline int r600_cs_check_reg(stru
 		track->db_depth_control = radeon_get_ib_value(p, idx);
 		break;
 	case R_028010_DB_DEPTH_INFO:
-		if (r600_cs_packet_next_is_pkt3_nop(p)) {
+		if (!p->keep_tiling_flags &&
+		    r600_cs_packet_next_is_pkt3_nop(p)) {
 			r = r600_cs_packet_next_reloc(p, &reloc);
 			if (r) {
 				dev_warn(p->dev, "bad SET_CONTEXT_REG "
@@ -1011,7 +993,8 @@ static inline int r600_cs_check_reg(stru
 	case R_0280B4_CB_COLOR5_INFO:
 	case R_0280B8_CB_COLOR6_INFO:
 	case R_0280BC_CB_COLOR7_INFO:
-		if (r600_cs_packet_next_is_pkt3_nop(p)) {
+		if (!p->keep_tiling_flags &&
+		     r600_cs_packet_next_is_pkt3_nop(p)) {
 			r = r600_cs_packet_next_reloc(p, &reloc);
 			if (r) {
 				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
@@ -1215,7 +1198,7 @@ static inline int r600_cs_check_reg(stru
 	return 0;
 }
 
-static inline unsigned mip_minify(unsigned size, unsigned level)
+static unsigned mip_minify(unsigned size, unsigned level)
 {
 	unsigned val;
 
@@ -1285,7 +1268,7 @@ static void r600_texture_size(unsigned n
  * This function will check that the resource has valid field and that
  * the texture and mipmap bo object are big enough to cover this resource.
  */
-static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 					      struct radeon_bo *texture,
 					      struct radeon_bo *mipmap,
 					      u64 base_offset,
@@ -1310,10 +1293,12 @@ static inline int r600_check_texture_res
 	mip_offset <<= 8;
 
 	word0 = radeon_get_ib_value(p, idx + 0);
-	if (tiling_flags & RADEON_TILING_MACRO)
-		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-	else if (tiling_flags & RADEON_TILING_MICRO)
-		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	if (!p->keep_tiling_flags) {
+		if (tiling_flags & RADEON_TILING_MACRO)
+			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+		else if (tiling_flags & RADEON_TILING_MICRO)
+			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	}
 	word1 = radeon_get_ib_value(p, idx + 1);
 	w0 = G_038000_TEX_WIDTH(word0) + 1;
 	h0 = G_038004_TEX_HEIGHT(word1) + 1;
@@ -1640,10 +1625,12 @@ static int r600_packet3_check(struct rad
 					return -EINVAL;
 				}
 				base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+				if (!p->keep_tiling_flags) {
+					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+					else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+				}
 				texture = reloc->robj;
 				/* tex mip base */
 				r = r600_cs_packet_next_reloc(p, &reloc);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600d.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600d.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/r600d.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/r600d.h	2012-01-04 18:55:44.000000000 -0500
@@ -79,6 +79,11 @@
 #define CB_COLOR0_SIZE                                  0x28060
 #define CB_COLOR0_VIEW                                  0x28080
 #define CB_COLOR0_INFO                                  0x280a0
+#	define CB_FORMAT(x)				((x) << 2)
+#       define CB_ARRAY_MODE(x)                         ((x) << 8)
+#	define CB_SOURCE_FORMAT(x)			((x) << 27)
+#	define CB_SF_EXPORT_FULL			0
+#	define CB_SF_EXPORT_NORM			1
 #define CB_COLOR0_TILE                                  0x280c0
 #define CB_COLOR0_FRAG                                  0x280e0
 #define CB_COLOR0_MASK                                  0x28100
@@ -417,6 +422,17 @@
 #define	SQ_PGM_START_VS					0x28858
 #define SQ_PGM_RESOURCES_VS                             0x28868
 #define SQ_PGM_CF_OFFSET_VS                             0x288d0
+
+#define SQ_VTX_CONSTANT_WORD0_0				0x30000
+#define SQ_VTX_CONSTANT_WORD1_0				0x30004
+#define SQ_VTX_CONSTANT_WORD2_0				0x30008
+#	define SQ_VTXC_BASE_ADDR_HI(x)			((x) << 0)
+#	define SQ_VTXC_STRIDE(x)			((x) << 8)
+#	define SQ_VTXC_ENDIAN_SWAP(x)			((x) << 30)
+#	define SQ_ENDIAN_NONE				0
+#	define SQ_ENDIAN_8IN16				1
+#	define SQ_ENDIAN_8IN32				2
+#define SQ_VTX_CONSTANT_WORD3_0				0x3000c
 #define	SQ_VTX_CONSTANT_WORD6_0				0x38018
 #define		S__SQ_VTX_CONSTANT_TYPE(x)			(((x) & 3) << 30)
 #define		G__SQ_VTX_CONSTANT_TYPE(x)			(((x) >> 30) & 3)
@@ -1352,6 +1368,12 @@
 #define   S_038010_DST_SEL_W(x)                        (((x) & 0x7) << 25)
 #define   G_038010_DST_SEL_W(x)                        (((x) >> 25) & 0x7)
 #define   C_038010_DST_SEL_W                           0xF1FFFFFF
+#	define SQ_SEL_X					0
+#	define SQ_SEL_Y					1
+#	define SQ_SEL_Z					2
+#	define SQ_SEL_W					3
+#	define SQ_SEL_0					4
+#	define SQ_SEL_1					5
 #define   S_038010_BASE_LEVEL(x)                       (((x) & 0xF) << 28)
 #define   G_038010_BASE_LEVEL(x)                       (((x) >> 28) & 0xF)
 #define   C_038010_BASE_LEVEL                          0x0FFFFFFF
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_acpi.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_acpi.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,8 @@ static int radeon_atif_call(acpi_handle
 
 	/* Fail only if calling the method fails and ATIF is supported */
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		printk(KERN_DEBUG "failed to evaluate ATIF got %s\n", acpi_format_exception(status));
+		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
+				 acpi_format_exception(status));
 		kfree(buffer.pointer);
 		return 1;
 	}
@@ -50,13 +51,13 @@ int radeon_acpi_init(struct radeon_devic
 	acpi_handle handle;
 	int ret;
 
-	/* No need to proceed if we're sure that ATIF is not supported */
-	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios)
-		return 0;
-
 	/* Get the device handle */
 	handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
 
+	/* No need to proceed if we're sure that ATIF is not supported */
+	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle)
+		return 0;
+
 	/* Call the ATIF method */
 	ret = radeon_atif_call(handle);
 	if (ret)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_asic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_asic.c	2012-01-04 18:55:44.000000000 -0500
@@ -765,9 +765,9 @@ static struct radeon_asic evergreen_asic
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -812,9 +812,9 @@ static struct radeon_asic sumo_asic = {
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = NULL,
@@ -834,7 +834,7 @@ static struct radeon_asic sumo_asic = {
 	.pm_misc = &evergreen_pm_misc,
 	.pm_prepare = &evergreen_pm_prepare,
 	.pm_finish = &evergreen_pm_finish,
-	.pm_init_profile = &rs780_pm_init_profile,
+	.pm_init_profile = &sumo_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
 	.pre_page_flip = &evergreen_pre_page_flip,
 	.page_flip = &evergreen_page_flip,
@@ -859,9 +859,9 @@ static struct radeon_asic btc_asic = {
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -906,9 +906,9 @@ static struct radeon_asic cayman_asic =
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_asic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_asic.h	2012-01-04 18:55:44.000000000 -0500
@@ -364,11 +364,11 @@ void r600_hdmi_init(struct drm_encoder *
 int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 /* r600 blit */
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages);
 void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
 void r600_kms_blit_copy(struct radeon_device *rdev,
 			u64 src_gpu_addr, u64 dst_gpu_addr,
-			int size_bytes);
+			unsigned num_gpu_pages);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -401,9 +401,6 @@ bool evergreen_gpu_is_lockup(struct rade
 int evergreen_asic_reset(struct radeon_device *rdev);
 void evergreen_bandwidth_update(struct radeon_device *rdev);
 void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-int evergreen_copy_blit(struct radeon_device *rdev,
-			uint64_t src_offset, uint64_t dst_offset,
-			unsigned num_gpu_pages, struct radeon_fence *fence);
 void evergreen_hpd_init(struct radeon_device *rdev);
 void evergreen_hpd_fini(struct radeon_device *rdev);
 bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -416,18 +413,12 @@ extern int evergreen_cs_parse(struct rad
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
+extern void sumo_pm_init_profile(struct radeon_device *rdev);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
 void evergreen_disable_interrupt_state(struct radeon_device *rdev);
 int evergreen_blit_init(struct radeon_device *rdev);
-void evergreen_blit_fini(struct radeon_device *rdev);
-/* evergreen blit */
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
-			     u64 src_gpu_addr, u64 dst_gpu_addr,
-			     int size_bytes);
 
 /*
  * cayman
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,7 +62,88 @@ union atom_supported_devices {
 	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
 };
 
-static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
+static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
+					  ATOM_GPIO_I2C_ASSIGMENT *gpio,
+					  u8 index)
+{
+	/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
+	if ((rdev->family == CHIP_R420) ||
+	    (rdev->family == CHIP_R423) ||
+	    (rdev->family == CHIP_RV410)) {
+		if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
+			gpio->ucClkMaskShift = 0x19;
+			gpio->ucDataMaskShift = 0x18;
+		}
+	}
+
+	/* some evergreen boards have bad data for this entry */
+	if (ASIC_IS_DCE4(rdev)) {
+		if ((index == 7) &&
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
+		    (gpio->sucI2cId.ucAccess == 0)) {
+			gpio->sucI2cId.ucAccess = 0x97;
+			gpio->ucDataMaskShift = 8;
+			gpio->ucDataEnShift = 8;
+			gpio->ucDataY_Shift = 8;
+			gpio->ucDataA_Shift = 8;
+		}
+	}
+
+	/* some DCE3 boards have bad data for this entry */
+	if (ASIC_IS_DCE3(rdev)) {
+		if ((index == 4) &&
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
+		    (gpio->sucI2cId.ucAccess == 0x94))
+			gpio->sucI2cId.ucAccess = 0x14;
+	}
+}
+
+static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
+{
+	struct radeon_i2c_bus_rec i2c;
+
+	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+
+	i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+	i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+	i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+	i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+	i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+	i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+	i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+	i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+	i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+	i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+	i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+	i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+	i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+	i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+	i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+	i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+	if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+		i2c.hw_capable = true;
+	else
+		i2c.hw_capable = false;
+
+	if (gpio->sucI2cId.ucAccess == 0xa0)
+		i2c.mm_i2c = true;
+	else
+		i2c.mm_i2c = false;
+
+	i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+	if (i2c.mask_clk_reg)
+		i2c.valid = true;
+	else
+		i2c.valid = false;
+
+	return i2c;
+}
+
+static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
 							       uint8_t id)
 {
 	struct atom_context *ctx = rdev->mode_info.atom_context;
@@ -85,59 +166,10 @@ static inline struct radeon_i2c_bus_rec
 		for (i = 0; i < num_indices; i++) {
 			gpio = &i2c_info->asGPIO_Info[i];
 
-			/* some evergreen boards have bad data for this entry */
-			if (ASIC_IS_DCE4(rdev)) {
-				if ((i == 7) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-				    (gpio->sucI2cId.ucAccess == 0)) {
-					gpio->sucI2cId.ucAccess = 0x97;
-					gpio->ucDataMaskShift = 8;
-					gpio->ucDataEnShift = 8;
-					gpio->ucDataY_Shift = 8;
-					gpio->ucDataA_Shift = 8;
-				}
-			}
-
-			/* some DCE3 boards have bad data for this entry */
-			if (ASIC_IS_DCE3(rdev)) {
-				if ((i == 4) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-				    (gpio->sucI2cId.ucAccess == 0x94))
-					gpio->sucI2cId.ucAccess = 0x14;
-			}
+			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
 			if (gpio->sucI2cId.ucAccess == id) {
-				i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-				i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-				i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-				i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-				i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-				i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-				i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-				i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-				i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-				i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-				i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-				i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-				i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-				i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-				i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-				i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-				if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-					i2c.hw_capable = true;
-				else
-					i2c.hw_capable = false;
-
-				if (gpio->sucI2cId.ucAccess == 0xa0)
-					i2c.mm_i2c = true;
-				else
-					i2c.mm_i2c = false;
-
-				i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-				if (i2c.mask_clk_reg)
-					i2c.valid = true;
+				i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 				break;
 			}
 		}
@@ -157,8 +189,6 @@ void radeon_atombios_i2c_init(struct rad
 	int i, num_indices;
 	char stmp[32];
 
-	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
-
 	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
 		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
@@ -167,60 +197,12 @@ void radeon_atombios_i2c_init(struct rad
 
 		for (i = 0; i < num_indices; i++) {
 			gpio = &i2c_info->asGPIO_Info[i];
-			i2c.valid = false;
-
-			/* some evergreen boards have bad data for this entry */
-			if (ASIC_IS_DCE4(rdev)) {
-				if ((i == 7) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-				    (gpio->sucI2cId.ucAccess == 0)) {
-					gpio->sucI2cId.ucAccess = 0x97;
-					gpio->ucDataMaskShift = 8;
-					gpio->ucDataEnShift = 8;
-					gpio->ucDataY_Shift = 8;
-					gpio->ucDataA_Shift = 8;
-				}
-			}
-
-			/* some DCE3 boards have bad data for this entry */
-			if (ASIC_IS_DCE3(rdev)) {
-				if ((i == 4) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-				    (gpio->sucI2cId.ucAccess == 0x94))
-					gpio->sucI2cId.ucAccess = 0x14;
-			}
-
-			i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-			i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-			i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-			i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-			i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-			i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-			i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-			i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-			i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-			i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-			i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-			i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-			i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-			i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-			i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-			i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
 
-			if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-				i2c.hw_capable = true;
-			else
-				i2c.hw_capable = false;
-
-			if (gpio->sucI2cId.ucAccess == 0xa0)
-				i2c.mm_i2c = true;
-			else
-				i2c.mm_i2c = false;
+			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
-			i2c.i2c_id = gpio->sucI2cId.ucAccess;
+			i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 
-			if (i2c.mask_clk_reg) {
-				i2c.valid = true;
+			if (i2c.valid) {
 				sprintf(stmp, "0x%x", i2c.i2c_id);
 				rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
 			}
@@ -228,7 +210,7 @@ void radeon_atombios_i2c_init(struct rad
 	}
 }
 
-static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
+static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
 							u8 id)
 {
 	struct atom_context *ctx = rdev->mode_info.atom_context;
@@ -1996,10 +1978,14 @@ static int radeon_atombios_parse_power_t
 		return state_index;
 	/* last mode is usually default, array is low to high */
 	for (i = 0; i < num_modes; i++) {
+		rdev->pm.power_state[state_index].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		if (!rdev->pm.power_state[state_index].clock_info)
+			return state_index;
+		rdev->pm.power_state[state_index].num_clock_modes = 1;
 		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
 		switch (frev) {
 		case 1:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2035,7 +2021,6 @@ static int radeon_atombios_parse_power_t
 			state_index++;
 			break;
 		case 2:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2072,7 +2057,6 @@ static int radeon_atombios_parse_power_t
 			state_index++;
 			break;
 		case 3:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2257,7 +2241,7 @@ static void radeon_atombios_parse_pplib_
 		rdev->pm.default_power_state_index = state_index;
 		rdev->pm.power_state[state_index].default_clock_mode =
 			&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
-		if (ASIC_IS_DCE5(rdev)) {
+		if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
 			/* NI chips post without MC ucode, so default clocks are strobe mode only */
 			rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
 			rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
@@ -2377,17 +2361,31 @@ static int radeon_atombios_parse_power_t
 			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
 			 (power_state->v1.ucNonClockStateIndex *
 			  power_info->pplib.ucNonClockSize));
-		for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
-			clock_info = (union pplib_clock_info *)
-				(mode_info->atom_context->bios + data_offset +
-				 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
-				 (power_state->v1.ucClockStateIndices[j] *
-				  power_info->pplib.ucClockInfoSize));
-			valid = radeon_atombios_parse_pplib_clock_info(rdev,
-								       state_index, mode_index,
-								       clock_info);
-			if (valid)
-				mode_index++;
+		rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+							     ((power_info->pplib.ucStateEntrySize - 1) ?
+							      (power_info->pplib.ucStateEntrySize - 1) : 1),
+							     GFP_KERNEL);
+		if (!rdev->pm.power_state[i].clock_info)
+			return state_index;
+		if (power_info->pplib.ucStateEntrySize - 1) {
+			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
+				clock_info = (union pplib_clock_info *)
+					(mode_info->atom_context->bios + data_offset +
+					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
+					 (power_state->v1.ucClockStateIndices[j] *
+					  power_info->pplib.ucClockInfoSize));
+				valid = radeon_atombios_parse_pplib_clock_info(rdev,
+									       state_index, mode_index,
+									       clock_info);
+				if (valid)
+					mode_index++;
+			}
+		} else {
+			rdev->pm.power_state[state_index].clock_info[0].mclk =
+				rdev->clock.default_mclk;
+			rdev->pm.power_state[state_index].clock_info[0].sclk =
+				rdev->clock.default_sclk;
+			mode_index++;
 		}
 		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
 		if (mode_index) {
@@ -2456,18 +2454,32 @@ static int radeon_atombios_parse_power_t
 		non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
-		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
-			clock_array_index = power_state->v2.clockInfoIndex[j];
-			/* XXX this might be an inagua bug... */
-			if (clock_array_index >= clock_info_array->ucNumEntries)
-				continue;
-			clock_info = (union pplib_clock_info *)
-				&clock_info_array->clockInfo[clock_array_index];
-			valid = radeon_atombios_parse_pplib_clock_info(rdev,
-								       state_index, mode_index,
-								       clock_info);
-			if (valid)
-				mode_index++;
+		rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+							     (power_state->v2.ucNumDPMLevels ?
+							      power_state->v2.ucNumDPMLevels : 1),
+							     GFP_KERNEL);
+		if (!rdev->pm.power_state[i].clock_info)
+			return state_index;
+		if (power_state->v2.ucNumDPMLevels) {
+			for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
+				clock_array_index = power_state->v2.clockInfoIndex[j];
+				/* XXX this might be an inagua bug... */
+				if (clock_array_index >= clock_info_array->ucNumEntries)
+					continue;
+				clock_info = (union pplib_clock_info *)
+					&clock_info_array->clockInfo[clock_array_index];
+				valid = radeon_atombios_parse_pplib_clock_info(rdev,
+									       state_index, mode_index,
+									       clock_info);
+				if (valid)
+					mode_index++;
+			}
+		} else {
+			rdev->pm.power_state[state_index].clock_info[0].mclk =
+				rdev->clock.default_mclk;
+			rdev->pm.power_state[state_index].clock_info[0].sclk =
+				rdev->clock.default_sclk;
+			mode_index++;
 		}
 		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
 		if (mode_index) {
@@ -2524,19 +2536,23 @@ void radeon_atombios_get_power_modes(str
 	} else {
 		rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
 		if (rdev->pm.power_state) {
-			/* add the default mode */
-			rdev->pm.power_state[state_index].type =
-				POWER_STATE_TYPE_DEFAULT;
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
-			rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
-			rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
-			rdev->pm.power_state[state_index].default_clock_mode =
-				&rdev->pm.power_state[state_index].clock_info[0];
-			rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
-			rdev->pm.power_state[state_index].pcie_lanes = 16;
-			rdev->pm.default_power_state_index = state_index;
-			rdev->pm.power_state[state_index].flags = 0;
-			state_index++;
+			rdev->pm.power_state[0].clock_info =
+				kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+			if (rdev->pm.power_state[0].clock_info) {
+				/* add the default mode */
+				rdev->pm.power_state[state_index].type =
+					POWER_STATE_TYPE_DEFAULT;
+				rdev->pm.power_state[state_index].num_clock_modes = 1;
+				rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+				rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+				rdev->pm.power_state[state_index].default_clock_mode =
+					&rdev->pm.power_state[state_index].clock_info[0];
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+				rdev->pm.power_state[state_index].pcie_lanes = 16;
+				rdev->pm.default_power_state_index = state_index;
+				rdev->pm.power_state[state_index].flags = 0;
+				state_index++;
+			}
 		}
 	}
 
@@ -2544,7 +2560,11 @@ void radeon_atombios_get_power_modes(str
 
 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 	rdev->pm.current_clock_mode_index = 0;
-	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.default_power_state_index >= 0)
+		rdev->pm.current_vddc =
+			rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	else
+		rdev->pm.current_vddc = 0;
 }
 
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,21 +26,81 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 
-void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
-			   unsigned sdomain, unsigned ddomain)
+#define RADEON_BENCHMARK_COPY_BLIT 1
+#define RADEON_BENCHMARK_COPY_DMA  0
+
+#define RADEON_BENCHMARK_ITERATIONS 1024
+#define RADEON_BENCHMARK_COMMON_MODES_N 17
+
+static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size,
+				    uint64_t saddr, uint64_t daddr,
+				    int flag, int n)
+{
+	unsigned long start_jiffies;
+	unsigned long end_jiffies;
+	struct radeon_fence *fence = NULL;
+	int i, r;
+
+	start_jiffies = jiffies;
+	for (i = 0; i < n; i++) {
+		r = radeon_fence_create(rdev, &fence);
+		if (r)
+			return r;
+
+		switch (flag) {
+		case RADEON_BENCHMARK_COPY_DMA:
+			r = radeon_copy_dma(rdev, saddr, daddr,
+					    size / RADEON_GPU_PAGE_SIZE,
+					    fence);
+			break;
+		case RADEON_BENCHMARK_COPY_BLIT:
+			r = radeon_copy_blit(rdev, saddr, daddr,
+					     size / RADEON_GPU_PAGE_SIZE,
+					     fence);
+			break;
+		default:
+			DRM_ERROR("Unknown copy method\n");
+			r = -EINVAL;
+		}
+		if (r)
+			goto exit_do_move;
+		r = radeon_fence_wait(fence, false);
+		if (r)
+			goto exit_do_move;
+		radeon_fence_unref(&fence);
+	}
+	end_jiffies = jiffies;
+	r = jiffies_to_msecs(end_jiffies - start_jiffies);
+
+exit_do_move:
+	if (fence)
+		radeon_fence_unref(&fence);
+	return r;
+}
+
+
+static void radeon_benchmark_log_results(int n, unsigned size,
+					 unsigned int time,
+					 unsigned sdomain, unsigned ddomain,
+					 char *kind)
+{
+	unsigned int throughput = (n * (size >> 10)) / time;
+	DRM_INFO("radeon: %s %u bo moves of %u kB from"
+		 " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n",
+		 kind, n, size >> 10, sdomain, ddomain, time,
+		 throughput * 8, throughput);
+}
+
+static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
+				  unsigned sdomain, unsigned ddomain)
 {
 	struct radeon_bo *dobj = NULL;
 	struct radeon_bo *sobj = NULL;
-	struct radeon_fence *fence = NULL;
 	uint64_t saddr, daddr;
-	unsigned long start_jiffies;
-	unsigned long end_jiffies;
-	unsigned long time;
-	unsigned i, n, size;
-	int r;
+	int r, n;
+	int time;
 
-	size = bsize;
-	n = 1024;
+	n = RADEON_BENCHMARK_ITERATIONS;
 	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
 	if (r) {
 		goto out_cleanup;
@@ -67,65 +127,26 @@ void radeon_benchmark_move(struct radeon
 	}
 
 	/* r100 doesn't have dma engine so skip the test */
-	if (rdev->asic->copy_dma) {
-
-		start_jiffies = jiffies;
-		for (i = 0; i < n; i++) {
-			r = radeon_fence_create(rdev, &fence);
-			if (r) {
-				goto out_cleanup;
-			}
-
-			r = radeon_copy_dma(rdev, saddr, daddr,
-					size / RADEON_GPU_PAGE_SIZE, fence);
-
-			if (r) {
-				goto out_cleanup;
-			}
-			r = radeon_fence_wait(fence, false);
-			if (r) {
-				goto out_cleanup;
-			}
-			radeon_fence_unref(&fence);
-		}
-		end_jiffies = jiffies;
-		time = end_jiffies - start_jiffies;
-		time = jiffies_to_msecs(time);
-		if (time > 0) {
-			i = ((n * size) >> 10) / time;
-			printk(KERN_INFO "radeon: dma %u bo moves of %ukb from"
-					" %d to %d in %lums (%ukb/ms %ukb/s %uM/s)\n",
-					n, size >> 10,
-					sdomain, ddomain, time,
-					i, i * 1000, (i * 1000) / 1024);
-		}
-	}
-
-	start_jiffies = jiffies;
-	for (i = 0; i < n; i++) {
-		r = radeon_fence_create(rdev, &fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_copy_blit(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_fence_wait(fence, false);
-		if (r) {
+	/* also, VRAM-to-VRAM test doesn't make much sense for DMA */
+	/* skip it as well if domains are the same */
+	if ((rdev->asic->copy_dma) && (sdomain != ddomain)) {
+		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+						RADEON_BENCHMARK_COPY_DMA, n);
+		if (time < 0)
 			goto out_cleanup;
-		}
-		radeon_fence_unref(&fence);
-	}
-	end_jiffies = jiffies;
-	time = end_jiffies - start_jiffies;
-	time = jiffies_to_msecs(time);
-	if (time > 0) {
-		i = ((n * size) >> 10) / time;
-		printk(KERN_INFO "radeon: blit %u bo moves of %ukb from %d to %d"
-		       " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
-		       sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
+		if (time > 0)
+			radeon_benchmark_log_results(n, size, time,
+						     sdomain, ddomain, "dma");
 	}
+
+	time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+					RADEON_BENCHMARK_COPY_BLIT, n);
+	if (time < 0)
+		goto out_cleanup;
+	if (time > 0)
+		radeon_benchmark_log_results(n, size, time,
+					     sdomain, ddomain, "blit");
+
 out_cleanup:
 	if (sobj) {
 		r = radeon_bo_reserve(sobj, false);
@@ -143,18 +164,92 @@ out_cleanup:
 		}
 		radeon_bo_unref(&dobj);
 	}
-	if (fence) {
-		radeon_fence_unref(&fence);
-	}
+
 	if (r) {
-		printk(KERN_WARNING "Error while benchmarking BO move.\n");
+		DRM_ERROR("Error while benchmarking BO move.\n");
 	}
 }
 
-void radeon_benchmark(struct radeon_device *rdev)
+void radeon_benchmark(struct radeon_device *rdev, int test_number)
 {
-	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
-			      RADEON_GEM_DOMAIN_VRAM);
-	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
-			      RADEON_GEM_DOMAIN_GTT);
+	int i;
+	int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = {
+		640 * 480 * 4,
+		720 * 480 * 4,
+		800 * 600 * 4,
+		848 * 480 * 4,
+		1024 * 768 * 4,
+		1152 * 768 * 4,
+		1280 * 720 * 4,
+		1280 * 800 * 4,
+		1280 * 854 * 4,
+		1280 * 960 * 4,
+		1280 * 1024 * 4,
+		1440 * 900 * 4,
+		1400 * 1050 * 4,
+		1680 * 1050 * 4,
+		1600 * 1200 * 4,
+		1920 * 1080 * 4,
+		1920 * 1200 * 4
+	};
+
+	switch (test_number) {
+	case 1:
+		/* simple test, VRAM to GTT and GTT to VRAM */
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
+				      RADEON_GEM_DOMAIN_VRAM);
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+				      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 2:
+		/* simple test, VRAM to VRAM */
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+				      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 3:
+		/* GTT to VRAM, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_GTT,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 4:
+		/* VRAM to GTT, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 5:
+		/* VRAM to VRAM, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 6:
+		/* GTT to VRAM, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_GTT,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 7:
+		/* VRAM to GTT, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 8:
+		/* VRAM to VRAM, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+
+	default:
+		DRM_ERROR("Unknown benchmark\n");
+	}
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2012-01-04 18:55:44.000000000 -0500
@@ -620,8 +620,8 @@ static struct radeon_i2c_bus_rec combios
 		i2c.y_data_mask = 0x80;
 	} else {
 		/* default masks for ddc pads */
-		i2c.mask_clk_mask = RADEON_GPIO_EN_1;
-		i2c.mask_data_mask = RADEON_GPIO_EN_0;
+		i2c.mask_clk_mask = RADEON_GPIO_MASK_1;
+		i2c.mask_data_mask = RADEON_GPIO_MASK_0;
 		i2c.a_clk_mask = RADEON_GPIO_A_1;
 		i2c.a_data_mask = RADEON_GPIO_A_0;
 		i2c.en_clk_mask = RADEON_GPIO_EN_1;
@@ -2563,14 +2563,17 @@ void radeon_combios_get_power_modes(stru
 
 	/* allocate 2 power states */
 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
-	if (!rdev->pm.power_state) {
-		rdev->pm.default_power_state_index = state_index;
-		rdev->pm.num_power_states = 0;
-
-		rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
-		rdev->pm.current_clock_mode_index = 0;
-		return;
-	}
+	if (rdev->pm.power_state) {
+		/* allocate 1 clock mode per state */
+		rdev->pm.power_state[0].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		rdev->pm.power_state[1].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		if (!rdev->pm.power_state[0].clock_info ||
+		    !rdev->pm.power_state[1].clock_info)
+			goto pm_failed;
+	} else
+		goto pm_failed;
 
 	/* check for a thermal chip */
 	offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
@@ -2735,6 +2738,14 @@ default_mode:
 
 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 	rdev->pm.current_clock_mode_index = 0;
+	return;
+
+pm_failed:
+	rdev->pm.default_power_state_index = state_index;
+	rdev->pm.num_power_states = 0;
+
+	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+	rdev->pm.current_clock_mode_index = 0;
 }
 
 void radeon_external_tmds_setup(struct drm_encoder *encoder)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,8 +44,6 @@ extern void
 radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
 			     struct drm_connector *drm_connector);
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
-
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -432,55 +430,6 @@ int radeon_connector_set_property(struct
 	return 0;
 }
 
-/*
- * Some integrated ATI Radeon chipset implementations (e. g.
- * Asus M2A-VM HDMI) may indicate the availability of a DDC,
- * even when there's no monitor connected. For these connectors
- * following DDC probe extension will be applied: check also for the
- * availability of EDID with at least a correct EDID header. Only then,
- * DDC is assumed to be available. This prevents drm_get_edid() and
- * drm_edid_block_valid() from periodically dumping data and kernel
- * errors into the logs and onto the terminal.
- */
-static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
-				     uint32_t supported_device,
-				     int connector_type)
-{
-	/* Asus M2A-VM HDMI board sends data to i2c bus even,
-	 * if HDMI add-on card is not plugged in or HDMI is disabled in
-	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
-	 * can be retrieved via i2c bus during DDC probe */
-	if ((dev->pdev->device == 0x791e) &&
-	    (dev->pdev->subsystem_vendor == 0x1043) &&
-	    (dev->pdev->subsystem_device == 0x826d)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-	/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
-	 * for a DVI connector that is not implemented */
-	if ((dev->pdev->device == 0x796e) &&
-	    (dev->pdev->subsystem_vendor == 0x1019) &&
-	    (dev->pdev->subsystem_device == 0x2615)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-	/* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
-	 * (RS690M) sends data to i2c bus for a HDMI connector that
-	 * is not implemented */
-	if ((dev->pdev->device == 0x791f) &&
-	    (dev->pdev->subsystem_vendor == 0x1179) &&
-	    (dev->pdev->subsystem_device == 0xff68)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-
-	/* Default: no EDID header probe required for DDC probing */
-	return false;
-}
-
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -721,9 +670,9 @@ radeon_vga_detect(struct drm_connector *
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector,
-					radeon_connector->requires_extended_probe);
+		dret = radeon_ddc_probe(radeon_connector);
 	if (dret) {
+		radeon_connector->detected_by_load = false;
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
@@ -750,12 +699,21 @@ radeon_vga_detect(struct drm_connector *
 	} else {
 
 		/* if we aren't forcing don't do destructive polling */
-		if (!force)
-			return connector->status;
+		if (!force) {
+			/* only return the previous status if we last
+			 * detected a monitor via load.
+			 */
+			if (radeon_connector->detected_by_load)
+				return connector->status;
+			else
+				return ret;
+		}
 
 		if (radeon_connector->dac_load_detect && encoder) {
 			encoder_funcs = encoder->helper_private;
 			ret = encoder_funcs->detect(encoder, connector);
+			if (ret != connector_status_disconnected)
+				radeon_connector->detected_by_load = true;
 		}
 	}
 
@@ -894,9 +852,9 @@ radeon_dvi_detect(struct drm_connector *
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector,
-					radeon_connector->requires_extended_probe);
+		dret = radeon_ddc_probe(radeon_connector);
 	if (dret) {
+		radeon_connector->detected_by_load = false;
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
@@ -959,8 +917,18 @@ radeon_dvi_detect(struct drm_connector *
 	if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
 		goto out;
 
+	/* DVI-D and HDMI-A are digital only */
+	if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
+	    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
+		goto out;
+
+	/* if we aren't forcing don't do destructive polling */
 	if (!force) {
-		ret = connector->status;
+		/* only return the previous status if we last
+		 * detected a monitor via load.
+		 */
+		if (radeon_connector->detected_by_load)
+			ret = connector->status;
 		goto out;
 	}
 
@@ -985,6 +953,8 @@ radeon_dvi_detect(struct drm_connector *
 					if (ret == connector_status_connected) {
 						radeon_connector->use_digital = false;
 					}
+					if (ret != connector_status_disconnected)
+						radeon_connector->detected_by_load = true;
 				}
 				break;
 			}
@@ -1181,7 +1151,8 @@ static int radeon_dp_get_modes(struct dr
 		}
 	} else {
 		/* need to setup ddc on the bridge */
-		if (radeon_connector_encoder_is_dp_bridge(connector)) {
+		if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+			ENCODER_OBJECT_ID_NONE) {
 			if (encoder)
 				radeon_atom_ext_encoder_setup_ddc(encoder);
 		}
@@ -1191,13 +1162,12 @@ static int radeon_dp_get_modes(struct dr
 	return ret;
 }
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
+u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
 {
 	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	struct radeon_encoder *radeon_encoder;
 	int i;
-	bool found = false;
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 		if (connector->encoder_ids[i] == 0)
@@ -1213,14 +1183,13 @@ bool radeon_connector_encoder_is_dp_brid
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_TRAVIS:
 		case ENCODER_OBJECT_ID_NUTMEG:
-			found = true;
-			break;
+			return radeon_encoder->encoder_id;
 		default:
 			break;
 		}
 	}
 
-	return found;
+	return ENCODER_OBJECT_ID_NONE;
 }
 
 bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
@@ -1297,7 +1266,8 @@ radeon_dp_detect(struct drm_connector *c
 		if (!radeon_dig_connector->edp_on)
 			atombios_set_edp_panel_power(connector,
 						     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-	} else if (radeon_connector_encoder_is_dp_bridge(connector)) {
+	} else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+		   ENCODER_OBJECT_ID_NONE) {
 		/* DP bridges are always DP */
 		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
 		/* get the DPCD from the bridge */
@@ -1306,8 +1276,7 @@ radeon_dp_detect(struct drm_connector *c
 		if (encoder) {
 			/* setup ddc on the bridge */
 			radeon_atom_ext_encoder_setup_ddc(encoder);
-			if (radeon_ddc_probe(radeon_connector,
-					     radeon_connector->requires_extended_probe)) /* try DDC */
+			if (radeon_ddc_probe(radeon_connector)) /* try DDC */
 				ret = connector_status_connected;
 			else if (radeon_connector->dac_load_detect) { /* try load detection */
 				struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -1325,8 +1294,7 @@ radeon_dp_detect(struct drm_connector *c
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector,
-						     radeon_connector->requires_extended_probe))
+				if (radeon_ddc_probe(radeon_connector))
 					ret = connector_status_connected;
 			}
 		}
@@ -1471,9 +1439,7 @@ radeon_add_atom_connector(struct drm_dev
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
-	radeon_connector->requires_extended_probe =
-		radeon_connector_needs_extended_probe(rdev, supported_device,
-							connector_type);
+
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1820,9 +1786,7 @@ radeon_add_legacy_connector(struct drm_d
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
-	radeon_connector->requires_extended_probe =
-		radeon_connector_needs_extended_probe(rdev, supported_device,
-							connector_type);
+
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_cp.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_cp.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_cp.c	2013-05-02 01:33:28.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_cp.c	2013-05-01 23:41:30.000000000 -0400
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "drm_sarea.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ int radeon_cs_parser_init(struct radeon_
 {
 	struct drm_radeon_cs *cs = data;
 	uint64_t *chunk_array_ptr;
-	unsigned size, i;
+	unsigned size, i, flags = 0;
 
 	if (!cs->num_chunks) {
 		return 0;
@@ -140,6 +140,10 @@ int radeon_cs_parser_init(struct radeon_
 			if (p->chunks[i].length_dw == 0)
 				return -EINVAL;
 		}
+		if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS &&
+		    !p->chunks[i].length_dw) {
+			return -EINVAL;
+		}
 
 		p->chunks[i].length_dw = user_chunk.length_dw;
 		p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
@@ -155,6 +159,9 @@ int radeon_cs_parser_init(struct radeon_
 					       p->chunks[i].user_ptr, size)) {
 				return -EFAULT;
 			}
+			if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
+				flags = p->chunks[i].kdata[0];
+			}
 		} else {
 			p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
 			p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -174,6 +181,8 @@ int radeon_cs_parser_init(struct radeon_
 			  p->chunks[p->chunk_ib_idx].length_dw);
 		return -EINVAL;
 	}
+
+	p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0;
 	return 0;
 }
 
@@ -222,7 +231,7 @@ int radeon_cs_ioctl(struct drm_device *d
 	struct radeon_cs_chunk *ib_chunk;
 	int r;
 
-	mutex_lock(&rdev->cs_mutex);
+	radeon_mutex_lock(&rdev->cs_mutex);
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
@@ -233,14 +242,14 @@ int radeon_cs_ioctl(struct drm_device *d
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r =  radeon_ib_get(rdev, &parser.ib);
 	if (r) {
 		DRM_ERROR("Failed to get ib !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_cs_parser_relocs(&parser);
@@ -248,7 +257,7 @@ int radeon_cs_ioctl(struct drm_device *d
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to parse relocation %d!\n", r);
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	/* Copy the packet into the IB, the parser will read from the
@@ -260,14 +269,14 @@ int radeon_cs_ioctl(struct drm_device *d
 	if (r || parser.parser_error) {
 		DRM_ERROR("Invalid command stream !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_cs_finish_pages(&parser);
 	if (r) {
 		DRM_ERROR("Invalid command stream !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_ib_schedule(rdev, parser.ib);
@@ -275,7 +284,7 @@ int radeon_cs_ioctl(struct drm_device *d
 		DRM_ERROR("Failed to schedule IB !\n");
 	}
 	radeon_cs_parser_fini(&parser, r);
-	mutex_unlock(&rdev->cs_mutex);
+	radeon_mutex_unlock(&rdev->cs_mutex);
 	return r;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_device.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -716,7 +716,7 @@ int radeon_device_init(struct radeon_dev
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
-	mutex_init(&rdev->cs_mutex);
+	radeon_mutex_init(&rdev->cs_mutex);
 	mutex_init(&rdev->ib_pool.mutex);
 	mutex_init(&rdev->cp.mutex);
 	mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -750,14 +750,15 @@ int radeon_device_init(struct radeon_dev
 
 	/* set DMA mask + need_dma32 flags.
 	 * PCIE - can handle 40-bits.
-	 * IGP - can handle 40-bits (in theory)
+	 * IGP - can handle 40-bits
 	 * AGP - generally dma32 is safest
-	 * PCI - only dma32
+	 * PCI - dma32 for legacy pci gart, 40 bits on newer asics
 	 */
 	rdev->need_dma32 = false;
 	if (rdev->flags & RADEON_IS_AGP)
 		rdev->need_dma32 = true;
-	if (rdev->flags & RADEON_IS_PCI)
+	if ((rdev->flags & RADEON_IS_PCI) &&
+	    (rdev->family < CHIP_RS400))
 		rdev->need_dma32 = true;
 
 	dma_bits = rdev->need_dma32 ? 32 : 40;
@@ -817,7 +818,7 @@ int radeon_device_init(struct radeon_dev
 		radeon_test_moves(rdev);
 	}
 	if (radeon_benchmarking) {
-		radeon_benchmark(rdev);
+		radeon_benchmark(rdev, radeon_benchmarking);
 	}
 	return 0;
 }
@@ -954,6 +955,9 @@ int radeon_gpu_reset(struct radeon_devic
 	int r;
 	int resched;
 
+	/* Prevent CS ioctl from interfering */
+	radeon_mutex_lock(&rdev->cs_mutex);
+
 	radeon_save_bios_scratch_regs(rdev);
 	/* block TTM */
 	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -966,10 +970,15 @@ int radeon_gpu_reset(struct radeon_devic
 		radeon_restore_bios_scratch_regs(rdev);
 		drm_helper_resume_force_mode(rdev->ddev);
 		ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-		return 0;
 	}
-	/* bad news, how to tell it to userspace ? */
-	dev_info(rdev->dev, "GPU reset failed\n");
+
+	radeon_mutex_unlock(&rdev->cs_mutex);
+
+	if (r) {
+		/* bad news, how to tell it to userspace ? */
+		dev_info(rdev->dev, "GPU reset failed\n");
+	}
+
 	return r;
 }
 
@@ -981,7 +990,7 @@ struct radeon_debugfs {
 	struct drm_info_list	*files;
 	unsigned		num_files;
 };
-static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES];
+static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
 static unsigned _radeon_debugfs_count = 0;
 
 int radeon_debugfs_add_files(struct radeon_device *rdev,
@@ -996,14 +1005,17 @@ int radeon_debugfs_add_files(struct rade
 			return 0;
 		}
 	}
-	if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) {
-		DRM_ERROR("Reached maximum number of debugfs files.\n");
-		DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n");
+
+	i = _radeon_debugfs_count + 1;
+	if (i > RADEON_DEBUGFS_MAX_COMPONENTS) {
+		DRM_ERROR("Reached maximum number of debugfs components.\n");
+		DRM_ERROR("Report so we increase "
+		          "RADEON_DEBUGFS_MAX_COMPONENTS.\n");
 		return -EINVAL;
 	}
 	_radeon_debugfs[_radeon_debugfs_count].files = files;
 	_radeon_debugfs[_radeon_debugfs_count].num_files = nfiles;
-	_radeon_debugfs_count++;
+	_radeon_debugfs_count = i;
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
 				 rdev->ddev->control->debugfs_root,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_display.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,6 @@
 #include "drm_crtc_helper.h"
 #include "drm_edid.h"
 
-static int radeon_ddc_dump(struct drm_connector *connector);
-
 static void avivo_crtc_load_lut(struct drm_crtc *crtc)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -669,7 +667,6 @@ static void radeon_print_display_setup(s
 static bool radeon_setup_enc_conn(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
-	struct drm_connector *drm_connector;
 	bool ret = false;
 
 	if (rdev->bios) {
@@ -689,8 +686,6 @@ static bool radeon_setup_enc_conn(struct
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
-		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
-			radeon_ddc_dump(drm_connector);
 	}
 
 	return ret;
@@ -708,7 +703,8 @@ int radeon_ddc_get_modes(struct radeon_c
 
 	if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
 	    (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
-	    radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) {
+	    (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
+	     ENCODER_OBJECT_ID_NONE)) {
 		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
 
 		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
@@ -743,34 +739,6 @@ int radeon_ddc_get_modes(struct radeon_c
 	return 0;
 }
 
-static int radeon_ddc_dump(struct drm_connector *connector)
-{
-	struct edid *edid;
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	int ret = 0;
-
-	/* on hw with routers, select right port */
-	if (radeon_connector->router.ddc_valid)
-		radeon_router_select_ddc_port(radeon_connector);
-
-	if (!radeon_connector->ddc_bus)
-		return -1;
-	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
-	/* Log EDID retrieval status here. In particular with regard to
-	 * connectors with requires_extended_probe flag set, that will prevent
-	 * function radeon_dvi_detect() to fetch EDID on this connector,
-	 * as long as there is no valid EDID header found */
-	if (edid) {
-		DRM_INFO("Radeon display connector %s: Found valid EDID",
-				drm_get_connector_name(connector));
-		kfree(edid);
-	} else {
-		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
-				drm_get_connector_name(connector));
-	}
-	return ret;
-}
-
 /* avivo */
 static void avivo_get_fb_div(struct radeon_pll *pll,
 			     u32 target_clock,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include "drm_pciids.h"
 #include <linux/console.h>
+#include <linux/module.h>
 
 
 /*
@@ -52,9 +53,10 @@
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  *   2.10.0 - fusion 2D tiling
  *   2.11.0 - backend map, initial compute support for the CS checker
+ *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	11
+#define KMS_DRIVER_MINOR	12
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -118,6 +120,7 @@ int radeon_audio = 0;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
+int radeon_msi = -1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -164,6 +167,9 @@ module_param_named(hw_i2c, radeon_hw_i2c
 MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
 module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 
+MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(msi, radeon_msi, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,12 +29,6 @@
 #include "radeon.h"
 #include "atom.h"
 
-extern int atom_debug;
-
-/* evil but including atombios.h is much worse */
-bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
-				struct drm_display_mode *mode);
-
 static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
@@ -156,27 +150,6 @@ radeon_get_encoder_enum(struct drm_devic
 	return ret;
 }
 
-static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		return true;
-	default:
-		return false;
-	}
-}
-
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
@@ -229,23 +202,7 @@ radeon_get_connector_for_encoder(struct
 	return NULL;
 }
 
-static struct drm_connector *
-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		radeon_connector = to_radeon_connector(connector);
-		if (radeon_encoder->devices & radeon_connector->devices)
-			return connector;
-	}
-	return NULL;
-}
-
-struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
+struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -266,9 +223,9 @@ struct drm_encoder *radeon_atom_get_exte
 	return NULL;
 }
 
-bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder)
+u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
 {
-	struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
+	struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder);
 
 	if (other_encoder) {
 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
@@ -276,13 +233,12 @@ bool radeon_encoder_is_dp_bridge(struct
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_TRAVIS:
 		case ENCODER_OBJECT_ID_NUTMEG:
-			return true;
+			return radeon_encoder->encoder_id;
 		default:
-			return false;
+			return ENCODER_OBJECT_ID_NONE;
 		}
 	}
-
-	return false;
+	return ENCODER_OBJECT_ID_NONE;
 }
 
 void radeon_panel_mode_fixup(struct drm_encoder *encoder,
@@ -332,2105 +288,3 @@ void radeon_panel_mode_fixup(struct drm_
 
 }
 
-static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
-				   struct drm_display_mode *mode,
-				   struct drm_display_mode *adjusted_mode)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* set the active encoder to connector routing */
-	radeon_encoder_set_active_device(encoder);
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	/* hw bug */
-	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
-	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
-		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
-
-	/* get the native mode for LVDS */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
-		radeon_panel_mode_fixup(encoder, adjusted_mode);
-
-	/* get the native mode for TV */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
-		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
-		if (tv_dac) {
-			if (tv_dac->tv_std == TV_STD_NTSC ||
-			    tv_dac->tv_std == TV_STD_NTSC_J ||
-			    tv_dac->tv_std == TV_STD_PAL_M)
-				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
-			else
-				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
-		}
-	}
-
-	if (ASIC_IS_DCE3(rdev) &&
-	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-	     radeon_encoder_is_dp_bridge(encoder))) {
-		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-		radeon_dp_set_link_config(connector, mode);
-	}
-
-	return true;
-}
-
-static void
-atombios_dac_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
-		break;
-	}
-
-	args.ucAction = action;
-
-	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
-		args.ucDacStandard = ATOM_DAC1_PS2;
-	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		args.ucDacStandard = ATOM_DAC1_CV;
-	else {
-		switch (dac_info->tv_std) {
-		case TV_STD_PAL:
-		case TV_STD_PAL_M:
-		case TV_STD_SCART_PAL:
-		case TV_STD_SECAM:
-		case TV_STD_PAL_CN:
-			args.ucDacStandard = ATOM_DAC1_PAL;
-			break;
-		case TV_STD_NTSC:
-		case TV_STD_NTSC_J:
-		case TV_STD_PAL_60:
-		default:
-			args.ucDacStandard = ATOM_DAC1_NTSC;
-			break;
-		}
-	}
-	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-static void
-atombios_tv_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	TV_ENCODER_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-	memset(&args, 0, sizeof(args));
-
-	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
-
-	args.sTVEncoder.ucAction = action;
-
-	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
-	else {
-		switch (dac_info->tv_std) {
-		case TV_STD_NTSC:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-			break;
-		case TV_STD_PAL:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
-			break;
-		case TV_STD_PAL_M:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
-			break;
-		case TV_STD_PAL_60:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
-			break;
-		case TV_STD_NTSC_J:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
-			break;
-		case TV_STD_SCART_PAL:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
-			break;
-		case TV_STD_SECAM:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
-			break;
-		case TV_STD_PAL_CN:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
-			break;
-		default:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-			break;
-		}
-	}
-
-	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dvo_encoder_control {
-	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
-	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
-	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
-};
-
-void
-atombios_dvo_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	union dvo_encoder_control args;
-	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
-
-	memset(&args, 0, sizeof(args));
-
-	if (ASIC_IS_DCE3(rdev)) {
-		/* DCE3+ */
-		args.dvo_v3.ucAction = action;
-		args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-		args.dvo_v3.ucDVOConfig = 0; /* XXX */
-	} else if (ASIC_IS_DCE2(rdev)) {
-		/* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
-		args.dvo.sDVOEncoder.ucAction = action;
-		args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-		/* DFP1, CRT1, TV1 depending on the type of port */
-		args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
-
-		if (radeon_encoder->pixel_clock > 165000)
-			args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
-	} else {
-		/* R4xx, R5xx */
-		args.ext_tmds.sXTmdsEncoder.ucEnable = action;
-
-		if (radeon_encoder->pixel_clock > 165000)
-			args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-
-		/*if (pScrn->rgbBits == 8)*/
-		args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-union lvds_encoder_control {
-	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
-	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
-};
-
-void
-atombios_digital_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	union lvds_encoder_control args;
-	int index = 0;
-	int hdmi_detected = 0;
-	uint8_t frev, crev;
-
-	if (!dig)
-		return;
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-		hdmi_detected = 1;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
-		break;
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-	case 2:
-		switch (crev) {
-		case 1:
-			args.v1.ucMisc = 0;
-			args.v1.ucAction = action;
-			if (hdmi_detected)
-				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-			} else {
-				if (dig->linkb)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-				if (radeon_encoder->pixel_clock > 165000)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				/*if (pScrn->rgbBits == 8) */
-				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-			}
-			break;
-		case 2:
-		case 3:
-			args.v2.ucMisc = 0;
-			args.v2.ucAction = action;
-			if (crev == 3) {
-				if (dig->coherent_mode)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
-			}
-			if (hdmi_detected)
-				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v2.ucTruncate = 0;
-			args.v2.ucSpatial = 0;
-			args.v2.ucTemporal = 0;
-			args.v2.ucFRC = 0;
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
-					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
-					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
-				}
-				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
-					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
-					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
-					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
-						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
-				}
-			} else {
-				if (dig->linkb)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-				if (radeon_encoder->pixel_clock > 165000)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-			}
-			break;
-		default:
-			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-			break;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-		break;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-int
-atombios_get_encoder_mode(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *dig_connector;
-
-	/* dp bridges are always DP */
-	if (radeon_encoder_is_dp_bridge(encoder))
-		return ATOM_ENCODER_MODE_DP;
-
-	/* DVO is always DVO */
-	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
-		return ATOM_ENCODER_MODE_DVO;
-
-	connector = radeon_get_connector_for_encoder(encoder);
-	/* if we don't have an active device yet, just use one of
-	 * the connectors tied to the encoder.
-	 */
-	if (!connector)
-		connector = radeon_get_connector_for_encoder_init(encoder);
-	radeon_connector = to_radeon_connector(connector);
-
-	switch (connector->connector_type) {
-	case DRM_MODE_CONNECTOR_DVII:
-	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else if (radeon_connector->use_digital)
-			return ATOM_ENCODER_MODE_DVI;
-		else
-			return ATOM_ENCODER_MODE_CRT;
-		break;
-	case DRM_MODE_CONNECTOR_DVID:
-	case DRM_MODE_CONNECTOR_HDMIA:
-	default:
-		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else
-			return ATOM_ENCODER_MODE_DVI;
-		break;
-	case DRM_MODE_CONNECTOR_LVDS:
-		return ATOM_ENCODER_MODE_LVDS;
-		break;
-	case DRM_MODE_CONNECTOR_DisplayPort:
-		dig_connector = radeon_connector->con_priv;
-		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
-			return ATOM_ENCODER_MODE_DP;
-		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else
-			return ATOM_ENCODER_MODE_DVI;
-		break;
-	case DRM_MODE_CONNECTOR_eDP:
-		return ATOM_ENCODER_MODE_DP;
-	case DRM_MODE_CONNECTOR_DVIA:
-	case DRM_MODE_CONNECTOR_VGA:
-		return ATOM_ENCODER_MODE_CRT;
-		break;
-	case DRM_MODE_CONNECTOR_Composite:
-	case DRM_MODE_CONNECTOR_SVIDEO:
-	case DRM_MODE_CONNECTOR_9PinDIN:
-		/* fix me */
-		return ATOM_ENCODER_MODE_TV;
-		/*return ATOM_ENCODER_MODE_CV;*/
-		break;
-	}
-}
-
-/*
- * DIG Encoder/Transmitter Setup
- *
- * DCE 3.0/3.1
- * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
- * Supports up to 3 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1 can drive UNIPHY link A or link B
- * DIG2 can drive UNIPHY link B or LVTMA
- *
- * DCE 3.2
- * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
- * Supports up to 5 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * DCE 4.0/5.0
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 6 DIG encoder blocks.
- * - DIG to PHY mapping is hardcoded
- * DIG1 drives UNIPHY0 link A, A+B
- * DIG2 drives UNIPHY0 link B
- * DIG3 drives UNIPHY1 link A, A+B
- * DIG4 drives UNIPHY1 link B
- * DIG5 drives UNIPHY2 link A, A+B
- * DIG6 drives UNIPHY2 link B
- *
- * DCE 4.1
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * Routing
- * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
- * Examples:
- * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
- * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
- * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
- * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
- */
-
-union dig_encoder_control {
-	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
-	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
-	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
-	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-	union dig_encoder_control args;
-	int index = 0;
-	uint8_t frev, crev;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int hpd_id = RADEON_HPD_NONE;
-	int bpc = 8;
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		hpd_id = radeon_connector->hpd.hpd;
-		bpc = connector->display_info.bpc;
-	}
-
-	/* no dig encoder assigned */
-	if (dig->dig_encoder == -1)
-		return;
-
-	memset(&args, 0, sizeof(args));
-
-	if (ASIC_IS_DCE4(rdev))
-		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
-	else {
-		if (dig->dig_encoder)
-			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	args.v1.ucAction = action;
-	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-	if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
-		args.v3.ucPanelMode = panel_mode;
-	else
-		args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-	if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-	    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST))
-		args.v1.ucLaneNum = dp_lane_count;
-	else if (radeon_encoder->pixel_clock > 165000)
-		args.v1.ucLaneNum = 8;
-	else
-		args.v1.ucLaneNum = 4;
-
-	if (ASIC_IS_DCE5(rdev)) {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-		    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) {
-			if (dp_clock == 270000)
-				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
-			else if (dp_clock == 540000)
-				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
-		}
-		args.v4.acConfig.ucDigSel = dig->dig_encoder;
-		switch (bpc) {
-		case 0:
-			args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
-			break;
-		case 6:
-			args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-			break;
-		case 8:
-		default:
-			args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-			break;
-		case 10:
-			args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-			break;
-		case 12:
-			args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-			break;
-		case 16:
-			args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-			break;
-		}
-		if (hpd_id == RADEON_HPD_NONE)
-			args.v4.ucHPD_ID = 0;
-		else
-			args.v4.ucHPD_ID = hpd_id + 1;
-	} else if (ASIC_IS_DCE4(rdev)) {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-		args.v3.acConfig.ucDigSel = dig->dig_encoder;
-		switch (bpc) {
-		case 0:
-			args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
-			break;
-		case 6:
-			args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-			break;
-		case 8:
-		default:
-			args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-			break;
-		case 10:
-			args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-			break;
-		case 12:
-			args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-			break;
-		case 16:
-			args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-			break;
-		}
-	} else {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
-			break;
-		}
-		if (dig->linkb)
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-		else
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dig_transmitter_control {
-	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	union dig_transmitter_control args;
-	int index = 0;
-	uint8_t frev, crev;
-	bool is_dp = false;
-	int pll_id = 0;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int connector_object_id = 0;
-	int igp_lane_info = 0;
-	int dig_encoder = dig->dig_encoder;
-
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-		connector = radeon_get_connector_for_encoder_init(encoder);
-		/* just needed to avoid bailing in the encoder check.  the encoder
-		 * isn't used for init
-		 */
-		dig_encoder = 0;
-	} else
-		connector = radeon_get_connector_for_encoder(encoder);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		connector_object_id =
-			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-		igp_lane_info = dig_connector->igp_lane_info;
-	}
-
-	/* no dig encoder assigned */
-	if (dig_encoder == -1)
-		return;
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
-		is_dp = true;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
-		break;
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	args.v1.ucAction = action;
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-		args.v1.usInitInfo = cpu_to_le16(connector_object_id);
-	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-		args.v1.asMode.ucLaneSel = lane_num;
-		args.v1.asMode.ucLaneSet = lane_set;
-	} else {
-		if (is_dp)
-			args.v1.usPixelClock =
-				cpu_to_le16(dp_clock / 10);
-		else if (radeon_encoder->pixel_clock > 165000)
-			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-		else
-			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-	}
-	if (ASIC_IS_DCE4(rdev)) {
-		if (is_dp)
-			args.v3.ucLaneNum = dp_lane_count;
-		else if (radeon_encoder->pixel_clock > 165000)
-			args.v3.ucLaneNum = 8;
-		else
-			args.v3.ucLaneNum = 4;
-
-		if (dig->linkb)
-			args.v3.acConfig.ucLinkSel = 1;
-		if (dig_encoder & 1)
-			args.v3.acConfig.ucEncoderSel = 1;
-
-		/* Select the PLL for the PHY
-		 * DP PHY should be clocked from external src if there is
-		 * one.
-		 */
-		if (encoder->crtc) {
-			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-			pll_id = radeon_crtc->pll_id;
-		}
-
-		if (ASIC_IS_DCE5(rdev)) {
-			/* On DCE5 DCPLL usually generates the DP ref clock */
-			if (is_dp) {
-				if (rdev->clock.dp_extclk)
-					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
-				else
-					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
-			} else
-				args.v4.acConfig.ucRefClkSource = pll_id;
-		} else {
-			/* On DCE4, if there is an external clock, it generates the DP ref clock */
-			if (is_dp && rdev->clock.dp_extclk)
-				args.v3.acConfig.ucRefClkSource = 2; /* external src */
-			else
-				args.v3.acConfig.ucRefClkSource = pll_id;
-		}
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v3.acConfig.ucTransmitterSel = 0;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			args.v3.acConfig.ucTransmitterSel = 1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v3.acConfig.ucTransmitterSel = 2;
-			break;
-		}
-
-		if (is_dp)
-			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
-		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v3.acConfig.fCoherentMode = 1;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v3.acConfig.fDualLinkConnector = 1;
-		}
-	} else if (ASIC_IS_DCE32(rdev)) {
-		args.v2.acConfig.ucEncoderSel = dig_encoder;
-		if (dig->linkb)
-			args.v2.acConfig.ucLinkSel = 1;
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v2.acConfig.ucTransmitterSel = 0;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			args.v2.acConfig.ucTransmitterSel = 1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v2.acConfig.ucTransmitterSel = 2;
-			break;
-		}
-
-		if (is_dp) {
-			args.v2.acConfig.fCoherentMode = 1;
-			args.v2.acConfig.fDPConnector = 1;
-		} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v2.acConfig.fCoherentMode = 1;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v2.acConfig.fDualLinkConnector = 1;
-		}
-	} else {
-		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-
-		if (dig_encoder)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-		else
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
-
-		if ((rdev->flags & RADEON_IS_IGP) &&
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
-			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
-				if (igp_lane_info & 0x1)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-				else if (igp_lane_info & 0x2)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
-				else if (igp_lane_info & 0x4)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
-				else if (igp_lane_info & 0x8)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
-			} else {
-				if (igp_lane_info & 0x3)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
-				else if (igp_lane_info & 0xc)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
-			}
-		}
-
-		if (dig->linkb)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
-		else
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
-
-		if (is_dp)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
-		}
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-bool
-atombios_set_edp_panel_power(struct drm_connector *connector, int action)
-{
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_device *dev = radeon_connector->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
-	union dig_transmitter_control args;
-	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-	uint8_t frev, crev;
-
-	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-		goto done;
-
-	if (!ASIC_IS_DCE4(rdev))
-		goto done;
-
-	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
-	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
-		goto done;
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		goto done;
-
-	memset(&args, 0, sizeof(args));
-
-	args.v1.ucAction = action;
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	/* wait for the panel to power up */
-	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
-		int i;
-
-		for (i = 0; i < 300; i++) {
-			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
-				return true;
-			mdelay(1);
-		}
-		return false;
-	}
-done:
-	return true;
-}
-
-union external_encoder_control {
-	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
-	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
-};
-
-static void
-atombios_external_encoder_setup(struct drm_encoder *encoder,
-				struct drm_encoder *ext_encoder,
-				int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-	union external_encoder_control args;
-	struct drm_connector *connector;
-	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
-	u8 frev, crev;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int connector_object_id = 0;
-	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-	int bpc = 8;
-
-	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-		connector = radeon_get_connector_for_encoder_init(encoder);
-	else
-		connector = radeon_get_connector_for_encoder(encoder);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		connector_object_id =
-			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-		bpc = connector->display_info.bpc;
-	}
-
-	memset(&args, 0, sizeof(args));
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-		/* no params on frev 1 */
-		break;
-	case 2:
-		switch (crev) {
-		case 1:
-		case 2:
-			args.v1.sDigEncoder.ucAction = action;
-			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-			if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-				if (dp_clock == 270000)
-					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
-			} else if (radeon_encoder->pixel_clock > 165000)
-				args.v1.sDigEncoder.ucLaneNum = 8;
-			else
-				args.v1.sDigEncoder.ucLaneNum = 4;
-			break;
-		case 3:
-			args.v3.sExtEncoder.ucAction = action;
-			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
-			else
-				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-			if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-				if (dp_clock == 270000)
-					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-				else if (dp_clock == 540000)
-					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
-				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
-			} else if (radeon_encoder->pixel_clock > 165000)
-				args.v3.sExtEncoder.ucLaneNum = 8;
-			else
-				args.v3.sExtEncoder.ucLaneNum = 4;
-			switch (ext_enum) {
-			case GRAPH_OBJECT_ENUM_ID1:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
-				break;
-			case GRAPH_OBJECT_ENUM_ID2:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
-				break;
-			case GRAPH_OBJECT_ENUM_ID3:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
-				break;
-			}
-			switch (bpc) {
-			case 0:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
-				break;
-			case 6:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-				break;
-			case 8:
-			default:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-				break;
-			case 10:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-				break;
-			case 12:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-				break;
-			case 16:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-				break;
-			}
-			break;
-		default:
-			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-			return;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-		return;
-	}
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-static void
-atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	ENABLE_YUV_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
-	uint32_t temp, reg;
-
-	memset(&args, 0, sizeof(args));
-
-	if (rdev->family >= CHIP_R600)
-		reg = R600_BIOS_3_SCRATCH;
-	else
-		reg = RADEON_BIOS_3_SCRATCH;
-
-	/* XXX: fix up scratch reg handling */
-	temp = RREG32(reg);
-	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
-			     (radeon_crtc->crtc_id << 18)));
-	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
-	else
-		WREG32(reg, 0);
-
-	if (enable)
-		args.ucEnable = ATOM_ENABLE;
-	args.ucCRTC = radeon_crtc->crtc_id;
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	WREG32(reg, temp);
-}
-
-static void
-radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	bool is_dig = false;
-	bool is_dce5_dac = false;
-	bool is_dce5_dvo = false;
-
-	memset(&args, 0, sizeof(args));
-
-	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
-		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
-		  radeon_encoder->active_device);
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		is_dig = true;
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		if (ASIC_IS_DCE5(rdev))
-			is_dce5_dvo = true;
-		else if (ASIC_IS_DCE3(rdev))
-			is_dig = true;
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-		if (ASIC_IS_DCE5(rdev))
-			is_dce5_dac = true;
-		else {
-			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-			else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-			else
-				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
-		break;
-	}
-
-	if (is_dig) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			/* some early dce3.2 boards have a bug in their transmitter control table */
-			if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-			else
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
-			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (connector &&
-				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-					struct radeon_connector_atom_dig *radeon_dig_connector =
-						radeon_connector->con_priv;
-					atombios_set_edp_panel_power(connector,
-								     ATOM_TRANSMITTER_ACTION_POWER_ON);
-					radeon_dig_connector->edp_on = true;
-				}
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-				radeon_dp_link_train(encoder, connector);
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
-			}
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-				if (connector &&
-				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-					struct radeon_connector_atom_dig *radeon_dig_connector =
-						radeon_connector->con_priv;
-					atombios_set_edp_panel_power(connector,
-								     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-					radeon_dig_connector->edp_on = false;
-				}
-			}
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-			break;
-		}
-	} else if (is_dce5_dac) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			atombios_dac_setup(encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dac_setup(encoder, ATOM_DISABLE);
-			break;
-		}
-	} else if (is_dce5_dvo) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			atombios_dvo_setup(encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dvo_setup(encoder, ATOM_DISABLE);
-			break;
-		}
-	} else {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			args.ucAction = ATOM_ENABLE;
-			/* workaround for DVOOutputControl on some RS690 systems */
-			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
-				u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
-				WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-				WREG32(RADEON_BIOS_3_SCRATCH, reg);
-			} else
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				args.ucAction = ATOM_LCD_BLON;
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			}
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			args.ucAction = ATOM_DISABLE;
-			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				args.ucAction = ATOM_LCD_BLOFF;
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			}
-			break;
-		}
-	}
-
-	if (ext_encoder) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-		default:
-			if (ASIC_IS_DCE41(rdev)) {
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
-			} else
-				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			if (ASIC_IS_DCE41(rdev)) {
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
-			} else
-				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
-			break;
-		}
-	}
-
-	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
-
-}
-
-union crtc_source_param {
-	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
-	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
-};
-
-static void
-atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	union crtc_source_param args;
-	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
-	uint8_t frev, crev;
-	struct radeon_encoder_atom_dig *dig;
-
-	memset(&args, 0, sizeof(args));
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-		switch (crev) {
-		case 1:
-		default:
-			if (ASIC_IS_AVIVO(rdev))
-				args.v1.ucCRTC = radeon_crtc->crtc_id;
-			else {
-				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
-					args.v1.ucCRTC = radeon_crtc->crtc_id;
-				} else {
-					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
-				}
-			}
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
-					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-			case ENCODER_OBJECT_ID_INTERNAL_DDI:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
-				break;
-			}
-			break;
-		case 2:
-			args.v2.ucCRTC = radeon_crtc->crtc_id;
-			if (radeon_encoder_is_dp_bridge(encoder)) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
-					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
-				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
-					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
-				else
-					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-			} else
-				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-				dig = radeon_encoder->enc_priv;
-				switch (dig->dig_encoder) {
-				case 0:
-					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
-					break;
-				case 1:
-					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-					break;
-				case 2:
-					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
-					break;
-				case 3:
-					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
-					break;
-				case 4:
-					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
-					break;
-				case 5:
-					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
-					break;
-				}
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else
-					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else
-					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
-				break;
-			}
-			break;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-		return;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	/* update scratch regs with new routing */
-	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
-}
-
-static void
-atombios_apply_encoder_quirks(struct drm_encoder *encoder,
-			      struct drm_display_mode *mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-
-	/* Funky macbooks */
-	if ((dev->pdev->device == 0x71C5) &&
-	    (dev->pdev->subsystem_vendor == 0x106b) &&
-	    (dev->pdev->subsystem_device == 0x0080)) {
-		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
-			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
-
-			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
-			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
-
-			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
-		}
-	}
-
-	/* set scaler clears this on some chips */
-	if (ASIC_IS_AVIVO(rdev) &&
-	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
-		if (ASIC_IS_DCE4(rdev)) {
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
-				       EVERGREEN_INTERLEAVE_EN);
-			else
-				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-		} else {
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
-				       AVIVO_D1MODE_INTERLEAVE_EN);
-			else
-				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-		}
-	}
-}
-
-static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *test_encoder;
-	struct radeon_encoder_atom_dig *dig;
-	uint32_t dig_enc_in_use = 0;
-
-	/* DCE4/5 */
-	if (ASIC_IS_DCE4(rdev)) {
-		dig = radeon_encoder->enc_priv;
-		if (ASIC_IS_DCE41(rdev)) {
-			/* ontario follows DCE4 */
-			if (rdev->family == CHIP_PALM) {
-				if (dig->linkb)
-					return 1;
-				else
-					return 0;
-			} else
-				/* llano follows DCE3.2 */
-				return radeon_crtc->crtc_id;
-		} else {
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-				if (dig->linkb)
-					return 1;
-				else
-					return 0;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-				if (dig->linkb)
-					return 3;
-				else
-					return 2;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-				if (dig->linkb)
-					return 5;
-				else
-					return 4;
-				break;
-			}
-		}
-	}
-
-	/* on DCE32 and encoder can driver any block so just crtc id */
-	if (ASIC_IS_DCE32(rdev)) {
-		return radeon_crtc->crtc_id;
-	}
-
-	/* on DCE3 - LVTMA can only be driven by DIGB */
-	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
-		struct radeon_encoder *radeon_test_encoder;
-
-		if (encoder == test_encoder)
-			continue;
-
-		if (!radeon_encoder_is_digital(test_encoder))
-			continue;
-
-		radeon_test_encoder = to_radeon_encoder(test_encoder);
-		dig = radeon_test_encoder->enc_priv;
-
-		if (dig->dig_encoder >= 0)
-			dig_enc_in_use |= (1 << dig->dig_encoder);
-	}
-
-	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
-		if (dig_enc_in_use & 0x2)
-			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
-		return 1;
-	}
-	if (!(dig_enc_in_use & 1))
-		return 0;
-	return 1;
-}
-
-/* This only needs to be called once at startup */
-void
-radeon_atom_encoder_init(struct radeon_device *rdev)
-{
-	struct drm_device *dev = rdev->ddev;
-	struct drm_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-		struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
-			break;
-		default:
-			break;
-		}
-
-		if (ext_encoder && ASIC_IS_DCE41(rdev))
-			atombios_external_encoder_setup(encoder, ext_encoder,
-							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
-	}
-}
-
-static void
-radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
-			     struct drm_display_mode *mode,
-			     struct drm_display_mode *adjusted_mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-	radeon_encoder->pixel_clock = adjusted_mode->clock;
-
-	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
-		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
-			atombios_yuv_setup(encoder, true);
-		else
-			atombios_yuv_setup(encoder, false);
-	}
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		if (ASIC_IS_DCE4(rdev)) {
-			/* disable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			/* setup and enable the encoder */
-			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-
-			/* enable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-		} else {
-			/* disable the encoder and transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-
-			/* setup and enable the encoder and transmitter */
-			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		atombios_dvo_setup(encoder, ATOM_ENABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		atombios_dac_setup(encoder, ATOM_ENABLE);
-		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
-			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-				atombios_tv_setup(encoder, ATOM_ENABLE);
-			else
-				atombios_tv_setup(encoder, ATOM_DISABLE);
-		}
-		break;
-	}
-
-	if (ext_encoder) {
-		if (ASIC_IS_DCE41(rdev))
-			atombios_external_encoder_setup(encoder, ext_encoder,
-							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
-		else
-			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-	}
-
-	atombios_apply_encoder_quirks(encoder, adjusted_mode);
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
-		r600_hdmi_enable(encoder);
-		r600_hdmi_setmode(encoder, adjusted_mode);
-	}
-}
-
-static bool
-atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
-				       ATOM_DEVICE_CV_SUPPORT |
-				       ATOM_DEVICE_CRT_SUPPORT)) {
-		DAC_LOAD_DETECTION_PS_ALLOCATION args;
-		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
-		uint8_t frev, crev;
-
-		memset(&args, 0, sizeof(args));
-
-		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-			return false;
-
-		args.sDacload.ucMisc = 0;
-
-		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
-			args.sDacload.ucDacType = ATOM_DAC_A;
-		else
-			args.sDacload.ucDacType = ATOM_DAC_B;
-
-		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
-		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
-		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
-			if (crev >= 3)
-				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
-			if (crev >= 3)
-				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-		}
-
-		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-		return true;
-	} else
-		return false;
-}
-
-static enum drm_connector_status
-radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	uint32_t bios_0_scratch;
-
-	if (!atombios_dac_load_detect(encoder, connector)) {
-		DRM_DEBUG_KMS("detect returned false \n");
-		return connector_status_unknown;
-	}
-
-	if (rdev->family >= CHIP_R600)
-		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-	else
-		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
-
-	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-			return connector_status_connected; /* CTV */
-		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-			return connector_status_connected; /* STV */
-	}
-	return connector_status_disconnected;
-}
-
-static enum drm_connector_status
-radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-	u32 bios_0_scratch;
-
-	if (!ASIC_IS_DCE4(rdev))
-		return connector_status_unknown;
-
-	if (!ext_encoder)
-		return connector_status_unknown;
-
-	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
-		return connector_status_unknown;
-
-	/* load detect on the dp bridge */
-	atombios_external_encoder_setup(encoder, ext_encoder,
-					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
-
-	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-
-	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-			return connector_status_connected; /* CTV */
-		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-			return connector_status_connected; /* STV */
-	}
-	return connector_status_disconnected;
-}
-
-void
-radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
-{
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-	if (ext_encoder)
-		/* ddc_setup on the dp bridge */
-		atombios_external_encoder_setup(encoder, ext_encoder,
-						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
-
-}
-
-static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-	if ((radeon_encoder->active_device &
-	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-	    radeon_encoder_is_dp_bridge(encoder)) {
-		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-		if (dig)
-			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
-	}
-
-	radeon_atom_output_lock(encoder, true);
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-		/* select the clock/data port if it uses a router */
-		if (radeon_connector->router.cd_valid)
-			radeon_router_select_cd_port(radeon_connector);
-
-		/* turn eDP panel on for mode set */
-		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-			atombios_set_edp_panel_power(connector,
-						     ATOM_TRANSMITTER_ACTION_POWER_ON);
-	}
-
-	/* this is needed for the pll/ss setup to work correctly in some cases */
-	atombios_set_encoder_crtc_source(encoder);
-}
-
-static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
-{
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-	radeon_atom_output_lock(encoder, false);
-}
-
-static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig;
-
-	/* check for pre-DCE3 cards with shared encoders;
-	 * can't really use the links individually, so don't disable
-	 * the encoder if it's in use by another connector
-	 */
-	if (!ASIC_IS_DCE3(rdev)) {
-		struct drm_encoder *other_encoder;
-		struct radeon_encoder *other_radeon_encoder;
-
-		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
-			other_radeon_encoder = to_radeon_encoder(other_encoder);
-			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
-			    drm_helper_encoder_in_use(other_encoder))
-				goto disable_done;
-		}
-	}
-
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		if (ASIC_IS_DCE4(rdev))
-			/* disable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-		else {
-			/* disable the encoder and transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		atombios_dvo_setup(encoder, ATOM_DISABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		atombios_dac_setup(encoder, ATOM_DISABLE);
-		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-			atombios_tv_setup(encoder, ATOM_DISABLE);
-		break;
-	}
-
-disable_done:
-	if (radeon_encoder_is_digital(encoder)) {
-		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-			r600_hdmi_disable(encoder);
-		dig = radeon_encoder->enc_priv;
-		dig->dig_encoder = -1;
-	}
-	radeon_encoder->active_device = 0;
-}
-
-/* these are handled by the primary encoders */
-static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
-{
-
-}
-
-static void radeon_atom_ext_commit(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_mode_set(struct drm_encoder *encoder,
-			 struct drm_display_mode *mode,
-			 struct drm_display_mode *adjusted_mode)
-{
-
-}
-
-static void radeon_atom_ext_disable(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
-{
-
-}
-
-static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
-	.dpms = radeon_atom_ext_dpms,
-	.mode_fixup = radeon_atom_ext_mode_fixup,
-	.prepare = radeon_atom_ext_prepare,
-	.mode_set = radeon_atom_ext_mode_set,
-	.commit = radeon_atom_ext_commit,
-	.disable = radeon_atom_ext_disable,
-	/* no detect for TMDS/LVDS yet */
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
-	.dpms = radeon_atom_encoder_dpms,
-	.mode_fixup = radeon_atom_mode_fixup,
-	.prepare = radeon_atom_encoder_prepare,
-	.mode_set = radeon_atom_encoder_mode_set,
-	.commit = radeon_atom_encoder_commit,
-	.disable = radeon_atom_encoder_disable,
-	.detect = radeon_atom_dig_detect,
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
-	.dpms = radeon_atom_encoder_dpms,
-	.mode_fixup = radeon_atom_mode_fixup,
-	.prepare = radeon_atom_encoder_prepare,
-	.mode_set = radeon_atom_encoder_mode_set,
-	.commit = radeon_atom_encoder_commit,
-	.detect = radeon_atom_dac_detect,
-};
-
-void radeon_enc_destroy(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	kfree(radeon_encoder->enc_priv);
-	drm_encoder_cleanup(encoder);
-	kfree(radeon_encoder);
-}
-
-static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
-	.destroy = radeon_enc_destroy,
-};
-
-struct radeon_encoder_atom_dac *
-radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
-{
-	struct drm_device *dev = radeon_encoder->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
-
-	if (!dac)
-		return NULL;
-
-	dac->tv_std = radeon_atombios_get_tv_info(rdev);
-	return dac;
-}
-
-struct radeon_encoder_atom_dig *
-radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
-{
-	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
-
-	if (!dig)
-		return NULL;
-
-	/* coherent mode by default */
-	dig->coherent_mode = true;
-	dig->dig_encoder = -1;
-
-	if (encoder_enum == 2)
-		dig->linkb = true;
-	else
-		dig->linkb = false;
-
-	return dig;
-}
-
-void
-radeon_add_atom_encoder(struct drm_device *dev,
-			uint32_t encoder_enum,
-			uint32_t supported_device,
-			u16 caps)
-{
-	struct radeon_device *rdev = dev->dev_private;
-	struct drm_encoder *encoder;
-	struct radeon_encoder *radeon_encoder;
-
-	/* see if we already added it */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		radeon_encoder = to_radeon_encoder(encoder);
-		if (radeon_encoder->encoder_enum == encoder_enum) {
-			radeon_encoder->devices |= supported_device;
-			return;
-		}
-
-	}
-
-	/* add a new one */
-	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
-	if (!radeon_encoder)
-		return;
-
-	encoder = &radeon_encoder->base;
-	switch (rdev->num_crtc) {
-	case 1:
-		encoder->possible_crtcs = 0x1;
-		break;
-	case 2:
-	default:
-		encoder->possible_crtcs = 0x3;
-		break;
-	case 4:
-		encoder->possible_crtcs = 0xf;
-		break;
-	case 6:
-		encoder->possible_crtcs = 0x3f;
-		break;
-	}
-
-	radeon_encoder->enc_priv = NULL;
-
-	radeon_encoder->encoder_enum = encoder_enum;
-	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-	radeon_encoder->devices = supported_device;
-	radeon_encoder->rmx_type = RMX_OFF;
-	radeon_encoder->underscan_type = UNDERSCAN_OFF;
-	radeon_encoder->is_ext_encoder = false;
-	radeon_encoder->caps = caps;
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		}
-		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
-		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		}
-		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_SI170B:
-	case ENCODER_OBJECT_ID_CH7303:
-	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
-	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
-	case ENCODER_OBJECT_ID_TITFP513:
-	case ENCODER_OBJECT_ID_VT1623:
-	case ENCODER_OBJECT_ID_HDMI_SI1930:
-	case ENCODER_OBJECT_ID_TRAVIS:
-	case ENCODER_OBJECT_ID_NUTMEG:
-		/* these are handled by the primary encoders */
-		radeon_encoder->is_ext_encoder = true;
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-		else
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
-		break;
-	}
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,7 @@ static void radeon_fence_write(struct ra
 			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
 		else
 			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
+		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);
 	} else
 		WREG32(rdev->fence_drv.scratch_reg, seq);
 }
@@ -263,7 +263,7 @@ retry:
 		 */
 		if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) {
 			/* good news we believe it's a lockup */
-			WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
+			printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
 			     fence->seq, seq);
 			/* FIXME: what should we do ? marking everyone
 			 * as signaled for now
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_gart.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_gart.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_gart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_gart.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,27 +49,27 @@ int radeon_gart_table_ram_alloc(struct r
 			      rdev->gart.table_size >> PAGE_SHIFT);
 	}
 #endif
-	rdev->gart.table.ram.ptr = ptr;
-	memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size);
+	rdev->gart.ptr = ptr;
+	memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size);
 	return 0;
 }
 
 void radeon_gart_table_ram_free(struct radeon_device *rdev)
 {
-	if (rdev->gart.table.ram.ptr == NULL) {
+	if (rdev->gart.ptr == NULL) {
 		return;
 	}
 #ifdef CONFIG_X86
 	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
 	    rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
-		set_memory_wb((unsigned long)rdev->gart.table.ram.ptr,
+		set_memory_wb((unsigned long)rdev->gart.ptr,
 			      rdev->gart.table_size >> PAGE_SHIFT);
 	}
 #endif
 	pci_free_consistent(rdev->pdev, rdev->gart.table_size,
-			    (void *)rdev->gart.table.ram.ptr,
+			    (void *)rdev->gart.ptr,
 			    rdev->gart.table_addr);
-	rdev->gart.table.ram.ptr = NULL;
+	rdev->gart.ptr = NULL;
 	rdev->gart.table_addr = 0;
 }
 
@@ -77,10 +77,10 @@ int radeon_gart_table_vram_alloc(struct
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		r = radeon_bo_create(rdev, rdev->gart.table_size,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     &rdev->gart.table.vram.robj);
+				     &rdev->gart.robj);
 		if (r) {
 			return r;
 		}
@@ -93,38 +93,46 @@ int radeon_gart_table_vram_pin(struct ra
 	uint64_t gpu_addr;
 	int r;
 
-	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	r = radeon_bo_reserve(rdev->gart.robj, false);
 	if (unlikely(r != 0))
 		return r;
-	r = radeon_bo_pin(rdev->gart.table.vram.robj,
+	r = radeon_bo_pin(rdev->gart.robj,
 				RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
 	if (r) {
-		radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		radeon_bo_unreserve(rdev->gart.robj);
 		return r;
 	}
-	r = radeon_bo_kmap(rdev->gart.table.vram.robj,
-				(void **)&rdev->gart.table.vram.ptr);
+	r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
 	if (r)
-		radeon_bo_unpin(rdev->gart.table.vram.robj);
-	radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		radeon_bo_unpin(rdev->gart.robj);
+	radeon_bo_unreserve(rdev->gart.robj);
 	rdev->gart.table_addr = gpu_addr;
 	return r;
 }
 
-void radeon_gart_table_vram_free(struct radeon_device *rdev)
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		return;
 	}
-	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	r = radeon_bo_reserve(rdev->gart.robj, false);
 	if (likely(r == 0)) {
-		radeon_bo_kunmap(rdev->gart.table.vram.robj);
-		radeon_bo_unpin(rdev->gart.table.vram.robj);
-		radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		radeon_bo_kunmap(rdev->gart.robj);
+		radeon_bo_unpin(rdev->gart.robj);
+		radeon_bo_unreserve(rdev->gart.robj);
+		rdev->gart.ptr = NULL;
 	}
-	radeon_bo_unref(&rdev->gart.table.vram.robj);
+}
+
+void radeon_gart_table_vram_free(struct radeon_device *rdev)
+{
+	if (rdev->gart.robj == NULL) {
+		return;
+	}
+	radeon_gart_table_vram_unpin(rdev);
+	radeon_bo_unref(&rdev->gart.robj);
 }
 
 
@@ -142,7 +150,7 @@ void radeon_gart_unbind(struct radeon_de
 	u64 page_base;
 
 	if (!rdev->gart.ready) {
-		WARN(1, "trying to unbind memory to unitialized GART !\n");
+		WARN(1, "trying to unbind memory from uninitialized GART !\n");
 		return;
 	}
 	t = offset / RADEON_GPU_PAGE_SIZE;
@@ -151,12 +159,14 @@ void radeon_gart_unbind(struct radeon_de
 		if (rdev->gart.pages[p]) {
 			if (!rdev->gart.ttm_alloced[p])
 				pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
-				       		PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+						PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 			rdev->gart.pages[p] = NULL;
 			rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
 			page_base = rdev->gart.pages_addr[p];
 			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-				radeon_gart_set_page(rdev, t, page_base);
+				if (rdev->gart.ptr) {
+					radeon_gart_set_page(rdev, t, page_base);
+				}
 				page_base += RADEON_GPU_PAGE_SIZE;
 			}
 		}
@@ -174,7 +184,7 @@ int radeon_gart_bind(struct radeon_devic
 	int i, j;
 
 	if (!rdev->gart.ready) {
-		WARN(1, "trying to bind memory to unitialized GART !\n");
+		WARN(1, "trying to bind memory to uninitialized GART !\n");
 		return -EINVAL;
 	}
 	t = offset / RADEON_GPU_PAGE_SIZE;
@@ -199,10 +209,12 @@ int radeon_gart_bind(struct radeon_devic
 			}
 		}
 		rdev->gart.pages[p] = pagelist[i];
-		page_base = rdev->gart.pages_addr[p];
-		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-			radeon_gart_set_page(rdev, t, page_base);
-			page_base += RADEON_GPU_PAGE_SIZE;
+		if (rdev->gart.ptr) {
+			page_base = rdev->gart.pages_addr[p];
+			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
+				radeon_gart_set_page(rdev, t, page_base);
+				page_base += RADEON_GPU_PAGE_SIZE;
+			}
 		}
 	}
 	mb();
@@ -215,6 +227,9 @@ void radeon_gart_restore(struct radeon_d
 	int i, j, t;
 	u64 page_base;
 
+	if (!rdev->gart.ptr) {
+		return;
+	}
 	for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
 		page_base = rdev->gart.pages_addr[i];
 		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,6 +93,7 @@ extern int radeon_audio;
 extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
+extern int radeon_msi;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -102,7 +103,7 @@ extern int radeon_pcie_gen2;
 #define RADEON_FENCE_JIFFIES_TIMEOUT	(HZ / 2)
 /* RADEON_IB_POOL_SIZE must be a power of 2 */
 #define RADEON_IB_POOL_SIZE		16
-#define RADEON_DEBUGFS_MAX_NUM_FILES	32
+#define RADEON_DEBUGFS_MAX_COMPONENTS	32
 #define RADEONFB_CONN_LIMIT		4
 #define RADEON_BIOS_NUM_SCRATCH		8
 
@@ -306,30 +307,17 @@ int radeon_mode_dumb_destroy(struct drm_
  */
 struct radeon_mc;
 
-struct radeon_gart_table_ram {
-	volatile uint32_t		*ptr;
-};
-
-struct radeon_gart_table_vram {
-	struct radeon_bo		*robj;
-	volatile uint32_t		*ptr;
-};
-
-union radeon_gart_table {
-	struct radeon_gart_table_ram	ram;
-	struct radeon_gart_table_vram	vram;
-};
-
 #define RADEON_GPU_PAGE_SIZE 4096
 #define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
 #define RADEON_GPU_PAGE_SHIFT 12
 
 struct radeon_gart {
 	dma_addr_t			table_addr;
+	struct radeon_bo		*robj;
+	void				*ptr;
 	unsigned			num_gpu_pages;
 	unsigned			num_cpu_pages;
 	unsigned			table_size;
-	union radeon_gart_table		table;
 	struct page			**pages;
 	dma_addr_t			*pages_addr;
 	bool				*ttm_alloced;
@@ -340,6 +328,8 @@ int radeon_gart_table_ram_alloc(struct r
 void radeon_gart_table_ram_free(struct radeon_device *rdev);
 int radeon_gart_table_vram_alloc(struct radeon_device *rdev);
 void radeon_gart_table_vram_free(struct radeon_device *rdev);
+int radeon_gart_table_vram_pin(struct radeon_device *rdev);
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev);
 int radeon_gart_init(struct radeon_device *rdev);
 void radeon_gart_fini(struct radeon_device *rdev);
 void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
@@ -347,6 +337,7 @@ void radeon_gart_unbind(struct radeon_de
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
 		     int pages, struct page **pagelist,
 		     dma_addr_t *dma_addr);
+void radeon_gart_restore(struct radeon_device *rdev);
 
 
 /*
@@ -437,25 +428,26 @@ union radeon_irq_stat_regs {
 	struct evergreen_irq_stat_regs evergreen;
 };
 
+#define RADEON_MAX_HPD_PINS 6
+#define RADEON_MAX_CRTCS 6
+#define RADEON_MAX_HDMI_BLOCKS 2
+
 struct radeon_irq {
 	bool		installed;
 	bool		sw_int;
-	/* FIXME: use a define max crtc rather than hardcode it */
-	bool		crtc_vblank_int[6];
-	bool		pflip[6];
+	bool		crtc_vblank_int[RADEON_MAX_CRTCS];
+	bool		pflip[RADEON_MAX_CRTCS];
 	wait_queue_head_t	vblank_queue;
-	/* FIXME: use defines for max hpd/dacs */
-	bool            hpd[6];
+	bool            hpd[RADEON_MAX_HPD_PINS];
 	bool            gui_idle;
 	bool            gui_idle_acked;
 	wait_queue_head_t	idle_queue;
-	/* FIXME: use defines for max HDMI blocks */
-	bool		hdmi[2];
+	bool		hdmi[RADEON_MAX_HDMI_BLOCKS];
 	spinlock_t sw_lock;
 	int sw_refcount;
 	union radeon_irq_stat_regs stat_regs;
-	spinlock_t pflip_lock[6];
-	int pflip_refcount[6];
+	spinlock_t pflip_lock[RADEON_MAX_CRTCS];
+	int pflip_refcount[RADEON_MAX_CRTCS];
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
@@ -523,9 +515,30 @@ struct r600_ih {
 	bool                    enabled;
 };
 
+struct r600_blit_cp_primitives {
+	void (*set_render_target)(struct radeon_device *rdev, int format,
+				  int w, int h, u64 gpu_addr);
+	void (*cp_set_surface_sync)(struct radeon_device *rdev,
+				    u32 sync_type, u32 size,
+				    u64 mc_addr);
+	void (*set_shaders)(struct radeon_device *rdev);
+	void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr);
+	void (*set_tex_resource)(struct radeon_device *rdev,
+				 int format, int w, int h, int pitch,
+				 u64 gpu_addr, u32 size);
+	void (*set_scissors)(struct radeon_device *rdev, int x1, int y1,
+			     int x2, int y2);
+	void (*draw_auto)(struct radeon_device *rdev);
+	void (*set_default_state)(struct radeon_device *rdev);
+};
+
 struct r600_blit {
 	struct mutex		mutex;
 	struct radeon_bo	*shader_obj;
+	struct r600_blit_cp_primitives primitives;
+	int max_dim;
+	int ring_size_common;
+	int ring_size_per_loop;
 	u64 shader_gpu_addr;
 	u32 vs_offset, ps_offset;
 	u32 state_offset;
@@ -534,6 +547,8 @@ struct r600_blit {
 	struct radeon_ib *vb_ib;
 };
 
+void r600_blit_suspend(struct radeon_device *rdev);
+
 int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
@@ -596,37 +611,13 @@ struct radeon_cs_parser {
 	struct radeon_ib	*ib;
 	void			*track;
 	unsigned		family;
-	int parser_error;
+	int			parser_error;
+	bool			keep_tiling_flags;
 };
 
 extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
 extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
-
-
-static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
-{
-	struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
-	u32 pg_idx, pg_offset;
-	u32 idx_value = 0;
-	int new_page;
-
-	pg_idx = (idx * 4) / PAGE_SIZE;
-	pg_offset = (idx * 4) % PAGE_SIZE;
-
-	if (ibc->kpage_idx[0] == pg_idx)
-		return ibc->kpage[0][pg_offset/4];
-	if (ibc->kpage_idx[1] == pg_idx)
-		return ibc->kpage[1][pg_offset/4];
-
-	new_page = radeon_cs_update_pages(p, pg_idx);
-	if (new_page < 0) {
-		p->parser_error = new_page;
-		return 0;
-	}
-
-	idx_value = ibc->kpage[new_page][pg_offset/4];
-	return idx_value;
-}
+extern u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx);
 
 struct radeon_cs_packet {
 	unsigned	idx;
@@ -794,8 +785,7 @@ struct radeon_pm_clock_info {
 
 struct radeon_power_state {
 	enum radeon_pm_state_type type;
-	/* XXX: use a define for num clock modes */
-	struct radeon_pm_clock_info clock_info[8];
+	struct radeon_pm_clock_info *clock_info;
 	/* number of valid clock modes in this power state */
 	int num_clock_modes;
 	struct radeon_pm_clock_info *default_clock_mode;
@@ -865,11 +855,14 @@ struct radeon_pm {
 	struct device	        *int_hwmon_dev;
 };
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+			     enum radeon_pm_state_type ps_type,
+			     int instance);
 
 /*
  * Benchmarking
  */
-void radeon_benchmark(struct radeon_device *rdev);
+void radeon_benchmark(struct radeon_device *rdev, int test_number);
 
 
 /*
@@ -1145,12 +1138,55 @@ int radeon_gem_set_tiling_ioctl(struct d
 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *filp);
 
-/* VRAM scratch page for HDP bug */
-struct r700_vram_scratch {
+/* VRAM scratch page for HDP bug, default vram page */
+struct r600_vram_scratch {
 	struct radeon_bo		*robj;
 	volatile uint32_t		*ptr;
+	u64				gpu_addr;
 };
 
+
+/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+	struct mutex		mutex;
+	struct task_struct	*owner;
+	int			level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+	mutex_init(&mutex->mutex);
+	mutex->owner = NULL;
+	mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+	if (mutex_trylock(&mutex->mutex)) {
+		/* The mutex was unlocked before, so it's ours now */
+		mutex->owner = current;
+	} else if (mutex->owner != current) {
+		/* Another process locked the mutex, take it */
+		mutex_lock(&mutex->mutex);
+		mutex->owner = current;
+	}
+	/* Otherwise the mutex was already locked by this process */
+
+	mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+	if (--mutex->level > 0)
+		return;
+
+	mutex->owner = NULL;
+	mutex_unlock(&mutex->mutex);
+}
+
+
 /*
  * Core structure, functions and helpers.
  */
@@ -1206,7 +1242,7 @@ struct radeon_device {
 	struct radeon_gem		gem;
 	struct radeon_pm		pm;
 	uint32_t			bios_scratch[RADEON_BIOS_NUM_SCRATCH];
-	struct mutex			cs_mutex;
+	struct radeon_mutex		cs_mutex;
 	struct radeon_wb		wb;
 	struct radeon_dummy_page	dummy_page;
 	bool				gpu_lockup;
@@ -1220,7 +1256,7 @@ struct radeon_device {
 	const struct firmware *rlc_fw;	/* r6/700 RLC firmware */
 	const struct firmware *mc_fw;	/* NI MC firmware */
 	struct r600_blit r600_blit;
-	struct r700_vram_scratch vram_scratch;
+	struct r600_vram_scratch vram_scratch;
 	int msi_enabled; /* msi enabled */
 	struct r600_ih ih; /* r6/700 interrupt ring */
 	struct work_struct hotplug_work;
@@ -1252,45 +1288,10 @@ int radeon_device_init(struct radeon_dev
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-	if (reg < rdev->rmmio_size)
-		return readl((rdev->rmmio) + reg);
-	else {
-		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
-		return readl((rdev->rmmio) + RADEON_MM_DATA);
-	}
-}
-
-static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-	if (reg < rdev->rmmio_size)
-		writel(v, (rdev->rmmio) + reg);
-	else {
-		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
-		writel(v, (rdev->rmmio) + RADEON_MM_DATA);
-	}
-}
-
-static inline u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
-{
-	if (reg < rdev->rio_mem_size)
-		return ioread32(rdev->rio_mem + reg);
-	else {
-		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
-		return ioread32(rdev->rio_mem + RADEON_MM_DATA);
-	}
-}
-
-static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
-{
-	if (reg < rdev->rio_mem_size)
-		iowrite32(v, rdev->rio_mem + reg);
-	else {
-		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
-		iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
-	}
-}
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 
 /*
  * Cast helper
@@ -1413,19 +1414,19 @@ void radeon_atombios_fini(struct radeon_
 /*
  * RING helpers.
  */
+
+#if DRM_DEBUG_CODE == 0
 static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 {
-#if DRM_DEBUG_CODE
-	if (rdev->cp.count_dw <= 0) {
-		DRM_ERROR("radeon: writting more dword to ring than expected !\n");
-	}
-#endif
 	rdev->cp.ring[rdev->cp.wptr++] = v;
 	rdev->cp.wptr &= rdev->cp.ptr_mask;
 	rdev->cp.count_dw--;
 	rdev->cp.ring_free_dw--;
 }
-
+#else
+/* With debugging this is just too big to inline */
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v);
+#endif
 
 /*
  * ASICs macro.
@@ -1479,8 +1480,6 @@ static inline void radeon_ring_write(str
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
 extern void radeon_agp_disable(struct radeon_device *rdev);
-extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
-extern void radeon_gart_restore(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
@@ -1504,6 +1503,12 @@ extern int radeon_suspend_kms(struct drm
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
 /*
+ * R600 vram scratch functions
+ */
+int r600_vram_scratch_init(struct radeon_device *rdev);
+void r600_vram_scratch_fini(struct radeon_device *rdev);
+
+/*
  * r600 functions used by radeon_encoder.c
  */
 extern void r600_hdmi_enable(struct drm_encoder *encoder);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_i2c.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_i2c.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  * Authors: Dave Airlie
  *          Alex Deucher
  */
+#include <linux/export.h>
+
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
@@ -32,7 +34,7 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
 	u8 out = 0x0;
 	u8 buf[8];
@@ -47,15 +49,11 @@ bool radeon_ddc_probe(struct radeon_conn
 		{
 			.addr = 0x50,
 			.flags = I2C_M_RD,
-			.len = 1,
+			.len = 8,
 			.buf = buf,
 		}
 	};
 
-	/* Read 8 bytes from i2c for extended probe of EDID header */
-	if (requires_extended_probe)
-		msgs[1].len = 8;
-
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
@@ -64,25 +62,24 @@ bool radeon_ddc_probe(struct radeon_conn
 	if (ret != 2)
 		/* Couldn't find an accessible DDC on this connector */
 		return false;
-	if (requires_extended_probe) {
-		/* Probe also for valid EDID header
-		 * EDID header starts with:
-		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
-		 * Only the first 6 bytes must be valid as
-		 * drm_edid_block_valid() can fix the last 2 bytes */
-		if (drm_edid_header_is_valid(buf) < 6) {
-			/* Couldn't find an accessible EDID on this
-			 * connector */
-			return false;
-		}
+	/* Probe also for valid EDID header
+	 * EDID header starts with:
+	 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+	 * Only the first 6 bytes must be valid as
+	 * drm_edid_block_valid() can fix the last 2 bytes */
+	if (drm_edid_header_is_valid(buf) < 6) {
+		/* Couldn't find an accessible EDID on this
+		 * connector */
+		return false;
 	}
 	return true;
 }
 
 /* bit banging i2c */
 
-static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
+static int pre_xfer(struct i2c_adapter *i2c_adap)
 {
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
 	struct radeon_device *rdev = i2c->dev->dev_private;
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t temp;
@@ -137,19 +134,30 @@ static void radeon_i2c_do_lock(struct ra
 	WREG32(rec->en_data_reg, temp);
 
 	/* mask the gpio pins for software use */
-	temp = RREG32(rec->mask_clk_reg);
-	if (lock_state)
-		temp |= rec->mask_clk_mask;
-	else
-		temp &= ~rec->mask_clk_mask;
+	temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask;
 	WREG32(rec->mask_clk_reg, temp);
 	temp = RREG32(rec->mask_clk_reg);
 
+	temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask;
+	WREG32(rec->mask_data_reg, temp);
 	temp = RREG32(rec->mask_data_reg);
-	if (lock_state)
-		temp |= rec->mask_data_mask;
-	else
-		temp &= ~rec->mask_data_mask;
+
+	return 0;
+}
+
+static void post_xfer(struct i2c_adapter *i2c_adap)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t temp;
+
+	/* unmask the gpio pins for software use */
+	temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask;
+	WREG32(rec->mask_clk_reg, temp);
+	temp = RREG32(rec->mask_clk_reg);
+
+	temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
 	WREG32(rec->mask_data_reg, temp);
 	temp = RREG32(rec->mask_data_reg);
 }
@@ -209,22 +217,6 @@ static void set_data(void *i2c_priv, int
 	WREG32(rec->en_data_reg, val);
 }
 
-static int pre_xfer(struct i2c_adapter *i2c_adap)
-{
-	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
-	radeon_i2c_do_lock(i2c, 1);
-
-	return 0;
-}
-
-static void post_xfer(struct i2c_adapter *i2c_adap)
-{
-	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
-	radeon_i2c_do_lock(i2c, 0);
-}
-
 /* hw i2c */
 
 static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_irq.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_irq.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@ void radeon_disable_vblank(struct drm_de
 	}
 }
 
-static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
+static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
 {
 	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
 	u32 irq_mask = RADEON_SW_INT_TEST;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,10 +67,10 @@ void radeon_driver_irq_preinstall_kms(st
 	/* Disable *all* interrupts */
 	rdev->irq.sw_int = false;
 	rdev->irq.gui_idle = false;
-	for (i = 0; i < rdev->num_crtc; i++)
-		rdev->irq.crtc_vblank_int[i] = false;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 		rdev->irq.hpd[i] = false;
+	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
 		rdev->irq.pflip[i] = false;
 	}
 	radeon_irq_set(rdev);
@@ -99,15 +99,55 @@ void radeon_driver_irq_uninstall_kms(str
 	/* Disable *all* interrupts */
 	rdev->irq.sw_int = false;
 	rdev->irq.gui_idle = false;
-	for (i = 0; i < rdev->num_crtc; i++)
-		rdev->irq.crtc_vblank_int[i] = false;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 		rdev->irq.hpd[i] = false;
+	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
 		rdev->irq.pflip[i] = false;
 	}
 	radeon_irq_set(rdev);
 }
 
+static bool radeon_msi_ok(struct radeon_device *rdev)
+{
+	/* RV370/RV380 was first asic with MSI support */
+	if (rdev->family < CHIP_RV380)
+		return false;
+
+	/* MSIs don't work on AGP */
+	if (rdev->flags & RADEON_IS_AGP)
+		return false;
+
+	/* force MSI on */
+	if (radeon_msi == 1)
+		return true;
+	else if (radeon_msi == 0)
+		return false;
+
+	/* Quirks */
+	/* HP RS690 only seems to work with MSIs. */
+	if ((rdev->pdev->device == 0x791f) &&
+	    (rdev->pdev->subsystem_vendor == 0x103c) &&
+	    (rdev->pdev->subsystem_device == 0x30c2))
+		return true;
+
+	/* Dell RS690 only seems to work with MSIs. */
+	if ((rdev->pdev->device == 0x791f) &&
+	    (rdev->pdev->subsystem_vendor == 0x1028) &&
+	    (rdev->pdev->subsystem_device == 0x01fd))
+		return true;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		/* APUs work fine with MSIs */
+		if (rdev->family >= CHIP_PALM)
+			return true;
+		/* lots of IGPs have problems with MSIs */
+		return false;
+	}
+
+	return true;
+}
+
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
 	int i;
@@ -124,12 +164,8 @@ int radeon_irq_kms_init(struct radeon_de
 	}
 	/* enable msi */
 	rdev->msi_enabled = 0;
-	/* MSIs don't seem to work reliably on all IGP
-	 * chips.  Disable MSI on them for now.
-	 */
-	if ((rdev->family >= CHIP_RV380) &&
-	    ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) &&
-	    (!(rdev->flags & RADEON_IS_AGP))) {
+
+	if (radeon_msi_ok(rdev)) {
 		int ret = pci_enable_msi(rdev->pdev);
 		if (!ret) {
 			rdev->msi_enabled = 1;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -991,12 +991,6 @@ static bool radeon_crtc_mode_fixup(struc
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* adjust pm to upcoming mode change */
-	radeon_pm_compute_clocks(rdev);
-
 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 		return false;
 	return true;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_legacy_tv.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_legacy_tv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_legacy_tv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_legacy_tv.c	2012-01-04 18:55:44.000000000 -0500
@@ -864,7 +864,7 @@ void radeon_legacy_tv_adjust_crtc_reg(st
 	*v_sync_strt_wid = tmp;
 }
 
-static inline int get_post_div(int value)
+static int get_post_div(int value)
 {
 	int post_div;
 	switch (value) {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_mode.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_mode.h	2012-01-04 18:55:44.000000000 -0500
@@ -438,15 +438,13 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
-	/* for some Radeon chip families we apply an additional EDID header
-	   check as part of the DDC probe */
-	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
 	struct edid *edid;
 	void *con_priv;
 	bool dac_load_detect;
+	bool detected_by_load; /* if the connection status was determined by load */
 	uint16_t connector_object_id;
 	struct radeon_hpd hpd;
 	struct radeon_router router;
@@ -458,6 +456,8 @@ struct radeon_framebuffer {
 	struct drm_gem_object *obj;
 };
 
+#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
+				((em) == ATOM_ENCODER_MODE_DP_MST))
 
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
@@ -467,8 +467,8 @@ radeon_atombios_get_tv_info(struct radeo
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 
-extern bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder);
-extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
+extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
 extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
 
@@ -488,7 +488,7 @@ extern void atombios_dig_transmitter_set
 					   int action, uint8_t lane_num,
 					   uint8_t lane_set);
 extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
-extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);
+extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 				u8 write_byte, u8 *read_byte);
 
@@ -518,8 +518,7 @@ extern void radeon_i2c_put_byte(struct r
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
-			bool requires_extended_probe);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_object.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_object.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_object.c	2012-01-04 18:55:44.000000000 -0500
@@ -515,3 +515,44 @@ int radeon_bo_fault_reserve_notify(struc
 	}
 	return 0;
 }
+
+int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0))
+		return r;
+	spin_lock(&bo->tbo.bdev->fence_lock);
+	if (mem_type)
+		*mem_type = bo->tbo.mem.mem_type;
+	if (bo->tbo.sync_obj)
+		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	spin_unlock(&bo->tbo.bdev->fence_lock);
+	ttm_bo_unreserve(&bo->tbo);
+	return r;
+}
+
+
+/**
+ * radeon_bo_reserve - reserve bo
+ * @bo:		bo structure
+ * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
+ *
+ * Returns:
+ * -EBUSY: buffer is busy and @no_wait is true
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
+ * a signal. Release all buffer reservations and return to user-space.
+ */
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
+		return r;
+	}
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_object.h linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_object.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_object.h	2012-01-04 18:55:44.000000000 -0500
@@ -52,28 +52,7 @@ static inline unsigned radeon_mem_type_t
 	return 0;
 }
 
-/**
- * radeon_bo_reserve - reserve bo
- * @bo:		bo structure
- * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
- *
- * Returns:
- * -EBUSY: buffer is busy and @no_wait is true
- * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
- * a signal. Release all buffer reservations and return to user-space.
- */
-static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
-{
-	int r;
-
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-	if (unlikely(r != 0)) {
-		if (r != -ERESTARTSYS)
-			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
-		return r;
-	}
-	return 0;
-}
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait);
 
 static inline void radeon_bo_unreserve(struct radeon_bo *bo)
 {
@@ -118,23 +97,8 @@ static inline u64 radeon_bo_mmap_offset(
 	return bo->tbo.addr_space_offset;
 }
 
-static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
-					bool no_wait)
-{
-	int r;
-
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-	if (unlikely(r != 0))
-		return r;
-	spin_lock(&bo->tbo.bdev->fence_lock);
-	if (mem_type)
-		*mem_type = bo->tbo.mem.mem_type;
-	if (bo->tbo.sync_obj)
-		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
-	spin_unlock(&bo->tbo.bdev->fence_lock);
-	ttm_bo_unreserve(&bo->tbo);
-	return r;
-}
+extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
+			  bool no_wait);
 
 extern int radeon_bo_create(struct radeon_device *rdev,
 				unsigned long size, int byte_align,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,6 +53,24 @@ static void radeon_pm_set_clocks(struct
 
 #define ACPI_AC_CLASS           "ac_adapter"
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+			     enum radeon_pm_state_type ps_type,
+			     int instance)
+{
+	int i;
+	int found_instance = -1;
+
+	for (i = 0; i < rdev->pm.num_power_states; i++) {
+		if (rdev->pm.power_state[i].type == ps_type) {
+			found_instance++;
+			if (found_instance == instance)
+				return i;
+		}
+	}
+	/* return default if no match */
+	return rdev->pm.default_power_state_index;
+}
+
 #ifdef CONFIG_ACPI
 static int radeon_acpi_event(struct notifier_block *nb,
 			     unsigned long val,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_ring.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_ring.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,44 @@
 
 int radeon_debugfs_ib_init(struct radeon_device *rdev);
 
+u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
+{
+	struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+	u32 pg_idx, pg_offset;
+	u32 idx_value = 0;
+	int new_page;
+
+	pg_idx = (idx * 4) / PAGE_SIZE;
+	pg_offset = (idx * 4) % PAGE_SIZE;
+
+	if (ibc->kpage_idx[0] == pg_idx)
+		return ibc->kpage[0][pg_offset/4];
+	if (ibc->kpage_idx[1] == pg_idx)
+		return ibc->kpage[1][pg_offset/4];
+
+	new_page = radeon_cs_update_pages(p, pg_idx);
+	if (new_page < 0) {
+		p->parser_error = new_page;
+		return 0;
+	}
+
+	idx_value = ibc->kpage[new_page][pg_offset/4];
+	return idx_value;
+}
+
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
+{
+#if DRM_DEBUG_CODE
+	if (rdev->cp.count_dw <= 0) {
+		DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+	}
+#endif
+	rdev->cp.ring[rdev->cp.wptr++] = v;
+	rdev->cp.wptr &= rdev->cp.ptr_mask;
+	rdev->cp.count_dw--;
+	rdev->cp.ring_free_dw--;
+}
+
 void radeon_ib_bogus_cleanup(struct radeon_device *rdev)
 {
 	struct radeon_ib *ib, *n;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_state.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_state.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/radeon_state.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/radeon_state.c	2012-01-04 18:55:44.000000000 -0500
@@ -272,12 +272,12 @@ static __inline__ int radeon_check_and_f
 	return 0;
 }
 
-static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
-						     dev_priv,
-						     struct drm_file *file_priv,
-						     drm_radeon_kcmd_buffer_t *
-						     cmdbuf,
-						     unsigned int *cmdsz)
+static int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+					  dev_priv,
+					  struct drm_file *file_priv,
+					  drm_radeon_kcmd_buffer_t *
+					  cmdbuf,
+					  unsigned int *cmdsz)
 {
 	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 	u32 offset, narrays;
@@ -446,8 +446,8 @@ static __inline__ int radeon_check_and_f
  * CP hardware state programming functions
  */
 
-static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-					     struct drm_clip_rect * box)
+static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+				  struct drm_clip_rect * box)
 {
 	RING_LOCALS;
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rs400.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rs400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rs400.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@ int rs400_gart_init(struct radeon_device
 {
 	int r;
 
-	if (rdev->gart.table.ram.ptr) {
+	if (rdev->gart.ptr) {
 		WARN(1, "RS400 GART already initialized\n");
 		return 0;
 	}
@@ -182,6 +182,9 @@ int rs400_gart_enable(struct radeon_devi
 	/* Enable gart */
 	WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg));
 	rs400_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -209,6 +212,7 @@ void rs400_gart_fini(struct radeon_devic
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
 	uint32_t entry;
+	u32 *gtt = rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
@@ -218,7 +222,7 @@ int rs400_gart_set_page(struct radeon_de
 		((upper_32_bits(addr) & 0xff) << 4) |
 		RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
 	entry = cpu_to_le32(entry);
-	rdev->gart.table.ram.ptr[i] = entry;
+	gtt[i] = entry;
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rs600.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rs600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rs600.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,7 @@ u32 rs600_page_flip(struct radeon_device
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -287,6 +292,7 @@ void rs600_hpd_init(struct radeon_device
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		rs600_irq_set(rdev);
@@ -413,7 +419,7 @@ int rs600_gart_init(struct radeon_device
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "RS600 GART already initialized\n");
 		return 0;
 	}
@@ -431,7 +437,7 @@ static int rs600_gart_enable(struct rade
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -484,6 +490,9 @@ static int rs600_gart_enable(struct rade
 	tmp = RREG32_MC(R_000009_MC_CNTL1);
 	WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1)));
 	rs600_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -491,20 +500,12 @@ static int rs600_gart_enable(struct rade
 void rs600_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	/* FIXME: disable out of gart access */
 	WREG32_MC(R_000100_MC_PT0_CNTL, 0);
 	tmp = RREG32_MC(R_000009_MC_CNTL1);
 	WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (r == 0) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rs600_gart_fini(struct radeon_device *rdev)
@@ -522,7 +523,7 @@ void rs600_gart_fini(struct radeon_devic
 
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+	void __iomem *ptr = (void *)rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rv770.c linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/radeon/rv770.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/radeon/rv770.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@ u32 rv770_page_flip(struct radeon_device
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -124,7 +129,7 @@ int rv770_pcie_gart_enable(struct radeon
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -161,6 +166,9 @@ int rv770_pcie_gart_enable(struct radeon
 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
 
 	r600_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -168,7 +176,7 @@ int rv770_pcie_gart_enable(struct radeon
 void rv770_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i, r;
+	int i;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -188,14 +196,7 @@ void rv770_pcie_gart_disable(struct rade
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rdev->gart.table.vram.robj);
-			radeon_bo_unpin(rdev->gart.table.vram.robj);
-			radeon_bo_unreserve(rdev->gart.table.vram.robj);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv770_pcie_gart_fini(struct radeon_device *rdev)
@@ -279,7 +280,7 @@ static void rv770_mc_program(struct rade
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
 			rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 	WREG32(MC_VM_FB_LOCATION, tmp);
@@ -956,54 +957,6 @@ static void rv770_gpu_init(struct radeon
 
 }
 
-static int rv770_vram_scratch_init(struct radeon_device *rdev)
-{
-	int r;
-	u64 gpu_addr;
-
-	if (rdev->vram_scratch.robj == NULL) {
-		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
-				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     &rdev->vram_scratch.robj);
-		if (r) {
-			return r;
-		}
-	}
-
-	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-	if (unlikely(r != 0))
-		return r;
-	r = radeon_bo_pin(rdev->vram_scratch.robj,
-			  RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
-	if (r) {
-		radeon_bo_unreserve(rdev->vram_scratch.robj);
-		return r;
-	}
-	r = radeon_bo_kmap(rdev->vram_scratch.robj,
-				(void **)&rdev->vram_scratch.ptr);
-	if (r)
-		radeon_bo_unpin(rdev->vram_scratch.robj);
-	radeon_bo_unreserve(rdev->vram_scratch.robj);
-
-	return r;
-}
-
-static void rv770_vram_scratch_fini(struct radeon_device *rdev)
-{
-	int r;
-
-	if (rdev->vram_scratch.robj == NULL) {
-		return;
-	}
-	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-	if (likely(r == 0)) {
-		radeon_bo_kunmap(rdev->vram_scratch.robj);
-		radeon_bo_unpin(rdev->vram_scratch.robj);
-		radeon_bo_unreserve(rdev->vram_scratch.robj);
-	}
-	radeon_bo_unref(&rdev->vram_scratch.robj);
-}
-
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 {
 	u64 size_bf, size_af;
@@ -1103,6 +1056,10 @@ static int rv770_startup(struct radeon_d
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	rv770_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		rv770_agp_enable(rdev);
@@ -1111,9 +1068,7 @@ static int rv770_startup(struct radeon_d
 		if (r)
 			return r;
 	}
-	r = rv770_vram_scratch_init(rdev);
-	if (r)
-		return r;
+
 	rv770_gpu_init(rdev);
 	r = r600_blit_init(rdev);
 	if (r) {
@@ -1184,8 +1139,6 @@ int rv770_resume(struct radeon_device *r
 
 int rv770_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	r600_audio_fini(rdev);
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
@@ -1193,14 +1146,8 @@ int rv770_suspend(struct radeon_device *
 	r600_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	rv770_pcie_gart_disable(rdev);
-	/* unpin shaders bo */
-	if (rdev->r600_blit.shader_obj) {
-		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-		if (likely(r == 0)) {
-			radeon_bo_unpin(rdev->r600_blit.shader_obj);
-			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-		}
-	}
+	r600_blit_suspend(rdev);
+
 	return 0;
 }
 
@@ -1321,7 +1268,7 @@ void rv770_fini(struct radeon_device *rd
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	rv770_pcie_gart_fini(rdev);
-	rv770_vram_scratch_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_agp_fini(rdev);
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/savage/savage_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/savage/savage_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/savage/savage_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/savage/savage_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "savage_drm.h"
 #include "savage_drv.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/sis/sis_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/sis/sis_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/sis/sis_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/sis/sis_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "sis_drm.h"
 #include "sis_drv.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/tdfx/tdfx_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/tdfx/tdfx_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/tdfx/tdfx_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/tdfx/tdfx_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "tdfx_drv.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-3.2-gnu1/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2012-01-04 18:55:44.000000000 -0500
@@ -574,10 +574,16 @@ retry:
 		return ret;
 
 	spin_lock(&glob->lru_lock);
+
+	if (unlikely(list_empty(&bo->ddestroy))) {
+		spin_unlock(&glob->lru_lock);
+		return 0;
+	}
+
 	ret = ttm_bo_reserve_locked(bo, interruptible,
 				    no_wait_reserve, false, 0);
 
-	if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
+	if (unlikely(ret != 0)) {
 		spin_unlock(&glob->lru_lock);
 		return ret;
 	}
@@ -1293,6 +1299,7 @@ int ttm_bo_create(struct ttm_bo_device *
 
 	return ret;
 }
+EXPORT_SYMBOL(ttm_bo_create);
 
 static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
 					unsigned mem_type, bool allow_errors)
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/ttm/ttm_tt.c linux-libre-3.2-gnu1/drivers/gpu/drm/ttm/ttm_tt.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/ttm/ttm_tt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/ttm/ttm_tt.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/file.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drm_cache.h"
 #include "drm_mem_util.h"
 #include "ttm/ttm_module.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/via/via_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/via/via_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/via/via_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/via/via_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "via_drm.h"
 #include "via_drv.h"
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/Kconfig linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/Kconfig
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,8 @@ config DRM_VMWGFX
 	select FB_CFB_IMAGEBLIT
 	select DRM_TTM
 	help
-	  KMS enabled DRM driver for SVGA2 virtual hardware.
-
-	  If unsure say n. The compiled module will be
-	  called vmwgfx.ko
+	  Choose this option if you would like to run 3D acceleration
+	  in a VMware virtual machine.
+	  This is a KMS enabled DRM driver for the VMware SVGA2
+	  virtual hardware.
+	  The compiled module will be called "vmwgfx.ko".
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/Makefile linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/Makefile
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@ ccflags-y := -Iinclude/drm
 vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
 	    vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
 	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
-	    vmwgfx_overlay.o vmwgfx_fence.o vmwgfx_gmrid_manager.o
+	    vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
+	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga3d_reg.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga3d_reg.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga3d_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga3d_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,7 +57,8 @@ typedef enum {
    SVGA3D_HWVERSION_WS6_B1    = SVGA3D_MAKE_HWVERSION(1, 1),
    SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
    SVGA3D_HWVERSION_WS65_B1   = SVGA3D_MAKE_HWVERSION(2, 0),
-   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS65_B1,
+   SVGA3D_HWVERSION_WS8_B1    = SVGA3D_MAKE_HWVERSION(2, 1),
+   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS8_B1,
 } SVGA3dHardwareVersion;
 
 /*
@@ -67,7 +68,8 @@ typedef enum {
 typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
 #define SVGA3D_NUM_CLIPPLANES                   6
 #define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS  8
-
+#define SVGA3D_MAX_CONTEXT_IDS                  256
+#define SVGA3D_MAX_SURFACE_IDS                  (32 * 1024)
 
 /*
  * Surface formats.
@@ -79,76 +81,91 @@ typedef uint32 SVGA3dBool; /* 32-bit Boo
  */
 
 typedef enum SVGA3dSurfaceFormat {
-   SVGA3D_FORMAT_INVALID = 0,
+   SVGA3D_FORMAT_INVALID               = 0,
 
-   SVGA3D_X8R8G8B8       = 1,
-   SVGA3D_A8R8G8B8       = 2,
+   SVGA3D_X8R8G8B8                     = 1,
+   SVGA3D_A8R8G8B8                     = 2,
 
-   SVGA3D_R5G6B5         = 3,
-   SVGA3D_X1R5G5B5       = 4,
-   SVGA3D_A1R5G5B5       = 5,
-   SVGA3D_A4R4G4B4       = 6,
+   SVGA3D_R5G6B5                       = 3,
+   SVGA3D_X1R5G5B5                     = 4,
+   SVGA3D_A1R5G5B5                     = 5,
+   SVGA3D_A4R4G4B4                     = 6,
 
-   SVGA3D_Z_D32          = 7,
-   SVGA3D_Z_D16          = 8,
-   SVGA3D_Z_D24S8        = 9,
-   SVGA3D_Z_D15S1        = 10,
+   SVGA3D_Z_D32                        = 7,
+   SVGA3D_Z_D16                        = 8,
+   SVGA3D_Z_D24S8                      = 9,
+   SVGA3D_Z_D15S1                      = 10,
 
-   SVGA3D_LUMINANCE8            = 11,
-   SVGA3D_LUMINANCE4_ALPHA4     = 12,
-   SVGA3D_LUMINANCE16           = 13,
-   SVGA3D_LUMINANCE8_ALPHA8     = 14,
+   SVGA3D_LUMINANCE8                   = 11,
+   SVGA3D_LUMINANCE4_ALPHA4            = 12,
+   SVGA3D_LUMINANCE16                  = 13,
+   SVGA3D_LUMINANCE8_ALPHA8            = 14,
 
-   SVGA3D_DXT1           = 15,
-   SVGA3D_DXT2           = 16,
-   SVGA3D_DXT3           = 17,
-   SVGA3D_DXT4           = 18,
-   SVGA3D_DXT5           = 19,
+   SVGA3D_DXT1                         = 15,
+   SVGA3D_DXT2                         = 16,
+   SVGA3D_DXT3                         = 17,
+   SVGA3D_DXT4                         = 18,
+   SVGA3D_DXT5                         = 19,
 
-   SVGA3D_BUMPU8V8       = 20,
-   SVGA3D_BUMPL6V5U5     = 21,
-   SVGA3D_BUMPX8L8V8U8   = 22,
-   SVGA3D_BUMPL8V8U8     = 23,
+   SVGA3D_BUMPU8V8                     = 20,
+   SVGA3D_BUMPL6V5U5                   = 21,
+   SVGA3D_BUMPX8L8V8U8                 = 22,
+   SVGA3D_BUMPL8V8U8                   = 23,
 
-   SVGA3D_ARGB_S10E5     = 24,   /* 16-bit floating-point ARGB */
-   SVGA3D_ARGB_S23E8     = 25,   /* 32-bit floating-point ARGB */
+   SVGA3D_ARGB_S10E5                   = 24,   /* 16-bit floating-point ARGB */
+   SVGA3D_ARGB_S23E8                   = 25,   /* 32-bit floating-point ARGB */
 
-   SVGA3D_A2R10G10B10    = 26,
+   SVGA3D_A2R10G10B10                  = 26,
 
    /* signed formats */
-   SVGA3D_V8U8           = 27,
-   SVGA3D_Q8W8V8U8       = 28,
-   SVGA3D_CxV8U8         = 29,
+   SVGA3D_V8U8                         = 27,
+   SVGA3D_Q8W8V8U8                     = 28,
+   SVGA3D_CxV8U8                       = 29,
 
    /* mixed formats */
-   SVGA3D_X8L8V8U8       = 30,
-   SVGA3D_A2W10V10U10    = 31,
+   SVGA3D_X8L8V8U8                     = 30,
+   SVGA3D_A2W10V10U10                  = 31,
 
-   SVGA3D_ALPHA8         = 32,
+   SVGA3D_ALPHA8                       = 32,
 
    /* Single- and dual-component floating point formats */
-   SVGA3D_R_S10E5        = 33,
-   SVGA3D_R_S23E8        = 34,
-   SVGA3D_RG_S10E5       = 35,
-   SVGA3D_RG_S23E8       = 36,
+   SVGA3D_R_S10E5                      = 33,
+   SVGA3D_R_S23E8                      = 34,
+   SVGA3D_RG_S10E5                     = 35,
+   SVGA3D_RG_S23E8                     = 36,
 
    /*
     * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
     * the most efficient format to use when creating new surfaces
     * expressly for index or vertex data.
     */
-   SVGA3D_BUFFER         = 37,
 
-   SVGA3D_Z_D24X8        = 38,
+   SVGA3D_BUFFER                       = 37,
 
-   SVGA3D_V16U16         = 39,
+   SVGA3D_Z_D24X8                      = 38,
 
-   SVGA3D_G16R16         = 40,
-   SVGA3D_A16B16G16R16   = 41,
+   SVGA3D_V16U16                       = 39,
+
+   SVGA3D_G16R16                       = 40,
+   SVGA3D_A16B16G16R16                 = 41,
 
    /* Packed Video formats */
-   SVGA3D_UYVY           = 42,
-   SVGA3D_YUY2           = 43,
+   SVGA3D_UYVY                         = 42,
+   SVGA3D_YUY2                         = 43,
+
+   /* Planar video formats */
+   SVGA3D_NV12                         = 44,
+
+   /* Video format with alpha */
+   SVGA3D_AYUV                         = 45,
+
+   SVGA3D_BC4_UNORM                    = 108,
+   SVGA3D_BC5_UNORM                    = 111,
+
+   /* Advanced D3D9 depth formats. */
+   SVGA3D_Z_DF16                       = 118,
+   SVGA3D_Z_DF24                       = 119,
+   SVGA3D_Z_D24S8_INT                  = 120,
 
    SVGA3D_FORMAT_MAX
 } SVGA3dSurfaceFormat;
@@ -414,10 +431,20 @@ typedef enum {
    SVGA3D_RS_SRCBLENDALPHA             = 94,    /* SVGA3dBlendOp */
    SVGA3D_RS_DSTBLENDALPHA             = 95,    /* SVGA3dBlendOp */
    SVGA3D_RS_BLENDEQUATIONALPHA        = 96,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_TRANSPARENCYANTIALIAS     = 97,    /* SVGA3dTransparencyAntialiasType */
+   SVGA3D_RS_LINEAA                    = 98,    /* SVGA3dBool */
+   SVGA3D_RS_LINEWIDTH                 = 99,    /* float */
    SVGA3D_RS_MAX
 } SVGA3dRenderStateName;
 
 typedef enum {
+   SVGA3D_TRANSPARENCYANTIALIAS_NORMAL            = 0,
+   SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE   = 1,
+   SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE       = 2,
+   SVGA3D_TRANSPARENCYANTIALIAS_MAX
+} SVGA3dTransparencyAntialiasType;
+
+typedef enum {
    SVGA3D_VERTEXMATERIAL_NONE     = 0,    /* Use the value in the current material */
    SVGA3D_VERTEXMATERIAL_DIFFUSE  = 1,    /* Use the value in the diffuse component */
    SVGA3D_VERTEXMATERIAL_SPECULAR = 2,    /* Use the value in the specular component */
@@ -728,10 +755,10 @@ typedef enum {
    SVGA3D_TEX_FILTER_NEAREST        = 1,
    SVGA3D_TEX_FILTER_LINEAR         = 2,
    SVGA3D_TEX_FILTER_ANISOTROPIC    = 3,
-   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, // Deprecated, not implemented
-   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, // Deprecated, not implemented
-   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, // Not currently implemented
-   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, // Not currently implemented
+   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, /* Deprecated, not implemented */
+   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, /* Deprecated, not implemented */
+   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, /* Not currently implemented */
+   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, /* Not currently implemented */
    SVGA3D_TEX_FILTER_MAX
 } SVGA3dTextureFilter;
 
@@ -799,19 +826,19 @@ typedef enum {
 
 typedef enum {
    SVGA3D_DECLUSAGE_POSITION     = 0,
-   SVGA3D_DECLUSAGE_BLENDWEIGHT,       //  1
-   SVGA3D_DECLUSAGE_BLENDINDICES,      //  2
-   SVGA3D_DECLUSAGE_NORMAL,            //  3
-   SVGA3D_DECLUSAGE_PSIZE,             //  4
-   SVGA3D_DECLUSAGE_TEXCOORD,          //  5
-   SVGA3D_DECLUSAGE_TANGENT,           //  6
-   SVGA3D_DECLUSAGE_BINORMAL,          //  7
-   SVGA3D_DECLUSAGE_TESSFACTOR,        //  8
-   SVGA3D_DECLUSAGE_POSITIONT,         //  9
-   SVGA3D_DECLUSAGE_COLOR,             // 10
-   SVGA3D_DECLUSAGE_FOG,               // 11
-   SVGA3D_DECLUSAGE_DEPTH,             // 12
-   SVGA3D_DECLUSAGE_SAMPLE,            // 13
+   SVGA3D_DECLUSAGE_BLENDWEIGHT,       /*  1 */
+   SVGA3D_DECLUSAGE_BLENDINDICES,      /*  2 */
+   SVGA3D_DECLUSAGE_NORMAL,            /*  3 */
+   SVGA3D_DECLUSAGE_PSIZE,             /*  4 */
+   SVGA3D_DECLUSAGE_TEXCOORD,          /*  5 */
+   SVGA3D_DECLUSAGE_TANGENT,           /*  6 */
+   SVGA3D_DECLUSAGE_BINORMAL,          /*  7 */
+   SVGA3D_DECLUSAGE_TESSFACTOR,        /*  8 */
+   SVGA3D_DECLUSAGE_POSITIONT,         /*  9 */
+   SVGA3D_DECLUSAGE_COLOR,             /* 10 */
+   SVGA3D_DECLUSAGE_FOG,               /* 11 */
+   SVGA3D_DECLUSAGE_DEPTH,             /* 12 */
+   SVGA3D_DECLUSAGE_SAMPLE,            /* 13 */
    SVGA3D_DECLUSAGE_MAX
 } SVGA3dDeclUsage;
 
@@ -819,10 +846,10 @@ typedef enum {
    SVGA3D_DECLMETHOD_DEFAULT     = 0,
    SVGA3D_DECLMETHOD_PARTIALU,
    SVGA3D_DECLMETHOD_PARTIALV,
-   SVGA3D_DECLMETHOD_CROSSUV,          // Normal
+   SVGA3D_DECLMETHOD_CROSSUV,          /* Normal */
    SVGA3D_DECLMETHOD_UV,
-   SVGA3D_DECLMETHOD_LOOKUP,           // Lookup a displacement map
-   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
+   SVGA3D_DECLMETHOD_LOOKUP,           /* Lookup a displacement map */
+   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, /* Lookup a pre-sampled displacement map */
 } SVGA3dDeclMethod;
 
 typedef enum {
@@ -930,7 +957,6 @@ typedef enum {
 } SVGA3dCubeFace;
 
 typedef enum {
-   SVGA3D_SHADERTYPE_COMPILED_DX8               = 0,
    SVGA3D_SHADERTYPE_VS                         = 1,
    SVGA3D_SHADERTYPE_PS                         = 2,
    SVGA3D_SHADERTYPE_MAX
@@ -968,12 +994,18 @@ typedef enum {
 } SVGA3dTransferType;
 
 /*
- * The maximum number vertex arrays we're guaranteed to support in
+ * The maximum number of vertex arrays we're guaranteed to support in
  * SVGA_3D_CMD_DRAWPRIMITIVES.
  */
 #define SVGA3D_MAX_VERTEX_ARRAYS   32
 
 /*
+ * The maximum number of primitive ranges we're guaranteed to support
+ * in SVGA_3D_CMD_DRAWPRIMITIVES.
+ */
+#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32
+
+/*
  * Identifiers for commands in the command FIFO.
  *
  * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
@@ -990,7 +1022,7 @@ typedef enum {
 #define SVGA_3D_CMD_LEGACY_BASE            1000
 #define SVGA_3D_CMD_BASE                   1040
 
-#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0     /* Deprecated */
 #define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
 #define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
 #define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
@@ -1008,7 +1040,7 @@ typedef enum {
 #define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
 #define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
 #define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
-#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    // Deprecated
+#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    /* Deprecated */
 #define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
 #define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
 #define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
@@ -1018,9 +1050,13 @@ typedef enum {
 #define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
 #define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
 #define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
-#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    // Deprecated
+#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    /* Deprecated */
 #define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
-#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_SURFACE_DEFINE_V2      SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_GENERATE_MIPMAPS       SVGA_3D_CMD_BASE + 31
+#define SVGA_3D_CMD_ACTIVATE_SURFACE       SVGA_3D_CMD_BASE + 40
+#define SVGA_3D_CMD_DEACTIVATE_SURFACE     SVGA_3D_CMD_BASE + 41
+#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 42
 
 #define SVGA_3D_CMD_FUTURE_MAX             2000
 
@@ -1031,9 +1067,9 @@ typedef enum {
 typedef struct {
    union {
       struct {
-         uint16  function;       // SVGA3dFogFunction
-         uint8   type;           // SVGA3dFogType
-         uint8   base;           // SVGA3dFogBase
+         uint16  function;       /* SVGA3dFogFunction */
+         uint8   type;           /* SVGA3dFogType */
+         uint8   base;           /* SVGA3dFogBase */
       };
       uint32     uintValue;
    };
@@ -1109,6 +1145,8 @@ typedef enum {
    SVGA3D_SURFACE_HINT_RENDERTARGET    = (1 << 6),
    SVGA3D_SURFACE_HINT_DEPTHSTENCIL    = (1 << 7),
    SVGA3D_SURFACE_HINT_WRITEONLY       = (1 << 8),
+   SVGA3D_SURFACE_MASKABLE_ANTIALIAS   = (1 << 9),
+   SVGA3D_SURFACE_AUTOGENMIPMAPS       = (1 << 10),
 } SVGA3dSurfaceFlags;
 
 typedef
@@ -1121,6 +1159,12 @@ struct {
    uint32                      sid;
    SVGA3dSurfaceFlags          surfaceFlags;
    SVGA3dSurfaceFormat         format;
+   /*
+    * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+    * structures must have the same value of numMipLevels field.
+    * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+    * numMipLevels set to 0.
+    */
    SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
    /*
     * Followed by an SVGA3dSize structure for each mip level in each face.
@@ -1135,6 +1179,31 @@ struct {
 
 typedef
 struct {
+   uint32                      sid;
+   SVGA3dSurfaceFlags          surfaceFlags;
+   SVGA3dSurfaceFormat         format;
+   /*
+    * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+    * structures must have the same value of numMipLevels field.
+    * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+    * numMipLevels set to 0.
+    */
+   SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
+   uint32                      multisampleCount;
+   SVGA3dTextureFilter         autogenFilter;
+   /*
+    * Followed by an SVGA3dSize structure for each mip level in each face.
+    *
+    * A note on surface sizes: Sizes are always specified in pixels,
+    * even if the true surface size is not a multiple of the minimum
+    * block size of the surface's format. For example, a 3x3x1 DXT1
+    * compressed texture would actually be stored as a 4x4x1 image in
+    * memory.
+    */
+} SVGA3dCmdDefineSurface_v2;     /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */
+
+typedef
+struct {
    uint32               sid;
 } SVGA3dCmdDestroySurface;      /* SVGA_3D_CMD_SURFACE_DESTROY */
 
@@ -1474,10 +1543,12 @@ struct {
     * SVGA3dCmdDrawPrimitives structure. In order,
     * they are:
     *
-    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls'
-    * 2. SVGA3dPrimitiveRange, quantity 'numRanges'
+    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
+    *    SVGA3D_MAX_VERTEX_ARRAYS;
+    * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
+    *    SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
     * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
-    *    the frequency divisor for this the corresponding vertex decl)
+    *    the frequency divisor for the corresponding vertex decl).
     */
 } SVGA3dCmdDrawPrimitives;      /* SVGA_3D_CMD_DRAWPRIMITIVES */
 
@@ -1671,6 +1742,12 @@ struct {
    /* Clipping: zero or more SVGASignedRects follow */
 } SVGA3dCmdBlitSurfaceToScreen;         /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
 
+typedef
+struct {
+   uint32               sid;
+   SVGA3dTextureFilter  filter;
+} SVGA3dCmdGenerateMipmaps;             /* SVGA_3D_CMD_GENERATE_MIPMAPS */
+
 
 /*
  * Capability query index.
@@ -1774,6 +1851,32 @@ typedef enum {
    SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16           = 67,
    SVGA3D_DEVCAP_SURFACEFMT_UYVY                   = 68,
    SVGA3D_DEVCAP_SURFACEFMT_YUY2                   = 69,
+   SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES    = 70,
+   SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES       = 71,
+   SVGA3D_DEVCAP_ALPHATOCOVERAGE                   = 72,
+   SVGA3D_DEVCAP_SUPERSAMPLE                       = 73,
+   SVGA3D_DEVCAP_AUTOGENMIPMAPS                    = 74,
+   SVGA3D_DEVCAP_SURFACEFMT_NV12                   = 75,
+   SVGA3D_DEVCAP_SURFACEFMT_AYUV                   = 76,
+
+   /*
+    * This is the maximum number of SVGA context IDs that the guest
+    * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
+    */
+   SVGA3D_DEVCAP_MAX_CONTEXT_IDS                   = 77,
+
+   /*
+    * This is the maximum number of SVGA surface IDs that the guest
+    * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
+    */
+   SVGA3D_DEVCAP_MAX_SURFACE_IDS                   = 78,
+
+   SVGA3D_DEVCAP_SURFACEFMT_Z_DF16                 = 79,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_DF24                 = 80,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT            = 81,
+
+   SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM              = 82,
+   SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM              = 83,
 
    /*
     * Don't add new caps into the previous section; the values in this
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_escape.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_escape.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_escape.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_escape.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,7 +75,7 @@
  */
 
 #define SVGA_ESCAPE_VMWARE_HINT               0x00030000
-#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  // Deprecated
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  /* Deprecated */
 
 typedef
 struct {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_overlay.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_overlay.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_overlay.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_overlay.h	2012-01-04 18:55:44.000000000 -0500
@@ -38,9 +38,9 @@
  * Video formats we support
  */
 
-#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2'
-#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2'
-#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y'
+#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */
+#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */
+#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */
 
 typedef enum {
    SVGA_OVERLAY_FORMAT_INVALID = 0,
@@ -68,7 +68,7 @@ struct SVGAEscapeVideoSetRegs {
       uint32 streamId;
    } header;
 
-   // May include zero or more items.
+   /* May include zero or more items. */
    struct {
       uint32 registerId;
       uint32 value;
@@ -134,12 +134,12 @@ struct {
  */
 
 static inline bool
-VMwareVideoGetAttributes(const SVGAOverlayFormat format,    // IN
-                         uint32 *width,                     // IN / OUT
-                         uint32 *height,                    // IN / OUT
-                         uint32 *size,                      // OUT
-                         uint32 *pitches,                   // OUT (optional)
-                         uint32 *offsets)                   // OUT (optional)
+VMwareVideoGetAttributes(const SVGAOverlayFormat format,    /* IN */
+                         uint32 *width,                     /* IN / OUT */
+                         uint32 *height,                    /* IN / OUT */
+                         uint32 *size,                      /* OUT */
+                         uint32 *pitches,                   /* OUT (optional) */
+                         uint32 *offsets)                   /* OUT (optional) */
 {
     int tmp;
 
@@ -198,4 +198,4 @@ VMwareVideoGetAttributes(const SVGAOverl
     return true;
 }
 
-#endif // _SVGA_OVERLAY_H_
+#endif /* _SVGA_OVERLAY_H_ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_reg.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_reg.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/svga_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/svga_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,15 @@
 #define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
 
 /*
+ * SVGA_REG_ENABLE bit definitions.
+ */
+#define SVGA_REG_ENABLE_DISABLE     0
+#define SVGA_REG_ENABLE_ENABLE      1
+#define SVGA_REG_ENABLE_HIDE        2
+#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\
+				     SVGA_REG_ENABLE_HIDE)
+
+/*
  * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
  * cursor bypass mode. This is still supported, but no new guest
  * drivers should use it.
@@ -158,7 +167,9 @@ enum {
    SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
 
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
-   SVGA_REG_TOP = 46,               /* Must be 1 more than the last register */
+   SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
+   SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
+   SVGA_REG_TOP = 48,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
@@ -265,7 +276,7 @@ enum {
  * possible.
  */
 #define SVGA_GMR_NULL         ((uint32) -1)
-#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  // Guest Framebuffer (GFB)
+#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  /* Guest Framebuffer (GFB) */
 
 typedef
 struct SVGAGuestMemDescriptor {
@@ -306,13 +317,35 @@ struct SVGAGMRImageFormat {
       struct {
          uint32 bitsPerPixel : 8;
          uint32 colorDepth   : 8;
-         uint32 reserved     : 16;  // Must be zero
+         uint32 reserved     : 16;  /* Must be zero */
       };
 
       uint32 value;
    };
 } SVGAGMRImageFormat;
 
+typedef
+struct SVGAGuestImage {
+   SVGAGuestPtr         ptr;
+
+   /*
+    * A note on interpretation of pitch: This value of pitch is the
+    * number of bytes between vertically adjacent image
+    * blocks. Normally this is the number of bytes between the first
+    * pixel of two adjacent scanlines. With compressed textures,
+    * however, this may represent the number of bytes between
+    * compression blocks rather than between rows of pixels.
+    *
+    * XXX: Compressed textures currently must be tightly packed in guest memory.
+    *
+    * If the image is 1-dimensional, pitch is ignored.
+    *
+    * If 'pitch' is zero, the SVGA3D device calculates a pitch value
+    * assuming each row of blocks is tightly packed.
+    */
+   uint32 pitch;
+} SVGAGuestImage;
+
 /*
  * SVGAColorBGRX --
  *
@@ -328,7 +361,7 @@ struct SVGAColorBGRX {
          uint32 b : 8;
          uint32 g : 8;
          uint32 r : 8;
-         uint32 x : 8;  // Unused
+         uint32 x : 8;  /* Unused */
       };
 
       uint32 value;
@@ -370,23 +403,34 @@ struct SVGASignedPoint {
  *  Note the holes in the bitfield. Missing bits have been deprecated,
  *  and must not be reused. Those capabilities will never be reported
  *  by new versions of the SVGA device.
+ *
+ * SVGA_CAP_GMR2 --
+ *    Provides asynchronous commands to define and remap guest memory
+ *    regions.  Adds device registers SVGA_REG_GMRS_MAX_PAGES and
+ *    SVGA_REG_MEMORY_SIZE.
+ *
+ * SVGA_CAP_SCREEN_OBJECT_2 --
+ *    Allow screen object support, and require backing stores from the
+ *    guest for each screen object.
  */
 
 #define SVGA_CAP_NONE               0x00000000
 #define SVGA_CAP_RECT_COPY          0x00000002
 #define SVGA_CAP_CURSOR             0x00000020
-#define SVGA_CAP_CURSOR_BYPASS      0x00000040   // Legacy (Use Cursor Bypass 3 instead)
-#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_CURSOR_BYPASS      0x00000040   /* Legacy (Use Cursor Bypass 3 instead) */
+#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   /* Legacy (Use Cursor Bypass 3 instead) */
 #define SVGA_CAP_8BIT_EMULATION     0x00000100
 #define SVGA_CAP_ALPHA_CURSOR       0x00000200
 #define SVGA_CAP_3D                 0x00004000
 #define SVGA_CAP_EXTENDED_FIFO      0x00008000
-#define SVGA_CAP_MULTIMON           0x00010000   // Legacy multi-monitor support
+#define SVGA_CAP_MULTIMON           0x00010000   /* Legacy multi-monitor support */
 #define SVGA_CAP_PITCHLOCK          0x00020000
 #define SVGA_CAP_IRQMASK            0x00040000
-#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   // Legacy multi-monitor support
+#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   /* Legacy multi-monitor support */
 #define SVGA_CAP_GMR                0x00100000
 #define SVGA_CAP_TRACES             0x00200000
+#define SVGA_CAP_GMR2               0x00400000
+#define SVGA_CAP_SCREEN_OBJECT_2    0x00800000
 
 
 /*
@@ -431,7 +475,7 @@ enum {
 
    SVGA_FIFO_CAPABILITIES = 4,
    SVGA_FIFO_FLAGS,
-   // Valid with SVGA_FIFO_CAP_FENCE:
+   /* Valid with SVGA_FIFO_CAP_FENCE: */
    SVGA_FIFO_FENCE,
 
    /*
@@ -444,33 +488,47 @@ enum {
     * extended FIFO.
     */
 
-   // Valid if exists (i.e. if extended FIFO enabled):
+   /* Valid if exists (i.e. if extended FIFO enabled): */
    SVGA_FIFO_3D_HWVERSION,       /* See SVGA3dHardwareVersion in svga3d_reg.h */
-   // Valid with SVGA_FIFO_CAP_PITCHLOCK:
+   /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */
    SVGA_FIFO_PITCHLOCK,
 
-   // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3:
+   /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
    SVGA_FIFO_CURSOR_ON,          /* Cursor bypass 3 show/hide register */
    SVGA_FIFO_CURSOR_X,           /* Cursor bypass 3 x register */
    SVGA_FIFO_CURSOR_Y,           /* Cursor bypass 3 y register */
    SVGA_FIFO_CURSOR_COUNT,       /* Incremented when any of the other 3 change */
    SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
 
-   // Valid with SVGA_FIFO_CAP_RESERVE:
+   /* Valid with SVGA_FIFO_CAP_RESERVE: */
    SVGA_FIFO_RESERVED,           /* Bytes past NEXT_CMD with real contents */
 
    /*
-    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT:
+    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2:
     *
     * By default this is SVGA_ID_INVALID, to indicate that the cursor
     * coordinates are specified relative to the virtual root. If this
     * is set to a specific screen ID, cursor position is reinterpreted
-    * as a signed offset relative to that screen's origin. This is the
-    * only way to place the cursor on a non-rooted screen.
+    * as a signed offset relative to that screen's origin.
     */
    SVGA_FIFO_CURSOR_SCREEN_ID,
 
    /*
+    * Valid with SVGA_FIFO_CAP_DEAD
+    *
+    * An arbitrary value written by the host, drivers should not use it.
+    */
+   SVGA_FIFO_DEAD,
+
+   /*
+    * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED:
+    *
+    * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h)
+    * on platforms that can enforce graphics resource limits.
+    */
+   SVGA_FIFO_3D_HWVERSION_REVISED,
+
+   /*
     * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
     * registers, but this must be done carefully and with judicious use of
     * capability bits, since comparisons based on SVGA_FIFO_MIN aren't
@@ -508,7 +566,7 @@ enum {
     * sets SVGA_FIFO_MIN high enough to leave room for them.
     */
 
-   // Valid if register exists:
+   /* Valid if register exists: */
    SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
    SVGA_FIFO_FENCE_GOAL,         /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
    SVGA_FIFO_BUSY,               /* See "FIFO Synchronization Registers" */
@@ -709,6 +767,37 @@ enum {
  *
  *       - When a screen is resized, either using Screen Object commands or
  *         legacy multimon registers, its contents are preserved.
+ *
+ * SVGA_FIFO_CAP_GMR2 --
+ *
+ *    Provides new commands to define and remap guest memory regions (GMR).
+ *
+ *    New 2D commands:
+ *       DEFINE_GMR2, REMAP_GMR2.
+ *
+ * SVGA_FIFO_CAP_3D_HWVERSION_REVISED --
+ *
+ *    Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists.
+ *    This register may replace SVGA_FIFO_3D_HWVERSION on platforms
+ *    that enforce graphics resource limits.  This allows the platform
+ *    to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest
+ *    drivers that do not limit their resources.
+ *
+ *    Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators
+ *    are codependent (and thus we use a single capability bit).
+ *
+ * SVGA_FIFO_CAP_SCREEN_OBJECT_2 --
+ *
+ *    Modifies the DEFINE_SCREEN command to include a guest provided
+ *    backing store in GMR memory and the bytesPerLine for the backing
+ *    store.  This capability requires the use of a backing store when
+ *    creating screen objects.  However if SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    is present then backing stores are optional.
+ *
+ * SVGA_FIFO_CAP_DEAD --
+ *
+ *    Drivers should not use this cap bit.  This cap bit can not be
+ *    reused since some hosts already expose it.
  */
 
 #define SVGA_FIFO_CAP_NONE                  0
@@ -720,6 +809,10 @@ enum {
 #define SVGA_FIFO_CAP_ESCAPE            (1<<5)
 #define SVGA_FIFO_CAP_RESERVE           (1<<6)
 #define SVGA_FIFO_CAP_SCREEN_OBJECT     (1<<7)
+#define SVGA_FIFO_CAP_GMR2              (1<<8)
+#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED  SVGA_FIFO_CAP_GMR2
+#define SVGA_FIFO_CAP_SCREEN_OBJECT_2   (1<<9)
+#define SVGA_FIFO_CAP_DEAD              (1<<10)
 
 
 /*
@@ -730,7 +823,7 @@ enum {
 
 #define SVGA_FIFO_FLAG_NONE                 0
 #define SVGA_FIFO_FLAG_ACCELFRONT       (1<<0)
-#define SVGA_FIFO_FLAG_RESERVED        (1<<31) // Internal use only
+#define SVGA_FIFO_FLAG_RESERVED        (1<<31) /* Internal use only */
 
 /*
  * FIFO reservation sentinel value
@@ -763,22 +856,22 @@ enum {
    SVGA_VIDEO_DATA_OFFSET,
    SVGA_VIDEO_FORMAT,
    SVGA_VIDEO_COLORKEY,
-   SVGA_VIDEO_SIZE,          // Deprecated
+   SVGA_VIDEO_SIZE,          /* Deprecated */
    SVGA_VIDEO_WIDTH,
    SVGA_VIDEO_HEIGHT,
    SVGA_VIDEO_SRC_X,
    SVGA_VIDEO_SRC_Y,
    SVGA_VIDEO_SRC_WIDTH,
    SVGA_VIDEO_SRC_HEIGHT,
-   SVGA_VIDEO_DST_X,         // Signed int32
-   SVGA_VIDEO_DST_Y,         // Signed int32
+   SVGA_VIDEO_DST_X,         /* Signed int32 */
+   SVGA_VIDEO_DST_Y,         /* Signed int32 */
    SVGA_VIDEO_DST_WIDTH,
    SVGA_VIDEO_DST_HEIGHT,
    SVGA_VIDEO_PITCH_1,
    SVGA_VIDEO_PITCH_2,
    SVGA_VIDEO_PITCH_3,
-   SVGA_VIDEO_DATA_GMRID,    // Optional, defaults to SVGA_GMR_FRAMEBUFFER
-   SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID)
+   SVGA_VIDEO_DATA_GMRID,    /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */
+   SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */
    SVGA_VIDEO_NUM_REGS
 };
 
@@ -829,15 +922,51 @@ typedef struct SVGAOverlayUnit {
  *    compatibility. New flags can be added, and the struct may grow,
  *    but existing fields must retain their meaning.
  *
+ *    Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of
+ *    a SVGAGuestPtr that is used to back the screen contents.  This
+ *    memory must come from the GFB.  The guest is not allowed to
+ *    access the memory and doing so will have undefined results.  The
+ *    backing store is required to be page aligned and the size is
+ *    padded to the next page boundry.  The number of pages is:
+ *       (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE
+ *
+ *    The pitch in the backingStore is required to be at least large
+ *    enough to hold a 32bbp scanline.  It is recommended that the
+ *    driver pad bytesPerLine for a potential performance win.
+ *
+ *    The cloneCount field is treated as a hint from the guest that
+ *    the user wants this display to be cloned, countCount times.  A
+ *    value of zero means no cloning should happen.
  */
 
-#define SVGA_SCREEN_HAS_ROOT    (1 << 0)  // Screen is present in the virtual coord space
-#define SVGA_SCREEN_IS_PRIMARY  (1 << 1)  // Guest considers this screen to be 'primary'
-#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)   // Guest is running a fullscreen app here
+#define SVGA_SCREEN_MUST_BE_SET     (1 << 0) /* Must be set or results undefined */
+#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */
+#define SVGA_SCREEN_IS_PRIMARY      (1 << 1) /* Guest considers this screen to be 'primary' */
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */
+
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2.  When the screen is
+ * deactivated the base layer is defined to lose all contents and
+ * become black.  When a screen is deactivated the backing store is
+ * optional.  When set backingPtr and bytesPerLine will be ignored.
+ */
+#define SVGA_SCREEN_DEACTIVATE  (1 << 3)
+
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2.  When this flag is set
+ * the screen contents will be outputted as all black to the user
+ * though the base layer contents is preserved.  The screen base layer
+ * can still be read and written to like normal though the no visible
+ * effect will be seen by the user.  When the flag is changed the
+ * screen will be blanked or redrawn to the current contents as needed
+ * without any extra commands from the driver.  This flag only has an
+ * effect when the screen is not deactivated.
+ */
+#define SVGA_SCREEN_BLANKING (1 << 4)
 
 typedef
 struct SVGAScreenObject {
-   uint32 structSize;   // sizeof(SVGAScreenObject)
+   uint32 structSize;   /* sizeof(SVGAScreenObject) */
    uint32 id;
    uint32 flags;
    struct {
@@ -847,7 +976,14 @@ struct SVGAScreenObject {
    struct {
       int32 x;
       int32 y;
-   } root;              // Only used if SVGA_SCREEN_HAS_ROOT is set.
+   } root;
+
+   /*
+    * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional
+    * with SVGA_FIFO_CAP_SCREEN_OBJECT.
+    */
+   SVGAGuestImage backingStore;
+   uint32 cloneCount;
 } SVGAScreenObject;
 
 
@@ -885,6 +1021,8 @@ typedef enum {
    SVGA_CMD_BLIT_SCREEN_TO_GMRFB  = 38,
    SVGA_CMD_ANNOTATION_FILL       = 39,
    SVGA_CMD_ANNOTATION_COPY       = 40,
+   SVGA_CMD_DEFINE_GMR2           = 41,
+   SVGA_CMD_REMAP_GMR2            = 42,
    SVGA_CMD_MAX
 } SVGAFifoCmdId;
 
@@ -920,7 +1058,7 @@ typedef enum {
  */
 
 typedef
-struct {
+struct SVGAFifoCmdUpdate {
    uint32 x;
    uint32 y;
    uint32 width;
@@ -939,7 +1077,7 @@ struct {
  */
 
 typedef
-struct {
+struct SVGAFifoCmdRectCopy {
    uint32 srcX;
    uint32 srcY;
    uint32 destX;
@@ -963,14 +1101,14 @@ struct {
  */
 
 typedef
-struct {
-   uint32 id;             // Reserved, must be zero.
+struct SVGAFifoCmdDefineCursor {
+   uint32 id;             /* Reserved, must be zero. */
    uint32 hotspotX;
    uint32 hotspotY;
    uint32 width;
    uint32 height;
-   uint32 andMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
-   uint32 xorMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   uint32 andMaskDepth;   /* Value must be 1 or equal to BITS_PER_PIXEL */
+   uint32 xorMaskDepth;   /* Value must be 1 or equal to BITS_PER_PIXEL */
    /*
     * Followed by scanline data for AND mask, then XOR mask.
     * Each scanline is padded to a 32-bit boundary.
@@ -992,8 +1130,8 @@ struct {
  */
 
 typedef
-struct {
-   uint32 id;             // Reserved, must be zero.
+struct SVGAFifoCmdDefineAlphaCursor {
+   uint32 id;             /* Reserved, must be zero. */
    uint32 hotspotX;
    uint32 hotspotY;
    uint32 width;
@@ -1015,7 +1153,7 @@ struct {
  */
 
 typedef
-struct {
+struct SVGAFifoCmdUpdateVerbose {
    uint32 x;
    uint32 y;
    uint32 width;
@@ -1040,13 +1178,13 @@ struct {
 #define  SVGA_ROP_COPY                    0x03
 
 typedef
-struct {
-   uint32 color;     // In the same format as the GFB
+struct SVGAFifoCmdFrontRopFill {
+   uint32 color;     /* In the same format as the GFB */
    uint32 x;
    uint32 y;
    uint32 width;
    uint32 height;
-   uint32 rop;       // Must be SVGA_ROP_COPY
+   uint32 rop;       /* Must be SVGA_ROP_COPY */
 } SVGAFifoCmdFrontRopFill;
 
 
@@ -1083,7 +1221,7 @@ struct {
  */
 
 typedef
-struct {
+struct SVGAFifoCmdEscape {
    uint32 nsid;
    uint32 size;
    /* followed by 'size' bytes of data */
@@ -1113,12 +1251,12 @@ struct {
  *    registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
 struct {
-   SVGAScreenObject screen;   // Variable-length according to version
+   SVGAScreenObject screen;   /* Variable-length according to version */
 } SVGAFifoCmdDefineScreen;
 
 
@@ -1129,7 +1267,7 @@ struct {
  *    re-use.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1182,7 +1320,7 @@ struct {
  *    GMRFB.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1219,7 +1357,7 @@ struct {
  *    SVGA_CMD_ANNOTATION_* commands for details.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1267,7 +1405,7 @@ struct {
  *    the time any subsequent FENCE commands are reached.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1302,7 +1440,7 @@ struct {
  *    user's display is being remoted over a network connection.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1334,7 +1472,7 @@ struct {
  *    undefined.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1343,4 +1481,72 @@ struct {
    uint32           srcScreenId;
 } SVGAFifoCmdAnnotationCopy;
 
+
+/*
+ * SVGA_CMD_DEFINE_GMR2 --
+ *
+ *    Define guest memory region v2.  See the description of GMRs above.
+ *
+ * Availability:
+ *    SVGA_CAP_GMR2
+ */
+
+typedef
+struct {
+   uint32 gmrId;
+   uint32 numPages;
+} SVGAFifoCmdDefineGMR2;
+
+
+/*
+ * SVGA_CMD_REMAP_GMR2 --
+ *
+ *    Remap guest memory region v2.  See the description of GMRs above.
+ *
+ *    This command allows guest to modify a portion of an existing GMR by
+ *    invalidating it or reassigning it to different guest physical pages.
+ *    The pages are identified by physical page number (PPN).  The pages
+ *    are assumed to be pinned and valid for DMA operations.
+ *
+ *    Description of command flags:
+ *
+ *    SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR.
+ *       The PPN list must not overlap with the remap region (this can be
+ *       handled trivially by referencing a separate GMR).  If flag is
+ *       disabled, PPN list is appended to SVGARemapGMR command.
+ *
+ *    SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise
+ *       it is in PPN32 format.
+ *
+ *    SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry.
+ *       A single PPN can be used to invalidate a portion of a GMR or
+ *       map it to to a single guest scratch page.
+ *
+ * Availability:
+ *    SVGA_CAP_GMR2
+ */
+
+typedef enum {
+   SVGA_REMAP_GMR2_PPN32         = 0,
+   SVGA_REMAP_GMR2_VIA_GMR       = (1 << 0),
+   SVGA_REMAP_GMR2_PPN64         = (1 << 1),
+   SVGA_REMAP_GMR2_SINGLE_PPN    = (1 << 2),
+} SVGARemapGMR2Flags;
+
+typedef
+struct {
+   uint32 gmrId;
+   SVGARemapGMR2Flags flags;
+   uint32 offsetPages; /* offset in pages to begin remap */
+   uint32 numPages; /* number of pages to remap */
+   /*
+    * Followed by additional data depending on SVGARemapGMR2Flags.
+    *
+    * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows.
+    * Otherwise an array of page descriptors in PPN32 or PPN64 format
+    * (according to flag SVGA_REMAP_GMR2_PPN64) follows.  If flag
+    * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry.
+    */
+} SVGAFifoCmdRemapGMR2;
+
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,10 @@ static uint32_t sys_placement_flags = TT
 static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR |
 	TTM_PL_FLAG_CACHED;
 
+static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
+	TTM_PL_FLAG_CACHED |
+	TTM_PL_FLAG_NO_EVICT;
+
 struct ttm_placement vmw_vram_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -56,6 +60,11 @@ static uint32_t vram_gmr_placement_flags
 	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
 };
 
+static uint32_t gmr_vram_placement_flags[] = {
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+};
+
 struct ttm_placement vmw_vram_gmr_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -65,6 +74,20 @@ struct ttm_placement vmw_vram_gmr_placem
 	.busy_placement = &gmr_placement_flags
 };
 
+static uint32_t vram_gmr_ne_placement_flags[] = {
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT,
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+};
+
+struct ttm_placement vmw_vram_gmr_ne_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 2,
+	.placement = vram_gmr_ne_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &gmr_ne_placement_flags
+};
+
 struct ttm_placement vmw_vram_sys_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -92,6 +115,30 @@ struct ttm_placement vmw_sys_placement =
 	.busy_placement = &sys_placement_flags
 };
 
+static uint32_t evictable_placement_flags[] = {
+	TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+};
+
+struct ttm_placement vmw_evictable_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 3,
+	.placement = evictable_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
+struct ttm_placement vmw_srf_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.num_busy_placement = 2,
+	.placement = &gmr_placement_flags,
+	.busy_placement = gmr_vram_placement_flags
+};
+
 struct vmw_ttm_backend {
 	struct ttm_backend backend;
 	struct page **pages;
@@ -274,39 +321,39 @@ static int vmw_ttm_fault_reserve_notify(
 
 static void *vmw_sync_obj_ref(void *sync_obj)
 {
-	return sync_obj;
+
+	return (void *)
+		vmw_fence_obj_reference((struct vmw_fence_obj *) sync_obj);
 }
 
 static void vmw_sync_obj_unref(void **sync_obj)
 {
-	*sync_obj = NULL;
+	vmw_fence_obj_unreference((struct vmw_fence_obj **) sync_obj);
 }
 
 static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-
-	mutex_lock(&dev_priv->hw_mutex);
-	vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
-	mutex_unlock(&dev_priv->hw_mutex);
+	vmw_fence_obj_flush((struct vmw_fence_obj *) sync_obj);
 	return 0;
 }
 
 static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-	uint32_t sequence = (unsigned long) sync_obj;
+	unsigned long flags = (unsigned long) sync_arg;
+	return	vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj,
+				       (uint32_t) flags);
 
-	return vmw_fence_signaled(dev_priv, sequence);
 }
 
 static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
 			     bool lazy, bool interruptible)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-	uint32_t sequence = (unsigned long) sync_obj;
+	unsigned long flags = (unsigned long) sync_arg;
 
-	return vmw_wait_fence(dev_priv, false, sequence, false, 3*HZ);
+	return vmw_fence_obj_wait((struct vmw_fence_obj *) sync_obj,
+				  (uint32_t) flags,
+				  lazy, interruptible,
+				  VMW_FENCE_WAIT_TIMEOUT);
 }
 
 struct ttm_bo_driver vmw_bo_driver = {
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,322 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "ttm/ttm_placement.h"
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+
+/**
+ * vmw_dmabuf_to_placement - Validate a buffer to placement.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo to avoid failures.
+ *
+ * Returns
+ *  -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
+			    struct vmw_dma_buffer *buf,
+			    struct ttm_placement *placement,
+			    bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	int ret;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+	ttm_bo_unreserve(bo);
+
+err:
+	ttm_write_unlock(&vmaster->lock);
+	return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+			      struct vmw_dma_buffer *buf,
+			      bool pin, bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_placement *placement;
+	int ret;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (pin)
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	/**
+	 * Put BO in VRAM if there is space, otherwise as a GMR.
+	 * If there is no space in VRAM and GMR ids are all used up,
+	 * start evicting GMRs to make room. If the DMA buffer can't be
+	 * used as a GMR, this will return -ENOMEM.
+	 */
+
+	if (pin)
+		placement = &vmw_vram_gmr_ne_placement;
+	else
+		placement = &vmw_vram_gmr_placement;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+	if (likely(ret == 0) || ret == -ERESTARTSYS)
+		goto err_unreserve;
+
+
+	/**
+	 * If that failed, try VRAM again, this time evicting
+	 * previous contents.
+	 */
+
+	if (pin)
+		placement = &vmw_vram_ne_placement;
+	else
+		placement = &vmw_vram_placement;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+err_unreserve:
+	ttm_bo_unreserve(bo);
+err:
+	ttm_write_unlock(&vmaster->lock);
+	return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram - Move a buffer to vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+		       struct vmw_dma_buffer *buf,
+		       bool pin, bool interruptible)
+{
+	struct ttm_placement *placement;
+
+	if (pin)
+		placement = &vmw_vram_ne_placement;
+	else
+		placement = &vmw_vram_placement;
+
+	return vmw_dmabuf_to_placement(dev_priv, buf,
+				       placement,
+				       interruptible);
+}
+
+/**
+ * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
+				struct vmw_dma_buffer *buf,
+				bool pin, bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_placement placement;
+	int ret = 0;
+
+	if (pin)
+		placement = vmw_vram_ne_placement;
+	else
+		placement = vmw_vram_placement;
+	placement.lpfn = bo->num_pages;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (pin)
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err_unlock;
+
+	/* Is this buffer already in vram but not at the start of it? */
+	if (bo->mem.mem_type == TTM_PL_VRAM &&
+	    bo->mem.start < bo->num_pages &&
+	    bo->mem.start > 0)
+		(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+				       false, false);
+
+	ret = ttm_bo_validate(bo, &placement, interruptible, false, false);
+
+	/* For some reason we didn't up at the start of vram */
+	WARN_ON(ret == 0 && bo->offset != 0);
+
+	ttm_bo_unreserve(bo);
+err_unlock:
+	ttm_write_unlock(&vmaster->lock);
+
+	return ret;
+}
+
+
+/**
+ * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to unpin.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_unpin(struct vmw_private *dev_priv,
+		     struct vmw_dma_buffer *buf,
+		     bool interruptible)
+{
+	/*
+	 * We could in theory early out if the buffer is
+	 * unpinned but we need to lock and reserve the buffer
+	 * anyways so we don't gain much by that.
+	 */
+	return vmw_dmabuf_to_placement(dev_priv, buf,
+				       &vmw_evictable_placement,
+				       interruptible);
+}
+
+
+/**
+ * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
+ * of a buffer.
+ *
+ * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
+ * @ptr: SVGAGuestPtr returning the result.
+ */
+void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
+			  SVGAGuestPtr *ptr)
+{
+	if (bo->mem.mem_type == TTM_PL_VRAM) {
+		ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
+		ptr->offset = bo->offset;
+	} else {
+		ptr->gmrId = bo->mem.start;
+		ptr->offset = 0;
+	}
+}
+
+
+/**
+ * vmw_bo_pin - Pin or unpin a buffer object without moving it.
+ *
+ * @bo: The buffer object. Must be reserved, and present either in VRAM
+ * or GMR memory.
+ * @pin: Whether to pin or unpin.
+ *
+ */
+void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
+{
+	uint32_t pl_flags;
+	struct ttm_placement placement;
+	uint32_t old_mem_type = bo->mem.mem_type;
+	int ret;
+
+	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(old_mem_type != TTM_PL_VRAM &&
+	       old_mem_type != VMW_PL_FLAG_GMR);
+
+	pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
+	if (pin)
+		pl_flags |= TTM_PL_FLAG_NO_EVICT;
+
+	memset(&placement, 0, sizeof(placement));
+	placement.num_placement = 1;
+	placement.placement = &pl_flags;
+
+	ret = ttm_bo_validate(bo, &placement, false, true, true);
+
+	BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  **************************************************************************/
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "vmwgfx_drv.h"
@@ -82,17 +83,31 @@
 #define DRM_IOCTL_VMW_EXECBUF					\
 	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_EXECBUF,		\
 		struct drm_vmw_execbuf_arg)
-#define DRM_IOCTL_VMW_FIFO_DEBUG				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FIFO_DEBUG,		\
-		 struct drm_vmw_fifo_debug_arg)
+#define DRM_IOCTL_VMW_GET_3D_CAP				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_GET_3D_CAP,		\
+		 struct drm_vmw_get_3d_cap_arg)
 #define DRM_IOCTL_VMW_FENCE_WAIT				\
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,		\
 		 struct drm_vmw_fence_wait_arg)
+#define DRM_IOCTL_VMW_FENCE_SIGNALED				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_SIGNALED,	\
+		 struct drm_vmw_fence_signaled_arg)
+#define DRM_IOCTL_VMW_FENCE_UNREF				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_UNREF,		\
+		 struct drm_vmw_fence_arg)
+#define DRM_IOCTL_VMW_FENCE_EVENT				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_EVENT,		\
+		 struct drm_vmw_fence_event_arg)
+#define DRM_IOCTL_VMW_PRESENT					\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT,		\
+		 struct drm_vmw_present_arg)
+#define DRM_IOCTL_VMW_PRESENT_READBACK				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK,	\
+		 struct drm_vmw_present_readback_arg)
 #define DRM_IOCTL_VMW_UPDATE_LAYOUT				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,	\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,	\
 		 struct drm_vmw_update_layout_arg)
 
-
 /**
  * The core DRM version of this macro doesn't account for
  * DRM_COMMAND_BASE.
@@ -135,12 +150,28 @@ static struct drm_ioctl_desc vmw_ioctls[
 		      DRM_AUTH | DRM_UNLOCKED),
 	VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
-		      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+	VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
-		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
+	VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
+		      vmw_fence_obj_signaled_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_FENCE_EVENT,
+		      vmw_fence_event_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+
+	/* these allow direct access to the framebuffers mark as master only */
+	VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
+		      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
+		      vmw_present_readback_ioctl,
+		      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
+		      vmw_kms_update_layout_ioctl,
+		      DRM_MASTER | DRM_UNLOCKED),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -189,8 +220,78 @@ static void vmw_print_capabilities(uint3
 		DRM_INFO("  GMR.\n");
 	if (capabilities & SVGA_CAP_TRACES)
 		DRM_INFO("  Traces.\n");
+	if (capabilities & SVGA_CAP_GMR2)
+		DRM_INFO("  GMR2.\n");
+	if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
+		DRM_INFO("  Screen Object 2.\n");
+}
+
+
+/**
+ * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at
+ * the start of a buffer object.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function will idle the buffer using an uninterruptible wait, then
+ * map the first page and initialize a pending occlusion query result structure,
+ * Finally it will unmap the buffer.
+ *
+ * TODO: Since we're only mapping a single page, we should optimize the map
+ * to use kmap_atomic / iomap_atomic.
+ */
+static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
+{
+	struct ttm_bo_kmap_obj map;
+	volatile SVGA3dQueryResult *result;
+	bool dummy;
+	int ret;
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+
+	ttm_bo_reserve(bo, false, false, false, 0);
+	spin_lock(&bdev->fence_lock);
+	ret = ttm_bo_wait(bo, false, false, false);
+	spin_unlock(&bdev->fence_lock);
+	if (unlikely(ret != 0))
+		(void) vmw_fallback_wait(dev_priv, false, true, 0, false,
+					 10*HZ);
+
+	ret = ttm_bo_kmap(bo, 0, 1, &map);
+	if (likely(ret == 0)) {
+		result = ttm_kmap_obj_virtual(&map, &dummy);
+		result->totalSize = sizeof(*result);
+		result->state = SVGA3D_QUERYSTATE_PENDING;
+		result->result32 = 0xff;
+		ttm_bo_kunmap(&map);
+	} else
+		DRM_ERROR("Dummy query buffer map failed.\n");
+	ttm_bo_unreserve(bo);
+}
+
+
+/**
+ * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
+ *
+ * @dev_priv: A device private structure.
+ *
+ * This function creates a small buffer object that holds the query
+ * result for dummy queries emitted as query barriers.
+ * No interruptible waits are done within this function.
+ *
+ * Returns an error if bo creation fails.
+ */
+static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
+{
+	return ttm_bo_create(&dev_priv->bdev,
+			     PAGE_SIZE,
+			     ttm_bo_type_device,
+			     &vmw_vram_sys_placement,
+			     0, 0, false, NULL,
+			     &dev_priv->dummy_query_bo);
 }
 
+
 static int vmw_request_device(struct vmw_private *dev_priv)
 {
 	int ret;
@@ -200,16 +301,42 @@ static int vmw_request_device(struct vmw
 		DRM_ERROR("Unable to initialize FIFO.\n");
 		return ret;
 	}
+	vmw_fence_fifo_up(dev_priv->fman);
+	ret = vmw_dummy_query_bo_create(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_no_query_bo;
+	vmw_dummy_query_bo_prepare(dev_priv);
 
 	return 0;
+
+out_no_query_bo:
+	vmw_fence_fifo_down(dev_priv->fman);
+	vmw_fifo_release(dev_priv, &dev_priv->fifo);
+	return ret;
 }
 
 static void vmw_release_device(struct vmw_private *dev_priv)
 {
+	/*
+	 * Previous destructions should've released
+	 * the pinned bo.
+	 */
+
+	BUG_ON(dev_priv->pinned_bo != NULL);
+
+	ttm_bo_unref(&dev_priv->dummy_query_bo);
+	vmw_fence_fifo_down(dev_priv->fman);
 	vmw_fifo_release(dev_priv, &dev_priv->fifo);
 }
 
-int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+/**
+ * Increase the 3d resource refcount.
+ * If the count was prevously zero, initialize the fifo, switching to svga
+ * mode. Note that the master holds a ref as well, and may request an
+ * explicit switch to svga mode if fb is not running, using @unhide_svga.
+ */
+int vmw_3d_resource_inc(struct vmw_private *dev_priv,
+			bool unhide_svga)
 {
 	int ret = 0;
 
@@ -218,19 +345,42 @@ int vmw_3d_resource_inc(struct vmw_priva
 		ret = vmw_request_device(dev_priv);
 		if (unlikely(ret != 0))
 			--dev_priv->num_3d_resources;
+	} else if (unhide_svga) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_ENABLE,
+			  vmw_read(dev_priv, SVGA_REG_ENABLE) &
+			  ~SVGA_REG_ENABLE_HIDE);
+		mutex_unlock(&dev_priv->hw_mutex);
 	}
+
 	mutex_unlock(&dev_priv->release_mutex);
 	return ret;
 }
 
-
-void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+/**
+ * Decrease the 3d resource refcount.
+ * If the count reaches zero, disable the fifo, switching to vga mode.
+ * Note that the master holds a refcount as well, and may request an
+ * explicit switch to vga mode when it releases its refcount to account
+ * for the situation of an X server vt switch to VGA with 3d resources
+ * active.
+ */
+void vmw_3d_resource_dec(struct vmw_private *dev_priv,
+			 bool hide_svga)
 {
 	int32_t n3d;
 
 	mutex_lock(&dev_priv->release_mutex);
 	if (unlikely(--dev_priv->num_3d_resources == 0))
 		vmw_release_device(dev_priv);
+	else if (hide_svga) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_ENABLE,
+			  vmw_read(dev_priv, SVGA_REG_ENABLE) |
+			  SVGA_REG_ENABLE_HIDE);
+		mutex_unlock(&dev_priv->hw_mutex);
+	}
+
 	n3d = (int32_t) dev_priv->num_3d_resources;
 	mutex_unlock(&dev_priv->release_mutex);
 
@@ -252,7 +402,7 @@ static int vmw_driver_load(struct drm_de
 
 	dev_priv->dev = dev;
 	dev_priv->vmw_chipset = chipset;
-	dev_priv->last_read_sequence = (uint32_t) -100;
+	dev_priv->last_read_seqno = (uint32_t) -100;
 	mutex_init(&dev_priv->hw_mutex);
 	mutex_init(&dev_priv->cmdbuf_mutex);
 	mutex_init(&dev_priv->release_mutex);
@@ -263,8 +413,10 @@ static int vmw_driver_load(struct drm_de
 	mutex_init(&dev_priv->init_mutex);
 	init_waitqueue_head(&dev_priv->fence_queue);
 	init_waitqueue_head(&dev_priv->fifo_queue);
-	atomic_set(&dev_priv->fence_queue_waiters, 0);
+	dev_priv->fence_queue_waiters = 0;
 	atomic_set(&dev_priv->fifo_queue_waiters, 0);
+	INIT_LIST_HEAD(&dev_priv->surface_lru);
+	dev_priv->used_memory_size = 0;
 
 	dev_priv->io_start = pci_resource_start(dev->pdev, 0);
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
@@ -285,6 +437,10 @@ static int vmw_driver_load(struct drm_de
 
 	dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
 
+	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
+	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
+	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
+	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
 	if (dev_priv->capabilities & SVGA_CAP_GMR) {
 		dev_priv->max_gmr_descriptors =
 			vmw_read(dev_priv,
@@ -292,11 +448,19 @@ static int vmw_driver_load(struct drm_de
 		dev_priv->max_gmr_ids =
 			vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
 	}
-
-	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
-	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
-	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
-	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+	if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+		dev_priv->max_gmr_pages =
+			vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES);
+		dev_priv->memory_size =
+			vmw_read(dev_priv, SVGA_REG_MEMORY_SIZE);
+		dev_priv->memory_size -= dev_priv->vram_size;
+	} else {
+		/*
+		 * An arbitrary limit of 512MiB on surface
+		 * memory. But all HWV8 hardware supports GMR2.
+		 */
+		dev_priv->memory_size = 512*1024*1024;
+	}
 
 	mutex_unlock(&dev_priv->hw_mutex);
 
@@ -308,6 +472,12 @@ static int vmw_driver_load(struct drm_de
 		DRM_INFO("Max GMR descriptors is %u\n",
 			 (unsigned)dev_priv->max_gmr_descriptors);
 	}
+	if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+		DRM_INFO("Max number of GMR pages is %u\n",
+			 (unsigned)dev_priv->max_gmr_pages);
+		DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
+			 (unsigned)dev_priv->memory_size / 1024);
+	}
 	DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
 		 dev_priv->vram_start, dev_priv->vram_size / 1024);
 	DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
@@ -394,22 +564,34 @@ static int vmw_driver_load(struct drm_de
 			goto out_no_device;
 		}
 	}
+
+	dev_priv->fman = vmw_fence_manager_init(dev_priv);
+	if (unlikely(dev_priv->fman == NULL))
+		goto out_no_fman;
+
+	/* Need to start the fifo to check if we can do screen objects */
+	ret = vmw_3d_resource_inc(dev_priv, true);
+	if (unlikely(ret != 0))
+		goto out_no_fifo;
+	vmw_kms_save_vga(dev_priv);
+
+	/* Start kms and overlay systems, needs fifo. */
 	ret = vmw_kms_init(dev_priv);
 	if (unlikely(ret != 0))
 		goto out_no_kms;
 	vmw_overlay_init(dev_priv);
+
+	/* 3D Depends on Screen Objects being used. */
+	DRM_INFO("Detected %sdevice 3D availability.\n",
+		 vmw_fifo_have_3d(dev_priv) ?
+		 "" : "no ");
+
+	/* We might be done with the fifo now */
 	if (dev_priv->enable_fb) {
-		ret = vmw_3d_resource_inc(dev_priv);
-		if (unlikely(ret != 0))
-			goto out_no_fifo;
-		vmw_kms_save_vga(dev_priv);
 		vmw_fb_init(dev_priv);
-		DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
-			 "Detected device 3D availability.\n" :
-			 "Detected no device 3D availability.\n");
 	} else {
-		DRM_INFO("Delayed 3D detection since we're not "
-			 "running the device in SVGA mode yet.\n");
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
@@ -426,15 +608,19 @@ static int vmw_driver_load(struct drm_de
 	return 0;
 
 out_no_irq:
-	if (dev_priv->enable_fb) {
+	if (dev_priv->enable_fb)
 		vmw_fb_close(dev_priv);
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
-	}
-out_no_fifo:
 	vmw_overlay_close(dev_priv);
 	vmw_kms_close(dev_priv);
 out_no_kms:
+	/* We still have a 3D resource reference held */
+	if (dev_priv->enable_fb) {
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, false);
+	}
+out_no_fifo:
+	vmw_fence_manager_takedown(dev_priv->fman);
+out_no_fman:
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -467,15 +653,18 @@ static int vmw_driver_unload(struct drm_
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
+	if (dev_priv->ctx.cmd_bounce)
+		vfree(dev_priv->ctx.cmd_bounce);
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
 		drm_irq_uninstall(dev_priv->dev);
 	if (dev_priv->enable_fb) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, false);
 	}
 	vmw_kms_close(dev_priv);
 	vmw_overlay_close(dev_priv);
+	vmw_fence_manager_takedown(dev_priv->fman);
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -646,7 +835,7 @@ static int vmw_master_set(struct drm_dev
 	int ret = 0;
 
 	if (!dev_priv->enable_fb) {
-		ret = vmw_3d_resource_inc(dev_priv);
+		ret = vmw_3d_resource_inc(dev_priv, true);
 		if (unlikely(ret != 0))
 			return ret;
 		vmw_kms_save_vga(dev_priv);
@@ -688,7 +877,7 @@ out_no_active_lock:
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 	return ret;
 }
@@ -709,7 +898,7 @@ static void vmw_master_drop(struct drm_d
 
 	vmw_fp->locked_master = drm_master_get(file_priv->master);
 	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
-	vmw_kms_idle_workqueues(vmaster);
+	vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
 
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
@@ -726,7 +915,7 @@ static void vmw_master_drop(struct drm_d
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 
 	dev_priv->active_master = &dev_priv->fbdev_master;
@@ -761,6 +950,7 @@ static int vmwgfx_pm_notifier(struct not
 		 * This empties VRAM and unbinds all GMR bindings.
 		 * Buffer contents is moved to swappable memory.
 		 */
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
 		ttm_bo_swapout_all(&dev_priv->bdev);
 
 		break;
@@ -835,7 +1025,7 @@ static int vmw_pm_prepare(struct device
 	 */
 	dev_priv->suspended = true;
 	if (dev_priv->enable_fb)
-		vmw_3d_resource_dec(dev_priv);
+			vmw_3d_resource_dec(dev_priv, true);
 
 	if (dev_priv->num_3d_resources != 0) {
 
@@ -843,7 +1033,7 @@ static int vmw_pm_prepare(struct device
 			 "while 3D resources are active.\n");
 
 		if (dev_priv->enable_fb)
-			vmw_3d_resource_inc(dev_priv);
+			vmw_3d_resource_inc(dev_priv, true);
 		dev_priv->suspended = false;
 		return -EBUSY;
 	}
@@ -862,7 +1052,7 @@ static void vmw_pm_complete(struct devic
 	 * start fifo.
 	 */
 	if (dev_priv->enable_fb)
-		vmw_3d_resource_inc(dev_priv);
+			vmw_3d_resource_inc(dev_priv, false);
 
 	dev_priv->suspended = false;
 }
@@ -886,6 +1076,8 @@ static struct drm_driver driver = {
 	.irq_uninstall = vmw_irq_uninstall,
 	.irq_handler = vmw_irq_handler,
 	.get_vblank_counter = vmw_get_vblank_counter,
+	.enable_vblank = vmw_enable_vblank,
+	.disable_vblank = vmw_disable_vblank,
 	.reclaim_buffers_locked = NULL,
 	.ioctls = vmw_ioctls,
 	.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
@@ -902,7 +1094,8 @@ static struct drm_driver driver = {
 		 .release = drm_release,
 		 .unlocked_ioctl = vmw_unlocked_ioctl,
 		 .mmap = vmw_mmap,
-		 .poll = drm_poll,
+		 .poll = vmw_fops_poll,
+		 .read = vmw_fops_read,
 		 .fasync = drm_fasync,
 #if defined(CONFIG_COMPAT)
 		 .compat_ioctl = drm_compat_ioctl,
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -38,20 +38,27 @@
 #include "ttm/ttm_lock.h"
 #include "ttm/ttm_execbuf_util.h"
 #include "ttm/ttm_module.h"
+#include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20100927"
-#define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 4
+#define VMWGFX_DRIVER_DATE "20111025"
+#define VMWGFX_DRIVER_MAJOR 2
+#define VMWGFX_DRIVER_MINOR 3
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_RELOCATIONS 2048
-#define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_VALIDATIONS 2048
 #define VMWGFX_MAX_DISPLAYS 16
+#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
 
 #define VMW_PL_GMR TTM_PL_PRIV0
 #define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
 
+#define VMW_RES_CONTEXT ttm_driver_type0
+#define VMW_RES_SURFACE ttm_driver_type1
+#define VMW_RES_STREAM ttm_driver_type2
+#define VMW_RES_FENCE ttm_driver_type3
+
 struct vmw_fpriv {
 	struct drm_master *locked_master;
 	struct ttm_object_file *tfile;
@@ -72,9 +79,11 @@ struct vmw_resource {
 	int id;
 	enum ttm_object_type res_type;
 	bool avail;
+	void (*remove_from_lists) (struct vmw_resource *res);
 	void (*hw_destroy) (struct vmw_resource *res);
 	void (*res_free) (struct vmw_resource *res);
-
+	struct list_head validate_head;
+	struct list_head query_head; /* Protected by the cmdbuf mutex */
 	/* TODO is a generic snooper needed? */
 #if 0
 	void (*snoop)(struct vmw_resource *res,
@@ -90,8 +99,12 @@ struct vmw_cursor_snooper {
 	uint32_t *image;
 };
 
+struct vmw_framebuffer;
+struct vmw_surface_offset;
+
 struct vmw_surface {
 	struct vmw_resource res;
+	struct list_head lru_head; /* Protected by the resource lock */
 	uint32_t flags;
 	uint32_t format;
 	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
@@ -102,9 +115,12 @@ struct vmw_surface {
 
 	/* TODO so far just a extra pointer */
 	struct vmw_cursor_snooper snooper;
+	struct ttm_buffer_object *backup;
+	struct vmw_surface_offset *offsets;
+	uint32_t backup_size;
 };
 
-struct vmw_fence_queue {
+struct vmw_marker_queue {
 	struct list_head head;
 	struct timespec lag;
 	struct timespec lag_time;
@@ -115,16 +131,12 @@ struct vmw_fifo_state {
 	unsigned long reserved_size;
 	__le32 *dynamic_buffer;
 	__le32 *static_buffer;
-	__le32 *last_buffer;
-	uint32_t last_data_size;
-	uint32_t last_buffer_size;
-	bool last_buffer_add;
 	unsigned long static_buffer_size;
 	bool using_bounce_buffer;
 	uint32_t capabilities;
 	struct mutex fifo_mutex;
 	struct rw_semaphore rwsem;
-	struct vmw_fence_queue fence_queue;
+	struct vmw_marker_queue marker_queue;
 };
 
 struct vmw_relocation {
@@ -136,6 +148,8 @@ struct vmw_sw_context{
 	struct ida bo_list;
 	uint32_t last_cid;
 	bool cid_valid;
+	bool kernel; /**< is the called made from the kernel */
+	struct vmw_resource *cur_ctx;
 	uint32_t last_sid;
 	uint32_t sid_translation;
 	bool sid_valid;
@@ -143,8 +157,16 @@ struct vmw_sw_context{
 	struct list_head validate_nodes;
 	struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
 	uint32_t cur_reloc;
-	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
+	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
 	uint32_t cur_val_buf;
+	uint32_t *cmd_bounce;
+	uint32_t cmd_bounce_size;
+	struct list_head resource_list;
+	uint32_t fence_flags;
+	struct list_head query_list;
+	struct ttm_buffer_object *cur_query_bo;
+	uint32_t cur_query_cid;
+	bool query_cid_valid;
 };
 
 struct vmw_legacy_display;
@@ -185,6 +207,8 @@ struct vmw_private {
 	uint32_t capabilities;
 	uint32_t max_gmr_descriptors;
 	uint32_t max_gmr_ids;
+	uint32_t max_gmr_pages;
+	uint32_t memory_size;
 	bool has_gmr;
 	struct mutex hw_mutex;
 
@@ -195,12 +219,7 @@ struct vmw_private {
 	struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
 	uint32_t vga_width;
 	uint32_t vga_height;
-	uint32_t vga_depth;
 	uint32_t vga_bpp;
-	uint32_t vga_pseudo;
-	uint32_t vga_red_mask;
-	uint32_t vga_green_mask;
-	uint32_t vga_blue_mask;
 	uint32_t vga_bpl;
 	uint32_t vga_pitchlock;
 
@@ -212,6 +231,7 @@ struct vmw_private {
 
 	void *fb_info;
 	struct vmw_legacy_display *ldu_priv;
+	struct vmw_screen_object_display *sou_priv;
 	struct vmw_overlay *overlay_priv;
 
 	/*
@@ -240,13 +260,16 @@ struct vmw_private {
 	 * Fencing and IRQs.
 	 */
 
-	atomic_t fence_seq;
+	atomic_t marker_seq;
 	wait_queue_head_t fence_queue;
 	wait_queue_head_t fifo_queue;
-	atomic_t fence_queue_waiters;
+	int fence_queue_waiters; /* Protected by hw_mutex */
+	int goal_queue_waiters; /* Protected by hw_mutex */
 	atomic_t fifo_queue_waiters;
-	uint32_t last_read_sequence;
+	uint32_t last_read_seqno;
 	spinlock_t irq_lock;
+	struct vmw_fence_manager *fman;
+	uint32_t irq_mask;
 
 	/*
 	 * Device state
@@ -285,6 +308,26 @@ struct vmw_private {
 
 	struct mutex release_mutex;
 	uint32_t num_3d_resources;
+
+	/*
+	 * Query processing. These members
+	 * are protected by the cmdbuf mutex.
+	 */
+
+	struct ttm_buffer_object *dummy_query_bo;
+	struct ttm_buffer_object *pinned_bo;
+	uint32_t query_cid;
+	bool dummy_query_bo_pinned;
+
+	/*
+	 * Surface swapping. The "surface_lru" list is protected by the
+	 * resource lock in order to be able to destroy a surface and take
+	 * it off the lru atomically. "used_memory_size" is currently
+	 * protected by the cmdbuf mutex for simplicity.
+	 */
+
+	struct list_head surface_lru;
+	uint32_t used_memory_size;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,8 +362,8 @@ static inline uint32_t vmw_read(struct v
 	return val;
 }
 
-int vmw_3d_resource_inc(struct vmw_private *dev_priv);
-void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+int vmw_3d_resource_inc(struct vmw_private *dev_priv, bool unhide_svga);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv, bool hide_svga);
 
 /**
  * GMR utilities - vmwgfx_gmr.c
@@ -345,7 +388,13 @@ extern int vmw_context_define_ioctl(stru
 				    struct drm_file *file_priv);
 extern int vmw_context_check(struct vmw_private *dev_priv,
 			     struct ttm_object_file *tfile,
-			     int id);
+			     int id,
+			     struct vmw_resource **p_res);
+extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
+				  struct ttm_object_file *tfile,
+				  uint32_t handle,
+				  struct vmw_surface **out_surf,
+				  struct vmw_dma_buffer **out_buf);
 extern void vmw_surface_res_free(struct vmw_resource *res);
 extern int vmw_surface_init(struct vmw_private *dev_priv,
 			    struct vmw_surface *srf,
@@ -363,6 +412,8 @@ extern int vmw_surface_reference_ioctl(s
 extern int vmw_surface_check(struct vmw_private *dev_priv,
 			     struct ttm_object_file *tfile,
 			     uint32_t handle, int *id);
+extern int vmw_surface_validate(struct vmw_private *dev_priv,
+				struct vmw_surface *srf);
 extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
 extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
 			   struct vmw_dma_buffer *vmw_bo,
@@ -378,10 +429,6 @@ extern uint32_t vmw_dmabuf_validate_node
 extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
 extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 				  uint32_t id, struct vmw_dma_buffer **out);
-extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
-				       struct vmw_dma_buffer *bo);
-extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
-				struct vmw_dma_buffer *bo);
 extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv);
 extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -390,7 +437,30 @@ extern int vmw_user_stream_lookup(struct
 				  struct ttm_object_file *tfile,
 				  uint32_t *inout_id,
 				  struct vmw_resource **out);
+extern void vmw_resource_unreserve(struct list_head *list);
 
+/**
+ * DMA buffer helper routines - vmwgfx_dmabuf.c
+ */
+extern int vmw_dmabuf_to_placement(struct vmw_private *vmw_priv,
+				   struct vmw_dma_buffer *bo,
+				   struct ttm_placement *placement,
+				   bool interruptible);
+extern int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+			      struct vmw_dma_buffer *buf,
+			      bool pin, bool interruptible);
+extern int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+				     struct vmw_dma_buffer *buf,
+				     bool pin, bool interruptible);
+extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				       struct vmw_dma_buffer *bo,
+				       bool pin, bool interruptible);
+extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv,
+			    struct vmw_dma_buffer *bo,
+			    bool interruptible);
+extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf,
+				 SVGAGuestPtr *ptr);
+extern void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin);
 
 /**
  * Misc Ioctl functionality - vmwgfx_ioctl.c
@@ -398,8 +468,16 @@ extern int vmw_user_stream_lookup(struct
 
 extern int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
-extern int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+extern int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+extern int vmw_present_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+				      struct drm_file *file_priv);
+extern unsigned int vmw_fops_poll(struct file *filp,
+				  struct poll_table_struct *wait);
+extern ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+			     size_t count, loff_t *offset);
 
 /**
  * Fifo utilities - vmwgfx_fifo.c
@@ -412,11 +490,12 @@ extern void vmw_fifo_release(struct vmw_
 extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes);
 extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes);
 extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
-			       uint32_t *sequence);
+			       uint32_t *seqno);
 extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
-extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
 extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
 extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
+extern int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+				     uint32_t cid);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
@@ -434,7 +513,10 @@ extern struct ttm_placement vmw_vram_pla
 extern struct ttm_placement vmw_vram_ne_placement;
 extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_vram_gmr_placement;
+extern struct ttm_placement vmw_vram_gmr_ne_placement;
 extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_placement vmw_evictable_placement;
+extern struct ttm_placement vmw_srf_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
 
@@ -444,45 +526,70 @@ extern int vmw_dma_quiescent(struct drm_
 
 extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv);
+extern int vmw_execbuf_process(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       void __user *user_commands,
+			       void *kernel_commands,
+			       uint32_t command_size,
+			       uint64_t throttle_us,
+			       struct drm_vmw_fence_rep __user
+			       *user_fence_rep);
+
+extern void
+vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+			      bool only_on_cid_match, uint32_t cid);
+
+extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+				      struct vmw_private *dev_priv,
+				      struct vmw_fence_obj **p_fence,
+				      uint32_t *p_handle);
+extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+					struct vmw_fpriv *vmw_fp,
+					int ret,
+					struct drm_vmw_fence_rep __user
+					*user_fence_rep,
+					struct vmw_fence_obj *fence,
+					uint32_t fence_handle);
 
 /**
  * IRQs and wating - vmwgfx_irq.c
  */
 
 extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
-extern int vmw_wait_fence(struct vmw_private *dev_priv, bool lazy,
-			  uint32_t sequence, bool interruptible,
-			  unsigned long timeout);
+extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy,
+			     uint32_t seqno, bool interruptible,
+			     unsigned long timeout);
 extern void vmw_irq_preinstall(struct drm_device *dev);
 extern int vmw_irq_postinstall(struct drm_device *dev);
 extern void vmw_irq_uninstall(struct drm_device *dev);
-extern bool vmw_fence_signaled(struct vmw_private *dev_priv,
-			       uint32_t sequence);
-extern int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv);
+extern bool vmw_seqno_passed(struct vmw_private *dev_priv,
+				uint32_t seqno);
 extern int vmw_fallback_wait(struct vmw_private *dev_priv,
 			     bool lazy,
 			     bool fifo_idle,
-			     uint32_t sequence,
+			     uint32_t seqno,
 			     bool interruptible,
 			     unsigned long timeout);
-extern void vmw_update_sequence(struct vmw_private *dev_priv,
+extern void vmw_update_seqno(struct vmw_private *dev_priv,
 				struct vmw_fifo_state *fifo_state);
-
+extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv);
 
 /**
- * Rudimentary fence objects currently used only for throttling -
- * vmwgfx_fence.c
+ * Rudimentary fence-like objects currently used only for throttling -
+ * vmwgfx_marker.c
  */
 
-extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
-extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
-extern int vmw_fence_push(struct vmw_fence_queue *queue,
-			  uint32_t sequence);
-extern int vmw_fence_pull(struct vmw_fence_queue *queue,
-			  uint32_t signaled_sequence);
+extern void vmw_marker_queue_init(struct vmw_marker_queue *queue);
+extern void vmw_marker_queue_takedown(struct vmw_marker_queue *queue);
+extern int vmw_marker_push(struct vmw_marker_queue *queue,
+			  uint32_t seqno);
+extern int vmw_marker_pull(struct vmw_marker_queue *queue,
+			  uint32_t signaled_seqno);
 extern int vmw_wait_lag(struct vmw_private *dev_priv,
-			struct vmw_fence_queue *queue, uint32_t us);
+			struct vmw_marker_queue *queue, uint32_t us);
 
 /**
  * Kernel framebuffer - vmwgfx_fb.c
@@ -508,16 +615,31 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 			  struct ttm_object_file *tfile,
 			  struct ttm_buffer_object *bo,
 			  SVGA3dCmdHeader *header);
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
-			unsigned width, unsigned height, unsigned pitch,
-			unsigned bbp, unsigned depth);
-int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv);
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
+		       unsigned width, unsigned height, unsigned pitch,
+		       unsigned bpp, unsigned depth);
 void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
 bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
 				uint32_t pitch,
 				uint32_t height);
 u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
+int vmw_enable_vblank(struct drm_device *dev, int crtc);
+void vmw_disable_vblank(struct drm_device *dev, int crtc);
+int vmw_kms_present(struct vmw_private *dev_priv,
+		    struct drm_file *file_priv,
+		    struct vmw_framebuffer *vfb,
+		    struct vmw_surface *surface,
+		    uint32_t sid, int32_t destX, int32_t destY,
+		    struct drm_vmw_rect *clips,
+		    uint32_t num_clips);
+int vmw_kms_readback(struct vmw_private *dev_priv,
+		     struct drm_file *file_priv,
+		     struct vmw_framebuffer *vfb,
+		     struct drm_vmw_fence_rep __user *user_fence_rep,
+		     struct drm_vmw_rect *clips,
+		     uint32_t num_clips);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
 
 /**
  * Overlay control - vmwgfx_overlay.c
@@ -576,4 +698,8 @@ static inline struct vmw_dma_buffer *vmw
 	return NULL;
 }
 
+static inline struct ttm_mem_global *vmw_mem_glob(struct vmw_private *dev_priv)
+{
+	return (struct ttm_mem_global *) dev_priv->mem_global_ref.object;
+}
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,71 @@ static int vmw_cmd_ok(struct vmw_private
 	return 0;
 }
 
+static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
+					  struct vmw_resource **p_res)
+{
+	struct vmw_resource *res = *p_res;
+
+	if (list_empty(&res->validate_head)) {
+		list_add_tail(&res->validate_head, &sw_context->resource_list);
+		*p_res = NULL;
+	} else
+		vmw_resource_unreference(p_res);
+}
+
+/**
+ * vmw_bo_to_validate_list - add a bo to a validate list
+ *
+ * @sw_context: The software context used for this command submission batch.
+ * @bo: The buffer object to add.
+ * @fence_flags: Fence flags to be or'ed with any other fence flags for
+ * this buffer on this submission batch.
+ * @p_val_node: If non-NULL Will be updated with the validate node number
+ * on return.
+ *
+ * Returns -EINVAL if the limit of number of buffer objects per command
+ * submission is reached.
+ */
+static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
+				   struct ttm_buffer_object *bo,
+				   uint32_t fence_flags,
+				   uint32_t *p_val_node)
+{
+	uint32_t val_node;
+	struct ttm_validate_buffer *val_buf;
+
+	val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
+
+	if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
+		DRM_ERROR("Max number of DMA buffers per submission"
+			  " exceeded.\n");
+		return -EINVAL;
+	}
+
+	val_buf = &sw_context->val_bufs[val_node];
+	if (unlikely(val_node == sw_context->cur_val_buf)) {
+		val_buf->new_sync_obj_arg = NULL;
+		val_buf->bo = ttm_bo_reference(bo);
+		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+		++sw_context->cur_val_buf;
+	}
+
+	val_buf->new_sync_obj_arg = (void *)
+		((unsigned long) val_buf->new_sync_obj_arg | fence_flags);
+	sw_context->fence_flags |= fence_flags;
+
+	if (p_val_node)
+		*p_val_node = val_node;
+
+	return 0;
+}
+
 static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
 			     SVGA3dCmdHeader *header)
 {
+	struct vmw_resource *ctx;
+
 	struct vmw_cid_cmd {
 		SVGA3dCmdHeader header;
 		__le32 cid;
@@ -58,7 +119,8 @@ static int vmw_cmd_cid_check(struct vmw_
 	if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
 		return 0;
 
-	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
+	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
+				&ctx);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Could not find or use context %u\n",
 			  (unsigned) cmd->cid);
@@ -67,6 +129,8 @@ static int vmw_cmd_cid_check(struct vmw_
 
 	sw_context->last_cid = cmd->cid;
 	sw_context->cid_valid = true;
+	sw_context->cur_ctx = ctx;
+	vmw_resource_to_validate_list(sw_context, &ctx);
 
 	return 0;
 }
@@ -75,29 +139,45 @@ static int vmw_cmd_sid_check(struct vmw_
 			     struct vmw_sw_context *sw_context,
 			     uint32_t *sid)
 {
+	struct vmw_surface *srf;
+	int ret;
+	struct vmw_resource *res;
+
 	if (*sid == SVGA3D_INVALID_ID)
 		return 0;
 
-	if (unlikely((!sw_context->sid_valid  ||
-		      *sid != sw_context->last_sid))) {
-		int real_id;
-		int ret = vmw_surface_check(dev_priv, sw_context->tfile,
-					    *sid, &real_id);
+	if (likely((sw_context->sid_valid  &&
+		      *sid == sw_context->last_sid))) {
+		*sid = sw_context->sid_translation;
+		return 0;
+	}
 
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Could ot find or use surface 0x%08x "
-				  "address 0x%08lx\n",
-				  (unsigned int) *sid,
-				  (unsigned long) sid);
-			return ret;
-		}
+	ret = vmw_user_surface_lookup_handle(dev_priv,
+					     sw_context->tfile,
+					     *sid, &srf);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could ot find or use surface 0x%08x "
+			  "address 0x%08lx\n",
+			  (unsigned int) *sid,
+			  (unsigned long) sid);
+		return ret;
+	}
 
-		sw_context->last_sid = *sid;
-		sw_context->sid_valid = true;
-		*sid = real_id;
-		sw_context->sid_translation = real_id;
-	} else
-		*sid = sw_context->sid_translation;
+	ret = vmw_surface_validate(dev_priv, srf);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Could not validate surface.\n");
+		vmw_surface_unreference(&srf);
+		return ret;
+	}
+
+	sw_context->last_sid = *sid;
+	sw_context->sid_valid = true;
+	sw_context->sid_translation = srf->res.id;
+	*sid = sw_context->sid_translation;
+
+	res = &srf->res;
+	vmw_resource_to_validate_list(sw_context, &res);
 
 	return 0;
 }
@@ -166,6 +246,12 @@ static int vmw_cmd_blt_surf_screen_check
 	} *cmd;
 
 	cmd = container_of(header, struct vmw_sid_cmd, header);
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+		return -EPERM;
+	}
+
 	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
 }
 
@@ -178,10 +264,179 @@ static int vmw_cmd_present_check(struct
 		SVGA3dCmdPresent body;
 	} *cmd;
 
+
 	cmd = container_of(header, struct vmw_sid_cmd, header);
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+		return -EPERM;
+	}
+
 	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
 }
 
+/**
+ * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context for the next query.
+ * @new_query_bo: The new buffer holding query results.
+ * @sw_context: The software context used for this command submission.
+ *
+ * This function checks whether @new_query_bo is suitable for holding
+ * query results, and if another buffer currently is pinned for query
+ * results. If so, the function prepares the state of @sw_context for
+ * switching pinned buffers after successful submission of the current
+ * command batch. It also checks whether we're using a new query context.
+ * In that case, it makes sure we emit a query barrier for the old
+ * context before the current query buffer is fenced.
+ */
+static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
+				       uint32_t cid,
+				       struct ttm_buffer_object *new_query_bo,
+				       struct vmw_sw_context *sw_context)
+{
+	int ret;
+	bool add_cid = false;
+	uint32_t cid_to_add;
+
+	if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
+
+		if (unlikely(new_query_bo->num_pages > 4)) {
+			DRM_ERROR("Query buffer too large.\n");
+			return -EINVAL;
+		}
+
+		if (unlikely(sw_context->cur_query_bo != NULL)) {
+			BUG_ON(!sw_context->query_cid_valid);
+			add_cid = true;
+			cid_to_add = sw_context->cur_query_cid;
+			ret = vmw_bo_to_validate_list(sw_context,
+						      sw_context->cur_query_bo,
+						      DRM_VMW_FENCE_FLAG_EXEC,
+						      NULL);
+			if (unlikely(ret != 0))
+				return ret;
+		}
+		sw_context->cur_query_bo = new_query_bo;
+
+		ret = vmw_bo_to_validate_list(sw_context,
+					      dev_priv->dummy_query_bo,
+					      DRM_VMW_FENCE_FLAG_EXEC,
+					      NULL);
+		if (unlikely(ret != 0))
+			return ret;
+
+	}
+
+	if (unlikely(cid != sw_context->cur_query_cid &&
+		     sw_context->query_cid_valid)) {
+		add_cid = true;
+		cid_to_add = sw_context->cur_query_cid;
+	}
+
+	sw_context->cur_query_cid = cid;
+	sw_context->query_cid_valid = true;
+
+	if (add_cid) {
+		struct vmw_resource *ctx = sw_context->cur_ctx;
+
+		if (list_empty(&ctx->query_head))
+			list_add_tail(&ctx->query_head,
+				      &sw_context->query_list);
+		ret = vmw_bo_to_validate_list(sw_context,
+					      dev_priv->dummy_query_bo,
+					      DRM_VMW_FENCE_FLAG_EXEC,
+					      NULL);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	return 0;
+}
+
+
+/**
+ * vmw_query_bo_switch_commit - Finalize switching pinned query buffer
+ *
+ * @dev_priv: The device private structure.
+ * @sw_context: The software context used for this command submission batch.
+ *
+ * This function will check if we're switching query buffers, and will then,
+ * if no other query waits are issued this command submission batch,
+ * issue a dummy occlusion query wait used as a query barrier. When the fence
+ * object following that query wait has signaled, we are sure that all
+ * preseding queries have finished, and the old query buffer can be unpinned.
+ * However, since both the new query buffer and the old one are fenced with
+ * that fence, we can do an asynchronus unpin now, and be sure that the
+ * old query buffer won't be moved until the fence has signaled.
+ *
+ * As mentioned above, both the new - and old query buffers need to be fenced
+ * using a sequence emitted *after* calling this function.
+ */
+static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
+				     struct vmw_sw_context *sw_context)
+{
+
+	struct vmw_resource *ctx, *next_ctx;
+	int ret;
+
+	/*
+	 * The validate list should still hold references to all
+	 * contexts here.
+	 */
+
+	list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list,
+				 query_head) {
+		list_del_init(&ctx->query_head);
+
+		BUG_ON(list_empty(&ctx->validate_head));
+
+		ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
+
+		if (unlikely(ret != 0))
+			DRM_ERROR("Out of fifo space for dummy query.\n");
+	}
+
+	if (dev_priv->pinned_bo != sw_context->cur_query_bo) {
+		if (dev_priv->pinned_bo) {
+			vmw_bo_pin(dev_priv->pinned_bo, false);
+			ttm_bo_unref(&dev_priv->pinned_bo);
+		}
+
+		vmw_bo_pin(sw_context->cur_query_bo, true);
+
+		/*
+		 * We pin also the dummy_query_bo buffer so that we
+		 * don't need to validate it when emitting
+		 * dummy queries in context destroy paths.
+		 */
+
+		vmw_bo_pin(dev_priv->dummy_query_bo, true);
+		dev_priv->dummy_query_bo_pinned = true;
+
+		dev_priv->query_cid = sw_context->cur_query_cid;
+		dev_priv->pinned_bo =
+			ttm_bo_reference(sw_context->cur_query_bo);
+	}
+}
+
+/**
+ * vmw_query_switch_backoff - clear query barrier list
+ * @sw_context: The sw context used for this submission batch.
+ *
+ * This function is used as part of an error path, where a previously
+ * set up list of query barriers needs to be cleared.
+ *
+ */
+static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
+{
+	struct list_head *list, *next;
+
+	list_for_each_safe(list, next, &sw_context->query_list) {
+		list_del_init(list);
+	}
+}
+
 static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
 				   struct vmw_sw_context *sw_context,
 				   SVGAGuestPtr *ptr,
@@ -191,8 +446,6 @@ static int vmw_translate_guest_ptr(struc
 	struct ttm_buffer_object *bo;
 	uint32_t handle = ptr->gmrId;
 	struct vmw_relocation *reloc;
-	uint32_t cur_validate_node;
-	struct ttm_validate_buffer *val_buf;
 	int ret;
 
 	ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
@@ -212,22 +465,11 @@ static int vmw_translate_guest_ptr(struc
 	reloc = &sw_context->relocs[sw_context->cur_reloc++];
 	reloc->location = ptr;
 
-	cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
-	if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
-		DRM_ERROR("Max number of DMA buffers per submission"
-			  " exceeded.\n");
-		ret = -EINVAL;
+	ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC,
+				      &reloc->index);
+	if (unlikely(ret != 0))
 		goto out_no_reloc;
-	}
 
-	reloc->index = cur_validate_node;
-	if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
-		val_buf = &sw_context->val_bufs[cur_validate_node];
-		val_buf->bo = ttm_bo_reference(bo);
-		val_buf->new_sync_obj_arg = (void *) dev_priv;
-		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
-		++sw_context->cur_val_buf;
-	}
 	*vmw_bo_p = vmw_bo;
 	return 0;
 
@@ -259,8 +501,11 @@ static int vmw_cmd_end_query(struct vmw_
 	if (unlikely(ret != 0))
 		return ret;
 
+	ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid,
+					  &vmw_bo->base, sw_context);
+
 	vmw_dmabuf_unreference(&vmw_bo);
-	return 0;
+	return ret;
 }
 
 static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
@@ -273,6 +518,7 @@ static int vmw_cmd_wait_query(struct vmw
 		SVGA3dCmdWaitForQuery q;
 	} *cmd;
 	int ret;
+	struct vmw_resource *ctx;
 
 	cmd = container_of(header, struct vmw_query_cmd, header);
 	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
@@ -286,10 +532,19 @@ static int vmw_cmd_wait_query(struct vmw
 		return ret;
 
 	vmw_dmabuf_unreference(&vmw_bo);
+
+	/*
+	 * This wait will act as a barrier for previous waits for this
+	 * context.
+	 */
+
+	ctx = sw_context->cur_ctx;
+	if (!list_empty(&ctx->query_head))
+		list_del_init(&ctx->query_head);
+
 	return 0;
 }
 
-
 static int vmw_cmd_dma(struct vmw_private *dev_priv,
 		       struct vmw_sw_context *sw_context,
 		       SVGA3dCmdHeader *header)
@@ -302,6 +557,7 @@ static int vmw_cmd_dma(struct vmw_privat
 		SVGA3dCmdSurfaceDMA dma;
 	} *cmd;
 	int ret;
+	struct vmw_resource *res;
 
 	cmd = container_of(header, struct vmw_dma_cmd, header);
 	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
@@ -318,18 +574,28 @@ static int vmw_cmd_dma(struct vmw_privat
 		goto out_no_reloc;
 	}
 
-	/**
+	ret = vmw_surface_validate(dev_priv, srf);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Culd not validate surface.\n");
+		goto out_no_validate;
+	}
+
+	/*
 	 * Patch command stream with device SID.
 	 */
-
 	cmd->dma.host.sid = srf->res.id;
 	vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
-	/**
-	 * FIXME: May deadlock here when called from the
-	 * command parsing code.
-	 */
-	vmw_surface_unreference(&srf);
 
+	vmw_dmabuf_unreference(&vmw_bo);
+
+	res = &srf->res;
+	vmw_resource_to_validate_list(sw_context, &res);
+
+	return 0;
+
+out_no_validate:
+	vmw_surface_unreference(&srf);
 out_no_reloc:
 	vmw_dmabuf_unreference(&vmw_bo);
 	return ret;
@@ -419,6 +685,71 @@ static int vmw_cmd_tex_state(struct vmw_
 	return 0;
 }
 
+static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
+				      struct vmw_sw_context *sw_context,
+				      void *buf)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	int ret;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd = buf;
+
+	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+				      &cmd->body.ptr,
+				      &vmw_bo);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_dmabuf_unreference(&vmw_bo);
+
+	return ret;
+}
+
+static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
+				struct vmw_sw_context *sw_context,
+				void *buf, uint32_t *size)
+{
+	uint32_t size_remaining = *size;
+	uint32_t cmd_id;
+
+	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+	switch (cmd_id) {
+	case SVGA_CMD_UPDATE:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate);
+		break;
+	case SVGA_CMD_DEFINE_GMRFB:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB);
+		break;
+	case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+		break;
+	case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+		break;
+	default:
+		DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id);
+		return -EINVAL;
+	}
+
+	if (*size > size_remaining) {
+		DRM_ERROR("Invalid SVGA command (size mismatch):"
+			  " %u.\n", cmd_id);
+		return -EINVAL;
+	}
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id);
+		return -EPERM;
+	}
+
+	if (cmd_id == SVGA_CMD_DEFINE_GMRFB)
+		return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf);
+
+	return 0;
+}
 
 typedef int (*vmw_cmd_func) (struct vmw_private *,
 			     struct vmw_sw_context *,
@@ -471,11 +802,11 @@ static int vmw_cmd_check(struct vmw_priv
 	SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
 	int ret;
 
-	cmd_id = ((uint32_t *)buf)[0];
-	if (cmd_id == SVGA_CMD_UPDATE) {
-		*size = 5 << 2;
-		return 0;
-	}
+	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+	/* Handle any none 3D commands */
+	if (unlikely(cmd_id < SVGA_CMD_MAX))
+		return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size);
+
 
 	cmd_id = le32_to_cpu(header->id);
 	*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
@@ -500,7 +831,8 @@ out_err:
 
 static int vmw_cmd_check_all(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
-			     void *buf, uint32_t size)
+			     void *buf,
+			     uint32_t size)
 {
 	int32_t cur_size = size;
 	int ret;
@@ -550,7 +882,11 @@ static void vmw_apply_relocations(struct
 static void vmw_clear_validations(struct vmw_sw_context *sw_context)
 {
 	struct ttm_validate_buffer *entry, *next;
+	struct vmw_resource *res, *res_next;
 
+	/*
+	 * Drop references to DMA buffers held during command submission.
+	 */
 	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
 				 head) {
 		list_del(&entry->head);
@@ -559,6 +895,16 @@ static void vmw_clear_validations(struct
 		sw_context->cur_val_buf--;
 	}
 	BUG_ON(sw_context->cur_val_buf != 0);
+
+	/*
+	 * Drop references to resources held during command submission.
+	 */
+	vmw_resource_unreserve(&sw_context->resource_list);
+	list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
+				 validate_head) {
+		list_del_init(&res->validate_head);
+		vmw_resource_unreference(&res);
+	}
 }
 
 static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
@@ -566,6 +912,16 @@ static int vmw_validate_single_buffer(st
 {
 	int ret;
 
+
+	/*
+	 * Don't validate pinned buffers.
+	 */
+
+	if (bo == dev_priv->pinned_bo ||
+	    (bo == dev_priv->dummy_query_bo &&
+	     dev_priv->dummy_query_bo_pinned))
+		return 0;
+
 	/**
 	 * Put BO in VRAM if there is space, otherwise as a GMR.
 	 * If there is no space in VRAM and GMR ids are all used up,
@@ -602,57 +958,208 @@ static int vmw_validate_buffers(struct v
 	return 0;
 }
 
-int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
+static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
+				 uint32_t size)
+{
+	if (likely(sw_context->cmd_bounce_size >= size))
+		return 0;
+
+	if (sw_context->cmd_bounce_size == 0)
+		sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;
+
+	while (sw_context->cmd_bounce_size < size) {
+		sw_context->cmd_bounce_size =
+			PAGE_ALIGN(sw_context->cmd_bounce_size +
+				   (sw_context->cmd_bounce_size >> 1));
+	}
+
+	if (sw_context->cmd_bounce != NULL)
+		vfree(sw_context->cmd_bounce);
+
+	sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);
+
+	if (sw_context->cmd_bounce == NULL) {
+		DRM_ERROR("Failed to allocate command bounce buffer.\n");
+		sw_context->cmd_bounce_size = 0;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * vmw_execbuf_fence_commands - create and submit a command stream fence
+ *
+ * Creates a fence object and submits a command stream marker.
+ * If this fails for some reason, We sync the fifo and return NULL.
+ * It is then safe to fence buffers with a NULL pointer.
+ *
+ * If @p_handle is not NULL @file_priv must also not be NULL. Creates
+ * a userspace handle if @p_handle is not NULL, otherwise not.
+ */
+
+int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       struct vmw_fence_obj **p_fence,
+			       uint32_t *p_handle)
 {
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
-	struct drm_vmw_fence_rep fence_rep;
-	struct drm_vmw_fence_rep __user *user_fence_rep;
-	int ret;
-	void *user_cmd;
-	void *cmd;
 	uint32_t sequence;
-	struct vmw_sw_context *sw_context = &dev_priv->ctx;
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+	bool synced = false;
 
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
+	/* p_handle implies file_priv. */
+	BUG_ON(p_handle != NULL && file_priv == NULL);
 
-	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	ret = vmw_fifo_send_fence(dev_priv, &sequence);
 	if (unlikely(ret != 0)) {
-		ret = -ERESTARTSYS;
-		goto out_no_cmd_mutex;
+		DRM_ERROR("Fence submission error. Syncing.\n");
+		synced = true;
 	}
 
-	cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving fifo space for commands.\n");
-		ret = -ENOMEM;
-		goto out_unlock;
+	if (p_handle != NULL)
+		ret = vmw_user_fence_create(file_priv, dev_priv->fman,
+					    sequence,
+					    DRM_VMW_FENCE_FLAG_EXEC,
+					    p_fence, p_handle);
+	else
+		ret = vmw_fence_create(dev_priv->fman, sequence,
+				       DRM_VMW_FENCE_FLAG_EXEC,
+				       p_fence);
+
+	if (unlikely(ret != 0 && !synced)) {
+		(void) vmw_fallback_wait(dev_priv, false, false,
+					 sequence, false,
+					 VMW_FENCE_WAIT_TIMEOUT);
+		*p_fence = NULL;
 	}
 
-	user_cmd = (void __user *)(unsigned long)arg->commands;
-	ret = copy_from_user(cmd, user_cmd, arg->command_size);
+	return 0;
+}
 
-	if (unlikely(ret != 0)) {
-		ret = -EFAULT;
-		DRM_ERROR("Failed copying commands.\n");
-		goto out_commit;
+/**
+ * vmw_execbuf_copy_fence_user - copy fence object information to
+ * user-space.
+ *
+ * @dev_priv: Pointer to a vmw_private struct.
+ * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file.
+ * @ret: Return value from fence object creation.
+ * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to
+ * which the information should be copied.
+ * @fence: Pointer to the fenc object.
+ * @fence_handle: User-space fence handle.
+ *
+ * This function copies fence information to user-space. If copying fails,
+ * The user-space struct drm_vmw_fence_rep::error member is hopefully
+ * left untouched, and if it's preloaded with an -EFAULT by user-space,
+ * the error will hopefully be detected.
+ * Also if copying fails, user-space will be unable to signal the fence
+ * object so we wait for it immediately, and then unreference the
+ * user-space reference.
+ */
+void
+vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+			    struct vmw_fpriv *vmw_fp,
+			    int ret,
+			    struct drm_vmw_fence_rep __user *user_fence_rep,
+			    struct vmw_fence_obj *fence,
+			    uint32_t fence_handle)
+{
+	struct drm_vmw_fence_rep fence_rep;
+
+	if (user_fence_rep == NULL)
+		return;
+
+	memset(&fence_rep, 0, sizeof(fence_rep));
+
+	fence_rep.error = ret;
+	if (ret == 0) {
+		BUG_ON(fence == NULL);
+
+		fence_rep.handle = fence_handle;
+		fence_rep.seqno = fence->seqno;
+		vmw_update_seqno(dev_priv, &dev_priv->fifo);
+		fence_rep.passed_seqno = dev_priv->last_read_seqno;
 	}
 
+	/*
+	 * copy_to_user errors will be detected by user space not
+	 * seeing fence_rep::error filled in. Typically
+	 * user-space would have pre-set that member to -EFAULT.
+	 */
+	ret = copy_to_user(user_fence_rep, &fence_rep,
+			   sizeof(fence_rep));
+
+	/*
+	 * User-space lost the fence object. We need to sync
+	 * and unreference the handle.
+	 */
+	if (unlikely(ret != 0) && (fence_rep.error == 0)) {
+		ttm_ref_object_base_unref(vmw_fp->tfile,
+					  fence_handle, TTM_REF_USAGE);
+		DRM_ERROR("Fence copy error. Syncing.\n");
+		(void) vmw_fence_obj_wait(fence, fence->signal_mask,
+					  false, false,
+					  VMW_FENCE_WAIT_TIMEOUT);
+	}
+}
+
+int vmw_execbuf_process(struct drm_file *file_priv,
+			struct vmw_private *dev_priv,
+			void __user *user_commands,
+			void *kernel_commands,
+			uint32_t command_size,
+			uint64_t throttle_us,
+			struct drm_vmw_fence_rep __user *user_fence_rep)
+{
+	struct vmw_sw_context *sw_context = &dev_priv->ctx;
+	struct vmw_fence_obj *fence;
+	uint32_t handle;
+	void *cmd;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	if (unlikely(ret != 0))
+		return -ERESTARTSYS;
+
+	if (kernel_commands == NULL) {
+		sw_context->kernel = false;
+
+		ret = vmw_resize_cmd_bounce(sw_context, command_size);
+		if (unlikely(ret != 0))
+			goto out_unlock;
+
+
+		ret = copy_from_user(sw_context->cmd_bounce,
+				     user_commands, command_size);
+
+		if (unlikely(ret != 0)) {
+			ret = -EFAULT;
+			DRM_ERROR("Failed copying commands.\n");
+			goto out_unlock;
+		}
+		kernel_commands = sw_context->cmd_bounce;
+	} else
+		sw_context->kernel = true;
+
 	sw_context->tfile = vmw_fpriv(file_priv)->tfile;
 	sw_context->cid_valid = false;
 	sw_context->sid_valid = false;
 	sw_context->cur_reloc = 0;
 	sw_context->cur_val_buf = 0;
+	sw_context->fence_flags = 0;
+	INIT_LIST_HEAD(&sw_context->query_list);
+	INIT_LIST_HEAD(&sw_context->resource_list);
+	sw_context->cur_query_bo = dev_priv->pinned_bo;
+	sw_context->cur_query_cid = dev_priv->query_cid;
+	sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL);
 
 	INIT_LIST_HEAD(&sw_context->validate_nodes);
 
-	ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
+	ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
+				command_size);
 	if (unlikely(ret != 0))
 		goto out_err;
+
 	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
 	if (unlikely(ret != 0))
 		goto out_err;
@@ -663,57 +1170,206 @@ int vmw_execbuf_ioctl(struct drm_device
 
 	vmw_apply_relocations(sw_context);
 
-	if (arg->throttle_us) {
-		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
-				   arg->throttle_us);
+	if (throttle_us) {
+		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
+				   throttle_us);
 
 		if (unlikely(ret != 0))
-			goto out_err;
+			goto out_throttle;
 	}
 
-	vmw_fifo_commit(dev_priv, arg->command_size);
-
-	ret = vmw_fifo_send_fence(dev_priv, &sequence);
+	cmd = vmw_fifo_reserve(dev_priv, command_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving fifo space for commands.\n");
+		ret = -ENOMEM;
+		goto out_throttle;
+	}
 
-	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
-				    (void *)(unsigned long) sequence);
-	vmw_clear_validations(sw_context);
-	mutex_unlock(&dev_priv->cmdbuf_mutex);
+	memcpy(cmd, kernel_commands, command_size);
+	vmw_fifo_commit(dev_priv, command_size);
 
+	vmw_query_bo_switch_commit(dev_priv, sw_context);
+	ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+					 &fence,
+					 (user_fence_rep) ? &handle : NULL);
 	/*
 	 * This error is harmless, because if fence submission fails,
-	 * vmw_fifo_send_fence will sync.
+	 * vmw_fifo_send_fence will sync. The error will be propagated to
+	 * user-space in @fence_rep
 	 */
 
 	if (ret != 0)
 		DRM_ERROR("Fence submission error. Syncing.\n");
 
-	fence_rep.error = ret;
-	fence_rep.fence_seq = (uint64_t) sequence;
-	fence_rep.pad64 = 0;
-
-	user_fence_rep = (struct drm_vmw_fence_rep __user *)
-	    (unsigned long)arg->fence_rep;
+	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+				    (void *) fence);
 
-	/*
-	 * copy_to_user errors will be detected by user space not
-	 * seeing fence_rep::error filled in.
-	 */
+	vmw_clear_validations(sw_context);
+	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
+				    user_fence_rep, fence, handle);
 
-	ret = copy_to_user(user_fence_rep, &fence_rep, sizeof(fence_rep));
+	if (likely(fence != NULL))
+		vmw_fence_obj_unreference(&fence);
 
-	vmw_kms_cursor_post_execbuf(dev_priv);
-	ttm_read_unlock(&vmaster->lock);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
 	return 0;
+
 out_err:
 	vmw_free_relocations(sw_context);
+out_throttle:
+	vmw_query_switch_backoff(sw_context);
 	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
 	vmw_clear_validations(sw_context);
-out_commit:
-	vmw_fifo_commit(dev_priv, 0);
 out_unlock:
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
-out_no_cmd_mutex:
+	return ret;
+}
+
+/**
+ * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function is called to idle the fifo and unpin the query buffer
+ * if the normal way to do this hits an error, which should typically be
+ * extremely rare.
+ */
+static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
+{
+	DRM_ERROR("Can't unpin query buffer. Trying to recover.\n");
+
+	(void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ);
+	vmw_bo_pin(dev_priv->pinned_bo, false);
+	vmw_bo_pin(dev_priv->dummy_query_bo, false);
+	dev_priv->dummy_query_bo_pinned = false;
+}
+
+
+/**
+ * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
+ * query bo.
+ *
+ * @dev_priv: The device private structure.
+ * @only_on_cid_match: Only flush and unpin if the current active query cid
+ * matches @cid.
+ * @cid: Optional context id to match.
+ *
+ * This function should be used to unpin the pinned query bo, or
+ * as a query barrier when we need to make sure that all queries have
+ * finished before the next fifo command. (For example on hardware
+ * context destructions where the hardware may otherwise leak unfinished
+ * queries).
+ *
+ * This function does not return any failure codes, but make attempts
+ * to do safe unpinning in case of errors.
+ *
+ * The function will synchronize on the previous query barrier, and will
+ * thus not finish until that barrier has executed.
+ */
+void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+				   bool only_on_cid_match, uint32_t cid)
+{
+	int ret = 0;
+	struct list_head validate_list;
+	struct ttm_validate_buffer pinned_val, query_val;
+	struct vmw_fence_obj *fence;
+
+	mutex_lock(&dev_priv->cmdbuf_mutex);
+
+	if (dev_priv->pinned_bo == NULL)
+		goto out_unlock;
+
+	if (only_on_cid_match && cid != dev_priv->query_cid)
+		goto out_unlock;
+
+	INIT_LIST_HEAD(&validate_list);
+
+	pinned_val.new_sync_obj_arg = (void *)(unsigned long)
+		DRM_VMW_FENCE_FLAG_EXEC;
+	pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
+	list_add_tail(&pinned_val.head, &validate_list);
+
+	query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg;
+	query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
+	list_add_tail(&query_val.head, &validate_list);
+
+	do {
+		ret = ttm_eu_reserve_buffers(&validate_list);
+	} while (ret == -ERESTARTSYS);
+
+	if (unlikely(ret != 0)) {
+		vmw_execbuf_unpin_panic(dev_priv);
+		goto out_no_reserve;
+	}
+
+	ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
+	if (unlikely(ret != 0)) {
+		vmw_execbuf_unpin_panic(dev_priv);
+		goto out_no_emit;
+	}
+
+	vmw_bo_pin(dev_priv->pinned_bo, false);
+	vmw_bo_pin(dev_priv->dummy_query_bo, false);
+	dev_priv->dummy_query_bo_pinned = false;
+
+	(void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
+	ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
+
+	ttm_bo_unref(&query_val.bo);
+	ttm_bo_unref(&pinned_val.bo);
+	ttm_bo_unref(&dev_priv->pinned_bo);
+
+out_unlock:
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+	return;
+
+out_no_emit:
+	ttm_eu_backoff_reservation(&validate_list);
+out_no_reserve:
+	ttm_bo_unref(&query_val.bo);
+	ttm_bo_unref(&pinned_val.bo);
+	ttm_bo_unref(&dev_priv->pinned_bo);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	/*
+	 * This will allow us to extend the ioctl argument while
+	 * maintaining backwards compatibility:
+	 * We take different code paths depending on the value of
+	 * arg->version.
+	 */
+
+	if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) {
+		DRM_ERROR("Incorrect execbuf version.\n");
+		DRM_ERROR("You're running outdated experimental "
+			  "vmwgfx user-space drivers.");
+		return -EINVAL;
+	}
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv,
+				  (void __user *)(unsigned long)arg->commands,
+				  NULL, arg->command_size, arg->throttle_us,
+				  (void __user *)(unsigned long)arg->fence_rep);
+
+	if (unlikely(ret != 0))
+		goto out_unlock;
+
+	vmw_kms_cursor_post_execbuf(dev_priv);
+
+out_unlock:
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  **************************************************************************/
 
+#include <linux/export.h>
+
 #include "drmP.h"
 #include "vmwgfx_drv.h"
 
@@ -158,10 +160,14 @@ static int vmw_fb_set_par(struct fb_info
 {
 	struct vmw_fb_par *par = info->par;
 	struct vmw_private *vmw_priv = par->vmw_priv;
+	int ret;
+
+	ret = vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+				 info->fix.line_length,
+				 par->bpp, par->depth);
+	if (ret)
+		return ret;
 
-	vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
-			   info->fix.line_length,
-			   par->bpp, par->depth);
 	if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
 		/* TODO check if pitch and offset changes */
 		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
@@ -405,14 +411,14 @@ int vmw_fb_init(struct vmw_private *vmw_
 	struct fb_info *info;
 	unsigned initial_width, initial_height;
 	unsigned fb_width, fb_height;
-	unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
+	unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size;
 	int ret;
 
 	/* XXX These shouldn't be hardcoded. */
 	initial_width = 800;
 	initial_height = 600;
 
-	fb_bbp = 32;
+	fb_bpp = 32;
 	fb_depth = 24;
 
 	/* XXX As shouldn't these be as well. */
@@ -422,7 +428,7 @@ int vmw_fb_init(struct vmw_private *vmw_
 	initial_width = min(fb_width, initial_width);
 	initial_height = min(fb_height, initial_height);
 
-	fb_pitch = fb_width * fb_bbp / 8;
+	fb_pitch = fb_width * fb_bpp / 8;
 	fb_size = fb_pitch * fb_height;
 	fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
 
@@ -437,7 +443,7 @@ int vmw_fb_init(struct vmw_private *vmw_
 	par = info->par;
 	par->vmw_priv = vmw_priv;
 	par->depth = fb_depth;
-	par->bpp = fb_bbp;
+	par->bpp = fb_bpp;
 	par->vmalloc = NULL;
 	par->max_width = fb_width;
 	par->max_height = fb_height;
@@ -588,58 +594,6 @@ int vmw_fb_close(struct vmw_private *vmw
 	return 0;
 }
 
-int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
-			 struct vmw_dma_buffer *vmw_bo)
-{
-	struct ttm_buffer_object *bo = &vmw_bo->base;
-	int ret = 0;
-
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false, false);
-	ttm_bo_unreserve(bo);
-
-	return ret;
-}
-
-int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
-				struct vmw_dma_buffer *vmw_bo)
-{
-	struct ttm_buffer_object *bo = &vmw_bo->base;
-	struct ttm_placement ne_placement = vmw_vram_ne_placement;
-	int ret = 0;
-
-	ne_placement.lpfn = bo->num_pages;
-
-	/* interuptable? */
-	ret = ttm_write_lock(&vmw_priv->active_master->lock, false);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
-	if (unlikely(ret != 0))
-		goto err_unlock;
-
-	if (bo->mem.mem_type == TTM_PL_VRAM &&
-	    bo->mem.start < bo->num_pages &&
-	    bo->mem.start > 0)
-		(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
-				       false, false);
-
-	ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
-
-	/* Could probably bug on */
-	WARN_ON(bo->offset != 0);
-
-	ttm_bo_unreserve(bo);
-err_unlock:
-	ttm_write_unlock(&vmw_priv->active_master->lock);
-
-	return ret;
-}
-
 int vmw_fb_off(struct vmw_private *vmw_priv)
 {
 	struct fb_info *info;
@@ -661,7 +615,7 @@ int vmw_fb_off(struct vmw_private *vmw_p
 	par->bo_ptr = NULL;
 	ttm_bo_kunmap(&par->map);
 
-	vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo);
+	vmw_dmabuf_unpin(vmw_priv, par->vmw_bo, false);
 
 	return 0;
 }
@@ -687,7 +641,7 @@ int vmw_fb_on(struct vmw_private *vmw_pr
 	/* Make sure that all overlays are stoped when we take over */
 	vmw_overlay_stop_all(vmw_priv);
 
-	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo);
+	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo, true, false);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("could not move buffer to start of VRAM\n");
 		goto err_no_buffer;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,149 +25,1100 @@
  *
  **************************************************************************/
 
-
+#include "drmP.h"
 #include "vmwgfx_drv.h"
 
-struct vmw_fence {
-	struct list_head head;
-	uint32_t sequence;
-	struct timespec submitted;
+#define VMW_FENCE_WRAP (1 << 31)
+
+struct vmw_fence_manager {
+	int num_fence_objects;
+	struct vmw_private *dev_priv;
+	spinlock_t lock;
+	struct list_head fence_list;
+	struct work_struct work;
+	u32 user_fence_size;
+	u32 fence_size;
+	u32 event_fence_action_size;
+	bool fifo_down;
+	struct list_head cleanup_list;
+	uint32_t pending_actions[VMW_ACTION_MAX];
+	struct mutex goal_irq_mutex;
+	bool goal_irq_on; /* Protected by @goal_irq_mutex */
+	bool seqno_valid; /* Protected by @lock, and may not be set to true
+			     without the @goal_irq_mutex held. */
 };
 
-void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+struct vmw_user_fence {
+	struct ttm_base_object base;
+	struct vmw_fence_obj fence;
+};
+
+/**
+ * struct vmw_event_fence_action - fence action that delivers a drm event.
+ *
+ * @e: A struct drm_pending_event that controls the event delivery.
+ * @action: A struct vmw_fence_action to hook up to a fence.
+ * @fence: A referenced pointer to the fence to keep it alive while @action
+ * hangs on it.
+ * @dev: Pointer to a struct drm_device so we can access the event stuff.
+ * @kref: Both @e and @action has destructors, so we need to refcount.
+ * @size: Size accounted for this object.
+ * @tv_sec: If non-null, the variable pointed to will be assigned
+ * current time tv_sec val when the fence signals.
+ * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will
+ * be assigned the current time tv_usec val when the fence signals.
+ */
+struct vmw_event_fence_action {
+	struct drm_pending_event e;
+	struct vmw_fence_action action;
+	struct vmw_fence_obj *fence;
+	struct drm_device *dev;
+	struct kref kref;
+	uint32_t size;
+	uint32_t *tv_sec;
+	uint32_t *tv_usec;
+};
+
+/**
+ * Note on fencing subsystem usage of irqs:
+ * Typically the vmw_fences_update function is called
+ *
+ * a) When a new fence seqno has been submitted by the fifo code.
+ * b) On-demand when we have waiters. Sleeping waiters will switch on the
+ * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE
+ * irq is received. When the last fence waiter is gone, that IRQ is masked
+ * away.
+ *
+ * In situations where there are no waiters and we don't submit any new fences,
+ * fence objects may not be signaled. This is perfectly OK, since there are
+ * no consumers of the signaled data, but that is NOT ok when there are fence
+ * actions attached to a fence. The fencing subsystem then makes use of the
+ * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence
+ * which has an action attached, and each time vmw_fences_update is called,
+ * the subsystem makes sure the fence goal seqno is updated.
+ *
+ * The fence goal seqno irq is on as long as there are unsignaled fence
+ * objects with actions attached to them.
+ */
+
+static void vmw_fence_obj_destroy_locked(struct kref *kref)
 {
-	INIT_LIST_HEAD(&queue->head);
-	queue->lag = ns_to_timespec(0);
-	getrawmonotonic(&queue->lag_time);
-	spin_lock_init(&queue->lock);
+	struct vmw_fence_obj *fence =
+		container_of(kref, struct vmw_fence_obj, kref);
+
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned int num_fences;
+
+	list_del_init(&fence->head);
+	num_fences = --fman->num_fence_objects;
+	spin_unlock_irq(&fman->lock);
+	if (fence->destroy)
+		fence->destroy(fence);
+	else
+		kfree(fence);
+
+	spin_lock_irq(&fman->lock);
 }
 
-void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+
+/**
+ * Execute signal actions on fences recently signaled.
+ * This is done from a workqueue so we don't have to execute
+ * signal actions from atomic context.
+ */
+
+static void vmw_fence_work_func(struct work_struct *work)
 {
-	struct vmw_fence *fence, *next;
+	struct vmw_fence_manager *fman =
+		container_of(work, struct vmw_fence_manager, work);
+	struct list_head list;
+	struct vmw_fence_action *action, *next_action;
+	bool seqno_valid;
 
-	spin_lock(&queue->lock);
-	list_for_each_entry_safe(fence, next, &queue->head, head) {
-		kfree(fence);
-	}
-	spin_unlock(&queue->lock);
+	do {
+		INIT_LIST_HEAD(&list);
+		mutex_lock(&fman->goal_irq_mutex);
+
+		spin_lock_irq(&fman->lock);
+		list_splice_init(&fman->cleanup_list, &list);
+		seqno_valid = fman->seqno_valid;
+		spin_unlock_irq(&fman->lock);
+
+		if (!seqno_valid && fman->goal_irq_on) {
+			fman->goal_irq_on = false;
+			vmw_goal_waiter_remove(fman->dev_priv);
+		}
+		mutex_unlock(&fman->goal_irq_mutex);
+
+		if (list_empty(&list))
+			return;
+
+		/*
+		 * At this point, only we should be able to manipulate the
+		 * list heads of the actions we have on the private list.
+		 * hence fman::lock not held.
+		 */
+
+		list_for_each_entry_safe(action, next_action, &list, head) {
+			list_del_init(&action->head);
+			if (action->cleanup)
+				action->cleanup(action);
+		}
+	} while (1);
 }
 
-int vmw_fence_push(struct vmw_fence_queue *queue,
-		   uint32_t sequence)
+struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
 {
-	struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+	struct vmw_fence_manager *fman = kzalloc(sizeof(*fman), GFP_KERNEL);
 
-	if (unlikely(!fence))
-		return -ENOMEM;
+	if (unlikely(fman == NULL))
+		return NULL;
 
-	fence->sequence = sequence;
-	getrawmonotonic(&fence->submitted);
-	spin_lock(&queue->lock);
-	list_add_tail(&fence->head, &queue->head);
-	spin_unlock(&queue->lock);
+	fman->dev_priv = dev_priv;
+	spin_lock_init(&fman->lock);
+	INIT_LIST_HEAD(&fman->fence_list);
+	INIT_LIST_HEAD(&fman->cleanup_list);
+	INIT_WORK(&fman->work, &vmw_fence_work_func);
+	fman->fifo_down = true;
+	fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence));
+	fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj));
+	fman->event_fence_action_size =
+		ttm_round_pot(sizeof(struct vmw_event_fence_action));
+	mutex_init(&fman->goal_irq_mutex);
 
-	return 0;
+	return fman;
 }
 
-int vmw_fence_pull(struct vmw_fence_queue *queue,
-		   uint32_t signaled_sequence)
+void vmw_fence_manager_takedown(struct vmw_fence_manager *fman)
 {
-	struct vmw_fence *fence, *next;
-	struct timespec now;
-	bool updated = false;
+	unsigned long irq_flags;
+	bool lists_empty;
 
-	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
+	(void) cancel_work_sync(&fman->work);
 
-	if (list_empty(&queue->head)) {
-		queue->lag = ns_to_timespec(0);
-		queue->lag_time = now;
-		updated = true;
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	lists_empty = list_empty(&fman->fence_list) &&
+		list_empty(&fman->cleanup_list);
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	BUG_ON(!lists_empty);
+	kfree(fman);
+}
+
+static int vmw_fence_obj_init(struct vmw_fence_manager *fman,
+			      struct vmw_fence_obj *fence,
+			      u32 seqno,
+			      uint32_t mask,
+			      void (*destroy) (struct vmw_fence_obj *fence))
+{
+	unsigned long irq_flags;
+	unsigned int num_fences;
+	int ret = 0;
+
+	fence->seqno = seqno;
+	INIT_LIST_HEAD(&fence->seq_passed_actions);
+	fence->fman = fman;
+	fence->signaled = 0;
+	fence->signal_mask = mask;
+	kref_init(&fence->kref);
+	fence->destroy = destroy;
+	init_waitqueue_head(&fence->queue);
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	if (unlikely(fman->fifo_down)) {
+		ret = -EBUSY;
 		goto out_unlock;
 	}
+	list_add_tail(&fence->head, &fman->fence_list);
+	num_fences = ++fman->num_fence_objects;
 
-	list_for_each_entry_safe(fence, next, &queue->head, head) {
-		if (signaled_sequence - fence->sequence > (1 << 30))
-			continue;
+out_unlock:
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+	return ret;
 
-		queue->lag = timespec_sub(now, fence->submitted);
-		queue->lag_time = now;
-		updated = true;
-		list_del(&fence->head);
-		kfree(fence);
+}
+
+struct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence)
+{
+	if (unlikely(fence == NULL))
+		return NULL;
+
+	kref_get(&fence->kref);
+	return fence;
+}
+
+/**
+ * vmw_fence_obj_unreference
+ *
+ * Note that this function may not be entered with disabled irqs since
+ * it may re-enable them in the destroy function.
+ *
+ */
+void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
+{
+	struct vmw_fence_obj *fence = *fence_p;
+	struct vmw_fence_manager *fman;
+
+	if (unlikely(fence == NULL))
+		return;
+
+	fman = fence->fman;
+	*fence_p = NULL;
+	spin_lock_irq(&fman->lock);
+	BUG_ON(atomic_read(&fence->kref.refcount) == 0);
+	kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+	spin_unlock_irq(&fman->lock);
+}
+
+void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
+				struct list_head *list)
+{
+	struct vmw_fence_action *action, *next_action;
+
+	list_for_each_entry_safe(action, next_action, list, head) {
+		list_del_init(&action->head);
+		fman->pending_actions[action->type]--;
+		if (action->seq_passed != NULL)
+			action->seq_passed(action);
+
+		/*
+		 * Add the cleanup action to the cleanup list so that
+		 * it will be performed by a worker task.
+		 */
+
+		list_add_tail(&action->head, &fman->cleanup_list);
 	}
+}
 
-out_unlock:
-	spin_unlock(&queue->lock);
+/**
+ * vmw_fence_goal_new_locked - Figure out a new device fence goal
+ * seqno if needed.
+ *
+ * @fman: Pointer to a fence manager.
+ * @passed_seqno: The seqno the device currently signals as passed.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when we have a new passed_seqno, and
+ * we might need to update the fence goal. It checks to see whether
+ * the current fence goal has already passed, and, in that case,
+ * scans through all unsignaled fences to get the next fence object with an
+ * action attached, and sets the seqno of that fence as a new fence goal.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
+				      u32 passed_seqno)
+{
+	u32 goal_seqno;
+	__le32 __iomem *fifo_mem;
+	struct vmw_fence_obj *fence;
 
-	return (updated) ? 0 : -EBUSY;
+	if (likely(!fman->seqno_valid))
+		return false;
+
+	fifo_mem = fman->dev_priv->mmio_virt;
+	goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
+		return false;
+
+	fman->seqno_valid = false;
+	list_for_each_entry(fence, &fman->fence_list, head) {
+		if (!list_empty(&fence->seq_passed_actions)) {
+			fman->seqno_valid = true;
+			iowrite32(fence->seqno,
+				  fifo_mem + SVGA_FIFO_FENCE_GOAL);
+			break;
+		}
+	}
+
+	return true;
 }
 
-static struct timespec vmw_timespec_add(struct timespec t1,
-					struct timespec t2)
+
+/**
+ * vmw_fence_goal_check_locked - Replace the device fence goal seqno if
+ * needed.
+ *
+ * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be
+ * considered as a device fence goal.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when an action has been attached to a fence to
+ * check whether the seqno of that fence should be used for a fence
+ * goal interrupt. This is typically needed if the current fence goal is
+ * invalid, or has a higher seqno than that of the current fence object.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
 {
-	t1.tv_sec += t2.tv_sec;
-	t1.tv_nsec += t2.tv_nsec;
-	if (t1.tv_nsec >= 1000000000L) {
-		t1.tv_sec += 1;
-		t1.tv_nsec -= 1000000000L;
+	u32 goal_seqno;
+	__le32 __iomem *fifo_mem;
+
+	if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC)
+		return false;
+
+	fifo_mem = fence->fman->dev_priv->mmio_virt;
+	goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	if (likely(fence->fman->seqno_valid &&
+		   goal_seqno - fence->seqno < VMW_FENCE_WRAP))
+		return false;
+
+	iowrite32(fence->seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	fence->fman->seqno_valid = true;
+
+	return true;
+}
+
+void vmw_fences_update(struct vmw_fence_manager *fman)
+{
+	unsigned long flags;
+	struct vmw_fence_obj *fence, *next_fence;
+	struct list_head action_list;
+	bool needs_rerun;
+	uint32_t seqno, new_seqno;
+	__le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt;
+
+	seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+rerun:
+	spin_lock_irqsave(&fman->lock, flags);
+	list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
+		if (seqno - fence->seqno < VMW_FENCE_WRAP) {
+			list_del_init(&fence->head);
+			fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+			INIT_LIST_HEAD(&action_list);
+			list_splice_init(&fence->seq_passed_actions,
+					 &action_list);
+			vmw_fences_perform_actions(fman, &action_list);
+			wake_up_all(&fence->queue);
+		} else
+			break;
 	}
 
-	return t1;
+	needs_rerun = vmw_fence_goal_new_locked(fman, seqno);
+
+	if (!list_empty(&fman->cleanup_list))
+		(void) schedule_work(&fman->work);
+	spin_unlock_irqrestore(&fman->lock, flags);
+
+	/*
+	 * Rerun if the fence goal seqno was updated, and the
+	 * hardware might have raced with that update, so that
+	 * we missed a fence_goal irq.
+	 */
+
+	if (unlikely(needs_rerun)) {
+		new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+		if (new_seqno != seqno) {
+			seqno = new_seqno;
+			goto rerun;
+		}
+	}
 }
 
-static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+			    uint32_t flags)
 {
-	struct timespec now;
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned long irq_flags;
+	uint32_t signaled;
 
-	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
-	queue->lag = vmw_timespec_add(queue->lag,
-				      timespec_sub(now, queue->lag_time));
-	queue->lag_time = now;
-	spin_unlock(&queue->lock);
-	return queue->lag;
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	signaled = fence->signaled;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	flags &= fence->signal_mask;
+	if ((signaled & flags) == flags)
+		return 1;
+
+	if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0)
+		vmw_fences_update(fman);
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	signaled = fence->signaled;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	return ((signaled & flags) == flags);
 }
 
+int vmw_fence_obj_wait(struct vmw_fence_obj *fence,
+		       uint32_t flags, bool lazy,
+		       bool interruptible, unsigned long timeout)
+{
+	struct vmw_private *dev_priv = fence->fman->dev_priv;
+	long ret;
+
+	if (likely(vmw_fence_obj_signaled(fence, flags)))
+		return 0;
 
-static bool vmw_lag_lt(struct vmw_fence_queue *queue,
-		       uint32_t us)
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	vmw_seqno_waiter_add(dev_priv);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+			(fence->queue,
+			 vmw_fence_obj_signaled(fence, flags),
+			 timeout);
+	else
+		ret = wait_event_timeout
+			(fence->queue,
+			 vmw_fence_obj_signaled(fence, flags),
+			 timeout);
+
+	vmw_seqno_waiter_remove(dev_priv);
+
+	if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	return ret;
+}
+
+void vmw_fence_obj_flush(struct vmw_fence_obj *fence)
 {
-	struct timespec lag, cond;
+	struct vmw_private *dev_priv = fence->fman->dev_priv;
 
-	cond = ns_to_timespec((s64) us * 1000);
-	lag = vmw_fifo_lag(queue);
-	return (timespec_compare(&lag, &cond) < 1);
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 }
 
-int vmw_wait_lag(struct vmw_private *dev_priv,
-		 struct vmw_fence_queue *queue, uint32_t us)
+static void vmw_fence_destroy(struct vmw_fence_obj *fence)
 {
-	struct vmw_fence *fence;
-	uint32_t sequence;
+	struct vmw_fence_manager *fman = fence->fman;
+
+	kfree(fence);
+	/*
+	 * Free kernel space accounting.
+	 */
+	ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+			    fman->fence_size);
+}
+
+int vmw_fence_create(struct vmw_fence_manager *fman,
+		     uint32_t seqno,
+		     uint32_t mask,
+		     struct vmw_fence_obj **p_fence)
+{
+	struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+	struct vmw_fence_obj *fence;
 	int ret;
 
-	while (!vmw_lag_lt(queue, us)) {
-		spin_lock(&queue->lock);
-		if (list_empty(&queue->head))
-			sequence = atomic_read(&dev_priv->fence_seq);
-		else {
-			fence = list_first_entry(&queue->head,
-						 struct vmw_fence, head);
-			sequence = fence->sequence;
+	ret = ttm_mem_global_alloc(mem_glob, fman->fence_size,
+				   false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (unlikely(fence == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_object;
+	}
+
+	ret = vmw_fence_obj_init(fman, fence, seqno, mask,
+				 vmw_fence_destroy);
+	if (unlikely(ret != 0))
+		goto out_err_init;
+
+	*p_fence = fence;
+	return 0;
+
+out_err_init:
+	kfree(fence);
+out_no_object:
+	ttm_mem_global_free(mem_glob, fman->fence_size);
+	return ret;
+}
+
+
+static void vmw_user_fence_destroy(struct vmw_fence_obj *fence)
+{
+	struct vmw_user_fence *ufence =
+		container_of(fence, struct vmw_user_fence, fence);
+	struct vmw_fence_manager *fman = fence->fman;
+
+	kfree(ufence);
+	/*
+	 * Free kernel space accounting.
+	 */
+	ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+			    fman->user_fence_size);
+}
+
+static void vmw_user_fence_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_fence *ufence =
+		container_of(base, struct vmw_user_fence, base);
+	struct vmw_fence_obj *fence = &ufence->fence;
+
+	*p_base = NULL;
+	vmw_fence_obj_unreference(&fence);
+}
+
+int vmw_user_fence_create(struct drm_file *file_priv,
+			  struct vmw_fence_manager *fman,
+			  uint32_t seqno,
+			  uint32_t mask,
+			  struct vmw_fence_obj **p_fence,
+			  uint32_t *p_handle)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_user_fence *ufence;
+	struct vmw_fence_obj *tmp;
+	struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+	int ret;
+
+	/*
+	 * Kernel memory space accounting, since this object may
+	 * be created by a user-space request.
+	 */
+
+	ret = ttm_mem_global_alloc(mem_glob, fman->user_fence_size,
+				   false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ufence = kzalloc(sizeof(*ufence), GFP_KERNEL);
+	if (unlikely(ufence == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_object;
+	}
+
+	ret = vmw_fence_obj_init(fman, &ufence->fence, seqno,
+				 mask, vmw_user_fence_destroy);
+	if (unlikely(ret != 0)) {
+		kfree(ufence);
+		goto out_no_object;
+	}
+
+	/*
+	 * The base object holds a reference which is freed in
+	 * vmw_user_fence_base_release.
+	 */
+	tmp = vmw_fence_obj_reference(&ufence->fence);
+	ret = ttm_base_object_init(tfile, &ufence->base, false,
+				   VMW_RES_FENCE,
+				   &vmw_user_fence_base_release, NULL);
+
+
+	if (unlikely(ret != 0)) {
+		/*
+		 * Free the base object's reference
+		 */
+		vmw_fence_obj_unreference(&tmp);
+		goto out_err;
+	}
+
+	*p_fence = &ufence->fence;
+	*p_handle = ufence->base.hash.key;
+
+	return 0;
+out_err:
+	tmp = &ufence->fence;
+	vmw_fence_obj_unreference(&tmp);
+out_no_object:
+	ttm_mem_global_free(mem_glob, fman->user_fence_size);
+	return ret;
+}
+
+
+/**
+ * vmw_fence_fifo_down - signal all unsignaled fence objects.
+ */
+
+void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
+{
+	unsigned long irq_flags;
+	struct list_head action_list;
+	int ret;
+
+	/*
+	 * The list may be altered while we traverse it, so always
+	 * restart when we've released the fman->lock.
+	 */
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	fman->fifo_down = true;
+	while (!list_empty(&fman->fence_list)) {
+		struct vmw_fence_obj *fence =
+			list_entry(fman->fence_list.prev, struct vmw_fence_obj,
+				   head);
+		kref_get(&fence->kref);
+		spin_unlock_irq(&fman->lock);
+
+		ret = vmw_fence_obj_wait(fence, fence->signal_mask,
+					 false, false,
+					 VMW_FENCE_WAIT_TIMEOUT);
+
+		if (unlikely(ret != 0)) {
+			list_del_init(&fence->head);
+			fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+			INIT_LIST_HEAD(&action_list);
+			list_splice_init(&fence->seq_passed_actions,
+					 &action_list);
+			vmw_fences_perform_actions(fman, &action_list);
+			wake_up_all(&fence->queue);
 		}
-		spin_unlock(&queue->lock);
 
-		ret = vmw_wait_fence(dev_priv, false, sequence, true,
-				     3*HZ);
+		spin_lock_irq(&fman->lock);
 
-		if (unlikely(ret != 0))
-			return ret;
+		BUG_ON(!list_empty(&fence->head));
+		kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+	}
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+}
 
-		(void) vmw_fence_pull(queue, sequence);
+void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	fman->fifo_down = false;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+}
+
+
+int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_wait_arg *arg =
+	    (struct drm_vmw_fence_wait_arg *)data;
+	unsigned long timeout;
+	struct ttm_base_object *base;
+	struct vmw_fence_obj *fence;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+	uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ);
+
+	/*
+	 * 64-bit division not present on 32-bit systems, so do an
+	 * approximation. (Divide by 1000000).
+	 */
+
+	wait_timeout = (wait_timeout >> 20) + (wait_timeout >> 24) -
+	  (wait_timeout >> 26);
+
+	if (!arg->cookie_valid) {
+		arg->cookie_valid = 1;
+		arg->kernel_cookie = jiffies + wait_timeout;
+	}
+
+	base = ttm_base_object_lookup(tfile, arg->handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Wait invalid fence object handle "
+		       "0x%08lx.\n",
+		       (unsigned long)arg->handle);
+		return -EINVAL;
+	}
+
+	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+
+	timeout = jiffies;
+	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) {
+		ret = ((vmw_fence_obj_signaled(fence, arg->flags)) ?
+		       0 : -EBUSY);
+		goto out;
 	}
+
+	timeout = (unsigned long)arg->kernel_cookie - timeout;
+
+	ret = vmw_fence_obj_wait(fence, arg->flags, arg->lazy, true, timeout);
+
+out:
+	ttm_base_object_unref(&base);
+
+	/*
+	 * Optionally unref the fence object.
+	 */
+
+	if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF))
+		return ttm_ref_object_base_unref(tfile, arg->handle,
+						 TTM_REF_USAGE);
+	return ret;
+}
+
+int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_signaled_arg *arg =
+		(struct drm_vmw_fence_signaled_arg *) data;
+	struct ttm_base_object *base;
+	struct vmw_fence_obj *fence;
+	struct vmw_fence_manager *fman;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	base = ttm_base_object_lookup(tfile, arg->handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Fence signaled invalid fence object handle "
+		       "0x%08lx.\n",
+		       (unsigned long)arg->handle);
+		return -EINVAL;
+	}
+
+	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+	fman = fence->fman;
+
+	arg->signaled = vmw_fence_obj_signaled(fence, arg->flags);
+	spin_lock_irq(&fman->lock);
+
+	arg->signaled_flags = fence->signaled;
+	arg->passed_seqno = dev_priv->last_read_seqno;
+	spin_unlock_irq(&fman->lock);
+
+	ttm_base_object_unref(&base);
+
 	return 0;
 }
 
 
+int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_arg *arg =
+		(struct drm_vmw_fence_arg *) data;
+
+	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					 arg->handle,
+					 TTM_REF_USAGE);
+}
+
+/**
+ * vmw_event_fence_action_destroy
+ *
+ * @kref: The struct kref embedded in a struct vmw_event_fence_action.
+ *
+ * The vmw_event_fence_action destructor that may be called either after
+ * the fence action cleanup, or when the event is delivered.
+ * It frees both the vmw_event_fence_action struct and the actual
+ * event structure copied to user-space.
+ */
+static void vmw_event_fence_action_destroy(struct kref *kref)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(kref, struct vmw_event_fence_action, kref);
+	struct ttm_mem_global *mem_glob =
+		vmw_mem_glob(vmw_priv(eaction->dev));
+	uint32_t size = eaction->size;
+
+	kfree(eaction->e.event);
+	kfree(eaction);
+	ttm_mem_global_free(mem_glob, size);
+}
+
+
+/**
+ * vmw_event_fence_action_delivered
+ *
+ * @e: The struct drm_pending_event embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * The struct drm_pending_event destructor that is called by drm
+ * once the event is delivered. Since we don't know whether this function
+ * will be called before or after the fence action destructor, we
+ * free a refcount and destroy if it becomes zero.
+ */
+static void vmw_event_fence_action_delivered(struct drm_pending_event *e)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(e, struct vmw_event_fence_action, e);
+
+	kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_event_fence_action_seq_passed
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is called when the seqno of the fence where @action is
+ * attached has passed. It queues the event on the submitter's event list.
+ * This function is always called from atomic context, and may be called
+ * from irq context. It ups a refcount reflecting that we now have two
+ * destructors.
+ */
+static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(action, struct vmw_event_fence_action, action);
+	struct drm_device *dev = eaction->dev;
+	struct drm_file *file_priv = eaction->e.file_priv;
+	unsigned long irq_flags;
+
+	kref_get(&eaction->kref);
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+	if (likely(eaction->tv_sec != NULL)) {
+		struct timeval tv;
+
+		do_gettimeofday(&tv);
+		*eaction->tv_sec = tv.tv_sec;
+		*eaction->tv_usec = tv.tv_usec;
+	}
+
+	list_add_tail(&eaction->e.link, &file_priv->event_list);
+	wake_up_all(&file_priv->event_wait);
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+}
+
+/**
+ * vmw_event_fence_action_cleanup
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is the struct vmw_fence_action destructor. It's typically
+ * called from a workqueue.
+ */
+static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(action, struct vmw_event_fence_action, action);
+
+	vmw_fence_obj_unreference(&eaction->fence);
+	kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_fence_obj_add_action - Add an action to a fence object.
+ *
+ * @fence - The fence object.
+ * @action - The action to add.
+ *
+ * Note that the action callbacks may be executed before this function
+ * returns.
+ */
+void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
+			      struct vmw_fence_action *action)
+{
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned long irq_flags;
+	bool run_update = false;
+
+	mutex_lock(&fman->goal_irq_mutex);
+	spin_lock_irqsave(&fman->lock, irq_flags);
+
+	fman->pending_actions[action->type]++;
+	if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) {
+		struct list_head action_list;
+
+		INIT_LIST_HEAD(&action_list);
+		list_add_tail(&action->head, &action_list);
+		vmw_fences_perform_actions(fman, &action_list);
+	} else {
+		list_add_tail(&action->head, &fence->seq_passed_actions);
+
+		/*
+		 * This function may set fman::seqno_valid, so it must
+		 * be run with the goal_irq_mutex held.
+		 */
+		run_update = vmw_fence_goal_check_locked(fence);
+	}
+
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	if (run_update) {
+		if (!fman->goal_irq_on) {
+			fman->goal_irq_on = true;
+			vmw_goal_waiter_add(fman->dev_priv);
+		}
+		vmw_fences_update(fman);
+	}
+	mutex_unlock(&fman->goal_irq_mutex);
+
+}
+
+/**
+ * vmw_event_fence_action_create - Post an event for sending when a fence
+ * object seqno has passed.
+ *
+ * @file_priv: The file connection on which the event should be posted.
+ * @fence: The fence object on which to post the event.
+ * @event: Event to be posted. This event should've been alloced
+ * using k[mz]alloc, and should've been completely initialized.
+ * @interruptible: Interruptible waits if possible.
+ *
+ * As a side effect, the object pointed to by @event may have been
+ * freed when this function returns. If this function returns with
+ * an error code, the caller needs to free that object.
+ */
+
+int vmw_event_fence_action_create(struct drm_file *file_priv,
+				  struct vmw_fence_obj *fence,
+				  struct drm_event *event,
+				  uint32_t *tv_sec,
+				  uint32_t *tv_usec,
+				  bool interruptible)
+{
+	struct vmw_event_fence_action *eaction;
+	struct ttm_mem_global *mem_glob =
+		vmw_mem_glob(fence->fman->dev_priv);
+	struct vmw_fence_manager *fman = fence->fman;
+	uint32_t size = fman->event_fence_action_size +
+		ttm_round_pot(event->length);
+	int ret;
+
+	/*
+	 * Account for internal structure size as well as the
+	 * event size itself.
+	 */
+
+	ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	eaction = kzalloc(sizeof(*eaction), GFP_KERNEL);
+	if (unlikely(eaction == NULL)) {
+		ttm_mem_global_free(mem_glob, size);
+		return -ENOMEM;
+	}
+
+	eaction->e.event = event;
+	eaction->e.file_priv = file_priv;
+	eaction->e.destroy = vmw_event_fence_action_delivered;
+
+	eaction->action.seq_passed = vmw_event_fence_action_seq_passed;
+	eaction->action.cleanup = vmw_event_fence_action_cleanup;
+	eaction->action.type = VMW_ACTION_EVENT;
+
+	eaction->fence = vmw_fence_obj_reference(fence);
+	eaction->dev = fman->dev_priv->dev;
+	eaction->size = size;
+	eaction->tv_sec = tv_sec;
+	eaction->tv_usec = tv_usec;
+
+	kref_init(&eaction->kref);
+	vmw_fence_obj_add_action(fence, &eaction->action);
+
+	return 0;
+}
+
+int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_fence_event_arg *arg =
+		(struct drm_vmw_fence_event_arg *) data;
+	struct vmw_fence_obj *fence = NULL;
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct drm_vmw_fence_rep __user *user_fence_rep =
+		(struct drm_vmw_fence_rep __user *)(unsigned long)
+		arg->fence_rep;
+	uint32_t handle;
+	unsigned long irq_flags;
+	struct drm_vmw_event_fence *event;
+	int ret;
+
+	/*
+	 * Look up an existing fence object,
+	 * and if user-space wants a new reference,
+	 * add one.
+	 */
+	if (arg->handle) {
+		struct ttm_base_object *base =
+			ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
+
+		if (unlikely(base == NULL)) {
+			DRM_ERROR("Fence event invalid fence object handle "
+				  "0x%08lx.\n",
+				  (unsigned long)arg->handle);
+			return -EINVAL;
+		}
+		fence = &(container_of(base, struct vmw_user_fence,
+				       base)->fence);
+		(void) vmw_fence_obj_reference(fence);
+
+		if (user_fence_rep != NULL) {
+			bool existed;
+
+			ret = ttm_ref_object_add(vmw_fp->tfile, base,
+						 TTM_REF_USAGE, &existed);
+			if (unlikely(ret != 0)) {
+				DRM_ERROR("Failed to reference a fence "
+					  "object.\n");
+				goto out_no_ref_obj;
+			}
+			handle = base->hash.key;
+		}
+		ttm_base_object_unref(&base);
+	}
+
+	/*
+	 * Create a new fence object.
+	 */
+	if (!fence) {
+		ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+						 &fence,
+						 (user_fence_rep) ?
+						 &handle : NULL);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Fence event failed to create fence.\n");
+			return ret;
+		}
+	}
+
+	BUG_ON(fence == NULL);
+
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+	ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0;
+	if (likely(ret == 0))
+		file_priv->event_space -= sizeof(*event);
+
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed to allocate event space for this file.\n");
+		goto out_no_event_space;
+	}
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (unlikely(event == NULL)) {
+		DRM_ERROR("Failed to allocate an event.\n");
+		goto out_no_event;
+	}
+
+	event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
+	event->base.length = sizeof(*event);
+	event->user_data = arg->user_data;
+
+	if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME)
+		ret = vmw_event_fence_action_create(file_priv, fence,
+						    &event->base,
+						    &event->tv_sec,
+						    &event->tv_usec,
+						    true);
+	else
+		ret = vmw_event_fence_action_create(file_priv, fence,
+						    &event->base,
+						    NULL,
+						    NULL,
+						    true);
+
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Failed to attach event to fence.\n");
+		goto out_no_attach;
+	}
+
+	vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
+				    handle);
+	vmw_fence_obj_unreference(&fence);
+	return 0;
+out_no_attach:
+	kfree(event);
+out_no_event:
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+	file_priv->event_space += sizeof(*event);
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+out_no_event_space:
+	if (user_fence_rep != NULL)
+		ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					  handle, TTM_REF_USAGE);
+out_no_ref_obj:
+	vmw_fence_obj_unreference(&fence);
+	return ret;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_FENCE_H_
+
+#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
+
+struct vmw_private;
+
+struct vmw_fence_manager;
+
+/**
+ *
+ *
+ */
+enum vmw_action_type {
+	VMW_ACTION_EVENT = 0,
+	VMW_ACTION_MAX
+};
+
+struct vmw_fence_action {
+	struct list_head head;
+	enum vmw_action_type type;
+	void (*seq_passed) (struct vmw_fence_action *action);
+	void (*cleanup) (struct vmw_fence_action *action);
+};
+
+struct vmw_fence_obj {
+	struct kref kref;
+	u32 seqno;
+
+	struct vmw_fence_manager *fman;
+	struct list_head head;
+	uint32_t signaled;
+	uint32_t signal_mask;
+	struct list_head seq_passed_actions;
+	void (*destroy)(struct vmw_fence_obj *fence);
+	wait_queue_head_t queue;
+};
+
+extern struct vmw_fence_manager *
+vmw_fence_manager_init(struct vmw_private *dev_priv);
+
+extern void vmw_fence_manager_takedown(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p);
+
+extern struct vmw_fence_obj *
+vmw_fence_obj_reference(struct vmw_fence_obj *fence);
+
+extern void vmw_fences_update(struct vmw_fence_manager *fman);
+
+extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+				   uint32_t flags);
+
+extern int vmw_fence_obj_wait(struct vmw_fence_obj *fence, uint32_t flags,
+			      bool lazy,
+			      bool interruptible, unsigned long timeout);
+
+extern void vmw_fence_obj_flush(struct vmw_fence_obj *fence);
+
+extern int vmw_fence_create(struct vmw_fence_manager *fman,
+			    uint32_t seqno,
+			    uint32_t mask,
+			    struct vmw_fence_obj **p_fence);
+
+extern int vmw_user_fence_create(struct drm_file *file_priv,
+				 struct vmw_fence_manager *fman,
+				 uint32_t sequence,
+				 uint32_t mask,
+				 struct vmw_fence_obj **p_fence,
+				 uint32_t *p_handle);
+
+extern void vmw_fence_fifo_up(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);
+
+extern int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+
+extern int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv);
+
+extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv);
+
+#endif /* _VMWGFX_FENCE_H_ */
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@ bool vmw_fifo_have_3d(struct vmw_private
 {
 	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
 	uint32_t fifo_min, hwversion;
+	const struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
 	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
 		return false;
@@ -41,11 +42,20 @@ bool vmw_fifo_have_3d(struct vmw_private
 	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
 		return false;
 
-	hwversion = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION);
+	hwversion = ioread32(fifo_mem +
+			     ((fifo->capabilities &
+			       SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+			      SVGA_FIFO_3D_HWVERSION_REVISED :
+			      SVGA_FIFO_3D_HWVERSION));
+
 	if (hwversion == 0)
 		return false;
 
-	if (hwversion < SVGA3D_HWVERSION_WS65_B1)
+	if (hwversion < SVGA3D_HWVERSION_WS8_B1)
+		return false;
+
+	/* Non-Screen Object path does not support surfaces */
+	if (!dev_priv->sou_priv)
 		return false;
 
 	return true;
@@ -72,22 +82,12 @@ int vmw_fifo_init(struct vmw_private *de
 	uint32_t max;
 	uint32_t min;
 	uint32_t dummy;
-	int ret;
 
 	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
 	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
 	if (unlikely(fifo->static_buffer == NULL))
 		return -ENOMEM;
 
-	fifo->last_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
-	fifo->last_data_size = 0;
-	fifo->last_buffer_add = false;
-	fifo->last_buffer = vmalloc(fifo->last_buffer_size);
-	if (unlikely(fifo->last_buffer == NULL)) {
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
 	fifo->dynamic_buffer = NULL;
 	fifo->reserved_size = 0;
 	fifo->using_bounce_buffer = false;
@@ -137,14 +137,10 @@ int vmw_fifo_init(struct vmw_private *de
 		 (unsigned int) min,
 		 (unsigned int) fifo->capabilities);
 
-	atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
-	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
-	vmw_fence_queue_init(&fifo->fence_queue);
+	atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
+	iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
+	vmw_marker_queue_init(&fifo->marker_queue);
 	return vmw_fifo_send_fence(dev_priv, &dummy);
-out_err:
-	vfree(fifo->static_buffer);
-	fifo->static_buffer = NULL;
-	return ret;
 }
 
 void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
@@ -170,7 +166,7 @@ void vmw_fifo_release(struct vmw_private
 	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
 		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
 
-	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+	dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
 	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
 		  dev_priv->config_done_state);
@@ -180,12 +176,7 @@ void vmw_fifo_release(struct vmw_private
 		  dev_priv->traces_state);
 
 	mutex_unlock(&dev_priv->hw_mutex);
-	vmw_fence_queue_takedown(&fifo->fence_queue);
-
-	if (likely(fifo->last_buffer != NULL)) {
-		vfree(fifo->last_buffer);
-		fifo->last_buffer = NULL;
-	}
+	vmw_marker_queue_takedown(&fifo->marker_queue);
 
 	if (likely(fifo->static_buffer != NULL)) {
 		vfree(fifo->static_buffer);
@@ -262,9 +253,8 @@ static int vmw_fifo_wait(struct vmw_priv
 		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
 		outl(SVGA_IRQFLAG_FIFO_PROGRESS,
 		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
-			  SVGA_IRQFLAG_FIFO_PROGRESS);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
 	}
 	mutex_unlock(&dev_priv->hw_mutex);
@@ -286,9 +276,8 @@ static int vmw_fifo_wait(struct vmw_priv
 	mutex_lock(&dev_priv->hw_mutex);
 	if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
 		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
-			  ~SVGA_IRQFLAG_FIFO_PROGRESS);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
 	}
 	mutex_unlock(&dev_priv->hw_mutex);
@@ -296,6 +285,16 @@ static int vmw_fifo_wait(struct vmw_priv
 	return ret;
 }
 
+/**
+ * Reserve @bytes number of bytes in the fifo.
+ *
+ * This function will return NULL (error) on two conditions:
+ *  If it timeouts waiting for fifo space, or if @bytes is larger than the
+ *   available fifo space.
+ *
+ * Returns:
+ *   Pointer to the fifo, or null on error (possible hardware hang).
+ */
 void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
 {
 	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
@@ -466,7 +465,7 @@ void vmw_fifo_commit(struct vmw_private
 	mutex_unlock(&fifo_state->fifo_mutex);
 }
 
-int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
+int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
 {
 	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
 	struct svga_fifo_cmd_fence *cmd_fence;
@@ -476,16 +475,16 @@ int vmw_fifo_send_fence(struct vmw_priva
 
 	fm = vmw_fifo_reserve(dev_priv, bytes);
 	if (unlikely(fm == NULL)) {
-		*sequence = atomic_read(&dev_priv->fence_seq);
+		*seqno = atomic_read(&dev_priv->marker_seq);
 		ret = -ENOMEM;
-		(void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+		(void)vmw_fallback_wait(dev_priv, false, true, *seqno,
 					false, 3*HZ);
 		goto out_err;
 	}
 
 	do {
-		*sequence = atomic_add_return(1, &dev_priv->fence_seq);
-	} while (*sequence == 0);
+		*seqno = atomic_add_return(1, &dev_priv->marker_seq);
+	} while (*seqno == 0);
 
 	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
 
@@ -502,61 +501,68 @@ int vmw_fifo_send_fence(struct vmw_priva
 	cmd_fence = (struct svga_fifo_cmd_fence *)
 	    ((unsigned long)fm + sizeof(__le32));
 
-	iowrite32(*sequence, &cmd_fence->fence);
-	fifo_state->last_buffer_add = true;
+	iowrite32(*seqno, &cmd_fence->fence);
 	vmw_fifo_commit(dev_priv, bytes);
-	fifo_state->last_buffer_add = false;
-	(void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
-	vmw_update_sequence(dev_priv, fifo_state);
+	(void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
+	vmw_update_seqno(dev_priv, fifo_state);
 
 out_err:
 	return ret;
 }
 
 /**
- * Map the first page of the FIFO read-only to user-space.
+ * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * This function is used to emit a dummy occlusion query with
+ * no primitives rendered between query begin and query end.
+ * It's used to provide a query barrier, in order to know that when
+ * this query is finished, all preceding queries are also finished.
+ *
+ * A Query results structure should have been initialized at the start
+ * of the dev_priv->dummy_query_bo buffer object. And that buffer object
+ * must also be either reserved or pinned when this function is called.
+ *
+ * Returns -ENOMEM on failure to reserve fifo space.
  */
-
-static int vmw_fifo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+			      uint32_t cid)
 {
-	int ret;
-	unsigned long address = (unsigned long)vmf->virtual_address;
-
-	if (address != vma->vm_start)
-		return VM_FAULT_SIGBUS;
+	/*
+	 * A query wait without a preceding query end will
+	 * actually finish all queries for this cid
+	 * without writing to the query result structure.
+	 */
 
-	ret = vm_insert_pfn(vma, address, vma->vm_pgoff);
-	if (likely(ret == -EBUSY || ret == 0))
-		return VM_FAULT_NOPAGE;
-	else if (ret == -ENOMEM)
-		return VM_FAULT_OOM;
+	struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdWaitForQuery body;
+	} *cmd;
 
-	return VM_FAULT_SIGBUS;
-}
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
 
-static struct vm_operations_struct vmw_fifo_vm_ops = {
-	.fault = vmw_fifo_vm_fault,
-	.open = NULL,
-	.close = NULL
-};
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Out of fifo space for dummy query.\n");
+		return -ENOMEM;
+	}
 
-int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct drm_file *file_priv;
-	struct vmw_private *dev_priv;
+	cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
+	cmd->header.size = sizeof(cmd->body);
+	cmd->body.cid = cid;
+	cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
 
-	file_priv = filp->private_data;
-	dev_priv = vmw_priv(file_priv->minor->dev);
+	if (bo->mem.mem_type == TTM_PL_VRAM) {
+		cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
+		cmd->body.guestResult.offset = bo->offset;
+	} else {
+		cmd->body.guestResult.gmrId = bo->mem.start;
+		cmd->body.guestResult.offset = 0;
+	}
 
-	if (vma->vm_pgoff != (dev_priv->mmio_start >> PAGE_SHIFT) ||
-	    (vma->vm_end - vma->vm_start) != PAGE_SIZE)
-		return -EINVAL;
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
-	vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_SHARED;
-	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-	vma->vm_page_prot = ttm_io_prot(TTM_PL_FLAG_UNCACHED,
-					vma->vm_page_prot);
-	vma->vm_ops = &vmw_fifo_vm_ops;
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright Â© 2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright Â© 2009-2011 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,6 +29,77 @@
 #include "drmP.h"
 #include "ttm/ttm_bo_driver.h"
 
+#define VMW_PPN_SIZE sizeof(unsigned long)
+
+static int vmw_gmr2_bind(struct vmw_private *dev_priv,
+			 struct page *pages[],
+			 unsigned long num_pages,
+			 int gmr_id)
+{
+	SVGAFifoCmdDefineGMR2 define_cmd;
+	SVGAFifoCmdRemapGMR2 remap_cmd;
+	uint32_t define_size = sizeof(define_cmd) + 4;
+	uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
+	uint32_t *cmd;
+	uint32_t *cmd_orig;
+	uint32_t i;
+
+	cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
+	if (unlikely(cmd == NULL))
+		return -ENOMEM;
+
+	define_cmd.gmrId = gmr_id;
+	define_cmd.numPages = num_pages;
+
+	remap_cmd.gmrId = gmr_id;
+	remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
+		SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
+	remap_cmd.offsetPages = 0;
+	remap_cmd.numPages = num_pages;
+
+	*cmd++ = SVGA_CMD_DEFINE_GMR2;
+	memcpy(cmd, &define_cmd, sizeof(define_cmd));
+	cmd += sizeof(define_cmd) / sizeof(uint32);
+
+	*cmd++ = SVGA_CMD_REMAP_GMR2;
+	memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
+	cmd += sizeof(remap_cmd) / sizeof(uint32);
+
+	for (i = 0; i < num_pages; ++i) {
+		if (VMW_PPN_SIZE > 4)
+			*cmd = page_to_pfn(*pages++);
+		else
+			*((uint64_t *)cmd) = page_to_pfn(*pages++);
+
+		cmd += VMW_PPN_SIZE / sizeof(*cmd);
+	}
+
+	vmw_fifo_commit(dev_priv, define_size + remap_size);
+
+	return 0;
+}
+
+static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
+			    int gmr_id)
+{
+	SVGAFifoCmdDefineGMR2 define_cmd;
+	uint32_t define_size = sizeof(define_cmd) + 4;
+	uint32_t *cmd;
+
+	cmd = vmw_fifo_reserve(dev_priv, define_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("GMR2 unbind failed.\n");
+		return;
+	}
+	define_cmd.gmrId = gmr_id;
+	define_cmd.numPages = 0;
+
+	*cmd++ = SVGA_CMD_DEFINE_GMR2;
+	memcpy(cmd, &define_cmd, sizeof(define_cmd));
+
+	vmw_fifo_commit(dev_priv, define_size);
+}
+
 /**
  * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
  * the number of used descriptors.
@@ -170,6 +241,9 @@ int vmw_gmr_bind(struct vmw_private *dev
 	struct list_head desc_pages;
 	int ret;
 
+	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
+		return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id);
+
 	if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR)))
 		return -EINVAL;
 
@@ -192,6 +266,11 @@ int vmw_gmr_bind(struct vmw_private *dev
 
 void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
 {
+	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
+		vmw_gmr2_unbind(dev_priv, gmr_id);
+		return;
+	}
+
 	mutex_lock(&dev_priv->hw_mutex);
 	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
 	wmb();
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,8 @@ struct vmwgfx_gmrid_man {
 	spinlock_t lock;
 	struct ida gmr_ida;
 	uint32_t max_gmr_ids;
+	uint32_t max_gmr_pages;
+	uint32_t used_gmr_pages;
 };
 
 static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
@@ -49,33 +51,50 @@ static int vmw_gmrid_man_get_node(struct
 {
 	struct vmwgfx_gmrid_man *gman =
 		(struct vmwgfx_gmrid_man *)man->priv;
-	int ret;
+	int ret = 0;
 	int id;
 
 	mem->mm_node = NULL;
 
-	do {
-		if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0))
-			return -ENOMEM;
+	spin_lock(&gman->lock);
 
+	if (gman->max_gmr_pages > 0) {
+		gman->used_gmr_pages += bo->num_pages;
+		if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
+			goto out_err_locked;
+	}
+
+	do {
+		spin_unlock(&gman->lock);
+		if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0)) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
 		spin_lock(&gman->lock);
-		ret = ida_get_new(&gman->gmr_ida, &id);
 
+		ret = ida_get_new(&gman->gmr_ida, &id);
 		if (unlikely(ret == 0 && id >= gman->max_gmr_ids)) {
 			ida_remove(&gman->gmr_ida, id);
-			spin_unlock(&gman->lock);
-			return 0;
+			ret = 0;
+			goto out_err_locked;
 		}
-
-		spin_unlock(&gman->lock);
-
 	} while (ret == -EAGAIN);
 
 	if (likely(ret == 0)) {
 		mem->mm_node = gman;
 		mem->start = id;
-	}
+		mem->num_pages = bo->num_pages;
+	} else
+		goto out_err_locked;
 
+	spin_unlock(&gman->lock);
+	return 0;
+
+out_err:
+	spin_lock(&gman->lock);
+out_err_locked:
+	gman->used_gmr_pages -= bo->num_pages;
+	spin_unlock(&gman->lock);
 	return ret;
 }
 
@@ -88,6 +107,7 @@ static void vmw_gmrid_man_put_node(struc
 	if (mem->mm_node) {
 		spin_lock(&gman->lock);
 		ida_remove(&gman->gmr_ida, mem->start);
+		gman->used_gmr_pages -= mem->num_pages;
 		spin_unlock(&gman->lock);
 		mem->mm_node = NULL;
 	}
@@ -96,6 +116,8 @@ static void vmw_gmrid_man_put_node(struc
 static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
 			      unsigned long p_size)
 {
+	struct vmw_private *dev_priv =
+		container_of(man->bdev, struct vmw_private, bdev);
 	struct vmwgfx_gmrid_man *gman =
 		kzalloc(sizeof(*gman), GFP_KERNEL);
 
@@ -103,6 +125,8 @@ static int vmw_gmrid_man_init(struct ttm
 		return -ENOMEM;
 
 	spin_lock_init(&gman->lock);
+	gman->max_gmr_pages = dev_priv->max_gmr_pages;
+	gman->used_gmr_pages = 0;
 	ida_init(&gman->gmr_ida);
 	gman->max_gmr_ids = p_size;
 	man->priv = (void *) gman;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include "vmwgfx_drv.h"
 #include "vmwgfx_drm.h"
+#include "vmwgfx_kms.h"
 
 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
@@ -45,9 +46,6 @@ int vmw_getparam_ioctl(struct drm_device
 	case DRM_VMW_PARAM_3D:
 		param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0;
 		break;
-	case DRM_VMW_PARAM_FIFO_OFFSET:
-		param->value = dev_priv->mmio_start;
-		break;
 	case DRM_VMW_PARAM_HW_CAPS:
 		param->value = dev_priv->capabilities;
 		break;
@@ -57,6 +55,19 @@ int vmw_getparam_ioctl(struct drm_device
 	case DRM_VMW_PARAM_MAX_FB_SIZE:
 		param->value = dev_priv->vram_size;
 		break;
+	case DRM_VMW_PARAM_FIFO_HW_VERSION:
+	{
+		__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+		const struct vmw_fifo_state *fifo = &dev_priv->fifo;
+
+		param->value =
+			ioread32(fifo_mem +
+				 ((fifo->capabilities &
+				   SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+				  SVGA_FIFO_3D_HWVERSION_REVISED :
+				  SVGA_FIFO_3D_HWVERSION));
+		break;
+	}
 	default:
 		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
 			  param->param);
@@ -66,25 +77,253 @@ int vmw_getparam_ioctl(struct drm_device
 	return 0;
 }
 
-int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+
+int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv)
 {
+	struct drm_vmw_get_3d_cap_arg *arg =
+		(struct drm_vmw_get_3d_cap_arg *) data;
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
-	struct drm_vmw_fifo_debug_arg *arg =
-	    (struct drm_vmw_fifo_debug_arg *)data;
-	__le32 __user *buffer = (__le32 __user *)
-	    (unsigned long)arg->debug_buffer;
+	uint32_t size;
+	__le32 __iomem *fifo_mem;
+	void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
+	void *bounce;
+	int ret;
 
-	if (unlikely(fifo_state->last_buffer == NULL))
+	if (unlikely(arg->pad64 != 0)) {
+		DRM_ERROR("Illegal GET_3D_CAP argument.\n");
 		return -EINVAL;
+	}
 
-	if (arg->debug_buffer_size < fifo_state->last_data_size) {
-		arg->used_size = arg->debug_buffer_size;
-		arg->did_not_fit = 1;
-	} else {
-		arg->used_size = fifo_state->last_data_size;
-		arg->did_not_fit = 0;
+	size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) << 2;
+
+	if (arg->max_size < size)
+		size = arg->max_size;
+
+	bounce = vmalloc(size);
+	if (unlikely(bounce == NULL)) {
+		DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
+		return -ENOMEM;
 	}
-	return copy_to_user(buffer, fifo_state->last_buffer, arg->used_size);
+
+	fifo_mem = dev_priv->mmio_virt;
+	memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+
+	ret = copy_to_user(buffer, bounce, size);
+	vfree(bounce);
+
+	if (unlikely(ret != 0))
+		DRM_ERROR("Failed to report 3D caps info.\n");
+
+	return ret;
+}
+
+int vmw_present_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_present_arg *arg =
+		(struct drm_vmw_present_arg *)data;
+	struct vmw_surface *surface;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct drm_vmw_rect __user *clips_ptr;
+	struct drm_vmw_rect *clips = NULL;
+	struct drm_mode_object *obj;
+	struct vmw_framebuffer *vfb;
+	uint32_t num_clips;
+	int ret;
+
+	num_clips = arg->num_clips;
+	clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+	if (unlikely(num_clips == 0))
+		return 0;
+
+	if (clips_ptr == NULL) {
+		DRM_ERROR("Variable clips_ptr must be specified.\n");
+		ret = -EINVAL;
+		goto out_clips;
+	}
+
+	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+	if (clips == NULL) {
+		DRM_ERROR("Failed to allocate clip rect list.\n");
+		ret = -ENOMEM;
+		goto out_clips;
+	}
+
+	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+	if (ret) {
+		DRM_ERROR("Failed to copy clip rects from userspace.\n");
+		ret = -EFAULT;
+		goto out_no_copy;
+	}
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTARTSYS;
+		goto out_no_mode_mutex;
+	}
+
+	obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_ERROR("Invalid framebuffer id.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+	vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		goto out_no_ttm_lock;
+
+	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid,
+					     &surface);
+	if (ret)
+		goto out_no_surface;
+
+	ret = vmw_kms_present(dev_priv, file_priv,
+			      vfb, surface, arg->sid,
+			      arg->dest_x, arg->dest_y,
+			      clips, num_clips);
+
+	/* vmw_user_surface_lookup takes one ref so does new_fb */
+	vmw_surface_unreference(&surface);
+
+out_no_surface:
+	ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+	mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+	kfree(clips);
+out_clips:
+	return ret;
+}
+
+int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_present_readback_arg *arg =
+		(struct drm_vmw_present_readback_arg *)data;
+	struct drm_vmw_fence_rep __user *user_fence_rep =
+		(struct drm_vmw_fence_rep __user *)
+		(unsigned long)arg->fence_rep;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct drm_vmw_rect __user *clips_ptr;
+	struct drm_vmw_rect *clips = NULL;
+	struct drm_mode_object *obj;
+	struct vmw_framebuffer *vfb;
+	uint32_t num_clips;
+	int ret;
+
+	num_clips = arg->num_clips;
+	clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+	if (unlikely(num_clips == 0))
+		return 0;
+
+	if (clips_ptr == NULL) {
+		DRM_ERROR("Argument clips_ptr must be specified.\n");
+		ret = -EINVAL;
+		goto out_clips;
+	}
+
+	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+	if (clips == NULL) {
+		DRM_ERROR("Failed to allocate clip rect list.\n");
+		ret = -ENOMEM;
+		goto out_clips;
+	}
+
+	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+	if (ret) {
+		DRM_ERROR("Failed to copy clip rects from userspace.\n");
+		ret = -EFAULT;
+		goto out_no_copy;
+	}
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTARTSYS;
+		goto out_no_mode_mutex;
+	}
+
+	obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_ERROR("Invalid framebuffer id.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+
+	vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+	if (!vfb->dmabuf) {
+		DRM_ERROR("Framebuffer not dmabuf backed.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		goto out_no_ttm_lock;
+
+	ret = vmw_kms_readback(dev_priv, file_priv,
+			       vfb, user_fence_rep,
+			       clips, num_clips);
+
+	ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+	mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+	kfree(clips);
+out_clips:
+	return ret;
+}
+
+
+/**
+ * vmw_fops_poll - wrapper around the drm_poll function
+ *
+ * @filp: See the linux fops poll documentation.
+ * @wait: See the linux fops poll documentation.
+ *
+ * Wrapper around the drm_poll function that makes sure the device is
+ * processing the fifo if drm_poll decides to wait.
+ */
+unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct vmw_private *dev_priv =
+		vmw_priv(file_priv->minor->dev);
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	return drm_poll(filp, wait);
+}
+
+
+/**
+ * vmw_fops_read - wrapper around the drm_read function
+ *
+ * @filp: See the linux fops read documentation.
+ * @buffer: See the linux fops read documentation.
+ * @count: See the linux fops read documentation.
+ * offset: See the linux fops read documentation.
+ *
+ * Wrapper around the drm_read function that makes sure the device is
+ * processing the fifo if drm_read decides to wait.
+ */
+ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+		      size_t count, loff_t *offset)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct vmw_private *dev_priv =
+		vmw_priv(file_priv->minor->dev);
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	return drm_read(filp, buffer, count, offset);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,26 +34,33 @@ irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS
 {
 	struct drm_device *dev = (struct drm_device *)arg;
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	uint32_t status;
+	uint32_t status, masked_status;
 
 	spin_lock(&dev_priv->irq_lock);
 	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	masked_status = status & dev_priv->irq_mask;
 	spin_unlock(&dev_priv->irq_lock);
 
-	if (status & SVGA_IRQFLAG_ANY_FENCE)
+	if (likely(status))
+		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+
+	if (!masked_status)
+		return IRQ_NONE;
+
+	if (masked_status & (SVGA_IRQFLAG_ANY_FENCE |
+			     SVGA_IRQFLAG_FENCE_GOAL)) {
+		vmw_fences_update(dev_priv->fman);
 		wake_up_all(&dev_priv->fence_queue);
-	if (status & SVGA_IRQFLAG_FIFO_PROGRESS)
+	}
+
+	if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS)
 		wake_up_all(&dev_priv->fifo_queue);
 
-	if (likely(status)) {
-		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		return IRQ_HANDLED;
-	}
 
-	return IRQ_NONE;
+	return IRQ_HANDLED;
 }
 
-static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
+static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
 {
 	uint32_t busy;
 
@@ -64,43 +71,43 @@ static bool vmw_fifo_idle(struct vmw_pri
 	return (busy == 0);
 }
 
-void vmw_update_sequence(struct vmw_private *dev_priv,
+void vmw_update_seqno(struct vmw_private *dev_priv,
 			 struct vmw_fifo_state *fifo_state)
 {
 	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
-	uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
-
-	if (dev_priv->last_read_sequence != sequence) {
-		dev_priv->last_read_sequence = sequence;
-		vmw_fence_pull(&fifo_state->fence_queue, sequence);
+	if (dev_priv->last_read_seqno != seqno) {
+		dev_priv->last_read_seqno = seqno;
+		vmw_marker_pull(&fifo_state->marker_queue, seqno);
+		vmw_fences_update(dev_priv->fman);
 	}
 }
 
-bool vmw_fence_signaled(struct vmw_private *dev_priv,
-			uint32_t sequence)
+bool vmw_seqno_passed(struct vmw_private *dev_priv,
+			 uint32_t seqno)
 {
 	struct vmw_fifo_state *fifo_state;
 	bool ret;
 
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return true;
 
 	fifo_state = &dev_priv->fifo;
-	vmw_update_sequence(dev_priv, fifo_state);
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	vmw_update_seqno(dev_priv, fifo_state);
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return true;
 
 	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
-	    vmw_fifo_idle(dev_priv, sequence))
+	    vmw_fifo_idle(dev_priv, seqno))
 		return true;
 
 	/**
-	 * Then check if the sequence is higher than what we've actually
+	 * Then check if the seqno is higher than what we've actually
 	 * emitted. Then the fence is stale and signaled.
 	 */
 
-	ret = ((atomic_read(&dev_priv->fence_seq) - sequence)
+	ret = ((atomic_read(&dev_priv->marker_seq) - seqno)
 	       > VMW_FENCE_WRAP);
 
 	return ret;
@@ -109,7 +116,7 @@ bool vmw_fence_signaled(struct vmw_priva
 int vmw_fallback_wait(struct vmw_private *dev_priv,
 		      bool lazy,
 		      bool fifo_idle,
-		      uint32_t sequence,
+		      uint32_t seqno,
 		      bool interruptible,
 		      unsigned long timeout)
 {
@@ -123,7 +130,7 @@ int vmw_fallback_wait(struct vmw_private
 	DEFINE_WAIT(__wait);
 
 	wait_condition = (fifo_idle) ? &vmw_fifo_idle :
-		&vmw_fence_signaled;
+		&vmw_seqno_passed;
 
 	/**
 	 * Block command submission while waiting for idle.
@@ -131,14 +138,14 @@ int vmw_fallback_wait(struct vmw_private
 
 	if (fifo_idle)
 		down_read(&fifo_state->rwsem);
-	signal_seq = atomic_read(&dev_priv->fence_seq);
+	signal_seq = atomic_read(&dev_priv->marker_seq);
 	ret = 0;
 
 	for (;;) {
 		prepare_to_wait(&dev_priv->fence_queue, &__wait,
 				(interruptible) ?
 				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		if (wait_condition(dev_priv, sequence))
+		if (wait_condition(dev_priv, seqno))
 			break;
 		if (time_after_eq(jiffies, end_jiffies)) {
 			DRM_ERROR("SVGA device lockup.\n");
@@ -175,68 +182,110 @@ int vmw_fallback_wait(struct vmw_private
 	return ret;
 }
 
-int vmw_wait_fence(struct vmw_private *dev_priv,
-		   bool lazy, uint32_t sequence,
-		   bool interruptible, unsigned long timeout)
+void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (dev_priv->fence_queue_waiters++ == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_ANY_FENCE,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (--dev_priv->fence_queue_waiters == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+
+void vmw_goal_waiter_add(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (dev_priv->goal_queue_waiters++ == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_FENCE_GOAL,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (--dev_priv->goal_queue_waiters == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+int vmw_wait_seqno(struct vmw_private *dev_priv,
+		      bool lazy, uint32_t seqno,
+		      bool interruptible, unsigned long timeout)
 {
 	long ret;
-	unsigned long irq_flags;
 	struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return 0;
 
-	if (likely(vmw_fence_signaled(dev_priv, sequence)))
+	if (likely(vmw_seqno_passed(dev_priv, seqno)))
 		return 0;
 
 	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 
 	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
-		return vmw_fallback_wait(dev_priv, lazy, true, sequence,
+		return vmw_fallback_wait(dev_priv, lazy, true, seqno,
 					 interruptible, timeout);
 
 	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
-		return vmw_fallback_wait(dev_priv, lazy, false, sequence,
+		return vmw_fallback_wait(dev_priv, lazy, false, seqno,
 					 interruptible, timeout);
 
-	mutex_lock(&dev_priv->hw_mutex);
-	if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
-		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		outl(SVGA_IRQFLAG_ANY_FENCE,
-		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
-			  SVGA_IRQFLAG_ANY_FENCE);
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-	}
-	mutex_unlock(&dev_priv->hw_mutex);
+	vmw_seqno_waiter_add(dev_priv);
 
 	if (interruptible)
 		ret = wait_event_interruptible_timeout
 		    (dev_priv->fence_queue,
-		     vmw_fence_signaled(dev_priv, sequence),
+		     vmw_seqno_passed(dev_priv, seqno),
 		     timeout);
 	else
 		ret = wait_event_timeout
 		    (dev_priv->fence_queue,
-		     vmw_fence_signaled(dev_priv, sequence),
+		     vmw_seqno_passed(dev_priv, seqno),
 		     timeout);
 
+	vmw_seqno_waiter_remove(dev_priv);
+
 	if (unlikely(ret == 0))
 		ret = -EBUSY;
 	else if (likely(ret > 0))
 		ret = 0;
 
-	mutex_lock(&dev_priv->hw_mutex);
-	if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
-		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
-			  ~SVGA_IRQFLAG_ANY_FENCE);
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-	}
-	mutex_unlock(&dev_priv->hw_mutex);
-
 	return ret;
 }
 
@@ -273,25 +322,3 @@ void vmw_irq_uninstall(struct drm_device
 	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
 	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
 }
-
-#define VMW_FENCE_WAIT_TIMEOUT 3*HZ;
-
-int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	struct drm_vmw_fence_wait_arg *arg =
-	    (struct drm_vmw_fence_wait_arg *)data;
-	unsigned long timeout;
-
-	if (!arg->cookie_valid) {
-		arg->cookie_valid = 1;
-		arg->kernel_cookie = jiffies + VMW_FENCE_WAIT_TIMEOUT;
-	}
-
-	timeout = jiffies;
-	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie))
-		return -EBUSY;
-
-	timeout = (unsigned long)arg->kernel_cookie - timeout;
-	return vmw_wait_fence(vmw_priv(dev), true, arg->sequence, true, timeout);
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,11 +27,47 @@
 
 #include "vmwgfx_kms.h"
 
+
 /* Might need a hrtimer here? */
 #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
 
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
+
+struct vmw_clip_rect {
+	int x1, x2, y1, y2;
+};
+
+/**
+ * Clip @num_rects number of @rects against @clip storing the
+ * results in @out_rects and the number of passed rects in @out_num.
+ */
+void vmw_clip_cliprects(struct drm_clip_rect *rects,
+			int num_rects,
+			struct vmw_clip_rect clip,
+			SVGASignedRect *out_rects,
+			int *out_num)
+{
+	int i, k;
+
+	for (i = 0, k = 0; i < num_rects; i++) {
+		int x1 = max_t(int, clip.x1, rects[i].x1);
+		int y1 = max_t(int, clip.y1, rects[i].y1);
+		int x2 = min_t(int, clip.x2, rects[i].x2);
+		int y2 = min_t(int, clip.y2, rects[i].y2);
+
+		if (x1 >= x2)
+			continue;
+		if (y1 >= y2)
+			continue;
+
+		out_rects[k].left   = x1;
+		out_rects[k].top    = y1;
+		out_rects[k].right  = x2;
+		out_rects[k].bottom = y2;
+		k++;
+	}
+
+	*out_num = k;
+}
 
 void vmw_display_unit_cleanup(struct vmw_display_unit *du)
 {
@@ -84,6 +120,43 @@ int vmw_cursor_update_image(struct vmw_p
 	return 0;
 }
 
+int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
+			     struct vmw_dma_buffer *dmabuf,
+			     u32 width, u32 height,
+			     u32 hotspotX, u32 hotspotY)
+{
+	struct ttm_bo_kmap_obj map;
+	unsigned long kmap_offset;
+	unsigned long kmap_num;
+	void *virtual;
+	bool dummy;
+	int ret;
+
+	kmap_offset = 0;
+	kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("reserve failed\n");
+		return -EINVAL;
+	}
+
+	ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0))
+		goto err_unreserve;
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+	ret = vmw_cursor_update_image(dev_priv, virtual, width, height,
+				      hotspotX, hotspotY);
+
+	ttm_bo_kunmap(&map);
+err_unreserve:
+	ttm_bo_unreserve(&dmabuf->base);
+
+	return ret;
+}
+
+
 void vmw_cursor_update_position(struct vmw_private *dev_priv,
 				bool show, int x, int y)
 {
@@ -107,24 +180,26 @@ int vmw_du_crtc_cursor_set(struct drm_cr
 	struct vmw_dma_buffer *dmabuf = NULL;
 	int ret;
 
+	/* A lot of the code assumes this */
+	if (handle && (width != 64 || height != 64))
+		return -EINVAL;
+
 	if (handle) {
-		ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
-						     handle, &surface);
-		if (!ret) {
-			if (!surface->snooper.image) {
-				DRM_ERROR("surface not suitable for cursor\n");
-				return -EINVAL;
-			}
-		} else {
-			ret = vmw_user_dmabuf_lookup(tfile,
-						     handle, &dmabuf);
-			if (ret) {
-				DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
-				return -EINVAL;
-			}
+		ret = vmw_user_lookup_handle(dev_priv, tfile,
+					     handle, &surface, &dmabuf);
+		if (ret) {
+			DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
+			return -EINVAL;
 		}
 	}
 
+	/* need to do this before taking down old image */
+	if (surface && !surface->snooper.image) {
+		DRM_ERROR("surface not suitable for cursor\n");
+		vmw_surface_unreference(&surface);
+		return -EINVAL;
+	}
+
 	/* takedown old cursor */
 	if (du->cursor_surface) {
 		du->cursor_surface->snooper.crtc = NULL;
@@ -143,42 +218,19 @@ int vmw_du_crtc_cursor_set(struct drm_cr
 		vmw_cursor_update_image(dev_priv, surface->snooper.image,
 					64, 64, du->hotspot_x, du->hotspot_y);
 	} else if (dmabuf) {
-		struct ttm_bo_kmap_obj map;
-		unsigned long kmap_offset;
-		unsigned long kmap_num;
-		void *virtual;
-		bool dummy;
-
 		/* vmw_user_surface_lookup takes one reference */
 		du->cursor_dmabuf = dmabuf;
 
-		kmap_offset = 0;
-		kmap_num = (64*64*4) >> PAGE_SHIFT;
-
-		ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("reserve failed\n");
-			return -EINVAL;
-		}
-
-		ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
-		if (unlikely(ret != 0))
-			goto err_unreserve;
-
-		virtual = ttm_kmap_obj_virtual(&map, &dummy);
-		vmw_cursor_update_image(dev_priv, virtual, 64, 64,
-					du->hotspot_x, du->hotspot_y);
-
-		ttm_bo_kunmap(&map);
-err_unreserve:
-		ttm_bo_unreserve(&dmabuf->base);
-
+		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
+					       du->hotspot_x, du->hotspot_y);
 	} else {
 		vmw_cursor_update_position(dev_priv, false, 0, 0);
 		return 0;
 	}
 
-	vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y);
+	vmw_cursor_update_position(dev_priv, true,
+				   du->cursor_x + du->hotspot_x,
+				   du->cursor_y + du->hotspot_y);
 
 	return 0;
 }
@@ -193,7 +245,8 @@ int vmw_du_crtc_cursor_move(struct drm_c
 	du->cursor_y = y + crtc->y;
 
 	vmw_cursor_update_position(dev_priv, shown,
-				   du->cursor_x, du->cursor_y);
+				   du->cursor_x + du->hotspot_x,
+				   du->cursor_y + du->hotspot_y);
 
 	return 0;
 }
@@ -214,7 +267,7 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 		SVGA3dCmdHeader header;
 		SVGA3dCmdSurfaceDMA dma;
 	} *cmd;
-	int ret;
+	int i, ret;
 
 	cmd = container_of(header, struct vmw_dma_cmd, header);
 
@@ -236,16 +289,19 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 	box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
 			sizeof(SVGA3dCopyBox);
 
-	if (cmd->dma.guest.pitch != (64 * 4) ||
-	    cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+	if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
 	    box->x != 0    || box->y != 0    || box->z != 0    ||
 	    box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
-	    box->w != 64   || box->h != 64   || box->d != 1    ||
-	    box_count != 1) {
+	    box->d != 1    || box_count != 1) {
 		/* TODO handle none page aligned offsets */
-		/* TODO handle partial uploads and pitch != 256 */
-		/* TODO handle more then one copy (size != 64) */
-		DRM_ERROR("lazy programmer, can't handle weird stuff\n");
+		/* TODO handle more dst & src != 0 */
+		/* TODO handle more then one copy */
+		DRM_ERROR("Cant snoop dma request for cursor!\n");
+		DRM_ERROR("(%u, %u, %u) (%u, %u, %u) (%ux%ux%u) %u %u\n",
+			  box->srcx, box->srcy, box->srcz,
+			  box->x, box->y, box->z,
+			  box->w, box->h, box->d, box_count,
+			  cmd->dma.guest.ptr.offset);
 		return;
 	}
 
@@ -264,7 +320,16 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 
 	virtual = ttm_kmap_obj_virtual(&map, &dummy);
 
-	memcpy(srf->snooper.image, virtual, 64*64*4);
+	if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
+		memcpy(srf->snooper.image, virtual, 64*64*4);
+	} else {
+		/* Image is unsigned pointer. */
+		for (i = 0; i < box->h; i++)
+			memcpy(srf->snooper.image + i * 64,
+			       virtual + i * cmd->dma.guest.pitch,
+			       box->w * 4);
+	}
+
 	srf->snooper.age++;
 
 	/* we can't call this function from this function since execbuf has
@@ -329,41 +394,10 @@ struct vmw_framebuffer_surface {
 	struct vmw_framebuffer base;
 	struct vmw_surface *surface;
 	struct vmw_dma_buffer *buffer;
-	struct delayed_work d_work;
-	struct mutex work_lock;
-	bool present_fs;
 	struct list_head head;
 	struct drm_master *master;
 };
 
-/**
- * vmw_kms_idle_workqueues - Flush workqueues on this master
- *
- * @vmaster - Pointer identifying the master, for the surfaces of which
- * we idle the dirty work queues.
- *
- * This function should be called with the ttm lock held in exclusive mode
- * to idle all dirty work queues before the fifo is taken down.
- *
- * The work task may actually requeue itself, but after the flush returns we're
- * sure that there's nothing to present, since the ttm lock is held in
- * exclusive mode, so the fifo will never get used.
- */
-
-void vmw_kms_idle_workqueues(struct vmw_master *vmaster)
-{
-	struct vmw_framebuffer_surface *entry;
-
-	mutex_lock(&vmaster->fb_surf_mutex);
-	list_for_each_entry(entry, &vmaster->fb_surf, head) {
-		if (cancel_delayed_work_sync(&entry->d_work))
-			(void) entry->d_work.work.func(&entry->d_work.work);
-
-		(void) cancel_delayed_work_sync(&entry->d_work);
-	}
-	mutex_unlock(&vmaster->fb_surf_mutex);
-}
-
 void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
 {
 	struct vmw_framebuffer_surface *vfbs =
@@ -375,64 +409,157 @@ void vmw_framebuffer_surface_destroy(str
 	list_del(&vfbs->head);
 	mutex_unlock(&vmaster->fb_surf_mutex);
 
-	cancel_delayed_work_sync(&vfbs->d_work);
 	drm_master_put(&vfbs->master);
 	drm_framebuffer_cleanup(framebuffer);
 	vmw_surface_unreference(&vfbs->surface);
+	ttm_base_object_unref(&vfbs->base.user_obj);
 
 	kfree(vfbs);
 }
 
-static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
+static int do_surface_dirty_sou(struct vmw_private *dev_priv,
+				struct drm_file *file_priv,
+				struct vmw_framebuffer *framebuffer,
+				unsigned flags, unsigned color,
+				struct drm_clip_rect *clips,
+				unsigned num_clips, int inc)
 {
-	struct delayed_work *d_work =
-		container_of(work, struct delayed_work, work);
-	struct vmw_framebuffer_surface *vfbs =
-		container_of(d_work, struct vmw_framebuffer_surface, d_work);
-	struct vmw_surface *surf = vfbs->surface;
-	struct drm_framebuffer *framebuffer = &vfbs->base.base;
-	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *clips_ptr;
+	struct drm_clip_rect *tmp;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, num_units;
+	int ret = 0; /* silence warning */
+	int left, right, top, bottom;
 
 	struct {
 		SVGA3dCmdHeader header;
-		SVGA3dCmdPresent body;
-		SVGA3dCopyRect cr;
+		SVGA3dCmdBlitSurfaceToScreen body;
 	} *cmd;
+	SVGASignedRect *blits;
 
-	/**
-	 * Strictly we should take the ttm_lock in read mode before accessing
-	 * the fifo, to make sure the fifo is present and up. However,
-	 * instead we flush all workqueues under the ttm lock in exclusive mode
-	 * before taking down the fifo.
-	 */
-	mutex_lock(&vfbs->work_lock);
-	if (!vfbs->present_fs)
-		goto out_unlock;
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
+			    head) {
+		if (crtc->fb != &framebuffer->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-	if (unlikely(cmd == NULL))
-		goto out_resched;
+	BUG_ON(!clips || !num_clips);
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr));
-	cmd->body.sid = cpu_to_le32(surf->res.id);
-	cmd->cr.x = cpu_to_le32(0);
-	cmd->cr.y = cpu_to_le32(0);
-	cmd->cr.srcx = cmd->cr.x;
-	cmd->cr.srcy = cmd->cr.y;
-	cmd->cr.w = cpu_to_le32(framebuffer->width);
-	cmd->cr.h = cpu_to_le32(framebuffer->height);
-	vfbs->present_fs = false;
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-out_resched:
-	/**
-	 * Will not re-add if already pending.
-	 */
-	schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
-out_unlock:
-	mutex_unlock(&vfbs->work_lock);
-}
+	tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL);
+	if (unlikely(tmp == NULL)) {
+		DRM_ERROR("Temporary cliprect memory alloc failed.\n");
+		return -ENOMEM;
+	}
+
+	fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+	cmd = kzalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Temporary fifo memory alloc failed.\n");
+		ret = -ENOMEM;
+		goto out_free_tmp;
+	}
+
+	/* setup blits pointer */
+	blits = (SVGASignedRect *)&cmd[1];
+
+	/* initial clip region */
+	left = clips->x1;
+	right = clips->x2;
+	top = clips->y1;
+	bottom = clips->y2;
+
+	/* skip the first clip rect */
+	for (i = 1, clips_ptr = clips + inc;
+	     i < num_clips; i++, clips_ptr += inc) {
+		left = min_t(int, left, (int)clips_ptr->x1);
+		right = max_t(int, right, (int)clips_ptr->x2);
+		top = min_t(int, top, (int)clips_ptr->y1);
+		bottom = max_t(int, bottom, (int)clips_ptr->y2);
+	}
+
+	/* only need to do this once */
+	memset(cmd, 0, fifo_size);
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+	cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+
+	cmd->body.srcRect.left = left;
+	cmd->body.srcRect.right = right;
+	cmd->body.srcRect.top = top;
+	cmd->body.srcRect.bottom = bottom;
+
+	clips_ptr = clips;
+	for (i = 0; i < num_clips; i++, clips_ptr += inc) {
+		tmp[i].x1 = clips_ptr->x1 - left;
+		tmp[i].x2 = clips_ptr->x2 - left;
+		tmp[i].y1 = clips_ptr->y1 - top;
+		tmp[i].y2 = clips_ptr->y2 - top;
+	}
+
+	/* do per unit writing, reuse fifo for each */
+	for (i = 0; i < num_units; i++) {
+		struct vmw_display_unit *unit = units[i];
+		struct vmw_clip_rect clip;
+		int num;
+
+		clip.x1 = left - unit->crtc.x;
+		clip.y1 = top - unit->crtc.y;
+		clip.x2 = right - unit->crtc.x;
+		clip.y2 = bottom - unit->crtc.y;
+
+		/* skip any crtcs that misses the clip region */
+		if (clip.x1 >= unit->crtc.mode.hdisplay ||
+		    clip.y1 >= unit->crtc.mode.vdisplay ||
+		    clip.x2 <= 0 || clip.y2 <= 0)
+			continue;
+
+		/*
+		 * In order for the clip rects to be correctly scaled
+		 * the src and dest rects needs to be the same size.
+		 */
+		cmd->body.destRect.left = clip.x1;
+		cmd->body.destRect.right = clip.x2;
+		cmd->body.destRect.top = clip.y1;
+		cmd->body.destRect.bottom = clip.y2;
+
+		/* create a clip rect of the crtc in dest coords */
+		clip.x2 = unit->crtc.mode.hdisplay - clip.x1;
+		clip.y2 = unit->crtc.mode.vdisplay - clip.y1;
+		clip.x1 = 0 - clip.x1;
+		clip.y1 = 0 - clip.y1;
+
+		/* need to reset sid as it is changed by execbuf */
+		cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle);
+		cmd->body.destScreenId = unit->unit;
+
+		/* clip and write blits to cmd stream */
+		vmw_clip_cliprects(tmp, num_clips, clip, blits, &num);
+
+		/* if no cliprects hit skip this */
+		if (num == 0)
+			continue;
+
+
+		/* recalculate package length */
+		fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num;
+		cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+					  fifo_size, 0, NULL);
 
+		if (unlikely(ret != 0))
+			break;
+	}
+
+
+	kfree(cmd);
+out_free_tmp:
+	kfree(tmp);
+
+	return ret;
+}
 
 int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 				  struct drm_file *file_priv,
@@ -444,44 +571,20 @@ int vmw_framebuffer_surface_dirty(struct
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	struct vmw_framebuffer_surface *vfbs =
 		vmw_framebuffer_to_vfbs(framebuffer);
-	struct vmw_surface *surf = vfbs->surface;
 	struct drm_clip_rect norect;
-	SVGA3dCopyRect *cr;
-	int i, inc = 1;
-	int ret;
-
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdPresent body;
-		SVGA3dCopyRect cr;
-	} *cmd;
+	int ret, inc = 1;
 
 	if (unlikely(vfbs->master != file_priv->master))
 		return -EINVAL;
 
+	/* Require ScreenObject support for 3D */
+	if (!dev_priv->sou_priv)
+		return -EINVAL;
+
 	ret = ttm_read_lock(&vmaster->lock, true);
 	if (unlikely(ret != 0))
 		return ret;
 
-	if (!num_clips ||
-	    !(dev_priv->fifo.capabilities &
-	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
-		int ret;
-
-		mutex_lock(&vfbs->work_lock);
-		vfbs->present_fs = true;
-		ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
-		mutex_unlock(&vfbs->work_lock);
-		if (ret) {
-			/**
-			 * No work pending, Force immediate present.
-			 */
-			vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
-		}
-		ttm_read_unlock(&vmaster->lock);
-		return 0;
-	}
-
 	if (!num_clips) {
 		num_clips = 1;
 		clips = &norect;
@@ -493,29 +596,10 @@ int vmw_framebuffer_surface_dirty(struct
 		inc = 2; /* skip source rects */
 	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Fifo reserve failed.\n");
-		ttm_read_unlock(&vmaster->lock);
-		return -ENOMEM;
-	}
-
-	memset(cmd, 0, sizeof(*cmd));
-
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr));
-	cmd->body.sid = cpu_to_le32(surf->res.id);
-
-	for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) {
-		cr->x = cpu_to_le16(clips->x1);
-		cr->y = cpu_to_le16(clips->y1);
-		cr->srcx = cr->x;
-		cr->srcy = cr->y;
-		cr->w = cpu_to_le16(clips->x2 - clips->x1);
-		cr->h = cpu_to_le16(clips->y2 - clips->y1);
-	}
+	ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base,
+				   flags, color,
+				   clips, num_clips, inc);
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
 	ttm_read_unlock(&vmaster->lock);
 	return 0;
 }
@@ -540,10 +624,18 @@ static int vmw_kms_new_framebuffer_surfa
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
+	/* 3D is only supported on HWv8 hosts which supports screen objects */
+	if (!dev_priv->sou_priv)
+		return -ENOSYS;
+
 	/*
 	 * Sanity checks.
 	 */
 
+	/* Surface must be marked as a scanout. */
+	if (unlikely(!surface->scanout))
+		return -EINVAL;
+
 	if (unlikely(surface->mip_levels[0] != 1 ||
 		     surface->num_sizes != 1 ||
 		     surface->sizes[0].width < mode_cmd->width ||
@@ -567,6 +659,9 @@ static int vmw_kms_new_framebuffer_surfa
 	case 15:
 		format = SVGA3D_A1R5G5B5;
 		break;
+	case 8:
+		format = SVGA3D_LUMINANCE8;
+		break;
 	default:
 		DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
 		return -EINVAL;
@@ -599,14 +694,11 @@ static int vmw_kms_new_framebuffer_surfa
 	vfbs->base.base.depth = mode_cmd->depth;
 	vfbs->base.base.width = mode_cmd->width;
 	vfbs->base.base.height = mode_cmd->height;
-	vfbs->base.pin = &vmw_surface_dmabuf_pin;
-	vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
 	vfbs->surface = surface;
+	vfbs->base.user_handle = mode_cmd->handle;
 	vfbs->master = drm_master_get(file_priv->master);
-	mutex_init(&vfbs->work_lock);
 
 	mutex_lock(&vmaster->fb_surf_mutex);
-	INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
 	list_add_tail(&vfbs->head, &vmaster->fb_surf);
 	mutex_unlock(&vmaster->fb_surf_mutex);
 
@@ -641,48 +733,33 @@ void vmw_framebuffer_dmabuf_destroy(stru
 
 	drm_framebuffer_cleanup(framebuffer);
 	vmw_dmabuf_unreference(&vfbd->buffer);
+	ttm_base_object_unref(&vfbd->base.user_obj);
 
 	kfree(vfbd);
 }
 
-int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
-				 struct drm_file *file_priv,
-				 unsigned flags, unsigned color,
-				 struct drm_clip_rect *clips,
-				 unsigned num_clips)
+static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv,
+			       struct vmw_framebuffer *framebuffer,
+			       unsigned flags, unsigned color,
+			       struct drm_clip_rect *clips,
+			       unsigned num_clips, int increment)
 {
-	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
-	struct drm_clip_rect norect;
-	int ret;
+	size_t fifo_size;
+	int i;
+
 	struct {
 		uint32_t header;
 		SVGAFifoCmdUpdate body;
 	} *cmd;
-	int i, increment = 1;
-
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
-
-	if (!num_clips) {
-		num_clips = 1;
-		clips = &norect;
-		norect.x1 = norect.y1 = 0;
-		norect.x2 = framebuffer->width;
-		norect.y2 = framebuffer->height;
-	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
-		num_clips /= 2;
-		increment = 2;
-	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
+	fifo_size = sizeof(*cmd) * num_clips;
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Fifo reserve failed.\n");
-		ttm_read_unlock(&vmaster->lock);
 		return -ENOMEM;
 	}
 
+	memset(cmd, 0, fifo_size);
 	for (i = 0; i < num_clips; i++, clips += increment) {
 		cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
 		cmd[i].body.x = cpu_to_le32(clips->x1);
@@ -691,57 +768,196 @@ int vmw_framebuffer_dmabuf_dirty(struct
 		cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
 	}
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
-	ttm_read_unlock(&vmaster->lock);
-
+	vmw_fifo_commit(dev_priv, fifo_size);
 	return 0;
 }
 
-static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
-	.destroy = vmw_framebuffer_dmabuf_destroy,
-	.dirty = vmw_framebuffer_dmabuf_dirty,
-	.create_handle = vmw_framebuffer_create_handle,
-};
-
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+static int do_dmabuf_define_gmrfb(struct drm_file *file_priv,
+				  struct vmw_private *dev_priv,
+				  struct vmw_framebuffer *framebuffer)
 {
-	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
-	struct vmw_framebuffer_surface *vfbs =
-		vmw_framebuffer_to_vfbs(&vfb->base);
-	unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+	int depth = framebuffer->base.depth;
+	size_t fifo_size;
 	int ret;
 
-	vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
-	if (unlikely(vfbs->buffer == NULL))
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd;
+
+	/* Emulate RGBA support, contrary to svga_reg.h this is not
+	 * supported by hosts. This is only a problem if we are reading
+	 * this value later and expecting what we uploaded back.
+	 */
+	if (depth == 32)
+		depth = 24;
+
+	fifo_size = sizeof(*cmd);
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
 		return -ENOMEM;
+	}
 
-	vmw_overlay_pause_all(dev_priv);
-	ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
-			       &vmw_vram_ne_placement,
-			       false, &vmw_dmabuf_bo_free);
-	vmw_overlay_resume_all(dev_priv);
+	memset(cmd, 0, fifo_size);
+	cmd->header = SVGA_CMD_DEFINE_GMRFB;
+	cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
+	cmd->body.format.colorDepth = depth;
+	cmd->body.format.reserved = 0;
+	cmd->body.bytesPerLine = framebuffer->base.pitch;
+	cmd->body.ptr.gmrId = framebuffer->user_handle;
+	cmd->body.ptr.offset = 0;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+				  fifo_size, 0, NULL);
+
+	kfree(cmd);
+
+	return ret;
+}
+
+static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       struct vmw_framebuffer *framebuffer,
+			       unsigned flags, unsigned color,
+			       struct drm_clip_rect *clips,
+			       unsigned num_clips, int increment)
+{
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *clips_ptr;
+	int i, k, num_units, ret;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdBlitGMRFBToScreen body;
+	} *blits;
+
+	ret = do_dmabuf_define_gmrfb(file_priv, dev_priv, framebuffer);
 	if (unlikely(ret != 0))
-		vfbs->buffer = NULL;
+		return ret; /* define_gmrfb prints warnings */
+
+	fifo_size = sizeof(*blits) * num_clips;
+	blits = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(blits == NULL)) {
+		DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
+		return -ENOMEM;
+	}
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &framebuffer->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
+
+	for (k = 0; k < num_units; k++) {
+		struct vmw_display_unit *unit = units[k];
+		int hit_num = 0;
+
+		clips_ptr = clips;
+		for (i = 0; i < num_clips; i++, clips_ptr += increment) {
+			int clip_x1 = clips_ptr->x1 - unit->crtc.x;
+			int clip_y1 = clips_ptr->y1 - unit->crtc.y;
+			int clip_x2 = clips_ptr->x2 - unit->crtc.x;
+			int clip_y2 = clips_ptr->y2 - unit->crtc.y;
+			int move_x, move_y;
+
+			/* skip any crtcs that misses the clip region */
+			if (clip_x1 >= unit->crtc.mode.hdisplay ||
+			    clip_y1 >= unit->crtc.mode.vdisplay ||
+			    clip_x2 <= 0 || clip_y2 <= 0)
+				continue;
+
+			/* clip size to crtc size */
+			clip_x2 = min_t(int, clip_x2, unit->crtc.mode.hdisplay);
+			clip_y2 = min_t(int, clip_y2, unit->crtc.mode.vdisplay);
+
+			/* translate both src and dest to bring clip into screen */
+			move_x = min_t(int, clip_x1, 0);
+			move_y = min_t(int, clip_y1, 0);
+
+			/* actual translate done here */
+			blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
+			blits[hit_num].body.destScreenId = unit->unit;
+			blits[hit_num].body.srcOrigin.x = clips_ptr->x1 - move_x;
+			blits[hit_num].body.srcOrigin.y = clips_ptr->y1 - move_y;
+			blits[hit_num].body.destRect.left = clip_x1 - move_x;
+			blits[hit_num].body.destRect.top = clip_y1 - move_y;
+			blits[hit_num].body.destRect.right = clip_x2;
+			blits[hit_num].body.destRect.bottom = clip_y2;
+			hit_num++;
+		}
+
+		/* no clips hit the crtc */
+		if (hit_num == 0)
+			continue;
+
+		fifo_size = sizeof(*blits) * hit_num;
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits,
+					  fifo_size, 0, NULL);
+
+		if (unlikely(ret != 0))
+			break;
+	}
+
+	kfree(blits);
 
 	return ret;
 }
 
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+				 struct drm_file *file_priv,
+				 unsigned flags, unsigned color,
+				 struct drm_clip_rect *clips,
+				 unsigned num_clips)
 {
-	struct ttm_buffer_object *bo;
-	struct vmw_framebuffer_surface *vfbs =
-		vmw_framebuffer_to_vfbs(&vfb->base);
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(framebuffer);
+	struct drm_clip_rect norect;
+	int ret, increment = 1;
 
-	if (unlikely(vfbs->buffer == NULL))
-		return 0;
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
 
-	bo = &vfbs->buffer->base;
-	ttm_bo_unref(&bo);
-	vfbs->buffer = NULL;
+	if (!num_clips) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		increment = 2;
+	}
 
-	return 0;
+	if (dev_priv->ldu_priv) {
+		ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base,
+					  flags, color,
+					  clips, num_clips, increment);
+	} else {
+		ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base,
+					  flags, color,
+					  clips, num_clips, increment);
+	}
+
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
 }
 
+static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
+	.destroy = vmw_framebuffer_dmabuf_destroy,
+	.dirty = vmw_framebuffer_dmabuf_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+/**
+ * Pin the dmabuffer to the start of vram.
+ */
 static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 {
 	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -749,10 +965,12 @@ static int vmw_framebuffer_dmabuf_pin(st
 		vmw_framebuffer_to_vfbd(&vfb->base);
 	int ret;
 
+	/* This code should not be used with screen objects */
+	BUG_ON(dev_priv->sou_priv);
 
 	vmw_overlay_pause_all(dev_priv);
 
-	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
+	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer, true, false);
 
 	vmw_overlay_resume_all(dev_priv);
 
@@ -772,7 +990,7 @@ static int vmw_framebuffer_dmabuf_unpin(
 		return 0;
 	}
 
-	return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
+	return vmw_dmabuf_unpin(dev_priv, vfbd->buffer, false);
 }
 
 static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
@@ -794,6 +1012,33 @@ static int vmw_kms_new_framebuffer_dmabu
 		return -EINVAL;
 	}
 
+	/* Limited framebuffer color depth support for screen objects */
+	if (dev_priv->sou_priv) {
+		switch (mode_cmd->depth) {
+		case 32:
+		case 24:
+			/* Only support 32 bpp for 32 and 24 depth fbs */
+			if (mode_cmd->bpp == 32)
+				break;
+
+			DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+				  mode_cmd->depth, mode_cmd->bpp);
+			return -EINVAL;
+		case 16:
+		case 15:
+			/* Only support 16 bpp for 16 and 15 depth fbs */
+			if (mode_cmd->bpp == 16)
+				break;
+
+			DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+				  mode_cmd->depth, mode_cmd->bpp);
+			return -EINVAL;
+		default:
+			DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+			return -EINVAL;
+		}
+	}
+
 	vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
 	if (!vfbd) {
 		ret = -ENOMEM;
@@ -815,9 +1060,13 @@ static int vmw_kms_new_framebuffer_dmabu
 	vfbd->base.base.depth = mode_cmd->depth;
 	vfbd->base.base.width = mode_cmd->width;
 	vfbd->base.base.height = mode_cmd->height;
-	vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
-	vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	if (!dev_priv->sou_priv) {
+		vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
+		vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	}
+	vfbd->base.dmabuf = true;
 	vfbd->buffer = dmabuf;
+	vfbd->base.user_handle = mode_cmd->handle;
 	*out = &vfbd->base;
 
 	return 0;
@@ -843,7 +1092,7 @@ static struct drm_framebuffer *vmw_kms_f
 	struct vmw_framebuffer *vfb = NULL;
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
-	u64 required_size;
+	struct ttm_base_object *user_obj;
 	int ret;
 
 	/**
@@ -852,69 +1101,308 @@ static struct drm_framebuffer *vmw_kms_f
 	 * requested framebuffer.
 	 */
 
-	required_size = mode_cmd->pitch * mode_cmd->height;
-	if (unlikely(required_size > (u64) dev_priv->vram_size)) {
+	if (!vmw_kms_validate_mode_vram(dev_priv,
+					mode_cmd->pitch,
+					mode_cmd->height)) {
 		DRM_ERROR("VRAM size is too small for requested mode.\n");
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 
-	/**
-	 * End conditioned code.
+	/*
+	 * Take a reference on the user object of the resource
+	 * backing the kms fb. This ensures that user-space handle
+	 * lookups on that resource will always work as long as
+	 * it's registered with a kms framebuffer. This is important,
+	 * since vmw_execbuf_process identifies resources in the
+	 * command stream using user-space handles.
 	 */
 
-	ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
-					     mode_cmd->handle, &surface);
-	if (ret)
-		goto try_dmabuf;
+	user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
+	if (unlikely(user_obj == NULL)) {
+		DRM_ERROR("Could not locate requested kms frame buffer.\n");
+		return ERR_PTR(-ENOENT);
+	}
 
-	if (!surface->scanout)
-		goto err_not_scanout;
+	/* returns either a dmabuf or surface */
+	ret = vmw_user_lookup_handle(dev_priv, tfile,
+				     mode_cmd->handle,
+				     &surface, &bo);
+	if (ret)
+		goto err_out;
 
-	ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
-					      &vfb, mode_cmd);
+	/* Create the new framebuffer depending one what we got back */
+	if (bo)
+		ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
+						     mode_cmd);
+	else if (surface)
+		ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv,
+						      surface, &vfb, mode_cmd);
+	else
+		BUG();
 
-	/* vmw_user_surface_lookup takes one ref so does new_fb */
-	vmw_surface_unreference(&surface);
+err_out:
+	/* vmw_user_lookup_handle takes one ref so does new_fb */
+	if (bo)
+		vmw_dmabuf_unreference(&bo);
+	if (surface)
+		vmw_surface_unreference(&surface);
 
 	if (ret) {
 		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		ttm_base_object_unref(&user_obj);
 		return ERR_PTR(ret);
-	}
+	} else
+		vfb->user_obj = user_obj;
+
 	return &vfb->base;
+}
 
-try_dmabuf:
-	DRM_INFO("%s: trying buffer\n", __func__);
+static struct drm_mode_config_funcs vmw_kms_funcs = {
+	.fb_create = vmw_kms_fb_create,
+};
 
-	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
-	if (ret) {
-		DRM_ERROR("failed to find buffer: %i\n", ret);
-		return ERR_PTR(-ENOENT);
+int vmw_kms_present(struct vmw_private *dev_priv,
+		    struct drm_file *file_priv,
+		    struct vmw_framebuffer *vfb,
+		    struct vmw_surface *surface,
+		    uint32_t sid,
+		    int32_t destX, int32_t destY,
+		    struct drm_vmw_rect *clips,
+		    uint32_t num_clips)
+{
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *tmp;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, k, num_units;
+	int ret = 0; /* silence warning */
+	int left, right, top, bottom;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdBlitSurfaceToScreen body;
+	} *cmd;
+	SVGASignedRect *blits;
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &vfb->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
 
-	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
-					     mode_cmd);
+	BUG_ON(surface == NULL);
+	BUG_ON(!clips || !num_clips);
 
-	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
-	vmw_dmabuf_unreference(&bo);
+	tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL);
+	if (unlikely(tmp == NULL)) {
+		DRM_ERROR("Temporary cliprect memory alloc failed.\n");
+		return -ENOMEM;
+	}
 
-	if (ret) {
-		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
-		return ERR_PTR(ret);
+	fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+		ret = -ENOMEM;
+		goto out_free_tmp;
 	}
 
-	return &vfb->base;
+	left = clips->x;
+	right = clips->x + clips->w;
+	top = clips->y;
+	bottom = clips->y + clips->h;
 
-err_not_scanout:
-	DRM_ERROR("surface not marked as scanout\n");
-	/* vmw_user_surface_lookup takes one ref */
-	vmw_surface_unreference(&surface);
+	for (i = 1; i < num_clips; i++) {
+		left = min_t(int, left, (int)clips[i].x);
+		right = max_t(int, right, (int)clips[i].x + clips[i].w);
+		top = min_t(int, top, (int)clips[i].y);
+		bottom = max_t(int, bottom, (int)clips[i].y + clips[i].h);
+	}
 
-	return ERR_PTR(-EINVAL);
+	/* only need to do this once */
+	memset(cmd, 0, fifo_size);
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+
+	blits = (SVGASignedRect *)&cmd[1];
+
+	cmd->body.srcRect.left = left;
+	cmd->body.srcRect.right = right;
+	cmd->body.srcRect.top = top;
+	cmd->body.srcRect.bottom = bottom;
+
+	for (i = 0; i < num_clips; i++) {
+		tmp[i].x1 = clips[i].x - left;
+		tmp[i].x2 = clips[i].x + clips[i].w - left;
+		tmp[i].y1 = clips[i].y - top;
+		tmp[i].y2 = clips[i].y + clips[i].h - top;
+	}
+
+	for (k = 0; k < num_units; k++) {
+		struct vmw_display_unit *unit = units[k];
+		struct vmw_clip_rect clip;
+		int num;
+
+		clip.x1 = left + destX - unit->crtc.x;
+		clip.y1 = top + destY - unit->crtc.y;
+		clip.x2 = right + destX - unit->crtc.x;
+		clip.y2 = bottom + destY - unit->crtc.y;
+
+		/* skip any crtcs that misses the clip region */
+		if (clip.x1 >= unit->crtc.mode.hdisplay ||
+		    clip.y1 >= unit->crtc.mode.vdisplay ||
+		    clip.x2 <= 0 || clip.y2 <= 0)
+			continue;
+
+		/*
+		 * In order for the clip rects to be correctly scaled
+		 * the src and dest rects needs to be the same size.
+		 */
+		cmd->body.destRect.left = clip.x1;
+		cmd->body.destRect.right = clip.x2;
+		cmd->body.destRect.top = clip.y1;
+		cmd->body.destRect.bottom = clip.y2;
+
+		/* create a clip rect of the crtc in dest coords */
+		clip.x2 = unit->crtc.mode.hdisplay - clip.x1;
+		clip.y2 = unit->crtc.mode.vdisplay - clip.y1;
+		clip.x1 = 0 - clip.x1;
+		clip.y1 = 0 - clip.y1;
+
+		/* need to reset sid as it is changed by execbuf */
+		cmd->body.srcImage.sid = sid;
+		cmd->body.destScreenId = unit->unit;
+
+		/* clip and write blits to cmd stream */
+		vmw_clip_cliprects(tmp, num_clips, clip, blits, &num);
+
+		/* if no cliprects hit skip this */
+		if (num == 0)
+			continue;
+
+		/* recalculate package length */
+		fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num;
+		cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+					  fifo_size, 0, NULL);
+
+		if (unlikely(ret != 0))
+			break;
+	}
+
+	kfree(cmd);
+out_free_tmp:
+	kfree(tmp);
+
+	return ret;
 }
 
-static struct drm_mode_config_funcs vmw_kms_funcs = {
-	.fb_create = vmw_kms_fb_create,
-};
+int vmw_kms_readback(struct vmw_private *dev_priv,
+		     struct drm_file *file_priv,
+		     struct vmw_framebuffer *vfb,
+		     struct drm_vmw_fence_rep __user *user_fence_rep,
+		     struct drm_vmw_rect *clips,
+		     uint32_t num_clips)
+{
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+	struct vmw_dma_buffer *dmabuf = vfbd->buffer;
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, k, ret, num_units, blits_pos;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdBlitScreenToGMRFB body;
+	} *blits;
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &vfb->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
+
+	BUG_ON(dmabuf == NULL);
+	BUG_ON(!clips || !num_clips);
+
+	/* take a safe guess at fifo size */
+	fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips * num_units;
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header = SVGA_CMD_DEFINE_GMRFB;
+	cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel;
+	cmd->body.format.colorDepth = vfb->base.depth;
+	cmd->body.format.reserved = 0;
+	cmd->body.bytesPerLine = vfb->base.pitch;
+	cmd->body.ptr.gmrId = vfb->user_handle;
+	cmd->body.ptr.offset = 0;
+
+	blits = (void *)&cmd[1];
+	blits_pos = 0;
+	for (i = 0; i < num_units; i++) {
+		struct drm_vmw_rect *c = clips;
+		for (k = 0; k < num_clips; k++, c++) {
+			/* transform clip coords to crtc origin based coords */
+			int clip_x1 = c->x - units[i]->crtc.x;
+			int clip_x2 = c->x - units[i]->crtc.x + c->w;
+			int clip_y1 = c->y - units[i]->crtc.y;
+			int clip_y2 = c->y - units[i]->crtc.y + c->h;
+			int dest_x = c->x;
+			int dest_y = c->y;
+
+			/* compensate for clipping, we negate
+			 * a negative number and add that.
+			 */
+			if (clip_x1 < 0)
+				dest_x += -clip_x1;
+			if (clip_y1 < 0)
+				dest_y += -clip_y1;
+
+			/* clip */
+			clip_x1 = max(clip_x1, 0);
+			clip_y1 = max(clip_y1, 0);
+			clip_x2 = min(clip_x2, units[i]->crtc.mode.hdisplay);
+			clip_y2 = min(clip_y2, units[i]->crtc.mode.vdisplay);
+
+			/* and cull any rects that misses the crtc */
+			if (clip_x1 >= units[i]->crtc.mode.hdisplay ||
+			    clip_y1 >= units[i]->crtc.mode.vdisplay ||
+			    clip_x2 <= 0 || clip_y2 <= 0)
+				continue;
+
+			blits[blits_pos].header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB;
+			blits[blits_pos].body.srcScreenId = units[i]->unit;
+			blits[blits_pos].body.destOrigin.x = dest_x;
+			blits[blits_pos].body.destOrigin.y = dest_y;
+
+			blits[blits_pos].body.srcRect.left = clip_x1;
+			blits[blits_pos].body.srcRect.top = clip_y1;
+			blits[blits_pos].body.srcRect.right = clip_x2;
+			blits[blits_pos].body.srcRect.bottom = clip_y2;
+			blits_pos++;
+		}
+	}
+	/* reset size here and use calculated exact size from loops */
+	fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size,
+				  0, user_fence_rep);
+
+	kfree(cmd);
+
+	return ret;
+}
 
 int vmw_kms_init(struct vmw_private *dev_priv)
 {
@@ -929,7 +1417,9 @@ int vmw_kms_init(struct vmw_private *dev
 	dev->mode_config.max_width = 8192;
 	dev->mode_config.max_height = 8192;
 
-	ret = vmw_kms_init_legacy_display_system(dev_priv);
+	ret = vmw_kms_init_screen_object_display(dev_priv);
+	if (ret) /* Fallback */
+		(void)vmw_kms_init_legacy_display_system(dev_priv);
 
 	return 0;
 }
@@ -942,7 +1432,10 @@ int vmw_kms_close(struct vmw_private *de
 	 * drm_encoder_cleanup which takes the lock we deadlock.
 	 */
 	drm_mode_config_cleanup(dev_priv->dev);
-	vmw_kms_close_legacy_display_system(dev_priv);
+	if (dev_priv->sou_priv)
+		vmw_kms_close_screen_object_display(dev_priv);
+	else
+		vmw_kms_close_legacy_display_system(dev_priv);
 	return 0;
 }
 
@@ -987,9 +1480,9 @@ out:
 	return ret;
 }
 
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
 			unsigned width, unsigned height, unsigned pitch,
-			unsigned bbp, unsigned depth)
+			unsigned bpp, unsigned depth)
 {
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
@@ -997,11 +1490,15 @@ void vmw_kms_write_svga(struct vmw_priva
 		iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
 	vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
 	vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
-	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
-	vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
-	vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bpp);
+
+	if (vmw_read(vmw_priv, SVGA_REG_DEPTH) != depth) {
+		DRM_ERROR("Invalid depth %u for %u bpp, host expects %u\n",
+			  depth, bpp, vmw_read(vmw_priv, SVGA_REG_DEPTH));
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 int vmw_kms_save_vga(struct vmw_private *vmw_priv)
@@ -1011,12 +1508,7 @@ int vmw_kms_save_vga(struct vmw_private
 
 	vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
 	vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
-	vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
 	vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
-	vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
-	vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
-	vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
-	vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_priv->vga_pitchlock =
 		  vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
@@ -1065,12 +1557,7 @@ int vmw_kms_restore_vga(struct vmw_priva
 
 	vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
 	vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
-	vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
 	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
-	vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
-	vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
-	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
-	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
 			  vmw_priv->vga_pitchlock);
@@ -1095,6 +1582,312 @@ int vmw_kms_restore_vga(struct vmw_priva
 	return 0;
 }
 
+bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
+				uint32_t pitch,
+				uint32_t height)
+{
+	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+}
+
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+int vmw_enable_vblank(struct drm_device *dev, int crtc)
+{
+	return -ENOSYS;
+}
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+void vmw_disable_vblank(struct drm_device *dev, int crtc)
+{
+}
+
+
+/*
+ * Small shared kms functions.
+ */
+
+int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+			 struct drm_vmw_rect *rects)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_display_unit *du;
+	struct drm_connector *con;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+	{
+		unsigned int i;
+
+		DRM_INFO("%s: new layout ", __func__);
+		for (i = 0; i < num; i++)
+			DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+				 rects[i].w, rects[i].h);
+		DRM_INFO("\n");
+	}
+#endif
+
+	list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+		du = vmw_connector_to_du(con);
+		if (num > du->unit) {
+			du->pref_width = rects[du->unit].w;
+			du->pref_height = rects[du->unit].h;
+			du->pref_active = true;
+			du->gui_x = rects[du->unit].x;
+			du->gui_y = rects[du->unit].y;
+		} else {
+			du->pref_width = 800;
+			du->pref_height = 600;
+			du->pref_active = false;
+		}
+		con->status = vmw_du_connector_detect(con, true);
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+}
+
+void vmw_du_crtc_save(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_restore(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+			   u16 *r, u16 *g, u16 *b,
+			   uint32_t start, uint32_t size)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	int i;
+
+	for (i = 0; i < size; i++) {
+		DRM_DEBUG("%d r/g/b = 0x%04x / 0x%04x / 0x%04x\n", i,
+			  r[i], g[i], b[i]);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 0, r[i] >> 8);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 1, g[i] >> 8);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 2, b[i] >> 8);
+	}
+}
+
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode)
+{
+}
+
+void vmw_du_connector_save(struct drm_connector *connector)
+{
+}
+
+void vmw_du_connector_restore(struct drm_connector *connector)
+{
+}
+
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force)
+{
+	uint32_t num_displays;
+	struct drm_device *dev = connector->dev;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_display_unit *du = vmw_connector_to_du(connector);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ((vmw_connector_to_du(connector)->unit < num_displays &&
+		 du->pref_active) ?
+		connector_status_connected : connector_status_disconnected);
+}
+
+static struct drm_display_mode vmw_kms_connector_builtin[] = {
+	/* 640x480@60Hz */
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
+		   752, 800, 0, 480, 489, 492, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 800x600@60Hz */
+	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+		   968, 1056, 0, 600, 601, 605, 628, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1024x768@60Hz */
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+		   1184, 1344, 0, 768, 771, 777, 806, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1152x864@75Hz */
+	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+		   1344, 1600, 0, 864, 865, 868, 900, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x768@60Hz */
+	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+		   1472, 1664, 0, 768, 771, 778, 798, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x800@60Hz */
+	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+		   1480, 1680, 0, 800, 803, 809, 831, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x960@60Hz */
+	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
+		   1488, 1800, 0, 960, 961, 964, 1000, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x1024@60Hz */
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
+		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1360x768@60Hz */
+	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
+		   1536, 1792, 0, 768, 771, 777, 795, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x1050@60Hz */
+	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x900@60Hz */
+	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
+		   1672, 1904, 0, 900, 903, 909, 934, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1600x1200@60Hz */
+	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
+		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1680x1050@60Hz */
+	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1792x1344@60Hz */
+	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
+		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1853x1392@60Hz */
+	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
+		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1200@60Hz */
+	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1440@60Hz */
+	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
+		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 2560x1600@60Hz */
+	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
+		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* Terminate */
+	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
+};
+
+/**
+ * vmw_guess_mode_timing - Provide fake timings for a
+ * 60Hz vrefresh mode.
+ *
+ * @mode - Pointer to a struct drm_display_mode with hdisplay and vdisplay
+ * members filled in.
+ */
+static void vmw_guess_mode_timing(struct drm_display_mode *mode)
+{
+	mode->hsync_start = mode->hdisplay + 50;
+	mode->hsync_end = mode->hsync_start + 50;
+	mode->htotal = mode->hsync_end + 50;
+
+	mode->vsync_start = mode->vdisplay + 50;
+	mode->vsync_end = mode->vsync_start + 50;
+	mode->vtotal = mode->vsync_end + 50;
+
+	mode->clock = (u32)mode->htotal * (u32)mode->vtotal / 100 * 6;
+	mode->vrefresh = drm_mode_vrefresh(mode);
+}
+
+
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+				uint32_t max_width, uint32_t max_height)
+{
+	struct vmw_display_unit *du = vmw_connector_to_du(connector);
+	struct drm_device *dev = connector->dev;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *bmode;
+	struct drm_display_mode prefmode = { DRM_MODE("preferred",
+		DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+	};
+	int i;
+
+	/* Add preferred mode */
+	{
+		mode = drm_mode_duplicate(dev, &prefmode);
+		if (!mode)
+			return 0;
+		mode->hdisplay = du->pref_width;
+		mode->vdisplay = du->pref_height;
+		vmw_guess_mode_timing(mode);
+
+		if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
+					       mode->vdisplay)) {
+			drm_mode_probed_add(connector, mode);
+		} else {
+			drm_mode_destroy(dev, mode);
+			mode = NULL;
+		}
+
+		if (du->pref_mode) {
+			list_del_init(&du->pref_mode->head);
+			drm_mode_destroy(dev, du->pref_mode);
+		}
+
+		/* mode might be null here, this is intended */
+		du->pref_mode = mode;
+	}
+
+	for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
+		bmode = &vmw_kms_connector_builtin[i];
+		if (bmode->hdisplay > max_width ||
+		    bmode->vdisplay > max_height)
+			continue;
+
+		if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
+						bmode->vdisplay))
+			continue;
+
+		mode = drm_mode_duplicate(dev, bmode);
+		if (!mode)
+			return 0;
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
+		drm_mode_probed_add(connector, mode);
+	}
+
+	/* Move the prefered mode first, help apps pick the right mode. */
+	if (du->pref_mode)
+		list_move(&du->pref_mode->head, &connector->probed_modes);
+
+	drm_mode_connector_list_update(connector);
+
+	return 1;
+}
+
+int vmw_du_connector_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val)
+{
+	return 0;
+}
+
+
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
@@ -1106,6 +1899,8 @@ int vmw_kms_update_layout_ioctl(struct d
 	struct drm_vmw_rect *rects;
 	unsigned rects_size;
 	int ret;
+	int i;
+	struct drm_mode_config *mode_config = &dev->mode_config;
 
 	ret = ttm_read_lock(&vmaster->lock, true);
 	if (unlikely(ret != 0))
@@ -1113,12 +1908,13 @@ int vmw_kms_update_layout_ioctl(struct d
 
 	if (!arg->num_outputs) {
 		struct drm_vmw_rect def_rect = {0, 0, 800, 600};
-		vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+		vmw_du_update_layout(dev_priv, 1, &def_rect);
 		goto out_unlock;
 	}
 
 	rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
-	rects = kzalloc(rects_size, GFP_KERNEL);
+	rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect),
+			GFP_KERNEL);
 	if (unlikely(!rects)) {
 		ret = -ENOMEM;
 		goto out_unlock;
@@ -1132,7 +1928,18 @@ int vmw_kms_update_layout_ioctl(struct d
 		goto out_free;
 	}
 
-	vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+	for (i = 0; i < arg->num_outputs; ++i) {
+		if (rects[i].x < 0 ||
+		    rects[i].y < 0 ||
+		    rects[i].x + rects[i].w > mode_config->max_width ||
+		    rects[i].y + rects[i].h > mode_config->max_height) {
+			DRM_ERROR("Invalid GUI layout.\n");
+			ret = -EINVAL;
+			goto out_free;
+		}
+	}
+
+	vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
 
 out_free:
 	kfree(rects);
@@ -1140,15 +1947,3 @@ out_unlock:
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
-
-bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
-				uint32_t pitch,
-				uint32_t height)
-{
-	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
-}
-
-u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
-{
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
 #include "drmP.h"
 #include "vmwgfx_drv.h"
 
+#define VMWGFX_NUM_DISPLAY_UNITS 8
+
 
 #define vmw_framebuffer_to_vfb(x) \
 	container_of(x, struct vmw_framebuffer, base)
@@ -45,6 +47,9 @@ struct vmw_framebuffer {
 	struct drm_framebuffer base;
 	int (*pin)(struct vmw_framebuffer *fb);
 	int (*unpin)(struct vmw_framebuffer *fb);
+	bool dmabuf;
+	struct ttm_base_object *user_obj;
+	uint32_t user_handle;
 };
 
 
@@ -57,9 +62,14 @@ struct vmw_framebuffer {
 int vmw_cursor_update_image(struct vmw_private *dev_priv,
 			    u32 *image, u32 width, u32 height,
 			    u32 hotspotX, u32 hotspotY);
+int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
+			     struct vmw_dma_buffer *dmabuf,
+			     u32 width, u32 height,
+			     u32 hotspotX, u32 hotspotY);
 void vmw_cursor_update_position(struct vmw_private *dev_priv,
 				bool show, int x, int y);
 
+
 /**
  * Base class display unit.
  *
@@ -83,22 +93,65 @@ struct vmw_display_unit {
 	int hotspot_y;
 
 	unsigned unit;
+
+	/*
+	 * Prefered mode tracking.
+	 */
+	unsigned pref_width;
+	unsigned pref_height;
+	bool pref_active;
+	struct drm_display_mode *pref_mode;
+
+	/*
+	 * Gui positioning
+	 */
+	int gui_x;
+	int gui_y;
+	bool is_implicit;
 };
 
+#define vmw_crtc_to_du(x) \
+	container_of(x, struct vmw_display_unit, crtc)
+#define vmw_connector_to_du(x) \
+	container_of(x, struct vmw_display_unit, connector)
+
+
 /*
  * Shared display unit functions - vmwgfx_kms.c
  */
 void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+void vmw_du_crtc_save(struct drm_crtc *crtc);
+void vmw_du_crtc_restore(struct drm_crtc *crtc);
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+			   u16 *r, u16 *g, u16 *b,
+			   uint32_t start, uint32_t size);
 int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 			   uint32_t handle, uint32_t width, uint32_t height);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode);
+void vmw_du_connector_save(struct drm_connector *connector);
+void vmw_du_connector_restore(struct drm_connector *connector);
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force);
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+				uint32_t max_width, uint32_t max_height);
+int vmw_du_connector_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val);
+
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
  */
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+
+/*
+ * Screen Objects display functions - vmwgfx_scrn.c
+ */
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
 			      struct drm_vmw_rect *rects);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 
 #include "vmwgfx_kms.h"
 
-#define VMWGFX_LDU_NUM_DU 8
 
 #define vmw_crtc_to_ldu(x) \
 	container_of(x, struct vmw_legacy_display_unit, base.crtc)
@@ -51,11 +50,6 @@ struct vmw_legacy_display {
 struct vmw_legacy_display_unit {
 	struct vmw_display_unit base;
 
-	unsigned pref_width;
-	unsigned pref_height;
-	bool pref_active;
-	struct drm_display_mode *pref_mode;
-
 	struct list_head active;
 };
 
@@ -71,20 +65,6 @@ static void vmw_ldu_destroy(struct vmw_l
  * Legacy Display Unit CRTC functions
  */
 
-static void vmw_ldu_crtc_save(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_restore(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc,
-				   u16 *r, u16 *g, u16 *b,
-				   uint32_t start, uint32_t size)
-{
-}
-
 static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc)
 {
 	vmw_ldu_destroy(vmw_crtc_to_ldu(crtc));
@@ -94,9 +74,10 @@ static int vmw_ldu_commit_list(struct vm
 {
 	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
 	struct vmw_legacy_display_unit *entry;
+	struct vmw_display_unit *du = NULL;
 	struct drm_framebuffer *fb = NULL;
 	struct drm_crtc *crtc = NULL;
-	int i = 0;
+	int i = 0, ret;
 
 	/* If there is no display topology the host just assumes
 	 * that the guest will set the same layout as the host.
@@ -114,10 +95,8 @@ static int vmw_ldu_commit_list(struct vm
 			return 0;
 		fb = entry->base.crtc.fb;
 
-		vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
-				   fb->bits_per_pixel, fb->depth);
-
-		return 0;
+		return vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+					  fb->bits_per_pixel, fb->depth);
 	}
 
 	if (!list_empty(&lds->active)) {
@@ -151,6 +130,25 @@ static int vmw_ldu_commit_list(struct vm
 
 	lds->last_num_active = lds->num_active;
 
+
+	/* Find the first du with a cursor. */
+	list_for_each_entry(entry, &lds->active, active) {
+		du = &entry->base;
+
+		if (!du->cursor_dmabuf)
+			continue;
+
+		ret = vmw_cursor_update_dmabuf(dev_priv,
+					       du->cursor_dmabuf,
+					       64, 64,
+					       du->hotspot_x,
+					       du->hotspot_y);
+		if (ret == 0)
+			break;
+
+		DRM_ERROR("Could not update cursor image\n");
+	}
+
 	return 0;
 }
 
@@ -265,9 +263,7 @@ static int vmw_ldu_crtc_set_config(struc
 
 		vmw_ldu_del_active(dev_priv, ldu);
 
-		vmw_ldu_commit_list(dev_priv);
-
-		return 0;
+		return vmw_ldu_commit_list(dev_priv);
 	}
 
 
@@ -292,21 +288,20 @@ static int vmw_ldu_crtc_set_config(struc
 
 	vmw_ldu_add_active(dev_priv, ldu, vfb);
 
-	vmw_ldu_commit_list(dev_priv);
-
-	return 0;
+	return vmw_ldu_commit_list(dev_priv);
 }
 
 static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
-	.save = vmw_ldu_crtc_save,
-	.restore = vmw_ldu_crtc_restore,
+	.save = vmw_du_crtc_save,
+	.restore = vmw_du_crtc_restore,
 	.cursor_set = vmw_du_crtc_cursor_set,
 	.cursor_move = vmw_du_crtc_cursor_move,
-	.gamma_set = vmw_ldu_crtc_gamma_set,
+	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
 	.set_config = vmw_ldu_crtc_set_config,
 };
 
+
 /*
  * Legacy Display Unit encoder functions
  */
@@ -324,183 +319,18 @@ static struct drm_encoder_funcs vmw_lega
  * Legacy Display Unit connector functions
  */
 
-static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode)
-{
-}
-
-static void vmw_ldu_connector_save(struct drm_connector *connector)
-{
-}
-
-static void vmw_ldu_connector_restore(struct drm_connector *connector)
-{
-}
-
-static enum drm_connector_status
-	vmw_ldu_connector_detect(struct drm_connector *connector,
-				 bool force)
-{
-	if (vmw_connector_to_ldu(connector)->pref_active)
-		return connector_status_connected;
-	return connector_status_disconnected;
-}
-
-static const struct drm_display_mode vmw_ldu_connector_builtin[] = {
-	/* 640x480@60Hz */
-	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
-		   752, 800, 0, 480, 489, 492, 525, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 800x600@60Hz */
-	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
-		   968, 1056, 0, 600, 601, 605, 628, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1024x768@60Hz */
-	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
-		   1184, 1344, 0, 768, 771, 777, 806, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 1152x864@75Hz */
-	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
-		   1344, 1600, 0, 864, 865, 868, 900, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x768@60Hz */
-	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
-		   1472, 1664, 0, 768, 771, 778, 798, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x800@60Hz */
-	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
-		   1480, 1680, 0, 800, 803, 809, 831, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 1280x960@60Hz */
-	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
-		   1488, 1800, 0, 960, 961, 964, 1000, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x1024@60Hz */
-	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
-		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1360x768@60Hz */
-	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
-		   1536, 1792, 0, 768, 771, 777, 795, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1440x1050@60Hz */
-	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
-		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1440x900@60Hz */
-	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
-		   1672, 1904, 0, 900, 903, 909, 934, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1600x1200@60Hz */
-	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
-		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1680x1050@60Hz */
-	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
-		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1792x1344@60Hz */
-	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
-		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1853x1392@60Hz */
-	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
-		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1920x1200@60Hz */
-	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
-		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1920x1440@60Hz */
-	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
-		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 2560x1600@60Hz */
-	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
-		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* Terminate */
-	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
-};
-
-static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
-					uint32_t max_width, uint32_t max_height)
-{
-	struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
-	struct drm_device *dev = connector->dev;
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct drm_display_mode *mode = NULL;
-	struct drm_display_mode prefmode = { DRM_MODE("preferred",
-		DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
-	};
-	int i;
-
-	/* Add preferred mode */
-	{
-		mode = drm_mode_duplicate(dev, &prefmode);
-		if (!mode)
-			return 0;
-		mode->hdisplay = ldu->pref_width;
-		mode->vdisplay = ldu->pref_height;
-		mode->vrefresh = drm_mode_vrefresh(mode);
-		if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
-					       mode->vdisplay)) {
-			drm_mode_probed_add(connector, mode);
-
-			if (ldu->pref_mode) {
-				list_del_init(&ldu->pref_mode->head);
-				drm_mode_destroy(dev, ldu->pref_mode);
-			}
-
-			ldu->pref_mode = mode;
-		}
-	}
-
-	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
-		const struct drm_display_mode *bmode;
-
-		bmode = &vmw_ldu_connector_builtin[i];
-		if (bmode->hdisplay > max_width ||
-		    bmode->vdisplay > max_height)
-			continue;
-
-		if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
-						bmode->vdisplay))
-			continue;
-
-		mode = drm_mode_duplicate(dev, bmode);
-		if (!mode)
-			return 0;
-		mode->vrefresh = drm_mode_vrefresh(mode);
-
-		drm_mode_probed_add(connector, mode);
-	}
-
-	drm_mode_connector_list_update(connector);
-
-	return 1;
-}
-
-static int vmw_ldu_connector_set_property(struct drm_connector *connector,
-					  struct drm_property *property,
-					  uint64_t val)
-{
-	return 0;
-}
-
 static void vmw_ldu_connector_destroy(struct drm_connector *connector)
 {
 	vmw_ldu_destroy(vmw_connector_to_ldu(connector));
 }
 
 static struct drm_connector_funcs vmw_legacy_connector_funcs = {
-	.dpms = vmw_ldu_connector_dpms,
-	.save = vmw_ldu_connector_save,
-	.restore = vmw_ldu_connector_restore,
-	.detect = vmw_ldu_connector_detect,
-	.fill_modes = vmw_ldu_connector_fill_modes,
-	.set_property = vmw_ldu_connector_set_property,
+	.dpms = vmw_du_connector_dpms,
+	.save = vmw_du_connector_save,
+	.restore = vmw_du_connector_restore,
+	.detect = vmw_du_connector_detect,
+	.fill_modes = vmw_du_connector_fill_modes,
+	.set_property = vmw_du_connector_set_property,
 	.destroy = vmw_ldu_connector_destroy,
 };
 
@@ -523,23 +353,26 @@ static int vmw_ldu_init(struct vmw_priva
 
 	INIT_LIST_HEAD(&ldu->active);
 
-	ldu->pref_active = (unit == 0);
-	ldu->pref_width = 800;
-	ldu->pref_height = 600;
-	ldu->pref_mode = NULL;
+	ldu->base.pref_active = (unit == 0);
+	ldu->base.pref_width = 800;
+	ldu->base.pref_height = 600;
+	ldu->base.pref_mode = NULL;
+	ldu->base.is_implicit = true;
 
 	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
-			   DRM_MODE_CONNECTOR_LVDS);
-	connector->status = vmw_ldu_connector_detect(connector, true);
+			   DRM_MODE_CONNECTOR_VIRTUAL);
+	connector->status = vmw_du_connector_detect(connector, true);
 
 	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
-			 DRM_MODE_ENCODER_LVDS);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
 	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
 	drm_connector_attach_property(connector,
 				      dev->mode_config.dirty_info_property,
 				      1);
@@ -550,8 +383,7 @@ static int vmw_ldu_init(struct vmw_priva
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	int i;
-	int ret;
+	int i, ret;
 
 	if (dev_priv->ldu_priv) {
 		DRM_INFO("ldu system already on\n");
@@ -559,7 +391,6 @@ int vmw_kms_init_legacy_display_system(s
 	}
 
 	dev_priv->ldu_priv = kmalloc(sizeof(*dev_priv->ldu_priv), GFP_KERNEL);
-
 	if (!dev_priv->ldu_priv)
 		return -ENOMEM;
 
@@ -568,18 +399,31 @@ int vmw_kms_init_legacy_display_system(s
 	dev_priv->ldu_priv->last_num_active = 0;
 	dev_priv->ldu_priv->fb = NULL;
 
-	drm_mode_create_dirty_info_property(dev_priv->dev);
+	/* for old hardware without multimon only enable one display */
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+		ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+	else
+		ret = drm_vblank_init(dev, 1);
+	if (ret != 0)
+		goto err_free;
 
-	if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-		for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+	ret = drm_mode_create_dirty_info_property(dev);
+	if (ret != 0)
+		goto err_vblank_cleanup;
+
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+		for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
 			vmw_ldu_init(dev_priv, i);
-		ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
-	} else {
-		/* for old hardware without multimon only enable one display */
+	else
 		vmw_ldu_init(dev_priv, 0);
-		ret = drm_vblank_init(dev, 1);
-	}
 
+	return 0;
+
+err_vblank_cleanup:
+	drm_vblank_cleanup(dev);
+err_free:
+	kfree(dev_priv->ldu_priv);
+	dev_priv->ldu_priv = NULL;
 	return ret;
 }
 
@@ -587,52 +431,14 @@ int vmw_kms_close_legacy_display_system(
 {
 	struct drm_device *dev = dev_priv->dev;
 
-	drm_vblank_cleanup(dev);
 	if (!dev_priv->ldu_priv)
 		return -ENOSYS;
 
+	drm_vblank_cleanup(dev);
+
 	BUG_ON(!list_empty(&dev_priv->ldu_priv->active));
 
 	kfree(dev_priv->ldu_priv);
 
 	return 0;
 }
-
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
-			      struct drm_vmw_rect *rects)
-{
-	struct drm_device *dev = dev_priv->dev;
-	struct vmw_legacy_display_unit *ldu;
-	struct drm_connector *con;
-	int i;
-
-	mutex_lock(&dev->mode_config.mutex);
-
-#if 0
-	DRM_INFO("%s: new layout ", __func__);
-	for (i = 0; i < (int)num; i++)
-		DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
-			 rects[i].w, rects[i].h);
-	DRM_INFO("\n");
-#else
-	(void)i;
-#endif
-
-	list_for_each_entry(con, &dev->mode_config.connector_list, head) {
-		ldu = vmw_connector_to_ldu(con);
-		if (num > ldu->base.unit) {
-			ldu->pref_width = rects[ldu->base.unit].w;
-			ldu->pref_height = rects[ldu->base.unit].h;
-			ldu->pref_active = true;
-		} else {
-			ldu->pref_width = 800;
-			ldu->pref_height = 600;
-			ldu->pref_active = false;
-		}
-		con->status = vmw_ldu_connector_detect(con, true);
-	}
-
-	mutex_unlock(&dev->mode_config.mutex);
-
-	return 0;
-}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_marker {
+	struct list_head head;
+	uint32_t seqno;
+	struct timespec submitted;
+};
+
+void vmw_marker_queue_init(struct vmw_marker_queue *queue)
+{
+	INIT_LIST_HEAD(&queue->head);
+	queue->lag = ns_to_timespec(0);
+	getrawmonotonic(&queue->lag_time);
+	spin_lock_init(&queue->lock);
+}
+
+void vmw_marker_queue_takedown(struct vmw_marker_queue *queue)
+{
+	struct vmw_marker *marker, *next;
+
+	spin_lock(&queue->lock);
+	list_for_each_entry_safe(marker, next, &queue->head, head) {
+		kfree(marker);
+	}
+	spin_unlock(&queue->lock);
+}
+
+int vmw_marker_push(struct vmw_marker_queue *queue,
+		   uint32_t seqno)
+{
+	struct vmw_marker *marker = kmalloc(sizeof(*marker), GFP_KERNEL);
+
+	if (unlikely(!marker))
+		return -ENOMEM;
+
+	marker->seqno = seqno;
+	getrawmonotonic(&marker->submitted);
+	spin_lock(&queue->lock);
+	list_add_tail(&marker->head, &queue->head);
+	spin_unlock(&queue->lock);
+
+	return 0;
+}
+
+int vmw_marker_pull(struct vmw_marker_queue *queue,
+		   uint32_t signaled_seqno)
+{
+	struct vmw_marker *marker, *next;
+	struct timespec now;
+	bool updated = false;
+
+	spin_lock(&queue->lock);
+	getrawmonotonic(&now);
+
+	if (list_empty(&queue->head)) {
+		queue->lag = ns_to_timespec(0);
+		queue->lag_time = now;
+		updated = true;
+		goto out_unlock;
+	}
+
+	list_for_each_entry_safe(marker, next, &queue->head, head) {
+		if (signaled_seqno - marker->seqno > (1 << 30))
+			continue;
+
+		queue->lag = timespec_sub(now, marker->submitted);
+		queue->lag_time = now;
+		updated = true;
+		list_del(&marker->head);
+		kfree(marker);
+	}
+
+out_unlock:
+	spin_unlock(&queue->lock);
+
+	return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+					struct timespec t2)
+{
+	t1.tv_sec += t2.tv_sec;
+	t1.tv_nsec += t2.tv_nsec;
+	if (t1.tv_nsec >= 1000000000L) {
+		t1.tv_sec += 1;
+		t1.tv_nsec -= 1000000000L;
+	}
+
+	return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
+{
+	struct timespec now;
+
+	spin_lock(&queue->lock);
+	getrawmonotonic(&now);
+	queue->lag = vmw_timespec_add(queue->lag,
+				      timespec_sub(now, queue->lag_time));
+	queue->lag_time = now;
+	spin_unlock(&queue->lock);
+	return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_marker_queue *queue,
+		       uint32_t us)
+{
+	struct timespec lag, cond;
+
+	cond = ns_to_timespec((s64) us * 1000);
+	lag = vmw_fifo_lag(queue);
+	return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+		 struct vmw_marker_queue *queue, uint32_t us)
+{
+	struct vmw_marker *marker;
+	uint32_t seqno;
+	int ret;
+
+	while (!vmw_lag_lt(queue, us)) {
+		spin_lock(&queue->lock);
+		if (list_empty(&queue->head))
+			seqno = atomic_read(&dev_priv->marker_seq);
+		else {
+			marker = list_first_entry(&queue->head,
+						 struct vmw_marker, head);
+			seqno = marker->seqno;
+		}
+		spin_unlock(&queue->lock);
+
+		ret = vmw_wait_seqno(dev_priv, false, seqno, true,
+					3*HZ);
+
+		if (unlikely(ret != 0))
+			return ret;
+
+		(void) vmw_marker_pull(queue, seqno);
+	}
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,48 +87,6 @@ static inline void fill_flush(struct vmw
 }
 
 /**
- * Pin or unpin a buffer in vram.
- *
- * @dev_priv:  Driver private.
- * @buf:  DMA buffer to pin or unpin.
- * @pin:  Pin buffer in vram if true.
- * @interruptible:  Use interruptible wait.
- *
- * Takes the current masters ttm lock in read.
- *
- * Returns
- * -ERESTARTSYS if interrupted by a signal.
- */
-static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
-				  struct vmw_dma_buffer *buf,
-				  bool pin, bool interruptible)
-{
-	struct ttm_buffer_object *bo = &buf->base;
-	struct ttm_placement *overlay_placement = &vmw_vram_placement;
-	int ret;
-
-	ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
-	if (unlikely(ret != 0))
-		goto err;
-
-	if (pin)
-		overlay_placement = &vmw_vram_ne_placement;
-
-	ret = ttm_bo_validate(bo, overlay_placement, interruptible, false, false);
-
-	ttm_bo_unreserve(bo);
-
-err:
-	ttm_read_unlock(&dev_priv->active_master->lock);
-
-	return ret;
-}
-
-/**
  * Send put command to hw.
  *
  * Returns
@@ -139,68 +97,80 @@ static int vmw_overlay_send_put(struct v
 				struct drm_vmw_control_stream_arg *arg,
 				bool interruptible)
 {
+	struct vmw_escape_video_flush *flush;
+	size_t fifo_size;
+	bool have_so = dev_priv->sou_priv ? true : false;
+	int i, num_items;
+	SVGAGuestPtr ptr;
+
 	struct {
 		struct vmw_escape_header escape;
 		struct {
-			struct {
-				uint32_t cmdType;
-				uint32_t streamId;
-			} header;
-			struct {
-				uint32_t registerId;
-				uint32_t value;
-			} items[SVGA_VIDEO_PITCH_3 + 1];
-		} body;
-		struct vmw_escape_video_flush flush;
+			uint32_t cmdType;
+			uint32_t streamId;
+		} header;
 	} *cmds;
-	uint32_t offset;
-	int i, ret;
+	struct {
+		uint32_t registerId;
+		uint32_t value;
+	} *items;
 
-	for (;;) {
-		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
-		if (cmds)
-			break;
+	/* defines are a index needs + 1 */
+	if (have_so)
+		num_items = SVGA_VIDEO_DST_SCREEN_ID + 1;
+	else
+		num_items = SVGA_VIDEO_PITCH_3 + 1;
 
-		ret = vmw_fallback_wait(dev_priv, false, true, 0,
-					interruptible, 3*HZ);
-		if (interruptible && ret == -ERESTARTSYS)
-			return ret;
-		else
-			BUG_ON(ret != 0);
-	}
+	fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items;
 
-	fill_escape(&cmds->escape, sizeof(cmds->body));
-	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
-	cmds->body.header.streamId = arg->stream_id;
+	cmds = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* hardware has hung, can't do anything here */
+	if (!cmds)
+		return -ENOMEM;
 
-	for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
-		cmds->body.items[i].registerId = i;
+	items = (typeof(items))&cmds[1];
+	flush = (struct vmw_escape_video_flush *)&items[num_items];
 
-	offset = buf->base.offset + arg->offset;
+	/* the size is header + number of items */
+	fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1));
 
-	cmds->body.items[SVGA_VIDEO_ENABLED].value     = true;
-	cmds->body.items[SVGA_VIDEO_FLAGS].value       = arg->flags;
-	cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
-	cmds->body.items[SVGA_VIDEO_FORMAT].value      = arg->format;
-	cmds->body.items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
-	cmds->body.items[SVGA_VIDEO_SIZE].value        = arg->size;
-	cmds->body.items[SVGA_VIDEO_WIDTH].value       = arg->width;
-	cmds->body.items[SVGA_VIDEO_HEIGHT].value      = arg->height;
-	cmds->body.items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
-	cmds->body.items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
-	cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
-	cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
-	cmds->body.items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
-	cmds->body.items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
-	cmds->body.items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
-	cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
-	cmds->body.items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
-	cmds->body.items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
-	cmds->body.items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+	cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->header.streamId = arg->stream_id;
 
-	fill_flush(&cmds->flush, arg->stream_id);
+	/* the IDs are neatly numbered */
+	for (i = 0; i < num_items; i++)
+		items[i].registerId = i;
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+	vmw_bo_get_guest_ptr(&buf->base, &ptr);
+	ptr.offset += arg->offset;
+
+	items[SVGA_VIDEO_ENABLED].value     = true;
+	items[SVGA_VIDEO_FLAGS].value       = arg->flags;
+	items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset;
+	items[SVGA_VIDEO_FORMAT].value      = arg->format;
+	items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
+	items[SVGA_VIDEO_SIZE].value        = arg->size;
+	items[SVGA_VIDEO_WIDTH].value       = arg->width;
+	items[SVGA_VIDEO_HEIGHT].value      = arg->height;
+	items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
+	items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
+	items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
+	items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
+	items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
+	items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
+	items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
+	items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
+	items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
+	items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
+	items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+	if (have_so) {
+		items[SVGA_VIDEO_DATA_GMRID].value    = ptr.gmrId;
+		items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID;
+	}
+
+	fill_flush(flush, arg->stream_id);
+
+	vmw_fifo_commit(dev_priv, fifo_size);
 
 	return 0;
 }
@@ -248,6 +218,25 @@ static int vmw_overlay_send_stop(struct
 }
 
 /**
+ * Move a buffer to vram or gmr if @pin is set, else unpin the buffer.
+ *
+ * With the introduction of screen objects buffers could now be
+ * used with GMRs instead of being locked to vram.
+ */
+static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,
+				   struct vmw_dma_buffer *buf,
+				   bool pin, bool inter)
+{
+	if (!pin)
+		return vmw_dmabuf_unpin(dev_priv, buf, inter);
+
+	if (!dev_priv->sou_priv)
+		return vmw_dmabuf_to_vram(dev_priv, buf, true, inter);
+
+	return vmw_dmabuf_to_vram_or_gmr(dev_priv, buf, true, inter);
+}
+
+/**
  * Stop or pause a stream.
  *
  * If the stream is paused the no evict flag is removed from the buffer
@@ -279,8 +268,8 @@ static int vmw_overlay_stop(struct vmw_p
 			return ret;
 
 		/* We just remove the NO_EVICT flag so no -ENOMEM */
-		ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
-					     interruptible);
+		ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false,
+					      interruptible);
 		if (interruptible && ret == -ERESTARTSYS)
 			return ret;
 		else
@@ -342,7 +331,7 @@ static int vmw_overlay_update_stream(str
 	/* We don't start the old stream if we are interrupted.
 	 * Might return -ENOMEM if it can't fit the buffer in vram.
 	 */
-	ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
+	ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible);
 	if (ret)
 		return ret;
 
@@ -351,7 +340,8 @@ static int vmw_overlay_update_stream(str
 		/* This one needs to happen no matter what. We only remove
 		 * the NO_EVICT flag so this is safe from -ENOMEM.
 		 */
-		BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
+		BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false)
+		       != 0);
 		return ret;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,10 +31,6 @@
 #include "ttm/ttm_placement.h"
 #include "drmP.h"
 
-#define VMW_RES_CONTEXT ttm_driver_type0
-#define VMW_RES_SURFACE ttm_driver_type1
-#define VMW_RES_STREAM ttm_driver_type2
-
 struct vmw_user_context {
 	struct ttm_base_object base;
 	struct vmw_resource res;
@@ -43,6 +39,7 @@ struct vmw_user_context {
 struct vmw_user_surface {
 	struct ttm_base_object base;
 	struct vmw_surface srf;
+	uint32_t size;
 };
 
 struct vmw_user_dma_buffer {
@@ -65,6 +62,17 @@ struct vmw_user_stream {
 	struct vmw_stream stream;
 };
 
+struct vmw_surface_offset {
+	uint32_t face;
+	uint32_t mip;
+	uint32_t bo_offset;
+};
+
+
+static uint64_t vmw_user_context_size;
+static uint64_t vmw_user_surface_size;
+static uint64_t vmw_user_stream_size;
+
 static inline struct vmw_dma_buffer *
 vmw_dma_buffer(struct ttm_buffer_object *bo)
 {
@@ -84,13 +92,36 @@ struct vmw_resource *vmw_resource_refere
 	return res;
 }
 
+
+/**
+ * vmw_resource_release_id - release a resource id to the id manager.
+ *
+ * @res: Pointer to the resource.
+ *
+ * Release the resource id to the resource id manager and set it to -1
+ */
+static void vmw_resource_release_id(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	write_lock(&dev_priv->resource_lock);
+	if (res->id != -1)
+		idr_remove(res->idr, res->id);
+	res->id = -1;
+	write_unlock(&dev_priv->resource_lock);
+}
+
 static void vmw_resource_release(struct kref *kref)
 {
 	struct vmw_resource *res =
 	    container_of(kref, struct vmw_resource, kref);
 	struct vmw_private *dev_priv = res->dev_priv;
+	int id = res->id;
+	struct idr *idr = res->idr;
 
-	idr_remove(res->idr, res->id);
+	res->avail = false;
+	if (res->remove_from_lists != NULL)
+		res->remove_from_lists(res);
 	write_unlock(&dev_priv->resource_lock);
 
 	if (likely(res->hw_destroy != NULL))
@@ -102,6 +133,9 @@ static void vmw_resource_release(struct
 		kfree(res);
 
 	write_lock(&dev_priv->resource_lock);
+
+	if (id != -1)
+		idr_remove(idr, id);
 }
 
 void vmw_resource_unreference(struct vmw_resource **p_res)
@@ -115,28 +149,29 @@ void vmw_resource_unreference(struct vmw
 	write_unlock(&dev_priv->resource_lock);
 }
 
-static int vmw_resource_init(struct vmw_private *dev_priv,
-			     struct vmw_resource *res,
-			     struct idr *idr,
-			     enum ttm_object_type obj_type,
-			     void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_resource_alloc_id - release a resource id to the id manager.
+ *
+ * @dev_priv: Pointer to the device private structure.
+ * @res: Pointer to the resource.
+ *
+ * Allocate the lowest free resource from the resource manager, and set
+ * @res->id to that id. Returns 0 on success and -ENOMEM on failure.
+ */
+static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
+				 struct vmw_resource *res)
 {
 	int ret;
 
-	kref_init(&res->kref);
-	res->hw_destroy = NULL;
-	res->res_free = res_free;
-	res->res_type = obj_type;
-	res->idr = idr;
-	res->avail = false;
-	res->dev_priv = dev_priv;
+	BUG_ON(res->id != -1);
 
 	do {
-		if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+		if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0))
 			return -ENOMEM;
 
 		write_lock(&dev_priv->resource_lock);
-		ret = idr_get_new_above(idr, res, 1, &res->id);
+		ret = idr_get_new_above(res->idr, res, 1, &res->id);
 		write_unlock(&dev_priv->resource_lock);
 
 	} while (ret == -EAGAIN);
@@ -144,6 +179,33 @@ static int vmw_resource_init(struct vmw_
 	return ret;
 }
 
+
+static int vmw_resource_init(struct vmw_private *dev_priv,
+			     struct vmw_resource *res,
+			     struct idr *idr,
+			     enum ttm_object_type obj_type,
+			     bool delay_id,
+			     void (*res_free) (struct vmw_resource *res),
+			     void (*remove_from_lists)
+			     (struct vmw_resource *res))
+{
+	kref_init(&res->kref);
+	res->hw_destroy = NULL;
+	res->res_free = res_free;
+	res->remove_from_lists = remove_from_lists;
+	res->res_type = obj_type;
+	res->idr = idr;
+	res->avail = false;
+	res->dev_priv = dev_priv;
+	INIT_LIST_HEAD(&res->query_head);
+	INIT_LIST_HEAD(&res->validate_head);
+	res->id = -1;
+	if (delay_id)
+		return 0;
+	else
+		return vmw_resource_alloc_id(dev_priv, res);
+}
+
 /**
  * vmw_resource_activate
  *
@@ -198,8 +260,12 @@ static void vmw_hw_context_destroy(struc
 	struct {
 		SVGA3dCmdHeader header;
 		SVGA3dCmdDestroyContext body;
-	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	} *cmd;
+
+
+	vmw_execbuf_release_pinned_bo(dev_priv, true, res->id);
 
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Failed reserving FIFO space for surface "
 			  "destruction.\n");
@@ -211,7 +277,7 @@ static void vmw_hw_context_destroy(struc
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	vmw_3d_resource_dec(dev_priv);
+	vmw_3d_resource_dec(dev_priv, false);
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -226,14 +292,17 @@ static int vmw_context_init(struct vmw_p
 	} *cmd;
 
 	ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
-				VMW_RES_CONTEXT, res_free);
+				VMW_RES_CONTEXT, false, res_free, NULL);
 
 	if (unlikely(ret != 0)) {
-		if (res_free == NULL)
-			kfree(res);
-		else
-			res_free(res);
-		return ret;
+		DRM_ERROR("Failed to allocate a resource id.\n");
+		goto out_early;
+	}
+
+	if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
+		DRM_ERROR("Out of hw context ids.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
 	}
 
 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
@@ -248,9 +317,16 @@ static int vmw_context_init(struct vmw_p
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	(void) vmw_3d_resource_inc(dev_priv);
+	(void) vmw_3d_resource_inc(dev_priv, false);
 	vmw_resource_activate(res, vmw_hw_context_destroy);
 	return 0;
+
+out_early:
+	if (res_free == NULL)
+		kfree(res);
+	else
+		res_free(res);
+	return ret;
 }
 
 struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
@@ -273,8 +349,11 @@ static void vmw_user_context_free(struct
 {
 	struct vmw_user_context *ctx =
 	    container_of(res, struct vmw_user_context, res);
+	struct vmw_private *dev_priv = res->dev_priv;
 
 	kfree(ctx);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_user_context_size);
 }
 
 /**
@@ -328,23 +407,56 @@ int vmw_context_define_ioctl(struct drm_
 			     struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	struct vmw_user_context *ctx;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
 	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
-	if (unlikely(ctx == NULL))
-		return -ENOMEM;
+
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of contexts anyway.
+	 */
+
+	if (unlikely(vmw_user_context_size == 0))
+		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_user_context_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for context"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (unlikely(ctx == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_user_context_size);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
 	res = &ctx->res;
 	ctx->base.shareable = false;
 	ctx->base.tfile = NULL;
 
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+
 	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(&ctx->res);
 	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
@@ -358,13 +470,16 @@ int vmw_context_define_ioctl(struct drm_
 	arg->cid = res->id;
 out_err:
 	vmw_resource_unreference(&res);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 
 }
 
 int vmw_context_check(struct vmw_private *dev_priv,
 		      struct ttm_object_file *tfile,
-		      int id)
+		      int id,
+		      struct vmw_resource **p_res)
 {
 	struct vmw_resource *res;
 	int ret = 0;
@@ -376,6 +491,8 @@ int vmw_context_check(struct vmw_private
 			container_of(res, struct vmw_user_context, res);
 		if (ctx->base.tfile != tfile && !ctx->base.shareable)
 			ret = -EPERM;
+		if (p_res)
+			*p_res = vmw_resource_reference(res);
 	} else
 		ret = -EINVAL;
 	read_unlock(&dev_priv->resource_lock);
@@ -383,102 +500,638 @@ int vmw_context_check(struct vmw_private
 	return ret;
 }
 
+struct vmw_bpp {
+	uint8_t bpp;
+	uint8_t s_bpp;
+};
+
+/*
+ * Size table for the supported SVGA3D surface formats. It consists of
+ * two values. The bpp value and the s_bpp value which is short for
+ * "stride bits per pixel" The values are given in such a way that the
+ * minimum stride for the image is calculated using
+ *
+ * min_stride = w*s_bpp
+ *
+ * and the total memory requirement for the image is
+ *
+ * h*min_stride*bpp/s_bpp
+ *
+ */
+static const struct vmw_bpp vmw_sf_bpp[] = {
+	[SVGA3D_FORMAT_INVALID] = {0, 0},
+	[SVGA3D_X8R8G8B8] = {32, 32},
+	[SVGA3D_A8R8G8B8] = {32, 32},
+	[SVGA3D_R5G6B5] = {16, 16},
+	[SVGA3D_X1R5G5B5] = {16, 16},
+	[SVGA3D_A1R5G5B5] = {16, 16},
+	[SVGA3D_A4R4G4B4] = {16, 16},
+	[SVGA3D_Z_D32] = {32, 32},
+	[SVGA3D_Z_D16] = {16, 16},
+	[SVGA3D_Z_D24S8] = {32, 32},
+	[SVGA3D_Z_D15S1] = {16, 16},
+	[SVGA3D_LUMINANCE8] = {8, 8},
+	[SVGA3D_LUMINANCE4_ALPHA4] = {8, 8},
+	[SVGA3D_LUMINANCE16] = {16, 16},
+	[SVGA3D_LUMINANCE8_ALPHA8] = {16, 16},
+	[SVGA3D_DXT1] = {4, 16},
+	[SVGA3D_DXT2] = {8, 32},
+	[SVGA3D_DXT3] = {8, 32},
+	[SVGA3D_DXT4] = {8, 32},
+	[SVGA3D_DXT5] = {8, 32},
+	[SVGA3D_BUMPU8V8] = {16, 16},
+	[SVGA3D_BUMPL6V5U5] = {16, 16},
+	[SVGA3D_BUMPX8L8V8U8] = {32, 32},
+	[SVGA3D_ARGB_S10E5] = {16, 16},
+	[SVGA3D_ARGB_S23E8] = {32, 32},
+	[SVGA3D_A2R10G10B10] = {32, 32},
+	[SVGA3D_V8U8] = {16, 16},
+	[SVGA3D_Q8W8V8U8] = {32, 32},
+	[SVGA3D_CxV8U8] = {16, 16},
+	[SVGA3D_X8L8V8U8] = {32, 32},
+	[SVGA3D_A2W10V10U10] = {32, 32},
+	[SVGA3D_ALPHA8] = {8, 8},
+	[SVGA3D_R_S10E5] = {16, 16},
+	[SVGA3D_R_S23E8] = {32, 32},
+	[SVGA3D_RG_S10E5] = {16, 16},
+	[SVGA3D_RG_S23E8] = {32, 32},
+	[SVGA3D_BUFFER] = {8, 8},
+	[SVGA3D_Z_D24X8] = {32, 32},
+	[SVGA3D_V16U16] = {32, 32},
+	[SVGA3D_G16R16] = {32, 32},
+	[SVGA3D_A16B16G16R16] = {64,  64},
+	[SVGA3D_UYVY] = {12, 12},
+	[SVGA3D_YUY2] = {12, 12},
+	[SVGA3D_NV12] = {12, 8},
+	[SVGA3D_AYUV] = {32, 32},
+	[SVGA3D_BC4_UNORM] = {4,  16},
+	[SVGA3D_BC5_UNORM] = {8,  32},
+	[SVGA3D_Z_DF16] = {16,  16},
+	[SVGA3D_Z_DF24] = {24,  24},
+	[SVGA3D_Z_D24S8_INT] = {32,  32}
+};
+
 
 /**
  * Surface management.
  */
 
+struct vmw_surface_dma {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdSurfaceDMA body;
+	SVGA3dCopyBox cb;
+	SVGA3dCmdSurfaceDMASuffix suffix;
+};
+
+struct vmw_surface_define {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDefineSurface body;
+};
+
+struct vmw_surface_destroy {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDestroySurface body;
+};
+
+
+/**
+ * vmw_surface_dma_size - Compute fifo size for a dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface dma command for backup or
+ * restoration of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
+{
+	return srf->num_sizes * sizeof(struct vmw_surface_dma);
+}
+
+
+/**
+ * vmw_surface_define_size - Compute fifo size for a surface define command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface define command for the definition
+ * of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
+{
+	return sizeof(struct vmw_surface_define) + srf->num_sizes *
+		sizeof(SVGA3dSize);
+}
+
+
+/**
+ * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
+ *
+ * Computes the required size for a surface destroy command for the destruction
+ * of a hw surface.
+ */
+static inline uint32_t vmw_surface_destroy_size(void)
+{
+	return sizeof(struct vmw_surface_destroy);
+}
+
+/**
+ * vmw_surface_destroy_encode - Encode a surface_destroy command.
+ *
+ * @id: The surface id
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_destroy_encode(uint32_t id,
+				       void *cmd_space)
+{
+	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
+		cmd_space;
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
+	cmd->header.size = sizeof(cmd->body);
+	cmd->body.sid = id;
+}
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_define_encode(const struct vmw_surface *srf,
+				      void *cmd_space)
+{
+	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
+		cmd_space;
+	struct drm_vmw_size *src_size;
+	SVGA3dSize *cmd_size;
+	uint32_t cmd_len;
+	int i;
+
+	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
+	cmd->header.size = cmd_len;
+	cmd->body.sid = srf->res.id;
+	cmd->body.surfaceFlags = srf->flags;
+	cmd->body.format = cpu_to_le32(srf->format);
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
+
+	cmd += 1;
+	cmd_size = (SVGA3dSize *) cmd;
+	src_size = srf->sizes;
+
+	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+		cmd_size->width = src_size->width;
+		cmd_size->height = src_size->height;
+		cmd_size->depth = src_size->depth;
+	}
+}
+
+
+/**
+ * vmw_surface_dma_encode - Encode a surface_dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
+ * should be placed or read from.
+ * @to_surface: Boolean whether to DMA to the surface or from the surface.
+ */
+static void vmw_surface_dma_encode(struct vmw_surface *srf,
+				   void *cmd_space,
+				   const SVGAGuestPtr *ptr,
+				   bool to_surface)
+{
+	uint32_t i;
+	uint32_t bpp = vmw_sf_bpp[srf->format].bpp;
+	uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
+
+	for (i = 0; i < srf->num_sizes; ++i) {
+		SVGA3dCmdHeader *header = &cmd->header;
+		SVGA3dCmdSurfaceDMA *body = &cmd->body;
+		SVGA3dCopyBox *cb = &cmd->cb;
+		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
+		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
+		const struct drm_vmw_size *cur_size = &srf->sizes[i];
+
+		header->id = SVGA_3D_CMD_SURFACE_DMA;
+		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
+
+		body->guest.ptr = *ptr;
+		body->guest.ptr.offset += cur_offset->bo_offset;
+		body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3;
+		body->host.sid = srf->res.id;
+		body->host.face = cur_offset->face;
+		body->host.mipmap = cur_offset->mip;
+		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
+				  SVGA3D_READ_HOST_VRAM);
+		cb->x = 0;
+		cb->y = 0;
+		cb->z = 0;
+		cb->srcx = 0;
+		cb->srcy = 0;
+		cb->srcz = 0;
+		cb->w = cur_size->width;
+		cb->h = cur_size->height;
+		cb->d = cur_size->depth;
+
+		suffix->suffixSize = sizeof(*suffix);
+		suffix->maximumOffset = body->guest.pitch*cur_size->height*
+			cur_size->depth*bpp / stride_bpp;
+		suffix->flags.discard = 0;
+		suffix->flags.unsynchronized = 0;
+		suffix->flags.reserved = 0;
+		++cmd;
+	}
+};
+
+
 static void vmw_hw_surface_destroy(struct vmw_resource *res)
 {
 
 	struct vmw_private *dev_priv = res->dev_priv;
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDestroySurface body;
-	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	struct vmw_surface *srf;
+	void *cmd;
 
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving FIFO space for surface "
-			  "destruction.\n");
-		return;
-	}
+	if (res->id != -1) {
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
-	cmd->body.sid = cpu_to_le32(res->id);
+		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
+		if (unlikely(cmd == NULL)) {
+			DRM_ERROR("Failed reserving FIFO space for surface "
+				  "destruction.\n");
+			return;
+		}
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	vmw_3d_resource_dec(dev_priv);
+		vmw_surface_destroy_encode(res->id, cmd);
+		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
+
+		/*
+		 * used_memory_size_atomic, or separate lock
+		 * to avoid taking dev_priv::cmdbuf_mutex in
+		 * the destroy path.
+		 */
+
+		mutex_lock(&dev_priv->cmdbuf_mutex);
+		srf = container_of(res, struct vmw_surface, res);
+		dev_priv->used_memory_size -= srf->backup_size;
+		mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	}
+	vmw_3d_resource_dec(dev_priv, false);
 }
 
 void vmw_surface_res_free(struct vmw_resource *res)
 {
 	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
 
+	if (srf->backup)
+		ttm_bo_unref(&srf->backup);
+	kfree(srf->offsets);
 	kfree(srf->sizes);
 	kfree(srf->snooper.image);
 	kfree(srf);
 }
 
-int vmw_surface_init(struct vmw_private *dev_priv,
-		     struct vmw_surface *srf,
-		     void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_surface_do_validate - make a surface available to the device.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * If the surface doesn't have a hw id, allocate one, and optionally
+ * DMA the backed up surface contents to the device.
+ *
+ * Returns -EBUSY if there wasn't sufficient device resources to
+ * complete the validation. Retry after freeing up resources.
+ *
+ * May return other errors if the kernel is out of guest resources.
+ */
+int vmw_surface_do_validate(struct vmw_private *dev_priv,
+			    struct vmw_surface *srf)
 {
-	int ret;
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDefineSurface body;
-	} *cmd;
-	SVGA3dSize *cmd_size;
 	struct vmw_resource *res = &srf->res;
-	struct drm_vmw_size *src_size;
-	size_t submit_size;
-	uint32_t cmd_len;
-	int i;
+	struct list_head val_list;
+	struct ttm_validate_buffer val_buf;
+	uint32_t submit_size;
+	uint8_t *cmd;
+	int ret;
 
-	BUG_ON(res_free == NULL);
-	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
-				VMW_RES_SURFACE, res_free);
+	if (likely(res->id != -1))
+		return 0;
+
+	if (unlikely(dev_priv->used_memory_size + srf->backup_size >=
+		     dev_priv->memory_size))
+		return -EBUSY;
+
+	/*
+	 * Reserve- and validate the backup DMA bo.
+	 */
+
+	if (srf->backup) {
+		INIT_LIST_HEAD(&val_list);
+		val_buf.bo = ttm_bo_reference(srf->backup);
+		val_buf.new_sync_obj_arg = (void *)((unsigned long)
+						    DRM_VMW_FENCE_FLAG_EXEC);
+		list_add_tail(&val_buf.head, &val_list);
+		ret = ttm_eu_reserve_buffers(&val_list);
+		if (unlikely(ret != 0))
+			goto out_no_reserve;
+
+		ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+				      true, false, false);
+		if (unlikely(ret != 0))
+			goto out_no_validate;
+	}
 
+	/*
+	 * Alloc id for the resource.
+	 */
+
+	ret = vmw_resource_alloc_id(dev_priv, res);
 	if (unlikely(ret != 0)) {
-		res_free(res);
-		return ret;
+		DRM_ERROR("Failed to allocate a surface id.\n");
+		goto out_no_id;
+	}
+	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
+		ret = -EBUSY;
+		goto out_no_fifo;
 	}
 
-	submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
-	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	/*
+	 * Encode surface define- and dma commands.
+	 */
+
+	submit_size = vmw_surface_define_size(srf);
+	if (srf->backup)
+		submit_size += vmw_surface_dma_size(srf);
 
 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
 	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Fifo reserve failed for create surface.\n");
-		vmw_resource_unreference(&res);
-		return -ENOMEM;
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "validation.\n");
+		ret = -ENOMEM;
+		goto out_no_fifo;
 	}
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
-	cmd->header.size = cpu_to_le32(cmd_len);
-	cmd->body.sid = cpu_to_le32(res->id);
-	cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
-	cmd->body.format = cpu_to_le32(srf->format);
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
-		cmd->body.face[i].numMipLevels =
-		    cpu_to_le32(srf->mip_levels[i]);
+	vmw_surface_define_encode(srf, cmd);
+	if (srf->backup) {
+		SVGAGuestPtr ptr;
+
+		cmd += vmw_surface_define_size(srf);
+		vmw_bo_get_guest_ptr(srf->backup, &ptr);
+		vmw_surface_dma_encode(srf, cmd, &ptr, true);
 	}
 
-	cmd += 1;
-	cmd_size = (SVGA3dSize *) cmd;
-	src_size = srf->sizes;
+	vmw_fifo_commit(dev_priv, submit_size);
 
-	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
-		cmd_size->width = cpu_to_le32(src_size->width);
-		cmd_size->height = cpu_to_le32(src_size->height);
-		cmd_size->depth = cpu_to_le32(src_size->depth);
+	/*
+	 * Create a fence object and fence the backup buffer.
+	 */
+
+	if (srf->backup) {
+		struct vmw_fence_obj *fence;
+
+		(void) vmw_execbuf_fence_commands(NULL, dev_priv,
+						  &fence, NULL);
+		ttm_eu_fence_buffer_objects(&val_list, fence);
+		if (likely(fence != NULL))
+			vmw_fence_obj_unreference(&fence);
+		ttm_bo_unref(&val_buf.bo);
+		ttm_bo_unref(&srf->backup);
+	}
+
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size += srf->backup_size;
+
+	return 0;
+
+out_no_fifo:
+	vmw_resource_release_id(res);
+out_no_id:
+out_no_validate:
+	if (srf->backup)
+		ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+	if (srf->backup)
+		ttm_bo_unref(&val_buf.bo);
+	return ret;
+}
+
+/**
+ * vmw_surface_evict - Evict a hw surface.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * DMA the contents of a hw surface to a backup guest buffer object,
+ * and destroy the hw surface, releasing its id.
+ */
+int vmw_surface_evict(struct vmw_private *dev_priv,
+		      struct vmw_surface *srf)
+{
+	struct vmw_resource *res = &srf->res;
+	struct list_head val_list;
+	struct ttm_validate_buffer val_buf;
+	uint32_t submit_size;
+	uint8_t *cmd;
+	int ret;
+	struct vmw_fence_obj *fence;
+	SVGAGuestPtr ptr;
+
+	BUG_ON(res->id == -1);
+
+	/*
+	 * Create a surface backup buffer object.
+	 */
+
+	if (!srf->backup) {
+		ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size,
+				    ttm_bo_type_device,
+				    &vmw_srf_placement, 0, 0, true,
+				    NULL, &srf->backup);
+		if (unlikely(ret != 0))
+			return ret;
 	}
 
+	/*
+	 * Reserve- and validate the backup DMA bo.
+	 */
+
+	INIT_LIST_HEAD(&val_list);
+	val_buf.bo = ttm_bo_reference(srf->backup);
+	val_buf.new_sync_obj_arg = (void *)(unsigned long)
+		DRM_VMW_FENCE_FLAG_EXEC;
+	list_add_tail(&val_buf.head, &val_list);
+	ret = ttm_eu_reserve_buffers(&val_list);
+	if (unlikely(ret != 0))
+		goto out_no_reserve;
+
+	ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+			      true, false, false);
+	if (unlikely(ret != 0))
+		goto out_no_validate;
+
+
+	/*
+	 * Encode the dma- and surface destroy commands.
+	 */
+
+	submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size();
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "eviction.\n");
+		ret = -ENOMEM;
+		goto out_no_fifo;
+	}
+
+	vmw_bo_get_guest_ptr(srf->backup, &ptr);
+	vmw_surface_dma_encode(srf, cmd, &ptr, false);
+	cmd += vmw_surface_dma_size(srf);
+	vmw_surface_destroy_encode(res->id, cmd);
 	vmw_fifo_commit(dev_priv, submit_size);
-	(void) vmw_3d_resource_inc(dev_priv);
-	vmw_resource_activate(res, vmw_hw_surface_destroy);
+
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size -= srf->backup_size;
+
+	/*
+	 * Create a fence object and fence the DMA buffer.
+	 */
+
+	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
+					  &fence, NULL);
+	ttm_eu_fence_buffer_objects(&val_list, fence);
+	if (likely(fence != NULL))
+		vmw_fence_obj_unreference(&fence);
+	ttm_bo_unref(&val_buf.bo);
+
+	/*
+	 * Release the surface ID.
+	 */
+
+	vmw_resource_release_id(res);
+
 	return 0;
+
+out_no_fifo:
+out_no_validate:
+	if (srf->backup)
+		ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+	ttm_bo_unref(&val_buf.bo);
+	ttm_bo_unref(&srf->backup);
+	return ret;
+}
+
+
+/**
+ * vmw_surface_validate - make a surface available to the device, evicting
+ * other surfaces if needed.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * Try to validate a surface and if it fails due to limited device resources,
+ * repeatedly try to evict other surfaces until the request can be
+ * acommodated.
+ *
+ * May return errors if out of resources.
+ */
+int vmw_surface_validate(struct vmw_private *dev_priv,
+			 struct vmw_surface *srf)
+{
+	int ret;
+	struct vmw_surface *evict_srf;
+
+	do {
+		write_lock(&dev_priv->resource_lock);
+		list_del_init(&srf->lru_head);
+		write_unlock(&dev_priv->resource_lock);
+
+		ret = vmw_surface_do_validate(dev_priv, srf);
+		if (likely(ret != -EBUSY))
+			break;
+
+		write_lock(&dev_priv->resource_lock);
+		if (list_empty(&dev_priv->surface_lru)) {
+			DRM_ERROR("Out of device memory for surfaces.\n");
+			ret = -EBUSY;
+			write_unlock(&dev_priv->resource_lock);
+			break;
+		}
+
+		evict_srf = vmw_surface_reference
+			(list_first_entry(&dev_priv->surface_lru,
+					  struct vmw_surface,
+					  lru_head));
+		list_del_init(&evict_srf->lru_head);
+
+		write_unlock(&dev_priv->resource_lock);
+		(void) vmw_surface_evict(dev_priv, evict_srf);
+
+		vmw_surface_unreference(&evict_srf);
+
+	} while (1);
+
+	if (unlikely(ret != 0 && srf->res.id != -1)) {
+		write_lock(&dev_priv->resource_lock);
+		list_add_tail(&srf->lru_head, &dev_priv->surface_lru);
+		write_unlock(&dev_priv->resource_lock);
+	}
+
+	return ret;
+}
+
+
+/**
+ * vmw_surface_remove_from_lists - Remove surface resources from lookup lists
+ *
+ * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface
+ *
+ * As part of the resource destruction, remove the surface from any
+ * lookup lists.
+ */
+static void vmw_surface_remove_from_lists(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+
+	list_del_init(&srf->lru_head);
+}
+
+int vmw_surface_init(struct vmw_private *dev_priv,
+		     struct vmw_surface *srf,
+		     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+	struct vmw_resource *res = &srf->res;
+
+	BUG_ON(res_free == NULL);
+	INIT_LIST_HEAD(&srf->lru_head);
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
+				VMW_RES_SURFACE, true, res_free,
+				vmw_surface_remove_from_lists);
+
+	if (unlikely(ret != 0))
+		res_free(res);
+
+	/*
+	 * The surface won't be visible to hardware until a
+	 * surface validate.
+	 */
+
+	(void) vmw_3d_resource_inc(dev_priv, false);
+	vmw_resource_activate(res, vmw_hw_surface_destroy);
+	return ret;
 }
 
 static void vmw_user_surface_free(struct vmw_resource *res)
@@ -486,12 +1139,81 @@ static void vmw_user_surface_free(struct
 	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
 	struct vmw_user_surface *user_srf =
 	    container_of(srf, struct vmw_user_surface, srf);
+	struct vmw_private *dev_priv = srf->res.dev_priv;
+	uint32_t size = user_srf->size;
 
+	if (srf->backup)
+		ttm_bo_unref(&srf->backup);
+	kfree(srf->offsets);
 	kfree(srf->sizes);
 	kfree(srf->snooper.image);
 	kfree(user_srf);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_resource_unreserve - unreserve resources previously reserved for
+ * command submission.
+ *
+ * @list_head: list of resources to unreserve.
+ *
+ * Currently only surfaces are considered, and unreserving a surface
+ * means putting it back on the device's surface lru list,
+ * so that it can be evicted if necessary.
+ * This function traverses the resource list and
+ * checks whether resources are surfaces, and in that case puts them back
+ * on the device's surface LRU list.
+ */
+void vmw_resource_unreserve(struct list_head *list)
+{
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	rwlock_t *lock = NULL;
+
+	list_for_each_entry(res, list, validate_head) {
+
+		if (res->res_free != &vmw_surface_res_free &&
+		    res->res_free != &vmw_user_surface_free)
+			continue;
+
+		if (unlikely(lock == NULL)) {
+			lock = &res->dev_priv->resource_lock;
+			write_lock(lock);
+		}
+
+		srf = container_of(res, struct vmw_surface, res);
+		list_del_init(&srf->lru_head);
+		list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru);
+	}
+
+	if (lock != NULL)
+		write_unlock(lock);
+}
+
+/**
+ * Helper function that looks either a surface or dmabuf.
+ *
+ * The pointer this pointed at by out_surf and out_buf needs to be null.
+ */
+int vmw_user_lookup_handle(struct vmw_private *dev_priv,
+			   struct ttm_object_file *tfile,
+			   uint32_t handle,
+			   struct vmw_surface **out_surf,
+			   struct vmw_dma_buffer **out_buf)
+{
+	int ret;
+
+	BUG_ON(*out_surf || *out_buf);
+
+	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf);
+	if (!ret)
+		return 0;
+
+	ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
+	return ret;
 }
 
+
 int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
 				   struct ttm_object_file *tfile,
 				   uint32_t handle, struct vmw_surface **out)
@@ -556,8 +1278,7 @@ int vmw_surface_define_ioctl(struct drm_
 			     struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_surface *user_srf =
-	    kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	struct vmw_user_surface *user_srf;
 	struct vmw_surface *srf;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
@@ -568,10 +1289,51 @@ int vmw_surface_define_ioctl(struct drm_
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
 	struct drm_vmw_size __user *user_sizes;
 	int ret;
-	int i;
+	int i, j;
+	uint32_t cur_bo_offset;
+	struct drm_vmw_size *cur_size;
+	struct vmw_surface_offset *cur_offset;
+	uint32_t stride_bpp;
+	uint32_t bpp;
+	uint32_t num_sizes;
+	uint32_t size;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 
-	if (unlikely(user_srf == NULL))
-		return -ENOMEM;
+	if (unlikely(vmw_user_surface_size == 0))
+		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+			128;
+
+	num_sizes = 0;
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		num_sizes += req->mip_levels[i];
+
+	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+	    DRM_VMW_MAX_MIP_LEVELS)
+		return -EINVAL;
+
+	size = vmw_user_surface_size + 128 +
+		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
+		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
+
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   size, false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for surface"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	if (unlikely(user_srf == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_user_srf;
+	}
 
 	srf = &user_srf->srf;
 	res = &srf->res;
@@ -579,21 +1341,22 @@ int vmw_surface_define_ioctl(struct drm_
 	srf->flags = req->flags;
 	srf->format = req->format;
 	srf->scanout = req->scanout;
-	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
-	srf->num_sizes = 0;
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
-		srf->num_sizes += srf->mip_levels[i];
+	srf->backup = NULL;
 
-	if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
-	    DRM_VMW_MAX_MIP_LEVELS) {
-		ret = -EINVAL;
-		goto out_err0;
-	}
+	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+	srf->num_sizes = num_sizes;
+	user_srf->size = size;
 
 	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
 	if (unlikely(srf->sizes == NULL)) {
 		ret = -ENOMEM;
-		goto out_err0;
+		goto out_no_sizes;
+	}
+	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
+			       GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_offsets;
 	}
 
 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
@@ -603,9 +1366,32 @@ int vmw_surface_define_ioctl(struct drm_
 			     srf->num_sizes * sizeof(*srf->sizes));
 	if (unlikely(ret != 0)) {
 		ret = -EFAULT;
-		goto out_err1;
+		goto out_no_copy;
 	}
 
+	cur_bo_offset = 0;
+	cur_offset = srf->offsets;
+	cur_size = srf->sizes;
+
+	bpp = vmw_sf_bpp[srf->format].bpp;
+	stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		for (j = 0; j < srf->mip_levels[i]; ++j) {
+			uint32_t stride =
+				(cur_size->width * stride_bpp + 7) >> 3;
+
+			cur_offset->face = i;
+			cur_offset->mip = j;
+			cur_offset->bo_offset = cur_bo_offset;
+			cur_bo_offset += stride * cur_size->height *
+				cur_size->depth * bpp / stride_bpp;
+			++cur_offset;
+			++cur_size;
+		}
+	}
+	srf->backup_size = cur_bo_offset;
+
 	if (srf->scanout &&
 	    srf->num_sizes == 1 &&
 	    srf->sizes[0].width == 64 &&
@@ -617,7 +1403,7 @@ int vmw_surface_define_ioctl(struct drm_
 		if (!srf->snooper.image) {
 			DRM_ERROR("Failed to allocate cursor_image\n");
 			ret = -ENOMEM;
-			goto out_err1;
+			goto out_no_copy;
 		}
 	} else {
 		srf->snooper.image = NULL;
@@ -634,7 +1420,7 @@ int vmw_surface_define_ioctl(struct drm_
 
 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(&srf->res);
 	ret = ttm_base_object_init(tfile, &user_srf->base,
@@ -644,7 +1430,7 @@ int vmw_surface_define_ioctl(struct drm_
 	if (unlikely(ret != 0)) {
 		vmw_resource_unreference(&tmp);
 		vmw_resource_unreference(&res);
-		return ret;
+		goto out_unlock;
 	}
 
 	rep->sid = user_srf->base.hash.key;
@@ -652,11 +1438,19 @@ int vmw_surface_define_ioctl(struct drm_
 		DRM_ERROR("Created bad Surface ID.\n");
 
 	vmw_resource_unreference(&res);
+
+	ttm_read_unlock(&vmaster->lock);
 	return 0;
-out_err1:
+out_no_copy:
+	kfree(srf->offsets);
+out_no_offsets:
 	kfree(srf->sizes);
-out_err0:
+out_no_sizes:
 	kfree(user_srf);
+out_no_user_srf:
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
 
@@ -970,7 +1764,7 @@ static int vmw_stream_init(struct vmw_pr
 	int ret;
 
 	ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
-				VMW_RES_STREAM, res_free);
+				VMW_RES_STREAM, false, res_free, NULL);
 
 	if (unlikely(ret != 0)) {
 		if (res_free == NULL)
@@ -1000,8 +1794,11 @@ static void vmw_user_stream_free(struct
 {
 	struct vmw_user_stream *stream =
 	    container_of(res, struct vmw_user_stream, stream.res);
+	struct vmw_private *dev_priv = res->dev_priv;
 
 	kfree(stream);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_user_stream_size);
 }
 
 /**
@@ -1055,23 +1852,56 @@ int vmw_stream_claim_ioctl(struct drm_de
 			   struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	struct vmw_user_stream *stream;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
 	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
-	if (unlikely(stream == NULL))
-		return -ENOMEM;
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of streams anyway?
+	 */
+
+	if (unlikely(vmw_user_stream_size == 0))
+		vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_user_stream_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for stream"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+
+	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	if (unlikely(stream == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_user_stream_size);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
 	res = &stream->stream.res;
 	stream->base.shareable = false;
 	stream->base.tfile = NULL;
 
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+
 	ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(res);
 	ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
@@ -1085,6 +1915,8 @@ int vmw_stream_claim_ioctl(struct drm_de
 	arg->stream_id = res->id;
 out_err:
 	vmw_resource_unreference(&res);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,537 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_kms.h"
+
+
+#define vmw_crtc_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.crtc)
+#define vmw_encoder_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.encoder)
+#define vmw_connector_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.connector)
+
+struct vmw_screen_object_display {
+	unsigned num_implicit;
+
+	struct vmw_framebuffer *implicit_fb;
+};
+
+/**
+ * Display unit using screen objects.
+ */
+struct vmw_screen_object_unit {
+	struct vmw_display_unit base;
+
+	unsigned long buffer_size; /**< Size of allocated buffer */
+	struct vmw_dma_buffer *buffer; /**< Backing store buffer */
+
+	bool defined;
+	bool active_implicit;
+};
+
+static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
+{
+	vmw_display_unit_cleanup(&sou->base);
+	kfree(sou);
+}
+
+
+/*
+ * Screen Object Display Unit CRTC functions
+ */
+
+static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
+{
+	vmw_sou_destroy(vmw_crtc_to_sou(crtc));
+}
+
+static void vmw_sou_del_active(struct vmw_private *vmw_priv,
+			      struct vmw_screen_object_unit *sou)
+{
+	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+
+	if (sou->active_implicit) {
+		if (--(ld->num_implicit) == 0)
+			ld->implicit_fb = NULL;
+		sou->active_implicit = false;
+	}
+}
+
+static void vmw_sou_add_active(struct vmw_private *vmw_priv,
+			      struct vmw_screen_object_unit *sou,
+			      struct vmw_framebuffer *vfb)
+{
+	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+
+	BUG_ON(!ld->num_implicit && ld->implicit_fb);
+
+	if (!sou->active_implicit && sou->base.is_implicit) {
+		ld->implicit_fb = vfb;
+		sou->active_implicit = true;
+		ld->num_implicit++;
+	}
+}
+
+/**
+ * Send the fifo command to create a screen.
+ */
+static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
+			       struct vmw_screen_object_unit *sou,
+			       uint32_t x, uint32_t y,
+			       struct drm_display_mode *mode)
+{
+	size_t fifo_size;
+
+	struct {
+		struct {
+			uint32_t cmdType;
+		} header;
+		SVGAScreenObject obj;
+	} *cmd;
+
+	BUG_ON(!sou->buffer);
+
+	fifo_size = sizeof(*cmd);
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* The hardware has hung, nothing we can do about it here. */
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
+	cmd->obj.structSize = sizeof(SVGAScreenObject);
+	cmd->obj.id = sou->base.unit;
+	cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
+		(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
+	cmd->obj.size.width = mode->hdisplay;
+	cmd->obj.size.height = mode->vdisplay;
+	if (sou->base.is_implicit) {
+		cmd->obj.root.x = x;
+		cmd->obj.root.y = y;
+	} else {
+		cmd->obj.root.x = sou->base.gui_x;
+		cmd->obj.root.y = sou->base.gui_y;
+	}
+
+	/* Ok to assume that buffer is pinned in vram */
+	vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
+	cmd->obj.backingStore.pitch = mode->hdisplay * 4;
+
+	vmw_fifo_commit(dev_priv, fifo_size);
+
+	sou->defined = true;
+
+	return 0;
+}
+
+/**
+ * Send the fifo command to destroy a screen.
+ */
+static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
+				struct vmw_screen_object_unit *sou)
+{
+	size_t fifo_size;
+	int ret;
+
+	struct {
+		struct {
+			uint32_t cmdType;
+		} header;
+		SVGAFifoCmdDestroyScreen body;
+	} *cmd;
+
+	/* no need to do anything */
+	if (unlikely(!sou->defined))
+		return 0;
+
+	fifo_size = sizeof(*cmd);
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* the hardware has hung, nothing we can do about it here */
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
+	cmd->body.screenId = sou->base.unit;
+
+	vmw_fifo_commit(dev_priv, fifo_size);
+
+	/* Force sync */
+	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
+	if (unlikely(ret != 0))
+		DRM_ERROR("Failed to sync with HW");
+	else
+		sou->defined = false;
+
+	return ret;
+}
+
+/**
+ * Free the backing store.
+ */
+static void vmw_sou_backing_free(struct vmw_private *dev_priv,
+				 struct vmw_screen_object_unit *sou)
+{
+	struct ttm_buffer_object *bo;
+
+	if (unlikely(sou->buffer == NULL))
+		return;
+
+	bo = &sou->buffer->base;
+	ttm_bo_unref(&bo);
+	sou->buffer = NULL;
+	sou->buffer_size = 0;
+}
+
+/**
+ * Allocate the backing store for the buffer.
+ */
+static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
+				 struct vmw_screen_object_unit *sou,
+				 unsigned long size)
+{
+	int ret;
+
+	if (sou->buffer_size == size)
+		return 0;
+
+	if (sou->buffer)
+		vmw_sou_backing_free(dev_priv, sou);
+
+	sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
+	if (unlikely(sou->buffer == NULL))
+		return -ENOMEM;
+
+	/* After we have alloced the backing store might not be able to
+	 * resume the overlays, this is preferred to failing to alloc.
+	 */
+	vmw_overlay_pause_all(dev_priv);
+	ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
+			      &vmw_vram_ne_placement,
+			      false, &vmw_dmabuf_bo_free);
+	vmw_overlay_resume_all(dev_priv);
+
+	if (unlikely(ret != 0))
+		sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
+	else
+		sou->buffer_size = size;
+
+	return ret;
+}
+
+static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_object_unit *sou;
+	struct drm_connector *connector;
+	struct drm_display_mode *mode;
+	struct drm_encoder *encoder;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+	struct drm_crtc *crtc;
+	int ret = 0;
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	/* get the sou */
+	crtc = set->crtc;
+	sou = vmw_crtc_to_sou(crtc);
+	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (set->num_connectors > 1) {
+		DRM_ERROR("to many connectors\n");
+		return -EINVAL;
+	}
+
+	if (set->num_connectors == 1 &&
+	    set->connectors[0] != &sou->base.connector) {
+		DRM_ERROR("connector doesn't match %p %p\n",
+			set->connectors[0], &sou->base.connector);
+		return -EINVAL;
+	}
+
+	/* sou only supports one fb active at the time */
+	if (sou->base.is_implicit &&
+	    dev_priv->sou_priv->implicit_fb && vfb &&
+	    !(dev_priv->sou_priv->num_implicit == 1 &&
+	      sou->active_implicit) &&
+	    dev_priv->sou_priv->implicit_fb != vfb) {
+		DRM_ERROR("Multiple framebuffers not supported\n");
+		return -EINVAL;
+	}
+
+	/* since they always map one to one these are safe */
+	connector = &sou->base.connector;
+	encoder = &sou->base.encoder;
+
+	/* should we turn the crtc off */
+	if (set->num_connectors == 0 || !set->mode || !set->fb) {
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		/* the hardware has hung don't do anything more */
+		if (unlikely(ret != 0))
+			return ret;
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+		crtc->x = 0;
+		crtc->y = 0;
+
+		vmw_sou_del_active(dev_priv, sou);
+
+		vmw_sou_backing_free(dev_priv, sou);
+
+		return 0;
+	}
+
+
+	/* we now know we want to set a mode */
+	mode = set->mode;
+	fb = set->fb;
+
+	if (set->x + mode->hdisplay > fb->width ||
+	    set->y + mode->vdisplay > fb->height) {
+		DRM_ERROR("set outside of framebuffer\n");
+		return -EINVAL;
+	}
+
+	vmw_fb_off(dev_priv);
+
+	if (mode->hdisplay != crtc->mode.hdisplay ||
+	    mode->vdisplay != crtc->mode.vdisplay) {
+		/* no need to check if depth is different, because backing
+		 * store depth is forced to 4 by the device.
+		 */
+
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		/* the hardware has hung don't do anything more */
+		if (unlikely(ret != 0))
+			return ret;
+
+		vmw_sou_backing_free(dev_priv, sou);
+	}
+
+	if (!sou->buffer) {
+		/* forced to depth 4 by the device */
+		size_t size = mode->hdisplay * mode->vdisplay * 4;
+		ret = vmw_sou_backing_alloc(dev_priv, sou, size);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
+	if (unlikely(ret != 0)) {
+		/*
+		 * We are in a bit of a situation here, the hardware has
+		 * hung and we may or may not have a buffer hanging of
+		 * the screen object, best thing to do is not do anything
+		 * if we where defined, if not just turn the crtc of.
+		 * Not what userspace wants but it needs to htfu.
+		 */
+		if (sou->defined)
+			return ret;
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+		crtc->x = 0;
+		crtc->y = 0;
+
+		return ret;
+	}
+
+	vmw_sou_add_active(dev_priv, sou, vfb);
+
+	connector->encoder = encoder;
+	encoder->crtc = crtc;
+	crtc->mode = *mode;
+	crtc->fb = fb;
+	crtc->x = set->x;
+	crtc->y = set->y;
+
+	return 0;
+}
+
+static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
+	.save = vmw_du_crtc_save,
+	.restore = vmw_du_crtc_restore,
+	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_move = vmw_du_crtc_cursor_move,
+	.gamma_set = vmw_du_crtc_gamma_set,
+	.destroy = vmw_sou_crtc_destroy,
+	.set_config = vmw_sou_crtc_set_config,
+};
+
+/*
+ * Screen Object Display Unit encoder functions
+ */
+
+static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
+{
+	vmw_sou_destroy(vmw_encoder_to_sou(encoder));
+}
+
+static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
+	.destroy = vmw_sou_encoder_destroy,
+};
+
+/*
+ * Screen Object Display Unit connector functions
+ */
+
+static void vmw_sou_connector_destroy(struct drm_connector *connector)
+{
+	vmw_sou_destroy(vmw_connector_to_sou(connector));
+}
+
+static struct drm_connector_funcs vmw_legacy_connector_funcs = {
+	.dpms = vmw_du_connector_dpms,
+	.save = vmw_du_connector_save,
+	.restore = vmw_du_connector_restore,
+	.detect = vmw_du_connector_detect,
+	.fill_modes = vmw_du_connector_fill_modes,
+	.set_property = vmw_du_connector_set_property,
+	.destroy = vmw_sou_connector_destroy,
+};
+
+static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
+{
+	struct vmw_screen_object_unit *sou;
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
+	if (!sou)
+		return -ENOMEM;
+
+	sou->base.unit = unit;
+	crtc = &sou->base.crtc;
+	encoder = &sou->base.encoder;
+	connector = &sou->base.connector;
+
+	sou->active_implicit = false;
+
+	sou->base.pref_active = (unit == 0);
+	sou->base.pref_width = 800;
+	sou->base.pref_height = 600;
+	sou->base.pref_mode = NULL;
+	sou->base.is_implicit = true;
+
+	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+			   DRM_MODE_CONNECTOR_VIRTUAL);
+	connector->status = vmw_du_connector_detect(connector, true);
+
+	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
+			 DRM_MODE_ENCODER_VIRTUAL);
+	drm_mode_connector_attach_encoder(connector, encoder);
+	encoder->possible_crtcs = (1 << unit);
+	encoder->possible_clones = 0;
+
+	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
+
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
+	drm_connector_attach_property(connector,
+				      dev->mode_config.dirty_info_property,
+				      1);
+
+	return 0;
+}
+
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int i, ret;
+
+	if (dev_priv->sou_priv) {
+		DRM_INFO("sou system already on\n");
+		return -EINVAL;
+	}
+
+	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) {
+		DRM_INFO("Not using screen objects,"
+			 " missing cap SCREEN_OBJECT_2\n");
+		return -ENOSYS;
+	}
+
+	ret = -ENOMEM;
+	dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
+	if (unlikely(!dev_priv->sou_priv))
+		goto err_no_mem;
+
+	dev_priv->sou_priv->num_implicit = 0;
+	dev_priv->sou_priv->implicit_fb = NULL;
+
+	ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+	if (unlikely(ret != 0))
+		goto err_free;
+
+	ret = drm_mode_create_dirty_info_property(dev);
+	if (unlikely(ret != 0))
+		goto err_vblank_cleanup;
+
+	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
+		vmw_sou_init(dev_priv, i);
+
+	DRM_INFO("Screen objects system initialized\n");
+
+	return 0;
+
+err_vblank_cleanup:
+	drm_vblank_cleanup(dev);
+err_free:
+	kfree(dev_priv->sou_priv);
+	dev_priv->sou_priv = NULL;
+err_no_mem:
+	return ret;
+}
+
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (!dev_priv->sou_priv)
+		return -ENOSYS;
+
+	drm_vblank_cleanup(dev);
+
+	kfree(dev_priv->sou_priv);
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
--- linux-libre-3.1-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,9 +34,8 @@ int vmw_mmap(struct file *filp, struct v
 	struct vmw_private *dev_priv;
 
 	if (unlikely(vma->vm_pgoff < VMWGFX_FILE_PAGE_OFFSET)) {
-		if (vmw_fifo_mmap(filp, vma) == 0)
-			return 0;
-		return drm_mmap(filp, vma);
+		DRM_ERROR("Illegal attempt to mmap old fifo space.\n");
+		return -EINVAL;
 	}
 
 	file_priv = filp->private_data;
diff -druNp linux-libre-3.1-gnu1/drivers/gpu/vga/vgaarb.c linux-libre-3.2-gnu1/drivers/gpu/vga/vgaarb.c
--- linux-libre-3.1-gnu1/drivers/gpu/vga/vgaarb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/gpu/vga/vgaarb.c	2012-01-04 18:55:44.000000000 -0500
@@ -465,31 +465,29 @@ static void vga_arbiter_check_bridge_sha
 	while (new_bus) {
 		new_bridge = new_bus->self;
 
-		if (new_bridge) {
-			/* go through list of devices already registered */
-			list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
-				bus = same_bridge_vgadev->pdev->bus;
-				bridge = bus->self;
+		/* go through list of devices already registered */
+		list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
+			bus = same_bridge_vgadev->pdev->bus;
+			bridge = bus->self;
 
-				/* see if the share a bridge with this device */
-				if (new_bridge == bridge) {
-					/* if their direct parent bridge is the same
-					   as any bridge of this device then it can't be used
-					   for that device */
-					same_bridge_vgadev->bridge_has_one_vga = false;
-				}
+			/* see if the share a bridge with this device */
+			if (new_bridge == bridge) {
+				/* if their direct parent bridge is the same
+				   as any bridge of this device then it can't be used
+				   for that device */
+				same_bridge_vgadev->bridge_has_one_vga = false;
+			}
 
-				/* now iterate the previous devices bridge hierarchy */
-				/* if the new devices parent bridge is in the other devices
-				   hierarchy then we can't use it to control this device */
-				while (bus) {
-					bridge = bus->self;
-					if (bridge) {
-						if (bridge == vgadev->pdev->bus->self)
-							vgadev->bridge_has_one_vga = false;
-					}
-					bus = bus->parent;
+			/* now iterate the previous devices bridge hierarchy */
+			/* if the new devices parent bridge is in the other devices
+			   hierarchy then we can't use it to control this device */
+			while (bus) {
+				bridge = bus->self;
+				if (bridge) {
+					if (bridge == vgadev->pdev->bus->self)
+						vgadev->bridge_has_one_vga = false;
 				}
+				bus = bus->parent;
 			}
 		}
 		new_bus = new_bus->parent;
@@ -993,14 +991,20 @@ static ssize_t vga_arb_write(struct file
 				uc = &priv->cards[i];
 		}
 
-		if (!uc)
-			return -EINVAL;
+		if (!uc) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
-		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0)
-			return -EINVAL;
+		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
-		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0)
-			return -EINVAL;
+		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
 		vga_put(pdev, io_state);
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-apple.c linux-libre-3.2-gnu1/drivers/hid/hid-apple.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-apple.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-apple.c	2012-01-04 18:55:44.000000000 -0500
@@ -455,6 +455,9 @@ static const struct hid_device_id apple_
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
 			APPLE_ISO_KEYBOARD },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+			APPLE_ISO_KEYBOARD },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
@@ -493,6 +496,24 @@ static const struct hid_device_id apple_
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-axff.c linux-libre-3.2-gnu1/drivers/hid/hid-axff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-axff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-axff.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  * Xbox 360 controller.
  *
  * 1a34:0802 "ACRUX USB GAMEPAD 8116"
- *  - tested with a EXEQ EQ-PCU-02090 game controller.
+ *  - tested with an EXEQ EQ-PCU-02090 game controller.
  *
  * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru>
  */
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
@@ -45,7 +46,10 @@ static int axff_play(struct input_dev *d
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct axff_device *axff = data;
+	struct hid_report *report = axff->report;
+	int field_count = 0;
 	int left, right;
+	int i, j;
 
 	left = effect->u.rumble.strong_magnitude;
 	right = effect->u.rumble.weak_magnitude;
@@ -55,10 +59,14 @@ static int axff_play(struct input_dev *d
 	left = left * 0xff / 0xffff;
 	right = right * 0xff / 0xffff;
 
-	axff->report->field[0]->value[0] = left;
-	axff->report->field[1]->value[0] = right;
-	axff->report->field[2]->value[0] = left;
-	axff->report->field[3]->value[0] = right;
+	for (i = 0; i < report->maxfield; i++) {
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			report->field[i]->value[j] =
+				field_count % 2 ? right : left;
+			field_count++;
+		}
+	}
+
 	dbg_hid("running with 0x%02x 0x%02x", left, right);
 	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
 
@@ -72,6 +80,8 @@ static int axff_init(struct hid_device *
 	struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
 	struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct input_dev *dev = hidinput->input;
+	int field_count = 0;
+	int i, j;
 	int error;
 
 	if (list_empty(report_list)) {
@@ -80,9 +90,16 @@ static int axff_init(struct hid_device *
 	}
 
 	report = list_first_entry(report_list, struct hid_report, list);
+	for (i = 0; i < report->maxfield; i++) {
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			report->field[i]->value[j] = 0x00;
+			field_count++;
+		}
+	}
 
-	if (report->maxfield < 4) {
-		hid_err(hid, "no fields in the report: %d\n", report->maxfield);
+	if (field_count < 4) {
+		hid_err(hid, "not enough fields in the report: %d\n",
+			field_count);
 		return -ENODEV;
 	}
 
@@ -97,13 +114,9 @@ static int axff_init(struct hid_device *
 		goto err_free_mem;
 
 	axff->report = report;
-	axff->report->field[0]->value[0] = 0x00;
-	axff->report->field[1]->value[0] = 0x00;
-	axff->report->field[2]->value[0] = 0x00;
-	axff->report->field[3]->value[0] = 0x00;
 	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
 
-	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n");
+	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
 
 	return 0;
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-core.c linux-libre-3.2-gnu1/drivers/hid/hid-core.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/wait.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 
 #include <linux/hid.h>
 #include <linux/hiddev.h>
@@ -1085,16 +1086,25 @@ int hid_input_report(struct hid_device *
 	struct hid_report *report;
 	char *buf;
 	unsigned int i;
-	int ret;
+	int ret = 0;
 
-	if (!hid || !hid->driver)
+	if (!hid)
 		return -ENODEV;
+
+	if (down_trylock(&hid->driver_lock))
+		return -EBUSY;
+
+	if (!hid->driver) {
+		ret = -ENODEV;
+		goto unlock;
+	}
 	report_enum = hid->report_enum + type;
 	hdrv = hid->driver;
 
 	if (!size) {
 		dbg_hid("empty report\n");
-		return -1;
+		ret = -1;
+		goto unlock;
 	}
 
 	buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
@@ -1118,18 +1128,24 @@ int hid_input_report(struct hid_device *
 nomem:
 	report = hid_get_report(report_enum, data);
 
-	if (!report)
-		return -1;
+	if (!report) {
+		ret = -1;
+		goto unlock;
+	}
 
 	if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
 		ret = hdrv->raw_event(hid, report, data, size);
-		if (ret != 0)
-			return ret < 0 ? ret : 0;
+		if (ret != 0) {
+			ret = ret < 0 ? ret : 0;
+			goto unlock;
+		}
 	}
 
 	hid_report_raw_event(hid, type, data, size, interrupt);
 
-	return 0;
+unlock:
+	up(&hid->driver_lock);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
 
@@ -1212,6 +1228,12 @@ int hid_connect(struct hid_device *hdev,
 	if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
 				connect_mask & HID_CONNECT_HIDINPUT_FORCE))
 		hdev->claimed |= HID_CLAIMED_INPUT;
+	if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
+		/* this device should be handled by hid-multitouch, skip it */
+		hdev->quirks &= ~HID_QUIRK_MULTITOUCH;
+		return -ENODEV;
+	}
+
 	if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
 			!hdev->hiddev_connect(hdev,
 				connect_mask & HID_CONNECT_HIDDEV_FORCE))
@@ -1340,12 +1362,22 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
@@ -1391,6 +1423,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
@@ -1399,6 +1432,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1420,8 +1454,11 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
@@ -1461,6 +1498,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
@@ -1501,6 +1539,10 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
@@ -1620,10 +1662,15 @@ static int hid_device_probe(struct devic
 	const struct hid_device_id *id;
 	int ret = 0;
 
+	if (down_interruptible(&hdev->driver_lock))
+		return -EINTR;
+
 	if (!hdev->driver) {
 		id = hid_match_device(hdev, hdrv);
-		if (id == NULL)
-			return -ENODEV;
+		if (id == NULL) {
+			ret = -ENODEV;
+			goto unlock;
+		}
 
 		hdev->driver = hdrv;
 		if (hdrv->probe) {
@@ -1636,14 +1683,20 @@ static int hid_device_probe(struct devic
 		if (ret)
 			hdev->driver = NULL;
 	}
+unlock:
+	up(&hdev->driver_lock);
 	return ret;
 }
 
 static int hid_device_remove(struct device *dev)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct hid_driver *hdrv = hdev->driver;
+	struct hid_driver *hdrv;
 
+	if (down_interruptible(&hdev->driver_lock))
+		return -EINTR;
+
+	hdrv = hdev->driver;
 	if (hdrv) {
 		if (hdrv->remove)
 			hdrv->remove(hdev);
@@ -1652,6 +1705,7 @@ static int hid_device_remove(struct devi
 		hdev->driver = NULL;
 	}
 
+	up(&hdev->driver_lock);
 	return 0;
 }
 
@@ -1717,8 +1771,8 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) },
@@ -1892,6 +1946,15 @@ static const struct hid_device_id hid_mo
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
@@ -1999,6 +2062,7 @@ struct hid_device *hid_allocate_device(v
 
 	init_waitqueue_head(&hdev->debug_wait);
 	INIT_LIST_HEAD(&hdev->debug_list);
+	sema_init(&hdev->driver_lock, 1);
 
 	return hdev;
 err:
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-debug.c linux-libre-3.2-gnu1/drivers/hid/hid-debug.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/poll.h>
@@ -450,6 +451,11 @@ void hid_dump_field(struct hid_field *fi
 		seq_printf(f, "Logical(");
 		hid_resolv_usage(field->logical, f); seq_printf(f, ")\n");
 	}
+	if (field->application) {
+		tab(n, f);
+		seq_printf(f, "Application(");
+		hid_resolv_usage(field->application, f); seq_printf(f, ")\n");
+	}
 	tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage);
 	for (j = 0; j < field->maxusage; j++) {
 		tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n");
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-dr.c linux-libre-3.2-gnu1/drivers/hid/hid-dr.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-dr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-dr.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-emsff.c linux-libre-3.2-gnu1/drivers/hid/hid-emsff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-emsff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-emsff.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 #include "usbhid/usbhid.h"
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-gaff.c linux-libre-3.2-gnu1/drivers/hid/hid-gaff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-gaff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-gaff.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_GREENASIA_FF
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-holtekff.c linux-libre-3.2-gnu1/drivers/hid/hid-holtekff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-holtekff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-holtekff.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 
 #include <linux/hid.h>
 #include <linux/input.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-ids.h linux-libre-3.2-gnu1/drivers/hid/hid-ids.h
--- linux-libre-3.1-gnu1/drivers/hid/hid-ids.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-ids.h	2012-01-04 18:55:44.000000000 -0500
@@ -112,9 +112,19 @@
 #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI	0x024f
 #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO	0x0250
 #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS	0x0251
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI	0x0252
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO	0x0253
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS	0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI	0x0249
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO	0x024a
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS	0x024b
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI	0x024c
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO	0x024d
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS	0x024e
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
 #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL	0x8241
@@ -256,7 +266,7 @@
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
 
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
-#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
 
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
@@ -351,6 +361,9 @@
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
 #define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
 
+#define USB_VENDOR_ID_IDEACOM		0x1cb6
+#define USB_DEVICE_ID_IDEACOM_IDC6650	0x6650
+
 #define USB_VENDOR_ID_ILITEK		0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH	0x0001
 
@@ -423,6 +436,9 @@
 #define USB_DEVICE_ID_LD_HYBRID		0x2090
 #define USB_DEVICE_ID_LD_HEATCONTROL	0x20A0
 
+#define USB_VENDOR_ID_LG		0x1fd2
+#define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
+
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
@@ -440,6 +456,7 @@
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
 #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL	0xc298
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL	0xc299
+#define USB_DEVICE_ID_LOGITECH_DFGT_WHEEL	0xc29a
 #define USB_DEVICE_ID_LOGITECH_G27_WHEEL	0xc29b
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
@@ -447,6 +464,8 @@
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER	0xc52b
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2	0xc532
 #define USB_DEVICE_ID_SPACETRAVELLER	0xc623
 #define USB_DEVICE_ID_SPACENAVIGATOR	0xc626
 #define USB_DEVICE_ID_DINOVO_DESKTOP	0xc704
@@ -678,6 +697,9 @@
 #define USB_VENDOR_ID_WISEGROUP_LTD	0x6666
 #define USB_VENDOR_ID_WISEGROUP_LTD2	0x6677
 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO 0x8801
+#define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804
 
 #define USB_VENDOR_ID_X_TENSIONS               0x1ae7
 #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE    0x9001
@@ -693,4 +715,7 @@
 #define USB_VENDOR_ID_ZYDACRON	0x13EC
 #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL	0x0006
 
+#define USB_VENDOR_ID_PRIMAX	0x0461
+#define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
+
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-input.c linux-libre-3.2-gnu1/drivers/hid/hid-input.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -474,6 +474,10 @@ static void hidinput_configure_usage(str
 			map_key_clear(BTN_STYLUS2);
 			break;
 
+		case 0x51: /* ContactID */
+			device->quirks |= HID_QUIRK_MULTITOUCH;
+			goto unknown;
+
 		default:  goto unknown;
 		}
 		break;
@@ -978,6 +982,13 @@ int hidinput_connect(struct hid_device *
 		}
 	}
 
+	if (hid->quirks & HID_QUIRK_MULTITOUCH) {
+		/* generic hid does not know how to handle multitouch devices */
+		if (hidinput)
+			goto out_cleanup;
+		goto out_unwind;
+	}
+
 	if (hidinput && input_register_device(hidinput->input))
 		goto out_cleanup;
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-lg4ff.c linux-libre-3.2-gnu1/drivers/hid/hid-lg4ff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-lg4ff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-lg4ff.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,19 +29,108 @@
 
 #include "usbhid/usbhid.h"
 #include "hid-lg.h"
+#include "hid-ids.h"
 
-struct lg4ff_device {
-	struct hid_report *report;
+#define DFGT_REV_MAJ 0x13
+#define DFGT_REV_MIN 0x22
+#define DFP_REV_MAJ 0x11
+#define DFP_REV_MIN 0x06
+#define FFEX_REV_MAJ 0x21
+#define FFEX_REV_MIN 0x00
+#define G25_REV_MAJ 0x12
+#define G25_REV_MIN 0x22
+#define G27_REV_MAJ 0x12
+#define G27_REV_MIN 0x38
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+
+static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
+
+static bool list_inited;
+
+struct lg4ff_device_entry {
+	char  *device_id;	/* Use name in respective kobject structure's address as the ID */
+	__u16 range;
+	__u16 min_range;
+	__u16 max_range;
+	__u8  leds;
+	struct list_head list;
+	void (*set_range)(struct hid_device *hid, u16 range);
 };
 
-static const signed short ff4_wheel_ac[] = {
+static struct lg4ff_device_entry device_list;
+
+static const signed short lg4ff_wheel_effects[] = {
 	FF_CONSTANT,
 	FF_AUTOCENTER,
 	-1
 };
 
-static int hid_lg4ff_play(struct input_dev *dev, void *data,
-			 struct ff_effect *effect)
+struct lg4ff_wheel {
+	const __u32 product_id;
+	const signed short *ff_effects;
+	const __u16 min_range;
+	const __u16 max_range;
+	void (*set_range)(struct hid_device *hid, u16 range);
+};
+
+static const struct lg4ff_wheel lg4ff_devices[] = {
+	{USB_DEVICE_ID_LOGITECH_WHEEL,       lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,  lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_DFP_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp},
+	{USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
+};
+
+struct lg4ff_native_cmd {
+	const __u8 cmd_num;	/* Number of commands to send */
+	const __u8 cmd[];
+};
+
+struct lg4ff_usb_revision {
+	const __u16 rev_maj;
+	const __u16 rev_min;
+	const struct lg4ff_native_cmd *command;
+};
+
+static const struct lg4ff_native_cmd native_dfp = {
+	1,
+	{0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_dfgt = {
+	2,
+	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 1st command */
+	 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}	/* 2nd command */
+};
+
+static const struct lg4ff_native_cmd native_g25 = {
+	1,
+	{0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_g27 = {
+	2,
+	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 1st command */
+	 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}	/* 2nd command */
+};
+
+static const struct lg4ff_usb_revision lg4ff_revs[] = {
+	{DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt},	/* Driving Force GT */
+	{DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},	/* Driving Force Pro */
+	{G25_REV_MAJ,  G25_REV_MIN,  &native_g25},	/* G25 */
+	{G27_REV_MAJ,  G27_REV_MIN,  &native_g27},	/* G27 */
+};
+
+static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -55,13 +144,12 @@ static int hid_lg4ff_play(struct input_d
 		x = effect->u.ramp.start_level + 0x80;	/* 0x80 is no force */
 		CLAMP(x);
 		report->field[0]->value[0] = 0x11;	/* Slot 1 */
-		report->field[0]->value[1] = 0x10;
+		report->field[0]->value[1] = 0x08;
 		report->field[0]->value[2] = x;
-		report->field[0]->value[3] = 0x00;
+		report->field[0]->value[3] = 0x80;
 		report->field[0]->value[4] = 0x00;
-		report->field[0]->value[5] = 0x08;
+		report->field[0]->value[5] = 0x00;
 		report->field[0]->value[6] = 0x00;
-		dbg_hid("Autocenter, x=0x%02X\n", x);
 
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
@@ -69,24 +157,184 @@ static int hid_lg4ff_play(struct input_d
 	return 0;
 }
 
-static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+/* Sends default autocentering command compatible with
+ * all wheels except Formula Force EX */
+static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-	__s32 *value = report->field[0]->value;
 
-	*value++ = 0xfe;
-	*value++ = 0x0d;
-	*value++ = 0x07;
-	*value++ = 0x07;
-	*value++ = (magnitude >> 8) & 0xff;
-	*value++ = 0x00;
-	*value = 0x00;
+	report->field[0]->value[0] = 0xfe;
+	report->field[0]->value[1] = 0x0d;
+	report->field[0]->value[2] = magnitude >> 13;
+	report->field[0]->value[3] = magnitude >> 13;
+	report->field[0]->value[4] = magnitude >> 8;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
 
+/* Sends autocentering command compatible with Formula Force EX */
+static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	magnitude = magnitude * 90 / 65535;
+	
+
+	report->field[0]->value[0] = 0xfe;
+	report->field[0]->value[1] = 0x03;
+	report->field[0]->value[2] = magnitude >> 14;
+	report->field[0]->value[3] = magnitude >> 14;
+	report->field[0]->value[4] = magnitude;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends command to set range compatible with G25/G27/Driving Force GT */
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
+
+	report->field[0]->value[0] = 0xf8;
+	report->field[0]->value[1] = 0x81;
+	report->field[0]->value[2] = range & 0x00ff;
+	report->field[0]->value[3] = (range & 0xff00) >> 8;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends commands to set range compatible with Driving Force Pro wheel */
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	int start_left, start_right, full_range;
+	dbg_hid("Driving Force Pro: setting range to %u\n", range);
+
+	/* Prepare "coarse" limit command */
+	report->field[0]->value[0] = 0xf8;
+	report->field[0]->value[1] = 0x00; 	/* Set later */
+	report->field[0]->value[2] = 0x00;
+	report->field[0]->value[3] = 0x00;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	if (range > 200) {
+		report->field[0]->value[1] = 0x03;
+		full_range = 900;
+	} else {
+		report->field[0]->value[1] = 0x02;
+		full_range = 200;
+	}
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+
+	/* Prepare "fine" limit command */
+	report->field[0]->value[0] = 0x81;
+	report->field[0]->value[1] = 0x0b;
+	report->field[0]->value[2] = 0x00;
+	report->field[0]->value[3] = 0x00;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	if (range == 200 || range == 900) {	/* Do not apply any fine limit */
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		return;
+	}
+
+	/* Construct fine limit command */
+	start_left = (((full_range - range + 1) * 2047) / full_range);
+	start_right = 0xfff - start_left;
+
+	report->field[0]->value[2] = start_left >> 4;
+	report->field[0]->value[3] = start_right >> 4;
+	report->field[0]->value[4] = 0xff;
+	report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
+	report->field[0]->value[6] = 0xff;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__u8 i, j;
+
+	j = 0;
+	while (j < 7*cmd->cmd_num) {
+		for (i = 0; i < 7; i++)
+			report->field[0]->value[i] = cmd->cmd[j++];
+
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+	}
+}
+
+/* Read current range and display it in terminal */
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct lg4ff_device_entry *uninitialized_var(entry);
+	struct list_head *h;
+	struct hid_device *hid = to_hid_device(dev);
+	size_t count;
+
+	list_for_each(h, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+			break;
+	}
+	if (h == &device_list.list) {
+		dbg_hid("Device not found!");
+		return 0;
+	}
+
+	count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range);
+	return count;
+}
+
+/* Set range to user specified value, call appropriate function
+ * according to the type of the wheel */
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lg4ff_device_entry *uninitialized_var(entry);
+	struct list_head *h;
+	struct hid_device *hid = to_hid_device(dev);
+	__u16 range = simple_strtoul(buf, NULL, 10);
+
+	list_for_each(h, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+			break;
+	}
+	if (h == &device_list.list) {
+		dbg_hid("Device not found!");
+		return count;
+	}
+
+	if (range == 0)
+		range = entry->max_range;
+
+	/* Check if the wheel supports range setting
+	 * and that the range is within limits for the wheel */
+	if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) {
+		entry->set_range(hid, range);
+		entry->range = range;
+	}
+
+	return count;
+}
 
 int lg4ff_init(struct hid_device *hid)
 {
@@ -95,9 +343,10 @@ int lg4ff_init(struct hid_device *hid)
 	struct input_dev *dev = hidinput->input;
 	struct hid_report *report;
 	struct hid_field *field;
-	const signed short *ff_bits = ff4_wheel_ac;
-	int error;
-	int i;
+	struct lg4ff_device_entry *entry;
+	struct usb_device_descriptor *udesc;
+	int error, i, j;
+	__u16 bcdDevice, rev_maj, rev_min;
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
@@ -118,18 +367,122 @@ int lg4ff_init(struct hid_device *hid)
 		return -1;
 	}
 
-	for (i = 0; ff_bits[i] >= 0; i++)
-		set_bit(ff_bits[i], dev->ffbit);
+	/* Check what wheel has been connected */
+	for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
+		if (hid->product == lg4ff_devices[i].product_id) {
+			dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(lg4ff_devices)) {
+		hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to"
+			     "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n");
+		return -1;
+	}
+
+	/* Attempt to switch wheel to native mode when applicable */
+	udesc = &(hid_to_usb_dev(hid)->descriptor);
+	if (!udesc) {
+		hid_err(hid, "NULL USB device descriptor\n");
+		return -1;
+	}
+	bcdDevice = le16_to_cpu(udesc->bcdDevice);
+	rev_maj = bcdDevice >> 8;
+	rev_min = bcdDevice & 0xff;
+
+	if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) {
+		dbg_hid("Generic wheel detected, can it do native?\n");
+		dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min);
+
+		for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) {
+			if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) {
+				hid_lg4ff_switch_native(hid, lg4ff_revs[j].command);
+				hid_info(hid, "Switched to native mode\n");
+			}
+		}
+	}
+
+	/* Set supported force feedback capabilities */
+	for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
+		set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
 
 	error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
 
 	if (error)
 		return error;
 
-	if (test_bit(FF_AUTOCENTER, dev->ffbit))
-		dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
+	/* Check if autocentering is available and
+	 * set the centering force to zero by default */
+	if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+		if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)	/* Formula Force EX expects different autocentering command */
+			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+		else
+			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+		dev->ff->set_autocenter(dev, 0);
+	}
+
+		/* Initialize device_list if this is the first device to handle by lg4ff */
+	if (!list_inited) {
+		INIT_LIST_HEAD(&device_list.list);
+		list_inited = 1;
+	}
+
+	/* Add the device to device_list */
+	entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
+	if (!entry) {
+		hid_err(hid, "Cannot add device, insufficient memory.\n");
+		return -ENOMEM;
+	}
+	entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL);
+	if (!entry->device_id) {
+		hid_err(hid, "Cannot set device_id, insufficient memory.\n");
+		kfree(entry);
+		return -ENOMEM;
+	}
+	entry->min_range = lg4ff_devices[i].min_range;
+	entry->max_range = lg4ff_devices[i].max_range;
+	entry->set_range = lg4ff_devices[i].set_range;
+	list_add(&entry->list, &device_list.list);
+
+	/* Create sysfs interface */
+	error = device_create_file(&hid->dev, &dev_attr_range);
+	if (error)
+		return error;
+	dbg_hid("sysfs interface created\n");
+
+	/* Set the maximum range to start with */
+	entry->range = entry->max_range;
+	if (entry->set_range != NULL)
+		entry->set_range(hid, entry->range);
 
 	hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
 	return 0;
 }
 
+int lg4ff_deinit(struct hid_device *hid)
+{
+	bool found = 0;
+	struct lg4ff_device_entry *entry;
+	struct list_head *h, *g;
+	list_for_each_safe(h, g, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) {
+			list_del(h);
+			kfree(entry->device_id);
+			kfree(entry);
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		dbg_hid("Device entry not found!\n");
+		return -1;
+	}
+
+	device_remove_file(&hid->dev, &dev_attr_range);
+	dbg_hid("Device successfully unregistered\n");
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-lg.c linux-libre-3.2-gnu1/drivers/hid/hid-lg.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-lg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-lg.c	2012-01-04 18:55:44.000000000 -0500
@@ -363,7 +363,7 @@ static int lg_probe(struct hid_device *h
 		goto err_free;
 	}
 
-	if (quirks & (LG_FF | LG_FF2 | LG_FF3))
+	if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
 		connect_mask &= ~HID_CONNECT_FF;
 
 	ret = hid_hw_start(hdev, connect_mask);
@@ -372,7 +372,8 @@ static int lg_probe(struct hid_device *h
 		goto err_free;
 	}
 
-	if (quirks & LG_FF4) {
+	/* Setup wireless link with Logitech Wii wheel */
+	if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
 		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -405,6 +406,15 @@ err_free:
 	return ret;
 }
 
+static void lg_remove(struct hid_device *hdev)
+{
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	if(quirks & LG_FF4)
+		lg4ff_deinit(hdev);
+
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id lg_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
 		.driver_data = LG_RDESC | LG_WIRELESS },
@@ -431,7 +441,7 @@ static const struct hid_device_id lg_dev
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
 		.driver_data = LG_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
-		.driver_data = LG_NOGET | LG_FF },
+		.driver_data = LG_NOGET | LG_FF4 },
 
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
 		.driver_data = LG_FF2 },
@@ -444,15 +454,17 @@ static const struct hid_device_id lg_dev
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
-		.driver_data = LG_NOGET | LG_FF },
+		.driver_data = LG_NOGET | LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
 		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
@@ -478,6 +490,7 @@ static struct hid_driver lg_driver = {
 	.input_mapped = lg_input_mapped,
 	.event = lg_event,
 	.probe = lg_probe,
+	.remove = lg_remove,
 };
 
 static int __init lg_init(void)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-lgff.c linux-libre-3.2-gnu1/drivers/hid/hid-lgff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-lgff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-lgff.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,12 +58,6 @@ static const signed short ff_joystick_ac
 	-1
 };
 
-static const signed short ff_wheel[] = {
-	FF_CONSTANT,
-	FF_AUTOCENTER,
-	-1
-};
-
 static const struct dev_type devices[] = {
 	{ 0x046d, 0xc211, ff_rumble },
 	{ 0x046d, 0xc219, ff_rumble },
@@ -71,14 +65,7 @@ static const struct dev_type devices[] =
 	{ 0x046d, 0xc286, ff_joystick_ac },
 	{ 0x046d, 0xc287, ff_joystick_ac },
 	{ 0x046d, 0xc293, ff_joystick },
-	{ 0x046d, 0xc294, ff_wheel },
-	{ 0x046d, 0xc298, ff_wheel },
-	{ 0x046d, 0xc299, ff_wheel },
-	{ 0x046d, 0xc29b, ff_wheel },
 	{ 0x046d, 0xc295, ff_joystick },
-	{ 0x046d, 0xc298, ff_wheel },
-	{ 0x046d, 0xc299, ff_wheel },
-	{ 0x046d, 0xca03, ff_wheel },
 };
 
 static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-lg.h linux-libre-3.2-gnu1/drivers/hid/hid-lg.h
--- linux-libre-3.1-gnu1/drivers/hid/hid-lg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-lg.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,10 +19,12 @@ int lg3ff_init(struct hid_device *hdev);
 static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
-#ifdef CONFIG_LOGIWII_FF
+#ifdef CONFIG_LOGIWHEELS_FF
 int lg4ff_init(struct hid_device *hdev);
+int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
+static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-logitech-dj.c linux-libre-3.2-gnu1/drivers/hid/hid-logitech-dj.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-logitech-dj.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hid/hid-logitech-dj.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,922 @@
+/*
+ *  HID driver for Logitech Unifying receivers
+ *
+ *  Copyright (c) 2011 Logitech
+ */
+
+/*
+ * 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.
+
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+#include "hid-ids.h"
+#include "hid-logitech-dj.h"
+
+/* Keyboard descriptor (1) */
+static const char kbd_descriptor[] = {
+	0x05, 0x01,		/* USAGE_PAGE (generic Desktop)     */
+	0x09, 0x06,		/* USAGE (Keyboard)         */
+	0xA1, 0x01,		/* COLLECTION (Application)     */
+	0x85, 0x01,		/* REPORT_ID (1)            */
+	0x95, 0x08,		/*   REPORT_COUNT (8)           */
+	0x75, 0x01,		/*   REPORT_SIZE (1)            */
+	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
+	0x25, 0x01,		/*   LOGICAL_MAXIMUM (1)        */
+	0x05, 0x07,		/*   USAGE_PAGE (Keyboard)      */
+	0x19, 0xE0,		/*   USAGE_MINIMUM (Left Control)   */
+	0x29, 0xE7,		/*   USAGE_MAXIMUM (Right GUI)      */
+	0x81, 0x02,		/*   INPUT (Data,Var,Abs)       */
+	0x95, 0x05,		/*   REPORT COUNT (5)           */
+	0x05, 0x08,		/*   USAGE PAGE (LED page)      */
+	0x19, 0x01,		/*   USAGE MINIMUM (1)          */
+	0x29, 0x05,		/*   USAGE MAXIMUM (5)          */
+	0x91, 0x02,		/*   OUTPUT (Data, Variable, Absolute)  */
+	0x95, 0x01,		/*   REPORT COUNT (1)           */
+	0x75, 0x03,		/*   REPORT SIZE (3)            */
+	0x91, 0x01,		/*   OUTPUT (Constant)          */
+	0x95, 0x06,		/*   REPORT_COUNT (6)           */
+	0x75, 0x08,		/*   REPORT_SIZE (8)            */
+	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
+	0x26, 0xFF, 0x00,	/*   LOGICAL_MAXIMUM (255)      */
+	0x05, 0x07,		/*   USAGE_PAGE (Keyboard)      */
+	0x19, 0x00,		/*   USAGE_MINIMUM (no event)       */
+	0x2A, 0xFF, 0x00,	/*   USAGE_MAXIMUM (reserved)       */
+	0x81, 0x00,		/*   INPUT (Data,Ary,Abs)       */
+	0xC0
+};
+
+/* Mouse descriptor (2)     */
+static const char mse_descriptor[] = {
+	0x05, 0x01,		/*  USAGE_PAGE (Generic Desktop)        */
+	0x09, 0x02,		/*  USAGE (Mouse)                       */
+	0xA1, 0x01,		/*  COLLECTION (Application)            */
+	0x85, 0x02,		/*    REPORT_ID = 2                     */
+	0x09, 0x01,		/*    USAGE (pointer)                   */
+	0xA1, 0x00,		/*    COLLECTION (physical)             */
+	0x05, 0x09,		/*      USAGE_PAGE (buttons)            */
+	0x19, 0x01,		/*      USAGE_MIN (1)                   */
+	0x29, 0x10,		/*      USAGE_MAX (16)                  */
+	0x15, 0x00,		/*      LOGICAL_MIN (0)                 */
+	0x25, 0x01,		/*      LOGICAL_MAX (1)                 */
+	0x95, 0x10,		/*      REPORT_COUNT (16)               */
+	0x75, 0x01,		/*      REPORT_SIZE (1)                 */
+	0x81, 0x02,		/*      INPUT (data var abs)            */
+	0x05, 0x01,		/*      USAGE_PAGE (generic desktop)    */
+	0x16, 0x01, 0xF8,	/*      LOGICAL_MIN (-2047)             */
+	0x26, 0xFF, 0x07,	/*      LOGICAL_MAX (2047)              */
+	0x75, 0x0C,		/*      REPORT_SIZE (12)                */
+	0x95, 0x02,		/*      REPORT_COUNT (2)                */
+	0x09, 0x30,		/*      USAGE (X)                       */
+	0x09, 0x31,		/*      USAGE (Y)                       */
+	0x81, 0x06,		/*      INPUT                           */
+	0x15, 0x81,		/*      LOGICAL_MIN (-127)              */
+	0x25, 0x7F,		/*      LOGICAL_MAX (127)               */
+	0x75, 0x08,		/*      REPORT_SIZE (8)                 */
+	0x95, 0x01,		/*      REPORT_COUNT (1)                */
+	0x09, 0x38,		/*      USAGE (wheel)                   */
+	0x81, 0x06,		/*      INPUT                           */
+	0x05, 0x0C,		/*      USAGE_PAGE(consumer)            */
+	0x0A, 0x38, 0x02,	/*      USAGE(AC Pan)                   */
+	0x95, 0x01,		/*      REPORT_COUNT (1)                */
+	0x81, 0x06,		/*      INPUT                           */
+	0xC0,			/*    END_COLLECTION                    */
+	0xC0,			/*  END_COLLECTION                      */
+};
+
+/* Consumer Control descriptor (3) */
+static const char consumer_descriptor[] = {
+	0x05, 0x0C,		/* USAGE_PAGE (Consumer Devices)       */
+	0x09, 0x01,		/* USAGE (Consumer Control)            */
+	0xA1, 0x01,		/* COLLECTION (Application)            */
+	0x85, 0x03,		/* REPORT_ID = 3                       */
+	0x75, 0x10,		/* REPORT_SIZE (16)                    */
+	0x95, 0x02,		/* REPORT_COUNT (2)                    */
+	0x15, 0x01,		/* LOGICAL_MIN (1)                     */
+	0x26, 0x8C, 0x02,	/* LOGICAL_MAX (652)                   */
+	0x19, 0x01,		/* USAGE_MIN (1)                       */
+	0x2A, 0x8C, 0x02,	/* USAGE_MAX (652)                     */
+	0x81, 0x00,		/* INPUT (Data Ary Abs)                */
+	0xC0,			/* END_COLLECTION                      */
+};				/*                                     */
+
+/* System control descriptor (4) */
+static const char syscontrol_descriptor[] = {
+	0x05, 0x01,		/*   USAGE_PAGE (Generic Desktop)      */
+	0x09, 0x80,		/*   USAGE (System Control)            */
+	0xA1, 0x01,		/*   COLLECTION (Application)          */
+	0x85, 0x04,		/*   REPORT_ID = 4                     */
+	0x75, 0x02,		/*   REPORT_SIZE (2)                   */
+	0x95, 0x01,		/*   REPORT_COUNT (1)                  */
+	0x15, 0x01,		/*   LOGICAL_MIN (1)                   */
+	0x25, 0x03,		/*   LOGICAL_MAX (3)                   */
+	0x09, 0x82,		/*   USAGE (System Sleep)              */
+	0x09, 0x81,		/*   USAGE (System Power Down)         */
+	0x09, 0x83,		/*   USAGE (System Wake Up)            */
+	0x81, 0x60,		/*   INPUT (Data Ary Abs NPrf Null)    */
+	0x75, 0x06,		/*   REPORT_SIZE (6)                   */
+	0x81, 0x03,		/*   INPUT (Cnst Var Abs)              */
+	0xC0,			/*   END_COLLECTION                    */
+};
+
+/* Media descriptor (8) */
+static const char media_descriptor[] = {
+	0x06, 0xbc, 0xff,	/* Usage Page 0xffbc                   */
+	0x09, 0x88,		/* Usage 0x0088                        */
+	0xa1, 0x01,		/* BeginCollection                     */
+	0x85, 0x08,		/*   Report ID 8                       */
+	0x19, 0x01,		/*   Usage Min 0x0001                  */
+	0x29, 0xff,		/*   Usage Max 0x00ff                  */
+	0x15, 0x01,		/*   Logical Min 1                     */
+	0x26, 0xff, 0x00,	/*   Logical Max 255                   */
+	0x75, 0x08,		/*   Report Size 8                     */
+	0x95, 0x01,		/*   Report Count 1                    */
+	0x81, 0x00,		/*   Input                             */
+	0xc0,			/* EndCollection                       */
+};				/*                                     */
+
+/* Maximum size of all defined hid reports in bytes (including report id) */
+#define MAX_REPORT_SIZE 8
+
+/* Number of possible hid report types that can be created by this driver.
+ *
+ * Right now, RF report types have the same report types (or report id's)
+ * than the hid report created from those RF reports. In the future
+ * this doesnt have to be true.
+ *
+ * For instance, RF report type 0x01 which has a size of 8 bytes, corresponds
+ * to hid report id 0x01, this is standard keyboard. Same thing applies to mice
+ * reports and consumer control, etc. If a new RF report is created, it doesn't
+ * has to have the same report id as its corresponding hid report, so an
+ * translation may have to take place for future report types.
+ */
+#define NUMBER_OF_HID_REPORTS 32
+static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
+	[1] = 8,		/* Standard keyboard */
+	[2] = 8,		/* Standard mouse */
+	[3] = 5,		/* Consumer control */
+	[4] = 2,		/* System control */
+	[8] = 2,		/* Media Center */
+};
+
+
+#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
+
+static struct hid_ll_driver logi_dj_ll_driver;
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+					size_t count,
+					unsigned char report_type);
+
+static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
+						struct dj_report *dj_report)
+{
+	/* Called in delayed work context */
+	struct dj_device *dj_dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+	dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	if (dj_dev != NULL) {
+		hid_destroy_device(dj_dev->hdev);
+		kfree(dj_dev);
+	} else {
+		dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n",
+			__func__);
+	}
+}
+
+static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
+					  struct dj_report *dj_report)
+{
+	/* Called in delayed work context */
+	struct hid_device *djrcv_hdev = djrcv_dev->hdev;
+	struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct hid_device *dj_hiddev;
+	struct dj_device *dj_dev;
+
+	/* Device index goes from 1 to 6, we need 3 bytes to store the
+	 * semicolon, the index, and a null terminator
+	 */
+	unsigned char tmpstr[3];
+
+	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
+	    SPFUNCTION_DEVICE_LIST_EMPTY) {
+		dbg_hid("%s: device list is empty\n", __func__);
+		return;
+	}
+
+	if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
+	    (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
+		dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
+			__func__, dj_report->device_index);
+		return;
+	}
+
+	dj_hiddev = hid_allocate_device();
+	if (IS_ERR(dj_hiddev)) {
+		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
+			__func__);
+		return;
+	}
+
+	dj_hiddev->ll_driver = &logi_dj_ll_driver;
+	dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;
+
+	dj_hiddev->dev.parent = &djrcv_hdev->dev;
+	dj_hiddev->bus = BUS_USB;
+	dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+	dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
+	snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
+		"Logitech Unifying Device. Wireless PID:%02x%02x",
+		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
+		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);
+
+	usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
+	snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
+	strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
+
+	dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
+
+	if (!dj_dev) {
+		dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
+			__func__);
+		goto dj_device_allocate_fail;
+	}
+
+	dj_dev->reports_supported = le32_to_cpu(
+		dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
+	dj_dev->hdev = dj_hiddev;
+	dj_dev->dj_receiver_dev = djrcv_dev;
+	dj_dev->device_index = dj_report->device_index;
+	dj_hiddev->driver_data = dj_dev;
+
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
+
+	if (hid_add_device(dj_hiddev)) {
+		dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
+			__func__);
+		goto hid_add_device_fail;
+	}
+
+	return;
+
+hid_add_device_fail:
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+	kfree(dj_dev);
+dj_device_allocate_fail:
+	hid_destroy_device(dj_hiddev);
+}
+
+static void delayedwork_callback(struct work_struct *work)
+{
+	struct dj_receiver_dev *djrcv_dev =
+		container_of(work, struct dj_receiver_dev, work);
+
+	struct dj_report dj_report;
+	unsigned long flags;
+	int count;
+
+	dbg_hid("%s\n", __func__);
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+
+	count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
+				sizeof(struct dj_report));
+
+	if (count != sizeof(struct dj_report)) {
+		dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
+			"notifications available\n", __func__);
+		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+		return;
+	}
+
+	if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
+		if (schedule_work(&djrcv_dev->work) == 0) {
+			dbg_hid("%s: did not schedule the work item, was "
+				"already queued\n", __func__);
+		}
+	}
+
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	switch (dj_report.report_type) {
+	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+		logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
+		break;
+	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
+		break;
+	default:
+		dbg_hid("%s: unexpected report type\n", __func__);
+	}
+}
+
+static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
+					   struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+
+	kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+	if (schedule_work(&djrcv_dev->work) == 0) {
+		dbg_hid("%s: did not schedule the work item, was already "
+			"queued\n", __func__);
+	}
+}
+
+static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
+					     struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+	unsigned int i;
+	u8 reportbuffer[MAX_REPORT_SIZE];
+	struct dj_device *djdev;
+
+	djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+	if (!djdev) {
+		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+			" is NULL, index %d\n", dj_report->device_index);
+		return;
+	}
+
+	memset(reportbuffer, 0, sizeof(reportbuffer));
+
+	for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
+		if (djdev->reports_supported & (1 << i)) {
+			reportbuffer[0] = i;
+			if (hid_input_report(djdev->hdev,
+					     HID_INPUT_REPORT,
+					     reportbuffer,
+					     hid_reportid_size_map[i], 1)) {
+				dbg_hid("hid_input_report error sending null "
+					"report\n");
+			}
+		}
+	}
+}
+
+static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
+					struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+	struct dj_device *dj_device;
+
+	dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+	if (dj_device == NULL) {
+		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+			" is NULL, index %d\n", dj_report->device_index);
+		return;
+	}
+
+	if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
+	    (hid_reportid_size_map[dj_report->report_type] == 0)) {
+		dbg_hid("invalid report type:%x\n", dj_report->report_type);
+		return;
+	}
+
+	if (hid_input_report(dj_device->hdev,
+			HID_INPUT_REPORT, &dj_report->report_type,
+			hid_reportid_size_map[dj_report->report_type], 1)) {
+		dbg_hid("hid_input_report error\n");
+	}
+}
+
+
+static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
+				    struct dj_report *dj_report)
+{
+	struct hid_device *hdev = djrcv_dev->hdev;
+	int sent_bytes;
+
+	if (!hdev->hid_output_raw_report) {
+		dev_err(&hdev->dev, "%s:"
+			"hid_output_raw_report is null\n", __func__);
+		return -ENODEV;
+	}
+
+	sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
+						 sizeof(struct dj_report),
+						 HID_OUTPUT_REPORT);
+
+	return (sent_bytes < 0) ? sent_bytes : 0;
+}
+
+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
+{
+	struct dj_report dj_report;
+
+	memset(&dj_report, 0, sizeof(dj_report));
+	dj_report.report_id = REPORT_ID_DJ_SHORT;
+	dj_report.device_index = 0xFF;
+	dj_report.report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
+	return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+					  unsigned timeout)
+{
+	struct dj_report dj_report;
+
+	memset(&dj_report, 0, sizeof(dj_report));
+	dj_report.report_id = REPORT_ID_DJ_SHORT;
+	dj_report.device_index = 0xFF;
+	dj_report.report_type = REPORT_TYPE_CMD_SWITCH;
+	dj_report.report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x1F;
+	dj_report.report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
+	return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+
+static int logi_dj_ll_open(struct hid_device *hid)
+{
+	dbg_hid("%s:%s\n", __func__, hid->phys);
+	return 0;
+
+}
+
+static void logi_dj_ll_close(struct hid_device *hid)
+{
+	dbg_hid("%s:%s\n", __func__, hid->phys);
+}
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+					size_t count,
+					unsigned char report_type)
+{
+	/* Called by hid raw to send data */
+	dbg_hid("%s\n", __func__);
+
+	return 0;
+}
+
+static int logi_dj_ll_parse(struct hid_device *hid)
+{
+	struct dj_device *djdev = hid->driver_data;
+	int retval;
+
+	dbg_hid("%s\n", __func__);
+
+	djdev->hdev->version = 0x0111;
+	djdev->hdev->country = 0x00;
+
+	if (djdev->reports_supported & STD_KEYBOARD) {
+		dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) kbd_descriptor,
+					  sizeof(kbd_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a kbd descriptor, hid_parse failed"
+				" error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & STD_MOUSE) {
+		dbg_hid("%s: sending a mouse descriptor, reports_supported: "
+			"%x\n", __func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) mse_descriptor,
+					  sizeof(mse_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a mouse descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & MULTIMEDIA) {
+		dbg_hid("%s: sending a multimedia report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) consumer_descriptor,
+					  sizeof(consumer_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a consumer_descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & POWER_KEYS) {
+		dbg_hid("%s: sending a power keys report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) syscontrol_descriptor,
+					  sizeof(syscontrol_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a syscontrol_descriptor, "
+				"hid_parse failed error: %d\n",
+				__func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & MEDIA_CENTER) {
+		dbg_hid("%s: sending a media center report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) media_descriptor,
+					  sizeof(media_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a media_descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & KBD_LEDS) {
+		dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+	}
+
+	return 0;
+}
+
+static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
+				  unsigned int code, int value)
+{
+	/* Sent by the input layer to handle leds and Force Feedback */
+	struct hid_device *dj_hiddev = input_get_drvdata(dev);
+	struct dj_device *dj_dev = dj_hiddev->driver_data;
+
+	struct dj_receiver_dev *djrcv_dev =
+	    dev_get_drvdata(dj_hiddev->dev.parent);
+	struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
+	struct hid_report_enum *output_report_enum;
+
+	struct hid_field *field;
+	struct hid_report *report;
+	unsigned char data[8];
+	int offset;
+
+	dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
+		__func__, dev->phys, type, code, value);
+
+	if (type != EV_LED)
+		return -1;
+
+	offset = hidinput_find_field(dj_hiddev, type, code, &field);
+
+	if (offset == -1) {
+		dev_warn(&dev->dev, "event field not found\n");
+		return -1;
+	}
+	hid_set_field(field, offset, value);
+	hid_output_report(field->report, &data[0]);
+
+	output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
+	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+	hid_set_field(report->field[0], 0, dj_dev->device_index);
+	hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
+	hid_set_field(report->field[0], 2, data[1]);
+
+	usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
+
+	return 0;
+
+}
+
+static int logi_dj_ll_start(struct hid_device *hid)
+{
+	dbg_hid("%s\n", __func__);
+	return 0;
+}
+
+static void logi_dj_ll_stop(struct hid_device *hid)
+{
+	dbg_hid("%s\n", __func__);
+}
+
+
+static struct hid_ll_driver logi_dj_ll_driver = {
+	.parse = logi_dj_ll_parse,
+	.start = logi_dj_ll_start,
+	.stop = logi_dj_ll_stop,
+	.open = logi_dj_ll_open,
+	.close = logi_dj_ll_close,
+	.hidinput_input_event = logi_dj_ll_input_event,
+};
+
+
+static int logi_dj_raw_event(struct hid_device *hdev,
+			     struct hid_report *report, u8 *data,
+			     int size)
+{
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+	struct dj_report *dj_report = (struct dj_report *) data;
+	unsigned long flags;
+	bool report_processed = false;
+
+	dbg_hid("%s, size:%d\n", __func__, size);
+
+	/* Here we receive all data coming from iface 2, there are 4 cases:
+	 *
+	 * 1) Data should continue its normal processing i.e. data does not
+	 * come from the DJ collection, in which case we do nothing and
+	 * return 0, so hid-core can continue normal processing (will forward
+	 * to associated hidraw device)
+	 *
+	 * 2) Data is from DJ collection, and is intended for this driver i. e.
+	 * data contains arrival, departure, etc notifications, in which case
+	 * we queue them for delayed processing by the work queue. We return 1
+	 * to hid-core as no further processing is required from it.
+	 *
+	 * 3) Data is from DJ collection, and informs a connection change,
+	 * if the change means rf link loss, then we must send a null report
+	 * to the upper layer to discard potentially pressed keys that may be
+	 * repeated forever by the input layer. Return 1 to hid-core as no
+	 * further processing is required.
+	 *
+	 * 4) Data is from DJ collection and is an actual input event from
+	 * a paired DJ device in which case we forward it to the correct hid
+	 * device (via hid_input_report() ) and return 1 so hid-core does not do
+	 * anything else with it.
+	 */
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+	if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
+		switch (dj_report->report_type) {
+		case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+		case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+			logi_dj_recv_queue_notification(djrcv_dev, dj_report);
+			break;
+		case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+			if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
+			    STATUS_LINKLOSS) {
+				logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
+			}
+			break;
+		default:
+			logi_dj_recv_forward_report(djrcv_dev, dj_report);
+		}
+		report_processed = true;
+	}
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	return report_processed;
+}
+
+static int logi_dj_probe(struct hid_device *hdev,
+			 const struct hid_device_id *id)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct dj_receiver_dev *djrcv_dev;
+	int retval;
+
+	if (is_dj_device((struct dj_device *)hdev->driver_data))
+		return -ENODEV;
+
+	dbg_hid("%s called for ifnum %d\n", __func__,
+		intf->cur_altsetting->desc.bInterfaceNumber);
+
+	/* Ignore interfaces 0 and 1, they will not carry any data, dont create
+	 * any hid_device for them */
+	if (intf->cur_altsetting->desc.bInterfaceNumber !=
+	    LOGITECH_DJ_INTERFACE_NUMBER) {
+		dbg_hid("%s: ignoring ifnum %d\n", __func__,
+			intf->cur_altsetting->desc.bInterfaceNumber);
+		return -ENODEV;
+	}
+
+	/* Treat interface 2 */
+
+	djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
+	if (!djrcv_dev) {
+		dev_err(&hdev->dev,
+			"%s:failed allocating dj_receiver_dev\n", __func__);
+		return -ENOMEM;
+	}
+	djrcv_dev->hdev = hdev;
+	INIT_WORK(&djrcv_dev->work, delayedwork_callback);
+	spin_lock_init(&djrcv_dev->lock);
+	if (kfifo_alloc(&djrcv_dev->notif_fifo,
+			DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
+			GFP_KERNEL)) {
+		dev_err(&hdev->dev,
+			"%s:failed allocating notif_fifo\n", __func__);
+		kfree(djrcv_dev);
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, djrcv_dev);
+
+	/* Call  to usbhid to fetch the HID descriptors of interface 2 and
+	 * subsequently call to the hid/hid-core to parse the fetched
+	 * descriptors, this will in turn create the hidraw and hiddev nodes
+	 * for interface 2 of the receiver */
+	retval = hid_parse(hdev);
+	if (retval) {
+		dev_err(&hdev->dev,
+			"%s:parse of interface 2 failed\n", __func__);
+		goto hid_parse_fail;
+	}
+
+	/* Starts the usb device and connects to upper interfaces hiddev and
+	 * hidraw */
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		dev_err(&hdev->dev,
+			"%s:hid_hw_start returned error\n", __func__);
+		goto hid_hw_start_fail;
+	}
+
+	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+	if (retval < 0) {
+		dev_err(&hdev->dev,
+			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+			__func__, retval);
+		goto switch_to_dj_mode_fail;
+	}
+
+	/* This is enabling the polling urb on the IN endpoint */
+	retval = hdev->ll_driver->open(hdev);
+	if (retval < 0) {
+		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
+			"error:%d\n", __func__, retval);
+		goto llopen_failed;
+	}
+
+	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+	if (retval < 0) {
+		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
+			"error:%d\n", __func__, retval);
+		goto logi_dj_recv_query_paired_devices_failed;
+	}
+
+	return retval;
+
+logi_dj_recv_query_paired_devices_failed:
+	hdev->ll_driver->close(hdev);
+
+llopen_failed:
+switch_to_dj_mode_fail:
+	hid_hw_stop(hdev);
+
+hid_hw_start_fail:
+hid_parse_fail:
+	kfifo_free(&djrcv_dev->notif_fifo);
+	kfree(djrcv_dev);
+	hid_set_drvdata(hdev, NULL);
+	return retval;
+
+}
+
+#ifdef CONFIG_PM
+static int logi_dj_reset_resume(struct hid_device *hdev)
+{
+	int retval;
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+
+	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+	if (retval < 0) {
+		dev_err(&hdev->dev,
+			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+			__func__, retval);
+	}
+
+	return 0;
+}
+#endif
+
+static void logi_dj_remove(struct hid_device *hdev)
+{
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+	struct dj_device *dj_dev;
+	int i;
+
+	dbg_hid("%s\n", __func__);
+
+	cancel_work_sync(&djrcv_dev->work);
+
+	hdev->ll_driver->close(hdev);
+	hid_hw_stop(hdev);
+
+	/* I suppose that at this point the only context that can access
+	 * the djrecv_data is this thread as the work item is guaranteed to
+	 * have finished and no more raw_event callbacks should arrive after
+	 * the remove callback was triggered so no locks are put around the
+	 * code below */
+	for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
+		dj_dev = djrcv_dev->paired_dj_devices[i];
+		if (dj_dev != NULL) {
+			hid_destroy_device(dj_dev->hdev);
+			kfree(dj_dev);
+			djrcv_dev->paired_dj_devices[i] = NULL;
+		}
+	}
+
+	kfifo_free(&djrcv_dev->notif_fifo);
+	kfree(djrcv_dev);
+	hid_set_drvdata(hdev, NULL);
+}
+
+static int logi_djdevice_probe(struct hid_device *hdev,
+			 const struct hid_device_id *id)
+{
+	int ret;
+	struct dj_device *dj_dev = hdev->driver_data;
+
+	if (!is_dj_device(dj_dev))
+		return -ENODEV;
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	return ret;
+}
+
+static const struct hid_device_id logi_dj_receivers[] = {
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
+
+static struct hid_driver logi_djreceiver_driver = {
+	.name = "logitech-djreceiver",
+	.id_table = logi_dj_receivers,
+	.probe = logi_dj_probe,
+	.remove = logi_dj_remove,
+	.raw_event = logi_dj_raw_event,
+#ifdef CONFIG_PM
+	.reset_resume = logi_dj_reset_resume,
+#endif
+};
+
+
+static const struct hid_device_id logi_dj_devices[] = {
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+	{}
+};
+
+static struct hid_driver logi_djdevice_driver = {
+	.name = "logitech-djdevice",
+	.id_table = logi_dj_devices,
+	.probe = logi_djdevice_probe,
+};
+
+
+static int __init logi_dj_init(void)
+{
+	int retval;
+
+	dbg_hid("Logitech-DJ:%s\n", __func__);
+
+	retval = hid_register_driver(&logi_djreceiver_driver);
+	if (retval)
+		return retval;
+
+	retval = hid_register_driver(&logi_djdevice_driver);
+	if (retval)
+		hid_unregister_driver(&logi_djreceiver_driver);
+
+	return retval;
+
+}
+
+static void __exit logi_dj_exit(void)
+{
+	dbg_hid("Logitech-DJ:%s\n", __func__);
+
+	hid_unregister_driver(&logi_djdevice_driver);
+	hid_unregister_driver(&logi_djreceiver_driver);
+
+}
+
+module_init(logi_dj_init);
+module_exit(logi_dj_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Logitech");
+MODULE_AUTHOR("Nestor Lopez Casado");
+MODULE_AUTHOR("nlopezcasad@logitech.com");
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-logitech-dj.h linux-libre-3.2-gnu1/drivers/hid/hid-logitech-dj.h
--- linux-libre-3.1-gnu1/drivers/hid/hid-logitech-dj.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hid/hid-logitech-dj.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+#ifndef __HID_LOGITECH_DJ_H
+#define __HID_LOGITECH_DJ_H
+
+/*
+ *  HID driver for Logitech Unifying receivers
+ *
+ *  Copyright (c) 2011 Logitech
+ */
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kfifo.h>
+
+#define DJ_MAX_PAIRED_DEVICES			6
+#define DJ_MAX_NUMBER_NOTIFICATIONS		8
+#define DJ_DEVICE_INDEX_MIN 			1
+#define DJ_DEVICE_INDEX_MAX 			6
+
+#define DJREPORT_SHORT_LENGTH			15
+#define DJREPORT_LONG_LENGTH			32
+
+#define REPORT_ID_DJ_SHORT			0x20
+#define REPORT_ID_DJ_LONG			0x21
+
+#define REPORT_TYPE_RFREPORT_FIRST		0x01
+#define REPORT_TYPE_RFREPORT_LAST		0x1F
+
+/* Command Switch to DJ mode */
+#define REPORT_TYPE_CMD_SWITCH			0x80
+#define CMD_SWITCH_PARAM_DEVBITFIELD		0x00
+#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS	0x01
+#define TIMEOUT_NO_KEEPALIVE			0x00
+
+/* Command to Get the list of Paired devices */
+#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES	0x81
+
+/* Device Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_PAIRED		0x41
+#define SPFUNCTION_MORE_NOTIF_EXPECTED		0x01
+#define SPFUNCTION_DEVICE_LIST_EMPTY		0x02
+#define DEVICE_PAIRED_PARAM_SPFUNCTION		0x00
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB	0x01
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB	0x02
+#define DEVICE_PAIRED_RF_REPORT_TYPE		0x03
+
+/* Device Un-Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED	0x40
+
+
+/* Connection Status Notification */
+#define REPORT_TYPE_NOTIF_CONNECTION_STATUS	0x42
+#define CONNECTION_STATUS_PARAM_STATUS		0x00
+#define STATUS_LINKLOSS				0x01
+
+/* Error Notification */
+#define REPORT_TYPE_NOTIF_ERROR			0x7F
+#define NOTIF_ERROR_PARAM_ETYPE			0x00
+#define ETYPE_KEEPALIVE_TIMEOUT			0x01
+
+/* supported DJ HID && RF report types */
+#define REPORT_TYPE_KEYBOARD			0x01
+#define REPORT_TYPE_MOUSE			0x02
+#define REPORT_TYPE_CONSUMER_CONTROL		0x03
+#define REPORT_TYPE_SYSTEM_CONTROL		0x04
+#define REPORT_TYPE_MEDIA_CENTER		0x08
+#define REPORT_TYPE_LEDS			0x0E
+
+/* RF Report types bitfield */
+#define STD_KEYBOARD				0x00000002
+#define STD_MOUSE				0x00000004
+#define MULTIMEDIA				0x00000008
+#define POWER_KEYS				0x00000010
+#define MEDIA_CENTER				0x00000100
+#define KBD_LEDS				0x00004000
+
+struct dj_report {
+	u8 report_id;
+	u8 device_index;
+	u8 report_type;
+	u8 report_params[DJREPORT_SHORT_LENGTH - 3];
+};
+
+struct dj_receiver_dev {
+	struct hid_device *hdev;
+	struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
+					    DJ_DEVICE_INDEX_MIN];
+	struct work_struct work;
+	struct kfifo notif_fifo;
+	spinlock_t lock;
+};
+
+struct dj_device {
+	struct hid_device *hdev;
+	struct dj_receiver_dev *dj_receiver_dev;
+	u32 reports_supported;
+	u8 device_index;
+};
+
+/**
+ * is_dj_device - know if the given dj_device is not the receiver.
+ * @dj_dev: the dj device to test
+ *
+ * This macro tests if a struct dj_device pointer is a device created
+ * by the bus enumarator.
+ */
+#define is_dj_device(dj_dev) \
+	(&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-magicmouse.c linux-libre-3.2-gnu1/drivers/hid/hid-magicmouse.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-magicmouse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-magicmouse.c	2012-01-04 18:55:44.000000000 -0500
@@ -405,6 +405,13 @@ static void magicmouse_setup_input(struc
 			__set_bit(REL_HWHEEL, input->relbit);
 		}
 	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		/* input->keybit is initialized with incorrect button info
+		 * for Magic Trackpad. There really is only one physical
+		 * button (BTN_LEFT == BTN_MOUSE). Make sure we don't
+		 * advertise buttons that don't exist...
+		 */
+		__clear_bit(BTN_RIGHT, input->keybit);
+		__clear_bit(BTN_MIDDLE, input->keybit);
 		__set_bit(BTN_MOUSE, input->keybit);
 		__set_bit(BTN_TOOL_FINGER, input->keybit);
 		__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-multitouch.c linux-libre-3.2-gnu1/drivers/hid/hid-multitouch.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-multitouch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-multitouch.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,10 +47,11 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_SLOT_IS_CONTACTID	(1 << 1)
 #define MT_QUIRK_CYPRESS		(1 << 2)
 #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3)
-#define MT_QUIRK_VALID_IS_INRANGE	(1 << 4)
-#define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 5)
-#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 6)
-#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 7)
+#define MT_QUIRK_ALWAYS_VALID		(1 << 4)
+#define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
+#define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
+#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 7)
+#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
 
 struct mt_slot {
 	__s32 x, y, p, w, h;
@@ -86,11 +87,12 @@ struct mt_class {
 /* classes of device behavior */
 #define MT_CLS_DEFAULT				0x0001
 
-#define MT_CLS_CONFIDENCE			0x0002
-#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0003
-#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0004
-#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0005
-#define MT_CLS_DUAL_NSMU_CONTACTID		0x0006
+#define MT_CLS_SERIAL				0x0002
+#define MT_CLS_CONFIDENCE			0x0003
+#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0004
+#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0005
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0006
+#define MT_CLS_DUAL_NSMU_CONTACTID		0x0007
 
 /* vendor specific classes */
 #define MT_CLS_3M				0x0101
@@ -134,6 +136,8 @@ static int find_slot_from_contactid(stru
 struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
+	{ .name = MT_CLS_SERIAL,
+		.quirks = MT_QUIRK_ALWAYS_VALID},
 	{ .name = MT_CLS_CONFIDENCE,
 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
 	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
@@ -213,6 +217,16 @@ static int mt_input_mapping(struct hid_d
 	struct mt_class *cls = td->mtclass;
 	__s32 quirks = cls->quirks;
 
+	/* Only map fields from TouchScreen or TouchPad collections.
+         * We need to ignore fields that belong to other collections
+         * such as Mouse that might have the same GenericDesktop usages. */
+	if (field->application == HID_DG_TOUCHSCREEN)
+		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+	else if (field->application == HID_DG_TOUCHPAD)
+		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
+	else
+		return 0;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
@@ -435,7 +449,9 @@ static int mt_event(struct hid_device *h
 	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
-			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+			if (quirks & MT_QUIRK_ALWAYS_VALID)
+				td->curvalid = true;
+			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
 				td->curvalid = value;
 			break;
 		case HID_DG_TIPSWITCH:
@@ -662,6 +678,11 @@ static const struct hid_device_id mt_dev
 		HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
 			USB_DEVICE_ID_GOODTOUCH_000f) },
 
+	/* Ideacom panel */
+	{ .driver_data = MT_CLS_SERIAL,
+		HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
+			USB_DEVICE_ID_IDEACOM_IDC6650) },
+
 	/* Ilitek dual touch panel */
 	{  .driver_data = MT_CLS_DEFAULT,
 		HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
@@ -672,6 +693,11 @@ static const struct hid_device_id mt_dev
 		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
 			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 
+	/* LG Display panels */
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_LG,
+			USB_DEVICE_ID_LG_MULTITOUCH) },
+
 	/* Lumio panels */
 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
 		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-picolcd.c linux-libre-3.2-gnu1/drivers/hid/hid-picolcd.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-picolcd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-picolcd.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include <linux/completion.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 
 #define PICOLCD_NAME "PicoLCD (graphic)"
 
@@ -2409,7 +2410,7 @@ static int picolcd_raw_event(struct hid_
 #ifdef CONFIG_PM
 static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
 {
-	if (message.event & PM_EVENT_AUTO)
+	if (PMSG_IS_AUTO(message))
 		return 0;
 
 	picolcd_suspend_backlight(hid_get_drvdata(hdev));
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-pl.c linux-libre-3.2-gnu1/drivers/hid/hid-pl.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-pl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-pl.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-primax.c linux-libre-3.2-gnu1/drivers/hid/hid-primax.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-primax.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hid/hid-primax.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/*
+ * HID driver for primax and similar keyboards with in-band modifiers
+ *
+ * Copyright 2011 Google Inc. All Rights Reserved
+ *
+ * Author:
+ *	Terry Lambert <tlambert@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+	 u8 *data, int size)
+{
+	int idx = size;
+
+	switch (report->id) {
+	case 0:		/* keyboard input */
+		/*
+		 * Convert in-band modifier key values into out of band
+		 * modifier bits and pull the key strokes from the report.
+		 * Thus a report data set which looked like:
+		 *
+		 * [00][00][E0][30][00][00][00][00]
+		 * (no modifier bits + "Left Shift" key + "1" key)
+		 *
+		 * Would be converted to:
+		 *
+		 * [01][00][00][30][00][00][00][00]
+		 * (Left Shift modifier bit + "1" key)
+		 *
+		 * As long as it's in the size range, the upper level
+		 * drivers don't particularly care if there are in-band
+		 * 0-valued keys, so they don't stop parsing.
+		 */
+		while (--idx > 1) {
+			if (data[idx] < 0xE0 || data[idx] > 0xE7)
+				continue;
+			data[0] |= (1 << (data[idx] - 0xE0));
+			data[idx] = 0;
+		}
+		hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
+		return 1;
+
+	default:	/* unknown report */
+		/* Unknown report type; pass upstream */
+		hid_info(hid, "unknown report type %d\n", report->id);
+		break;
+	}
+
+	return 0;
+}
+
+static int px_probe(struct hid_device *hid, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hid);
+	if (ret) {
+		hid_err(hid, "parse failed\n");
+		goto fail;
+	}
+
+	ret = hid_hw_start(hid, HID_CONNECT_DEFAULT);
+	if (ret)
+		hid_err(hid, "hw start failed\n");
+
+fail:
+	return ret;
+}
+
+static void px_remove(struct hid_device *hid)
+{
+	hid_hw_stop(hid);
+}
+
+static const struct hid_device_id px_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, px_devices);
+
+static struct hid_driver px_driver = {
+	.name = "primax",
+	.id_table = px_devices,
+	.raw_event = px_raw_event,
+	.probe = px_probe,
+	.remove = px_remove,
+};
+
+static int __init px_init(void)
+{
+	return hid_register_driver(&px_driver);
+}
+
+static void __exit px_exit(void)
+{
+	hid_unregister_driver(&px_driver);
+}
+
+module_init(px_init);
+module_exit(px_exit);
+MODULE_AUTHOR("Terry Lambert <tlambert@google.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-prodikeys.c linux-libre-3.2-gnu1/drivers/hid/hid-prodikeys.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-prodikeys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-prodikeys.c	2012-01-04 18:55:44.000000000 -0500
@@ -816,7 +816,7 @@ static int pk_probe(struct hid_device *h
 	if (pm == NULL) {
 		hid_err(hdev, "can't alloc descriptor\n");
 		ret = -ENOMEM;
-		goto err_free;
+		goto err_free_pk;
 	}
 
 	pm->pk = pk;
@@ -849,10 +849,10 @@ static int pk_probe(struct hid_device *h
 err_stop:
 	hid_hw_stop(hdev);
 err_free:
-	if (pm != NULL)
-		kfree(pm);
-
+	kfree(pm);
+err_free_pk:
 	kfree(pk);
+
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hidraw.c linux-libre-3.2-gnu1/drivers/hid/hidraw.c
--- linux-libre-3.1-gnu1/drivers/hid/hidraw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hidraw.c	2012-01-04 18:55:44.000000000 -0500
@@ -259,7 +259,6 @@ static int hidraw_open(struct inode *ino
 
 	mutex_lock(&minors_lock);
 	if (!hidraw_table[minor]) {
-		kfree(list);
 		err = -ENODEV;
 		goto out_unlock;
 	}
@@ -272,8 +271,10 @@ static int hidraw_open(struct inode *ino
 	dev = hidraw_table[minor];
 	if (!dev->open++) {
 		err = hid_hw_power(dev->hid, PM_HINT_FULLON);
-		if (err < 0)
+		if (err < 0) {
+			dev->open--;
 			goto out_unlock;
+		}
 
 		err = hid_hw_open(dev->hid);
 		if (err < 0) {
@@ -285,6 +286,8 @@ static int hidraw_open(struct inode *ino
 out_unlock:
 	mutex_unlock(&minors_lock);
 out:
+	if (err < 0)
+		kfree(list);
 	return err;
 
 }
@@ -510,13 +513,12 @@ void hidraw_disconnect(struct hid_device
 {
 	struct hidraw *hidraw = hid->hidraw;
 
+	mutex_lock(&minors_lock);
 	hidraw->exist = 0;
 
 	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
-	mutex_lock(&minors_lock);
 	hidraw_table[hidraw->minor] = NULL;
-	mutex_unlock(&minors_lock);
 
 	if (hidraw->open) {
 		hid_hw_close(hid);
@@ -524,6 +526,7 @@ void hidraw_disconnect(struct hid_device
 	} else {
 		kfree(hidraw);
 	}
+	mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-roccat.c linux-libre-3.2-gnu1/drivers/hid/hid-roccat.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-roccat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-roccat.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/hid-roccat.h>
+#include <linux/module.h>
 
 #define ROCCAT_FIRST_MINOR 0
 #define ROCCAT_MAX_DEVICES 8
@@ -162,27 +163,27 @@ static int roccat_open(struct inode *ino
 
 	device = devices[minor];
 
-	mutex_lock(&device->readers_lock);
-
 	if (!device) {
 		pr_emerg("roccat device with minor %d doesn't exist\n", minor);
 		error = -ENODEV;
-		goto exit_err;
+		goto exit_err_devices;
 	}
 
+	mutex_lock(&device->readers_lock);
+
 	if (!device->open++) {
 		/* power on device on adding first reader */
 		error = hid_hw_power(device->hid, PM_HINT_FULLON);
 		if (error < 0) {
 			--device->open;
-			goto exit_err;
+			goto exit_err_readers;
 		}
 
 		error = hid_hw_open(device->hid);
 		if (error < 0) {
 			hid_hw_power(device->hid, PM_HINT_NORMAL);
 			--device->open;
-			goto exit_err;
+			goto exit_err_readers;
 		}
 	}
 
@@ -193,13 +194,13 @@ static int roccat_open(struct inode *ino
 	list_add_tail(&reader->node, &device->readers);
 	file->private_data = reader;
 
-exit_unlock:
+exit_err_readers:
 	mutex_unlock(&device->readers_lock);
+exit_err_devices:
 	mutex_unlock(&devices_lock);
+	if (error)
+		kfree(reader);
 	return error;
-exit_err:
-	kfree(reader);
-	goto exit_unlock;
 }
 
 static int roccat_release(struct inode *inode, struct file *file)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-roccat-common.c linux-libre-3.2-gnu1/drivers/hid/hid-roccat-common.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-roccat-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-roccat-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/hid.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "hid-roccat-common.h"
 
 static inline uint16_t roccat_common_feature_report(uint8_t report_id)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-roccat-kone.c linux-libre-3.2-gnu1/drivers/hid/hid-roccat-kone.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-roccat-kone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-roccat-kone.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,21 @@
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
 
+static void kone_profile_activated(struct kone_device *kone, uint new_profile)
+{
+	kone->actual_profile = new_profile;
+	kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi;
+}
+
+static void kone_profile_report(struct kone_device *kone, uint new_profile)
+{
+	struct kone_roccat_report roccat_report;
+	roccat_report.event = kone_mouse_event_switch_profile;
+	roccat_report.value = new_profile;
+	roccat_report.key = 0;
+	roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report);
+}
+
 static int kone_receive(struct usb_device *usb_dev, uint usb_command,
 		void *data, uint size)
 {
@@ -283,7 +298,7 @@ static ssize_t kone_sysfs_write_settings
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0, difference;
+	int retval = 0, difference, old_profile;
 
 	/* I need to get my data in one piece */
 	if (off != 0 || count != sizeof(struct kone_settings))
@@ -294,21 +309,20 @@ static ssize_t kone_sysfs_write_settings
 	if (difference) {
 		retval = kone_set_settings(usb_dev,
 				(struct kone_settings const *)buf);
-		if (!retval)
-			memcpy(&kone->settings, buf,
-					sizeof(struct kone_settings));
-	}
-	mutex_unlock(&kone->kone_lock);
+		if (retval) {
+			mutex_unlock(&kone->kone_lock);
+			return retval;
+		}
 
-	if (retval)
-		return retval;
+		old_profile = kone->settings.startup_profile;
+		memcpy(&kone->settings, buf, sizeof(struct kone_settings));
 
-	/*
-	 * If we get here, treat settings as okay and update actual values
-	 * according to startup_profile
-	 */
-	kone->actual_profile = kone->settings.startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+		kone_profile_activated(kone, kone->settings.startup_profile);
+
+		if (kone->settings.startup_profile != old_profile)
+			kone_profile_report(kone, kone->settings.startup_profile);
+	}
+	mutex_unlock(&kone->kone_lock);
 
 	return sizeof(struct kone_settings);
 }
@@ -501,6 +515,8 @@ static ssize_t kone_sysfs_set_tcu(struct
 				goto exit_no_settings;
 			goto exit_unlock;
 		}
+		/* calibration resets profile */
+		kone_profile_activated(kone, kone->settings.startup_profile);
 	}
 
 	retval = size;
@@ -544,16 +560,16 @@ static ssize_t kone_sysfs_set_startup_pr
 	kone_set_settings_checksum(&kone->settings);
 
 	retval = kone_set_settings(usb_dev, &kone->settings);
-
-	mutex_unlock(&kone->kone_lock);
-
-	if (retval)
+	if (retval) {
+		mutex_unlock(&kone->kone_lock);
 		return retval;
+	}
 
 	/* changing the startup profile immediately activates this profile */
-	kone->actual_profile = new_startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+	kone_profile_activated(kone, new_startup_profile);
+	kone_profile_report(kone, new_startup_profile);
 
+	mutex_unlock(&kone->kone_lock);
 	return size;
 }
 
@@ -665,8 +681,7 @@ static int kone_init_kone_device_struct(
 	if (retval)
 		return retval;
 
-	kone->actual_profile = kone->settings.startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
+	kone_profile_activated(kone, kone->settings.startup_profile);
 
 	return 0;
 }
@@ -776,10 +791,10 @@ static void kone_keep_values_up_to_date(
 {
 	switch (event->event) {
 	case kone_mouse_event_switch_profile:
+		kone->actual_dpi = kone->profiles[event->value - 1].
+				startup_dpi;
 	case kone_mouse_event_osd_profile:
 		kone->actual_profile = event->value;
-		kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
-				startup_dpi;
 		break;
 	case kone_mouse_event_switch_dpi:
 	case kone_mouse_event_osd_dpi:
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-roccat-kovaplus.c linux-libre-3.2-gnu1/drivers/hid/hid-roccat-kovaplus.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-roccat-kovaplus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-roccat-kovaplus.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,6 +323,7 @@ static ssize_t kovaplus_sysfs_set_actual
 	struct usb_device *usb_dev;
 	unsigned long profile;
 	int retval;
+	struct kovaplus_roccat_report roccat_report;
 
 	dev = dev->parent->parent;
 	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
@@ -337,10 +338,22 @@ static ssize_t kovaplus_sysfs_set_actual
 
 	mutex_lock(&kovaplus->kovaplus_lock);
 	retval = kovaplus_set_actual_profile(usb_dev, profile);
+	if (retval) {
+		mutex_unlock(&kovaplus->kovaplus_lock);
+		return retval;
+	}
+
 	kovaplus_profile_activated(kovaplus, profile);
+
+	roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1;
+	roccat_report.profile = profile + 1;
+	roccat_report.button = 0;
+	roccat_report.data1 = profile + 1;
+	roccat_report.data2 = 0;
+	roccat_report_event(kovaplus->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+
 	mutex_unlock(&kovaplus->kovaplus_lock);
-	if (retval)
-		return retval;
 
 	return size;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-roccat-pyra.c linux-libre-3.2-gnu1/drivers/hid/hid-roccat-pyra.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-roccat-pyra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-roccat-pyra.c	2012-01-04 18:55:44.000000000 -0500
@@ -298,6 +298,7 @@ static ssize_t pyra_sysfs_write_settings
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
 	int difference;
+	struct pyra_roccat_report roccat_report;
 
 	if (off != 0 || count != sizeof(struct pyra_settings))
 		return -EINVAL;
@@ -307,17 +308,23 @@ static ssize_t pyra_sysfs_write_settings
 	if (difference) {
 		retval = pyra_set_settings(usb_dev,
 				(struct pyra_settings const *)buf);
-		if (!retval)
-			memcpy(&pyra->settings, buf,
-					sizeof(struct pyra_settings));
-	}
-	mutex_unlock(&pyra->pyra_lock);
+		if (retval) {
+			mutex_unlock(&pyra->pyra_lock);
+			return retval;
+		}
 
-	if (retval)
-		return retval;
+		memcpy(&pyra->settings, buf,
+				sizeof(struct pyra_settings));
 
-	profile_activated(pyra, pyra->settings.startup_profile);
+		profile_activated(pyra, pyra->settings.startup_profile);
 
+		roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
+		roccat_report.value = pyra->settings.startup_profile + 1;
+		roccat_report.key = 0;
+		roccat_report_event(pyra->chrdev_minor,
+				(uint8_t const *)&roccat_report);
+	}
+	mutex_unlock(&pyra->pyra_lock);
 	return sizeof(struct pyra_settings);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-sjoy.c linux-libre-3.2-gnu1/drivers/hid/hid-sjoy.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-sjoy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-sjoy.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_SMARTJOYPLUS_FF
@@ -65,8 +66,7 @@ static int sjoyff_init(struct hid_device
 {
 	struct sjoyff_device *sjoyff;
 	struct hid_report *report;
-	struct hid_input *hidinput = list_entry(hid->inputs.next,
-						struct hid_input, list);
+	struct hid_input *hidinput;
 	struct list_head *report_list =
 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct list_head *report_ptr = report_list;
@@ -78,43 +78,45 @@ static int sjoyff_init(struct hid_device
 		return -ENODEV;
 	}
 
-	report_ptr = report_ptr->next;
+	list_for_each_entry(hidinput, &hid->inputs, list) {
+		report_ptr = report_ptr->next;
 
-	if (report_ptr == report_list) {
-		hid_err(hid, "required output report is missing\n");
-		return -ENODEV;
-	}
+		if (report_ptr == report_list) {
+			hid_err(hid, "required output report is missing\n");
+			return -ENODEV;
+		}
 
-	report = list_entry(report_ptr, struct hid_report, list);
-	if (report->maxfield < 1) {
-		hid_err(hid, "no fields in the report\n");
-		return -ENODEV;
-	}
+		report = list_entry(report_ptr, struct hid_report, list);
+		if (report->maxfield < 1) {
+			hid_err(hid, "no fields in the report\n");
+			return -ENODEV;
+		}
 
-	if (report->field[0]->report_count < 3) {
-		hid_err(hid, "not enough values in the field\n");
-		return -ENODEV;
-	}
+		if (report->field[0]->report_count < 3) {
+			hid_err(hid, "not enough values in the field\n");
+			return -ENODEV;
+		}
 
-	sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
-	if (!sjoyff)
-		return -ENOMEM;
+		sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
+		if (!sjoyff)
+			return -ENOMEM;
 
-	dev = hidinput->input;
+		dev = hidinput->input;
 
-	set_bit(FF_RUMBLE, dev->ffbit);
+		set_bit(FF_RUMBLE, dev->ffbit);
 
-	error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
-	if (error) {
-		kfree(sjoyff);
-		return error;
-	}
+		error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+		if (error) {
+			kfree(sjoyff);
+			return error;
+		}
 
-	sjoyff->report = report;
-	sjoyff->report->field[0]->value[0] = 0x01;
-	sjoyff->report->field[0]->value[1] = 0x00;
-	sjoyff->report->field[0]->value[2] = 0x00;
-	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+		sjoyff->report = report;
+		sjoyff->report->field[0]->value[0] = 0x01;
+		sjoyff->report->field[0]->value[1] = 0x00;
+		sjoyff->report->field[0]->value[2] = 0x00;
+		usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+	}
 
 	hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
 
@@ -131,6 +133,8 @@ static int sjoy_probe(struct hid_device
 {
 	int ret;
 
+	hdev->quirks |= id->driver_data;
+
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
@@ -151,7 +155,17 @@ err:
 }
 
 static const struct hid_device_id sjoy_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, sjoy_devices);
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-tmff.c linux-libre-3.2-gnu1/drivers/hid/hid-tmff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-tmff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-tmff.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-wacom.c linux-libre-3.2-gnu1/drivers/hid/hid-wacom.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-wacom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-wacom.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_de
 	return 1;
 }
 
+static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+	struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
+								int *max)
+{
+	struct input_dev *input = hi->input;
+
+	__set_bit(INPUT_PROP_POINTER, input->propbit);
+
+	/* Basics */
+	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+
+	__set_bit(REL_WHEEL, input->relbit);
+
+	__set_bit(BTN_TOOL_PEN, input->keybit);
+	__set_bit(BTN_TOUCH, input->keybit);
+	__set_bit(BTN_STYLUS, input->keybit);
+	__set_bit(BTN_STYLUS2, input->keybit);
+	__set_bit(BTN_LEFT, input->keybit);
+	__set_bit(BTN_RIGHT, input->keybit);
+	__set_bit(BTN_MIDDLE, input->keybit);
+
+	/* Pad */
+	input->evbit[0] |= BIT(EV_MSC);
+
+	__set_bit(MSC_SERIAL, input->mscbit);
+
+	__set_bit(BTN_0, input->keybit);
+	__set_bit(BTN_1, input->keybit);
+	__set_bit(BTN_TOOL_FINGER, input->keybit);
+
+	/* Distance, rubber and mouse */
+	__set_bit(BTN_TOOL_RUBBER, input->keybit);
+	__set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+	input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
+	input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
+	input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
+	input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
+
+	return 0;
+}
+
 static int wacom_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
-	struct hid_input *hidinput;
-	struct input_dev *input;
 	struct wacom_data *wdata;
 	int ret;
 
@@ -370,42 +410,6 @@ static int wacom_probe(struct hid_device
 		goto err_ac;
 	}
 #endif
-	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
-	input = hidinput->input;
-
-	__set_bit(INPUT_PROP_POINTER, input->propbit);
-
-	/* Basics */
-	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
-	__set_bit(REL_WHEEL, input->relbit);
-
-	__set_bit(BTN_TOOL_PEN, input->keybit);
-	__set_bit(BTN_TOUCH, input->keybit);
-	__set_bit(BTN_STYLUS, input->keybit);
-	__set_bit(BTN_STYLUS2, input->keybit);
-	__set_bit(BTN_LEFT, input->keybit);
-	__set_bit(BTN_RIGHT, input->keybit);
-	__set_bit(BTN_MIDDLE, input->keybit);
-
-	/* Pad */
-	input->evbit[0] |= BIT(EV_MSC);
-
-	__set_bit(MSC_SERIAL, input->mscbit);
-
-	__set_bit(BTN_0, input->keybit);
-	__set_bit(BTN_1, input->keybit);
-	__set_bit(BTN_TOOL_FINGER, input->keybit);
-
-	/* Distance, rubber and mouse */
-	__set_bit(BTN_TOOL_RUBBER, input->keybit);
-	__set_bit(BTN_TOOL_MOUSE, input->keybit);
-
-	input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
-	input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
-	input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
-	input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
-
 	return 0;
 
 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
@@ -448,6 +452,7 @@ static struct hid_driver wacom_driver =
 	.probe = wacom_probe,
 	.remove = wacom_remove,
 	.raw_event = wacom_raw_event,
+	.input_mapped = wacom_input_mapped,
 };
 
 static int __init wacom_init(void)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-wiimote.c linux-libre-3.2-gnu1/drivers/hid/hid-wiimote.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-wiimote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-wiimote.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,15 +10,18 @@
  * any later version.
  */
 
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
 #include <linux/spinlock.h>
 #include "hid-ids.h"
 
-#define WIIMOTE_VERSION "0.1"
+#define WIIMOTE_VERSION "0.2"
 #define WIIMOTE_NAME "Nintendo Wii Remote"
 #define WIIMOTE_BUFSIZE 32
 
@@ -30,12 +33,26 @@ struct wiimote_buf {
 struct wiimote_state {
 	spinlock_t lock;
 	__u8 flags;
+	__u8 accel_split[2];
+
+	/* synchronous cmd requests */
+	struct mutex sync;
+	struct completion ready;
+	int cmd;
+	__u32 opt;
+
+	/* results of synchronous requests */
+	__u8 cmd_battery;
+	__u8 cmd_err;
 };
 
 struct wiimote_data {
 	struct hid_device *hdev;
 	struct input_dev *input;
 	struct led_classdev *leds[4];
+	struct input_dev *accel;
+	struct input_dev *ir;
+	struct power_supply battery;
 
 	spinlock_t qlock;
 	__u8 head;
@@ -46,23 +63,47 @@ struct wiimote_data {
 	struct wiimote_state state;
 };
 
-#define WIIPROTO_FLAG_LED1 0x01
-#define WIIPROTO_FLAG_LED2 0x02
-#define WIIPROTO_FLAG_LED3 0x04
-#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAG_LED1		0x01
+#define WIIPROTO_FLAG_LED2		0x02
+#define WIIPROTO_FLAG_LED3		0x04
+#define WIIPROTO_FLAG_LED4		0x08
+#define WIIPROTO_FLAG_RUMBLE		0x10
+#define WIIPROTO_FLAG_ACCEL		0x20
+#define WIIPROTO_FLAG_IR_BASIC		0x40
+#define WIIPROTO_FLAG_IR_EXT		0x80
+#define WIIPROTO_FLAG_IR_FULL		0xc0 /* IR_BASIC | IR_EXT */
 #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
 					WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
+							WIIPROTO_FLAG_IR_FULL)
 
 /* return flag for led \num */
 #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
 
 enum wiiproto_reqs {
 	WIIPROTO_REQ_NULL = 0x0,
+	WIIPROTO_REQ_RUMBLE = 0x10,
 	WIIPROTO_REQ_LED = 0x11,
 	WIIPROTO_REQ_DRM = 0x12,
+	WIIPROTO_REQ_IR1 = 0x13,
+	WIIPROTO_REQ_SREQ = 0x15,
+	WIIPROTO_REQ_WMEM = 0x16,
+	WIIPROTO_REQ_RMEM = 0x17,
+	WIIPROTO_REQ_IR2 = 0x1a,
 	WIIPROTO_REQ_STATUS = 0x20,
+	WIIPROTO_REQ_DATA = 0x21,
 	WIIPROTO_REQ_RETURN = 0x22,
 	WIIPROTO_REQ_DRM_K = 0x30,
+	WIIPROTO_REQ_DRM_KA = 0x31,
+	WIIPROTO_REQ_DRM_KE = 0x32,
+	WIIPROTO_REQ_DRM_KAI = 0x33,
+	WIIPROTO_REQ_DRM_KEE = 0x34,
+	WIIPROTO_REQ_DRM_KAE = 0x35,
+	WIIPROTO_REQ_DRM_KIE = 0x36,
+	WIIPROTO_REQ_DRM_KAIE = 0x37,
+	WIIPROTO_REQ_DRM_E = 0x3d,
+	WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
+	WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
 };
 
 enum wiiproto_keys {
@@ -94,6 +135,56 @@ static __u16 wiiproto_keymap[] = {
 	BTN_MODE,	/* WIIPROTO_KEY_HOME */
 };
 
+static enum power_supply_property wiimote_battery_props[] = {
+	POWER_SUPPLY_PROP_CAPACITY
+};
+
+/* requires the state.lock spinlock to be held */
+static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
+								__u32 opt)
+{
+	return wdata->state.cmd == cmd && wdata->state.opt == opt;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
+{
+	wdata->state.cmd = WIIPROTO_REQ_NULL;
+	complete(&wdata->state.ready);
+}
+
+static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
+{
+	return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
+								__u32 opt)
+{
+	INIT_COMPLETION(wdata->state.ready);
+	wdata->state.cmd = cmd;
+	wdata->state.opt = opt;
+}
+
+static inline void wiimote_cmd_release(struct wiimote_data *wdata)
+{
+	mutex_unlock(&wdata->state.sync);
+}
+
+static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
+{
+	int ret;
+
+	ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
+	if (ret < 0)
+		return -ERESTARTSYS;
+	else if (ret == 0)
+		return -EIO;
+	else
+		return 0;
+}
+
 static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
 								size_t count)
 {
@@ -172,6 +263,39 @@ static void wiimote_queue(struct wiimote
 	spin_unlock_irqrestore(&wdata->qlock, flags);
 }
 
+/*
+ * This sets the rumble bit on the given output report if rumble is
+ * currently enabled.
+ * \cmd1 must point to the second byte in the output report => &cmd[1]
+ * This must be called on nearly every output report before passing it
+ * into the output queue!
+ */
+static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1)
+{
+	if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE)
+		*cmd1 |= 0x01;
+}
+
+static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble)
+{
+	__u8 cmd[2];
+
+	rumble = !!rumble;
+	if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE))
+		return;
+
+	if (rumble)
+		wdata->state.flags |= WIIPROTO_FLAG_RUMBLE;
+	else
+		wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE;
+
+	cmd[0] = WIIPROTO_REQ_RUMBLE;
+	cmd[1] = 0;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
 static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
 {
 	__u8 cmd[2];
@@ -193,6 +317,7 @@ static void wiiproto_req_leds(struct wii
 	if (leds & WIIPROTO_FLAG_LED4)
 		cmd[1] |= 0x80;
 
+	wiiproto_keep_rumble(wdata, &cmd[1]);
 	wiimote_queue(wdata, cmd, sizeof(cmd));
 }
 
@@ -203,7 +328,23 @@ static void wiiproto_req_leds(struct wii
  */
 static __u8 select_drm(struct wiimote_data *wdata)
 {
-	return WIIPROTO_REQ_DRM_K;
+	__u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
+
+	if (ir == WIIPROTO_FLAG_IR_BASIC) {
+		if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+			return WIIPROTO_REQ_DRM_KAIE;
+		else
+			return WIIPROTO_REQ_DRM_KIE;
+	} else if (ir == WIIPROTO_FLAG_IR_EXT) {
+		return WIIPROTO_REQ_DRM_KAI;
+	} else if (ir == WIIPROTO_FLAG_IR_FULL) {
+		return WIIPROTO_REQ_DRM_SKAI1;
+	} else {
+		if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+			return WIIPROTO_REQ_DRM_KA;
+		else
+			return WIIPROTO_REQ_DRM_K;
+	}
 }
 
 static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
@@ -217,9 +358,256 @@ static void wiiproto_req_drm(struct wiim
 	cmd[1] = 0;
 	cmd[2] = drm;
 
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_status(struct wiimote_data *wdata)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_SREQ;
+	cmd[1] = 0;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel)
+{
+	accel = !!accel;
+	if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+		return;
+
+	if (accel)
+		wdata->state.flags |= WIIPROTO_FLAG_ACCEL;
+	else
+		wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL;
+
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_IR1;
+	cmd[1] = flags;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_IR2;
+	cmd[1] = flags;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+#define wiiproto_req_wreg(wdata, os, buf, sz) \
+			wiiproto_req_wmem((wdata), false, (os), (buf), (sz))
+
+#define wiiproto_req_weeprom(wdata, os, buf, sz) \
+			wiiproto_req_wmem((wdata), true, (os), (buf), (sz))
+
+static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
+				__u32 offset, const __u8 *buf, __u8 size)
+{
+	__u8 cmd[22];
+
+	if (size > 16 || size == 0) {
+		hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size);
+		return;
+	}
+
+	memset(cmd, 0, sizeof(cmd));
+	cmd[0] = WIIPROTO_REQ_WMEM;
+	cmd[2] = (offset >> 16) & 0xff;
+	cmd[3] = (offset >> 8) & 0xff;
+	cmd[4] = offset & 0xff;
+	cmd[5] = size;
+	memcpy(&cmd[6], buf, size);
+
+	if (!eeprom)
+		cmd[1] |= 0x04;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
 	wiimote_queue(wdata, cmd, sizeof(cmd));
 }
 
+/* requries the cmd-mutex to be held */
+static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
+						const __u8 *wmem, __u8 size)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0);
+	wiiproto_req_wreg(wdata, offset, wmem, size);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (!ret && wdata->state.cmd_err)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int wiimote_battery_get_property(struct power_supply *psy,
+						enum power_supply_property psp,
+						union power_supply_propval *val)
+{
+	struct wiimote_data *wdata = container_of(psy,
+						struct wiimote_data, battery);
+	int ret = 0, state;
+	unsigned long flags;
+
+	ret = wiimote_cmd_acquire(wdata);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
+	wiiproto_req_status(wdata);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	state = wdata->state.cmd_battery;
+	wiimote_cmd_release(wdata);
+
+	if (ret)
+		return ret;
+
+	switch (psp) {
+		case POWER_SUPPLY_PROP_CAPACITY:
+			val->intval = state * 100 / 255;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode)
+{
+	int ret;
+	unsigned long flags;
+	__u8 format = 0;
+	static const __u8 data_enable[] = { 0x01 };
+	static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01,
+						0x00, 0xaa, 0x00, 0x64 };
+	static const __u8 data_sens2[] = { 0x63, 0x03 };
+	static const __u8 data_fin[] = { 0x08 };
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+
+	if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) {
+		spin_unlock_irqrestore(&wdata->state.lock, flags);
+		return 0;
+	}
+
+	if (mode == 0) {
+		wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+		wiiproto_req_ir1(wdata, 0);
+		wiiproto_req_ir2(wdata, 0);
+		wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+		spin_unlock_irqrestore(&wdata->state.lock, flags);
+		return 0;
+	}
+
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_acquire(wdata);
+	if (ret)
+		return ret;
+
+	/* send PIXEL CLOCK ENABLE cmd first */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0);
+	wiiproto_req_ir1(wdata, 0x06);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (ret)
+		goto unlock;
+	if (wdata->state.cmd_err) {
+		ret = -EIO;
+		goto unlock;
+	}
+
+	/* enable IR LOGIC */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0);
+	wiiproto_req_ir2(wdata, 0x06);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (ret)
+		goto unlock;
+	if (wdata->state.cmd_err) {
+		ret = -EIO;
+		goto unlock;
+	}
+
+	/* enable IR cam but do not make it send data, yet */
+	ret = wiimote_cmd_write(wdata, 0xb00030, data_enable,
+							sizeof(data_enable));
+	if (ret)
+		goto unlock;
+
+	/* write first sensitivity block */
+	ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1,
+							sizeof(data_sens1));
+	if (ret)
+		goto unlock;
+
+	/* write second sensitivity block */
+	ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2,
+							sizeof(data_sens2));
+	if (ret)
+		goto unlock;
+
+	/* put IR cam into desired state */
+	switch (mode) {
+		case WIIPROTO_FLAG_IR_FULL:
+			format = 5;
+			break;
+		case WIIPROTO_FLAG_IR_EXT:
+			format = 3;
+			break;
+		case WIIPROTO_FLAG_IR_BASIC:
+			format = 1;
+			break;
+	}
+	ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format));
+	if (ret)
+		goto unlock;
+
+	/* make IR cam send data */
+	ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin));
+	if (ret)
+		goto unlock;
+
+	/* request new DRM mode compatible to IR mode */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+	wdata->state.flags |= mode & WIIPROTO_FLAGS_IR;
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+unlock:
+	wiimote_cmd_release(wdata);
+	return ret;
+}
+
 static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
 {
 	struct wiimote_data *wdata;
@@ -268,9 +656,28 @@ static void wiimote_leds_set(struct led_
 	}
 }
 
-static int wiimote_input_event(struct input_dev *dev, unsigned int type,
-						unsigned int code, int value)
+static int wiimote_ff_play(struct input_dev *dev, void *data,
+							struct ff_effect *eff)
 {
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	__u8 value;
+	unsigned long flags;
+
+	/*
+	 * The wiimote supports only a single rumble motor so if any magnitude
+	 * is set to non-zero then we start the rumble motor. If both are set to
+	 * zero, we stop the rumble motor.
+	 */
+
+	if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
+		value = 1;
+	else
+		value = 0;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_rumble(wdata, value);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
 	return 0;
 }
 
@@ -288,6 +695,61 @@ static void wiimote_input_close(struct i
 	hid_hw_close(wdata->hdev);
 }
 
+static int wiimote_accel_open(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	int ret;
+	unsigned long flags;
+
+	ret = hid_hw_open(wdata->hdev);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_accel(wdata, true);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	return 0;
+}
+
+static void wiimote_accel_close(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_accel(wdata, false);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	hid_hw_close(wdata->hdev);
+}
+
+static int wiimote_ir_open(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	int ret;
+
+	ret = hid_hw_open(wdata->hdev);
+	if (ret)
+		return ret;
+
+	ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC);
+	if (ret) {
+		hid_hw_close(wdata->hdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void wiimote_ir_close(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+
+	wiimote_init_ir(wdata, 0);
+	hid_hw_close(wdata->hdev);
+}
+
 static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
 {
 	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
@@ -315,12 +777,100 @@ static void handler_keys(struct wiimote_
 	input_sync(wdata->input);
 }
 
+static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
+{
+	__u16 x, y, z;
+
+	if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+		return;
+
+	/*
+	 * payload is: BB BB XX YY ZZ
+	 * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ
+	 * contain the upper 8 bits of each value. The lower 2 bits are
+	 * contained in the buttons data BB BB.
+	 * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the
+	 * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y
+	 * accel value and bit 6 is the second bit of the Z value.
+	 * The first bit of Y and Z values is not available and always set to 0.
+	 * 0x200 is returned on no movement.
+	 */
+
+	x = payload[2] << 2;
+	y = payload[3] << 2;
+	z = payload[4] << 2;
+
+	x |= (payload[0] >> 5) & 0x3;
+	y |= (payload[1] >> 4) & 0x2;
+	z |= (payload[1] >> 5) & 0x2;
+
+	input_report_abs(wdata->accel, ABS_RX, x - 0x200);
+	input_report_abs(wdata->accel, ABS_RY, y - 0x200);
+	input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
+	input_sync(wdata->accel);
+}
+
+#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT0X, ABS_HAT0Y)
+#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT1X, ABS_HAT1Y)
+#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT2X, ABS_HAT2Y)
+#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT3X, ABS_HAT3Y)
+
+static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
+						bool packed, __u8 xid, __u8 yid)
+{
+	__u16 x, y;
+
+	if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
+		return;
+
+	/*
+	 * Basic IR data is encoded into 3 bytes. The first two bytes are the
+	 * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits
+	 * of both.
+	 * If data is packed, then the 3rd byte is put first and slightly
+	 * reordered. This allows to interleave packed and non-packed data to
+	 * have two IR sets in 5 bytes instead of 6.
+	 * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev.
+	 */
+
+	if (packed) {
+		x = ir[1] << 2;
+		y = ir[2] << 2;
+
+		x |= ir[0] & 0x3;
+		y |= (ir[0] >> 2) & 0x3;
+	} else {
+		x = ir[0] << 2;
+		y = ir[1] << 2;
+
+		x |= (ir[2] >> 4) & 0x3;
+		y |= (ir[2] >> 6) & 0x3;
+	}
+
+	input_report_abs(wdata->ir, xid, x);
+	input_report_abs(wdata->ir, yid, y);
+}
+
 static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
 {
 	handler_keys(wdata, payload);
 
 	/* on status reports the drm is reset so we need to resend the drm */
 	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+
+	if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
+		wdata->state.cmd_battery = payload[5];
+		wiimote_cmd_complete(wdata);
+	}
+}
+
+static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
 }
 
 static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
@@ -330,9 +880,105 @@ static void handler_return(struct wiimot
 
 	handler_keys(wdata, payload);
 
-	if (err)
+	if (wiimote_cmd_pending(wdata, cmd, 0)) {
+		wdata->state.cmd_err = err;
+		wiimote_cmd_complete(wdata);
+	} else if (err) {
 		hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err,
 									cmd);
+	}
+}
+
+static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+}
+
+static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+}
+
+static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+	ir_to_input0(wdata, &payload[5], false);
+	ir_to_input1(wdata, &payload[8], false);
+	ir_to_input2(wdata, &payload[11], false);
+	ir_to_input3(wdata, &payload[14], false);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+}
+
+static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	ir_to_input0(wdata, &payload[2], false);
+	ir_to_input1(wdata, &payload[4], true);
+	ir_to_input2(wdata, &payload[7], false);
+	ir_to_input3(wdata, &payload[9], true);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+}
+
+static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+	ir_to_input0(wdata, &payload[5], false);
+	ir_to_input1(wdata, &payload[7], true);
+	ir_to_input2(wdata, &payload[10], false);
+	ir_to_input3(wdata, &payload[12], true);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload)
+{
+}
+
+static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+
+	wdata->state.accel_split[0] = payload[2];
+	wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
+	wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
+
+	ir_to_input0(wdata, &payload[3], false);
+	ir_to_input1(wdata, &payload[12], false);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
+{
+	__u8 buf[5];
+
+	handler_keys(wdata, payload);
+
+	wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02);
+	wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08);
+
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = wdata->state.accel_split[0];
+	buf[3] = payload[2];
+	buf[4] = wdata->state.accel_split[1];
+	handler_accel(wdata, buf);
+
+	ir_to_input2(wdata, &payload[3], false);
+	ir_to_input3(wdata, &payload[12], false);
+	input_sync(wdata->ir);
 }
 
 struct wiiproto_handler {
@@ -343,8 +989,19 @@ struct wiiproto_handler {
 
 static struct wiiproto_handler handlers[] = {
 	{ .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+	{ .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data },
 	{ .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
 	{ .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
+	{ .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
+	{ .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE },
+	{ .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
+	{ .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE },
+	{ .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+	{ .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
+	{ .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
+	{ .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E },
+	{ .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
+	{ .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
 	{ .id = 0 }
 };
 
@@ -355,6 +1012,7 @@ static int wiimote_hid_event(struct hid_
 	struct wiiproto_handler *h;
 	int i;
 	unsigned long flags;
+	bool handled = false;
 
 	if (size < 1)
 		return -EINVAL;
@@ -363,10 +1021,16 @@ static int wiimote_hid_event(struct hid_
 
 	for (i = 0; handlers[i].id; ++i) {
 		h = &handlers[i];
-		if (h->id == raw_data[0] && h->size < size)
+		if (h->id == raw_data[0] && h->size < size) {
 			h->func(wdata, &raw_data[1]);
+			handled = true;
+		}
 	}
 
+	if (!handled)
+		hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0],
+									size);
+
 	spin_unlock_irqrestore(&wdata->state.lock, flags);
 
 	return 0;
@@ -434,16 +1098,13 @@ static struct wiimote_data *wiimote_crea
 		return NULL;
 
 	wdata->input = input_allocate_device();
-	if (!wdata->input) {
-		kfree(wdata);
-		return NULL;
-	}
+	if (!wdata->input)
+		goto err;
 
 	wdata->hdev = hdev;
 	hid_set_drvdata(hdev, wdata);
 
 	input_set_drvdata(wdata->input, wdata);
-	wdata->input->event = wiimote_input_event;
 	wdata->input->open = wiimote_input_open;
 	wdata->input->close = wiimote_input_close;
 	wdata->input->dev.parent = &wdata->hdev->dev;
@@ -457,18 +1118,89 @@ static struct wiimote_data *wiimote_crea
 	for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
 		set_bit(wiiproto_keymap[i], wdata->input->keybit);
 
+	set_bit(FF_RUMBLE, wdata->input->ffbit);
+	if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play))
+		goto err_input;
+
+	wdata->accel = input_allocate_device();
+	if (!wdata->accel)
+		goto err_input;
+
+	input_set_drvdata(wdata->accel, wdata);
+	wdata->accel->open = wiimote_accel_open;
+	wdata->accel->close = wiimote_accel_close;
+	wdata->accel->dev.parent = &wdata->hdev->dev;
+	wdata->accel->id.bustype = wdata->hdev->bus;
+	wdata->accel->id.vendor = wdata->hdev->vendor;
+	wdata->accel->id.product = wdata->hdev->product;
+	wdata->accel->id.version = wdata->hdev->version;
+	wdata->accel->name = WIIMOTE_NAME " Accelerometer";
+
+	set_bit(EV_ABS, wdata->accel->evbit);
+	set_bit(ABS_RX, wdata->accel->absbit);
+	set_bit(ABS_RY, wdata->accel->absbit);
+	set_bit(ABS_RZ, wdata->accel->absbit);
+	input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
+	input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
+	input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
+
+	wdata->ir = input_allocate_device();
+	if (!wdata->ir)
+		goto err_ir;
+
+	input_set_drvdata(wdata->ir, wdata);
+	wdata->ir->open = wiimote_ir_open;
+	wdata->ir->close = wiimote_ir_close;
+	wdata->ir->dev.parent = &wdata->hdev->dev;
+	wdata->ir->id.bustype = wdata->hdev->bus;
+	wdata->ir->id.vendor = wdata->hdev->vendor;
+	wdata->ir->id.product = wdata->hdev->product;
+	wdata->ir->id.version = wdata->hdev->version;
+	wdata->ir->name = WIIMOTE_NAME " IR";
+
+	set_bit(EV_ABS, wdata->ir->evbit);
+	set_bit(ABS_HAT0X, wdata->ir->absbit);
+	set_bit(ABS_HAT0Y, wdata->ir->absbit);
+	set_bit(ABS_HAT1X, wdata->ir->absbit);
+	set_bit(ABS_HAT1Y, wdata->ir->absbit);
+	set_bit(ABS_HAT2X, wdata->ir->absbit);
+	set_bit(ABS_HAT2Y, wdata->ir->absbit);
+	set_bit(ABS_HAT3X, wdata->ir->absbit);
+	set_bit(ABS_HAT3Y, wdata->ir->absbit);
+	input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4);
+
 	spin_lock_init(&wdata->qlock);
 	INIT_WORK(&wdata->worker, wiimote_worker);
 
 	spin_lock_init(&wdata->state.lock);
+	init_completion(&wdata->state.ready);
+	mutex_init(&wdata->state.sync);
 
 	return wdata;
+
+err_ir:
+	input_free_device(wdata->accel);
+err_input:
+	input_free_device(wdata->input);
+err:
+	kfree(wdata);
+	return NULL;
 }
 
 static void wiimote_destroy(struct wiimote_data *wdata)
 {
 	wiimote_leds_destroy(wdata);
 
+	power_supply_unregister(&wdata->battery);
+	input_unregister_device(wdata->accel);
+	input_unregister_device(wdata->ir);
 	input_unregister_device(wdata->input);
 	cancel_work_sync(&wdata->worker);
 	hid_hw_stop(wdata->hdev);
@@ -500,12 +1232,37 @@ static int wiimote_hid_probe(struct hid_
 		goto err;
 	}
 
-	ret = input_register_device(wdata->input);
+	ret = input_register_device(wdata->accel);
 	if (ret) {
 		hid_err(hdev, "Cannot register input device\n");
 		goto err_stop;
 	}
 
+	ret = input_register_device(wdata->ir);
+	if (ret) {
+		hid_err(hdev, "Cannot register input device\n");
+		goto err_ir;
+	}
+
+	ret = input_register_device(wdata->input);
+	if (ret) {
+		hid_err(hdev, "Cannot register input device\n");
+		goto err_input;
+	}
+
+	wdata->battery.properties = wiimote_battery_props;
+	wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props);
+	wdata->battery.get_property = wiimote_battery_get_property;
+	wdata->battery.name = "wiimote_battery";
+	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+	wdata->battery.use_for_apm = 0;
+
+	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
+	if (ret) {
+		hid_err(hdev, "Cannot register battery device\n");
+		goto err_battery;
+	}
+
 	ret = wiimote_leds_create(wdata);
 	if (ret)
 		goto err_free;
@@ -523,9 +1280,20 @@ err_free:
 	wiimote_destroy(wdata);
 	return ret;
 
+err_battery:
+	input_unregister_device(wdata->input);
+	wdata->input = NULL;
+err_input:
+	input_unregister_device(wdata->ir);
+	wdata->ir = NULL;
+err_ir:
+	input_unregister_device(wdata->accel);
+	wdata->accel = NULL;
 err_stop:
 	hid_hw_stop(hdev);
 err:
+	input_free_device(wdata->ir);
+	input_free_device(wdata->accel);
 	input_free_device(wdata->input);
 	kfree(wdata);
 	return ret;
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-zpff.c linux-libre-3.2-gnu1/drivers/hid/hid-zpff.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-zpff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-zpff.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/hid-zydacron.c linux-libre-3.2-gnu1/drivers/hid/hid-zydacron.c
--- linux-libre-3.1-gnu1/drivers/hid/hid-zydacron.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/hid-zydacron.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,9 +201,7 @@ static void zc_remove(struct hid_device
 	struct zc_device *zc = hid_get_drvdata(hdev);
 
 	hid_hw_stop(hdev);
-
-	if (NULL != zc)
-		kfree(zc);
+	kfree(zc);
 }
 
 static const struct hid_device_id zc_devices[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/hid/Kconfig linux-libre-3.2-gnu1/drivers/hid/Kconfig
--- linux-libre-3.1-gnu1/drivers/hid/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ config HID_ACRUX
 	Say Y here if you want to enable support for ACRUX game controllers.
 
 config HID_ACRUX_FF
-	tristate "ACRUX force feedback support"
+	bool "ACRUX force feedback support"
 	depends on HID_ACRUX
 	select INPUT_FF_MEMLESS
 	---help---
@@ -245,6 +245,15 @@ config HID_LOGITECH
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
 
+config HID_LOGITECH_DJ
+	tristate "Logitech Unifying receivers full support"
+	depends on HID_LOGITECH
+	default m
+	---help---
+	Say Y if you want support for Logitech Unifying receivers and devices.
+	Unifying receivers are capable of pairing up to 6 Logitech compliant
+	devices to the same receiver.
+
 config LOGITECH_FF
 	bool "Logitech force feedback support"
 	depends on HID_LOGITECH
@@ -278,13 +287,21 @@ config LOGIG940_FF
 	  Say Y here if you want to enable force feedback support for Logitech
 	  Flight System G940 devices.
 
-config LOGIWII_FF
-	bool "Logitech Speed Force Wireless force feedback support"
+config LOGIWHEELS_FF
+	bool "Logitech wheels configuration and force feedback support"
 	depends on HID_LOGITECH
 	select INPUT_FF_MEMLESS
+	default LOGITECH_FF
 	help
-	  Say Y here if you want to enable force feedback support for Logitech
-	  Speed Force Wireless (Wii) devices.
+	  Say Y here if you want to enable force feedback and range setting
+	  support for following Logitech wheels:
+	  - Logitech Driving Force
+	  - Logitech Driving Force Pro
+	  - Logitech Driving Force GT
+	  - Logitech G25
+	  - Logitech G27
+	  - Logitech MOMO/MOMO 2
+	  - Logitech Formula Force EX
 
 config HID_MAGICMOUSE
 	tristate "Apple MagicMouse multi-touch support"
@@ -328,6 +345,7 @@ config HID_MULTITOUCH
 	  - Hanvon dual touch panels
 	  - Ilitek dual touch panels
 	  - IrTouch Infrared USB panels
+	  - LG Display panels (Dell ST2220Tc)
 	  - Lumio CrystalTouch panels
 	  - MosArt dual-touch panels
 	  - PenMount dual touch panels
@@ -441,6 +459,13 @@ config HID_PICOLCD_LEDS
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
+config HID_PRIMAX
+	tristate "Primax non-fully HID-compliant devices"
+	depends on USB_HID
+	---help---
+	Support for Primax devices that are not fully compliant with the
+	HID standard.
+
 config HID_QUANTA
 	tristate "Quanta Optical Touch panels"
 	depends on USB_HID
@@ -539,7 +564,11 @@ config HID_SMARTJOYPLUS
 	tristate "SmartJoy PLUS PS2/USB adapter support"
 	depends on USB_HID
 	---help---
-	Support for SmartJoy PLUS PS2/USB adapter.
+	Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
+	Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
+
+	Note that DDR (Dance Dance Revolution) mode is not supported, nor
+	is pressure sensitive buttons on the pro models.
 
 config SMARTJOYPLUS_FF
 	bool "SmartJoy PLUS PS2/USB adapter force feedback support"
@@ -590,6 +619,7 @@ config HID_WIIMOTE
 	tristate "Nintendo Wii Remote support"
 	depends on BT_HIDP
 	depends on LEDS_CLASS
+	select POWER_SUPPLY
 	---help---
 	Support for the Nintendo Wii Remote bluetooth device.
 
diff -druNp linux-libre-3.1-gnu1/drivers/hid/Makefile linux-libre-3.2-gnu1/drivers/hid/Makefile
--- linux-libre-3.1-gnu1/drivers/hid/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@ endif
 ifdef CONFIG_LOGIG940_FF
 	hid-logitech-y	+= hid-lg3ff.o
 endif
-ifdef CONFIG_LOGIWII_FF
+ifdef CONFIG_LOGIWHEELS_FF
 	hid-logitech-y	+= hid-lg4ff.o
 endif
 
@@ -43,6 +43,7 @@ obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytou
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
 obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
+obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
@@ -54,6 +55,7 @@ obj-$(CONFIG_HID_QUANTA)	+= hid-quanta.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
+obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o
 obj-$(CONFIG_HID_ROCCAT_COMMON)	+= hid-roccat-common.o
 obj-$(CONFIG_HID_ROCCAT_ARVO)	+= hid-roccat-arvo.o
diff -druNp linux-libre-3.1-gnu1/drivers/hid/usbhid/hid-core.c linux-libre-3.2-gnu1/drivers/hid/usbhid/hid-core.c
--- linux-libre-3.1-gnu1/drivers/hid/usbhid/hid-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/usbhid/hid-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1270,7 +1270,7 @@ static void hid_cancel_delayed_stuff(str
 
 static void hid_cease_io(struct usbhid_device *usbhid)
 {
-	del_timer(&usbhid->io_retry);
+	del_timer_sync(&usbhid->io_retry);
 	usb_kill_urb(usbhid->urbin);
 	usb_kill_urb(usbhid->urbctrl);
 	usb_kill_urb(usbhid->urbout);
@@ -1332,7 +1332,7 @@ static int hid_suspend(struct usb_interf
 	struct usbhid_device *usbhid = hid->driver_data;
 	int status;
 
-	if (message.event & PM_EVENT_AUTO) {
+	if (PMSG_IS_AUTO(message)) {
 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
 		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
 		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
@@ -1367,7 +1367,7 @@ static int hid_suspend(struct usb_interf
 			return -EIO;
 	}
 
-	if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
+	if (!ignoreled && PMSG_IS_AUTO(message)) {
 		spin_lock_irq(&usbhid->lock);
 		if (test_bit(HID_LED_ON, &usbhid->iofl)) {
 			spin_unlock_irq(&usbhid->lock);
@@ -1380,8 +1380,7 @@ static int hid_suspend(struct usb_interf
 	hid_cancel_delayed_stuff(usbhid);
 	hid_cease_io(usbhid);
 
-	if ((message.event & PM_EVENT_AUTO) &&
-			test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+	if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
 		/* lost race against keypresses */
 		status = hid_start_in(hid);
 		if (status < 0)
diff -druNp linux-libre-3.1-gnu1/drivers/hid/usbhid/hiddev.c linux-libre-3.2-gnu1/drivers/hid/usbhid/hiddev.c
--- linux-libre-3.1-gnu1/drivers/hid/usbhid/hiddev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/usbhid/hiddev.c	2012-01-04 18:55:44.000000000 -0500
@@ -641,6 +641,8 @@ static long hiddev_ioctl(struct file *fi
 			struct usb_device *dev = hid_to_usb_dev(hid);
 			struct usbhid_device *usbhid = hid->driver_data;
 
+			memset(&dinfo, 0, sizeof(dinfo));
+
 			dinfo.bustype = BUS_USB;
 			dinfo.busnum = dev->bus->busnum;
 			dinfo.devnum = dev->devnum;
diff -druNp linux-libre-3.1-gnu1/drivers/hid/usbhid/hid-quirks.c linux-libre-3.2-gnu1/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-3.1-gnu1/drivers/hid/usbhid/hid-quirks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hid/usbhid/hid-quirks.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <linux/hid.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include "../hid-ids.h"
@@ -80,10 +81,8 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
-	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
 	{ USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
diff -druNp linux-libre-3.1-gnu1/drivers/hv/channel.c linux-libre-3.2-gnu1/drivers/hv/channel.c
--- linux-libre-3.1-gnu1/drivers/hv/channel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/channel.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+#define NUM_PAGES_SPANNED(addr, len) \
+((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
+
+/* Internal routines */
+static int create_gpadl_header(
+	void *kbuffer,	/* must be phys and virt contiguous */
+	u32 size,	/* page-size multiple */
+	struct vmbus_channel_msginfo **msginfo,
+	u32 *messagecount);
+static void vmbus_setevent(struct vmbus_channel *channel);
+
+/*
+ * vmbus_setevent- Trigger an event notification on the specified
+ * channel.
+ */
+static void vmbus_setevent(struct vmbus_channel *channel)
+{
+	struct hv_monitor_page *monitorpage;
+
+	if (channel->offermsg.monitor_allocated) {
+		/* Each u32 represents 32 channels */
+		sync_set_bit(channel->offermsg.child_relid & 31,
+			(unsigned long *) vmbus_connection.send_int_page +
+			(channel->offermsg.child_relid >> 5));
+
+		monitorpage = vmbus_connection.monitor_pages;
+		monitorpage++; /* Get the child to parent monitor page */
+
+		sync_set_bit(channel->monitor_bit,
+			(unsigned long *)&monitorpage->trigger_group
+					[channel->monitor_grp].pending);
+
+	} else {
+		vmbus_set_event(channel->offermsg.child_relid);
+	}
+}
+
+/*
+ * vmbus_get_debug_info -Retrieve various channel debug info
+ */
+void vmbus_get_debug_info(struct vmbus_channel *channel,
+			      struct vmbus_channel_debug_info *debuginfo)
+{
+	struct hv_monitor_page *monitorpage;
+	u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
+	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
+
+	debuginfo->relid = channel->offermsg.child_relid;
+	debuginfo->state = channel->state;
+	memcpy(&debuginfo->interfacetype,
+	       &channel->offermsg.offer.if_type, sizeof(uuid_le));
+	memcpy(&debuginfo->interface_instance,
+	       &channel->offermsg.offer.if_instance,
+	       sizeof(uuid_le));
+
+	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
+
+	debuginfo->monitorid = channel->offermsg.monitorid;
+
+	debuginfo->servermonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->servermonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->servermonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	monitorpage++;
+
+	debuginfo->clientmonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->clientmonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->clientmonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
+	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
+}
+
+/*
+ * vmbus_open - Open the specified channel.
+ */
+int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
+		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
+		     void (*onchannelcallback)(void *context), void *context)
+{
+	struct vmbus_channel_open_channel *open_msg;
+	struct vmbus_channel_msginfo *open_info = NULL;
+	void *in, *out;
+	unsigned long flags;
+	int ret, t, err = 0;
+
+	newchannel->onchannel_callback = onchannelcallback;
+	newchannel->channel_callback_context = context;
+
+	/* Allocate the ring buffer */
+	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+
+	if (!out)
+		return -ENOMEM;
+
+
+	in = (void *)((unsigned long)out + send_ringbuffer_size);
+
+	newchannel->ringbuffer_pages = out;
+	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
+					   recv_ringbuffer_size) >> PAGE_SHIFT;
+
+	ret = hv_ringbuffer_init(
+		&newchannel->outbound, out, send_ringbuffer_size);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	ret = hv_ringbuffer_init(
+		&newchannel->inbound, in, recv_ringbuffer_size);
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+
+	/* Establish the gpadl for the ring buffer */
+	newchannel->ringbuffer_gpadlhandle = 0;
+
+	ret = vmbus_establish_gpadl(newchannel,
+					 newchannel->outbound.ring_buffer,
+					 send_ringbuffer_size +
+					 recv_ringbuffer_size,
+					 &newchannel->ringbuffer_gpadlhandle);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	/* Create and init the channel open message */
+	open_info = kmalloc(sizeof(*open_info) +
+			   sizeof(struct vmbus_channel_open_channel),
+			   GFP_KERNEL);
+	if (!open_info) {
+		err = -ENOMEM;
+		goto errorout;
+	}
+
+	init_completion(&open_info->waitevent);
+
+	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
+	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
+	open_msg->openid = newchannel->offermsg.child_relid;
+	open_msg->child_relid = newchannel->offermsg.child_relid;
+	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
+	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
+						  PAGE_SHIFT;
+	open_msg->server_contextarea_gpadlhandle = 0;
+
+	if (userdatalen > MAX_USER_DEFINED_BYTES) {
+		err = -EINVAL;
+		goto errorout;
+	}
+
+	if (userdatalen)
+		memcpy(open_msg->userdata, userdata, userdatalen);
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&open_info->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(open_msg,
+			       sizeof(struct vmbus_channel_open_channel));
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
+	if (t == 0) {
+		err = -ETIMEDOUT;
+		goto errorout;
+	}
+
+
+	if (open_info->response.open_result.status)
+		err = open_info->response.open_result.status;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&open_info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(open_info);
+	return err;
+
+errorout:
+	hv_ringbuffer_cleanup(&newchannel->outbound);
+	hv_ringbuffer_cleanup(&newchannel->inbound);
+	free_pages((unsigned long)out,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+	kfree(open_info);
+	return err;
+}
+EXPORT_SYMBOL_GPL(vmbus_open);
+
+/*
+ * create_gpadl_header - Creates a gpadl for the specified buffer
+ */
+static int create_gpadl_header(void *kbuffer, u32 size,
+					 struct vmbus_channel_msginfo **msginfo,
+					 u32 *messagecount)
+{
+	int i;
+	int pagecount;
+	unsigned long long pfn;
+	struct vmbus_channel_gpadl_header *gpadl_header;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	struct vmbus_channel_msginfo *msgheader;
+	struct vmbus_channel_msginfo *msgbody = NULL;
+	u32 msgsize;
+
+	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
+
+	pagecount = size >> PAGE_SHIFT;
+	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
+
+	/* do we need a gpadl body msg */
+	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+		  sizeof(struct vmbus_channel_gpadl_header) -
+		  sizeof(struct gpa_range);
+	pfncount = pfnsize / sizeof(u64);
+
+	if (pagecount > pfncount) {
+		/* we need a gpadl body */
+		/* fill in the header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
+		msgheader =  kzalloc(msgsize, GFP_KERNEL);
+		if (!msgheader)
+			goto nomem;
+
+		INIT_LIST_HEAD(&msgheader->submsglist);
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pfncount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+		*msginfo = msgheader;
+		*messagecount = 1;
+
+		pfnsum = pfncount;
+		pfnleft = pagecount - pfncount;
+
+		/* how many pfns can we fit */
+		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+			  sizeof(struct vmbus_channel_gpadl_body);
+		pfncount = pfnsize / sizeof(u64);
+
+		/* fill in the body */
+		while (pfnleft) {
+			if (pfnleft > pfncount)
+				pfncurr = pfncount;
+			else
+				pfncurr = pfnleft;
+
+			msgsize = sizeof(struct vmbus_channel_msginfo) +
+				  sizeof(struct vmbus_channel_gpadl_body) +
+				  pfncurr * sizeof(u64);
+			msgbody = kzalloc(msgsize, GFP_KERNEL);
+
+			if (!msgbody) {
+				struct vmbus_channel_msginfo *pos = NULL;
+				struct vmbus_channel_msginfo *tmp = NULL;
+				/*
+				 * Free up all the allocated messages.
+				 */
+				list_for_each_entry_safe(pos, tmp,
+					&msgheader->submsglist,
+					msglistentry) {
+
+					list_del(&pos->msglistentry);
+					kfree(pos);
+				}
+
+				goto nomem;
+			}
+
+			msgbody->msgsize = msgsize;
+			(*messagecount)++;
+			gpadl_body =
+				(struct vmbus_channel_gpadl_body *)msgbody->msg;
+
+			/*
+			 * Gpadl is u32 and we are using a pointer which could
+			 * be 64-bit
+			 * This is governed by the guest/host protocol and
+			 * so the hypervisor gurantees that this is ok.
+			 */
+			for (i = 0; i < pfncurr; i++)
+				gpadl_body->pfn[i] = pfn + pfnsum + i;
+
+			/* add to msg header */
+			list_add_tail(&msgbody->msglistentry,
+				      &msgheader->submsglist);
+			pfnsum += pfncurr;
+			pfnleft -= pfncurr;
+		}
+	} else {
+		/* everything fits in a header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
+		msgheader = kzalloc(msgsize, GFP_KERNEL);
+		if (msgheader == NULL)
+			goto nomem;
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pagecount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+
+		*msginfo = msgheader;
+		*messagecount = 1;
+	}
+
+	return 0;
+nomem:
+	kfree(msgheader);
+	kfree(msgbody);
+	return -ENOMEM;
+}
+
+/*
+ * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
+ *
+ * @channel: a channel
+ * @kbuffer: from kmalloc
+ * @size: page-size multiple
+ * @gpadl_handle: some funky thing
+ */
+int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
+			       u32 size, u32 *gpadl_handle)
+{
+	struct vmbus_channel_gpadl_header *gpadlmsg;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_msginfo *submsginfo;
+	u32 msgcount;
+	struct list_head *curr;
+	u32 next_gpadl_handle;
+	unsigned long flags;
+	int ret = 0;
+	int t;
+
+	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
+	atomic_inc(&vmbus_connection.next_gpadl_handle);
+
+	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
+	if (ret)
+		return ret;
+
+	init_completion(&msginfo->waitevent);
+
+	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
+	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
+	gpadlmsg->child_relid = channel->offermsg.child_relid;
+	gpadlmsg->gpadl = next_gpadl_handle;
+
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+			       sizeof(*msginfo));
+	if (ret != 0)
+		goto cleanup;
+
+	if (msgcount > 1) {
+		list_for_each(curr, &msginfo->submsglist) {
+
+			submsginfo = (struct vmbus_channel_msginfo *)curr;
+			gpadl_body =
+			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
+
+			gpadl_body->header.msgtype =
+				CHANNELMSG_GPADL_BODY;
+			gpadl_body->gpadl = next_gpadl_handle;
+
+			ret = vmbus_post_msg(gpadl_body,
+					       submsginfo->msgsize -
+					       sizeof(*submsginfo));
+			if (ret != 0)
+				goto cleanup;
+
+		}
+	}
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+
+	/* At this point, we received the gpadl created msg */
+	*gpadl_handle = gpadlmsg->gpadl;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(msginfo);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
+
+/*
+ * vmbus_teardown_gpadl -Teardown the specified GPADL handle
+ */
+int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+{
+	struct vmbus_channel_gpadl_teardown *msg;
+	struct vmbus_channel_msginfo *info;
+	unsigned long flags;
+	int ret, t;
+
+	info = kmalloc(sizeof(*info) +
+		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	init_completion(&info->waitevent);
+
+	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
+
+	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
+	msg->child_relid = channel->offermsg.child_relid;
+	msg->gpadl = gpadl_handle;
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&info->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_gpadl_teardown));
+
+	BUG_ON(ret != 0);
+	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+	/* Received a torndown response */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(info);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+
+/*
+ * vmbus_close - Close the specified channel
+ */
+void vmbus_close(struct vmbus_channel *channel)
+{
+	struct vmbus_channel_close_channel *msg;
+	int ret;
+	unsigned long flags;
+
+	/* Stop callback and cancel the timer asap */
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+	channel->onchannel_callback = NULL;
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+
+	/* Send a closing message */
+
+	msg = &channel->close_msg.msg;
+
+	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
+	msg->child_relid = channel->offermsg.child_relid;
+
+	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
+
+	BUG_ON(ret != 0);
+	/* Tear down the gpadl for the channel's ring buffer */
+	if (channel->ringbuffer_gpadlhandle)
+		vmbus_teardown_gpadl(channel,
+					  channel->ringbuffer_gpadlhandle);
+
+	/* Cleanup the ring buffers for this channel */
+	hv_ringbuffer_cleanup(&channel->outbound);
+	hv_ringbuffer_cleanup(&channel->inbound);
+
+	free_pages((unsigned long)channel->ringbuffer_pages,
+		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
+
+
+}
+EXPORT_SYMBOL_GPL(vmbus_close);
+
+/**
+ * vmbus_sendpacket() - Send the specified buffer on the given channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @requestid: Identifier of the request
+ * @type: Type of packet that is being send e.g. negotiate, time
+ * packet etc.
+ *
+ * Sends data in @buffer directly to hyper-v via the vmbus
+ * This will send the data unparsed to hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
+			   u32 bufferlen, u64 requestid,
+			   enum vmbus_packet_type type, u32 flags)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
+	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	int ret;
+
+
+	/* Setup the descriptor */
+	desc.type = type; /* VmbusPacketTypeDataInBand; */
+	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
+	/* in 8-bytes granularity */
+	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
+	desc.len8 = (u16)(packetlen_aligned >> 3);
+	desc.trans_id = requestid;
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		   packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL(vmbus_sendpacket);
+
+/*
+ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+				     struct hv_page_buffer pagebuffers[],
+				     u32 pagecount, void *buffer, u32 bufferlen,
+				     u64 requestid)
+{
+	int ret;
+	int i;
+	struct vmbus_channel_packet_page_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+
+	if (pagecount > MAX_PAGE_BUFFER_COUNT)
+		return -EINVAL;
+
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
+	 * largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
+			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
+			  sizeof(struct hv_page_buffer));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = pagecount;
+
+	for (i = 0; i < pagecount; i++) {
+		desc.range[i].len = pagebuffers[i].len;
+		desc.range[i].offset = pagebuffers[i].offset;
+		desc.range[i].pfn	 = pagebuffers[i].pfn;
+	}
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
+
+/*
+ * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
+ * using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
+				struct hv_multipage_buffer *multi_pagebuffer,
+				void *buffer, u32 bufferlen, u64 requestid)
+{
+	int ret;
+	struct vmbus_channel_packet_multipage_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
+					 multi_pagebuffer->len);
+
+
+	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
+		return -EINVAL;
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
+	 * the largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
+			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
+			  sizeof(u64));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = 1;
+
+	desc.range.len = multi_pagebuffer->len;
+	desc.range.offset = multi_pagebuffer->offset;
+
+	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
+	       pfncount * sizeof(u64));
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
+
+/**
+ * vmbus_recvpacket() - Retrieve the user packet on the specified channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @buffer_actual_len: The actual size of the data after it was received
+ * @requestid: Identifier of the request
+ *
+ * Receives directly from the hyper-v vmbus and puts the data it received
+ * into Buffer. This will receive the data unparsed from hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
+			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0)
+		return 0;
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = userlen;
+
+	if (userlen > bufferlen) {
+
+		pr_err("Buffer too small - got %d needs %d\n",
+			   bufferlen, userlen);
+		return -ETOOSMALL;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
+			     (desc.offset8 << 3));
+
+
+	return 0;
+}
+EXPORT_SYMBOL(vmbus_recvpacket);
+
+/*
+ * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
+ */
+int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
+			      u32 bufferlen, u32 *buffer_actual_len,
+			      u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0)
+		return 0;
+
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = packetlen;
+
+	if (packetlen > bufferlen) {
+		pr_err("Buffer too small - needed %d bytes but "
+			"got space for only %d bytes\n",
+			packetlen, bufferlen);
+		return -ENOBUFS;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the entire packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff -druNp linux-libre-3.1-gnu1/drivers/hv/channel_mgmt.c linux-libre-3.2-gnu1/drivers/hv/channel_mgmt.c
--- linux-libre-3.1-gnu1/drivers/hv/channel_mgmt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/channel_mgmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,646 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+struct vmbus_channel_message_table_entry {
+	enum vmbus_channel_message_type message_type;
+	void (*message_handler)(struct vmbus_channel_message_header *msg);
+};
+
+#define MAX_MSG_TYPES                    4
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
+
+static const uuid_le
+	supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
+	/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+	/* Storage - SCSI */
+	{
+		.b  = {
+			0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
+			0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
+		}
+	},
+
+	/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
+	/* Network */
+	{
+		.b = {
+			0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
+			0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
+		}
+	},
+
+	/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
+	/* Input */
+	{
+		.b = {
+			0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
+			0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
+		}
+	},
+
+	/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
+	/* IDE */
+	{
+		.b = {
+			0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
+			0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
+		}
+	},
+	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
+	/* Shutdown */
+	{
+		.b = {
+			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
+		}
+	},
+	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+	/* TimeSync */
+	{
+		.b = {
+			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+		}
+	},
+	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
+	/* Heartbeat */
+	{
+		.b = {
+			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
+		}
+	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.b = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+	}
+	},
+
+};
+
+
+/**
+ * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
+ * @icmsghdrp: Pointer to msg header structure
+ * @icmsg_negotiate: Pointer to negotiate message structure
+ * @buf: Raw buffer channel data
+ *
+ * @icmsghdrp is of type &struct icmsg_hdr.
+ * @negop is of type &struct icmsg_negotiate.
+ * Set up and fill in default negotiate response message. This response can
+ * come from both the vmbus driver and the hv_utils driver. The current api
+ * will respond properly to both Windows 2008 and Windows 2008-R2 operating
+ * systems.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+			       struct icmsg_negotiate *negop, u8 *buf)
+{
+	if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+		icmsghdrp->icmsgsize = 0x10;
+
+		negop = (struct icmsg_negotiate *)&buf[
+			sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+
+		if (negop->icframe_vercnt == 2 &&
+		   negop->icversion_data[1].major == 3) {
+			negop->icversion_data[0].major = 3;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 3;
+			negop->icversion_data[1].minor = 0;
+		} else {
+			negop->icversion_data[0].major = 1;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 1;
+			negop->icversion_data[1].minor = 0;
+		}
+
+		negop->icframe_vercnt = 1;
+		negop->icmsg_vercnt = 1;
+	}
+}
+EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
+
+/*
+ * alloc_channel - Allocate and initialize a vmbus channel object
+ */
+static struct vmbus_channel *alloc_channel(void)
+{
+	struct vmbus_channel *channel;
+
+	channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
+	if (!channel)
+		return NULL;
+
+	spin_lock_init(&channel->inbound_lock);
+
+	channel->controlwq = create_workqueue("hv_vmbus_ctl");
+	if (!channel->controlwq) {
+		kfree(channel);
+		return NULL;
+	}
+
+	return channel;
+}
+
+/*
+ * release_hannel - Release the vmbus channel object itself
+ */
+static void release_channel(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	destroy_workqueue(channel->controlwq);
+
+	kfree(channel);
+}
+
+/*
+ * free_channel - Release the resources used by the vmbus channel object
+ */
+static void free_channel(struct vmbus_channel *channel)
+{
+
+	/*
+	 * We have to release the channel's workqueue/thread in the vmbus's
+	 * workqueue/thread context
+	 * ie we can't destroy ourselves.
+	 */
+	INIT_WORK(&channel->work, release_channel);
+	queue_work(vmbus_connection.work_queue, &channel->work);
+}
+
+
+
+/*
+ * vmbus_process_rescind_offer -
+ * Rescind the offer by initiating a device removal
+ */
+static void vmbus_process_rescind_offer(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	vmbus_device_unregister(channel->device_obj);
+}
+
+/*
+ * vmbus_process_offer - Process the offer by creating a channel/device
+ * associated with this offer
+ */
+static void vmbus_process_offer(struct work_struct *work)
+{
+	struct vmbus_channel *newchannel = container_of(work,
+							struct vmbus_channel,
+							work);
+	struct vmbus_channel *channel;
+	bool fnew = true;
+	int ret;
+	unsigned long flags;
+
+	/* The next possible work is rescind handling */
+	INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
+
+	/* Make sure this is a new offer */
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+			newchannel->offermsg.offer.if_type) &&
+			!uuid_le_cmp(channel->offermsg.offer.if_instance,
+				newchannel->offermsg.offer.if_instance)) {
+			fnew = false;
+			break;
+		}
+	}
+
+	if (fnew)
+		list_add_tail(&newchannel->listentry,
+			      &vmbus_connection.chn_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	if (!fnew) {
+		free_channel(newchannel);
+		return;
+	}
+
+	/*
+	 * Start the process of binding this offer to the driver
+	 * We need to set the DeviceObject field before calling
+	 * vmbus_child_dev_add()
+	 */
+	newchannel->device_obj = vmbus_device_create(
+		&newchannel->offermsg.offer.if_type,
+		&newchannel->offermsg.offer.if_instance,
+		newchannel);
+
+	/*
+	 * Add the new device to the bus. This will kick off device-driver
+	 * binding which eventually invokes the device driver's AddDevice()
+	 * method.
+	 */
+	ret = vmbus_device_register(newchannel->device_obj);
+	if (ret != 0) {
+		pr_err("unable to add child device object (relid %d)\n",
+			   newchannel->offermsg.child_relid);
+
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+		list_del(&newchannel->listentry);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+		free_channel(newchannel);
+	} else {
+		/*
+		 * This state is used to indicate a successful open
+		 * so that when we do close the channel normally, we
+		 * can cleanup properly
+		 */
+		newchannel->state = CHANNEL_OPEN_STATE;
+	}
+}
+
+/*
+ * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
+ *
+ */
+static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_offer_channel *offer;
+	struct vmbus_channel *newchannel;
+	uuid_le *guidtype;
+	uuid_le *guidinstance;
+	int i;
+	int fsupported = 0;
+
+	offer = (struct vmbus_channel_offer_channel *)hdr;
+	for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
+		if (!uuid_le_cmp(offer->offer.if_type,
+				supported_device_classes[i])) {
+			fsupported = 1;
+			break;
+		}
+	}
+
+	if (!fsupported)
+		return;
+
+	guidtype = &offer->offer.if_type;
+	guidinstance = &offer->offer.if_instance;
+
+	/* Allocate the channel object and save this offer. */
+	newchannel = alloc_channel();
+	if (!newchannel) {
+		pr_err("Unable to allocate channel object\n");
+		return;
+	}
+
+	memcpy(&newchannel->offermsg, offer,
+	       sizeof(struct vmbus_channel_offer_channel));
+	newchannel->monitor_grp = (u8)offer->monitorid / 32;
+	newchannel->monitor_bit = (u8)offer->monitorid % 32;
+
+	INIT_WORK(&newchannel->work, vmbus_process_offer);
+	queue_work(newchannel->controlwq, &newchannel->work);
+}
+
+/*
+ * vmbus_onoffer_rescind - Rescind offer handler.
+ *
+ * We queue a work item to process this offer synchronously
+ */
+static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_rescind_offer *rescind;
+	struct vmbus_channel *channel;
+
+	rescind = (struct vmbus_channel_rescind_offer *)hdr;
+	channel = relid2channel(rescind->child_relid);
+
+	if (channel == NULL)
+		/* Just return here, no channel found */
+		return;
+
+	/* work is initialized for vmbus_process_rescind_offer() from
+	 * vmbus_process_offer() where the channel got created */
+	queue_work(channel->controlwq, &channel->work);
+}
+
+/*
+ * vmbus_onoffers_delivered -
+ * This is invoked when all offers have been delivered.
+ *
+ * Nothing to do here.
+ */
+static void vmbus_onoffers_delivered(
+			struct vmbus_channel_message_header *hdr)
+{
+}
+
+/*
+ * vmbus_onopen_result - Open result handler.
+ *
+ * This is invoked when we received a response to our channel open request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_open_result *result;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_open_channel *openmsg;
+	unsigned long flags;
+
+	result = (struct vmbus_channel_open_result *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) {
+			openmsg =
+			(struct vmbus_channel_open_channel *)msginfo->msg;
+			if (openmsg->child_relid == result->child_relid &&
+			    openmsg->openid == result->openid) {
+				memcpy(&msginfo->response.open_result,
+				       result,
+				       sizeof(
+					struct vmbus_channel_open_result));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_created - GPADL created handler.
+ *
+ * This is invoked when we received a response to our gpadl create request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_created *gpadlcreated;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_header *gpadlheader;
+	unsigned long flags;
+
+	gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr;
+
+	/*
+	 * Find the establish msg, copy the result and signal/unblock the wait
+	 * event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) {
+			gpadlheader =
+			(struct vmbus_channel_gpadl_header *)requestheader;
+
+			if ((gpadlcreated->child_relid ==
+			     gpadlheader->child_relid) &&
+			    (gpadlcreated->gpadl == gpadlheader->gpadl)) {
+				memcpy(&msginfo->response.gpadl_created,
+				       gpadlcreated,
+				       sizeof(
+					struct vmbus_channel_gpadl_created));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_torndown - GPADL torndown handler.
+ *
+ * This is invoked when we received a response to our gpadl teardown request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_torndown(
+			struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_torndown *gpadl_torndown;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_teardown *gpadl_teardown;
+	unsigned long flags;
+
+	gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) {
+			gpadl_teardown =
+			(struct vmbus_channel_gpadl_teardown *)requestheader;
+
+			if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) {
+				memcpy(&msginfo->response.gpadl_torndown,
+				       gpadl_torndown,
+				       sizeof(
+					struct vmbus_channel_gpadl_torndown));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_onversion_response - Version response handler
+ *
+ * This is invoked when we received a response to our initiate contact request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onversion_response(
+		struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_initiate_contact *initiate;
+	struct vmbus_channel_version_response *version_response;
+	unsigned long flags;
+
+	version_response = (struct vmbus_channel_version_response *)hdr;
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype ==
+		    CHANNELMSG_INITIATE_CONTACT) {
+			initiate =
+			(struct vmbus_channel_initiate_contact *)requestheader;
+			memcpy(&msginfo->response.version_response,
+			      version_response,
+			      sizeof(struct vmbus_channel_version_response));
+			complete(&msginfo->waitevent);
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/* Channel message dispatch table */
+static struct vmbus_channel_message_table_entry
+	channel_message_table[CHANNELMSG_COUNT] = {
+	{CHANNELMSG_INVALID,			NULL},
+	{CHANNELMSG_OFFERCHANNEL,		vmbus_onoffer},
+	{CHANNELMSG_RESCIND_CHANNELOFFER,	vmbus_onoffer_rescind},
+	{CHANNELMSG_REQUESTOFFERS,		NULL},
+	{CHANNELMSG_ALLOFFERS_DELIVERED,	vmbus_onoffers_delivered},
+	{CHANNELMSG_OPENCHANNEL,		NULL},
+	{CHANNELMSG_OPENCHANNEL_RESULT,	vmbus_onopen_result},
+	{CHANNELMSG_CLOSECHANNEL,		NULL},
+	{CHANNELMSG_GPADL_HEADER,		NULL},
+	{CHANNELMSG_GPADL_BODY,		NULL},
+	{CHANNELMSG_GPADL_CREATED,		vmbus_ongpadl_created},
+	{CHANNELMSG_GPADL_TEARDOWN,		NULL},
+	{CHANNELMSG_GPADL_TORNDOWN,		vmbus_ongpadl_torndown},
+	{CHANNELMSG_RELID_RELEASED,		NULL},
+	{CHANNELMSG_INITIATE_CONTACT,		NULL},
+	{CHANNELMSG_VERSION_RESPONSE,		vmbus_onversion_response},
+	{CHANNELMSG_UNLOAD,			NULL},
+};
+
+/*
+ * vmbus_onmessage - Handler for channel protocol messages.
+ *
+ * This is invoked in the vmbus worker thread context.
+ */
+void vmbus_onmessage(void *context)
+{
+	struct hv_message *msg = context;
+	struct vmbus_channel_message_header *hdr;
+	int size;
+
+	hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+	size = msg->header.payload_size;
+
+	if (hdr->msgtype >= CHANNELMSG_COUNT) {
+		pr_err("Received invalid channel message type %d size %d\n",
+			   hdr->msgtype, size);
+		print_hex_dump_bytes("", DUMP_PREFIX_NONE,
+				     (unsigned char *)msg->u.payload, size);
+		return;
+	}
+
+	if (channel_message_table[hdr->msgtype].message_handler)
+		channel_message_table[hdr->msgtype].message_handler(hdr);
+	else
+		pr_err("Unhandled channel message type %d\n", hdr->msgtype);
+}
+
+/*
+ * vmbus_request_offers - Send a request to get all our pending offers.
+ */
+int vmbus_request_offers(void)
+{
+	struct vmbus_channel_message_header *msg;
+	struct vmbus_channel_msginfo *msginfo;
+	int ret, t;
+
+	msginfo = kmalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_message_header),
+			  GFP_KERNEL);
+	if (!msginfo)
+		return -ENOMEM;
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_message_header *)msginfo->msg;
+
+	msg->msgtype = CHANNELMSG_REQUESTOFFERS;
+
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_message_header));
+	if (ret != 0) {
+		pr_err("Unable to request offers - %d\n", ret);
+
+		goto cleanup;
+	}
+
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+
+
+cleanup:
+	kfree(msginfo);
+
+	return ret;
+}
+
+/* eof */
diff -druNp linux-libre-3.1-gnu1/drivers/hv/connection.c linux-libre-3.2-gnu1/drivers/hv/connection.c
--- linux-libre-3.1-gnu1/drivers/hv/connection.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/connection.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,318 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+
+struct vmbus_connection vmbus_connection = {
+	.conn_state		= DISCONNECTED,
+	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
+};
+
+/*
+ * vmbus_connect - Sends a connect request on the partition service connection
+ */
+int vmbus_connect(void)
+{
+	int ret = 0;
+	int t;
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_initiate_contact *msg;
+	unsigned long flags;
+
+	/* Initialize the vmbus connection */
+	vmbus_connection.conn_state = CONNECTING;
+	vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
+	if (!vmbus_connection.work_queue) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
+	spin_lock_init(&vmbus_connection.channelmsg_lock);
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_list);
+	spin_lock_init(&vmbus_connection.channel_lock);
+
+	/*
+	 * Setup the vmbus event connection for channel interrupt
+	 * abstraction stuff
+	 */
+	vmbus_connection.int_page =
+	(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
+	if (vmbus_connection.int_page == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	vmbus_connection.recv_int_page = vmbus_connection.int_page;
+	vmbus_connection.send_int_page =
+		(void *)((unsigned long)vmbus_connection.int_page +
+			(PAGE_SIZE >> 1));
+
+	/*
+	 * Setup the monitor notification facility. The 1st page for
+	 * parent->child and the 2nd page for child->parent
+	 */
+	vmbus_connection.monitor_pages =
+	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
+	if (vmbus_connection.monitor_pages == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	msginfo = kzalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_initiate_contact),
+			  GFP_KERNEL);
+	if (msginfo == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
+
+	msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
+	msg->vmbus_version_requested = VMBUS_REVISION_NUMBER;
+	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
+	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
+	msg->monitor_page2 = virt_to_phys(
+			(void *)((unsigned long)vmbus_connection.monitor_pages +
+				 PAGE_SIZE));
+
+	/*
+	 * Add to list before we send the request since we may
+	 * receive the response before returning from this routine
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_initiate_contact));
+	if (ret != 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		goto cleanup;
+	}
+
+	/* Wait for the connection response */
+	t =  wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	if (t == 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
+				flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	/* Check if successful */
+	if (msginfo->response.version_response.version_supported) {
+		vmbus_connection.conn_state = CONNECTED;
+	} else {
+		pr_err("Unable to connect, "
+			"Version %d not supported by Hyper-V\n",
+			VMBUS_REVISION_NUMBER);
+		ret = -ECONNREFUSED;
+		goto cleanup;
+	}
+
+	kfree(msginfo);
+	return 0;
+
+cleanup:
+	vmbus_connection.conn_state = DISCONNECTED;
+
+	if (vmbus_connection.work_queue)
+		destroy_workqueue(vmbus_connection.work_queue);
+
+	if (vmbus_connection.int_page) {
+		free_pages((unsigned long)vmbus_connection.int_page, 0);
+		vmbus_connection.int_page = NULL;
+	}
+
+	if (vmbus_connection.monitor_pages) {
+		free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
+		vmbus_connection.monitor_pages = NULL;
+	}
+
+	kfree(msginfo);
+
+	return ret;
+}
+
+
+/*
+ * relid2channel - Get the channel object given its
+ * child relative id (ie channel id)
+ */
+struct vmbus_channel *relid2channel(u32 relid)
+{
+	struct vmbus_channel *channel;
+	struct vmbus_channel *found_channel  = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (channel->offermsg.child_relid == relid) {
+			found_channel = channel;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	return found_channel;
+}
+
+/*
+ * process_chn_event - Process a channel event notification
+ */
+static void process_chn_event(u32 relid)
+{
+	struct vmbus_channel *channel;
+	unsigned long flags;
+
+	/*
+	 * Find the channel based on this relid and invokes the
+	 * channel callback to process the event
+	 */
+	channel = relid2channel(relid);
+
+	if (!channel) {
+		pr_err("channel not found for relid - %u\n", relid);
+		return;
+	}
+
+	/*
+	 * A channel once created is persistent even when there
+	 * is no driver handling the device. An unloading driver
+	 * sets the onchannel_callback to NULL under the
+	 * protection of the channel inbound_lock. Thus, checking
+	 * and invoking the driver specific callback takes care of
+	 * orderly unloading of the driver.
+	 */
+
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+	if (channel->onchannel_callback != NULL)
+		channel->onchannel_callback(channel->channel_callback_context);
+	else
+		pr_err("no channel callback for relid - %u\n", relid);
+
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+}
+
+/*
+ * vmbus_on_event - Handler for events
+ */
+void vmbus_on_event(unsigned long data)
+{
+	u32 dword;
+	u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
+	int bit;
+	u32 relid;
+	u32 *recv_int_page = vmbus_connection.recv_int_page;
+
+	/* Check events */
+	if (!recv_int_page)
+		return;
+	for (dword = 0; dword < maxdword; dword++) {
+		if (!recv_int_page[dword])
+			continue;
+		for (bit = 0; bit < 32; bit++) {
+			if (sync_test_and_clear_bit(bit,
+				(unsigned long *)&recv_int_page[dword])) {
+				relid = (dword << 5) + bit;
+
+				if (relid == 0)
+					/*
+					 * Special case - vmbus
+					 * channel protocol msg
+					 */
+					continue;
+
+				process_chn_event(relid);
+			}
+		}
+	}
+}
+
+/*
+ * vmbus_post_msg - Send a msg on the vmbus's message connection
+ */
+int vmbus_post_msg(void *buffer, size_t buflen)
+{
+	union hv_connection_id conn_id;
+	int ret = 0;
+	int retries = 0;
+
+	conn_id.asu32 = 0;
+	conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
+
+	/*
+	 * hv_post_message() can have transient failures because of
+	 * insufficient resources. Retry the operation a couple of
+	 * times before giving up.
+	 */
+	while (retries < 3) {
+		ret =  hv_post_message(conn_id, 1, buffer, buflen);
+		if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
+			return ret;
+		retries++;
+		msleep(100);
+	}
+	return ret;
+}
+
+/*
+ * vmbus_set_event - Send an event notification to the parent
+ */
+int vmbus_set_event(u32 child_relid)
+{
+	/* Each u32 represents 32 channels */
+	sync_set_bit(child_relid & 31,
+		(unsigned long *)vmbus_connection.send_int_page +
+		(child_relid >> 5));
+
+	return hv_signal_event();
+}
diff -druNp linux-libre-3.1-gnu1/drivers/hv/hv.c linux-libre-3.2-gnu1/drivers/hv/hv.c
--- linux-libre-3.1-gnu1/drivers/hv/hv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/hv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+/* The one and only */
+struct hv_context hv_context = {
+	.synic_initialized	= false,
+	.hypercall_page		= NULL,
+	.signal_event_param	= NULL,
+	.signal_event_buffer	= NULL,
+};
+
+/*
+ * query_hypervisor_presence
+ * - Query the cpuid for presence of windows hypervisor
+ */
+static int query_hypervisor_presence(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int op;
+
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VERSION_FEATURES;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return ecx & HV_PRESENT_BIT;
+}
+
+/*
+ * query_hypervisor_info - Get version info of the windows hypervisor
+ */
+static int query_hypervisor_info(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int max_leaf;
+	unsigned int op;
+
+	/*
+	* Its assumed that this is called after confirming that Viridian
+	* is present. Query id and revision.
+	*/
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VENDOR_MAXFUNCTION;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	max_leaf = eax;
+
+	if (max_leaf >= HVCPUID_VERSION) {
+		eax = 0;
+		ebx = 0;
+		ecx = 0;
+		edx = 0;
+		op = HVCPUID_VERSION;
+		cpuid(op, &eax, &ebx, &ecx, &edx);
+		pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n",
+			    eax,
+			    ebx >> 16,
+			    ebx & 0xFFFF,
+			    ecx,
+			    edx >> 24,
+			    edx & 0xFFFFFF);
+	}
+	return max_leaf;
+}
+
+/*
+ * do_hypercall- Invoke the specified hypercall
+ */
+static u64 do_hypercall(u64 control, void *input, void *output)
+{
+#ifdef CONFIG_X86_64
+	u64 hv_status = 0;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
+	__asm__ __volatile__("call *%3" : "=a" (hv_status) :
+			     "c" (control), "d" (input_address),
+			     "m" (hypercall_page));
+
+	return hv_status;
+
+#else
+
+	u32 control_hi = control >> 32;
+	u32 control_lo = control & 0xFFFFFFFF;
+	u32 hv_status_hi = 1;
+	u32 hv_status_lo = 1;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u32 input_address_hi = input_address >> 32;
+	u32 input_address_lo = input_address & 0xFFFFFFFF;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	u32 output_address_hi = output_address >> 32;
+	u32 output_address_lo = output_address & 0xFFFFFFFF;
+	void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
+			      "=a"(hv_status_lo) : "d" (control_hi),
+			      "a" (control_lo), "b" (input_address_hi),
+			      "c" (input_address_lo), "D"(output_address_hi),
+			      "S"(output_address_lo), "m" (hypercall_page));
+
+	return hv_status_lo | ((u64)hv_status_hi << 32);
+#endif /* !x86_64 */
+}
+
+/*
+ * hv_init - Main initialization routine.
+ *
+ * This routine must be called before any other routines in here are called
+ */
+int hv_init(void)
+{
+	int max_leaf;
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+	void *virtaddr = NULL;
+
+	memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS);
+	memset(hv_context.synic_message_page, 0,
+	       sizeof(void *) * MAX_NUM_CPUS);
+
+	if (!query_hypervisor_presence())
+		goto cleanup;
+
+	max_leaf = query_hypervisor_info();
+
+	rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
+
+	if (hv_context.guestid != 0)
+		goto cleanup;
+
+	/* Write our OS info */
+	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+	hv_context.guestid = HV_LINUX_GUEST_ID;
+
+	/* See if the hypercall page is already set */
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
+
+	if (!virtaddr)
+		goto cleanup;
+
+	hypercall_msr.enable = 1;
+
+	hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr);
+	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	/* Confirm that hypercall page did get setup. */
+	hypercall_msr.as_uint64 = 0;
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	if (!hypercall_msr.enable)
+		goto cleanup;
+
+	hv_context.hypercall_page = virtaddr;
+
+	/* Setup the global signal event param for the signal event hypercall */
+	hv_context.signal_event_buffer =
+			kmalloc(sizeof(struct hv_input_signal_event_buffer),
+				GFP_KERNEL);
+	if (!hv_context.signal_event_buffer)
+		goto cleanup;
+
+	hv_context.signal_event_param =
+		(struct hv_input_signal_event *)
+			(ALIGN((unsigned long)
+				  hv_context.signal_event_buffer,
+				  HV_HYPERCALL_PARAM_ALIGN));
+	hv_context.signal_event_param->connectionid.asu32 = 0;
+	hv_context.signal_event_param->connectionid.u.id =
+						VMBUS_EVENT_CONNECTION_ID;
+	hv_context.signal_event_param->flag_number = 0;
+	hv_context.signal_event_param->rsvdz = 0;
+
+	return 0;
+
+cleanup:
+	if (virtaddr) {
+		if (hypercall_msr.enable) {
+			hypercall_msr.as_uint64 = 0;
+			wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		}
+
+		vfree(virtaddr);
+	}
+
+	return -ENOTSUPP;
+}
+
+/*
+ * hv_cleanup - Cleanup routine.
+ *
+ * This routine is called normally during driver unloading or exiting.
+ */
+void hv_cleanup(void)
+{
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+
+	kfree(hv_context.signal_event_buffer);
+	hv_context.signal_event_buffer = NULL;
+	hv_context.signal_event_param = NULL;
+
+	if (hv_context.hypercall_page) {
+		hypercall_msr.as_uint64 = 0;
+		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		vfree(hv_context.hypercall_page);
+		hv_context.hypercall_page = NULL;
+	}
+}
+
+/*
+ * hv_post_message - Post a message using the hypervisor message IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_post_message(union hv_connection_id connection_id,
+		  enum hv_message_type message_type,
+		  void *payload, size_t payload_size)
+{
+	struct aligned_input {
+		u64 alignment8;
+		struct hv_input_post_message msg;
+	};
+
+	struct hv_input_post_message *aligned_msg;
+	u16 status;
+	unsigned long addr;
+
+	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
+		return -EMSGSIZE;
+
+	addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
+	if (!addr)
+		return -ENOMEM;
+
+	aligned_msg = (struct hv_input_post_message *)
+			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
+
+	aligned_msg->connectionid = connection_id;
+	aligned_msg->message_type = message_type;
+	aligned_msg->payload_size = payload_size;
+	memcpy((void *)aligned_msg->payload, payload, payload_size);
+
+	status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
+		& 0xFFFF;
+
+	kfree((void *)addr);
+
+	return status;
+}
+
+
+/*
+ * hv_signal_event -
+ * Signal an event on the specified connection using the hypervisor event IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_signal_event(void)
+{
+	u16 status;
+
+	status = do_hypercall(HVCALL_SIGNAL_EVENT,
+			       hv_context.signal_event_param,
+			       NULL) & 0xFFFF;
+	return status;
+}
+
+/*
+ * hv_synic_init - Initialize the Synthethic Interrupt Controller.
+ *
+ * If it is already initialized by another entity (ie x2v shim), we need to
+ * retrieve the initialized message and event pages.  Otherwise, we create and
+ * initialize the message and event pages.
+ */
+void hv_synic_init(void *irqarg)
+{
+	u64 version;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	union hv_synic_sint shared_sint;
+	union hv_synic_scontrol sctrl;
+
+	u32 irq_vector = *((u32 *)(irqarg));
+	int cpu = smp_processor_id();
+
+	if (!hv_context.hypercall_page)
+		return;
+
+	/* Check the version */
+	rdmsrl(HV_X64_MSR_SVERSION, version);
+
+	hv_context.synic_message_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_message_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC message page\n");
+		goto cleanup;
+	}
+
+	hv_context.synic_event_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_event_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC event page\n");
+		goto cleanup;
+	}
+
+	/* Setup the Synic's message page */
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 1;
+	simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	/* Setup the Synic's event page */
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 1;
+	siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	/* Setup the shared SINT. */
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.as_uint64 = 0;
+	shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
+	shared_sint.masked = false;
+	shared_sint.auto_eoi = false;
+
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	/* Enable the global synic bit */
+	rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+	sctrl.enable = 1;
+
+	wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+
+	hv_context.synic_initialized = true;
+	return;
+
+cleanup:
+	if (hv_context.synic_event_page[cpu])
+		free_page((unsigned long)hv_context.synic_event_page[cpu]);
+
+	if (hv_context.synic_message_page[cpu])
+		free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	return;
+}
+
+/*
+ * hv_synic_cleanup - Cleanup routine for hv_synic_init().
+ */
+void hv_synic_cleanup(void *arg)
+{
+	union hv_synic_sint shared_sint;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	int cpu = smp_processor_id();
+
+	if (!hv_context.synic_initialized)
+		return;
+
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.masked = 1;
+
+	/* Need to correctly cleanup in the case of SMP!!! */
+	/* Disable the interrupt */
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 0;
+	simp.base_simp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 0;
+	siefp.base_siefp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	free_page((unsigned long)hv_context.synic_event_page[cpu]);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/hv/hv_kvp.c linux-libre-3.2-gnu1/drivers/hv/hv_kvp.c
--- linux-libre-3.1-gnu1/drivers/hv/hv_kvp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/hv_kvp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,339 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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 published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+#include <linux/hyperv.h>
+
+#include "hv_kvp.h"
+
+
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * Note that only one transaction can be active at any point in time.
+ *
+ * This state is set when we receive a request from the host; we
+ * cleanup this state when the transaction is completed - when we respond
+ * to the host with the key value.
+ */
+
+static struct {
+	bool active; /* transaction status - active or not */
+	int recv_len; /* number of bytes received. */
+	int index; /* current index */
+	struct vmbus_channel *recv_channel; /* chn we got the request */
+	u64 recv_req_id; /* request ID. */
+} kvp_transaction;
+
+static void kvp_send_key(struct work_struct *dummy);
+
+#define TIMEOUT_FIRED 1
+
+static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_work_func(struct work_struct *dummy);
+static void kvp_register(void);
+
+static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
+
+static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
+static const char kvp_name[] = "kvp_kernel_module";
+static u8 *recv_buffer;
+/*
+ * Register the kernel component with the user-level daemon.
+ * As part of this registration, pass the LIC version number.
+ */
+
+static void
+kvp_register(void)
+{
+
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_REGISTER;
+		strcpy(msg->data, HV_DRV_VERSION);
+		msg->len = strlen(HV_DRV_VERSION) + 1;
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+}
+static void
+kvp_work_func(struct work_struct *dummy)
+{
+	/*
+	 * If the timer fires, the user-mode component has not responded;
+	 * process the pending transaction.
+	 */
+	kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
+}
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct hv_ku_msg *message;
+
+	message = (struct hv_ku_msg *)msg->data;
+	if (msg->seq == KVP_REGISTER) {
+		pr_info("KVP: user-mode registering done.\n");
+		kvp_register();
+	}
+
+	if (msg->seq == KVP_USER_SET) {
+		/*
+		 * Complete the transaction by forwarding the key value
+		 * to the host. But first, cancel the timeout.
+		 */
+		if (cancel_delayed_work_sync(&kvp_work))
+			kvp_respond_to_host(message->kvp_key,
+						message->kvp_value,
+						!strlen(message->kvp_key));
+	}
+}
+
+static void
+kvp_send_key(struct work_struct *dummy)
+{
+	struct cn_msg *msg;
+	int index = kvp_transaction.index;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_KERNEL_GET;
+		((struct hv_ku_msg *)msg->data)->kvp_index = index;
+		msg->len = sizeof(struct hv_ku_msg);
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+	return;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+kvp_respond_to_host(char *key, char *value, int error)
+{
+	struct hv_kvp_msg  *kvp_msg;
+	struct hv_kvp_msg_enumerate  *kvp_data;
+	char	*key_name;
+	struct icmsg_hdr *icmsghdrp;
+	int	keylen, valuelen;
+	u32	buf_len;
+	struct vmbus_channel *channel;
+	u64	req_id;
+
+	/*
+	 * If a transaction is not active; log and return.
+	 */
+
+	if (!kvp_transaction.active) {
+		/*
+		 * This is a spurious call!
+		 */
+		pr_warn("KVP: Transaction not active\n");
+		return;
+	}
+	/*
+	 * Copy the global state for completing the transaction. Note that
+	 * only one transaction can be active at a time.
+	 */
+
+	buf_len = kvp_transaction.recv_len;
+	channel = kvp_transaction.recv_channel;
+	req_id = kvp_transaction.recv_req_id;
+
+	kvp_transaction.active = false;
+
+	if (channel->onchannel_callback == NULL)
+		/*
+		 * We have raced with util driver being unloaded;
+		 * silently return.
+		 */
+		return;
+
+	icmsghdrp = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+	kvp_msg = (struct hv_kvp_msg *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+	kvp_data = &kvp_msg->kvp_data;
+	key_name = key;
+
+	/*
+	 * If the error parameter is set, terminate the host's enumeration.
+	 */
+	if (error) {
+		/*
+		 * We don't support this index or the we have timedout;
+		 * terminate the host-side iteration by returning an error.
+		 */
+		icmsghdrp->status = HV_E_FAIL;
+		goto response_done;
+	}
+
+	/*
+	 * The windows host expects the key/value pair to be encoded
+	 * in utf16.
+	 */
+	keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+				(wchar_t *)kvp_data->data.key);
+	kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+	valuelen = utf8s_to_utf16s(value, strlen(value),
+				(wchar_t *)kvp_data->data.value);
+	kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+
+	kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+	icmsghdrp->status = HV_S_OK;
+
+response_done:
+	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+
+}
+
+/*
+ * This callback is invoked when we get a KVP message from the host.
+ * The host ensures that only one KVP transaction can be active at a time.
+ * KVP implementation in Linux needs to forward the key to a user-mde
+ * component to retrive the corresponding value. Consequently, we cannot
+ * respond to the host in the conext of this callback. Since the host
+ * guarantees that at most only one transaction can be active at a time,
+ * we stash away the transaction state in a set of global variables.
+ */
+
+void hv_kvp_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+
+	struct hv_kvp_msg *kvp_msg;
+	struct hv_kvp_msg_enumerate *kvp_data;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+		} else {
+			kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			kvp_data = &kvp_msg->kvp_data;
+
+			/*
+			 * We only support the "get" operation on
+			 * "KVP_POOL_AUTO" pool.
+			 */
+
+			if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
+				(kvp_msg->kvp_hdr.operation !=
+				KVP_OP_ENUMERATE)) {
+				icmsghdrp->status = HV_E_FAIL;
+				goto callback_done;
+			}
+
+			/*
+			 * Stash away this global state for completing the
+			 * transaction; note transactions are serialized.
+			 */
+			kvp_transaction.recv_len = recvlen;
+			kvp_transaction.recv_channel = channel;
+			kvp_transaction.recv_req_id = requestid;
+			kvp_transaction.active = true;
+			kvp_transaction.index = kvp_data->index;
+
+			/*
+			 * Get the information from the
+			 * user-mode component.
+			 * component. This transaction will be
+			 * completed when we get the value from
+			 * the user-mode component.
+			 * Set a timeout to deal with
+			 * user-mode not responding.
+			 */
+			schedule_work(&kvp_sendkey_work);
+			schedule_delayed_work(&kvp_work, 5*HZ);
+
+			return;
+
+		}
+
+callback_done:
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, recv_buffer,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+}
+
+int
+hv_kvp_init(struct hv_util_service *srv)
+{
+	int err;
+
+	err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
+	if (err)
+		return err;
+	recv_buffer = srv->recv_buffer;
+
+	return 0;
+}
+
+void hv_kvp_deinit(void)
+{
+	cn_del_callback(&kvp_id);
+	cancel_delayed_work_sync(&kvp_work);
+	cancel_work_sync(&kvp_sendkey_work);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/hv/hv_kvp.h linux-libre-3.2-gnu1/drivers/hv/hv_kvp.h
--- linux-libre-3.1-gnu1/drivers/hv/hv_kvp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/hv_kvp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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 published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef	_KVP_H
+#define	_KVP_H_
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note:  This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note:  This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatibility.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ *	Index		Key Name
+ *	0		FullyQualifiedDomainName
+ *	1		IntegrationServicesVersion
+ *	2		NetworkAddressIPv4
+ *	3		NetworkAddressIPv6
+ *	4		OSBuildNumber
+ *	5		OSName
+ *	6		OSMajorVersion
+ *	7		OSMinorVersion
+ *	8		OSVersion
+ *	9		ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+/*
+ *
+ * The following definitions are shared with the user-mode component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP user-mode component.
+ */
+
+#define CN_KVP_VAL             0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL       0x2 /* This supports queries from the user */
+
+enum hv_ku_op {
+	KVP_REGISTER = 0, /* Register the user mode component */
+	KVP_KERNEL_GET, /* Kernel is requesting the value */
+	KVP_KERNEL_SET, /* Kernel is providing the value */
+	KVP_USER_GET,  /* User is requesting the value */
+	KVP_USER_SET  /* User is providing the value */
+};
+
+struct hv_ku_msg {
+	__u32 kvp_index; /* Key index */
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+
+
+
+#ifdef __KERNEL__
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+
+enum hv_kvp_exchg_op {
+	KVP_OP_GET = 0,
+	KVP_OP_SET,
+	KVP_OP_DELETE,
+	KVP_OP_ENUMERATE,
+	KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+	KVP_POOL_EXTERNAL = 0,
+	KVP_POOL_GUEST,
+	KVP_POOL_AUTO,
+	KVP_POOL_AUTO_EXTERNAL,
+	KVP_POOL_AUTO_INTERNAL,
+	KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+struct hv_kvp_hdr {
+	u8 operation;
+	u8 pool;
+};
+
+struct hv_kvp_exchg_msg_value {
+	u32 value_type;
+	u32 key_size;
+	u32 value_size;
+	u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+	u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+};
+
+struct hv_kvp_msg_enumerate {
+	u32 index;
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg {
+	struct hv_kvp_hdr	kvp_hdr;
+	struct hv_kvp_msg_enumerate	kvp_data;
+};
+
+int hv_kvp_init(struct hv_util_service *);
+void hv_kvp_deinit(void);
+void hv_kvp_onchannelcallback(void *);
+
+#endif /* __KERNEL__ */
+#endif	/* _KVP_H */
+
diff -druNp linux-libre-3.1-gnu1/drivers/hv/hv_util.c linux-libre-3.2-gnu1/drivers/hv/hv_util.c
--- linux-libre-3.1-gnu1/drivers/hv/hv_util.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/hv_util.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/reboot.h>
+#include <linux/hyperv.h>
+
+#include "hv_kvp.h"
+
+
+static void shutdown_onchannelcallback(void *context);
+static struct hv_util_service util_shutdown = {
+	.util_cb = shutdown_onchannelcallback,
+};
+
+static void timesync_onchannelcallback(void *context);
+static struct hv_util_service util_timesynch = {
+	.util_cb = timesync_onchannelcallback,
+};
+
+static void heartbeat_onchannelcallback(void *context);
+static struct hv_util_service util_heartbeat = {
+	.util_cb = heartbeat_onchannelcallback,
+};
+
+static struct hv_util_service util_kvp = {
+	.util_cb = hv_kvp_onchannelcallback,
+	.util_init = hv_kvp_init,
+	.util_deinit = hv_kvp_deinit,
+};
+
+static void shutdown_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	u8  execute_shutdown = false;
+	u8  *shut_txf_buf = util_shutdown.recv_buffer;
+
+	struct shutdown_msg_data *shutdown_msg;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+	vmbus_recvpacket(channel, shut_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+		} else {
+			shutdown_msg =
+				(struct shutdown_msg_data *)&shut_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			switch (shutdown_msg->flags) {
+			case 0:
+			case 1:
+				icmsghdrp->status = HV_S_OK;
+				execute_shutdown = true;
+
+				pr_info("Shutdown request received -"
+					    " graceful shutdown initiated\n");
+				break;
+			default:
+				icmsghdrp->status = HV_E_FAIL;
+				execute_shutdown = false;
+
+				pr_info("Shutdown request received -"
+					    " Invalid request\n");
+				break;
+			}
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, shut_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+	if (execute_shutdown == true)
+		orderly_poweroff(true);
+}
+
+/*
+ * Set guest time to host UTC time.
+ */
+static inline void do_adj_guesttime(u64 hosttime)
+{
+	s64 host_tns;
+	struct timespec host_ts;
+
+	host_tns = (hosttime - WLTIMEDELTA) * 100;
+	host_ts = ns_to_timespec(host_tns);
+
+	do_settimeofday(&host_ts);
+}
+
+/*
+ * Set the host time in a process context.
+ */
+
+struct adj_time_work {
+	struct work_struct work;
+	u64	host_time;
+};
+
+static void hv_set_host_time(struct work_struct *work)
+{
+	struct adj_time_work	*wrk;
+
+	wrk = container_of(work, struct adj_time_work, work);
+	do_adj_guesttime(wrk->host_time);
+	kfree(wrk);
+}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ *
+ * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
+ * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
+ * message after the timesync channel is opened. Since the hv_utils module is
+ * loaded after hv_vmbus, the first message is usually missed. The other
+ * thing is, systime is automatically set to emulated hardware clock which may
+ * not be UTC time or in the same time zone. So, to override these effects, we
+ * use the first 50 time samples for initial system time setting.
+ */
+static inline void adj_guesttime(u64 hosttime, u8 flags)
+{
+	struct adj_time_work    *wrk;
+	static s32 scnt = 50;
+
+	wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC);
+	if (wrk == NULL)
+		return;
+
+	wrk->host_time = hosttime;
+	if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+		INIT_WORK(&wrk->work, hv_set_host_time);
+		schedule_work(&wrk->work);
+		return;
+	}
+
+	if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
+		scnt--;
+		INIT_WORK(&wrk->work, hv_set_host_time);
+		schedule_work(&wrk->work);
+	} else
+		kfree(wrk);
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct ictimesync_data *timedatap;
+	u8 *time_txf_buf = util_timesynch.recv_buffer;
+
+	vmbus_recvpacket(channel, time_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+		} else {
+			timedatap = (struct ictimesync_data *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+			adj_guesttime(timedatap->parenttime, timedatap->flags);
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, time_txf_buf,
+				recvlen, requestid,
+				VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+/*
+ * Heartbeat functionality.
+ * Every two seconds, Hyper-V send us a heartbeat request message.
+ * we respond to this message, and Hyper-V knows we are alive.
+ */
+static void heartbeat_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct heartbeat_msg_data *heartbeat_msg;
+	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
+
+	vmbus_recvpacket(channel, hbeat_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+		} else {
+			heartbeat_msg =
+				(struct heartbeat_msg_data *)&hbeat_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			heartbeat_msg->seq_num += 1;
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, hbeat_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+static int util_probe(struct hv_device *dev,
+			const struct hv_vmbus_device_id *dev_id)
+{
+	struct hv_util_service *srv =
+		(struct hv_util_service *)dev_id->driver_data;
+	int ret;
+
+	srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!srv->recv_buffer)
+		return -ENOMEM;
+	if (srv->util_init) {
+		ret = srv->util_init(srv);
+		if (ret) {
+			ret = -ENODEV;
+			goto error1;
+		}
+	}
+
+	ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+			srv->util_cb, dev->channel);
+	if (ret)
+		goto error;
+
+	hv_set_drvdata(dev, srv);
+	return 0;
+
+error:
+	if (srv->util_deinit)
+		srv->util_deinit();
+error1:
+	kfree(srv->recv_buffer);
+	return ret;
+}
+
+static int util_remove(struct hv_device *dev)
+{
+	struct hv_util_service *srv = hv_get_drvdata(dev);
+
+	vmbus_close(dev->channel);
+	if (srv->util_deinit)
+		srv->util_deinit();
+	kfree(srv->recv_buffer);
+
+	return 0;
+}
+
+static const struct hv_vmbus_device_id id_table[] = {
+	/* Shutdown guid */
+	{ VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+		       0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB)
+	  .driver_data = (unsigned long)&util_shutdown },
+	/* Time synch guid */
+	{ VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+		       0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
+	  .driver_data = (unsigned long)&util_timesynch },
+	/* Heartbeat guid */
+	{ VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+		       0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
+	  .driver_data = (unsigned long)&util_heartbeat },
+	/* KVP guid */
+	{ VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+		       0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6)
+	  .driver_data = (unsigned long)&util_kvp },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+/* The one and only one */
+static  struct hv_driver util_drv = {
+	.name = "hv_util",
+	.id_table = id_table,
+	.probe =  util_probe,
+	.remove =  util_remove,
+};
+
+static int __init init_hyperv_utils(void)
+{
+	pr_info("Registering HyperV Utility Driver\n");
+
+	return vmbus_driver_register(&util_drv);
+}
+
+static void exit_hyperv_utils(void)
+{
+	pr_info("De-Registered HyperV Utility Driver\n");
+
+	vmbus_driver_unregister(&util_drv);
+}
+
+module_init(init_hyperv_utils);
+module_exit(exit_hyperv_utils);
+
+MODULE_DESCRIPTION("Hyper-V Utilities");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/hv/hyperv_vmbus.h linux-libre-3.2-gnu1/drivers/hv/hyperv_vmbus.h
--- linux-libre-3.1-gnu1/drivers/hv/hyperv_vmbus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/hyperv_vmbus.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,626 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_VMBUS_H
+#define _HYPERV_VMBUS_H
+
+#include <linux/list.h>
+#include <asm/sync_bitops.h>
+#include <linux/atomic.h>
+#include <linux/hyperv.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HVCPUID_VERSION_FEATURES).
+ */
+enum hv_cpuid_function {
+	HVCPUID_VERSION_FEATURES		= 0x00000001,
+	HVCPUID_VENDOR_MAXFUNCTION		= 0x40000000,
+	HVCPUID_INTERFACE			= 0x40000001,
+
+	/*
+	 * The remaining functions depend on the value of
+	 * HVCPUID_INTERFACE
+	 */
+	HVCPUID_VERSION			= 0x40000002,
+	HVCPUID_FEATURES			= 0x40000003,
+	HVCPUID_ENLIGHTENMENT_INFO	= 0x40000004,
+	HVCPUID_IMPLEMENTATION_LIMITS		= 0x40000005,
+};
+
+/* Define version of the synthetic interrupt controller. */
+#define HV_SYNIC_VERSION		(1)
+
+/* Define the expected SynIC version. */
+#define HV_SYNIC_VERSION_1		(0x1)
+
+/* Define synthetic interrupt controller message constants. */
+#define HV_MESSAGE_SIZE			(256)
+#define HV_MESSAGE_PAYLOAD_BYTE_COUNT	(240)
+#define HV_MESSAGE_PAYLOAD_QWORD_COUNT	(30)
+#define HV_ANY_VP			(0xFFFFFFFF)
+
+/* Define synthetic interrupt controller flag constants. */
+#define HV_EVENT_FLAGS_COUNT		(256 * 8)
+#define HV_EVENT_FLAGS_BYTE_COUNT	(256)
+#define HV_EVENT_FLAGS_DWORD_COUNT	(256 / sizeof(u32))
+
+/* Define hypervisor message types. */
+enum hv_message_type {
+	HVMSG_NONE			= 0x00000000,
+
+	/* Memory access messages. */
+	HVMSG_UNMAPPED_GPA		= 0x80000000,
+	HVMSG_GPA_INTERCEPT		= 0x80000001,
+
+	/* Timer notification messages. */
+	HVMSG_TIMER_EXPIRED			= 0x80000010,
+
+	/* Error messages. */
+	HVMSG_INVALID_VP_REGISTER_VALUE	= 0x80000020,
+	HVMSG_UNRECOVERABLE_EXCEPTION	= 0x80000021,
+	HVMSG_UNSUPPORTED_FEATURE		= 0x80000022,
+
+	/* Trace buffer complete messages. */
+	HVMSG_EVENTLOG_BUFFERCOMPLETE	= 0x80000040,
+
+	/* Platform-specific processor intercept messages. */
+	HVMSG_X64_IOPORT_INTERCEPT		= 0x80010000,
+	HVMSG_X64_MSR_INTERCEPT		= 0x80010001,
+	HVMSG_X64_CPUID_INTERCEPT		= 0x80010002,
+	HVMSG_X64_EXCEPTION_INTERCEPT	= 0x80010003,
+	HVMSG_X64_APIC_EOI			= 0x80010004,
+	HVMSG_X64_LEGACY_FP_ERROR		= 0x80010005
+};
+
+/* Define the number of synthetic interrupt sources. */
+#define HV_SYNIC_SINT_COUNT		(16)
+#define HV_SYNIC_STIMER_COUNT		(4)
+
+/* Define invalid partition identifier. */
+#define HV_PARTITION_ID_INVALID		((u64)0x0)
+
+/* Define connection identifier type. */
+union hv_connection_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u;
+};
+
+/* Define port identifier type. */
+union hv_port_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u ;
+};
+
+/* Define port type. */
+enum hv_port_type {
+	HVPORT_MSG	= 1,
+	HVPORT_EVENT		= 2,
+	HVPORT_MONITOR	= 3
+};
+
+/* Define port information structure. */
+struct hv_port_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u64 rsvdz;
+		} message_port_info;
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u16 base_flag_bumber;
+			u16 flag_count;
+			u32 rsvdz;
+		} event_port_info;
+		struct {
+			u64 monitor_address;
+			u64 rsvdz;
+		} monitor_port_info;
+	};
+};
+
+struct hv_connection_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u64 rsvdz;
+		} message_connection_info;
+		struct {
+			u64 rsvdz;
+		} event_connection_info;
+		struct {
+			u64 monitor_address;
+		} monitor_connection_info;
+	};
+};
+
+/* Define synthetic interrupt controller message flags. */
+union hv_message_flags {
+	u8 asu8;
+	struct {
+		u8 msg_pending:1;
+		u8 reserved:7;
+	};
+};
+
+/* Define synthetic interrupt controller message header. */
+struct hv_message_header {
+	enum hv_message_type message_type;
+	u8 payload_size;
+	union hv_message_flags message_flags;
+	u8 reserved[2];
+	union {
+		u64 sender;
+		union hv_port_id port;
+	};
+};
+
+/* Define timer message payload structure. */
+struct hv_timer_message_payload {
+	u32 timer_index;
+	u32 reserved;
+	u64 expiration_time;	/* When the timer expired */
+	u64 delivery_time;	/* When the message was delivered */
+};
+
+/* Define synthetic interrupt controller message format. */
+struct hv_message {
+	struct hv_message_header header;
+	union {
+		u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+	} u ;
+};
+
+/* Define the number of message buffers associated with each port. */
+#define HV_PORT_MESSAGE_BUFFER_COUNT	(16)
+
+/* Define the synthetic interrupt message page layout. */
+struct hv_message_page {
+	struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define the synthetic interrupt controller event flags format. */
+union hv_synic_event_flags {
+	u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT];
+	u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT];
+};
+
+/* Define the synthetic interrupt flags page layout. */
+struct hv_synic_event_flags_page {
+	union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define SynIC control register. */
+union hv_synic_scontrol {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:63;
+	};
+};
+
+/* Define synthetic interrupt source. */
+union hv_synic_sint {
+	u64 as_uint64;
+	struct {
+		u64 vector:8;
+		u64 reserved1:8;
+		u64 masked:1;
+		u64 auto_eoi:1;
+		u64 reserved2:46;
+	};
+};
+
+/* Define the format of the SIMP register */
+union hv_synic_simp {
+	u64 as_uint64;
+	struct {
+		u64 simp_enabled:1;
+		u64 preserved:11;
+		u64 base_simp_gpa:52;
+	};
+};
+
+/* Define the format of the SIEFP register */
+union hv_synic_siefp {
+	u64 as_uint64;
+	struct {
+		u64 siefp_enabled:1;
+		u64 preserved:11;
+		u64 base_siefp_gpa:52;
+	};
+};
+
+/* Definitions for the monitored notification facility */
+union hv_monitor_trigger_group {
+	u64 as_uint64;
+	struct {
+		u32 pending;
+		u32 armed;
+	};
+};
+
+struct hv_monitor_parameter {
+	union hv_connection_id connectionid;
+	u16 flagnumber;
+	u16 rsvdz;
+};
+
+union hv_monitor_trigger_state {
+	u32 asu32;
+
+	struct {
+		u32 group_enable:4;
+		u32 rsvdz:28;
+	};
+};
+
+/* struct hv_monitor_page Layout */
+/* ------------------------------------------------------ */
+/* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
+/* | 8   | TriggerGroup[0]                              | */
+/* | 10  | TriggerGroup[1]                              | */
+/* | 18  | TriggerGroup[2]                              | */
+/* | 20  | TriggerGroup[3]                              | */
+/* | 28  | Rsvd2[0]                                     | */
+/* | 30  | Rsvd2[1]                                     | */
+/* | 38  | Rsvd2[2]                                     | */
+/* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
+/* | ...                                                | */
+/* | 240 | Latency[0][0..3]                             | */
+/* | 340 | Rsvz3[0]                                     | */
+/* | 440 | Parameter[0][0]                              | */
+/* | 448 | Parameter[0][1]                              | */
+/* | ...                                                | */
+/* | 840 | Rsvd4[0]                                     | */
+/* ------------------------------------------------------ */
+struct hv_monitor_page {
+	union hv_monitor_trigger_state trigger_state;
+	u32 rsvdz1;
+
+	union hv_monitor_trigger_group trigger_group[4];
+	u64 rsvdz2[3];
+
+	s32 next_checktime[4][32];
+
+	u16 latency[4][32];
+	u64 rsvdz3[32];
+
+	struct hv_monitor_parameter parameter[4][32];
+
+	u8 rsvdz4[1984];
+};
+
+/* Declare the various hypercall operations. */
+enum hv_call_code {
+	HVCALL_POST_MESSAGE	= 0x005c,
+	HVCALL_SIGNAL_EVENT	= 0x005d,
+};
+
+/* Definition of the hv_post_message hypercall input structure. */
+struct hv_input_post_message {
+	union hv_connection_id connectionid;
+	u32 reserved;
+	enum hv_message_type message_type;
+	u32 payload_size;
+	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+};
+
+/* Definition of the hv_signal_event hypercall input structure. */
+struct hv_input_signal_event {
+	union hv_connection_id connectionid;
+	u16 flag_number;
+	u16 rsvdz;
+};
+
+/*
+ * Versioning definitions used for guests reporting themselves to the
+ * hypervisor, and visa versa.
+ */
+
+/* Version info reported by guest OS's */
+enum hv_guest_os_vendor {
+	HVGUESTOS_VENDOR_MICROSOFT	= 0x0001
+};
+
+enum hv_guest_os_microsoft_ids {
+	HVGUESTOS_MICROSOFT_UNDEFINED	= 0x00,
+	HVGUESTOS_MICROSOFT_MSDOS		= 0x01,
+	HVGUESTOS_MICROSOFT_WINDOWS3X	= 0x02,
+	HVGUESTOS_MICROSOFT_WINDOWS9X	= 0x03,
+	HVGUESTOS_MICROSOFT_WINDOWSNT	= 0x04,
+	HVGUESTOS_MICROSOFT_WINDOWSCE	= 0x05
+};
+
+/*
+ * Declare the MSR used to identify the guest OS.
+ */
+#define HV_X64_MSR_GUEST_OS_ID	0x40000000
+
+union hv_x64_msr_guest_os_id_contents {
+	u64 as_uint64;
+	struct {
+		u64 build_number:16;
+		u64 service_version:8; /* Service Pack, etc. */
+		u64 minor_version:8;
+		u64 major_version:8;
+		u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */
+		u64 vendor_id:16; /* enum hv_guest_os_vendor */
+	};
+};
+
+/*
+ * Declare the MSR used to setup pages used to communicate with the hypervisor.
+ */
+#define HV_X64_MSR_HYPERCALL	0x40000001
+
+union hv_x64_msr_hypercall_contents {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:11;
+		u64 guest_physical_address:52;
+	};
+};
+
+
+enum {
+	VMBUS_MESSAGE_CONNECTION_ID	= 1,
+	VMBUS_MESSAGE_PORT_ID		= 1,
+	VMBUS_EVENT_CONNECTION_ID	= 2,
+	VMBUS_EVENT_PORT_ID		= 2,
+	VMBUS_MONITOR_CONNECTION_ID	= 3,
+	VMBUS_MONITOR_PORT_ID		= 3,
+	VMBUS_MESSAGE_SINT		= 2,
+};
+
+/* #defines */
+
+#define HV_PRESENT_BIT			0x80000000
+
+#define HV_LINUX_GUEST_ID_LO		0x00000000
+#define HV_LINUX_GUEST_ID_HI		0xB16B00B5
+#define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
+					   HV_LINUX_GUEST_ID_LO)
+
+#define HV_CPU_POWER_MANAGEMENT		(1 << 0)
+#define HV_RECOMMENDATIONS_MAX		4
+
+#define HV_X64_MAX			5
+#define HV_CAPS_MAX			8
+
+
+#define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
+
+
+/* Service definitions */
+
+#define HV_SERVICE_PARENT_PORT				(0)
+#define HV_SERVICE_PARENT_CONNECTION			(0)
+
+#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS		(0)
+#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER	(1)
+#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE	(2)
+#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED	(3)
+
+#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID		(1)
+#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID		(2)
+#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID	(3)
+#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID	(4)
+#define HV_SERVICE_MAX_MESSAGE_ID				(4)
+
+#define HV_SERVICE_PROTOCOL_VERSION (0x0010)
+#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
+
+/* #define VMBUS_REVISION_NUMBER	6 */
+
+/* Our local vmbus's port and connection id. Anything >0 is fine */
+/* #define VMBUS_PORT_ID		11 */
+
+/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
+static const uuid_le VMBUS_SERVICE_ID = {
+	.b = {
+		0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
+		0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
+	},
+};
+
+#define MAX_NUM_CPUS	32
+
+
+struct hv_input_signal_event_buffer {
+	u64 align8;
+	struct hv_input_signal_event event;
+};
+
+struct hv_context {
+	/* We only support running on top of Hyper-V
+	* So at this point this really can only contain the Hyper-V ID
+	*/
+	u64 guestid;
+
+	void *hypercall_page;
+
+	bool synic_initialized;
+
+	/*
+	 * This is used as an input param to HvCallSignalEvent hypercall. The
+	 * input param is immutable in our usage and must be dynamic mem (vs
+	 * stack or global). */
+	struct hv_input_signal_event_buffer *signal_event_buffer;
+	/* 8-bytes aligned of the buffer above */
+	struct hv_input_signal_event *signal_event_param;
+
+	void *synic_message_page[MAX_NUM_CPUS];
+	void *synic_event_page[MAX_NUM_CPUS];
+};
+
+extern struct hv_context hv_context;
+
+
+/* Hv Interface */
+
+extern int hv_init(void);
+
+extern void hv_cleanup(void);
+
+extern u16 hv_post_message(union hv_connection_id connection_id,
+			 enum hv_message_type message_type,
+			 void *payload, size_t payload_size);
+
+extern u16 hv_signal_event(void);
+
+extern void hv_synic_init(void *irqarg);
+
+extern void hv_synic_cleanup(void *arg);
+
+
+/* Interface */
+
+
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
+
+int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
+		    struct scatterlist *sglist,
+		    u32 sgcount);
+
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
+		   void *buffer,
+		   u32 buflen,
+		   u32 offset);
+
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
+
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info);
+
+/*
+ * Maximum channels is determined by the size of the interrupt page
+ * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
+ * and the other is receive endpoint interrupt
+ */
+#define MAX_NUM_CHANNELS	((PAGE_SIZE >> 1) << 3)	/* 16348 channels */
+
+/* The value here must be in multiple of 32 */
+/* TODO: Need to make this configurable */
+#define MAX_NUM_CHANNELS_SUPPORTED	256
+
+
+enum vmbus_connect_state {
+	DISCONNECTED,
+	CONNECTING,
+	CONNECTED,
+	DISCONNECTING
+};
+
+#define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
+
+struct vmbus_connection {
+	enum vmbus_connect_state conn_state;
+
+	atomic_t next_gpadl_handle;
+
+	/*
+	 * Represents channel interrupts. Each bit position represents a
+	 * channel.  When a channel sends an interrupt via VMBUS, it finds its
+	 * bit in the sendInterruptPage, set it and calls Hv to generate a port
+	 * event. The other end receives the port event and parse the
+	 * recvInterruptPage to see which bit is set
+	 */
+	void *int_page;
+	void *send_int_page;
+	void *recv_int_page;
+
+	/*
+	 * 2 pages - 1st page for parent->child notification and 2nd
+	 * is child->parent notification
+	 */
+	void *monitor_pages;
+	struct list_head chn_msg_list;
+	spinlock_t channelmsg_lock;
+
+	/* List of channels */
+	struct list_head chn_list;
+	spinlock_t channel_lock;
+
+	struct workqueue_struct *work_queue;
+};
+
+
+struct vmbus_msginfo {
+	/* Bookkeeping stuff */
+	struct list_head msglist_entry;
+
+	/* The message itself */
+	unsigned char msg[0];
+};
+
+
+extern struct vmbus_connection vmbus_connection;
+
+/* General vmbus interface */
+
+struct hv_device *vmbus_device_create(uuid_le *type,
+					 uuid_le *instance,
+					 struct vmbus_channel *channel);
+
+int vmbus_device_register(struct hv_device *child_device_obj);
+void vmbus_device_unregister(struct hv_device *device_obj);
+
+/* static void */
+/* VmbusChildDeviceDestroy( */
+/* struct hv_device *); */
+
+struct vmbus_channel *relid2channel(u32 relid);
+
+
+/* Connection interface */
+
+int vmbus_connect(void);
+
+int vmbus_post_msg(void *buffer, size_t buflen);
+
+int vmbus_set_event(u32 child_relid);
+
+void vmbus_on_event(unsigned long data);
+
+
+#endif /* _HYPERV_VMBUS_H */
diff -druNp linux-libre-3.1-gnu1/drivers/hv/Kconfig linux-libre-3.2-gnu1/drivers/hv/Kconfig
--- linux-libre-3.1-gnu1/drivers/hv/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+config HYPERV
+	tristate "Microsoft Hyper-V client drivers"
+	depends on X86 && ACPI && PCI
+	help
+	  Select this option to run Linux as a Hyper-V client operating
+	  system.
+
+config HYPERV_UTILS
+	tristate "Microsoft Hyper-V Utilities driver"
+	depends on HYPERV && CONNECTOR && NLS
+	help
+	  Select this option to enable the Hyper-V Utilities.
+
+
diff -druNp linux-libre-3.1-gnu1/drivers/hv/Makefile linux-libre-3.2-gnu1/drivers/hv/Makefile
--- linux-libre-3.1-gnu1/drivers/hv/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+obj-$(CONFIG_HYPERV)		+= hv_vmbus.o
+obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
+
+hv_vmbus-y := vmbus_drv.o \
+		 hv.o connection.o channel.o \
+		 channel_mgmt.o ring_buffer.o
+hv_utils-y := hv_util.o hv_kvp.o
diff -druNp linux-libre-3.1-gnu1/drivers/hv/ring_buffer.c linux-libre-3.2-gnu1/drivers/hv/ring_buffer.c
--- linux-libre-3.1-gnu1/drivers/hv/ring_buffer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/ring_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,496 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+
+/* #defines */
+
+
+/* Amount of space to write to */
+#define BYTES_AVAIL_TO_WRITE(r, w, z) \
+	((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
+
+
+/*
+ *
+ * hv_get_ringbuffer_availbytes()
+ *
+ * Get number of bytes available to read and to write to
+ * for the specified ring buffer
+ */
+static inline void
+hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
+			  u32 *read, u32 *write)
+{
+	u32 read_loc, write_loc;
+
+	smp_read_barrier_depends();
+
+	/* Capture the read/write indices before they changed */
+	read_loc = rbi->ring_buffer->read_index;
+	write_loc = rbi->ring_buffer->write_index;
+
+	*write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize);
+	*read = rbi->ring_datasize - *write;
+}
+
+/*
+ * hv_get_next_write_location()
+ *
+ * Get the next write location for the specified ring buffer
+ *
+ */
+static inline u32
+hv_get_next_write_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->write_index;
+
+	return next;
+}
+
+/*
+ * hv_set_next_write_location()
+ *
+ * Set the next write location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_write_location(struct hv_ring_buffer_info *ring_info,
+		     u32 next_write_location)
+{
+	ring_info->ring_buffer->write_index = next_write_location;
+}
+
+/*
+ * hv_get_next_read_location()
+ *
+ * Get the next read location for the specified ring buffer
+ */
+static inline u32
+hv_get_next_read_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	return next;
+}
+
+/*
+ * hv_get_next_readlocation_withoffset()
+ *
+ * Get the next read location + offset for the specified ring buffer.
+ * This allows the caller to skip
+ */
+static inline u32
+hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info,
+				 u32 offset)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	next += offset;
+	next %= ring_info->ring_datasize;
+
+	return next;
+}
+
+/*
+ *
+ * hv_set_next_read_location()
+ *
+ * Set the next read location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_read_location(struct hv_ring_buffer_info *ring_info,
+		    u32 next_read_location)
+{
+	ring_info->ring_buffer->read_index = next_read_location;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffer()
+ *
+ * Get the start of the ring buffer
+ */
+static inline void *
+hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
+{
+	return (void *)ring_info->ring_buffer->buffer;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffersize()
+ *
+ * Get the size of the ring buffer
+ */
+static inline u32
+hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
+{
+	return ring_info->ring_datasize;
+}
+
+/*
+ *
+ * hv_get_ring_bufferindices()
+ *
+ * Get the read and write indices as u64 of the specified ring buffer
+ *
+ */
+static inline u64
+hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info)
+{
+	return (u64)ring_info->ring_buffer->write_index << 32;
+}
+
+/*
+ *
+ * hv_copyfrom_ringbuffer()
+ *
+ * Helper routine to copy to source from ring buffer.
+ * Assume there is enough room. Handles wrap-around in src case only!!
+ *
+ */
+static u32 hv_copyfrom_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	void				*dest,
+	u32				destlen,
+	u32				start_read_offset)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+
+	u32 frag_len;
+
+	/* wrap-around detected at the src */
+	if (destlen > ring_buffer_size - start_read_offset) {
+		frag_len = ring_buffer_size - start_read_offset;
+
+		memcpy(dest, ring_buffer + start_read_offset, frag_len);
+		memcpy(dest + frag_len, ring_buffer, destlen - frag_len);
+	} else
+
+		memcpy(dest, ring_buffer + start_read_offset, destlen);
+
+
+	start_read_offset += destlen;
+	start_read_offset %= ring_buffer_size;
+
+	return start_read_offset;
+}
+
+
+/*
+ *
+ * hv_copyto_ringbuffer()
+ *
+ * Helper routine to copy from source to ring buffer.
+ * Assume there is enough room. Handles wrap-around in dest case only!!
+ *
+ */
+static u32 hv_copyto_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	u32				start_write_offset,
+	void				*src,
+	u32				srclen)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+	u32 frag_len;
+
+	/* wrap-around detected! */
+	if (srclen > ring_buffer_size - start_write_offset) {
+		frag_len = ring_buffer_size - start_write_offset;
+		memcpy(ring_buffer + start_write_offset, src, frag_len);
+		memcpy(ring_buffer, src + frag_len, srclen - frag_len);
+	} else
+		memcpy(ring_buffer + start_write_offset, src, srclen);
+
+	start_write_offset += srclen;
+	start_write_offset %= ring_buffer_size;
+
+	return start_write_offset;
+}
+
+/*
+ *
+ * hv_ringbuffer_get_debuginfo()
+ *
+ * Get various debug metrics for the specified ring buffer
+ *
+ */
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+
+	if (ring_info->ring_buffer) {
+		hv_get_ringbuffer_availbytes(ring_info,
+					&bytes_avail_toread,
+					&bytes_avail_towrite);
+
+		debug_info->bytes_avail_toread = bytes_avail_toread;
+		debug_info->bytes_avail_towrite = bytes_avail_towrite;
+		debug_info->current_read_index =
+			ring_info->ring_buffer->read_index;
+		debug_info->current_write_index =
+			ring_info->ring_buffer->write_index;
+		debug_info->current_interrupt_mask =
+			ring_info->ring_buffer->interrupt_mask;
+	}
+}
+
+
+/*
+ *
+ * hv_get_ringbuffer_interrupt_mask()
+ *
+ * Get the interrupt mask for the specified ring buffer
+ *
+ */
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *rbi)
+{
+	return rbi->ring_buffer->interrupt_mask;
+}
+
+/*
+ *
+ * hv_ringbuffer_init()
+ *
+ *Initialize the ring buffer
+ *
+ */
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
+		   void *buffer, u32 buflen)
+{
+	if (sizeof(struct hv_ring_buffer) != PAGE_SIZE)
+		return -EINVAL;
+
+	memset(ring_info, 0, sizeof(struct hv_ring_buffer_info));
+
+	ring_info->ring_buffer = (struct hv_ring_buffer *)buffer;
+	ring_info->ring_buffer->read_index =
+		ring_info->ring_buffer->write_index = 0;
+
+	ring_info->ring_size = buflen;
+	ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
+
+	spin_lock_init(&ring_info->ring_lock);
+
+	return 0;
+}
+
+/*
+ *
+ * hv_ringbuffer_cleanup()
+ *
+ * Cleanup the ring buffer
+ *
+ */
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
+{
+}
+
+/*
+ *
+ * hv_ringbuffer_write()
+ *
+ * Write to the ring buffer
+ *
+ */
+int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
+		    struct scatterlist *sglist, u32 sgcount)
+{
+	int i = 0;
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 totalbytes_towrite = 0;
+
+	struct scatterlist *sg;
+	u32 next_write_location;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		totalbytes_towrite += sg->length;
+	}
+
+	totalbytes_towrite += sizeof(u64);
+
+	spin_lock_irqsave(&outring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(outring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+
+	/* If there is only room for the packet, assume it is full. */
+	/* Otherwise, the next time around, we think the ring buffer */
+	/* is empty since the read index == write index */
+	if (bytes_avail_towrite <= totalbytes_towrite) {
+		spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+		return -EAGAIN;
+	}
+
+	/* Write to the ring buffer */
+	next_write_location = hv_get_next_write_location(outring_info);
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		next_write_location = hv_copyto_ringbuffer(outring_info,
+						     next_write_location,
+						     sg_virt(sg),
+						     sg->length);
+	}
+
+	/* Set previous packet start */
+	prev_indices = hv_get_ring_bufferindices(outring_info);
+
+	next_write_location = hv_copyto_ringbuffer(outring_info,
+					     next_write_location,
+					     &prev_indices,
+					     sizeof(u64));
+
+	/* Make sure we flush all writes before updating the writeIndex */
+	smp_wmb();
+
+	/* Now, update the write location */
+	hv_set_next_write_location(outring_info, next_write_location);
+
+
+	spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_peek()
+ *
+ * Read without advancing the read index
+ *
+ */
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
+		   void *Buffer, u32 buflen)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&Inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(Inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+
+		spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+		return -EAGAIN;
+	}
+
+	/* Convert to byte offset */
+	next_read_location = hv_get_next_read_location(Inring_info);
+
+	next_read_location = hv_copyfrom_ringbuffer(Inring_info,
+						Buffer,
+						buflen,
+						next_read_location);
+
+	spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_read()
+ *
+ * Read and advance the read index
+ *
+ */
+int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
+		   u32 buflen, u32 offset)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	if (buflen <= 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+		spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+		return -EAGAIN;
+	}
+
+	next_read_location =
+		hv_get_next_readlocation_withoffset(inring_info, offset);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						buffer,
+						buflen,
+						next_read_location);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						&prev_indices,
+						sizeof(u64),
+						next_read_location);
+
+	/* Make sure all reads are done before we update the read index since */
+	/* the writer may start writing to the read area once the read index */
+	/*is updated */
+	smp_mb();
+
+	/* Update the read index */
+	hv_set_next_read_location(inring_info, next_read_location);
+
+	spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/hv/vmbus_drv.c linux-libre-3.2-gnu1/drivers/hv/vmbus_drv.c
--- linux-libre-3.1-gnu1/drivers/hv/vmbus_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hv/vmbus_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,786 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <linux/completion.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+
+static struct acpi_device  *hv_acpi_dev;
+
+static struct tasklet_struct msg_dpc;
+static struct tasklet_struct event_dpc;
+static struct completion probe_event;
+static int irq;
+
+struct hv_device_info {
+	u32 chn_id;
+	u32 chn_state;
+	uuid_le chn_type;
+	uuid_le chn_instance;
+
+	u32 monitor_id;
+	u32 server_monitor_pending;
+	u32 server_monitor_latency;
+	u32 server_monitor_conn_id;
+	u32 client_monitor_pending;
+	u32 client_monitor_latency;
+	u32 client_monitor_conn_id;
+
+	struct hv_dev_port_info inbound;
+	struct hv_dev_port_info outbound;
+};
+
+
+static void get_channel_info(struct hv_device *device,
+			     struct hv_device_info *info)
+{
+	struct vmbus_channel_debug_info debug_info;
+
+	if (!device->channel)
+		return;
+
+	vmbus_get_debug_info(device->channel, &debug_info);
+
+	info->chn_id = debug_info.relid;
+	info->chn_state = debug_info.state;
+	memcpy(&info->chn_type, &debug_info.interfacetype,
+	       sizeof(uuid_le));
+	memcpy(&info->chn_instance, &debug_info.interface_instance,
+	       sizeof(uuid_le));
+
+	info->monitor_id = debug_info.monitorid;
+
+	info->server_monitor_pending = debug_info.servermonitor_pending;
+	info->server_monitor_latency = debug_info.servermonitor_latency;
+	info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
+
+	info->client_monitor_pending = debug_info.clientmonitor_pending;
+	info->client_monitor_latency = debug_info.clientmonitor_latency;
+	info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
+
+	info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
+	info->inbound.read_idx = debug_info.inbound.current_read_index;
+	info->inbound.write_idx = debug_info.inbound.current_write_index;
+	info->inbound.bytes_avail_toread =
+		debug_info.inbound.bytes_avail_toread;
+	info->inbound.bytes_avail_towrite =
+		debug_info.inbound.bytes_avail_towrite;
+
+	info->outbound.int_mask =
+		debug_info.outbound.current_interrupt_mask;
+	info->outbound.read_idx = debug_info.outbound.current_read_index;
+	info->outbound.write_idx = debug_info.outbound.current_write_index;
+	info->outbound.bytes_avail_toread =
+		debug_info.outbound.bytes_avail_toread;
+	info->outbound.bytes_avail_towrite =
+		debug_info.outbound.bytes_avail_towrite;
+}
+
+#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
+static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
+{
+	int i;
+	for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
+		sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
+}
+
+/*
+ * vmbus_show_device_attr - Show the device attribute in sysfs.
+ *
+ * This is invoked when user does a
+ * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
+ */
+static ssize_t vmbus_show_device_attr(struct device *dev,
+				      struct device_attribute *dev_attr,
+				      char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_device_info *device_info;
+	char alias_name[VMBUS_ALIAS_LEN + 1];
+	int ret = 0;
+
+	device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
+	if (!device_info)
+		return ret;
+
+	get_channel_info(hv_dev, device_info);
+
+	if (!strcmp(dev_attr->attr.name, "class_id")) {
+		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info->chn_type.b[3],
+			       device_info->chn_type.b[2],
+			       device_info->chn_type.b[1],
+			       device_info->chn_type.b[0],
+			       device_info->chn_type.b[5],
+			       device_info->chn_type.b[4],
+			       device_info->chn_type.b[7],
+			       device_info->chn_type.b[6],
+			       device_info->chn_type.b[8],
+			       device_info->chn_type.b[9],
+			       device_info->chn_type.b[10],
+			       device_info->chn_type.b[11],
+			       device_info->chn_type.b[12],
+			       device_info->chn_type.b[13],
+			       device_info->chn_type.b[14],
+			       device_info->chn_type.b[15]);
+	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
+		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info->chn_instance.b[3],
+			       device_info->chn_instance.b[2],
+			       device_info->chn_instance.b[1],
+			       device_info->chn_instance.b[0],
+			       device_info->chn_instance.b[5],
+			       device_info->chn_instance.b[4],
+			       device_info->chn_instance.b[7],
+			       device_info->chn_instance.b[6],
+			       device_info->chn_instance.b[8],
+			       device_info->chn_instance.b[9],
+			       device_info->chn_instance.b[10],
+			       device_info->chn_instance.b[11],
+			       device_info->chn_instance.b[12],
+			       device_info->chn_instance.b[13],
+			       device_info->chn_instance.b[14],
+			       device_info->chn_instance.b[15]);
+	} else if (!strcmp(dev_attr->attr.name, "modalias")) {
+		print_alias_name(hv_dev, alias_name);
+		ret = sprintf(buf, "vmbus:%s\n", alias_name);
+	} else if (!strcmp(dev_attr->attr.name, "state")) {
+		ret = sprintf(buf, "%d\n", device_info->chn_state);
+	} else if (!strcmp(dev_attr->attr.name, "id")) {
+		ret = sprintf(buf, "%d\n", device_info->chn_id);
+	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->outbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->outbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->inbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->inbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
+		ret = sprintf(buf, "%d\n", device_info->monitor_id);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
+		ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
+		ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->server_monitor_conn_id);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
+		ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
+		ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->client_monitor_conn_id);
+	}
+
+	kfree(device_info);
+	return ret;
+}
+
+/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
+static struct device_attribute vmbus_device_attrs[] = {
+	__ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR_NULL
+};
+
+
+/*
+ * vmbus_uevent - add uevent for our device
+ *
+ * This routine is invoked when a device is added or removed on the vmbus to
+ * generate a uevent to udev in the userspace. The udev will then look at its
+ * rule and the uevent generated here to load the appropriate driver
+ *
+ * The alias string will be of the form vmbus:guid where guid is the string
+ * representation of the device guid (each byte of the guid will be
+ * represented with two hex characters.
+ */
+static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
+{
+	struct hv_device *dev = device_to_hv_device(device);
+	int ret;
+	char alias_name[VMBUS_ALIAS_LEN + 1];
+
+	print_alias_name(dev, alias_name);
+	ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name);
+	return ret;
+}
+
+static uuid_le null_guid;
+
+static inline bool is_null_guid(const __u8 *guid)
+{
+	if (memcmp(guid, &null_guid, sizeof(uuid_le)))
+		return false;
+	return true;
+}
+
+/*
+ * Return a matching hv_vmbus_device_id pointer.
+ * If there is no match, return NULL.
+ */
+static const struct hv_vmbus_device_id *hv_vmbus_get_id(
+					const struct hv_vmbus_device_id *id,
+					__u8 *guid)
+{
+	for (; !is_null_guid(id->guid); id++)
+		if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
+			return id;
+
+	return NULL;
+}
+
+
+
+/*
+ * vmbus_match - Attempt to match the specified device to the specified driver
+ */
+static int vmbus_match(struct device *device, struct device_driver *driver)
+{
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	struct hv_device *hv_dev = device_to_hv_device(device);
+
+	if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * vmbus_probe - Add the new vmbus's child device
+ */
+static int vmbus_probe(struct device *child_device)
+{
+	int ret = 0;
+	struct hv_driver *drv =
+			drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
+	const struct hv_vmbus_device_id *dev_id;
+
+	dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b);
+	if (drv->probe) {
+		ret = drv->probe(dev, dev_id);
+		if (ret != 0)
+			pr_err("probe failed for device %s (%d)\n",
+			       dev_name(child_device), ret);
+
+	} else {
+		pr_err("probe not set for driver %s\n",
+		       dev_name(child_device));
+		ret = -ENODEV;
+	}
+	return ret;
+}
+
+/*
+ * vmbus_remove - Remove a vmbus device
+ */
+static int vmbus_remove(struct device *child_device)
+{
+	struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
+
+	if (drv->remove)
+		drv->remove(dev);
+	else
+		pr_err("remove not set for driver %s\n",
+			dev_name(child_device));
+
+	return 0;
+}
+
+
+/*
+ * vmbus_shutdown - Shutdown a vmbus device
+ */
+static void vmbus_shutdown(struct device *child_device)
+{
+	struct hv_driver *drv;
+	struct hv_device *dev = device_to_hv_device(child_device);
+
+
+	/* The device may not be attached yet */
+	if (!child_device->driver)
+		return;
+
+	drv = drv_to_hv_drv(child_device->driver);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+
+	return;
+}
+
+
+/*
+ * vmbus_device_release - Final callback release of the vmbus child device
+ */
+static void vmbus_device_release(struct device *device)
+{
+	struct hv_device *hv_dev = device_to_hv_device(device);
+
+	kfree(hv_dev);
+
+}
+
+/* The one and only one */
+static struct bus_type  hv_bus = {
+	.name =		"vmbus",
+	.match =		vmbus_match,
+	.shutdown =		vmbus_shutdown,
+	.remove =		vmbus_remove,
+	.probe =		vmbus_probe,
+	.uevent =		vmbus_uevent,
+	.dev_attrs =	vmbus_device_attrs,
+};
+
+static const char *driver_name = "hyperv";
+
+
+struct onmessage_work_context {
+	struct work_struct work;
+	struct hv_message msg;
+};
+
+static void vmbus_onmessage_work(struct work_struct *work)
+{
+	struct onmessage_work_context *ctx;
+
+	ctx = container_of(work, struct onmessage_work_context,
+			   work);
+	vmbus_onmessage(&ctx->msg);
+	kfree(ctx);
+}
+
+static void vmbus_on_msg_dpc(unsigned long data)
+{
+	int cpu = smp_processor_id();
+	void *page_addr = hv_context.synic_message_page[cpu];
+	struct hv_message *msg = (struct hv_message *)page_addr +
+				  VMBUS_MESSAGE_SINT;
+	struct onmessage_work_context *ctx;
+
+	while (1) {
+		if (msg->header.message_type == HVMSG_NONE) {
+			/* no msg */
+			break;
+		} else {
+			ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+			if (ctx == NULL)
+				continue;
+			INIT_WORK(&ctx->work, vmbus_onmessage_work);
+			memcpy(&ctx->msg, msg, sizeof(*msg));
+			queue_work(vmbus_connection.work_queue, &ctx->work);
+		}
+
+		msg->header.message_type = HVMSG_NONE;
+
+		/*
+		 * Make sure the write to MessageType (ie set to
+		 * HVMSG_NONE) happens before we read the
+		 * MessagePending and EOMing. Otherwise, the EOMing
+		 * will not deliver any more messages since there is
+		 * no empty slot
+		 */
+		smp_mb();
+
+		if (msg->header.message_flags.msg_pending) {
+			/*
+			 * This will cause message queue rescan to
+			 * possibly deliver another msg from the
+			 * hypervisor
+			 */
+			wrmsrl(HV_X64_MSR_EOM, 0);
+		}
+	}
+}
+
+static irqreturn_t vmbus_isr(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+	void *page_addr;
+	struct hv_message *msg;
+	union hv_synic_event_flags *event;
+	bool handled = false;
+
+	/*
+	 * Check for events before checking for messages. This is the order
+	 * in which events and messages are checked in Windows guests on
+	 * Hyper-V, and the Windows team suggested we do the same.
+	 */
+
+	page_addr = hv_context.synic_event_page[cpu];
+	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
+
+	/* Since we are a child, we only need to check bit 0 */
+	if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
+		handled = true;
+		tasklet_schedule(&event_dpc);
+	}
+
+	page_addr = hv_context.synic_message_page[cpu];
+	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
+
+	/* Check if there are actual msgs to be processed */
+	if (msg->header.message_type != HVMSG_NONE) {
+		handled = true;
+		tasklet_schedule(&msg_dpc);
+	}
+
+	if (handled)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+/*
+ * vmbus_bus_init -Main vmbus driver initialization routine.
+ *
+ * Here, we
+ *	- initialize the vmbus driver context
+ *	- invoke the vmbus hv main init routine
+ *	- get the irq resource
+ *	- retrieve the channel offers
+ */
+static int vmbus_bus_init(int irq)
+{
+	int ret;
+	unsigned int vector;
+
+	/* Hypervisor initialization...setup hypercall page..etc */
+	ret = hv_init();
+	if (ret != 0) {
+		pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
+		return ret;
+	}
+
+	tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
+	tasklet_init(&event_dpc, vmbus_on_event, 0);
+
+	ret = bus_register(&hv_bus);
+	if (ret)
+		goto err_cleanup;
+
+	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+			driver_name, hv_acpi_dev);
+
+	if (ret != 0) {
+		pr_err("Unable to request IRQ %d\n",
+			   irq);
+		goto err_unregister;
+	}
+
+	vector = IRQ0_VECTOR + irq;
+
+	/*
+	 * Notify the hypervisor of our irq and
+	 * connect to the host.
+	 */
+	on_each_cpu(hv_synic_init, (void *)&vector, 1);
+	ret = vmbus_connect();
+	if (ret)
+		goto err_irq;
+
+	vmbus_request_offers();
+
+	return 0;
+
+err_irq:
+	free_irq(irq, hv_acpi_dev);
+
+err_unregister:
+	bus_unregister(&hv_bus);
+
+err_cleanup:
+	hv_cleanup();
+
+	return ret;
+}
+
+/**
+ * __vmbus_child_driver_register - Register a vmbus's driver
+ * @drv: Pointer to driver structure you want to register
+ * @owner: owner module of the drv
+ * @mod_name: module name string
+ *
+ * Registers the given driver with Linux through the 'driver_register()' call
+ * and sets up the hyper-v vmbus handling for this driver.
+ * It will return the state of the 'driver_register()' call.
+ *
+ */
+int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name)
+{
+	int ret;
+
+	pr_info("registering driver %s\n", hv_driver->name);
+
+	hv_driver->driver.name = hv_driver->name;
+	hv_driver->driver.owner = owner;
+	hv_driver->driver.mod_name = mod_name;
+	hv_driver->driver.bus = &hv_bus;
+
+	ret = driver_register(&hv_driver->driver);
+
+	vmbus_request_offers();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__vmbus_driver_register);
+
+/**
+ * vmbus_driver_unregister() - Unregister a vmbus's driver
+ * @drv: Pointer to driver structure you want to un-register
+ *
+ * Un-register the given driver that was previous registered with a call to
+ * vmbus_driver_register()
+ */
+void vmbus_driver_unregister(struct hv_driver *hv_driver)
+{
+	pr_info("unregistering driver %s\n", hv_driver->name);
+
+	driver_unregister(&hv_driver->driver);
+
+}
+EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
+
+/*
+ * vmbus_device_create - Creates and registers a new child device
+ * on the vmbus.
+ */
+struct hv_device *vmbus_device_create(uuid_le *type,
+					    uuid_le *instance,
+					    struct vmbus_channel *channel)
+{
+	struct hv_device *child_device_obj;
+
+	child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
+	if (!child_device_obj) {
+		pr_err("Unable to allocate device object for child device\n");
+		return NULL;
+	}
+
+	child_device_obj->channel = channel;
+	memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
+	memcpy(&child_device_obj->dev_instance, instance,
+	       sizeof(uuid_le));
+
+
+	return child_device_obj;
+}
+
+/*
+ * vmbus_device_register - Register the child device
+ */
+int vmbus_device_register(struct hv_device *child_device_obj)
+{
+	int ret = 0;
+
+	static atomic_t device_num = ATOMIC_INIT(0);
+
+	dev_set_name(&child_device_obj->device, "vmbus_0_%d",
+		     atomic_inc_return(&device_num));
+
+	child_device_obj->device.bus = &hv_bus;
+	child_device_obj->device.parent = &hv_acpi_dev->dev;
+	child_device_obj->device.release = vmbus_device_release;
+
+	/*
+	 * Register with the LDM. This will kick off the driver/device
+	 * binding...which will eventually call vmbus_match() and vmbus_probe()
+	 */
+	ret = device_register(&child_device_obj->device);
+
+	if (ret)
+		pr_err("Unable to register child device\n");
+	else
+		pr_info("child device %s registered\n",
+			dev_name(&child_device_obj->device));
+
+	return ret;
+}
+
+/*
+ * vmbus_device_unregister - Remove the specified child device
+ * from the vmbus.
+ */
+void vmbus_device_unregister(struct hv_device *device_obj)
+{
+	/*
+	 * Kick off the process of unregistering the device.
+	 * This will call vmbus_remove() and eventually vmbus_device_release()
+	 */
+	device_unregister(&device_obj->device);
+
+	pr_info("child device %s unregistered\n",
+		dev_name(&device_obj->device));
+}
+
+
+/*
+ * VMBUS is an acpi enumerated device. Get the the IRQ information
+ * from DSDT.
+ */
+
+static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
+{
+
+	if (res->type == ACPI_RESOURCE_TYPE_IRQ) {
+		struct acpi_resource_irq *irqp;
+		irqp = &res->data.irq;
+
+		*((unsigned int *)irq) = irqp->interrupts[0];
+	}
+
+	return AE_OK;
+}
+
+static int vmbus_acpi_add(struct acpi_device *device)
+{
+	acpi_status result;
+
+	hv_acpi_dev = device;
+
+	result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+					vmbus_walk_resources, &irq);
+
+	if (ACPI_FAILURE(result)) {
+		complete(&probe_event);
+		return -ENODEV;
+	}
+	complete(&probe_event);
+	return 0;
+}
+
+static const struct acpi_device_id vmbus_acpi_device_ids[] = {
+	{"VMBUS", 0},
+	{"VMBus", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
+
+static struct acpi_driver vmbus_acpi_driver = {
+	.name = "vmbus",
+	.ids = vmbus_acpi_device_ids,
+	.ops = {
+		.add = vmbus_acpi_add,
+	},
+};
+
+static int __init hv_acpi_init(void)
+{
+	int ret, t;
+
+	init_completion(&probe_event);
+
+	/*
+	 * Get irq resources first.
+	 */
+
+	ret = acpi_bus_register_driver(&vmbus_acpi_driver);
+
+	if (ret)
+		return ret;
+
+	t = wait_for_completion_timeout(&probe_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (irq <= 0) {
+		ret = -ENODEV;
+		goto cleanup;
+	}
+
+	ret = vmbus_bus_init(irq);
+	if (ret)
+		goto cleanup;
+
+	return 0;
+
+cleanup:
+	acpi_bus_unregister_driver(&vmbus_acpi_driver);
+	return ret;
+}
+
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
+
+module_init(hv_acpi_init);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ad7314.c linux-libre-3.2-gnu1/drivers/hwmon/ad7314.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ad7314.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hwmon/ad7314.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * Conversion to hwmon from IIO done by Jonathan Cameron <jic23@cam.ac.uk>
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/*
+ * AD7314 power mode
+ */
+#define AD7314_PD		0x2000
+
+/*
+ * AD7314 temperature masks
+ */
+#define AD7314_TEMP_SIGN		0x200
+#define AD7314_TEMP_MASK		0x7FE0
+#define AD7314_TEMP_OFFSET		5
+
+/*
+ * ADT7301 and ADT7302 temperature masks
+ */
+#define ADT7301_TEMP_SIGN		0x2000
+#define ADT7301_TEMP_MASK		0x3FFF
+
+enum ad7314_variant {
+	adt7301,
+	adt7302,
+	ad7314,
+};
+
+struct ad7314_data {
+	struct spi_device	*spi_dev;
+	struct device		*hwmon_dev;
+	u16 rx ____cacheline_aligned;
+};
+
+static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
+{
+	int ret;
+
+	ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx));
+	if (ret < 0) {
+		dev_err(&chip->spi_dev->dev, "SPI read error\n");
+		return ret;
+	}
+
+	*data = be16_to_cpu(chip->rx);
+
+	return ret;
+}
+
+static ssize_t ad7314_show_temperature(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct ad7314_data *chip = dev_get_drvdata(dev);
+	s16 data;
+	int ret;
+
+	ret = ad7314_spi_read(chip, &data);
+	if (ret < 0)
+		return ret;
+	switch (spi_get_device_id(chip->spi_dev)->driver_data) {
+	case ad7314:
+		data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+		data = (data << 6) >> 6;
+
+		return sprintf(buf, "%d\n", 250 * data);
+	case adt7301:
+	case adt7302:
+		/*
+		 * Documented as a 13 bit twos complement register
+		 * with a sign bit - which is a 14 bit 2's complement
+		 * register.  1lsb - 31.25 milli degrees centigrade
+		 */
+		data &= ADT7301_TEMP_MASK;
+		data = (data << 2) >> 2;
+
+		return sprintf(buf, "%d\n",
+			       DIV_ROUND_CLOSEST(data * 3125, 100));
+	default:
+		return -EINVAL;
+	}
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+			  ad7314_show_temperature, NULL, 0);
+
+static struct attribute *ad7314_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ad7314_group = {
+	.attrs = ad7314_attributes,
+};
+
+static int __devinit ad7314_probe(struct spi_device *spi_dev)
+{
+	int ret;
+	struct ad7314_data *chip;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	dev_set_drvdata(&spi_dev->dev, chip);
+
+	ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
+	if (ret < 0)
+		goto error_free_chip;
+	chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
+	if (IS_ERR(chip->hwmon_dev)) {
+		ret = PTR_ERR(chip->hwmon_dev);
+		goto error_remove_group;
+	}
+
+	return 0;
+error_remove_group:
+	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+error_free_chip:
+	kfree(chip);
+error_ret:
+	return ret;
+}
+
+static int __devexit ad7314_remove(struct spi_device *spi_dev)
+{
+	struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
+
+	hwmon_device_unregister(chip->hwmon_dev);
+	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+	kfree(chip);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7314_id[] = {
+	{ "adt7301", adt7301 },
+	{ "adt7302", adt7302 },
+	{ "ad7314", ad7314 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ad7314_id);
+
+static struct spi_driver ad7314_driver = {
+	.driver = {
+		.name = "ad7314",
+		.owner = THIS_MODULE,
+	},
+	.probe = ad7314_probe,
+	.remove = __devexit_p(ad7314_remove),
+	.id_table = ad7314_id,
+};
+
+static __init int ad7314_init(void)
+{
+	return spi_register_driver(&ad7314_driver);
+}
+module_init(ad7314_init);
+
+static __exit void ad7314_exit(void)
+{
+	spi_unregister_driver(&ad7314_driver);
+}
+module_exit(ad7314_exit);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
+			" temperature sensor driver");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ad7414.c linux-libre-3.2-gnu1/drivers/hwmon/ad7414.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ad7414.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ad7414.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,10 +58,9 @@ static inline int ad7414_temp_from_reg(s
 
 static inline int ad7414_read(struct i2c_client *client, u8 reg)
 {
-	if (reg == AD7414_REG_TEMP) {
-		int value = i2c_smbus_read_word_data(client, reg);
-		return (value < 0) ? value : swab16(value);
-	} else
+	if (reg == AD7414_REG_TEMP)
+		return i2c_smbus_read_word_swapped(client, reg);
+	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ad7418.c linux-libre-3.2-gnu1/drivers/hwmon/ad7418.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ad7418.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ad7418.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,20 +76,6 @@ static struct i2c_driver ad7418_driver =
 	.id_table	= ad7418_id,
 };
 
-/* All registers are word-sized, except for the configuration registers.
- * AD7418 uses a high-byte first convention. Do NOT use those functions to
- * access the configuration registers CONF and CONF2, as they are byte-sized.
- */
-static inline int ad7418_read(struct i2c_client *client, u8 reg)
-{
-	return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
-static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ad7418_init_client(struct i2c_client *client)
 {
 	struct ad7418_data *data = i2c_get_clientdata(client);
@@ -128,7 +114,9 @@ static struct ad7418_data *ad7418_update
 		udelay(30);
 
 		for (i = 0; i < 3; i++) {
-			data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]);
+			data->temp[i] =
+				i2c_smbus_read_word_swapped(client,
+						AD7418_REG_TEMP[i]);
 		}
 
 		for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
@@ -138,11 +126,12 @@ static struct ad7418_data *ad7418_update
 
 			udelay(15);
 			data->in[data->adc_max - 1 - i] =
-				ad7418_read(client, AD7418_REG_ADC);
+				i2c_smbus_read_word_swapped(client,
+						AD7418_REG_ADC);
 		}
 
 		/* restore old configuration value */
-		ad7418_write(client, AD7418_REG_CONF, cfg);
+		i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -182,7 +171,9 @@ static ssize_t set_temp(struct device *d
 
 	mutex_lock(&data->lock);
 	data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
-	ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client,
+				     AD7418_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->lock);
 	return count;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ads1015.c linux-libre-3.2-gnu1/drivers/hwmon/ads1015.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ads1015.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ads1015.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,19 +59,6 @@ struct ads1015_data {
 	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
 };
 
-static s32 ads1015_read_reg(struct i2c_client *client, unsigned int reg)
-{
-	s32 data = i2c_smbus_read_word_data(client, reg);
-
-	return (data < 0) ? data : swab16(data);
-}
-
-static s32 ads1015_write_reg(struct i2c_client *client, unsigned int reg,
-			     u16 val)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(val));
-}
-
 static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
 			      int *value)
 {
@@ -87,7 +74,7 @@ static int ads1015_read_value(struct i2c
 	mutex_lock(&data->update_lock);
 
 	/* get channel parameters */
-	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
 	if (res < 0)
 		goto err_unlock;
 	config = res;
@@ -101,13 +88,13 @@ static int ads1015_read_value(struct i2c
 	config |= (pga & 0x0007) << 9;
 	config |= (data_rate & 0x0007) << 5;
 
-	res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+	res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config);
 	if (res < 0)
 		goto err_unlock;
 
 	/* wait until conversion finished */
 	msleep(conversion_time_ms);
-	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
 	if (res < 0)
 		goto err_unlock;
 	config = res;
@@ -117,7 +104,7 @@ static int ads1015_read_value(struct i2c
 		goto err_unlock;
 	}
 
-	res = ads1015_read_reg(client, ADS1015_CONVERSION);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
 	if (res < 0)
 		goto err_unlock;
 	conversion = res;
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ads7828.c linux-libre-3.2-gnu1/drivers/hwmon/ads7828.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ads7828.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ads7828.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,13 +74,6 @@ static int ads7828_detect(struct i2c_cli
 static int ads7828_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id);
 
-/* The ADS7828 returns the 12-bit sample in two bytes,
-	these are read as a word then byte-swapped */
-static u16 ads7828_read_value(struct i2c_client *client, u8 reg)
-{
-	return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
 static inline u8 channel_cmd_byte(int ch)
 {
 	/* cmd byte C2,C1,C0 - see datasheet */
@@ -104,7 +97,8 @@ static struct ads7828_data *ads7828_upda
 
 		for (ch = 0; ch < ADS7828_NCH; ch++) {
 			u8 cmd = channel_cmd_byte(ch);
-			data->adc_input[ch] = ads7828_read_value(client, cmd);
+			data->adc_input[ch] =
+				i2c_smbus_read_word_swapped(client, cmd);
 		}
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -203,7 +197,7 @@ static int ads7828_detect(struct i2c_cli
 	for (ch = 0; ch < ADS7828_NCH; ch++) {
 		u16 in_data;
 		u8 cmd = channel_cmd_byte(ch);
-		in_data = ads7828_read_value(client, cmd);
+		in_data = i2c_smbus_read_word_swapped(client, cmd);
 		if (in_data & 0xF000) {
 			pr_debug("%s : Doesn't look like an ads7828 device\n",
 				 __func__);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ads7871.c linux-libre-3.2-gnu1/drivers/hwmon/ads7871.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ads7871.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ads7871.c	2012-01-04 18:55:44.000000000 -0500
@@ -227,7 +227,6 @@ static int __devexit ads7871_remove(stru
 static struct spi_driver ads7871_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
-		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/asb100.c linux-libre-3.2-gnu1/drivers/hwmon/asb100.c
--- linux-libre-3.1-gnu1/drivers/hwmon/asb100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/asb100.c	2012-01-04 18:55:44.000000000 -0500
@@ -829,17 +829,17 @@ static int asb100_read_value(struct i2c_
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50: /* TEMP */
-			res = swab16(i2c_smbus_read_word_data(cl, 0));
+			res = i2c_smbus_read_word_swapped(cl, 0);
 			break;
 		case 0x52: /* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53: /* HYST */
-			res = swab16(i2c_smbus_read_word_data(cl, 2));
+			res = i2c_smbus_read_word_swapped(cl, 2);
 			break;
 		case 0x55: /* MAX */
 		default:
-			res = swab16(i2c_smbus_read_word_data(cl, 3));
+			res = i2c_smbus_read_word_swapped(cl, 3);
 			break;
 		}
 	}
@@ -877,10 +877,10 @@ static void asb100_write_value(struct i2
 			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 			break;
 		case 0x53: /* HYST */
-			i2c_smbus_write_word_data(cl, 2, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 2, value);
 			break;
 		case 0x55: /* MAX */
-			i2c_smbus_write_word_data(cl, 3, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 3, value);
 			break;
 		}
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/coretemp.c linux-libre-3.2-gnu1/drivers/hwmon/coretemp.c
--- linux-libre-3.1-gnu1/drivers/hwmon/coretemp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/coretemp.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,14 +60,13 @@ MODULE_PARM_DESC(tjmax, "TjMax value in
 #ifdef CONFIG_SMP
 #define TO_PHYS_ID(cpu)		cpu_data(cpu).phys_proc_id
 #define TO_CORE_ID(cpu)		cpu_data(cpu).cpu_core_id
-#define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 #define for_each_sibling(i, cpu)	for_each_cpu(i, cpu_sibling_mask(cpu))
 #else
 #define TO_PHYS_ID(cpu)		(cpu)
 #define TO_CORE_ID(cpu)		(cpu)
-#define TO_ATTR_NO(cpu)		(cpu)
 #define for_each_sibling(i, cpu)	for (i = 0; false; )
 #endif
+#define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 
 /*
  * Per-Core Temperature Data
@@ -325,15 +324,6 @@ static int get_tjmax(struct cpuinfo_x86
 	return adjust_tjmax(c, id, dev);
 }
 
-static void __devinit get_ucode_rev_on_cpu(void *edx)
-{
-	u32 eax;
-
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-	sync_core();
-	rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
-}
-
 static int create_name_attr(struct platform_data *pdata, struct device *dev)
 {
 	sysfs_attr_init(&pdata->name_attr.attr);
@@ -380,27 +370,16 @@ exit_free:
 static int __cpuinit chk_ucode_version(unsigned int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	int err;
-	u32 edx;
 
 	/*
 	 * Check if we have problem with errata AE18 of Core processors:
 	 * Readings might stop update when processor visited too deep sleep,
 	 * fixed for stepping D0 (6EC).
 	 */
-	if (c->x86_model == 0xe && c->x86_mask < 0xc) {
-		/* check for microcode update */
-		err = smp_call_function_single(cpu, get_ucode_rev_on_cpu,
-					       &edx, 1);
-		if (err) {
-			pr_err("Cannot determine microcode revision of "
-			       "CPU#%u (%d)!\n", cpu, err);
-			return -ENODEV;
-		} else if (edx < 0x39) {
-			pr_err("Errata AE18 not fixed, update BIOS or "
-			       "microcode of the CPU!\n");
-			return -ENODEV;
-		}
+	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
+		pr_err("Errata AE18 not fixed, update BIOS or "
+		       "microcode of the CPU!\n");
+		return -ENODEV;
 	}
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ds1621.c linux-libre-3.2-gnu1/drivers/hwmon/ds1621.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ds1621.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ds1621.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,24 +80,6 @@ struct ds1621_data {
 	u8 conf;			/* Register encoding, combined */
 };
 
-/* Temperature registers are word-sized.
-   DS1621 uses a high-byte first convention, which is exactly opposite to
-   the SMBus standard. */
-static int ds1621_read_temp(struct i2c_client *client, u8 reg)
-{
-	int ret;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds1621_init_client(struct i2c_client *client)
 {
 	u8 conf, new_conf;
@@ -136,7 +118,7 @@ static struct ds1621_data *ds1621_update
 		data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
 
 		for (i = 0; i < ARRAY_SIZE(data->temp); i++)
-			data->temp[i] = ds1621_read_temp(client,
+			data->temp[i] = i2c_smbus_read_word_swapped(client,
 							 DS1621_REG_TEMP[i]);
 
 		/* reset alarms if necessary */
@@ -177,8 +159,8 @@ static ssize_t set_temp(struct device *d
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
-	ds1621_write_temp(client, DS1621_REG_TEMP[attr->index],
-			  data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ds620.c linux-libre-3.2-gnu1/drivers/hwmon/ds620.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ds620.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ds620.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,33 +75,13 @@ struct ds620_data {
 	s16 temp[3];		/* Register values, word */
 };
 
-/*
- *  Temperature registers are word-sized.
- *  DS620 uses a high-byte first convention, which is exactly opposite to
- *  the SMBus standard.
- */
-static int ds620_read_temp(struct i2c_client *client, u8 reg)
-{
-	int ret;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int ds620_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds620_init_client(struct i2c_client *client)
 {
 	struct ds620_platform_data *ds620_info = client->dev.platform_data;
 	u16 conf, new_conf;
 
 	new_conf = conf =
-	    swab16(i2c_smbus_read_word_data(client, DS620_REG_CONF));
+	    i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 
 	/* switch to continuous conversion mode */
 	new_conf &= ~DS620_REG_CONFIG_1SHOT;
@@ -118,8 +98,7 @@ static void ds620_init_client(struct i2c
 	new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;
 
 	if (conf != new_conf)
-		i2c_smbus_write_word_data(client, DS620_REG_CONF,
-					  swab16(new_conf));
+		i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf);
 
 	/* start conversion */
 	i2c_smbus_write_byte(client, DS620_COM_START);
@@ -141,8 +120,8 @@ static struct ds620_data *ds620_update_c
 		dev_dbg(&client->dev, "Starting ds620 update\n");
 
 		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-			res = ds620_read_temp(client,
-					      DS620_REG_TEMP[i]);
+			res = i2c_smbus_read_word_swapped(client,
+							  DS620_REG_TEMP[i]);
 			if (res < 0) {
 				ret = ERR_PTR(res);
 				goto abort;
@@ -191,8 +170,8 @@ static ssize_t set_temp(struct device *d
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
-	ds620_write_temp(client, DS620_REG_TEMP[attr->index],
-			 data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client, DS620_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -210,16 +189,15 @@ static ssize_t show_alarm(struct device
 		return PTR_ERR(data);
 
 	/* reset alarms if necessary */
-	res = i2c_smbus_read_word_data(client, DS620_REG_CONF);
+	res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 	if (res < 0)
 		return res;
 
-	conf = swab16(res);
-	new_conf = conf;
+	new_conf = conf = res;
 	new_conf &= ~attr->index;
 	if (conf != new_conf) {
-		res = i2c_smbus_write_word_data(client, DS620_REG_CONF,
-						swab16(new_conf));
+		res = i2c_smbus_write_word_swapped(client, DS620_REG_CONF,
+						   new_conf);
 		if (res < 0)
 			return res;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/exynos4_tmu.c linux-libre-3.2-gnu1/drivers/hwmon/exynos4_tmu.c
--- linux-libre-3.1-gnu1/drivers/hwmon/exynos4_tmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hwmon/exynos4_tmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,514 @@
+/*
+ * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit)
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *  Donggeun Kim <dg77.kim@samsung.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/platform_data/exynos4_tmu.h>
+
+#define EXYNOS4_TMU_REG_TRIMINFO	0x0
+#define EXYNOS4_TMU_REG_CONTROL		0x20
+#define EXYNOS4_TMU_REG_STATUS		0x28
+#define EXYNOS4_TMU_REG_CURRENT_TEMP	0x40
+#define EXYNOS4_TMU_REG_THRESHOLD_TEMP	0x44
+#define EXYNOS4_TMU_REG_TRIG_LEVEL0	0x50
+#define EXYNOS4_TMU_REG_TRIG_LEVEL1	0x54
+#define EXYNOS4_TMU_REG_TRIG_LEVEL2	0x58
+#define EXYNOS4_TMU_REG_TRIG_LEVEL3	0x5C
+#define EXYNOS4_TMU_REG_PAST_TEMP0	0x60
+#define EXYNOS4_TMU_REG_PAST_TEMP1	0x64
+#define EXYNOS4_TMU_REG_PAST_TEMP2	0x68
+#define EXYNOS4_TMU_REG_PAST_TEMP3	0x6C
+#define EXYNOS4_TMU_REG_INTEN		0x70
+#define EXYNOS4_TMU_REG_INTSTAT		0x74
+#define EXYNOS4_TMU_REG_INTCLEAR	0x78
+
+#define EXYNOS4_TMU_GAIN_SHIFT		8
+#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT	24
+
+#define EXYNOS4_TMU_TRIM_TEMP_MASK	0xff
+#define EXYNOS4_TMU_CORE_ON	3
+#define EXYNOS4_TMU_CORE_OFF	2
+#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET	50
+#define EXYNOS4_TMU_TRIG_LEVEL0_MASK	0x1
+#define EXYNOS4_TMU_TRIG_LEVEL1_MASK	0x10
+#define EXYNOS4_TMU_TRIG_LEVEL2_MASK	0x100
+#define EXYNOS4_TMU_TRIG_LEVEL3_MASK	0x1000
+#define EXYNOS4_TMU_INTCLEAR_VAL	0x1111
+
+struct exynos4_tmu_data {
+	struct exynos4_tmu_platform_data *pdata;
+	struct device *hwmon_dev;
+	struct resource *mem;
+	void __iomem *base;
+	int irq;
+	struct work_struct irq_work;
+	struct mutex lock;
+	struct clk *clk;
+	u8 temp_error1, temp_error2;
+};
+
+/*
+ * TMU treats temperature as a mapped temperature code.
+ * The temperature is converted differently depending on the calibration type.
+ */
+static int temp_to_code(struct exynos4_tmu_data *data, u8 temp)
+{
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp_code;
+
+	/* temp should range between 25 and 125 */
+	if (temp < 25 || temp > 125) {
+		temp_code = -EINVAL;
+		goto out;
+	}
+
+	switch (pdata->cal_type) {
+	case TYPE_TWO_POINT_TRIMMING:
+		temp_code = (temp - 25) *
+		    (data->temp_error2 - data->temp_error1) /
+		    (85 - 25) + data->temp_error1;
+		break;
+	case TYPE_ONE_POINT_TRIMMING:
+		temp_code = temp + data->temp_error1 - 25;
+		break;
+	default:
+		temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		break;
+	}
+out:
+	return temp_code;
+}
+
+/*
+ * Calculate a temperature value from a temperature code.
+ * The unit of the temperature is degree Celsius.
+ */
+static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code)
+{
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp;
+
+	/* temp_code should range between 75 and 175 */
+	if (temp_code < 75 || temp_code > 175) {
+		temp = -ENODATA;
+		goto out;
+	}
+
+	switch (pdata->cal_type) {
+	case TYPE_TWO_POINT_TRIMMING:
+		temp = (temp_code - data->temp_error1) * (85 - 25) /
+		    (data->temp_error2 - data->temp_error1) + 25;
+		break;
+	case TYPE_ONE_POINT_TRIMMING:
+		temp = temp_code - data->temp_error1 + 25;
+		break;
+	default:
+		temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		break;
+	}
+out:
+	return temp;
+}
+
+static int exynos4_tmu_initialize(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int status, trim_info;
+	int ret = 0, threshold_code;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	status = readb(data->base + EXYNOS4_TMU_REG_STATUS);
+	if (!status) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* Save trimming info in order to perform calibration */
+	trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO);
+	data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK;
+	data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK);
+
+	/* Write temperature code for threshold */
+	threshold_code = temp_to_code(data, pdata->threshold);
+	if (threshold_code < 0) {
+		ret = threshold_code;
+		goto out;
+	}
+	writeb(threshold_code,
+		data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP);
+
+	writeb(pdata->trigger_levels[0],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0);
+	writeb(pdata->trigger_levels[1],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1);
+	writeb(pdata->trigger_levels[2],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2);
+	writeb(pdata->trigger_levels[3],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3);
+
+	writel(EXYNOS4_TMU_INTCLEAR_VAL,
+		data->base + EXYNOS4_TMU_REG_INTCLEAR);
+out:
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static void exynos4_tmu_control(struct platform_device *pdev, bool on)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int con, interrupt_en;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT |
+		pdata->gain << EXYNOS4_TMU_GAIN_SHIFT;
+	if (on) {
+		con |= EXYNOS4_TMU_CORE_ON;
+		interrupt_en = pdata->trigger_level3_en << 12 |
+			pdata->trigger_level2_en << 8 |
+			pdata->trigger_level1_en << 4 |
+			pdata->trigger_level0_en;
+	} else {
+		con |= EXYNOS4_TMU_CORE_OFF;
+		interrupt_en = 0; /* Disable all interrupts */
+	}
+	writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN);
+	writel(con, data->base + EXYNOS4_TMU_REG_CONTROL);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+}
+
+static int exynos4_tmu_read(struct exynos4_tmu_data *data)
+{
+	u8 temp_code;
+	int temp;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP);
+	temp = code_to_temp(data, temp_code);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+
+	return temp;
+}
+
+static void exynos4_tmu_work(struct work_struct *work)
+{
+	struct exynos4_tmu_data *data = container_of(work,
+			struct exynos4_tmu_data, irq_work);
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR);
+
+	kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
+
+	enable_irq(data->irq);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+}
+
+static irqreturn_t exynos4_tmu_irq(int irq, void *id)
+{
+	struct exynos4_tmu_data *data = id;
+
+	disable_irq_nosync(irq);
+	schedule_work(&data->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static ssize_t exynos4_tmu_show_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "exynos4-tmu\n");
+}
+
+static ssize_t exynos4_tmu_show_temp(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = exynos4_tmu_read(data);
+	if (ret < 0)
+		return ret;
+
+	/* convert from degree Celsius to millidegree Celsius */
+	return sprintf(buf, "%d\n", ret * 1000);
+}
+
+static ssize_t exynos4_tmu_show_alarm(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp;
+	unsigned int trigger_level;
+
+	temp = exynos4_tmu_read(data);
+	if (temp < 0)
+		return temp;
+
+	trigger_level = pdata->threshold + pdata->trigger_levels[attr->index];
+
+	return sprintf(buf, "%d\n", !!(temp > trigger_level));
+}
+
+static ssize_t exynos4_tmu_show_level(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int temp = pdata->threshold +
+			pdata->trigger_levels[attr->index];
+
+	return sprintf(buf, "%u\n", temp * 1000);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO,
+		exynos4_tmu_show_level, NULL, 3);
+
+static struct attribute *exynos4_tmu_attributes[] = {
+	&dev_attr_name.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group exynos4_tmu_attr_group = {
+	.attrs = exynos4_tmu_attributes,
+};
+
+static int __devinit exynos4_tmu_probe(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data;
+	struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform init data supplied.\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+		return -ENOMEM;
+	}
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq < 0) {
+		ret = data->irq;
+		dev_err(&pdev->dev, "Failed to get platform irq\n");
+		goto err_free;
+	}
+
+	INIT_WORK(&data->irq_work, exynos4_tmu_work);
+
+	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!data->mem) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get platform resource\n");
+		goto err_free;
+	}
+
+	data->mem = request_mem_region(data->mem->start,
+			resource_size(data->mem), pdev->name);
+	if (!data->mem) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "Failed to request memory region\n");
+		goto err_free;
+	}
+
+	data->base = ioremap(data->mem->start, resource_size(data->mem));
+	if (!data->base) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "Failed to ioremap memory\n");
+		goto err_mem_region;
+	}
+
+	ret = request_irq(data->irq, exynos4_tmu_irq,
+		IRQF_TRIGGER_RISING,
+		"exynos4-tmu", data);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
+		goto err_io_remap;
+	}
+
+	data->clk = clk_get(NULL, "tmu_apbif");
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		dev_err(&pdev->dev, "Failed to get clock\n");
+		goto err_irq;
+	}
+
+	data->pdata = pdata;
+	platform_set_drvdata(pdev, data);
+	mutex_init(&data->lock);
+
+	ret = exynos4_tmu_initialize(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize TMU\n");
+		goto err_clk;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to create sysfs group\n");
+		goto err_clk;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		dev_err(&pdev->dev, "Failed to register hwmon device\n");
+		goto err_create_group;
+	}
+
+	exynos4_tmu_control(pdev, true);
+
+	return 0;
+
+err_create_group:
+	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+err_clk:
+	platform_set_drvdata(pdev, NULL);
+	clk_put(data->clk);
+err_irq:
+	free_irq(data->irq, data);
+err_io_remap:
+	iounmap(data->base);
+err_mem_region:
+	release_mem_region(data->mem->start, resource_size(data->mem));
+err_free:
+	kfree(data);
+
+	return ret;
+}
+
+static int __devexit exynos4_tmu_remove(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+
+	exynos4_tmu_control(pdev, false);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+
+	clk_put(data->clk);
+
+	free_irq(data->irq, data);
+
+	iounmap(data->base);
+	release_mem_region(data->mem->start, resource_size(data->mem));
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_tmu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	exynos4_tmu_control(pdev, false);
+
+	return 0;
+}
+
+static int exynos4_tmu_resume(struct platform_device *pdev)
+{
+	exynos4_tmu_initialize(pdev);
+	exynos4_tmu_control(pdev, true);
+
+	return 0;
+}
+#else
+#define exynos4_tmu_suspend NULL
+#define exynos4_tmu_resume NULL
+#endif
+
+static struct platform_driver exynos4_tmu_driver = {
+	.driver = {
+		.name   = "exynos4-tmu",
+		.owner  = THIS_MODULE,
+	},
+	.probe = exynos4_tmu_probe,
+	.remove	= __devexit_p(exynos4_tmu_remove),
+	.suspend = exynos4_tmu_suspend,
+	.resume = exynos4_tmu_resume,
+};
+
+module_platform_driver(exynos4_tmu_driver);
+
+MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:exynos4-tmu");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/f71882fg.c linux-libre-3.2-gnu1/drivers/hwmon/f71882fg.c
--- linux-libre-3.1-gnu1/drivers/hwmon/f71882fg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/f71882fg.c	2012-01-04 18:55:44.000000000 -0500
@@ -605,7 +605,7 @@ static struct sensor_device_attribute_2
 
 /* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
    standard models */
-static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -627,7 +627,7 @@ static struct sensor_device_attribute_2
 		      0, 0),
 	SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
 	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 1),
@@ -649,7 +649,7 @@ static struct sensor_device_attribute_2
 		      0, 1),
 	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-
+}, {
 	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 2),
@@ -671,12 +671,12 @@ static struct sensor_device_attribute_2
 		      0, 2),
 	SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-};
+} };
 
 /* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
    pwm setting when the temperature is above the pwmX_auto_point1_temp can be
    programmed instead of being hardcoded to 0xff */
-static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -701,7 +701,7 @@ static struct sensor_device_attribute_2
 		      0, 0),
 	SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
 	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 1),
@@ -726,7 +726,7 @@ static struct sensor_device_attribute_2
 		      0, 1),
 	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-
+}, {
 	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 2),
@@ -751,7 +751,7 @@ static struct sensor_device_attribute_2
 		      0, 2),
 	SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-};
+} };
 
 /* PWM attr for the standard models */
 static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
@@ -928,7 +928,7 @@ static struct sensor_device_attribute_2
 /* PWM attr for the f8000, zones mapped to temp instead of to pwm!
    Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
    F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
-static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -969,7 +969,7 @@ static struct sensor_device_attribute_2
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 2),
 	SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-
+}, {
 	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 1),
@@ -1010,7 +1010,7 @@ static struct sensor_device_attribute_2
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 0),
 	SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
 	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 2),
@@ -1051,7 +1051,7 @@ static struct sensor_device_attribute_2
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 1),
 	SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-};
+} };
 
 /* Super I/O functions */
 static inline int superio_inb(int base, int reg)
@@ -2154,6 +2154,104 @@ static void f71882fg_remove_sysfs_files(
 		device_remove_file(&pdev->dev, &attr[i].dev_attr);
 }
 
+static int __devinit f71882fg_create_fan_sysfs_files(
+	struct platform_device *pdev, int idx)
+{
+	struct f71882fg_data *data = platform_get_drvdata(pdev);
+	int err;
+
+	/* Sanity check the pwm setting */
+	err = 0;
+	switch (data->type) {
+	case f71858fg:
+		if (((data->pwm_enable >> (idx * 2)) & 3) == 3)
+			err = 1;
+		break;
+	case f71862fg:
+		if (((data->pwm_enable >> (idx * 2)) & 1) != 1)
+			err = 1;
+		break;
+	case f8000:
+		if (idx == 2)
+			err = data->pwm_enable & 0x20;
+		break;
+	default:
+		break;
+	}
+	if (err) {
+		dev_err(&pdev->dev,
+			"Invalid (reserved) pwm settings: 0x%02x, "
+			"skipping fan %d\n",
+			(data->pwm_enable >> (idx * 2)) & 3, idx + 1);
+		return 0; /* This is a non fatal condition */
+	}
+
+	err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],
+					  ARRAY_SIZE(fxxxx_fan_attr[0]));
+	if (err)
+		return err;
+
+	if (f71882fg_fan_has_beep[data->type]) {
+		err = f71882fg_create_sysfs_files(pdev,
+						  &fxxxx_fan_beep_attr[idx],
+						  1);
+		if (err)
+			return err;
+	}
+
+	dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,
+		 (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");
+
+	/* Check for unsupported auto pwm settings */
+	switch (data->type) {
+	case f71808e:
+	case f71808a:
+	case f71869:
+	case f71869a:
+	case f71889fg:
+	case f71889ed:
+	case f71889a:
+		data->pwm_auto_point_mapping[idx] =
+			f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));
+		if ((data->pwm_auto_point_mapping[idx] & 0x80) ||
+		    (data->pwm_auto_point_mapping[idx] & 3) == 0) {
+			dev_warn(&pdev->dev,
+				 "Auto pwm controlled by raw digital "
+				 "data, disabling pwm auto_point "
+				 "sysfs attributes for fan %d\n", idx + 1);
+			return 0; /* This is a non fatal condition */
+		}
+		break;
+	default:
+		break;
+	}
+
+	switch (data->type) {
+	case f71862fg:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f71862fg_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));
+		break;
+	case f71808e:
+	case f71869:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f71869_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f71869_auto_pwm_attr[0]));
+		break;
+	case f8000:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f8000_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f8000_auto_pwm_attr[0]));
+		break;
+	default:
+		err = f71882fg_create_sysfs_files(pdev,
+					&fxxxx_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));
+	}
+
+	return err;
+}
+
 static int __devinit f71882fg_probe(struct platform_device *pdev)
 {
 	struct f71882fg_data *data;
@@ -2272,117 +2370,29 @@ static int __devinit f71882fg_probe(stru
 		data->pwm_enable =
 			f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
 
-		/* Sanity check the pwm settings */
-		switch (data->type) {
-		case f71858fg:
-			err = 0;
-			for (i = 0; i < nr_fans; i++)
-				if (((data->pwm_enable >> (i * 2)) & 3) == 3)
-					err = 1;
-			break;
-		case f71862fg:
-			err = (data->pwm_enable & 0x15) != 0x15;
-			break;
-		case f8000:
-			err = data->pwm_enable & 0x20;
-			break;
-		default:
-			err = 0;
-			break;
-		}
-		if (err) {
-			dev_err(&pdev->dev,
-				"Invalid (reserved) pwm settings: 0x%02x\n",
-				(unsigned int)data->pwm_enable);
-			err = -ENODEV;
-			goto exit_unregister_sysfs;
-		}
-
-		err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
-				ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
-		if (err)
-			goto exit_unregister_sysfs;
-
-		if (f71882fg_fan_has_beep[data->type]) {
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_fan_beep_attr, nr_fans);
+		for (i = 0; i < nr_fans; i++) {
+			err = f71882fg_create_fan_sysfs_files(pdev, i);
 			if (err)
 				goto exit_unregister_sysfs;
 		}
 
-		switch (data->type) {
-		case f71808e:
-		case f71808a:
-		case f71869:
-		case f71869a:
-		case f71889fg:
-		case f71889ed:
-		case f71889a:
-			for (i = 0; i < nr_fans; i++) {
-				data->pwm_auto_point_mapping[i] =
-					f71882fg_read8(data,
-						F71882FG_REG_POINT_MAPPING(i));
-				if ((data->pwm_auto_point_mapping[i] & 0x80) ||
-				    (data->pwm_auto_point_mapping[i] & 3) == 0)
-					break;
-			}
-			if (i != nr_fans) {
-				dev_warn(&pdev->dev,
-					 "Auto pwm controlled by raw digital "
-					 "data, disabling pwm auto_point "
-					 "sysfs attributes\n");
-				goto no_pwm_auto_point;
-			}
-			break;
-		default:
-			break;
-		}
-
+		/* Some types have 1 extra fan with limited functionality */
 		switch (data->type) {
 		case f71808a:
 			err = f71882fg_create_sysfs_files(pdev,
-				&fxxxx_auto_pwm_attr[0][0],
-				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
-			if (err)
-				goto exit_unregister_sysfs;
-			err = f71882fg_create_sysfs_files(pdev,
 					f71808a_fan3_attr,
 					ARRAY_SIZE(f71808a_fan3_attr));
 			break;
-		case f71862fg:
-			err = f71882fg_create_sysfs_files(pdev,
-					f71862fg_auto_pwm_attr,
-					ARRAY_SIZE(f71862fg_auto_pwm_attr));
-			break;
-		case f71808e:
-		case f71869:
-			err = f71882fg_create_sysfs_files(pdev,
-					f71869_auto_pwm_attr,
-					ARRAY_SIZE(f71869_auto_pwm_attr));
-			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
 					f8000_fan_attr,
 					ARRAY_SIZE(f8000_fan_attr));
-			if (err)
-				goto exit_unregister_sysfs;
-			err = f71882fg_create_sysfs_files(pdev,
-					f8000_auto_pwm_attr,
-					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
 		default:
-			err = f71882fg_create_sysfs_files(pdev,
-				&fxxxx_auto_pwm_attr[0][0],
-				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
+			break;
 		}
 		if (err)
 			goto exit_unregister_sysfs;
-
-no_pwm_auto_point:
-		for (i = 0; i < nr_fans; i++)
-			dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
-				 (data->pwm_enable & (1 << 2 * i)) ?
-				 "duty-cycle" : "RPM");
 	}
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -2476,22 +2486,23 @@ static int f71882fg_remove(struct platfo
 			break;
 		case f71862fg:
 			f71882fg_remove_sysfs_files(pdev,
-					f71862fg_auto_pwm_attr,
-					ARRAY_SIZE(f71862fg_auto_pwm_attr));
+				&f71862fg_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *
+					nr_fans);
 			break;
 		case f71808e:
 		case f71869:
 			f71882fg_remove_sysfs_files(pdev,
-					f71869_auto_pwm_attr,
-					ARRAY_SIZE(f71869_auto_pwm_attr));
+				&f71869_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);
 			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
 					f8000_fan_attr,
 					ARRAY_SIZE(f8000_fan_attr));
 			f71882fg_remove_sysfs_files(pdev,
-					f8000_auto_pwm_attr,
-					ARRAY_SIZE(f8000_auto_pwm_attr));
+				&f8000_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);
 			break;
 		default:
 			f71882fg_remove_sysfs_files(pdev,
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/gl518sm.c linux-libre-3.2-gnu1/drivers/hwmon/gl518sm.c
--- linux-libre-3.1-gnu1/drivers/hwmon/gl518sm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/gl518sm.c	2012-01-04 18:55:44.000000000 -0500
@@ -591,7 +591,7 @@ static int gl518_remove(struct i2c_clien
 static int gl518_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
@@ -599,7 +599,7 @@ static int gl518_read_value(struct i2c_c
 static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 	else
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/gl520sm.c linux-libre-3.2-gnu1/drivers/hwmon/gl520sm.c
--- linux-libre-3.1-gnu1/drivers/hwmon/gl520sm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/gl520sm.c	2012-01-04 18:55:44.000000000 -0500
@@ -821,7 +821,7 @@ static int gl520_remove(struct i2c_clien
 static int gl520_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
@@ -829,7 +829,7 @@ static int gl520_read_value(struct i2c_c
 static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 	else
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/gpio-fan.c linux-libre-3.2-gnu1/drivers/hwmon/gpio-fan.c
--- linux-libre-3.1-gnu1/drivers/hwmon/gpio-fan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/gpio-fan.c	2012-01-04 18:55:44.000000000 -0500
@@ -539,18 +539,7 @@ static struct platform_driver gpio_fan_d
 	},
 };
 
-static int __init gpio_fan_init(void)
-{
-	return platform_driver_register(&gpio_fan_driver);
-}
-
-static void __exit gpio_fan_exit(void)
-{
-	platform_driver_unregister(&gpio_fan_driver);
-}
-
-module_init(gpio_fan_init);
-module_exit(gpio_fan_exit);
+module_platform_driver(gpio_fan_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("GPIO FAN driver");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,7 @@
 
 static struct class *hwmon_class;
 
-static DEFINE_IDR(hwmon_idr);
-static DEFINE_SPINLOCK(idr_lock);
+static DEFINE_IDA(hwmon_ida);
 
 /**
  * hwmon_device_register - register w/ hwmon
@@ -42,30 +41,17 @@ static DEFINE_SPINLOCK(idr_lock);
 struct device *hwmon_device_register(struct device *dev)
 {
 	struct device *hwdev;
-	int id, err;
-
-again:
-	if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock(&idr_lock);
-	err = idr_get_new(&hwmon_idr, NULL, &id);
-	spin_unlock(&idr_lock);
+	int id;
 
-	if (unlikely(err == -EAGAIN))
-		goto again;
-	else if (unlikely(err))
-		return ERR_PTR(err);
+	id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return ERR_PTR(id);
 
-	id = id & MAX_ID_MASK;
 	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
 			      HWMON_ID_FORMAT, id);
 
-	if (IS_ERR(hwdev)) {
-		spin_lock(&idr_lock);
-		idr_remove(&hwmon_idr, id);
-		spin_unlock(&idr_lock);
-	}
+	if (IS_ERR(hwdev))
+		ida_simple_remove(&hwmon_ida, id);
 
 	return hwdev;
 }
@@ -81,9 +67,7 @@ void hwmon_device_unregister(struct devi
 
 	if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
 		device_unregister(dev);
-		spin_lock(&idr_lock);
-		idr_remove(&hwmon_idr, id);
-		spin_unlock(&idr_lock);
+		ida_simple_remove(&hwmon_ida, id);
 	} else
 		dev_dbg(dev->parent,
 			"hwmon_device_unregister() failed: bad class ID!\n");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ibmaem.c linux-libre-3.2-gnu1/drivers/hwmon/ibmaem.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ibmaem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ibmaem.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,8 +88,7 @@
 #define AEM_MIN_POWER_INTERVAL	200
 #define UJ_PER_MJ		1000L
 
-static DEFINE_IDR(aem_idr);
-static DEFINE_SPINLOCK(aem_idr_lock);
+static DEFINE_IDA(aem_ida);
 
 static struct platform_driver aem_driver = {
 	.driver = {
@@ -148,8 +147,9 @@ struct aem_data {
 	int			id;
 	struct aem_ipmi_data	ipmi;
 
-	/* Function to update sensors */
+	/* Function and buffer to update sensors */
 	void (*update)(struct aem_data *data);
+	struct aem_read_sensor_resp *rs_resp;
 
 	/*
 	 * AEM 1.x sensors:
@@ -246,8 +246,6 @@ static void aem_bmc_gone(int iface);
 static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
 
 static void aem_remove_sensors(struct aem_data *data);
-static int aem_init_aem1(struct aem_ipmi_data *probe);
-static int aem_init_aem2(struct aem_ipmi_data *probe);
 static int aem1_find_sensors(struct aem_data *data);
 static int aem2_find_sensors(struct aem_data *data);
 static void update_aem1_sensors(struct aem_data *data);
@@ -356,47 +354,16 @@ static void aem_msg_handler(struct ipmi_
 	complete(&data->read_complete);
 }
 
-/* ID functions */
-
-/* Obtain an id */
-static int aem_idr_get(int *id)
-{
-	int i, err;
-
-again:
-	if (unlikely(!idr_pre_get(&aem_idr, GFP_KERNEL)))
-		return -ENOMEM;
-
-	spin_lock(&aem_idr_lock);
-	err = idr_get_new(&aem_idr, NULL, &i);
-	spin_unlock(&aem_idr_lock);
-
-	if (unlikely(err == -EAGAIN))
-		goto again;
-	else if (unlikely(err))
-		return err;
-
-	*id = i & MAX_ID_MASK;
-	return 0;
-}
-
-/* Release an object ID */
-static void aem_idr_put(int id)
-{
-	spin_lock(&aem_idr_lock);
-	idr_remove(&aem_idr, id);
-	spin_unlock(&aem_idr_lock);
-}
-
 /* Sensor support functions */
 
-/* Read a sensor value */
+/* Read a sensor value; must be called with data->lock held */
 static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
 			   void *buf, size_t size)
 {
 	int rs_size, res;
 	struct aem_read_sensor_req rs_req;
-	struct aem_read_sensor_resp *rs_resp;
+	/* Use preallocated rx buffer */
+	struct aem_read_sensor_resp *rs_resp = data->rs_resp;
 	struct aem_ipmi_data *ipmi = &data->ipmi;
 
 	/* AEM registers are 1, 2, 4 or 8 bytes */
@@ -422,10 +389,6 @@ static int aem_read_sensor(struct aem_da
 	ipmi->tx_message.data_len = sizeof(rs_req);
 
 	rs_size = sizeof(*rs_resp) + size;
-	rs_resp = kzalloc(rs_size, GFP_KERNEL);
-	if (!rs_resp)
-		return -ENOMEM;
-
 	ipmi->rx_msg_data = rs_resp;
 	ipmi->rx_msg_len = rs_size;
 
@@ -468,7 +431,6 @@ static int aem_read_sensor(struct aem_da
 	res = 0;
 
 out:
-	kfree(rs_resp);
 	return res;
 }
 
@@ -526,11 +488,12 @@ static void aem_delete(struct aem_data *
 {
 	list_del(&data->list);
 	aem_remove_sensors(data);
+	kfree(data->rs_resp);
 	hwmon_device_unregister(data->hwmon_dev);
 	ipmi_destroy_user(data->ipmi.user);
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 	kfree(data);
 }
 
@@ -587,7 +550,8 @@ static int aem_init_aem1_inst(struct aem
 		data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
 
 	/* Create sub-device for this fw instance */
-	if (aem_idr_get(&data->id))
+	data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+	if (data->id < 0)
 		goto id_err;
 
 	data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -602,24 +566,31 @@ static int aem_init_aem1_inst(struct aem
 	platform_set_drvdata(data->pdev, data);
 
 	/* Set up IPMI interface */
-	if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-			       probe->bmc_device))
+	res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+				 probe->bmc_device);
+	if (res)
 		goto ipmi_err;
 
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
 	if (IS_ERR(data->hwmon_dev)) {
 		dev_err(&data->pdev->dev, "Unable to register hwmon "
 			"device for IPMI interface %d\n",
 			probe->interface);
+		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
 	}
 
 	data->update = update_aem1_sensors;
+	data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+	if (!data->rs_resp) {
+		res = -ENOMEM;
+		goto alloc_resp_err;
+	}
 
 	/* Find sensors */
-	if (aem1_find_sensors(data))
+	res = aem1_find_sensors(data);
+	if (res)
 		goto sensor_err;
 
 	/* Add to our list of AEM devices */
@@ -631,6 +602,8 @@ static int aem_init_aem1_inst(struct aem
 	return 0;
 
 sensor_err:
+	kfree(data->rs_resp);
+alloc_resp_err:
 	hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
 	ipmi_destroy_user(data->ipmi.user);
@@ -638,7 +611,7 @@ ipmi_err:
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
 dev_err:
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 id_err:
 	kfree(data);
 
@@ -646,7 +619,7 @@ id_err:
 }
 
 /* Find and initialize all AEM1 instances */
-static int aem_init_aem1(struct aem_ipmi_data *probe)
+static void aem_init_aem1(struct aem_ipmi_data *probe)
 {
 	int num, i, err;
 
@@ -657,11 +630,8 @@ static int aem_init_aem1(struct aem_ipmi
 			dev_err(probe->bmc_device,
 				"Error %d initializing AEM1 0x%X\n",
 				err, i);
-			return err;
 		}
 	}
-
-	return 0;
 }
 
 /* Probe functions for AEM2 devices */
@@ -720,7 +690,8 @@ static int aem_init_aem2_inst(struct aem
 		data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
 
 	/* Create sub-device for this fw instance */
-	if (aem_idr_get(&data->id))
+	data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+	if (data->id < 0)
 		goto id_err;
 
 	data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -735,24 +706,31 @@ static int aem_init_aem2_inst(struct aem
 	platform_set_drvdata(data->pdev, data);
 
 	/* Set up IPMI interface */
-	if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-			       probe->bmc_device))
+	res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+				 probe->bmc_device);
+	if (res)
 		goto ipmi_err;
 
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
 	if (IS_ERR(data->hwmon_dev)) {
 		dev_err(&data->pdev->dev, "Unable to register hwmon "
 			"device for IPMI interface %d\n",
 			probe->interface);
+		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
 	}
 
 	data->update = update_aem2_sensors;
+	data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+	if (!data->rs_resp) {
+		res = -ENOMEM;
+		goto alloc_resp_err;
+	}
 
 	/* Find sensors */
-	if (aem2_find_sensors(data))
+	res = aem2_find_sensors(data);
+	if (res)
 		goto sensor_err;
 
 	/* Add to our list of AEM devices */
@@ -764,6 +742,8 @@ static int aem_init_aem2_inst(struct aem
 	return 0;
 
 sensor_err:
+	kfree(data->rs_resp);
+alloc_resp_err:
 	hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
 	ipmi_destroy_user(data->ipmi.user);
@@ -771,7 +751,7 @@ ipmi_err:
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
 dev_err:
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 id_err:
 	kfree(data);
 
@@ -779,7 +759,7 @@ id_err:
 }
 
 /* Find and initialize all AEM2 instances */
-static int aem_init_aem2(struct aem_ipmi_data *probe)
+static void aem_init_aem2(struct aem_ipmi_data *probe)
 {
 	struct aem_find_instance_resp fi_resp;
 	int err;
@@ -798,12 +778,9 @@ static int aem_init_aem2(struct aem_ipmi
 			dev_err(probe->bmc_device,
 				"Error %d initializing AEM2 0x%X\n",
 				err, fi_resp.module_handle);
-			return err;
 		}
 		i++;
 	}
-
-	return 0;
 }
 
 /* Probe a BMC for AEM firmware instances */
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/jc42.c linux-libre-3.2-gnu1/drivers/hwmon/jc42.c
--- linux-libre-3.1-gnu1/drivers/hwmon/jc42.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/jc42.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,8 +154,6 @@ static int jc42_probe(struct i2c_client
 		      const struct i2c_device_id *id);
 static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info);
 static int jc42_remove(struct i2c_client *client);
-static int jc42_read_value(struct i2c_client *client, u8 reg);
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value);
 
 static struct jc42_data *jc42_update_device(struct device *dev);
 
@@ -187,7 +185,7 @@ static int jc42_suspend(struct device *d
 	struct jc42_data *data = i2c_get_clientdata(client);
 
 	data->config |= JC42_CFG_SHUTDOWN;
-	jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
 	return 0;
 }
 
@@ -197,7 +195,7 @@ static int jc42_resume(struct device *de
 	struct jc42_data *data = i2c_get_clientdata(client);
 
 	data->config &= ~JC42_CFG_SHUTDOWN;
-	jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
 	return 0;
 }
 
@@ -315,7 +313,7 @@ static ssize_t set_##value(struct device
 		return -EINVAL;						\
 	mutex_lock(&data->update_lock);					\
 	data->value = jc42_temp_to_reg(val, data->extended);		\
-	err = jc42_write_value(client, reg, data->value);		\
+	err = i2c_smbus_write_word_swapped(client, reg, data->value);	\
 	if (err < 0)							\
 		ret = err;						\
 	mutex_unlock(&data->update_lock);				\
@@ -357,7 +355,8 @@ static ssize_t set_temp_crit_hyst(struct
 	data->config = (data->config
 			& ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
 	  | (hyst << JC42_CFG_HYST_SHIFT);
-	err = jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+					   data->config);
 	if (err < 0)
 		ret = err;
 	mutex_unlock(&data->update_lock);
@@ -452,10 +451,10 @@ static int jc42_detect(struct i2c_client
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	cap = jc42_read_value(new_client, JC42_REG_CAP);
-	config = jc42_read_value(new_client, JC42_REG_CONFIG);
-	manid = jc42_read_value(new_client, JC42_REG_MANID);
-	devid = jc42_read_value(new_client, JC42_REG_DEVICEID);
+	cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
+	config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
+	manid = i2c_smbus_read_word_swapped(new_client, JC42_REG_MANID);
+	devid = i2c_smbus_read_word_swapped(new_client, JC42_REG_DEVICEID);
 
 	if (cap < 0 || config < 0 || manid < 0 || devid < 0)
 		return -ENODEV;
@@ -489,14 +488,14 @@ static int jc42_probe(struct i2c_client
 	i2c_set_clientdata(new_client, data);
 	mutex_init(&data->update_lock);
 
-	cap = jc42_read_value(new_client, JC42_REG_CAP);
+	cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
 	if (cap < 0) {
 		err = -EINVAL;
 		goto exit_free;
 	}
 	data->extended = !!(cap & JC42_CAP_RANGE);
 
-	config = jc42_read_value(new_client, JC42_REG_CONFIG);
+	config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
 	if (config < 0) {
 		err = -EINVAL;
 		goto exit_free;
@@ -504,7 +503,8 @@ static int jc42_probe(struct i2c_client
 	data->orig_config = config;
 	if (config & JC42_CFG_SHUTDOWN) {
 		config &= ~JC42_CFG_SHUTDOWN;
-		jc42_write_value(new_client, JC42_REG_CONFIG, config);
+		i2c_smbus_write_word_swapped(new_client, JC42_REG_CONFIG,
+					     config);
 	}
 	data->config = config;
 
@@ -535,25 +535,12 @@ static int jc42_remove(struct i2c_client
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &jc42_group);
 	if (data->config != data->orig_config)
-		jc42_write_value(client, JC42_REG_CONFIG, data->orig_config);
+		i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+					     data->orig_config);
 	kfree(data);
 	return 0;
 }
 
-/* All registers are word-sized. */
-static int jc42_read_value(struct i2c_client *client, u8 reg)
-{
-	int ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static struct jc42_data *jc42_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -564,28 +551,29 @@ static struct jc42_data *jc42_update_dev
 	mutex_lock(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-		val = jc42_read_value(client, JC42_REG_TEMP);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_input = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_CRITICAL);
+		val = i2c_smbus_read_word_swapped(client,
+						  JC42_REG_TEMP_CRITICAL);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_crit = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_LOWER);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_min = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_UPPER);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/jz4740-hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/jz4740-hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/jz4740-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/jz4740-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,7 +59,7 @@ static ssize_t jz4740_hwmon_read_adcin(s
 {
 	struct jz4740_hwmon *hwmon = dev_get_drvdata(dev);
 	struct completion *completion = &hwmon->read_completion;
-	unsigned long t;
+	long t;
 	unsigned long val;
 	int ret;
 
@@ -203,7 +203,7 @@ static int __devexit jz4740_hwmon_remove
 	return 0;
 }
 
-struct platform_driver jz4740_hwmon_driver = {
+static struct platform_driver jz4740_hwmon_driver = {
 	.probe	= jz4740_hwmon_probe,
 	.remove = __devexit_p(jz4740_hwmon_remove),
 	.driver = {
@@ -212,17 +212,7 @@ struct platform_driver jz4740_hwmon_driv
 	},
 };
 
-static int __init jz4740_hwmon_init(void)
-{
-	return platform_driver_register(&jz4740_hwmon_driver);
-}
-module_init(jz4740_hwmon_init);
-
-static void __exit jz4740_hwmon_exit(void)
-{
-	platform_driver_unregister(&jz4740_hwmon_driver);
-}
-module_exit(jz4740_hwmon_exit);
+module_platform_driver(jz4740_hwmon_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC HWMON driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/Kconfig linux-libre-3.2-gnu1/drivers/hwmon/Kconfig
--- linux-libre-3.1-gnu1/drivers/hwmon/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,16 @@ config SENSORS_ABITUGURU3
 	  This driver can also be built as a module.  If so, the module
 	  will be called abituguru3.
 
+config SENSORS_AD7314
+	tristate "Analog Devices AD7314 and compatibles"
+	depends on SPI && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Analog Devices
+	  AD7314, ADT7301 and ADT7302 temperature sensors.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called ad7314.
+
 config SENSORS_AD7414
 	tristate "Analog Devices AD7414"
 	depends on I2C && EXPERIMENTAL
@@ -303,6 +313,16 @@ config SENSORS_DS1621
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1621.
 
+config SENSORS_EXYNOS4_TMU
+	tristate "Temperature sensor on Samsung EXYNOS4"
+	depends on ARCH_EXYNOS4
+	help
+	  If you say yes here you get support for TMU (Thermal Managment
+	  Unit) on SAMSUNG EXYNOS4 series of SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called exynos4-tmu.
+
 config SENSORS_I5K_AMB
 	tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
 	depends on PCI && EXPERIMENTAL
@@ -315,6 +335,7 @@ config SENSORS_I5K_AMB
 
 config SENSORS_F71805F
 	tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
+	depends on !PPC
 	help
 	  If you say yes here you get support for hardware monitoring
 	  features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG
@@ -325,6 +346,7 @@ config SENSORS_F71805F
 
 config SENSORS_F71882FG
 	tristate "Fintek F71882FG and compatibles"
+	depends on !PPC
 	help
 	  If you say yes here you get support for hardware monitoring
 	  features of many Fintek Super-I/O (LPC) chips. The currently
@@ -448,6 +470,7 @@ config SENSORS_IBMPEX
 
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for ITE IT8705F, IT8712F,
@@ -531,6 +554,7 @@ config SENSORS_LM75
 	  If you say yes here you get support for one common type of
 	  temperature sensor chip, with models including:
 
+		- Analog Devices ADT75
 		- Dallas Semiconductor DS75 and DS1775
 		- Maxim MAX6625 and MAX6626
 		- Microchip MCP980x
@@ -803,6 +827,7 @@ config SENSORS_NTC_THERMISTOR
 
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get access to the hardware monitoring
@@ -816,6 +841,7 @@ config SENSORS_PC87360
 
 config SENSORS_PC87427
 	tristate "National Semiconductor PC87427"
+	depends on !PPC
 	help
 	  If you say yes here you get access to the hardware monitoring
 	  functions of the National Semiconductor PC87427 Super-I/O chip.
@@ -907,7 +933,7 @@ config SENSORS_SMM665
 
 config SENSORS_DME1737
 	tristate "SMSC DME1737, SCH311x and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C && EXPERIMENTAL && !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -949,6 +975,7 @@ config SENSORS_EMC6W201
 
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
+	depends on !PPC
 	help
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
@@ -982,7 +1009,7 @@ config SENSORS_SMSC47M192
 
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
-	depends on EXPERIMENTAL
+	depends on EXPERIMENTAL && !PPC
 	help
 	  If you say yes here you get support for the SMSC LPC47B397-NC
 	  sensor chip.
@@ -996,6 +1023,7 @@ config SENSORS_SCH56XX_COMMON
 
 config SENSORS_SCH5627
 	tristate "SMSC SCH5627"
+	depends on !PPC
 	select SENSORS_SCH56XX_COMMON
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -1006,6 +1034,7 @@ config SENSORS_SCH5627
 
 config SENSORS_SCH5636
 	tristate "SMSC SCH5636"
+	depends on !PPC
 	select SENSORS_SCH56XX_COMMON
 	help
 	  SMSC SCH5636 Super I/O chips include an embedded microcontroller for
@@ -1129,6 +1158,7 @@ config SENSORS_VIA686A
 
 config SENSORS_VT1211
 	tristate "VIA VT1211"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here then you get support for hardware monitoring
@@ -1241,6 +1271,7 @@ config SENSORS_W83L786NG
 
 config SENSORS_W83627HF
 	tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W836X7 series
@@ -1251,7 +1282,8 @@ config SENSORS_W83627HF
 	  will be called w83627hf.
 
 config SENSORS_W83627EHF
-	tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
+	tristate "Winbond W83627EHF/EHG/DHG/UHG, W83667HG, NCT6775F, NCT6776F"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware
@@ -1260,7 +1292,8 @@ config SENSORS_W83627EHF
 	  This driver also supports the W83627EHG, which is the lead-free
 	  version of the W83627EHF, and the W83627DHG, which is a similar
 	  chip suited for specific Intel processors that use PECI such as
-	  the Core 2 Duo.
+	  the Core 2 Duo. And also the W83627UHG, which is a stripped down
+	  version of the W83627DHG (as far as hardware monitoring goes.)
 
 	  This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
 	  (also known as W83667HG-I), and NCT6776F.
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/lm73.c linux-libre-3.2-gnu1/drivers/hwmon/lm73.c
--- linux-libre-3.1-gnu1/drivers/hwmon/lm73.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/lm73.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@ static const unsigned short normal_i2c[]
 #define LM73_REG_CTRL		0x04
 #define LM73_REG_ID		0x07
 
-#define LM73_ID			0x9001 /* or 0x190 after a swab16() */
+#define LM73_ID			0x9001	/* 0x0190, byte-swapped */
 #define DRVNAME			"lm73"
 #define LM73_TEMP_MIN		(-40)
 #define LM73_TEMP_MAX		150
@@ -57,7 +57,7 @@ static ssize_t set_temp(struct device *d
 	/* Write value */
 	value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
 		(LM73_TEMP_MAX*4)) << 5;
-	i2c_smbus_write_word_data(client, attr->index, swab16(value));
+	i2c_smbus_write_word_swapped(client, attr->index, value);
 	return count;
 }
 
@@ -68,8 +68,8 @@ static ssize_t show_temp(struct device *
 	struct i2c_client *client = to_i2c_client(dev);
 	/* use integer division instead of equivalent right shift to
 	   guarantee arithmetic shift and preserve the sign */
-	int temp = ((s16) (swab16(i2c_smbus_read_word_data(client,
-		attr->index)))*250) / 32;
+	int temp = ((s16) (i2c_smbus_read_word_swapped(client,
+		    attr->index))*250) / 32;
 	return sprintf(buf, "%d\n", temp);
 }
 
@@ -150,17 +150,31 @@ static int lm73_detect(struct i2c_client
 			struct i2c_board_info *info)
 {
 	struct i2c_adapter *adapter = new_client->adapter;
-	u16 id;
-	u8 ctrl;
+	int id, ctrl, conf;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 					I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
+	/*
+	 * Do as much detection as possible with byte reads first, as word
+	 * reads can confuse other devices.
+	 */
+	ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
+	if (ctrl < 0 || (ctrl & 0x10))
+		return -ENODEV;
+
+	conf = i2c_smbus_read_byte_data(new_client, LM73_REG_CONF);
+	if (conf < 0 || (conf & 0x0c))
+		return -ENODEV;
+
+	id = i2c_smbus_read_byte_data(new_client, LM73_REG_ID);
+	if (id < 0 || id != (LM73_ID & 0xff))
+		return -ENODEV;
+
 	/* Check device ID */
 	id = i2c_smbus_read_word_data(new_client, LM73_REG_ID);
-	ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
-	if ((id != LM73_ID) || (ctrl & 0x10))
+	if (id < 0 || id != LM73_ID)
 		return -ENODEV;
 
 	strlcpy(info->type, "lm73", I2C_NAME_SIZE);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/lm75.c linux-libre-3.2-gnu1/drivers/hwmon/lm75.c
--- linux-libre-3.1-gnu1/drivers/hwmon/lm75.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/lm75.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
  */
 
 enum lm75_type {		/* keep sorted in alphabetical order */
+	adt75,
 	ds1775,
 	ds75,
 	lm75,
@@ -213,6 +214,7 @@ static int lm75_remove(struct i2c_client
 }
 
 static const struct i2c_device_id lm75_ids[] = {
+	{ "adt75", adt75, },
 	{ "ds1775", ds1775, },
 	{ "ds75", ds75, },
 	{ "lm75", lm75, },
@@ -247,19 +249,30 @@ static int lm75_detect(struct i2c_client
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	/* Now, we do the remaining detection. There is no identification-
-	   dedicated register so we have to rely on several tricks:
-	   unused bits, registers cycling over 8-address boundaries,
-	   addresses 0x04-0x07 returning the last read value.
-	   The cycling+unused addresses combination is not tested,
-	   since it would significantly slow the detection down and would
-	   hardly add any value.
-
-	   The National Semiconductor LM75A is different than earlier
-	   LM75s.  It has an ID byte of 0xaX (where X is the chip
-	   revision, with 1 being the only revision in existence) in
-	   register 7, and unused registers return 0xff rather than the
-	   last read value. */
+	/*
+	 * Now, we do the remaining detection. There is no identification-
+	 * dedicated register so we have to rely on several tricks:
+	 * unused bits, registers cycling over 8-address boundaries,
+	 * addresses 0x04-0x07 returning the last read value.
+	 * The cycling+unused addresses combination is not tested,
+	 * since it would significantly slow the detection down and would
+	 * hardly add any value.
+	 *
+	 * The National Semiconductor LM75A is different than earlier
+	 * LM75s.  It has an ID byte of 0xaX (where X is the chip
+	 * revision, with 1 being the only revision in existence) in
+	 * register 7, and unused registers return 0xff rather than the
+	 * last read value.
+	 *
+	 * Note that this function only detects the original National
+	 * Semiconductor LM75 and the LM75A. Clones from other vendors
+	 * aren't detected, on purpose, because they are typically never
+	 * found on PC hardware. They are found on embedded designs where
+	 * they can be instantiated explicitly so detection is not needed.
+	 * The absence of identification registers on all these clones
+	 * would make their exhaustive detection very difficult and weak,
+	 * and odds are that the driver would bind to unsupported devices.
+	 */
 
 	/* Unused bits */
 	conf = i2c_smbus_read_byte_data(new_client, 1);
@@ -371,13 +384,10 @@ static struct i2c_driver lm75_driver = {
  */
 static int lm75_read_value(struct i2c_client *client, u8 reg)
 {
-	int value;
-
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
-
-	value = i2c_smbus_read_word_data(client, reg);
-	return (value < 0) ? value : swab16(value);
+	else
+		return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -385,7 +395,7 @@ static int lm75_write_value(struct i2c_c
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static struct lm75_data *lm75_update_device(struct device *dev)
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/lm77.c linux-libre-3.2-gnu1/drivers/hwmon/lm77.c
--- linux-libre-3.1-gnu1/drivers/hwmon/lm77.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/lm77.c	2012-01-04 18:55:44.000000000 -0500
@@ -365,7 +365,7 @@ static u16 lm77_read_value(struct i2c_cl
 	if (reg == LM77_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
 	else
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -373,7 +373,7 @@ static int lm77_write_value(struct i2c_c
 	if (reg == LM77_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static void lm77_init_client(struct i2c_client *client)
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/lm90.c linux-libre-3.2-gnu1/drivers/hwmon/lm90.c
--- linux-libre-3.1-gnu1/drivers/hwmon/lm90.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/lm90.c	2012-01-04 18:55:44.000000000 -0500
@@ -1105,41 +1105,37 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUG
  */
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
-static int lm90_detect(struct i2c_client *new_client,
+static int lm90_detect(struct i2c_client *client,
 		       struct i2c_board_info *info)
 {
-	struct i2c_adapter *adapter = new_client->adapter;
-	int address = new_client->addr;
+	struct i2c_adapter *adapter = client->adapter;
+	int address = client->addr;
 	const char *name = NULL;
-	int man_id, chip_id, reg_config1, reg_config2, reg_convrate;
+	int man_id, chip_id, config1, config2, convrate;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
 	/* detection and identification */
-	if ((man_id = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_MAN_ID)) < 0
-	 || (chip_id = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CHIP_ID)) < 0
-	 || (reg_config1 = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONFIG1)) < 0
-	 || (reg_convrate = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONVRATE)) < 0)
+	man_id = i2c_smbus_read_byte_data(client, LM90_REG_R_MAN_ID);
+	chip_id = i2c_smbus_read_byte_data(client, LM90_REG_R_CHIP_ID);
+	config1 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+	convrate = i2c_smbus_read_byte_data(client, LM90_REG_R_CONVRATE);
+	if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
 		return -ENODEV;
 
 	if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
-		reg_config2 = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONFIG2);
-		if (reg_config2 < 0)
+		config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
+		if (config2 < 0)
 			return -ENODEV;
 	} else
-		reg_config2 = 0;	/* Make compiler happy */
+		config2 = 0;		/* Make compiler happy */
 
 	if ((address == 0x4C || address == 0x4D)
 	 && man_id == 0x01) { /* National Semiconductor */
-		if ((reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xF8) == 0x00
-		 && reg_convrate <= 0x09) {
+		if ((config1 & 0x2A) == 0x00
+		 && (config2 & 0xF8) == 0x00
+		 && convrate <= 0x09) {
 			if (address == 0x4C
 			 && (chip_id & 0xF0) == 0x20) { /* LM90 */
 				name = "lm90";
@@ -1163,8 +1159,8 @@ static int lm90_detect(struct i2c_client
 	if ((address == 0x4C || address == 0x4D)
 	 && man_id == 0x41) { /* Analog Devices */
 		if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
-		 && (reg_config1 & 0x3F) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x3F) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adm1032";
 			/* The ADM1032 supports PEC, but only if combined
 			   transactions are not used. */
@@ -1173,18 +1169,18 @@ static int lm90_detect(struct i2c_client
 				info->flags |= I2C_CLIENT_PEC;
 		} else
 		if (chip_id == 0x51 /* ADT7461 */
-		 && (reg_config1 & 0x1B) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x1B) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adt7461";
 		} else
 		if (chip_id == 0x57 /* ADT7461A, NCT1008 */
-		 && (reg_config1 & 0x1B) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x1B) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adt7461a";
 		}
 	} else
 	if (man_id == 0x4D) { /* Maxim */
-		int reg_emerg, reg_emerg2, reg_status2;
+		int emerg, emerg2, status2;
 
 		/*
 		 * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read
@@ -1192,13 +1188,15 @@ static int lm90_detect(struct i2c_client
 		 * exists, both readings will reflect the same value. Otherwise,
 		 * the readings will be different.
 		 */
-		if ((reg_emerg = i2c_smbus_read_byte_data(new_client,
-						MAX6659_REG_R_REMOTE_EMERG)) < 0
-		 || i2c_smbus_read_byte_data(new_client, LM90_REG_R_MAN_ID) < 0
-		 || (reg_emerg2 = i2c_smbus_read_byte_data(new_client,
-						MAX6659_REG_R_REMOTE_EMERG)) < 0
-		 || (reg_status2 = i2c_smbus_read_byte_data(new_client,
-						MAX6696_REG_R_STATUS2)) < 0)
+		emerg = i2c_smbus_read_byte_data(client,
+						 MAX6659_REG_R_REMOTE_EMERG);
+		man_id = i2c_smbus_read_byte_data(client,
+						  LM90_REG_R_MAN_ID);
+		emerg2 = i2c_smbus_read_byte_data(client,
+						  MAX6659_REG_R_REMOTE_EMERG);
+		status2 = i2c_smbus_read_byte_data(client,
+						   MAX6696_REG_R_STATUS2);
+		if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
 			return -ENODEV;
 
 		/*
@@ -1216,8 +1214,8 @@ static int lm90_detect(struct i2c_client
 		 */
 		if (chip_id == man_id
 		 && (address == 0x4C || address == 0x4D || address == 0x4E)
-		 && (reg_config1 & 0x1F) == (man_id & 0x0F)
-		 && reg_convrate <= 0x09) {
+		 && (config1 & 0x1F) == (man_id & 0x0F)
+		 && convrate <= 0x09) {
 			if (address == 0x4C)
 				name = "max6657";
 			else
@@ -1235,10 +1233,10 @@ static int lm90_detect(struct i2c_client
 		 * one of those registers exists.
 		 */
 		if (chip_id == 0x01
-		 && (reg_config1 & 0x10) == 0x00
-		 && (reg_status2 & 0x01) == 0x00
-		 && reg_emerg == reg_emerg2
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x10) == 0x00
+		 && (status2 & 0x01) == 0x00
+		 && emerg == emerg2
+		 && convrate <= 0x07) {
 			name = "max6696";
 		} else
 		/*
@@ -1248,8 +1246,8 @@ static int lm90_detect(struct i2c_client
 		 * second to last bit of config1 (software reset).
 		 */
 		if (chip_id == 0x01
-		 && (reg_config1 & 0x03) == 0x00
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x03) == 0x00
+		 && convrate <= 0x07) {
 			name = "max6680";
 		} else
 		/*
@@ -1258,21 +1256,21 @@ static int lm90_detect(struct i2c_client
 		 * register are unused and should return zero when read.
 		 */
 		if (chip_id == 0x59
-		 && (reg_config1 & 0x3f) == 0x00
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x3f) == 0x00
+		 && convrate <= 0x07) {
 			name = "max6646";
 		}
 	} else
 	if (address == 0x4C
 	 && man_id == 0x5C) { /* Winbond/Nuvoton */
-		if ((reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xF8) == 0x00) {
+		if ((config1 & 0x2A) == 0x00
+		 && (config2 & 0xF8) == 0x00) {
 			if (chip_id == 0x01 /* W83L771W/G */
-			 && reg_convrate <= 0x09) {
+			 && convrate <= 0x09) {
 				name = "w83l771";
 			} else
 			if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
-			 && reg_convrate <= 0x08) {
+			 && convrate <= 0x08) {
 				name = "w83l771";
 			}
 		}
@@ -1280,9 +1278,9 @@ static int lm90_detect(struct i2c_client
 	if (address >= 0x48 && address <= 0x4F
 	 && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
 		if (chip_id == 0x00
-		 && (reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xFE) == 0x00
-		 && reg_convrate <= 0x09) {
+		 && (config1 & 0x2A) == 0x00
+		 && (config2 & 0xFE) == 0x00
+		 && convrate <= 0x09) {
 			name = "sa56004";
 		}
 	}
@@ -1301,19 +1299,18 @@ static int lm90_detect(struct i2c_client
 
 static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
 {
+	struct device *dev = &client->dev;
+
 	if (data->flags & LM90_HAVE_TEMP3)
-		sysfs_remove_group(&client->dev.kobj, &lm90_temp3_group);
+		sysfs_remove_group(&dev->kobj, &lm90_temp3_group);
 	if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
-		sysfs_remove_group(&client->dev.kobj,
-				   &lm90_emergency_alarm_group);
+		sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group);
 	if (data->flags & LM90_HAVE_EMERGENCY)
-		sysfs_remove_group(&client->dev.kobj,
-				   &lm90_emergency_group);
+		sysfs_remove_group(&dev->kobj, &lm90_emergency_group);
 	if (data->flags & LM90_HAVE_OFFSET)
-		device_remove_file(&client->dev,
-				   &sensor_dev_attr_temp2_offset.dev_attr);
-	device_remove_file(&client->dev, &dev_attr_pec);
-	sysfs_remove_group(&client->dev.kobj, &lm90_group);
+		device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr);
+	device_remove_file(dev, &dev_attr_pec);
+	sysfs_remove_group(&dev->kobj, &lm90_group);
 }
 
 static void lm90_init_client(struct i2c_client *client)
@@ -1362,10 +1359,11 @@ static void lm90_init_client(struct i2c_
 		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
 }
 
-static int lm90_probe(struct i2c_client *new_client,
+static int lm90_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
-	struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent);
+	struct device *dev = &client->dev;
+	struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
 	struct lm90_data *data;
 	int err;
 
@@ -1374,14 +1372,14 @@ static int lm90_probe(struct i2c_client
 		err = -ENOMEM;
 		goto exit;
 	}
-	i2c_set_clientdata(new_client, data);
+	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
 	/* Set the device type */
 	data->kind = id->driver_data;
 	if (data->kind == adm1032) {
 		if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
-			new_client->flags &= ~I2C_CLIENT_PEC;
+			client->flags &= ~I2C_CLIENT_PEC;
 	}
 
 	/* Different devices have different alarm bits triggering the
@@ -1396,43 +1394,41 @@ static int lm90_probe(struct i2c_client
 	data->max_convrate = lm90_params[data->kind].max_convrate;
 
 	/* Initialize the LM90 chip */
-	lm90_init_client(new_client);
+	lm90_init_client(client);
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &lm90_group);
+	err = sysfs_create_group(&dev->kobj, &lm90_group);
 	if (err)
 		goto exit_free;
-	if (new_client->flags & I2C_CLIENT_PEC) {
-		err = device_create_file(&new_client->dev, &dev_attr_pec);
+	if (client->flags & I2C_CLIENT_PEC) {
+		err = device_create_file(dev, &dev_attr_pec);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_OFFSET) {
-		err = device_create_file(&new_client->dev,
+		err = device_create_file(dev,
 					&sensor_dev_attr_temp2_offset.dev_attr);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_EMERGENCY) {
-		err = sysfs_create_group(&new_client->dev.kobj,
-					 &lm90_emergency_group);
+		err = sysfs_create_group(&dev->kobj, &lm90_emergency_group);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_EMERGENCY_ALARM) {
-		err = sysfs_create_group(&new_client->dev.kobj,
+		err = sysfs_create_group(&dev->kobj,
 					 &lm90_emergency_alarm_group);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_TEMP3) {
-		err = sysfs_create_group(&new_client->dev.kobj,
-					 &lm90_temp3_group);
+		err = sysfs_create_group(&dev->kobj, &lm90_temp3_group);
 		if (err)
 			goto exit_remove_files;
 	}
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove_files;
@@ -1441,7 +1437,7 @@ static int lm90_probe(struct i2c_client
 	return 0;
 
 exit_remove_files:
-	lm90_remove_files(new_client, data);
+	lm90_remove_files(client, data);
 exit_free:
 	kfree(data);
 exit:
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/lm92.c linux-libre-3.2-gnu1/drivers/hwmon/lm92.c
--- linux-libre-3.1-gnu1/drivers/hwmon/lm92.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/lm92.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,16 +117,16 @@ static struct lm92_data *lm92_update_dev
 	if (time_after(jiffies, data->last_updated + HZ)
 	 || !data->valid) {
 		dev_dbg(&client->dev, "Updating lm92 data\n");
-		data->temp1_input = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP));
-		data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_HYST));
-		data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_CRIT));
-		data->temp1_min = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_LOW));
-		data->temp1_max = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_HIGH));
+		data->temp1_input = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP);
+		data->temp1_hyst = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_HYST);
+		data->temp1_crit = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_CRIT);
+		data->temp1_min = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_LOW);
+		data->temp1_max = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_HIGH);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -158,7 +158,7 @@ static ssize_t set_##value(struct device
  \
 	mutex_lock(&data->update_lock); \
 	data->value = TEMP_TO_REG(val); \
-	i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+	i2c_smbus_write_word_swapped(client, reg, data->value); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -194,8 +194,8 @@ static ssize_t set_temp1_crit_hyst(struc
 
 	mutex_lock(&data->update_lock);
 	data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val;
-	i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
-				  swab16(TEMP_TO_REG(data->temp1_hyst)));
+	i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
+				     TEMP_TO_REG(data->temp1_hyst));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/Makefile linux-libre-3.2-gnu1/drivers/hwmon/Makefile
--- linux-libre-3.1-gnu1/drivers/hwmon/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@ obj-$(CONFIG_SENSORS_W83791D)	+= w83791d
 
 obj-$(CONFIG_SENSORS_ABITUGURU)	+= abituguru.o
 obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
+obj-$(CONFIG_SENSORS_AD7314)	+= ad7314.o
 obj-$(CONFIG_SENSORS_AD7414)	+= ad7414.o
 obj-$(CONFIG_SENSORS_AD7418)	+= ad7418.o
 obj-$(CONFIG_SENSORS_ADCXX)	+= adcxx.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_EMC6W201)	+= emc6w201.o
+obj-$(CONFIG_SENSORS_EXYNOS4_TMU)	+= exynos4_tmu.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/max16065.c linux-libre-3.2-gnu1/drivers/hwmon/max16065.c
--- linux-libre-3.1-gnu1/drivers/hwmon/max16065.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/max16065.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,10 +137,10 @@ static int max16065_read_adc(struct i2c_
 {
 	int rv;
 
-	rv = i2c_smbus_read_word_data(client, reg);
+	rv = i2c_smbus_read_word_swapped(client, reg);
 	if (unlikely(rv < 0))
 		return rv;
-	return ((rv & 0xff) << 2) | ((rv >> 14) & 0x03);
+	return rv >> 6;
 }
 
 static struct max16065_data *max16065_update_device(struct device *dev)
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/mc13783-adc.c linux-libre-3.2-gnu1/drivers/hwmon/mc13783-adc.c
--- linux-libre-3.1-gnu1/drivers/hwmon/mc13783-adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/mc13783-adc.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 #define MC13783_ADC_NAME	"mc13783-adc"
 
 struct mc13783_adc_priv {
-	struct mc13783 *mc13783;
+	struct mc13xxx *mc13xxx;
 	struct device *hwmon_dev;
 };
 
@@ -51,8 +51,8 @@ static int mc13783_adc_read(struct devic
 	unsigned int sample[4];
 	int ret;
 
-	ret = mc13783_adc_do_conversion(priv->mc13783,
-			MC13783_ADC_MODE_MULT_CHAN,
+	ret = mc13xxx_adc_do_conversion(priv->mc13xxx,
+			MC13XXX_ADC_MODE_MULT_CHAN,
 			channel, sample);
 	if (ret)
 		return ret;
@@ -147,9 +147,9 @@ static const struct attribute_group mc13
 static int mc13783_adc_use_touchscreen(struct platform_device *pdev)
 {
 	struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
-	unsigned flags = mc13783_get_flags(priv->mc13783);
+	unsigned flags = mc13xxx_get_flags(priv->mc13xxx);
 
-	return flags & MC13783_USE_TOUCHSCREEN;
+	return flags & MC13XXX_USE_TOUCHSCREEN;
 }
 
 static int __init mc13783_adc_probe(struct platform_device *pdev)
@@ -161,7 +161,7 @@ static int __init mc13783_adc_probe(stru
 	if (!priv)
 		return -ENOMEM;
 
-	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
 
 	platform_set_drvdata(pdev, priv);
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ntc_thermistor.c linux-libre-3.2-gnu1/drivers/hwmon/ntc_thermistor.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ntc_thermistor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ntc_thermistor.c	2012-01-04 18:55:44.000000000 -0500
@@ -432,19 +432,7 @@ static struct platform_driver ntc_thermi
 	.id_table = ntc_thermistor_id,
 };
 
-static int __init ntc_thermistor_init(void)
-{
-	return platform_driver_register(&ntc_thermistor_driver);
-}
-
-module_init(ntc_thermistor_init);
-
-static void __exit ntc_thermistor_cleanup(void)
-{
-	platform_driver_unregister(&ntc_thermistor_driver);
-}
-
-module_exit(ntc_thermistor_cleanup);
+module_platform_driver(ntc_thermistor_driver);
 
 MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/adm1275.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/adm1275.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/adm1275.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/adm1275.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+enum chips { adm1275, adm1276 };
+
 #define ADM1275_PEAK_IOUT		0xd0
 #define ADM1275_PEAK_VIN		0xd1
 #define ADM1275_PEAK_VOUT		0xd2
@@ -31,14 +33,47 @@
 #define ADM1275_VIN_VOUT_SELECT		(1 << 6)
 #define ADM1275_VRANGE			(1 << 5)
 
+#define ADM1275_IOUT_WARN2_LIMIT	0xd7
+#define ADM1275_DEVICE_CONFIG		0xd8
+
+#define ADM1275_IOUT_WARN2_SELECT	(1 << 4)
+
+#define ADM1276_PEAK_PIN		0xda
+
+#define ADM1275_MFR_STATUS_IOUT_WARN2	(1 << 0)
+
+struct adm1275_data {
+	int id;
+	bool have_oc_fault;
+	struct pmbus_driver_info info;
+};
+
+#define to_adm1275_data(x)  container_of(x, struct adm1275_data, info)
+
 static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
 {
-	int ret;
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct adm1275_data *data = to_adm1275_data(info);
+	int ret = 0;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
+	case PMBUS_IOUT_UC_FAULT_LIMIT:
+		if (data->have_oc_fault) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+		break;
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		if (!data->have_oc_fault) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+		break;
 	case PMBUS_VIRT_READ_IOUT_MAX:
 		ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
 		break;
@@ -48,10 +83,20 @@ static int adm1275_read_word_data(struct
 	case PMBUS_VIRT_READ_VIN_MAX:
 		ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
 		break;
+	case PMBUS_VIRT_READ_PIN_MAX:
+		if (data->id != adm1276) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
+		break;
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
 	case PMBUS_VIRT_RESET_VIN_HISTORY:
-		ret = 0;
+		break;
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+		if (data->id != adm1276)
+			ret = -ENXIO;
 		break;
 	default:
 		ret = -ENODATA;
@@ -66,9 +111,14 @@ static int adm1275_write_word_data(struc
 	int ret;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
+	case PMBUS_IOUT_UC_FAULT_LIMIT:
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT,
+					    word);
+		break;
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
 		ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
 		break;
@@ -78,6 +128,41 @@ static int adm1275_write_word_data(struc
 	case PMBUS_VIRT_RESET_VIN_HISTORY:
 		ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
 		break;
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+		ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct adm1275_data *data = to_adm1275_data(info);
+	int mfr_status, ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	switch (reg) {
+	case PMBUS_STATUS_IOUT:
+		ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
+		if (ret < 0)
+			break;
+		mfr_status = pmbus_read_byte_data(client, page,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfr_status < 0) {
+			ret = mfr_status;
+			break;
+		}
+		if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
+			ret |= data->have_oc_fault ?
+			  PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
+		}
+		break;
 	default:
 		ret = -ENODATA;
 		break;
@@ -88,16 +173,17 @@ static int adm1275_write_word_data(struc
 static int adm1275_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	int config;
+	int config, device_config;
 	int ret;
 	struct pmbus_driver_info *info;
+	struct adm1275_data *data;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_READ_BYTE_DATA))
 		return -ENODEV;
 
-	info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
-	if (!info)
+	data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
 	config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
@@ -106,6 +192,15 @@ static int adm1275_probe(struct i2c_clie
 		goto err_mem;
 	}
 
+	device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
+	if (device_config < 0) {
+		ret = device_config;
+		goto err_mem;
+	}
+
+	data->id = id->driver_data;
+	info = &data->info;
+
 	info->pages = 1;
 	info->format[PSC_VOLTAGE_IN] = direct;
 	info->format[PSC_VOLTAGE_OUT] = direct;
@@ -116,6 +211,7 @@ static int adm1275_probe(struct i2c_clie
 	info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 
 	info->read_word_data = adm1275_read_word_data;
+	info->read_byte_data = adm1275_read_byte_data;
 	info->write_word_data = adm1275_write_word_data;
 
 	if (config & ADM1275_VRANGE) {
@@ -134,10 +230,36 @@ static int adm1275_probe(struct i2c_clie
 		info->R[PSC_VOLTAGE_OUT] = -1;
 	}
 
-	if (config & ADM1275_VIN_VOUT_SELECT)
-		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
-	else
-		info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+	if (device_config & ADM1275_IOUT_WARN2_SELECT)
+		data->have_oc_fault = true;
+
+	switch (id->driver_data) {
+	case adm1275:
+		if (config & ADM1275_VIN_VOUT_SELECT)
+			info->func[0] |=
+			  PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+		else
+			info->func[0] |=
+			  PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+		break;
+	case adm1276:
+		info->format[PSC_POWER] = direct;
+		info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
+		  | PMBUS_HAVE_STATUS_INPUT;
+		if (config & ADM1275_VIN_VOUT_SELECT)
+			info->func[0] |=
+			  PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+		if (config & ADM1275_VRANGE) {
+			info->m[PSC_POWER] = 6043;
+			info->b[PSC_POWER] = 0;
+			info->R[PSC_POWER] = -2;
+		} else {
+			info->m[PSC_POWER] = 2115;
+			info->b[PSC_POWER] = 0;
+			info->R[PSC_POWER] = -1;
+		}
+		break;
+	}
 
 	ret = pmbus_do_probe(client, id, info);
 	if (ret)
@@ -145,22 +267,23 @@ static int adm1275_probe(struct i2c_clie
 	return 0;
 
 err_mem:
-	kfree(info);
+	kfree(data);
 	return ret;
 }
 
 static int adm1275_remove(struct i2c_client *client)
 {
 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
-	int ret;
+	const struct adm1275_data *data = to_adm1275_data(info);
 
-	ret = pmbus_do_remove(client);
-	kfree(info);
-	return ret;
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
 }
 
 static const struct i2c_device_id adm1275_id[] = {
-	{"adm1275", 0},
+	{ "adm1275", adm1275 },
+	{ "adm1276", adm1276 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1275_id);
@@ -185,7 +308,7 @@ static void __exit adm1275_exit(void)
 }
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
 MODULE_LICENSE("GPL");
 module_init(adm1275_init);
 module_exit(adm1275_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/Kconfig linux-libre-3.2-gnu1/drivers/hwmon/pmbus/Kconfig
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -20,17 +20,18 @@ config SENSORS_PMBUS
 	help
 	  If you say yes here you get hardware monitoring support for generic
 	  PMBus devices, including but not limited to ADP4000, BMR450, BMR451,
-	  BMR453, BMR454, LTC2978, NCP4200, and NCP4208.
+	  BMR453, BMR454, NCP4200, and NCP4208.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called pmbus.
 
 config SENSORS_ADM1275
-	tristate "Analog Devices ADM1275"
+	tristate "Analog Devices ADM1275 and compatibles"
 	default n
 	help
 	  If you say yes here you get hardware monitoring support for Analog
-	  Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
+	  Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power
+	  Monitor.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called adm1275.
@@ -45,6 +46,16 @@ config SENSORS_LM25066
 	  This driver can also be built as a module. If so, the module will
 	  be called lm25066.
 
+config SENSORS_LTC2978
+	tristate "Linear Technologies LTC2978 and LTC3880"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Linear
+	  Technology LTC2978 and LTC3880.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc2978.
+
 config SENSORS_MAX16064
 	tristate "Maxim MAX16064"
 	default n
@@ -97,4 +108,15 @@ config SENSORS_UCD9200
 	  This driver can also be built as a module. If so, the module will
 	  be called ucd9200.
 
+config SENSORS_ZL6100
+	tristate "Intersil ZL6100 and compatibles"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Intersil
+	  ZL2004, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 Digital
+	  DC/DC Controllers.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called zl6100.
+
 endif # PMBUS
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/lm25066.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/lm25066.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/lm25066.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/lm25066.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,7 +57,7 @@ static int lm25066_read_word_data(struct
 	int ret;
 
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
 	/* Map READ_VAUX into READ_VOUT register on page 1 */
 	if (page == 1) {
@@ -85,7 +85,7 @@ static int lm25066_read_word_data(struct
 			break;
 		default:
 			/* No other valid registers on page 1 */
-			ret = -EINVAL;
+			ret = -ENXIO;
 			break;
 		}
 		goto done;
@@ -138,7 +138,7 @@ static int lm25066_write_word_data(struc
 	int ret;
 
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_IIN_OC_WARN_LIMIT:
@@ -164,10 +164,10 @@ static int lm25066_write_word_data(struc
 static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
 {
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
-	if (page == 0)
-		return pmbus_write_byte(client, 0, value);
+	if (page <= 0)
+		return pmbus_write_byte(client, page, value);
 
 	return 0;
 }
@@ -309,11 +309,10 @@ static int lm25066_remove(struct i2c_cli
 {
 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 	const struct lm25066_data *data = to_lm25066_data(info);
-	int ret;
 
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(data);
-	return ret;
+	return 0;
 }
 
 static const struct i2c_device_id lm25066_id[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ltc2978.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ltc2978.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ltc2978.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ltc2978.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,408 @@
+/*
+ * Hardware monitoring driver for LTC2978 and LTC3880
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { ltc2978, ltc3880 };
+
+/* LTC2978 and LTC3880 */
+#define LTC2978_MFR_VOUT_PEAK		0xdd
+#define LTC2978_MFR_VIN_PEAK		0xde
+#define LTC2978_MFR_TEMPERATURE_PEAK	0xdf
+#define LTC2978_MFR_SPECIAL_ID		0xe7
+
+/* LTC2978 only */
+#define LTC2978_MFR_VOUT_MIN		0xfb
+#define LTC2978_MFR_VIN_MIN		0xfc
+#define LTC2978_MFR_TEMPERATURE_MIN	0xfd
+
+/* LTC3880 only */
+#define LTC3880_MFR_IOUT_PEAK		0xd7
+#define LTC3880_MFR_CLEAR_PEAKS		0xe3
+#define LTC3880_MFR_TEMPERATURE2_PEAK	0xf4
+
+#define LTC2978_ID_REV1			0x0121
+#define LTC2978_ID_REV2			0x0122
+#define LTC3880_ID			0x4000
+#define LTC3880_ID_MASK			0xff00
+
+/*
+ * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
+ * happens pretty much each time chip data is updated. Raw peak data therefore
+ * does not provide much value. To be able to provide useful peak data, keep an
+ * internal cache of measured peak data, which is only cleared if an explicit
+ * "clear peak" command is executed for the sensor in question.
+ */
+struct ltc2978_data {
+	enum chips id;
+	int vin_min, vin_max;
+	int temp_min, temp_max;
+	int vout_min[8], vout_max[8];
+	int iout_max[2];
+	int temp2_max[2];
+	struct pmbus_driver_info info;
+};
+
+#define to_ltc2978_data(x)  container_of(x, struct ltc2978_data, info)
+
+static inline int lin11_to_val(int data)
+{
+	s16 e = ((s16)data) >> 11;
+	s32 m = (((s16)(data << 5)) >> 5);
+
+	/*
+	 * mantissa is 10 bit + sign, exponent adds up to 15 bit.
+	 * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31).
+	 */
+	e += 6;
+	return (e < 0 ? m >> -e : m << e);
+}
+
+static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
+					 int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VIN_MAX:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
+				data->vin_max = ret;
+			ret = data->vin_max;
+		}
+		break;
+	case PMBUS_VIRT_READ_VOUT_MAX:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
+		if (ret >= 0) {
+			/*
+			 * VOUT is 16 bit unsigned with fixed exponent,
+			 * so we can compare it directly
+			 */
+			if (ret > data->vout_max[page])
+				data->vout_max[page] = ret;
+			ret = data->vout_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP_MAX:
+		ret = pmbus_read_word_data(client, page,
+					   LTC2978_MFR_TEMPERATURE_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
+				data->temp_max = ret;
+			ret = data->temp_max;
+		}
+		break;
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VIN_MIN:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
+				data->vin_min = ret;
+			ret = data->vin_min;
+		}
+		break;
+	case PMBUS_VIRT_READ_VOUT_MIN:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
+		if (ret >= 0) {
+			/*
+			 * VOUT_MIN is known to not be supported on some lots
+			 * of LTC2978 revision 1, and will return the maximum
+			 * possible voltage if read. If VOUT_MAX is valid and
+			 * lower than the reading of VOUT_MIN, use it instead.
+			 */
+			if (data->vout_max[page] && ret > data->vout_max[page])
+				ret = data->vout_max[page];
+			if (ret < data->vout_min[page])
+				data->vout_min[page] = ret;
+			ret = data->vout_min[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP_MIN:
+		ret = pmbus_read_word_data(client, page,
+					   LTC2978_MFR_TEMPERATURE_MIN);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    < lin11_to_val(data->temp_min))
+				data->temp_min = ret;
+			ret = data->temp_min;
+		}
+		break;
+	case PMBUS_VIRT_READ_IOUT_MAX:
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+	case PMBUS_VIRT_READ_TEMP2_MAX:
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		ret = -ENXIO;
+		break;
+	default:
+		ret = ltc2978_read_word_data_common(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
+static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_IOUT_MAX:
+		ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->iout_max[page]))
+				data->iout_max[page] = ret;
+			ret = data->iout_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP2_MAX:
+		ret = pmbus_read_word_data(client, page,
+					   LTC3880_MFR_TEMPERATURE2_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->temp2_max[page]))
+				data->temp2_max[page] = ret;
+			ret = data->temp2_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_VIN_MIN:
+	case PMBUS_VIRT_READ_VOUT_MIN:
+	case PMBUS_VIRT_READ_TEMP_MIN:
+		ret = -ENXIO;
+		break;
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = ltc2978_read_word_data_common(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
+static int ltc2978_clear_peaks(struct i2c_client *client, int page,
+			       enum chips id)
+{
+	int ret;
+
+	if (id == ltc2978)
+		ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+	else
+		ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+
+	return ret;
+}
+
+static int ltc2978_write_word_data(struct i2c_client *client, int page,
+				    int reg, u16 word)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+		data->iout_max[page] = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		data->temp2_max[page] = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+		data->vout_min[page] = 0xffff;
+		data->vout_max[page] = 0;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+		data->vin_min = 0x7bff;
+		data->vin_max = 0;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+		data->temp_min = 0x7bff;
+		data->temp_max = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static const struct i2c_device_id ltc2978_id[] = {
+	{"ltc2978", ltc2978},
+	{"ltc3880", ltc3880},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ltc2978_id);
+
+static int ltc2978_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	int chip_id, ret, i;
+	struct ltc2978_data *data;
+	struct pmbus_driver_info *info;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+	if (chip_id < 0) {
+		ret = chip_id;
+		goto err_mem;
+	}
+
+	if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
+		data->id = ltc2978;
+	} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
+		data->id = ltc3880;
+	} else {
+		dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
+		ret = -ENODEV;
+		goto err_mem;
+	}
+	if (data->id != id->driver_data)
+		dev_warn(&client->dev,
+			 "Device mismatch: Configured %s, detected %s\n",
+			 id->name,
+			 ltc2978_id[data->id].name);
+
+	info = &data->info;
+	info->write_word_data = ltc2978_write_word_data;
+
+	data->vout_min[0] = 0xffff;
+	data->vin_min = 0x7bff;
+	data->temp_min = 0x7bff;
+	data->temp_max = 0x7fff;
+
+	switch (id->driver_data) {
+	case ltc2978:
+		info->read_word_data = ltc2978_read_word_data;
+		info->pages = 8;
+		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+		for (i = 1; i < 8; i++) {
+			info->func[i] = PMBUS_HAVE_VOUT
+			  | PMBUS_HAVE_STATUS_VOUT;
+			data->vout_min[i] = 0xffff;
+		}
+		break;
+	case ltc3880:
+		info->read_word_data = ltc3880_read_word_data;
+		info->pages = 2;
+		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+		  | PMBUS_HAVE_STATUS_INPUT
+		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		  | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+		  | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+		info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		  | PMBUS_HAVE_POUT
+		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+		data->vout_min[1] = 0xffff;
+		break;
+	default:
+		ret = -ENODEV;
+		goto err_mem;
+	}
+
+	ret = pmbus_do_probe(client, id, info);
+	if (ret)
+		goto err_mem;
+	return 0;
+
+err_mem:
+	kfree(data);
+	return ret;
+}
+
+static int ltc2978_remove(struct i2c_client *client)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct ltc2978_data *data = to_ltc2978_data(info);
+
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc2978_driver = {
+	.driver = {
+		   .name = "ltc2978",
+		   },
+	.probe = ltc2978_probe,
+	.remove = ltc2978_remove,
+	.id_table = ltc2978_id,
+};
+
+static int __init ltc2978_init(void)
+{
+	return i2c_add_driver(&ltc2978_driver);
+}
+
+static void __exit ltc2978_exit(void)
+{
+	i2c_del_driver(&ltc2978_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
+MODULE_LICENSE("GPL");
+module_init(ltc2978_init);
+module_exit(ltc2978_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/Makefile linux-libre-3.2-gnu1/drivers/hwmon/pmbus/Makefile
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,8 +6,10 @@ obj-$(CONFIG_PMBUS)		+= pmbus_core.o
 obj-$(CONFIG_SENSORS_PMBUS)	+= pmbus.o
 obj-$(CONFIG_SENSORS_ADM1275)	+= adm1275.o
 obj-$(CONFIG_SENSORS_LM25066)	+= lm25066.o
+obj-$(CONFIG_SENSORS_LTC2978)	+= ltc2978.o
 obj-$(CONFIG_SENSORS_MAX16064)	+= max16064.o
 obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
 obj-$(CONFIG_SENSORS_UCD9000)	+= ucd9000.o
 obj-$(CONFIG_SENSORS_UCD9200)	+= ucd9200.o
+obj-$(CONFIG_SENSORS_ZL6100)	+= zl6100.o
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max16064.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max16064.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max16064.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max16064.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,7 +105,8 @@ static int max16064_probe(struct i2c_cli
 
 static int max16064_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max16064_id[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max34440.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max34440.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max34440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max34440.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,12 +93,14 @@ static int max34440_write_word_data(stru
 
 static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
 {
-	int ret;
+	int ret = 0;
 	int mfg_status;
 
-	ret = pmbus_set_page(client, page);
-	if (ret < 0)
-		return ret;
+	if (page >= 0) {
+		ret = pmbus_set_page(client, page);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (reg) {
 	case PMBUS_STATUS_IOUT:
@@ -224,7 +226,8 @@ static int max34440_probe(struct i2c_cli
 
 static int max34440_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max34440_id[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max8688.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max8688.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/max8688.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/max8688.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,7 @@ static int max8688_read_word_data(struct
 	int ret;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_VIRT_READ_VOUT_MAX:
@@ -101,8 +101,8 @@ static int max8688_read_byte_data(struct
 	int ret = 0;
 	int mfg_status;
 
-	if (page)
-		return -EINVAL;
+	if (page > 0)
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_STATUS_VOUT:
@@ -182,7 +182,8 @@ static int max8688_probe(struct i2c_clie
 
 static int max8688_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max8688_id[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,13 +187,12 @@ out:
 
 static int pmbus_remove(struct i2c_client *client)
 {
-	int ret;
 	const struct pmbus_driver_info *info;
 
 	info = pmbus_get_driver_info(client);
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(info);
-	return ret;
+	return 0;
 }
 
 /*
@@ -205,10 +204,13 @@ static const struct i2c_device_id pmbus_
 	{"bmr451", 1},
 	{"bmr453", 1},
 	{"bmr454", 1},
-	{"ltc2978", 8},
 	{"ncp4200", 1},
 	{"ncp4208", 1},
+	{"pdt003", 1},
+	{"pdt006", 1},
+	{"pdt012", 1},
 	{"pmbus", 0},
+	{"udt020", 1},
 	{}
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus_core.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus_core.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,7 @@ int pmbus_set_page(struct i2c_client *cl
 		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
 		newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
 		if (newpage != page)
-			rv = -EINVAL;
+			rv = -EIO;
 		else
 			data->currpage = page;
 	}
@@ -229,7 +229,7 @@ static int _pmbus_write_word_data(struct
 			return status;
 	}
 	if (reg >= PMBUS_VIRT_BASE)
-		return -EINVAL;
+		return -ENXIO;
 	return pmbus_write_word_data(client, page, reg, word);
 }
 
@@ -261,7 +261,7 @@ static int _pmbus_read_word_data(struct
 			return status;
 	}
 	if (reg >= PMBUS_VIRT_BASE)
-		return -EINVAL;
+		return -ENXIO;
 	return pmbus_read_word_data(client, page, reg);
 }
 
@@ -316,11 +316,11 @@ static int pmbus_check_status_cml(struct
 {
 	int status, status2;
 
-	status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
+	status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
 	if (status < 0 || (status & PB_STATUS_CML)) {
-		status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
+		status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
 		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
-			return -EINVAL;
+			return -EIO;
 	}
 	return 0;
 }
@@ -371,8 +371,8 @@ static struct pmbus_data *pmbus_update_d
 
 		for (i = 0; i < info->pages; i++)
 			data->status[PB_STATUS_BASE + i]
-			    = pmbus_read_byte_data(client, i,
-						   PMBUS_STATUS_BYTE);
+			    = _pmbus_read_byte_data(client, i,
+						    PMBUS_STATUS_BYTE);
 		for (i = 0; i < info->pages; i++) {
 			if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
 				continue;
@@ -445,13 +445,8 @@ static long pmbus_reg2data_linear(struct
 		exponent = data->exponent;
 		mantissa = (u16) sensor->data;
 	} else {				/* LINEAR11 */
-		exponent = (sensor->data >> 11) & 0x001f;
-		mantissa = sensor->data & 0x07ff;
-
-		if (exponent > 0x0f)
-			exponent |= 0xffe0;	/* sign extend exponent */
-		if (mantissa > 0x03ff)
-			mantissa |= 0xfffff800;	/* sign extend mantissa */
+		exponent = ((s16)sensor->data) >> 11;
+		mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
 	}
 
 	val = mantissa;
@@ -1401,7 +1396,42 @@ static const struct pmbus_limit_attr tem
 	}
 };
 
-static const struct pmbus_limit_attr temp_limit_attrs23[] = {
+static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+	{
+		.reg = PMBUS_UT_WARN_LIMIT,
+		.low = true,
+		.attr = "min",
+		.alarm = "min_alarm",
+		.sbit = PB_TEMP_UT_WARNING,
+	}, {
+		.reg = PMBUS_UT_FAULT_LIMIT,
+		.low = true,
+		.attr = "lcrit",
+		.alarm = "lcrit_alarm",
+		.sbit = PB_TEMP_UT_FAULT,
+	}, {
+		.reg = PMBUS_OT_WARN_LIMIT,
+		.attr = "max",
+		.alarm = "max_alarm",
+		.sbit = PB_TEMP_OT_WARNING,
+	}, {
+		.reg = PMBUS_OT_FAULT_LIMIT,
+		.attr = "crit",
+		.alarm = "crit_alarm",
+		.sbit = PB_TEMP_OT_FAULT,
+	}, {
+		.reg = PMBUS_VIRT_READ_TEMP2_MIN,
+		.attr = "lowest",
+	}, {
+		.reg = PMBUS_VIRT_READ_TEMP2_MAX,
+		.attr = "highest",
+	}, {
+		.reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+		.attr = "reset_history",
+	}
+};
+
+static const struct pmbus_limit_attr temp_limit_attrs3[] = {
 	{
 		.reg = PMBUS_UT_WARN_LIMIT,
 		.low = true,
@@ -1450,8 +1480,8 @@ static const struct pmbus_sensor_attr te
 		.sfunc = PMBUS_HAVE_STATUS_TEMP,
 		.sbase = PB_STATUS_TEMP_BASE,
 		.gbit = PB_STATUS_TEMPERATURE,
-		.limit = temp_limit_attrs23,
-		.nlimit = ARRAY_SIZE(temp_limit_attrs23),
+		.limit = temp_limit_attrs2,
+		.nlimit = ARRAY_SIZE(temp_limit_attrs2),
 	}, {
 		.reg = PMBUS_READ_TEMPERATURE_3,
 		.class = PSC_TEMPERATURE,
@@ -1462,8 +1492,8 @@ static const struct pmbus_sensor_attr te
 		.sfunc = PMBUS_HAVE_STATUS_TEMP,
 		.sbase = PB_STATUS_TEMP_BASE,
 		.gbit = PB_STATUS_TEMPERATURE,
-		.limit = temp_limit_attrs23,
-		.nlimit = ARRAY_SIZE(temp_limit_attrs23),
+		.limit = temp_limit_attrs3,
+		.nlimit = ARRAY_SIZE(temp_limit_attrs3),
 	}
 };
 
@@ -1593,10 +1623,10 @@ static void pmbus_find_attributes(struct
 static int pmbus_identify_common(struct i2c_client *client,
 				 struct pmbus_data *data)
 {
-	int vout_mode = -1, exponent;
+	int vout_mode = -1;
 
 	if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
-		vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+		vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
 	if (vout_mode >= 0 && vout_mode != 0xff) {
 		/*
 		 * Not all chips support the VOUT_MODE command,
@@ -1607,11 +1637,7 @@ static int pmbus_identify_common(struct
 			if (data->info->format[PSC_VOLTAGE_OUT] != linear)
 				return -ENODEV;
 
-			exponent = vout_mode & 0x1f;
-			/* and sign-extend it */
-			if (exponent & 0x10)
-				exponent |= ~0x1f;
-			data->exponent = exponent;
+			data->exponent = ((s8)(vout_mode << 3)) >> 3;
 			break;
 		case 1: /* VID mode         */
 			if (data->info->format[PSC_VOLTAGE_OUT] != vid)
@@ -1682,7 +1708,7 @@ int pmbus_do_probe(struct i2c_client *cl
 	if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
 		dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
 			info->pages);
-		ret = -EINVAL;
+		ret = -ENODEV;
 		goto out_data;
 	}
 
@@ -1764,7 +1790,7 @@ out_data:
 }
 EXPORT_SYMBOL_GPL(pmbus_do_probe);
 
-int pmbus_do_remove(struct i2c_client *client)
+void pmbus_do_remove(struct i2c_client *client)
 {
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
@@ -1774,7 +1800,6 @@ int pmbus_do_remove(struct i2c_client *c
 	kfree(data->booleans);
 	kfree(data->sensors);
 	kfree(data);
-	return 0;
 }
 EXPORT_SYMBOL_GPL(pmbus_do_remove);
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus.h linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus.h
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/pmbus.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/pmbus.h	2012-01-04 18:55:44.000000000 -0500
@@ -134,8 +134,16 @@
  * Semantics:
  * Virtual registers are all word size.
  * READ registers are read-only; writes are either ignored or return an error.
- * RESET registers are read/write. Reading returns zero (used for detection),
- * writing any value causes the associated history to be reset.
+ * RESET registers are read/write. Reading reset registers returns zero
+ * (used for detection), writing any value causes the associated history to be
+ * reset.
+ * Virtual registers have to be handled in device specific driver code. Chip
+ * driver code returns non-negative register values if a virtual register is
+ * supported, or a negative error code if not. The chip driver may return
+ * -ENODATA or any other error code in this case, though an error code other
+ * than -ENODATA is handled more efficiently and thus preferred. Either case,
+ * the calling PMBus core code will abort if the chip driver returns an error
+ * code when reading or writing virtual registers.
  */
 #define PMBUS_VIRT_BASE			0x100
 #define PMBUS_VIRT_READ_TEMP_MIN	(PMBUS_VIRT_BASE + 0)
@@ -160,6 +168,9 @@
 #define PMBUS_VIRT_READ_IOUT_MIN	(PMBUS_VIRT_BASE + 19)
 #define PMBUS_VIRT_READ_IOUT_MAX	(PMBUS_VIRT_BASE + 20)
 #define PMBUS_VIRT_RESET_IOUT_HISTORY	(PMBUS_VIRT_BASE + 21)
+#define PMBUS_VIRT_READ_TEMP2_MIN	(PMBUS_VIRT_BASE + 22)
+#define PMBUS_VIRT_READ_TEMP2_MAX	(PMBUS_VIRT_BASE + 23)
+#define PMBUS_VIRT_RESET_TEMP2_HISTORY	(PMBUS_VIRT_BASE + 24)
 
 /*
  * CAPABILITY
@@ -320,6 +331,12 @@ struct pmbus_driver_info {
 	 * The following functions map manufacturing specific register values
 	 * to PMBus standard register values. Specify only if mapping is
 	 * necessary.
+	 * Functions return the register value (read) or zero (write) if
+	 * successful. A return value of -ENODATA indicates that there is no
+	 * manufacturer specific register, but that a standard PMBus register
+	 * may exist. Any other negative return value indicates that the
+	 * register does not exist, and that no attempt should be made to read
+	 * the standard register.
 	 */
 	int (*read_byte_data)(struct i2c_client *client, int page, int reg);
 	int (*read_word_data)(struct i2c_client *client, int page, int reg);
@@ -347,7 +364,7 @@ bool pmbus_check_byte_register(struct i2
 bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
 int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
 		   struct pmbus_driver_info *info);
-int pmbus_do_remove(struct i2c_client *client);
+void pmbus_do_remove(struct i2c_client *client);
 const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
 						      *client);
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ucd9000.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ucd9000.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ucd9000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ucd9000.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,8 @@ static int ucd9000_read_byte_data(struct
 
 	switch (reg) {
 	case PMBUS_FAN_CONFIG_12:
-		if (page)
-			return -EINVAL;
+		if (page > 0)
+			return -ENXIO;
 
 		ret = ucd9000_get_fan_config(client, 0);
 		if (ret < 0)
@@ -88,8 +88,8 @@ static int ucd9000_read_byte_data(struct
 		ret = fan_config;
 		break;
 	case PMBUS_FAN_CONFIG_34:
-		if (page)
-			return -EINVAL;
+		if (page > 0)
+			return -ENXIO;
 
 		ret = ucd9000_get_fan_config(client, 2);
 		if (ret < 0)
@@ -239,13 +239,12 @@ out:
 
 static int ucd9000_remove(struct i2c_client *client)
 {
-	int ret;
 	struct ucd9000_data *data;
 
 	data = to_ucd9000_data(pmbus_get_driver_info(client));
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(data);
-	return ret;
+	return 0;
 }
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ucd9200.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ucd9200.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/ucd9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/ucd9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,13 +171,12 @@ out:
 
 static int ucd9200_remove(struct i2c_client *client)
 {
-	int ret;
 	const struct pmbus_driver_info *info;
 
 	info = pmbus_get_driver_info(client);
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(info);
-	return ret;
+	return 0;
 }
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/pmbus/zl6100.c linux-libre-3.2-gnu1/drivers/hwmon/pmbus/zl6100.c
--- linux-libre-3.1-gnu1/drivers/hwmon/pmbus/zl6100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hwmon/pmbus/zl6100.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,256 @@
+/*
+ * Hardware monitoring driver for ZL6100 and compatibles
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/ktime.h>
+#include <linux/delay.h>
+#include "pmbus.h"
+
+enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 };
+
+struct zl6100_data {
+	int id;
+	ktime_t access;		/* chip access time */
+	struct pmbus_driver_info info;
+};
+
+#define to_zl6100_data(x)  container_of(x, struct zl6100_data, info)
+
+#define ZL6100_DEVICE_ID		0xe4
+
+#define ZL6100_WAIT_TIME		1000	/* uS	*/
+
+static ushort delay = ZL6100_WAIT_TIME;
+module_param(delay, ushort, 0644);
+MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
+
+/* Some chips need a delay between accesses */
+static inline void zl6100_wait(const struct zl6100_data *data)
+{
+	if (delay) {
+		s64 delta = ktime_us_delta(ktime_get(), data->access);
+		if (delta < delay)
+			udelay(delay - delta);
+	}
+}
+
+static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page || reg >= PMBUS_VIRT_BASE)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_read_word_data(client, page, reg);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_read_byte_data(client, page, reg);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
+				  u16 word)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page || reg >= PMBUS_VIRT_BASE)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_write_word_data(client, page, reg, word);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_write_byte(client, page, value);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static const struct i2c_device_id zl6100_id[] = {
+	{"zl2004", zl2004},
+	{"zl2006", zl2006},
+	{"zl2008", zl2008},
+	{"zl2105", zl2105},
+	{"zl2106", zl2106},
+	{"zl6100", zl6100},
+	{"zl6105", zl6105},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, zl6100_id);
+
+static int zl6100_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct zl6100_data *data;
+	struct pmbus_driver_info *info;
+	u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
+	const struct i2c_device_id *mid;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_BYTE_DATA
+				     | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+		return -ENODEV;
+
+	ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
+					device_id);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to read device ID\n");
+		return ret;
+	}
+	device_id[ret] = '\0';
+	dev_info(&client->dev, "Device ID %s\n", device_id);
+
+	mid = NULL;
+	for (mid = zl6100_id; mid->name[0]; mid++) {
+		if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
+			break;
+	}
+	if (!mid->name[0]) {
+		dev_err(&client->dev, "Unsupported device\n");
+		return -ENODEV;
+	}
+	if (id->driver_data != mid->driver_data)
+		dev_notice(&client->dev,
+			   "Device mismatch: Configured %s, detected %s\n",
+			   id->name, mid->name);
+
+	data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->id = mid->driver_data;
+
+	/*
+	 * ZL2008, ZL2105, and ZL6100 are known to require a wait time
+	 * between I2C accesses. ZL2004 and ZL6105 are known to be safe.
+	 *
+	 * Only clear the wait time for chips known to be safe. The wait time
+	 * can be cleared later for additional chips if tests show that it
+	 * is not needed (in other words, better be safe than sorry).
+	 */
+	if (data->id == zl2004 || data->id == zl6105)
+		delay = 0;
+
+	/*
+	 * Since there was a direct I2C device access above, wait before
+	 * accessing the chip again.
+	 * Set the timestamp, wait, then set it again. This should provide
+	 * enough buffer time to be safe.
+	 */
+	data->access = ktime_get();
+	zl6100_wait(data);
+	data->access = ktime_get();
+
+	info = &data->info;
+
+	info->pages = 1;
+	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+	  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+	  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+
+	info->read_word_data = zl6100_read_word_data;
+	info->read_byte_data = zl6100_read_byte_data;
+	info->write_word_data = zl6100_write_word_data;
+	info->write_byte = zl6100_write_byte;
+
+	ret = pmbus_do_probe(client, mid, info);
+	if (ret)
+		goto err_mem;
+	return 0;
+
+err_mem:
+	kfree(data);
+	return ret;
+}
+
+static int zl6100_remove(struct i2c_client *client)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct zl6100_data *data = to_zl6100_data(info);
+
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_driver zl6100_driver = {
+	.driver = {
+		   .name = "zl6100",
+		   },
+	.probe = zl6100_probe,
+	.remove = zl6100_remove,
+	.id_table = zl6100_id,
+};
+
+static int __init zl6100_init(void)
+{
+	return i2c_add_driver(&zl6100_driver);
+}
+
+static void __exit zl6100_exit(void)
+{
+	i2c_del_driver(&zl6100_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
+MODULE_LICENSE("GPL");
+module_init(zl6100_init);
+module_exit(zl6100_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/s3c-hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/s3c-hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/s3c-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/s3c-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -393,18 +393,7 @@ static struct platform_driver s3c_hwmon_
 	.remove		= __devexit_p(s3c_hwmon_remove),
 };
 
-static int __init s3c_hwmon_init(void)
-{
-	return platform_driver_register(&s3c_hwmon_driver);
-}
-
-static void __exit s3c_hwmon_exit(void)
-{
-	platform_driver_unregister(&s3c_hwmon_driver);
-}
-
-module_init(s3c_hwmon_init);
-module_exit(s3c_hwmon_exit);
+module_platform_driver(s3c_hwmon_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C ADC HWMon driver");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/sch5627.c linux-libre-3.2-gnu1/drivers/hwmon/sch5627.c
--- linux-libre-3.1-gnu1/drivers/hwmon/sch5627.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/sch5627.c	2012-01-04 18:55:44.000000000 -0500
@@ -590,19 +590,8 @@ static struct platform_driver sch5627_dr
 	.remove		= sch5627_remove,
 };
 
-static int __init sch5627_init(void)
-{
-	return platform_driver_register(&sch5627_driver);
-}
-
-static void __exit sch5627_exit(void)
-{
-	platform_driver_unregister(&sch5627_driver);
-}
+module_platform_driver(sch5627_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5627_init);
-module_exit(sch5627_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/sch5636.c linux-libre-3.2-gnu1/drivers/hwmon/sch5636.c
--- linux-libre-3.1-gnu1/drivers/hwmon/sch5636.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/sch5636.c	2012-01-04 18:55:44.000000000 -0500
@@ -521,19 +521,8 @@ static struct platform_driver sch5636_dr
 	.remove		= sch5636_remove,
 };
 
-static int __init sch5636_init(void)
-{
-	return platform_driver_register(&sch5636_driver);
-}
-
-static void __exit sch5636_exit(void)
-{
-	platform_driver_unregister(&sch5636_driver);
-}
+module_platform_driver(sch5636_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5636_init);
-module_exit(sch5636_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/sht21.c linux-libre-3.2-gnu1/drivers/hwmon/sht21.c
--- linux-libre-3.1-gnu1/drivers/hwmon/sht21.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/sht21.c	2012-01-04 18:55:44.000000000 -0500
@@ -83,25 +83,6 @@ static inline int sht21_rh_ticks_to_per_
 }
 
 /**
- * sht21_read_word_data() - read word from register
- * @client: I2C client device
- * @reg: I2C command byte
- *
- * Returns value, negative errno on error.
- */
-static inline int sht21_read_word_data(struct i2c_client *client, u8 reg)
-{
-	int ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	/*
-	 * SMBus specifies low byte first, but the SHT21 returns MSB
-	 * first, so we have to swab16 the values
-	 */
-	return swab16(ret);
-}
-
-/**
  * sht21_update_measurements() - get updated measurements from device
  * @client: I2C client device
  *
@@ -119,12 +100,13 @@ static int sht21_update_measurements(str
 	 * maximum two measurements per second at 12bit accuracy shall be made.
 	 */
 	if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) {
-		ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM);
+		ret = i2c_smbus_read_word_swapped(client,
+						  SHT21_TRIG_T_MEASUREMENT_HM);
 		if (ret < 0)
 			goto out;
 		sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
-		ret = sht21_read_word_data(client,
-					SHT21_TRIG_RH_MEASUREMENT_HM);
+		ret = i2c_smbus_read_word_swapped(client,
+						  SHT21_TRIG_RH_MEASUREMENT_HM);
 		if (ret < 0)
 			goto out;
 		sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/smm665.c linux-libre-3.2-gnu1/drivers/hwmon/smm665.c
--- linux-libre-3.1-gnu1/drivers/hwmon/smm665.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/smm665.c	2012-01-04 18:55:44.000000000 -0500
@@ -214,33 +214,26 @@ static int smm665_read_adc(struct smm665
 	 *
 	 * Neither i2c_smbus_read_byte() nor
 	 * i2c_smbus_read_block_data() worked here,
-	 * so use i2c_smbus_read_word_data() instead.
+	 * so use i2c_smbus_read_word_swapped() instead.
 	 * We could also try to use i2c_master_recv(),
 	 * but that is not always supported.
 	 */
-	rv = i2c_smbus_read_word_data(client, 0);
+	rv = i2c_smbus_read_word_swapped(client, 0);
 	if (rv < 0) {
 		dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
 		return -1;
 	}
 	/*
 	 * Validate/verify readback adc channel (in bit 11..14).
-	 * High byte is in lower 8 bit of rv, so only shift by 3.
 	 */
-	radc = (rv >> 3) & 0x0f;
+	radc = (rv >> 11) & 0x0f;
 	if (radc != adc) {
 		dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
 			adc, radc);
 		return -EIO;
 	}
-	/*
-	 * Chip replies with H/L, while SMBus expects L/H.
-	 * Thus, byte order is reversed, and we have to swap
-	 * the result.
-	 */
-	rv = swab16(rv) & SMM665_ADC_MASK;
 
-	return rv;
+	return rv & SMM665_ADC_MASK;
 }
 
 static struct smm665_data *smm665_update_device(struct device *dev)
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/smsc47b397.c linux-libre-3.2-gnu1/drivers/hwmon/smsc47b397.c
--- linux-libre-3.1-gnu1/drivers/hwmon/smsc47b397.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/smsc47b397.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,7 +113,7 @@ struct smsc47b397_data {
 	u8 temp[4];
 };
 
-static int smsc47b397_read_value(struct smsc47b397_data* data, u8 reg)
+static int smsc47b397_read_value(struct smsc47b397_data *data, u8 reg)
 {
 	int res;
 
@@ -265,7 +265,8 @@ static int __devinit smsc47b397_probe(st
 		return -EBUSY;
 	}
 
-	if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto error_release;
 	}
@@ -276,7 +277,8 @@ static int __devinit smsc47b397_probe(st
 	mutex_init(&data->update_lock);
 	platform_set_drvdata(pdev, data);
 
-	if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group)))
+	err = sysfs_create_group(&dev->kobj, &smsc47b397_group);
+	if (err)
 		goto error_free;
 
 	data->hwmon_dev = hwmon_device_register(dev);
@@ -345,7 +347,7 @@ static int __init smsc47b397_find(unsign
 	superio_enter();
 	id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
-	switch(id) {
+	switch (id) {
 	case 0x81:
 		name = "SCH5307-NS";
 		break;
@@ -379,7 +381,8 @@ static int __init smsc47b397_init(void)
 	unsigned short address;
 	int ret;
 
-	if ((ret = smsc47b397_find(&address)))
+	ret = smsc47b397_find(&address);
+	if (ret)
 		return ret;
 
 	ret = platform_driver_register(&smsc47b397_driver);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/tmp102.c linux-libre-3.2-gnu1/drivers/hwmon/tmp102.c
--- linux-libre-3.1-gnu1/drivers/hwmon/tmp102.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/tmp102.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,19 +55,6 @@ struct tmp102 {
 	int temp[3];
 };
 
-/* SMBus specifies low byte first, but the TMP102 returns high byte first,
- * so we have to swab16 the values */
-static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
-{
-	int result = i2c_smbus_read_word_data(client, reg);
-	return result < 0 ? result : swab16(result);
-}
-
-static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(val));
-}
-
 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */
 static inline int tmp102_reg_to_mC(s16 val)
 {
@@ -94,7 +81,8 @@ static struct tmp102 *tmp102_update_devi
 	if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
 		int i;
 		for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
-			int status = tmp102_read_reg(client, tmp102_reg[i]);
+			int status = i2c_smbus_read_word_swapped(client,
+								 tmp102_reg[i]);
 			if (status > -1)
 				tmp102->temp[i] = tmp102_reg_to_mC(status);
 		}
@@ -130,8 +118,8 @@ static ssize_t tmp102_set_temp(struct de
 
 	mutex_lock(&tmp102->lock);
 	tmp102->temp[sda->index] = val;
-	status = tmp102_write_reg(client, tmp102_reg[sda->index],
-				  tmp102_mC_to_reg(val));
+	status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index],
+					      tmp102_mC_to_reg(val));
 	mutex_unlock(&tmp102->lock);
 	return status ? : count;
 }
@@ -178,18 +166,19 @@ static int __devinit tmp102_probe(struct
 	}
 	i2c_set_clientdata(client, tmp102);
 
-	status = tmp102_read_reg(client, TMP102_CONF_REG);
+	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
 		dev_err(&client->dev, "error reading config register\n");
 		goto fail_free;
 	}
 	tmp102->config_orig = status;
-	status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
+	status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+					      TMP102_CONFIG);
 	if (status < 0) {
 		dev_err(&client->dev, "error writing config register\n");
 		goto fail_restore_config;
 	}
-	status = tmp102_read_reg(client, TMP102_CONF_REG);
+	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
 		dev_err(&client->dev, "error reading config register\n");
 		goto fail_restore_config;
@@ -222,7 +211,8 @@ static int __devinit tmp102_probe(struct
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
-	tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
+	i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+				     tmp102->config_orig);
 fail_free:
 	kfree(tmp102);
 
@@ -240,10 +230,10 @@ static int __devexit tmp102_remove(struc
 	if (tmp102->config_orig & TMP102_CONF_SD) {
 		int config;
 
-		config = tmp102_read_reg(client, TMP102_CONF_REG);
+		config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 		if (config >= 0)
-			tmp102_write_reg(client, TMP102_CONF_REG,
-					 config | TMP102_CONF_SD);
+			i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+						     config | TMP102_CONF_SD);
 	}
 
 	kfree(tmp102);
@@ -257,12 +247,12 @@ static int tmp102_suspend(struct device
 	struct i2c_client *client = to_i2c_client(dev);
 	int config;
 
-	config = tmp102_read_reg(client, TMP102_CONF_REG);
+	config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (config < 0)
 		return config;
 
 	config |= TMP102_CONF_SD;
-	return tmp102_write_reg(client, TMP102_CONF_REG, config);
+	return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static int tmp102_resume(struct device *dev)
@@ -270,12 +260,12 @@ static int tmp102_resume(struct device *
 	struct i2c_client *client = to_i2c_client(dev);
 	int config;
 
-	config = tmp102_read_reg(client, TMP102_CONF_REG);
+	config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (config < 0)
 		return config;
 
 	config &= ~TMP102_CONF_SD;
-	return tmp102_write_reg(client, TMP102_CONF_REG, config);
+	return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static const struct dev_pm_ops tmp102_dev_pm_ops = {
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/twl4030-madc-hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/twl4030-madc-hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/twl4030-madc-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/twl4030-madc-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,19 +136,7 @@ static struct platform_driver twl4030_ma
 		   },
 };
 
-static int __init twl4030_madc_hwmon_init(void)
-{
-	return platform_driver_register(&twl4030_madc_hwmon_driver);
-}
-
-module_init(twl4030_madc_hwmon_init);
-
-static void __exit twl4030_madc_hwmon_exit(void)
-{
-	platform_driver_unregister(&twl4030_madc_hwmon_driver);
-}
-
-module_exit(twl4030_madc_hwmon_exit);
+module_platform_driver(twl4030_madc_hwmon_driver);
 
 MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/ultra45_env.c linux-libre-3.2-gnu1/drivers/hwmon/ultra45_env.c
--- linux-libre-3.1-gnu1/drivers/hwmon/ultra45_env.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/ultra45_env.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/io.h>
 #include <linux/hwmon.h>
@@ -308,15 +309,4 @@ static struct platform_driver env_driver
 	.remove		= __devexit_p(env_remove),
 };
 
-static int __init env_init(void)
-{
-	return platform_driver_register(&env_driver);
-}
-
-static void __exit env_exit(void)
-{
-	platform_driver_unregister(&env_driver);
-}
-
-module_init(env_init);
-module_exit(env_exit);
+module_platform_driver(env_driver);
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/w83627ehf.c linux-libre-3.2-gnu1/drivers/hwmon/w83627ehf.c
--- linux-libre-3.1-gnu1/drivers/hwmon/w83627ehf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/w83627ehf.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
     w83627ehf - Driver for the hardware monitoring functionality of
 		the Winbond W83627EHF Super-I/O chip
-    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2005-2011  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2006  Yuan Mu (Winbond),
 			Rudolf Marek <r.marek@assembler.cz>
 			David Hubbard <david.c.hubbard@gmail.com>
@@ -39,6 +39,7 @@
 					       0x8860 0xa1
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
     w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
+    w83627uhg    8      2       2       2      0xa230 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
     w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
     nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
@@ -61,14 +62,17 @@
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
-	nct6776 };
+enum kinds {
+	w83627ehf, w83627dhg, w83627dhg_p, w83627uhg,
+	w83667hg, w83667hg_b, nct6775, nct6776,
+};
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
 static const char * const w83627ehf_device_names[] = {
 	"w83627ehf",
 	"w83627dhg",
 	"w83627dhg",
+	"w83627uhg",
 	"w83667hg",
 	"w83667hg",
 	"nct6775",
@@ -104,6 +108,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable d
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627DHG_ID	0xa020
 #define SIO_W83627DHG_P_ID	0xb070
+#define SIO_W83627UHG_ID	0xa230
 #define SIO_W83667HG_ID		0xa510
 #define SIO_W83667HG_B_ID	0xb350
 #define SIO_NCT6775_ID		0xb470
@@ -197,6 +202,9 @@ static const u16 W83627EHF_REG_TEMP_CONF
 #define W83627EHF_REG_ALARM2		0x45A
 #define W83627EHF_REG_ALARM3		0x45B
 
+#define W83627EHF_REG_CASEOPEN_DET	0x42 /* SMI STATUS #2 */
+#define W83627EHF_REG_CASEOPEN_CLR	0x46 /* SMI MASK #3 */
+
 /* SmartFan registers */
 #define W83627EHF_REG_FAN_STEPUP_TIME 0x0f
 #define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e
@@ -316,7 +324,7 @@ static const char *const nct6776_temp_la
 
 #define NUM_REG_TEMP	ARRAY_SIZE(NCT6775_REG_TEMP)
 
-static inline int is_word_sized(u16 reg)
+static int is_word_sized(u16 reg)
 {
 	return ((((reg & 0xff00) == 0x100
 	      || (reg & 0xff00) == 0x200)
@@ -385,35 +393,23 @@ div_from_reg(u8 reg)
 	return 1 << reg;
 }
 
-static inline int
-temp_from_reg(u16 reg, s16 regval)
-{
-	if (is_word_sized(reg))
-		return LM75_TEMP_FROM_REG(regval);
-	return ((s8)regval) * 1000;
-}
-
-static inline u16
-temp_to_reg(u16 reg, long temp)
-{
-	if (is_word_sized(reg))
-		return LM75_TEMP_TO_REG(temp);
-	return (s8)DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000),
-				     1000);
-}
-
-/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
-
-static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
+/* Some of the voltage inputs have internal scaling, the tables below
+ * contain 8 (the ADC LSB in mV) * scaling factor * 100 */
+static const u16 scale_in_common[10] = {
+	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800
+};
+static const u16 scale_in_w83627uhg[9] = {
+	800, 800, 3328, 3424, 800, 800, 0, 3328, 3400
+};
 
-static inline long in_from_reg(u8 reg, u8 nr)
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
 {
-	return reg * scale_in[nr];
+	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
 }
 
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
 {
-	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
+	return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
 			     255);
 }
 
@@ -444,6 +440,7 @@ struct w83627ehf_data {
 	const u16 *REG_FAN_STOP_TIME;
 	const u16 *REG_FAN_MAX_OUTPUT;
 	const u16 *REG_FAN_STEP_OUTPUT;
+	const u16 *scale_in;
 
 	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
 	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
@@ -469,6 +466,7 @@ struct w83627ehf_data {
 	s16 temp_max[9];
 	s16 temp_max_hyst[9];
 	u32 alarms;
+	u8 caseopen;
 
 	u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
 	u8 pwm_enable[4]; /* 1->manual
@@ -494,7 +492,8 @@ struct w83627ehf_data {
 	u8 vrm;
 
 	u16 have_temp;
-	u8 in6_skip;
+	u8 in6_skip:1;
+	u8 temp3_val_only:1;
 };
 
 struct w83627ehf_sio_data {
@@ -557,6 +556,26 @@ static int w83627ehf_write_value(struct
 	return 0;
 }
 
+/* We left-align 8-bit temperature values to make the code simpler */
+static u16 w83627ehf_read_temp(struct w83627ehf_data *data, u16 reg)
+{
+	u16 res;
+
+	res = w83627ehf_read_value(data, reg);
+	if (!is_word_sized(reg))
+		res <<= 8;
+
+	return res;
+}
+
+static int w83627ehf_write_temp(struct w83627ehf_data *data, u16 reg,
+				       u16 value)
+{
+	if (!is_word_sized(reg))
+		value >>= 8;
+	return w83627ehf_write_value(data, reg, value);
+}
+
 /* This function assumes that the caller holds data->update_lock */
 static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
 {
@@ -771,6 +790,9 @@ static struct w83627ehf_data *w83627ehf_
 
 		/* Measured voltages and limits */
 		for (i = 0; i < data->in_num; i++) {
+			if ((i == 6) && data->in6_skip)
+				continue;
+
 			data->in[i] = w83627ehf_read_value(data,
 				      W83627EHF_REG_IN(i));
 			data->in_min[i] = w83627ehf_read_value(data,
@@ -855,15 +877,15 @@ static struct w83627ehf_data *w83627ehf_
 		for (i = 0; i < NUM_REG_TEMP; i++) {
 			if (!(data->have_temp & (1 << i)))
 				continue;
-			data->temp[i] = w83627ehf_read_value(data,
+			data->temp[i] = w83627ehf_read_temp(data,
 						data->reg_temp[i]);
 			if (data->reg_temp_over[i])
 				data->temp_max[i]
-				  = w83627ehf_read_value(data,
+				  = w83627ehf_read_temp(data,
 						data->reg_temp_over[i]);
 			if (data->reg_temp_hyst[i])
 				data->temp_max_hyst[i]
-				  = w83627ehf_read_value(data,
+				  = w83627ehf_read_temp(data,
 						data->reg_temp_hyst[i]);
 		}
 
@@ -874,6 +896,9 @@ static struct w83627ehf_data *w83627ehf_
 			       (w83627ehf_read_value(data,
 					W83627EHF_REG_ALARM3) << 16);
 
+		data->caseopen = w83627ehf_read_value(data,
+						W83627EHF_REG_CASEOPEN_DET);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -894,7 +919,8 @@ show_##reg(struct device *dev, struct de
 	struct sensor_device_attribute *sensor_attr = \
 		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
+	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \
+		       data->scale_in)); \
 }
 show_in_reg(in)
 show_in_reg(in_min)
@@ -915,7 +941,7 @@ store_in_##reg(struct device *dev, struc
 	if (err < 0) \
 		return err; \
 	mutex_lock(&data->update_lock); \
-	data->in_##reg[nr] = in_to_reg(val, nr); \
+	data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \
 	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
 			      data->in_##reg[nr]); \
 	mutex_unlock(&data->update_lock); \
@@ -1156,8 +1182,7 @@ show_##reg(struct device *dev, struct de
 	struct sensor_device_attribute *sensor_attr = \
 		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", \
-		       temp_from_reg(data->addr[nr], data->reg[nr])); \
+	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->reg[nr])); \
 }
 show_temp_reg(reg_temp, temp);
 show_temp_reg(reg_temp_over, temp_max);
@@ -1178,9 +1203,8 @@ store_##reg(struct device *dev, struct d
 	if (err < 0) \
 		return err; \
 	mutex_lock(&data->update_lock); \
-	data->reg[nr] = temp_to_reg(data->addr[nr], val); \
-	w83627ehf_write_value(data, data->addr[nr], \
-			      data->reg[nr]); \
+	data->reg[nr] = LM75_TEMP_TO_REG(val); \
+	w83627ehf_write_temp(data, data->addr[nr], data->reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -1606,25 +1630,28 @@ static struct sensor_device_attribute sd
 		    store_fan_step_output, 3),
 };
 
+static struct sensor_device_attribute sda_sf3_arrays_fan3[] = {
+	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 2),
+	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
+		    store_fan_start_output, 2),
+	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
+		    store_fan_stop_output, 2),
+};
+
 static struct sensor_device_attribute sda_sf3_arrays[] = {
 	SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
 		    store_fan_stop_time, 0),
 	SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
 		    store_fan_stop_time, 1),
-	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
-		    store_fan_stop_time, 2),
 	SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
 		    store_fan_start_output, 0),
 	SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
 		    store_fan_start_output, 1),
-	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
-		    store_fan_start_output, 2),
 	SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
 		    store_fan_stop_output, 0),
 	SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
 		    store_fan_stop_output, 1),
-	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
-		    store_fan_stop_output, 2),
 };
 
 
@@ -1655,6 +1682,48 @@ show_vid(struct device *dev, struct devi
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
+
+/* Case open detection */
+
+static ssize_t
+show_caseopen(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		!!(data->caseopen & to_sensor_dev_attr_2(attr)->index));
+}
+
+static ssize_t
+clear_caseopen(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	u16 reg, mask;
+
+	if (strict_strtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mask = to_sensor_dev_attr_2(attr)->nr;
+
+	mutex_lock(&data->update_lock);
+	reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR);
+	w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask);
+	w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask);
+	data->valid = 0;	/* Force cache refresh */
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute_2 sda_caseopen[] = {
+	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+			clear_caseopen, 0x80, 0x10),
+	SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+			clear_caseopen, 0x40, 0x40),
+};
+
 /*
  * Driver and device management
  */
@@ -1675,6 +1744,8 @@ static void w83627ehf_device_remove_file
 		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
 			device_remove_file(dev, &attr->dev_attr);
 	}
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++)
+		device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr);
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
 		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
 	for (i = 0; i < data->in_num; i++) {
@@ -1703,6 +1774,8 @@ static void w83627ehf_device_remove_file
 			continue;
 		device_remove_file(dev, &sda_temp_input[i].dev_attr);
 		device_remove_file(dev, &sda_temp_label[i].dev_attr);
+		if (i == 2 && data->temp3_val_only)
+			continue;
 		device_remove_file(dev, &sda_temp_max[i].dev_attr);
 		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
 		if (i > 2)
@@ -1711,6 +1784,9 @@ static void w83627ehf_device_remove_file
 		device_remove_file(dev, &sda_temp_type[i].dev_attr);
 	}
 
+	device_remove_file(dev, &sda_caseopen[0].dev_attr);
+	device_remove_file(dev, &sda_caseopen[1].dev_attr);
+
 	device_remove_file(dev, &dev_attr_name);
 	device_remove_file(dev, &dev_attr_cpu0_vid);
 }
@@ -1752,11 +1828,24 @@ static inline void __devinit w83627ehf_i
 	case w83627ehf:
 		diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
 		break;
+	case w83627uhg:
+		diode = 0x00;
+		break;
 	default:
 		diode = 0x70;
 	}
 	for (i = 0; i < 3; i++) {
-		if ((tmp & (0x02 << i)))
+		const char *label = NULL;
+
+		if (data->temp_label)
+			label = data->temp_label[data->temp_src[i]];
+
+		/* Digital source overrides analog type */
+		if (label && strncmp(label, "PECI", 4) == 0)
+			data->temp_type[i] = 6;
+		else if (label && strncmp(label, "AMD", 3) == 0)
+			data->temp_type[i] = 5;
+		else if ((tmp & (0x02 << i)))
 			data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3;
 		else
 			data->temp_type[i] = 4; /* thermistor */
@@ -1789,13 +1878,98 @@ static void w82627ehf_swap_tempreg(struc
 	data->reg_temp_config[r2] = tmp;
 }
 
+static void __devinit
+w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
+{
+	int i;
+
+	for (i = 0; i < n_temp; i++) {
+		data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+		data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+		data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+		data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+	}
+}
+
+static void __devinit
+w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
+			   struct w83627ehf_data *data)
+{
+	int fan3pin, fan4pin, fan4min, fan5pin, regval;
+
+	/* The W83627UHG is simple, only two fan inputs, no config */
+	if (sio_data->kind == w83627uhg) {
+		data->has_fan = 0x03; /* fan1 and fan2 */
+		data->has_fan_min = 0x03;
+		return;
+	}
+
+	superio_enter(sio_data->sioreg);
+
+	/* fan4 and fan5 share some pins with the GPIO and serial flash */
+	if (sio_data->kind == nct6775) {
+		/* On NCT6775, fan4 shares pins with the fdc interface */
+		fan3pin = 1;
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+		fan4min = 0;
+		fan5pin = 0;
+	} else if (sio_data->kind == nct6776) {
+		fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+		fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+		fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+		fan4min = fan4pin;
+	} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+		fan3pin = 1;
+		fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
+		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+		fan4min = fan4pin;
+	} else {
+		fan3pin = 1;
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan4min = fan4pin;
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+	data->has_fan |= (fan3pin << 2);
+	data->has_fan_min |= (fan3pin << 2);
+
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		/*
+		 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1
+		 * register
+		 */
+		data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+		data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+	} else {
+		/*
+		 * It looks like fan4 and fan5 pins can be alternatively used
+		 * as fan on/off switches, but fan5 control is write only :/
+		 * We assume that if the serial interface is disabled, designers
+		 * connected fan5 as input unless they are emitting log 1, which
+		 * is not the default.
+		 */
+		regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+		if ((regval & (1 << 2)) && fan4pin) {
+			data->has_fan |= (1 << 3);
+			data->has_fan_min |= (1 << 3);
+		}
+		if (!(regval & (1 << 1)) && fan5pin) {
+			data->has_fan |= (1 << 4);
+			data->has_fan_min |= (1 << 4);
+		}
+	}
+}
+
 static int __devinit w83627ehf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct w83627ehf_data *data;
 	struct resource *res;
-	u8 fan3pin, fan4pin, fan4min, fan5pin, en_vrm10;
+	u8 en_vrm10;
 	int i, err = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1821,23 +1995,24 @@ static int __devinit w83627ehf_probe(str
 
 	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
 	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
-	/* 667HG, NCT6775F, and NCT6776F have 3 pwms */
-	data->pwm_num = (sio_data->kind == w83667hg
-			 || sio_data->kind == w83667hg_b
-			 || sio_data->kind == nct6775
-			 || sio_data->kind == nct6776) ? 3 : 4;
+	/* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */
+	switch (sio_data->kind) {
+	default:
+		data->pwm_num = 4;
+		break;
+	case w83667hg:
+	case w83667hg_b:
+	case nct6775:
+	case nct6776:
+		data->pwm_num = 3;
+		break;
+	case w83627uhg:
+		data->pwm_num = 2;
+		break;
+	}
 
+	/* Default to 3 temperature inputs, code below will adjust as needed */
 	data->have_temp = 0x07;
-	/* Check temp3 configuration bit for 667HG */
-	if (sio_data->kind == w83667hg) {
-		u8 reg;
-
-		reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
-		if (reg & 0x01)
-			data->have_temp &= ~(1 << 2);
-		else
-			data->in6_skip = 1;	/* either temp3 or in6 */
-	}
 
 	/* Deal with temperature register setup first. */
 	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
@@ -1914,16 +2089,12 @@ static int __devinit w83627ehf_probe(str
 	} else if (sio_data->kind == w83667hg_b) {
 		u8 reg;
 
+		w83627ehf_set_temp_reg_ehf(data, 4);
+
 		/*
 		 * Temperature sources are selected with bank 0, registers 0x49
 		 * and 0x4a.
 		 */
-		for (i = 0; i < ARRAY_SIZE(W83627EHF_REG_TEMP); i++) {
-			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
-			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
-			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
-			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
-		}
 		reg = w83627ehf_read_value(data, 0x4a);
 		data->temp_src[0] = reg >> 5;
 		reg = w83627ehf_read_value(data, 0x49);
@@ -1957,13 +2128,60 @@ static int __devinit w83627ehf_probe(str
 			data->in6_skip = 1;
 
 		data->temp_label = w83667hg_b_temp_label;
+	} else if (sio_data->kind == w83627uhg) {
+		u8 reg;
+
+		w83627ehf_set_temp_reg_ehf(data, 3);
+
+		/*
+		 * Temperature sources for temp1 and temp2 are selected with
+		 * bank 0, registers 0x49 and 0x4a.
+		 */
+		data->temp_src[0] = 0;	/* SYSTIN */
+		reg = w83627ehf_read_value(data, 0x49) & 0x07;
+		/* Adjust to have the same mapping as other source registers */
+		if (reg == 0)
+			data->temp_src[1]++;
+		else if (reg >= 2 && reg <= 5)
+			data->temp_src[1] += 2;
+		else	/* should never happen */
+			data->have_temp &= ~(1 << 1);
+		reg = w83627ehf_read_value(data, 0x4a);
+		data->temp_src[2] = reg >> 5;
+
+		/*
+		 * Skip temp3 if source is invalid or the same as temp1
+		 * or temp2.
+		 */
+		if (data->temp_src[2] == 2 || data->temp_src[2] == 3 ||
+		    data->temp_src[2] == data->temp_src[0] ||
+		    ((data->have_temp & (1 << 1)) &&
+		     data->temp_src[2] == data->temp_src[1]))
+			data->have_temp &= ~(1 << 2);
+		else
+			data->temp3_val_only = 1;	/* No limit regs */
+
+		data->in6_skip = 1;			/* No VIN3 */
+
+		data->temp_label = w83667hg_b_temp_label;
 	} else {
+		w83627ehf_set_temp_reg_ehf(data, 3);
+
 		/* Temperature sources are fixed */
-		for (i = 0; i < 3; i++) {
-			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
-			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
-			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
-			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+
+		if (sio_data->kind == w83667hg) {
+			u8 reg;
+
+			/*
+			 * Chip supports either AUXTIN or VIN3. Try to find
+			 * out which one.
+			 */
+			reg = w83627ehf_read_value(data,
+						W83627EHF_REG_TEMP_CONFIG[2]);
+			if (reg & 0x01)
+				data->have_temp &= ~(1 << 2);
+			else
+				data->in6_skip = 1;
 		}
 	}
 
@@ -2023,6 +2241,12 @@ static int __devinit w83627ehf_probe(str
 		  W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
 	}
 
+	/* Setup input voltage scaling factors */
+	if (sio_data->kind == w83627uhg)
+		data->scale_in = scale_in_w83627uhg;
+	else
+		data->scale_in = scale_in_common;
+
 	/* Initialize the chip */
 	w83627ehf_init_device(data, sio_data->kind);
 
@@ -2039,7 +2263,7 @@ static int __devinit w83627ehf_probe(str
 		err = device_create_file(dev, &dev_attr_cpu0_vid);
 		if (err)
 			goto exit_release;
-	} else {
+	} else if (sio_data->kind != w83627uhg) {
 		superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
 		if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
 			/* Set VID input sensibility if needed. In theory the
@@ -2080,30 +2304,6 @@ static int __devinit w83627ehf_probe(str
 		}
 	}
 
-	/* fan4 and fan5 share some pins with the GPIO and serial flash */
-	if (sio_data->kind == nct6775) {
-		/* On NCT6775, fan4 shares pins with the fdc interface */
-		fan3pin = 1;
-		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
-		fan4min = 0;
-		fan5pin = 0;
-	} else if (sio_data->kind == nct6776) {
-		fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
-		fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
-		fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
-		fan4min = fan4pin;
-	} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
-		fan3pin = 1;
-		fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
-		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
-		fan4min = fan4pin;
-	} else {
-		fan3pin = 1;
-		fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
-		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
-		fan4min = fan4pin;
-	}
-
 	if (fan_debounce &&
 	    (sio_data->kind == nct6775 || sio_data->kind == nct6776)) {
 		u8 tmp;
@@ -2121,34 +2321,7 @@ static int __devinit w83627ehf_probe(str
 
 	superio_exit(sio_data->sioreg);
 
-	/* It looks like fan4 and fan5 pins can be alternatively used
-	   as fan on/off switches, but fan5 control is write only :/
-	   We assume that if the serial interface is disabled, designers
-	   connected fan5 as input unless they are emitting log 1, which
-	   is not the default. */
-
-	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
-
-	data->has_fan |= (fan3pin << 2);
-	data->has_fan_min |= (fan3pin << 2);
-
-	/*
-	 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1 register
-	 */
-	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
-		data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
-		data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
-	} else {
-		i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
-		if ((i & (1 << 2)) && fan4pin) {
-			data->has_fan |= (1 << 3);
-			data->has_fan_min |= (1 << 3);
-		}
-		if (!(i & (1 << 1)) && fan5pin) {
-			data->has_fan |= (1 << 4);
-			data->has_fan_min |= (1 << 4);
-		}
-	}
+	w83627ehf_check_fan_inputs(sio_data, data);
 
 	/* Read fan clock dividers immediately */
 	w83627ehf_update_fan_div_common(dev, data);
@@ -2180,7 +2353,14 @@ static int __devinit w83627ehf_probe(str
 				goto exit_remove;
 		}
 	}
-	/* if fan4 is enabled create the sf3 files for it */
+	/* if fan3 and fan4 are enabled create the sf3 files for them */
+	if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3)
+		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) {
+			err = device_create_file(dev,
+					&sda_sf3_arrays_fan3[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
 	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
 		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
 			err = device_create_file(dev,
@@ -2248,6 +2428,8 @@ static int __devinit w83627ehf_probe(str
 			if (err)
 				goto exit_remove;
 		}
+		if (i == 2 && data->temp3_val_only)
+			continue;
 		if (data->reg_temp_over[i]) {
 			err = device_create_file(dev,
 				&sda_temp_max[i].dev_attr);
@@ -2269,6 +2451,16 @@ static int __devinit w83627ehf_probe(str
 			goto exit_remove;
 	}
 
+	err = device_create_file(dev, &sda_caseopen[0].dev_attr);
+	if (err)
+		goto exit_remove;
+
+	if (sio_data->kind == nct6776) {
+		err = device_create_file(dev, &sda_caseopen[1].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
 	err = device_create_file(dev, &dev_attr_name);
 	if (err)
 		goto exit_remove;
@@ -2321,6 +2513,7 @@ static int __init w83627ehf_find(int sio
 	static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
 	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
 	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
+	static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
 	static const char __initdata sio_name_W83667HG[] = "W83667HG";
 	static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
 	static const char __initdata sio_name_NCT6775[] = "NCT6775F";
@@ -2353,6 +2546,10 @@ static int __init w83627ehf_find(int sio
 		sio_data->kind = w83627dhg_p;
 		sio_name = sio_name_W83627DHG_P;
 		break;
+	case SIO_W83627UHG_ID:
+		sio_data->kind = w83627uhg;
+		sio_name = sio_name_W83627UHG;
+		break;
 	case SIO_W83667HG_ID:
 		sio_data->kind = w83667hg;
 		sio_name = sio_name_W83667HG;
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/w83781d.c linux-libre-3.2-gnu1/drivers/hwmon/w83781d.c
--- linux-libre-3.1-gnu1/drivers/hwmon/w83781d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/w83781d.c	2012-01-04 18:55:44.000000000 -0500
@@ -1245,17 +1245,17 @@ w83781d_read_value_i2c(struct w83781d_da
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50:	/* TEMP */
-			res = swab16(i2c_smbus_read_word_data(cl, 0));
+			res = i2c_smbus_read_word_swapped(cl, 0);
 			break;
 		case 0x52:	/* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53:	/* HYST */
-			res = swab16(i2c_smbus_read_word_data(cl, 2));
+			res = i2c_smbus_read_word_swapped(cl, 2);
 			break;
 		case 0x55:	/* OVER */
 		default:
-			res = swab16(i2c_smbus_read_word_data(cl, 3));
+			res = i2c_smbus_read_word_swapped(cl, 3);
 			break;
 		}
 	}
@@ -1289,10 +1289,10 @@ w83781d_write_value_i2c(struct w83781d_d
 			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 			break;
 		case 0x53:	/* HYST */
-			i2c_smbus_write_word_data(cl, 2, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 2, value);
 			break;
 		case 0x55:	/* OVER */
-			i2c_smbus_write_word_data(cl, 3, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 3, value);
 			break;
 		}
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/wm831x-hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/wm831x-hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/wm831x-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/wm831x-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -209,17 +209,7 @@ static struct platform_driver wm831x_hwm
 	},
 };
 
-static int __init wm831x_hwmon_init(void)
-{
-	return platform_driver_register(&wm831x_hwmon_driver);
-}
-module_init(wm831x_hwmon_init);
-
-static void __exit wm831x_hwmon_exit(void)
-{
-	platform_driver_unregister(&wm831x_hwmon_driver);
-}
-module_exit(wm831x_hwmon_exit);
+module_platform_driver(wm831x_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM831x Hardware Monitoring");
diff -druNp linux-libre-3.1-gnu1/drivers/hwmon/wm8350-hwmon.c linux-libre-3.2-gnu1/drivers/hwmon/wm8350-hwmon.c
--- linux-libre-3.1-gnu1/drivers/hwmon/wm8350-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwmon/wm8350-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -133,17 +133,7 @@ static struct platform_driver wm8350_hwm
 	},
 };
 
-static int __init wm8350_hwmon_init(void)
-{
-	return platform_driver_register(&wm8350_hwmon_driver);
-}
-module_init(wm8350_hwmon_init);
-
-static void __exit wm8350_hwmon_exit(void)
-{
-	platform_driver_unregister(&wm8350_hwmon_driver);
-}
-module_exit(wm8350_hwmon_exit);
+module_platform_driver(wm8350_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM8350 Hardware Monitoring");
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/hwspinlock_core.c linux-libre-3.2-gnu1/drivers/hwspinlock/hwspinlock_core.c
--- linux-libre-3.1-gnu1/drivers/hwspinlock/hwspinlock_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/hwspinlock_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/radix-tree.h>
 #include <linux/hwspinlock.h>
 #include <linux/pm_runtime.h>
+#include <linux/mutex.h>
 
 #include "hwspinlock_internal.h"
 
@@ -52,10 +53,12 @@
 static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
 
 /*
- * Synchronization of access to the tree is achieved using this spinlock,
+ * Synchronization of access to the tree is achieved using this mutex,
  * as the radix-tree API requires that users provide all synchronisation.
+ * A mutex is needed because we're using non-atomic radix tree allocations.
  */
-static DEFINE_SPINLOCK(hwspinlock_tree_lock);
+static DEFINE_MUTEX(hwspinlock_tree_lock);
+
 
 /**
  * __hwspin_trylock() - attempt to lock a specific hwspinlock
@@ -114,7 +117,7 @@ int __hwspin_trylock(struct hwspinlock *
 		return -EBUSY;
 
 	/* try to take the hwspinlock device */
-	ret = hwlock->ops->trylock(hwlock);
+	ret = hwlock->bank->ops->trylock(hwlock);
 
 	/* if hwlock is already taken, undo spin_trylock_* and exit */
 	if (!ret) {
@@ -196,8 +199,8 @@ int __hwspin_lock_timeout(struct hwspinl
 		 * Allow platform-specific relax handlers to prevent
 		 * hogging the interconnect (no sleeping, though)
 		 */
-		if (hwlock->ops->relax)
-			hwlock->ops->relax(hwlock);
+		if (hwlock->bank->ops->relax)
+			hwlock->bank->ops->relax(hwlock);
 	}
 
 	return ret;
@@ -242,7 +245,7 @@ void __hwspin_unlock(struct hwspinlock *
 	 */
 	mb();
 
-	hwlock->ops->unlock(hwlock);
+	hwlock->bank->ops->unlock(hwlock);
 
 	/* Undo the spin_trylock{_irq, _irqsave} called while locking */
 	if (mode == HWLOCK_IRQSTATE)
@@ -254,68 +257,37 @@ void __hwspin_unlock(struct hwspinlock *
 }
 EXPORT_SYMBOL_GPL(__hwspin_unlock);
 
-/**
- * hwspin_lock_register() - register a new hw spinlock
- * @hwlock: hwspinlock to register.
- *
- * This function should be called from the underlying platform-specific
- * implementation, to register a new hwspinlock instance.
- *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context.
- *
- * Returns 0 on success, or an appropriate error code on failure
- */
-int hwspin_lock_register(struct hwspinlock *hwlock)
+static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
 {
 	struct hwspinlock *tmp;
 	int ret;
 
-	if (!hwlock || !hwlock->ops ||
-		!hwlock->ops->trylock || !hwlock->ops->unlock) {
-		pr_err("invalid parameters\n");
-		return -EINVAL;
-	}
-
-	spin_lock_init(&hwlock->lock);
-
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
-	ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
-	if (ret)
+	ret = radix_tree_insert(&hwspinlock_tree, id, hwlock);
+	if (ret) {
+		if (ret == -EEXIST)
+			pr_err("hwspinlock id %d already exists!\n", id);
 		goto out;
+	}
 
 	/* mark this hwspinlock as available */
-	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
-							HWSPINLOCK_UNUSED);
+	tmp = radix_tree_tag_set(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
 
 	/* self-sanity check which should never fail */
 	WARN_ON(tmp != hwlock);
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
-	return ret;
+	mutex_unlock(&hwspinlock_tree_lock);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(hwspin_lock_register);
 
-/**
- * hwspin_lock_unregister() - unregister an hw spinlock
- * @id: index of the specific hwspinlock to unregister
- *
- * This function should be called from the underlying platform-specific
- * implementation, to unregister an existing (and unused) hwspinlock.
- *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context.
- *
- * Returns the address of hwspinlock @id on success, or NULL on failure
- */
-struct hwspinlock *hwspin_lock_unregister(unsigned int id)
+static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
 {
 	struct hwspinlock *hwlock = NULL;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* make sure the hwspinlock is not in use (tag is set) */
 	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
@@ -331,9 +303,91 @@ struct hwspinlock *hwspin_lock_unregiste
 	}
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
+
+/**
+ * hwspin_lock_register() - register a new hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ * @dev: the backing device
+ * @ops: hwspinlock handlers for this device
+ * @base_id: id of the first hardware spinlock in this bank
+ * @num_locks: number of hwspinlocks provided by this device
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to register a new hwspinlock device instance.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+		const struct hwspinlock_ops *ops, int base_id, int num_locks)
+{
+	struct hwspinlock *hwlock;
+	int ret = 0, i;
+
+	if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
+							!ops->unlock) {
+		pr_err("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	bank->dev = dev;
+	bank->ops = ops;
+	bank->base_id = base_id;
+	bank->num_locks = num_locks;
+
+	for (i = 0; i < num_locks; i++) {
+		hwlock = &bank->lock[i];
+
+		spin_lock_init(&hwlock->lock);
+		hwlock->bank = bank;
+
+		ret = hwspin_lock_register_single(hwlock, i);
+		if (ret)
+			goto reg_failed;
+	}
+
+	return 0;
+
+reg_failed:
+	while (--i >= 0)
+		hwspin_lock_unregister_single(i);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_register);
+
+/**
+ * hwspin_lock_unregister() - unregister an hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to unregister an existing (and unused) hwspinlock.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_unregister(struct hwspinlock_device *bank)
+{
+	struct hwspinlock *hwlock, *tmp;
+	int i;
+
+	for (i = 0; i < bank->num_locks; i++) {
+		hwlock = &bank->lock[i];
+
+		tmp = hwspin_lock_unregister_single(bank->base_id + i);
+		if (!tmp)
+			return -EBUSY;
+
+		/* self-sanity check that should never fail */
+		WARN_ON(tmp != hwlock);
+	}
+
+	return 0;
+}
 EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
 
 /**
@@ -348,24 +402,25 @@ EXPORT_SYMBOL_GPL(hwspin_lock_unregister
  */
 static int __hwspin_lock_request(struct hwspinlock *hwlock)
 {
+	struct device *dev = hwlock->bank->dev;
 	struct hwspinlock *tmp;
 	int ret;
 
 	/* prevent underlying implementation from being removed */
-	if (!try_module_get(hwlock->owner)) {
-		dev_err(hwlock->dev, "%s: can't get owner\n", __func__);
+	if (!try_module_get(dev->driver->owner)) {
+		dev_err(dev, "%s: can't get owner\n", __func__);
 		return -EINVAL;
 	}
 
 	/* notify PM core that power is now needed */
-	ret = pm_runtime_get_sync(hwlock->dev);
+	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
-		dev_err(hwlock->dev, "%s: can't power on device\n", __func__);
+		dev_err(dev, "%s: can't power on device\n", __func__);
 		return ret;
 	}
 
 	/* mark hwspinlock as used, should not fail */
-	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock->id,
+	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 
 	/* self-sanity check that should never fail */
@@ -387,7 +442,7 @@ int hwspin_lock_get_id(struct hwspinlock
 		return -EINVAL;
 	}
 
-	return hwlock->id;
+	return hwlock_to_id(hwlock);
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
 
@@ -400,9 +455,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
  * to the remote core before it can be used for synchronization (to get the
  * id of a given hwlock, use hwspin_lock_get_id()).
  *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
  *
  * Returns the address of the assigned hwspinlock, or NULL on error
  */
@@ -411,7 +464,7 @@ struct hwspinlock *hwspin_lock_request(v
 	struct hwspinlock *hwlock;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* look for an unused lock */
 	ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
@@ -431,7 +484,7 @@ struct hwspinlock *hwspin_lock_request(v
 		hwlock = NULL;
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_request);
@@ -445,9 +498,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request);
  * Usually early board code will be calling this function in order to
  * reserve specific hwspinlock ids for predefined purposes.
  *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
  *
  * Returns the address of the assigned hwspinlock, or NULL on error
  */
@@ -456,7 +507,7 @@ struct hwspinlock *hwspin_lock_request_s
 	struct hwspinlock *hwlock;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* make sure this hwspinlock exists */
 	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
@@ -466,7 +517,7 @@ struct hwspinlock *hwspin_lock_request_s
 	}
 
 	/* sanity check (this shouldn't happen) */
-	WARN_ON(hwlock->id != id);
+	WARN_ON(hwlock_to_id(hwlock) != id);
 
 	/* make sure this hwspinlock is unused */
 	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
@@ -482,7 +533,7 @@ struct hwspinlock *hwspin_lock_request_s
 		hwlock = NULL;
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
@@ -495,14 +546,13 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_sp
  * Should only be called with an @hwlock that was retrieved from
  * an earlier call to omap_hwspin_lock_request{_specific}.
  *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
  *
  * Returns 0 on success, or an appropriate error code on failure
  */
 int hwspin_lock_free(struct hwspinlock *hwlock)
 {
+	struct device *dev = hwlock->bank->dev;
 	struct hwspinlock *tmp;
 	int ret;
 
@@ -511,34 +561,34 @@ int hwspin_lock_free(struct hwspinlock *
 		return -EINVAL;
 	}
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* make sure the hwspinlock is used */
-	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id,
+	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 	if (ret == 1) {
-		dev_err(hwlock->dev, "%s: hwlock is already free\n", __func__);
+		dev_err(dev, "%s: hwlock is already free\n", __func__);
 		dump_stack();
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* notify the underlying device that power is not needed */
-	ret = pm_runtime_put(hwlock->dev);
+	ret = pm_runtime_put(dev);
 	if (ret < 0)
 		goto out;
 
 	/* mark this hwspinlock as available */
-	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 
 	/* sanity check (this shouldn't happen) */
 	WARN_ON(tmp != hwlock);
 
-	module_put(hwlock->owner);
+	module_put(dev->driver->owner);
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_free);
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/hwspinlock_internal.h linux-libre-3.2-gnu1/drivers/hwspinlock/hwspinlock_internal.h
--- linux-libre-3.1-gnu1/drivers/hwspinlock/hwspinlock_internal.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/hwspinlock_internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 
+struct hwspinlock_device;
+
 /**
  * struct hwspinlock_ops - platform-specific hwspinlock handlers
  *
@@ -39,23 +41,37 @@ struct hwspinlock_ops {
 
 /**
  * struct hwspinlock - this struct represents a single hwspinlock instance
- *
- * @dev: underlying device, will be used to invoke runtime PM api
- * @ops: platform-specific hwspinlock handlers
- * @id: a global, unique, system-wide, index of the lock.
+ * @bank: the hwspinlock_device structure which owns this lock
  * @lock: initialized and used by hwspinlock core
- * @owner: underlying implementation module, used to maintain module ref count
- *
- * Note: currently simplicity was opted for, but later we can squeeze some
- * memory bytes by grouping the dev, ops and owner members in a single
- * per-platform struct, and have all hwspinlocks point at it.
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
  */
 struct hwspinlock {
+	struct hwspinlock_device *bank;
+	spinlock_t lock;
+	void *priv;
+};
+
+/**
+ * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
+ */
+struct hwspinlock_device {
 	struct device *dev;
 	const struct hwspinlock_ops *ops;
-	int id;
-	spinlock_t lock;
-	struct module *owner;
+	int base_id;
+	int num_locks;
+	struct hwspinlock lock[0];
 };
 
+static inline int hwlock_to_id(struct hwspinlock *hwlock)
+{
+	int local_id = hwlock - &hwlock->bank->lock[0];
+
+	return hwlock->bank->base_id + local_id;
+}
+
 #endif /* __HWSPINLOCK_HWSPINLOCK_H */
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/Kconfig linux-libre-3.2-gnu1/drivers/hwspinlock/Kconfig
--- linux-libre-3.1-gnu1/drivers/hwspinlock/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -2,22 +2,31 @@
 # Generic HWSPINLOCK framework
 #
 
+# HWSPINLOCK always gets selected by whoever wants it.
 config HWSPINLOCK
-	tristate "Generic Hardware Spinlock framework"
-	depends on ARCH_OMAP4
-	help
-	  Say y here to support the generic hardware spinlock framework.
-	  You only need to enable this if you have hardware spinlock module
-	  on your system (usually only relevant if your system has remote slave
-	  coprocessors).
+	tristate
 
-	  If unsure, say N.
+menu "Hardware Spinlock drivers"
 
 config HWSPINLOCK_OMAP
 	tristate "OMAP Hardware Spinlock device"
-	depends on HWSPINLOCK && ARCH_OMAP4
+	depends on ARCH_OMAP4
+	select HWSPINLOCK
 	help
 	  Say y here to support the OMAP Hardware Spinlock device (firstly
 	  introduced in OMAP4).
 
 	  If unsure, say N.
+
+config HSEM_U8500
+	tristate "STE Hardware Semaphore functionality"
+	depends on ARCH_U8500
+	select HWSPINLOCK
+	help
+	  Say y here to support the STE Hardware Semaphore functionality, which
+	  provides a synchronisation mechanism for the various processor on the
+	  SoC.
+
+	  If unsure, say N.
+
+endmenu
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/Makefile linux-libre-3.2-gnu1/drivers/hwspinlock/Makefile
--- linux-libre-3.1-gnu1/drivers/hwspinlock/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_HWSPINLOCK)		+= hwspinlock_core.o
 obj-$(CONFIG_HWSPINLOCK_OMAP)		+= omap_hwspinlock.o
+obj-$(CONFIG_HSEM_U8500)		+= u8500_hsem.o
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/omap_hwspinlock.c linux-libre-3.2-gnu1/drivers/hwspinlock/omap_hwspinlock.c
--- linux-libre-3.1-gnu1/drivers/hwspinlock/omap_hwspinlock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/omap_hwspinlock.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,33 +41,20 @@
 #define SPINLOCK_NOTTAKEN		(0)	/* free */
 #define SPINLOCK_TAKEN			(1)	/* locked */
 
-#define to_omap_hwspinlock(lock)	\
-	container_of(lock, struct omap_hwspinlock, lock)
-
-struct omap_hwspinlock {
-	struct hwspinlock lock;
-	void __iomem *addr;
-};
-
-struct omap_hwspinlock_state {
-	int num_locks;			/* Total number of locks in system */
-	void __iomem *io_base;		/* Mapped base address */
-};
-
 static int omap_hwspinlock_trylock(struct hwspinlock *lock)
 {
-	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+	void __iomem *lock_addr = lock->priv;
 
 	/* attempt to acquire the lock by reading its value */
-	return (SPINLOCK_NOTTAKEN == readl(omap_lock->addr));
+	return (SPINLOCK_NOTTAKEN == readl(lock_addr));
 }
 
 static void omap_hwspinlock_unlock(struct hwspinlock *lock)
 {
-	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+	void __iomem *lock_addr = lock->priv;
 
 	/* release the lock by writing 0 to it */
-	writel(SPINLOCK_NOTTAKEN, omap_lock->addr);
+	writel(SPINLOCK_NOTTAKEN, lock_addr);
 }
 
 /*
@@ -93,26 +80,23 @@ static const struct hwspinlock_ops omap_
 
 static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
 {
-	struct omap_hwspinlock *omap_lock;
-	struct omap_hwspinlock_state *state;
-	struct hwspinlock *lock;
+	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+	struct hwspinlock_device *bank;
+	struct hwspinlock *hwlock;
 	struct resource *res;
 	void __iomem *io_base;
-	int i, ret;
+	int num_locks, i, ret;
+
+	if (!pdata)
+		return -ENODEV;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
 
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return -ENOMEM;
-
 	io_base = ioremap(res->start, resource_size(res));
-	if (!io_base) {
-		ret = -ENOMEM;
-		goto free_state;
-	}
+	if (!io_base)
+		return -ENOMEM;
 
 	/* Determine number of locks */
 	i = readl(io_base + SYSSTATUS_OFFSET);
@@ -124,10 +108,18 @@ static int __devinit omap_hwspinlock_pro
 		goto iounmap_base;
 	}
 
-	state->num_locks = i * 32;
-	state->io_base = io_base;
+	num_locks = i * 32; /* actual number of locks in this device */
 
-	platform_set_drvdata(pdev, state);
+	bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+	if (!bank) {
+		ret = -ENOMEM;
+		goto iounmap_base;
+	}
+
+	platform_set_drvdata(pdev, bank);
+
+	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+		hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
 
 	/*
 	 * runtime PM will make sure the clock of this module is
@@ -135,79 +127,46 @@ static int __devinit omap_hwspinlock_pro
 	 */
 	pm_runtime_enable(&pdev->dev);
 
-	for (i = 0; i < state->num_locks; i++) {
-		omap_lock = kzalloc(sizeof(*omap_lock), GFP_KERNEL);
-		if (!omap_lock) {
-			ret = -ENOMEM;
-			goto free_locks;
-		}
-
-		omap_lock->lock.dev = &pdev->dev;
-		omap_lock->lock.owner = THIS_MODULE;
-		omap_lock->lock.id = i;
-		omap_lock->lock.ops = &omap_hwspinlock_ops;
-		omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
-
-		ret = hwspin_lock_register(&omap_lock->lock);
-		if (ret) {
-			kfree(omap_lock);
-			goto free_locks;
-		}
-	}
+	ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
+						pdata->base_id, num_locks);
+	if (ret)
+		goto reg_fail;
 
 	return 0;
 
-free_locks:
-	while (--i >= 0) {
-		lock = hwspin_lock_unregister(i);
-		/* this should't happen, but let's give our best effort */
-		if (!lock) {
-			dev_err(&pdev->dev, "%s: cleanups failed\n", __func__);
-			continue;
-		}
-		omap_lock = to_omap_hwspinlock(lock);
-		kfree(omap_lock);
-	}
+reg_fail:
 	pm_runtime_disable(&pdev->dev);
+	kfree(bank);
 iounmap_base:
 	iounmap(io_base);
-free_state:
-	kfree(state);
 	return ret;
 }
 
-static int omap_hwspinlock_remove(struct platform_device *pdev)
+static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
 {
-	struct omap_hwspinlock_state *state = platform_get_drvdata(pdev);
-	struct hwspinlock *lock;
-	struct omap_hwspinlock *omap_lock;
-	int i;
-
-	for (i = 0; i < state->num_locks; i++) {
-		lock = hwspin_lock_unregister(i);
-		/* this shouldn't happen at this point. if it does, at least
-		 * don't continue with the remove */
-		if (!lock) {
-			dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i);
-			return -EBUSY;
-		}
+	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+	void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
+	int ret;
 
-		omap_lock = to_omap_hwspinlock(lock);
-		kfree(omap_lock);
+	ret = hwspin_lock_unregister(bank);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+		return ret;
 	}
 
 	pm_runtime_disable(&pdev->dev);
-	iounmap(state->io_base);
-	kfree(state);
+	iounmap(io_base);
+	kfree(bank);
 
 	return 0;
 }
 
 static struct platform_driver omap_hwspinlock_driver = {
 	.probe		= omap_hwspinlock_probe,
-	.remove		= omap_hwspinlock_remove,
+	.remove		= __devexit_p(omap_hwspinlock_remove),
 	.driver		= {
 		.name	= "omap_hwspinlock",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/hwspinlock/u8500_hsem.c linux-libre-3.2-gnu1/drivers/hwspinlock/u8500_hsem.c
--- linux-libre-3.1-gnu1/drivers/hwspinlock/u8500_hsem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/hwspinlock/u8500_hsem.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,197 @@
+/*
+ * u8500 HWSEM driver
+ *
+ * Copyright (C) 2010-2011 ST-Ericsson
+ *
+ * Implements u8500 semaphore handling for protocol 1, no interrupts.
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ * Heavily borrowed from the work of :
+ *   Simon Que <sque@ti.com>
+ *   Hari Kanigeri <h-kanigeri2@ti.com>
+ *   Ohad Ben-Cohen <ohad@wizery.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 published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+#include <linux/platform_device.h>
+
+#include "hwspinlock_internal.h"
+
+/*
+ * Implementation of STE's HSem protocol 1 without interrutps.
+ * The only masterID we allow is '0x01' to force people to use
+ * HSems for synchronisation between processors rather than processes
+ * on the ARM core.
+ */
+
+#define U8500_MAX_SEMAPHORE		32	/* a total of 32 semaphore */
+#define RESET_SEMAPHORE			(0)	/* free */
+
+/*
+ * CPU ID for master running u8500 kernel.
+ * Hswpinlocks should only be used to synchonise operations
+ * between the Cortex A9 core and the other CPUs.  Hence
+ * forcing the masterID to a preset value.
+ */
+#define HSEM_MASTER_ID			0x01
+
+#define HSEM_REGISTER_OFFSET		0x08
+
+#define HSEM_CTRL_REG			0x00
+#define HSEM_ICRALL			0x90
+#define HSEM_PROTOCOL_1			0x01
+
+static int u8500_hsem_trylock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	writel(HSEM_MASTER_ID, lock_addr);
+
+	/* get only first 4 bit and compare to masterID.
+	 * if equal, we have the semaphore, otherwise
+	 * someone else has it.
+	 */
+	return (HSEM_MASTER_ID == (0x0F & readl(lock_addr)));
+}
+
+static void u8500_hsem_unlock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	/* release the lock by writing 0 to it */
+	writel(RESET_SEMAPHORE, lock_addr);
+}
+
+/*
+ * u8500: what value is recommended here ?
+ */
+static void u8500_hsem_relax(struct hwspinlock *lock)
+{
+	ndelay(50);
+}
+
+static const struct hwspinlock_ops u8500_hwspinlock_ops = {
+	.trylock	= u8500_hsem_trylock,
+	.unlock		= u8500_hsem_unlock,
+	.relax		= u8500_hsem_relax,
+};
+
+static int __devinit u8500_hsem_probe(struct platform_device *pdev)
+{
+	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+	struct hwspinlock_device *bank;
+	struct hwspinlock *hwlock;
+	struct resource *res;
+	void __iomem *io_base;
+	int i, ret, num_locks = U8500_MAX_SEMAPHORE;
+	ulong val;
+
+	if (!pdata)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	io_base = ioremap(res->start, resource_size(res));
+	if (!io_base)
+		return -ENOMEM;
+
+	/* make sure protocol 1 is selected */
+	val = readl(io_base + HSEM_CTRL_REG);
+	writel((val & ~HSEM_PROTOCOL_1), io_base + HSEM_CTRL_REG);
+
+	/* clear all interrupts */
+	writel(0xFFFF, io_base + HSEM_ICRALL);
+
+	bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+	if (!bank) {
+		ret = -ENOMEM;
+		goto iounmap_base;
+	}
+
+	platform_set_drvdata(pdev, bank);
+
+	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+		hwlock->priv = io_base + HSEM_REGISTER_OFFSET + sizeof(u32) * i;
+
+	/* no pm needed for HSem but required to comply with hwspilock core */
+	pm_runtime_enable(&pdev->dev);
+
+	ret = hwspin_lock_register(bank, &pdev->dev, &u8500_hwspinlock_ops,
+						pdata->base_id, num_locks);
+	if (ret)
+		goto reg_fail;
+
+	return 0;
+
+reg_fail:
+	pm_runtime_disable(&pdev->dev);
+	kfree(bank);
+iounmap_base:
+	iounmap(io_base);
+	return ret;
+}
+
+static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+{
+	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+	void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
+	int ret;
+
+	/* clear all interrupts */
+	writel(0xFFFF, io_base + HSEM_ICRALL);
+
+	ret = hwspin_lock_unregister(bank);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	iounmap(io_base);
+	kfree(bank);
+
+	return 0;
+}
+
+static struct platform_driver u8500_hsem_driver = {
+	.probe		= u8500_hsem_probe,
+	.remove		= __devexit_p(u8500_hsem_remove),
+	.driver		= {
+		.name	= "u8500_hsem",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init u8500_hsem_init(void)
+{
+	return platform_driver_register(&u8500_hsem_driver);
+}
+/* board init code might need to reserve hwspinlocks for predefined purposes */
+postcore_initcall(u8500_hsem_init);
+
+static void __exit u8500_hsem_exit(void)
+{
+	platform_driver_unregister(&u8500_hsem_driver);
+}
+module_exit(u8500_hsem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware Spinlock driver for u8500");
+MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/algos/i2c-algo-bit.c linux-libre-3.2-gnu1/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-3.1-gnu1/drivers/i2c/algos/i2c-algo-bit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/algos/i2c-algo-bit.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,8 +47,8 @@
 /* ----- global variables ---------------------------------------------	*/
 
 static int bit_test;	/* see if the line-setting functions work	*/
-module_param(bit_test, bool, 0);
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+module_param(bit_test, int, S_IRUGO);
+MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck");
 
 #ifdef DEBUG
 static int i2c_debug = 1;
@@ -250,7 +250,9 @@ static int test_bus(struct i2c_adapter *
 	sda = getsda(adap);
 	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
 	if (!scl || !sda) {
-		printk(KERN_WARNING "%s: bus seems to be busy\n", name);
+		printk(KERN_WARNING
+		       "%s: bus seems to be busy (scl=%d, sda=%d)\n",
+		       name, scl, sda);
 		goto bailout;
 	}
 
@@ -441,7 +443,7 @@ static int readbytes(struct i2c_adapter
 					acknak(i2c_adap, 0);
 				dev_err(&i2c_adap->dev, "readbytes: invalid "
 					"block length (%d)\n", inval);
-				return -EREMOTEIO;
+				return -EPROTO;
 			}
 			/* The original count value accounts for the extra
 			   bytes, that is, either 1 for a regular transaction,
@@ -470,7 +472,7 @@ static int readbytes(struct i2c_adapter
  * reads, writes as well as 10bit-addresses.
  * returns:
  *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
- * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
+ * -x an error occurred (like: -ENXIO if the device did not answer, or
  *	-ETIMEDOUT, for example if the lines are stuck...)
  */
 static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
@@ -486,21 +488,21 @@ static int bit_doAddress(struct i2c_adap
 
 	if (flags & I2C_M_TEN) {
 		/* a ten bit address */
-		addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+		addr = 0xf0 | ((msg->addr >> 7) & 0x06);
 		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
 		/* try extended address code...*/
 		ret = try_address(i2c_adap, addr, retries);
 		if ((ret != 1) && !nak_ok)  {
 			dev_err(&i2c_adap->dev,
 				"died at extended address code\n");
-			return -EREMOTEIO;
+			return -ENXIO;
 		}
 		/* the remaining 8 bit address */
-		ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
+		ret = i2c_outb(i2c_adap, msg->addr & 0xff);
 		if ((ret != 1) && !nak_ok) {
 			/* the chip did not ack / xmission error occurred */
 			dev_err(&i2c_adap->dev, "died at 2nd address code\n");
-			return -EREMOTEIO;
+			return -ENXIO;
 		}
 		if (flags & I2C_M_RD) {
 			bit_dbg(3, &i2c_adap->dev, "emitting repeated "
@@ -512,7 +514,7 @@ static int bit_doAddress(struct i2c_adap
 			if ((ret != 1) && !nak_ok) {
 				dev_err(&i2c_adap->dev,
 					"died at repeated address code\n");
-				return -EREMOTEIO;
+				return -EIO;
 			}
 		}
 	} else {		/* normal 7bit address	*/
@@ -570,7 +572,7 @@ static int bit_xfer(struct i2c_adapter *
 					ret, ret == 1 ? "" : "s");
 			if (ret < pmsg->len) {
 				if (ret >= 0)
-					ret = -EREMOTEIO;
+					ret = -EIO;
 				goto bailout;
 			}
 		} else {
@@ -581,7 +583,7 @@ static int bit_xfer(struct i2c_adapter *
 					ret, ret == 1 ? "" : "s");
 			if (ret < pmsg->len) {
 				if (ret >= 0)
-					ret = -EREMOTEIO;
+					ret = -EIO;
 				goto bailout;
 			}
 		}
@@ -624,7 +626,7 @@ static int __i2c_bit_add_bus(struct i2c_
 
 	if (bit_test) {
 		ret = test_bus(adap);
-		if (ret < 0)
+		if (bit_test >= 2 && ret < 0)
 			return -ENODEV;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/algos/i2c-algo-pca.c linux-libre-3.2-gnu1/drivers/i2c/algos/i2c-algo-pca.c
--- linux-libre-3.1-gnu1/drivers/i2c/algos/i2c-algo-pca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/algos/i2c-algo-pca.c	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@ static int pca_xfer(struct i2c_adapter *
 		} else {
 			dev_dbg(&i2c_adap->dev, "bus is not idle. status is "
 				"%#04x\n", state);
-			return -EAGAIN;
+			return -EBUSY;
 		}
 	}
 
@@ -224,7 +224,7 @@ static int pca_xfer(struct i2c_adapter *
 	}
 
 	curmsg = 0;
-	ret = -EREMOTEIO;
+	ret = -EIO;
 	while (curmsg < num) {
 		state = pca_status(adap);
 
@@ -259,6 +259,7 @@ static int pca_xfer(struct i2c_adapter *
 		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+W\n");
 			pca_stop(adap);
+			ret = -ENXIO;
 			goto out;
 
 		case 0x40: /* SLA+R has been transmitted; ACK has been received */
@@ -283,6 +284,7 @@ static int pca_xfer(struct i2c_adapter *
 		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+R\n");
 			pca_stop(adap);
+			ret = -ENXIO;
 			goto out;
 
 		case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-au1550.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-au1550.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-au1550.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-au1550.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,32 +36,44 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
+#define PSC_SEL		0x00
+#define PSC_CTRL	0x04
+#define PSC_SMBCFG	0x08
+#define PSC_SMBMSK	0x0C
+#define PSC_SMBPCR	0x10
+#define PSC_SMBSTAT	0x14
+#define PSC_SMBEVNT	0x18
+#define PSC_SMBTXRX	0x1C
+#define PSC_SMBTMR	0x20
+
 struct i2c_au1550_data {
-	u32	psc_base;
+	void __iomem *psc_base;
 	int	xfer_timeout;
-	int	ack_timeout;
 	struct i2c_adapter adap;
 	struct resource *ioarea;
 };
 
-static int
-wait_xfer_done(struct i2c_au1550_data *adap)
+static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
+	__raw_writel(v, a->psc_base + r);
+	wmb();
+}
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+static inline unsigned long RD(struct i2c_au1550_data *a, int r)
+{
+	return __raw_readl(a->psc_base + r);
+}
 
-	/* Wait for Tx Buffer Empty
-	*/
+static int wait_xfer_done(struct i2c_au1550_data *adap)
+{
+	int i;
+
+	/* Wait for Tx Buffer Empty */
 	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_TE) != 0)
+		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
 			return 0;
 
 		udelay(1);
@@ -70,41 +82,27 @@ wait_xfer_done(struct i2c_au1550_data *a
 	return -ETIMEDOUT;
 }
 
-static int
-wait_ack(struct i2c_au1550_data *adap)
+static int wait_ack(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	volatile psc_smb_t	*sp;
+	unsigned long stat;
 
 	if (wait_xfer_done(adap))
 		return -ETIMEDOUT;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
-	stat = sp->psc_smbevnt;
-	au_sync();
-
+	stat = RD(adap, PSC_SMBEVNT);
 	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
 		return -ETIMEDOUT;
 
 	return 0;
 }
 
-static int
-wait_master_done(struct i2c_au1550_data *adap)
+static int wait_master_done(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+	int i;
 
-	/* Wait for Master Done.
-	*/
-	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbevnt;
-		au_sync();
-		if ((stat & PSC_SMBEVNT_MD) != 0)
+	/* Wait for Master Done. */
+	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
+		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
 			return 0;
 		udelay(1);
 	}
@@ -115,29 +113,20 @@ wait_master_done(struct i2c_au1550_data
 static int
 do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
 {
-	volatile psc_smb_t	*sp;
-	u32			stat;
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+	unsigned long stat;
 
-	/* Reset the FIFOs, clear events.
-	*/
-	stat = sp->psc_smbstat;
-	sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
-	au_sync();
+	/* Reset the FIFOs, clear events. */
+	stat = RD(adap, PSC_SMBSTAT);
+	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
 
 	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
-		sp->psc_smbpcr = PSC_SMBPCR_DC;
-		au_sync();
-		do {
-			stat = sp->psc_smbpcr;
-			au_sync();
-		} while ((stat & PSC_SMBPCR_DC) != 0);
+		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
+		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
+			cpu_relax();
 		udelay(50);
 	}
 
-	/* Write out the i2c chip address and specify operation
-	*/
+	/* Write out the i2c chip address and specify operation */
 	addr <<= 1;
 	if (rd)
 		addr |= 1;
@@ -146,56 +135,42 @@ do_address(struct i2c_au1550_data *adap,
 	if (q)
 		addr |= PSC_SMBTXRX_STP;
 
-	/* Put byte into fifo, start up master.
-	*/
-	sp->psc_smbtxrx = addr;
-	au_sync();
-	sp->psc_smbpcr = PSC_SMBPCR_MS;
-	au_sync();
+	/* Put byte into fifo, start up master. */
+	WR(adap, PSC_SMBTXRX, addr);
+	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
 	if (wait_ack(adap))
 		return -EIO;
 	return (q) ? wait_master_done(adap) : 0;
 }
 
-static u32
-wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data)
+static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
 {
-	int	j;
-	u32	data, stat;
-	volatile psc_smb_t	*sp;
+	int j;
 
 	if (wait_xfer_done(adap))
 		return -EIO;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	j =  adap->xfer_timeout * 100;
 	do {
 		j--;
 		if (j <= 0)
 			return -EIO;
 
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_RE) == 0)
+		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
 			j = 0;
 		else
 			udelay(1);
 	} while (j > 0);
-	data = sp->psc_smbtxrx;
-	au_sync();
-	*ret_data = data;
+
+	*out = RD(adap, PSC_SMBTXRX);
 
 	return 0;
 }
 
-static int
-i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
 		    unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
 
 	if (len == 0)
 		return 0;
@@ -204,62 +179,46 @@ i2c_read(struct i2c_au1550_data *adap, u
 	 * zero bytes for timing, waiting for bytes to appear in the
 	 * receive fifo, then reading the bytes.
 	 */
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
-	while (i < (len-1)) {
-		sp->psc_smbtxrx = 0;
-		au_sync();
-		if (wait_for_rx_byte(adap, &data))
+	while (i < (len - 1)) {
+		WR(adap, PSC_SMBTXRX, 0);
+		if (wait_for_rx_byte(adap, &buf[i]))
 			return -EIO;
 
-		buf[i] = data;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
-	sp->psc_smbtxrx = PSC_SMBTXRX_STP;
-	au_sync();
+	/* The last byte has to indicate transfer done. */
+	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
 	if (wait_master_done(adap))
 		return -EIO;
 
-	data = sp->psc_smbtxrx;
-	au_sync();
-	buf[i] = data;
+	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
 	return 0;
 }
 
-static int
-i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
 		     unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
+	unsigned long data;
 
 	if (len == 0)
 		return 0;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
 	while (i < (len-1)) {
 		data = buf[i];
-		sp->psc_smbtxrx = data;
-		au_sync();
+		WR(adap, PSC_SMBTXRX, data);
 		if (wait_ack(adap))
 			return -EIO;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
+	/* The last byte has to indicate transfer done. */
 	data = buf[i];
 	data |= PSC_SMBTXRX_STP;
-	sp->psc_smbtxrx = data;
-	au_sync();
+	WR(adap, PSC_SMBTXRX, data);
 	if (wait_master_done(adap))
 		return -EIO;
 	return 0;
@@ -269,12 +228,10 @@ static int
 au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
 	struct i2c_au1550_data *adap = i2c_adap->algo_data;
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
 	struct i2c_msg *p;
 	int i, err = 0;
 
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
 
 	for (i = 0; !err && i < num; i++) {
 		p = &msgs[i];
@@ -293,14 +250,12 @@ au1550_xfer(struct i2c_adapter *i2c_adap
 	if (err == 0)
 		err = num;
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
 
 	return err;
 }
 
-static u32
-au1550_func(struct i2c_adapter *adap)
+static u32 au1550_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
@@ -312,57 +267,45 @@ static const struct i2c_algorithm au1550
 
 static void i2c_au1550_setup(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-	u32 stat;
+	unsigned long cfg;
 
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
-	sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-	sp->psc_smbcfg = 0;
-	au_sync();
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
+	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
 
-	sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
-				PSC_SMBCFG_DD_DISABLE);
+	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
+	WR(priv, PSC_SMBCFG, cfg);
 
 	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
 	 * timings are based on this clock.
 	 */
-	sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
-	sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
-	au_sync();
+	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+	WR(priv, PSC_SMBCFG, cfg);
+	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
 
 	/* Set the protocol timer values.  See Table 71 in the
 	 * Au1550 Data Book for standard timing values.
 	 */
-	sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
 		PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
 		PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
-		PSC_SMBTMR_SET_CH(15);
-	au_sync();
+		PSC_SMBTMR_SET_CH(15));
 
-	sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	cfg |= PSC_SMBCFG_DE_ENABLE;
+	WR(priv, PSC_SMBCFG, cfg);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
 }
 
 static void i2c_au1550_disable(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-
-	sp->psc_smbcfg = 0;
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
 }
 
 /*
@@ -396,9 +339,12 @@ i2c_au1550_probe(struct platform_device
 		goto out_mem;
 	}
 
-	priv->psc_base = CKSEG1ADDR(r->start);
+	priv->psc_base = ioremap(r->start, resource_size(r));
+	if (!priv->psc_base) {
+		ret = -EIO;
+		goto out_map;
+	}
 	priv->xfer_timeout = 200;
-	priv->ack_timeout = 200;
 
 	priv->adap.nr = pdev->id;
 	priv->adap.algo = &au1550_algo;
@@ -406,8 +352,7 @@ i2c_au1550_probe(struct platform_device
 	priv->adap.dev.parent = &pdev->dev;
 	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
 
-	/* Now, set up the PSC for SMBus PIO mode.
-	*/
+	/* Now, set up the PSC for SMBus PIO mode. */
 	i2c_au1550_setup(priv);
 
 	ret = i2c_add_numbered_adapter(&priv->adap);
@@ -417,7 +362,8 @@ i2c_au1550_probe(struct platform_device
 	}
 
 	i2c_au1550_disable(priv);
-
+	iounmap(priv->psc_base);
+out_map:
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 out_mem:
@@ -426,14 +372,14 @@ out:
 	return ret;
 }
 
-static int __devexit
-i2c_au1550_remove(struct platform_device *pdev)
+static int __devexit i2c_au1550_remove(struct platform_device *pdev)
 {
 	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
 
 	platform_set_drvdata(pdev, NULL);
 	i2c_del_adapter(&priv->adap);
 	i2c_au1550_disable(priv);
+	iounmap(priv->psc_base);
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 	kfree(priv);
@@ -441,49 +387,51 @@ i2c_au1550_remove(struct platform_device
 }
 
 #ifdef CONFIG_PM
-static int
-i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+static int i2c_au1550_suspend(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_disable(priv);
 
 	return 0;
 }
 
-static int
-i2c_au1550_resume(struct platform_device *pdev)
+static int i2c_au1550_resume(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_setup(priv);
 
 	return 0;
 }
+
+static const struct dev_pm_ops i2c_au1550_pmops = {
+	.suspend	= i2c_au1550_suspend,
+	.resume		= i2c_au1550_resume,
+};
+
+#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
+
 #else
-#define i2c_au1550_suspend	NULL
-#define i2c_au1550_resume	NULL
+#define AU1XPSC_SMBUS_PMOPS NULL
 #endif
 
 static struct platform_driver au1xpsc_smbus_driver = {
 	.driver = {
 		.name	= "au1xpsc_smbus",
 		.owner	= THIS_MODULE,
+		.pm	= AU1XPSC_SMBUS_PMOPS,
 	},
 	.probe		= i2c_au1550_probe,
 	.remove		= __devexit_p(i2c_au1550_remove),
-	.suspend	= i2c_au1550_suspend,
-	.resume		= i2c_au1550_resume,
 };
 
-static int __init
-i2c_au1550_init(void)
+static int __init i2c_au1550_init(void)
 {
 	return platform_driver_register(&au1xpsc_smbus_driver);
 }
 
-static void __exit
-i2c_au1550_exit(void)
+static void __exit i2c_au1550_exit(void)
 {
 	platform_driver_unregister(&au1xpsc_smbus_driver);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-bfin-twi.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-bfin-twi.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-bfin-twi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-bfin-twi.c	2012-01-04 18:55:44.000000000 -0500
@@ -631,7 +631,7 @@ static int i2c_bfin_twi_resume(struct pl
 	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
 
 	int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		return -ENODEV;
@@ -702,7 +702,7 @@ static int i2c_bfin_twi_probe(struct pla
 	}
 
 	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		rc = -ENODEV;
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,847 +0,0 @@
-/*
- * Synopsys DesignWare I2C adapter driver (master only).
- *
- * Based on the TI DAVINCI I2C adapter driver.
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software Inc.
- * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ----------------------------------------------------------------------------
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-/*
- * Registers offset
- */
-#define DW_IC_CON		0x0
-#define DW_IC_TAR		0x4
-#define DW_IC_DATA_CMD		0x10
-#define DW_IC_SS_SCL_HCNT	0x14
-#define DW_IC_SS_SCL_LCNT	0x18
-#define DW_IC_FS_SCL_HCNT	0x1c
-#define DW_IC_FS_SCL_LCNT	0x20
-#define DW_IC_INTR_STAT		0x2c
-#define DW_IC_INTR_MASK		0x30
-#define DW_IC_RAW_INTR_STAT	0x34
-#define DW_IC_RX_TL		0x38
-#define DW_IC_TX_TL		0x3c
-#define DW_IC_CLR_INTR		0x40
-#define DW_IC_CLR_RX_UNDER	0x44
-#define DW_IC_CLR_RX_OVER	0x48
-#define DW_IC_CLR_TX_OVER	0x4c
-#define DW_IC_CLR_RD_REQ	0x50
-#define DW_IC_CLR_TX_ABRT	0x54
-#define DW_IC_CLR_RX_DONE	0x58
-#define DW_IC_CLR_ACTIVITY	0x5c
-#define DW_IC_CLR_STOP_DET	0x60
-#define DW_IC_CLR_START_DET	0x64
-#define DW_IC_CLR_GEN_CALL	0x68
-#define DW_IC_ENABLE		0x6c
-#define DW_IC_STATUS		0x70
-#define DW_IC_TXFLR		0x74
-#define DW_IC_RXFLR		0x78
-#define DW_IC_COMP_PARAM_1	0xf4
-#define DW_IC_TX_ABRT_SOURCE	0x80
-
-#define DW_IC_CON_MASTER		0x1
-#define DW_IC_CON_SPEED_STD		0x2
-#define DW_IC_CON_SPEED_FAST		0x4
-#define DW_IC_CON_10BITADDR_MASTER	0x10
-#define DW_IC_CON_RESTART_EN		0x20
-#define DW_IC_CON_SLAVE_DISABLE		0x40
-
-#define DW_IC_INTR_RX_UNDER	0x001
-#define DW_IC_INTR_RX_OVER	0x002
-#define DW_IC_INTR_RX_FULL	0x004
-#define DW_IC_INTR_TX_OVER	0x008
-#define DW_IC_INTR_TX_EMPTY	0x010
-#define DW_IC_INTR_RD_REQ	0x020
-#define DW_IC_INTR_TX_ABRT	0x040
-#define DW_IC_INTR_RX_DONE	0x080
-#define DW_IC_INTR_ACTIVITY	0x100
-#define DW_IC_INTR_STOP_DET	0x200
-#define DW_IC_INTR_START_DET	0x400
-#define DW_IC_INTR_GEN_CALL	0x800
-
-#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
-					 DW_IC_INTR_TX_EMPTY | \
-					 DW_IC_INTR_TX_ABRT | \
-					 DW_IC_INTR_STOP_DET)
-
-#define DW_IC_STATUS_ACTIVITY	0x1
-
-#define DW_IC_ERR_TX_ABRT	0x1
-
-/*
- * status codes
- */
-#define STATUS_IDLE			0x0
-#define STATUS_WRITE_IN_PROGRESS	0x1
-#define STATUS_READ_IN_PROGRESS		0x2
-
-#define TIMEOUT			20 /* ms */
-
-/*
- * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
- *
- * only expected abort codes are listed here
- * refer to the datasheet for the full list
- */
-#define ABRT_7B_ADDR_NOACK	0
-#define ABRT_10ADDR1_NOACK	1
-#define ABRT_10ADDR2_NOACK	2
-#define ABRT_TXDATA_NOACK	3
-#define ABRT_GCALL_NOACK	4
-#define ABRT_GCALL_READ		5
-#define ABRT_SBYTE_ACKDET	7
-#define ABRT_SBYTE_NORSTRT	9
-#define ABRT_10B_RD_NORSTRT	10
-#define ABRT_MASTER_DIS		11
-#define ARB_LOST		12
-
-#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
-#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
-#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
-#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
-#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
-#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
-#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
-#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
-#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
-#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
-#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
-
-#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
-					 DW_IC_TX_ABRT_TXDATA_NOACK | \
-					 DW_IC_TX_ABRT_GCALL_NOACK)
-
-static char *abort_sources[] = {
-	[ABRT_7B_ADDR_NOACK] =
-		"slave address not acknowledged (7bit mode)",
-	[ABRT_10ADDR1_NOACK] =
-		"first address byte not acknowledged (10bit mode)",
-	[ABRT_10ADDR2_NOACK] =
-		"second address byte not acknowledged (10bit mode)",
-	[ABRT_TXDATA_NOACK] =
-		"data not acknowledged",
-	[ABRT_GCALL_NOACK] =
-		"no acknowledgement for a general call",
-	[ABRT_GCALL_READ] =
-		"read after general call",
-	[ABRT_SBYTE_ACKDET] =
-		"start byte acknowledged",
-	[ABRT_SBYTE_NORSTRT] =
-		"trying to send start byte when restart is disabled",
-	[ABRT_10B_RD_NORSTRT] =
-		"trying to read when restart is disabled (10bit mode)",
-	[ABRT_MASTER_DIS] =
-		"trying to use disabled adapter",
-	[ARB_LOST] =
-		"lost arbitration",
-};
-
-/**
- * struct dw_i2c_dev - private i2c-designware data
- * @dev: driver model device node
- * @base: IO registers pointer
- * @cmd_complete: tx completion indicator
- * @lock: protect this struct and IO registers
- * @clk: input reference clock
- * @cmd_err: run time hadware error code
- * @msgs: points to an array of messages currently being transferred
- * @msgs_num: the number of elements in msgs
- * @msg_write_idx: the element index of the current tx message in the msgs
- *	array
- * @tx_buf_len: the length of the current tx buffer
- * @tx_buf: the current tx buffer
- * @msg_read_idx: the element index of the current rx message in the msgs
- *	array
- * @rx_buf_len: the length of the current rx buffer
- * @rx_buf: the current rx buffer
- * @msg_err: error status of the current transfer
- * @status: i2c master status, one of STATUS_*
- * @abort_source: copy of the TX_ABRT_SOURCE register
- * @irq: interrupt number for the i2c master
- * @adapter: i2c subsystem adapter node
- * @tx_fifo_depth: depth of the hardware tx fifo
- * @rx_fifo_depth: depth of the hardware rx fifo
- */
-struct dw_i2c_dev {
-	struct device		*dev;
-	void __iomem		*base;
-	struct completion	cmd_complete;
-	struct mutex		lock;
-	struct clk		*clk;
-	int			cmd_err;
-	struct i2c_msg		*msgs;
-	int			msgs_num;
-	int			msg_write_idx;
-	u32			tx_buf_len;
-	u8			*tx_buf;
-	int			msg_read_idx;
-	u32			rx_buf_len;
-	u8			*rx_buf;
-	int			msg_err;
-	unsigned int		status;
-	u32			abort_source;
-	int			irq;
-	struct i2c_adapter	adapter;
-	unsigned int		tx_fifo_depth;
-	unsigned int		rx_fifo_depth;
-};
-
-static u32
-i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
-{
-	/*
-	 * DesignWare I2C core doesn't seem to have solid strategy to meet
-	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
-	 * will result in violation of the tHD;STA spec.
-	 */
-	if (cond)
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
-		 *
-		 * This is based on the DW manuals, and represents an ideal
-		 * configuration.  The resulting I2C bus speed will be
-		 * faster than any of the others.
-		 *
-		 * If your hardware is free from tHD;STA issue, try this one.
-		 */
-		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
-	else
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
-		 *
-		 * This is just experimental rule; the tHD;STA period turned
-		 * out to be proportinal to (_HCNT + 3).  With this setting,
-		 * we could meet both tHIGH and tHD;STA timing specs.
-		 *
-		 * If unsure, you'd better to take this alternative.
-		 *
-		 * The reason why we need to take into account "tf" here,
-		 * is the same as described in i2c_dw_scl_lcnt().
-		 */
-		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
-}
-
-static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
-{
-	/*
-	 * Conditional expression:
-	 *
-	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
-	 *
-	 * DW I2C core starts counting the SCL CNTs for the LOW period
-	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
-	 * In order to meet the tLOW timing spec, we need to take into
-	 * account the fall time of SCL signal (tf).  Default tf value
-	 * should be 0.3 us, for safety.
-	 */
-	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
-}
-
-/**
- * i2c_dw_init() - initialize the designware i2c master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- */
-static void i2c_dw_init(struct dw_i2c_dev *dev)
-{
-	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
-	u32 ic_con, hcnt, lcnt;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set standard and fast speed deviders for high/low periods */
-
-	/* Standard-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				40,	/* tHD;STA = tHIGH = 4.0 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				47,	/* tLOW = 4.7 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
-	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Fast-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				6,	/* tHD;STA = tHIGH = 0.6 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				13,	/* tLOW = 1.3 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
-	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Configure Tx/Rx FIFO threshold levels */
-	writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
-	writel(0, dev->base + DW_IC_RX_TL);
-
-	/* configure the i2c master */
-	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
-	writel(ic_con, dev->base + DW_IC_CON);
-}
-
-/*
- * Waiting for bus not busy
- */
-static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
-{
-	int timeout = TIMEOUT;
-
-	while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
-		if (timeout <= 0) {
-			dev_warn(dev->dev, "timeout waiting for bus ready\n");
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 ic_con;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set the slave (target) address */
-	writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
-
-	/* if the slave address is ten bit address, enable 10BITADDR */
-	ic_con = readl(dev->base + DW_IC_CON);
-	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
-		ic_con |= DW_IC_CON_10BITADDR_MASTER;
-	else
-		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-	writel(ic_con, dev->base + DW_IC_CON);
-
-	/* Enable the adapter */
-	writel(1, dev->base + DW_IC_ENABLE);
-
-	/* Enable interrupts */
-	writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
-}
-
-/*
- * Initiate (and continue) low level master read/write transaction.
- * This function is only called from i2c_dw_isr, and pumping i2c_msg
- * messages into the tx buffer.  Even if the size of i2c_msg data is
- * longer than the size of the tx buffer, it handles everything.
- */
-static void
-i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 intr_mask;
-	int tx_limit, rx_limit;
-	u32 addr = msgs[dev->msg_write_idx].addr;
-	u32 buf_len = dev->tx_buf_len;
-	u8 *buf = dev->tx_buf;;
-
-	intr_mask = DW_IC_INTR_DEFAULT_MASK;
-
-	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
-		/*
-		 * if target address has changed, we need to
-		 * reprogram the target address in the i2c
-		 * adapter when we are done with this transfer
-		 */
-		if (msgs[dev->msg_write_idx].addr != addr) {
-			dev_err(dev->dev,
-				"%s: invalid target address\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (msgs[dev->msg_write_idx].len == 0) {
-			dev_err(dev->dev,
-				"%s: invalid message length\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
-			/* new i2c_msg */
-			buf = msgs[dev->msg_write_idx].buf;
-			buf_len = msgs[dev->msg_write_idx].len;
-		}
-
-		tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
-		rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
-
-		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
-			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
-				writel(0x100, dev->base + DW_IC_DATA_CMD);
-				rx_limit--;
-			} else
-				writel(*buf++, dev->base + DW_IC_DATA_CMD);
-			tx_limit--; buf_len--;
-		}
-
-		dev->tx_buf = buf;
-		dev->tx_buf_len = buf_len;
-
-		if (buf_len > 0) {
-			/* more bytes to be written */
-			dev->status |= STATUS_WRITE_IN_PROGRESS;
-			break;
-		} else
-			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
-	}
-
-	/*
-	 * If i2c_msg index search is completed, we don't need TX_EMPTY
-	 * interrupt any more.
-	 */
-	if (dev->msg_write_idx == dev->msgs_num)
-		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
-
-	if (dev->msg_err)
-		intr_mask = 0;
-
-	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
-}
-
-static void
-i2c_dw_read(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	int rx_valid;
-
-	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
-		u32 len;
-		u8 *buf;
-
-		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
-			continue;
-
-		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
-			len = msgs[dev->msg_read_idx].len;
-			buf = msgs[dev->msg_read_idx].buf;
-		} else {
-			len = dev->rx_buf_len;
-			buf = dev->rx_buf;
-		}
-
-		rx_valid = readl(dev->base + DW_IC_RXFLR);
-
-		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
-			*buf++ = readl(dev->base + DW_IC_DATA_CMD);
-
-		if (len > 0) {
-			dev->status |= STATUS_READ_IN_PROGRESS;
-			dev->rx_buf_len = len;
-			dev->rx_buf = buf;
-			return;
-		} else
-			dev->status &= ~STATUS_READ_IN_PROGRESS;
-	}
-}
-
-static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
-{
-	unsigned long abort_source = dev->abort_source;
-	int i;
-
-	if (abort_source & DW_IC_TX_ABRT_NOACK) {
-		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-			dev_dbg(dev->dev,
-				"%s: %s\n", __func__, abort_sources[i]);
-		return -EREMOTEIO;
-	}
-
-	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
-
-	if (abort_source & DW_IC_TX_ARB_LOST)
-		return -EAGAIN;
-	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
-		return -EINVAL; /* wrong msgs[] data */
-	else
-		return -EIO;
-}
-
-/*
- * Prepare controller for a transaction and call i2c_dw_xfer_msg
- */
-static int
-i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
-{
-	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
-	int ret;
-
-	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
-
-	mutex_lock(&dev->lock);
-
-	INIT_COMPLETION(dev->cmd_complete);
-	dev->msgs = msgs;
-	dev->msgs_num = num;
-	dev->cmd_err = 0;
-	dev->msg_write_idx = 0;
-	dev->msg_read_idx = 0;
-	dev->msg_err = 0;
-	dev->status = STATUS_IDLE;
-	dev->abort_source = 0;
-
-	ret = i2c_dw_wait_bus_not_busy(dev);
-	if (ret < 0)
-		goto done;
-
-	/* start the transfers */
-	i2c_dw_xfer_init(dev);
-
-	/* wait for tx to complete */
-	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
-	if (ret == 0) {
-		dev_err(dev->dev, "controller timed out\n");
-		i2c_dw_init(dev);
-		ret = -ETIMEDOUT;
-		goto done;
-	} else if (ret < 0)
-		goto done;
-
-	if (dev->msg_err) {
-		ret = dev->msg_err;
-		goto done;
-	}
-
-	/* no error */
-	if (likely(!dev->cmd_err)) {
-		/* Disable the adapter */
-		writel(0, dev->base + DW_IC_ENABLE);
-		ret = num;
-		goto done;
-	}
-
-	/* We have an error */
-	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
-		ret = i2c_dw_handle_tx_abort(dev);
-		goto done;
-	}
-	ret = -EIO;
-
-done:
-	mutex_unlock(&dev->lock);
-
-	return ret;
-}
-
-static u32 i2c_dw_func(struct i2c_adapter *adap)
-{
-	return	I2C_FUNC_I2C |
-		I2C_FUNC_10BIT_ADDR |
-		I2C_FUNC_SMBUS_BYTE |
-		I2C_FUNC_SMBUS_BYTE_DATA |
-		I2C_FUNC_SMBUS_WORD_DATA |
-		I2C_FUNC_SMBUS_I2C_BLOCK;
-}
-
-static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
-{
-	u32 stat;
-
-	/*
-	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
-	 * Ths unmasked raw version of interrupt status bits are available
-	 * in the IC_RAW_INTR_STAT register.
-	 *
-	 * That is,
-	 *   stat = readl(IC_INTR_STAT);
-	 * equals to,
-	 *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
-	 *
-	 * The raw version might be useful for debugging purposes.
-	 */
-	stat = readl(dev->base + DW_IC_INTR_STAT);
-
-	/*
-	 * Do not use the IC_CLR_INTR register to clear interrupts, or
-	 * you'll miss some interrupts, triggered during the period from
-	 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
-	 *
-	 * Instead, use the separately-prepared IC_CLR_* registers.
-	 */
-	if (stat & DW_IC_INTR_RX_UNDER)
-		readl(dev->base + DW_IC_CLR_RX_UNDER);
-	if (stat & DW_IC_INTR_RX_OVER)
-		readl(dev->base + DW_IC_CLR_RX_OVER);
-	if (stat & DW_IC_INTR_TX_OVER)
-		readl(dev->base + DW_IC_CLR_TX_OVER);
-	if (stat & DW_IC_INTR_RD_REQ)
-		readl(dev->base + DW_IC_CLR_RD_REQ);
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		/*
-		 * The IC_TX_ABRT_SOURCE register is cleared whenever
-		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
-		 */
-		dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
-		readl(dev->base + DW_IC_CLR_TX_ABRT);
-	}
-	if (stat & DW_IC_INTR_RX_DONE)
-		readl(dev->base + DW_IC_CLR_RX_DONE);
-	if (stat & DW_IC_INTR_ACTIVITY)
-		readl(dev->base + DW_IC_CLR_ACTIVITY);
-	if (stat & DW_IC_INTR_STOP_DET)
-		readl(dev->base + DW_IC_CLR_STOP_DET);
-	if (stat & DW_IC_INTR_START_DET)
-		readl(dev->base + DW_IC_CLR_START_DET);
-	if (stat & DW_IC_INTR_GEN_CALL)
-		readl(dev->base + DW_IC_CLR_GEN_CALL);
-
-	return stat;
-}
-
-/*
- * Interrupt service routine. This gets called whenever an I2C interrupt
- * occurs.
- */
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
-{
-	struct dw_i2c_dev *dev = dev_id;
-	u32 stat;
-
-	stat = i2c_dw_read_clear_intrbits(dev);
-	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
-
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
-		dev->status = STATUS_IDLE;
-
-		/*
-		 * Anytime TX_ABRT is set, the contents of the tx/rx
-		 * buffers are flushed.  Make sure to skip them.
-		 */
-		writel(0, dev->base + DW_IC_INTR_MASK);
-		goto tx_aborted;
-	}
-
-	if (stat & DW_IC_INTR_RX_FULL)
-		i2c_dw_read(dev);
-
-	if (stat & DW_IC_INTR_TX_EMPTY)
-		i2c_dw_xfer_msg(dev);
-
-	/*
-	 * No need to modify or disable the interrupt mask here.
-	 * i2c_dw_xfer_msg() will take care of it according to
-	 * the current transmit status.
-	 */
-
-tx_aborted:
-	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
-		complete(&dev->cmd_complete);
-
-	return IRQ_HANDLED;
-}
-
-static struct i2c_algorithm i2c_dw_algo = {
-	.master_xfer	= i2c_dw_xfer,
-	.functionality	= i2c_dw_func,
-};
-
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev;
-	struct i2c_adapter *adap;
-	struct resource *mem, *ioarea;
-	int irq, r;
-
-	/* NOTE: driver uses the static register mapping */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		return irq; /* -ENXIO */
-	}
-
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
-	}
-
-	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
-	if (!dev) {
-		r = -ENOMEM;
-		goto err_release_region;
-	}
-
-	init_completion(&dev->cmd_complete);
-	mutex_init(&dev->lock);
-	dev->dev = get_device(&pdev->dev);
-	dev->irq = irq;
-	platform_set_drvdata(pdev, dev);
-
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		r = -ENODEV;
-		goto err_free_mem;
-	}
-	clk_enable(dev->clk);
-
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (dev->base == NULL) {
-		dev_err(&pdev->dev, "failure mapping io resources\n");
-		r = -EBUSY;
-		goto err_unuse_clocks;
-	}
-	{
-		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
-
-		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-	}
-	i2c_dw_init(dev);
-
-	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
-	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-	if (r) {
-		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
-		goto err_iounmap;
-	}
-
-	adap = &dev->adapter;
-	i2c_set_adapdata(adap, dev);
-	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON;
-	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
-			sizeof(adap->name));
-	adap->algo = &i2c_dw_algo;
-	adap->dev.parent = &pdev->dev;
-
-	adap->nr = pdev->id;
-	r = i2c_add_numbered_adapter(adap);
-	if (r) {
-		dev_err(&pdev->dev, "failure adding adapter\n");
-		goto err_free_irq;
-	}
-
-	return 0;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err_iounmap:
-	iounmap(dev->base);
-err_unuse_clocks:
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-err_free_mem:
-	platform_set_drvdata(pdev, NULL);
-	put_device(&pdev->dev);
-	kfree(dev);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-
-	return r;
-}
-
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
-	struct resource *mem;
-
-	platform_set_drvdata(pdev, NULL);
-	i2c_del_adapter(&dev->adapter);
-	put_device(&pdev->dev);
-
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-
-	writel(0, dev->base + DW_IC_ENABLE);
-	free_irq(dev->irq, dev);
-	kfree(dev);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
-
-static struct platform_driver dw_i2c_driver = {
-	.remove		= __devexit_p(dw_i2c_remove),
-	.driver		= {
-		.name	= "i2c_designware",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init dw_i2c_init_driver(void)
-{
-	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
-}
-module_init(dw_i2c_init_driver);
-
-static void __exit dw_i2c_exit_driver(void)
-{
-	platform_driver_unregister(&dw_i2c_driver);
-}
-module_exit(dw_i2c_exit_driver);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-core.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-core.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,705 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "i2c-designware-core.h"
+
+/*
+ * Registers offset
+ */
+#define DW_IC_CON		0x0
+#define DW_IC_TAR		0x4
+#define DW_IC_DATA_CMD		0x10
+#define DW_IC_SS_SCL_HCNT	0x14
+#define DW_IC_SS_SCL_LCNT	0x18
+#define DW_IC_FS_SCL_HCNT	0x1c
+#define DW_IC_FS_SCL_LCNT	0x20
+#define DW_IC_INTR_STAT		0x2c
+#define DW_IC_INTR_MASK		0x30
+#define DW_IC_RAW_INTR_STAT	0x34
+#define DW_IC_RX_TL		0x38
+#define DW_IC_TX_TL		0x3c
+#define DW_IC_CLR_INTR		0x40
+#define DW_IC_CLR_RX_UNDER	0x44
+#define DW_IC_CLR_RX_OVER	0x48
+#define DW_IC_CLR_TX_OVER	0x4c
+#define DW_IC_CLR_RD_REQ	0x50
+#define DW_IC_CLR_TX_ABRT	0x54
+#define DW_IC_CLR_RX_DONE	0x58
+#define DW_IC_CLR_ACTIVITY	0x5c
+#define DW_IC_CLR_STOP_DET	0x60
+#define DW_IC_CLR_START_DET	0x64
+#define DW_IC_CLR_GEN_CALL	0x68
+#define DW_IC_ENABLE		0x6c
+#define DW_IC_STATUS		0x70
+#define DW_IC_TXFLR		0x74
+#define DW_IC_RXFLR		0x78
+#define DW_IC_TX_ABRT_SOURCE	0x80
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_COMP_TYPE		0xfc
+#define DW_IC_COMP_TYPE_VALUE	0x44570140
+
+#define DW_IC_INTR_RX_UNDER	0x001
+#define DW_IC_INTR_RX_OVER	0x002
+#define DW_IC_INTR_RX_FULL	0x004
+#define DW_IC_INTR_TX_OVER	0x008
+#define DW_IC_INTR_TX_EMPTY	0x010
+#define DW_IC_INTR_RD_REQ	0x020
+#define DW_IC_INTR_TX_ABRT	0x040
+#define DW_IC_INTR_RX_DONE	0x080
+#define DW_IC_INTR_ACTIVITY	0x100
+#define DW_IC_INTR_STOP_DET	0x200
+#define DW_IC_INTR_START_DET	0x400
+#define DW_IC_INTR_GEN_CALL	0x800
+
+#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
+					 DW_IC_INTR_TX_EMPTY | \
+					 DW_IC_INTR_TX_ABRT | \
+					 DW_IC_INTR_STOP_DET)
+
+#define DW_IC_STATUS_ACTIVITY	0x1
+
+#define DW_IC_ERR_TX_ABRT	0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE			0x0
+#define STATUS_WRITE_IN_PROGRESS	0x1
+#define STATUS_READ_IN_PROGRESS		0x2
+
+#define TIMEOUT			20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK	0
+#define ABRT_10ADDR1_NOACK	1
+#define ABRT_10ADDR2_NOACK	2
+#define ABRT_TXDATA_NOACK	3
+#define ABRT_GCALL_NOACK	4
+#define ABRT_GCALL_READ		5
+#define ABRT_SBYTE_ACKDET	7
+#define ABRT_SBYTE_NORSTRT	9
+#define ABRT_10B_RD_NORSTRT	10
+#define ABRT_MASTER_DIS		11
+#define ARB_LOST		12
+
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
+					 DW_IC_TX_ABRT_TXDATA_NOACK | \
+					 DW_IC_TX_ABRT_GCALL_NOACK)
+
+static char *abort_sources[] = {
+	[ABRT_7B_ADDR_NOACK] =
+		"slave address not acknowledged (7bit mode)",
+	[ABRT_10ADDR1_NOACK] =
+		"first address byte not acknowledged (10bit mode)",
+	[ABRT_10ADDR2_NOACK] =
+		"second address byte not acknowledged (10bit mode)",
+	[ABRT_TXDATA_NOACK] =
+		"data not acknowledged",
+	[ABRT_GCALL_NOACK] =
+		"no acknowledgement for a general call",
+	[ABRT_GCALL_READ] =
+		"read after general call",
+	[ABRT_SBYTE_ACKDET] =
+		"start byte acknowledged",
+	[ABRT_SBYTE_NORSTRT] =
+		"trying to send start byte when restart is disabled",
+	[ABRT_10B_RD_NORSTRT] =
+		"trying to read when restart is disabled (10bit mode)",
+	[ABRT_MASTER_DIS] =
+		"trying to use disabled adapter",
+	[ARB_LOST] =
+		"lost arbitration",
+};
+
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+	u32 value = readl(dev->base + offset);
+
+	if (dev->swab)
+		return swab32(value);
+	else
+		return value;
+}
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+	if (dev->swab)
+		b = swab32(b);
+
+	writel(b, dev->base + offset);
+}
+
+static u32
+i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+	/*
+	 * DesignWare I2C core doesn't seem to have solid strategy to meet
+	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
+	 * will result in violation of the tHD;STA spec.
+	 */
+	if (cond)
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
+		 *
+		 * This is based on the DW manuals, and represents an ideal
+		 * configuration.  The resulting I2C bus speed will be
+		 * faster than any of the others.
+		 *
+		 * If your hardware is free from tHD;STA issue, try this one.
+		 */
+		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
+	else
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+		 *
+		 * This is just experimental rule; the tHD;STA period turned
+		 * out to be proportinal to (_HCNT + 3).  With this setting,
+		 * we could meet both tHIGH and tHD;STA timing specs.
+		 *
+		 * If unsure, you'd better to take this alternative.
+		 *
+		 * The reason why we need to take into account "tf" here,
+		 * is the same as described in i2c_dw_scl_lcnt().
+		 */
+		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
+}
+
+static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+{
+	/*
+	 * Conditional expression:
+	 *
+	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
+	 *
+	 * DW I2C core starts counting the SCL CNTs for the LOW period
+	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
+	 * In order to meet the tLOW timing spec, we need to take into
+	 * account the fall time of SCL signal (tf).  Default tf value
+	 * should be 0.3 us, for safety.
+	 */
+	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
+}
+
+/**
+ * i2c_dw_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+int i2c_dw_init(struct dw_i2c_dev *dev)
+{
+	u32 input_clock_khz;
+	u32 hcnt, lcnt;
+	u32 reg;
+
+	input_clock_khz = dev->get_clk_rate_khz(dev);
+
+	/* Configure register endianess access */
+	reg = dw_readl(dev, DW_IC_COMP_TYPE);
+	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+		dev->swab = 1;
+		reg = DW_IC_COMP_TYPE_VALUE;
+	}
+
+	if (reg != DW_IC_COMP_TYPE_VALUE) {
+		dev_err(dev->dev, "Unknown Synopsys component type: "
+			"0x%08x\n", reg);
+		return -ENODEV;
+	}
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set standard and fast speed deviders for high/low periods */
+
+	/* Standard-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				40,	/* tHD;STA = tHIGH = 4.0 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				47,	/* tLOW = 4.7 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
+	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Fast-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				6,	/* tHD;STA = tHIGH = 0.6 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				13,	/* tLOW = 1.3 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
+	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Configure Tx/Rx FIFO threshold levels */
+	dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+	dw_writel(dev, 0, DW_IC_RX_TL);
+
+	/* configure the i2c master */
+	dw_writel(dev, dev->master_cfg , DW_IC_CON);
+	return 0;
+}
+
+/*
+ * Waiting for bus not busy
+ */
+static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
+{
+	int timeout = TIMEOUT;
+
+	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+		if (timeout <= 0) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 ic_con;
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set the slave (target) address */
+	dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
+
+	/* if the slave address is ten bit address, enable 10BITADDR */
+	ic_con = dw_readl(dev, DW_IC_CON);
+	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+		ic_con |= DW_IC_CON_10BITADDR_MASTER;
+	else
+		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+	dw_writel(dev, ic_con, DW_IC_CON);
+
+	/* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+
+	/* Enable interrupts */
+	dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
+}
+
+/*
+ * Initiate (and continue) low level master read/write transaction.
+ * This function is only called from i2c_dw_isr, and pumping i2c_msg
+ * messages into the tx buffer.  Even if the size of i2c_msg data is
+ * longer than the size of the tx buffer, it handles everything.
+ */
+void
+i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 intr_mask;
+	int tx_limit, rx_limit;
+	u32 addr = msgs[dev->msg_write_idx].addr;
+	u32 buf_len = dev->tx_buf_len;
+	u8 *buf = dev->tx_buf;
+
+	intr_mask = DW_IC_INTR_DEFAULT_MASK;
+
+	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+		/*
+		 * if target address has changed, we need to
+		 * reprogram the target address in the i2c
+		 * adapter when we are done with this transfer
+		 */
+		if (msgs[dev->msg_write_idx].addr != addr) {
+			dev_err(dev->dev,
+				"%s: invalid target address\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (msgs[dev->msg_write_idx].len == 0) {
+			dev_err(dev->dev,
+				"%s: invalid message length\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+			/* new i2c_msg */
+			buf = msgs[dev->msg_write_idx].buf;
+			buf_len = msgs[dev->msg_write_idx].len;
+		}
+
+		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+		rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
+
+		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+				dw_writel(dev, 0x100, DW_IC_DATA_CMD);
+				rx_limit--;
+			} else
+				dw_writel(dev, *buf++, DW_IC_DATA_CMD);
+			tx_limit--; buf_len--;
+		}
+
+		dev->tx_buf = buf;
+		dev->tx_buf_len = buf_len;
+
+		if (buf_len > 0) {
+			/* more bytes to be written */
+			dev->status |= STATUS_WRITE_IN_PROGRESS;
+			break;
+		} else
+			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+	}
+
+	/*
+	 * If i2c_msg index search is completed, we don't need TX_EMPTY
+	 * interrupt any more.
+	 */
+	if (dev->msg_write_idx == dev->msgs_num)
+		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+	if (dev->msg_err)
+		intr_mask = 0;
+
+	dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
+}
+
+static void
+i2c_dw_read(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	int rx_valid;
+
+	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+		u32 len;
+		u8 *buf;
+
+		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+			continue;
+
+		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+			len = msgs[dev->msg_read_idx].len;
+			buf = msgs[dev->msg_read_idx].buf;
+		} else {
+			len = dev->rx_buf_len;
+			buf = dev->rx_buf;
+		}
+
+		rx_valid = dw_readl(dev, DW_IC_RXFLR);
+
+		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+			*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+
+		if (len > 0) {
+			dev->status |= STATUS_READ_IN_PROGRESS;
+			dev->rx_buf_len = len;
+			dev->rx_buf = buf;
+			return;
+		} else
+			dev->status &= ~STATUS_READ_IN_PROGRESS;
+	}
+}
+
+static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+{
+	unsigned long abort_source = dev->abort_source;
+	int i;
+
+	if (abort_source & DW_IC_TX_ABRT_NOACK) {
+		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+			dev_dbg(dev->dev,
+				"%s: %s\n", __func__, abort_sources[i]);
+		return -EREMOTEIO;
+	}
+
+	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+
+	if (abort_source & DW_IC_TX_ARB_LOST)
+		return -EAGAIN;
+	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+		return -EINVAL; /* wrong msgs[] data */
+	else
+		return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ */
+int
+i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+	mutex_lock(&dev->lock);
+	pm_runtime_get_sync(dev->dev);
+
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->msgs = msgs;
+	dev->msgs_num = num;
+	dev->cmd_err = 0;
+	dev->msg_write_idx = 0;
+	dev->msg_read_idx = 0;
+	dev->msg_err = 0;
+	dev->status = STATUS_IDLE;
+	dev->abort_source = 0;
+
+	ret = i2c_dw_wait_bus_not_busy(dev);
+	if (ret < 0)
+		goto done;
+
+	/* start the transfers */
+	i2c_dw_xfer_init(dev);
+
+	/* wait for tx to complete */
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		i2c_dw_init(dev);
+		ret = -ETIMEDOUT;
+		goto done;
+	} else if (ret < 0)
+		goto done;
+
+	if (dev->msg_err) {
+		ret = dev->msg_err;
+		goto done;
+	}
+
+	/* no error */
+	if (likely(!dev->cmd_err)) {
+		/* Disable the adapter */
+		dw_writel(dev, 0, DW_IC_ENABLE);
+		ret = num;
+		goto done;
+	}
+
+	/* We have an error */
+	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+		ret = i2c_dw_handle_tx_abort(dev);
+		goto done;
+	}
+	ret = -EIO;
+
+done:
+	pm_runtime_put(dev->dev);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+u32 i2c_dw_func(struct i2c_adapter *adap)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	return dev->functionality;
+}
+
+static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
+{
+	u32 stat;
+
+	/*
+	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
+	 * Ths unmasked raw version of interrupt status bits are available
+	 * in the IC_RAW_INTR_STAT register.
+	 *
+	 * That is,
+	 *   stat = dw_readl(IC_INTR_STAT);
+	 * equals to,
+	 *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
+	 *
+	 * The raw version might be useful for debugging purposes.
+	 */
+	stat = dw_readl(dev, DW_IC_INTR_STAT);
+
+	/*
+	 * Do not use the IC_CLR_INTR register to clear interrupts, or
+	 * you'll miss some interrupts, triggered during the period from
+	 * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
+	 *
+	 * Instead, use the separately-prepared IC_CLR_* registers.
+	 */
+	if (stat & DW_IC_INTR_RX_UNDER)
+		dw_readl(dev, DW_IC_CLR_RX_UNDER);
+	if (stat & DW_IC_INTR_RX_OVER)
+		dw_readl(dev, DW_IC_CLR_RX_OVER);
+	if (stat & DW_IC_INTR_TX_OVER)
+		dw_readl(dev, DW_IC_CLR_TX_OVER);
+	if (stat & DW_IC_INTR_RD_REQ)
+		dw_readl(dev, DW_IC_CLR_RD_REQ);
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		/*
+		 * The IC_TX_ABRT_SOURCE register is cleared whenever
+		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
+		 */
+		dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+		dw_readl(dev, DW_IC_CLR_TX_ABRT);
+	}
+	if (stat & DW_IC_INTR_RX_DONE)
+		dw_readl(dev, DW_IC_CLR_RX_DONE);
+	if (stat & DW_IC_INTR_ACTIVITY)
+		dw_readl(dev, DW_IC_CLR_ACTIVITY);
+	if (stat & DW_IC_INTR_STOP_DET)
+		dw_readl(dev, DW_IC_CLR_STOP_DET);
+	if (stat & DW_IC_INTR_START_DET)
+		dw_readl(dev, DW_IC_CLR_START_DET);
+	if (stat & DW_IC_INTR_GEN_CALL)
+		dw_readl(dev, DW_IC_CLR_GEN_CALL);
+
+	return stat;
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+{
+	struct dw_i2c_dev *dev = dev_id;
+	u32 stat, enabled;
+
+	enabled = dw_readl(dev, DW_IC_ENABLE);
+	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+	dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
+		dev->adapter.name, enabled, stat);
+	if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+		return IRQ_NONE;
+
+	stat = i2c_dw_read_clear_intrbits(dev);
+
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+		dev->status = STATUS_IDLE;
+
+		/*
+		 * Anytime TX_ABRT is set, the contents of the tx/rx
+		 * buffers are flushed.  Make sure to skip them.
+		 */
+		dw_writel(dev, 0, DW_IC_INTR_MASK);
+		goto tx_aborted;
+	}
+
+	if (stat & DW_IC_INTR_RX_FULL)
+		i2c_dw_read(dev);
+
+	if (stat & DW_IC_INTR_TX_EMPTY)
+		i2c_dw_xfer_msg(dev);
+
+	/*
+	 * No need to modify or disable the interrupt mask here.
+	 * i2c_dw_xfer_msg() will take care of it according to
+	 * the current transmit status.
+	 */
+
+tx_aborted:
+	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+		complete(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+void i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+       /* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+}
+
+u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_ENABLE);
+}
+
+void i2c_dw_disable(struct dw_i2c_dev *dev)
+{
+	/* Disable controller */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* Disable all interupts */
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_clear_int(struct dw_i2c_dev *dev)
+{
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_disable_int(struct dw_i2c_dev *dev)
+{
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+}
+
+u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_COMP_PARAM_1);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-core.h linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-core.h
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,105 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#define DW_IC_CON_MASTER		0x1
+#define DW_IC_CON_SPEED_STD		0x2
+#define DW_IC_CON_SPEED_FAST		0x4
+#define DW_IC_CON_10BITADDR_MASTER	0x10
+#define DW_IC_CON_RESTART_EN		0x20
+#define DW_IC_CON_SLAVE_DISABLE		0x40
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *	array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *	array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct mutex		lock;
+	struct clk		*clk;
+	u32			(*get_clk_rate_khz) (struct dw_i2c_dev *dev);
+	struct dw_pci_controller *controller;
+	int			cmd_err;
+	struct i2c_msg		*msgs;
+	int			msgs_num;
+	int			msg_write_idx;
+	u32			tx_buf_len;
+	u8			*tx_buf;
+	int			msg_read_idx;
+	u32			rx_buf_len;
+	u8			*rx_buf;
+	int			msg_err;
+	unsigned int		status;
+	u32			abort_source;
+	int			irq;
+	int			swab;
+	struct i2c_adapter	adapter;
+	u32			functionality;
+	u32			master_cfg;
+	unsigned int		tx_fifo_depth;
+	unsigned int		rx_fifo_depth;
+};
+
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+		int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-pcidrv.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-pcidrv.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-pcidrv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-pcidrv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,392 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ * Copyright (C) 2011 Intel corporation.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include "i2c-designware-core.h"
+
+#define DRIVER_NAME "i2c-designware-pci"
+
+enum dw_pci_ctl_id_t {
+	moorestown_0,
+	moorestown_1,
+	moorestown_2,
+
+	medfield_0,
+	medfield_1,
+	medfield_2,
+	medfield_3,
+	medfield_4,
+	medfield_5,
+};
+
+struct dw_pci_controller {
+	u32 bus_num;
+	u32 bus_cfg;
+	u32 tx_fifo_depth;
+	u32 rx_fifo_depth;
+	u32 clk_khz;
+};
+
+#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |			\
+				DW_IC_CON_SLAVE_DISABLE |	\
+				DW_IC_CON_RESTART_EN)
+
+static struct  dw_pci_controller  dw_pci_controllers[] = {
+	[moorestown_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_3] = {
+		.bus_num     = 3,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_4] = {
+		.bus_num     = 4,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_5] = {
+		.bus_num     = 5,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+};
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int i2c_dw_pci_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+
+
+	i2c_dw_disable(i2c);
+
+	err = pci_save_state(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_save_state failed\n");
+		return err;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D3hot);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int i2c_dw_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+	u32 enabled;
+
+	enabled = i2c_dw_is_enabled(i2c);
+	if (enabled)
+		return 0;
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+		return err;
+	}
+
+	pci_restore_state(pdev);
+
+	i2c_dw_init(i2c);
+	i2c_dw_enable(i2c);
+	return 0;
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+	int err = pm_schedule_suspend(dev, 500);
+	dev_dbg(dev, "runtime_idle called\n");
+
+	if (err != 0)
+		return 0;
+	return -EBUSY;
+}
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+	.resume         = i2c_dw_pci_resume,
+	.suspend        = i2c_dw_pci_suspend,
+	SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume,
+			   i2c_dw_pci_runtime_idle)
+};
+
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return dev->controller->clk_khz;
+}
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	unsigned long start, len;
+	void __iomem *base;
+	int r;
+	struct  dw_pci_controller *controller;
+
+	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+		printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+			id->driver_data);
+		return -EINVAL;
+	}
+
+	controller = &dw_pci_controllers[id->driver_data];
+
+	r = pci_enable_device(pdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+			r);
+		goto exit;
+	}
+
+	/* Determine the address of the I2C area */
+	start = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!start || len == 0) {
+		dev_err(&pdev->dev, "base address not set\n");
+		r = -ENODEV;
+		goto exit;
+	}
+
+	r = pci_request_region(pdev, 0, DRIVER_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "failed to request I2C region "
+			"0x%lx-0x%lx\n", start,
+			(unsigned long)pci_resource_end(pdev, 0));
+		goto exit;
+	}
+
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "I/O memory remapping failed\n");
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->clk = NULL;
+	dev->controller = controller;
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+	dev->base = base;
+	dev->dev = get_device(&pdev->dev);
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  controller->bus_cfg;
+
+	pci_set_drvdata(pdev, dev);
+
+	dev->tx_fifo_depth = controller->tx_fifo_depth;
+	dev->rx_fifo_depth = controller->rx_fifo_depth;
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = 0;
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->nr = controller->bus_num;
+	snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d",
+		adap->nr);
+
+	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	i2c_dw_disable_int(dev);
+	i2c_dw_clear_int(dev);
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+
+	return 0;
+
+err_free_irq:
+	free_irq(pdev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+	pci_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	pci_release_region(pdev, 0);
+exit:
+	return r;
+}
+
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+{
+	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+
+	i2c_dw_disable(dev);
+	pm_runtime_forbid(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	pci_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	free_irq(dev->irq, dev);
+	kfree(dev);
+	pci_release_region(pdev, 0);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("i2c_designware-pci");
+
+DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+	/* Moorestown */
+	{ PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+	{ PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+	{ PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+	/* Medfield */
+	{ PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+	{ PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+	{ PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+	{ PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+	{ PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+	{ PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+	{ 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= i2_designware_pci_ids,
+	.probe		= i2c_dw_pci_probe,
+	.remove		= __devexit_p(i2c_dw_pci_remove),
+	.driver         = {
+		.pm     = &i2c_dw_pm_ops,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return  pci_register_driver(&dw_i2c_driver);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	pci_unregister_driver(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-platdrv.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-platdrv.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-designware-platdrv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-designware-platdrv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,215 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return clk_get_rate(dev->clk)/1000;
+}
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *ioarea;
+	int irq, r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return irq; /* -ENXIO */
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq;
+	platform_set_drvdata(pdev, dev);
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+
+	if (IS_ERR(dev->clk)) {
+		r = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = i2c_dw_read_comp_param(dev);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	i2c_dw_disable_int(dev);
+	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	i2c_dw_disable(dev);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-eg20t.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-eg20t.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-eg20t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-eg20t.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,6 +64,7 @@
 #define TEN_BIT_ADDR_DEFAULT	0xF000
 #define TEN_BIT_ADDR_MASK	0xF0
 #define PCH_START		0x0020
+#define PCH_RESTART		0x0004
 #define PCH_ESR_START		0x0001
 #define PCH_BUFF_START		0x1
 #define PCH_REPSTART		0x0004
@@ -273,23 +274,24 @@ static s32 pch_i2c_wait_for_bus_idle(str
 				     s32 timeout)
 {
 	void __iomem *p = adap->pch_base_address;
+	ktime_t ns_val;
+
+	if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+		return 0;
 
 	/* MAX timeout value is timeout*1000*1000nsec */
-	ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+	ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
 	do {
-		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
-			break;
 		msleep(20);
+		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+			return 0;
 	} while (ktime_lt(ktime_get(), ns_val));
 
 	pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+	pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+	pch_i2c_init(adap);
 
-	if (timeout == 0) {
-		pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
-		return -ETIME;
-	}
-
-	return 0;
+	return -ETIME;
 }
 
 /**
@@ -311,21 +313,19 @@ static void pch_i2c_start(struct i2c_alg
  */
 static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
-	s32 ret;
+	long ret;
 	ret = wait_event_timeout(pch_event,
 			(adap->pch_event_flag != 0), msecs_to_jiffies(50));
-	if (ret < 0) {
-		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
-		return ret;
-	}
 
 	if (ret == 0) {
 		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -ETIMEDOUT;
 	}
 
 	if (adap->pch_event_flag & I2C_ERROR_MASK) {
 		pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -EIO;
 	}
 
@@ -394,6 +394,7 @@ static s32 pch_i2c_writebytes(struct i2c
 	u32 addr_2_msb;
 	u32 addr_8_lsb;
 	s32 wrcount;
+	s32 rtn;
 	void __iomem *p = adap->pch_base_address;
 
 	length = msgs->len;
@@ -412,15 +413,29 @@ static s32 pch_i2c_writebytes(struct i2c
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
 		if (first)
 			pch_i2c_start(adap);
-		if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
-		    pch_i2c_getack(adap) == 0) {
+
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
 			addr_8_lsb = (addr & I2C_ADDR_MSK);
 			iowrite32(addr_8_lsb, p + PCH_I2CDR);
-		} else {
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
 			pch_i2c_stop(adap);
 			return -ETIME;
 		}
@@ -431,30 +446,51 @@ static s32 pch_i2c_writebytes(struct i2c
 			pch_i2c_start(adap);
 	}
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		for (wrcount = 0; wrcount < length; ++wrcount) {
-			/* write buffer value to I2C data register */
-			iowrite32(buf[wrcount], p + PCH_I2CDR);
-			pch_dbg(adap, "writing %x to Data register\n",
-				buf[wrcount]);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-			if (pch_i2c_wait_for_xfer_complete(adap) != 0)
-				return -ETIME;
+	for (wrcount = 0; wrcount < length; ++wrcount) {
+		/* write buffer value to I2C data register */
+		iowrite32(buf[wrcount], p + PCH_I2CDR);
+		pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
 
-			if (pch_i2c_getack(adap))
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
 				return -EIO;
+			}
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMCF_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
+	}
 
-		/* check if this is the last message */
-		if (last)
-			pch_i2c_stop(adap);
-		else
-			pch_i2c_repstart(adap);
-	} else {
+	/* check if this is the last message */
+	if (last)
 		pch_i2c_stop(adap);
-		return -EIO;
-	}
+	else
+		pch_i2c_repstart(adap);
 
 	pch_dbg(adap, "return=%d\n", wrcount);
 
@@ -484,6 +520,19 @@ static void pch_i2c_sendnack(struct i2c_
 }
 
 /**
+ * pch_i2c_restart() - Generate I2C restart condition in normal mode.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
+ */
+static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
+}
+
+/**
  * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
  * @i2c_adap:	Pointer to the struct i2c_adapter.
  * @msgs:	Pointer to i2c_msg structure.
@@ -500,7 +549,9 @@ static s32 pch_i2c_readbytes(struct i2c_
 	u32 length;
 	u32 addr;
 	u32 addr_2_msb;
+	u32 addr_8_lsb;
 	void __iomem *p = adap->pch_base_address;
+	s32 rtn;
 
 	length = msgs->len;
 	buf = msgs->buf;
@@ -515,9 +566,55 @@ static s32 pch_i2c_readbytes(struct i2c_
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+		if (first)
+			pch_i2c_start(adap);
 
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_8_lsb = (addr & I2C_ADDR_MSK);
+			iowrite32(addr_8_lsb, p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
+		pch_i2c_restart(adap);
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_2_msb |= I2C_RD;
+			iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
+				  p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
 	} else {
 		/* 7 address bits + R/W bit */
 		addr = (((addr) << 1) | (I2C_RD));
@@ -528,56 +625,81 @@ static s32 pch_i2c_readbytes(struct i2c_
 	if (first)
 		pch_i2c_start(adap);
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		pch_dbg(adap, "return %d\n", 0);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-		if (length == 0) {
-			pch_i2c_stop(adap);
-			ioread32(p + PCH_I2CDR); /* Dummy read needs */
+	if (length == 0) {
+		pch_i2c_stop(adap);
+		ioread32(p + PCH_I2CDR); /* Dummy read needs */
 
-			count = length;
-		} else {
-			int read_index;
-			int loop;
-			pch_i2c_sendack(adap);
+		count = length;
+	} else {
+		int read_index;
+		int loop;
+		pch_i2c_sendack(adap);
 
-			/* Dummy read */
-			for (loop = 1, read_index = 0; loop < length; loop++) {
-				buf[read_index] = ioread32(p + PCH_I2CDR);
+		/* Dummy read */
+		for (loop = 1, read_index = 0; loop < length; loop++) {
+			buf[read_index] = ioread32(p + PCH_I2CDR);
 
-				if (loop != 1)
-					read_index++;
+			if (loop != 1)
+				read_index++;
 
-				if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
-					pch_i2c_stop(adap);
-					return -ETIME;
+			rtn = pch_i2c_wait_for_xfer_complete(adap);
+			if (rtn == 0) {
+				if (pch_i2c_getack(adap)) {
+					pch_dbg(adap, "Receive NACK for slave"
+						"address setting\n");
+					return -EIO;
 				}
-			}	/* end for */
+			} else { /* wait-event timeout */
+				pch_i2c_stop(adap);
+				return -ETIME;
+			}
 
-			pch_i2c_sendnack(adap);
+		}	/* end for */
 
-			buf[read_index] = ioread32(p + PCH_I2CDR);
+		pch_i2c_sendnack(adap);
 
-			if (length != 1)
-				read_index++;
+		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
 
-			if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
-				if (last)
-					pch_i2c_stop(adap);
-				else
-					pch_i2c_repstart(adap);
+		if (length != 1)
+			read_index++;
 
-				buf[read_index++] = ioread32(p + PCH_I2CDR);
-				count = read_index;
-			} else {
-				count = -ETIME;
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave"
+					"address setting\n");
+				return -EIO;
 			}
-
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
-	} else {
-		count = -ETIME;
-		pch_i2c_stop(adap);
+
+		if (last)
+			pch_i2c_stop(adap);
+		else
+			pch_i2c_repstart(adap);
+
+		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
+		count = read_index;
 	}
 
 	return count;
@@ -771,6 +893,13 @@ static int __devinit pch_i2c_probe(struc
 	/* Set the number of I2C channel instance */
 	adap_info->ch_num = id->driver_data;
 
+	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
+		  KBUILD_MODNAME, adap_info);
+	if (ret) {
+		pch_pci_err(pdev, "request_irq FAILED\n");
+		goto err_request_irq;
+	}
+
 	for (i = 0; i < adap_info->ch_num; i++) {
 		pch_adap = &adap_info->pch_data[i].pch_adapter;
 		adap_info->pch_i2c_suspended = false;
@@ -788,28 +917,23 @@ static int __devinit pch_i2c_probe(struc
 
 		pch_adap->dev.parent = &pdev->dev;
 
+		pch_i2c_init(&adap_info->pch_data[i]);
 		ret = i2c_add_adapter(pch_adap);
 		if (ret) {
 			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
-			goto err_i2c_add_adapter;
+			goto err_add_adapter;
 		}
-
-		pch_i2c_init(&adap_info->pch_data[i]);
-	}
-	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-		  KBUILD_MODNAME, adap_info);
-	if (ret) {
-		pch_pci_err(pdev, "request_irq FAILED\n");
-		goto err_i2c_add_adapter;
 	}
 
 	pci_set_drvdata(pdev, adap_info);
 	pch_pci_dbg(pdev, "returns %d.\n", ret);
 	return 0;
 
-err_i2c_add_adapter:
+err_add_adapter:
 	for (j = 0; j < i; j++)
 		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
+	free_irq(pdev->irq, adap_info);
+err_request_irq:
 	pci_iounmap(pdev, base_addr);
 err_pci_iomap:
 	pci_release_regions(pdev);
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-highlander.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-highlander.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-highlander.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-highlander.c	2012-01-04 18:55:44.000000000 -0500
@@ -387,7 +387,7 @@ static int __devinit highlander_i2c_prob
 		dev->irq = 0;
 
 	if (dev->irq) {
-		ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+		ret = request_irq(dev->irq, highlander_i2c_irq, 0,
 				  pdev->name, dev);
 		if (unlikely(ret))
 			goto err_unmap;
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-imx.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-imx.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-imx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,9 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -125,6 +128,11 @@ struct imx_i2c_struct {
 	unsigned int		ifdr; /* IMX_I2C_IFDR */
 };
 
+static const struct of_device_id i2c_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx1-i2c", },
+	{ /* sentinel */ }
+};
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -466,10 +474,10 @@ static int __init i2c_imx_probe(struct p
 {
 	struct imx_i2c_struct *i2c_imx;
 	struct resource *res;
-	struct imxi2c_platform_data *pdata;
+	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 	void __iomem *base;
 	resource_size_t res_size;
-	int irq;
+	int irq, bitrate;
 	int ret;
 
 	dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -485,19 +493,11 @@ static int __init i2c_imx_probe(struct p
 		return -ENOENT;
 	}
 
-	pdata = pdev->dev.platform_data;
-
-	if (pdata && pdata->init) {
-		ret = pdata->init(&pdev->dev);
-		if (ret)
-			return ret;
-	}
-
 	res_size = resource_size(res);
 
 	if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
-		ret = -EBUSY;
-		goto fail0;
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
 	}
 
 	base = ioremap(res->start, res_size);
@@ -520,6 +520,7 @@ static int __init i2c_imx_probe(struct p
 	i2c_imx->adapter.algo		= &i2c_imx_algo;
 	i2c_imx->adapter.dev.parent	= &pdev->dev;
 	i2c_imx->adapter.nr 		= pdev->id;
+	i2c_imx->adapter.dev.of_node	= pdev->dev.of_node;
 	i2c_imx->irq			= irq;
 	i2c_imx->base			= base;
 	i2c_imx->res			= res;
@@ -546,10 +547,12 @@ static int __init i2c_imx_probe(struct p
 	i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
 
 	/* Set up clock divider */
-	if (pdata && pdata->bitrate)
-		i2c_imx_set_clk(i2c_imx, pdata->bitrate);
-	else
-		i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
+	bitrate = IMX_I2C_BIT_RATE;
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "clock-frequency", &bitrate);
+	if (ret < 0 && pdata && pdata->bitrate)
+		bitrate = pdata->bitrate;
+	i2c_imx_set_clk(i2c_imx, bitrate);
 
 	/* Set up chip registers to defaults */
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -562,6 +565,8 @@ static int __init i2c_imx_probe(struct p
 		goto fail5;
 	}
 
+	of_i2c_register_devices(&i2c_imx->adapter);
+
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, i2c_imx);
 
@@ -586,16 +591,12 @@ fail2:
 	iounmap(base);
 fail1:
 	release_mem_region(res->start, resource_size(res));
-fail0:
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
 	return ret; /* Return error number */
 }
 
 static int __exit i2c_imx_remove(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
-	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 
 	/* remove adapter */
 	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -611,10 +612,6 @@ static int __exit i2c_imx_remove(struct
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
 	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 
-	/* Shut down hardware */
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
-
 	clk_put(i2c_imx->clk);
 
 	iounmap(i2c_imx->base);
@@ -628,6 +625,7 @@ static struct platform_driver i2c_imx_dr
 	.driver	= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = i2c_imx_dt_ids,
 	}
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-ixp2000.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-ixp2000.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-ixp2000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-ixp2000.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/slab.h>
 
 #include <mach/hardware.h>	/* Pick up IXP2000-specific bits */
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
 
 static inline int ixp2000_scl_pin(void *data)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-nomadik.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-nomadik.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-nomadik.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-nomadik.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,11 +63,11 @@
 /* Master controller (MCR) register */
 #define I2C_MCR_OP		(0x1 << 0)	/* Operation */
 #define I2C_MCR_A7		(0x7f << 1)	/* 7-bit address */
-#define I2C_MCR_EA10		(0x7 << 8) 	/* 10-bit Extended address */
+#define I2C_MCR_EA10		(0x7 << 8)	/* 10-bit Extended address */
 #define I2C_MCR_SB		(0x1 << 11)	/* Extended address */
 #define I2C_MCR_AM		(0x3 << 12)	/* Address type */
-#define I2C_MCR_STOP		(0x1 << 14) 	/* Stop condition */
-#define I2C_MCR_LENGTH		(0x7ff << 15) 	/* Transaction length */
+#define I2C_MCR_STOP		(0x1 << 14)	/* Stop condition */
+#define I2C_MCR_LENGTH		(0x7ff << 15)	/* Transaction length */
 
 /* Status register (SR) */
 #define I2C_SR_OP		(0x3 << 0)	/* Operation */
@@ -77,7 +77,7 @@
 #define I2C_SR_LENGTH		(0x7ff << 9)	/* Transfer length */
 
 /* Interrupt mask set/clear (IMSCR) bits */
-#define I2C_IT_TXFE 		(0x1 << 0)
+#define I2C_IT_TXFE		(0x1 << 0)
 #define I2C_IT_TXFNE		(0x1 << 1)
 #define I2C_IT_TXFF		(0x1 << 2)
 #define I2C_IT_TXFOVR		(0x1 << 3)
@@ -135,31 +135,31 @@ struct i2c_nmk_client {
 };
 
 /**
- * struct nmk_i2c_dev - private data structure of the controller
- * @pdev: parent platform device
- * @adap: corresponding I2C adapter
- * @irq: interrupt line for the controller
- * @virtbase: virtual io memory area
- * @clk: hardware i2c block clock
- * @cfg: machine provided controller configuration
- * @cli: holder of client specific data
- * @stop: stop condition
- * @xfer_complete: acknowledge completion for a I2C message
- * @result: controller propogated result
- * @regulator: pointer to i2c regulator
- * @busy: Busy doing transfer
+ * struct nmk_i2c_dev - private data structure of the controller.
+ * @pdev: parent platform device.
+ * @adap: corresponding I2C adapter.
+ * @irq: interrupt line for the controller.
+ * @virtbase: virtual io memory area.
+ * @clk: hardware i2c block clock.
+ * @cfg: machine provided controller configuration.
+ * @cli: holder of client specific data.
+ * @stop: stop condition.
+ * @xfer_complete: acknowledge completion for a I2C message.
+ * @result: controller propogated result.
+ * @regulator: pointer to i2c regulator.
+ * @busy: Busy doing transfer.
  */
 struct nmk_i2c_dev {
 	struct platform_device		*pdev;
-	struct i2c_adapter 		adap;
-	int 				irq;
+	struct i2c_adapter		adap;
+	int				irq;
 	void __iomem			*virtbase;
 	struct clk			*clk;
 	struct nmk_i2c_controller	cfg;
 	struct i2c_nmk_client		cli;
-	int 				stop;
+	int				stop;
 	struct completion		xfer_complete;
-	int 				result;
+	int				result;
 	struct regulator		*regulator;
 	bool				busy;
 };
@@ -217,8 +217,9 @@ static int flush_i2c_fifo(struct nmk_i2c
 		}
 	}
 
-	dev_err(&dev->pdev->dev, "flushing operation timed out "
-		"giving up after %d attempts", LOOP_ATTEMPTS);
+	dev_err(&dev->pdev->dev,
+		"flushing operation timed out giving up after %d attempts",
+		LOOP_ATTEMPTS);
 
 	return -ETIMEDOUT;
 }
@@ -270,7 +271,7 @@ exit:
 }
 
 /* enable peripheral, master mode operation */
-#define DEFAULT_I2C_REG_CR 	((1 << 1) | I2C_CR_PE)
+#define DEFAULT_I2C_REG_CR	((1 << 1) | I2C_CR_PE)
 
 /**
  * load_i2c_mcr_reg() - load the MCR register
@@ -363,8 +364,8 @@ static void setup_i2c_controller(struct
 	 * and high speed (up to 3.4 Mb/s)
 	 */
 	if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
-		dev_err(&dev->pdev->dev, "do not support this mode "
-			"defaulting to std. mode\n");
+		dev_err(&dev->pdev->dev,
+			"do not support this mode defaulting to std. mode\n");
 		brcr2 = i2c_clk/(100000 * 2) & 0xffff;
 		writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
 		writel(I2C_FREQ_MODE_STANDARD << 4,
@@ -423,7 +424,7 @@ static int read_i2c(struct nmk_i2c_dev *
 
 	if (timeout < 0) {
 		dev_err(&dev->pdev->dev,
-			"wait_for_completion_timeout"
+			"wait_for_completion_timeout "
 			"returned %d waiting for event\n", timeout);
 		status = timeout;
 	}
@@ -556,8 +557,8 @@ static int nmk_i2c_xfer_one(struct nmk_i
 		if (((i2c_sr >> 2) & 0x3) == 0x3) {
 			/* get the abort cause */
 			cause =	(i2c_sr >> 4) & 0x7;
-			dev_err(&dev->pdev->dev, "%s\n", cause
-				>= ARRAY_SIZE(abort_causes) ?
+			dev_err(&dev->pdev->dev, "%s\n",
+				cause >= ARRAY_SIZE(abort_causes) ?
 				"unknown reason" :
 				abort_causes[cause]);
 		}
@@ -582,13 +583,13 @@ static int nmk_i2c_xfer_one(struct nmk_i
  *
  * NOTE:
  * READ TRANSFER : We impose a restriction of the first message to be the
- * 		index message for any read transaction.
- * 		- a no index is coded as '0',
- * 		- 2byte big endian index is coded as '3'
- * 		!!! msg[0].buf holds the actual index.
- * 		This is compatible with generic messages of smbus emulator
- * 		that send a one byte index.
- * 		eg. a I2C transation to read 2 bytes from index 0
+ *		index message for any read transaction.
+ *		- a no index is coded as '0',
+ *		- 2byte big endian index is coded as '3'
+ *		!!! msg[0].buf holds the actual index.
+ *		This is compatible with generic messages of smbus emulator
+ *		that send a one byte index.
+ *		eg. a I2C transation to read 2 bytes from index 0
  *			idx = 0;
  *			msg[0].addr = client->addr;
  *			msg[0].flags = 0x0;
@@ -644,8 +645,8 @@ static int nmk_i2c_xfer(struct i2c_adapt
 
 		for (i = 0; i < num_msgs; i++) {
 			if (unlikely(msgs[i].flags & I2C_M_TEN)) {
-				dev_err(&dev->pdev->dev, "10 bit addressing"
-						"not supported\n");
+				dev_err(&dev->pdev->dev,
+					"10 bit addressing not supported\n");
 
 				status = -EINVAL;
 				goto out;
@@ -789,8 +790,9 @@ static irqreturn_t i2c_irq_handler(int i
 
 		if (dev->cli.count) {
 			dev->result = -EIO;
-			dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
-					"xfered\n", dev->cli.count);
+			dev_err(&dev->pdev->dev,
+				"%lu bytes still remain to be xfered\n",
+				dev->cli.count);
 			(void) init_hw(dev);
 		}
 		complete(&dev->xfer_complete);
@@ -923,7 +925,7 @@ static int __devinit nmk_i2c_probe(struc
 	}
 
 	if (request_mem_region(res->start, resource_size(res),
-		DRIVER_NAME "I/O region") == 	NULL)	{
+		DRIVER_NAME "I/O region") == NULL) {
 		ret = -EBUSY;
 		goto err_no_region;
 	}
@@ -935,7 +937,7 @@ static int __devinit nmk_i2c_probe(struc
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+	ret = request_irq(dev->irq, i2c_irq_handler, 0,
 				DRIVER_NAME, dev);
 	if (ret) {
 		dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
@@ -980,8 +982,9 @@ static int __devinit nmk_i2c_probe(struc
 
 	i2c_set_adapdata(adap, dev);
 
-	dev_info(&pdev->dev, "initialize %s on virtual "
-		"base %p\n", adap->name, dev->virtbase);
+	dev_info(&pdev->dev,
+		 "initialize %s on virtual base %p\n",
+		 adap->name, dev->virtbase);
 
 	ret = i2c_add_numbered_adapter(adap);
 	if (ret) {
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-nuc900.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-nuc900.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-nuc900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-nuc900.c	2012-01-04 18:55:44.000000000 -0500
@@ -593,7 +593,7 @@ static int __devinit nuc900_i2c_probe(st
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &pdev->dev;
 
-	mfp_set_groupg(&pdev->dev);
+	mfp_set_groupg(&pdev->dev, NULL);
 
 	clk_get_rate(i2c->clk);
 
@@ -610,7 +610,7 @@ static int __devinit nuc900_i2c_probe(st
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED,
+	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-omap.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-omap.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-omap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-omap.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,12 +42,12 @@
 #include <linux/pm_runtime.h>
 
 /* I2C controller revisions */
-#define OMAP_I2C_REV_2			0x20
+#define OMAP_I2C_OMAP1_REV_2		0x20
 
 /* I2C controller revisions present on specific hardware */
 #define OMAP_I2C_REV_ON_2430		0x36
 #define OMAP_I2C_REV_ON_3430		0x3C
-#define OMAP_I2C_REV_ON_4430		0x40
+#define OMAP_I2C_REV_ON_3530_4430	0x40
 
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -72,11 +72,12 @@ enum {
 	OMAP_I2C_SCLH_REG,
 	OMAP_I2C_SYSTEST_REG,
 	OMAP_I2C_BUFSTAT_REG,
-	OMAP_I2C_REVNB_LO,
-	OMAP_I2C_REVNB_HI,
-	OMAP_I2C_IRQSTATUS_RAW,
-	OMAP_I2C_IRQENABLE_SET,
-	OMAP_I2C_IRQENABLE_CLR,
+	/* only on OMAP4430 */
+	OMAP_I2C_IP_V2_REVNB_LO,
+	OMAP_I2C_IP_V2_REVNB_HI,
+	OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+	OMAP_I2C_IP_V2_IRQENABLE_SET,
+	OMAP_I2C_IP_V2_IRQENABLE_CLR,
 };
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
@@ -193,7 +194,6 @@ struct omap_i2c_dev {
 						 */
 	u8			rev;
 	unsigned		b_hw:1;		/* bad h/w fixes */
-	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt register */
 	u16			pscstate;
 	u16			scllstate;
@@ -204,7 +204,7 @@ struct omap_i2c_dev {
 	u16			errata;
 };
 
-static const u8 reg_map[] = {
+static const u8 reg_map_ip_v1[] = {
 	[OMAP_I2C_REV_REG] = 0x00,
 	[OMAP_I2C_IE_REG] = 0x01,
 	[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@ static const u8 reg_map[] = {
 	[OMAP_I2C_BUFSTAT_REG] = 0x10,
 };
 
-static const u8 omap4_reg_map[] = {
+static const u8 reg_map_ip_v2[] = {
 	[OMAP_I2C_REV_REG] = 0x04,
 	[OMAP_I2C_IE_REG] = 0x2c,
 	[OMAP_I2C_STAT_REG] = 0x28,
@@ -244,11 +244,11 @@ static const u8 omap4_reg_map[] = {
 	[OMAP_I2C_SCLH_REG] = 0xb8,
 	[OMAP_I2C_SYSTEST_REG] = 0xbC,
 	[OMAP_I2C_BUFSTAT_REG] = 0xc0,
-	[OMAP_I2C_REVNB_LO] = 0x00,
-	[OMAP_I2C_REVNB_HI] = 0x04,
-	[OMAP_I2C_IRQSTATUS_RAW] = 0x24,
-	[OMAP_I2C_IRQENABLE_SET] = 0x2c,
-	[OMAP_I2C_IRQENABLE_CLR] = 0x30,
+	[OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+	[OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+	[OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+	[OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+	[OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -266,17 +266,11 @@ static inline u16 omap_i2c_read_reg(stru
 
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 
-	WARN_ON(!dev->idle);
-
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
-
-	pm_runtime_get_sync(&pdev->dev);
+	pdata = dev->dev->platform_data;
 
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -286,7 +280,6 @@ static void omap_i2c_unidle(struct omap_
 		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 	}
-	dev->idle = 0;
 
 	/*
 	 * Don't write to this register if the IE state is 0 as it can
@@ -298,32 +291,25 @@ static void omap_i2c_unidle(struct omap_
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 	u16 iv;
 
-	WARN_ON(dev->idle);
-
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
+	pdata = dev->dev->platform_data;
 
 	dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-	if (dev->rev >= OMAP_I2C_REV_ON_4430)
-		omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
 	else
 		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
 
-	if (dev->rev < OMAP_I2C_REV_2) {
+	if (dev->rev < OMAP_I2C_OMAP1_REV_2) {
 		iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
 	} else {
 		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
 
-		/* Flush posted write before the dev->idle store occurs */
+		/* Flush posted write */
 		omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
 	}
-	dev->idle = 1;
-
-	pm_runtime_put_sync(&pdev->dev);
 }
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -334,8 +320,11 @@ static int omap_i2c_init(struct omap_i2c
 	unsigned long timeout;
 	unsigned long internal_clk = 0;
 	struct clk *fclk;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (dev->rev >= OMAP_I2C_REV_2) {
+	pdata = dev->dev->platform_data;
+
+	if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
 		/* Disable I2C controller before soft reset */
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
 			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@@ -378,12 +367,13 @@ static int omap_i2c_init(struct omap_i2c
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
 			dev->westate = OMAP_I2C_WE_ALL;
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+							dev->westate);
 		}
 	}
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
-	if (cpu_class_is_omap1()) {
+	if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
 		/*
 		 * The I2C functional clock is the armxor_ck, so there's
 		 * no need to get "armxor_ck" separately.  Now, if OMAP2420
@@ -407,7 +397,7 @@ static int omap_i2c_init(struct omap_i2c
 			psc = fclk_rate / 12000000;
 	}
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
 
 		/*
 		 * HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -415,7 +405,8 @@ static int omap_i2c_init(struct omap_i2c
 		 * to get longer filter period for better noise suppression.
 		 * The filter is iclk (fclk for HS) period.
 		 */
-		if (dev->speed > 400 || cpu_is_omap2430())
+		if (dev->speed > 400 ||
+			       pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
 			internal_clk = 19200;
 		else if (dev->speed > 100)
 			internal_clk = 9600;
@@ -484,7 +475,7 @@ static int omap_i2c_init(struct omap_i2c
 
 	dev->errata = 0;
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
+	if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
 		dev->errata |= I2C_OMAP_ERRATA_I207;
 
 	/* Enable interrupts */
@@ -493,7 +484,7 @@ static int omap_i2c_init(struct omap_i2c
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
 				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
 	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		dev->pscstate = psc;
 		dev->scllstate = scll;
 		dev->sclhstate = sclh;
@@ -642,7 +633,7 @@ omap_i2c_xfer(struct i2c_adapter *adap,
 	int i;
 	int r;
 
-	omap_i2c_unidle(dev);
+	pm_runtime_get_sync(dev->dev);
 
 	r = omap_i2c_wait_for_bb(dev);
 	if (r < 0)
@@ -665,7 +656,7 @@ omap_i2c_xfer(struct i2c_adapter *adap,
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	return r;
 }
 
@@ -720,12 +711,12 @@ static inline void i2c_omap_errata_i207(
 #ifdef CONFIG_ARCH_OMAP15XX
 
 static irqreturn_t
-omap_i2c_rev1_isr(int this_irq, void *dev_id)
+omap_i2c_omap1_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
 	u16 iv, w;
 
-	if (dev->idle)
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
@@ -774,7 +765,7 @@ omap_i2c_rev1_isr(int this_irq, void *de
 	return IRQ_HANDLED;
 }
 #else
-#define omap_i2c_rev1_isr		NULL
+#define omap_i2c_omap1_isr		NULL
 #endif
 
 /*
@@ -813,8 +804,11 @@ omap_i2c_isr(int this_irq, void *dev_id)
 	u16 bits;
 	u16 stat, w;
 	int err, count = 0;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (dev->idle)
+	pdata = dev->dev->platform_data;
+
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
@@ -881,8 +875,8 @@ complete:
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							*dev->buf++ = w >> 8;
 							dev->buf_len--;
@@ -924,8 +918,8 @@ complete:
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							w |= *dev->buf++ << 8;
 							dev->buf_len--;
@@ -1016,7 +1010,6 @@ omap_i2c_probe(struct platform_device *p
 	}
 
 	dev->speed = speed;
-	dev->idle = 1;
 	dev->dev = &pdev->dev;
 	dev->irq = irq->start;
 	dev->base = ioremap(mem->start, resource_size(mem));
@@ -1027,27 +1020,22 @@ omap_i2c_probe(struct platform_device *p
 
 	platform_set_drvdata(pdev, dev);
 
-	if (cpu_is_omap7xx())
-		dev->reg_shift = 1;
-	else if (cpu_is_omap44xx())
-		dev->reg_shift = 0;
-	else
-		dev->reg_shift = 2;
+	dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
 
-	if (cpu_is_omap44xx())
-		dev->regs = (u8 *) omap4_reg_map;
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		dev->regs = (u8 *)reg_map_ip_v2;
 	else
-		dev->regs = (u8 *) reg_map;
+		dev->regs = (u8 *)reg_map_ip_v1;
 
-	pm_runtime_enable(&pdev->dev);
-	omap_i2c_unidle(dev);
+	pm_runtime_enable(dev->dev);
+	pm_runtime_get_sync(dev->dev);
 
 	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
 
 	if (dev->rev <= OMAP_I2C_REV_ON_3430)
 		dev->errata |= I2C_OMAP3_1P153;
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
 		u16 s;
 
 		/* Set up the fifo size - Get total size */
@@ -1059,13 +1047,14 @@ omap_i2c_probe(struct platform_device *p
 		 * size. This is to ensure that we can handle the status on int
 		 * call back latencies.
 		 */
-		if (dev->rev >= OMAP_I2C_REV_ON_4430) {
-			dev->fifo_size = 0;
+
+		dev->fifo_size = (dev->fifo_size / 2);
+
+		if (dev->rev >= OMAP_I2C_REV_ON_3530_4430)
 			dev->b_hw = 0; /* Disable hardware fixes */
-		} else {
-			dev->fifo_size = (dev->fifo_size / 2);
+		else
 			dev->b_hw = 1; /* Enable hardware fixes */
-		}
+
 		/* calculate wakeup latency constraint for MPU */
 		if (dev->set_mpu_wkup_lat != NULL)
 			dev->latency = (1000000 * dev->fifo_size) /
@@ -1075,7 +1064,8 @@ omap_i2c_probe(struct platform_device *p
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
+								   omap_i2c_isr;
 	r = request_irq(dev->irq, isr, 0, pdev->name, dev);
 
 	if (r) {
@@ -1083,10 +1073,10 @@ omap_i2c_probe(struct platform_device *p
 		goto err_unuse_clocks;
 	}
 
-	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
-		 pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
+		 pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
 
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
@@ -1110,7 +1100,7 @@ err_free_irq:
 	free_irq(dev->irq, dev);
 err_unuse_clocks:
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	iounmap(dev->base);
 err_free_mem:
 	platform_set_drvdata(pdev, NULL);
@@ -1139,12 +1129,43 @@ omap_i2c_remove(struct platform_device *
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int omap_i2c_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_idle(_dev);
+
+	return 0;
+}
+
+static int omap_i2c_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_unidle(_dev);
+
+	return 0;
+}
+
+static struct dev_pm_ops omap_i2c_pm_ops = {
+	.runtime_suspend = omap_i2c_runtime_suspend,
+	.runtime_resume = omap_i2c_runtime_resume,
+};
+#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
+#else
+#define OMAP_I2C_PM_OPS NULL
+#endif
+
 static struct platform_driver omap_i2c_driver = {
 	.probe		= omap_i2c_probe,
 	.remove		= omap_i2c_remove,
 	.driver		= {
 		.name	= "omap_i2c",
 		.owner	= THIS_MODULE,
+		.pm	= OMAP_I2C_PM_OPS,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-pmcmsp.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-pmcmsp.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-pmcmsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-pmcmsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -306,7 +306,7 @@ static int __devinit pmcmsptwi_probe(str
 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
 	if (pmcmsptwi_data.irq) {
 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
-			IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			pldev->name, &pmcmsptwi_data);
 		if (rc == 0) {
 			/*
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-pxa-pci.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-pxa-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-pxa-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,7 @@
  * It does not support slave mode, the register slightly moved. This PCI
  * device provides three bars, every contains a single I2C controller.
  */
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/pxa-i2c.h>
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-s3c2410.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-s3c2410.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-s3c2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-s3c2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,8 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
 
 #include <asm/irq.h>
 
@@ -78,6 +80,8 @@ struct s3c24xx_i2c {
 	struct resource		*ioarea;
 	struct i2c_adapter	adap;
 
+	struct s3c2410_platform_i2c	*pdata;
+	int			gpios[2];
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
 #endif
@@ -95,6 +99,12 @@ static inline int s3c24xx_i2c_is2440(str
 	struct platform_device *pdev = to_platform_device(i2c->dev);
 	enum s3c24xx_i2c_type type;
 
+#ifdef CONFIG_OF
+	if (i2c->dev->of_node)
+		return of_device_is_compatible(i2c->dev->of_node,
+				"samsung,s3c2440-i2c");
+#endif
+
 	type = platform_get_device_id(pdev)->driver_data;
 	return type == TYPE_S3C2440;
 }
@@ -524,6 +534,7 @@ static int s3c24xx_i2c_doxfer(struct s3c
 
 	/* first, try busy waiting briefly */
 	do {
+		cpu_relax();
 		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
 	} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
 
@@ -625,7 +636,7 @@ static int s3c24xx_i2c_calcdivisor(unsig
 
 static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
-	struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
 	unsigned long clkin = clk_get_rate(i2c->clk);
 	unsigned int divs, div1;
 	unsigned long target_frequency;
@@ -741,6 +752,49 @@ static inline void s3c24xx_i2c_deregiste
 }
 #endif
 
+#ifdef CONFIG_OF
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	int idx, gpio, ret;
+
+	for (idx = 0; idx < 2; idx++) {
+		gpio = of_get_gpio(i2c->dev->of_node, idx);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
+			goto free_gpio;
+		}
+
+		ret = gpio_request(gpio, "i2c-bus");
+		if (ret) {
+			dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
+			goto free_gpio;
+		}
+	}
+	return 0;
+
+free_gpio:
+	while (--idx >= 0)
+		gpio_free(i2c->gpios[idx]);
+	return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+	unsigned int idx;
+	for (idx = 0; idx < 2; idx++)
+		gpio_free(i2c->gpios[idx]);
+}
+#else
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	return 0;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
 /* s3c24xx_i2c_init
  *
  * initialise the controller, set the IO lines and frequency
@@ -754,12 +808,15 @@ static int s3c24xx_i2c_init(struct s3c24
 
 	/* get the plafrom data */
 
-	pdata = i2c->dev->platform_data;
+	pdata = i2c->pdata;
 
 	/* inititalise the gpio */
 
 	if (pdata->cfg_gpio)
 		pdata->cfg_gpio(to_platform_device(i2c->dev));
+	else
+		if (s3c24xx_i2c_parse_dt_gpio(i2c))
+			return -EINVAL;
 
 	/* write slave address */
 
@@ -785,6 +842,34 @@ static int s3c24xx_i2c_init(struct s3c24
 	return 0;
 }
 
+#ifdef CONFIG_OF
+/* s3c24xx_i2c_parse_dt
+ *
+ * Parse the device tree node and retreive the platform data.
+*/
+
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
+
+	if (!np)
+		return;
+
+	pdata->bus_num = -1; /* i2c bus number is dynamically assigned */
+	of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay);
+	of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr);
+	of_property_read_u32(np, "samsung,i2c-max-bus-freq",
+				(u32 *)&pdata->frequency);
+}
+#else
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	return;
+}
+#endif
+
 /* s3c24xx_i2c_probe
  *
  * called by the bus driver when a suitable device is found
@@ -793,14 +878,16 @@ static int s3c24xx_i2c_init(struct s3c24
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c;
-	struct s3c2410_platform_i2c *pdata;
+	struct s3c2410_platform_i2c *pdata = NULL;
 	struct resource *res;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data\n");
-		return -EINVAL;
+	if (!pdev->dev.of_node) {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "no platform data\n");
+			return -EINVAL;
+		}
 	}
 
 	i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
@@ -809,6 +896,17 @@ static int s3c24xx_i2c_probe(struct plat
 		return -ENOMEM;
 	}
 
+	i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!i2c->pdata) {
+		ret = -ENOMEM;
+		goto err_noclk;
+	}
+
+	if (pdata)
+		memcpy(i2c->pdata, pdata, sizeof(*pdata));
+	else
+		s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
+
 	strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
 	i2c->adap.owner   = THIS_MODULE;
 	i2c->adap.algo    = &s3c24xx_i2c_algorithm;
@@ -883,7 +981,7 @@ static int s3c24xx_i2c_probe(struct plat
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
@@ -903,7 +1001,8 @@ static int s3c24xx_i2c_probe(struct plat
 	 * being bus 0.
 	 */
 
-	i2c->adap.nr = pdata->bus_num;
+	i2c->adap.nr = i2c->pdata->bus_num;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
@@ -911,6 +1010,7 @@ static int s3c24xx_i2c_probe(struct plat
 		goto err_cpufreq;
 	}
 
+	of_i2c_register_devices(&i2c->adap);
 	platform_set_drvdata(pdev, i2c);
 
 	dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
@@ -959,6 +1059,7 @@ static int s3c24xx_i2c_remove(struct pla
 	iounmap(i2c->regs);
 
 	release_resource(i2c->ioarea);
+	s3c24xx_i2c_dt_gpio_free(i2c);
 	kfree(i2c->ioarea);
 	kfree(i2c);
 
@@ -1012,6 +1113,17 @@ static struct platform_device_id s3c24xx
 };
 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c24xx_i2c_match[] = {
+	{ .compatible = "samsung,s3c2410-i2c" },
+	{ .compatible = "samsung,s3c2440-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
+#else
+#define s3c24xx_i2c_match NULL
+#endif
+
 static struct platform_driver s3c24xx_i2c_driver = {
 	.probe		= s3c24xx_i2c_probe,
 	.remove		= s3c24xx_i2c_remove,
@@ -1020,6 +1132,7 @@ static struct platform_driver s3c24xx_i2
 		.owner	= THIS_MODULE,
 		.name	= "s3c-i2c",
 		.pm	= S3C24XX_DEV_PM_OPS,
+		.of_match_table = s3c24xx_i2c_match,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-sh7760.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-sh7760.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-sh7760.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-sh7760.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <asm/clock.h>
 #include <asm/i2c-sh7760.h>
@@ -502,7 +503,7 @@ static int __devinit sh7760_i2c_probe(st
 	}
 	OUT32(id, I2CCCR, ret);
 
-	if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
+	if (request_irq(id->irq, sh7760_i2c_irq, 0,
 			SH7760_I2C_DEVNAME, id)) {
 		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
 		ret = -EBUSY;
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-sh_mobile.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-sh_mobile.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-sh_mobile.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-sh_mobile.c	2012-01-04 18:55:44.000000000 -0500
@@ -543,7 +543,7 @@ static int sh_mobile_i2c_hook_irqs(struc
 
 	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
 		for (n = res->start; hook && n <= res->end; n++) {
-			if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
+			if (request_irq(n, sh_mobile_i2c_isr, 0,
 					dev_name(&dev->dev), dev)) {
 				for (n--; n >= res->start; n--)
 					free_irq(n, dev);
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-stu300.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-stu300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-stu300.c	2012-01-04 18:55:44.000000000 -0500
@@ -916,7 +916,7 @@ stu300_probe(struct platform_device *pde
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED,
+	if (request_irq(dev->irq, stu300_irh, 0,
 			NAME, dev)) {
 		ret = -EIO;
 		goto err_no_irq;
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-tegra.c linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/i2c-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/i2c-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-tegra.h>
 #include <linux/of_i2c.h>
+#include <linux/module.h>
 
 #include <asm/unaligned.h>
 
@@ -566,7 +567,7 @@ static int tegra_i2c_probe(struct platfo
 	struct clk *clk;
 	struct clk *i2c_clk;
 	const unsigned int *prop;
-	void *base;
+	void __iomem *base;
 	int irq;
 	int ret = 0;
 
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/Kconfig linux-libre-3.2-gnu1/drivers/i2c/busses/Kconfig
--- linux-libre-3.1-gnu1/drivers/i2c/busses/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,6 @@ config I2C_I801
 config I2C_ISCH
 	tristate "Intel SCH SMBus 1.0"
 	depends on PCI
-	select MFD_CORE
 	select LPC_SCH
 	help
 	  Say Y here if you want to use SMBus controller on the Intel SCH
@@ -301,7 +300,7 @@ config I2C_AT91
 
 config I2C_AU1550
 	tristate "Au1550/Au1200 SMBus interface"
-	depends on SOC_AU1550 || SOC_AU1200
+	depends on MIPS_ALCHEMY
 	help
 	  If you say yes to this option, support will be included for the
 	  Au1550 and Au1200 SMBus interface.
@@ -350,15 +349,25 @@ config I2C_DAVINCI
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
-config I2C_DESIGNWARE
-	tristate "Synopsys DesignWare"
+config I2C_DESIGNWARE_PLATFORM
+	tristate "Synopsys DesignWare Platfrom"
 	depends on HAVE_CLK
 	help
 	  If you say yes to this option, support will be included for the
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-designware.
+	  will be called i2c-designware-platform.
+
+config I2C_DESIGNWARE_PCI
+	tristate "Synopsys DesignWare PCI"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware-pci.
 
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
@@ -789,7 +798,7 @@ config I2C_ACORN
 
 config I2C_ELEKTOR
 	tristate "Elektor ISA card"
-	depends on ISA && BROKEN_ON_SMP
+	depends on ISA && HAS_IOPORT && BROKEN_ON_SMP
 	select I2C_ALGOPCF
 	help
 	  This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/Makefile linux-libre-3.2-gnu1/drivers/i2c/busses/Makefile
--- linux-libre-3.1-gnu1/drivers/i2c/busses/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,10 @@ obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/busses/scx200_acb.c linux-libre-3.2-gnu1/drivers/i2c/busses/scx200_acb.c
--- linux-libre-3.1-gnu1/drivers/i2c/busses/scx200_acb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/busses/scx200_acb.c	2012-01-04 18:55:44.000000000 -0500
@@ -550,7 +550,7 @@ static int __devexit scx200_remove(struc
 	return 0;
 }
 
-static struct platform_driver scx200_pci_drv = {
+static struct platform_driver scx200_pci_driver = {
 	.driver = {
 		.name = "cs5535-smb",
 		.owner = THIS_MODULE,
@@ -593,14 +593,14 @@ static int __init scx200_acb_init(void)
 		return 0;
 
 	/* No ISA devices; register the platform driver for PCI-based devices */
-	return platform_driver_register(&scx200_pci_drv);
+	return platform_driver_register(&scx200_pci_driver);
 }
 
 static void __exit scx200_acb_cleanup(void)
 {
 	struct scx200_acb_iface *iface;
 
-	platform_driver_unregister(&scx200_pci_drv);
+	platform_driver_unregister(&scx200_pci_driver);
 
 	mutex_lock(&scx200_acb_list_mutex);
 	while ((iface = scx200_acb_list) != NULL) {
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/i2c-boardinfo.c linux-libre-3.2-gnu1/drivers/i2c/i2c-boardinfo.c
--- linux-libre-3.1-gnu1/drivers/i2c/i2c-boardinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/i2c-boardinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/rwsem.h>
 
 #include "i2c-core.h"
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/i2c-core.c linux-libre-3.2-gnu1/drivers/i2c/i2c-core.c
--- linux-libre-3.1-gnu1/drivers/i2c/i2c-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/i2c-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -539,8 +539,10 @@ i2c_new_device(struct i2c_adapter *adap,
 	client->dev.type = &i2c_client_type;
 	client->dev.of_node = info->of_node;
 
+	/* For 10-bit clients, add an arbitrary offset to avoid collisions */
 	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-		     client->addr);
+		     client->addr | ((client->flags & I2C_CLIENT_TEN)
+				     ? 0xa000 : 0));
 	status = device_register(&client->dev);
 	if (status)
 		goto out_err;
diff -druNp linux-libre-3.1-gnu1/drivers/i2c/i2c-dev.c linux-libre-3.2-gnu1/drivers/i2c/i2c-dev.c
--- linux-libre-3.1-gnu1/drivers/i2c/i2c-dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/i2c/i2c-dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -579,7 +579,7 @@ static int i2cdev_detach_adapter(struct
 	return 0;
 }
 
-int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
 			 void *data)
 {
 	struct device *dev = data;
diff -druNp linux-libre-3.1-gnu1/drivers/ide/at91_ide.c linux-libre-3.2-gnu1/drivers/ide/at91_ide.c
--- linux-libre-3.1-gnu1/drivers/ide/at91_ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/at91_ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #define DRV_NAME "at91_ide"
diff -druNp linux-libre-3.1-gnu1/drivers/ide/au1xxx-ide.c linux-libre-3.2-gnu1/drivers/ide/au1xxx-ide.c
--- linux-libre-3.1-gnu1/drivers/ide/au1xxx-ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/au1xxx-ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,13 +36,17 @@
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1xxx_ide.h>
 
 #define DRV_NAME	"au1200-ide"
 #define DRV_AUTHOR	"Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
 
+#ifndef IDE_REG_SHIFT
+#define IDE_REG_SHIFT 5
+#endif
+
 /* enable the burstmode in the dbdma */
 #define IDE_AU1XXX_BURSTMODE	1
 
@@ -317,10 +321,11 @@ static void auide_ddma_rx_callback(int i
 }
 #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
 
-static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags)
+static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize,
+				 u32 devwidth, u32 flags, u32 regbase)
 {
 	dev->dev_id          = dev_id;
-	dev->dev_physaddr    = (u32)IDE_PHYS_ADDR;
+	dev->dev_physaddr    = CPHYSADDR(regbase);
 	dev->dev_intlevel    = 0;
 	dev->dev_intpolarity = 0;
 	dev->dev_tsize       = tsize;
@@ -344,7 +349,7 @@ static int auide_ddma_init(ide_hwif_t *h
 	dbdev_tab_t source_dev_tab, target_dev_tab;
 	u32 dev_id, tsize, devwidth, flags;
 
-	dev_id	 = IDE_DDMA_REQ;
+	dev_id	 = hwif->ddma_id;
 
 	tsize    =  8; /*  1 */
 	devwidth = 32; /* 16 */
@@ -356,20 +361,17 @@ static int auide_ddma_init(ide_hwif_t *h
 #endif
 
 	/* setup dev_tab for tx channel */
-	auide_init_dbdma_dev( &source_dev_tab,
-			      dev_id,
-			      tsize, devwidth, DEV_FLAGS_OUT | flags);
+	auide_init_dbdma_dev(&source_dev_tab, dev_id, tsize, devwidth,
+			     DEV_FLAGS_OUT | flags, auide->regbase);
  	auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 
-	auide_init_dbdma_dev( &source_dev_tab,
-			      dev_id,
-			      tsize, devwidth, DEV_FLAGS_IN | flags);
+	auide_init_dbdma_dev(&source_dev_tab, dev_id, tsize, devwidth,
+			     DEV_FLAGS_IN | flags, auide->regbase);
  	auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 	
 	/* We also need to add a target device for the DMA */
-	auide_init_dbdma_dev( &target_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      tsize, devwidth, DEV_FLAGS_ANYUSE);
+	auide_init_dbdma_dev(&target_dev_tab, (u32)DSCR_CMD0_ALWAYS, tsize,
+			     devwidth, DEV_FLAGS_ANYUSE, auide->regbase);
 	auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab);	
  
 	/* Get a channel for TX */
@@ -411,14 +413,12 @@ static int auide_ddma_init(ide_hwif_t *h
 #endif
 
 	/* setup dev_tab for tx channel */
-	auide_init_dbdma_dev( &source_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      8, 32, DEV_FLAGS_OUT | flags);
+	auide_init_dbdma_dev(&source_dev_tab, (u32)DSCR_CMD0_ALWAYS, 8, 32,
+			     DEV_FLAGS_OUT | flags, auide->regbase);
  	auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 
-	auide_init_dbdma_dev( &source_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      8, 32, DEV_FLAGS_IN | flags);
+	auide_init_dbdma_dev(&source_dev_tab, (u32)DSCR_CMD0_ALWAYS, 8, 32,
+			     DEV_FLAGS_IN | flags, auide->regbase);
  	auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 	
 	/* Get a channel for TX */
@@ -540,6 +540,14 @@ static int au_ide_probe(struct platform_
 		goto out;
 	}
 
+	res = platform_get_resource(dev, IORESOURCE_DMA, 0);
+	if (!res) {
+		pr_debug("%s: no DDMA ID resource\n", DRV_NAME);
+		ret = -ENODEV;
+		goto out;
+	}
+	ahwif->ddma_id = res->start;
+
 	memset(&hw, 0, sizeof(hw));
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
diff -druNp linux-libre-3.1-gnu1/drivers/ide/buddha.c linux-libre-3.2-gnu1/drivers/ide/buddha.c
--- linux-libre-3.1-gnu1/drivers/ide/buddha.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/buddha.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/zorro.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/cmd640.c linux-libre-3.2-gnu1/drivers/ide/cmd640.c
--- linux-libre-3.1-gnu1/drivers/ide/cmd640.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/cmd640.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,6 +105,7 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/cy82c693.c linux-libre-3.2-gnu1/drivers/ide/cy82c693.c
--- linux-libre-3.1-gnu1/drivers/ide/cy82c693.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/cy82c693.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
- *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
  *
  * CYPRESS CY82C693 chipset IDE controller
  *
@@ -90,7 +90,7 @@ static void cy82c693_set_pio_mode(ide_hw
 	u8 time_16, time_8;
 
 	/* select primary or secondary channel */
-	if (hwif->index > 0) {  /* drive is on the secondary channel */
+	if (drive->dn > 1) {  /* drive is on the secondary channel */
 		dev = pci_get_slot(dev->bus, dev->devfn+1);
 		if (!dev) {
 			printk(KERN_ERR "%s: tune_drive: "
@@ -141,7 +141,7 @@ static void cy82c693_set_pio_mode(ide_hw
 		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
 		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
 	}
-	if (hwif->index > 0)
+	if (drive->dn > 1)
 		pci_dev_put(dev);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/icside.c linux-libre-3.2-gnu1/drivers/ide/icside.c
--- linux-libre-3.1-gnu1/drivers/ide/icside.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/icside.c	2012-01-04 18:55:44.000000000 -0500
@@ -521,8 +521,8 @@ icside_register_v6(struct icside_state *
 	if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
 		d.init_dma = icside_dma_init;
 		d.port_ops = &icside_v6_port_ops;
+	} else
 		d.dma_ops = NULL;
-	}
 
 	ret = ide_host_register(host, &d, hws);
 	if (ret)
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-acpi.c linux-libre-3.2-gnu1/drivers/ide/ide-acpi.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/ide.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
+#include <linux/module.h>
 
 #include <acpi/acpi_bus.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-atapi.c linux-libre-3.2-gnu1/drivers/ide/ide-atapi.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-atapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-atapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/cdrom.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/gfp.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-cd.c linux-libre-3.2-gnu1/drivers/ide/ide-cd.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-cd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-cd.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@
 /* For SCSI -> ATAPI command conversion */
 #include <scsi/scsi.h>
 
-#include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-disk_proc.c linux-libre-3.2-gnu1/drivers/ide/ide-disk_proc.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-disk_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-disk_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/seq_file.h>
 
 #include "ide-disk.h"
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-dma.c linux-libre-3.2-gnu1/drivers/ide/ide-dma.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/gfp.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-dma-sff.c linux-libre-3.2-gnu1/drivers/ide/ide-dma-sff.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-dma-sff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-dma-sff.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-eh.c linux-libre-3.2-gnu1/drivers/ide/ide-eh.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-eh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-eh.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/delay.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-floppy.c linux-libre-3.2-gnu1/drivers/ide/ide-floppy.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-floppy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-floppy.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,6 @@
 #include <scsi/scsi_ioctl.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-floppy_proc.c linux-libre-3.2-gnu1/drivers/ide/ide-floppy_proc.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-floppy_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-floppy_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-ioctls.c linux-libre-3.2-gnu1/drivers/ide/ide-ioctls.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-ioctls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-ioctls.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * IDE ioctls handling.
  */
 
+#include <linux/export.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/slab.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-io-std.c linux-libre-3.2-gnu1/drivers/ide/ide-io-std.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-io-std.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-io-std.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 
 #if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-legacy.c linux-libre-3.2-gnu1/drivers/ide/ide-legacy.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 
 static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw,
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-lib.c linux-libre-3.2-gnu1/drivers/ide/ide-lib.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-pnp.c linux-libre-3.2-gnu1/drivers/ide/ide-pnp.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-pnp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-pnp.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/pnp.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #define DRV_NAME "ide-pnp"
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-tape.c linux-libre-3.2-gnu1/drivers/ide/ide-tape.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-tape.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-tape.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,6 @@
 #include <scsi/scsi.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-taskfile.c linux-libre-3.2-gnu1/drivers/ide/ide-taskfile.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-taskfile.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-taskfile.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/ide-xfer-mode.c linux-libre-3.2-gnu1/drivers/ide/ide-xfer-mode.c
--- linux-libre-3.1-gnu1/drivers/ide/ide-xfer-mode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/ide-xfer-mode.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/Kconfig linux-libre-3.2-gnu1/drivers/ide/Kconfig
--- linux-libre-3.1-gnu1/drivers/ide/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -677,19 +677,19 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
 
 config BLK_DEV_IDE_AU1XXX
        bool "IDE for AMD Alchemy Au1200"
-       depends on SOC_AU1200
+       depends on MIPS_ALCHEMY
        select IDE_XFER_MODE
 choice
        prompt "IDE Mode for AMD Alchemy Au1200"
-       default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
-       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+       default BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       depends on BLK_DEV_IDE_AU1XXX
 
 config BLK_DEV_IDE_AU1XXX_PIO_DBDMA
        bool "PIO+DbDMA IDE for AMD Alchemy Au1200"
 
 config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
        bool "MDMA2+DbDMA IDE for AMD Alchemy Au1200"
-       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+       depends on BLK_DEV_IDE_AU1XXX
 endchoice
 
 config BLK_DEV_IDE_TX4938
diff -druNp linux-libre-3.1-gnu1/drivers/ide/macide.c linux-libre-3.2-gnu1/drivers/ide/macide.c
--- linux-libre-3.1-gnu1/drivers/ide/macide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/macide.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #include <asm/macintosh.h>
 #include <asm/macints.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/piix.c linux-libre-3.2-gnu1/drivers/ide/piix.c
--- linux-libre-3.1-gnu1/drivers/ide/piix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/piix.c	2012-01-04 18:55:44.000000000 -0500
@@ -331,7 +331,7 @@ static const struct ide_port_ops ich_por
 		.udma_mask	= udma,			\
 	}
 
-#define DECLARE_ICH_DEV(udma) \
+#define DECLARE_ICH_DEV(mwdma, udma) \
 	{ \
 		.name		= DRV_NAME, \
 		.init_chipset	= init_chipset_ich, \
@@ -340,7 +340,7 @@ static const struct ide_port_ops ich_por
 		.port_ops	= &ich_port_ops, \
 		.pio_mask	= ATA_PIO4, \
 		.swdma_mask	= ATA_SWDMA2_ONLY, \
-		.mwdma_mask	= ATA_MWDMA12_ONLY, \
+		.mwdma_mask	= mwdma, \
 		.udma_mask	= udma, \
 	}
 
@@ -362,13 +362,15 @@ static const struct ide_port_info piix_p
 	/* 2: PIIX4 */
 	DECLARE_PIIX_DEV(ATA_UDMA2),
 	/* 3: ICH0 */
-	DECLARE_ICH_DEV(ATA_UDMA2),
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA2),
 	/* 4: ICH */
-	DECLARE_ICH_DEV(ATA_UDMA4),
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA4),
 	/* 5: PIIX4 */
 	DECLARE_PIIX_DEV(ATA_UDMA4),
-	/* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
-	DECLARE_ICH_DEV(ATA_UDMA5),
+	/* 6: ICH[2-6]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA5),
+	/* 7: ICH7/7-R, no MWDMA1 */
+	DECLARE_ICH_DEV(ATA_MWDMA2_ONLY, ATA_UDMA5),
 };
 
 /**
@@ -438,9 +440,9 @@ static const struct pci_device_id piix_p
 #endif
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    7 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    7 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
 	{ 0, },
 };
diff -druNp linux-libre-3.1-gnu1/drivers/ide/pmac.c linux-libre-3.2-gnu1/drivers/ide/pmac.c
--- linux-libre-3.1-gnu1/drivers/ide/pmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/pmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/notifier.h>
+#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/pci.h>
 #include <linux/adb.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/q40ide.c linux-libre-3.2-gnu1/drivers/ide/q40ide.c
--- linux-libre-3.1-gnu1/drivers/ide/q40ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/q40ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #include <asm/ide.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/setup-pci.c linux-libre-3.2-gnu1/drivers/ide/setup-pci.c
--- linux-libre-3.1-gnu1/drivers/ide/setup-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/setup-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
diff -druNp linux-libre-3.1-gnu1/drivers/ide/tc86c001.c linux-libre-3.2-gnu1/drivers/ide/tc86c001.c
--- linux-libre-3.1-gnu1/drivers/ide/tc86c001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/tc86c001.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #define DRV_NAME "tc86c001"
 
diff -druNp linux-libre-3.1-gnu1/drivers/ide/triflex.c linux-libre-3.2-gnu1/drivers/ide/triflex.c
--- linux-libre-3.1-gnu1/drivers/ide/triflex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/ide/triflex.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,12 +113,26 @@ static const struct pci_device_id trifle
 };
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
+#ifdef CONFIG_PM
+static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	/*
+	 * We must not disable or powerdown the device.
+	 * APM bios refuses to suspend if IDE is not accessible.
+	 */
+	pci_save_state(dev);
+	return 0;
+}
+#else
+#define triflex_ide_pci_suspend NULL
+#endif
+
 static struct pci_driver triflex_pci_driver = {
 	.name		= "TRIFLEX_IDE",
 	.id_table	= triflex_pci_tbl,
 	.probe		= triflex_init_one,
 	.remove		= ide_pci_remove,
-	.suspend	= ide_pci_suspend,
+	.suspend	= triflex_ide_pci_suspend,
 	.resume		= ide_pci_resume,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/idle/intel_idle.c linux-libre-3.2-gnu1/drivers/idle/intel_idle.c
--- linux-libre-3.1-gnu1/drivers/idle/intel_idle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/idle/intel_idle.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,7 @@
 #include <linux/sched.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/module.h>
 #include <asm/mwait.h>
 #include <asm/msr.h>
 
@@ -81,7 +82,8 @@ static unsigned int mwait_substates;
 static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
 
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
+static int intel_idle(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv, int index);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -109,7 +111,6 @@ static struct cpuidle_state nehalem_csta
 	{ /* MWAIT C1 */
 		.name = "C1-NHM",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 3,
 		.target_residency = 6,
@@ -117,7 +118,6 @@ static struct cpuidle_state nehalem_csta
 	{ /* MWAIT C2 */
 		.name = "C3-NHM",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 20,
 		.target_residency = 80,
@@ -125,7 +125,6 @@ static struct cpuidle_state nehalem_csta
 	{ /* MWAIT C3 */
 		.name = "C6-NHM",
 		.desc = "MWAIT 0x20",
-		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 200,
 		.target_residency = 800,
@@ -137,7 +136,6 @@ static struct cpuidle_state snb_cstates[
 	{ /* MWAIT C1 */
 		.name = "C1-SNB",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
 		.target_residency = 1,
@@ -145,7 +143,6 @@ static struct cpuidle_state snb_cstates[
 	{ /* MWAIT C2 */
 		.name = "C3-SNB",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 80,
 		.target_residency = 211,
@@ -153,7 +150,6 @@ static struct cpuidle_state snb_cstates[
 	{ /* MWAIT C3 */
 		.name = "C6-SNB",
 		.desc = "MWAIT 0x20",
-		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 104,
 		.target_residency = 345,
@@ -161,7 +157,6 @@ static struct cpuidle_state snb_cstates[
 	{ /* MWAIT C4 */
 		.name = "C7-SNB",
 		.desc = "MWAIT 0x30",
-		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 109,
 		.target_residency = 345,
@@ -173,7 +168,6 @@ static struct cpuidle_state atom_cstates
 	{ /* MWAIT C1 */
 		.name = "C1-ATM",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
 		.target_residency = 4,
@@ -181,7 +175,6 @@ static struct cpuidle_state atom_cstates
 	{ /* MWAIT C2 */
 		.name = "C2-ATM",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 20,
 		.target_residency = 80,
@@ -190,7 +183,6 @@ static struct cpuidle_state atom_cstates
 	{ /* MWAIT C4 */
 		.name = "C4-ATM",
 		.desc = "MWAIT 0x30",
-		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 100,
 		.target_residency = 400,
@@ -199,23 +191,55 @@ static struct cpuidle_state atom_cstates
 	{ /* MWAIT C6 */
 		.name = "C6-ATM",
 		.desc = "MWAIT 0x52",
-		.driver_data = (void *) 0x52,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 140,
 		.target_residency = 560,
 		.enter = &intel_idle },
 };
 
+static int get_driver_data(int cstate)
+{
+	int driver_data;
+	switch (cstate) {
+
+	case 1:	/* MWAIT C1 */
+		driver_data = 0x00;
+		break;
+	case 2:	/* MWAIT C2 */
+		driver_data = 0x10;
+		break;
+	case 3:	/* MWAIT C3 */
+		driver_data = 0x20;
+		break;
+	case 4:	/* MWAIT C4 */
+		driver_data = 0x30;
+		break;
+	case 5:	/* MWAIT C5 */
+		driver_data = 0x40;
+		break;
+	case 6:	/* MWAIT C6 */
+		driver_data = 0x52;
+		break;
+	default:
+		driver_data = 0x00;
+	}
+	return driver_data;
+}
+
 /**
  * intel_idle
  * @dev: cpuidle_device
- * @state: cpuidle state
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
  *
  */
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+static int intel_idle(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index)
 {
 	unsigned long ecx = 1; /* break on interrupt flag */
-	unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+	struct cpuidle_state *state = &drv->states[index];
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
 	unsigned int cstate;
 	ktime_t kt_before, kt_after;
 	s64 usec_delta;
@@ -256,7 +280,10 @@ static int intel_idle(struct cpuidle_dev
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
-	return usec_delta;
+	/* Update cpuidle counters */
+	dev->last_residency = (int)usec_delta;
+
+	return index;
 }
 
 static void __setup_broadcast_timer(void *arg)
@@ -397,6 +424,60 @@ static void intel_idle_cpuidle_devices_u
 	return;
 }
 /*
+ * intel_idle_cpuidle_driver_init()
+ * allocate, initialize cpuidle_states
+ */
+static int intel_idle_cpuidle_driver_init(void)
+{
+	int cstate;
+	struct cpuidle_driver *drv = &intel_idle_driver;
+
+	drv->state_count = 1;
+
+	for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+		int num_substates;
+
+		if (cstate > max_cstate) {
+			printk(PREFIX "max_cstate %d reached\n",
+				max_cstate);
+			break;
+		}
+
+		/* does the state exist in CPUID.MWAIT? */
+		num_substates = (mwait_substates >> ((cstate) * 4))
+					& MWAIT_SUBSTATE_MASK;
+		if (num_substates == 0)
+			continue;
+		/* is the state not enabled? */
+		if (cpuidle_state_table[cstate].enter == NULL) {
+			/* does the driver not know about the state? */
+			if (*cpuidle_state_table[cstate].name == '\0')
+				pr_debug(PREFIX "unaware of model 0x%x"
+					" MWAIT %d please"
+					" contact lenb@kernel.org",
+				boot_cpu_data.x86_model, cstate);
+			continue;
+		}
+
+		if ((cstate > 2) &&
+			!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+			mark_tsc_unstable("TSC halts in idle"
+					" states deeper than C2");
+
+		drv->states[drv->state_count] =	/* structure copy */
+			cpuidle_state_table[cstate];
+
+		drv->state_count += 1;
+	}
+
+	if (auto_demotion_disable_flags)
+		smp_call_function(auto_demotion_disable, NULL, 1);
+
+	return 0;
+}
+
+
+/*
  * intel_idle_cpuidle_devices_init()
  * allocate, initialize, register cpuidle_devices
  */
@@ -430,22 +511,11 @@ static int intel_idle_cpuidle_devices_in
 				continue;
 			/* is the state not enabled? */
 			if (cpuidle_state_table[cstate].enter == NULL) {
-				/* does the driver not know about the state? */
-				if (*cpuidle_state_table[cstate].name == '\0')
-					pr_debug(PREFIX "unaware of model 0x%x"
-						" MWAIT %d please"
-						" contact lenb@kernel.org",
-					boot_cpu_data.x86_model, cstate);
 				continue;
 			}
 
-			if ((cstate > 2) &&
-				!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
-				mark_tsc_unstable("TSC halts in idle"
-					" states deeper than C2");
-
-			dev->states[dev->state_count] =	/* structure copy */
-				cpuidle_state_table[cstate];
+			dev->states_usage[dev->state_count].driver_data =
+				(void *)get_driver_data(cstate);
 
 			dev->state_count += 1;
 		}
@@ -458,8 +528,6 @@ static int intel_idle_cpuidle_devices_in
 			return -EIO;
 		}
 	}
-	if (auto_demotion_disable_flags)
-		smp_call_function(auto_demotion_disable, NULL, 1);
 
 	return 0;
 }
@@ -477,6 +545,7 @@ static int __init intel_idle_init(void)
 	if (retval)
 		return retval;
 
+	intel_idle_cpuidle_driver_init();
 	retval = cpuidle_register_driver(&intel_idle_driver);
 	if (retval) {
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/addr.c linux-libre-3.2-gnu1/drivers/infiniband/core/addr.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/addr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/addr.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/inetdevice.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <net/arp.h>
 #include <net/neighbour.h>
 #include <net/route.h>
@@ -215,7 +216,9 @@ static int addr4_resolve(struct sockaddr
 
 	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+		rcu_read_lock();
 		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+		rcu_read_unlock();
 		ret = -ENODATA;
 		if (neigh)
 			goto release;
@@ -273,15 +276,16 @@ static int addr6_resolve(struct sockaddr
 		goto put;
 	}
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
 		if (neigh)
 			neigh_event_send(neigh, NULL);
 		ret = -ENODATA;
-		goto put;
+	} else {
+		ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
 	}
-
-	ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+	rcu_read_unlock();
 put:
 	dst_release(dst);
 	return ret;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/cma.c linux-libre-3.2-gnu1/drivers/infiniband/core/cma.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/cma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/cma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/idr.h>
 #include <linux/inetdevice.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <net/tcp.h>
 #include <net/ipv6.h>
@@ -81,6 +82,7 @@ static DEFINE_IDR(sdp_ps);
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
 static DEFINE_IDR(ipoib_ps);
+static DEFINE_IDR(ib_ps);
 
 struct cma_device {
 	struct list_head	list;
@@ -1179,6 +1181,15 @@ static void cma_set_req_event_data(struc
 	event->param.conn.qp_num = req_data->remote_qpn;
 }
 
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+	return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+		 (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+		((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+		 (id->qp_type == IB_QPT_UD)) ||
+		(!id->qp_type));
+}
+
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
 	struct rdma_id_private *listen_id, *conn_id;
@@ -1186,13 +1197,16 @@ static int cma_req_handler(struct ib_cm_
 	int offset, ret;
 
 	listen_id = cm_id->context;
+	if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+		return -EINVAL;
+
 	if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
 		return -ECONNABORTED;
 
 	memset(&event, 0, sizeof event);
 	offset = cma_user_data_offset(listen_id->id.ps);
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-	if (listen_id->id.qp_type == IB_QPT_UD) {
+	if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
 		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
 		event.param.ud.private_data = ib_event->private_data + offset;
 		event.param.ud.private_data_len =
@@ -1328,6 +1342,8 @@ static int cma_iw_handler(struct iw_cm_i
 		switch (iw_event->status) {
 		case 0:
 			event.event = RDMA_CM_EVENT_ESTABLISHED;
+			event.param.conn.initiator_depth = iw_event->ird;
+			event.param.conn.responder_resources = iw_event->ord;
 			break;
 		case -ECONNRESET:
 		case -ECONNREFUSED:
@@ -1343,6 +1359,8 @@ static int cma_iw_handler(struct iw_cm_i
 		break;
 	case IW_CM_EVENT_ESTABLISHED:
 		event.event = RDMA_CM_EVENT_ESTABLISHED;
+		event.param.conn.initiator_depth = iw_event->ird;
+		event.param.conn.responder_resources = iw_event->ord;
 		break;
 	default:
 		BUG_ON(1);
@@ -1433,8 +1451,8 @@ static int iw_conn_req_handler(struct iw
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
 	event.param.conn.private_data = iw_event->private_data;
 	event.param.conn.private_data_len = iw_event->private_data_len;
-	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
-	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+	event.param.conn.initiator_depth = iw_event->ird;
+	event.param.conn.responder_resources = iw_event->ord;
 
 	/*
 	 * Protect against the user destroying conn_id from another thread
@@ -2234,6 +2252,9 @@ static int cma_get_port(struct rdma_id_p
 	case RDMA_PS_IPOIB:
 		ps = &ipoib_ps;
 		break;
+	case RDMA_PS_IB:
+		ps = &ib_ps;
+		break;
 	default:
 		return -EPROTONOSUPPORT;
 	}
@@ -2492,6 +2513,9 @@ static int cma_resolve_ib_udp(struct rdm
 
 	req.private_data_len = sizeof(struct cma_hdr) +
 			       conn_param->private_data_len;
+	if (req.private_data_len < conn_param->private_data_len)
+		return -EINVAL;
+
 	req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
 	if (!req.private_data)
 		return -ENOMEM;
@@ -2541,6 +2565,9 @@ static int cma_connect_ib(struct rdma_id
 	memset(&req, 0, sizeof req);
 	offset = cma_user_data_offset(id_priv->id.ps);
 	req.private_data_len = offset + conn_param->private_data_len;
+	if (req.private_data_len < conn_param->private_data_len)
+		return -EINVAL;
+
 	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
 	if (!private_data)
 		return -ENOMEM;
@@ -2569,7 +2596,7 @@ static int cma_connect_ib(struct rdma_id
 	req.service_id = cma_get_service_id(id_priv->id.ps,
 					    (struct sockaddr *) &route->addr.dst_addr);
 	req.qp_num = id_priv->qp_num;
-	req.qp_type = IB_QPT_RC;
+	req.qp_type = id_priv->id.qp_type;
 	req.starting_psn = id_priv->seq_num;
 	req.responder_resources = conn_param->responder_resources;
 	req.initiator_depth = conn_param->initiator_depth;
@@ -2616,14 +2643,16 @@ static int cma_connect_iw(struct rdma_id
 	if (ret)
 		goto out;
 
-	iw_param.ord = conn_param->initiator_depth;
-	iw_param.ird = conn_param->responder_resources;
-	iw_param.private_data = conn_param->private_data;
-	iw_param.private_data_len = conn_param->private_data_len;
-	if (id_priv->id.qp)
+	if (conn_param) {
+		iw_param.ord = conn_param->initiator_depth;
+		iw_param.ird = conn_param->responder_resources;
+		iw_param.private_data = conn_param->private_data;
+		iw_param.private_data_len = conn_param->private_data_len;
+		iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
+	} else {
+		memset(&iw_param, 0, sizeof iw_param);
 		iw_param.qpn = id_priv->qp_num;
-	else
-		iw_param.qpn = conn_param->qp_num;
+	}
 	ret = iw_cm_connect(cm_id, &iw_param);
 out:
 	if (ret) {
@@ -2765,14 +2794,20 @@ int rdma_accept(struct rdma_cm_id *id, s
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->qp_type == IB_QPT_UD)
-			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
-						conn_param->private_data,
-						conn_param->private_data_len);
-		else if (conn_param)
-			ret = cma_accept_ib(id_priv, conn_param);
-		else
-			ret = cma_rep_recv(id_priv);
+		if (id->qp_type == IB_QPT_UD) {
+			if (conn_param)
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							conn_param->private_data,
+							conn_param->private_data_len);
+			else
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							NULL, 0);
+		} else {
+			if (conn_param)
+				ret = cma_accept_ib(id_priv, conn_param);
+			else
+				ret = cma_rep_recv(id_priv);
+		}
 		break;
 	case RDMA_TRANSPORT_IWARP:
 		ret = cma_accept_iw(id_priv, conn_param);
@@ -3460,6 +3495,7 @@ static void __exit cma_cleanup(void)
 	idr_destroy(&tcp_ps);
 	idr_destroy(&udp_ps);
 	idr_destroy(&ipoib_ps);
+	idr_destroy(&ib_ps);
 }
 
 module_init(cma_init);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/cm.c linux-libre-3.2-gnu1/drivers/infiniband/core/cm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/completion.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
@@ -889,6 +890,8 @@ retest:
 		break;
 	case IB_CM_ESTABLISHED:
 		spin_unlock_irq(&cm_id_priv->lock);
+		if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
+			break;
 		ib_send_cm_dreq(cm_id, NULL, 0);
 		goto retest;
 	case IB_CM_DREQ_SENT:
@@ -1008,7 +1011,6 @@ static void cm_format_req(struct cm_req_
 	req_msg->service_id = param->service_id;
 	req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 	cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
-	cm_req_set_resp_res(req_msg, param->responder_resources);
 	cm_req_set_init_depth(req_msg, param->initiator_depth);
 	cm_req_set_remote_resp_timeout(req_msg,
 				       param->remote_cm_response_timeout);
@@ -1017,12 +1019,16 @@ static void cm_format_req(struct cm_req_
 	cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
 	cm_req_set_local_resp_timeout(req_msg,
 				      param->local_cm_response_timeout);
-	cm_req_set_retry_count(req_msg, param->retry_count);
 	req_msg->pkey = param->primary_path->pkey;
 	cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
-	cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
 	cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
-	cm_req_set_srq(req_msg, param->srq);
+
+	if (param->qp_type != IB_QPT_XRC_INI) {
+		cm_req_set_resp_res(req_msg, param->responder_resources);
+		cm_req_set_retry_count(req_msg, param->retry_count);
+		cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
+		cm_req_set_srq(req_msg, param->srq);
+	}
 
 	if (pri_path->hop_limit <= 1) {
 		req_msg->primary_local_lid = pri_path->slid;
@@ -1080,7 +1086,8 @@ static int cm_validate_req_param(struct
 	if (!param->primary_path)
 		return -EINVAL;
 
-	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
+	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
+	    param->qp_type != IB_QPT_XRC_INI)
 		return -EINVAL;
 
 	if (param->private_data &&
@@ -1601,18 +1608,24 @@ static void cm_format_rep(struct cm_rep_
 	cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
 	rep_msg->local_comm_id = cm_id_priv->id.local_id;
 	rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
-	cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
 	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
 	rep_msg->resp_resources = param->responder_resources;
-	rep_msg->initiator_depth = param->initiator_depth;
 	cm_rep_set_target_ack_delay(rep_msg,
 				    cm_id_priv->av.port->cm_dev->ack_delay);
 	cm_rep_set_failover(rep_msg, param->failover_accepted);
-	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
 	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
-	cm_rep_set_srq(rep_msg, param->srq);
 	rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 
+	if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
+		rep_msg->initiator_depth = param->initiator_depth;
+		cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
+		cm_rep_set_srq(rep_msg, param->srq);
+		cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
+	} else {
+		cm_rep_set_srq(rep_msg, 1);
+		cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
+	}
+
 	if (param->private_data && param->private_data_len)
 		memcpy(rep_msg->private_data, param->private_data,
 		       param->private_data_len);
@@ -1660,7 +1673,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_i
 	cm_id_priv->initiator_depth = param->initiator_depth;
 	cm_id_priv->responder_resources = param->responder_resources;
 	cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
-	cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
 
 out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 	return ret;
@@ -1731,7 +1744,7 @@ error:	spin_unlock_irqrestore(&cm_id_pri
 }
 EXPORT_SYMBOL(ib_send_cm_rtu);
 
-static void cm_format_rep_event(struct cm_work *work)
+static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
 {
 	struct cm_rep_msg *rep_msg;
 	struct ib_cm_rep_event_param *param;
@@ -1740,7 +1753,7 @@ static void cm_format_rep_event(struct c
 	param = &work->cm_event.param.rep_rcvd;
 	param->remote_ca_guid = rep_msg->local_ca_guid;
 	param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
-	param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
+	param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
 	param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
 	param->responder_resources = rep_msg->initiator_depth;
 	param->initiator_depth = rep_msg->resp_resources;
@@ -1808,7 +1821,7 @@ static int cm_rep_handler(struct cm_work
 		return -EINVAL;
 	}
 
-	cm_format_rep_event(work);
+	cm_format_rep_event(work, cm_id_priv->qp_type);
 
 	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
@@ -1823,7 +1836,7 @@ static int cm_rep_handler(struct cm_work
 
 	cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
 	cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
-	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 
 	spin_lock(&cm.lock);
 	/* Check for duplicate REP. */
@@ -1850,7 +1863,7 @@ static int cm_rep_handler(struct cm_work
 
 	cm_id_priv->id.state = IB_CM_REP_RCVD;
 	cm_id_priv->id.remote_id = rep_msg->local_comm_id;
-	cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 	cm_id_priv->initiator_depth = rep_msg->resp_resources;
 	cm_id_priv->responder_resources = rep_msg->initiator_depth;
 	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
@@ -3492,7 +3505,8 @@ static int cm_init_qp_rtr_attr(struct cm
 		qp_attr->path_mtu = cm_id_priv->path_mtu;
 		qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
 		qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
-		if (cm_id_priv->qp_type == IB_QPT_RC) {
+		if (cm_id_priv->qp_type == IB_QPT_RC ||
+		    cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
 			*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
 					 IB_QP_MIN_RNR_TIMER;
 			qp_attr->max_dest_rd_atomic =
@@ -3537,15 +3551,21 @@ static int cm_init_qp_rts_attr(struct cm
 		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
 			*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
 			qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-			if (cm_id_priv->qp_type == IB_QPT_RC) {
-				*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-						 IB_QP_RNR_RETRY |
+			switch (cm_id_priv->qp_type) {
+			case IB_QPT_RC:
+			case IB_QPT_XRC_INI:
+				*qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
 						 IB_QP_MAX_QP_RD_ATOMIC;
-				qp_attr->timeout = cm_id_priv->av.timeout;
 				qp_attr->retry_cnt = cm_id_priv->retry_count;
 				qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
-				qp_attr->max_rd_atomic =
-					cm_id_priv->initiator_depth;
+				qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+				/* fall through */
+			case IB_QPT_XRC_TGT:
+				*qp_attr_mask |= IB_QP_TIMEOUT;
+				qp_attr->timeout = cm_id_priv->av.timeout;
+				break;
+			default:
+				break;
 			}
 			if (cm_id_priv->alt_av.ah_attr.dlid) {
 				*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/cm_msgs.h linux-libre-3.2-gnu1/drivers/infiniband/core/cm_msgs.h
--- linux-libre-3.1-gnu1/drivers/infiniband/core/cm_msgs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/cm_msgs.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  *
@@ -86,7 +86,7 @@ struct cm_req_msg {
 	__be16 pkey;
 	/* path MTU:4, RDC exists:1, RNR retry count:3. */
 	u8 offset50;
-	/* max CM Retries:4, SRQ:1, rsvd:3 */
+	/* max CM Retries:4, SRQ:1, extended transport type:3 */
 	u8 offset51;
 
 	__be16 primary_local_lid;
@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get
 	switch(transport_type) {
 	case 0: return IB_QPT_RC;
 	case 1: return IB_QPT_UC;
+	case 3:
+		switch (req_msg->offset51 & 0x7) {
+		case 1: return IB_QPT_XRC_TGT;
+		default: return 0;
+		}
 	default: return 0;
 	}
 }
@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(st
 						  req_msg->offset40) &
 						   0xFFFFFFF9) | 0x2);
 		break;
+	case IB_QPT_XRC_INI:
+		req_msg->offset40 = cpu_to_be32((be32_to_cpu(
+						 req_msg->offset40) &
+						   0xFFFFFFF9) | 0x6);
+		req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
+		break;
 	default:
 		req_msg->offset40 = cpu_to_be32(be32_to_cpu(
 						 req_msg->offset40) &
@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(
 			    (be32_to_cpu(rep_msg->offset12) & 0x000000FF));
 }
 
+static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
+{
+	return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
+}
+
+static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
+{
+	rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
+			    (be32_to_cpu(rep_msg->offset16) & 0x000000FF));
+}
+
+static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
+{
+	return (qp_type == IB_QPT_XRC_INI) ?
+		cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
+}
+
 static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
 {
 	return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/fmr_pool.c linux-libre-3.2-gnu1/drivers/infiniband/core/fmr_pool.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/fmr_pool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/fmr_pool.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/jhash.h>
 #include <linux/kthread.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/iwcm.c linux-libre-3.2-gnu1/drivers/infiniband/core/iwcm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/iwcm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/iwcm.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/workqueue.h>
 #include <linux/completion.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <rdma/iw_cm.h>
 #include <rdma/ib_addr.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/mad.c linux-libre-3.2-gnu1/drivers/infiniband/core/mad.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/mad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/mad.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
  */
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <rdma/ib_cache.h>
 
 #include "mad_priv.h"
@@ -1596,6 +1597,9 @@ find_mad_agent(struct ib_mad_port_privat
 					mad->mad_hdr.class_version].class;
 			if (!class)
 				goto out;
+			if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
+			    IB_MGMT_MAX_METHODS)
+				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad->mad_hdr.mgmt_class)];
 			if (method)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/multicast.c linux-libre-3.2-gnu1/drivers/infiniband/core/multicast.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/multicast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/multicast.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/random.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/netlink.c linux-libre-3.2-gnu1/drivers/infiniband/core/netlink.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/netlink.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/netlink.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
 
+#include <linux/export.h>
 #include <net/netlink.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/packer.c linux-libre-3.2-gnu1/drivers/infiniband/core/packer.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/packer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/packer.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/export.h>
 #include <linux/string.h>
 
 #include <rdma/ib_pack.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/sysfs.c linux-libre-3.2-gnu1/drivers/infiniband/core/sysfs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "core_priv.h"
 
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/string.h>
 
 #include <rdma/ib_mad.h>
@@ -185,17 +186,35 @@ static ssize_t rate_show(struct ib_port
 	if (ret)
 		return ret;
 
+	rate = (25 * attr.active_speed) / 10;
+
 	switch (attr.active_speed) {
-	case 2: speed = " DDR"; break;
-	case 4: speed = " QDR"; break;
+	case 2:
+		speed = " DDR";
+		break;
+	case 4:
+		speed = " QDR";
+		break;
+	case 8:
+		speed = " FDR10";
+		rate = 10;
+		break;
+	case 16:
+		speed = " FDR";
+		rate = 14;
+		break;
+	case 32:
+		speed = " EDR";
+		rate = 25;
+		break;
 	}
 
-	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+	rate *= ib_width_enum_to_int(attr.active_width);
 	if (rate < 0)
 		return -EINVAL;
 
 	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
-		       rate / 10, rate % 10 ? ".5" : "",
+		       rate, (attr.active_speed == 1) ? ".5" : "",
 		       ib_width_enum_to_int(attr.active_width), speed);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/ucma.c linux-libre-3.2-gnu1/drivers/infiniband/core/ucma.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/ucma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/ucma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/module.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
@@ -276,7 +277,7 @@ static int ucma_event_handler(struct rdm
 	ucma_set_event_context(ctx, event, uevent);
 	uevent->resp.event = event->event;
 	uevent->resp.status = event->status;
-	if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
+	if (cm_id->qp_type == IB_QPT_UD)
 		ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
 	else
 		ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -377,6 +378,9 @@ static int ucma_get_qp_type(struct rdma_
 	case RDMA_PS_IPOIB:
 		*qp_type = IB_QPT_UD;
 		return 0;
+	case RDMA_PS_IB:
+		*qp_type = cmd->qp_type;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1270,7 +1274,7 @@ static ssize_t ucma_write(struct file *f
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/ucm.c linux-libre-3.2-gnu1/drivers/infiniband/core/ucm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/ucm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/ucm.c	2012-01-04 18:55:44.000000000 -0500
@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/ud_header.c linux-libre-3.2-gnu1/drivers/infiniband/core/ud_header.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/ud_header.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/ud_header.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/if_ether.h>
 
 #include <rdma/ib_pack.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/umem.c linux-libre-3.2-gnu1/drivers/infiniband/core/umem.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/umem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/umem.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/hugetlb.h>
 #include <linux/dma-attrs.h>
 #include <linux/slab.h>
@@ -136,7 +137,7 @@ struct ib_umem *ib_umem_get(struct ib_uc
 
 	down_write(&current->mm->mmap_sem);
 
-	locked     = npages + current->mm->locked_vm;
+	locked     = npages + current->mm->pinned_vm;
 	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
 	if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
@@ -206,7 +207,7 @@ out:
 		__ib_umem_release(context->device, umem, 0);
 		kfree(umem);
 	} else
-		current->mm->locked_vm = locked;
+		current->mm->pinned_vm = locked;
 
 	up_write(&current->mm->mmap_sem);
 	if (vma_list)
@@ -222,7 +223,7 @@ static void ib_umem_account(struct work_
 	struct ib_umem *umem = container_of(work, struct ib_umem, work);
 
 	down_write(&umem->mm->mmap_sem);
-	umem->mm->locked_vm -= umem->diff;
+	umem->mm->pinned_vm -= umem->diff;
 	up_write(&umem->mm->mmap_sem);
 	mmput(umem->mm);
 	kfree(umem);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/user_mad.c linux-libre-3.2-gnu1/drivers/infiniband/core/user_mad.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/user_mad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/user_mad.c	2012-01-04 18:55:44.000000000 -0500
@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file
 		goto err;
 	}
 
-	if (packet->mad.hdr.id < 0 ||
-	    packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
+	if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
 		ret = -EINVAL;
 		goto err;
 	}
@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib
 	mutex_lock(&file->port->file_mutex);
 	mutex_lock(&file->mutex);
 
-	if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+	if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
 		ret = -EINVAL;
 		goto out;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_cmd.c linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_cmd.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_cmd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_cmd.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@ static struct lock_class_key cq_lock_key
 static struct lock_class_key qp_lock_key;
 static struct lock_class_key ah_lock_key;
 static struct lock_class_key srq_lock_key;
+static struct lock_class_key xrcd_lock_key;
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)			\
 	do {								\
@@ -255,6 +256,18 @@ static void put_srq_read(struct ib_srq *
 	put_uobj_read(srq->uobject);
 }
 
+static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
+				     struct ib_uobject **uobj)
+{
+	*uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
+	return *uobj ? (*uobj)->object : NULL;
+}
+
+static void put_xrcd_read(struct ib_uobject *uobj)
+{
+	put_uobj_read(uobj);
+}
+
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -298,6 +311,7 @@ ssize_t ib_uverbs_get_context(struct ib_
 	INIT_LIST_HEAD(&ucontext->qp_list);
 	INIT_LIST_HEAD(&ucontext->srq_list);
 	INIT_LIST_HEAD(&ucontext->ah_list);
+	INIT_LIST_HEAD(&ucontext->xrcd_list);
 	ucontext->closing = 0;
 
 	resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -579,6 +593,310 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_u
 	return in_len;
 }
 
+struct xrcd_table_entry {
+	struct rb_node  node;
+	struct ib_xrcd *xrcd;
+	struct inode   *inode;
+};
+
+static int xrcd_table_insert(struct ib_uverbs_device *dev,
+			    struct inode *inode,
+			    struct ib_xrcd *xrcd)
+{
+	struct xrcd_table_entry *entry, *scan;
+	struct rb_node **p = &dev->xrcd_tree.rb_node;
+	struct rb_node *parent = NULL;
+
+	entry = kmalloc(sizeof *entry, GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->xrcd  = xrcd;
+	entry->inode = inode;
+
+	while (*p) {
+		parent = *p;
+		scan = rb_entry(parent, struct xrcd_table_entry, node);
+
+		if (inode < scan->inode) {
+			p = &(*p)->rb_left;
+		} else if (inode > scan->inode) {
+			p = &(*p)->rb_right;
+		} else {
+			kfree(entry);
+			return -EEXIST;
+		}
+	}
+
+	rb_link_node(&entry->node, parent, p);
+	rb_insert_color(&entry->node, &dev->xrcd_tree);
+	igrab(inode);
+	return 0;
+}
+
+static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
+						  struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+	struct rb_node *p = dev->xrcd_tree.rb_node;
+
+	while (p) {
+		entry = rb_entry(p, struct xrcd_table_entry, node);
+
+		if (inode < entry->inode)
+			p = p->rb_left;
+		else if (inode > entry->inode)
+			p = p->rb_right;
+		else
+			return entry;
+	}
+
+	return NULL;
+}
+
+static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (!entry)
+		return NULL;
+
+	return entry->xrcd;
+}
+
+static void xrcd_table_delete(struct ib_uverbs_device *dev,
+			      struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (entry) {
+		iput(inode);
+		rb_erase(&entry->node, &dev->xrcd_tree);
+		kfree(entry);
+	}
+}
+
+ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
+			    const char __user *buf, int in_len,
+			    int out_len)
+{
+	struct ib_uverbs_open_xrcd	cmd;
+	struct ib_uverbs_open_xrcd_resp	resp;
+	struct ib_udata			udata;
+	struct ib_uxrcd_object         *obj;
+	struct ib_xrcd                 *xrcd = NULL;
+	struct file                    *f = NULL;
+	struct inode                   *inode = NULL;
+	int				ret = 0;
+	int				new_xrcd = 0;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof  resp);
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+
+	if (cmd.fd != -1) {
+		/* search for file descriptor */
+		f = fget(cmd.fd);
+		if (!f) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		inode = f->f_dentry->d_inode;
+		if (!inode) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		xrcd = find_xrcd(file->device, inode);
+		if (!xrcd && !(cmd.oflags & O_CREAT)) {
+			/* no file descriptor. Need CREATE flag */
+			ret = -EAGAIN;
+			goto err_tree_mutex_unlock;
+		}
+
+		if (xrcd && cmd.oflags & O_EXCL) {
+			ret = -EINVAL;
+			goto err_tree_mutex_unlock;
+		}
+	}
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj) {
+		ret = -ENOMEM;
+		goto err_tree_mutex_unlock;
+	}
+
+	init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+
+	down_write(&obj->uobject.mutex);
+
+	if (!xrcd) {
+		xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
+							file->ucontext, &udata);
+		if (IS_ERR(xrcd)) {
+			ret = PTR_ERR(xrcd);
+			goto err;
+		}
+
+		xrcd->inode   = inode;
+		xrcd->device  = file->device->ib_dev;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+		new_xrcd = 1;
+	}
+
+	atomic_set(&obj->refcnt, 0);
+	obj->uobject.object = xrcd;
+	ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+	if (ret)
+		goto err_idr;
+
+	memset(&resp, 0, sizeof resp);
+	resp.xrcd_handle = obj->uobject.id;
+
+	if (inode) {
+		if (new_xrcd) {
+			/* create new inode/xrcd table entry */
+			ret = xrcd_table_insert(file->device, inode, xrcd);
+			if (ret)
+				goto err_insert_xrcd;
+		}
+		atomic_inc(&xrcd->usecnt);
+	}
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_copy;
+	}
+
+	if (f)
+		fput(f);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uobject.live = 1;
+	up_write(&obj->uobject.mutex);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return in_len;
+
+err_copy:
+	if (inode) {
+		if (new_xrcd)
+			xrcd_table_delete(file->device, inode);
+		atomic_dec(&xrcd->usecnt);
+	}
+
+err_insert_xrcd:
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+
+err_idr:
+	ib_dealloc_xrcd(xrcd);
+
+err:
+	put_uobj_write(&obj->uobject);
+
+err_tree_mutex_unlock:
+	if (f)
+		fput(f);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
+	return ret;
+}
+
+ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_close_xrcd cmd;
+	struct ib_uobject           *uobj;
+	struct ib_xrcd              *xrcd = NULL;
+	struct inode                *inode = NULL;
+	struct ib_uxrcd_object      *obj;
+	int                         live;
+	int                         ret = 0;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
+	if (!uobj) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	xrcd  = uobj->object;
+	inode = xrcd->inode;
+	obj   = container_of(uobj, struct ib_uxrcd_object, uobject);
+	if (atomic_read(&obj->refcnt)) {
+		put_uobj_write(uobj);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+		ret = ib_dealloc_xrcd(uobj->object);
+		if (!ret)
+			uobj->live = 0;
+	}
+
+	live = uobj->live;
+	if (inode && ret)
+		atomic_inc(&xrcd->usecnt);
+
+	put_uobj_write(uobj);
+
+	if (ret)
+		goto out;
+
+	if (inode && !live)
+		xrcd_table_delete(file->device, inode);
+
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+	mutex_lock(&file->mutex);
+	list_del(&uobj->list);
+	mutex_unlock(&file->mutex);
+
+	put_uobj(uobj);
+	ret = in_len;
+
+out:
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return ret;
+}
+
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
+			    struct ib_xrcd *xrcd)
+{
+	struct inode *inode;
+
+	inode = xrcd->inode;
+	if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+		return;
+
+	ib_dealloc_xrcd(xrcd);
+
+	if (inode)
+		xrcd_table_delete(dev, inode);
+}
+
 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 			 const char __user *buf, int in_len,
 			 int out_len)
@@ -1052,9 +1370,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	struct ib_uverbs_create_qp_resp resp;
 	struct ib_udata                 udata;
 	struct ib_uqp_object           *obj;
-	struct ib_pd                   *pd;
-	struct ib_cq                   *scq, *rcq;
-	struct ib_srq                  *srq;
+	struct ib_device	       *device;
+	struct ib_pd                   *pd = NULL;
+	struct ib_xrcd		       *xrcd = NULL;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_cq                   *scq = NULL, *rcq = NULL;
+	struct ib_srq                  *srq = NULL;
 	struct ib_qp                   *qp;
 	struct ib_qp_init_attr          attr;
 	int ret;
@@ -1076,15 +1397,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
 	down_write(&obj->uevent.uobject.mutex);
 
-	srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
-	scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
-	rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
-		scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+	if (cmd.qp_type == IB_QPT_XRC_TGT) {
+		xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+		if (!xrcd) {
+			ret = -EINVAL;
+			goto err_put;
+		}
+		device = xrcd->device;
+	} else {
+		pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+		scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+		if (!pd || !scq) {
+			ret = -EINVAL;
+			goto err_put;
+		}
 
-	if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
-		ret = -EINVAL;
-		goto err_put;
+		if (cmd.qp_type == IB_QPT_XRC_INI) {
+			cmd.max_recv_wr = cmd.max_recv_sge = 0;
+		} else {
+			if (cmd.is_srq) {
+				srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+				if (!srq || srq->srq_type != IB_SRQT_BASIC) {
+					ret = -EINVAL;
+					goto err_put;
+				}
+			}
+			rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
+			       scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+			if (!rcq) {
+				ret = -EINVAL;
+				goto err_put;
+			}
+		}
+		device = pd->device;
 	}
 
 	attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1092,6 +1437,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	attr.send_cq       = scq;
 	attr.recv_cq       = rcq;
 	attr.srq           = srq;
+	attr.xrcd	   = xrcd;
 	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
 	attr.qp_type       = cmd.qp_type;
 	attr.create_flags  = 0;
@@ -1106,26 +1452,34 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	INIT_LIST_HEAD(&obj->uevent.event_list);
 	INIT_LIST_HEAD(&obj->mcast_list);
 
-	qp = pd->device->create_qp(pd, &attr, &udata);
+	if (cmd.qp_type == IB_QPT_XRC_TGT)
+		qp = ib_create_qp(pd, &attr);
+	else
+		qp = device->create_qp(pd, &attr, &udata);
+
 	if (IS_ERR(qp)) {
 		ret = PTR_ERR(qp);
 		goto err_put;
 	}
 
-	qp->device     	  = pd->device;
-	qp->pd         	  = pd;
-	qp->send_cq    	  = attr.send_cq;
-	qp->recv_cq    	  = attr.recv_cq;
-	qp->srq	       	  = attr.srq;
-	qp->uobject       = &obj->uevent.uobject;
-	qp->event_handler = attr.event_handler;
-	qp->qp_context    = attr.qp_context;
-	qp->qp_type	  = attr.qp_type;
-	atomic_inc(&pd->usecnt);
-	atomic_inc(&attr.send_cq->usecnt);
-	atomic_inc(&attr.recv_cq->usecnt);
-	if (attr.srq)
-		atomic_inc(&attr.srq->usecnt);
+	if (cmd.qp_type != IB_QPT_XRC_TGT) {
+		qp->real_qp	  = qp;
+		qp->device	  = device;
+		qp->pd		  = pd;
+		qp->send_cq	  = attr.send_cq;
+		qp->recv_cq	  = attr.recv_cq;
+		qp->srq		  = attr.srq;
+		qp->event_handler = attr.event_handler;
+		qp->qp_context	  = attr.qp_context;
+		qp->qp_type	  = attr.qp_type;
+		atomic_inc(&pd->usecnt);
+		atomic_inc(&attr.send_cq->usecnt);
+		if (attr.recv_cq)
+			atomic_inc(&attr.recv_cq->usecnt);
+		if (attr.srq)
+			atomic_inc(&attr.srq->usecnt);
+	}
+	qp->uobject = &obj->uevent.uobject;
 
 	obj->uevent.uobject.object = qp;
 	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1147,9 +1501,13 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 		goto err_copy;
 	}
 
-	put_pd_read(pd);
-	put_cq_read(scq);
-	if (rcq != scq)
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
+	if (pd)
+		put_pd_read(pd);
+	if (scq)
+		put_cq_read(scq);
+	if (rcq && rcq != scq)
 		put_cq_read(rcq);
 	if (srq)
 		put_srq_read(srq);
@@ -1171,6 +1529,8 @@ err_destroy:
 	ib_destroy_qp(qp);
 
 err_put:
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
 	if (pd)
 		put_pd_read(pd);
 	if (scq)
@@ -1184,6 +1544,98 @@ err_put:
 	return ret;
 }
 
+ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+			  const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_open_qp        cmd;
+	struct ib_uverbs_create_qp_resp resp;
+	struct ib_udata                 udata;
+	struct ib_uqp_object           *obj;
+	struct ib_xrcd		       *xrcd;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_qp                   *qp;
+	struct ib_qp_open_attr          attr;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
+
+	xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+	if (!xrcd) {
+		ret = -EINVAL;
+		goto err_put;
+	}
+
+	attr.event_handler = ib_uverbs_qp_event_handler;
+	attr.qp_context    = file;
+	attr.qp_num        = cmd.qpn;
+	attr.qp_type       = cmd.qp_type;
+
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
+	INIT_LIST_HEAD(&obj->mcast_list);
+
+	qp = ib_open_qp(xrcd, &attr);
+	if (IS_ERR(qp)) {
+		ret = PTR_ERR(qp);
+		goto err_put;
+	}
+
+	qp->uobject = &obj->uevent.uobject;
+
+	obj->uevent.uobject.object = qp;
+	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+	if (ret)
+		goto err_destroy;
+
+	memset(&resp, 0, sizeof resp);
+	resp.qpn       = qp->qp_num;
+	resp.qp_handle = obj->uevent.uobject.id;
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_remove;
+	}
+
+	put_xrcd_read(xrcd_uobj);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uevent.uobject.live = 1;
+
+	up_write(&obj->uevent.uobject.mutex);
+
+	return in_len;
+
+err_remove:
+	idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+	ib_destroy_qp(qp);
+
+err_put:
+	put_xrcd_read(xrcd_uobj);
+	put_uobj_write(&obj->uevent.uobject);
+	return ret;
+}
+
 ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
 			   const char __user *buf, int in_len,
 			   int out_len)
@@ -1284,6 +1736,20 @@ out:
 	return ret ? ret : in_len;
 }
 
+/* Remove ignored fields set in the attribute mask */
+static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
+{
+	switch (qp_type) {
+	case IB_QPT_XRC_INI:
+		return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
+	case IB_QPT_XRC_TGT:
+		return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
+				IB_QP_RNR_RETRY);
+	default:
+		return mask;
+	}
+}
+
 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
 			    const char __user *buf, int in_len,
 			    int out_len)
@@ -1356,7 +1822,12 @@ ssize_t ib_uverbs_modify_qp(struct ib_uv
 	attr->alt_ah_attr.ah_flags 	    = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
 	attr->alt_ah_attr.port_num 	    = cmd.alt_dest.port_num;
 
-	ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
+	if (qp->real_qp == qp) {
+		ret = qp->device->modify_qp(qp, attr,
+			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+	} else {
+		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+	}
 
 	put_qp_read(qp);
 
@@ -1553,7 +2024,7 @@ ssize_t ib_uverbs_post_send(struct ib_uv
 	}
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_send(qp, wr, &bad_wr);
+	ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
 	if (ret)
 		for (next = wr; next; next = next->next) {
 			++resp.bad_wr;
@@ -1691,7 +2162,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uv
 		goto out;
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_recv(qp, wr, &bad_wr);
+	ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
 
 	put_qp_read(qp);
 
@@ -1975,107 +2446,199 @@ out_put:
 	return ret ? ret : in_len;
 }
 
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
-			     const char __user *buf, int in_len,
-			     int out_len)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+			 struct ib_uverbs_create_xsrq *cmd,
+			 struct ib_udata *udata)
 {
-	struct ib_uverbs_create_srq      cmd;
 	struct ib_uverbs_create_srq_resp resp;
-	struct ib_udata                  udata;
-	struct ib_uevent_object         *obj;
+	struct ib_usrq_object           *obj;
 	struct ib_pd                    *pd;
 	struct ib_srq                   *srq;
+	struct ib_uobject               *uninitialized_var(xrcd_uobj);
 	struct ib_srq_init_attr          attr;
 	int ret;
 
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd,
-		   (unsigned long) cmd.response + sizeof resp,
-		   in_len - sizeof cmd, out_len - sizeof resp);
-
 	obj = kmalloc(sizeof *obj, GFP_KERNEL);
 	if (!obj)
 		return -ENOMEM;
 
-	init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
-	down_write(&obj->uobject.mutex);
+	init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
 
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+	pd  = idr_read_pd(cmd->pd_handle, file->ucontext);
 	if (!pd) {
 		ret = -EINVAL;
 		goto err;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		attr.ext.xrc.cq  = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+		if (!attr.ext.xrc.cq) {
+			ret = -EINVAL;
+			goto err_put_pd;
+		}
+
+		attr.ext.xrc.xrcd  = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+		if (!attr.ext.xrc.xrcd) {
+			ret = -EINVAL;
+			goto err_put_cq;
+		}
+
+		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+		atomic_inc(&obj->uxrcd->refcnt);
+	}
+
 	attr.event_handler  = ib_uverbs_srq_event_handler;
 	attr.srq_context    = file;
-	attr.attr.max_wr    = cmd.max_wr;
-	attr.attr.max_sge   = cmd.max_sge;
-	attr.attr.srq_limit = cmd.srq_limit;
+	attr.srq_type       = cmd->srq_type;
+	attr.attr.max_wr    = cmd->max_wr;
+	attr.attr.max_sge   = cmd->max_sge;
+	attr.attr.srq_limit = cmd->srq_limit;
 
-	obj->events_reported     = 0;
-	INIT_LIST_HEAD(&obj->event_list);
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
 
-	srq = pd->device->create_srq(pd, &attr, &udata);
+	srq = pd->device->create_srq(pd, &attr, udata);
 	if (IS_ERR(srq)) {
 		ret = PTR_ERR(srq);
 		goto err_put;
 	}
 
-	srq->device    	   = pd->device;
-	srq->pd        	   = pd;
-	srq->uobject       = &obj->uobject;
+	srq->device        = pd->device;
+	srq->pd            = pd;
+	srq->srq_type	   = cmd->srq_type;
+	srq->uobject       = &obj->uevent.uobject;
 	srq->event_handler = attr.event_handler;
 	srq->srq_context   = attr.srq_context;
+
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		srq->ext.xrc.cq   = attr.ext.xrc.cq;
+		srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+		atomic_inc(&attr.ext.xrc.cq->usecnt);
+		atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+	}
+
 	atomic_inc(&pd->usecnt);
 	atomic_set(&srq->usecnt, 0);
 
-	obj->uobject.object = srq;
-	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	obj->uevent.uobject.object = srq;
+	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 	if (ret)
 		goto err_destroy;
 
 	memset(&resp, 0, sizeof resp);
-	resp.srq_handle = obj->uobject.id;
+	resp.srq_handle = obj->uevent.uobject.id;
 	resp.max_wr     = attr.attr.max_wr;
 	resp.max_sge    = attr.attr.max_sge;
+	if (cmd->srq_type == IB_SRQT_XRC)
+		resp.srqn = srq->ext.xrc.srq_num;
 
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+	if (copy_to_user((void __user *) (unsigned long) cmd->response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
 		goto err_copy;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		put_uobj_read(xrcd_uobj);
+		put_cq_read(attr.ext.xrc.cq);
+	}
 	put_pd_read(pd);
 
 	mutex_lock(&file->mutex);
-	list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
 	mutex_unlock(&file->mutex);
 
-	obj->uobject.live = 1;
+	obj->uevent.uobject.live = 1;
 
-	up_write(&obj->uobject.mutex);
+	up_write(&obj->uevent.uobject.mutex);
 
-	return in_len;
+	return 0;
 
 err_copy:
-	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 
 err_destroy:
 	ib_destroy_srq(srq);
 
 err_put:
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		atomic_dec(&obj->uxrcd->refcnt);
+		put_uobj_read(xrcd_uobj);
+	}
+
+err_put_cq:
+	if (cmd->srq_type == IB_SRQT_XRC)
+		put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
 	put_pd_read(pd);
 
 err:
-	put_uobj_write(&obj->uobject);
+	put_uobj_write(&obj->uevent.uobject);
 	return ret;
 }
 
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_create_srq      cmd;
+	struct ib_uverbs_create_xsrq     xcmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	xcmd.response	 = cmd.response;
+	xcmd.user_handle = cmd.user_handle;
+	xcmd.srq_type	 = IB_SRQT_BASIC;
+	xcmd.pd_handle	 = cmd.pd_handle;
+	xcmd.max_wr	 = cmd.max_wr;
+	xcmd.max_sge	 = cmd.max_sge;
+	xcmd.srq_limit	 = cmd.srq_limit;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+			      const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_create_xsrq     cmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &cmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
 			     const char __user *buf, int in_len,
 			     int out_len)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs.h linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs.h
--- linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@ struct ib_uverbs_device {
 	struct ib_device		       *ib_dev;
 	int					devnum;
 	struct cdev			        cdev;
+	struct rb_root				xrcd_tree;
+	struct mutex				xrcd_tree_mutex;
 };
 
 struct ib_uverbs_event_file {
@@ -120,6 +122,16 @@ struct ib_uevent_object {
 	u32			events_reported;
 };
 
+struct ib_uxrcd_object {
+	struct ib_uobject	uobject;
+	atomic_t		refcnt;
+};
+
+struct ib_usrq_object {
+	struct ib_uevent_object	uevent;
+	struct ib_uxrcd_object *uxrcd;
+};
+
 struct ib_uqp_object {
 	struct ib_uevent_object	uevent;
 	struct list_head 	mcast_list;
@@ -142,6 +154,7 @@ extern struct idr ib_uverbs_ah_idr;
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
+extern struct idr ib_uverbs_xrcd_idr;
 
 void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
 
@@ -161,6 +174,7 @@ void ib_uverbs_qp_event_handler(struct i
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_event_handler(struct ib_event_handler *handler,
 			     struct ib_event *event);
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
 
 #define IB_UVERBS_DECLARE_CMD(name)					\
 	ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,		\
@@ -181,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq);
 IB_UVERBS_DECLARE_CMD(req_notify_cq);
 IB_UVERBS_DECLARE_CMD(destroy_cq);
 IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(open_qp);
 IB_UVERBS_DECLARE_CMD(query_qp);
 IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
@@ -195,5 +210,8 @@ IB_UVERBS_DECLARE_CMD(create_srq);
 IB_UVERBS_DECLARE_CMD(modify_srq);
 IB_UVERBS_DECLARE_CMD(query_srq);
 IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_xsrq);
+IB_UVERBS_DECLARE_CMD(open_xrcd);
+IB_UVERBS_DECLARE_CMD(close_xrcd);
 
 #endif /* UVERBS_H */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_main.c linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_main.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
 
 static DEFINE_SPINLOCK(map_lock);
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(str
 	[IB_USER_VERBS_CMD_MODIFY_SRQ]		= ib_uverbs_modify_srq,
 	[IB_USER_VERBS_CMD_QUERY_SRQ]		= ib_uverbs_query_srq,
 	[IB_USER_VERBS_CMD_DESTROY_SRQ]		= ib_uverbs_destroy_srq,
+	[IB_USER_VERBS_CMD_OPEN_XRCD]		= ib_uverbs_open_xrcd,
+	[IB_USER_VERBS_CMD_CLOSE_XRCD]		= ib_uverbs_close_xrcd,
+	[IB_USER_VERBS_CMD_CREATE_XSRQ]		= ib_uverbs_create_xsrq,
+	[IB_USER_VERBS_CMD_OPEN_QP]		= ib_uverbs_open_qp
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(st
 			container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
 		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-		ib_uverbs_detach_umcast(qp, uqp);
-		ib_destroy_qp(qp);
+		if (qp != qp->real_qp) {
+			ib_close_qp(qp);
+		} else {
+			ib_uverbs_detach_umcast(qp, uqp);
+			ib_destroy_qp(qp);
+		}
 		ib_uverbs_release_uevent(file, &uqp->uevent);
 		kfree(uqp);
 	}
@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(st
 		kfree(uobj);
 	}
 
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+		struct ib_xrcd *xrcd = uobj->object;
+		struct ib_uxrcd_object *uxrcd =
+			container_of(uobj, struct ib_uxrcd_object, uobject);
+
+		idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+		ib_uverbs_dealloc_xrcd(file->device, xrcd);
+		kfree(uxrcd);
+	}
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
 	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
 		struct ib_pd *pd = uobj->object;
 
@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct fi
 	if (hdr.in_words * 4 != count)
 		return -EINVAL;
 
-	if (hdr.command < 0				||
-	    hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+	if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
 	    !uverbs_cmd_table[hdr.command])
 		return -EINVAL;
 
@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_
 
 	kref_init(&uverbs_dev->ref);
 	init_completion(&uverbs_dev->comp);
+	uverbs_dev->xrcd_tree = RB_ROOT;
+	mutex_init(&uverbs_dev->xrcd_tree_mutex);
 
 	spin_lock(&map_lock);
 	devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_marshall.c linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_marshall.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/uverbs_marshall.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/uverbs_marshall.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */
 
+#include <linux/export.h>
 #include <rdma/ib_marshall.h>
 
 void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/core/verbs.c linux-libre-3.2-gnu1/drivers/infiniband/core/verbs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/core/verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/core/verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,9 @@
 
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
@@ -77,6 +79,31 @@ enum ib_rate mult_to_ib_rate(int mult)
 }
 EXPORT_SYMBOL(mult_to_ib_rate);
 
+int ib_rate_to_mbps(enum ib_rate rate)
+{
+	switch (rate) {
+	case IB_RATE_2_5_GBPS: return 2500;
+	case IB_RATE_5_GBPS:   return 5000;
+	case IB_RATE_10_GBPS:  return 10000;
+	case IB_RATE_20_GBPS:  return 20000;
+	case IB_RATE_30_GBPS:  return 30000;
+	case IB_RATE_40_GBPS:  return 40000;
+	case IB_RATE_60_GBPS:  return 60000;
+	case IB_RATE_80_GBPS:  return 80000;
+	case IB_RATE_120_GBPS: return 120000;
+	case IB_RATE_14_GBPS:  return 14062;
+	case IB_RATE_56_GBPS:  return 56250;
+	case IB_RATE_112_GBPS: return 112500;
+	case IB_RATE_168_GBPS: return 168750;
+	case IB_RATE_25_GBPS:  return 25781;
+	case IB_RATE_100_GBPS: return 103125;
+	case IB_RATE_200_GBPS: return 206250;
+	case IB_RATE_300_GBPS: return 309375;
+	default:	       return -1;
+	}
+}
+EXPORT_SYMBOL(ib_rate_to_mbps);
+
 enum rdma_transport_type
 rdma_node_get_transport(enum rdma_node_type node_type)
 {
@@ -250,6 +277,13 @@ struct ib_srq *ib_create_srq(struct ib_p
 		srq->uobject       = NULL;
 		srq->event_handler = srq_init_attr->event_handler;
 		srq->srq_context   = srq_init_attr->srq_context;
+		srq->srq_type      = srq_init_attr->srq_type;
+		if (srq->srq_type == IB_SRQT_XRC) {
+			srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
+			srq->ext.xrc.cq   = srq_init_attr->ext.xrc.cq;
+			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+			atomic_inc(&srq->ext.xrc.cq->usecnt);
+		}
 		atomic_inc(&pd->usecnt);
 		atomic_set(&srq->usecnt, 0);
 	}
@@ -279,16 +313,29 @@ EXPORT_SYMBOL(ib_query_srq);
 int ib_destroy_srq(struct ib_srq *srq)
 {
 	struct ib_pd *pd;
+	enum ib_srq_type srq_type;
+	struct ib_xrcd *uninitialized_var(xrcd);
+	struct ib_cq *uninitialized_var(cq);
 	int ret;
 
 	if (atomic_read(&srq->usecnt))
 		return -EBUSY;
 
 	pd = srq->pd;
+	srq_type = srq->srq_type;
+	if (srq_type == IB_SRQT_XRC) {
+		xrcd = srq->ext.xrc.xrcd;
+		cq = srq->ext.xrc.cq;
+	}
 
 	ret = srq->device->destroy_srq(srq);
-	if (!ret)
+	if (!ret) {
 		atomic_dec(&pd->usecnt);
+		if (srq_type == IB_SRQT_XRC) {
+			atomic_dec(&xrcd->usecnt);
+			atomic_dec(&cq->usecnt);
+		}
+	}
 
 	return ret;
 }
@@ -296,28 +343,123 @@ EXPORT_SYMBOL(ib_destroy_srq);
 
 /* Queue pairs */
 
+static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
+{
+	struct ib_qp *qp = context;
+
+	list_for_each_entry(event->element.qp, &qp->open_list, open_list)
+		event->element.qp->event_handler(event, event->element.qp->qp_context);
+}
+
+static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
+{
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+}
+
+static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
+				  void (*event_handler)(struct ib_event *, void *),
+				  void *qp_context)
+{
+	struct ib_qp *qp;
+	unsigned long flags;
+
+	qp = kzalloc(sizeof *qp, GFP_KERNEL);
+	if (!qp)
+		return ERR_PTR(-ENOMEM);
+
+	qp->real_qp = real_qp;
+	atomic_inc(&real_qp->usecnt);
+	qp->device = real_qp->device;
+	qp->event_handler = event_handler;
+	qp->qp_context = qp_context;
+	qp->qp_num = real_qp->qp_num;
+	qp->qp_type = real_qp->qp_type;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_add(&qp->open_list, &real_qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	return qp;
+}
+
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+			 struct ib_qp_open_attr *qp_open_attr)
+{
+	struct ib_qp *qp, *real_qp;
+
+	if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
+		return ERR_PTR(-EINVAL);
+
+	qp = ERR_PTR(-EINVAL);
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
+		if (real_qp->qp_num == qp_open_attr->qp_num) {
+			qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
+					  qp_open_attr->qp_context);
+			break;
+		}
+	}
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+	return qp;
+}
+EXPORT_SYMBOL(ib_open_qp);
+
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
 			   struct ib_qp_init_attr *qp_init_attr)
 {
-	struct ib_qp *qp;
+	struct ib_qp *qp, *real_qp;
+	struct ib_device *device;
 
-	qp = pd->device->create_qp(pd, qp_init_attr, NULL);
+	device = pd ? pd->device : qp_init_attr->xrcd->device;
+	qp = device->create_qp(pd, qp_init_attr, NULL);
 
 	if (!IS_ERR(qp)) {
-		qp->device     	  = pd->device;
-		qp->pd         	  = pd;
-		qp->send_cq    	  = qp_init_attr->send_cq;
-		qp->recv_cq    	  = qp_init_attr->recv_cq;
-		qp->srq	       	  = qp_init_attr->srq;
-		qp->uobject       = NULL;
-		qp->event_handler = qp_init_attr->event_handler;
-		qp->qp_context    = qp_init_attr->qp_context;
-		qp->qp_type	  = qp_init_attr->qp_type;
-		atomic_inc(&pd->usecnt);
-		atomic_inc(&qp_init_attr->send_cq->usecnt);
-		atomic_inc(&qp_init_attr->recv_cq->usecnt);
-		if (qp_init_attr->srq)
-			atomic_inc(&qp_init_attr->srq->usecnt);
+		qp->device     = device;
+		qp->real_qp    = qp;
+		qp->uobject    = NULL;
+		qp->qp_type    = qp_init_attr->qp_type;
+
+		if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
+			qp->event_handler = __ib_shared_qp_event_handler;
+			qp->qp_context = qp;
+			qp->pd = NULL;
+			qp->send_cq = qp->recv_cq = NULL;
+			qp->srq = NULL;
+			qp->xrcd = qp_init_attr->xrcd;
+			atomic_inc(&qp_init_attr->xrcd->usecnt);
+			INIT_LIST_HEAD(&qp->open_list);
+			atomic_set(&qp->usecnt, 0);
+
+			real_qp = qp;
+			qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+					  qp_init_attr->qp_context);
+			if (!IS_ERR(qp))
+				__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+			else
+				real_qp->device->destroy_qp(real_qp);
+		} else {
+			qp->event_handler = qp_init_attr->event_handler;
+			qp->qp_context = qp_init_attr->qp_context;
+			if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+				qp->recv_cq = NULL;
+				qp->srq = NULL;
+			} else {
+				qp->recv_cq = qp_init_attr->recv_cq;
+				atomic_inc(&qp_init_attr->recv_cq->usecnt);
+				qp->srq = qp_init_attr->srq;
+				if (qp->srq)
+					atomic_inc(&qp_init_attr->srq->usecnt);
+			}
+
+			qp->pd	    = pd;
+			qp->send_cq = qp_init_attr->send_cq;
+			qp->xrcd    = NULL;
+
+			atomic_inc(&pd->usecnt);
+			atomic_inc(&qp_init_attr->send_cq->usecnt);
+		}
 	}
 
 	return qp;
@@ -326,8 +468,8 @@ EXPORT_SYMBOL(ib_create_qp);
 
 static const struct {
 	int			valid;
-	enum ib_qp_attr_mask	req_param[IB_QPT_RAW_ETHERTYPE + 1];
-	enum ib_qp_attr_mask	opt_param[IB_QPT_RAW_ETHERTYPE + 1];
+	enum ib_qp_attr_mask	req_param[IB_QPT_MAX];
+	enum ib_qp_attr_mask	opt_param[IB_QPT_MAX];
 } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
 	[IB_QPS_RESET] = {
 		[IB_QPS_RESET] = { .valid = 1 },
@@ -343,6 +485,12 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -365,6 +513,12 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -384,6 +538,16 @@ static const struct {
 						IB_QP_RQ_PSN			|
 						IB_QP_MAX_DEST_RD_ATOMIC	|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN),
+				[IB_QPT_XRC_TGT] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_MIN_RNR_TIMER),
 			},
 			.opt_param = {
 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
@@ -394,6 +558,12 @@ static const struct {
 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -414,6 +584,13 @@ static const struct {
 						IB_QP_RNR_RETRY			|
 						IB_QP_SQ_PSN			|
 						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT		|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_SQ_PSN			|
+						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT		|
+						IB_QP_SQ_PSN),
 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
 			},
@@ -429,6 +606,15 @@ static const struct {
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_MIN_RNR_TIMER		|
 						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_MIN_RNR_TIMER		|
+						 IB_QP_PATH_MIG_STATE),
 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
@@ -453,6 +639,15 @@ static const struct {
 						IB_QP_ALT_PATH			|
 						IB_QP_PATH_MIG_STATE		|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE		|
+						IB_QP_MIN_RNR_TIMER),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -465,6 +660,8 @@ static const struct {
 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
 			}
@@ -487,6 +684,15 @@ static const struct {
 						IB_QP_ACCESS_FLAGS		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -515,6 +721,25 @@ static const struct {
 						IB_QP_PKEY_INDEX		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_MAX_QP_RD_ATOMIC		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -579,7 +804,7 @@ int ib_modify_qp(struct ib_qp *qp,
 		 struct ib_qp_attr *qp_attr,
 		 int qp_attr_mask)
 {
-	return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL);
+	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
 }
 EXPORT_SYMBOL(ib_modify_qp);
 
@@ -589,11 +814,59 @@ int ib_query_qp(struct ib_qp *qp,
 		struct ib_qp_init_attr *qp_init_attr)
 {
 	return qp->device->query_qp ?
-		qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
+		qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
 		-ENOSYS;
 }
 EXPORT_SYMBOL(ib_query_qp);
 
+int ib_close_qp(struct ib_qp *qp)
+{
+	struct ib_qp *real_qp;
+	unsigned long flags;
+
+	real_qp = qp->real_qp;
+	if (real_qp == qp)
+		return -EINVAL;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_del(&qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	atomic_dec(&real_qp->usecnt);
+	kfree(qp);
+
+	return 0;
+}
+EXPORT_SYMBOL(ib_close_qp);
+
+static int __ib_destroy_shared_qp(struct ib_qp *qp)
+{
+	struct ib_xrcd *xrcd;
+	struct ib_qp *real_qp;
+	int ret;
+
+	real_qp = qp->real_qp;
+	xrcd = real_qp->xrcd;
+
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	ib_close_qp(qp);
+	if (atomic_read(&real_qp->usecnt) == 0)
+		list_del(&real_qp->xrcd_list);
+	else
+		real_qp = NULL;
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+
+	if (real_qp) {
+		ret = ib_destroy_qp(real_qp);
+		if (!ret)
+			atomic_dec(&xrcd->usecnt);
+		else
+			__ib_insert_xrcd_qp(xrcd, real_qp);
+	}
+
+	return 0;
+}
+
 int ib_destroy_qp(struct ib_qp *qp)
 {
 	struct ib_pd *pd;
@@ -601,16 +874,25 @@ int ib_destroy_qp(struct ib_qp *qp)
 	struct ib_srq *srq;
 	int ret;
 
-	pd  = qp->pd;
-	scq = qp->send_cq;
-	rcq = qp->recv_cq;
-	srq = qp->srq;
+	if (atomic_read(&qp->usecnt))
+		return -EBUSY;
+
+	if (qp->real_qp != qp)
+		return __ib_destroy_shared_qp(qp);
+
+	pd   = qp->pd;
+	scq  = qp->send_cq;
+	rcq  = qp->recv_cq;
+	srq  = qp->srq;
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
-		atomic_dec(&pd->usecnt);
-		atomic_dec(&scq->usecnt);
-		atomic_dec(&rcq->usecnt);
+		if (pd)
+			atomic_dec(&pd->usecnt);
+		if (scq)
+			atomic_dec(&scq->usecnt);
+		if (rcq)
+			atomic_dec(&rcq->usecnt);
 		if (srq)
 			atomic_dec(&srq->usecnt);
 	}
@@ -920,3 +1202,42 @@ int ib_detach_mcast(struct ib_qp *qp, un
 	return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
+
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
+{
+	struct ib_xrcd *xrcd;
+
+	if (!device->alloc_xrcd)
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = device->alloc_xrcd(device, NULL, NULL);
+	if (!IS_ERR(xrcd)) {
+		xrcd->device = device;
+		xrcd->inode = NULL;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+	}
+
+	return xrcd;
+}
+EXPORT_SYMBOL(ib_alloc_xrcd);
+
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	struct ib_qp *qp;
+	int ret;
+
+	if (atomic_read(&xrcd->usecnt))
+		return -EBUSY;
+
+	while (!list_empty(&xrcd->tgt_qp_list)) {
+		qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
+		ret = ib_destroy_qp(qp);
+		if (ret)
+			return ret;
+	}
+
+	return xrcd->device->dealloc_xrcd(xrcd);
+}
+EXPORT_SYMBOL(ib_dealloc_xrcd);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_ae.c linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_ae.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_ae.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_ae.c	2012-01-04 18:55:44.000000000 -0500
@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u
 		cm_event.private_data_len =
 			be32_to_cpu(req->private_data_length);
 		cm_event.private_data = req->private_data;
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 
 		if (cm_id->event_handler)
 			cm_id->event_handler(cm_id, &cm_event);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2.c linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2.c	2012-01-04 18:55:44.000000000 -0500
@@ -800,13 +800,10 @@ static int c2_xmit_frame(struct sk_buff
 	/* Loop thru additional data fragments and queue them */
 	if (skb_shinfo(skb)->nr_frags) {
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			maplen = frag->size;
-			mapaddr =
-			    pci_map_page(c2dev->pcidev, frag->page,
-					 frag->page_offset, maplen,
-					 PCI_DMA_TODEVICE);
-
+			const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			maplen = skb_frag_size(frag);
+			mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag,
+						   0, maplen, DMA_TO_DEVICE);
 			elem = elem->next;
 			elem->skb = NULL;
 			elem->mapaddr = mapaddr;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_intr.c linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_intr.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_intr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_intr.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2d
 	case IW_CM_EVENT_ESTABLISHED:
 		c2_set_qp_state(req->qp,
 				C2_QP_STATE_RTS);
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 	case IW_CM_EVENT_CLOSE:
 
 		/*
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_provider.c linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_provider.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/amso1100/c2_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/amso1100/c2_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,10 +753,7 @@ static struct net_device *c2_pseudo_netd
 	memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
 
 	/* Print out the MAC address */
-	pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
-		netdev->name,
-		netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-		netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+	pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
 
 #if 0
 	/* Disable network packets */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,6 +753,11 @@ static void connect_request_upcall(struc
 	event.private_data_len = ep->plen;
 	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -770,6 +775,11 @@ static void established_upcall(struct iw
 	PDBG("%s ep %p\n", __func__, ep);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -1365,8 +1375,10 @@ static int pass_accept_req(struct t3cdev
 		goto reject;
 	}
 	dst = &rt->dst;
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	l2t = t3_l2t_get(tdev, neigh, neigh->dev);
+	rcu_read_unlock();
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
 		       __func__);
@@ -1936,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id,
 	}
 	ep->dst = &rt->dst;
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(ep->dst);
 
 	/* get a l2t entry */
 	ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
+	rcu_read_unlock();
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 		err = -ENOMEM;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_ev.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_ev.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_ev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_ev.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_de
 	struct ib_event event;
 	struct iwch_qp_attributes attrs;
 	struct iwch_qp *qhp;
+	unsigned long flag;
 
 	spin_lock(&rnicp->lock);
 	qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_de
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 
 	if (atomic_dec_and_test(&qhp->refcnt))
 		wake_up(&qhp->wait);
@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *
 	struct iwch_cq *chp;
 	struct iwch_qp *qhp;
 	u32 cqid = RSPQ_CQID(rsp_msg);
+	unsigned long flag;
 
 	rnicp = (struct iwch_dev *) rdev_p->ulp;
 	spin_lock(&rnicp->lock);
@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *
 		 */
 		if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
 			dst_confirm(qhp->ep->dst);
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 		break;
 
 	case TPT_ERR_STAG:
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,6 +190,7 @@ static struct ib_cq *iwch_create_cq(stru
 	chp->rhp = rhp;
 	chp->ibcq.cqe = 1 << chp->cq.size_log2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h	2012-01-04 18:55:44.000000000 -0500
@@ -103,6 +103,7 @@ struct iwch_cq {
 	struct iwch_dev *rhp;
 	struct t3_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 	u32 __user *user_rptr_addr;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *q
 	flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, *flag);
@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *q
 	flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
+	}
 
 	/* deref */
 	if (atomic_dec_and_test(&qhp->refcnt))
@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp
 	if (qhp->ibqp.uobject) {
 		cxio_set_wq_in_error(&qhp->wq);
 		cxio_set_cq_in_error(&rchp->cq);
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
 		if (schp != rchp) {
 			cxio_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 			(*schp->ibcq.comp_handler)(&schp->ibcq,
 						   schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
 		}
 		return;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/Makefile linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/Makefile
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb3/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb3/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb3
 
 obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/cm.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,7 +103,8 @@ MODULE_PARM_DESC(ep_timeout_secs, "CM En
 static int mpa_rev = 1;
 module_param(mpa_rev, int, 0644);
 MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
-		 "1 is spec compliant. (default=1)");
+		"1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+		" compliant (default=1)");
 
 static int markers_enabled;
 module_param(markers_enabled, int, 0644);
@@ -497,17 +498,21 @@ static int send_connect(struct c4iw_ep *
 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
+static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+		u8 mpa_rev_to_use)
 {
 	int mpalen, wrlen;
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	BUG_ON(skb_cloned(skb));
 
 	mpalen = sizeof(*mpa) + ep->plen;
+	if (mpa_rev_to_use == 2)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 	skb = get_skb(skb, wrlen, GFP_KERNEL);
 	if (!skb) {
@@ -533,12 +538,41 @@ static void send_mpa_req(struct c4iw_ep
 	mpa = (struct mpa_message *)(req + 1);
 	memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
 	mpa->flags = (crc_enabled ? MPA_CRC : 0) |
-		     (markers_enabled ? MPA_MARKERS : 0);
+		     (markers_enabled ? MPA_MARKERS : 0) |
+		     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
 	mpa->private_data_size = htons(ep->plen);
-	mpa->revision = mpa_rev;
+	mpa->revision = mpa_rev_to_use;
+	if (mpa_rev_to_use == 1) {
+		ep->tried_with_mpa_v1 = 1;
+		ep->retry_with_mpa_v1 = 0;
+	}
 
-	if (ep->plen)
-		memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+	if (mpa_rev_to_use == 2) {
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+
+		if (peer2peer) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params),
+			       ep->mpa_pkt + sizeof(*mpa), ep->plen);
+	} else
+		if (ep->plen)
+			memcpy(mpa->private_data,
+					ep->mpa_pkt + sizeof(*mpa), ep->plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -562,10 +596,13 @@ static int send_mpa_reject(struct c4iw_e
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -595,8 +632,29 @@ static int send_mpa_reject(struct c4iw_e
 	mpa->flags = MPA_REJECT;
 	mpa->revision = mpa_rev;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons(((u16)ep->ird) |
+					  (peer2peer ? MPA_V2_PEER2PEER_MODEL :
+					   0));
+		mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
+					  (p2p_type ==
+					   FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
+					   MPA_V2_RDMA_WRITE_RTR : p2p_type ==
+					   FW_RI_INIT_P2PTYPE_READ_REQ ?
+					   MPA_V2_RDMA_READ_RTR : 0) : 0));
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb again.  This ensures the data area
@@ -617,10 +675,13 @@ static int send_mpa_reply(struct c4iw_ep
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -649,10 +710,36 @@ static int send_mpa_reply(struct c4iw_ep
 	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
 	mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
 		     (markers_enabled ? MPA_MARKERS : 0);
-	mpa->revision = mpa_rev;
+	mpa->revision = ep->mpa_attr.version;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+		if (peer2peer && (ep->mpa_attr.p2p_type !=
+					FW_RI_INIT_P2PTYPE_DISABLED)) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -695,7 +782,10 @@ static int act_establish(struct c4iw_dev
 
 	/* start MPA negotiation */
 	send_flowc(ep, NULL);
-	send_mpa_req(ep, skb);
+	if (ep->retry_with_mpa_v1)
+		send_mpa_req(ep, skb, 1);
+	else
+		send_mpa_req(ep, skb, mpa_rev);
 
 	return 0;
 }
@@ -769,8 +859,19 @@ static void connect_reply_upcall(struct
 	event.remote_addr = ep->com.remote_addr;
 
 	if ((status == 0) || (status == -ECONNREFUSED)) {
-		event.private_data_len = ep->plen;
-		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+		if (!ep->tried_with_mpa_v1) {
+			/* this means MPA_v2 is used */
+			event.private_data_len = ep->plen -
+				sizeof(struct mpa_v2_conn_params);
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message) +
+				sizeof(struct mpa_v2_conn_params);
+		} else {
+			/* this means MPA_v1 is used */
+			event.private_data_len = ep->plen;
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message);
+		}
 	}
 
 	PDBG("%s ep %p tid %u status %d\n", __func__, ep,
@@ -793,9 +894,22 @@ static void connect_request_upcall(struc
 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	event.local_addr = ep->com.local_addr;
 	event.remote_addr = ep->com.remote_addr;
-	event.private_data_len = ep->plen;
-	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	if (!ep->tried_with_mpa_v1) {
+		/* this means MPA_v2 is used */
+		event.ord = ep->ord;
+		event.ird = ep->ird;
+		event.private_data_len = ep->plen -
+			sizeof(struct mpa_v2_conn_params);
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
+			sizeof(struct mpa_v2_conn_params);
+	} else {
+		/* this means MPA_v1 is used. Send max supported */
+		event.ord = c4iw_max_read_depth;
+		event.ird = c4iw_max_read_depth;
+		event.private_data_len = ep->plen;
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+	}
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		c4iw_get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -813,6 +927,8 @@ static void established_upcall(struct c4
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	event.ird = ep->ird;
+	event.ord = ep->ord;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -848,7 +964,10 @@ static int update_rx_credits(struct c4iw
 static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
+	u16 resp_ird, resp_ord;
+	u8 rtr_mismatch = 0, insuff_ird = 0;
 	struct c4iw_qp_attributes attrs;
 	enum c4iw_qp_attr_mask mask;
 	int err;
@@ -888,7 +1007,9 @@ static void process_mpa_reply(struct c4i
 	mpa = (struct mpa_message *) ep->mpa_pkt;
 
 	/* Validate MPA header. */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		err = -EPROTO;
 		goto err;
 	}
@@ -938,13 +1059,66 @@ static void process_mpa_reply(struct c4i
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			resp_ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			resp_ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+
+			/*
+			 * This is a double-check. Ideally, below checks are
+			 * not required since ird/ord stuff has been taken
+			 * care of in c4iw_accept_cr
+			 */
+			if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+				err = -ENOMEM;
+				ep->ird = resp_ord;
+				ep->ord = resp_ird;
+				insuff_ird = 1;
+			}
+
+			if (ntohs(mpa_v2_params->ird) &
+					MPA_V2_PEER2PEER_MODEL) {
+				if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_WRITE_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+				else if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_READ_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+			}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
-	     "xmit_marker_enabled=%d, version=%d\n", __func__,
-	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
-	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+	     "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
+	     "%d\n", __func__, ep->mpa_attr.crc_enabled,
+	     ep->mpa_attr.recv_marker_enabled,
+	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
+	     ep->mpa_attr.p2p_type, p2p_type);
+
+	/*
+	 * If responder's RTR does not match with that of initiator, assign
+	 * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
+	 * generated when moving QP to RTS state.
+	 * A TERM message will be sent after QP has moved to RTS state
+	 */
+	if ((ep->mpa_attr.version == 2) &&
+			(ep->mpa_attr.p2p_type != p2p_type)) {
+		ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+		rtr_mismatch = 1;
+	}
 
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -961,6 +1135,39 @@ static void process_mpa_reply(struct c4i
 			     ep->com.qp, mask, &attrs, 1);
 	if (err)
 		goto err;
+
+	/*
+	 * If responder's RTR requirement did not match with what initiator
+	 * supports, generate TERM message
+	 */
+	if (rtr_mismatch) {
+		printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_NOMATCH_RTR;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Generate TERM if initiator IRD is not sufficient for responder
+	 * provided ORD. Currently, we do the same behaviour even when
+	 * responder provided IRD is also not sufficient as regards to
+	 * initiator ORD.
+	 */
+	if (insuff_ird) {
+		printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
+				__func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_INSUFF_IRD;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
 	goto out;
 err:
 	state_set(&ep->com, ABORTING);
@@ -973,6 +1180,7 @@ out:
 static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1013,7 +1221,9 @@ static void process_mpa_request(struct c
 	/*
 	 * Validate MPA Header.
 	 */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1056,9 +1266,37 @@ static void process_mpa_request(struct c
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	if (mpa->revision == 1)
+		ep->tried_with_mpa_v1 = 1;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			ep->ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			ep->ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+			if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
+				if (peer2peer) {
+					if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_WRITE_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+					else if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_READ_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+				}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
 	     "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
@@ -1358,6 +1596,7 @@ static int pass_accept_req(struct c4iw_d
 		goto reject;
 	}
 	dst = &rt->dst;
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	if (neigh->dev->flags & IFF_LOOPBACK) {
 		pdev = ip_dev_find(&init_net, peer_ip);
@@ -1384,6 +1623,7 @@ static int pass_accept_req(struct c4iw_d
 		rss_qid = dev->rdev.lldi.rxq_ids[
 			  cxgb4_port_idx(neigh->dev) * step];
 	}
+	rcu_read_unlock();
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
 		       __func__);
@@ -1550,6 +1790,114 @@ static int is_neg_adv_abort(unsigned int
 	       status == CPL_ERR_PERSIST_NEG_ADVICE;
 }
 
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+	int err = 0;
+	struct rtable *rt;
+	struct net_device *pdev;
+	struct neighbour *neigh;
+	int step;
+
+	PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+	init_timer(&ep->timer);
+
+	/*
+	 * Allocate an active TID to initiate a TCP connection.
+	 */
+	ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+	if (ep->atid == -1) {
+		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	/* find a route */
+	rt = find_route(ep->com.dev,
+			ep->com.cm_id->local_addr.sin_addr.s_addr,
+			ep->com.cm_id->remote_addr.sin_addr.s_addr,
+			ep->com.cm_id->local_addr.sin_port,
+			ep->com.cm_id->remote_addr.sin_port, 0);
+	if (!rt) {
+		printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+		err = -EHOSTUNREACH;
+		goto fail3;
+	}
+	ep->dst = &rt->dst;
+
+	rcu_read_lock();
+	neigh = dst_get_neighbour(ep->dst);
+
+	/* get a l2t entry */
+	if (neigh->dev->flags & IFF_LOOPBACK) {
+		PDBG("%s LOOPBACK\n", __func__);
+		pdev = ip_dev_find(&init_net,
+				   ep->com.cm_id->remote_addr.sin_addr.s_addr);
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, pdev, 0);
+		ep->mtu = pdev->mtu;
+		ep->tx_chan = cxgb4_port_chan(pdev);
+		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(pdev) * step;
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->ctrlq_idx = cxgb4_port_idx(pdev);
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(pdev) * step];
+		dev_put(pdev);
+	} else {
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, neigh->dev, 0);
+		ep->mtu = dst_mtu(ep->dst);
+		ep->tx_chan = cxgb4_port_chan(neigh->dev);
+		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(neigh->dev) * step];
+	}
+	rcu_read_unlock();
+	if (!ep->l2t) {
+		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+		err = -ENOMEM;
+		goto fail4;
+	}
+
+	PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+	     __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+	     ep->l2t->idx);
+
+	state_set(&ep->com, CONNECTING);
+	ep->tos = 0;
+
+	/* send connect request to rnic */
+	err = send_connect(ep);
+	if (!err)
+		goto out;
+
+	cxgb4_l2t_release(ep->l2t);
+fail4:
+	dst_release(ep->dst);
+fail3:
+	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+	/*
+	 * remember to send notification to upper layer.
+	 * We are in here so the upper layer is not aware that this is
+	 * re-connect attempt and so, upper layer is still waiting for
+	 * response of 1st connect request.
+	 */
+	connect_reply_upcall(ep, -ECONNRESET);
+	c4iw_put_ep(&ep->com);
+out:
+	return err;
+}
+
 static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1573,8 +1921,11 @@ static int peer_abort(struct c4iw_dev *d
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 
 	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
@@ -1585,7 +1936,21 @@ static int peer_abort(struct c4iw_dev *d
 		break;
 	case MPA_REQ_SENT:
 		stop_ep_timer(ep);
-		connect_reply_upcall(ep, -ECONNRESET);
+		if (mpa_rev == 2 && ep->tried_with_mpa_v1)
+			connect_reply_upcall(ep, -ECONNRESET);
+		else {
+			/*
+			 * we just don't send notification upwards because we
+			 * want to retry with mpa_v1 without upper layers even
+			 * knowing it.
+			 *
+			 * do some housekeeping so as to re-initiate the
+			 * connection
+			 */
+			PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
+			     mpa_rev);
+			ep->retry_with_mpa_v1 = 1;
+		}
 		break;
 	case MPA_REP_SENT:
 		break;
@@ -1621,7 +1986,9 @@ static int peer_abort(struct c4iw_dev *d
 	dst_confirm(ep->dst);
 	if (ep->com.state != ABORTING) {
 		__state_set(&ep->com, DEAD);
-		release = 1;
+		/* we don't release if we want to retry with mpa_v1 */
+		if (!ep->retry_with_mpa_v1)
+			release = 1;
 	}
 	mutex_unlock(&ep->com.mutex);
 
@@ -1641,6 +2008,15 @@ static int peer_abort(struct c4iw_dev *d
 out:
 	if (release)
 		release_ep_resources(ep);
+
+	/* retry with mpa-v1 */
+	if (ep && ep->retry_with_mpa_v1) {
+		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
+		dst_release(ep->dst);
+		cxgb4_l2t_release(ep->l2t);
+		c4iw_reconnect(ep);
+	}
+
 	return 0;
 }
 
@@ -1792,18 +2168,40 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 		goto err;
 	}
 
-	cm_id->add_ref(cm_id);
-	ep->com.cm_id = cm_id;
-	ep->com.qp = qp;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		if (conn_param->ord > ep->ird) {
+			ep->ird = conn_param->ird;
+			ep->ord = conn_param->ord;
+			send_mpa_reject(ep, conn_param->private_data,
+					conn_param->private_data_len);
+			abort_connection(ep, NULL, GFP_KERNEL);
+			err = -ENOMEM;
+			goto err;
+		}
+		if (conn_param->ird > ep->ord) {
+			if (!ep->ord)
+				conn_param->ird = 1;
+			else {
+				abort_connection(ep, NULL, GFP_KERNEL);
+				err = -ENOMEM;
+				goto err;
+			}
+		}
 
+	}
 	ep->ird = conn_param->ird;
 	ep->ord = conn_param->ord;
 
-	if (peer2peer && ep->ird == 0)
-		ep->ird = 1;
+	if (ep->mpa_attr.version != 2)
+		if (peer2peer && ep->ird == 0)
+			ep->ird = 1;
 
 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->com.qp = qp;
+
 	/* bind QP to EP and move to RTS */
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -1909,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id,
 	}
 	ep->dst = &rt->dst;
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(ep->dst);
 
 	/* get a l2t entry */
@@ -1944,7 +2343,10 @@ int c4iw_connect(struct iw_cm_id *cm_id,
 		       ep->com.dev->rdev.lldi.nchan;
 		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
 			      cxgb4_port_idx(neigh->dev) * step];
+		ep->retry_with_mpa_v1 = 0;
+		ep->tried_with_mpa_v1 = 0;
 	}
+	rcu_read_unlock();
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 		err = -ENOMEM;
@@ -2323,8 +2725,11 @@ static int peer_abort_intr(struct c4iw_d
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 	sched(dev, skb);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/cq.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/cq.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/cq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/cq.c	2012-01-04 18:55:44.000000000 -0500
@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq
 				 V_CQE_OPCODE(FW_RI_SEND) |
 				 V_CQE_TYPE(0) |
 				 V_CQE_SWCQE(1) |
-				 V_CQE_QPID(wq->rq.qid));
+				 V_CQE_QPID(wq->sq.qid));
 	cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
 	cq->sw_queue[cq->sw_pidx] = cqe;
 	t4_swcq_produce(cq);
@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq,
 	while (ptr != cq->sw_pidx) {
 		cqe = &cq->sw_queue[ptr];
 		if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
-		    (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq))
+		    (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
 			(*count)++;
 		if (++ptr == cq->size)
 			ptr = 0;
@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_d
 	chp->cq.size--;				/* status page */
 	chp->ibcq.cqe = entries - 2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/device.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/device.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/device.c	2012-01-04 18:55:44.000000000 -0500
@@ -376,10 +376,8 @@ struct uld_ctx {
 	struct c4iw_dev *dev;
 };
 
-static void c4iw_remove(struct uld_ctx *ctx)
+static void c4iw_dealloc(struct uld_ctx *ctx)
 {
-	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
-	c4iw_unregister_device(ctx->dev);
 	c4iw_rdev_close(&ctx->dev->rdev);
 	idr_destroy(&ctx->dev->cqidr);
 	idr_destroy(&ctx->dev->qpidr);
@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *
 	ctx->dev = NULL;
 }
 
+static void c4iw_remove(struct uld_ctx *ctx)
+{
+	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
+	c4iw_unregister_device(ctx->dev);
+	c4iw_dealloc(ctx);
+}
+
+static int rdma_supported(const struct cxgb4_lld_info *infop)
+{
+	return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
+	       infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
+	       infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+}
+
 static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 {
 	struct c4iw_dev *devp;
 	int ret;
 
+	if (!rdma_supported(infop)) {
+		printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
+		       pci_name(infop->pdev));
+		return ERR_PTR(-ENOSYS);
+	}
 	devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
 	if (!devp) {
 		printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const
 
 	ret = c4iw_rdev_open(&devp->rdev);
 	if (ret) {
-		mutex_unlock(&dev_mutex);
 		printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
 		ib_dealloc_device(&devp->ibdev);
 		return ERR_PTR(ret);
@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *h
 	case CXGB4_STATE_UP:
 		printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
 		if (!ctx->dev) {
-			int ret = 0;
+			int ret;
 
 			ctx->dev = c4iw_alloc(&ctx->lldi);
-			if (!IS_ERR(ctx->dev))
-				ret = c4iw_register_device(ctx->dev);
-			if (IS_ERR(ctx->dev) || ret)
+			if (IS_ERR(ctx->dev)) {
+				printk(KERN_ERR MOD
+				       "%s: initialization failed: %ld\n",
+				       pci_name(ctx->lldi.pdev),
+				       PTR_ERR(ctx->dev));
+				ctx->dev = NULL;
+				break;
+			}
+			ret = c4iw_register_device(ctx->dev);
+			if (ret) {
 				printk(KERN_ERR MOD
 				       "%s: RDMA registration failed: %d\n",
 				       pci_name(ctx->lldi.pdev), ret);
+				c4iw_dealloc(ctx);
+			}
 		}
 		break;
 	case CXGB4_STATE_DOWN:
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/ev.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/ev.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/ev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/ev.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_de
 {
 	struct ib_event event;
 	struct c4iw_qp_attributes attrs;
+	unsigned long flag;
 
 	if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
 	    (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_de
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 }
 
 void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
@@ -183,11 +186,14 @@ out:
 int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 {
 	struct c4iw_cq *chp;
+	unsigned long flag;
 
 	chp = get_chp(dev, qid);
-	if (chp)
+	if (chp) {
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
-	else
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
+	} else
 		PDBG("%s unknown cqid 0x%x\n", __func__, qid);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2012-01-04 18:55:44.000000000 -0500
@@ -309,6 +309,7 @@ struct c4iw_cq {
 	struct c4iw_dev *rhp;
 	struct t4_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 };
@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes {
 	u8 recv_marker_enabled;
 	u8 xmit_marker_enabled;
 	u8 crc_enabled;
+	u8 enhanced_rdma_conn;
 	u8 version;
 	u8 p2p_type;
 };
@@ -349,6 +351,8 @@ struct c4iw_qp_attributes {
 	u8 is_terminate_local;
 	struct c4iw_mpa_attributes mpa_attr;
 	struct c4iw_ep *llp_stream_handle;
+	u8 layer_etype;
+	u8 ecode;
 };
 
 struct c4iw_qp {
@@ -501,11 +505,18 @@ enum c4iw_mmid_state {
 #define MPA_KEY_REP "MPA ID Rep Frame"
 
 #define MPA_MAX_PRIVATE_DATA	256
+#define MPA_ENHANCED_RDMA_CONN	0x10
 #define MPA_REJECT		0x20
 #define MPA_CRC			0x40
 #define MPA_MARKERS		0x80
 #define MPA_FLAGS_MASK		0xE0
 
+#define MPA_V2_PEER2PEER_MODEL          0x8000
+#define MPA_V2_ZERO_LEN_FPDU_RTR        0x4000
+#define MPA_V2_RDMA_WRITE_RTR           0x8000
+#define MPA_V2_RDMA_READ_RTR            0x4000
+#define MPA_V2_IRD_ORD_MASK             0x3FFF
+
 #define c4iw_put_ep(ep) { \
 	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
 	     ep, atomic_read(&((ep)->kref.refcount))); \
@@ -528,6 +539,11 @@ struct mpa_message {
 	u8 private_data[0];
 };
 
+struct mpa_v2_conn_params {
+	__be16 ird;
+	__be16 ord;
+};
+
 struct terminate_message {
 	u8 layer_etype;
 	u8 ecode;
@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes {
 
 enum c4iw_mpa_ecodes {
 	MPA_CRC_ERR		= 0x02,
-	MPA_MARKER_ERR		= 0x03
+	MPA_MARKER_ERR          = 0x03,
+	MPA_LOCAL_CATA          = 0x05,
+	MPA_INSUFF_IRD          = 0x06,
+	MPA_NOMATCH_RTR         = 0x07,
 };
 
 enum c4iw_ep_state {
@@ -651,6 +670,8 @@ struct c4iw_ep {
 	u16 txq_idx;
 	u16 ctrlq_idx;
 	u8 tos;
+	u8 retry_with_mpa_v1;
+	u8 tried_with_mpa_v1;
 };
 
 static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/Makefile linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/Makefile
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
 
 obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/qp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
+
+#include <linux/module.h>
+
 #include "iw_cxgb4.h"
 
 static int ocqp_support = 1;
@@ -917,7 +920,11 @@ static void post_terminate(struct c4iw_q
 	wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
 	wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
 	term = (struct terminate_message *)wqe->u.terminate.termmsg;
-	build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
+	if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
+		term->layer_etype = qhp->attr.layer_etype;
+		term->ecode = qhp->attr.ecode;
+	} else
+		build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
 	c4iw_ofld_send(&qhp->rhp->rdev, skb);
 }
 
@@ -941,8 +948,11 @@ static void __flush_qp(struct c4iw_qp *q
 	flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, flag);
@@ -952,13 +962,17 @@ static void __flush_qp(struct c4iw_qp *q
 	flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+	}
 }
 
 static void flush_qp(struct c4iw_qp *qhp)
 {
 	struct c4iw_cq *rchp, *schp;
+	unsigned long flag;
 
 	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
 	schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -966,8 +980,16 @@ static void flush_qp(struct c4iw_qp *qhp
 	if (qhp->ibqp.uobject) {
 		t4_set_wq_in_error(&qhp->wq);
 		t4_set_cq_in_error(&rchp->cq);
-		if (schp != rchp)
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+		if (schp != rchp) {
 			t4_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, flag);
+			(*schp->ibcq.comp_handler)(&schp->ibcq,
+					schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+		}
 		return;
 	}
 	__flush_qp(qhp, rchp, schp);
@@ -1012,6 +1034,7 @@ out:
 
 static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
 {
+	PDBG("%s p2p_type = %d\n", __func__, p2p_type);
 	memset(&init->u, 0, sizeof init->u);
 	switch (p2p_type) {
 	case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
@@ -1206,12 +1229,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp,
 				disconnect = 1;
 				c4iw_get_ep(&qhp->ep->com);
 			}
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			ret = rdma_fini(rhp, qhp, ep);
 			if (ret)
 				goto err;
 			break;
 		case C4IW_QP_STATE_TERMINATE:
 			set_state(qhp, C4IW_QP_STATE_TERMINATE);
+			qhp->attr.layer_etype = attrs->layer_etype;
+			qhp->attr.ecode = attrs->ecode;
 			if (qhp->ibqp.uobject)
 				t4_set_wq_in_error(&qhp->wq);
 			ep = qhp->ep;
@@ -1222,6 +1249,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp,
 			break;
 		case C4IW_QP_STATE_ERROR:
 			set_state(qhp, C4IW_QP_STATE_ERROR);
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			if (!internal) {
 				abort = 1;
 				disconnect = 1;
@@ -1334,7 +1363,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 	rhp = qhp->rhp;
 
 	attrs.next_state = C4IW_QP_STATE_ERROR;
-	c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+	if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+	else
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
 	wait_event(qhp->wait, !qhp->ep);
 
 	remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ehca/ehca_eq.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ehca/ehca_eq.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ehca/ehca_eq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ehca/ehca_eq.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shc
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
-					  IRQF_DISABLED, "ehca_eq",
+					  0, "ehca_eq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shc
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
-					  IRQF_DISABLED, "ehca_neq",
+					  0, "ehca_neq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ehca/ehca_qp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ehca/ehca_qp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ehca/ehca_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ehca/ehca_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib
 	struct hcp_modify_qp_control_block *mqpcb;
 	u64 hret, update_mask;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	/* For common attributes, internal_create_qp() takes its info
 	 * out of qp_init_attr, so copy all common attrs there.
 	 */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_diag.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_diag.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/export.h>
 #include <asm/uaccess.h>
 
 #include "ipath_kernel.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/vmalloc.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/cdev.h>
 #include <linux/swap.h>
+#include <linux/export.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,9 @@
 
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/moduleparam.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/vmalloc.h>
 
 #include "ipath_kernel.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_srq.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_srq.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct i
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_wr == 0) {
 		ret = ERR_PTR(-EINVAL);
 		goto done;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_sysfs.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_sysfs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
  */
 
 #include <linux/ctype.h>
+#include <linux/stat.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@ static int __ipath_get_user_pages(unsign
 			goto bail_release;
 	}
 
-	current->mm->locked_vm += num_pages;
+	current->mm->pinned_vm += num_pages;
 
 	ret = 0;
 	goto bail;
@@ -178,7 +178,7 @@ void ipath_release_user_pages(struct pag
 
 	__ipath_release_user_pages(p, num_pages, 1);
 
-	current->mm->locked_vm -= num_pages;
+	current->mm->pinned_vm -= num_pages;
 
 	up_write(&current->mm->mmap_sem);
 }
@@ -195,7 +195,7 @@ static void user_pages_account(struct wo
 		container_of(_work, struct ipath_user_pages_work, work);
 
 	down_write(&work->mm->mmap_sem);
-	work->mm->locked_vm -= work->num_pages;
+	work->mm->pinned_vm -= work->num_pages;
 	up_write(&work->mm->mmap_sem);
 	mmput(work->mm);
 	kfree(work);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_verbs.c linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_verbs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/ipath/ipath_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/ipath/ipath_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <rdma/ib_user_verbs.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/rculist.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/Kconfig linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/Kconfig
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 config MLX4_INFINIBAND
 	tristate "Mellanox ConnectX HCA support"
-	depends on NETDEVICES && NETDEV_10000 && PCI
+	depends on NETDEVICES && ETHERNET && PCI
+	select NET_VENDOR_MELLANOX
 	select MLX4_CORE
 	---help---
 	  This driver provides low-level InfiniBand support for
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/main.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct i
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
 		props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+		props->device_cap_flags |= IB_DEVICE_XRC;
 
 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
 		0xffffff;
@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device
 
 static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 			      struct ib_port_attr *props,
+			      struct ib_smp *in_mad,
 			      struct ib_smp *out_mad)
 {
+	int ext_active_speed;
+	int err;
+
 	props->lid		= be16_to_cpup((__be16 *) (out_mad->data + 16));
 	props->lmc		= out_mad->data[34] & 0x7;
 	props->sm_lid		= be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= out_mad->data[41] >> 4;
 
+	/* Check if extended speeds (EDR/FDR/...) are supported */
+	if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
+		ext_active_speed = out_mad->data[62] >> 4;
+
+		switch (ext_active_speed) {
+		case 1:
+			props->active_speed = 16; /* FDR */
+			break;
+		case 2:
+			props->active_speed = 32; /* EDR */
+			break;
+		}
+	}
+
+	/* If reported active speed is QDR, check if is FDR-10 */
+	if (props->active_speed == 4) {
+		if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
+		    MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
+			init_query_mad(in_mad);
+			in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
+			in_mad->attr_mod = cpu_to_be32(port);
+
+			err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+					   NULL, NULL, in_mad, out_mad);
+			if (err)
+				return err;
+
+			/* Checking LinkSpeedActive for FDR-10 */
+			if (out_mad->data[15] & 0x1)
+				props->active_speed = 8;
+		}
+	}
+
 	return 0;
 }
 
@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib
 	props->pkey_tbl_len	= 1;
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 46));
 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 48));
-	props->max_mtu		= IB_MTU_2048;
+	props->max_mtu		= IB_MTU_4096;
 	props->subnet_timeout	= 0;
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= 0;
@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_
 		goto out;
 
 	err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
-		ib_link_query_port(ibdev, port, props, out_mad) :
+		ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
 		eth_link_query_port(ibdev, port, props, out_mad);
 
 out:
@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_
 	return 0;
 }
 
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+					  struct ib_ucontext *context,
+					  struct ib_udata *udata)
+{
+	struct mlx4_ib_xrcd *xrcd;
+	int err;
+
+	if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+	if (!xrcd)
+		return ERR_PTR(-ENOMEM);
+
+	err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
+	if (err)
+		goto err1;
+
+	xrcd->pd = ib_alloc_pd(ibdev);
+	if (IS_ERR(xrcd->pd)) {
+		err = PTR_ERR(xrcd->pd);
+		goto err2;
+	}
+
+	xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
+	if (IS_ERR(xrcd->cq)) {
+		err = PTR_ERR(xrcd->cq);
+		goto err3;
+	}
+
+	return &xrcd->ibxrcd;
+
+err3:
+	ib_dealloc_pd(xrcd->pd);
+err2:
+	mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
+err1:
+	kfree(xrcd);
+	return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	ib_destroy_cq(to_mxrcd(xrcd)->cq);
+	ib_dealloc_pd(to_mxrcd(xrcd)->pd);
+	mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+	kfree(xrcd);
+
+	return 0;
+}
+
 static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
 {
 	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev
 		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_XSRQ)		|
+		(1ull << IB_USER_VERBS_CMD_OPEN_QP);
 
 	ibdev->ib_dev.query_device	= mlx4_ib_query_device;
 	ibdev->ib_dev.query_port	= mlx4_ib_query_port;
@@ -1093,6 +1185,14 @@ static void *mlx4_ib_add(struct mlx4_dev
 	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
 	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
 
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+		ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+		ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+		ibdev->ib_dev.uverbs_cmd_mask |=
+			(1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
+			(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
+	}
+
 	spin_lock_init(&iboe->lock);
 
 	if (init_node_data(ibdev))
@@ -1144,7 +1244,8 @@ err_reg:
 
 err_counter:
 	for (; i; --i)
-		mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+		if (ibdev->counters[i - 1] != -1)
+			mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
 
 err_map:
 	iounmap(ibdev->uar_map);
@@ -1175,7 +1276,8 @@ static void mlx4_ib_remove(struct mlx4_d
 	}
 	iounmap(ibdev->uar_map);
 	for (p = 0; p < ibdev->num_ports; ++p)
-		mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
+		if (ibdev->counters[p] != -1)
+			mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
 	mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
 		mlx4_CLOSE_PORT(dev, p);
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/mlx4_ib.h linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/mlx4_ib.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/mlx4_ib.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/mlx4_ib.h	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,13 @@ struct mlx4_ib_pd {
 	u32			pdn;
 };
 
+struct mlx4_ib_xrcd {
+	struct ib_xrcd		ibxrcd;
+	u32			xrcdn;
+	struct ib_pd	       *pd;
+	struct ib_cq	       *cq;
+};
+
 struct mlx4_ib_cq_buf {
 	struct mlx4_buf		buf;
 	struct mlx4_mtt		mtt;
@@ -138,6 +145,7 @@ struct mlx4_ib_qp {
 	struct mlx4_mtt		mtt;
 	int			buf_size;
 	struct mutex		mutex;
+	u16			xrcdn;
 	u32			flags;
 	u8			port;
 	u8			alt_port;
@@ -211,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(
 	return container_of(ibpd, struct mlx4_ib_pd, ibpd);
 }
 
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+	return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
 static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
 {
 	return container_of(ibcq, struct mlx4_ib_cq, ibcq);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/qp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_
 }
 
 static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-		       int is_user, int has_srq, struct mlx4_ib_qp *qp)
+		       int is_user, int has_rq, struct mlx4_ib_qp *qp)
 {
 	/* Sanity check RQ size before proceeding */
 	if (cap->max_recv_wr  > dev->dev->caps.max_wqes  ||
 	    cap->max_recv_sge > dev->dev->caps.max_rq_sg)
 		return -EINVAL;
 
-	if (has_srq) {
-		/* QPs attached to an SRQ should have no RQ */
+	if (!has_rq) {
 		if (cap->max_recv_wr)
 			return -EINVAL;
 
@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_
 	return 0;
 }
 
+static int qp_has_rq(struct ib_qp_init_attr *attr)
+{
+	if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
+		return 0;
+
+	return !attr->srq;
+}
+
 static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 			    struct ib_qp_init_attr *init_attr,
 			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_
 	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
 		qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
 
-	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
 	if (err)
 		goto err;
 
@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_
 		if (err)
 			goto err_mtt;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
 						  ucmd.db_addr, &qp->db);
 			if (err)
@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_
 		if (err)
 			goto err;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_db_alloc(dev->dev, &qp->db, 0);
 			if (err)
 				goto err;
@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_
 	if (err)
 		goto err_qpn;
 
+	if (init_attr->qp_type == IB_QPT_XRC_TGT)
+		qp->mqp.qpn |= (1 << 23);
+
 	/*
 	 * Hardware wants QPN written in big-endian order (after
 	 * shifting) for send doorbell.  Precompute this value to save
@@ -592,9 +602,8 @@ err_qpn:
 
 err_wrid:
 	if (pd->uobject) {
-		if (!init_attr->srq)
-			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
-					      &qp->db);
+		if (qp_has_rq(init_attr))
+			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
 	} else {
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
@@ -610,7 +619,7 @@ err_buf:
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 
 err_db:
-	if (!pd->uobject && !init_attr->srq)
+	if (!pd->uobject && qp_has_rq(init_attr))
 		mlx4_db_free(dev->dev, &qp->db);
 
 err:
@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_
 	}
 }
 
+static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
+{
+	if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
+		return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
+	else
+		return to_mpd(qp->ibqp.pd);
+}
+
+static void get_cqs(struct mlx4_ib_qp *qp,
+		    struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
+{
+	switch (qp->ibqp.qp_type) {
+	case IB_QPT_XRC_TGT:
+		*send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
+		*recv_cq = *send_cq;
+		break;
+	case IB_QPT_XRC_INI:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = *send_cq;
+		break;
+	default:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = to_mcq(qp->ibqp.recv_cq);
+		break;
+	}
+}
+
 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 			      int is_user)
 {
@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx
 			printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
 			       qp->mqp.qpn);
 
-	send_cq = to_mcq(qp->ibqp.send_cq);
-	recv_cq = to_mcq(qp->ibqp.recv_cq);
+	get_cqs(qp, &send_cq, &recv_cq);
 
 	mlx4_ib_lock_cqs(send_cq, recv_cq);
 
@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
 
 	if (is_user) {
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
 					      &qp->db);
 		ib_umem_release(qp->umem);
@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_db_free(dev->dev, &qp->db);
 	}
 
@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct i
 				struct ib_qp_init_attr *init_attr,
 				struct ib_udata *udata)
 {
-	struct mlx4_ib_dev *dev = to_mdev(pd->device);
 	struct mlx4_ib_sqp *sqp;
 	struct mlx4_ib_qp *qp;
 	int err;
+	u16 xrcdn = 0;
 
 	/*
 	 * We only support LSO and multicast loopback blocking, and
@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct i
 		return ERR_PTR(-EINVAL);
 
 	if (init_attr->create_flags &&
-	    (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+	    (udata || init_attr->qp_type != IB_QPT_UD))
 		return ERR_PTR(-EINVAL);
 
 	switch (init_attr->qp_type) {
+	case IB_QPT_XRC_TGT:
+		pd = to_mxrcd(init_attr->xrcd)->pd;
+		xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
+		init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
+		/* fall through */
+	case IB_QPT_XRC_INI:
+		if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+			return ERR_PTR(-ENOSYS);
+		init_attr->recv_cq = init_attr->send_cq;
+		/* fall through */
 	case IB_QPT_RC:
 	case IB_QPT_UC:
 	case IB_QPT_UD:
@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct i
 		if (!qp)
 			return ERR_PTR(-ENOMEM);
 
-		err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
 		if (err) {
 			kfree(qp);
 			return ERR_PTR(err);
 		}
 
 		qp->ibqp.qp_num = qp->mqp.qpn;
+		qp->xrcdn = xrcdn;
 
 		break;
 	}
@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct i
 	case IB_QPT_GSI:
 	{
 		/* Userspace is not allowed to create special QPs: */
-		if (pd->uobject)
+		if (udata)
 			return ERR_PTR(-EINVAL);
 
 		sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct i
 
 		qp = &sqp->qp;
 
-		err = create_qp_common(dev, pd, init_attr, udata,
-				       dev->dev->caps.sqp_start +
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
+				       to_mdev(pd->device)->dev->caps.sqp_start +
 				       (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
 				       init_attr->port_num - 1,
 				       qp);
@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
 {
 	struct mlx4_ib_dev *dev = to_mdev(qp->device);
 	struct mlx4_ib_qp *mqp = to_mqp(qp);
+	struct mlx4_ib_pd *pd;
 
 	if (is_qp0(dev, mqp))
 		mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
-	destroy_qp_common(dev, mqp, !!qp->pd->uobject);
+	pd = get_pd(mqp);
+	destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
 
 	if (is_sqp(dev, mqp))
 		kfree(to_msqp(mqp));
@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type ty
 	case IB_QPT_RC:		return MLX4_QP_ST_RC;
 	case IB_QPT_UC:		return MLX4_QP_ST_UC;
 	case IB_QPT_UD:		return MLX4_QP_ST_UD;
+	case IB_QPT_XRC_INI:
+	case IB_QPT_XRC_TGT:	return MLX4_QP_ST_XRC;
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:	return MLX4_QP_ST_MLX;
 	default:		return -1;
@@ -959,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	struct mlx4_ib_pd *pd;
+	struct mlx4_ib_cq *send_cq, *recv_cq;
 	struct mlx4_qp_context *context;
 	enum mlx4_qp_optpar optpar = 0;
 	int sqd_event;
@@ -1014,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib
 		context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
 	context->sq_size_stride |= qp->sq.wqe_shift - 4;
 
-	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
 		context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+		context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+	}
 
 	if (qp->ibqp.uobject)
 		context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -1079,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib
 		optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
 	}
 
-	context->pd	    = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
-	context->params1    = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+	pd = get_pd(qp);
+	get_cqs(qp, &send_cq, &recv_cq);
+	context->pd       = cpu_to_be32(pd->pdn);
+	context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
+	context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
+	context->params1  = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
 
 	/* Set "fast registration enabled" for all kernel QPs */
 	if (!qp->ibqp.uobject)
@@ -1106,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib
 	if (attr_mask & IB_QP_SQ_PSN)
 		context->next_send_psn = cpu_to_be32(attr->sq_psn);
 
-	context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
 		if (attr->max_dest_rd_atomic)
 			context->params2 |=
@@ -1130,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib
 	if (attr_mask & IB_QP_RQ_PSN)
 		context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
-	context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_QKEY) {
 		context->qkey = cpu_to_be32(attr->qkey);
 		optpar |= MLX4_QP_OPTPAR_Q_KEY;
@@ -1140,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib
 	if (ibqp->srq)
 		context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
 
-	if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->db_rec_addr = cpu_to_be64(qp->db.dma);
 
 	if (cur_state == IB_QPS_INIT &&
@@ -1225,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib
 	 * entries and reinitialize the QP.
 	 */
 	if (new_state == IB_QPS_RESET && !ibqp->uobject) {
-		mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn,
+		mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
 				 ibqp->srq ? to_msrq(ibqp->srq): NULL);
-		if (ibqp->send_cq != ibqp->recv_cq)
-			mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL);
+		if (send_cq != recv_cq)
+			mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
 
 		qp->rq.head = 0;
 		qp->rq.tail = 0;
 		qp->sq.head = 0;
 		qp->sq.tail = 0;
 		qp->sq_next_wqe = 0;
-		if (!ibqp->srq)
+		if (qp->rq.wqe_cnt)
 			*qp->db.db  = 0;
 	}
 
@@ -1547,14 +1601,13 @@ static void set_masked_atomic_seg(struct
 }
 
 static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-			     struct ib_send_wr *wr, __be16 *vlan)
+			     struct ib_send_wr *wr)
 {
 	memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
 	dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
 	dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
 	dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
 	memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
-	*vlan = dseg->vlan;
 }
 
 static void set_mlx_icrc_seg(void *dseg)
@@ -1657,7 +1710,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp
 	__be32 uninitialized_var(lso_hdr_sz);
 	__be32 blh;
 	int i;
-	__be16 vlan = cpu_to_be16(0xffff);
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
 
@@ -1761,7 +1813,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp
 			break;
 
 		case IB_QPT_UD:
-			set_datagram_seg(wqe, wr, &vlan);
+			set_datagram_seg(wqe, wr);
 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
@@ -1824,11 +1876,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp
 		ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
 				    MLX4_WQE_CTRL_FENCE : 0) | size;
 
-		if (be16_to_cpu(vlan) < 0x1000) {
-			ctrl->ins_vlan = 1 << 6;
-			ctrl->vlan_tag = vlan;
-		}
-
 		/*
 		 * Make sure descriptor is fully written before
 		 * setting ownership bit (because HW can start
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/srq.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/srq.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mlx4/srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mlx4/srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct
 	struct mlx4_ib_srq *srq;
 	struct mlx4_wqe_srq_next_seg *next;
 	struct mlx4_wqe_data_seg *scatter;
+	u32 cqn;
+	u16 xrcdn;
 	int desc_size;
 	int buf_size;
 	int err;
@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct
 		}
 	}
 
-	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+	cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
+	xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
+		(u16) dev->dev->caps.reserved_xrcds;
+	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
 			     srq->db.dma, &srq->msrq);
 	if (err)
 		goto err_wrid;
 
 	srq->msrq.event = mlx4_ib_srq_event;
+	srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
 
 	if (pd->uobject)
 		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  */
 
 #include <linux/jiffies.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <rdma/ib_mad.h>
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@ static int mthca_buddy_init(struct mthca
 
 	buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
 			      GFP_KERNEL);
-	buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+	buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
 				  GFP_KERNEL);
 	if (!buddy->bits || !buddy->num_free)
 		goto err_out;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_provider.c linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_provider.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/mthca/mthca_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/mthca/mthca_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,9 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
@@ -438,6 +440,9 @@ static struct ib_srq *mthca_create_srq(s
 	struct mthca_srq *srq;
 	int err;
 
+	if (init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	srq = kmalloc(sizeof *srq, GFP_KERNEL);
 	if (!srq)
 		return ERR_PTR(-ENOMEM);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/Makefile linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/Makefile
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
 
-iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
 MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
 
 
-unsigned int nes_drv_opt = 0;
+unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
 module_param(nes_drv_opt, int, 0644);
 MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
 
@@ -130,9 +130,6 @@ static struct notifier_block nes_net_not
 	.notifier_call = nes_net_event
 };
 
-
-
-
 /**
  * nes_inetaddr_event
  */
@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
 	}
 
 	if (atomic_dec_and_test(&nesqp->refcount)) {
+		if (nesqp->pau_mode)
+			nes_destroy_pau_qp(nesdev, nesqp);
+
 		/* Destroy the QP */
 		cqp_request = nes_get_cqp_request(nesdev);
 		if (cqp_request == NULL) {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_cm.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,26 +77,19 @@ atomic_t cm_nodes_destroyed;
 atomic_t cm_accel_dropped_pkts;
 atomic_t cm_resets_recvd;
 
-static inline int mini_cm_accelerated(struct nes_cm_core *,
-	struct nes_cm_node *);
-static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
-	struct nes_vnic *, struct nes_cm_info *);
+static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);
 static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
-	struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);
 static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
-	struct sk_buff *);
+static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
 static int mini_cm_dealloc_core(struct nes_cm_core *);
 static int mini_cm_get(struct nes_cm_core *);
 static int mini_cm_set(struct nes_cm_core *, u32, u32);
 
-static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
-	void *, u32, void *, u32, u8);
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);
 static int add_ref_cm_node(struct nes_cm_node *);
 static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
 
@@ -111,16 +104,14 @@ static int send_syn(struct nes_cm_node *
 static int send_reset(struct nes_cm_node *, struct sk_buff *);
 static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
 static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
-static void process_packet(struct nes_cm_node *, struct sk_buff *,
-	struct nes_cm_core *);
+static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
 
 static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void cleanup_retrans_entry(struct nes_cm_node *);
 static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
 static void free_retrans_entry(struct nes_cm_node *cm_node);
-static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);
 
 /* CM event handler functions */
 static void cm_event_connected(struct nes_cm_event *);
@@ -130,6 +121,12 @@ static void cm_event_mpa_req(struct nes_
 static void cm_event_mpa_reject(struct nes_cm_event *);
 static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
 
+/* MPA build functions */
+static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8);
+static void build_mpa_v2(struct nes_cm_node *, void *, u8);
+static void build_mpa_v1(struct nes_cm_node *, void *, u8);
+static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **);
+
 static void print_core(struct nes_cm_core *core);
 
 /* External CM API Interface */
@@ -159,12 +156,21 @@ atomic_t cm_connecteds;
 atomic_t cm_connect_reqs;
 atomic_t cm_rejects;
 
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return add_ref_cm_node(cm_node);
+}
+
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return rem_ref_cm_node(cm_node->cm_core, cm_node);
+}
 
 /**
  * create_event
  */
-static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
-		enum nes_cm_event_type type)
+static struct nes_cm_event *create_event(struct nes_cm_node *	cm_node,
+					 enum nes_cm_event_type type)
 {
 	struct nes_cm_event *event;
 
@@ -186,10 +192,10 @@ static struct nes_cm_event *create_event
 	event->cm_info.cm_id = cm_node->cm_id;
 
 	nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
-		"dst_addr=%08x[%x], src_addr=%08x[%x]\n",
-		cm_node, event, type, event->cm_info.loc_addr,
-		event->cm_info.loc_port, event->cm_info.rem_addr,
-		event->cm_info.rem_port);
+		  "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+		  cm_node, event, type, event->cm_info.loc_addr,
+		  event->cm_info.loc_port, event->cm_info.rem_addr,
+		  event->cm_info.rem_port);
 
 	nes_cm_post_event(event);
 	return event;
@@ -201,14 +207,19 @@ static struct nes_cm_event *create_event
  */
 static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
+
 	if (!skb) {
 		nes_debug(NES_DBG_CM, "skb set to NULL\n");
 		return -1;
 	}
 
 	/* send an MPA Request frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);
 
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
 }
@@ -217,7 +228,11 @@ static int send_mpa_request(struct nes_c
 
 static int send_mpa_reject(struct nes_cm_node *cm_node)
 {
-	struct sk_buff  *skb = NULL;
+	struct sk_buff *skb = NULL;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	skb = dev_alloc_skb(MAX_CM_BUFFER);
 	if (!skb) {
@@ -226,8 +241,8 @@ static int send_mpa_reject(struct nes_cm
 	}
 
 	/* send an MPA reject frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK | SET_FIN);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
 
 	cm_node->state = NES_CM_STATE_FIN_WAIT1;
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
@@ -239,24 +254,31 @@ static int send_mpa_reject(struct nes_cm
  * IETF MPA frame
  */
 static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
-		u32 len)
+		     u32 len)
 {
-	struct ietf_mpa_frame *mpa_frame;
+	struct ietf_mpa_v1 *mpa_frame;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	struct ietf_rtr_msg *rtr_msg;
+	int mpa_hdr_len;
+	int priv_data_len;
 
 	*type = NES_MPA_REQUEST_ACCEPT;
 
 	/* assume req frame is in tcp data payload */
-	if (len < sizeof(struct ietf_mpa_frame)) {
+	if (len < sizeof(struct ietf_mpa_v1)) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
 		return -EINVAL;
 	}
 
-	mpa_frame = (struct ietf_mpa_frame *)buffer;
-	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+	/* points to the beginning of the frame, which could be MPA V1 or V2 */
+	mpa_frame = (struct ietf_mpa_v1 *)buffer;
+	mpa_hdr_len = sizeof(struct ietf_mpa_v1);
+	priv_data_len = ntohs(mpa_frame->priv_data_len);
+
 	/* make sure mpa private data len is less than 512 bytes */
-	if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+	if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {
 		nes_debug(NES_DBG_CM, "The received Length of Private"
-			" Data field exceeds 512 octets\n");
+			  " Data field exceeds 512 octets\n");
 		return -EINVAL;
 	}
 	/*
@@ -264,11 +286,22 @@ static int parse_mpa(struct nes_cm_node
 	 * received MPA version and MPA key information
 	 *
 	 */
-	if (mpa_frame->rev != mpa_version) {
+	if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) {
 		nes_debug(NES_DBG_CM, "The received mpa version"
-				" can not be interoperated\n");
+			  " is not supported\n");
+		return -EINVAL;
+	}
+	/*
+	* backwards compatibility only
+	*/
+	if (mpa_frame->rev > cm_node->mpa_frame_rev) {
+		nes_debug(NES_DBG_CM, "The received mpa version"
+			" can not be interoperated\n");
 		return -EINVAL;
+	} else {
+		cm_node->mpa_frame_rev = mpa_frame->rev;
 	}
+
 	if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
 		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
 			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
@@ -281,25 +314,75 @@ static int parse_mpa(struct nes_cm_node
 		}
 	}
 
-	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
+
+	if (priv_data_len + mpa_hdr_len != len) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
-				" complete (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" complete (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 	/* make sure it does not exceed the max size */
 	if (len > MAX_CM_BUFFER) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
-				" (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 
+	cm_node->mpa_frame_size = priv_data_len;
+
+	switch (mpa_frame->rev) {
+	case IETF_MPA_V2: {
+		u16 ird_size;
+		u16 ord_size;
+		mpa_v2_frame = (struct ietf_mpa_v2 *)buffer;
+		mpa_hdr_len += IETF_RTR_MSG_SIZE;
+		cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE;
+		rtr_msg = &mpa_v2_frame->rtr_msg;
+
+		/* parse rtr message */
+		rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird);
+		rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord);
+		ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD;
+		ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD;
+
+		if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) {
+			/* send reset */
+			return -EINVAL;
+		}
+
+		if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+			/* responder */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+		} else {
+			/* initiator */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+
+			if (cm_node->ird_size < ord_size) {
+				/* no resources available */
+				/* send terminate message */
+				return -EINVAL;
+			}
+		}
+
+		if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) {
+			cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+		} else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) {
+			cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO;
+		} else {        /* Not supported RDMA0 operation */
+			return -EINVAL;
+		}
+		break;
+	}
+	case IETF_MPA_V1:
+	default:
+		break;
+	}
+
 	/* copy entire MPA frame to our cm_node's frame */
-	memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
-			cm_node->mpa_frame_size);
+	memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);
 
 	if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
 		*type = NES_MPA_REQUEST_REJECT;
@@ -312,8 +395,8 @@ static int parse_mpa(struct nes_cm_node
  * node info to build.
  */
 static void form_cm_frame(struct sk_buff *skb,
-	struct nes_cm_node *cm_node, void *options, u32 optionsize,
-	void *data, u32 datasize, u8 flags)
+			  struct nes_cm_node *cm_node, void *options, u32 optionsize,
+			  void *data, u32 datasize, u8 flags)
 {
 	struct tcphdr *tcph;
 	struct iphdr *iph;
@@ -322,14 +405,14 @@ static void form_cm_frame(struct sk_buff
 	u16 packetsize = sizeof(*iph);
 
 	packetsize += sizeof(*tcph);
-	packetsize +=  optionsize + datasize;
+	packetsize += optionsize + datasize;
 
+	skb_trim(skb, 0);
 	memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
 
-	skb->len = 0;
 	buf = skb_put(skb, packetsize + ETH_HLEN);
 
-	ethh = (struct ethhdr *) buf;
+	ethh = (struct ethhdr *)buf;
 	buf += ETH_HLEN;
 
 	iph = (struct iphdr *)buf;
@@ -337,7 +420,7 @@ static void form_cm_frame(struct sk_buff
 	tcph = (struct tcphdr *)buf;
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, ETH_HLEN);
-	skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
+	skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));
 	buf += sizeof(*tcph);
 
 	skb->ip_summed = CHECKSUM_PARTIAL;
@@ -350,14 +433,14 @@ static void form_cm_frame(struct sk_buff
 	ethh->h_proto = htons(0x0800);
 
 	iph->version = IPVERSION;
-	iph->ihl = 5;		/* 5 * 4Byte words, IP headr len */
+	iph->ihl = 5;           /* 5 * 4Byte words, IP headr len */
 	iph->tos = 0;
 	iph->tot_len = htons(packetsize);
 	iph->id = htons(++cm_node->tcp_cntxt.loc_id);
 
 	iph->frag_off = htons(0x4000);
 	iph->ttl = 0x40;
-	iph->protocol = 0x06;	/* IPPROTO_TCP */
+	iph->protocol = 0x06;   /* IPPROTO_TCP */
 
 	iph->saddr = htonl(cm_node->loc_addr);
 	iph->daddr = htonl(cm_node->rem_addr);
@@ -370,14 +453,16 @@ static void form_cm_frame(struct sk_buff
 		cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
 		tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
 		tcph->ack = 1;
-	} else
+	} else {
 		tcph->ack_seq = 0;
+	}
 
 	if (flags & SET_SYN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
 		tcph->syn = 1;
-	} else
+	} else {
 		cm_node->tcp_cntxt.loc_seq_num += datasize;
+	}
 
 	if (flags & SET_FIN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
@@ -398,10 +483,8 @@ static void form_cm_frame(struct sk_buff
 
 	skb_shinfo(skb)->nr_frags = 0;
 	cm_packets_created++;
-
 }
 
-
 /**
  * print_core - dump a cm core
  */
@@ -413,7 +496,7 @@ static void print_core(struct nes_cm_cor
 		return;
 	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
 
-	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state);
+	nes_debug(NES_DBG_CM, "State         : %u \n", core->state);
 
 	nes_debug(NES_DBG_CM, "Listen Nodes  : %u \n", atomic_read(&core->listen_node_cnt));
 	nes_debug(NES_DBG_CM, "Active Nodes  : %u \n", atomic_read(&core->node_cnt));
@@ -423,6 +506,147 @@ static void print_core(struct nes_cm_cor
 	nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
 }
 
+/**
+ * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame
+ */
+static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff,
+			      u16 *buff_len, u8 *pci_mem, u8 mpa_key)
+{
+	int ret = 0;
+
+	*start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0];
+
+	switch (cm_node->mpa_frame_rev) {
+	case IETF_MPA_V1:
+		*start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg);
+		*buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size;
+		build_mpa_v1(cm_node, *start_buff, mpa_key);
+		break;
+	case IETF_MPA_V2:
+		*buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size;
+		build_mpa_v2(cm_node, *start_buff, mpa_key);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/**
+ * build_mpa_v2 - build a MPA V2 frame
+ */
+static void build_mpa_v2(struct nes_cm_node *cm_node,
+			 void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr;
+	struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg;
+
+	/* initialize the upper 5 bytes of the frame */
+	build_mpa_v1(cm_node, start_addr, mpa_key);
+	mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */
+	mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);
+
+	/* initialize RTR msg */
+	rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ird_size;
+	rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ord_size;
+
+	rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER;
+	rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+		rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+		break;
+	case MPA_KEY_REPLY:
+		switch (cm_node->send_rdma0_op) {
+		case SEND_RDMA_WRITE_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+			break;
+		case SEND_RDMA_READ_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+			break;
+		}
+	}
+	rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird);
+	rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord);
+}
+
+/**
+ * build_mpa_v1 - build a MPA V1 frame
+ */
+static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
+		break;
+	case MPA_KEY_REPLY:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
+		break;
+	}
+	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+	mpa_frame->rev = cm_node->mpa_frame_rev;
+	mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size);
+}
+
+static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr)
+{
+	u64 u64temp;
+	struct nes_qp *nesqp = *nesqp_addr;
+	struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0];
+
+	u64temp = (unsigned long)nesqp;
+	u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
+	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+
+	switch (cm_node->send_rdma0_op) {
+	case SEND_RDMA_WRITE_ZERO:
+		nes_debug(NES_DBG_CM, "Sending first write.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+		break;
+
+	case SEND_RDMA_READ_ZERO:
+	default:
+		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
+			printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
+				 __func__, __LINE__, cm_node->send_rdma0_op);
+			WARN_ON(1);
+		}
+		nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1;
+		break;
+	}
+
+	if (nesqp->sq_kmapped) {
+		nesqp->sq_kmapped = 0;
+		kunmap(nesqp->page);
+	}
+
+	/*use the reserved spot on the WQ for the extra first WQE*/
+	nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+							     NES_QPCONTEXT_ORDIRD_WRPDU |
+							     NES_QPCONTEXT_ORDIRD_ALSMM));
+	nesqp->skip_lsmm = 1;
+	nesqp->hwqp.sq_tail = 0;
+}
 
 /**
  * schedule_nes_timer
@@ -430,10 +654,10 @@ static void print_core(struct nes_cm_cor
  *			rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
  */
 int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
-		enum nes_timer_type type, int send_retrans,
-		int close_when_complete)
+		       enum nes_timer_type type, int send_retrans,
+		       int close_when_complete)
 {
-	unsigned long  flags;
+	unsigned long flags;
 	struct nes_cm_core *cm_core = cm_node->cm_core;
 	struct nes_timer_entry *new_send;
 	int ret = 0;
@@ -454,7 +678,7 @@ int schedule_nes_timer(struct nes_cm_nod
 	new_send->close_when_complete = close_when_complete;
 
 	if (type == NES_TIMER_TYPE_CLOSE) {
-		new_send->timetosend += (HZ/10);
+		new_send->timetosend += (HZ / 10);
 		if (cm_node->recv_entry) {
 			kfree(new_send);
 			WARN_ON(1);
@@ -475,7 +699,7 @@ int schedule_nes_timer(struct nes_cm_nod
 		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
 		if (ret != NETDEV_TX_OK) {
 			nes_debug(NES_DBG_CM, "Error sending packet %p "
-				"(jiffies = %lu)\n", new_send, jiffies);
+				  "(jiffies = %lu)\n", new_send, jiffies);
 			new_send->timetosend = jiffies;
 			ret = NETDEV_TX_OK;
 		} else {
@@ -504,6 +728,7 @@ static void nes_retrans_expired(struct n
 	struct iw_cm_id *cm_id = cm_node->cm_id;
 	enum nes_cm_node_state state = cm_node->state;
 	cm_node->state = NES_CM_STATE_CLOSED;
+
 	switch (state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_CLOSING:
@@ -536,10 +761,10 @@ static void handle_recv_entry(struct nes
 		spin_lock_irqsave(&nesqp->lock, qplockflags);
 		if (nesqp->cm_id) {
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with something "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with something "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
 			nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
 			nesqp->ibqp_state = IB_QPS_ERR;
@@ -548,10 +773,10 @@ static void handle_recv_entry(struct nes
 		} else {
 			spin_unlock_irqrestore(&nesqp->lock, qplockflags);
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with nothing "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with nothing "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 		}
 	} else if (rem_node) {
 		/* TIME_WAIT state */
@@ -580,11 +805,12 @@ static void nes_cm_timer_tick(unsigned l
 	int ret = NETDEV_TX_OK;
 
 	struct list_head timer_list;
+
 	INIT_LIST_HEAD(&timer_list);
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
 	list_for_each_safe(list_node, list_core_temp,
-				&cm_core->connected_nodes) {
+			   &cm_core->connected_nodes) {
 		cm_node = container_of(list_node, struct nes_cm_node, list);
 		if ((cm_node->recv_entry) || (cm_node->send_entry)) {
 			add_ref_cm_node(cm_node);
@@ -595,18 +821,19 @@ static void nes_cm_timer_tick(unsigned l
 
 	list_for_each_safe(list_node, list_core_temp, &timer_list) {
 		cm_node = container_of(list_node, struct nes_cm_node,
-					timer_entry);
+				       timer_entry);
 		recv_entry = cm_node->recv_entry;
 
 		if (recv_entry) {
 			if (time_after(recv_entry->timetosend, jiffies)) {
 				if (nexttimeout > recv_entry->timetosend ||
-						!settimer) {
+				    !settimer) {
 					nexttimeout = recv_entry->timetosend;
 					settimer = 1;
 				}
-			} else
+			} else {
 				handle_recv_entry(cm_node, 1);
+			}
 		}
 
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
@@ -617,8 +844,8 @@ static void nes_cm_timer_tick(unsigned l
 			if (time_after(send_entry->timetosend, jiffies)) {
 				if (cm_node->state != NES_CM_STATE_TSA) {
 					if ((nexttimeout >
-						send_entry->timetosend) ||
-						!settimer) {
+					     send_entry->timetosend) ||
+					    !settimer) {
 						nexttimeout =
 							send_entry->timetosend;
 						settimer = 1;
@@ -630,13 +857,13 @@ static void nes_cm_timer_tick(unsigned l
 			}
 
 			if ((cm_node->state == NES_CM_STATE_TSA) ||
-				(cm_node->state == NES_CM_STATE_CLOSED)) {
+			    (cm_node->state == NES_CM_STATE_CLOSED)) {
 				free_retrans_entry(cm_node);
 				break;
 			}
 
 			if (!send_entry->retranscount ||
-				!send_entry->retrycount) {
+			    !send_entry->retrycount) {
 				cm_packets_dropped++;
 				free_retrans_entry(cm_node);
 
@@ -645,28 +872,28 @@ static void nes_cm_timer_tick(unsigned l
 				nes_retrans_expired(cm_node);
 				cm_node->state = NES_CM_STATE_CLOSED;
 				spin_lock_irqsave(&cm_node->retrans_list_lock,
-					flags);
+						  flags);
 				break;
 			}
 			atomic_inc(&send_entry->skb->users);
 			cm_packets_retrans++;
 			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
-				"for node %p, jiffies = %lu, time to send = "
-				"%lu, retranscount = %u, send_entry->seq_num = "
-				"0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
-				"0x%08X\n", send_entry, cm_node, jiffies,
-				send_entry->timetosend,
-				send_entry->retranscount,
-				send_entry->seq_num,
-				cm_node->tcp_cntxt.rem_ack_num);
+				  "for node %p, jiffies = %lu, time to send = "
+				  "%lu, retranscount = %u, send_entry->seq_num = "
+				  "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+				  "0x%08X\n", send_entry, cm_node, jiffies,
+				  send_entry->timetosend,
+				  send_entry->retranscount,
+				  send_entry->seq_num,
+				  cm_node->tcp_cntxt.rem_ack_num);
 
 			spin_unlock_irqrestore(&cm_node->retrans_list_lock,
-				flags);
+					       flags);
 			ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
 			spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 			if (ret != NETDEV_TX_OK) {
 				nes_debug(NES_DBG_CM, "rexmit failed for "
-					"node=%p\n", cm_node);
+					  "node=%p\n", cm_node);
 				cm_packets_bounced++;
 				send_entry->retrycount--;
 				nexttimeout = jiffies + NES_SHORT_TIME;
@@ -676,18 +903,18 @@ static void nes_cm_timer_tick(unsigned l
 				cm_packets_sent++;
 			}
 			nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
-				"%u, retry count = %u.\n",
-				send_entry->retranscount,
-				send_entry->retrycount);
+				  "%u, retry count = %u.\n",
+				  send_entry->retranscount,
+				  send_entry->retrycount);
 			if (send_entry->send_retrans) {
 				send_entry->retranscount--;
 				timetosend = (NES_RETRY_TIMEOUT <<
-					(NES_DEFAULT_RETRANS - send_entry->retranscount));
+					      (NES_DEFAULT_RETRANS - send_entry->retranscount));
 
 				send_entry->timetosend = jiffies +
-					min(timetosend, NES_MAX_TIMEOUT);
+							 min(timetosend, NES_MAX_TIMEOUT);
 				if (nexttimeout > send_entry->timetosend ||
-					!settimer) {
+				    !settimer) {
 					nexttimeout = send_entry->timetosend;
 					settimer = 1;
 				}
@@ -696,11 +923,11 @@ static void nes_cm_timer_tick(unsigned l
 				close_when_complete =
 					send_entry->close_when_complete;
 				nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
-					cm_node, cm_node->state);
+					  cm_node, cm_node->state);
 				free_retrans_entry(cm_node);
 				if (close_when_complete)
 					rem_ref_cm_node(cm_node->cm_core,
-						cm_node);
+							cm_node);
 			}
 		} while (0);
 
@@ -710,7 +937,7 @@ static void nes_cm_timer_tick(unsigned l
 
 	if (settimer) {
 		if (!timer_pending(&cm_core->tcp_timer)) {
-			cm_core->tcp_timer.expires  = nexttimeout;
+			cm_core->tcp_timer.expires = nexttimeout;
 			add_timer(&cm_core->tcp_timer);
 		}
 	}
@@ -721,13 +948,13 @@ static void nes_cm_timer_tick(unsigned l
  * send_syn
  */
 static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
-	struct sk_buff *skb)
+		    struct sk_buff *skb)
 {
 	int ret;
 	int flags = SET_SYN;
 	char optionsbuffer[sizeof(struct option_mss) +
-		sizeof(struct option_windowscale) + sizeof(struct option_base) +
-		TCP_OPTIONS_PADDING];
+			   sizeof(struct option_windowscale) + sizeof(struct option_base) +
+			   TCP_OPTIONS_PADDING];
 
 	int optionssize = 0;
 	/* Sending MSS option */
@@ -854,7 +1081,7 @@ static int send_fin(struct nes_cm_node *
  * find_node - find a cm node that matches the reference cm node
  */
 static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
-		u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
+				     u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
 {
 	unsigned long flags;
 	struct list_head *hte;
@@ -868,12 +1095,12 @@ static struct nes_cm_node *find_node(str
 	list_for_each_entry(cm_node, hte, list) {
 		/* compare quad, return node handle if a match */
 		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
-				cm_node->loc_addr, cm_node->loc_port,
-				loc_addr, loc_port,
-				cm_node->rem_addr, cm_node->rem_port,
-				rem_addr, rem_port);
+			  cm_node->loc_addr, cm_node->loc_port,
+			  loc_addr, loc_port,
+			  cm_node->rem_addr, cm_node->rem_port,
+			  rem_addr, rem_port);
 		if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
-				(cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
+		    (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
 			add_ref_cm_node(cm_node);
 			spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 			return cm_node;
@@ -890,7 +1117,7 @@ static struct nes_cm_node *find_node(str
  * find_listener - find a cm node listening on this addr-port pair
  */
 static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
-		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+					     nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
 {
 	unsigned long flags;
 	struct nes_cm_listener *listen_node;
@@ -900,9 +1127,9 @@ static struct nes_cm_listener *find_list
 	list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
 		/* compare node pair, return node handle if a match */
 		if (((listen_node->loc_addr == dst_addr) ||
-				listen_node->loc_addr == 0x00000000) &&
-				(listen_node->loc_port == dst_port) &&
-				(listener_state & listen_node->listener_state)) {
+		     listen_node->loc_addr == 0x00000000) &&
+		    (listen_node->loc_port == dst_port) &&
+		    (listener_state & listen_node->listener_state)) {
 			atomic_inc(&listen_node->ref_count);
 			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 			return listen_node;
@@ -927,7 +1154,7 @@ static int add_hte_node(struct nes_cm_co
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
-		cm_node);
+		  cm_node);
 
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
@@ -946,7 +1173,7 @@ static int add_hte_node(struct nes_cm_co
  * mini_cm_dec_refcnt_listen
  */
 static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
-	struct nes_cm_listener *listener, int free_hanging_nodes)
+				     struct nes_cm_listener *listener, int free_hanging_nodes)
 {
 	int ret = -EINVAL;
 	int err = 0;
@@ -957,8 +1184,8 @@ static int mini_cm_dec_refcnt_listen(str
 	struct list_head reset_list;
 
 	nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
-		"refcnt=%d\n", listener, free_hanging_nodes,
-		atomic_read(&listener->ref_count));
+		  "refcnt=%d\n", listener, free_hanging_nodes,
+		  atomic_read(&listener->ref_count));
 	/* free non-accelerated child nodes for this listener */
 	INIT_LIST_HEAD(&reset_list);
 	if (free_hanging_nodes) {
@@ -966,7 +1193,7 @@ static int mini_cm_dec_refcnt_listen(str
 		list_for_each_safe(list_pos, list_temp,
 				   &g_cm_core->connected_nodes) {
 			cm_node = container_of(list_pos, struct nes_cm_node,
-				list);
+					       list);
 			if ((cm_node->listener == listener) &&
 			    (!cm_node->accelerated)) {
 				add_ref_cm_node(cm_node);
@@ -978,7 +1205,7 @@ static int mini_cm_dec_refcnt_listen(str
 
 	list_for_each_safe(list_pos, list_temp, &reset_list) {
 		cm_node = container_of(list_pos, struct nes_cm_node,
-				reset_entry);
+				       reset_entry);
 		{
 			struct nes_cm_node *loopback = cm_node->loopbackpartner;
 			enum nes_cm_node_state old_state;
@@ -990,7 +1217,7 @@ static int mini_cm_dec_refcnt_listen(str
 					err = send_reset(cm_node, NULL);
 					if (err) {
 						cm_node->state =
-							 NES_CM_STATE_CLOSED;
+							NES_CM_STATE_CLOSED;
 						WARN_ON(1);
 					} else {
 						old_state = cm_node->state;
@@ -1035,10 +1262,9 @@ static int mini_cm_dec_refcnt_listen(str
 
 		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
-		if (listener->nesvnic) {
+		if (listener->nesvnic)
 			nes_manage_apbvt(listener->nesvnic, listener->loc_port,
-					PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
-		}
+					 PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
 
 		nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
 
@@ -1052,8 +1278,8 @@ static int mini_cm_dec_refcnt_listen(str
 	if (listener) {
 		if (atomic_read(&listener->pend_accepts_cnt) > 0)
 			nes_debug(NES_DBG_CM, "destroying listener (%p)"
-					" with non-zero pending accepts=%u\n",
-					listener, atomic_read(&listener->pend_accepts_cnt));
+				  " with non-zero pending accepts=%u\n",
+				  listener, atomic_read(&listener->pend_accepts_cnt));
 	}
 
 	return ret;
@@ -1064,7 +1290,7 @@ static int mini_cm_dec_refcnt_listen(str
  * mini_cm_del_listen
  */
 static int mini_cm_del_listen(struct nes_cm_core *cm_core,
-		struct nes_cm_listener *listener)
+			      struct nes_cm_listener *listener)
 {
 	listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
 	listener->cm_id = NULL; /* going to be destroyed pretty soon */
@@ -1076,9 +1302,10 @@ static int mini_cm_del_listen(struct nes
  * mini_cm_accelerated
  */
 static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
-		struct nes_cm_node *cm_node)
+				      struct nes_cm_node *cm_node)
 {
 	u32 was_timer_set;
+
 	cm_node->accelerated = 1;
 
 	if (cm_node->accept_pend) {
@@ -1112,7 +1339,7 @@ static int nes_addr_resolve_neigh(struct
 	rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
 	if (IS_ERR(rt)) {
 		printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
-				__func__, dst_ip);
+		       __func__, dst_ip);
 		return rc;
 	}
 
@@ -1130,7 +1357,7 @@ static int nes_addr_resolve_neigh(struct
 
 			if (arpindex >= 0) {
 				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
-							neigh->ha, ETH_ALEN)){
+					    neigh->ha, ETH_ALEN)) {
 					/* Mac address same as in nes_arp_table */
 					neigh_release(neigh);
 					ip_rt_put(rt);
@@ -1138,8 +1365,8 @@ static int nes_addr_resolve_neigh(struct
 				}
 
 				nes_manage_arp_cache(nesvnic->netdev,
-						nesadapter->arp_table[arpindex].mac_addr,
-						dst_ip, NES_ARP_DELETE);
+						     nesadapter->arp_table[arpindex].mac_addr,
+						     dst_ip, NES_ARP_DELETE);
 			}
 
 			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
@@ -1150,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct
 		neigh_release(neigh);
 	}
 
-	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
+		rcu_read_lock();
 		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
-
+		rcu_read_unlock();
+	}
 	ip_rt_put(rt);
 	return rc;
 }
@@ -1161,8 +1390,8 @@ static int nes_addr_resolve_neigh(struct
  * make_cm_node - create a new instance of a cm node
  */
 static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
-		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
-		struct nes_cm_listener *listener)
+					struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
+					struct nes_cm_listener *listener)
 {
 	struct nes_cm_node *cm_node;
 	struct timespec ts;
@@ -1181,7 +1410,12 @@ static struct nes_cm_node *make_cm_node(
 	cm_node->rem_addr = cm_info->rem_addr;
 	cm_node->loc_port = cm_info->loc_port;
 	cm_node->rem_port = cm_info->rem_port;
-	cm_node->send_write0 = send_first;
+
+	cm_node->mpa_frame_rev = mpa_version;
+	cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+	cm_node->ird_size = IETF_NO_IRD_ORD;
+	cm_node->ord_size = IETF_NO_IRD_ORD;
+
 	nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
 		  &cm_node->loc_addr, cm_node->loc_port,
 		  &cm_node->rem_addr, cm_node->rem_port);
@@ -1191,7 +1425,7 @@ static struct nes_cm_node *make_cm_node(
 	memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
 
 	nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
-			cm_node->cm_id);
+		  cm_node->cm_id);
 
 	spin_lock_init(&cm_node->retrans_list_lock);
 
@@ -1202,11 +1436,11 @@ static struct nes_cm_node *make_cm_node(
 	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
 	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
 	cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
-			NES_CM_DEFAULT_RCV_WND_SCALE;
+				     NES_CM_DEFAULT_RCV_WND_SCALE;
 	ts = current_kernel_time();
 	cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
 	cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
-			sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
+				 sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
 	cm_node->tcp_cntxt.rcv_nxt = 0;
 	/* get a unique session ID , add thread_id to an upcounter to handle race */
 	atomic_inc(&cm_core->node_cnt);
@@ -1222,12 +1456,11 @@ static struct nes_cm_node *make_cm_node(
 	cm_node->loopbackpartner = NULL;
 
 	/* get the mac addr for the remote node */
-	if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+	if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
 		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
-	else {
+	} else {
 		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
 		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-
 	}
 	if (arpindex < 0) {
 		kfree(cm_node);
@@ -1260,7 +1493,7 @@ static int add_ref_cm_node(struct nes_cm
  * rem_ref_cm_node - destroy an instance of a cm node
  */
 static int rem_ref_cm_node(struct nes_cm_core *cm_core,
-	struct nes_cm_node *cm_node)
+			   struct nes_cm_node *cm_node)
 {
 	unsigned long flags;
 	struct nes_qp *nesqp;
@@ -1291,9 +1524,9 @@ static int rem_ref_cm_node(struct nes_cm
 	} else {
 		if (cm_node->apbvt_set && cm_node->nesvnic) {
 			nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
-				PCI_FUNC(
-				cm_node->nesvnic->nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(
+						 cm_node->nesvnic->nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 		}
 	}
 
@@ -1314,7 +1547,7 @@ static int rem_ref_cm_node(struct nes_cm
  * process_options
  */
 static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
-	u32 optionsize, u32 syn_packet)
+			   u32 optionsize, u32 syn_packet)
 {
 	u32 tmp;
 	u32 offset = 0;
@@ -1332,15 +1565,15 @@ static int process_options(struct nes_cm
 			continue;
 		case OPTION_NUMBER_MSS:
 			nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
-				"Size: %d\n", __func__,
-				all_options->as_mss.length, offset, optionsize);
+				  "Size: %d\n", __func__,
+				  all_options->as_mss.length, offset, optionsize);
 			got_mss_option = 1;
 			if (all_options->as_mss.length != 4) {
 				return 1;
 			} else {
 				tmp = ntohs(all_options->as_mss.mss);
 				if (tmp > 0 && tmp <
-					cm_node->tcp_cntxt.mss)
+				    cm_node->tcp_cntxt.mss)
 					cm_node->tcp_cntxt.mss = tmp;
 			}
 			break;
@@ -1348,12 +1581,9 @@ static int process_options(struct nes_cm
 			cm_node->tcp_cntxt.snd_wscale =
 				all_options->as_windowscale.shiftcount;
 			break;
-		case OPTION_NUMBER_WRITE0:
-			cm_node->send_write0 = 1;
-			break;
 		default:
 			nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
-				all_options->as_base.optionnum);
+				  all_options->as_base.optionnum);
 			break;
 		}
 		offset += all_options->as_base.length;
@@ -1372,8 +1602,8 @@ static void drop_packet(struct sk_buff *
 static void handle_fin_pkt(struct nes_cm_node *cm_node)
 {
 	nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
-		"refcnt=%d\n", cm_node, cm_node->state,
-		atomic_read(&cm_node->ref_count));
+		  "refcnt=%d\n", cm_node, cm_node->state,
+		  atomic_read(&cm_node->ref_count));
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_SYN_SENT:
@@ -1439,7 +1669,20 @@ static void handle_rst_pkt(struct nes_cm
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
 			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
 			cm_node->listener, cm_node->state);
-		active_open_err(cm_node, skb, reset);
+		switch (cm_node->mpa_frame_rev) {
+		case IETF_MPA_V2:
+			cm_node->mpa_frame_rev = IETF_MPA_V1;
+			/* send a syn and goto syn sent state */
+			cm_node->state = NES_CM_STATE_SYN_SENT;
+			if (send_syn(cm_node, 0, NULL)) {
+				active_open_err(cm_node, skb, reset);
+			}
+			break;
+		case IETF_MPA_V1:
+		default:
+			active_open_err(cm_node, skb, reset);
+			break;
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_RCVD:
 		atomic_inc(&cm_node->passive_state);
@@ -1475,21 +1718,21 @@ static void handle_rst_pkt(struct nes_cm
 
 static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
-
-	int	ret = 0;
+	int ret = 0;
 	int datasize = skb->len;
 	u8 *dataloc = skb->data;
 
 	enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
-	u32     res_type;
+	u32 res_type;
+
 	ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
 	if (ret) {
 		nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
 		if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
 			nes_debug(NES_DBG_CM, "%s[%u] create abort for "
-				"cm_node=%p listener=%p state=%d\n", __func__,
-				__LINE__, cm_node, cm_node->listener,
-				cm_node->state);
+				  "cm_node=%p listener=%p state=%d\n", __func__,
+				  __LINE__, cm_node, cm_node->listener,
+				  cm_node->state);
 			active_open_err(cm_node, skb, 1);
 		} else {
 			passive_open_err(cm_node, skb, 1);
@@ -1499,16 +1742,15 @@ static void handle_rcv_mpa(struct nes_cm
 
 	switch (cm_node->state) {
 	case NES_CM_STATE_ESTABLISHED:
-		if (res_type == NES_MPA_REQUEST_REJECT) {
+		if (res_type == NES_MPA_REQUEST_REJECT)
 			/*BIG problem as we are receiving the MPA.. So should
-			* not be REJECT.. This is Passive Open.. We can
-			* only receive it Reject for Active Open...*/
+			 * not be REJECT.. This is Passive Open.. We can
+			 * only receive it Reject for Active Open...*/
 			WARN_ON(1);
-		}
 		cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
 		type = NES_CM_EVENT_MPA_REQ;
 		atomic_set(&cm_node->passive_state,
-				NES_PASSIVE_STATE_INDICATED);
+			   NES_PASSIVE_STATE_INDICATED);
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cleanup_retrans_entry(cm_node);
@@ -1535,8 +1777,8 @@ static void indicate_pkt_err(struct nes_
 	case NES_CM_STATE_SYN_SENT:
 	case NES_CM_STATE_MPAREQ_SENT:
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		active_open_err(cm_node, skb, 1);
 		break;
 	case NES_CM_STATE_ESTABLISHED:
@@ -1550,11 +1792,11 @@ static void indicate_pkt_err(struct nes_
 }
 
 static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err;
 
-	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;
 	if (err)
 		active_open_err(cm_node, skb, 1);
 
@@ -1562,7 +1804,7 @@ static int check_syn(struct nes_cm_node
 }
 
 static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err = 0;
 	u32 seq;
@@ -1570,21 +1812,22 @@ static int check_seq(struct nes_cm_node
 	u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
 	u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
 	u32 rcv_wnd;
+
 	seq = ntohl(tcph->seq);
 	ack_seq = ntohl(tcph->ack_seq);
 	rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
 	if (ack_seq != loc_seq_num)
 		err = 1;
-	else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
+	else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))
 		err = 1;
 	if (err) {
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		indicate_pkt_err(cm_node, skb);
 		nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
-			"rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
-			rcv_wnd);
+			  "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+			  rcv_wnd);
 	}
 	return err;
 }
@@ -1594,9 +1837,8 @@ static int check_seq(struct nes_cm_node
  * is created with a listener or it may comein as rexmitted packet which in
  * that case will be just dropped.
  */
-
 static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			   struct tcphdr *tcph)
 {
 	int ret;
 	u32 inc_sequence;
@@ -1615,15 +1857,15 @@ static void handle_syn_pkt(struct nes_cm
 	case NES_CM_STATE_LISTENING:
 		/* Passive OPEN */
 		if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
-				cm_node->listener->backlog) {
+		    cm_node->listener->backlog) {
 			nes_debug(NES_DBG_CM, "drop syn due to backlog "
-				"pressure \n");
+				  "pressure \n");
 			cm_backlog_drops++;
 			passive_open_err(cm_node, skb, 0);
 			break;
 		}
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
-			1);
+					 1);
 		if (ret) {
 			passive_open_err(cm_node, skb, 0);
 			/* drop pkt */
@@ -1657,9 +1899,8 @@ static void handle_syn_pkt(struct nes_cm
 }
 
 static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			      struct tcphdr *tcph)
 {
-
 	int ret;
 	u32 inc_sequence;
 	int optionsize;
@@ -1678,7 +1919,7 @@ static void handle_synack_pkt(struct nes
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
 		if (ret) {
 			nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
-				cm_node);
+				  cm_node);
 			break;
 		}
 		cleanup_retrans_entry(cm_node);
@@ -1717,12 +1958,13 @@ static void handle_synack_pkt(struct nes
 }
 
 static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			  struct tcphdr *tcph)
 {
 	int datasize = 0;
 	u32 inc_sequence;
 	int ret = 0;
 	int optionsize;
+
 	optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
 
 	if (check_seq(cm_node, tcph, skb))
@@ -1743,8 +1985,9 @@ static int handle_ack_pkt(struct nes_cm_
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* rcvd ACK only */
+		} else { /* rcvd ACK only */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_ESTABLISHED:
 		/* Passive OPEN */
@@ -1752,16 +1995,18 @@ static int handle_ack_pkt(struct nes_cm_
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else
+		} else {
 			drop_packet(skb);
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* Could be just an ack pkt.. */
+		} else { /* Could be just an ack pkt.. */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_LISTENING:
 		cleanup_retrans_entry(cm_node);
@@ -1802,14 +2047,15 @@ static int handle_ack_pkt(struct nes_cm_
 
 
 static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive)
+			      struct sk_buff *skb, int optionsize, int passive)
 {
 	u8 *optionsloc = (u8 *)&tcph[1];
+
 	if (optionsize) {
 		if (process_options(cm_node, optionsloc, optionsize,
-			(u32)tcph->syn)) {
+				    (u32)tcph->syn)) {
 			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
-				__func__, cm_node);
+				  __func__, cm_node);
 			if (passive)
 				passive_open_err(cm_node, skb, 1);
 			else
@@ -1819,7 +2065,7 @@ static int handle_tcp_options(struct nes
 	}
 
 	cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
-			cm_node->tcp_cntxt.snd_wscale;
+				     cm_node->tcp_cntxt.snd_wscale;
 
 	if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
 		cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
@@ -1830,18 +2076,18 @@ static int handle_tcp_options(struct nes
  * active_open_err() will send reset() if flag set..
  * It will also send ABORT event.
  */
-
 static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			    int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	if (reset) {
 		nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
-				"state=%d\n", cm_node, cm_node->state);
+			  "state=%d\n", cm_node, cm_node->state);
 		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
-	} else
+	} else {
 		dev_kfree_skb_any(skb);
+	}
 
 	cm_node->state = NES_CM_STATE_CLOSED;
 	create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1851,15 +2097,14 @@ static void active_open_err(struct nes_c
  * passive_open_err() will either do a reset() or will free up the skb and
  * remove the cm_node.
  */
-
 static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			     int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	cm_node->state = NES_CM_STATE_CLOSED;
 	if (reset) {
 		nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
-			"cm_node=%p state =%d\n", cm_node, cm_node->state);
+			  "cm_node=%p state =%d\n", cm_node, cm_node->state);
 		send_reset(cm_node, skb);
 	} else {
 		dev_kfree_skb_any(skb);
@@ -1874,6 +2119,7 @@ static void passive_open_err(struct nes_
 static void free_retrans_entry(struct nes_cm_node *cm_node)
 {
 	struct nes_timer_entry *send_entry;
+
 	send_entry = cm_node->send_entry;
 	if (send_entry) {
 		cm_node->send_entry = NULL;
@@ -1897,26 +2143,28 @@ static void cleanup_retrans_entry(struct
  * Returns skb if to be freed, else it will return NULL if already used..
  */
 static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct nes_cm_core *cm_core)
+			   struct nes_cm_core *cm_core)
 {
-	enum nes_tcpip_pkt_type	pkt_type = NES_PKT_TYPE_UNKNOWN;
+	enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
 	struct tcphdr *tcph = tcp_hdr(skb);
-	u32     fin_set = 0;
+	u32 fin_set = 0;
 	int ret = 0;
+
 	skb_pull(skb, ip_hdr(skb)->ihl << 2);
 
 	nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
-		"ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
-		tcph->ack, tcph->rst, tcph->fin);
+		  "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+		  tcph->ack, tcph->rst, tcph->fin);
 
-	if (tcph->rst)
+	if (tcph->rst) {
 		pkt_type = NES_PKT_TYPE_RST;
-	else if (tcph->syn) {
+	} else if (tcph->syn) {
 		pkt_type = NES_PKT_TYPE_SYN;
 		if (tcph->ack)
 			pkt_type = NES_PKT_TYPE_SYNACK;
-	} else if (tcph->ack)
+	} else if (tcph->ack) {
 		pkt_type = NES_PKT_TYPE_ACK;
+	}
 	if (tcph->fin)
 		fin_set = 1;
 
@@ -1947,17 +2195,17 @@ static void process_packet(struct nes_cm
  * mini_cm_listen - create a listen node with params
  */
 static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+					      struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
 {
 	struct nes_cm_listener *listener;
 	unsigned long flags;
 
 	nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
-		cm_info->loc_addr, cm_info->loc_port);
+		  cm_info->loc_addr, cm_info->loc_port);
 
 	/* cannot have multiple matching listeners */
 	listener = find_listener(cm_core, htonl(cm_info->loc_addr),
-			htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
+				 htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
 	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
 		/* find automatically incs ref count ??? */
 		atomic_dec(&listener->ref_count);
@@ -2003,9 +2251,9 @@ static struct nes_cm_listener *mini_cm_l
 	}
 
 	nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
-			" listener = %p, backlog = %d, cm_id = %p.\n",
-			cm_info->loc_addr, cm_info->loc_port,
-			listener, listener->backlog, listener->cm_id);
+		  " listener = %p, backlog = %d, cm_id = %p.\n",
+		  cm_info->loc_addr, cm_info->loc_port,
+		  listener, listener->backlog, listener->cm_id);
 
 	return listener;
 }
@@ -2015,26 +2263,20 @@ static struct nes_cm_listener *mini_cm_l
  * mini_cm_connect - make a connection node with params
  */
 static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, u16 private_data_len,
-	void *private_data, struct nes_cm_info *cm_info)
+					   struct nes_vnic *nesvnic, u16 private_data_len,
+					   void *private_data, struct nes_cm_info *cm_info)
 {
 	int ret = 0;
 	struct nes_cm_node *cm_node;
 	struct nes_cm_listener *loopbackremotelistener;
 	struct nes_cm_node *loopbackremotenode;
 	struct nes_cm_info loopback_cm_info;
-	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
-	struct ietf_mpa_frame *mpa_frame = NULL;
+	u8 *start_buff;
 
 	/* create a CM connection node */
 	cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
 	if (!cm_node)
 		return NULL;
-	mpa_frame = &cm_node->mpa_frame;
-	memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
-	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
-	mpa_frame->rev =  IETF_MPA_VERSION;
-	mpa_frame->priv_data_len = htons(private_data_len);
 
 	/* set our node side to client (active) side */
 	cm_node->tcp_cntxt.client = 1;
@@ -2042,8 +2284,8 @@ static struct nes_cm_node *mini_cm_conne
 
 	if (cm_info->loc_addr == cm_info->rem_addr) {
 		loopbackremotelistener = find_listener(cm_core,
-				ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						       ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+						       NES_CM_LISTENER_ACTIVE_STATE);
 		if (loopbackremotelistener == NULL) {
 			create_event(cm_node, NES_CM_EVENT_ABORTED);
 		} else {
@@ -2052,7 +2294,7 @@ static struct nes_cm_node *mini_cm_conne
 			loopback_cm_info.rem_port = cm_info->loc_port;
 			loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
 			loopbackremotenode = make_cm_node(cm_core, nesvnic,
-				&loopback_cm_info, loopbackremotelistener);
+							  &loopback_cm_info, loopbackremotelistener);
 			if (!loopbackremotenode) {
 				rem_ref_cm_node(cm_node->cm_core, cm_node);
 				return NULL;
@@ -2063,7 +2305,7 @@ static struct nes_cm_node *mini_cm_conne
 				NES_CM_DEFAULT_RCV_WND_SCALE;
 			cm_node->loopbackpartner = loopbackremotenode;
 			memcpy(loopbackremotenode->mpa_frame_buf, private_data,
-				private_data_len);
+			       private_data_len);
 			loopbackremotenode->mpa_frame_size = private_data_len;
 
 			/* we are done handling this state. */
@@ -2091,12 +2333,10 @@ static struct nes_cm_node *mini_cm_conne
 		return cm_node;
 	}
 
-	/* set our node side to client (active) side */
-	cm_node->tcp_cntxt.client = 1;
-	/* init our MPA frame ptr */
-	memcpy(mpa_frame->priv_data, private_data, private_data_len);
+	start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+	cm_node->mpa_frame_size = private_data_len;
 
-	cm_node->mpa_frame_size = mpa_frame_size;
+	memcpy(start_buff, private_data, private_data_len);
 
 	/* send a syn and goto syn sent state */
 	cm_node->state = NES_CM_STATE_SYN_SENT;
@@ -2105,18 +2345,19 @@ static struct nes_cm_node *mini_cm_conne
 	if (ret) {
 		/* error in sending the syn free up the cm_node struct */
 		nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
-			"addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 		cm_node = NULL;
 	}
 
-	if (cm_node)
+	if (cm_node) {
 		nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
-			"port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
+	}
 
 	return cm_node;
 }
@@ -2126,8 +2367,7 @@ static struct nes_cm_node *mini_cm_conne
  * mini_cm_accept - accept a connection
  * This function is never called
  */
-static int mini_cm_accept(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	return 0;
 }
@@ -2136,8 +2376,7 @@ static int mini_cm_accept(struct nes_cm_
 /**
  * mini_cm_reject - reject and teardown a connection
  */
-static int mini_cm_reject(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	int ret = 0;
 	int err = 0;
@@ -2147,7 +2386,7 @@ static int mini_cm_reject(struct nes_cm_
 	struct nes_cm_node *loopback = cm_node->loopbackpartner;
 
 	nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
-		__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
+		  __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
 
 	if (cm_node->tcp_cntxt.client)
 		return ret;
@@ -2168,8 +2407,9 @@ static int mini_cm_reject(struct nes_cm_
 					err = send_reset(cm_node, NULL);
 					if (err)
 						WARN_ON(1);
-				} else
+				} else {
 					cm_id->add_ref(cm_id);
+				}
 			}
 		}
 	} else {
@@ -2244,7 +2484,7 @@ static int mini_cm_close(struct nes_cm_c
 	case NES_CM_STATE_TSA:
 		if (cm_node->send_entry)
 			printk(KERN_ERR "ERROR Close got called from STATE_TSA "
-				"send_entry=%p\n", cm_node->send_entry);
+			       "send_entry=%p\n", cm_node->send_entry);
 		ret = rem_ref_cm_node(cm_core, cm_node);
 		break;
 	}
@@ -2257,7 +2497,7 @@ static int mini_cm_close(struct nes_cm_c
  * node state machine
  */
 static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct sk_buff *skb)
+			    struct nes_vnic *nesvnic, struct sk_buff *skb)
 {
 	struct nes_cm_node *cm_node = NULL;
 	struct nes_cm_listener *listener = NULL;
@@ -2269,9 +2509,8 @@ static int mini_cm_recv_pkt(struct nes_c
 
 	if (!skb)
 		return 0;
-	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))
 		return 0;
-	}
 
 	iph = (struct iphdr *)skb->data;
 	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
@@ -2289,8 +2528,8 @@ static int mini_cm_recv_pkt(struct nes_c
 
 	do {
 		cm_node = find_node(cm_core,
-			nfo.rem_port, nfo.rem_addr,
-			nfo.loc_port, nfo.loc_addr);
+				    nfo.rem_port, nfo.rem_addr,
+				    nfo.loc_port, nfo.loc_addr);
 
 		if (!cm_node) {
 			/* Only type of packet accepted are for */
@@ -2300,8 +2539,8 @@ static int mini_cm_recv_pkt(struct nes_c
 				break;
 			}
 			listener = find_listener(cm_core, nfo.loc_addr,
-				nfo.loc_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						 nfo.loc_port,
+						 NES_CM_LISTENER_ACTIVE_STATE);
 			if (!listener) {
 				nfo.cm_id = NULL;
 				nfo.conn_type = 0;
@@ -2312,10 +2551,10 @@ static int mini_cm_recv_pkt(struct nes_c
 			nfo.cm_id = listener->cm_id;
 			nfo.conn_type = listener->conn_type;
 			cm_node = make_cm_node(cm_core, nesvnic, &nfo,
-				listener);
+					       listener);
 			if (!cm_node) {
 				nes_debug(NES_DBG_CM, "Unable to allocate "
-					"node\n");
+					  "node\n");
 				cm_packets_dropped++;
 				atomic_dec(&listener->ref_count);
 				dev_kfree_skb_any(skb);
@@ -2331,9 +2570,13 @@ static int mini_cm_recv_pkt(struct nes_c
 			}
 			add_ref_cm_node(cm_node);
 		} else if (cm_node->state == NES_CM_STATE_TSA) {
-			rem_ref_cm_node(cm_core, cm_node);
-			atomic_inc(&cm_accel_dropped_pkts);
-			dev_kfree_skb_any(skb);
+			if (cm_node->nesqp->pau_mode)
+				nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
+			else {
+				rem_ref_cm_node(cm_core, cm_node);
+				atomic_inc(&cm_accel_dropped_pkts);
+				dev_kfree_skb_any(skb);
+			}
 			break;
 		}
 		skb_reset_network_header(skb);
@@ -2363,7 +2606,7 @@ static struct nes_cm_core *nes_cm_alloc_
 	init_timer(&cm_core->tcp_timer);
 	cm_core->tcp_timer.function = nes_cm_timer_tick;
 
-	cm_core->mtu   = NES_CM_DEFAULT_MTU;
+	cm_core->mtu = NES_CM_DEFAULT_MTU;
 	cm_core->state = NES_CM_STATE_INITED;
 	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
 
@@ -2401,9 +2644,8 @@ static int mini_cm_dealloc_core(struct n
 
 	barrier();
 
-	if (timer_pending(&cm_core->tcp_timer)) {
+	if (timer_pending(&cm_core->tcp_timer))
 		del_timer(&cm_core->tcp_timer);
-	}
 
 	destroy_workqueue(cm_core->event_wq);
 	destroy_workqueue(cm_core->disconn_wq);
@@ -2458,8 +2700,8 @@ static int nes_cm_init_tsa_conn(struct n
 		return -EINVAL;
 
 	nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
-			NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
-			NES_QPCONTEXT_MISC_DROS);
+						  NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
+						  NES_QPCONTEXT_MISC_DROS);
 
 	if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
 		nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
@@ -2469,15 +2711,15 @@ static int nes_cm_init_tsa_conn(struct n
 	nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
 
 	nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
-			(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
+		(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
+		(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
+		(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
 
 	nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
 	nesqp->nesqp_context->ts_recent = 0;
@@ -2486,24 +2728,24 @@ static int nes_cm_init_tsa_conn(struct n
 	nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
 	nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
-			cm_node->tcp_cntxt.rcv_wscale);
+						    cm_node->tcp_cntxt.rcv_wscale);
 	nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->srtt = 0;
 	nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
 	nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
-	nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
+	nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);
 	nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
 
 	nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
-			" Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
-			nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
-			le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
-			le32_to_cpu(nesqp->nesqp_context->misc));
+		  " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
+		  nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
+		  le32_to_cpu(nesqp->nesqp_context->misc));
 	nes_debug(NES_DBG_CM, "  snd_wnd  = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
 	nes_debug(NES_DBG_CM, "  snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
 	nes_debug(NES_DBG_CM, "  max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
@@ -2524,7 +2766,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
 
 	work = kzalloc(sizeof *work, GFP_ATOMIC);
 	if (!work)
-		return -ENOMEM; /* Timer will clean up */
+		return -ENOMEM;  /* Timer will clean up */
 
 	nes_add_ref(&nesqp->ibqp);
 	work->nesqp = nesqp;
@@ -2544,7 +2786,7 @@ static void nes_disconnect_worker(struct
 
 	kfree(dwork);
 	nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
-			nesqp->last_aeq, nesqp->hwqp.qp_id);
+		  nesqp->last_aeq, nesqp->hwqp.qp_id);
 	nes_cm_disconn_true(nesqp);
 	nes_rem_ref(&nesqp->ibqp);
 }
@@ -2580,7 +2822,7 @@ static int nes_cm_disconn_true(struct ne
 	/* make sure we havent already closed this connection */
 	if (!cm_id) {
 		nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
-				nesqp->hwqp.qp_id);
+			  nesqp->hwqp.qp_id);
 		spin_unlock_irqrestore(&nesqp->lock, flags);
 		return -1;
 	}
@@ -2589,7 +2831,7 @@ static int nes_cm_disconn_true(struct ne
 	nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
 
 	original_hw_tcp_state = nesqp->hw_tcp_state;
-	original_ibqp_state   = nesqp->ibqp_state;
+	original_ibqp_state = nesqp->ibqp_state;
 	last_ae = nesqp->last_aeq;
 
 	if (nesqp->term_flags) {
@@ -2647,16 +2889,16 @@ static int nes_cm_disconn_true(struct ne
 			cm_event.private_data_len = 0;
 
 			nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
-				" for  QP%u, SQ Head = %u, SQ Tail = %u. "
-				"cm_id = %p, refcount = %u.\n",
-				nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
-				nesqp->hwqp.sq_tail, cm_id,
-				atomic_read(&nesqp->refcount));
+				  " for  QP%u, SQ Head = %u, SQ Tail = %u. "
+				  "cm_id = %p, refcount = %u.\n",
+				  nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+				  nesqp->hwqp.sq_tail, cm_id,
+				  atomic_read(&nesqp->refcount));
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
 			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler "
-					"returned, ret=%d\n", ret);
+					  "returned, ret=%d\n", ret);
 		}
 
 		if (issue_close) {
@@ -2674,9 +2916,8 @@ static int nes_cm_disconn_true(struct ne
 			cm_event.private_data_len = 0;
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
-			if (ret) {
+			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
-			}
 
 			cm_id->rem_ref(cm_id);
 		}
@@ -2716,8 +2957,8 @@ static int nes_disconnect(struct nes_qp
 			if (nesqp->lsmm_mr)
 				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
 			pci_free_consistent(nesdev->pcidev,
-					nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-					nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 		}
 	}
 
@@ -2756,6 +2997,12 @@ int nes_accept(struct iw_cm_id *cm_id, s
 	struct ib_phys_buf ibphysbuf;
 	struct nes_pd *nespd;
 	u64 tagged_offset;
+	u8 mpa_frame_offset = 0;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
 	if (!ibqp)
@@ -2796,53 +3043,49 @@ int nes_accept(struct iw_cm_id *cm_id, s
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
 			netdev_refcnt_read(nesvnic->netdev));
 
+	nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);
 	/* allocate the ietf frame and space for private data */
 	nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
-		sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
-		&nesqp->ietf_frame_pbase);
+						 nesqp->ietf_frame_size + conn_param->private_data_len,
+						 &nesqp->ietf_frame_pbase);
 
 	if (!nesqp->ietf_frame) {
-		nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
-			"data\n");
+		nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
 		return -ENOMEM;
 	}
+	mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame;
 
+	if (cm_node->mpa_frame_rev == IETF_MPA_V1)
+		mpa_frame_offset = 4;
 
-	/* setup the MPA frame */
-	nesqp->private_data_len = conn_param->private_data_len;
-	memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
-
-	memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
-			conn_param->private_data_len);
+	memcpy(mpa_v2_frame->priv_data, conn_param->private_data,
+	       conn_param->private_data_len);
 
-	nesqp->ietf_frame->priv_data_len =
-		cpu_to_be16(conn_param->private_data_len);
-	nesqp->ietf_frame->rev = mpa_version;
-	nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY);
+	nesqp->private_data_len = conn_param->private_data_len;
 
 	/* setup our first outgoing iWarp send WQE (the IETF frame response) */
 	wqe = &nesqp->hwqp.sq_vbase[0];
 
 	if (cm_id->remote_addr.sin_addr.s_addr !=
-			cm_id->local_addr.sin_addr.s_addr) {
+	    cm_id->local_addr.sin_addr.s_addr) {
 		u64temp = (unsigned long)nesqp;
 		nesibdev = nesvnic->nesibdev;
 		nespd = nesqp->nespd;
-		ibphysbuf.addr = nesqp->ietf_frame_pbase;
-		ibphysbuf.size = conn_param->private_data_len +
-					sizeof(struct ietf_mpa_frame);
-		tagged_offset = (u64)(unsigned long)nesqp->ietf_frame;
+		ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset;
+		ibphysbuf.size = buff_len;
+		tagged_offset = (u64)(unsigned long)*start_buff;
 		ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
-						&ibphysbuf, 1,
-						IB_ACCESS_LOCAL_WRITE,
-						&tagged_offset);
+						   &ibphysbuf, 1,
+						   IB_ACCESS_LOCAL_WRITE,
+						   &tagged_offset);
 		if (!ibmr) {
 			nes_debug(NES_DBG_CM, "Unable to register memory region"
-					"for lSMM for cm_node = %p \n",
-					cm_node);
+				  "for lSMM for cm_node = %p \n",
+				  cm_node);
 			pci_free_consistent(nesdev->pcidev,
-				nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-				nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 			return -ENOMEM;
 		}
 
@@ -2850,22 +3093,20 @@ int nes_accept(struct iw_cm_id *cm_id, s
 		ibmr->device = nespd->ibpd.device;
 		nesqp->lsmm_mr = ibmr;
 
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+		u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
 		set_wqe_64bit_value(wqe->wqe_words,
-			NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
-			u64temp);
+				    NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+				    u64temp);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
 			cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
-			NES_IWARP_SQ_WQE_WRPDU);
+				    NES_IWARP_SQ_WQE_WRPDU);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		set_wqe_64bit_value(wqe->wqe_words,
-					NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
-					(u64)(unsigned long)nesqp->ietf_frame);
+				    NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+				    (u64)(unsigned long)(*start_buff));
 		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
 		if (nesqp->sq_kmapped) {
 			nesqp->sq_kmapped = 0;
@@ -2874,7 +3115,7 @@ int nes_accept(struct iw_cm_id *cm_id, s
 
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-			NES_QPCONTEXT_ORDIRD_WRPDU);
+				    NES_QPCONTEXT_ORDIRD_WRPDU);
 	} else {
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
@@ -2888,11 +3129,11 @@ int nes_accept(struct iw_cm_id *cm_id, s
 
 	/*  nesqp->cm_node = (void *)cm_id->provider_data; */
 	cm_id->provider_data = nesqp;
-	nesqp->active_conn   = 0;
+	nesqp->active_conn = 0;
 
 	if (cm_node->state == NES_CM_STATE_TSA)
 		nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
-			cm_node);
+			  cm_node);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -2909,13 +3150,13 @@ int nes_accept(struct iw_cm_id *cm_id, s
 			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
 	nesqp->nesqp_context->misc2 |= cpu_to_le32(
-			(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
-			NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+		(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+		NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
 
 	nesqp->nesqp_context->arp_index_vlan |=
 		cpu_to_le32(nes_arp_table(nesdev,
-			le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
-			NES_ARP_RESOLVE) << 16);
+					  le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+					  NES_ARP_RESOLVE) << 16);
 
 	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
 		jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
@@ -2941,7 +3182,7 @@ int nes_accept(struct iw_cm_id *cm_id, s
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
-		nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
 
 	nesqp->hte_index &= adapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
@@ -2949,17 +3190,15 @@ int nes_accept(struct iw_cm_id *cm_id, s
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
-			"0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
-			"private data length=%zu.\n", nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohl(cm_id->local_addr.sin_addr.s_addr),
-			ntohs(cm_id->local_addr.sin_port),
-			le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
-
+		  "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+		  "private data length=%u.\n", nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  buff_len);
 
 	/* notify OF layer that accept event was successful */
 	cm_id->add_ref(cm_id);
@@ -2980,12 +3219,12 @@ int nes_accept(struct iw_cm_id *cm_id, s
 			nesqp->private_data_len;
 		/* copy entire MPA frame to our cm_node's frame */
 		memcpy(cm_node->loopbackpartner->mpa_frame_buf,
-			nesqp->ietf_frame->priv_data, nesqp->private_data_len);
+		       conn_param->private_data, conn_param->private_data_len);
 		create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
 	}
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 
 	return 0;
 }
@@ -2998,34 +3237,28 @@ int nes_reject(struct iw_cm_id *cm_id, c
 {
 	struct nes_cm_node *cm_node;
 	struct nes_cm_node *loopback;
-
 	struct nes_cm_core *cm_core;
+	u8 *start_buff;
 
 	atomic_inc(&cm_rejects);
-	cm_node = (struct nes_cm_node *) cm_id->provider_data;
+	cm_node = (struct nes_cm_node *)cm_id->provider_data;
 	loopback = cm_node->loopbackpartner;
 	cm_core = cm_node->cm_core;
 	cm_node->cm_id = cm_id;
-	cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
 
-	if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
+	if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)
 		return -EINVAL;
 
-	memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 	if (loopback) {
 		memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
 		loopback->mpa_frame.priv_data_len = pdata_len;
-		loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
-				pdata_len;
+		loopback->mpa_frame_size = pdata_len;
 	} else {
-		memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
-		cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
+		start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+		cm_node->mpa_frame_size = pdata_len;
+		memcpy(start_buff, pdata, pdata_len);
 	}
-
-	cm_node->mpa_frame.rev = mpa_version;
-	cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
-
-	return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
+	return cm_core->api->reject(cm_core, cm_node);
 }
 
 
@@ -3052,7 +3285,7 @@ int nes_connect(struct iw_cm_id *cm_id,
 	nesvnic = to_nesvnic(nesqp->ibqp.device);
 	if (!nesvnic)
 		return -EINVAL;
-	nesdev  = nesvnic->nesdev;
+	nesdev = nesvnic->nesdev;
 	if (!nesdev)
 		return -EINVAL;
 
@@ -3060,12 +3293,12 @@ int nes_connect(struct iw_cm_id *cm_id,
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
-		"0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
-		ntohl(nesvnic->local_ipaddr),
-		ntohl(cm_id->remote_addr.sin_addr.s_addr),
-		ntohs(cm_id->remote_addr.sin_port),
-		ntohl(cm_id->local_addr.sin_addr.s_addr),
-		ntohs(cm_id->local_addr.sin_port));
+		  "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+		  ntohl(nesvnic->local_ipaddr),
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port));
 
 	atomic_inc(&cm_connects);
 	nesqp->active_conn = 1;
@@ -3079,12 +3312,12 @@ int nes_connect(struct iw_cm_id *cm_id,
 	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
-		conn_param->private_data_len);
+		  conn_param->private_data_len);
 
 	if (cm_id->local_addr.sin_addr.s_addr !=
-		cm_id->remote_addr.sin_addr.s_addr) {
+	    cm_id->remote_addr.sin_addr.s_addr) {
 		nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+				 PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
 		apbvt_set = 1;
 	}
 
@@ -3100,13 +3333,13 @@ int nes_connect(struct iw_cm_id *cm_id,
 
 	/* create a connect CM node connection */
 	cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
-		conn_param->private_data_len, (void *)conn_param->private_data,
-		&cm_info);
+					  conn_param->private_data_len, (void *)conn_param->private_data,
+					  &cm_info);
 	if (!cm_node) {
 		if (apbvt_set)
 			nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-				PCI_FUNC(nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 
 		cm_id->rem_ref(cm_id);
 		return -ENOMEM;
@@ -3156,7 +3389,7 @@ int nes_create_listen(struct iw_cm_id *c
 	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
 	if (!cm_node) {
 		printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
-				__func__, __LINE__);
+		       __func__, __LINE__);
 		return -ENOMEM;
 	}
 
@@ -3164,12 +3397,12 @@ int nes_create_listen(struct iw_cm_id *c
 
 	if (!cm_node->reused_node) {
 		err = nes_manage_apbvt(nesvnic,
-			ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
-			NES_MANAGE_APBVT_ADD);
+				       ntohs(cm_id->local_addr.sin_port),
+				       PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+				       NES_MANAGE_APBVT_ADD);
 		if (err) {
 			printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
-				err);
+			       err);
 			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
 			return err;
 		}
@@ -3206,13 +3439,13 @@ int nes_destroy_listen(struct iw_cm_id *
 int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
 {
 	int rc = 0;
+
 	cm_packets_received++;
-	if ((g_cm_core) && (g_cm_core->api)) {
+	if ((g_cm_core) && (g_cm_core->api))
 		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
-	} else {
+	else
 		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
-				" cm is not setup properly.\n");
-	}
+			  " cm is not setup properly.\n");
 
 	return rc;
 }
@@ -3227,11 +3460,10 @@ int nes_cm_start(void)
 	nes_debug(NES_DBG_CM, "\n");
 	/* create the primary CM core, pass this handle to subsequent core inits */
 	g_cm_core = nes_cm_alloc_core();
-	if (g_cm_core) {
+	if (g_cm_core)
 		return 0;
-	} else {
+	else
 		return -ENOMEM;
-	}
 }
 
 
@@ -3252,7 +3484,6 @@ int nes_cm_stop(void)
  */
 static void cm_event_connected(struct nes_cm_event *event)
 {
-	u64 u64temp;
 	struct nes_qp *nesqp;
 	struct nes_vnic *nesvnic;
 	struct nes_device *nesdev;
@@ -3261,7 +3492,6 @@ static void cm_event_connected(struct ne
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	struct nes_hw_qp_wqe *wqe;
 	struct nes_v4_quad nes_quad;
 	u32 crc_value;
 	int ret;
@@ -3275,17 +3505,16 @@ static void cm_event_connected(struct ne
 	nesdev = nesvnic->nesdev;
 	nesadapter = nesdev->nesadapter;
 
-	if (nesqp->destroyed) {
+	if (nesqp->destroyed)
 		return;
-	}
 	atomic_inc(&cm_connecteds);
 	nes_debug(NES_DBG_CM, "QP%u attempting to connect to  0x%08X:0x%04X on"
-			" local port 0x%04X. jiffies = %lu.\n",
-			nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohs(cm_id->local_addr.sin_port),
-			jiffies);
+		  " local port 0x%04X. jiffies = %lu.\n",
+		  nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohs(cm_id->local_addr.sin_port),
+		  jiffies);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -3316,40 +3545,12 @@ static void cm_event_connected(struct ne
 			NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
 
 	/* Adjust tail for not having a LSMM */
-	nesqp->hwqp.sq_tail = 1;
-
-#if defined(NES_SEND_FIRST_WRITE)
-	if (cm_node->send_write0) {
-		nes_debug(NES_DBG_CM, "Sending first write.\n");
-		wqe = &nesqp->hwqp.sq_vbase[0];
-		u64temp = (unsigned long)nesqp;
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
-		set_wqe_64bit_value(wqe->wqe_words,
-				NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
-			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+	/*nesqp->hwqp.sq_tail = 1;*/
 
-		if (nesqp->sq_kmapped) {
-			nesqp->sq_kmapped = 0;
-			kunmap(nesqp->page);
-		}
+	build_rdma0_msg(cm_node, &nesqp);
 
-		/* use the reserved spot on the WQ for the extra first WQE */
-		nesqp->nesqp_context->ird_ord_sizes &=
-			cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-						NES_QPCONTEXT_ORDIRD_WRPDU |
-						NES_QPCONTEXT_ORDIRD_ALSMM));
-		nesqp->skip_lsmm = 1;
-		nesqp->hwqp.sq_tail = 0;
-		nes_write32(nesdev->regs + NES_WQE_ALLOC,
-				(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
-	}
-#endif
+	nes_write32(nesdev->regs + NES_WQE_ALLOC,
+		    (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
 
 	memset(&nes_quad, 0, sizeof(nes_quad));
 
@@ -3366,13 +3567,13 @@ static void cm_event_connected(struct ne
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
-			nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
 
 	nesqp->hte_index &= nesadapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
 
 	nesqp->ietf_frame = &cm_node->mpa_frame;
-	nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
+	nesqp->private_data_len = (u8)cm_node->mpa_frame_size;
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	/* notify OF layer we successfully created the requested connection */
@@ -3384,7 +3585,9 @@ static void cm_event_connected(struct ne
 	cm_event.remote_addr = cm_id->remote_addr;
 
 	cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
 	ret = cm_id->event_handler(cm_id, &cm_event);
@@ -3392,12 +3595,12 @@ static void cm_event_connected(struct ne
 
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	attr.qp_state = IB_QPS_RTS;
 	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
 
 	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
-		"%lu\n", nesqp->hwqp.qp_id, jiffies);
+		  "%lu\n", nesqp->hwqp.qp_id, jiffies);
 
 	return;
 }
@@ -3418,16 +3621,14 @@ static void cm_event_connect_error(struc
 		return;
 
 	cm_id = event->cm_node->cm_id;
-	if (!cm_id) {
+	if (!cm_id)
 		return;
-	}
 
 	nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
 	nesqp = cm_id->provider_data;
 
-	if (!nesqp) {
+	if (!nesqp)
 		return;
-	}
 
 	/* notify OF layer about this connection error event */
 	/* cm_id->rem_ref(cm_id); */
@@ -3442,14 +3643,14 @@ static void cm_event_connect_error(struc
 	cm_event.private_data_len = 0;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
-		"remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
-		cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	cm_id->rem_ref(cm_id);
 
 	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
@@ -3519,7 +3720,7 @@ static void cm_event_reset(struct nes_cm
  */
 static void cm_event_mpa_req(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	int ret;
 	struct nes_cm_node *cm_node;
@@ -3531,7 +3732,7 @@ static void cm_event_mpa_req(struct nes_
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	cm_event.status = 0;
@@ -3545,19 +3746,21 @@ static void cm_event_mpa_req(struct nes_
 	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len  = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 	return;
 }
 
 
 static void cm_event_mpa_reject(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	struct nes_cm_node *cm_node;
 	int ret;
@@ -3569,7 +3772,7 @@ static void cm_event_mpa_reject(struct n
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
 	cm_event.status = -ECONNREFUSED;
@@ -3584,17 +3787,17 @@ static void cm_event_mpa_reject(struct n
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
-			"remove_addr=%08x\n",
-			cm_event.local_addr.sin_addr.s_addr,
-			cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n",
+		  cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 
 	return;
 }
@@ -3613,7 +3816,7 @@ static int nes_cm_post_event(struct nes_
 	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
 	INIT_WORK(&event->event_work, nes_cm_event_handler);
 	nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
-		event->cm_node, event);
+		  event->cm_node, event);
 
 	queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
 
@@ -3630,7 +3833,7 @@ static int nes_cm_post_event(struct nes_
 static void nes_cm_event_handler(struct work_struct *work)
 {
 	struct nes_cm_event *event = container_of(work, struct nes_cm_event,
-			event_work);
+						  event_work);
 	struct nes_cm_core *cm_core;
 
 	if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
@@ -3638,29 +3841,29 @@ static void nes_cm_event_handler(struct
 
 	cm_core = event->cm_node->cm_core;
 	nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
-		event, event->type, atomic_read(&cm_core->events_posted));
+		  event, event->type, atomic_read(&cm_core->events_posted));
 
 	switch (event->type) {
 	case NES_CM_EVENT_MPA_REQ:
 		cm_event_mpa_req(event);
 		nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
-			event->cm_node);
+			  event->cm_node);
 		break;
 	case NES_CM_EVENT_RESET:
 		nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
-			event->cm_node);
+			  event->cm_node);
 		cm_event_reset(event);
 		break;
 	case NES_CM_EVENT_CONNECTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state != NES_CM_STATE_TSA))
+		    (event->cm_node->state != NES_CM_STATE_TSA))
 			break;
 		cm_event_connected(event);
 		nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
 		break;
 	case NES_CM_EVENT_MPA_REJECT:
 		if ((!event->cm_node->cm_id) ||
-				(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_mpa_reject(event);
 		nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
@@ -3668,7 +3871,7 @@ static void nes_cm_event_handler(struct
 
 	case NES_CM_EVENT_ABORTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_connect_error(event);
 		nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_cm.h linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_cm.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_cm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_cm.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,16 @@
 #define IETF_MPA_KEY_SIZE 16
 #define IETF_MPA_VERSION  1
 #define IETF_MAX_PRIV_DATA_LEN 512
-#define IETF_MPA_FRAME_SIZE     20
+#define IETF_MPA_FRAME_SIZE    20
+#define IETF_RTR_MSG_SIZE      4
+#define IETF_MPA_V2_FLAG       0x10
+
+/* IETF RTR MSG Fields               */
+#define IETF_PEER_TO_PEER       0x8000
+#define IETF_FLPDU_ZERO_LEN     0x4000
+#define IETF_RDMA0_WRITE        0x8000
+#define IETF_RDMA0_READ         0x4000
+#define IETF_NO_IRD_ORD         0x3FFF
 
 enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */
@@ -56,7 +65,7 @@ enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_REJECT  = 0x20,	/* Reject */
 };
 
-struct ietf_mpa_frame {
+struct ietf_mpa_v1 {
 	u8 key[IETF_MPA_KEY_SIZE];
 	u8 flags;
 	u8 rev;
@@ -66,6 +75,20 @@ struct ietf_mpa_frame {
 
 #define ietf_mpa_req_resp_frame ietf_mpa_frame
 
+struct ietf_rtr_msg {
+	__be16 ctrl_ird;
+	__be16 ctrl_ord;
+};
+
+struct ietf_mpa_v2 {
+	u8 key[IETF_MPA_KEY_SIZE];
+	u8 flags;
+	u8 rev;
+	 __be16 priv_data_len;
+	struct ietf_rtr_msg rtr_msg;
+	u8 priv_data[0];
+};
+
 struct nes_v4_quad {
 	u32 rsvd0;
 	__le32 DstIpAdrIndex;	/* Only most significant 5 bits are valid */
@@ -171,8 +194,7 @@ struct nes_timer_entry {
 
 #define NES_CM_DEF_SEQ2      0x18ed5740
 #define NES_CM_DEF_LOCAL_ID2 0xb807
-#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
-
+#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
 
 typedef u32 nes_addr_t;
 
@@ -204,6 +226,21 @@ enum nes_cm_node_state {
 	NES_CM_STATE_CLOSED
 };
 
+enum mpa_frame_version {
+	IETF_MPA_V1 = 1,
+	IETF_MPA_V2 = 2
+};
+
+enum mpa_frame_key {
+	MPA_KEY_REQUEST,
+	MPA_KEY_REPLY
+};
+
+enum send_rdma0 {
+	SEND_RDMA_READ_ZERO = 1,
+	SEND_RDMA_WRITE_ZERO = 2
+};
+
 enum nes_tcpip_pkt_type {
 	NES_PKT_TYPE_UNKNOWN,
 	NES_PKT_TYPE_SYN,
@@ -245,9 +282,9 @@ struct nes_cm_tcp_context {
 
 
 enum nes_cm_listener_state {
-	NES_CM_LISTENER_PASSIVE_STATE=1,
-	NES_CM_LISTENER_ACTIVE_STATE=2,
-	NES_CM_LISTENER_EITHER_STATE=3
+	NES_CM_LISTENER_PASSIVE_STATE = 1,
+	NES_CM_LISTENER_ACTIVE_STATE = 2,
+	NES_CM_LISTENER_EITHER_STATE = 3
 };
 
 struct nes_cm_listener {
@@ -283,16 +320,20 @@ struct nes_cm_node {
 
 	struct nes_cm_node        *loopbackpartner;
 
-	struct nes_timer_entry	*send_entry;
-
+	struct nes_timer_entry	  *send_entry;
+	struct nes_timer_entry    *recv_entry;
 	spinlock_t                retrans_list_lock;
-	struct nes_timer_entry  *recv_entry;
+	enum send_rdma0           send_rdma0_op;
 
-	int                       send_write0;
 	union {
-		struct ietf_mpa_frame mpa_frame;
-		u8                    mpa_frame_buf[MAX_CM_BUFFER];
+		struct ietf_mpa_v1 mpa_frame;
+		struct ietf_mpa_v2 mpa_v2_frame;
+		u8                 mpa_frame_buf[MAX_CM_BUFFER];
 	};
+	enum mpa_frame_version    mpa_frame_rev;
+	u16			  ird_size;
+	u16                       ord_size;
+
 	u16                       mpa_frame_size;
 	struct iw_cm_id           *cm_id;
 	struct list_head          list;
@@ -399,10 +440,8 @@ struct nes_cm_ops {
 			struct nes_vnic *, u16, void *,
 			struct nes_cm_info *);
 	int (*close)(struct nes_cm_core *, struct nes_cm_node *);
-	int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
-	int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
+	int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
+	int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
 	int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
 			struct sk_buff *);
 	int (*destroy_cm_core)(struct nes_cm_core *);
@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *
 int nes_cm_recv(struct sk_buff *, struct net_device *);
 int nes_cm_start(void);
 int nes_cm_stop(void);
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
 
 #endif			/* NES_CM_H */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes.h linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes.h	2012-01-04 18:55:44.000000000 -0500
@@ -102,6 +102,7 @@
 #define NES_DRV_OPT_NO_INLINE_DATA       0x00000080
 #define NES_DRV_OPT_DISABLE_INT_MOD      0x00000100
 #define NES_DRV_OPT_DISABLE_VIRT_WQ      0x00000200
+#define NES_DRV_OPT_ENABLE_PAU           0x00000400
 
 #define NES_AEQ_EVENT_TIMEOUT         2500
 #define NES_DISCONNECT_EVENT_TIMEOUT  2000
@@ -128,6 +129,7 @@
 #define NES_DBG_IW_RX       0x00020000
 #define NES_DBG_IW_TX       0x00040000
 #define NES_DBG_SHUTDOWN    0x00080000
+#define NES_DBG_PAU         0x00100000
 #define NES_DBG_RSVD1       0x10000000
 #define NES_DBG_RSVD2       0x20000000
 #define NES_DBG_RSVD3       0x40000000
@@ -162,6 +164,7 @@ do { \
 #include "nes_context.h"
 #include "nes_user.h"
 #include "nes_cm.h"
+#include "nes_mgt.h"
 
 extern int max_mtu;
 #define max_frame_len (max_mtu+ETH_HLEN)
@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
 extern atomic_t cm_nodes_destroyed;
 extern atomic_t cm_accel_dropped_pkts;
 extern atomic_t cm_resets_recvd;
+extern atomic_t pau_qps_created;
+extern atomic_t pau_qps_destroyed;
 
 extern u32 int_mod_timer_init;
 extern u32 int_mod_cq_depth_256;
@@ -273,6 +278,14 @@ struct nes_device {
 	u8                     link_recheck;
 };
 
+/* Receive skb private area - must fit in skb->cb area */
+struct nes_rskb_cb {
+	u64                    busaddr;
+	u32                    maplen;
+	u32                    seqnum;
+	u8                     *data_start;
+	struct nes_qp          *nesqp;
+};
 
 static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
 {
@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u
 static inline void
 nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
 {
-	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
-			(u64)((unsigned long) &nesdev->cqp));
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]       = 0;
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX]      = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]   = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]  = 0;
 	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_hw.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,6 +110,14 @@ static unsigned char *nes_tcp_state_str[
 };
 #endif
 
+static inline void print_ip(struct nes_cm_node *cm_node)
+{
+	unsigned char *rem_addr;
+	if (cm_node) {
+		rem_addr = (unsigned char *)&cm_node->rem_addr;
+		printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
+	}
+}
 
 /**
  * nes_nic_init_timer_defaults
@@ -1555,6 +1563,7 @@ static void nes_replenish_nic_rq(struct
 	struct nes_hw_nic_rq_wqe *nic_rqe;
 	struct nes_hw_nic *nesnic;
 	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
 	u32 rx_wqes_posted = 0;
 
 	nesnic = &nesvnic->nic;
@@ -1580,6 +1589,9 @@ static void nes_replenish_nic_rq(struct
 
 			bus_address = pci_map_single(nesdev->pcidev,
 					skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = nesvnic->max_frame_size;
 
 			nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
 			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
@@ -1669,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *n
 	u32 cqp_head;
 	u32 counter;
 	u32 wqe_count;
+	struct nes_rskb_cb *cb;
 	u8 jumbomode=0;
 
 	/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
@@ -1845,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *n
 
 		pmem = pci_map_single(nesdev->pcidev, skb->data,
 				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		cb->busaddr = pmem;
+		cb->maplen = nesvnic->max_frame_size;
 
 		nic_rqe = &nesvnic->nic.rq_vbase[counter];
 		nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
@@ -1873,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *n
 			jumbomode = 1;
 		nes_nic_init_timer_defaults(nesdev, jumbomode);
 	}
+	if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
+		(nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
+			nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
+			nes_destroy_nic_qp(nesvnic);
+		return -ENOMEM;
+	}
+
 	nesvnic->lro_mgr.max_aggr       = nes_lro_max_aggr;
 	nesvnic->lro_mgr.max_desc       = NES_MAX_LRO_DESCRIPTORS;
 	nesvnic->lro_mgr.lro_arr        = nesvnic->lro_desc;
@@ -1895,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic
 	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_hw_cqp_wqe *cqp_wqe;
 	struct nes_hw_nic_sq_wqe *nic_sqe;
-	struct nes_hw_nic_rq_wqe *nic_rqe;
 	__le16 *wqe_fragment_length;
 	u16  wqe_fragment_index;
-	u64 wqe_frag;
 	u32 cqp_head;
 	u32 wqm_cfg0;
 	unsigned long flags;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	int ret;
 
+	if (nesdev->nesadapter->allow_unaligned_fpdus)
+		nes_destroy_mgt(nesvnic);
+
 	/* clear wqe stall before destroying NIC QP */
 	wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
 	nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
 
 	/* Free remaining NIC receive buffers */
 	while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
-		nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
-		wqe_frag  = (u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
-		wqe_frag |= ((u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
-		pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
-				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
+		cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+		pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
+			PCI_DMA_FROMDEVICE);
+
 		dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
 		nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
 	}
@@ -2775,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_devic
 	struct nes_hw_nic_sq_wqe *nic_sqe;
 	struct sk_buff *skb;
 	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	__le16 *wqe_fragment_length;
 	u32 head;
 	u32 cq_size;
@@ -2859,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_devic
 				bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
 				pci_unmap_single(nesdev->pcidev, bus_address,
 						nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+				cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+				cb->busaddr = 0;
 				/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
 				/* rx_skb->len = rx_pkt_size; */
 				rx_skb->len = 0;  /* TODO: see if this is necessary */
@@ -2983,6 +3010,7 @@ skip_rx_indicate0:
 }
 
 
+
 /**
  * nes_cqp_ce_handler
  */
@@ -2997,6 +3025,8 @@ static void nes_cqp_ce_handler(struct ne
 	u32 cq_size;
 	u32 cqe_count=0;
 	u32 error_code;
+	u32 opcode;
+	u32 ctx_index;
 	/* u32 counter; */
 
 	head = cq->cq_head;
@@ -3007,12 +3037,9 @@ static void nes_cqp_ce_handler(struct ne
 		/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
 			  le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
 
-		if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
-			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
-			cqp = *((struct nes_hw_cqp **)&u64temp);
+		opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
+		if (opcode & NES_CQE_VALID) {
+			cqp = &nesdev->cqp;
 
 			error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
 			if (error_code) {
@@ -3021,15 +3048,14 @@ static void nes_cqp_ce_handler(struct ne
 						le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
 						(u16)(error_code >> 16),
 						(u16)error_code);
-				nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
-						cqp->qp_id, cqp->sq_head, cqp->sq_tail);
 			}
 
-			u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
-			cqp_request = *((struct nes_cqp_request **)&u64temp);
+			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+					((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+
+			cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
 			if (cqp_request) {
 				if (cqp_request->waiting) {
 					/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
@@ -3075,9 +3101,15 @@ static void nes_cqp_ce_handler(struct ne
 		cqp_wqe = &nesdev->cqp.sq_vbase[head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
 		barrier();
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
+
+		opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
+		else
+			ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
+		cqp_wqe->wqe_words[ctx_index] =
 			cpu_to_le32((u32)((unsigned long)cqp_request));
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
+		cqp_wqe->wqe_words[ctx_index + 1] =
 			cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
 		nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
 				cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
@@ -3093,7 +3125,6 @@ static void nes_cqp_ce_handler(struct ne
 	nes_read32(nesdev->regs+NES_CQE_ALLOC);
 }
 
-
 static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
 {
 	if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
@@ -3553,9 +3584,9 @@ static void nes_process_iwarp_aeqe(struc
 
 	aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
 	if (aeq_info & NES_AEQE_QP) {
-		if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,
-				aeqe_cq_id)) ||
-				(atomic_read(&nesqp->close_timer_started)))
+		if (!nes_is_resource_allocated(nesadapter,
+				nesadapter->allocated_qps,
+				aeqe_cq_id))
 			return;
 	}
 
@@ -3566,8 +3597,7 @@ static void nes_process_iwarp_aeqe(struc
 
 			if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
 				if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
-					(nesqp->ibqp_state == IB_QPS_RTS) &&
-					((nesadapter->eeprom_version >> 16) != NES_A0)) {
+					(nesqp->ibqp_state == IB_QPS_RTS)) {
 					spin_lock_irqsave(&nesqp->lock, flags);
 					nesqp->hw_iwarp_state = iwarp_state;
 					nesqp->hw_tcp_state = tcp_state;
@@ -3594,9 +3624,10 @@ static void nes_process_iwarp_aeqe(struc
 				return;
 			}
 			spin_lock_irqsave(&nesqp->lock, flags);
-			nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+			nesqp->hw_iwarp_state = iwarp_state;
+			nesqp->hw_tcp_state = tcp_state;
+			nesqp->last_aeq = async_event_id;
 			spin_unlock_irqrestore(&nesqp->lock, flags);
-			nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
 			nes_cm_disconn(nesqp);
 			break;
 
@@ -3694,7 +3725,9 @@ static void nes_process_iwarp_aeqe(struc
 		case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
 			printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
 					nesqp->hwqp.qp_id, async_event_id);
-			nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
+			print_ip(nesqp->cm_node);
+			if (!atomic_read(&nesqp->close_timer_started))
+				nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
 			break;
 
 		case NES_AEQE_AEID_CQ_OPERATION_ERROR:
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_hw.h linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_hw.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_hw.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,11 @@
 #define NES_MULTICAST_PF_MAX 8
 #define NES_A0 3
 
+#define NES_ENABLE_PAU 0x07000001
+#define NES_DISABLE_PAU 0x07000000
+#define NES_PAU_COUNTER 10
+#define NES_CQP_OPCODE_MASK 0x3f
+
 enum pci_regs {
 	NES_INT_STAT = 0x0000,
 	NES_INT_MASK = 0x0004,
@@ -73,8 +78,10 @@ enum indexed_regs {
 	NES_IDX_QP_CONTROL = 0x0040,
 	NES_IDX_FLM_CONTROL = 0x0080,
 	NES_IDX_INT_CPU_STATUS = 0x00a0,
+	NES_IDX_GPR_TRIGGER = 0x00bc,
 	NES_IDX_GPIO_CONTROL = 0x00f0,
 	NES_IDX_GPIO_DATA = 0x00f4,
+	NES_IDX_GPR2 = 0x010c,
 	NES_IDX_TCP_CONFIG0 = 0x01e4,
 	NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
 	NES_IDX_TCP_NOW = 0x01f0,
@@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
 	NES_CQP_REGISTER_SHARED_STAG = 0x0c,
 	NES_CQP_DEALLOCATE_STAG = 0x0d,
 	NES_CQP_MANAGE_ARP_CACHE = 0x0f,
+	NES_CQP_DOWNLOAD_SEGMENT = 0x10,
 	NES_CQP_SUSPEND_QPS = 0x11,
 	NES_CQP_UPLOAD_CONTEXT = 0x13,
 	NES_CQP_CREATE_CEQ = 0x16,
@@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
 	NES_CQP_DESTROY_AEQ = 0x1b,
 	NES_CQP_LMI_ACCESS = 0x20,
 	NES_CQP_FLUSH_WQES = 0x22,
-	NES_CQP_MANAGE_APBVT = 0x23
+	NES_CQP_MANAGE_APBVT = 0x23,
+	NES_CQP_MANAGE_QUAD_HASH = 0x25
 };
 
 enum nes_cqp_wqe_word_idx {
@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
 	NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
 };
 
+enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
+	NES_CQP_WQE_DL_OPCODE_IDX = 0,
+	NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
+	NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
+	NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
+	/* For index values 4-15 use NES_NIC_SQ_WQE_ values */
+};
+
 enum nes_cqp_cq_wqeword_idx {
 	NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
 	NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
 	NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
 };
 
+#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
 #define NES_CQP_OP_IWARP_STATE_SHIFT 28
 #define NES_CQP_OP_TERMLEN_SHIFT     28
 
@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
 
 enum nes_nic_cqe_word_idx {
 	NES_NIC_CQE_ACCQP_ID_IDX = 0,
+	NES_NIC_CQE_HASH_RCVNXT = 1,
 	NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
 	NES_NIC_CQE_MISC_IDX = 3,
 };
@@ -1005,6 +1024,11 @@ struct nes_arp_entry {
 #define NES_NIC_CQ_DOWNWARD_TREND   16
 #define NES_PFT_SIZE		    48
 
+#define NES_MGT_WQ_COUNT 32
+#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
+#define NES_MGT_QP_OFFSET 36
+#define NES_MGT_QP_COUNT 4
+
 struct nes_hw_tune_timer {
     /* u16 cq_count; */
     u16 threshold_low;
@@ -1118,6 +1142,7 @@ struct nes_adapter {
 	u32 et_rate_sample_interval;
 	u32 timer_int_limit;
 	u32 wqm_quanta;
+	u8 allow_unaligned_fpdus;
 
 	/* Adapter base MAC address */
 	u32 mac_addr_low;
@@ -1251,6 +1276,14 @@ struct nes_vnic {
 	enum ib_event_type delayed_event;
 	enum ib_event_type last_dispatched_event;
 	spinlock_t port_ibevent_lock;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
+	struct task_struct *mgt_thread;
+	wait_queue_head_t mgt_wait_queue;
+	struct sk_buff_head mgt_skb_list;
+
 };
 
 struct nes_ib_device {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_mgt.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_mgt.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_mgt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_mgt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include "nes.h"
+#include "nes_mgt.h"
+
+atomic_t pau_qps_created;
+atomic_t pau_qps_destroyed;
+
+static void nes_replenish_mgt_rq(struct nes_vnic_mgt *mgtvnic)
+{
+	unsigned long flags;
+	dma_addr_t bus_address;
+	struct sk_buff *skb;
+	struct nes_hw_nic_rq_wqe *nic_rqe;
+	struct nes_hw_mgt *nesmgt;
+	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
+	u32 rx_wqes_posted = 0;
+
+	nesmgt = &mgtvnic->mgt;
+	nesdev = mgtvnic->nesvnic->nesdev;
+	spin_lock_irqsave(&nesmgt->rq_lock, flags);
+	if (nesmgt->replenishing_rq != 0) {
+		if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+		    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+			atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+			add_timer(&mgtvnic->rq_wqes_timer);
+		} else {
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+		}
+		return;
+	}
+	nesmgt->replenishing_rq = 1;
+	spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+	do {
+		skb = dev_alloc_skb(mgtvnic->nesvnic->max_frame_size);
+		if (skb) {
+			skb->dev = mgtvnic->nesvnic->netdev;
+
+			bus_address = pci_map_single(nesdev->pcidev,
+						     skb->data, mgtvnic->nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = mgtvnic->nesvnic->max_frame_size;
+
+			nic_rqe = &nesmgt->rq_vbase[mgtvnic->mgt.rq_head];
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
+				cpu_to_le32(mgtvnic->nesvnic->max_frame_size);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
+				cpu_to_le32((u32)bus_address);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
+				cpu_to_le32((u32)((u64)bus_address >> 32));
+			nesmgt->rx_skb[nesmgt->rq_head] = skb;
+			nesmgt->rq_head++;
+			nesmgt->rq_head &= nesmgt->rq_size - 1;
+			atomic_dec(&mgtvnic->rx_skbs_needed);
+			barrier();
+			if (++rx_wqes_posted == 255) {
+				nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+				rx_wqes_posted = 0;
+			}
+		} else {
+			spin_lock_irqsave(&nesmgt->rq_lock, flags);
+			if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+			    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+				atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+				mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+				add_timer(&mgtvnic->rq_wqes_timer);
+			} else {
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			}
+			break;
+		}
+	} while (atomic_read(&mgtvnic->rx_skbs_needed));
+	barrier();
+	if (rx_wqes_posted)
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+	nesmgt->replenishing_rq = 0;
+}
+
+/**
+ * nes_mgt_rq_wqes_timeout
+ */
+static void nes_mgt_rq_wqes_timeout(unsigned long parm)
+{
+	struct nes_vnic_mgt *mgtvnic = (struct nes_vnic_mgt *)parm;
+
+	atomic_set(&mgtvnic->rx_skb_timer_running, 0);
+	if (atomic_read(&mgtvnic->rx_skbs_needed))
+		nes_replenish_mgt_rq(mgtvnic);
+}
+
+/**
+ * nes_mgt_free_skb - unmap and free skb
+ */
+static void nes_mgt_free_skb(struct nes_device *nesdev, struct sk_buff *skb, u32 dir)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, dir);
+	cb->busaddr = 0;
+	dev_kfree_skb_any(skb);
+}
+
+/**
+ * nes_download_callback - handle download completions
+ */
+static void nes_download_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_fpdu_info *fpdu_info = cqp_request->cqp_callback_pointer;
+	struct nes_qp *nesqp = fpdu_info->nesqp;
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 0; i < fpdu_info->frag_cnt; i++) {
+		skb = fpdu_info->frags[i].skb;
+		if (fpdu_info->frags[i].cmplt) {
+			nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+			nes_rem_ref_cm_node(nesqp->cm_node);
+		}
+	}
+
+	if (fpdu_info->hdr_vbase)
+		pci_free_consistent(nesdev->pcidev, fpdu_info->hdr_len,
+				    fpdu_info->hdr_vbase, fpdu_info->hdr_pbase);
+	kfree(fpdu_info);
+}
+
+/**
+ * nes_get_seq - Get the seq, ack_seq and window from the packet
+ */
+static u32 nes_get_seq(struct sk_buff *skb, u32 *ack, u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	struct nes_rskb_cb *cb = (struct nes_rskb_cb *)&skb->cb[0];
+	struct iphdr *iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	struct tcphdr *tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+
+	*ack = be32_to_cpu(tcph->ack_seq);
+	*wnd = be16_to_cpu(tcph->window);
+	*fin_rcvd = tcph->fin;
+	*rst_rcvd = tcph->rst;
+	return be32_to_cpu(tcph->seq);
+}
+
+/**
+ * nes_get_next_skb - Get the next skb based on where current skb is in the queue
+ */
+static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp *nesqp,
+					struct sk_buff *skb, u32 nextseq, u32 *ack,
+					u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	u32 seq;
+	bool processacks;
+	struct sk_buff *old_skb;
+
+	if (skb) {
+		/* Continue processing fpdu */
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+		skb = skb->next;
+		processacks = false;
+	} else {
+		/* Starting a new one */
+		if (skb_queue_empty(&nesqp->pau_list))
+			goto out;
+		skb = skb_peek(&nesqp->pau_list);
+		processacks = true;
+	}
+
+	while (1) {
+		seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
+		if (seq == nextseq) {
+			if (skb->len || processacks)
+				break;
+		} else if (after(seq, nextseq)) {
+			goto out;
+		}
+
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+
+		old_skb = skb;
+		skb = skb->next;
+		skb_unlink(old_skb, &nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	return skb;
+
+out:
+	return NULL;
+}
+
+/**
+ * get_fpdu_info - Find the next complete fpdu and return its fragments.
+ */
+static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
+			 struct pau_fpdu_info **pau_fpdu_info)
+{
+	struct sk_buff *skb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct nes_rskb_cb *cb;
+	struct pau_fpdu_info *fpdu_info = NULL;
+	struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
+	unsigned long flags;
+	u32 fpdu_len = 0;
+	u32 tmp_len;
+	int frag_cnt = 0;
+	u32 tot_len;
+	u32 frag_tot;
+	u32 ack;
+	u32 fin_rcvd;
+	u32 rst_rcvd;
+	u16 wnd;
+	int i;
+	int rc = 0;
+
+	*pau_fpdu_info = NULL;
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+	if (!skb) {
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		goto out;
+	}
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	if (skb->len) {
+		fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
+		fpdu_len = (fpdu_len + 3) & 0xfffffffc;
+		tmp_len = fpdu_len;
+
+		/* See if we have all of the fpdu */
+		frag_tot = 0;
+		memset(&frags, 0, sizeof frags);
+		for (i = 0; i < MAX_FPDU_FRAGS; i++) {
+			frags[i].physaddr = cb->busaddr;
+			frags[i].physaddr += skb->data - cb->data_start;
+			frags[i].frag_len = min(tmp_len, skb->len);
+			frags[i].skb = skb;
+			frags[i].cmplt = (skb->len == frags[i].frag_len);
+			frag_tot += frags[i].frag_len;
+			frag_cnt++;
+
+			tmp_len -= frags[i].frag_len;
+			if (tmp_len == 0)
+				break;
+
+			skb = nes_get_next_skb(nesdev, nesqp, skb,
+					       nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+			if (!skb) {
+				spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+				goto out;
+			} else if (rst_rcvd) {
+				/* rst received in the middle of fpdu */
+				for (; i >= 0; i--) {
+					skb_unlink(frags[i].skb, &nesqp->pau_list);
+					nes_mgt_free_skb(nesdev, frags[i].skb, PCI_DMA_TODEVICE);
+				}
+				cb = (struct nes_rskb_cb *)&skb->cb[0];
+				frags[0].physaddr = cb->busaddr;
+				frags[0].physaddr += skb->data - cb->data_start;
+				frags[0].frag_len = skb->len;
+				frags[0].skb = skb;
+				frags[0].cmplt = true;
+				frag_cnt = 1;
+				break;
+			}
+
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+		}
+	} else {
+		/* no data */
+		frags[0].physaddr = cb->busaddr;
+		frags[0].frag_len = 0;
+		frags[0].skb = skb;
+		frags[0].cmplt = true;
+		frag_cnt = 1;
+	}
+
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	/* Found one */
+	fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
+	if (fpdu_info == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to alloc a fpdu_info.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	fpdu_info->cqp_request = nes_get_cqp_request(nesdev);
+	if (fpdu_info->cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cb = (struct nes_rskb_cb *)&frags[0].skb->cb[0];
+	iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	fpdu_info->hdr_len = (((unsigned char *)tcph) + 4 * (tcph->doff)) - cb->data_start;
+	fpdu_info->data_len = fpdu_len;
+	tot_len = fpdu_info->hdr_len + fpdu_len - ETH_HLEN;
+
+	if (frags[0].cmplt) {
+		fpdu_info->hdr_pbase = cb->busaddr;
+		fpdu_info->hdr_vbase = NULL;
+	} else {
+		fpdu_info->hdr_vbase = pci_alloc_consistent(nesdev->pcidev,
+							    fpdu_info->hdr_len, &fpdu_info->hdr_pbase);
+		if (!fpdu_info->hdr_vbase) {
+			nes_debug(NES_DBG_PAU, "Unable to allocate memory for pau first frag\n");
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		/* Copy hdrs, adjusting len and seqnum */
+		memcpy(fpdu_info->hdr_vbase, cb->data_start, fpdu_info->hdr_len);
+		iph = (struct iphdr *)(fpdu_info->hdr_vbase + ETH_HLEN);
+		tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	}
+
+	iph->tot_len = cpu_to_be16(tot_len);
+	iph->saddr = cpu_to_be32(0x7f000001);
+
+	tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+	tcph->ack_seq = cpu_to_be32(ack);
+	tcph->window = cpu_to_be16(wnd);
+
+	nesqp->pau_rcv_nxt += fpdu_len + fin_rcvd;
+
+	memcpy(fpdu_info->frags, frags, sizeof(fpdu_info->frags));
+	fpdu_info->frag_cnt = frag_cnt;
+	fpdu_info->nesqp = nesqp;
+	*pau_fpdu_info = fpdu_info;
+
+	/* Update skb's for next pass */
+	for (i = 0; i < frag_cnt; i++) {
+		cb = (struct nes_rskb_cb *)&frags[i].skb->cb[0];
+		skb_pull(frags[i].skb, frags[i].frag_len);
+
+		if (frags[i].skb->len == 0) {
+			/* Pull skb off the list - it will be freed in the callback */
+			spin_lock_irqsave(&nesqp->pau_lock, flags);
+			skb_unlink(frags[i].skb, &nesqp->pau_list);
+			spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		} else {
+			/* Last skb still has data so update the seq */
+			iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+			tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+			tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+		}
+	}
+
+out:
+	if (rc) {
+		if (fpdu_info) {
+			if (fpdu_info->cqp_request)
+				nes_put_cqp_request(nesdev, fpdu_info->cqp_request);
+			kfree(fpdu_info);
+		}
+	}
+	return rc;
+}
+
+/**
+ * forward_fpdu - send complete fpdus, one at a time
+ */
+static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct pau_fpdu_info *fpdu_info;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_cqp_request *cqp_request;
+	u64 u64tmp;
+	u32 u32tmp;
+	int rc;
+
+	while (1) {
+		rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
+		if (fpdu_info == NULL)
+			return rc;
+
+		cqp_request = fpdu_info->cqp_request;
+		cqp_wqe = &cqp_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_OPCODE_IDX,
+				    NES_CQP_DOWNLOAD_SEGMENT |
+				    (((u32)nesvnic->logical_port) << NES_CQP_OP_LOGICAL_PORT_SHIFT));
+
+		u32tmp = fpdu_info->hdr_len << 16;
+		u32tmp |= fpdu_info->hdr_len + (u32)fpdu_info->data_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[1].frag_len << 16) | fpdu_info->frags[0].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_2_1_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[3].frag_len << 16) | fpdu_info->frags[2].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_4_3_IDX,
+				    u32tmp);
+
+		u64tmp = (u64)fpdu_info->hdr_pbase;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
+				    lower_32_bits(u64tmp));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
+				    upper_32_bits(u64tmp >> 32));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[0].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[0].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[1].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[1].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[2].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[2].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[3].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[3].physaddr));
+
+		cqp_request->cqp_callback_pointer = fpdu_info;
+		cqp_request->callback = 1;
+		cqp_request->cqp_callback = nes_download_callback;
+
+		atomic_set(&cqp_request->refcount, 1);
+		nes_post_cqp_request(nesdev, cqp_request);
+	}
+
+	return 0;
+}
+
+static void process_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	int again = 1;
+	unsigned long flags;
+
+	do {
+		/* Ignore rc - if it failed, tcp retries will cause it to try again */
+		forward_fpdus(nesvnic, nesqp);
+
+		spin_lock_irqsave(&nesqp->pau_lock, flags);
+		if (nesqp->pau_pending) {
+			nesqp->pau_pending = 0;
+		} else {
+			nesqp->pau_busy = 0;
+			again = 0;
+		}
+
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+	} while (again);
+}
+
+/**
+ * queue_fpdus - Handle fpdu's that hw passed up to sw
+ */
+static void queue_fpdus(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct sk_buff *tmpskb;
+	struct nes_rskb_cb *cb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	unsigned char *tcph_end;
+	u32 rcv_nxt;
+	u32 rcv_wnd;
+	u32 seqnum;
+	u32 len;
+	bool process_it = false;
+	unsigned long flags;
+
+	/* Move data ptr to after tcp header */
+	iph = (struct iphdr *)skb->data;
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	seqnum = be32_to_cpu(tcph->seq);
+	tcph_end = (((char *)tcph) + (4 * tcph->doff));
+
+	len = be16_to_cpu(iph->tot_len);
+	if (skb->len > len)
+		skb_trim(skb, len);
+	skb_pull(skb, tcph_end - skb->data);
+
+	/* Initialize tracking values */
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->seqnum = seqnum;
+
+	/* Make sure data is in the receive window */
+	rcv_nxt = nesqp->pau_rcv_nxt;
+	rcv_wnd = le32_to_cpu(nesqp->nesqp_context->rcv_wnd);
+	if (!between(seqnum, rcv_nxt, (rcv_nxt + rcv_wnd))) {
+		nes_mgt_free_skb(nesvnic->nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+		return;
+	}
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+
+	if (nesqp->pau_busy)
+		nesqp->pau_pending = 1;
+	else
+		nesqp->pau_busy = 1;
+
+	/* Queue skb by sequence number */
+	if (skb_queue_len(&nesqp->pau_list) == 0) {
+		skb_queue_head(&nesqp->pau_list, skb);
+	} else {
+		tmpskb = nesqp->pau_list.next;
+		while (tmpskb != (struct sk_buff *)&nesqp->pau_list) {
+			cb = (struct nes_rskb_cb *)&tmpskb->cb[0];
+			if (before(seqnum, cb->seqnum))
+				break;
+			tmpskb = tmpskb->next;
+		}
+		skb_insert(tmpskb, skb, &nesqp->pau_list);
+	}
+	if (nesqp->pau_state == PAU_READY)
+		process_it = true;
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	if (process_it)
+		process_fpdus(nesvnic, nesqp);
+
+	return;
+}
+
+/**
+ * mgt_thread - Handle mgt skbs in a safe context
+ */
+static int mgt_thread(void *context)
+{
+	struct nes_vnic *nesvnic = context;
+	struct sk_buff *skb;
+	struct nes_rskb_cb *cb;
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(nesvnic->mgt_wait_queue,
+					 skb_queue_len(&nesvnic->mgt_skb_list) || kthread_should_stop());
+		while ((skb_queue_len(&nesvnic->mgt_skb_list)) && !kthread_should_stop()) {
+			skb = skb_dequeue(&nesvnic->mgt_skb_list);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->data_start = skb->data - ETH_HLEN;
+			cb->busaddr = pci_map_single(nesvnic->nesdev->pcidev, cb->data_start,
+						     nesvnic->max_frame_size, PCI_DMA_TODEVICE);
+			queue_fpdus(skb, nesvnic, cb->nesqp);
+		}
+	}
+
+	/* Closing down so delete any entries on the queue */
+	while (skb_queue_len(&nesvnic->mgt_skb_list)) {
+		skb = skb_dequeue(&nesvnic->mgt_skb_list);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		nes_rem_ref_cm_node(cb->nesqp->cm_node);
+		dev_kfree_skb_any(skb);
+	}
+	return 0;
+}
+
+/**
+ * nes_queue_skbs - Queue skb so it can be handled in a thread context
+ */
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->nesqp = nesqp;
+	skb_queue_tail(&nesvnic->mgt_skb_list, skb);
+	wake_up_interruptible(&nesvnic->mgt_wait_queue);
+}
+
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	atomic_inc(&pau_qps_destroyed);
+
+	/* Free packets that have not yet been forwarded */
+	/* Lock is acquired by skb_dequeue when removing the skb */
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	while (skb_queue_len(&nesqp->pau_list)) {
+		skb = skb_dequeue(&nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+}
+
+static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_qh_chg *qh_chg = cqp_request->cqp_callback_pointer;
+	struct nes_cqp_request *new_request;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_adapter *nesadapter;
+	struct nes_qp *nesqp;
+	struct nes_v4_quad nes_quad;
+	u32 crc_value;
+	u64 u64temp;
+
+	nesadapter = nesdev->nesadapter;
+	nesqp = qh_chg->nesqp;
+
+	/* Should we handle the bad completion */
+	if (cqp_request->major_code) {
+		printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+		       cqp_request->major_code);
+		WARN_ON(1);
+	}
+
+	switch (nesqp->pau_state) {
+	case PAU_DEL_QH:
+		/* Old hash code deleted, now set the new one */
+		nesqp->pau_state = PAU_ADD_LB_QH;
+		new_request = nes_get_cqp_request(nesdev);
+		if (new_request == NULL) {
+			nes_debug(NES_DBG_PAU, "Failed to get a new_request.\n");
+			WARN_ON(1);
+			return;
+		}
+
+		memset(&nes_quad, 0, sizeof(nes_quad));
+		nes_quad.DstIpAdrIndex =
+			cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+		nes_quad.SrcIpadr = cpu_to_be32(0x7f000001);
+		nes_quad.TcpPorts[0] = swab16(nesqp->nesqp_context->tcpPorts[1]);
+		nes_quad.TcpPorts[1] = swab16(nesqp->nesqp_context->tcpPorts[0]);
+
+		/* Produce hash key */
+		crc_value = get_crc_value(&nes_quad);
+		nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
+		nes_debug(NES_DBG_PAU, "new HTE Index = 0x%08X, CRC = 0x%08X\n",
+			  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+
+		nesqp->hte_index &= nesadapter->hte_index_mask;
+		nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
+		nesqp->nesqp_context->ip0 = cpu_to_le32(0x7f000001);
+		nesqp->nesqp_context->rcv_nxt = cpu_to_le32(nesqp->pau_rcv_nxt);
+
+		cqp_wqe = &new_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words,
+				    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH |
+				    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+		u64temp = (u64)nesqp->nesqp_context_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		nes_debug(NES_DBG_PAU, "Waiting for CQP completion for adding the quad hash.\n");
+
+		new_request->cqp_callback_pointer = qh_chg;
+		new_request->callback = 1;
+		new_request->cqp_callback = nes_chg_qh_handler;
+		atomic_set(&new_request->refcount, 1);
+		nes_post_cqp_request(nesdev, new_request);
+		break;
+
+	case PAU_ADD_LB_QH:
+		/* Start processing the queued fpdu's */
+		nesqp->pau_state = PAU_READY;
+		process_fpdus(qh_chg->nesvnic, qh_chg->nesqp);
+		kfree(qh_chg);
+		break;
+	}
+}
+
+/**
+ * nes_change_quad_hash
+ */
+static int nes_change_quad_hash(struct nes_device *nesdev,
+				struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_cqp_request *cqp_request = NULL;
+	struct pau_qh_chg *qh_chg = NULL;
+	u64 u64temp;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	int ret = 0;
+
+	cqp_request = nes_get_cqp_request(nesdev);
+	if (cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+
+	qh_chg = kmalloc(sizeof *qh_chg, GFP_ATOMIC);
+	if (qh_chg == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+	qh_chg->nesdev = nesdev;
+	qh_chg->nesvnic = nesvnic;
+	qh_chg->nesqp = nesqp;
+	nesqp->pau_state = PAU_DEL_QH;
+
+	cqp_wqe = &cqp_request->cqp_wqe;
+	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+	set_wqe_32bit_value(cqp_wqe->wqe_words,
+			    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH | NES_CQP_QP_DEL_HTE |
+			    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+	u64temp = (u64)nesqp->nesqp_context_pbase;
+	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+	nes_debug(NES_DBG_PAU, "Waiting for CQP completion for deleting the quad hash.\n");
+
+	cqp_request->cqp_callback_pointer = qh_chg;
+	cqp_request->callback = 1;
+	cqp_request->cqp_callback = nes_chg_qh_handler;
+	atomic_set(&cqp_request->refcount, 1);
+	nes_post_cqp_request(nesdev, cqp_request);
+
+	return ret;
+
+chg_qh_err:
+	kfree(qh_chg);
+	if (cqp_request)
+		nes_put_cqp_request(nesdev, cqp_request);
+	return ret;
+}
+
+/**
+ * nes_mgt_ce_handler
+ * This management code deals with any packed and unaligned (pau) fpdu's
+ * that the hardware cannot handle.
+ */
+static void nes_mgt_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+{
+	struct nes_vnic_mgt *mgtvnic = container_of(cq, struct nes_vnic_mgt, mgt_cq);
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	u32 head;
+	u32 cq_size;
+	u32 cqe_count = 0;
+	u32 cqe_misc;
+	u32 qp_id = 0;
+	u32 skbs_needed;
+	unsigned long context;
+	struct nes_qp *nesqp;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
+
+	head = cq->cq_head;
+	cq_size = cq->cq_size;
+
+	while (1) {
+		cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
+		if (!(cqe_misc & NES_NIC_CQE_VALID))
+			break;
+
+		nesqp = NULL;
+		if (cqe_misc & NES_NIC_CQE_ACCQP_VALID) {
+			qp_id = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_ACCQP_ID_IDX]);
+			qp_id &= 0x001fffff;
+			if (qp_id < nesadapter->max_qp) {
+				context = (unsigned long)nesadapter->qp_table[qp_id - NES_FIRST_QPN];
+				nesqp = (struct nes_qp *)context;
+			}
+		}
+
+		if (nesqp) {
+			if (nesqp->pau_mode == false) {
+				nesqp->pau_mode = true; /* First time for this qp */
+				nesqp->pau_rcv_nxt = le32_to_cpu(
+					cq->cq_vbase[head].cqe_words[NES_NIC_CQE_HASH_RCVNXT]);
+				skb_queue_head_init(&nesqp->pau_list);
+				spin_lock_init(&nesqp->pau_lock);
+				atomic_inc(&pau_qps_created);
+				nes_change_quad_hash(nesdev, mgtvnic->nesvnic, nesqp);
+			}
+
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			rx_skb->len = 0;
+			skb_put(rx_skb, cqe_misc & 0x0000ffff);
+			rx_skb->protocol = eth_type_trans(rx_skb, mgtvnic->nesvnic->netdev);
+			cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+			pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, PCI_DMA_FROMDEVICE);
+			cb->busaddr = 0;
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= mgtvnic->mgt.rq_size - 1;
+
+			nes_add_ref_cm_node(nesqp->cm_node);
+			nes_queue_mgt_skbs(rx_skb, mgtvnic->nesvnic, nesqp);
+		} else {
+			printk(KERN_ERR PFX "Invalid QP %d for packed/unaligned handling\n", qp_id);
+		}
+
+		cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
+		cqe_count++;
+		if (++head >= cq_size)
+			head = 0;
+
+		if (cqe_count == 255) {
+			/* Replenish mgt CQ */
+			nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (cqe_count << 16));
+			nesdev->currcq_count += cqe_count;
+			cqe_count = 0;
+		}
+
+		skbs_needed = atomic_inc_return(&mgtvnic->rx_skbs_needed);
+		if (skbs_needed > (mgtvnic->mgt.rq_size >> 1))
+			nes_replenish_mgt_rq(mgtvnic);
+	}
+
+	cq->cq_head = head;
+	nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+		    cq->cq_number | (cqe_count << 16));
+	nes_read32(nesdev->regs + NES_CQE_ALLOC);
+	nesdev->currcq_count += cqe_count;
+}
+
+/**
+ * nes_init_mgt_qp
+ */
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic)
+{
+	struct nes_vnic_mgt *mgtvnic;
+	u32 counter;
+	void *vmem;
+	dma_addr_t pmem;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	unsigned long flags;
+	struct nes_hw_nic_qp_context *mgt_context;
+	u64 u64temp;
+	struct nes_hw_nic_rq_wqe *mgt_rqe;
+	struct sk_buff *skb;
+	u32 wqe_count;
+	struct nes_rskb_cb *cb;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	int i;
+	int ret;
+
+	/* Allocate space the all mgt QPs once */
+	mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL);
+	if (mgtvnic == NULL) {
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt structure\n");
+		return -ENOMEM;
+	}
+
+	/* Allocate fragment, RQ, and CQ; Reuse CEQ based on the PCI function */
+	/* We are not sending from this NIC so sq is not allocated */
+	mgt_mem_size = 256 +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe)) +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_cqe)) +
+		       sizeof(struct nes_hw_nic_qp_context);
+	mgt_mem_size = (mgt_mem_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+	mgt_vbase = pci_alloc_consistent(nesdev->pcidev, NES_MGT_QP_COUNT * mgt_mem_size, &mgt_pbase);
+	if (!mgt_vbase) {
+		kfree(mgtvnic);
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt host descriptor rings\n");
+		return -ENOMEM;
+	}
+
+	nesvnic->mgt_mem_size = NES_MGT_QP_COUNT * mgt_mem_size;
+	nesvnic->mgt_vbase = mgt_vbase;
+	nesvnic->mgt_pbase = mgt_pbase;
+
+	skb_queue_head_init(&nesvnic->mgt_skb_list);
+	init_waitqueue_head(&nesvnic->mgt_wait_queue);
+	nesvnic->mgt_thread = kthread_run(mgt_thread, nesvnic, "nes_mgt_thread");
+
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic->nesvnic = nesvnic;
+		mgtvnic->mgt.qp_id = nesdev->mac_index + NES_MGT_QP_OFFSET + i;
+		memset(mgt_vbase, 0, mgt_mem_size);
+		nes_debug(NES_DBG_INIT, "Allocated mgt QP structures at %p (phys = %016lX), size = %u.\n",
+			  mgt_vbase, (unsigned long)mgt_pbase, mgt_mem_size);
+
+		vmem = (void *)(((unsigned long)mgt_vbase + (256 - 1)) &
+				~(unsigned long)(256 - 1));
+		pmem = (dma_addr_t)(((unsigned long long)mgt_pbase + (256 - 1)) &
+				    ~(unsigned long long)(256 - 1));
+
+		spin_lock_init(&mgtvnic->mgt.rq_lock);
+
+		/* setup the RQ */
+		mgtvnic->mgt.rq_vbase = vmem;
+		mgtvnic->mgt.rq_pbase = pmem;
+		mgtvnic->mgt.rq_head = 0;
+		mgtvnic->mgt.rq_tail = 0;
+		mgtvnic->mgt.rq_size = NES_MGT_WQ_COUNT;
+
+		/* setup the CQ */
+		vmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+		pmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+
+		mgtvnic->mgt_cq.cq_number = mgtvnic->mgt.qp_id;
+		mgtvnic->mgt_cq.cq_vbase = vmem;
+		mgtvnic->mgt_cq.cq_pbase = pmem;
+		mgtvnic->mgt_cq.cq_head = 0;
+		mgtvnic->mgt_cq.cq_size = NES_MGT_WQ_COUNT;
+
+		mgtvnic->mgt_cq.ce_handler = nes_mgt_ce_handler;
+
+		/* Send CreateCQ request to CQP */
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+		cqp_head = nesdev->cqp.sq_head;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
+			NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
+			((u32)mgtvnic->mgt_cq.cq_size << 16));
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
+			mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16));
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
+		u64temp = (unsigned long)&mgtvnic->mgt_cq;
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
+			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		/* Send CreateQP request to CQP */
+		mgt_context = (void *)(&mgtvnic->mgt_cq.cq_vbase[mgtvnic->mgt_cq.cq_size]);
+		mgt_context->context_words[NES_NIC_CTX_MISC_IDX] =
+			cpu_to_le32((u32)NES_MGT_CTX_SIZE |
+				    ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
+		nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
+		if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0)
+			mgt_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
+
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
+									 NES_CQP_QP_TYPE_NIC);
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(mgtvnic->mgt.qp_id);
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase +
+			  (mgtvnic->mgt_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		nesdev->cqp.sq_head = cqp_head;
+
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_INIT, "Waiting for create MGT QP%u to complete.\n",
+			  mgtvnic->mgt.qp_id);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+		nes_debug(NES_DBG_INIT, "Create MGT QP%u completed, wait_event_timeout ret = %u.\n",
+			  mgtvnic->mgt.qp_id, ret);
+		if (!ret) {
+			nes_debug(NES_DBG_INIT, "MGT QP%u create timeout expired\n", mgtvnic->mgt.qp_id);
+			if (i == 0) {
+				pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+						    nesvnic->mgt_pbase);
+				kfree(mgtvnic);
+			} else {
+				nes_destroy_mgt(nesvnic);
+			}
+			return -EIO;
+		}
+
+		/* Populate the RQ */
+		for (counter = 0; counter < (NES_MGT_WQ_COUNT - 1); counter++) {
+			skb = dev_alloc_skb(nesvnic->max_frame_size);
+			if (!skb) {
+				nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
+				return -ENOMEM;
+			}
+
+			skb->dev = netdev;
+
+			pmem = pci_map_single(nesdev->pcidev, skb->data,
+					      nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = pmem;
+			cb->maplen = nesvnic->max_frame_size;
+
+			mgt_rqe = &mgtvnic->mgt.rq_vbase[counter];
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32((u32)nesvnic->max_frame_size);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
+			mgtvnic->mgt.rx_skb[counter] = skb;
+		}
+
+		init_timer(&mgtvnic->rq_wqes_timer);
+		mgtvnic->rq_wqes_timer.function = nes_mgt_rq_wqes_timeout;
+		mgtvnic->rq_wqes_timer.data = (unsigned long)mgtvnic;
+
+		wqe_count = NES_MGT_WQ_COUNT - 1;
+		mgtvnic->mgt.rq_head = wqe_count;
+		barrier();
+		do {
+			counter = min(wqe_count, ((u32)255));
+			wqe_count -= counter;
+			nes_write32(nesdev->regs + NES_WQE_ALLOC, (counter << 24) | mgtvnic->mgt.qp_id);
+		} while (wqe_count);
+
+		nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+			    mgtvnic->mgt_cq.cq_number);
+		nes_read32(nesdev->regs + NES_CQE_ALLOC);
+
+		mgt_vbase += mgt_mem_size;
+		mgt_pbase += mgt_mem_size;
+		nesvnic->mgtvnic[i] = mgtvnic++;
+	}
+	return 0;
+}
+
+
+void nes_destroy_mgt(struct nes_vnic *nesvnic)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct nes_vnic_mgt *mgtvnic;
+	struct nes_vnic_mgt *first_mgtvnic;
+	unsigned long flags;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	struct sk_buff *rx_skb;
+	int i;
+	int ret;
+
+	kthread_stop(nesvnic->mgt_thread);
+
+	/* Free remaining NIC receive buffers */
+	first_mgtvnic = nesvnic->mgtvnic[0];
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic = nesvnic->mgtvnic[i];
+		if (mgtvnic == NULL)
+			continue;
+
+		while (mgtvnic->mgt.rq_head != mgtvnic->mgt.rq_tail) {
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			nes_mgt_free_skb(nesdev, rx_skb, PCI_DMA_FROMDEVICE);
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= (mgtvnic->mgt.rq_size - 1);
+		}
+
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+
+		/* Destroy NIC QP */
+		cqp_head = nesdev->cqp.sq_head;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    mgtvnic->mgt.qp_id);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+
+		/* Destroy NIC CQ */
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_CQ | ((u32)mgtvnic->mgt_cq.cq_size << 16)));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    (mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		nesdev->cqp.sq_head = cqp_head;
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
+			  " cqp.sq_tail=%u, cqp.sq_size=%u\n",
+			  cqp_head, nesdev->cqp.sq_head,
+			  nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+
+		nes_debug(NES_DBG_SHUTDOWN, "Destroy MGT QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
+			  " cqp.sq_head=%u, cqp.sq_tail=%u\n",
+			  ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
+		if (!ret)
+			nes_debug(NES_DBG_SHUTDOWN, "MGT QP%u destroy timeout expired\n",
+				  mgtvnic->mgt.qp_id);
+
+		nesvnic->mgtvnic[i] = NULL;
+	}
+
+	if (nesvnic->mgt_vbase) {
+		pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+				    nesvnic->mgt_pbase);
+		nesvnic->mgt_vbase = NULL;
+		nesvnic->mgt_pbase = 0;
+	}
+
+	kfree(first_mgtvnic);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_mgt.h linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_mgt.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_mgt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_mgt.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved.
+*
+* This software is available to you under a choice of one of two
+* licenses.  You may choose to be licensed under the terms of the GNU
+* General Public License (GPL) Version 2, available from the file
+* COPYING in the main directory of this source tree, or the
+* OpenIB.org BSD license below:
+*
+*     Redistribution and use in source and binary forms, with or
+*     without modification, are permitted provided that the following
+*     conditions are met:
+*
+*      - Redistributions of source code must retain the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer.
+*
+*      - Redistributions in binary form must reproduce the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer in the documentation and/or other materials
+*        provided with the distribution.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+#ifndef __NES_MGT_H
+#define __NES_MGT_H
+
+#define MPA_FRAMING 6	/* length is 2 bytes, crc is 4 bytes */
+
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
+void nes_destroy_mgt(struct nes_vnic *nesvnic);
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
+
+struct nes_hw_mgt {
+	struct nes_hw_nic_rq_wqe *rq_vbase;	/* virtual address of rq */
+	dma_addr_t rq_pbase;			/* PCI memory for host rings */
+	struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
+	u16 qp_id;
+	u16 sq_head;
+	u16 rq_head;
+	u16 rq_tail;
+	u16 rq_size;
+	u8 replenishing_rq;
+	u8 reserved;
+	spinlock_t rq_lock;
+};
+
+struct nes_vnic_mgt {
+	struct nes_vnic        *nesvnic;
+	struct nes_hw_mgt      mgt;
+	struct nes_hw_nic_cq   mgt_cq;
+	atomic_t               rx_skbs_needed;
+	struct timer_list      rq_wqes_timer;
+	atomic_t               rx_skb_timer_running;
+};
+
+#define MAX_FPDU_FRAGS 4
+struct pau_fpdu_frag {
+	struct sk_buff         *skb;
+	u64                    physaddr;
+	u32                    frag_len;
+	bool                   cmplt;
+};
+
+struct pau_fpdu_info {
+	struct nes_qp          *nesqp;
+	struct nes_cqp_request *cqp_request;
+	void                   *hdr_vbase;
+	dma_addr_t             hdr_pbase;
+	int                    hdr_len;
+	u16                    data_len;
+	u16                    frag_cnt;
+	struct pau_fpdu_frag   frags[MAX_FPDU_FRAGS];
+};
+
+enum pau_qh_state {
+	PAU_DEL_QH,
+	PAU_ADD_LB_QH,
+	PAU_READY
+};
+
+struct pau_qh_chg {
+	struct nes_device *nesdev;
+	struct nes_vnic *nesvnic;
+	struct nes_qp *nesqp;
+};
+
+#endif          /* __NES_MGT_H */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_nic.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_nic.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_nic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_nic.c	2012-01-04 18:55:44.000000000 -0500
@@ -441,13 +441,13 @@ static int nes_nic_send(struct sk_buff *
 		nesnic->tx_skb[nesnic->sq_head] = skb;
 		for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
 				skb_fragment_index++) {
-			bus_address = pci_map_page( nesdev->pcidev,
-					skb_shinfo(skb)->frags[skb_fragment_index].page,
-					skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
-					skb_shinfo(skb)->frags[skb_fragment_index].size,
-					PCI_DMA_TODEVICE);
+			skb_frag_t *frag =
+				&skb_shinfo(skb)->frags[skb_fragment_index];
+			bus_address = skb_frag_dma_map(&nesdev->pcidev->dev,
+						       frag, 0, skb_frag_size(frag),
+						       DMA_TO_DEVICE);
 			wqe_fragment_length[wqe_fragment_index] =
-					cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
+					cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[skb_fragment_index]));
 			set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
 				bus_address);
 			wqe_fragment_index++;
@@ -561,11 +561,12 @@ tso_sq_no_longer_full:
 			/* Map all the buffers */
 			for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
 					tso_frag_count++) {
-				tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
-						skb_shinfo(skb)->frags[tso_frag_count].page,
-						skb_shinfo(skb)->frags[tso_frag_count].page_offset,
-						skb_shinfo(skb)->frags[tso_frag_count].size,
-						PCI_DMA_TODEVICE);
+				skb_frag_t *frag =
+					&skb_shinfo(skb)->frags[tso_frag_count];
+				tso_bus_address[tso_frag_count] =
+					skb_frag_dma_map(&nesdev->pcidev->dev,
+							 frag, 0, skb_frag_size(frag),
+							 DMA_TO_DEVICE);
 			}
 
 			tso_frag_index = 0;
@@ -636,11 +637,11 @@ tso_sq_no_longer_full:
 				}
 				while (wqe_fragment_index < 5) {
 					wqe_fragment_length[wqe_fragment_index] =
-							cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
+							cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index]));
 					set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
 						(u64)tso_bus_address[tso_frag_index]);
 					wqe_fragment_index++;
-					tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
+					tso_wqe_length += skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index++]);
 					if (wqe_fragment_index < 5)
 						wqe_fragment_length[wqe_fragment_index] = 0;
 					if (tso_frag_index == tso_frag_count)
@@ -1090,6 +1091,8 @@ static const char nes_ethtool_stringset[
 	"LRO aggregated",
 	"LRO flushed",
 	"LRO no_desc",
+	"PAU CreateQPs",
+	"PAU DestroyQPs",
 };
 #define NES_ETHTOOL_STAT_COUNT  ARRAY_SIZE(nes_ethtool_stringset)
 
@@ -1305,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
+	target_stat_values[++index] = atomic_read(&pau_qps_created);
+	target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
 }
 
 /**
@@ -1638,7 +1643,7 @@ static const struct net_device_ops nes_n
 	.ndo_get_stats		= nes_netdev_get_stats,
 	.ndo_tx_timeout		= nes_netdev_tx_timeout,
 	.ndo_set_mac_address	= nes_netdev_set_mac_address,
-	.ndo_set_multicast_list = nes_netdev_set_multicast_list,
+	.ndo_set_rx_mode	= nes_netdev_set_multicast_list,
 	.ndo_change_mtu		= nes_netdev_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_fix_features	= nes_fix_features,
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_utils.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_utils.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_utils.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_utils.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,13 +51,34 @@
 
 #include "nes.h"
 
-
-
 static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
 
 u32 mh_detected;
 u32 mh_pauses_sent;
 
+u32 nes_set_pau(struct nes_device *nesdev)
+{
+	u32 ret = 0;
+	u32 counter;
+
+	nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
+	nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+
+	for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
+		udelay(30);
+		if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
+			printk(KERN_INFO PFX "PAU is supported.\n");
+			break;
+		}
+		nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+	}
+	if (counter == NES_PAU_COUNTER) {
+		printk(KERN_INFO PFX "PAU is not supported.\n");
+		return -EPERM;
+	}
+	return ret;
+}
+
 /**
  * nes_read_eeprom_values -
  */
@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_de
 		if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
 			nesadapter->send_term_ok = 1;
 
+		if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
+			if (!nes_set_pau(nesdev))
+				nesadapter->allow_unaligned_fpdus = 1;
+		}
+
 		nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8))  <<  16) +
 				(u32)((u8)eeprom_data);
 
@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_devi
 		nes_free_cqp_request(nesdev, cqp_request);
 }
 
+
 /**
  * nes_post_cqp_request
  */
@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_dev
 	unsigned long flags;
 	u32 cqp_head;
 	u64 u64temp;
+	u32 opcode;
+	int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
 
 	spin_lock_irqsave(&nesdev->cqp.lock, flags);
 
@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_dev
 		nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
 		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
+		opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
 		barrier();
 		u64temp = (unsigned long)cqp_request;
-		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
-				    u64temp);
+		set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
 		nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
-				" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
-				" waiting = %d, refcount = %d.\n",
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
-				nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
-				cqp_request->waiting, atomic_read(&cqp_request->refcount));
+			" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
+			" waiting = %d, refcount = %d.\n",
+			opcode & NES_CQP_OPCODE_MASK,
+			le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
+			nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
+			cqp_request->waiting, atomic_read(&cqp_request->refcount));
+
 		barrier();
 
 		/* Ring doorbell (1 WQEs) */
@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_dev
 	return;
 }
 
-
 /**
  * nes_arp_table
  */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	int ret;
+	int ret = 0;
 
 	atomic_inc(&sw_qps_destroyed);
 	nesqp->destroyed = 1;
@@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *
 		if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
 			nes_clean_cq(nesqp, nesqp->nesrcq);
 	}
-
 	nes_rem_ref(&nesqp->ibqp);
 	return 0;
 }
@@ -2338,8 +2337,10 @@ static struct ib_mr *nes_reg_user_mr(str
 
 	skip_pages = ((u32)region->offset) >> 12;
 
-	if (ib_copy_from_udata(&req, udata, sizeof(req)))
+	if (ib_copy_from_udata(&req, udata, sizeof(req))) {
+		ib_umem_release(region);
 		return ERR_PTR(-EFAULT);
+	}
 	nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
 
 	switch (req.reg_type) {
@@ -2631,6 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(str
 			return &nesmr->ibmr;
 	}
 
+	ib_umem_release(region);
 	return ERR_PTR(-ENOSYS);
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_verbs.h linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_verbs.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/nes/nes_verbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/nes/nes_verbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,8 @@ struct nes_qp {
 	struct nes_cq         *nesrcq;
 	struct nes_pd         *nespd;
 	void *cm_node; /* handle of the node this QP is associated with */
-	struct ietf_mpa_frame *ietf_frame;
+	void                  *ietf_frame;
+	u8                    ietf_frame_size;
 	dma_addr_t            ietf_frame_pbase;
 	struct ib_mr          *lsmm_mr;
 	struct nes_hw_qp      hwqp;
@@ -154,6 +155,7 @@ struct nes_qp {
 	u32                   mmap_sq_db_index;
 	u32                   mmap_rq_db_index;
 	spinlock_t            lock;
+	spinlock_t            pau_lock;
 	struct nes_qp_context *nesqp_context;
 	dma_addr_t            nesqp_context_pbase;
 	void	              *pbl_vbase;
@@ -161,6 +163,8 @@ struct nes_qp {
 	struct page           *page;
 	struct timer_list     terminate_timer;
 	enum ib_event_type    terminate_eventtype;
+	struct sk_buff_head   pau_list;
+	u32                   pau_rcv_nxt;
 	u16                   active_conn:1;
 	u16                   skip_lsmm:1;
 	u16                   user_mode:1;
@@ -168,7 +172,8 @@ struct nes_qp {
 	u16                   flush_issued:1;
 	u16                   destroyed:1;
 	u16                   sig_all:1;
-	u16                   rsvd:9;
+	u16                   pau_mode:1;
+	u16                   rsvd:8;
 	u16                   private_data_len;
 	u16                   term_sq_flush_code;
 	u16                   term_rq_flush_code;
@@ -176,5 +181,8 @@ struct nes_qp {
 	u8                    hw_tcp_state;
 	u8                    term_flags;
 	u8                    sq_kmapped;
+	u8                    pau_busy;
+	u8                    pau_pending;
+	u8                    pau_state;
 };
 #endif			/* NES_VERBS_H */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_diag.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_diag.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_driver.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_driver.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/module.h>
 
 #include "qib.h"
 
@@ -279,10 +280,10 @@ bail:
  */
 static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
 {
-	const u32 chunk = etail / rcd->rcvegrbufs_perchunk;
-	const u32 idx =  etail % rcd->rcvegrbufs_perchunk;
+	const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
+	const u32 idx =  etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
 
-	return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize;
+	return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
 }
 
 /*
@@ -310,7 +311,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctx
 		u32 opcode;
 		u32 psn;
 		int diff;
-		unsigned long flags;
 
 		/* Sanity check packet */
 		if (tlen < 24)
@@ -365,7 +365,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctx
 
 			switch (qp->ibqp.qp_type) {
 			case IB_QPT_RC:
-				spin_lock_irqsave(&qp->s_lock, flags);
 				ruc_res =
 					qib_ruc_check_hdr(
 						ibp, hdr,
@@ -373,11 +372,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctx
 						qp,
 						be32_to_cpu(ohdr->bth[0]));
 				if (ruc_res) {
-					spin_unlock_irqrestore(&qp->s_lock,
-							       flags);
 					goto unlock;
 				}
-				spin_unlock_irqrestore(&qp->s_lock, flags);
 
 				/* Only deal with RDMA Writes for now */
 				if (opcode <
@@ -547,6 +543,15 @@ move_along:
 			updegr = 0;
 		}
 	}
+	/*
+	 * Notify qib_destroy_qp() if it is waiting
+	 * for lookaside_qp to finish.
+	 */
+	if (rcd->lookaside_qp) {
+		if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
+			wake_up(&rcd->lookaside_qp->wait);
+		rcd->lookaside_qp = NULL;
+	}
 
 	rcd->head = l;
 	rcd->pkt_count += i;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <linux/jiffies.h>
 #include <asm/pgtable.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include "qib.h"
 #include "qib_common.h"
@@ -1284,6 +1285,7 @@ static int setup_ctxt(struct qib_pportda
 	strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
 	ctxt_fp(fp) = rcd;
 	qib_stats.sps_ctxts++;
+	dd->freectxts--;
 	ret = 0;
 	goto bail;
 
@@ -1792,6 +1794,7 @@ static int qib_close(struct inode *in, s
 		if (dd->pageshadow)
 			unlock_expected_tids(rcd);
 		qib_stats.sps_ctxts--;
+		dd->freectxts++;
 	}
 
 	mutex_unlock(&qib_mutex);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib.h linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib.h	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,9 @@ struct qib_ctxtdata {
 	/* how many alloc_pages() chunks in rcvegrbuf_pages */
 	u32 rcvegrbuf_chunks;
 	/* how many egrbufs per chunk */
-	u32 rcvegrbufs_perchunk;
+	u16 rcvegrbufs_perchunk;
+	/* ilog2 of above */
+	u16 rcvegrbufs_perchunk_shift;
 	/* order for rcvegrbuf_pages */
 	size_t rcvegrbuf_size;
 	/* rcvhdrq size (for freeing) */
@@ -221,6 +223,9 @@ struct qib_ctxtdata {
 	/* ctxt rcvhdrq head offset */
 	u32 head;
 	u32 pkt_count;
+	/* lookaside fields */
+	struct qib_qp *lookaside_qp;
+	u32 lookaside_qpn;
 	/* QPs waiting for context processing */
 	struct list_head qp_wait_list;
 };
@@ -807,6 +812,10 @@ struct qib_devdata {
 	 * supports, less gives more pio bufs/ctxt, etc.
 	 */
 	u32 cfgctxts;
+	/*
+	 * number of ctxts available for PSM open
+	 */
+	u32 freectxts;
 
 	/*
 	 * hint that we should update pioavailshadow before
@@ -936,7 +945,9 @@ struct qib_devdata {
 	/* chip address space used by 4k pio buffers */
 	u32 align4k;
 	/* size of each rcvegrbuffer */
-	u32 rcvegrbufsize;
+	u16 rcvegrbufsize;
+	/* log2 of above */
+	u16 rcvegrbufsize_shift;
 	/* localbus width (1, 2,4,8,16,32) from config space  */
 	u32 lbus_width;
 	/* localbus speed in MHz */
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c	2012-01-04 18:55:44.000000000 -0500
@@ -3273,6 +3273,8 @@ static int init_6120_variables(struct qi
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_6120_tidtemplate(dd);
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <rdma/ib_verbs.h>
 
@@ -4085,6 +4086,8 @@ static int qib_init_7220_variables(struc
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7220_tidtemplate(dd);
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
+#include <linux/module.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_smi.h>
 
@@ -2306,16 +2307,11 @@ static int qib_7322_bringup_serdes(struc
 		SYM_LSB(IBCCtrlA_0, MaxPktLen);
 	ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
 
-	/* initially come up waiting for TS1, without sending anything. */
-	val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
-		QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
-
 	/*
 	 * Reset the PCS interface to the serdes (and also ibc, which is still
 	 * in reset from above).  Writes new value of ibcctrl_a as last step.
 	 */
 	qib_7322_mini_pcs_reset(ppd);
-	qib_write_kreg(dd, kr_scratch, 0ULL);
 
 	if (!ppd->cpspec->ibcctrl_b) {
 		unsigned lse = ppd->link_speed_enabled;
@@ -2381,17 +2377,20 @@ static int qib_7322_bringup_serdes(struc
 	ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
 	set_vls(ppd);
 
+	/* initially come up DISABLED, without sending anything. */
+	val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
+					QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+	qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
+	qib_write_kreg(dd, kr_scratch, 0ULL);
+	/* clear the linkinit cmds */
+	ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
+
 	/* be paranoid against later code motion, etc. */
 	spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
 	ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
 	qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
 	spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
 
-	/* Hold the link state machine for mezz boards */
-	if (IS_QMH(dd) || IS_QME(dd))
-		qib_set_ib_7322_lstate(ppd, 0,
-				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-
 	/* Also enable IBSTATUSCHG interrupt.  */
 	val = qib_read_kreg_port(ppd, krp_errmask);
 	qib_write_kreg_port(ppd, krp_errmask,
@@ -2853,9 +2852,8 @@ static irqreturn_t qib_7322intr(int irq,
 		for (i = 0; i < dd->first_user_ctxt; i++) {
 			if (ctxtrbits & rmask) {
 				ctxtrbits &= ~rmask;
-				if (dd->rcd[i]) {
+				if (dd->rcd[i])
 					qib_kreceive(dd->rcd[i], NULL, &npkts);
-				}
 			}
 			rmask <<= 1;
 		}
@@ -5230,6 +5228,8 @@ static int qib_7322_ib_updown(struct qib
 				     QIBL_IB_AUTONEG_INPROG)))
 			set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
 		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+			struct qib_qsfp_data *qd =
+				&ppd->cpspec->qsfp_data;
 			/* unlock the Tx settings, speed may change */
 			qib_write_kreg_port(ppd, krp_tx_deemph_override,
 				SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
@@ -5237,6 +5237,12 @@ static int qib_7322_ib_updown(struct qib
 			qib_cancel_sends(ppd);
 			/* on link down, ensure sane pcs state */
 			qib_7322_mini_pcs_reset(ppd);
+			/* schedule the qsfp refresh which should turn the link
+			   off */
+			if (ppd->dd->flags & QIB_HAS_QSFP) {
+				qd->t_insert = get_jiffies_64();
+				queue_work(ib_wq, &qd->work);
+			}
 			spin_lock_irqsave(&ppd->sdma_lock, flags);
 			if (__qib_sdma_running(ppd))
 				__qib_sdma_process_event(ppd,
@@ -5587,43 +5593,79 @@ static void qsfp_7322_event(struct work_
 	struct qib_qsfp_data *qd;
 	struct qib_pportdata *ppd;
 	u64 pwrup;
+	unsigned long flags;
 	int ret;
 	u32 le2;
 
 	qd = container_of(work, struct qib_qsfp_data, work);
 	ppd = qd->ppd;
-	pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC);
+	pwrup = qd->t_insert +
+		msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
 
-	/*
-	 * Some QSFP's not only do not respond until the full power-up
-	 * time, but may behave badly if we try. So hold off responding
-	 * to insertion.
-	 */
-	while (1) {
-		u64 now = get_jiffies_64();
-		if (time_after64(now, pwrup))
-			break;
-		msleep(20);
-	}
-	ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
-	/*
-	 * Need to change LE2 back to defaults if we couldn't
-	 * read the cable type (to handle cable swaps), so do this
-	 * even on failure to read cable information.  We don't
-	 * get here for QME, so IS_QME check not needed here.
-	 */
-	if (!ret && !ppd->dd->cspec->r1) {
-		if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
-			le2 = LE2_QME;
-		else if (qd->cache.atten[1] >= qib_long_atten &&
-			 QSFP_IS_CU(qd->cache.tech))
-			le2 = LE2_5m;
-		else
+	/* Delay for 20 msecs to allow ModPrs resistor to setup */
+	mdelay(QSFP_MODPRS_LAG_MSEC);
+
+	if (!qib_qsfp_mod_present(ppd)) {
+		ppd->cpspec->qsfp_data.modpresent = 0;
+		/* Set the physical link to disabled */
+		qib_set_ib_7322_lstate(ppd, 0,
+				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
+		spin_lock_irqsave(&ppd->lflags_lock, flags);
+		ppd->lflags &= ~QIBL_LINKV;
+		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+	} else {
+		/*
+		 * Some QSFP's not only do not respond until the full power-up
+		 * time, but may behave badly if we try. So hold off responding
+		 * to insertion.
+		 */
+		while (1) {
+			u64 now = get_jiffies_64();
+			if (time_after64(now, pwrup))
+				break;
+			msleep(20);
+		}
+
+		ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
+
+		/*
+		 * Need to change LE2 back to defaults if we couldn't
+		 * read the cable type (to handle cable swaps), so do this
+		 * even on failure to read cable information.  We don't
+		 * get here for QME, so IS_QME check not needed here.
+		 */
+		if (!ret && !ppd->dd->cspec->r1) {
+			if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+				le2 = LE2_QME;
+			else if (qd->cache.atten[1] >= qib_long_atten &&
+				 QSFP_IS_CU(qd->cache.tech))
+				le2 = LE2_5m;
+			else
+				le2 = LE2_DEFAULT;
+		} else
 			le2 = LE2_DEFAULT;
-	} else
-		le2 = LE2_DEFAULT;
-	ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
-	init_txdds_table(ppd, 0);
+		ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
+		/*
+		 * We always change parameteters, since we can choose
+		 * values for cables without eeproms, and the cable may have
+		 * changed from a cable with full or partial eeprom content
+		 * to one with partial or no content.
+		 */
+		init_txdds_table(ppd, 0);
+		/* The physical link is being re-enabled only when the
+		 * previous state was DISABLED and the VALID bit is not
+		 * set. This should only happen when  the cable has been
+		 * physically pulled. */
+		if (!ppd->cpspec->qsfp_data.modpresent &&
+		    (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
+			ppd->cpspec->qsfp_data.modpresent = 1;
+			qib_set_ib_7322_lstate(ppd, 0,
+				QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
+			spin_lock_irqsave(&ppd->lflags_lock, flags);
+			ppd->lflags |= QIBL_LINKV;
+			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+		}
+	}
 }
 
 /*
@@ -5727,7 +5769,8 @@ static void set_no_qsfp_atten(struct qib
 			/* now change the IBC and serdes, overriding generic */
 			init_txdds_table(ppd, 1);
 			/* Re-enable the physical state machine on mezz boards
-			 * now that the correct settings have been set. */
+			 * now that the correct settings have been set.
+			 * QSFP boards are handles by the QSFP event handler */
 			if (IS_QMH(dd) || IS_QME(dd))
 				qib_set_ib_7322_lstate(ppd, 0,
 					    QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
@@ -6205,6 +6248,8 @@ static int qib_init_7322_variables(struc
 
 	/* we always allocate at least 2048 bytes for eager buffers */
 	dd->rcvegrbufsize = max(mtu, 2048);
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7322_tidtemplate(dd);
 
@@ -7147,7 +7192,8 @@ static void find_best_ent(struct qib_ppo
 		}
 	}
 
-	/* Lookup serdes setting by cable type and attenuation */
+	/* Active cables don't have attenuation so we only set SERDES
+	 * settings to account for the attenuation of the board traces. */
 	if (!override && QSFP_IS_ACTIVE(qd->tech)) {
 		*sdr_dds = txdds_sdr + ppd->dd->board_atten;
 		*ddr_dds = txdds_ddr + ppd->dd->board_atten;
@@ -7464,12 +7510,6 @@ static int serdes_7322_init_new(struct q
 	u32 le_val, rxcaldone;
 	int chan, chan_done = (1 << SERDES_CHANS) - 1;
 
-	/*
-	 * Initialize the Tx DDS tables.  Also done every QSFP event,
-	 * for adapters with QSFP
-	 */
-	init_txdds_table(ppd, 0);
-
 	/* Clear cmode-override, may be set from older driver */
 	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
 
@@ -7655,6 +7695,12 @@ static int serdes_7322_init_new(struct q
 	/* VGA output common mode */
 	ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
 
+	/*
+	 * Initialize the Tx DDS tables.  Also done every QSFP event,
+	 * for adapters with QSFP
+	 */
+	init_txdds_table(ppd, 0);
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_init.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/idr.h>
+#include <linux/module.h>
 
 #include "qib.h"
 #include "qib_common.h"
@@ -183,6 +184,9 @@ struct qib_ctxtdata *qib_create_ctxtdata
 		rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
 			rcd->rcvegrbufs_perchunk - 1) /
 			rcd->rcvegrbufs_perchunk;
+		BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
+		rcd->rcvegrbufs_perchunk_shift =
+			ilog2(rcd->rcvegrbufs_perchunk);
 	}
 	return rcd;
 }
@@ -398,6 +402,7 @@ static void enable_chip(struct qib_devda
 		if (rcd)
 			dd->f_rcvctrl(rcd->ppd, rcvmask, i);
 	}
+	dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
 }
 
 static void verify_interrupt(unsigned long opaque)
@@ -581,10 +586,6 @@ int qib_init(struct qib_devdata *dd, int
 			continue;
 		}
 
-		/* let link come up, and enable IBC */
-		spin_lock_irqsave(&ppd->lflags_lock, flags);
-		ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
-		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 		portok++;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_pcie.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_pcie.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/aer.h>
+#include <linux/module.h>
 
 #include "qib.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/jhash.h>
 
 #include "qib.h"
 
@@ -204,6 +205,13 @@ static void free_qpn(struct qib_qpn_tabl
 		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
 }
 
+static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
+{
+	return jhash_1word(qpn, dev->qp_rnd) &
+		(dev->qp_table_size - 1);
+}
+
+
 /*
  * Put the QP into the hash table.
  * The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@ static void free_qpn(struct qib_qpn_tabl
 static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
 	unsigned long flags;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
+	atomic_inc(&qp->refcount);
 
 	if (qp->ibqp.qp_num == 0)
-		ibp->qp0 = qp;
+		rcu_assign_pointer(ibp->qp0, qp);
 	else if (qp->ibqp.qp_num == 1)
-		ibp->qp1 = qp;
+		rcu_assign_pointer(ibp->qp1, qp);
 	else {
 		qp->next = dev->qp_table[n];
-		dev->qp_table[n] = qp;
+		rcu_assign_pointer(dev->qp_table[n], qp);
 	}
-	atomic_inc(&qp->refcount);
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /*
@@ -236,29 +245,32 @@ static void insert_qp(struct qib_ibdev *
 static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	struct qib_qp *q, **qpp;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 	unsigned long flags;
 
-	qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
-
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 
 	if (ibp->qp0 == qp) {
-		ibp->qp0 = NULL;
 		atomic_dec(&qp->refcount);
+		rcu_assign_pointer(ibp->qp0, NULL);
 	} else if (ibp->qp1 == qp) {
-		ibp->qp1 = NULL;
 		atomic_dec(&qp->refcount);
-	} else
+		rcu_assign_pointer(ibp->qp1, NULL);
+	} else {
+		struct qib_qp *q, **qpp;
+
+		qpp = &dev->qp_table[n];
 		for (; (q = *qpp) != NULL; qpp = &q->next)
 			if (q == qp) {
-				*qpp = qp->next;
-				qp->next = NULL;
 				atomic_dec(&qp->refcount);
+				rcu_assign_pointer(*qpp, qp->next);
+				qp->next = NULL;
 				break;
 			}
+	}
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /**
@@ -280,21 +292,24 @@ unsigned qib_free_all_qps(struct qib_dev
 
 		if (!qib_mcast_tree_empty(ibp))
 			qp_inuse++;
-		if (ibp->qp0)
+		rcu_read_lock();
+		if (rcu_dereference(ibp->qp0))
 			qp_inuse++;
-		if (ibp->qp1)
+		if (rcu_dereference(ibp->qp1))
 			qp_inuse++;
+		rcu_read_unlock();
 	}
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 	for (n = 0; n < dev->qp_table_size; n++) {
 		qp = dev->qp_table[n];
-		dev->qp_table[n] = NULL;
+		rcu_assign_pointer(dev->qp_table[n], NULL);
 
 		for (; qp; qp = qp->next)
 			qp_inuse++;
 	}
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 
 	return qp_inuse;
 }
@@ -309,25 +324,28 @@ unsigned qib_free_all_qps(struct qib_dev
  */
 struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
 {
-	struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
-	unsigned long flags;
-	struct qib_qp *qp;
+	struct qib_qp *qp = NULL;
 
-	spin_lock_irqsave(&dev->qpt_lock, flags);
+	if (unlikely(qpn <= 1)) {
+		rcu_read_lock();
+		if (qpn == 0)
+			qp = rcu_dereference(ibp->qp0);
+		else
+			qp = rcu_dereference(ibp->qp1);
+	} else {
+		struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
+		unsigned n = qpn_hash(dev, qpn);
 
-	if (qpn == 0)
-		qp = ibp->qp0;
-	else if (qpn == 1)
-		qp = ibp->qp1;
-	else
-		for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
-		     qp = qp->next)
+		rcu_read_lock();
+		for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
 			if (qp->ibqp.qp_num == qpn)
 				break;
+	}
 	if (qp)
-		atomic_inc(&qp->refcount);
+		if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
+			qp = NULL;
 
-	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	rcu_read_unlock();
 	return qp;
 }
 
@@ -765,8 +783,10 @@ int qib_modify_qp(struct ib_qp *ibqp, st
 		}
 	}
 
-	if (attr_mask & IB_QP_PATH_MTU)
+	if (attr_mask & IB_QP_PATH_MTU) {
 		qp->path_mtu = pmtu;
+		qp->pmtu = ib_mtu_enum_to_int(pmtu);
+	}
 
 	if (attr_mask & IB_QP_RETRY_CNT) {
 		qp->s_retry_cnt = attr->retry_cnt;
@@ -781,8 +801,12 @@ int qib_modify_qp(struct ib_qp *ibqp, st
 	if (attr_mask & IB_QP_MIN_RNR_TIMER)
 		qp->r_min_rnr_timer = attr->min_rnr_timer;
 
-	if (attr_mask & IB_QP_TIMEOUT)
+	if (attr_mask & IB_QP_TIMEOUT) {
 		qp->timeout = attr->timeout;
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
+	}
 
 	if (attr_mask & IB_QP_QKEY)
 		qp->qkey = attr->qkey;
@@ -1013,6 +1037,10 @@ struct ib_qp *qib_create_qp(struct ib_pd
 			ret = ERR_PTR(-ENOMEM);
 			goto bail_swq;
 		}
+		RCU_INIT_POINTER(qp->next, NULL);
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
 		if (init_attr->srq)
 			sz = 0;
 		else {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pp
 	int ret;
 	int idx;
 	u16 cks;
-	u32 mask;
 	u8 peek[4];
 
 	/* ensure sane contents on invalid reads, for cable swaps */
 	memset(cp, 0, sizeof(*cp));
 
-	mask = QSFP_GPIO_MOD_PRS_N;
-	if (ppd->hw_pidx)
-		mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
-	if (ret & mask) {
+	if (!qib_qsfp_mod_present(ppd)) {
 		ret = -ENODEV;
 		goto bail;
 	}
@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16]
 
 static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
 
+int qib_qsfp_mod_present(struct qib_pportdata *ppd)
+{
+	u32 mask;
+	int ret;
+
+	mask = QSFP_GPIO_MOD_PRS_N <<
+		(ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
+	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
+
+	return !((ret & mask) >>
+		 ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
+}
+
 /*
  * Initialize structures that control access to QSFP. Called once per port
  * on cards that support QSFP.
@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data
 		   void (*fevent)(struct work_struct *))
 {
 	u32 mask, highs;
-	int pins;
 
 	struct qib_devdata *dd = qd->ppd->dd;
 
@@ -474,19 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data
 	udelay(20); /* Generous RST dwell */
 
 	dd->f_gpio_mod(dd, mask, mask, mask);
-	/* Spec says module can take up to two seconds! */
-	mask = QSFP_GPIO_MOD_PRS_N;
-	if (qd->ppd->hw_pidx)
-		mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-	/* Do not try to wait here. Better to let event handle it */
-	pins = dd->f_gpio_mod(dd, 0, 0, 0);
-	if (pins & mask)
-		goto bail;
-	/* We see a module, but it may be unwise to look yet. Just schedule */
-	qd->t_insert = get_jiffies_64();
-	queue_work(ib_wq, &qd->work);
-bail:
 	return;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qsfp.h linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qsfp.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_qsfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_qsfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #define QSFP_DEV 0xA0
 #define QSFP_PWR_LAG_MSEC 2000
+#define QSFP_MODPRS_LAG_MSEC 20
 
 /*
  * Below are masks for various QSFP signals, for Port 1.
@@ -177,10 +178,12 @@ struct qib_qsfp_data {
 	struct work_struct work;
 	struct qib_qsfp_cache cache;
 	u64 t_insert;
+	u8 modpresent;
 };
 
 extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
 				  struct qib_qsfp_cache *cp);
+extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
 extern void qib_qsfp_init(struct qib_qsfp_data *qd,
 			  void (*fevent)(struct work_struct *));
 extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_rc.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_rc.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_rc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_rc.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,8 +59,7 @@ static void start_timer(struct qib_qp *q
 	qp->s_flags |= QIB_S_TIMER;
 	qp->s_timer.function = rc_timeout;
 	/* 4.096 usec. * (1 << qp->timeout) */
-	qp->s_timer.expires = jiffies +
-		usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL);
+	qp->s_timer.expires = jiffies + qp->timeout_jiffies;
 	add_timer(&qp->s_timer);
 }
 
@@ -239,7 +238,7 @@ int qib_make_rc_req(struct qib_qp *qp)
 	u32 len;
 	u32 bth0;
 	u32 bth2;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	char newreq;
 	unsigned long flags;
 	int ret = 0;
@@ -272,13 +271,9 @@ int qib_make_rc_req(struct qib_qp *qp)
 			goto bail;
 		}
 		wqe = get_swqe_ptr(qp, qp->s_last);
-		while (qp->s_last != qp->s_acked) {
-			qib_send_complete(qp, wqe, IB_WC_SUCCESS);
-			if (++qp->s_last >= qp->s_size)
-				qp->s_last = 0;
-			wqe = get_swqe_ptr(qp, qp->s_last);
-		}
-		qib_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
+		qib_send_complete(qp, wqe, qp->s_last != qp->s_acked ?
+			IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR);
+		/* will get called again */
 		goto done;
 	}
 
@@ -1519,9 +1514,7 @@ read_middle:
 		 * 4.096 usec. * (1 << qp->timeout)
 		 */
 		qp->s_flags |= QIB_S_TIMER;
-		mod_timer(&qp->s_timer, jiffies +
-			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
-					 1000UL));
+		mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies);
 		if (qp->s_flags & QIB_S_WAIT_ACK) {
 			qp->s_flags &= ~QIB_S_WAIT_ACK;
 			qib_schedule_send(qp);
@@ -1732,7 +1725,7 @@ static int qib_rc_rcv_error(struct qib_o
 		 * same request.
 		 */
 		offset = ((psn - e->psn) & QIB_PSN_MASK) *
-			ib_mtu_enum_to_int(qp->path_mtu);
+			qp->pmtu;
 		len = be32_to_cpu(reth->length);
 		if (unlikely(offset + len != e->rdma_sge.sge_length))
 			goto unlock_done;
@@ -1876,7 +1869,7 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int diff;
 	struct ib_reth *reth;
 	unsigned long flags;
@@ -1892,10 +1885,8 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
@@ -1955,8 +1946,6 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd
 		break;
 	}
 
-	memset(&wc, 0, sizeof wc);
-
 	if (qp->state == IB_QPS_RTR && !(qp->r_flags & QIB_R_COMM_EST)) {
 		qp->r_flags |= QIB_R_COMM_EST;
 		if (qp->ibqp.event_handler) {
@@ -2009,16 +1998,19 @@ send_middle:
 			goto rnr_nak;
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
-		/* FALLTHROUGH */
+			goto no_immediate_data;
+		/* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
 	case OP(SEND_LAST_WITH_IMMEDIATE):
 send_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
 	case OP(RDMA_WRITE_LAST):
+no_immediate_data:
+		wc.wc_flags = 0;
+		wc.ex.imm_data = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -2051,6 +2043,12 @@ send_last:
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -2089,7 +2087,7 @@ send_last:
 		if (opcode == OP(RDMA_WRITE_FIRST))
 			goto send_middle;
 		else if (opcode == OP(RDMA_WRITE_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		ret = qib_get_rwqe(qp, 1);
 		if (ret < 0)
 			goto nack_op_err;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_ruc.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_ruc.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_ruc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_ruc.c	2012-01-04 18:55:44.000000000 -0500
@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __b
 
 /*
  *
- * This should be called with the QP s_lock held.
+ * This should be called with the QP r_lock held.
+ *
+ * The s_lock will be acquired around the qib_migrate_qp() call.
  */
 int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 		      int has_grh, struct qib_qp *qp, u32 bth0)
 {
 	__be64 guid;
+	unsigned long flags;
 
 	if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
 		if (!has_grh) {
@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport
 		if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
 		    ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
 			goto err;
+		spin_lock_irqsave(&qp->s_lock, flags);
 		qib_migrate_qp(qp);
+		spin_unlock_irqrestore(&qp->s_lock, flags);
 	} else {
 		if (!has_grh) {
 			if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sd7220.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sd7220.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sd7220.c	2013-05-02 01:43:12.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sd7220.c	2013-05-01 23:49:47.000000000 -0400
@@ -38,6 +38,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/firmware.h>
 
 #include "qib.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sdma.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sdma.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
+#include <linux/moduleparam.h>
 
 #include "qib.h"
 #include "qib_common.h"
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_srq.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_srq.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_sge == 0 ||
 	    srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
 	    srq_init_attr->attr.max_wr == 0 ||
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sysfs.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sysfs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -515,8 +515,7 @@ static ssize_t show_nfreectxts(struct de
 	struct qib_devdata *dd = dd_from_dev(dev);
 
 	/* Return the number of free user ports (contexts) available. */
-	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
-		dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
 }
 
 static ssize_t show_serial(struct device *device,
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_tx.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_tx.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_tx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_tx.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include "qib.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_uc.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_uc.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_uc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_uc.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@ int qib_make_uc_req(struct qib_qp *qp)
 	u32 hwords;
 	u32 bth0;
 	u32 len;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int ret = 0;
 
 	spin_lock_irqsave(&qp->s_lock, flags);
@@ -243,13 +243,12 @@ void qib_uc_rcv(struct qib_ibport *ibp,
 		int has_grh, void *data, u32 tlen, struct qib_qp *qp)
 {
 	struct qib_other_headers *ohdr;
-	unsigned long flags;
 	u32 opcode;
 	u32 hdrsize;
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	struct ib_reth *reth;
 	int ret;
 
@@ -263,14 +262,11 @@ void qib_uc_rcv(struct qib_ibport *ibp,
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
-	memset(&wc, 0, sizeof wc);
 
 	/* Compare the PSN verses the expected PSN. */
 	if (unlikely(qib_cmp24(psn, qp->r_psn) != 0)) {
@@ -370,7 +366,7 @@ send_first:
 		}
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
 			goto send_last_imm;
 		/* FALLTHROUGH */
@@ -389,8 +385,11 @@ send_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
+no_immediate_data:
+		wc.ex.imm_data = 0;
+		wc.wc_flags = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -418,6 +417,12 @@ last_imm:
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -546,6 +551,4 @@ op_err:
 	qib_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
 	return;
 
-sunlock:
-	spin_unlock_irqrestore(&qp->s_lock, flags);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_user_pages.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_user_pages.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_user_pages.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_user_pages.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@ static int __qib_get_user_pages(unsigned
 			goto bail_release;
 	}
 
-	current->mm->locked_vm += num_pages;
+	current->mm->pinned_vm += num_pages;
 
 	ret = 0;
 	goto bail;
@@ -151,7 +151,7 @@ void qib_release_user_pages(struct page
 	__qib_release_user_pages(p, num_pages, 1);
 
 	if (current->mm) {
-		current->mm->locked_vm -= num_pages;
+		current->mm->pinned_vm -= num_pages;
 		up_write(&current->mm->mmap_sem);
 	}
 }
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_verbs.c linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_verbs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,14 +35,16 @@
 #include <rdma/ib_mad.h>
 #include <rdma/ib_user_verbs.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/rculist.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 
 #include "qib.h"
 #include "qib_common.h"
 
-static unsigned int ib_qib_qp_table_size = 251;
+static unsigned int ib_qib_qp_table_size = 256;
 module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(qp_table_size, "QP table size");
 
@@ -659,17 +661,25 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd
 		if (atomic_dec_return(&mcast->refcount) <= 1)
 			wake_up(&mcast->wait);
 	} else {
-		qp = qib_lookup_qpn(ibp, qp_num);
-		if (!qp)
-			goto drop;
+		if (rcd->lookaside_qp) {
+			if (rcd->lookaside_qpn != qp_num) {
+				if (atomic_dec_and_test(
+					&rcd->lookaside_qp->refcount))
+					wake_up(
+					 &rcd->lookaside_qp->wait);
+					rcd->lookaside_qp = NULL;
+				}
+		}
+		if (!rcd->lookaside_qp) {
+			qp = qib_lookup_qpn(ibp, qp_num);
+			if (!qp)
+				goto drop;
+			rcd->lookaside_qp = qp;
+			rcd->lookaside_qpn = qp_num;
+		} else
+			qp = rcd->lookaside_qp;
 		ibp->n_unicast_rcv++;
 		qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
-		/*
-		 * Notify qib_destroy_qp() if it is waiting
-		 * for us to finish.
-		 */
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
 	}
 	return;
 
@@ -1974,6 +1984,8 @@ static void init_ibport(struct qib_pport
 	ibp->z_excessive_buffer_overrun_errors =
 		cntrs.excessive_buffer_overrun_errors;
 	ibp->z_vl15_dropped = cntrs.vl15_dropped;
+	RCU_INIT_POINTER(ibp->qp0, NULL);
+	RCU_INIT_POINTER(ibp->qp1, NULL);
 }
 
 /**
@@ -1990,12 +2002,15 @@ int qib_register_ib_device(struct qib_de
 	int ret;
 
 	dev->qp_table_size = ib_qib_qp_table_size;
-	dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table,
+	get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
+	dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
 				GFP_KERNEL);
 	if (!dev->qp_table) {
 		ret = -ENOMEM;
 		goto err_qpt;
 	}
+	for (i = 0; i < dev->qp_table_size; i++)
+		RCU_INIT_POINTER(dev->qp_table[i], NULL);
 
 	for (i = 0; i < dd->num_pports; i++)
 		init_ibport(ppd + i);
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_verbs.h linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_verbs.h
--- linux-libre-3.1-gnu1/drivers/infiniband/hw/qib/qib_verbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/hw/qib/qib_verbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -485,6 +485,7 @@ struct qib_qp {
 	u8 alt_timeout;         /* Alternate path timeout for this QP */
 	u8 port_num;
 	enum ib_mtu path_mtu;
+	u32 pmtu;		/* decoded from path_mtu */
 	u32 remote_qpn;
 	u32 qkey;               /* QKEY for this QP (for UD or RD) */
 	u32 s_size;             /* send work queue size */
@@ -495,6 +496,7 @@ struct qib_qp {
 	u32 s_last;             /* last completed entry */
 	u32 s_ssn;              /* SSN of tail entry */
 	u32 s_lsn;              /* limit sequence number (credit) */
+	unsigned long timeout_jiffies;  /* computed from timeout */
 	struct qib_swqe *s_wq;  /* send work queue */
 	struct qib_swqe *s_wqe;
 	struct qib_rq r_rq;             /* receive work queue */
@@ -723,7 +725,8 @@ struct qib_ibdev {
 	dma_addr_t pio_hdrs_phys;
 	/* list of QPs waiting for RNR timer */
 	spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
-	unsigned qp_table_size; /* size of the hash table */
+	u32 qp_table_size; /* size of the hash table */
+	u32 qp_rnd; /* random bytes for hash */
 	spinlock_t qpt_lock;
 
 	u32 n_piowait;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include "ipoib.h"
 
@@ -84,7 +85,7 @@ static void ipoib_cm_dma_unmap_rx(struct
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (i = 0; i < frags; ++i)
-		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
 static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
@@ -169,7 +170,7 @@ static struct sk_buff *ipoib_cm_alloc_rx
 			goto partial_error;
 		skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
 
-		mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+		mapping[i + 1] = ib_dma_map_page(priv->ca, page,
 						 0, PAGE_SIZE, DMA_FROM_DEVICE);
 		if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
 			goto partial_error;
@@ -183,7 +184,7 @@ partial_error:
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (; i > 0; --i)
-		ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
 
 	dev_kfree_skb_any(skb);
 	return NULL;
@@ -537,12 +538,13 @@ static void skb_put_frags(struct sk_buff
 
 		if (length == 0) {
 			/* don't need this page */
-			skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
+			skb_fill_page_desc(toskb, i, skb_frag_page(frag),
+					   0, PAGE_SIZE);
 			--skb_shinfo(skb)->nr_frags;
 		} else {
 			size = min(length, (unsigned) PAGE_SIZE);
 
-			frag->size = size;
+			skb_frag_size_set(frag, size);
 			skb->data_len += size;
 			skb->truesize += size;
 			skb->len += size;
@@ -1496,6 +1498,7 @@ static void ipoib_cm_create_srq(struct n
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_srq_init_attr srq_init_attr = {
+		.srq_type = IB_SRQT_BASIC,
 		.attr = {
 			.max_wr  = ipoib_recvq_size,
 			.max_sge = max_sge
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_fs.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_fs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 struct file_operations;
 
 #include <linux/debugfs.h>
+#include <linux/export.h>
 
 #include "ipoib.h"
 
@@ -212,16 +213,15 @@ static int ipoib_path_seq_show(struct se
 		   gid_buf, path.pathrec.dlid ? "yes" : "no");
 
 	if (path.pathrec.dlid) {
-		rate = ib_rate_to_mult(path.pathrec.rate) * 25;
+		rate = ib_rate_to_mbps(path.pathrec.rate);
 
 		seq_printf(file,
 			   "  DLID:     0x%04x\n"
 			   "  SL: %12d\n"
-			   "  rate: %*d%s Gb/sec\n",
+			   "  rate: %8d.%d Gb/sec\n",
 			   be16_to_cpu(path.pathrec.dlid),
 			   path.pathrec.sl,
-			   10 - ((rate % 10) ? 2 : 0),
-			   rate / 10, rate % 10 ? ".5" : "");
+			   rate / 1000, rate % 1000);
 	}
 
 	seq_putc(file, '\n');
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
@@ -56,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct
 				 struct ib_pd *pd, struct ib_ah_attr *attr)
 {
 	struct ipoib_ah *ah;
+	struct ib_ah *vah;
 
 	ah = kmalloc(sizeof *ah, GFP_KERNEL);
 	if (!ah)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	ah->dev       = dev;
 	ah->last_send = 0;
 	kref_init(&ah->ref);
 
-	ah->ah = ib_create_ah(pd, attr);
-	if (IS_ERR(ah->ah)) {
+	vah = ib_create_ah(pd, attr);
+	if (IS_ERR(vah)) {
 		kfree(ah);
-		ah = NULL;
-	} else
+		ah = (struct ipoib_ah *)vah;
+	} else {
+		ah->ah = vah;
 		ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+	}
 
 	return ah;
 }
@@ -117,7 +121,7 @@ static void ipoib_ud_skb_put_frags(struc
 
 		size = length - IPOIB_UD_HEAD_SIZE;
 
-		frag->size     = size;
+		skb_frag_size_set(frag, size);
 		skb->data_len += size;
 		skb->truesize += size;
 	} else
@@ -182,7 +186,7 @@ static struct sk_buff *ipoib_alloc_rx_sk
 			goto partial_error;
 		skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
 		mapping[1] =
-			ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+			ib_dma_map_page(priv->ca, page,
 					0, PAGE_SIZE, DMA_FROM_DEVICE);
 		if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
 			goto partial_error;
@@ -322,9 +326,10 @@ static int ipoib_dma_map_tx(struct ib_de
 		off = 0;
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		mapping[i + off] = ib_dma_map_page(ca, frag->page,
-						 frag->page_offset, frag->size,
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		mapping[i + off] = ib_dma_map_page(ca,
+						 skb_frag_page(frag),
+						 frag->page_offset, skb_frag_size(frag),
 						 DMA_TO_DEVICE);
 		if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
 			goto partial_error;
@@ -333,8 +338,9 @@ static int ipoib_dma_map_tx(struct ib_de
 
 partial_error:
 	for (; i > 0; --i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
-		ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+
+		ib_dma_unmap_page(ca, mapping[i - !off], skb_frag_size(frag), DMA_TO_DEVICE);
 	}
 
 	if (off)
@@ -358,8 +364,9 @@ static void ipoib_dma_unmap_tx(struct ib
 		off = 0;
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag),
 				  DMA_TO_DEVICE);
 	}
 }
@@ -509,7 +516,7 @@ static inline int post_send(struct ipoib
 
 	for (i = 0; i < nr_frags; ++i) {
 		priv->tx_sge[i + off].addr = mapping[i + off];
-		priv->tx_sge[i + off].length = frags[i].size;
+		priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
 	}
 	priv->tx_wr.num_sge	     = nr_frags + off;
 	priv->tx_wr.wr_id 	     = wr_id;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -432,7 +432,7 @@ static void path_rec_completion(int stat
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (ah) {
+	if (!IS_ERR_OR_NULL(ah)) {
 		path->pathrec = *pathrec;
 
 		old_ah   = path->ah;
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_dev
 	return 0;
 }
 
+/* called with rcu_read_lock */
 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -636,6 +637,7 @@ err_drop:
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* called with rcu_read_lock */
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_bu
 	struct neighbour *n = NULL;
 	unsigned long flags;
 
+	rcu_read_lock();
 	if (likely(skb_dst(skb)))
 		n = dst_get_neighbour(skb_dst(skb));
 
 	if (likely(n)) {
 		if (unlikely(!*to_ipoib_neigh(n))) {
 			ipoib_path_lookup(skb, dev);
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		neigh = *to_ipoib_neigh(n);
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_bu
 			ipoib_neigh_free(dev, neigh);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			ipoib_path_lookup(skb, dev);
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		if (ipoib_cm_get(neigh)) {
 			if (ipoib_cm_up(neigh)) {
 				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
-				return NETDEV_TX_OK;
+				goto unlock;
 			}
 		} else if (neigh->ah) {
 			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_bu
 					   phdr->hwaddr + 4);
 				dev_kfree_skb_any(skb);
 				++dev->stats.tx_dropped;
-				return NETDEV_TX_OK;
+				goto unlock;
 			}
 
 			unicast_arp_send(skb, dev, phdr);
 		}
 	}
-
+unlock:
+	rcu_read_unlock();
 	return NETDEV_TX_OK;
 }
 
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_b
 	dst = skb_dst(skb);
 	n = NULL;
 	if (dst)
-		n = dst_get_neighbour(dst);
+		n = dst_get_neighbour_raw(dst);
 	if ((!dst || !n) && daddr) {
 		struct ipoib_pseudoheader *phdr =
 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
@@ -998,7 +1002,7 @@ static const struct net_device_ops ipoib
 	.ndo_fix_features	 = ipoib_fix_features,
 	.ndo_start_xmit	 	 = ipoib_start_xmit,
 	.ndo_tx_timeout		 = ipoib_timeout,
-	.ndo_set_multicast_list	 = ipoib_set_mcast_list,
+	.ndo_set_rx_mode	 = ipoib_set_mcast_list,
 	.ndo_neigh_setup	 = ipoib_neigh_setup_dev,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
 #include <linux/ip.h>
 #include <linux/in.h>
 #include <linux/igmp.h>
@@ -239,8 +240,11 @@ static int ipoib_mcast_join_finish(struc
 		av.grh.dgid = mcast->mcmember.mgid;
 
 		ah = ipoib_create_ah(dev, priv->pd, &av);
-		if (!ah) {
-			ipoib_warn(priv, "ib_address_create failed\n");
+		if (IS_ERR(ah)) {
+			ipoib_warn(priv, "ib_address_create failed %ld\n",
+				-PTR_ERR(ah));
+			/* use original error */
+			return PTR_ERR(ah);
 		} else {
 			spin_lock_irq(&priv->lock);
 			mcast->ah = ah;
@@ -265,7 +269,7 @@ static int ipoib_mcast_join_finish(struc
 
 		skb->dev = dev;
 		if (dst)
-			n = dst_get_neighbour(dst);
+			n = dst_get_neighbour_raw(dst);
 		if (!dst || !n) {
 			/* put pseudoheader back on for next time */
 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
@@ -721,6 +725,8 @@ out:
 	if (mcast && mcast->ah) {
 		struct dst_entry *dst = skb_dst(skb);
 		struct neighbour *n = NULL;
+
+		rcu_read_lock();
 		if (dst)
 			n = dst_get_neighbour(dst);
 		if (n && !*to_ipoib_neigh(n)) {
@@ -733,7 +739,7 @@ out:
 				list_add_tail(&neigh->list, &mcast->neigh_list);
 			}
 		}
-
+		rcu_read_unlock();
 		spin_unlock_irqrestore(&priv->lock, flags);
 		ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
 		return;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <net/sock.h>
 
@@ -151,7 +152,6 @@ int iser_initialize_task_headers(struct
 	tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
 	tx_desc->tx_sg[0].lkey   = device->mr->lkey;
 
-	iser_task->headers_initialized	= 1;
 	iser_task->iser_conn		= iser_conn;
 	return 0;
 }
@@ -166,8 +166,7 @@ iscsi_iser_task_init(struct iscsi_task *
 {
 	struct iscsi_iser_task *iser_task = task->dd_data;
 
-	if (!iser_task->headers_initialized)
-		if (iser_initialize_task_headers(task, &iser_task->desc))
+	if (iser_initialize_task_headers(task, &iser_task->desc))
 			return -ENOMEM;
 
 	/* mgmt task */
@@ -278,6 +277,13 @@ iscsi_iser_task_xmit(struct iscsi_task *
 static void iscsi_iser_cleanup_task(struct iscsi_task *task)
 {
 	struct iscsi_iser_task *iser_task = task->dd_data;
+	struct iser_tx_desc	*tx_desc = &iser_task->desc;
+
+	struct iscsi_iser_conn *iser_conn = task->conn->dd_data;
+	struct iser_device     *device    = iser_conn->ib_conn->device;
+
+	ib_dma_unmap_single(device->ib_device,
+		tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
 	/* mgmt tasks do not need special cleanup */
 	if (!task->sc)
@@ -632,6 +638,59 @@ iscsi_iser_ep_disconnect(struct iscsi_en
 	iser_conn_terminate(ib_conn);
 }
 
+static mode_t iser_attr_is_visible(int param_type, int param)
+{
+	switch (param_type) {
+	case ISCSI_HOST_PARAM:
+		switch (param) {
+		case ISCSI_HOST_PARAM_NETDEV_NAME:
+		case ISCSI_HOST_PARAM_HWADDRESS:
+		case ISCSI_HOST_PARAM_INITIATOR_NAME:
+			return S_IRUGO;
+		default:
+			return 0;
+		}
+	case ISCSI_PARAM:
+		switch (param) {
+		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		case ISCSI_PARAM_HDRDGST_EN:
+		case ISCSI_PARAM_DATADGST_EN:
+		case ISCSI_PARAM_CONN_ADDRESS:
+		case ISCSI_PARAM_CONN_PORT:
+		case ISCSI_PARAM_EXP_STATSN:
+		case ISCSI_PARAM_PERSISTENT_ADDRESS:
+		case ISCSI_PARAM_PERSISTENT_PORT:
+		case ISCSI_PARAM_PING_TMO:
+		case ISCSI_PARAM_RECV_TMO:
+		case ISCSI_PARAM_INITIAL_R2T_EN:
+		case ISCSI_PARAM_MAX_R2T:
+		case ISCSI_PARAM_IMM_DATA_EN:
+		case ISCSI_PARAM_FIRST_BURST:
+		case ISCSI_PARAM_MAX_BURST:
+		case ISCSI_PARAM_PDU_INORDER_EN:
+		case ISCSI_PARAM_DATASEQ_INORDER_EN:
+		case ISCSI_PARAM_TARGET_NAME:
+		case ISCSI_PARAM_TPGT:
+		case ISCSI_PARAM_USERNAME:
+		case ISCSI_PARAM_PASSWORD:
+		case ISCSI_PARAM_USERNAME_IN:
+		case ISCSI_PARAM_PASSWORD_IN:
+		case ISCSI_PARAM_FAST_ABORT:
+		case ISCSI_PARAM_ABORT_TMO:
+		case ISCSI_PARAM_LU_RESET_TMO:
+		case ISCSI_PARAM_TGT_RESET_TMO:
+		case ISCSI_PARAM_IFACE_NAME:
+		case ISCSI_PARAM_INITIATOR_NAME:
+			return S_IRUGO;
+		default:
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
 static struct scsi_host_template iscsi_iser_sht = {
 	.module                 = THIS_MODULE,
 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
@@ -653,32 +712,6 @@ static struct iscsi_transport iscsi_iser
 	.owner                  = THIS_MODULE,
 	.name                   = "iser",
 	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
-				  ISCSI_MAX_XMIT_DLENGTH |
-				  ISCSI_HDRDGST_EN |
-				  ISCSI_DATADGST_EN |
-				  ISCSI_INITIAL_R2T_EN |
-				  ISCSI_MAX_R2T |
-				  ISCSI_IMM_DATA_EN |
-				  ISCSI_FIRST_BURST |
-				  ISCSI_MAX_BURST |
-				  ISCSI_PDU_INORDER_EN |
-				  ISCSI_DATASEQ_INORDER_EN |
-				  ISCSI_CONN_PORT |
-				  ISCSI_CONN_ADDRESS |
-				  ISCSI_EXP_STATSN |
-				  ISCSI_PERSISTENT_PORT |
-				  ISCSI_PERSISTENT_ADDRESS |
-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
-				  ISCSI_USERNAME | ISCSI_PASSWORD |
-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
-				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
-				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
-	.host_param_mask	= ISCSI_HOST_HWADDRESS |
-				  ISCSI_HOST_NETDEV_NAME |
-				  ISCSI_HOST_INITIATOR_NAME,
 	/* session management */
 	.create_session         = iscsi_iser_session_create,
 	.destroy_session        = iscsi_iser_session_destroy,
@@ -686,6 +719,7 @@ static struct iscsi_transport iscsi_iser
 	.create_conn            = iscsi_iser_conn_create,
 	.bind_conn              = iscsi_iser_conn_bind,
 	.destroy_conn           = iscsi_iser_conn_destroy,
+	.attr_is_visible	= iser_attr_is_visible,
 	.set_param              = iscsi_iser_set_param,
 	.get_conn_param		= iscsi_conn_get_param,
 	.get_ep_param		= iscsi_iser_get_ep_param,
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iscsi_iser.h	2012-01-04 18:55:44.000000000 -0500
@@ -257,7 +257,8 @@ struct iser_conn {
 	struct list_head	     conn_list;       /* entry in ig conn list */
 
 	char  			     *login_buf;
-	u64 			     login_dma;
+	char			     *login_req_buf, *login_resp_buf;
+	u64			     login_req_dma, login_resp_dma;
 	unsigned int 		     rx_desc_head;
 	struct iser_rx_desc	     *rx_descs;
 	struct ib_recv_wr	     rx_wr[ISER_MIN_POSTED_RX];
@@ -277,7 +278,6 @@ struct iscsi_iser_task {
 	struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
 	struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
 	struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
-	int                          headers_initialized;
 };
 
 struct iser_page_vec {
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iser_initiator.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iser_initiator.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iser_initiator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iser_initiator.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct ise
 	struct iser_device *device = ib_conn->device;
 
 	if (ib_conn->login_buf) {
-		ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
-			ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+		if (ib_conn->login_req_dma)
+			ib_dma_unmap_single(device->ib_device,
+				ib_conn->login_req_dma,
+				ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+		if (ib_conn->login_resp_dma)
+			ib_dma_unmap_single(device->ib_device,
+				ib_conn->login_resp_dma,
+				ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
 		kfree(ib_conn->login_buf);
 	}
 
@@ -394,6 +400,7 @@ int iser_send_control(struct iscsi_conn
 	unsigned long data_seg_len;
 	int err = 0;
 	struct iser_device *device;
+	struct iser_conn *ib_conn = iser_conn->ib_conn;
 
 	/* build the tx desc regd header and add it to the tx desc dto */
 	mdesc->type = ISCSI_TX_CONTROL;
@@ -409,9 +416,19 @@ int iser_send_control(struct iscsi_conn
 			iser_err("data present on non login task!!!\n");
 			goto send_control_error;
 		}
-		memcpy(iser_conn->ib_conn->login_buf, task->data,
+
+		ib_dma_sync_single_for_cpu(device->ib_device,
+			ib_conn->login_req_dma, task->data_count,
+			DMA_TO_DEVICE);
+
+		memcpy(iser_conn->ib_conn->login_req_buf, task->data,
 							task->data_count);
-		tx_dsg->addr    = iser_conn->ib_conn->login_dma;
+
+		ib_dma_sync_single_for_device(device->ib_device,
+			ib_conn->login_req_dma, task->data_count,
+			DMA_TO_DEVICE);
+
+		tx_dsg->addr    = iser_conn->ib_conn->login_req_dma;
 		tx_dsg->length  = task->data_count;
 		tx_dsg->lkey    = device->mr->lkey;
 		mdesc->num_sge = 2;
@@ -445,8 +462,8 @@ void iser_rcv_completion(struct iser_rx_
 	int rx_buflen, outstanding, count, err;
 
 	/* differentiate between login to all other PDUs */
-	if ((char *)rx_desc == ib_conn->login_buf) {
-		rx_dma = ib_conn->login_dma;
+	if ((char *)rx_desc == ib_conn->login_resp_buf) {
+		rx_dma = ib_conn->login_resp_dma;
 		rx_buflen = ISER_RX_LOGIN_SIZE;
 	} else {
 		rx_dma = rx_desc->dma_addr;
@@ -473,7 +490,7 @@ void iser_rcv_completion(struct iser_rx_
 	 * for the posted rx bufs refcount to become zero handles everything   */
 	conn->ib_conn->post_recv_buf_count--;
 
-	if (rx_dma == ib_conn->login_dma)
+	if (rx_dma == ib_conn->login_resp_dma)
 		return;
 
 	outstanding = ib_conn->post_recv_buf_count;
diff -druNp linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iser_verbs.c linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iser_verbs.c
--- linux-libre-3.1-gnu1/drivers/infiniband/ulp/iser/iser_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/infiniband/ulp/iser/iser_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struc
 {
 	struct iser_device	*device;
 	struct ib_qp_init_attr	init_attr;
-	int			ret = -ENOMEM;
+	int			req_err, resp_err, ret = -ENOMEM;
 	struct ib_fmr_pool_param params;
 
 	BUG_ON(ib_conn->device == NULL);
 
 	device = ib_conn->device;
 
-	ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL);
+	ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
+					ISER_RX_LOGIN_SIZE, GFP_KERNEL);
 	if (!ib_conn->login_buf)
 		goto out_err;
 
-	ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
-				(void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
-				DMA_FROM_DEVICE);
+	ib_conn->login_req_buf  = ib_conn->login_buf;
+	ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
+
+	ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
+				(void *)ib_conn->login_req_buf,
+				ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+
+	ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
+				(void *)ib_conn->login_resp_buf,
+				ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+
+	req_err  = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma);
+	resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma);
+
+	if (req_err || resp_err) {
+		if (req_err)
+			ib_conn->login_req_dma = 0;
+		if (resp_err)
+			ib_conn->login_resp_dma = 0;
+		goto out_err;
+	}
 
 	ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
 				    (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib
 	struct ib_sge	  sge;
 	int ib_ret;
 
-	sge.addr   = ib_conn->login_dma;
+	sge.addr   = ib_conn->login_resp_dma;
 	sge.length = ISER_RX_LOGIN_SIZE;
 	sge.lkey   = ib_conn->device->mr->lkey;
 
-	rx_wr.wr_id   = (unsigned long)ib_conn->login_buf;
+	rx_wr.wr_id   = (unsigned long)ib_conn->login_resp_buf;
 	rx_wr.sg_list = &sge;
 	rx_wr.num_sge = 1;
 	rx_wr.next    = NULL;
diff -druNp linux-libre-3.1-gnu1/drivers/input/ff-core.c linux-libre-3.2-gnu1/drivers/input/ff-core.c
--- linux-libre-3.1-gnu1/drivers/input/ff-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/ff-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,9 +309,10 @@ EXPORT_SYMBOL_GPL(input_ff_event);
  * Once ff device is created you need to setup its upload, erase,
  * playback and other handlers before registering input device
  */
-int input_ff_create(struct input_dev *dev, int max_effects)
+int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 {
 	struct ff_device *ff;
+	size_t ff_dev_size;
 	int i;
 
 	if (!max_effects) {
@@ -319,8 +320,12 @@ int input_ff_create(struct input_dev *de
 		return -EINVAL;
 	}
 
-	ff = kzalloc(sizeof(struct ff_device) +
-		     max_effects * sizeof(struct file *), GFP_KERNEL);
+	ff_dev_size = sizeof(struct ff_device) +
+				max_effects * sizeof(struct file *);
+	if (ff_dev_size < max_effects) /* overflow */
+		return -EINVAL;
+
+	ff = kzalloc(ff_dev_size, GFP_KERNEL);
 	if (!ff)
 		return -ENOMEM;
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/input-compat.c linux-libre-3.2-gnu1/drivers/input/input-compat.c
--- linux-libre-3.1-gnu1/drivers/input/input-compat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/input-compat.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/export.h>
 #include <asm/uaccess.h>
 #include "input-compat.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/input-mt.c linux-libre-3.2-gnu1/drivers/input/input-mt.c
--- linux-libre-3.1-gnu1/drivers/input/input-mt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/input-mt.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/input/mt.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #define TRKID_SGN	((TRKID_MAX + 1) >> 1)
@@ -117,6 +118,7 @@ void input_mt_report_finger_count(struct
 	input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
 	input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
 	input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
+	input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5);
 }
 EXPORT_SYMBOL(input_mt_report_finger_count);
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/input-polldev.c linux-libre-3.2-gnu1/drivers/input/input-polldev.c
--- linux-libre-3.1-gnu1/drivers/input/input-polldev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/input-polldev.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <linux/input-polldev.h>
 
 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
@@ -49,8 +50,10 @@ static int input_open_polled_device(stru
 		dev->open(dev);
 
 	/* Only start polling if polling is enabled */
-	if (dev->poll_interval > 0)
-		queue_delayed_work(system_freezable_wq, &dev->work, 0);
+	if (dev->poll_interval > 0) {
+		dev->poll(dev);
+		input_polldev_queue_work(dev);
+	}
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/input/joystick/as5011.c linux-libre-3.2-gnu1/drivers/input/joystick/as5011.c
--- linux-libre-3.1-gnu1/drivers/input/joystick/as5011.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/joystick/as5011.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/input/as5011.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
 #define MODULE_DEVICE_ALIAS "as5011"
diff -druNp linux-libre-3.1-gnu1/drivers/input/Kconfig linux-libre-3.2-gnu1/drivers/input/Kconfig
--- linux-libre-3.1-gnu1/drivers/input/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 menu "Input device support"
-	depends on !S390
+	depends on !S390 && !UML
 
 config INPUT
 	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/adp5588-keys.c linux-libre-3.2-gnu1/drivers/input/keyboard/adp5588-keys.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/adp5588-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/adp5588-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -550,7 +550,7 @@ static int __devinit adp5588_probe(struc
 	}
 
 	error = request_irq(client->irq, adp5588_irq,
-			    IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+			    IRQF_TRIGGER_FALLING,
 			    client->dev.driver->name, kpad);
 	if (error) {
 		dev_err(&client->dev, "irq %d busy?\n", client->irq);
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/adp5589-keys.c linux-libre-3.2-gnu1/drivers/input/keyboard/adp5589-keys.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/adp5589-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/adp5589-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Description:  keypad driver for ADP5589
+ * Description:  keypad driver for ADP5589, ADP5585
  *		 I2C QWERTY Keypad and IO Expander
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
@@ -22,35 +22,165 @@
 
 #include <linux/input/adp5589.h>
 
+/* ADP5589/ADP5585 Common Registers */
+#define ADP5589_5_ID			0x00
+#define ADP5589_5_INT_STATUS		0x01
+#define ADP5589_5_STATUS		0x02
+#define ADP5589_5_FIFO_1		0x03
+#define ADP5589_5_FIFO_2		0x04
+#define ADP5589_5_FIFO_3		0x05
+#define ADP5589_5_FIFO_4		0x06
+#define ADP5589_5_FIFO_5		0x07
+#define ADP5589_5_FIFO_6		0x08
+#define ADP5589_5_FIFO_7		0x09
+#define ADP5589_5_FIFO_8		0x0A
+#define ADP5589_5_FIFO_9		0x0B
+#define ADP5589_5_FIFO_10		0x0C
+#define ADP5589_5_FIFO_11		0x0D
+#define ADP5589_5_FIFO_12		0x0E
+#define ADP5589_5_FIFO_13		0x0F
+#define ADP5589_5_FIFO_14		0x10
+#define ADP5589_5_FIFO_15		0x11
+#define ADP5589_5_FIFO_16		0x12
+#define ADP5589_5_GPI_INT_STAT_A	0x13
+#define ADP5589_5_GPI_INT_STAT_B	0x14
+
+/* ADP5589 Registers */
+#define ADP5589_GPI_INT_STAT_C		0x15
+#define ADP5589_GPI_STATUS_A		0x16
+#define ADP5589_GPI_STATUS_B		0x17
+#define ADP5589_GPI_STATUS_C		0x18
+#define ADP5589_RPULL_CONFIG_A		0x19
+#define ADP5589_RPULL_CONFIG_B		0x1A
+#define ADP5589_RPULL_CONFIG_C		0x1B
+#define ADP5589_RPULL_CONFIG_D		0x1C
+#define ADP5589_RPULL_CONFIG_E		0x1D
+#define ADP5589_GPI_INT_LEVEL_A		0x1E
+#define ADP5589_GPI_INT_LEVEL_B		0x1F
+#define ADP5589_GPI_INT_LEVEL_C		0x20
+#define ADP5589_GPI_EVENT_EN_A		0x21
+#define ADP5589_GPI_EVENT_EN_B		0x22
+#define ADP5589_GPI_EVENT_EN_C		0x23
+#define ADP5589_GPI_INTERRUPT_EN_A	0x24
+#define ADP5589_GPI_INTERRUPT_EN_B	0x25
+#define ADP5589_GPI_INTERRUPT_EN_C	0x26
+#define ADP5589_DEBOUNCE_DIS_A		0x27
+#define ADP5589_DEBOUNCE_DIS_B		0x28
+#define ADP5589_DEBOUNCE_DIS_C		0x29
+#define ADP5589_GPO_DATA_OUT_A		0x2A
+#define ADP5589_GPO_DATA_OUT_B		0x2B
+#define ADP5589_GPO_DATA_OUT_C		0x2C
+#define ADP5589_GPO_OUT_MODE_A		0x2D
+#define ADP5589_GPO_OUT_MODE_B		0x2E
+#define ADP5589_GPO_OUT_MODE_C		0x2F
+#define ADP5589_GPIO_DIRECTION_A	0x30
+#define ADP5589_GPIO_DIRECTION_B	0x31
+#define ADP5589_GPIO_DIRECTION_C	0x32
+#define ADP5589_UNLOCK1			0x33
+#define ADP5589_UNLOCK2			0x34
+#define ADP5589_EXT_LOCK_EVENT		0x35
+#define ADP5589_UNLOCK_TIMERS		0x36
+#define ADP5589_LOCK_CFG		0x37
+#define ADP5589_RESET1_EVENT_A		0x38
+#define ADP5589_RESET1_EVENT_B		0x39
+#define ADP5589_RESET1_EVENT_C		0x3A
+#define ADP5589_RESET2_EVENT_A		0x3B
+#define ADP5589_RESET2_EVENT_B		0x3C
+#define ADP5589_RESET_CFG		0x3D
+#define ADP5589_PWM_OFFT_LOW		0x3E
+#define ADP5589_PWM_OFFT_HIGH		0x3F
+#define ADP5589_PWM_ONT_LOW		0x40
+#define ADP5589_PWM_ONT_HIGH		0x41
+#define ADP5589_PWM_CFG			0x42
+#define ADP5589_CLOCK_DIV_CFG		0x43
+#define ADP5589_LOGIC_1_CFG		0x44
+#define ADP5589_LOGIC_2_CFG		0x45
+#define ADP5589_LOGIC_FF_CFG		0x46
+#define ADP5589_LOGIC_INT_EVENT_EN	0x47
+#define ADP5589_POLL_PTIME_CFG		0x48
+#define ADP5589_PIN_CONFIG_A		0x49
+#define ADP5589_PIN_CONFIG_B		0x4A
+#define ADP5589_PIN_CONFIG_C		0x4B
+#define ADP5589_PIN_CONFIG_D		0x4C
+#define ADP5589_GENERAL_CFG		0x4D
+#define ADP5589_INT_EN			0x4E
+
+/* ADP5585 Registers */
+#define ADP5585_GPI_STATUS_A		0x15
+#define ADP5585_GPI_STATUS_B		0x16
+#define ADP5585_RPULL_CONFIG_A		0x17
+#define ADP5585_RPULL_CONFIG_B		0x18
+#define ADP5585_RPULL_CONFIG_C		0x19
+#define ADP5585_RPULL_CONFIG_D		0x1A
+#define ADP5585_GPI_INT_LEVEL_A		0x1B
+#define ADP5585_GPI_INT_LEVEL_B		0x1C
+#define ADP5585_GPI_EVENT_EN_A		0x1D
+#define ADP5585_GPI_EVENT_EN_B		0x1E
+#define ADP5585_GPI_INTERRUPT_EN_A	0x1F
+#define ADP5585_GPI_INTERRUPT_EN_B	0x20
+#define ADP5585_DEBOUNCE_DIS_A		0x21
+#define ADP5585_DEBOUNCE_DIS_B		0x22
+#define ADP5585_GPO_DATA_OUT_A		0x23
+#define ADP5585_GPO_DATA_OUT_B		0x24
+#define ADP5585_GPO_OUT_MODE_A		0x25
+#define ADP5585_GPO_OUT_MODE_B		0x26
+#define ADP5585_GPIO_DIRECTION_A	0x27
+#define ADP5585_GPIO_DIRECTION_B	0x28
+#define ADP5585_RESET1_EVENT_A		0x29
+#define ADP5585_RESET1_EVENT_B		0x2A
+#define ADP5585_RESET1_EVENT_C		0x2B
+#define ADP5585_RESET2_EVENT_A		0x2C
+#define ADP5585_RESET2_EVENT_B		0x2D
+#define ADP5585_RESET_CFG		0x2E
+#define ADP5585_PWM_OFFT_LOW		0x2F
+#define ADP5585_PWM_OFFT_HIGH		0x30
+#define ADP5585_PWM_ONT_LOW		0x31
+#define ADP5585_PWM_ONT_HIGH		0x32
+#define ADP5585_PWM_CFG			0x33
+#define ADP5585_LOGIC_CFG		0x34
+#define ADP5585_LOGIC_FF_CFG		0x35
+#define ADP5585_LOGIC_INT_EVENT_EN	0x36
+#define ADP5585_POLL_PTIME_CFG		0x37
+#define ADP5585_PIN_CONFIG_A		0x38
+#define ADP5585_PIN_CONFIG_B		0x39
+#define ADP5585_PIN_CONFIG_D		0x3A
+#define ADP5585_GENERAL_CFG		0x3B
+#define ADP5585_INT_EN			0x3C
+
+/* ID Register */
+#define ADP5589_5_DEVICE_ID_MASK	0xF
+#define ADP5589_5_MAN_ID_MASK		0xF
+#define ADP5589_5_MAN_ID_SHIFT		4
+#define ADP5589_5_MAN_ID		0x02
+
 /* GENERAL_CFG Register */
 #define OSC_EN		(1 << 7)
 #define CORE_CLK(x)	(((x) & 0x3) << 5)
-#define LCK_TRK_LOGIC	(1 << 4)
-#define LCK_TRK_GPI	(1 << 3)
+#define LCK_TRK_LOGIC	(1 << 4)	/* ADP5589 only */
+#define LCK_TRK_GPI	(1 << 3)	/* ADP5589 only */
 #define INT_CFG		(1 << 1)
 #define RST_CFG		(1 << 0)
 
 /* INT_EN Register */
-#define LOGIC2_IEN	(1 << 5)
+#define LOGIC2_IEN	(1 << 5)	/* ADP5589 only */
 #define LOGIC1_IEN	(1 << 4)
-#define LOCK_IEN	(1 << 3)
+#define LOCK_IEN	(1 << 3)	/* ADP5589 only */
 #define OVRFLOW_IEN	(1 << 2)
 #define GPI_IEN		(1 << 1)
 #define EVENT_IEN	(1 << 0)
 
 /* Interrupt Status Register */
-#define LOGIC2_INT	(1 << 5)
+#define LOGIC2_INT	(1 << 5)	/* ADP5589 only */
 #define LOGIC1_INT	(1 << 4)
-#define LOCK_INT	(1 << 3)
+#define LOCK_INT	(1 << 3)	/* ADP5589 only */
 #define OVRFLOW_INT	(1 << 2)
 #define GPI_INT		(1 << 1)
 #define EVENT_INT	(1 << 0)
 
 /* STATUS Register */
-
-#define LOGIC2_STAT	(1 << 7)
+#define LOGIC2_STAT	(1 << 7)	/* ADP5589 only */
 #define LOGIC1_STAT	(1 << 6)
-#define LOCK_STAT	(1 << 5)
+#define LOCK_STAT	(1 << 5)	/* ADP5589 only */
 #define KEC		0xF
 
 /* PIN_CONFIG_D Register */
@@ -61,27 +191,54 @@
 #define LOCK_EN		(1 << 0)
 
 #define PTIME_MASK	0x3
-#define LTIME_MASK	0x3
+#define LTIME_MASK	0x3		/* ADP5589 only */
 
 /* Key Event Register xy */
 #define KEY_EV_PRESSED		(1 << 7)
 #define KEY_EV_MASK		(0x7F)
 
 #define KEYP_MAX_EVENT		16
+#define ADP5589_MAXGPIO		19
+#define ADP5585_MAXGPIO		11 /* 10 on the ADP5585-01, 11 on ADP5585-02 */
 
-#define MAXGPIO			19
-#define ADP_BANK(offs)		((offs) >> 3)
-#define ADP_BIT(offs)		(1u << ((offs) & 0x7))
+enum {
+	ADP5589,
+	ADP5585_01,
+	ADP5585_02
+};
+
+struct adp_constants {
+	u8 maxgpio;
+	u8 keymapsize;
+	u8 gpi_pin_row_base;
+	u8 gpi_pin_row_end;
+	u8 gpi_pin_col_base;
+	u8 gpi_pin_base;
+	u8 gpi_pin_end;
+	u8 gpimapsize_max;
+	u8 max_row_num;
+	u8 max_col_num;
+	u8 row_mask;
+	u8 col_mask;
+	u8 col_shift;
+	u8 c4_extend_cfg;
+	u8 (*bank) (u8 offset);
+	u8 (*bit) (u8 offset);
+	u8 (*reg) (u8 reg);
+};
 
 struct adp5589_kpad {
 	struct i2c_client *client;
 	struct input_dev *input;
+	const struct adp_constants *var;
 	unsigned short keycode[ADP5589_KEYMAPSIZE];
 	const struct adp5589_gpi_map *gpimap;
 	unsigned short gpimapsize;
 	unsigned extend_cfg;
+	bool is_adp5585;
+	bool adp5585_support_row5;
 #ifdef CONFIG_GPIOLIB
-	unsigned char gpiomap[MAXGPIO];
+	unsigned char gpiomap[ADP5589_MAXGPIO];
 	bool export_gpio;
 	struct gpio_chip gc;
 	struct mutex gpio_lock;	/* Protect cached dir, dat_out */
@@ -90,6 +247,129 @@ struct adp5589_kpad {
 #endif
 };
 
+/*
+ *  ADP5589 / ADP5585 derivative / variant handling
+ */
+
+
+/* ADP5589 */
+
+static unsigned char adp5589_bank(unsigned char offset)
+{
+	return offset >> 3;
+}
+
+static unsigned char adp5589_bit(unsigned char offset)
+{
+	return 1u << (offset & 0x7);
+}
+
+static unsigned char adp5589_reg(unsigned char reg)
+{
+	return reg;
+}
+
+static const struct adp_constants const_adp5589 = {
+	.maxgpio		= ADP5589_MAXGPIO,
+	.keymapsize		= ADP5589_KEYMAPSIZE,
+	.gpi_pin_row_base	= ADP5589_GPI_PIN_ROW_BASE,
+	.gpi_pin_row_end	= ADP5589_GPI_PIN_ROW_END,
+	.gpi_pin_col_base	= ADP5589_GPI_PIN_COL_BASE,
+	.gpi_pin_base		= ADP5589_GPI_PIN_BASE,
+	.gpi_pin_end		= ADP5589_GPI_PIN_END,
+	.gpimapsize_max		= ADP5589_GPIMAPSIZE_MAX,
+	.c4_extend_cfg		= 12,
+	.max_row_num		= ADP5589_MAX_ROW_NUM,
+	.max_col_num		= ADP5589_MAX_COL_NUM,
+	.row_mask		= ADP5589_ROW_MASK,
+	.col_mask		= ADP5589_COL_MASK,
+	.col_shift		= ADP5589_COL_SHIFT,
+	.bank			= adp5589_bank,
+	.bit			= adp5589_bit,
+	.reg			= adp5589_reg,
+};
+
+/* ADP5585 */
+
+static unsigned char adp5585_bank(unsigned char offset)
+{
+	return offset > ADP5585_MAX_ROW_NUM;
+}
+
+static unsigned char adp5585_bit(unsigned char offset)
+{
+	return (offset > ADP5585_MAX_ROW_NUM) ?
+		1u << (offset - ADP5585_COL_SHIFT) : 1u << offset;
+}
+
+static const unsigned char adp5585_reg_lut[] = {
+	[ADP5589_GPI_STATUS_A]		= ADP5585_GPI_STATUS_A,
+	[ADP5589_GPI_STATUS_B]		= ADP5585_GPI_STATUS_B,
+	[ADP5589_RPULL_CONFIG_A]	= ADP5585_RPULL_CONFIG_A,
+	[ADP5589_RPULL_CONFIG_B]	= ADP5585_RPULL_CONFIG_B,
+	[ADP5589_RPULL_CONFIG_C]	= ADP5585_RPULL_CONFIG_C,
+	[ADP5589_RPULL_CONFIG_D]	= ADP5585_RPULL_CONFIG_D,
+	[ADP5589_GPI_INT_LEVEL_A]	= ADP5585_GPI_INT_LEVEL_A,
+	[ADP5589_GPI_INT_LEVEL_B]	= ADP5585_GPI_INT_LEVEL_B,
+	[ADP5589_GPI_EVENT_EN_A]	= ADP5585_GPI_EVENT_EN_A,
+	[ADP5589_GPI_EVENT_EN_B]	= ADP5585_GPI_EVENT_EN_B,
+	[ADP5589_GPI_INTERRUPT_EN_A]	= ADP5585_GPI_INTERRUPT_EN_A,
+	[ADP5589_GPI_INTERRUPT_EN_B]	= ADP5585_GPI_INTERRUPT_EN_B,
+	[ADP5589_DEBOUNCE_DIS_A]	= ADP5585_DEBOUNCE_DIS_A,
+	[ADP5589_DEBOUNCE_DIS_B]	= ADP5585_DEBOUNCE_DIS_B,
+	[ADP5589_GPO_DATA_OUT_A]	= ADP5585_GPO_DATA_OUT_A,
+	[ADP5589_GPO_DATA_OUT_B]	= ADP5585_GPO_DATA_OUT_B,
+	[ADP5589_GPO_OUT_MODE_A]	= ADP5585_GPO_OUT_MODE_A,
+	[ADP5589_GPO_OUT_MODE_B]	= ADP5585_GPO_OUT_MODE_B,
+	[ADP5589_GPIO_DIRECTION_A]	= ADP5585_GPIO_DIRECTION_A,
+	[ADP5589_GPIO_DIRECTION_B]	= ADP5585_GPIO_DIRECTION_B,
+	[ADP5589_RESET1_EVENT_A]	= ADP5585_RESET1_EVENT_A,
+	[ADP5589_RESET1_EVENT_B]	= ADP5585_RESET1_EVENT_B,
+	[ADP5589_RESET1_EVENT_C]	= ADP5585_RESET1_EVENT_C,
+	[ADP5589_RESET2_EVENT_A]	= ADP5585_RESET2_EVENT_A,
+	[ADP5589_RESET2_EVENT_B]	= ADP5585_RESET2_EVENT_B,
+	[ADP5589_RESET_CFG]		= ADP5585_RESET_CFG,
+	[ADP5589_PWM_OFFT_LOW]		= ADP5585_PWM_OFFT_LOW,
+	[ADP5589_PWM_OFFT_HIGH]		= ADP5585_PWM_OFFT_HIGH,
+	[ADP5589_PWM_ONT_LOW]		= ADP5585_PWM_ONT_LOW,
+	[ADP5589_PWM_ONT_HIGH]		= ADP5585_PWM_ONT_HIGH,
+	[ADP5589_PWM_CFG]		= ADP5585_PWM_CFG,
+	[ADP5589_LOGIC_1_CFG]		= ADP5585_LOGIC_CFG,
+	[ADP5589_LOGIC_FF_CFG]		= ADP5585_LOGIC_FF_CFG,
+	[ADP5589_LOGIC_INT_EVENT_EN]	= ADP5585_LOGIC_INT_EVENT_EN,
+	[ADP5589_POLL_PTIME_CFG]	= ADP5585_POLL_PTIME_CFG,
+	[ADP5589_PIN_CONFIG_A]		= ADP5585_PIN_CONFIG_A,
+	[ADP5589_PIN_CONFIG_B]		= ADP5585_PIN_CONFIG_B,
+	[ADP5589_PIN_CONFIG_D]		= ADP5585_PIN_CONFIG_D,
+	[ADP5589_GENERAL_CFG]		= ADP5585_GENERAL_CFG,
+	[ADP5589_INT_EN]		= ADP5585_INT_EN,
+};
+
+static unsigned char adp5585_reg(unsigned char reg)
+{
+	return adp5585_reg_lut[reg];
+}
+
+static const struct adp_constants const_adp5585 = {
+	.maxgpio		= ADP5585_MAXGPIO,
+	.keymapsize		= ADP5585_KEYMAPSIZE,
+	.gpi_pin_row_base	= ADP5585_GPI_PIN_ROW_BASE,
+	.gpi_pin_row_end	= ADP5585_GPI_PIN_ROW_END,
+	.gpi_pin_col_base	= ADP5585_GPI_PIN_COL_BASE,
+	.gpi_pin_base		= ADP5585_GPI_PIN_BASE,
+	.gpi_pin_end		= ADP5585_GPI_PIN_END,
+	.gpimapsize_max		= ADP5585_GPIMAPSIZE_MAX,
+	.c4_extend_cfg		= 10,
+	.max_row_num		= ADP5585_MAX_ROW_NUM,
+	.max_col_num		= ADP5585_MAX_COL_NUM,
+	.row_mask		= ADP5585_ROW_MASK,
+	.col_mask		= ADP5585_COL_MASK,
+	.col_shift		= ADP5585_COL_SHIFT,
+	.bank			= adp5585_bank,
+	.bit			= adp5585_bit,
+	.reg			= adp5585_reg,
+};
+
 static int adp5589_read(struct i2c_client *client, u8 reg)
 {
 	int ret = i2c_smbus_read_byte_data(client, reg);
@@ -109,19 +389,20 @@ static int adp5589_write(struct i2c_clie
 static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 
-	return !!(adp5589_read(kpad->client, ADP5589_GPI_STATUS_A + bank) &
-		  bit);
+	return !!(adp5589_read(kpad->client,
+			       kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
+			       bit);
 }
 
 static void adp5589_gpio_set_value(struct gpio_chip *chip,
 				   unsigned off, int val)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 
 	mutex_lock(&kpad->gpio_lock);
 
@@ -130,8 +411,8 @@ static void adp5589_gpio_set_value(struc
 	else
 		kpad->dat_out[bank] &= ~bit;
 
-	adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
-		      kpad->dat_out[bank]);
+	adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) +
+		      bank, kpad->dat_out[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
 }
@@ -139,14 +420,15 @@ static void adp5589_gpio_set_value(struc
 static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 	int ret;
 
 	mutex_lock(&kpad->gpio_lock);
 
 	kpad->dir[bank] &= ~bit;
-	ret = adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+	ret = adp5589_write(kpad->client,
+			    kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
 			    kpad->dir[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
@@ -158,8 +440,8 @@ static int adp5589_gpio_direction_output
 					 unsigned off, int val)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 	int ret;
 
 	mutex_lock(&kpad->gpio_lock);
@@ -171,9 +453,10 @@ static int adp5589_gpio_direction_output
 	else
 		kpad->dat_out[bank] &= ~bit;
 
-	ret = adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
-			    kpad->dat_out[bank]);
-	ret |= adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+	ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A)
+			    + bank, kpad->dat_out[bank]);
+	ret |= adp5589_write(kpad->client,
+			     kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
 			     kpad->dir[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
@@ -184,26 +467,29 @@ static int adp5589_gpio_direction_output
 static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
 				const struct adp5589_kpad_platform_data *pdata)
 {
-	bool pin_used[MAXGPIO];
+	bool pin_used[ADP5589_MAXGPIO];
 	int n_unused = 0;
 	int i;
 
 	memset(pin_used, false, sizeof(pin_used));
 
-	for (i = 0; i < MAXGPIO; i++)
+	for (i = 0; i < kpad->var->maxgpio; i++)
 		if (pdata->keypad_en_mask & (1 << i))
 			pin_used[i] = true;
 
 	for (i = 0; i < kpad->gpimapsize; i++)
-		pin_used[kpad->gpimap[i].pin - ADP5589_GPI_PIN_BASE] = true;
+		pin_used[kpad->gpimap[i].pin - kpad->var->gpi_pin_base] = true;
 
 	if (kpad->extend_cfg & R4_EXTEND_CFG)
 		pin_used[4] = true;
 
 	if (kpad->extend_cfg & C4_EXTEND_CFG)
-		pin_used[12] = true;
+		pin_used[kpad->var->c4_extend_cfg] = true;
 
-	for (i = 0; i < MAXGPIO; i++)
+	if (!kpad->adp5585_support_row5)
+		pin_used[5] = true;
+
+	for (i = 0; i < kpad->var->maxgpio; i++)
 		if (!pin_used[i])
 			kpad->gpiomap[n_unused++] = i;
 
@@ -246,11 +532,11 @@ static int __devinit adp5589_gpio_add(st
 		return error;
 	}
 
-	for (i = 0; i <= ADP_BANK(MAXGPIO); i++) {
-		kpad->dat_out[i] = adp5589_read(kpad->client,
-						ADP5589_GPO_DATA_OUT_A + i);
-		kpad->dir[i] = adp5589_read(kpad->client,
-					    ADP5589_GPIO_DIRECTION_A + i);
+	for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) {
+		kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg(
+						ADP5589_GPO_DATA_OUT_A) + i);
+		kpad->dir[i] = adp5589_read(kpad->client, kpad->var->reg(
+					    ADP5589_GPIO_DIRECTION_A) + i);
 	}
 
 	if (gpio_data->setup) {
@@ -317,11 +603,11 @@ static void adp5589_report_events(struct
 	int i;
 
 	for (i = 0; i < ev_cnt; i++) {
-		int key = adp5589_read(kpad->client, ADP5589_FIFO_1 + i);
+		int key = adp5589_read(kpad->client, ADP5589_5_FIFO_1 + i);
 		int key_val = key & KEY_EV_MASK;
 
-		if (key_val >= ADP5589_GPI_PIN_BASE &&
-		    key_val <= ADP5589_GPI_PIN_END) {
+		if (key_val >= kpad->var->gpi_pin_base &&
+		    key_val <= kpad->var->gpi_pin_end) {
 			adp5589_report_switches(kpad, key, key_val);
 		} else {
 			input_report_key(kpad->input,
@@ -337,29 +623,30 @@ static irqreturn_t adp5589_irq(int irq,
 	struct i2c_client *client = kpad->client;
 	int status, ev_cnt;
 
-	status = adp5589_read(client, ADP5589_INT_STATUS);
+	status = adp5589_read(client, ADP5589_5_INT_STATUS);
 
 	if (status & OVRFLOW_INT)	/* Unlikely and should never happen */
 		dev_err(&client->dev, "Event Overflow Error\n");
 
 	if (status & EVENT_INT) {
-		ev_cnt = adp5589_read(client, ADP5589_STATUS) & KEC;
+		ev_cnt = adp5589_read(client, ADP5589_5_STATUS) & KEC;
 		if (ev_cnt) {
 			adp5589_report_events(kpad, ev_cnt);
 			input_sync(kpad->input);
 		}
 	}
 
-	adp5589_write(client, ADP5589_INT_STATUS, status);	/* Status is W1C */
+	adp5589_write(client, ADP5589_5_INT_STATUS, status); /* Status is W1C */
 
 	return IRQ_HANDLED;
 }
 
-static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key)
+static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
+					unsigned short key)
 {
 	int i;
 
-	for (i = 0; i < ADP5589_KEYMAPSIZE; i++)
+	for (i = 0; i < kpad->var->keymapsize; i++)
 		if (key == kpad->keycode[i])
 			return (i + 1) | KEY_EV_PRESSED;
 
@@ -372,19 +659,23 @@ static int __devinit adp5589_setup(struc
 {
 	struct i2c_client *client = kpad->client;
 	const struct adp5589_kpad_platform_data *pdata =
-	    client->dev.platform_data;
-	int i, ret;
+		client->dev.platform_data;
+	u8 (*reg) (u8) = kpad->var->reg;
 	unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
 	unsigned char pull_mask = 0;
+	int i, ret;
 
-	ret = adp5589_write(client, ADP5589_PIN_CONFIG_A,
-			    pdata->keypad_en_mask & 0xFF);
-	ret |= adp5589_write(client, ADP5589_PIN_CONFIG_B,
-			     (pdata->keypad_en_mask >> 8) & 0xFF);
-	ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
-			     (pdata->keypad_en_mask >> 16) & 0xFF);
+	ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A),
+			    pdata->keypad_en_mask & kpad->var->row_mask);
+	ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B),
+			     (pdata->keypad_en_mask >> kpad->var->col_shift) &
+			     kpad->var->col_mask);
 
-	if (pdata->en_keylock) {
+	if (!kpad->is_adp5585)
+		ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
+				     (pdata->keypad_en_mask >> 16) & 0xFF);
+
+	if (!kpad->is_adp5585 && pdata->en_keylock) {
 		ret |= adp5589_write(client, ADP5589_UNLOCK1,
 				     pdata->unlock_key1);
 		ret |= adp5589_write(client, ADP5589_UNLOCK2,
@@ -395,96 +686,130 @@ static int __devinit adp5589_setup(struc
 	}
 
 	for (i = 0; i < KEYP_MAX_EVENT; i++)
-		ret |= adp5589_read(client, ADP5589_FIFO_1 + i);
+		ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i);
 
 	for (i = 0; i < pdata->gpimapsize; i++) {
 		unsigned short pin = pdata->gpimap[i].pin;
 
-		if (pin <= ADP5589_GPI_PIN_ROW_END) {
-			evt_mode1 |= (1 << (pin - ADP5589_GPI_PIN_ROW_BASE));
+		if (pin <= kpad->var->gpi_pin_row_end) {
+			evt_mode1 |= (1 << (pin - kpad->var->gpi_pin_row_base));
 		} else {
 			evt_mode2 |=
-			    ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) & 0xFF);
-			evt_mode3 |=
-			    ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) >> 8);
+			    ((1 << (pin - kpad->var->gpi_pin_col_base)) & 0xFF);
+			if (!kpad->is_adp5585)
+				evt_mode3 |= ((1 << (pin -
+					kpad->var->gpi_pin_col_base)) >> 8);
 		}
 	}
 
 	if (pdata->gpimapsize) {
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_A, evt_mode1);
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_B, evt_mode2);
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_C, evt_mode3);
+		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A),
+				     evt_mode1);
+		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B),
+				     evt_mode2);
+		if (!kpad->is_adp5585)
+			ret |= adp5589_write(client,
+					     reg(ADP5589_GPI_EVENT_EN_C),
+					     evt_mode3);
 	}
 
 	if (pdata->pull_dis_mask & pdata->pullup_en_100k &
-	    pdata->pullup_en_300k & pdata->pulldown_en_300k)
+		pdata->pullup_en_300k & pdata->pulldown_en_300k)
 		dev_warn(&client->dev, "Conflicting pull resistor config\n");
 
-	for (i = 0; i < MAXGPIO; i++) {
-		unsigned val = 0;
+	for (i = 0; i <= kpad->var->max_row_num; i++) {
+		unsigned val = 0, bit = (1 << i);
+		if (pdata->pullup_en_300k & bit)
+			val = 0;
+		else if (pdata->pulldown_en_300k & bit)
+			val = 1;
+		else if (pdata->pullup_en_100k & bit)
+			val = 2;
+		else if (pdata->pull_dis_mask & bit)
+			val = 3;
 
-		if (pdata->pullup_en_300k & (1 << i))
+		pull_mask |= val << (2 * (i & 0x3));
+
+		if (i == 3 || i == kpad->var->max_row_num) {
+			ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A)
+					     + (i >> 2), pull_mask);
+			pull_mask = 0;
+		}
+	}
+
+	for (i = 0; i <= kpad->var->max_col_num; i++) {
+		unsigned val = 0, bit = 1 << (i + kpad->var->col_shift);
+		if (pdata->pullup_en_300k & bit)
 			val = 0;
-		else if (pdata->pulldown_en_300k & (1 << i))
+		else if (pdata->pulldown_en_300k & bit)
 			val = 1;
-		else if (pdata->pullup_en_100k & (1 << i))
+		else if (pdata->pullup_en_100k & bit)
 			val = 2;
-		else if (pdata->pull_dis_mask & (1 << i))
+		else if (pdata->pull_dis_mask & bit)
 			val = 3;
 
 		pull_mask |= val << (2 * (i & 0x3));
 
-		if ((i & 0x3) == 0x3 || i == MAXGPIO - 1) {
+		if (i == 3 || i == kpad->var->max_col_num) {
 			ret |= adp5589_write(client,
-					     ADP5589_RPULL_CONFIG_A + (i >> 2),
-					     pull_mask);
+					     reg(ADP5585_RPULL_CONFIG_C) +
+					     (i >> 2), pull_mask);
 			pull_mask = 0;
 		}
 	}
 
 	if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) {
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_A,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_1));
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_B,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_2));
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_C,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_3));
 		kpad->extend_cfg |= R4_EXTEND_CFG;
 	}
 
 	if (pdata->reset2_key_1 && pdata->reset2_key_2) {
-		ret |= adp5589_write(client, ADP5589_RESET2_EVENT_A,
+		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A),
 				     adp5589_get_evcode(kpad,
 							pdata->reset2_key_1));
-		ret |= adp5589_write(client, ADP5589_RESET2_EVENT_B,
+		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B),
 				     adp5589_get_evcode(kpad,
 							pdata->reset2_key_2));
 		kpad->extend_cfg |= C4_EXTEND_CFG;
 	}
 
 	if (kpad->extend_cfg) {
-		ret |= adp5589_write(client, ADP5589_RESET_CFG,
+		ret |= adp5589_write(client, reg(ADP5589_RESET_CFG),
 				     pdata->reset_cfg);
-		ret |= adp5589_write(client, ADP5589_PIN_CONFIG_D,
+		ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D),
 				     kpad->extend_cfg);
 	}
 
-	for (i = 0; i <= ADP_BANK(MAXGPIO); i++)
-		ret |= adp5589_write(client, ADP5589_DEBOUNCE_DIS_A + i,
-				     pdata->debounce_dis_mask >> (i * 8));
+	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A),
+			    pdata->debounce_dis_mask & kpad->var->row_mask);
 
-	ret |= adp5589_write(client, ADP5589_POLL_PTIME_CFG,
+	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B),
+			     (pdata->debounce_dis_mask >> kpad->var->col_shift)
+			     & kpad->var->col_mask);
+
+	if (!kpad->is_adp5585)
+		ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C),
+				     (pdata->debounce_dis_mask >> 16) & 0xFF);
+
+	ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG),
 			     pdata->scan_cycle_time & PTIME_MASK);
-	ret |= adp5589_write(client, ADP5589_INT_STATUS, LOGIC2_INT |
-			     LOGIC1_INT | OVRFLOW_INT | LOCK_INT |
+	ret |= adp5589_write(client, ADP5589_5_INT_STATUS,
+			     (kpad->is_adp5585 ? 0 : LOGIC2_INT) |
+			     LOGIC1_INT | OVRFLOW_INT |
+			     (kpad->is_adp5585 ? 0 : LOCK_INT) |
 			     GPI_INT | EVENT_INT);	/* Status is W1C */
 
-	ret |= adp5589_write(client, ADP5589_GENERAL_CFG,
+	ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG),
 			     INT_CFG | OSC_EN | CORE_CLK(3));
-	ret |= adp5589_write(client, ADP5589_INT_EN,
+	ret |= adp5589_write(client, reg(ADP5589_INT_EN),
 			     OVRFLOW_IEN | GPI_IEN | EVENT_IEN);
 
 	if (ret < 0) {
@@ -497,30 +822,33 @@ static int __devinit adp5589_setup(struc
 
 static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
 {
-	int gpi_stat1 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_A);
-	int gpi_stat2 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_B);
-	int gpi_stat3 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_C);
 	int gpi_stat_tmp, pin_loc;
 	int i;
+	int gpi_stat1 = adp5589_read(kpad->client,
+				     kpad->var->reg(ADP5589_GPI_STATUS_A));
+	int gpi_stat2 = adp5589_read(kpad->client,
+				     kpad->var->reg(ADP5589_GPI_STATUS_B));
+	int gpi_stat3 = !kpad->is_adp5585 ?
+			adp5589_read(kpad->client, ADP5589_GPI_STATUS_C) : 0;
 
 	for (i = 0; i < kpad->gpimapsize; i++) {
 		unsigned short pin = kpad->gpimap[i].pin;
 
-		if (pin <= ADP5589_GPI_PIN_ROW_END) {
+		if (pin <= kpad->var->gpi_pin_row_end) {
 			gpi_stat_tmp = gpi_stat1;
-			pin_loc = pin - ADP5589_GPI_PIN_ROW_BASE;
-		} else if ((pin - ADP5589_GPI_PIN_COL_BASE) < 8) {
+			pin_loc = pin - kpad->var->gpi_pin_row_base;
+		} else if ((pin - kpad->var->gpi_pin_col_base) < 8) {
 			gpi_stat_tmp = gpi_stat2;
-			pin_loc = pin - ADP5589_GPI_PIN_COL_BASE;
+			pin_loc = pin - kpad->var->gpi_pin_col_base;
 		} else {
 			gpi_stat_tmp = gpi_stat3;
-			pin_loc = pin - ADP5589_GPI_PIN_COL_BASE - 8;
+			pin_loc = pin - kpad->var->gpi_pin_col_base - 8;
 		}
 
 		if (gpi_stat_tmp < 0) {
 			dev_err(&kpad->client->dev,
-				"Can't read GPIO_DAT_STAT switch"
-				" %d default to OFF\n", pin);
+				"Can't read GPIO_DAT_STAT switch %d, default to OFF\n",
+				pin);
 			gpi_stat_tmp = 0;
 		}
 
@@ -536,7 +864,8 @@ static int __devinit adp5589_probe(struc
 				   const struct i2c_device_id *id)
 {
 	struct adp5589_kpad *kpad;
-	const struct adp5589_kpad_platform_data *pdata;
+	const struct adp5589_kpad_platform_data *pdata =
+		client->dev.platform_data;
 	struct input_dev *input;
 	unsigned int revid;
 	int ret, i;
@@ -548,56 +877,79 @@ static int __devinit adp5589_probe(struc
 		return -EIO;
 	}
 
-	pdata = client->dev.platform_data;
 	if (!pdata) {
 		dev_err(&client->dev, "no platform data?\n");
 		return -EINVAL;
 	}
 
-	if (!((pdata->keypad_en_mask & 0xFF) &&
-			(pdata->keypad_en_mask >> 8)) || !pdata->keymap) {
+	kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
+	if (!kpad)
+		return -ENOMEM;
+
+	switch (id->driver_data) {
+	case ADP5585_02:
+		kpad->adp5585_support_row5 = true;
+	case ADP5585_01:
+		kpad->is_adp5585 = true;
+		kpad->var = &const_adp5585;
+		break;
+	case ADP5589:
+		kpad->var = &const_adp5589;
+		break;
+	}
+
+	if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
+			(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
+			!pdata->keymap) {
 		dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	if (pdata->keymapsize != ADP5589_KEYMAPSIZE) {
+	if (pdata->keymapsize != kpad->var->keymapsize) {
 		dev_err(&client->dev, "invalid keymapsize\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
 	if (!pdata->gpimap && pdata->gpimapsize) {
 		dev_err(&client->dev, "invalid gpimap from pdata\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	if (pdata->gpimapsize > ADP5589_GPIMAPSIZE_MAX) {
+	if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
 		dev_err(&client->dev, "invalid gpimapsize\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
 	for (i = 0; i < pdata->gpimapsize; i++) {
 		unsigned short pin = pdata->gpimap[i].pin;
 
-		if (pin < ADP5589_GPI_PIN_BASE || pin > ADP5589_GPI_PIN_END) {
+		if (pin < kpad->var->gpi_pin_base ||
+				pin > kpad->var->gpi_pin_end) {
 			dev_err(&client->dev, "invalid gpi pin data\n");
-			return -EINVAL;
+			error = -EINVAL;
+			goto err_free_mem;
 		}
 
-		if ((1 << (pin - ADP5589_GPI_PIN_ROW_BASE)) &
+		if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
 				pdata->keypad_en_mask) {
 			dev_err(&client->dev, "invalid gpi row/col data\n");
-			return -EINVAL;
+			error = -EINVAL;
+			goto err_free_mem;
 		}
 	}
 
 	if (!client->irq) {
 		dev_err(&client->dev, "no IRQ?\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
 	input = input_allocate_device();
-	if (!kpad || !input) {
+	if (!input) {
 		error = -ENOMEM;
 		goto err_free_mem;
 	}
@@ -605,13 +957,13 @@ static int __devinit adp5589_probe(struc
 	kpad->client = client;
 	kpad->input = input;
 
-	ret = adp5589_read(client, ADP5589_ID);
+	ret = adp5589_read(client, ADP5589_5_ID);
 	if (ret < 0) {
 		error = ret;
-		goto err_free_mem;
+		goto err_free_input;
 	}
 
-	revid = (u8) ret & ADP5589_DEVICE_ID_MASK;
+	revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
 
 	input->name = client->name;
 	input->phys = "adp5589-keys/input0";
@@ -652,7 +1004,7 @@ static int __devinit adp5589_probe(struc
 	error = input_register_device(input);
 	if (error) {
 		dev_err(&client->dev, "unable to register input device\n");
-		goto err_free_mem;
+		goto err_free_input;
 	}
 
 	error = request_threaded_irq(client->irq, NULL, adp5589_irq,
@@ -685,8 +1037,9 @@ err_free_irq:
 err_unreg_dev:
 	input_unregister_device(input);
 	input = NULL;
-err_free_mem:
+err_free_input:
 	input_free_device(input);
+err_free_mem:
 	kfree(kpad);
 
 	return error;
@@ -696,7 +1049,7 @@ static int __devexit adp5589_remove(stru
 {
 	struct adp5589_kpad *kpad = i2c_get_clientdata(client);
 
-	adp5589_write(client, ADP5589_GENERAL_CFG, 0);
+	adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
 	free_irq(client->irq, kpad);
 	input_unregister_device(kpad->input);
 	adp5589_gpio_remove(kpad);
@@ -736,7 +1089,9 @@ static int adp5589_resume(struct device
 static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
 
 static const struct i2c_device_id adp5589_id[] = {
-	{"adp5589-keys", 0},
+	{"adp5589-keys", ADP5589},
+	{"adp5585-keys", ADP5585_01},
+	{"adp5585-02-keys", ADP5585_02}, /* Adds ROW5 to ADP5585 */
 	{}
 };
 
@@ -767,4 +1122,4 @@ module_exit(adp5589_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("ADP5589 Keypad driver");
+MODULE_DESCRIPTION("ADP5589/ADP5585 Keypad driver");
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/davinci_keyscan.c linux-libre-3.2-gnu1/drivers/input/keyboard/davinci_keyscan.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/davinci_keyscan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/davinci_keyscan.c	2012-01-04 18:55:44.000000000 -0500
@@ -271,7 +271,7 @@ static int __init davinci_ks_probe(struc
 	}
 
 	error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
-			  IRQF_DISABLED, pdev->name, davinci_ks);
+			  0, pdev->name, davinci_ks);
 	if (error < 0) {
 		dev_err(dev, "unable to register davinci key scan interrupt\n");
 		goto fail5;
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/ep93xx_keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/ep93xx_keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/ep93xx_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/ep93xx_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@ static int __devinit ep93xx_keypad_probe
 	platform_set_drvdata(pdev, keypad);
 
 	err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
-			  IRQF_DISABLED, pdev->name, keypad);
+			  0, pdev->name, keypad);
 	if (err)
 		goto failed_free_dev;
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/gpio_keys.c linux-libre-3.2-gnu1/drivers/input/keyboard/gpio_keys.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/gpio_keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/gpio_keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -461,8 +461,7 @@ static int gpio_keys_get_devtree_pdata(s
 	struct device_node *node, *pp;
 	int i;
 	struct gpio_keys_button *buttons;
-	const u32 *reg;
-	int len;
+	u32 reg;
 
 	node = dev->of_node;
 	if (node == NULL)
@@ -470,7 +469,7 @@ static int gpio_keys_get_devtree_pdata(s
 
 	memset(pdata, 0, sizeof *pdata);
 
-	pdata->rep = !!of_get_property(node, "autorepeat", &len);
+	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
 
 	/* First count the subnodes */
 	pdata->nbuttons = 0;
@@ -498,22 +497,25 @@ static int gpio_keys_get_devtree_pdata(s
 		buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
 		buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-		reg = of_get_property(pp, "linux,code", &len);
-		if (!reg) {
+		if (of_property_read_u32(pp, "linux,code", &reg)) {
 			dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
 			goto out_fail;
 		}
-		buttons[i].code = be32_to_cpup(reg);
+		buttons[i].code = reg;
 
-		buttons[i].desc = of_get_property(pp, "label", &len);
+		buttons[i].desc = of_get_property(pp, "label", NULL);
 
-		reg = of_get_property(pp, "linux,input-type", &len);
-		buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+		if (of_property_read_u32(pp, "linux,input-type", &reg) == 0)
+			buttons[i].type = reg;
+		else
+			buttons[i].type = EV_KEY;
 
 		buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
 
-		reg = of_get_property(pp, "debounce-interval", &len);
-		buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+		if (of_property_read_u32(pp, "debounce-interval", &reg) == 0)
+			buttons[i].debounce_interval = reg;
+		else
+			buttons[i].debounce_interval = 5;
 
 		i++;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/imx_keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/imx_keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/imx_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/imx_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -510,7 +510,7 @@ static int __devinit imx_keypad_probe(st
 	/* Ensure that the keypad will stay dormant until opened */
 	imx_keypad_inhibit(keypad);
 
-	error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED,
+	error = request_irq(irq, imx_keypad_irq_handler, 0,
 			    pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
@@ -567,10 +567,54 @@ static int __devexit imx_keypad_remove(s
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int imx_kbd_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_keypad *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input_dev;
+
+	/* imx kbd can wake up system even clock is disabled */
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		clk_disable(kbd->clk);
+
+	mutex_unlock(&input_dev->mutex);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(kbd->irq);
+
+	return 0;
+}
+
+static int imx_kbd_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_keypad *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input_dev;
+
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(kbd->irq);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		clk_enable(kbd->clk);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
+
 static struct platform_driver imx_keypad_driver = {
 	.driver		= {
 		.name	= "imx-keypad",
 		.owner	= THIS_MODULE,
+		.pm	= &imx_kbd_pm_ops,
 	},
 	.probe		= imx_keypad_probe,
 	.remove		= __devexit_p(imx_keypad_remove),
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/jornada720_kbd.c linux-libre-3.2-gnu1/drivers/input/keyboard/jornada720_kbd.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/jornada720_kbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/jornada720_kbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@ static int __devinit jornada720_kbd_prob
 
 	err = request_irq(IRQ_GPIO0,
 			  jornada720_kbd_interrupt,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  IRQF_TRIGGER_FALLING,
 			  "jornadakbd", pdev);
 	if (err) {
 		printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/Kconfig linux-libre-3.2-gnu1/drivers/input/keyboard/Kconfig
--- linux-libre-3.1-gnu1/drivers/input/keyboard/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -33,10 +33,10 @@ config KEYBOARD_ADP5588
 	  module will be called adp5588-keys.
 
 config KEYBOARD_ADP5589
-	tristate "ADP5589 I2C QWERTY Keypad and IO Expander"
+	tristate "ADP5585/ADP5589 I2C QWERTY Keypad and IO Expander"
 	depends on I2C
 	help
-	  Say Y here if you want to use a ADP5589 attached to your
+	  Say Y here if you want to use a ADP5585/ADP5589 attached to your
 	  system I2C bus.
 
 	  To compile this driver as a module, choose M here: the
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/lm8323.c linux-libre-3.2-gnu1/drivers/input/keyboard/lm8323.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/lm8323.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/lm8323.c	2012-01-04 18:55:44.000000000 -0500
@@ -788,7 +788,7 @@ static int __devexit lm8323_remove(struc
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 /*
  * We don't need to explicitly suspend the chip, as it already switches off
  * when there's no activity.
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/matrix_keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/matrix_keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/matrix_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/matrix_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -343,7 +343,6 @@ static int __devinit init_matrix_gpio(st
 		for (i = 0; i < pdata->num_row_gpios; i++) {
 			err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
 					matrix_keypad_interrupt,
-					IRQF_DISABLED |
 					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING,
 					"matrix-keypad", keypad);
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/nomadik-ske-keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/nomadik-ske-keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/nomadik-ske-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/nomadik-ske-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/module.h>
 
 #include <plat/ske.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/omap-keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/omap-keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/omap-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/omap-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/mutex.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <asm/irq.h>
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/pxa27x_keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/pxa27x_keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/pxa27x_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/pxa27x_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -535,7 +535,7 @@ static int __devinit pxa27x_keypad_probe
 		input_dev->evbit[0] |= BIT_MASK(EV_REL);
 	}
 
-	error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
+	error = request_irq(irq, pxa27x_keypad_irq_handler, 0,
 			    pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/pxa930_rotary.c linux-libre-3.2-gnu1/drivers/input/keyboard/pxa930_rotary.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/pxa930_rotary.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/pxa930_rotary.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@ static int __devinit pxa930_rotary_probe
 	r->input_dev = input_dev;
 	input_set_drvdata(input_dev, r);
 
-	err = request_irq(irq, rotary_irq, IRQF_DISABLED,
+	err = request_irq(irq, rotary_irq, 0,
 			"enhanced rotary", r);
 	if (err) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/tc3589x-keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/tc3589x-keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/tc3589x-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/tc3589x-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,7 @@ struct tc_keypad {
 	bool keypad_stopped;
 };
 
-static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
+static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
 {
 	int ret;
 	struct tc3589x *tc3589x = keypad->tc3589x;
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/tegra-kbc.c linux-libre-3.2-gnu1/drivers/input/keyboard/tegra-kbc.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/tegra-kbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/tegra-kbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@
 
 #define KBC_ROW_CFG0_0	0x8
 #define KBC_COL_CFG0_0	0x18
+#define KBC_TO_CNT_0	0x24
 #define KBC_INIT_DLY_0	0x28
 #define KBC_RPT_DLY_0	0x2c
 #define KBC_KP_ENT0_0	0x30
@@ -70,6 +71,7 @@ struct tegra_kbc {
 	spinlock_t lock;
 	unsigned int repoll_dly;
 	unsigned long cp_dly_jiffies;
+	unsigned int cp_to_wkup_dly;
 	bool use_fn_map;
 	bool use_ghost_filter;
 	const struct tegra_kbc_platform_data *pdata;
@@ -258,12 +260,10 @@ static void tegra_kbc_report_keys(struct
 	u32 val = 0;
 	unsigned int i;
 	unsigned int num_down = 0;
-	unsigned long flags;
 	bool fn_keypress = false;
 	bool key_in_same_row = false;
 	bool key_in_same_col = false;
 
-	spin_lock_irqsave(&kbc->lock, flags);
 	for (i = 0; i < KBC_MAX_KPENT; i++) {
 		if ((i % 4) == 0)
 			val = readl(kbc->mmio + KBC_KP_ENT0_0 + i);
@@ -292,7 +292,7 @@ static void tegra_kbc_report_keys(struct
 	 * any 2 of the 3 keys share a row, and any 2 of them share a column.
 	 * If so ignore the key presses for this iteration.
 	 */
-	if ((kbc->use_ghost_filter) && (num_down >= 3)) {
+	if (kbc->use_ghost_filter && num_down >= 3) {
 		for (i = 0; i < num_down; i++) {
 			unsigned int j;
 			u8 curr_col = scancodes[i] & 0x07;
@@ -325,8 +325,6 @@ static void tegra_kbc_report_keys(struct
 		}
 	}
 
-	spin_unlock_irqrestore(&kbc->lock, flags);
-
 	/* Ignore the key presses for this iteration? */
 	if (key_in_same_col && key_in_same_row)
 		return;
@@ -341,6 +339,18 @@ static void tegra_kbc_report_keys(struct
 	kbc->num_pressed_keys = num_down;
 }
 
+static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
+{
+	u32 val;
+
+	val = readl(kbc->mmio + KBC_CONTROL_0);
+	if (enable)
+		val |= KBC_CONTROL_FIFO_CNT_INT_EN;
+	else
+		val &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
+	writel(val, kbc->mmio + KBC_CONTROL_0);
+}
+
 static void tegra_kbc_keypress_timer(unsigned long data)
 {
 	struct tegra_kbc *kbc = (struct tegra_kbc *)data;
@@ -348,6 +358,8 @@ static void tegra_kbc_keypress_timer(uns
 	u32 val;
 	unsigned int i;
 
+	spin_lock_irqsave(&kbc->lock, flags);
+
 	val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf;
 	if (val) {
 		unsigned long dly;
@@ -369,26 +381,19 @@ static void tegra_kbc_keypress_timer(uns
 		kbc->num_pressed_keys = 0;
 
 		/* All keys are released so enable the keypress interrupt */
-		spin_lock_irqsave(&kbc->lock, flags);
-		val = readl(kbc->mmio + KBC_CONTROL_0);
-		val |= KBC_CONTROL_FIFO_CNT_INT_EN;
-		writel(val, kbc->mmio + KBC_CONTROL_0);
-		spin_unlock_irqrestore(&kbc->lock, flags);
+		tegra_kbc_set_fifo_interrupt(kbc, true);
 	}
+
+	spin_unlock_irqrestore(&kbc->lock, flags);
 }
 
 static irqreturn_t tegra_kbc_isr(int irq, void *args)
 {
 	struct tegra_kbc *kbc = args;
-	u32 val, ctl;
+	unsigned long flags;
+	u32 val;
 
-	/*
-	 * Until all keys are released, defer further processing to
-	 * the polling loop in tegra_kbc_keypress_timer
-	 */
-	ctl = readl(kbc->mmio + KBC_CONTROL_0);
-	ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
-	writel(ctl, kbc->mmio + KBC_CONTROL_0);
+	spin_lock_irqsave(&kbc->lock, flags);
 
 	/*
 	 * Quickly bail out & reenable interrupts if the fifo threshold
@@ -399,15 +404,15 @@ static irqreturn_t tegra_kbc_isr(int irq
 
 	if (val & KBC_INT_FIFO_CNT_INT_STATUS) {
 		/*
-		 * Schedule timer to run when hardware is in continuous
-		 * polling mode.
+		 * Until all keys are released, defer further processing to
+		 * the polling loop in tegra_kbc_keypress_timer.
 		 */
+		tegra_kbc_set_fifo_interrupt(kbc, false);
 		mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
-	} else {
-		ctl |= KBC_CONTROL_FIFO_CNT_INT_EN;
-		writel(ctl, kbc->mmio + KBC_CONTROL_0);
 	}
 
+	spin_unlock_irqrestore(&kbc->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -455,7 +460,6 @@ static void tegra_kbc_config_pins(struct
 static int tegra_kbc_start(struct tegra_kbc *kbc)
 {
 	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
-	unsigned long flags;
 	unsigned int debounce_cnt;
 	u32 val = 0;
 
@@ -493,7 +497,6 @@ static int tegra_kbc_start(struct tegra_
 	 * Atomically clear out any remaining entries in the key FIFO
 	 * and enable keyboard interrupts.
 	 */
-	spin_lock_irqsave(&kbc->lock, flags);
 	while (1) {
 		val = readl(kbc->mmio + KBC_INT_0);
 		val >>= 4;
@@ -504,7 +507,6 @@ static int tegra_kbc_start(struct tegra_
 		val = readl(kbc->mmio + KBC_KP_ENT1_0);
 	}
 	writel(0x7, kbc->mmio + KBC_INT_0);
-	spin_unlock_irqrestore(&kbc->lock, flags);
 
 	enable_irq(kbc->irq);
 
@@ -734,18 +736,30 @@ static int tegra_kbc_suspend(struct devi
 	struct platform_device *pdev = to_platform_device(dev);
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 
+	mutex_lock(&kbc->idev->mutex);
 	if (device_may_wakeup(&pdev->dev)) {
-		tegra_kbc_setup_wakekeys(kbc, true);
-		enable_irq_wake(kbc->irq);
+		disable_irq(kbc->irq);
+		del_timer_sync(&kbc->timer);
+		tegra_kbc_set_fifo_interrupt(kbc, false);
+
 		/* Forcefully clear the interrupt status */
 		writel(0x7, kbc->mmio + KBC_INT_0);
+		/*
+		 * Store the previous resident time of continuous polling mode.
+		 * Force the keyboard into interrupt mode.
+		 */
+		kbc->cp_to_wkup_dly = readl(kbc->mmio + KBC_TO_CNT_0);
+		writel(0, kbc->mmio + KBC_TO_CNT_0);
+
+		tegra_kbc_setup_wakekeys(kbc, true);
 		msleep(30);
+
+		enable_irq_wake(kbc->irq);
 	} else {
-		mutex_lock(&kbc->idev->mutex);
 		if (kbc->idev->users)
 			tegra_kbc_stop(kbc);
-		mutex_unlock(&kbc->idev->mutex);
 	}
+	mutex_unlock(&kbc->idev->mutex);
 
 	return 0;
 }
@@ -756,15 +770,22 @@ static int tegra_kbc_resume(struct devic
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 	int err = 0;
 
+	mutex_lock(&kbc->idev->mutex);
 	if (device_may_wakeup(&pdev->dev)) {
 		disable_irq_wake(kbc->irq);
 		tegra_kbc_setup_wakekeys(kbc, false);
+
+		/* Restore the resident time of continuous polling mode. */
+		writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0);
+
+		tegra_kbc_set_fifo_interrupt(kbc, true);
+
+		enable_irq(kbc->irq);
 	} else {
-		mutex_lock(&kbc->idev->mutex);
 		if (kbc->idev->users)
 			err = tegra_kbc_start(kbc);
-		mutex_unlock(&kbc->idev->mutex);
 	}
+	mutex_unlock(&kbc->idev->mutex);
 
 	return err;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/tnetv107x-keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/tnetv107x-keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/tnetv107x-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/tnetv107x-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/module.h>
 
 #define BITS(x)			(BIT(x) - 1)
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/keyboard/w90p910_keypad.c linux-libre-3.2-gnu1/drivers/input/keyboard/w90p910_keypad.c
--- linux-libre-3.1-gnu1/drivers/input/keyboard/w90p910_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/keyboard/w90p910_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@ static int __devinit w90p910_keypad_prob
 				   input_dev->keycode, input_dev->keybit);
 
 	error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
-			    IRQF_DISABLED, pdev->name, keypad);
+			    0, pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
 		goto failed_put_clk;
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/ad714x.c linux-libre-3.2-gnu1/drivers/input/misc/ad714x.c
--- linux-libre-3.1-gnu1/drivers/input/misc/ad714x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/ad714x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/input/ad714x.h>
+#include <linux/module.h>
 #include "ad714x.h"
 
 #define AD714X_PWR_CTRL           0x0
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/ad714x-i2c.c linux-libre-3.2-gnu1/drivers/input/misc/ad714x-i2c.c
--- linux-libre-3.1-gnu1/drivers/input/misc/ad714x-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/ad714x-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,13 +116,13 @@ static struct i2c_driver ad714x_i2c_driv
 	.id_table = ad714x_id,
 };
 
-static __init int ad714x_i2c_init(void)
+static int __init ad714x_i2c_init(void)
 {
 	return i2c_add_driver(&ad714x_i2c_driver);
 }
 module_init(ad714x_i2c_init);
 
-static __exit void ad714x_i2c_exit(void)
+static void __exit ad714x_i2c_exit(void)
 {
 	i2c_del_driver(&ad714x_i2c_driver);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/adxl34x.c linux-libre-3.2-gnu1/drivers/input/misc/adxl34x.c
--- linux-libre-3.1-gnu1/drivers/input/misc/adxl34x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/adxl34x.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/input/adxl34x.h>
+#include <linux/module.h>
 
 #include "adxl34x.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/ati_remote2.c linux-libre-3.2-gnu1/drivers/input/misc/ati_remote2.c
--- linux-libre-3.1-gnu1/drivers/input/misc/ati_remote2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/ati_remote2.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/usb/input.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_DESC    "ATI/Philips USB RF remote driver"
 #define DRIVER_VERSION "0.3"
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/ati_remote.c linux-libre-3.2-gnu1/drivers/input/misc/ati_remote.c
--- linux-libre-3.1-gnu1/drivers/input/misc/ati_remote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/ati_remote.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,867 +0,0 @@
-/*
- *  USB ATI Remote support
- *
- *  Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
- *  Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
- *
- *  This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
- *  porting to the 2.6 kernel interfaces, along with other modification
- *  to better match the style of the existing usb/input drivers.  However, the
- *  protocol and hardware handling is essentially unchanged from 2.1.1.
- *
- *  The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by
- *  Vojtech Pavlik.
- *
- *  Changes:
- *
- *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
- *            Version 2.2.0
- *  Jun 2004: Torrey Hoffman <thoffman@arnor.net>
- *            Version 2.2.1
- *            Added key repeat support contributed by:
- *                Vincent Vanackere <vanackere@lif.univ-mrs.fr>
- *            Added support for the "Lola" remote contributed by:
- *                Seth Cohn <sethcohn@yahoo.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Hardware & software notes
- *
- * These remote controls are distributed by ATI as part of their
- * "All-In-Wonder" video card packages.  The receiver self-identifies as a
- * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
- *
- * The "Lola" remote is available from X10.  See:
- *    http://www.x10.com/products/lola_sg1.htm
- * The Lola is similar to the ATI remote but has no mouse support, and slightly
- * different keys.
- *
- * It is possible to use multiple receivers and remotes on multiple computers
- * simultaneously by configuring them to use specific channels.
- *
- * The RF protocol used by the remote supports 16 distinct channels, 1 to 16.
- * Actually, it may even support more, at least in some revisions of the
- * hardware.
- *
- * Each remote can be configured to transmit on one channel as follows:
- *   - Press and hold the "hand icon" button.
- *   - When the red LED starts to blink, let go of the "hand icon" button.
- *   - When it stops blinking, input the channel code as two digits, from 01
- *     to 16, and press the hand icon again.
- *
- * The timing can be a little tricky.  Try loading the module with debug=1
- * to have the kernel print out messages about the remote control number
- * and mask.  Note: debugging prints remote numbers as zero-based hexadecimal.
- *
- * The driver has a "channel_mask" parameter. This bitmask specifies which
- * channels will be ignored by the module.  To mask out channels, just add
- * all the 2^channel_number values together.
- *
- * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
- * ignore signals coming from remote controls transmitting on channel 4, but
- * accept all other channels.
- *
- * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be
- * ignored.
- *
- * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this
- * parameter are unused.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb/input.h>
-#include <linux/wait.h>
-#include <linux/jiffies.h>
-
-/*
- * Module and Version Information, Module Parameters
- */
-
-#define ATI_REMOTE_VENDOR_ID		0x0bc7
-#define LOLA_REMOTE_PRODUCT_ID		0x0002
-#define LOLA2_REMOTE_PRODUCT_ID		0x0003
-#define ATI_REMOTE_PRODUCT_ID		0x0004
-#define NVIDIA_REMOTE_PRODUCT_ID	0x0005
-#define MEDION_REMOTE_PRODUCT_ID	0x0006
-
-#define DRIVER_VERSION	        "2.2.1"
-#define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
-#define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
-
-#define NAME_BUFSIZE      80    /* size of product name, path buffers */
-#define DATA_BUFSIZE      63    /* size of URB data buffers */
-
-/*
- * Duplicate event filtering time.
- * Sequential, identical KIND_FILTERED inputs with less than
- * FILTER_TIME milliseconds between them are considered as repeat
- * events. The hardware generates 5 events for the first keypress
- * and we have to take this into account for an accurate repeat
- * behaviour.
- */
-#define FILTER_TIME	60 /* msec */
-#define REPEAT_DELAY	500 /* msec */
-
-static unsigned long channel_mask;
-module_param(channel_mask, ulong, 0644);
-MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
-
-static int repeat_filter = FILTER_TIME;
-module_param(repeat_filter, int, 0644);
-MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
-
-static int repeat_delay = REPEAT_DELAY;
-module_param(repeat_delay, int, 0644);
-MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
-
-#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
-#undef err
-#define err(format, arg...) printk(KERN_ERR format , ## arg)
-
-static struct usb_device_id ati_remote_table[] = {
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) },
-	{}	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, ati_remote_table);
-
-/* Get hi and low bytes of a 16-bits int */
-#define HI(a)	((unsigned char)((a) >> 8))
-#define LO(a)	((unsigned char)((a) & 0xff))
-
-#define SEND_FLAG_IN_PROGRESS	1
-#define SEND_FLAG_COMPLETE	2
-
-/* Device initialization strings */
-static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
-static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
-
-struct ati_remote {
-	struct input_dev *idev;
-	struct usb_device *udev;
-	struct usb_interface *interface;
-
-	struct urb *irq_urb;
-	struct urb *out_urb;
-	struct usb_endpoint_descriptor *endpoint_in;
-	struct usb_endpoint_descriptor *endpoint_out;
-	unsigned char *inbuf;
-	unsigned char *outbuf;
-	dma_addr_t inbuf_dma;
-	dma_addr_t outbuf_dma;
-
-	unsigned char old_data[2];  /* Detect duplicate events */
-	unsigned long old_jiffies;
-	unsigned long acc_jiffies;  /* handle acceleration */
-	unsigned long first_jiffies;
-
-	unsigned int repeat_count;
-
-	char name[NAME_BUFSIZE];
-	char phys[NAME_BUFSIZE];
-
-	wait_queue_head_t wait;
-	int send_flags;
-};
-
-/* "Kinds" of messages sent from the hardware to the driver. */
-#define KIND_END        0
-#define KIND_LITERAL    1   /* Simply pass to input system */
-#define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
-#define KIND_LU         3   /* Directional keypad diagonals - left up, */
-#define KIND_RU         4   /*   right up,  */
-#define KIND_LD         5   /*   left down, */
-#define KIND_RD         6   /*   right down */
-#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
-
-/* Translation table from hardware messages to input events. */
-static const struct {
-	short kind;
-	unsigned char data1, data2;
-	int type;
-	unsigned int code;
-	int value;
-}  ati_remote_tbl[] = {
-	/* Directional control pad axes */
-	{KIND_ACCEL,   0x35, 0x70, EV_REL, REL_X, -1},	 /* left */
-	{KIND_ACCEL,   0x36, 0x71, EV_REL, REL_X, 1},    /* right */
-	{KIND_ACCEL,   0x37, 0x72, EV_REL, REL_Y, -1},	 /* up */
-	{KIND_ACCEL,   0x38, 0x73, EV_REL, REL_Y, 1},    /* down */
-	/* Directional control pad diagonals */
-	{KIND_LU,      0x39, 0x74, EV_REL, 0, 0},        /* left up */
-	{KIND_RU,      0x3a, 0x75, EV_REL, 0, 0},        /* right up */
-	{KIND_LD,      0x3c, 0x77, EV_REL, 0, 0},        /* left down */
-	{KIND_RD,      0x3b, 0x76, EV_REL, 0, 0},        /* right down */
-
-	/* "Mouse button" buttons */
-	{KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
-	{KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
-	{KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
-	{KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
-
-	/* Artificial "doubleclick" events are generated by the hardware.
-	 * They are mapped to the "side" and "extra" mouse buttons here. */
-	{KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
-	{KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
-
-	/* keyboard. */
-	{KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1},
-	{KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1},
-	{KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1},
-	{KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1},
-	{KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1},
-	{KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1},
-	{KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1},
-	{KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1},
-	{KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1},
-	{KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1},
-	{KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1},
-	{KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1},
-	{KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1},
-	{KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1},
-	{KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1},
-	{KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1},
-
-	/* "special" keys */
-	{KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1},    /* "check" */
-	{KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1},       /* "menu" */
-	{KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1},      /* Power */
-	{KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1},         /* TV */
-	{KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1},        /* DVD */
-	{KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1},        /* WEB */
-	{KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1},  /* "book" */
-	{KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1},       /* "hand" */
-	{KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1},     /* "timer" */
-	{KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1},      /* "max" */
-	{KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1},       /* left */
-	{KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1},      /* right */
-	{KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1},       /* down */
-	{KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1},         /* up */
-	{KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1},         /* "OK" */
-	{KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
-	{KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1},   /* VOL - */
-	{KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1},       /* MUTE  */
-	{KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1},  /* CH + */
-	{KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
-	{KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1},     /* ( o) red */
-	{KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1},       /* ( >) */
-	{KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1},     /* (<<) */
-	{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1},    /* (>>) */
-	{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1},       /* ([]) */
-	{KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1},      /* ('') */
-	{KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1},   /* (<-) */
-	{KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1},       /* (>+) */
-	{KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1},       /* PLAYING */
-	{KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1},       /* TOP */
-	{KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1},        /* END */
-	{KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1},     /* SELECT */
-
-	{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
-};
-
-/* Local function prototypes */
-static int ati_remote_open		(struct input_dev *inputdev);
-static void ati_remote_close		(struct input_dev *inputdev);
-static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
-static void ati_remote_irq_out		(struct urb *urb);
-static void ati_remote_irq_in		(struct urb *urb);
-static void ati_remote_input_report	(struct urb *urb);
-static int ati_remote_initialize	(struct ati_remote *ati_remote);
-static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
-static void ati_remote_disconnect	(struct usb_interface *interface);
-
-/* usb specific object to register with the usb subsystem */
-static struct usb_driver ati_remote_driver = {
-	.name         = "ati_remote",
-	.probe        = ati_remote_probe,
-	.disconnect   = ati_remote_disconnect,
-	.id_table     = ati_remote_table,
-};
-
-/*
- *	ati_remote_dump_input
- */
-static void ati_remote_dump(struct device *dev, unsigned char *data,
-			    unsigned int len)
-{
-	if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00))
-		dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
-	else if (len == 4)
-		dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
-		     data[0], data[1], data[2], data[3]);
-	else
-		dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
-		     len, data[0], data[1], data[2], data[3], data[4], data[5]);
-}
-
-/*
- *	ati_remote_open
- */
-static int ati_remote_open(struct input_dev *inputdev)
-{
-	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
-
-	/* On first open, submit the read urb which was set up previously. */
-	ati_remote->irq_urb->dev = ati_remote->udev;
-	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
-		dev_err(&ati_remote->interface->dev,
-			"%s: usb_submit_urb failed!\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*
- *	ati_remote_close
- */
-static void ati_remote_close(struct input_dev *inputdev)
-{
-	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
-
-	usb_kill_urb(ati_remote->irq_urb);
-}
-
-/*
- *		ati_remote_irq_out
- */
-static void ati_remote_irq_out(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-
-	if (urb->status) {
-		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
-			__func__, urb->status);
-		return;
-	}
-
-	ati_remote->send_flags |= SEND_FLAG_COMPLETE;
-	wmb();
-	wake_up(&ati_remote->wait);
-}
-
-/*
- *	ati_remote_sendpacket
- *
- *	Used to send device initialization strings
- */
-static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
-{
-	int retval = 0;
-
-	/* Set up out_urb */
-	memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
-	((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);
-
-	ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
-	ati_remote->out_urb->dev = ati_remote->udev;
-	ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
-
-	retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC);
-	if (retval) {
-		dev_dbg(&ati_remote->interface->dev,
-			 "sendpacket: usb_submit_urb failed: %d\n", retval);
-		return retval;
-	}
-
-	wait_event_timeout(ati_remote->wait,
-		((ati_remote->out_urb->status != -EINPROGRESS) ||
-			(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
-		HZ);
-	usb_kill_urb(ati_remote->out_urb);
-
-	return retval;
-}
-
-/*
- *	ati_remote_event_lookup
- */
-static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
-{
-	int i;
-
-	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
-		/*
-		 * Decide if the table entry matches the remote input.
-		 */
-		if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) &&
-		    ((((ati_remote_tbl[i].data1 >> 4) -
-		       (d1 >> 4) + rem) & 0x0f) == 0x0f) &&
-		    (ati_remote_tbl[i].data2 == d2))
-			return i;
-
-	}
-	return -1;
-}
-
-/*
- *	ati_remote_compute_accel
- *
- * Implements acceleration curve for directional control pad
- * If elapsed time since last event is > 1/4 second, user "stopped",
- * so reset acceleration. Otherwise, user is probably holding the control
- * pad down, so we increase acceleration, ramping up over two seconds to
- * a maximum speed.
- */
-static int ati_remote_compute_accel(struct ati_remote *ati_remote)
-{
-	static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
-	unsigned long now = jiffies;
-	int acc;
-
-	if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
-		acc = 1;
-		ati_remote->acc_jiffies = now;
-	}
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
-		acc = accel[0];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
-		acc = accel[1];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
-		acc = accel[2];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
-		acc = accel[3];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
-		acc = accel[4];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
-		acc = accel[5];
-	else
-		acc = accel[6];
-
-	return acc;
-}
-
-/*
- *	ati_remote_report_input
- */
-static void ati_remote_input_report(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-	unsigned char *data= ati_remote->inbuf;
-	struct input_dev *dev = ati_remote->idev;
-	int index, acc;
-	int remote_num;
-
-	/* Deal with strange looking inputs */
-	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
-		((data[3] & 0x0f) != 0x00) ) {
-		ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
-		return;
-	}
-
-	/* Mask unwanted remote channels.  */
-	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
-	remote_num = (data[3] >> 4) & 0x0f;
-        if (channel_mask & (1 << (remote_num + 1))) {
-		dbginfo(&ati_remote->interface->dev,
-			"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
-			remote_num, data[1], data[2], channel_mask);
-		return;
-	}
-
-	/* Look up event code index in translation table */
-	index = ati_remote_event_lookup(remote_num, data[1], data[2]);
-	if (index < 0) {
-		dev_warn(&ati_remote->interface->dev,
-			 "Unknown input from channel 0x%02x: data %02x,%02x\n",
-			 remote_num, data[1], data[2]);
-		return;
-	}
-	dbginfo(&ati_remote->interface->dev,
-		"channel 0x%02x; data %02x,%02x; index %d; keycode %d\n",
-		remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
-
-	if (ati_remote_tbl[index].kind == KIND_LITERAL) {
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code,
-			ati_remote_tbl[index].value);
-		input_sync(dev);
-
-		ati_remote->old_jiffies = jiffies;
-		return;
-	}
-
-	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
-		unsigned long now = jiffies;
-
-		/* Filter duplicate events which happen "too close" together. */
-		if (ati_remote->old_data[0] == data[1] &&
-		    ati_remote->old_data[1] == data[2] &&
-		    time_before(now, ati_remote->old_jiffies +
-				     msecs_to_jiffies(repeat_filter))) {
-			ati_remote->repeat_count++;
-		} else {
-			ati_remote->repeat_count = 0;
-			ati_remote->first_jiffies = now;
-		}
-
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
-		ati_remote->old_jiffies = now;
-
-		/* Ensure we skip at least the 4 first duplicate events (generated
-		 * by a single keypress), and continue skipping until repeat_delay
-		 * msecs have passed
-		 */
-		if (ati_remote->repeat_count > 0 &&
-		    (ati_remote->repeat_count < 5 ||
-		     time_before(now, ati_remote->first_jiffies +
-				      msecs_to_jiffies(repeat_delay))))
-			return;
-
-
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 1);
-		input_sync(dev);
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 0);
-		input_sync(dev);
-
-	} else {
-
-		/*
-		 * Other event kinds are from the directional control pad, and have an
-		 * acceleration factor applied to them.  Without this acceleration, the
-		 * control pad is mostly unusable.
-		 */
-		acc = ati_remote_compute_accel(ati_remote);
-
-		switch (ati_remote_tbl[index].kind) {
-		case KIND_ACCEL:
-			input_event(dev, ati_remote_tbl[index].type,
-				ati_remote_tbl[index].code,
-				ati_remote_tbl[index].value * acc);
-			break;
-		case KIND_LU:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_RU:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_LD:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		case KIND_RD:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		default:
-			dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
-				ati_remote_tbl[index].kind);
-		}
-		input_sync(dev);
-
-		ati_remote->old_jiffies = jiffies;
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
-	}
-}
-
-/*
- *	ati_remote_irq_in
- */
-static void ati_remote_irq_in(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:			/* success */
-		ati_remote_input_report(urb);
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
-			__func__);
-		return;
-	default:		/* error */
-		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
-			__func__, urb->status);
-	}
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
-			__func__, retval);
-}
-
-/*
- *	ati_remote_alloc_buffers
- */
-static int ati_remote_alloc_buffers(struct usb_device *udev,
-				    struct ati_remote *ati_remote)
-{
-	ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
-					       &ati_remote->inbuf_dma);
-	if (!ati_remote->inbuf)
-		return -1;
-
-	ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
-					        &ati_remote->outbuf_dma);
-	if (!ati_remote->outbuf)
-		return -1;
-
-	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->irq_urb)
-		return -1;
-
-	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->out_urb)
-		return -1;
-
-	return 0;
-}
-
-/*
- *	ati_remote_free_buffers
- */
-static void ati_remote_free_buffers(struct ati_remote *ati_remote)
-{
-	usb_free_urb(ati_remote->irq_urb);
-	usb_free_urb(ati_remote->out_urb);
-
-	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
-		ati_remote->inbuf, ati_remote->inbuf_dma);
-
-	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
-		ati_remote->outbuf, ati_remote->outbuf_dma);
-}
-
-static void ati_remote_input_init(struct ati_remote *ati_remote)
-{
-	struct input_dev *idev = ati_remote->idev;
-	int i;
-
-	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-	idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
-		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
-	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
-		if (ati_remote_tbl[i].type == EV_KEY)
-			set_bit(ati_remote_tbl[i].code, idev->keybit);
-
-	input_set_drvdata(idev, ati_remote);
-
-	idev->open = ati_remote_open;
-	idev->close = ati_remote_close;
-
-	idev->name = ati_remote->name;
-	idev->phys = ati_remote->phys;
-
-	usb_to_input_id(ati_remote->udev, &idev->id);
-	idev->dev.parent = &ati_remote->udev->dev;
-}
-
-static int ati_remote_initialize(struct ati_remote *ati_remote)
-{
-	struct usb_device *udev = ati_remote->udev;
-	int pipe, maxp;
-
-	init_waitqueue_head(&ati_remote->wait);
-
-	/* Set up irq_urb */
-	pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
-
-	usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
-			 maxp, ati_remote_irq_in, ati_remote,
-			 ati_remote->endpoint_in->bInterval);
-	ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
-	ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/* Set up out_urb */
-	pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
-
-	usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
-			 maxp, ati_remote_irq_out, ati_remote,
-			 ati_remote->endpoint_out->bInterval);
-	ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
-	ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/* send initialization strings */
-	if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
-	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
-		dev_err(&ati_remote->interface->dev,
-			 "Initializing ati_remote hardware failed.\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*
- *	ati_remote_probe
- */
-static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_host = interface->cur_altsetting;
-	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
-	struct ati_remote *ati_remote;
-	struct input_dev *input_dev;
-	int err = -ENOMEM;
-
-	if (iface_host->desc.bNumEndpoints != 2) {
-		err("%s: Unexpected desc.bNumEndpoints\n", __func__);
-		return -ENODEV;
-	}
-
-	endpoint_in = &iface_host->endpoint[0].desc;
-	endpoint_out = &iface_host->endpoint[1].desc;
-
-	if (!usb_endpoint_is_int_in(endpoint_in)) {
-		err("%s: Unexpected endpoint_in\n", __func__);
-		return -ENODEV;
-	}
-	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
-		err("%s: endpoint_in message size==0? \n", __func__);
-		return -ENODEV;
-	}
-
-	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ati_remote || !input_dev)
-		goto fail1;
-
-	/* Allocate URB buffers, URBs */
-	if (ati_remote_alloc_buffers(udev, ati_remote))
-		goto fail2;
-
-	ati_remote->endpoint_in = endpoint_in;
-	ati_remote->endpoint_out = endpoint_out;
-	ati_remote->udev = udev;
-	ati_remote->idev = input_dev;
-	ati_remote->interface = interface;
-
-	usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
-	strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
-
-	if (udev->manufacturer)
-		strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
-
-	if (udev->product)
-		snprintf(ati_remote->name, sizeof(ati_remote->name),
-			 "%s %s", ati_remote->name, udev->product);
-
-	if (!strlen(ati_remote->name))
-		snprintf(ati_remote->name, sizeof(ati_remote->name),
-			DRIVER_DESC "(%04x,%04x)",
-			le16_to_cpu(ati_remote->udev->descriptor.idVendor),
-			le16_to_cpu(ati_remote->udev->descriptor.idProduct));
-
-	ati_remote_input_init(ati_remote);
-
-	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
-	err = ati_remote_initialize(ati_remote);
-	if (err)
-		goto fail3;
-
-	/* Set up and register input device */
-	err = input_register_device(ati_remote->idev);
-	if (err)
-		goto fail3;
-
-	usb_set_intfdata(interface, ati_remote);
-	return 0;
-
- fail3:	usb_kill_urb(ati_remote->irq_urb);
-	usb_kill_urb(ati_remote->out_urb);
- fail2:	ati_remote_free_buffers(ati_remote);
- fail1:	input_free_device(input_dev);
-	kfree(ati_remote);
-	return err;
-}
-
-/*
- *	ati_remote_disconnect
- */
-static void ati_remote_disconnect(struct usb_interface *interface)
-{
-	struct ati_remote *ati_remote;
-
-	ati_remote = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-	if (!ati_remote) {
-		dev_warn(&interface->dev, "%s - null device?\n", __func__);
-		return;
-	}
-
-	usb_kill_urb(ati_remote->irq_urb);
-	usb_kill_urb(ati_remote->out_urb);
-	input_unregister_device(ati_remote->idev);
-	ati_remote_free_buffers(ati_remote);
-	kfree(ati_remote);
-}
-
-/*
- *	ati_remote_init
- */
-static int __init ati_remote_init(void)
-{
-	int result;
-
-	result = usb_register(&ati_remote_driver);
-	if (result)
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": usb_register error #%d\n", result);
-	else
-		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-		       DRIVER_DESC "\n");
-
-	return result;
-}
-
-/*
- *	ati_remote_exit
- */
-static void __exit ati_remote_exit(void)
-{
-	usb_deregister(&ati_remote_driver);
-}
-
-/*
- *	module specification
- */
-
-module_init(ati_remote_init);
-module_exit(ati_remote_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/bma150.c linux-libre-3.2-gnu1/drivers/input/misc/bma150.c
--- linux-libre-3.1-gnu1/drivers/input/misc/bma150.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/input/misc/bma150.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2011 Bosch Sensortec GmbH
+ * Copyright (c) 2011 Unixphere
+ *
+ * This driver adds support for Bosch Sensortec's digital acceleration
+ * sensors BMA150 and SMB380.
+ * The SMB380 is fully compatible with BMA150 and only differs in packaging.
+ *
+ * The datasheet for the BMA150 chip can be found here:
+ * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/bma150.h>
+
+#define ABSMAX_ACC_VAL		0x01FF
+#define ABSMIN_ACC_VAL		-(ABSMAX_ACC_VAL)
+
+/* Each axis is represented by a 2-byte data word */
+#define BMA150_XYZ_DATA_SIZE	6
+
+/* Input poll interval in milliseconds */
+#define BMA150_POLL_INTERVAL	10
+#define BMA150_POLL_MAX		200
+#define BMA150_POLL_MIN		0
+
+#define BMA150_BW_25HZ		0
+#define BMA150_BW_50HZ		1
+#define BMA150_BW_100HZ		2
+#define BMA150_BW_190HZ		3
+#define BMA150_BW_375HZ		4
+#define BMA150_BW_750HZ		5
+#define BMA150_BW_1500HZ	6
+
+#define BMA150_RANGE_2G		0
+#define BMA150_RANGE_4G		1
+#define BMA150_RANGE_8G		2
+
+#define BMA150_MODE_NORMAL	0
+#define BMA150_MODE_SLEEP	2
+#define BMA150_MODE_WAKE_UP	3
+
+/* Data register addresses */
+#define BMA150_DATA_0_REG	0x00
+#define BMA150_DATA_1_REG	0x01
+#define BMA150_DATA_2_REG	0x02
+
+/* Control register addresses */
+#define BMA150_CTRL_0_REG	0x0A
+#define BMA150_CTRL_1_REG	0x0B
+#define BMA150_CTRL_2_REG	0x14
+#define BMA150_CTRL_3_REG	0x15
+
+/* Configuration/Setting register addresses */
+#define BMA150_CFG_0_REG	0x0C
+#define BMA150_CFG_1_REG	0x0D
+#define BMA150_CFG_2_REG	0x0E
+#define BMA150_CFG_3_REG	0x0F
+#define BMA150_CFG_4_REG	0x10
+#define BMA150_CFG_5_REG	0x11
+
+#define BMA150_CHIP_ID		2
+#define BMA150_CHIP_ID_REG	BMA150_DATA_0_REG
+
+#define BMA150_ACC_X_LSB_REG	BMA150_DATA_2_REG
+
+#define BMA150_SLEEP_POS	0
+#define BMA150_SLEEP_MSK	0x01
+#define BMA150_SLEEP_REG	BMA150_CTRL_0_REG
+
+#define BMA150_BANDWIDTH_POS	0
+#define BMA150_BANDWIDTH_MSK	0x07
+#define BMA150_BANDWIDTH_REG	BMA150_CTRL_2_REG
+
+#define BMA150_RANGE_POS	3
+#define BMA150_RANGE_MSK	0x18
+#define BMA150_RANGE_REG	BMA150_CTRL_2_REG
+
+#define BMA150_WAKE_UP_POS	0
+#define BMA150_WAKE_UP_MSK	0x01
+#define BMA150_WAKE_UP_REG	BMA150_CTRL_3_REG
+
+#define BMA150_SW_RES_POS	1
+#define BMA150_SW_RES_MSK	0x02
+#define BMA150_SW_RES_REG	BMA150_CTRL_0_REG
+
+/* Any-motion interrupt register fields */
+#define BMA150_ANY_MOTION_EN_POS	6
+#define BMA150_ANY_MOTION_EN_MSK	0x40
+#define BMA150_ANY_MOTION_EN_REG	BMA150_CTRL_1_REG
+
+#define BMA150_ANY_MOTION_DUR_POS	6
+#define BMA150_ANY_MOTION_DUR_MSK	0xC0
+#define BMA150_ANY_MOTION_DUR_REG	BMA150_CFG_5_REG
+
+#define BMA150_ANY_MOTION_THRES_REG	BMA150_CFG_4_REG
+
+/* Advanced interrupt register fields */
+#define BMA150_ADV_INT_EN_POS		6
+#define BMA150_ADV_INT_EN_MSK		0x40
+#define BMA150_ADV_INT_EN_REG		BMA150_CTRL_3_REG
+
+/* High-G interrupt register fields */
+#define BMA150_HIGH_G_EN_POS		1
+#define BMA150_HIGH_G_EN_MSK		0x02
+#define BMA150_HIGH_G_EN_REG		BMA150_CTRL_1_REG
+
+#define BMA150_HIGH_G_HYST_POS		3
+#define BMA150_HIGH_G_HYST_MSK		0x38
+#define BMA150_HIGH_G_HYST_REG		BMA150_CFG_5_REG
+
+#define BMA150_HIGH_G_DUR_REG		BMA150_CFG_3_REG
+#define BMA150_HIGH_G_THRES_REG		BMA150_CFG_2_REG
+
+/* Low-G interrupt register fields */
+#define BMA150_LOW_G_EN_POS		0
+#define BMA150_LOW_G_EN_MSK		0x01
+#define BMA150_LOW_G_EN_REG		BMA150_CTRL_1_REG
+
+#define BMA150_LOW_G_HYST_POS		0
+#define BMA150_LOW_G_HYST_MSK		0x07
+#define BMA150_LOW_G_HYST_REG		BMA150_CFG_5_REG
+
+#define BMA150_LOW_G_DUR_REG		BMA150_CFG_1_REG
+#define BMA150_LOW_G_THRES_REG		BMA150_CFG_0_REG
+
+struct bma150_data {
+	struct i2c_client *client;
+	struct input_polled_dev *input_polled;
+	struct input_dev *input;
+	u8 mode;
+};
+
+/*
+ * The settings for the given range, bandwidth and interrupt features
+ * are stated and verified by Bosch Sensortec where they are configured
+ * to provide a generic sensitivity performance.
+ */
+static struct bma150_cfg default_cfg __devinitdata = {
+	.any_motion_int = 1,
+	.hg_int = 1,
+	.lg_int = 1,
+	.any_motion_dur = 0,
+	.any_motion_thres = 0,
+	.hg_hyst = 0,
+	.hg_dur = 150,
+	.hg_thres = 160,
+	.lg_hyst = 0,
+	.lg_dur = 150,
+	.lg_thres = 20,
+	.range = BMA150_RANGE_2G,
+	.bandwidth = BMA150_BW_50HZ
+};
+
+static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val)
+{
+	s32 ret;
+
+	/* As per specification, disable irq in between register writes */
+	if (client->irq)
+		disable_irq_nosync(client->irq);
+
+	ret = i2c_smbus_write_byte_data(client, reg, val);
+
+	if (client->irq)
+		enable_irq(client->irq);
+
+	return ret;
+}
+
+static int bma150_set_reg_bits(struct i2c_client *client,
+					int val, int shift, u8 mask, u8 reg)
+{
+	int data;
+
+	data = i2c_smbus_read_byte_data(client, reg);
+	if (data < 0)
+		return data;
+
+	data = (data & ~mask) | ((val << shift) & mask);
+	return bma150_write_byte(client, reg, data);
+}
+
+static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS,
+				BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG);
+	if (error)
+		return error;
+
+	error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS,
+				BMA150_SLEEP_MSK, BMA150_SLEEP_REG);
+	if (error)
+		return error;
+
+	if (mode == BMA150_MODE_NORMAL)
+		msleep(2);
+
+	bma150->mode = mode;
+	return 0;
+}
+
+static int __devinit bma150_soft_reset(struct bma150_data *bma150)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS,
+				BMA150_SW_RES_MSK, BMA150_SW_RES_REG);
+	if (error)
+		return error;
+
+	msleep(2);
+	return 0;
+}
+
+static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range)
+{
+	return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
+				BMA150_RANGE_MSK, BMA150_RANGE_REG);
+}
+
+static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
+{
+	return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
+				BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
+}
+
+static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
+					u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, hyst,
+				BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK,
+				BMA150_LOW_G_HYST_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK,
+				BMA150_LOW_G_EN_REG);
+}
+
+static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
+					u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, hyst,
+				BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK,
+				BMA150_HIGH_G_HYST_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_HIGH_G_DUR_REG, dur);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_HIGH_G_THRES_REG, thres);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK,
+				BMA150_HIGH_G_EN_REG);
+}
+
+
+static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150,
+						u8 enable, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, dur,
+				BMA150_ANY_MOTION_DUR_POS,
+				BMA150_ANY_MOTION_DUR_MSK,
+				BMA150_ANY_MOTION_DUR_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_ANY_MOTION_THRES_REG, thres);
+	if (error)
+		return error;
+
+	error = bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK,
+				BMA150_ADV_INT_EN_REG);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_ANY_MOTION_EN_POS,
+				BMA150_ANY_MOTION_EN_MSK,
+				BMA150_ANY_MOTION_EN_REG);
+}
+
+static void bma150_report_xyz(struct bma150_data *bma150)
+{
+	u8 data[BMA150_XYZ_DATA_SIZE];
+	s16 x, y, z;
+	s32 ret;
+
+	ret = i2c_smbus_read_i2c_block_data(bma150->client,
+			BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data);
+	if (ret != BMA150_XYZ_DATA_SIZE)
+		return;
+
+	x = ((0xc0 & data[0]) >> 6) | (data[1] << 2);
+	y = ((0xc0 & data[2]) >> 6) | (data[3] << 2);
+	z = ((0xc0 & data[4]) >> 6) | (data[5] << 2);
+
+	/* sign extension */
+	x = (s16) (x << 6) >> 6;
+	y = (s16) (y << 6) >> 6;
+	z = (s16) (z << 6) >> 6;
+
+	input_report_abs(bma150->input, ABS_X, x);
+	input_report_abs(bma150->input, ABS_Y, y);
+	input_report_abs(bma150->input, ABS_Z, z);
+	input_sync(bma150->input);
+}
+
+static irqreturn_t bma150_irq_thread(int irq, void *dev)
+{
+	bma150_report_xyz(dev);
+
+	return IRQ_HANDLED;
+}
+
+static void bma150_poll(struct input_polled_dev *dev)
+{
+	bma150_report_xyz(dev->private);
+}
+
+static int bma150_open(struct bma150_data *bma150)
+{
+	int error;
+
+	error = pm_runtime_get_sync(&bma150->client->dev);
+	if (error && error != -ENOSYS)
+		return error;
+
+	/*
+	 * See if runtime PM woke up the device. If runtime PM
+	 * is disabled we need to do it ourselves.
+	 */
+	if (bma150->mode != BMA150_MODE_NORMAL) {
+		error = bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+static void bma150_close(struct bma150_data *bma150)
+{
+	pm_runtime_put_sync(&bma150->client->dev);
+
+	if (bma150->mode != BMA150_MODE_SLEEP)
+		bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_irq_open(struct input_dev *input)
+{
+	struct bma150_data *bma150 = input_get_drvdata(input);
+
+	return bma150_open(bma150);
+}
+
+static void bma150_irq_close(struct input_dev *input)
+{
+	struct bma150_data *bma150 = input_get_drvdata(input);
+
+	bma150_close(bma150);
+}
+
+static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
+{
+	struct bma150_data *bma150 = ipoll_dev->private;
+
+	bma150_open(bma150);
+}
+
+static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
+{
+	struct bma150_data *bma150 = ipoll_dev->private;
+
+	bma150_close(bma150);
+}
+
+static int __devinit bma150_initialize(struct bma150_data *bma150,
+				       const struct bma150_cfg *cfg)
+{
+	int error;
+
+	error = bma150_soft_reset(bma150);
+	if (error)
+		return error;
+
+	error = bma150_set_bandwidth(bma150, cfg->bandwidth);
+	if (error)
+		return error;
+
+	error = bma150_set_range(bma150, cfg->range);
+	if (error)
+		return error;
+
+	if (bma150->client->irq) {
+		error = bma150_set_any_motion_interrupt(bma150,
+					cfg->any_motion_int,
+					cfg->any_motion_dur,
+					cfg->any_motion_thres);
+		if (error)
+			return error;
+
+		error = bma150_set_high_g_interrupt(bma150,
+					cfg->hg_int, cfg->hg_hyst,
+					cfg->hg_dur, cfg->hg_thres);
+		if (error)
+			return error;
+
+		error = bma150_set_low_g_interrupt(bma150,
+					cfg->lg_int, cfg->lg_hyst,
+					cfg->lg_dur, cfg->lg_thres);
+		if (error)
+			return error;
+	}
+
+	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static void __devinit bma150_init_input_device(struct bma150_data *bma150,
+						struct input_dev *idev)
+{
+	idev->name = BMA150_DRIVER;
+	idev->phys = BMA150_DRIVER "/input0";
+	idev->id.bustype = BUS_I2C;
+	idev->dev.parent = &bma150->client->dev;
+
+	idev->evbit[0] = BIT_MASK(EV_ABS);
+	input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+	input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+	input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+}
+
+static int __devinit bma150_register_input_device(struct bma150_data *bma150)
+{
+	struct input_dev *idev;
+	int error;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	bma150_init_input_device(bma150, idev);
+
+	idev->open = bma150_irq_open;
+	idev->close = bma150_irq_close;
+	input_set_drvdata(idev, bma150);
+
+	error = input_register_device(idev);
+	if (error) {
+		input_free_device(idev);
+		return error;
+	}
+
+	bma150->input = idev;
+	return 0;
+}
+
+static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
+{
+	struct input_polled_dev *ipoll_dev;
+	int error;
+
+	ipoll_dev = input_allocate_polled_device();
+	if (!ipoll_dev)
+		return -ENOMEM;
+
+	ipoll_dev->private = bma150;
+	ipoll_dev->open = bma150_poll_open;
+	ipoll_dev->close = bma150_poll_close;
+	ipoll_dev->poll = bma150_poll;
+	ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
+	ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
+	ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
+
+	bma150_init_input_device(bma150, ipoll_dev->input);
+
+	error = input_register_polled_device(ipoll_dev);
+	if (error) {
+		input_free_polled_device(ipoll_dev);
+		return error;
+	}
+
+	bma150->input_polled = ipoll_dev;
+	bma150->input = ipoll_dev->input;
+
+	return 0;
+}
+
+static int __devinit bma150_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	const struct bma150_platform_data *pdata = client->dev.platform_data;
+	const struct bma150_cfg *cfg;
+	struct bma150_data *bma150;
+	int chip_id;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "i2c_check_functionality error\n");
+		return -EIO;
+	}
+
+	chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
+	if (chip_id != BMA150_CHIP_ID) {
+		dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
+		return -EINVAL;
+	}
+
+	bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
+	if (!bma150)
+		return -ENOMEM;
+
+	bma150->client = client;
+
+	if (pdata) {
+		if (pdata->irq_gpio_cfg) {
+			error = pdata->irq_gpio_cfg();
+			if (error) {
+				dev_err(&client->dev,
+					"IRQ GPIO conf. error %d, error %d\n",
+					client->irq, error);
+				goto err_free_mem;
+			}
+		}
+		cfg = &pdata->cfg;
+	} else {
+		cfg = &default_cfg;
+	}
+
+	error = bma150_initialize(bma150, cfg);
+	if (error)
+		goto err_free_mem;
+
+	if (client->irq > 0) {
+		error = bma150_register_input_device(bma150);
+		if (error)
+			goto err_free_mem;
+
+		error = request_threaded_irq(client->irq,
+					NULL, bma150_irq_thread,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					BMA150_DRIVER, bma150);
+		if (error) {
+			dev_err(&client->dev,
+				"irq request failed %d, error %d\n",
+				client->irq, error);
+			input_unregister_device(bma150->input);
+			goto err_free_mem;
+		}
+	} else {
+		error = bma150_register_polled_device(bma150);
+		if (error)
+			goto err_free_mem;
+	}
+
+	i2c_set_clientdata(client, bma150);
+
+	pm_runtime_enable(&client->dev);
+
+	return 0;
+
+err_free_mem:
+	kfree(bma150);
+	return error;
+}
+
+static int __devexit bma150_remove(struct i2c_client *client)
+{
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	pm_runtime_disable(&client->dev);
+
+	if (client->irq > 0) {
+		free_irq(client->irq, bma150);
+		input_unregister_device(bma150->input);
+	} else {
+		input_unregister_polled_device(bma150->input_polled);
+		input_free_polled_device(bma150->input_polled);
+	}
+
+	kfree(bma150);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bma150_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
+
+static const struct i2c_device_id bma150_id[] = {
+	{ "bma150", 0 },
+	{ "smb380", 0 },
+	{ "bma023", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, bma150_id);
+
+static struct i2c_driver bma150_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMA150_DRIVER,
+		.pm	= &bma150_pm,
+	},
+	.class		= I2C_CLASS_HWMON,
+	.id_table	= bma150_id,
+	.probe		= bma150_probe,
+	.remove		= __devexit_p(bma150_remove),
+};
+
+static int __init BMA150_init(void)
+{
+	return i2c_add_driver(&bma150_driver);
+}
+
+static void __exit BMA150_exit(void)
+{
+	i2c_del_driver(&bma150_driver);
+}
+
+MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
+MODULE_DESCRIPTION("BMA150 driver");
+MODULE_LICENSE("GPL");
+
+module_init(BMA150_init);
+module_exit(BMA150_exit);
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/cma3000_d0x.c linux-libre-3.2-gnu1/drivers/input/misc/cma3000_d0x.c
--- linux-libre-3.1-gnu1/drivers/input/misc/cma3000_d0x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/cma3000_d0x.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/cma3000.h>
+#include <linux/module.h>
 
 #include "cma3000_d0x.h"
 
@@ -114,8 +115,8 @@ static void decode_mg(struct cma3000_acc
 static irqreturn_t cma3000_thread_irq(int irq, void *dev_id)
 {
 	struct cma3000_accl_data *data = dev_id;
-	int datax, datay, dataz;
-	u8 ctrl, mode, range, intr_status;
+	int datax, datay, dataz, intr_status;
+	u8 ctrl, mode, range;
 
 	intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
 	if (intr_status < 0)
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/dm355evm_keys.c linux-libre-3.2-gnu1/drivers/input/misc/dm355evm_keys.c
--- linux-libre-3.1-gnu1/drivers/input/misc/dm355evm_keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/dm355evm_keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/i2c/dm355evm_msp.h>
+#include <linux/module.h>
 
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/ixp4xx-beeper.c linux-libre-3.2-gnu1/drivers/input/misc/ixp4xx-beeper.c
--- linux-libre-3.1-gnu1/drivers/input/misc/ixp4xx-beeper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/ixp4xx-beeper.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@ static int __devinit ixp4xx_spkr_probe(s
 	input_dev->event = ixp4xx_spkr_event;
 
 	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
-			  IRQF_DISABLED | IRQF_NO_SUSPEND, "ixp4xx-beeper",
+			  IRQF_NO_SUSPEND, "ixp4xx-beeper",
 			  (void *) dev->id);
 	if (err)
 		goto err_free_device;
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/Kconfig linux-libre-3.2-gnu1/drivers/input/misc/Kconfig
--- linux-libre-3.1-gnu1/drivers/input/misc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,17 @@ config INPUT_AD714X_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad714x-spi.
 
+config INPUT_BMA150
+	tristate "BMA150/SMB380 acceleration sensor support"
+	depends on I2C
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you have Bosch Sensortec's BMA150 or SMB380
+	  acceleration sensor hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bma150.
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
 	depends on PCSPKR_PLATFORM
@@ -74,6 +85,29 @@ config INPUT_PCSPKR
 	  To compile this driver as a module, choose M here: the
 	  module will be called pcspkr.
 
+config INPUT_PM8XXX_VIBRATOR
+	tristate "Qualcomm PM8XXX vibrator support"
+	depends on MFD_PM8XXX
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the vibrator
+	  on Qualcomm PM8xxx chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called pm8xxx-vibrator.
+
+config INPUT_PMIC8XXX_PWRKEY
+	tristate "PMIC8XXX power key support"
+	depends on MFD_PM8XXX
+	help
+	  Say Y here if you want support for the PMIC8XXX power key.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pmic8xxx-pwrkey.
+
 config INPUT_SPARCSPKR
 	tristate "SPARC Speaker support"
 	depends on PCI && SPARC64
@@ -100,6 +134,16 @@ config INPUT_MAX8925_ONKEY
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MC13783_PWRBUTTON
+	tristate "MC13783 ON buttons"
+	depends on MFD_MC13783
+	help
+	  Support the ON buttons of MC13783 PMIC as an input device
+	  reporting power button status.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mc13783-pwrbutton.
+
 config INPUT_MMA8450
 	tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
 	depends on I2C
@@ -183,22 +227,6 @@ config INPUT_ATLAS_BTNS
 	  To compile this driver as a module, choose M here: the module will
 	  be called atlas_btns.
 
-config INPUT_ATI_REMOTE
-	tristate "ATI / X10 USB RF remote control"
-	depends on USB_ARCH_HAS_HCD
-	select USB
-	help
-	  Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
-	  These are RF remotes with USB receivers.
-	  The ATI remote comes with many of ATI's All-In-Wonder video cards.
-	  The X10 "Lola" remote is available at:
-	     <http://www.x10.com/products/lola_sg1.htm>
-	  This driver provides mouse pointer, left and right mouse buttons,
-	  and maps all the other remote buttons to keypress events.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called ati_remote.
-
 config INPUT_ATI_REMOTE2
 	tristate "ATI / Philips USB RF remote control"
 	depends on USB_ARCH_HAS_HCD
@@ -379,17 +407,6 @@ config INPUT_PWM_BEEPER
 	  To compile this driver as a module, choose M here: the module will be
 	  called pwm-beeper.
 
-config INPUT_PMIC8XXX_PWRKEY
-	tristate "PMIC8XXX power key support"
-	depends on MFD_PM8XXX
-	help
-	  Say Y here if you want support for the PMIC8XXX power key.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pmic8xxx-pwrkey.
-
 config INPUT_GPIO_ROTARY_ENCODER
 	tristate "Rotary encoders connected to GPIO pins"
 	depends on GPIOLIB && GENERIC_GPIO
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/Makefile linux-libre-3.2-gnu1/drivers/input/misc/Makefile
--- linux-libre-3.1-gnu1/drivers/input/misc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,10 +13,10 @@ obj-$(CONFIG_INPUT_ADXL34X)		+= adxl34x.
 obj-$(CONFIG_INPUT_ADXL34X_I2C)		+= adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)		+= adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)		+= apanel.o
-obj-$(CONFIG_INPUT_ATI_REMOTE)		+= ati_remote.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)		+= bfin_rotary.o
+obj-$(CONFIG_INPUT_BMA150)		+= bma150.o
 obj-$(CONFIG_INPUT_CM109)		+= cm109.o
 obj-$(CONFIG_INPUT_CMA3000)		+= cma3000_d0x.o
 obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
@@ -28,15 +28,17 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= ke
 obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
+obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
 obj-$(CONFIG_INPUT_MMA8450)		+= mma8450.o
 obj-$(CONFIG_INPUT_MPU3050)		+= mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)		+= pcap_keys.o
 obj-$(CONFIG_INPUT_PCF50633_PMU)	+= pcf50633-input.o
 obj-$(CONFIG_INPUT_PCF8574)		+= pcf8574_keypad.o
 obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
+obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR)	+= pm8xxx-vibrator.o
+obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_POWERMATE)		+= powermate.o
 obj-$(CONFIG_INPUT_PWM_BEEPER)		+= pwm-beeper.o
-obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)	+= rb532_button.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
 obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/mc13783-pwrbutton.c linux-libre-3.2-gnu1/drivers/input/misc/mc13783-pwrbutton.c
--- linux-libre-3.1-gnu1/drivers/input/misc/mc13783-pwrbutton.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/input/misc/mc13783-pwrbutton.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,282 @@
+/**
+ * Copyright (C) 2011 Philippe RÃ©tornaz
+ *
+ * Based on twl4030-pwrbutton driver by:
+ *     Peter De Schrijver <peter.de-schrijver@nokia.com>
+ *     Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+struct mc13783_pwrb {
+	struct input_dev *pwr;
+	struct mc13xxx *mc13783;
+#define MC13783_PWRB_B1_POL_INVERT	(1 << 0)
+#define MC13783_PWRB_B2_POL_INVERT	(1 << 1)
+#define MC13783_PWRB_B3_POL_INVERT	(1 << 2)
+	int flags;
+	unsigned short keymap[3];
+};
+
+#define MC13783_REG_INTERRUPT_SENSE_1		5
+#define MC13783_IRQSENSE1_ONOFD1S		(1 << 3)
+#define MC13783_IRQSENSE1_ONOFD2S		(1 << 4)
+#define MC13783_IRQSENSE1_ONOFD3S		(1 << 5)
+
+#define MC13783_REG_POWER_CONTROL_2		15
+#define MC13783_POWER_CONTROL_2_ON1BDBNC	4
+#define MC13783_POWER_CONTROL_2_ON2BDBNC	6
+#define MC13783_POWER_CONTROL_2_ON3BDBNC	8
+#define MC13783_POWER_CONTROL_2_ON1BRSTEN	(1 << 1)
+#define MC13783_POWER_CONTROL_2_ON2BRSTEN	(1 << 2)
+#define MC13783_POWER_CONTROL_2_ON3BRSTEN	(1 << 3)
+
+static irqreturn_t button_irq(int irq, void *_priv)
+{
+	struct mc13783_pwrb *priv = _priv;
+	int val;
+
+	mc13xxx_irq_ack(priv->mc13783, irq);
+	mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val);
+
+	switch (irq) {
+	case MC13783_IRQ_ONOFD1:
+		val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B1_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[0], val);
+		break;
+
+	case MC13783_IRQ_ONOFD2:
+		val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B2_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[1], val);
+		break;
+
+	case MC13783_IRQ_ONOFD3:
+		val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B3_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[2], val);
+		break;
+	}
+
+	input_sync(priv->pwr);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
+{
+	const struct mc13xxx_buttons_platform_data *pdata;
+	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
+	struct input_dev *pwr;
+	struct mc13783_pwrb *priv;
+	int err = 0;
+	int reg = 0;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	pwr = input_allocate_device();
+	if (!pwr) {
+		dev_dbg(&pdev->dev, "Can't allocate power button\n");
+		return -ENOMEM;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		err = -ENOMEM;
+		dev_dbg(&pdev->dev, "Can't allocate power button\n");
+		goto free_input_dev;
+	}
+
+	reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
+	reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
+	reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;
+
+	priv->pwr = pwr;
+	priv->mc13783 = mc13783;
+
+	mc13xxx_lock(mc13783);
+
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[0] = pdata->b1on_key;
+		if (pdata->b1on_key != KEY_RESERVED)
+			__set_bit(pdata->b1on_key, pwr->keybit);
+
+		if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B1_POL_INVERT;
+
+		if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1,
+					  button_irq, "b1on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq\n");
+			goto free_priv;
+		}
+	}
+
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[1] = pdata->b2on_key;
+		if (pdata->b2on_key != KEY_RESERVED)
+			__set_bit(pdata->b2on_key, pwr->keybit);
+
+		if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B2_POL_INVERT;
+
+		if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2,
+					  button_irq, "b2on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq\n");
+			goto free_irq_b1;
+		}
+	}
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[2] = pdata->b3on_key;
+		if (pdata->b3on_key != KEY_RESERVED)
+			__set_bit(pdata->b3on_key, pwr->keybit);
+
+		if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B3_POL_INVERT;
+
+		if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3,
+					  button_irq, "b3on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
+			goto free_irq_b2;
+		}
+	}
+
+	mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);
+
+	mc13xxx_unlock(mc13783);
+
+	pwr->name = "mc13783_pwrbutton";
+	pwr->phys = "mc13783_pwrbutton/input0";
+	pwr->dev.parent = &pdev->dev;
+
+	pwr->keycode = priv->keymap;
+	pwr->keycodemax = ARRAY_SIZE(priv->keymap);
+	pwr->keycodesize = sizeof(priv->keymap[0]);
+	__set_bit(EV_KEY, pwr->evbit);
+
+	err = input_register_device(pwr);
+	if (err) {
+		dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
+		goto free_irq;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+
+free_irq:
+	mc13xxx_lock(mc13783);
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);
+
+free_irq_b2:
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);
+
+free_irq_b1:
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
+
+free_priv:
+	mc13xxx_unlock(mc13783);
+	kfree(priv);
+
+free_input_dev:
+	input_free_device(pwr);
+
+	return err;
+}
+
+static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
+{
+	struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
+	const struct mc13xxx_buttons_platform_data *pdata;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	mc13xxx_lock(priv->mc13783);
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv);
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv);
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv);
+
+	mc13xxx_unlock(priv->mc13783);
+
+	input_unregister_device(priv->pwr);
+	kfree(priv);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+struct platform_driver mc13783_pwrbutton_driver = {
+	.probe		= mc13783_pwrbutton_probe,
+	.remove		= __devexit_p(mc13783_pwrbutton_remove),
+	.driver		= {
+		.name	= "mc13783-pwrbutton",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mc13783_pwrbutton_init(void)
+{
+	return platform_driver_register(&mc13783_pwrbutton_driver);
+}
+module_init(mc13783_pwrbutton_init);
+
+static void __exit mc13783_pwrbutton_exit(void)
+{
+	platform_driver_unregister(&mc13783_pwrbutton_driver);
+}
+module_exit(mc13783_pwrbutton_exit);
+
+MODULE_ALIAS("platform:mc13783-pwrbutton");
+MODULE_DESCRIPTION("MC13783 Power Button");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Philippe Retornaz");
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/mma8450.c linux-libre-3.2-gnu1/drivers/input/misc/mma8450.c
--- linux-libre-3.1-gnu1/drivers/input/misc/mma8450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/mma8450.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,13 +88,13 @@ static int mma8450_write(struct mma8450
 	return 0;
 }
 
-static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+static int mma8450_read_block(struct mma8450 *m, unsigned off,
+			      u8 *buf, size_t size)
 {
 	struct i2c_client *c = m->client;
-	u8 buff[6];
 	int err;
 
-	err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+	err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
 	if (err < 0) {
 		dev_err(&c->dev,
 			"failed to read block data at 0x%02x, error %d\n",
@@ -102,10 +102,6 @@ static int mma8450_read_xyz(struct mma84
 		return err;
 	}
 
-	*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
-	*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
-	*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
-
 	return 0;
 }
 
@@ -114,7 +110,7 @@ static void mma8450_poll(struct input_po
 	struct mma8450 *m = dev->private;
 	int x, y, z;
 	int ret;
-	int err;
+	u8 buf[6];
 
 	ret = mma8450_read(m, MMA8450_STATUS);
 	if (ret < 0)
@@ -123,10 +119,14 @@ static void mma8450_poll(struct input_po
 	if (!(ret & MMA8450_STATUS_ZXYDR))
 		return;
 
-	err = mma8450_read_xyz(m, &x, &y, &z);
-	if (err)
+	ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
+	if (ret < 0)
 		return;
 
+	x = ((buf[1] << 4) & 0xff0) | (buf[0] & 0xf);
+	y = ((buf[3] << 4) & 0xff0) | (buf[2] & 0xf);
+	z = ((buf[5] << 4) & 0xff0) | (buf[4] & 0xf);
+
 	input_report_abs(dev->input, ABS_X, x);
 	input_report_abs(dev->input, ABS_Y, y);
 	input_report_abs(dev->input, ABS_Z, z);
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/pm8xxx-vibrator.c linux-libre-3.2-gnu1/drivers/input/misc/pm8xxx-vibrator.c
--- linux-libre-3.1-gnu1/drivers/input/misc/pm8xxx-vibrator.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/input/misc/pm8xxx-vibrator.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,296 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+
+#define VIB_DRV			0x4A
+
+#define VIB_DRV_SEL_MASK	0xf8
+#define VIB_DRV_SEL_SHIFT	0x03
+#define VIB_DRV_EN_MANUAL_MASK	0xfc
+
+#define VIB_MAX_LEVEL_mV	(3100)
+#define VIB_MIN_LEVEL_mV	(1200)
+#define VIB_MAX_LEVELS		(VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
+
+#define MAX_FF_SPEED		0xff
+
+/**
+ * struct pm8xxx_vib - structure to hold vibrator data
+ * @vib_input_dev: input device supporting force feedback
+ * @work: work structure to set the vibration parameters
+ * @dev: device supporting force feedback
+ * @speed: speed of vibration set from userland
+ * @active: state of vibrator
+ * @level: level of vibration to set in the chip
+ * @reg_vib_drv: VIB_DRV register value
+ */
+struct pm8xxx_vib {
+	struct input_dev *vib_input_dev;
+	struct work_struct work;
+	struct device *dev;
+	int speed;
+	int level;
+	bool active;
+	u8  reg_vib_drv;
+};
+
+/**
+ * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: placeholder for data to be read
+ * @reg: register address
+ */
+static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib,
+				 u8 *data, u16 reg)
+{
+	int rc;
+
+	rc = pm8xxx_readb(vib->dev->parent, reg, data);
+	if (rc < 0)
+		dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n",
+				reg, rc);
+	return rc;
+}
+
+/**
+ * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: data to write
+ * @reg: register address
+ */
+static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib,
+				 u8 data, u16 reg)
+{
+	int rc;
+
+	rc = pm8xxx_writeb(vib->dev->parent, reg, data);
+	if (rc < 0)
+		dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n",
+				reg, rc);
+	return rc;
+}
+
+/**
+ * pm8xxx_vib_set - handler to start/stop vibration
+ * @vib: pointer to vibrator structure
+ * @on: state to set
+ */
+static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
+{
+	int rc;
+	u8 val = vib->reg_vib_drv;
+
+	if (on)
+		val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK);
+	else
+		val &= ~VIB_DRV_SEL_MASK;
+
+	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+	if (rc < 0)
+		return rc;
+
+	vib->reg_vib_drv = val;
+	return 0;
+}
+
+/**
+ * pm8xxx_work_handler - worker to set vibration level
+ * @work: pointer to work_struct
+ */
+static void pm8xxx_work_handler(struct work_struct *work)
+{
+	struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
+	int rc;
+	u8 val;
+
+	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+	if (rc < 0)
+		return;
+
+	/*
+	 * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
+	 * scale the level to fit into these ranges.
+	 */
+	if (vib->speed) {
+		vib->active = true;
+		vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
+						VIB_MIN_LEVEL_mV;
+		vib->level /= 100;
+	} else {
+		vib->active = false;
+		vib->level = VIB_MIN_LEVEL_mV / 100;
+	}
+
+	pm8xxx_vib_set(vib, vib->active);
+}
+
+/**
+ * pm8xxx_vib_close - callback of input close callback
+ * @dev: input device pointer
+ *
+ * Turns off the vibrator.
+ */
+static void pm8xxx_vib_close(struct input_dev *dev)
+{
+	struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+	cancel_work_sync(&vib->work);
+	if (vib->active)
+		pm8xxx_vib_set(vib, false);
+}
+
+/**
+ * pm8xxx_vib_play_effect - function to handle vib effects.
+ * @dev: input device pointer
+ * @data: data of effect
+ * @effect: effect to play
+ *
+ * Currently this driver supports only rumble effects.
+ */
+static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
+				  struct ff_effect *effect)
+{
+	struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+	vib->speed = effect->u.rumble.strong_magnitude >> 8;
+	if (!vib->speed)
+		vib->speed = effect->u.rumble.weak_magnitude >> 9;
+
+	schedule_work(&vib->work);
+
+	return 0;
+}
+
+static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)
+
+{
+	struct pm8xxx_vib *vib;
+	struct input_dev *input_dev;
+	int error;
+	u8 val;
+
+	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!vib || !input_dev) {
+		dev_err(&pdev->dev, "couldn't allocate memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	INIT_WORK(&vib->work, pm8xxx_work_handler);
+	vib->dev = &pdev->dev;
+	vib->vib_input_dev = input_dev;
+
+	/* operate in manual mode */
+	error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+	if (error < 0)
+		goto err_free_mem;
+	val &= ~VIB_DRV_EN_MANUAL_MASK;
+	error = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+	if (error < 0)
+		goto err_free_mem;
+
+	vib->reg_vib_drv = val;
+
+	input_dev->name = "pm8xxx_vib_ffmemless";
+	input_dev->id.version = 1;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->close = pm8xxx_vib_close;
+	input_set_drvdata(input_dev, vib);
+	input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE);
+
+	error = input_ff_create_memless(input_dev, NULL,
+					pm8xxx_vib_play_effect);
+	if (error) {
+		dev_err(&pdev->dev,
+			"couldn't register vibrator as FF device\n");
+		goto err_free_mem;
+	}
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(&pdev->dev, "couldn't register input device\n");
+		goto err_destroy_memless;
+	}
+
+	platform_set_drvdata(pdev, vib);
+	return 0;
+
+err_destroy_memless:
+	input_ff_destroy(input_dev);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(vib);
+
+	return error;
+}
+
+static int __devexit pm8xxx_vib_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_vib *vib = platform_get_drvdata(pdev);
+
+	input_unregister_device(vib->vib_input_dev);
+	kfree(vib);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm8xxx_vib_suspend(struct device *dev)
+{
+	struct pm8xxx_vib *vib = dev_get_drvdata(dev);
+
+	/* Turn off the vibrator */
+	pm8xxx_vib_set(vib, false);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
+
+static struct platform_driver pm8xxx_vib_driver = {
+	.probe		= pm8xxx_vib_probe,
+	.remove		= __devexit_p(pm8xxx_vib_remove),
+	.driver		= {
+		.name	= "pm8xxx-vib",
+		.owner	= THIS_MODULE,
+		.pm	= &pm8xxx_vib_pm_ops,
+	},
+};
+
+static int __init pm8xxx_vib_init(void)
+{
+	return platform_driver_register(&pm8xxx_vib_driver);
+}
+module_init(pm8xxx_vib_init);
+
+static void __exit pm8xxx_vib_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_vib_driver);
+}
+module_exit(pm8xxx_vib_exit);
+
+MODULE_ALIAS("platform:pm8xxx_vib");
+MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>");
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/rotary_encoder.c linux-libre-3.2-gnu1/drivers/input/misc/rotary_encoder.c
--- linux-libre-3.1-gnu1/drivers/input/misc/rotary_encoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/rotary_encoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * state machine code inspired by code from Tim Ruetz
  *
  * A generic driver for rotary encoders connected to GPIO lines.
- * See file:Documentation/input/rotary_encoder.txt for more information
+ * See file:Documentation/input/rotary-encoder.txt for more information
  *
  * 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
diff -druNp linux-libre-3.1-gnu1/drivers/input/misc/twl6040-vibra.c linux-libre-3.2-gnu1/drivers/input/misc/twl6040-vibra.c
--- linux-libre-3.1-gnu1/drivers/input/misc/twl6040-vibra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/misc/twl6040-vibra.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,12 +74,12 @@ static irqreturn_t twl6040_vib_irq_handl
 	if (status & TWL6040_VIBLOCDET) {
 		dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
-				   TWL6040_VIBENAL);
+				   TWL6040_VIBENA);
 	}
 	if (status & TWL6040_VIBROCDET) {
 		dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
-				   TWL6040_VIBENAR);
+				   TWL6040_VIBENA);
 	}
 
 	return IRQ_HANDLED;
@@ -97,23 +97,23 @@ static void twl6040_vibra_enable(struct
 	}
 
 	twl6040_power(info->twl6040, 1);
-	if (twl6040->rev <= TWL6040_REV_ES1_1) {
+	if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) {
 		/*
 		 * ERRATA: Disable overcurrent protection for at least
 		 * 3ms when enabling vibrator drivers to avoid false
 		 * overcurrent detection
 		 */
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-				  TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-				  TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		usleep_range(3000, 3500);
 	}
 
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-			  TWL6040_VIBENAL);
+			  TWL6040_VIBENA);
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-			  TWL6040_VIBENAR);
+			  TWL6040_VIBENA);
 
 	info->enabled = true;
 }
@@ -201,6 +201,13 @@ static int vibra_play(struct input_dev *
 	struct vibra_info *info = input_get_drvdata(input);
 	int ret;
 
+	/* Do not allow effect, while the routing is set to use audio */
+	ret = twl6040_get_vibralr_status(info->twl6040);
+	if (ret & TWL6040_VIBSEL) {
+		dev_info(&input->dev, "Vibra is configured for audio\n");
+		return -EBUSY;
+	}
+
 	info->weak_speed = effect->u.rumble.weak_magnitude;
 	info->strong_speed = effect->u.rumble.strong_magnitude;
 	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
@@ -228,7 +235,7 @@ static void twl6040_vibra_close(struct i
 	mutex_unlock(&info->mutex);
 }
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int twl6040_vibra_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/alps.c linux-libre-3.2-gnu1/drivers/input/mouse/alps.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/alps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/alps.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,13 +23,6 @@
 #include "psmouse.h"
 #include "alps.h"
 
-#undef DEBUG
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
 #define ALPS_OLDPROTO		0x01	/* old style input */
 #define ALPS_DUALPOINT		0x02	/* touchpad has trackstick */
 #define ALPS_PASS		0x04	/* device has a pass-through port */
@@ -297,10 +290,10 @@ static psmouse_ret_t alps_handle_interle
 		      psmouse->packet[4] |
 		      psmouse->packet[5]) & 0x80) ||
 		    (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
-			dbg("refusing packet %x %x %x %x "
-			    "(suspected interleaved ps/2)\n",
-			    psmouse->packet[3], psmouse->packet[4],
-			    psmouse->packet[5], psmouse->packet[6]);
+			psmouse_dbg(psmouse,
+				    "refusing packet %x %x %x %x (suspected interleaved ps/2)\n",
+				    psmouse->packet[3], psmouse->packet[4],
+				    psmouse->packet[5], psmouse->packet[6]);
 			return PSMOUSE_BAD_DATA;
 		}
 
@@ -319,13 +312,13 @@ static psmouse_ret_t alps_handle_interle
 		 * There is also possibility that we got 6-byte ALPS
 		 * packet followed  by 3-byte packet from trackpoint. We
 		 * can not distinguish between these 2 scenarios but
-		 * becase the latter is unlikely to happen in course of
+		 * because the latter is unlikely to happen in course of
 		 * normal operation (user would need to press all
 		 * buttons on the pad and start moving trackpoint
 		 * without touching the pad surface) we assume former.
 		 * Even if we are wrong the wost thing that would happen
 		 * the cursor would jump but we should not get protocol
-		 * desynchronization.
+		 * de-synchronization.
 		 */
 
 		alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
@@ -361,10 +354,10 @@ static void alps_flush_packet(unsigned l
 		if ((psmouse->packet[3] |
 		     psmouse->packet[4] |
 		     psmouse->packet[5]) & 0x80) {
-			dbg("refusing packet %x %x %x "
-			    "(suspected interleaved ps/2)\n",
-			    psmouse->packet[3], psmouse->packet[4],
-			    psmouse->packet[5]);
+			psmouse_dbg(psmouse,
+				    "refusing packet %x %x %x (suspected interleaved ps/2)\n",
+				    psmouse->packet[3], psmouse->packet[4],
+				    psmouse->packet[5]);
 		} else {
 			alps_process_packet(psmouse);
 		}
@@ -396,16 +389,18 @@ static psmouse_ret_t alps_process_byte(s
 	}
 
 	if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
-		dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
-		    psmouse->packet[0], model->mask0, model->byte0);
+		psmouse_dbg(psmouse,
+			    "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+			    psmouse->packet[0], model->mask0, model->byte0);
 		return PSMOUSE_BAD_DATA;
 	}
 
 	/* Bytes 2 - 6 should have 0 in the highest bit */
 	if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
 	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
-		dbg("refusing packet[%i] = %x\n",
-		    psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
+		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+			    psmouse->pktcnt - 1,
+			    psmouse->packet[psmouse->pktcnt - 1]);
 		return PSMOUSE_BAD_DATA;
 	}
 
@@ -439,7 +434,8 @@ static const struct alps_model_info *alp
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return NULL;
 
-	dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
 		return NULL;
@@ -459,7 +455,8 @@ static const struct alps_model_info *alp
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return NULL;
 
-	dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	if (version) {
 		for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
@@ -527,7 +524,8 @@ static int alps_get_status(struct psmous
 	    ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return -1;
 
-	dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	return 0;
 }
@@ -605,12 +603,12 @@ static int alps_hw_init(struct psmouse *
 	}
 
 	if (alps_tap_mode(psmouse, true)) {
-		printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
+		psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
 		return -1;
 	}
 
 	if (alps_absolute_mode(psmouse)) {
-		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+		psmouse_err(psmouse, "Failed to enable absolute mode\n");
 		return -1;
 	}
 
@@ -621,7 +619,7 @@ static int alps_hw_init(struct psmouse *
 
 	/* ALPS needs stream mode, otherwise it won't report any data */
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
-		printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+		psmouse_err(psmouse, "Failed to enable stream mode\n");
 		return -1;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/elantech.c linux-libre-3.2-gnu1/drivers/input/mouse/elantech.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/elantech.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/elantech.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,6 @@
  * Trademarks are the property of their respective owners.
  */
 
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -25,13 +23,10 @@
 #define elantech_debug(fmt, ...)					\
 	do {								\
 		if (etd->debug)						\
-			printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__);	\
+			psmouse_printk(KERN_DEBUG, psmouse,		\
+					fmt, ##__VA_ARGS__);		\
 	} while (0)
 
-static bool force_elantech;
-module_param_named(force_elantech, force_elantech, bool, 0644);
-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
-
 /*
  * Send a Synaptics style sliced query command
  */
@@ -40,7 +35,7 @@ static int synaptics_send_cmd(struct psm
 {
 	if (psmouse_sliced_command(psmouse, c) ||
 	    ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-		pr_err("synaptics_send_cmd query 0x%02x failed.\n", c);
+		psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
 		return -1;
 	}
 
@@ -69,7 +64,7 @@ static int elantech_ps2_command(struct p
 	} while (tries > 0);
 
 	if (rc)
-		pr_err("ps2 command 0x%02x failed.\n", command);
+		psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
 
 	return rc;
 }
@@ -84,7 +79,7 @@ static int elantech_read_reg(struct psmo
 	unsigned char param[3];
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
+	if (reg < 0x07 || reg > 0x26)
 		return -1;
 
 	if (reg > 0x11 && reg < 0x20)
@@ -108,12 +103,24 @@ static int elantech_read_reg(struct psmo
 			rc = -1;
 		}
 		break;
+
+	case 3 ... 4:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
-		pr_err("failed to read register 0x%02x.\n", reg);
-	else
+		psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
+	else if (etd->hw_version != 4)
 		*val = param[0];
+	else
+		*val = param[1];
 
 	return rc;
 }
@@ -127,7 +134,7 @@ static int elantech_write_reg(struct psm
 	struct elantech_data *etd = psmouse->private;
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
+	if (reg < 0x07 || reg > 0x26)
 		return -1;
 
 	if (reg > 0x11 && reg < 0x20)
@@ -154,11 +161,38 @@ static int elantech_write_reg(struct psm
 			rc = -1;
 		}
 		break;
+
+	case 3:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
+
+	case 4:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
-		pr_err("failed to write register 0x%02x with value 0x%02x.\n",
-			reg, val);
+		psmouse_err(psmouse,
+			    "failed to write register 0x%02x with value 0x%02x.\n",
+			    reg, val);
 
 	return rc;
 }
@@ -166,13 +200,13 @@ static int elantech_write_reg(struct psm
 /*
  * Dump a complete mouse movement packet to the syslog
  */
-static void elantech_packet_dump(unsigned char *packet, int size)
+static void elantech_packet_dump(struct psmouse *psmouse)
 {
 	int	i;
 
-	printk(KERN_DEBUG pr_fmt("PS/2 packet ["));
-	for (i = 0; i < size; i++)
-		printk("%s0x%02x ", (i) ? ", " : " ", packet[i]);
+	psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
+	for (i = 0; i < psmouse->pktsize; i++)
+		printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
 	printk("]\n");
 }
 
@@ -223,7 +257,7 @@ static void elantech_report_absolute_v1(
 		input_report_abs(dev, ABS_X,
 			((packet[1] & 0x0c) << 6) | packet[2]);
 		input_report_abs(dev, ABS_Y,
-			ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
+			etd->y_max - (((packet[1] & 0x03) << 8) | packet[3]));
 	}
 
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -233,7 +267,7 @@ static void elantech_report_absolute_v1(
 	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 
 	if (etd->fw_version < 0x020000 &&
-	    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+	    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 		/* rocker up */
 		input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
 		/* rocker down */
@@ -273,11 +307,11 @@ static void elantech_report_absolute_v2(
 	struct elantech_data *etd = psmouse->private;
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
-	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0;
+	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
 
 	/* byte 0: n1  n0   .   .   .   .   R   L */
 	fingers = (packet[0] & 0xc0) >> 6;
-	input_report_key(dev, BTN_TOUCH, fingers != 0);
 
 	switch (fingers) {
 	case 3:
@@ -290,18 +324,15 @@ static void elantech_report_absolute_v2(
 		/* pass through... */
 	case 1:
 		/*
-		 * byte 1:  .   .   .   .   .  x10 x9  x8
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
 		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
 		 */
-		x1 = ((packet[1] & 0x07) << 8) | packet[2];
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
 		/*
-		 * byte 4:  .   .   .   .   .   .  y9  y8
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
 		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
 		 */
-		y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]);
-
-		input_report_abs(dev, ABS_X, x1);
-		input_report_abs(dev, ABS_Y, y1);
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
 
 		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
 		width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
@@ -314,22 +345,18 @@ static void elantech_report_absolute_v2(
 		 * byte 0:  .   .  ay8 ax8  .   .   .   .
 		 * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
 		 */
-		x1 = ((packet[0] & 0x10) << 4) | packet[1];
+		x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
 		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
-		y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
+		y1 = etd->y_max -
+			((((packet[0] & 0x20) << 3) | packet[2]) << 2);
 		/*
 		 * byte 3:  .   .  by8 bx8  .   .   .   .
 		 * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
 		 */
-		x2 = ((packet[3] & 0x10) << 4) | packet[4];
+		x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
 		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
-		y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
-		/*
-		 * For compatibility with the X Synaptics driver scale up
-		 * one coordinate and report as ordinary mouse movent
-		 */
-		input_report_abs(dev, ABS_X, x1 << 2);
-		input_report_abs(dev, ABS_Y, y1 << 2);
+		y2 = etd->y_max -
+			((((packet[3] & 0x20) << 3) | packet[5]) << 2);
 
 		/* Unknown so just report sensible values */
 		pres = 127;
@@ -337,6 +364,11 @@ static void elantech_report_absolute_v2(
 		break;
 	}
 
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
 	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
 	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
@@ -352,7 +384,208 @@ static void elantech_report_absolute_v2(
 	input_sync(dev);
 }
 
-static int elantech_check_parity_v1(struct psmouse *psmouse)
+/*
+ * Interpret complete data packets and report absolute mode input events for
+ * hardware version 3. (12 byte packets for two fingers)
+ */
+static void elantech_report_absolute_v3(struct psmouse *psmouse,
+					int packet_type)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
+
+	/* byte 0: n1  n0   .   .   .   .   R   L */
+	fingers = (packet[0] & 0xc0) >> 6;
+
+	switch (fingers) {
+	case 3:
+	case 1:
+		/*
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
+		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
+		 */
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
+		/*
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
+		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+		 */
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+
+	case 2:
+		if (packet_type == PACKET_V3_HEAD) {
+			/*
+			 * byte 1:   .    .    .    .  ax11 ax10 ax9  ax8
+			 * byte 2: ax7  ax6  ax5  ax4  ax3  ax2  ax1  ax0
+			 */
+			etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
+			/*
+			 * byte 4:   .    .    .    .  ay11 ay10 ay9  ay8
+			 * byte 5: ay7  ay6  ay5  ay4  ay3  ay2  ay1  ay0
+			 */
+			etd->mt[0].y = etd->y_max -
+				(((packet[4] & 0x0f) << 8) | packet[5]);
+			/*
+			 * wait for next packet
+			 */
+			return;
+		}
+
+		/* packet_type == PACKET_V3_TAIL */
+		x1 = etd->mt[0].x;
+		y1 = etd->mt[0].y;
+		x2 = ((packet[1] & 0x0f) << 8) | packet[2];
+		y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+	}
+
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
+
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
+	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
+	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
+	input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_report_abs(dev, ABS_PRESSURE, pres);
+	input_report_abs(dev, ABS_TOOL_WIDTH, width);
+
+	input_sync(dev);
+}
+
+static void elantech_input_sync_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_mt_report_pointer_emulation(dev, true);
+	input_sync(dev);
+}
+
+static void process_packet_status_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+	unsigned fingers;
+	int i;
+
+	/* notify finger state change */
+	fingers = packet[1] & 0x1f;
+	for (i = 0; i < ETP_MAX_FINGERS; i++) {
+		if ((fingers & (1 << i)) == 0) {
+			input_mt_slot(dev, i);
+			input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+		}
+	}
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_head_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int id = ((packet[3] & 0xe0) >> 5) - 1;
+	int pres, traces;
+
+	if (id < 0)
+		return;
+
+	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+	etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	traces = (packet[0] & 0xf0) >> 4;
+
+	input_mt_slot(dev, id);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+	input_report_abs(dev, ABS_MT_PRESSURE, pres);
+	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+	/* report this for backwards compatibility */
+	input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_motion_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
+	int id, sid;
+
+	id = ((packet[0] & 0xe0) >> 5) - 1;
+	if (id < 0)
+		return;
+
+	sid = ((packet[3] & 0xe0) >> 5) - 1;
+	weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
+	/*
+	 * Motion packets give us the delta of x, y values of specific fingers,
+	 * but in two's complement. Let the compiler do the conversion for us.
+	 * Also _enlarge_ the numbers to int, in case of overflow.
+	 */
+	delta_x1 = (signed char)packet[1];
+	delta_y1 = (signed char)packet[2];
+	delta_x2 = (signed char)packet[4];
+	delta_y2 = (signed char)packet[5];
+
+	etd->mt[id].x += delta_x1 * weight;
+	etd->mt[id].y -= delta_y1 * weight;
+	input_mt_slot(dev, id);
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+
+	if (sid >= 0) {
+		etd->mt[sid].x += delta_x2 * weight;
+		etd->mt[sid].y -= delta_y2 * weight;
+		input_mt_slot(dev, sid);
+		input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
+	}
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void elantech_report_absolute_v4(struct psmouse *psmouse,
+					int packet_type)
+{
+	switch (packet_type) {
+	case PACKET_V4_STATUS:
+		process_packet_status_v4(psmouse);
+		break;
+
+	case PACKET_V4_HEAD:
+		process_packet_head_v4(psmouse);
+		break;
+
+	case PACKET_V4_MOTION:
+		process_packet_motion_v4(psmouse);
+		break;
+
+	case PACKET_UNKNOWN:
+	default:
+		/* impossible to get here */
+		break;
+	}
+}
+
+static int elantech_packet_check_v1(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
@@ -376,31 +609,142 @@ static int elantech_check_parity_v1(stru
 	       etd->parity[packet[3]] == p3;
 }
 
+static int elantech_debounce_check_v2(struct psmouse *psmouse)
+{
+        /*
+         * When we encounter packet that matches this exactly, it means the
+         * hardware is in debounce status. Just ignore the whole packet.
+         */
+        const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
+        unsigned char *packet = psmouse->packet;
+
+        return !memcmp(packet, debounce_packet, sizeof(debounce_packet));
+}
+
+static int elantech_packet_check_v2(struct psmouse *psmouse)
+{
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * V2 hardware has two flavors. Older ones that do not report pressure,
+	 * and newer ones that reports pressure and width. With newer ones, all
+	 * packets (1, 2, 3 finger touch) have the same constant bits. With
+	 * older ones, 1/3 finger touch packets and 2 finger touch packets
+	 * have different constant bits.
+	 * With all three cases, if the constant bits are not exactly what I
+	 * expected, I consider them invalid.
+	 */
+	if (etd->reports_pressure)
+		return (packet[0] & 0x0c) == 0x04 &&
+		       (packet[3] & 0x0f) == 0x02;
+
+	if ((packet[0] & 0xc0) == 0x80)
+		return (packet[0] & 0x0c) == 0x0c &&
+		       (packet[3] & 0x0e) == 0x08;
+
+	return (packet[0] & 0x3c) == 0x3c &&
+	       (packet[1] & 0xf0) == 0x00 &&
+	       (packet[3] & 0x3e) == 0x38 &&
+	       (packet[4] & 0xf0) == 0x00;
+}
+
+/*
+ * We check the constant bits to determine what packet type we get,
+ * so packet checking is mandatory for v3 and later hardware.
+ */
+static int elantech_packet_check_v3(struct psmouse *psmouse)
+{
+	const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * check debounce first, it has the same signature in byte 0
+	 * and byte 3 as PACKET_V3_HEAD.
+	 */
+	if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
+		return PACKET_DEBOUNCE;
+
+	if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+		return PACKET_V3_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+		return PACKET_V3_TAIL;
+
+	return PACKET_UNKNOWN;
+}
+
+static int elantech_packet_check_v4(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x11)
+		return PACKET_V4_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x12)
+		return PACKET_V4_MOTION;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x10)
+		return PACKET_V4_STATUS;
+
+	return PACKET_UNKNOWN;
+}
+
 /*
  * Process byte stream from mouse and handle complete packets
  */
 static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
+	int packet_type;
 
 	if (psmouse->pktcnt < psmouse->pktsize)
 		return PSMOUSE_GOOD_DATA;
 
 	if (etd->debug > 1)
-		elantech_packet_dump(psmouse->packet, psmouse->pktsize);
+		elantech_packet_dump(psmouse);
 
 	switch (etd->hw_version) {
 	case 1:
-		if (etd->paritycheck && !elantech_check_parity_v1(psmouse))
+		if (etd->paritycheck && !elantech_packet_check_v1(psmouse))
 			return PSMOUSE_BAD_DATA;
 
 		elantech_report_absolute_v1(psmouse);
 		break;
 
 	case 2:
-		/* We don't know how to check parity in protocol v2 */
+		/* ignore debounce */
+		if (elantech_debounce_check_v2(psmouse))
+			return PSMOUSE_FULL_PACKET;
+
+		if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
+			return PSMOUSE_BAD_DATA;
+
 		elantech_report_absolute_v2(psmouse);
 		break;
+
+	case 3:
+		packet_type = elantech_packet_check_v3(psmouse);
+		/* ignore debounce */
+		if (packet_type == PACKET_DEBOUNCE)
+			return PSMOUSE_FULL_PACKET;
+
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v3(psmouse, packet_type);
+		break;
+
+	case 4:
+		packet_type = elantech_packet_check_v4(psmouse);
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v4(psmouse, packet_type);
+		break;
 	}
 
 	return PSMOUSE_FULL_PACKET;
@@ -435,15 +779,29 @@ static int elantech_set_absolute_mode(st
 		    elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
 		    elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
 			rc = -1;
-			break;
 		}
+		break;
+
+	case 3:
+		etd->reg_10 = 0x0b;
+		if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
+			rc = -1;
+
+		break;
+
+	case 4:
+		etd->reg_07 = 0x01;
+		if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+			rc = -1;
+
+		goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
 	}
 
 	if (rc == 0) {
 		/*
 		 * Read back reg 0x10. For hardware version 1 we must make
 		 * sure the absolute mode bit is set. For hardware version 2
-		 * the touchpad is probably initalising and not ready until
+		 * the touchpad is probably initializing and not ready until
 		 * we read back the value we just wrote.
 		 */
 		do {
@@ -456,27 +814,115 @@ static int elantech_set_absolute_mode(st
 		} while (tries > 0);
 
 		if (rc) {
-			pr_err("failed to read back register 0x10.\n");
+			psmouse_err(psmouse,
+				    "failed to read back register 0x10.\n");
 		} else if (etd->hw_version == 1 &&
 			   !(val & ETP_R10_ABSOLUTE_MODE)) {
-			pr_err("touchpad refuses to switch to absolute mode.\n");
+			psmouse_err(psmouse,
+				    "touchpad refuses to switch to absolute mode.\n");
 			rc = -1;
 		}
 	}
 
+ skip_readback_reg_10:
 	if (rc)
-		pr_err("failed to initialise registers.\n");
+		psmouse_err(psmouse, "failed to initialise registers.\n");
 
 	return rc;
 }
 
+static int elantech_set_range(struct psmouse *psmouse,
+			      unsigned int *x_min, unsigned int *y_min,
+			      unsigned int *x_max, unsigned int *y_max,
+			      unsigned int *width)
+{
+	struct elantech_data *etd = psmouse->private;
+	unsigned char param[3];
+	unsigned char traces;
+
+	switch (etd->hw_version) {
+	case 1:
+		*x_min = ETP_XMIN_V1;
+		*y_min = ETP_YMIN_V1;
+		*x_max = ETP_XMAX_V1;
+		*y_max = ETP_YMAX_V1;
+		break;
+
+	case 2:
+		if (etd->fw_version == 0x020800 ||
+		    etd->fw_version == 0x020b00 ||
+		    etd->fw_version == 0x020030) {
+			*x_min = ETP_XMIN_V2;
+			*y_min = ETP_YMIN_V2;
+			*x_max = ETP_XMAX_V2;
+			*y_max = ETP_YMAX_V2;
+		} else {
+			int i;
+			int fixed_dpi;
+
+			i = (etd->fw_version > 0x020800 &&
+			     etd->fw_version < 0x020900) ? 1 : 2;
+
+			if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+				return -1;
+
+			fixed_dpi = param[1] & 0x10;
+
+			if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
+				if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+					return -1;
+
+				*x_max = (etd->capabilities[1] - i) * param[1] / 2;
+				*y_max = (etd->capabilities[2] - i) * param[2] / 2;
+			} else if (etd->fw_version == 0x040216) {
+				*x_max = 819;
+				*y_max = 405;
+			} else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) {
+				*x_max = 900;
+				*y_max = 500;
+			} else {
+				*x_max = (etd->capabilities[1] - i) * 64;
+				*y_max = (etd->capabilities[2] - i) * 64;
+			}
+		}
+		break;
+
+	case 3:
+		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			return -1;
+
+		*x_max = (0x0f & param[0]) << 8 | param[1];
+		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		break;
+
+	case 4:
+		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			return -1;
+
+		*x_max = (0x0f & param[0]) << 8 | param[1];
+		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		traces = etd->capabilities[1];
+		if ((traces < 2) || (traces > *x_max))
+			return -1;
+
+		*width = *x_max / (traces - 1);
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Set the appropriate event bits for the input subsystem
  */
-static void elantech_set_input_params(struct psmouse *psmouse)
+static int elantech_set_input_params(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
+	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
+
+	if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
+		return -1;
 
 	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
@@ -494,30 +940,64 @@ static void elantech_set_input_params(st
 	case 1:
 		/* Rocker button */
 		if (etd->fw_version < 0x020000 &&
-		    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+		    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 			__set_bit(BTN_FORWARD, dev->keybit);
 			__set_bit(BTN_BACK, dev->keybit);
 		}
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0);
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		break;
 
 	case 2:
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+		/* fall through */
+	case 3:
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		if (etd->reports_pressure) {
 			input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
 					     ETP_PMAX_V2, 0, 0);
 			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 					     ETP_WMAX_V2, 0, 0);
 		}
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		break;
+
+	case 4:
+		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		/* For X to recognize me as touchpad. */
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+		/*
+		 * range of pressure and width is the same as v2,
+		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
+		 */
+		input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+				     ETP_WMAX_V2, 0, 0);
+		/* Multitouch capable pad, up to 5 fingers. */
+		input_mt_init_slots(dev, ETP_MAX_FINGERS);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		/*
+		 * The firmware reports how many trace lines the finger spans,
+		 * convert to surface unit as Protocol-B requires.
+		 */
+		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+				     ETP_WMAX_V2 * width, 0, 0);
 		break;
 	}
+
+	etd->y_max = y_max;
+	etd->width = width;
+
+	return 0;
 }
 
 struct elantech_attr_data {
@@ -587,6 +1067,7 @@ static ssize_t elantech_set_int_attr(str
 			    elantech_show_int_attr,			\
 			    elantech_set_int_attr)
 
+ELANTECH_INT_ATTR(reg_07, 0x07);
 ELANTECH_INT_ATTR(reg_10, 0x10);
 ELANTECH_INT_ATTR(reg_11, 0x11);
 ELANTECH_INT_ATTR(reg_20, 0x20);
@@ -600,6 +1081,7 @@ ELANTECH_INT_ATTR(debug, 0);
 ELANTECH_INT_ATTR(paritycheck, 0);
 
 static struct attribute *elantech_attrs[] = {
+	&psmouse_attr_reg_07.dattr.attr,
 	&psmouse_attr_reg_10.dattr.attr,
 	&psmouse_attr_reg_11.dattr.attr,
 	&psmouse_attr_reg_20.dattr.attr,
@@ -651,7 +1133,7 @@ int elantech_detect(struct psmouse *psmo
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-		pr_debug("sending Elantech magic knock failed.\n");
+		psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n");
 		return -1;
 	}
 
@@ -659,9 +1141,11 @@ int elantech_detect(struct psmouse *psmo
 	 * Report this in case there are Elantech models that use a different
 	 * set of magic numbers
 	 */
-	if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
-		pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
-			 param[0], param[1], param[2]);
+	if (param[0] != 0x3c || param[1] != 0x03 ||
+	    (param[2] != 0xc8 && param[2] != 0x00)) {
+		psmouse_dbg(psmouse,
+			    "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+			    param[0], param[1], param[2]);
 		return -1;
 	}
 
@@ -671,20 +1155,18 @@ int elantech_detect(struct psmouse *psmo
 	 * to Elantech magic knock and there might be more.
 	 */
 	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-		pr_debug("failed to query firmware version.\n");
+		psmouse_dbg(psmouse, "failed to query firmware version.\n");
 		return -1;
 	}
 
-	pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
-		 param[0], param[1], param[2]);
+	psmouse_dbg(psmouse,
+		    "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+		    param[0], param[1], param[2]);
 
 	if (!elantech_is_signature_valid(param)) {
-		if (!force_elantech) {
-			pr_debug("Probably not a real Elantech touchpad. Aborting.\n");
-			return -1;
-		}
-
-		pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
+		psmouse_dbg(psmouse,
+			    "Probably not a real Elantech touchpad. Aborting.\n");
+		return -1;
 	}
 
 	if (set_properties) {
@@ -715,7 +1197,8 @@ static int elantech_reconnect(struct psm
 		return -1;
 
 	if (elantech_set_absolute_mode(psmouse)) {
-		pr_err("failed to put touchpad back into absolute mode.\n");
+		psmouse_err(psmouse,
+			    "failed to put touchpad back into absolute mode.\n");
 		return -1;
 	}
 
@@ -723,6 +1206,58 @@ static int elantech_reconnect(struct psm
 }
 
 /*
+ * determine hardware version and set some properties according to it.
+ */
+static int elantech_set_properties(struct elantech_data *etd)
+{
+	/* This represents the version of IC body. */
+	int ver = (etd->fw_version & 0x0f0000) >> 16;
+
+	/* Early version of Elan touchpads doesn't obey the rule. */
+	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
+		etd->hw_version = 1;
+	else {
+		switch (ver) {
+		case 2:
+		case 4:
+			etd->hw_version = 2;
+			break;
+		case 5:
+			etd->hw_version = 3;
+			break;
+		case 6:
+			etd->hw_version = 4;
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	/*
+	 * Turn on packet checking by default.
+	 */
+	etd->paritycheck = 1;
+
+	/*
+	 * This firmware suffers from misreporting coordinates when
+	 * a touch action starts causing the mouse cursor or scrolled page
+	 * to jump. Enable a workaround.
+	 */
+	etd->jumpy_cursor =
+		(etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
+
+	if (etd->hw_version > 1) {
+		/* For now show extra debug information */
+		etd->debug = 1;
+
+		if (etd->fw_version >= 0x020800)
+			etd->reports_pressure = true;
+	}
+
+	return 0;
+}
+
+/*
  * Initialize the touchpad and create sysfs entries
  */
 int elantech_init(struct psmouse *psmouse)
@@ -743,70 +1278,53 @@ int elantech_init(struct psmouse *psmous
 	 * Do the version query again so we can store the result
 	 */
 	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-		pr_err("failed to query firmware version.\n");
+		psmouse_err(psmouse, "failed to query firmware version.\n");
 		goto init_fail;
 	}
-
 	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
 
-	/*
-	 * Assume every version greater than this is new EeePC style
-	 * hardware with 6 byte packets
-	 */
-	if (etd->fw_version >= 0x020030) {
-		etd->hw_version = 2;
-		/* For now show extra debug information */
-		etd->debug = 1;
-		/* Don't know how to do parity checking for version 2 */
-		etd->paritycheck = 0;
-
-		if (etd->fw_version >= 0x020800)
-			etd->reports_pressure = true;
-
-	} else {
-		etd->hw_version = 1;
-		etd->paritycheck = 1;
-	}
-
-	pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
-		etd->hw_version, param[0], param[1], param[2]);
-
-	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
-		pr_err("failed to query capabilities.\n");
+	if (elantech_set_properties(etd)) {
+		psmouse_err(psmouse, "unknown hardware version, aborting...\n");
 		goto init_fail;
 	}
-	pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
-		param[0], param[1], param[2]);
-	etd->capabilities = param[0];
+	psmouse_info(psmouse,
+		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
+		     etd->hw_version, param[0], param[1], param[2]);
 
-	/*
-	 * This firmware suffers from misreporting coordinates when
-	 * a touch action starts causing the mouse cursor or scrolled page
-	 * to jump. Enable a workaround.
-	 */
-	if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
-		pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n");
-		etd->jumpy_cursor = true;
+	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+	    etd->capabilities)) {
+		psmouse_err(psmouse, "failed to query capabilities.\n");
+		goto init_fail;
 	}
+	psmouse_info(psmouse,
+		     "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+		     etd->capabilities[0], etd->capabilities[1],
+		     etd->capabilities[2]);
 
 	if (elantech_set_absolute_mode(psmouse)) {
-		pr_err("failed to put touchpad into absolute mode.\n");
+		psmouse_err(psmouse,
+			    "failed to put touchpad into absolute mode.\n");
 		goto init_fail;
 	}
 
-	elantech_set_input_params(psmouse);
+	if (elantech_set_input_params(psmouse)) {
+		psmouse_err(psmouse, "failed to query touchpad range.\n");
+		goto init_fail;
+	}
 
 	error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
 				   &elantech_attr_group);
 	if (error) {
-		pr_err("failed to create sysfs attributes, error: %d.\n", error);
+		psmouse_err(psmouse,
+			    "failed to create sysfs attributes, error: %d.\n",
+			    error);
 		goto init_fail;
 	}
 
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
-	psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
+	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/elantech.h linux-libre-3.2-gnu1/drivers/input/mouse/elantech.h
--- linux-libre-3.1-gnu1/drivers/input/mouse/elantech.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/elantech.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,14 +16,17 @@
 /*
  * Command values for Synaptics style queries
  */
+#define ETP_FW_ID_QUERY			0x00
 #define ETP_FW_VERSION_QUERY		0x01
 #define ETP_CAPABILITIES_QUERY		0x02
+#define ETP_SAMPLE_QUERY		0x03
 
 /*
  * Command values for register reading or writing
  */
 #define ETP_REGISTER_READ		0x10
 #define ETP_REGISTER_WRITE		0x11
+#define ETP_REGISTER_READWRITE		0x00
 
 /*
  * Hardware version 2 custom PS/2 command value
@@ -66,16 +69,13 @@
 #define ETP_YMAX_V1			(384 - ETP_EDGE_FUZZ_V1)
 
 /*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
  */
-#define ETP_EDGE_FUZZ_V2		8
-
-#define ETP_XMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2			(1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2			( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2			0
+#define ETP_XMAX_V2			1152
+#define ETP_YMIN_V2			0
+#define ETP_YMAX_V2			768
 
 #define ETP_PMIN_V2			0
 #define ETP_PMAX_V2			255
@@ -83,17 +83,37 @@
 #define ETP_WMAX_V2			15
 
 /*
- * For two finger touches the coordinate of each finger gets reported
- * separately but with reduced resolution.
+ * v3 hardware has 2 kinds of packet types,
+ * v4 hardware has 3.
  */
-#define ETP_2FT_FUZZ			4
+#define PACKET_UNKNOWN			0x01
+#define PACKET_DEBOUNCE			0x02
+#define PACKET_V3_HEAD			0x03
+#define PACKET_V3_TAIL			0x04
+#define PACKET_V4_HEAD			0x05
+#define PACKET_V4_MOTION		0x06
+#define PACKET_V4_STATUS		0x07
 
-#define ETP_2FT_XMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_XMAX			(288 - ETP_2FT_FUZZ)
-#define ETP_2FT_YMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_YMAX			(192 - ETP_2FT_FUZZ)
+/*
+ * track up to 5 fingers for v4 hardware
+ */
+#define ETP_MAX_FINGERS			5
+
+/*
+ * weight value for v4 hardware
+ */
+#define ETP_WEIGHT_VALUE		5
+
+/*
+ * The base position for one finger, v4 hardware
+ */
+struct finger_pos {
+	unsigned int x;
+	unsigned int y;
+};
 
 struct elantech_data {
+	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;
 	unsigned char reg_20;
@@ -104,13 +124,16 @@ struct elantech_data {
 	unsigned char reg_25;
 	unsigned char reg_26;
 	unsigned char debug;
-	unsigned char capabilities;
+	unsigned char capabilities[3];
 	bool paritycheck;
 	bool jumpy_cursor;
 	bool reports_pressure;
 	unsigned char hw_version;
 	unsigned int fw_version;
 	unsigned int single_finger_reports;
+	unsigned int y_max;
+	unsigned int width;
+	struct finger_pos mt[ETP_MAX_FINGERS];
 	unsigned char parity[256];
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/hgpk.c linux-libre-3.2-gnu1/drivers/input/mouse/hgpk.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/hgpk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/hgpk.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,10 +136,10 @@ static int hgpk_discard_decay_hack(struc
 	/* discard if too big, or half that but > 4 times the prev delta */
 	if (avx > recalib_delta ||
 		(avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
-		hgpk_err(psmouse, "detected %dpx jump in x\n", x);
+		psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
 		priv->xbigj = avx;
 	} else if (approx_half(avx, priv->xbigj)) {
-		hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
+		psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
 		priv->xbigj = avx;
 		priv->xsaw_secondary++;
 	} else {
@@ -151,10 +151,10 @@ static int hgpk_discard_decay_hack(struc
 
 	if (avy > recalib_delta ||
 		(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
-		hgpk_err(psmouse, "detected %dpx jump in y\n", y);
+		psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
 		priv->ybigj = avy;
 	} else if (approx_half(avy, priv->ybigj)) {
-		hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
+		psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
 		priv->ybigj = avy;
 		priv->ysaw_secondary++;
 	} else {
@@ -168,7 +168,7 @@ static int hgpk_discard_decay_hack(struc
 	priv->ylast = avy;
 
 	if (do_recal && jumpy_delay) {
-		hgpk_err(psmouse, "scheduling recalibration\n");
+		psmouse_warn(psmouse, "scheduling recalibration\n");
 		psmouse_queue_work(psmouse, &priv->recalib_wq,
 				msecs_to_jiffies(jumpy_delay));
 	}
@@ -260,8 +260,8 @@ static void hgpk_spewing_hack(struct psm
 		 * movement, it is probably a case of the user moving the
 		 * cursor very slowly across the screen. */
 		if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
-			hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
-				 priv->x_tally, priv->y_tally);
+			psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
+				     priv->x_tally, priv->y_tally);
 			priv->spew_flag = RECALIBRATING;
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					   msecs_to_jiffies(spew_delay));
@@ -333,12 +333,12 @@ static bool hgpk_is_byte_valid(struct ps
 	}
 
 	if (!valid)
-		hgpk_dbg(psmouse,
-			 "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
-			 priv->mode, pktcnt,
-			 psmouse->packet[0], psmouse->packet[1],
-			 psmouse->packet[2], psmouse->packet[3],
-			 psmouse->packet[4], psmouse->packet[5]);
+		psmouse_dbg(psmouse,
+			    "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
+			    priv->mode, pktcnt,
+			    psmouse->packet[0], psmouse->packet[1],
+			    psmouse->packet[2], psmouse->packet[3],
+			    psmouse->packet[4], psmouse->packet[5]);
 
 	return valid;
 }
@@ -361,19 +361,20 @@ static void hgpk_process_advanced_packet
 
 		input_report_abs(idev, ABS_PRESSURE, z);
 		if (tpdebug)
-			hgpk_dbg(psmouse, "pd=%d fd=%d z=%d",
-				 pt_down, finger_down, z);
+			psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
+				    pt_down, finger_down, z);
 	} else {
 		/*
 		 * PenTablet mode does not report pressure, so we don't
 		 * report it here
 		 */
 		if (tpdebug)
-			hgpk_dbg(psmouse, "pd=%d ", down);
+			psmouse_dbg(psmouse, "pd=%d ", down);
 	}
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+		psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+			    left, right, x, y);
 
 	input_report_key(idev, BTN_TOUCH, down);
 	input_report_key(idev, BTN_LEFT, left);
@@ -395,7 +396,7 @@ static void hgpk_process_advanced_packet
 	if (x == priv->abs_x && y == priv->abs_y) {
 		if (++priv->dupe_count > SPEW_WATCH_COUNT) {
 			if (tpdebug)
-				hgpk_dbg(psmouse, "hard spew detected\n");
+				psmouse_dbg(psmouse, "hard spew detected\n");
 			priv->spew_flag = RECALIBRATING;
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					   msecs_to_jiffies(spew_delay));
@@ -412,7 +413,7 @@ static void hgpk_process_advanced_packet
 		int y_diff = priv->abs_y - y;
 		if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
 			if (tpdebug)
-				hgpk_dbg(psmouse, "discarding\n");
+				psmouse_dbg(psmouse, "discarding\n");
 			goto done;
 		}
 		hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
@@ -437,20 +438,21 @@ static void hgpk_process_simple_packet(s
 	int y = ((packet[0] << 3) & 0x100) - packet[2];
 
 	if (packet[0] & 0xc0)
-		hgpk_dbg(psmouse,
-			 "overflow -- 0x%02x 0x%02x 0x%02x\n",
-			 packet[0], packet[1], packet[2]);
+		psmouse_dbg(psmouse,
+			    "overflow -- 0x%02x 0x%02x 0x%02x\n",
+			    packet[0], packet[1], packet[2]);
 
 	if (hgpk_discard_decay_hack(psmouse, x, y)) {
 		if (tpdebug)
-			hgpk_dbg(psmouse, "discarding\n");
+			psmouse_dbg(psmouse, "discarding\n");
 		return;
 	}
 
 	hgpk_spewing_hack(psmouse, left, right, x, y);
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+		psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+			    left, right, x, y);
 
 	input_report_key(dev, BTN_LEFT, left);
 	input_report_key(dev, BTN_RIGHT, right);
@@ -482,9 +484,8 @@ static psmouse_ret_t hgpk_process_byte(s
 			 * ugh, got a packet inside our recalibration
 			 * window, schedule another recalibration.
 			 */
-			hgpk_dbg(psmouse,
-				 "packet inside calibration window, "
-				 "queueing another recalibration\n");
+			psmouse_dbg(psmouse,
+				    "packet inside calibration window, queueing another recalibration\n");
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					msecs_to_jiffies(post_interrupt_delay));
 		}
@@ -628,7 +629,7 @@ static int hgpk_reset_device(struct psmo
 
 	err = hgpk_select_mode(psmouse);
 	if (err) {
-		hgpk_err(psmouse, "failed to select mode\n");
+		psmouse_err(psmouse, "failed to select mode\n");
 		return err;
 	}
 
@@ -648,11 +649,11 @@ static int hgpk_force_recalibrate(struct
 		return 0;
 
 	if (!autorecal) {
-		hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
+		psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
 		return 0;
 	}
 
-	hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+	psmouse_dbg(psmouse, "recalibrating touchpad..\n");
 
 	/* we don't want to race with the irq handler, nor with resyncs */
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -675,7 +676,7 @@ static int hgpk_force_recalibrate(struct
 	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "touchpad reactivated\n");
+		psmouse_dbg(psmouse, "touchpad reactivated\n");
 
 	/*
 	 * If we get packets right away after recalibrating, it's likely
@@ -727,16 +728,16 @@ static int hgpk_toggle_powersave(struct
 
 		err = hgpk_reset_device(psmouse, false);
 		if (err) {
-			hgpk_err(psmouse, "Failed to reset device!\n");
+			psmouse_err(psmouse, "Failed to reset device!\n");
 			return err;
 		}
 
 		/* should be all set, enable the touchpad */
 		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
 		psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
-		hgpk_dbg(psmouse, "Touchpad powered up.\n");
+		psmouse_dbg(psmouse, "Touchpad powered up.\n");
 	} else {
-		hgpk_dbg(psmouse, "Powering off touchpad.\n");
+		psmouse_dbg(psmouse, "Powering off touchpad.\n");
 
 		if (ps2_command(ps2dev, NULL, 0xec) ||
 		    ps2_command(ps2dev, NULL, 0xec) ||
@@ -923,7 +924,7 @@ static void hgpk_recalib_work(struct wor
 	struct psmouse *psmouse = priv->psmouse;
 
 	if (hgpk_force_recalibrate(psmouse))
-		hgpk_err(psmouse, "recalibration failed!\n");
+		psmouse_err(psmouse, "recalibration failed!\n");
 }
 
 static int hgpk_register(struct psmouse *psmouse)
@@ -947,14 +948,15 @@ static int hgpk_register(struct psmouse
 	err = device_create_file(&psmouse->ps2dev.serio->dev,
 				 &psmouse_attr_powered.dattr);
 	if (err) {
-		hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
+		psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
 		return err;
 	}
 
 	err = device_create_file(&psmouse->ps2dev.serio->dev,
 				 &psmouse_attr_hgpk_mode.dattr);
 	if (err) {
-		hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n");
+		psmouse_err(psmouse,
+			    "Failed creating 'hgpk_mode' sysfs node\n");
 		goto err_remove_powered;
 	}
 
@@ -963,8 +965,8 @@ static int hgpk_register(struct psmouse
 		err = device_create_file(&psmouse->ps2dev.serio->dev,
 					 &psmouse_attr_recalibrate.dattr);
 		if (err) {
-			hgpk_err(psmouse,
-				"Failed creating 'recalibrate' sysfs node\n");
+			psmouse_err(psmouse,
+				    "Failed creating 'recalibrate' sysfs node\n");
 			goto err_remove_mode;
 		}
 	}
@@ -1027,13 +1029,13 @@ static enum hgpk_model_t hgpk_get_model(
 		return -EIO;
 	}
 
-	hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
 
 	/* HGPK signature: 0x67, 0x00, 0x<model> */
 	if (param[0] != 0x67 || param[1] != 0x00)
 		return -ENODEV;
 
-	hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+	psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
 
 	return param[2];
 }
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/hgpk.h linux-libre-3.2-gnu1/drivers/input/mouse/hgpk.h
--- linux-libre-3.1-gnu1/drivers/input/mouse/hgpk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/hgpk.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,17 +46,6 @@ struct hgpk_data {
 	int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
 };
 
-#define hgpk_dbg(psmouse, format, arg...)		\
-	dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_err(psmouse, format, arg...)		\
-	dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_info(psmouse, format, arg...)		\
-	dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_warn(psmouse, format, arg...)		\
-	dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_notice(psmouse, format, arg...)		\
-	dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-
 #ifdef CONFIG_MOUSE_PS2_OLPC
 void hgpk_module_init(void);
 int hgpk_detect(struct psmouse *psmouse, bool set_properties);
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/lifebook.c linux-libre-3.2-gnu1/drivers/input/mouse/lifebook.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/lifebook.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/lifebook.c	2012-01-04 18:55:44.000000000 -0500
@@ -169,8 +169,8 @@ static psmouse_ret_t lifebook_process_by
 
 	if (relative_packet) {
 		if (!dev2)
-			printk(KERN_WARNING "lifebook.c: got relative packet "
-				"but no relative device set up\n");
+			psmouse_warn(psmouse,
+				     "got relative packet but no relative device set up\n");
 	} else {
 		if (lifebook_use_6byte_proto) {
 			input_report_abs(dev1, ABS_X,
@@ -212,7 +212,7 @@ static int lifebook_absolute_mode(struct
 
 	/*
 	 * Enable absolute output -- ps2_command fails always but if
-	 * you leave this call out the touchsreen will never send
+	 * you leave this call out the touchscreen will never send
 	 * absolute coordinates
 	 */
 	param = lifebook_use_6byte_proto ? 0x08 : 0x07;
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/logips2pp.c linux-libre-3.2-gnu1/drivers/input/mouse/logips2pp.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/logips2pp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/logips2pp.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,11 +82,11 @@ static psmouse_ret_t ps2pp_process_byte(
 			packet[0] = packet[2] | 0x08;
 			break;
 
-#ifdef DEBUG
 		default:
-			printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
-				(packet[1] >> 4) | (packet[0] & 0x30));
-#endif
+			psmouse_dbg(psmouse,
+				    "Received PS2++ packet #%x, but don't know how to handle.\n",
+				    (packet[1] >> 4) | (packet[0] & 0x30));
+			break;
 		}
 	} else {
 		/* Standard PS/2 motion data */
@@ -382,7 +382,7 @@ int ps2pp_init(struct psmouse *psmouse,
 		}
 
 	} else {
-		printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
+		psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
 	}
 
 	if (set_properties) {
@@ -400,9 +400,9 @@ int ps2pp_init(struct psmouse *psmouse,
 				error = device_create_file(&psmouse->ps2dev.serio->dev,
 							   &psmouse_attr_smartscroll.dattr);
 				if (error) {
-					printk(KERN_ERR
-						"logips2pp.c: failed to create smartscroll "
-						"sysfs attribute, error: %d\n", error);
+					psmouse_err(psmouse,
+						    "failed to create smartscroll sysfs attribute, error: %d\n",
+						    error);
 					return -1;
 				}
 			}
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/psmouse-base.c linux-libre-3.2-gnu1/drivers/input/mouse/psmouse-base.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/psmouse-base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/psmouse-base.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,9 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
+#define psmouse_fmt(fmt)	fmt
+
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -251,11 +254,14 @@ static int psmouse_handle_byte(struct ps
 	switch (rc) {
 	case PSMOUSE_BAD_DATA:
 		if (psmouse->state == PSMOUSE_ACTIVATED) {
-			printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
-				psmouse->name, psmouse->phys, psmouse->pktcnt);
+			psmouse_warn(psmouse,
+				     "%s at %s lost sync at byte %d\n",
+				     psmouse->name, psmouse->phys,
+				     psmouse->pktcnt);
 			if (++psmouse->out_of_sync_cnt == psmouse->resetafter) {
 				__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-				printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+				psmouse_notice(psmouse,
+						"issuing reconnect request\n");
 				serio_reconnect(psmouse->ps2dev.serio);
 				return -1;
 			}
@@ -267,8 +273,9 @@ static int psmouse_handle_byte(struct ps
 		psmouse->pktcnt = 0;
 		if (psmouse->out_of_sync_cnt) {
 			psmouse->out_of_sync_cnt = 0;
-			printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
-				psmouse->name, psmouse->phys);
+			psmouse_notice(psmouse,
+					"%s at %s - driver resynced.\n",
+					psmouse->name, psmouse->phys);
 		}
 		break;
 
@@ -295,9 +302,10 @@ static irqreturn_t psmouse_interrupt(str
 		     ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
 
 		if (psmouse->state == PSMOUSE_ACTIVATED)
-			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
-				flags & SERIO_TIMEOUT ? " timeout" : "",
-				flags & SERIO_PARITY ? " bad parity" : "");
+			psmouse_warn(psmouse,
+				     "bad data from KBC -%s%s\n",
+				     flags & SERIO_TIMEOUT ? " timeout" : "",
+				     flags & SERIO_PARITY ? " bad parity" : "");
 		ps2_cmd_aborted(&psmouse->ps2dev);
 		goto out;
 	}
@@ -315,8 +323,8 @@ static irqreturn_t psmouse_interrupt(str
 
 	if (psmouse->state == PSMOUSE_ACTIVATED &&
 	    psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
-		printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
-		       psmouse->name, psmouse->phys, psmouse->pktcnt);
+		psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n",
+			     psmouse->name, psmouse->phys, psmouse->pktcnt);
 		psmouse->badbyte = psmouse->packet[0];
 		__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
 		psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
@@ -943,7 +951,8 @@ static int psmouse_probe(struct psmouse
  */
 
 	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
-		printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys);
+		psmouse_warn(psmouse, "Failed to reset mouse on %s\n",
+			     ps2dev->serio->phys);
 
 	return 0;
 }
@@ -1005,8 +1014,8 @@ static void psmouse_initialize(struct ps
 static void psmouse_activate(struct psmouse *psmouse)
 {
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to enable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 }
@@ -1020,14 +1029,14 @@ static void psmouse_activate(struct psmo
 static void psmouse_deactivate(struct psmouse *psmouse)
 {
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 }
 
 /*
- * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
  */
 
 static int psmouse_poll(struct psmouse *psmouse)
@@ -1115,14 +1124,15 @@ static void psmouse_resync(struct work_s
 	}
 
 	if (!enabled) {
-		printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "failed to re-enable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 		failed = true;
 	}
 
 	if (failed) {
 		psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-		printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+		psmouse_info(psmouse,
+			     "resync failed, issuing reconnect request\n");
 		serio_reconnect(serio);
 	} else
 		psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
@@ -1155,8 +1165,8 @@ static void psmouse_cleanup(struct serio
 	 * Disable stream mode so cleanup routine can proceed undisturbed.
 	 */
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to disable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	if (psmouse->cleanup)
 		psmouse->cleanup(psmouse);
@@ -1400,7 +1410,8 @@ static int psmouse_reconnect(struct seri
 	int rc = -1;
 
 	if (!drv || !psmouse) {
-		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
+		psmouse_dbg(psmouse,
+			    "reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
@@ -1427,8 +1438,9 @@ static int psmouse_reconnect(struct seri
 			goto out;
 	}
 
-	/* ok, the device type (and capabilities) match the old one,
-	 * we can continue using it, complete intialization
+	/*
+	 * OK, the device type (and capabilities) match the old one,
+	 * we can continue using it, complete initialization
 	 */
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
@@ -1586,9 +1598,8 @@ static ssize_t psmouse_attr_set_protocol
 
 	while (!list_empty(&serio->children)) {
 		if (++retry > 3) {
-			printk(KERN_WARNING
-				"psmouse: failed to destroy children ports, "
-				"protocol change aborted.\n");
+			psmouse_warn(psmouse,
+				     "failed to destroy children ports, protocol change aborted.\n");
 			input_free_device(new_dev);
 			return -EIO;
 		}
@@ -1715,7 +1726,7 @@ static int __init psmouse_init(void)
 
 	kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
 	if (!kpsmoused_wq) {
-		printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+		pr_err("failed to create kpsmoused workqueue\n");
 		return -ENOMEM;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/psmouse.h linux-libre-3.2-gnu1/drivers/input/mouse/psmouse.h
--- linux-libre-3.1-gnu1/drivers/input/mouse/psmouse.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/psmouse.h	2012-01-04 18:55:44.000000000 -0500
@@ -150,4 +150,29 @@ static struct psmouse_attribute psmouse_
 	static ssize_t _set(struct psmouse *, void *, const char *, size_t);	\
 	__PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true)
 
+#ifndef psmouse_fmt
+#define psmouse_fmt(fmt)	KBUILD_BASENAME ": " fmt
+#endif
+
+#define psmouse_dbg(psmouse, format, ...)		\
+	dev_dbg(&(psmouse)->ps2dev.serio->dev,		\
+		psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_info(psmouse, format, ...)		\
+	dev_info(&(psmouse)->ps2dev.serio->dev,		\
+		 psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_warn(psmouse, format, ...)		\
+	dev_warn(&(psmouse)->ps2dev.serio->dev,		\
+		 psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_err(psmouse, format, ...)		\
+	dev_err(&(psmouse)->ps2dev.serio->dev,		\
+		psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_notice(psmouse, format, ...)		\
+	dev_notice(&(psmouse)->ps2dev.serio->dev,	\
+		   psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_printk(level, psmouse, format, ...)	\
+	dev_printk(level,				\
+		   &(psmouse)->ps2dev.serio->dev,	\
+		   psmouse_fmt(format), ##__VA_ARGS__)
+
+
 #endif /* _PSMOUSE_H */
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/pxa930_trkball.c linux-libre-3.2-gnu1/drivers/input/mouse/pxa930_trkball.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/pxa930_trkball.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/pxa930_trkball.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,7 +183,7 @@ static int __devinit pxa930_trkball_prob
 	/* held the module in reset, will be enabled in open() */
 	pxa930_trkball_disable(trkball);
 
-	error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED,
+	error = request_irq(irq, pxa930_trkball_interrupt, 0,
 			    pdev->name, trkball);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request irq: %d\n", error);
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/sentelic.c linux-libre-3.2-gnu1/drivers/input/mouse/sentelic.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/sentelic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/sentelic.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  * Finger Sensing Pad PS/2 mouse driver.
  *
  * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -162,7 +162,7 @@ static int fsp_reg_write(struct psmouse
 	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
 
 	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
-		return -1;
+		goto out;
 
 	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 		/* inversion is required */
@@ -261,7 +261,7 @@ static int fsp_page_reg_write(struct psm
 	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
 
 	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
-		return -1;
+		goto out;
 
 	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
@@ -309,7 +309,7 @@ static int fsp_get_buttons(struct psmous
 	};
 	int val;
 
-	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1)
+	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
 		return -EIO;
 
 	*btn = buttons[(val & 0x30) >> 4];
@@ -607,11 +607,12 @@ static void fsp_packet_debug(unsigned ch
 
 	ps2_packet_cnt++;
 	jiffies_msec = jiffies_to_msecs(jiffies);
-	printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
-		jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
+	psmouse_dbg(psmouse,
+		    "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
+		    jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
 
 	if (jiffies_msec - ps2_last_second > 1000) {
-		printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt);
+		psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
 		ps2_packet_cnt = 0;
 		ps2_last_second = jiffies_msec;
 	}
@@ -820,9 +821,9 @@ int fsp_init(struct psmouse *psmouse)
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO
-		"Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
-		ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
+	psmouse_info(psmouse,
+		     "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
+		     ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
 
 	psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
 	if (!priv)
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/sentelic.h linux-libre-3.2-gnu1/drivers/input/mouse/sentelic.h
--- linux-libre-3.1-gnu1/drivers/input/mouse/sentelic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/sentelic.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  * Finger Sensing Pad PS/2 mouse driver.
  *
  * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -33,6 +33,7 @@
 /* Finger-sensing Pad control registers */
 #define	FSP_REG_SYSCTL1		0x10
 #define	FSP_BIT_EN_REG_CLK	BIT(5)
+#define	FSP_REG_TMOD_STATUS	0x20
 #define	FSP_REG_OPC_QDOWN	0x31
 #define	FSP_BIT_EN_OPC_TAG	BIT(7)
 #define	FSP_REG_OPTZ_XLO	0x34
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/synaptics.c linux-libre-3.2-gnu1/drivers/input/mouse/synaptics.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/synaptics.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/synaptics.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/dmi.h>
 #include <linux/input/mt.h>
 #include <linux/serio.h>
@@ -44,6 +45,16 @@
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
+/*
+ * Synaptics touchpads report the y coordinate from bottom to top, which is
+ * opposite from what userspace expects.
+ * This function is used to invert y before reporting.
+ */
+static int synaptics_invert_y(int y)
+{
+	return YMAX_NOMINAL + YMIN_NOMINAL - y;
+}
+
 
 /*****************************************************************************
  *	Stuff we need even when we do not want native Synaptics support
@@ -157,8 +168,8 @@ static int synaptics_capability(struct p
 
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
-			printk(KERN_ERR "Synaptics claims to have extended capabilities,"
-			       " but I'm not able to read them.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have extended capabilities, but I'm not able to read them.\n");
 		} else {
 			priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 
@@ -173,8 +184,8 @@ static int synaptics_capability(struct p
 
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
-			printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
-			       " but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
 		} else {
 			priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 		}
@@ -222,8 +233,8 @@ static int synaptics_resolution(struct p
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
 	    SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
-			printk(KERN_ERR "Synaptics claims to have max coordinates"
-			       " query, but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have max coordinates query, but I'm not able to read it.\n");
 		} else {
 			priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
 			priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -233,8 +244,8 @@ static int synaptics_resolution(struct p
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
 	    SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
-			printk(KERN_ERR "Synaptics claims to have min coordinates"
-			       " query, but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have min coordinates query, but I'm not able to read it.\n");
 		} else {
 			priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
 			priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -294,7 +305,8 @@ static int synaptics_set_advanced_gestur
 	static unsigned char param = 0xc8;
 	struct synaptics_data *priv = psmouse->private;
 
-	if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+	if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
 		return 0;
 
 	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
@@ -377,7 +389,8 @@ static void synaptics_pt_activate(struct
 			priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
 
 		if (synaptics_mode_cmd(psmouse, priv->mode))
-			printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
+			psmouse_warn(psmouse,
+				     "failed to switch guest protocol\n");
 	}
 }
 
@@ -387,7 +400,8 @@ static void synaptics_pt_create(struct p
 
 	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!serio) {
-		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
+		psmouse_err(psmouse,
+			    "not enough memory for pass-through port\n");
 		return;
 	}
 
@@ -401,7 +415,8 @@ static void synaptics_pt_create(struct p
 
 	psmouse->pt_activate = synaptics_pt_activate;
 
-	printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+	psmouse_info(psmouse, "serio: %s port at %s\n",
+		     serio->name, psmouse->phys);
 	serio_register_port(serio);
 }
 
@@ -409,6 +424,44 @@ static void synaptics_pt_create(struct p
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
+static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
+				   int sgm, int agm)
+{
+	state->count = count;
+	state->sgm = sgm;
+	state->agm = agm;
+}
+
+static void synaptics_parse_agm(const unsigned char buf[],
+				struct synaptics_data *priv,
+				struct synaptics_hw_state *hw)
+{
+	struct synaptics_hw_state *agm = &priv->agm;
+	int agm_packet_type;
+
+	agm_packet_type = (buf[5] & 0x30) >> 4;
+	switch (agm_packet_type) {
+	case 1:
+		/* Gesture packet: (x, y, z) half resolution */
+		agm->w = hw->w;
+		agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+		agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+		agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+		break;
+
+	case 2:
+		/* AGM-CONTACT packet: (count, sgm, agm) */
+		synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
+		break;
+
+	default:
+		break;
+	}
+
+	/* Record that at least one AGM has been received since last SGM */
+	priv->agm_pending = true;
+}
+
 static int synaptics_parse_hw_state(const unsigned char buf[],
 				    struct synaptics_data *priv,
 				    struct synaptics_hw_state *hw)
@@ -442,11 +495,10 @@ static int synaptics_parse_hw_state(cons
 			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
 
-		if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
-			/* Gesture packet: (x, y, z) at half resolution */
-			priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
-			priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
-			priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+		    hw->w == 2) {
+			synaptics_parse_agm(buf, priv, hw);
 			return 1;
 		}
 
@@ -502,8 +554,7 @@ static void synaptics_report_semi_mt_slo
 	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
 	if (active) {
 		input_report_abs(dev, ABS_MT_POSITION_X, x);
-		input_report_abs(dev, ABS_MT_POSITION_Y,
-				 YMAX_NOMINAL + YMIN_NOMINAL - y);
+		input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
 	}
 }
 
@@ -526,6 +577,388 @@ static void synaptics_report_semi_mt_dat
 	}
 }
 
+static void synaptics_report_buttons(struct psmouse *psmouse,
+				     const struct synaptics_hw_state *hw)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	int i;
+
+	input_report_key(dev, BTN_LEFT, hw->left);
+	input_report_key(dev, BTN_RIGHT, hw->right);
+
+	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+		input_report_key(dev, BTN_MIDDLE, hw->middle);
+
+	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+		input_report_key(dev, BTN_FORWARD, hw->up);
+		input_report_key(dev, BTN_BACK, hw->down);
+	}
+
+	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+		input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
+}
+
+static void synaptics_report_slot(struct input_dev *dev, int slot,
+				  const struct synaptics_hw_state *hw)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
+	if (!hw)
+		return;
+
+	input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
+	input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
+}
+
+static void synaptics_report_mt_data(struct psmouse *psmouse,
+				     struct synaptics_mt_state *mt_state,
+				     const struct synaptics_hw_state *sgm)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (mt_state->count) {
+	case 0:
+		synaptics_report_slot(dev, 0, NULL);
+		synaptics_report_slot(dev, 1, NULL);
+		break;
+	case 1:
+		if (mt_state->sgm == -1) {
+			synaptics_report_slot(dev, 0, NULL);
+			synaptics_report_slot(dev, 1, NULL);
+		} else if (mt_state->sgm == 0) {
+			synaptics_report_slot(dev, 0, sgm);
+			synaptics_report_slot(dev, 1, NULL);
+		} else {
+			synaptics_report_slot(dev, 0, NULL);
+			synaptics_report_slot(dev, 1, sgm);
+		}
+		break;
+	default:
+		/*
+		 * If the finger slot contained in SGM is valid, and either
+		 * hasn't changed, or is new, then report SGM in MTB slot 0.
+		 * Otherwise, empty MTB slot 0.
+		 */
+		if (mt_state->sgm != -1 &&
+		    (mt_state->sgm == old->sgm || old->sgm == -1))
+			synaptics_report_slot(dev, 0, sgm);
+		else
+			synaptics_report_slot(dev, 0, NULL);
+
+		/*
+		 * If the finger slot contained in AGM is valid, and either
+		 * hasn't changed, or is new, then report AGM in MTB slot 1.
+		 * Otherwise, empty MTB slot 1.
+		 */
+		if (mt_state->agm != -1 &&
+		    (mt_state->agm == old->agm || old->agm == -1))
+			synaptics_report_slot(dev, 1, agm);
+		else
+			synaptics_report_slot(dev, 1, NULL);
+		break;
+	}
+
+	/* Don't use active slot count to generate BTN_TOOL events. */
+	input_mt_report_pointer_emulation(dev, false);
+
+	/* Send the number of fingers reported by touchpad itself. */
+	input_mt_report_finger_count(dev, mt_state->count);
+
+	synaptics_report_buttons(psmouse, sgm);
+
+	input_sync(dev);
+}
+
+/* Handle case where mt_state->count = 0 */
+static void synaptics_image_sensor_0f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	synaptics_mt_state_set(mt_state, 0, -1, -1);
+	priv->mt_state_lost = false;
+}
+
+/* Handle case where mt_state->count = 1 */
+static void synaptics_image_sensor_1f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	/*
+	 * If the last AGM was (0,0,0), and there is only one finger left,
+	 * then we absolutely know that SGM contains slot 0, and all other
+	 * fingers have been removed.
+	 */
+	if (priv->agm_pending && agm->z == 0) {
+		synaptics_mt_state_set(mt_state, 1, 0, -1);
+		priv->mt_state_lost = false;
+		return;
+	}
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 1, 0, -1);
+		break;
+	case 1:
+		/*
+		 * If mt_state_lost, then the previous transition was 3->1,
+		 * and SGM now contains either slot 0 or 1, but we don't know
+		 * which.  So, we just assume that the SGM now contains slot 1.
+		 *
+		 * If pending AGM and either:
+		 *   (a) the previous SGM slot contains slot 0, or
+		 *   (b) there was no SGM slot
+		 * then, the SGM now contains slot 1
+		 *
+		 * Case (a) happens with very rapid "drum roll" gestures, where
+		 * slot 0 finger is lifted and a new slot 1 finger touches
+		 * within one reporting interval.
+		 *
+		 * Case (b) happens if initially two or more fingers tap
+		 * briefly, and all but one lift before the end of the first
+		 * reporting interval.
+		 *
+		 * (In both these cases, slot 0 will becomes empty, so SGM
+		 * contains slot 1 with the new finger)
+		 *
+		 * Else, if there was no previous SGM, it now contains slot 0.
+		 *
+		 * Otherwise, SGM still contains the same slot.
+		 */
+		if (priv->mt_state_lost ||
+		    (priv->agm_pending && old->sgm <= 0))
+			synaptics_mt_state_set(mt_state, 1, 1, -1);
+		else if (old->sgm == -1)
+			synaptics_mt_state_set(mt_state, 1, 0, -1);
+		break;
+	case 2:
+		/*
+		 * If mt_state_lost, we don't know which finger SGM contains.
+		 *
+		 * So, report 1 finger, but with both slots empty.
+		 * We will use slot 1 on subsequent 1->1
+		 */
+		if (priv->mt_state_lost) {
+			synaptics_mt_state_set(mt_state, 1, -1, -1);
+			break;
+		}
+		/*
+		 * Since the last AGM was NOT (0,0,0), it was the finger in
+		 * slot 0 that has been removed.
+		 * So, SGM now contains previous AGM's slot, and AGM is now
+		 * empty.
+		 */
+		synaptics_mt_state_set(mt_state, 1, old->agm, -1);
+		break;
+	case 3:
+		/*
+		 * Since last AGM was not (0,0,0), we don't know which finger
+		 * is left.
+		 *
+		 * So, report 1 finger, but with both slots empty.
+		 * We will use slot 1 on subsequent 1->1
+		 */
+		synaptics_mt_state_set(mt_state, 1, -1, -1);
+		priv->mt_state_lost = true;
+		break;
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 2 */
+static void synaptics_image_sensor_2f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 2, 0, 1);
+		break;
+	case 1:
+		/*
+		 * If previous SGM contained slot 1 or higher, SGM now contains
+		 * slot 0 (the newly touching finger) and AGM contains SGM's
+		 * previous slot.
+		 *
+		 * Otherwise, SGM still contains slot 0 and AGM now contains
+		 * slot 1.
+		 */
+		if (old->sgm >= 1)
+			synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
+		else
+			synaptics_mt_state_set(mt_state, 2, 0, 1);
+		break;
+	case 2:
+		/*
+		 * If mt_state_lost, SGM now contains either finger 1 or 2, but
+		 * we don't know which.
+		 * So, we just assume that the SGM contains slot 0 and AGM 1.
+		 */
+		if (priv->mt_state_lost)
+			synaptics_mt_state_set(mt_state, 2, 0, 1);
+		/*
+		 * Otherwise, use the same mt_state, since it either hasn't
+		 * changed, or was updated by a recently received AGM-CONTACT
+		 * packet.
+		 */
+		break;
+	case 3:
+		/*
+		 * 3->2 transitions have two unsolvable problems:
+		 *  1) no indication is given which finger was removed
+		 *  2) no way to tell if agm packet was for finger 3
+		 *     before 3->2, or finger 2 after 3->2.
+		 *
+		 * So, report 2 fingers, but empty all slots.
+		 * We will guess slots [0,1] on subsequent 2->2.
+		 */
+		synaptics_mt_state_set(mt_state, 2, -1, -1);
+		priv->mt_state_lost = true;
+		break;
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 3 */
+static void synaptics_image_sensor_3f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 3, 0, 2);
+		break;
+	case 1:
+		/*
+		 * If previous SGM contained slot 2 or higher, SGM now contains
+		 * slot 0 (one of the newly touching fingers) and AGM contains
+		 * SGM's previous slot.
+		 *
+		 * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
+		 */
+		if (old->sgm >= 2)
+			synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
+		else
+			synaptics_mt_state_set(mt_state, 3, 0, 2);
+		break;
+	case 2:
+		/*
+		 * If the AGM previously contained slot 3 or higher, then the
+		 * newly touching finger is in the lowest available slot.
+		 *
+		 * If SGM was previously 1 or higher, then the new SGM is
+		 * now slot 0 (with a new finger), otherwise, the new finger
+		 * is now in a hidden slot between 0 and AGM's slot.
+		 *
+		 * In all such cases, the SGM now contains slot 0, and the AGM
+		 * continues to contain the same slot as before.
+		 */
+		if (old->agm >= 3) {
+			synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+			break;
+		}
+
+		/*
+		 * After some 3->1 and all 3->2 transitions, we lose track
+		 * of which slot is reported by SGM and AGM.
+		 *
+		 * For 2->3 in this state, report 3 fingers, but empty all
+		 * slots, and we will guess (0,2) on a subsequent 0->3.
+		 *
+		 * To userspace, the resulting transition will look like:
+		 *    2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
+		 */
+		if (priv->mt_state_lost) {
+			synaptics_mt_state_set(mt_state, 3, -1, -1);
+			break;
+		}
+
+		/*
+		 * If the (SGM,AGM) really previously contained slots (0, 1),
+		 * then we cannot know what slot was just reported by the AGM,
+		 * because the 2->3 transition can occur either before or after
+		 * the AGM packet. Thus, this most recent AGM could contain
+		 * either the same old slot 1 or the new slot 2.
+		 * Subsequent AGMs will be reporting slot 2.
+		 *
+		 * To userspace, the resulting transition will look like:
+		 *    2:[0,1] -> 3:[0,-1] -> 3:[0,2]
+		 */
+		synaptics_mt_state_set(mt_state, 3, 0, -1);
+		break;
+	case 3:
+		/*
+		 * If, for whatever reason, the previous agm was invalid,
+		 * Assume SGM now contains slot 0, AGM now contains slot 2.
+		 */
+		if (old->agm <= 2)
+			synaptics_mt_state_set(mt_state, 3, 0, 2);
+		/*
+		 * mt_state either hasn't changed, or was updated by a recently
+		 * received AGM-CONTACT packet.
+		 */
+		break;
+
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+				       struct synaptics_mt_state *mt_state)
+{
+	/* mt_state was updated correctly by AGM-CONTACT packet */
+	priv->mt_state_lost = false;
+}
+
+static void synaptics_image_sensor_process(struct psmouse *psmouse,
+					   struct synaptics_hw_state *sgm)
+{
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state mt_state;
+
+	/* Initialize using current mt_state (as updated by last agm) */
+	mt_state = agm->mt_state;
+
+	/*
+	 * Update mt_state using the new finger count and current mt_state.
+	 */
+	if (sgm->z == 0)
+		synaptics_image_sensor_0f(priv, &mt_state);
+	else if (sgm->w >= 4)
+		synaptics_image_sensor_1f(priv, &mt_state);
+	else if (sgm->w == 0)
+		synaptics_image_sensor_2f(priv, &mt_state);
+	else if (sgm->w == 1 && mt_state.count <= 3)
+		synaptics_image_sensor_3f(priv, &mt_state);
+	else
+		synaptics_image_sensor_45f(priv, &mt_state);
+
+	/* Send resulting input events to user space */
+	synaptics_report_mt_data(psmouse, &mt_state, sgm);
+
+	/* Store updated mt_state */
+	priv->mt_state = agm->mt_state = mt_state;
+	priv->agm_pending = false;
+}
+
 /*
  *  called for each full received packet from the touchpad
  */
@@ -536,11 +969,15 @@ static void synaptics_process_packet(str
 	struct synaptics_hw_state hw;
 	int num_fingers;
 	int finger_width;
-	int i;
 
 	if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
 		return;
 
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+		synaptics_image_sensor_process(psmouse, &hw);
+		return;
+	}
+
 	if (hw.scroll) {
 		priv->scroll += hw.scroll;
 
@@ -586,7 +1023,8 @@ static void synaptics_process_packet(str
 	}
 
 	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
-		synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
+		synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
+					      num_fingers);
 
 	/* Post events
 	 * BTN_TOUCH has to be first as mousedev relies on it when doing
@@ -597,7 +1035,7 @@ static void synaptics_process_packet(str
 
 	if (num_fingers > 0) {
 		input_report_abs(dev, ABS_X, hw.x);
-		input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
+		input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
 	}
 	input_report_abs(dev, ABS_PRESSURE, hw.z);
 
@@ -605,35 +1043,25 @@ static void synaptics_process_packet(str
 		input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
 
 	input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
-	input_report_key(dev, BTN_LEFT, hw.left);
-	input_report_key(dev, BTN_RIGHT, hw.right);
-
 	if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 		input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
 		input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
 	}
 
-	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
-		input_report_key(dev, BTN_MIDDLE, hw.middle);
-
-	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
-		input_report_key(dev, BTN_FORWARD, hw.up);
-		input_report_key(dev, BTN_BACK, hw.down);
-	}
-
-	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-		input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
+	synaptics_report_buttons(psmouse, &hw);
 
 	input_sync(dev);
 }
 
-static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
+static int synaptics_validate_byte(struct psmouse *psmouse,
+				   int idx, unsigned char pkt_type)
 {
 	static const unsigned char newabs_mask[]	= { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
 	static const unsigned char newabs_rel_mask[]	= { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
 	static const unsigned char newabs_rslt[]	= { 0x80, 0x00, 0x00, 0xC0, 0x00 };
 	static const unsigned char oldabs_mask[]	= { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
 	static const unsigned char oldabs_rslt[]	= { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+	const char *packet = psmouse->packet;
 
 	if (idx < 0 || idx > 4)
 		return 0;
@@ -651,7 +1079,7 @@ static int synaptics_validate_byte(unsig
 		return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
 
 	default:
-		printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
+		psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
 		return 0;
 	}
 }
@@ -661,8 +1089,8 @@ static unsigned char synaptics_detect_pk
 	int i;
 
 	for (i = 0; i < 5; i++)
-		if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
-			printk(KERN_INFO "synaptics: using relaxed packet validation\n");
+		if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
+			psmouse_info(psmouse, "using relaxed packet validation\n");
 			return SYN_NEWABS_RELAXED;
 		}
 
@@ -687,46 +1115,56 @@ static psmouse_ret_t synaptics_process_b
 		return PSMOUSE_FULL_PACKET;
 	}
 
-	return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
+	return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
 		PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
 }
 
 /*****************************************************************************
  *	Driver initialization/cleanup functions
  ****************************************************************************/
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_abs_position_params(struct input_dev *dev,
+				    struct synaptics_data *priv, int x_code,
+				    int y_code)
 {
-	int i;
+	int x_min = priv->x_min ?: XMIN_NOMINAL;
+	int x_max = priv->x_max ?: XMAX_NOMINAL;
+	int y_min = priv->y_min ?: YMIN_NOMINAL;
+	int y_max = priv->y_max ?: YMAX_NOMINAL;
 	int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
 			SYN_REDUCED_FILTER_FUZZ : 0;
 
+	input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
+	input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
+	input_abs_set_res(dev, x_code, priv->x_res);
+	input_abs_set_res(dev, y_code, priv->y_res);
+}
+
+static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+{
+	int i;
+
 	__set_bit(INPUT_PROP_POINTER, dev->propbit);
 
 	__set_bit(EV_ABS, dev->evbit);
-	input_set_abs_params(dev, ABS_X,
-			     priv->x_min ?: XMIN_NOMINAL,
-			     priv->x_max ?: XMAX_NOMINAL,
-			     fuzz, 0);
-	input_set_abs_params(dev, ABS_Y,
-			     priv->y_min ?: YMIN_NOMINAL,
-			     priv->y_max ?: YMAX_NOMINAL,
-			     fuzz, 0);
+	set_abs_position_params(dev, priv, ABS_X, ABS_Y);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
-	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X,
-				     priv->x_min ?: XMIN_NOMINAL,
-				     priv->x_max ?: XMAX_NOMINAL,
-				     fuzz, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y,
-				     priv->y_min ?: YMIN_NOMINAL,
-				     priv->y_max ?: YMAX_NOMINAL,
-				     fuzz, 0);
+		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+					ABS_MT_POSITION_Y);
+		/* Image sensors can report per-contact pressure */
+		input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
 
-		input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
-		input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
+		/* Image sensors can signal 4 and 5 finger clicks */
+		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+		/* Non-image sensors with AGM use semi-mt */
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+		input_mt_init_slots(dev, 2);
+		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+					ABS_MT_POSITION_Y);
 	}
 
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -759,9 +1197,6 @@ static void set_input_params(struct inpu
 	__clear_bit(REL_X, dev->relbit);
 	__clear_bit(REL_Y, dev->relbit);
 
-	input_abs_set_res(dev, ABS_X, priv->x_res);
-	input_abs_set_res(dev, ABS_Y, priv->y_res);
-
 	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
 		__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
 		/* Clickpads report only left button */
@@ -786,6 +1221,16 @@ static int synaptics_reconnect(struct ps
 
 	do {
 		psmouse_reset(psmouse);
+		if (retry) {
+			/*
+			 * On some boxes, right after resuming, the touchpad
+			 * needs some time to finish initializing (I assume
+			 * it needs time to calibrate) and start responding
+			 * to Synaptics-specific queries, so let's wait a
+			 * bit.
+			 */
+			ssleep(1);
+		}
 		error = synaptics_detect(psmouse, 0);
 	} while (error && ++retry < 3);
 
@@ -793,21 +1238,21 @@ static int synaptics_reconnect(struct ps
 		return -1;
 
 	if (retry > 1)
-		printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
-			retry);
+		psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
 
 	if (synaptics_query_hardware(psmouse)) {
-		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to query device.\n");
 		return -1;
 	}
 
 	if (synaptics_set_absolute_mode(psmouse)) {
-		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to initialize device.\n");
 		return -1;
 	}
 
 	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+		psmouse_err(psmouse,
+			    "Advanced gesture mode reconnect failed.\n");
 		return -1;
 	}
 
@@ -815,12 +1260,12 @@ static int synaptics_reconnect(struct ps
 	    old_priv.model_id != priv->model_id ||
 	    old_priv.capabilities != priv->capabilities ||
 	    old_priv.ext_cap != priv->ext_cap) {
-		printk(KERN_ERR "Synaptics hardware appears to be different: "
-			"id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
-			old_priv.identity, priv->identity,
-			old_priv.model_id, priv->model_id,
-			old_priv.capabilities, priv->capabilities,
-			old_priv.ext_cap, priv->ext_cap);
+		psmouse_err(psmouse,
+			    "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
+			    old_priv.identity, priv->identity,
+			    old_priv.model_id, priv->model_id,
+			    old_priv.capabilities, priv->capabilities,
+			    old_priv.ext_cap, priv->ext_cap);
 		return -1;
 	}
 
@@ -901,7 +1346,8 @@ int synaptics_init(struct psmouse *psmou
 	 * just fine.
 	 */
 	if (broken_olpc_ec) {
-		printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n");
+		psmouse_info(psmouse,
+			     "OLPC XO detected, not enabling Synaptics protocol.\n");
 		return -ENODEV;
 	}
 
@@ -912,26 +1358,28 @@ int synaptics_init(struct psmouse *psmou
 	psmouse_reset(psmouse);
 
 	if (synaptics_query_hardware(psmouse)) {
-		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to query device.\n");
 		goto init_fail;
 	}
 
 	if (synaptics_set_absolute_mode(psmouse)) {
-		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to initialize device.\n");
 		goto init_fail;
 	}
 
 	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		printk(KERN_ERR "Advanced gesture mode init failed.\n");
+		psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
 		goto init_fail;
 	}
 
 	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
-	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
-		SYN_ID_MODEL(priv->identity),
-		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
-		priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
+	psmouse_info(psmouse,
+		     "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
+		     SYN_ID_MODEL(priv->identity),
+		     SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
+		     priv->model_id,
+		     priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
 
 	set_input_params(psmouse->dev, priv);
 
@@ -963,8 +1411,9 @@ int synaptics_init(struct psmouse *psmou
 	 * the same rate as a standard PS/2 mouse).
 	 */
 	if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
-		printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
-			dmi_get_system_info(DMI_PRODUCT_NAME));
+		psmouse_info(psmouse,
+			     "Toshiba %s detected, limiting rate to 40pps.\n",
+			     dmi_get_system_info(DMI_PRODUCT_NAME));
 		psmouse->rate = 40;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/synaptics.h linux-libre-3.2-gnu1/drivers/input/mouse/synaptics.h
--- linux-libre-3.1-gnu1/drivers/input/mouse/synaptics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/synaptics.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,6 +74,8 @@
  * 2	0x04	reduced filtering	firmware does less filtering on
  *					position data, driver should watch
  *					for noise.
+ * 2	0x08	image sensor		image sensor tracks 5 fingers, but only
+ *					reports 2.
  * 2	0x20	report min		query 0x0f gives min coord reported
  */
 #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
@@ -82,6 +84,7 @@
 #define SYN_CAP_MIN_DIMENSIONS(ex0c)	((ex0c) & 0x002000)
 #define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
 #define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
+#define SYN_CAP_IMAGE_SENSOR(ex0c)	((ex0c) & 0x000800)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -112,9 +115,18 @@
 #define SYN_REDUCED_FILTER_FUZZ		8
 
 /*
- * A structure to describe the state of the touchpad hardware (buttons and pad)
+ * A structure to describe which internal touchpad finger slots are being
+ * reported in raw packets.
  */
+struct synaptics_mt_state {
+	int count;			/* num fingers being tracked */
+	int sgm;			/* which slot is reported by sgm pkt */
+	int agm;			/* which slot is reported by agm pkt*/
+};
 
+/*
+ * A structure to describe the state of the touchpad hardware (buttons and pad)
+ */
 struct synaptics_hw_state {
 	int x;
 	int y;
@@ -127,6 +139,9 @@ struct synaptics_hw_state {
 	unsigned int down:1;
 	unsigned char ext_buttons;
 	signed char scroll;
+
+	/* As reported in last AGM-CONTACT packets */
+	struct synaptics_mt_state mt_state;
 };
 
 struct synaptics_data {
@@ -146,7 +161,15 @@ struct synaptics_data {
 
 	struct serio *pt_port;			/* Pass-through serio port */
 
-	struct synaptics_hw_state mt;		/* current gesture packet */
+	struct synaptics_mt_state mt_state;	/* Current mt finger state */
+	bool mt_state_lost;			/* mt_state may be incorrect */
+
+	/*
+	 * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
+	 * contains position data for a second contact, at half resolution.
+	 */
+	struct synaptics_hw_state agm;
+	bool agm_pending;			/* new AGM packet received */
 };
 
 void synaptics_module_init(void);
diff -druNp linux-libre-3.1-gnu1/drivers/input/mouse/synaptics_i2c.c linux-libre-3.2-gnu1/drivers/input/mouse/synaptics_i2c.c
--- linux-libre-3.1-gnu1/drivers/input/mouse/synaptics_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/mouse/synaptics_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -570,7 +570,7 @@ static int __devinit synaptics_i2c_probe
 			 "Requesting IRQ: %d\n", touch->client->irq);
 
 		ret = request_irq(touch->client->irq, synaptics_i2c_irq,
-				  IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING,
+				  IRQ_TYPE_EDGE_FALLING,
 				  DRIVER_NAME, touch);
 		if (ret) {
 			dev_warn(&touch->client->dev,
@@ -619,7 +619,7 @@ static int __devexit synaptics_i2c_remov
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int synaptics_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
diff -druNp linux-libre-3.1-gnu1/drivers/input/serio/ams_delta_serio.c linux-libre-3.2-gnu1/drivers/input/serio/ams_delta_serio.c
--- linux-libre-3.1-gnu1/drivers/input/serio/ams_delta_serio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/serio/ams_delta_serio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/serio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/mach-types.h>
 #include <plat/board-ams-delta.h>
diff -druNp linux-libre-3.1-gnu1/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.2-gnu1/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.1-gnu1/drivers/input/serio/i8042-x86ia64io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/serio/i8042-x86ia64io.h	2012-01-04 18:55:44.000000000 -0500
@@ -431,6 +431,13 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
 		},
 	},
+	{
+		/* Newer HP Pavilion dv4 models */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+		},
+	},
 	{ }
 };
 
@@ -560,6 +567,13 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
 		},
 	},
+	{
+		/* Newer HP Pavilion dv4 models */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+		},
+	},
 	{ }
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/serio/serio_raw.c linux-libre-3.2-gnu1/drivers/input/serio/serio_raw.c
--- linux-libre-3.1-gnu1/drivers/input/serio/serio_raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/serio/serio_raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/kref.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -33,15 +34,16 @@ struct serio_raw {
 	unsigned int tail, head;
 
 	char name[16];
-	unsigned int refcnt;
+	struct kref kref;
 	struct serio *serio;
 	struct miscdevice dev;
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct list_head node;
+	bool dead;
 };
 
-struct serio_raw_list {
+struct serio_raw_client {
 	struct fasync_struct *fasync;
 	struct serio_raw *serio_raw;
 	struct list_head node;
@@ -49,7 +51,6 @@ struct serio_raw_list {
 
 static DEFINE_MUTEX(serio_raw_mutex);
 static LIST_HEAD(serio_raw_list);
-static unsigned int serio_raw_no;
 
 /*********************************************************************
  *             Interface with userspace (file operations)            *
@@ -57,9 +58,9 @@ static unsigned int serio_raw_no;
 
 static int serio_raw_fasync(int fd, struct file *file, int on)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
 
-	return fasync_helper(fd, file, on, &list->fasync);
+	return fasync_helper(fd, file, on, &client->fasync);
 }
 
 static struct serio_raw *serio_raw_locate(int minor)
@@ -77,8 +78,8 @@ static struct serio_raw *serio_raw_locat
 static int serio_raw_open(struct inode *inode, struct file *file)
 {
 	struct serio_raw *serio_raw;
-	struct serio_raw_list *list;
-	int retval = 0;
+	struct serio_raw_client *client;
+	int retval;
 
 	retval = mutex_lock_interruptible(&serio_raw_mutex);
 	if (retval)
@@ -90,60 +91,61 @@ static int serio_raw_open(struct inode *
 		goto out;
 	}
 
-	if (!serio_raw->serio) {
+	if (serio_raw->dead) {
 		retval = -ENODEV;
 		goto out;
 	}
 
-	list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL);
-	if (!list) {
+	client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
+	if (!client) {
 		retval = -ENOMEM;
 		goto out;
 	}
 
-	list->serio_raw = serio_raw;
-	file->private_data = list;
+	client->serio_raw = serio_raw;
+	file->private_data = client;
 
-	serio_raw->refcnt++;
-	list_add_tail(&list->node, &serio_raw->list);
+	kref_get(&serio_raw->kref);
+
+	serio_pause_rx(serio_raw->serio);
+	list_add_tail(&client->node, &serio_raw->client_list);
+	serio_continue_rx(serio_raw->serio);
 
 out:
 	mutex_unlock(&serio_raw_mutex);
 	return retval;
 }
 
-static int serio_raw_cleanup(struct serio_raw *serio_raw)
+static void serio_raw_free(struct kref *kref)
 {
-	if (--serio_raw->refcnt == 0) {
-		misc_deregister(&serio_raw->dev);
-		list_del_init(&serio_raw->node);
-		kfree(serio_raw);
-
-		return 1;
-	}
+	struct serio_raw *serio_raw =
+			container_of(kref, struct serio_raw, kref);
 
-	return 0;
+	put_device(&serio_raw->serio->dev);
+	kfree(serio_raw);
 }
 
 static int serio_raw_release(struct inode *inode, struct file *file)
 {
-	struct serio_raw_list *list = file->private_data;
-	struct serio_raw *serio_raw = list->serio_raw;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 
-	mutex_lock(&serio_raw_mutex);
+	serio_pause_rx(serio_raw->serio);
+	list_del(&client->node);
+	serio_continue_rx(serio_raw->serio);
 
-	serio_raw_cleanup(serio_raw);
+	kfree(client);
+
+	kref_put(&serio_raw->kref, serio_raw_free);
 
-	mutex_unlock(&serio_raw_mutex);
 	return 0;
 }
 
-static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
 {
-	unsigned long flags;
-	int empty;
+	bool empty;
 
-	spin_lock_irqsave(&serio_raw->serio->lock, flags);
+	serio_pause_rx(serio_raw->serio);
 
 	empty = serio_raw->head == serio_raw->tail;
 	if (!empty) {
@@ -151,30 +153,31 @@ static int serio_raw_fetch_byte(struct s
 		serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
 	}
 
-	spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+	serio_continue_rx(serio_raw->serio);
 
 	return !empty;
 }
 
-static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_read(struct file *file, char __user *buffer,
+			      size_t count, loff_t *ppos)
 {
-	struct serio_raw_list *list = file->private_data;
-	struct serio_raw *serio_raw = list->serio_raw;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 	char uninitialized_var(c);
 	ssize_t retval = 0;
 
-	if (!serio_raw->serio)
+	if (serio_raw->dead)
 		return -ENODEV;
 
 	if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->serio_raw->wait,
-					  serio_raw->head != serio_raw->tail || !serio_raw->serio);
+	retval = wait_event_interruptible(serio_raw->wait,
+			serio_raw->head != serio_raw->tail || serio_raw->dead);
 	if (retval)
 		return retval;
 
-	if (!serio_raw->serio)
+	if (serio_raw->dead)
 		return -ENODEV;
 
 	while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -186,9 +189,11 @@ static ssize_t serio_raw_read(struct fil
 	return retval;
 }
 
-static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 	ssize_t written = 0;
 	int retval;
 	unsigned char c;
@@ -197,7 +202,7 @@ static ssize_t serio_raw_write(struct fi
 	if (retval)
 		return retval;
 
-	if (!list->serio_raw->serio) {
+	if (serio_raw->dead) {
 		retval = -ENODEV;
 		goto out;
 	}
@@ -210,7 +215,7 @@ static ssize_t serio_raw_write(struct fi
 			retval = -EFAULT;
 			goto out;
 		}
-		if (serio_write(list->serio_raw->serio, c)) {
+		if (serio_write(serio_raw->serio, c)) {
 			retval = -EIO;
 			goto out;
 		}
@@ -224,46 +229,49 @@ out:
 
 static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
+	unsigned int mask;
 
-	poll_wait(file, &list->serio_raw->wait, wait);
+	poll_wait(file, &serio_raw->wait, wait);
 
-	if (list->serio_raw->head != list->serio_raw->tail)
+	mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
+	if (serio_raw->head != serio_raw->tail)
 		return POLLIN | POLLRDNORM;
 
 	return 0;
 }
 
 static const struct file_operations serio_raw_fops = {
-	.owner =	THIS_MODULE,
-	.open =		serio_raw_open,
-	.release =	serio_raw_release,
-	.read =		serio_raw_read,
-	.write =	serio_raw_write,
-	.poll =		serio_raw_poll,
-	.fasync =	serio_raw_fasync,
-	.llseek = noop_llseek,
+	.owner		= THIS_MODULE,
+	.open		= serio_raw_open,
+	.release	= serio_raw_release,
+	.read		= serio_raw_read,
+	.write		= serio_raw_write,
+	.poll		= serio_raw_poll,
+	.fasync		= serio_raw_fasync,
+	.llseek		= noop_llseek,
 };
 
 
 /*********************************************************************
- *                   Interface with serio port   	             *
+ *                   Interface with serio port                       *
  *********************************************************************/
 
 static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
 					unsigned int dfl)
 {
 	struct serio_raw *serio_raw = serio_get_drvdata(serio);
-	struct serio_raw_list *list;
+	struct serio_raw_client *client;
 	unsigned int head = serio_raw->head;
 
-	/* we are holding serio->lock here so we are prootected */
+	/* we are holding serio->lock here so we are protected */
 	serio_raw->queue[head] = data;
 	head = (head + 1) % SERIO_RAW_QUEUE_LEN;
 	if (likely(head != serio_raw->tail)) {
 		serio_raw->head = head;
-		list_for_each_entry(list, &serio_raw->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		list_for_each_entry(client, &serio_raw->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 		wake_up_interruptible(&serio_raw->wait);
 	}
 
@@ -272,29 +280,37 @@ static irqreturn_t serio_raw_interrupt(s
 
 static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
 {
+	static atomic_t serio_raw_no = ATOMIC_INIT(0);
 	struct serio_raw *serio_raw;
 	int err;
 
-	if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
-		printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+	serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
+	if (!serio_raw) {
+		dev_dbg(&serio->dev, "can't allocate memory for a device\n");
 		return -ENOMEM;
 	}
 
-	mutex_lock(&serio_raw_mutex);
+	snprintf(serio_raw->name, sizeof(serio_raw->name),
+		 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
+	kref_init(&serio_raw->kref);
+	INIT_LIST_HEAD(&serio_raw->client_list);
+	init_waitqueue_head(&serio_raw->wait);
 
-	snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
-	serio_raw->refcnt = 1;
 	serio_raw->serio = serio;
-	INIT_LIST_HEAD(&serio_raw->list);
-	init_waitqueue_head(&serio_raw->wait);
+	get_device(&serio->dev);
 
 	serio_set_drvdata(serio, serio_raw);
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto out_free;
+		goto err_free;
+
+	err = mutex_lock_killable(&serio_raw_mutex);
+	if (err)
+		goto err_close;
 
 	list_add_tail(&serio_raw->node, &serio_raw_list);
+	mutex_unlock(&serio_raw_mutex);
 
 	serio_raw->dev.minor = PSMOUSE_MINOR;
 	serio_raw->dev.name = serio_raw->name;
@@ -308,23 +324,23 @@ static int serio_raw_connect(struct seri
 	}
 
 	if (err) {
-		printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+		dev_err(&serio->dev,
+			"failed to register raw access device for %s\n",
 			serio->phys);
-		goto out_close;
+		goto err_unlink;
 	}
 
-	printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
-		serio->phys, serio_raw->name, serio_raw->dev.minor);
-	goto out;
+	dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
+		 serio->phys, serio_raw->name, serio_raw->dev.minor);
+	return 0;
 
-out_close:
-	serio_close(serio);
+err_unlink:
 	list_del_init(&serio_raw->node);
-out_free:
+err_close:
+	serio_close(serio);
+err_free:
 	serio_set_drvdata(serio, NULL);
-	kfree(serio_raw);
-out:
-	mutex_unlock(&serio_raw_mutex);
+	kref_put(&serio_raw->kref, serio_raw_free);
 	return err;
 }
 
@@ -334,7 +350,8 @@ static int serio_raw_reconnect(struct se
 	struct serio_driver *drv = serio->drv;
 
 	if (!drv || !serio_raw) {
-		printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+		dev_dbg(&serio->dev,
+			"reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
@@ -345,22 +362,40 @@ static int serio_raw_reconnect(struct se
 	return 0;
 }
 
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void serio_raw_hangup(struct serio_raw *serio_raw)
+{
+	struct serio_raw_client *client;
+
+	serio_pause_rx(serio_raw->serio);
+	list_for_each_entry(client, &serio_raw->client_list, node)
+		kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+	serio_continue_rx(serio_raw->serio);
+
+	wake_up_interruptible(&serio_raw->wait);
+}
+
+
 static void serio_raw_disconnect(struct serio *serio)
 {
-	struct serio_raw *serio_raw;
+	struct serio_raw *serio_raw = serio_get_drvdata(serio);
+
+	misc_deregister(&serio_raw->dev);
 
 	mutex_lock(&serio_raw_mutex);
+	serio_raw->dead = true;
+	list_del_init(&serio_raw->node);
+	mutex_unlock(&serio_raw_mutex);
 
-	serio_raw = serio_get_drvdata(serio);
+	serio_raw_hangup(serio_raw);
 
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-
-	serio_raw->serio = NULL;
-	if (!serio_raw_cleanup(serio_raw))
-		wake_up_interruptible(&serio_raw->wait);
+	kref_put(&serio_raw->kref, serio_raw_free);
 
-	mutex_unlock(&serio_raw_mutex);
+	serio_set_drvdata(serio, NULL);
 }
 
 static struct serio_device_id serio_raw_serio_ids[] = {
@@ -391,7 +426,7 @@ static struct serio_driver serio_raw_drv
 	.connect	= serio_raw_connect,
 	.reconnect	= serio_raw_reconnect,
 	.disconnect	= serio_raw_disconnect,
-	.manual_bind	= 1,
+	.manual_bind	= true,
 };
 
 static int __init serio_raw_init(void)
diff -druNp linux-libre-3.1-gnu1/drivers/input/sparse-keymap.c linux-libre-3.2-gnu1/drivers/input/sparse-keymap.c
--- linux-libre-3.1-gnu1/drivers/input/sparse-keymap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/sparse-keymap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
diff -druNp linux-libre-3.1-gnu1/drivers/input/tablet/wacom.h linux-libre-3.2-gnu1/drivers/input/tablet/wacom.h
--- linux-libre-3.1-gnu1/drivers/input/tablet/wacom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/tablet/wacom.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2009 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2002-2011 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -93,7 +93,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.52"
+#define DRIVER_VERSION "v1.53"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -114,6 +114,12 @@ struct wacom {
 	struct mutex lock;
 	bool open;
 	char phys[32];
+	struct wacom_led {
+		u8 select[2]; /* status led selector (0..3) */
+		u8 llv;       /* status led brightness no button (1..127) */
+		u8 hlv;       /* status led brightness button pressed (1..127) */
+		u8 img_lum;   /* OLED matrix display brightness */
+	} led;
 };
 
 extern const struct usb_device_id wacom_ids[];
diff -druNp linux-libre-3.1-gnu1/drivers/input/tablet/wacom_sys.c linux-libre-3.2-gnu1/drivers/input/tablet/wacom_sys.c
--- linux-libre-3.1-gnu1/drivers/input/tablet/wacom_sys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/tablet/wacom_sys.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,27 +48,49 @@ struct hid_descriptor {
 /* defines to get/set USB message */
 #define USB_REQ_GET_REPORT	0x01
 #define USB_REQ_SET_REPORT	0x09
+
 #define WAC_HID_FEATURE_REPORT	0x03
 #define WAC_MSG_RETRIES		5
 
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
+#define WAC_CMD_LED_CONTROL	0x20
+#define WAC_CMD_ICON_START	0x21
+#define WAC_CMD_ICON_XFER	0x23
+#define WAC_CMD_RETRIES		10
+
+static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+			    void *buf, size_t size, unsigned int retries)
 {
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
-		USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 100);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	int retval;
+
+	do {
+		retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				USB_REQ_GET_REPORT,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				(type << 8) + id,
+				intf->altsetting[0].desc.bInterfaceNumber,
+				buf, size, 100);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
 }
 
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
+static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
+			    void *buf, size_t size, unsigned int retries)
 {
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
-                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 1000);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	int retval;
+
+	do {
+		retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				USB_REQ_SET_REPORT,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				(type << 8) + id,
+				intf->altsetting[0].desc.bInterfaceNumber,
+				buf, size, 1000);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
 }
 
 static void wacom_sys_irq(struct urb *urb)
@@ -319,23 +341,23 @@ static int wacom_query_tablet_data(struc
 			rep_data[2] = 0;
 			rep_data[3] = 0;
 			report_id = 3;
-			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-				report_id, rep_data, 4);
+			error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+						 report_id, rep_data, 4, 1);
 			if (error >= 0)
-				error = usb_get_report(intf,
-					WAC_HID_FEATURE_REPORT, report_id,
-					rep_data, 4);
+				error = wacom_get_report(intf,
+						WAC_HID_FEATURE_REPORT,
+						report_id, rep_data, 4, 1);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
 	} else if (features->type != TABLETPC) {
 		do {
 			rep_data[0] = 2;
 			rep_data[1] = 2;
-			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-				report_id, rep_data, 2);
+			error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+						 report_id, rep_data, 2, 1);
 			if (error >= 0)
-				error = usb_get_report(intf,
-					WAC_HID_FEATURE_REPORT, report_id,
-					rep_data, 2);
+				error = wacom_get_report(intf,
+						WAC_HID_FEATURE_REPORT,
+						report_id, rep_data, 2, 1);
 		} while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
 	}
 
@@ -454,6 +476,275 @@ static void wacom_remove_shared_data(str
 	}
 }
 
+static int wacom_led_control(struct wacom *wacom)
+{
+	unsigned char *buf;
+	int retval, led = 0;
+
+	buf = kzalloc(9, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (wacom->wacom_wac.features.type == WACOM_21UX2)
+		led = (wacom->led.select[1] << 4) | 0x40;
+
+	led |=  wacom->led.select[0] | 0x4;
+
+	buf[0] = WAC_CMD_LED_CONTROL;
+	buf[1] = led;
+	buf[2] = wacom->led.llv;
+	buf[3] = wacom->led.hlv;
+	buf[4] = wacom->led.img_lum;
+
+	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
+				  buf, 9, WAC_CMD_RETRIES);
+	kfree(buf);
+
+	return retval;
+}
+
+static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+{
+	unsigned char *buf;
+	int i, retval;
+
+	buf = kzalloc(259, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Send 'start' command */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 1;
+	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+				  buf, 2, WAC_CMD_RETRIES);
+	if (retval < 0)
+		goto out;
+
+	buf[0] = WAC_CMD_ICON_XFER;
+	buf[1] = button_id & 0x07;
+	for (i = 0; i < 4; i++) {
+		buf[2] = i;
+		memcpy(buf + 3, img + i * 256, 256);
+
+		retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
+					  buf, 259, WAC_CMD_RETRIES);
+		if (retval < 0)
+			break;
+	}
+
+	/* Send 'stop' */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 0;
+	wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+			 buf, 2, WAC_CMD_RETRIES);
+
+out:
+	kfree(buf);
+	return retval;
+}
+
+static ssize_t wacom_led_select_store(struct device *dev, int set_id,
+				      const char *buf, size_t count)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	unsigned int id;
+	int err;
+
+	err = kstrtouint(buf, 10, &id);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	wacom->led.select[set_id] = id & 0x3;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LED_SELECT_ATTR(SET_ID)					\
+static ssize_t wacom_led##SET_ID##_select_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_led_select_store(dev, SET_ID, buf, count);		\
+}									\
+static ssize_t wacom_led##SET_ID##_select_show(struct device *dev,	\
+	struct device_attribute *attr, char *buf)			\
+{									\
+	struct wacom *wacom = dev_get_drvdata(dev);			\
+	return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);	\
+}									\
+static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR,	\
+		    wacom_led##SET_ID##_select_show,			\
+		    wacom_led##SET_ID##_select_store)
+
+DEVICE_LED_SELECT_ATTR(0);
+DEVICE_LED_SELECT_ATTR(1);
+
+static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
+				     const char *buf, size_t count)
+{
+	unsigned int value;
+	int err;
+
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	*dest = value & 0x7f;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LUMINANCE_ATTR(name, field)				\
+static ssize_t wacom_##name##_luminance_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct wacom *wacom = dev_get_drvdata(dev);			\
+									\
+	return wacom_luminance_store(wacom, &wacom->led.field,		\
+				     buf, count);			\
+}									\
+static DEVICE_ATTR(name##_luminance, S_IWUSR,				\
+		   NULL, wacom_##name##_luminance_store)
+
+DEVICE_LUMINANCE_ATTR(status0, llv);
+DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(buttons, img_lum);
+
+static ssize_t wacom_button_image_store(struct device *dev, int button_id,
+					const char *buf, size_t count)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	int err;
+
+	if (count != 1024)
+		return -EINVAL;
+
+	mutex_lock(&wacom->lock);
+
+	err = wacom_led_putimage(wacom, button_id, buf);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_BTNIMG_ATTR(BUTTON_ID)					\
+static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_button_image_store(dev, BUTTON_ID, buf, count);	\
+}									\
+static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR,			\
+		   NULL, wacom_btnimg##BUTTON_ID##_store)
+
+DEVICE_BTNIMG_ATTR(0);
+DEVICE_BTNIMG_ATTR(1);
+DEVICE_BTNIMG_ATTR(2);
+DEVICE_BTNIMG_ATTR(3);
+DEVICE_BTNIMG_ATTR(4);
+DEVICE_BTNIMG_ATTR(5);
+DEVICE_BTNIMG_ATTR(6);
+DEVICE_BTNIMG_ATTR(7);
+
+static struct attribute *cintiq_led_attrs[] = {
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_status_led1_select.attr,
+	NULL
+};
+
+static struct attribute_group cintiq_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = cintiq_led_attrs,
+};
+
+static struct attribute *intuos4_led_attrs[] = {
+	&dev_attr_status0_luminance.attr,
+	&dev_attr_status1_luminance.attr,
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_buttons_luminance.attr,
+	&dev_attr_button0_rawimg.attr,
+	&dev_attr_button1_rawimg.attr,
+	&dev_attr_button2_rawimg.attr,
+	&dev_attr_button3_rawimg.attr,
+	&dev_attr_button4_rawimg.attr,
+	&dev_attr_button5_rawimg.attr,
+	&dev_attr_button6_rawimg.attr,
+	&dev_attr_button7_rawimg.attr,
+	NULL
+};
+
+static struct attribute_group intuos4_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = intuos4_led_attrs,
+};
+
+static int wacom_initialize_leds(struct wacom *wacom)
+{
+	int error;
+
+	/* Initialize default values */
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4:
+	case INTUOS4L:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 10;
+		wacom->led.hlv = 20;
+		wacom->led.img_lum = 10;
+		error = sysfs_create_group(&wacom->intf->dev.kobj,
+					   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_21UX2:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 0;
+		wacom->led.hlv = 0;
+		wacom->led.img_lum = 0;
+
+		error = sysfs_create_group(&wacom->intf->dev.kobj,
+					   &cintiq_led_attr_group);
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (error) {
+		dev_err(&wacom->intf->dev,
+			"cannot create sysfs group err: %d\n", error);
+		return error;
+	}
+	wacom_led_control(wacom);
+
+	return 0;
+}
+
+static void wacom_destroy_leds(struct wacom *wacom)
+{
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4:
+	case INTUOS4L:
+		sysfs_remove_group(&wacom->intf->dev.kobj,
+				   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_21UX2:
+		sysfs_remove_group(&wacom->intf->dev.kobj,
+				   &cintiq_led_attr_group);
+		break;
+	}
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -542,16 +833,21 @@ static int wacom_probe(struct usb_interf
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	error = input_register_device(input_dev);
+	error = wacom_initialize_leds(wacom);
 	if (error)
 		goto fail4;
 
+	error = input_register_device(input_dev);
+	if (error)
+		goto fail5;
+
 	/* Note that if query fails it is not a hard failure */
 	wacom_query_tablet_data(intf, features);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
+ fail5: wacom_destroy_leds(wacom);
  fail4:	wacom_remove_shared_data(wacom_wac);
  fail3:	usb_free_urb(wacom->irq);
  fail2:	usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
@@ -568,6 +864,7 @@ static void wacom_disconnect(struct usb_
 
 	usb_kill_urb(wacom->irq);
 	input_unregister_device(wacom->wacom_wac.input);
+	wacom_destroy_leds(wacom);
 	usb_free_urb(wacom->irq);
 	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
 			wacom->wacom_wac.data, wacom->data_dma);
@@ -590,17 +887,16 @@ static int wacom_resume(struct usb_inter
 {
 	struct wacom *wacom = usb_get_intfdata(intf);
 	struct wacom_features *features = &wacom->wacom_wac.features;
-	int rv;
+	int rv = 0;
 
 	mutex_lock(&wacom->lock);
 
 	/* switch to wacom mode first */
 	wacom_query_tablet_data(intf, features);
+	wacom_led_control(wacom);
 
-	if (wacom->open)
-		rv = usb_submit_urb(wacom->irq, GFP_NOIO);
-	else
-		rv = 0;
+	if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+		rv = -EIO;
 
 	mutex_unlock(&wacom->lock);
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/tablet/wacom_wac.c linux-libre-3.2-gnu1/drivers/input/tablet/wacom_wac.c
--- linux-libre-3.1-gnu1/drivers/input/tablet/wacom_wac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/tablet/wacom_wac.c	2012-01-04 18:55:44.000000000 -0500
@@ -874,7 +874,15 @@ static int wacom_bpt_pen(struct wacom_wa
 		x = le16_to_cpup((__le16 *)&data[2]);
 		y = le16_to_cpup((__le16 *)&data[4]);
 		p = le16_to_cpup((__le16 *)&data[6]);
-		d = data[8];
+		/*
+		 * Convert distance from out prox to distance from tablet.
+		 * distance will be greater than distance_max once
+		 * touching and applying pressure; do not report negative
+		 * distance.
+		 */
+		if (data[8] <= wacom->features.distance_max)
+			d = wacom->features.distance_max - data[8];
+
 		pen = data[1] & 0x01;
 		btn1 = data[1] & 0x02;
 		btn2 = data[1] & 0x04;
@@ -1030,8 +1038,6 @@ void wacom_setup_device_quirks(struct wa
 		features->y_max <<= 5;
 		features->x_fuzz <<= 5;
 		features->y_fuzz <<= 5;
-		features->pressure_max = 256;
-		features->pressure_fuzz = 16;
 		features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
 	}
 }
@@ -1241,14 +1247,14 @@ void wacom_setup_input_capabilities(stru
 			input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
 					     0, features->y_max,
 					     features->y_fuzz, 0);
-			input_set_abs_params(input_dev, ABS_MT_PRESSURE,
-					     0, features->pressure_max,
-					     features->pressure_fuzz, 0);
 		} else if (features->device_type == BTN_TOOL_PEN) {
 			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
 			__set_bit(BTN_STYLUS, input_dev->keybit);
 			__set_bit(BTN_STYLUS2, input_dev->keybit);
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+					      features->distance_max,
+					      0, 0);
 		}
 		break;
 	}
@@ -1464,42 +1470,45 @@ static const struct wacom_features wacom
 static const struct wacom_features wacom_features_0xE6 =
 	{ "Wacom ISDv4 E6",       WACOM_PKGLEN_TPC2FG,    27760, 15694,  255,
 	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xEC =
+	{ "Wacom ISDv4 EC",       WACOM_PKGLEN_GRAPHIRE,  25710, 14500,  255,
+	  0, TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x47 =
 	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
 	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD0 =
 	{ "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD1 =
 	{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD2 =
 	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD3 =
-	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13700, 1023,
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
 	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD5 =
-	{ "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
 	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD7 =
 	{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD8 =
-	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13700, 1023,
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xDA =
 	{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static struct wacom_features wacom_features_0xDB =
-	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x6004 =
 	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1605,6 +1614,7 @@ const struct usb_device_id wacom_ids[] =
 	{ USB_DEVICE_WACOM(0xE2) },
 	{ USB_DEVICE_WACOM(0xE3) },
 	{ USB_DEVICE_WACOM(0xE6) },
+	{ USB_DEVICE_WACOM(0xEC) },
 	{ USB_DEVICE_WACOM(0x47) },
 	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7877.c linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7877.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7877.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7877.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ad7877.h>
+#include <linux/module.h>
 #include <asm/irq.h>
 
 #define	TS_PEN_UP_TIMEOUT	msecs_to_jiffies(100)
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879.c linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 
 #include <linux/spi/ad7879.h>
+#include <linux/module.h>
 #include "ad7879.h"
 
 #define AD7879_REG_ZEROS		0
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879-i2c.c linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879-i2c.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 
 #define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ad7879_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -36,9 +36,9 @@ static int ad7879_i2c_resume(struct devi
 
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume);
-#endif
 
 /* All registers are word-sized.
  * AD7879 uses a high-byte first convention.
@@ -119,9 +119,7 @@ static struct i2c_driver ad7879_i2c_driv
 	.driver = {
 		.name	= "ad7879",
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm	= &ad7879_i2c_pm,
-#endif
 	},
 	.probe		= ad7879_i2c_probe,
 	.remove		= __devexit_p(ad7879_i2c_remove),
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879-spi.c linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879-spi.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/ad7879-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/ad7879-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/input.h>	/* BUS_SPI */
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/module.h>
 
 #include "ad7879.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/ads7846.c linux-libre-3.2-gnu1/drivers/input/touchscreen/ads7846.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/ads7846.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/ads7846.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 #include <asm/irq.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/atmel_mxt_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/atmel_mxt_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/atmel_mxt_ts.c	2013-05-02 01:43:51.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/atmel_mxt_ts.c	2013-05-01 23:50:04.000000000 -0400
@@ -910,12 +910,17 @@ static ssize_t mxt_object_show(struct de
 	for (i = 0; i < data->info.object_num; i++) {
 		object = data->object_table + i;
 
-		count += sprintf(buf + count,
-				"Object Table Element %d(Type %d)\n",
+		count += snprintf(buf + count, PAGE_SIZE - count,
+				"Object[%d] (Type %d)\n",
 				i + 1, object->type);
+		if (count >= PAGE_SIZE)
+			return PAGE_SIZE - 1;
 
 		if (!mxt_object_readable(object->type)) {
-			count += sprintf(buf + count, "\n");
+			count += snprintf(buf + count, PAGE_SIZE - count,
+					"\n");
+			if (count >= PAGE_SIZE)
+				return PAGE_SIZE - 1;
 			continue;
 		}
 
@@ -925,11 +930,15 @@ static ssize_t mxt_object_show(struct de
 			if (error)
 				return error;
 
-			count += sprintf(buf + count,
-					"  Byte %d: 0x%x (%d)\n", j, val, val);
+			count += snprintf(buf + count, PAGE_SIZE - count,
+					"\t[%2d]: %02x (%d)\n", j, val, val);
+			if (count >= PAGE_SIZE)
+				return PAGE_SIZE - 1;
 		}
 
-		count += sprintf(buf + count, "\n");
+		count += snprintf(buf + count, PAGE_SIZE - count, "\n");
+		if (count >= PAGE_SIZE)
+			return PAGE_SIZE - 1;
 	}
 
 	return count;
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/atmel_tsadcc.c linux-libre-3.2-gnu1/drivers/input/touchscreen/atmel_tsadcc.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/atmel_tsadcc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/atmel_tsadcc.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@ static int __devinit atmel_tsadcc_probe(
 		goto err_release_mem;
 	}
 
-	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
+	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
 			pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/bu21013_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/bu21013_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/bu21013_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/bu21013_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/input/bu21013.h>
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 #define PEN_DOWN_INTR	0
 #define MAX_FINGERS	2
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/h3600_ts_input.c linux-libre-3.2-gnu1/drivers/input/touchscreen/h3600_ts_input.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/h3600_ts_input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/h3600_ts_input.c	2012-01-04 18:55:44.000000000 -0500
@@ -396,14 +396,14 @@ static int h3600ts_connect(struct serio
 	set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
 
 	if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
-			IRQF_SHARED | IRQF_DISABLED, "h3600_action", ts->dev)) {
+			IRQF_SHARED, "h3600_action", ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
 		err = -EBUSY;
 		goto fail1;
 	}
 
 	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
-			IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", ts->dev)) {
+			IRQF_SHARED, "h3600_suspend", ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
 		err = -EBUSY;
 		goto fail2;
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/hp680_ts_input.c linux-libre-3.2-gnu1/drivers/input/touchscreen/hp680_ts_input.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/hp680_ts_input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/hp680_ts_input.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void)
 	hp680_ts_dev->phys = "hp680_ts/input0";
 
 	if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
-			IRQF_DISABLED, MODNAME, 0) < 0) {
+			0, MODNAME, 0) < 0) {
 		printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
 		       HP680_TS_IRQ);
 		err = -EBUSY;
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/jornada720_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/jornada720_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/jornada720_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/jornada720_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,7 +127,7 @@ static int __devinit jornada720_ts_probe
 
 	error = request_irq(IRQ_GPIO9,
 			jornada720_ts_interrupt,
-			IRQF_DISABLED | IRQF_TRIGGER_RISING,
+			IRQF_TRIGGER_RISING,
 			"HP7XX Touchscreen driver", pdev);
 	if (error) {
 		printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/Kconfig linux-libre-3.2-gnu1/drivers/input/touchscreen/Kconfig
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -651,6 +651,18 @@ config TOUCHSCREEN_TOUCHIT213
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+config TOUCHSCREEN_TSC_SERIO
+	tristate "TSC-10/25/40 serial touchscreen support"
+	select SERIO
+	help
+	  Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected
+	  to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc40.
+
 config TOUCHSCREEN_TSC2005
         tristate "TSC2005 based touchscreens"
         depends on SPI_MASTER && GENERIC_HARDIRQS
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/lpc32xx_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/lpc32xx_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/lpc32xx_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/lpc32xx_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -276,7 +276,7 @@ static int __devinit lpc32xx_ts_probe(st
 	input_set_drvdata(input, tsc);
 
 	error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
-			    IRQF_DISABLED, pdev->name, tsc);
+			    0, pdev->name, tsc);
 	if (error) {
 		dev_err(&pdev->dev, "failed requesting interrupt\n");
 		goto err_put_clock;
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/Makefile linux-libre-3.2-gnu1/drivers/input/touchscreen/Makefile
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= t
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO)	+= tsc40.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2005)	+= tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/mc13783_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/mc13783_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/mc13783_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/mc13783_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@ MODULE_PARM_DESC(sample_tolerance,
 
 struct mc13783_ts_priv {
 	struct input_dev *idev;
-	struct mc13783 *mc13783;
+	struct mc13xxx *mc13xxx;
 	struct delayed_work work;
 	struct workqueue_struct *workq;
 	unsigned int sample[4];
@@ -45,7 +45,7 @@ static irqreturn_t mc13783_ts_handler(in
 {
 	struct mc13783_ts_priv *priv = data;
 
-	mc13783_irq_ack(priv->mc13783, irq);
+	mc13xxx_irq_ack(priv->mc13xxx, irq);
 
 	/*
 	 * Kick off reading coordinates. Note that if work happens already
@@ -121,10 +121,10 @@ static void mc13783_ts_work(struct work_
 {
 	struct mc13783_ts_priv *priv =
 		container_of(work, struct mc13783_ts_priv, work.work);
-	unsigned int mode = MC13783_ADC_MODE_TS;
+	unsigned int mode = MC13XXX_ADC_MODE_TS;
 	unsigned int channel = 12;
 
-	if (mc13783_adc_do_conversion(priv->mc13783,
+	if (mc13xxx_adc_do_conversion(priv->mc13xxx,
 				mode, channel, priv->sample) == 0)
 		mc13783_ts_report_sample(priv);
 }
@@ -134,21 +134,21 @@ static int mc13783_ts_open(struct input_
 	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
 	int ret;
 
-	mc13783_lock(priv->mc13783);
+	mc13xxx_lock(priv->mc13xxx);
 
-	mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS);
+	mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
 
-	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+	ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
 		mc13783_ts_handler, MC13783_TS_NAME, priv);
 	if (ret)
 		goto out;
 
-	ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-			MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+	ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+			MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0);
 	if (ret)
-		mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+		mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
 out:
-	mc13783_unlock(priv->mc13783);
+	mc13xxx_unlock(priv->mc13xxx);
 	return ret;
 }
 
@@ -156,11 +156,11 @@ static void mc13783_ts_close(struct inpu
 {
 	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
 
-	mc13783_lock(priv->mc13783);
-	mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-			MC13783_ADC0_TSMOD_MASK, 0);
-	mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
-	mc13783_unlock(priv->mc13783);
+	mc13xxx_lock(priv->mc13xxx);
+	mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+			MC13XXX_ADC0_TSMOD_MASK, 0);
+	mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
+	mc13xxx_unlock(priv->mc13xxx);
 
 	cancel_delayed_work_sync(&priv->work);
 }
@@ -177,7 +177,7 @@ static int __init mc13783_ts_probe(struc
 		goto err_free_mem;
 
 	INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
-	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
 	priv->idev = idev;
 
 	/*
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/penmount.c linux-libre-3.2-gnu1/drivers/input/touchscreen/penmount.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/penmount.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/penmount.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * Penmount serial touchscreen driver
  *
  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
  *
  * Based on ELO driver (drivers/input/touchscreen/elo.c)
  * Copyright (c) 2004 Vojtech Pavlik
@@ -18,12 +19,14 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/init.h>
 
-#define DRIVER_DESC	"Penmount serial touchscreen driver"
+#define DRIVER_DESC	"PenMount serial touchscreen driver"
 
 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
+MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
@@ -31,7 +34,19 @@ MODULE_LICENSE("GPL");
  * Definitions & global arrays.
  */
 
-#define	PM_MAX_LENGTH	5
+#define	PM_MAX_LENGTH	6
+#define	PM_MAX_MTSLOT	16
+#define	PM_3000_MTSLOT	2
+#define	PM_6250_MTSLOT	12
+
+/*
+ * Multi-touch slot
+ */
+
+struct mt_slot {
+	unsigned short x, y;
+	bool active; /* is the touch valid? */
+};
 
 /*
  * Per-touchscreen data.
@@ -43,25 +58,119 @@ struct pm {
 	int idx;
 	unsigned char data[PM_MAX_LENGTH];
 	char phys[32];
+	unsigned char packetsize;
+	unsigned char maxcontacts;
+	struct mt_slot slots[PM_MAX_MTSLOT];
+	void (*parse_packet)(struct pm *);
 };
 
-static irqreturn_t pm_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags)
+/*
+ * pm_mtevent() sends mt events and also emulates pointer movement
+ */
+
+static void pm_mtevent(struct pm *pm, struct input_dev *input)
+{
+	int i;
+
+	for (i = 0; i < pm->maxcontacts; ++i) {
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER,
+				pm->slots[i].active);
+		if (pm->slots[i].active) {
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y);
+		}
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+	input_sync(input);
+}
+
+/*
+ * pm_checkpacket() checks if data packet is valid
+ */
+
+static bool pm_checkpacket(unsigned char *packet)
+{
+	int total = 0;
+	int i;
+
+	for (i = 0; i < 5; i++)
+		total += packet[i];
+
+	return packet[5] == (unsigned char)~(total & 0xff);
+}
+
+static void pm_parse_9000(struct pm *pm)
 {
-	struct pm *pm = serio_get_drvdata(serio);
 	struct input_dev *dev = pm->dev;
 
-	pm->data[pm->idx] = data;
+	if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) {
+		input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
+		input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
+		input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+		input_sync(dev);
+		pm->idx = 0;
+	}
+}
 
-	if (pm->data[0] & 0x80) {
-		if (PM_MAX_LENGTH == ++pm->idx) {
-			input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]);
-			input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]);
-			input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+static void pm_parse_6000(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			input_report_abs(dev, ABS_X,
+					pm->data[2] * 256 + pm->data[1]);
+			input_report_abs(dev, ABS_Y,
+					pm->data[4] * 256 + pm->data[3]);
+			input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40);
 			input_sync(dev);
-			pm->idx = 0;
 		}
+		pm->idx = 0;
 	}
+}
+
+static void pm_parse_3000(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			int slotnum = pm->data[0] & 0x0f;
+			pm->slots[slotnum].active = pm->data[0] & 0x30;
+			pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+			pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+			pm_mtevent(pm, dev);
+		}
+		pm->idx = 0;
+	}
+}
+
+static void pm_parse_6250(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			int slotnum = pm->data[0] & 0x0f;
+			pm->slots[slotnum].active = pm->data[0] & 0x40;
+			pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+			pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+			pm_mtevent(pm, dev);
+		}
+		pm->idx = 0;
+	}
+}
+
+static irqreturn_t pm_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct pm *pm = serio_get_drvdata(serio);
+
+	pm->data[pm->idx] = data;
+
+	pm->parse_packet(pm);
 
 	return IRQ_HANDLED;
 }
@@ -74,17 +183,17 @@ static void pm_disconnect(struct serio *
 {
 	struct pm *pm = serio_get_drvdata(serio);
 
-	input_get_device(pm->dev);
-	input_unregister_device(pm->dev);
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-	input_put_device(pm->dev);
+
+	input_unregister_device(pm->dev);
 	kfree(pm);
+
+	serio_set_drvdata(serio, NULL);
 }
 
 /*
  * pm_connect() is the routine that is called when someone adds a
- * new serio device that supports Gunze protocol and registers it as
+ * new serio device that supports PenMount protocol and registers it as
  * an input device.
  */
 
@@ -92,6 +201,7 @@ static int pm_connect(struct serio *seri
 {
 	struct pm *pm;
 	struct input_dev *input_dev;
+	int max_x, max_y;
 	int err;
 
 	pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
@@ -104,8 +214,9 @@ static int pm_connect(struct serio *seri
 	pm->serio = serio;
 	pm->dev = input_dev;
 	snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
+	pm->maxcontacts = 1;
 
-	input_dev->name = "Penmount Serial TouchScreen";
+	input_dev->name = "PenMount Serial TouchScreen";
 	input_dev->phys = pm->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_PENMOUNT;
@@ -113,10 +224,52 @@ static int pm_connect(struct serio *seri
 	input_dev->id.version = 0x0100;
 	input_dev->dev.parent = &serio->dev;
 
-        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-        input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
-        input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	switch (serio->id.id) {
+	default:
+	case 0:
+		pm->packetsize = 5;
+		pm->parse_packet = pm_parse_9000;
+		input_dev->id.product = 0x9000;
+		max_x = max_y = 0x3ff;
+		break;
+
+	case 1:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_6000;
+		input_dev->id.product = 0x6000;
+		max_x = max_y = 0x3ff;
+		break;
+
+	case 2:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_3000;
+		input_dev->id.product = 0x3000;
+		max_x = max_y = 0x7ff;
+		pm->maxcontacts = PM_3000_MTSLOT;
+		break;
+
+	case 3:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_6250;
+		input_dev->id.product = 0x6250;
+		max_x = max_y = 0x3ff;
+		pm->maxcontacts = PM_6250_MTSLOT;
+		break;
+	}
+
+	input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
+	input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
+
+	if (pm->maxcontacts > 1) {
+		input_mt_init_slots(pm->dev, pm->maxcontacts);
+		input_set_abs_params(pm->dev,
+				     ABS_MT_POSITION_X, 0, max_x, 0, 0);
+		input_set_abs_params(pm->dev,
+				     ABS_MT_POSITION_Y, 0, max_y, 0, 0);
+	}
 
 	serio_set_drvdata(serio, pm);
 
@@ -155,7 +308,7 @@ MODULE_DEVICE_TABLE(serio, pm_serio_ids)
 
 static struct serio_driver pm_drv = {
 	.driver		= {
-		.name	= "penmountlpc",
+		.name	= "serio-penmount",
 	},
 	.description	= DRIVER_DESC,
 	.id_table	= pm_serio_ids,
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/s3c2410_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/s3c2410_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/s3c2410_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/s3c2410_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -328,7 +328,7 @@ static int __devinit s3c2410ts_probe(str
 	ts.shift = info->oversampling_shift;
 	ts.features = platform_get_device_id(pdev)->driver_data;
 
-	ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
+	ret = request_irq(ts.irq_tc, stylus_irq, 0,
 			  "s3c2410_ts_pen", ts.input);
 	if (ret) {
 		dev_err(dev, "cannot get TC interrupt\n");
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/tsc2007.c linux-libre-3.2-gnu1/drivers/input/touchscreen/tsc2007.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/tsc2007.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/tsc2007.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,6 @@ struct ts_event {
 struct tsc2007 {
 	struct input_dev	*input;
 	char			phys[32];
-	struct delayed_work	work;
 
 	struct i2c_client	*client;
 
@@ -76,9 +75,11 @@ struct tsc2007 {
 	unsigned long		poll_delay;
 	unsigned long		poll_period;
 
-	bool			pendown;
 	int			irq;
 
+	wait_queue_head_t	wait;
+	bool			stopped;
+
 	int			(*get_pendown_state)(void);
 	void			(*clear_penirq)(void);
 };
@@ -141,25 +142,8 @@ static u32 tsc2007_calculate_pressure(st
 	return rt;
 }
 
-static void tsc2007_send_up_event(struct tsc2007 *tsc)
-{
-	struct input_dev *input = tsc->input;
-
-	dev_dbg(&tsc->client->dev, "UP\n");
-
-	input_report_key(input, BTN_TOUCH, 0);
-	input_report_abs(input, ABS_PRESSURE, 0);
-	input_sync(input);
-}
-
-static void tsc2007_work(struct work_struct *work)
+static bool tsc2007_is_pen_down(struct tsc2007 *ts)
 {
-	struct tsc2007 *ts =
-		container_of(to_delayed_work(work), struct tsc2007, work);
-	bool debounced = false;
-	struct ts_event tc;
-	u32 rt;
-
 	/*
 	 * NOTE: We can't rely on the pressure to determine the pen down
 	 * state, even though this controller has a pressure sensor.
@@ -170,79 +154,82 @@ static void tsc2007_work(struct work_str
 	 * The only safe way to check for the pen up condition is in the
 	 * work function by reading the pen signal state (it's a GPIO
 	 * and IRQ). Unfortunately such callback is not always available,
-	 * in that case we have rely on the pressure anyway.
+	 * in that case we assume that the pen is down and expect caller
+	 * to fall back on the pressure reading.
 	 */
-	if (ts->get_pendown_state) {
-		if (unlikely(!ts->get_pendown_state())) {
-			tsc2007_send_up_event(ts);
-			ts->pendown = false;
-			goto out;
-		}
 
-		dev_dbg(&ts->client->dev, "pen is still down\n");
-	}
+	if (!ts->get_pendown_state)
+		return true;
 
-	tsc2007_read_values(ts, &tc);
+	return ts->get_pendown_state();
+}
 
-	rt = tsc2007_calculate_pressure(ts, &tc);
-	if (rt > ts->max_rt) {
-		/*
-		 * Sample found inconsistent by debouncing or pressure is
-		 * beyond the maximum. Don't report it to user space,
-		 * repeat at least once more the measurement.
-		 */
-		dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
-		debounced = true;
-		goto out;
+static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
+{
+	struct tsc2007 *ts = handle;
+	struct input_dev *input = ts->input;
+	struct ts_event tc;
+	u32 rt;
 
-	}
+	while (!ts->stopped && tsc2007_is_pen_down(ts)) {
 
-	if (rt) {
-		struct input_dev *input = ts->input;
+		/* pen is down, continue with the measurement */
+		tsc2007_read_values(ts, &tc);
 
-		if (!ts->pendown) {
-			dev_dbg(&ts->client->dev, "DOWN\n");
+		rt = tsc2007_calculate_pressure(ts, &tc);
 
-			input_report_key(input, BTN_TOUCH, 1);
-			ts->pendown = true;
+		if (rt == 0 && !ts->get_pendown_state) {
+			/*
+			 * If pressure reported is 0 and we don't have
+			 * callback to check pendown state, we have to
+			 * assume that pen was lifted up.
+			 */
+			break;
 		}
 
-		input_report_abs(input, ABS_X, tc.x);
-		input_report_abs(input, ABS_Y, tc.y);
-		input_report_abs(input, ABS_PRESSURE, rt);
+		if (rt <= ts->max_rt) {
+			dev_dbg(&ts->client->dev,
+				"DOWN point(%4d,%4d), pressure (%4u)\n",
+				tc.x, tc.y, rt);
 
-		input_sync(input);
+			input_report_key(input, BTN_TOUCH, 1);
+			input_report_abs(input, ABS_X, tc.x);
+			input_report_abs(input, ABS_Y, tc.y);
+			input_report_abs(input, ABS_PRESSURE, rt);
 
-		dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
-			tc.x, tc.y, rt);
+			input_sync(input);
 
-	} else if (!ts->get_pendown_state && ts->pendown) {
-		/*
-		 * We don't have callback to check pendown state, so we
-		 * have to assume that since pressure reported is 0 the
-		 * pen was lifted up.
-		 */
-		tsc2007_send_up_event(ts);
-		ts->pendown = false;
+		} else {
+			/*
+			 * Sample found inconsistent by debouncing or pressure is
+			 * beyond the maximum. Don't report it to user space,
+			 * repeat at least once more the measurement.
+			 */
+			dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
+		}
+
+		wait_event_timeout(ts->wait, ts->stopped,
+				   msecs_to_jiffies(ts->poll_period));
 	}
 
- out:
-	if (ts->pendown || debounced)
-		schedule_delayed_work(&ts->work,
-				      msecs_to_jiffies(ts->poll_period));
-	else
-		enable_irq(ts->irq);
+	dev_dbg(&ts->client->dev, "UP\n");
+
+	input_report_key(input, BTN_TOUCH, 0);
+	input_report_abs(input, ABS_PRESSURE, 0);
+	input_sync(input);
+
+	if (ts->clear_penirq)
+		ts->clear_penirq();
+
+	return IRQ_HANDLED;
 }
 
-static irqreturn_t tsc2007_irq(int irq, void *handle)
+static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
 {
 	struct tsc2007 *ts = handle;
 
-	if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
-		disable_irq_nosync(ts->irq);
-		schedule_delayed_work(&ts->work,
-				      msecs_to_jiffies(ts->poll_delay));
-	}
+	if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
+		return IRQ_WAKE_THREAD;
 
 	if (ts->clear_penirq)
 		ts->clear_penirq();
@@ -250,17 +237,40 @@ static irqreturn_t tsc2007_irq(int irq,
 	return IRQ_HANDLED;
 }
 
-static void tsc2007_free_irq(struct tsc2007 *ts)
+static void tsc2007_stop(struct tsc2007 *ts)
 {
-	free_irq(ts->irq, ts);
-	if (cancel_delayed_work_sync(&ts->work)) {
-		/*
-		 * Work was pending, therefore we need to enable
-		 * IRQ here to balance the disable_irq() done in the
-		 * interrupt handler.
-		 */
-		enable_irq(ts->irq);
+	ts->stopped = true;
+	mb();
+	wake_up(&ts->wait);
+
+	disable_irq(ts->irq);
+}
+
+static int tsc2007_open(struct input_dev *input_dev)
+{
+	struct tsc2007 *ts = input_get_drvdata(input_dev);
+	int err;
+
+	ts->stopped = false;
+	mb();
+
+	enable_irq(ts->irq);
+
+	/* Prepare for touch readings - power down ADC and enable PENIRQ */
+	err = tsc2007_xfer(ts, PWRDOWN);
+	if (err < 0) {
+		tsc2007_stop(ts);
+		return err;
 	}
+
+	return 0;
+}
+
+static void tsc2007_close(struct input_dev *input_dev)
+{
+	struct tsc2007 *ts = input_get_drvdata(input_dev);
+
+	tsc2007_stop(ts);
 }
 
 static int __devinit tsc2007_probe(struct i2c_client *client,
@@ -290,7 +300,7 @@ static int __devinit tsc2007_probe(struc
 	ts->client = client;
 	ts->irq = client->irq;
 	ts->input = input_dev;
-	INIT_DELAYED_WORK(&ts->work, tsc2007_work);
+	init_waitqueue_head(&ts->wait);
 
 	ts->model             = pdata->model;
 	ts->x_plate_ohms      = pdata->x_plate_ohms;
@@ -300,6 +310,12 @@ static int __devinit tsc2007_probe(struc
 	ts->get_pendown_state = pdata->get_pendown_state;
 	ts->clear_penirq      = pdata->clear_penirq;
 
+	if (pdata->x_plate_ohms == 0) {
+		dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
+		err = -EINVAL;
+		goto err_free_mem;
+	}
+
 	snprintf(ts->phys, sizeof(ts->phys),
 		 "%s/input0", dev_name(&client->dev));
 
@@ -307,6 +323,11 @@ static int __devinit tsc2007_probe(struc
 	input_dev->phys = ts->phys;
 	input_dev->id.bustype = BUS_I2C;
 
+	input_dev->open = tsc2007_open;
+	input_dev->close = tsc2007_close;
+
+	input_set_drvdata(input_dev, ts);
+
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
@@ -318,17 +339,14 @@ static int __devinit tsc2007_probe(struc
 	if (pdata->init_platform_hw)
 		pdata->init_platform_hw();
 
-	err = request_irq(ts->irq, tsc2007_irq, 0,
-			client->dev.driver->name, ts);
+	err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
+				   IRQF_ONESHOT, client->dev.driver->name, ts);
 	if (err < 0) {
 		dev_err(&client->dev, "irq %d busy?\n", ts->irq);
 		goto err_free_mem;
 	}
 
-	/* Prepare for touch readings - power down ADC and enable PENIRQ */
-	err = tsc2007_xfer(ts, PWRDOWN);
-	if (err < 0)
-		goto err_free_irq;
+	tsc2007_stop(ts);
 
 	err = input_register_device(input_dev);
 	if (err)
@@ -339,7 +357,7 @@ static int __devinit tsc2007_probe(struc
 	return 0;
 
  err_free_irq:
-	tsc2007_free_irq(ts);
+	free_irq(ts->irq, ts);
 	if (pdata->exit_platform_hw)
 		pdata->exit_platform_hw();
  err_free_mem:
@@ -353,7 +371,7 @@ static int __devexit tsc2007_remove(stru
 	struct tsc2007	*ts = i2c_get_clientdata(client);
 	struct tsc2007_platform_data *pdata = client->dev.platform_data;
 
-	tsc2007_free_irq(ts);
+	free_irq(ts->irq, ts);
 
 	if (pdata->exit_platform_hw)
 		pdata->exit_platform_hw();
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/tsc40.c linux-libre-3.2-gnu1/drivers/input/touchscreen/tsc40.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/tsc40.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/tsc40.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * TSC-40 serial touchscreen driver. It should be compatible with
+ * TSC-10 and 25.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * License: GPLv2 as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define PACKET_LENGTH  5
+struct tsc_ser {
+	struct input_dev *dev;
+	struct serio *serio;
+	u32 idx;
+	unsigned char data[PACKET_LENGTH];
+	char phys[32];
+};
+
+static void tsc_process_data(struct tsc_ser *ptsc)
+{
+	struct input_dev *dev = ptsc->dev;
+	u8 *data = ptsc->data;
+	u32 x;
+	u32 y;
+
+	x = ((data[1] & 0x03) << 8) | data[2];
+	y = ((data[3] & 0x03) << 8) | data[4];
+
+	input_report_abs(dev, ABS_X, x);
+	input_report_abs(dev, ABS_Y, y);
+	input_report_key(dev, BTN_TOUCH, 1);
+
+	input_sync(dev);
+}
+
+static irqreturn_t tsc_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct tsc_ser *ptsc = serio_get_drvdata(serio);
+	struct input_dev *dev = ptsc->dev;
+
+	ptsc->data[ptsc->idx] = data;
+	switch (ptsc->idx++) {
+	case 0:
+		if (unlikely((data & 0x3e) != 0x10)) {
+			dev_dbg(&serio->dev,
+				"unsynchronized packet start (0x%02x)\n", data);
+			ptsc->idx = 0;
+		} else if (!(data & 0x01)) {
+			input_report_key(dev, BTN_TOUCH, 0);
+			input_sync(dev);
+			ptsc->idx = 0;
+		}
+		break;
+
+	case 1:
+	case 3:
+		if (unlikely(data & 0xfc)) {
+			dev_dbg(&serio->dev,
+				"unsynchronized data 0x%02x at offset %d\n",
+				data, ptsc->idx - 1);
+			ptsc->idx = 0;
+		}
+		break;
+
+	case 4:
+		tsc_process_data(ptsc);
+		ptsc->idx = 0;
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int tsc_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct tsc_ser *ptsc;
+	struct input_dev *input_dev;
+	int error;
+
+	ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ptsc || !input_dev) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+
+	ptsc->serio = serio;
+	ptsc->dev = input_dev;
+	snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
+
+	input_dev->name = "TSC-10/25/40 Serial TouchScreen";
+	input_dev->phys = ptsc->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_TSC40;
+	input_dev->id.product = 40;
+	input_dev->id.version = 0x0001;
+	input_dev->dev.parent = &serio->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
+	input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
+	input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
+
+	serio_set_drvdata(serio, ptsc);
+
+	error = serio_open(serio, drv);
+	if (error)
+		goto fail2;
+
+	error = input_register_device(ptsc->dev);
+	if (error)
+		goto fail3;
+
+	return 0;
+
+fail3:
+	serio_close(serio);
+fail2:
+	serio_set_drvdata(serio, NULL);
+fail1:
+	input_free_device(input_dev);
+	kfree(ptsc);
+	return error;
+}
+
+static void tsc_disconnect(struct serio *serio)
+{
+	struct tsc_ser *ptsc = serio_get_drvdata(serio);
+
+	serio_close(serio);
+
+	input_unregister_device(ptsc->dev);
+	kfree(ptsc);
+
+	serio_set_drvdata(serio, NULL);
+}
+
+static struct serio_device_id tsc_serio_ids[] = {
+	{
+		.type   = SERIO_RS232,
+		.proto  = SERIO_TSC40,
+		.id     = SERIO_ANY,
+		.extra  = SERIO_ANY,
+	},
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(serio, tsc_serio_ids);
+
+#define DRIVER_DESC    "TSC-10/25/40 serial touchscreen driver"
+
+static struct serio_driver tsc_drv = {
+	.driver	= {
+		.name   = "tsc40",
+	},
+	.description    = DRIVER_DESC,
+	.id_table	= tsc_serio_ids,
+	.interrupt      = tsc_interrupt,
+	.connect	= tsc_connect,
+	.disconnect     = tsc_disconnect,
+};
+
+static int __init tsc_ser_init(void)
+{
+	return serio_register_driver(&tsc_drv);
+}
+module_init(tsc_ser_init);
+
+static void __exit tsc_exit(void)
+{
+	serio_unregister_driver(&tsc_drv);
+}
+module_exit(tsc_exit);
+
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/w90p910_ts.c linux-libre-3.2-gnu1/drivers/input/touchscreen/w90p910_ts.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/w90p910_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/w90p910_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -279,7 +279,7 @@ static int __devinit w90x900ts_probe(str
 
 	w90p910_ts->irq_num = platform_get_irq(pdev, 0);
 	if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt,
-			IRQF_DISABLED, "w90p910ts", w90p910_ts)) {
+			0, "w90p910ts", w90p910_ts)) {
 		err = -EBUSY;
 		goto fail4;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/input/touchscreen/wacom_w8001.c linux-libre-3.2-gnu1/drivers/input/touchscreen/wacom_w8001.c
--- linux-libre-3.1-gnu1/drivers/input/touchscreen/wacom_w8001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/input/touchscreen/wacom_w8001.c	2012-01-04 18:55:44.000000000 -0500
@@ -367,6 +367,20 @@ static int w8001_command(struct w8001 *w
 	return rc;
 }
 
+static int w8001_open(struct input_dev *dev)
+{
+	struct w8001 *w8001 = input_get_drvdata(dev);
+
+	return w8001_command(w8001, W8001_CMD_START, false);
+}
+
+static void w8001_close(struct input_dev *dev)
+{
+	struct w8001 *w8001 = input_get_drvdata(dev);
+
+	w8001_command(w8001, W8001_CMD_STOP, false);
+}
+
 static int w8001_setup(struct w8001 *w8001)
 {
 	struct input_dev *dev = w8001->dev;
@@ -476,7 +490,7 @@ static int w8001_setup(struct w8001 *w80
 
 	strlcat(w8001->name, " Touchscreen", sizeof(w8001->name));
 
-	return w8001_command(w8001, W8001_CMD_START, false);
+	return 0;
 }
 
 /*
@@ -487,12 +501,12 @@ static void w8001_disconnect(struct seri
 {
 	struct w8001 *w8001 = serio_get_drvdata(serio);
 
-	input_get_device(w8001->dev);
-	input_unregister_device(w8001->dev);
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-	input_put_device(w8001->dev);
+
+	input_unregister_device(w8001->dev);
 	kfree(w8001);
+
+	serio_set_drvdata(serio, NULL);
 }
 
 /*
@@ -536,6 +550,11 @@ static int w8001_connect(struct serio *s
 	input_dev->id.version = 0x0100;
 	input_dev->dev.parent = &serio->dev;
 
+	input_dev->open = w8001_open;
+	input_dev->close = w8001_close;
+
+	input_set_drvdata(input_dev, w8001);
+
 	err = input_register_device(w8001->dev);
 	if (err)
 		goto fail3;
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/amd_iommu.c linux-libre-3.2-gnu1/drivers/iommu/amd_iommu.c
--- linux-libre-3.1-gnu1/drivers/iommu/amd_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/amd_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -1283,7 +1283,7 @@ static int alloc_new_range(struct dma_op
 		if (!pte || !IOMMU_PTE_PRESENT(*pte))
 			continue;
 
-		dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
+		dma_ops_reserve_addresses(dma_dom, i >> PAGE_SHIFT, 1);
 	}
 
 	update_domain(&dma_dom->domain);
@@ -2495,7 +2495,7 @@ static unsigned device_dma_ops_init(void
 
 void __init amd_iommu_init_api(void)
 {
-	register_iommu(&amd_iommu_ops);
+	bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
 }
 
 int __init amd_iommu_init_dma_ops(void)
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/dmar.c linux-libre-3.2-gnu1/drivers/iommu/dmar.c
--- linux-libre-3.1-gnu1/drivers/iommu/dmar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/dmar.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,7 +46,7 @@
  */
 LIST_HEAD(dmar_drhd_units);
 
-static struct acpi_table_header * __initdata dmar_tbl;
+struct acpi_table_header * __initdata dmar_tbl;
 static acpi_size dmar_tbl_size;
 
 static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
@@ -118,8 +118,8 @@ static int __init dmar_parse_one_dev_sco
 	return 0;
 }
 
-static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
-				       struct pci_dev ***devices, u16 segment)
+int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
+				struct pci_dev ***devices, u16 segment)
 {
 	struct acpi_dmar_device_scope *scope;
 	void * tmp = start;
@@ -217,133 +217,6 @@ static int __init dmar_parse_dev(struct
 	return ret;
 }
 
-#ifdef CONFIG_DMAR
-LIST_HEAD(dmar_rmrr_units);
-
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
-	list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
-
-static int __init
-dmar_parse_one_rmrr(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	struct dmar_rmrr_unit *rmrru;
-
-	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
-	if (!rmrru)
-		return -ENOMEM;
-
-	rmrru->hdr = header;
-	rmrr = (struct acpi_dmar_reserved_memory *)header;
-	rmrru->base_address = rmrr->base_address;
-	rmrru->end_address = rmrr->end_address;
-
-	dmar_register_rmrr_unit(rmrru);
-	return 0;
-}
-
-static int __init
-rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	int ret;
-
-	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
-	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
-		((void *)rmrr) + rmrr->header.length,
-		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
-
-	if (ret || (rmrru->devices_cnt == 0)) {
-		list_del(&rmrru->list);
-		kfree(rmrru);
-	}
-	return ret;
-}
-
-static LIST_HEAD(dmar_atsr_units);
-
-static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
-{
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
-	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
-	if (!atsru)
-		return -ENOMEM;
-
-	atsru->hdr = hdr;
-	atsru->include_all = atsr->flags & 0x1;
-
-	list_add(&atsru->list, &dmar_atsr_units);
-
-	return 0;
-}
-
-static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
-{
-	int rc;
-	struct acpi_dmar_atsr *atsr;
-
-	if (atsru->include_all)
-		return 0;
-
-	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-	rc = dmar_parse_dev_scope((void *)(atsr + 1),
-				(void *)atsr + atsr->header.length,
-				&atsru->devices_cnt, &atsru->devices,
-				atsr->segment);
-	if (rc || !atsru->devices_cnt) {
-		list_del(&atsru->list);
-		kfree(atsru);
-	}
-
-	return rc;
-}
-
-int dmar_find_matched_atsr_unit(struct pci_dev *dev)
-{
-	int i;
-	struct pci_bus *bus;
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	dev = pci_physfn(dev);
-
-	list_for_each_entry(atsru, &dmar_atsr_units, list) {
-		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-		if (atsr->segment == pci_domain_nr(dev->bus))
-			goto found;
-	}
-
-	return 0;
-
-found:
-	for (bus = dev->bus; bus; bus = bus->parent) {
-		struct pci_dev *bridge = bus->self;
-
-		if (!bridge || !pci_is_pcie(bridge) ||
-		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-			return 0;
-
-		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
-			for (i = 0; i < atsru->devices_cnt; i++)
-				if (atsru->devices[i] == bridge)
-					return 1;
-			break;
-		}
-	}
-
-	if (atsru->include_all)
-		return 1;
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_ACPI_NUMA
 static int __init
 dmar_parse_one_rhsa(struct acpi_dmar_header *header)
@@ -484,14 +357,10 @@ parse_dmar_table(void)
 			ret = dmar_parse_one_drhd(entry_header);
 			break;
 		case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-#ifdef CONFIG_DMAR
 			ret = dmar_parse_one_rmrr(entry_header);
-#endif
 			break;
 		case ACPI_DMAR_TYPE_ATSR:
-#ifdef CONFIG_DMAR
 			ret = dmar_parse_one_atsr(entry_header);
-#endif
 			break;
 		case ACPI_DMAR_HARDWARE_AFFINITY:
 #ifdef CONFIG_ACPI_NUMA
@@ -557,34 +426,31 @@ dmar_find_matched_drhd_unit(struct pci_d
 
 int __init dmar_dev_scope_init(void)
 {
+	static int dmar_dev_scope_initialized;
 	struct dmar_drhd_unit *drhd, *drhd_n;
 	int ret = -ENODEV;
 
+	if (dmar_dev_scope_initialized)
+		return dmar_dev_scope_initialized;
+
+	if (list_empty(&dmar_drhd_units))
+		goto fail;
+
 	list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
 		ret = dmar_parse_dev(drhd);
 		if (ret)
-			return ret;
+			goto fail;
 	}
 
-#ifdef CONFIG_DMAR
-	{
-		struct dmar_rmrr_unit *rmrr, *rmrr_n;
-		struct dmar_atsr_unit *atsr, *atsr_n;
-
-		list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
-			ret = rmrr_parse_dev(rmrr);
-			if (ret)
-				return ret;
-		}
+	ret = dmar_parse_rmrr_atsr_dev();
+	if (ret)
+		goto fail;
 
-		list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
-			ret = atsr_parse_dev(atsr);
-			if (ret)
-				return ret;
-		}
-	}
-#endif
+	dmar_dev_scope_initialized = 1;
+	return 0;
 
+fail:
+	dmar_dev_scope_initialized = ret;
 	return ret;
 }
 
@@ -611,14 +477,6 @@ int __init dmar_table_init(void)
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_DMAR
-	if (list_empty(&dmar_rmrr_units))
-		printk(KERN_INFO PREFIX "No RMRR found\n");
-
-	if (list_empty(&dmar_atsr_units))
-		printk(KERN_INFO PREFIX "No ATSR found\n");
-#endif
-
 	return 0;
 }
 
@@ -682,9 +540,6 @@ int __init check_zero_address(void)
 	return 1;
 
 failed:
-#ifdef CONFIG_DMAR
-	dmar_disabled = 1;
-#endif
 	return 0;
 }
 
@@ -696,22 +551,21 @@ int __init detect_intel_iommu(void)
 	if (ret)
 		ret = check_zero_address();
 	{
-#ifdef CONFIG_INTR_REMAP
 		struct acpi_table_dmar *dmar;
 
 		dmar = (struct acpi_table_dmar *) dmar_tbl;
-		if (ret && cpu_has_x2apic && dmar->flags & 0x1)
+
+		if (ret && intr_remapping_enabled && cpu_has_x2apic &&
+		    dmar->flags & 0x1)
 			printk(KERN_INFO
-			       "Queued invalidation will be enabled to support "
-			       "x2apic and Intr-remapping.\n");
-#endif
-#ifdef CONFIG_DMAR
+			       "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
+
 		if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
 			iommu_detected = 1;
 			/* Make sure ACS will be enabled */
 			pci_request_acs();
 		}
-#endif
+
 #ifdef CONFIG_X86
 		if (ret)
 			x86_init.iommu.iommu_init = intel_iommu_init;
@@ -758,7 +612,6 @@ int alloc_iommu(struct dmar_drhd_unit *d
 		goto err_unmap;
 	}
 
-#ifdef CONFIG_DMAR
 	agaw = iommu_calculate_agaw(iommu);
 	if (agaw < 0) {
 		printk(KERN_ERR
@@ -773,7 +626,6 @@ int alloc_iommu(struct dmar_drhd_unit *d
 			iommu->seq_id);
 		goto err_unmap;
 	}
-#endif
 	iommu->agaw = agaw;
 	iommu->msagaw = msagaw;
 
@@ -800,7 +652,7 @@ int alloc_iommu(struct dmar_drhd_unit *d
 		(unsigned long long)iommu->cap,
 		(unsigned long long)iommu->ecap);
 
-	spin_lock_init(&iommu->register_lock);
+	raw_spin_lock_init(&iommu->register_lock);
 
 	drhd->iommu = iommu;
 	return 0;
@@ -817,9 +669,7 @@ void free_iommu(struct intel_iommu *iomm
 	if (!iommu)
 		return;
 
-#ifdef CONFIG_DMAR
 	free_dmar_iommu(iommu);
-#endif
 
 	if (iommu->reg)
 		iounmap(iommu->reg);
@@ -921,11 +771,11 @@ int qi_submit_sync(struct qi_desc *desc,
 restart:
 	rc = 0;
 
-	spin_lock_irqsave(&qi->q_lock, flags);
+	raw_spin_lock_irqsave(&qi->q_lock, flags);
 	while (qi->free_cnt < 3) {
-		spin_unlock_irqrestore(&qi->q_lock, flags);
+		raw_spin_unlock_irqrestore(&qi->q_lock, flags);
 		cpu_relax();
-		spin_lock_irqsave(&qi->q_lock, flags);
+		raw_spin_lock_irqsave(&qi->q_lock, flags);
 	}
 
 	index = qi->free_head;
@@ -965,15 +815,15 @@ restart:
 		if (rc)
 			break;
 
-		spin_unlock(&qi->q_lock);
+		raw_spin_unlock(&qi->q_lock);
 		cpu_relax();
-		spin_lock(&qi->q_lock);
+		raw_spin_lock(&qi->q_lock);
 	}
 
 	qi->desc_status[index] = QI_DONE;
 
 	reclaim_free_desc(qi);
-	spin_unlock_irqrestore(&qi->q_lock, flags);
+	raw_spin_unlock_irqrestore(&qi->q_lock, flags);
 
 	if (rc == -EAGAIN)
 		goto restart;
@@ -1062,7 +912,7 @@ void dmar_disable_qi(struct intel_iommu
 	if (!ecap_qis(iommu->ecap))
 		return;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
 	if (!(sts & DMA_GSTS_QIES))
@@ -1082,7 +932,7 @@ void dmar_disable_qi(struct intel_iommu
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
 		      !(sts & DMA_GSTS_QIES), sts);
 end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 /*
@@ -1097,7 +947,7 @@ static void __dmar_enable_qi(struct inte
 	qi->free_head = qi->free_tail = 0;
 	qi->free_cnt = QI_LENGTH;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	/* write zero to the tail reg */
 	writel(0, iommu->reg + DMAR_IQT_REG);
@@ -1110,7 +960,7 @@ static void __dmar_enable_qi(struct inte
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 /*
@@ -1159,7 +1009,7 @@ int dmar_enable_qi(struct intel_iommu *i
 	qi->free_head = qi->free_tail = 0;
 	qi->free_cnt = QI_LENGTH;
 
-	spin_lock_init(&qi->q_lock);
+	raw_spin_lock_init(&qi->q_lock);
 
 	__dmar_enable_qi(iommu);
 
@@ -1225,11 +1075,11 @@ void dmar_msi_unmask(struct irq_data *da
 	unsigned long flag;
 
 	/* unmask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(0, iommu->reg + DMAR_FECTL_REG);
 	/* Read a reg to force flush the post write */
 	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_mask(struct irq_data *data)
@@ -1238,11 +1088,11 @@ void dmar_msi_mask(struct irq_data *data
 	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
 
 	/* mask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
 	/* Read a reg to force flush the post write */
 	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_write(int irq, struct msi_msg *msg)
@@ -1250,11 +1100,11 @@ void dmar_msi_write(int irq, struct msi_
 	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
 	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
 	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_read(int irq, struct msi_msg *msg)
@@ -1262,11 +1112,11 @@ void dmar_msi_read(int irq, struct msi_m
 	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
 	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
 	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
@@ -1303,7 +1153,7 @@ irqreturn_t dmar_fault(int irq, void *de
 	u32 fault_status;
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
 	if (fault_status)
 		printk(KERN_ERR "DRHD: handling fault status reg %x\n",
@@ -1342,7 +1192,7 @@ irqreturn_t dmar_fault(int irq, void *de
 		writel(DMA_FRCD_F, iommu->reg + reg +
 			fault_index * PRIMARY_FAULT_REG_LEN + 12);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 
 		dmar_fault_do_one(iommu, type, fault_reason,
 				source_id, guest_addr);
@@ -1350,14 +1200,14 @@ irqreturn_t dmar_fault(int irq, void *de
 		fault_index++;
 		if (fault_index >= cap_num_fault_regs(iommu->cap))
 			fault_index = 0;
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	}
 clear_rest:
 	/* clear all the other faults */
 	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
 	writel(fault_status, iommu->reg + DMAR_FSTS_REG);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	return IRQ_HANDLED;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/intel-iommu.c linux-libre-3.2-gnu1/drivers/iommu/intel-iommu.c
--- linux-libre-3.1-gnu1/drivers/iommu/intel-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/intel-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/bitmap.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -398,11 +399,14 @@ static long list_size;
 
 static void domain_remove_dev_info(struct dmar_domain *domain);
 
-#ifdef CONFIG_DMAR_DEFAULT_ON
+#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
 #else
 int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
+#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
+
+int intel_iommu_enabled = 0;
+EXPORT_SYMBOL_GPL(intel_iommu_enabled);
 
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
@@ -939,7 +943,7 @@ static void iommu_set_root_entry(struct
 
 	addr = iommu->root_entry;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
 
 	writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
@@ -948,7 +952,7 @@ static void iommu_set_root_entry(struct
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_RTPS), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 static void iommu_flush_write_buffer(struct intel_iommu *iommu)
@@ -959,14 +963,14 @@ static void iommu_flush_write_buffer(str
 	if (!rwbf_quirk && !cap_rwbf(iommu->cap))
 		return;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
 
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (!(val & DMA_GSTS_WBFS)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 /* return value determine if we need a write buffer flush */
@@ -993,14 +997,14 @@ static void __iommu_flush_context(struct
 	}
 	val |= DMA_CCMD_ICC;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
 
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
 		dmar_readq, (!(val & DMA_CCMD_ICC)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 /* return value determine if we need a write buffer flush */
@@ -1039,7 +1043,7 @@ static void __iommu_flush_iotlb(struct i
 	if (cap_write_drain(iommu->cap))
 		val |= DMA_TLB_WRITE_DRAIN;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	/* Note: Only uses first TLB reg currently */
 	if (val_iva)
 		dmar_writeq(iommu->reg + tlb_offset, val_iva);
@@ -1049,7 +1053,7 @@ static void __iommu_flush_iotlb(struct i
 	IOMMU_WAIT_OP(iommu, tlb_offset + 8,
 		dmar_readq, (!(val & DMA_TLB_IVT)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 
 	/* check IOTLB invalidation granularity */
 	if (DMA_TLB_IAIG(val) == 0)
@@ -1165,7 +1169,7 @@ static void iommu_disable_protect_mem_re
 	u32 pmen;
 	unsigned long flags;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 	pmen = readl(iommu->reg + DMAR_PMEN_REG);
 	pmen &= ~DMA_PMEN_EPM;
 	writel(pmen, iommu->reg + DMAR_PMEN_REG);
@@ -1174,7 +1178,7 @@ static void iommu_disable_protect_mem_re
 	IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
 		readl, !(pmen & DMA_PMEN_PRS), pmen);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 static int iommu_enable_translation(struct intel_iommu *iommu)
@@ -1182,7 +1186,7 @@ static int iommu_enable_translation(stru
 	u32 sts;
 	unsigned long flags;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 	iommu->gcmd |= DMA_GCMD_TE;
 	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 
@@ -1190,7 +1194,7 @@ static int iommu_enable_translation(stru
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_TES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 	return 0;
 }
 
@@ -1199,7 +1203,7 @@ static int iommu_disable_translation(str
 	u32 sts;
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	iommu->gcmd &= ~DMA_GCMD_TE;
 	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 
@@ -1207,7 +1211,7 @@ static int iommu_disable_translation(str
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (!(sts & DMA_GSTS_TES)), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	return 0;
 }
 
@@ -2157,7 +2161,7 @@ static inline int iommu_prepare_rmrr_dev
 		rmrr->end_address);
 }
 
-#ifdef CONFIG_DMAR_FLOPPY_WA
+#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
 static inline void iommu_prepare_isa(void)
 {
 	struct pci_dev *pdev;
@@ -2180,7 +2184,7 @@ static inline void iommu_prepare_isa(voi
 {
 	return;
 }
-#endif /* !CONFIG_DMAR_FLPY_WA */
+#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
 
@@ -2491,7 +2495,7 @@ static int __init init_dmars(void)
 	if (iommu_pass_through)
 		iommu_identity_mapping |= IDENTMAP_ALL;
 
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
 	iommu_identity_mapping |= IDENTMAP_GFX;
 #endif
 
@@ -3329,7 +3333,7 @@ static int iommu_suspend(void)
 	for_each_active_iommu(iommu, drhd) {
 		iommu_disable_translation(iommu);
 
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 
 		iommu->iommu_state[SR_DMAR_FECTL_REG] =
 			readl(iommu->reg + DMAR_FECTL_REG);
@@ -3340,7 +3344,7 @@ static int iommu_suspend(void)
 		iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
 			readl(iommu->reg + DMAR_FEUADDR_REG);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	}
 	return 0;
 
@@ -3367,7 +3371,7 @@ static void iommu_resume(void)
 
 	for_each_active_iommu(iommu, drhd) {
 
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 
 		writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
 			iommu->reg + DMAR_FECTL_REG);
@@ -3378,7 +3382,7 @@ static void iommu_resume(void)
 		writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
 			iommu->reg + DMAR_FEUADDR_REG);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	}
 
 	for_each_active_iommu(iommu, drhd)
@@ -3399,6 +3403,151 @@ static void __init init_iommu_pm_ops(voi
 static inline void init_iommu_pm_ops(void) {}
 #endif	/* CONFIG_PM */
 
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+	list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
+int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	struct dmar_rmrr_unit *rmrru;
+
+	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+	if (!rmrru)
+		return -ENOMEM;
+
+	rmrru->hdr = header;
+	rmrr = (struct acpi_dmar_reserved_memory *)header;
+	rmrru->base_address = rmrr->base_address;
+	rmrru->end_address = rmrr->end_address;
+
+	dmar_register_rmrr_unit(rmrru);
+	return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	int ret;
+
+	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
+	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+		((void *)rmrr) + rmrr->header.length,
+		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+	if (ret || (rmrru->devices_cnt == 0)) {
+		list_del(&rmrru->list);
+		kfree(rmrru);
+	}
+	return ret;
+}
+
+static LIST_HEAD(dmar_atsr_units);
+
+int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
+{
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
+	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
+	if (!atsru)
+		return -ENOMEM;
+
+	atsru->hdr = hdr;
+	atsru->include_all = atsr->flags & 0x1;
+
+	list_add(&atsru->list, &dmar_atsr_units);
+
+	return 0;
+}
+
+static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
+{
+	int rc;
+	struct acpi_dmar_atsr *atsr;
+
+	if (atsru->include_all)
+		return 0;
+
+	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+	rc = dmar_parse_dev_scope((void *)(atsr + 1),
+				(void *)atsr + atsr->header.length,
+				&atsru->devices_cnt, &atsru->devices,
+				atsr->segment);
+	if (rc || !atsru->devices_cnt) {
+		list_del(&atsru->list);
+		kfree(atsru);
+	}
+
+	return rc;
+}
+
+int dmar_find_matched_atsr_unit(struct pci_dev *dev)
+{
+	int i;
+	struct pci_bus *bus;
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	dev = pci_physfn(dev);
+
+	list_for_each_entry(atsru, &dmar_atsr_units, list) {
+		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+		if (atsr->segment == pci_domain_nr(dev->bus))
+			goto found;
+	}
+
+	return 0;
+
+found:
+	for (bus = dev->bus; bus; bus = bus->parent) {
+		struct pci_dev *bridge = bus->self;
+
+		if (!bridge || !pci_is_pcie(bridge) ||
+		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+			return 0;
+
+		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+			for (i = 0; i < atsru->devices_cnt; i++)
+				if (atsru->devices[i] == bridge)
+					return 1;
+			break;
+		}
+	}
+
+	if (atsru->include_all)
+		return 1;
+
+	return 0;
+}
+
+int __init dmar_parse_rmrr_atsr_dev(void)
+{
+	struct dmar_rmrr_unit *rmrr, *rmrr_n;
+	struct dmar_atsr_unit *atsr, *atsr_n;
+	int ret = 0;
+
+	list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
+		ret = rmrr_parse_dev(rmrr);
+		if (ret)
+			return ret;
+	}
+
+	list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
+		ret = atsr_parse_dev(atsr);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
 /*
  * Here we only respond to action of unbound device from driver.
  *
@@ -3448,16 +3597,12 @@ int __init intel_iommu_init(void)
 		return 	-ENODEV;
 	}
 
-	if (dmar_dev_scope_init()) {
+	if (dmar_dev_scope_init() < 0) {
 		if (force_on)
 			panic("tboot: Failed to initialize DMAR device scope\n");
 		return 	-ENODEV;
 	}
 
-	/*
-	 * Check the need for DMA-remapping initialization now.
-	 * Above initialization will also be used by Interrupt-remapping.
-	 */
 	if (no_iommu || dmar_disabled)
 		return -ENODEV;
 
@@ -3467,6 +3612,12 @@ int __init intel_iommu_init(void)
 		return 	-ENODEV;
 	}
 
+	if (list_empty(&dmar_rmrr_units))
+		printk(KERN_INFO "DMAR: No RMRR found\n");
+
+	if (list_empty(&dmar_atsr_units))
+		printk(KERN_INFO "DMAR: No ATSR found\n");
+
 	if (dmar_init_reserved_ranges()) {
 		if (force_on)
 			panic("tboot: Failed to reserve iommu ranges\n");
@@ -3495,10 +3646,12 @@ int __init intel_iommu_init(void)
 
 	init_iommu_pm_ops();
 
-	register_iommu(&intel_iommu_ops);
+	bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
 
 	bus_register_notifier(&pci_bus_type, &device_nb);
 
+	intel_iommu_enabled = 1;
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/intr_remapping.c linux-libre-3.2-gnu1/drivers/iommu/intr_remapping.c
--- linux-libre-3.1-gnu1/drivers/iommu/intr_remapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/intr_remapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@ int intr_remapping_enabled;
 
 static int disable_intremap;
 static int disable_sourceid_checking;
+static int no_x2apic_optout;
 
 static __init int setup_nointremap(char *str)
 {
@@ -34,18 +35,26 @@ static __init int setup_intremap(char *s
 	if (!str)
 		return -EINVAL;
 
-	if (!strncmp(str, "on", 2))
-		disable_intremap = 0;
-	else if (!strncmp(str, "off", 3))
-		disable_intremap = 1;
-	else if (!strncmp(str, "nosid", 5))
-		disable_sourceid_checking = 1;
+	while (*str) {
+		if (!strncmp(str, "on", 2))
+			disable_intremap = 0;
+		else if (!strncmp(str, "off", 3))
+			disable_intremap = 1;
+		else if (!strncmp(str, "nosid", 5))
+			disable_sourceid_checking = 1;
+		else if (!strncmp(str, "no_x2apic_optout", 16))
+			no_x2apic_optout = 1;
+
+		str += strcspn(str, ",");
+		while (*str == ',')
+			str++;
+	}
 
 	return 0;
 }
 early_param("intremap", setup_intremap);
 
-static DEFINE_SPINLOCK(irq_2_ir_lock);
+static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
 
 static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
@@ -62,12 +71,12 @@ int get_irte(int irq, struct irte *entry
 	if (!entry || !irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	*entry = *(irq_iommu->iommu->ir_table->base + index);
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return 0;
 }
 
@@ -101,7 +110,7 @@ int alloc_irte(struct intel_iommu *iommu
 		return -1;
 	}
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 	do {
 		for (i = index; i < index + count; i++)
 			if  (table->base[i].present)
@@ -113,7 +122,7 @@ int alloc_irte(struct intel_iommu *iommu
 		index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
 
 		if (index == start_index) {
-			spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+			raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 			printk(KERN_ERR "can't allocate an IRTE\n");
 			return -1;
 		}
@@ -127,7 +136,7 @@ int alloc_irte(struct intel_iommu *iommu
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = mask;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return index;
 }
@@ -152,10 +161,10 @@ int map_irq_to_irte_handle(int irq, u16
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 	*sub_handle = irq_iommu->sub_handle;
 	index = irq_iommu->irte_index;
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return index;
 }
 
@@ -167,14 +176,14 @@ int set_irte_irq(int irq, struct intel_i
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	irq_iommu->iommu = iommu;
 	irq_iommu->irte_index = index;
 	irq_iommu->sub_handle = subhandle;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return 0;
 }
@@ -190,7 +199,7 @@ int modify_irte(int irq, struct irte *ir
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	iommu = irq_iommu->iommu;
 
@@ -202,7 +211,7 @@ int modify_irte(int irq, struct irte *ir
 	__iommu_flush_cache(iommu, irte, sizeof(*irte));
 
 	rc = qi_flush_iec(iommu, index, 0);
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -270,7 +279,7 @@ int free_irte(int irq)
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	rc = clear_entries(irq_iommu);
 
@@ -279,7 +288,7 @@ int free_irte(int irq)
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -409,7 +418,7 @@ static void iommu_set_intr_remapping(str
 
 	addr = virt_to_phys((void *)iommu->ir_table->base);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	dmar_writeq(iommu->reg + DMAR_IRTA_REG,
 		    (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
@@ -420,7 +429,7 @@ static void iommu_set_intr_remapping(str
 
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_IRTPS), sts);
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 
 	/*
 	 * global invalidation of interrupt entry cache before enabling
@@ -428,7 +437,7 @@ static void iommu_set_intr_remapping(str
 	 */
 	qi_global_iec(iommu);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	/* Enable interrupt-remapping */
 	iommu->gcmd |= DMA_GCMD_IRE;
@@ -437,7 +446,7 @@ static void iommu_set_intr_remapping(str
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_IRES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 
@@ -485,7 +494,7 @@ static void iommu_disable_intr_remapping
 	 */
 	qi_global_iec(iommu);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
 	if (!(sts & DMA_GSTS_IRES))
@@ -498,7 +507,16 @@ static void iommu_disable_intr_remapping
 		      readl, !(sts & DMA_GSTS_IRES), sts);
 
 end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+static int __init dmar_x2apic_optout(void)
+{
+	struct acpi_table_dmar *dmar;
+	dmar = (struct acpi_table_dmar *)dmar_tbl;
+	if (!dmar || no_x2apic_optout)
+		return 0;
+	return dmar->flags & DMAR_X2APIC_OPT_OUT;
 }
 
 int __init intr_remapping_supported(void)
@@ -521,16 +539,25 @@ int __init intr_remapping_supported(void
 	return 1;
 }
 
-int __init enable_intr_remapping(int eim)
+int __init enable_intr_remapping(void)
 {
 	struct dmar_drhd_unit *drhd;
 	int setup = 0;
+	int eim = 0;
 
 	if (parse_ioapics_under_ir() != 1) {
 		printk(KERN_INFO "Not enable interrupt remapping\n");
 		return -1;
 	}
 
+	if (x2apic_supported()) {
+		eim = !dmar_x2apic_optout();
+		WARN(!eim, KERN_WARNING
+			   "Your BIOS is broken and requested that x2apic be disabled\n"
+			   "This will leave your machine vulnerable to irq-injection attacks\n"
+			   "Use 'intremap=no_x2apic_optout' to override BIOS request\n");
+	}
+
 	for_each_drhd_unit(drhd) {
 		struct intel_iommu *iommu = drhd->iommu;
 
@@ -606,8 +633,9 @@ int __init enable_intr_remapping(int eim
 		goto error;
 
 	intr_remapping_enabled = 1;
+	pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
 
-	return 0;
+	return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
 
 error:
 	/*
@@ -745,6 +773,15 @@ int __init parse_ioapics_under_ir(void)
 	return ir_supported;
 }
 
+int __init ir_dev_scope_init(void)
+{
+	if (!intr_remapping_enabled)
+		return 0;
+
+	return dmar_dev_scope_init();
+}
+rootfs_initcall(ir_dev_scope_init);
+
 void disable_intr_remapping(void)
 {
 	struct dmar_drhd_unit *drhd;
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/iommu.c linux-libre-3.2-gnu1/drivers/iommu/iommu.c
--- linux-libre-3.1-gnu1/drivers/iommu/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/device.h>
+#include <linux/kernel.h>
 #include <linux/bug.h>
 #include <linux/types.h>
 #include <linux/module.h>
@@ -23,32 +25,78 @@
 #include <linux/errno.h>
 #include <linux/iommu.h>
 
-static struct iommu_ops *iommu_ops;
+static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
+{
+}
 
-void register_iommu(struct iommu_ops *ops)
+/**
+ * bus_set_iommu - set iommu-callbacks for the bus
+ * @bus: bus.
+ * @ops: the callbacks provided by the iommu-driver
+ *
+ * This function is called by an iommu driver to set the iommu methods
+ * used for a particular bus. Drivers for devices on that bus can use
+ * the iommu-api after these ops are registered.
+ * This special function is needed because IOMMUs are usually devices on
+ * the bus itself, so the iommu drivers are not initialized when the bus
+ * is set up. With this function the iommu-driver can set the iommu-ops
+ * afterwards.
+ */
+int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
 {
-	if (iommu_ops)
-		BUG();
+	if (bus->iommu_ops != NULL)
+		return -EBUSY;
 
-	iommu_ops = ops;
+	bus->iommu_ops = ops;
+
+	/* Do IOMMU specific setup for this bus-type */
+	iommu_bus_init(bus, ops);
+
+	return 0;
 }
+EXPORT_SYMBOL_GPL(bus_set_iommu);
 
-bool iommu_found(void)
+bool iommu_present(struct bus_type *bus)
 {
-	return iommu_ops != NULL;
+	return bus->iommu_ops != NULL;
 }
-EXPORT_SYMBOL_GPL(iommu_found);
+EXPORT_SYMBOL_GPL(iommu_present);
 
-struct iommu_domain *iommu_domain_alloc(void)
+/**
+ * iommu_set_fault_handler() - set a fault handler for an iommu domain
+ * @domain: iommu domain
+ * @handler: fault handler
+ *
+ * This function should be used by IOMMU users which want to be notified
+ * whenever an IOMMU fault happens.
+ *
+ * The fault handler itself should return 0 on success, and an appropriate
+ * error code otherwise.
+ */
+void iommu_set_fault_handler(struct iommu_domain *domain,
+					iommu_fault_handler_t handler)
+{
+	BUG_ON(!domain);
+
+	domain->handler = handler;
+}
+EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+
+struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
 {
 	struct iommu_domain *domain;
 	int ret;
 
-	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+	if (bus == NULL || bus->iommu_ops == NULL)
+		return NULL;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
 	if (!domain)
 		return NULL;
 
-	ret = iommu_ops->domain_init(domain);
+	domain->ops = bus->iommu_ops;
+
+	ret = domain->ops->domain_init(domain);
 	if (ret)
 		goto out_free;
 
@@ -63,62 +111,78 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);
 
 void iommu_domain_free(struct iommu_domain *domain)
 {
-	iommu_ops->domain_destroy(domain);
+	if (likely(domain->ops->domain_destroy != NULL))
+		domain->ops->domain_destroy(domain);
+
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(iommu_domain_free);
 
 int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
 {
-	return iommu_ops->attach_dev(domain, dev);
+	if (unlikely(domain->ops->attach_dev == NULL))
+		return -ENODEV;
+
+	return domain->ops->attach_dev(domain, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device);
 
 void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
 {
-	iommu_ops->detach_dev(domain, dev);
+	if (unlikely(domain->ops->detach_dev == NULL))
+		return;
+
+	domain->ops->detach_dev(domain, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_detach_device);
 
 phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
 			       unsigned long iova)
 {
-	return iommu_ops->iova_to_phys(domain, iova);
+	if (unlikely(domain->ops->iova_to_phys == NULL))
+		return 0;
+
+	return domain->ops->iova_to_phys(domain, iova);
 }
 EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
 
 int iommu_domain_has_cap(struct iommu_domain *domain,
 			 unsigned long cap)
 {
-	return iommu_ops->domain_has_cap(domain, cap);
+	if (unlikely(domain->ops->domain_has_cap == NULL))
+		return 0;
+
+	return domain->ops->domain_has_cap(domain, cap);
 }
 EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
 
 int iommu_map(struct iommu_domain *domain, unsigned long iova,
 	      phys_addr_t paddr, int gfp_order, int prot)
 {
-	unsigned long invalid_mask;
 	size_t size;
 
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
+	if (unlikely(domain->ops->map == NULL))
+		return -ENODEV;
 
-	BUG_ON((iova | paddr) & invalid_mask);
+	size         = PAGE_SIZE << gfp_order;
 
-	return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
+	BUG_ON(!IS_ALIGNED(iova | paddr, size));
+
+	return domain->ops->map(domain, iova, paddr, gfp_order, prot);
 }
 EXPORT_SYMBOL_GPL(iommu_map);
 
 int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
 {
-	unsigned long invalid_mask;
 	size_t size;
 
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
+	if (unlikely(domain->ops->unmap == NULL))
+		return -ENODEV;
 
-	BUG_ON(iova & invalid_mask);
+	size         = PAGE_SIZE << gfp_order;
 
-	return iommu_ops->unmap(domain, iova, gfp_order);
+	BUG_ON(!IS_ALIGNED(iova, size));
+
+	return domain->ops->unmap(domain, iova, gfp_order);
 }
 EXPORT_SYMBOL_GPL(iommu_unmap);
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/Kconfig linux-libre-3.2-gnu1/drivers/iommu/Kconfig
--- linux-libre-3.1-gnu1/drivers/iommu/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -59,10 +59,14 @@ config AMD_IOMMU_STATS
 	  If unsure, say N.
 
 # Intel IOMMU support
-config DMAR
-	bool "Support for DMA Remapping Devices"
+config DMAR_TABLE
+	bool
+
+config INTEL_IOMMU
+	bool "Support for Intel IOMMU using DMA Remapping Devices"
 	depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
 	select IOMMU_API
+	select DMAR_TABLE
 	help
 	  DMA remapping (DMAR) devices support enables independent address
 	  translations for Direct Memory Access (DMA) from devices.
@@ -70,18 +74,18 @@ config DMAR
 	  and include PCI device scope covered by these DMA
 	  remapping devices.
 
-config DMAR_DEFAULT_ON
+config INTEL_IOMMU_DEFAULT_ON
 	def_bool y
-	prompt "Enable DMA Remapping Devices by default"
-	depends on DMAR
+	prompt "Enable Intel DMA Remapping Devices by default"
+	depends on INTEL_IOMMU
 	help
 	  Selecting this option will enable a DMAR device at boot time if
 	  one is found. If this option is not selected, DMAR support can
 	  be enabled by passing intel_iommu=on to the kernel.
 
-config DMAR_BROKEN_GFX_WA
+config INTEL_IOMMU_BROKEN_GFX_WA
 	bool "Workaround broken graphics drivers (going away soon)"
-	depends on DMAR && BROKEN && X86
+	depends on INTEL_IOMMU && BROKEN && X86
 	---help---
 	  Current Graphics drivers tend to use physical address
 	  for DMA and avoid using DMA APIs. Setting this config
@@ -90,21 +94,41 @@ config DMAR_BROKEN_GFX_WA
 	  to use physical addresses for DMA, at least until this
 	  option is removed in the 2.6.32 kernel.
 
-config DMAR_FLOPPY_WA
+config INTEL_IOMMU_FLOPPY_WA
 	def_bool y
-	depends on DMAR && X86
+	depends on INTEL_IOMMU && X86
 	---help---
 	  Floppy disk drivers are known to bypass DMA API calls
 	  thereby failing to work when IOMMU is enabled. This
 	  workaround will setup a 1:1 mapping for the first
 	  16MiB to make floppy (an ISA device) work.
 
-config INTR_REMAP
+config IRQ_REMAP
 	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
 	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+	select DMAR_TABLE
 	---help---
 	  Supports Interrupt remapping for IO-APIC and MSI devices.
 	  To use x2apic mode in the CPU's which support x2APIC enhancements or
 	  to support platforms with CPU's having > 8 bit APIC ID, say Y.
 
+# OMAP IOMMU support
+config OMAP_IOMMU
+	bool "OMAP IOMMU Support"
+	depends on ARCH_OMAP
+	select IOMMU_API
+
+config OMAP_IOVMM
+	tristate "OMAP IO Virtual Memory Manager Support"
+	depends on OMAP_IOMMU
+
+config OMAP_IOMMU_DEBUG
+       tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
+       depends on OMAP_IOVMM && DEBUG_FS
+       help
+         Select this to see extensive information about
+         the internal state of OMAP IOMMU/IOVMM in debugfs.
+
+         Say N unless you know you need this.
+
 endif # IOMMU_SUPPORT
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/Makefile linux-libre-3.2-gnu1/drivers/iommu/Makefile
--- linux-libre-3.1-gnu1/drivers/iommu/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,9 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+obj-$(CONFIG_DMAR_TABLE) += dmar.o
+obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
+obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
+obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
+obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/msm_iommu.c linux-libre-3.2-gnu1/drivers/iommu/msm_iommu.c
--- linux-libre-3.1-gnu1/drivers/iommu/msm_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/iommu/msm_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -543,6 +543,13 @@ static int msm_iommu_unmap(struct iommu_
 	}
 
 	ret = __flush_iotlb(domain);
+
+	/*
+	 * the IOMMU API requires us to return the order of the unmapped
+	 * page (on success).
+	 */
+	if (!ret)
+		ret = order;
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -721,7 +728,7 @@ static void __init setup_iommu_tex_class
 static int __init msm_iommu_init(void)
 {
 	setup_iommu_tex_classes();
-	register_iommu(&msm_iommu_ops);
+	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/omap-iommu.c linux-libre-3.2-gnu1/drivers/iommu/omap-iommu.c
--- linux-libre-3.1-gnu1/drivers/iommu/omap-iommu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/iommu/omap-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1245 @@
+/*
+ * omap iommu: tlb and pagetable primitives
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
+ *		Paul Mundt and Toshihiro Kobayashi
+ *
+ * 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/err.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/iommu.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+
+#include <plat/iommu.h>
+
+#include <plat/iopgtable.h>
+
+#define for_each_iotlb_cr(obj, n, __i, cr)				\
+	for (__i = 0;							\
+	     (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true);	\
+	     __i++)
+
+/**
+ * struct omap_iommu_domain - omap iommu domain
+ * @pgtable:	the page table
+ * @iommu_dev:	an omap iommu device attached to this domain. only a single
+ *		iommu device can be attached for now.
+ * @lock:	domain lock, should be taken when attaching/detaching
+ */
+struct omap_iommu_domain {
+	u32 *pgtable;
+	struct omap_iommu *iommu_dev;
+	spinlock_t lock;
+};
+
+/* accommodate the difference between omap1 and omap2/3 */
+static const struct iommu_functions *arch_iommu;
+
+static struct platform_driver omap_iommu_driver;
+static struct kmem_cache *iopte_cachep;
+
+/**
+ * omap_install_iommu_arch - Install archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * There are several kind of iommu algorithm(tlb, pagetable) among
+ * omap series. This interface installs such an iommu algorighm.
+ **/
+int omap_install_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu)
+		return -EBUSY;
+
+	arch_iommu = ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
+
+/**
+ * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * This interface uninstalls the iommu algorighm installed previously.
+ **/
+void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu != ops)
+		pr_err("%s: not your arch\n", __func__);
+
+	arch_iommu = NULL;
+}
+EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
+
+/**
+ * omap_iommu_save_ctx - Save registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void omap_iommu_save_ctx(struct omap_iommu *obj)
+{
+	arch_iommu->save_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
+
+/**
+ * omap_iommu_restore_ctx - Restore registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void omap_iommu_restore_ctx(struct omap_iommu *obj)
+{
+	arch_iommu->restore_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
+
+/**
+ * omap_iommu_arch_version - Return running iommu arch version
+ **/
+u32 omap_iommu_arch_version(void)
+{
+	return arch_iommu->version;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
+
+static int iommu_enable(struct omap_iommu *obj)
+{
+	int err;
+
+	if (!obj)
+		return -EINVAL;
+
+	if (!arch_iommu)
+		return -ENODEV;
+
+	clk_enable(obj->clk);
+
+	err = arch_iommu->enable(obj);
+
+	clk_disable(obj->clk);
+	return err;
+}
+
+static void iommu_disable(struct omap_iommu *obj)
+{
+	if (!obj)
+		return;
+
+	clk_enable(obj->clk);
+
+	arch_iommu->disable(obj);
+
+	clk_disable(obj->clk);
+}
+
+/*
+ *	TLB operations
+ */
+void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+{
+	BUG_ON(!cr || !e);
+
+	arch_iommu->cr_to_e(cr, e);
+}
+EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
+
+static inline int iotlb_cr_valid(struct cr_regs *cr)
+{
+	if (!cr)
+		return -EINVAL;
+
+	return arch_iommu->cr_valid(cr);
+}
+
+static inline struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
+					     struct iotlb_entry *e)
+{
+	if (!e)
+		return NULL;
+
+	return arch_iommu->alloc_cr(obj, e);
+}
+
+static u32 iotlb_cr_to_virt(struct cr_regs *cr)
+{
+	return arch_iommu->cr_to_virt(cr);
+}
+
+static u32 get_iopte_attr(struct iotlb_entry *e)
+{
+	return arch_iommu->get_pte_attr(e);
+}
+
+static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da)
+{
+	return arch_iommu->fault_isr(obj, da);
+}
+
+static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	val = iommu_read_reg(obj, MMU_LOCK);
+
+	l->base = MMU_LOCK_BASE(val);
+	l->vict = MMU_LOCK_VICT(val);
+
+}
+
+static void iotlb_lock_set(struct omap_iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	val = (l->base << MMU_LOCK_BASE_SHIFT);
+	val |= (l->vict << MMU_LOCK_VICT_SHIFT);
+
+	iommu_write_reg(obj, val, MMU_LOCK);
+}
+
+static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_read_cr(obj, cr);
+}
+
+static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_load_cr(obj, cr);
+
+	iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+	iommu_write_reg(obj, 1, MMU_LD_TLB);
+}
+
+/**
+ * iotlb_dump_cr - Dump an iommu tlb entry into buf
+ * @obj:	target iommu
+ * @cr:		contents of cam and ram register
+ * @buf:	output buffer
+ **/
+static inline ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
+				    char *buf)
+{
+	BUG_ON(!cr || !buf);
+
+	return arch_iommu->dump_cr(obj, cr, buf);
+}
+
+/* only used in iotlb iteration for-loop */
+static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
+{
+	struct cr_regs cr;
+	struct iotlb_lock l;
+
+	iotlb_lock_get(obj, &l);
+	l.vict = n;
+	iotlb_lock_set(obj, &l);
+	iotlb_read_cr(obj, &cr);
+
+	return cr;
+}
+
+/**
+ * load_iotlb_entry - Set an iommu tlb entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+#ifdef PREFETCH_IOTLB
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int err = 0;
+	struct iotlb_lock l;
+	struct cr_regs *cr;
+
+	if (!obj || !obj->nr_tlb_entries || !e)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	iotlb_lock_get(obj, &l);
+	if (l.base == obj->nr_tlb_entries) {
+		dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
+		err = -EBUSY;
+		goto out;
+	}
+	if (!e->prsvd) {
+		int i;
+		struct cr_regs tmp;
+
+		for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
+			if (!iotlb_cr_valid(&tmp))
+				break;
+
+		if (i == obj->nr_tlb_entries) {
+			dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
+			err = -EBUSY;
+			goto out;
+		}
+
+		iotlb_lock_get(obj, &l);
+	} else {
+		l.vict = l.base;
+		iotlb_lock_set(obj, &l);
+	}
+
+	cr = iotlb_alloc_cr(obj, e);
+	if (IS_ERR(cr)) {
+		clk_disable(obj->clk);
+		return PTR_ERR(cr);
+	}
+
+	iotlb_load_cr(obj, cr);
+	kfree(cr);
+
+	if (e->prsvd)
+		l.base++;
+	/* increment victim for next tlb load */
+	if (++l.vict == obj->nr_tlb_entries)
+		l.vict = l.base;
+	iotlb_lock_set(obj, &l);
+out:
+	clk_disable(obj->clk);
+	return err;
+}
+
+#else /* !PREFETCH_IOTLB */
+
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	return 0;
+}
+
+#endif /* !PREFETCH_IOTLB */
+
+static int prefetch_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	return load_iotlb_entry(obj, e);
+}
+
+/**
+ * flush_iotlb_page - Clear an iommu tlb entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ *
+ * Clear an iommu tlb entry which includes 'da' address.
+ **/
+static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
+{
+	int i;
+	struct cr_regs cr;
+
+	clk_enable(obj->clk);
+
+	for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
+		u32 start;
+		size_t bytes;
+
+		if (!iotlb_cr_valid(&cr))
+			continue;
+
+		start = iotlb_cr_to_virt(&cr);
+		bytes = iopgsz_to_bytes(cr.cam & 3);
+
+		if ((start <= da) && (da < start + bytes)) {
+			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
+				__func__, start, da, bytes);
+			iotlb_load_cr(obj, &cr);
+			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+		}
+	}
+	clk_disable(obj->clk);
+
+	if (i == obj->nr_tlb_entries)
+		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
+}
+
+/**
+ * flush_iotlb_all - Clear all iommu tlb entries
+ * @obj:	target iommu
+ **/
+static void flush_iotlb_all(struct omap_iommu *obj)
+{
+	struct iotlb_lock l;
+
+	clk_enable(obj->clk);
+
+	l.base = 0;
+	l.vict = 0;
+	iotlb_lock_set(obj, &l);
+
+	iommu_write_reg(obj, 1, MMU_GFLUSH);
+
+	clk_disable(obj->clk);
+}
+
+#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
+
+ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
+{
+	if (!obj || !buf)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	bytes = arch_iommu->dump_ctx(obj, buf, bytes);
+
+	clk_disable(obj->clk);
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_dump_ctx);
+
+static int
+__dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
+{
+	int i;
+	struct iotlb_lock saved;
+	struct cr_regs tmp;
+	struct cr_regs *p = crs;
+
+	clk_enable(obj->clk);
+	iotlb_lock_get(obj, &saved);
+
+	for_each_iotlb_cr(obj, num, i, tmp) {
+		if (!iotlb_cr_valid(&tmp))
+			continue;
+		*p++ = tmp;
+	}
+
+	iotlb_lock_set(obj, &saved);
+	clk_disable(obj->clk);
+
+	return  p - crs;
+}
+
+/**
+ * omap_dump_tlb_entries - dump cr arrays to given buffer
+ * @obj:	target iommu
+ * @buf:	output buffer
+ **/
+size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t bytes)
+{
+	int i, num;
+	struct cr_regs *cr;
+	char *p = buf;
+
+	num = bytes / sizeof(*cr);
+	num = min(obj->nr_tlb_entries, num);
+
+	cr = kcalloc(num, sizeof(*cr), GFP_KERNEL);
+	if (!cr)
+		return 0;
+
+	num = __dump_tlb_entries(obj, cr, num);
+	for (i = 0; i < num; i++)
+		p += iotlb_dump_cr(obj, cr + i, p);
+	kfree(cr);
+
+	return p - buf;
+}
+EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
+
+int omap_foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
+{
+	return driver_for_each_device(&omap_iommu_driver.driver,
+				      NULL, data, fn);
+}
+EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
+
+#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
+
+/*
+ *	H/W pagetable operations
+ */
+static void flush_iopgd_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void flush_iopte_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void iopte_free(u32 *iopte)
+{
+	/* Note: freed iopte's must be clean ready for re-use */
+	kmem_cache_free(iopte_cachep, iopte);
+}
+
+static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
+{
+	u32 *iopte;
+
+	/* a table has already existed */
+	if (*iopgd)
+		goto pte_ready;
+
+	/*
+	 * do the allocation outside the page table lock
+	 */
+	spin_unlock(&obj->page_table_lock);
+	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
+	spin_lock(&obj->page_table_lock);
+
+	if (!*iopgd) {
+		if (!iopte)
+			return ERR_PTR(-ENOMEM);
+
+		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
+		flush_iopgd_range(iopgd, iopgd);
+
+		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
+	} else {
+		/* We raced, free the reduniovant table */
+		iopte_free(iopte);
+	}
+
+pte_ready:
+	iopte = iopte_offset(iopgd, da);
+
+	dev_vdbg(obj->dev,
+		 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
+		 __func__, da, iopgd, *iopgd, iopte, *iopte);
+
+	return iopte;
+}
+
+static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+
+	if ((da | pa) & ~IOSECTION_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOSECTION_SIZE);
+		return -EINVAL;
+	}
+
+	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
+	flush_iopgd_range(iopgd, iopgd);
+	return 0;
+}
+
+static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	int i;
+
+	if ((da | pa) & ~IOSUPER_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOSUPER_SIZE);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 16; i++)
+		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
+	flush_iopgd_range(iopgd, iopgd + 15);
+	return 0;
+}
+
+static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
+	flush_iopte_range(iopte, iopte);
+
+	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
+		 __func__, da, pa, iopte, *iopte);
+
+	return 0;
+}
+
+static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+	int i;
+
+	if ((da | pa) & ~IOLARGE_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOLARGE_SIZE);
+		return -EINVAL;
+	}
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	for (i = 0; i < 16; i++)
+		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
+	flush_iopte_range(iopte, iopte + 15);
+	return 0;
+}
+
+static int
+iopgtable_store_entry_core(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int (*fn)(struct omap_iommu *, u32, u32, u32);
+	u32 prot;
+	int err;
+
+	if (!obj || !e)
+		return -EINVAL;
+
+	switch (e->pgsz) {
+	case MMU_CAM_PGSZ_16M:
+		fn = iopgd_alloc_super;
+		break;
+	case MMU_CAM_PGSZ_1M:
+		fn = iopgd_alloc_section;
+		break;
+	case MMU_CAM_PGSZ_64K:
+		fn = iopte_alloc_large;
+		break;
+	case MMU_CAM_PGSZ_4K:
+		fn = iopte_alloc_page;
+		break;
+	default:
+		fn = NULL;
+		BUG();
+		break;
+	}
+
+	prot = get_iopte_attr(e);
+
+	spin_lock(&obj->page_table_lock);
+	err = fn(obj, e->da, e->pa, prot);
+	spin_unlock(&obj->page_table_lock);
+
+	return err;
+}
+
+/**
+ * omap_iopgtable_store_entry - Make an iommu pte entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+int omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int err;
+
+	flush_iotlb_page(obj, e->da);
+	err = iopgtable_store_entry_core(obj, e);
+	if (!err)
+		prefetch_iotlb_entry(obj, e);
+	return err;
+}
+EXPORT_SYMBOL_GPL(omap_iopgtable_store_entry);
+
+/**
+ * iopgtable_lookup_entry - Lookup an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ * @ppgd:	iommu pgd entry pointer to be returned
+ * @ppte:	iommu pte entry pointer to be returned
+ **/
+static void
+iopgtable_lookup_entry(struct omap_iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
+{
+	u32 *iopgd, *iopte = NULL;
+
+	iopgd = iopgd_offset(obj, da);
+	if (!*iopgd)
+		goto out;
+
+	if (iopgd_is_table(*iopgd))
+		iopte = iopte_offset(iopgd, da);
+out:
+	*ppgd = iopgd;
+	*ppte = iopte;
+}
+
+static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
+{
+	size_t bytes;
+	u32 *iopgd = iopgd_offset(obj, da);
+	int nent = 1;
+
+	if (!*iopgd)
+		return 0;
+
+	if (iopgd_is_table(*iopgd)) {
+		int i;
+		u32 *iopte = iopte_offset(iopgd, da);
+
+		bytes = IOPTE_SIZE;
+		if (*iopte & IOPTE_LARGE) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopte = iopte_offset(iopgd, (da & IOLARGE_MASK));
+		}
+		bytes *= nent;
+		memset(iopte, 0, nent * sizeof(*iopte));
+		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
+
+		/*
+		 * do table walk to check if this table is necessary or not
+		 */
+		iopte = iopte_offset(iopgd, 0);
+		for (i = 0; i < PTRS_PER_IOPTE; i++)
+			if (iopte[i])
+				goto out;
+
+		iopte_free(iopte);
+		nent = 1; /* for the next L1 entry */
+	} else {
+		bytes = IOPGD_SIZE;
+		if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopgd = iopgd_offset(obj, (da & IOSUPER_MASK));
+		}
+		bytes *= nent;
+	}
+	memset(iopgd, 0, nent * sizeof(*iopgd));
+	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
+out:
+	return bytes;
+}
+
+/**
+ * iopgtable_clear_entry - Remove an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ **/
+static size_t iopgtable_clear_entry(struct omap_iommu *obj, u32 da)
+{
+	size_t bytes;
+
+	spin_lock(&obj->page_table_lock);
+
+	bytes = iopgtable_clear_entry_core(obj, da);
+	flush_iotlb_page(obj, da);
+
+	spin_unlock(&obj->page_table_lock);
+
+	return bytes;
+}
+
+static void iopgtable_clear_entry_all(struct omap_iommu *obj)
+{
+	int i;
+
+	spin_lock(&obj->page_table_lock);
+
+	for (i = 0; i < PTRS_PER_IOPGD; i++) {
+		u32 da;
+		u32 *iopgd;
+
+		da = i << IOPGD_SHIFT;
+		iopgd = iopgd_offset(obj, da);
+
+		if (!*iopgd)
+			continue;
+
+		if (iopgd_is_table(*iopgd))
+			iopte_free(iopte_offset(iopgd, 0));
+
+		*iopgd = 0;
+		flush_iopgd_range(iopgd, iopgd);
+	}
+
+	flush_iotlb_all(obj);
+
+	spin_unlock(&obj->page_table_lock);
+}
+
+/*
+ *	Device IOMMU generic operations
+ */
+static irqreturn_t iommu_fault_handler(int irq, void *data)
+{
+	u32 da, errs;
+	u32 *iopgd, *iopte;
+	struct omap_iommu *obj = data;
+	struct iommu_domain *domain = obj->domain;
+
+	if (!obj->refcount)
+		return IRQ_NONE;
+
+	clk_enable(obj->clk);
+	errs = iommu_report_fault(obj, &da);
+	clk_disable(obj->clk);
+	if (errs == 0)
+		return IRQ_HANDLED;
+
+	/* Fault callback or TLB/PTE Dynamic loading */
+	if (!report_iommu_fault(domain, obj->dev, da, 0))
+		return IRQ_HANDLED;
+
+	iommu_disable(obj);
+
+	iopgd = iopgd_offset(obj, da);
+
+	if (!iopgd_is_table(*iopgd)) {
+		dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
+			"*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd);
+		return IRQ_NONE;
+	}
+
+	iopte = iopte_offset(iopgd, da);
+
+	dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
+		"pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
+		iopte, *iopte);
+
+	return IRQ_NONE;
+}
+
+static int device_match_by_alias(struct device *dev, void *data)
+{
+	struct omap_iommu *obj = to_iommu(dev);
+	const char *name = data;
+
+	pr_debug("%s: %s %s\n", __func__, obj->name, name);
+
+	return strcmp(obj->name, name) == 0;
+}
+
+/**
+ * omap_find_iommu_device() - find an omap iommu device by name
+ * @name:	name of the iommu device
+ *
+ * The generic iommu API requires the caller to provide the device
+ * he wishes to attach to a certain iommu domain.
+ *
+ * Drivers generally should not bother with this as it should just
+ * be taken care of by the DMA-API using dev_archdata.
+ *
+ * This function is provided as an interim solution until the latter
+ * materializes, and omap3isp is fully migrated to the DMA-API.
+ */
+struct device *omap_find_iommu_device(const char *name)
+{
+	return driver_find_device(&omap_iommu_driver.driver, NULL,
+				(void *)name,
+				device_match_by_alias);
+}
+EXPORT_SYMBOL_GPL(omap_find_iommu_device);
+
+/**
+ * omap_iommu_attach() - attach iommu device to an iommu domain
+ * @dev:	target omap iommu device
+ * @iopgd:	page table
+ **/
+static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
+{
+	int err = -ENOMEM;
+	struct omap_iommu *obj = to_iommu(dev);
+
+	spin_lock(&obj->iommu_lock);
+
+	/* an iommu device can only be attached once */
+	if (++obj->refcount > 1) {
+		dev_err(dev, "%s: already attached!\n", obj->name);
+		err = -EBUSY;
+		goto err_enable;
+	}
+
+	obj->iopgd = iopgd;
+	err = iommu_enable(obj);
+	if (err)
+		goto err_enable;
+	flush_iotlb_all(obj);
+
+	if (!try_module_get(obj->owner))
+		goto err_module;
+
+	spin_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+	return obj;
+
+err_module:
+	if (obj->refcount == 1)
+		iommu_disable(obj);
+err_enable:
+	obj->refcount--;
+	spin_unlock(&obj->iommu_lock);
+	return ERR_PTR(err);
+}
+
+/**
+ * omap_iommu_detach - release iommu device
+ * @obj:	target iommu
+ **/
+static void omap_iommu_detach(struct omap_iommu *obj)
+{
+	if (!obj || IS_ERR(obj))
+		return;
+
+	spin_lock(&obj->iommu_lock);
+
+	if (--obj->refcount == 0)
+		iommu_disable(obj);
+
+	module_put(obj->owner);
+
+	obj->iopgd = NULL;
+
+	spin_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+}
+
+/*
+ *	OMAP Device MMU(IOMMU) detection
+ */
+static int __devinit omap_iommu_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	int irq;
+	struct omap_iommu *obj;
+	struct resource *res;
+	struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdev->num_resources != 2)
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	obj->clk = clk_get(&pdev->dev, pdata->clk_name);
+	if (IS_ERR(obj->clk))
+		goto err_clk;
+
+	obj->nr_tlb_entries = pdata->nr_tlb_entries;
+	obj->name = pdata->name;
+	obj->dev = &pdev->dev;
+	obj->ctx = (void *)obj + sizeof(*obj);
+	obj->da_start = pdata->da_start;
+	obj->da_end = pdata->da_end;
+
+	spin_lock_init(&obj->iommu_lock);
+	mutex_init(&obj->mmap_lock);
+	spin_lock_init(&obj->page_table_lock);
+	INIT_LIST_HEAD(&obj->mmap);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err_mem;
+	}
+
+	res = request_mem_region(res->start, resource_size(res),
+				 dev_name(&pdev->dev));
+	if (!res) {
+		err = -EIO;
+		goto err_mem;
+	}
+
+	obj->regbase = ioremap(res->start, resource_size(res));
+	if (!obj->regbase) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		err = -ENODEV;
+		goto err_irq;
+	}
+	err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
+			  dev_name(&pdev->dev), obj);
+	if (err < 0)
+		goto err_irq;
+	platform_set_drvdata(pdev, obj);
+
+	dev_info(&pdev->dev, "%s registered\n", obj->name);
+	return 0;
+
+err_irq:
+	iounmap(obj->regbase);
+err_ioremap:
+	release_mem_region(res->start, resource_size(res));
+err_mem:
+	clk_put(obj->clk);
+err_clk:
+	kfree(obj);
+	return err;
+}
+
+static int __devexit omap_iommu_remove(struct platform_device *pdev)
+{
+	int irq;
+	struct resource *res;
+	struct omap_iommu *obj = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	iopgtable_clear_entry_all(obj);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, obj);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+	iounmap(obj->regbase);
+
+	clk_put(obj->clk);
+	dev_info(&pdev->dev, "%s removed\n", obj->name);
+	kfree(obj);
+	return 0;
+}
+
+static struct platform_driver omap_iommu_driver = {
+	.probe	= omap_iommu_probe,
+	.remove	= __devexit_p(omap_iommu_remove),
+	.driver	= {
+		.name	= "omap-iommu",
+	},
+};
+
+static void iopte_cachep_ctor(void *iopte)
+{
+	clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
+}
+
+static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
+			 phys_addr_t pa, int order, int prot)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	size_t bytes = PAGE_SIZE << order;
+	struct iotlb_entry e;
+	int omap_pgsz;
+	u32 ret, flags;
+
+	/* we only support mapping a single iommu page for now */
+	omap_pgsz = bytes_to_iopgsz(bytes);
+	if (omap_pgsz < 0) {
+		dev_err(dev, "invalid size to map: %d\n", bytes);
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes);
+
+	flags = omap_pgsz | prot;
+
+	iotlb_init_entry(&e, da, pa, flags);
+
+	ret = omap_iopgtable_store_entry(oiommu, &e);
+	if (ret)
+		dev_err(dev, "omap_iopgtable_store_entry failed: %d\n", ret);
+
+	return ret;
+}
+
+static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
+			    int order)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	size_t unmap_size;
+
+	dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order);
+
+	unmap_size = iopgtable_clear_entry(oiommu, da);
+
+	return unmap_size ? get_order(unmap_size) : -EINVAL;
+}
+
+static int
+omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu;
+	int ret = 0;
+
+	spin_lock(&omap_domain->lock);
+
+	/* only a single device is supported per domain for now */
+	if (omap_domain->iommu_dev) {
+		dev_err(dev, "iommu domain is already attached\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* get a handle to and enable the omap iommu */
+	oiommu = omap_iommu_attach(dev, omap_domain->pgtable);
+	if (IS_ERR(oiommu)) {
+		ret = PTR_ERR(oiommu);
+		dev_err(dev, "can't get omap iommu: %d\n", ret);
+		goto out;
+	}
+
+	omap_domain->iommu_dev = oiommu;
+	oiommu->domain = domain;
+
+out:
+	spin_unlock(&omap_domain->lock);
+	return ret;
+}
+
+static void omap_iommu_detach_dev(struct iommu_domain *domain,
+				 struct device *dev)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = to_iommu(dev);
+
+	spin_lock(&omap_domain->lock);
+
+	/* only a single device is supported per domain for now */
+	if (omap_domain->iommu_dev != oiommu) {
+		dev_err(dev, "invalid iommu device\n");
+		goto out;
+	}
+
+	iopgtable_clear_entry_all(oiommu);
+
+	omap_iommu_detach(oiommu);
+
+	omap_domain->iommu_dev = NULL;
+
+out:
+	spin_unlock(&omap_domain->lock);
+}
+
+static int omap_iommu_domain_init(struct iommu_domain *domain)
+{
+	struct omap_iommu_domain *omap_domain;
+
+	omap_domain = kzalloc(sizeof(*omap_domain), GFP_KERNEL);
+	if (!omap_domain) {
+		pr_err("kzalloc failed\n");
+		goto out;
+	}
+
+	omap_domain->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL);
+	if (!omap_domain->pgtable) {
+		pr_err("kzalloc failed\n");
+		goto fail_nomem;
+	}
+
+	/*
+	 * should never fail, but please keep this around to ensure
+	 * we keep the hardware happy
+	 */
+	BUG_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE));
+
+	clean_dcache_area(omap_domain->pgtable, IOPGD_TABLE_SIZE);
+	spin_lock_init(&omap_domain->lock);
+
+	domain->priv = omap_domain;
+
+	return 0;
+
+fail_nomem:
+	kfree(omap_domain);
+out:
+	return -ENOMEM;
+}
+
+/* assume device was already detached */
+static void omap_iommu_domain_destroy(struct iommu_domain *domain)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+
+	domain->priv = NULL;
+
+	kfree(omap_domain->pgtable);
+	kfree(omap_domain);
+}
+
+static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
+					  unsigned long da)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	u32 *pgd, *pte;
+	phys_addr_t ret = 0;
+
+	iopgtable_lookup_entry(oiommu, da, &pgd, &pte);
+
+	if (pte) {
+		if (iopte_is_small(*pte))
+			ret = omap_iommu_translate(*pte, da, IOPTE_MASK);
+		else if (iopte_is_large(*pte))
+			ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
+		else
+			dev_err(dev, "bogus pte 0x%x", *pte);
+	} else {
+		if (iopgd_is_section(*pgd))
+			ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
+		else if (iopgd_is_super(*pgd))
+			ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
+		else
+			dev_err(dev, "bogus pgd 0x%x", *pgd);
+	}
+
+	return ret;
+}
+
+static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
+				    unsigned long cap)
+{
+	return 0;
+}
+
+static struct iommu_ops omap_iommu_ops = {
+	.domain_init	= omap_iommu_domain_init,
+	.domain_destroy	= omap_iommu_domain_destroy,
+	.attach_dev	= omap_iommu_attach_dev,
+	.detach_dev	= omap_iommu_detach_dev,
+	.map		= omap_iommu_map,
+	.unmap		= omap_iommu_unmap,
+	.iova_to_phys	= omap_iommu_iova_to_phys,
+	.domain_has_cap	= omap_iommu_domain_has_cap,
+};
+
+static int __init omap_iommu_init(void)
+{
+	struct kmem_cache *p;
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	size_t align = 1 << 10; /* L2 pagetable alignement */
+
+	p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
+			      iopte_cachep_ctor);
+	if (!p)
+		return -ENOMEM;
+	iopte_cachep = p;
+
+	bus_set_iommu(&platform_bus_type, &omap_iommu_ops);
+
+	return platform_driver_register(&omap_iommu_driver);
+}
+module_init(omap_iommu_init);
+
+static void __exit omap_iommu_exit(void)
+{
+	kmem_cache_destroy(iopte_cachep);
+
+	platform_driver_unregister(&omap_iommu_driver);
+}
+module_exit(omap_iommu_exit);
+
+MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
+MODULE_ALIAS("platform:omap-iommu");
+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/omap-iommu-debug.c linux-libre-3.2-gnu1/drivers/iommu/omap-iommu-debug.c
--- linux-libre-3.1-gnu1/drivers/iommu/omap-iommu-debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/iommu/omap-iommu-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,419 @@
+/*
+ * omap iommu: debugfs interface
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+
+#include <plat/iopgtable.h>
+
+#define MAXCOLUMN 100 /* for short messages */
+
+static DEFINE_MUTEX(iommu_debug_lock);
+
+static struct dentry *iommu_debug_root;
+
+static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	u32 ver = omap_iommu_arch_version();
+	char buf[MAXCOLUMN], *p = buf;
+
+	p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+
+static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	ssize_t bytes;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	bytes = omap_iommu_dump_ctx(obj, p, count);
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
+
+	mutex_unlock(&iommu_debug_lock);
+	kfree(buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	ssize_t bytes, rest;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
+	p += sprintf(p, "-----------------------------------------\n");
+	rest = count - (p - buf);
+	p += omap_dump_tlb_entries(obj, p, rest);
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	kfree(buf);
+
+	return bytes;
+}
+
+static ssize_t debug_write_pagetable(struct file *file,
+		     const char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct iotlb_entry e;
+	struct cr_regs cr;
+	int err;
+	struct omap_iommu *obj = file->private_data;
+	char buf[MAXCOLUMN], *p = buf;
+
+	count = min(count, sizeof(buf));
+
+	mutex_lock(&iommu_debug_lock);
+	if (copy_from_user(p, userbuf, count)) {
+		mutex_unlock(&iommu_debug_lock);
+		return -EFAULT;
+	}
+
+	sscanf(p, "%x %x", &cr.cam, &cr.ram);
+	if (!cr.cam || !cr.ram) {
+		mutex_unlock(&iommu_debug_lock);
+		return -EINVAL;
+	}
+
+	omap_iotlb_cr_to_e(&cr, &e);
+	err = omap_iopgtable_store_entry(obj, &e);
+	if (err)
+		dev_err(obj->dev, "%s: fail to store cr\n", __func__);
+
+	mutex_unlock(&iommu_debug_lock);
+	return count;
+}
+
+#define dump_ioptable_entry_one(lv, da, val)			\
+	({							\
+		int __err = 0;					\
+		ssize_t bytes;					\
+		const int maxcol = 22;				\
+		const char *str = "%d: %08x %08x\n";		\
+		bytes = snprintf(p, maxcol, str, lv, da, val);	\
+		p += bytes;					\
+		len -= bytes;					\
+		if (len < maxcol)				\
+			__err = -ENOMEM;			\
+		__err;						\
+	})
+
+static ssize_t dump_ioptable(struct omap_iommu *obj, char *buf, ssize_t len)
+{
+	int i;
+	u32 *iopgd;
+	char *p = buf;
+
+	spin_lock(&obj->page_table_lock);
+
+	iopgd = iopgd_offset(obj, 0);
+	for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
+		int j, err;
+		u32 *iopte;
+		u32 da;
+
+		if (!*iopgd)
+			continue;
+
+		if (!(*iopgd & IOPGD_TABLE)) {
+			da = i << IOPGD_SHIFT;
+
+			err = dump_ioptable_entry_one(1, da, *iopgd);
+			if (err)
+				goto out;
+			continue;
+		}
+
+		iopte = iopte_offset(iopgd, 0);
+
+		for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
+			if (!*iopte)
+				continue;
+
+			da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
+			err = dump_ioptable_entry_one(2, da, *iopgd);
+			if (err)
+				goto out;
+		}
+	}
+out:
+	spin_unlock(&obj->page_table_lock);
+
+	return p - buf;
+}
+
+static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
+				    size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	size_t bytes;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	p += sprintf(p, "L: %8s %8s\n", "da:", "pa:");
+	p += sprintf(p, "-----------------------------------------\n");
+
+	mutex_lock(&iommu_debug_lock);
+
+	bytes = PAGE_SIZE - (p - buf);
+	p += dump_ioptable(obj, p, bytes);
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	struct iovm_struct *tmp;
+	int uninitialized_var(i);
+	ssize_t bytes;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
+		     "No", "start", "end", "size", "flags");
+	p += sprintf(p, "-------------------------------------------------\n");
+
+	mutex_lock(&iommu_debug_lock);
+
+	list_for_each_entry(tmp, &obj->mmap, list) {
+		size_t len;
+		const char *str = "%3d %08x-%08x %6x %8x\n";
+		const int maxcol = 39;
+
+		len = tmp->da_end - tmp->da_start;
+		p += snprintf(p, maxcol, str,
+			      i, tmp->da_start, tmp->da_end, len, tmp->flags);
+
+		if (PAGE_SIZE - (p - buf) < maxcol)
+			break;
+		i++;
+	}
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	struct iovm_struct *area;
+	ssize_t bytes;
+
+	count = min_t(ssize_t, count, PAGE_SIZE);
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	area = omap_find_iovm_area(obj, (u32)ppos);
+	if (IS_ERR(area)) {
+		bytes = -EINVAL;
+		goto err_out;
+	}
+	memcpy(p, area->va, count);
+	p += count;
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+err_out:
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	struct iovm_struct *area;
+	char *p, *buf;
+
+	count = min_t(size_t, count, PAGE_SIZE);
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	if (copy_from_user(p, userbuf, count)) {
+		count =  -EFAULT;
+		goto err_out;
+	}
+
+	area = omap_find_iovm_area(obj, (u32)ppos);
+	if (IS_ERR(area)) {
+		count = -EINVAL;
+		goto err_out;
+	}
+	memcpy(area->va, p, count);
+err_out:
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return count;
+}
+
+static int debug_open_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define DEBUG_FOPS(name)						\
+	static const struct file_operations debug_##name##_fops = {	\
+		.open = debug_open_generic,				\
+		.read = debug_read_##name,				\
+		.write = debug_write_##name,				\
+		.llseek = generic_file_llseek,				\
+	};
+
+#define DEBUG_FOPS_RO(name)						\
+	static const struct file_operations debug_##name##_fops = {	\
+		.open = debug_open_generic,				\
+		.read = debug_read_##name,				\
+		.llseek = generic_file_llseek,				\
+	};
+
+DEBUG_FOPS_RO(ver);
+DEBUG_FOPS_RO(regs);
+DEBUG_FOPS_RO(tlb);
+DEBUG_FOPS(pagetable);
+DEBUG_FOPS_RO(mmap);
+DEBUG_FOPS(mem);
+
+#define __DEBUG_ADD_FILE(attr, mode)					\
+	{								\
+		struct dentry *dent;					\
+		dent = debugfs_create_file(#attr, mode, parent,		\
+					   obj, &debug_##attr##_fops);	\
+		if (!dent)						\
+			return -ENOMEM;					\
+	}
+
+#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
+#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
+
+static int iommu_debug_register(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_iommu *obj = platform_get_drvdata(pdev);
+	struct dentry *d, *parent;
+
+	if (!obj || !obj->dev)
+		return -EINVAL;
+
+	d = debugfs_create_dir(obj->name, iommu_debug_root);
+	if (!d)
+		return -ENOMEM;
+	parent = d;
+
+	d = debugfs_create_u8("nr_tlb_entries", 400, parent,
+			      (u8 *)&obj->nr_tlb_entries);
+	if (!d)
+		return -ENOMEM;
+
+	DEBUG_ADD_FILE_RO(ver);
+	DEBUG_ADD_FILE_RO(regs);
+	DEBUG_ADD_FILE_RO(tlb);
+	DEBUG_ADD_FILE(pagetable);
+	DEBUG_ADD_FILE_RO(mmap);
+	DEBUG_ADD_FILE(mem);
+
+	return 0;
+}
+
+static int __init iommu_debug_init(void)
+{
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("iommu", NULL);
+	if (!d)
+		return -ENOMEM;
+	iommu_debug_root = d;
+
+	err = omap_foreach_iommu_device(d, iommu_debug_register);
+	if (err)
+		goto err_out;
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(iommu_debug_root);
+	return err;
+}
+module_init(iommu_debug_init)
+
+static void __exit iommu_debugfs_exit(void)
+{
+	debugfs_remove_recursive(iommu_debug_root);
+}
+module_exit(iommu_debugfs_exit)
+
+MODULE_DESCRIPTION("omap iommu: debugfs interface");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/iommu/omap-iovmm.c linux-libre-3.2-gnu1/drivers/iommu/omap-iovmm.c
--- linux-libre-3.1-gnu1/drivers/iommu/omap-iovmm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/iommu/omap-iovmm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,743 @@
+/*
+ * omap iommu: simple virtual address space management
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/scatterlist.h>
+#include <linux/iommu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+
+#include <plat/iopgtable.h>
+
+static struct kmem_cache *iovm_area_cachep;
+
+/* return the offset of the first scatterlist entry in a sg table */
+static unsigned int sgtable_offset(const struct sg_table *sgt)
+{
+	if (!sgt || !sgt->nents)
+		return 0;
+
+	return sgt->sgl->offset;
+}
+
+/* return total bytes of sg buffers */
+static size_t sgtable_len(const struct sg_table *sgt)
+{
+	unsigned int i, total = 0;
+	struct scatterlist *sg;
+
+	if (!sgt)
+		return 0;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+
+		bytes = sg->length + sg->offset;
+
+		if (!iopgsz_ok(bytes)) {
+			pr_err("%s: sg[%d] not iommu pagesize(%u %u)\n",
+			       __func__, i, bytes, sg->offset);
+			return 0;
+		}
+
+		if (i && sg->offset) {
+			pr_err("%s: sg[%d] offset not allowed in internal "
+					"entries\n", __func__, i);
+			return 0;
+		}
+
+		total += bytes;
+	}
+
+	return total;
+}
+#define sgtable_ok(x)	(!!sgtable_len(x))
+
+static unsigned max_alignment(u32 addr)
+{
+	int i;
+	unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
+	for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
+		;
+	return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
+}
+
+/*
+ * calculate the optimal number sg elements from total bytes based on
+ * iommu superpages
+ */
+static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
+{
+	unsigned nr_entries = 0, ent_sz;
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
+		pr_err("%s: wrong size %08x\n", __func__, bytes);
+		return 0;
+	}
+
+	while (bytes) {
+		ent_sz = max_alignment(da | pa);
+		ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
+		nr_entries++;
+		da += ent_sz;
+		pa += ent_sz;
+		bytes -= ent_sz;
+	}
+
+	return nr_entries;
+}
+
+/* allocate and initialize sg_table header(a kind of 'superblock') */
+static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
+							u32 da, u32 pa)
+{
+	unsigned int nr_entries;
+	int err;
+	struct sg_table *sgt;
+
+	if (!bytes)
+		return ERR_PTR(-EINVAL);
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE))
+		return ERR_PTR(-EINVAL);
+
+	if (flags & IOVMF_LINEAR) {
+		nr_entries = sgtable_nents(bytes, da, pa);
+		if (!nr_entries)
+			return ERR_PTR(-EINVAL);
+	} else
+		nr_entries =  bytes / PAGE_SIZE;
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return ERR_PTR(-ENOMEM);
+
+	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
+	if (err) {
+		kfree(sgt);
+		return ERR_PTR(err);
+	}
+
+	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
+
+	return sgt;
+}
+
+/* free sg_table header(a kind of superblock) */
+static void sgtable_free(struct sg_table *sgt)
+{
+	if (!sgt)
+		return;
+
+	sg_free_table(sgt);
+	kfree(sgt);
+
+	pr_debug("%s: sgt:%p\n", __func__, sgt);
+}
+
+/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
+static void *vmap_sg(const struct sg_table *sgt)
+{
+	u32 va;
+	size_t total;
+	unsigned int i;
+	struct scatterlist *sg;
+	struct vm_struct *new;
+	const struct mem_type *mtype;
+
+	mtype = get_mem_type(MT_DEVICE);
+	if (!mtype)
+		return ERR_PTR(-EINVAL);
+
+	total = sgtable_len(sgt);
+	if (!total)
+		return ERR_PTR(-EINVAL);
+
+	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+	va = (u32)new->addr;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+		u32 pa;
+		int err;
+
+		pa = sg_phys(sg) - sg->offset;
+		bytes = sg->length + sg->offset;
+
+		BUG_ON(bytes != PAGE_SIZE);
+
+		err = ioremap_page(va,  pa, mtype);
+		if (err)
+			goto err_out;
+
+		va += bytes;
+	}
+
+	flush_cache_vmap((unsigned long)new->addr,
+				(unsigned long)(new->addr + total));
+	return new->addr;
+
+err_out:
+	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
+	vunmap(new->addr);
+	return ERR_PTR(-EAGAIN);
+}
+
+static inline void vunmap_sg(const void *va)
+{
+	vunmap(va);
+}
+
+static struct iovm_struct *__find_iovm_area(struct omap_iommu *obj,
+							const u32 da)
+{
+	struct iovm_struct *tmp;
+
+	list_for_each_entry(tmp, &obj->mmap, list) {
+		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
+			size_t len;
+
+			len = tmp->da_end - tmp->da_start;
+
+			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
+				__func__, tmp->da_start, da, tmp->da_end, len,
+				tmp->flags);
+
+			return tmp;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * omap_find_iovm_area  -  find iovma which includes @da
+ * @da:		iommu device virtual address
+ *
+ * Find the existing iovma starting at @da
+ */
+struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da)
+{
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+	area = __find_iovm_area(obj, da);
+	mutex_unlock(&obj->mmap_lock);
+
+	return area;
+}
+EXPORT_SYMBOL_GPL(omap_find_iovm_area);
+
+/*
+ * This finds the hole(area) which fits the requested address and len
+ * in iovmas mmap, and returns the new allocated iovma.
+ */
+static struct iovm_struct *alloc_iovm_area(struct omap_iommu *obj, u32 da,
+					   size_t bytes, u32 flags)
+{
+	struct iovm_struct *new, *tmp;
+	u32 start, prev_end, alignment;
+
+	if (!obj || !bytes)
+		return ERR_PTR(-EINVAL);
+
+	start = da;
+	alignment = PAGE_SIZE;
+
+	if (~flags & IOVMF_DA_FIXED) {
+		/* Don't map address 0 */
+		start = obj->da_start ? obj->da_start : alignment;
+
+		if (flags & IOVMF_LINEAR)
+			alignment = iopgsz_max(bytes);
+		start = roundup(start, alignment);
+	} else if (start < obj->da_start || start > obj->da_end ||
+					obj->da_end - start < bytes) {
+		return ERR_PTR(-EINVAL);
+	}
+
+	tmp = NULL;
+	if (list_empty(&obj->mmap))
+		goto found;
+
+	prev_end = 0;
+	list_for_each_entry(tmp, &obj->mmap, list) {
+
+		if (prev_end > start)
+			break;
+
+		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
+			goto found;
+
+		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
+			start = roundup(tmp->da_end + 1, alignment);
+
+		prev_end = tmp->da_end;
+	}
+
+	if ((start >= prev_end) && (obj->da_end - start >= bytes))
+		goto found;
+
+	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
+		__func__, da, bytes, flags);
+
+	return ERR_PTR(-EINVAL);
+
+found:
+	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+	new->iommu = obj;
+	new->da_start = start;
+	new->da_end = start + bytes;
+	new->flags = flags;
+
+	/*
+	 * keep ascending order of iovmas
+	 */
+	if (tmp)
+		list_add_tail(&new->list, &tmp->list);
+	else
+		list_add(&new->list, &obj->mmap);
+
+	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
+		__func__, new->da_start, start, new->da_end, bytes, flags);
+
+	return new;
+}
+
+static void free_iovm_area(struct omap_iommu *obj, struct iovm_struct *area)
+{
+	size_t bytes;
+
+	BUG_ON(!obj || !area);
+
+	bytes = area->da_end - area->da_start;
+
+	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
+		__func__, area->da_start, area->da_end, bytes, area->flags);
+
+	list_del(&area->list);
+	kmem_cache_free(iovm_area_cachep, area);
+}
+
+/**
+ * omap_da_to_va - convert (d) to (v)
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ * @va:		mpu virtual address
+ *
+ * Returns mpu virtual addr which corresponds to a given device virtual addr
+ */
+void *omap_da_to_va(struct omap_iommu *obj, u32 da)
+{
+	void *va = NULL;
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+	va = area->va;
+out:
+	mutex_unlock(&obj->mmap_lock);
+
+	return va;
+}
+EXPORT_SYMBOL_GPL(omap_da_to_va);
+
+static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+	void *va = _va;
+	void *va_end;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		struct page *pg;
+		const size_t bytes = PAGE_SIZE;
+
+		/*
+		 * iommu 'superpage' isn't supported with 'omap_iommu_vmalloc()'
+		 */
+		pg = vmalloc_to_page(va);
+		BUG_ON(!pg);
+		sg_set_page(sg, pg, bytes, 0);
+
+		va += bytes;
+	}
+
+	va_end = _va + PAGE_SIZE * i;
+}
+
+static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
+{
+	/*
+	 * Actually this is not necessary at all, just exists for
+	 * consistency of the code readability.
+	 */
+	BUG_ON(!sgt);
+}
+
+/* create 'da' <-> 'pa' mapping from 'sgt' */
+static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
+			const struct sg_table *sgt, u32 flags)
+{
+	int err;
+	unsigned int i, j;
+	struct scatterlist *sg;
+	u32 da = new->da_start;
+	int order;
+
+	if (!domain || !sgt)
+		return -EINVAL;
+
+	BUG_ON(!sgtable_ok(sgt));
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		u32 pa;
+		size_t bytes;
+
+		pa = sg_phys(sg) - sg->offset;
+		bytes = sg->length + sg->offset;
+
+		flags &= ~IOVMF_PGSZ_MASK;
+
+		if (bytes_to_iopgsz(bytes) < 0)
+			goto err_out;
+
+		order = get_order(bytes);
+
+		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
+			 i, da, pa, bytes);
+
+		err = iommu_map(domain, da, pa, order, flags);
+		if (err)
+			goto err_out;
+
+		da += bytes;
+	}
+	return 0;
+
+err_out:
+	da = new->da_start;
+
+	for_each_sg(sgt->sgl, sg, i, j) {
+		size_t bytes;
+
+		bytes = sg->length + sg->offset;
+		order = get_order(bytes);
+
+		/* ignore failures.. we're already handling one */
+		iommu_unmap(domain, da, order);
+
+		da += bytes;
+	}
+	return err;
+}
+
+/* release 'da' <-> 'pa' mapping */
+static void unmap_iovm_area(struct iommu_domain *domain, struct omap_iommu *obj,
+						struct iovm_struct *area)
+{
+	u32 start;
+	size_t total = area->da_end - area->da_start;
+	const struct sg_table *sgt = area->sgt;
+	struct scatterlist *sg;
+	int i, err;
+
+	BUG_ON(!sgtable_ok(sgt));
+	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
+
+	start = area->da_start;
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+		int order;
+
+		bytes = sg->length + sg->offset;
+		order = get_order(bytes);
+
+		err = iommu_unmap(domain, start, order);
+		if (err < 0)
+			break;
+
+		dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
+				__func__, start, bytes, area->flags);
+
+		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
+
+		total -= bytes;
+		start += bytes;
+	}
+	BUG_ON(total);
+}
+
+/* template function for all unmapping */
+static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
+				      struct omap_iommu *obj, const u32 da,
+				      void (*fn)(const void *), u32 flags)
+{
+	struct sg_table *sgt = NULL;
+	struct iovm_struct *area;
+
+	if (!IS_ALIGNED(da, PAGE_SIZE)) {
+		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
+		return NULL;
+	}
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+
+	if ((area->flags & flags) != flags) {
+		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
+			area->flags);
+		goto out;
+	}
+	sgt = (struct sg_table *)area->sgt;
+
+	unmap_iovm_area(domain, obj, area);
+
+	fn(area->va);
+
+	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
+		area->da_start, da, area->da_end,
+		area->da_end - area->da_start, area->flags);
+
+	free_iovm_area(obj, area);
+out:
+	mutex_unlock(&obj->mmap_lock);
+
+	return sgt;
+}
+
+static u32 map_iommu_region(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, const struct sg_table *sgt, void *va,
+				size_t bytes, u32 flags)
+{
+	int err = -ENOMEM;
+	struct iovm_struct *new;
+
+	mutex_lock(&obj->mmap_lock);
+
+	new = alloc_iovm_area(obj, da, bytes, flags);
+	if (IS_ERR(new)) {
+		err = PTR_ERR(new);
+		goto err_alloc_iovma;
+	}
+	new->va = va;
+	new->sgt = sgt;
+
+	if (map_iovm_area(domain, new, sgt, new->flags))
+		goto err_map;
+
+	mutex_unlock(&obj->mmap_lock);
+
+	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
+		__func__, new->da_start, bytes, new->flags, va);
+
+	return new->da_start;
+
+err_map:
+	free_iovm_area(obj, new);
+err_alloc_iovma:
+	mutex_unlock(&obj->mmap_lock);
+	return err;
+}
+
+static inline u32
+__iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, const struct sg_table *sgt,
+				void *va, size_t bytes, u32 flags)
+{
+	return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
+}
+
+/**
+ * omap_iommu_vmap  -  (d)-(p)-(v) address mapper
+ * @obj:	objective iommu
+ * @sgt:	address of scatter gather table
+ * @flags:	iovma and page property
+ *
+ * Creates 1-n-1 mapping with given @sgt and returns @da.
+ * All @sgt element must be io page size aligned.
+ */
+u32 omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+		const struct sg_table *sgt, u32 flags)
+{
+	size_t bytes;
+	void *va = NULL;
+
+	if (!obj || !obj->dev || !sgt)
+		return -EINVAL;
+
+	bytes = sgtable_len(sgt);
+	if (!bytes)
+		return -EINVAL;
+	bytes = PAGE_ALIGN(bytes);
+
+	if (flags & IOVMF_MMIO) {
+		va = vmap_sg(sgt);
+		if (IS_ERR(va))
+			return PTR_ERR(va);
+	}
+
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_MMIO;
+
+	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		vunmap_sg(va);
+
+	return da + sgtable_offset(sgt);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vmap);
+
+/**
+ * omap_iommu_vunmap  -  release virtual mapping obtained by 'omap_iommu_vmap()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Free the iommu virtually contiguous memory area starting at
+ * @da, which was returned by 'omap_iommu_vmap()'.
+ */
+struct sg_table *
+omap_iommu_vunmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da)
+{
+	struct sg_table *sgt;
+	/*
+	 * 'sgt' is allocated before 'omap_iommu_vmalloc()' is called.
+	 * Just returns 'sgt' to the caller to free
+	 */
+	da &= PAGE_MASK;
+	sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
+					IOVMF_DISCONT | IOVMF_MMIO);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	return sgt;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vunmap);
+
+/**
+ * omap_iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
+ * @obj:	objective iommu
+ * @da:		contiguous iommu virtual memory
+ * @bytes:	allocation size
+ * @flags:	iovma and page property
+ *
+ * Allocate @bytes linearly and creates 1-n-1 mapping and returns
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
+ */
+u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+						size_t bytes, u32 flags)
+{
+	void *va;
+	struct sg_table *sgt;
+
+	if (!obj || !obj->dev || !bytes)
+		return -EINVAL;
+
+	bytes = PAGE_ALIGN(bytes);
+
+	va = vmalloc(bytes);
+	if (!va)
+		return -ENOMEM;
+
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_ALLOC;
+
+	sgt = sgtable_alloc(bytes, flags, da, 0);
+	if (IS_ERR(sgt)) {
+		da = PTR_ERR(sgt);
+		goto err_sgt_alloc;
+	}
+	sgtable_fill_vmalloc(sgt, va);
+
+	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		goto err_iommu_vmap;
+
+	return da;
+
+err_iommu_vmap:
+	sgtable_drain_vmalloc(sgt);
+	sgtable_free(sgt);
+err_sgt_alloc:
+	vfree(va);
+	return da;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vmalloc);
+
+/**
+ * omap_iommu_vfree  -  release memory allocated by 'omap_iommu_vmalloc()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Frees the iommu virtually continuous memory area starting at
+ * @da, as obtained from 'omap_iommu_vmalloc()'.
+ */
+void omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+								const u32 da)
+{
+	struct sg_table *sgt;
+
+	sgt = unmap_vm_area(domain, obj, da, vfree,
+						IOVMF_DISCONT | IOVMF_ALLOC);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	sgtable_free(sgt);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vfree);
+
+static int __init iovmm_init(void)
+{
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	struct kmem_cache *p;
+
+	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
+			      flags, NULL);
+	if (!p)
+		return -ENOMEM;
+	iovm_area_cachep = p;
+
+	return 0;
+}
+module_init(iovmm_init);
+
+static void __exit iovmm_exit(void)
+{
+	kmem_cache_destroy(iovm_area_cachep);
+}
+module_exit(iovmm_exit);
+
+MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/capi/kcapi_proc.c linux-libre-3.2-gnu1/drivers/isdn/capi/kcapi_proc.c
--- linux-libre-3.1-gnu1/drivers/isdn/capi/kcapi_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/capi/kcapi_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/export.h>
 
 static char *state2str(unsigned short state)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/divert/divert_procfs.c linux-libre-3.2-gnu1/drivers/isdn/divert/divert_procfs.c
--- linux-libre-3.1-gnu1/drivers/isdn/divert/divert_procfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/divert/divert_procfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -242,6 +242,12 @@ static int isdn_divert_ioctl_unlocked(st
 		case IIOCDOCFINT:
 			if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
 				return (-EINVAL);	/* invalid driver */
+			if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
+					sizeof(dioctl.cf_ctrl.msn))
+				return -EINVAL;
+			if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
+					sizeof(dioctl.cf_ctrl.fwd_nr))
+				return -EINVAL;
 			if ((i = cf_command(dioctl.cf_ctrl.drvid,
 					    (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
 					    dioctl.cf_ctrl.cfproc,
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/asyncdata.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/asyncdata.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/asyncdata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/asyncdata.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
 #include <linux/bitrev.h>
+#include <linux/export.h>
 
 /* check if byte must be stuffed/escaped
  * I'm not sure which data should be encoded.
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/capi.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/capi.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/capi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/capi.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/isdn/capilli.h>
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
+#include <linux/export.h>
 
 /* missing from kernelcapi.h */
 #define CapiNcpiNotSupportedByProtocol	0x0001
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/dummyll.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/dummyll.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/dummyll.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/dummyll.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * =====================================================================
  */
 
+#include <linux/export.h>
 #include "gigaset.h"
 
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/ev-layer.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/ev-layer.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/ev-layer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/ev-layer.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  * =====================================================================
  */
 
+#include <linux/export.h>
 #include "gigaset.h"
 
 /* ========================================================== */
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/i4l.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/i4l.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/i4l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/i4l.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include "gigaset.h"
 #include <linux/isdnif.h>
+#include <linux/export.h>
 
 #define SBUFSIZE	4096	/* sk_buff payload size */
 #define TRANSBUFSIZE	768	/* bytes per skb for transparent receive */
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/gigaset/interface.c linux-libre-3.2-gnu1/drivers/isdn/gigaset/interface.c
--- linux-libre-3.1-gnu1/drivers/isdn/gigaset/interface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/gigaset/interface.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "gigaset.h"
 #include <linux/gigaset_dev.h>
 #include <linux/tty_flip.h>
+#include <linux/module.h>
 
 /*** our ioctls ***/
 
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c linux-libre-3.2-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c
--- linux-libre-3.1-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/mISDNhw.h>
+#include <linux/module.h>
 #include "isar.h"
 
 #define ISAR_REV	"2.1"
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/callc.c linux-libre-3.2-gnu1/drivers/isdn/hisax/callc.c
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/callc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/callc.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,7 +65,7 @@ hisax_findcard(int driverid)
 	return (struct IsdnCardState *) 0;
 }
 
-static __attribute__((format(printf, 3, 4))) void
+static __printf(3, 4) void
 link_debug(struct Channel *chanp, int direction, char *fmt, ...)
 {
 	va_list args;
@@ -1068,7 +1068,7 @@ init_d_st(struct Channel *chanp)
 	return 0;
 }
 
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
 callc_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/hisax.h linux-libre-3.2-gnu1/drivers/isdn/hisax/hisax.h
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/hisax.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/hisax.h	2012-01-04 18:55:44.000000000 -0500
@@ -1287,9 +1287,9 @@ int jiftime(char *s, long mark);
 
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-__attribute__((format(printf, 3, 4)))
+__printf(3, 4)
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-__attribute__((format(printf, 3, 0)))
+__printf(3, 0)
 void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char * p, int cnt);
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/isdnl1.h linux-libre-3.2-gnu1/drivers/isdn/hisax/isdnl1.h
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/isdnl1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/isdnl1.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #define B_XMTBUFREADY	1
 #define B_ACKPENDING	2
 
-__attribute__((format(printf, 2, 3)))
+__printf(2, 3)
 void debugl1(struct IsdnCardState *cs, char *fmt, ...);
 void DChannel_proc_xmt(struct IsdnCardState *cs);
 void DChannel_proc_rcv(struct IsdnCardState *cs);
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/isdnl3.c linux-libre-3.2-gnu1/drivers/isdn/hisax/isdnl3.c
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/isdnl3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/isdnl3.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,7 @@ static char *strL3Event[] =
 	"EV_TIMEOUT",
 };
 
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
 l3m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/l3dss1.c linux-libre-3.2-gnu1/drivers/isdn/hisax/l3dss1.c
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/l3dss1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/l3dss1.c	2012-01-04 18:55:44.000000000 -0500
@@ -353,7 +353,7 @@ l3dss1_parse_facility(struct PStack *st,
 			         { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
                                    return;
                                  } 
-#ifdef HISAX_DE_AOC
+#ifdef CONFIG_DE_AOC
 			{
 
 #define FOO1(s,a,b) \
@@ -422,9 +422,9 @@ l3dss1_parse_facility(struct PStack *st,
 #undef FOO1
 
 			}
-#else  /* not HISAX_DE_AOC */
+#else  /* not CONFIG_DE_AOC */
                         l3_debug(st, "invoke break");
-#endif /* not HISAX_DE_AOC */
+#endif /* not CONFIG_DE_AOC */
 			break;
 		case 2:	/* return result */
 			 /* if no process available handle separately */ 
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/hisax/st5481_d.c linux-libre-3.2-gnu1/drivers/isdn/hisax/st5481_d.c
--- linux-libre-3.1-gnu1/drivers/isdn/hisax/st5481_d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/hisax/st5481_d.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@ static struct FsmNode L1FnList[] __initd
 	{ST_L1_F8, EV_IND_RSY,           l1_ignore},
 };
 
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
 void l1m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
@@ -270,7 +270,7 @@ static char *strDoutEvent[] =
 	"EV_DOUT_UNDERRUN",
 };
 
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
 void dout_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_common.c linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_common.c
--- linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -2308,11 +2308,11 @@ static int __init isdn_init(void)
 	int i;
 	char tmprev[50];
 
-	if (!(dev = vmalloc(sizeof(isdn_dev)))) {
+	dev = vzalloc(sizeof(isdn_dev));
+	if (!dev) {
 		printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
 		return -EIO;
 	}
-	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
 	spin_lock_init(&dev->lock);
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_net.c linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_net.c
--- linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_net.c	2012-01-04 18:55:44.000000000 -0500
@@ -2756,6 +2756,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg
 			char *c,
 			*e;
 
+			if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
+					sizeof(cfg->drvid))
+				return -EINVAL;
 			drvidx = -1;
 			chidx = -1;
 			strcpy(drvid, cfg->drvid);
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_tty.c linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_tty.c
--- linux-libre-3.1-gnu1/drivers/isdn/i4l/isdn_tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/i4l/isdn_tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -750,6 +750,7 @@ isdn_tty_modem_hup(modem_info * info, in
  * supplementary service (CAPI 2.0 part III)
  */
 #include <linux/isdn/capicmd.h>
+#include <linux/module.h>
 
 int
 isdn_tty_capi_facility(capi_msg *cm) {
@@ -1693,7 +1694,7 @@ isdn_tty_close(struct tty_struct *tty, s
 	 * line status register.
 	 */
 	if (info->flags & ISDN_ASYNC_INITIALIZED) {
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
+		tty_wait_until_sent_from_close(tty, 3000);	/* 30 seconds timeout */
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/Kconfig linux-libre-3.2-gnu1/drivers/isdn/Kconfig
--- linux-libre-3.1-gnu1/drivers/isdn/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 menuconfig ISDN
 	bool "ISDN support"
 	depends on NET
-	depends on !S390
+	depends on !S390 && !UML
 	---help---
 	  ISDN ("Integrated Services Digital Network", called RNIS in France)
 	  is a fully digital telephone service that can be used for voice and
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/clock.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/clock.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/mISDNif.h>
+#include <linux/export.h>
 #include "core.h"
 
 static u_int *debug;
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_audio.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_audio.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/mISDNif.h>
 #include <linux/mISDNdsp.h>
+#include <linux/export.h>
 #include "core.h"
 #include "dsp.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_core.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_core.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1052,12 +1052,11 @@ dspcreate(struct channel_req *crq)
 	if (crq->protocol != ISDN_P_B_L2DSP
 	 && crq->protocol != ISDN_P_B_L2DSPHDLC)
 		return -EPROTONOSUPPORT;
-	ndsp = vmalloc(sizeof(struct dsp));
+	ndsp = vzalloc(sizeof(struct dsp));
 	if (!ndsp) {
 		printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);
 		return -ENOMEM;
 	}
-	memset(ndsp, 0, sizeof(struct dsp));
 	if (dsp_debug & DEBUG_DSP_CTRL)
 		printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);
 
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_pipeline.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_pipeline.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/dsp_pipeline.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/dsp_pipeline.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 #include <linux/mISDNif.h>
 #include <linux/mISDNdsp.h>
+#include <linux/export.h>
 #include "dsp.h"
 #include "dsp_hwec.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/l1oip_codec.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/l1oip_codec.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/l1oip_codec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/l1oip_codec.c	2012-01-04 18:55:44.000000000 -0500
@@ -330,14 +330,12 @@ l1oip_4bit_alloc(int ulaw)
 		return 0;
 
 	/* alloc conversion tables */
-	table_com = vmalloc(65536);
-	table_dec = vmalloc(512);
+	table_com = vzalloc(65536);
+	table_dec = vzalloc(512);
 	if (!table_com || !table_dec) {
 		l1oip_4bit_free();
 		return -ENOMEM;
 	}
-	memset(table_com, 0, 65536);
-	memset(table_dec, 0, 512);
 	/* generate compression table */
 	i1 = 0;
 	while (i1 < 256) {
diff -druNp linux-libre-3.1-gnu1/drivers/isdn/mISDN/socket.c linux-libre-3.2-gnu1/drivers/isdn/mISDN/socket.c
--- linux-libre-3.1-gnu1/drivers/isdn/mISDN/socket.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/isdn/mISDN/socket.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 
 #include <linux/mISDNif.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "core.h"
 
 static u_int	*debug;
diff -druNp linux-libre-3.1-gnu1/drivers/Kconfig linux-libre-3.2-gnu1/drivers/Kconfig
--- linux-libre-3.1-gnu1/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,8 @@ source "drivers/pps/Kconfig"
 
 source "drivers/ptp/Kconfig"
 
+source "drivers/pinctrl/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/w1/Kconfig"
@@ -130,4 +132,8 @@ source "drivers/iommu/Kconfig"
 
 source "drivers/virt/Kconfig"
 
+source "drivers/hv/Kconfig"
+
+source "drivers/devfreq/Kconfig"
+
 endmenu
diff -druNp linux-libre-3.1-gnu1/drivers/leds/dell-led.c linux-libre-3.2-gnu1/drivers/leds/dell-led.c
--- linux-libre-3.1-gnu1/drivers/leds/dell-led.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/dell-led.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/acpi.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 MODULE_AUTHOR("Louis Davis/Jim Dailey");
 MODULE_DESCRIPTION("Dell LED Control Driver");
diff -druNp linux-libre-3.1-gnu1/drivers/leds/Kconfig linux-libre-3.2-gnu1/drivers/leds/Kconfig
--- linux-libre-3.1-gnu1/drivers/leds/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -113,14 +113,6 @@ config LEDS_WRAP
 	help
 	  This option enables support for the PCEngines WRAP programmable LEDs.
 
-config LEDS_ALIX2
-	tristate "LED Support for ALIX.2 and ALIX.3 series"
-	depends on LEDS_CLASS
-	depends on X86 && !GPIO_CS5535 && !CS5535_GPIO
-	help
-	  This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
-	  You have to set leds-alix2.force=1 for boards with Award BIOS.
-
 config LEDS_COBALT_QUBE
 	tristate "LED Support for the Cobalt Qube series front LED"
 	depends on LEDS_CLASS
@@ -383,6 +375,18 @@ config LEDS_ASIC3
 	  cannot be used. This driver supports hardware blinking with an on+off
 	  period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
 
+config LEDS_RENESAS_TPU
+	bool "LED support for Renesas TPU"
+	depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO
+	help
+	  This option enables build of the LED TPU platform driver,
+	  suitable to drive any TPU channel on newer Renesas SoCs.
+	  The driver controls the GPIO pin connected to the LED via
+	  the GPIO framework and expects the LED to be connected to
+	  a pin that can be driven in both GPIO mode and using TPU
+	  pin function. The latter to support brightness control.
+	  Brightness control is supported but hardware blinking is not.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	depends on LEDS_CLASS
@@ -400,7 +404,7 @@ config LEDS_TRIGGER_TIMER
 	  This allows LEDs to be controlled by a programmable timer
 	  via sysfs. Some LED hardware can be programmed to start
 	  blinking the LED without any further software interaction.
-	  For more details read Documentation/leds-class.txt.
+	  For more details read Documentation/leds/leds-class.txt.
 
 	  If unsure, say Y.
 
diff -druNp linux-libre-3.1-gnu1/drivers/leds/led-class.c linux-libre-3.2-gnu1/drivers/leds/led-class.c
--- linux-libre-3.1-gnu1/drivers/leds/led-class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/led-class.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,6 +267,8 @@ void led_blink_set(struct led_classdev *
 		   unsigned long *delay_on,
 		   unsigned long *delay_off)
 {
+	del_timer_sync(&led_cdev->blink_timer);
+
 	if (led_cdev->blink_set &&
 	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
 		return;
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-88pm860x.c linux-libre-3.2-gnu1/drivers/leds/leds-88pm860x.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-88pm860x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-88pm860x.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/module.h>
 
 #define LED_PWM_SHIFT		(3)
 #define LED_PWM_MASK		(0x1F)
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-alix2.c linux-libre-3.2-gnu1/drivers/leds/leds-alix2.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-alix2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-alix2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,239 +0,0 @@
-/*
- * LEDs driver for PCEngines ALIX.2 and ALIX.3
- *
- * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-static int force = 0;
-module_param(force, bool, 0444);
-MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
-
-#define MSR_LBAR_GPIO		0x5140000C
-#define CS5535_GPIO_SIZE	256
-
-static u32 gpio_base;
-
-static struct pci_device_id divil_pci[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ } /* NULL entry */
-};
-MODULE_DEVICE_TABLE(pci, divil_pci);
-
-struct alix_led {
-	struct led_classdev cdev;
-	unsigned short port;
-	unsigned int on_value;
-	unsigned int off_value;
-};
-
-static void alix_led_set(struct led_classdev *led_cdev,
-			 enum led_brightness brightness)
-{
-	struct alix_led *led_dev =
-		container_of(led_cdev, struct alix_led, cdev);
-
-	if (brightness)
-		outl(led_dev->on_value, gpio_base + led_dev->port);
-	else
-		outl(led_dev->off_value, gpio_base + led_dev->port);
-}
-
-static struct alix_led alix_leds[] = {
-	{
-		.cdev = {
-			.name = "alix:1",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x00,
-		.on_value = 1 << 22,
-		.off_value = 1 << 6,
-	},
-	{
-		.cdev = {
-			.name = "alix:2",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x80,
-		.on_value = 1 << 25,
-		.off_value = 1 << 9,
-	},
-	{
-		.cdev = {
-			.name = "alix:3",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x80,
-		.on_value = 1 << 27,
-		.off_value = 1 << 11,
-	},
-};
-
-static int __init alix_led_probe(struct platform_device *pdev)
-{
-	int i;
-	int ret;
-
-	for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
-		alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
-		ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
-		if (ret < 0)
-			goto fail;
-	}
-	return 0;
-
-fail:
-	while (--i >= 0)
-		led_classdev_unregister(&alix_leds[i].cdev);
-	return ret;
-}
-
-static int alix_led_remove(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
-		led_classdev_unregister(&alix_leds[i].cdev);
-	return 0;
-}
-
-static struct platform_driver alix_led_driver = {
-	.remove = alix_led_remove,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init alix_present(unsigned long bios_phys,
-				const char *alix_sig,
-				size_t alix_sig_len)
-{
-	const size_t bios_len = 0x00010000;
-	const char *bios_virt;
-	const char *scan_end;
-	const char *p;
-	char name[64];
-
-	if (force) {
-		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
-		       "assume system has ALIX.2 style LEDs\n",
-		       KBUILD_MODNAME);
-		return 1;
-	}
-
-	bios_virt = phys_to_virt(bios_phys);
-	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
-	for (p = bios_virt; p < scan_end; p++) {
-		const char *tail;
-		char *a;
-
-		if (memcmp(p, alix_sig, alix_sig_len) != 0)
-			continue;
-
-		memcpy(name, p, sizeof(name));
-
-		/* remove the first \0 character from string */
-		a = strchr(name, '\0');
-		if (a)
-			*a = ' ';
-
-		/* cut the string at a newline */
-		a = strchr(name, '\r');
-		if (a)
-			*a = '\0';
-
-		tail = p + alix_sig_len;
-		if ((tail[0] == '2' || tail[0] == '3')) {
-			printk(KERN_INFO
-			       "%s: system is recognized as \"%s\"\n",
-			       KBUILD_MODNAME, name);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static struct platform_device *pdev;
-
-static int __init alix_pci_led_init(void)
-{
-	u32 low, hi;
-
-	if (pci_dev_present(divil_pci) == 0) {
-		printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
-		return -ENODEV;
-	}
-
-	/* Grab the GPIO I/O range */
-	rdmsr(MSR_LBAR_GPIO, low, hi);
-
-	/* Check the mask and whether GPIO is enabled (sanity check) */
-	if (hi != 0x0000f001) {
-		printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
-		return -ENODEV;
-	}
-
-	/* Mask off the IO base address */
-	gpio_base = low & 0x0000ff00;
-
-	if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
-		printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
-		return -ENODEV;
-	}
-
-	/* Set GPIO function to output */
-	outl(1 << 6, gpio_base + 0x04);
-	outl(1 << 9, gpio_base + 0x84);
-	outl(1 << 11, gpio_base + 0x84);
-
-	return 0;
-}
-
-static int __init alix_led_init(void)
-{
-	int ret = -ENODEV;
-	const char tinybios_sig[] = "PC Engines ALIX.";
-	const char coreboot_sig[] = "PC Engines\0ALIX.";
-
-	if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
-	    alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
-		ret = alix_pci_led_init();
-
-	if (ret < 0)
-		return ret;
-
-	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
-	if (!IS_ERR(pdev)) {
-		ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
-		if (ret)
-			platform_device_unregister(pdev);
-	} else
-		ret = PTR_ERR(pdev);
-
-	return ret;
-}
-
-static void __exit alix_led_exit(void)
-{
-	platform_device_unregister(pdev);
-	platform_driver_unregister(&alix_led_driver);
-	release_region(gpio_base, CS5535_GPIO_SIZE);
-}
-
-module_init(alix_led_init);
-module_exit(alix_led_exit);
-
-MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
-MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-asic3.c linux-libre-3.2-gnu1/drivers/leds/leds-asic3.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-asic3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-asic3.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/mfd/asic3.h>
 #include <linux/mfd/core.h>
+#include <linux/module.h>
 
 /*
  *	The HTC ASIC3 LED GPIOs are inputs, not outputs.
@@ -107,9 +108,10 @@ static int __devinit asic3_led_probe(str
 	}
 
 	led->cdev->name = led->name;
-	led->cdev->default_trigger = led->default_trigger;
+	led->cdev->flags = LED_CORE_SUSPENDRESUME;
 	led->cdev->brightness_set = brightness_set;
 	led->cdev->blink_set = blink_set;
+	led->cdev->default_trigger = led->default_trigger;
 
 	ret = led_classdev_register(&pdev->dev, led->cdev);
 	if (ret < 0)
@@ -136,12 +138,44 @@ static int __devexit asic3_led_remove(st
 	return mfd_cell_disable(pdev);
 }
 
+static int asic3_led_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int ret;
+
+	ret = 0;
+	if (cell->suspend)
+		ret = (*cell->suspend)(pdev);
+
+	return ret;
+}
+
+static int asic3_led_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int ret;
+
+	ret = 0;
+	if (cell->resume)
+		ret = (*cell->resume)(pdev);
+
+	return ret;
+}
+
+static const struct dev_pm_ops asic3_led_pm_ops = {
+	.suspend	= asic3_led_suspend,
+	.resume		= asic3_led_resume,
+};
+
 static struct platform_driver asic3_led_driver = {
 	.probe		= asic3_led_probe,
 	.remove		= __devexit_p(asic3_led_remove),
 	.driver		= {
 		.name	= "leds-asic3",
 		.owner	= THIS_MODULE,
+		.pm	= &asic3_led_pm_ops,
 	},
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-atmel-pwm.c linux-libre-3.2-gnu1/drivers/leds/leds-atmel-pwm.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-atmel-pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-atmel-pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 #include <linux/io.h>
 #include <linux/atmel_pwm.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 
 struct pwmled {
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-cobalt-raq.c linux-libre-3.2-gnu1/drivers/leds/leds-cobalt-raq.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-cobalt-raq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-cobalt-raq.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/export.h>
 
 #define LED_WEB		0x04
 #define LED_POWER_OFF	0x08
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-fsg.c linux-libre-3.2-gnu1/drivers/leds/leds-fsg.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-fsg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-fsg.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/module.h>
 #include <mach/hardware.h>
 #include <asm/io.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-gpio.c linux-libre-3.2-gnu1/drivers/leds/leds-gpio.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 
 #include <asm/gpio.h>
 
@@ -121,7 +122,7 @@ static int __devinit create_gpio_led(con
 	}
 	led_dat->cdev.brightness_set = gpio_led_set;
 	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-		state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;
+		state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
 	else
 		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
 	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-lm3530.c linux-libre-3.2-gnu1/drivers/leds/leds-lm3530.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-lm3530.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-lm3530.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/led-lm3530.h>
 #include <linux/types.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 #define LM3530_LED_DEV "lcd-backlight"
 #define LM3530_NAME "lm3530-led"
@@ -421,7 +422,6 @@ err_class_register:
 err_reg_init:
 	regulator_put(drvdata->regulator);
 err_regulator_get:
-	i2c_set_clientdata(client, NULL);
 	kfree(drvdata);
 err_out:
 	return err;
@@ -449,7 +449,7 @@ MODULE_DEVICE_TABLE(i2c, lm3530_id);
 
 static struct i2c_driver lm3530_i2c_driver = {
 	.probe = lm3530_probe,
-	.remove = lm3530_remove,
+	.remove = __devexit_p(lm3530_remove),
 	.id_table = lm3530_id,
 	.driver = {
 		.name = LM3530_NAME,
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-locomo.c linux-libre-3.2-gnu1/drivers/leds/leds-locomo.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-locomo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-locomo.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/leds.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-lp5521.c linux-libre-3.2-gnu1/drivers/leds/leds-lp5521.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-lp5521.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-lp5521.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,6 +97,9 @@
 /* Status */
 #define LP5521_EXT_CLK_USED		0x08
 
+/* default R channel current register value */
+#define LP5521_REG_R_CURR_DEFAULT	0xAF
+
 struct lp5521_engine {
 	int		id;
 	u8		mode;
@@ -175,14 +178,14 @@ static int lp5521_set_engine_mode(struct
 		mode = LP5521_CMD_DIRECT;
 
 	ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state);
+	if (ret < 0)
+		return ret;
 
 	/* set mode only for this engine */
 	engine_state &= ~(engine->engine_mask);
 	mode &= engine->engine_mask;
 	engine_state |= mode;
-	ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
-
-	return ret;
+	return lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
 }
 
 static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
@@ -643,6 +646,7 @@ static int __devinit lp5521_probe(struct
 	struct lp5521_chip		*chip;
 	struct lp5521_platform_data	*pdata;
 	int ret, i, led;
+	u8 buf;
 
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (!chip)
@@ -681,6 +685,20 @@ static int __devinit lp5521_probe(struct
 				     * Exact value is not available. 10 - 20ms
 				     * appears to be enough for reset.
 				     */
+
+	/*
+	 * Make sure that the chip is reset by reading back the r channel
+	 * current reg. This is dummy read is required on some platforms -
+	 * otherwise further access to the R G B channels in the
+	 * LP5521_REG_ENABLE register will not have any effect - strange!
+	 */
+	lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
+	if (buf != LP5521_REG_R_CURR_DEFAULT) {
+		dev_err(&client->dev, "error in reseting chip\n");
+		goto fail2;
+	}
+	usleep_range(10000, 20000);
+
 	ret = lp5521_detect(client);
 
 	if (ret) {
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-lt3593.c linux-libre-3.2-gnu1/drivers/leds/leds-lt3593.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-lt3593.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-lt3593.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct lt3593_led_data {
 	struct led_classdev cdev;
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-mc13783.c linux-libre-3.2-gnu1/drivers/leds/leds-mc13783.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-mc13783.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-mc13783.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,13 +21,13 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
-#include <linux/mfd/mc13783.h>
+#include <linux/mfd/mc13xxx.h>
 #include <linux/slab.h>
 
 struct mc13783_led {
 	struct led_classdev	cdev;
 	struct work_struct	work;
-	struct mc13783		*master;
+	struct mc13xxx		*master;
 	enum led_brightness	new_brightness;
 	int			id;
 };
@@ -111,11 +111,11 @@ static void mc13783_led_work(struct work
 		break;
 	}
 
-	mc13783_lock(led->master);
+	mc13xxx_lock(led->master);
 
-	mc13783_reg_rmw(led->master, reg, mask, value);
+	mc13xxx_reg_rmw(led->master, reg, mask, value);
 
-	mc13783_unlock(led->master);
+	mc13xxx_unlock(led->master);
 }
 
 static void mc13783_led_set(struct led_classdev *led_cdev,
@@ -172,23 +172,23 @@ static int __devinit mc13783_led_setup(s
 		break;
 	}
 
-	mc13783_lock(led->master);
+	mc13xxx_lock(led->master);
 
-	ret = mc13783_reg_rmw(led->master, reg, mask << shift,
+	ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
 						value << shift);
 
-	mc13783_unlock(led->master);
+	mc13xxx_unlock(led->master);
 	return ret;
 }
 
 static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
 	int ret = 0;
 	int reg = 0;
 
-	mc13783_lock(dev);
+	mc13xxx_lock(dev);
 
 	if (pdata->flags & MC13783_LED_TC1HALF)
 		reg |= MC13783_LED_C1_TC1HALF_BIT;
@@ -196,7 +196,7 @@ static int __devinit mc13783_leds_prepar
 	if (pdata->flags & MC13783_LED_SLEWLIMTC)
 		reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
 	if (ret)
 		goto out;
 
@@ -206,7 +206,7 @@ static int __devinit mc13783_leds_prepar
 	if (pdata->flags & MC13783_LED_SLEWLIMBL)
 		reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
 	if (ret)
 		goto out;
 
@@ -216,7 +216,7 @@ static int __devinit mc13783_leds_prepar
 	if (pdata->flags & MC13783_LED_TRIODE_TC1)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
 	if (ret)
 		goto out;
 
@@ -226,7 +226,7 @@ static int __devinit mc13783_leds_prepar
 	if (pdata->flags & MC13783_LED_TRIODE_TC2)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
 	if (ret)
 		goto out;
 
@@ -236,7 +236,7 @@ static int __devinit mc13783_leds_prepar
 	if (pdata->flags & MC13783_LED_TRIODE_TC3)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
 	if (ret)
 		goto out;
 
@@ -255,17 +255,17 @@ static int __devinit mc13783_leds_prepar
 	reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) <<
 							MC13783_LED_C0_ABREF;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
 
 out:
-	mc13783_unlock(dev);
+	mc13xxx_unlock(dev);
 	return ret;
 }
 
 static int __devinit mc13783_led_probe(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct mc13783_led_platform_data *led_cur;
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx_led_platform_data *led_cur;
 	struct mc13783_led *led, *led_dat;
 	int ret, i;
 	int init_led = 0;
@@ -351,9 +351,9 @@ err_free:
 
 static int __devexit mc13783_led_remove(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mc13783_led *led = platform_get_drvdata(pdev);
-	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
 	int i;
 
 	for (i = 0; i < pdata->num_leds; i++) {
@@ -361,16 +361,16 @@ static int __devexit mc13783_led_remove(
 		cancel_work_sync(&led[i].work);
 	}
 
-	mc13783_lock(dev);
+	mc13xxx_lock(dev);
 
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
 
-	mc13783_unlock(dev);
+	mc13xxx_unlock(dev);
 
 	kfree(led);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-net48xx.c linux-libre-3.2-gnu1/drivers/leds/leds-net48xx.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-net48xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-net48xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
+#include <linux/module.h>
 
 #define DRVNAME "net48xx-led"
 #define NET48XX_ERROR_LED_GPIO	20
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-net5501.c linux-libre-3.2-gnu1/drivers/leds/leds-net5501.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-net5501.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-net5501.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 
 #include <asm/geode.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-ns2.c linux-libre-3.2-gnu1/drivers/leds/leds-ns2.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-ns2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-ns2.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/module.h>
 #include <mach/leds-ns2.h>
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-renesas-tpu.c linux-libre-3.2-gnu1/drivers/leds/leds-renesas-tpu.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-renesas-tpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/leds/leds-renesas-tpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,357 @@
+/*
+ * LED control using Renesas TPU
+ *
+ *  Copyright (C) 2011 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/printk.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+
+enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN };
+enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON };
+
+struct r_tpu_priv {
+	struct led_classdev ldev;
+	void __iomem *mapbase;
+	struct clk *clk;
+	struct platform_device *pdev;
+	enum r_tpu_pin pin_state;
+	enum r_tpu_timer timer_state;
+	unsigned long min_rate;
+	unsigned int refresh_rate;
+	struct work_struct work;
+	enum led_brightness new_brightness;
+};
+
+static DEFINE_SPINLOCK(r_tpu_lock);
+
+#define TSTR -1 /* Timer start register (shared register) */
+#define TCR  0 /* Timer control register (+0x00) */
+#define TMDR 1 /* Timer mode register (+0x04) */
+#define TIOR 2 /* Timer I/O control register (+0x08) */
+#define TIER 3 /* Timer interrupt enable register (+0x0c) */
+#define TSR  4 /* Timer status register (+0x10) */
+#define TCNT 5 /* Timer counter (+0x14) */
+#define TGRA 6 /* Timer general register A (+0x18) */
+#define TGRB 7 /* Timer general register B (+0x1c) */
+#define TGRC 8 /* Timer general register C (+0x20) */
+#define TGRD 9 /* Timer general register D (+0x24) */
+
+static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs = reg_nr << 2;
+
+	if (reg_nr == TSTR)
+		return ioread16(base - cfg->channel_offset);
+
+	return ioread16(base + offs);
+}
+
+static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr,
+			       unsigned short value)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs = reg_nr << 2;
+
+	if (reg_nr == TSTR) {
+		iowrite16(value, base - cfg->channel_offset);
+		return;
+	}
+
+	iowrite16(value, base + offs);
+}
+
+static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	unsigned long flags, value;
+
+	/* start stop register shared by multiple timer channels */
+	spin_lock_irqsave(&r_tpu_lock, flags);
+	value = r_tpu_read(p, TSTR);
+
+	if (start)
+		value |= 1 << cfg->timer_bit;
+	else
+		value &= ~(1 << cfg->timer_bit);
+
+	r_tpu_write(p, TSTR, value);
+	spin_unlock_irqrestore(&r_tpu_lock, flags);
+}
+
+static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	int prescaler[] = { 1, 4, 16, 64 };
+	int k, ret;
+	unsigned long rate, tmp;
+
+	if (p->timer_state == R_TPU_TIMER_ON)
+		return 0;
+
+	/* wake up device and enable clock */
+	pm_runtime_get_sync(&p->pdev->dev);
+	ret = clk_enable(p->clk);
+	if (ret) {
+		dev_err(&p->pdev->dev, "cannot enable clock\n");
+		return ret;
+	}
+
+	/* make sure channel is disabled */
+	r_tpu_start_stop_ch(p, 0);
+
+	/* get clock rate after enabling it */
+	rate = clk_get_rate(p->clk);
+
+	/* pick the lowest acceptable rate */
+	for (k = 0; k < ARRAY_SIZE(prescaler); k++)
+		if ((rate / prescaler[k]) < p->min_rate)
+			break;
+
+	if (!k) {
+		dev_err(&p->pdev->dev, "clock rate mismatch\n");
+		goto err0;
+	}
+	dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
+		rate, prescaler[k - 1]);
+
+	/* clear TCNT on TGRB match, count on rising edge, set prescaler */
+	r_tpu_write(p, TCR, 0x0040 | (k - 1));
+
+	/* output 0 until TGRA, output 1 until TGRB */
+	r_tpu_write(p, TIOR, 0x0002);
+
+	rate /= prescaler[k - 1] * p->refresh_rate;
+	r_tpu_write(p, TGRB, rate);
+	dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);
+
+	tmp = (cfg->max_brightness - brightness) * rate;
+	r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
+	dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);
+
+	/* PWM mode */
+	r_tpu_write(p, TMDR, 0x0002);
+
+	/* enable channel */
+	r_tpu_start_stop_ch(p, 1);
+
+	p->timer_state = R_TPU_TIMER_ON;
+	return 0;
+ err0:
+	clk_disable(p->clk);
+	pm_runtime_put_sync(&p->pdev->dev);
+	return -ENOTSUPP;
+}
+
+static void r_tpu_disable(struct r_tpu_priv *p)
+{
+	if (p->timer_state == R_TPU_TIMER_UNUSED)
+		return;
+
+	/* disable channel */
+	r_tpu_start_stop_ch(p, 0);
+
+	/* stop clock and mark device as idle */
+	clk_disable(p->clk);
+	pm_runtime_put_sync(&p->pdev->dev);
+
+	p->timer_state = R_TPU_TIMER_UNUSED;
+}
+
+static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
+			  enum led_brightness brightness)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+
+	if (p->pin_state == new_state) {
+		if (p->pin_state == R_TPU_PIN_GPIO)
+			gpio_set_value(cfg->pin_gpio, brightness);
+		return;
+	}
+
+	if (p->pin_state == R_TPU_PIN_GPIO)
+		gpio_free(cfg->pin_gpio);
+
+	if (p->pin_state == R_TPU_PIN_GPIO_FN)
+		gpio_free(cfg->pin_gpio_fn);
+
+	if (new_state == R_TPU_PIN_GPIO) {
+		gpio_request(cfg->pin_gpio, cfg->name);
+		gpio_direction_output(cfg->pin_gpio, !!brightness);
+	}
+	if (new_state == R_TPU_PIN_GPIO_FN)
+		gpio_request(cfg->pin_gpio_fn, cfg->name);
+
+	p->pin_state = new_state;
+}
+
+static void r_tpu_work(struct work_struct *work)
+{
+	struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work);
+	enum led_brightness brightness = p->new_brightness;
+
+	r_tpu_disable(p);
+
+	/* off and maximum are handled as GPIO pins, in between PWM */
+	if ((brightness == 0) || (brightness == p->ldev.max_brightness))
+		r_tpu_set_pin(p, R_TPU_PIN_GPIO, brightness);
+	else {
+		r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0);
+		r_tpu_enable(p, brightness);
+	}
+}
+
+static void r_tpu_set_brightness(struct led_classdev *ldev,
+				 enum led_brightness brightness)
+{
+	struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev);
+	p->new_brightness = brightness;
+	schedule_work(&p->work);
+}
+
+static int __devinit r_tpu_probe(struct platform_device *pdev)
+{
+	struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
+	struct r_tpu_priv *p;
+	struct resource *res;
+	int ret = -ENXIO;
+
+	if (!cfg) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		goto err0;
+	}
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		goto err1;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (p->mapbase == NULL) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		goto err1;
+	}
+
+	/* get hold of clock */
+	p->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(p->clk)) {
+		dev_err(&pdev->dev, "cannot get clock\n");
+		ret = PTR_ERR(p->clk);
+		goto err2;
+	}
+
+	p->pdev = pdev;
+	p->pin_state = R_TPU_PIN_UNUSED;
+	p->timer_state = R_TPU_TIMER_UNUSED;
+	p->refresh_rate = cfg->refresh_rate ? cfg->refresh_rate : 100;
+	r_tpu_set_pin(p, R_TPU_PIN_GPIO, LED_OFF);
+	platform_set_drvdata(pdev, p);
+
+	INIT_WORK(&p->work, r_tpu_work);
+
+	p->ldev.name = cfg->name;
+	p->ldev.brightness = LED_OFF;
+	p->ldev.max_brightness = cfg->max_brightness;
+	p->ldev.brightness_set = r_tpu_set_brightness;
+	p->ldev.flags |= LED_CORE_SUSPENDRESUME;
+	ret = led_classdev_register(&pdev->dev, &p->ldev);
+	if (ret < 0)
+		goto err3;
+
+	/* max_brightness may be updated by the LED core code */
+	p->min_rate = p->ldev.max_brightness * p->refresh_rate;
+
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+
+ err3:
+	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+	clk_put(p->clk);
+ err2:
+	iounmap(p->mapbase);
+ err1:
+	kfree(p);
+ err0:
+	return ret;
+}
+
+static int __devexit r_tpu_remove(struct platform_device *pdev)
+{
+	struct r_tpu_priv *p = platform_get_drvdata(pdev);
+
+	r_tpu_set_brightness(&p->ldev, LED_OFF);
+	led_classdev_unregister(&p->ldev);
+	cancel_work_sync(&p->work);
+	r_tpu_disable(p);
+	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+
+	pm_runtime_disable(&pdev->dev);
+	clk_put(p->clk);
+
+	iounmap(p->mapbase);
+	kfree(p);
+	return 0;
+}
+
+static struct platform_driver r_tpu_device_driver = {
+	.probe		= r_tpu_probe,
+	.remove		= __devexit_p(r_tpu_remove),
+	.driver		= {
+		.name	= "leds-renesas-tpu",
+	}
+};
+
+static int __init r_tpu_init(void)
+{
+	return platform_driver_register(&r_tpu_device_driver);
+}
+
+static void __exit r_tpu_exit(void)
+{
+	platform_driver_unregister(&r_tpu_device_driver);
+}
+
+module_init(r_tpu_init);
+module_exit(r_tpu_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas TPU LED Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-s3c24xx.c linux-libre-3.2-gnu1/drivers/leds/leds-s3c24xx.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-s3c24xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-s3c24xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-wm831x-status.c linux-libre-3.2-gnu1/drivers/leds/leds-wm831x-status.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-wm831x-status.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-wm831x-status.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/status.h>
+#include <linux/module.h>
 
 
 struct wm831x_status {
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-wm8350.c linux-libre-3.2-gnu1/drivers/leds/leds-wm8350.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-wm8350.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-wm8350.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/mfd/wm8350/pmic.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 /* Microamps */
 static const int isink_cur[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/leds/leds-wrap.c linux-libre-3.2-gnu1/drivers/leds/leds-wrap.c
--- linux-libre-3.1-gnu1/drivers/leds/leds-wrap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/leds-wrap.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <asm/io.h>
 #include <linux/scx200_gpio.h>
+#include <linux/module.h>
 
 #define DRVNAME "wrap-led"
 #define WRAP_POWER_LED_GPIO	2
diff -druNp linux-libre-3.1-gnu1/drivers/leds/led-triggers.c linux-libre-3.2-gnu1/drivers/leds/led-triggers.c
--- linux-libre-3.1-gnu1/drivers/leds/led-triggers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/led-triggers.c	2012-01-04 18:55:44.000000000 -0500
@@ -261,9 +261,12 @@ void led_trigger_register_simple(const c
 	if (trigger) {
 		trigger->name = name;
 		err = led_trigger_register(trigger);
-		if (err < 0)
+		if (err < 0) {
+			kfree(trigger);
+			trigger = NULL;
 			printk(KERN_WARNING "LED trigger %s failed to register"
 				" (%d)\n", name, err);
+		}
 	} else
 		printk(KERN_WARNING "LED trigger %s failed to register"
 			" (no memory)\n", name);
diff -druNp linux-libre-3.1-gnu1/drivers/leds/Makefile linux-libre-3.2-gnu1/drivers/leds/Makefile
--- linux-libre-3.1-gnu1/drivers/leds/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/leds/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@ obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-am
 obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
 obj-$(CONFIG_LEDS_NET5501)		+= leds-net5501.o
 obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
-obj-$(CONFIG_LEDS_ALIX2)		+= leds-alix2.o
 obj-$(CONFIG_LEDS_COBALT_QUBE)		+= leds-cobalt-qube.o
 obj-$(CONFIG_LEDS_COBALT_RAQ)		+= leds-cobalt-raq.o
 obj-$(CONFIG_LEDS_SUNFIRE)		+= leds-sunfire.o
@@ -43,6 +42,7 @@ obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
+obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff -druNp linux-libre-3.1-gnu1/drivers/lguest/core.c linux-libre-3.2-gnu1/drivers/lguest/core.c
--- linux-libre-3.1-gnu1/drivers/lguest/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/lguest/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -232,6 +232,13 @@ int run_guest(struct lg_cpu *cpu, unsign
 			}
 		}
 
+		/*
+		 * All long-lived kernel loops need to check with this horrible
+		 * thing called the freezer.  If the Host is trying to suspend,
+		 * it stops us.
+		 */
+		try_to_freeze();
+
 		/* Check for signals */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
@@ -246,13 +253,6 @@ int run_guest(struct lg_cpu *cpu, unsign
 			try_deliver_interrupt(cpu, irq, more);
 
 		/*
-		 * All long-lived kernel loops need to check with this horrible
-		 * thing called the freezer.  If the Host is trying to suspend,
-		 * it stops us.
-		 */
-		try_to_freeze();
-
-		/*
 		 * Just make absolutely sure the Guest is still alive.  One of
 		 * those hypercalls could have been fatal, for example.
 		 */
@@ -313,7 +313,7 @@ static int __init init(void)
 	int err;
 
 	/* Lguest can't run under Xen, VMI or itself.  It does Tricky Stuff. */
-	if (paravirt_enabled()) {
+	if (get_kernel_rpl() != 0) {
 		printk("lguest is afraid of being a guest\n");
 		return -EPERM;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/lguest/lguest_device.c linux-libre-3.2-gnu1/drivers/lguest/lguest_device.c
--- linux-libre-3.1-gnu1/drivers/lguest/lguest_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/lguest/lguest_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/virtio_ring.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/paravirt.h>
diff -druNp linux-libre-3.1-gnu1/drivers/lguest/lguest_user.c linux-libre-3.2-gnu1/drivers/lguest/lguest_user.c
--- linux-libre-3.1-gnu1/drivers/lguest/lguest_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/lguest/lguest_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/eventfd.h>
 #include <linux/file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "lg.h"
 
 /*L:056
diff -druNp linux-libre-3.1-gnu1/drivers/macintosh/via-macii.c linux-libre-3.2-gnu1/drivers/macintosh/via-macii.c
--- linux-libre-3.1-gnu1/drivers/macintosh/via-macii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/macintosh/via-macii.c	2012-01-04 18:55:44.000000000 -0500
@@ -159,7 +159,7 @@ int macii_init(void)
 	err = macii_init_via();
 	if (err) goto out;
 
-	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+	err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
 			  macii_interrupt);
 	if (err) goto out;
 
diff -druNp linux-libre-3.1-gnu1/drivers/macintosh/via-maciisi.c linux-libre-3.2-gnu1/drivers/macintosh/via-maciisi.c
--- linux-libre-3.1-gnu1/drivers/macintosh/via-maciisi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/macintosh/via-maciisi.c	2012-01-04 18:55:44.000000000 -0500
@@ -122,8 +122,8 @@ maciisi_init(void)
 		return err;
 	}
 
-	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, 
-			"ADB", maciisi_interrupt)) {
+	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+			maciisi_interrupt)) {
 		printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
 		return -EAGAIN;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/Makefile linux-libre-3.2-gnu1/drivers/Makefile
--- linux-libre-3.1-gnu1/drivers/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,8 @@
 # Rewritten to use lists instead of if-statements.
 #
 
+# GPIO must come after pinctrl as gpios may need to mux pins etc
+obj-y				+= pinctrl/
 obj-y				+= gpio/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
@@ -127,3 +129,6 @@ obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
 
 # Virtualization drivers
 obj-$(CONFIG_VIRT_DRIVERS)	+= virt/
+obj-$(CONFIG_HYPERV)		+= hv/
+
+obj-$(CONFIG_PM_DEVFREQ)	+= devfreq/
diff -druNp linux-libre-3.1-gnu1/drivers/md/bitmap.c linux-libre-3.2-gnu1/drivers/md/bitmap.c
--- linux-libre-3.1-gnu1/drivers/md/bitmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/bitmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,35 +29,6 @@
 #include "md.h"
 #include "bitmap.h"
 
-/* debug macros */
-
-#define DEBUG 0
-
-#if DEBUG
-/* these are for debugging purposes only! */
-
-/* define one and only one of these */
-#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
-#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
-#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
-#define INJECT_FAULTS_4 0 /* undef */
-#define INJECT_FAULTS_5 0 /* undef */
-#define INJECT_FAULTS_6 0
-
-/* if these are defined, the driver will fail! debug only */
-#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
-#define INJECT_FATAL_FAULT_2 0 /* undef */
-#define INJECT_FATAL_FAULT_3 0 /* undef */
-#endif
-
-#ifndef PRINTK
-#  if DEBUG > 0
-#    define PRINTK(x...) printk(KERN_DEBUG x)
-#  else
-#    define PRINTK(x...)
-#  endif
-#endif
-
 static inline char *bmname(struct bitmap *bitmap)
 {
 	return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
@@ -70,16 +41,12 @@ static unsigned char *bitmap_alloc_page(
 {
 	unsigned char *page;
 
-#ifdef INJECT_FAULTS_1
-	page = NULL;
-#else
 	page = kzalloc(PAGE_SIZE, GFP_NOIO);
-#endif
 	if (!page)
 		printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
 	else
-		PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
-			bmname(bitmap), page);
+		pr_debug("%s: bitmap_alloc_page: allocated page at %p\n",
+			 bmname(bitmap), page);
 	return page;
 }
 
@@ -88,7 +55,7 @@ static unsigned char *bitmap_alloc_page(
  */
 static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
 {
-	PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+	pr_debug("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
 	kfree(page);
 }
 
@@ -133,8 +100,8 @@ __acquires(bitmap->lock)
 	spin_lock_irq(&bitmap->lock);
 
 	if (mappage == NULL) {
-		PRINTK("%s: bitmap map page allocation failed, hijacking\n",
-			bmname(bitmap));
+		pr_debug("%s: bitmap map page allocation failed, hijacking\n",
+			 bmname(bitmap));
 		/* failed - set the hijacked flag so that we can use the
 		 * pointer as a counter */
 		if (!bitmap->bp[page].map)
@@ -187,13 +154,13 @@ static void bitmap_checkfree(struct bitm
  */
 
 /* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
+static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
 				 struct page *page,
 				 unsigned long index, int size)
 {
 	/* choose a good rdev and read the page from there */
 
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t target;
 	int did_alloc = 0;
 
@@ -226,7 +193,7 @@ static struct page *read_sb_page(mddev_t
 
 }
 
-static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	/* Iterate the disks of an mddev, using rcu to protect access to the
 	 * linked list, and raising the refcount of devices we return to ensure
@@ -247,7 +214,7 @@ static mdk_rdev_t *next_active_rdev(mdk_
 		pos = &rdev->same_set;
 	}
 	list_for_each_continue_rcu(pos, &mddev->disks) {
-		rdev = list_entry(pos, mdk_rdev_t, same_set);
+		rdev = list_entry(pos, struct md_rdev, same_set);
 		if (rdev->raid_disk >= 0 &&
 		    !test_bit(Faulty, &rdev->flags)) {
 			/* this is a usable devices */
@@ -262,9 +229,9 @@ static mdk_rdev_t *next_active_rdev(mdk_
 
 static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-	mdk_rdev_t *rdev = NULL;
+	struct md_rdev *rdev = NULL;
 	struct block_device *bdev;
-	mddev_t *mddev = bitmap->mddev;
+	struct mddev *mddev = bitmap->mddev;
 
 	while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
 		int size = PAGE_SIZE;
@@ -409,8 +376,8 @@ static struct page *read_page(struct fil
 	struct buffer_head *bh;
 	sector_t block;
 
-	PRINTK("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
-			(unsigned long long)index << PAGE_SHIFT);
+	pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
+		 (unsigned long long)index << PAGE_SHIFT);
 
 	page = alloc_page(GFP_KERNEL);
 	if (!page)
@@ -868,7 +835,8 @@ static void bitmap_file_kick(struct bitm
 
 enum bitmap_page_attr {
 	BITMAP_PAGE_DIRTY = 0,     /* there are set bits that need to be synced */
-	BITMAP_PAGE_CLEAN = 1,     /* there are bits that might need to be cleared */
+	BITMAP_PAGE_PENDING = 1,   /* there are bits that are being cleaned.
+				    * i.e. counter is 1 or 2. */
 	BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */
 };
 
@@ -919,7 +887,7 @@ static void bitmap_file_set_bit(struct b
 	else
 		__set_bit_le(bit, kaddr);
 	kunmap_atomic(kaddr, KM_USER0);
-	PRINTK("set file bit %lu page %lu\n", bit, page->index);
+	pr_debug("set file bit %lu page %lu\n", bit, page->index);
 	/* record page number so it gets flushed to disk when unplug occurs */
 	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
 }
@@ -997,11 +965,7 @@ static int bitmap_init_from_disk(struct
 
 	BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
 
-#ifdef INJECT_FAULTS_3
-	outofdate = 1;
-#else
 	outofdate = bitmap->flags & BITMAP_STALE;
-#endif
 	if (outofdate)
 		printk(KERN_INFO "%s: bitmap file is out of date, doing full "
 			"recovery\n", bmname(bitmap));
@@ -1111,7 +1075,6 @@ static int bitmap_init_from_disk(struct
 					       (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
 					       needed);
 			bit_cnt++;
-			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
 		}
 	}
 
@@ -1143,9 +1106,12 @@ void bitmap_write_all(struct bitmap *bit
 	 */
 	int i;
 
+	spin_lock_irq(&bitmap->lock);
 	for (i = 0; i < bitmap->file_pages; i++)
 		set_page_attr(bitmap, bitmap->filemap[i],
 			      BITMAP_PAGE_NEEDWRITE);
+	bitmap->allclean = 0;
+	spin_unlock_irq(&bitmap->lock);
 }
 
 static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1164,7 +1130,7 @@ static bitmap_counter_t *bitmap_get_coun
  *			out to disk
  */
 
-void bitmap_daemon_work(mddev_t *mddev)
+void bitmap_daemon_work(struct mddev *mddev)
 {
 	struct bitmap *bitmap;
 	unsigned long j;
@@ -1204,17 +1170,15 @@ void bitmap_daemon_work(mddev_t *mddev)
 
 		if (page != lastpage) {
 			/* skip this page unless it's marked as needing cleaning */
-			if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) {
+			if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) {
 				int need_write = test_page_attr(bitmap, page,
 								BITMAP_PAGE_NEEDWRITE);
 				if (need_write)
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 
 				spin_unlock_irqrestore(&bitmap->lock, flags);
-				if (need_write) {
+				if (need_write)
 					write_page(bitmap, page, 0);
-					bitmap->allclean = 0;
-				}
 				spin_lock_irqsave(&bitmap->lock, flags);
 				j |= (PAGE_BITS - 1);
 				continue;
@@ -1222,12 +1186,16 @@ void bitmap_daemon_work(mddev_t *mddev)
 
 			/* grab the new page, sync and release the old */
 			if (lastpage != NULL) {
-				if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
-					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+				if (test_page_attr(bitmap, lastpage,
+						   BITMAP_PAGE_NEEDWRITE)) {
+					clear_page_attr(bitmap, lastpage,
+							BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 					write_page(bitmap, lastpage, 0);
 				} else {
-					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+					set_page_attr(bitmap, lastpage,
+						      BITMAP_PAGE_NEEDWRITE);
+					bitmap->allclean = 0;
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
 			} else
@@ -1249,19 +1217,17 @@ void bitmap_daemon_work(mddev_t *mddev)
 			}
 			spin_lock_irqsave(&bitmap->lock, flags);
 			if (!bitmap->need_sync)
-				clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+				clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+			else
+				bitmap->allclean = 0;
 		}
 		bmc = bitmap_get_counter(bitmap,
 					 (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
 					 &blocks, 0);
-		if (bmc) {
-			if (*bmc)
-				bitmap->allclean = 0;
-
-			if (*bmc == 2) {
-				*bmc = 1; /* maybe clear the bit next time */
-				set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
-			} else if (*bmc == 1 && !bitmap->need_sync) {
+		if (!bmc)
+			j |= PAGE_COUNTER_MASK;
+		else if (*bmc) {
+			if (*bmc == 1 && !bitmap->need_sync) {
 				/* we can clear the bit */
 				*bmc = 0;
 				bitmap_count_page(bitmap,
@@ -1275,13 +1241,16 @@ void bitmap_daemon_work(mddev_t *mddev)
 						  paddr);
 				else
 					__clear_bit_le(
-							file_page_offset(bitmap,
-									 j),
-							paddr);
+						file_page_offset(bitmap,
+								 j),
+						paddr);
 				kunmap_atomic(paddr, KM_USER0);
+			} else if (*bmc <= 2) {
+				*bmc = 1; /* maybe clear the bit next time */
+				set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+				bitmap->allclean = 0;
 			}
-		} else
-			j |= PAGE_COUNTER_MASK;
+		}
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 
@@ -1294,6 +1263,7 @@ void bitmap_daemon_work(mddev_t *mddev)
 			write_page(bitmap, lastpage, 0);
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+			bitmap->allclean = 0;
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 	}
@@ -1359,8 +1329,8 @@ int bitmap_startwrite(struct bitmap *bit
 		if (bw > bitmap->behind_writes_used)
 			bitmap->behind_writes_used = bw;
 
-		PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
-		       bw, bitmap->max_write_behind);
+		pr_debug("inc write-behind count %d/%lu\n",
+			 bw, bitmap->mddev->bitmap_info.max_write_behind);
 	}
 
 	while (sectors) {
@@ -1407,7 +1377,6 @@ int bitmap_startwrite(struct bitmap *bit
 		else
 			sectors = 0;
 	}
-	bitmap->allclean = 0;
 	return 0;
 }
 EXPORT_SYMBOL(bitmap_startwrite);
@@ -1420,12 +1389,10 @@ void bitmap_endwrite(struct bitmap *bitm
 	if (behind) {
 		if (atomic_dec_and_test(&bitmap->behind_writes))
 			wake_up(&bitmap->behind_wait);
-		PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
-		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+		pr_debug("dec write-behind count %d/%lu\n",
+			 atomic_read(&bitmap->behind_writes),
+			 bitmap->mddev->bitmap_info.max_write_behind);
 	}
-	if (bitmap->mddev->degraded)
-		/* Never clear bits or update events_cleared when degraded */
-		success = 0;
 
 	while (sectors) {
 		sector_t blocks;
@@ -1439,7 +1406,7 @@ void bitmap_endwrite(struct bitmap *bitm
 			return;
 		}
 
-		if (success &&
+		if (success && !bitmap->mddev->degraded &&
 		    bitmap->events_cleared < bitmap->mddev->events) {
 			bitmap->events_cleared = bitmap->mddev->events;
 			bitmap->need_sync = 1;
@@ -1453,13 +1420,14 @@ void bitmap_endwrite(struct bitmap *bitm
 			wake_up(&bitmap->overflow_wait);
 
 		(*bmc)--;
-		if (*bmc <= 2)
+		if (*bmc <= 2) {
 			set_page_attr(bitmap,
 				      filemap_get_page(
 					      bitmap,
 					      offset >> CHUNK_BLOCK_SHIFT(bitmap)),
-				      BITMAP_PAGE_CLEAN);
-
+				      BITMAP_PAGE_PENDING);
+			bitmap->allclean = 0;
+		}
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 		offset += blocks;
 		if (sectors > blocks)
@@ -1495,7 +1463,6 @@ static int __bitmap_start_sync(struct bi
 		}
 	}
 	spin_unlock_irq(&bitmap->lock);
-	bitmap->allclean = 0;
 	return rv;
 }
 
@@ -1543,15 +1510,16 @@ void bitmap_end_sync(struct bitmap *bitm
 		if (!NEEDED(*bmc) && aborted)
 			*bmc |= NEEDED_MASK;
 		else {
-			if (*bmc <= 2)
+			if (*bmc <= 2) {
 				set_page_attr(bitmap,
 					      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
-					      BITMAP_PAGE_CLEAN);
+					      BITMAP_PAGE_PENDING);
+				bitmap->allclean = 0;
+			}
 		}
 	}
  unlock:
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	bitmap->allclean = 0;
 }
 EXPORT_SYMBOL(bitmap_end_sync);
 
@@ -1622,10 +1590,10 @@ static void bitmap_set_memory_bits(struc
 		*bmc = 1 | (needed ? NEEDED_MASK : 0);
 		bitmap_count_page(bitmap, offset, 1);
 		page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
-		set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+		set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+		bitmap->allclean = 0;
 	}
 	spin_unlock_irq(&bitmap->lock);
-	bitmap->allclean = 0;
 }
 
 /* dirty the memory and file bits for bitmap chunks "s" to "e" */
@@ -1636,7 +1604,9 @@ void bitmap_dirty_bits(struct bitmap *bi
 	for (chunk = s; chunk <= e; chunk++) {
 		sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
 		bitmap_set_memory_bits(bitmap, sec, 1);
+		spin_lock_irq(&bitmap->lock);
 		bitmap_file_set_bit(bitmap, sec);
+		spin_unlock_irq(&bitmap->lock);
 		if (sec < bitmap->mddev->recovery_cp)
 			/* We are asserting that the array is dirty,
 			 * so move the recovery_cp address back so
@@ -1649,7 +1619,7 @@ void bitmap_dirty_bits(struct bitmap *bi
 /*
  * flush out any pending updates
  */
-void bitmap_flush(mddev_t *mddev)
+void bitmap_flush(struct mddev *mddev)
 {
 	struct bitmap *bitmap = mddev->bitmap;
 	long sleep;
@@ -1697,7 +1667,7 @@ static void bitmap_free(struct bitmap *b
 	kfree(bitmap);
 }
 
-void bitmap_destroy(mddev_t *mddev)
+void bitmap_destroy(struct mddev *mddev)
 {
 	struct bitmap *bitmap = mddev->bitmap;
 
@@ -1720,7 +1690,7 @@ void bitmap_destroy(mddev_t *mddev)
  * initialize the bitmap structure
  * if this returns an error, bitmap_destroy must be called to do clean up
  */
-int bitmap_create(mddev_t *mddev)
+int bitmap_create(struct mddev *mddev)
 {
 	struct bitmap *bitmap;
 	sector_t blocks = mddev->resync_max_sectors;
@@ -1802,11 +1772,8 @@ int bitmap_create(mddev_t *mddev)
 	bitmap->pages = pages;
 	bitmap->missing_pages = pages;
 
-#ifdef INJECT_FATAL_FAULT_1
-	bitmap->bp = NULL;
-#else
 	bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
-#endif
+
 	err = -ENOMEM;
 	if (!bitmap->bp)
 		goto error;
@@ -1824,7 +1791,7 @@ int bitmap_create(mddev_t *mddev)
 	return err;
 }
 
-int bitmap_load(mddev_t *mddev)
+int bitmap_load(struct mddev *mddev)
 {
 	int err = 0;
 	sector_t start = 0;
@@ -1870,7 +1837,7 @@ out:
 EXPORT_SYMBOL_GPL(bitmap_load);
 
 static ssize_t
-location_show(mddev_t *mddev, char *page)
+location_show(struct mddev *mddev, char *page)
 {
 	ssize_t len;
 	if (mddev->bitmap_info.file)
@@ -1884,7 +1851,7 @@ location_show(mddev_t *mddev, char *page
 }
 
 static ssize_t
-location_store(mddev_t *mddev, const char *buf, size_t len)
+location_store(struct mddev *mddev, const char *buf, size_t len)
 {
 
 	if (mddev->pers) {
@@ -1961,7 +1928,7 @@ static struct md_sysfs_entry bitmap_loca
 __ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
 
 static ssize_t
-timeout_show(mddev_t *mddev, char *page)
+timeout_show(struct mddev *mddev, char *page)
 {
 	ssize_t len;
 	unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ;
@@ -1975,7 +1942,7 @@ timeout_show(mddev_t *mddev, char *page)
 }
 
 static ssize_t
-timeout_store(mddev_t *mddev, const char *buf, size_t len)
+timeout_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* timeout can be set at any time */
 	unsigned long timeout;
@@ -2011,13 +1978,13 @@ static struct md_sysfs_entry bitmap_time
 __ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store);
 
 static ssize_t
-backlog_show(mddev_t *mddev, char *page)
+backlog_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind);
 }
 
 static ssize_t
-backlog_store(mddev_t *mddev, const char *buf, size_t len)
+backlog_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	unsigned long backlog;
 	int rv = strict_strtoul(buf, 10, &backlog);
@@ -2033,13 +2000,13 @@ static struct md_sysfs_entry bitmap_back
 __ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store);
 
 static ssize_t
-chunksize_show(mddev_t *mddev, char *page)
+chunksize_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize);
 }
 
 static ssize_t
-chunksize_store(mddev_t *mddev, const char *buf, size_t len)
+chunksize_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* Can only be changed when no bitmap is active */
 	int rv;
@@ -2059,13 +2026,13 @@ chunksize_store(mddev_t *mddev, const ch
 static struct md_sysfs_entry bitmap_chunksize =
 __ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
 
-static ssize_t metadata_show(mddev_t *mddev, char *page)
+static ssize_t metadata_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%s\n", (mddev->bitmap_info.external
 				      ? "external" : "internal"));
 }
 
-static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap ||
 	    mddev->bitmap_info.file ||
@@ -2083,7 +2050,7 @@ static ssize_t metadata_store(mddev_t *m
 static struct md_sysfs_entry bitmap_metadata =
 __ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
 
-static ssize_t can_clear_show(mddev_t *mddev, char *page)
+static ssize_t can_clear_show(struct mddev *mddev, char *page)
 {
 	int len;
 	if (mddev->bitmap)
@@ -2094,7 +2061,7 @@ static ssize_t can_clear_show(mddev_t *m
 	return len;
 }
 
-static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap == NULL)
 		return -ENOENT;
@@ -2113,7 +2080,7 @@ static struct md_sysfs_entry bitmap_can_
 __ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
 
 static ssize_t
-behind_writes_used_show(mddev_t *mddev, char *page)
+behind_writes_used_show(struct mddev *mddev, char *page)
 {
 	if (mddev->bitmap == NULL)
 		return sprintf(page, "0\n");
@@ -2122,7 +2089,7 @@ behind_writes_used_show(mddev_t *mddev,
 }
 
 static ssize_t
-behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
+behind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap)
 		mddev->bitmap->behind_writes_used = 0;
diff -druNp linux-libre-3.1-gnu1/drivers/md/bitmap.h linux-libre-3.2-gnu1/drivers/md/bitmap.h
--- linux-libre-3.1-gnu1/drivers/md/bitmap.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/bitmap.h	2012-01-04 18:55:44.000000000 -0500
@@ -193,7 +193,7 @@ struct bitmap {
 	unsigned long pages; /* total number of pages in the bitmap */
 	unsigned long missing_pages; /* number of pages not yet allocated */
 
-	mddev_t *mddev; /* the md device that the bitmap is for */
+	struct mddev *mddev; /* the md device that the bitmap is for */
 
 	/* bitmap chunksize -- how much data does each bit represent? */
 	unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
@@ -238,10 +238,10 @@ struct bitmap {
 /* the bitmap API */
 
 /* these are used only by md/bitmap */
-int  bitmap_create(mddev_t *mddev);
-int bitmap_load(mddev_t *mddev);
-void bitmap_flush(mddev_t *mddev);
-void bitmap_destroy(mddev_t *mddev);
+int  bitmap_create(struct mddev *mddev);
+int bitmap_load(struct mddev *mddev);
+void bitmap_flush(struct mddev *mddev);
+void bitmap_destroy(struct mddev *mddev);
 
 void bitmap_print_sb(struct bitmap *bitmap);
 void bitmap_update_sb(struct bitmap *bitmap);
@@ -262,7 +262,7 @@ void bitmap_close_sync(struct bitmap *bi
 void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
 
 void bitmap_unplug(struct bitmap *bitmap);
-void bitmap_daemon_work(mddev_t *mddev);
+void bitmap_daemon_work(struct mddev *mddev);
 #endif
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-bufio.c linux-libre-3.2-gnu1/drivers/md/dm-bufio.c
--- linux-libre-3.1-gnu1/drivers/md/dm-bufio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/dm-bufio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1700 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+#include <linux/shrinker.h>
+#include <linux/module.h>
+
+#define DM_MSG_PREFIX "bufio"
+
+/*
+ * Memory management policy:
+ *	Limit the number of buffers to DM_BUFIO_MEMORY_PERCENT of main memory
+ *	or DM_BUFIO_VMALLOC_PERCENT of vmalloc memory (whichever is lower).
+ *	Always allocate at least DM_BUFIO_MIN_BUFFERS buffers.
+ *	Start background writeback when there are DM_BUFIO_WRITEBACK_PERCENT
+ *	dirty buffers.
+ */
+#define DM_BUFIO_MIN_BUFFERS		8
+
+#define DM_BUFIO_MEMORY_PERCENT		2
+#define DM_BUFIO_VMALLOC_PERCENT	25
+#define DM_BUFIO_WRITEBACK_PERCENT	75
+
+/*
+ * Check buffer ages in this interval (seconds)
+ */
+#define DM_BUFIO_WORK_TIMER_SECS	10
+
+/*
+ * Free buffers when they are older than this (seconds)
+ */
+#define DM_BUFIO_DEFAULT_AGE_SECS	60
+
+/*
+ * The number of bvec entries that are embedded directly in the buffer.
+ * If the chunk size is larger, dm-io is used to do the io.
+ */
+#define DM_BUFIO_INLINE_VECS		16
+
+/*
+ * Buffer hash
+ */
+#define DM_BUFIO_HASH_BITS	20
+#define DM_BUFIO_HASH(block) \
+	((((block) >> DM_BUFIO_HASH_BITS) ^ (block)) & \
+	 ((1 << DM_BUFIO_HASH_BITS) - 1))
+
+/*
+ * Don't try to use kmem_cache_alloc for blocks larger than this.
+ * For explanation, see alloc_buffer_data below.
+ */
+#define DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT	(PAGE_SIZE >> 1)
+#define DM_BUFIO_BLOCK_SIZE_GFP_LIMIT	(PAGE_SIZE << (MAX_ORDER - 1))
+
+/*
+ * dm_buffer->list_mode
+ */
+#define LIST_CLEAN	0
+#define LIST_DIRTY	1
+#define LIST_SIZE	2
+
+/*
+ * Linking of buffers:
+ *	All buffers are linked to cache_hash with their hash_list field.
+ *
+ *	Clean buffers that are not being written (B_WRITING not set)
+ *	are linked to lru[LIST_CLEAN] with their lru_list field.
+ *
+ *	Dirty and clean buffers that are being written are linked to
+ *	lru[LIST_DIRTY] with their lru_list field. When the write
+ *	finishes, the buffer cannot be relinked immediately (because we
+ *	are in an interrupt context and relinking requires process
+ *	context), so some clean-not-writing buffers can be held on
+ *	dirty_lru too.  They are later added to lru in the process
+ *	context.
+ */
+struct dm_bufio_client {
+	struct mutex lock;
+
+	struct list_head lru[LIST_SIZE];
+	unsigned long n_buffers[LIST_SIZE];
+
+	struct block_device *bdev;
+	unsigned block_size;
+	unsigned char sectors_per_block_bits;
+	unsigned char pages_per_block_bits;
+	unsigned char blocks_per_page_bits;
+	unsigned aux_size;
+	void (*alloc_callback)(struct dm_buffer *);
+	void (*write_callback)(struct dm_buffer *);
+
+	struct dm_io_client *dm_io;
+
+	struct list_head reserved_buffers;
+	unsigned need_reserved_buffers;
+
+	struct hlist_head *cache_hash;
+	wait_queue_head_t free_buffer_wait;
+
+	int async_write_error;
+
+	struct list_head client_list;
+	struct shrinker shrinker;
+};
+
+/*
+ * Buffer state bits.
+ */
+#define B_READING	0
+#define B_WRITING	1
+#define B_DIRTY		2
+
+/*
+ * Describes how the block was allocated:
+ * kmem_cache_alloc(), __get_free_pages() or vmalloc().
+ * See the comment at alloc_buffer_data.
+ */
+enum data_mode {
+	DATA_MODE_SLAB = 0,
+	DATA_MODE_GET_FREE_PAGES = 1,
+	DATA_MODE_VMALLOC = 2,
+	DATA_MODE_LIMIT = 3
+};
+
+struct dm_buffer {
+	struct hlist_node hash_list;
+	struct list_head lru_list;
+	sector_t block;
+	void *data;
+	enum data_mode data_mode;
+	unsigned char list_mode;		/* LIST_* */
+	unsigned hold_count;
+	int read_error;
+	int write_error;
+	unsigned long state;
+	unsigned long last_accessed;
+	struct dm_bufio_client *c;
+	struct bio bio;
+	struct bio_vec bio_vec[DM_BUFIO_INLINE_VECS];
+};
+
+/*----------------------------------------------------------------*/
+
+static struct kmem_cache *dm_bufio_caches[PAGE_SHIFT - SECTOR_SHIFT];
+static char *dm_bufio_cache_names[PAGE_SHIFT - SECTOR_SHIFT];
+
+static inline int dm_bufio_cache_index(struct dm_bufio_client *c)
+{
+	unsigned ret = c->blocks_per_page_bits - 1;
+
+	BUG_ON(ret >= ARRAY_SIZE(dm_bufio_caches));
+
+	return ret;
+}
+
+#define DM_BUFIO_CACHE(c)	(dm_bufio_caches[dm_bufio_cache_index(c)])
+#define DM_BUFIO_CACHE_NAME(c)	(dm_bufio_cache_names[dm_bufio_cache_index(c)])
+
+#define dm_bufio_in_request()	(!!current->bio_list)
+
+static void dm_bufio_lock(struct dm_bufio_client *c)
+{
+	mutex_lock_nested(&c->lock, dm_bufio_in_request());
+}
+
+static int dm_bufio_trylock(struct dm_bufio_client *c)
+{
+	return mutex_trylock(&c->lock);
+}
+
+static void dm_bufio_unlock(struct dm_bufio_client *c)
+{
+	mutex_unlock(&c->lock);
+}
+
+/*
+ * FIXME Move to sched.h?
+ */
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+#  define dm_bufio_cond_resched()		\
+do {						\
+	if (unlikely(need_resched()))		\
+		_cond_resched();		\
+} while (0)
+#else
+#  define dm_bufio_cond_resched()                do { } while (0)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Default cache size: available memory divided by the ratio.
+ */
+static unsigned long dm_bufio_default_cache_size;
+
+/*
+ * Total cache size set by the user.
+ */
+static unsigned long dm_bufio_cache_size;
+
+/*
+ * A copy of dm_bufio_cache_size because dm_bufio_cache_size can change
+ * at any time.  If it disagrees, the user has changed cache size.
+ */
+static unsigned long dm_bufio_cache_size_latch;
+
+static DEFINE_SPINLOCK(param_spinlock);
+
+/*
+ * Buffers are freed after this timeout
+ */
+static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+
+static unsigned long dm_bufio_peak_allocated;
+static unsigned long dm_bufio_allocated_kmem_cache;
+static unsigned long dm_bufio_allocated_get_free_pages;
+static unsigned long dm_bufio_allocated_vmalloc;
+static unsigned long dm_bufio_current_allocated;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Per-client cache: dm_bufio_cache_size / dm_bufio_client_count
+ */
+static unsigned long dm_bufio_cache_size_per_client;
+
+/*
+ * The current number of clients.
+ */
+static int dm_bufio_client_count;
+
+/*
+ * The list of all clients.
+ */
+static LIST_HEAD(dm_bufio_all_clients);
+
+/*
+ * This mutex protects dm_bufio_cache_size_latch,
+ * dm_bufio_cache_size_per_client and dm_bufio_client_count
+ */
+static DEFINE_MUTEX(dm_bufio_clients_lock);
+
+/*----------------------------------------------------------------*/
+
+static void adjust_total_allocated(enum data_mode data_mode, long diff)
+{
+	static unsigned long * const class_ptr[DATA_MODE_LIMIT] = {
+		&dm_bufio_allocated_kmem_cache,
+		&dm_bufio_allocated_get_free_pages,
+		&dm_bufio_allocated_vmalloc,
+	};
+
+	spin_lock(&param_spinlock);
+
+	*class_ptr[data_mode] += diff;
+
+	dm_bufio_current_allocated += diff;
+
+	if (dm_bufio_current_allocated > dm_bufio_peak_allocated)
+		dm_bufio_peak_allocated = dm_bufio_current_allocated;
+
+	spin_unlock(&param_spinlock);
+}
+
+/*
+ * Change the number of clients and recalculate per-client limit.
+ */
+static void __cache_size_refresh(void)
+{
+	BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
+	BUG_ON(dm_bufio_client_count < 0);
+
+	dm_bufio_cache_size_latch = dm_bufio_cache_size;
+
+	barrier();
+
+	/*
+	 * Use default if set to 0 and report the actual cache size used.
+	 */
+	if (!dm_bufio_cache_size_latch) {
+		(void)cmpxchg(&dm_bufio_cache_size, 0,
+			      dm_bufio_default_cache_size);
+		dm_bufio_cache_size_latch = dm_bufio_default_cache_size;
+	}
+
+	dm_bufio_cache_size_per_client = dm_bufio_cache_size_latch /
+					 (dm_bufio_client_count ? : 1);
+}
+
+/*
+ * Allocating buffer data.
+ *
+ * Small buffers are allocated with kmem_cache, to use space optimally.
+ *
+ * For large buffers, we choose between get_free_pages and vmalloc.
+ * Each has advantages and disadvantages.
+ *
+ * __get_free_pages can randomly fail if the memory is fragmented.
+ * __vmalloc won't randomly fail, but vmalloc space is limited (it may be
+ * as low as 128M) so using it for caching is not appropriate.
+ *
+ * If the allocation may fail we use __get_free_pages. Memory fragmentation
+ * won't have a fatal effect here, but it just causes flushes of some other
+ * buffers and more I/O will be performed. Don't use __get_free_pages if it
+ * always fails (i.e. order >= MAX_ORDER).
+ *
+ * If the allocation shouldn't fail we use __vmalloc. This is only for the
+ * initial reserve allocation, so there's no risk of wasting all vmalloc
+ * space.
+ */
+static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
+			       enum data_mode *data_mode)
+{
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
+		*data_mode = DATA_MODE_SLAB;
+		return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
+	}
+
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_GFP_LIMIT &&
+	    gfp_mask & __GFP_NORETRY) {
+		*data_mode = DATA_MODE_GET_FREE_PAGES;
+		return (void *)__get_free_pages(gfp_mask,
+						c->pages_per_block_bits);
+	}
+
+	*data_mode = DATA_MODE_VMALLOC;
+	return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+}
+
+/*
+ * Free buffer's data.
+ */
+static void free_buffer_data(struct dm_bufio_client *c,
+			     void *data, enum data_mode data_mode)
+{
+	switch (data_mode) {
+	case DATA_MODE_SLAB:
+		kmem_cache_free(DM_BUFIO_CACHE(c), data);
+		break;
+
+	case DATA_MODE_GET_FREE_PAGES:
+		free_pages((unsigned long)data, c->pages_per_block_bits);
+		break;
+
+	case DATA_MODE_VMALLOC:
+		vfree(data);
+		break;
+
+	default:
+		DMCRIT("dm_bufio_free_buffer_data: bad data mode: %d",
+		       data_mode);
+		BUG();
+	}
+}
+
+/*
+ * Allocate buffer and its data.
+ */
+static struct dm_buffer *alloc_buffer(struct dm_bufio_client *c, gfp_t gfp_mask)
+{
+	struct dm_buffer *b = kmalloc(sizeof(struct dm_buffer) + c->aux_size,
+				      gfp_mask);
+
+	if (!b)
+		return NULL;
+
+	b->c = c;
+
+	b->data = alloc_buffer_data(c, gfp_mask, &b->data_mode);
+	if (!b->data) {
+		kfree(b);
+		return NULL;
+	}
+
+	adjust_total_allocated(b->data_mode, (long)c->block_size);
+
+	return b;
+}
+
+/*
+ * Free buffer and its data.
+ */
+static void free_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	adjust_total_allocated(b->data_mode, -(long)c->block_size);
+
+	free_buffer_data(c, b->data, b->data_mode);
+	kfree(b);
+}
+
+/*
+ * Link buffer to the hash list and clean or dirty queue.
+ */
+static void __link_buffer(struct dm_buffer *b, sector_t block, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	c->n_buffers[dirty]++;
+	b->block = block;
+	b->list_mode = dirty;
+	list_add(&b->lru_list, &c->lru[dirty]);
+	hlist_add_head(&b->hash_list, &c->cache_hash[DM_BUFIO_HASH(block)]);
+	b->last_accessed = jiffies;
+}
+
+/*
+ * Unlink buffer from the hash list and dirty or clean queue.
+ */
+static void __unlink_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	hlist_del(&b->hash_list);
+	list_del(&b->lru_list);
+}
+
+/*
+ * Place the buffer to the head of dirty or clean LRU queue.
+ */
+static void __relink_lru(struct dm_buffer *b, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	c->n_buffers[dirty]++;
+	b->list_mode = dirty;
+	list_del(&b->lru_list);
+	list_add(&b->lru_list, &c->lru[dirty]);
+}
+
+/*----------------------------------------------------------------
+ * Submit I/O on the buffer.
+ *
+ * Bio interface is faster but it has some problems:
+ *	the vector list is limited (increasing this limit increases
+ *	memory-consumption per buffer, so it is not viable);
+ *
+ *	the memory must be direct-mapped, not vmalloced;
+ *
+ *	the I/O driver can reject requests spuriously if it thinks that
+ *	the requests are too big for the device or if they cross a
+ *	controller-defined memory boundary.
+ *
+ * If the buffer is small enough (up to DM_BUFIO_INLINE_VECS pages) and
+ * it is not vmalloced, try using the bio interface.
+ *
+ * If the buffer is big, if it is vmalloced or if the underlying device
+ * rejects the bio because it is too large, use dm-io layer to do the I/O.
+ * The dm-io layer splits the I/O into multiple requests, avoiding the above
+ * shortcomings.
+ *--------------------------------------------------------------*/
+
+/*
+ * dm-io completion routine. It just calls b->bio.bi_end_io, pretending
+ * that the request was handled directly with bio interface.
+ */
+static void dmio_complete(unsigned long error, void *context)
+{
+	struct dm_buffer *b = context;
+
+	b->bio.bi_end_io(&b->bio, error ? -EIO : 0);
+}
+
+static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
+		     bio_end_io_t *end_io)
+{
+	int r;
+	struct dm_io_request io_req = {
+		.bi_rw = rw,
+		.notify.fn = dmio_complete,
+		.notify.context = b,
+		.client = b->c->dm_io,
+	};
+	struct dm_io_region region = {
+		.bdev = b->c->bdev,
+		.sector = block << b->c->sectors_per_block_bits,
+		.count = b->c->block_size >> SECTOR_SHIFT,
+	};
+
+	if (b->data_mode != DATA_MODE_VMALLOC) {
+		io_req.mem.type = DM_IO_KMEM;
+		io_req.mem.ptr.addr = b->data;
+	} else {
+		io_req.mem.type = DM_IO_VMA;
+		io_req.mem.ptr.vma = b->data;
+	}
+
+	b->bio.bi_end_io = end_io;
+
+	r = dm_io(&io_req, 1, &region, NULL);
+	if (r)
+		end_io(&b->bio, r);
+}
+
+static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
+			   bio_end_io_t *end_io)
+{
+	char *ptr;
+	int len;
+
+	bio_init(&b->bio);
+	b->bio.bi_io_vec = b->bio_vec;
+	b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
+	b->bio.bi_sector = block << b->c->sectors_per_block_bits;
+	b->bio.bi_bdev = b->c->bdev;
+	b->bio.bi_end_io = end_io;
+
+	/*
+	 * We assume that if len >= PAGE_SIZE ptr is page-aligned.
+	 * If len < PAGE_SIZE the buffer doesn't cross page boundary.
+	 */
+	ptr = b->data;
+	len = b->c->block_size;
+
+	if (len >= PAGE_SIZE)
+		BUG_ON((unsigned long)ptr & (PAGE_SIZE - 1));
+	else
+		BUG_ON((unsigned long)ptr & (len - 1));
+
+	do {
+		if (!bio_add_page(&b->bio, virt_to_page(ptr),
+				  len < PAGE_SIZE ? len : PAGE_SIZE,
+				  virt_to_phys(ptr) & (PAGE_SIZE - 1))) {
+			BUG_ON(b->c->block_size <= PAGE_SIZE);
+			use_dmio(b, rw, block, end_io);
+			return;
+		}
+
+		len -= PAGE_SIZE;
+		ptr += PAGE_SIZE;
+	} while (len > 0);
+
+	submit_bio(rw, &b->bio);
+}
+
+static void submit_io(struct dm_buffer *b, int rw, sector_t block,
+		      bio_end_io_t *end_io)
+{
+	if (rw == WRITE && b->c->write_callback)
+		b->c->write_callback(b);
+
+	if (b->c->block_size <= DM_BUFIO_INLINE_VECS * PAGE_SIZE &&
+	    b->data_mode != DATA_MODE_VMALLOC)
+		use_inline_bio(b, rw, block, end_io);
+	else
+		use_dmio(b, rw, block, end_io);
+}
+
+/*----------------------------------------------------------------
+ * Writing dirty buffers
+ *--------------------------------------------------------------*/
+
+/*
+ * The endio routine for write.
+ *
+ * Set the error, clear B_WRITING bit and wake anyone who was waiting on
+ * it.
+ */
+static void write_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->write_error = error;
+	if (error) {
+		struct dm_bufio_client *c = b->c;
+		(void)cmpxchg(&c->async_write_error, 0, error);
+	}
+
+	BUG_ON(!test_bit(B_WRITING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_WRITING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_WRITING);
+}
+
+/*
+ * This function is called when wait_on_bit is actually waiting.
+ */
+static int do_io_schedule(void *word)
+{
+	io_schedule();
+
+	return 0;
+}
+
+/*
+ * Initiate a write on a dirty buffer, but don't wait for it.
+ *
+ * - If the buffer is not dirty, exit.
+ * - If there some previous write going on, wait for it to finish (we can't
+ *   have two writes on the same buffer simultaneously).
+ * - Submit our write and don't wait on it. We set B_WRITING indicating
+ *   that there is a write in progress.
+ */
+static void __write_dirty_buffer(struct dm_buffer *b)
+{
+	if (!test_bit(B_DIRTY, &b->state))
+		return;
+
+	clear_bit(B_DIRTY, &b->state);
+	wait_on_bit_lock(&b->state, B_WRITING,
+			 do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	submit_io(b, WRITE, b->block, write_endio);
+}
+
+/*
+ * Wait until any activity on the buffer finishes.  Possibly write the
+ * buffer if it is dirty.  When this function finishes, there is no I/O
+ * running on the buffer and the buffer is not dirty.
+ */
+static void __make_buffer_clean(struct dm_buffer *b)
+{
+	BUG_ON(b->hold_count);
+
+	if (!b->state)	/* fast case */
+		return;
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	__write_dirty_buffer(b);
+	wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+/*
+ * Find some buffer that is not held by anybody, clean it, unlink it and
+ * return it.
+ */
+static struct dm_buffer *__get_unclaimed_buffer(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_CLEAN], lru_list) {
+		BUG_ON(test_bit(B_WRITING, &b->state));
+		BUG_ON(test_bit(B_DIRTY, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	return NULL;
+}
+
+/*
+ * Wait until some other threads free some buffer or release hold count on
+ * some buffer.
+ *
+ * This function is entered with c->lock held, drops it and regains it
+ * before exiting.
+ */
+static void __wait_for_free_buffer(struct dm_bufio_client *c)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(&c->free_buffer_wait, &wait);
+	set_task_state(current, TASK_UNINTERRUPTIBLE);
+	dm_bufio_unlock(c);
+
+	io_schedule();
+
+	set_task_state(current, TASK_RUNNING);
+	remove_wait_queue(&c->free_buffer_wait, &wait);
+
+	dm_bufio_lock(c);
+}
+
+/*
+ * Allocate a new buffer. If the allocation is not possible, wait until
+ * some other thread frees a buffer.
+ *
+ * May drop the lock and regain it.
+ */
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	/*
+	 * dm-bufio is resistant to allocation failures (it just keeps
+	 * one buffer reserved in cases all the allocations fail).
+	 * So set flags to not try too hard:
+	 *	GFP_NOIO: don't recurse into the I/O layer
+	 *	__GFP_NORETRY: don't retry and rather return failure
+	 *	__GFP_NOMEMALLOC: don't use emergency reserves
+	 *	__GFP_NOWARN: don't print a warning in case of failure
+	 *
+	 * For debugging, if we set the cache size to 1, no new buffers will
+	 * be allocated.
+	 */
+	while (1) {
+		if (dm_bufio_cache_size_latch != 1) {
+			b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+			if (b)
+				return b;
+		}
+
+		if (!list_empty(&c->reserved_buffers)) {
+			b = list_entry(c->reserved_buffers.next,
+				       struct dm_buffer, lru_list);
+			list_del(&b->lru_list);
+			c->need_reserved_buffers++;
+
+			return b;
+		}
+
+		b = __get_unclaimed_buffer(c);
+		if (b)
+			return b;
+
+		__wait_for_free_buffer(c);
+	}
+}
+
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+
+	if (c->alloc_callback)
+		c->alloc_callback(b);
+
+	return b;
+}
+
+/*
+ * Free a buffer and wake other threads waiting for free buffers.
+ */
+static void __free_buffer_wake(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	if (!c->need_reserved_buffers)
+		free_buffer(b);
+	else {
+		list_add(&b->lru_list, &c->reserved_buffers);
+		c->need_reserved_buffers--;
+	}
+
+	wake_up(&c->free_buffer_wait);
+}
+
+static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait)
+{
+	struct dm_buffer *b, *tmp;
+
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state)) {
+			__relink_lru(b, LIST_CLEAN);
+			continue;
+		}
+
+		if (no_wait && test_bit(B_WRITING, &b->state))
+			return;
+
+		__write_dirty_buffer(b);
+		dm_bufio_cond_resched();
+	}
+}
+
+/*
+ * Get writeback threshold and buffer limit for a given client.
+ */
+static void __get_memory_limit(struct dm_bufio_client *c,
+			       unsigned long *threshold_buffers,
+			       unsigned long *limit_buffers)
+{
+	unsigned long buffers;
+
+	if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+		mutex_lock(&dm_bufio_clients_lock);
+		__cache_size_refresh();
+		mutex_unlock(&dm_bufio_clients_lock);
+	}
+
+	buffers = dm_bufio_cache_size_per_client >>
+		  (c->sectors_per_block_bits + SECTOR_SHIFT);
+
+	if (buffers < DM_BUFIO_MIN_BUFFERS)
+		buffers = DM_BUFIO_MIN_BUFFERS;
+
+	*limit_buffers = buffers;
+	*threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
+}
+
+/*
+ * Check if we're over watermark.
+ * If we are over threshold_buffers, start freeing buffers.
+ * If we're over "limit_buffers", block until we get under the limit.
+ */
+static void __check_watermark(struct dm_bufio_client *c)
+{
+	unsigned long threshold_buffers, limit_buffers;
+
+	__get_memory_limit(c, &threshold_buffers, &limit_buffers);
+
+	while (c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY] >
+	       limit_buffers) {
+
+		struct dm_buffer *b = __get_unclaimed_buffer(c);
+
+		if (!b)
+			return;
+
+		__free_buffer_wake(b);
+		dm_bufio_cond_resched();
+	}
+
+	if (c->n_buffers[LIST_DIRTY] > threshold_buffers)
+		__write_dirty_buffers_async(c, 1);
+}
+
+/*
+ * Find a buffer in the hash.
+ */
+static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
+{
+	struct dm_buffer *b;
+	struct hlist_node *hn;
+
+	hlist_for_each_entry(b, hn, &c->cache_hash[DM_BUFIO_HASH(block)],
+			     hash_list) {
+		dm_bufio_cond_resched();
+		if (b->block == block)
+			return b;
+	}
+
+	return NULL;
+}
+
+/*----------------------------------------------------------------
+ * Getting a buffer
+ *--------------------------------------------------------------*/
+
+enum new_flag {
+	NF_FRESH = 0,
+	NF_READ = 1,
+	NF_GET = 2
+};
+
+static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
+				     enum new_flag nf, struct dm_buffer **bp,
+				     int *need_submit)
+{
+	struct dm_buffer *b, *new_b = NULL;
+
+	*need_submit = 0;
+
+	b = __find(c, block);
+	if (b) {
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	if (nf == NF_GET)
+		return NULL;
+
+	new_b = __alloc_buffer_wait(c);
+
+	/*
+	 * We've had a period where the mutex was unlocked, so need to
+	 * recheck the hash table.
+	 */
+	b = __find(c, block);
+	if (b) {
+		__free_buffer_wake(new_b);
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	__check_watermark(c);
+
+	b = new_b;
+	b->hold_count = 1;
+	b->read_error = 0;
+	b->write_error = 0;
+	__link_buffer(b, block, LIST_CLEAN);
+
+	if (nf == NF_FRESH) {
+		b->state = 0;
+		return b;
+	}
+
+	b->state = 1 << B_READING;
+	*need_submit = 1;
+
+	return b;
+}
+
+/*
+ * The endio routine for reading: set the error, clear the bit and wake up
+ * anyone waiting on the buffer.
+ */
+static void read_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->read_error = error;
+
+	BUG_ON(!test_bit(B_READING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_READING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_READING);
+}
+
+/*
+ * A common routine for dm_bufio_new and dm_bufio_read.  Operation of these
+ * functions is similar except that dm_bufio_new doesn't read the
+ * buffer from the disk (assuming that the caller overwrites all the data
+ * and uses dm_bufio_mark_buffer_dirty to write new data back).
+ */
+static void *new_read(struct dm_bufio_client *c, sector_t block,
+		      enum new_flag nf, struct dm_buffer **bp)
+{
+	int need_submit;
+	struct dm_buffer *b;
+
+	dm_bufio_lock(c);
+	b = __bufio_new(c, block, nf, bp, &need_submit);
+	dm_bufio_unlock(c);
+
+	if (!b || IS_ERR(b))
+		return b;
+
+	if (need_submit)
+		submit_io(b, READ, b->block, read_endio);
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	if (b->read_error) {
+		int error = b->read_error;
+
+		dm_bufio_release(b);
+
+		return ERR_PTR(error);
+	}
+
+	*bp = b;
+
+	return b->data;
+}
+
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	return new_read(c, block, NF_GET, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get);
+
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_READ, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_read);
+
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_FRESH, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_new);
+
+void dm_bufio_release(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	BUG_ON(test_bit(B_READING, &b->state));
+	BUG_ON(!b->hold_count);
+
+	b->hold_count--;
+	if (!b->hold_count) {
+		wake_up(&c->free_buffer_wait);
+
+		/*
+		 * If there were errors on the buffer, and the buffer is not
+		 * to be written, free the buffer. There is no point in caching
+		 * invalid buffer.
+		 */
+		if ((b->read_error || b->write_error) &&
+		    !test_bit(B_WRITING, &b->state) &&
+		    !test_bit(B_DIRTY, &b->state)) {
+			__unlink_buffer(b);
+			__free_buffer_wake(b);
+		}
+	}
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release);
+
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	if (!test_and_set_bit(B_DIRTY, &b->state))
+		__relink_lru(b, LIST_DIRTY);
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_mark_buffer_dirty);
+
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async);
+
+/*
+ * For performance, it is essential that the buffers are written asynchronously
+ * and simultaneously (so that the block layer can merge the writes) and then
+ * waited upon.
+ *
+ * Finally, we flush hardware disk cache.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
+{
+	int a, f;
+	unsigned long buffers_processed = 0;
+	struct dm_buffer *b, *tmp;
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+
+again:
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		int dropped_lock = 0;
+
+		if (buffers_processed < c->n_buffers[LIST_DIRTY])
+			buffers_processed++;
+
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (test_bit(B_WRITING, &b->state)) {
+			if (buffers_processed < c->n_buffers[LIST_DIRTY]) {
+				dropped_lock = 1;
+				b->hold_count++;
+				dm_bufio_unlock(c);
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+				dm_bufio_lock(c);
+				b->hold_count--;
+			} else
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+		}
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state))
+			__relink_lru(b, LIST_CLEAN);
+
+		dm_bufio_cond_resched();
+
+		/*
+		 * If we dropped the lock, the list is no longer consistent,
+		 * so we must restart the search.
+		 *
+		 * In the most common case, the buffer just processed is
+		 * relinked to the clean list, so we won't loop scanning the
+		 * same buffer again and again.
+		 *
+		 * This may livelock if there is another thread simultaneously
+		 * dirtying buffers, so we count the number of buffers walked
+		 * and if it exceeds the total number of buffers, it means that
+		 * someone is doing some writes simultaneously with us.  In
+		 * this case, stop, dropping the lock.
+		 */
+		if (dropped_lock)
+			goto again;
+	}
+	wake_up(&c->free_buffer_wait);
+	dm_bufio_unlock(c);
+
+	a = xchg(&c->async_write_error, 0);
+	f = dm_bufio_issue_flush(c);
+	if (a)
+		return a;
+
+	return f;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers);
+
+/*
+ * Use dm-io to send and empty barrier flush the device.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c)
+{
+	struct dm_io_request io_req = {
+		.bi_rw = REQ_FLUSH,
+		.mem.type = DM_IO_KMEM,
+		.mem.ptr.addr = NULL,
+		.client = c->dm_io,
+	};
+	struct dm_io_region io_reg = {
+		.bdev = c->bdev,
+		.sector = 0,
+		.count = 0,
+	};
+
+	BUG_ON(dm_bufio_in_request());
+
+	return dm_io(&io_req, 1, &io_reg, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
+
+/*
+ * We first delete any other buffer that may be at that new location.
+ *
+ * Then, we write the buffer to the original location if it was dirty.
+ *
+ * Then, if we are the only one who is holding the buffer, relink the buffer
+ * in the hash queue for the new location.
+ *
+ * If there was someone else holding the buffer, we write it to the new
+ * location but not relink it, because that other user needs to have the buffer
+ * at the same place.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)
+{
+	struct dm_bufio_client *c = b->c;
+	struct dm_buffer *new;
+
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+
+retry:
+	new = __find(c, new_block);
+	if (new) {
+		if (new->hold_count) {
+			__wait_for_free_buffer(c);
+			goto retry;
+		}
+
+		/*
+		 * FIXME: Is there any point waiting for a write that's going
+		 * to be overwritten in a bit?
+		 */
+		__make_buffer_clean(new);
+		__unlink_buffer(new);
+		__free_buffer_wake(new);
+	}
+
+	BUG_ON(!b->hold_count);
+	BUG_ON(test_bit(B_READING, &b->state));
+
+	__write_dirty_buffer(b);
+	if (b->hold_count == 1) {
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		set_bit(B_DIRTY, &b->state);
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, LIST_DIRTY);
+	} else {
+		sector_t old_block;
+		wait_on_bit_lock(&b->state, B_WRITING,
+				 do_io_schedule, TASK_UNINTERRUPTIBLE);
+		/*
+		 * Relink buffer to "new_block" so that write_callback
+		 * sees "new_block" as a block number.
+		 * After the write, link the buffer back to old_block.
+		 * All this must be done in bufio lock, so that block number
+		 * change isn't visible to other threads.
+		 */
+		old_block = b->block;
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, b->list_mode);
+		submit_io(b, WRITE, new_block, write_endio);
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		__unlink_buffer(b);
+		__link_buffer(b, old_block, b->list_mode);
+	}
+
+	dm_bufio_unlock(c);
+	dm_bufio_release(b);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release_move);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+{
+	return c->block_size;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
+
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+{
+	return i_size_read(c->bdev->bd_inode) >>
+			   (SECTOR_SHIFT + c->sectors_per_block_bits);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
+
+sector_t dm_bufio_get_block_number(struct dm_buffer *b)
+{
+	return b->block;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_number);
+
+void *dm_bufio_get_block_data(struct dm_buffer *b)
+{
+	return b->data;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_data);
+
+void *dm_bufio_get_aux_data(struct dm_buffer *b)
+{
+	return b + 1;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_aux_data);
+
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b)
+{
+	return b->c;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_client);
+
+static void drop_buffers(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+	int i;
+
+	BUG_ON(dm_bufio_in_request());
+
+	/*
+	 * An optimization so that the buffers are not written one-by-one.
+	 */
+	dm_bufio_write_dirty_buffers_async(c);
+
+	dm_bufio_lock(c);
+
+	while ((b = __get_unclaimed_buffer(c)))
+		__free_buffer_wake(b);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		list_for_each_entry(b, &c->lru[i], lru_list)
+			DMERR("leaked buffer %llx, hold count %u, list %d",
+			      (unsigned long long)b->block, b->hold_count, i);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(!list_empty(&c->lru[i]));
+
+	dm_bufio_unlock(c);
+}
+
+/*
+ * Test if the buffer is unused and too old, and commit it.
+ * At if noio is set, we must not do any I/O because we hold
+ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to
+ * different bufio client.
+ */
+static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
+				unsigned long max_jiffies)
+{
+	if (jiffies - b->last_accessed < max_jiffies)
+		return 1;
+
+	if (!(gfp & __GFP_IO)) {
+		if (test_bit(B_READING, &b->state) ||
+		    test_bit(B_WRITING, &b->state) ||
+		    test_bit(B_DIRTY, &b->state))
+			return 1;
+	}
+
+	if (b->hold_count)
+		return 1;
+
+	__make_buffer_clean(b);
+	__unlink_buffer(b);
+	__free_buffer_wake(b);
+
+	return 0;
+}
+
+static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+		   struct shrink_control *sc)
+{
+	int l;
+	struct dm_buffer *b, *tmp;
+
+	for (l = 0; l < LIST_SIZE; l++) {
+		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list)
+			if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) &&
+			    !--nr_to_scan)
+				return;
+		dm_bufio_cond_resched();
+	}
+}
+
+static int shrink(struct shrinker *shrinker, struct shrink_control *sc)
+{
+	struct dm_bufio_client *c =
+	    container_of(shrinker, struct dm_bufio_client, shrinker);
+	unsigned long r;
+	unsigned long nr_to_scan = sc->nr_to_scan;
+
+	if (sc->gfp_mask & __GFP_IO)
+		dm_bufio_lock(c);
+	else if (!dm_bufio_trylock(c))
+		return !nr_to_scan ? 0 : -1;
+
+	if (nr_to_scan)
+		__scan(c, nr_to_scan, sc);
+
+	r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+	if (r > INT_MAX)
+		r = INT_MAX;
+
+	dm_bufio_unlock(c);
+
+	return r;
+}
+
+/*
+ * Create the buffering interface
+ */
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+					       unsigned reserved_buffers, unsigned aux_size,
+					       void (*alloc_callback)(struct dm_buffer *),
+					       void (*write_callback)(struct dm_buffer *))
+{
+	int r;
+	struct dm_bufio_client *c;
+	unsigned i;
+
+	BUG_ON(block_size < 1 << SECTOR_SHIFT ||
+	       (block_size & (block_size - 1)));
+
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		r = -ENOMEM;
+		goto bad_client;
+	}
+	c->cache_hash = vmalloc(sizeof(struct hlist_head) << DM_BUFIO_HASH_BITS);
+	if (!c->cache_hash) {
+		r = -ENOMEM;
+		goto bad_hash;
+	}
+
+	c->bdev = bdev;
+	c->block_size = block_size;
+	c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT;
+	c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ?
+				  ffs(block_size) - 1 - PAGE_SHIFT : 0;
+	c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ?
+				  PAGE_SHIFT - (ffs(block_size) - 1) : 0);
+
+	c->aux_size = aux_size;
+	c->alloc_callback = alloc_callback;
+	c->write_callback = write_callback;
+
+	for (i = 0; i < LIST_SIZE; i++) {
+		INIT_LIST_HEAD(&c->lru[i]);
+		c->n_buffers[i] = 0;
+	}
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		INIT_HLIST_HEAD(&c->cache_hash[i]);
+
+	mutex_init(&c->lock);
+	INIT_LIST_HEAD(&c->reserved_buffers);
+	c->need_reserved_buffers = reserved_buffers;
+
+	init_waitqueue_head(&c->free_buffer_wait);
+	c->async_write_error = 0;
+
+	c->dm_io = dm_io_client_create();
+	if (IS_ERR(c->dm_io)) {
+		r = PTR_ERR(c->dm_io);
+		goto bad_dm_io;
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	if (c->blocks_per_page_bits) {
+		if (!DM_BUFIO_CACHE_NAME(c)) {
+			DM_BUFIO_CACHE_NAME(c) = kasprintf(GFP_KERNEL, "dm_bufio_cache-%u", c->block_size);
+			if (!DM_BUFIO_CACHE_NAME(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+
+		if (!DM_BUFIO_CACHE(c)) {
+			DM_BUFIO_CACHE(c) = kmem_cache_create(DM_BUFIO_CACHE_NAME(c),
+							      c->block_size,
+							      c->block_size, 0, NULL);
+			if (!DM_BUFIO_CACHE(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	while (c->need_reserved_buffers) {
+		struct dm_buffer *b = alloc_buffer(c, GFP_KERNEL);
+
+		if (!b) {
+			r = -ENOMEM;
+			goto bad_buffer;
+		}
+		__free_buffer_wake(b);
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	dm_bufio_client_count++;
+	list_add(&c->client_list, &dm_bufio_all_clients);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	c->shrinker.shrink = shrink;
+	c->shrinker.seeks = 1;
+	c->shrinker.batch = 0;
+	register_shrinker(&c->shrinker);
+
+	return c;
+
+bad_buffer:
+bad_cache:
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+	dm_io_client_destroy(c->dm_io);
+bad_dm_io:
+	vfree(c->cache_hash);
+bad_hash:
+	kfree(c);
+bad_client:
+	return ERR_PTR(r);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_create);
+
+/*
+ * Free the buffering interface.
+ * It is required that there are no references on any buffers.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c)
+{
+	unsigned i;
+
+	drop_buffers(c);
+
+	unregister_shrinker(&c->shrinker);
+
+	mutex_lock(&dm_bufio_clients_lock);
+
+	list_del(&c->client_list);
+	dm_bufio_client_count--;
+	__cache_size_refresh();
+
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		BUG_ON(!hlist_empty(&c->cache_hash[i]));
+
+	BUG_ON(c->need_reserved_buffers);
+
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+
+	for (i = 0; i < LIST_SIZE; i++)
+		if (c->n_buffers[i])
+			DMERR("leaked buffer count %d: %ld", i, c->n_buffers[i]);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(c->n_buffers[i]);
+
+	dm_io_client_destroy(c->dm_io);
+	vfree(c->cache_hash);
+	kfree(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
+
+static void cleanup_old_buffers(void)
+{
+	unsigned long max_age = dm_bufio_max_age;
+	struct dm_bufio_client *c;
+
+	barrier();
+
+	if (max_age > ULONG_MAX / HZ)
+		max_age = ULONG_MAX / HZ;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	list_for_each_entry(c, &dm_bufio_all_clients, client_list) {
+		if (!dm_bufio_trylock(c))
+			continue;
+
+		while (!list_empty(&c->lru[LIST_CLEAN])) {
+			struct dm_buffer *b;
+			b = list_entry(c->lru[LIST_CLEAN].prev,
+				       struct dm_buffer, lru_list);
+			if (__cleanup_old_buffer(b, 0, max_age * HZ))
+				break;
+			dm_bufio_cond_resched();
+		}
+
+		dm_bufio_unlock(c);
+		dm_bufio_cond_resched();
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+}
+
+static struct workqueue_struct *dm_bufio_wq;
+static struct delayed_work dm_bufio_work;
+
+static void work_fn(struct work_struct *w)
+{
+	cleanup_old_buffers();
+
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+}
+
+/*----------------------------------------------------------------
+ * Module setup
+ *--------------------------------------------------------------*/
+
+/*
+ * This is called only once for the whole dm_bufio module.
+ * It initializes memory limit.
+ */
+static int __init dm_bufio_init(void)
+{
+	__u64 mem;
+
+	memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
+	memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
+
+	mem = (__u64)((totalram_pages - totalhigh_pages) *
+		      DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
+
+	if (mem > ULONG_MAX)
+		mem = ULONG_MAX;
+
+#ifdef CONFIG_MMU
+	/*
+	 * Get the size of vmalloc space the same way as VMALLOC_TOTAL
+	 * in fs/proc/internal.h
+	 */
+	if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
+		mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
+#endif
+
+	dm_bufio_default_cache_size = mem;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	dm_bufio_wq = create_singlethread_workqueue("dm_bufio_cache");
+	if (!dm_bufio_wq)
+		return -ENOMEM;
+
+	INIT_DELAYED_WORK(&dm_bufio_work, work_fn);
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+
+	return 0;
+}
+
+/*
+ * This is called once when unloading the dm_bufio module.
+ */
+static void __exit dm_bufio_exit(void)
+{
+	int bug = 0;
+	int i;
+
+	cancel_delayed_work_sync(&dm_bufio_work);
+	destroy_workqueue(dm_bufio_wq);
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) {
+		struct kmem_cache *kc = dm_bufio_caches[i];
+
+		if (kc)
+			kmem_cache_destroy(kc);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
+		kfree(dm_bufio_cache_names[i]);
+
+	if (dm_bufio_client_count) {
+		DMCRIT("%s: dm_bufio_client_count leaked: %d",
+			__func__, dm_bufio_client_count);
+		bug = 1;
+	}
+
+	if (dm_bufio_current_allocated) {
+		DMCRIT("%s: dm_bufio_current_allocated leaked: %lu",
+			__func__, dm_bufio_current_allocated);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_get_free_pages) {
+		DMCRIT("%s: dm_bufio_allocated_get_free_pages leaked: %lu",
+		       __func__, dm_bufio_allocated_get_free_pages);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_vmalloc) {
+		DMCRIT("%s: dm_bufio_vmalloc leaked: %lu",
+		       __func__, dm_bufio_allocated_vmalloc);
+		bug = 1;
+	}
+
+	if (bug)
+		BUG();
+}
+
+module_init(dm_bufio_init)
+module_exit(dm_bufio_exit)
+
+module_param_named(max_cache_size_bytes, dm_bufio_cache_size, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
+
+module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
+
+module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
+
+module_param_named(allocated_kmem_cache_bytes, dm_bufio_allocated_kmem_cache, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_kmem_cache_bytes, "Memory allocated with kmem_cache_alloc");
+
+module_param_named(allocated_get_free_pages_bytes, dm_bufio_allocated_get_free_pages, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_get_free_pages_bytes, "Memory allocated with get_free_pages");
+
+module_param_named(allocated_vmalloc_bytes, dm_bufio_allocated_vmalloc, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_vmalloc_bytes, "Memory allocated with vmalloc");
+
+module_param_named(current_allocated_bytes, dm_bufio_current_allocated, ulong, S_IRUGO);
+MODULE_PARM_DESC(current_allocated_bytes, "Memory currently used by the cache");
+
+MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>");
+MODULE_DESCRIPTION(DM_NAME " buffered I/O library");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-bufio.h linux-libre-3.2-gnu1/drivers/md/dm-bufio.h
--- linux-libre-3.1-gnu1/drivers/md/dm-bufio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/dm-bufio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BUFIO_H
+#define DM_BUFIO_H
+
+#include <linux/blkdev.h>
+#include <linux/types.h>
+
+/*----------------------------------------------------------------*/
+
+struct dm_bufio_client;
+struct dm_buffer;
+
+/*
+ * Create a buffered IO cache on a given device
+ */
+struct dm_bufio_client *
+dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+		       unsigned reserved_buffers, unsigned aux_size,
+		       void (*alloc_callback)(struct dm_buffer *),
+		       void (*write_callback)(struct dm_buffer *));
+
+/*
+ * Release a buffered IO cache.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c);
+
+/*
+ * WARNING: to avoid deadlocks, these conditions are observed:
+ *
+ * - At most one thread can hold at most "reserved_buffers" simultaneously.
+ * - Each other threads can hold at most one buffer.
+ * - Threads which call only dm_bufio_get can hold unlimited number of
+ *   buffers.
+ */
+
+/*
+ * Read a given block from disk. Returns pointer to data.  Returns a
+ * pointer to dm_buffer that can be used to release the buffer or to make
+ * it dirty.
+ */
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but return buffer from cache, don't read
+ * it. If the buffer is not in the cache, return NULL.
+ */
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but don't read anything from the disk.  It is
+ * expected that the caller initializes the buffer and marks it dirty.
+ */
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Release a reference obtained with dm_bufio_{read,get,new}. The data
+ * pointer and dm_buffer pointer is no longer valid after this call.
+ */
+void dm_bufio_release(struct dm_buffer *b);
+
+/*
+ * Mark a buffer dirty. It should be called after the buffer is modified.
+ *
+ * In case of memory pressure, the buffer may be written after
+ * dm_bufio_mark_buffer_dirty, but before dm_bufio_write_dirty_buffers.  So
+ * dm_bufio_write_dirty_buffers guarantees that the buffer is on-disk but
+ * the actual writing may occur earlier.
+ */
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
+
+/*
+ * Initiate writing of dirty buffers, without waiting for completion.
+ */
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c);
+
+/*
+ * Write all dirty buffers. Guarantees that all dirty buffers created prior
+ * to this call are on disk when this call exits.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c);
+
+/*
+ * Send an empty write barrier to the device to flush hardware disk cache.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c);
+
+/*
+ * Like dm_bufio_release but also move the buffer to the new
+ * block. dm_bufio_write_dirty_buffers is needed to commit the new block.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_block_number(struct dm_buffer *b);
+void *dm_bufio_get_block_data(struct dm_buffer *b);
+void *dm_bufio_get_aux_data(struct dm_buffer *b);
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm.c linux-libre-3.2-gnu1/drivers/md/dm.c
--- linux-libre-3.1-gnu1/drivers/md/dm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,16 @@
 
 #define DM_MSG_PREFIX "core"
 
+#ifdef CONFIG_PRINTK
+/*
+ * ratelimit state to be used in DMXXX_LIMIT().
+ */
+DEFINE_RATELIMIT_STATE(dm_ratelimit_state,
+		       DEFAULT_RATELIMIT_INTERVAL,
+		       DEFAULT_RATELIMIT_BURST);
+EXPORT_SYMBOL(dm_ratelimit_state);
+#endif
+
 /*
  * Cookies are numeric values sent with CHANGE and REMOVE
  * uevents while resuming, removing or renaming the device.
@@ -130,6 +140,8 @@ struct mapped_device {
 	/* Protect queue and type against concurrent access. */
 	struct mutex type_lock;
 
+	struct target_type *immutable_target_type;
+
 	struct gendisk *disk;
 	char name[16];
 
@@ -180,9 +192,6 @@ struct mapped_device {
 	/* forced geometry settings */
 	struct hd_geometry geometry;
 
-	/* For saving the address of __make_request for request based dm */
-	make_request_fn *saved_make_request_fn;
-
 	/* sysfs handle */
 	struct kobject kobj;
 
@@ -1391,7 +1400,7 @@ out:
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
  */
-static int _dm_request(struct request_queue *q, struct bio *bio)
+static void _dm_request(struct request_queue *q, struct bio *bio)
 {
 	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
@@ -1412,19 +1421,12 @@ static int _dm_request(struct request_qu
 			queue_io(md, bio);
 		else
 			bio_io_error(bio);
-		return 0;
+		return;
 	}
 
 	__split_and_process_bio(md, bio);
 	up_read(&md->io_lock);
-	return 0;
-}
-
-static int dm_make_request(struct request_queue *q, struct bio *bio)
-{
-	struct mapped_device *md = q->queuedata;
-
-	return md->saved_make_request_fn(q, bio); /* call __make_request() */
+	return;
 }
 
 static int dm_request_based(struct mapped_device *md)
@@ -1432,14 +1434,14 @@ static int dm_request_based(struct mappe
 	return blk_queue_stackable(md->queue);
 }
 
-static int dm_request(struct request_queue *q, struct bio *bio)
+static void dm_request(struct request_queue *q, struct bio *bio)
 {
 	struct mapped_device *md = q->queuedata;
 
 	if (dm_request_based(md))
-		return dm_make_request(q, bio);
-
-	return _dm_request(q, bio);
+		blk_queue_bio(q, bio);
+	else
+		_dm_request(q, bio);
 }
 
 void dm_dispatch_request(struct request *rq)
@@ -2086,6 +2088,8 @@ static struct dm_table *__bind(struct ma
 	write_lock_irqsave(&md->map_lock, flags);
 	old_map = md->map;
 	md->map = t;
+	md->immutable_target_type = dm_table_get_immutable_target_type(t);
+
 	dm_table_set_restrictions(t, q, limits);
 	if (merge_is_optional)
 		set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
@@ -2156,6 +2160,11 @@ unsigned dm_get_md_type(struct mapped_de
 	return md->type;
 }
 
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
+{
+	return md->immutable_target_type;
+}
+
 /*
  * Fully initialize a request-based queue (->elevator, ->request_fn, etc).
  */
@@ -2172,7 +2181,6 @@ static int dm_init_request_based_queue(s
 		return 0;
 
 	md->queue = q;
-	md->saved_make_request_fn = md->queue->make_request_fn;
 	dm_init_md_queue(md);
 	blk_queue_softirq_done(md->queue, dm_softirq_done);
 	blk_queue_prep_rq(md->queue, dm_prep_fn);
@@ -2231,6 +2239,7 @@ struct mapped_device *dm_get_md(dev_t de
 
 	return md;
 }
+EXPORT_SYMBOL_GPL(dm_get_md);
 
 void *dm_get_mdptr(struct mapped_device *md)
 {
@@ -2316,7 +2325,6 @@ static int dm_wait_for_completion(struct
 	while (1) {
 		set_current_state(interruptible);
 
-		smp_mb();
 		if (!md_in_flight(md))
 			break;
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-exception-store.c linux-libre-3.2-gnu1/drivers/md/dm-exception-store.c
--- linux-libre-3.1-gnu1/drivers/md/dm-exception-store.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-exception-store.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #define DM_MSG_PREFIX "snapshot exception stores"
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm.h linux-libre-3.2-gnu1/drivers/md/dm.h
--- linux-libre-3.1-gnu1/drivers/md/dm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@ int dm_table_resume_targets(struct dm_ta
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 int dm_table_any_busy_target(struct dm_table *t);
 unsigned dm_table_get_type(struct dm_table *t);
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 bool dm_table_supports_discards(struct dm_table *t);
 int dm_table_alloc_md_mempools(struct dm_table *t);
@@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_devic
 void dm_unlock_md_type(struct mapped_device *md);
 void dm_set_md_type(struct mapped_device *md, unsigned type);
 unsigned dm_get_md_type(struct mapped_device *md);
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
 
 int dm_setup_md_queue(struct mapped_device *md);
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-ioctl.c linux-libre-3.2-gnu1/drivers/md/dm-ioctl.c
--- linux-libre-3.1-gnu1/drivers/md/dm-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1215,6 +1215,7 @@ static int table_load(struct dm_ioctl *p
 	struct hash_cell *hc;
 	struct dm_table *t;
 	struct mapped_device *md;
+	struct target_type *immutable_target_type;
 
 	md = find_device(param);
 	if (!md)
@@ -1230,6 +1231,16 @@ static int table_load(struct dm_ioctl *p
 		goto out;
 	}
 
+	immutable_target_type = dm_get_immutable_target_type(md);
+	if (immutable_target_type &&
+	    (immutable_target_type != dm_table_get_immutable_target_type(t))) {
+		DMWARN("can't replace immutable target type %s",
+		       immutable_target_type->name);
+		dm_table_destroy(t);
+		r = -EINVAL;
+		goto out;
+	}
+
 	/* Protect md->type and md->queue against concurrent table loads. */
 	dm_lock_md_type(md);
 	if (dm_get_md_type(md) == DM_TYPE_NONE)
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-kcopyd.c linux-libre-3.2-gnu1/drivers/md/dm-kcopyd.c
--- linux-libre-3.1-gnu1/drivers/md/dm-kcopyd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-kcopyd.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,8 @@ struct dm_kcopyd_client {
 	struct list_head pages_jobs;
 };
 
+static struct page_list zero_page_list;
+
 static void wake(struct dm_kcopyd_client *kc)
 {
 	queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
@@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void)
 	if (!_job_cache)
 		return -ENOMEM;
 
+	zero_page_list.next = &zero_page_list;
+	zero_page_list.page = ZERO_PAGE(0);
+
 	return 0;
 }
 
@@ -322,7 +327,7 @@ static int run_complete_job(struct kcopy
 	dm_kcopyd_notify_fn fn = job->fn;
 	struct dm_kcopyd_client *kc = job->kc;
 
-	if (job->pages)
+	if (job->pages && job->pages != &zero_page_list)
 		kcopyd_put_pages(kc, job->pages);
 	/*
 	 * If this is the master job, the sub jobs have already
@@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_j
 	atomic_inc(&kc->nr_jobs);
 	if (unlikely(!job->source.count))
 		push(&kc->complete_jobs, job);
+	else if (job->pages == &zero_page_list)
+		push(&kc->io_jobs, job);
 	else
 		push(&kc->pages_jobs, job);
 	wake(kc);
@@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_clie
 	job->flags = flags;
 	job->read_err = 0;
 	job->write_err = 0;
-	job->rw = READ;
-
-	job->source = *from;
 
 	job->num_dests = num_dests;
 	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
 
-	job->pages = NULL;
+	if (from) {
+		job->source = *from;
+		job->pages = NULL;
+		job->rw = READ;
+	} else {
+		memset(&job->source, 0, sizeof job->source);
+		job->source.count = job->dests[0].count;
+		job->pages = &zero_page_list;
+		job->rw = WRITE;
+	}
 
 	job->fn = fn;
 	job->context = context;
@@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_clie
 }
 EXPORT_SYMBOL(dm_kcopyd_copy);
 
+int dm_kcopyd_zero(struct dm_kcopyd_client *kc,
+		   unsigned num_dests, struct dm_io_region *dests,
+		   unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+{
+	return dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
+}
+EXPORT_SYMBOL(dm_kcopyd_zero);
+
 void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
 				 dm_kcopyd_notify_fn fn, void *context)
 {
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-log-userspace-base.c linux-libre-3.2-gnu1/drivers/md/dm-log-userspace-base.c
--- linux-libre-3.1-gnu1/drivers/md/dm-log-userspace-base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-log-userspace-base.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/dm-dirty-log.h>
 #include <linux/device-mapper.h>
 #include <linux/dm-log-userspace.h>
+#include <linux/module.h>
 
 #include "dm-log-userspace-transfer.h"
 
@@ -30,6 +31,7 @@ struct flush_entry {
 
 struct log_c {
 	struct dm_target *ti;
+	struct dm_dev *log_dev;
 	uint32_t region_size;
 	region_t region_count;
 	uint64_t luid;
@@ -146,7 +148,7 @@ static int build_constructor_string(stru
  *	<UUID> <other args>
  * Where 'other args' is the userspace implementation specific log
  * arguments.  An example might be:
- *	<UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync]
+ *	<UUID> clustered-disk <arg count> <log dev> <region_size> [[no]sync]
  *
  * So, this module will strip off the <UUID> for identification purposes
  * when communicating with userspace about a log; but will pass on everything
@@ -161,13 +163,15 @@ static int userspace_ctr(struct dm_dirty
 	struct log_c *lc = NULL;
 	uint64_t rdata;
 	size_t rdata_size = sizeof(rdata);
+	char *devices_rdata = NULL;
+	size_t devices_rdata_size = DM_NAME_LEN;
 
 	if (argc < 3) {
 		DMWARN("Too few arguments to userspace dirty log");
 		return -EINVAL;
 	}
 
-	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+	lc = kzalloc(sizeof(*lc), GFP_KERNEL);
 	if (!lc) {
 		DMWARN("Unable to allocate userspace log context.");
 		return -ENOMEM;
@@ -195,9 +199,19 @@ static int userspace_ctr(struct dm_dirty
 		return str_size;
 	}
 
-	/* Send table string */
+	devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
+	if (!devices_rdata) {
+		DMERR("Failed to allocate memory for device information");
+		r = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Send table string and get back any opened device.
+	 */
 	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
-				 ctr_str, str_size, NULL, NULL);
+				 ctr_str, str_size,
+				 devices_rdata, &devices_rdata_size);
 
 	if (r < 0) {
 		if (r == -ESRCH)
@@ -220,7 +234,20 @@ static int userspace_ctr(struct dm_dirty
 	lc->region_size = (uint32_t)rdata;
 	lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
 
+	if (devices_rdata_size) {
+		if (devices_rdata[devices_rdata_size - 1] != '\0') {
+			DMERR("DM_ULOG_CTR device return string not properly terminated");
+			r = -EINVAL;
+			goto out;
+		}
+		r = dm_get_device(ti, devices_rdata,
+				  dm_table_get_mode(ti->table), &lc->log_dev);
+		if (r)
+			DMERR("Failed to register %s with device-mapper",
+			      devices_rdata);
+	}
 out:
+	kfree(devices_rdata);
 	if (r) {
 		kfree(lc);
 		kfree(ctr_str);
@@ -241,6 +268,9 @@ static void userspace_dtr(struct dm_dirt
 				 NULL, 0,
 				 NULL, NULL);
 
+	if (lc->log_dev)
+		dm_put_device(lc->ti, lc->log_dev);
+
 	kfree(lc->usr_argv_str);
 	kfree(lc);
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-path-selector.c linux-libre-3.2-gnu1/drivers/md/dm-path-selector.c
--- linux-libre-3.1-gnu1/drivers/md/dm-path-selector.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-path-selector.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/device-mapper.h>
+#include <linux/module.h>
 
 #include "dm-path-selector.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-raid.c linux-libre-3.2-gnu1/drivers/md/dm-raid.c
--- linux-libre-3.1-gnu1/drivers/md/dm-raid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-raid.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "md.h"
 #include "raid1.h"
@@ -37,7 +38,7 @@ struct raid_dev {
 	 */
 	struct dm_dev *meta_dev;
 	struct dm_dev *data_dev;
-	struct mdk_rdev_s rdev;
+	struct md_rdev rdev;
 };
 
 /*
@@ -57,7 +58,7 @@ struct raid_set {
 
 	uint64_t print_flags;
 
-	struct mddev_s md;
+	struct mddev md;
 	struct raid_type *raid_type;
 	struct dm_target_callbacks callbacks;
 
@@ -594,7 +595,7 @@ struct dm_raid_superblock {
 				/* Always set to 0 when writing. */
 } __packed;
 
-static int read_disk_sb(mdk_rdev_t *rdev, int size)
+static int read_disk_sb(struct md_rdev *rdev, int size)
 {
 	BUG_ON(!rdev->sb_page);
 
@@ -611,9 +612,9 @@ static int read_disk_sb(mdk_rdev_t *rdev
 	return 0;
 }
 
-static void super_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
-	mdk_rdev_t *r, *t;
+	struct md_rdev *r, *t;
 	uint64_t failed_devices;
 	struct dm_raid_superblock *sb;
 
@@ -651,7 +652,7 @@ static void super_sync(mddev_t *mddev, m
  *
  * Return: 1 if use rdev, 0 if use refdev, -Exxx otherwise
  */
-static int super_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
+static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
 {
 	int ret;
 	struct dm_raid_superblock *sb;
@@ -689,7 +690,7 @@ static int super_load(mdk_rdev_t *rdev,
 	return (events_sb > events_refsb) ? 1 : 0;
 }
 
-static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev)
 {
 	int role;
 	struct raid_set *rs = container_of(mddev, struct raid_set, md);
@@ -698,7 +699,7 @@ static int super_init_validation(mddev_t
 	struct dm_raid_superblock *sb;
 	uint32_t new_devs = 0;
 	uint32_t rebuilds = 0;
-	mdk_rdev_t *r, *t;
+	struct md_rdev *r, *t;
 	struct dm_raid_superblock *sb2;
 
 	sb = page_address(rdev->sb_page);
@@ -809,7 +810,7 @@ static int super_init_validation(mddev_t
 	return 0;
 }
 
-static int super_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct dm_raid_superblock *sb = page_address(rdev->sb_page);
 
@@ -849,8 +850,8 @@ static int super_validate(mddev_t *mddev
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
 	int ret;
-	mdk_rdev_t *rdev, *freshest, *tmp;
-	mddev_t *mddev = &rs->md;
+	struct md_rdev *rdev, *freshest, *tmp;
+	struct mddev *mddev = &rs->md;
 
 	freshest = NULL;
 	rdev_for_each(rdev, tmp, mddev) {
@@ -1004,7 +1005,7 @@ static void raid_dtr(struct dm_target *t
 static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_context)
 {
 	struct raid_set *rs = ti->private;
-	mddev_t *mddev = &rs->md;
+	struct mddev *mddev = &rs->md;
 
 	mddev->pers->make_request(mddev, bio);
 
@@ -1017,30 +1018,56 @@ static int raid_status(struct dm_target
 	struct raid_set *rs = ti->private;
 	unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
 	unsigned sz = 0;
-	int i;
+	int i, array_in_sync = 0;
 	sector_t sync;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
 		DMEMIT("%s %d ", rs->raid_type->name, rs->md.raid_disks);
 
-		for (i = 0; i < rs->md.raid_disks; i++) {
-			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
-				DMEMIT("D");
-			else if (test_bit(In_sync, &rs->dev[i].rdev.flags))
-				DMEMIT("A");
-			else
-				DMEMIT("a");
-		}
-
 		if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
 			sync = rs->md.curr_resync_completed;
 		else
 			sync = rs->md.recovery_cp;
 
-		if (sync > rs->md.resync_max_sectors)
+		if (sync >= rs->md.resync_max_sectors) {
+			array_in_sync = 1;
 			sync = rs->md.resync_max_sectors;
+		} else {
+			/*
+			 * The array may be doing an initial sync, or it may
+			 * be rebuilding individual components.  If all the
+			 * devices are In_sync, then it is the array that is
+			 * being initialized.
+			 */
+			for (i = 0; i < rs->md.raid_disks; i++)
+				if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+					array_in_sync = 1;
+		}
+		/*
+		 * Status characters:
+		 *  'D' = Dead/Failed device
+		 *  'a' = Alive but not in-sync
+		 *  'A' = Alive and in-sync
+		 */
+		for (i = 0; i < rs->md.raid_disks; i++) {
+			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
+				DMEMIT("D");
+			else if (!array_in_sync ||
+				 !test_bit(In_sync, &rs->dev[i].rdev.flags))
+				DMEMIT("a");
+			else
+				DMEMIT("A");
+		}
 
+		/*
+		 * In-sync ratio:
+		 *  The in-sync ratio shows the progress of:
+		 *   - Initializing the array
+		 *   - Rebuilding a subset of devices of the array
+		 *  The user can distinguish between the two by referring
+		 *  to the status characters.
+		 */
 		DMEMIT(" %llu/%llu",
 		       (unsigned long long) sync,
 		       (unsigned long long) rs->md.resync_max_sectors);
@@ -1097,7 +1124,7 @@ static int raid_status(struct dm_target
 			       rs->md.bitmap_info.max_write_behind);
 
 		if (rs->print_flags & DMPF_STRIPE_CACHE) {
-			raid5_conf_t *conf = rs->md.private;
+			struct r5conf *conf = rs->md.private;
 
 			/* convert from kiB to sectors */
 			DMEMIT(" stripe_cache %d",
@@ -1146,7 +1173,7 @@ static void raid_io_hints(struct dm_targ
 {
 	struct raid_set *rs = ti->private;
 	unsigned chunk_size = rs->md.chunk_sectors << 9;
-	raid5_conf_t *conf = rs->md.private;
+	struct r5conf *conf = rs->md.private;
 
 	blk_limits_io_min(limits, chunk_size);
 	blk_limits_io_opt(limits, chunk_size * (conf->raid_disks - conf->max_degraded));
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-round-robin.c linux-libre-3.2-gnu1/drivers/md/dm-round-robin.c
--- linux-libre-3.1-gnu1/drivers/md/dm-round-robin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-round-robin.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "dm-path-selector.h"
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DM_MSG_PREFIX "multipath round-robin"
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-service-time.c linux-libre-3.2-gnu1/drivers/md/dm-service-time.c
--- linux-libre-3.1-gnu1/drivers/md/dm-service-time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-service-time.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include "dm-path-selector.h"
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DM_MSG_PREFIX	"multipath service-time"
 #define ST_MIN_IO	1
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-snap-persistent.c linux-libre-3.2-gnu1/drivers/md/dm-snap-persistent.c
--- linux-libre-3.1-gnu1/drivers/md/dm-snap-persistent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-snap-persistent.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/dm-io.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-snap-transient.c linux-libre-3.2-gnu1/drivers/md/dm-snap-transient.c
--- linux-libre-3.1-gnu1/drivers/md/dm-snap-transient.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-snap-transient.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/dm-io.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-table.c linux-libre-3.2-gnu1/drivers/md/dm-table.c
--- linux-libre-3.1-gnu1/drivers/md/dm-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,9 @@ struct dm_table {
 	sector_t *highs;
 	struct dm_target *targets;
 
+	struct target_type *immutable_target_type;
 	unsigned integrity_supported:1;
+	unsigned singleton:1;
 
 	/*
 	 * Indicates the rw permissions for the new logical
@@ -740,6 +742,12 @@ int dm_table_add_target(struct dm_table
 	char **argv;
 	struct dm_target *tgt;
 
+	if (t->singleton) {
+		DMERR("%s: target type %s must appear alone in table",
+		      dm_device_name(t->md), t->targets->type->name);
+		return -EINVAL;
+	}
+
 	if ((r = check_space(t)))
 		return r;
 
@@ -758,6 +766,36 @@ int dm_table_add_target(struct dm_table
 		return -EINVAL;
 	}
 
+	if (dm_target_needs_singleton(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: target type %s must appear alone in table",
+			      dm_device_name(t->md), type);
+			return -EINVAL;
+		}
+		t->singleton = 1;
+	}
+
+	if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
+		DMERR("%s: target type %s may not be included in read-only tables",
+		      dm_device_name(t->md), type);
+		return -EINVAL;
+	}
+
+	if (t->immutable_target_type) {
+		if (t->immutable_target_type != tgt->type) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), t->immutable_target_type->name);
+			return -EINVAL;
+		}
+	} else if (dm_target_is_immutable(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), tgt->type->name);
+			return -EINVAL;
+		}
+		t->immutable_target_type = tgt->type;
+	}
+
 	tgt->table = t;
 	tgt->begin = start;
 	tgt->len = len;
@@ -915,6 +953,11 @@ unsigned dm_table_get_type(struct dm_tab
 	return t->type;
 }
 
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
+{
+	return t->immutable_target_type;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
 	return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1299,6 +1342,31 @@ static bool dm_table_discard_zeroes_data
 	return 1;
 }
 
+static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
+			    sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && blk_queue_nonrot(q);
+}
+
+static bool dm_table_is_nonrot(struct dm_table *t)
+{
+	struct dm_target *ti;
+	unsigned i = 0;
+
+	/* Ensure that all underlying device are non-rotational. */
+	while (i < dm_table_get_num_targets(t)) {
+		ti = dm_table_get_target(t, i++);
+
+		if (!ti->type->iterate_devices ||
+		    !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+			return 0;
+	}
+
+	return 1;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 			       struct queue_limits *limits)
 {
@@ -1324,6 +1392,11 @@ void dm_table_set_restrictions(struct dm
 	if (!dm_table_discard_zeroes_data(t))
 		q->limits.discard_zeroes_data = 0;
 
+	if (dm_table_is_nonrot(t))
+		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+	else
+		queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
+
 	dm_table_set_integrity(t);
 
 	/*
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-thin.c linux-libre-3.2-gnu1/drivers/md/dm-thin.c
--- linux-libre-3.1-gnu1/drivers/md/dm-thin.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/dm-thin.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2011 Red Hat UK.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define	DM_MSG_PREFIX	"thin"
+
+/*
+ * Tunable constants
+ */
+#define ENDIO_HOOK_POOL_SIZE 10240
+#define DEFERRED_SET_SIZE 64
+#define MAPPING_POOL_SIZE 1024
+#define PRISON_CELLS 1024
+
+/*
+ * The block size of the device holding pool data must be
+ * between 64KB and 1GB.
+ */
+#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
+#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.  The limitation is
+ * checked lower down in dm-space-map-metadata, but we also check it here
+ * so we can fail early.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * Device id is restricted to 24 bits.
+ */
+#define MAX_DEV_ID ((1 << 24) - 1)
+
+/*
+ * How do we handle breaking sharing of data blocks?
+ * =================================================
+ *
+ * We use a standard copy-on-write btree to store the mappings for the
+ * devices (note I'm talking about copy-on-write of the metadata here, not
+ * the data).  When you take an internal snapshot you clone the root node
+ * of the origin btree.  After this there is no concept of an origin or a
+ * snapshot.  They are just two device trees that happen to point to the
+ * same data blocks.
+ *
+ * When we get a write in we decide if it's to a shared data block using
+ * some timestamp magic.  If it is, we have to break sharing.
+ *
+ * Let's say we write to a shared block in what was the origin.  The
+ * steps are:
+ *
+ * i) plug io further to this physical block. (see bio_prison code).
+ *
+ * ii) quiesce any read io to that shared data block.  Obviously
+ * including all devices that share this block.  (see deferred_set code)
+ *
+ * iii) copy the data block to a newly allocate block.  This step can be
+ * missed out if the io covers the block. (schedule_copy).
+ *
+ * iv) insert the new mapping into the origin's btree
+ * (process_prepared_mappings).  This act of inserting breaks some
+ * sharing of btree nodes between the two devices.  Breaking sharing only
+ * effects the btree of that specific device.  Btrees for the other
+ * devices that share the block never change.  The btree for the origin
+ * device as it was after the last commit is untouched, ie. we're using
+ * persistent data structures in the functional programming sense.
+ *
+ * v) unplug io to this physical block, including the io that triggered
+ * the breaking of sharing.
+ *
+ * Steps (ii) and (iii) occur in parallel.
+ *
+ * The metadata _doesn't_ need to be committed before the io continues.  We
+ * get away with this because the io is always written to a _new_ block.
+ * If there's a crash, then:
+ *
+ * - The origin mapping will point to the old origin block (the shared
+ * one).  This will contain the data as it was before the io that triggered
+ * the breaking of sharing came in.
+ *
+ * - The snap mapping still points to the old block.  As it would after
+ * the commit.
+ *
+ * The downside of this scheme is the timestamp magic isn't perfect, and
+ * will continue to think that data block in the snapshot device is shared
+ * even after the write to the origin has broken sharing.  I suspect data
+ * blocks will typically be shared by many different devices, so we're
+ * breaking sharing n + 1 times, rather than n, where n is the number of
+ * devices that reference this data block.  At the moment I think the
+ * benefits far, far outweigh the disadvantages.
+ */
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Sometimes we can't deal with a bio straight away.  We put them in prison
+ * where they can't cause any mischief.  Bios are put in a cell identified
+ * by a key, multiple bios can be in the same cell.  When the cell is
+ * subsequently unlocked the bios become available.
+ */
+struct bio_prison;
+
+struct cell_key {
+	int virtual;
+	dm_thin_id dev;
+	dm_block_t block;
+};
+
+struct cell {
+	struct hlist_node list;
+	struct bio_prison *prison;
+	struct cell_key key;
+	unsigned count;
+	struct bio_list bios;
+};
+
+struct bio_prison {
+	spinlock_t lock;
+	mempool_t *cell_pool;
+
+	unsigned nr_buckets;
+	unsigned hash_mask;
+	struct hlist_head *cells;
+};
+
+static uint32_t calc_nr_buckets(unsigned nr_cells)
+{
+	uint32_t n = 128;
+
+	nr_cells /= 4;
+	nr_cells = min(nr_cells, 8192u);
+
+	while (n < nr_cells)
+		n <<= 1;
+
+	return n;
+}
+
+/*
+ * @nr_cells should be the number of cells you want in use _concurrently_.
+ * Don't confuse it with the number of distinct keys.
+ */
+static struct bio_prison *prison_create(unsigned nr_cells)
+{
+	unsigned i;
+	uint32_t nr_buckets = calc_nr_buckets(nr_cells);
+	size_t len = sizeof(struct bio_prison) +
+		(sizeof(struct hlist_head) * nr_buckets);
+	struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
+
+	if (!prison)
+		return NULL;
+
+	spin_lock_init(&prison->lock);
+	prison->cell_pool = mempool_create_kmalloc_pool(nr_cells,
+							sizeof(struct cell));
+	if (!prison->cell_pool) {
+		kfree(prison);
+		return NULL;
+	}
+
+	prison->nr_buckets = nr_buckets;
+	prison->hash_mask = nr_buckets - 1;
+	prison->cells = (struct hlist_head *) (prison + 1);
+	for (i = 0; i < nr_buckets; i++)
+		INIT_HLIST_HEAD(prison->cells + i);
+
+	return prison;
+}
+
+static void prison_destroy(struct bio_prison *prison)
+{
+	mempool_destroy(prison->cell_pool);
+	kfree(prison);
+}
+
+static uint32_t hash_key(struct bio_prison *prison, struct cell_key *key)
+{
+	const unsigned long BIG_PRIME = 4294967291UL;
+	uint64_t hash = key->block * BIG_PRIME;
+
+	return (uint32_t) (hash & prison->hash_mask);
+}
+
+static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
+{
+	       return (lhs->virtual == rhs->virtual) &&
+		       (lhs->dev == rhs->dev) &&
+		       (lhs->block == rhs->block);
+}
+
+static struct cell *__search_bucket(struct hlist_head *bucket,
+				    struct cell_key *key)
+{
+	struct cell *cell;
+	struct hlist_node *tmp;
+
+	hlist_for_each_entry(cell, tmp, bucket, list)
+		if (keys_equal(&cell->key, key))
+			return cell;
+
+	return NULL;
+}
+
+/*
+ * This may block if a new cell needs allocating.  You must ensure that
+ * cells will be unlocked even if the calling thread is blocked.
+ *
+ * Returns the number of entries in the cell prior to the new addition
+ * or < 0 on failure.
+ */
+static int bio_detain(struct bio_prison *prison, struct cell_key *key,
+		      struct bio *inmate, struct cell **ref)
+{
+	int r;
+	unsigned long flags;
+	uint32_t hash = hash_key(prison, key);
+	struct cell *uninitialized_var(cell), *cell2 = NULL;
+
+	BUG_ON(hash > prison->nr_buckets);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	cell = __search_bucket(prison->cells + hash, key);
+
+	if (!cell) {
+		/*
+		 * Allocate a new cell
+		 */
+		spin_unlock_irqrestore(&prison->lock, flags);
+		cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+		spin_lock_irqsave(&prison->lock, flags);
+
+		/*
+		 * We've been unlocked, so we have to double check that
+		 * nobody else has inserted this cell in the meantime.
+		 */
+		cell = __search_bucket(prison->cells + hash, key);
+
+		if (!cell) {
+			cell = cell2;
+			cell2 = NULL;
+
+			cell->prison = prison;
+			memcpy(&cell->key, key, sizeof(cell->key));
+			cell->count = 0;
+			bio_list_init(&cell->bios);
+			hlist_add_head(&cell->list, prison->cells + hash);
+		}
+	}
+
+	r = cell->count++;
+	bio_list_add(&cell->bios, inmate);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	if (cell2)
+		mempool_free(cell2, prison->cell_pool);
+
+	*ref = cell;
+
+	return r;
+}
+
+/*
+ * @inmates must have been initialised prior to this call
+ */
+static void __cell_release(struct cell *cell, struct bio_list *inmates)
+{
+	struct bio_prison *prison = cell->prison;
+
+	hlist_del(&cell->list);
+
+	if (inmates)
+		bio_list_merge(inmates, &cell->bios);
+
+	mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release(struct cell *cell, struct bio_list *bios)
+{
+	unsigned long flags;
+	struct bio_prison *prison = cell->prison;
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * There are a couple of places where we put a bio into a cell briefly
+ * before taking it out again.  In these situations we know that no other
+ * bio may be in the cell.  This function releases the cell, and also does
+ * a sanity check.
+ */
+static void cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *b;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	b = bio_list_pop(&bios);
+	BUG_ON(b != bio);
+	BUG_ON(!bio_list_empty(&bios));
+}
+
+static void cell_error(struct cell *cell)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *bio;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	while ((bio = bio_list_pop(&bios)))
+		bio_io_error(bio);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We use the deferred set to keep track of pending reads to shared blocks.
+ * We do this to ensure the new mapping caused by a write isn't performed
+ * until these prior reads have completed.  Otherwise the insertion of the
+ * new mapping could free the old block that the read bios are mapped to.
+ */
+
+struct deferred_set;
+struct deferred_entry {
+	struct deferred_set *ds;
+	unsigned count;
+	struct list_head work_items;
+};
+
+struct deferred_set {
+	spinlock_t lock;
+	unsigned current_entry;
+	unsigned sweeper;
+	struct deferred_entry entries[DEFERRED_SET_SIZE];
+};
+
+static void ds_init(struct deferred_set *ds)
+{
+	int i;
+
+	spin_lock_init(&ds->lock);
+	ds->current_entry = 0;
+	ds->sweeper = 0;
+	for (i = 0; i < DEFERRED_SET_SIZE; i++) {
+		ds->entries[i].ds = ds;
+		ds->entries[i].count = 0;
+		INIT_LIST_HEAD(&ds->entries[i].work_items);
+	}
+}
+
+static struct deferred_entry *ds_inc(struct deferred_set *ds)
+{
+	unsigned long flags;
+	struct deferred_entry *entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	entry = ds->entries + ds->current_entry;
+	entry->count++;
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return entry;
+}
+
+static unsigned ds_next(unsigned index)
+{
+	return (index + 1) % DEFERRED_SET_SIZE;
+}
+
+static void __sweep(struct deferred_set *ds, struct list_head *head)
+{
+	while ((ds->sweeper != ds->current_entry) &&
+	       !ds->entries[ds->sweeper].count) {
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+		ds->sweeper = ds_next(ds->sweeper);
+	}
+
+	if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+}
+
+static void ds_dec(struct deferred_entry *entry, struct list_head *head)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&entry->ds->lock, flags);
+	BUG_ON(!entry->count);
+	--entry->count;
+	__sweep(entry->ds, head);
+	spin_unlock_irqrestore(&entry->ds->lock, flags);
+}
+
+/*
+ * Returns 1 if deferred or 0 if no pending items to delay job.
+ */
+static int ds_add_work(struct deferred_set *ds, struct list_head *work)
+{
+	int r = 1;
+	unsigned long flags;
+	unsigned next_entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	if ((ds->sweeper == ds->current_entry) &&
+	    !ds->entries[ds->current_entry].count)
+		r = 0;
+	else {
+		list_add(work, &ds->entries[ds->current_entry].work_items);
+		next_entry = ds_next(ds->current_entry);
+		if (!ds->entries[next_entry].count)
+			ds->current_entry = next_entry;
+	}
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return r;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Key building.
+ */
+static void build_data_key(struct dm_thin_device *td,
+			   dm_block_t b, struct cell_key *key)
+{
+	key->virtual = 0;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
+			      struct cell_key *key)
+{
+	key->virtual = 1;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A pool device ties together a metadata device and a data device.  It
+ * also provides the interface for creating and destroying internal
+ * devices.
+ */
+struct new_mapping;
+struct pool {
+	struct list_head list;
+	struct dm_target *ti;	/* Only set if a pool target is bound */
+
+	struct mapped_device *pool_md;
+	struct block_device *md_dev;
+	struct dm_pool_metadata *pmd;
+
+	uint32_t sectors_per_block;
+	unsigned block_shift;
+	dm_block_t offset_mask;
+	dm_block_t low_water_blocks;
+
+	unsigned zero_new_blocks:1;
+	unsigned low_water_triggered:1;	/* A dm event has been sent */
+	unsigned no_free_space:1;	/* A -ENOSPC warning has been issued */
+
+	struct bio_prison *prison;
+	struct dm_kcopyd_client *copier;
+
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+
+	unsigned ref_count;
+
+	spinlock_t lock;
+	struct bio_list deferred_bios;
+	struct bio_list deferred_flush_bios;
+	struct list_head prepared_mappings;
+
+	struct bio_list retry_on_resume_list;
+
+	struct deferred_set ds;	/* FIXME: move to thin_c */
+
+	struct new_mapping *next_mapping;
+	mempool_t *mapping_pool;
+	mempool_t *endio_hook_pool;
+};
+
+/*
+ * Target context for a pool.
+ */
+struct pool_c {
+	struct dm_target *ti;
+	struct pool *pool;
+	struct dm_dev *data_dev;
+	struct dm_dev *metadata_dev;
+	struct dm_target_callbacks callbacks;
+
+	dm_block_t low_water_blocks;
+	unsigned zero_new_blocks:1;
+};
+
+/*
+ * Target context for a thin.
+ */
+struct thin_c {
+	struct dm_dev *pool_dev;
+	dm_thin_id dev_id;
+
+	struct pool *pool;
+	struct dm_thin_device *td;
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A global list of pools that uses a struct mapped_device as a key.
+ */
+static struct dm_thin_pool_table {
+	struct mutex mutex;
+	struct list_head pools;
+} dm_thin_pool_table;
+
+static void pool_table_init(void)
+{
+	mutex_init(&dm_thin_pool_table.mutex);
+	INIT_LIST_HEAD(&dm_thin_pool_table.pools);
+}
+
+static void __pool_table_insert(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_add(&pool->list, &dm_thin_pool_table.pools);
+}
+
+static void __pool_table_remove(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_del(&pool->list);
+}
+
+static struct pool *__pool_table_lookup(struct mapped_device *md)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->pool_md == md) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->md_dev == md_dev) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------*/
+
+static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	bio_list_merge(&bios, master);
+	bio_list_init(master);
+
+	while ((bio = bio_list_pop(&bios))) {
+		if (dm_get_mapinfo(bio)->ptr == tc)
+			bio_endio(bio, DM_ENDIO_REQUEUE);
+		else
+			bio_list_add(master, bio);
+	}
+}
+
+static void requeue_io(struct thin_c *tc)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	__requeue_bio_list(tc, &pool->deferred_bios);
+	__requeue_bio_list(tc, &pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+/*
+ * This section of code contains the logic for processing a thin device's IO.
+ * Much of the code depends on pool object resources (lists, workqueues, etc)
+ * but most is exclusively called from the thin target rather than the thin-pool
+ * target.
+ */
+
+static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
+{
+	return bio->bi_sector >> tc->pool->block_shift;
+}
+
+static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+
+	bio->bi_bdev = tc->pool_dev->bdev;
+	bio->bi_sector = (block << pool->block_shift) +
+		(bio->bi_sector & pool->offset_mask);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+			    dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	remap(tc, bio, block);
+
+	/*
+	 * Batch together any FUA/FLUSH bios we find and then issue
+	 * a single commit for them in process_deferred_bios().
+	 */
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		spin_lock_irqsave(&pool->lock, flags);
+		bio_list_add(&pool->deferred_flush_bios, bio);
+		spin_unlock_irqrestore(&pool->lock, flags);
+	} else
+		generic_make_request(bio);
+}
+
+/*
+ * wake_worker() is used when new work is queued and when pool_resume is
+ * ready to continue deferred IO processing.
+ */
+static void wake_worker(struct pool *pool)
+{
+	queue_work(pool->wq, &pool->worker);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bio endio functions.
+ */
+struct endio_hook {
+	struct thin_c *tc;
+	bio_end_io_t *saved_bi_end_io;
+	struct deferred_entry *entry;
+};
+
+struct new_mapping {
+	struct list_head list;
+
+	int prepared;
+
+	struct thin_c *tc;
+	dm_block_t virt_block;
+	dm_block_t data_block;
+	struct cell *cell;
+	int err;
+
+	/*
+	 * If the bio covers the whole area of a block then we can avoid
+	 * zeroing or copying.  Instead this bio is hooked.  The bio will
+	 * still be in the cell, so care has to be taken to avoid issuing
+	 * the bio twice.
+	 */
+	struct bio *bio;
+	bio_end_io_t *saved_bi_end_io;
+};
+
+static void __maybe_add_mapping(struct new_mapping *m)
+{
+	struct pool *pool = m->tc->pool;
+
+	if (list_empty(&m->list) && m->prepared) {
+		list_add(&m->list, &pool->prepared_mappings);
+		wake_worker(pool);
+	}
+}
+
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+	unsigned long flags;
+	struct new_mapping *m = context;
+	struct pool *pool = m->tc->pool;
+
+	m->err = read_err || write_err ? -EIO : 0;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void overwrite_endio(struct bio *bio, int err)
+{
+	unsigned long flags;
+	struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = m->tc->pool;
+
+	m->err = err;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void shared_read_endio(struct bio *bio, int err)
+{
+	struct list_head mappings;
+	struct new_mapping *m, *tmp;
+	struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+	unsigned long flags;
+	struct pool *pool = h->tc->pool;
+
+	bio->bi_end_io = h->saved_bi_end_io;
+	bio_endio(bio, err);
+
+	INIT_LIST_HEAD(&mappings);
+	ds_dec(h->entry, &mappings);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	list_for_each_entry_safe(m, tmp, &mappings, list) {
+		list_del(&m->list);
+		INIT_LIST_HEAD(&m->list);
+		__maybe_add_mapping(m);
+	}
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	mempool_free(h, pool->endio_hook_pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Workqueue.
+ */
+
+/*
+ * Prepared mapping jobs.
+ */
+
+/*
+ * This sends the bios in the cell back to the deferred_bios list.
+ */
+static void cell_defer(struct thin_c *tc, struct cell *cell,
+		       dm_block_t data_block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	cell_release(cell, &pool->deferred_bios);
+	spin_unlock_irqrestore(&tc->pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Same as cell_defer above, except it omits one particular detainee,
+ * a write bio that covers the block and has already been processed.
+ */
+static void cell_defer_except(struct thin_c *tc, struct cell *cell,
+			      struct bio *exception)
+{
+	struct bio_list bios;
+	struct bio *bio;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	while ((bio = bio_list_pop(&bios)))
+		if (bio != exception)
+			bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void process_prepared_mapping(struct new_mapping *m)
+{
+	struct thin_c *tc = m->tc;
+	struct bio *bio;
+	int r;
+
+	bio = m->bio;
+	if (bio)
+		bio->bi_end_io = m->saved_bi_end_io;
+
+	if (m->err) {
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Commit the prepared block into the mapping btree.
+	 * Any I/O for this block arriving after this point will get
+	 * remapped to it directly.
+	 */
+	r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
+	if (r) {
+		DMERR("dm_thin_insert_block() failed");
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Release any bios held while the block was being provisioned.
+	 * If we are processing a write bio that completely covers the block,
+	 * we already processed it so can ignore it now when processing
+	 * the bios in the cell.
+	 */
+	if (bio) {
+		cell_defer_except(tc, m->cell, bio);
+		bio_endio(bio, 0);
+	} else
+		cell_defer(tc, m->cell, m->data_block);
+
+	list_del(&m->list);
+	mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared_mappings(struct pool *pool)
+{
+	unsigned long flags;
+	struct list_head maps;
+	struct new_mapping *m, *tmp;
+
+	INIT_LIST_HEAD(&maps);
+	spin_lock_irqsave(&pool->lock, flags);
+	list_splice_init(&pool->prepared_mappings, &maps);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	list_for_each_entry_safe(m, tmp, &maps, list)
+		process_prepared_mapping(m);
+}
+
+/*
+ * Deferred bio jobs.
+ */
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+	return ((bio_data_dir(bio) == WRITE) &&
+		!(bio->bi_sector & pool->offset_mask)) &&
+		(bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+}
+
+static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
+			       bio_end_io_t *fn)
+{
+	*save = bio->bi_end_io;
+	bio->bi_end_io = fn;
+}
+
+static int ensure_next_mapping(struct pool *pool)
+{
+	if (pool->next_mapping)
+		return 0;
+
+	pool->next_mapping = mempool_alloc(pool->mapping_pool, GFP_ATOMIC);
+
+	return pool->next_mapping ? 0 : -ENOMEM;
+}
+
+static struct new_mapping *get_next_mapping(struct pool *pool)
+{
+	struct new_mapping *r = pool->next_mapping;
+
+	BUG_ON(!pool->next_mapping);
+
+	pool->next_mapping = NULL;
+
+	return r;
+}
+
+static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_origin, dm_block_t data_dest,
+			  struct cell *cell, struct bio *bio)
+{
+	int r;
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_dest;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	ds_add_work(&pool->ds, &m->list);
+
+	/*
+	 * IO to pool_dev remaps to the pool target's data_dev.
+	 *
+	 * If the whole block of data is being overwritten, we can issue the
+	 * bio immediately. Otherwise we use kcopyd to clone the data first.
+	 */
+	if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_dest);
+	} else {
+		struct dm_io_region from, to;
+
+		from.bdev = tc->pool_dev->bdev;
+		from.sector = data_origin * pool->sectors_per_block;
+		from.count = pool->sectors_per_block;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_dest * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
+				   0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_copy() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_block, struct cell *cell,
+			  struct bio *bio)
+{
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_block;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	/*
+	 * If the whole block of data is being overwritten or we are not
+	 * zeroing pre-existing data, we can issue the bio immediately.
+	 * Otherwise we use kcopyd to zero the data first.
+	 */
+	if (!pool->zero_new_blocks)
+		process_prepared_mapping(m);
+
+	else if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_block);
+
+	} else {
+		int r;
+		struct dm_io_region to;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_block * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_zero() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
+{
+	int r;
+	dm_block_t free_blocks;
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+	if (r)
+		return r;
+
+	if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
+		DMWARN("%s: reached low water mark, sending event.",
+		       dm_device_name(pool->pool_md));
+		spin_lock_irqsave(&pool->lock, flags);
+		pool->low_water_triggered = 1;
+		spin_unlock_irqrestore(&pool->lock, flags);
+		dm_table_event(pool->ti->table);
+	}
+
+	if (!free_blocks) {
+		if (pool->no_free_space)
+			return -ENOSPC;
+		else {
+			/*
+			 * Try to commit to see if that will free up some
+			 * more space.
+			 */
+			r = dm_pool_commit_metadata(pool->pmd);
+			if (r) {
+				DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+				      __func__, r);
+				return r;
+			}
+
+			r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+			if (r)
+				return r;
+
+			/*
+			 * If we still have no space we set a flag to avoid
+			 * doing all this checking and return -ENOSPC.
+			 */
+			if (!free_blocks) {
+				DMWARN("%s: no free space available.",
+				       dm_device_name(pool->pool_md));
+				spin_lock_irqsave(&pool->lock, flags);
+				pool->no_free_space = 1;
+				spin_unlock_irqrestore(&pool->lock, flags);
+				return -ENOSPC;
+			}
+		}
+	}
+
+	r = dm_pool_alloc_data_block(pool->pmd, result);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+/*
+ * If we have run out of space, queue bios until the device is
+ * resumed, presumably after having been reloaded with more space.
+ */
+static void retry_on_resume(struct bio *bio)
+{
+	struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->retry_on_resume_list, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void no_space(struct cell *cell)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	while ((bio = bio_list_pop(&bios)))
+		retry_on_resume(bio);
+}
+
+static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			  struct cell_key *key,
+			  struct dm_thin_lookup_result *lookup_result,
+			  struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_copy(tc, block, lookup_result->block,
+			      data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_shared_bio(struct thin_c *tc, struct bio *bio,
+			       dm_block_t block,
+			       struct dm_thin_lookup_result *lookup_result)
+{
+	struct cell *cell;
+	struct pool *pool = tc->pool;
+	struct cell_key key;
+
+	/*
+	 * If cell is already occupied, then sharing is already in the process
+	 * of being broken so we have nothing further to do here.
+	 */
+	build_data_key(tc->td, lookup_result->block, &key);
+	if (bio_detain(pool->prison, &key, bio, &cell))
+		return;
+
+	if (bio_data_dir(bio) == WRITE)
+		break_sharing(tc, bio, block, &key, lookup_result, cell);
+	else {
+		struct endio_hook *h;
+		h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+		h->tc = tc;
+		h->entry = ds_inc(&pool->ds);
+		save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
+		dm_get_mapinfo(bio)->ptr = h;
+
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, lookup_result->block);
+	}
+}
+
+static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			    struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	/*
+	 * Remap empty bios (flushes) immediately, without provisioning.
+	 */
+	if (!bio->bi_size) {
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, 0);
+		return;
+	}
+
+	/*
+	 * Fill read bios with zeroes and complete them immediately.
+	 */
+	if (bio_data_dir(bio) == READ) {
+		zero_fill_bio(bio);
+		cell_release_singleton(cell, bio);
+		bio_endio(bio, 0);
+		return;
+	}
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_zero(tc, block, data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_bio(struct thin_c *tc, struct bio *bio)
+{
+	int r;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct cell *cell;
+	struct cell_key key;
+	struct dm_thin_lookup_result lookup_result;
+
+	/*
+	 * If cell is already occupied, then the block is already
+	 * being provisioned so we have nothing further to do here.
+	 */
+	build_virtual_key(tc->td, block, &key);
+	if (bio_detain(tc->pool->prison, &key, bio, &cell))
+		return;
+
+	r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+	switch (r) {
+	case 0:
+		/*
+		 * We can release this cell now.  This thread is the only
+		 * one that puts bios into a cell, and we know there were
+		 * no preceding bios.
+		 */
+		/*
+		 * TODO: this will probably have to change when discard goes
+		 * back in.
+		 */
+		cell_release_singleton(cell, bio);
+
+		if (lookup_result.shared)
+			process_shared_bio(tc, bio, block, &lookup_result);
+		else
+			remap_and_issue(tc, bio, lookup_result.block);
+		break;
+
+	case -ENODATA:
+		provision_block(tc, bio, block, cell);
+		break;
+
+	default:
+		DMERR("dm_thin_find_block() failed, error = %d", r);
+		bio_io_error(bio);
+		break;
+	}
+}
+
+static void process_deferred_bios(struct pool *pool)
+{
+	unsigned long flags;
+	struct bio *bio;
+	struct bio_list bios;
+	int r;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_bios);
+	bio_list_init(&pool->deferred_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	while ((bio = bio_list_pop(&bios))) {
+		struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+		/*
+		 * If we've got no free new_mapping structs, and processing
+		 * this bio might require one, we pause until there are some
+		 * prepared mappings to process.
+		 */
+		if (ensure_next_mapping(pool)) {
+			spin_lock_irqsave(&pool->lock, flags);
+			bio_list_merge(&pool->deferred_bios, &bios);
+			spin_unlock_irqrestore(&pool->lock, flags);
+
+			break;
+		}
+		process_bio(tc, bio);
+	}
+
+	/*
+	 * If there are any deferred flush bios, we must commit
+	 * the metadata before issuing them.
+	 */
+	bio_list_init(&bios);
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_flush_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	if (bio_list_empty(&bios))
+		return;
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		while ((bio = bio_list_pop(&bios)))
+			bio_io_error(bio);
+		return;
+	}
+
+	while ((bio = bio_list_pop(&bios)))
+		generic_make_request(bio);
+}
+
+static void do_worker(struct work_struct *ws)
+{
+	struct pool *pool = container_of(ws, struct pool, worker);
+
+	process_prepared_mappings(pool);
+	process_deferred_bios(pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Mapping functions.
+ */
+
+/*
+ * Called only while mapping a thin bio to hand it over to the workqueue.
+ */
+static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
+{
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Non-blocking function called from the thin target's map function.
+ */
+static int thin_bio_map(struct dm_target *ti, struct bio *bio,
+			union map_info *map_context)
+{
+	int r;
+	struct thin_c *tc = ti->private;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct dm_thin_device *td = tc->td;
+	struct dm_thin_lookup_result result;
+
+	/*
+	 * Save the thin context for easy access from the deferred bio later.
+	 */
+	map_context->ptr = tc;
+
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		thin_defer_bio(tc, bio);
+		return DM_MAPIO_SUBMITTED;
+	}
+
+	r = dm_thin_find_block(td, block, 0, &result);
+
+	/*
+	 * Note that we defer readahead too.
+	 */
+	switch (r) {
+	case 0:
+		if (unlikely(result.shared)) {
+			/*
+			 * We have a race condition here between the
+			 * result.shared value returned by the lookup and
+			 * snapshot creation, which may cause new
+			 * sharing.
+			 *
+			 * To avoid this always quiesce the origin before
+			 * taking the snap.  You want to do this anyway to
+			 * ensure a consistent application view
+			 * (i.e. lockfs).
+			 *
+			 * More distant ancestors are irrelevant. The
+			 * shared flag will be set in their case.
+			 */
+			thin_defer_bio(tc, bio);
+			r = DM_MAPIO_SUBMITTED;
+		} else {
+			remap(tc, bio, result.block);
+			r = DM_MAPIO_REMAPPED;
+		}
+		break;
+
+	case -ENODATA:
+		/*
+		 * In future, the failed dm_thin_find_block above could
+		 * provide the hint to load the metadata into cache.
+		 */
+	case -EWOULDBLOCK:
+		thin_defer_bio(tc, bio);
+		r = DM_MAPIO_SUBMITTED;
+		break;
+	}
+
+	return r;
+}
+
+static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
+{
+	int r;
+	unsigned long flags;
+	struct pool_c *pt = container_of(cb, struct pool_c, callbacks);
+
+	spin_lock_irqsave(&pt->pool->lock, flags);
+	r = !bio_list_empty(&pt->pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pt->pool->lock, flags);
+
+	if (!r) {
+		struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+		r = bdi_congested(&q->backing_dev_info, bdi_bits);
+	}
+
+	return r;
+}
+
+static void __requeue_bios(struct pool *pool)
+{
+	bio_list_merge(&pool->deferred_bios, &pool->retry_on_resume_list);
+	bio_list_init(&pool->retry_on_resume_list);
+}
+
+/*----------------------------------------------------------------
+ * Binding of control targets to a pool object
+ *--------------------------------------------------------------*/
+static int bind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	pool->ti = ti;
+	pool->low_water_blocks = pt->low_water_blocks;
+	pool->zero_new_blocks = pt->zero_new_blocks;
+
+	return 0;
+}
+
+static void unbind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	if (pool->ti == ti)
+		pool->ti = NULL;
+}
+
+/*----------------------------------------------------------------
+ * Pool creation
+ *--------------------------------------------------------------*/
+static void __pool_destroy(struct pool *pool)
+{
+	__pool_table_remove(pool);
+
+	if (dm_pool_metadata_close(pool->pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	prison_destroy(pool->prison);
+	dm_kcopyd_client_destroy(pool->copier);
+
+	if (pool->wq)
+		destroy_workqueue(pool->wq);
+
+	if (pool->next_mapping)
+		mempool_free(pool->next_mapping, pool->mapping_pool);
+	mempool_destroy(pool->mapping_pool);
+	mempool_destroy(pool->endio_hook_pool);
+	kfree(pool);
+}
+
+static struct pool *pool_create(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	int r;
+	void *err_p;
+	struct pool *pool;
+	struct dm_pool_metadata *pmd;
+
+	pmd = dm_pool_metadata_open(metadata_dev, block_size);
+	if (IS_ERR(pmd)) {
+		*error = "Error creating metadata object";
+		return (struct pool *)pmd;
+	}
+
+	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool) {
+		*error = "Error allocating memory for pool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_pool;
+	}
+
+	pool->pmd = pmd;
+	pool->sectors_per_block = block_size;
+	pool->block_shift = ffs(block_size) - 1;
+	pool->offset_mask = block_size - 1;
+	pool->low_water_blocks = 0;
+	pool->zero_new_blocks = 1;
+	pool->prison = prison_create(PRISON_CELLS);
+	if (!pool->prison) {
+		*error = "Error creating pool's bio prison";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_prison;
+	}
+
+	pool->copier = dm_kcopyd_client_create();
+	if (IS_ERR(pool->copier)) {
+		r = PTR_ERR(pool->copier);
+		*error = "Error creating pool's kcopyd client";
+		err_p = ERR_PTR(r);
+		goto bad_kcopyd_client;
+	}
+
+	/*
+	 * Create singlethreaded workqueue that will service all devices
+	 * that use this metadata.
+	 */
+	pool->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
+	if (!pool->wq) {
+		*error = "Error creating pool's workqueue";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_wq;
+	}
+
+	INIT_WORK(&pool->worker, do_worker);
+	spin_lock_init(&pool->lock);
+	bio_list_init(&pool->deferred_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	INIT_LIST_HEAD(&pool->prepared_mappings);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	bio_list_init(&pool->retry_on_resume_list);
+	ds_init(&pool->ds);
+
+	pool->next_mapping = NULL;
+	pool->mapping_pool =
+		mempool_create_kmalloc_pool(MAPPING_POOL_SIZE, sizeof(struct new_mapping));
+	if (!pool->mapping_pool) {
+		*error = "Error creating pool's mapping mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_mapping_pool;
+	}
+
+	pool->endio_hook_pool =
+		mempool_create_kmalloc_pool(ENDIO_HOOK_POOL_SIZE, sizeof(struct endio_hook));
+	if (!pool->endio_hook_pool) {
+		*error = "Error creating pool's endio_hook mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_endio_hook_pool;
+	}
+	pool->ref_count = 1;
+	pool->pool_md = pool_md;
+	pool->md_dev = metadata_dev;
+	__pool_table_insert(pool);
+
+	return pool;
+
+bad_endio_hook_pool:
+	mempool_destroy(pool->mapping_pool);
+bad_mapping_pool:
+	destroy_workqueue(pool->wq);
+bad_wq:
+	dm_kcopyd_client_destroy(pool->copier);
+bad_kcopyd_client:
+	prison_destroy(pool->prison);
+bad_prison:
+	kfree(pool);
+bad_pool:
+	if (dm_pool_metadata_close(pmd))
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	return err_p;
+}
+
+static void __pool_inc(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	pool->ref_count++;
+}
+
+static void __pool_dec(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	BUG_ON(!pool->ref_count);
+	if (!--pool->ref_count)
+		__pool_destroy(pool);
+}
+
+static struct pool *__pool_find(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
+
+	if (pool) {
+		if (pool->pool_md != pool_md)
+			return ERR_PTR(-EBUSY);
+		__pool_inc(pool);
+
+	} else {
+		pool = __pool_table_lookup(pool_md);
+		if (pool) {
+			if (pool->md_dev != metadata_dev)
+				return ERR_PTR(-EINVAL);
+			__pool_inc(pool);
+
+		} else
+			pool = pool_create(pool_md, metadata_dev, block_size, error);
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------
+ * Pool target methods
+ *--------------------------------------------------------------*/
+static void pool_dtr(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	unbind_control_target(pt->pool, ti);
+	__pool_dec(pt->pool);
+	dm_put_device(ti, pt->metadata_dev);
+	dm_put_device(ti, pt->data_dev);
+	kfree(pt);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+struct pool_features {
+	unsigned zero_new_blocks:1;
+};
+
+static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
+			       struct dm_target *ti)
+{
+	int r;
+	unsigned argc;
+	const char *arg_name;
+
+	static struct dm_arg _args[] = {
+		{0, 1, "Invalid number of pool feature arguments"},
+	};
+
+	/*
+	 * No feature arguments supplied.
+	 */
+	if (!as->argc)
+		return 0;
+
+	r = dm_read_arg_group(_args, as, &argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	while (argc && !r) {
+		arg_name = dm_shift_arg(as);
+		argc--;
+
+		if (!strcasecmp(arg_name, "skip_block_zeroing")) {
+			pf->zero_new_blocks = 0;
+			continue;
+		}
+
+		ti->error = "Unrecognised pool feature requested";
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+/*
+ * thin-pool <metadata dev> <data dev>
+ *	     <data block size (sectors)>
+ *	     <low water mark (blocks)>
+ *	     [<#feature args> [<arg>]*]
+ *
+ * Optional feature arguments are:
+ *	     skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ */
+static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct pool_c *pt;
+	struct pool *pool;
+	struct pool_features pf;
+	struct dm_arg_set as;
+	struct dm_dev *data_dev;
+	unsigned long block_size;
+	dm_block_t low_water_blocks;
+	struct dm_dev *metadata_dev;
+	sector_t metadata_dev_size;
+
+	/*
+	 * FIXME Remove validation from scope of lock.
+	 */
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc < 4) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+	as.argc = argc;
+	as.argv = argv;
+
+	r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &metadata_dev);
+	if (r) {
+		ti->error = "Error opening metadata block device";
+		goto out_unlock;
+	}
+
+	metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
+		ti->error = "Metadata device is too large";
+		r = -EINVAL;
+		goto out_metadata;
+	}
+
+	r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
+	if (r) {
+		ti->error = "Error getting data device";
+		goto out_metadata;
+	}
+
+	if (kstrtoul(argv[2], 10, &block_size) || !block_size ||
+	    block_size < DATA_DEV_BLOCK_SIZE_MIN_SECTORS ||
+	    block_size > DATA_DEV_BLOCK_SIZE_MAX_SECTORS ||
+	    !is_power_of_2(block_size)) {
+		ti->error = "Invalid block size";
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (kstrtoull(argv[3], 10, (unsigned long long *)&low_water_blocks)) {
+		ti->error = "Invalid low water mark";
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Set default pool features.
+	 */
+	memset(&pf, 0, sizeof(pf));
+	pf.zero_new_blocks = 1;
+
+	dm_consume_args(&as, 4);
+	r = parse_pool_features(&as, &pf, ti);
+	if (r)
+		goto out;
+
+	pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+	if (!pt) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+			   block_size, &ti->error);
+	if (IS_ERR(pool)) {
+		r = PTR_ERR(pool);
+		goto out_free_pt;
+	}
+
+	pt->pool = pool;
+	pt->ti = ti;
+	pt->metadata_dev = metadata_dev;
+	pt->data_dev = data_dev;
+	pt->low_water_blocks = low_water_blocks;
+	pt->zero_new_blocks = pf.zero_new_blocks;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->private = pt;
+
+	pt->callbacks.congested_fn = pool_is_congested;
+	dm_table_add_target_callbacks(ti->table, &pt->callbacks);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+out_free_pt:
+	kfree(pt);
+out:
+	dm_put_device(ti, data_dev);
+out_metadata:
+	dm_put_device(ti, metadata_dev);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int pool_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	/*
+	 * As this is a singleton target, ti->begin is always zero.
+	 */
+	spin_lock_irqsave(&pool->lock, flags);
+	bio->bi_bdev = pt->data_dev->bdev;
+	r = DM_MAPIO_REMAPPED;
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	return r;
+}
+
+/*
+ * Retrieves the number of blocks of the data device from
+ * the superblock and compares it to the actual device size,
+ * thus resizing the data device in case it has grown.
+ *
+ * This both copes with opening preallocated data devices in the ctr
+ * being followed by a resume
+ * -and-
+ * calling the resume method individually after userspace has
+ * grown the data device in reaction to a table event.
+ */
+static int pool_preresume(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	dm_block_t data_size, sb_data_size;
+
+	/*
+	 * Take control of the pool object.
+	 */
+	r = bind_control_target(pool, ti);
+	if (r)
+		return r;
+
+	data_size = ti->len >> pool->block_shift;
+	r = dm_pool_get_data_dev_size(pool->pmd, &sb_data_size);
+	if (r) {
+		DMERR("failed to retrieve data device size");
+		return r;
+	}
+
+	if (data_size < sb_data_size) {
+		DMERR("pool target too small, is %llu blocks (expected %llu)",
+		      data_size, sb_data_size);
+		return -EINVAL;
+
+	} else if (data_size > sb_data_size) {
+		r = dm_pool_resize_data_dev(pool->pmd, data_size);
+		if (r) {
+			DMERR("failed to resize data device");
+			return r;
+		}
+
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r) {
+			DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+			      __func__, r);
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+static void pool_resume(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	__requeue_bios(pool);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void pool_postsuspend(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	flush_workqueue(pool->wq);
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		/* FIXME: invalidate device? error the next FUA or FLUSH bio ?*/
+	}
+}
+
+static int check_arg_count(unsigned argc, unsigned args_required)
+{
+	if (argc != args_required) {
+		DMWARN("Message received with %u arguments instead of %u.",
+		       argc, args_required);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
+{
+	if (!kstrtoull(arg, 10, (unsigned long long *)dev_id) &&
+	    *dev_id <= MAX_DEV_ID)
+		return 0;
+
+	if (warning)
+		DMWARN("Message received with invalid device id: %s", arg);
+
+	return -EINVAL;
+}
+
+static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_thin(pool->pmd, dev_id);
+	if (r) {
+		DMWARN("Creation of new thinly-provisioned device with id %s failed.",
+		       argv[1]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	dm_thin_id origin_dev_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[2], &origin_dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_snap(pool->pmd, dev_id, origin_dev_id);
+	if (r) {
+		DMWARN("Creation of new snapshot %s of device %s failed.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_delete_thin_device(pool->pmd, dev_id);
+	if (r)
+		DMWARN("Deletion of thin device %s failed.", argv[1]);
+
+	return r;
+}
+
+static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id old_id, new_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	if (kstrtoull(argv[1], 10, (unsigned long long *)&old_id)) {
+		DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]);
+		return -EINVAL;
+	}
+
+	if (kstrtoull(argv[2], 10, (unsigned long long *)&new_id)) {
+		DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]);
+		return -EINVAL;
+	}
+
+	r = dm_pool_set_metadata_transaction_id(pool->pmd, old_id, new_id);
+	if (r) {
+		DMWARN("Failed to change transaction id from %s to %s.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Messages supported:
+ *   create_thin	<dev_id>
+ *   create_snap	<dev_id> <origin_id>
+ *   delete		<dev_id>
+ *   trim		<dev_id> <new_size_in_sectors>
+ *   set_transaction_id <current_trans_id> <new_trans_id>
+ */
+static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r = -EINVAL;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	if (!strcasecmp(argv[0], "create_thin"))
+		r = process_create_thin_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "create_snap"))
+		r = process_create_snap_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "delete"))
+		r = process_delete_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "set_transaction_id"))
+		r = process_set_transaction_id_mesg(argc, argv, pool);
+
+	else
+		DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
+
+	if (!r) {
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r)
+			DMERR("%s message: dm_pool_commit_metadata() failed, error = %d",
+			      argv[0], r);
+	}
+
+	return r;
+}
+
+/*
+ * Status line is:
+ *    <transaction id> <used metadata sectors>/<total metadata sectors>
+ *    <used data sectors>/<total data sectors> <held metadata root>
+ */
+static int pool_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	unsigned sz = 0;
+	uint64_t transaction_id;
+	dm_block_t nr_free_blocks_data;
+	dm_block_t nr_free_blocks_metadata;
+	dm_block_t nr_blocks_data;
+	dm_block_t nr_blocks_metadata;
+	dm_block_t held_root;
+	char buf[BDEVNAME_SIZE];
+	char buf2[BDEVNAME_SIZE];
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		r = dm_pool_get_metadata_transaction_id(pool->pmd,
+							&transaction_id);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_metadata_block_count(pool->pmd,
+							  &nr_free_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_block_count(pool->pmd,
+						 &nr_free_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_held_metadata_root(pool->pmd, &held_root);
+		if (r)
+			return r;
+
+		DMEMIT("%llu %llu/%llu %llu/%llu ",
+		       (unsigned long long)transaction_id,
+		       (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
+		       (unsigned long long)nr_blocks_metadata,
+		       (unsigned long long)(nr_blocks_data - nr_free_blocks_data),
+		       (unsigned long long)nr_blocks_data);
+
+		if (held_root)
+			DMEMIT("%llu", held_root);
+		else
+			DMEMIT("-");
+
+		break;
+
+	case STATUSTYPE_TABLE:
+		DMEMIT("%s %s %lu %llu ",
+		       format_dev_t(buf, pt->metadata_dev->bdev->bd_dev),
+		       format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
+		       (unsigned long)pool->sectors_per_block,
+		       (unsigned long long)pt->low_water_blocks);
+
+		DMEMIT("%u ", !pool->zero_new_blocks);
+
+		if (!pool->zero_new_blocks)
+			DMEMIT("skip_block_zeroing ");
+		break;
+	}
+
+	return 0;
+}
+
+static int pool_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	struct pool_c *pt = ti->private;
+
+	return fn(ti, pt->data_dev, 0, ti->len, data);
+}
+
+static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+		      struct bio_vec *biovec, int max_size)
+{
+	struct pool_c *pt = ti->private;
+	struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = pt->data_dev->bdev;
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type pool_target = {
+	.name = "thin-pool",
+	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
+		    DM_TARGET_IMMUTABLE,
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr = pool_ctr,
+	.dtr = pool_dtr,
+	.map = pool_map,
+	.postsuspend = pool_postsuspend,
+	.preresume = pool_preresume,
+	.resume = pool_resume,
+	.message = pool_message,
+	.status = pool_status,
+	.merge = pool_merge,
+	.iterate_devices = pool_iterate_devices,
+	.io_hints = pool_io_hints,
+};
+
+/*----------------------------------------------------------------
+ * Thin target methods
+ *--------------------------------------------------------------*/
+static void thin_dtr(struct dm_target *ti)
+{
+	struct thin_c *tc = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	__pool_dec(tc->pool);
+	dm_pool_close_thin_device(tc->td);
+	dm_put_device(ti, tc->pool_dev);
+	kfree(tc);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+/*
+ * Thin target parameters:
+ *
+ * <pool_dev> <dev_id>
+ *
+ * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
+ * dev_id: the internal device identifier
+ */
+static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct thin_c *tc;
+	struct dm_dev *pool_dev;
+	struct mapped_device *pool_md;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc != 2) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+
+	tc = ti->private = kzalloc(sizeof(*tc), GFP_KERNEL);
+	if (!tc) {
+		ti->error = "Out of memory";
+		r = -ENOMEM;
+		goto out_unlock;
+	}
+
+	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
+	if (r) {
+		ti->error = "Error opening pool device";
+		goto bad_pool_dev;
+	}
+	tc->pool_dev = pool_dev;
+
+	if (read_dev_id(argv[1], (unsigned long long *)&tc->dev_id, 0)) {
+		ti->error = "Invalid device id";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	pool_md = dm_get_md(tc->pool_dev->bdev->bd_dev);
+	if (!pool_md) {
+		ti->error = "Couldn't get pool mapped device";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	tc->pool = __pool_table_lookup(pool_md);
+	if (!tc->pool) {
+		ti->error = "Couldn't find pool object";
+		r = -EINVAL;
+		goto bad_pool_lookup;
+	}
+	__pool_inc(tc->pool);
+
+	r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
+	if (r) {
+		ti->error = "Couldn't open thin internal device";
+		goto bad_thin_open;
+	}
+
+	ti->split_io = tc->pool->sectors_per_block;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->discards_supported = 0;
+
+	dm_put(pool_md);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+bad_thin_open:
+	__pool_dec(tc->pool);
+bad_pool_lookup:
+	dm_put(pool_md);
+bad_common:
+	dm_put_device(ti, tc->pool_dev);
+bad_pool_dev:
+	kfree(tc);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int thin_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	bio->bi_sector -= ti->begin;
+
+	return thin_bio_map(ti, bio, map_context);
+}
+
+static void thin_postsuspend(struct dm_target *ti)
+{
+	if (dm_noflush_suspending(ti))
+		requeue_io((struct thin_c *)ti->private);
+}
+
+/*
+ * <nr mapped sectors> <highest mapped sector>
+ */
+static int thin_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	ssize_t sz = 0;
+	dm_block_t mapped, highest;
+	char buf[BDEVNAME_SIZE];
+	struct thin_c *tc = ti->private;
+
+	if (!tc->td)
+		DMEMIT("-");
+	else {
+		switch (type) {
+		case STATUSTYPE_INFO:
+			r = dm_thin_get_mapped_count(tc->td, &mapped);
+			if (r)
+				return r;
+
+			r = dm_thin_get_highest_mapped_block(tc->td, &highest);
+			if (r < 0)
+				return r;
+
+			DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
+			if (r)
+				DMEMIT("%llu", ((highest + 1) *
+						tc->pool->sectors_per_block) - 1);
+			else
+				DMEMIT("-");
+			break;
+
+		case STATUSTYPE_TABLE:
+			DMEMIT("%s %lu",
+			       format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
+			       (unsigned long) tc->dev_id);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int thin_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	dm_block_t blocks;
+	struct thin_c *tc = ti->private;
+
+	/*
+	 * We can't call dm_pool_get_data_dev_size() since that blocks.  So
+	 * we follow a more convoluted path through to the pool's target.
+	 */
+	if (!tc->pool->ti)
+		return 0;	/* nothing is bound */
+
+	blocks = tc->pool->ti->len >> tc->pool->block_shift;
+	if (blocks)
+		return fn(ti, tc->pool_dev, 0, tc->pool->sectors_per_block * blocks, data);
+
+	return 0;
+}
+
+static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct thin_c *tc = ti->private;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type thin_target = {
+	.name = "thin",
+	.version = {1, 0, 0},
+	.module	= THIS_MODULE,
+	.ctr = thin_ctr,
+	.dtr = thin_dtr,
+	.map = thin_map,
+	.postsuspend = thin_postsuspend,
+	.status = thin_status,
+	.iterate_devices = thin_iterate_devices,
+	.io_hints = thin_io_hints,
+};
+
+/*----------------------------------------------------------------*/
+
+static int __init dm_thin_init(void)
+{
+	int r;
+
+	pool_table_init();
+
+	r = dm_register_target(&thin_target);
+	if (r)
+		return r;
+
+	r = dm_register_target(&pool_target);
+	if (r)
+		dm_unregister_target(&thin_target);
+
+	return r;
+}
+
+static void dm_thin_exit(void)
+{
+	dm_unregister_target(&thin_target);
+	dm_unregister_target(&pool_target);
+}
+
+module_init(dm_thin_init);
+module_exit(dm_thin_exit);
+
+MODULE_DESCRIPTION(DM_NAME "device-mapper thin provisioning target");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-thin-metadata.c linux-libre-3.2-gnu1/drivers/md/dm-thin-metadata.c
--- linux-libre-3.1-gnu1/drivers/md/dm-thin-metadata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/dm-thin-metadata.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+#include "persistent-data/dm-btree.h"
+#include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-disk.h"
+#include "persistent-data/dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/device-mapper.h>
+#include <linux/workqueue.h>
+
+/*--------------------------------------------------------------------------
+ * As far as the metadata goes, there is:
+ *
+ * - A superblock in block zero, taking up fewer than 512 bytes for
+ *   atomic writes.
+ *
+ * - A space map managing the metadata blocks.
+ *
+ * - A space map managing the data blocks.
+ *
+ * - A btree mapping our internal thin dev ids onto struct disk_device_details.
+ *
+ * - A hierarchical btree, with 2 levels which effectively maps (thin
+ *   dev id, virtual block) -> block_time.  Block time is a 64-bit
+ *   field holding the time in the low 24 bits, and block in the top 48
+ *   bits.
+ *
+ * BTrees consist solely of btree_nodes, that fill a block.  Some are
+ * internal nodes, as such their values are a __le64 pointing to other
+ * nodes.  Leaf nodes can store data of any reasonable size (ie. much
+ * smaller than the block size).  The nodes consist of the header,
+ * followed by an array of keys, followed by an array of values.  We have
+ * to binary search on the keys so they're all held together to help the
+ * cpu cache.
+ *
+ * Space maps have 2 btrees:
+ *
+ * - One maps a uint64_t onto a struct index_entry.  Which points to a
+ *   bitmap block, and has some details about how many free entries there
+ *   are etc.
+ *
+ * - The bitmap blocks have a header (for the checksum).  Then the rest
+ *   of the block is pairs of bits.  With the meaning being:
+ *
+ *   0 - ref count is 0
+ *   1 - ref count is 1
+ *   2 - ref count is 2
+ *   3 - ref count is higher than 2
+ *
+ * - If the count is higher than 2 then the ref count is entered in a
+ *   second btree that directly maps the block_address to a uint32_t ref
+ *   count.
+ *
+ * The space map metadata variant doesn't have a bitmaps btree.  Instead
+ * it has one single blocks worth of index_entries.  This avoids
+ * recursive issues with the bitmap btree needing to allocate space in
+ * order to insert.  With a small data block size such as 64k the
+ * metadata support data devices that are hundreds of terrabytes.
+ *
+ * The space maps allocate space linearly from front to back.  Space that
+ * is freed in a transaction is never recycled within that transaction.
+ * To try and avoid fragmenting _free_ space the allocator always goes
+ * back and fills in gaps.
+ *
+ * All metadata io is in THIN_METADATA_BLOCK_SIZE sized/aligned chunks
+ * from the block manager.
+ *--------------------------------------------------------------------------*/
+
+#define DM_MSG_PREFIX   "thin metadata"
+
+#define THIN_SUPERBLOCK_MAGIC 27022010
+#define THIN_SUPERBLOCK_LOCATION 0
+#define THIN_VERSION 1
+#define THIN_METADATA_CACHE_SIZE 64
+#define SECTOR_TO_BLOCK_SHIFT 3
+
+/* This should be plenty */
+#define SPACE_MAP_ROOT_SIZE 128
+
+/*
+ * Little endian on-disk superblock and device details.
+ */
+struct thin_disk_superblock {
+	__le32 csum;	/* Checksum of superblock except for this field. */
+	__le32 flags;
+	__le64 blocknr;	/* This block number, dm_block_t. */
+
+	__u8 uuid[16];
+	__le64 magic;
+	__le32 version;
+	__le32 time;
+
+	__le64 trans_id;
+
+	/*
+	 * Root held by userspace transactions.
+	 */
+	__le64 held_root;
+
+	__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];
+	__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+	/*
+	 * 2-level btree mapping (dev_id, (dev block, time)) -> data block
+	 */
+	__le64 data_mapping_root;
+
+	/*
+	 * Device detail root mapping dev_id -> device_details
+	 */
+	__le64 device_details_root;
+
+	__le32 data_block_size;		/* In 512-byte sectors. */
+
+	__le32 metadata_block_size;	/* In 512-byte sectors. */
+	__le64 metadata_nr_blocks;
+
+	__le32 compat_flags;
+	__le32 compat_ro_flags;
+	__le32 incompat_flags;
+} __packed;
+
+struct disk_device_details {
+	__le64 mapped_blocks;
+	__le64 transaction_id;		/* When created. */
+	__le32 creation_time;
+	__le32 snapshotted_time;
+} __packed;
+
+struct dm_pool_metadata {
+	struct hlist_node hash;
+
+	struct block_device *bdev;
+	struct dm_block_manager *bm;
+	struct dm_space_map *metadata_sm;
+	struct dm_space_map *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_transaction_manager *nb_tm;
+
+	/*
+	 * Two-level btree.
+	 * First level holds thin_dev_t.
+	 * Second level holds mappings.
+	 */
+	struct dm_btree_info info;
+
+	/*
+	 * Non-blocking version of the above.
+	 */
+	struct dm_btree_info nb_info;
+
+	/*
+	 * Just the top level for deleting whole devices.
+	 */
+	struct dm_btree_info tl_info;
+
+	/*
+	 * Just the bottom level for creating new devices.
+	 */
+	struct dm_btree_info bl_info;
+
+	/*
+	 * Describes the device details btree.
+	 */
+	struct dm_btree_info details_info;
+
+	struct rw_semaphore root_lock;
+	uint32_t time;
+	int need_commit;
+	dm_block_t root;
+	dm_block_t details_root;
+	struct list_head thin_devices;
+	uint64_t trans_id;
+	unsigned long flags;
+	sector_t data_block_size;
+};
+
+struct dm_thin_device {
+	struct list_head list;
+	struct dm_pool_metadata *pmd;
+	dm_thin_id id;
+
+	int open_count;
+	int changed;
+	uint64_t mapped_blocks;
+	uint64_t transaction_id;
+	uint32_t creation_time;
+	uint32_t snapshotted_time;
+};
+
+/*----------------------------------------------------------------
+ * superblock validator
+ *--------------------------------------------------------------*/
+
+#define SUPERBLOCK_CSUM_XOR 160774
+
+static void sb_prepare_for_write(struct dm_block_validator *v,
+				 struct dm_block *b,
+				 size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+
+	disk_super->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_super->csum = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+						      block_size - sizeof(__le32),
+						      SUPERBLOCK_CSUM_XOR));
+}
+
+static int sb_check(struct dm_block_validator *v,
+		    struct dm_block *b,
+		    size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+	__le32 csum_le;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_super->blocknr)) {
+		DMERR("sb_check failed: blocknr %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->blocknr),
+		      (unsigned long long)dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	if (le64_to_cpu(disk_super->magic) != THIN_SUPERBLOCK_MAGIC) {
+		DMERR("sb_check failed: magic %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->magic),
+		      (unsigned long long)THIN_SUPERBLOCK_MAGIC);
+		return -EILSEQ;
+	}
+
+	csum_le = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+					     block_size - sizeof(__le32),
+					     SUPERBLOCK_CSUM_XOR));
+	if (csum_le != disk_super->csum) {
+		DMERR("sb_check failed: csum %u: wanted %u",
+		      le32_to_cpu(csum_le), le32_to_cpu(disk_super->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator sb_validator = {
+	.name = "superblock",
+	.prepare_for_write = sb_prepare_for_write,
+	.check = sb_check
+};
+
+/*----------------------------------------------------------------
+ * Methods for the btree value types
+ *--------------------------------------------------------------*/
+
+static uint64_t pack_block_time(dm_block_t b, uint32_t t)
+{
+	return (b << 24) | t;
+}
+
+static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
+{
+	*b = v >> 24;
+	*t = v & ((1 << 24) - 1);
+}
+
+static void data_block_inc(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_inc_block(sm, b);
+}
+
+static void data_block_dec(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_dec_block(sm, b);
+}
+
+static int data_block_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	uint64_t b1, b2;
+	uint32_t t;
+
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+	unpack_block_time(le64_to_cpu(v1_le), &b1, &t);
+	unpack_block_time(le64_to_cpu(v2_le), &b2, &t);
+
+	return b1 == b2;
+}
+
+static void subtree_inc(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	dm_tm_inc(info->tm, root);
+}
+
+static void subtree_dec(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	if (dm_btree_del(info, root))
+		DMERR("btree delete failed\n");
+}
+
+static int subtree_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+
+	return v1_le == v2_le;
+}
+
+/*----------------------------------------------------------------*/
+
+static int superblock_all_zeroes(struct dm_block_manager *bm, int *result)
+{
+	int r;
+	unsigned i;
+	struct dm_block *b;
+	__le64 *data_le, zero = cpu_to_le64(0);
+	unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+
+	/*
+	 * We can't use a validator here - it may be all zeroes.
+	 */
+	r = dm_bm_read_lock(bm, THIN_SUPERBLOCK_LOCATION, NULL, &b);
+	if (r)
+		return r;
+
+	data_le = dm_block_data(b);
+	*result = 1;
+	for (i = 0; i < block_size; i++) {
+		if (data_le[i] != zero) {
+			*result = 0;
+			break;
+		}
+	}
+
+	return dm_bm_unlock(b);
+}
+
+static int init_pmd(struct dm_pool_metadata *pmd,
+		    struct dm_block_manager *bm,
+		    dm_block_t nr_blocks, int create)
+{
+	int r;
+	struct dm_space_map *sm, *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_block *sblock;
+
+	if (create) {
+		r = dm_tm_create_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+					 &sb_validator, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_create_with_sm failed");
+			return r;
+		}
+
+		data_sm = dm_sm_disk_create(tm, nr_blocks);
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_create failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	} else {
+		struct thin_disk_superblock *disk_super = NULL;
+		size_t space_map_root_offset =
+			offsetof(struct thin_disk_superblock, metadata_space_map_root);
+
+		r = dm_tm_open_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+				       &sb_validator, space_map_root_offset,
+				       SPACE_MAP_ROOT_SIZE, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_open_with_sm failed");
+			return r;
+		}
+
+		disk_super = dm_block_data(sblock);
+		data_sm = dm_sm_disk_open(tm, disk_super->data_space_map_root,
+					  sizeof(disk_super->data_space_map_root));
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_open failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	}
+
+
+	r = dm_tm_unlock(tm, sblock);
+	if (r < 0) {
+		DMERR("couldn't unlock superblock");
+		goto bad_data_sm;
+	}
+
+	pmd->bm = bm;
+	pmd->metadata_sm = sm;
+	pmd->data_sm = data_sm;
+	pmd->tm = tm;
+	pmd->nb_tm = dm_tm_create_non_blocking_clone(tm);
+	if (!pmd->nb_tm) {
+		DMERR("could not create clone tm");
+		r = -ENOMEM;
+		goto bad_data_sm;
+	}
+
+	pmd->info.tm = tm;
+	pmd->info.levels = 2;
+	pmd->info.value_type.context = pmd->data_sm;
+	pmd->info.value_type.size = sizeof(__le64);
+	pmd->info.value_type.inc = data_block_inc;
+	pmd->info.value_type.dec = data_block_dec;
+	pmd->info.value_type.equal = data_block_equal;
+
+	memcpy(&pmd->nb_info, &pmd->info, sizeof(pmd->nb_info));
+	pmd->nb_info.tm = pmd->nb_tm;
+
+	pmd->tl_info.tm = tm;
+	pmd->tl_info.levels = 1;
+	pmd->tl_info.value_type.context = &pmd->info;
+	pmd->tl_info.value_type.size = sizeof(__le64);
+	pmd->tl_info.value_type.inc = subtree_inc;
+	pmd->tl_info.value_type.dec = subtree_dec;
+	pmd->tl_info.value_type.equal = subtree_equal;
+
+	pmd->bl_info.tm = tm;
+	pmd->bl_info.levels = 1;
+	pmd->bl_info.value_type.context = pmd->data_sm;
+	pmd->bl_info.value_type.size = sizeof(__le64);
+	pmd->bl_info.value_type.inc = data_block_inc;
+	pmd->bl_info.value_type.dec = data_block_dec;
+	pmd->bl_info.value_type.equal = data_block_equal;
+
+	pmd->details_info.tm = tm;
+	pmd->details_info.levels = 1;
+	pmd->details_info.value_type.context = NULL;
+	pmd->details_info.value_type.size = sizeof(struct disk_device_details);
+	pmd->details_info.value_type.inc = NULL;
+	pmd->details_info.value_type.dec = NULL;
+	pmd->details_info.value_type.equal = NULL;
+
+	pmd->root = 0;
+
+	init_rwsem(&pmd->root_lock);
+	pmd->time = 0;
+	pmd->need_commit = 0;
+	pmd->details_root = 0;
+	pmd->trans_id = 0;
+	pmd->flags = 0;
+	INIT_LIST_HEAD(&pmd->thin_devices);
+
+	return 0;
+
+bad_data_sm:
+	dm_sm_destroy(data_sm);
+bad:
+	dm_tm_destroy(tm);
+	dm_sm_destroy(sm);
+
+	return r;
+}
+
+static int __begin_transaction(struct dm_pool_metadata *pmd)
+{
+	int r;
+	u32 features;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * __maybe_commit_transaction() resets these
+	 */
+	WARN_ON(pmd->need_commit);
+
+	/*
+	 * We re-read the superblock every time.  Shouldn't need to do this
+	 * really.
+	 */
+	r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			    &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	pmd->time = le32_to_cpu(disk_super->time);
+	pmd->root = le64_to_cpu(disk_super->data_mapping_root);
+	pmd->details_root = le64_to_cpu(disk_super->device_details_root);
+	pmd->trans_id = le64_to_cpu(disk_super->trans_id);
+	pmd->flags = le32_to_cpu(disk_super->flags);
+	pmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
+
+	features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
+	if (features) {
+		DMERR("could not access metadata due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Check for read-only metadata to skip the following RDWR checks.
+	 */
+	if (get_disk_ro(pmd->bdev->bd_disk))
+		goto out;
+
+	features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
+	if (features) {
+		DMERR("could not access metadata RDWR due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+	}
+
+out:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+static int __write_changed_details(struct dm_pool_metadata *pmd)
+{
+	int r;
+	struct dm_thin_device *td, *tmp;
+	struct disk_device_details details;
+	uint64_t key;
+
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (!td->changed)
+			continue;
+
+		key = td->id;
+
+		details.mapped_blocks = cpu_to_le64(td->mapped_blocks);
+		details.transaction_id = cpu_to_le64(td->transaction_id);
+		details.creation_time = cpu_to_le32(td->creation_time);
+		details.snapshotted_time = cpu_to_le32(td->snapshotted_time);
+		__dm_bless_for_disk(&details);
+
+		r = dm_btree_insert(&pmd->details_info, pmd->details_root,
+				    &key, &details, &pmd->details_root);
+		if (r)
+			return r;
+
+		if (td->open_count)
+			td->changed = 0;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+
+		pmd->need_commit = 1;
+	}
+
+	return 0;
+}
+
+static int __commit_transaction(struct dm_pool_metadata *pmd)
+{
+	/*
+	 * FIXME: Associated pool should be made read-only on failure.
+	 */
+	int r;
+	size_t metadata_len, data_len;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
+	 */
+	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+
+	r = __write_changed_details(pmd);
+	if (r < 0)
+		goto out;
+
+	if (!pmd->need_commit)
+		goto out;
+
+	r = dm_sm_commit(pmd->data_sm);
+	if (r < 0)
+		goto out;
+
+	r = dm_tm_pre_commit(pmd->tm);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &metadata_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto out;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->time = cpu_to_le32(pmd->time);
+	disk_super->data_mapping_root = cpu_to_le64(pmd->root);
+	disk_super->device_details_root = cpu_to_le64(pmd->details_root);
+	disk_super->trans_id = cpu_to_le64(pmd->trans_id);
+	disk_super->flags = cpu_to_le32(pmd->flags);
+
+	r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
+			    metadata_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
+			    data_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_tm_commit(pmd->tm, sblock);
+	if (!r)
+		pmd->need_commit = 0;
+
+out:
+	return r;
+
+out_locked:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_pool_metadata *pmd;
+	sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	struct dm_block_manager *bm;
+	int create;
+	struct dm_block *sblock;
+
+	pmd = kmalloc(sizeof(*pmd), GFP_KERNEL);
+	if (!pmd) {
+		DMERR("could not allocate metadata struct");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/*
+	 * Max hex locks:
+	 *  3 for btree insert +
+	 *  2 for btree lookup used within space map
+	 */
+	bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE,
+				     THIN_METADATA_CACHE_SIZE, 5);
+	if (!bm) {
+		DMERR("could not create block manager");
+		kfree(pmd);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	r = superblock_all_zeroes(bm, &create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+
+
+	r = init_pmd(pmd, bm, 0, create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+	pmd->bdev = bdev;
+
+	if (!create) {
+		r = __begin_transaction(pmd);
+		if (r < 0)
+			goto bad;
+		return pmd;
+	}
+
+	/*
+	 * Create.
+	 */
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto bad;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
+	disk_super->version = cpu_to_le32(THIN_VERSION);
+	disk_super->time = 0;
+	disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
+	disk_super->data_block_size = cpu_to_le32(data_block_size);
+
+	r = dm_bm_unlock(sblock);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->info, &pmd->root);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->details_info, &pmd->details_root);
+	if (r < 0) {
+		DMERR("couldn't create devices root");
+		goto bad;
+	}
+
+	pmd->flags = 0;
+	pmd->need_commit = 1;
+	r = dm_pool_commit_metadata(pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		goto bad;
+	}
+
+	return pmd;
+
+bad:
+	if (dm_pool_metadata_close(pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+	return ERR_PTR(r);
+}
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
+{
+	int r;
+	unsigned open_devices = 0;
+	struct dm_thin_device *td, *tmp;
+
+	down_read(&pmd->root_lock);
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (td->open_count)
+			open_devices++;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+	}
+	up_read(&pmd->root_lock);
+
+	if (open_devices) {
+		DMERR("attempt to close pmd when %u device(s) are still open",
+		       open_devices);
+		return -EBUSY;
+	}
+
+	r = __commit_transaction(pmd);
+	if (r < 0)
+		DMWARN("%s: __commit_transaction() failed, error = %d",
+		       __func__, r);
+
+	dm_tm_destroy(pmd->tm);
+	dm_tm_destroy(pmd->nb_tm);
+	dm_block_manager_destroy(pmd->bm);
+	dm_sm_destroy(pmd->metadata_sm);
+	dm_sm_destroy(pmd->data_sm);
+	kfree(pmd);
+
+	return 0;
+}
+
+static int __open_device(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, int create,
+			 struct dm_thin_device **td)
+{
+	int r, changed = 0;
+	struct dm_thin_device *td2;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+
+	/*
+	 * Check the device isn't already open.
+	 */
+	list_for_each_entry(td2, &pmd->thin_devices, list)
+		if (td2->id == dev) {
+			td2->open_count++;
+			*td = td2;
+			return 0;
+		}
+
+	/*
+	 * Check the device exists.
+	 */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (r) {
+		if (r != -ENODATA || !create)
+			return r;
+
+		changed = 1;
+		details_le.mapped_blocks = 0;
+		details_le.transaction_id = cpu_to_le64(pmd->trans_id);
+		details_le.creation_time = cpu_to_le32(pmd->time);
+		details_le.snapshotted_time = cpu_to_le32(pmd->time);
+	}
+
+	*td = kmalloc(sizeof(**td), GFP_NOIO);
+	if (!*td)
+		return -ENOMEM;
+
+	(*td)->pmd = pmd;
+	(*td)->id = dev;
+	(*td)->open_count = 1;
+	(*td)->changed = changed;
+	(*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
+	(*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
+	(*td)->creation_time = le32_to_cpu(details_le.creation_time);
+	(*td)->snapshotted_time = le32_to_cpu(details_le.snapshotted_time);
+
+	list_add(&(*td)->list, &pmd->thin_devices);
+
+	return 0;
+}
+
+static void __close_device(struct dm_thin_device *td)
+{
+	--td->open_count;
+}
+
+static int __create_thin(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev)
+{
+	int r;
+	dm_block_t dev_root;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+	struct dm_thin_device *td;
+	__le64 value;
+
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/*
+	 * Create an empty btree for the mappings.
+	 */
+	r = dm_btree_empty(&pmd->bl_info, &dev_root);
+	if (r)
+		return r;
+
+	/*
+	 * Insert it into the main mapping tree.
+	 */
+	value = cpu_to_le64(dev_root);
+	__dm_bless_for_disk(&value);
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r) {
+		__close_device(td);
+		dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+	td->changed = 1;
+	__close_device(td);
+
+	return r;
+}
+
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_thin(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __set_snapshot_details(struct dm_pool_metadata *pmd,
+				  struct dm_thin_device *snap,
+				  dm_thin_id origin, uint32_t time)
+{
+	int r;
+	struct dm_thin_device *td;
+
+	r = __open_device(pmd, origin, 0, &td);
+	if (r)
+		return r;
+
+	td->changed = 1;
+	td->snapshotted_time = time;
+
+	snap->mapped_blocks = td->mapped_blocks;
+	snap->snapshotted_time = time;
+	__close_device(td);
+
+	return 0;
+}
+
+static int __create_snap(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, dm_thin_id origin)
+{
+	int r;
+	dm_block_t origin_root;
+	uint64_t key = origin, dev_key = dev;
+	struct dm_thin_device *td;
+	struct disk_device_details details_le;
+	__le64 value;
+
+	/* check this device is unused */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &dev_key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/* find the mapping tree for the origin */
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &key, &value);
+	if (r)
+		return r;
+	origin_root = le64_to_cpu(value);
+
+	/* clone the origin, an inc will do */
+	dm_tm_inc(pmd->tm, origin_root);
+
+	/* insert into the main mapping tree */
+	value = cpu_to_le64(origin_root);
+	__dm_bless_for_disk(&value);
+	key = dev;
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_tm_dec(pmd->tm, origin_root);
+		return r;
+	}
+
+	pmd->time++;
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r)
+		goto bad;
+
+	r = __set_snapshot_details(pmd, td, origin, pmd->time);
+	if (r)
+		goto bad;
+
+	__close_device(td);
+	return 0;
+
+bad:
+	__close_device(td);
+	dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	dm_btree_remove(&pmd->details_info, pmd->details_root,
+			&key, &pmd->details_root);
+	return r;
+}
+
+int dm_pool_create_snap(struct dm_pool_metadata *pmd,
+				 dm_thin_id dev,
+				 dm_thin_id origin)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_snap(pmd, dev, origin);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+	uint64_t key = dev;
+	struct dm_thin_device *td;
+
+	/* TODO: failure should mark the transaction invalid */
+	r = __open_device(pmd, dev, 0, &td);
+	if (r)
+		return r;
+
+	if (td->open_count > 1) {
+		__close_device(td);
+		return -EBUSY;
+	}
+
+	list_del(&td->list);
+	kfree(td);
+	r = dm_btree_remove(&pmd->details_info, pmd->details_root,
+			    &key, &pmd->details_root);
+	if (r)
+		return r;
+
+	r = dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __delete_device(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id)
+{
+	down_write(&pmd->root_lock);
+	if (pmd->trans_id != current_id) {
+		up_write(&pmd->root_lock);
+		DMERR("mismatched transaction id");
+		return -EINVAL;
+	}
+
+	pmd->trans_id = new_id;
+	pmd->need_commit = 1;
+	up_write(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->trans_id;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
+				    dm_block_t *result)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	*result = le64_to_cpu(disk_super->held_root);
+
+	return dm_bm_unlock(sblock);
+}
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = __get_held_metadata_root(pmd, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __open_device(pmd, dev, 0, td);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_close_thin_device(struct dm_thin_device *td)
+{
+	down_write(&td->pmd->root_lock);
+	__close_device(td);
+	up_write(&td->pmd->root_lock);
+
+	return 0;
+}
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td)
+{
+	return td->id;
+}
+
+static int __snapshotted_since(struct dm_thin_device *td, uint32_t time)
+{
+	return td->snapshotted_time > time;
+}
+
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result)
+{
+	int r;
+	uint64_t block_time = 0;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	if (can_block) {
+		down_read(&pmd->root_lock);
+		r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else if (down_read_trylock(&pmd->root_lock)) {
+		r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else
+		return -EWOULDBLOCK;
+
+	if (!r) {
+		dm_block_t exception_block;
+		uint32_t exception_time;
+		unpack_block_time(block_time, &exception_block,
+				  &exception_time);
+		result->block = exception_block;
+		result->shared = __snapshotted_since(td, exception_time);
+	}
+
+	return r;
+}
+
+static int __insert(struct dm_thin_device *td, dm_block_t block,
+		    dm_block_t data_block)
+{
+	int r, inserted;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	pmd->need_commit = 1;
+	value = cpu_to_le64(pack_block_time(data_block, pmd->time));
+	__dm_bless_for_disk(&value);
+
+	r = dm_btree_insert_notify(&pmd->info, pmd->root, keys, &value,
+				   &pmd->root, &inserted);
+	if (r)
+		return r;
+
+	if (inserted) {
+		td->mapped_blocks++;
+		td->changed = 1;
+	}
+
+	return 0;
+}
+
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __insert(td, block, data_block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+static int __remove(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	r = dm_btree_remove(&pmd->info, pmd->root, keys, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __remove(td, block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = dm_sm_new_block(pmd->data_sm, result);
+	pmd->need_commit = 1;
+
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = __commit_transaction(pmd);
+	if (r <= 0)
+		goto out;
+
+	/*
+	 * Open the next transaction.
+	 */
+	r = __begin_transaction(pmd);
+out:
+	up_write(&pmd->root_lock);
+	return r;
+}
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->data_block_size;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result)
+{
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	*result = td->mapped_blocks;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
+{
+	int r;
+	__le64 value_le;
+	dm_block_t thin_root;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &td->id, &value_le);
+	if (r)
+		return r;
+
+	thin_root = le64_to_cpu(value_le);
+
+	return dm_btree_find_highest_key(&pmd->bl_info, thin_root, result);
+}
+
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *result)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	r = __highest_block(td, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+	dm_block_t old_count;
+
+	r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
+	if (r)
+		return r;
+
+	if (new_count == old_count)
+		return 0;
+
+	if (new_count < old_count) {
+		DMERR("cannot reduce size of data device");
+		return -EINVAL;
+	}
+
+	r = dm_sm_extend(pmd->data_sm, new_count - old_count);
+	if (!r)
+		pmd->need_commit = 1;
+
+	return r;
+}
+
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __resize_data_dev(pmd, new_count);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-thin-metadata.h linux-libre-3.2-gnu1/drivers/md/dm-thin-metadata.h
--- linux-libre-3.1-gnu1/drivers/md/dm-thin-metadata.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/dm-thin-metadata.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_THIN_METADATA_H
+#define DM_THIN_METADATA_H
+
+#include "persistent-data/dm-block-manager.h"
+
+#define THIN_METADATA_BLOCK_SIZE 4096
+
+/*----------------------------------------------------------------*/
+
+struct dm_pool_metadata;
+struct dm_thin_device;
+
+/*
+ * Device identifier
+ */
+typedef uint64_t dm_thin_id;
+
+/*
+ * Reopens or creates a new, empty metadata volume.
+ */
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size);
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
+
+/*
+ * Compat feature flags.  Any incompat flags beyond the ones
+ * specified below will prevent use of the thin metadata.
+ */
+#define THIN_FEATURE_COMPAT_SUPP	  0UL
+#define THIN_FEATURE_COMPAT_RO_SUPP	  0UL
+#define THIN_FEATURE_INCOMPAT_SUPP	  0UL
+
+/*
+ * Device creation/deletion.
+ */
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev);
+
+/*
+ * An internal snapshot.
+ *
+ * You can only snapshot a quiesced origin i.e. one that is either
+ * suspended or not instanced at all.
+ */
+int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			dm_thin_id origin);
+
+/*
+ * Deletes a virtual device from the metadata.  It _is_ safe to call this
+ * when that device is open.  Operations on that device will just start
+ * failing.  You still need to call close() on the device.
+ */
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev);
+
+/*
+ * Commits _all_ metadata changes: device creation, deletion, mapping
+ * updates.
+ */
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
+
+/*
+ * Set/get userspace transaction id.
+ */
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id);
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result);
+
+/*
+ * Hold/get root for userspace transaction.
+ */
+int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd);
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result);
+
+/*
+ * Actions on a single virtual device.
+ */
+
+/*
+ * Opening the same device more than once will fail with -EBUSY.
+ */
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td);
+
+int dm_pool_close_thin_device(struct dm_thin_device *td);
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td);
+
+struct dm_thin_lookup_result {
+	dm_block_t block;
+	int shared;
+};
+
+/*
+ * Returns:
+ *   -EWOULDBLOCK iff @can_block is set and would block.
+ *   -ENODATA iff that mapping is not present.
+ *   0 success
+ */
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result);
+
+/*
+ * Obtain an unused block.
+ */
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Insert or remove block.
+ */
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block);
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
+
+/*
+ * Queries.
+ */
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *highest_mapped);
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result);
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd,
+				 dm_block_t *result);
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result);
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result);
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result);
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Returns -ENOSPC if the new size is too small and already allocated
+ * blocks would be lost.
+ */
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/dm-uevent.c linux-libre-3.2-gnu1/drivers/md/dm-uevent.c
--- linux-libre-3.1-gnu1/drivers/md/dm-uevent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/dm-uevent.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/kobject.h>
 #include <linux/dm-ioctl.h>
+#include <linux/export.h>
 
 #include "dm.h"
 #include "dm-uevent.h"
diff -druNp linux-libre-3.1-gnu1/drivers/md/faulty.c linux-libre-3.2-gnu1/drivers/md/faulty.c
--- linux-libre-3.1-gnu1/drivers/md/faulty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/faulty.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@
 
 #define MaxFault	50
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/raid/md_u.h>
 #include <linux/slab.h>
 #include "md.h"
@@ -81,16 +82,16 @@ static void faulty_fail(struct bio *bio,
 	bio_io_error(b);
 }
 
-typedef struct faulty_conf {
+struct faulty_conf {
 	int period[Modes];
 	atomic_t counters[Modes];
 	sector_t faults[MaxFault];
 	int	modes[MaxFault];
 	int nfaults;
-	mdk_rdev_t *rdev;
-} conf_t;
+	struct md_rdev *rdev;
+};
 
-static int check_mode(conf_t *conf, int mode)
+static int check_mode(struct faulty_conf *conf, int mode)
 {
 	if (conf->period[mode] == 0 &&
 	    atomic_read(&conf->counters[mode]) <= 0)
@@ -105,7 +106,7 @@ static int check_mode(conf_t *conf, int
 	return 0;
 }
 
-static int check_sector(conf_t *conf, sector_t start, sector_t end, int dir)
+static int check_sector(struct faulty_conf *conf, sector_t start, sector_t end, int dir)
 {
 	/* If we find a ReadFixable sector, we fix it ... */
 	int i;
@@ -129,7 +130,7 @@ static int check_sector(conf_t *conf, se
 	return 0;
 }
 
-static void add_sector(conf_t *conf, sector_t start, int mode)
+static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
 {
 	int i;
 	int n = conf->nfaults;
@@ -169,9 +170,9 @@ static void add_sector(conf_t *conf, sec
 		conf->nfaults = n+1;
 }
 
-static int make_request(mddev_t *mddev, struct bio *bio)
+static void make_request(struct mddev *mddev, struct bio *bio)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 	int failit = 0;
 
 	if (bio_data_dir(bio) == WRITE) {
@@ -181,7 +182,7 @@ static int make_request(mddev_t *mddev,
 			 * just fail immediately
 			 */
 			bio_endio(bio, -EIO);
-			return 0;
+			return;
 		}
 
 		if (check_sector(conf, bio->bi_sector, bio->bi_sector+(bio->bi_size>>9),
@@ -211,20 +212,20 @@ static int make_request(mddev_t *mddev,
 	}
 	if (failit) {
 		struct bio *b = bio_clone_mddev(bio, GFP_NOIO, mddev);
+
 		b->bi_bdev = conf->rdev->bdev;
 		b->bi_private = bio;
 		b->bi_end_io = faulty_fail;
-		generic_make_request(b);
-		return 0;
-	} else {
+		bio = b;
+	} else
 		bio->bi_bdev = conf->rdev->bdev;
-		return 1;
-	}
+
+	generic_make_request(bio);
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 	int n;
 
 	if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
@@ -255,11 +256,11 @@ static void status(struct seq_file *seq,
 }
 
 
-static int reshape(mddev_t *mddev)
+static int reshape(struct mddev *mddev)
 {
 	int mode = mddev->new_layout & ModeMask;
 	int count = mddev->new_layout >> ModeShift;
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 
 	if (mddev->new_layout < 0)
 		return 0;
@@ -284,7 +285,7 @@ static int reshape(mddev_t *mddev)
 	return 0;
 }
 
-static sector_t faulty_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t faulty_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	WARN_ONCE(raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -295,11 +296,11 @@ static sector_t faulty_size(mddev_t *mdd
 	return sectors;
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int i;
-	conf_t *conf;
+	struct faulty_conf *conf;
 
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
@@ -325,16 +326,16 @@ static int run(mddev_t *mddev)
 	return 0;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
 }
 
-static struct mdk_personality faulty_personality =
+static struct md_personality faulty_personality =
 {
 	.name		= "faulty",
 	.level		= LEVEL_FAULTY,
diff -druNp linux-libre-3.1-gnu1/drivers/md/Kconfig linux-libre-3.2-gnu1/drivers/md/Kconfig
--- linux-libre-3.1-gnu1/drivers/md/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -208,6 +208,16 @@ config DM_DEBUG
 
 	  If unsure, say N.
 
+config DM_BUFIO
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+	 This interface allows you to do buffered I/O on a device and acts
+	 as a cache, holding recently-read blocks in memory and performing
+	 delayed writes.
+
+source "drivers/md/persistent-data/Kconfig"
+
 config DM_CRYPT
 	tristate "Crypt target support"
 	depends on BLK_DEV_DM
@@ -233,6 +243,32 @@ config DM_SNAPSHOT
        ---help---
          Allow volume managers to take writable snapshots of a device.
 
+config DM_THIN_PROVISIONING
+       tristate "Thin provisioning target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select DM_PERSISTENT_DATA
+       ---help---
+         Provides thin provisioning and snapshots that share a data store.
+
+config DM_DEBUG_BLOCK_STACK_TRACING
+	boolean "Keep stack trace of thin provisioning block lock holders"
+	depends on STACKTRACE_SUPPORT && DM_THIN_PROVISIONING
+	select STACKTRACE
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  block manager locking used by thin provisioning.
+
+	  If unsure, say N.
+
+config DM_DEBUG_SPACE_MAPS
+	boolean "Extra validation for thin provisioning space maps"
+	depends on DM_THIN_PROVISIONING
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  space maps used by thin provisioning.
+
+          If unsure, say N.
+
 config DM_MIRROR
        tristate "Mirror target"
        depends on BLK_DEV_DM
diff -druNp linux-libre-3.1-gnu1/drivers/md/linear.c linux-libre-3.2-gnu1/drivers/md/linear.c
--- linux-libre-3.1-gnu1/drivers/md/linear.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/linear.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/blkdev.h>
 #include <linux/raid/md_u.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include "md.h"
 #include "linear.h"
@@ -26,10 +27,10 @@
 /*
  * find which device holds a particular offset 
  */
-static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
 {
 	int lo, mid, hi;
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 
 	lo = 0;
 	hi = mddev->raid_disks - 1;
@@ -63,8 +64,8 @@ static int linear_mergeable_bvec(struct
 				 struct bvec_merge_data *bvm,
 				 struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
-	dev_info_t *dev0;
+	struct mddev *mddev = q->queuedata;
+	struct dev_info *dev0;
 	unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
@@ -89,8 +90,8 @@ static int linear_mergeable_bvec(struct
 
 static int linear_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	linear_conf_t *conf;
+	struct mddev *mddev = data;
+	struct linear_conf *conf;
 	int i, ret = 0;
 
 	if (mddev_congested(mddev, bits))
@@ -108,9 +109,9 @@ static int linear_congested(void *data,
 	return ret;
 }
 
-static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 	sector_t array_sectors;
 
 	rcu_read_lock();
@@ -123,13 +124,13 @@ static sector_t linear_size(mddev_t *mdd
 	return array_sectors;
 }
 
-static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
+static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
 {
-	linear_conf_t *conf;
-	mdk_rdev_t *rdev;
+	struct linear_conf *conf;
+	struct md_rdev *rdev;
 	int i, cnt;
 
-	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
+	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
 			GFP_KERNEL);
 	if (!conf)
 		return NULL;
@@ -139,7 +140,7 @@ static linear_conf_t *linear_conf(mddev_
 
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		int j = rdev->raid_disk;
-		dev_info_t *disk = conf->disks + j;
+		struct dev_info *disk = conf->disks + j;
 		sector_t sectors;
 
 		if (j < 0 || j >= raid_disks || disk->rdev) {
@@ -194,9 +195,9 @@ out:
 	return NULL;
 }
 
-static int linear_run (mddev_t *mddev)
+static int linear_run (struct mddev *mddev)
 {
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
@@ -213,7 +214,7 @@ static int linear_run (mddev_t *mddev)
 	return md_integrity_register(mddev);
 }
 
-static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
+static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
 {
 	/* Adding a drive to a linear array allows the array to grow.
 	 * It is permitted if the new drive has a matching superblock
@@ -223,12 +224,13 @@ static int linear_add(mddev_t *mddev, md
 	 * The current one is never freed until the array is stopped.
 	 * This avoids races.
 	 */
-	linear_conf_t *newconf, *oldconf;
+	struct linear_conf *newconf, *oldconf;
 
 	if (rdev->saved_raid_disk != mddev->raid_disks)
 		return -EINVAL;
 
 	rdev->raid_disk = rdev->saved_raid_disk;
+	rdev->saved_raid_disk = -1;
 
 	newconf = linear_conf(mddev,mddev->raid_disks+1);
 
@@ -245,9 +247,9 @@ static int linear_add(mddev_t *mddev, md
 	return 0;
 }
 
-static int linear_stop (mddev_t *mddev)
+static int linear_stop (struct mddev *mddev)
 {
-	linear_conf_t *conf = mddev->private;
+	struct linear_conf *conf = mddev->private;
 
 	/*
 	 * We do not require rcu protection here since
@@ -264,14 +266,14 @@ static int linear_stop (mddev_t *mddev)
 	return 0;
 }
 
-static int linear_make_request (mddev_t *mddev, struct bio *bio)
+static void linear_make_request(struct mddev *mddev, struct bio *bio)
 {
-	dev_info_t *tmp_dev;
+	struct dev_info *tmp_dev;
 	sector_t start_sector;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	rcu_read_lock();
@@ -293,7 +295,7 @@ static int linear_make_request (mddev_t
 		       (unsigned long long)start_sector);
 		rcu_read_unlock();
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
 		     tmp_dev->end_sector)) {
@@ -307,30 +309,27 @@ static int linear_make_request (mddev_t
 
 		bp = bio_split(bio, end_sector - bio->bi_sector);
 
-		if (linear_make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (linear_make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
+		linear_make_request(mddev, &bp->bio1);
+		linear_make_request(mddev, &bp->bio2);
 		bio_pair_release(bp);
-		return 0;
+		return;
 	}
 		    
 	bio->bi_bdev = tmp_dev->rdev->bdev;
 	bio->bi_sector = bio->bi_sector - start_sector
 		+ tmp_dev->rdev->data_offset;
 	rcu_read_unlock();
-
-	return 1;
+	generic_make_request(bio);
 }
 
-static void linear_status (struct seq_file *seq, mddev_t *mddev)
+static void linear_status (struct seq_file *seq, struct mddev *mddev)
 {
 
 	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
 }
 
 
-static struct mdk_personality linear_personality =
+static struct md_personality linear_personality =
 {
 	.name		= "linear",
 	.level		= LEVEL_LINEAR,
diff -druNp linux-libre-3.1-gnu1/drivers/md/linear.h linux-libre-3.2-gnu1/drivers/md/linear.h
--- linux-libre-3.1-gnu1/drivers/md/linear.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/linear.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,20 +2,14 @@
 #define _LINEAR_H
 
 struct dev_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	end_sector;
 };
 
-typedef struct dev_info dev_info_t;
-
-struct linear_private_data
+struct linear_conf
 {
 	struct rcu_head		rcu;
 	sector_t		array_sectors;
-	dev_info_t		disks[0];
+	struct dev_info		disks[0];
 };
-
-
-typedef struct linear_private_data linear_conf_t;
-
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/Makefile linux-libre-3.2-gnu1/drivers/md/Makefile
--- linux-libre-3.1-gnu1/drivers/md/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@ dm-snapshot-y	+= dm-snap.o dm-exception-
 dm-mirror-y	+= dm-raid1.o
 dm-log-userspace-y \
 		+= dm-log-userspace-base.o dm-log-userspace-transfer.o
+dm-thin-pool-y	+= dm-thin.o dm-thin-metadata.o
 md-mod-y	+= md.o bitmap.o
 raid456-y	+= raid5.o
 
@@ -27,6 +28,7 @@ obj-$(CONFIG_MD_MULTIPATH)	+= multipath.
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
@@ -34,10 +36,12 @@ obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipa
 obj-$(CONFIG_DM_MULTIPATH_QL)	+= dm-queue-length.o
 obj-$(CONFIG_DM_MULTIPATH_ST)	+= dm-service-time.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
+obj-$(CONFIG_DM_PERSISTENT_DATA)	+= persistent-data/
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o dm-region-hash.o
 obj-$(CONFIG_DM_LOG_USERSPACE)	+= dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 obj-$(CONFIG_DM_RAID)	+= dm-raid.o
+obj-$(CONFIG_DM_THIN_PROVISIONING)	+= dm-thin-pool.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
diff -druNp linux-libre-3.1-gnu1/drivers/md/md.c linux-libre-3.2-gnu1/drivers/md/md.c
--- linux-libre-3.1-gnu1/drivers/md/md.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/md.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,7 @@
 #include <linux/hdreg.h>
 #include <linux/proc_fs.h>
 #include <linux/random.h>
+#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/file.h>
 #include <linux/compat.h>
@@ -54,9 +55,6 @@
 #include "md.h"
 #include "bitmap.h"
 
-#define DEBUG 0
-#define dprintk(x...) ((void)(DEBUG && printk(x)))
-
 #ifndef MODULE
 static void autostart_arrays(int part);
 #endif
@@ -98,13 +96,13 @@ static struct workqueue_struct *md_misc_
 
 static int sysctl_speed_limit_min = 1000;
 static int sysctl_speed_limit_max = 200000;
-static inline int speed_min(mddev_t *mddev)
+static inline int speed_min(struct mddev *mddev)
 {
 	return mddev->sync_speed_min ?
 		mddev->sync_speed_min : sysctl_speed_limit_min;
 }
 
-static inline int speed_max(mddev_t *mddev)
+static inline int speed_max(struct mddev *mddev)
 {
 	return mddev->sync_speed_max ?
 		mddev->sync_speed_max : sysctl_speed_limit_max;
@@ -160,7 +158,7 @@ static int start_readonly;
 
 static void mddev_bio_destructor(struct bio *bio)
 {
-	mddev_t *mddev, **mddevp;
+	struct mddev *mddev, **mddevp;
 
 	mddevp = (void*)bio;
 	mddev = mddevp[-1];
@@ -169,10 +167,10 @@ static void mddev_bio_destructor(struct
 }
 
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
-			    mddev_t *mddev)
+			    struct mddev *mddev)
 {
 	struct bio *b;
-	mddev_t **mddevp;
+	struct mddev **mddevp;
 
 	if (!mddev || !mddev->bio_set)
 		return bio_alloc(gfp_mask, nr_iovecs);
@@ -189,10 +187,10 @@ struct bio *bio_alloc_mddev(gfp_t gfp_ma
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 
 struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
-			    mddev_t *mddev)
+			    struct mddev *mddev)
 {
 	struct bio *b;
-	mddev_t **mddevp;
+	struct mddev **mddevp;
 
 	if (!mddev || !mddev->bio_set)
 		return bio_clone(bio, gfp_mask);
@@ -281,7 +279,7 @@ EXPORT_SYMBOL_GPL(md_trim_bio);
  */
 static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
 static atomic_t md_event_count;
-void md_new_event(mddev_t *mddev)
+void md_new_event(struct mddev *mddev)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
@@ -291,7 +289,7 @@ EXPORT_SYMBOL_GPL(md_new_event);
 /* Alternate version that can be called from interrupts
  * when calling sysfs_notify isn't needed.
  */
-static void md_new_event_inintr(mddev_t *mddev)
+static void md_new_event_inintr(struct mddev *mddev)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
@@ -312,19 +310,19 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
  * Any code which breaks out of this loop while own
  * a reference to the current mddev and must mddev_put it.
  */
-#define for_each_mddev(mddev,tmp)					\
+#define for_each_mddev(_mddev,_tmp)					\
 									\
 	for (({ spin_lock(&all_mddevs_lock); 				\
-		tmp = all_mddevs.next;					\
-		mddev = NULL;});					\
-	     ({ if (tmp != &all_mddevs)					\
-			mddev_get(list_entry(tmp, mddev_t, all_mddevs));\
+		_tmp = all_mddevs.next;					\
+		_mddev = NULL;});					\
+	     ({ if (_tmp != &all_mddevs)				\
+			mddev_get(list_entry(_tmp, struct mddev, all_mddevs));\
 		spin_unlock(&all_mddevs_lock);				\
-		if (mddev) mddev_put(mddev);				\
-		mddev = list_entry(tmp, mddev_t, all_mddevs);		\
-		tmp != &all_mddevs;});					\
+		if (_mddev) mddev_put(_mddev);				\
+		_mddev = list_entry(_tmp, struct mddev, all_mddevs);	\
+		_tmp != &all_mddevs;});					\
 	     ({ spin_lock(&all_mddevs_lock);				\
-		tmp = tmp->next;})					\
+		_tmp = _tmp->next;})					\
 		)
 
 
@@ -335,18 +333,17 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
  * call has finished, the bio has been linked into some internal structure
  * and so is visible to ->quiesce(), so we don't need the refcount any more.
  */
-static int md_make_request(struct request_queue *q, struct bio *bio)
+static void md_make_request(struct request_queue *q, struct bio *bio)
 {
 	const int rw = bio_data_dir(bio);
-	mddev_t *mddev = q->queuedata;
-	int rv;
+	struct mddev *mddev = q->queuedata;
 	int cpu;
 	unsigned int sectors;
 
 	if (mddev == NULL || mddev->pers == NULL
 	    || !mddev->ready) {
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 	smp_rmb(); /* Ensure implications of  'active' are visible */
 	rcu_read_lock();
@@ -371,7 +368,7 @@ static int md_make_request(struct reques
 	 * go away inside make_request
 	 */
 	sectors = bio_sectors(bio);
-	rv = mddev->pers->make_request(mddev, bio);
+	mddev->pers->make_request(mddev, bio);
 
 	cpu = part_stat_lock();
 	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
@@ -380,8 +377,6 @@ static int md_make_request(struct reques
 
 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
 		wake_up(&mddev->sb_wait);
-
-	return rv;
 }
 
 /* mddev_suspend makes sure no new requests are submitted
@@ -390,7 +385,7 @@ static int md_make_request(struct reques
  * Once ->stop is called and completes, the module will be completely
  * unused.
  */
-void mddev_suspend(mddev_t *mddev)
+void mddev_suspend(struct mddev *mddev)
 {
 	BUG_ON(mddev->suspended);
 	mddev->suspended = 1;
@@ -400,7 +395,7 @@ void mddev_suspend(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(mddev_suspend);
 
-void mddev_resume(mddev_t *mddev)
+void mddev_resume(struct mddev *mddev)
 {
 	mddev->suspended = 0;
 	wake_up(&mddev->sb_wait);
@@ -411,7 +406,7 @@ void mddev_resume(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(mddev_resume);
 
-int mddev_congested(mddev_t *mddev, int bits)
+int mddev_congested(struct mddev *mddev, int bits)
 {
 	return mddev->suspended;
 }
@@ -423,8 +418,8 @@ EXPORT_SYMBOL(mddev_congested);
 
 static void md_end_flush(struct bio *bio, int err)
 {
-	mdk_rdev_t *rdev = bio->bi_private;
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = bio->bi_private;
+	struct mddev *mddev = rdev->mddev;
 
 	rdev_dec_pending(rdev, mddev);
 
@@ -439,8 +434,8 @@ static void md_submit_flush_data(struct
 
 static void submit_flushes(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
-	mdk_rdev_t *rdev;
+	struct mddev *mddev = container_of(ws, struct mddev, flush_work);
+	struct md_rdev *rdev;
 
 	INIT_WORK(&mddev->flush_work, md_submit_flush_data);
 	atomic_set(&mddev->flush_pending, 1);
@@ -472,7 +467,7 @@ static void submit_flushes(struct work_s
 
 static void md_submit_flush_data(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+	struct mddev *mddev = container_of(ws, struct mddev, flush_work);
 	struct bio *bio = mddev->flush_bio;
 
 	if (bio->bi_size == 0)
@@ -480,15 +475,14 @@ static void md_submit_flush_data(struct
 		bio_endio(bio, 0);
 	else {
 		bio->bi_rw &= ~REQ_FLUSH;
-		if (mddev->pers->make_request(mddev, bio))
-			generic_make_request(bio);
+		mddev->pers->make_request(mddev, bio);
 	}
 
 	mddev->flush_bio = NULL;
 	wake_up(&mddev->sb_wait);
 }
 
-void md_flush_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(struct mddev *mddev, struct bio *bio)
 {
 	spin_lock_irq(&mddev->write_lock);
 	wait_event_lock_irq(mddev->sb_wait,
@@ -512,7 +506,7 @@ EXPORT_SYMBOL(md_flush_request);
  */
 struct md_plug_cb {
 	struct blk_plug_cb cb;
-	mddev_t *mddev;
+	struct mddev *mddev;
 };
 
 static void plugger_unplug(struct blk_plug_cb *cb)
@@ -526,7 +520,7 @@ static void plugger_unplug(struct blk_pl
 /* Check that an unplug wakeup will come shortly.
  * If not, wakeup the md thread immediately
  */
-int mddev_check_plugged(mddev_t *mddev)
+int mddev_check_plugged(struct mddev *mddev)
 {
 	struct blk_plug *plug = current->plug;
 	struct md_plug_cb *mdcb;
@@ -558,7 +552,7 @@ int mddev_check_plugged(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(mddev_check_plugged);
 
-static inline mddev_t *mddev_get(mddev_t *mddev)
+static inline struct mddev *mddev_get(struct mddev *mddev)
 {
 	atomic_inc(&mddev->active);
 	return mddev;
@@ -566,7 +560,7 @@ static inline mddev_t *mddev_get(mddev_t
 
 static void mddev_delayed_delete(struct work_struct *ws);
 
-static void mddev_put(mddev_t *mddev)
+static void mddev_put(struct mddev *mddev)
 {
 	struct bio_set *bs = NULL;
 
@@ -576,7 +570,7 @@ static void mddev_put(mddev_t *mddev)
 	    mddev->ctime == 0 && !mddev->hold_active) {
 		/* Array is not configured at all, and not held active,
 		 * so destroy it */
-		list_del(&mddev->all_mddevs);
+		list_del_init(&mddev->all_mddevs);
 		bs = mddev->bio_set;
 		mddev->bio_set = NULL;
 		if (mddev->gendisk) {
@@ -595,7 +589,7 @@ static void mddev_put(mddev_t *mddev)
 		bioset_free(bs);
 }
 
-void mddev_init(mddev_t *mddev)
+void mddev_init(struct mddev *mddev)
 {
 	mutex_init(&mddev->open_mutex);
 	mutex_init(&mddev->reconfig_mutex);
@@ -618,9 +612,9 @@ void mddev_init(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(mddev_init);
 
-static mddev_t * mddev_find(dev_t unit)
+static struct mddev * mddev_find(dev_t unit)
 {
-	mddev_t *mddev, *new = NULL;
+	struct mddev *mddev, *new = NULL;
 
 	if (unit && MAJOR(unit) != MD_MAJOR)
 		unit &= ~((1<<MdpMinorShift)-1);
@@ -692,24 +686,24 @@ static mddev_t * mddev_find(dev_t unit)
 	goto retry;
 }
 
-static inline int mddev_lock(mddev_t * mddev)
+static inline int mddev_lock(struct mddev * mddev)
 {
 	return mutex_lock_interruptible(&mddev->reconfig_mutex);
 }
 
-static inline int mddev_is_locked(mddev_t *mddev)
+static inline int mddev_is_locked(struct mddev *mddev)
 {
 	return mutex_is_locked(&mddev->reconfig_mutex);
 }
 
-static inline int mddev_trylock(mddev_t * mddev)
+static inline int mddev_trylock(struct mddev * mddev)
 {
 	return mutex_trylock(&mddev->reconfig_mutex);
 }
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(mddev_t * mddev)
+static void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -744,17 +738,17 @@ static void mddev_unlock(mddev_t * mddev
 	} else
 		mutex_unlock(&mddev->reconfig_mutex);
 
-	/* was we've dropped the mutex we need a spinlock to
-	 * make sur the thread doesn't disappear
+	/* As we've dropped the mutex we need a spinlock to
+	 * make sure the thread doesn't disappear
 	 */
 	spin_lock(&pers_lock);
 	md_wakeup_thread(mddev->thread);
 	spin_unlock(&pers_lock);
 }
 
-static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->desc_nr == nr)
@@ -763,9 +757,9 @@ static mdk_rdev_t * find_rdev_nr(mddev_t
 	return NULL;
 }
 
-static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
+static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->bdev->bd_dev == dev)
@@ -774,9 +768,9 @@ static mdk_rdev_t * find_rdev(mddev_t *
 	return NULL;
 }
 
-static struct mdk_personality *find_pers(int level, char *clevel)
+static struct md_personality *find_pers(int level, char *clevel)
 {
-	struct mdk_personality *pers;
+	struct md_personality *pers;
 	list_for_each_entry(pers, &pers_list, list) {
 		if (level != LEVEL_NONE && pers->level == level)
 			return pers;
@@ -787,13 +781,13 @@ static struct mdk_personality *find_pers
 }
 
 /* return the offset of the super block in 512byte sectors */
-static inline sector_t calc_dev_sboffset(mdk_rdev_t *rdev)
+static inline sector_t calc_dev_sboffset(struct md_rdev *rdev)
 {
 	sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
 	return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static int alloc_disk_sb(mdk_rdev_t * rdev)
+static int alloc_disk_sb(struct md_rdev * rdev)
 {
 	if (rdev->sb_page)
 		MD_BUG();
@@ -807,7 +801,7 @@ static int alloc_disk_sb(mdk_rdev_t * rd
 	return 0;
 }
 
-static void free_disk_sb(mdk_rdev_t * rdev)
+static void free_disk_sb(struct md_rdev * rdev)
 {
 	if (rdev->sb_page) {
 		put_page(rdev->sb_page);
@@ -825,8 +819,8 @@ static void free_disk_sb(mdk_rdev_t * rd
 
 static void super_written(struct bio *bio, int error)
 {
-	mdk_rdev_t *rdev = bio->bi_private;
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = bio->bi_private;
+	struct mddev *mddev = rdev->mddev;
 
 	if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
 		printk("md: super_written gets error=%d, uptodate=%d\n",
@@ -840,7 +834,7 @@ static void super_written(struct bio *bi
 	bio_put(bio);
 }
 
-void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 		   sector_t sector, int size, struct page *page)
 {
 	/* write first size bytes of page to sector of rdev
@@ -861,7 +855,7 @@ void md_super_write(mddev_t *mddev, mdk_
 	submit_bio(WRITE_FLUSH_FUA, bio);
 }
 
-void md_super_wait(mddev_t *mddev)
+void md_super_wait(struct mddev *mddev)
 {
 	/* wait for all superblock writes that were scheduled to complete */
 	DEFINE_WAIT(wq);
@@ -879,7 +873,7 @@ static void bi_complete(struct bio *bio,
 	complete((struct completion*)bio->bi_private);
 }
 
-int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
+int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
 		 struct page *page, int rw, bool metadata_op)
 {
 	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
@@ -907,7 +901,7 @@ int sync_page_io(mdk_rdev_t *rdev, secto
 }
 EXPORT_SYMBOL_GPL(sync_page_io);
 
-static int read_disk_sb(mdk_rdev_t * rdev, int size)
+static int read_disk_sb(struct md_rdev * rdev, int size)
 {
 	char b[BDEVNAME_SIZE];
 	if (!rdev->sb_page) {
@@ -1014,7 +1008,7 @@ static unsigned int calc_sb_csum(mdp_sup
  * We rely on user-space to write the initial superblock, and support
  * reading and updating of superblocks.
  * Interface methods are:
- *   int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version)
+ *   int load_super(struct md_rdev *dev, struct md_rdev *refdev, int minor_version)
  *      loads and validates a superblock on dev.
  *      if refdev != NULL, compare superblocks on both devices
  *    Return:
@@ -1024,13 +1018,13 @@ static unsigned int calc_sb_csum(mdp_sup
  *     -EINVAL superblock incompatible or invalid
  *     -othererror e.g. -EIO
  *
- *   int validate_super(mddev_t *mddev, mdk_rdev_t *dev)
+ *   int validate_super(struct mddev *mddev, struct md_rdev *dev)
  *      Verify that dev is acceptable into mddev.
  *       The first time, mddev->raid_disks will be 0, and data from
  *       dev should be merged in.  Subsequent calls check that dev
  *       is new enough.  Return 0 or -EINVAL
  *
- *   void sync_super(mddev_t *mddev, mdk_rdev_t *dev)
+ *   void sync_super(struct mddev *mddev, struct md_rdev *dev)
  *     Update the superblock for rdev with data in mddev
  *     This does not write to disc.
  *
@@ -1039,11 +1033,11 @@ static unsigned int calc_sb_csum(mdp_sup
 struct super_type  {
 	char		    *name;
 	struct module	    *owner;
-	int		    (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+	int		    (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev,
 					  int minor_version);
-	int		    (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
-	void		    (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
-	unsigned long long  (*rdev_size_change)(mdk_rdev_t *rdev,
+	int		    (*validate_super)(struct mddev *mddev, struct md_rdev *rdev);
+	void		    (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
+	unsigned long long  (*rdev_size_change)(struct md_rdev *rdev,
 						sector_t num_sectors);
 };
 
@@ -1055,7 +1049,7 @@ struct super_type  {
  * has a bitmap. Otherwise, it returns 0.
  *
  */
-int md_check_no_bitmap(mddev_t *mddev)
+int md_check_no_bitmap(struct mddev *mddev)
 {
 	if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset)
 		return 0;
@@ -1068,7 +1062,7 @@ EXPORT_SYMBOL(md_check_no_bitmap);
 /*
  * load_super for 0.90.0 
  */
-static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
 {
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	mdp_super_t *sb;
@@ -1163,7 +1157,7 @@ static int super_90_load(mdk_rdev_t *rde
 /*
  * validate_super for 0.90.0
  */
-static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	mdp_disk_t *desc;
 	mdp_super_t *sb = page_address(rdev->sb_page);
@@ -1275,10 +1269,10 @@ static int super_90_validate(mddev_t *md
 /*
  * sync_super for 0.90.0
  */
-static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
 	mdp_super_t *sb;
-	mdk_rdev_t *rdev2;
+	struct md_rdev *rdev2;
 	int next_spare = mddev->raid_disks;
 
 
@@ -1419,7 +1413,7 @@ static void super_90_sync(mddev_t *mddev
  * rdev_size_change for 0.90.0
  */
 static unsigned long long
-super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 {
 	if (num_sectors && num_sectors < rdev->mddev->dev_sectors)
 		return 0; /* component must fit device */
@@ -1469,7 +1463,7 @@ static __le32 calc_sb_1_csum(struct mdp_
 
 static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
 			    int acknowledged);
-static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
 {
 	struct mdp_superblock_1 *sb;
 	int ret;
@@ -1625,7 +1619,7 @@ static int super_1_load(mdk_rdev_t *rdev
 	return ret;
 }
 
-static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
 	__u64 ev1 = le64_to_cpu(sb->events);
@@ -1726,10 +1720,10 @@ static int super_1_validate(mddev_t *mdd
 	return 0;
 }
 
-static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb;
-	mdk_rdev_t *rdev2;
+	struct md_rdev *rdev2;
 	int max_dev, i;
 	/* make rdev->sb match mddev and rdev data. */
 
@@ -1851,7 +1845,7 @@ retry:
 }
 
 static unsigned long long
-super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 {
 	struct mdp_superblock_1 *sb;
 	sector_t max_sectors;
@@ -1905,7 +1899,7 @@ static struct super_type super_types[] =
 	},
 };
 
-static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
+static void sync_super(struct mddev *mddev, struct md_rdev *rdev)
 {
 	if (mddev->sync_super) {
 		mddev->sync_super(mddev, rdev);
@@ -1917,9 +1911,9 @@ static void sync_super(mddev_t *mddev, m
 	super_types[mddev->major_version].sync_super(mddev, rdev);
 }
 
-static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
+static int match_mddev_units(struct mddev *mddev1, struct mddev *mddev2)
 {
-	mdk_rdev_t *rdev, *rdev2;
+	struct md_rdev *rdev, *rdev2;
 
 	rcu_read_lock();
 	rdev_for_each_rcu(rdev, mddev1)
@@ -1942,9 +1936,9 @@ static LIST_HEAD(pending_raid_disks);
  * from the array. It only succeeds if all working and active component devices
  * are integrity capable with matching profiles.
  */
-int md_integrity_register(mddev_t *mddev)
+int md_integrity_register(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev, *reference = NULL;
+	struct md_rdev *rdev, *reference = NULL;
 
 	if (list_empty(&mddev->disks))
 		return 0; /* nothing to do */
@@ -1989,7 +1983,7 @@ int md_integrity_register(mddev_t *mddev
 EXPORT_SYMBOL(md_integrity_register);
 
 /* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
 	struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
@@ -2006,7 +2000,7 @@ void md_integrity_add_rdev(mdk_rdev_t *r
 }
 EXPORT_SYMBOL(md_integrity_add_rdev);
 
-static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev)
 {
 	char b[BDEVNAME_SIZE];
 	struct kobject *ko;
@@ -2086,12 +2080,12 @@ static int bind_rdev_to_array(mdk_rdev_t
 
 static void md_delayed_delete(struct work_struct *ws)
 {
-	mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
+	struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work);
 	kobject_del(&rdev->kobj);
 	kobject_put(&rdev->kobj);
 }
 
-static void unbind_rdev_from_array(mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(struct md_rdev * rdev)
 {
 	char b[BDEVNAME_SIZE];
 	if (!rdev->mddev) {
@@ -2123,14 +2117,14 @@ static void unbind_rdev_from_array(mdk_r
  * otherwise reused by a RAID array (or any other kernel
  * subsystem), by bd_claiming the device.
  */
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
+static int lock_rdev(struct md_rdev *rdev, dev_t dev, int shared)
 {
 	int err = 0;
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 
 	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
-				 shared ? (mdk_rdev_t *)lock_rdev : rdev);
+				 shared ? (struct md_rdev *)lock_rdev : rdev);
 	if (IS_ERR(bdev)) {
 		printk(KERN_ERR "md: could not open %s.\n",
 			__bdevname(dev, b));
@@ -2140,7 +2134,7 @@ static int lock_rdev(mdk_rdev_t *rdev, d
 	return err;
 }
 
-static void unlock_rdev(mdk_rdev_t *rdev)
+static void unlock_rdev(struct md_rdev *rdev)
 {
 	struct block_device *bdev = rdev->bdev;
 	rdev->bdev = NULL;
@@ -2151,7 +2145,7 @@ static void unlock_rdev(mdk_rdev_t *rdev
 
 void md_autodetect_dev(dev_t dev);
 
-static void export_rdev(mdk_rdev_t * rdev)
+static void export_rdev(struct md_rdev * rdev)
 {
 	char b[BDEVNAME_SIZE];
 	printk(KERN_INFO "md: export_rdev(%s)\n",
@@ -2167,15 +2161,15 @@ static void export_rdev(mdk_rdev_t * rde
 	kobject_put(&rdev->kobj);
 }
 
-static void kick_rdev_from_array(mdk_rdev_t * rdev)
+static void kick_rdev_from_array(struct md_rdev * rdev)
 {
 	unbind_rdev_from_array(rdev);
 	export_rdev(rdev);
 }
 
-static void export_array(mddev_t *mddev)
+static void export_array(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev, *tmp;
+	struct md_rdev *rdev, *tmp;
 
 	rdev_for_each(rdev, tmp, mddev) {
 		if (!rdev->mddev) {
@@ -2271,7 +2265,7 @@ static void print_sb_1(struct mdp_superb
 		);
 }
 
-static void print_rdev(mdk_rdev_t *rdev, int major_version)
+static void print_rdev(struct md_rdev *rdev, int major_version)
 {
 	char b[BDEVNAME_SIZE];
 	printk(KERN_INFO "md: rdev %s, Sect:%08llu F:%d S:%d DN:%u\n",
@@ -2295,8 +2289,8 @@ static void print_rdev(mdk_rdev_t *rdev,
 static void md_print_devices(void)
 {
 	struct list_head *tmp;
-	mdk_rdev_t *rdev;
-	mddev_t *mddev;
+	struct md_rdev *rdev;
+	struct mddev *mddev;
 	char b[BDEVNAME_SIZE];
 
 	printk("\n");
@@ -2321,7 +2315,7 @@ static void md_print_devices(void)
 }
 
 
-static void sync_sbs(mddev_t * mddev, int nospares)
+static void sync_sbs(struct mddev * mddev, int nospares)
 {
 	/* Update each superblock (in-memory image), but
 	 * if we are allowed to, skip spares which already
@@ -2329,7 +2323,7 @@ static void sync_sbs(mddev_t * mddev, in
 	 * (which would mean they aren't being marked as dirty
 	 * with the rest of the array)
 	 */
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		if (rdev->sb_events == mddev->events ||
 		    (nospares &&
@@ -2344,9 +2338,9 @@ static void sync_sbs(mddev_t * mddev, in
 	}
 }
 
-static void md_update_sb(mddev_t * mddev, int force_change)
+static void md_update_sb(struct mddev * mddev, int force_change)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int sync_req;
 	int nospares = 0;
 	int any_badblocks_changed = 0;
@@ -2442,27 +2436,24 @@ repeat:
 	sync_sbs(mddev, nospares);
 	spin_unlock_irq(&mddev->write_lock);
 
-	dprintk(KERN_INFO 
-		"md: updating %s RAID superblock on device (in sync %d)\n",
-		mdname(mddev),mddev->in_sync);
+	pr_debug("md: updating %s RAID superblock on device (in sync %d)\n",
+		 mdname(mddev), mddev->in_sync);
 
 	bitmap_update_sb(mddev->bitmap);
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		char b[BDEVNAME_SIZE];
-		dprintk(KERN_INFO "md: ");
+
 		if (rdev->sb_loaded != 1)
 			continue; /* no noise on spare devices */
-		if (test_bit(Faulty, &rdev->flags))
-			dprintk("(skipping faulty ");
 
-		dprintk("%s ", bdevname(rdev->bdev,b));
-		if (!test_bit(Faulty, &rdev->flags)) {
+		if (!test_bit(Faulty, &rdev->flags) &&
+		    rdev->saved_raid_disk == -1) {
 			md_super_write(mddev,rdev,
 				       rdev->sb_start, rdev->sb_size,
 				       rdev->sb_page);
-			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
-				bdevname(rdev->bdev,b),
-				(unsigned long long)rdev->sb_start);
+			pr_debug("md: (write) %s's sb offset: %llu\n",
+				 bdevname(rdev->bdev, b),
+				 (unsigned long long)rdev->sb_start);
 			rdev->sb_events = mddev->events;
 			if (rdev->badblocks.size) {
 				md_super_write(mddev, rdev,
@@ -2472,8 +2463,12 @@ repeat:
 				rdev->badblocks.size = 0;
 			}
 
-		} else
-			dprintk(")\n");
+		} else if (test_bit(Faulty, &rdev->flags))
+			pr_debug("md: %s (skipping faulty)\n",
+				 bdevname(rdev->bdev, b));
+		else
+			pr_debug("(skipping incremental s/r ");
+
 		if (mddev->level == LEVEL_MULTIPATH)
 			/* only need to write one superblock... */
 			break;
@@ -2527,12 +2522,12 @@ static int cmd_match(const char *cmd, co
 
 struct rdev_sysfs_entry {
 	struct attribute attr;
-	ssize_t (*show)(mdk_rdev_t *, char *);
-	ssize_t (*store)(mdk_rdev_t *, const char *, size_t);
+	ssize_t (*show)(struct md_rdev *, char *);
+	ssize_t (*store)(struct md_rdev *, const char *, size_t);
 };
 
 static ssize_t
-state_show(mdk_rdev_t *rdev, char *page)
+state_show(struct md_rdev *rdev, char *page)
 {
 	char *sep = "";
 	size_t len = 0;
@@ -2551,7 +2546,8 @@ state_show(mdk_rdev_t *rdev, char *page)
 		sep = ",";
 	}
 	if (test_bit(Blocked, &rdev->flags) ||
-	    rdev->badblocks.unacked_exist) {
+	    (rdev->badblocks.unacked_exist
+	     && !test_bit(Faulty, &rdev->flags))) {
 		len += sprintf(page+len, "%sblocked", sep);
 		sep = ",";
 	}
@@ -2568,7 +2564,7 @@ state_show(mdk_rdev_t *rdev, char *page)
 }
 
 static ssize_t
-state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+state_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	/* can write
 	 *  faulty  - simulates an error
@@ -2592,7 +2588,7 @@ state_store(mdk_rdev_t *rdev, const char
 		if (rdev->raid_disk >= 0)
 			err = -EBUSY;
 		else {
-			mddev_t *mddev = rdev->mddev;
+			struct mddev *mddev = rdev->mddev;
 			kick_rdev_from_array(rdev);
 			if (mddev->pers)
 				md_update_sb(mddev, 1);
@@ -2641,13 +2637,13 @@ static struct rdev_sysfs_entry rdev_stat
 __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store);
 
 static ssize_t
-errors_show(mdk_rdev_t *rdev, char *page)
+errors_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
 }
 
 static ssize_t
-errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+errors_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -2661,7 +2657,7 @@ static struct rdev_sysfs_entry rdev_erro
 __ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
 
 static ssize_t
-slot_show(mdk_rdev_t *rdev, char *page)
+slot_show(struct md_rdev *rdev, char *page)
 {
 	if (rdev->raid_disk < 0)
 		return sprintf(page, "none\n");
@@ -2670,7 +2666,7 @@ slot_show(mdk_rdev_t *rdev, char *page)
 }
 
 static ssize_t
-slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+slot_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	int err;
@@ -2701,7 +2697,7 @@ slot_store(mdk_rdev_t *rdev, const char
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
 	} else if (rdev->mddev->pers) {
-		mdk_rdev_t *rdev2;
+		struct md_rdev *rdev2;
 		/* Activating a spare .. or possibly reactivating
 		 * if we ever get bitmaps working here.
 		 */
@@ -2728,6 +2724,7 @@ slot_store(mdk_rdev_t *rdev, const char
 			rdev->saved_raid_disk = slot;
 		else
 			rdev->saved_raid_disk = -1;
+		clear_bit(In_sync, &rdev->flags);
 		err = rdev->mddev->pers->
 			hot_add_disk(rdev->mddev, rdev);
 		if (err) {
@@ -2757,13 +2754,13 @@ static struct rdev_sysfs_entry rdev_slot
 __ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store);
 
 static ssize_t
-offset_show(mdk_rdev_t *rdev, char *page)
+offset_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
 }
 
 static ssize_t
-offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+offset_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long offset = simple_strtoull(buf, &e, 10);
@@ -2783,7 +2780,7 @@ static struct rdev_sysfs_entry rdev_offs
 __ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
 
 static ssize_t
-rdev_size_show(mdk_rdev_t *rdev, char *page)
+rdev_size_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)rdev->sectors / 2);
 }
@@ -2818,9 +2815,9 @@ static int strict_blocks_to_sectors(cons
 }
 
 static ssize_t
-rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
-	mddev_t *my_mddev = rdev->mddev;
+	struct mddev *my_mddev = rdev->mddev;
 	sector_t oldsectors = rdev->sectors;
 	sector_t sectors;
 
@@ -2846,13 +2843,13 @@ rdev_size_store(mdk_rdev_t *rdev, const
 		 * a deadlock.  We have already changed rdev->sectors, and if
 		 * we have to change it back, we will have the lock again.
 		 */
-		mddev_t *mddev;
+		struct mddev *mddev;
 		int overlap = 0;
 		struct list_head *tmp;
 
 		mddev_unlock(my_mddev);
 		for_each_mddev(mddev, tmp) {
-			mdk_rdev_t *rdev2;
+			struct md_rdev *rdev2;
 
 			mddev_lock(mddev);
 			list_for_each_entry(rdev2, &mddev->disks, same_set)
@@ -2889,7 +2886,7 @@ static struct rdev_sysfs_entry rdev_size
 __ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
 
 
-static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
+static ssize_t recovery_start_show(struct md_rdev *rdev, char *page)
 {
 	unsigned long long recovery_start = rdev->recovery_offset;
 
@@ -2900,7 +2897,7 @@ static ssize_t recovery_start_show(mdk_r
 	return sprintf(page, "%llu\n", recovery_start);
 }
 
-static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	unsigned long long recovery_start;
 
@@ -2930,11 +2927,11 @@ badblocks_show(struct badblocks *bb, cha
 static ssize_t
 badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack);
 
-static ssize_t bb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t bb_show(struct md_rdev *rdev, char *page)
 {
 	return badblocks_show(&rdev->badblocks, page, 0);
 }
-static ssize_t bb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len)
 {
 	int rv = badblocks_store(&rdev->badblocks, page, len, 0);
 	/* Maybe that ack was all we needed */
@@ -2946,11 +2943,11 @@ static struct rdev_sysfs_entry rdev_bad_
 __ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store);
 
 
-static ssize_t ubb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t ubb_show(struct md_rdev *rdev, char *page)
 {
 	return badblocks_show(&rdev->badblocks, page, 1);
 }
-static ssize_t ubb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t ubb_store(struct md_rdev *rdev, const char *page, size_t len)
 {
 	return badblocks_store(&rdev->badblocks, page, len, 1);
 }
@@ -2972,8 +2969,8 @@ static ssize_t
 rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
 	struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
-	mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
+	struct mddev *mddev = rdev->mddev;
 	ssize_t rv;
 
 	if (!entry->show)
@@ -2995,9 +2992,9 @@ rdev_attr_store(struct kobject *kobj, st
 	      const char *page, size_t length)
 {
 	struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
-	mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+	struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
 	ssize_t rv;
-	mddev_t *mddev = rdev->mddev;
+	struct mddev *mddev = rdev->mddev;
 
 	if (!entry->store)
 		return -EIO;
@@ -3016,7 +3013,7 @@ rdev_attr_store(struct kobject *kobj, st
 
 static void rdev_free(struct kobject *ko)
 {
-	mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
+	struct md_rdev *rdev = container_of(ko, struct md_rdev, kobj);
 	kfree(rdev);
 }
 static const struct sysfs_ops rdev_sysfs_ops = {
@@ -3029,7 +3026,7 @@ static struct kobj_type rdev_ktype = {
 	.default_attrs	= rdev_default_attrs,
 };
 
-int md_rdev_init(mdk_rdev_t *rdev)
+int md_rdev_init(struct md_rdev *rdev)
 {
 	rdev->desc_nr = -1;
 	rdev->saved_raid_disk = -1;
@@ -3072,11 +3069,11 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
  *
  * a faulty rdev _never_ has rdev->sb set.
  */
-static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
+static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
 	char b[BDEVNAME_SIZE];
 	int err;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t size;
 
 	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
@@ -3145,10 +3142,10 @@ abort_free:
  */
 
 
-static void analyze_sbs(mddev_t * mddev)
+static void analyze_sbs(struct mddev * mddev)
 {
 	int i;
-	mdk_rdev_t *rdev, *freshest, *tmp;
+	struct md_rdev *rdev, *freshest, *tmp;
 	char b[BDEVNAME_SIZE];
 
 	freshest = NULL;
@@ -3248,13 +3245,13 @@ int strict_strtoul_scaled(const char *cp
 static void md_safemode_timeout(unsigned long data);
 
 static ssize_t
-safe_delay_show(mddev_t *mddev, char *page)
+safe_delay_show(struct mddev *mddev, char *page)
 {
 	int msec = (mddev->safemode_delay*1000)/HZ;
 	return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
 }
 static ssize_t
-safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
+safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
 {
 	unsigned long msec;
 
@@ -3276,9 +3273,9 @@ static struct md_sysfs_entry md_safe_del
 __ATTR(safe_mode_delay, S_IRUGO|S_IWUSR,safe_delay_show, safe_delay_store);
 
 static ssize_t
-level_show(mddev_t *mddev, char *page)
+level_show(struct mddev *mddev, char *page)
 {
-	struct mdk_personality *p = mddev->pers;
+	struct md_personality *p = mddev->pers;
 	if (p)
 		return sprintf(page, "%s\n", p->name);
 	else if (mddev->clevel[0])
@@ -3290,14 +3287,14 @@ level_show(mddev_t *mddev, char *page)
 }
 
 static ssize_t
-level_store(mddev_t *mddev, const char *buf, size_t len)
+level_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char clevel[16];
 	ssize_t rv = len;
-	struct mdk_personality *pers;
+	struct md_personality *pers;
 	long level;
 	void *priv;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->pers == NULL) {
 		if (len == 0)
@@ -3471,7 +3468,7 @@ __ATTR(level, S_IRUGO|S_IWUSR, level_sho
 
 
 static ssize_t
-layout_show(mddev_t *mddev, char *page)
+layout_show(struct mddev *mddev, char *page)
 {
 	/* just a number, not meaningful for all levels */
 	if (mddev->reshape_position != MaxSector &&
@@ -3482,7 +3479,7 @@ layout_show(mddev_t *mddev, char *page)
 }
 
 static ssize_t
-layout_store(mddev_t *mddev, const char *buf, size_t len)
+layout_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3512,7 +3509,7 @@ __ATTR(layout, S_IRUGO|S_IWUSR, layout_s
 
 
 static ssize_t
-raid_disks_show(mddev_t *mddev, char *page)
+raid_disks_show(struct mddev *mddev, char *page)
 {
 	if (mddev->raid_disks == 0)
 		return 0;
@@ -3523,10 +3520,10 @@ raid_disks_show(mddev_t *mddev, char *pa
 	return sprintf(page, "%d\n", mddev->raid_disks);
 }
 
-static int update_raid_disks(mddev_t *mddev, int raid_disks);
+static int update_raid_disks(struct mddev *mddev, int raid_disks);
 
 static ssize_t
-raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	int rv = 0;
@@ -3549,7 +3546,7 @@ static struct md_sysfs_entry md_raid_dis
 __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
 
 static ssize_t
-chunk_size_show(mddev_t *mddev, char *page)
+chunk_size_show(struct mddev *mddev, char *page)
 {
 	if (mddev->reshape_position != MaxSector &&
 	    mddev->chunk_sectors != mddev->new_chunk_sectors)
@@ -3560,7 +3557,7 @@ chunk_size_show(mddev_t *mddev, char *pa
 }
 
 static ssize_t
-chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3589,7 +3586,7 @@ static struct md_sysfs_entry md_chunk_si
 __ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store);
 
 static ssize_t
-resync_start_show(mddev_t *mddev, char *page)
+resync_start_show(struct mddev *mddev, char *page)
 {
 	if (mddev->recovery_cp == MaxSector)
 		return sprintf(page, "none\n");
@@ -3597,7 +3594,7 @@ resync_start_show(mddev_t *mddev, char *
 }
 
 static ssize_t
-resync_start_store(mddev_t *mddev, const char *buf, size_t len)
+resync_start_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long n = simple_strtoull(buf, &e, 10);
@@ -3667,7 +3664,7 @@ static int match_word(const char *word,
 }
 
 static ssize_t
-array_state_show(mddev_t *mddev, char *page)
+array_state_show(struct mddev *mddev, char *page)
 {
 	enum array_state st = inactive;
 
@@ -3700,13 +3697,13 @@ array_state_show(mddev_t *mddev, char *p
 	return sprintf(page, "%s\n", array_states[st]);
 }
 
-static int do_md_stop(mddev_t * mddev, int ro, int is_open);
-static int md_set_readonly(mddev_t * mddev, int is_open);
-static int do_md_run(mddev_t * mddev);
-static int restart_array(mddev_t *mddev);
+static int do_md_stop(struct mddev * mddev, int ro, int is_open);
+static int md_set_readonly(struct mddev * mddev, int is_open);
+static int do_md_run(struct mddev * mddev);
+static int restart_array(struct mddev *mddev);
 
 static ssize_t
-array_state_store(mddev_t *mddev, const char *buf, size_t len)
+array_state_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int err = -EINVAL;
 	enum array_state st = match_word(buf, array_states);
@@ -3792,6 +3789,8 @@ array_state_store(mddev_t *mddev, const
 	if (err)
 		return err;
 	else {
+		if (mddev->hold_active == UNTIL_IOCTL)
+			mddev->hold_active = 0;
 		sysfs_notify_dirent_safe(mddev->sysfs_state);
 		return len;
 	}
@@ -3800,13 +3799,13 @@ static struct md_sysfs_entry md_array_st
 __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
 
 static ssize_t
-max_corrected_read_errors_show(mddev_t *mddev, char *page) {
+max_corrected_read_errors_show(struct mddev *mddev, char *page) {
 	return sprintf(page, "%d\n",
 		       atomic_read(&mddev->max_corr_read_errors));
 }
 
 static ssize_t
-max_corrected_read_errors_store(mddev_t *mddev, const char *buf, size_t len)
+max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3823,13 +3822,13 @@ __ATTR(max_read_errors, S_IRUGO|S_IWUSR,
 	max_corrected_read_errors_store);
 
 static ssize_t
-null_show(mddev_t *mddev, char *page)
+null_show(struct mddev *mddev, char *page)
 {
 	return -EINVAL;
 }
 
 static ssize_t
-new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+new_dev_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* buf must be %d:%d\n? giving major and minor numbers */
 	/* The new device is added to the array.
@@ -3842,7 +3841,7 @@ new_dev_store(mddev_t *mddev, const char
 	int major = simple_strtoul(buf, &e, 10);
 	int minor;
 	dev_t dev;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int err;
 
 	if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
@@ -3860,8 +3859,9 @@ new_dev_store(mddev_t *mddev, const char
 		rdev = md_import_device(dev, mddev->major_version,
 					mddev->minor_version);
 		if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
-			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
-						       mdk_rdev_t, same_set);
+			struct md_rdev *rdev0
+				= list_entry(mddev->disks.next,
+					     struct md_rdev, same_set);
 			err = super_types[mddev->major_version]
 				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0)
@@ -3885,7 +3885,7 @@ static struct md_sysfs_entry md_new_devi
 __ATTR(new_dev, S_IWUSR, null_show, new_dev_store);
 
 static ssize_t
-bitmap_store(mddev_t *mddev, const char *buf, size_t len)
+bitmap_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *end;
 	unsigned long chunk, end_chunk;
@@ -3914,16 +3914,16 @@ static struct md_sysfs_entry md_bitmap =
 __ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store);
 
 static ssize_t
-size_show(mddev_t *mddev, char *page)
+size_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		(unsigned long long)mddev->dev_sectors / 2);
 }
 
-static int update_size(mddev_t *mddev, sector_t num_sectors);
+static int update_size(struct mddev *mddev, sector_t num_sectors);
 
 static ssize_t
-size_store(mddev_t *mddev, const char *buf, size_t len)
+size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* If array is inactive, we can reduce the component size, but
 	 * not increase it (except from 0).
@@ -3958,7 +3958,7 @@ __ATTR(component_size, S_IRUGO|S_IWUSR,
  * or N.M for internally known formats
  */
 static ssize_t
-metadata_show(mddev_t *mddev, char *page)
+metadata_show(struct mddev *mddev, char *page)
 {
 	if (mddev->persistent)
 		return sprintf(page, "%d.%d\n",
@@ -3970,7 +3970,7 @@ metadata_show(mddev_t *mddev, char *page
 }
 
 static ssize_t
-metadata_store(mddev_t *mddev, const char *buf, size_t len)
+metadata_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int major, minor;
 	char *e;
@@ -4024,7 +4024,7 @@ static struct md_sysfs_entry md_metadata
 __ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
 
 static ssize_t
-action_show(mddev_t *mddev, char *page)
+action_show(struct mddev *mddev, char *page)
 {
 	char *type = "idle";
 	if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
@@ -4046,10 +4046,10 @@ action_show(mddev_t *mddev, char *page)
 	return sprintf(page, "%s\n", type);
 }
 
-static void reap_sync_thread(mddev_t *mddev);
+static void reap_sync_thread(struct mddev *mddev);
 
 static ssize_t
-action_store(mddev_t *mddev, const char *page, size_t len)
+action_store(struct mddev *mddev, const char *page, size_t len)
 {
 	if (!mddev->pers || !mddev->pers->sync_request)
 		return -EINVAL;
@@ -4095,7 +4095,7 @@ action_store(mddev_t *mddev, const char
 }
 
 static ssize_t
-mismatch_cnt_show(mddev_t *mddev, char *page)
+mismatch_cnt_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		       (unsigned long long) mddev->resync_mismatches);
@@ -4108,14 +4108,14 @@ __ATTR(sync_action, S_IRUGO|S_IWUSR, act
 static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt);
 
 static ssize_t
-sync_min_show(mddev_t *mddev, char *page)
+sync_min_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d (%s)\n", speed_min(mddev),
 		       mddev->sync_speed_min ? "local": "system");
 }
 
 static ssize_t
-sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+sync_min_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int min;
 	char *e;
@@ -4134,14 +4134,14 @@ static struct md_sysfs_entry md_sync_min
 __ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
 
 static ssize_t
-sync_max_show(mddev_t *mddev, char *page)
+sync_max_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d (%s)\n", speed_max(mddev),
 		       mddev->sync_speed_max ? "local": "system");
 }
 
 static ssize_t
-sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+sync_max_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int max;
 	char *e;
@@ -4160,20 +4160,20 @@ static struct md_sysfs_entry md_sync_max
 __ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
 
 static ssize_t
-degraded_show(mddev_t *mddev, char *page)
+degraded_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d\n", mddev->degraded);
 }
 static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
 
 static ssize_t
-sync_force_parallel_show(mddev_t *mddev, char *page)
+sync_force_parallel_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d\n", mddev->parallel_resync);
 }
 
 static ssize_t
-sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len)
+sync_force_parallel_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	long n;
 
@@ -4197,7 +4197,7 @@ __ATTR(sync_force_parallel, S_IRUGO|S_IW
        sync_force_parallel_show, sync_force_parallel_store);
 
 static ssize_t
-sync_speed_show(mddev_t *mddev, char *page)
+sync_speed_show(struct mddev *mddev, char *page)
 {
 	unsigned long resync, dt, db;
 	if (mddev->curr_resync == 0)
@@ -4212,7 +4212,7 @@ sync_speed_show(mddev_t *mddev, char *pa
 static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
 
 static ssize_t
-sync_completed_show(mddev_t *mddev, char *page)
+sync_completed_show(struct mddev *mddev, char *page)
 {
 	unsigned long long max_sectors, resync;
 
@@ -4231,13 +4231,13 @@ sync_completed_show(mddev_t *mddev, char
 static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
 
 static ssize_t
-min_sync_show(mddev_t *mddev, char *page)
+min_sync_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		       (unsigned long long)mddev->resync_min);
 }
 static ssize_t
-min_sync_store(mddev_t *mddev, const char *buf, size_t len)
+min_sync_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	unsigned long long min;
 	if (strict_strtoull(buf, 10, &min))
@@ -4262,7 +4262,7 @@ static struct md_sysfs_entry md_min_sync
 __ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
 
 static ssize_t
-max_sync_show(mddev_t *mddev, char *page)
+max_sync_show(struct mddev *mddev, char *page)
 {
 	if (mddev->resync_max == MaxSector)
 		return sprintf(page, "max\n");
@@ -4271,7 +4271,7 @@ max_sync_show(mddev_t *mddev, char *page
 			       (unsigned long long)mddev->resync_max);
 }
 static ssize_t
-max_sync_store(mddev_t *mddev, const char *buf, size_t len)
+max_sync_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (strncmp(buf, "max", 3) == 0)
 		mddev->resync_max = MaxSector;
@@ -4302,13 +4302,13 @@ static struct md_sysfs_entry md_max_sync
 __ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
 
 static ssize_t
-suspend_lo_show(mddev_t *mddev, char *page)
+suspend_lo_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
 }
 
 static ssize_t
-suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_lo_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4336,13 +4336,13 @@ __ATTR(suspend_lo, S_IRUGO|S_IWUSR, susp
 
 
 static ssize_t
-suspend_hi_show(mddev_t *mddev, char *page)
+suspend_hi_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi);
 }
 
 static ssize_t
-suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_hi_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4369,7 +4369,7 @@ static struct md_sysfs_entry md_suspend_
 __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
 
 static ssize_t
-reshape_position_show(mddev_t *mddev, char *page)
+reshape_position_show(struct mddev *mddev, char *page)
 {
 	if (mddev->reshape_position != MaxSector)
 		return sprintf(page, "%llu\n",
@@ -4379,7 +4379,7 @@ reshape_position_show(mddev_t *mddev, ch
 }
 
 static ssize_t
-reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
+reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4400,7 +4400,7 @@ __ATTR(reshape_position, S_IRUGO|S_IWUSR
        reshape_position_store);
 
 static ssize_t
-array_size_show(mddev_t *mddev, char *page)
+array_size_show(struct mddev *mddev, char *page)
 {
 	if (mddev->external_size)
 		return sprintf(page, "%llu\n",
@@ -4410,7 +4410,7 @@ array_size_show(mddev_t *mddev, char *pa
 }
 
 static ssize_t
-array_size_store(mddev_t *mddev, const char *buf, size_t len)
+array_size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	sector_t sectors;
 
@@ -4485,16 +4485,25 @@ static ssize_t
 md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
 	struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
-	mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+	struct mddev *mddev = container_of(kobj, struct mddev, kobj);
 	ssize_t rv;
 
 	if (!entry->show)
 		return -EIO;
+	spin_lock(&all_mddevs_lock);
+	if (list_empty(&mddev->all_mddevs)) {
+		spin_unlock(&all_mddevs_lock);
+		return -EBUSY;
+	}
+	mddev_get(mddev);
+	spin_unlock(&all_mddevs_lock);
+
 	rv = mddev_lock(mddev);
 	if (!rv) {
 		rv = entry->show(mddev, page);
 		mddev_unlock(mddev);
 	}
+	mddev_put(mddev);
 	return rv;
 }
 
@@ -4503,26 +4512,32 @@ md_attr_store(struct kobject *kobj, stru
 	      const char *page, size_t length)
 {
 	struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
-	mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+	struct mddev *mddev = container_of(kobj, struct mddev, kobj);
 	ssize_t rv;
 
 	if (!entry->store)
 		return -EIO;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
+	spin_lock(&all_mddevs_lock);
+	if (list_empty(&mddev->all_mddevs)) {
+		spin_unlock(&all_mddevs_lock);
+		return -EBUSY;
+	}
+	mddev_get(mddev);
+	spin_unlock(&all_mddevs_lock);
 	rv = mddev_lock(mddev);
-	if (mddev->hold_active == UNTIL_IOCTL)
-		mddev->hold_active = 0;
 	if (!rv) {
 		rv = entry->store(mddev, page, length);
 		mddev_unlock(mddev);
 	}
+	mddev_put(mddev);
 	return rv;
 }
 
 static void md_free(struct kobject *ko)
 {
-	mddev_t *mddev = container_of(ko, mddev_t, kobj);
+	struct mddev *mddev = container_of(ko, struct mddev, kobj);
 
 	if (mddev->sysfs_state)
 		sysfs_put(mddev->sysfs_state);
@@ -4551,7 +4566,7 @@ int mdp_major = 0;
 
 static void mddev_delayed_delete(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, del_work);
+	struct mddev *mddev = container_of(ws, struct mddev, del_work);
 
 	sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
 	kobject_del(&mddev->kobj);
@@ -4561,7 +4576,7 @@ static void mddev_delayed_delete(struct
 static int md_alloc(dev_t dev, char *name)
 {
 	static DEFINE_MUTEX(disks_mutex);
-	mddev_t *mddev = mddev_find(dev);
+	struct mddev *mddev = mddev_find(dev);
 	struct gendisk *disk;
 	int partitioned;
 	int shift;
@@ -4588,7 +4603,7 @@ static int md_alloc(dev_t dev, char *nam
 	if (name) {
 		/* Need to ensure that 'name' is not a duplicate.
 		 */
-		mddev_t *mddev2;
+		struct mddev *mddev2;
 		spin_lock(&all_mddevs_lock);
 
 		list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
@@ -4689,7 +4704,7 @@ static int add_named_array(const char *v
 
 static void md_safemode_timeout(unsigned long data)
 {
-	mddev_t *mddev = (mddev_t *) data;
+	struct mddev *mddev = (struct mddev *) data;
 
 	if (!atomic_read(&mddev->writes_pending)) {
 		mddev->safemode = 1;
@@ -4701,11 +4716,11 @@ static void md_safemode_timeout(unsigned
 
 static int start_dirty_degraded;
 
-int md_run(mddev_t *mddev)
+int md_run(struct mddev *mddev)
 {
 	int err;
-	mdk_rdev_t *rdev;
-	struct mdk_personality *pers;
+	struct md_rdev *rdev;
+	struct md_personality *pers;
 
 	if (list_empty(&mddev->disks))
 		/* cannot run an array with no devices.. */
@@ -4769,7 +4784,7 @@ int md_run(mddev_t *mddev)
 
 	if (mddev->bio_set == NULL)
 		mddev->bio_set = bioset_create(BIO_POOL_SIZE,
-					       sizeof(mddev_t *));
+					       sizeof(struct mddev *));
 
 	spin_lock(&pers_lock);
 	pers = find_pers(mddev->level, mddev->clevel);
@@ -4804,7 +4819,7 @@ int md_run(mddev_t *mddev)
 		 * configuration.
 		 */
 		char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
-		mdk_rdev_t *rdev2;
+		struct md_rdev *rdev2;
 		int warned = 0;
 
 		list_for_each_entry(rdev, &mddev->disks, same_set)
@@ -4903,7 +4918,7 @@ int md_run(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_run);
 
-static int do_md_run(mddev_t *mddev)
+static int do_md_run(struct mddev *mddev)
 {
 	int err;
 
@@ -4927,7 +4942,7 @@ out:
 	return err;
 }
 
-static int restart_array(mddev_t *mddev)
+static int restart_array(struct mddev *mddev)
 {
 	struct gendisk *disk = mddev->gendisk;
 
@@ -4977,7 +4992,7 @@ void restore_bitmap_write_access(struct
 	spin_unlock(&inode->i_lock);
 }
 
-static void md_clean(mddev_t *mddev)
+static void md_clean(struct mddev *mddev)
 {
 	mddev->array_sectors = 0;
 	mddev->external_size = 0;
@@ -5020,7 +5035,7 @@ static void md_clean(mddev_t *mddev)
 	mddev->bitmap_info.max_write_behind = 0;
 }
 
-static void __md_stop_writes(mddev_t *mddev)
+static void __md_stop_writes(struct mddev *mddev)
 {
 	if (mddev->sync_thread) {
 		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -5040,7 +5055,7 @@ static void __md_stop_writes(mddev_t *md
 	}
 }
 
-void md_stop_writes(mddev_t *mddev)
+void md_stop_writes(struct mddev *mddev)
 {
 	mddev_lock(mddev);
 	__md_stop_writes(mddev);
@@ -5048,7 +5063,7 @@ void md_stop_writes(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(mddev_t *mddev)
+void md_stop(struct mddev *mddev)
 {
 	mddev->ready = 0;
 	mddev->pers->stop(mddev);
@@ -5060,7 +5075,7 @@ void md_stop(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop);
 
-static int md_set_readonly(mddev_t *mddev, int is_open)
+static int md_set_readonly(struct mddev *mddev, int is_open)
 {
 	int err = 0;
 	mutex_lock(&mddev->open_mutex);
@@ -5090,10 +5105,10 @@ out:
  *   0 - completely stop and dis-assemble array
  *   2 - stop but do not disassemble array
  */
-static int do_md_stop(mddev_t * mddev, int mode, int is_open)
+static int do_md_stop(struct mddev * mddev, int mode, int is_open)
 {
 	struct gendisk *disk = mddev->gendisk;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	mutex_lock(&mddev->open_mutex);
 	if (atomic_read(&mddev->openers) > is_open ||
@@ -5156,9 +5171,9 @@ static int do_md_stop(mddev_t * mddev, i
 }
 
 #ifndef MODULE
-static void autorun_array(mddev_t *mddev)
+static void autorun_array(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int err;
 
 	if (list_empty(&mddev->disks))
@@ -5193,8 +5208,8 @@ static void autorun_array(mddev_t *mddev
  */
 static void autorun_devices(int part)
 {
-	mdk_rdev_t *rdev0, *rdev, *tmp;
-	mddev_t *mddev;
+	struct md_rdev *rdev0, *rdev, *tmp;
+	struct mddev *mddev;
 	char b[BDEVNAME_SIZE];
 
 	printk(KERN_INFO "md: autorun ...\n");
@@ -5203,7 +5218,7 @@ static void autorun_devices(int part)
 		dev_t dev;
 		LIST_HEAD(candidates);
 		rdev0 = list_entry(pending_raid_disks.next,
-					 mdk_rdev_t, same_set);
+					 struct md_rdev, same_set);
 
 		printk(KERN_INFO "md: considering %s ...\n",
 			bdevname(rdev0->bdev,b));
@@ -5289,11 +5304,11 @@ static int get_version(void __user * arg
 	return 0;
 }
 
-static int get_array_info(mddev_t * mddev, void __user * arg)
+static int get_array_info(struct mddev * mddev, void __user * arg)
 {
 	mdu_array_info_t info;
 	int nr,working,insync,failed,spare;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	nr=working=insync=failed=spare=0;
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
@@ -5342,7 +5357,7 @@ static int get_array_info(mddev_t * mdde
 	return 0;
 }
 
-static int get_bitmap_file(mddev_t * mddev, void __user * arg)
+static int get_bitmap_file(struct mddev * mddev, void __user * arg)
 {
 	mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
 	char *ptr, *buf = NULL;
@@ -5382,10 +5397,10 @@ out:
 	return err;
 }
 
-static int get_disk_info(mddev_t * mddev, void __user * arg)
+static int get_disk_info(struct mddev * mddev, void __user * arg)
 {
 	mdu_disk_info_t info;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
@@ -5416,10 +5431,10 @@ static int get_disk_info(mddev_t * mddev
 	return 0;
 }
 
-static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
 {
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	dev_t dev = MKDEV(info->major,info->minor);
 
 	if (info->major != MAJOR(dev) || info->minor != MINOR(dev))
@@ -5436,8 +5451,9 @@ static int add_new_disk(mddev_t * mddev,
 			return PTR_ERR(rdev);
 		}
 		if (!list_empty(&mddev->disks)) {
-			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
-							mdk_rdev_t, same_set);
+			struct md_rdev *rdev0
+				= list_entry(mddev->disks.next,
+					     struct md_rdev, same_set);
 			err = super_types[mddev->major_version]
 				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0) {
@@ -5587,10 +5603,10 @@ static int add_new_disk(mddev_t * mddev,
 	return 0;
 }
 
-static int hot_remove_disk(mddev_t * mddev, dev_t dev)
+static int hot_remove_disk(struct mddev * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
@@ -5610,11 +5626,11 @@ busy:
 	return -EBUSY;
 }
 
-static int hot_add_disk(mddev_t * mddev, dev_t dev)
+static int hot_add_disk(struct mddev * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
 	int err;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (!mddev->pers)
 		return -ENODEV;
@@ -5684,7 +5700,7 @@ abort_export:
 	return err;
 }
 
-static int set_bitmap_file(mddev_t *mddev, int fd)
+static int set_bitmap_file(struct mddev *mddev, int fd)
 {
 	int err;
 
@@ -5757,7 +5773,7 @@ static int set_bitmap_file(mddev_t *mdde
  *  The minor and patch _version numbers are also kept incase the
  *  super_block handler wishes to interpret them.
  */
-static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
+static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
 {
 
 	if (info->raid_disks == 0) {
@@ -5827,7 +5843,7 @@ static int set_array_info(mddev_t * mdde
 	return 0;
 }
 
-void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
+void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors)
 {
 	WARN(!mddev_is_locked(mddev), "%s: unlocked mddev!\n", __func__);
 
@@ -5838,9 +5854,9 @@ void md_set_array_sectors(mddev_t *mddev
 }
 EXPORT_SYMBOL(md_set_array_sectors);
 
-static int update_size(mddev_t *mddev, sector_t num_sectors)
+static int update_size(struct mddev *mddev, sector_t num_sectors)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int rv;
 	int fit = (num_sectors == 0);
 
@@ -5876,7 +5892,7 @@ static int update_size(mddev_t *mddev, s
 	return rv;
 }
 
-static int update_raid_disks(mddev_t *mddev, int raid_disks)
+static int update_raid_disks(struct mddev *mddev, int raid_disks)
 {
 	int rv;
 	/* change the number of raid disks */
@@ -5904,7 +5920,7 @@ static int update_raid_disks(mddev_t *md
  * Any differences that cannot be handled will cause an error.
  * Normally, only one change can be managed at a time.
  */
-static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
 {
 	int rv = 0;
 	int cnt = 0;
@@ -5997,9 +6013,9 @@ static int update_array_info(mddev_t *md
 	return rv;
 }
 
-static int set_disk_faulty(mddev_t *mddev, dev_t dev)
+static int set_disk_faulty(struct mddev *mddev, dev_t dev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->pers == NULL)
 		return -ENODEV;
@@ -6022,7 +6038,7 @@ static int set_disk_faulty(mddev_t *mdde
  */
 static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-	mddev_t *mddev = bdev->bd_disk->private_data;
+	struct mddev *mddev = bdev->bd_disk->private_data;
 
 	geo->heads = 2;
 	geo->sectors = 4;
@@ -6035,7 +6051,7 @@ static int md_ioctl(struct block_device
 {
 	int err = 0;
 	void __user *argp = (void __user *)arg;
-	mddev_t *mddev = NULL;
+	struct mddev *mddev = NULL;
 	int ro;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -6298,7 +6314,7 @@ static int md_open(struct block_device *
 	 * Succeed if we can lock the mddev, which confirms that
 	 * it isn't being stopped right now.
 	 */
-	mddev_t *mddev = mddev_find(bdev->bd_dev);
+	struct mddev *mddev = mddev_find(bdev->bd_dev);
 	int err;
 
 	if (mddev->gendisk != bdev->bd_disk) {
@@ -6327,7 +6343,7 @@ static int md_open(struct block_device *
 
 static int md_release(struct gendisk *disk, fmode_t mode)
 {
- 	mddev_t *mddev = disk->private_data;
+ 	struct mddev *mddev = disk->private_data;
 
 	BUG_ON(!mddev);
 	atomic_dec(&mddev->openers);
@@ -6338,14 +6354,14 @@ static int md_release(struct gendisk *di
 
 static int md_media_changed(struct gendisk *disk)
 {
-	mddev_t *mddev = disk->private_data;
+	struct mddev *mddev = disk->private_data;
 
 	return mddev->changed;
 }
 
 static int md_revalidate(struct gendisk *disk)
 {
-	mddev_t *mddev = disk->private_data;
+	struct mddev *mddev = disk->private_data;
 
 	mddev->changed = 0;
 	return 0;
@@ -6366,7 +6382,7 @@ static const struct block_device_operati
 
 static int md_thread(void * arg)
 {
-	mdk_thread_t *thread = arg;
+	struct md_thread *thread = arg;
 
 	/*
 	 * md_thread is a 'system-thread', it's priority should be very
@@ -6405,21 +6421,21 @@ static int md_thread(void * arg)
 	return 0;
 }
 
-void md_wakeup_thread(mdk_thread_t *thread)
+void md_wakeup_thread(struct md_thread *thread)
 {
 	if (thread) {
-		dprintk("md: waking up MD thread %s.\n", thread->tsk->comm);
+		pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm);
 		set_bit(THREAD_WAKEUP, &thread->flags);
 		wake_up(&thread->wqueue);
 	}
 }
 
-mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev,
 				 const char *name)
 {
-	mdk_thread_t *thread;
+	struct md_thread *thread;
 
-	thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+	thread = kzalloc(sizeof(struct md_thread), GFP_KERNEL);
 	if (!thread)
 		return NULL;
 
@@ -6439,12 +6455,12 @@ mdk_thread_t *md_register_thread(void (*
 	return thread;
 }
 
-void md_unregister_thread(mdk_thread_t **threadp)
+void md_unregister_thread(struct md_thread **threadp)
 {
-	mdk_thread_t *thread = *threadp;
+	struct md_thread *thread = *threadp;
 	if (!thread)
 		return;
-	dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
+	pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
 	/* Locking ensures that mddev_unlock does not wake_up a
 	 * non-existent thread
 	 */
@@ -6456,7 +6472,7 @@ void md_unregister_thread(mdk_thread_t *
 	kfree(thread);
 }
 
-void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
+void md_error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	if (!mddev) {
 		MD_BUG();
@@ -6485,7 +6501,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t
 static void status_unused(struct seq_file *seq)
 {
 	int i = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	seq_printf(seq, "unused devices: ");
 
@@ -6502,7 +6518,7 @@ static void status_unused(struct seq_fil
 }
 
 
-static void status_resync(struct seq_file *seq, mddev_t * mddev)
+static void status_resync(struct seq_file *seq, struct mddev * mddev)
 {
 	sector_t max_sectors, resync, res;
 	unsigned long dt, db;
@@ -6593,7 +6609,7 @@ static void *md_seq_start(struct seq_fil
 {
 	struct list_head *tmp;
 	loff_t l = *pos;
-	mddev_t *mddev;
+	struct mddev *mddev;
 
 	if (l >= 0x10000)
 		return NULL;
@@ -6604,7 +6620,7 @@ static void *md_seq_start(struct seq_fil
 	spin_lock(&all_mddevs_lock);
 	list_for_each(tmp,&all_mddevs)
 		if (!l--) {
-			mddev = list_entry(tmp, mddev_t, all_mddevs);
+			mddev = list_entry(tmp, struct mddev, all_mddevs);
 			mddev_get(mddev);
 			spin_unlock(&all_mddevs_lock);
 			return mddev;
@@ -6618,7 +6634,7 @@ static void *md_seq_start(struct seq_fil
 static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct list_head *tmp;
-	mddev_t *next_mddev, *mddev = v;
+	struct mddev *next_mddev, *mddev = v;
 	
 	++*pos;
 	if (v == (void*)2)
@@ -6630,7 +6646,7 @@ static void *md_seq_next(struct seq_file
 	else
 		tmp = mddev->all_mddevs.next;
 	if (tmp != &all_mddevs)
-		next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs));
+		next_mddev = mddev_get(list_entry(tmp,struct mddev,all_mddevs));
 	else {
 		next_mddev = (void*)2;
 		*pos = 0x10000;
@@ -6645,7 +6661,7 @@ static void *md_seq_next(struct seq_file
 
 static void md_seq_stop(struct seq_file *seq, void *v)
 {
-	mddev_t *mddev = v;
+	struct mddev *mddev = v;
 
 	if (mddev && v != (void*)1 && v != (void*)2)
 		mddev_put(mddev);
@@ -6653,13 +6669,13 @@ static void md_seq_stop(struct seq_file
 
 static int md_seq_show(struct seq_file *seq, void *v)
 {
-	mddev_t *mddev = v;
+	struct mddev *mddev = v;
 	sector_t sectors;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct bitmap *bitmap;
 
 	if (v == (void*)1) {
-		struct mdk_personality *pers;
+		struct md_personality *pers;
 		seq_printf(seq, "Personalities : ");
 		spin_lock(&pers_lock);
 		list_for_each_entry(pers, &pers_list, list)
@@ -6815,7 +6831,7 @@ static const struct file_operations md_s
 	.poll		= mdstat_poll,
 };
 
-int register_md_personality(struct mdk_personality *p)
+int register_md_personality(struct md_personality *p)
 {
 	spin_lock(&pers_lock);
 	list_add_tail(&p->list, &pers_list);
@@ -6824,7 +6840,7 @@ int register_md_personality(struct mdk_p
 	return 0;
 }
 
-int unregister_md_personality(struct mdk_personality *p)
+int unregister_md_personality(struct md_personality *p)
 {
 	printk(KERN_INFO "md: %s personality unregistered\n", p->name);
 	spin_lock(&pers_lock);
@@ -6833,9 +6849,9 @@ int unregister_md_personality(struct mdk
 	return 0;
 }
 
-static int is_mddev_idle(mddev_t *mddev, int init)
+static int is_mddev_idle(struct mddev *mddev, int init)
 {
-	mdk_rdev_t * rdev;
+	struct md_rdev * rdev;
 	int idle;
 	int curr_events;
 
@@ -6877,7 +6893,7 @@ static int is_mddev_idle(mddev_t *mddev,
 	return idle;
 }
 
-void md_done_sync(mddev_t *mddev, int blocks, int ok)
+void md_done_sync(struct mddev *mddev, int blocks, int ok)
 {
 	/* another "blocks" (512byte) blocks have been synced */
 	atomic_sub(blocks, &mddev->recovery_active);
@@ -6895,7 +6911,7 @@ void md_done_sync(mddev_t *mddev, int bl
  * in superblock) before writing, schedule a superblock update
  * and wait for it to complete.
  */
-void md_write_start(mddev_t *mddev, struct bio *bi)
+void md_write_start(struct mddev *mddev, struct bio *bi)
 {
 	int did_change = 0;
 	if (bio_data_dir(bi) != WRITE)
@@ -6930,7 +6946,7 @@ void md_write_start(mddev_t *mddev, stru
 		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
 }
 
-void md_write_end(mddev_t *mddev)
+void md_write_end(struct mddev *mddev)
 {
 	if (atomic_dec_and_test(&mddev->writes_pending)) {
 		if (mddev->safemode == 2)
@@ -6949,7 +6965,7 @@ void md_write_end(mddev_t *mddev)
  * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
  * is dropped, so return -EAGAIN after notifying userspace.
  */
-int md_allow_write(mddev_t *mddev)
+int md_allow_write(struct mddev *mddev)
 {
 	if (!mddev->pers)
 		return 0;
@@ -6981,9 +6997,9 @@ EXPORT_SYMBOL_GPL(md_allow_write);
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
-void md_do_sync(mddev_t *mddev)
+void md_do_sync(struct mddev *mddev)
 {
-	mddev_t *mddev2;
+	struct mddev *mddev2;
 	unsigned int currspeed = 0,
 		 window;
 	sector_t max_sectors,j, io_sectors;
@@ -6993,7 +7009,7 @@ void md_do_sync(mddev_t *mddev)
 	struct list_head *tmp;
 	sector_t last_check;
 	int skipped = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	char *desc;
 
 	/* just incase thread restarts... */
@@ -7308,9 +7324,9 @@ void md_do_sync(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_do_sync);
 
-static int remove_and_add_spares(mddev_t *mddev)
+static int remove_and_add_spares(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int spares = 0;
 
 	mddev->curr_resync_completed = 0;
@@ -7344,17 +7360,16 @@ static int remove_and_add_spares(mddev_t
 					spares++;
 					md_new_event(mddev);
 					set_bit(MD_CHANGE_DEVS, &mddev->flags);
-				} else
-					break;
+				}
 			}
 		}
 	}
 	return spares;
 }
 
-static void reap_sync_thread(mddev_t *mddev)
+static void reap_sync_thread(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	/* resync has finished, collect result */
 	md_unregister_thread(&mddev->sync_thread);
@@ -7369,15 +7384,19 @@ static void reap_sync_thread(mddev_t *md
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
 	    mddev->pers->finish_reshape)
 		mddev->pers->finish_reshape(mddev);
-	md_update_sb(mddev, 1);
 
-	/* if array is no-longer degraded, then any saved_raid_disk
-	 * information must be scrapped
+	/* If array is no-longer degraded, then any saved_raid_disk
+	 * information must be scrapped.  Also if any device is now
+	 * In_sync we must scrape the saved_raid_disk for that device
+	 * do the superblock for an incrementally recovered device
+	 * written out.
 	 */
-	if (!mddev->degraded)
-		list_for_each_entry(rdev, &mddev->disks, same_set)
+	list_for_each_entry(rdev, &mddev->disks, same_set)
+		if (!mddev->degraded ||
+		    test_bit(In_sync, &rdev->flags))
 			rdev->saved_raid_disk = -1;
 
+	md_update_sb(mddev, 1);
 	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
 	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -7413,7 +7432,7 @@ static void reap_sync_thread(mddev_t *md
  *  5/ If array is degraded, try to add spares devices
  *  6/ If array has spares or is not in-sync, start a resync thread.
  */
-void md_check_recovery(mddev_t *mddev)
+void md_check_recovery(struct mddev *mddev)
 {
 	if (mddev->suspended)
 		return;
@@ -7449,7 +7468,7 @@ void md_check_recovery(mddev_t *mddev)
 			/* Only thing we do on a ro array is remove
 			 * failed devices.
 			 */
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			list_for_each_entry(rdev, &mddev->disks, same_set)
 				if (rdev->raid_disk >= 0 &&
 				    !test_bit(Blocked, &rdev->flags) &&
@@ -7573,7 +7592,7 @@ void md_check_recovery(mddev_t *mddev)
 	}
 }
 
-void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	sysfs_notify_dirent_safe(rdev->sysfs_state);
 	wait_event_timeout(rdev->blocked_wait,
@@ -7831,13 +7850,14 @@ static int md_set_badblocks(struct badbl
 	return rv;
 }
 
-int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
 		       int acknowledged)
 {
 	int rv = md_set_badblocks(&rdev->badblocks,
 				  s + rdev->data_offset, sectors, acknowledged);
 	if (rv) {
 		/* Make sure they get written out promptly */
+		sysfs_notify_dirent_safe(rdev->sysfs_state);
 		set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
 		md_wakeup_thread(rdev->mddev->thread);
 	}
@@ -7940,7 +7960,7 @@ out:
 	return rv;
 }
 
-int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors)
+int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors)
 {
 	return md_clear_badblocks(&rdev->badblocks,
 				  s + rdev->data_offset,
@@ -8074,13 +8094,14 @@ static int md_notify_reboot(struct notif
 			    unsigned long code, void *x)
 {
 	struct list_head *tmp;
-	mddev_t *mddev;
+	struct mddev *mddev;
+	int need_delay = 0;
 
 	if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
 
 		printk(KERN_INFO "md: stopping all md devices.\n");
 
-		for_each_mddev(mddev, tmp)
+		for_each_mddev(mddev, tmp) {
 			if (mddev_trylock(mddev)) {
 				/* Force a switch to readonly even array
 				 * appears to still be in use.  Hence
@@ -8089,13 +8110,16 @@ static int md_notify_reboot(struct notif
 				md_set_readonly(mddev, 100);
 				mddev_unlock(mddev);
 			}
+			need_delay = 1;
+		}
 		/*
 		 * certain more exotic SCSI devices are known to be
 		 * volatile wrt too early system reboots. While the
 		 * right place to handle this issue is the given
 		 * driver, we do want to have a safe RAID driver ...
 		 */
-		mdelay(1000*1);
+		if (need_delay)
+			mdelay(1000*1);
 	}
 	return NOTIFY_DONE;
 }
@@ -8108,7 +8132,7 @@ static struct notifier_block md_notifier
 
 static void md_geninit(void)
 {
-	dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+	pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
 	proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
 }
@@ -8183,7 +8207,7 @@ void md_autodetect_dev(dev_t dev)
 
 static void autostart_arrays(int part)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct detected_devices_node *node_detected_dev;
 	dev_t dev;
 	int i_scanned, i_passed;
@@ -8223,7 +8247,7 @@ static void autostart_arrays(int part)
 
 static __exit void md_exit(void)
 {
-	mddev_t *mddev;
+	struct mddev *mddev;
 	struct list_head *tmp;
 
 	blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
diff -druNp linux-libre-3.1-gnu1/drivers/md/md.h linux-libre-3.2-gnu1/drivers/md/md.h
--- linux-libre-3.1-gnu1/drivers/md/md.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/md.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
-   md_k.h : kernel internal structure of the Linux MD driver
+   md.h : kernel internal structure of the Linux MD driver
           Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
 	  
    This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,6 @@
 
 #define MaxSector (~(sector_t)0)
 
-typedef struct mddev_s mddev_t;
-typedef struct mdk_rdev_s mdk_rdev_t;
-
 /* Bad block numbers are stored sorted in a single page.
  * 64bits is used for each block or extent.
  * 54 bits are sector number, 9 bits are extent size,
@@ -39,12 +36,11 @@ typedef struct mdk_rdev_s mdk_rdev_t;
 /*
  * MD's 'extended' device
  */
-struct mdk_rdev_s
-{
+struct md_rdev {
 	struct list_head same_set;	/* RAID devices within the same set */
 
 	sector_t sectors;		/* Device size (in 512bytes sectors) */
-	mddev_t *mddev;			/* RAID array if running */
+	struct mddev *mddev;		/* RAID array if running */
 	int last_events;		/* IO event timestamp */
 
 	/*
@@ -168,7 +164,7 @@ struct mdk_rdev_s
 
 extern int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 			  sector_t *first_bad, int *bad_sectors);
-static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors,
+static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
 			      sector_t *first_bad, int *bad_sectors)
 {
 	if (unlikely(rdev->badblocks.count)) {
@@ -181,15 +177,14 @@ static inline int is_badblock(mdk_rdev_t
 	}
 	return 0;
 }
-extern int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+extern int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
 			      int acknowledged);
-extern int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors);
+extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors);
 extern void md_ack_all_badblocks(struct badblocks *bb);
 
-struct mddev_s
-{
+struct mddev {
 	void				*private;
-	struct mdk_personality		*pers;
+	struct md_personality		*pers;
 	dev_t				unit;
 	int				md_minor;
 	struct list_head 		disks;
@@ -256,8 +251,8 @@ struct mddev_s
 	atomic_t			plug_cnt;	/* If device is expecting
 							 * more bios soon.
 							 */
-	struct mdk_thread_s		*thread;	/* management thread */
-	struct mdk_thread_s		*sync_thread;	/* doing resync or reconstruct */
+	struct md_thread		*thread;	/* management thread */
+	struct md_thread		*sync_thread;	/* doing resync or reconstruct */
 	sector_t			curr_resync;	/* last block scheduled */
 	/* As resync requests can complete out of order, we cannot easily track
 	 * how much resync has been completed.  So we occasionally pause until
@@ -402,11 +397,11 @@ struct mddev_s
 	atomic_t flush_pending;
 	struct work_struct flush_work;
 	struct work_struct event_work;	/* used by dm to report failure event */
-	void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+	void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
 };
 
 
-static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
+static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
 {
 	int faulty = test_bit(Faulty, &rdev->flags);
 	if (atomic_dec_and_test(&rdev->nr_pending) && faulty)
@@ -418,35 +413,35 @@ static inline void md_sync_acct(struct b
         atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
 }
 
-struct mdk_personality
+struct md_personality
 {
 	char *name;
 	int level;
 	struct list_head list;
 	struct module *owner;
-	int (*make_request)(mddev_t *mddev, struct bio *bio);
-	int (*run)(mddev_t *mddev);
-	int (*stop)(mddev_t *mddev);
-	void (*status)(struct seq_file *seq, mddev_t *mddev);
+	void (*make_request)(struct mddev *mddev, struct bio *bio);
+	int (*run)(struct mddev *mddev);
+	int (*stop)(struct mddev *mddev);
+	void (*status)(struct seq_file *seq, struct mddev *mddev);
 	/* error_handler must set ->faulty and clear ->in_sync
 	 * if appropriate, and should abort recovery if needed 
 	 */
-	void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev);
-	int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
-	int (*hot_remove_disk) (mddev_t *mddev, int number);
-	int (*spare_active) (mddev_t *mddev);
-	sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
-	int (*resize) (mddev_t *mddev, sector_t sectors);
-	sector_t (*size) (mddev_t *mddev, sector_t sectors, int raid_disks);
-	int (*check_reshape) (mddev_t *mddev);
-	int (*start_reshape) (mddev_t *mddev);
-	void (*finish_reshape) (mddev_t *mddev);
+	void (*error_handler)(struct mddev *mddev, struct md_rdev *rdev);
+	int (*hot_add_disk) (struct mddev *mddev, struct md_rdev *rdev);
+	int (*hot_remove_disk) (struct mddev *mddev, int number);
+	int (*spare_active) (struct mddev *mddev);
+	sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster);
+	int (*resize) (struct mddev *mddev, sector_t sectors);
+	sector_t (*size) (struct mddev *mddev, sector_t sectors, int raid_disks);
+	int (*check_reshape) (struct mddev *mddev);
+	int (*start_reshape) (struct mddev *mddev);
+	void (*finish_reshape) (struct mddev *mddev);
 	/* quiesce moves between quiescence states
 	 * 0 - fully active
 	 * 1 - no new requests allowed
 	 * others - reserved
 	 */
-	void (*quiesce) (mddev_t *mddev, int state);
+	void (*quiesce) (struct mddev *mddev, int state);
 	/* takeover is used to transition an array from one
 	 * personality to another.  The new personality must be able
 	 * to handle the data in the current layout.
@@ -456,14 +451,14 @@ struct mdk_personality
 	 * This needs to be installed and then ->run used to activate the
 	 * array.
 	 */
-	void *(*takeover) (mddev_t *mddev);
+	void *(*takeover) (struct mddev *mddev);
 };
 
 
 struct md_sysfs_entry {
 	struct attribute attr;
-	ssize_t (*show)(mddev_t *, char *);
-	ssize_t (*store)(mddev_t *, const char *, size_t);
+	ssize_t (*show)(struct mddev *, char *);
+	ssize_t (*store)(struct mddev *, const char *, size_t);
 };
 extern struct attribute_group md_bitmap_group;
 
@@ -479,19 +474,19 @@ static inline void sysfs_notify_dirent_s
 		sysfs_notify_dirent(sd);
 }
 
-static inline char * mdname (mddev_t * mddev)
+static inline char * mdname (struct mddev * mddev)
 {
 	return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
 }
 
-static inline int sysfs_link_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
 	sprintf(nm, "rd%d", rdev->raid_disk);
 	return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
 }
 
-static inline void sysfs_unlink_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
 	sprintf(nm, "rd%d", rdev->raid_disk);
@@ -514,14 +509,14 @@ static inline void sysfs_unlink_rdev(mdd
 #define rdev_for_each_rcu(rdev, mddev)				\
 	list_for_each_entry_rcu(rdev, &((mddev)->disks), same_set)
 
-typedef struct mdk_thread_s {
-	void			(*run) (mddev_t *mddev);
-	mddev_t			*mddev;
+struct md_thread {
+	void			(*run) (struct mddev *mddev);
+	struct mddev		*mddev;
 	wait_queue_head_t	wqueue;
 	unsigned long           flags;
 	struct task_struct	*tsk;
 	unsigned long		timeout;
-} mdk_thread_t;
+};
 
 #define THREAD_WAKEUP  0
 
@@ -556,48 +551,50 @@ static inline void safe_put_page(struct
 	if (p) put_page(p);
 }
 
-extern int register_md_personality(struct mdk_personality *p);
-extern int unregister_md_personality(struct mdk_personality *p);
-extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
-				mddev_t *mddev, const char *name);
-extern void md_unregister_thread(mdk_thread_t **threadp);
-extern void md_wakeup_thread(mdk_thread_t *thread);
-extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev, struct bio *bi);
-extern void md_write_end(mddev_t *mddev);
-extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
+extern int register_md_personality(struct md_personality *p);
+extern int unregister_md_personality(struct md_personality *p);
+extern struct md_thread *md_register_thread(
+	void (*run)(struct mddev *mddev),
+	struct mddev *mddev,
+	const char *name);
+extern void md_unregister_thread(struct md_thread **threadp);
+extern void md_wakeup_thread(struct md_thread *thread);
+extern void md_check_recovery(struct mddev *mddev);
+extern void md_write_start(struct mddev *mddev, struct bio *bi);
+extern void md_write_end(struct mddev *mddev);
+extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
 
-extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_flush_request(mddev_t *mddev, struct bio *bio);
-extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+extern int mddev_congested(struct mddev *mddev, int bits);
+extern void md_flush_request(struct mddev *mddev, struct bio *bio);
+extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 			   sector_t sector, int size, struct page *page);
-extern void md_super_wait(mddev_t *mddev);
-extern int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size, 
+extern void md_super_wait(struct mddev *mddev);
+extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, 
 			struct page *page, int rw, bool metadata_op);
-extern void md_do_sync(mddev_t *mddev);
-extern void md_new_event(mddev_t *mddev);
-extern int md_allow_write(mddev_t *mddev);
-extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
-extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
-extern int md_check_no_bitmap(mddev_t *mddev);
-extern int md_integrity_register(mddev_t *mddev);
-extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+extern void md_do_sync(struct mddev *mddev);
+extern void md_new_event(struct mddev *mddev);
+extern int md_allow_write(struct mddev *mddev);
+extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
+extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
+extern int md_check_no_bitmap(struct mddev *mddev);
+extern int md_integrity_register(struct mddev *mddev);
+extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
 extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
 extern void restore_bitmap_write_access(struct file *file);
 
-extern void mddev_init(mddev_t *mddev);
-extern int md_run(mddev_t *mddev);
-extern void md_stop(mddev_t *mddev);
-extern void md_stop_writes(mddev_t *mddev);
-extern int md_rdev_init(mdk_rdev_t *rdev);
+extern void mddev_init(struct mddev *mddev);
+extern int md_run(struct mddev *mddev);
+extern void md_stop(struct mddev *mddev);
+extern void md_stop_writes(struct mddev *mddev);
+extern int md_rdev_init(struct md_rdev *rdev);
 
-extern void mddev_suspend(mddev_t *mddev);
-extern void mddev_resume(mddev_t *mddev);
+extern void mddev_suspend(struct mddev *mddev);
+extern void mddev_resume(struct mddev *mddev);
 extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
-				   mddev_t *mddev);
+				   struct mddev *mddev);
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
-				   mddev_t *mddev);
-extern int mddev_check_plugged(mddev_t *mddev);
+				   struct mddev *mddev);
+extern int mddev_check_plugged(struct mddev *mddev);
 extern void md_trim_bio(struct bio *bio, int offset, int size);
 #endif /* _MD_MD_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/multipath.c linux-libre-3.2-gnu1/drivers/md/multipath.c
--- linux-libre-3.1-gnu1/drivers/md/multipath.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/multipath.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/raid/md_u.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -31,7 +32,7 @@
 #define	NR_RESERVED_BUFS	32
 
 
-static int multipath_map (multipath_conf_t *conf)
+static int multipath_map (struct mpconf *conf)
 {
 	int i, disks = conf->raid_disks;
 
@@ -42,7 +43,7 @@ static int multipath_map (multipath_conf
 
 	rcu_read_lock();
 	for (i = 0; i < disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
 		if (rdev && test_bit(In_sync, &rdev->flags)) {
 			atomic_inc(&rdev->nr_pending);
 			rcu_read_unlock();
@@ -58,8 +59,8 @@ static int multipath_map (multipath_conf
 static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
 {
 	unsigned long flags;
-	mddev_t *mddev = mp_bh->mddev;
-	multipath_conf_t *conf = mddev->private;
+	struct mddev *mddev = mp_bh->mddev;
+	struct mpconf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&mp_bh->retry_list, &conf->retry_list);
@@ -76,7 +77,7 @@ static void multipath_reschedule_retry (
 static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 {
 	struct bio *bio = mp_bh->master_bio;
-	multipath_conf_t *conf = mp_bh->mddev->private;
+	struct mpconf *conf = mp_bh->mddev->private;
 
 	bio_endio(bio, err);
 	mempool_free(mp_bh, conf->pool);
@@ -86,8 +87,8 @@ static void multipath_end_request(struct
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct multipath_bh *mp_bh = bio->bi_private;
-	multipath_conf_t *conf = mp_bh->mddev->private;
-	mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
+	struct mpconf *conf = mp_bh->mddev->private;
+	struct md_rdev *rdev = conf->multipaths[mp_bh->path].rdev;
 
 	if (uptodate)
 		multipath_end_bh_io(mp_bh, 0);
@@ -106,15 +107,15 @@ static void multipath_end_request(struct
 	rdev_dec_pending(rdev, conf->mddev);
 }
 
-static int multipath_make_request(mddev_t *mddev, struct bio * bio)
+static void multipath_make_request(struct mddev *mddev, struct bio * bio)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
@@ -126,7 +127,7 @@ static int multipath_make_request(mddev_
 	if (mp_bh->path < 0) {
 		bio_endio(bio, -EIO);
 		mempool_free(mp_bh, conf->pool);
-		return 0;
+		return;
 	}
 	multipath = conf->multipaths + mp_bh->path;
 
@@ -137,12 +138,12 @@ static int multipath_make_request(mddev_
 	mp_bh->bio.bi_end_io = multipath_end_request;
 	mp_bh->bio.bi_private = mp_bh;
 	generic_make_request(&mp_bh->bio);
-	return 0;
+	return;
 }
 
-static void multipath_status (struct seq_file *seq, mddev_t *mddev)
+static void multipath_status (struct seq_file *seq, struct mddev *mddev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	int i;
 	
 	seq_printf (seq, " [%d/%d] [", conf->raid_disks,
@@ -156,8 +157,8 @@ static void multipath_status (struct seq
 
 static int multipath_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	multipath_conf_t *conf = mddev->private;
+	struct mddev *mddev = data;
+	struct mpconf *conf = mddev->private;
 	int i, ret = 0;
 
 	if (mddev_congested(mddev, bits))
@@ -165,7 +166,7 @@ static int multipath_congested(void *dat
 
 	rcu_read_lock();
 	for (i = 0; i < mddev->raid_disks ; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -183,9 +184,9 @@ static int multipath_congested(void *dat
 /*
  * Careful, this can execute in IRQ contexts as well!
  */
-static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
+static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	char b[BDEVNAME_SIZE];
 
 	if (conf->raid_disks - mddev->degraded <= 1) {
@@ -218,7 +219,7 @@ static void multipath_error (mddev_t *md
 	       conf->raid_disks - mddev->degraded);
 }
 
-static void print_multipath_conf (multipath_conf_t *conf)
+static void print_multipath_conf (struct mpconf *conf)
 {
 	int i;
 	struct multipath_info *tmp;
@@ -242,9 +243,9 @@ static void print_multipath_conf (multip
 }
 
 
-static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct request_queue *q;
 	int err = -EEXIST;
 	int path;
@@ -291,11 +292,11 @@ static int multipath_add_disk(mddev_t *m
 	return err;
 }
 
-static int multipath_remove_disk(mddev_t *mddev, int number)
+static int multipath_remove_disk(struct mddev *mddev, int number)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct multipath_info *p = conf->multipaths + number;
 
 	print_multipath_conf(conf);
@@ -335,12 +336,12 @@ abort:
  *	3.	Performs writes following reads for array syncronising.
  */
 
-static void multipathd (mddev_t *mddev)
+static void multipathd (struct mddev *mddev)
 {
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 
 	md_check_recovery(mddev);
@@ -379,7 +380,7 @@ static void multipathd (mddev_t *mddev)
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
 
-static sector_t multipath_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t multipath_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	WARN_ONCE(sectors || raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -387,12 +388,12 @@ static sector_t multipath_size(mddev_t *
 	return mddev->dev_sectors;
 }
 
-static int multipath_run (mddev_t *mddev)
+static int multipath_run (struct mddev *mddev)
 {
-	multipath_conf_t *conf;
+	struct mpconf *conf;
 	int disk_idx;
 	struct multipath_info *disk;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int working_disks;
 
 	if (md_check_no_bitmap(mddev))
@@ -409,7 +410,7 @@ static int multipath_run (mddev_t *mddev
 	 * should be freed in multipath_stop()]
 	 */
 
-	conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct mpconf), GFP_KERNEL);
 	mddev->private = conf;
 	if (!conf) {
 		printk(KERN_ERR 
@@ -510,9 +511,9 @@ out:
 }
 
 
-static int multipath_stop (mddev_t *mddev)
+static int multipath_stop (struct mddev *mddev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 
 	md_unregister_thread(&mddev->thread);
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
@@ -523,7 +524,7 @@ static int multipath_stop (mddev_t *mdde
 	return 0;
 }
 
-static struct mdk_personality multipath_personality =
+static struct md_personality multipath_personality =
 {
 	.name		= "multipath",
 	.level		= LEVEL_MULTIPATH,
diff -druNp linux-libre-3.1-gnu1/drivers/md/multipath.h linux-libre-3.2-gnu1/drivers/md/multipath.h
--- linux-libre-3.1-gnu1/drivers/md/multipath.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/multipath.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,11 +2,11 @@
 #define _MULTIPATH_H
 
 struct multipath_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 };
 
-struct multipath_private_data {
-	mddev_t			*mddev;
+struct mpconf {
+	struct mddev			*mddev;
 	struct multipath_info	*multipaths;
 	int			raid_disks;
 	spinlock_t		device_lock;
@@ -15,8 +15,6 @@ struct multipath_private_data {
 	mempool_t		*pool;
 };
 
-typedef struct multipath_private_data multipath_conf_t;
-
 /*
  * this is our 'private' 'collective' MULTIPATH buffer head.
  * it contains information about what kind of IO operations were started
@@ -24,7 +22,7 @@ typedef struct multipath_private_data mu
  */
 
 struct multipath_bh {
-	mddev_t			*mddev;
+	struct mddev			*mddev;
 	struct bio		*master_bio;
 	struct bio		bio;
 	int			path;
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-block-manager.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-block-manager.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-block-manager.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-block-manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-block-manager.h"
+#include "dm-persistent-data-internal.h"
+#include "../dm-bufio.h"
+
+#include <linux/crc32c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/device-mapper.h>
+#include <linux/stacktrace.h>
+
+#define DM_MSG_PREFIX "block manager"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This is a read/write semaphore with a couple of differences.
+ *
+ * i) There is a restriction on the number of concurrent read locks that
+ * may be held at once.  This is just an implementation detail.
+ *
+ * ii) Recursive locking attempts are detected and return EINVAL.  A stack
+ * trace is also emitted for the previous lock aquisition.
+ *
+ * iii) Priority is given to write locks.
+ */
+#define MAX_HOLDERS 4
+#define MAX_STACK 10
+
+typedef unsigned long stack_entries[MAX_STACK];
+
+struct block_lock {
+	spinlock_t lock;
+	__s32 count;
+	struct list_head waiters;
+	struct task_struct *holders[MAX_HOLDERS];
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace traces[MAX_HOLDERS];
+	stack_entries entries[MAX_HOLDERS];
+#endif
+};
+
+struct waiter {
+	struct list_head list;
+	struct task_struct *task;
+	int wants_write;
+};
+
+static unsigned __find_holder(struct block_lock *lock,
+			      struct task_struct *task)
+{
+	unsigned i;
+
+	for (i = 0; i < MAX_HOLDERS; i++)
+		if (lock->holders[i] == task)
+			break;
+
+	BUG_ON(i == MAX_HOLDERS);
+	return i;
+}
+
+/* call this *after* you increment lock->count */
+static void __add_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, NULL);
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace *t;
+#endif
+
+	get_task_struct(task);
+	lock->holders[h] = task;
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	t = lock->traces + h;
+	t->nr_entries = 0;
+	t->max_entries = MAX_STACK;
+	t->entries = lock->entries[h];
+	t->skip = 2;
+	save_stack_trace(t);
+#endif
+}
+
+/* call this *before* you decrement lock->count */
+static void __del_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, task);
+	lock->holders[h] = NULL;
+	put_task_struct(task);
+}
+
+static int __check_holder(struct block_lock *lock)
+{
+	unsigned i;
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	static struct stack_trace t;
+	static stack_entries entries;
+#endif
+
+	for (i = 0; i < MAX_HOLDERS; i++) {
+		if (lock->holders[i] == current) {
+			DMERR("recursive lock detected in pool metadata");
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+			DMERR("previously held here:");
+			print_stack_trace(lock->traces + i, 4);
+
+			DMERR("subsequent aquisition attempted here:");
+			t.nr_entries = 0;
+			t.max_entries = MAX_STACK;
+			t.entries = entries;
+			t.skip = 3;
+			save_stack_trace(&t);
+			print_stack_trace(&t, 4);
+#endif
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void __wait(struct waiter *w)
+{
+	for (;;) {
+		set_task_state(current, TASK_UNINTERRUPTIBLE);
+
+		if (!w->task)
+			break;
+
+		schedule();
+	}
+
+	set_task_state(current, TASK_RUNNING);
+}
+
+static void __wake_waiter(struct waiter *w)
+{
+	struct task_struct *task;
+
+	list_del(&w->list);
+	task = w->task;
+	smp_mb();
+	w->task = NULL;
+	wake_up_process(task);
+}
+
+/*
+ * We either wake a few readers or a single writer.
+ */
+static void __wake_many(struct block_lock *lock)
+{
+	struct waiter *w, *tmp;
+
+	BUG_ON(lock->count < 0);
+	list_for_each_entry_safe(w, tmp, &lock->waiters, list) {
+		if (lock->count >= MAX_HOLDERS)
+			return;
+
+		if (w->wants_write) {
+			if (lock->count > 0)
+				return; /* still read locked */
+
+			lock->count = -1;
+			__add_holder(lock, w->task);
+			__wake_waiter(w);
+			return;
+		}
+
+		lock->count++;
+		__add_holder(lock, w->task);
+		__wake_waiter(w);
+	}
+}
+
+static void bl_init(struct block_lock *lock)
+{
+	int i;
+
+	spin_lock_init(&lock->lock);
+	lock->count = 0;
+	INIT_LIST_HEAD(&lock->waiters);
+	for (i = 0; i < MAX_HOLDERS; i++)
+		lock->holders[i] = NULL;
+}
+
+static int __available_for_read(struct block_lock *lock)
+{
+	return lock->count >= 0 &&
+		lock->count < MAX_HOLDERS &&
+		list_empty(&lock->waiters);
+}
+
+static int bl_down_read(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+
+	w.task = current;
+	w.wants_write = 0;
+	list_add_tail(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+	return 0;
+}
+
+static int bl_down_read_nonblock(struct block_lock *lock)
+{
+	int r;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r)
+		goto out;
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		r = 0;
+	} else
+		r = -EWOULDBLOCK;
+
+out:
+	spin_unlock(&lock->lock);
+	return r;
+}
+
+static void bl_up_read(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	BUG_ON(lock->count <= 0);
+	__del_holder(lock, current);
+	--lock->count;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static int bl_down_write(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (lock->count == 0 && list_empty(&lock->waiters)) {
+		lock->count = -1;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+	w.task = current;
+	w.wants_write = 1;
+
+	/*
+	 * Writers given priority. We know there's only one mutator in the
+	 * system, so ignoring the ordering reversal.
+	 */
+	list_add(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+
+	return 0;
+}
+
+static void bl_up_write(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	__del_holder(lock, current);
+	lock->count = 0;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static void report_recursive_bug(dm_block_t b, int r)
+{
+	if (r == -EINVAL)
+		DMERR("recursive acquisition of block %llu requested.",
+		      (unsigned long long) b);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block manager is currently implemented using dm-bufio.  struct
+ * dm_block_manager and struct dm_block map directly onto a couple of
+ * structs in the bufio interface.  I want to retain the freedom to move
+ * away from bufio in the future.  So these structs are just cast within
+ * this .c file, rather than making it through to the public interface.
+ */
+static struct dm_buffer *to_buffer(struct dm_block *b)
+{
+	return (struct dm_buffer *) b;
+}
+
+static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm)
+{
+	return (struct dm_bufio_client *) bm;
+}
+
+dm_block_t dm_block_location(struct dm_block *b)
+{
+	return dm_bufio_get_block_number(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_location);
+
+void *dm_block_data(struct dm_block *b)
+{
+	return dm_bufio_get_block_data(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_data);
+
+struct buffer_aux {
+	struct dm_block_validator *validator;
+	struct block_lock lock;
+	int write_locked;
+};
+
+static void dm_block_manager_alloc_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	aux->validator = NULL;
+	bl_init(&aux->lock);
+}
+
+static void dm_block_manager_write_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	if (aux->validator) {
+		aux->validator->prepare_for_write(aux->validator, (struct dm_block *) buf,
+			 dm_bufio_get_block_size(dm_bufio_get_client(buf)));
+	}
+}
+
+/*----------------------------------------------------------------
+ * Public interface
+ *--------------------------------------------------------------*/
+struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
+						 unsigned block_size,
+						 unsigned cache_size,
+						 unsigned max_held_per_thread)
+{
+	return (struct dm_block_manager *)
+		dm_bufio_client_create(bdev, block_size, max_held_per_thread,
+				       sizeof(struct buffer_aux),
+				       dm_block_manager_alloc_callback,
+				       dm_block_manager_write_callback);
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_create);
+
+void dm_block_manager_destroy(struct dm_block_manager *bm)
+{
+	return dm_bufio_client_destroy(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_block_size(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_bm_block_size);
+
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_device_size(to_bufio(bm));
+}
+
+static int dm_bm_validate_buffer(struct dm_block_manager *bm,
+				 struct dm_buffer *buf,
+				 struct buffer_aux *aux,
+				 struct dm_block_validator *v)
+{
+	if (unlikely(!aux->validator)) {
+		int r;
+		if (!v)
+			return 0;
+		r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm)));
+		if (unlikely(r))
+			return r;
+		aux->validator = v;
+	} else {
+		if (unlikely(aux->validator != v)) {
+			DMERR("validator mismatch (old=%s vs new=%s) for block %llu",
+				aux->validator->name, v ? v->name : "NULL",
+				(unsigned long long)
+					dm_bufio_get_block_number(buf));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read(&aux->lock);
+	if (unlikely(r)) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_read_lock);
+
+int dm_bm_write_lock(struct dm_block_manager *bm,
+		     dm_block_t b, struct dm_block_validator *v,
+		     struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 1;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_write(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_write_lock);
+
+int dm_bm_read_try_lock(struct dm_block_manager *bm,
+			dm_block_t b, struct dm_block_validator *v,
+			struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+	if (unlikely(!p))
+		return -EWOULDBLOCK;
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read_nonblock(&aux->lock);
+	if (r < 0) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+
+int dm_bm_write_lock_zero(struct dm_block_manager *bm,
+			  dm_block_t b, struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	struct buffer_aux *aux;
+	void *p;
+
+	p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	memset(p, 0, dm_bm_block_size(bm));
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	aux->write_locked = 1;
+	aux->validator = v;
+
+	return 0;
+}
+
+int dm_bm_unlock(struct dm_block *b)
+{
+	struct buffer_aux *aux;
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release(to_buffer(b));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_unlock);
+
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n)
+{
+	struct buffer_aux *aux;
+
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release_move(to_buffer(b), n);
+	return 0;
+}
+
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock)
+{
+	int r;
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	dm_bm_unlock(superblock);
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	return 0;
+}
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
+{
+	return crc32c(~(u32) 0, data, len) ^ init_xor;
+}
+EXPORT_SYMBOL_GPL(dm_bm_checksum);
+
+/*----------------------------------------------------------------*/
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_DESCRIPTION("Immutable metadata library for dm");
+
+/*----------------------------------------------------------------*/
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-block-manager.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-block-manager.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-block-manager.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-block-manager.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_BLOCK_MANAGER_H
+#define _LINUX_DM_BLOCK_MANAGER_H
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block number.
+ */
+typedef uint64_t dm_block_t;
+struct dm_block;
+
+dm_block_t dm_block_location(struct dm_block *b);
+void *dm_block_data(struct dm_block *b);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * @name should be a unique identifier for the block manager, no longer
+ * than 32 chars.
+ *
+ * @max_held_per_thread should be the maximum number of locks, read or
+ * write, that an individual thread holds at any one time.
+ */
+struct dm_block_manager;
+struct dm_block_manager *dm_block_manager_create(
+	struct block_device *bdev, unsigned block_size,
+	unsigned cache_size, unsigned max_held_per_thread);
+void dm_block_manager_destroy(struct dm_block_manager *bm);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm);
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * The validator allows the caller to verify newly-read data and modify
+ * the data just before writing, e.g. to calculate checksums.  It's
+ * important to be consistent with your use of validators.  The only time
+ * you can change validators is if you call dm_bm_write_lock_zero.
+ */
+struct dm_block_validator {
+	const char *name;
+	void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+
+	/*
+	 * Return 0 if the checksum is valid or < 0 on error.
+	 */
+	int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * You can have multiple concurrent readers or a single writer holding a
+ * block lock.
+ */
+
+/*
+ * dm_bm_lock() locks a block and returns through @result a pointer to
+ * memory that holds a copy of that block.  If you have write-locked the
+ * block then any changes you make to memory pointed to by @result will be
+ * written back to the disk sometime after dm_bm_unlock is called.
+ */
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b,
+		     struct dm_block_validator *v,
+		     struct dm_block **result);
+
+/*
+ * The *_try_lock variants return -EWOULDBLOCK if the block isn't
+ * available immediately.
+ */
+int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b,
+			struct dm_block_validator *v,
+			struct dm_block **result);
+
+/*
+ * Use dm_bm_write_lock_zero() when you know you're going to
+ * overwrite the block completely.  It saves a disk read.
+ */
+int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
+			  struct dm_block_validator *v,
+			  struct dm_block **result);
+
+int dm_bm_unlock(struct dm_block *b);
+
+/*
+ * An optimisation; we often want to copy a block's contents to a new
+ * block.  eg, as part of the shadowing operation.  It's far better for
+ * bufio to do this move behind the scenes than hold 2 locks and memcpy the
+ * data.
+ */
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n);
+
+/*
+ * It's a common idiom to have a superblock that should be committed last.
+ *
+ * @superblock should be write-locked on entry. It will be unlocked during
+ * this function.  All dirty blocks are guaranteed to be written and flushed
+ * before the superblock.
+ *
+ * This method always blocks.
+ */
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock);
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* _LINUX_DM_BLOCK_MANAGER_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,805 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/export.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree"
+
+/*----------------------------------------------------------------
+ * Array manipulation
+ *--------------------------------------------------------------*/
+static void memcpy_disk(void *dest, const void *src, size_t len)
+	__dm_written_to_disk(src)
+{
+	memcpy(dest, src, len);
+	__dm_unbless_for_disk(src);
+}
+
+static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
+			 unsigned index, void *elt)
+	__dm_written_to_disk(elt)
+{
+	if (index < nr_elts)
+		memmove(base + (elt_size * (index + 1)),
+			base + (elt_size * index),
+			(nr_elts - index) * elt_size);
+
+	memcpy_disk(base + (elt_size * index), elt, elt_size);
+}
+
+/*----------------------------------------------------------------*/
+
+/* makes the assumption that no two keys are the same. */
+static int bsearch(struct node *n, uint64_t key, int want_hi)
+{
+	int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
+
+	while (hi - lo > 1) {
+		int mid = lo + ((hi - lo) / 2);
+		uint64_t mid_key = le64_to_cpu(n->keys[mid]);
+
+		if (mid_key == key)
+			return mid;
+
+		if (mid_key < key)
+			lo = mid;
+		else
+			hi = mid;
+	}
+
+	return want_hi ? hi : lo;
+}
+
+int lower_bound(struct node *n, uint64_t key)
+{
+	return bsearch(n, key, 0);
+}
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt)
+{
+	unsigned i;
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+
+	if (le32_to_cpu(n->header.flags) & INTERNAL_NODE)
+		for (i = 0; i < nr_entries; i++)
+			dm_tm_inc(tm, value64(n, i));
+	else if (vt->inc)
+		for (i = 0; i < nr_entries; i++)
+			vt->inc(vt->context,
+				value_ptr(n, i, vt->size));
+}
+
+static int insert_at(size_t value_size, struct node *node, unsigned index,
+		      uint64_t key, void *value)
+		      __dm_written_to_disk(value)
+{
+	uint32_t nr_entries = le32_to_cpu(node->header.nr_entries);
+	__le64 key_le = cpu_to_le64(key);
+
+	if (index > nr_entries ||
+	    index >= le32_to_cpu(node->header.max_entries)) {
+		DMERR("too many entries in btree node for insert");
+		__dm_unbless_for_disk(value);
+		return -ENOMEM;
+	}
+
+	__dm_bless_for_disk(&key_le);
+
+	array_insert(node->keys, sizeof(*node->keys), nr_entries, index, &key_le);
+	array_insert(value_base(node), value_size, nr_entries, index, value);
+	node->header.nr_entries = cpu_to_le32(nr_entries + 1);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We want 3n entries (for some n).  This works more nicely for repeated
+ * insert remove loops than (2n + 1).
+ */
+static uint32_t calc_max_entries(size_t value_size, size_t block_size)
+{
+	uint32_t total, n;
+	size_t elt_size = sizeof(uint64_t) + value_size; /* key + value */
+
+	block_size -= sizeof(struct node_header);
+	total = block_size / elt_size;
+	n = total / 3;		/* rounds down */
+
+	return 3 * n;
+}
+
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
+{
+	int r;
+	struct dm_block *b;
+	struct node *n;
+	size_t block_size;
+	uint32_t max_entries;
+
+	r = new_block(info, &b);
+	if (r < 0)
+		return r;
+
+	block_size = dm_bm_block_size(dm_tm_get_bm(info->tm));
+	max_entries = calc_max_entries(info->value_type.size, block_size);
+
+	n = dm_block_data(b);
+	memset(n, 0, block_size);
+	n->header.flags = cpu_to_le32(LEAF_NODE);
+	n->header.nr_entries = cpu_to_le32(0);
+	n->header.max_entries = cpu_to_le32(max_entries);
+	n->header.value_size = cpu_to_le32(info->value_type.size);
+
+	*root = dm_block_location(b);
+	return unlock_block(info, b);
+}
+EXPORT_SYMBOL_GPL(dm_btree_empty);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Deletion uses a recursive algorithm, since we have limited stack space
+ * we explicitly manage our own stack on the heap.
+ */
+#define MAX_SPINE_DEPTH 64
+struct frame {
+	struct dm_block *b;
+	struct node *n;
+	unsigned level;
+	unsigned nr_children;
+	unsigned current_child;
+};
+
+struct del_stack {
+	struct dm_transaction_manager *tm;
+	int top;
+	struct frame spine[MAX_SPINE_DEPTH];
+};
+
+static int top_frame(struct del_stack *s, struct frame **f)
+{
+	if (s->top < 0) {
+		DMERR("btree deletion stack empty");
+		return -EINVAL;
+	}
+
+	*f = s->spine + s->top;
+
+	return 0;
+}
+
+static int unprocessed_frames(struct del_stack *s)
+{
+	return s->top >= 0;
+}
+
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+{
+	int r;
+	uint32_t ref_count;
+
+	if (s->top >= MAX_SPINE_DEPTH - 1) {
+		DMERR("btree deletion stack out of memory");
+		return -ENOMEM;
+	}
+
+	r = dm_tm_ref(s->tm, b, &ref_count);
+	if (r)
+		return r;
+
+	if (ref_count > 1)
+		/*
+		 * This is a shared node, so we can just decrement it's
+		 * reference counter and leave the children.
+		 */
+		dm_tm_dec(s->tm, b);
+
+	else {
+		struct frame *f = s->spine + ++s->top;
+
+		r = dm_tm_read_lock(s->tm, b, &btree_node_validator, &f->b);
+		if (r) {
+			s->top--;
+			return r;
+		}
+
+		f->n = dm_block_data(f->b);
+		f->level = level;
+		f->nr_children = le32_to_cpu(f->n->header.nr_entries);
+		f->current_child = 0;
+	}
+
+	return 0;
+}
+
+static void pop_frame(struct del_stack *s)
+{
+	struct frame *f = s->spine + s->top--;
+
+	dm_tm_dec(s->tm, dm_block_location(f->b));
+	dm_tm_unlock(s->tm, f->b);
+}
+
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
+{
+	int r;
+	struct del_stack *s;
+
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	s->tm = info->tm;
+	s->top = -1;
+
+	r = push_frame(s, root, 1);
+	if (r)
+		goto out;
+
+	while (unprocessed_frames(s)) {
+		uint32_t flags;
+		struct frame *f;
+		dm_block_t b;
+
+		r = top_frame(s, &f);
+		if (r)
+			goto out;
+
+		if (f->current_child >= f->nr_children) {
+			pop_frame(s);
+			continue;
+		}
+
+		flags = le32_to_cpu(f->n->header.flags);
+		if (flags & INTERNAL_NODE) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level);
+			if (r)
+				goto out;
+
+		} else if (f->level != (info->levels - 1)) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level + 1);
+			if (r)
+				goto out;
+
+		} else {
+			if (info->value_type.dec) {
+				unsigned i;
+
+				for (i = 0; i < f->nr_children; i++)
+					info->value_type.dec(info->value_type.context,
+							     value_ptr(f->n, i, info->value_type.size));
+			}
+			f->current_child = f->nr_children;
+		}
+	}
+
+out:
+	kfree(s);
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_del);
+
+/*----------------------------------------------------------------*/
+
+static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
+			    int (*search_fn)(struct node *, uint64_t),
+			    uint64_t *result_key, void *v, size_t value_size)
+{
+	int i, r;
+	uint32_t flags, nr_entries;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		i = search_fn(ro_node(s), key);
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		nr_entries = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (i < 0 || i >= nr_entries)
+			return -ENODATA;
+
+		if (flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (!(flags & LEAF_NODE));
+
+	*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+	memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+
+	return 0;
+}
+
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le)
+{
+	unsigned level, last_level = info->levels - 1;
+	int r = -ENODATA;
+	uint64_t rkey;
+	__le64 internal_value_le;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		size_t size;
+		void *value_p;
+
+		if (level == last_level) {
+			value_p = value_le;
+			size = info->value_type.size;
+
+		} else {
+			value_p = &internal_value_le;
+			size = sizeof(uint64_t);
+		}
+
+		r = btree_lookup_raw(&spine, root, keys[level],
+				     lower_bound, &rkey,
+				     value_p, size);
+
+		if (!r) {
+			if (rkey != keys[level]) {
+				exit_ro_spine(&spine);
+				return -ENODATA;
+			}
+		} else {
+			exit_ro_spine(&spine);
+			return r;
+		}
+
+		root = le64_to_cpu(internal_value_le);
+	}
+	exit_ro_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_lookup);
+
+/*
+ * Splits a node by creating a sibling node and shifting half the nodes
+ * contents across.  Assumes there is a parent node, and it has room for
+ * another child.
+ *
+ * Before:
+ *	  +--------+
+ *	  | Parent |
+ *	  +--------+
+ *	     |
+ *	     v
+ *	+----------+
+ *	| A ++++++ |
+ *	+----------+
+ *
+ *
+ * After:
+ *		+--------+
+ *		| Parent |
+ *		+--------+
+ *		  |	|
+ *		  v	+------+
+ *	    +---------+	       |
+ *	    | A* +++  |	       v
+ *	    +---------+	  +-------+
+ *			  | B +++ |
+ *			  +-------+
+ *
+ * Where A* is a shadow of A.
+ */
+static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
+			       unsigned parent_index, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *parent;
+	struct node *ln, *rn, *pn;
+	__le64 location;
+
+	left = shadow_current(s);
+
+	r = new_block(s->info, &right);
+	if (r < 0)
+		return r;
+
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(ln->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(ln->header.nr_entries) - nr_left;
+
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+
+	rn->header.flags = ln->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = ln->header.max_entries;
+	rn->header.value_size = ln->header.value_size;
+	memcpy(rn->keys, ln->keys + nr_left, nr_right * sizeof(rn->keys[0]));
+
+	size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
+		sizeof(uint64_t) : s->info->value_type.size;
+	memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+	       size * nr_right);
+
+	/*
+	 * Patch up the parent
+	 */
+	parent = shadow_parent(s);
+
+	pn = dm_block_data(parent);
+	location = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&location);
+	memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+		    &location, sizeof(__le64));
+
+	location = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&location);
+
+	r = insert_at(sizeof(__le64), pn, parent_index + 1,
+		      le64_to_cpu(rn->keys[0]), &location);
+	if (r)
+		return r;
+
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+
+	return 0;
+}
+
+/*
+ * Splits a node by creating two new children beneath the given node.
+ *
+ * Before:
+ *	  +----------+
+ *	  | A ++++++ |
+ *	  +----------+
+ *
+ *
+ * After:
+ *	+------------+
+ *	| A (shadow) |
+ *	+------------+
+ *	    |	|
+ *   +------+	+----+
+ *   |		     |
+ *   v		     v
+ * +-------+	 +-------+
+ * | B +++ |	 | C +++ |
+ * +-------+	 +-------+
+ */
+static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *new_parent;
+	struct node *pn, *ln, *rn;
+	__le64 val;
+
+	new_parent = shadow_current(s);
+
+	r = new_block(s->info, &left);
+	if (r < 0)
+		return r;
+
+	r = new_block(s->info, &right);
+	if (r < 0) {
+		/* FIXME: put left */
+		return r;
+	}
+
+	pn = dm_block_data(new_parent);
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
+
+	ln->header.flags = pn->header.flags;
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+	ln->header.max_entries = pn->header.max_entries;
+	ln->header.value_size = pn->header.value_size;
+
+	rn->header.flags = pn->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = pn->header.max_entries;
+	rn->header.value_size = pn->header.value_size;
+
+	memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+	memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
+
+	size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+		sizeof(__le64) : s->info->value_type.size;
+	memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
+	memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+	       nr_right * size);
+
+	/* new_parent should just point to l and r now */
+	pn->header.flags = cpu_to_le32(INTERNAL_NODE);
+	pn->header.nr_entries = cpu_to_le32(2);
+	pn->header.max_entries = cpu_to_le32(
+		calc_max_entries(sizeof(__le64),
+				 dm_bm_block_size(
+					 dm_tm_get_bm(s->info->tm))));
+	pn->header.value_size = cpu_to_le32(sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&val);
+	pn->keys[0] = ln->keys[0];
+	memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&val);
+	pn->keys[1] = rn->keys[0];
+	memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+
+	/*
+	 * rejig the spine.  This is ugly, since it knows too
+	 * much about the spine
+	 */
+	if (s->nodes[0] != new_parent) {
+		unlock_block(s->info, s->nodes[0]);
+		s->nodes[0] = new_parent;
+	}
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+	s->count = 2;
+
+	return 0;
+}
+
+static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
+			    struct dm_btree_value_type *vt,
+			    uint64_t key, unsigned *index)
+{
+	int r, i = *index, top = 1;
+	struct node *node;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			return r;
+
+		node = dm_block_data(shadow_current(s));
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s) && i >= 0) { /* FIXME: second clause unness. */
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+
+			__dm_bless_for_disk(&location);
+			memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+				    &location, sizeof(__le64));
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		if (node->header.nr_entries == node->header.max_entries) {
+			if (top)
+				r = btree_split_beneath(s, key);
+			else
+				r = btree_split_sibling(s, root, i, key);
+
+			if (r < 0)
+				return r;
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		i = lower_bound(node, key);
+
+		if (le32_to_cpu(node->header.flags) & LEAF_NODE)
+			break;
+
+		if (i < 0) {
+			/* change the bounds on the lowest key */
+			node->keys[0] = cpu_to_le64(key);
+			i = 0;
+		}
+
+		root = value64(node, i);
+		top = 0;
+	}
+
+	if (i < 0 || le64_to_cpu(node->keys[i]) != key)
+		i++;
+
+	*index = i;
+	return 0;
+}
+
+static int insert(struct dm_btree_info *info, dm_block_t root,
+		  uint64_t *keys, void *value, dm_block_t *new_root,
+		  int *inserted)
+		  __dm_written_to_disk(value)
+{
+	int r, need_insert;
+	unsigned level, index = -1, last_level = info->levels - 1;
+	dm_block_t block = root;
+	struct shadow_spine spine;
+	struct node *n;
+	struct dm_btree_value_type le64_type;
+
+	le64_type.context = NULL;
+	le64_type.size = sizeof(__le64);
+	le64_type.inc = NULL;
+	le64_type.dec = NULL;
+	le64_type.equal = NULL;
+
+	init_shadow_spine(&spine, info);
+
+	for (level = 0; level < (info->levels - 1); level++) {
+		r = btree_insert_raw(&spine, block, &le64_type, keys[level], &index);
+		if (r < 0)
+			goto bad;
+
+		n = dm_block_data(shadow_current(&spine));
+		need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+			       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+		if (need_insert) {
+			dm_block_t new_tree;
+			__le64 new_le;
+
+			r = dm_btree_empty(info, &new_tree);
+			if (r < 0)
+				goto bad;
+
+			new_le = cpu_to_le64(new_tree);
+			__dm_bless_for_disk(&new_le);
+
+			r = insert_at(sizeof(uint64_t), n, index,
+				      keys[level], &new_le);
+			if (r)
+				goto bad;
+		}
+
+		if (level < last_level)
+			block = value64(n, index);
+	}
+
+	r = btree_insert_raw(&spine, block, &info->value_type,
+			     keys[level], &index);
+	if (r < 0)
+		goto bad;
+
+	n = dm_block_data(shadow_current(&spine));
+	need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+		       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+	if (need_insert) {
+		if (inserted)
+			*inserted = 1;
+
+		r = insert_at(info->value_type.size, n, index,
+			      keys[level], value);
+		if (r)
+			goto bad_unblessed;
+	} else {
+		if (inserted)
+			*inserted = 0;
+
+		if (info->value_type.dec &&
+		    (!info->value_type.equal ||
+		     !info->value_type.equal(
+			     info->value_type.context,
+			     value_ptr(n, index, info->value_type.size),
+			     value))) {
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+		}
+		memcpy_disk(value_ptr(n, index, info->value_type.size),
+			    value, info->value_type.size);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return 0;
+
+bad:
+	__dm_unbless_for_disk(value);
+bad_unblessed:
+	exit_shadow_spine(&spine);
+	return r;
+}
+
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert);
+
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, inserted);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert_notify);
+
+/*----------------------------------------------------------------*/
+
+static int find_highest_key(struct ro_spine *s, dm_block_t block,
+			    uint64_t *result_key, dm_block_t *next_block)
+{
+	int i, r;
+	uint32_t flags;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		i = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (!i)
+			return -ENODATA;
+		else
+			i--;
+
+		*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+		if (next_block || flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (flags & INTERNAL_NODE);
+
+	if (next_block)
+		*next_block = block;
+	return 0;
+}
+
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys)
+{
+	int r = 0, count = 0, level;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = find_highest_key(&spine, root, result_keys + level,
+				     level == info->levels - 1 ? NULL : &root);
+		if (r == -ENODATA) {
+			r = 0;
+			break;
+
+		} else if (r)
+			break;
+
+		count++;
+	}
+	exit_ro_spine(&spine);
+
+	return r ? r : count;
+}
+EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#ifndef _LINUX_DM_BTREE_H
+#define _LINUX_DM_BTREE_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Annotations used to check on-disk metadata is handled as little-endian.
+ */
+#ifdef __CHECKER__
+#  define __dm_written_to_disk(x) __releases(x)
+#  define __dm_reads_from_disk(x) __acquires(x)
+#  define __dm_bless_for_disk(x) __acquire(x)
+#  define __dm_unbless_for_disk(x) __release(x)
+#else
+#  define __dm_written_to_disk(x)
+#  define __dm_reads_from_disk(x)
+#  define __dm_bless_for_disk(x)
+#  define __dm_unbless_for_disk(x)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Manipulates hierarchical B+ trees with 64-bit keys and arbitrary-sized
+ * values.
+ */
+
+/*
+ * Infomation about the values stored within the btree.
+ */
+struct dm_btree_value_type {
+	void *context;
+
+	/*
+	 * The size in bytes of each value.
+	 */
+	uint32_t size;
+
+	/*
+	 * Any of these methods can be safely set to NULL if you do not
+	 * need the corresponding feature.
+	 */
+
+	/*
+	 * The btree is making a duplicate of the value, for instance
+	 * because previously-shared btree nodes have now diverged.
+	 * @value argument is the new copy that the copy function may modify.
+	 * (Probably it just wants to increment a reference count
+	 * somewhere.) This method is _not_ called for insertion of a new
+	 * value: It is assumed the ref count is already 1.
+	 */
+	void (*inc)(void *context, void *value);
+
+	/*
+	 * This value is being deleted.  The btree takes care of freeing
+	 * the memory pointed to by @value.  Often the del function just
+	 * needs to decrement a reference count somewhere.
+	 */
+	void (*dec)(void *context, void *value);
+
+	/*
+	 * A test for equality between two values.  When a value is
+	 * overwritten with a new one, the old one has the dec method
+	 * called _unless_ the new and old value are deemed equal.
+	 */
+	int (*equal)(void *context, void *value1, void *value2);
+};
+
+/*
+ * The shape and contents of a btree.
+ */
+struct dm_btree_info {
+	struct dm_transaction_manager *tm;
+
+	/*
+	 * Number of nested btrees. (Not the depth of a single tree.)
+	 */
+	unsigned levels;
+	struct dm_btree_value_type value_type;
+};
+
+/*
+ * Set up an empty tree.  O(1).
+ */
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root);
+
+/*
+ * Delete a tree.  O(n) - this is the slow one!  It can also block, so
+ * please don't call it on an IO path.
+ */
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root);
+
+/*
+ * All the lookup functions return -ENODATA if the key cannot be found.
+ */
+
+/*
+ * Tries to find a key that matches exactly.  O(ln(n))
+ */
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le);
+
+/*
+ * Insertion (or overwrite an existing value).  O(ln(n))
+ */
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value);
+
+/*
+ * A variant of insert that indicates whether it actually inserted or just
+ * overwrote.  Useful if you're keeping track of the number of entries in a
+ * tree.
+ */
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value);
+
+/*
+ * Remove a key if present.  This doesn't remove empty sub trees.  Normally
+ * subtrees represent a separate entity, like a snapshot map, so this is
+ * correct behaviour.  O(ln(n)).
+ */
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root);
+
+/*
+ * Returns < 0 on failure.  Otherwise the number of key entries that have
+ * been filled out.  Remember trees can have zero entries, and as such have
+ * no highest key.
+ */
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys);
+
+#endif	/* _LINUX_DM_BTREE_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-internal.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-internal.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BTREE_INTERNAL_H
+#define DM_BTREE_INTERNAL_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We'll need 2 accessor functions for n->csum and n->blocknr
+ * to support dm-btree-spine.c in that case.
+ */
+
+enum node_flags {
+	INTERNAL_NODE = 1,
+	LEAF_NODE = 1 << 1
+};
+
+/*
+ * Every btree node begins with this structure.  Make sure it's a multiple
+ * of 8-bytes in size, otherwise the 64bit keys will be mis-aligned.
+ */
+struct node_header {
+	__le32 csum;
+	__le32 flags;
+	__le64 blocknr; /* Block this node is supposed to live in. */
+
+	__le32 nr_entries;
+	__le32 max_entries;
+	__le32 value_size;
+	__le32 padding;
+} __packed;
+
+struct node {
+	struct node_header header;
+	__le64 keys[0];
+} __packed;
+
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt);
+
+int new_block(struct dm_btree_info *info, struct dm_block **result);
+int unlock_block(struct dm_btree_info *info, struct dm_block *b);
+
+/*
+ * Spines keep track of the rolling locks.  There are 2 variants, read-only
+ * and one that uses shadowing.  These are separate structs to allow the
+ * type checker to spot misuse, for example accidentally calling read_lock
+ * on a shadow spine.
+ */
+struct ro_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+};
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
+int exit_ro_spine(struct ro_spine *s);
+int ro_step(struct ro_spine *s, dm_block_t new_child);
+struct node *ro_node(struct ro_spine *s);
+
+struct shadow_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+
+	dm_block_t root;
+};
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info);
+int exit_shadow_spine(struct shadow_spine *s);
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt);
+
+/*
+ * The spine must have at least one entry before calling this.
+ */
+struct dm_block *shadow_current(struct shadow_spine *s);
+
+/*
+ * The spine must have at least two entries before calling this.
+ */
+struct dm_block *shadow_parent(struct shadow_spine *s);
+
+int shadow_has_parent(struct shadow_spine *s);
+
+int shadow_root(struct shadow_spine *s);
+
+/*
+ * Some inlines.
+ */
+static inline __le64 *key_ptr(struct node *n, uint32_t index)
+{
+	return n->keys + index;
+}
+
+static inline void *value_base(struct node *n)
+{
+	return &n->keys[le32_to_cpu(n->header.max_entries)];
+}
+
+/*
+ * FIXME: Now that value size is stored in node we don't need the third parm.
+ */
+static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+{
+	BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+	return value_base(n) + (value_size * index);
+}
+
+/*
+ * Assumes the values are suitably-aligned and converts to core format.
+ */
+static inline uint64_t value64(struct node *n, uint32_t index)
+{
+	__le64 *values_le = value_base(n);
+
+	return le64_to_cpu(values_le[index]);
+}
+
+/*
+ * Searching for a key within a single node.
+ */
+int lower_bound(struct node *n, uint64_t key);
+
+extern struct dm_block_validator btree_node_validator;
+
+#endif	/* DM_BTREE_INTERNAL_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-remove.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-remove.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-remove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-remove.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree.h"
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/export.h>
+
+/*
+ * Removing an entry from a btree
+ * ==============================
+ *
+ * A very important constraint for our btree is that no node, except the
+ * root, may have fewer than a certain number of entries.
+ * (MIN_ENTRIES <= nr_entries <= MAX_ENTRIES).
+ *
+ * Ensuring this is complicated by the way we want to only ever hold the
+ * locks on 2 nodes concurrently, and only change nodes in a top to bottom
+ * fashion.
+ *
+ * Each node may have a left or right sibling.  When decending the spine,
+ * if a node contains only MIN_ENTRIES then we try and increase this to at
+ * least MIN_ENTRIES + 1.  We do this in the following ways:
+ *
+ * [A] No siblings => this can only happen if the node is the root, in which
+ *     case we copy the childs contents over the root.
+ *
+ * [B] No left sibling
+ *     ==> rebalance(node, right sibling)
+ *
+ * [C] No right sibling
+ *     ==> rebalance(left sibling, node)
+ *
+ * [D] Both siblings, total_entries(left, node, right) <= DEL_THRESHOLD
+ *     ==> delete node adding it's contents to left and right
+ *
+ * [E] Both siblings, total_entries(left, node, right) > DEL_THRESHOLD
+ *     ==> rebalance(left, node, right)
+ *
+ * After these operations it's possible that the our original node no
+ * longer contains the desired sub tree.  For this reason this rebalancing
+ * is performed on the children of the current node.  This also avoids
+ * having a special case for the root.
+ *
+ * Once this rebalancing has occurred we can then step into the child node
+ * for internal nodes.  Or delete the entry for leaf nodes.
+ */
+
+/*
+ * Some little utilities for moving node data around.
+ */
+static void node_shift(struct node *n, int shift)
+{
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(shift > nr_entries);
+		BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+		memmove(key_ptr(n, 0),
+			key_ptr(n, shift),
+			(nr_entries - shift) * sizeof(__le64));
+		memmove(value_ptr(n, 0, value_size),
+			value_ptr(n, shift, value_size),
+			(nr_entries - shift) * value_size);
+	} else {
+		BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
+		memmove(key_ptr(n, shift),
+			key_ptr(n, 0),
+			nr_entries * sizeof(__le64));
+		memmove(value_ptr(n, shift, value_size),
+			value_ptr(n, 0, value_size),
+			nr_entries * value_size);
+	}
+}
+
+static void node_copy(struct node *left, struct node *right, int shift)
+{
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(left->header.value_size);
+	BUG_ON(value_size != le32_to_cpu(right->header.value_size));
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(nr_left + shift > le32_to_cpu(left->header.max_entries));
+		memcpy(key_ptr(left, nr_left),
+		       key_ptr(right, 0),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(left, nr_left, value_size),
+		       value_ptr(right, 0, value_size),
+		       shift * value_size);
+	} else {
+		BUG_ON(shift > le32_to_cpu(right->header.max_entries));
+		memcpy(key_ptr(right, 0),
+		       key_ptr(left, nr_left - shift),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(right, 0, value_size),
+		       value_ptr(left, nr_left - shift, value_size),
+		       shift * value_size);
+	}
+}
+
+/*
+ * Delete a specific entry from a leaf node.
+ */
+static void delete_at(struct node *n, unsigned index)
+{
+	unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
+	unsigned nr_to_copy = nr_entries - (index + 1);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+	BUG_ON(index >= nr_entries);
+
+	if (nr_to_copy) {
+		memmove(key_ptr(n, index),
+			key_ptr(n, index + 1),
+			nr_to_copy * sizeof(__le64));
+
+		memmove(value_ptr(n, index, value_size),
+			value_ptr(n, index + 1, value_size),
+			nr_to_copy * value_size);
+	}
+
+	n->header.nr_entries = cpu_to_le32(nr_entries - 1);
+}
+
+static unsigned del_threshold(struct node *n)
+{
+	return le32_to_cpu(n->header.max_entries) / 3;
+}
+
+static unsigned merge_threshold(struct node *n)
+{
+	/*
+	 * The extra one is because we know we're potentially going to
+	 * delete an entry.
+	 */
+	return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+}
+
+struct child {
+	unsigned index;
+	struct dm_block *block;
+	struct node *n;
+};
+
+static struct dm_btree_value_type le64_type = {
+	.context = NULL,
+	.size = sizeof(__le64),
+	.inc = NULL,
+	.dec = NULL,
+	.equal = NULL
+};
+
+static int init_child(struct dm_btree_info *info, struct node *parent,
+		      unsigned index, struct child *result)
+{
+	int r, inc;
+	dm_block_t root;
+
+	result->index = index;
+	root = value64(parent, index);
+
+	r = dm_tm_shadow_block(info->tm, root, &btree_node_validator,
+			       &result->block, &inc);
+	if (r)
+		return r;
+
+	result->n = dm_block_data(result->block);
+
+	if (inc)
+		inc_children(info->tm, result->n, &le64_type);
+
+	*((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+		cpu_to_le64(dm_block_location(result->block));
+
+	return 0;
+}
+
+static int exit_child(struct dm_btree_info *info, struct child *c)
+{
+	return dm_tm_unlock(info->tm, c->block);
+}
+
+static void shift(struct node *left, struct node *right, int count)
+{
+	if (!count)
+		return;
+
+	if (count > 0) {
+		node_shift(right, count);
+		node_copy(left, right, count);
+	} else {
+		node_copy(left, right, count);
+		node_shift(right, count);
+	}
+
+	left->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
+	BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
+
+	right->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
+	BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+}
+
+static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *right = r->n;
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+
+	if (nr_left + nr_right <= merge_threshold(left)) {
+		/*
+		 * Merge
+		 */
+		node_copy(left, right, -nr_right);
+		left->header.nr_entries = cpu_to_le32(nr_left + nr_right);
+		delete_at(parent, r->index);
+
+		/*
+		 * We need to decrement the right block, but not it's
+		 * children, since they're still referenced by left.
+		 */
+		dm_tm_dec(info->tm, dm_block_location(r->block));
+	} else {
+		/*
+		 * Rebalance.
+		 */
+		unsigned target_left = (nr_left + nr_right) / 2;
+		unsigned shift_ = nr_left - target_left;
+		BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
+		BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
+		shift(left, right, nr_left - target_left);
+		*key_ptr(parent, r->index) = right->keys[0];
+	}
+}
+
+static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent;
+	struct child left, right;
+
+	parent = dm_block_data(shadow_current(s));
+
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &right);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	__rebalance2(info, parent, &left, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	return exit_child(info, &right);
+}
+
+static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *c, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *center = c->n;
+	struct node *right = r->n;
+
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+
+	unsigned target;
+
+	BUG_ON(left->header.max_entries != center->header.max_entries);
+	BUG_ON(center->header.max_entries != right->header.max_entries);
+
+	if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
+		/*
+		 * Delete center node:
+		 *
+		 * We dump as many entries from center as possible into
+		 * left, then the rest in right, then rebalance2.  This
+		 * wastes some cpu, but I want something simple atm.
+		 */
+		unsigned shift = min(max_entries - nr_left, nr_center);
+
+		BUG_ON(nr_left + shift > max_entries);
+		node_copy(left, center, -shift);
+		left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+		if (shift != nr_center) {
+			shift = nr_center - shift;
+			BUG_ON((nr_right + shift) >= max_entries);
+			node_shift(right, shift);
+			node_copy(center, right, shift);
+			right->header.nr_entries = cpu_to_le32(nr_right + shift);
+		}
+		*key_ptr(parent, r->index) = right->keys[0];
+
+		delete_at(parent, c->index);
+		r->index--;
+
+		dm_tm_dec(info->tm, dm_block_location(c->block));
+		__rebalance2(info, parent, l, r);
+
+		return;
+	}
+
+	/*
+	 * Rebalance
+	 */
+	target = (nr_left + nr_center + nr_right) / 3;
+	BUG_ON(target > max_entries);
+
+	/*
+	 * Adjust the left node
+	 */
+	shift(left, center, nr_left - target);
+
+	/*
+	 * Adjust the right node
+	 */
+	shift(center, right, target - nr_right);
+	*key_ptr(parent, c->index) = center->keys[0];
+	*key_ptr(parent, r->index) = right->keys[0];
+}
+
+static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent = dm_block_data(shadow_current(s));
+	struct child left, center, right;
+
+	/*
+	 * FIXME: fill out an array?
+	 */
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &center);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	r = init_child(info, parent, left_index + 2, &right);
+	if (r) {
+		exit_child(info, &left);
+		exit_child(info, &center);
+		return r;
+	}
+
+	__rebalance3(info, parent, &left, &center, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &center);
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &center);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &right);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int get_nr_entries(struct dm_transaction_manager *tm,
+			  dm_block_t b, uint32_t *result)
+{
+	int r;
+	struct dm_block *block;
+	struct node *n;
+
+	r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
+	if (r)
+		return r;
+
+	n = dm_block_data(block);
+	*result = le32_to_cpu(n->header.nr_entries);
+
+	return dm_tm_unlock(tm, block);
+}
+
+static int rebalance_children(struct shadow_spine *s,
+			      struct dm_btree_info *info, uint64_t key)
+{
+	int i, r, has_left_sibling, has_right_sibling;
+	uint32_t child_entries;
+	struct node *n;
+
+	n = dm_block_data(shadow_current(s));
+
+	if (le32_to_cpu(n->header.nr_entries) == 1) {
+		struct dm_block *child;
+		dm_block_t b = value64(n, 0);
+
+		r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
+		if (r)
+			return r;
+
+		memcpy(n, dm_block_data(child),
+		       dm_bm_block_size(dm_tm_get_bm(info->tm)));
+		r = dm_tm_unlock(info->tm, child);
+		if (r)
+			return r;
+
+		dm_tm_dec(info->tm, dm_block_location(child));
+		return 0;
+	}
+
+	i = lower_bound(n, key);
+	if (i < 0)
+		return -ENODATA;
+
+	r = get_nr_entries(info->tm, value64(n, i), &child_entries);
+	if (r)
+		return r;
+
+	if (child_entries > del_threshold(n))
+		return 0;
+
+	has_left_sibling = i > 0;
+	has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
+
+	if (!has_left_sibling)
+		r = rebalance2(s, info, i);
+
+	else if (!has_right_sibling)
+		r = rebalance2(s, info, i - 1);
+
+	else
+		r = rebalance3(s, info, i - 1);
+
+	return r;
+}
+
+static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+{
+	int i = lower_bound(n, key);
+
+	if ((i < 0) ||
+	    (i >= le32_to_cpu(n->header.nr_entries)) ||
+	    (le64_to_cpu(n->keys[i]) != key))
+		return -ENODATA;
+
+	*index = i;
+
+	return 0;
+}
+
+/*
+ * Prepares for removal from one level of the hierarchy.  The caller must
+ * call delete_at() to remove the entry at index.
+ */
+static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
+		      struct dm_btree_value_type *vt, dm_block_t root,
+		      uint64_t key, unsigned *index)
+{
+	int i = *index, r;
+	struct node *n;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			break;
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s)) {
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+			memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+			       &location, sizeof(__le64));
+		}
+
+		n = dm_block_data(shadow_current(s));
+
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		r = rebalance_children(s, info, key);
+		if (r)
+			break;
+
+		n = dm_block_data(shadow_current(s));
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		i = lower_bound(n, key);
+
+		/*
+		 * We know the key is present, or else
+		 * rebalance_children would have returned
+		 * -ENODATA
+		 */
+		root = value64(n, i);
+	}
+
+	return r;
+}
+
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root)
+{
+	unsigned level, last_level = info->levels - 1;
+	int index = 0, r = 0;
+	struct shadow_spine spine;
+	struct node *n;
+
+	init_shadow_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = remove_raw(&spine, info,
+			       (level == last_level ?
+				&info->value_type : &le64_type),
+			       root, keys[level], (unsigned *)&index);
+		if (r < 0)
+			break;
+
+		n = dm_block_data(shadow_current(&spine));
+		if (level != last_level) {
+			root = value64(n, index);
+			continue;
+		}
+
+		BUG_ON(index < 0 || index >= le32_to_cpu(n->header.nr_entries));
+
+		if (info->value_type.dec)
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+
+		delete_at(n, index);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_remove);
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-spine.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-spine.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-btree-spine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-btree-spine.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree spine"
+
+/*----------------------------------------------------------------*/
+
+#define BTREE_CSUM_XOR 121107
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size);
+
+static void node_prepare_for_write(struct dm_block_validator *v,
+				   struct dm_block *b,
+				   size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+
+	h->blocknr = cpu_to_le64(dm_block_location(b));
+	h->csum = cpu_to_le32(dm_bm_checksum(&h->flags,
+					     block_size - sizeof(__le32),
+					     BTREE_CSUM_XOR));
+
+	BUG_ON(node_check(v, b, 4096));
+}
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+	size_t value_size;
+	__le32 csum_disk;
+	uint32_t flags;
+
+	if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
+		DMERR("node_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(h->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&h->flags,
+					       block_size - sizeof(__le32),
+					       BTREE_CSUM_XOR));
+	if (csum_disk != h->csum) {
+		DMERR("node_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
+		return -EILSEQ;
+	}
+
+	value_size = le32_to_cpu(h->value_size);
+
+	if (sizeof(struct node_header) +
+	    (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
+		DMERR("node_check failed: max_entries too large");
+		return -EILSEQ;
+	}
+
+	if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
+		DMERR("node_check failed, too many entries");
+		return -EILSEQ;
+	}
+
+	/*
+	 * The node must be either INTERNAL or LEAF.
+	 */
+	flags = le32_to_cpu(h->flags);
+	if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
+		DMERR("node_check failed, node is neither INTERNAL or LEAF");
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+struct dm_block_validator btree_node_validator = {
+	.name = "btree_node",
+	.prepare_for_write = node_prepare_for_write,
+	.check = node_check
+};
+
+/*----------------------------------------------------------------*/
+
+static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+		 struct dm_block **result)
+{
+	return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
+}
+
+static int bn_shadow(struct dm_btree_info *info, dm_block_t orig,
+	      struct dm_btree_value_type *vt,
+	      struct dm_block **result)
+{
+	int r, inc;
+
+	r = dm_tm_shadow_block(info->tm, orig, &btree_node_validator,
+			       result, &inc);
+	if (!r && inc)
+		inc_children(info->tm, dm_block_data(*result), vt);
+
+	return r;
+}
+
+int new_block(struct dm_btree_info *info, struct dm_block **result)
+{
+	return dm_tm_new_block(info->tm, &btree_node_validator, result);
+}
+
+int unlock_block(struct dm_btree_info *info, struct dm_block *b)
+{
+	return dm_tm_unlock(info->tm, b);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+	s->nodes[0] = NULL;
+	s->nodes[1] = NULL;
+}
+
+int exit_ro_spine(struct ro_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int ro_step(struct ro_spine *s, dm_block_t new_child)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_read_lock(s->info, new_child, s->nodes + s->count);
+	if (!r)
+		s->count++;
+
+	return r;
+}
+
+struct node *ro_node(struct ro_spine *s)
+{
+	struct dm_block *block;
+
+	BUG_ON(!s->count);
+	block = s->nodes[s->count - 1];
+
+	return dm_block_data(block);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+}
+
+int exit_shadow_spine(struct shadow_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_shadow(s->info, b, vt, s->nodes + s->count);
+	if (!r) {
+		if (!s->count)
+			s->root = dm_block_location(s->nodes[0]);
+
+		s->count++;
+	}
+
+	return r;
+}
+
+struct dm_block *shadow_current(struct shadow_spine *s)
+{
+	BUG_ON(!s->count);
+
+	return s->nodes[s->count - 1];
+}
+
+struct dm_block *shadow_parent(struct shadow_spine *s)
+{
+	BUG_ON(s->count != 2);
+
+	return s->count == 2 ? s->nodes[0] : NULL;
+}
+
+int shadow_has_parent(struct shadow_spine *s)
+{
+	return s->count >= 2;
+}
+
+int shadow_root(struct shadow_spine *s)
+{
+	return s->root;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-persistent-data-internal.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-persistent-data-internal.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-persistent-data-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-persistent-data-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_PERSISTENT_DATA_INTERNAL_H
+#define _DM_PERSISTENT_DATA_INTERNAL_H
+
+#include "dm-block-manager.h"
+
+static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+{
+	const unsigned BIG_PRIME = 4294967291UL;
+
+	return (((unsigned) b) * BIG_PRIME) & hash_mask;
+}
+
+#endif	/* _PERSISTENT_DATA_INTERNAL_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-checker.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-checker.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-checker.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-checker.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+
+#include <linux/device-mapper.h>
+#include <linux/export.h>
+
+#ifdef CONFIG_DM_DEBUG_SPACE_MAPS
+
+#define DM_MSG_PREFIX "space map checker"
+
+/*----------------------------------------------------------------*/
+
+struct count_array {
+	dm_block_t nr;
+	dm_block_t nr_free;
+
+	uint32_t *counts;
+};
+
+static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*count = ca->counts[b];
+	return 0;
+}
+
+static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*r = ca->counts[b] > 1;
+	return 0;
+}
+
+static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count)
+{
+	uint32_t old_count;
+
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	old_count = ca->counts[b];
+
+	if (!count && old_count)
+		ca->nr_free++;
+
+	else if (count && !old_count)
+		ca->nr_free--;
+
+	ca->counts[b] = count;
+	return 0;
+}
+
+static int ca_inc_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	ca_set_count(ca, b, ca->counts[b] + 1);
+	return 0;
+}
+
+static int ca_dec_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	BUG_ON(ca->counts[b] == 0);
+	ca_set_count(ca, b, ca->counts[b] - 1);
+	return 0;
+}
+
+static int ca_create(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_blocks;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	ca->nr = nr_blocks;
+	ca->nr_free = nr_blocks;
+	ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL);
+	if (!ca->counts)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int ca_load(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	uint32_t count;
+	dm_block_t nr_blocks, i;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	BUG_ON(ca->nr != nr_blocks);
+
+	DMWARN("Loading debug space map from disk.  This may take some time");
+	for (i = 0; i < nr_blocks; i++) {
+		r = dm_sm_get_count(sm, i, &count);
+		if (r) {
+			DMERR("load failed");
+			return r;
+		}
+
+		ca_set_count(ca, i, count);
+	}
+	DMWARN("Load complete");
+
+	return 0;
+}
+
+static int ca_extend(struct count_array *ca, dm_block_t extra_blocks)
+{
+	dm_block_t nr_blocks = ca->nr + extra_blocks;
+	uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL);
+	if (!counts)
+		return -ENOMEM;
+
+	memcpy(counts, ca->counts, sizeof(*counts) * ca->nr);
+	kfree(ca->counts);
+	ca->nr = nr_blocks;
+	ca->nr_free += extra_blocks;
+	ca->counts = counts;
+	return 0;
+}
+
+static int ca_commit(struct count_array *old, struct count_array *new)
+{
+	if (old->nr != new->nr) {
+		BUG_ON(old->nr > new->nr);
+		ca_extend(old, new->nr - old->nr);
+	}
+
+	BUG_ON(old->nr != new->nr);
+	old->nr_free = new->nr_free;
+	memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr);
+	return 0;
+}
+
+static void ca_destroy(struct count_array *ca)
+{
+	kfree(ca->counts);
+}
+
+/*----------------------------------------------------------------*/
+
+struct sm_checker {
+	struct dm_space_map sm;
+
+	struct count_array old_counts;
+	struct count_array counts;
+
+	struct dm_space_map *real_sm;
+};
+
+static void sm_checker_destroy(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+
+	dm_sm_destroy(smc->real_sm);
+	ca_destroy(&smc->old_counts);
+	ca_destroy(&smc->counts);
+	kfree(smc);
+}
+
+static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_blocks(smc->real_sm, count);
+	if (!r)
+		BUG_ON(smc->old_counts.nr != *count);
+	return r;
+}
+
+static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_free(smc->real_sm, count);
+	if (!r) {
+		/*
+		 * Slow, but we know it's correct.
+		 */
+		dm_block_t b, n = 0;
+		for (b = 0; b < smc->old_counts.nr; b++)
+			if (smc->old_counts.counts[b] == 0 &&
+			    smc->counts.counts[b] == 0)
+				n++;
+
+		if (n != *count)
+			DMERR("free block counts differ, checker %u, sm-disk:%u",
+			      (unsigned) n, (unsigned) *count);
+	}
+	return r;
+}
+
+static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_new_block(smc->real_sm, b);
+
+	if (!r) {
+		BUG_ON(*b >= smc->old_counts.nr);
+		BUG_ON(smc->old_counts.counts[*b] != 0);
+		BUG_ON(*b >= smc->counts.nr);
+		BUG_ON(smc->counts.counts[*b] != 0);
+		ca_set_count(&smc->counts, *b, 1);
+	}
+
+	return r;
+}
+
+static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_inc_block(smc->real_sm, b);
+	int r2 = ca_inc_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_dec_block(smc->real_sm, b);
+	int r2 = ca_dec_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t result2 = 0;
+	int r = dm_sm_get_count(smc->real_sm, b, result);
+	int r2 = ca_get_count(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(*result != result2);
+	return r;
+}
+
+static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int result2 = 0;
+	int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result);
+	int r2 = ca_count_more_than_one(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(!(*result) && result2);
+	return r;
+}
+
+static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t old_rc;
+	int r = dm_sm_set_count(smc->real_sm, b, count);
+	int r2;
+
+	BUG_ON(b >= smc->counts.nr);
+	old_rc = smc->counts.counts[b];
+	r2 = ca_set_count(&smc->counts, b, count);
+	BUG_ON(r != r2);
+
+	return r;
+}
+
+static int sm_checker_commit(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r;
+
+	r = dm_sm_commit(smc->real_sm);
+	if (r)
+		return r;
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_extend(smc->real_sm, extra_blocks);
+	if (r)
+		return r;
+
+	return ca_extend(&smc->counts, extra_blocks);
+}
+
+static int sm_checker_root_size(struct dm_space_map *sm, size_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_root_size(smc->real_sm, result);
+}
+
+static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops_ = {
+	.destroy = sm_checker_destroy,
+	.get_nr_blocks = sm_checker_get_nr_blocks,
+	.get_nr_free = sm_checker_get_nr_free,
+	.inc_block = sm_checker_inc_block,
+	.dec_block = sm_checker_dec_block,
+	.new_block = sm_checker_new_block,
+	.get_count = sm_checker_get_count,
+	.count_is_more_than_one = sm_checker_count_more_than_one,
+	.set_count = sm_checker_set_count,
+	.commit = sm_checker_commit,
+	.extend = sm_checker_extend,
+	.root_size = sm_checker_root_size,
+	.copy_root = sm_checker_copy_root
+};
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+
+	r = ca_load(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#else
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-checker.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-checker.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-checker.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-checker.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H
+#define SNAPSHOTS_SPACE_MAP_CHECKER_H
+
+#include "dm-space-map.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This space map wraps a real on-disk space map, and verifies all of its
+ * operations.  It uses a lot of memory, so only use if you have a specific
+ * problem that you're debugging.
+ *
+ * Ownership of @sm passes.
+ */
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm);
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-common.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-common.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-common.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/bitops.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map common"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Index validator.
+ */
+#define INDEX_CSUM_XOR 160478
+
+static void index_prepare_for_write(struct dm_block_validator *v,
+				    struct dm_block *b,
+				    size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+
+	mi_le->blocknr = cpu_to_le64(dm_block_location(b));
+	mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+						 block_size - sizeof(__le32),
+						 INDEX_CSUM_XOR));
+}
+
+static int index_check(struct dm_block_validator *v,
+		       struct dm_block *b,
+		       size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
+		DMERR("index_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(mi_le->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+					       block_size - sizeof(__le32),
+					       INDEX_CSUM_XOR));
+	if (csum_disk != mi_le->csum) {
+		DMERR("index_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator index_validator = {
+	.name = "index",
+	.prepare_for_write = index_prepare_for_write,
+	.check = index_check
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bitmap validator
+ */
+#define BITMAP_CSUM_XOR 240779
+
+static void bitmap_prepare_for_write(struct dm_block_validator *v,
+				     struct dm_block *b,
+				     size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+
+	disk_header->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+						       block_size - sizeof(__le32),
+						       BITMAP_CSUM_XOR));
+}
+
+static int bitmap_check(struct dm_block_validator *v,
+			struct dm_block *b,
+			size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
+		DMERR("bitmap check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(disk_header->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+					       block_size - sizeof(__le32),
+					       BITMAP_CSUM_XOR));
+	if (csum_disk != disk_header->csum) {
+		DMERR("bitmap check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator dm_sm_bitmap_validator = {
+	.name = "sm_bitmap",
+	.prepare_for_write = bitmap_prepare_for_write,
+	.check = bitmap_check
+};
+
+/*----------------------------------------------------------------*/
+
+#define ENTRIES_PER_WORD 32
+#define ENTRIES_SHIFT	5
+
+static void *dm_bitmap_data(struct dm_block *b)
+{
+	return dm_block_data(b) + sizeof(struct disk_bitmap_header);
+}
+
+#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
+
+static unsigned bitmap_word_used(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	uint64_t bits = le64_to_cpu(*w_le);
+	uint64_t mask = (bits + WORD_MASK_HIGH + 1) & WORD_MASK_HIGH;
+
+	return !(~bits & mask);
+}
+
+static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+	unsigned hi, lo;
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+	hi = !!test_bit_le(b, (void *) w_le);
+	lo = !!test_bit_le(b + 1, (void *) w_le);
+	return (hi << 1) | lo;
+}
+
+static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+
+	if (val & 2)
+		__set_bit_le(b, (void *) w_le);
+	else
+		__clear_bit_le(b, (void *) w_le);
+
+	if (val & 1)
+		__set_bit_le(b + 1, (void *) w_le);
+	else
+		__clear_bit_le(b + 1, (void *) w_le);
+}
+
+static int sm_find_free(void *addr, unsigned begin, unsigned end,
+			unsigned *result)
+{
+	while (begin < end) {
+		if (!(begin & (ENTRIES_PER_WORD - 1)) &&
+		    bitmap_word_used(addr, begin)) {
+			begin += ENTRIES_PER_WORD;
+			continue;
+		}
+
+		if (!sm_lookup_bitmap(addr, begin)) {
+			*result = begin;
+			return 0;
+		}
+
+		begin++;
+	}
+
+	return -ENOSPC;
+}
+
+/*----------------------------------------------------------------*/
+
+static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	ll->tm = tm;
+
+	ll->bitmap_info.tm = tm;
+	ll->bitmap_info.levels = 1;
+
+	/*
+	 * Because the new bitmap blocks are created via a shadow
+	 * operation, the old entry has already had its reference count
+	 * decremented and we don't need the btree to do any bookkeeping.
+	 */
+	ll->bitmap_info.value_type.size = sizeof(struct disk_index_entry);
+	ll->bitmap_info.value_type.inc = NULL;
+	ll->bitmap_info.value_type.dec = NULL;
+	ll->bitmap_info.value_type.equal = NULL;
+
+	ll->ref_count_info.tm = tm;
+	ll->ref_count_info.levels = 1;
+	ll->ref_count_info.value_type.size = sizeof(uint32_t);
+	ll->ref_count_info.value_type.inc = NULL;
+	ll->ref_count_info.value_type.dec = NULL;
+	ll->ref_count_info.value_type.equal = NULL;
+
+	ll->block_size = dm_bm_block_size(dm_tm_get_bm(tm));
+
+	if (ll->block_size > (1 << 30)) {
+		DMERR("block size too big to hold bitmaps");
+		return -EINVAL;
+	}
+
+	ll->entries_per_block = (ll->block_size - sizeof(struct disk_bitmap_header)) *
+		ENTRIES_PER_BYTE;
+	ll->nr_blocks = 0;
+	ll->bitmap_root = 0;
+	ll->ref_count_root = 0;
+
+	return 0;
+}
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
+{
+	int r;
+	dm_block_t i, nr_blocks, nr_indexes;
+	unsigned old_blocks, blocks;
+
+	nr_blocks = ll->nr_blocks + extra_blocks;
+	old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
+	blocks = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+
+	nr_indexes = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+	if (nr_indexes > ll->max_entries(ll)) {
+		DMERR("space map too large");
+		return -EINVAL;
+	}
+
+	for (i = old_blocks; i < blocks; i++) {
+		struct dm_block *b;
+		struct disk_index_entry idx;
+
+		r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b);
+		if (r < 0)
+			return r;
+		idx.blocknr = cpu_to_le64(dm_block_location(b));
+
+		r = dm_tm_unlock(ll->tm, b);
+		if (r < 0)
+			return r;
+
+		idx.nr_free = cpu_to_le32(ll->entries_per_block);
+		idx.none_free_before = 0;
+
+		r = ll->save_ie(ll, i, &idx);
+		if (r < 0)
+			return r;
+	}
+
+	ll->nr_blocks = nr_blocks;
+	return 0;
+}
+
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	int r;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	struct dm_block *blk;
+
+	b = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			    &dm_sm_bitmap_validator, &blk);
+	if (r < 0)
+		return r;
+
+	*result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
+
+	return dm_tm_unlock(ll->tm, blk);
+}
+
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	__le32 le_rc;
+	int r = sm_ll_lookup_bitmap(ll, b, result);
+
+	if (r)
+		return r;
+
+	if (*result != 3)
+		return r;
+
+	r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
+	if (r < 0)
+		return r;
+
+	*result = le32_to_cpu(le_rc);
+
+	return r;
+}
+
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result)
+{
+	int r;
+	struct disk_index_entry ie_disk;
+	dm_block_t i, index_begin = begin;
+	dm_block_t index_end = dm_sector_div_up(end, ll->entries_per_block);
+
+	/*
+	 * FIXME: Use shifts
+	 */
+	begin = do_div(index_begin, ll->entries_per_block);
+	end = do_div(end, ll->entries_per_block);
+
+	for (i = index_begin; i < index_end; i++, begin = 0) {
+		struct dm_block *blk;
+		unsigned position;
+		uint32_t bit_end;
+
+		r = ll->load_ie(ll, i, &ie_disk);
+		if (r < 0)
+			return r;
+
+		if (le32_to_cpu(ie_disk.nr_free) == 0)
+			continue;
+
+		r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+				    &dm_sm_bitmap_validator, &blk);
+		if (r < 0)
+			return r;
+
+		bit_end = (i == index_end - 1) ?  end : ll->entries_per_block;
+
+		r = sm_find_free(dm_bitmap_data(blk),
+				 max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+				 bit_end, &position);
+		if (r == -ENOSPC) {
+			/*
+			 * This might happen because we started searching
+			 * part way through the bitmap.
+			 */
+			dm_tm_unlock(ll->tm, blk);
+			continue;
+
+		} else if (r < 0) {
+			dm_tm_unlock(ll->tm, blk);
+			return r;
+		}
+
+		r = dm_tm_unlock(ll->tm, blk);
+		if (r < 0)
+			return r;
+
+		*result = i * ll->entries_per_block + (dm_block_t) position;
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
+		 uint32_t ref_count, enum allocation_event *ev)
+{
+	int r;
+	uint32_t bit, old;
+	struct dm_block *nb;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	void *bm_le;
+	int inc;
+
+	bit = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_shadow_block(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			       &dm_sm_bitmap_validator, &nb, &inc);
+	if (r < 0) {
+		DMERR("dm_tm_shadow_block() failed");
+		return r;
+	}
+	ie_disk.blocknr = cpu_to_le64(dm_block_location(nb));
+
+	bm_le = dm_bitmap_data(nb);
+	old = sm_lookup_bitmap(bm_le, bit);
+
+	if (ref_count <= 2) {
+		sm_set_bitmap(bm_le, bit, ref_count);
+
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+#if 0
+		/* FIXME: dm_btree_remove doesn't handle this yet */
+		if (old > 2) {
+			r = dm_btree_remove(&ll->ref_count_info,
+					    ll->ref_count_root,
+					    &b, &ll->ref_count_root);
+			if (r)
+				return r;
+		}
+#endif
+
+	} else {
+		__le32 le_rc = cpu_to_le32(ref_count);
+
+		sm_set_bitmap(bm_le, bit, 3);
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+		__dm_bless_for_disk(&le_rc);
+		r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
+				    &b, &le_rc, &ll->ref_count_root);
+		if (r < 0) {
+			DMERR("ref count insert failed");
+			return r;
+		}
+	}
+
+	if (ref_count && !old) {
+		*ev = SM_ALLOC;
+		ll->nr_allocated++;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) - 1);
+		if (le32_to_cpu(ie_disk.none_free_before) == bit)
+			ie_disk.none_free_before = cpu_to_le32(bit + 1);
+
+	} else if (old && !ref_count) {
+		*ev = SM_FREE;
+		ll->nr_allocated--;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) + 1);
+		ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
+	}
+
+	return ll->save_ie(ll, index, &ie_disk);
+}
+
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	return sm_ll_insert(ll, b, rc + 1, ev);
+}
+
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	if (!rc)
+		return -EINVAL;
+
+	return sm_ll_insert(ll, b, rc - 1, ev);
+}
+
+int sm_ll_commit(struct ll_disk *ll)
+{
+	return ll->commit(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ie, ll->mi_le.index + index, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ll->mi_le.index + index, ie, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_init_index(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *b;
+
+	r = dm_tm_new_block(ll->tm, &index_validator, &b);
+	if (r < 0)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+static int metadata_ll_open(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *block;
+
+	r = dm_tm_read_lock(ll->tm, ll->bitmap_root,
+			    &index_validator, &block);
+	if (r)
+		return r;
+
+	memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
+	return dm_tm_unlock(ll->tm, block);
+}
+
+static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
+{
+	return MAX_METADATA_BITMAPS;
+}
+
+static int metadata_ll_commit(struct ll_disk *ll)
+{
+	int r, inc;
+	struct dm_block *b;
+
+	r = dm_tm_shadow_block(ll->tm, ll->bitmap_root, &index_validator, &b, &inc);
+	if (r)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
+}
+
+static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	__dm_bless_for_disk(ie);
+	return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
+			       &index, ie, &ll->bitmap_root);
+}
+
+static int disk_ll_init_index(struct ll_disk *ll)
+{
+	return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
+}
+
+static int disk_ll_open(struct ll_disk *ll)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
+{
+	return -1ULL;
+}
+
+static int disk_ll_commit(struct ll_disk *ll)
+{
+	return 0;
+}
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-common.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-common.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_COMMON_H
+#define DM_SPACE_MAP_COMMON_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Low level disk format
+ *
+ * Bitmap btree
+ * ------------
+ *
+ * Each value stored in the btree is an index_entry.  This points to a
+ * block that is used as a bitmap.  Within the bitmap hold 2 bits per
+ * entry, which represent UNUSED = 0, REF_COUNT = 1, REF_COUNT = 2 and
+ * REF_COUNT = many.
+ *
+ * Refcount btree
+ * --------------
+ *
+ * Any entry that has a ref count higher than 2 gets entered in the ref
+ * count tree.  The leaf values for this tree is the 32-bit ref count.
+ */
+
+struct disk_index_entry {
+	__le64 blocknr;
+	__le32 nr_free;
+	__le32 none_free_before;
+} __packed;
+
+
+#define MAX_METADATA_BITMAPS 255
+struct disk_metadata_index {
+	__le32 csum;
+	__le32 padding;
+	__le64 blocknr;
+
+	struct disk_index_entry index[MAX_METADATA_BITMAPS];
+} __packed;
+
+struct ll_disk;
+
+typedef int (*load_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *result);
+typedef int (*save_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie);
+typedef int (*init_index_fn)(struct ll_disk *ll);
+typedef int (*open_index_fn)(struct ll_disk *ll);
+typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
+typedef int (*commit_fn)(struct ll_disk *ll);
+
+struct ll_disk {
+	struct dm_transaction_manager *tm;
+	struct dm_btree_info bitmap_info;
+	struct dm_btree_info ref_count_info;
+
+	uint32_t block_size;
+	uint32_t entries_per_block;
+	dm_block_t nr_blocks;
+	dm_block_t nr_allocated;
+
+	/*
+	 * bitmap_root may be a btree root or a simple index.
+	 */
+	dm_block_t bitmap_root;
+
+	dm_block_t ref_count_root;
+
+	struct disk_metadata_index mi_le;
+	load_ie_fn load_ie;
+	save_ie_fn save_ie;
+	init_index_fn init_index;
+	open_index_fn open_index;
+	max_index_entries_fn max_entries;
+	commit_fn commit;
+};
+
+struct disk_sm_root {
+	__le64 nr_blocks;
+	__le64 nr_allocated;
+	__le64 bitmap_root;
+	__le64 ref_count_root;
+} __packed;
+
+#define ENTRIES_PER_BYTE 4
+
+struct disk_bitmap_header {
+	__le32 csum;
+	__le32 not_used;
+	__le64 blocknr;
+} __packed;
+
+enum allocation_event {
+	SM_NONE,
+	SM_ALLOC,
+	SM_FREE,
+};
+
+/*----------------------------------------------------------------*/
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks);
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result);
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_commit(struct ll_disk *ll);
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* DM_SPACE_MAP_COMMON_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-disk.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-disk.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-disk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-disk.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map disk"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ */
+struct sm_disk {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+	dm_block_t nr_allocated_this_transaction;
+};
+
+static void sm_disk_destroy(struct dm_space_map *sm)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	kfree(smd);
+}
+
+static int sm_disk_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	return sm_ll_extend(&smd->ll, extra_blocks);
+}
+
+static int sm_disk_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = smd->old_ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_disk_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = (smd->old_ll.nr_blocks - smd->old_ll.nr_allocated) - smd->nr_allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_disk_get_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t *result)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	return sm_ll_lookup(&smd->ll, b, result);
+}
+
+static int sm_disk_count_is_more_than_one(struct dm_space_map *sm, dm_block_t b,
+					  int *result)
+{
+	int r;
+	uint32_t count;
+
+	r = sm_disk_get_count(sm, b, &count);
+	if (r)
+		return r;
+
+	return count > 1;
+}
+
+static int sm_disk_set_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t count)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_insert(&smd->ll, b, count, &ev);
+	if (!r) {
+		switch (ev) {
+		case SM_NONE:
+			break;
+
+		case SM_ALLOC:
+			/*
+			 * This _must_ be free in the prior transaction
+			 * otherwise we've lost atomicity.
+			 */
+			smd->nr_allocated_this_transaction++;
+			break;
+
+		case SM_FREE:
+			/*
+			 * It's only free if it's also free in the last
+			 * transaction.
+			 */
+			r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+			if (r)
+				return r;
+
+			if (!old_count)
+				smd->nr_allocated_this_transaction--;
+			break;
+		}
+	}
+
+	return r;
+}
+
+static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_inc(&smd->ll, b, &ev);
+	if (!r && (ev == SM_ALLOC))
+		/*
+		 * This _must_ be free in the prior transaction
+		 * otherwise we've lost atomicity.
+		 */
+		smd->nr_allocated_this_transaction++;
+
+	return r;
+}
+
+static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_dec(&smd->ll, b, &ev);
+	if (!r && (ev == SM_FREE)) {
+		/*
+		 * It's only free if it's also free in the last
+		 * transaction.
+		 */
+		r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+		if (r)
+			return r;
+
+		if (!old_count)
+			smd->nr_allocated_this_transaction--;
+	}
+
+	return r;
+}
+
+static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	/* FIXME: we should loop round a couple of times */
+	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smd->begin = *b + 1;
+	r = sm_ll_inc(&smd->ll, *b, &ev);
+	if (!r) {
+		BUG_ON(ev != SM_ALLOC);
+		smd->nr_allocated_this_transaction++;
+	}
+
+	return r;
+}
+
+static int sm_disk_commit(struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_free;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	r = sm_ll_commit(&smd->ll);
+	if (r)
+		return r;
+
+	memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll));
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_disk_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_disk_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smd->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smd->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smd->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smd->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops = {
+	.destroy = sm_disk_destroy,
+	.extend = sm_disk_extend,
+	.get_nr_blocks = sm_disk_get_nr_blocks,
+	.get_nr_free = sm_disk_get_nr_free,
+	.get_count = sm_disk_get_count,
+	.count_is_more_than_one = sm_disk_count_is_more_than_one,
+	.set_count = sm_disk_set_count,
+	.inc_block = sm_disk_inc_block,
+	.dec_block = sm_disk_dec_block,
+	.new_block = sm_disk_new_block,
+	.commit = sm_disk_commit,
+	.root_size = sm_disk_root_size,
+	.copy_root = sm_disk_copy_root
+};
+
+static struct dm_space_map *dm_sm_disk_create_real(
+	struct dm_transaction_manager *tm,
+	dm_block_t nr_blocks)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_new_disk(&smd->ll, tm);
+	if (r)
+		goto bad;
+
+	r = sm_ll_extend(&smd->ll, nr_blocks);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks)
+{
+	struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks);
+	return dm_sm_checker_create_fresh(sm);
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_create);
+
+static struct dm_space_map *dm_sm_disk_open_real(
+	struct dm_transaction_manager *tm,
+	void *root_le, size_t len)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_open_disk(&smd->ll, tm, root_le, len);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root_le, size_t len)
+{
+	return dm_sm_checker_create(
+		dm_sm_disk_open_real(tm, root_le, len));
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_open);
+
+/*----------------------------------------------------------------*/
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-disk.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-disk.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-disk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-disk.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_DISK_H
+#define _LINUX_DM_SPACE_MAP_DISK_H
+
+#include "dm-block-manager.h"
+
+struct dm_space_map;
+struct dm_transaction_manager;
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks);
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root, size_t len);
+
+#endif /* _LINUX_DM_SPACE_MAP_DISK_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_H
+#define _LINUX_DM_SPACE_MAP_H
+
+#include "dm-block-manager.h"
+
+/*
+ * struct dm_space_map keeps a record of how many times each block in a device
+ * is referenced.  It needs to be fixed on disk as part of the transaction.
+ */
+struct dm_space_map {
+	void (*destroy)(struct dm_space_map *sm);
+
+	/*
+	 * You must commit before allocating the newly added space.
+	 */
+	int (*extend)(struct dm_space_map *sm, dm_block_t extra_blocks);
+
+	/*
+	 * Extensions do not appear in this count until after commit has
+	 * been called.
+	 */
+	int (*get_nr_blocks)(struct dm_space_map *sm, dm_block_t *count);
+
+	/*
+	 * Space maps must never allocate a block from the previous
+	 * transaction, in case we need to rollback.  This complicates the
+	 * semantics of get_nr_free(), it should return the number of blocks
+	 * that are available for allocation _now_.  For instance you may
+	 * have blocks with a zero reference count that will not be
+	 * available for allocation until after the next commit.
+	 */
+	int (*get_nr_free)(struct dm_space_map *sm, dm_block_t *count);
+
+	int (*get_count)(struct dm_space_map *sm, dm_block_t b, uint32_t *result);
+	int (*count_is_more_than_one)(struct dm_space_map *sm, dm_block_t b,
+				      int *result);
+	int (*set_count)(struct dm_space_map *sm, dm_block_t b, uint32_t count);
+
+	int (*commit)(struct dm_space_map *sm);
+
+	int (*inc_block)(struct dm_space_map *sm, dm_block_t b);
+	int (*dec_block)(struct dm_space_map *sm, dm_block_t b);
+
+	/*
+	 * new_block will increment the returned block.
+	 */
+	int (*new_block)(struct dm_space_map *sm, dm_block_t *b);
+
+	/*
+	 * The root contains all the information needed to fix the space map.
+	 * Generally this info is small, so squirrel it away in a disk block
+	 * along with other info.
+	 */
+	int (*root_size)(struct dm_space_map *sm, size_t *result);
+	int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len);
+};
+
+/*----------------------------------------------------------------*/
+
+static inline void dm_sm_destroy(struct dm_space_map *sm)
+{
+	sm->destroy(sm);
+}
+
+static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	return sm->extend(sm, extra_blocks);
+}
+
+static inline int dm_sm_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_blocks(sm, count);
+}
+
+static inline int dm_sm_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_free(sm, count);
+}
+
+static inline int dm_sm_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	return sm->get_count(sm, b, result);
+}
+
+static inline int dm_sm_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	return sm->count_is_more_than_one(sm, b, result);
+}
+
+static inline int dm_sm_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	return sm->set_count(sm, b, count);
+}
+
+static inline int dm_sm_commit(struct dm_space_map *sm)
+{
+	return sm->commit(sm);
+}
+
+static inline int dm_sm_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->inc_block(sm, b);
+}
+
+static inline int dm_sm_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->dec_block(sm, b);
+}
+
+static inline int dm_sm_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	return sm->new_block(sm, b);
+}
+
+static inline int dm_sm_root_size(struct dm_space_map *sm, size_t *result)
+{
+	return sm->root_size(sm, result);
+}
+
+static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	return sm->copy_root(sm, copy_to_here_le, len);
+}
+
+#endif	/* _LINUX_DM_SPACE_MAP_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-metadata.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-metadata.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-metadata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-metadata.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-metadata.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map metadata"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ *
+ * The low level disk format is written using the standard btree and
+ * transaction manager.  This means that performing disk operations may
+ * cause us to recurse into the space map in order to allocate new blocks.
+ * For this reason we have a pool of pre-allocated blocks large enough to
+ * service any metadata_ll_disk operation.
+ */
+
+/*
+ * FIXME: we should calculate this based on the size of the device.
+ * Only the metadata space map needs this functionality.
+ */
+#define MAX_RECURSIVE_ALLOCATIONS 1024
+
+enum block_op_type {
+	BOP_INC,
+	BOP_DEC
+};
+
+struct block_op {
+	enum block_op_type type;
+	dm_block_t block;
+};
+
+struct sm_metadata {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+
+	unsigned recursion_count;
+	unsigned allocated_this_transaction;
+	unsigned nr_uncommitted;
+	struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+};
+
+static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
+{
+	struct block_op *op;
+
+	if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) {
+		DMERR("too many recursive allocations");
+		return -ENOMEM;
+	}
+
+	op = smm->uncommitted + smm->nr_uncommitted++;
+	op->type = type;
+	op->block = b;
+
+	return 0;
+}
+
+static int commit_bop(struct sm_metadata *smm, struct block_op *op)
+{
+	int r = 0;
+	enum allocation_event ev;
+
+	switch (op->type) {
+	case BOP_INC:
+		r = sm_ll_inc(&smm->ll, op->block, &ev);
+		break;
+
+	case BOP_DEC:
+		r = sm_ll_dec(&smm->ll, op->block, &ev);
+		break;
+	}
+
+	return r;
+}
+
+static void in(struct sm_metadata *smm)
+{
+	smm->recursion_count++;
+}
+
+static int out(struct sm_metadata *smm)
+{
+	int r = 0;
+
+	/*
+	 * If we're not recursing then very bad things are happening.
+	 */
+	if (!smm->recursion_count) {
+		DMERR("lost track of recursion depth");
+		return -ENOMEM;
+	}
+
+	if (smm->recursion_count == 1 && smm->nr_uncommitted) {
+		while (smm->nr_uncommitted && !r) {
+			smm->nr_uncommitted--;
+			r = commit_bop(smm, smm->uncommitted +
+				       smm->nr_uncommitted);
+			if (r)
+				break;
+		}
+	}
+
+	smm->recursion_count--;
+
+	return r;
+}
+
+/*
+ * When using the out() function above, we often want to combine an error
+ * code for the operation run in the recursive context with that from
+ * out().
+ */
+static int combine_errors(int r1, int r2)
+{
+	return r1 ? r1 : r2;
+}
+
+static int recursing(struct sm_metadata *smm)
+{
+	return smm->recursion_count;
+}
+
+static void sm_metadata_destroy(struct dm_space_map *sm)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	kfree(smm);
+}
+
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("doesn't support extend");
+	return -EINVAL;
+}
+
+static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->old_ll.nr_blocks - smm->old_ll.nr_allocated -
+		 smm->allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t *result)
+{
+	int r, i;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	unsigned adjustment = 0;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	r = sm_ll_lookup(&smm->ll, b, result);
+	if (r)
+		return r;
+
+	*result += adjustment;
+
+	return 0;
+}
+
+static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
+					      dm_block_t b, int *result)
+{
+	int r, i, adjustment = 0;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	uint32_t rc;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	if (adjustment > 1) {
+		*result = 1;
+		return 0;
+	}
+
+	r = sm_ll_lookup_bitmap(&smm->ll, b, &rc);
+	if (r)
+		return r;
+
+	if (rc == 3)
+		/*
+		 * We err on the side of caution, and always return true.
+		 */
+		*result = 1;
+	else
+		*result = rc + adjustment > 1;
+
+	return 0;
+}
+
+static int sm_metadata_set_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t count)
+{
+	int r, r2;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (smm->recursion_count) {
+		DMERR("cannot recurse set_count()");
+		return -EINVAL;
+	}
+
+	in(smm);
+	r = sm_ll_insert(&smm->ll, b, count, &ev);
+	r2 = out(smm);
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_DEC, b);
+	else {
+		in(smm);
+		r = sm_ll_dec(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smm->begin = *b + 1;
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, *b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, *b, &ev);
+		r2 = out(smm);
+	}
+
+	if (!r)
+		smm->allocated_this_transaction++;
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r = sm_metadata_new_block_(sm, b);
+	if (r)
+		DMERR("out of metadata space");
+	return r;
+}
+
+static int sm_metadata_commit(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_commit(&smm->ll);
+	if (r)
+		return r;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	smm->begin = 0;
+	smm->allocated_this_transaction = 0;
+
+	return 0;
+}
+
+static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smm->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smm->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smm->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smm->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+static struct dm_space_map ops = {
+	.destroy = sm_metadata_destroy,
+	.extend = sm_metadata_extend,
+	.get_nr_blocks = sm_metadata_get_nr_blocks,
+	.get_nr_free = sm_metadata_get_nr_free,
+	.get_count = sm_metadata_get_count,
+	.count_is_more_than_one = sm_metadata_count_is_more_than_one,
+	.set_count = sm_metadata_set_count,
+	.inc_block = sm_metadata_inc_block,
+	.dec_block = sm_metadata_dec_block,
+	.new_block = sm_metadata_new_block,
+	.commit = sm_metadata_commit,
+	.root_size = sm_metadata_root_size,
+	.copy_root = sm_metadata_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * When a new space map is created that manages its own space.  We use
+ * this tiny bootstrap allocator.
+ */
+static void sm_bootstrap_destroy(struct dm_space_map *sm)
+{
+}
+
+static int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("boostrap doesn't support extend");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return smm->ll.nr_blocks;
+}
+
+static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks - smm->begin;
+
+	return 0;
+}
+
+static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return b < smm->begin ? 1 : 0;
+}
+
+static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	*result = 0;
+
+	return 0;
+}
+
+static int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	DMERR("boostrap doesn't support set_count");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	/*
+	 * We know the entire device is unused.
+	 */
+	if (smm->begin == smm->ll.nr_blocks)
+		return -ENOSPC;
+
+	*b = smm->begin++;
+
+	return 0;
+}
+
+static int sm_bootstrap_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_INC, b);
+}
+
+static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_DEC, b);
+}
+
+static int sm_bootstrap_commit(struct dm_space_map *sm)
+{
+	return 0;
+}
+
+static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
+{
+	DMERR("boostrap doesn't support root_size");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where,
+				  size_t max)
+{
+	DMERR("boostrap doesn't support copy_root");
+
+	return -EINVAL;
+}
+
+static struct dm_space_map bootstrap_ops = {
+	.destroy = sm_bootstrap_destroy,
+	.extend = sm_bootstrap_extend,
+	.get_nr_blocks = sm_bootstrap_get_nr_blocks,
+	.get_nr_free = sm_bootstrap_get_nr_free,
+	.get_count = sm_bootstrap_get_count,
+	.count_is_more_than_one = sm_bootstrap_count_is_more_than_one,
+	.set_count = sm_bootstrap_set_count,
+	.inc_block = sm_bootstrap_inc_block,
+	.dec_block = sm_bootstrap_dec_block,
+	.new_block = sm_bootstrap_new_block,
+	.commit = sm_bootstrap_commit,
+	.root_size = sm_bootstrap_root_size,
+	.copy_root = sm_bootstrap_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+struct dm_space_map *dm_sm_metadata_init(void)
+{
+	struct sm_metadata *smm;
+
+	smm = kmalloc(sizeof(*smm), GFP_KERNEL);
+	if (!smm)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	return &smm->sm;
+}
+
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock)
+{
+	int r;
+	dm_block_t i;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	smm->begin = superblock + 1;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
+
+	r = sm_ll_new_metadata(&smm->ll, tm);
+	if (r)
+		return r;
+
+	r = sm_ll_extend(&smm->ll, nr_blocks);
+	if (r)
+		return r;
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	/*
+	 * Now we need to update the newly created data structures with the
+	 * allocated blocks that they were built from.
+	 */
+	for (i = superblock; !r && i < smm->begin; i++)
+		r = sm_ll_inc(&smm->ll, i, &ev);
+
+	if (r)
+		return r;
+
+	return sm_metadata_commit(sm);
+}
+
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_open_metadata(&smm->ll, tm, root_le, len);
+	if (r)
+		return r;
+
+	smm->begin = 0;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	return 0;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-metadata.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-metadata.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-space-map-metadata.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-space-map-metadata.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_METADATA_H
+#define DM_SPACE_MAP_METADATA_H
+
+#include "dm-transaction-manager.h"
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_metadata_init(void);
+
+/*
+ * Create a fresh space map.
+ */
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock);
+
+/*
+ * Open from a previously-recorded root.
+ */
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+#endif	/* DM_SPACE_MAP_METADATA_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-transaction-manager.c linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-transaction-manager.c
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-transaction-manager.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-transaction-manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-transaction-manager.h"
+#include "dm-space-map.h"
+#include "dm-space-map-checker.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map-metadata.h"
+#include "dm-persistent-data-internal.h"
+
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "transaction manager"
+
+/*----------------------------------------------------------------*/
+
+struct shadow_info {
+	struct hlist_node hlist;
+	dm_block_t where;
+};
+
+/*
+ * It would be nice if we scaled with the size of transaction.
+ */
+#define HASH_SIZE 256
+#define HASH_MASK (HASH_SIZE - 1)
+
+struct dm_transaction_manager {
+	int is_clone;
+	struct dm_transaction_manager *real;
+
+	struct dm_block_manager *bm;
+	struct dm_space_map *sm;
+
+	spinlock_t lock;
+	struct hlist_head buckets[HASH_SIZE];
+};
+
+/*----------------------------------------------------------------*/
+
+static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	int r = 0;
+	unsigned bucket = dm_hash_block(b, HASH_MASK);
+	struct shadow_info *si;
+	struct hlist_node *n;
+
+	spin_lock(&tm->lock);
+	hlist_for_each_entry(si, n, tm->buckets + bucket, hlist)
+		if (si->where == b) {
+			r = 1;
+			break;
+		}
+	spin_unlock(&tm->lock);
+
+	return r;
+}
+
+/*
+ * This can silently fail if there's no memory.  We're ok with this since
+ * creating redundant shadows causes no harm.
+ */
+static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	unsigned bucket;
+	struct shadow_info *si;
+
+	si = kmalloc(sizeof(*si), GFP_NOIO);
+	if (si) {
+		si->where = b;
+		bucket = dm_hash_block(b, HASH_MASK);
+		spin_lock(&tm->lock);
+		hlist_add_head(&si->hlist, tm->buckets + bucket);
+		spin_unlock(&tm->lock);
+	}
+}
+
+static void wipe_shadow_table(struct dm_transaction_manager *tm)
+{
+	struct shadow_info *si;
+	struct hlist_node *n, *tmp;
+	struct hlist_head *bucket;
+	int i;
+
+	spin_lock(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++) {
+		bucket = tm->buckets + i;
+		hlist_for_each_entry_safe(si, n, tmp, bucket, hlist)
+			kfree(si);
+
+		INIT_HLIST_HEAD(bucket);
+	}
+
+	spin_unlock(&tm->lock);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
+						   struct dm_space_map *sm)
+{
+	int i;
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (!tm)
+		return ERR_PTR(-ENOMEM);
+
+	tm->is_clone = 0;
+	tm->real = NULL;
+	tm->bm = bm;
+	tm->sm = sm;
+
+	spin_lock_init(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++)
+		INIT_HLIST_HEAD(tm->buckets + i);
+
+	return tm;
+}
+
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real)
+{
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (tm) {
+		tm->is_clone = 1;
+		tm->real = real;
+	}
+
+	return tm;
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
+
+void dm_tm_destroy(struct dm_transaction_manager *tm)
+{
+	kfree(tm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_destroy);
+
+int dm_tm_pre_commit(struct dm_transaction_manager *tm)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_commit(tm->sm);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_tm_pre_commit);
+
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	wipe_shadow_table(tm);
+
+	return dm_bm_flush_and_unlock(tm->bm, root);
+}
+EXPORT_SYMBOL_GPL(dm_tm_commit);
+
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	int r;
+	dm_block_t new_block;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_new_block(tm->sm, &new_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_write_lock_zero(tm->bm, new_block, v, result);
+	if (r < 0) {
+		dm_sm_dec_block(tm->sm, new_block);
+		return r;
+	}
+
+	/*
+	 * New blocks count as shadows in that they don't need to be
+	 * shadowed again.
+	 */
+	insert_shadow(tm, new_block);
+
+	return 0;
+}
+
+static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+			  struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	dm_block_t new;
+	struct dm_block *orig_block;
+
+	r = dm_sm_new_block(tm->sm, &new);
+	if (r < 0)
+		return r;
+
+	r = dm_sm_dec_block(tm->sm, orig);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_read_lock(tm->bm, orig, v, &orig_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_unlock_move(orig_block, new);
+	if (r < 0) {
+		dm_bm_unlock(orig_block);
+		return r;
+	}
+
+	return dm_bm_write_lock(tm->bm, new, v, result);
+}
+
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v, struct dm_block **result,
+		       int *inc_children)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_count_is_more_than_one(tm->sm, orig, inc_children);
+	if (r < 0)
+		return r;
+
+	if (is_shadow(tm, orig) && !*inc_children)
+		return dm_bm_write_lock(tm->bm, orig, v, result);
+
+	r = __shadow_block(tm, orig, v, result);
+	if (r < 0)
+		return r;
+	insert_shadow(tm, dm_block_location(*result));
+
+	return r;
+}
+
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **blk)
+{
+	if (tm->is_clone)
+		return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+	return dm_bm_read_lock(tm->bm, b, v, blk);
+}
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
+{
+	return dm_bm_unlock(b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_unlock);
+
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_inc_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_inc);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_dec_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_dec);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	return dm_sm_get_count(tm->sm, b, result);
+}
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
+{
+	return tm->bm;
+}
+
+/*----------------------------------------------------------------*/
+
+static int dm_tm_create_internal(struct dm_block_manager *bm,
+				 dm_block_t sb_location,
+				 struct dm_block_validator *sb_validator,
+				 size_t root_offset, size_t root_max_len,
+				 struct dm_transaction_manager **tm,
+				 struct dm_space_map **sm,
+				 struct dm_block **sblock,
+				 int create)
+{
+	int r;
+	struct dm_space_map *inner;
+
+	inner = dm_sm_metadata_init();
+	if (IS_ERR(inner))
+		return PTR_ERR(inner);
+
+	*tm = dm_tm_create(bm, inner);
+	if (IS_ERR(*tm)) {
+		dm_sm_destroy(inner);
+		return PTR_ERR(*tm);
+	}
+
+	if (create) {
+		r = dm_bm_write_lock_zero(dm_tm_get_bm(*tm), sb_location,
+					  sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm),
+					  sb_location);
+		if (r) {
+			DMERR("couldn't create metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+
+	} else {
+		r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location,
+				     sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_open(inner, *tm,
+					dm_block_data(*sblock) + root_offset,
+					root_max_len);
+		if (r) {
+			DMERR("couldn't open metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+	}
+
+	return 0;
+
+bad2:
+	dm_tm_unlock(*tm, *sblock);
+bad1:
+	dm_tm_destroy(*tm);
+	dm_sm_destroy(inner);
+	return r;
+}
+
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator,
+				     0, 0, tm, sm, sblock, 1);
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_with_sm);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator, root_offset,
+				     root_max_len, tm, sm, sblock, 0);
+}
+EXPORT_SYMBOL_GPL(dm_tm_open_with_sm);
+
+/*----------------------------------------------------------------*/
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-transaction-manager.h linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-transaction-manager.h
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/dm-transaction-manager.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/dm-transaction-manager.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_TRANSACTION_MANAGER_H
+#define _LINUX_DM_TRANSACTION_MANAGER_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+struct dm_space_map;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This manages the scope of a transaction.  It also enforces immutability
+ * of the on-disk data structures by limiting access to writeable blocks.
+ *
+ * Clients should not fiddle with the block manager directly.
+ */
+
+void dm_tm_destroy(struct dm_transaction_manager *tm);
+
+/*
+ * The non-blocking version of a transaction manager is intended for use in
+ * fast path code that needs to do lookups e.g. a dm mapping function.
+ * You create the non-blocking variant from a normal tm.  The interface is
+ * the same, except that most functions will just return -EWOULDBLOCK.
+ * Methods that return void yet may block should not be called on a clone
+ * viz. dm_tm_inc, dm_tm_dec.  Call dm_tm_destroy() as you would with a normal
+ * tm when you've finished with it.  You may not destroy the original prior
+ * to clones.
+ */
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real);
+
+/*
+ * We use a 2-phase commit here.
+ *
+ * i) In the first phase the block manager is told to start flushing, and
+ * the changes to the space map are written to disk.  You should interrogate
+ * your particular space map to get detail of its root node etc. to be
+ * included in your superblock.
+ *
+ * ii) @root will be committed last.  You shouldn't use more than the
+ * first 512 bytes of @root if you wish the transaction to survive a power
+ * failure.  You *must* have a write lock held on @root for both stage (i)
+ * and (ii).  The commit will drop the write lock.
+ */
+int dm_tm_pre_commit(struct dm_transaction_manager *tm);
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root);
+
+/*
+ * These methods are the only way to get hold of a writeable block.
+ */
+
+/*
+ * dm_tm_new_block() is pretty self-explanatory.  Make sure you do actually
+ * write to the whole of @data before you unlock, otherwise you could get
+ * a data leak.  (The other option is for tm_new_block() to zero new blocks
+ * before handing them out, which will be redundant in most, if not all,
+ * cases).
+ * Zeroes the new block and returns with write lock held.
+ */
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+/*
+ * dm_tm_shadow_block() allocates a new block and copies the data from @orig
+ * to it.  It then decrements the reference count on original block.  Use
+ * this to update the contents of a block in a data structure, don't
+ * confuse this with a clone - you shouldn't access the orig block after
+ * this operation.  Because the tm knows the scope of the transaction it
+ * can optimise requests for a shadow of a shadow to a no-op.  Don't forget
+ * to unlock when you've finished with the shadow.
+ *
+ * The @inc_children flag is used to tell the caller whether it needs to
+ * adjust reference counts for children.  (Data in the block may refer to
+ * other blocks.)
+ *
+ * Shadowing implicitly drops a reference on @orig so you must not have
+ * it locked when you call this.
+ */
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v,
+		       struct dm_block **result, int *inc_children);
+
+/*
+ * Read access.  You can lock any block you want.  If there's a write lock
+ * on it outstanding then it'll block.
+ */
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
+
+/*
+ * Functions for altering the reference count of a block directly.
+ */
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result);
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm);
+
+/*
+ * A little utility that ties the knot by producing a transaction manager
+ * that has a space map managed by the transaction manager...
+ *
+ * Returns a tm that has an open transaction to write the new disk sm.
+ * Caller should store the new sm root and commit.
+ */
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock);
+
+#endif	/* _LINUX_DM_TRANSACTION_MANAGER_H */
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/Kconfig linux-libre-3.2-gnu1/drivers/md/persistent-data/Kconfig
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+config DM_PERSISTENT_DATA
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select LIBCRC32C
+       select DM_BUFIO
+       ---help---
+	 Library providing immutable on-disk data structure support for
+	 device-mapper targets such as the thin provisioning target.
diff -druNp linux-libre-3.1-gnu1/drivers/md/persistent-data/Makefile linux-libre-3.2-gnu1/drivers/md/persistent-data/Makefile
--- linux-libre-3.1-gnu1/drivers/md/persistent-data/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/md/persistent-data/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o
+dm-persistent-data-objs := \
+	dm-block-manager.o \
+	dm-space-map-checker.o \
+	dm-space-map-common.o \
+	dm-space-map-disk.o \
+	dm-space-map-metadata.o \
+	dm-transaction-manager.o \
+	dm-btree.o \
+	dm-btree-remove.o \
+	dm-btree-spine.o
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid0.c linux-libre-3.2-gnu1/drivers/md/raid0.c
--- linux-libre-3.1-gnu1/drivers/md/raid0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid0.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include "md.h"
 #include "raid0.h"
@@ -27,9 +28,9 @@
 
 static int raid0_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	raid0_conf_t *conf = mddev->private;
-	mdk_rdev_t **devlist = conf->devlist;
+	struct mddev *mddev = data;
+	struct r0conf *conf = mddev->private;
+	struct md_rdev **devlist = conf->devlist;
 	int raid_disks = conf->strip_zone[0].nb_dev;
 	int i, ret = 0;
 
@@ -47,52 +48,53 @@ static int raid0_congested(void *data, i
 /*
  * inform the user of the raid configuration
 */
-static void dump_zones(mddev_t *mddev)
+static void dump_zones(struct mddev *mddev)
 {
-	int j, k, h;
+	int j, k;
 	sector_t zone_size = 0;
 	sector_t zone_start = 0;
 	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 	int raid_disks = conf->strip_zone[0].nb_dev;
-	printk(KERN_INFO "******* %s configuration *********\n",
-		mdname(mddev));
-	h = 0;
+	printk(KERN_INFO "md: RAID0 configuration for %s - %d zone%s\n",
+	       mdname(mddev),
+	       conf->nr_strip_zones, conf->nr_strip_zones==1?"":"s");
 	for (j = 0; j < conf->nr_strip_zones; j++) {
-		printk(KERN_INFO "zone%d=[", j);
+		printk(KERN_INFO "md: zone%d=[", j);
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			printk(KERN_CONT "%s/",
+			printk(KERN_CONT "%s%s", k?"/":"",
 			bdevname(conf->devlist[j*raid_disks
 						+ k]->bdev, b));
 		printk(KERN_CONT "]\n");
 
 		zone_size  = conf->strip_zone[j].zone_end - zone_start;
-		printk(KERN_INFO "        zone offset=%llukb "
-				"device offset=%llukb size=%llukb\n",
+		printk(KERN_INFO "      zone-offset=%10lluKB, "
+				"device-offset=%10lluKB, size=%10lluKB\n",
 			(unsigned long long)zone_start>>1,
 			(unsigned long long)conf->strip_zone[j].dev_start>>1,
 			(unsigned long long)zone_size>>1);
 		zone_start = conf->strip_zone[j].zone_end;
 	}
-	printk(KERN_INFO "**********************************\n\n");
+	printk(KERN_INFO "\n");
 }
 
-static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
+static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 {
 	int i, c, err;
 	sector_t curr_zone_end, sectors;
-	mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev, **dev;
+	struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
 	struct strip_zone *zone;
 	int cnt;
 	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+	char b2[BDEVNAME_SIZE];
+	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
 
 	if (!conf)
 		return -ENOMEM;
 	list_for_each_entry(rdev1, &mddev->disks, same_set) {
-		printk(KERN_INFO "md/raid0:%s: looking at %s\n",
-		       mdname(mddev),
-		       bdevname(rdev1->bdev, b));
+		pr_debug("md/raid0:%s: looking at %s\n",
+			 mdname(mddev),
+			 bdevname(rdev1->bdev, b));
 		c = 0;
 
 		/* round size to chunk_size */
@@ -101,16 +103,16 @@ static int create_strip_zones(mddev_t *m
 		rdev1->sectors = sectors * mddev->chunk_sectors;
 
 		list_for_each_entry(rdev2, &mddev->disks, same_set) {
-			printk(KERN_INFO "md/raid0:%s:   comparing %s(%llu)",
-			       mdname(mddev),
-			       bdevname(rdev1->bdev,b),
-			       (unsigned long long)rdev1->sectors);
-			printk(KERN_CONT " with %s(%llu)\n",
-			       bdevname(rdev2->bdev,b),
-			       (unsigned long long)rdev2->sectors);
+			pr_debug("md/raid0:%s:   comparing %s(%llu)"
+				 " with %s(%llu)\n",
+				 mdname(mddev),
+				 bdevname(rdev1->bdev,b),
+				 (unsigned long long)rdev1->sectors,
+				 bdevname(rdev2->bdev,b2),
+				 (unsigned long long)rdev2->sectors);
 			if (rdev2 == rdev1) {
-				printk(KERN_INFO "md/raid0:%s:   END\n",
-				       mdname(mddev));
+				pr_debug("md/raid0:%s:   END\n",
+					 mdname(mddev));
 				break;
 			}
 			if (rdev2->sectors == rdev1->sectors) {
@@ -118,30 +120,30 @@ static int create_strip_zones(mddev_t *m
 				 * Not unique, don't count it as a new
 				 * group
 				 */
-				printk(KERN_INFO "md/raid0:%s:   EQUAL\n",
-				       mdname(mddev));
+				pr_debug("md/raid0:%s:   EQUAL\n",
+					 mdname(mddev));
 				c = 1;
 				break;
 			}
-			printk(KERN_INFO "md/raid0:%s:   NOT EQUAL\n",
-			       mdname(mddev));
+			pr_debug("md/raid0:%s:   NOT EQUAL\n",
+				 mdname(mddev));
 		}
 		if (!c) {
-			printk(KERN_INFO "md/raid0:%s:   ==> UNIQUE\n",
-			       mdname(mddev));
+			pr_debug("md/raid0:%s:   ==> UNIQUE\n",
+				 mdname(mddev));
 			conf->nr_strip_zones++;
-			printk(KERN_INFO "md/raid0:%s: %d zones\n",
-			       mdname(mddev), conf->nr_strip_zones);
+			pr_debug("md/raid0:%s: %d zones\n",
+				 mdname(mddev), conf->nr_strip_zones);
 		}
 	}
-	printk(KERN_INFO "md/raid0:%s: FINAL %d zones\n",
-	       mdname(mddev), conf->nr_strip_zones);
+	pr_debug("md/raid0:%s: FINAL %d zones\n",
+		 mdname(mddev), conf->nr_strip_zones);
 	err = -ENOMEM;
 	conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
 				conf->nr_strip_zones, GFP_KERNEL);
 	if (!conf->strip_zone)
 		goto abort;
-	conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
+	conf->devlist = kzalloc(sizeof(struct md_rdev*)*
 				conf->nr_strip_zones*mddev->raid_disks,
 				GFP_KERNEL);
 	if (!conf->devlist)
@@ -218,44 +220,45 @@ static int create_strip_zones(mddev_t *m
 		zone = conf->strip_zone + i;
 		dev = conf->devlist + i * mddev->raid_disks;
 
-		printk(KERN_INFO "md/raid0:%s: zone %d\n",
-		       mdname(mddev), i);
+		pr_debug("md/raid0:%s: zone %d\n", mdname(mddev), i);
 		zone->dev_start = smallest->sectors;
 		smallest = NULL;
 		c = 0;
 
 		for (j=0; j<cnt; j++) {
 			rdev = conf->devlist[j];
-			printk(KERN_INFO "md/raid0:%s: checking %s ...",
-			       mdname(mddev),
-			       bdevname(rdev->bdev, b));
 			if (rdev->sectors <= zone->dev_start) {
-				printk(KERN_CONT " nope.\n");
+				pr_debug("md/raid0:%s: checking %s ... nope\n",
+					 mdname(mddev),
+					 bdevname(rdev->bdev, b));
 				continue;
 			}
-			printk(KERN_CONT " contained as device %d\n", c);
+			pr_debug("md/raid0:%s: checking %s ..."
+				 " contained as device %d\n",
+				 mdname(mddev),
+				 bdevname(rdev->bdev, b), c);
 			dev[c] = rdev;
 			c++;
 			if (!smallest || rdev->sectors < smallest->sectors) {
 				smallest = rdev;
-				printk(KERN_INFO "md/raid0:%s:  (%llu) is smallest!.\n",
-				       mdname(mddev),
-				       (unsigned long long)rdev->sectors);
+				pr_debug("md/raid0:%s:  (%llu) is smallest!.\n",
+					 mdname(mddev),
+					 (unsigned long long)rdev->sectors);
 			}
 		}
 
 		zone->nb_dev = c;
 		sectors = (smallest->sectors - zone->dev_start) * c;
-		printk(KERN_INFO "md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
-		       mdname(mddev),
-		       zone->nb_dev, (unsigned long long)sectors);
+		pr_debug("md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
+			 mdname(mddev),
+			 zone->nb_dev, (unsigned long long)sectors);
 
 		curr_zone_end += sectors;
 		zone->zone_end = curr_zone_end;
 
-		printk(KERN_INFO "md/raid0:%s: current zone start: %llu\n",
-		       mdname(mddev),
-		       (unsigned long long)smallest->sectors);
+		pr_debug("md/raid0:%s: current zone start: %llu\n",
+			 mdname(mddev),
+			 (unsigned long long)smallest->sectors);
 	}
 	mddev->queue->backing_dev_info.congested_fn = raid0_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
@@ -275,7 +278,7 @@ static int create_strip_zones(mddev_t *m
 	blk_queue_io_opt(mddev->queue,
 			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
-	printk(KERN_INFO "md/raid0:%s: done.\n", mdname(mddev));
+	pr_debug("md/raid0:%s: done.\n", mdname(mddev));
 	*private_conf = conf;
 
 	return 0;
@@ -299,7 +302,7 @@ static int raid0_mergeable_bvec(struct r
 				struct bvec_merge_data *bvm,
 				struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -318,10 +321,10 @@ static int raid0_mergeable_bvec(struct r
 		return max;
 }
 
-static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	sector_t array_sectors = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	WARN_ONCE(sectors || raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -332,9 +335,9 @@ static sector_t raid0_size(mddev_t *mdde
 	return array_sectors;
 }
 
-static int raid0_run(mddev_t *mddev)
+static int raid0_run(struct mddev *mddev)
 {
-	raid0_conf_t *conf;
+	struct r0conf *conf;
 	int ret;
 
 	if (mddev->chunk_sectors == 0) {
@@ -382,9 +385,9 @@ static int raid0_run(mddev_t *mddev)
 	return md_integrity_register(mddev);
 }
 
-static int raid0_stop(mddev_t *mddev)
+static int raid0_stop(struct mddev *mddev)
 {
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	kfree(conf->strip_zone);
@@ -397,7 +400,7 @@ static int raid0_stop(mddev_t *mddev)
 /* Find the zone which holds a particular offset
  * Update *sectorp to be an offset in that zone
  */
-static struct strip_zone *find_zone(struct raid0_private_data *conf,
+static struct strip_zone *find_zone(struct r0conf *conf,
 				    sector_t *sectorp)
 {
 	int i;
@@ -417,12 +420,12 @@ static struct strip_zone *find_zone(stru
  * remaps the bio to the target device. we separate two flows.
  * power 2 flow and a general flow for the sake of perfromance
 */
-static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
+static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
 				sector_t sector, sector_t *sector_offset)
 {
 	unsigned int sect_in_chunk;
 	sector_t chunk;
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 	int raid_disks = conf->strip_zone[0].nb_dev;
 	unsigned int chunk_sects = mddev->chunk_sectors;
 
@@ -453,7 +456,7 @@ static mdk_rdev_t *map_sector(mddev_t *m
 /*
  * Is io distribute over 1 or more chunks ?
 */
-static inline int is_io_in_chunk_boundary(mddev_t *mddev,
+static inline int is_io_in_chunk_boundary(struct mddev *mddev,
 			unsigned int chunk_sects, struct bio *bio)
 {
 	if (likely(is_power_of_2(chunk_sects))) {
@@ -466,16 +469,16 @@ static inline int is_io_in_chunk_boundar
 	}
 }
 
-static int raid0_make_request(mddev_t *mddev, struct bio *bio)
+static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
 	unsigned int chunk_sects;
 	sector_t sector_offset;
 	struct strip_zone *zone;
-	mdk_rdev_t *tmp_dev;
+	struct md_rdev *tmp_dev;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	chunk_sects = mddev->chunk_sectors;
@@ -495,13 +498,10 @@ static int raid0_make_request(mddev_t *m
 		else
 			bp = bio_split(bio, chunk_sects -
 				       sector_div(sector, chunk_sects));
-		if (raid0_make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (raid0_make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
-
+		raid0_make_request(mddev, &bp->bio1);
+		raid0_make_request(mddev, &bp->bio2);
 		bio_pair_release(bp);
-		return 0;
+		return;
 	}
 
 	sector_offset = bio->bi_sector;
@@ -511,10 +511,9 @@ static int raid0_make_request(mddev_t *m
 	bio->bi_bdev = tmp_dev->bdev;
 	bio->bi_sector = sector_offset + zone->dev_start +
 		tmp_dev->data_offset;
-	/*
-	 * Let the main block layer submit the IO and resolve recursion:
-	 */
-	return 1;
+
+	generic_make_request(bio);
+	return;
 
 bad_map:
 	printk("md/raid0:%s: make_request bug: can't convert block across chunks"
@@ -523,46 +522,19 @@ bad_map:
 	       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
 	bio_io_error(bio);
-	return 0;
+	return;
 }
 
-static void raid0_status(struct seq_file *seq, mddev_t *mddev)
+static void raid0_status(struct seq_file *seq, struct mddev *mddev)
 {
-#undef MD_DEBUG
-#ifdef MD_DEBUG
-	int j, k, h;
-	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = mddev->private;
-	int raid_disks = conf->strip_zone[0].nb_dev;
-
-	sector_t zone_size;
-	sector_t zone_start = 0;
-	h = 0;
-
-	for (j = 0; j < conf->nr_strip_zones; j++) {
-		seq_printf(seq, "      z%d", j);
-		seq_printf(seq, "=[");
-		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			seq_printf(seq, "%s/", bdevname(
-				conf->devlist[j*raid_disks + k]
-						->bdev, b));
-
-		zone_size  = conf->strip_zone[j].zone_end - zone_start;
-		seq_printf(seq, "] ze=%lld ds=%lld s=%lld\n",
-			(unsigned long long)zone_start>>1,
-			(unsigned long long)conf->strip_zone[j].dev_start>>1,
-			(unsigned long long)zone_size>>1);
-		zone_start = conf->strip_zone[j].zone_end;
-	}
-#endif
 	seq_printf(seq, " %dk chunks", mddev->chunk_sectors / 2);
 	return;
 }
 
-static void *raid0_takeover_raid45(mddev_t *mddev)
+static void *raid0_takeover_raid45(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
-	raid0_conf_t *priv_conf;
+	struct md_rdev *rdev;
+	struct r0conf *priv_conf;
 
 	if (mddev->degraded != 1) {
 		printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
@@ -593,9 +565,9 @@ static void *raid0_takeover_raid45(mddev
 	return priv_conf;
 }
 
-static void *raid0_takeover_raid10(mddev_t *mddev)
+static void *raid0_takeover_raid10(struct mddev *mddev)
 {
-	raid0_conf_t *priv_conf;
+	struct r0conf *priv_conf;
 
 	/* Check layout:
 	 *  - far_copies must be 1
@@ -634,9 +606,9 @@ static void *raid0_takeover_raid10(mddev
 	return priv_conf;
 }
 
-static void *raid0_takeover_raid1(mddev_t *mddev)
+static void *raid0_takeover_raid1(struct mddev *mddev)
 {
-	raid0_conf_t *priv_conf;
+	struct r0conf *priv_conf;
 
 	/* Check layout:
 	 *  - (N - 1) mirror drives must be already faulty
@@ -660,7 +632,7 @@ static void *raid0_takeover_raid1(mddev_
 	return priv_conf;
 }
 
-static void *raid0_takeover(mddev_t *mddev)
+static void *raid0_takeover(struct mddev *mddev)
 {
 	/* raid0 can take over:
 	 *  raid4 - if all data disks are active.
@@ -691,11 +663,11 @@ static void *raid0_takeover(mddev_t *mdd
 	return ERR_PTR(-EINVAL);
 }
 
-static void raid0_quiesce(mddev_t *mddev, int state)
+static void raid0_quiesce(struct mddev *mddev, int state)
 {
 }
 
-static struct mdk_personality raid0_personality=
+static struct md_personality raid0_personality=
 {
 	.name		= "raid0",
 	.level		= 0,
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid0.h linux-libre-3.2-gnu1/drivers/md/raid0.h
--- linux-libre-3.1-gnu1/drivers/md/raid0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid0.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,20 +1,16 @@
 #ifndef _RAID0_H
 #define _RAID0_H
 
-struct strip_zone
-{
+struct strip_zone {
 	sector_t zone_end;	/* Start of the next zone (in sectors) */
 	sector_t dev_start;	/* Zone offset in real dev (in sectors) */
 	int nb_dev;		/* # of devices attached to the zone */
 };
 
-struct raid0_private_data
-{
+struct r0conf {
 	struct strip_zone *strip_zone;
-	mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
+	struct md_rdev **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
 	int nr_strip_zones;
 };
 
-typedef struct raid0_private_data raid0_conf_t;
-
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid10.c linux-libre-3.2-gnu1/drivers/md/raid10.c
--- linux-libre-3.1-gnu1/drivers/md/raid10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid10.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include "md.h"
@@ -58,13 +59,19 @@
  */
 #define	NR_RAID10_BIOS 256
 
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+/* When there are this many requests queue to be written by
+ * the raid10 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
+
+static void allow_barrier(struct r10conf *conf);
+static void lower_barrier(struct r10conf *conf);
 
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
-	conf_t *conf = data;
-	int size = offsetof(struct r10bio_s, devs[conf->copies]);
+	struct r10conf *conf = data;
+	int size = offsetof(struct r10bio, devs[conf->copies]);
 
 	/* allocate a r10bio with room for raid_disks entries in the bios array */
 	return kzalloc(size, gfp_flags);
@@ -92,9 +99,9 @@ static void r10bio_pool_free(void *r10_b
  */
 static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 {
-	conf_t *conf = data;
+	struct r10conf *conf = data;
 	struct page *page;
-	r10bio_t *r10_bio;
+	struct r10bio *r10_bio;
 	struct bio *bio;
 	int i, j;
 	int nalloc;
@@ -158,8 +165,8 @@ out_free_bio:
 static void r10buf_pool_free(void *__r10_bio, void *data)
 {
 	int i;
-	conf_t *conf = data;
-	r10bio_t *r10bio = __r10_bio;
+	struct r10conf *conf = data;
+	struct r10bio *r10bio = __r10_bio;
 	int j;
 
 	for (j=0; j < conf->copies; j++) {
@@ -175,7 +182,7 @@ static void r10buf_pool_free(void *__r10
 	r10bio_pool_free(r10bio, conf);
 }
 
-static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
+static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio)
 {
 	int i;
 
@@ -187,28 +194,28 @@ static void put_all_bios(conf_t *conf, r
 	}
 }
 
-static void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	put_all_bios(conf, r10_bio);
 	mempool_free(r10_bio, conf->r10bio_pool);
 }
 
-static void put_buf(r10bio_t *r10_bio)
+static void put_buf(struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	mempool_free(r10_bio, conf->r10buf_pool);
 
 	lower_barrier(conf);
 }
 
-static void reschedule_retry(r10bio_t *r10_bio)
+static void reschedule_retry(struct r10bio *r10_bio)
 {
 	unsigned long flags;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r10_bio->retry_list, &conf->retry_list);
@@ -226,11 +233,11 @@ static void reschedule_retry(r10bio_t *r
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void raid_end_bio_io(r10bio_t *r10_bio)
+static void raid_end_bio_io(struct r10bio *r10_bio)
 {
 	struct bio *bio = r10_bio->master_bio;
 	int done;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	if (bio->bi_phys_segments) {
 		unsigned long flags;
@@ -256,9 +263,9 @@ static void raid_end_bio_io(r10bio_t *r1
 /*
  * Update disk head position estimator based on IRQ completion info.
  */
-static inline void update_head_pos(int slot, r10bio_t *r10_bio)
+static inline void update_head_pos(int slot, struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	conf->mirrors[r10_bio->devs[slot].devnum].head_position =
 		r10_bio->devs[slot].addr + (r10_bio->sectors);
@@ -267,7 +274,7 @@ static inline void update_head_pos(int s
 /*
  * Find the disk number which triggered given bio
  */
-static int find_bio_disk(conf_t *conf, r10bio_t *r10_bio,
+static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
 			 struct bio *bio, int *slotp)
 {
 	int slot;
@@ -287,9 +294,9 @@ static int find_bio_disk(conf_t *conf, r
 static void raid10_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
+	struct r10bio *r10_bio = bio->bi_private;
 	int slot, dev;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 
 	slot = r10_bio->read_slot;
@@ -327,7 +334,7 @@ static void raid10_end_read_request(stru
 	}
 }
 
-static void close_write(r10bio_t *r10_bio)
+static void close_write(struct r10bio *r10_bio)
 {
 	/* clear the bitmap if all writes complete successfully */
 	bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
@@ -337,7 +344,7 @@ static void close_write(r10bio_t *r10_bi
 	md_write_end(r10_bio->mddev);
 }
 
-static void one_write_done(r10bio_t *r10_bio)
+static void one_write_done(struct r10bio *r10_bio)
 {
 	if (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (test_bit(R10BIO_WriteError, &r10_bio->state))
@@ -355,10 +362,10 @@ static void one_write_done(r10bio_t *r10
 static void raid10_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
+	struct r10bio *r10_bio = bio->bi_private;
 	int dev;
 	int dec_rdev = 1;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 	int slot;
 
 	dev = find_bio_disk(conf, r10_bio, bio, &slot);
@@ -433,7 +440,7 @@ static void raid10_end_write_request(str
  * sector offset to a virtual address
  */
 
-static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
+static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
 {
 	int n,f;
 	sector_t sector;
@@ -481,7 +488,7 @@ static void raid10_find_phys(conf_t *con
 	BUG_ON(slot != conf->copies);
 }
 
-static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
+static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
 {
 	sector_t offset, chunk, vchunk;
 
@@ -522,7 +529,7 @@ static int raid10_mergeable_bvec(struct
 				 struct bvec_merge_data *bvm,
 				 struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -555,14 +562,14 @@ static int raid10_mergeable_bvec(struct
  * FIXME: possibly should rethink readbalancing and do it differently
  * depending on near_copies / far_copies geometry.
  */
-static int read_balance(conf_t *conf, r10bio_t *r10_bio, int *max_sectors)
+static int read_balance(struct r10conf *conf, struct r10bio *r10_bio, int *max_sectors)
 {
 	const sector_t this_sector = r10_bio->sector;
 	int disk, slot;
 	int sectors = r10_bio->sectors;
 	int best_good_sectors;
 	sector_t new_distance, best_dist;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int do_balance;
 	int best_slot;
 
@@ -677,15 +684,19 @@ retry:
 
 static int raid10_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = data;
+	struct r10conf *conf = mddev->private;
 	int i, ret = 0;
 
+	if ((bits & (1 << BDI_async_congested)) &&
+	    conf->pending_count >= max_queued_requests)
+		return 1;
+
 	if (mddev_congested(mddev, bits))
 		return 1;
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks && ret == 0; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -696,7 +707,7 @@ static int raid10_congested(void *data,
 	return ret;
 }
 
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r10conf *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
@@ -706,10 +717,12 @@ static void flush_pending_writes(conf_t
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		conf->pending_count = 0;
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to disk
 		 * before proceeding w/ I/O */
 		bitmap_unplug(conf->mddev->bitmap);
+		wake_up(&conf->wait_barrier);
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
@@ -743,7 +756,7 @@ static void flush_pending_writes(conf_t
  *    lower_barrier when the particular background IO completes.
  */
 
-static void raise_barrier(conf_t *conf, int force)
+static void raise_barrier(struct r10conf *conf, int force)
 {
 	BUG_ON(force && !conf->barrier);
 	spin_lock_irq(&conf->resync_lock);
@@ -763,7 +776,7 @@ static void raise_barrier(conf_t *conf,
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r10conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -772,7 +785,7 @@ static void lower_barrier(conf_t *conf)
 	wake_up(&conf->wait_barrier);
 }
 
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r10conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
@@ -786,7 +799,7 @@ static void wait_barrier(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r10conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -795,7 +808,7 @@ static void allow_barrier(conf_t *conf)
 	wake_up(&conf->wait_barrier);
 }
 
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r10conf *conf)
 {
 	/* stop syncio and normal IO and wait for everything to
 	 * go quiet.
@@ -820,7 +833,7 @@ static void freeze_array(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r10conf *conf)
 {
 	/* reverse the effect of the freeze */
 	spin_lock_irq(&conf->resync_lock);
@@ -830,11 +843,11 @@ static void unfreeze_array(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static int make_request(mddev_t *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
-	conf_t *conf = mddev->private;
-	mirror_info_t *mirror;
-	r10bio_t *r10_bio;
+	struct r10conf *conf = mddev->private;
+	struct mirror_info *mirror;
+	struct r10bio *r10_bio;
 	struct bio *read_bio;
 	int i;
 	int chunk_sects = conf->chunk_mask + 1;
@@ -842,14 +855,14 @@ static int make_request(mddev_t *mddev,
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	unsigned long flags;
-	mdk_rdev_t *blocked_rdev;
+	struct md_rdev *blocked_rdev;
 	int plugged;
 	int sectors_handled;
 	int max_sectors;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	/* If this request crosses a chunk boundary, we need to
@@ -881,10 +894,8 @@ static int make_request(mddev_t *mddev,
 		conf->nr_waiting++;
 		spin_unlock_irq(&conf->resync_lock);
 
-		if (make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
+		make_request(mddev, &bp->bio1);
+		make_request(mddev, &bp->bio2);
 
 		spin_lock_irq(&conf->resync_lock);
 		conf->nr_waiting--;
@@ -892,14 +903,14 @@ static int make_request(mddev_t *mddev,
 		spin_unlock_irq(&conf->resync_lock);
 
 		bio_pair_release(bp);
-		return 0;
+		return;
 	bad_map:
 		printk("md/raid10:%s: make_request bug: can't convert block across chunks"
 		       " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
 		       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 
 	md_write_start(mddev, bio);
@@ -942,7 +953,7 @@ read_again:
 		slot = r10_bio->read_slot;
 		if (disk < 0) {
 			raid_end_bio_io(r10_bio);
-			return 0;
+			return;
 		}
 		mirror = conf->mirrors + disk;
 
@@ -990,12 +1001,17 @@ read_again:
 			goto read_again;
 		} else
 			generic_make_request(read_bio);
-		return 0;
+		return;
 	}
 
 	/*
 	 * WRITE:
 	 */
+	if (conf->pending_count >= max_queued_requests) {
+		md_wakeup_thread(mddev->thread);
+		wait_event(conf->wait_barrier,
+			   conf->pending_count < max_queued_requests);
+	}
 	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
@@ -1017,7 +1033,7 @@ retry_write:
 
 	for (i = 0;  i < conf->copies; i++) {
 		int d = r10_bio->devs[i].devnum;
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
 		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
 			atomic_inc(&rdev->nr_pending);
 			blocked_rdev = rdev;
@@ -1129,6 +1145,7 @@ retry_write:
 		atomic_inc(&r10_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
+		conf->pending_count++;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 
@@ -1158,12 +1175,11 @@ retry_write:
 
 	if (do_sync || !mddev->bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
-	return 0;
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int i;
 
 	if (conf->near_copies < conf->raid_disks)
@@ -1190,7 +1206,7 @@ static void status(struct seq_file *seq,
  * Don't consider the device numbered 'ignore'
  * as we might be about to remove it.
  */
-static int enough(conf_t *conf, int ignore)
+static int enough(struct r10conf *conf, int ignore)
 {
 	int first = 0;
 
@@ -1209,10 +1225,10 @@ static int enough(conf_t *conf, int igno
 	return 1;
 }
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1246,10 +1262,10 @@ static void error(mddev_t *mddev, mdk_rd
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
 
-static void print_conf(conf_t *conf)
+static void print_conf(struct r10conf *conf)
 {
 	int i;
-	mirror_info_t *tmp;
+	struct mirror_info *tmp;
 
 	printk(KERN_DEBUG "RAID10 conf printout:\n");
 	if (!conf) {
@@ -1270,7 +1286,7 @@ static void print_conf(conf_t *conf)
 	}
 }
 
-static void close_sync(conf_t *conf)
+static void close_sync(struct r10conf *conf)
 {
 	wait_barrier(conf);
 	allow_barrier(conf);
@@ -1279,11 +1295,11 @@ static void close_sync(conf_t *conf)
 	conf->r10buf_pool = NULL;
 }
 
-static int raid10_spare_active(mddev_t *mddev)
+static int raid10_spare_active(struct mddev *mddev)
 {
 	int i;
-	conf_t *conf = mddev->private;
-	mirror_info_t *tmp;
+	struct r10conf *conf = mddev->private;
+	struct mirror_info *tmp;
 	int count = 0;
 	unsigned long flags;
 
@@ -1309,9 +1325,9 @@ static int raid10_spare_active(mddev_t *
 }
 
 
-static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int err = -EEXIST;
 	int mirror;
 	int first = 0;
@@ -1334,10 +1350,10 @@ static int raid10_add_disk(mddev_t *mdde
 	else
 		mirror = first;
 	for ( ; mirror <= last ; mirror++) {
-		mirror_info_t *p = &conf->mirrors[mirror];
+		struct mirror_info *p = &conf->mirrors[mirror];
 		if (p->recovery_disabled == mddev->recovery_disabled)
 			continue;
-		if (!p->rdev)
+		if (p->rdev)
 			continue;
 
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
@@ -1355,6 +1371,7 @@ static int raid10_add_disk(mddev_t *mdde
 		}
 
 		p->head_position = 0;
+		p->recovery_disabled = mddev->recovery_disabled - 1;
 		rdev->raid_disk = mirror;
 		err = 0;
 		if (rdev->saved_raid_disk != mirror)
@@ -1368,12 +1385,12 @@ static int raid10_add_disk(mddev_t *mdde
 	return err;
 }
 
-static int raid10_remove_disk(mddev_t *mddev, int number)
+static int raid10_remove_disk(struct mddev *mddev, int number)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
-	mirror_info_t *p = conf->mirrors+ number;
+	struct md_rdev *rdev;
+	struct mirror_info *p = conf->mirrors+ number;
 
 	print_conf(conf);
 	rdev = p->rdev;
@@ -1411,8 +1428,8 @@ abort:
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r10bio_t *r10_bio = bio->bi_private;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10bio *r10_bio = bio->bi_private;
+	struct r10conf *conf = r10_bio->mddev->private;
 	int d;
 
 	d = find_bio_disk(conf, r10_bio, bio, NULL);
@@ -1439,9 +1456,9 @@ static void end_sync_read(struct bio *bi
 	}
 }
 
-static void end_sync_request(r10bio_t *r10_bio)
+static void end_sync_request(struct r10bio *r10_bio)
 {
-	mddev_t *mddev = r10_bio->mddev;
+	struct mddev *mddev = r10_bio->mddev;
 
 	while (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (r10_bio->master_bio == NULL) {
@@ -1455,7 +1472,7 @@ static void end_sync_request(r10bio_t *r
 			md_done_sync(mddev, s, 1);
 			break;
 		} else {
-			r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
+			struct r10bio *r10_bio2 = (struct r10bio *)r10_bio->master_bio;
 			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
 			    test_bit(R10BIO_WriteError, &r10_bio->state))
 				reschedule_retry(r10_bio);
@@ -1469,9 +1486,9 @@ static void end_sync_request(r10bio_t *r
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct r10bio *r10_bio = bio->bi_private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 	int d;
 	sector_t first_bad;
 	int bad_sectors;
@@ -1509,9 +1526,9 @@ static void end_sync_write(struct bio *b
  * We check if all blocks are in-sync and only write to blocks that
  * aren't in sync
  */
-static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int i, first;
 	struct bio *tbio, *fbio;
 
@@ -1609,7 +1626,7 @@ done:
  * The second for writing.
  *
  */
-static void fix_recovery_read_error(r10bio_t *r10_bio)
+static void fix_recovery_read_error(struct r10bio *r10_bio)
 {
 	/* We got a read error during recovery.
 	 * We repeat the read in smaller page-sized sections.
@@ -1618,8 +1635,8 @@ static void fix_recovery_read_error(r10b
 	 * If a read fails, record a bad block on both old and
 	 * new devices.
 	 */
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 	struct bio *bio = r10_bio->devs[0].bio;
 	sector_t sect = 0;
 	int sectors = r10_bio->sectors;
@@ -1629,7 +1646,7 @@ static void fix_recovery_read_error(r10b
 
 	while (sectors) {
 		int s = sectors;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		sector_t addr;
 		int ok;
 
@@ -1663,7 +1680,7 @@ static void fix_recovery_read_error(r10b
 
 			if (rdev != conf->mirrors[dw].rdev) {
 				/* need bad block on destination too */
-				mdk_rdev_t *rdev2 = conf->mirrors[dw].rdev;
+				struct md_rdev *rdev2 = conf->mirrors[dw].rdev;
 				addr = r10_bio->devs[1].addr + sect;
 				ok = rdev_set_badblocks(rdev2, addr, s, 0);
 				if (!ok) {
@@ -1688,9 +1705,9 @@ static void fix_recovery_read_error(r10b
 	}
 }
 
-static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int d;
 	struct bio *wbio;
 
@@ -1719,7 +1736,7 @@ static void recovery_request_write(mddev
  * since the last recorded read error.
  *
  */
-static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
+static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct timespec cur_time_mon;
 	unsigned long hours_since_last;
@@ -1750,7 +1767,7 @@ static void check_decay_read_errors(mdde
 		atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
 }
 
-static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
 			    int sectors, struct page *page, int rw)
 {
 	sector_t first_bad;
@@ -1778,11 +1795,11 @@ static int r10_sync_page_io(mdk_rdev_t *
  *	3.	Performs writes following reads for array synchronising.
  */
 
-static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
+static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10bio *r10_bio)
 {
 	int sect = 0; /* Offset from r10_bio->sector */
 	int sectors = r10_bio->sectors;
-	mdk_rdev_t*rdev;
+	struct md_rdev*rdev;
 	int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
 	int d = r10_bio->devs[r10_bio->read_slot].devnum;
 
@@ -1983,12 +2000,12 @@ static int submit_bio_wait(int rw, struc
 	return test_bit(BIO_UPTODATE, &bio->bi_flags);
 }
 
-static int narrow_write_error(r10bio_t *r10_bio, int i)
+static int narrow_write_error(struct r10bio *r10_bio, int i)
 {
 	struct bio *bio = r10_bio->master_bio;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
+	struct md_rdev *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
 	/* bio has the data to be written to slot 'i' where
 	 * we just recently had a write error.
 	 * We repeatedly clone the bio and trim down to one block,
@@ -2040,13 +2057,13 @@ static int narrow_write_error(r10bio_t *
 	return ok;
 }
 
-static void handle_read_error(mddev_t *mddev, r10bio_t *r10_bio)
+static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
 {
 	int slot = r10_bio->read_slot;
 	int mirror = r10_bio->devs[slot].devnum;
 	struct bio *bio;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev;
+	struct r10conf *conf = mddev->private;
+	struct md_rdev *rdev;
 	char b[BDEVNAME_SIZE];
 	unsigned long do_sync;
 	int max_sectors;
@@ -2139,7 +2156,7 @@ read_more:
 		generic_make_request(bio);
 }
 
-static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
+static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
 {
 	/* Some sort of write request has finished and it
 	 * succeeded in writing where we thought there was a
@@ -2148,7 +2165,7 @@ static void handle_write_completed(conf_
 	 * a bad block.
 	 */
 	int m;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
 	    test_bit(R10BIO_IsRecover, &r10_bio->state)) {
@@ -2200,11 +2217,11 @@ static void handle_write_completed(conf_
 	}
 }
 
-static void raid10d(mddev_t *mddev)
+static void raid10d(struct mddev *mddev)
 {
-	r10bio_t *r10_bio;
+	struct r10bio *r10_bio;
 	unsigned long flags;
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	struct blk_plug plug;
 
@@ -2220,7 +2237,7 @@ static void raid10d(mddev_t *mddev)
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			break;
 		}
-		r10_bio = list_entry(head->prev, r10bio_t, retry_list);
+		r10_bio = list_entry(head->prev, struct r10bio, retry_list);
 		list_del(head->prev);
 		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2252,7 +2269,7 @@ static void raid10d(mddev_t *mddev)
 }
 
 
-static int init_resync(conf_t *conf)
+static int init_resync(struct r10conf *conf)
 {
 	int buffs;
 
@@ -2297,11 +2314,11 @@ static int init_resync(conf_t *conf)
  *
  */
 
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 			     int *skipped, int go_faster)
 {
-	conf_t *conf = mddev->private;
-	r10bio_t *r10_bio;
+	struct r10conf *conf = mddev->private;
+	struct r10bio *r10_bio;
 	struct bio *biolist = NULL, *bio;
 	sector_t max_sector, nr_sectors;
 	int i;
@@ -2393,7 +2410,7 @@ static sector_t sync_request(mddev_t *md
 
 		for (i=0 ; i<conf->raid_disks; i++) {
 			int still_degraded;
-			r10bio_t *rb2;
+			struct r10bio *rb2;
 			sector_t sect;
 			int must_sync;
 			int any_working;
@@ -2453,7 +2470,7 @@ static sector_t sync_request(mddev_t *md
 				int k;
 				int d = r10_bio->devs[j].devnum;
 				sector_t from_addr, to_addr;
-				mdk_rdev_t *rdev;
+				struct md_rdev *rdev;
 				sector_t sector, first_bad;
 				int bad_sectors;
 				if (!conf->mirrors[d].rdev ||
@@ -2547,8 +2564,8 @@ static sector_t sync_request(mddev_t *md
 		}
 		if (biolist == NULL) {
 			while (r10_bio) {
-				r10bio_t *rb2 = r10_bio;
-				r10_bio = (r10bio_t*) rb2->master_bio;
+				struct r10bio *rb2 = r10_bio;
+				r10_bio = (struct r10bio*) rb2->master_bio;
 				rb2->master_bio = NULL;
 				put_buf(rb2);
 			}
@@ -2714,10 +2731,10 @@ static sector_t sync_request(mddev_t *md
 }
 
 static sector_t
-raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	sector_t size;
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	if (!raid_disks)
 		raid_disks = conf->raid_disks;
@@ -2733,9 +2750,9 @@ raid10_size(mddev_t *mddev, sector_t sec
 }
 
 
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r10conf *setup_conf(struct mddev *mddev)
 {
-	conf_t *conf = NULL;
+	struct r10conf *conf = NULL;
 	int nc, fc, fo;
 	sector_t stride, size;
 	int err = -EINVAL;
@@ -2760,7 +2777,7 @@ static conf_t *setup_conf(mddev_t *mddev
 	}
 
 	err = -ENOMEM;
-	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r10conf), GFP_KERNEL);
 	if (!conf)
 		goto out;
 
@@ -2836,12 +2853,12 @@ static conf_t *setup_conf(mddev_t *mddev
 	return ERR_PTR(err);
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r10conf *conf;
 	int i, disk_idx, chunk_size;
-	mirror_info_t *disk;
-	mdk_rdev_t *rdev;
+	struct mirror_info *disk;
+	struct md_rdev *rdev;
 	sector_t size;
 
 	/*
@@ -2913,6 +2930,7 @@ static int run(mddev_t *mddev)
 			if (disk->rdev)
 				conf->fullsync = 1;
 		}
+		disk->recovery_disabled = mddev->recovery_disabled - 1;
 	}
 
 	if (mddev->recovery_cp != MaxSector)
@@ -2966,9 +2984,9 @@ out:
 	return -EIO;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	raise_barrier(conf, 0);
 	lower_barrier(conf);
@@ -2983,9 +3001,9 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
-static void raid10_quiesce(mddev_t *mddev, int state)
+static void raid10_quiesce(struct mddev *mddev, int state)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	switch(state) {
 	case 1:
@@ -2997,10 +3015,10 @@ static void raid10_quiesce(mddev_t *mdde
 	}
 }
 
-static void *raid10_takeover_raid0(mddev_t *mddev)
+static void *raid10_takeover_raid0(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
-	conf_t *conf;
+	struct md_rdev *rdev;
+	struct r10conf *conf;
 
 	if (mddev->degraded > 0) {
 		printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!\n",
@@ -3029,17 +3047,17 @@ static void *raid10_takeover_raid0(mddev
 	return conf;
 }
 
-static void *raid10_takeover(mddev_t *mddev)
+static void *raid10_takeover(struct mddev *mddev)
 {
-	struct raid0_private_data *raid0_priv;
+	struct r0conf *raid0_conf;
 
 	/* raid10 can take over:
 	 *  raid0 - providing it has only two drives
 	 */
 	if (mddev->level == 0) {
 		/* for raid0 takeover only one zone is supported */
-		raid0_priv = mddev->private;
-		if (raid0_priv->nr_strip_zones > 1) {
+		raid0_conf = mddev->private;
+		if (raid0_conf->nr_strip_zones > 1) {
 			printk(KERN_ERR "md/raid10:%s: cannot takeover raid 0"
 			       " with more than one zone.\n",
 			       mdname(mddev));
@@ -3050,7 +3068,7 @@ static void *raid10_takeover(mddev_t *md
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid10_personality =
+static struct md_personality raid10_personality =
 {
 	.name		= "raid10",
 	.level		= 10,
@@ -3086,3 +3104,5 @@ MODULE_DESCRIPTION("RAID10 (striped mirr
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
 MODULE_ALIAS("md-raid10");
 MODULE_ALIAS("md-level-10");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid10.h linux-libre-3.2-gnu1/drivers/md/raid10.h
--- linux-libre-3.1-gnu1/drivers/md/raid10.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid10.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,8 @@
 #ifndef _RAID10_H
 #define _RAID10_H
 
-typedef struct mirror_info mirror_info_t;
-
 struct mirror_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	head_position;
 	int		recovery_disabled;	/* matches
 						 * mddev->recovery_disabled
@@ -13,11 +11,9 @@ struct mirror_info {
 						 */
 };
 
-typedef struct r10bio_s r10bio_t;
-
-struct r10_private_data_s {
-	mddev_t			*mddev;
-	mirror_info_t		*mirrors;
+struct r10conf {
+	struct mddev		*mddev;
+	struct mirror_info	*mirrors;
 	int			raid_disks;
 	spinlock_t		device_lock;
 
@@ -46,7 +42,7 @@ struct r10_private_data_s {
 	struct list_head	retry_list;
 	/* queue pending writes and submit them on unplug */
 	struct bio_list		pending_bio_list;
-
+	int			pending_count;
 
 	spinlock_t		resync_lock;
 	int nr_pending;
@@ -68,11 +64,9 @@ struct r10_private_data_s {
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct r10_private_data_s conf_t;
-
 /*
  * this is our 'private' RAID10 bio.
  *
@@ -80,14 +74,14 @@ typedef struct r10_private_data_s conf_t
  * for this RAID10 operation, and about their status:
  */
 
-struct r10bio_s {
+struct r10bio {
 	atomic_t		remaining; /* 'have we finished' count,
 					    * used from IRQ handlers
 					    */
 	sector_t		sector;	/* virtual sector number */
 	int			sectors;
 	unsigned long		state;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	/*
 	 * original bio going to /dev/mdx
 	 */
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid1.c linux-libre-3.2-gnu1/drivers/md/raid1.c
--- linux-libre-3.1-gnu1/drivers/md/raid1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid1.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,28 +34,31 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include "md.h"
 #include "raid1.h"
 #include "bitmap.h"
 
-#define DEBUG 0
-#define PRINTK(x...) do { if (DEBUG) printk(x); } while (0)
-
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
 #define	NR_RAID1_BIOS 256
 
+/* When there are this many requests queue to be written by
+ * the raid1 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
 
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+static void allow_barrier(struct r1conf *conf);
+static void lower_barrier(struct r1conf *conf);
 
 static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
-	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
+	int size = offsetof(struct r1bio, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
 	return kzalloc(size, gfp_flags);
@@ -76,7 +79,7 @@ static void * r1buf_pool_alloc(gfp_t gfp
 {
 	struct pool_info *pi = data;
 	struct page *page;
-	r1bio_t *r1_bio;
+	struct r1bio *r1_bio;
 	struct bio *bio;
 	int i, j;
 
@@ -142,7 +145,7 @@ static void r1buf_pool_free(void *__r1_b
 {
 	struct pool_info *pi = data;
 	int i,j;
-	r1bio_t *r1bio = __r1_bio;
+	struct r1bio *r1bio = __r1_bio;
 
 	for (i = 0; i < RESYNC_PAGES; i++)
 		for (j = pi->raid_disks; j-- ;) {
@@ -157,7 +160,7 @@ static void r1buf_pool_free(void *__r1_b
 	r1bio_pool_free(r1bio, data);
 }
 
-static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
+static void put_all_bios(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int i;
 
@@ -169,17 +172,17 @@ static void put_all_bios(conf_t *conf, r
 	}
 }
 
-static void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	put_all_bios(conf, r1_bio);
 	mempool_free(r1_bio, conf->r1bio_pool);
 }
 
-static void put_buf(r1bio_t *r1_bio)
+static void put_buf(struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 	int i;
 
 	for (i=0; i<conf->raid_disks; i++) {
@@ -193,11 +196,11 @@ static void put_buf(r1bio_t *r1_bio)
 	lower_barrier(conf);
 }
 
-static void reschedule_retry(r1bio_t *r1_bio)
+static void reschedule_retry(struct r1bio *r1_bio)
 {
 	unsigned long flags;
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r1_bio->retry_list, &conf->retry_list);
@@ -213,11 +216,11 @@ static void reschedule_retry(r1bio_t *r1
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void call_bio_endio(r1bio_t *r1_bio)
+static void call_bio_endio(struct r1bio *r1_bio)
 {
 	struct bio *bio = r1_bio->master_bio;
 	int done;
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	if (bio->bi_phys_segments) {
 		unsigned long flags;
@@ -240,17 +243,17 @@ static void call_bio_endio(r1bio_t *r1_b
 	}
 }
 
-static void raid_end_bio_io(r1bio_t *r1_bio)
+static void raid_end_bio_io(struct r1bio *r1_bio)
 {
 	struct bio *bio = r1_bio->master_bio;
 
 	/* if nobody has done the final endio yet, do it now */
 	if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
-		PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
-			(bio_data_dir(bio) == WRITE) ? "write" : "read",
-			(unsigned long long) bio->bi_sector,
-			(unsigned long long) bio->bi_sector +
-				(bio->bi_size >> 9) - 1);
+		pr_debug("raid1: sync end %s on sectors %llu-%llu\n",
+			 (bio_data_dir(bio) == WRITE) ? "write" : "read",
+			 (unsigned long long) bio->bi_sector,
+			 (unsigned long long) bio->bi_sector +
+			 (bio->bi_size >> 9) - 1);
 
 		call_bio_endio(r1_bio);
 	}
@@ -260,20 +263,38 @@ static void raid_end_bio_io(r1bio_t *r1_
 /*
  * Update disk head position estimator based on IRQ completion info.
  */
-static inline void update_head_pos(int disk, r1bio_t *r1_bio)
+static inline void update_head_pos(int disk, struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	conf->mirrors[disk].head_position =
 		r1_bio->sector + (r1_bio->sectors);
 }
 
+/*
+ * Find the disk number which triggered given bio
+ */
+static int find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
+{
+	int mirror;
+	int raid_disks = r1_bio->mddev->raid_disks;
+
+	for (mirror = 0; mirror < raid_disks; mirror++)
+		if (r1_bio->bios[mirror] == bio)
+			break;
+
+	BUG_ON(mirror == raid_disks);
+	update_head_pos(mirror, r1_bio);
+
+	return mirror;
+}
+
 static void raid1_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
+	struct r1bio *r1_bio = bio->bi_private;
 	int mirror;
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	mirror = r1_bio->read_disk;
 	/*
@@ -318,7 +339,7 @@ static void raid1_end_read_request(struc
 	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 }
 
-static void close_write(r1bio_t *r1_bio)
+static void close_write(struct r1bio *r1_bio)
 {
 	/* it really is the end of this request */
 	if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
@@ -337,7 +358,7 @@ static void close_write(r1bio_t *r1_bio)
 	md_write_end(r1_bio->mddev);
 }
 
-static void r1_bio_write_done(r1bio_t *r1_bio)
+static void r1_bio_write_done(struct r1bio *r1_bio)
 {
 	if (!atomic_dec_and_test(&r1_bio->remaining))
 		return;
@@ -356,15 +377,12 @@ static void r1_bio_write_done(r1bio_t *r
 static void raid1_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
+	struct r1bio *r1_bio = bio->bi_private;
 	int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 	struct bio *to_put = NULL;
 
-
-	for (mirror = 0; mirror < conf->raid_disks; mirror++)
-		if (r1_bio->bios[mirror] == bio)
-			break;
+	mirror = find_bio_disk(r1_bio, bio);
 
 	/*
 	 * 'one mirror IO has finished' event handler:
@@ -400,8 +418,6 @@ static void raid1_end_write_request(stru
 		}
 	}
 
-	update_head_pos(mirror, r1_bio);
-
 	if (behind) {
 		if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
 			atomic_dec(&r1_bio->behind_remaining);
@@ -418,10 +434,11 @@ static void raid1_end_write_request(stru
 			/* Maybe we can return now */
 			if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
 				struct bio *mbio = r1_bio->master_bio;
-				PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
-				       (unsigned long long) mbio->bi_sector,
-				       (unsigned long long) mbio->bi_sector +
-				       (mbio->bi_size >> 9) - 1);
+				pr_debug("raid1: behind end write sectors"
+					 " %llu-%llu\n",
+					 (unsigned long long) mbio->bi_sector,
+					 (unsigned long long) mbio->bi_sector +
+					 (mbio->bi_size >> 9) - 1);
 				call_bio_endio(r1_bio);
 			}
 		}
@@ -455,7 +472,7 @@ static void raid1_end_write_request(stru
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
+static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors)
 {
 	const sector_t this_sector = r1_bio->sector;
 	int sectors;
@@ -464,7 +481,7 @@ static int read_balance(conf_t *conf, r1
 	int best_disk;
 	int i;
 	sector_t best_dist;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int choose_first;
 
 	rcu_read_lock();
@@ -582,14 +599,18 @@ static int read_balance(conf_t *conf, r1
 	return best_disk;
 }
 
-int md_raid1_congested(mddev_t *mddev, int bits)
+int md_raid1_congested(struct mddev *mddev, int bits)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i, ret = 0;
 
+	if ((bits & (1 << BDI_async_congested)) &&
+	    conf->pending_count >= max_queued_requests)
+		return 1;
+
 	rcu_read_lock();
 	for (i = 0; i < mddev->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -611,13 +632,13 @@ EXPORT_SYMBOL_GPL(md_raid1_congested);
 
 static int raid1_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
+	struct mddev *mddev = data;
 
 	return mddev_congested(mddev, bits) ||
 		md_raid1_congested(mddev, bits);
 }
 
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r1conf *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
@@ -627,10 +648,12 @@ static void flush_pending_writes(conf_t
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		conf->pending_count = 0;
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to
 		 * disk before proceeding w/ I/O */
 		bitmap_unplug(conf->mddev->bitmap);
+		wake_up(&conf->wait_barrier);
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
@@ -665,7 +688,7 @@ static void flush_pending_writes(conf_t
  */
 #define RESYNC_DEPTH 32
 
-static void raise_barrier(conf_t *conf)
+static void raise_barrier(struct r1conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 
@@ -684,7 +707,7 @@ static void raise_barrier(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r1conf *conf)
 {
 	unsigned long flags;
 	BUG_ON(conf->barrier <= 0);
@@ -694,7 +717,7 @@ static void lower_barrier(conf_t *conf)
 	wake_up(&conf->wait_barrier);
 }
 
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r1conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
@@ -708,7 +731,7 @@ static void wait_barrier(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r1conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -717,7 +740,7 @@ static void allow_barrier(conf_t *conf)
 	wake_up(&conf->wait_barrier);
 }
 
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r1conf *conf)
 {
 	/* stop syncio and normal IO and wait for everything to
 	 * go quite.
@@ -740,7 +763,7 @@ static void freeze_array(conf_t *conf)
 			    flush_pending_writes(conf));
 	spin_unlock_irq(&conf->resync_lock);
 }
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r1conf *conf)
 {
 	/* reverse the effect of the freeze */
 	spin_lock_irq(&conf->resync_lock);
@@ -753,7 +776,7 @@ static void unfreeze_array(conf_t *conf)
 
 /* duplicate the data pages for behind I/O 
  */
-static void alloc_behind_pages(struct bio *bio, r1bio_t *r1_bio)
+static void alloc_behind_pages(struct bio *bio, struct r1bio *r1_bio)
 {
 	int i;
 	struct bio_vec *bvec;
@@ -782,14 +805,14 @@ do_sync_io:
 		if (bvecs[i].bv_page)
 			put_page(bvecs[i].bv_page);
 	kfree(bvecs);
-	PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+	pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
 }
 
-static int make_request(mddev_t *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
-	conf_t *conf = mddev->private;
-	mirror_info_t *mirror;
-	r1bio_t *r1_bio;
+	struct r1conf *conf = mddev->private;
+	struct mirror_info *mirror;
+	struct r1bio *r1_bio;
 	struct bio *read_bio;
 	int i, disks;
 	struct bitmap *bitmap;
@@ -797,7 +820,7 @@ static int make_request(mddev_t *mddev,
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
-	mdk_rdev_t *blocked_rdev;
+	struct md_rdev *blocked_rdev;
 	int plugged;
 	int first_clone;
 	int sectors_handled;
@@ -870,7 +893,7 @@ read_again:
 		if (rdisk < 0) {
 			/* couldn't find anywhere to read from */
 			raid_end_bio_io(r1_bio);
-			return 0;
+			return;
 		}
 		mirror = conf->mirrors + rdisk;
 
@@ -928,12 +951,17 @@ read_again:
 			goto read_again;
 		} else
 			generic_make_request(read_bio);
-		return 0;
+		return;
 	}
 
 	/*
 	 * WRITE:
 	 */
+	if (conf->pending_count >= max_queued_requests) {
+		md_wakeup_thread(mddev->thread);
+		wait_event(conf->wait_barrier,
+			   conf->pending_count < max_queued_requests);
+	}
 	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
@@ -952,7 +980,7 @@ read_again:
 	rcu_read_lock();
 	max_sectors = r1_bio->sectors;
 	for (i = 0;  i < disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
 			atomic_inc(&rdev->nr_pending);
 			blocked_rdev = rdev;
@@ -1097,6 +1125,7 @@ read_again:
 		atomic_inc(&r1_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
+		conf->pending_count++;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	/* Mustn't call r1_bio_write_done before this next test,
@@ -1123,20 +1152,18 @@ read_again:
 
 	if (do_sync || !bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
-
-	return 0;
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
 		   conf->raid_disks - mddev->degraded);
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		seq_printf(seq, "%s",
 			   rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
 	}
@@ -1145,10 +1172,10 @@ static void status(struct seq_file *seq,
 }
 
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1188,7 +1215,7 @@ static void error(mddev_t *mddev, mdk_rd
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
 
-static void print_conf(conf_t *conf)
+static void print_conf(struct r1conf *conf)
 {
 	int i;
 
@@ -1203,7 +1230,7 @@ static void print_conf(conf_t *conf)
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
 		char b[BDEVNAME_SIZE];
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev)
 			printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s\n",
 			       i, !test_bit(In_sync, &rdev->flags),
@@ -1213,7 +1240,7 @@ static void print_conf(conf_t *conf)
 	rcu_read_unlock();
 }
 
-static void close_sync(conf_t *conf)
+static void close_sync(struct r1conf *conf)
 {
 	wait_barrier(conf);
 	allow_barrier(conf);
@@ -1222,10 +1249,10 @@ static void close_sync(conf_t *conf)
 	conf->r1buf_pool = NULL;
 }
 
-static int raid1_spare_active(mddev_t *mddev)
+static int raid1_spare_active(struct mddev *mddev)
 {
 	int i;
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int count = 0;
 	unsigned long flags;
 
@@ -1235,7 +1262,7 @@ static int raid1_spare_active(mddev_t *m
 	 * Called under mddev lock, so rcu protection not needed.
 	 */
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		struct md_rdev *rdev = conf->mirrors[i].rdev;
 		if (rdev
 		    && !test_bit(Faulty, &rdev->flags)
 		    && !test_and_set_bit(In_sync, &rdev->flags)) {
@@ -1252,12 +1279,12 @@ static int raid1_spare_active(mddev_t *m
 }
 
 
-static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int err = -EEXIST;
 	int mirror = 0;
-	mirror_info_t *p;
+	struct mirror_info *p;
 	int first = 0;
 	int last = mddev->raid_disks - 1;
 
@@ -1300,12 +1327,12 @@ static int raid1_add_disk(mddev_t *mddev
 	return err;
 }
 
-static int raid1_remove_disk(mddev_t *mddev, int number)
+static int raid1_remove_disk(struct mddev *mddev, int number)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
-	mirror_info_t *p = conf->mirrors+ number;
+	struct md_rdev *rdev;
+	struct mirror_info *p = conf->mirrors+ number;
 
 	print_conf(conf);
 	rdev = p->rdev;
@@ -1343,14 +1370,10 @@ abort:
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r1bio_t *r1_bio = bio->bi_private;
-	int i;
+	struct r1bio *r1_bio = bio->bi_private;
+
+	update_head_pos(r1_bio->read_disk, r1_bio);
 
-	for (i=r1_bio->mddev->raid_disks; i--; )
-		if (r1_bio->bios[i] == bio)
-			break;
-	BUG_ON(i < 0);
-	update_head_pos(i, r1_bio);
 	/*
 	 * we have read a block, now it needs to be re-written,
 	 * or re-read if the read failed.
@@ -1366,19 +1389,15 @@ static void end_sync_read(struct bio *bi
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
-	int i;
+	struct r1bio *r1_bio = bio->bi_private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	int mirror=0;
 	sector_t first_bad;
 	int bad_sectors;
 
-	for (i = 0; i < conf->raid_disks; i++)
-		if (r1_bio->bios[i] == bio) {
-			mirror = i;
-			break;
-		}
+	mirror = find_bio_disk(r1_bio, bio);
+
 	if (!uptodate) {
 		sector_t sync_blocks = 0;
 		sector_t s = r1_bio->sector;
@@ -1404,8 +1423,6 @@ static void end_sync_write(struct bio *b
 		)
 		set_bit(R1BIO_MadeGood, &r1_bio->state);
 
-	update_head_pos(mirror, r1_bio);
-
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
 		int s = r1_bio->sectors;
 		if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
@@ -1418,7 +1435,7 @@ static void end_sync_write(struct bio *b
 	}
 }
 
-static int r1_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector,
 			    int sectors, struct page *page, int rw)
 {
 	if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
@@ -1432,7 +1449,7 @@ static int r1_sync_page_io(mdk_rdev_t *r
 	return 0;
 }
 
-static int fix_sync_read_error(r1bio_t *r1_bio)
+static int fix_sync_read_error(struct r1bio *r1_bio)
 {
 	/* Try some synchronous reads of other devices to get
 	 * good data, much like with normal read errors.  Only
@@ -1445,8 +1462,8 @@ static int fix_sync_read_error(r1bio_t *
 	 * made sure that anything with a bad block in range
 	 * will have bi_end_io clear.
 	 */
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	struct bio *bio = r1_bio->bios[r1_bio->read_disk];
 	sector_t sect = r1_bio->sector;
 	int sectors = r1_bio->sectors;
@@ -1456,7 +1473,7 @@ static int fix_sync_read_error(r1bio_t *
 		int s = sectors;
 		int d = r1_bio->read_disk;
 		int success = 0;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		int start;
 
 		if (s > (PAGE_SIZE>>9))
@@ -1501,7 +1518,8 @@ static int fix_sync_read_error(r1bio_t *
 					abort = 1;
 			}
 			if (abort) {
-				mddev->recovery_disabled = 1;
+				conf->recovery_disabled =
+					mddev->recovery_disabled;
 				set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 				md_done_sync(mddev, r1_bio->sectors, 0);
 				put_buf(r1_bio);
@@ -1552,7 +1570,7 @@ static int fix_sync_read_error(r1bio_t *
 	return 1;
 }
 
-static int process_checks(r1bio_t *r1_bio)
+static int process_checks(struct r1bio *r1_bio)
 {
 	/* We have read all readable devices.  If we haven't
 	 * got the block, then there is no hope left.
@@ -1561,8 +1579,8 @@ static int process_checks(r1bio_t *r1_bi
 	 * If any blocks failed to read, then we need to
 	 * attempt an over-write
 	 */
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	int primary;
 	int i;
 
@@ -1634,9 +1652,9 @@ static int process_checks(r1bio_t *r1_bi
 	return 0;
 }
 
-static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
+static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i;
 	int disks = conf->raid_disks;
 	struct bio *bio, *wbio;
@@ -1686,16 +1704,16 @@ static void sync_request_write(mddev_t *
  *	3.	Performs writes following reads for array synchronising.
  */
 
-static void fix_read_error(conf_t *conf, int read_disk,
+static void fix_read_error(struct r1conf *conf, int read_disk,
 			   sector_t sect, int sectors)
 {
-	mddev_t *mddev = conf->mddev;
+	struct mddev *mddev = conf->mddev;
 	while(sectors) {
 		int s = sectors;
 		int d = read_disk;
 		int success = 0;
 		int start;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 
 		if (s > (PAGE_SIZE>>9))
 			s = PAGE_SIZE >> 9;
@@ -1726,7 +1744,7 @@ static void fix_read_error(conf_t *conf,
 
 		if (!success) {
 			/* Cannot read from anywhere - mark it bad */
-			mdk_rdev_t *rdev = conf->mirrors[read_disk].rdev;
+			struct md_rdev *rdev = conf->mirrors[read_disk].rdev;
 			if (!rdev_set_badblocks(rdev, sect, s, 0))
 				md_error(mddev, rdev);
 			break;
@@ -1789,11 +1807,11 @@ static int submit_bio_wait(int rw, struc
 	return test_bit(BIO_UPTODATE, &bio->bi_flags);
 }
 
-static int narrow_write_error(r1bio_t *r1_bio, int i)
+static int narrow_write_error(struct r1bio *r1_bio, int i)
 {
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
+	struct md_rdev *rdev = conf->mirrors[i].rdev;
 	int vcnt, idx;
 	struct bio_vec *vec;
 
@@ -1865,12 +1883,12 @@ static int narrow_write_error(r1bio_t *r
 	return ok;
 }
 
-static void handle_sync_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int m;
 	int s = r1_bio->sectors;
 	for (m = 0; m < conf->raid_disks ; m++) {
-		mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+		struct md_rdev *rdev = conf->mirrors[m].rdev;
 		struct bio *bio = r1_bio->bios[m];
 		if (bio->bi_end_io == NULL)
 			continue;
@@ -1888,12 +1906,12 @@ static void handle_sync_write_finished(c
 	md_done_sync(conf->mddev, s, 1);
 }
 
-static void handle_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int m;
 	for (m = 0; m < conf->raid_disks ; m++)
 		if (r1_bio->bios[m] == IO_MADE_GOOD) {
-			mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+			struct md_rdev *rdev = conf->mirrors[m].rdev;
 			rdev_clear_badblocks(rdev,
 					     r1_bio->sector,
 					     r1_bio->sectors);
@@ -1917,14 +1935,14 @@ static void handle_write_finished(conf_t
 	raid_end_bio_io(r1_bio);
 }
 
-static void handle_read_error(conf_t *conf, r1bio_t *r1_bio)
+static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int disk;
 	int max_sectors;
-	mddev_t *mddev = conf->mddev;
+	struct mddev *mddev = conf->mddev;
 	struct bio *bio;
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	clear_bit(R1BIO_ReadError, &r1_bio->state);
 	/* we got a read error. Maybe the drive is bad.  Maybe just
@@ -2007,11 +2025,11 @@ read_more:
 	}
 }
 
-static void raid1d(mddev_t *mddev)
+static void raid1d(struct mddev *mddev)
 {
-	r1bio_t *r1_bio;
+	struct r1bio *r1_bio;
 	unsigned long flags;
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	struct blk_plug plug;
 
@@ -2028,7 +2046,7 @@ static void raid1d(mddev_t *mddev)
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			break;
 		}
-		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
+		r1_bio = list_entry(head->prev, struct r1bio, retry_list);
 		list_del(head->prev);
 		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2060,7 +2078,7 @@ static void raid1d(mddev_t *mddev)
 }
 
 
-static int init_resync(conf_t *conf)
+static int init_resync(struct r1conf *conf)
 {
 	int buffs;
 
@@ -2084,10 +2102,10 @@ static int init_resync(conf_t *conf)
  * that can be installed to exclude normal IO requests.
  */
 
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	conf_t *conf = mddev->private;
-	r1bio_t *r1_bio;
+	struct r1conf *conf = mddev->private;
+	struct r1bio *r1_bio;
 	struct bio *bio;
 	sector_t max_sector, nr_sectors;
 	int disk = -1;
@@ -2167,14 +2185,13 @@ static sector_t sync_request(mddev_t *md
 	set_bit(R1BIO_IsSync, &r1_bio->state);
 
 	for (i=0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		bio = r1_bio->bios[i];
 
 		/* take from bio_init */
 		bio->bi_next = NULL;
 		bio->bi_flags &= ~(BIO_POOL_MASK-1);
 		bio->bi_flags |= 1 << BIO_UPTODATE;
-		bio->bi_comp_cpu = -1;
 		bio->bi_rw = READ;
 		bio->bi_vcnt = 0;
 		bio->bi_idx = 0;
@@ -2239,7 +2256,7 @@ static sector_t sync_request(mddev_t *md
 		int ok = 1;
 		for (i = 0 ; i < conf->raid_disks ; i++)
 			if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
-				mdk_rdev_t *rdev =
+				struct md_rdev *rdev =
 					rcu_dereference(conf->mirrors[i].rdev);
 				ok = rdev_set_badblocks(rdev, sector_nr,
 							min_bad, 0
@@ -2356,7 +2373,7 @@ static sector_t sync_request(mddev_t *md
 	return nr_sectors;
 }
 
-static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid1_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	if (sectors)
 		return sectors;
@@ -2364,15 +2381,15 @@ static sector_t raid1_size(mddev_t *mdde
 	return mddev->dev_sectors;
 }
 
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r1conf *setup_conf(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r1conf *conf;
 	int i;
-	mirror_info_t *disk;
-	mdk_rdev_t *rdev;
+	struct mirror_info *disk;
+	struct md_rdev *rdev;
 	int err = -ENOMEM;
 
-	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r1conf), GFP_KERNEL);
 	if (!conf)
 		goto abort;
 
@@ -2417,6 +2434,8 @@ static conf_t *setup_conf(mddev_t *mddev
 	init_waitqueue_head(&conf->wait_barrier);
 
 	bio_list_init(&conf->pending_bio_list);
+	conf->pending_count = 0;
+	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
 	conf->last_used = -1;
 	for (i = 0; i < conf->raid_disks; i++) {
@@ -2465,11 +2484,11 @@ static conf_t *setup_conf(mddev_t *mddev
 	return ERR_PTR(err);
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r1conf *conf;
 	int i;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->level != 1) {
 		printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2545,9 +2564,9 @@ static int run(mddev_t *mddev)
 	return md_integrity_register(mddev);
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	struct bitmap *bitmap = mddev->bitmap;
 
 	/* wait for behind writes to complete */
@@ -2572,7 +2591,7 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
-static int raid1_resize(mddev_t *mddev, sector_t sectors)
+static int raid1_resize(struct mddev *mddev, sector_t sectors)
 {
 	/* no resync is happening, and there is enough space
 	 * on all devices, so we can resize.
@@ -2596,7 +2615,7 @@ static int raid1_resize(mddev_t *mddev,
 	return 0;
 }
 
-static int raid1_reshape(mddev_t *mddev)
+static int raid1_reshape(struct mddev *mddev)
 {
 	/* We need to:
 	 * 1/ resize the r1bio_pool
@@ -2611,8 +2630,8 @@ static int raid1_reshape(mddev_t *mddev)
 	 */
 	mempool_t *newpool, *oldpool;
 	struct pool_info *newpoolinfo;
-	mirror_info_t *newmirrors;
-	conf_t *conf = mddev->private;
+	struct mirror_info *newmirrors;
+	struct r1conf *conf = mddev->private;
 	int cnt, raid_disks;
 	unsigned long flags;
 	int d, d2, err;
@@ -2668,7 +2687,7 @@ static int raid1_reshape(mddev_t *mddev)
 	conf->r1bio_pool = newpool;
 
 	for (d = d2 = 0; d < conf->raid_disks; d++) {
-		mdk_rdev_t *rdev = conf->mirrors[d].rdev;
+		struct md_rdev *rdev = conf->mirrors[d].rdev;
 		if (rdev && rdev->raid_disk != d2) {
 			sysfs_unlink_rdev(mddev, rdev);
 			rdev->raid_disk = d2;
@@ -2702,9 +2721,9 @@ static int raid1_reshape(mddev_t *mddev)
 	return 0;
 }
 
-static void raid1_quiesce(mddev_t *mddev, int state)
+static void raid1_quiesce(struct mddev *mddev, int state)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 
 	switch(state) {
 	case 2: /* wake for suspend */
@@ -2719,13 +2738,13 @@ static void raid1_quiesce(mddev_t *mddev
 	}
 }
 
-static void *raid1_takeover(mddev_t *mddev)
+static void *raid1_takeover(struct mddev *mddev)
 {
 	/* raid1 can take over:
 	 *  raid5 with 2 devices, any layout or chunk size
 	 */
 	if (mddev->level == 5 && mddev->raid_disks == 2) {
-		conf_t *conf;
+		struct r1conf *conf;
 		mddev->new_level = 1;
 		mddev->new_layout = 0;
 		mddev->new_chunk_sectors = 0;
@@ -2737,7 +2756,7 @@ static void *raid1_takeover(mddev_t *mdd
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid1_personality =
+static struct md_personality raid1_personality =
 {
 	.name		= "raid1",
 	.level		= 1,
@@ -2775,3 +2794,5 @@ MODULE_DESCRIPTION("RAID1 (mirroring) pe
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
 MODULE_ALIAS("md-raid1");
 MODULE_ALIAS("md-level-1");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid1.h linux-libre-3.2-gnu1/drivers/md/raid1.h
--- linux-libre-3.1-gnu1/drivers/md/raid1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid1.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,8 @@
 #ifndef _RAID1_H
 #define _RAID1_H
 
-typedef struct mirror_info mirror_info_t;
-
 struct mirror_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	head_position;
 };
 
@@ -17,61 +15,82 @@ struct mirror_info {
  */
 
 struct pool_info {
-	mddev_t *mddev;
+	struct mddev *mddev;
 	int	raid_disks;
 };
 
-
-typedef struct r1bio_s r1bio_t;
-
-struct r1_private_data_s {
-	mddev_t			*mddev;
-	mirror_info_t		*mirrors;
+struct r1conf {
+	struct mddev		*mddev;
+	struct mirror_info		*mirrors;
 	int			raid_disks;
+
+	/* When choose the best device for a read (read_balance())
+	 * we try to keep sequential reads one the same device
+	 * using 'last_used' and 'next_seq_sect'
+	 */
 	int			last_used;
 	sector_t		next_seq_sect;
+	/* During resync, read_balancing is only allowed on the part
+	 * of the array that has been resynced.  'next_resync' tells us
+	 * where that is.
+	 */
+	sector_t		next_resync;
+
 	spinlock_t		device_lock;
 
+	/* list of 'struct r1bio' that need to be processed by raid1d,
+	 * whether to retry a read, writeout a resync or recovery
+	 * block, or anything else.
+	 */
 	struct list_head	retry_list;
-	/* queue pending writes and submit them on unplug */
-	struct bio_list		pending_bio_list;
 
-	/* for use when syncing mirrors: */
+	/* queue pending writes to be submitted on unplug */
+	struct bio_list		pending_bio_list;
+	int			pending_count;
 
+	/* for use when syncing mirrors:
+	 * We don't allow both normal IO and resync/recovery IO at
+	 * the same time - resync/recovery can only happen when there
+	 * is no other IO.  So when either is active, the other has to wait.
+	 * See more details description in raid1.c near raise_barrier().
+	 */
+	wait_queue_head_t	wait_barrier;
 	spinlock_t		resync_lock;
 	int			nr_pending;
 	int			nr_waiting;
 	int			nr_queued;
 	int			barrier;
-	sector_t		next_resync;
-	int			fullsync;  /* set to 1 if a full sync is needed,
-					    * (fresh device added).
-					    * Cleared when a sync completes.
-					    */
-	int			recovery_disabled; /* when the same as
-						    * mddev->recovery_disabled
-						    * we don't allow recovery
-						    * to be attempted as we
-						    * expect a read error
-						    */
 
-	wait_queue_head_t	wait_barrier;
+	/* Set to 1 if a full sync is needed, (fresh device added).
+	 * Cleared when a sync completes.
+	 */
+	int			fullsync;
+
+	/* When the same as mddev->recovery_disabled we don't allow
+	 * recovery to be attempted as we expect a read error.
+	 */
+	int			recovery_disabled;
 
+
+	/* poolinfo contains information about the content of the
+	 * mempools - it changes when the array grows or shrinks
+	 */
 	struct pool_info	*poolinfo;
+	mempool_t		*r1bio_pool;
+	mempool_t		*r1buf_pool;
 
+	/* temporary buffer to synchronous IO when attempting to repair
+	 * a read error.
+	 */
 	struct page		*tmppage;
 
-	mempool_t *r1bio_pool;
-	mempool_t *r1buf_pool;
 
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct r1_private_data_s conf_t;
-
 /*
  * this is our 'private' RAID1 bio.
  *
@@ -79,7 +98,7 @@ typedef struct r1_private_data_s conf_t;
  * for this RAID1 operation, and about their status:
  */
 
-struct r1bio_s {
+struct r1bio {
 	atomic_t		remaining; /* 'have we finished' count,
 					    * used from IRQ handlers
 					    */
@@ -89,7 +108,7 @@ struct r1bio_s {
 	sector_t		sector;
 	int			sectors;
 	unsigned long		state;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	/*
 	 * original bio going to /dev/mdx
 	 */
@@ -148,6 +167,6 @@ struct r1bio_s {
 #define	R1BIO_MadeGood 7
 #define	R1BIO_WriteError 8
 
-extern int md_raid1_congested(mddev_t *mddev, int bits);
+extern int md_raid1_congested(struct mddev *mddev, int bits);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid5.c linux-libre-3.2-gnu1/drivers/md/raid5.c
--- linux-libre-3.1-gnu1/drivers/md/raid5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid5.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <linux/kthread.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
+#include <linux/module.h>
 #include <linux/async.h>
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
@@ -70,7 +71,11 @@
 #define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
 #define HASH_MASK		(NR_HASH - 1)
 
-#define stripe_hash(conf, sect)	(&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
+static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect)
+{
+	int hash = (sect >> STRIPE_SHIFT) & HASH_MASK;
+	return &conf->stripe_hashtbl[hash];
+}
 
 /* bio's attached to a stripe+device for I/O are linked together in bi_sector
  * order without overlap.  There may be several bio's per stripe+device, and
@@ -78,24 +83,17 @@
  * When walking this list for a particular stripe+device, we must never proceed
  * beyond a bio that extends past this device, as the next bio might no longer
  * be valid.
- * This macro is used to determine the 'next' bio in the list, given the sector
+ * This function is used to determine the 'next' bio in the list, given the sector
  * of the current stripe+device
  */
-#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
-/*
- * The following can be used to debug the driver
- */
-#define RAID5_PARANOIA	1
-#if RAID5_PARANOIA && defined(CONFIG_SMP)
-# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
-#else
-# define CHECK_DEVLOCK()
-#endif
-
-#ifdef DEBUG
-#define inline
-#define __inline__
-#endif
+static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
+{
+	int sectors = bio->bi_size >> 9;
+	if (bio->bi_sector + sectors < sector + STRIPE_SECTORS)
+		return bio->bi_next;
+	else
+		return NULL;
+}
 
 /*
  * We maintain a biased count of active stripes in the bottom 16 bits of
@@ -183,7 +181,7 @@ static void return_io(struct bio *return
 	}
 }
 
-static void print_raid5_conf (raid5_conf_t *conf);
+static void print_raid5_conf (struct r5conf *conf);
 
 static int stripe_operations_active(struct stripe_head *sh)
 {
@@ -192,7 +190,7 @@ static int stripe_operations_active(stru
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
-static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
 		BUG_ON(!list_empty(&sh->lru));
@@ -228,7 +226,7 @@ static void __release_stripe(raid5_conf_
 
 static void release_stripe(struct stripe_head *sh)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -244,25 +242,23 @@ static inline void remove_hash(struct st
 	hlist_del_init(&sh->hash);
 }
 
-static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(struct r5conf *conf, struct stripe_head *sh)
 {
 	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
 	pr_debug("insert_hash(), stripe %llu\n",
 		(unsigned long long)sh->sector);
 
-	CHECK_DEVLOCK();
 	hlist_add_head(&sh->hash, hp);
 }
 
 
 /* find an idle stripe, make sure it is unhashed, and return it. */
-static struct stripe_head *get_free_stripe(raid5_conf_t *conf)
+static struct stripe_head *get_free_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh = NULL;
 	struct list_head *first;
 
-	CHECK_DEVLOCK();
 	if (list_empty(&conf->inactive_list))
 		goto out;
 	first = conf->inactive_list.next;
@@ -306,19 +302,18 @@ static int grow_buffers(struct stripe_he
 }
 
 static void raid5_build_block(struct stripe_head *sh, int i, int previous);
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
 			    struct stripe_head *sh);
 
 static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 
 	BUG_ON(atomic_read(&sh->count) != 0);
 	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 	BUG_ON(stripe_operations_active(sh));
 
-	CHECK_DEVLOCK();
 	pr_debug("init_stripe called, stripe %llu\n",
 		(unsigned long long)sh->sector);
 
@@ -348,13 +343,12 @@ static void init_stripe(struct stripe_he
 	insert_hash(conf, sh);
 }
 
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
+static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
 					 short generation)
 {
 	struct stripe_head *sh;
 	struct hlist_node *hn;
 
-	CHECK_DEVLOCK();
 	pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
 	hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
 		if (sh->sector == sector && sh->generation == generation)
@@ -376,7 +370,7 @@ static struct stripe_head *__find_stripe
  * of the two sections, and some non-in_sync devices may
  * be insync in the section most affected by failed devices.
  */
-static int has_failed(raid5_conf_t *conf)
+static int has_failed(struct r5conf *conf)
 {
 	int degraded;
 	int i;
@@ -386,7 +380,7 @@ static int has_failed(raid5_conf_t *conf
 	rcu_read_lock();
 	degraded = 0;
 	for (i = 0; i < conf->previous_raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || test_bit(Faulty, &rdev->flags))
 			degraded++;
 		else if (test_bit(In_sync, &rdev->flags))
@@ -410,7 +404,7 @@ static int has_failed(raid5_conf_t *conf
 	rcu_read_lock();
 	degraded = 0;
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || test_bit(Faulty, &rdev->flags))
 			degraded++;
 		else if (test_bit(In_sync, &rdev->flags))
@@ -431,7 +425,7 @@ static int has_failed(raid5_conf_t *conf
 }
 
 static struct stripe_head *
-get_active_stripe(raid5_conf_t *conf, sector_t sector,
+get_active_stripe(struct r5conf *conf, sector_t sector,
 		  int previous, int noblock, int noquiesce)
 {
 	struct stripe_head *sh;
@@ -491,7 +485,7 @@ raid5_end_write_request(struct bio *bi,
 
 static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i, disks = sh->disks;
 
 	might_sleep();
@@ -499,7 +493,7 @@ static void ops_run_io(struct stripe_hea
 	for (i = disks; i--; ) {
 		int rw;
 		struct bio *bi;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
 			if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
 				rw = WRITE_FUA;
@@ -650,7 +644,7 @@ static void ops_complete_biofill(void *s
 {
 	struct stripe_head *sh = stripe_head_ref;
 	struct bio *return_bi = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 
 	pr_debug("%s: stripe %llu\n", __func__,
@@ -695,7 +689,7 @@ static void ops_complete_biofill(void *s
 static void ops_run_biofill(struct stripe_head *sh)
 {
 	struct dma_async_tx_descriptor *tx = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	struct async_submit_ctl submit;
 	int i;
 
@@ -1246,7 +1240,7 @@ static void __raid_run_ops(struct stripe
 {
 	int overlap_clear = 0, i, disks = sh->disks;
 	struct dma_async_tx_descriptor *tx = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int level = conf->level;
 	struct raid5_percpu *percpu;
 	unsigned long cpu;
@@ -1337,7 +1331,7 @@ static void raid_run_ops(struct stripe_h
 #define raid_run_ops __raid_run_ops
 #endif
 
-static int grow_one_stripe(raid5_conf_t *conf)
+static int grow_one_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 	sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
@@ -1362,7 +1356,7 @@ static int grow_one_stripe(raid5_conf_t
 	return 1;
 }
 
-static int grow_stripes(raid5_conf_t *conf, int num)
+static int grow_stripes(struct r5conf *conf, int num)
 {
 	struct kmem_cache *sc;
 	int devs = max(conf->raid_disks, conf->previous_raid_disks);
@@ -1411,7 +1405,7 @@ static size_t scribble_len(int num)
 	return len;
 }
 
-static int resize_stripes(raid5_conf_t *conf, int newsize)
+static int resize_stripes(struct r5conf *conf, int newsize)
 {
 	/* Make all the stripes able to hold 'newsize' devices.
 	 * New slots in each stripe get 'page' set to a new page.
@@ -1556,7 +1550,7 @@ static int resize_stripes(raid5_conf_t *
 	return err;
 }
 
-static int drop_one_stripe(raid5_conf_t *conf)
+static int drop_one_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 
@@ -1572,7 +1566,7 @@ static int drop_one_stripe(raid5_conf_t
 	return 1;
 }
 
-static void shrink_stripes(raid5_conf_t *conf)
+static void shrink_stripes(struct r5conf *conf)
 {
 	while (drop_one_stripe(conf))
 		;
@@ -1585,11 +1579,11 @@ static void shrink_stripes(raid5_conf_t
 static void raid5_end_read_request(struct bio * bi, int error)
 {
 	struct stripe_head *sh = bi->bi_private;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks, i;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 
 	for (i=0 ; i<disks; i++)
@@ -1672,7 +1666,7 @@ static void raid5_end_read_request(struc
 static void raid5_end_write_request(struct bio *bi, int error)
 {
 	struct stripe_head *sh = bi->bi_private;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks, i;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 	sector_t first_bad;
@@ -1726,10 +1720,10 @@ static void raid5_build_block(struct str
 	dev->sector = compute_blocknr(sh, i, previous);
 }
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	pr_debug("raid456: error called\n");
 
 	if (test_and_clear_bit(In_sync, &rdev->flags)) {
@@ -1758,7 +1752,7 @@ static void error(mddev_t *mddev, mdk_rd
  * Input: a 'big' sector number,
  * Output: index of the data and parity disk, and the sector # in them.
  */
-static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
+static sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
 				     int previous, int *dd_idx,
 				     struct stripe_head *sh)
 {
@@ -1963,7 +1957,7 @@ static sector_t raid5_compute_sector(rai
 
 static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int raid_disks = sh->disks;
 	int data_disks = raid_disks - conf->max_degraded;
 	sector_t new_sector = sh->sector, check;
@@ -2088,7 +2082,7 @@ schedule_reconstruction(struct stripe_he
 			 int rcw, int expand)
 {
 	int i, pd_idx = sh->pd_idx, disks = sh->disks;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int level = conf->level;
 
 	if (rcw) {
@@ -2173,7 +2167,7 @@ schedule_reconstruction(struct stripe_he
 static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
 {
 	struct bio **bip;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int firstwrite=0;
 
 	pr_debug("adding bi b#%llu to stripe s#%llu\n",
@@ -2235,9 +2229,9 @@ static int add_stripe_bio(struct stripe_
 	return 0;
 }
 
-static void end_reshape(raid5_conf_t *conf);
+static void end_reshape(struct r5conf *conf);
 
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
 			    struct stripe_head *sh)
 {
 	int sectors_per_chunk =
@@ -2254,7 +2248,7 @@ static void stripe_set_idx(sector_t stri
 }
 
 static void
-handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks,
 				struct bio **return_bi)
 {
@@ -2264,7 +2258,7 @@ handle_failed_stripe(raid5_conf_t *conf,
 		int bitmap_end = 0;
 
 		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			rcu_read_lock();
 			rdev = rcu_dereference(conf->disks[i].rdev);
 			if (rdev && test_bit(In_sync, &rdev->flags))
@@ -2359,7 +2353,7 @@ handle_failed_stripe(raid5_conf_t *conf,
 }
 
 static void
-handle_failed_sync(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
 		   struct stripe_head_state *s)
 {
 	int abort = 0;
@@ -2378,7 +2372,7 @@ handle_failed_sync(raid5_conf_t *conf, s
 	 * refcounting of rdevs is not needed
 	 */
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		struct md_rdev *rdev = conf->disks[i].rdev;
 		if (!rdev
 		    || test_bit(Faulty, &rdev->flags)
 		    || test_bit(In_sync, &rdev->flags))
@@ -2508,7 +2502,7 @@ static void handle_stripe_fill(struct st
  * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
  * never LOCKED, so we don't need to test 'failed' directly.
  */
-static void handle_stripe_clean_event(raid5_conf_t *conf,
+static void handle_stripe_clean_event(struct r5conf *conf,
 	struct stripe_head *sh, int disks, struct bio **return_bi)
 {
 	int i;
@@ -2553,7 +2547,7 @@ static void handle_stripe_clean_event(ra
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-static void handle_stripe_dirtying(raid5_conf_t *conf,
+static void handle_stripe_dirtying(struct r5conf *conf,
 				   struct stripe_head *sh,
 				   struct stripe_head_state *s,
 				   int disks)
@@ -2655,7 +2649,7 @@ static void handle_stripe_dirtying(raid5
 		schedule_reconstruction(sh, s, rcw == 0, 0);
 }
 
-static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks)
 {
 	struct r5dev *dev = NULL;
@@ -2743,7 +2737,7 @@ static void handle_parity_checks5(raid5_
 }
 
 
-static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
 				  struct stripe_head_state *s,
 				  int disks)
 {
@@ -2906,7 +2900,7 @@ static void handle_parity_checks6(raid5_
 	}
 }
 
-static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh)
+static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
 {
 	int i;
 
@@ -2985,7 +2979,7 @@ static void handle_stripe_expansion(raid
 
 static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks;
 	struct r5dev *dev;
 	int i;
@@ -3002,7 +2996,7 @@ static void analyse_stripe(struct stripe
 	rcu_read_lock();
 	spin_lock_irq(&conf->device_lock);
 	for (i=disks; i--; ) {
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		sector_t first_bad;
 		int bad_sectors;
 		int is_bad = 0;
@@ -3042,6 +3036,8 @@ static void analyse_stripe(struct stripe
 		if (dev->written)
 			s->written++;
 		rdev = rcu_dereference(conf->disks[i].rdev);
+		if (rdev && test_bit(Faulty, &rdev->flags))
+			rdev = NULL;
 		if (rdev) {
 			is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
 					     &first_bad, &bad_sectors);
@@ -3069,12 +3065,18 @@ static void analyse_stripe(struct stripe
 			}
 		} else if (test_bit(In_sync, &rdev->flags))
 			set_bit(R5_Insync, &dev->flags);
-		else {
+		else if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
 			/* in sync if before recovery_offset */
-			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
-				set_bit(R5_Insync, &dev->flags);
-		}
-		if (test_bit(R5_WriteError, &dev->flags)) {
+			set_bit(R5_Insync, &dev->flags);
+		else if (test_bit(R5_UPTODATE, &dev->flags) &&
+			 test_bit(R5_Expanded, &dev->flags))
+			/* If we've reshaped into here, we assume it is Insync.
+			 * We will shortly update recovery_offset to make
+			 * it official.
+			 */
+			set_bit(R5_Insync, &dev->flags);
+
+		if (rdev && test_bit(R5_WriteError, &dev->flags)) {
 			clear_bit(R5_Insync, &dev->flags);
 			if (!test_bit(Faulty, &rdev->flags)) {
 				s->handle_bad_blocks = 1;
@@ -3082,7 +3084,7 @@ static void analyse_stripe(struct stripe
 			} else
 				clear_bit(R5_WriteError, &dev->flags);
 		}
-		if (test_bit(R5_MadeGood, &dev->flags)) {
+		if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
 			if (!test_bit(Faulty, &rdev->flags)) {
 				s->handle_bad_blocks = 1;
 				atomic_inc(&rdev->nr_pending);
@@ -3109,14 +3111,14 @@ static void analyse_stripe(struct stripe
 static void handle_stripe(struct stripe_head *sh)
 {
 	struct stripe_head_state s;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 	int prexor;
 	int disks = sh->disks;
 	struct r5dev *pdev, *qdev;
 
 	clear_bit(STRIPE_HANDLE, &sh->state);
-	if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) {
+	if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) {
 		/* already being handled, ensure it gets handled
 		 * again when current action finishes */
 		set_bit(STRIPE_HANDLE, &sh->state);
@@ -3165,10 +3167,14 @@ static void handle_stripe(struct stripe_
 	/* check if the array has lost more than max_degraded devices and,
 	 * if so, some requests might need to be failed.
 	 */
-	if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written)
-		handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
-	if (s.failed > conf->max_degraded && s.syncing)
-		handle_failed_sync(conf, sh, &s);
+	if (s.failed > conf->max_degraded) {
+		sh->check_state = 0;
+		sh->reconstruct_state = 0;
+		if (s.to_read+s.to_write+s.written)
+			handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
+		if (s.syncing)
+			handle_failed_sync(conf, sh, &s);
+	}
 
 	/*
 	 * might be able to return some write requests if the parity blocks
@@ -3341,7 +3347,7 @@ finish:
 
 	if (s.handle_bad_blocks)
 		for (i = disks; i--; ) {
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			struct r5dev *dev = &sh->dev[i];
 			if (test_and_clear_bit(R5_WriteError, &dev->flags)) {
 				/* We own a safe reference to the rdev */
@@ -3377,10 +3383,10 @@ finish:
 
 	return_io(s.return_bi);
 
-	clear_bit(STRIPE_ACTIVE, &sh->state);
+	clear_bit_unlock(STRIPE_ACTIVE, &sh->state);
 }
 
-static void raid5_activate_delayed(raid5_conf_t *conf)
+static void raid5_activate_delayed(struct r5conf *conf)
 {
 	if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
 		while (!list_empty(&conf->delayed_list)) {
@@ -3396,7 +3402,7 @@ static void raid5_activate_delayed(raid5
 	}
 }
 
-static void activate_bit_delay(raid5_conf_t *conf)
+static void activate_bit_delay(struct r5conf *conf)
 {
 	/* device_lock is held */
 	struct list_head head;
@@ -3410,9 +3416,9 @@ static void activate_bit_delay(raid5_con
 	}
 }
 
-int md_raid5_congested(mddev_t *mddev, int bits)
+int md_raid5_congested(struct mddev *mddev, int bits)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	/* No difference between reads and writes.  Just check
 	 * how busy the stripe_cache is
@@ -3431,7 +3437,7 @@ EXPORT_SYMBOL_GPL(md_raid5_congested);
 
 static int raid5_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
+	struct mddev *mddev = data;
 
 	return mddev_congested(mddev, bits) ||
 		md_raid5_congested(mddev, bits);
@@ -3444,7 +3450,7 @@ static int raid5_mergeable_bvec(struct r
 				struct bvec_merge_data *bvm,
 				struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3464,7 +3470,7 @@ static int raid5_mergeable_bvec(struct r
 }
 
 
-static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
+static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
 {
 	sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3480,7 +3486,7 @@ static int in_chunk_boundary(mddev_t *md
  *  add bio to the retry LIFO  ( in O(1) ... we are in interrupt )
  *  later sampled by raid5d.
  */
-static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
+static void add_bio_to_retry(struct bio *bi,struct r5conf *conf)
 {
 	unsigned long flags;
 
@@ -3494,7 +3500,7 @@ static void add_bio_to_retry(struct bio
 }
 
 
-static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+static struct bio *remove_bio_from_retry(struct r5conf *conf)
 {
 	struct bio *bi;
 
@@ -3527,10 +3533,10 @@ static struct bio *remove_bio_from_retry
 static void raid5_align_endio(struct bio *bi, int error)
 {
 	struct bio* raid_bi  = bi->bi_private;
-	mddev_t *mddev;
-	raid5_conf_t *conf;
+	struct mddev *mddev;
+	struct r5conf *conf;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	bio_put(bi);
 
@@ -3574,12 +3580,12 @@ static int bio_fits_rdev(struct bio *bi)
 }
 
 
-static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
+static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int dd_idx;
 	struct bio* align_bi;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (!in_chunk_boundary(mddev, raid_bio)) {
 		pr_debug("chunk_aligned_read : non aligned\n");
@@ -3652,7 +3658,7 @@ static int chunk_aligned_read(mddev_t *m
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 
@@ -3695,9 +3701,9 @@ static struct stripe_head *__get_priorit
 	return sh;
 }
 
-static int make_request(mddev_t *mddev, struct bio * bi)
+static void make_request(struct mddev *mddev, struct bio * bi)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int dd_idx;
 	sector_t new_sector;
 	sector_t logical_sector, last_sector;
@@ -3708,7 +3714,7 @@ static int make_request(mddev_t *mddev,
 
 	if (unlikely(bi->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bi);
-		return 0;
+		return;
 	}
 
 	md_write_start(mddev, bi);
@@ -3716,7 +3722,7 @@ static int make_request(mddev_t *mddev,
 	if (rw == READ &&
 	     mddev->reshape_position == MaxSector &&
 	     chunk_aligned_read(mddev,bi))
-		return 0;
+		return;
 
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
 	last_sector = bi->bi_sector + (bi->bi_size>>9);
@@ -3851,13 +3857,11 @@ static int make_request(mddev_t *mddev,
 
 		bio_endio(bi, 0);
 	}
-
-	return 0;
 }
 
-static sector_t raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks);
+static sector_t raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks);
 
-static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped)
+static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *skipped)
 {
 	/* reshaping is quite different to recovery/resync so it is
 	 * handled quite separately ... here.
@@ -3868,7 +3872,7 @@ static sector_t reshape_request(mddev_t
 	 * As the reads complete, handle_stripe will copy the data
 	 * into the destination stripe and release that stripe.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t first_sector, last_sector;
 	int raid_disks = conf->previous_raid_disks;
@@ -4075,9 +4079,9 @@ static sector_t reshape_request(mddev_t
 }
 
 /* FIXME go_faster isn't used */
-static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t max_sector = mddev->dev_sectors;
 	sector_t sync_blocks;
@@ -4162,7 +4166,7 @@ static inline sector_t sync_request(mdde
 	return STRIPE_SECTORS;
 }
 
-static int  retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 {
 	/* We may not be able to submit a whole bio at once as there
 	 * may not be enough stripe_heads available.
@@ -4234,10 +4238,10 @@ static int  retry_aligned_read(raid5_con
  * During the scan, completed stripes are saved for us by the interrupt
  * handler, so that they will not have to wait for our next wakeup.
  */
-static void raid5d(mddev_t *mddev)
+static void raid5d(struct mddev *mddev)
 {
 	struct stripe_head *sh;
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int handled;
 	struct blk_plug plug;
 
@@ -4301,9 +4305,9 @@ static void raid5d(mddev_t *mddev)
 }
 
 static ssize_t
-raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
+raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->max_nr_stripes);
 	else
@@ -4311,9 +4315,9 @@ raid5_show_stripe_cache_size(mddev_t *md
 }
 
 int
-raid5_set_cache_size(mddev_t *mddev, int size)
+raid5_set_cache_size(struct mddev *mddev, int size)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err;
 
 	if (size <= 16 || size > 32768)
@@ -4337,9 +4341,9 @@ raid5_set_cache_size(mddev_t *mddev, int
 EXPORT_SYMBOL(raid5_set_cache_size);
 
 static ssize_t
-raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+raid5_store_stripe_cache_size(struct mddev *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	unsigned long new;
 	int err;
 
@@ -4362,9 +4366,9 @@ raid5_stripecache_size = __ATTR(stripe_c
 				raid5_store_stripe_cache_size);
 
 static ssize_t
-raid5_show_preread_threshold(mddev_t *mddev, char *page)
+raid5_show_preread_threshold(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->bypass_threshold);
 	else
@@ -4372,9 +4376,9 @@ raid5_show_preread_threshold(mddev_t *md
 }
 
 static ssize_t
-raid5_store_preread_threshold(mddev_t *mddev, const char *page, size_t len)
+raid5_store_preread_threshold(struct mddev *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	unsigned long new;
 	if (len >= PAGE_SIZE)
 		return -EINVAL;
@@ -4396,9 +4400,9 @@ raid5_preread_bypass_threshold = __ATTR(
 					raid5_store_preread_threshold);
 
 static ssize_t
-stripe_cache_active_show(mddev_t *mddev, char *page)
+stripe_cache_active_show(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
 	else
@@ -4420,9 +4424,9 @@ static struct attribute_group raid5_attr
 };
 
 static sector_t
-raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (!sectors)
 		sectors = mddev->dev_sectors;
@@ -4435,7 +4439,7 @@ raid5_size(mddev_t *mddev, sector_t sect
 	return sectors * (raid_disks - conf->max_degraded);
 }
 
-static void raid5_free_percpu(raid5_conf_t *conf)
+static void raid5_free_percpu(struct r5conf *conf)
 {
 	struct raid5_percpu *percpu;
 	unsigned long cpu;
@@ -4457,7 +4461,7 @@ static void raid5_free_percpu(raid5_conf
 	free_percpu(conf->percpu);
 }
 
-static void free_conf(raid5_conf_t *conf)
+static void free_conf(struct r5conf *conf)
 {
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
@@ -4470,7 +4474,7 @@ static void free_conf(raid5_conf_t *conf
 static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
-	raid5_conf_t *conf = container_of(nfb, raid5_conf_t, cpu_notify);
+	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
 	long cpu = (long)hcpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
@@ -4505,7 +4509,7 @@ static int raid456_cpu_notify(struct not
 }
 #endif
 
-static int raid5_alloc_percpu(raid5_conf_t *conf)
+static int raid5_alloc_percpu(struct r5conf *conf)
 {
 	unsigned long cpu;
 	struct page *spare_page;
@@ -4547,11 +4551,11 @@ static int raid5_alloc_percpu(raid5_conf
 	return err;
 }
 
-static raid5_conf_t *setup_conf(mddev_t *mddev)
+static struct r5conf *setup_conf(struct mddev *mddev)
 {
-	raid5_conf_t *conf;
+	struct r5conf *conf;
 	int raid_disk, memory, max_disks;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct disk_info *disk;
 
 	if (mddev->new_level != 5
@@ -4583,7 +4587,7 @@ static raid5_conf_t *setup_conf(mddev_t
 		return ERR_PTR(-EINVAL);
 	}
 
-	conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r5conf), GFP_KERNEL);
 	if (conf == NULL)
 		goto abort;
 	spin_lock_init(&conf->device_lock);
@@ -4598,6 +4602,7 @@ static raid5_conf_t *setup_conf(mddev_t
 	atomic_set(&conf->preread_active_stripes, 0);
 	atomic_set(&conf->active_aligned_reads, 0);
 	conf->bypass_threshold = BYPASS_THRESHOLD;
+	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
@@ -4712,12 +4717,12 @@ static int only_parity(int raid_disk, in
 	return 0;
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	raid5_conf_t *conf;
+	struct r5conf *conf;
 	int working_disks = 0;
 	int dirty_parity_disks = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t reshape_offset = 0;
 
 	if (mddev->recovery_cp != MaxSector)
@@ -4942,18 +4947,16 @@ static int run(mddev_t *mddev)
 	return 0;
 abort:
 	md_unregister_thread(&mddev->thread);
-	if (conf) {
-		print_raid5_conf(conf);
-		free_conf(conf);
-	}
+	print_raid5_conf(conf);
+	free_conf(conf);
 	mddev->private = NULL;
 	printk(KERN_ALERT "md/raid:%s: failed to run raid set.\n", mdname(mddev));
 	return -EIO;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
@@ -4964,44 +4967,9 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
-#ifdef DEBUG
-static void print_sh(struct seq_file *seq, struct stripe_head *sh)
-{
-	int i;
-
-	seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n",
-		   (unsigned long long)sh->sector, sh->pd_idx, sh->state);
-	seq_printf(seq, "sh %llu,  count %d.\n",
-		   (unsigned long long)sh->sector, atomic_read(&sh->count));
-	seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector);
-	for (i = 0; i < sh->disks; i++) {
-		seq_printf(seq, "(cache%d: %p %ld) ",
-			   i, sh->dev[i].page, sh->dev[i].flags);
-	}
-	seq_printf(seq, "\n");
-}
-
-static void printall(struct seq_file *seq, raid5_conf_t *conf)
-{
-	struct stripe_head *sh;
-	struct hlist_node *hn;
-	int i;
-
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < NR_HASH; i++) {
-		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
-			if (sh->raid_conf != conf)
-				continue;
-			print_sh(seq, sh);
-		}
-	}
-	spin_unlock_irq(&conf->device_lock);
-}
-#endif
-
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " level %d, %dk chunk, algorithm %d", mddev->level,
@@ -5012,13 +4980,9 @@ static void status(struct seq_file *seq,
 			       conf->disks[i].rdev &&
 			       test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
 	seq_printf (seq, "]");
-#ifdef DEBUG
-	seq_printf (seq, "\n");
-	printall(seq, conf);
-#endif
 }
 
-static void print_raid5_conf (raid5_conf_t *conf)
+static void print_raid5_conf (struct r5conf *conf)
 {
 	int i;
 	struct disk_info *tmp;
@@ -5042,10 +5006,10 @@ static void print_raid5_conf (raid5_conf
 	}
 }
 
-static int raid5_spare_active(mddev_t *mddev)
+static int raid5_spare_active(struct mddev *mddev)
 {
 	int i;
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct disk_info *tmp;
 	int count = 0;
 	unsigned long flags;
@@ -5067,11 +5031,11 @@ static int raid5_spare_active(mddev_t *m
 	return count;
 }
 
-static int raid5_remove_disk(mddev_t *mddev, int number)
+static int raid5_remove_disk(struct mddev *mddev, int number)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct disk_info *p = conf->disks + number;
 
 	print_raid5_conf(conf);
@@ -5110,9 +5074,9 @@ abort:
 	return err;
 }
 
-static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err = -EEXIST;
 	int disk;
 	struct disk_info *p;
@@ -5153,7 +5117,7 @@ static int raid5_add_disk(mddev_t *mddev
 	return err;
 }
 
-static int raid5_resize(mddev_t *mddev, sector_t sectors)
+static int raid5_resize(struct mddev *mddev, sector_t sectors)
 {
 	/* no resync is happening, and there is enough space
 	 * on all devices, so we can resize.
@@ -5180,7 +5144,7 @@ static int raid5_resize(mddev_t *mddev,
 	return 0;
 }
 
-static int check_stripe_cache(mddev_t *mddev)
+static int check_stripe_cache(struct mddev *mddev)
 {
 	/* Can only proceed if there are plenty of stripe_heads.
 	 * We need a minimum of one full stripe,, and for sensible progress
@@ -5190,7 +5154,7 @@ static int check_stripe_cache(mddev_t *m
 	 * If the chunk size is greater, user-space should request more
 	 * stripe_heads first.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
 	    > conf->max_nr_stripes ||
 	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
@@ -5204,9 +5168,9 @@ static int check_stripe_cache(mddev_t *m
 	return 1;
 }
 
-static int check_reshape(mddev_t *mddev)
+static int check_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (mddev->delta_disks == 0 &&
 	    mddev->new_layout == mddev->layout &&
@@ -5236,10 +5200,10 @@ static int check_reshape(mddev_t *mddev)
 	return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
 }
 
-static int raid5_start_reshape(mddev_t *mddev)
+static int raid5_start_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev;
+	struct r5conf *conf = mddev->private;
+	struct md_rdev *rdev;
 	int spares = 0;
 	unsigned long flags;
 
@@ -5353,7 +5317,7 @@ static int raid5_start_reshape(mddev_t *
 /* This is called from the reshape thread and should make any
  * changes needed in 'conf'
  */
-static void end_reshape(raid5_conf_t *conf)
+static void end_reshape(struct r5conf *conf)
 {
 
 	if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
@@ -5380,9 +5344,9 @@ static void end_reshape(raid5_conf_t *co
 /* This is called from the raid5d thread with mddev_lock held.
  * It makes config changes to the device.
  */
-static void raid5_finish_reshape(mddev_t *mddev)
+static void raid5_finish_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 
@@ -5401,7 +5365,7 @@ static void raid5_finish_reshape(mddev_t
 			for (d = conf->raid_disks ;
 			     d < conf->raid_disks - mddev->delta_disks;
 			     d++) {
-				mdk_rdev_t *rdev = conf->disks[d].rdev;
+				struct md_rdev *rdev = conf->disks[d].rdev;
 				if (rdev && raid5_remove_disk(mddev, d) == 0) {
 					sysfs_unlink_rdev(mddev, rdev);
 					rdev->raid_disk = -1;
@@ -5415,9 +5379,9 @@ static void raid5_finish_reshape(mddev_t
 	}
 }
 
-static void raid5_quiesce(mddev_t *mddev, int state)
+static void raid5_quiesce(struct mddev *mddev, int state)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	switch(state) {
 	case 2: /* resume for a suspend */
@@ -5451,20 +5415,20 @@ static void raid5_quiesce(mddev_t *mddev
 }
 
 
-static void *raid45_takeover_raid0(mddev_t *mddev, int level)
+static void *raid45_takeover_raid0(struct mddev *mddev, int level)
 {
-	struct raid0_private_data *raid0_priv = mddev->private;
+	struct r0conf *raid0_conf = mddev->private;
 	sector_t sectors;
 
 	/* for raid0 takeover only one zone is supported */
-	if (raid0_priv->nr_strip_zones > 1) {
+	if (raid0_conf->nr_strip_zones > 1) {
 		printk(KERN_ERR "md/raid:%s: cannot takeover raid0 with more than one zone.\n",
 		       mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 
-	sectors = raid0_priv->strip_zone[0].zone_end;
-	sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+	sectors = raid0_conf->strip_zone[0].zone_end;
+	sector_div(sectors, raid0_conf->strip_zone[0].nb_dev);
 	mddev->dev_sectors = sectors;
 	mddev->new_level = level;
 	mddev->new_layout = ALGORITHM_PARITY_N;
@@ -5478,7 +5442,7 @@ static void *raid45_takeover_raid0(mddev
 }
 
 
-static void *raid5_takeover_raid1(mddev_t *mddev)
+static void *raid5_takeover_raid1(struct mddev *mddev)
 {
 	int chunksect;
 
@@ -5505,7 +5469,7 @@ static void *raid5_takeover_raid1(mddev_
 	return setup_conf(mddev);
 }
 
-static void *raid5_takeover_raid6(mddev_t *mddev)
+static void *raid5_takeover_raid6(struct mddev *mddev)
 {
 	int new_layout;
 
@@ -5539,14 +5503,14 @@ static void *raid5_takeover_raid6(mddev_
 }
 
 
-static int raid5_check_reshape(mddev_t *mddev)
+static int raid5_check_reshape(struct mddev *mddev)
 {
 	/* For a 2-drive array, the layout and chunk size can be changed
 	 * immediately as not restriping is needed.
 	 * For larger arrays we record the new value - after validation
 	 * to be used by a reshape pass.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int new_chunk = mddev->new_chunk_sectors;
 
 	if (mddev->new_layout >= 0 && !algorithm_valid_raid5(mddev->new_layout))
@@ -5579,7 +5543,7 @@ static int raid5_check_reshape(mddev_t *
 	return check_reshape(mddev);
 }
 
-static int raid6_check_reshape(mddev_t *mddev)
+static int raid6_check_reshape(struct mddev *mddev)
 {
 	int new_chunk = mddev->new_chunk_sectors;
 
@@ -5599,7 +5563,7 @@ static int raid6_check_reshape(mddev_t *
 	return check_reshape(mddev);
 }
 
-static void *raid5_takeover(mddev_t *mddev)
+static void *raid5_takeover(struct mddev *mddev)
 {
 	/* raid5 can take over:
 	 *  raid0 - if there is only one strip zone - make it a raid4 layout
@@ -5622,7 +5586,7 @@ static void *raid5_takeover(mddev_t *mdd
 	return ERR_PTR(-EINVAL);
 }
 
-static void *raid4_takeover(mddev_t *mddev)
+static void *raid4_takeover(struct mddev *mddev)
 {
 	/* raid4 can take over:
 	 *  raid0 - if there is only one strip zone
@@ -5639,9 +5603,9 @@ static void *raid4_takeover(mddev_t *mdd
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid5_personality;
+static struct md_personality raid5_personality;
 
-static void *raid6_takeover(mddev_t *mddev)
+static void *raid6_takeover(struct mddev *mddev)
 {
 	/* Currently can only take over a raid5.  We map the
 	 * personality to an equivalent raid6 personality
@@ -5688,7 +5652,7 @@ static void *raid6_takeover(mddev_t *mdd
 }
 
 
-static struct mdk_personality raid6_personality =
+static struct md_personality raid6_personality =
 {
 	.name		= "raid6",
 	.level		= 6,
@@ -5710,7 +5674,7 @@ static struct mdk_personality raid6_pers
 	.quiesce	= raid5_quiesce,
 	.takeover	= raid6_takeover,
 };
-static struct mdk_personality raid5_personality =
+static struct md_personality raid5_personality =
 {
 	.name		= "raid5",
 	.level		= 5,
@@ -5733,7 +5697,7 @@ static struct mdk_personality raid5_pers
 	.takeover	= raid5_takeover,
 };
 
-static struct mdk_personality raid4_personality =
+static struct md_personality raid4_personality =
 {
 	.name		= "raid4",
 	.level		= 4,
diff -druNp linux-libre-3.1-gnu1/drivers/md/raid5.h linux-libre-3.2-gnu1/drivers/md/raid5.h
--- linux-libre-3.1-gnu1/drivers/md/raid5.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/md/raid5.h	2012-01-04 18:55:44.000000000 -0500
@@ -197,7 +197,7 @@ enum reconstruct_states {
 struct stripe_head {
 	struct hlist_node	hash;
 	struct list_head	lru;	      /* inactive_list or handle_list */
-	struct raid5_private_data *raid_conf;
+	struct r5conf		*raid_conf;
 	short			generation;	/* increments with every
 						 * reshape */
 	sector_t		sector;		/* sector of this row */
@@ -248,7 +248,7 @@ struct stripe_head_state {
 	unsigned long ops_request;
 
 	struct bio *return_bi;
-	mdk_rdev_t *blocked_rdev;
+	struct md_rdev *blocked_rdev;
 	int handle_bad_blocks;
 };
 
@@ -344,12 +344,12 @@ enum {
 
 
 struct disk_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 };
 
-struct raid5_private_data {
+struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	struct disk_info	*spare;
 	int			chunk_sectors;
 	int			level, algorithm;
@@ -436,11 +436,9 @@ struct raid5_private_data {
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct raid5_private_data raid5_conf_t;
-
 /*
  * Our supported algorithms
  */
@@ -503,7 +501,7 @@ static inline int algorithm_is_DDF(int l
 	return layout >= 8 && layout <= 10;
 }
 
-extern int md_raid5_congested(mddev_t *mddev, int bits);
-extern void md_raid5_kick_device(raid5_conf_t *conf);
-extern int raid5_set_cache_size(mddev_t *mddev, int size);
+extern int md_raid5_congested(struct mddev *mddev, int bits);
+extern void md_raid5_kick_device(struct r5conf *conf);
+extern int raid5_set_cache_size(struct mddev *mddev, int size);
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_core.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_core.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,10 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146.h>
+#include <linux/module.h>
 
 LIST_HEAD(saa7146_devices);
 DEFINE_MUTEX(saa7146_devices_lock);
@@ -35,10 +38,9 @@ static void dump_registers(struct saa714
 {
 	int i = 0;
 
-	INFO((" @ %li jiffies:\n",jiffies));
-	for(i = 0; i <= 0x148; i+=4) {
-		printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
-	}
+	pr_info(" @ %li jiffies:\n", jiffies);
+	for (i = 0; i <= 0x148; i += 4)
+		pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
 }
 #endif
 
@@ -72,9 +74,8 @@ static inline int saa7146_wait_for_debi_
 		if (saa7146_read(dev, MC2) & 2)
 			break;
 		if (err) {
-			printk(KERN_ERR "%s: %s timed out while waiting for "
-					"registers getting programmed\n",
-					dev->name, __func__);
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		msleep(1);
@@ -88,8 +89,8 @@ static inline int saa7146_wait_for_debi_
 			break;
 		saa7146_read(dev, MC2);
 		if (err) {
-			DEB_S(("%s: %s timed out while waiting for transfer "
-				"completion\n",	dev->name, __func__));
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		msleep(1);
@@ -109,9 +110,8 @@ static inline int saa7146_wait_for_debi_
 		if (saa7146_read(dev, MC2) & 2)
 			break;
 		if (!loops--) {
-			printk(KERN_ERR "%s: %s timed out while waiting for "
-					"registers getting programmed\n",
-					dev->name, __func__);
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		udelay(1);
@@ -124,8 +124,8 @@ static inline int saa7146_wait_for_debi_
 			break;
 		saa7146_read(dev, MC2);
 		if (!loops--) {
-			DEB_S(("%s: %s timed out while waiting for transfer "
-				"completion\n", dev->name, __func__));
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		udelay(5);
@@ -264,7 +264,9 @@ int saa7146_pgtable_build_single(struct
 	ptr = pt->cpu;
 	for (i = 0; i < sglen; i++, list++) {
 /*
-		printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+		pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
+			 i, sg_dma_address(list), sg_dma_len(list),
+			 list->offset);
 */
 		for (p = 0; p * 4096 < list->length; p++, ptr++) {
 			*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
@@ -281,9 +283,9 @@ int saa7146_pgtable_build_single(struct
 
 /*
 	ptr = pt->cpu;
-	printk("offset: %d\n",pt->offset);
+	pr_debug("offset: %d\n", pt->offset);
 	for(i=0;i<5;i++) {
-		printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
+		pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
 	}
 */
 	return 0;
@@ -314,7 +316,7 @@ static irqreturn_t interrupt_hw(int irq,
 		}
 	}
 	if (0 != (isr & (MASK_27))) {
-		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
 		if (dev->vv_data && dev->vv_callback)
 			dev->vv_callback(dev,isr);
 		isr &= ~MASK_27;
@@ -333,14 +335,15 @@ static irqreturn_t interrupt_hw(int irq,
 		} else {
 			u32 psr = saa7146_read(dev, PSR);
 			u32 ssr = saa7146_read(dev, SSR);
-			printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
-			       dev->name, isr, psr, ssr);
+			pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+				dev->name, isr, psr, ssr);
 		}
 		isr &= ~(MASK_16|MASK_17);
 	}
 	if( 0 != isr ) {
-		ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
-		ERR(("disabling interrupt source(s)!\n"));
+		ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
+		    isr);
+		ERR("disabling interrupt source(s)!\n");
 		SAA7146_IER_DISABLE(dev,isr);
 	}
 	saa7146_write(dev, ISR, ack_isr);
@@ -360,15 +363,15 @@ static int saa7146_init_one(struct pci_d
 	/* clear out mem for sure */
 	dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
 	if (!dev) {
-		ERR(("out of memory.\n"));
+		ERR("out of memory\n");
 		goto out;
 	}
 
-	DEB_EE(("pci:%p\n",pci));
+	DEB_EE("pci:%p\n", pci);
 
 	err = pci_enable_device(pci);
 	if (err < 0) {
-		ERR(("pci_enable_device() failed.\n"));
+		ERR("pci_enable_device() failed\n");
 		goto err_free;
 	}
 
@@ -389,7 +392,7 @@ static int saa7146_init_one(struct pci_d
 	dev->mem = ioremap(pci_resource_start(pci, 0),
 			   pci_resource_len(pci, 0));
 	if (!dev->mem) {
-		ERR(("ioremap() failed.\n"));
+		ERR("ioremap() failed\n");
 		err = -ENODEV;
 		goto err_release;
 	}
@@ -414,7 +417,7 @@ static int saa7146_init_one(struct pci_d
 	err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
 			  dev->name, dev);
 	if (err < 0) {
-		ERR(("request_irq() failed.\n"));
+		ERR("request_irq() failed\n");
 		goto err_unmap;
 	}
 
@@ -444,7 +447,9 @@ static int saa7146_init_one(struct pci_d
 	/* create a nice device name */
 	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
 
-	INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
+	pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
+		dev->mem, dev->revision, pci->irq,
+		pci->subsystem_vendor, pci->subsystem_device);
 	dev->ext = ext;
 
 	mutex_init(&dev->v4l2_lock);
@@ -464,12 +469,12 @@ static int saa7146_init_one(struct pci_d
 	err = -ENODEV;
 
 	if (ext->probe && ext->probe(dev)) {
-		DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
+		DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
 		goto err_free_i2c;
 	}
 
 	if (ext->attach(dev, pci_ext)) {
-		DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
+		DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
 		goto err_free_i2c;
 	}
 	/* V4L extensions will set the pci drvdata to the v4l2_device in the
@@ -521,7 +526,7 @@ static void saa7146_remove_one(struct pc
 		{ NULL, 0 }
 	}, *p;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	dev->ext->detach(dev);
 	/* Zero the PCI drvdata after use. */
@@ -552,21 +557,21 @@ static void saa7146_remove_one(struct pc
 
 int saa7146_register_extension(struct saa7146_extension* ext)
 {
-	DEB_EE(("ext:%p\n",ext));
+	DEB_EE("ext:%p\n", ext);
 
 	ext->driver.name = ext->name;
 	ext->driver.id_table = ext->pci_tbl;
 	ext->driver.probe = saa7146_init_one;
 	ext->driver.remove = saa7146_remove_one;
 
-	printk("saa7146: register extension '%s'.\n",ext->name);
+	pr_info("register extension '%s'\n", ext->name);
 	return pci_register_driver(&ext->driver);
 }
 
 int saa7146_unregister_extension(struct saa7146_extension* ext)
 {
-	DEB_EE(("ext:%p\n",ext));
-	printk("saa7146: unregister extension '%s'.\n",ext->name);
+	DEB_EE("ext:%p\n", ext);
+	pr_info("unregister extension '%s'\n", ext->name);
 	pci_unregister_driver(&ext->driver);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_fops.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_fops.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_fops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_fops.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 /****************************************************************************/
 /* resource management functions, shamelessly stolen from saa7134 driver */
@@ -9,21 +12,23 @@ int saa7146_res_get(struct saa7146_fh *f
 	struct saa7146_vv *vv = dev->vv_data;
 
 	if (fh->resources & bit) {
-		DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
+		DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
+		      bit, vv->resources);
 		/* have it already allocated */
 		return 1;
 	}
 
 	/* is it free? */
 	if (vv->resources & bit) {
-		DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+		DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
+		      vv->resources, bit);
 		/* no, someone else uses it */
 		return 0;
 	}
 	/* it's free, grab it */
-	fh->resources  |= bit;
+	fh->resources |= bit;
 	vv->resources |= bit;
-	DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
+	DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
 	return 1;
 }
 
@@ -34,9 +39,9 @@ void saa7146_res_free(struct saa7146_fh
 
 	BUG_ON((fh->resources & bits) != bits);
 
-	fh->resources  &= ~bits;
+	fh->resources &= ~bits;
 	vv->resources &= ~bits;
-	DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
+	DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
 }
 
 
@@ -47,7 +52,7 @@ void saa7146_dma_free(struct saa7146_dev
 						struct saa7146_buf *buf)
 {
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-	DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+	DEB_EE("dev:%p, buf:%p\n", dev, buf);
 
 	BUG_ON(in_interrupt());
 
@@ -66,18 +71,19 @@ int saa7146_buffer_queue(struct saa7146_
 			 struct saa7146_buf *buf)
 {
 	assert_spin_locked(&dev->slock);
-	DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
+	DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
 
 	BUG_ON(!q);
 
 	if (NULL == q->curr) {
 		q->curr = buf;
-		DEB_D(("immediately activating buffer %p\n", buf));
+		DEB_D("immediately activating buffer %p\n", buf);
 		buf->activate(dev,buf,NULL);
 	} else {
 		list_add_tail(&buf->vb.queue,&q->queue);
 		buf->vb.state = VIDEOBUF_QUEUED;
-		DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
+		DEB_D("adding buffer %p to queue. (active buffer present)\n",
+		      buf);
 	}
 	return 0;
 }
@@ -87,14 +93,14 @@ void saa7146_buffer_finish(struct saa714
 			   int state)
 {
 	assert_spin_locked(&dev->slock);
-	DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
-	DEB_EE(("q->curr:%p\n",q->curr));
+	DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+	DEB_EE("q->curr:%p\n", q->curr);
 
 	BUG_ON(!q->curr);
 
 	/* finish current buffer */
 	if (NULL == q->curr) {
-		DEB_D(("aiii. no current buffer\n"));
+		DEB_D("aiii. no current buffer\n");
 		return;
 	}
 
@@ -112,7 +118,7 @@ void saa7146_buffer_next(struct saa7146_
 
 	BUG_ON(!q);
 
-	DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+	DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
 
 	assert_spin_locked(&dev->slock);
 	if (!list_empty(&q->queue)) {
@@ -122,10 +128,11 @@ void saa7146_buffer_next(struct saa7146_
 		if (!list_empty(&q->queue))
 			next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
 		q->curr = buf;
-		DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+		DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
+			buf, q->queue.prev, q->queue.next);
 		buf->activate(dev,buf,next);
 	} else {
-		DEB_INT(("no next buffer. stopping.\n"));
+		DEB_INT("no next buffer. stopping.\n");
 		if( 0 != vbi ) {
 			/* turn off video-dma3 */
 			saa7146_write(dev,MC1, MASK_20);
@@ -162,11 +169,11 @@ void saa7146_buffer_timeout(unsigned lon
 	struct saa7146_dev *dev = q->dev;
 	unsigned long flags;
 
-	DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
+	DEB_EE("dev:%p, dmaq:%p\n", dev, q);
 
 	spin_lock_irqsave(&dev->slock,flags);
 	if (q->curr) {
-		DEB_D(("timeout on %p\n", q->curr));
+		DEB_D("timeout on %p\n", q->curr);
 		saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
 	}
 
@@ -194,12 +201,12 @@ static int fops_open(struct file *file)
 
 	enum v4l2_buf_type type;
 
-	DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
+	DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
 
 	if (mutex_lock_interruptible(&saa7146_devices_lock))
 		return -ERESTARTSYS;
 
-	DEB_D(("using: %p\n",dev));
+	DEB_D("using: %p\n", dev);
 
 	type = vdev->vfl_type == VFL_TYPE_GRABBER
 	     ? V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -207,7 +214,7 @@ static int fops_open(struct file *file)
 
 	/* check if an extension is registered */
 	if( NULL == dev->ext ) {
-		DEB_S(("no extension registered for this device.\n"));
+		DEB_S("no extension registered for this device\n");
 		result = -ENODEV;
 		goto out;
 	}
@@ -215,7 +222,7 @@ static int fops_open(struct file *file)
 	/* allocate per open data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
 	if (NULL == fh) {
-		DEB_S(("cannot allocate memory for per open data.\n"));
+		DEB_S("cannot allocate memory for per open data\n");
 		result = -ENOMEM;
 		goto out;
 	}
@@ -225,13 +232,13 @@ static int fops_open(struct file *file)
 	fh->type = type;
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		DEB_S(("initializing vbi...\n"));
+		DEB_S("initializing vbi...\n");
 		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 			result = saa7146_vbi_uops.open(dev,file);
 		if (dev->ext_vv_data->vbi_fops.open)
 			dev->ext_vv_data->vbi_fops.open(file);
 	} else {
-		DEB_S(("initializing video...\n"));
+		DEB_S("initializing video...\n");
 		result = saa7146_video_uops.open(dev,file);
 	}
 
@@ -259,7 +266,7 @@ static int fops_release(struct file *fil
 	struct saa7146_fh  *fh  = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 
-	DEB_EE(("file:%p\n", file));
+	DEB_EE("file:%p\n", file);
 
 	if (mutex_lock_interruptible(&saa7146_devices_lock))
 		return -ERESTARTSYS;
@@ -289,12 +296,14 @@ static int fops_mmap(struct file *file,
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
 		q = &fh->video_q;
 		break;
 		}
 	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-		DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
 		q = &fh->vbi_q;
 		break;
 		}
@@ -312,14 +321,14 @@ static unsigned int fops_poll(struct fil
 	struct videobuf_buffer *buf = NULL;
 	struct videobuf_queue *q;
 
-	DEB_EE(("file:%p, poll:%p\n",file, wait));
+	DEB_EE("file:%p, poll:%p\n", file, wait);
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if( 0 == fh->vbi_q.streaming )
 			return videobuf_poll_stream(file, &fh->vbi_q, wait);
 		q = &fh->vbi_q;
 	} else {
-		DEB_D(("using video queue.\n"));
+		DEB_D("using video queue\n");
 		q = &fh->video_q;
 	}
 
@@ -327,17 +336,17 @@ static unsigned int fops_poll(struct fil
 		buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
 
 	if (!buf) {
-		DEB_D(("buf == NULL!\n"));
+		DEB_D("buf == NULL!\n");
 		return POLLERR;
 	}
 
 	poll_wait(file, &buf->done, wait);
 	if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
-		DEB_D(("poll succeeded!\n"));
+		DEB_D("poll succeeded!\n");
 		return POLLIN|POLLRDNORM;
 	}
 
-	DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
+	DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
 	return 0;
 }
 
@@ -346,18 +355,20 @@ static ssize_t fops_read(struct file *fi
 	struct saa7146_fh *fh = file->private_data;
 
 	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-//		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
+		       file, data, (unsigned long)count);
+*/
 		return saa7146_video_uops.read(file,data,count,ppos);
-		}
-	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-//		DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
+		       file, data, (unsigned long)count);
+*/
 		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 			return saa7146_vbi_uops.read(file,data,count,ppos);
-		else
-			return -EINVAL;
-		}
-		break;
+		return -EINVAL;
 	default:
 		BUG();
 		return 0;
@@ -398,22 +409,22 @@ static void vv_callback(struct saa7146_d
 {
 	u32 isr = status;
 
-	DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+	DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
 
 	if (0 != (isr & (MASK_27))) {
-		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
 		saa7146_video_uops.irq_done(dev,isr);
 	}
 
 	if (0 != (isr & (MASK_28))) {
 		u32 mc2 = saa7146_read(dev, MC2);
 		if( 0 != (mc2 & MASK_15)) {
-			DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
+			DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
 			wake_up(&dev->vv_data->vbi_wq);
 			saa7146_write(dev,MC2, MASK_31);
 			return;
 		}
-		DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS1 (0x%08x)\n", isr);
 		saa7146_vbi_uops.irq_done(dev,isr);
 	}
 }
@@ -429,13 +440,13 @@ int saa7146_vv_init(struct saa7146_dev*
 
 	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
 	if (vv == NULL) {
-		ERR(("out of memory. aborting.\n"));
+		ERR("out of memory. aborting.\n");
 		return -ENOMEM;
 	}
 	ext_vv->ops = saa7146_video_ioctl_ops;
 	ext_vv->core_ops = &saa7146_video_ioctl_ops;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	/* set default values for video parts of the saa7146 */
 	saa7146_write(dev, BCS_CTRL, 0x80400040);
@@ -450,7 +461,7 @@ int saa7146_vv_init(struct saa7146_dev*
 
 	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
 	if( NULL == vv->d_clipping.cpu_addr ) {
-		ERR(("out of memory. aborting.\n"));
+		ERR("out of memory. aborting.\n");
 		kfree(vv);
 		return -1;
 	}
@@ -471,7 +482,7 @@ int saa7146_vv_release(struct saa7146_de
 {
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	v4l2_device_unregister(&dev->v4l2_dev);
 	pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
@@ -490,7 +501,7 @@ int saa7146_register_device(struct video
 	int err;
 	int i;
 
-	DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
+	DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 
 	// released by vfd->release
 	vfd = video_device_alloc();
@@ -509,13 +520,13 @@ int saa7146_register_device(struct video
 
 	err = video_register_device(vfd, type, -1);
 	if (err < 0) {
-		ERR(("cannot register v4l2 device. skipping.\n"));
+		ERR("cannot register v4l2 device. skipping.\n");
 		video_device_release(vfd);
 		return err;
 	}
 
-	INFO(("%s: registered device %s [v4l2]\n",
-		dev->name, video_device_node_name(vfd)));
+	pr_info("%s: registered device %s [v4l2]\n",
+		dev->name, video_device_node_name(vfd));
 
 	*vid = vfd;
 	return 0;
@@ -524,7 +535,7 @@ EXPORT_SYMBOL_GPL(saa7146_register_devic
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	video_unregister_device(*vid);
 	*vid = NULL;
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_hlp.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_hlp.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_hlp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_hlp.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <media/saa7146_vv.h>
 
 static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
@@ -711,8 +714,8 @@ static int calculate_video_dma_grab_pack
 
 	int depth = sfmt->depth;
 
-	DEB_CAP(("[size=%dx%d,fields=%s]\n",
-		width,height,v4l2_field_names[field]));
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
 
 	if( bytesperline != 0) {
 		vdma1.pitch = bytesperline*2;
@@ -837,8 +840,8 @@ static int calculate_video_dma_grab_plan
 	BUG_ON(0 == buf->pt[1].dma);
 	BUG_ON(0 == buf->pt[2].dma);
 
-	DEB_CAP(("[size=%dx%d,fields=%s]\n",
-		width,height,v4l2_field_names[field]));
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
 
 	/* fixme: look at bytesperline! */
 
@@ -998,12 +1001,12 @@ void saa7146_set_capture(struct saa7146_
 	struct saa7146_vv *vv = dev->vv_data;
 	u32 vdma1_prot_addr;
 
-	DEB_CAP(("buf:%p, next:%p\n",buf,next));
+	DEB_CAP("buf:%p, next:%p\n", buf, next);
 
 	vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
 	if( 0 == vdma1_prot_addr ) {
 		/* clear out beginning of streaming bit (rps register 0)*/
-		DEB_CAP(("forcing sync to new frame\n"));
+		DEB_CAP("forcing sync to new frame\n");
 		saa7146_write(dev, MC2, MASK_27 );
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_i2c.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_i2c.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,8 +1,10 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
 
 static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
 {
-//fm	DEB_I2C(("'%s'.\n", adapter->name));
+	/* DEB_I2C("'%s'\n", adapter->name); */
 
 	return	  I2C_FUNC_I2C
 		| I2C_FUNC_SMBUS_QUICK
@@ -14,9 +16,7 @@ static u32 saa7146_i2c_func(struct i2c_a
 static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
 {
 	u32 iicsta = saa7146_read(dev, I2C_STATUS);
-/*
-	DEB_I2C(("status: 0x%08x\n",iicsta));
-*/
+	/* DEB_I2C("status: 0x%08x\n", iicsta); */
 	return iicsta;
 }
 
@@ -39,10 +39,11 @@ static int saa7146_i2c_msg_prepare(const
 	   plus one extra byte to address the device */
 	mem = 1 + ((mem-1) / 3);
 
-	/* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
-	   size. if we exceed this limit... */
-	if ( (4*mem) > SAA7146_I2C_MEM ) {
-//fm		DEB_I2C(("cannot prepare i2c-message.\n"));
+	/* we assume that op points to a memory of at least
+	 * SAA7146_I2C_MEM bytes size. if we exceed this limit...
+	 */
+	if ((4 * mem) > SAA7146_I2C_MEM) {
+		/* DEB_I2C("cannot prepare i2c-message\n"); */
 		return -ENOMEM;
 	}
 
@@ -123,7 +124,7 @@ static int saa7146_i2c_reset(struct saa7
 	if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
 
 		/* yes, kill ongoing operation */
-		DEB_I2C(("busy_state detected.\n"));
+		DEB_I2C("busy_state detected\n");
 
 		/* set "ABORT-OPERATION"-bit (bit 7)*/
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
@@ -141,7 +142,7 @@ static int saa7146_i2c_reset(struct saa7
 
 	if ( dev->i2c_bitrate != status ) {
 
-		DEB_I2C(("error_state detected. status:0x%08x\n",status));
+		DEB_I2C("error_state detected. status:0x%08x\n", status);
 
 		/* Repeat the abort operation. This seems to be necessary
 		   after serious protocol errors caused by e.g. the SAA7740 */
@@ -164,7 +165,7 @@ static int saa7146_i2c_reset(struct saa7
 	/* if any error is still present, a fatal error has occurred ... */
 	status = saa7146_i2c_status(dev);
 	if ( dev->i2c_bitrate != status ) {
-		DEB_I2C(("fatal error. status:0x%08x\n",status));
+		DEB_I2C("fatal error. status:0x%08x\n", status);
 		return -1;
 	}
 
@@ -181,7 +182,8 @@ static int saa7146_i2c_writeout(struct s
 	unsigned long timeout;
 
 	/* write out i2c-command */
-	DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
+	DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
+		*dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
 
 	if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
 
@@ -202,7 +204,7 @@ static int saa7146_i2c_writeout(struct s
 				/* a signal arrived */
 				return -ERESTARTSYS;
 
-			printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+			pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
 				dev->name, __func__);
 			return -EIO;
 		}
@@ -220,7 +222,7 @@ static int saa7146_i2c_writeout(struct s
 				break;
 			}
 			if (time_after(jiffies,timeout)) {
-				printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+				pr_warn("%s %s: timed out waiting for MC2\n",
 					dev->name, __func__);
 				return -EIO;
 			}
@@ -237,7 +239,7 @@ static int saa7146_i2c_writeout(struct s
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
 				 */
-				printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+				pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
 					dev->name, __func__);
 				return -EIO;
 			}
@@ -257,24 +259,24 @@ static int saa7146_i2c_writeout(struct s
 		if ( 0 == (status & SAA7146_I2C_ERR) ||
 		     0 == (status & SAA7146_I2C_BUSY) ) {
 			/* it may take some time until ERR goes high - ignore */
-			DEB_I2C(("unexpected i2c status %04x\n", status));
+			DEB_I2C("unexpected i2c status %04x\n", status);
 		}
 		if( 0 != (status & SAA7146_I2C_SPERR) ) {
-			DEB_I2C(("error due to invalid start/stop condition.\n"));
+			DEB_I2C("error due to invalid start/stop condition\n");
 		}
 		if( 0 != (status & SAA7146_I2C_DTERR) ) {
-			DEB_I2C(("error in data transmission.\n"));
+			DEB_I2C("error in data transmission\n");
 		}
 		if( 0 != (status & SAA7146_I2C_DRERR) ) {
-			DEB_I2C(("error when receiving data.\n"));
+			DEB_I2C("error when receiving data\n");
 		}
 		if( 0 != (status & SAA7146_I2C_AL) ) {
-			DEB_I2C(("error because arbitration lost.\n"));
+			DEB_I2C("error because arbitration lost\n");
 		}
 
 		/* we handle address-errors here */
 		if( 0 != (status & SAA7146_I2C_APERR) ) {
-			DEB_I2C(("error in address phase.\n"));
+			DEB_I2C("error in address phase\n");
 			return -EREMOTEIO;
 		}
 
@@ -284,7 +286,7 @@ static int saa7146_i2c_writeout(struct s
 	/* read back data, just in case we were reading ... */
 	*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
 
-	DEB_I2C(("after: 0x%08x\n",*dword));
+	DEB_I2C("after: 0x%08x\n", *dword);
 	return 0;
 }
 
@@ -299,7 +301,7 @@ static int saa7146_i2c_transfer(struct s
 		return -ERESTARTSYS;
 
 	for(i=0;i<num;i++) {
-		DEB_I2C(("msg:%d/%d\n",i+1,num));
+		DEB_I2C("msg:%d/%d\n", i+1, num);
 	}
 
 	/* prepare the message(s), get number of u32s to transfer */
@@ -316,7 +318,7 @@ static int saa7146_i2c_transfer(struct s
 		/* reset the i2c-device if necessary */
 		err = saa7146_i2c_reset(dev);
 		if ( 0 > err ) {
-			DEB_I2C(("could not reset i2c-device.\n"));
+			DEB_I2C("could not reset i2c-device\n");
 			goto out;
 		}
 
@@ -336,7 +338,7 @@ static int saa7146_i2c_transfer(struct s
 				   address error and trust the saa7146 address error detection. */
 				if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
 					goto out;
-				DEB_I2C(("error while sending message(s). starting again.\n"));
+				DEB_I2C("error while sending message(s). starting again\n");
 				break;
 			}
 		}
@@ -356,13 +358,13 @@ static int saa7146_i2c_transfer(struct s
 
 	/* if any things had to be read, get the results */
 	if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
-		DEB_I2C(("could not cleanup i2c-message.\n"));
+		DEB_I2C("could not cleanup i2c-message\n");
 		err = -1;
 		goto out;
 	}
 
 	/* return the number of delivered messages */
-	DEB_I2C(("transmission successful. (msg:%d).\n",err));
+	DEB_I2C("transmission successful. (msg:%d)\n", err);
 out:
 	/* another bug in revision 0: the i2c-registers get uploaded randomly by other
 	   uploads, so we better clear them out before continuing */
@@ -370,7 +372,7 @@ out:
 		__le32 zero = 0;
 		saa7146_i2c_reset(dev);
 		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
-			INFO(("revision 0 error. this should never happen.\n"));
+			pr_info("revision 0 error. this should never happen\n");
 		}
 	}
 
@@ -400,7 +402,7 @@ static struct i2c_algorithm saa7146_algo
 
 int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
 {
-	DEB_EE(("bitrate: 0x%08x\n",bitrate));
+	DEB_EE("bitrate: 0x%08x\n", bitrate);
 
 	/* enable i2c-port pins */
 	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_vbi.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_vbi.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@ static int vbi_workaround(struct saa7146
 
 	DECLARE_WAITQUEUE(wait, current);
 
-	DEB_VBI(("dev:%p\n",dev));
+	DEB_VBI("dev:%p\n", dev);
 
 	/* once again, a bug in the saa7146: the brs acquisition
 	   is buggy and especially the BXO-counter does not work
@@ -40,14 +40,14 @@ static int vbi_workaround(struct saa7146
 	WRITE_RPS1(0xc000008c);
 	/* wait for vbi_a or vbi_b*/
 	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
-		DEB_D(("...using port b\n"));
+		DEB_D("...using port b\n");
 		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
 		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
 /*
 		WRITE_RPS1(CMD_PAUSE | MASK_09);
 */
 	} else {
-		DEB_D(("...using port a\n"));
+		DEB_D("...using port a\n");
 		WRITE_RPS1(CMD_PAUSE | MASK_10);
 	}
 	/* upload brs */
@@ -103,7 +103,7 @@ static int vbi_workaround(struct saa7146
 
 		schedule();
 
-		DEB_VBI(("brs bug workaround %d/1.\n",i));
+		DEB_VBI("brs bug workaround %d/1\n", i);
 
 		remove_wait_queue(&vv->vbi_wq, &wait);
 		current->state = TASK_RUNNING;
@@ -116,7 +116,8 @@ static int vbi_workaround(struct saa7146
 
 		if(signal_pending(current)) {
 
-			DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
+			DEB_VBI("aborted (rps:0x%08x)\n",
+				saa7146_read(dev, RPS_ADDR1));
 
 			/* stop rps1 for sure */
 			saa7146_write(dev, MC1, MASK_29);
@@ -207,7 +208,7 @@ static int buffer_activate(struct saa714
 	struct saa7146_vv *vv = dev->vv_data;
 	buf->vb.state = VIDEOBUF_ACTIVE;
 
-	DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
+	DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
 	saa7146_set_vbi_capture(dev,buf,next);
 
 	mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
@@ -228,10 +229,10 @@ static int buffer_prepare(struct videobu
 	llength = vbi_pixel_to_capture;
 	size = lines * llength;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
-		DEB_VBI(("size mismatch.\n"));
+		DEB_VBI("size mismatch\n");
 		return -EINVAL;
 	}
 
@@ -263,7 +264,7 @@ static int buffer_prepare(struct videobu
 	return 0;
 
  oops:
-	DEB_VBI(("error out.\n"));
+	DEB_VBI("error out\n");
 	saa7146_dma_free(dev,q,buf);
 
 	return err;
@@ -279,7 +280,7 @@ static int buffer_setup(struct videobuf_
 	*size = lines * llength;
 	*count = 2;
 
-	DEB_VBI(("count:%d, size:%d\n",*count,*size));
+	DEB_VBI("count:%d, size:%d\n", *count, *size);
 
 	return 0;
 }
@@ -292,7 +293,7 @@ static void buffer_queue(struct videobuf
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 	saa7146_buffer_queue(dev,&vv->vbi_q,buf);
 }
 
@@ -303,7 +304,7 @@ static void buffer_release(struct videob
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 	saa7146_dma_free(dev,q,buf);
 }
 
@@ -321,7 +322,7 @@ static void vbi_stop(struct saa7146_fh *
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 	unsigned long flags;
-	DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	spin_lock_irqsave(&dev->slock,flags);
 
@@ -354,14 +355,14 @@ static void vbi_read_timeout(unsigned lo
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	vbi_stop(fh, file);
 }
 
 static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 {
-	DEB_VBI(("dev:%p\n",dev));
+	DEB_VBI("dev:%p\n", dev);
 
 	INIT_LIST_HEAD(&vv->vbi_q.queue);
 
@@ -380,11 +381,11 @@ static int vbi_open(struct saa7146_dev *
 	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
 	int ret = 0;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
 	if (0 == ret) {
-		DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+		DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
 		return -EBUSY;
 	}
 
@@ -425,7 +426,7 @@ static int vbi_open(struct saa7146_dev *
 		saa7146_write(dev, BRS_CTRL, 0x00000001);
 
 		if (0 != (ret = vbi_workaround(dev))) {
-			DEB_VBI(("vbi workaround failed!\n"));
+			DEB_VBI("vbi workaround failed!\n");
 			/* return ret;*/
 		}
 	}
@@ -439,7 +440,7 @@ static void vbi_close(struct saa7146_dev
 {
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	if( fh == vv->vbi_streaming ) {
 		vbi_stop(fh, file);
@@ -453,13 +454,13 @@ static void vbi_irq_done(struct saa7146_
 	spin_lock(&dev->slock);
 
 	if (vv->vbi_q.curr) {
-		DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
+		DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_q.curr);
 		/* this must be += 2, one count for each field */
 		vv->vbi_fieldcount+=2;
 		vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
 		saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
 	} else {
-		DEB_VBI(("dev:%p\n",dev));
+		DEB_VBI("dev:%p\n", dev);
 	}
 	saa7146_buffer_next(dev,&vv->vbi_q,1);
 
@@ -473,7 +474,7 @@ static ssize_t vbi_read(struct file *fil
 	struct saa7146_vv *vv = dev->vv_data;
 	ssize_t ret = 0;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	if( NULL == vv->vbi_streaming ) {
 		// fixme: check if dma3 is available
@@ -482,7 +483,8 @@ static ssize_t vbi_read(struct file *fil
 	}
 
 	if( fh != vv->vbi_streaming ) {
-		DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
+		DEB_VBI("open %p is already using vbi capture\n",
+			vv->vbi_streaming);
 		return -EBUSY;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/saa7146_video.c linux-libre-3.2-gnu1/drivers/media/common/saa7146_video.c
--- linux-libre-3.1-gnu1/drivers/media/common/saa7146_video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/saa7146_video.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,8 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
 #include <media/v4l2-chip-ident.h>
+#include <linux/module.h>
 
 static int max_memory = 32;
 
@@ -94,7 +97,7 @@ struct saa7146_format* saa7146_format_by
 		}
 	}
 
-	DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
+	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
 	return NULL;
 }
 
@@ -107,32 +110,32 @@ int saa7146_start_preview(struct saa7146
 	struct v4l2_format fmt;
 	int ret = 0, err = 0;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	/* check if we have overlay informations */
 	if( NULL == fh->ov.fh ) {
-		DEB_D(("no overlay data available. try S_FMT first.\n"));
+		DEB_D("no overlay data available. try S_FMT first.\n");
 		return -EAGAIN;
 	}
 
 	/* check if streaming capture is running */
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D(("streaming capture is active.\n"));
+		DEB_D("streaming capture is active\n");
 		return -EBUSY;
 	}
 
 	/* check if overlay is running */
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		if (vv->video_fh == fh) {
-			DEB_D(("overlay is already active.\n"));
+			DEB_D("overlay is already active\n");
 			return 0;
 		}
-		DEB_D(("overlay is already active in another open.\n"));
+		DEB_D("overlay is already active in another open\n");
 		return -EBUSY;
 	}
 
 	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
-		DEB_D(("cannot get necessary overlay resources\n"));
+		DEB_D("cannot get necessary overlay resources\n");
 		return -EBUSY;
 	}
 
@@ -145,13 +148,13 @@ int saa7146_start_preview(struct saa7146
 	fh->ov.win = fmt.fmt.win;
 	vv->ov_data = &fh->ov;
 
-	DEB_D(("%dx%d+%d+%d %s field=%s\n",
-		fh->ov.win.w.width,fh->ov.win.w.height,
-		fh->ov.win.w.left,fh->ov.win.w.top,
-		vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
+	DEB_D("%dx%d+%d+%d %s field=%s\n",
+	      fh->ov.win.w.width, fh->ov.win.w.height,
+	      fh->ov.win.w.left, fh->ov.win.w.top,
+	      vv->ov_fmt->name, v4l2_field_names[fh->ov.win.field]);
 
 	if (0 != (ret = saa7146_enable_overlay(fh))) {
-		DEB_D(("enabling overlay failed: %d\n",ret));
+		DEB_D("enabling overlay failed: %d\n", ret);
 		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		return ret;
 	}
@@ -168,22 +171,22 @@ int saa7146_stop_preview(struct saa7146_
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	/* check if streaming capture is running */
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D(("streaming capture is active.\n"));
+		DEB_D("streaming capture is active\n");
 		return -EBUSY;
 	}
 
 	/* check if overlay is running at all */
 	if ((vv->video_status & STATUS_OVERLAY) == 0) {
-		DEB_D(("no active overlay.\n"));
+		DEB_D("no active overlay\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_D(("overlay is active, but in another open.\n"));
+		DEB_D("overlay is active, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -268,7 +271,7 @@ static int saa7146_pgtable_build(struct
 	int length = dma->sglen;
 	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
-	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
+	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
 
 	if( 0 != IS_PLANAR(sfmt->trans)) {
 		struct saa7146_pgtable *pt1 = &buf->pt[0];
@@ -288,7 +291,8 @@ static int saa7146_pgtable_build(struct
 				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/4))%PAGE_SIZE;
-				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
 				break;
 			}
 			case 16: {
@@ -298,7 +302,8 @@ static int saa7146_pgtable_build(struct
 				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/2))%PAGE_SIZE;
-				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
 				break;
 			}
 			default: {
@@ -387,23 +392,23 @@ static int video_begin(struct saa7146_fh
 	unsigned int resource;
 	int ret = 0, err = 0;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	if ((vv->video_status & STATUS_CAPTURE) != 0) {
 		if (vv->video_fh == fh) {
-			DEB_S(("already capturing.\n"));
+			DEB_S("already capturing\n");
 			return 0;
 		}
-		DEB_S(("already capturing in another open.\n"));
+		DEB_S("already capturing in another open\n");
 		return -EBUSY;
 	}
 
 	if ((vv->video_status & STATUS_OVERLAY) != 0) {
-		DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+		DEB_S("warning: suspending overlay video for streaming capture\n");
 		vv->ov_suspend = vv->video_fh;
 		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (0 != err) {
-			DEB_D(("suspending video failed. aborting\n"));
+			DEB_D("suspending video failed. aborting\n");
 			return err;
 		}
 	}
@@ -420,7 +425,7 @@ static int video_begin(struct saa7146_fh
 
 	ret = saa7146_res_get(fh, resource);
 	if (0 == ret) {
-		DEB_S(("cannot get capture resource %d\n",resource));
+		DEB_S("cannot get capture resource %d\n", resource);
 		if (vv->ov_suspend != NULL) {
 			saa7146_start_preview(vv->ov_suspend);
 			vv->ov_suspend = NULL;
@@ -448,15 +453,15 @@ static int video_end(struct saa7146_fh *
 	unsigned long flags;
 	unsigned int resource;
 	u32 dmas = 0;
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-		DEB_S(("not capturing.\n"));
+		DEB_S("not capturing\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_S(("capturing, but in another open.\n"));
+		DEB_S("capturing, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -530,7 +535,7 @@ static int vidioc_s_fbuf(struct file *fi
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_format *fmt;
 
-	DEB_EE(("VIDIOC_S_FBUF\n"));
+	DEB_EE("VIDIOC_S_FBUF\n");
 
 	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
@@ -542,13 +547,13 @@ static int vidioc_s_fbuf(struct file *fi
 
 	/* planar formats are not allowed for overlay video, clipping and video dma would clash */
 	if (fmt->flags & FORMAT_IS_PLANAR)
-		DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
-					(char *)&fmt->pixelformat));
+		DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
+		      (char *)&fmt->pixelformat);
 
 	/* check if overlay is running */
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		if (vv->video_fh != fh) {
-			DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+			DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
 			return -EBUSY;
 		}
 	}
@@ -559,7 +564,7 @@ static int vidioc_s_fbuf(struct file *fi
 
 	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
 		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
-		DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
+		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
 	}
 	return 0;
 }
@@ -588,7 +593,7 @@ static int vidioc_queryctrl(struct file
 	if (ctrl == NULL)
 		return -EINVAL;
 
-	DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
+	DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
 	*c = *ctrl;
 	return 0;
 }
@@ -607,25 +612,25 @@ static int vidioc_g_ctrl(struct file *fi
 	case V4L2_CID_BRIGHTNESS:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0xff & (value >> 24);
-		DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
+		DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value);
 		break;
 	case V4L2_CID_CONTRAST:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0x7f & (value >> 16);
-		DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
+		DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
 		break;
 	case V4L2_CID_SATURATION:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0x7f & (value >> 0);
-		DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
+		DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
 		break;
 	case V4L2_CID_VFLIP:
 		c->value = vv->vflip;
-		DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
+		DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
 		break;
 	case V4L2_CID_HFLIP:
 		c->value = vv->hflip;
-		DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
+		DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
 		break;
 	default:
 		return -EINVAL;
@@ -641,7 +646,7 @@ static int vidioc_s_ctrl(struct file *fi
 
 	ctrl = ctrl_by_id(c->id);
 	if (NULL == ctrl) {
-		DEB_D(("unknown control %d\n", c->id));
+		DEB_D("unknown control %d\n", c->id);
 		return -EINVAL;
 	}
 
@@ -686,14 +691,14 @@ static int vidioc_s_ctrl(struct file *fi
 	case V4L2_CID_HFLIP:
 		/* fixme: we can support changing VFLIP and HFLIP here... */
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+			DEB_D("V4L2_CID_HFLIP while active capture\n");
 			return -EBUSY;
 		}
 		vv->hflip = c->value;
 		break;
 	case V4L2_CID_VFLIP:
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+			DEB_D("V4L2_CID_VFLIP while active capture\n");
 			return -EBUSY;
 		}
 		vv->vflip = c->value;
@@ -748,7 +753,7 @@ static int vidioc_try_fmt_vid_cap(struct
 	int maxw, maxh;
 	int calc_bpl;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
 
 	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
 	if (NULL == fmt)
@@ -777,7 +782,7 @@ static int vidioc_try_fmt_vid_cap(struct
 		vv->last_field = V4L2_FIELD_INTERLACED;
 		break;
 	default:
-		DEB_D(("no known field mode '%d'.\n", field));
+		DEB_D("no known field mode '%d'\n", field);
 		return -EINVAL;
 	}
 
@@ -796,8 +801,9 @@ static int vidioc_try_fmt_vid_cap(struct
 		f->fmt.pix.bytesperline = calc_bpl;
 
 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
-	DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
-			f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
+	DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
+	      f->fmt.pix.width, f->fmt.pix.height,
+	      f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
 
 	return 0;
 }
@@ -811,22 +817,23 @@ static int vidioc_try_fmt_vid_overlay(st
 	enum v4l2_field field;
 	int maxw, maxh;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	if (NULL == vv->ov_fb.base) {
-		DEB_D(("no fb base set.\n"));
+		DEB_D("no fb base set\n");
 		return -EINVAL;
 	}
 	if (NULL == vv->ov_fmt) {
-		DEB_D(("no fb fmt set.\n"));
+		DEB_D("no fb fmt set\n");
 		return -EINVAL;
 	}
 	if (win->w.width < 48 || win->w.height < 32) {
-		DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
+		DEB_D("min width/height. (%d,%d)\n",
+		      win->w.width, win->w.height);
 		return -EINVAL;
 	}
 	if (win->clipcount > 16) {
-		DEB_D(("clipcount too big.\n"));
+		DEB_D("clipcount too big\n");
 		return -EINVAL;
 	}
 
@@ -848,7 +855,7 @@ static int vidioc_try_fmt_vid_overlay(st
 	case V4L2_FIELD_INTERLACED:
 		break;
 	default:
-		DEB_D(("no known field mode '%d'.\n", field));
+		DEB_D("no known field mode '%d'\n", field);
 		return -EINVAL;
 	}
 
@@ -868,16 +875,17 @@ static int vidioc_s_fmt_vid_cap(struct f
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_EE(("streaming capture is active\n"));
+		DEB_EE("streaming capture is active\n");
 		return -EBUSY;
 	}
 	err = vidioc_try_fmt_vid_cap(file, fh, f);
 	if (0 != err)
 		return err;
 	fh->video_fmt = f->fmt.pix;
-	DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
+	DEB_EE("set to pixelformat '%4.4s'\n",
+	       (char *)&fh->video_fmt.pixelformat);
 	return 0;
 }
 
@@ -888,7 +896,7 @@ static int vidioc_s_fmt_vid_overlay(stru
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
 	err = vidioc_try_fmt_vid_overlay(file, fh, f);
 	if (0 != err)
 		return err;
@@ -931,7 +939,7 @@ static int vidioc_g_std(struct file *fil
 		if (e->index < 0 )
 			return -EINVAL;
 		if( e->index < dev->ext_vv_data->num_stds ) {
-			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
+			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
 			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
 			return 0;
 		}
@@ -946,10 +954,10 @@ static int vidioc_s_std(struct file *fil
 	int found = 0;
 	int err, i;
 
-	DEB_EE(("VIDIOC_S_STD\n"));
+	DEB_EE("VIDIOC_S_STD\n");
 
 	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
-		DEB_D(("cannot change video standard while streaming capture is active\n"));
+		DEB_D("cannot change video standard while streaming capture is active\n");
 		return -EBUSY;
 	}
 
@@ -957,7 +965,7 @@ static int vidioc_s_std(struct file *fil
 		vv->ov_suspend = vv->video_fh;
 		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (0 != err) {
-			DEB_D(("suspending video failed. aborting\n"));
+			DEB_D("suspending video failed. aborting\n");
 			return err;
 		}
 	}
@@ -978,11 +986,11 @@ static int vidioc_s_std(struct file *fil
 	}
 
 	if (!found) {
-		DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+		DEB_EE("VIDIOC_S_STD: standard not found\n");
 		return -EINVAL;
 	}
 
-	DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
+	DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
 	return 0;
 }
 
@@ -990,7 +998,7 @@ static int vidioc_overlay(struct file *f
 {
 	int err;
 
-	DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
+	DEB_D("VIDIOC_OVERLAY on:%d\n", on);
 	if (on)
 		err = saa7146_start_preview(fh);
 	else
@@ -1047,7 +1055,7 @@ static int vidioc_streamon(struct file *
 	struct saa7146_fh *fh = __fh;
 	int err;
 
-	DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
+	DEB_D("VIDIOC_STREAMON, type:%d\n", type);
 
 	err = video_begin(fh);
 	if (err)
@@ -1066,18 +1074,18 @@ static int vidioc_streamoff(struct file
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
+	DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
 
 	/* ugly: we need to copy some checks from video_end(),
 	   because videobuf_streamoff() relies on the capture running.
 	   check and fix this */
 	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-		DEB_S(("not capturing.\n"));
+		DEB_S("not capturing\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_S(("capturing, but in another open.\n"));
+		DEB_S("capturing, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -1087,7 +1095,7 @@ static int vidioc_streamoff(struct file
 	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
 		err = videobuf_streamoff(&fh->vbi_q);
 	if (0 != err) {
-		DEB_D(("warning: videobuf_streamoff() failed.\n"));
+		DEB_D("warning: videobuf_streamoff() failed\n");
 		video_end(fh, file);
 	} else {
 		err = video_end(fh, file);
@@ -1174,25 +1182,27 @@ static int buffer_prepare(struct videobu
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 	int size,err = 0;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 
 	/* sanity checks */
 	if (fh->video_fmt.width  < 48 ||
 	    fh->video_fmt.height < 32 ||
 	    fh->video_fmt.width  > vv->standard->h_max_out ||
 	    fh->video_fmt.height > vv->standard->v_max_out) {
-		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
+		DEB_D("w (%d) / h (%d) out of bounds\n",
+		      fh->video_fmt.width, fh->video_fmt.height);
 		return -EINVAL;
 	}
 
 	size = fh->video_fmt.sizeimage;
 	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
-		DEB_D(("size mismatch.\n"));
+		DEB_D("size mismatch\n");
 		return -EINVAL;
 	}
 
-	DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
-		fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
+	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+		fh->video_fmt.width, fh->video_fmt.height,
+		size, v4l2_field_names[fh->video_fmt.field]);
 	if (buf->vb.width  != fh->video_fmt.width  ||
 	    buf->vb.bytesperline != fh->video_fmt.bytesperline ||
 	    buf->vb.height != fh->video_fmt.height ||
@@ -1238,7 +1248,7 @@ static int buffer_prepare(struct videobu
 	return 0;
 
  oops:
-	DEB_D(("error out.\n"));
+	DEB_D("error out\n");
 	saa7146_dma_free(dev,q,buf);
 
 	return err;
@@ -1259,7 +1269,7 @@ static int buffer_setup(struct videobuf_
 		*count = (max_memory*1048576) / *size;
 	}
 
-	DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
+	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
 
 	return 0;
 }
@@ -1272,7 +1282,7 @@ static void buffer_queue(struct videobuf
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 	saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
 }
 
@@ -1283,7 +1293,7 @@ static void buffer_release(struct videob
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 
 	saa7146_dma_free(dev,q,buf);
 
@@ -1347,18 +1357,14 @@ static void video_close(struct saa7146_d
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	struct videobuf_queue *q = &fh->video_q;
-	int err;
 
-	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		err = video_end(fh, file);
-	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
-		err = saa7146_stop_preview(fh);
-	}
+	if (IS_CAPTURE_ACTIVE(fh) != 0)
+		video_end(fh, file);
+	else if (IS_OVERLAY_ACTIVE(fh) != 0)
+		saa7146_stop_preview(fh);
 
 	videobuf_stop(q);
-
 	/* hmm, why is this function declared void? */
-	/* return err */
 }
 
 
@@ -1368,7 +1374,7 @@ static void video_irq_done(struct saa714
 	struct saa7146_dmaqueue *q = &vv->video_q;
 
 	spin_lock(&dev->slock);
-	DEB_CAP(("called.\n"));
+	DEB_CAP("called\n");
 
 	/* only finish the buffer if we have one... */
 	if( NULL != q->curr ) {
@@ -1386,15 +1392,15 @@ static ssize_t video_read(struct file *f
 	struct saa7146_vv *vv = dev->vv_data;
 	ssize_t ret = 0;
 
-	DEB_EE(("called.\n"));
+	DEB_EE("called\n");
 
 	if ((vv->video_status & STATUS_CAPTURE) != 0) {
 		/* fixme: should we allow read() captures while streaming capture? */
 		if (vv->video_fh == fh) {
-			DEB_S(("already capturing.\n"));
+			DEB_S("already capturing\n");
 			return -EBUSY;
 		}
-		DEB_S(("already capturing in another open.\n"));
+		DEB_S("already capturing in another open\n");
 		return -EBUSY;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/Makefile linux-libre-3.2-gnu1/drivers/media/common/tuners/Makefile
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -28,5 +28,5 @@ obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max
 obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/mt20xx.c linux-libre-3.2-gnu1/drivers/media/common/tuners/mt20xx.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/mt20xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/mt20xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -430,11 +430,10 @@ static void mt2050_set_antenna(struct dv
 {
 	struct microtune_priv *priv = fe->tuner_priv;
 	unsigned char buf[2];
-	int ret;
 
 	buf[0] = 6;
 	buf[1] = antenna ? 0x11 : 0x10;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
 	tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
 }
 
@@ -574,21 +573,20 @@ static int mt2050_init(struct dvb_fronte
 {
 	struct microtune_priv *priv = fe->tuner_priv;
 	unsigned char buf[2];
-	int ret;
 
-	buf[0]=6;
-	buf[1]=0x10;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); //  power
+	buf[0] = 6;
+	buf[1] = 0x10;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
 
-	buf[0]=0x0f;
-	buf[1]=0x0f;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
+	buf[0] = 0x0f;
+	buf[1] = 0x0f;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
 
-	buf[0]=0x0d;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-	tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+	buf[0] = 0x0d;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
+	tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
 
-	tuner_dbg("mt2050: sro is %x\n",buf[0]);
+	tuner_dbg("mt2050: sro is %x\n", buf[0]);
 
 	memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/mxl5005s.c linux-libre-3.2-gnu1/drivers/media/common/tuners/mxl5005s.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/mxl5005s.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/mxl5005s.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,7 +309,6 @@ static u16 MXL_ControlWrite_Group(struct
 static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
 static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
 	u8 *RegVal, int *count);
-static u32 MXL_GetXtalInt(u32 Xtal_Freq);
 static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
 static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
 static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
@@ -2307,14 +2306,6 @@ static u16 MXL_IFSynthInit(struct dvb_fr
 	return status ;
 }
 
-static u32 MXL_GetXtalInt(u32 Xtal_Freq)
-{
-	if ((Xtal_Freq % 1000000) == 0)
-		return (Xtal_Freq / 10000);
-	else
-		return (((Xtal_Freq / 1000000) + 1)*100);
-}
-
 static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
 {
 	struct mxl5005s_state *state = fe->tuner_priv;
@@ -2324,13 +2315,10 @@ static u16 MXL_TuneRF(struct dvb_fronten
 	u32 Kdbl_RF = 2;
 	u32 tg_divval;
 	u32 tg_lo;
-	u32 Xtal_Int;
 
 	u32 Fref_TG;
 	u32 Fvco;
 
-	Xtal_Int = MXL_GetXtalInt(state->Fxtal);
-
 	state->RF_IN = RF_Freq;
 
 	MXL_SynthRFTGLO_Calc(fe);
@@ -2779,6 +2767,16 @@ static u16 MXL_TuneRF(struct dvb_fronten
 	tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
 
 	/* below equation is same as above but much harder to debug.
+	 *
+	 * static u32 MXL_GetXtalInt(u32 Xtal_Freq)
+	 * {
+	 *	if ((Xtal_Freq % 1000000) == 0)
+	 *		return (Xtal_Freq / 10000);
+	 *	else
+	 *		return (((Xtal_Freq / 1000000) + 1)*100);
+	 * }
+	 *
+	 * u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
 	 * tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
 	 * ((state->TG_LO/10000)*divider_val *
 	 * (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/mxl5007t.c linux-libre-3.2-gnu1/drivers/media/common/tuners/mxl5007t.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/mxl5007t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/mxl5007t.c	2012-01-04 18:55:44.000000000 -0500
@@ -488,9 +488,10 @@ static int mxl5007t_write_regs(struct mx
 
 static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
 {
+	u8 buf[2] = { 0xfb, reg };
 	struct i2c_msg msg[] = {
 		{ .addr = state->i2c_props.addr, .flags = 0,
-		  .buf = &reg, .len = 1 },
+		  .buf = buf, .len = 2 },
 		{ .addr = state->i2c_props.addr, .flags = I2C_M_RD,
 		  .buf = val, .len = 1 },
 	};
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18212.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18212.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18212.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18212.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,20 @@
  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "tda18212_priv.h"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "tda18212.h"
+
+struct tda18212_priv {
+	struct tda18212_config *cfg;
+	struct i2c_adapter *i2c;
+};
+
+#define dbg(fmt, arg...)					\
+do {								\
+	if (debug)						\
+		pr_info("%s: " fmt, __func__, ##arg);		\
+} while (0)
 
 static int debug;
 module_param(debug, int, 0644);
@@ -46,7 +59,8 @@ static int tda18212_wr_regs(struct tda18
 	if (ret == 1) {
 		ret = 0;
 	} else {
-		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
+			ret, reg, len);
 		ret = -EREMOTEIO;
 	}
 	return ret;
@@ -77,7 +91,8 @@ static int tda18212_rd_regs(struct tda18
 		memcpy(val, buf, len);
 		ret = 0;
 	} else {
-		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
+			ret, reg, len);
 		ret = -EREMOTEIO;
 	}
 
@@ -129,8 +144,8 @@ static int tda18212_set_params(struct dv
 		{ 0x92, 0x53, 0x03 }, /* DVB-C */
 	};
 
-	dbg("%s: delsys=%d RF=%d BW=%d", __func__,
-		c->delivery_system, c->frequency, c->bandwidth_hz);
+	dbg("delsys=%d RF=%d BW=%d\n",
+	    c->delivery_system, c->frequency, c->bandwidth_hz);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
@@ -196,7 +211,7 @@ exit:
 	return ret;
 
 error:
-	dbg("%s: failed:%d", __func__, ret);
+	dbg("failed:%d\n", ret);
 	goto exit;
 }
 
@@ -245,13 +260,13 @@ struct dvb_frontend *tda18212_attach(str
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
-	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+	dbg("ret:%d chip ID:%02x\n", ret, val);
 	if (ret || val != 0xc7) {
 		kfree(priv);
 		return NULL;
 	}
 
-	info("NXP TDA18212HN successfully identified.");
+	pr_info("NXP TDA18212HN successfully identified\n");
 
 	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18212_priv.h linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18212_priv.h
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18212_priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18212_priv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * NXP TDA18212HN silicon tuner driver
- *
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TDA18212_PRIV_H
-#define TDA18212_PRIV_H
-
-#include "tda18212.h"
-
-#define LOG_PREFIX "tda18212"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (debug) \
-		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct tda18212_priv {
-	struct tda18212_config *cfg;
-	struct i2c_adapter *i2c;
-};
-
-#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18218.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18218.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18218.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18218.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@ static int tda18218_set_params(struct dv
 	switch (params->u.ofdm.bandwidth) {
 	case BANDWIDTH_6_MHZ:
 		LP_Fc = 0;
-		LO_Frac = params->frequency + 4000000;
+		LO_Frac = params->frequency + 3000000;
 		break;
 	case BANDWIDTH_7_MHZ:
 		LP_Fc = 1;
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-common.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-common.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -676,10 +676,28 @@ fail:
 	return ret;
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+int _tda_printk(struct tda18271_priv *state, const char *level,
+		const char *func, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int rtn;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	if (state)
+		rtn = printk("%s%s: [%d-%04x|%c] %pV",
+			     level, func, i2c_adapter_id(state->i2c_props.adap),
+			     state->i2c_props.addr,
+			     (state->role == TDA18271_MASTER) ? 'M' : 'S',
+			     &vaf);
+	else
+		rtn = printk("%s%s: %pV", level, func, &vaf);
+
+	va_end(args);
+
+	return rtn;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-fe.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-fe.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-fe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -1230,7 +1230,7 @@ static int tda18271_set_config(struct dv
 	return 0;
 }
 
-static struct dvb_tuner_ops tda18271_tuner_ops = {
+static const struct dvb_tuner_ops tda18271_tuner_ops = {
 	.info = {
 		.name = "NXP TDA18271HD",
 		.frequency_min  =  45000000,
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-priv.h linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-priv.h
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda18271-priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda18271-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -136,29 +136,26 @@ extern int tda18271_debug;
 #define DBG_ADV  8
 #define DBG_CAL  16
 
-#define tda_printk(st, kern, fmt, arg...) do {\
-	if (st) { \
-		struct tda18271_priv *state = st; \
-		printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \
-			i2c_adapter_id(state->i2c_props.adap), \
-			state->i2c_props.addr, \
-			(state->role == TDA18271_MASTER) \
-			? "M" : "S", ##arg); \
-	} else \
-		printk(kern "%s: " fmt, __func__, ##arg); \
-} while (0)
+__attribute__((format(printf, 4, 5)))
+int _tda_printk(struct tda18271_priv *state, const char *level,
+		const char *func, const char *fmt, ...);
 
-#define tda_dprintk(st, lvl, fmt, arg...) do {\
-	if (tda18271_debug & lvl) \
-		tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0)
+#define tda_printk(st, lvl, fmt, arg...)			\
+	_tda_printk(st, lvl, __func__, fmt, ##arg)
 
-#define tda_info(fmt, arg...)     printk(KERN_INFO     fmt, ##arg)
-#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...)  tda_printk(priv, KERN_ERR,     fmt, ##arg)
-#define tda_dbg(fmt, arg...)  tda_dprintk(priv, DBG_INFO,    fmt, ##arg)
-#define tda_map(fmt, arg...)  tda_dprintk(priv, DBG_MAP,     fmt, ##arg)
-#define tda_reg(fmt, arg...)  tda_dprintk(priv, DBG_REG,     fmt, ##arg)
-#define tda_cal(fmt, arg...)  tda_dprintk(priv, DBG_CAL,     fmt, ##arg)
+#define tda_dprintk(st, lvl, fmt, arg...)			\
+do {								\
+	if (tda18271_debug & lvl)				\
+		tda_printk(st, KERN_DEBUG, fmt, ##arg);		\
+} while (0)
+
+#define tda_info(fmt, arg...)	pr_info(fmt, ##arg)
+#define tda_warn(fmt, arg...)	tda_printk(priv, KERN_WARNING, fmt, ##arg)
+#define tda_err(fmt, arg...)	tda_printk(priv, KERN_ERR,     fmt, ##arg)
+#define tda_dbg(fmt, arg...)	tda_dprintk(priv, DBG_INFO,    fmt, ##arg)
+#define tda_map(fmt, arg...)	tda_dprintk(priv, DBG_MAP,     fmt, ##arg)
+#define tda_reg(fmt, arg...)	tda_dprintk(priv, DBG_REG,     fmt, ##arg)
+#define tda_cal(fmt, arg...)	tda_dprintk(priv, DBG_CAL,     fmt, ##arg)
 
 #define tda_fail(ret)							     \
 ({									     \
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tda827x.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tda827x.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tda827x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tda827x.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,7 @@ static int tda827xo_set_params(struct dv
 		if_freq = 5000000;
 		break;
 	}
-	tuner_freq = params->frequency + if_freq;
+	tuner_freq = params->frequency;
 
 	i = 0;
 	while (tda827x_table[i].lomax < tuner_freq) {
@@ -185,6 +185,8 @@ static int tda827xo_set_params(struct dv
 		i++;
 	}
 
+	tuner_freq += if_freq;
+
 	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
 	buf[0] = 0;
 	buf[1] = (N>>8) | 0x40;
@@ -540,7 +542,7 @@ static int tda827xa_set_params(struct dv
 		if_freq = 5000000;
 		break;
 	}
-	tuner_freq = params->frequency + if_freq;
+	tuner_freq = params->frequency;
 
 	if (fe->ops.info.type == FE_QAM) {
 		dprintk("%s select tda827xa_dvbc\n", __func__);
@@ -554,6 +556,8 @@ static int tda827xa_set_params(struct dv
 		i++;
 	}
 
+	tuner_freq += if_freq;
+
 	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
 	buf[0] = 0;            // subaddress
 	buf[1] = N >> 8;
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-types.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-types.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-types.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-types.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/tuner.h>
 #include <media/tuner-types.h>
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-xc2028.c linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-xc2028.c
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-xc2028.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-xc2028.c	2013-05-01 23:42:04.000000000 -0400
@@ -614,6 +614,13 @@ static int load_firmware(struct dvb_fron
 			p += len;
 			size -= len;
 		}
+
+		/* silently fail if the frontend doesn't support I2C flush */
+		rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
+		if ((rc < 0) && (rc != -EINVAL)) {
+			tuner_err("error executing flush: %d\n", rc);
+			return rc;
+		}
 	}
 	return 0;
 }
@@ -933,11 +940,16 @@ static int generic_set_freq(struct dvb_f
 	 * that xc2028 will be in a safe state.
 	 * Maybe this might also be needed for DTV.
 	 */
-	if (new_type == V4L2_TUNER_ANALOG_TV) {
+	switch (new_type) {
+	case V4L2_TUNER_ANALOG_TV:
 		rc = send_seq(priv, {0x00, 0x00});
 
-		/* Analog modes require offset = 0 */
-	} else {
+		/* Analog mode requires offset = 0 */
+		break;
+	case V4L2_TUNER_RADIO:
+		/* Radio mode requires offset = 0 */
+		break;
+	case V4L2_TUNER_DIGITAL_TV:
 		/*
 		 * Digital modes require an offset to adjust to the
 		 * proper frequency. The offset depends on what
diff -druNp linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-xc2028.h linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-xc2028.h
--- linux-libre-3.1-gnu1/drivers/media/common/tuners/tuner-xc2028.h	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/common/tuners/tuner-xc2028.h	2013-05-01 23:42:04.000000000 -0400
@@ -54,6 +54,7 @@ struct xc2028_config {
 /* xc2028 commands for callback */
 #define XC2028_TUNER_RESET	0
 #define XC2028_RESET_CLK	1
+#define XC2028_I2C_FLUSH	2
 
 #if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
 extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/b2c2/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/b2c2/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/b2c2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/b2c2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,5 +12,5 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2
 b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/bt8xx/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/bt8xx/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/bt8xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/bt8xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video/bt8xx
+ccflags-y += -Idrivers/media/common/tuners
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ddbridge/ddbridge-core.c linux-libre-3.2-gnu1/drivers/media/dvb/ddbridge/ddbridge-core.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ddbridge/ddbridge-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ddbridge/ddbridge-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -507,15 +507,14 @@ static u32 ddb_input_avail(struct ddb_in
 	return 0;
 }
 
-static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
 {
 	struct ddb *dev = input->port->dev;
 	u32 left = count;
-	u32 idx, off, free, stat = input->stat;
+	u32 idx, free, stat = input->stat;
 	int ret;
 
 	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
 
 	while (left) {
 		if (input->cbuf == idx)
@@ -525,6 +524,8 @@ static size_t ddb_input_read(struct ddb_
 			free = left;
 		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
 				   input->coff, free);
+		if (ret)
+			return -EFAULT;
 		input->coff += free;
 		if (input->coff == input->dma_buf_size) {
 			input->coff = 0;
@@ -939,6 +940,8 @@ static ssize_t ts_read(struct file *file
 				break;
 		}
 		read = ddb_input_read(input, buf, left);
+		if (read < 0)
+			return read;
 		left -= read;
 		buf += read;
 	}
@@ -1438,7 +1441,7 @@ static long ddb_ioctl(struct file *file,
 {
 	struct ddb *dev = file->private_data;
 	void *parg = (void *)arg;
-	int res = -EFAULT;
+	int res;
 
 	switch (cmd) {
 	case IOCTL_DDB_FLASHIO:
@@ -1447,29 +1450,29 @@ static long ddb_ioctl(struct file *file,
 		u8 *rbuf, *wbuf;
 
 		if (copy_from_user(&fio, parg, sizeof(fio)))
-			break;
-		if (fio.write_len + fio.read_len > 1028) {
-			printk(KERN_ERR "IOBUF too small\n");
-			return -ENOMEM;
-		}
+			return -EFAULT;
+
+		if (fio.write_len > 1028 || fio.read_len > 1028)
+			return -EINVAL;
+		if (fio.write_len + fio.read_len > 1028)
+			return -EINVAL;
+
 		wbuf = &dev->iobuf[0];
-		if (!wbuf)
-			return -ENOMEM;
 		rbuf = wbuf + fio.write_len;
-		if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) {
-			vfree(wbuf);
-			break;
-		}
-		res = flashio(dev, wbuf, fio.write_len,
-			      rbuf, fio.read_len);
+
+		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
+			return -EFAULT;
+		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
+		if (res)
+			return res;
 		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
-			res = -EFAULT;
+			return -EFAULT;
 		break;
 	}
 	default:
-		break;
+		return -ENOTTY;
 	}
-	return res;
+	return 0;
 }
 
 static const struct file_operations ddb_fops = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ddbridge/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/ddbridge/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/ddbridge/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ddbridge/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,9 @@ ddbridge-objs := ddbridge-core.o
 
 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dm1105/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/dm1105/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/dm1105/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dm1105/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_DM1105) += dm1105.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c	2012-01-04 18:55:44.000000000 -0500
@@ -149,30 +149,25 @@ static void dvb_frontend_add_event(struc
 
 	dprintk ("%s\n", __func__);
 
-	if (mutex_lock_interruptible (&events->mtx))
-		return;
+	if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
+		fe->ops.get_frontend(fe, &fepriv->parameters_out);
 
-	wp = (events->eventw + 1) % MAX_EVENT;
+	mutex_lock(&events->mtx);
 
+	wp = (events->eventw + 1) % MAX_EVENT;
 	if (wp == events->eventr) {
 		events->overflow = 1;
 		events->eventr = (events->eventr + 1) % MAX_EVENT;
 	}
 
 	e = &events->events[events->eventw];
-
-	if (status & FE_HAS_LOCK)
-		if (fe->ops.get_frontend)
-			fe->ops.get_frontend(fe, &fepriv->parameters_out);
-
+	e->status = status;
 	e->parameters = fepriv->parameters_out;
 
 	events->eventw = wp;
 
 	mutex_unlock(&events->mtx);
 
-	e->status = status;
-
 	wake_up_interruptible (&events->wait_queue);
 }
 
@@ -207,19 +202,24 @@ static int dvb_frontend_get_event(struct
 			return ret;
 	}
 
-	if (mutex_lock_interruptible (&events->mtx))
-		return -ERESTARTSYS;
-
-	memcpy (event, &events->events[events->eventr],
-		sizeof(struct dvb_frontend_event));
-
+	mutex_lock(&events->mtx);
+	*event = events->events[events->eventr];
 	events->eventr = (events->eventr + 1) % MAX_EVENT;
-
 	mutex_unlock(&events->mtx);
 
 	return 0;
 }
 
+static void dvb_frontend_clear_events(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+
+	mutex_lock(&events->mtx);
+	events->eventr = events->eventw;
+	mutex_unlock(&events->mtx);
+}
+
 static void dvb_frontend_init(struct dvb_frontend *fe)
 {
 	dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
@@ -537,7 +537,6 @@ static int dvb_frontend_thread(void *dat
 {
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	unsigned long timeout;
 	fe_status_t s;
 	enum dvbfe_algo algo;
 
@@ -558,7 +557,7 @@ static int dvb_frontend_thread(void *dat
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
 restart:
-		timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
+		wait_event_interruptible_timeout(fepriv->wait_queue,
 			dvb_frontend_should_wakeup(fe) || kthread_should_stop()
 				|| freezing(current),
 			fepriv->delay);
@@ -577,12 +576,10 @@ restart:
 
 		if (fepriv->reinitialise) {
 			dvb_frontend_init(fe);
-			if (fepriv->tone != -1) {
+			if (fe->ops.set_tone && fepriv->tone != -1)
 				fe->ops.set_tone(fe, fepriv->tone);
-			}
-			if (fepriv->voltage != -1) {
+			if (fe->ops.set_voltage && fepriv->voltage != -1)
 				fe->ops.set_voltage(fe, fepriv->voltage);
-			}
 			fepriv->reinitialise = 0;
 		}
 
@@ -1019,6 +1016,29 @@ static int is_legacy_delivery_system(fe_
 	return 0;
 }
 
+/* Initialize the cache with some default values derived from the
+ * legacy frontend_info structure.
+ */
+static void dtv_property_cache_init(struct dvb_frontend *fe,
+				    struct dtv_frontend_properties *c)
+{
+	switch (fe->ops.info.type) {
+	case FE_QPSK:
+		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
+		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+		c->delivery_system = SYS_DVBS;
+		break;
+	case FE_QAM:
+		c->delivery_system = SYS_DVBC_ANNEX_AC;
+		break;
+	case FE_OFDM:
+		c->delivery_system = SYS_DVBT;
+		break;
+	case FE_ATSC:
+		break;
+	}
+}
+
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
  * drivers can use a single set_frontend tuning function, regardless of whether
  * it's being used for the legacy or new API, reducing code and complexity.
@@ -1032,17 +1052,13 @@ static void dtv_property_cache_sync(stru
 
 	switch (fe->ops.info.type) {
 	case FE_QPSK:
-		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
-		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
 		c->symbol_rate = p->u.qpsk.symbol_rate;
 		c->fec_inner = p->u.qpsk.fec_inner;
-		c->delivery_system = SYS_DVBS;
 		break;
 	case FE_QAM:
 		c->symbol_rate = p->u.qam.symbol_rate;
 		c->fec_inner = p->u.qam.fec_inner;
 		c->modulation = p->u.qam.modulation;
-		c->delivery_system = SYS_DVBC_ANNEX_AC;
 		break;
 	case FE_OFDM:
 		if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
@@ -1060,7 +1076,6 @@ static void dtv_property_cache_sync(stru
 		c->transmission_mode = p->u.ofdm.transmission_mode;
 		c->guard_interval = p->u.ofdm.guard_interval;
 		c->hierarchy = p->u.ofdm.hierarchy_information;
-		c->delivery_system = SYS_DVBT;
 		break;
 	case FE_ATSC:
 		c->modulation = p->u.vsb.modulation;
@@ -1132,16 +1147,13 @@ static void dtv_property_adv_params_sync
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
 
-	switch(c->modulation) {
-	case PSK_8:
-	case APSK_16:
-	case APSK_32:
-	case QPSK:
+	if (c->delivery_system == SYS_DSS ||
+	    c->delivery_system == SYS_DVBS ||
+	    c->delivery_system == SYS_DVBS2 ||
+	    c->delivery_system == SYS_ISDBS ||
+	    c->delivery_system == SYS_TURBO) {
 		p->u.qpsk.symbol_rate = c->symbol_rate;
 		p->u.qpsk.fec_inner = c->fec_inner;
-		break;
-	default:
-		break;
 	}
 
 	/* Fake out a generic DVB-T request so we pass validation in the ioctl */
@@ -1824,9 +1836,17 @@ static int dvb_frontend_ioctl_legacy(str
 
 			memcpy (&fepriv->parameters_in, parg,
 				sizeof (struct dvb_frontend_parameters));
+			dtv_property_cache_init(fe, c);
 			dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
 		}
 
+		/*
+		 * Initialize output parameters to match the values given by
+		 * the user. FE_SET_FRONTEND triggers an initial frontend event
+		 * with status = 0, which copies output parameters to userspace.
+		 */
+		fepriv->parameters_out = fepriv->parameters_in;
+
 		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
 		memcpy(&fetunesettings.parameters, parg,
 		       sizeof (struct dvb_frontend_parameters));
@@ -1884,8 +1904,9 @@ static int dvb_frontend_ioctl_legacy(str
 		/* Request the search algorithm to search */
 		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
 
-		dvb_frontend_wakeup(fe);
+		dvb_frontend_clear_events(fe);
 		dvb_frontend_add_event(fe, 0);
+		dvb_frontend_wakeup(fe);
 		fepriv->status = 0;
 		err = 0;
 		break;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.h	2012-01-04 18:55:44.000000000 -0500
@@ -209,6 +209,7 @@ struct dvb_tuner_ops {
 
 	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
 	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
 
 #define TUNER_STATUS_LOCKED 1
 #define TUNER_STATUS_STEREO 2
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_net.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_net.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-core/dvb_net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-core/dvb_net.c	2012-01-04 18:55:44.000000000 -0500
@@ -1230,7 +1230,7 @@ static const struct net_device_ops dvb_n
 	.ndo_open		= dvb_net_open,
 	.ndo_stop		= dvb_net_stop,
 	.ndo_start_xmit		= dvb_net_tx,
-	.ndo_set_multicast_list = dvb_net_set_multicast_list,
+	.ndo_set_rx_mode	= dvb_net_set_multicast_list,
 	.ndo_set_mac_address    = dvb_net_set_mac,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/a800.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/a800.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/a800.c	2013-05-02 01:34:00.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/a800.c	2013-05-01 23:42:09.000000000 -0400
@@ -127,6 +127,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
@@ -147,7 +149,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		},
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005.c	2013-05-02 01:34:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005.c	2013-05-01 23:42:13.000000000 -0400
@@ -19,7 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "af9005.h"
 
@@ -815,7 +815,7 @@ static int af9005_frontend_attach(struct
 			debug_dump(buf, 8, printk);
 		}
 	}
-	adap->fe = af9005_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -999,6 +999,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		    {
+		    .num_frontends = 1,
+		    .fe = {{
 		     .caps =
 		     DVB_USB_ADAP_HAS_PID_FILTER |
 		     DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1018,6 +1020,7 @@ static struct dvb_usb_device_properties
 					       }
 				      }
 				},
+		     }},
 		     }
 		    },
 	.power_ctrl = af9005_power_ctrl,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005-fe.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005-fe.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005-fe.c	2013-05-02 01:34:03.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005-fe.c	2013-05-01 23:42:11.000000000 -0400
@@ -63,11 +63,9 @@ static int af9005_write_word_agc(struct
 				 u16 reglo, u8 pos, u8 len, u16 value)
 {
 	int ret;
-	u8 temp;
 
 	if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
 		return ret;
-	temp = (u8) ((value & 0x0300) >> 8);
 	return af9005_write_register_bits(d, reghi, pos, len,
 					  (u8) ((value & 0x300) >> 8));
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "af9005.h"
 /* debug */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9015.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9015.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/af9015.c	2013-05-02 01:34:08.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/af9015.c	2013-05-01 23:42:16.000000000 -0400
@@ -744,29 +744,31 @@ static const struct af9015_rc_setup af90
 };
 
 static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
-	{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+	{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
 		RC_MAP_TERRATEC_SLIM_2 },
-	{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
+	{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
 		RC_MAP_TERRATEC_SLIM },
-	{ (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
+	{ (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
 		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN,
+	{ (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
 		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
+	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
 		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO,
+	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
 		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
+	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
 		RC_MAP_LEADTEK_Y04G0051 },
-	{ (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
+	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
+		RC_MAP_LEADTEK_Y04G0051 },
+	{ (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
 		RC_MAP_AVERMEDIA_M135A },
-	{ (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT,
+	{ (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
 		RC_MAP_TREKSTOR },
-	{ (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2,
+	{ (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
 		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
+	{ (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
 		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22,
+	{ (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
 		RC_MAP_MSI_DIGIVOX_III },
 	{ }
 };
@@ -859,13 +861,13 @@ static int af9015_read_config(struct usb
 	for (i = 0; i < af9015_properties_count; i++) {
 		/* USB1.1 set smaller buffersize and disable 2nd adapter */
 		if (udev->speed == USB_SPEED_FULL) {
-			af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
 				= TS_USB11_FRAME_SIZE;
 			/* disable 2nd adapter because we don't have
 			   PID-filters */
 			af9015_config.dual_mode = 0;
 		} else {
-			af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
 				= TS_USB20_FRAME_SIZE;
 		}
 	}
@@ -1111,10 +1113,10 @@ static int af9015_af9013_frontend_attach
 	}
 
 	/* attach demodulator */
-	adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+	adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
 		&adap->dev->i2c_adap);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct mt2060_config af9015_mt2060_config = {
@@ -1188,49 +1190,49 @@ static int af9015_tuner_attach(struct dv
 	switch (af9015_af9013_config[adap->id].tuner) {
 	case AF9013_TUNER_MT2060:
 	case AF9013_TUNER_MT2060_2:
-		ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap,
+		ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&af9015_mt2060_config,
 			af9015_config.mt2060_if1[adap->id])
 			== NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_QT1010:
 	case AF9013_TUNER_QT1010A:
-		ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
+		ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&af9015_qt1010_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_TDA18271:
-		ret = dvb_attach(tda18271_attach, adap->fe, 0xc0,
+		ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap,
 			&af9015_tda18271_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_TDA18218:
-		ret = dvb_attach(tda18218_attach, adap->fe,
+		ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_tda18218_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5003D:
-		ret = dvb_attach(mxl5005s_attach, adap->fe,
+		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5005D:
 	case AF9013_TUNER_MXL5005R:
-		ret = dvb_attach(mxl5005s_attach, adap->fe,
+		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_ENV77H11D5:
-		ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+		ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap,
 			DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MC44S803:
-		ret = dvb_attach(mc44s803_attach, adap->fe,
+		ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5007T:
-		ret = dvb_attach(mxl5007t_attach, adap->fe,
+		ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
 		break;
@@ -1304,6 +1306,8 @@ static struct dvb_usb_device_properties
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1319,8 +1323,11 @@ static struct dvb_usb_device_properties
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1335,6 +1342,7 @@ static struct dvb_usb_device_properties
 						}
 					}
 				},
+			}},
 			}
 		},
 
@@ -1432,6 +1440,8 @@ static struct dvb_usb_device_properties
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1447,8 +1457,11 @@ static struct dvb_usb_device_properties
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1463,6 +1476,7 @@ static struct dvb_usb_device_properties
 						}
 					}
 				},
+			}},
 			}
 		},
 
@@ -1549,6 +1563,8 @@ static struct dvb_usb_device_properties
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1564,8 +1580,11 @@ static struct dvb_usb_device_properties
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1580,6 +1599,7 @@ static struct dvb_usb_device_properties
 						}
 					}
 				},
+			}},
 			}
 		},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/anysee.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/anysee.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/anysee.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/anysee.c	2012-01-04 18:55:44.000000000 -0500
@@ -446,6 +446,114 @@ static struct isl6423_config anysee_isl6
  * IOE[5] STV0903 1=enabled
  */
 
+static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct anysee_state *state = adap->dev->priv;
+	int ret;
+
+	deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+	/* no frontend sleep control */
+	if (onoff == 0)
+		return 0;
+
+	switch (state->hw) {
+	case ANYSEE_HW_507FA: /* 15 */
+		/* E30 Combo Plus */
+		/* E30 C Plus */
+
+		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		} else {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		}
+
+		break;
+	case ANYSEE_HW_508TC: /* 18 */
+	case ANYSEE_HW_508PTC: /* 21 */
+		/* E7 TC */
+		/* E7 PTC */
+
+		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		} else {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		}
+
+		break;
+	default:
+		ret = 0;
+	}
+
+error:
+	return ret;
+}
+
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
@@ -466,41 +574,54 @@ static int anysee_frontend_attach(struct
 		}
 	};
 
-	/* Check which hardware we have.
-	 * We must do this call two times to get reliable values (hw bug).
-	 */
-	ret = anysee_get_hw_info(adap->dev, hw_info);
-	if (ret)
-		goto error;
+	/* detect hardware only once */
+	if (adap->fe_adap[0].fe == NULL) {
+		/* Check which hardware we have.
+		 * We must do this call two times to get reliable values (hw bug).
+		 */
+		ret = anysee_get_hw_info(adap->dev, hw_info);
+		if (ret)
+			goto error;
 
-	ret = anysee_get_hw_info(adap->dev, hw_info);
-	if (ret)
-		goto error;
+		ret = anysee_get_hw_info(adap->dev, hw_info);
+		if (ret)
+			goto error;
 
-	/* Meaning of these info bytes are guessed. */
-	info("firmware version:%d.%d hardware id:%d",
-		hw_info[1], hw_info[2], hw_info[0]);
+		/* Meaning of these info bytes are guessed. */
+		info("firmware version:%d.%d hardware id:%d",
+			hw_info[1], hw_info[2], hw_info[0]);
 
-	state->hw = hw_info[0];
+		state->hw = hw_info[0];
+	}
+
+	/* set current frondend ID for devices having two frondends */
+	if (adap->fe_adap[0].fe)
+		state->fe_id++;
 
 	switch (state->hw) {
 	case ANYSEE_HW_507T: /* 2 */
 		/* E30 */
 
+		if (state->fe_id)
+			break;
+
 		/* attach demod */
-		adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+		adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
 			&adap->dev->i2c_adap);
-		if (adap->fe)
+		if (adap->fe_adap[0].fe)
 			break;
 
 		/* attach demod */
-		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+		adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
 			&adap->dev->i2c_adap);
 
 		break;
 	case ANYSEE_HW_507CD: /* 6 */
 		/* E30 Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-T demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
@@ -512,33 +633,39 @@ static int anysee_frontend_attach(struct
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-			&adap->dev->i2c_adap);
+		adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+			&anysee_zl10353_config, &adap->dev->i2c_adap);
 
 		break;
 	case ANYSEE_HW_507DC: /* 10 */
 		/* E30 C Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-C demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
-			&adap->dev->i2c_adap, 0x48);
+		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+			&anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
 
 		break;
 	case ANYSEE_HW_507SI: /* 11 */
 		/* E30 S2 Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-S/S2 demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+		adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
 			&adap->dev->i2c_adap);
 
 		break;
@@ -564,55 +691,59 @@ static int anysee_frontend_attach(struct
 		if (ret)
 			goto error;
 
-		if (dvb_usb_anysee_delsys) {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
+		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+				0x01);
 			if (ret)
 				goto error;
 
-			/* enable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-				0x01);
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
 			/* attach demod */
 			if (tmp == 0xc7) {
 				/* TDA18212 config */
-				adap->fe = dvb_attach(zl10353_attach,
-					&anysee_zl10353_tda18212_config2,
-					&adap->dev->i2c_adap);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					tda10023_attach,
+					&anysee_tda10023_tda18212_config,
+					&adap->dev->i2c_adap, 0x48);
 			} else {
 				/* PLL config */
-				adap->fe = dvb_attach(zl10353_attach,
-					&anysee_zl10353_config,
-					&adap->dev->i2c_adap);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					tda10023_attach,
+					&anysee_tda10023_config,
+					&adap->dev->i2c_adap, 0x48);
 			}
 		} else {
-			/* disable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-				0x01);
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
+			/* enable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+				0x01);
 			if (ret)
 				goto error;
 
 			/* attach demod */
 			if (tmp == 0xc7) {
 				/* TDA18212 config */
-				adap->fe = dvb_attach(tda10023_attach,
-					&anysee_tda10023_tda18212_config,
-					&adap->dev->i2c_adap, 0x48);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					zl10353_attach,
+					&anysee_zl10353_tda18212_config2,
+					&adap->dev->i2c_adap);
 			} else {
 				/* PLL config */
-				adap->fe = dvb_attach(tda10023_attach,
-					&anysee_tda10023_config,
-					&adap->dev->i2c_adap, 0x48);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					zl10353_attach,
+					&anysee_zl10353_config,
+					&adap->dev->i2c_adap);
 			}
 		}
 
@@ -627,52 +758,40 @@ static int anysee_frontend_attach(struct
 		if (ret)
 			goto error;
 
-		if (dvb_usb_anysee_delsys) {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
 				0x40);
 			if (ret)
 				goto error;
 
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
 			/* attach demod */
-			adap->fe = dvb_attach(zl10353_attach,
-				&anysee_zl10353_tda18212_config,
-				&adap->dev->i2c_adap);
+			adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+				&anysee_tda10023_tda18212_config,
+				&adap->dev->i2c_adap, 0x48);
 		} else {
-			/* disable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
 				0x20);
 			if (ret)
 				goto error;
 
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
+			/* enable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+				0x40);
 			if (ret)
 				goto error;
 
 			/* attach demod */
-			adap->fe = dvb_attach(tda10023_attach,
-				&anysee_tda10023_tda18212_config,
-				&adap->dev->i2c_adap, 0x48);
+			adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+				&anysee_zl10353_tda18212_config,
+				&adap->dev->i2c_adap);
 		}
 
 		break;
@@ -681,6 +800,9 @@ static int anysee_frontend_attach(struct
 		/* E7 S2 */
 		/* E7 PS2 */
 
+		if (state->fe_id)
+			break;
+
 		/* enable transport stream on IOA[7] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
 		if (ret)
@@ -692,13 +814,13 @@ static int anysee_frontend_attach(struct
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+		adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
 			&adap->dev->i2c_adap, 0);
 
 		break;
 	}
 
-	if (!adap->fe) {
+	if (!adap->fe_adap[0].fe) {
 		/* we have no frontend :-( */
 		ret = -ENODEV;
 		err("Unsupported Anysee version. " \
@@ -713,14 +835,14 @@ static int anysee_tuner_attach(struct dv
 	struct anysee_state *state = adap->dev->priv;
 	struct dvb_frontend *fe;
 	int ret;
-	deb_info("%s:\n", __func__);
+	deb_info("%s: fe=%d\n", __func__, state->fe_id);
 
 	switch (state->hw) {
 	case ANYSEE_HW_507T: /* 2 */
 		/* E30 */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
 			NULL, DVB_PLL_THOMSON_DTT7579);
 
 		break;
@@ -728,7 +850,7 @@ static int anysee_tuner_attach(struct dv
 		/* E30 Plus */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
 			&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
 
 		break;
@@ -736,7 +858,7 @@ static int anysee_tuner_attach(struct dv
 		/* E30 C Plus */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
 			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
 
 		break;
@@ -744,28 +866,14 @@ static int anysee_tuner_attach(struct dv
 		/* E30 S2 Plus */
 
 		/* attach LNB controller */
-		fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_isl6423_config);
+		fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
+			&adap->dev->i2c_adap, &anysee_isl6423_config);
 
 		break;
 	case ANYSEE_HW_507FA: /* 15 */
 		/* E30 Combo Plus */
 		/* E30 C Plus */
 
-		if (dvb_usb_anysee_delsys) {
-			/* enable DVB-T tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		} else {
-			/* enable DVB-C tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		}
-
 		/* Try first attach TDA18212 silicon tuner on IOE[4], if that
 		 * fails attach old simple PLL. */
 
@@ -775,8 +883,8 @@ static int anysee_tuner_attach(struct dv
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_tda18212_config);
+		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+			&adap->dev->i2c_adap, &anysee_tda18212_config);
 		if (fe)
 			break;
 
@@ -786,8 +894,9 @@ static int anysee_tuner_attach(struct dv
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
-			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
+			(0xc0 >> 1), &adap->dev->i2c_adap,
+			DVB_PLL_SAMSUNG_DTOS403IH102A);
 
 		break;
 	case ANYSEE_HW_508TC: /* 18 */
@@ -801,8 +910,8 @@ static int anysee_tuner_attach(struct dv
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_tda18212_config);
+		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+			&adap->dev->i2c_adap, &anysee_tda18212_config);
 
 		break;
 	case ANYSEE_HW_508S2: /* 19 */
@@ -811,12 +920,12 @@ static int anysee_tuner_attach(struct dv
 		/* E7 PS2 */
 
 		/* attach tuner */
-		fe = dvb_attach(stv6110_attach, adap->fe,
+		fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
 			&anysee_stv6110_config, &adap->dev->i2c_adap);
 
 		if (fe) {
 			/* attach LNB controller */
-			fe = dvb_attach(isl6423_attach, adap->fe,
+			fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
 				&adap->dev->i2c_adap, &anysee_isl6423_config);
 		}
 
@@ -918,6 +1027,9 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends    = 2,
+		.frontend_ctrl    = anysee_frontend_ctrl,
+		.fe = {{
 			.streaming_ctrl   = anysee_streaming_ctrl,
 			.frontend_attach  = anysee_frontend_attach,
 			.tuner_attach     = anysee_tuner_attach,
@@ -931,6 +1043,21 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}, {
+			.streaming_ctrl   = anysee_streaming_ctrl,
+			.frontend_attach  = anysee_frontend_attach,
+			.tuner_attach     = anysee_tuner_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = (16*512),
+					}
+				}
+			},
+		}},
 		}
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/anysee.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/anysee.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/anysee.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/anysee.h	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@ enum cmd {
 struct anysee_state {
 	u8 hw; /* PCB ID */
 	u8 seq;
+	u8 fe_id:1; /* frondend ID */
 };
 
 #define ANYSEE_HW_507T    2 /* E30 */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/au6610.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/au6610.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/au6610.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/au6610.c	2012-01-04 18:55:44.000000000 -0500
@@ -140,9 +140,9 @@ static struct zl10353_config au6610_zl10
 
 static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -155,7 +155,7 @@ static struct qt1010_config au6610_qt101
 static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &au6610_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -204,6 +204,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = au6610_zl10353_frontend_attach,
 			.tuner_attach     = au6610_qt1010_tuner_attach,
 
@@ -219,6 +221,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/az6027.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/az6027.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/az6027.c	2013-05-02 01:34:10.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/az6027.c	2013-05-01 23:42:18.000000000 -0400
@@ -40,7 +40,6 @@ static const struct stb0899_s1_reg az602
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x99 },
 	{ STB0899_DISF22RX      	, 0xa8 },
@@ -782,7 +781,6 @@ static int az6027_set_voltage(struct dvb
 {
 
 	u8 buf;
-	int ret;
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
 	struct i2c_msg i2c_msg = {
@@ -800,17 +798,17 @@ static int az6027_set_voltage(struct dvb
 	switch (voltage) {
 	case SEC_VOLTAGE_13:
 		buf = 1;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	case SEC_VOLTAGE_18:
 		buf = 2;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	case SEC_VOLTAGE_OFF:
 		buf = 0;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	default:
@@ -910,16 +908,16 @@ static int az6027_frontend_attach(struct
 	az6027_frontend_reset(adap);
 
 	deb_info("adap = %p, dev = %p\n", adap, adap->dev);
-	adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
+	adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
 
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
-		if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
+		if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
 			deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
-			adap->fe->ops.set_voltage = az6027_set_voltage;
+			adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
 			az6027_ci_init(adap);
 		} else {
-			adap->fe = NULL;
+			adap->fe_adap[0].fe = NULL;
 		}
 	} else
 		warn("no front-end attached\n");
@@ -954,7 +952,6 @@ static int az6027_i2c_xfer(struct i2c_ad
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int i = 0, j = 0, len = 0;
-	int ret;
 	u16 index;
 	u16 value;
 	int length;
@@ -990,7 +987,7 @@ static int az6027_i2c_xfer(struct i2c_ad
 				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
 				value = msg[i].addr + (msg[i].len << 8);
 				length = msg[i + 1].len + 6;
-				ret = az6027_usb_in_op(d, req, value, index, data, length);
+				az6027_usb_in_op(d, req, value, index, data, length);
 				len = msg[i + 1].len;
 				for (j = 0; j < len; j++)
 					msg[i + 1].buf[j] = data[j + 5];
@@ -1017,7 +1014,7 @@ static int az6027_i2c_xfer(struct i2c_ad
 				index = 0x0;
 				value = msg[i].addr;
 				length = msg[i].len + 6;
-				ret = az6027_usb_in_op(d, req, value, index, data, length);
+				az6027_usb_in_op(d, req, value, index, data, length);
 				len = msg[i].len;
 				for (j = 0; j < len; j++)
 					msg[i].buf[j] = data[j + 5];
@@ -1106,6 +1103,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = az6027_streaming_ctrl,
 			.frontend_attach  = az6027_frontend_attach,
 
@@ -1120,6 +1119,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ce6230.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ce6230.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ce6230.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ce6230.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,9 +186,9 @@ static struct zl10353_config ce6230_zl10
 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 	return 0;
 }
@@ -214,7 +214,7 @@ static int ce6230_mxl5003s_tuner_attach(
 {
 	int ret;
 	deb_info("%s:\n", __func__);
-	ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+	ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
 	return ret;
 }
@@ -273,6 +273,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = ce6230_zl10353_frontend_attach,
 			.tuner_attach     = ce6230_mxl5003s_tuner_attach,
 			.stream = {
@@ -285,6 +287,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ static int cinergyt2_frontend_attach(str
 	char state[3];
 	int ret;
 
-	adap->fe = cinergyt2_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
 
 	ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
 				sizeof(state), 0);
@@ -198,6 +198,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cinergyt2_streaming_ctrl,
 			.frontend_attach  = cinergyt2_frontend_attach,
 
@@ -212,6 +214,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/cxusb.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/cxusb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/cxusb.c	2013-05-02 01:34:13.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/cxusb.c	2013-05-01 23:42:20.000000000 -0400
@@ -347,7 +347,7 @@ static void cxusb_d680_dmb_drain_message
 
 static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
 {
-	struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+	struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
 	const int timeout = 100;
 	const int junk_len = p->u.bulk.buffersize;
 	u8        *junk;
@@ -725,7 +725,7 @@ static struct max2165_config mygica_d689
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61,
 		   TUNER_PHILIPS_FMD1216ME_MK3);
 	return 0;
@@ -733,27 +733,27 @@ static int cxusb_fmd1216me_tuner_attach(
 
 static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
 		   NULL, DVB_PLL_THOMSON_DTT7579);
 	return 0;
 }
 
 static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
 	return 0;
 }
 
 static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		   NULL, DVB_PLL_THOMSON_DTT7579);
 	return 0;
 }
 
 static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
 	return 0;
 }
@@ -795,9 +795,9 @@ static int cxusb_dvico_xc3028_tuner_atta
 	};
 
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = dvico_bluebird_xc2028_callback;
+	adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
 
-	fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+	fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
 	if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
 		return -EIO;
 
@@ -808,7 +808,7 @@ static int cxusb_dvico_xc3028_tuner_atta
 
 static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(mxl5005s_attach, adap->fe,
+	dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, &aver_a868r_tuner);
 	return 0;
 }
@@ -816,7 +816,7 @@ static int cxusb_mxl5003s_tuner_attach(s
 static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_frontend *fe;
-	fe = dvb_attach(mxl5005s_attach, adap->fe,
+	fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap, &d680_dmb_tuner);
 	return (fe == NULL) ? -EIO : 0;
 }
@@ -824,7 +824,7 @@ static int cxusb_d680_dmb_tuner_attach(s
 static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_frontend *fe;
-	fe = dvb_attach(max2165_attach, adap->fe,
+	fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
 	return (fe == NULL) ? -EIO : 0;
 }
@@ -837,8 +837,9 @@ static int cxusb_cx22702_frontend_attach
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
 
-	if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -851,8 +852,10 @@ static int cxusb_lgdt3303_frontend_attac
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
+					 &cxusb_lgdt3303_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -860,9 +863,9 @@ static int cxusb_lgdt3303_frontend_attac
 
 static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
 			      &adap->dev->i2c_adap);
-	if (adap->fe != NULL)
+	if (adap->fe_adap[0].fe != NULL)
 		return 0;
 
 	return -EIO;
@@ -876,8 +879,9 @@ static int cxusb_mt352_frontend_attach(s
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -890,11 +894,15 @@ static int cxusb_dee1601_frontend_attach
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
-				    &adap->dev->i2c_adap)) != NULL) ||
-		((adap->fe = dvb_attach(zl10353_attach,
-					&cxusb_zl10353_dee1601_config,
-					&adap->dev->i2c_adap)) != NULL))
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
+		return 0;
+
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+					 &cxusb_zl10353_dee1601_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -917,9 +925,11 @@ static int cxusb_dualdig4_frontend_attac
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
-	if ((adap->fe = dvb_attach(zl10353_attach,
-				   &cxusb_zl10353_xc3028_config_no_i2c_gate,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe =
+		dvb_attach(zl10353_attach,
+			   &cxusb_zl10353_xc3028_config_no_i2c_gate,
+			   &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	/* try to determine if there is no IR decoder on the I2C bus */
@@ -1031,9 +1041,9 @@ static int cxusb_dualdig4_rev2_frontend_
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 			      &cxusb_dualdig4_rev2_config);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1084,15 +1094,15 @@ static int cxusb_dualdig4_rev2_tuner_att
 {
 	struct dib0700_adapter_state *st = adap->priv;
 	struct i2c_adapter *tun_i2c =
-		dib7000p_get_i2c_master(adap->fe,
+		dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 					DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 	    &dib7070p_dib0070_config) == NULL)
 		return -ENODEV;
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
 	return 0;
 }
 
@@ -1108,14 +1118,16 @@ static int cxusb_nano2_frontend_attach(s
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
-	if ((adap->fe = dvb_attach(zl10353_attach,
-				   &cxusb_zl10353_xc3028_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+					 &cxusb_zl10353_xc3028_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
-	if ((adap->fe = dvb_attach(mt352_attach,
-				   &cxusb_mt352_xc3028_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+					 &cxusb_mt352_xc3028_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -1150,7 +1162,7 @@ static int cxusb_d680_dmb_frontend_attac
 	usb_clear_halt(d->udev,
 		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
 	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
 
 	/* Drain USB pipes to avoid hang after reboot */
 	for (n = 0;  n < 5;  n++) {
@@ -1172,8 +1184,8 @@ static int cxusb_d680_dmb_frontend_attac
 	msleep(100);
 
 	/* Attach frontend */
-	adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1207,7 +1219,7 @@ static int cxusb_mygica_d689_frontend_at
 	usb_clear_halt(d->udev,
 		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
 	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
 
 
 	/* Reset the tuner */
@@ -1223,9 +1235,9 @@ static int cxusb_mygica_d689_frontend_at
 	msleep(100);
 
 	/* Attach frontend */
-	adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
+	adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
 		&d->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1383,6 +1395,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_cx22702_frontend_attach,
 			.tuner_attach     = cxusb_fmd1216me_tuner_attach,
@@ -1397,7 +1411,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_power_ctrl,
@@ -1429,6 +1443,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_lgdt3303_frontend_attach,
 			.tuner_attach     = cxusb_lgh064f_tuner_attach,
@@ -1444,6 +1460,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1483,6 +1500,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_dee1601_frontend_attach,
 			.tuner_attach     = cxusb_dee1601_tuner_attach,
@@ -1497,6 +1516,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1544,6 +1564,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 2,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_mt352_frontend_attach,
 			.tuner_attach     = cxusb_lgz201_tuner_attach,
@@ -1559,6 +1581,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -1596,6 +1619,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_mt352_frontend_attach,
 			.tuner_attach     = cxusb_dtt7579_tuner_attach,
@@ -1611,6 +1636,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -1645,6 +1671,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_dualdig4_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1659,6 +1687,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1695,6 +1724,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_nano2_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1709,6 +1740,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1747,6 +1779,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_nano2_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1761,6 +1795,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1796,6 +1831,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_aver_streaming_ctrl,
 			.frontend_attach  = cxusb_aver_lgdt3303_frontend_attach,
 			.tuner_attach     = cxusb_mxl5003s_tuner_attach,
@@ -1810,7 +1847,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_aver_power_ctrl,
@@ -1839,10 +1876,12 @@ struct dvb_usb_device_properties cxusb_b
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.size_of_priv    = sizeof(struct dib0700_adapter_state),
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl  = cxusb_streaming_ctrl,
 			.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
 			.tuner_attach    = cxusb_dualdig4_rev2_tuner_attach,
-			.size_of_priv    = sizeof(struct dib0700_adapter_state),
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
 				.type = USB_BULK,
@@ -1854,6 +1893,7 @@ struct dvb_usb_device_properties cxusb_b
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1889,6 +1929,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
 			.frontend_attach  = cxusb_d680_dmb_frontend_attach,
 			.tuner_attach     = cxusb_d680_dmb_tuner_attach,
@@ -1904,6 +1946,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1940,6 +1983,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
 			.frontend_attach  = cxusb_mygica_d689_frontend_attach,
 			.tuner_attach     = cxusb_mygica_d689_tuner_attach,
@@ -1955,6 +2000,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		},
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_d
 	struct dib0700_state *st = d->priv;
 	int ret;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_d
 	if (fwtype != NULL)
 		*fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
 			(st->buf[14] << 8) | st->buf[15];
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_devic
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
 	struct dib0700_state *st = d->priv;
-	s16 ret;
+	int ret;
+
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	st->buf[0] = REQUEST_SET_GPIO;
 	st->buf[1] = gpio;
@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_devi
 
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
 
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(stru
 	int ret;
 
 	if (st->fw_version >= 0x10201) {
+		if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+			err("could not acquire lock");
+			return 0;
+		}
+
 		st->buf[0] = REQUEST_SET_USB_XFER_LEN;
 		st->buf[1] = (nb_ts_packets >> 8) & 0xff;
 		st->buf[2] = nb_ts_packets & 0xff;
@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(stru
 		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
 
 		ret = dib0700_ctrl_wr(d, st->buf, 3);
+		mutex_unlock(&d->usb_mutex);
 	} else {
 		deb_info("this firmware does not allow to change the USB xfer len\n");
 		ret = -EIO;
@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i
 
 		} else {
 			/* Write request */
+			if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+				err("could not acquire lock");
+				return 0;
+			}
 			st->buf[0] = REQUEST_NEW_I2C_WRITE;
 			st->buf[1] = msg[i].addr << 1;
 			st->buf[2] = (en_start << 7) | (en_stop << 6) |
@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i
 						 USB_TYPE_VENDOR | USB_DIR_OUT,
 						 0, 0, st->buf, msg[i].len + 4,
 						 USB_CTRL_GET_TIMEOUT);
+			mutex_unlock(&d->usb_mutex);
 			if (result < 0) {
 				deb_info("i2c write error (status = %d)\n", result);
 				break;
@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struc
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	for (i = 0; i < num; i++) {
 		/* fill in the address */
@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struc
 				break;
 		}
 	}
+	mutex_unlock(&d->usb_mutex);
 	mutex_unlock(&d->i2c_mutex);
 
 	return i;
@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_
 	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
 {
 	struct dib0700_state *st = d->priv;
-	s16 ret;
+	int ret;
+
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	st->buf[0] = REQUEST_SET_CLOCK;
 	st->buf[1] = (en_pll << 7) | (pll_src << 6) |
@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_
 	st->buf[9] =  dsuScaler         & 0xff; /* LSB */
 
 	ret = dib0700_ctrl_wr(d, st->buf, 10);
+	mutex_unlock(&d->usb_mutex);
 
 	return ret;
 }
@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb
 {
 	struct dib0700_state *st = d->priv;
 	u16 divider;
+	int ret;
 
 	if (scl_kHz == 0)
 		return -EINVAL;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_SET_I2C_PARAM;
 	divider = (u16) (30000 / scl_kHz);
 	st->buf[1] = 0;
@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb
 	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
 		(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
 		st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
-	return dib0700_ctrl_wr(d, st->buf, 8);
+
+	ret = dib0700_ctrl_wr(d, st->buf, 8);
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
 }
 
 
@@ -484,13 +528,13 @@ int dib0700_download_firmware(struct usb
 		for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
 				adap_num++) {
 			if (fw_version >= 0x10201) {
-				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
+				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
 			} else {
 				/* for fw version older than 1.20.1,
 				 * the buffersize has to be n times 512 */
-				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
-				if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
-					dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
+				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
+				if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
+					dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
 			}
 		}
 	}
@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_us
 		}
 	}
 
+	if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_ENABLE_VIDEO;
 	/* this bit gives a kind of command,
 	 * rather than enabling something or not */
@@ -530,25 +579,28 @@ int dib0700_streaming_ctrl(struct dvb_us
 	deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
 
 	st->channel_state &= ~0x3;
-	if ((adap->stream.props.endpoint != 2)
-			&& (adap->stream.props.endpoint != 3)) {
-		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
+	if ((adap->fe_adap[0].stream.props.endpoint != 2)
+			&& (adap->fe_adap[0].stream.props.endpoint != 3)) {
+		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
 		if (onoff)
 			st->channel_state |=	1 << (adap->id);
 		else
 			st->channel_state |=	1 << ~(adap->id);
 	} else {
 		if (onoff)
-			st->channel_state |=	1 << (adap->stream.props.endpoint-2);
+			st->channel_state |=	1 << (adap->fe_adap[0].stream.props.endpoint-2);
 		else
-			st->channel_state |=	1 << (3-adap->stream.props.endpoint);
+			st->channel_state |=	1 << (3-adap->fe_adap[0].stream.props.endpoint);
 	}
 
 	st->buf[2] |= st->channel_state;
 
 	deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
 
-	return dib0700_ctrl_wr(adap->dev, st->buf, 4);
+	ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
+	mutex_unlock(&adap->dev->usb_mutex);
+
+	return ret;
 }
 
 int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_de
 	struct dib0700_state *st = d->priv;
 	int new_proto, ret;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_SET_RC;
 	st->buf[1] = 0;
 	st->buf[2] = 0;
@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_de
 	else if (rc_type == RC_TYPE_NEC)
 		new_proto = 0;
 	else if (rc_type == RC_TYPE_RC6) {
-		if (st->fw_version < 0x10200)
-			return -EINVAL;
+		if (st->fw_version < 0x10200) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		new_proto = 2;
-	} else
-		return -EINVAL;
+	} else {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	st->buf[1] = new_proto;
 
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
 	if (ret < 0) {
 		err("ir protocol setup failed");
-		return ret;
+		goto out;
 	}
 
 	d->props.rc.core.protocol = rc_type;
 
+out:
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c	2013-05-02 01:34:16.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c	2013-05-01 23:42:23.000000000 -0400
@@ -101,7 +101,7 @@ static int bristol_frontend_attach(struc
 		}
 	}
 	st->mt2060_if1[adap->id] = 1220;
-	return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+	return (adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
 		(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
 }
 
@@ -118,15 +118,16 @@ static int eeprom_read(struct i2c_adapte
 static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
-	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
 	s8 a;
 	int if1=1220;
 	if (adap->dev->udev->descriptor.idVendor  == cpu_to_le16(USB_VID_HAUPPAUGE) &&
 		adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
 		if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
 	}
-	return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
-		if1) == NULL ? -ENODEV : 0;
+	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c,
+			  &bristol_mt2060_config[adap->id], if1) == NULL ?
+			  -ENODEV : 0;
 }
 
 /* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@@ -279,10 +280,12 @@ static int stk7700P2_frontend_attach(str
 		}
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
-				&stk7700d_dib7000p_mt2266_config[adap->id]);
+	adap->fe_adap[0].fe =
+		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+			   0x80 + (adap->id << 1),
+			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
@@ -306,17 +309,19 @@ static int stk7700d_frontend_attach(stru
 		}
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
-				&stk7700d_dib7000p_mt2266_config[adap->id]);
+	adap->fe_adap[0].fe =
+		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+			   0x80 + (adap->id << 1),
+			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
-	tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
 		&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
 }
 
@@ -396,8 +401,8 @@ static int stk7700ph_xc3028_callback(voi
 	switch (command) {
 	case XC2028_TUNER_RESET:
 		/* Send the tuner in then out of reset */
-		dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
-		dib7000p_set_gpio(adap->fe, 8, 0, 1);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 		break;
 	case XC2028_RESET_CLK:
 		break;
@@ -447,25 +452,25 @@ static int stk7700ph_frontend_attach(str
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&stk7700ph_dib7700_xc3028_config);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
 
-	tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 		DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	stk7700ph_xc3028_config.i2c_adap = tun_i2c;
 
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = stk7700ph_xc3028_callback;
+	adap->fe_adap[0].fe->callback = stk7700ph_xc3028_callback;
 
-	return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+	return dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &stk7700ph_xc3028_config)
 		== NULL ? -ENODEV : 0;
 }
 
@@ -685,12 +690,12 @@ static int stk7700p_frontend_attach(stru
 	st->mt2060_if1[0] = 1220;
 
 	if (dib7000pc_detection(&adap->dev->i2c_adap)) {
-		adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+		adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
 		st->is_dib7000pc = 1;
 	} else
-		adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+		adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct mt2060_config stk7700p_mt2060_config = {
@@ -709,11 +714,11 @@ static int stk7700p_tuner_attach(struct
 		if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
 	}
 	if (st->is_dib7000pc)
-		tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 	else
-		tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk7700p_mt2060_config,
 		if1) == NULL ? -ENODEV : 0;
 }
 
@@ -843,33 +848,33 @@ static int dib7770_set_param_override(st
 static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	 struct dib0700_adapter_state *st = adap->priv;
-	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 			 DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	 if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
-				 &dib7770p_dib0070_config) == NULL)
+	 if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+			&dib7770p_dib0070_config) == NULL)
 		 return -ENODEV;
 
-	 st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	 adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+	 st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	 adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
 	 return 0;
 }
 
 static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
 			return -ENODEV;
 	} else {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
 			return -ENODEV;
 	}
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
 	return 0;
 }
 
@@ -878,26 +883,26 @@ static int stk7700p_pid_filter(struct dv
 {
 	struct dib0700_state *st = adapter->dev->priv;
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
-	return dib7000m_pid_filter(adapter->fe, index, pid, onoff);
+		return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+	return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
 	struct dib0700_state *st = adapter->dev->priv;
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
-	return dib7000m_pid_filter_ctrl(adapter->fe, onoff);
+		return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+	return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
 {
-    return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
+	return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
-    return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
+	return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -955,9 +960,9 @@ static int stk7070p_frontend_attach(stru
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&dib7070p_dib7000p_config);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* STK7770P */
@@ -1007,9 +1012,9 @@ static int stk7770p_frontend_attach(stru
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&dib7770p_dib7000p_config);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* DIB807x generic */
@@ -1225,34 +1230,34 @@ static int dib807x_set_param_override(st
 static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe,
+	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
 			DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 				&dib807x_dib0070_config[0]) == NULL)
 			return -ENODEV;
 	} else {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 				&dib807x_dib0070_config[1]) == NULL)
 			return -ENODEV;
 	}
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib807x_set_param_override;
 	return 0;
 }
 
 static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
 	u16 pid, int onoff)
 {
-	return dib8000_pid_filter(adapter->fe, index, pid, onoff);
+	return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
 		int onoff)
 {
-	return dib8000_pid_filter_ctrl(adapter->fe, onoff);
+	return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 /* STK807x */
@@ -1276,10 +1281,10 @@ static int stk807x_frontend_attach(struc
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
 
 /* STK807xPVR */
@@ -1305,10 +1310,10 @@ static int stk807xpvr_frontend_attach0(s
 	/* initialize IC 0 */
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
@@ -1316,10 +1321,10 @@ static int stk807xpvr_frontend_attach1(s
 	/* initialize IC 1 */
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
 			      &dib807x_dib8000_config[1]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* STK8096GP */
@@ -1546,13 +1551,13 @@ static int dib8096_set_param_override(st
 static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
 		return -ENODEV;
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
 	return 0;
 }
 
@@ -1575,30 +1580,30 @@ static int stk809x_frontend_attach(struc
 
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
 
 static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
 	struct i2c_adapter *tun_i2c;
-	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe, 1);
+	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
 
 	if (fe_slave) {
 		tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
 		if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
 			return -ENODEV;
-		fe_slave->dvb = adap->fe->dvb;
+		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
 		fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
 	}
-	tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+	tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
 		return -ENODEV;
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
 
 	return 0;
 }
@@ -1626,12 +1631,12 @@ static int nim8096md_frontend_attach(str
 
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
 	fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
-	dib8000_set_slave_frontend(adap->fe, fe_slave);
+	dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
 	return fe_slave == NULL ?  -ENODEV : 0;
 }
@@ -1639,12 +1644,12 @@ static int nim8096md_frontend_attach(str
 /* STK9090M */
 static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
 {
-	return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff);
+	return dib9000_fw_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
-	return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff);
+	return dib9000_fw_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
@@ -1856,15 +1861,15 @@ static int stk9090m_frontend_attach(stru
 	stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
 	stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
 
-	adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
+	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
 
 static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *state = adap->priv;
-	struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe);
+	struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
 	u16 data_dib190[10] = {
 		1, 0x1374,
 		2, 0x01a2,
@@ -1873,13 +1878,13 @@ static int dib9090_tuner_attach(struct d
 		8, 0x0486,
 	};
 
-	if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL)
 		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
 	if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
 		return -ENODEV;
 	dib0700_set_i2c_speed(adap->dev, 2000);
-	if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
 		return -ENODEV;
 	release_firmware(state->frontend_firmware);
 	return 0;
@@ -1925,16 +1930,16 @@ static int nim9090md_frontend_attach(str
 	nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
 
 	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
-	adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
+	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
 
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
 	dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
 
 	fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
-	dib9000_set_slave_frontend(adap->fe, fe_slave);
+	dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
 	return fe_slave == NULL ?  -ENODEV : 0;
 }
@@ -1951,26 +1956,26 @@ static int nim9090md_tuner_attach(struct
 		0, 0x00ef,
 		8, 0x0406,
 	};
-	i2c = dib9000_get_tuner_interface(adap->fe);
-	if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
+	i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
+	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
 		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
 	if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
 		return -ENODEV;
 	dib0700_set_i2c_speed(adap->dev, 2000);
-	if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
 		return -ENODEV;
 
-	fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
+	fe_slave = dib9000_get_slave_frontend(adap->fe_adap[0].fe, 1);
 	if (fe_slave != NULL) {
-		i2c = dib9000_get_component_bus_interface(adap->fe);
+		i2c = dib9000_get_component_bus_interface(adap->fe_adap[0].fe);
 		dib9000_set_i2c_adapter(fe_slave, i2c);
 
 		i2c = dib9000_get_tuner_interface(fe_slave);
 		if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
 			return -ENODEV;
-		fe_slave->dvb = adap->fe->dvb;
-		dib9000_fw_set_component_bus_speed(adap->fe, 2000);
+		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
+		dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
 		if (dib9000_firmware_post_pll_init(fe_slave) < 0)
 			return -ENODEV;
 	}
@@ -2393,23 +2398,23 @@ static int nim7090_frontend_attach(struc
 		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
 		return -ENODEV;
 	}
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
 
 static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
 	return 0;
 }
 
@@ -2439,11 +2444,11 @@ static int tfe7090pvr_frontend0_attach(s
 	}
 
 	dib0700_set_i2c_speed(adap->dev, 340);
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	dib7090_slave_reset(adap->fe);
+	dib7090_slave_reset(adap->fe_adap[0].fe);
 
 	return 0;
 }
@@ -2452,50 +2457,50 @@ static int tfe7090pvr_frontend1_attach(s
 {
 	struct i2c_adapter *i2c;
 
-	if (adap->dev->adapter[0].fe == NULL) {
+	if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
 		err("the master dib7090 has to be initialized first");
 		return -ENODEV; /* the master device has not been initialized */
 	}
 
-	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
 	if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
 		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
 	dib0700_set_i2c_speed(adap->dev, 200);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
 	return 0;
 }
 
 static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
 	return 0;
 }
 
@@ -2555,14 +2560,14 @@ static int stk7070pd_frontend_attach0(st
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
-	return adap->fe == NULL ? -ENODEV : 0;
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
-	return adap->fe == NULL ? -ENODEV : 0;
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* S5H1411 */
@@ -2617,9 +2622,9 @@ static int s5h1411_frontend_attach(struc
 	dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
 
 	/* GPIOs are initialized, do the attach */
-	adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+	adap->fe_adap[0].fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
 			      &adap->dev->i2c_adap);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int dib0700_xc5000_tuner_callback(void *priv, int component,
@@ -2649,9 +2654,9 @@ static struct xc5000_config s5h1411_xc50
 static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = dib0700_xc5000_tuner_callback;
+	adap->fe_adap[0].fe->callback = dib0700_xc5000_tuner_callback;
 
-	return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+	return dvb_attach(xc5000_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &s5h1411_xc5000_tunerconfig)
 		== NULL ? -ENODEV : 0;
 }
@@ -2663,9 +2668,9 @@ static int dib0700_xc4000_tuner_callback
 
 	if (command == XC4000_TUNER_RESET) {
 		/* Reset the tuner */
-		dib7000p_set_gpio(adap->fe, 8, 0, 0);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
 		msleep(10);
-		dib7000p_set_gpio(adap->fe, 8, 0, 1);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 	} else {
 		err("xc4000: unknown tuner callback command: %d\n", command);
 		return -EINVAL;
@@ -2771,11 +2776,11 @@ static int pctv340e_frontend_attach(stru
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
 			      &pctv_340e_config);
 	st->is_dib7000pc = 1;
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct xc4000_config dib7000p_xc4000_tunerconfig = {
@@ -2791,7 +2796,7 @@ static int xc4000_tuner_attach(struct dv
 	struct i2c_adapter *tun_i2c;
 
 	/* The xc4000 is not on the main i2c bus */
-	tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 					  DIBX000_I2C_INTERFACE_TUNER, 1);
 	if (tun_i2c == NULL) {
 		printk(KERN_ERR "Could not reach tuner i2c bus\n");
@@ -2799,9 +2804,9 @@ static int xc4000_tuner_attach(struct dv
 	}
 
 	/* Setup the reset callback */
-	adap->fe->callback = dib0700_xc4000_tuner_callback;
+	adap->fe_adap[0].fe->callback = dib0700_xc4000_tuner_callback;
 
-	return dvb_attach(xc4000_attach, adap->fe, tun_i2c,
+	return dvb_attach(xc4000_attach, adap->fe_adap[0].fe, tun_i2c,
 			  &dib7000p_xc4000_tunerconfig)
 		== NULL ? -ENODEV : 0;
 }
@@ -2857,16 +2862,16 @@ static int lgdt3305_frontend_attach(stru
 	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 	msleep(30);
 
-	adap->fe = dvb_attach(lgdt3305_attach,
+	adap->fe_adap[0].fe = dvb_attach(lgdt3305_attach,
 			      &hcw_lgdt3305_config,
 			      &adap->dev->i2c_adap);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	return dvb_attach(mxl5007t_attach, adap->fe,
+	return dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
 			  &adap->dev->i2c_adap, 0x60,
 			  &hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
 }
@@ -2989,6 +2994,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk7700p_pid_filter,
@@ -2997,6 +3004,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = stk7700p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			},
 		},
 
@@ -3050,15 +3058,21 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = bristol_frontend_attach,
 				.tuner_attach     = bristol_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = bristol_frontend_attach,
 				.tuner_attach     = bristol_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+			}},
 			}
 		},
 
@@ -3084,6 +3098,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3092,7 +3108,10 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3101,6 +3120,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+			}},
 			}
 		},
 
@@ -3143,6 +3163,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3151,6 +3173,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			},
 		},
 
@@ -3185,6 +3208,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3193,7 +3218,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			},
 		},
@@ -3261,6 +3286,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3269,7 +3296,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			},
 		},
@@ -3305,6 +3332,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3313,9 +3342,11 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3324,7 +3355,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}
 		},
@@ -3373,6 +3404,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3381,9 +3414,11 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3392,7 +3427,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}
 		},
@@ -3420,6 +3455,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3428,7 +3465,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = stk7700ph_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3488,11 +3525,13 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = s5h1411_frontend_attach,
 				.tuner_attach     = xc5000_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3524,11 +3563,13 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = lgdt3305_frontend_attach,
 				.tuner_attach     = mxl5007t_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3550,6 +3591,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
@@ -3558,7 +3601,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib7770p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3600,6 +3643,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter = stk80xx_pid_filter,
@@ -3608,7 +3653,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3644,6 +3689,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter = stk80xx_pid_filter,
@@ -3652,11 +3699,13 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter = stk80xx_pid_filter,
@@ -3665,7 +3714,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3693,6 +3742,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3702,7 +3753,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib809x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3730,6 +3781,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3739,7 +3792,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = dib9090_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3767,6 +3820,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3776,7 +3831,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = nim8096md_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3804,6 +3859,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3813,7 +3870,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = nim9090md_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3841,6 +3898,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3850,7 +3909,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = nim7090_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3878,6 +3937,8 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3887,11 +3948,13 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = tfe7090pvr_tuner0_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3901,7 +3964,7 @@ struct dvb_usb_device_properties dib0700
 				.tuner_attach     = tfe7090pvr_tuner1_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3929,11 +3992,13 @@ struct dvb_usb_device_properties dib0700
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = pctv340e_frontend_attach,
 				.tuner_attach     = xc4000_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@ int dibusb_streaming_ctrl(struct dvb_usb
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.fifo_ctrl != NULL)
-			if (st->ops.fifo_ctrl(adap->fe,onoff)) {
+			if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
 				err("error while controlling the fifo of the demod.");
 				return -ENODEV;
 			}
@@ -37,7 +37,8 @@ int dibusb_pid_filter(struct dvb_usb_ada
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_ctrl != NULL)
-			st->ops.pid_ctrl(adap->fe,index,pid,onoff);
+			st->ops.pid_ctrl(adap->fe_adap[0].fe,
+					 index, pid, onoff);
 	}
 	return 0;
 }
@@ -48,7 +49,7 @@ int dibusb_pid_filter_ctrl(struct dvb_us
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_parse != NULL)
-			if (st->ops.pid_parse(adap->fe,onoff) < 0)
+			if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
 				err("could not handle pid_parser");
 	}
 	return 0;
@@ -254,8 +255,16 @@ int dibusb_dib3000mc_frontend_attach(str
 		msleep(1000);
 	}
 
-	if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS,  &mod3000p_dib3000p_config)) != NULL ||
-		(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+					 &adap->dev->i2c_adap,
+					 DEFAULT_DIB3000P_I2C_ADDRESS,
+					 &mod3000p_dib3000p_config);
+	if ((adap->fe_adap[0].fe) == NULL)
+		adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+						 &adap->dev->i2c_adap,
+						 DEFAULT_DIB3000MC_I2C_ADDRESS,
+						 &mod3000p_dib3000p_config);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		if (adap->priv != NULL) {
 			struct dibusb_state *st = adap->priv;
 			st->ops.pid_parse = dib3000mc_pid_parse;
@@ -309,15 +318,15 @@ int dibusb_dib3000mc_tuner_attach(struct
 		}
 	}
 
-	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
-	if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
+	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
+	if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
 		/* not found - use panasonic pll parameters */
-		if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
+		if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
 			return -ENOMEM;
 	} else {
 		st->mt2060_present = 1;
 		/* set the correct parameters for the dib3000p */
-		dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
+		dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
 	}
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c	2013-05-02 01:34:18.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c	2013-05-01 23:42:25.000000000 -0400
@@ -31,11 +31,12 @@ static int dibusb_dib3000mb_frontend_att
 
 	demod_cfg.demod_address = 0x8;
 
-	if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
-				   &adap->dev->i2c_adap, &st->ops)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
+					 &adap->dev->i2c_adap, &st->ops);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -ENODEV;
 
-	adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
+	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
 
 	return 0;
 }
@@ -46,7 +47,7 @@ static int dibusb_thomson_tuner_attach(s
 
 	st->tuner_addr = 0x61;
 
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
 		   DVB_PLL_TUA6010XS);
 	return 0;
 }
@@ -57,7 +58,7 @@ static int dibusb_panasonic_tuner_attach
 
 	st->tuner_addr = 0x60;
 
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
 		   DVB_PLL_TDA665X);
 	return 0;
 }
@@ -78,16 +79,16 @@ static int dibusb_tuner_probe_and_attach
 	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
 	msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
 
-	if (adap->fe->ops.i2c_gate_ctrl)
-		adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
+	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
 
 	if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
 		err("tuner i2c write failed.");
 		ret = -EREMOTEIO;
 	}
 
-	if (adap->fe->ops.i2c_gate_ctrl)
-		adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
+	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
 
 	if (b2[0] == 0xfe) {
 		info("This device has the Thomson Cable onboard. Which is default.");
@@ -185,6 +186,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -205,6 +208,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
@@ -272,6 +276,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
 			.pid_filter_count = 16,
 
@@ -292,6 +298,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		},
 	},
@@ -338,6 +345,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -358,6 +367,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
@@ -398,6 +408,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -417,6 +429,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c	2013-05-02 01:34:20.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c	2013-05-01 23:42:27.000000000 -0400
@@ -57,6 +57,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
@@ -76,6 +78,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/digitv.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/digitv.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/digitv.c	2013-05-02 01:34:23.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/digitv.c	2013-05-01 23:42:29.000000000 -0400
@@ -137,11 +137,16 @@ static int digitv_frontend_attach(struct
 {
 	struct digitv_state *st = adap->dev->priv;
 
-	if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		st->is_nxt6000 = 0;
 		return 0;
 	}
-	if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
+					 &digitv_nxt6000_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		st->is_nxt6000 = 1;
 		return 0;
 	}
@@ -152,11 +157,11 @@ static int digitv_tuner_attach(struct dv
 {
 	struct digitv_state *st = adap->dev->priv;
 
-	if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
+	if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
 		return -ENODEV;
 
 	if (st->is_nxt6000)
-		adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+		adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
 
 	return 0;
 }
@@ -292,6 +297,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = digitv_frontend_attach,
 			.tuner_attach     = digitv_tuner_attach,
 
@@ -306,6 +313,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.identify_state   = digitv_identify_state,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c	2013-05-02 01:34:25.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c	2013-05-01 23:42:31.000000000 -0400
@@ -90,7 +90,7 @@ static int dtt200u_rc_query(struct dvb_u
 
 static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dtt200u_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -140,6 +140,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -157,6 +159,7 @@ static struct dvb_usb_device_properties
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -187,6 +190,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -204,6 +209,7 @@ static struct dvb_usb_device_properties
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -234,6 +240,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -251,6 +259,7 @@ static struct dvb_usb_device_properties
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -281,6 +290,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -298,6 +309,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dtv5100.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dtv5100.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dtv5100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dtv5100.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,13 +115,13 @@ static struct zl10353_config dtv5100_zl1
 
 static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
 			      &adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	/* disable i2c gate, or it won't work... is this safe? */
-	adap->fe->ops.i2c_gate_ctrl = NULL;
+	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
 
 	return 0;
 }
@@ -133,7 +133,7 @@ static struct qt1010_config dtv5100_qt10
 static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -180,6 +180,8 @@ static struct dvb_usb_device_properties
 
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 		.frontend_attach = dtv5100_frontend_attach,
 		.tuner_attach    = dtv5100_tuner_attach,
 
@@ -193,6 +195,7 @@ static struct dvb_usb_device_properties
 				}
 			}
 		},
+		}},
 	} },
 
 	.i2c_algo = &dtv5100_i2c_algo,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,15 +17,20 @@ static int dvb_usb_ctrl_feed(struct dvb_
 	if (adap == NULL)
 		return -ENODEV;
 
+	if ((adap->active_fe < 0) ||
+	    (adap->active_fe >= adap->num_frontends_initialized)) {
+		return -EINVAL;
+	}
+
 	newfeedcount = adap->feedcount + (onoff ? 1 : -1);
 
 	/* stop feed before setting a new pid if there will be no pid anymore */
 	if (newfeedcount == 0) {
 		deb_ts("stop feeding\n");
-		usb_urb_kill(&adap->stream);
+		usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
 
-		if (adap->props.streaming_ctrl != NULL) {
-			ret = adap->props.streaming_ctrl(adap, 0);
+		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
 			if (ret < 0) {
 				err("error while stopping stream.");
 				return ret;
@@ -36,36 +41,37 @@ static int dvb_usb_ctrl_feed(struct dvb_
 	adap->feedcount = newfeedcount;
 
 	/* activate the pid on the device specific pid_filter */
-	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
-		"yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
-		"on" : "off");
-	if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-		adap->pid_filtering &&
-		adap->props.pid_filter != NULL)
-		adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
+	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
+		adap->fe_adap[adap->active_fe].pid_filtering ?
+		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
+		dvbdmxfeed->index, onoff ? "on" : "off");
+	if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+		adap->fe_adap[adap->active_fe].pid_filtering &&
+		adap->props.fe[adap->active_fe].pid_filter != NULL)
+		adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
 
 	/* start the feed if this was the first feed and there is still a feed
 	 * for reception.
 	 */
 	if (adap->feedcount == onoff && adap->feedcount > 0) {
 		deb_ts("submitting all URBs\n");
-		usb_urb_submit(&adap->stream);
+		usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
 
 		deb_ts("controlling pid parser\n");
-		if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->props.caps &
+		if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+			adap->props.fe[adap->active_fe].caps &
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-			adap->props.pid_filter_ctrl != NULL) {
-			ret = adap->props.pid_filter_ctrl(adap,
-				adap->pid_filtering);
+			adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
+				adap->fe_adap[adap->active_fe].pid_filtering);
 			if (ret < 0) {
 				err("could not handle pid_parser");
 				return ret;
 			}
 		}
 		deb_ts("start feeding\n");
-		if (adap->props.streaming_ctrl != NULL) {
-			ret = adap->props.streaming_ctrl(adap, 1);
+		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
 			if (ret < 0) {
 				err("error while enabling fifo.");
 				return ret;
@@ -90,6 +96,7 @@ static int dvb_usb_stop_feed(struct dvb_
 
 int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
 {
+	int i;
 	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
 				       adap->dev->owner, &adap->dev->udev->dev,
 				       adapter_nums);
@@ -112,7 +119,12 @@ int dvb_usb_adapter_dvb_init(struct dvb_
 	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
 	adap->demux.priv             = adap;
 
-	adap->demux.feednum          = adap->demux.filternum = adap->max_feed_count;
+	adap->demux.filternum        = 0;
+	for (i = 0; i < adap->props.num_frontends; i++) {
+		if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
+			adap->demux.filternum = adap->fe_adap[i].max_feed_count;
+	}
+	adap->demux.feednum          = adap->demux.filternum;
 	adap->demux.start_feed       = dvb_usb_start_feed;
 	adap->demux.stop_feed        = dvb_usb_stop_feed;
 	adap->demux.write_to_decoder = NULL;
@@ -156,14 +168,33 @@ int dvb_usb_adapter_dvb_exit(struct dvb_
 	return 0;
 }
 
+static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+	int ret = (adap->props.frontend_ctrl) ?
+		adap->props.frontend_ctrl(fe, onoff) : 0;
+
+	if (ret < 0) {
+		err("frontend_ctrl request failed");
+		return ret;
+	}
+	if (onoff)
+		adap->active_fe = fe->id;
+
+	return 0;
+}
+
 static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
 {
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
 	dvb_usb_device_power_ctrl(adap->dev, 1);
 
-	if (adap->fe_init)
-		adap->fe_init(fe);
+	dvb_usb_set_active_fe(fe, 1);
+
+	if (adap->fe_adap[fe->id].fe_init)
+		adap->fe_adap[fe->id].fe_init(fe);
 
 	return 0;
 }
@@ -172,45 +203,81 @@ static int dvb_usb_fe_sleep(struct dvb_f
 {
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
-	if (adap->fe_sleep)
-		adap->fe_sleep(fe);
+	if (adap->fe_adap[fe->id].fe_sleep)
+		adap->fe_adap[fe->id].fe_sleep(fe);
+
+	dvb_usb_set_active_fe(fe, 0);
 
 	return dvb_usb_device_power_ctrl(adap->dev, 0);
 }
 
 int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
 {
-	if (adap->props.frontend_attach == NULL) {
-		err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
-		return 0;
-	}
+	int ret, i;
 
-	/* re-assign sleep and wakeup functions */
-	if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
-		adap->fe_init  = adap->fe->ops.init;  adap->fe->ops.init  = dvb_usb_fe_wakeup;
-		adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
+	/* register all given adapter frontends */
+	for (i = 0; i < adap->props.num_frontends; i++) {
 
-		if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
-			err("Frontend registration failed.");
-			dvb_frontend_detach(adap->fe);
-			adap->fe = NULL;
-			return -ENODEV;
+		if (adap->props.fe[i].frontend_attach == NULL) {
+			err("strange: '%s' #%d,%d "
+			    "doesn't want to attach a frontend.",
+			    adap->dev->desc->name, adap->id, i);
+
+			return 0;
+		}
+
+		ret = adap->props.fe[i].frontend_attach(adap);
+		if (ret || adap->fe_adap[i].fe == NULL) {
+			/* only print error when there is no FE at all */
+			if (i == 0)
+				err("no frontend was attached by '%s'",
+					adap->dev->desc->name);
+
+			return 0;
+		}
+
+		adap->fe_adap[i].fe->id = i;
+
+		/* re-assign sleep and wakeup functions */
+		adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
+		adap->fe_adap[i].fe->ops.init  = dvb_usb_fe_wakeup;
+		adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
+		adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
+
+		if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
+			err("Frontend %d registration failed.", i);
+			dvb_frontend_detach(adap->fe_adap[i].fe);
+			adap->fe_adap[i].fe = NULL;
+			/* In error case, do not try register more FEs,
+			 * still leaving already registered FEs alive. */
+			if (i == 0)
+				return -ENODEV;
+			else
+				return 0;
 		}
 
 		/* only attach the tuner if the demod is there */
-		if (adap->props.tuner_attach != NULL)
-			adap->props.tuner_attach(adap);
-	} else
-		err("no frontend was attached by '%s'",adap->dev->desc->name);
+		if (adap->props.fe[i].tuner_attach != NULL)
+			adap->props.fe[i].tuner_attach(adap);
+
+		adap->num_frontends_initialized++;
+	}
 
 	return 0;
 }
 
 int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
 {
-	if (adap->fe != NULL) {
-		dvb_unregister_frontend(adap->fe);
-		dvb_frontend_detach(adap->fe);
+	int i = adap->num_frontends_initialized - 1;
+
+	/* unregister all given adapter frontends */
+	for (; i >= 0; i--) {
+		if (adap->fe_adap[i].fe != NULL) {
+			dvb_unregister_frontend(adap->fe_adap[i].fe);
+			dvb_frontend_detach(adap->fe_adap[i].fe);
+		}
 	}
+	adap->num_frontends_initialized = 0;
+
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h	2012-01-04 18:55:44.000000000 -0500
@@ -124,6 +124,8 @@ struct usb_data_stream_properties {
  * @caps: capabilities of the DVB USB device.
  * @pid_filter_count: number of PID filter position in the optional hardware
  *  PID-filter.
+ * @num_frontends: number of frontends of the DVB USB adapter.
+ * @frontend_ctrl: called to power on/off active frontend.
  * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
  *  device (not URB submitting/killing).
  * @pid_filter_ctrl: called to en/disable the PID filter, if any.
@@ -134,7 +136,7 @@ struct usb_data_stream_properties {
  *  pll_desc and pll_init_buf of struct dvb_usb_device).
  * @stream: configuration of the USB streaming
  */
-struct dvb_usb_adapter_properties {
+struct dvb_usb_adapter_fe_properties {
 #define DVB_USB_ADAP_HAS_PID_FILTER               0x01
 #define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
 #define DVB_USB_ADAP_NEED_PID_FILTERING           0x04
@@ -152,9 +154,18 @@ struct dvb_usb_adapter_properties {
 	struct usb_data_stream_properties stream;
 
 	int size_of_priv;
+};
+
+#define MAX_NO_OF_FE_PER_ADAP 2
+struct dvb_usb_adapter_properties {
+	int size_of_priv;
 
+	int (*frontend_ctrl)   (struct dvb_frontend *, int);
 	int (*fe_ioctl_override) (struct dvb_frontend *,
 				  unsigned int, void *, unsigned int);
+
+	int num_frontends;
+	struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
 };
 
 /**
@@ -345,6 +356,20 @@ struct usb_data_stream {
  *
  * @stream: the usb data stream.
  */
+struct dvb_usb_fe_adapter {
+	struct dvb_frontend *fe;
+
+	int (*fe_init)  (struct dvb_frontend *);
+	int (*fe_sleep) (struct dvb_frontend *);
+
+	struct usb_data_stream stream;
+
+	int pid_filtering;
+	int max_feed_count;
+
+	void *priv;
+};
+
 struct dvb_usb_adapter {
 	struct dvb_usb_device *dev;
 	struct dvb_usb_adapter_properties props;
@@ -356,20 +381,16 @@ struct dvb_usb_adapter {
 	u8  id;
 
 	int feedcount;
-	int pid_filtering;
 
 	/* dvb */
 	struct dvb_adapter   dvb_adap;
 	struct dmxdev        dmxdev;
 	struct dvb_demux     demux;
 	struct dvb_net       dvb_net;
-	struct dvb_frontend *fe;
-	int                  max_feed_count;
-
-	int (*fe_init)  (struct dvb_frontend *);
-	int (*fe_sleep) (struct dvb_frontend *);
 
-	struct usb_data_stream stream;
+	struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
+	int active_fe;
+	int num_frontends_initialized;
 
 	void *priv;
 };
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #define USB_VID_HAUPPAUGE			0x2040
 #define USB_VID_HYPER_PALTEK			0x1025
 #define USB_VID_INTEL				0x8086
+#define USB_VID_ITETECH				0x048d
 #define USB_VID_KWORLD				0xeb2a
 #define USB_VID_KWORLD_2			0x1b80
 #define USB_VID_KYE				0x0458
@@ -126,6 +127,7 @@
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
 #define USB_PID_INTEL_CE9500				0x9500
+#define USB_PID_ITETECH_IT9135				0x9135
 #define USB_PID_KWORLD_399U				0xe399
 #define USB_PID_KWORLD_399U_2				0xe400
 #define USB_PID_KWORLD_395U				0xe396
@@ -136,6 +138,7 @@
 #define USB_PID_KWORLD_PC160_2T				0xc160
 #define USB_PID_KWORLD_PC160_T				0xc161
 #define USB_PID_KWORLD_UB383_T				0xe383
+#define USB_PID_KWORLD_UB499_2T_T09			0xe409
 #define USB_PID_KWORLD_VSTREAM_COLD			0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df
 #define USB_PID_TERRATEC_CINERGY_T_USB_XE		0x0055
@@ -240,6 +243,9 @@
 #define USB_PID_PCTV_200E				0x020e
 #define USB_PID_PCTV_400E				0x020f
 #define USB_PID_PCTV_450E				0x0222
+#define USB_PID_PCTV_452E				0x021f
+#define USB_PID_TECHNOTREND_CONNECT_S2_3600		0x3007
+#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI		0x300a
 #define USB_PID_NEBULA_DIGITV				0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-init.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-init.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-init.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage,
 static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
 	struct dvb_usb_adapter *adap;
-	int ret, n;
+	int ret, n, o;
 
 	for (n = 0; n < d->props.num_adapters; n++) {
 		adap = &d->adapter[n];
@@ -38,30 +38,41 @@ static int dvb_usb_adapter_init(struct d
 
 		memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
 
+	for (o = 0; o < adap->props.num_frontends; o++) {
+		struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
 		/* speed - when running at FULL speed we need a HW PID filter */
-		if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+		if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
 			err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
 			return -ENODEV;
 		}
 
-		if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
-			(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
-			info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
-			adap->pid_filtering  = 1;
-			adap->max_feed_count = adap->props.pid_filter_count;
+		if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+			(props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+			info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
+			adap->fe_adap[o].pid_filtering  = 1;
+			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
 		} else {
 			info("will pass the complete MPEG2 transport stream to the software demuxer.");
-			adap->pid_filtering  = 0;
-			adap->max_feed_count = 255;
+			adap->fe_adap[o].pid_filtering  = 0;
+			adap->fe_adap[o].max_feed_count = 255;
 		}
 
-		if (!adap->pid_filtering &&
+		if (!adap->fe_adap[o].pid_filtering &&
 			dvb_usb_force_pid_filter_usage &&
-			adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+			props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
 			info("pid filter enabled by module option.");
-			adap->pid_filtering  = 1;
-			adap->max_feed_count = adap->props.pid_filter_count;
+			adap->fe_adap[o].pid_filtering  = 1;
+			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
+		}
+
+		if (props->size_of_priv > 0) {
+			adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
+			if (adap->fe_adap[o].priv == NULL) {
+				err("no memory for priv for adapter %d fe %d.", n, o);
+				return -ENOMEM;
+			}
 		}
+	}
 
 		if (adap->props.size_of_priv > 0) {
 			adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
@@ -77,6 +88,10 @@ static int dvb_usb_adapter_init(struct d
 			return ret;
 		}
 
+		/* use exclusive FE lock if there is multiple shared FEs */
+		if (adap->fe_adap[1].fe)
+			adap->dvb_adap.mfe_shared = 1;
+
 		d->num_adapters_initialized++;
 		d->state |= DVB_USB_STATE_DVB;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-urb.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-urb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-urb.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,16 +82,28 @@ static void dvb_usb_data_complete_204(st
 
 int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
 {
-	adap->stream.udev      = adap->dev->udev;
-	if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
-		adap->stream.complete = dvb_usb_data_complete_204;
-	else
-	adap->stream.complete  = dvb_usb_data_complete;
-	adap->stream.user_priv = adap;
-	return usb_urb_init(&adap->stream, &adap->props.stream);
+	int i, ret = 0;
+	for (i = 0; i < adap->props.num_frontends; i++) {
+
+		adap->fe_adap[i].stream.udev      = adap->dev->udev;
+		if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
+			adap->fe_adap[i].stream.complete =
+				dvb_usb_data_complete_204;
+		else
+		adap->fe_adap[i].stream.complete  = dvb_usb_data_complete;
+		adap->fe_adap[i].stream.user_priv = adap;
+		ret = usb_urb_init(&adap->fe_adap[i].stream,
+				   &adap->props.fe[i].stream);
+		if (ret < 0)
+			break;
+	}
+	return ret;
 }
 
 int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
 {
-	return usb_urb_exit(&adap->stream);
+	int i;
+	for (i = 0; i < adap->props.num_frontends; i++)
+		usb_urb_exit(&adap->fe_adap[i].stream);
+	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dw2102.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dw2102.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/dw2102.c	2013-05-02 01:34:28.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/dw2102.c	2013-05-01 23:42:33.000000000 -0400
@@ -992,18 +992,18 @@ static int dw2104_frontend_attach(struct
 	struct dvb_tuner_ops *tuner_ops = NULL;
 
 	if (demod_probe & 4) {
-		d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
+		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
 				&d->dev->i2c_adap, 0);
-		if (d->fe != NULL) {
-			if (dvb_attach(stb6100_attach, d->fe,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
 					&dw2104a_stb6100_config,
 					&d->dev->i2c_adap)) {
-				tuner_ops = &d->fe->ops.tuner_ops;
+				tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
 				tuner_ops->set_frequency = stb6100_set_freq;
 				tuner_ops->get_frequency = stb6100_get_freq;
 				tuner_ops->set_bandwidth = stb6100_set_bandw;
 				tuner_ops->get_bandwidth = stb6100_get_bandw;
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached STV0900+STB6100!\n");
 				return 0;
 			}
@@ -1011,13 +1011,13 @@ static int dw2104_frontend_attach(struct
 	}
 
 	if (demod_probe & 2) {
-		d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
+		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
 				&d->dev->i2c_adap, 0);
-		if (d->fe != NULL) {
-			if (dvb_attach(stv6110_attach, d->fe,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
 					&dw2104_stv6110_config,
 					&d->dev->i2c_adap)) {
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached STV0900+STV6110A!\n");
 				return 0;
 			}
@@ -1025,19 +1025,19 @@ static int dw2104_frontend_attach(struct
 	}
 
 	if (demod_probe & 1) {
-		d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+		d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
 				&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached cx24116!\n");
 			return 0;
 		}
 	}
 
-	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		d->fe->ops.set_voltage = dw210x_set_voltage;
+	if (d->fe_adap[0].fe != NULL) {
+		d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 		info("Attached DS3000!\n");
 		return 0;
 	}
@@ -1053,22 +1053,22 @@ static int dw2102_frontend_attach(struct
 {
 	if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
 		/*dw2102_properties.adapter->tuner_attach = NULL;*/
-		d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+		d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached si21xx!\n");
 			return 0;
 		}
 	}
 
 	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
-		d->fe = dvb_attach(stv0288_attach, &earda_config,
+		d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			if (dvb_attach(stb6000_attach, d->fe, 0x61,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
 					&d->dev->i2c_adap)) {
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached stv0288!\n");
 				return 0;
 			}
@@ -1077,10 +1077,10 @@ static int dw2102_frontend_attach(struct
 
 	if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
 		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
-		d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+		d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached stv0299!\n");
 			return 0;
 		}
@@ -1090,9 +1090,9 @@ static int dw2102_frontend_attach(struct
 
 static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
 {
-	d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+	d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
 				&d->dev->i2c_adap, 0x48);
-	if (d->fe != NULL) {
+	if (d->fe_adap[0].fe != NULL) {
 		info("Attached tda10023!\n");
 		return 0;
 	}
@@ -1101,12 +1101,12 @@ static int dw3101_frontend_attach(struct
 
 static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
 {
-	d->fe = dvb_attach(mt312_attach, &zl313_config,
+	d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		if (dvb_attach(zl10039_attach, d->fe, 0x60,
+	if (d->fe_adap[0].fe != NULL) {
+		if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
 				&d->dev->i2c_adap)) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached zl100313+zl10039!\n");
 			return 0;
 		}
@@ -1119,16 +1119,16 @@ static int stv0288_frontend_attach(struc
 {
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(stv0288_attach, &earda_config,
+	d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
 			&d->dev->i2c_adap);
 
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
+	if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
 		return -EIO;
 
-	d->fe->ops.set_voltage = dw210x_set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1143,14 +1143,14 @@ static int ds3000_frontend_attach(struct
 	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
 			&d->dev->i2c_adap);
 
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	st->old_set_voltage = d->fe->ops.set_voltage;
-	d->fe->ops.set_voltage = s660_set_voltage;
+	st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1163,12 +1163,12 @@ static int prof_7500_frontend_attach(str
 {
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
+	d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
 					&d->dev->i2c_adap, 0);
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	d->fe->ops.set_voltage = dw210x_set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1204,9 +1204,9 @@ static int su3000_frontend_attach(struct
 	if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
 		err("command 0x51 transfer failed.");
 
-	d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
+	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
 					&d->dev->i2c_adap);
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	info("Attached DS3000!\n");
@@ -1216,14 +1216,14 @@ static int su3000_frontend_attach(struct
 
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		&adap->dev->i2c_adap, DVB_PLL_OPERA1);
 	return 0;
 }
 
 static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		&adap->dev->i2c_adap, DVB_PLL_TUA6034);
 
 	return 0;
@@ -1535,7 +1535,7 @@ static int dw2102_load_firmware(struct u
 					DW210X_READ_MSG);
 			if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
 				dw2102_properties.i2c_algo = &dw2102_i2c_algo;
-				dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+				dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
 				break;
 			} else {
 				/* check STV0288 frontend  */
@@ -1591,6 +1591,8 @@ static struct dvb_usb_device_properties
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw2102_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1602,6 +1604,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 3,
@@ -1642,6 +1645,8 @@ static struct dvb_usb_device_properties
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw2104_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1653,6 +1658,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 2,
@@ -1689,6 +1695,8 @@ static struct dvb_usb_device_properties
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw3101_frontend_attach,
 			.tuner_attach = dw3101_tuner_attach,
 			.stream = {
@@ -1701,6 +1709,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
@@ -1733,6 +1742,8 @@ static struct dvb_usb_device_properties
 	.read_mac_address = s6x0_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = zl100313_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1744,6 +1755,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
@@ -1810,6 +1822,8 @@ static struct dvb_usb_device_properties
 
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = su3000_streaming_ctrl,
 			.frontend_attach  = su3000_frontend_attach,
 			.stream = {
@@ -1822,6 +1836,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}},
 		}
 	},
 	.num_device_descs = 3,
@@ -1855,7 +1870,7 @@ static int dw2102_probe(struct usb_inter
 	p1100->devices[0] = d1100;
 	p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
 	p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
-	p1100->adapter->frontend_attach = stv0288_frontend_attach;
+	p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
 
 	s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
 	if (!s660) {
@@ -1869,7 +1884,7 @@ static int dw2102_probe(struct usb_inter
 	s660->devices[0] = d660;
 	s660->devices[1] = d480_1;
 	s660->devices[2] = d480_2;
-	s660->adapter->frontend_attach = ds3000_frontend_attach;
+	s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
 
 	p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
 	if (!p7500) {
@@ -1883,7 +1898,7 @@ static int dw2102_probe(struct usb_inter
 	p7500->devices[0] = d7500;
 	p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
 	p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
-	p7500->adapter->frontend_attach = prof_7500_frontend_attach;
+	p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
 
 	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
 			THIS_MODULE, NULL, adapter_nr) ||
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ec168.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ec168.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ec168.c	2013-05-02 01:34:30.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ec168.c	2013-05-01 23:42:35.000000000 -0400
@@ -200,9 +200,9 @@ static struct ec100_config ec168_ec100_c
 static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,
+	adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -228,7 +228,7 @@ static struct mxl5005s_config ec168_mxl5
 static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+	return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 		&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
 }
 
@@ -382,6 +382,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = ec168_streaming_ctrl,
 			.frontend_attach  = ec168_ec100_frontend_attach,
 			.tuner_attach     = ec168_mxl5003s_tuner_attach,
@@ -395,6 +397,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/friio.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/friio.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/friio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/friio.c	2012-01-04 18:55:44.000000000 -0500
@@ -403,8 +403,8 @@ static int friio_frontend_attach(struct
 	if (friio_initialize(adap->dev) < 0)
 		return -EIO;
 
-	adap->fe = jdvbt90502_attach(adap->dev);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -473,6 +473,8 @@ static struct dvb_usb_device_properties
 		/* caps:0 =>  no pid filter, 188B TS packet */
 		/* GL861 has a HW pid filter, but no info available. */
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps  = 0,
 
 			.frontend_attach  = friio_frontend_attach,
@@ -490,6 +492,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.i2c_algo = &gl861_i2c_algo,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gl861.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gl861.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gl861.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gl861.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,9 +103,9 @@ static struct zl10353_config gl861_zl103
 static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
 {
 
-	adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -118,7 +118,7 @@ static struct qt1010_config gl861_qt1010
 static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &gl861_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -167,6 +167,8 @@ static struct dvb_usb_device_properties
 
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 
 		.frontend_attach  = gl861_frontend_attach,
 		.tuner_attach     = gl861_tuner_attach,
@@ -181,6 +183,7 @@ static struct dvb_usb_device_properties
 				}
 			}
 		},
+		}},
 	} },
 	.i2c_algo         = &gl861_i2c_algo,
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c	2013-05-02 01:34:32.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c	2013-05-01 23:42:37.000000000 -0400
@@ -230,7 +230,7 @@ static int gp8psk_streaming_ctrl(struct
 
 static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = gp8psk_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -268,6 +268,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = gp8psk_streaming_ctrl,
 			.frontend_attach  = gp8psk_frontend_attach,
 			/* parameter for the MPEG2-data transfer */
@@ -281,6 +283,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl       = gp8psk_power_ctrl,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gp8psk-fe.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gp8psk-fe.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/gp8psk-fe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/gp8psk-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,19 +144,25 @@ static int gp8psk_fe_set_frontend(struct
 	cmd[6] = (freq >> 16) & 0xff;
 	cmd[7] = (freq >> 24) & 0xff;
 
+	/* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
+	if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
+		c->delivery_system = SYS_TURBO;
+
 	switch (c->delivery_system) {
 	case SYS_DVBS:
-		/* Allow QPSK and 8PSK (even for DVB-S) */
-		if (c->modulation != QPSK && c->modulation != PSK_8) {
+		if (c->modulation != QPSK) {
 			deb_fe("%s: unsupported modulation selected (%d)\n",
 				__func__, c->modulation);
 			return -EOPNOTSUPP;
 		}
 		c->fec_inner = FEC_AUTO;
 		break;
-	case SYS_DVBS2:
+	case SYS_DVBS2: /* kept for backwards compatibility */
 		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
 		break;
+	case SYS_TURBO:
+		deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
+		break;
 
 	default:
 		deb_fe("%s: unsupported delivery system selected (%d)\n",
@@ -189,7 +195,10 @@ static int gp8psk_fe_set_frontend(struct
 		default:
 			cmd[9] = 5; break;
 		}
-		cmd[8] = ADV_MOD_DVB_QPSK;
+		if (c->delivery_system == SYS_TURBO)
+			cmd[8] = ADV_MOD_TURBO_QPSK;
+		else
+			cmd[8] = ADV_MOD_DVB_QPSK;
 		break;
 	case PSK_8: /* PSK_8 is for compatibility with DN */
 		cmd[8] = ADV_MOD_TURBO_8PSK;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/it913x.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/it913x.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/it913x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/it913x.c	2013-05-01 23:42:39.000000000 -0400
@@ -0,0 +1,702 @@
+/* DVB USB compliant linux driver for IT9137
+ *
+ * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ * IT9137 (C) ITE Tech Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/dvb/it9137.txt for firmware information
+ *
+ */
+#define DVB_USB_LOG_PREFIX "it913x"
+
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#include "dvb-usb.h"
+#include "it913x-fe.h"
+
+/* debug */
+static int dvb_usb_it913x_debug;
+#define l_dprintk(var, level, args...) do { \
+	if ((var >= level)) \
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
+} while (0)
+
+#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
+#define debug_data_snipet(level, name, p) \
+	 deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
+			*(p+5), *(p+6), *(p+7));
+
+
+module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
+			DVB_USB_DEBUG_STATUS);
+
+static int pid_filter;
+module_param_named(pid, pid_filter, int, 0644);
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
+
+int cmd_counter;
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct it913x_state {
+	u8 id;
+};
+
+struct ite_config {
+	u8 chip_ver;
+	u16 chip_type;
+	u32 firmware;
+	u8 tuner_id_0;
+	u8 tuner_id_1;
+	u8 dual_mode;
+};
+
+struct ite_config it913x_config;
+
+static int it913x_bulk_write(struct usb_device *dev,
+				u8 *snd, int len, u8 pipe)
+{
+	int ret, actual_l;
+
+	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
+				snd, len , &actual_l, 100);
+	return ret;
+}
+
+static int it913x_bulk_read(struct usb_device *dev,
+				u8 *rev, int len, u8 pipe)
+{
+	int ret, actual_l;
+
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
+				 rev, len , &actual_l, 200);
+	return ret;
+}
+
+static u16 check_sum(u8 *p, u8 len)
+{
+	u16 sum = 0;
+	u8 i = 1;
+	while (i < len)
+		sum += (i++ & 1) ? (*p++) << 8 : *p++;
+	return ~sum;
+}
+
+static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+			u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
+{
+	int ret = 0, i, buf_size = 1;
+	u8 *buff;
+	u8 rlen;
+	u16 chk_sum;
+
+	buff = kzalloc(256, GFP_KERNEL);
+	if (!buff) {
+		info("USB Buffer Failed");
+		return -ENOMEM;
+	}
+
+	buff[buf_size++] = pro;
+	buff[buf_size++] = cmd;
+	buff[buf_size++] = cmd_counter;
+
+	switch (mode) {
+	case READ_LONG:
+	case WRITE_LONG:
+		buff[buf_size++] = len;
+		buff[buf_size++] = 2;
+		buff[buf_size++] = (reg >> 24);
+		buff[buf_size++] = (reg >> 16) & 0xff;
+		buff[buf_size++] = (reg >> 8) & 0xff;
+		buff[buf_size++] = reg & 0xff;
+	break;
+	case READ_SHORT:
+		buff[buf_size++] = addr;
+		break;
+	case WRITE_SHORT:
+		buff[buf_size++] = len;
+		buff[buf_size++] = addr;
+		buff[buf_size++] = (reg >> 8) & 0xff;
+		buff[buf_size++] = reg & 0xff;
+	break;
+	case READ_DATA:
+	case WRITE_DATA:
+		break;
+	case WRITE_CMD:
+		mode = 7;
+		break;
+	default:
+		kfree(buff);
+		return -EINVAL;
+	}
+
+	if (mode & 1) {
+		for (i = 0; i < len ; i++)
+			buff[buf_size++] = data[i];
+	}
+	chk_sum = check_sum(&buff[1], buf_size);
+
+	buff[buf_size++] = chk_sum >> 8;
+	buff[0] = buf_size;
+	buff[buf_size++] = (chk_sum & 0xff);
+
+	ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
+
+	ret |= it913x_bulk_read(udev, buff, (mode & 1) ?
+			5 : len + 5 , 0x01);
+
+	rlen = (mode & 0x1) ? 0x1 : len;
+
+	if (mode & 1)
+		ret |= buff[2];
+	else
+		memcpy(data, &buff[3], rlen);
+
+	cmd_counter++;
+
+	kfree(buff);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
+{
+	int ret;
+	u8 b[1];
+	b[0] = data;
+	ret = it913x_io(udev, WRITE_LONG, pro,
+			CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
+
+	return ret;
+}
+
+static int it913x_read_reg(struct usb_device *udev, u32 reg)
+{
+	int ret;
+	u8 data[1];
+
+	ret = it913x_io(udev, READ_LONG, DEV_0,
+			CMD_DEMOD_READ, reg, 0, &data[0], 1);
+
+	return (ret < 0) ? ret : data[0];
+}
+
+static u32 it913x_query(struct usb_device *udev, u8 pro)
+{
+	int ret;
+	u8 data[4];
+	ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
+		0x1222, 0, &data[0], 3);
+
+	it913x_config.chip_ver = data[0];
+	it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
+
+	info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
+		it913x_config.chip_type);
+
+	ret |= it913x_io(udev, READ_SHORT, pro,
+			CMD_QUERYINFO, 0, 0x1, &data[0], 4);
+
+	it913x_config.firmware = (data[0] << 24) + (data[1] << 16) +
+			(data[2] << 8) + data[3];
+
+	return (ret < 0) ? 0 : it913x_config.firmware;
+}
+
+static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "PID_C  (%02x)", onoff);
+
+	if (!onoff)
+		ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+	return ret;
+}
+
+static int it913x_pid_filter(struct dvb_usb_adapter *adap,
+		int index, u16 pid, int onoff)
+{
+	struct usb_device *udev = adap->dev->udev;
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (pid_filter > 0)
+		return 0;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "PID_F  (%02x)", onoff);
+	if (onoff) {
+		ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
+
+		ret |= it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
+
+		ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
+
+		ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
+
+		ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
+
+	}
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+	return 0;
+}
+
+
+static int it913x_return_status(struct usb_device *udev)
+{
+	u32 firm = 0;
+
+	firm = it913x_query(udev, DEV_0);
+	if (firm > 0)
+		info("Firmware Version %d", firm);
+
+	return (firm > 0) ? firm : 0;
+}
+
+static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+				 int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	static u8 data[256];
+	int ret;
+	u32 reg;
+	u8 pro;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+			return -EAGAIN;
+
+	debug_data_snipet(1, "Message out", msg[0].buf);
+	deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
+
+	pro = (msg[0].addr & 0x2) ?  DEV_0_DMOD : 0x0;
+	pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
+	memcpy(data, msg[0].buf, msg[0].len);
+	reg = (data[0] << 24) + (data[1] << 16) +
+			(data[2] << 8) + data[3];
+	if (num == 2) {
+		ret = it913x_io(d->udev, READ_LONG, pro,
+			CMD_DEMOD_READ, reg, 0, data, msg[1].len);
+		memcpy(msg[1].buf, data, msg[1].len);
+	} else
+		ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
+			reg, 0, &data[4], msg[0].len - 4);
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+
+static u32 it913x_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm it913x_i2c_algo = {
+	.master_xfer   = it913x_i2c_xfer,
+	.functionality = it913x_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+#define IT913X_POLL 250
+static int it913x_rc_query(struct dvb_usb_device *d)
+{
+	u8 ibuf[4];
+	int ret;
+	u32 key;
+	/* Avoid conflict with frontends*/
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+			return -EAGAIN;
+
+	ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
+		0, 0, &ibuf[0], sizeof(ibuf));
+
+	if ((ibuf[2] + ibuf[3]) == 0xff) {
+		key = ibuf[2];
+		key += ibuf[0] << 8;
+		deb_info(1, "INT Key =%08x", key);
+		if (d->rc_dev != NULL)
+			rc_keydown(d->rc_dev, key, 0);
+	}
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+static int it913x_identify_state(struct usb_device *udev,
+		struct dvb_usb_device_properties *props,
+		struct dvb_usb_device_description **desc,
+		int *cold)
+{
+	int ret = 0, firm_no;
+	u8 reg, remote;
+
+	firm_no = it913x_return_status(udev);
+
+	/* checnk for dual mode */
+	it913x_config.dual_mode =  it913x_read_reg(udev, 0x49c5);
+
+	/* TODO different remotes */
+	remote = it913x_read_reg(udev, 0x49ac); /* Remote */
+	if (remote == 0)
+		props->rc.core.rc_codes = NULL;
+
+	/* TODO at the moment tuner_id is always assigned to 0x38 */
+	it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0);
+
+	info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
+		, remote, it913x_config.tuner_id_0);
+
+	if (firm_no > 0) {
+		*cold = 0;
+		return 0;
+	}
+
+	if (it913x_config.dual_mode) {
+		it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0);
+		ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
+		msleep(50);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
+		msleep(50);
+		reg = it913x_read_reg(udev, GPIOH1_O);
+		if (reg == 0) {
+			ret |= it913x_wr_reg(udev, DEV_0,  GPIOH1_O, 0x1);
+			ret |= it913x_return_status(udev);
+			if (ret != 0)
+				ret = it913x_wr_reg(udev, DEV_0,
+					GPIOH1_O, 0x0);
+		}
+		props->num_adapters = 2;
+	} else
+		props->num_adapters = 1;
+
+	reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+
+	if (it913x_config.dual_mode) {
+		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
+		ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
+	} else {
+		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
+		ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
+	}
+
+	*cold = 1;
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "STM  (%02x)", onoff);
+
+	if (!onoff)
+		ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+
+	return ret;
+}
+
+
+static int it913x_download_firmware(struct usb_device *udev,
+					const struct firmware *fw)
+{
+	int ret = 0, i;
+	u8 packet_size, dlen;
+	u8 *fw_data;
+
+	packet_size = 0x29;
+
+	ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
+
+	info("FRM Starting Firmware Download");
+	/* This uses scatter write firmware headers follow */
+	/* 03 XX 00     XX = chip number? */ 
+
+	for (i = 0; i < fw->size; i += packet_size) {
+			if (i > 0)
+				packet_size = 0x39;
+			fw_data = (u8 *)(fw->data + i);
+			dlen = ((i + packet_size) > fw->size)
+				? (fw->size - i) : packet_size;
+			ret |= it913x_io(udev, WRITE_DATA, DEV_0,
+				CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
+			udelay(1000);
+	}
+
+	ret |= it913x_io(udev, WRITE_CMD, DEV_0,
+			CMD_BOOT, 0, 0, NULL, 0);
+
+	msleep(100);
+
+	if (ret < 0)
+		info("FRM Firmware Download Failed (%04x)" , ret);
+	else
+		info("FRM Firmware Download Completed - Resetting Device");
+
+	ret |= it913x_return_status(udev);
+
+	msleep(30);
+
+	ret |= it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
+
+	/* Tuner function */
+	if (it913x_config.dual_mode)
+		ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
+
+	ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
+	ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
+	if (it913x_config.dual_mode) {
+		ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
+		ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
+	}
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_name(struct dvb_usb_adapter *adap)
+{
+	const char *desc = adap->dev->desc->name;
+	char *fe_name[] = {"_1", "_2", "_3", "_4"};
+	char *name = adap->fe_adap[0].fe->ops.info.name;
+
+	strlcpy(name, desc, 128);
+	strlcat(name, fe_name[adap->id], 128);
+
+	return 0;
+}
+
+static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct usb_device *udev = adap->dev->udev;
+	int ret = 0;
+	u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+	u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
+	u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
+	u8 tuner_id, tuner_type;
+
+	if (adap->id == 0)
+		tuner_id = it913x_config.tuner_id_0;
+	else
+		tuner_id = it913x_config.tuner_id_1;
+
+	/* TODO we always use IT9137 possible references here*/
+	/* Documentation suggests don't care */
+	switch (tuner_id) {
+	case 0x51:
+	case 0x52:
+	case 0x60:
+	case 0x61:
+	case 0x62:
+	default:
+	case 0x38:
+		tuner_type = IT9137;
+	}
+
+	adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
+		&adap->dev->i2c_adap, adap_addr, adf, tuner_type);
+
+	if (adap->id == 0 && adap->fe_adap[0].fe) {
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
+					ep_size & 0xff);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80);
+	} else if (adap->id == 1 && adap->fe_adap[0].fe) {
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
+					ep_size & 0xff);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
+	} else
+		return -ENODEV;
+
+	ret = it913x_name(adap);
+
+	return ret;
+}
+
+/* DVB USB Driver */
+static struct dvb_usb_device_properties it913x_properties;
+
+static int it913x_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	cmd_counter = 0;
+	if (0 == dvb_usb_device_init(intf, &it913x_properties,
+				     THIS_MODULE, NULL, adapter_nr)) {
+		info("DEV registering device driver");
+		return 0;
+	}
+
+	info("DEV it913x Error");
+	return -ENODEV;
+
+}
+
+static struct usb_device_id it913x_table[] = {
+	{ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
+	{ USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
+	{}		/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, it913x_table);
+
+static struct dvb_usb_device_properties it913x_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.download_firmware = it913x_download_firmware,
+	.firmware = "/*(DEBLOBBED)*/",
+	.no_reconnect = 1,
+	.size_of_priv = sizeof(struct it913x_state),
+	.num_adapters = 2,
+	.adapter = {
+		{
+		.num_frontends = 1,
+		.fe = {{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.streaming_ctrl   = it913x_streaming_ctrl,
+			.pid_filter_count = 31,
+			.pid_filter = it913x_pid_filter,
+			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
+			.frontend_attach  = it913x_frontend_attach,
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 10,
+				.endpoint = 0x04,
+				.u = {/* Keep Low if PID filter on */
+					.bulk = {
+						.buffersize = 3584,
+
+					}
+				}
+			}
+		}},
+		},
+			{
+		.num_frontends = 1,
+		.fe = {{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.streaming_ctrl   = it913x_streaming_ctrl,
+			.pid_filter_count = 31,
+			.pid_filter = it913x_pid_filter,
+			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
+			.frontend_attach  = it913x_frontend_attach,
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 5,
+				.endpoint = 0x05,
+				.u = {
+					.bulk = {
+						.buffersize = 3584,
+
+					}
+				}
+			}
+		}},
+		}
+	},
+	.identify_state   = it913x_identify_state,
+	.rc.core = {
+		.protocol	= RC_TYPE_NEC,
+		.module_name	= "it913x",
+		.rc_query	= it913x_rc_query,
+		.rc_interval	= IT913X_POLL,
+		.allowed_protos	= RC_TYPE_NEC,
+		.rc_codes	= RC_MAP_KWORLD_315U,
+	},
+	.i2c_algo         = &it913x_i2c_algo,
+	.num_device_descs = 2,
+	.devices = {
+		{   "Kworld UB499-2T T09(IT9137)",
+			{ &it913x_table[0], NULL },
+			},
+		{   "ITE 9135 Generic",
+			{ &it913x_table[1], NULL },
+			},
+	}
+};
+
+static struct usb_driver it913x_driver = {
+	.name		= "it913x",
+	.probe		= it913x_probe,
+	.disconnect	= dvb_usb_device_exit,
+	.id_table	= it913x_table,
+};
+
+/* module stuff */
+static int __init it913x_module_init(void)
+{
+	int result = usb_register(&it913x_driver);
+	if (result) {
+		err("usb_register failed. Error number %d", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit it913x_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&it913x_driver);
+}
+
+module_init(it913x_module_init);
+module_exit(it913x_module_exit);
+
+MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
+MODULE_DESCRIPTION("it913x USB 2 Driver");
+MODULE_VERSION("1.07");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/Kconfig linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -258,6 +258,19 @@ config DVB_USB_AF9005_REMOTE
 	  Say Y here to support the default remote control decoding for the
 	  Afatech AF9005 based receiver.
 
+config DVB_USB_PCTV452E
+	tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
+	depends on DVB_USB
+	select TTPCI_EEPROM
+	select DVB_LNBP22 if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
+	select DVB_STB6100 if !DVB_FE_CUSTOMISE
+	help
+	  Support for external USB adapter designed by Pinnacle,
+	  shipped under the brand name 'PCTV HDTV Pro USB'.
+	  Also supports TT Connect S2-3600/3650 cards.
+	  Say Y if you own such a device and want to use it.
+
 config DVB_USB_DW2102
 	tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
 	depends on DVB_USB
@@ -374,3 +387,18 @@ config DVB_USB_TECHNISAT_USB2
 	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_IT913X
+	tristate "it913x driver"
+	depends on DVB_USB
+	select DVB_IT913X_FE
+	help
+	  Say Y here to support the it913x device
+
+config DVB_USB_MXL111SF
+	tristate "MxL111SF DTV USB2.0 support"
+	depends on DVB_USB
+	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+	select VIDEO_TVEEPROM
+	help
+	  Say Y here to support the MxL111SF USB2.0 DTV receiver.
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c	2013-05-02 01:34:34.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c	2013-05-01 23:42:41.000000000 -0400
@@ -162,7 +162,7 @@ static int lme2510_usb_talk(struct dvb_u
 	int ret = 0;
 
 	if (st->usb_buffer == NULL) {
-		st->usb_buffer = kmalloc(512, GFP_KERNEL);
+		st->usb_buffer = kmalloc(64, GFP_KERNEL);
 		if (st->usb_buffer == NULL) {
 			info("MEM Error no memory");
 			return -ENOMEM;
@@ -175,8 +175,8 @@ static int lme2510_usb_talk(struct dvb_u
 	if (ret < 0)
 		return -EAGAIN;
 
-	/* the read/write capped at 512 */
-	memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+	/* the read/write capped at 64 */
+	memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
 
 	ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
 
@@ -186,8 +186,8 @@ static int lme2510_usb_talk(struct dvb_u
 
 	ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
 
-	ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ?
-			512 : rlen , 0x01);
+	ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
+			rlen : 64 , 0x01);
 
 	if (rlen > 0)
 		memcpy(rbuf, buff, rlen);
@@ -333,7 +333,7 @@ static int lme2510_int_read(struct dvb_u
 	if (lme_int->lme_urb == NULL)
 			return -ENOMEM;
 
-	lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC,
+	lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
 					&lme_int->lme_urb->transfer_dma);
 
 	if (lme_int->buffer == NULL)
@@ -343,10 +343,10 @@ static int lme2510_int_read(struct dvb_u
 				adap->dev->udev,
 				usb_rcvintpipe(adap->dev->udev, 0xa),
 				lme_int->buffer,
-				4096,
+				128,
 				lme2510_int_response,
 				adap,
-				11);
+				8);
 
 	lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -580,7 +580,7 @@ static int lme2510_i2c_xfer(struct i2c_a
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	struct lme2510_state *st = d->priv;
-	static u8 obuf[64], ibuf[512];
+	static u8 obuf[64], ibuf[64];
 	int i, read, read_o;
 	u16 len;
 	u8 gate = st->i2c_gate;
@@ -621,7 +621,7 @@ static int lme2510_i2c_xfer(struct i2c_a
 			len = msg[i].len+3;
 		}
 
-		if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) {
+		if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
 			deb_info(1, "i2c transfer failed.");
 			return -EAGAIN;
 		}
@@ -941,7 +941,7 @@ static int lme_name(struct dvb_usb_adapt
 	const char *desc = adap->dev->desc->name;
 	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
 				" SHARP:BS2F7HZ0194"};
-	char *name = adap->fe->ops.info.name;
+	char *name = adap->fe_adap[0].fe->ops.info.name;
 
 	strlcpy(name, desc, 128);
 	strlcat(name, fe_name[st->tuner_config], 128);
@@ -958,10 +958,10 @@ static int dm04_lme2510_frontend_attach(
 	st->i2c_talk_onoff = 1;
 
 	st->i2c_gate = 4;
-	adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
+	adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
 		&adap->dev->i2c_adap);
 
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("TUN Found Frontend TDA10086");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 4;
@@ -975,9 +975,9 @@ static int dm04_lme2510_frontend_attach(
 	}
 
 	st->i2c_gate = 4;
-	adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
+	adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
 			&adap->dev->i2c_adap);
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("FE Found Stv0299");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
@@ -991,9 +991,9 @@ static int dm04_lme2510_frontend_attach(
 	}
 
 	st->i2c_gate = 5;
-	adap->fe = dvb_attach(stv0288_attach, &lme_config,
+	adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
 			&adap->dev->i2c_adap);
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("FE Found Stv0288");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
@@ -1010,15 +1010,15 @@ static int dm04_lme2510_frontend_attach(
 
 
 end:	if (ret) {
-		if (adap->fe) {
-			dvb_frontend_detach(adap->fe);
-			adap->fe = NULL;
+		if (adap->fe_adap[0].fe) {
+			dvb_frontend_detach(adap->fe_adap[0].fe);
+			adap->fe_adap[0].fe = NULL;
 		}
 		adap->dev->props.rc.core.rc_codes = NULL;
 		return -ENODEV;
 	}
 
-	adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
+	adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
 	ret = lme_name(adap);
 	return ret;
 }
@@ -1031,17 +1031,17 @@ static int dm04_lme2510_tuner(struct dvb
 
 	switch (st->tuner_config) {
 	case TUNER_LG:
-		if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
+		if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap, 1))
 			ret = st->tuner_config;
 		break;
 	case TUNER_S7395:
-		if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
+		if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
 			&adap->dev->i2c_adap))
 			ret = st->tuner_config;
 		break;
 	case TUNER_S0194:
-		if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
+		if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap, DVB_PLL_OPERA1))
 			ret = st->tuner_config;
 		break;
@@ -1145,6 +1145,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
 				DVB_USB_ADAP_NEED_PID_FILTERING|
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1166,6 +1168,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}},
 		}
 	},
 	.rc.core = {
@@ -1193,6 +1196,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
 				DVB_USB_ADAP_NEED_PID_FILTERING|
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1214,6 +1219,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}},
 		}
 	},
 	.rc.core = {
@@ -1241,7 +1247,7 @@ static void *lme2510_exit_int(struct dvb
 	void *buffer = NULL;
 
 	if (adap != NULL) {
-		lme2510_kill_urb(&adap->stream);
+		lme2510_kill_urb(&adap->fe_adap[0].stream);
 		adap->feedcount = 0;
 	}
 
@@ -1255,7 +1261,7 @@ static void *lme2510_exit_int(struct dvb
 
 	if (st->lme_urb != NULL) {
 		usb_kill_urb(st->lme_urb);
-		usb_free_coherent(d->udev, 5000, st->buffer,
+		usb_free_coherent(d->udev, 128, st->buffer,
 				  st->lme_urb->transfer_dma);
 		info("Interrupt Service Stopped");
 	}
@@ -1306,5 +1312,5 @@ module_exit(lme2510_module_exit);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.88");
+MODULE_VERSION("1.90");
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/m920x.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/m920x.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/m920x.c	2013-05-02 01:34:36.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/m920x.c	2013-05-01 23:42:43.000000000 -0400
@@ -86,12 +86,12 @@ static int m920x_init(struct dvb_usb_dev
 	}
 
 	for (i = 0; i < d->props.num_adapters; i++)
-		flags |= d->adapter[i].props.caps;
+		flags |= d->adapter[i].props.fe[0].caps;
 
 	/* Some devices(Dposh) might crash if we attempt touch at all. */
 	if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
 		for (i = 0; i < d->props.num_adapters; i++) {
-			epi = d->adapter[i].props.stream.endpoint - 0x81;
+			epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
 
 			if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
 				printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
@@ -292,7 +292,7 @@ static int m920x_update_filters(struct d
 	struct m920x_state *m = adap->dev->priv;
 	int enabled = m->filtering_enabled[adap->id];
 	int i, ret = 0, filter = 0;
-	int ep = adap->props.stream.endpoint;
+	int ep = adap->props.fe[0].stream.endpoint;
 
 	for (i = 0; i < M9206_MAX_FILTERS; i++)
 		if (m->filters[adap->id][i] == 8192)
@@ -501,9 +501,10 @@ static int m920x_mt352_frontend_attach(s
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(mt352_attach,
-				   &m920x_mt352_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+					 &m920x_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -513,9 +514,10 @@ static int m920x_tda10046_08_frontend_at
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(tda10046_attach,
-				   &m920x_tda10046_08_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+					 &m920x_tda10046_08_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -525,9 +527,10 @@ static int m920x_tda10046_0b_frontend_at
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(tda10046_attach,
-				   &m920x_tda10046_0b_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+					 &m920x_tda10046_0b_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -537,7 +540,7 @@ static int m920x_qt1010_tuner_attach(str
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+	if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -547,7 +550,7 @@ static int m920x_tda8275_60_tuner_attach
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -557,7 +560,7 @@ static int m920x_tda8275_61_tuner_attach
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -565,7 +568,7 @@ static int m920x_tda8275_61_tuner_attach
 
 static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61,
 		   TUNER_PHILIPS_FMD1216ME_MK3);
 	return 0;
@@ -807,6 +810,9 @@ static struct dvb_usb_device_properties
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -827,6 +833,7 @@ static struct dvb_usb_device_properties
 				}
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -851,6 +858,9 @@ static struct dvb_usb_device_properties
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -871,6 +881,7 @@ static struct dvb_usb_device_properties
 				}
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -910,6 +921,9 @@ static struct dvb_usb_device_properties
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 2,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -929,7 +943,11 @@ static struct dvb_usb_device_properties
 					 .buffersize = 512,
 				 }
 			}
+		}},
 		}},{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -949,6 +967,7 @@ static struct dvb_usb_device_properties
 					 .buffersize = 512,
 				 }
 			}
+		}},
 		},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
@@ -974,6 +993,8 @@ static struct dvb_usb_device_properties
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 		/* Hardware pid filters don't work with this device/firmware */
 
 		.frontend_attach  = m920x_mt352_frontend_attach,
@@ -989,6 +1010,7 @@ static struct dvb_usb_device_properties
 				 }
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -1019,6 +1041,9 @@ static struct dvb_usb_device_properties
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1041,6 +1066,7 @@ static struct dvb_usb_device_properties
 				}
 			}
 		},
+		}},
 	} },
 	.i2c_algo         = &m920x_i2c_algo,
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -64,6 +64,9 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += d
 dvb-usb-anysee-objs = anysee.o
 obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
 
+dvb-usb-pctv452e-objs = pctv452e.o
+obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
+
 dvb-usb-dw2102-objs = dw2102.o
 obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
 
@@ -94,7 +97,16 @@ obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb
 dvb-usb-technisat-usb2-objs = technisat-usb2.o
 obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+dvb-usb-it913x-objs := it913x.o
+obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
+
+dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/i2c.h>
+
+#include "mxl111sf.h"
+#include "mxl111sf-reg.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf-gpio.h"
+
+#include "mxl111sf-demod.h"
+#include "mxl111sf-tuner.h"
+
+#include "lgdt3305.h"
+
+int dvb_usb_mxl111sf_debug;
+module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level "
+		 "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
+
+int dvb_usb_mxl111sf_isoc;
+module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
+MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
+
+#define ANT_PATH_AUTO 0
+#define ANT_PATH_EXTERNAL 1
+#define ANT_PATH_INTERNAL 2
+
+int dvb_usb_mxl111sf_rfswitch =
+#if 0
+		ANT_PATH_AUTO;
+#else
+		ANT_PATH_EXTERNAL;
+#endif
+
+module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
+MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define deb_info(args...)   dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
+#define deb_reg(args...)    dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
+#define deb_adv(args...)    dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
+
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	int wo = (rbuf == NULL || rlen == 0); /* write-only */
+	int ret;
+	u8 sndbuf[1+wlen];
+
+	deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+
+	memset(sndbuf, 0, 1+wlen);
+
+	sndbuf[0] = cmd;
+	memcpy(&sndbuf[1], wbuf, wlen);
+
+	ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
+		dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define MXL_CMD_REG_READ	0xaa
+#define MXL_CMD_REG_WRITE	0x55
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
+{
+	u8 buf[2];
+	int ret;
+
+	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+	if (mxl_fail(ret)) {
+		mxl_debug("error reading reg: 0x%02x", addr);
+		goto fail;
+	}
+
+	if (buf[0] == addr)
+		*data = buf[1];
+	else {
+		err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
+		    addr, buf[0], buf[1]);
+		ret = -EINVAL;
+	}
+
+	deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
+fail:
+	return ret;
+}
+
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
+{
+	u8 buf[] = { addr, data };
+	int ret;
+
+	deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
+
+	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+	if (mxl_fail(ret))
+		err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+				   u8 addr, u8 mask, u8 data)
+{
+	int ret;
+	u8 val;
+
+	if (mask != 0xff) {
+		ret = mxl111sf_read_reg(state, addr, &val);
+#if 1
+		/* dont know why this usually errors out on the first try */
+		if (mxl_fail(ret))
+			err("error writing addr: 0x%02x, mask: 0x%02x, "
+			    "data: 0x%02x, retrying...", addr, mask, data);
+
+		ret = mxl111sf_read_reg(state, addr, &val);
+#endif
+		if (mxl_fail(ret))
+			goto fail;
+	}
+	val &= ~mask;
+	val |= data;
+
+	ret = mxl111sf_write_reg(state, addr, val);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	int i, ret = 0;
+
+	for (i = 0;  ctrl_reg_info[i].addr |
+		     ctrl_reg_info[i].mask |
+		     ctrl_reg_info[i].data;  i++) {
+
+		ret = mxl111sf_write_reg_mask(state,
+					      ctrl_reg_info[i].addr,
+					      ctrl_reg_info[i].mask,
+					      ctrl_reg_info[i].data);
+		if (mxl_fail(ret)) {
+			err("failed on reg #%d (0x%02x)", i,
+			    ctrl_reg_info[i].addr);
+			break;
+		}
+	}
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 id, ver;
+	char *mxl_chip, *mxl_rev;
+
+	if ((state->chip_id) && (state->chip_ver))
+		return 0;
+
+	ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
+	if (mxl_fail(ret))
+		goto fail;
+	state->chip_id = id;
+
+	ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
+	if (mxl_fail(ret))
+		goto fail;
+	state->chip_ver = ver;
+
+	switch (id) {
+	case 0x61:
+		mxl_chip = "MxL101SF";
+		break;
+	case 0x63:
+		mxl_chip = "MxL111SF";
+		break;
+	default:
+		mxl_chip = "UNKNOWN MxL1X1";
+		break;
+	}
+	switch (ver) {
+	case 0x36:
+		state->chip_rev = MXL111SF_V6;
+		mxl_rev = "v6";
+		break;
+	case 0x08:
+		state->chip_rev = MXL111SF_V8_100;
+		mxl_rev = "v8_100";
+		break;
+	case 0x18:
+		state->chip_rev = MXL111SF_V8_200;
+		mxl_rev = "v8_200";
+		break;
+	default:
+		state->chip_rev = 0;
+		mxl_rev = "UNKNOWN REVISION";
+		break;
+	}
+	info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
+fail:
+	return ret;
+}
+
+#define get_chip_info(state)						\
+({									\
+	int ___ret;							\
+	___ret = mxl1x1sf_get_chip_info(state);				\
+	if (mxl_fail(___ret)) {						\
+		mxl_debug("failed to get chip info"			\
+			  " on first probe attempt");			\
+		___ret = mxl1x1sf_get_chip_info(state);			\
+		if (mxl_fail(___ret))					\
+			err("failed to get chip info during probe");	\
+		else							\
+			mxl_debug("probe needed a retry "		\
+				  "in order to succeed.");		\
+	}								\
+	___ret;								\
+})
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	/* power control depends on which adapter is being woken:
+	 * save this for init, instead, via mxl111sf_adap_fe_init */
+	return 0;
+}
+
+static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+
+	int err;
+
+	/* exit if we didnt initialize the driver yet */
+	if (!state->chip_id) {
+		mxl_debug("driver not yet initialized, exit.");
+		goto fail;
+	}
+
+	deb_info("%s()\n", __func__);
+
+	mutex_lock(&state->fe_lock);
+
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	err = mxl1x1sf_soft_reset(state);
+	mxl_fail(err);
+	err = mxl111sf_init_tuner_demod(state);
+	mxl_fail(err);
+	err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+
+	mxl_fail(err);
+	mxl111sf_enable_usb_output(state);
+	mxl_fail(err);
+	mxl1x1sf_top_master_ctrl(state, 1);
+	mxl_fail(err);
+
+	if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
+	    (state->chip_rev > MXL111SF_V6)) {
+		mxl111sf_config_pin_mux_modes(state,
+					      PIN_MUX_TS_SPI_IN_MODE_1);
+		mxl_fail(err);
+	}
+	err = mxl111sf_init_port_expander(state);
+	if (!mxl_fail(err)) {
+		state->gpio_mode = adap_state->gpio_mode;
+		err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+		mxl_fail(err);
+#if 0
+		err = fe->ops.init(fe);
+#endif
+		msleep(100); /* add short delay after enabling
+			      * the demod before touching it */
+	}
+
+	return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
+fail:
+	return -ENODEV;
+}
+
+static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+	int err;
+
+	/* exit if we didnt initialize the driver yet */
+	if (!state->chip_id) {
+		mxl_debug("driver not yet initialized, exit.");
+		goto fail;
+	}
+
+	deb_info("%s()\n", __func__);
+
+	err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
+
+	mutex_unlock(&state->fe_lock);
+
+	return err;
+fail:
+	return -ENODEV;
+}
+
+
+static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
+	int ret = 0;
+	u8 tmp;
+
+	deb_info("%s(%d)\n", __func__, onoff);
+
+	if (onoff) {
+		ret = mxl111sf_enable_usb_output(state);
+		mxl_fail(ret);
+		ret = mxl111sf_config_mpeg_in(state, 1, 1,
+					      adap_state->ep6_clockphase,
+					      0, 0);
+		mxl_fail(ret);
+	} else {
+		ret = mxl111sf_disable_656_port(state);
+		mxl_fail(ret);
+	}
+
+	mxl111sf_read_reg(state, 0x12, &tmp);
+	tmp &= ~0x04;
+	mxl111sf_write_reg(state, 0x12, tmp);
+
+	return ret;
+}
+
+static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int ret = 0;
+
+	deb_info("%s(%d)\n", __func__, onoff);
+
+	if (onoff) {
+		ret = mxl111sf_enable_usb_output(state);
+		mxl_fail(ret);
+	}
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+	.i2c_addr           = 0xb2 >> 1,
+	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
+	.tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+	.deny_i2c_rptr      = 1,
+	.spectral_inversion = 0,
+	.qam_if_khz         = 6000,
+	.vsb_if_khz         = 6000,
+};
+
+static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+	int ret;
+
+	deb_adv("%s()\n", __func__);
+
+	/* save a pointer to the dvb_usb_device in device state */
+	state->d = d;
+	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
+	adap_state->gpio_mode = state->gpio_mode;
+	adap_state->device_mode = MXL_TUNER_MODE;
+	adap_state->ep6_clockphase = 1;
+
+	ret = mxl1x1sf_soft_reset(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_init_tuner_demod(state);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_enable_usb_output(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_top_master_ctrl(state, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_init_port_expander(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
+				 &hauppauge_lgdt3305_config,
+				 &adap->dev->i2c_adap);
+	if (adap->fe_adap[fe_id].fe) {
+		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+		return 0;
+	}
+	ret = -EIO;
+fail:
+	return ret;
+}
+
+static struct mxl111sf_demod_config mxl_demod_config = {
+	.read_reg        = mxl111sf_read_reg,
+	.write_reg       = mxl111sf_write_reg,
+	.program_regs    = mxl111sf_ctrl_program_regs,
+};
+
+static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+	int ret;
+
+	deb_adv("%s()\n", __func__);
+
+	/* save a pointer to the dvb_usb_device in device state */
+	state->d = d;
+	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
+	adap_state->gpio_mode = state->gpio_mode;
+	adap_state->device_mode = MXL_SOC_MODE;
+	adap_state->ep6_clockphase = 1;
+
+	ret = mxl1x1sf_soft_reset(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_init_tuner_demod(state);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_enable_usb_output(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_top_master_ctrl(state, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* dont care if this fails */
+	mxl111sf_init_port_expander(state);
+
+	adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
+			      &mxl_demod_config);
+	if (adap->fe_adap[fe_id].fe) {
+		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+		return 0;
+	}
+	ret = -EIO;
+fail:
+	return ret;
+}
+
+static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
+					int antpath)
+{
+	return mxl111sf_idac_config(state, 1, 1,
+				    (antpath == ANT_PATH_INTERNAL) ?
+				    0x3f : 0x00, 0);
+}
+
+#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
+	err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
+	    __func__, __LINE__, \
+	    (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
+	    pwr0, pwr1, pwr2, pwr3)
+
+#define ANT_HUNT_SLEEP 90
+#define ANT_EXT_TWEAK 0
+
+static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+
+	int antctrl = dvb_usb_mxl111sf_rfswitch;
+
+	u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
+
+	/* FIXME: must force EXTERNAL for QAM - done elsewhere */
+	mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
+			      ANT_PATH_EXTERNAL : antctrl);
+
+	if (antctrl == ANT_PATH_AUTO) {
+#if 0
+		msleep(ANT_HUNT_SLEEP);
+#endif
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
+
+		if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
+			/* return with EXTERNAL enabled */
+			mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+			DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
+				   rxPwr0, rxPwr1, rxPwr2);
+		} else {
+			/* return with INTERNAL enabled */
+			DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
+				   rxPwr0, rxPwr1, rxPwr2);
+		}
+	}
+	return 0;
+}
+
+static struct mxl111sf_tuner_config mxl_tuner_config = {
+	.if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
+	.invert_spectrum = 0,
+	.read_reg        = mxl111sf_read_reg,
+	.write_reg       = mxl111sf_write_reg,
+	.program_regs    = mxl111sf_ctrl_program_regs,
+	.top_master_ctrl = mxl1x1sf_top_master_ctrl,
+	.ant_hunt        = mxl111sf_ant_hunt,
+};
+
+static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+
+	deb_adv("%s()\n", __func__);
+
+	if (NULL != dvb_attach(mxl111sf_tuner_attach,
+			       adap->fe_adap[fe_id].fe, state,
+			       &mxl_tuner_config))
+		return 0;
+
+	return -EIO;
+}
+
+static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
+				      unsigned int cmd, void *parg,
+				      unsigned int stage)
+{
+	int err = 0;
+
+	switch (stage) {
+	case DVB_FE_IOCTL_PRE:
+
+		switch (cmd) {
+		case FE_READ_SIGNAL_STRENGTH:
+			err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
+			/* If no error occurs, prevent dvb-core from handling
+			 * this IOCTL, otherwise return the error */
+			if (0 == err)
+				err = 1;
+			break;
+		}
+		break;
+
+	case DVB_FE_IOCTL_POST:
+		/* no post-ioctl handling required */
+		break;
+	}
+	return err;
+};
+
+static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm mxl111sf_i2c_algo = {
+	.master_xfer   = mxl111sf_i2c_xfer,
+	.functionality = mxl111sf_i2c_func,
+#ifdef NEED_ALGO_CONTROL
+	.algo_control = dummy_algo_control,
+#endif
+};
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
+
+static int mxl111sf_probe(struct usb_interface *intf,
+			  const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d = NULL;
+
+	deb_adv("%s()\n", __func__);
+
+	if (((dvb_usb_mxl111sf_isoc) &&
+	     (0 == dvb_usb_device_init(intf,
+				       &mxl111sf_dvbt_isoc_properties,
+				       THIS_MODULE, &d, adapter_nr) ||
+	      0 == dvb_usb_device_init(intf,
+				       &mxl111sf_atsc_isoc_properties,
+				       THIS_MODULE, &d, adapter_nr))) ||
+	    0 == dvb_usb_device_init(intf,
+				     &mxl111sf_dvbt_bulk_properties,
+				     THIS_MODULE, &d, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf,
+				     &mxl111sf_atsc_bulk_properties,
+				     THIS_MODULE, &d, adapter_nr) || 0) {
+
+		struct mxl111sf_state *state = d->priv;
+		static u8 eeprom[256];
+		struct i2c_client c;
+		int ret;
+
+		ret = get_chip_info(state);
+		if (mxl_fail(ret))
+			err("failed to get chip info during probe");
+
+		mutex_init(&state->fe_lock);
+
+		if (state->chip_rev > MXL111SF_V6)
+			mxl111sf_config_pin_mux_modes(state,
+						      PIN_MUX_TS_SPI_IN_MODE_1);
+
+		c.adapter = &d->i2c_adap;
+		c.addr = 0xa0 >> 1;
+
+		ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
+		if (mxl_fail(ret))
+			return 0;
+		tveeprom_hauppauge_analog(&c, &state->tv,
+					  (0x84 == eeprom[0xa0]) ?
+					  eeprom + 0xa0 : eeprom + 0x80);
+#if 0
+		switch (state->tv.model) {
+		case 117001:
+		case 126001:
+		case 138001:
+			break;
+		default:
+			printk(KERN_WARNING "%s: warning: "
+			       "unknown hauppauge model #%d\n",
+			       __func__, state->tv.model);
+		}
+#endif
+		return 0;
+	}
+	err("Your device is not yet supported by this driver. "
+	    "See kernellabs.com for more info");
+	return -EINVAL;
+}
+
+static struct usb_device_id mxl111sf_table[] = {
+/* 0 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC         */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /*     +        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT         */
+/* 5 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC  IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /*     + IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT  IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+        */
+/*10 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /*     + sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw     */
+/*15 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw     */
+/*20 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT  sw     */
+/*25 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /*     +        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+        */
+/*30 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /*     + IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
+	{}		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, mxl111sf_table);
+
+
+#define MXL111SF_EP4_BULK_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_BULK,			\
+		.count = 5,				\
+		.endpoint = 0x04,			\
+		.u = {					\
+			.bulk = {			\
+				.buffersize = 8192,	\
+			}				\
+		}					\
+	}
+
+/* FIXME: works for v6 but not v8 silicon */
+#define MXL111SF_EP4_ISOC_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_ISOC,			\
+		.count = 5,				\
+		.endpoint = 0x04,			\
+		.u = {					\
+			.isoc = {			\
+				.framesperurb = 96,	\
+				/* FIXME: v6 SILICON: */	\
+				.framesize = 564,	\
+				.interval = 1,		\
+			}				\
+		}					\
+	}
+
+#define MXL111SF_EP6_BULK_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_BULK,			\
+		.count = 5,				\
+		.endpoint = 0x06,			\
+		.u = {					\
+			.bulk = {			\
+				.buffersize = 8192,	\
+			}				\
+		}					\
+	}
+
+/* FIXME */
+#define MXL111SF_EP6_ISOC_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_ISOC,			\
+		.count = 5,				\
+		.endpoint = 0x06,			\
+		.u = {					\
+			.isoc = {			\
+				.framesperurb = 24,	\
+				.framesize = 3072,	\
+				.interval = 1,		\
+			}				\
+		}					\
+	}
+
+#define MXL111SF_DEFAULT_DEVICE_PROPERTIES			\
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,			\
+	.usb_ctrl = DEVICE_SPECIFIC,				\
+	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),	\
+				     EP6 BULK transfer (atsc/qam), \
+	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),	\
+				     EP6 ISOC transfer (atsc/qam), \
+	*/							\
+	.power_ctrl       = mxl111sf_power_ctrl,		\
+	.i2c_algo         = &mxl111sf_i2c_algo,			\
+	.generic_bulk_ctrl_endpoint          = MXL_EP2_REG_WRITE, \
+	.generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
+	.size_of_priv     = sizeof(struct mxl111sf_state)
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 1,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_BULK_STREAMING_CONFIG,
+		} },
+		},
+	},
+	.num_device_descs = 4,
+	.devices = {
+		{   "Hauppauge 126xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[4], &mxl111sf_table[8],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[15], &mxl111sf_table[18],
+			  NULL },
+		},
+		{   "Hauppauge 138xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[20], &mxl111sf_table[22],
+			  &mxl111sf_table[24], &mxl111sf_table[26],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx (tp-bulk)",
+			{ NULL },
+			{ &mxl111sf_table[28], &mxl111sf_table[30],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 1,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+		} },
+		},
+	},
+	.num_device_descs = 4,
+	.devices = {
+		{   "Hauppauge 126xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[4], &mxl111sf_table[8],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[15], &mxl111sf_table[18],
+			  NULL },
+		},
+		{   "Hauppauge 138xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[20], &mxl111sf_table[22],
+			  &mxl111sf_table[24], &mxl111sf_table[26],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[28], &mxl111sf_table[30],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 2,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP6_BULK_STREAMING_CONFIG,
+		},
+		{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_BULK_STREAMING_CONFIG,
+		}},
+		},
+	},
+	.num_device_descs = 6,
+	.devices = {
+		{   "Hauppauge 126xxx ATSC (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[1], &mxl111sf_table[5],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx ATSC (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[12],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx ATSC+ (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[0], &mxl111sf_table[3],
+			  &mxl111sf_table[7], &mxl111sf_table[9],
+			  &mxl111sf_table[10], NULL },
+		},
+		{   "Hauppauge 117xxx ATSC+ (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[11], &mxl111sf_table[14],
+			  &mxl111sf_table[16], &mxl111sf_table[17],
+			  &mxl111sf_table[32], &mxl111sf_table[33],
+			  NULL },
+		},
+		{   "Hauppauge Mercury (tp-bulk)",
+			{ NULL },
+			{ &mxl111sf_table[19], &mxl111sf_table[21],
+			  &mxl111sf_table[23], &mxl111sf_table[25],
+			  &mxl111sf_table[27], NULL },
+		},
+		{   "Hauppauge WinTV-Aero-M",
+			{ NULL },
+			{ &mxl111sf_table[29], &mxl111sf_table[31],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 2,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+		},
+		{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+		}},
+		},
+	},
+	.num_device_descs = 6,
+	.devices = {
+		{   "Hauppauge 126xxx ATSC (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[1], &mxl111sf_table[5],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx ATSC (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[12],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx ATSC+ (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[0], &mxl111sf_table[3],
+			  &mxl111sf_table[7], &mxl111sf_table[9],
+			  &mxl111sf_table[10], NULL },
+		},
+		{   "Hauppauge 117xxx ATSC+ (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[11], &mxl111sf_table[14],
+			  &mxl111sf_table[16], &mxl111sf_table[17],
+			  &mxl111sf_table[32], &mxl111sf_table[33],
+			  NULL },
+		},
+		{   "Hauppauge Mercury (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[19], &mxl111sf_table[21],
+			  &mxl111sf_table[23], &mxl111sf_table[25],
+			  &mxl111sf_table[27], NULL },
+		},
+		{   "Hauppauge WinTV-Aero-M (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[29], &mxl111sf_table[31],
+			  NULL },
+		},
+	}
+};
+
+static struct usb_driver mxl111sf_driver = {
+	.name		= "dvb_usb_mxl111sf",
+	.probe		= mxl111sf_probe,
+	.disconnect     = dvb_usb_device_exit,
+	.id_table	= mxl111sf_table,
+};
+
+static int __init mxl111sf_module_init(void)
+{
+	int result = usb_register(&mxl111sf_driver);
+	if (result) {
+		err("usb_register failed. Error number %d", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit mxl111sf_module_exit(void)
+{
+	usb_deregister(&mxl111sf_driver);
+}
+
+module_init(mxl111sf_module_init);
+module_exit(mxl111sf_module_exit);
+
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,614 @@
+/*
+ *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-demod.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_demod_debug;
+module_param_named(debug, mxl111sf_demod_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+	if (mxl111sf_demod_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_demod_state {
+	struct mxl111sf_state *mxl_state;
+
+	struct mxl111sf_demod_config *cfg;
+
+	struct dvb_frontend fe;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
+				   u8 addr, u8 *data)
+{
+	return (state->cfg->read_reg) ?
+		state->cfg->read_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
+				    u8 addr, u8 data)
+{
+	return (state->cfg->write_reg) ?
+		state->cfg->write_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static
+int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
+				struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	return (state->cfg->program_regs) ?
+		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+		-EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+/* TPS */
+
+static
+int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
+				     fe_code_rate_t *code_rate)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
+	/* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch (val & V6_CODE_RATE_TPS_MASK) {
+	case 0:
+		*code_rate = FEC_1_2;
+		break;
+	case 1:
+		*code_rate = FEC_2_3;
+		break;
+	case 2:
+		*code_rate = FEC_3_4;
+		break;
+	case 3:
+		*code_rate = FEC_5_6;
+		break;
+	case 4:
+		*code_rate = FEC_7_8;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
+					 fe_modulation_t *constellation)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
+	/* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
+	case 0:
+		*constellation = QPSK;
+		break;
+	case 1:
+		*constellation = QAM_16;
+		break;
+	case 2:
+		*constellation = QAM_64;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
+					  fe_transmit_mode_t *fft_mode)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
+	/* FFT Mode, 00:2K, 01:8K, 10:4K */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
+	case 0:
+		*fft_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		*fft_mode = TRANSMISSION_MODE_8K;
+		break;
+	case 2:
+		*fft_mode = TRANSMISSION_MODE_4K;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
+					  fe_guard_interval_t *guard)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
+	/* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_GI_MASK) >> 4) {
+	case 0:
+		*guard = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		*guard = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		*guard = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		*guard = GUARD_INTERVAL_1_4;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
+				     fe_hierarchy_t *hierarchy)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
+	/* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
+	case 0:
+		*hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		*hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		*hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		*hierarchy = HIERARCHY_4;
+		break;
+	}
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+/* LOCKS */
+
+static
+int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
+					int *sync_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*sync_lock = (val & SYNC_LOCK_MASK) >> 4;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
+				      int *rs_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
+				       int *tps_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
+				       int *fec_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
+fail:
+	return ret;
+}
+
+#if 0
+static
+int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
+				      int *cp_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
+fail:
+	return ret;
+}
+#endif
+
+static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
+{
+	return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
+				       struct dvb_frontend_parameters *param)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	int ret = 0;
+
+	struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
+		{0x00, 0xff, 0x01}, /* change page to 1 */
+		{0x40, 0xff, 0x05},
+		{0x40, 0xff, 0x01},
+		{0x41, 0xff, 0xca},
+		{0x41, 0xff, 0xc0},
+		{0x00, 0xff, 0x00}, /* change page to 0 */
+		{0,    0,    0}
+	};
+
+	mxl_dbg("()");
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe, param);
+		if (mxl_fail(ret))
+			goto fail;
+		msleep(50);
+	}
+	ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
+	mxl_fail(ret);
+	msleep(50);
+	ret = mxl1x1sf_demod_reset_irq_status(state);
+	mxl_fail(ret);
+	msleep(100);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+/* resets TS Packet error count */
+/* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
+static
+int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
+{
+	struct mxl111sf_reg_ctrl_info reset_per_count[] = {
+		{0x20, 0x01, 0x01},
+		{0x20, 0x01, 0x00},
+		{0,    0,    0}
+	};
+	return mxl111sf_demod_program_regs(state, reset_per_count);
+}
+#endif
+
+/* returns TS Packet error count */
+/* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
+static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	u32 fec_per_count, fec_per_scale;
+	u8 val;
+	int ret;
+
+	*ucblocks = 0;
+
+	/* FEC_PER_COUNT Register */
+	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	fec_per_count = val;
+
+	/* FEC_PER_SCALE Register */
+	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	val &= V6_FEC_PER_SCALE_MASK;
+	val *= 4;
+
+	fec_per_scale = 1 << val;
+
+	fec_per_count *= fec_per_scale;
+
+	*ucblocks = fec_per_count;
+fail:
+	return ret;
+}
+
+#ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
+/* FIXME: leaving this enabled breaks the build on some architectures,
+ * and we shouldn't have any floating point math in the kernel, anyway.
+ *
+ * These macros need to be re-written, but it's harmless to simply
+ * return zero for now. */
+#define CALCULATE_BER(avg_errors, count) \
+	((u32)(avg_errors * 4)/(count*64*188*8))
+#define CALCULATE_SNR(data) \
+	((u32)((10 * (u32)data / 64) - 2.5))
+#else
+#define CALCULATE_BER(avg_errors, count) 0
+#define CALCULATE_SNR(data) 0
+#endif
+
+static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	u8 val1, val2, val3;
+	int ret;
+
+	*ber = 0;
+
+	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
+				   u16 *snr)
+{
+	u8 val1, val2;
+	int ret;
+
+	*snr = 0;
+
+	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+	int ret = mxl111sf_demod_calc_snr(state, snr);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*snr /= 10; /* 0.1 dB */
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
+				      fe_status_t *status)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	int ret, locked, cr_lock, sync_lock, fec_lock;
+
+	*status = 0;
+
+	ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (locked)
+		*status |= FE_HAS_SIGNAL;
+	if (cr_lock)
+		*status |= FE_HAS_CARRIER;
+	if (sync_lock)
+		*status |= FE_HAS_SYNC;
+	if (fec_lock) /* false positives? */
+		*status |= FE_HAS_VITERBI;
+
+	if ((locked) && (cr_lock) && (sync_lock))
+		*status |= FE_HAS_LOCK;
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
+					       u16 *signal_strength)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	fe_modulation_t constellation;
+	u16 snr;
+
+	mxl111sf_demod_calc_snr(state, &snr);
+	mxl1x1sf_demod_get_tps_constellation(state, &constellation);
+
+	switch (constellation) {
+	case QPSK:
+		*signal_strength = (snr >= 1300) ?
+			min(65535, snr * 44) : snr * 38;
+		break;
+	case QAM_16:
+		*signal_strength = (snr >= 1500) ?
+			min(65535, snr * 38) : snr * 33;
+		break;
+	case QAM_64:
+		*signal_strength = (snr >= 2000) ?
+			min(65535, snr * 29) : snr * 25;
+		break;
+	default:
+		*signal_strength = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
+				       struct dvb_frontend_parameters *p)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+	mxl_dbg("()");
+#if 0
+	p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
+#endif
+	if (fe->ops.tuner_ops.get_bandwidth)
+		fe->ops.tuner_ops.get_bandwidth(fe, &p->u.ofdm.bandwidth);
+	if (fe->ops.tuner_ops.get_frequency)
+		fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
+	mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_HP);
+	mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_LP);
+	mxl1x1sf_demod_get_tps_constellation(state, &p->u.ofdm.constellation);
+	mxl1x1sf_demod_get_tps_guard_fft_mode(state,
+					      &p->u.ofdm.transmission_mode);
+	mxl1x1sf_demod_get_tps_guard_interval(state,
+					      &p->u.ofdm.guard_interval);
+	mxl1x1sf_demod_get_tps_hierarchy(state,
+					 &p->u.ofdm.hierarchy_information);
+
+	return 0;
+}
+
+static
+int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void mxl111sf_demod_release(struct dvb_frontend *fe)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	mxl_dbg("()");
+	kfree(state);
+	fe->demodulator_priv = NULL;
+}
+
+static struct dvb_frontend_ops mxl111sf_demod_ops = {
+
+	.info = {
+		.name               = "MaxLinear MxL111SF DVB-T demodulator",
+		.type               = FE_OFDM,
+		.frequency_min      = 177000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 166666,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+	},
+	.release              = mxl111sf_demod_release,
+#if 0
+	.init                 = mxl111sf_init,
+	.i2c_gate_ctrl        = mxl111sf_i2c_gate_ctrl,
+#endif
+	.set_frontend         = mxl111sf_demod_set_frontend,
+	.get_frontend         = mxl111sf_demod_get_frontend,
+	.get_tune_settings    = mxl111sf_demod_get_tune_settings,
+	.read_status          = mxl111sf_demod_read_status,
+	.read_signal_strength = mxl111sf_demod_read_signal_strength,
+	.read_ber             = mxl111sf_demod_read_ber,
+	.read_snr             = mxl111sf_demod_read_snr,
+	.read_ucblocks        = mxl111sf_demod_read_ucblocks,
+};
+
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg)
+{
+	struct mxl111sf_demod_state *state = NULL;
+
+	mxl_dbg("()");
+
+	state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->mxl_state = mxl_state;
+	state->cfg = cfg;
+
+	memcpy(&state->fe.ops, &mxl111sf_demod_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	state->fe.demodulator_priv = state;
+	return &state->fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-demod.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ *  mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MXL111SF_DEMOD_H__
+#define __MXL111SF_DEMOD_H__
+
+#include "dvb_frontend.h"
+#include "mxl111sf.h"
+
+struct mxl111sf_demod_config {
+	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+	int (*program_regs)(struct mxl111sf_state *state,
+			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+};
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_USB_MXL111SF */
+
+#endif /* __MXL111SF_DEMOD_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,763 @@
+/*
+ *  mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-gpio.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define MXL_GPIO_MUX_REG_0 0x84
+#define MXL_GPIO_MUX_REG_1 0x89
+#define MXL_GPIO_MUX_REG_2 0x82
+
+#define MXL_GPIO_DIR_INPUT  0
+#define MXL_GPIO_DIR_OUTPUT 1
+
+
+static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug_adv("(%d, %d)", pin, val);
+
+	if ((pin > 0) && (pin < 8)) {
+		ret = mxl111sf_read_reg(state, 0x19, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (pin - 1));
+		tmp |= (val << (pin - 1));
+		ret = mxl111sf_write_reg(state, 0x19, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+	} else if (pin <= 10) {
+		if (pin == 0)
+			pin += 7;
+		ret = mxl111sf_read_reg(state, 0x30, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (pin - 3));
+		tmp |= (val << (pin - 3));
+		ret = mxl111sf_write_reg(state, 0x30, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+	} else
+		ret = -EINVAL;
+fail:
+	return ret;
+}
+
+static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug("(0x%02x)", pin);
+
+	*val = 0;
+
+	switch (pin) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		ret = mxl111sf_read_reg(state, 0x23, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> (pin + 4)) & 0x01;
+		break;
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		ret = mxl111sf_read_reg(state, 0x2f, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> pin) & 0x01;
+		break;
+	case 8:
+	case 9:
+	case 10:
+		ret = mxl111sf_read_reg(state, 0x22, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> (pin - 3)) & 0x01;
+		break;
+	default:
+		return -EINVAL; /* invalid pin */
+	}
+fail:
+	return ret;
+}
+
+struct mxl_gpio_cfg {
+	u8 pin;
+	u8 dir;
+	u8 val;
+};
+
+static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
+				     struct mxl_gpio_cfg *gpio_cfg)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
+
+	switch (gpio_cfg->pin) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (gpio_cfg->pin + 4));
+		tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << gpio_cfg->pin);
+		tmp |= (gpio_cfg->dir << gpio_cfg->pin);
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	case 8:
+	case 9:
+	case 10:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (gpio_cfg->pin - 3));
+		tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	default:
+		return -EINVAL; /* invalid pin */
+	}
+
+	ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
+		mxl111sf_set_gpo_state(state,
+				       gpio_cfg->pin, gpio_cfg->val) :
+		mxl111sf_get_gpi_state(state,
+				       gpio_cfg->pin, &gpio_cfg->val);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
+				   int gpio, int direction, int val)
+{
+	struct mxl_gpio_cfg gpio_config = {
+		.pin = gpio,
+		.dir = direction,
+		.val = val,
+	};
+
+	mxl_debug("(%d, %d, %d)", gpio, direction, val);
+
+	return mxl111sf_config_gpio_pins(state, &gpio_config);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#define PIN_MUX_MPEG_MODE_MASK          0x40   /* 0x17 <6> */
+#define PIN_MUX_MPEG_PAR_EN_MASK        0x01   /* 0x18 <0> */
+#define PIN_MUX_MPEG_SER_EN_MASK        0x02   /* 0x18 <1> */
+#define PIN_MUX_MPG_IN_MUX_MASK         0x80   /* 0x3D <7> */
+#define PIN_MUX_BT656_ENABLE_MASK       0x04   /* 0x12 <2> */
+#define PIN_MUX_I2S_ENABLE_MASK         0x40   /* 0x15 <6> */
+#define PIN_MUX_SPI_MODE_MASK           0x10   /* 0x3D <4> */
+#define PIN_MUX_MCLK_EN_CTRL_MASK       0x10   /* 0x82 <4> */
+#define PIN_MUX_MPSYN_EN_CTRL_MASK      0x20   /* 0x82 <5> */
+#define PIN_MUX_MDVAL_EN_CTRL_MASK      0x40   /* 0x82 <6> */
+#define PIN_MUX_MPERR_EN_CTRL_MASK      0x80   /* 0x82 <7> */
+#define PIN_MUX_MDAT_EN_0_MASK          0x10   /* 0x84 <4> */
+#define PIN_MUX_MDAT_EN_1_MASK          0x20   /* 0x84 <5> */
+#define PIN_MUX_MDAT_EN_2_MASK          0x40   /* 0x84 <6> */
+#define PIN_MUX_MDAT_EN_3_MASK          0x80   /* 0x84 <7> */
+#define PIN_MUX_MDAT_EN_4_MASK          0x10   /* 0x89 <4> */
+#define PIN_MUX_MDAT_EN_5_MASK          0x20   /* 0x89 <5> */
+#define PIN_MUX_MDAT_EN_6_MASK          0x40   /* 0x89 <6> */
+#define PIN_MUX_MDAT_EN_7_MASK          0x80   /* 0x89 <7> */
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+				  enum mxl111sf_mux_config pin_mux_config)
+{
+	u8 r12, r15, r17, r18, r3D, r82, r84, r89;
+	int ret;
+
+	mxl_debug("(%d)", pin_mux_config);
+
+	ret = mxl111sf_read_reg(state, 0x17, &r17);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x18, &r18);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x12, &r12);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x15, &r15);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x82, &r82);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x84, &r84);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x89, &r89);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x3D, &r3D);
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch (pin_mux_config) {
+	case PIN_MUX_TS_OUT_PARALLEL:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 1 */
+		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 1 */
+		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 1 */
+		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0xF */
+		r84 |= 0xF0;
+		/* mdat_en_ctrl[7:4] = 0xF */
+		r89 |= 0xF0;
+		break;
+	case PIN_MUX_TS_OUT_SERIAL:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 1 */
+		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 1 */
+		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0xF */
+		r84 |= 0xF0;
+		/* mdat_en_ctrl[7:4] = 0xF */
+		r89 |= 0xF0;
+		break;
+	case PIN_MUX_GPIO_MODE:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SERIAL_IN_MODE_0:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SERIAL_IN_MODE_1:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 1 */
+		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SPI_IN_MODE_1:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 1 */
+		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 1 */
+		r3D |= PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SPI_IN_MODE_0:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 1 */
+		r3D |= PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_PARALLEL_IN:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 1 */
+		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_BT656_I2S_MODE:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 1 */
+		r12 |= PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_DEFAULT:
+	default:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	}
+
+	ret = mxl111sf_write_reg(state, 0x17, r17);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x18, r18);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x12, r12);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x15, r15);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x82, r82);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x84, r84);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x89, r89);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x3D, r3D);
+	if (mxl_fail(ret))
+		goto fail;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
+}
+
+static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
+{
+	u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
+	int i, ret;
+
+	mxl_debug("()");
+
+	for (i = 3; i < 8; i++) {
+		ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
+		if (mxl_fail(ret))
+			break;
+	}
+
+	return ret;
+}
+
+#define PCA9534_I2C_ADDR (0x40 >> 1)
+static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	u8 w[2] = { 1, 0 };
+	u8 r = 0;
+	struct i2c_msg msg[] = {
+		{ .addr = PCA9534_I2C_ADDR,
+		  .flags = 0, .buf = w, .len = 1 },
+		{ .addr = PCA9534_I2C_ADDR,
+		  .flags = I2C_M_RD, .buf = &r, .len = 1 },
+	};
+
+	mxl_debug("(%d, %d)", gpio, val);
+
+	/* read current GPIO levels from flip-flop */
+	i2c_transfer(&state->d->i2c_adap, msg, 2);
+
+	/* prepare write buffer with current GPIO levels */
+	msg[0].len = 2;
+#if 0
+	w[0] = 1;
+#endif
+	w[1] = r;
+
+	/* clear the desired GPIO */
+	w[1] &= ~(1 << gpio);
+
+	/* set the desired GPIO value */
+	w[1] |= ((val ? 1 : 0) << gpio);
+
+	/* write new GPIO levels to flip-flop */
+	i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
+
+	return 0;
+}
+
+static int pca9534_init_port_expander(struct mxl111sf_state *state)
+{
+	u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
+
+	struct i2c_msg msg = {
+		.addr = PCA9534_I2C_ADDR,
+		.flags = 0, .buf = w, .len = 2
+	};
+
+	mxl_debug("()");
+
+	i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+	/* configure all pins as outputs */
+	w[0] = 3;
+	w[1] = 0;
+
+	i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+	return 0;
+}
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	mxl_debug("(%d, %d)", gpio, val);
+
+	switch (state->gpio_port_expander) {
+	default:
+		mxl_printk(KERN_ERR,
+			   "gpio_port_expander undefined, assuming PCA9534");
+		/* fall-thru */
+	case mxl111sf_PCA9534:
+		return pca9534_set_gpio(state, gpio, val);
+	case mxl111sf_gpio_hw:
+		return mxl111sf_hw_set_gpio(state, gpio, val);
+	}
+}
+
+static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 w = 1;
+	u8 r = 0;
+	struct i2c_msg msg[] = {
+		{ .flags = 0,        .buf = &w, .len = 1 },
+		{ .flags = I2C_M_RD, .buf = &r, .len = 1 },
+	};
+
+	mxl_debug("()");
+
+	msg[0].addr = 0x70 >> 1;
+	msg[1].addr = 0x70 >> 1;
+
+	/* read current GPIO levels from flip-flop */
+	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+	if (ret == 2) {
+		state->port_expander_addr = msg[0].addr;
+		state->gpio_port_expander = mxl111sf_PCA9534;
+		mxl_debug("found port expander at 0x%02x",
+			  state->port_expander_addr);
+		return 0;
+	}
+
+	msg[0].addr = 0x40 >> 1;
+	msg[1].addr = 0x40 >> 1;
+
+	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+	if (ret == 2) {
+		state->port_expander_addr = msg[0].addr;
+		state->gpio_port_expander = mxl111sf_PCA9534;
+		mxl_debug("found port expander at 0x%02x",
+			  state->port_expander_addr);
+		return 0;
+	}
+	state->port_expander_addr = 0xff;
+	state->gpio_port_expander = mxl111sf_gpio_hw;
+	mxl_debug("using hardware gpio");
+	return 0;
+}
+
+int mxl111sf_init_port_expander(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	if (0x00 == state->port_expander_addr)
+		mxl111sf_probe_port_expander(state);
+
+	switch (state->gpio_port_expander) {
+	default:
+		mxl_printk(KERN_ERR,
+			   "gpio_port_expander undefined, assuming PCA9534");
+		/* fall-thru */
+	case mxl111sf_PCA9534:
+		return pca9534_init_port_expander(state);
+	case mxl111sf_gpio_hw:
+		return mxl111sf_hw_gpio_initialize(state);
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
+{
+/*	GPO:
+ *	3 - ATSC/MH#   | 1 = ATSC transport, 0 = MH transport      | default 0
+ *	4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset           | default 0
+ *	5 - ATSC_EN    | 1 = ATSC power enable, 0 = ATSC power off | default 0
+ *	6 - MH_RESET#  | 1 = MH enable, 0 = MH Reset               | default 0
+ *	7 - MH_EN      | 1 = MH power enable, 0 = MH power off     | default 0
+ */
+	mxl_debug("(%d)", mode);
+
+	switch (mode) {
+	case MXL111SF_GPIO_MOD_MH:
+		mxl111sf_set_gpio(state, 4, 0);
+		mxl111sf_set_gpio(state, 5, 0);
+		msleep(50);
+		mxl111sf_set_gpio(state, 7, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 6, 1);
+		msleep(50);
+
+		mxl111sf_set_gpio(state, 3, 0);
+		break;
+	case MXL111SF_GPIO_MOD_ATSC:
+		mxl111sf_set_gpio(state, 6, 0);
+		mxl111sf_set_gpio(state, 7, 0);
+		msleep(50);
+		mxl111sf_set_gpio(state, 5, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 4, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 3, 1);
+		break;
+	default: /* DVBT / STANDBY */
+		mxl111sf_init_port_expander(state);
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ *  mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DVB_USB_MXL111SF_GPIO_H_
+#define _DVB_USB_MXL111SF_GPIO_H_
+
+#include "mxl111sf.h"
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val);
+int mxl111sf_init_port_expander(struct mxl111sf_state *state);
+
+#define MXL111SF_GPIO_MOD_DVBT	0
+#define MXL111SF_GPIO_MOD_MH	1
+#define MXL111SF_GPIO_MOD_ATSC	2
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode);
+
+enum mxl111sf_mux_config {
+	PIN_MUX_DEFAULT = 0,
+	PIN_MUX_TS_OUT_PARALLEL,
+	PIN_MUX_TS_OUT_SERIAL,
+	PIN_MUX_GPIO_MODE,
+	PIN_MUX_TS_SERIAL_IN_MODE_0,
+	PIN_MUX_TS_SERIAL_IN_MODE_1,
+	PIN_MUX_TS_SPI_IN_MODE_0,
+	PIN_MUX_TS_SPI_IN_MODE_1,
+	PIN_MUX_TS_PARALLEL_IN,
+	PIN_MUX_BT656_I2S_MODE,
+};
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+				  enum mxl111sf_mux_config pin_mux_config);
+
+#endif /* _DVB_USB_MXL111SF_GPIO_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#ifndef _DVB_USB_MXL111SF_H_
+#define _DVB_USB_MXL111SF_H_
+
+#ifdef DVB_USB_LOG_PREFIX
+#undef DVB_USB_LOG_PREFIX
+#endif
+#define DVB_USB_LOG_PREFIX "mxl111sf"
+#include "dvb-usb.h"
+#include <media/tveeprom.h>
+
+#define MXL_EP1_REG_READ     1
+#define MXL_EP2_REG_WRITE    2
+#define MXL_EP3_INTERRUPT    3
+#define MXL_EP4_MPEG2        4
+#define MXL_EP5_I2S          5
+#define MXL_EP6_656          6
+#define MXL_EP6_MPEG2        6
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+enum mxl111sf_current_mode {
+	mxl_mode_dvbt = MXL_EP4_MPEG2,
+	mxl_mode_mh   = MXL_EP5_I2S,
+	mxl_mode_atsc = MXL_EP6_MPEG2,
+};
+#endif
+
+enum mxl111sf_gpio_port_expander {
+	mxl111sf_gpio_hw,
+	mxl111sf_PCA9534,
+};
+
+struct mxl111sf_state {
+	struct dvb_usb_device *d;
+
+	enum mxl111sf_gpio_port_expander gpio_port_expander;
+	u8 port_expander_addr;
+
+	u8 chip_id;
+	u8 chip_ver;
+#define MXL111SF_V6     1
+#define MXL111SF_V8_100 2
+#define MXL111SF_V8_200 3
+	u8 chip_rev;
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+	enum mxl111sf_current_mode current_mode;
+#endif
+
+#define MXL_TUNER_MODE         0
+#define MXL_SOC_MODE           1
+#define MXL_DEV_MODE_MASK      0x01
+#if 1
+	int device_mode;
+#endif
+	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),
+				     EP5 BULK transfer (atsc-mh),
+				     EP6 BULK transfer (atsc/qam),
+	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),
+				     EP5 ISOC transfer (atsc-mh),
+				     EP6 ISOC transfer (atsc/qam),
+	 */
+	int alt_mode;
+	int gpio_mode;
+	struct tveeprom tv;
+
+	struct mutex fe_lock;
+};
+
+struct mxl111sf_adap_state {
+	int alt_mode;
+	int gpio_mode;
+	int device_mode;
+	int ep6_clockphase;
+	int (*fe_init)(struct dvb_frontend *);
+	int (*fe_sleep)(struct dvb_frontend *);
+};
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data);
+
+struct mxl111sf_reg_ctrl_info {
+	u8 addr;
+	u8 mask;
+	u8 data;
+};
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+			    u8 addr, u8 mask, u8 data);
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+
+/* needed for hardware i2c functions in mxl111sf-i2c.c:
+ * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
+
+#define mxl_printk(kern, fmt, arg...) \
+	printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define mxl_info(fmt, arg...) \
+	mxl_printk(KERN_INFO, fmt, ##arg)
+
+extern int dvb_usb_mxl111sf_debug;
+#define mxl_debug(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define MXL_I2C_DBG 0x04
+#define MXL_ADV_DBG 0x10
+#define mxl_debug_adv(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c_adv(fmt, arg...) \
+	if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \
+		(MXL_I2C_DBG | MXL_ADV_DBG)) \
+			mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* The following allows the mxl_fail() macro defined below to work
+ * in externel modules, such as mxl111sf-tuner.ko, even though
+ * dvb_usb_mxl111sf_debug is not defined within those modules */
+#if (defined(__MXL111SF_TUNER_H__)) || (defined(__MXL111SF_DEMOD_H__))
+#define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
+#else
+#define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
+#endif
+
+#define mxl_fail(ret)							\
+({									\
+	int __ret;							\
+	__ret = (ret < 0);						\
+	if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG))		\
+		mxl_printk(KERN_ERR, "error %d on line %d",		\
+			   ret, __LINE__);				\
+	__ret;								\
+})
+
+#endif /* _DVB_USB_MXL111SF_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,850 @@
+/*
+ *  mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* SW-I2C ----------------------------------------------------------------- */
+
+#define SW_I2C_ADDR		0x1a
+#define SW_I2C_EN		0x02
+#define SW_SCL_OUT		0x04
+#define SW_SDA_OUT		0x08
+#define SW_SDA_IN		0x04
+
+#define SW_I2C_BUSY_ADDR	0x2f
+#define SW_I2C_BUSY		0x02
+
+static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state,
+					 u8 byte)
+{
+	int i, ret;
+	u8 data = 0;
+
+	mxl_i2c("(0x%02x)", byte);
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	for (i = 0; i < 8; i++) {
+
+		data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data | SW_SCL_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+
+	/* last bit was 0 so we need to release SDA */
+	if (!(byte & 1)) {
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+
+	/* CLK high for ACK readback */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* drop the CLK after getting ACK, SDA will go high right away */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (data & SW_SDA_IN)
+		ret = -EIO;
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state,
+					 u8 *pbyte)
+{
+	int i, ret;
+	u8 byte = 0;
+	u8 data = 0;
+
+	mxl_i2c("()");
+
+	*pbyte = 0;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	for (i = 0; i < 8; i++) {
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN |
+					 SW_SCL_OUT | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+		if (mxl_fail(ret))
+			goto fail;
+
+		if (data & SW_SDA_IN)
+			byte |= (0x80 >> i);
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+	*pbyte = byte;
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_start(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN); /* start */
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_stop(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN); /* stop */
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_SCL_OUT | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_ack(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 b = 0;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* pull SDA low */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_nack(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	/* SDA high to signal last byte read from slave */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state,
+				    struct i2c_msg *msg)
+{
+	int i, ret;
+
+	mxl_i2c("()");
+
+	if (msg->flags & I2C_M_RD) {
+
+		ret = mxl111sf_i2c_start(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_i2c_bitbang_sendbyte(state,
+						    (msg->addr << 1) | 0x01);
+		if (mxl_fail(ret)) {
+			mxl111sf_i2c_stop(state);
+			goto fail;
+		}
+
+		for (i = 0; i < msg->len; i++) {
+			ret = mxl111sf_i2c_bitbang_recvbyte(state,
+							    &msg->buf[i]);
+			if (mxl_fail(ret)) {
+				mxl111sf_i2c_stop(state);
+				goto fail;
+			}
+
+			if (i < msg->len - 1)
+				mxl111sf_i2c_ack(state);
+		}
+
+		mxl111sf_i2c_nack(state);
+
+		ret = mxl111sf_i2c_stop(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+	} else {
+
+		ret = mxl111sf_i2c_start(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_i2c_bitbang_sendbyte(state,
+						    (msg->addr << 1) & 0xfe);
+		if (mxl_fail(ret)) {
+			mxl111sf_i2c_stop(state);
+			goto fail;
+		}
+
+		for (i = 0; i < msg->len; i++) {
+			ret = mxl111sf_i2c_bitbang_sendbyte(state,
+							    msg->buf[i]);
+			if (mxl_fail(ret)) {
+				mxl111sf_i2c_stop(state);
+				goto fail;
+			}
+		}
+
+		/* FIXME: we only want to do this on the last transaction */
+		mxl111sf_i2c_stop(state);
+	}
+fail:
+	return ret;
+}
+
+/* HW-I2C ----------------------------------------------------------------- */
+
+#define USB_WRITE_I2C_CMD     0x99
+#define USB_READ_I2C_CMD      0xdd
+#define USB_END_I2C_CMD       0xfe
+
+#define USB_WRITE_I2C_CMD_LEN   26
+#define USB_READ_I2C_CMD_LEN    24
+
+#define I2C_MUX_REG           0x30
+#define I2C_CONTROL_REG       0x00
+#define I2C_SLAVE_ADDR_REG    0x08
+#define I2C_DATA_REG          0x0c
+#define I2C_INT_STATUS_REG    0x10
+
+static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
+				  u8 index, u8 *wdata)
+{
+	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+				    &wdata[1], 25, NULL, 0);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
+				 u8 index, u8 *wdata, u8 *rdata)
+{
+	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+				    &wdata[1], 25, rdata, 24);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state)
+{
+	u8 status = 0;
+	u8 buf[26];
+
+	mxl_i2c_adv("()");
+
+	buf[0] = USB_READ_I2C_CMD;
+	buf[1] = 0x00;
+
+	buf[2] = I2C_INT_STATUS_REG;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+
+	buf[5] = USB_END_I2C_CMD;
+
+	mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+	if (buf[1] & 0x04)
+		status = 1;
+
+	return status;
+}
+
+static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state)
+{
+	u8 status = 0;
+	u8 buf[26];
+
+	mxl_i2c("()");
+
+	buf[0] = USB_READ_I2C_CMD;
+	buf[1] = 0x00;
+
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+
+	buf[5] = I2C_INT_STATUS_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+	buf[8] = USB_END_I2C_CMD;
+
+	mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+	if (0x08 == (buf[1] & 0x08))
+		status = 1;
+
+	if ((buf[5] & 0x02) == 0x02)
+		mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */
+
+	return status;
+}
+
+static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
+				  u8 count, u8 *rbuf)
+{
+	u8 i2c_w_data[26];
+	u8 i2c_r_data[24];
+	u8 i = 0;
+	u8 fifo_status = 0;
+	int status = 0;
+
+	mxl_i2c("read %d bytes", count);
+
+	while ((fifo_status == 0) && (i++ < 5))
+		fifo_status = mxl111sf_i2c_check_fifo(state);
+
+	i2c_w_data[0] = 0xDD;
+	i2c_w_data[1] = 0x00;
+
+	for (i = 2; i < 26; i++)
+		i2c_w_data[i] = 0xFE;
+
+	for (i = 0; i < count; i++) {
+		i2c_w_data[2+(i*3)] = 0x0C;
+		i2c_w_data[3+(i*3)] = 0x00;
+		i2c_w_data[4+(i*3)] = 0x00;
+	}
+
+	mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
+
+	/* Check for I2C NACK status */
+	if (mxl111sf_i2c_check_status(state) == 1) {
+		mxl_i2c("error!");
+	} else {
+		for (i = 0; i < count; i++) {
+			rbuf[i] = i2c_r_data[(i*3)+1];
+			mxl_i2c("%02x\t %02x",
+				i2c_r_data[(i*3)+1],
+				i2c_r_data[(i*3)+2]);
+		}
+
+		status = 1;
+	}
+
+	return status;
+}
+
+#define HWI2C400 1
+static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
+				    struct i2c_msg *msg)
+{
+	int i, k, ret = 0;
+	u16 index = 0;
+	u8 buf[26];
+	u8 i2c_r_data[24];
+	u16 block_len;
+	u16 left_over_len;
+	u8 rd_status[8];
+	u8 ret_status;
+	u8 readbuff[26];
+
+	mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d",
+		msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0,
+		(!(msg->flags & I2C_M_RD)) ? msg->len : 0);
+
+	for (index = 0; index < 26; index++)
+		buf[index] = USB_END_I2C_CMD;
+
+	/* command to indicate data payload is destined for I2C interface */
+	buf[0] = USB_WRITE_I2C_CMD;
+	buf[1] = 0x00;
+
+	/* enable I2C interface */
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x80;
+	buf[4] = 0x00;
+
+	/* enable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x81;
+	buf[7] = 0x00;
+
+	/* set Timeout register on I2C interface */
+	buf[8] = 0x14;
+	buf[9] = 0xff;
+	buf[10] = 0x00;
+#if 0
+	/* enable Interrupts on I2C interface */
+	buf[8] = 0x24;
+	buf[9] = 0xF7;
+	buf[10] = 0x00;
+#endif
+	buf[11] = 0x24;
+	buf[12] = 0xF7;
+	buf[13] = 0x00;
+
+	ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* write data on I2C bus */
+	if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) {
+		mxl_i2c("%d\t%02x", msg->len, msg->buf[0]);
+
+		/* control register on I2C interface to initialize I2C bus */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x5E;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		/* I2C Slave device Address */
+		buf[5] = I2C_SLAVE_ADDR_REG;
+		buf[6] = (msg->addr);
+		buf[7] = 0x00;
+		buf[8] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* check for slave device status */
+		if (mxl111sf_i2c_check_status(state) == 1) {
+			mxl_i2c("NACK writing slave address %02x",
+				msg->addr);
+			/* if NACK, stop I2C bus and exit */
+			buf[2] = I2C_CONTROL_REG;
+			buf[3] = 0x4E;
+			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+			ret = -EIO;
+			goto exit;
+		}
+
+		/* I2C interface can do I2C operations in block of 8 bytes of
+		   I2C data. calculation to figure out number of blocks of i2c
+		   data required to program */
+		block_len = (msg->len / 8);
+		left_over_len = (msg->len % 8);
+		index = 0;
+
+		mxl_i2c("block_len %d, left_over_len %d",
+			block_len, left_over_len);
+
+		for (index = 0; index < block_len; index++) {
+			for (i = 0; i < 8; i++) {
+				/* write data on I2C interface */
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = msg->buf[(index*8)+i];
+				buf[4+(i*3)] = 0x00;
+			}
+
+			ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK writing slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0x4E;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+		}
+
+		if (left_over_len) {
+			for (k = 0; k < 26; k++)
+				buf[k] = USB_END_I2C_CMD;
+
+			buf[0] = 0x99;
+			buf[1] = 0x00;
+
+			for (i = 0; i < left_over_len; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = msg->buf[(index*8)+i];
+				mxl_i2c("index = %d %d data %d",
+					index, i, msg->buf[(index*8)+i]);
+				buf[4+(i*3)] = 0x00;
+			}
+			ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK writing slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0x4E;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+		}
+
+		/* issue I2C STOP after write */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x4E;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+	}
+
+	/* read data from I2C bus */
+	if ((msg->flags & I2C_M_RD) && (msg->len > 0)) {
+		mxl_i2c("read buf len %d", msg->len);
+
+		/* command to indicate data payload is
+		   destined for I2C interface */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0xDF;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		/* I2C xfer length */
+		buf[5] = 0x14;
+		buf[6] = (msg->len & 0xFF);
+		buf[7] = 0;
+
+		/* I2C slave device Address */
+		buf[8] = I2C_SLAVE_ADDR_REG;
+		buf[9] = msg->addr;
+		buf[10] = 0x00;
+		buf[11] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* check for I2C NACK status */
+		if (mxl111sf_i2c_check_status(state) == 1) {
+			mxl_i2c("NACK reading slave address %02x",
+				msg->addr);
+
+			/* if NACK, stop I2C bus and exit */
+			buf[2] = I2C_CONTROL_REG;
+			buf[3] = 0xC7;
+			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+			ret = -EIO;
+			goto exit;
+		}
+
+		/* I2C interface can do I2C operations in block of 8 bytes of
+		   I2C data. calculation to figure out number of blocks of
+		   i2c data required to program */
+		block_len = ((msg->len) / 8);
+		left_over_len = ((msg->len) % 8);
+		index = 0;
+
+		mxl_i2c("block_len %d, left_over_len %d",
+			block_len, left_over_len);
+
+		/* command to read data from I2C interface */
+		buf[0] = USB_READ_I2C_CMD;
+		buf[1] = 0x00;
+
+		for (index = 0; index < block_len; index++) {
+			/* setup I2C read request packet on I2C interface */
+			for (i = 0; i < 8; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = 0x00;
+				buf[4+(i*3)] = 0x00;
+			}
+
+			ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK reading slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0xC7;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+			/* copy data from i2c data payload to read buffer */
+			for (i = 0; i < 8; i++) {
+				rd_status[i] = i2c_r_data[(i*3)+2];
+
+				if (rd_status[i] == 0x04) {
+					if (i < 7) {
+						mxl_i2c("i2c fifo empty!"
+							" @ %d", i);
+						msg->buf[(index*8)+i] =
+							i2c_r_data[(i*3)+1];
+						/* read again */
+						ret_status =
+							mxl111sf_i2c_readagain(
+								state, 8-(i+1),
+								readbuff);
+						if (ret_status == 1) {
+							for (k = 0;
+							     k < 8-(i+1);
+							     k++) {
+
+					msg->buf[(index*8)+(k+i+1)] =
+						readbuff[k];
+					mxl_i2c("read data: %02x\t %02x",
+						msg->buf[(index*8)+(k+i)],
+						(index*8)+(k+i));
+					mxl_i2c("read data: %02x\t %02x",
+						msg->buf[(index*8)+(k+i+1)],
+						readbuff[k]);
+
+							}
+							goto stop_copy;
+						} else {
+							mxl_i2c("readagain "
+								"ERROR!");
+						}
+					} else {
+						msg->buf[(index*8)+i] =
+							i2c_r_data[(i*3)+1];
+					}
+				} else {
+					msg->buf[(index*8)+i] =
+						i2c_r_data[(i*3)+1];
+				}
+			}
+stop_copy:
+			;
+
+		}
+
+		if (left_over_len) {
+			for (k = 0; k < 26; k++)
+				buf[k] = USB_END_I2C_CMD;
+
+			buf[0] = 0xDD;
+			buf[1] = 0x00;
+
+			for (i = 0; i < left_over_len; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = 0x00;
+				buf[4+(i*3)] = 0x00;
+			}
+			ret = mxl111sf_i2c_get_data(state, 0, buf,
+						    i2c_r_data);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK reading slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0xC7;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+			for (i = 0; i < left_over_len; i++) {
+				msg->buf[(block_len*8)+i] =
+					i2c_r_data[(i*3)+1];
+				mxl_i2c("read data: %02x\t %02x",
+					i2c_r_data[(i*3)+1],
+					i2c_r_data[(i*3)+2]);
+			}
+		}
+
+		/* indicate I2C interface to issue NACK
+		   after next I2C read op */
+		buf[0] = USB_WRITE_I2C_CMD;
+		buf[1] = 0x00;
+
+		/* control register */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x17;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		buf[5] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* control register */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0xC7;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+	}
+exit:
+	/* STOP and disable I2C MUX */
+	buf[0] = USB_WRITE_I2C_CMD;
+	buf[1] = 0x00;
+
+	/* de-initilize I2C BUS */
+	buf[5] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* Control Register */
+	buf[2] = I2C_CONTROL_REG;
+	buf[3] = 0xDF;
+	buf[4] = 0x03;
+
+	/* disable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+
+	/* de-initilize I2C BUS */
+	buf[8] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* disable I2C interface */
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x81;
+	buf[4] = 0x00;
+
+	/* disable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+
+	/* disable I2C interface */
+	buf[8] = I2C_MUX_REG;
+	buf[9] = 0x00;
+	buf[10] = 0x00;
+
+	buf[11] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+		      struct i2c_msg msg[], int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct mxl111sf_state *state = d->priv;
+	int hwi2c = (state->chip_rev > MXL111SF_V6);
+	int i, ret;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		ret = (hwi2c) ?
+			mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) :
+			mxl111sf_i2c_sw_xfer_msg(state, &msg[i]);
+		if (mxl_fail(ret)) {
+			mxl_debug_adv("failed with error %d on i2c "
+				      "transaction %d of %d, %sing %d bytes "
+				      "to/from 0x%02x", ret, i+1, num,
+				      (msg[i].flags & I2C_M_RD) ?
+				      "read" : "writ",
+				      msg[i].len, msg[i].addr);
+
+			break;
+		}
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return i == num ? num : -EREMOTEIO;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ *  mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DVB_USB_MXL111SF_I2C_H_
+#define _DVB_USB_MXL111SF_I2C_H_
+
+#include <linux/i2c.h>
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+		      struct i2c_msg msg[], int num);
+
+#endif /* _DVB_USB_MXL111SF_I2C_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,343 @@
+/*
+ *  mxl111sf-phy.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
+{
+	struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
+		{0x07, 0xff, 0x0c},
+		{0x58, 0xff, 0x9d},
+		{0x09, 0xff, 0x00},
+		{0x06, 0xff, 0x06},
+		{0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
+		{0x8d, 0x01, 0x01}, /* NEGATE_Q */
+		{0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
+		{0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
+		{0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
+		{0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
+		{0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
+		{0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
+		{0x88, 0xff, 0xf0}, /* INF_THD = 240 */
+		{0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
+		{0x00, 0xff, 0x01}, /* Change to page 1 */
+		{0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
+		{0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
+		{0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
+		{0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
+		{0x00, 0xff, 0x00}, /* Change to page 0 */
+		{0,    0,    0}
+	};
+
+	mxl_debug("()");
+
+	return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
+}
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
+{
+	int ret;
+	mxl_debug("()");
+
+	ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
+{
+	int ret;
+
+	mxl_debug("(%s)", MXL_SOC_MODE == mode ?
+		"MXL_SOC_MODE" : "MXL_TUNER_MODE");
+
+	/* set device mode */
+	ret = mxl111sf_write_reg(state, 0x03,
+				 MXL_SOC_MODE == mode ? 0x01 : 0x00);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg_mask(state,
+				      0x7d, 0x40, MXL_SOC_MODE == mode ?
+				      0x00 : /* enable impulse noise filter,
+						INF_BYP = 0 */
+				      0x40); /* disable impulse noise filter,
+						INF_BYP = 1 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	state->device_mode = mode;
+fail:
+	return ret;
+}
+
+/* power up tuner */
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
+{
+	mxl_debug("(%d)", onoff);
+
+	return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
+}
+
+int mxl111sf_disable_656_port(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
+}
+
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
+}
+
+/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+			    unsigned int parallel_serial,
+			    unsigned int msb_lsb_1st,
+			    unsigned int clock_phase,
+			    unsigned int mpeg_valid_pol,
+			    unsigned int mpeg_sync_pol)
+{
+	int ret;
+	u8 mode, tmp;
+
+	mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
+		  clock_phase, mpeg_valid_pol, mpeg_sync_pol);
+
+	/* Enable PIN MUX */
+	ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
+	mxl_fail(ret);
+
+	/* Configure MPEG Clock phase */
+	mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
+
+	if (clock_phase == TSIF_NORMAL)
+		mode &= ~V6_INVERTED_CLK_PHASE;
+	else
+		mode |= V6_INVERTED_CLK_PHASE;
+
+	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
+	mxl_fail(ret);
+
+	/* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
+	 * Get current configuration */
+	ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
+	mxl_fail(ret);
+
+	/* Data Input mode */
+	if (parallel_serial == TSIF_INPUT_PARALLEL) {
+		/* Disable serial mode */
+		mode &= ~V6_MPEG_IN_DATA_SERIAL;
+
+		/* Enable Parallel mode */
+		mode |= V6_MPEG_IN_DATA_PARALLEL;
+	} else {
+		/* Disable Parallel mode */
+		mode &= ~V6_MPEG_IN_DATA_PARALLEL;
+
+		/* Enable Serial Mode */
+		mode |= V6_MPEG_IN_DATA_SERIAL;
+
+		/* If serial interface is chosen, configure
+		   MSB or LSB order in transmission */
+		ret = mxl111sf_read_reg(state,
+					V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+					&tmp);
+		mxl_fail(ret);
+
+		if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
+			tmp |= V6_MPEG_SER_MSB_FIRST;
+		else
+			tmp &= ~V6_MPEG_SER_MSB_FIRST;
+
+		ret = mxl111sf_write_reg(state,
+					 V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+					 tmp);
+		mxl_fail(ret);
+	}
+
+	/* MPEG Sync polarity */
+	if (mpeg_sync_pol == TSIF_NORMAL)
+		mode &= ~V6_INVERTED_MPEG_SYNC;
+	else
+		mode |= V6_INVERTED_MPEG_SYNC;
+
+	/* MPEG Valid polarity */
+	if (mpeg_valid_pol == 0)
+		mode &= ~V6_INVERTED_MPEG_VALID;
+	else
+		mode |= V6_INVERTED_MPEG_VALID;
+
+	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
+{
+	static struct mxl111sf_reg_ctrl_info init_i2s[] = {
+		{0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
+		{0x15, 0x60, 0x60}, /* Enable I2S */
+		{0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
+				       Inverted 656 Clock, I2S_SOFT_RESET,
+				       0 : Normal operation, 1 : Reset State */
+#if 0
+		{0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
+#endif
+		{0x00, 0xff, 0x02}, /* Change to Control Page */
+		{0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
+		{0x00, 0xff, 0x00},
+		{0,    0,    0}
+	};
+	int ret;
+
+	mxl_debug("(0x%02x)", sample_size);
+
+	ret = mxl111sf_ctrl_program_regs(state, init_i2s);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
+{
+	static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
+		{0x15, 0x40, 0x00},
+		{0,    0,    0}
+	};
+
+	mxl_debug("()");
+
+	return mxl111sf_ctrl_program_regs(state, disable_i2s);
+}
+
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+			u8 msb_start_pos, u8 data_width)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
+
+	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	tmp &= 0xe0;
+	tmp |= msb_start_pos;
+	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	tmp &= 0xe0;
+	tmp |= data_width;
+	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
+{
+	u8 val;
+	int ret;
+
+	mxl_debug("(%d)", onoff);
+
+	ret = mxl111sf_write_reg(state, 0x00, 0x02);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (onoff)
+		val |= 0x04;
+	else
+		val &= ~0x04;
+
+	ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, 0x00, 0x00);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+			 u8 control_mode, u8 current_setting,
+			 u8 current_value, u8 hysteresis_value)
+{
+	int ret;
+	u8 val;
+	/* current value will be set for both automatic & manual IDAC control */
+	val = current_value;
+
+	if (control_mode == IDAC_MANUAL_CONTROL) {
+		/* enable manual control of IDAC */
+		val |= IDAC_MANUAL_CONTROL_BIT_MASK;
+
+		if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
+			/* enable current sinking in manual mode */
+			val |= IDAC_CURRENT_SINKING_BIT_MASK;
+		else
+			/* disable current sinking in manual mode */
+			val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
+	} else {
+		/* disable manual control of IDAC */
+		val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
+
+		/* set hysteresis value  reg: 0x0B<5:0> */
+		ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
+					 (hysteresis_value & 0x3F));
+		mxl_fail(ret);
+	}
+
+	ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,53 @@
+/*
+ *  mxl111sf-phy.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DVB_USB_MXL111SF_PHY_H_
+#define _DVB_USB_MXL111SF_PHY_H_
+
+#include "mxl111sf.h"
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state);
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode);
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff);
+int mxl111sf_disable_656_port(struct mxl111sf_state *state);
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state);
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state);
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+			    unsigned int parallel_serial,
+			    unsigned int msb_lsb_1st,
+			    unsigned int clock_phase,
+			    unsigned int mpeg_valid_pol,
+			    unsigned int mpeg_sync_pol);
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+			u8 msb_start_pos, u8 data_width);
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size);
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state);
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff);
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+			 u8 control_mode, u8 current_setting,
+			 u8 current_value, u8 hysteresis_value);
+
+#endif /* _DVB_USB_MXL111SF_PHY_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-reg.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,179 @@
+/*
+ *  mxl111sf-reg.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DVB_USB_MXL111SF_REG_H_
+#define _DVB_USB_MXL111SF_REG_H_
+
+#define CHIP_ID_REG                  0xFC
+#define TOP_CHIP_REV_ID_REG          0xFA
+
+#define V6_SNR_RB_LSB_REG            0x27
+#define V6_SNR_RB_MSB_REG            0x28
+
+#define V6_N_ACCUMULATE_REG          0x11
+#define V6_RS_AVG_ERRORS_LSB_REG     0x2C
+#define V6_RS_AVG_ERRORS_MSB_REG     0x2D
+
+#define V6_IRQ_STATUS_REG            0x24
+#define  IRQ_MASK_FEC_LOCK       0x10
+
+#define V6_SYNC_LOCK_REG             0x28
+#define SYNC_LOCK_MASK           0x10
+
+#define V6_RS_LOCK_DET_REG           0x28
+#define  RS_LOCK_DET_MASK        0x08
+
+#define V6_INITACQ_NODETECT_REG    0x20
+#define V6_FORCE_NFFT_CPSIZE_REG   0x20
+
+#define V6_CODE_RATE_TPS_REG       0x29
+#define V6_CODE_RATE_TPS_MASK      0x07
+
+
+#define V6_CP_LOCK_DET_REG        0x28
+#define V6_CP_LOCK_DET_MASK       0x04
+
+#define V6_TPS_HIERACHY_REG        0x29
+#define V6_TPS_HIERARCHY_INFO_MASK  0x40
+
+#define V6_MODORDER_TPS_REG        0x2A
+#define V6_PARAM_CONSTELLATION_MASK   0x30
+
+#define V6_MODE_TPS_REG            0x2A
+#define V6_PARAM_FFT_MODE_MASK        0x0C
+
+
+#define V6_CP_TPS_REG             0x29
+#define V6_PARAM_GI_MASK              0x30
+
+#define V6_TPS_LOCK_REG           0x2A
+#define V6_PARAM_TPS_LOCK_MASK        0x40
+
+#define V6_FEC_PER_COUNT_REG      0x2E
+#define V6_FEC_PER_SCALE_REG      0x2B
+#define V6_FEC_PER_SCALE_MASK        0x03
+#define V6_FEC_PER_CLR_REG        0x20
+#define V6_FEC_PER_CLR_MASK          0x01
+
+#define V6_PIN_MUX_MODE_REG       0x1B
+#define V6_ENABLE_PIN_MUX            0x1E
+
+#define V6_I2S_NUM_SAMPLES_REG    0x16
+
+#define V6_MPEG_IN_CLK_INV_REG    0x17
+#define V6_MPEG_IN_CTRL_REG       0x18
+
+#define V6_INVERTED_CLK_PHASE       0x20
+#define V6_MPEG_IN_DATA_PARALLEL    0x01
+#define V6_MPEG_IN_DATA_SERIAL      0x02
+
+#define V6_INVERTED_MPEG_SYNC       0x04
+#define V6_INVERTED_MPEG_VALID      0x08
+
+#define TSIF_INPUT_PARALLEL         0
+#define TSIF_INPUT_SERIAL           1
+#define TSIF_NORMAL                 0
+
+#define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG  0x19
+#define V6_MPEG_SER_MSB_FIRST                0x80
+#define MPEG_SER_MSB_FIRST_ENABLED        0x01
+
+#define V6_656_I2S_BUFF_STATUS_REG   0x2F
+#define V6_656_OVERFLOW_MASK_BIT         0x08
+#define V6_I2S_OVERFLOW_MASK_BIT         0x01
+
+#define V6_I2S_STREAM_START_BIT_REG  0x14
+#define V6_I2S_STREAM_END_BIT_REG    0x15
+#define I2S_RIGHT_JUSTIFIED     0
+#define I2S_LEFT_JUSTIFIED      1
+#define I2S_DATA_FORMAT         2
+
+#define V6_TUNER_LOOP_THRU_CONTROL_REG  0x09
+#define V6_ENABLE_LOOP_THRU               0x01
+
+#define TOTAL_NUM_IF_OUTPUT_FREQ       16
+
+#define TUNER_NORMAL_IF_SPECTRUM       0x0
+#define TUNER_INVERT_IF_SPECTRUM       0x10
+
+#define V6_TUNER_IF_SEL_REG              0x06
+#define V6_TUNER_IF_FCW_REG              0x3C
+#define V6_TUNER_IF_FCW_BYP_REG          0x3D
+#define V6_RF_LOCK_STATUS_REG            0x23
+
+#define NUM_DIG_TV_CHANNEL     1000
+
+#define V6_DIG_CLK_FREQ_SEL_REG  0x07
+#define V6_REF_SYNTH_INT_REG     0x5C
+#define V6_REF_SYNTH_REMAIN_REG  0x58
+#define V6_DIG_RFREFSELECT_REG   0x32
+#define V6_XTAL_CLK_OUT_GAIN_REG   0x31
+#define V6_TUNER_LOOP_THRU_CTRL_REG      0x09
+#define V6_DIG_XTAL_ENABLE_REG  0x06
+#define V6_DIG_XTAL_BIAS_REG  0x66
+#define V6_XTAL_CAP_REG    0x08
+
+#define V6_GPO_CTRL_REG     0x18
+#define MXL_GPO_0           0x00
+#define MXL_GPO_1           0x01
+#define V6_GPO_0_MASK       0x10
+#define V6_GPO_1_MASK       0x20
+
+#define V6_111SF_GPO_CTRL_REG     0x19
+#define MXL_111SF_GPO_1               0x00
+#define MXL_111SF_GPO_2               0x01
+#define MXL_111SF_GPO_3               0x02
+#define MXL_111SF_GPO_4               0x03
+#define MXL_111SF_GPO_5               0x04
+#define MXL_111SF_GPO_6               0x05
+#define MXL_111SF_GPO_7               0x06
+
+#define MXL_111SF_GPO_0_MASK          0x01
+#define MXL_111SF_GPO_1_MASK          0x02
+#define MXL_111SF_GPO_2_MASK          0x04
+#define MXL_111SF_GPO_3_MASK          0x08
+#define MXL_111SF_GPO_4_MASK          0x10
+#define MXL_111SF_GPO_5_MASK          0x20
+#define MXL_111SF_GPO_6_MASK          0x40
+
+#define V6_ATSC_CONFIG_REG  0x0A
+
+#define MXL_MODE_REG    0x03
+#define START_TUNE_REG  0x1C
+
+#define V6_IDAC_HYSTERESIS_REG    0x0B
+#define V6_IDAC_SETTINGS_REG      0x0C
+#define IDAC_MANUAL_CONTROL             1
+#define IDAC_CURRENT_SINKING_ENABLE     1
+#define IDAC_MANUAL_CONTROL_BIT_MASK      0x80
+#define IDAC_CURRENT_SINKING_BIT_MASK     0x40
+
+#define V8_SPI_MODE_REG  0xE9
+
+#define V6_DIG_RF_PWR_LSB_REG  0x46
+#define V6_DIG_RF_PWR_MSB_REG  0x47
+
+#endif /* _DVB_USB_MXL111SF_REG_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,476 @@
+/*
+ *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-tuner.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_tuner_debug;
+module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+	if (mxl111sf_tuner_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_tuner_state {
+	struct mxl111sf_state *mxl_state;
+
+	struct mxl111sf_tuner_config *cfg;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
+				   u8 addr, u8 *data)
+{
+	return (state->cfg->read_reg) ?
+		state->cfg->read_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
+				    u8 addr, u8 data)
+{
+	return (state->cfg->write_reg) ?
+		state->cfg->write_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	return (state->cfg->program_regs) ?
+		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+		-EINVAL;
+}
+
+static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
+					  int onoff)
+{
+	return (state->cfg->top_master_ctrl) ?
+		state->cfg->top_master_ctrl(state->mxl_state, onoff) :
+		-EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
+	{0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
+			       DIG_MODEINDEX, _A, _CSF, */
+	{0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
+	{0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
+	{0,    0,    0}
+};
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
+								  u8 bw)
+{
+	u8 filt_bw;
+
+	/* set channel bandwidth */
+	switch (bw) {
+	case 0: /* ATSC */
+		filt_bw = 25;
+		break;
+	case 1: /* QAM */
+		filt_bw = 69;
+		break;
+	case 6:
+		filt_bw = 21;
+		break;
+	case 7:
+		filt_bw = 42;
+		break;
+	case 8:
+		filt_bw = 63;
+		break;
+	default:
+		err("%s: invalid bandwidth setting!", __func__);
+		return NULL;
+	}
+
+	/* calculate RF channel */
+	freq /= 1000000;
+
+	freq *= 64;
+#if 0
+	/* do round */
+	freq += 0.5;
+#endif
+	/* set bandwidth */
+	mxl_phy_tune_rf[0].data = filt_bw;
+
+	/* set RF */
+	mxl_phy_tune_rf[1].data = (freq & 0xff);
+	mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
+
+	/* start tune */
+	return mxl_phy_tune_rf;
+}
+
+static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
+{
+	int ret;
+	u8 ctrl;
+#if 0
+	u16 iffcw;
+	u32 if_freq;
+#endif
+	mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
+		state->cfg->invert_spectrum, state->cfg->if_freq);
+
+	/* set IF polarity */
+	ctrl = state->cfg->invert_spectrum;
+
+	ctrl |= state->cfg->if_freq;
+
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+#if 0
+	if_freq /= 1000000;
+
+	/* do round */
+	if_freq += 0.5;
+
+	if (MXL_IF_LO == state->cfg->if_freq) {
+		ctrl = 0x08;
+		iffcw = (u16)(if_freq / (108 * 4096));
+	} else if (MXL_IF_HI == state->cfg->if_freq) {
+		ctrl = 0x08;
+		iffcw = (u16)(if_freq / (216 * 4096));
+	} else {
+		ctrl = 0;
+		iffcw = 0;
+	}
+
+	ctrl |= (iffcw >> 8);
+#endif
+	ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ctrl &= 0xf0;
+	ctrl |= 0x90;
+
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+#if 0
+	ctrl = iffcw & 0x00ff;
+#endif
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
+	int ret;
+	u8 mxl_mode;
+
+	mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
+
+	/* stop tune */
+	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* check device mode */
+	ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* Fill out registers for channel tune */
+	reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
+	if (!reg_ctrl_array)
+		return -EINVAL;
+
+	ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
+		/* IF tuner mode only */
+		mxl1x1sf_tuner_top_master_ctrl(state, 0);
+		mxl1x1sf_tuner_top_master_ctrl(state, 1);
+		mxl1x1sf_tuner_set_if_output_freq(state);
+	}
+
+	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (state->cfg->ant_hunt)
+		state->cfg->ant_hunt(fe);
+fail:
+	return ret;
+}
+
+static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
+					  int *rf_synth_lock,
+					  int *ref_synth_lock)
+{
+	int ret;
+	u8 data;
+
+	*rf_synth_lock = 0;
+	*ref_synth_lock = 0;
+
+	ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
+	*rf_synth_lock  = ((data & 0x0c) == 0x0c) ? 1 : 0;
+fail:
+	return ret;
+}
+
+#if 0
+static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
+					 int onoff)
+{
+	return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
+					onoff ? 1 : 0);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
+				     struct dvb_frontend_parameters *params)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+	u8 bw;
+
+	mxl_dbg("()");
+
+	if (fe->ops.info.type == FE_ATSC) {
+		switch (params->u.vsb.modulation) {
+		case VSB_8:
+		case VSB_16:
+			bw = 0; /* ATSC */
+			break;
+		case QAM_64:
+		case QAM_256:
+			bw = 1; /* US CABLE */
+			break;
+		default:
+			err("%s: modulation not set!", __func__);
+			return -EINVAL;
+		}
+	} else if (fe->ops.info.type == FE_OFDM) {
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			bw = 6;
+			break;
+		case BANDWIDTH_7_MHZ:
+			bw = 7;
+			break;
+		case BANDWIDTH_8_MHZ:
+			bw = 8;
+			break;
+		default:
+			err("%s: bandwidth not set!", __func__);
+			return -EINVAL;
+		}
+	} else {
+		err("%s: modulation type not supported!", __func__);
+		return -EINVAL;
+	}
+	ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
+	if (mxl_fail(ret))
+		goto fail;
+
+	state->frequency = params->frequency;
+	state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+		params->u.ofdm.bandwidth : 0;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+static int mxl111sf_tuner_init(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+
+	/* wake from standby handled by usb driver */
+
+	return ret;
+}
+
+static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+
+	/* enter standby mode handled by usb driver */
+
+	return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int rf_locked, ref_locked, ret;
+
+	*status = 0;
+
+	ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
+	if (mxl_fail(ret))
+		goto fail;
+	mxl_info("%s%s", rf_locked ? "rf locked " : "",
+		 ref_locked ? "ref locked" : "");
+
+	if ((rf_locked) || (ref_locked))
+		*status |= TUNER_STATUS_LOCKED;
+fail:
+	return ret;
+}
+
+static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	u8 val1, val2;
+	int ret;
+
+	*strength = 0;
+
+	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*strength = val1 | ((val2 & 0x07) << 8);
+fail:
+	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	*frequency = state->frequency;
+	return 0;
+}
+
+static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	*bandwidth = state->bandwidth;
+	return 0;
+}
+
+static int mxl111sf_tuner_release(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	mxl_dbg("()");
+	kfree(state);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
+	.info = {
+		.name = "MaxLinear MxL111SF",
+#if 0
+		.frequency_min  = ,
+		.frequency_max  = ,
+		.frequency_step = ,
+#endif
+	},
+#if 0
+	.init              = mxl111sf_tuner_init,
+	.sleep             = mxl111sf_tuner_sleep,
+#endif
+	.set_params        = mxl111sf_tuner_set_params,
+	.get_status        = mxl111sf_tuner_get_status,
+	.get_rf_strength   = mxl111sf_get_rf_strength,
+	.get_frequency     = mxl111sf_tuner_get_frequency,
+	.get_bandwidth     = mxl111sf_tuner_get_bandwidth,
+	.release           = mxl111sf_tuner_release,
+};
+
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_tuner_config *cfg)
+{
+	struct mxl111sf_tuner_state *state = NULL;
+
+	mxl_dbg("()");
+
+	state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->mxl_state = mxl_state;
+	state->cfg = cfg;
+
+	memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = state;
+	return fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,89 @@
+/*
+ *  mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MXL111SF_TUNER_H__
+#define __MXL111SF_TUNER_H__
+
+#include "dvb_frontend.h"
+
+#include "mxl111sf.h"
+
+enum mxl_if_freq {
+#if 0
+	MXL_IF_LO    = 0x00, /* other IF < 9MHz */
+#endif
+	MXL_IF_4_0   = 0x01, /* 4.0   MHz */
+	MXL_IF_4_5   = 0x02, /* 4.5   MHz */
+	MXL_IF_4_57  = 0x03, /* 4.57  MHz */
+	MXL_IF_5_0   = 0x04, /* 5.0   MHz */
+	MXL_IF_5_38  = 0x05, /* 5.38  MHz */
+	MXL_IF_6_0   = 0x06, /* 6.0   MHz */
+	MXL_IF_6_28  = 0x07, /* 6.28  MHz */
+	MXL_IF_7_2   = 0x08, /* 7.2   MHz */
+	MXL_IF_35_25 = 0x09, /* 35.25 MHz */
+	MXL_IF_36    = 0x0a, /* 36    MHz */
+	MXL_IF_36_15 = 0x0b, /* 36.15 MHz */
+	MXL_IF_44    = 0x0c, /* 44    MHz */
+#if 0
+	MXL_IF_HI    = 0x0f, /* other IF > 35 MHz and < 45 MHz */
+#endif
+};
+
+struct mxl111sf_tuner_config {
+	enum mxl_if_freq if_freq;
+	unsigned int invert_spectrum:1;
+
+	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+	int (*program_regs)(struct mxl111sf_state *state,
+			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+	int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff);
+	int (*ant_hunt)(struct dvb_frontend *fe);
+};
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_tuner_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state
+					   struct mxl111sf_tuner_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* __MXL111SF_TUNER_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2013-05-02 01:34:38.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2013-05-01 23:42:45.000000000 -0400
@@ -166,6 +166,8 @@ static struct dvb_usb_device_properties
 	.num_adapters     = 1,
 	.adapter          = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 
@@ -186,7 +188,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/opera1.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/opera1.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/opera1.c	2013-05-02 01:34:40.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/opera1.c	2013-05-01 23:42:47.000000000 -0400
@@ -263,10 +263,10 @@ static struct stv0299_config opera1_stv0
 
 static int opera1_frontend_attach(struct dvb_usb_adapter *d)
 {
-	if ((d->fe =
-	     dvb_attach(stv0299_attach, &opera1_stv0299_config,
-			&d->dev->i2c_adap)) != NULL) {
-		d->fe->ops.set_voltage = opera1_set_voltage;
+	d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
+				      &d->dev->i2c_adap);
+	if ((d->fe_adap[0].fe) != NULL) {
+		d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
 		return 0;
 	}
 	info("not attached stv0299");
@@ -276,7 +276,7 @@ static int opera1_frontend_attach(struct
 static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	dvb_attach(
-		dvb_pll_attach, adap->fe, 0xc0>>1,
+		dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
 		&adap->dev->i2c_adap, DVB_PLL_OPERA1
 	);
 	return 0;
@@ -516,6 +516,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = opera1_frontend_attach,
 			.streaming_ctrl = opera1_streaming_ctrl,
 			.tuner_attach = opera1_tuner_attach,
@@ -535,6 +537,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/pctv452e.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/pctv452e.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/pctv452e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/pctv452e.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1079 @@
+/*
+ * PCTV 452e DVB driver
+ *
+ * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
+ *
+ * TT connect S2-3650-CI Common Interface support, MAC readout
+ * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
+ *
+ * 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.
+ */
+
+/* dvb usb framework */
+#define DVB_USB_LOG_PREFIX "pctv452e"
+#include "dvb-usb.h"
+
+/* Demodulator */
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+/* Tuner */
+#include "stb6100.h"
+#include "stb6100_cfg.h"
+/* FE Power */
+#include "lnbp22.h"
+
+#include "dvb_ca_en50221.h"
+#include "ttpci-eeprom.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define ISOC_INTERFACE_ALTERNATIVE 3
+
+#define SYNC_BYTE_OUT 0xaa
+#define SYNC_BYTE_IN  0x55
+
+/* guessed: (copied from ttusb-budget) */
+#define PCTV_CMD_RESET 0x15
+/* command to poll IR receiver */
+#define PCTV_CMD_IR    0x1b
+/* command to send I2C  */
+#define PCTV_CMD_I2C   0x31
+
+#define I2C_ADDR_STB0899 (0xd0 >> 1)
+#define I2C_ADDR_STB6100 (0xc0 >> 1)
+#define I2C_ADDR_LNBP22  (0x10 >> 1)
+#define I2C_ADDR_24C16   (0xa0 >> 1)
+#define I2C_ADDR_24C64   (0xa2 >> 1)
+
+
+/* pctv452e sends us this amount of data for each issued usb-command */
+#define PCTV_ANSWER_LEN 64
+/* Wait up to 1000ms for device  */
+#define PCTV_TIMEOUT 1000
+
+
+#define PCTV_LED_GPIO   STB0899_GPIO01
+#define PCTV_LED_GREEN  0x82
+#define PCTV_LED_ORANGE 0x02
+
+#define ci_dbg(format, arg...)				\
+do {							\
+	if (0)						\
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX	\
+			": " format "\n" , ## arg);	\
+} while (0)
+
+enum {
+	TT3650_CMD_CI_TEST = 0x40,
+	TT3650_CMD_CI_RD_CTRL,
+	TT3650_CMD_CI_WR_CTRL,
+	TT3650_CMD_CI_RD_ATTR,
+	TT3650_CMD_CI_WR_ATTR,
+	TT3650_CMD_CI_RESET,
+	TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
+
+static struct stb0899_postproc pctv45e_postproc[] = {
+	{ PCTV_LED_GPIO, STB0899_GPIOPULLUP },
+	{ 0, 0 }
+};
+
+/*
+ * stores all private variables for communication with the PCTV452e DVB-S2
+ */
+struct pctv452e_state {
+	struct dvb_ca_en50221 ca;
+	struct mutex ca_mutex;
+
+	u8 c;	   /* transaction counter, wraps around...  */
+	u8 initialized; /* set to 1 if 0x15 has been sent */
+	u16 last_rc_key;
+};
+
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
+			 unsigned int write_len, unsigned int read_len)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[64];
+	u8 id;
+	unsigned int rlen;
+	int ret;
+
+	BUG_ON(NULL == data && 0 != (write_len | read_len));
+	BUG_ON(write_len > 64 - 4);
+	BUG_ON(read_len > 64 - 4);
+
+	id = state->c++;
+
+	buf[0] = SYNC_BYTE_OUT;
+	buf[1] = id;
+	buf[2] = cmd;
+	buf[3] = write_len;
+
+	memcpy(buf + 4, data, write_len);
+
+	rlen = (read_len > 0) ? 64 : 0;
+	ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
+				  buf, rlen, /* delay_ms */ 0);
+	if (0 != ret)
+		goto failed;
+
+	ret = -EIO;
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+		goto failed;
+
+	memcpy(data, buf + 4, read_len);
+
+	return 0;
+
+failed:
+	err("CI error %d; %02X %02X %02X -> %02X %02X %02X.",
+	     ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]);
+
+	return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
+				u8 cmd, u8 *data, unsigned int write_len,
+				unsigned int read_len)
+{
+	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	int ret;
+
+	mutex_lock(&state->ca_mutex);
+	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
+				 int slot, int address)
+{
+	u8 buf[3];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+	ci_dbg("%s %04x -> %d 0x%02x",
+		__func__, address, ret, buf[2]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
+				 int slot, int address, u8 value)
+{
+	u8 buf[3];
+
+	ci_dbg("%s %d 0x%04x 0x%02x",
+		__func__, slot, address, value);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+	buf[2] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 u8			address)
+{
+	u8 buf[2];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = address & 3;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+	ci_dbg("%s 0x%02x -> %d 0x%02x",
+		__func__, address, ret, buf[1]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 u8			address,
+				 u8			value)
+{
+	u8 buf[2];
+
+	ci_dbg("%s %d 0x%02x 0x%02x",
+		__func__, slot, address, value);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = address;
+	buf[1] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 int			enable)
+{
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%s %d %d", __func__, slot, enable);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	enable = !!enable;
+	buf[0] = enable;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	if (enable != buf[0]) {
+		err("CI not %sabled.", enable ? "en" : "dis");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, /* enable */ 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, /* enable */ 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%s %d", __func__, slot);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = 0;
+
+	mutex_lock(&state->ca_mutex);
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (0 != ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 1;
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (0 != ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 0; /* FTA */
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+ failed:
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 int			open)
+{
+	u8 buf[1];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+	if (0 != ret)
+		return ret;
+
+	if (1 == buf[0])
+		return DVB_CA_EN50221_POLL_CAM_PRESENT |
+			DVB_CA_EN50221_POLL_CAM_READY;
+
+	return 0;
+
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+	struct pctv452e_state *state;
+
+	ci_dbg("%s", __func__);
+
+	if (NULL == d)
+		return;
+
+	state = (struct pctv452e_state *)d->priv;
+	if (NULL == state)
+		return;
+
+	if (NULL == state->ca.data)
+		return;
+
+	/* Error ignored. */
+	tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
+
+	dvb_ca_en50221_release(&state->ca);
+
+	memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+	struct dvb_usb_device *d = a->dev;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	int ret;
+
+	ci_dbg("%s", __func__);
+
+	mutex_init(&state->ca_mutex);
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+	state->ca.read_cam_control = tt3650_ci_read_cam_control;
+	state->ca.write_cam_control = tt3650_ci_write_cam_control;
+	state->ca.slot_reset = tt3650_ci_slot_reset;
+	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+	state->ca.data = d;
+
+	ret = dvb_ca_en50221_init(&a->dvb_adap,
+				   &state->ca,
+				   /* flags */ 0,
+				   /* n_slots */ 1);
+	if (0 != ret) {
+		err("Cannot initialize CI: Error %d.", ret);
+		memset(&state->ca, 0, sizeof(state->ca));
+		return ret;
+	}
+
+	info("CI initialized.");
+
+	return 0;
+}
+
+#define CMD_BUFFER_SIZE 0x28
+static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
+				const u8 *snd_buf, u8 snd_len,
+				u8 *rcv_buf, u8 rcv_len)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[64];
+	u8 id;
+	int ret;
+
+	id = state->c++;
+
+	ret = -EINVAL;
+	if (snd_len > 64 - 7 || rcv_len > 64 - 7)
+		goto failed;
+
+	buf[0] = SYNC_BYTE_OUT;
+	buf[1] = id;
+	buf[2] = PCTV_CMD_I2C;
+	buf[3] = snd_len + 3;
+	buf[4] = addr << 1;
+	buf[5] = snd_len;
+	buf[6] = rcv_len;
+
+	memcpy(buf + 7, snd_buf, snd_len);
+
+	ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
+				  buf, /* rcv_len */ 64,
+				  /* delay_ms */ 0);
+	if (ret < 0)
+		goto failed;
+
+	/* TT USB protocol error. */
+	ret = -EIO;
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+		goto failed;
+
+	/* I2C device didn't respond as expected. */
+	ret = -EREMOTEIO;
+	if (buf[5] < snd_len || buf[6] < rcv_len)
+		goto failed;
+
+	memcpy(rcv_buf, buf + 7, rcv_len);
+
+	return rcv_len;
+
+failed:
+	err("I2C error %d; %02X %02X  %02X %02X %02X -> "
+	     "%02X %02X  %02X %02X %02X.",
+	     ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
+	     buf[0], buf[1], buf[4], buf[5], buf[6]);
+
+	return ret;
+}
+
+static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
+				int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adapter);
+	int i;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
+		int ret;
+
+		if (msg[i].flags & I2C_M_RD) {
+			addr = msg[i].addr;
+			snd_buf = NULL;
+			snd_len = 0;
+			rcv_buf = msg[i].buf;
+			rcv_len = msg[i].len;
+		} else {
+			addr = msg[i].addr;
+			snd_buf = msg[i].buf;
+			snd_len = msg[i].len;
+			rcv_buf = NULL;
+			rcv_len = 0;
+		}
+
+		ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf,
+					rcv_len);
+		if (ret < rcv_len)
+			break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return i;
+}
+
+static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
+	u8 rx[PCTV_ANSWER_LEN];
+	int ret;
+
+	info("%s: %d\n", __func__, i);
+
+	if (!i)
+		return 0;
+
+	if (state->initialized)
+		return 0;
+
+	/* hmm where shoud this should go? */
+	ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
+	if (ret != 0)
+		info("%s: Warning set interface returned: %d\n",
+			__func__, ret);
+
+	/* this is a one-time initialization, dont know where to put */
+	b0[1] = state->c++;
+	/* reset board */
+	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+	if (ret)
+		return ret;
+
+	b0[1] = state->c++;
+	b0[4] = 1;
+	/* reset board (again?) */
+	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+	if (ret)
+		return ret;
+
+	state->initialized = 1;
+
+	return 0;
+}
+
+static int pctv452e_rc_query(struct dvb_usb_device *d)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 b[CMD_BUFFER_SIZE];
+	u8 rx[PCTV_ANSWER_LEN];
+	int ret, i;
+	u8 id = state->c++;
+
+	/* prepare command header  */
+	b[0] = SYNC_BYTE_OUT;
+	b[1] = id;
+	b[2] = PCTV_CMD_IR;
+	b[3] = 0;
+
+	/* send ir request */
+	ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
+	if (ret != 0)
+		return ret;
+
+	if (debug > 3) {
+		info("%s: read: %2d: %02x %02x %02x: ", __func__,
+				ret, rx[0], rx[1], rx[2]);
+		for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
+			info(" %02x", rx[i+3]);
+
+		info("\n");
+	}
+
+	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
+		/* got a "press" event */
+		state->last_rc_key = (rx[7] << 8) | rx[6];
+		if (debug > 2)
+			info("%s: cmd=0x%02x sys=0x%02x\n",
+				__func__, rx[6], rx[7]);
+
+		rc_keydown(d->rc_dev, state->last_rc_key, 0);
+	} else if (state->last_rc_key) {
+		rc_keyup(d->rc_dev);
+		state->last_rc_key = 0;
+	}
+
+	return 0;
+}
+
+static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+	const u8 mem_addr[] = { 0x1f, 0xcc };
+	u8 encoded_mac[20];
+	int ret;
+
+	ret = -EAGAIN;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		goto failed;
+
+	ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16,
+				mem_addr + 1, /* snd_len */ 1,
+				encoded_mac, /* rcv_len */ 20);
+	if (-EREMOTEIO == ret)
+		/* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a
+		   byte write if /WC is low. */
+		ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64,
+					mem_addr, 2,
+					encoded_mac, 20);
+
+	mutex_unlock(&d->i2c_mutex);
+
+	if (20 != ret)
+		goto failed;
+
+	ret = ttpci_eeprom_decode_mac(mac, encoded_mac);
+	if (0 != ret)
+		goto failed;
+
+	return 0;
+
+failed:
+	memset(mac, 0, 6);
+
+	return ret;
+}
+
+static const struct stb0899_s1_reg pctv452e_init_dev[] = {
+	{ STB0899_DISCNTRL1,	0x26 },
+	{ STB0899_DISCNTRL2,	0x80 },
+	{ STB0899_DISRX_ST0,	0x04 },
+	{ STB0899_DISRX_ST1,	0x20 },
+	{ STB0899_DISPARITY,	0x00 },
+	{ STB0899_DISFIFO,	0x00 },
+	{ STB0899_DISF22,	0x99 },
+	{ STB0899_DISF22RX,	0x85 }, /* 0xa8 */
+	{ STB0899_ACRPRESC,	0x11 },
+	{ STB0899_ACRDIV1,	0x0a },
+	{ STB0899_ACRDIV2,	0x05 },
+	{ STB0899_DACR1	,	0x00 },
+	{ STB0899_DACR2	,	0x00 },
+	{ STB0899_OUTCFG,	0x00 },
+	{ STB0899_MODECFG,	0x00 }, /* Inversion */
+	{ STB0899_IRQMSK_3,	0xf3 },
+	{ STB0899_IRQMSK_2,	0xfc },
+	{ STB0899_IRQMSK_1,	0xff },
+	{ STB0899_IRQMSK_0,	0xff },
+	{ STB0899_I2CCFG,	0x88 },
+	{ STB0899_I2CRPT,	0x58 },
+	{ STB0899_GPIO00CFG,	0x82 },
+	{ STB0899_GPIO01CFG,	0x82 }, /* LED: 0x02 green, 0x82 orange */
+	{ STB0899_GPIO02CFG,	0x82 },
+	{ STB0899_GPIO03CFG,	0x82 },
+	{ STB0899_GPIO04CFG,	0x82 },
+	{ STB0899_GPIO05CFG,	0x82 },
+	{ STB0899_GPIO06CFG,	0x82 },
+	{ STB0899_GPIO07CFG,	0x82 },
+	{ STB0899_GPIO08CFG,	0x82 },
+	{ STB0899_GPIO09CFG,	0x82 },
+	{ STB0899_GPIO10CFG,	0x82 },
+	{ STB0899_GPIO11CFG,	0x82 },
+	{ STB0899_GPIO12CFG,	0x82 },
+	{ STB0899_GPIO13CFG,	0x82 },
+	{ STB0899_GPIO14CFG,	0x82 },
+	{ STB0899_GPIO15CFG,	0x82 },
+	{ STB0899_GPIO16CFG,	0x82 },
+	{ STB0899_GPIO17CFG,	0x82 },
+	{ STB0899_GPIO18CFG,	0x82 },
+	{ STB0899_GPIO19CFG,	0x82 },
+	{ STB0899_GPIO20CFG,	0x82 },
+	{ STB0899_SDATCFG,	0xb8 },
+	{ STB0899_SCLTCFG,	0xba },
+	{ STB0899_AGCRFCFG,	0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */
+	{ STB0899_GPIO22,	0x82 },
+	{ STB0899_GPIO21,	0x91 },
+	{ STB0899_DIRCLKCFG,	0x82 },
+	{ STB0899_CLKOUT27CFG,	0x7e },
+	{ STB0899_STDBYCFG,	0x82 },
+	{ STB0899_CS0CFG,	0x82 },
+	{ STB0899_CS1CFG,	0x82 },
+	{ STB0899_DISEQCOCFG,	0x20 },
+	{ STB0899_NCOARSE,	0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */
+	{ STB0899_SYNTCTRL,	0x00 }, /* 0x00 CLKI, 0x02 XTALI */
+	{ STB0899_FILTCTRL,	0x00 },
+	{ STB0899_SYSCTRL,	0x00 },
+	{ STB0899_STOPCLK1,	0x20 }, /* orig: 0x00 budget-ci: 0x20 */
+	{ STB0899_STOPCLK2,	0x00 },
+	{ STB0899_INTBUFCTRL,	0x0a },
+	{ STB0899_AGC2I1,	0x00 },
+	{ STB0899_AGC2I2,	0x00 },
+	{ STB0899_AGCIQIN,	0x00 },
+	{ STB0899_TSTRES,	0x40 }, /* rjkm */
+	{ 0xffff,		0xff },
+};
+
+static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = {
+	{ STB0899_DEMOD,	0x00 },
+	{ STB0899_RCOMPC,	0xc9 },
+	{ STB0899_AGC1CN,	0x01 },
+	{ STB0899_AGC1REF,	0x10 },
+	{ STB0899_RTC,		0x23 },
+	{ STB0899_TMGCFG,	0x4e },
+	{ STB0899_AGC2REF,	0x34 },
+	{ STB0899_TLSR,		0x84 },
+	{ STB0899_CFD,		0xf7 },
+	{ STB0899_ACLC,		0x87 },
+	{ STB0899_BCLC,		0x94 },
+	{ STB0899_EQON,		0x41 },
+	{ STB0899_LDT,		0xf1 },
+	{ STB0899_LDT2,		0xe3 },
+	{ STB0899_EQUALREF,	0xb4 },
+	{ STB0899_TMGRAMP,	0x10 },
+	{ STB0899_TMGTHD,	0x30 },
+	{ STB0899_IDCCOMP,	0xfd },
+	{ STB0899_QDCCOMP,	0xff },
+	{ STB0899_POWERI,	0x0c },
+	{ STB0899_POWERQ,	0x0f },
+	{ STB0899_RCOMP,	0x6c },
+	{ STB0899_AGCIQIN,	0x80 },
+	{ STB0899_AGC2I1,	0x06 },
+	{ STB0899_AGC2I2,	0x00 },
+	{ STB0899_TLIR,		0x30 },
+	{ STB0899_RTF,		0x7f },
+	{ STB0899_DSTATUS,	0x00 },
+	{ STB0899_LDI,		0xbc },
+	{ STB0899_CFRM,		0xea },
+	{ STB0899_CFRL,		0x31 },
+	{ STB0899_NIRM,		0x2b },
+	{ STB0899_NIRL,		0x80 },
+	{ STB0899_ISYMB,	0x1d },
+	{ STB0899_QSYMB,	0xa6 },
+	{ STB0899_SFRH,		0x2f },
+	{ STB0899_SFRM,		0x68 },
+	{ STB0899_SFRL,		0x40 },
+	{ STB0899_SFRUPH,	0x2f },
+	{ STB0899_SFRUPM,	0x68 },
+	{ STB0899_SFRUPL,	0x40 },
+	{ STB0899_EQUAI1,	0x02 },
+	{ STB0899_EQUAQ1,	0xff },
+	{ STB0899_EQUAI2,	0x04 },
+	{ STB0899_EQUAQ2,	0x05 },
+	{ STB0899_EQUAI3,	0x02 },
+	{ STB0899_EQUAQ3,	0xfd },
+	{ STB0899_EQUAI4,	0x03 },
+	{ STB0899_EQUAQ4,	0x07 },
+	{ STB0899_EQUAI5,	0x08 },
+	{ STB0899_EQUAQ5,	0xf5 },
+	{ STB0899_DSTATUS2,	0x00 },
+	{ STB0899_VSTATUS,	0x00 },
+	{ STB0899_VERROR,	0x86 },
+	{ STB0899_IQSWAP,	0x2a },
+	{ STB0899_ECNT1M,	0x00 },
+	{ STB0899_ECNT1L,	0x00 },
+	{ STB0899_ECNT2M,	0x00 },
+	{ STB0899_ECNT2L,	0x00 },
+	{ STB0899_ECNT3M,	0x0a },
+	{ STB0899_ECNT3L,	0xad },
+	{ STB0899_FECAUTO1,	0x06 },
+	{ STB0899_FECM,		0x01 },
+	{ STB0899_VTH12,	0xb0 },
+	{ STB0899_VTH23,	0x7a },
+	{ STB0899_VTH34,	0x58 },
+	{ STB0899_VTH56,	0x38 },
+	{ STB0899_VTH67,	0x34 },
+	{ STB0899_VTH78,	0x24 },
+	{ STB0899_PRVIT,	0xff },
+	{ STB0899_VITSYNC,	0x19 },
+	{ STB0899_RSULC,	0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC,	0x42 },
+	{ STB0899_RSLLC,	0x41 },
+	{ STB0899_TSLPL,	0x12 },
+	{ STB0899_TSCFGH,	0x0c },
+	{ STB0899_TSCFGM,	0x00 },
+	{ STB0899_TSCFGL,	0x00 },
+	{ STB0899_TSOUT,	0x69 }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL,	0x00 },
+	{ STB0899_TSINHDELH,	0x02 },
+	{ STB0899_TSINHDELM,	0x00 },
+	{ STB0899_TSINHDELL,	0x00 },
+	{ STB0899_TSLLSTKM,	0x1b },
+	{ STB0899_TSLLSTKL,	0xb3 },
+	{ STB0899_TSULSTKM,	0x00 },
+	{ STB0899_TSULSTKL,	0x00 },
+	{ STB0899_PCKLENUL,	0xbc },
+	{ STB0899_PCKLENLL,	0xcc },
+	{ STB0899_RSPCKLEN,	0xbd },
+	{ STB0899_TSSTATUS,	0x90 },
+	{ STB0899_ERRCTRL1,	0xb6 },
+	{ STB0899_ERRCTRL2,	0x95 },
+	{ STB0899_ERRCTRL3,	0x8d },
+	{ STB0899_DMONMSK1,	0x27 },
+	{ STB0899_DMONMSK0,	0x03 },
+	{ STB0899_DEMAPVIT,	0x5c },
+	{ STB0899_PLPARM,	0x19 },
+	{ STB0899_PDELCTRL,	0x48 },
+	{ STB0899_PDELCTRL2,	0x00 },
+	{ STB0899_BBHCTRL1,	0x00 },
+	{ STB0899_BBHCTRL2,	0x00 },
+	{ STB0899_HYSTTHRESH,	0x77 },
+	{ STB0899_MATCSTM,	0x00 },
+	{ STB0899_MATCSTL,	0x00 },
+	{ STB0899_UPLCSTM,	0x00 },
+	{ STB0899_UPLCSTL,	0x00 },
+	{ STB0899_DFLCSTM,	0x00 },
+	{ STB0899_DFLCSTL,	0x00 },
+	{ STB0899_SYNCCST,	0x00 },
+	{ STB0899_SYNCDCSTM,	0x00 },
+	{ STB0899_SYNCDCSTL,	0x00 },
+	{ STB0899_ISI_ENTRY,	0x00 },
+	{ STB0899_ISI_BIT_EN,	0x00 },
+	{ STB0899_MATSTRM,	0xf0 },
+	{ STB0899_MATSTRL,	0x02 },
+	{ STB0899_UPLSTRM,	0x45 },
+	{ STB0899_UPLSTRL,	0x60 },
+	{ STB0899_DFLSTRM,	0xe3 },
+	{ STB0899_DFLSTRL,	0x00 },
+	{ STB0899_SYNCSTR,	0x47 },
+	{ STB0899_SYNCDSTRM,	0x05 },
+	{ STB0899_SYNCDSTRL,	0x18 },
+	{ STB0899_CFGPDELSTATUS1, 0x19 },
+	{ STB0899_CFGPDELSTATUS2, 0x2b },
+	{ STB0899_BBFERRORM,	0x00 },
+	{ STB0899_BBFERRORL,	0x01 },
+	{ STB0899_UPKTERRORM,	0x00 },
+	{ STB0899_UPKTERRORL,	0x00 },
+	{ 0xffff,		0xff },
+};
+
+static struct stb0899_config stb0899_config = {
+	.init_dev	= pctv452e_init_dev,
+	.init_s2_demod	= stb0899_s2_init_2,
+	.init_s1_demod	= pctv452e_init_s1_demod,
+	.init_s2_fec	= stb0899_s2_init_4,
+	.init_tst	= stb0899_s1_init_5,
+
+	.demod_address   = I2C_ADDR_STB0899, /* I2C Address */
+	.block_sync_mode = STB0899_SYNC_FORCED, /* ? */
+
+	.xtal_freq       = 27000000,	 /* Assume Hz ? */
+	.inversion       = IQ_SWAP_ON,       /* ? */
+
+	.lo_clk	  = 76500000,
+	.hi_clk	  = 99000000,
+
+	.ts_output_mode  = 0,	/* Use parallel mode */
+	.clock_polarity  = 0,
+	.data_clk_parity = 0,
+	.fec_mode	= 0,
+
+	.esno_ave	    = STB0899_DVBS2_ESNO_AVE,
+	.esno_quant	  = STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse     = STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine       = STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold      = STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq   = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof   = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout  = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits	  = STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits	  = STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter	 = STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= stb6100_get_frequency,
+	.tuner_set_frequency	= stb6100_set_frequency,
+	.tuner_set_bandwidth	= stb6100_set_bandwidth,
+	.tuner_get_bandwidth	= stb6100_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL,
+
+	/* helper for switching LED green/orange */
+	.postproc = pctv45e_postproc
+};
+
+static struct stb6100_config stb6100_config = {
+	.tuner_address = I2C_ADDR_STB6100,
+	.refclock      = 27000000
+};
+
+
+static struct i2c_algorithm pctv452e_i2c_algo = {
+	.master_xfer   = pctv452e_i2c_xfer,
+	.functionality = pctv452e_i2c_func
+};
+
+static int pctv452e_frontend_attach(struct dvb_usb_adapter *a)
+{
+	struct usb_device_id *id;
+
+	a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config,
+						&a->dev->i2c_adap);
+	if (!a->fe_adap[0].fe)
+		return -ENODEV;
+	if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe,
+					&a->dev->i2c_adap)) == 0)
+		err("Cannot attach lnbp22\n");
+
+	id = a->dev->desc->warm_ids[0];
+	if (USB_VID_TECHNOTREND == id->idVendor
+	    && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct)
+		/* Error ignored. */
+		tt3650_ci_init(a);
+
+	return 0;
+}
+
+static int pctv452e_tuner_attach(struct dvb_usb_adapter *a)
+{
+	if (!a->fe_adap[0].fe)
+		return -ENODEV;
+	if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config,
+					&a->dev->i2c_adap) == 0) {
+		err("%s failed\n", __func__);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct usb_device_id pctv452e_usb_table[] = {
+	{USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)},
+	{USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)},
+	{USB_DEVICE(USB_VID_TECHNOTREND,
+				USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)},
+	{}
+};
+MODULE_DEVICE_TABLE(usb, pctv452e_usb_table);
+
+static struct dvb_usb_device_properties pctv452e_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+	.usb_ctrl = DEVICE_SPECIFIC,
+
+	.size_of_priv     = sizeof(struct pctv452e_state),
+
+	.power_ctrl       = pctv452e_power_ctrl,
+
+	.rc.core = {
+		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
+		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.rc_query	= pctv452e_rc_query,
+		.rc_interval	= 100,
+	},
+
+	.num_adapters     = 1,
+	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+			.frontend_attach  = pctv452e_frontend_attach,
+			.tuner_attach     = pctv452e_tuner_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type     = USB_ISOC,
+				.count    = 4,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize    = 940,
+						.interval     = 1
+					}
+				}
+			},
+		} },
+	} },
+
+	.i2c_algo = &pctv452e_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "PCTV HDTV USB",
+		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
+		  .warm_ids = { &pctv452e_usb_table[0], NULL }
+		},
+		{ 0 },
+	}
+};
+
+static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+	.usb_ctrl = DEVICE_SPECIFIC,
+
+	.size_of_priv		= sizeof(struct pctv452e_state),
+
+	.power_ctrl		= pctv452e_power_ctrl,
+	.read_mac_address	= pctv452e_read_mac_address,
+
+	.rc.core = {
+		.rc_codes	= RC_MAP_TT_1500,
+		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.rc_query	= pctv452e_rc_query,
+		.rc_interval	= 100,
+	},
+
+	.num_adapters		= 1,
+	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+			.frontend_attach = pctv452e_frontend_attach,
+			.tuner_attach = pctv452e_tuner_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_ISOC,
+				.count = 7,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize = 940,
+						.interval = 1
+					}
+				}
+			},
+
+		} },
+	} },
+
+	.i2c_algo = &pctv452e_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/
+
+	.num_device_descs = 2,
+	.devices = {
+		{ .name = "Technotrend TT Connect S2-3600",
+		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
+		  .warm_ids = { &pctv452e_usb_table[1], NULL }
+		},
+		{ .name = "Technotrend TT Connect S2-3650-CI",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &pctv452e_usb_table[2], NULL }
+		},
+		{ 0 },
+	}
+};
+
+static void pctv452e_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+	tt3650_ci_uninit(d);
+	dvb_usb_device_exit(intf);
+}
+
+static int pctv452e_usb_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	if (0 == dvb_usb_device_init(intf, &pctv452e_properties,
+					THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties,
+					THIS_MODULE, NULL, adapter_nr))
+		return 0;
+
+	return -ENODEV;
+}
+
+static struct usb_driver pctv452e_usb_driver = {
+	.name       = "pctv452e",
+	.probe      = pctv452e_usb_probe,
+	.disconnect = pctv452e_usb_disconnect,
+	.id_table   = pctv452e_usb_table,
+};
+
+static int __init pctv452e_usb_init(void)
+{
+	int ret = usb_register(&pctv452e_usb_driver);
+	if (ret)
+		err("%s: usb_register failed! Error %d", __FILE__, ret);
+
+	return ret;
+}
+
+static void __exit pctv452e_usb_exit(void)
+{
+	usb_deregister(&pctv452e_usb_driver);
+}
+
+module_init(pctv452e_usb_init);
+module_exit(pctv452e_usb_exit);
+
+MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>");
+MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>");
+MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>");
+MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/technisat-usb2.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/technisat-usb2.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/technisat-usb2.c	2013-05-02 01:34:42.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/technisat-usb2.c	2013-05-01 23:42:49.000000000 -0400
@@ -292,7 +292,7 @@ static void technisat_usb2_green_led_con
 {
 	struct technisat_usb2_state *state =
 		container_of(work, struct technisat_usb2_state, green_led_work.work);
-	struct dvb_frontend *fe = state->dev->adapter[0].fe;
+	struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
 
 	if (state->power_state == 0)
 		goto schedule;
@@ -505,14 +505,14 @@ static int technisat_usb2_frontend_attac
 	struct usb_device *udev = a->dev->udev;
 	int ret;
 
-	a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
+	a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
 			&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
 
-	if (a->fe) {
+	if (a->fe_adap[0].fe) {
 		struct stv6110x_devctl *ctl;
 
 		ctl = dvb_attach(stv6110x_attach,
-				a->fe,
+				a->fe_adap[0].fe,
 				&technisat_usb2_stv6110x_config,
 				&a->dev->i2c_adap);
 
@@ -532,8 +532,8 @@ static int technisat_usb2_frontend_attac
 			/* call the init function once to initialize
 			   tuner's clock output divider and demod's
 			   master clock */
-			if (a->fe->ops.init)
-				a->fe->ops.init(a->fe);
+			if (a->fe_adap[0].fe->ops.init)
+				a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
 
 			if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
 				return -EAGAIN;
@@ -548,20 +548,20 @@ static int technisat_usb2_frontend_attac
 			if (ret != 0)
 				err("could not set IF_CLK to external");
 
-			a->fe->ops.set_voltage = technisat_usb2_set_voltage;
+			a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
 
 			/* if everything was successful assign a nice name to the frontend */
-			strlcpy(a->fe->ops.info.name, a->dev->desc->name,
-					sizeof(a->fe->ops.info.name));
+			strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
+					sizeof(a->fe_adap[0].fe->ops.info.name));
 		} else {
-			dvb_frontend_detach(a->fe);
-			a->fe = NULL;
+			dvb_frontend_detach(a->fe_adap[0].fe);
+			a->fe_adap[0].fe = NULL;
 		}
 	}
 
 	technisat_usb2_set_led_timer(a->dev, 1, 1);
 
-	return a->fe == NULL ? -ENODEV : 0;
+	return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* Remote control */
@@ -697,6 +697,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = technisat_usb2_frontend_attach,
 
 			.stream = {
@@ -711,7 +713,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 			.size_of_priv = 0,
 		},
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c	2013-05-02 01:34:45.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c	2013-05-01 23:42:51.000000000 -0400
@@ -30,18 +30,43 @@
 #include "tda826x.h"
 #include "tda10086.h"
 #include "tda1002x.h"
+#include "tda10048.h"
 #include "tda827x.h"
 #include "lnbp21.h"
+/* CA */
+#include "dvb_ca_en50221.h"
 
 /* debug */
 static int dvb_usb_ttusb2_debug;
 #define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
 module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+static int dvb_usb_ttusb2_debug_ci;
+module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
+MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+#define ci_dbg(format, arg...)                \
+do {                                          \
+	if (dvb_usb_ttusb2_debug_ci)                                    \
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
+			": %s " format "\n" , __func__, ## arg);       \
+} while (0)
+
+enum {
+	TT3650_CMD_CI_TEST = 0x40,
+	TT3650_CMD_CI_RD_CTRL,
+	TT3650_CMD_CI_WR_CTRL,
+	TT3650_CMD_CI_RD_ATTR,
+	TT3650_CMD_CI_WR_ATTR,
+	TT3650_CMD_CI_RESET,
+	TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
 struct ttusb2_state {
+	struct dvb_ca_en50221 ca;
+	struct mutex ca_mutex;
 	u8 id;
 	u16 last_rc_key;
 };
@@ -78,11 +103,260 @@ static int ttusb2_msg(struct dvb_usb_dev
 	return 0;
 }
 
+/* ci */
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+	int ret;
+	u8 rx[60];/* (64 -4) */
+	ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
+	if (!ret)
+		memcpy(data, rx, read_len);
+	return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+	struct dvb_usb_device *d = ca->data;
+	struct ttusb2_state *state = d->priv;
+	int ret;
+
+	mutex_lock(&state->ca_mutex);
+	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+	u8 buf[3];
+	int ret = 0;
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+	ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+	u8 buf[3];
+
+	ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+	buf[2] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+	u8 buf[2];
+	int ret;
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = address & 3;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+	ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+	u8 buf[2];
+
+	ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = address;
+	buf[1] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
+{
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%d %d", slot, enable);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = enable;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	if (enable != buf[0]) {
+		err("CI not %sabled.", enable ? "en" : "dis");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct dvb_usb_device *d = ca->data;
+	struct ttusb2_state *state = d->priv;
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%d", slot);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = 0;
+
+	mutex_lock(&state->ca_mutex);
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 1;
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 0; /* FTA */
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+	msleep(1100);
+
+ failed:
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	u8 buf[1];
+	int ret;
+
+	if (slot)
+		return -EINVAL;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+	if (ret)
+		return ret;
+
+	if (1 == buf[0]) {
+		return DVB_CA_EN50221_POLL_CAM_PRESENT |
+			DVB_CA_EN50221_POLL_CAM_READY;
+	}
+	return 0;
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+	struct ttusb2_state *state;
+
+	ci_dbg("");
+
+	if (NULL == d)
+		return;
+
+	state = d->priv;
+	if (NULL == state)
+		return;
+
+	if (NULL == state->ca.data)
+		return;
+
+	dvb_ca_en50221_release(&state->ca);
+
+	memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+	struct dvb_usb_device *d = a->dev;
+	struct ttusb2_state *state = d->priv;
+	int ret;
+
+	ci_dbg("");
+
+	mutex_init(&state->ca_mutex);
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+	state->ca.read_cam_control = tt3650_ci_read_cam_control;
+	state->ca.write_cam_control = tt3650_ci_write_cam_control;
+	state->ca.slot_reset = tt3650_ci_slot_reset;
+	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+	state->ca.data = d;
+
+	ret = dvb_ca_en50221_init(&a->dvb_adap,
+				  &state->ca,
+				  /* flags */ 0,
+				  /* n_slots */ 1);
+	if (ret) {
+		err("Cannot initialize CI: Error %d.", ret);
+		memset(&state->ca, 0, sizeof(state->ca));
+		return ret;
+	}
+
+	info("CI initialized.");
+
+	return 0;
+}
+
 static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	static u8 obuf[60], ibuf[60];
-	int i,read;
+	int i, write_read, read;
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
@@ -91,28 +365,35 @@ static int ttusb2_i2c_xfer(struct i2c_ad
 		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
 
 	for (i = 0; i < num; i++) {
-		read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+		write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+		read = msg[i].flags & I2C_M_RD;
 
-		obuf[0] = (msg[i].addr << 1) | read;
-		obuf[1] = msg[i].len;
+		obuf[0] = (msg[i].addr << 1) | (write_read | read);
+		if (read)
+			obuf[1] = 0;
+		else
+			obuf[1] = msg[i].len;
 
 		/* read request */
-		if (read)
+		if (write_read)
 			obuf[2] = msg[i+1].len;
+		else if (read)
+			obuf[2] = msg[i].len;
 		else
 			obuf[2] = 0;
 
-		memcpy(&obuf[3],msg[i].buf,msg[i].len);
+		memcpy(&obuf[3], msg[i].buf, msg[i].len);
 
 		if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
 			err("i2c transfer failed.");
 			break;
 		}
 
-		if (read) {
-			memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+		if (write_read) {
+			memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
 			i++;
-		}
+		} else if (read)
+			memcpy(msg[i].buf, &ibuf[3], msg[i].len);
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -190,12 +471,31 @@ static struct tda10023_config tda10023_c
 	.deltaf = 0xa511,
 };
 
+static struct tda10048_config tda10048_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_PARALLEL_OUTPUT,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_4000,
+	.dtv7_if_freq_khz = TDA10048_IF_4500,
+	.dtv8_if_freq_khz = TDA10048_IF_5000,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+	.no_firmware      = 1,
+	.set_pll          = true ,
+	.pll_m            = 5,
+	.pll_n            = 3,
+	.pll_p            = 0,
+};
+
+static struct tda827x_config tda827x_config = {
+	.config = 0,
+};
+
 static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
 {
 	if (usb_set_interface(adap->dev->udev,0,3) < 0)
 		err("set interface to alts=3 failed");
 
-	if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+	if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
 		deb_info("TDA10086 attach failed\n");
 		return -ENODEV;
 	}
@@ -203,20 +503,57 @@ static int ttusb2_frontend_tda10086_atta
 	return 0;
 }
 
+static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+	return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
+}
+
 static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
 {
 	if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
 		err("set interface to alts=3 failed");
-	if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
-		deb_info("TDA10023 attach failed\n");
-		return -ENODEV;
+
+	if (adap->fe_adap[0].fe == NULL) {
+		/* FE 0 DVB-C */
+		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+			&tda10023_config, &adap->dev->i2c_adap, 0x48);
+
+		if (adap->fe_adap[0].fe == NULL) {
+			deb_info("TDA10023 attach failed\n");
+			return -ENODEV;
+		}
+		tt3650_ci_init(adap);
+	} else {
+		adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
+			&tda10048_config, &adap->dev->i2c_adap);
+
+		if (adap->fe_adap[1].fe == NULL) {
+			deb_info("TDA10048 attach failed\n");
+			return -ENODEV;
+		}
+
+		/* tuner is behind TDA10023 I2C-gate */
+		adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
+
 	}
+
 	return 0;
 }
 
 static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+	struct dvb_frontend *fe;
+
+	/* MFE: select correct FE to attach tuner since that's called twice */
+	if (adap->fe_adap[1].fe == NULL)
+		fe = adap->fe_adap[0].fe;
+	else
+		fe = adap->fe_adap[1].fe;
+
+	/* attach tuner */
+	if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
 		printk(KERN_ERR "%s: No tda827x found!\n", __func__);
 		return -ENODEV;
 	}
@@ -225,12 +562,12 @@ static int ttusb2_tuner_tda827x_attach(s
 
 static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+	if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
 		deb_info("TDA8263 attach failed\n");
 		return -ENODEV;
 	}
 
-	if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+	if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
 		deb_info("LNBP21 attach failed\n");
 		return -ENODEV;
 	}
@@ -242,6 +579,14 @@ static struct dvb_usb_device_properties
 static struct dvb_usb_device_properties ttusb2_properties_s2400;
 static struct dvb_usb_device_properties ttusb2_properties_ct3650;
 
+static void ttusb2_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+	tt3650_ci_uninit(d);
+	dvb_usb_device_exit(intf);
+}
+
 static int ttusb2_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
@@ -277,6 +622,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
 
 			.frontend_attach  = ttusb2_frontend_tda10086_attach,
@@ -295,6 +642,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}},
 		}
 	},
 
@@ -329,6 +677,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = NULL,
 
 			.frontend_attach  = ttusb2_frontend_tda10086_attach,
@@ -347,6 +697,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}},
 		}
 	},
 
@@ -383,6 +734,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 2,
+		.fe = {{
 			.streaming_ctrl   = NULL,
 
 			.frontend_attach  = ttusb2_frontend_tda10023_attach,
@@ -401,6 +754,26 @@ static struct dvb_usb_device_properties
 					}
 				}
 			}
+		}, {
+			.streaming_ctrl   = NULL,
+
+			.frontend_attach  = ttusb2_frontend_tda10023_attach,
+			.tuner_attach = ttusb2_tuner_tda827x_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_ISOC,
+				.count = 5,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize = 940,
+						.interval = 1,
+					}
+				}
+			}
+		}},
 		},
 	},
 
@@ -422,7 +795,7 @@ static struct dvb_usb_device_properties
 static struct usb_driver ttusb2_driver = {
 	.name		= "dvb_usb_ttusb2",
 	.probe		= ttusb2_probe,
-	.disconnect = dvb_usb_device_exit,
+	.disconnect	= ttusb2_usb_disconnect,
 	.id_table	= ttusb2_table,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/umt-010.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/umt-010.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/umt-010.c	2013-05-02 01:34:46.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/umt-010.c	2013-05-01 23:42:53.000000000 -0400
@@ -60,14 +60,14 @@ static int umt_mt352_frontend_attach(str
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_address = 0xf;
 
-	adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
 
 	return 0;
 }
 
 static int umt_tuner_attach (struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
 	return 0;
 }
 
@@ -100,6 +100,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 			.frontend_attach  = umt_mt352_frontend_attach,
 			.tuner_attach     = umt_tuner_attach,
@@ -115,7 +117,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/usb-urb.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/usb-urb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/usb-urb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/usb-urb.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@ static int usb_bulk_urb_init(struct usb_
 		if (!stream->urb_list[i]) {
 			deb_mem("not enough memory for urb_alloc_urb!.\n");
 			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[i]);
+				usb_free_urb(stream->urb_list[j]);
 			return -ENOMEM;
 		}
 		usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
@@ -181,7 +181,7 @@ static int usb_isoc_urb_init(struct usb_
 		if (!stream->urb_list[i]) {
 			deb_mem("not enough memory for urb_alloc_urb!\n");
 			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[i]);
+				usb_free_urb(stream->urb_list[j]);
 			return -ENOMEM;
 		}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/vp702x.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/vp702x.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/vp702x.c	2013-05-02 01:34:48.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/vp702x.c	2013-05-01 23:42:55.000000000 -0400
@@ -320,7 +320,7 @@ static int vp702x_frontend_attach(struct
 
 	vp702x_init_pid_filter(adap);
 
-	adap->fe = vp702x_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
 	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
 
 	return 0;
@@ -383,6 +383,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
 
 			.streaming_ctrl   = vp702x_streaming_ctrl,
@@ -399,6 +401,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct vp702x_adapter_state),
 		}
 	},
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/vp7045.c linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/vp7045.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/dvb-usb/vp7045.c	2013-05-02 01:34:50.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/dvb-usb/vp7045.c	2013-05-01 23:42:57.000000000 -0400
@@ -214,7 +214,7 @@ static int vp7045_frontend_attach(struct
 /*	Dump the EEPROM */
 /*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
 
-	adap->fe = vp7045_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
 
 	return 0;
 }
@@ -245,6 +245,8 @@ static struct dvb_usb_device_properties
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = vp7045_frontend_attach,
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
@@ -257,6 +259,7 @@ static struct dvb_usb_device_properties
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl       = vp7045_power_ctrl,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/a8293.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/a8293.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/a8293.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/a8293.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dvb_frontend.h"
+#include "a8293.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define LOG_PREFIX "a8293"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+
+struct a8293_priv {
+	struct i2c_adapter *i2c;
+	const struct a8293_config *cfg;
+	u8 reg[2];
+};
+
+static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
+{
+	int ret;
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg->i2c_addr,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	if (rd)
+		msg[0].flags = I2C_M_RD;
+	else
+		msg[0].flags = 0;
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c failed=%d rd=%d", ret, rd);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 0);
+}
+
+static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 1);
+}
+
+static int a8293_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct a8293_priv *priv = fe->sec_priv;
+	int ret;
+
+	dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_OFF:
+		/* ENB=0 */
+		priv->reg[0] = 0x10;
+		break;
+	case SEC_VOLTAGE_13:
+		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
+		priv->reg[0] = 0x31;
+		break;
+	case SEC_VOLTAGE_18:
+		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
+		priv->reg[0] = 0x38;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	};
+
+	ret = a8293_wr(priv, &priv->reg[0], 1);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static void a8293_release_sec(struct dvb_frontend *fe)
+{
+	dbg("%s:", __func__);
+
+	a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	int ret;
+	struct a8293_priv *priv = NULL;
+	u8 buf[2];
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	priv->cfg = cfg;
+	fe->sec_priv = priv;
+
+	/* check if the SEC is there */
+	ret = a8293_rd(priv, buf, 2);
+	if (ret)
+		goto err;
+
+	/* ENB=0 */
+	priv->reg[0] = 0x10;
+	ret = a8293_wr(priv, &priv->reg[1], 1);
+	if (ret)
+		goto err;
+
+	/* TMODE=0, TGATE=1 */
+	priv->reg[1] = 0x82;
+	ret = a8293_wr(priv, &priv->reg[1], 1);
+	if (ret)
+		goto err;
+
+	info("Allegro A8293 SEC attached.");
+
+	fe->ops.release_sec = a8293_release_sec;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = a8293_set_voltage;
+
+	return fe;
+err:
+	dbg("%s: failed=%d", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(a8293_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Allegro A8293 SEC driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/a8293.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/a8293.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/a8293.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/a8293.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef A8293_H
+#define A8293_H
+
+struct a8293_config {
+	u8 i2c_addr;
+};
+
+#if defined(CONFIG_DVB_A8293) || \
+	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg);
+#else
+static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* A8293_H */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_c.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_c.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_c.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,4 +335,3 @@ int cxd2820r_get_tune_settings_c(struct
 
 	return 0;
 }
-
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_core.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_core.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -727,72 +727,22 @@ static void cxd2820r_release(struct dvb_
 	struct cxd2820r_priv *priv = fe->demodulator_priv;
 	dbg("%s", __func__);
 
-	if (fe->ops.info.type == FE_OFDM) {
-		i2c_del_adapter(&priv->tuner_i2c_adapter);
+	if (fe->ops.info.type == FE_OFDM)
 		kfree(priv);
-	}
 
 	return;
 }
 
-static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
-	struct i2c_msg msg[], int num)
-{
-	struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
-	int ret;
-	u8 *obuf = kmalloc(msg[0].len + 2, GFP_KERNEL);
-	struct i2c_msg msg2[2] = {
-		{
-			.addr = priv->cfg.i2c_address,
-			.flags = 0,
-			.len = msg[0].len + 2,
-			.buf = obuf,
-		}, {
-			.addr = priv->cfg.i2c_address,
-			.flags = I2C_M_RD,
-			.len = msg[1].len,
-			.buf = msg[1].buf,
-		}
-	};
-
-	if (!obuf)
-		return -ENOMEM;
-
-	obuf[0] = 0x09;
-	obuf[1] = (msg[0].addr << 1);
-	if (num == 2) { /* I2C read */
-		obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
-		msg2[0].len = msg[0].len + 2 - 1; /* '-1' maybe HW bug ? */
-	}
-	memcpy(&obuf[2], msg[0].buf, msg[0].len);
-
-	ret = i2c_transfer(priv->i2c, msg2, num);
-	if (ret < 0)
-		warn("tuner i2c failed ret:%d", ret);
-
-	kfree(obuf);
-
-	return ret;
-}
-
-static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
-	.master_xfer   = cxd2820r_tuner_i2c_xfer,
-	.functionality = cxd2820r_tuner_i2c_func,
-};
-
-struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	return &priv->tuner_i2c_adapter;
+	dbg("%s: %d", __func__, enable);
+
+	/* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
+	return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
 }
-EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
 
-static struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops[2];
 
 struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
 	struct i2c_adapter *i2c, struct dvb_frontend *fe)
@@ -831,18 +781,6 @@ struct dvb_frontend *cxd2820r_attach(con
 		priv->fe[0].demodulator_priv = priv;
 		priv->fe[1].demodulator_priv = priv;
 
-		/* create tuner i2c adapter */
-		strlcpy(priv->tuner_i2c_adapter.name,
-			"CXD2820R tuner I2C adapter",
-			sizeof(priv->tuner_i2c_adapter.name));
-		priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
-		priv->tuner_i2c_adapter.algo_data = NULL;
-		i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
-		if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
-			err("tuner I2C bus could not be initialized");
-			goto error;
-		}
-
 		return &priv->fe[0];
 
 	} else {
@@ -858,7 +796,7 @@ error:
 }
 EXPORT_SYMBOL(cxd2820r_attach);
 
-static struct dvb_frontend_ops cxd2820r_ops[2] = {
+static const struct dvb_frontend_ops cxd2820r_ops[2] = {
 	{
 		/* DVB-T/T2 */
 		.info = {
@@ -883,6 +821,7 @@ static struct dvb_frontend_ops cxd2820r_
 		.sleep = cxd2820r_sleep,
 
 		.get_tune_settings = cxd2820r_get_tune_settings,
+		.i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
 
 		.get_frontend = cxd2820r_get_frontend,
 
@@ -911,6 +850,7 @@ static struct dvb_frontend_ops cxd2820r_
 		.sleep = cxd2820r_sleep,
 
 		.get_tune_settings = cxd2820r_get_tune_settings,
+		.i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
 
 		.set_frontend = cxd2820r_set_frontend,
 		.get_frontend = cxd2820r_get_frontend,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,9 +93,6 @@ extern struct dvb_frontend *cxd2820r_att
 	struct i2c_adapter *i2c,
 	struct dvb_frontend *fe
 );
-extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-);
 #else
 static inline struct dvb_frontend *cxd2820r_attach(
 	const struct cxd2820r_config *config,
@@ -106,12 +103,6 @@ static inline struct dvb_frontend *cxd28
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
 
 #endif
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_priv.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_priv.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,7 +50,6 @@ struct cxd2820r_priv {
 	struct i2c_adapter *i2c;
 	struct dvb_frontend fe[2];
 	struct cxd2820r_config cfg;
-	struct i2c_adapter tuner_i2c_adapter;
 
 	struct mutex fe_lock; /*Â FE lock */
 	int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_t2.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_t2.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_t2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_t2.c	2012-01-04 18:55:44.000000000 -0500
@@ -420,4 +420,3 @@ int cxd2820r_get_tune_settings_t2(struct
 
 	return 0;
 }
-
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_t.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_t.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/cxd2820r_t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/cxd2820r_t.c	2012-01-04 18:55:44.000000000 -0500
@@ -446,4 +446,3 @@ int cxd2820r_get_tune_settings_t(struct
 
 	return 0;
 }
-
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib0070.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib0070.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib0070.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib0070.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -78,10 +79,18 @@ struct dib0070_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[3];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0070 I2C read failed\n");
-		return 0;
-	}
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
 	state->i2c_write_buffer[0] = reg;
 	state->i2c_write_buffer[1] = val >> 8;
 	state->i2c_write_buffer[2] = val & 0xff;
@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0070 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 #define HARD_RESET(state) do { \
@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(stru
 	state->cfg = cfg;
 	state->i2c = i2c;
 	state->fe  = fe;
+	mutex_init(&state->i2c_buffer_lock);
 	fe->tuner_priv = state;
 
 	if (dib0070_reset(fe) != 0)
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib0090.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib0090.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib0090.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib0090.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -196,6 +197,7 @@ struct dib0090_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[3];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 struct dib0090_fw_state {
@@ -208,10 +210,18 @@ struct dib0090_fw_state {
 	struct i2c_msg msg;
 	u8 i2c_write_buffer[2];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib00
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		return 0;
-	}
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = reg & 0xff;
 	state->i2c_write_buffer[1] = val >> 8;
 	state->i2c_write_buffer[2] = val & 0xff;
@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(&state->msg, 0, sizeof(struct i2c_msg));
@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct di
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		return 0;
-	}
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = val >> 8;
 	state->i2c_write_buffer[1] = val & 0xff;
 
@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct d
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 #define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(st
 	st->config = config;
 	st->i2c = i2c;
 	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
 	fe->tuner_priv = st;
 
 	if (config->wbd == NULL)
@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register
 	st->config = config;
 	st->i2c = i2c;
 	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
 	fe->tuner_priv = st;
 
 	if (dib0090_fw_reset_digital(fe, st->config) != 0)
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib3000.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib3000.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib3000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib3000.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dvb-dibusb) are based.
  *
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  *
  */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib3000mb.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib3000mb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib3000mb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib3000mb.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dvb-dibusb) are based.
  *
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  *
  */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib7000m.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib7000m.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib7000m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib7000m.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -55,6 +56,7 @@ struct dib7000m_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib7000m_power_mode {
@@ -69,6 +71,13 @@ enum dib7000m_power_mode {
 
 static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d",reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct di
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
 {
@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(st
 	demod                   = &st->demod;
 	demod->demodulator_priv = st;
 	memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
 
 	st->timf_default = cfg->bw->timf;
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib7000p.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib7000p.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib7000p.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib7000p.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_math.h"
 #include "dvb_frontend.h"
@@ -68,6 +69,7 @@ struct dib7000p_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib7000p_power_mode {
@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(stru
 
 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg >> 8;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct di
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
@@ -1577,8 +1598,8 @@ int dib7000pc_detection(struct i2c_adapt
 		return -ENOMEM;
 	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
 	if (!rx) {
-		goto rx_memory_error;
 		ret = -ENOMEM;
+		goto rx_memory_error;
 	}
 
 	msg[0].buf = tx;
@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_
 		return -ENOMEM;
 
 	dpst->i2c_adap = i2c;
+	mutex_init(&dpst->i2c_buffer_lock);
 
 	for (k = no_of_demods - 1; k >= 0; k--) {
 		dpst->cfg = cfg[k];
@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(str
 	demod = &st->demod;
 	demod->demodulator_priv = st;
 	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
 
 	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
 
@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(str
 	st->version = dib7000p_read_word(st, 897);
 
 	/* FIXME: make sure the dev.parent field is initialized, or else
-		request_firmware() will hit an OOPS (this should be moved somewhere
-		more common) */
+	   request_firmware() will hit an OOPS (this should be moved somewhere
+	   more common) */
+	st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
 
 	/* FIXME: make sure the dev.parent field is initialized, or else
 	   request_firmware() will hit an OOPS (this should be moved somewhere
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib8000.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib8000.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib8000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib8000.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
+
 #include "dvb_math.h"
 
 #include "dvb_frontend.h"
@@ -37,6 +39,7 @@ struct i2c_device {
 	u8 addr;
 	u8 *i2c_write_buffer;
 	u8 *i2c_read_buffer;
+	struct mutex *i2c_buffer_lock;
 };
 
 struct dib8000_state {
@@ -77,6 +80,7 @@ struct dib8000_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib8000_power_mode {
@@ -86,24 +90,39 @@ enum dib8000_power_mode {
 
 static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
 {
+	u16 ret;
 	struct i2c_msg msg[2] = {
-		{.addr = i2c->addr >> 1, .flags = 0,
-			.buf = i2c->i2c_write_buffer, .len = 2},
-		{.addr = i2c->addr >> 1, .flags = I2C_M_RD,
-			.buf = i2c->i2c_read_buffer, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = 0, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
 	};
 
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	msg[0].buf    = i2c->i2c_write_buffer;
 	msg[0].buf[0] = reg >> 8;
 	msg[0].buf[1] = reg & 0xff;
+	msg[1].buf    = i2c->i2c_read_buffer;
 
 	if (i2c_transfer(i2c->adap, msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (msg[1].buf[0] << 8) | msg[1].buf[1];
+	ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
+	mutex_unlock(i2c->i2c_buffer_lock);
+	return ret;
 }
 
 static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg >> 8;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8
 	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000
 
 static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
 {
-	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
-		.buf = i2c->i2c_write_buffer, .len = 4};
+	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
 	int ret = 0;
 
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	msg.buf    = i2c->i2c_write_buffer;
 	msg.buf[0] = (reg >> 8) & 0xff;
 	msg.buf[1] = reg & 0xff;
 	msg.buf[2] = (val >> 8) & 0xff;
 	msg.buf[3] = val & 0xff;
 
 	ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(i2c->i2c_buffer_lock);
 
 	return ret;
 }
 
 static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_a
 	if (!client.i2c_read_buffer) {
 		dprintk("%s: not enough memory", __func__);
 		ret = -ENOMEM;
-		goto error_memory;
+		goto error_memory_read;
+	}
+	client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+	if (!client.i2c_buffer_lock) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory_lock;
 	}
+	mutex_init(client.i2c_buffer_lock);
 
 	for (k = no_of_demods - 1; k >= 0; k--) {
 		/* designated i2c address */
@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_a
 	}
 
 error:
+	kfree(client.i2c_buffer_lock);
+error_memory_lock:
 	kfree(client.i2c_read_buffer);
-error_memory:
+error_memory_read:
 	kfree(client.i2c_write_buffer);
 
 	return ret;
@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(stru
 	state->i2c.addr = i2c_addr;
 	state->i2c.i2c_write_buffer = state->i2c_write_buffer;
 	state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+	mutex_init(&state->i2c_buffer_lock);
+	state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
 	state->gpio_val = cfg->gpio_val;
 	state->gpio_dir = cfg->gpio_dir;
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib9000.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib9000.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dib9000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dib9000.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,15 @@ struct i2c_device {
 #define DibInitLock(lock) mutex_init(lock)
 #define DibFreeLock(lock)
 
+struct dib9000_pid_ctrl {
+#define DIB9000_PID_FILTER_CTRL 0
+#define DIB9000_PID_FILTER      1
+	u8 cmd;
+	u8 id;
+	u16 pid;
+	u8 onoff;
+};
+
 struct dib9000_state {
 	struct i2c_device i2c;
 
@@ -99,6 +108,10 @@ struct dib9000_state {
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[255];
 	u8 i2c_read_buffer[255];
+	DIB_LOCK demod_lock;
+	u8 get_frontend_internal;
+	struct dib9000_pid_ctrl pid_ctrl[10];
+	s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
 };
 
 static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1167,8 +1180,8 @@ static int dib9000_fw_get_channel(struct
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		goto error;
 		ret = -EIO;
+		goto error;
 	}
 
 	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio);
 int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 val = dib9000_read_word(state, 294 + 1) & 0xffef;
+	u16 val;
+	int ret;
+
+	if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter cmd postpone");
+		state->pid_ctrl_index++;
+		state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
+		state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		return 0;
+	}
+
+	DibAcquireLock(&state->demod_lock);
+
+	val = dib9000_read_word(state, 294 + 1) & 0xffef;
 	val |= (onoff & 0x1) << 4;
 
 	dprintk("PID filter enabled %d", onoff);
-	return dib9000_write_word(state, 294 + 1, val);
+	ret = dib9000_write_word(state, 294 + 1, val);
+	DibReleaseLock(&state->demod_lock);
+	return ret;
+
 }
 EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
 
 int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
+	int ret;
+
+	if (state->pid_ctrl_index != -2) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter postpone");
+		if (state->pid_ctrl_index < 9) {
+			state->pid_ctrl_index++;
+			state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
+			state->pid_ctrl[state->pid_ctrl_index].id = id;
+			state->pid_ctrl[state->pid_ctrl_index].pid = pid;
+			state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		} else
+			dprintk("can not add any more pid ctrl cmd");
+		return 0;
+	}
+
+	DibAcquireLock(&state->demod_lock);
 	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
-	return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
+	ret = dib9000_write_word(state, 300 + 1 + id,
+			onoff ? (1 << 13) | pid : 0);
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 EXPORT_SYMBOL(dib9000_fw_pid_filter);
 
@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_f
 	DibFreeLock(&state->platform.risc.mbx_lock);
 	DibFreeLock(&state->platform.risc.mem_lock);
 	DibFreeLock(&state->platform.risc.mem_mbx_lock);
+	DibFreeLock(&state->demod_lock);
 	dibx000_exit_i2c_master(&st->i2c_master);
 
 	i2c_del_adapter(&st->tuner_adap);
@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_fron
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend;
-	int ret;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
 		if (ret < 0)
-			return ret;
+			goto error;
 	}
-	return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+	ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct d
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend, sub_index_frontend;
 	fe_status_t stat;
-	int ret;
+	int ret = 0;
+
+	if (state->get_frontend_internal == 0)
+		DibAcquireLock(&state->demod_lock);
 
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct d
 					    state->fe[index_frontend]->dtv_property_cache.rolloff;
 				}
 			}
-			return 0;
+			ret = 0;
+			goto return_value;
 		}
 	}
 
 	/* get the channel from master chip */
 	ret = dib9000_fw_get_channel(fe, fep);
 	if (ret != 0)
-		return ret;
+		goto return_value;
 
 	/* synchronize the cache with the other frontends */
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct d
 		state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
 		state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
 	}
+	ret = 0;
 
-	return 0;
+return_value:
+	if (state->get_frontend_internal == 0)
+		DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct d
 		dprintk("dib9000: must specify bandwidth ");
 		return 0;
 	}
+
+	state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
+	DibAcquireLock(&state->demod_lock);
+
 	fe->dtv_property_cache.delivery_system = SYS_DVBT;
 
 	/* set the master status */
@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct d
 	/* check the tune result */
 	if (exit_condition == 1) {	/* tune failed */
 		dprintk("tune failed");
+		DibReleaseLock(&state->demod_lock);
+		/* tune failed; put all the pid filtering cmd to junk */
+		state->pid_ctrl_index = -1;
 		return 0;
 	}
 
 	dprintk("tune success on frontend%i", index_frontend_success);
 
 	/* synchronize all the channel cache */
+	state->get_frontend_internal = 1;
 	dib9000_get_frontend(state->fe[0], fep);
+	state->get_frontend_internal = 0;
 
 	/* retune the other frontends with the found channel */
 	channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct d
 	/* turn off the diversity for the last frontend */
 	dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
 
+	DibReleaseLock(&state->demod_lock);
+	if (state->pid_ctrl_index >= 0) {
+		u8 index_pid_filter_cmd;
+		u8 pid_ctrl_index = state->pid_ctrl_index;
+
+		state->pid_ctrl_index = -2;
+		for (index_pid_filter_cmd = 0;
+				index_pid_filter_cmd <= pid_ctrl_index;
+				index_pid_filter_cmd++) {
+			if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
+				dib9000_fw_pid_filter_ctrl(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+			else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
+				dib9000_fw_pid_filter(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].id,
+						state->pid_ctrl[index_pid_filter_cmd].pid,
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+		}
+	}
+	/* do not postpone any more the pid filtering */
+	state->pid_ctrl_index = -2;
+
 	return 0;
 }
 
@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dv
 	u8 index_frontend;
 	u16 lock = 0, lock_slave = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
 		lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
 
@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dv
 	if ((lock & 0x0008) || (lock_slave & 0x0008))
 		*stat |= FE_HAS_LOCK;
 
+	DibReleaseLock(&state->demod_lock);
+
 	return 0;
 }
 
@@ -2066,10 +2164,15 @@ static int dib9000_read_ber(struct dvb_f
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u16 *c;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
 			state->i2c_read_buffer, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
@@ -2077,7 +2180,10 @@ static int dib9000_read_ber(struct dvb_f
 	c = (u16 *)state->i2c_read_buffer;
 
 	*ber = c[10] << 16 | c[11];
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
@@ -2086,7 +2192,9 @@ static int dib9000_read_signal_strength(
 	u8 index_frontend;
 	u16 *c = (u16 *)state->i2c_read_buffer;
 	u16 val;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	*strength = 0;
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
@@ -2097,8 +2205,10 @@ static int dib9000_read_signal_strength(
 	}
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
@@ -2107,7 +2217,10 @@ static int dib9000_read_signal_strength(
 		*strength = 65535;
 	else
 		*strength += val;
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static u32 dib9000_get_snr(struct dvb_frontend *fe)
@@ -2151,6 +2264,7 @@ static int dib9000_read_snr(struct dvb_f
 	u8 index_frontend;
 	u32 snr_master;
 
+	DibAcquireLock(&state->demod_lock);
 	snr_master = dib9000_get_snr(fe);
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
 		snr_master += dib9000_get_snr(state->fe[index_frontend]);
@@ -2161,6 +2275,8 @@ static int dib9000_read_snr(struct dvb_f
 	} else
 		*snr = 0;
 
+	DibReleaseLock(&state->demod_lock);
+
 	return 0;
 }
 
@@ -2168,15 +2284,22 @@ static int dib9000_read_unc_blocks(struc
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u16 *c = (u16 *)state->i2c_read_buffer;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	*unc = c[12];
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
@@ -2322,6 +2445,10 @@ struct dvb_frontend *dib9000_attach(stru
 	DibInitLock(&st->platform.risc.mbx_lock);
 	DibInitLock(&st->platform.risc.mem_lock);
 	DibInitLock(&st->platform.risc.mem_mbx_lock);
+	DibInitLock(&st->demod_lock);
+	st->get_frontend_internal = 0;
+
+	st->pid_ctrl_index = -2;
 
 	st->fe[0] = fe;
 	fe->demodulator_priv = st;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dibx000_common.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dibx000_common.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dibx000_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dibx000_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,6 @@
 #include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
 
 #include "dibx000_common.h"
 
@@ -10,6 +12,13 @@ MODULE_PARM_DESC(debug, "turn on debuggi
 
 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	mst->i2c_write_buffer[1] = reg & 0xff;
 	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -21,11 +30,21 @@ static int dibx000_write_word(struct dib
 	mst->msg[0].buf = mst->i2c_write_buffer;
 	mst->msg[0].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	mst->i2c_write_buffer[0] = reg >> 8;
 	mst->i2c_write_buffer[1] = reg & 0xff;
 
@@ -42,7 +61,10 @@ static u16 dibx000_read_word(struct dibx
 	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
@@ -257,6 +279,7 @@ static int dibx000_i2c_gated_gpio67_xfer
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
 
 	if (num > 32) {
 		dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -264,10 +287,15 @@ static int dibx000_i2c_gated_gpio67_xfer
 		return -ENOMEM;
 	}
 
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
 
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
 	/* open the gate */
 	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 	mst->msg[0].addr = mst->i2c_addr;
@@ -282,7 +310,11 @@ static int dibx000_i2c_gated_gpio67_xfer
 	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
@@ -294,6 +326,7 @@ static int dibx000_i2c_gated_tuner_xfer(
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
 
 	if (num > 32) {
 		dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -301,10 +334,14 @@ static int dibx000_i2c_gated_tuner_xfer(
 		return -ENOMEM;
 	}
 
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
 	/* open the gate */
 	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 	mst->msg[0].addr = mst->i2c_addr;
@@ -319,7 +356,10 @@ static int dibx000_i2c_gated_tuner_xfer(
 	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
@@ -390,8 +430,18 @@ static int i2c_adapter_init(struct i2c_a
 int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
 				struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
-	u8 tx[4];
-	struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
+	int ret;
+
+	mutex_init(&mst->i2c_buffer_lock);
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg));
+	mst->msg[0].addr = i2c_addr >> 1;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 4;
 
 	mst->device_rev = device_rev;
 	mst->i2c_adap = i2c_adap;
@@ -431,9 +481,12 @@ int dibx000_init_i2c_master(struct dibx0
 				"DiBX000: could not initialize the master i2c_adapter\n");
 
 	/* initialize the i2c-master by closing the gate */
-	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
 
-	return i2c_transfer(i2c_adap, &m, 1) == 1;
+	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 EXPORT_SYMBOL(dibx000_init_i2c_master);
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dibx000_common.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dibx000_common.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/dibx000_common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/dibx000_common.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@ struct dibx000_i2c_master {
 	struct i2c_msg msg[34];
 	u8 i2c_write_buffer[8];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/drxd_hard.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/drxd_hard.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/drxd_hard.c	2013-05-02 01:35:15.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/drxd_hard.c	2013-05-01 23:43:22.000000000 -0400
@@ -889,10 +889,15 @@ static int ReadIFAgc(struct drxd_state *
 			u32 R2 = state->if_agc_cfg.R2;
 			u32 R3 = state->if_agc_cfg.R3;
 
-			u32 Vmax = (3300 * R2) / (R1 + R2);
-			u32 Rpar = (R2 * R3) / (R3 + R2);
-			u32 Vmin = (3300 * Rpar) / (R1 + Rpar);
-			u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+			u32 Vmax, Rpar, Vmin, Vout;
+
+			if (R2 == 0 && (R1 == 0 || R3 == 0))
+				return 0;
+
+			Vmax = (3300 * R2) / (R1 + R2);
+			Rpar = (R2 * R3) / (R3 + R2);
+			Vmin = (3300 * Rpar) / (R1 + Rpar);
+			Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
 
 			*pValue = Vout;
 		}
@@ -926,16 +931,15 @@ static int DownloadMicrocode(struct drxd
 			     const u8 *pMCImage, u32 Length)
 {
 	u8 *pSrc;
-	u16 Flags;
 	u32 Address;
 	u16 nBlocks;
 	u16 BlockSize;
-	u16 BlockCRC;
 	u32 offset = 0;
 	int i, status = 0;
 
 	pSrc = (u8 *) pMCImage;
-	Flags = (pSrc[0] << 8) | pSrc[1];
+	/* We're not using Flags */
+	/* Flags = (pSrc[0] << 8) | pSrc[1]; */
 	pSrc += sizeof(u16);
 	offset += sizeof(u16);
 	nBlocks = (pSrc[0] << 8) | pSrc[1];
@@ -952,11 +956,13 @@ static int DownloadMicrocode(struct drxd
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
-		Flags = (pSrc[0] << 8) | pSrc[1];
+		/* We're not using Flags */
+		/* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
-		BlockCRC = (pSrc[0] << 8) | pSrc[1];
+		/* We're not using BlockCRC */
+		/* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/drxk_hard.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/drxk_hard.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/drxk_hard.c	2013-05-02 01:35:15.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/drxk_hard.c	2013-05-01 23:43:22.000000000 -0400
@@ -6211,6 +6211,14 @@ static int drxk_set_parameters(struct dv
 	u32 IF;
 
 	dprintk(1, "\n");
+
+	if (!fe->ops.tuner_ops.get_if_frequency) {
+		printk(KERN_ERR
+		       "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
+		return -EINVAL;
+	}
+
+
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (fe->ops.tuner_ops.set_params)
@@ -6218,7 +6226,7 @@ static int drxk_set_parameters(struct dv
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 	state->param = *p;
-	fe->ops.tuner_ops.get_frequency(fe, &IF);
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
 	Start(state, 0, IF);
 
 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,839 @@
+/*
+ *  Driver for it913x-fe Frontend
+ *
+ *  with support for on chip it9137 integral tuner
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "dvb_frontend.h"
+#include "it913x-fe.h"
+#include "it913x-fe-priv.h"
+
+static int it913x_debug;
+
+module_param_named(debug, it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define dprintk(level, args...) do { \
+	if (level & it913x_debug) \
+		printk(KERN_DEBUG "it913x-fe: " args); \
+} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define debug_data_snipet(level, name, p) \
+	  dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
+			*(p+5), *(p+6), *(p+7));
+
+struct it913x_fe_state {
+	struct dvb_frontend frontend;
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+	u32 frequency;
+	u8 adf;
+	u32 crystalFrequency;
+	u32 adcFrequency;
+	u8 tuner_type;
+	struct adctable *table;
+	fe_status_t it913x_status;
+	u16 tun_xtal;
+	u8 tun_fdiv;
+	u8 tun_clk_mode;
+	u32 tun_fn_min;
+};
+
+static int it913x_read_reg(struct it913x_fe_state *state,
+		u32 reg, u8 *data, u8 count)
+{
+	int ret;
+	u8 pro = PRO_DMOD; /* All reads from demodulator */
+	u8 b[4];
+	struct i2c_msg msg[2] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+			.buf = b, .len = sizeof(b) },
+		{ .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
+			.buf = data, .len = count }
+	};
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	return ret;
+}
+
+static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
+{
+	int ret;
+	u8 b[1];
+	ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
+	return (ret < 0) ? -ENODEV : b[0];
+}
+
+static int it913x_write(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u8 buf[], u8 count)
+{
+	u8 b[256];
+	struct i2c_msg msg[1] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+		  .buf = b, .len = count + 4 }
+	};
+	int ret;
+
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+	memcpy(&b[4], buf, count);
+
+	ret = i2c_transfer(state->i2c_adap, msg, 1);
+
+	if (ret < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int it913x_write_reg(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u32 data)
+{
+	int ret;
+	u8 b[4];
+	u8 s;
+
+	b[0] = data >> 24;
+	b[1] = (data >> 16) & 0xff;
+	b[2] = (data >> 8) & 0xff;
+	b[3] = data & 0xff;
+	/* expand write as needed */
+	if (data < 0x100)
+		s = 3;
+	else if (data < 0x1000)
+		s = 2;
+	else if (data < 0x100000)
+		s = 1;
+	else
+		s = 0;
+
+	ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
+
+	return ret;
+}
+
+static int it913x_fe_script_loader(struct it913x_fe_state *state,
+		struct it913xset *loadscript)
+{
+	int ret, i;
+	if (loadscript == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < 1000; ++i) {
+		if (loadscript[i].pro == 0xff)
+			break;
+		ret = it913x_write(state, loadscript[i].pro,
+			loadscript[i].address,
+			loadscript[i].reg, loadscript[i].count);
+		if (ret < 0)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static int it913x_init_tuner(struct it913x_fe_state *state)
+{
+	int ret, i, reg;
+	u8 val, nv_val;
+	u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
+	u8 b[2];
+
+	reg = it913x_read_reg_u8(state, 0xec86);
+	switch (reg) {
+	case 0:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 2000;
+		state->tun_fdiv = 3;
+		val = 16;
+		break;
+	case -ENODEV:
+		return -ENODEV;
+	case 1:
+	default:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 640;
+		state->tun_fdiv = 1;
+		val = 6;
+		break;
+	}
+
+	reg = it913x_read_reg_u8(state, 0xed03);
+
+	if (reg < 0)
+		return -ENODEV;
+	else if (reg < sizeof(nv))
+		nv_val = nv[reg];
+	else
+		nv_val = 2;
+
+	for (i = 0; i < 50; i++) {
+		ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b));
+		reg = (b[1] << 8) + b[0];
+		if (reg > 0)
+			break;
+		if (ret < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+	state->tun_fn_min = state->tun_xtal * reg;
+	state->tun_fn_min /= (state->tun_fdiv * nv_val);
+	deb_info("Tuner fn_min %d", state->tun_fn_min);
+
+	for (i = 0; i < 50; i++) {
+		reg = it913x_read_reg_u8(state, 0xec82);
+		if (reg > 0)
+			break;
+		if (reg < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+
+	return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
+}
+
+static int it9137_set_tuner(struct it913x_fe_state *state,
+		enum fe_bandwidth bandwidth, u32 frequency_m)
+{
+	struct it913xset *set_tuner = set_it9137_template;
+	int ret, reg;
+	u32 frequency = frequency_m / 1000;
+	u32 freq, temp_f, tmp;
+	u16 iqik_m_cal;
+	u16 n_div;
+	u8 n;
+	u8 l_band;
+	u8 lna_band;
+	u8 bw;
+
+	deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
+
+	if (frequency >= 51000 && frequency <= 440000) {
+		l_band = 0;
+		lna_band = 0;
+	} else if (frequency > 440000 && frequency <= 484000) {
+		l_band = 1;
+		lna_band = 1;
+	} else if (frequency > 484000 && frequency <= 533000) {
+		l_band = 1;
+		lna_band = 2;
+	} else if (frequency > 533000 && frequency <= 587000) {
+		l_band = 1;
+		lna_band = 3;
+	} else if (frequency > 587000 && frequency <= 645000) {
+		l_band = 1;
+		lna_band = 4;
+	} else if (frequency > 645000 && frequency <= 710000) {
+		l_band = 1;
+		lna_band = 5;
+	} else if (frequency > 710000 && frequency <= 782000) {
+		l_band = 1;
+		lna_band = 6;
+	} else if (frequency > 782000 && frequency <= 860000) {
+		l_band = 1;
+		lna_band = 7;
+	} else if (frequency > 1450000 && frequency <= 1492000) {
+		l_band = 1;
+		lna_band = 0;
+	} else if (frequency > 1660000 && frequency <= 1685000) {
+		l_band = 1;
+		lna_band = 1;
+	} else
+		return -EINVAL;
+	set_tuner[0].reg[0] = lna_band;
+
+	if (bandwidth == BANDWIDTH_5_MHZ)
+		bw = 0;
+	else if (bandwidth == BANDWIDTH_6_MHZ)
+		bw = 2;
+	else if (bandwidth == BANDWIDTH_7_MHZ)
+		bw = 4;
+	else if (bandwidth == BANDWIDTH_8_MHZ)
+		bw = 6;
+	else
+		bw = 6;
+
+	set_tuner[1].reg[0] = bw;
+	set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
+
+	if (frequency > 53000 && frequency <= 74000) {
+		n_div = 48;
+		n = 0;
+	} else if (frequency > 74000 && frequency <= 111000) {
+		n_div = 32;
+		n = 1;
+	} else if (frequency > 111000 && frequency <= 148000) {
+		n_div = 24;
+		n = 2;
+	} else if (frequency > 148000 && frequency <= 222000) {
+		n_div = 16;
+		n = 3;
+	} else if (frequency > 222000 && frequency <= 296000) {
+		n_div = 12;
+		n = 4;
+	} else if (frequency > 296000 && frequency <= 445000) {
+		n_div = 8;
+		n = 5;
+	} else if (frequency > 445000 && frequency <= state->tun_fn_min) {
+		n_div = 6;
+		n = 6;
+	} else if (frequency > state->tun_fn_min && frequency <= 950000) {
+		n_div = 4;
+		n = 7;
+	} else if (frequency > 1450000 && frequency <= 1680000) {
+		n_div = 2;
+		n = 0;
+	} else
+		return -EINVAL;
+
+	reg = it913x_read_reg_u8(state, 0xed81);
+	iqik_m_cal = (u16)reg * n_div;
+
+	if (reg < 0x20) {
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = (iqik_m_cal * 9) >> 5;
+		else
+			iqik_m_cal >>= 1;
+	} else {
+		iqik_m_cal = 0x40 - iqik_m_cal;
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
+		else
+			iqik_m_cal = ~(iqik_m_cal >> 1);
+	}
+
+	temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
+	freq = temp_f / state->tun_xtal;
+	tmp = freq * state->tun_xtal;
+
+	if ((temp_f - tmp) >= (state->tun_xtal >> 1))
+		freq++;
+
+	freq += (u32) n << 13;
+	/* Frequency OMEGA_IQIK_M_CAL_MID*/
+	temp_f = freq + (u32)iqik_m_cal;
+
+	set_tuner[3].reg[0] =  temp_f & 0xff;
+	set_tuner[4].reg[0] =  (temp_f >> 8) & 0xff;
+
+	deb_info("High Frequency = %04x", temp_f);
+
+	/* Lower frequency */
+	set_tuner[5].reg[0] =  freq & 0xff;
+	set_tuner[6].reg[0] =  (freq >> 8) & 0xff;
+
+	deb_info("low Frequency = %04x", freq);
+
+	ret = it913x_fe_script_loader(state, set_tuner);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_select_bw(struct it913x_fe_state *state,
+			enum fe_bandwidth bandwidth, u32 adcFrequency)
+{
+	int ret, i;
+	u8 buffer[256];
+	u32 coeff[8];
+	u16 bfsfcw_fftinx_ratio;
+	u16 fftinx_bfsfcw_ratio;
+	u8 count;
+	u8 bw;
+	u8 adcmultiplier;
+
+	deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
+
+	if (bandwidth == BANDWIDTH_5_MHZ)
+		bw = 3;
+	else if (bandwidth == BANDWIDTH_6_MHZ)
+		bw = 0;
+	else if (bandwidth == BANDWIDTH_7_MHZ)
+		bw = 1;
+	else if (bandwidth == BANDWIDTH_8_MHZ)
+		bw = 2;
+	else
+		bw = 2;
+
+	ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
+
+	if (state->table == NULL)
+		return -EINVAL;
+
+	/* In write order */
+	coeff[0] = state->table[bw].coeff_1_2048;
+	coeff[1] = state->table[bw].coeff_2_2k;
+	coeff[2] = state->table[bw].coeff_1_8191;
+	coeff[3] = state->table[bw].coeff_1_8192;
+	coeff[4] = state->table[bw].coeff_1_8193;
+	coeff[5] = state->table[bw].coeff_2_8k;
+	coeff[6] = state->table[bw].coeff_1_4096;
+	coeff[7] = state->table[bw].coeff_2_4k;
+	bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
+	fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
+
+	/* ADC multiplier */
+	ret = it913x_read_reg_u8(state, ADC_X_2);
+	if (ret < 0)
+		return -EINVAL;
+
+	adcmultiplier = ret;
+
+	count = 0;
+
+	/*  Build Buffer for COEFF Registers */
+	for (i = 0; i < 8; i++) {
+		if (adcmultiplier == 1)
+			coeff[i] /= 2;
+		buffer[count++] = (coeff[i] >> 24) & 0x3;
+		buffer[count++] = (coeff[i] >> 16) & 0xff;
+		buffer[count++] = (coeff[i] >> 8) & 0xff;
+		buffer[count++] = coeff[i] & 0xff;
+	}
+
+	/* bfsfcw_fftinx_ratio register 0x21-0x22 */
+	buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
+	buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
+	/* fftinx_bfsfcw_ratio register 0x23-0x24 */
+	buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
+	buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
+	/* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
+	ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
+
+	for (i = 0; i < 42; i += 8)
+		debug_data_snipet(0x1, "Buffer", &buffer[i]);
+
+	return ret;
+}
+
+
+
+static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret, i;
+	fe_status_t old_status = state->it913x_status;
+	*status = 0;
+
+	if (state->it913x_status == 0) {
+		ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (ret == 0x1) {
+			*status |= FE_HAS_SIGNAL;
+			for (i = 0; i < 40; i++) {
+				ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
+				if (ret == 0x1)
+					break;
+				msleep(25);
+			}
+			if (ret == 0x1)
+				*status |= FE_HAS_CARRIER
+					| FE_HAS_VITERBI
+					| FE_HAS_SYNC;
+			state->it913x_status = *status;
+		}
+	}
+
+	if (state->it913x_status & FE_HAS_SYNC) {
+		ret = it913x_read_reg_u8(state, TPSD_LOCK);
+		if (ret == 0x1)
+			*status |= FE_HAS_LOCK
+				| state->it913x_status;
+		else
+			state->it913x_status = 0;
+		if (old_status != state->it913x_status)
+			ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
+	}
+
+	return 0;
+}
+
+static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
+		u16 *strength)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
+	/*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/
+	if (state->it913x_status & FE_HAS_SIGNAL)
+		ret = (ret * 0xff) / 0x64;
+	else
+		ret = 0x0;
+	ret |= ret << 0x8;
+	*strength = ret;
+	return 0;
+}
+
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
+	ret = (ret * 0xff) / 0x64;
+	ret |= (ret << 0x8);
+	*snr = ~ret;
+	return 0;
+}
+
+static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int it913x_fe_get_frontend(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret;
+	u8 reg[8];
+
+	ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
+
+	if (reg[3] < 3)
+		p->u.ofdm.constellation = fe_con[reg[3]];
+
+	if (reg[0] < 3)
+		p->u.ofdm.transmission_mode = fe_mode[reg[0]];
+
+	if (reg[1] < 4)
+		p->u.ofdm.guard_interval = fe_gi[reg[1]];
+
+	if (reg[2] < 4)
+		p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
+
+	p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+	p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+
+	return 0;
+}
+
+static int it913x_fe_set_frontend(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret, i;
+	u8 empty_ch, last_ch;
+
+	state->it913x_status = 0;
+
+	/* Set bw*/
+	ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
+		state->adcFrequency);
+
+	/* Training Mode Off */
+	ret = it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
+
+	/* Clear Empty Channel */
+	ret = it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
+
+	/* Clear bits */
+	ret = it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
+	/* LED on */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+	/* Select Band*/
+	if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
+		i = 0;
+	else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
+			i = 1;
+	else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
+			i = 2;
+		else
+			return -EOPNOTSUPP;
+
+	ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
+
+	deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
+	switch (state->tuner_type) {
+	case IT9137: /* Tuner type 0x38 */
+		ret = it9137_set_tuner(state,
+			p->u.ofdm.bandwidth, p->frequency);
+		break;
+	default:
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe, p);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		break;
+	}
+	/* LED off */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+	/* Trigger ofsm */
+	ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+	last_ch = 2;
+	for (i = 0; i < 40; ++i) {
+		empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (last_ch == 1 && empty_ch == 1)
+			break;
+		if (last_ch == 2 && empty_ch == 2)
+			return 0;
+		last_ch = empty_ch;
+		msleep(25);
+	}
+	for (i = 0; i < 40; ++i) {
+		if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
+			break;
+		msleep(25);
+	}
+
+	state->frequency = p->frequency;
+	return 0;
+}
+
+static int it913x_fe_suspend(struct it913x_fe_state *state)
+{
+	int ret, i;
+	u8 b;
+
+	ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+
+	for (i = 0; i < 128; i++) {
+		ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
+		if (ret < 0)
+			return -ENODEV;
+		if (b == 0)
+			break;
+
+	}
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
+	/* Turn LED off */
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+
+	ret |= it913x_fe_script_loader(state, it9137_tuner_off);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+/* Power sequence */
+/* Power Up	Tuner on -> Frontend suspend off -> Tuner clk on */
+/* Power Down	Frontend suspend on -> Tuner clk off -> Tuner off */
+
+static int it913x_fe_sleep(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	return it913x_fe_suspend(state);
+}
+
+static u32 compute_div(u32 a, u32 b, u32 x)
+{
+	u32 res = 0;
+	u32 c = 0;
+	u32 i = 0;
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			res += 1;
+			a -= b;
+		}
+		a <<= 1;
+		res <<= 1;
+	}
+
+	res = (c << x) + res;
+
+	return res;
+}
+
+static int it913x_fe_start(struct it913x_fe_state *state)
+{
+	struct it913xset *set_fe;
+	struct it913xset *set_mode;
+	int ret;
+	u8 adf = (state->adf & 0xf);
+	u32 adc, xtal;
+	u8 b[4];
+
+	ret = it913x_init_tuner(state);
+
+	if (adf < 12) {
+		state->crystalFrequency = fe_clockTable[adf].xtal ;
+		state->table = fe_clockTable[adf].table;
+		state->adcFrequency = state->table->adcFrequency;
+
+		adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
+		xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
+
+	} else
+		return -EINVAL;
+
+	deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
+		state->crystalFrequency, state->adcFrequency, adc, xtal);
+
+	/* Set LED indicator on GPIOH3 */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
+
+	b[0] = xtal & 0xff;
+	b[1] = (xtal >> 8) & 0xff;
+	b[2] = (xtal >> 16) & 0xff;
+	b[3] = (xtal >> 24);
+	ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
+
+	b[0] = adc & 0xff;
+	b[1] = (adc >> 8) & 0xff;
+	b[2] = (adc >> 16) & 0xff;
+	ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
+
+	switch (state->tuner_type) {
+	case IT9137: /* Tuner type 0x38 */
+		set_fe = it9137_set;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set the demod */
+	ret = it913x_fe_script_loader(state, set_fe);
+	/* Always solo frontend */
+	set_mode = set_solo_fe;
+	ret |= it913x_fe_script_loader(state, set_mode);
+
+	ret |= it913x_fe_suspend(state);
+	return 0;
+}
+
+static int it913x_fe_init(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = 0;
+	/* Power Up Tuner - common all versions */
+	ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+	ret |= it913x_fe_script_loader(state, init_1);
+
+	switch (state->tuner_type) {
+	case IT9137:
+		ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static void it913x_fe_release(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops;
+
+struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+		u8 i2c_addr, u8 adf, u8 type)
+{
+	struct it913x_fe_state *state = NULL;
+	int ret;
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->i2c_adap = i2c_adap;
+	state->i2c_addr = i2c_addr;
+	state->adf = adf;
+	state->tuner_type = type;
+
+	ret = it913x_fe_start(state);
+	if (ret < 0)
+		goto error;
+
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(it913x_fe_attach);
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
+
+	.info = {
+		.name			= "it913x-fe DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 51000000,
+		.frequency_max		= 1680000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = it913x_fe_release,
+
+	.init = it913x_fe_init,
+	.sleep = it913x_fe_sleep,
+
+	.set_frontend = it913x_fe_set_frontend,
+	.get_frontend = it913x_fe_get_frontend,
+
+	.read_status = it913x_fe_read_status,
+	.read_signal_strength = it913x_fe_read_signal_strength,
+	.read_snr = it913x_fe_read_snr,
+	.read_ber = it913x_fe_read_ber,
+	.read_ucblocks = it913x_fe_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
+MODULE_VERSION("1.07");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,196 @@
+/*
+ *  Driver for it913x Frontend
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef IT913X_FE_H
+#define IT913X_FE_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
+defined(MODULE))
+extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+			u8 i2c_addr, u8 adf, u8 type);
+#else
+static inline struct dvb_frontend *it913x_fe_attach(
+		struct i2c_adapter *i2c_adap,	u8 i2c_addr, u8 adf, u8 type)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_IT913X_FE */
+#define I2C_BASE_ADDR		0x10
+#define DEV_0			0x0
+#define DEV_1			0x10
+#define PRO_LINK		0x0
+#define PRO_DMOD		0x1
+#define DEV_0_DMOD		(PRO_DMOD << 0x7)
+#define DEV_1_DMOD		(DEV_0_DMOD | DEV_1)
+#define CHIP2_I2C_ADDR		0x3a
+
+#define AFE_MEM0		0xfb24
+
+#define MP2_SW_RST		0xf99d
+#define MP2IF2_SW_RST		0xf9a4
+
+#define	PADODPU			0xd827
+#define THIRDODPU		0xd828
+#define AGC_O_D			0xd829
+
+#define EP0_TX_EN		0xdd11
+#define EP0_TX_NAK		0xdd13
+#define EP4_TX_LEN_LSB		0xdd88
+#define EP4_TX_LEN_MSB		0xdd89
+#define EP4_MAX_PKT		0xdd0c
+#define EP5_TX_LEN_LSB		0xdd8a
+#define EP5_TX_LEN_MSB		0xdd8b
+#define EP5_MAX_PKT		0xdd0d
+
+#define IO_MUX_POWER_CLK	0xd800
+#define CLK_O_EN		0xd81a
+#define I2C_CLK			0xf103
+#define I2C_CLK_100		0x7
+#define I2C_CLK_400		0x1a
+
+#define D_TPSD_LOCK		0xf5a9
+#define MP2IF2_EN		0xf9a3
+#define MP2IF_SERIAL		0xf985
+#define TSIS_ENABLE		0xf9cd
+#define MP2IF2_HALF_PSB		0xf9a5
+#define MP2IF_STOP_EN		0xf9b5
+#define MPEG_FULL_SPEED		0xf990
+#define TOP_HOSTB_SER_MODE	0xd91c
+
+#define PID_RST			0xf992
+#define PID_EN			0xf993
+#define PID_INX_EN		0xf994
+#define PID_INX			0xf995
+#define PID_LSB			0xf996
+#define PID_MSB			0xf997
+
+#define MP2IF_MPEG_PAR_MODE	0xf986
+#define DCA_UPPER_CHIP		0xf731
+#define DCA_LOWER_CHIP		0xf732
+#define DCA_PLATCH		0xf730
+#define DCA_FPGA_LATCH		0xf778
+#define DCA_STAND_ALONE		0xf73c
+#define DCA_ENABLE		0xf776
+
+#define DVBT_INTEN		0xf41f
+#define DVBT_ENABLE		0xf41a
+#define HOSTB_DCA_LOWER		0xd91f
+#define HOSTB_MPEG_PAR_MODE	0xd91b
+#define HOSTB_MPEG_SER_MODE	0xd91c
+#define HOSTB_MPEG_SER_DO7	0xd91d
+#define HOSTB_DCA_UPPER		0xd91e
+#define PADMISCDR2		0xd830
+#define PADMISCDR4		0xd831
+#define PADMISCDR8		0xd832
+#define PADMISCDRSR		0xd833
+#define LOCK3_OUT		0xd8fd
+
+#define GPIOH1_O		0xd8af
+#define GPIOH1_EN		0xd8b0
+#define GPIOH1_ON		0xd8b1
+#define GPIOH3_O		0xd8b3
+#define GPIOH3_EN		0xd8b4
+#define GPIOH3_ON		0xd8b5
+#define GPIOH5_O		0xd8bb
+#define GPIOH5_EN		0xd8bc
+#define GPIOH5_ON		0xd8bd
+
+#define AFE_MEM0		0xfb24
+
+#define REG_TPSD_TX_MODE	0xf900
+#define REG_TPSD_GI		0xf901
+#define REG_TPSD_HIER		0xf902
+#define REG_TPSD_CONST		0xf903
+#define REG_BW			0xf904
+#define REG_PRIV		0xf905
+#define REG_TPSD_HP_CODE	0xf906
+#define REG_TPSD_LP_CODE	0xf907
+
+#define MP2IF_SYNC_LK		0xf999
+#define ADC_FREQ		0xf1cd
+
+#define TRIGGER_OFSM		0x0000
+/* COEFF Registers start at 0x0001 to 0x0020 */
+#define COEFF_1_2048		0x0001
+#define XTAL_CLK		0x0025
+#define BFS_FCW			0x0029
+#define TPSD_LOCK		0x003c
+#define TRAINING_MODE		0x0040
+#define ADC_X_2			0x0045
+#define TUNER_ID		0x0046
+#define EMPTY_CHANNEL_STATUS	0x0047
+#define SIGNAL_LEVEL		0x0048
+#define SIGNAL_QUALITY		0x0049
+#define EST_SIGNAL_LEVEL	0x004a
+#define FREE_BAND		0x004b
+#define SUSPEND_FLAG		0x004c
+/* Build in tuners */
+#define IT9137 0x38
+
+enum {
+	CMD_DEMOD_READ = 0,
+	CMD_DEMOD_WRITE,
+	CMD_TUNER_READ,
+	CMD_TUNER_WRITE,
+	CMD_REG_EEPROM_READ,
+	CMD_REG_EEPROM_WRITE,
+	CMD_DATA_READ,
+	CMD_VAR_READ = 8,
+	CMD_VAR_WRITE,
+	CMD_PLATFORM_GET,
+	CMD_PLATFORM_SET,
+	CMD_IP_CACHE,
+	CMD_IP_ADD,
+	CMD_IP_REMOVE,
+	CMD_PID_ADD,
+	CMD_PID_REMOVE,
+	CMD_SIPSI_GET,
+	CMD_SIPSI_MPE_RESET,
+	CMD_H_PID_ADD = 0x15,
+	CMD_H_PID_REMOVE,
+	CMD_ABORT,
+	CMD_IR_GET,
+	CMD_IR_SET,
+	CMD_FW_DOWNLOAD = 0x21,
+	CMD_QUERYINFO,
+	CMD_BOOT,
+	CMD_FW_DOWNLOAD_BEGIN,
+	CMD_FW_DOWNLOAD_END,
+	CMD_RUN_CODE,
+	CMD_SCATTER_READ = 0x28,
+	CMD_SCATTER_WRITE,
+	CMD_GENERIC_READ,
+	CMD_GENERIC_WRITE
+};
+
+enum {
+	READ_LONG,
+	WRITE_LONG,
+	READ_SHORT,
+	WRITE_SHORT,
+	READ_DATA,
+	WRITE_DATA,
+	WRITE_CMD,
+};
+
+#endif /* IT913X_FE_H */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe-priv.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe-priv.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/it913x-fe-priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/it913x-fe-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,336 @@
+
+struct it913xset {	u32 pro;
+			u32 address;
+			u8 reg[15];
+			u8 count;
+};
+
+struct adctable {	u32 adcFrequency;
+			u32 bandwidth;
+			u32 coeff_1_2048;
+			u32 coeff_1_4096;
+			u32 coeff_1_8191;
+			u32 coeff_1_8192;
+			u32 coeff_1_8193;
+			u32 coeff_2_2k;
+			u32 coeff_2_4k;
+			u32 coeff_2_8k;
+			u16 bfsfcw_fftinx_ratio;
+			u16 fftinx_bfsfcw_ratio;
+};
+
+/* clock and coeff tables only table 3 is used with IT9137*/
+/* TODO other tables relate AF9035 may be removed */
+static struct adctable tab1[] = {
+	{	20156250, BANDWIDTH_6_MHZ,
+		0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
+		0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c	},
+	{	20156250, BANDWIDTH_7_MHZ,
+		0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
+		0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196	},
+	{	20156250, BANDWIDTH_8_MHZ,
+		0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
+		0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0	},
+	{	20156250, BANDWIDTH_5_MHZ,
+		0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
+		0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122	}
+};
+
+static struct adctable tab2[] = {
+	{	20187500, BANDWIDTH_6_MHZ,
+		0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
+		0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c	},
+	{	20187500, BANDWIDTH_7_MHZ,
+		0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
+		0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196	},
+	{	20187500, BANDWIDTH_8_MHZ,
+		0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
+		0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0	},
+	{	20187500, BANDWIDTH_5_MHZ,
+		0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
+		0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122	}
+
+};
+
+static struct adctable tab3[] = {
+	{	20250000, BANDWIDTH_6_MHZ,
+		0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
+		0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b	},
+	{	20250000, BANDWIDTH_7_MHZ,
+		0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
+		0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195	},
+	{	20250000, BANDWIDTH_8_MHZ,
+		0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
+		0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce	},
+	{	20250000, BANDWIDTH_5_MHZ,
+		0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
+		0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121	}
+
+};
+
+static struct adctable tab4[] = {
+	{	20583333, BANDWIDTH_6_MHZ,
+		0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
+		0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155	},
+	{	20583333, BANDWIDTH_7_MHZ,
+		0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
+		0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e	},
+	{	20583333, BANDWIDTH_8_MHZ,
+		0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
+		0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7	},
+	{	20583333, BANDWIDTH_5_MHZ,
+		0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
+		0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c	}
+
+};
+
+static struct adctable tab5[] = {
+	{	20416667, BANDWIDTH_6_MHZ,
+		0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
+		0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158	},
+	{	20416667, BANDWIDTH_7_MHZ,
+		0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
+		0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191	},
+	{	20416667, BANDWIDTH_8_MHZ,
+		0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
+		0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb	},
+	{	20416667, BANDWIDTH_5_MHZ,
+		0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
+		0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f	}
+
+};
+
+static struct adctable tab6[] = {
+	{	20480000, BANDWIDTH_6_MHZ,
+		0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
+		0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157	},
+	{	20480000, BANDWIDTH_7_MHZ,
+		0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
+		0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190	},
+	{	20480000, BANDWIDTH_8_MHZ,
+		0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
+		0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9	},
+	{	20480000, BANDWIDTH_5_MHZ,
+		0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
+		0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e	}
+};
+
+static struct adctable tab7[] = {
+	{	20500000, BANDWIDTH_6_MHZ,
+		0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
+		0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157	},
+	{	20500000, BANDWIDTH_7_MHZ,
+		0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
+		0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190	},
+	{	20500000, BANDWIDTH_8_MHZ,
+		0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
+		0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9	},
+	{	20500000, BANDWIDTH_5_MHZ,
+		0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
+		0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d	}
+
+};
+
+static struct adctable tab8[] = {
+	{	20625000, BANDWIDTH_6_MHZ,
+		0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
+		0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154	},
+	{	20625000, BANDWIDTH_7_MHZ,
+		0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
+		0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d	},
+	{	20625000, BANDWIDTH_8_MHZ,
+		0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
+		0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6	},
+	{	20625000, BANDWIDTH_5_MHZ,
+		0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
+		0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c	}
+
+};
+
+struct table {
+		u32 xtal;
+		struct adctable *table;
+};
+
+static struct table fe_clockTable[] = {
+		{12000000, tab3},	/* FPGA     */
+		{16384000, tab6},	/* 16.38MHz */
+		{20480000, tab6},	/* 20.48MHz */
+		{36000000, tab3},	/* 36.00MHz */
+		{30000000, tab1},	/* 30.00MHz */
+		{26000000, tab4},	/* 26.00MHz */
+		{28000000, tab5},	/* 28.00MHz */
+		{32000000, tab7},	/* 32.00MHz */
+		{34000000, tab2},	/* 34.00MHz */
+		{24000000, tab1},	/* 24.00MHz */
+		{22000000, tab8},	/* 22.00MHz */
+		{12000000, tab3}	/* 12.00MHz */
+};
+
+/* fe get */
+fe_code_rate_t fe_code[] = {
+	FEC_1_2,
+	FEC_2_3,
+	FEC_3_4,
+	FEC_5_6,
+	FEC_7_8,
+	FEC_NONE,
+};
+
+fe_guard_interval_t fe_gi[] = {
+	GUARD_INTERVAL_1_32,
+	GUARD_INTERVAL_1_16,
+	GUARD_INTERVAL_1_8,
+	GUARD_INTERVAL_1_4,
+};
+
+fe_hierarchy_t fe_hi[] = {
+	HIERARCHY_NONE,
+	HIERARCHY_1,
+	HIERARCHY_2,
+	HIERARCHY_4,
+};
+
+fe_transmit_mode_t fe_mode[] = {
+	TRANSMISSION_MODE_2K,
+	TRANSMISSION_MODE_8K,
+	TRANSMISSION_MODE_4K,
+};
+
+fe_modulation_t fe_con[] = {
+	QPSK,
+	QAM_16,
+	QAM_64,
+};
+
+/* Standard demodulator functions */
+static struct it913xset set_solo_fe[] = {
+	{PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
+	{PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_SER_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, DCA_UPPER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_UPPER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_LOWER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_LOWER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_PLATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_FPGA_LATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_STAND_ALONE, {0x01}, 0x01},
+	{PRO_DMOD, DCA_ENABLE, {0x00}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, BFS_FCW, {0x00, 0x00, 0x00}, 0x03},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+
+static struct it913xset init_1[] = {
+	{PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+	{PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
+	{PRO_LINK, PADMISCDR8, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* ---------IT9137 0x38 tuner init---------- */
+static struct it913xset it9137_set[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x38}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
+				0xd0, 0xc3, 0x01	}, 0x0a},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x32}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
+				0x00, 0x02, 0xc8, 0x05, 0x7b	}, 0x0c},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+	{PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04},
+	{PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
+	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f	}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset it9137_tuner_off[] = {
+	{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
+	{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
+	{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+	{PRO_DMOD, 0xec3f, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9137_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4f, {0x00}, 0x01},
+	{PRO_DMOD, 0xec50, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/Kconfig linux-libre-3.2-gnu1/drivers/media/dvb/frontends/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -236,6 +236,13 @@ config DVB_MB86A16
 	  A DVB-S/DSS Direct Conversion reveiver.
 	  Say Y when you want to support this frontend.
 
+config DVB_TDA10071
+	tristate "NXP TDA10071"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Say Y when you want to support this frontend.
+
 comment "DVB-T (terrestrial) frontends"
 	depends on DVB_CORE
 
@@ -600,6 +607,16 @@ config DVB_LNBP21
 	help
 	  An SEC control chips.
 
+config DVB_LNBP22
+	tristate "LNBP22 SEC controllers"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  LNB power supply and control voltage
+	  regulator chip with step-up converter
+	  and I2C interface.
+	  Say Y when you want to support this chip.
+
 config DVB_ISL6405
 	tristate "ISL6405 SEC controller"
 	depends on DVB_CORE && I2C
@@ -621,6 +638,11 @@ config DVB_ISL6423
 	help
 	  A SEC controller chip from Intersil
 
+config DVB_A8293
+	tristate "Allegro A8293"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+
 config DVB_LGS8GL5
 	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
 	depends on DVB_CORE && I2C
@@ -661,6 +683,14 @@ config DVB_IX2505V
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_IT913X_FE
+	tristate "it913x frontend and it9137 tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-T tuner module.
+	  Say Y when you want to support this frontend.
+
 comment "Tools to develop new frontends"
 
 config DVB_DUMMY_FE
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/lnbp22.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/lnbp22.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/lnbp22.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/lnbp22.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21 driver
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp22.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+
+#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
+
+struct lnbp22 {
+	u8		    config[4];
+	struct i2c_adapter *i2c;
+};
+
+static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
+	       SEC_VOLTAGE_18, SEC_VOLTAGE_13);
+
+	lnbp22->config[3] = 0x60; /* Power down */
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp22->config[3] |= LNBP22_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d\n", __func__, (int)arg);
+	if (arg)
+		lnbp22->config[3] |= LNBP22_LLC;
+	else
+		lnbp22->config[3] &= ~LNBP22_LLC;
+
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp22_release(struct dvb_frontend *fe)
+{
+	dprintk(1, "%s\n", __func__);
+	/* LNBP power off */
+	lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+					struct i2c_adapter *i2c)
+{
+	struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
+	if (!lnbp22)
+		return NULL;
+
+	/* default configuration */
+	lnbp22->config[0] = 0x00; /* ? */
+	lnbp22->config[1] = 0x28; /* ? */
+	lnbp22->config[2] = 0x48; /* ? */
+	lnbp22->config[3] = 0x60; /* Power down */
+	lnbp22->i2c = i2c;
+	fe->sec_priv = lnbp22;
+
+	/* detect if it is present or not */
+	if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		dprintk(0, "%s LNBP22 not found\n", __func__);
+		kfree(lnbp22);
+		fe->sec_priv = NULL;
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = lnbp22_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp22_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
+
+	return fe;
+}
+EXPORT_SYMBOL(lnbp22_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
+MODULE_AUTHOR("Dominik Kuhlen");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/lnbp22.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/lnbp22.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/lnbp22.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/lnbp22.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,57 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _LNBP22_H
+#define _LNBP22_H
+
+/* Enable */
+#define LNBP22_EN	  0x10
+/* Voltage selection */
+#define LNBP22_VSEL	0x02
+/* Plus 1 Volt Bit */
+#define LNBP22_LLC	0x01
+
+#include <linux/dvb/frontend.h>
+
+#if defined(CONFIG_DVB_LNBP22) || \
+		(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
+/*
+ * override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LNBP22 */
+
+#endif /* _LNBP22_H */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/frontends/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB frontend device drivers.
 #
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/common/tuners/
 
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
@@ -52,6 +52,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
 obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
@@ -91,4 +92,7 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
+obj-$(CONFIG_DVB_A8293) += a8293.o
+obj-$(CONFIG_DVB_TDA10071) += tda10071.o
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stb0899_algo.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stb0899_algo.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stb0899_algo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stb0899_algo.c	2012-01-04 18:55:44.000000000 -0500
@@ -358,6 +358,9 @@ static enum stb0899_status stb0899_check
 	else
 		dataTime = 500;
 
+	/* clear previous failed END_LOOPVIT */
+	stb0899_read_reg(state, STB0899_VSTATUS);
+
 	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
 	while (1) {
 		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stb0899_drv.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stb0899_drv.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stb0899_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stb0899_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -706,7 +706,7 @@ static int stb0899_send_diseqc_msg(struc
 	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
 	for (i = 0; i < cmd->msg_len; i++) {
 		/* wait for FIFO empty	*/
-		if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+		if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
 			return -ETIMEDOUT;
 
 		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
@@ -1426,9 +1426,9 @@ static void stb0899_set_iterations(struc
 	if (iter_scale > config->ldpc_max_iter)
 		iter_scale = config->ldpc_max_iter;
 
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+	reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
 	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+	stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
 }
 
 static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stv0288.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stv0288.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stv0288.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stv0288.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,6 +127,11 @@ static int stv0288_set_symbolrate(struct
 	if ((srate < 1000000) || (srate > 45000000))
 		return -EINVAL;
 
+	stv0288_writeregI(state, 0x22, 0);
+	stv0288_writeregI(state, 0x23, 0);
+	stv0288_writeregI(state, 0x2b, 0xff);
+	stv0288_writeregI(state, 0x2c, 0xf7);
+
 	temp = (unsigned int)srate / 1000;
 
 		temp = temp * 32768;
@@ -461,6 +466,7 @@ static int stv0288_set_frontend(struct d
 
 	char tm;
 	unsigned char tda[3];
+	u8 reg, time_out = 0;
 
 	dprintk("%s : FE_SET_FRONTEND\n", __func__);
 
@@ -488,22 +494,29 @@ static int stv0288_set_frontend(struct d
 	/* Carrier lock control register */
 	stv0288_writeregI(state, 0x15, 0xc5);
 
-	tda[0] = 0x2b; /* CFRM */
 	tda[2] = 0x0; /* CFRL */
-	for (tm = -6; tm < 7;) {
+	for (tm = -9; tm < 7;) {
 		/* Viterbi status */
-		if (stv0288_readreg(state, 0x24) & 0x8)
-			break;
-
-		tda[2] += 40;
-		if (tda[2] < 40)
+		reg = stv0288_readreg(state, 0x24);
+		if (reg & 0x8)
+				break;
+		if (reg & 0x80) {
+			time_out++;
+			if (time_out > 10)
+				break;
+			tda[2] += 40;
+			if (tda[2] < 40)
+				tm++;
+		} else {
 			tm++;
+			tda[2] = 0;
+			time_out = 0;
+		}
 		tda[1] = (unsigned char)tm;
 		stv0288_writeregI(state, 0x2b, tda[1]);
 		stv0288_writeregI(state, 0x2c, tda[2]);
 		udelay(30);
 	}
-
 	state->tuner_frequency = c->frequency;
 	state->fec_inner = FEC_AUTO;
 	state->symbol_rate = c->symbol_rate;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stv090x.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stv090x.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/stv090x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/stv090x.c	2012-01-04 18:55:44.000000000 -0500
@@ -3463,9 +3463,15 @@ static enum dvbfe_search stv090x_search(
 static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
 {
 	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
+	u32 reg, dstatus;
 	u8 search_state;
 
+	*status = 0;
+
+	dstatus = STV090x_READ_DEMOD(state, DSTATUS);
+	if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
 	reg = STV090x_READ_DEMOD(state, DMDSTATE);
 	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
 
@@ -3474,41 +3480,30 @@ static int stv090x_read_status(struct dv
 	case 1: /* first PLH detected */
 	default:
 		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
-		*status = 0;
 		break;
 
 	case 2: /* DVB-S2 mode */
 		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
 			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
 			if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
+				*status |= FE_HAS_VITERBI;
 				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-					*status = FE_HAS_SIGNAL |
-						  FE_HAS_CARRIER |
-						  FE_HAS_VITERBI |
-						  FE_HAS_SYNC |
-						  FE_HAS_LOCK;
-				}
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
 			}
 		}
 		break;
 
 	case 3: /* DVB-S1/legacy mode */
 		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
 			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
 			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+				*status |= FE_HAS_VITERBI;
 				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-					*status = FE_HAS_SIGNAL |
-						  FE_HAS_CARRIER |
-						  FE_HAS_VITERBI |
-						  FE_HAS_SYNC |
-						  FE_HAS_LOCK;
-				}
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
 			}
 		}
 		break;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10048.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10048.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10048.c	2013-05-02 01:35:06.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10048.c	2013-05-01 23:43:12.000000000 -0400
@@ -206,15 +206,16 @@ static struct init_tab {
 static struct pll_tab {
 	u32	clk_freq_khz;
 	u32	if_freq_khz;
-	u8	m, n, p;
 } pll_tab[] = {
-	{ TDA10048_CLK_4000,  TDA10048_IF_36130, 10, 0, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3300,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3500,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3800,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4000,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4300,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+	{ TDA10048_CLK_4000,  TDA10048_IF_36130 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3800 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_5000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_36130 },
 };
 
 static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
@@ -460,9 +461,6 @@ static int tda10048_set_if(struct dvb_fr
 
 			state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
 			state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
-			state->pll_mfactor = pll_tab[i].m;
-			state->pll_nfactor = pll_tab[i].n;
-			state->pll_pfactor = pll_tab[i].p;
 			break;
 		}
 	}
@@ -781,6 +779,10 @@ static int tda10048_init(struct dvb_fron
 
 	dprintk(1, "%s()\n", __func__);
 
+	/* PLL */
+	init_tab[4].data = (u8)(state->pll_mfactor);
+	init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
+
 	/* Apply register defaults */
 	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
 		tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
@@ -1123,7 +1125,7 @@ struct dvb_frontend *tda10048_attach(con
 	/* setup the state and clone the config */
 	memcpy(&state->config, config, sizeof(*config));
 	state->i2c = i2c;
-	state->fwloaded = 0;
+	state->fwloaded = config->no_firmware;
 	state->bandwidth = BANDWIDTH_8_MHZ;
 
 	/* check if the demod is present */
@@ -1135,6 +1137,17 @@ struct dvb_frontend *tda10048_attach(con
 		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
+	/* set pll */
+	if (config->set_pll) {
+		state->pll_mfactor = config->pll_m;
+		state->pll_nfactor = config->pll_n;
+		state->pll_pfactor = config->pll_p;
+	} else {
+		state->pll_mfactor = 10;
+		state->pll_nfactor = 3;
+		state->pll_pfactor = 0;
+	}
+
 	/* Establish any defaults the the user didn't pass */
 	tda10048_establish_defaults(&state->frontend);
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10048.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10048.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10048.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10048.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,7 @@ struct tda10048_config {
 #define TDA10048_IF_4300  4300
 #define TDA10048_IF_4500  4500
 #define TDA10048_IF_4750  4750
+#define TDA10048_IF_5000  5000
 #define TDA10048_IF_36130 36130
 	u16 dtv6_if_freq_khz;
 	u16 dtv7_if_freq_khz;
@@ -62,6 +63,13 @@ struct tda10048_config {
 
 	/* Disable I2C gate access */
 	u8 disable_gate_access;
+
+	bool no_firmware;
+
+	bool set_pll;
+	u8 pll_m;
+	u8 pll_p;
+	u8 pll_n;
 };
 
 #if defined(CONFIG_DVB_TDA10048) || \
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071.c	2013-05-01 23:43:14.000000000 -0400
@@ -0,0 +1,1269 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tda10071_priv.h"
+
+int tda10071_debug;
+module_param_named(debug, tda10071_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+static struct dvb_frontend_ops tda10071_ops;
+
+/* write multiple registers */
+static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg.i2c_address,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write single register */
+static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val)
+{
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
+{
+	return tda10071_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+/* execute firmware command */
+static int tda10071_cmd_execute(struct tda10071_priv *priv,
+	struct tda10071_cmd *cmd)
+{
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	/* write cmd and args for firmware */
+	ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len);
+	if (ret)
+		goto error;
+
+	/* start cmd execution */
+	ret = tda10071_wr_reg(priv, 0x1f, 1);
+	if (ret)
+		goto error;
+
+	/* wait cmd execution terminate */
+	for (i = 1000, tmp = 1; i && tmp; i--) {
+		ret = tda10071_rd_reg(priv, 0x1f, &tmp);
+		if (ret)
+			goto error;
+
+		usleep_range(200, 5000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_tone(struct dvb_frontend *fe,
+	fe_sec_tone_mode_t fe_sec_tone_mode)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tone;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: tone_mode=%d", __func__, fe_sec_tone_mode);
+
+	switch (fe_sec_tone_mode) {
+	case SEC_TONE_ON:
+		tone = 1;
+		break;
+	case SEC_TONE_OFF:
+		tone = 0;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_tone_mode", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_LNB_PCB_CONFIG;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 0x00;
+	cmd.args[0x03] = 0x00;
+	cmd.args[0x04] = tone;
+	cmd.len = 0x05;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 voltage;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: voltage=%d", __func__, fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_13:
+		voltage = 0;
+		break;
+	case SEC_VOLTAGE_18:
+		voltage = 1;
+		break;
+	case SEC_VOLTAGE_OFF:
+		voltage = 0;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_voltage", __func__);
+		ret = -EINVAL;
+		goto error;
+	};
+
+	cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = voltage;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *diseqc_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: msg_len=%d", __func__, diseqc_cmd->msg_len);
+
+	if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 16) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_LNB_SEND_DISEQC;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 0;
+	cmd.args[0x03] = 0;
+	cmd.args[0x04] = 2;
+	cmd.args[0x05] = 0;
+	cmd.args[0x06] = diseqc_cmd->msg_len;
+	memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len);
+	cmd.len = 0x07 + diseqc_cmd->msg_len;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
+	struct dvb_diseqc_slave_reply *reply)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s:", __func__);
+
+	/* wait LNB RX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	/* reply len */
+	ret = tda10071_rd_reg(priv, 0x46, &tmp);
+	if (ret)
+		goto error;
+
+	reply->msg_len = tmp & 0x1f; /* [4:0] */;
+	if (reply->msg_len > sizeof(reply->msg))
+		reply->msg_len = sizeof(reply->msg); /* truncate API max */
+
+	/* read reply */
+	cmd.args[0x00] = CMD_LNB_UPDATE_REPLY;
+	cmd.args[0x01] = 0;
+	cmd.len = 0x02;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t fe_sec_mini_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp, burst;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: fe_sec_mini_cmd=%d", __func__, fe_sec_mini_cmd);
+
+	switch (fe_sec_mini_cmd) {
+	case SEC_MINI_A:
+		burst = 0;
+		break;
+	case SEC_MINI_B:
+		burst = 1;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_mini_cmd", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_LNB_SEND_TONEBURST;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = burst;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	*status = 0;
+
+	if (!priv->warm) {
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_reg(priv, 0x39, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp & 0x01) /* tuner PLL */
+		*status |= FE_HAS_SIGNAL;
+	if (tmp & 0x02) /* demod PLL */
+		*status |= FE_HAS_CARRIER;
+	if (tmp & 0x04) /* viterbi or LDPC*/
+		*status |= FE_HAS_VITERBI;
+	if (tmp & 0x08) /* RS or BCH */
+		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+	priv->fe_status = *status;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*snr = 0;
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x3a, buf, 2);
+	if (ret)
+		goto error;
+
+	/* Es/No dBx10 */
+	*snr = buf[0] << 8 | buf[1];
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*strength = 0;
+		ret = 0;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_GET_AGCACC;
+	cmd.args[0x01] = 0;
+	cmd.len = 0x02;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	/* input power estimate dBm */
+	ret = tda10071_rd_reg(priv, 0x50, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp < 181)
+		tmp = 181; /* -75 dBm */
+	else if (tmp > 236)
+		tmp = 236; /* -20 dBm */
+
+	/* scale value to 0x0000-0xffff */
+	*strength = (tmp-181) * 0xffff / (236-181);
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len;
+	u8 tmp, reg, buf[8];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ber = priv->ber = 0;
+		ret = 0;
+		goto error;
+	}
+
+	switch (priv->delivery_system) {
+	case SYS_DVBS:
+		reg = 0x4c;
+		len = 8;
+		i = 1;
+		break;
+	case SYS_DVBS2:
+		reg = 0x4d;
+		len = 4;
+		i = 0;
+		break;
+	default:
+		*ber = priv->ber = 0;
+		return 0;
+	}
+
+	ret = tda10071_rd_reg(priv, reg, &tmp);
+	if (ret)
+		goto error;
+
+	if (priv->meas_count[i] == tmp) {
+		dbg("%s: meas not ready=%02x", __func__, tmp);
+		*ber = priv->ber;
+		return 0;
+	} else {
+		priv->meas_count[i] = tmp;
+	}
+
+	cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = i;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, buf, len);
+	if (ret)
+		goto error;
+
+	if (priv->delivery_system == SYS_DVBS) {
+		*ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+		priv->ucb += (buf[4] << 8) | buf[5];
+	} else {
+		*ber = (buf[0] << 8) | buf[1];
+	}
+	priv->ber = *ber;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret = 0;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ucblocks = 0;
+		goto error;
+	}
+
+	/* UCB is updated when BER is read. Assume BER is read anyway. */
+
+	*ucblocks = priv->ucb;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 mode, rolloff, pilot, inversion, div;
+
+	dbg("%s: delivery_system=%d modulation=%d frequency=%d " \
+		"symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__,
+		c->delivery_system, c->modulation, c->frequency,
+		c->symbol_rate, c->inversion, c->pilot, c->rolloff);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	switch (c->inversion) {
+	case INVERSION_OFF:
+		inversion = 1;
+		break;
+	case INVERSION_ON:
+		inversion = 0;
+		break;
+	case INVERSION_AUTO:
+		/* 2 = auto; try first on then off
+		 * 3 = auto; try first off then on */
+		inversion = 3;
+		break;
+	default:
+		dbg("%s: invalid inversion", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		rolloff = 0;
+		pilot = 2;
+		break;
+	case SYS_DVBS2:
+		switch (c->rolloff) {
+		case ROLLOFF_20:
+			rolloff = 2;
+			break;
+		case ROLLOFF_25:
+			rolloff = 1;
+			break;
+		case ROLLOFF_35:
+			rolloff = 0;
+			break;
+		case ROLLOFF_AUTO:
+		default:
+			dbg("%s: invalid rolloff", __func__);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		switch (c->pilot) {
+		case PILOT_OFF:
+			pilot = 0;
+			break;
+		case PILOT_ON:
+			pilot = 1;
+			break;
+		case PILOT_AUTO:
+			pilot = 2;
+			break;
+		default:
+			dbg("%s: invalid pilot", __func__);
+			ret = -EINVAL;
+			goto error;
+		}
+		break;
+	default:
+		dbg("%s: invalid delivery_system", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
+			c->modulation == TDA10071_MODCOD[i].modulation &&
+			c->fec_inner == TDA10071_MODCOD[i].fec) {
+			mode = TDA10071_MODCOD[i].val;
+			dbg("%s: mode found=%02x", __func__, mode);
+			break;
+		}
+	}
+
+	if (mode == 0xff) {
+		dbg("%s: invalid parameter combination", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (c->symbol_rate <= 5000000)
+		div = 14;
+	else
+		div = 4;
+
+	ret = tda10071_wr_reg(priv, 0x81, div);
+	if (ret)
+		goto error;
+
+	ret = tda10071_wr_reg(priv, 0xe3, div);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_CHANGE_CHANNEL;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = mode;
+	cmd.args[0x03] = (c->frequency >> 16) & 0xff;
+	cmd.args[0x04] = (c->frequency >>  8) & 0xff;
+	cmd.args[0x05] = (c->frequency >>  0) & 0xff;
+	cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+	cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff;
+	cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
+	cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
+	cmd.args[0x0a] = rolloff;
+	cmd.args[0x0b] = inversion;
+	cmd.args[0x0c] = pilot;
+	cmd.args[0x0d] = 0x00;
+	cmd.args[0x0e] = 0x00;
+	cmd.len = 0x0f;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	priv->delivery_system = c->delivery_system;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 buf[5], tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x30, buf, 5);
+	if (ret)
+		goto error;
+
+	tmp = buf[0] & 0x3f;
+	for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (tmp == TDA10071_MODCOD[i].val) {
+			c->modulation = TDA10071_MODCOD[i].modulation;
+			c->fec_inner = TDA10071_MODCOD[i].fec;
+			c->delivery_system = TDA10071_MODCOD[i].delivery_system;
+		}
+	}
+
+	switch ((buf[1] >> 0) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	switch ((buf[1] >> 7) & 0x01) {
+	case 0:
+		c->pilot = PILOT_OFF;
+		break;
+	case 1:
+		c->pilot = PILOT_ON;
+		break;
+	}
+
+	c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
+
+	ret = tda10071_rd_regs(priv, 0x52, buf, 3);
+	if (ret)
+		goto error;
+
+	c->symbol_rate = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_init(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len, remaining, fw_size;
+	const struct firmware *fw;
+	u8 *fw_file = "/*(DEBLOBBED)*/";
+	u8 tmp, buf[4];
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x00, 0x07 },
+		{ 0x80, 0x00, 0x02 },
+		{ 0xcd, 0x00, 0xc0 },
+		{ 0xce, 0x00, 0x1b },
+		{ 0x9d, 0x00, 0x01 },
+		{ 0x9d, 0x00, 0x02 },
+		{ 0x9e, 0x00, 0x01 },
+		{ 0x87, 0x00, 0x80 },
+		{ 0xce, 0x00, 0x08 },
+		{ 0xce, 0x00, 0x10 },
+	};
+	struct tda10071_reg_val_mask tab2[] = {
+		{ 0xf1, 0x70, 0xff },
+		{ 0x88, priv->cfg.pll_multiplier, 0x3f },
+		{ 0x89, 0x00, 0x10 },
+		{ 0x89, 0x10, 0x10 },
+		{ 0xc0, 0x01, 0x01 },
+		{ 0xc0, 0x00, 0x01 },
+		{ 0xe0, 0xff, 0xff },
+		{ 0xe0, 0x00, 0xff },
+		{ 0x96, 0x1e, 0x7e },
+		{ 0x8b, 0x08, 0x08 },
+		{ 0x8b, 0x00, 0x08 },
+		{ 0x8f, 0x1a, 0x7e },
+		{ 0x8c, 0x68, 0xff },
+		{ 0x8d, 0x08, 0xff },
+		{ 0x8e, 0x4c, 0xff },
+		{ 0x8f, 0x01, 0x01 },
+		{ 0x8b, 0x04, 0x04 },
+		{ 0x8b, 0x00, 0x04 },
+		{ 0x87, 0x05, 0x07 },
+		{ 0x80, 0x00, 0x20 },
+		{ 0xc8, 0x01, 0xff },
+		{ 0xb4, 0x47, 0xff },
+		{ 0xb5, 0x9c, 0xff },
+		{ 0xb6, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x03 },
+		{ 0xb7, 0x47, 0xff },
+		{ 0xb8, 0x9c, 0xff },
+		{ 0xb9, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x0c },
+		{ 0xc8, 0x00, 0xff },
+		{ 0xcd, 0x00, 0x04 },
+		{ 0xcd, 0x00, 0x20 },
+		{ 0xe8, 0x02, 0xff },
+		{ 0xcf, 0x20, 0xff },
+		{ 0x9b, 0xd7, 0xff },
+		{ 0x9a, 0x01, 0x03 },
+		{ 0xa8, 0x05, 0x0f },
+		{ 0xa8, 0x65, 0xf0 },
+		{ 0xa6, 0xa0, 0xf0 },
+		{ 0x9d, 0x50, 0xfc },
+		{ 0x9e, 0x20, 0xe0 },
+		{ 0xa3, 0x1c, 0x7c },
+		{ 0xd5, 0x03, 0x03 },
+	};
+
+	/* firmware status */
+	ret = tda10071_rd_reg(priv, 0x51, &tmp);
+	if (ret)
+		goto error;
+
+	if (!tmp) {
+		/* warm state - wake up device from sleep */
+		priv->warm = 1;
+
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+
+		cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 0;
+		cmd.len = 0x03;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	} else {
+		/* cold state - try to download firmware */
+		priv->warm = 0;
+
+		/* request the firmware, this will block and timeout */
+		ret = reject_firmware(&fw, fw_file, priv->i2c->dev.parent);
+		if (ret) {
+			err("did not find the firmware file. (%s) "
+				"Please see linux/Documentation/dvb/ for more" \
+				" details on firmware-problems. (%d)",
+				fw_file, ret);
+			goto error;
+		}
+
+		/* init */
+		for (i = 0; i < ARRAY_SIZE(tab2); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab2[i].reg,
+				tab2[i].val, tab2[i].mask);
+			if (ret)
+				goto error_release_firmware;
+		}
+
+		/*  download firmware */
+		ret = tda10071_wr_reg(priv, 0xe0, 0x7f);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x81);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf8, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf9, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		info("found a '%s' in cold state, will try to load a firmware",
+			tda10071_ops.info.name);
+
+		info("downloading firmware from file '%s'", fw_file);
+
+		/* do not download last byte */
+		fw_size = fw->size - 1;
+
+		for (remaining = fw_size; remaining > 0;
+			remaining -= (priv->cfg.i2c_wr_max - 1)) {
+			len = remaining;
+			if (len > (priv->cfg.i2c_wr_max - 1))
+				len = (priv->cfg.i2c_wr_max - 1);
+
+			ret = tda10071_wr_regs(priv, 0xfa,
+				(u8 *) &fw->data[fw_size - remaining], len);
+			if (ret) {
+				err("firmware download failed=%d", ret);
+				if (ret)
+					goto error_release_firmware;
+			}
+		}
+		release_firmware(fw);
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x0c);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg(priv, 0xe0, 0x00);
+		if (ret)
+			goto error;
+
+		/* wait firmware start */
+		msleep(250);
+
+		/* firmware status */
+		ret = tda10071_rd_reg(priv, 0x51, &tmp);
+		if (ret)
+			goto error;
+
+		if (tmp) {
+			info("firmware did not run");
+			ret = -EFAULT;
+			goto error;
+		} else {
+			priv->warm = 1;
+		}
+
+		cmd.args[0x00] = CMD_GET_FW_VERSION;
+		cmd.len = 0x01;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_rd_regs(priv, cmd.len, buf, 4);
+		if (ret)
+			goto error;
+
+		info("firmware version %d.%d.%d.%d",
+			buf[0], buf[1], buf[2], buf[3]);
+		info("found a '%s' in warm state.", tda10071_ops.info.name);
+
+		ret = tda10071_rd_regs(priv, 0x81, buf, 2);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_DEMOD_INIT;
+		cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
+		cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
+		cmd.args[0x03] = buf[0];
+		cmd.args[0x04] = buf[1];
+		cmd.args[0x05] = priv->cfg.pll_multiplier;
+		cmd.args[0x06] = priv->cfg.spec_inv;
+		cmd.args[0x07] = 0x00;
+		cmd.len = 0x08;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_TUNER_INIT;
+		cmd.args[0x01] = 0x00;
+		cmd.args[0x02] = 0x00;
+		cmd.args[0x03] = 0x00;
+		cmd.args[0x04] = 0x00;
+		cmd.args[0x05] = 0x14;
+		cmd.args[0x06] = 0x00;
+		cmd.args[0x07] = 0x03;
+		cmd.args[0x08] = 0x02;
+		cmd.args[0x09] = 0x02;
+		cmd.args[0x0a] = 0x00;
+		cmd.args[0x0b] = 0x00;
+		cmd.args[0x0c] = 0x00;
+		cmd.args[0x0d] = 0x00;
+		cmd.args[0x0e] = 0x00;
+		cmd.len = 0x0f;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_MPEG_CONFIG;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = priv->cfg.ts_mode;
+		cmd.args[0x03] = 0x00;
+		cmd.args[0x04] = 0x04;
+		cmd.args[0x05] = 0x00;
+		cmd.len = 0x06;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_LNB_CONFIG;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 150;
+		cmd.args[0x03] = 3;
+		cmd.args[0x04] = 22;
+		cmd.args[0x05] = 1;
+		cmd.args[0x06] = 1;
+		cmd.args[0x07] = 30;
+		cmd.args[0x08] = 30;
+		cmd.args[0x09] = 30;
+		cmd.args[0x0a] = 30;
+		cmd.len = 0x0b;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_BER_CONTROL;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 14;
+		cmd.args[0x03] = 14;
+		cmd.len = 0x04;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error_release_firmware:
+	release_firmware(fw);
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_sleep(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x07, 0x07 },
+		{ 0x80, 0x02, 0x02 },
+		{ 0xcd, 0xc0, 0xc0 },
+		{ 0xce, 0x1b, 0x1b },
+		{ 0x9d, 0x01, 0x01 },
+		{ 0x9d, 0x02, 0x02 },
+		{ 0x9e, 0x01, 0x01 },
+		{ 0x87, 0x80, 0x80 },
+		{ 0xce, 0x08, 0x08 },
+		{ 0xce, 0x10, 0x10 },
+	};
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 1;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 8000;
+	s->step_size = 0;
+	s->max_drift = 0;
+
+	return 0;
+}
+
+static void tda10071_release(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	kfree(priv);
+}
+
+struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct tda10071_priv *priv = NULL;
+	u8 tmp;
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
+
+	/* chip ID */
+	ret = tda10071_rd_reg(priv, 0xff, &tmp);
+	if (ret || tmp != 0x0f)
+		goto error;
+
+	/* chip type */
+	ret = tda10071_rd_reg(priv, 0xdd, &tmp);
+	if (ret || tmp != 0x00)
+		goto error;
+
+	/* chip version */
+	ret = tda10071_rd_reg(priv, 0xfe, &tmp);
+	if (ret || tmp != 0x01)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	return &priv->fe;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(tda10071_attach);
+
+static struct dvb_frontend_ops tda10071_ops = {
+	.info = {
+		.name = "NXP TDA10071",
+		.type = FE_QPSK,
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_8_9 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_RECOVER |
+			FE_CAN_2G_MODULATION
+	},
+
+	.release = tda10071_release,
+
+	.get_tune_settings = tda10071_get_tune_settings,
+
+	.init = tda10071_init,
+	.sleep = tda10071_sleep,
+
+	.set_frontend = tda10071_set_frontend,
+	.get_frontend = tda10071_get_frontend,
+
+	.read_status = tda10071_read_status,
+	.read_snr = tda10071_read_snr,
+	.read_signal_strength = tda10071_read_signal_strength,
+	.read_ber = tda10071_read_ber,
+	.read_ucblocks = tda10071_read_ucblocks,
+
+	.diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
+	.diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
+	.diseqc_send_burst = tda10071_diseqc_send_burst,
+
+	.set_tone = tda10071_set_tone,
+	.set_voltage = tda10071_set_voltage,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA10071_H
+#define TDA10071_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda10071_config {
+	/* Demodulator I2C address.
+	 * Default: none, must set
+	 * Values: 0x55,
+	 */
+	u8 i2c_address;
+
+	/* Max bytes I2C provider can write at once.
+	 * Note: Buffer is taken from the stack currently!
+	 * Default: none, must set
+	 * Values:
+	 */
+	u16 i2c_wr_max;
+
+	/* TS output mode.
+	 * Default: TDA10071_TS_SERIAL
+	 * Values:
+	 */
+#define TDA10071_TS_SERIAL        0
+#define TDA10071_TS_PARALLEL      1
+	u8 ts_mode;
+
+	/* Input spectrum inversion.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool spec_inv;
+
+	/* Xtal frequency Hz
+	 * Default: none, must set
+	 * Values:
+	 */
+	u32 xtal;
+
+	/* PLL multiplier.
+	 * Default: none, must set
+	 * Values:
+	 */
+	u8 pll_multiplier;
+};
+
+
+#if defined(CONFIG_DVB_TDA10071) || \
+	(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* TDA10071_H */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071_priv.h linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071_priv.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda10071_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda10071_priv.h	2013-05-01 23:43:14.000000000 -0400
@@ -0,0 +1,122 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA10071_PRIV
+#define TDA10071_PRIV
+
+#include "dvb_frontend.h"
+#include "tda10071.h"
+#include <linux/firmware.h>
+
+#define LOG_PREFIX "tda10071"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (tda10071_debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct tda10071_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct tda10071_config cfg;
+
+	u8 meas_count[2];
+	u32 ber;
+	u32 ucb;
+	fe_status_t fe_status;
+	fe_delivery_system_t delivery_system;
+	bool warm; /* FW running */
+};
+
+static struct tda10071_modcod {
+	fe_delivery_system_t delivery_system;
+	fe_modulation_t modulation;
+	fe_code_rate_t fec;
+	u8 val;
+} TDA10071_MODCOD[] = {
+	/* NBC-QPSK */
+	{ SYS_DVBS2, QPSK,  FEC_AUTO, 0x00 },
+	{ SYS_DVBS2, QPSK,  FEC_1_2,  0x04 },
+	{ SYS_DVBS2, QPSK,  FEC_3_5,  0x05 },
+	{ SYS_DVBS2, QPSK,  FEC_2_3,  0x06 },
+	{ SYS_DVBS2, QPSK,  FEC_3_4,  0x07 },
+	{ SYS_DVBS2, QPSK,  FEC_4_5,  0x08 },
+	{ SYS_DVBS2, QPSK,  FEC_5_6,  0x09 },
+	{ SYS_DVBS2, QPSK,  FEC_8_9,  0x0a },
+	{ SYS_DVBS2, QPSK,  FEC_9_10, 0x0b },
+	/* 8PSK */
+	{ SYS_DVBS2, PSK_8, FEC_3_5,  0x0c },
+	{ SYS_DVBS2, PSK_8, FEC_2_3,  0x0d },
+	{ SYS_DVBS2, PSK_8, FEC_3_4,  0x0e },
+	{ SYS_DVBS2, PSK_8, FEC_5_6,  0x0f },
+	{ SYS_DVBS2, PSK_8, FEC_8_9,  0x10 },
+	{ SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+	/* QPSK */
+	{ SYS_DVBS,  QPSK,  FEC_AUTO, 0x2d },
+	{ SYS_DVBS,  QPSK,  FEC_1_2,  0x2e },
+	{ SYS_DVBS,  QPSK,  FEC_2_3,  0x2f },
+	{ SYS_DVBS,  QPSK,  FEC_3_4,  0x30 },
+	{ SYS_DVBS,  QPSK,  FEC_5_6,  0x31 },
+	{ SYS_DVBS,  QPSK,  FEC_7_8,  0x32 },
+};
+
+struct tda10071_reg_val_mask {
+	u8 reg;
+	u8 val;
+	u8 mask;
+};
+
+/* firmware filename */
+/*(DEBLOBBED)*/
+
+/* firmware commands */
+#define CMD_DEMOD_INIT          0x10
+#define CMD_CHANGE_CHANNEL      0x11
+#define CMD_MPEG_CONFIG         0x13
+#define CMD_TUNER_INIT          0x15
+#define CMD_GET_AGCACC          0x1a
+
+#define CMD_LNB_CONFIG          0x20
+#define CMD_LNB_SEND_DISEQC     0x21
+#define CMD_LNB_SET_DC_LEVEL    0x22
+#define CMD_LNB_PCB_CONFIG      0x23
+#define CMD_LNB_SEND_TONEBURST  0x24
+#define CMD_LNB_UPDATE_REPLY    0x25
+
+#define CMD_GET_FW_VERSION      0x35
+#define CMD_SET_SLEEP_MODE      0x36
+#define CMD_BER_CONTROL         0x3e
+#define CMD_BER_UPDATE_COUNTERS 0x3f
+
+/* firmare command struct */
+#define TDA10071_ARGLEN      0x1e
+struct tda10071_cmd {
+	u8 args[TDA10071_ARGLEN];
+	u8 len;
+};
+
+
+#endif /* TDA10071_PRIV */
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda18271c2dd.c linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda18271c2dd.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/frontends/tda18271c2dd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/frontends/tda18271c2dd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1195,7 +1195,7 @@ static int GetSignalStrength(s32 *pSigna
 }
 #endif
 
-static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
 	struct tda_state *state = fe->tuner_priv;
 
@@ -1222,7 +1222,7 @@ static struct dvb_tuner_ops tuner_ops =
 	.sleep             = sleep,
 	.set_params        = set_params,
 	.release           = release,
-	.get_frequency     = get_frequency,
+	.get_if_frequency  = get_if_frequency,
 	.get_bandwidth     = get_bandwidth,
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/hopper_cards.c linux-libre-3.2-gnu1/drivers/media/dvb/mantis/hopper_cards.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/hopper_cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/hopper_cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,7 +65,7 @@ static int devs;
 
 static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
 {
-	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 stat = 0, mask = 0, lstat = 0;
 	u32 rst_stat = 0, rst_mask = 0;
 
 	struct mantis_pci *mantis;
@@ -80,7 +80,7 @@ static irqreturn_t hopper_irq_handler(in
 
 	stat = mmread(MANTIS_INT_STAT);
 	mask = mmread(MANTIS_INT_MASK);
-	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	lstat = stat & ~MANTIS_INT_RISCSTAT;
 	if (!(stat & mask))
 		return IRQ_NONE;
 
@@ -126,7 +126,7 @@ static irqreturn_t hopper_irq_handler(in
 	}
 	if (stat & MANTIS_INT_RISCI) {
 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
 		tasklet_schedule(&mantis->tasklet);
 	}
 	if (stat & MANTIS_INT_I2CDONE) {
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/mantis/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE)	+= mantis_core
 obj-$(CONFIG_DVB_MANTIS)	+= mantis.o
 obj-$(CONFIG_DVB_HOPPER)	+= hopper.o
 
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_cards.c linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_cards.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@ static char *label[10] = {
 
 static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
 {
-	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 stat = 0, mask = 0, lstat = 0;
 	u32 rst_stat = 0, rst_mask = 0;
 
 	struct mantis_pci *mantis;
@@ -88,7 +88,7 @@ static irqreturn_t mantis_irq_handler(in
 
 	stat = mmread(MANTIS_INT_STAT);
 	mask = mmread(MANTIS_INT_MASK);
-	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	lstat = stat & ~MANTIS_INT_RISCSTAT;
 	if (!(stat & mask))
 		return IRQ_NONE;
 
@@ -134,7 +134,7 @@ static irqreturn_t mantis_irq_handler(in
 	}
 	if (stat & MANTIS_INT_RISCI) {
 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
 		tasklet_schedule(&mantis->tasklet);
 	}
 	if (stat & MANTIS_INT_I2CDONE) {
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_common.h linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_common.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_common.h	2012-01-04 18:55:44.000000000 -0500
@@ -123,11 +123,8 @@ struct mantis_pci {
 	unsigned int		num;
 
 	/*	RISC Core		*/
-	u32			finished_block;
+	u32			busy_block;
 	u32			last_block;
-	u32			line_bytes;
-	u32			line_count;
-	u32			risc_pos;
 	u8			*buf_cpu;
 	dma_addr_t		buf_dma;
 	u32			*risc_cpu;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_dma.c linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_dma.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,13 +43,17 @@
 #define RISC_IRQ		(0x01 << 24)
 
 #define RISC_STATUS(status)	((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
-#define RISC_FLUSH()		(mantis->risc_pos = 0)
-#define RISC_INSTR(opcode)	(mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
+#define RISC_FLUSH(risc_pos)		(risc_pos = 0)
+#define RISC_INSTR(risc_pos, opcode)	(mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
 
 #define MANTIS_BUF_SIZE		(64 * 1024)
-#define MANTIS_BLOCK_BYTES	(MANTIS_BUF_SIZE >> 4)
-#define MANTIS_BLOCK_COUNT	(1 << 4)
-#define MANTIS_RISC_SIZE	PAGE_SIZE
+#define MANTIS_BLOCK_BYTES      (MANTIS_BUF_SIZE / 4)
+#define MANTIS_DMA_TR_BYTES     (2 * 1024) /* upper limit: 4095 bytes. */
+#define MANTIS_BLOCK_COUNT	(MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
+
+#define MANTIS_DMA_TR_UNITS     (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
+/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
+#define MANTIS_RISC_SIZE	PAGE_SIZE /* RISC program must fit here. */
 
 int mantis_dma_exit(struct mantis_pci *mantis)
 {
@@ -124,27 +128,6 @@ err:
 	return -ENOMEM;
 }
 
-static inline int mantis_calc_lines(struct mantis_pci *mantis)
-{
-	mantis->line_bytes = MANTIS_BLOCK_BYTES;
-	mantis->line_count = MANTIS_BLOCK_COUNT;
-
-	while (mantis->line_bytes > 4095) {
-		mantis->line_bytes >>= 1;
-		mantis->line_count <<= 1;
-	}
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
-		MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
-
-	if (mantis->line_count > 255) {
-		dprintk(MANTIS_ERROR, 1, "Buffer size error");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 int mantis_dma_init(struct mantis_pci *mantis)
 {
 	int err = 0;
@@ -158,12 +141,6 @@ int mantis_dma_init(struct mantis_pci *m
 
 		goto err;
 	}
-	err = mantis_calc_lines(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
-
-		goto err;
-	}
 
 	return 0;
 err:
@@ -174,31 +151,32 @@ EXPORT_SYMBOL_GPL(mantis_dma_init);
 static inline void mantis_risc_program(struct mantis_pci *mantis)
 {
 	u32 buf_pos = 0;
-	u32 line;
+	u32 line, step;
+	u32 risc_pos;
 
 	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
-	RISC_FLUSH();
+	RISC_FLUSH(risc_pos);
 
-	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
-		mantis->line_count, mantis->line_bytes);
+	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
+		MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
 
-	for (line = 0; line < mantis->line_count; line++) {
-		dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
-		if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
-			RISC_INSTR(RISC_WRITE	|
-				   RISC_IRQ	|
-				   RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
-				   (MANTIS_BLOCK_COUNT - 1)) %
-				    MANTIS_BLOCK_COUNT) |
-				    mantis->line_bytes);
-		} else {
-			RISC_INSTR(RISC_WRITE	| mantis->line_bytes);
-		}
-		RISC_INSTR(mantis->buf_dma + buf_pos);
-		buf_pos += mantis->line_bytes;
+	for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
+		for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
+			dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
+			if (step == 0) {
+				RISC_INSTR(risc_pos, RISC_WRITE	|
+					   RISC_IRQ	|
+					   RISC_STATUS(line) |
+					   MANTIS_DMA_TR_BYTES);
+			} else {
+				RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
+			}
+			RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
+			buf_pos += MANTIS_DMA_TR_BYTES;
+		  }
 	}
-	RISC_INSTR(RISC_JUMP);
-	RISC_INSTR(mantis->risc_dma);
+	RISC_INSTR(risc_pos, RISC_JUMP);
+	RISC_INSTR(risc_pos, mantis->risc_dma);
 }
 
 void mantis_dma_start(struct mantis_pci *mantis)
@@ -210,7 +188,7 @@ void mantis_dma_start(struct mantis_pci
 	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
 
 	mmwrite(0, MANTIS_DMA_CTL);
-	mantis->last_block = mantis->finished_block = 0;
+	mantis->last_block = mantis->busy_block = 0;
 
 	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
 
@@ -245,9 +223,9 @@ void mantis_dma_xfer(unsigned long data)
 	struct mantis_pci *mantis = (struct mantis_pci *) data;
 	struct mantis_hwconfig *config = mantis->hwconfig;
 
-	while (mantis->last_block != mantis->finished_block) {
+	while (mantis->last_block != mantis->busy_block) {
 		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
-			mantis->last_block, mantis->finished_block);
+			mantis->last_block, mantis->busy_block);
 
 		(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
 		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,6 @@ static const struct stb0899_s1_reg vp104
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x99 },
 	{ STB0899_DISF22RX      	, 0xa8 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ngene/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/ngene/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/ngene/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ngene/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,9 @@ ngene-objs := ngene-core.o ngene-i2c.o n
 
 obj-$(CONFIG_DVB_NGENE) += ngene.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/pluto2/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/pluto2/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/pluto2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/pluto2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/pt1/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/pt1/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/pt1/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/pt1/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o v
 
 obj-$(CONFIG_DVB_PT1) += earth-pt1.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/siano/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/siano/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/siano/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/siano/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@ obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.
 obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
 obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/dvb-core
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/siano/sms-cards.c linux-libre-3.2-gnu1/drivers/media/dvb/siano/sms-cards.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/siano/sms-cards.c	2013-05-02 01:35:21.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/siano/sms-cards.c	2013-05-01 23:43:28.000000000 -0400
@@ -19,6 +19,7 @@
 
 #include "sms-cards.h"
 #include "smsir.h"
+#include <linux/module.h>
 
 static int sms_dbg;
 module_param_named(cards_dbg, sms_dbg, int, 0644);
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/siano/smsendian.c linux-libre-3.2-gnu1/drivers/media/dvb/siano/smsendian.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/siano/smsendian.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/siano/smsendian.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 
  ****************************************************************/
 
+#include <linux/export.h>
 #include <asm/byteorder.h>
 
 #include "smsendian.h"
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/siano/smssdio.c linux-libre-3.2-gnu1/drivers/media/dvb/siano/smssdio.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/siano/smssdio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/siano/smssdio.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/siano/smsusb.c linux-libre-3.2-gnu1/drivers/media/dvb/siano/smsusb.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/siano/smsusb.c	2013-05-02 01:35:24.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/siano/smsusb.c	2013-05-01 23:43:30.000000000 -0400
@@ -24,6 +24,7 @@ along with this program.  If not, see <h
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,8 @@
  * the project's page is at http://www.linuxtv.org/ 
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/delay.h>
@@ -253,7 +255,7 @@ static int av7110_dvb_c_switch(struct sa
 
 		switch (av7110->current_input) {
 		case 1:
-			dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+			dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
 			msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
 			msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
 			msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
@@ -263,7 +265,7 @@ static int av7110_dvb_c_switch(struct sa
 
 			if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 				if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
-					dprintk(1, "setting band in demodulator failed.\n");
+					dprintk(1, "setting band in demodulator failed\n");
 			} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 				saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
 				saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
@@ -272,17 +274,17 @@ static int av7110_dvb_c_switch(struct sa
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		case 2:
-			dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+			dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
 			if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		case 3:
-			dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+			dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
 			if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		default:
-			dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
+			dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
 		}
 	} else {
 		adswitch = 0;
@@ -299,7 +301,7 @@ static int av7110_dvb_c_switch(struct sa
 
 		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 			if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed.\n");
+				dprintk(1, "setting band in demodulator failed\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
 			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -413,7 +415,7 @@ static int vidioc_g_frequency(struct fil
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
-	dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
+	dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
 
 	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
 		return -EINVAL;
@@ -429,7 +431,7 @@ static int vidioc_s_frequency(struct fil
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
-	dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
+	dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
 
 	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
 		return -EINVAL;
@@ -689,12 +691,12 @@ int av7110_init_analog_module(struct av7
 
 	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
 	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
-		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
+		pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
 			av7110->dvb_adapter.num);
 		av7110->adac_type = DVB_ADAC_MSP34x0;
 	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
 		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
-		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
+		pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
 			av7110->dvb_adapter.num);
 		av7110->adac_type = DVB_ADAC_MSP34x5;
 	} else
@@ -715,7 +717,7 @@ int av7110_init_analog_module(struct av7
 	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
 
 	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
-		INFO(("saa7113 not accessible.\n"));
+		pr_info("saa7113 not accessible\n");
 	} else {
 		u8 *i = saa7113_init_regs;
 
@@ -733,7 +735,7 @@ int av7110_init_analog_module(struct av7
 		/* setup for DVB by default */
 		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 			if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed.\n");
+				dprintk(1, "setting band in demodulator failed\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
 			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -797,7 +799,7 @@ int av7110_init_v4l(struct av7110 *av711
 	ret = saa7146_vv_init(dev, vv_data);
 
 	if (ret) {
-		ERR(("cannot init capture device. skipping.\n"));
+		ERR("cannot init capture device. skipping\n");
 		return -ENODEV;
 	}
 	vv_data->ops.vidioc_enum_input = vidioc_enum_input;
@@ -814,12 +816,12 @@ int av7110_init_v4l(struct av7110 *av711
 	vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
 
 	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
-		ERR(("cannot register capture device. skipping.\n"));
+		ERR("cannot register capture device. skipping\n");
 		saa7146_vv_release(dev);
 		return -ENODEV;
 	}
 	if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
-		ERR(("cannot register vbi v4l2 device. skipping.\n"));
+		ERR("cannot register vbi v4l2 device. skipping\n");
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-av.c linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-av.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-av.c	2013-05-02 01:35:12.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-av.c	2013-05-01 23:43:19.000000000 -0400
@@ -33,6 +33,8 @@
  * the project's page is at http://www.linuxtv.org/ 
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "budget.h"
 #include "stv0299.h"
 #include "stb0899_drv.h"
@@ -149,7 +151,7 @@ static int ciintf_read_attribute_mem(str
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 1\n");
+		pr_info("cam ejected 1\n");
 	}
 	return result;
 }
@@ -168,7 +170,7 @@ static int ciintf_write_attribute_mem(st
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 2\n");
+		pr_info("cam ejected 2\n");
 	}
 	return result;
 }
@@ -187,7 +189,7 @@ static int ciintf_read_cam_control(struc
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 3\n");
+		pr_info("cam ejected 3\n");
 		return -ETIMEDOUT;
 	}
 	return result;
@@ -207,7 +209,7 @@ static int ciintf_write_cam_control(stru
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 5\n");
+		pr_info("cam ejected 5\n");
 	}
 	return result;
 }
@@ -289,7 +291,7 @@ static int ciintf_poll_slot_status(struc
 		if (saa7146_read(saa, PSR) & MASK_06) {
 			if (budget_av->slot_status == SLOTSTATUS_NONE) {
 				budget_av->slot_status = SLOTSTATUS_PRESENT;
-				printk(KERN_INFO "budget-av: cam inserted A\n");
+				pr_info("cam inserted A\n");
 			}
 		}
 		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
@@ -306,11 +308,11 @@ static int ciintf_poll_slot_status(struc
 		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
 		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
 			budget_av->slot_status = SLOTSTATUS_PRESENT;
-			printk(KERN_INFO "budget-av: cam inserted B\n");
+			pr_info("cam inserted B\n");
 		} else if (result < 0) {
 			if (budget_av->slot_status != SLOTSTATUS_NONE) {
 				ciintf_slot_shutdown(ca, slot);
-				printk(KERN_INFO "budget-av: cam ejected 5\n");
+				pr_info("cam ejected 5\n");
 				return 0;
 			}
 		}
@@ -365,11 +367,11 @@ static int ciintf_init(struct budget_av
 
 	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
 					  &budget_av->ca, 0, 1)) != 0) {
-		printk(KERN_ERR "budget-av: ci initialisation failed.\n");
+		pr_err("ci initialisation failed\n");
 		goto error;
 	}
 
-	printk(KERN_INFO "budget-av: ci interface initialised.\n");
+	pr_info("ci interface initialised\n");
 	return 0;
 
 error:
@@ -896,7 +898,6 @@ static const struct stb0899_s1_reg knc1_
 	{ STB0899_DISRX_ST0		, 0x04 },
 	{ STB0899_DISRX_ST1		, 0x00 },
 	{ STB0899_DISPARITY		, 0x00 },
-	{ STB0899_DISFIFO		, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22		, 0x8c },
 	{ STB0899_DISF22RX		, 0x9a },
@@ -1197,6 +1198,7 @@ static u8 read_pwm(struct budget_av *bud
 #define SUBID_DVBC_KNC1			0x0020
 #define SUBID_DVBC_KNC1_PLUS		0x0021
 #define SUBID_DVBC_KNC1_MK3		0x0022
+#define SUBID_DVBC_KNC1_TDA10024	0x0028
 #define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
 #define SUBID_DVBC_CINERGY1200		0x1156
 #define SUBID_DVBC_CINERGY1200_MK3	0x1176
@@ -1316,6 +1318,7 @@ static void frontend_init(struct budget_
 	case SUBID_DVBC_EASYWATCH_MK3:
 	case SUBID_DVBC_CINERGY1200_MK3:
 	case SUBID_DVBC_KNC1_MK3:
+	case SUBID_DVBC_KNC1_TDA10024:
 	case SUBID_DVBC_KNC1_PLUS_MK3:
 		budget_av->reinitialise_demod = 1;
 		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
@@ -1343,8 +1346,7 @@ static void frontend_init(struct budget_
 	}
 
 	if (fe == NULL) {
-		printk(KERN_ERR "budget-av: A frontend driver was not found "
-				"for device [%04x:%04x] subsystem [%04x:%04x]\n",
+		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
 		       saa->pci->vendor,
 		       saa->pci->device,
 		       saa->pci->subsystem_vendor,
@@ -1356,7 +1358,7 @@ static void frontend_init(struct budget_
 
 	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
 				  budget_av->budget.dvb_frontend)) {
-		printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+		pr_err("Frontend registration failed!\n");
 		dvb_frontend_detach(budget_av->budget.dvb_frontend);
 		budget_av->budget.dvb_frontend = NULL;
 	}
@@ -1414,7 +1416,7 @@ static struct v4l2_input knc1_inputs[KNC
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+	dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
 	if (i->index >= KNC1_INPUTS)
 		return -EINVAL;
 	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
@@ -1428,7 +1430,7 @@ static int vidioc_g_input(struct file *f
 
 	*i = budget_av->cur_input;
 
-	dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
+	dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
 	return 0;
 }
 
@@ -1437,7 +1439,7 @@ static int vidioc_s_input(struct file *f
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
 
-	dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+	dprintk(1, "VIDIOC_S_INPUT %d\n", input);
 	return saa7113_setinput(budget_av, input);
 }
 
@@ -1476,7 +1478,7 @@ static int budget_av_attach(struct saa71
 
 		if (0 != saa7146_vv_init(dev, &vv_data)) {
 			/* fixme: proper cleanup here */
-			ERR(("cannot init vv subsystem.\n"));
+			ERR("cannot init vv subsystem\n");
 			return err;
 		}
 		vv_data.ops.vidioc_enum_input = vidioc_enum_input;
@@ -1485,7 +1487,7 @@ static int budget_av_attach(struct saa71
 
 		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
 			/* fixme: proper cleanup here */
-			ERR(("cannot register capture v4l2 device.\n"));
+			ERR("cannot register capture v4l2 device\n");
 			saa7146_vv_release(dev);
 			return err;
 		}
@@ -1502,13 +1504,12 @@ static int budget_av_attach(struct saa71
 
 	mac = budget_av->budget.dvb_adapter.proposed_mac;
 	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
-		printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+		pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
 		       budget_av->budget.dvb_adapter.num);
 		memset(mac, 0, 6);
 	} else {
-		printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-		       budget_av->budget.dvb_adapter.num,
-		       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		pr_info("KNC1-%d: MAC addr = %pM\n",
+			budget_av->budget.dvb_adapter.num, mac);
 	}
 
 	budget_av->budget.dvb_adapter.priv = budget_av;
@@ -1558,6 +1559,7 @@ MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plu
 MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
 MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
@@ -1587,6 +1589,7 @@ static struct pci_device_id pci_tbl[] =
 	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
 	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
 	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
+	MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
 	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
 	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
 	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-ci.c linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-ci.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-ci.c	2013-05-02 01:35:12.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-ci.c	2013-05-01 23:43:19.000000000 -0400
@@ -1053,7 +1053,6 @@ static const struct stb0899_s1_reg tt320
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x8c },
 	{ STB0899_DISF22RX      	, 0x9a },
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-core.c linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-core.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,6 +110,7 @@ static int start_ts_capture(struct budge
 		break;
 	case BUDGET_CIN1200C_MK3:
 	case BUDGET_KNC1C_MK3:
+	case BUDGET_KNC1C_TDA10024:
 	case BUDGET_KNC1CP_MK3:
 		if (budget->video_port == BUDGET_VIDEO_PORTA) {
 			saa7146_write(dev, DD1_INIT, 0x06000200);
@@ -434,6 +435,7 @@ int ttpci_budget_init(struct budget *bud
 	case BUDGET_KNC1CP:
 	case BUDGET_CIN1200C:
 	case BUDGET_KNC1C_MK3:
+	case BUDGET_KNC1C_TDA10024:
 	case BUDGET_KNC1CP_MK3:
 	case BUDGET_CIN1200C_MK3:
 		budget->buffer_width = TS_WIDTH_DVBC;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget.h linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/budget.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/budget.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,6 +104,7 @@ static struct saa7146_pci_extension_data
 #define BUDGET_KNC1C_MK3	   16
 #define BUDGET_KNC1CP_MK3	   17
 #define BUDGET_KNC1S2              18
+#define BUDGET_KNC1C_TDA10024	   19
 
 #define BUDGET_VIDEO_PORTA         0
 #define BUDGET_VIDEO_PORTB         1
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci
 obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
 obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.c linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.c
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,35 @@ static int getmac_tt(u8 * decodedMAC, u8
 	return 0;
 }
 
+int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
+{
+	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
+		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
+		       0x1d, 0x36, 0x64, 0x78};
+	u8 data[20];
+	int i;
+
+	memcpy(data, encodedMAC, 20);
+
+	for (i = 0; i < 20; i++)
+		data[i] ^= xor[i];
+	for (i = 0; i < 10; i++)
+		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
+			>> ((data[2 * i + 1] >> 6) & 3);
+
+	if (check_mac_tt(data))
+		return -ENODEV;
+
+	decodedMAC[0] = data[2];
+	decodedMAC[1] = data[1];
+	decodedMAC[2] = data[0];
+	decodedMAC[3] = data[6];
+	decodedMAC[4] = data[5];
+	decodedMAC[5] = data[4];
+	return 0;
+}
+EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
+
 static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
 {
 	int ret;
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.h linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.h
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttpci/ttpci-eeprom.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 
+extern int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC);
 extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac);
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttusb-budget/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/ttusb-budget/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttusb-budget/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttusb-budget/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/dvb/ttusb-dec/Makefile linux-libre-3.2-gnu1/drivers/media/dvb/ttusb-dec/Makefile
--- linux-libre-3.1-gnu1/drivers/media/dvb/ttusb-dec/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/dvb/ttusb-dec/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
diff -druNp linux-libre-3.1-gnu1/drivers/media/media-device.c linux-libre-3.2-gnu1/drivers/media/media-device.c
--- linux-libre-3.1-gnu1/drivers/media/media-device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/media-device.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #include <linux/media.h>
+#include <linux/export.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/Kconfig linux-libre-3.2-gnu1/drivers/media/radio/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/radio/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -426,7 +426,6 @@ config RADIO_TIMBERDALE
 config RADIO_WL1273
 	tristate "Texas Instruments WL1273 I2C FM Radio"
 	depends on I2C && VIDEO_V4L2
-	select MFD_CORE
 	select MFD_WL1273_CORE
 	select FW_LOADER
 	---help---
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/Makefile linux-libre-3.2-gnu1/drivers/media/radio/Makefile
--- linux-libre-3.1-gnu1/drivers/media/radio/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -27,4 +27,4 @@ obj-$(CONFIG_RADIO_TIMBERDALE) += radio-
 obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
 obj-$(CONFIG_RADIO_WL128X) += wl128x/
 
-EXTRA_CFLAGS += -Isound
+ccflags-y += -Isound
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/radio-si4713.c linux-libre-3.2-gnu1/drivers/media/radio/radio-si4713.c
--- linux-libre-3.1-gnu1/drivers/media/radio/radio-si4713.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/radio-si4713.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,10 +92,6 @@ static int radio_si4713_s_audout(struct
 static int radio_si4713_querycap(struct file *file, void *priv,
 					struct v4l2_capability *capability)
 {
-	struct radio_si4713_device *rsdev;
-
-	rsdev = video_get_drvdata(video_devdata(file));
-
 	strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
 	strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
 				sizeof(capability->card));
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/radio-tea5764.c linux-libre-3.2-gnu1/drivers/media/radio/radio-tea5764.c
--- linux-libre-3.1-gnu1/drivers/media/radio/radio-tea5764.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/radio-tea5764.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,8 +128,10 @@ struct tea5764_write_regs {
 	u16 rdsbbl;				/* PAUSEDET & RDSBBL */
 } __attribute__ ((packed));
 
-#ifndef RADIO_TEA5764_XTAL
+#ifdef CONFIG_RADIO_TEA5764_XTAL
 #define RADIO_TEA5764_XTAL 1
+#else
+#define RADIO_TEA5764_XTAL 0
 #endif
 
 static int radio_nr = -1;
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/radio-timb.c linux-libre-3.2-gnu1/drivers/media/radio/radio-timb.c
--- linux-libre-3.1-gnu1/drivers/media/radio/radio-timb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/radio-timb.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/timb_radio.h>
 
 #define DRIVER_NAME "timb-radio"
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/radio-wl1273.c linux-libre-3.2-gnu1/drivers/media/radio/radio-wl1273.c
--- linux-libre-3.1-gnu1/drivers/media/radio/radio-wl1273.c	2013-05-02 01:36:37.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/radio-wl1273.c	2013-05-01 23:44:35.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/mfd/wl1273-core.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -2109,7 +2110,7 @@ static int __devinit wl1273_fm_radio_pro
 				 V4L2_CID_TUNE_ANTENNA_CAPACITOR,
 				 0, 255, 1, 255);
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	if (radio->ctrl_handler.error) {
 		r = radio->ctrl_handler.error;
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/si470x/radio-si470x-usb.c linux-libre-3.2-gnu1/drivers/media/radio/si470x/radio-si470x-usb.c
--- linux-libre-3.1-gnu1/drivers/media/radio/si470x/radio-si470x-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/si470x/radio-si470x-usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -395,7 +395,6 @@ int si470x_disconnect_check(struct si470
 static void si470x_int_in_callback(struct urb *urb)
 {
 	struct si470x_device *radio = urb->context;
-	unsigned char buf[RDS_REPORT_SIZE];
 	int retval;
 	unsigned char regnr;
 	unsigned char blocknum;
@@ -423,7 +422,6 @@ static void si470x_int_in_callback(struc
 
 	if (urb->actual_length > 0) {
 		/* Update RDS registers with URB data */
-		buf[0] = RDS_REPORT;
 		for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
 			radio->registers[STATUSRSSI + regnr] =
 			    get_unaligned_be16(&radio->int_in_buffer[
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/si4713-i2c.c linux-libre-3.2-gnu1/drivers/media/radio/si4713-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/radio/si4713-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/si4713-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/radio/wl128x/fmdrv_v4l2.c linux-libre-3.2-gnu1/drivers/media/radio/wl128x/fmdrv_v4l2.c
--- linux-libre-3.1-gnu1/drivers/media/radio/wl128x/fmdrv_v4l2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/radio/wl128x/fmdrv_v4l2.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  *
  */
 
+#include <linux/export.h>
+
 #include "fmdrv.h"
 #include "fmdrv_v4l2.h"
 #include "fmdrv_common.h"
@@ -84,12 +86,14 @@ static ssize_t fm_v4l2_fops_write(struct
 	ret = copy_from_user(&rds, buf, sizeof(rds));
 	fmdbg("(%d)type: %d, text %s, af %d\n",
 		   ret, rds.text_type, rds.text, rds.af_freq);
+	if (ret)
+		return -EFAULT;
 
 	fmdev = video_drvdata(file);
 	fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
 	fm_tx_set_af(fmdev, rds.af_freq);
 
-	return 0;
+	return sizeof(rds);
 }
 
 static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
@@ -402,7 +406,7 @@ static int fm_v4l2_vidioc_s_hw_freq_seek
 static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
 		struct v4l2_modulator *mod)
 {
-	struct fmdev *fmdev = video_drvdata(file);;
+	struct fmdev *fmdev = video_drvdata(file);
 
 	if (mod->index != 0)
 		return -EINVAL;
@@ -557,7 +561,7 @@ int fm_v4l2_init_video_device(struct fmd
 			255, 1, 255);
 
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ati_remote.c linux-libre-3.2-gnu1/drivers/media/rc/ati_remote.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ati_remote.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/rc/ati_remote.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,937 @@
+/*
+ *  USB ATI Remote support
+ *
+ *                Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi>
+ *  Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ *  Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
+ *
+ *  This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
+ *  porting to the 2.6 kernel interfaces, along with other modification
+ *  to better match the style of the existing usb/input drivers.  However, the
+ *  protocol and hardware handling is essentially unchanged from 2.1.1.
+ *
+ *  The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by
+ *  Vojtech Pavlik.
+ *
+ *  Changes:
+ *
+ *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.0
+ *  Jun 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.1
+ *            Added key repeat support contributed by:
+ *                Vincent Vanackere <vanackere@lif.univ-mrs.fr>
+ *            Added support for the "Lola" remote contributed by:
+ *                Seth Cohn <sethcohn@yahoo.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Hardware & software notes
+ *
+ * These remote controls are distributed by ATI as part of their
+ * "All-In-Wonder" video card packages.  The receiver self-identifies as a
+ * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
+ *
+ * The "Lola" remote is available from X10.  See:
+ *    http://www.x10.com/products/lola_sg1.htm
+ * The Lola is similar to the ATI remote but has no mouse support, and slightly
+ * different keys.
+ *
+ * It is possible to use multiple receivers and remotes on multiple computers
+ * simultaneously by configuring them to use specific channels.
+ *
+ * The RF protocol used by the remote supports 16 distinct channels, 1 to 16.
+ * Actually, it may even support more, at least in some revisions of the
+ * hardware.
+ *
+ * Each remote can be configured to transmit on one channel as follows:
+ *   - Press and hold the "hand icon" button.
+ *   - When the red LED starts to blink, let go of the "hand icon" button.
+ *   - When it stops blinking, input the channel code as two digits, from 01
+ *     to 16, and press the hand icon again.
+ *
+ * The timing can be a little tricky.  Try loading the module with debug=1
+ * to have the kernel print out messages about the remote control number
+ * and mask.  Note: debugging prints remote numbers as zero-based hexadecimal.
+ *
+ * The driver has a "channel_mask" parameter. This bitmask specifies which
+ * channels will be ignored by the module.  To mask out channels, just add
+ * all the 2^channel_number values together.
+ *
+ * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
+ * ignore signals coming from remote controls transmitting on channel 4, but
+ * accept all other channels.
+ *
+ * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be
+ * ignored.
+ *
+ * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this
+ * parameter are unused.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/usb/input.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <media/rc-core.h>
+
+/*
+ * Module and Version Information, Module Parameters
+ */
+
+#define ATI_REMOTE_VENDOR_ID		0x0bc7
+#define LOLA_REMOTE_PRODUCT_ID		0x0002
+#define LOLA2_REMOTE_PRODUCT_ID		0x0003
+#define ATI_REMOTE_PRODUCT_ID		0x0004
+#define NVIDIA_REMOTE_PRODUCT_ID	0x0005
+#define MEDION_REMOTE_PRODUCT_ID	0x0006
+#define FIREFLY_REMOTE_PRODUCT_ID	0x0008
+
+#define DRIVER_VERSION		"2.2.1"
+#define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
+#define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
+
+#define NAME_BUFSIZE      80    /* size of product name, path buffers */
+#define DATA_BUFSIZE      63    /* size of URB data buffers */
+
+/*
+ * Duplicate event filtering time.
+ * Sequential, identical KIND_FILTERED inputs with less than
+ * FILTER_TIME milliseconds between them are considered as repeat
+ * events. The hardware generates 5 events for the first keypress
+ * and we have to take this into account for an accurate repeat
+ * behaviour.
+ */
+#define FILTER_TIME	60 /* msec */
+#define REPEAT_DELAY	500 /* msec */
+
+static unsigned long channel_mask;
+module_param(channel_mask, ulong, 0644);
+MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
+
+static int repeat_filter = FILTER_TIME;
+module_param(repeat_filter, int, 0644);
+MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
+
+static int repeat_delay = REPEAT_DELAY;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+
+static bool mouse = true;
+module_param(mouse, bool, 0444);
+MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes");
+
+#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+#undef err
+#define err(format, arg...) printk(KERN_ERR format , ## arg)
+
+static struct usb_device_id ati_remote_table[] = {
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_MEDION_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_SNAPSTREAM_FIREFLY },
+	{}	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ati_remote_table);
+
+/* Get hi and low bytes of a 16-bits int */
+#define HI(a)	((unsigned char)((a) >> 8))
+#define LO(a)	((unsigned char)((a) & 0xff))
+
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+
+/* Device initialization strings */
+static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
+static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
+
+struct ati_remote {
+	struct input_dev *idev;
+	struct rc_dev *rdev;
+	struct usb_device *udev;
+	struct usb_interface *interface;
+
+	struct urb *irq_urb;
+	struct urb *out_urb;
+	struct usb_endpoint_descriptor *endpoint_in;
+	struct usb_endpoint_descriptor *endpoint_out;
+	unsigned char *inbuf;
+	unsigned char *outbuf;
+	dma_addr_t inbuf_dma;
+	dma_addr_t outbuf_dma;
+
+	unsigned char old_data;     /* Detect duplicate events */
+	unsigned long old_jiffies;
+	unsigned long acc_jiffies;  /* handle acceleration */
+	unsigned long first_jiffies;
+
+	unsigned int repeat_count;
+
+	char rc_name[NAME_BUFSIZE];
+	char rc_phys[NAME_BUFSIZE];
+	char mouse_name[NAME_BUFSIZE];
+	char mouse_phys[NAME_BUFSIZE];
+
+	wait_queue_head_t wait;
+	int send_flags;
+
+	int users; /* 0-2, users are rc and input */
+	struct mutex open_mutex;
+};
+
+/* "Kinds" of messages sent from the hardware to the driver. */
+#define KIND_END        0
+#define KIND_LITERAL    1   /* Simply pass to input system */
+#define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
+#define KIND_LU         3   /* Directional keypad diagonals - left up, */
+#define KIND_RU         4   /*   right up,  */
+#define KIND_LD         5   /*   left down, */
+#define KIND_RD         6   /*   right down */
+#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
+
+/* Translation table from hardware messages to input events. */
+static const struct {
+	short kind;
+	unsigned char data;
+	int type;
+	unsigned int code;
+	int value;
+}  ati_remote_tbl[] = {
+	/* Directional control pad axes */
+	{KIND_ACCEL,   0x70, EV_REL, REL_X, -1},   /* left */
+	{KIND_ACCEL,   0x71, EV_REL, REL_X, 1},    /* right */
+	{KIND_ACCEL,   0x72, EV_REL, REL_Y, -1},   /* up */
+	{KIND_ACCEL,   0x73, EV_REL, REL_Y, 1},    /* down */
+	/* Directional control pad diagonals */
+	{KIND_LU,      0x74, EV_REL, 0, 0},        /* left up */
+	{KIND_RU,      0x75, EV_REL, 0, 0},        /* right up */
+	{KIND_LD,      0x77, EV_REL, 0, 0},        /* left down */
+	{KIND_RD,      0x76, EV_REL, 0, 0},        /* right down */
+
+	/* "Mouse button" buttons */
+	{KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
+	{KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
+	{KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
+	{KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+
+	/* Artificial "doubleclick" events are generated by the hardware.
+	 * They are mapped to the "side" and "extra" mouse buttons here. */
+	{KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
+	{KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+
+	/* Non-mouse events are handled by rc-core */
+	{KIND_END, 0x00, EV_MAX + 1, 0, 0}
+};
+
+/* Local function prototypes */
+static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
+static void ati_remote_irq_out		(struct urb *urb);
+static void ati_remote_irq_in		(struct urb *urb);
+static void ati_remote_input_report	(struct urb *urb);
+static int ati_remote_initialize	(struct ati_remote *ati_remote);
+static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote_disconnect	(struct usb_interface *interface);
+
+/* usb specific object to register with the usb subsystem */
+static struct usb_driver ati_remote_driver = {
+	.name         = "ati_remote",
+	.probe        = ati_remote_probe,
+	.disconnect   = ati_remote_disconnect,
+	.id_table     = ati_remote_table,
+};
+
+/*
+ *	ati_remote_dump_input
+ */
+static void ati_remote_dump(struct device *dev, unsigned char *data,
+			    unsigned int len)
+{
+	if (len == 1) {
+		if (data[0] != (unsigned char)0xff && data[0] != 0x00)
+			dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
+	} else if (len == 4)
+		dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
+		     data[0], data[1], data[2], data[3]);
+	else
+		dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
+		     len, data[0], data[1], data[2], data[3], data[4], data[5]);
+}
+
+/*
+ *	ati_remote_open
+ */
+static int ati_remote_open(struct ati_remote *ati_remote)
+{
+	int err = 0;
+
+	mutex_lock(&ati_remote->open_mutex);
+
+	if (ati_remote->users++ != 0)
+		goto out; /* one was already active */
+
+	/* On first open, submit the read urb which was set up previously. */
+	ati_remote->irq_urb->dev = ati_remote->udev;
+	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
+		dev_err(&ati_remote->interface->dev,
+			"%s: usb_submit_urb failed!\n", __func__);
+		err = -EIO;
+	}
+
+out:	mutex_unlock(&ati_remote->open_mutex);
+	return err;
+}
+
+/*
+ *	ati_remote_close
+ */
+static void ati_remote_close(struct ati_remote *ati_remote)
+{
+	mutex_lock(&ati_remote->open_mutex);
+	if (--ati_remote->users == 0)
+		usb_kill_urb(ati_remote->irq_urb);
+	mutex_unlock(&ati_remote->open_mutex);
+}
+
+static int ati_remote_input_open(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+	return ati_remote_open(ati_remote);
+}
+
+static void ati_remote_input_close(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+	ati_remote_close(ati_remote);
+}
+
+static int ati_remote_rc_open(struct rc_dev *rdev)
+{
+	struct ati_remote *ati_remote = rdev->priv;
+	return ati_remote_open(ati_remote);
+}
+
+static void ati_remote_rc_close(struct rc_dev *rdev)
+{
+	struct ati_remote *ati_remote = rdev->priv;
+	ati_remote_close(ati_remote);
+}
+
+/*
+ *		ati_remote_irq_out
+ */
+static void ati_remote_irq_out(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+
+	if (urb->status) {
+		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
+			__func__, urb->status);
+		return;
+	}
+
+	ati_remote->send_flags |= SEND_FLAG_COMPLETE;
+	wmb();
+	wake_up(&ati_remote->wait);
+}
+
+/*
+ *	ati_remote_sendpacket
+ *
+ *	Used to send device initialization strings
+ */
+static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
+{
+	int retval = 0;
+
+	/* Set up out_urb */
+	memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
+	((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);
+
+	ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
+	ati_remote->out_urb->dev = ati_remote->udev;
+	ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
+
+	retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC);
+	if (retval) {
+		dev_dbg(&ati_remote->interface->dev,
+			 "sendpacket: usb_submit_urb failed: %d\n", retval);
+		return retval;
+	}
+
+	wait_event_timeout(ati_remote->wait,
+		((ati_remote->out_urb->status != -EINPROGRESS) ||
+			(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
+		HZ);
+	usb_kill_urb(ati_remote->out_urb);
+
+	return retval;
+}
+
+/*
+ *	ati_remote_compute_accel
+ *
+ * Implements acceleration curve for directional control pad
+ * If elapsed time since last event is > 1/4 second, user "stopped",
+ * so reset acceleration. Otherwise, user is probably holding the control
+ * pad down, so we increase acceleration, ramping up over two seconds to
+ * a maximum speed.
+ */
+static int ati_remote_compute_accel(struct ati_remote *ati_remote)
+{
+	static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+	unsigned long now = jiffies;
+	int acc;
+
+	if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
+		acc = 1;
+		ati_remote->acc_jiffies = now;
+	}
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
+		acc = accel[0];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
+		acc = accel[1];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
+		acc = accel[2];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
+		acc = accel[3];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
+		acc = accel[4];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
+		acc = accel[5];
+	else
+		acc = accel[6];
+
+	return acc;
+}
+
+/*
+ *	ati_remote_report_input
+ */
+static void ati_remote_input_report(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+	unsigned char *data= ati_remote->inbuf;
+	struct input_dev *dev = ati_remote->idev;
+	int index = -1;
+	int acc;
+	int remote_num;
+	unsigned char scancode;
+	int i;
+
+	/*
+	 * data[0] = 0x14
+	 * data[1] = data[2] + data[3] + 0xd5 (a checksum byte)
+	 * data[2] = the key code (with toggle bit in MSB with some models)
+	 * data[3] = channel << 4 (the low 4 bits must be zero)
+	 */
+
+	/* Deal with strange looking inputs */
+	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
+		((data[3] & 0x0f) != 0x00) ) {
+		ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
+		return;
+	}
+
+	if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
+		dbginfo(&ati_remote->interface->dev,
+			"wrong checksum in input: %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3]);
+		return;
+	}
+
+	/* Mask unwanted remote channels.  */
+	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
+	remote_num = (data[3] >> 4) & 0x0f;
+	if (channel_mask & (1 << (remote_num + 1))) {
+		dbginfo(&ati_remote->interface->dev,
+			"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
+			remote_num, data[1], data[2], channel_mask);
+		return;
+	}
+
+	/*
+	 * MSB is a toggle code, though only used by some devices
+	 * (e.g. SnapStream Firefly)
+	 */
+	scancode = data[2] & 0x7f;
+
+	/* Look up event code index in the mouse translation table. */
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
+		if (scancode == ati_remote_tbl[i].data) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index >= 0) {
+		dbginfo(&ati_remote->interface->dev,
+			"channel 0x%02x; mouse data %02x; index %d; keycode %d\n",
+			remote_num, data[2], index, ati_remote_tbl[index].code);
+		if (!dev)
+			return; /* no mouse device */
+	} else
+		dbginfo(&ati_remote->interface->dev,
+			"channel 0x%02x; key data %02x, scancode %02x\n",
+			remote_num, data[2], scancode);
+
+
+	if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code,
+			ati_remote_tbl[index].value);
+		input_sync(dev);
+
+		ati_remote->old_jiffies = jiffies;
+		return;
+	}
+
+	if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
+		unsigned long now = jiffies;
+
+		/* Filter duplicate events which happen "too close" together. */
+		if (ati_remote->old_data == data[2] &&
+		    time_before(now, ati_remote->old_jiffies +
+				     msecs_to_jiffies(repeat_filter))) {
+			ati_remote->repeat_count++;
+		} else {
+			ati_remote->repeat_count = 0;
+			ati_remote->first_jiffies = now;
+		}
+
+		ati_remote->old_data = data[2];
+		ati_remote->old_jiffies = now;
+
+		/* Ensure we skip at least the 4 first duplicate events (generated
+		 * by a single keypress), and continue skipping until repeat_delay
+		 * msecs have passed
+		 */
+		if (ati_remote->repeat_count > 0 &&
+		    (ati_remote->repeat_count < 5 ||
+		     time_before(now, ati_remote->first_jiffies +
+				      msecs_to_jiffies(repeat_delay))))
+			return;
+
+		if (index < 0) {
+			/* Not a mouse event, hand it to rc-core. */
+
+			/*
+			 * We don't use the rc-core repeat handling yet as
+			 * it would cause ghost repeats which would be a
+			 * regression for this driver.
+			 */
+			rc_keydown_notimeout(ati_remote->rdev, scancode,
+					     data[2]);
+			rc_keyup(ati_remote->rdev);
+			return;
+		}
+
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 1);
+		input_sync(dev);
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 0);
+		input_sync(dev);
+
+	} else {
+
+		/*
+		 * Other event kinds are from the directional control pad, and have an
+		 * acceleration factor applied to them.  Without this acceleration, the
+		 * control pad is mostly unusable.
+		 */
+		acc = ati_remote_compute_accel(ati_remote);
+
+		switch (ati_remote_tbl[index].kind) {
+		case KIND_ACCEL:
+			input_event(dev, ati_remote_tbl[index].type,
+				ati_remote_tbl[index].code,
+				ati_remote_tbl[index].value * acc);
+			break;
+		case KIND_LU:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_RU:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_LD:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		case KIND_RD:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		default:
+			dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+				ati_remote_tbl[index].kind);
+		}
+		input_sync(dev);
+
+		ati_remote->old_jiffies = jiffies;
+		ati_remote->old_data = data[2];
+	}
+}
+
+/*
+ *	ati_remote_irq_in
+ */
+static void ati_remote_irq_in(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+	int retval;
+
+	switch (urb->status) {
+	case 0:			/* success */
+		ati_remote_input_report(urb);
+		break;
+	case -ECONNRESET:	/* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
+			__func__);
+		return;
+	default:		/* error */
+		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
+			__func__, urb->status);
+	}
+
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
+			__func__, retval);
+}
+
+/*
+ *	ati_remote_alloc_buffers
+ */
+static int ati_remote_alloc_buffers(struct usb_device *udev,
+				    struct ati_remote *ati_remote)
+{
+	ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
+					       &ati_remote->inbuf_dma);
+	if (!ati_remote->inbuf)
+		return -1;
+
+	ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
+						&ati_remote->outbuf_dma);
+	if (!ati_remote->outbuf)
+		return -1;
+
+	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->irq_urb)
+		return -1;
+
+	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->out_urb)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	ati_remote_free_buffers
+ */
+static void ati_remote_free_buffers(struct ati_remote *ati_remote)
+{
+	usb_free_urb(ati_remote->irq_urb);
+	usb_free_urb(ati_remote->out_urb);
+
+	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->inbuf, ati_remote->inbuf_dma);
+
+	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->outbuf, ati_remote->outbuf_dma);
+}
+
+static void ati_remote_input_init(struct ati_remote *ati_remote)
+{
+	struct input_dev *idev = ati_remote->idev;
+	int i;
+
+	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+	idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
+		if (ati_remote_tbl[i].type == EV_KEY)
+			set_bit(ati_remote_tbl[i].code, idev->keybit);
+
+	input_set_drvdata(idev, ati_remote);
+
+	idev->open = ati_remote_input_open;
+	idev->close = ati_remote_input_close;
+
+	idev->name = ati_remote->mouse_name;
+	idev->phys = ati_remote->mouse_phys;
+
+	usb_to_input_id(ati_remote->udev, &idev->id);
+	idev->dev.parent = &ati_remote->interface->dev;
+}
+
+static void ati_remote_rc_init(struct ati_remote *ati_remote)
+{
+	struct rc_dev *rdev = ati_remote->rdev;
+
+	rdev->priv = ati_remote;
+	rdev->driver_type = RC_DRIVER_SCANCODE;
+	rdev->allowed_protos = RC_TYPE_OTHER;
+	rdev->driver_name = "ati_remote";
+
+	rdev->open = ati_remote_rc_open;
+	rdev->close = ati_remote_rc_close;
+
+	rdev->input_name = ati_remote->rc_name;
+	rdev->input_phys = ati_remote->rc_phys;
+
+	usb_to_input_id(ati_remote->udev, &rdev->input_id);
+	rdev->dev.parent = &ati_remote->interface->dev;
+}
+
+static int ati_remote_initialize(struct ati_remote *ati_remote)
+{
+	struct usb_device *udev = ati_remote->udev;
+	int pipe, maxp;
+
+	init_waitqueue_head(&ati_remote->wait);
+
+	/* Set up irq_urb */
+	pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+
+	usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
+			 maxp, ati_remote_irq_in, ati_remote,
+			 ati_remote->endpoint_in->bInterval);
+	ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
+	ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* Set up out_urb */
+	pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+
+	usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
+			 maxp, ati_remote_irq_out, ati_remote,
+			 ati_remote->endpoint_out->bInterval);
+	ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
+	ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* send initialization strings */
+	if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
+	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
+		dev_err(&ati_remote->interface->dev,
+			 "Initializing ati_remote hardware failed.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ *	ati_remote_probe
+ */
+static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *iface_host = interface->cur_altsetting;
+	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
+	struct ati_remote *ati_remote;
+	struct input_dev *input_dev;
+	struct rc_dev *rc_dev;
+	int err = -ENOMEM;
+
+	if (iface_host->desc.bNumEndpoints != 2) {
+		err("%s: Unexpected desc.bNumEndpoints\n", __func__);
+		return -ENODEV;
+	}
+
+	endpoint_in = &iface_host->endpoint[0].desc;
+	endpoint_out = &iface_host->endpoint[1].desc;
+
+	if (!usb_endpoint_is_int_in(endpoint_in)) {
+		err("%s: Unexpected endpoint_in\n", __func__);
+		return -ENODEV;
+	}
+	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
+		err("%s: endpoint_in message size==0? \n", __func__);
+		return -ENODEV;
+	}
+
+	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+	rc_dev = rc_allocate_device();
+	if (!ati_remote || !rc_dev)
+		goto fail1;
+
+	/* Allocate URB buffers, URBs */
+	if (ati_remote_alloc_buffers(udev, ati_remote))
+		goto fail2;
+
+	ati_remote->endpoint_in = endpoint_in;
+	ati_remote->endpoint_out = endpoint_out;
+	ati_remote->udev = udev;
+	ati_remote->rdev = rc_dev;
+	ati_remote->interface = interface;
+
+	usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys));
+	strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys,
+		sizeof(ati_remote->mouse_phys));
+
+	strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
+	strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys));
+
+	if (udev->manufacturer)
+		strlcpy(ati_remote->rc_name, udev->manufacturer,
+			sizeof(ati_remote->rc_name));
+
+	if (udev->product)
+		snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
+			 "%s %s", ati_remote->rc_name, udev->product);
+
+	if (!strlen(ati_remote->rc_name))
+		snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
+			DRIVER_DESC "(%04x,%04x)",
+			le16_to_cpu(ati_remote->udev->descriptor.idVendor),
+			le16_to_cpu(ati_remote->udev->descriptor.idProduct));
+
+	snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name),
+		 "%s mouse", ati_remote->rc_name);
+
+	if (id->driver_info)
+		rc_dev->map_name = (const char *)id->driver_info;
+	else
+		rc_dev->map_name = RC_MAP_ATI_X10;
+
+	ati_remote_rc_init(ati_remote);
+	mutex_init(&ati_remote->open_mutex);
+
+	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
+	err = ati_remote_initialize(ati_remote);
+	if (err)
+		goto fail3;
+
+	/* Set up and register rc device */
+	err = rc_register_device(ati_remote->rdev);
+	if (err)
+		goto fail3;
+
+	/* use our delay for rc_dev */
+	ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
+
+	/* Set up and register mouse input device */
+	if (mouse) {
+		input_dev = input_allocate_device();
+		if (!input_dev)
+			goto fail4;
+
+		ati_remote->idev = input_dev;
+		ati_remote_input_init(ati_remote);
+		err = input_register_device(input_dev);
+
+		if (err)
+			goto fail5;
+	}
+
+	usb_set_intfdata(interface, ati_remote);
+	return 0;
+
+ fail5:	input_free_device(input_dev);
+ fail4:	rc_unregister_device(rc_dev);
+	rc_dev = NULL;
+ fail3:	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+ fail2:	ati_remote_free_buffers(ati_remote);
+ fail1:	rc_free_device(rc_dev);
+	kfree(ati_remote);
+	return err;
+}
+
+/*
+ *	ati_remote_disconnect
+ */
+static void ati_remote_disconnect(struct usb_interface *interface)
+{
+	struct ati_remote *ati_remote;
+
+	ati_remote = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+	if (!ati_remote) {
+		dev_warn(&interface->dev, "%s - null device?\n", __func__);
+		return;
+	}
+
+	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+	if (ati_remote->idev)
+		input_unregister_device(ati_remote->idev);
+	rc_unregister_device(ati_remote->rdev);
+	ati_remote_free_buffers(ati_remote);
+	kfree(ati_remote);
+}
+
+/*
+ *	ati_remote_init
+ */
+static int __init ati_remote_init(void)
+{
+	int result;
+
+	result = usb_register(&ati_remote_driver);
+	if (result)
+		printk(KERN_ERR KBUILD_MODNAME
+		       ": usb_register error #%d\n", result);
+	else
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+		       DRIVER_DESC "\n");
+
+	return result;
+}
+
+/*
+ *	ati_remote_exit
+ */
+static void __exit ati_remote_exit(void)
+{
+	usb_deregister(&ati_remote_driver);
+}
+
+/*
+ *	module specification
+ */
+
+module_init(ati_remote_init);
+module_exit(ati_remote_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ene_ir.c linux-libre-3.2-gnu1/drivers/media/rc/ene_ir.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ene_ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ene_ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pnp.h>
@@ -118,31 +120,31 @@ static int ene_hw_detect(struct ene_devi
 			dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
 
 	if (hw_revision == 0xFF) {
-		ene_warn("device seems to be disabled");
-		ene_warn("send a mail to lirc-list@lists.sourceforge.net");
-		ene_warn("please attach output of acpidump and dmidecode");
+		pr_warn("device seems to be disabled\n");
+		pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
+		pr_warn("please attach output of acpidump and dmidecode\n");
 		return -ENODEV;
 	}
 
-	ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
-		chip_major, chip_minor, old_ver, hw_revision);
+	pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
+		  chip_major, chip_minor, old_ver, hw_revision);
 
-	ene_notice("PLL freq = %d", dev->pll_freq);
+	pr_notice("PLL freq = %d\n", dev->pll_freq);
 
 	if (chip_major == 0x33) {
-		ene_warn("chips 0x33xx aren't supported");
+		pr_warn("chips 0x33xx aren't supported\n");
 		return -ENODEV;
 	}
 
 	if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
 		dev->hw_revision = ENE_HW_C;
-		ene_notice("KB3926C detected");
+		pr_notice("KB3926C detected\n");
 	} else if (old_ver == 0x24 && hw_revision == 0xC0) {
 		dev->hw_revision = ENE_HW_B;
-		ene_notice("KB3926B detected");
+		pr_notice("KB3926B detected\n");
 	} else {
 		dev->hw_revision = ENE_HW_D;
-		ene_notice("KB3926D or higher detected");
+		pr_notice("KB3926D or higher detected\n");
 	}
 
 	/* detect features hardware supports */
@@ -152,7 +154,7 @@ static int ene_hw_detect(struct ene_devi
 	fw_reg1 = ene_read_reg(dev, ENE_FW1);
 	fw_reg2 = ene_read_reg(dev, ENE_FW2);
 
-	ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2);
+	pr_notice("Firmware regs: %02x %02x\n", fw_reg1, fw_reg2);
 
 	dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
 	dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
@@ -161,30 +163,29 @@ static int ene_hw_detect(struct ene_devi
 	if (dev->hw_learning_and_tx_capable)
 		dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
 
-	ene_notice("Hardware features:");
+	pr_notice("Hardware features:\n");
 
 	if (dev->hw_learning_and_tx_capable) {
-		ene_notice("* Supports transmitting & learning mode");
-		ene_notice("   This feature is rare and therefore,");
-		ene_notice("   you are welcome to test it,");
-		ene_notice("   and/or contact the author via:");
-		ene_notice("   lirc-list@lists.sourceforge.net");
-		ene_notice("   or maximlevitsky@gmail.com");
+		pr_notice("* Supports transmitting & learning mode\n");
+		pr_notice("   This feature is rare and therefore,\n");
+		pr_notice("   you are welcome to test it,\n");
+		pr_notice("   and/or contact the author via:\n");
+		pr_notice("   lirc-list@lists.sourceforge.net\n");
+		pr_notice("   or maximlevitsky@gmail.com\n");
 
-		ene_notice("* Uses GPIO %s for IR raw input",
-			dev->hw_use_gpio_0a ? "40" : "0A");
+		pr_notice("* Uses GPIO %s for IR raw input\n",
+			  dev->hw_use_gpio_0a ? "40" : "0A");
 
 		if (dev->hw_fan_input)
-			ene_notice("* Uses unused fan feedback input as source"
-					" of demodulated IR data");
+			pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
 	}
 
 	if (!dev->hw_fan_input)
-		ene_notice("* Uses GPIO %s for IR demodulated input",
-			dev->hw_use_gpio_0a ? "0A" : "40");
+		pr_notice("* Uses GPIO %s for IR demodulated input\n",
+			  dev->hw_use_gpio_0a ? "0A" : "40");
 
 	if (dev->hw_extra_buffer)
-		ene_notice("* Uses new style input buffer");
+		pr_notice("* Uses new style input buffer\n");
 	return 0;
 }
 
@@ -215,13 +216,13 @@ static void ene_rx_setup_hw_buffer(struc
 
 	dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
 
-	ene_notice("Hardware uses 2 extended buffers:");
-	ene_notice("  0x%04x - len : %d", dev->extra_buf1_address,
-						dev->extra_buf1_len);
-	ene_notice("  0x%04x - len : %d", dev->extra_buf2_address,
-						dev->extra_buf2_len);
+	pr_notice("Hardware uses 2 extended buffers:\n");
+	pr_notice("  0x%04x - len : %d\n",
+		  dev->extra_buf1_address, dev->extra_buf1_len);
+	pr_notice("  0x%04x - len : %d\n",
+		  dev->extra_buf2_address, dev->extra_buf2_len);
 
-	ene_notice("Total buffer len = %d", dev->buffer_len);
+	pr_notice("Total buffer len = %d\n", dev->buffer_len);
 
 	if (dev->buffer_len > 64 || dev->buffer_len < 16)
 		goto error;
@@ -240,7 +241,7 @@ static void ene_rx_setup_hw_buffer(struc
 	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
 	return;
 error:
-	ene_warn("Error validating extra buffers, device probably won't work");
+	pr_warn("Error validating extra buffers, device probably won't work\n");
 	dev->hw_extra_buffer = false;
 	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
 }
@@ -588,7 +589,7 @@ static void ene_tx_enable(struct ene_dev
 		dbg("TX: Transmitter #2 is connected");
 
 	if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
-		ene_warn("TX: transmitter cable isn't connected!");
+		pr_warn("TX: transmitter cable isn't connected!\n");
 
 	/* disable receive on revc */
 	if (dev->hw_revision == ENE_HW_C)
@@ -615,7 +616,7 @@ static void ene_tx_sample(struct ene_dev
 	bool pulse = dev->tx_sample_pulse;
 
 	if (!dev->tx_buffer) {
-		ene_warn("TX: BUG: attempt to transmit NULL buffer");
+		pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
 		return;
 	}
 
@@ -1049,7 +1050,7 @@ static int ene_probe(struct pnp_dev *pnp
 		dev->hw_learning_and_tx_capable = true;
 		setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
 						(long unsigned int)dev);
-		ene_warn("Simulation of TX activated");
+		pr_warn("Simulation of TX activated\n");
 	}
 
 	if (!dev->hw_learning_and_tx_capable)
@@ -1089,7 +1090,7 @@ static int ene_probe(struct pnp_dev *pnp
 	if (error < 0)
 		goto error;
 
-	ene_notice("driver has been successfully loaded");
+	pr_notice("driver has been successfully loaded\n");
 	return 0;
 error:
 	if (dev && dev->irq >= 0)
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ene_ir.h linux-libre-3.2-gnu1/drivers/media/rc/ene_ir.h
--- linux-libre-3.1-gnu1/drivers/media/rc/ene_ir.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ene_ir.h	2012-01-04 18:55:44.000000000 -0500
@@ -182,20 +182,11 @@
 #define  ENE_HW_C		2	/* 3926C */
 #define  ENE_HW_D		3	/* 3926D or later */
 
-#define ene_printk(level, text, ...) \
-	printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
-
-#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
-#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
-
-
-#define __dbg(level, format, ...) \
-	do { \
-		if (debug >= level) \
-			printk(KERN_DEBUG ENE_DRIVER_NAME \
-				": " format "\n", ## __VA_ARGS__); \
-	} while (0)
-
+#define __dbg(level, format, ...)				\
+do {								\
+	if (debug >= level)					\
+		pr_debug(format "\n", ## __VA_ARGS__);		\
+} while (0)
 
 #define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
 #define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/imon.c linux-libre-3.2-gnu1/drivers/media/rc/imon.c
--- linux-libre-3.1-gnu1/drivers/media/rc/imon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/imon.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/ratelimit.h>
 
 #include <linux/input.h>
 #include <linux/usb.h>
@@ -516,19 +517,19 @@ static int send_packet(struct imon_conte
 	if (retval) {
 		ictx->tx.busy = false;
 		smp_rmb(); /* ensure later readers know we're not busy */
-		pr_err("error submitting urb(%d)\n", retval);
+		pr_err_ratelimited("error submitting urb(%d)\n", retval);
 	} else {
 		/* Wait for transmission to complete (or abort) */
 		mutex_unlock(&ictx->lock);
 		retval = wait_for_completion_interruptible(
 				&ictx->tx.finished);
 		if (retval)
-			pr_err("task interrupted\n");
+			pr_err_ratelimited("task interrupted\n");
 		mutex_lock(&ictx->lock);
 
 		retval = ictx->tx.status;
 		if (retval)
-			pr_err("packet tx failed (%d)\n", retval);
+			pr_err_ratelimited("packet tx failed (%d)\n", retval);
 	}
 
 	kfree(control_req);
@@ -830,20 +831,20 @@ static ssize_t vfd_write(struct file *fi
 
 	ictx = file->private_data;
 	if (!ictx) {
-		pr_err("no context for device\n");
+		pr_err_ratelimited("no context for device\n");
 		return -ENODEV;
 	}
 
 	mutex_lock(&ictx->lock);
 
 	if (!ictx->dev_present_intf0) {
-		pr_err("no iMON device present\n");
+		pr_err_ratelimited("no iMON device present\n");
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	if (n_bytes <= 0 || n_bytes > 32) {
-		pr_err("invalid payload size\n");
+		pr_err_ratelimited("invalid payload size\n");
 		retval = -EINVAL;
 		goto exit;
 	}
@@ -869,7 +870,7 @@ static ssize_t vfd_write(struct file *fi
 
 		retval = send_packet(ictx);
 		if (retval) {
-			pr_err("send packet failed for packet #%d\n", seq / 2);
+			pr_err_ratelimited("send packet #%d failed\n", seq / 2);
 			goto exit;
 		} else {
 			seq += 2;
@@ -883,7 +884,7 @@ static ssize_t vfd_write(struct file *fi
 	ictx->usb_tx_buf[7] = (unsigned char) seq;
 	retval = send_packet(ictx);
 	if (retval)
-		pr_err("send packet failed for packet #%d\n", seq / 2);
+		pr_err_ratelimited("send packet #%d failed\n", seq / 2);
 
 exit:
 	mutex_unlock(&ictx->lock);
@@ -912,20 +913,21 @@ static ssize_t lcd_write(struct file *fi
 
 	ictx = file->private_data;
 	if (!ictx) {
-		pr_err("no context for device\n");
+		pr_err_ratelimited("no context for device\n");
 		return -ENODEV;
 	}
 
 	mutex_lock(&ictx->lock);
 
 	if (!ictx->display_supported) {
-		pr_err("no iMON display present\n");
+		pr_err_ratelimited("no iMON display present\n");
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	if (n_bytes != 8) {
-		pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
+		pr_err_ratelimited("invalid payload size: %d (expected 8)\n",
+				   (int)n_bytes);
 		retval = -EINVAL;
 		goto exit;
 	}
@@ -937,7 +939,7 @@ static ssize_t lcd_write(struct file *fi
 
 	retval = send_packet(ictx);
 	if (retval) {
-		pr_err("send packet failed!\n");
+		pr_err_ratelimited("send packet failed!\n");
 		goto exit;
 	} else {
 		dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
@@ -1656,7 +1658,7 @@ static void usb_rx_callback_intf0(struct
 		return;
 
 	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
+	if (!ictx || !ictx->dev_present_intf0)
 		return;
 
 	switch (urb->status) {
@@ -1688,7 +1690,7 @@ static void usb_rx_callback_intf1(struct
 		return;
 
 	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
+	if (!ictx || !ictx->dev_present_intf1)
 		return;
 
 	switch (urb->status) {
@@ -2116,7 +2118,6 @@ static struct imon_context *imon_init_in
 
 	ictx->dev = dev;
 	ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
-	ictx->dev_present_intf0 = true;
 	ictx->rx_urb_intf0 = rx_urb;
 	ictx->tx_urb = tx_urb;
 	ictx->rf_device = false;
@@ -2155,6 +2156,8 @@ static struct imon_context *imon_init_in
 		goto rdev_setup_failed;
 	}
 
+	ictx->dev_present_intf0 = true;
+
 	mutex_unlock(&ictx->lock);
 	return ictx;
 
@@ -2198,7 +2201,6 @@ static struct imon_context *imon_init_in
 	}
 
 	ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
-	ictx->dev_present_intf1 = true;
 	ictx->rx_urb_intf1 = rx_urb;
 
 	ret = -ENODEV;
@@ -2227,6 +2229,8 @@ static struct imon_context *imon_init_in
 		goto urb_submit_failed;
 	}
 
+	ictx->dev_present_intf1 = true;
+
 	mutex_unlock(&ictx->lock);
 	return ictx;
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-jvc-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-jvc-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-jvc-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-jvc-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define JVC_NBITS		16		/* dev(8) + func(8) */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-lirc-codec.c linux-libre-3.2-gnu1/drivers/media/rc/ir-lirc-codec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-lirc-codec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-lirc-codec.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 #include <media/rc-core.h>
@@ -98,7 +99,7 @@ static int ir_lirc_decode(struct rc_dev
 	return 0;
 }
 
-static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 				   size_t n, loff_t *ppos)
 {
 	struct lirc_codec *lirc;
@@ -140,10 +141,11 @@ out:
 }
 
 static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
-			unsigned long __user arg)
+			unsigned long arg)
 {
 	struct lirc_codec *lirc;
 	struct rc_dev *dev;
+	u32 __user *argp = (u32 __user *)(arg);
 	int ret = 0;
 	__u32 val = 0, tmp;
 
@@ -156,7 +158,7 @@ static long ir_lirc_ioctl(struct file *f
 		return -EFAULT;
 
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
-		ret = get_user(val, (__u32 *)arg);
+		ret = get_user(val, argp);
 		if (ret)
 			return ret;
 	}
@@ -265,7 +267,7 @@ static long ir_lirc_ioctl(struct file *f
 	}
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
-		ret = put_user(val, (__u32 *)arg);
+		ret = put_user(val, argp);
 
 	return ret;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-nec-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-nec-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-nec-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-nec-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define NEC_NBITS		32
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-raw.c linux-libre-3.2-gnu1/drivers/media/rc/ir-raw.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,10 @@
  *  GNU General Public License for more details.
  */
 
+#include <linux/export.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
+#include <linux/kmod.h>
 #include <linux/sched.h>
 #include <linux/freezer.h>
 #include "rc-core-priv.h"
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-rc5-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-rc5-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-rc5-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-rc5-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 #define RC5_NBITS		14
 #define RC5X_NBITS		20
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 #define RC5_SZ_NBITS		15
 #define RC5_UNIT		888888 /* ns */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-rc6-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-rc6-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-rc6-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-rc6-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 /*
  * This decoder currently supports:
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/ir-sony-decoder.c linux-libre-3.2-gnu1/drivers/media/rc/ir-sony-decoder.c
--- linux-libre-3.1-gnu1/drivers/media/rc/ir-sony-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/ir-sony-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define SONY_UNIT		600000 /* ns */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/Kconfig linux-libre-3.2-gnu1/drivers/media/rc/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/rc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@ menuconfig RC_CORE
 	default INPUT
 	---help---
 	  Enable support for Remote Controllers on Linux. This is
-	  needed in order to support several video capture adapters.
-	  Currently, all supported devices use InfraRed.
+	  needed in order to support several video capture adapters,
+	  standalone IR receivers/transmitters, and RF receivers.
 
 	  Enable this option if you have a video capture board even
 	  if you don't need IR, as otherwise, you may not be able to
@@ -108,6 +108,25 @@ config IR_LIRC_CODEC
 	   Enable this option to pass raw IR to and from userspace via
 	   the LIRC interface.
 
+config RC_ATI_REMOTE
+	tristate "ATI / X10 based USB RF remote controls"
+	depends on USB_ARCH_HAS_HCD
+	depends on RC_CORE
+	select USB
+	help
+	   Say Y here if you want to use an X10 based USB remote control.
+	   These are RF remotes with USB receivers.
+
+	   Such devices include the ATI remote that comes with many of ATI's
+	   All-In-Wonder video cards, the X10 "Lola" remote, NVIDIA RF remote,
+	   Medion RF remote, and SnapStream FireFly remote.
+
+	   This driver provides mouse pointer, left and right mouse buttons,
+	   and maps all the other remote buttons to keypress events.
+
+	   To compile this driver as a module, choose M here: the module will be
+	   called ati_remote.
+
 config IR_ENE
 	tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
 	depends on PNP
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/Makefile linux-libre-3.2-gnu1/drivers/media/rc/keymaps/Makefile
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t
 			rc-apac-viewcomp.o \
 			rc-asus-pc39.o \
 			rc-ati-tv-wonder-hd-600.o \
+			rc-ati-x10.o \
 			rc-avermedia-a16d.o \
 			rc-avermedia.o \
 			rc-avermedia-cardbus.o \
@@ -47,6 +48,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t
 			rc-lirc.o \
 			rc-lme2510.o \
 			rc-manli.o \
+			rc-medion-x10.o \
 			rc-msi-digivox-ii.o \
 			rc-msi-digivox-iii.o \
 			rc-msi-tvanywhere.o \
@@ -70,6 +72,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t
 			rc-hauppauge.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
+			rc-snapstream-firefly.o \
 			rc-streamzap.o \
 			rc-tbs-nec.o \
 			rc-technisat-usb2.o \
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* ADS Tech Instant TV DVB-T PCI Remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
 static struct rc_map_table alink_dtu_m[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-anysee.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-anysee.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-anysee.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-anysee.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table anysee[] = {
 	{ 0x0800, KEY_0 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Attila Kondoros <attila.kondoros@chello.hu> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Marc Fargas <telenieko@telenieko.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* ATI TV Wonder HD 600 USB
    Devin Heitmueller <devin.heitmueller@gmail.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-ati-x10.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-ati-x10.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-ati-x10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-ati-x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * ATI X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on the static generic keytable previously found in
+ * ati_remote.c, which is
+ * Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ * Copyright (c) 2002 Vladimir Dergachev
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table ati_x10[] = {
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x00, KEY_A },
+	{ 0x01, KEY_B },
+	{ 0x19, KEY_C },
+	{ 0x1b, KEY_D },
+	{ 0x21, KEY_E },
+	{ 0x23, KEY_F },
+
+	{ 0x18, KEY_KPENTER },    /* "check" */
+	{ 0x16, KEY_MENU },       /* "menu" */
+	{ 0x02, KEY_POWER },      /* Power */
+	{ 0x03, KEY_TV },         /* TV */
+	{ 0x04, KEY_DVD },        /* DVD */
+	{ 0x05, KEY_WWW },        /* WEB */
+	{ 0x06, KEY_BOOKMARKS },  /* "book" */
+	{ 0x07, KEY_EDIT },       /* "hand" */
+	{ 0x1c, KEY_COFFEE },     /* "timer" */
+	{ 0x20, KEY_FRONT },      /* "max" */
+	{ 0x1d, KEY_LEFT },       /* left */
+	{ 0x1f, KEY_RIGHT },      /* right */
+	{ 0x22, KEY_DOWN },       /* down */
+	{ 0x1a, KEY_UP },         /* up */
+	{ 0x1e, KEY_OK },         /* "OK" */
+	{ 0x09, KEY_VOLUMEDOWN }, /* VOL + */
+	{ 0x08, KEY_VOLUMEUP },   /* VOL - */
+	{ 0x0a, KEY_MUTE },       /* MUTE  */
+	{ 0x0b, KEY_CHANNELUP },  /* CH + */
+	{ 0x0c, KEY_CHANNELDOWN },/* CH - */
+	{ 0x27, KEY_RECORD },     /* ( o) red */
+	{ 0x25, KEY_PLAY },       /* ( >) */
+	{ 0x24, KEY_REWIND },     /* (<<) */
+	{ 0x26, KEY_FORWARD },    /* (>>) */
+	{ 0x28, KEY_STOP },       /* ([]) */
+	{ 0x29, KEY_PAUSE },      /* ('') */
+	{ 0x2b, KEY_PREVIOUS },   /* (<-) */
+	{ 0x2a, KEY_NEXT },       /* (>+) */
+	{ 0x2d, KEY_INFO },       /* PLAYING */
+	{ 0x2e, KEY_HOME },       /* TOP */
+	{ 0x2f, KEY_END },        /* END */
+	{ 0x30, KEY_SELECT },     /* SELECT */
+};
+
+static struct rc_map_list ati_x10_map = {
+	.map = {
+		.scan    = ati_x10,
+		.size    = ARRAY_SIZE(ati_x10),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_ATI_X10,
+	}
+};
+
+static int __init init_rc_map_ati_x10(void)
+{
+	return rc_map_register(&ati_x10_map);
+}
+
+static void __exit exit_rc_map_ati_x10(void)
+{
+	rc_map_unregister(&ati_x10_map);
+}
+
+module_init(init_rc_map_ati_x10)
+module_exit(exit_rc_map_ati_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table avermedia_a16d[] = {
 	{ 0x20, KEY_LIST},
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Alex Hermann <gaaf@gmx.net> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Oldrich Jedlicka <oldium.pro@seznam.cz> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Matt Jesson <dvb@jesson.eclipse.co.uk */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Avermedia M135A with RM-JX and RM-K6 remote controls
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Avermedia M733A with IR model RM-K6
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
    and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* AVERTV STUDIO 303 Remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table azurewave_ad_tu700[] = {
 	{ 0x0000, KEY_TAB },             /* Tab */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-behold.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-behold.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-behold.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-behold.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Igor Kuznetsov <igk72@ya.ru>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Beholder Intl. Ltd. 2008
  * Dmitry Belimov d.belimov@google.com
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * From reading the following remotes:
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Cinergy 1400 DVB-T */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-cinergy.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-cinergy.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-cinergy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-cinergy.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table cinergy[] = {
 	{ 0x00, KEY_0 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table dib0700_nec_table[] = {
 	/* Key codes for the Pixelview SBTVD remote */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table dib0700_rc5_table[] = {
 	/* Key codes for the tiny Pinnacle remote*/
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table digitalnow_tinytwin[] = {
 	{ 0x0000, KEY_MUTE },            /* [symbol speaker] */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-digittrade.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-digittrade.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-digittrade.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-digittrade.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Digittrade DVB-T USB Stick remote controller. */
 /* Imported from af9015.h.
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DVBWorld remotes
    Igor M. Liplianin <liplianin@me.by>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DigitalNow DNTV Live DVB-T Remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DigitalNow DNTV Live! DVB-T Pro Remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table em_terratec[] = {
 	{ 0x01, KEY_CHANNEL },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV2-FM  - silver plastic - "Wand Media" written at the botton
     Mauro Carvalho Chehab <mchehab@infradead.org> */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
     Juan Pablo Sormani <sorman@gmail.com> */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV-FM v5.3
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* EVGA inDtube
    Devin Heitmueller <devin.heitmueller@gmail.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-eztv.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-eztv.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-eztv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-eztv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Alfons Geser <a.geser@cox.net>
  * updates from Job D. R. Borges <jobdrb@ig.com.br> */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-flydvb.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-flydvb.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-flydvb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-flydvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table flydvb[] = {
 	{ 0x01, KEY_ZOOM },		/* Full Screen */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table flyvideo[] = {
 	{ 0x0f, KEY_0 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DViCO FUSION HDTV MCE remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* GADMEI UTV330+ RM008Z remote
    Shine Liu <shinel@foxmail.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Remote control for the Genius TVGO A11MCE
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mike Baikov <mike@baikov.com> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-hauppauge.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-hauppauge.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-hauppauge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-hauppauge.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Hauppauge:the newer, gray remotes (seems there are multiple
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* mce-mode imon mce remote key table */
 static struct rc_map_table imon_mce[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * standard imon remote key table, which isn't really entirely
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* IO-DATA BCTV7E Remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kaiomy TVnPC U2
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kworld 315U
  */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kworld Plus TV Analog Lite PCI IR
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table leadtek_y04g0051[] = {
 	{ 0x0300, KEY_POWER2 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-lirc.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-lirc.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-lirc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-lirc.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-core.h>
+#include <linux/module.h>
 
 static struct rc_map_table lirc[] = {
 	{ },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-lme2510.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-lme2510.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-lme2510.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-lme2510.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 
 static struct rc_map_table lme2510_rc[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-manli.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-manli.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-manli.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-manli.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Michael Tokarev <mjt@tls.msk.ru>
    keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-medion-x10.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-medion-x10.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-medion-x10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-medion-x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/*
+ * Medion X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on a keytable provided by
+ * Jan Losinski <losinski@wh2.tu-dresden.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table medion_x10[] = {
+	{ 0x2c, KEY_TV },    /* TV */
+	{ 0x2d, KEY_VCR },   /* VCR */
+	{ 0x04, KEY_DVD },   /* DVD */
+	{ 0x06, KEY_AUDIO }, /* MUSIC */
+
+	{ 0x2e, KEY_RADIO },     /* RADIO */
+	{ 0x05, KEY_DIRECTORY }, /* PHOTO */
+	{ 0x2f, KEY_INFO },      /* TV-PREVIEW */
+	{ 0x30, KEY_LIST },      /* CHANNEL-LST */
+
+	{ 0x1b, KEY_SETUP }, /* SETUP */
+	{ 0x31, KEY_VIDEO }, /* VIDEO DESKTOP */
+
+	{ 0x08, KEY_VOLUMEDOWN },  /* VOL - */
+	{ 0x09, KEY_VOLUMEUP },    /* VOL + */
+	{ 0x0b, KEY_CHANNELUP },   /* CHAN + */
+	{ 0x0c, KEY_CHANNELDOWN }, /* CHAN - */
+	{ 0x00, KEY_MUTE },        /* MUTE */
+
+	{ 0x32, KEY_RED }, /* red */
+	{ 0x33, KEY_GREEN }, /* green */
+	{ 0x34, KEY_YELLOW }, /* yellow */
+	{ 0x35, KEY_BLUE }, /* blue */
+	{ 0x16, KEY_TEXT }, /* TXT */
+
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x1c, KEY_SEARCH }, /* TV/RAD, CH SRC */
+	{ 0x20, KEY_DELETE }, /* DELETE */
+
+	{ 0x36, KEY_KEYBOARD }, /* RENAME */
+	{ 0x18, KEY_SCREEN },   /* SNAPSHOT */
+
+	{ 0x1a, KEY_UP },    /* up */
+	{ 0x22, KEY_DOWN },  /* down */
+	{ 0x1d, KEY_LEFT },  /* left */
+	{ 0x1f, KEY_RIGHT }, /* right */
+	{ 0x1e, KEY_OK },    /* OK */
+
+	{ 0x37, KEY_SELECT }, /* ACQUIRE IMAGE */
+	{ 0x38, KEY_EDIT },   /* EDIT IMAGE */
+
+	{ 0x24, KEY_REWIND },   /* rewind  (<<) */
+	{ 0x25, KEY_PLAY },     /* play    ( >) */
+	{ 0x26, KEY_FORWARD },  /* forward (>>) */
+	{ 0x27, KEY_RECORD },   /* record  ( o) */
+	{ 0x28, KEY_STOP },     /* stop    ([]) */
+	{ 0x29, KEY_PAUSE },    /* pause   ('') */
+
+	{ 0x21, KEY_PREVIOUS },        /* prev */
+	{ 0x39, KEY_SWITCHVIDEOMODE }, /* F SCR */
+	{ 0x23, KEY_NEXT },            /* next */
+	{ 0x19, KEY_MENU },            /* MENU */
+	{ 0x3a, KEY_LANGUAGE },        /* AUDIO */
+
+	{ 0x02, KEY_POWER }, /* POWER */
+};
+
+static struct rc_map_list medion_x10_map = {
+	.map = {
+		.scan    = medion_x10,
+		.size    = ARRAY_SIZE(medion_x10),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_MEDION_X10,
+	}
+};
+
+static int __init init_rc_map_medion_x10(void)
+{
+	return rc_map_register(&medion_x10_map);
+}
+
+static void __exit exit_rc_map_medion_x10(void)
+{
+	rc_map_unregister(&medion_x10_map);
+}
+
+module_init(init_rc_map_medion_x10)
+module_exit(exit_rc_map_medion_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table msi_digivox_ii[] = {
 	{ 0x0002, KEY_2 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* MSI DIGIVOX mini III */
 /* Uses NEC extended 0x61d6. */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* MSI TV@nywhere MASTER remote */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
   Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-nebula.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-nebula.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-nebula.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-nebula.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table nebula[] = {
 	{ 0x00, KEY_0 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Terratec Cinergy Hybrid T USB XS FM
    Mauro Carvalho Chehab <mchehab@redhat.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-norwood.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-norwood.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-norwood.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-norwood.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Norwood Micro (non-Pro) TV Tuner
    By Peter Naulls <peter@chocky.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-npgtech.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-npgtech.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-npgtech.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-npgtech.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table npgtech[] = {
 	{ 0x1d, KEY_SWITCHVIDEOMODE },	/* switch inputs */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mapping for the 28 key remote control as seen at
    http://www.sednacomputer.com/photo/cardbus-tv.jpg
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pinnacle_color[] = {
 	{ 0x59, KEY_MUTE },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pinnacle_grey[] = {
 	{ 0x3a, KEY_0 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Pinnacle PCTV HD 800i mini remote */
 
@@ -20,6 +21,7 @@ static struct rc_map_table pinnacle_pctv
 	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
 	{ 0x0739, KEY_POWER },
 	{ 0x0703, KEY_VOLUMEUP },
+	{ 0x0705, KEY_OK },
 	{ 0x0709, KEY_VOLUMEDOWN },
 	{ 0x0706, KEY_CHANNELUP },
 	{ 0x070c, KEY_CHANNELDOWN },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Keytable for 002-T IR remote provided together with Pixelview
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pixelview[] = {
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Keytable for MK-F12 IR remote provided together with Pixelview
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Remote control for Powercolor Real Angel 330
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Michal Majchrowicz <mmajchrowicz@gmail.com> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-purpletv.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-purpletv.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-purpletv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-purpletv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table purpletv[] = {
 	{ 0x03, KEY_POWER },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pv951.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pv951.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-pv951.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-pv951.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mark Phalan <phalanm@o2.ie> */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table rc6_mce[] = {
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Zogis Real Audio 220 - 32 keys IR */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-snapstream-firefly.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-snapstream-firefly.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-snapstream-firefly.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-snapstream-firefly.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,107 @@
+/*
+ * SnapStream Firefly X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table snapstream_firefly[] = {
+	{ 0x2c, KEY_ZOOM },       /* Maximize */
+	{ 0x02, KEY_CLOSE },
+
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x16, KEY_BACK },
+	{ 0x18, KEY_KPENTER },    /* ent */
+
+	{ 0x09, KEY_VOLUMEUP },
+	{ 0x08, KEY_VOLUMEDOWN },
+	{ 0x0a, KEY_MUTE },
+	{ 0x0b, KEY_CHANNELUP },
+	{ 0x0c, KEY_CHANNELDOWN },
+	{ 0x00, KEY_VENDOR },     /* firefly */
+
+	{ 0x2e, KEY_INFO },
+	{ 0x2f, KEY_OPTION },
+
+	{ 0x1d, KEY_LEFT },
+	{ 0x1f, KEY_RIGHT },
+	{ 0x22, KEY_DOWN },
+	{ 0x1a, KEY_UP },
+	{ 0x1e, KEY_OK },
+
+	{ 0x1c, KEY_MENU },
+	{ 0x20, KEY_EXIT },
+
+	{ 0x27, KEY_RECORD },
+	{ 0x25, KEY_PLAY },
+	{ 0x28, KEY_STOP },
+	{ 0x24, KEY_REWIND },
+	{ 0x26, KEY_FORWARD },
+	{ 0x29, KEY_PAUSE },
+	{ 0x2b, KEY_PREVIOUS },
+	{ 0x2a, KEY_NEXT },
+
+	{ 0x06, KEY_AUDIO },      /* Music */
+	{ 0x05, KEY_IMAGES },     /* Photos */
+	{ 0x04, KEY_DVD },
+	{ 0x03, KEY_TV },
+	{ 0x07, KEY_VIDEO },
+
+	{ 0x01, KEY_HELP },
+	{ 0x2d, KEY_MODE },       /* Mouse */
+
+	{ 0x19, KEY_A },
+	{ 0x1b, KEY_B },
+	{ 0x21, KEY_C },
+	{ 0x23, KEY_D },
+};
+
+static struct rc_map_list snapstream_firefly_map = {
+	.map = {
+		.scan    = snapstream_firefly,
+		.size    = ARRAY_SIZE(snapstream_firefly),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_SNAPSTREAM_FIREFLY,
+	}
+};
+
+static int __init init_rc_map_snapstream_firefly(void)
+{
+	return rc_map_register(&snapstream_firefly_map);
+}
+
+static void __exit exit_rc_map_snapstream_firefly(void)
+{
+	rc_map_unregister(&snapstream_firefly_map);
+}
+
+module_init(init_rc_map_snapstream_firefly)
+module_exit(exit_rc_map_snapstream_firefly)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-streamzap.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-streamzap.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-streamzap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-streamzap.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table streamzap[] = {
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table tbs_nec[] = {
 	{ 0x84, KEY_POWER2},		/* power */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-technisat-usb2.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-technisat-usb2.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-technisat-usb2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-technisat-usb2.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table technisat_usb2[] = {
 	{0x0a0c, KEY_POWER},
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Terratec Cinergy Hybrid T USB XS
    Devin Heitmueller <dheitmueller@linuxtv.org>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-slim-2.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-slim-2.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-slim-2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-slim-2.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * TerraTec slim remote, 6 rows, 3 columns.
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* TerraTec slim remote, 7 rows, 4 columns. */
 /* Uses NEC extended 0x02bd. */
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table tevii_nec[] = {
 	{ 0x0a, KEY_POWER2},
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tivo.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tivo.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tivo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tivo.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle,
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Uses NEC extended 0x02bd */
 static struct rc_map_table total_media_in_hand[] = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-trekstor.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-trekstor.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-trekstor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-trekstor.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* TrekStor DVB-T USB Stick remote controller. */
 /* Imported from af9015.h.
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* for the Technotrend 1500 bundled remotes (grey and black): */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table twinhan_vp1027[] = {
 	{ 0x16, KEY_POWER2 },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_m1f[] = {
 	{ 0x01, KEY_POWER },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_s350[] = {
 	{ 0x00, KEY_TV},
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_tv_pvr[] = {
 	{ 0x14, KEY_MUTE },
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-winfast.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-winfast.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-winfast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-winfast.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
--- linux-libre-3.1-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Leadtek Winfast TV USB II Deluxe remote
    Magnus Alm <magnus.alm@gmail.com>
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/Makefile linux-libre-3.2-gnu1/drivers/media/rc/Makefile
--- linux-libre-3.1-gnu1/drivers/media/rc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-m
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 # stand-alone IR receivers/transmitters
+obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
 obj-$(CONFIG_IR_IMON) += imon.o
 obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/mceusb.c linux-libre-3.2-gnu1/drivers/media/rc/mceusb.c
--- linux-libre-3.1-gnu1/drivers/media/rc/mceusb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/mceusb.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
  *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ * Copyright (c) 2010-2011, Jarod Wilson <jarod@redhat.com>
  *
  * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan
  * Conti, Martin Blatter and Daniel Melander, the latter of which was
@@ -15,6 +15,11 @@
  * Jon Smirl, which included enhancements and simplifications to the
  * incoming IR buffer parsing routines.
  *
+ * Updated in July of 2011 with the aid of Microsoft's official
+ * remote/transceiver requirements and specification document, found at
+ * download.microsoft.com, title
+ * Windows-Media-Center-RC-IR-Collection-Green-Button-Specification-03-08-2011-V2.pdf
+ *
  *
  * 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
@@ -37,10 +42,11 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
+#include <linux/pm_wakeup.h>
 #include <media/rc-core.h>
 
-#define DRIVER_VERSION	"1.91"
-#define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
+#define DRIVER_VERSION	"1.92"
+#define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
 #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
 			"device driver"
 #define DRIVER_NAME	"mceusb"
@@ -63,43 +69,90 @@
 #define MCE_PULSE_MASK		0x7f /* Pulse mask */
 #define MCE_MAX_PULSE_LENGTH	0x7f /* Longest transmittable pulse symbol */
 
-#define MCE_HW_CMD_HEADER	0xff	/* MCE hardware command header */
-#define MCE_COMMAND_HEADER	0x9f	/* MCE command header */
-#define MCE_COMMAND_MASK	0xe0	/* Mask out command bits */
-#define MCE_COMMAND_NULL	0x00	/* These show up various places... */
-/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
- * then we're looking at a raw IR data sample */
-#define MCE_COMMAND_IRDATA	0x80
-#define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
+/*
+ * The interface between the host and the IR hardware is command-response
+ * based. All commands and responses have a consistent format, where a lead
+ * byte always identifies the type of data following it. The lead byte has
+ * a port value in the 3 highest bits and a length value in the 5 lowest
+ * bits.
+ *
+ * The length field is overloaded, with a value of 11111 indicating that the
+ * following byte is a command or response code, and the length of the entire
+ * message is determined by the code. If the length field is not 11111, then
+ * it specifies the number of bytes of port data that follow.
+ */
+#define MCE_CMD			0x1f
+#define MCE_PORT_IR		0x4	/* (0x4 << 5) | MCE_CMD = 0x9f */
+#define MCE_PORT_SYS		0x7	/* (0x7 << 5) | MCE_CMD = 0xff */
+#define MCE_PORT_SER		0x6	/* 0xc0 thru 0xdf flush & 0x1f bytes */
+#define MCE_PORT_MASK	0xe0	/* Mask out command bits */
 
-/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+/* Command port headers */
+#define MCE_CMD_PORT_IR		0x9f	/* IR-related cmd/rsp */
+#define MCE_CMD_PORT_SYS	0xff	/* System (non-IR) device cmd/rsp */
+
+/* Commands that set device state  (2-4 bytes in length) */
+#define MCE_CMD_RESET		0xfe	/* Reset device, 2 bytes */
+#define MCE_CMD_RESUME		0xaa	/* Resume device after error, 2 bytes */
+#define MCE_CMD_SETIRCFS	0x06	/* Set tx carrier, 4 bytes */
+#define MCE_CMD_SETIRTIMEOUT	0x0c	/* Set timeout, 4 bytes */
+#define MCE_CMD_SETIRTXPORTS	0x08	/* Set tx ports, 3 bytes */
+#define MCE_CMD_SETIRRXPORTEN	0x14	/* Set rx ports, 3 bytes */
+#define MCE_CMD_FLASHLED	0x23	/* Flash receiver LED, 2 bytes */
+
+/* Commands that query device state (all 2 bytes, unless noted) */
+#define MCE_CMD_GETIRCFS	0x07	/* Get carrier */
+#define MCE_CMD_GETIRTIMEOUT	0x0d	/* Get timeout */
+#define MCE_CMD_GETIRTXPORTS	0x13	/* Get tx ports */
+#define MCE_CMD_GETIRRXPORTEN	0x15	/* Get rx ports */
+#define MCE_CMD_GETPORTSTATUS	0x11	/* Get tx port status, 3 bytes */
+#define MCE_CMD_GETIRNUMPORTS	0x16	/* Get number of ports */
+#define MCE_CMD_GETWAKESOURCE	0x17	/* Get wake source */
+#define MCE_CMD_GETEMVER	0x22	/* Get emulator interface version */
+#define MCE_CMD_GETDEVDETAILS	0x21	/* Get device details (em ver2 only) */
+#define MCE_CMD_GETWAKESUPPORT	0x20	/* Get wake details (em ver2 only) */
+#define MCE_CMD_GETWAKEVERSION	0x18	/* Get wake pattern (em ver2 only) */
+
+/* Misc commands */
+#define MCE_CMD_NOP		0xff	/* No operation */
+
+/* Responses to commands (non-error cases) */
+#define MCE_RSP_EQIRCFS		0x06	/* tx carrier, 4 bytes */
+#define MCE_RSP_EQIRTIMEOUT	0x0c	/* rx timeout, 4 bytes */
+#define MCE_RSP_GETWAKESOURCE	0x17	/* wake source, 3 bytes */
+#define MCE_RSP_EQIRTXPORTS	0x08	/* tx port mask, 3 bytes */
+#define MCE_RSP_EQIRRXPORTEN	0x14	/* rx port mask, 3 bytes */
+#define MCE_RSP_GETPORTSTATUS	0x11	/* tx port status, 7 bytes */
+#define MCE_RSP_EQIRRXCFCNT	0x15	/* rx carrier count, 4 bytes */
+#define MCE_RSP_EQIRNUMPORTS	0x16	/* number of ports, 4 bytes */
+#define MCE_RSP_EQWAKESUPPORT	0x20	/* wake capabilities, 3 bytes */
+#define MCE_RSP_EQWAKEVERSION	0x18	/* wake pattern details, 6 bytes */
+#define MCE_RSP_EQDEVDETAILS	0x21	/* device capabilities, 3 bytes */
+#define MCE_RSP_EQEMVER		0x22	/* emulator interface ver, 3 bytes */
+#define MCE_RSP_FLASHLED	0x23	/* success flashing LED, 2 bytes */
+
+/* Responses to error cases, must send MCE_CMD_RESUME to clear them */
+#define MCE_RSP_CMD_ILLEGAL	0xfe	/* illegal command for port, 2 bytes */
+#define MCE_RSP_TX_TIMEOUT	0x81	/* tx timed out, 2 bytes */
+
+/* Misc commands/responses not defined in the MCE remote/transceiver spec */
 #define MCE_CMD_SIG_END		0x01	/* End of signal */
 #define MCE_CMD_PING		0x03	/* Ping device */
 #define MCE_CMD_UNKNOWN		0x04	/* Unknown */
 #define MCE_CMD_UNKNOWN2	0x05	/* Unknown */
-#define MCE_CMD_S_CARRIER	0x06	/* Set TX carrier frequency */
-#define MCE_CMD_G_CARRIER	0x07	/* Get TX carrier frequency */
-#define MCE_CMD_S_TXMASK	0x08	/* Set TX port bitmask */
 #define MCE_CMD_UNKNOWN3	0x09	/* Unknown */
 #define MCE_CMD_UNKNOWN4	0x0a	/* Unknown */
 #define MCE_CMD_G_REVISION	0x0b	/* Get hw/sw revision */
-#define MCE_CMD_S_TIMEOUT	0x0c	/* Set RX timeout value */
-#define MCE_CMD_G_TIMEOUT	0x0d	/* Get RX timeout value */
 #define MCE_CMD_UNKNOWN5	0x0e	/* Unknown */
 #define MCE_CMD_UNKNOWN6	0x0f	/* Unknown */
-#define MCE_CMD_G_RXPORTSTS	0x11	/* Get RX port status */
-#define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
-#define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
-#define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
-#define MCE_RSP_PULSE_COUNT	0x15	/* RX pulse count (only if learning) */
-#define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
-#define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
-#define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
 #define MCE_CMD_UNKNOWN8	0x19	/* Unknown */
 #define MCE_CMD_UNKNOWN9	0x1b	/* Unknown */
-#define MCE_CMD_DEVICE_RESET	0xaa	/* Reset the hardware */
-#define MCE_RSP_CMD_INVALID	0xfe	/* Invalid command issued */
+#define MCE_CMD_NULL		0x00	/* These show up various places... */
 
+/* if buf[i] & MCE_PORT_MASK == 0x80 and buf[i] != MCE_CMD_PORT_IR,
+ * then we're looking at a raw IR data sample */
+#define MCE_COMMAND_IRDATA	0x80
+#define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
 
 /* module parameters */
 #ifdef CONFIG_USB_DEBUG
@@ -388,48 +441,37 @@ struct mceusb_dev {
 	char name[128];
 	char phys[64];
 	enum mceusb_model_type model;
+
+	bool need_reset;	/* flag to issue a device resume cmd */
+	u8 emver;		/* emulator interface version */
+	u8 num_txports;		/* number of transmit ports */
+	u8 num_rxports;		/* number of receive sensors */
+	u8 txports_cabled;	/* bitmask of transmitters with cable */
+	u8 rxports_active;	/* bitmask of active receive sensors */
 };
 
-/*
- * MCE Device Command Strings
- * Device command responses vary from device to device...
- * - DEVICE_RESET resets the hardware to its default state
- * - GET_REVISION fetches the hardware/software revision, common
- *   replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
- * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
- *   device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
- *   meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
- *   ((clk / frequency) - 1)
- * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
- *   response in the form of 9f 0c msb lsb
- * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
- *   the form of 9f 08 bm, where bm is the bitmask
- * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
- *   general use one or short-range learning one, in the form of
- *   9f 14 ss, where ss is either 01 for long-range or 02 for short
- * - SET_CARRIER_FREQ sets a new carrier mode and frequency
- * - SET_TX_BITMASK sets the transmitter bitmask
- * - SET_RX_TIMEOUT sets the receiver timeout
- * - SET_RX_SENSOR sets which receiver sensor to use
- */
-static char DEVICE_RESET[]	= {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
-				   MCE_CMD_DEVICE_RESET};
-static char GET_REVISION[]	= {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
-static char GET_UNKNOWN[]	= {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
-static char GET_UNKNOWN2[]	= {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
-static char GET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
-static char GET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
-static char GET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
-static char GET_RX_SENSOR[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
+/* MCE Device Command Strings, generally a port and command pair */
+static char DEVICE_RESUME[]	= {MCE_CMD_NULL, MCE_CMD_PORT_SYS,
+				   MCE_CMD_RESUME};
+static char GET_REVISION[]	= {MCE_CMD_PORT_SYS, MCE_CMD_G_REVISION};
+static char GET_EMVER[]		= {MCE_CMD_PORT_SYS, MCE_CMD_GETEMVER};
+static char GET_WAKEVERSION[]	= {MCE_CMD_PORT_SYS, MCE_CMD_GETWAKEVERSION};
+static char FLASH_LED[]		= {MCE_CMD_PORT_SYS, MCE_CMD_FLASHLED};
+static char GET_UNKNOWN2[]	= {MCE_CMD_PORT_IR, MCE_CMD_UNKNOWN2};
+static char GET_CARRIER_FREQ[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRCFS};
+static char GET_RX_TIMEOUT[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRTIMEOUT};
+static char GET_NUM_PORTS[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRNUMPORTS};
+static char GET_TX_BITMASK[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRTXPORTS};
+static char GET_RX_SENSOR[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRRXPORTEN};
 /* sub in desired values in lower byte or bytes for full command */
 /* FIXME: make use of these for transmit.
-static char SET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_CARRIER, 0x00, 0x00};
-static char SET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
-static char SET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_TIMEOUT, 0x00, 0x00};
-static char SET_RX_SENSOR[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_RXSENSOR, 0x00};
+static char SET_CARRIER_FREQ[]	= {MCE_CMD_PORT_IR,
+				   MCE_CMD_SETIRCFS, 0x00, 0x00};
+static char SET_TX_BITMASK[]	= {MCE_CMD_PORT_IR, MCE_CMD_SETIRTXPORTS, 0x00};
+static char SET_RX_TIMEOUT[]	= {MCE_CMD_PORT_IR,
+				   MCE_CMD_SETIRTIMEOUT, 0x00, 0x00};
+static char SET_RX_SENSOR[]	= {MCE_CMD_PORT_IR,
+				   MCE_RSP_EQIRRXPORTEN, 0x00};
 */
 
 static int mceusb_cmdsize(u8 cmd, u8 subcmd)
@@ -437,27 +479,33 @@ static int mceusb_cmdsize(u8 cmd, u8 sub
 	int datasize = 0;
 
 	switch (cmd) {
-	case MCE_COMMAND_NULL:
-		if (subcmd == MCE_HW_CMD_HEADER)
+	case MCE_CMD_NULL:
+		if (subcmd == MCE_CMD_PORT_SYS)
 			datasize = 1;
 		break;
-	case MCE_HW_CMD_HEADER:
+	case MCE_CMD_PORT_SYS:
 		switch (subcmd) {
+		case MCE_RSP_EQWAKEVERSION:
+			datasize = 4;
+			break;
 		case MCE_CMD_G_REVISION:
 			datasize = 2;
 			break;
+		case MCE_RSP_EQWAKESUPPORT:
+			datasize = 1;
+			break;
 		}
-	case MCE_COMMAND_HEADER:
+	case MCE_CMD_PORT_IR:
 		switch (subcmd) {
 		case MCE_CMD_UNKNOWN:
-		case MCE_CMD_S_CARRIER:
-		case MCE_CMD_S_TIMEOUT:
-		case MCE_RSP_PULSE_COUNT:
+		case MCE_RSP_EQIRCFS:
+		case MCE_RSP_EQIRTIMEOUT:
+		case MCE_RSP_EQIRRXCFCNT:
 			datasize = 2;
 			break;
 		case MCE_CMD_SIG_END:
-		case MCE_CMD_S_TXMASK:
-		case MCE_CMD_S_RXSENSOR:
+		case MCE_RSP_EQIRTXPORTS:
+		case MCE_RSP_EQIRRXPORTEN:
 			datasize = 1;
 			break;
 		}
@@ -470,9 +518,10 @@ static void mceusb_dev_printdata(struct
 {
 	char codes[USB_BUFLEN * 3 + 1];
 	char inout[9];
-	u8 cmd, subcmd, data1, data2;
+	u8 cmd, subcmd, data1, data2, data3, data4, data5;
 	struct device *dev = ir->dev;
 	int i, start, skip = 0;
+	u32 carrier, period;
 
 	if (!debug)
 		return;
@@ -500,18 +549,28 @@ static void mceusb_dev_printdata(struct
 	subcmd = buf[start + 1] & 0xff;
 	data1  = buf[start + 2] & 0xff;
 	data2  = buf[start + 3] & 0xff;
+	data3  = buf[start + 4] & 0xff;
+	data4  = buf[start + 5] & 0xff;
+	data5  = buf[start + 6] & 0xff;
 
 	switch (cmd) {
-	case MCE_COMMAND_NULL:
-		if ((subcmd == MCE_HW_CMD_HEADER) &&
-		    (data1 == MCE_CMD_DEVICE_RESET))
-			dev_info(dev, "Device reset requested\n");
+	case MCE_CMD_NULL:
+		if (subcmd == MCE_CMD_NULL)
+			break;
+		if ((subcmd == MCE_CMD_PORT_SYS) &&
+		    (data1 == MCE_CMD_RESUME))
+			dev_info(dev, "Device resume requested\n");
 		else
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 		break;
-	case MCE_HW_CMD_HEADER:
+	case MCE_CMD_PORT_SYS:
 		switch (subcmd) {
+		case MCE_RSP_EQEMVER:
+			if (!out)
+				dev_info(dev, "Emulator interface version %x\n",
+					 data1);
+			break;
 		case MCE_CMD_G_REVISION:
 			if (len == 2)
 				dev_info(dev, "Get hw/sw rev?\n");
@@ -520,21 +579,35 @@ static void mceusb_dev_printdata(struct
 					 "0x%02x 0x%02x\n", data1, data2,
 					 buf[start + 4], buf[start + 5]);
 			break;
-		case MCE_CMD_DEVICE_RESET:
-			dev_info(dev, "Device reset requested\n");
+		case MCE_CMD_RESUME:
+			dev_info(dev, "Device resume requested\n");
 			break;
-		case MCE_RSP_CMD_INVALID:
-			dev_info(dev, "Previous command not supported\n");
+		case MCE_RSP_CMD_ILLEGAL:
+			dev_info(dev, "Illegal PORT_SYS command\n");
+			break;
+		case MCE_RSP_EQWAKEVERSION:
+			if (!out)
+				dev_info(dev, "Wake version, proto: 0x%02x, "
+					 "payload: 0x%02x, address: 0x%02x, "
+					 "version: 0x%02x\n",
+					 data1, data2, data3, data4);
+			break;
+		case MCE_RSP_GETPORTSTATUS:
+			if (!out)
+				/* We use data1 + 1 here, to match hw labels */
+				dev_info(dev, "TX port %d: blaster is%s connected\n",
+					 data1 + 1, data4 ? " not" : "");
+			break;
+		case MCE_CMD_FLASHLED:
+			dev_info(dev, "Attempting to flash LED\n");
 			break;
-		case MCE_CMD_UNKNOWN7:
-		case MCE_CMD_UNKNOWN9:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 			break;
 		}
 		break;
-	case MCE_COMMAND_HEADER:
+	case MCE_CMD_PORT_IR:
 		switch (subcmd) {
 		case MCE_CMD_SIG_END:
 			dev_info(dev, "End of signal\n");
@@ -546,47 +619,55 @@ static void mceusb_dev_printdata(struct
 			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
 				 data1, data2);
 			break;
-		case MCE_CMD_S_CARRIER:
-			dev_info(dev, "%s carrier mode and freq of "
-				 "0x%02x 0x%02x\n", inout, data1, data2);
+		case MCE_RSP_EQIRCFS:
+			period = DIV_ROUND_CLOSEST(
+					(1 << data1 * 2) * (data2 + 1), 10);
+			if (!period)
+				break;
+			carrier = (1000 * 1000) / period;
+			dev_info(dev, "%s carrier of %u Hz (period %uus)\n",
+				 inout, carrier, period);
 			break;
-		case MCE_CMD_G_CARRIER:
+		case MCE_CMD_GETIRCFS:
 			dev_info(dev, "Get carrier mode and freq\n");
 			break;
-		case MCE_CMD_S_TXMASK:
+		case MCE_RSP_EQIRTXPORTS:
 			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
 				 inout, data1);
 			break;
-		case MCE_CMD_S_TIMEOUT:
+		case MCE_RSP_EQIRTIMEOUT:
 			/* value is in units of 50us, so x*50/1000 ms */
+			period = ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000;
 			dev_info(dev, "%s receive timeout of %d ms\n",
-				 inout,
-				 ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000);
+				 inout, period);
 			break;
-		case MCE_CMD_G_TIMEOUT:
+		case MCE_CMD_GETIRTIMEOUT:
 			dev_info(dev, "Get receive timeout\n");
 			break;
-		case MCE_CMD_G_TXMASK:
+		case MCE_CMD_GETIRTXPORTS:
 			dev_info(dev, "Get transmit blaster mask\n");
 			break;
-		case MCE_CMD_S_RXSENSOR:
+		case MCE_RSP_EQIRRXPORTEN:
 			dev_info(dev, "%s %s-range receive sensor in use\n",
 				 inout, data1 == 0x02 ? "short" : "long");
 			break;
-		case MCE_CMD_G_RXSENSOR:
-		/* aka MCE_RSP_PULSE_COUNT */
+		case MCE_CMD_GETIRRXPORTEN:
+		/* aka MCE_RSP_EQIRRXCFCNT */
 			if (out)
 				dev_info(dev, "Get receive sensor\n");
 			else if (ir->learning_enabled)
 				dev_info(dev, "RX pulse count: %d\n",
 					 ((data1 << 8) | data2));
 			break;
-		case MCE_RSP_CMD_INVALID:
-			dev_info(dev, "Error! Hardware is likely wedged...\n");
+		case MCE_RSP_EQIRNUMPORTS:
+			if (out)
+				break;
+			dev_info(dev, "Num TX ports: %x, num RX ports: %x\n",
+				 data1, data2);
+			break;
+		case MCE_RSP_CMD_ILLEGAL:
+			dev_info(dev, "Illegal PORT_IR command\n");
 			break;
-		case MCE_CMD_UNKNOWN2:
-		case MCE_CMD_UNKNOWN3:
-		case MCE_CMD_UNKNOWN5:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
@@ -599,8 +680,8 @@ static void mceusb_dev_printdata(struct
 
 	if (cmd == MCE_IRDATA_TRAILER)
 		dev_info(dev, "End of raw IR data\n");
-	else if ((cmd != MCE_COMMAND_HEADER) &&
-		 ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
+	else if ((cmd != MCE_CMD_PORT_IR) &&
+		 ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA))
 		dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
 }
 
@@ -616,9 +697,6 @@ static void mce_async_callback(struct ur
 	if (ir) {
 		len = urb->actual_length;
 
-		mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",
-			urb->status, len);
-
 		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
 	}
 
@@ -683,7 +761,16 @@ static void mce_request_packet(struct mc
 
 static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
 {
+	int rsize = sizeof(DEVICE_RESUME);
+
+	if (ir->need_reset) {
+		ir->need_reset = false;
+		mce_request_packet(ir, DEVICE_RESUME, rsize, MCEUSB_TX);
+		msleep(10);
+	}
+
 	mce_request_packet(ir, data, size, MCEUSB_TX);
+	msleep(10);
 }
 
 static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
@@ -708,8 +795,8 @@ static int mceusb_tx_ir(struct rc_dev *d
 		return -ENOMEM;
 
 	/* MCE tx init header */
-	cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
-	cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
+	cmdbuf[cmdcount++] = MCE_CMD_PORT_IR;
+	cmdbuf[cmdcount++] = MCE_CMD_SETIRTXPORTS;
 	cmdbuf[cmdcount++] = ir->tx_mask;
 
 	/* Generate mce packet data */
@@ -795,8 +882,8 @@ static int mceusb_set_tx_carrier(struct
 	struct mceusb_dev *ir = dev->priv;
 	int clk = 10000000;
 	int prescaler = 0, divisor = 0;
-	unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
-				    MCE_CMD_S_CARRIER, 0x00, 0x00 };
+	unsigned char cmdbuf[4] = { MCE_CMD_PORT_IR,
+				    MCE_CMD_SETIRCFS, 0x00, 0x00 };
 
 	/* Carrier has changed */
 	if (ir->carrier != carrier) {
@@ -844,17 +931,34 @@ static void mceusb_handle_command(struct
 	u8 lo = ir->buf_in[index + 2] & 0xff;
 
 	switch (ir->buf_in[index]) {
+	/* the one and only 5-byte return value command */
+	case MCE_RSP_GETPORTSTATUS:
+		if ((ir->buf_in[index + 4] & 0xff) == 0x00)
+			ir->txports_cabled |= 1 << hi;
+		break;
+
 	/* 2-byte return value commands */
-	case MCE_CMD_S_TIMEOUT:
+	case MCE_RSP_EQIRTIMEOUT:
 		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
 		break;
+	case MCE_RSP_EQIRNUMPORTS:
+		ir->num_txports = hi;
+		ir->num_rxports = lo;
+		break;
 
 	/* 1-byte return value commands */
-	case MCE_CMD_S_TXMASK:
+	case MCE_RSP_EQEMVER:
+		ir->emver = hi;
+		break;
+	case MCE_RSP_EQIRTXPORTS:
 		ir->tx_mask = hi;
 		break;
-	case MCE_CMD_S_RXSENSOR:
-		ir->learning_enabled = (hi == 0x02);
+	case MCE_RSP_EQIRRXPORTEN:
+		ir->learning_enabled = ((hi & 0x02) == 0x02);
+		ir->rxports_active = hi;
+		break;
+	case MCE_RSP_CMD_ILLEGAL:
+		ir->need_reset = true;
 		break;
 	default:
 		break;
@@ -903,8 +1007,8 @@ static void mceusb_process_ir_data(struc
 			/* decode mce packets of the form (84),AA,BB,CC,DD */
 			/* IR data packets can span USB messages - rem */
 			ir->cmd = ir->buf_in[i];
-			if ((ir->cmd == MCE_COMMAND_HEADER) ||
-			    ((ir->cmd & MCE_COMMAND_MASK) !=
+			if ((ir->cmd == MCE_CMD_PORT_IR) ||
+			    ((ir->cmd & MCE_PORT_MASK) !=
 			     MCE_COMMAND_IRDATA)) {
 				ir->parser_state = SUBCMD;
 				continue;
@@ -969,6 +1073,13 @@ static void mceusb_dev_recv(struct urb *
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
+static void mceusb_get_emulator_version(struct mceusb_dev *ir)
+{
+	/* If we get no reply or an illegal command reply, its ver 1, says MS */
+	ir->emver = 1;
+	mce_async_out(ir, GET_EMVER, sizeof(GET_EMVER));
+}
+
 static void mceusb_gen1_init(struct mceusb_dev *ir)
 {
 	int ret;
@@ -1011,8 +1122,8 @@ static void mceusb_gen1_init(struct mceu
 			      0x0000, 0x0100, NULL, 0, HZ * 3);
 	mce_dbg(dev, "%s - retC = %d\n", __func__, ret);
 
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	/* device resume */
+	mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
 
 	/* get hw/sw revision? */
 	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
@@ -1022,23 +1133,36 @@ static void mceusb_gen1_init(struct mceu
 
 static void mceusb_gen2_init(struct mceusb_dev *ir)
 {
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	/* device resume */
+	mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
 
 	/* get hw/sw revision? */
 	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
 
-	/* unknown what the next two actually return... */
-	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
+	/* get wake version (protocol, key, address) */
+	mce_async_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION));
+
+	/* unknown what this one actually returns... */
 	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
 }
 
 static void mceusb_get_parameters(struct mceusb_dev *ir)
 {
+	int i;
+	unsigned char cmdbuf[3] = { MCE_CMD_PORT_SYS,
+				    MCE_CMD_GETPORTSTATUS, 0x00 };
+
+	/* defaults, if the hardware doesn't support querying */
+	ir->num_txports = 2;
+	ir->num_rxports = 2;
+
+	/* get number of tx and rx ports */
+	mce_async_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS));
+
 	/* get the carrier and frequency */
 	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
 
-	if (!ir->flags.no_tx)
+	if (ir->num_txports && !ir->flags.no_tx)
 		/* get the transmitter bitmask */
 		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
 
@@ -1047,6 +1171,19 @@ static void mceusb_get_parameters(struct
 
 	/* get receiver sensor setting */
 	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
+
+	for (i = 0; i < ir->num_txports; i++) {
+		cmdbuf[2] = i;
+		mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+	}
+}
+
+static void mceusb_flash_led(struct mceusb_dev *ir)
+{
+	if (ir->emver < 2)
+		return;
+
+	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
 }
 
 static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
@@ -1220,6 +1357,9 @@ static int __devinit mceusb_dev_probe(st
 	mce_dbg(&intf->dev, "Flushing receive buffers\n");
 	mce_flush_rx_buffer(ir, maxp);
 
+	/* figure out which firmware/emulator version this hardware has */
+	mceusb_get_emulator_version(ir);
+
 	/* initialize device */
 	if (ir->flags.microsoft_gen1)
 		mceusb_gen1_init(ir);
@@ -1228,13 +1368,23 @@ static int __devinit mceusb_dev_probe(st
 
 	mceusb_get_parameters(ir);
 
+	mceusb_flash_led(ir);
+
 	if (!ir->flags.no_tx)
 		mceusb_set_tx_mask(ir->rc, MCE_DEFAULT_TX_MASK);
 
 	usb_set_intfdata(intf, ir);
 
-	dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name,
-		 dev->bus->busnum, dev->devnum);
+	/* enable wake via this device */
+	device_set_wakeup_capable(ir->dev, true);
+	device_set_wakeup_enable(ir->dev, true);
+
+	dev_info(&intf->dev, "Registered %s with mce emulator interface "
+		 "version %x\n", name, ir->emver);
+	dev_info(&intf->dev, "%x tx ports (0x%x cabled) and "
+		 "%x rx sensors (0x%x active)\n",
+		 ir->num_txports, ir->txports_cabled,
+		 ir->num_rxports, ir->rxports_active);
 
 	return 0;
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/rc-core-priv.h linux-libre-3.2-gnu1/drivers/media/rc/rc-core-priv.h
--- linux-libre-3.1-gnu1/drivers/media/rc/rc-core-priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/rc-core-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -162,49 +162,49 @@ void ir_raw_init(void);
 #ifdef CONFIG_IR_NEC_DECODER_MODULE
 #define load_nec_decode()	request_module("ir-nec-decoder")
 #else
-#define load_nec_decode()	0
+static inline void load_nec_decode(void) { }
 #endif
 
 /* from ir-rc5-decoder.c */
 #ifdef CONFIG_IR_RC5_DECODER_MODULE
 #define load_rc5_decode()	request_module("ir-rc5-decoder")
 #else
-#define load_rc5_decode()	0
+static inline void load_rc5_decode(void) { }
 #endif
 
 /* from ir-rc6-decoder.c */
 #ifdef CONFIG_IR_RC6_DECODER_MODULE
 #define load_rc6_decode()	request_module("ir-rc6-decoder")
 #else
-#define load_rc6_decode()	0
+static inline void load_rc6_decode(void) { }
 #endif
 
 /* from ir-jvc-decoder.c */
 #ifdef CONFIG_IR_JVC_DECODER_MODULE
 #define load_jvc_decode()	request_module("ir-jvc-decoder")
 #else
-#define load_jvc_decode()	0
+static inline void load_jvc_decode(void) { }
 #endif
 
 /* from ir-sony-decoder.c */
 #ifdef CONFIG_IR_SONY_DECODER_MODULE
 #define load_sony_decode()	request_module("ir-sony-decoder")
 #else
-#define load_sony_decode()	0
+static inline void load_sony_decode(void) { }
 #endif
 
 /* from ir-mce_kbd-decoder.c */
 #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
 #define load_mce_kbd_decode()	request_module("ir-mce_kbd-decoder")
 #else
-#define load_mce_kbd_decode()	0
+static inline void load_mce_kbd_decode(void) { }
 #endif
 
 /* from ir-lirc-codec.c */
 #ifdef CONFIG_IR_LIRC_CODEC_MODULE
 #define load_lirc_codec()	request_module("ir-lirc-codec")
 #else
-#define load_lirc_codec()	0
+static inline void load_lirc_codec(void) { }
 #endif
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/rc-main.c linux-libre-3.2-gnu1/drivers/media/rc/rc-main.c
--- linux-libre-3.1-gnu1/drivers/media/rc/rc-main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/rc-main.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
@@ -928,10 +929,6 @@ out:
 
 static void rc_dev_release(struct device *device)
 {
-	struct rc_dev *dev = to_rc_dev(device);
-
-	kfree(dev);
-	module_put(THIS_MODULE);
 }
 
 #define ADD_HOTPLUG_VAR(fmt, val...)					\
@@ -945,6 +942,9 @@ static int rc_dev_uevent(struct device *
 {
 	struct rc_dev *dev = to_rc_dev(device);
 
+	if (!dev || !dev->input_dev)
+		return -ENODEV;
+
 	if (dev->rc_map.name)
 		ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
 	if (dev->driver_name)
@@ -1013,10 +1013,16 @@ EXPORT_SYMBOL_GPL(rc_allocate_device);
 
 void rc_free_device(struct rc_dev *dev)
 {
-	if (dev) {
+	if (!dev)
+		return;
+
+	if (dev->input_dev)
 		input_free_device(dev->input_dev);
-		put_device(&dev->dev);
-	}
+
+	put_device(&dev->dev);
+
+	kfree(dev);
+	module_put(THIS_MODULE);
 }
 EXPORT_SYMBOL_GPL(rc_free_device);
 
@@ -1143,14 +1149,18 @@ void rc_unregister_device(struct rc_dev
 	if (dev->driver_type == RC_DRIVER_IR_RAW)
 		ir_raw_event_unregister(dev);
 
+	/* Freeing the table should also call the stop callback */
+	ir_free_table(&dev->rc_map);
+	IR_dprintk(1, "Freed keycode table\n");
+
 	input_unregister_device(dev->input_dev);
 	dev->input_dev = NULL;
 
-	ir_free_table(&dev->rc_map);
-	IR_dprintk(1, "Freed keycode table\n");
+	device_del(&dev->dev);
 
-	device_unregister(&dev->dev);
+	rc_free_device(dev);
 }
+
 EXPORT_SYMBOL_GPL(rc_unregister_device);
 
 /*
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/redrat3.c linux-libre-3.2-gnu1/drivers/media/rc/redrat3.c
--- linux-libre-3.1-gnu1/drivers/media/rc/redrat3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/redrat3.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,11 +195,6 @@ struct redrat3_dev {
 	dma_addr_t dma_in;
 	dma_addr_t dma_out;
 
-	/* true if write urb is busy */
-	bool write_busy;
-	/* wait for the write to finish */
-	struct completion write_finished;
-
 	/* locks this structure */
 	struct mutex lock;
 
@@ -207,8 +202,6 @@ struct redrat3_dev {
 	struct timer_list rx_timeout;
 	u32 hw_timeout;
 
-	/* Is the device currently receiving? */
-	bool recv_in_progress;
 	/* is the detector enabled*/
 	bool det_enabled;
 	/* Is the device currently transmitting?*/
diff -druNp linux-libre-3.1-gnu1/drivers/media/rc/winbond-cir.c linux-libre-3.2-gnu1/drivers/media/rc/winbond-cir.c
--- linux-libre-3.1-gnu1/drivers/media/rc/winbond-cir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/rc/winbond-cir.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/pnp.h>
 #include <linux/interrupt.h>
@@ -1155,12 +1157,12 @@ wbcir_init(void)
 	case IR_PROTOCOL_RC6:
 		break;
 	default:
-		printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n");
+		pr_err("Invalid power-on protocol\n");
 	}
 
 	ret = pnp_register_driver(&wbcir_driver);
 	if (ret)
-		printk(KERN_ERR DRVNAME ": Unable to register driver\n");
+		pr_err("Unable to register driver\n");
 
 	return ret;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/adp1653.c linux-libre-3.2-gnu1/drivers/media/video/adp1653.c
--- linux-libre-3.1-gnu1/drivers/media/video/adp1653.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/adp1653.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,9 @@
  */
 
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <media/adp1653.h>
@@ -258,7 +260,7 @@ static int adp1653_init_controls(struct
 	if (flash->ctrls.error)
 		return flash->ctrls.error;
 
-	fault->is_volatile = 1;
+	fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	flash->subdev.ctrl_handler = &flash->ctrls;
 	return 0;
@@ -413,6 +415,10 @@ static int adp1653_probe(struct i2c_clie
 	struct adp1653_flash *flash;
 	int ret;
 
+	/* we couldn't work without platform data */
+	if (client->dev.platform_data == NULL)
+		return -ENODEV;
+
 	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
 	if (flash == NULL)
 		return -ENOMEM;
@@ -425,12 +431,21 @@ static int adp1653_probe(struct i2c_clie
 	flash->subdev.internal_ops = &adp1653_internal_ops;
 	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-	adp1653_init_controls(flash);
+	ret = adp1653_init_controls(flash);
+	if (ret)
+		goto free_and_quit;
 
 	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
 	if (ret < 0)
-		kfree(flash);
+		goto free_and_quit;
+
+	flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
 
+	return 0;
+
+free_and_quit:
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	kfree(flash);
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/adv7175.c linux-libre-3.2-gnu1/drivers/media/video/adv7175.c
--- linux-libre-3.1-gnu1/drivers/media/video/adv7175.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/adv7175.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,11 @@ static inline struct adv7175 *to_adv7175
 
 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
 
+static enum v4l2_mbus_pixelcode adv7175_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -296,6 +301,60 @@ static int adv7175_s_routing(struct v4l2
 	return 0;
 }
 
+static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(adv7175_codes))
+		return -EINVAL;
+
+	*code = adv7175_codes[index];
+	return 0;
+}
+
+static int adv7175_g_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+
+	if ((val & 0x40) == (1 << 6))
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+	else
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
+	mf->width       = 0;
+	mf->height      = 0;
+	mf->field       = V4L2_FIELD_ANY;
+
+	return 0;
+}
+
+static int adv7175_s_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+	int ret;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		val &= ~0x40;
+		break;
+
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		val |= 0x40;
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd,
+			"illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+		return -EINVAL;
+	}
+
+	ret = adv7175_write(sd, 0x7, val);
+
+	return ret;
+}
+
 static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -324,6 +383,9 @@ static const struct v4l2_subdev_core_ops
 static const struct v4l2_subdev_video_ops adv7175_video_ops = {
 	.s_std_output = adv7175_s_std_output,
 	.s_routing = adv7175_s_routing,
+	.s_mbus_fmt = adv7175_s_fmt,
+	.g_mbus_fmt = adv7175_g_fmt,
+	.enum_mbus_fmt  = adv7175_enum_fmt,
 };
 
 static const struct v4l2_subdev_ops adv7175_ops = {
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/ak881x.c linux-libre-3.2-gnu1/drivers/media/video/ak881x.c
--- linux-libre-3.1-gnu1/drivers/media/video/ak881x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/ak881x.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/ak881x.h>
 #include <media/v4l2-chip-ident.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/atmel-isi.c linux-libre-3.2-gnu1/drivers/media/video/atmel-isi.c
--- linux-libre-3.1-gnu1/drivers/media/video/atmel-isi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/atmel-isi.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,6 +94,7 @@ struct atmel_isi {
 	unsigned int			irq;
 
 	struct isi_platform_data	*pdata;
+	u16				width_flags;	/* max 12 bits */
 
 	struct list_head		video_buffer_list;
 	struct frame_buffer		*active;
@@ -248,9 +249,9 @@ static int atmel_isi_wait_status(struct
 /* ------------------------------------------------------------------
 	Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -341,7 +342,7 @@ static int buffer_prepare(struct vb2_buf
 
 			/* Initialize the dma descriptor */
 			desc->p_fbd->fb_address =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 			desc->p_fbd->next_fbd_address = 0;
 			set_dma_ctrl(desc->p_fbd, ISI_DMA_CTRL_WB);
 
@@ -404,12 +405,13 @@ static void buffer_queue(struct vb2_buff
 
 	if (isi->active == NULL) {
 		isi->active = buf;
-		start_dma(isi, buf);
+		if (vb2_is_streaming(vb->vb2_queue))
+			start_dma(isi, buf);
 	}
 	spin_unlock_irqrestore(&isi->lock, flags);
 }
 
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -431,17 +433,26 @@ static int start_streaming(struct vb2_qu
 	ret = wait_event_interruptible(isi->vsync_wq,
 				       isi->state != ISI_STATE_IDLE);
 	if (ret)
-		return ret;
+		goto err;
 
-	if (isi->state != ISI_STATE_READY)
-		return -EIO;
+	if (isi->state != ISI_STATE_READY) {
+		ret = -EIO;
+		goto err;
+	}
 
 	spin_lock_irq(&isi->lock);
 	isi->state = ISI_STATE_WAIT_SOF;
 	isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
+	if (count)
+		start_dma(isi, isi->active);
 	spin_unlock_irq(&isi->lock);
 
 	return 0;
+err:
+	isi->active = NULL;
+	isi->sequence = 0;
+	INIT_LIST_HEAD(&isi->video_buffer_list);
+	return ret;
 }
 
 /* abort streaming and wait for last buffer */
@@ -637,50 +648,42 @@ static bool isi_camera_packing_supported
 		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
-static unsigned long make_bus_param(struct atmel_isi *isi)
-{
-	unsigned long flags;
-	/*
-	 * Platform specified synchronization and pixel clock polarities are
-	 * only a recommendation and are only used during probing. Atmel ISI
-	 * camera interface only works in master mode, i.e., uses HSYNC and
-	 * VSYNC signals from the sensor
-	 */
-	flags = SOCAM_MASTER |
-		SOCAM_HSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_DATA_ACTIVE_HIGH;
-
-	if (isi->pdata->data_width_flags & ISI_DATAWIDTH_10)
-		flags |= SOCAM_DATAWIDTH_10;
-
-	if (isi->pdata->data_width_flags & ISI_DATAWIDTH_8)
-		flags |= SOCAM_DATAWIDTH_8;
-
-	if (flags & SOCAM_DATAWIDTH_MASK)
-		return flags;
-
-	return 0;
-}
+#define ISI_BUS_PARAM (V4L2_MBUS_MASTER |	\
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_HSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_VSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_PCLK_SAMPLE_RISING |	\
+		V4L2_MBUS_PCLK_SAMPLE_FALLING |	\
+		V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 static int isi_camera_try_bus_param(struct soc_camera_device *icd,
 				    unsigned char buswidth)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct atmel_isi *isi = ici->priv;
-	unsigned long camera_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-	ret = soc_camera_bus_param_compatible(camera_flags,
-					make_bus_param(isi));
-	if (!ret)
-		return -EINVAL;
-	return 0;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  ISI_BUS_PARAM);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, ISI_BUS_PARAM);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	}
+
+	if ((1 << (buswidth - 1)) & isi->width_flags)
+		return 0;
+	return -EINVAL;
 }
 
 
@@ -802,59 +805,71 @@ static int isi_camera_querycap(struct so
 
 static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct atmel_isi *isi = ici->priv;
-	unsigned long bus_flags, camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	int ret;
 	u32 cfg1 = 0;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	bus_flags = make_bus_param(isi);
-	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-	dev_dbg(icd->parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
-		camera_flags, bus_flags, common_flags);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  ISI_BUS_PARAM);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, ISI_BUS_PARAM);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = ISI_BUS_PARAM;
+	}
+	dev_dbg(icd->parent, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n",
+		cfg.flags, ISI_BUS_PARAM, common_flags);
 
 	/* Make choises, based on platform preferences */
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (isi->pdata->hsync_act_low)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 		if (isi->pdata->vsync_act_low)
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (isi->pdata->pclk_act_falling)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0) {
-		dev_dbg(icd->parent, "Camera set_bus_param(%lx) returned %d\n",
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
 			common_flags, ret);
 		return ret;
 	}
 
 	/* set bus param for ISI */
-	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW;
-	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 		cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW;
-	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
 
 	if (isi->pdata->has_emb_sync)
@@ -973,6 +988,11 @@ static int __devinit atmel_isi_probe(str
 		goto err_ioremap;
 	}
 
+	if (pdata->data_width_flags & ISI_DATAWIDTH_8)
+		isi->width_flags = 1 << 7;
+	if (pdata->data_width_flags & ISI_DATAWIDTH_10)
+		isi->width_flags |= 1 << 9;
+
 	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 
 	irq = platform_get_irq(pdev, 0);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/au0828/au0828-cards.c linux-libre-3.2-gnu1/drivers/media/video/au0828/au0828-cards.c
--- linux-libre-3.1-gnu1/drivers/media/video/au0828/au0828-cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/au0828/au0828-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,11 +162,14 @@ static void hauppauge_eeprom(struct au08
 	switch (tv.model) {
 	case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
 	case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
 	case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
 	case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
 		break;
@@ -324,6 +327,10 @@ struct usb_device_id au0828_usb_id_table
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 	{ USB_DEVICE(0x2040, 0x8200),
 		.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
+	{ USB_DEVICE(0x2040, 0x7260),
+		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+	{ USB_DEVICE(0x2040, 0x7213),
+		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ },
 };
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/au0828/Makefile linux-libre-3.2-gnu1/drivers/media/video/au0828/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/au0828/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/au0828/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,8 +2,8 @@ au0828-objs	:= au0828-core.o au0828-i2c.
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt819.c linux-libre-3.2-gnu1/drivers/media/video/bt819.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt819.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt819.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@ static int bt819_status(struct v4l2_subd
 	if (pstd)
 		*pstd = std;
 	if (pstatus)
-		*pstatus = status;
+		*pstatus = res;
 
 	v4l2_dbg(1, debug, sd, "get status %x\n", status);
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-cards.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-cards.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-cards.c	2013-05-02 01:35:35.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-cards.c	2013-05-01 23:43:41.000000000 -0400
@@ -25,6 +25,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
@@ -2905,19 +2907,17 @@ void __devinit bttv_idcard(struct bttv *
 
 		if (type != -1) {
 			/* found it */
-			printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
-			       "PCI subsystem ID is %04x:%04x\n",
-			       btv->c.nr,cards[type].name,cards[type].cardnr,
-			       btv->cardid & 0xffff,
-			       (btv->cardid >> 16) & 0xffff);
+			pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+				btv->c.nr, cards[type].name, cards[type].cardnr,
+				btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
 			btv->c.type = cards[type].cardnr;
 		} else {
 			/* 404 */
-			printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
-			       btv->c.nr, btv->cardid & 0xffff,
-			       (btv->cardid >> 16) & 0xffff);
-			printk(KERN_DEBUG "please mail id, board name and "
-			       "the correct card= insmod option to linux-media@vger.kernel.org\n");
+			pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+				btv->c.nr, btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
+			pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
 		}
 	}
 
@@ -2926,10 +2926,10 @@ void __devinit bttv_idcard(struct bttv *
 		btv->c.type=card[btv->c.nr];
 
 	/* print which card config we are using */
-	printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
-	       bttv_tvcards[btv->c.type].name, btv->c.type,
-	       card[btv->c.nr] < bttv_num_tvcards
-	       ? "insmod option" : "autodetected");
+	pr_info("%d: using: %s [card=%d,%s]\n",
+		btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+		card[btv->c.nr] < bttv_num_tvcards
+		? "insmod option" : "autodetected");
 
 	/* overwrite gpio stuff ?? */
 	if (UNSET == audioall && UNSET == audiomux[0])
@@ -2948,12 +2948,13 @@ void __devinit bttv_idcard(struct bttv *
 		}
 	}
 	bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
-	printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
-	       btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
+	pr_info("%d: gpio config override: mask=0x%x, mux=",
+		btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
 	for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
-		printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+		pr_cont("%s0x%x",
+			i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
 	}
-	printk("\n");
+	pr_cont("\n");
 }
 
 /*
@@ -2974,8 +2975,8 @@ static void identify_by_eeprom(struct bt
 
 	if (-1 != type) {
 		btv->c.type = type;
-		printk("bttv%d: detected by eeprom: %s [card=%d]\n",
-		       btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+		pr_info("%d: detected by eeprom: %s [card=%d]\n",
+			btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
 	}
 }
 
@@ -3019,7 +3020,7 @@ static void flyvideo_gpio(struct bttv *b
 		tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
 		break;
 	default:
-		printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+		pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
 		break;
 	}
 
@@ -3036,13 +3037,13 @@ static void flyvideo_gpio(struct bttv *b
 	if (is_capture_only)
 		tuner_type = TUNER_ABSENT; /* No tuner present */
 
-	printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
-		btv->c.nr, has_radio ? "yes" : "no ",
-		has_remote ? "yes" : "no ", tuner_type, gpio);
-	printk(KERN_INFO "bttv%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-		btv->c.nr, is_lr90 ? "yes" : "no ",
-		has_tda9820_tda9821 ? "yes" : "no ",
-		is_capture_only ? "yes" : "no ");
+	pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+		btv->c.nr, has_radio ? "yes" : "no",
+		has_remote ? "yes" : "no", tuner_type, gpio);
+	pr_info("%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+		btv->c.nr, is_lr90 ? "yes" : "no",
+		has_tda9820_tda9821 ? "yes" : "no",
+		is_capture_only ? "yes" : "no");
 
 	if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
 		btv->tuner_type = tuner_type;
@@ -3091,12 +3092,11 @@ static void miro_pinnacle_gpio(struct bt
 			if (btv->c.type == BTTV_BOARD_PINNACLE)
 				btv->c.type = BTTV_BOARD_PINNACLEPRO;
 		}
-		printk(KERN_INFO
-		       "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
-		       btv->c.nr, id+1, btv->tuner_type,
-		       !btv->has_radio ? "no" :
-		       (btv->has_matchbox ? "matchbox" : "fmtuner"),
-		       (-1 == msp) ? "no" : "yes");
+		pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+			btv->c.nr, id+1, btv->tuner_type,
+			!btv->has_radio ? "no" :
+			(btv->has_matchbox ? "matchbox" : "fmtuner"),
+			(-1 == msp) ? "no" : "yes");
 	} else {
 		/* new cards with microtune tuner */
 		id = 63 - id;
@@ -3138,9 +3138,8 @@ static void miro_pinnacle_gpio(struct bt
 		}
 		if (-1 != msp)
 			btv->c.type = BTTV_BOARD_PINNACLEPRO;
-		printk(KERN_INFO
-		       "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
-		       btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+		pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+			btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
 		btv->tuner_type = TUNER_MT2032;
 	}
 }
@@ -3202,7 +3201,7 @@ static void gvc1100_muxsel(struct bttv *
 
 static void init_lmlbt4x(struct bttv *btv)
 {
-	printk(KERN_DEBUG "LMLBT4x init\n");
+	pr_debug("LMLBT4x init\n");
 	btwrite(0x000000, BT848_GPIO_REG_INP);
 	gpio_inout(0xffffff, 0x0006C0);
 	gpio_write(0x000000);
@@ -3246,7 +3245,7 @@ static void bttv_reset_audio(struct bttv
 		return;
 
 	if (bttv_debug)
-		printk("bttv%d: BT878A ARESET\n",btv->c.nr);
+		pr_debug("%d: BT878A ARESET\n", btv->c.nr);
 	btwrite((1<<7), 0x058);
 	udelay(10);
 	btwrite(     0, 0x058);
@@ -3349,7 +3348,8 @@ void __devinit bttv_init_card2(struct bt
 	case BTTV_BOARD_MAGICTVIEW061:
 		if (btv->cardid == 0x3002144f) {
 			btv->has_radio=1;
-			printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
+			pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+				btv->c.nr);
 		}
 		break;
 	case BTTV_BOARD_STB2:
@@ -3438,17 +3438,16 @@ void __devinit bttv_init_card2(struct bt
 		btv->tuner_type = tuner[btv->c.nr];
 
 	if (btv->tuner_type == TUNER_ABSENT)
-		printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
-	else if(btv->tuner_type == UNSET)
-		printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
+		pr_info("%d: tuner absent\n", btv->c.nr);
+	else if (btv->tuner_type == UNSET)
+		pr_warn("%d: tuner type unset\n", btv->c.nr);
 	else
-		printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
-		       btv->tuner_type);
+		pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
 
 	if (autoload != UNSET) {
-		printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr);
-		printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr);
-		printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr);
+		pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+		pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+			btv->c.nr);
 	}
 
 	if (UNSET == btv->tuner_type)
@@ -3541,8 +3540,7 @@ void __devinit bttv_init_card2(struct bt
 	}
 
 	default:
-		printk(KERN_WARNING "bttv%d: unknown audiodev value!\n",
-			btv->c.nr);
+		pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
 		return;
 	}
 
@@ -3585,8 +3583,7 @@ void __devinit bttv_init_card2(struct bt
 		return;
 
 no_audio:
-	printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n",
-			btv->c.nr);
+	pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
 }
 
 
@@ -3639,19 +3636,19 @@ static void modtec_eeprom(struct bttv *b
 {
 	if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
 		btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
 		btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
 		btv->tuner_type=TUNER_PHILIPS_NTSC;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else {
-		printk("bttv%d: Modtec: Unknown TunerString: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Unknown TunerString: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	}
 }
 
@@ -3663,7 +3660,7 @@ static void __devinit hauppauge_eeprom(s
 	btv->tuner_type = tv.tuner_type;
 	btv->has_radio  = tv.has_radio;
 
-	printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+	pr_info("%d: Hauppauge eeprom indicates model#%d\n",
 		btv->c.nr, tv.model);
 
 	/*
@@ -3671,7 +3668,7 @@ static void __devinit hauppauge_eeprom(s
 	 * type based on model #.
 	 */
 	if(tv.model == 64900) {
-		printk("bttv%d: Switching board type from %s to %s\n",
+		pr_info("%d: Switching board type from %s to %s\n",
 			btv->c.nr,
 			bttv_tvcards[btv->c.type].name,
 			bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
@@ -3698,8 +3695,7 @@ static int terratec_active_radio_upgrade
 	freq=88000/62.5;
 	tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
 	if (0x1ed8 == tea5757_read(btv)) {
-		printk("bttv%d: Terratec Active Radio Upgrade found.\n",
-		       btv->c.nr);
+		pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
 		btv->has_radio    = 1;
 		btv->has_saa6588  = 1;
 		btv->has_matchbox = 1;
@@ -3768,13 +3764,12 @@ static int __devinit pvr_boot(struct btt
 
 	rc = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/", &btv->c.pci->dev);
 	if (rc != 0) {
-		printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
-		       btv->c.nr);
+		pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
 		return rc;
 	}
 	rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
-	printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
-	       btv->c.nr, (rc < 0) ? "failed" : "ok");
+	pr_info("%d: altera firmware upload %s\n",
+		btv->c.nr, (rc < 0) ? "failed" : "ok");
 	release_firmware(fw_entry);
 	return rc;
 }
@@ -3870,29 +3865,27 @@ static void __devinit osprey_eeprom(stru
 			break;
 		default:
 			/* unknown...leave generic, but get serial # */
-			printk(KERN_INFO "bttv%d: "
-			       "osprey eeprom: unknown card type 0x%04x\n",
-			       btv->c.nr, type);
+			pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+				btv->c.nr, type);
 			break;
 		}
 		serial = get_unaligned_be32((__be32 *)(ee+6));
 	}
 
-	printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
-	       btv->c.nr, cardid,
-	       cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+	pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+		btv->c.nr, cardid,
+		cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
 
 	if (cardid<0 || btv->c.type == cardid)
 		return;
 
 	/* card type isn't set correctly */
 	if (card[btv->c.nr] < bttv_num_tvcards) {
-		printk(KERN_WARNING "bttv%d: osprey eeprom: "
-		       "Not overriding user specified card type\n", btv->c.nr);
+		pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+			btv->c.nr);
 	} else {
-		printk(KERN_INFO "bttv%d: osprey eeprom: "
-		       "Changing card type from %d to %d\n", btv->c.nr,
-		       btv->c.type, cardid);
+		pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+			btv->c.nr, btv->c.type, cardid);
 		btv->c.type = cardid;
 	}
 }
@@ -3935,14 +3928,14 @@ static void __devinit avermedia_eeprom(s
 		if (tuner_format == 0x09)
 			tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
 
-	printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+	pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
 		btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
 	if (tuner_type) {
 		btv->tuner_type = tuner_type;
-		printk(KERN_CONT "%d", tuner_type);
+		pr_cont("%d", tuner_type);
 	} else
-		printk(KERN_CONT "Unknown type");
-	printk(KERN_CONT " radio:%s remote control:%s\n",
+		pr_cont("Unknown type");
+	pr_cont(" radio:%s remote control:%s\n",
 	       tuner_tv_fm     ? "yes" : "no",
 	       btv->has_remote ? "yes" : "no");
 }
@@ -3990,8 +3983,8 @@ static void __devinit boot_msp34xx(struc
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"msp34xx");
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
-		       "init [%d]\n", btv->c.nr, pin);
+		pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+			btv->c.nr, pin);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4031,7 +4024,7 @@ static void __devinit init_PXC200(struct
 	btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
 
 	/*	Initialise MAX517 DAC */
-	printk(KERN_INFO "Setting DAC reference voltage level ...\n");
+	pr_info("Setting DAC reference voltage level ...\n");
 	bttv_I2CWrite(btv,0x5E,0,0x80,1);
 
 	/*	Initialise 12C508 PIC */
@@ -4040,7 +4033,7 @@ static void __devinit init_PXC200(struct
 	 *	argument so the numbers are different */
 
 
-	printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
+	pr_info("Initialising 12C508 PIC chip ...\n");
 
 	/* First of all, enable the clock line. This is used in the PXC200-F */
 	val = btread(BT848_GPIO_DMA_CTL);
@@ -4059,13 +4052,12 @@ static void __devinit init_PXC200(struct
 	for (i = 0; i < ARRAY_SIZE(vals); i++) {
 		tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
 		if (tmp != -1) {
-			printk(KERN_INFO
-			       "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+			pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
 			       vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
 		}
 	}
 
-	printk(KERN_INFO "PXC200 Initialised.\n");
+	pr_info("PXC200 Initialised\n");
 }
 
 
@@ -4104,8 +4096,7 @@ init_RTV24 (struct bttv *btv)
 	uint32_t dataRead = 0;
 	long watchdog_value = 0x0E;
 
-	printk (KERN_INFO
-		"bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+	pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
 		btv->c.nr);
 
 	btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
@@ -4119,8 +4110,7 @@ init_RTV24 (struct bttv *btv)
 	dataRead = btread (BT848_GPIO_DATA);
 
 	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
-		printk (KERN_INFO
-			"bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+		pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
 			btv->c.nr, dataRead);
 	}
 
@@ -4133,15 +4123,13 @@ init_RTV24 (struct bttv *btv)
 	dataRead = btread (BT848_GPIO_DATA);
 
 	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
-		printk (KERN_INFO
-			"bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+		pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
 			btv->c.nr, dataRead);
 
 		return;
 	}
 
-	printk (KERN_INFO
-		"bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+	pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
 }
 
 
@@ -4258,22 +4246,25 @@ static int tea5757_read(struct bttv *btv
 	while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
 		schedule();
 	if (bus_in(btv,btv->mbox_data)) {
-		printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr);
+		pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
 		return -1;
 	}
 
-	dprintk("bttv%d: tea5757:",btv->c.nr);
+	dprintk("%d: tea5757:", btv->c.nr);
 	for (i = 0; i < 24; i++) {
 		udelay(5);
 		bus_high(btv,btv->mbox_clk);
 		udelay(5);
-		dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-');
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
 		bus_low(btv,btv->mbox_clk);
 		value <<= 1;
 		value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
-		dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M');
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
 	}
-	dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value);
+	dprintk_cont("\n");
+	dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
 	return value;
 }
 
@@ -4292,7 +4283,7 @@ static int tea5757_write(struct bttv *bt
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"tea5757 write");
 
-	dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value);
+	dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
 	bus_low(btv,btv->mbox_clk);
 	bus_high(btv,btv->mbox_we);
 	for (i = 0; i < 25; i++) {
@@ -4544,7 +4535,7 @@ static void picolo_tetra_init(struct btt
 static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
 {
 
-	dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel =>  input = %d\n",btv->c.nr,input);
+	dprintk("%d : picolo_tetra_muxsel =>  input = %d\n", btv->c.nr, input);
 	/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
 	/*GPIO[20]&GPIO[21] used to choose the right input*/
 	btwrite (input<<20,BT848_GPIO_DATA);
@@ -4589,7 +4580,7 @@ static void ivc120_muxsel(struct bttv *b
 	int key = input % 4;
 	int matrix = input / 4;
 
-	dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+	dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
 		btv->c.nr, input, matrix, key);
 
 	/* Handles the input selection on the TDA8540's */
@@ -4646,15 +4637,17 @@ static void PXC200_muxsel(struct bttv *b
 	buf[1]=0;
 	rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
 	if (rc) {
-	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
+		pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+			 btv->c.nr, rc);
 	  /* not PXC ? do nothing */
-	  return;
+		return;
 	}
 
 	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
 	if (!(rc & PX_CFG_PXC200F)) {
-	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
-	  return;
+		pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+			 btv->c.nr, rc);
+		return;
 	}
 
 
@@ -4693,7 +4686,7 @@ static void PXC200_muxsel(struct bttv *b
 	else /* older device */
 	  btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
 
-	printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
+	pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
 }
 
 static void phytec_muxsel(struct bttv *btv, unsigned int input)
@@ -4844,29 +4837,27 @@ void __init bttv_check_chipset(void)
 
 	/* print warnings about any quirks found */
 	if (triton1)
-		printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
+		pr_info("Host bridge needs ETBF enabled\n");
 	if (vsfx)
-		printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
+		pr_info("Host bridge needs VSFX enabled\n");
 	if (pcipci_fail) {
-		printk(KERN_INFO "bttv: bttv and your chipset may not work "
-							"together.\n");
+		pr_info("bttv and your chipset may not work together\n");
 		if (!no_overlay) {
-			printk(KERN_INFO "bttv: overlay will be disabled.\n");
+			pr_info("overlay will be disabled\n");
 			no_overlay = 1;
 		} else {
-			printk(KERN_INFO "bttv: overlay forced. Use this "
-						"option at your own risk.\n");
+			pr_info("overlay forced. Use this option at your own risk.\n");
 		}
 	}
 	if (UNSET != latency)
-		printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
+		pr_info("pci latency fixup [%d]\n", latency);
 	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				      PCI_DEVICE_ID_INTEL_82441, dev))) {
 		unsigned char b;
 		pci_read_config_byte(dev, 0x53, &b);
 		if (bttv_debug)
-			printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "
-			       "bufcon=0x%02x\n",b);
+			pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+				b);
 	}
 }
 
@@ -4879,12 +4870,13 @@ int __devinit bttv_handle_chipset(struct
 
 	if (bttv_verbose) {
 		if (triton1)
-			printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr);
+			pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+				btv->c.nr);
 		if (vsfx && btv->id >= 878)
-			printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr);
+			pr_info("%d: enabling VSFX\n", btv->c.nr);
 		if (UNSET != latency)
-			printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
-			       btv->c.nr,latency);
+			pr_info("%d: setting pci timer to %d\n",
+				btv->c.nr, latency);
 	}
 
 	if (btv->id < 878) {
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-driver.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-driver.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -942,8 +944,8 @@ static
 void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 {
 	if ((fh->resources & bits) != bits) {
-		/* trying to free ressources not allocated by us ... */
-		printk("bttv: BUG! (btres)\n");
+		/* trying to free resources not allocated by us ... */
+		pr_err("BUG! (btres)\n");
 	}
 	fh->resources  &= ~bits;
 	btv->resources &= ~bits;
@@ -1000,7 +1002,7 @@ static void set_pll(struct bttv *btv)
 		return;
 
 	if (btv->pll.pll_ofreq == btv->pll.pll_current) {
-		dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
+		dprintk("%d: PLL: no change required\n", btv->c.nr);
 		return;
 	}
 
@@ -1008,21 +1010,23 @@ static void set_pll(struct bttv *btv)
 		/* no PLL needed */
 		if (btv->pll.pll_current == 0)
 			return;
-		bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
-			btv->c.nr,btv->pll.pll_ifreq);
+		if (bttv_verbose)
+			pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+				btv->c.nr, btv->pll.pll_ifreq);
 		btwrite(0x00,BT848_TGCTRL);
 		btwrite(0x00,BT848_PLL_XCI);
 		btv->pll.pll_current = 0;
 		return;
 	}
 
-	bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
-		btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+	if (bttv_verbose)
+		pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+			btv->c.nr,
+			btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 	set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
 	for (i=0; i<10; i++) {
 		/*  Let other people run while the PLL stabilizes */
-		bttv_printk(".");
 		msleep(10);
 
 		if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -1030,12 +1034,14 @@ static void set_pll(struct bttv *btv)
 		} else {
 			btwrite(0x08,BT848_TGCTRL);
 			btv->pll.pll_current = btv->pll.pll_ofreq;
-			bttv_printk(" ok\n");
+			if (bttv_verbose)
+				pr_info("PLL set ok\n");
 			return;
 		}
 	}
 	btv->pll.pll_current = -1;
-	bttv_printk("failed\n");
+	if (bttv_verbose)
+		pr_info("Setting PLL failed\n");
 	return;
 }
 
@@ -1047,7 +1053,7 @@ static void bt848A_set_timing(struct btt
 	int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
 
 	if (btv->input == btv->dig) {
-		dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
+		dprintk("%d: load digital timing table (table_idx=%d)\n",
 			btv->c.nr,table_idx);
 
 		/* timing change...reset timing generator address */
@@ -1076,7 +1082,7 @@ static void bt848_bright(struct bttv *bt
 {
 	int value;
 
-	// printk("bttv: set bright: %d\n",bright); // DEBUG
+	// printk("set bright: %d\n", bright); // DEBUG
 	btv->bright = bright;
 
 	/* We want -128 to 127 we get 0-65535 */
@@ -1150,8 +1156,7 @@ video_mux(struct bttv *btv, unsigned int
 	}
 	mux = bttv_muxsel(btv, input);
 	btaor(mux<<5, ~(3<<5), BT848_IFORM);
-	dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
-		btv->c.nr,input,mux);
+	dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
 
 	/* card specific hook */
 	if(bttv_tvcards[btv->c.type].muxsel_hook)
@@ -1440,7 +1445,7 @@ static void bttv_reinit_bt848(struct btt
 	unsigned long flags;
 
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
+		pr_info("%d: reset, reinitialize\n", btv->c.nr);
 	spin_lock_irqsave(&btv->s_lock,flags);
 	btv->errors=0;
 	bttv_set_dma(btv,0);
@@ -1622,8 +1627,8 @@ void bttv_gpio_tracking(struct bttv *btv
 	unsigned int outbits, data;
 	outbits = btread(BT848_GPIO_OUT_EN);
 	data    = btread(BT848_GPIO_DATA);
-	printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
-	       btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
+	pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+		 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
 }
 
 static void bttv_field_count(struct bttv *btv)
@@ -1668,7 +1673,7 @@ bttv_switch_overlay(struct bttv *btv, st
 	unsigned long flags;
 	int retval = 0;
 
-	dprintk("switch_overlay: enter [new=%p]\n",new);
+	dprintk("switch_overlay: enter [new=%p]\n", new);
 	if (new)
 		new->vb.state = VIDEOBUF_DONE;
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -1678,7 +1683,8 @@ bttv_switch_overlay(struct bttv *btv, st
 	bttv_set_dma(btv, 0x03);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
 	if (NULL != old) {
-		dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
+		dprintk("switch_overlay: old=%p state is %d\n",
+			old, old->vb.state);
 		bttv_dma_free(&fh->cap,btv, old);
 		kfree(old);
 	}
@@ -2029,11 +2035,11 @@ static int bttv_log_status(struct file *
 	struct bttv_fh *fh  = f;
 	struct bttv *btv = fh->btv;
 
-	printk(KERN_INFO "bttv%d: ========  START STATUS CARD #%d  ========\n",
-			btv->c.nr, btv->c.nr);
+	pr_info("%d: ========  START STATUS CARD #%d  ========\n",
+		btv->c.nr, btv->c.nr);
 	bttv_call_all(btv, core, log_status);
-	printk(KERN_INFO "bttv%d: ========  END STATUS CARD   #%d  ========\n",
-			btv->c.nr, btv->c.nr);
+	pr_info("%d: ========  END STATUS CARD   #%d  ========\n",
+		btv->c.nr, btv->c.nr);
 	return 0;
 }
 
@@ -2598,7 +2604,7 @@ static int bttv_s_fmt_vid_overlay(struct
 	struct bttv *btv = fh->btv;
 
 	if (no_overlay > 0) {
-		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
 
@@ -2673,7 +2679,7 @@ static int bttv_enum_fmt_vid_overlay(str
 	int rc;
 
 	if (no_overlay > 0) {
-		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
 
@@ -2714,7 +2720,7 @@ static int bttv_overlay(struct file *fil
 			return -EINVAL;
 		}
 		if (unlikely(!fh->ov.setup_ok)) {
-			dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
+			dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
 			retval = -EINVAL;
 		}
 		if (retval)
@@ -3091,8 +3097,8 @@ static ssize_t bttv_read(struct file *fi
 
 	if (fh->btv->errors)
 		bttv_reinit_bt848(fh->btv);
-	dprintk("bttv%d: read count=%d type=%s\n",
-		fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
+	dprintk("%d: read count=%d type=%s\n",
+		fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -3174,7 +3180,7 @@ static int bttv_open(struct file *file)
 	struct bttv_fh *fh;
 	enum v4l2_buf_type type = 0;
 
-	dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
 
 	if (vdev->vfl_type == VFL_TYPE_GRABBER) {
 		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -3185,8 +3191,8 @@ static int bttv_open(struct file *file)
 		return -ENODEV;
 	}
 
-	dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
-		btv->c.nr,v4l2_type_names[type]);
+	dprintk("%d: open called (type=%s)\n",
+		btv->c.nr, v4l2_type_names[type]);
 
 	/* allocate per filehandle data */
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3288,7 +3294,7 @@ bttv_mmap(struct file *file, struct vm_a
 {
 	struct bttv_fh *fh = file->private_data;
 
-	dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
+	dprintk("%d: mmap type=%s 0x%lx+%ld\n",
 		fh->btv->c.nr, v4l2_type_names[fh->type],
 		vma->vm_start, vma->vm_end - vma->vm_start);
 	return videobuf_mmap_mapper(bttv_queue(fh),vma);
@@ -3370,9 +3376,9 @@ static int radio_open(struct file *file)
 	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
 
-	dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
 
-	dprintk("bttv%d: open called (radio)\n",btv->c.nr);
+	dprintk("%d: open called (radio)\n", btv->c.nr);
 
 	/* allocate per filehandle data */
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3616,12 +3622,12 @@ static int bttv_risc_decode(u32 risc)
 	};
 	int i;
 
-	printk("0x%08x [ %s", risc,
+	pr_cont("0x%08x [ %s", risc,
 	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
 	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
 		if (risc & (1 << (i + 12)))
-			printk(" %s",bits[i]);
-	printk(" count=%d ]\n", risc & 0xfff);
+			pr_cont(" %s", bits[i]);
+	pr_cont(" count=%d ]\n", risc & 0xfff);
 	return incr[risc >> 28] ? incr[risc >> 28] : 1;
 }
 
@@ -3630,16 +3636,18 @@ static void bttv_risc_disasm(struct bttv
 {
 	unsigned int i,j,n;
 
-	printk("%s: risc disasm: %p [dma=0x%08lx]\n",
-	       btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+	pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+		btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
 	for (i = 0; i < (risc->size >> 2); i += n) {
-		printk("%s:   0x%lx: ", btv->c.v4l2_dev.name,
-		       (unsigned long)(risc->dma + (i<<2)));
+		pr_info("%s:   0x%lx: ",
+			btv->c.v4l2_dev.name,
+			(unsigned long)(risc->dma + (i<<2)));
 		n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
 		for (j = 1; j < n; j++)
-			printk("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
-			       btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
-			       risc->cpu[i+j], j);
+			pr_info("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
+				btv->c.v4l2_dev.name,
+				(unsigned long)(risc->dma + ((i+j)<<2)),
+				risc->cpu[i+j], j);
 		if (0 == risc->cpu[i])
 			break;
 	}
@@ -3647,17 +3655,18 @@ static void bttv_risc_disasm(struct bttv
 
 static void bttv_print_riscaddr(struct bttv *btv)
 {
-	printk("  main: %08Lx\n",
-	       (unsigned long long)btv->main.dma);
-	printk("  vbi : o=%08Lx e=%08Lx\n",
-	       btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
-	       btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
-	printk("  cap : o=%08Lx e=%08Lx\n",
-	       btv->curr.top    ? (unsigned long long)btv->curr.top->top.dma : 0,
-	       btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
-	printk("  scr : o=%08Lx e=%08Lx\n",
-	       btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
-	       btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+	pr_info("  main: %08llx\n", (unsigned long long)btv->main.dma);
+	pr_info("  vbi : o=%08llx e=%08llx\n",
+		btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+		btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+	pr_info("  cap : o=%08llx e=%08llx\n",
+		btv->curr.top
+		? (unsigned long long)btv->curr.top->top.dma : 0,
+		btv->curr.bottom
+		? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+	pr_info("  scr : o=%08llx e=%08llx\n",
+		btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+		btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
 	bttv_risc_disasm(btv, &btv->main);
 }
 
@@ -3690,34 +3699,34 @@ static void bttv_print_irqbits(u32 print
 {
 	unsigned int i;
 
-	printk("bits:");
+	pr_cont("bits:");
 	for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
 		if (print & (1 << i))
-			printk(" %s",irq_name[i]);
+			pr_cont(" %s", irq_name[i]);
 		if (mark & (1 << i))
-			printk("*");
+			pr_cont("*");
 	}
 }
 
 static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
 {
-	printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
-	       btv->c.nr,
-	       (unsigned long)btv->main.dma,
-	       (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
-	       (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
-	       (unsigned long)rc);
+	pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+		btv->c.nr,
+		(unsigned long)btv->main.dma,
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+		(unsigned long)rc);
 
 	if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
-		printk("bttv%d: Oh, there (temporarely?) is no input signal. "
-		       "Ok, then this is harmless, don't worry ;)\n",
-		       btv->c.nr);
+		pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+			  "Ok, then this is harmless, don't worry ;)\n",
+			  btv->c.nr);
 		return;
 	}
-	printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
-	       btv->c.nr);
-	printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
-	       btv->c.nr);
+	pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+		  btv->c.nr);
+	pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+		  btv->c.nr);
 	dump_stack();
 }
 
@@ -3798,9 +3807,9 @@ bttv_irq_next_video(struct bttv *btv, st
 		}
 	}
 
-	dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
-		btv->c.nr,set->top, set->bottom,
-		btv->screen,set->frame_irq,set->top_irq);
+	dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+		btv->c.nr, set->top, set->bottom,
+		btv->screen, set->frame_irq, set->top_irq);
 	return 0;
 }
 
@@ -3815,7 +3824,8 @@ bttv_irq_wakeup_video(struct bttv *btv,
 	if (wakeup->top == wakeup->bottom) {
 		if (NULL != wakeup->top && curr->top != wakeup->top) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
+				pr_debug("%d: wakeup: both=%p\n",
+					 btv->c.nr, wakeup->top);
 			wakeup->top->vb.ts = ts;
 			wakeup->top->vb.field_count = btv->field_count;
 			wakeup->top->vb.state = state;
@@ -3824,7 +3834,8 @@ bttv_irq_wakeup_video(struct bttv *btv,
 	} else {
 		if (NULL != wakeup->top && curr->top != wakeup->top) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
+				pr_debug("%d: wakeup: top=%p\n",
+					 btv->c.nr, wakeup->top);
 			wakeup->top->vb.ts = ts;
 			wakeup->top->vb.field_count = btv->field_count;
 			wakeup->top->vb.state = state;
@@ -3832,7 +3843,8 @@ bttv_irq_wakeup_video(struct bttv *btv,
 		}
 		if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
+				pr_debug("%d: wakeup: bottom=%p\n",
+					 btv->c.nr, wakeup->bottom);
 			wakeup->bottom->vb.ts = ts;
 			wakeup->bottom->vb.field_count = btv->field_count;
 			wakeup->bottom->vb.state = state;
@@ -3866,11 +3878,11 @@ static void bttv_irq_timeout(unsigned lo
 	unsigned long flags;
 
 	if (bttv_verbose) {
-		printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
-		       btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
-		       btread(BT848_RISC_COUNT));
+		pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+			btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+			btread(BT848_RISC_COUNT));
 		bttv_print_irqbits(btread(BT848_INT_STAT),0);
-		printk("\n");
+		pr_cont("\n");
 	}
 
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -4033,21 +4045,23 @@ static irqreturn_t bttv_irq(int irq, voi
 		dstat=btread(BT848_DSTATUS);
 
 		if (irq_debug) {
-			printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
-			       "riscs=%x, riscc=%08x, ",
-			       btv->c.nr, count, btv->field_count,
-			       stat>>28, btread(BT848_RISC_COUNT));
+			pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+				 btv->c.nr, count, btv->field_count,
+				 stat>>28, btread(BT848_RISC_COUNT));
 			bttv_print_irqbits(stat,astat);
 			if (stat & BT848_INT_HLOCK)
-				printk("   HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
-				       ? "yes" : "no");
+				pr_cont("   HLOC => %s",
+					dstat & BT848_DSTATUS_HLOC
+					? "yes" : "no");
 			if (stat & BT848_INT_VPRES)
-				printk("   PRES => %s", (dstat & BT848_DSTATUS_PRES)
-				       ? "yes" : "no");
+				pr_cont("   PRES => %s",
+					dstat & BT848_DSTATUS_PRES
+					? "yes" : "no");
 			if (stat & BT848_INT_FMTCHG)
-				printk("   NUML => %s", (dstat & BT848_DSTATUS_NUML)
-				       ? "625" : "525");
-			printk("\n");
+				pr_cont("   NUML => %s",
+					dstat & BT848_DSTATUS_NUML
+					? "625" : "525");
+			pr_cont("\n");
 		}
 
 		if (astat&BT848_INT_VSYNC)
@@ -4075,18 +4089,19 @@ static irqreturn_t bttv_irq(int irq, voi
 			audio_mute(btv, btv->mute);  /* trigger automute */
 
 		if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
-			printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
-			       (astat & BT848_INT_SCERR) ? "SCERR" : "",
-			       (astat & BT848_INT_OCERR) ? "OCERR" : "",
-			       btread(BT848_RISC_COUNT));
+			pr_info("%d: %s%s @ %08x,",
+				btv->c.nr,
+				(astat & BT848_INT_SCERR) ? "SCERR" : "",
+				(astat & BT848_INT_OCERR) ? "OCERR" : "",
+				btread(BT848_RISC_COUNT));
 			bttv_print_irqbits(stat,astat);
-			printk("\n");
+			pr_cont("\n");
 			if (bttv_debug)
 				bttv_print_riscaddr(btv);
 		}
 		if (fdsr && astat & BT848_INT_FDSR) {
-			printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
-			       btv->c.nr,btread(BT848_RISC_COUNT));
+			pr_info("%d: FDSR @ %08x\n",
+				btv->c.nr, btread(BT848_RISC_COUNT));
 			if (bttv_debug)
 				bttv_print_riscaddr(btv);
 		}
@@ -4097,11 +4112,11 @@ static irqreturn_t bttv_irq(int irq, voi
 			if (count > 8 || !(astat & BT848_INT_GPINT)) {
 				btwrite(0, BT848_INT_MASK);
 
-				printk(KERN_ERR
-					   "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
+				pr_err("%d: IRQ lockup, cleared int mask [",
+				       btv->c.nr);
 			} else {
-				printk(KERN_ERR
-					   "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
+				pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+				       btv->c.nr);
 
 				btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
 						BT848_INT_MASK);
@@ -4109,7 +4124,7 @@ static irqreturn_t bttv_irq(int irq, voi
 
 			bttv_print_irqbits(stat,astat);
 
-			printk("]\n");
+			pr_cont("]\n");
 		}
 	}
 	btv->irq_total++;
@@ -4171,7 +4186,7 @@ static void bttv_unregister_video(struct
 static int __devinit bttv_register_video(struct bttv *btv)
 {
 	if (no_overlay > 0)
-		printk("bttv: Overlay support disabled.\n");
+		pr_notice("Overlay support disabled\n");
 
 	/* video */
 	btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
@@ -4181,12 +4196,11 @@ static int __devinit bttv_register_video
 	if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
 				  video_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->video_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->video_dev));
 	if (device_create_file(&btv->video_dev->dev,
 				     &dev_attr_card)<0) {
-		printk(KERN_ERR "bttv%d: device_create_file 'card' "
-		       "failed\n", btv->c.nr);
+		pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
 		goto err;
 	}
 
@@ -4198,8 +4212,8 @@ static int __devinit bttv_register_video
 	if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
 				  vbi_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->vbi_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->vbi_dev));
 
 	if (!btv->has_radio)
 		return 0;
@@ -4210,8 +4224,8 @@ static int __devinit bttv_register_video
 	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
 				  radio_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->radio_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->radio_dev));
 
 	/* all done */
 	return 0;
@@ -4244,10 +4258,10 @@ static int __devinit bttv_probe(struct p
 
 	if (bttv_num == BTTV_MAX)
 		return -ENOMEM;
-	printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
+	pr_info("Bt8xx card found (%d)\n", bttv_num);
 	bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
 	if (btv == NULL) {
-		printk(KERN_ERR "bttv: out of memory.\n");
+		pr_err("out of memory\n");
 		return -ENOMEM;
 	}
 	btv->c.nr  = bttv_num;
@@ -4277,21 +4291,19 @@ static int __devinit bttv_probe(struct p
 	btv->c.pci = dev;
 	btv->id  = dev->device;
 	if (pci_enable_device(dev)) {
-		printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-		       btv->c.nr);
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
 		return -EIO;
 	}
 	if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
-		printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
-		       btv->c.nr);
+		pr_warn("%d: No suitable DMA available\n", btv->c.nr);
 		return -EIO;
 	}
 	if (!request_mem_region(pci_resource_start(dev,0),
 				pci_resource_len(dev,0),
 				btv->c.v4l2_dev.name)) {
-		printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
-		       btv->c.nr,
-		       (unsigned long long)pci_resource_start(dev,0));
+		pr_warn("%d: can't request iomem (0x%llx)\n",
+			btv->c.nr,
+			(unsigned long long)pci_resource_start(dev, 0));
 		return -EBUSY;
 	}
 	pci_set_master(dev);
@@ -4299,22 +4311,21 @@ static int __devinit bttv_probe(struct p
 
 	result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
 	if (result < 0) {
-		printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
+		pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
 		goto fail0;
 	}
 
 	btv->revision = dev->revision;
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-	printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
-	       bttv_num,btv->id, btv->revision, pci_name(dev));
-	printk("irq: %d, latency: %d, mmio: 0x%llx\n",
-	       btv->c.pci->irq, lat,
-	       (unsigned long long)pci_resource_start(dev,0));
+	pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+		bttv_num, btv->id, btv->revision, pci_name(dev),
+		btv->c.pci->irq, lat,
+		(unsigned long long)pci_resource_start(dev, 0));
 	schedule();
 
 	btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
 	if (NULL == btv->bt848_mmio) {
-		printk("bttv%d: ioremap() failed\n", btv->c.nr);
+		pr_err("%d: ioremap() failed\n", btv->c.nr);
 		result = -EIO;
 		goto fail1;
 	}
@@ -4327,8 +4338,8 @@ static int __devinit bttv_probe(struct p
 	result = request_irq(btv->c.pci->irq, bttv_irq,
 	    IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
 	if (result < 0) {
-		printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
-		       bttv_num,btv->c.pci->irq);
+		pr_err("%d: can't get IRQ %d\n",
+		       bttv_num, btv->c.pci->irq);
 		goto fail1;
 	}
 
@@ -4433,7 +4444,7 @@ static void __devexit bttv_remove(struct
 	struct bttv *btv = to_bttv(v4l2_dev);
 
 	if (bttv_verbose)
-		printk("bttv%d: unloading\n",btv->c.nr);
+		pr_info("%d: unloading\n", btv->c.nr);
 
 	if (bttv_tvcards[btv->c.type].has_dvb)
 		flush_request_modules(btv);
@@ -4481,7 +4492,7 @@ static int bttv_suspend(struct pci_dev *
 	struct bttv_buffer_set idle;
 	unsigned long flags;
 
-	dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
+	dprintk("%d: suspend %d\n", btv->c.nr, state.event);
 
 	/* stop dma + irqs */
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -4517,14 +4528,13 @@ static int bttv_resume(struct pci_dev *p
 	unsigned long flags;
 	int err;
 
-	dprintk("bttv%d: resume\n", btv->c.nr);
+	dprintk("%d: resume\n", btv->c.nr);
 
 	/* restore pci state */
 	if (btv->state.disabled) {
 		err=pci_enable_device(pci_dev);
 		if (err) {
-			printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-								btv->c.nr);
+			pr_warn("%d: Can't enable device\n", btv->c.nr);
 			return err;
 		}
 		btv->state.disabled = 0;
@@ -4532,8 +4542,7 @@ static int bttv_resume(struct pci_dev *p
 	err=pci_set_power_state(pci_dev, PCI_D0);
 	if (err) {
 		pci_disable_device(pci_dev);
-		printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-							btv->c.nr);
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
 		btv->state.disabled = 1;
 		return err;
 	}
@@ -4585,22 +4594,21 @@ static int __init bttv_init_module(void)
 
 	bttv_num = 0;
 
-	printk(KERN_INFO "bttv: driver version %s loaded\n",
-	       BTTV_VERSION);
+	pr_info("driver version %s loaded\n", BTTV_VERSION);
 	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
 		gbuffers = 2;
 	if (gbufsize > BTTV_MAX_FBUF)
 		gbufsize = BTTV_MAX_FBUF;
 	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
-		       gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+		pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+			gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
 
 	bttv_check_chipset();
 
 	ret = bus_register(&bttv_sub_bus_type);
 	if (ret < 0) {
-		printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+		pr_warn("bus_register error: %d\n", ret);
 		return ret;
 	}
 	ret = pci_register_driver(&bttv_pci_driver);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-gpio.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-gpio.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -99,7 +101,7 @@ int bttv_sub_add_device(struct bttv_core
 		kfree(sub);
 		return err;
 	}
-	printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+	pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
 	list_add_tail(&sub->list,&core->subs);
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-i2c.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -154,9 +156,7 @@ bttv_i2c_sendbytes(struct bttv *btv, con
 	if (retval == 0)
 		goto eio;
 	if (i2c_debug) {
-		printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
-		if (!(xmit & BT878_I2C_NOSTOP))
-			printk(" >\n");
+		pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
 	}
 
 	for (cnt = 1; cnt < msg->len; cnt++ ) {
@@ -170,19 +170,18 @@ bttv_i2c_sendbytes(struct bttv *btv, con
 			goto err;
 		if (retval == 0)
 			goto eio;
-		if (i2c_debug) {
-			printk(" %02x", msg->buf[cnt]);
-			if (!(xmit & BT878_I2C_NOSTOP))
-				printk(" >\n");
-		}
+		if (i2c_debug)
+			pr_cont(" %02x", msg->buf[cnt]);
 	}
+	if (!(xmit & BT878_I2C_NOSTOP))
+		pr_cont(">\n");
 	return msg->len;
 
  eio:
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n",retval);
+		pr_cont(" ERR: %d\n",retval);
 	return retval;
 }
 
@@ -193,7 +192,7 @@ bttv_i2c_readbytes(struct bttv *btv, con
 	u32 cnt;
 	int retval;
 
-	for(cnt = 0; cnt < msg->len; cnt++) {
+	for (cnt = 0; cnt < msg->len; cnt++) {
 		xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
 		if (cnt < msg->len-1)
 			xmit |= BT848_I2C_W3B;
@@ -201,6 +200,12 @@ bttv_i2c_readbytes(struct bttv *btv, con
 			xmit |= BT878_I2C_NOSTOP;
 		if (cnt)
 			xmit |= BT878_I2C_NOSTART;
+
+		if (i2c_debug) {
+			if (!(xmit & BT878_I2C_NOSTART))
+				pr_cont(" <R %02x", (msg->addr << 1) +1);
+		}
+
 		btwrite(xmit, BT848_I2C);
 		retval = bttv_i2c_wait_done(btv);
 		if (retval < 0)
@@ -209,20 +214,20 @@ bttv_i2c_readbytes(struct bttv *btv, con
 			goto eio;
 		msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
 		if (i2c_debug) {
-			if (!(xmit & BT878_I2C_NOSTART))
-				printk(" <R %02x", (msg->addr << 1) +1);
-			printk(" =%02x", msg->buf[cnt]);
-			if (!(xmit & BT878_I2C_NOSTOP))
-				printk(" >\n");
+			pr_cont(" =%02x", msg->buf[cnt]);
 		}
+		if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+			pr_cont(" >\n");
 	}
+
+
 	return msg->len;
 
  eio:
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n",retval);
+		pr_cont(" ERR: %d\n",retval);
 	return retval;
 }
 
@@ -234,7 +239,8 @@ static int bttv_i2c_xfer(struct i2c_adap
 	int i;
 
 	if (i2c_debug)
-		printk("bt-i2c:");
+		pr_debug("bt-i2c:");
+
 	btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
 	for (i = 0 ; i < num; i++) {
 		if (msgs[i].flags & I2C_M_RD) {
@@ -271,20 +277,20 @@ int bttv_I2CRead(struct bttv *btv, unsig
 	if (0 != btv->i2c_rc)
 		return -1;
 	if (bttv_verbose && NULL != probe_for)
-		printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
-		       btv->c.nr,probe_for,addr);
+		pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+			btv->c.nr, probe_for, addr);
 	btv->i2c_client.addr = addr >> 1;
 	if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
 		if (NULL != probe_for) {
 			if (bttv_verbose)
-				printk("not found\n");
+				pr_cont("not found\n");
 		} else
-			printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
-			       btv->c.nr,addr);
+			pr_warn("%d: i2c read 0x%x: error\n",
+				btv->c.nr, addr);
 		return -1;
 	}
 	if (bttv_verbose && NULL != probe_for)
-		printk("found\n");
+		pr_cont("found\n");
 	return buffer;
 }
 
@@ -335,8 +341,8 @@ static void do_i2c_scan(char *name, stru
 		rc = i2c_master_recv(c,&buf,0);
 		if (rc < 0)
 			continue;
-		printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
-		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+			name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-input.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-input.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -36,9 +38,10 @@ static int ir_rc5_remote_gap = 885;
 module_param(ir_rc5_remote_gap, int, 0644);
 
 #undef dprintk
-#define dprintk(arg...) do {	\
-	if (ir_debug >= 1)	\
-		printk(arg);	\
+#define dprintk(fmt, ...)			\
+do {						\
+	if (ir_debug >= 1)			\
+		pr_info(fmt, ##__VA_ARGS__);	\
 } while (0)
 
 #define DEVNAME "bttv-input"
@@ -62,7 +65,7 @@ static void ir_handle_key(struct bttv *b
 
 	/* extract data */
 	data = ir_extract_bits(gpio, ir->mask_keycode);
-	dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+	dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
 		gpio, data,
 		ir->polling               ? "poll"  : "irq",
 		(gpio & ir->mask_keydown) ? " down" : "",
@@ -96,7 +99,7 @@ static void ir_enltv_handle_key(struct b
 	keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
 
 	if ((ir->last_gpio & 0x7f) != data) {
-		dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+		dprintk("gpio=0x%x code=%d | %s\n",
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "up/down");
 
@@ -107,7 +110,7 @@ static void ir_enltv_handle_key(struct b
 		if ((ir->last_gpio & 1 << 31) == keyup)
 			return;
 
-		dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+		dprintk("(cnt) gpio=0x%x code=%d | %s\n",
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "down");
 
@@ -177,13 +180,12 @@ static u32 bttv_rc5_decode(unsigned int
 			rc5 |= 1;
 		break;
 		case 3:
-			dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n",
+			dprintk("rc5_decode(%x) bad code\n",
 				org_code);
 			return 0;
 		}
 	}
-	dprintk(KERN_INFO DEVNAME ":"
-		"code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+	dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
 		"instr=%x\n", rc5, org_code, RC5_START(rc5),
 		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
 	return rc5;
@@ -212,20 +214,20 @@ static void bttv_rc5_timer_end(unsigned
 
 	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
 	if (gap < 28000) {
-		dprintk(KERN_INFO DEVNAME ": spurious timer_end\n");
+		dprintk("spurious timer_end\n");
 		return;
 	}
 
 	if (ir->last_bit < 20) {
 		/* ignore spurious codes (caused by light/other remotes) */
-		dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code);
+		dprintk("short code: %x\n", ir->code);
 	} else {
 		ir->code = (ir->code << ir->shift_by) | 1;
 		rc5 = bttv_rc5_decode(ir->code);
 
 		/* two start bits? */
 		if (RC5_START(rc5) != ir->start) {
-			printk(KERN_INFO DEVNAME ":"
+			pr_info(DEVNAME ":"
 			       " rc5 start bits invalid: %u\n", RC5_START(rc5));
 
 			/* right address? */
@@ -235,8 +237,7 @@ static void bttv_rc5_timer_end(unsigned
 
 			/* Good code */
 			rc_keydown(ir->dev, instr, toggle);
-			dprintk(KERN_INFO DEVNAME ":"
-				" instruction %x, toggle %x\n",
+			dprintk("instruction %x, toggle %x\n",
 				instr, toggle);
 		}
 	}
@@ -265,7 +266,7 @@ static int bttv_rc5_irq(struct bttv *btv
 		    tv.tv_usec - ir->base_time.tv_usec;
 	}
 
-	dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n",
+	dprintk("RC5 IRQ: gap %d us for %s\n",
 		gap, (gpio & 0x20) ? "mark" : "space");
 
 	/* remote IRQ? */
@@ -340,14 +341,14 @@ static int get_key_pv951(struct IR_i2c *
 
 	/* poll IR chip */
 	if (1 != i2c_master_recv(ir->c, &b, 1)) {
-		dprintk(KERN_INFO DEVNAME ": read error\n");
+		dprintk("read error\n");
 		return -EIO;
 	}
 
 	/* ignore 0xaa */
 	if (b==0xaa)
 		return 0;
-	dprintk(KERN_INFO DEVNAME ": key %02x\n", b);
+	dprintk("key %02x\n", b);
 
 	/*
 	 * NOTE:
@@ -517,7 +518,7 @@ int bttv_input_init(struct bttv *btv)
 		break;
 	}
 	if (NULL == ir_codes) {
-		dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+		dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
 		err = -ENODEV;
 		goto err_out_free;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttvp.h linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttvp.h
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttvp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttvp.h	2012-01-04 18:55:44.000000000 -0500
@@ -310,9 +310,21 @@ extern unsigned int bttv_gpio;
 extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
 extern int init_bttv_i2c(struct bttv *btv);
 
-#define bttv_printk if (bttv_verbose) printk
-#define dprintk  if (bttv_debug >= 1) printk
-#define d2printk if (bttv_debug >= 2) printk
+#define dprintk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_debug(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define dprintk_cont(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_cont(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define d2printk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 2)			\
+		printk(fmt, ##__VA_ARGS__);	\
+} while (0)
 
 #define BTTV_MAX_FBUF   0x208000
 #define BTTV_TIMEOUT    msecs_to_jiffies(500)    /* 0.5 seconds */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-risc.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-risc.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-risc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-risc.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -473,8 +475,7 @@ bttv_set_dma(struct bttv *btv, int overr
 	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
 	capctl |= override;
 
-	d2printk(KERN_DEBUG
-		 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
+	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
 		 btv->c.nr,capctl,btv->loop_irq,
 		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
@@ -517,8 +518,8 @@ bttv_risc_init_main(struct bttv *btv)
 
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
 		return rc;
-	dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
-		btv->c.nr,(unsigned long long)btv->main.dma);
+	dprintk("%d: risc main @ %08llx\n",
+		btv->c.nr, (unsigned long long)btv->main.dma);
 
 	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
 				       BT848_FIFO_STATUS_VRE);
@@ -557,12 +558,12 @@ bttv_risc_hook(struct bttv *btv, int slo
 	unsigned long next = btv->main.dma + ((slot+2) << 2);
 
 	if (NULL == risc) {
-		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
-			 btv->c.nr,risc,slot);
+		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
 		btv->main.cpu[slot+1] = cpu_to_le32(next);
 	} else {
-		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
-			 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
+		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+			 btv->c.nr, risc, slot,
+			 (unsigned long long)risc->dma, irqflags);
 		cmd = BT848_RISC_JUMP;
 		if (irqflags) {
 			cmd |= BT848_RISC_IRQ;
@@ -708,8 +709,7 @@ bttv_buffer_risc(struct bttv *btv, struc
 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 
-	dprintk(KERN_DEBUG
-		"bttv%d: buffer field: %s  format: %s  size: %dx%d\n",
+	dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
 		btv->c.nr, v4l2_field_names[buf->vb.field],
 		buf->fmt->name, buf->vb.width, buf->vb.height);
 
@@ -870,10 +870,9 @@ bttv_overlay_risc(struct bttv *btv,
 		  struct bttv_buffer *buf)
 {
 	/* check interleave, bottom+top fields */
-	dprintk(KERN_DEBUG
-		"bttv%d: overlay fields: %s format: %s  size: %dx%d\n",
+	dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
 		btv->c.nr, v4l2_field_names[buf->vb.field],
-		fmt->name,ov->w.width,ov->w.height);
+		fmt->name, ov->w.width, ov->w.height);
 
 	/* calculate geometry */
 	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-vbi.c linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-vbi.c
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/bttv-vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/bttv-vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -65,8 +67,11 @@ MODULE_PARM_DESC(vbi_debug,"vbi code deb
 #ifdef dprintk
 # undef dprintk
 #endif
-#define dprintk(fmt, arg...)	if (vbi_debug) \
-	printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
+#define dprintk(fmt, ...)						\
+do {									\
+	if (vbi_debug)							\
+		pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);		\
+} while (0)
 
 #define IMAGE_SIZE(fmt) \
 	(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/bt8xx/Makefile linux-libre-3.2-gnu1/drivers/media/video/bt8xx/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/bt8xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/bt8xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,6 @@ bttv-objs      :=      bttv-driver.o btt
 
 obj-$(CONFIG_VIDEO_BT848) += bttv.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cpia2/cpia2_usb.c linux-libre-3.2-gnu1/drivers/media/video/cpia2/cpia2_usb.c
--- linux-libre-3.1-gnu1/drivers/media/video/cpia2/cpia2_usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cpia2/cpia2_usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "cpia2.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-driver.c linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-driver.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-driver.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-driver.c	2013-05-01 23:42:04.000000000 -0400
@@ -1085,6 +1085,8 @@ static int __devinit cx18_probe(struct p
 		setup.addr = ADDR_UNSET;
 		setup.type = cx->options.tuner;
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (cx->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
 			cx18_reset_tuner_gpio : NULL;
 		cx18_call_all(cx, tuner, s_type_addr, &setup);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-driver.h linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-driver.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-driver.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-driver.h	2012-01-04 18:55:44.000000000 -0500
@@ -409,6 +409,7 @@ struct cx18_stream {
 
 	/* Videobuf for YUV video */
 	u32 pixelformat;
+	u32 vb_bytes_per_frame;
 	struct list_head vb_capture;    /* video capture queue */
 	spinlock_t vb_lock;
 	struct timer_list vb_timeout;
@@ -430,10 +431,6 @@ struct cx18_open_id {
 	u32 open_id;
 	int type;
 	struct cx18 *cx;
-
-	struct videobuf_queue vbuf_q;
-	spinlock_t s_lock; /* Protect vbuf_q */
-	enum v4l2_buf_type vb_type;
 };
 
 static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-fileops.c linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-fileops.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-fileops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-fileops.c	2012-01-04 18:55:44.000000000 -0500
@@ -784,8 +784,6 @@ int cx18_v4l2_close(struct file *filp)
 		cx18_release_stream(s);
 	} else {
 		cx18_stop_capture(id, 0);
-		if (id->type == CX18_ENC_STREAM_TYPE_YUV)
-			videobuf_mmap_free(&id->vbuf_q);
 	}
 	kfree(id);
 	mutex_unlock(&cx->serialize_lock);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-ioctl.c linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-ioctl.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,12 +160,7 @@ static int cx18_g_fmt_vid_cap(struct fil
 	pixfmt->priv = 0;
 	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = s->pixelformat;
-		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-		if (s->pixelformat == V4L2_PIX_FMT_HM12)
-			pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
-		else
-			pixfmt->sizeimage = pixfmt->height * 720 * 2;
+		pixfmt->sizeimage = s->vb_bytes_per_frame;
 		pixfmt->bytesperline = 720;
 	} else {
 		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,6 +291,12 @@ static int cx18_s_fmt_vid_cap(struct fil
 		return -EBUSY;
 
 	s->pixelformat = fmt->fmt.pix.pixelformat;
+	/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+	   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+	if (s->pixelformat == V4L2_PIX_FMT_HM12)
+		s->vb_bytes_per_frame = h * 720 * 3 / 2;
+	else
+		s->vb_bytes_per_frame = h * 720 * 2;
 
 	mbus_fmt.width = cx->cxhdl.width = w;
 	mbus_fmt.height = cx->cxhdl.height = h;
@@ -463,13 +464,16 @@ static int cx18_s_register(struct file *
 static int cx18_querycap(struct file *file, void *fh,
 				struct v4l2_capability *vcap)
 {
-	struct cx18 *cx = fh2id(fh)->cx;
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
 
 	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
 	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
 		 "PCI:%s", pci_name(cx->pci_dev));
 	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+		vcap->capabilities |= V4L2_CAP_STREAMING;
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-mailbox.c linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-mailbox.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@ static void cx18_mdl_send_to_videobuf(st
 	}
 
 	/* If we've filled the buffer as per the callers res then dispatch it */
-	if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
+	if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
 		dispatch = 1;
 		vb_buf->bytes_used = 0;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-mailbox.h linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-mailbox.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-mailbox.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-mailbox.h	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@ struct cx18_mailbox {
     /* Each command can have up to 6 arguments */
     u32       args[MAX_MB_ARGUMENTS];
     /* The return code can be one of the codes in the file cx23418.h. If the
-       command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+       command is completed successfully, the error will be ERR_SYS_SUCCESS.
        If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
        code would indicate the task from which the error originated and will
        be one of the errors in cx23418.h. In that case, the following
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-streams.c linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-streams.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/cx18-streams.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/cx18-streams.c	2012-01-04 18:55:44.000000000 -0500
@@ -138,6 +138,12 @@ static int cx18_prepare_buffer(struct vi
 		buf->tvnorm    = cx->std;
 		s->pixelformat = pixelformat;
 
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
 		cx18_dma_free(q, s, buf);
 	}
 
@@ -154,6 +160,12 @@ static int cx18_prepare_buffer(struct vi
 		buf->tvnorm    = cx->std;
 		s->pixelformat = pixelformat;
 
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
 		rc = videobuf_iolock(q, &buf->vb, NULL);
 		if (rc != 0)
 			goto fail;
@@ -287,6 +299,7 @@ static void cx18_stream_init(struct cx18
 
 		/* Assume the previous pixel default */
 		s->pixelformat = V4L2_PIX_FMT_HM12;
+		s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
 	}
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx18/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx18/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx18/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx18/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,6 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-
 obj-$(CONFIG_VIDEO_CX18) += cx18.o
 obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx231xx/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx231xx/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx231xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx231xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
 obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
 obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-usb
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-alsa.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-alsa.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-alsa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-alsa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,535 @@
+/*
+ *
+ *  Support for CX23885 analog audio capture
+ *
+ *    (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
+ *    Adapted from cx88-alsa.c
+ *    (c) 2009 Steven Toth <stoth@kernellabs.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include <sound/tlv.h>
+
+
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH07
+
+#define dprintk(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static unsigned int disable_analog_audio;
+module_param(disable_analog_audio, int, 0644);
+MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
+
+/****************************************************************************
+			Board specific funtions
+ ****************************************************************************/
+
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_audio_buffer *buf = chip->buf;
+	struct cx23885_dev *dev  = chip->dev;
+	struct sram_channel *audio_ch =
+		&dev->sram_channels[AUDIO_SRAM_CHANNEL];
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* setup fifo + format - out channel */
+	cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
+		buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_INT_A_LNGTH, buf->bpl);
+
+	/* This is required to get good audio (1 seems to be ok) */
+	cx_write(AUD_INT_A_MODE, 1);
+
+	/* reset counter */
+	cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+		"byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUDIO_INT_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* start dma */
+	cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+	cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
+					  RISC enable */
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev, audio_ch);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_dev *dev = chip->dev;
+	dprintk(1, "Stopping audio DMA\n");
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Handles audio IRQ
+ */
+int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	if (0 == (status & mask))
+		return 0;
+
+	cx_write(AUDIO_INT_INT_STAT, status);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+			dev->name);
+		cx_clear(AUD_INT_DMA_CTL, 0x11);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		dprintk(1, "Downstream sync error\n");
+		cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return 1;
+	}
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+	/* FIXME: Any other status should deserve a special handling? */
+
+	return 1;
+}
+
+static int dsp_buffer_free(struct cx23885_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	4096
+
+static struct snd_pcm_hardware snd_cx23885_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE/4,
+	.period_bytes_max = DEFAULT_FIFO_SIZE/4,
+	.periods_min = 1,
+	.periods_max = 1024,
+	.buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	if (!chip) {
+		printk(KERN_ERR "BUG: cx23885 can't find device struct."
+				" Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx23885_digital_hw;
+
+	if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+		DEFAULT_FIFO_SIZE) {
+		unsigned int bpl = chip->dev->
+			sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
+		bpl &= ~7; /* must be multiple of 8 */
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx23885_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx23885_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+				   chip->period_size, chip->num_periods, 1);
+	if (ret < 0)
+		goto error;
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
+{
+
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
+	int cmd)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = cx23885_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = cx23885_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx23885_pointer(
+	struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
+				unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx23885_pcm_ops = {
+	.open = snd_cx23885_pcm_open,
+	.close = snd_cx23885_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx23885_hw_params,
+	.hw_free = snd_cx23885_hw_free,
+	.prepare = snd_cx23885_prepare,
+	.trigger = snd_cx23885_card_trigger,
+	.pointer = snd_cx23885_pointer,
+	.page = snd_cx23885_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
+	char *name)
+{
+	int err;
+	struct snd_pcm *pcm;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
+{
+	struct snd_card *card;
+	struct cx23885_audio_dev *chip;
+	int err;
+
+	if (disable_analog_audio)
+		return NULL;
+
+	if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
+		printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
+			"for analog TV Audio\n", __func__);
+		return NULL;
+	}
+
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
+	if (err < 0)
+		goto error;
+
+	chip = (struct cx23885_audio_dev *) card->private_data;
+	chip->dev = dev;
+	chip->pci = dev->pci;
+	chip->card = card;
+	spin_lock_init(&chip->lock);
+
+	snd_card_set_dev(card, &dev->pci->dev);
+
+	err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
+	if (err < 0)
+		goto error;
+
+	strcpy(card->driver, "CX23885");
+	sprintf(card->shortname, "Conexant CX23885");
+	sprintf(card->longname, "%s at %s", card->shortname, dev->name);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
+	dprintk(0, "registered ALSA audio device\n");
+
+	return chip;
+
+error:
+	snd_card_free(card);
+	printk(KERN_ERR "%s(): Failed to register analog "
+			"audio adapter\n", __func__);
+
+	return NULL;
+}
+
+/*
+ * ALSA destructor
+ */
+void cx23885_audio_unregister(struct cx23885_dev *dev)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	snd_card_free(chip->card);
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-cards.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-cards.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-cards.c	2013-05-02 01:35:59.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-cards.c	2013-05-01 23:44:00.000000000 -0400
@@ -25,8 +25,8 @@
 #include <linux/delay.h>
 #include <media/cx25840.h>
 #include <linux/firmware.h>
+#include <misc/altera.h>
 
-#include "../../../staging/altera-stapl/altera.h"
 #include "cx23885.h"
 #include "tuner-xc2028.h"
 #include "netup-eeprom.h"
@@ -106,12 +106,14 @@ struct cx23885_board cx23885_boards[] =
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN5_CH2 |
 					CX25840_VIN2_CH1,
+			.amux   = CX25840_AUDIO8,
 			.gpio0  = 0,
 		}, {
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN4_CH2 |
 					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
 			.gpio0  = 0,
 		}, {
 			.type   = CX23885_VMUX_SVIDEO,
@@ -119,6 +121,7 @@ struct cx23885_board cx23885_boards[] =
 					CX25840_VIN4_CH2 |
 					CX25840_VIN8_CH1 |
 					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
 			.gpio0  = 0,
 		} },
 	},
@@ -153,7 +156,30 @@ struct cx23885_board cx23885_boards[] =
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1500] = {
 		.name		= "Hauppauge WinTV-HVR1500",
+		.porta		= CX23885_ANALOG_VIDEO,
 		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_XC2028,
+		.tuner_addr	= 0x61, /* 0xc2 >> 1 */
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.gpio0  = 0,
+		} },
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
 		.name		= "Hauppauge WinTV-HVR1200",
@@ -387,6 +413,31 @@ struct cx23885_board cx23885_boards[] =
 				.vmux   = CX25840_COMPOSITE1,
 		} },
 	},
+	[CX23885_BOARD_MPX885] = {
+		.name		= "MPX-885",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_COMPOSITE1,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE2,
+			.vmux   = CX25840_COMPOSITE2,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE3,
+			.vmux   = CX25840_COMPOSITE3,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE4,
+			.vmux   = CX25840_COMPOSITE4,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -1415,6 +1466,8 @@ void cx23885_card_setup(struct cx23885_d
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
 	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_MPX885:
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
 				&dev->i2c_bus[2].i2c_adap,
 				"cx25840", 0x88 >> 1, NULL);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-core.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(card, "card type");
 
 #define dprintk(level, fmt, arg...)\
 	do { if (debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
 	} while (0)
 
 static unsigned int cx23885_devcount;
@@ -155,12 +155,12 @@ static struct sram_channel cx23885_sram_
 		.cnt2_reg	= DMA5_CNT2,
 	},
 	[SRAM_CH07] = {
-		.name		= "ch7",
-		.cmds_start	= 0x0,
-		.ctrl_start	= 0x0,
-		.cdt		= 0x0,
-		.fifo_start	= 0x0,
-		.fifo_size	= 0x0,
+		.name		= "TV Audio",
+		.cmds_start	= 0x10190,
+		.ctrl_start	= 0x10480,
+		.cdt		= 0x10a00,
+		.fifo_start	= 0x7000,
+		.fifo_size	= 0x1000,
 		.ptr1_reg	= DMA6_PTR1,
 		.ptr2_reg	= DMA6_PTR2,
 		.cnt1_reg	= DMA6_CNT1,
@@ -1082,10 +1082,10 @@ static void cx23885_dev_unregister(struc
 static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
 			       unsigned int offset, u32 sync_line,
 			       unsigned int bpl, unsigned int padding,
-			       unsigned int lines)
+			       unsigned int lines,  unsigned int lpi)
 {
 	struct scatterlist *sg;
-	unsigned int line, todo;
+	unsigned int line, todo, sol;
 
 	/* sync instruction */
 	if (sync_line != NO_SYNC_LINE)
@@ -1098,16 +1098,22 @@ static __le32 *cx23885_risc_field(__le32
 			offset -= sg_dma_len(sg);
 			sg++;
 		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
 		if (bpl <= sg_dma_len(sg)-offset) {
 			/* fits into current chunk */
-			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
 			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
 			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 			offset += bpl;
 		} else {
 			/* scanline needs to be split */
 			todo = bpl;
-			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|
 					    (sg_dma_len(sg)-offset));
 			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
 			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1164,10 +1170,10 @@ int cx23885_risc_buffer(struct pci_dev *
 	rp = risc->cpu;
 	if (UNSET != top_offset)
 		rp = cx23885_risc_field(rp, sglist, top_offset, 0,
-					bpl, padding, lines);
+					bpl, padding, lines, 0);
 	if (UNSET != bottom_offset)
 		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
-					bpl, padding, lines);
+					bpl, padding, lines, 0);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -1175,11 +1181,11 @@ int cx23885_risc_buffer(struct pci_dev *
 	return 0;
 }
 
-static int cx23885_risc_databuffer(struct pci_dev *pci,
+int cx23885_risc_databuffer(struct pci_dev *pci,
 				   struct btcx_riscmem *risc,
 				   struct scatterlist *sglist,
 				   unsigned int bpl,
-				   unsigned int lines)
+				   unsigned int lines, unsigned int lpi)
 {
 	u32 instructions;
 	__le32 *rp;
@@ -1199,7 +1205,8 @@ static int cx23885_risc_databuffer(struc
 
 	/* write risc instructions */
 	rp = risc->cpu;
-	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+				bpl, 0, lines, lpi);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -1207,6 +1214,54 @@ static int cx23885_risc_databuffer(struc
 	return 0;
 }
 
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions, fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions  = fields * (1 + ((bpl + padding) * lines)
+		/ PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
+		return rc;
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	/* Sync to line 6, so US CC line 21 will appear in line '12'
+	 * in the userland vbi payload */
+	if (UNSET != top_offset)
+		rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+					bpl, padding, lines, 0);
+
+	if (UNSET != bottom_offset)
+		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+					bpl, padding, lines, 0);
+
+
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+
 int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 				u32 reg, u32 mask, u32 value)
 {
@@ -1517,7 +1572,7 @@ int cx23885_buf_prepare(struct videobuf_
 			goto fail;
 		cx23885_risc_databuffer(dev->pci, &buf->risc,
 					videobuf_to_dma(&buf->vb)->sglist,
-					buf->vb.width, buf->vb.height);
+					buf->vb.width, buf->vb.height, 0);
 	}
 	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
@@ -1741,15 +1796,19 @@ static irqreturn_t cx23885_irq(int irq,
 	struct cx23885_tsport *ts2 = &dev->ts2;
 	u32 pci_status, pci_mask;
 	u32 vida_status, vida_mask;
+	u32 audint_status, audint_mask;
 	u32 ts1_status, ts1_mask;
 	u32 ts2_status, ts2_mask;
 	int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+	int audint_count = 0;
 	bool subdev_handled;
 
 	pci_status = cx_read(PCI_INT_STAT);
 	pci_mask = cx23885_irq_get_mask(dev);
 	vida_status = cx_read(VID_A_INT_STAT);
 	vida_mask = cx_read(VID_A_INT_MSK);
+	audint_status = cx_read(AUDIO_INT_INT_STAT);
+	audint_mask = cx_read(AUDIO_INT_INT_MSK);
 	ts1_status = cx_read(VID_B_INT_STAT);
 	ts1_mask = cx_read(VID_B_INT_MSK);
 	ts2_status = cx_read(VID_C_INT_STAT);
@@ -1759,12 +1818,15 @@ static irqreturn_t cx23885_irq(int irq,
 		goto out;
 
 	vida_count = cx_read(VID_A_GPCNT);
+	audint_count = cx_read(AUD_INT_A_GPCNT);
 	ts1_count = cx_read(ts1->reg_gpcnt);
 	ts2_count = cx_read(ts2->reg_gpcnt);
 	dprintk(7, "pci_status: 0x%08x  pci_mask: 0x%08x\n",
 		pci_status, pci_mask);
 	dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
 		vida_status, vida_mask, vida_count);
+	dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+		audint_status, audint_mask, audint_count);
 	dprintk(7, "ts1_status: 0x%08x  ts1_mask: 0x%08x count: 0x%x\n",
 		ts1_status, ts1_mask, ts1_count);
 	dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
@@ -1861,6 +1923,9 @@ static irqreturn_t cx23885_irq(int irq,
 	if (vida_status)
 		handled += cx23885_video_irq(dev, vida_status);
 
+	if (audint_status)
+		handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
 	if (pci_status & PCI_MSK_IR) {
 		subdev_handled = false;
 		v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-dvb.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-dvb.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-dvb.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-dvb.c	2013-05-01 23:42:04.000000000 -0400
@@ -844,7 +844,7 @@ static int dvb_register(struct cx23885_t
 			static struct xc2028_ctrl ctl = {
 				.fname   = "/*(DEBLOBBED)*/",
 				.max_len = 64,
-				.demod   = 5000,
+				.demod   = XC3028_FE_DIBCOM52,
 				/* This is true for all demods with
 					v36 firmware? */
 				.type    = XC2028_D2633,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885.h linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,7 @@
 #define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
 #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885                   32
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -192,6 +193,7 @@ struct cx23885_buffer {
 struct cx23885_input {
 	enum cx23885_itype type;
 	unsigned int    vmux;
+	unsigned int    amux;
 	u32             gpio0, gpio1, gpio2, gpio3;
 };
 
@@ -318,6 +320,34 @@ struct cx23885_kernel_ir {
 	struct rc_dev		*rc;
 };
 
+struct cx23885_audio_buffer {
+	unsigned int		bpl;
+	struct btcx_riscmem	risc;
+	struct videobuf_dmabuf	dma;
+};
+
+struct cx23885_audio_dev {
+	struct cx23885_dev	*dev;
+
+	struct pci_dev		*pci;
+
+	struct snd_card		*card;
+
+	spinlock_t		lock;
+
+	atomic_t		count;
+
+	unsigned int		dma_size;
+	unsigned int		period_size;
+	unsigned int		num_periods;
+
+	struct videobuf_dmabuf	*dma_risc;
+
+	struct cx23885_audio_buffer   *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
 struct cx23885_dev {
 	atomic_t                   refcount;
 	struct v4l2_device 	   v4l2_dev;
@@ -362,6 +392,7 @@ struct cx23885_dev {
 	/* Analog video */
 	u32                        resources;
 	unsigned int               input;
+	unsigned int               audinput; /* Selectable audio input */
 	u32                        tvaudio;
 	v4l2_std_id                tvnorm;
 	unsigned int               tuner_type;
@@ -400,6 +431,9 @@ struct cx23885_dev {
 	atomic_t                   v4l_reader_count;
 	struct cx23885_tvnorm      encodernorm;
 
+	/* Analog raw audio */
+	struct cx23885_audio_dev   *audio_dev;
+
 };
 
 static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
@@ -478,6 +512,11 @@ extern int cx23885_risc_buffer(struct pc
 	unsigned int top_offset, unsigned int bottom_offset,
 	unsigned int bpl, unsigned int padding, unsigned int lines);
 
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+	struct btcx_riscmem *risc, struct scatterlist *sglist,
+	unsigned int top_offset, unsigned int bottom_offset,
+	unsigned int bpl, unsigned int padding, unsigned int lines);
+
 void cx23885_cancel_buffers(struct cx23885_tsport *port);
 
 extern int cx23885_restart_queue(struct cx23885_tsport *port,
@@ -533,6 +572,8 @@ extern void cx23885_free_buffer(struct v
 extern int cx23885_video_register(struct cx23885_dev *dev);
 extern void cx23885_video_unregister(struct cx23885_dev *dev);
 extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count);
 
 /* ----------------------------------------------------------- */
 /* cx23885-vbi.c                                               */
@@ -540,6 +581,9 @@ extern int cx23885_vbi_fmt(struct file *
 	struct v4l2_format *f);
 extern void cx23885_vbi_timeout(unsigned long data);
 extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
 
 /* cx23885-i2c.c                                                */
 extern int cx23885_i2c_register(struct cx23885_i2c *bus);
@@ -563,6 +607,18 @@ extern void mc417_gpio_set(struct cx2388
 extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
 extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
 
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c                                             */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+					struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+				   struct btcx_riscmem *risc,
+				   struct scatterlist *sglist,
+				   unsigned int bpl,
+				   unsigned int lines,
+				   unsigned int lpi);
 
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-i2c.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -287,6 +287,7 @@ static char *i2c_devs[128] = {
 	[0x32 >> 1] = "cx24227",
 	[0x88 >> 1] = "cx25837",
 	[0x84 >> 1] = "tda8295",
+	[0x98 >> 1] = "flatiron",
 	[0xa0 >> 1] = "eeprom",
 	[0xc0 >> 1] = "tuner/mt2131/tda8275",
 	[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-reg.h linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-reg.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -203,6 +203,7 @@ Channel manager Data Structure entry = 2
 #define SD2_BIAS_CTRL	0x0000000A
 #define AMP_BIAS_CTRL	0x0000000C
 #define CH_PWR_CTRL1	0x0000000E
+#define FLD_CH_SEL      (1 << 3)
 #define CH_PWR_CTRL2	0x0000000F
 #define DSM_STATUS1	0x00000010
 #define DSM_STATUS2	0x00000011
@@ -271,7 +272,9 @@ Channel manager Data Structure entry = 2
 #define VID_BC_MSK_OPC_ERR (1 << 16)
 #define VID_BC_MSK_SYNC    (1 << 12)
 #define VID_BC_MSK_OF      (1 <<  8)
+#define VID_BC_MSK_VBI_RISCI2 (1 <<  5)
 #define VID_BC_MSK_RISCI2  (1 <<  4)
+#define VID_BC_MSK_VBI_RISCI1 (1 <<  1)
 #define VID_BC_MSK_RISCI1   1
 
 #define VID_C_INT_MSK	0x00040040
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-vbi.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-vbi.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,12 @@ MODULE_PARM_DESC(vbi_debug, "enable debu
 
 /* ------------------------------------------------------------------ */
 
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10        /* line 10 - 21 */
+#define NTSC_VBI_END_LINE   21
+#define NTSC_VBI_LINES      (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
 int cx23885_vbi_fmt(struct file *file, void *priv,
 	struct v4l2_format *f)
 {
@@ -49,43 +55,86 @@ int cx23885_vbi_fmt(struct file *file, v
 
 	if (dev->tvnorm & V4L2_STD_525_60) {
 		/* ntsc */
-		f->fmt.vbi.sampling_rate = 28636363;
+		f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+		f->fmt.vbi.sampling_rate = 27000000;
+		f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+		f->fmt.vbi.offset = 0;
+		f->fmt.vbi.flags = 0;
 		f->fmt.vbi.start[0] = 10;
-		f->fmt.vbi.start[1] = 273;
-
+		f->fmt.vbi.count[0] = 17;
+		f->fmt.vbi.start[1] = 263 + 10 + 1;
+		f->fmt.vbi.count[1] = 17;
 	} else if (dev->tvnorm & V4L2_STD_625_50) {
 		/* pal */
 		f->fmt.vbi.sampling_rate = 35468950;
 		f->fmt.vbi.start[0] = 7 - 1;
 		f->fmt.vbi.start[1] = 319 - 1;
 	}
+
 	return 0;
 }
 
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+	u32 count;
+	int handled = 0;
+
+	if (status & VID_BC_MSK_VBI_RISCI1) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+		spin_lock(&dev->slock);
+		count = cx_read(VID_A_GPCNT);
+		cx23885_video_wakeup(dev, &dev->vbiq, count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	if (status & VID_BC_MSK_VBI_RISCI2) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+		dprintk(2, "stopper vbi\n");
+		spin_lock(&dev->slock);
+		cx23885_restart_vbi_queue(dev, &dev->vbiq);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	return handled;
+}
+
 static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
 			 struct cx23885_dmaqueue *q,
 			 struct cx23885_buffer   *buf)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	/* setup fifo + format */
 	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
 				buf->vb.width, buf->risc.dma);
 
 	/* reset counter */
+	cx_write(VID_A_GPCNT_CTL, 3);
+	cx_write(VID_A_VBI_CTRL, 3);
+	cx_write(VBI_A_GPCNT_CTL, 3);
 	q->count = 1;
 
-	/* enable irqs */
+	/* enable irq */
 	cx23885_irq_add_enable(dev, 0x01);
 	cx_set(VID_A_INT_MSK, 0x000022);
 
 	/* start dma */
 	cx_set(DEV_CNTRL2, (1<<5));
-	cx_set(VID_A_DMA_CTL, 0x00000022);
+	cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
 
 	return 0;
 }
 
 
-static int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
+int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
 			     struct cx23885_dmaqueue *q)
 {
 	struct cx23885_buffer *buf;
@@ -102,7 +151,7 @@ static int cx23885_restart_vbi_queue(str
 		buf = list_entry(item, struct cx23885_buffer, vb.queue);
 		buf->count = q->count++;
 	}
-	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
 	return 0;
 }
 
@@ -113,8 +162,7 @@ void cx23885_vbi_timeout(unsigned long d
 	struct cx23885_buffer *buf;
 	unsigned long flags;
 
-	cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]);
-
+	/* Stop the VBI engine */
 	cx_clear(VID_A_DMA_CTL, 0x22);
 
 	spin_lock_irqsave(&dev->slock, flags);
@@ -132,7 +180,7 @@ void cx23885_vbi_timeout(unsigned long d
 }
 
 /* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 2048
+#define VBI_LINE_LENGTH 1440
 #define VBI_LINE_COUNT 17
 
 static int
@@ -173,7 +221,7 @@ vbi_prepare(struct videobuf_queue *q, st
 		rc = videobuf_iolock(q, &buf->vb, NULL);
 		if (0 != rc)
 			goto fail;
-		cx23885_risc_buffer(dev->pci, &buf->risc,
+		cx23885_risc_vbibuffer(dev->pci, &buf->risc,
 				 dma->sglist,
 				 0, buf->vb.width * buf->vb.height,
 				 buf->vb.width, 0,
@@ -207,7 +255,7 @@ vbi_queue(struct videobuf_queue *vq, str
 		cx23885_start_vbi_dma(dev, q, buf);
 		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = q->count++;
-		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
 		dprintk(2, "[%p/%d] vbi_queue - first active\n",
 			buf, buf->vb.i);
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-video.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-video.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23885-video.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23885-video.c	2013-05-01 23:42:04.000000000 -0400
@@ -37,6 +37,8 @@
 #include "cx23885-ioctl.h"
 #include "tuner-xc2028.h"
 
+#include <media/cx25840.h>
+
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
@@ -69,14 +71,14 @@ MODULE_PARM_DESC(vid_limit, "capture mem
 
 #define dprintk(level, fmt, arg...)\
 	do { if (video_debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
 	} while (0)
 
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
 
 #define FORMAT_FLAGS_PACKED       0x01
-
+#if 0
 static struct cx23885_fmt formats[] = {
 	{
 		.name     = "8 bpp, gray",
@@ -130,6 +132,23 @@ static struct cx23885_fmt formats[] = {
 		.flags    = FORMAT_FLAGS_PACKED,
 	},
 };
+#else
+static struct cx23885_fmt formats[] = {
+	{
+#if 0
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+#endif
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}
+};
+#endif
 
 static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
 {
@@ -139,7 +158,12 @@ static struct cx23885_fmt *format_by_fou
 		if (formats[i].fourcc == fourcc)
 			return formats+i;
 
-	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+		(fourcc & 0xff),
+		((fourcc >> 8) & 0xff),
+		((fourcc >> 16) & 0xff),
+		((fourcc >> 24) & 0xff)
+		);
 	return NULL;
 }
 
@@ -171,7 +195,7 @@ static struct cx23885_ctrl cx23885_ctls[
 			.id            = V4L2_CID_CONTRAST,
 			.name          = "Contrast",
 			.minimum       = 0,
-			.maximum       = 0xff,
+			.maximum       = 0x7f,
 			.step          = 1,
 			.default_value = 0x3f,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
@@ -184,10 +208,10 @@ static struct cx23885_ctrl cx23885_ctls[
 		.v = {
 			.id            = V4L2_CID_HUE,
 			.name          = "Hue",
-			.minimum       = 0,
-			.maximum       = 0xff,
+			.minimum       = -127,
+			.maximum       = 128,
 			.step          = 1,
-			.default_value = 0x7f,
+			.default_value = 0x0,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
 		},
 		.off                   = 128,
@@ -202,9 +226,9 @@ static struct cx23885_ctrl cx23885_ctls[
 			.id            = V4L2_CID_SATURATION,
 			.name          = "Saturation",
 			.minimum       = 0,
-			.maximum       = 0xff,
+			.maximum       = 0x7f,
 			.step          = 1,
-			.default_value = 0x7f,
+			.default_value = 0x3f,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
 		},
 		.off                   = 0,
@@ -258,8 +282,8 @@ static const u32 *ctrl_classes[] = {
 	NULL
 };
 
-static void cx23885_video_wakeup(struct cx23885_dev *dev,
-		 struct cx23885_dmaqueue *q, u32 count)
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count)
 {
 	struct cx23885_buffer *buf;
 	int bc;
@@ -393,6 +417,71 @@ static void res_free(struct cx23885_dev
 	mutex_unlock(&dev->lock);
 }
 
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+	/* 8 bit registers, 8 bit values */
+	u8 buf[] = { reg, data };
+
+	struct i2c_msg msg = { .addr = 0x98 >> 1,
+		.flags = 0, .buf = buf, .len = 2 };
+
+	return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+	/* 8 bit registers, 8 bit values */
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+		{ .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+	if (ret != 2)
+		printk(KERN_ERR "%s() error\n", __func__);
+
+	return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+	int i;
+	dprintk(1, "Flatiron dump\n");
+	for (i = 0; i < 0x24; i++) {
+		dprintk(1, "FI[%02x] = %02x\n", i,
+			cx23885_flatiron_read(dev, i));
+	}
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+	u8 val;
+	dprintk(1, "%s(input = %d)\n", __func__, input);
+
+	if (input == 1)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+	else if (input == 2)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+	else
+		return -EINVAL;
+
+	val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+	cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+	/* Wake up */
+	cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+	if (video_debug)
+		cx23885_flatiron_dump(dev);
+
+	return 0;
+}
+
 static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 {
 	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
@@ -413,27 +502,59 @@ static int cx23885_video_mux(struct cx23
 	v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
 			INPUT(input)->vmux, 0, 0);
 
+	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+		(dev->board == CX23885_BOARD_MPX885)) {
+		/* Configure audio routing */
+		v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+			INPUT(input)->amux, 0, 0);
+
+		if (INPUT(input)->amux == CX25840_AUDIO7)
+			cx23885_flatiron_mux(dev, 1);
+		else if (INPUT(input)->amux == CX25840_AUDIO6)
+			cx23885_flatiron_mux(dev, 2);
+	}
+
 	return 0;
 }
 
-/* ------------------------------------------------------------------ */
-static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
-	unsigned int height, enum v4l2_field field)
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
 {
-	dprintk(1, "%s()\n", __func__);
+	dprintk(1, "%s(input=%d)\n", __func__, input);
+
+	/* The baseband video core of the cx23885 has two audio inputs.
+	 * LR1 and LR2. In almost every single case so far only HVR1xxx
+	 * cards we've only ever supported LR1. Time to support LR2,
+	 * which is available via the optional white breakout header on
+	 * the board.
+	 * We'll use a could of existing enums in the card struct to allow
+	 * devs to specify which baseband input they need, or just default
+	 * to what we've always used.
+	 */
+	if (INPUT(input)->amux == CX25840_AUDIO7)
+		cx23885_flatiron_mux(dev, 1);
+	else if (INPUT(input)->amux == CX25840_AUDIO6)
+		cx23885_flatiron_mux(dev, 2);
+	else {
+		/* Not specifically defined, assume the default. */
+		cx23885_flatiron_mux(dev, 1);
+	}
+
 	return 0;
 }
 
+/* ------------------------------------------------------------------ */
 static int cx23885_start_video_dma(struct cx23885_dev *dev,
 			   struct cx23885_dmaqueue *q,
 			   struct cx23885_buffer *buf)
 {
 	dprintk(1, "%s()\n", __func__);
 
+	/* Stop the dma/fifo before we tamper with it's risc programs */
+	cx_clear(VID_A_DMA_CTL, 0x11);
+
 	/* setup fifo + format */
 	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
 				buf->bpl, buf->risc.dma);
-	cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
 
 	/* reset counter */
 	cx_write(VID_A_GPCNT_CTL, 3);
@@ -748,7 +869,7 @@ static int video_open(struct file *file)
 	fh->type     = type;
 	fh->width    = 320;
 	fh->height   = 240;
-	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
 
 	videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
 			    &dev->pci->dev, &dev->slock,
@@ -757,6 +878,14 @@ static int video_open(struct file *file)
 			    sizeof(struct cx23885_buffer),
 			    fh, NULL);
 
+	videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+		&dev->pci->dev, &dev->slock,
+		V4L2_BUF_TYPE_VBI_CAPTURE,
+		V4L2_FIELD_SEQ_TB,
+		sizeof(struct cx23885_buffer),
+		fh, NULL);
+
+
 	dprintk(1, "post videobuf_queue_init()\n");
 
 	return 0;
@@ -884,8 +1013,9 @@ static int cx23885_get_control(struct cx
 static int cx23885_set_control(struct cx23885_dev *dev,
 	struct v4l2_control *ctl)
 {
-	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
-		" (disabled - no action)\n", __func__);
+	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+	call_all(dev, core, s_ctrl, ctl);
+
 	return 0;
 }
 
@@ -1059,13 +1189,22 @@ static int vidioc_streamon(struct file *
 	struct cx23885_dev *dev = fh->dev;
 	dprintk(1, "%s()\n", __func__);
 
-	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 	if (unlikely(i != fh->type))
 		return -EINVAL;
 
 	if (unlikely(!res_get(dev, fh, get_resource(fh))))
 		return -EBUSY;
+
+	/* Don't start VBI streaming unless vida streaming
+	 * has already started.
+	 */
+	if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+		((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+		return -EINVAL;
+
 	return videobuf_streamon(get_queue(fh));
 }
 
@@ -1076,7 +1215,8 @@ static int vidioc_streamoff(struct file
 	int err, res;
 	dprintk(1, "%s()\n", __func__);
 
-	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 	if (i != fh->type)
 		return -EINVAL;
@@ -1119,7 +1259,7 @@ static int cx23885_enum_input(struct cx2
 	dprintk(1, "%s()\n", __func__);
 
 	n = i->index;
-	if (n >= 4)
+	if (n >= MAX_CX23885_INPUT)
 		return -EINVAL;
 
 	if (0 == INPUT(n)->type)
@@ -1133,6 +1273,11 @@ static int cx23885_enum_input(struct cx2
 		i->type = V4L2_INPUT_TYPE_TUNER;
 		i->std = CX23885_NORMS;
 	}
+
+	/* Two selectable audio inputs for non-tv inputs */
+	if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+		i->audioset = 0x3;
+
 	return 0;
 }
 
@@ -1159,13 +1304,20 @@ static int vidioc_s_input(struct file *f
 
 	dprintk(1, "%s(%d)\n", __func__, i);
 
-	if (i >= 4) {
+	if (i >= MAX_CX23885_INPUT) {
 		dprintk(1, "%s() -EINVAL\n", __func__);
 		return -EINVAL;
 	}
 
+	if (INPUT(i)->type == 0)
+		return -EINVAL;
+
 	mutex_lock(&dev->lock);
 	cx23885_video_mux(dev, i);
+
+	/* By default establish the default audio input for the card also */
+	/* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+	cx23885_audio_mux(dev, i);
 	mutex_unlock(&dev->lock);
 	return 0;
 }
@@ -1185,6 +1337,64 @@ static int vidioc_log_status(struct file
 	return 0;
 }
 
+static int cx23885_query_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	static const char *iname[] = {
+		[0] = "Baseband L/R 1",
+		[1] = "Baseband L/R 2",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	memset(i, 0, sizeof(*i));
+	i->index = n;
+	strcpy(i->name, iname[n]);
+	i->capability  = V4L2_AUDCAP_STEREO;
+	i->mode  = V4L2_AUDMODE_AVL;
+	return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+				struct v4l2_audio *i)
+{
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	i->index = dev->audinput;
+	dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	if (i->index >= 2)
+		return -EINVAL;
+
+	dprintk(1, "%s(%d)\n", __func__, i->index);
+
+	dev->audinput = i->index;
+
+	/* Skip the audio defaults from the cards struct, caller wants
+	 * directly touch the audio mux hardware. */
+	cx23885_flatiron_mux(dev, dev->audinput + 1);
+	return 0;
+}
+
 static int vidioc_queryctrl(struct file *file, void *priv,
 				struct v4l2_queryctrl *qctrl)
 {
@@ -1221,10 +1431,8 @@ static int vidioc_g_tuner(struct file *f
 		return -EINVAL;
 
 	strcpy(t->name, "Television");
-	t->type       = V4L2_TUNER_ANALOG_TV;
-	t->capability = V4L2_TUNER_CAP_NORM;
-	t->rangehigh  = 0xffffffffUL;
-	t->signal = 0xffff ; /* LOCKED */
+
+	call_all(dev, tuner, g_tuner, t);
 	return 0;
 }
 
@@ -1237,6 +1445,9 @@ static int vidioc_s_tuner(struct file *f
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
+	/* Update the A/V core */
+	call_all(dev, tuner, s_tuner, t);
+
 	return 0;
 }
 
@@ -1302,10 +1513,6 @@ static void cx23885_vid_timeout(unsigned
 	struct cx23885_buffer *buf;
 	unsigned long flags;
 
-	cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
-
-	cx_clear(VID_A_DMA_CTL, 0x11);
-
 	spin_lock_irqsave(&dev->slock, flags);
 	while (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next,
@@ -1313,7 +1520,7 @@ static void cx23885_vid_timeout(unsigned
 		list_del(&buf->vb.queue);
 		buf->vb.state = VIDEOBUF_ERROR;
 		wake_up(&buf->vb.done);
-		printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n",
+		printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
 			dev->name, buf, buf->vb.i,
 			(unsigned long)buf->risc.dma);
 	}
@@ -1329,27 +1536,43 @@ int cx23885_video_irq(struct cx23885_dev
 	mask   = cx_read(VID_A_INT_MSK);
 	if (0 == (status & mask))
 		return handled;
+
 	cx_write(VID_A_INT_STAT, status);
 
-	dprintk(2, "%s() status = 0x%08x\n", __func__, status);
-	/* risc op code error */
-	if (status & (1 << 16)) {
-		printk(KERN_WARNING "%s/0: video risc op code error\n",
-			dev->name);
-		cx_clear(VID_A_DMA_CTL, 0x11);
-		cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
+	/* risc op code error, fifo overflow or line sync detection error */
+	if ((status & VID_BC_MSK_OPC_ERR) ||
+		(status & VID_BC_MSK_SYNC) ||
+		(status & VID_BC_MSK_OF)) {
+
+		if (status & VID_BC_MSK_OPC_ERR) {
+			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+				VID_BC_MSK_OPC_ERR);
+			printk(KERN_WARNING "%s: video risc op code error\n",
+				dev->name);
+			cx23885_sram_channel_dump(dev,
+				&dev->sram_channels[SRAM_CH01]);
+		}
+
+		if (status & VID_BC_MSK_SYNC)
+			dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+				"video lines miss-match\n",
+				VID_BC_MSK_SYNC);
+
+		if (status & VID_BC_MSK_OF)
+			dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+				VID_BC_MSK_OF);
+
 	}
 
-	/* risc1 y */
-	if (status & 0x01) {
+	/* Video */
+	if (status & VID_BC_MSK_RISCI1) {
 		spin_lock(&dev->slock);
 		count = cx_read(VID_A_GPCNT);
 		cx23885_video_wakeup(dev, &dev->vidq, count);
 		spin_unlock(&dev->slock);
 		handled++;
 	}
-	/* risc2 y */
-	if (status & 0x10) {
+	if (status & VID_BC_MSK_RISCI2) {
 		dprintk(2, "stopper video\n");
 		spin_lock(&dev->slock);
 		cx23885_restart_video_queue(dev, &dev->vidq);
@@ -1357,6 +1580,9 @@ int cx23885_video_irq(struct cx23885_dev
 		handled++;
 	}
 
+	/* Allow the VBI framework to process it's payload */
+	handled += cx23885_vbi_irq(dev, status);
+
 	return handled;
 }
 
@@ -1405,6 +1631,9 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_g_register    = cx23885_g_register,
 	.vidioc_s_register    = cx23885_s_register,
 #endif
+	.vidioc_enumaudio     = vidioc_enum_audinput,
+	.vidioc_g_audio       = vidioc_g_audinput,
+	.vidioc_s_audio       = vidioc_s_audinput,
 };
 
 static struct video_device cx23885_vbi_template;
@@ -1429,6 +1658,14 @@ void cx23885_video_unregister(struct cx2
 	dprintk(1, "%s()\n", __func__);
 	cx23885_irq_remove(dev, 0x01);
 
+	if (dev->vbi_dev) {
+		if (video_is_registered(dev->vbi_dev))
+			video_unregister_device(dev->vbi_dev);
+		else
+			video_device_release(dev->vbi_dev);
+		dev->vbi_dev = NULL;
+		btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+	}
 	if (dev->video_dev) {
 		if (video_is_registered(dev->video_dev))
 			video_unregister_device(dev->video_dev);
@@ -1438,6 +1675,9 @@ void cx23885_video_unregister(struct cx2
 
 		btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
 	}
+
+	if (dev->audio_dev)
+		cx23885_audio_unregister(dev);
 }
 
 int cx23885_video_register(struct cx23885_dev *dev)
@@ -1463,7 +1703,14 @@ int cx23885_video_register(struct cx2388
 	cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
 		VID_A_DMA_CTL, 0x11, 0x00);
 
-	/* Don't enable VBI yet */
+	/* init vbi dma queues */
+	INIT_LIST_HEAD(&dev->vbiq.active);
+	INIT_LIST_HEAD(&dev->vbiq.queued);
+	dev->vbiq.timeout.function = cx23885_vbi_timeout;
+	dev->vbiq.timeout.data = (unsigned long)dev;
+	init_timer(&dev->vbiq.timeout);
+	cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+		VID_A_DMA_CTL, 0x22, 0x00);
 
 	cx23885_irq_add_enable(dev, 0x01);
 
@@ -1504,8 +1751,7 @@ int cx23885_video_register(struct cx2388
 		}
 	}
 
-
-	/* register v4l devices */
+	/* register Video device */
 	dev->video_dev = cx23885_vdev_init(dev, dev->pci,
 		&cx23885_video_template, "video");
 	err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
@@ -1515,13 +1761,31 @@ int cx23885_video_register(struct cx2388
 			dev->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
 	       dev->name, video_device_node_name(dev->video_dev));
+
+	/* register VBI device */
+	dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+		&cx23885_vbi_template, "vbi");
+	err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+				    vbi_nr[dev->nr]);
+	if (err < 0) {
+		printk(KERN_INFO "%s: can't register vbi device\n",
+			dev->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s: registered device %s\n",
+	       dev->name, video_device_node_name(dev->vbi_dev));
+
+	/* Register ALSA audio device */
+	dev->audio_dev = cx23885_audio_register(dev);
+
 	/* initial device configuration */
 	mutex_lock(&dev->lock);
 	cx23885_set_tvnorm(dev, dev->tvnorm);
 	init_controls(dev);
 	cx23885_video_mux(dev, 0);
+	cx23885_audio_mux(dev, 0);
 	mutex_unlock(&dev->lock);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23888-ir.c linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23888-ir.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/cx23888-ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/cx23888-ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -673,7 +673,7 @@ static int cx23888_ir_rx_read(struct v4l
 
 	unsigned int i, n;
 	union cx23888_ir_fifo_rec *p;
-	unsigned u, v;
+	unsigned u, v, w;
 
 	n = count / sizeof(union cx23888_ir_fifo_rec)
 		* sizeof(union cx23888_ir_fifo_rec);
@@ -692,11 +692,12 @@ static int cx23888_ir_rx_read(struct v4l
 		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
 			/* Assume RTO was because of no IR light input */
 			u = 0;
-			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+			w = 1;
 		} else {
 			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
 			if (invert)
 				u = u ? 0 : 1;
+			w = 0;
 		}
 
 		v = (unsigned) pulse_width_count_to_ns(
@@ -707,9 +708,12 @@ static int cx23888_ir_rx_read(struct v4l
 		init_ir_raw_event(&p->ir_core_data);
 		p->ir_core_data.pulse = u;
 		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
 
-		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s\n",
-			 v, u ? "mark" : "space");
+		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
 	}
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/Kconfig linux-libre-3.2-gnu1/drivers/media/video/cx23885/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@ config VIDEO_CX23885
 config MEDIA_ALTERA_CI
 	tristate "Altera FPGA based CI module"
 	depends on VIDEO_CX23885 && DVB_CORE
-	select STAPL_ALTERA
+	select ALTERA_STAPL
 	---help---
 	  An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx23885/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx23885/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx23885/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx23885/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,14 +2,14 @@ cx23885-objs	:= cx23885-cards.o cx23885-
 		    cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
 		    cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
 		    cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
-		    cx23885-f300.o
+		    cx23885-f300.o cx23885-alsa.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-alsa.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-alsa.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-alsa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-alsa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,795 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on SAA713x ALSA driver and CX88 driver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, version 2
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH08
+
+#define dprintk(level, fmt, arg...)				\
+do {								\
+	if (debug >= level)					\
+		pr_info("%s/1: " fmt, chip->dev->name, ##arg);	\
+} while (0)
+#define dprintk_core(level, fmt, arg...)				\
+do {									\
+	if (debug >= level)						\
+		printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+
+/****************************************************************************
+	Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_buffer {
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct videobuf_dmabuf dma;
+};
+
+struct cx25821_audio_dev {
+	struct cx25821_dev *dev;
+	struct cx25821_dmaqueue q;
+
+	/* pci i/o */
+	struct pci_dev *pci;
+
+	/* audio controls */
+	int irq;
+
+	struct snd_card *card;
+
+	unsigned long iobase;
+	spinlock_t reg_lock;
+	atomic_t count;
+
+	unsigned int dma_size;
+	unsigned int period_size;
+	unsigned int num_periods;
+
+	struct videobuf_dmabuf *dma_risc;
+
+	struct cx25821_audio_buffer *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+/****************************************************************************
+				Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");	/* "{{Conexant,23881}," */
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+			Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4)	/* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_audio_buffer *buf = chip->buf;
+	struct cx25821_dev *dev = chip->dev;
+	struct sram_channel *audio_ch =
+	    &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+	u32 tmp = 0;
+
+	/* enable output on the GPIO 0 for the MCLK ADC (Audio) */
+	cx25821_set_gpiopin_direction(chip->dev, 0, 0);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* setup fifo + format - out channel */
+	cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
+					 buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_A_LNGTH, buf->bpl);
+
+	/* reset counter */
+	/* GP_COUNT_CONTROL_RESET = 0x3 */
+	cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(AUD_A_CFG);
+	cx_write(AUD_A_CFG,
+		 tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+		 FLD_AUD_CLK_ENABLE);
+
+	/*
+	pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
+		buf->bpl, audio_ch->cmds_start,
+		cx_read(audio_ch->cmds_start + 12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+	*/
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUD_A_INT_MSK,
+		 FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC |
+		 FLD_AUD_DST_OPC_ERR);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUD_A_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* Turn on audio downstream fifo and risc enable 0x101 */
+	tmp = cx_read(AUD_INT_DMA_CTL);
+	cx_set(AUD_INT_DMA_CTL,
+	       tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+
+	mdelay(100);
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUD_A_INT_MSK,
+		 AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 |
+		 AUD_INT_DN_RISCI1);
+
+	return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+	"dn_risci1", "up_risci1", "rds_dn_risc1",	/* 0-2 */
+	NULL,			/* reserved */
+	"dn_risci2", "up_risci2", "rds_dn_risc2",	/* 4-6 */
+	NULL,			/* reserved */
+	"dnf_of", "upf_uf", "rds_dnf_uf",	/* 8-10 */
+	NULL,			/* reserved */
+	"dn_sync", "up_sync", "rds_dn_sync",	/* 12-14 */
+	NULL,			/* reserved */
+	"opc_err", "par_err", "rip_err",	/* 16-18 */
+	"pci_abort", "ber_irq", "mchg_irq"	/* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
+			    u32 mask)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	if (0 == (status & mask))
+		return;
+
+	cx_write(AUD_A_INT_STAT, status);
+	if (debug > 1 || (status & mask & ~0xff))
+		cx25821_print_irqbits(dev->name, "irq aud",
+				      cx25821_aud_irqs,
+				      ARRAY_SIZE(cx25821_aud_irqs), status,
+				      mask);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
+
+		cx_clear(AUD_INT_DMA_CTL,
+			 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+		cx25821_sram_channel_dump_audio(dev,
+						&cx25821_sram_channels
+						[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
+		cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return;
+	}
+
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_audio_dev *chip = dev_id;
+	struct cx25821_dev *dev = chip->dev;
+	u32 status, pci_status;
+	u32 audint_status, audint_mask;
+	int loop, handled = 0;
+	int audint_count = 0;
+
+	audint_status = cx_read(AUD_A_INT_STAT);
+	audint_mask = cx_read(AUD_A_INT_MSK);
+	audint_count = cx_read(AUD_A_GPCNT);
+	status = cx_read(PCI_INT_STAT);
+
+	for (loop = 0; loop < 1; loop++) {
+		status = cx_read(PCI_INT_STAT);
+		if (0 == status) {
+			status = cx_read(PCI_INT_STAT);
+			audint_status = cx_read(AUD_A_INT_STAT);
+			audint_mask = cx_read(AUD_A_INT_MSK);
+
+			if (status) {
+				handled = 1;
+				cx_write(PCI_INT_STAT, status);
+
+				cx25821_aud_irq(chip, audint_status,
+						audint_mask);
+				break;
+			} else
+				goto out;
+		}
+
+		handled = 1;
+		cx_write(PCI_INT_STAT, status);
+
+		cx25821_aud_irq(chip, audint_status, audint_mask);
+	}
+
+	pci_status = cx_read(PCI_INT_STAT);
+
+	if (handled)
+		cx_write(PCI_INT_STAT, pci_status);
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+static int dsp_buffer_free(struct cx25821_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+	    SNDRV_PCM_INFO_INTERLEAVED |
+	    SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_48000,
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE / 3,
+	.period_bytes_max = DEFAULT_FIFO_SIZE / 3,
+	.periods_min = 1,
+	.periods_max = AUDIO_LINE_SIZE,
+	/* 128 * 128 = 16384 = 1024 * 16 */
+	.buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+	unsigned int bpl = 0;
+
+	if (!chip) {
+		pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err =
+	    snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx25821_digital_hw;
+
+	if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+	    DEFAULT_FIFO_SIZE) {
+		/* since there are 3 audio Clusters */
+		bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
+		bpl &= ~7;	/* must be multiple of 8 */
+
+		if (bpl > AUDIO_LINE_SIZE)
+			bpl = AUDIO_LINE_SIZE;
+
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx25821_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods - 1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	if (chip->period_size > AUDIO_LINE_SIZE)
+		chip->period_size = AUDIO_LINE_SIZE;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+				       (PAGE_ALIGN(chip->dma_size) >>
+					PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret =
+	    cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+					  chip->period_size, chip->num_periods,
+					  1);
+	if (ret < 0) {
+		pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
+		goto error;
+	}
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);	/* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
+				    int cmd)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err = 0;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->reg_lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = _cx25821_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = _cx25821_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->reg_lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
+					     *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods - 1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+				     unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+	.open = snd_cx25821_pcm_open,
+	.close = snd_cx25821_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx25821_hw_params,
+	.hw_free = snd_cx25821_hw_free,
+	.prepare = snd_cx25821_prepare,
+	.trigger = snd_cx25821_card_trigger,
+	.pointer = snd_cx25821_pointer,
+	.page = snd_cx25821_page,
+};
+
+/*
+ * ALSA create a PCM device:  Called when initializing the board.
+ * Sets up the name and hooks up the callbacks
+ */
+static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
+			   char *name)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0) {
+		pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+		return err;
+	}
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = {
+	{0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Not used in the function snd_cx25821_dev_free so removing
+ * from the file.
+ */
+/*
+static int snd_cx25821_free(struct cx25821_audio_dev *chip)
+{
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+
+	cx25821_dev_unregister(chip->dev);
+	pci_disable_device(chip->pci);
+
+	return 0;
+}
+*/
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card *card)
+{
+	struct cx25821_audio_dev *chip = card->private_data;
+
+	/* snd_cx25821_free(chip); */
+	snd_card_free(chip->card);
+}
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+	struct snd_card *card;
+	struct cx25821_audio_dev *chip;
+	int err;
+
+	if (devno >= SNDRV_CARDS) {
+		pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!enable[devno]) {
+		++devno;
+		pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
+		return -ENOENT;
+	}
+
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			 sizeof(struct cx25821_audio_dev), &card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+			__func__);
+		return err;
+	}
+
+	strcpy(card->driver, "cx25821");
+
+	/* Card "creation" */
+	card->private_free = snd_cx25821_dev_free;
+	chip = card->private_data;
+	spin_lock_init(&chip->reg_lock);
+
+	chip->dev = dev;
+	chip->card = card;
+	chip->pci = dev->pci;
+	chip->iobase = pci_resource_start(dev->pci, 0);
+
+	chip->irq = dev->pci->irq;
+
+	err = request_irq(dev->pci->irq, cx25821_irq,
+			  IRQF_SHARED, chip->dev->name, chip);
+
+	if (err < 0) {
+		pr_err("ERROR %s: can't get IRQ %d for ALSA\n",
+		       chip->dev->name, dev->pci->irq);
+		goto error;
+	}
+
+	err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_card_set_dev(card, &chip->pci->dev);
+
+	strcpy(card->shortname, "cx25821");
+	sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+		chip->iobase, chip->irq);
+	strcpy(card->mixername, "CX25821");
+
+	pr_info("%s/%i: ALSA support for cx25821 boards\n",
+		card->driver, devno);
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot register sound card %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_cx25821_cards[devno] = card;
+
+	devno++;
+	return 0;
+
+error:
+	snd_card_free(card);
+	return err;
+}
+
+/****************************************************************************
+				LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+	snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+	struct cx25821_dev *dev = NULL;
+	struct list_head *list;
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_for_each(list, &cx25821_devlist) {
+		dev = list_entry(list, struct cx25821_dev, devlist);
+		cx25821_audio_initdev(dev);
+	}
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	if (dev == NULL)
+		pr_info("ERROR ALSA: no cx25821 cards found\n");
+
+	return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP               1
+#define LINES_PER_BUFFER            15
+#define AUDIO_LINE_SIZE             128
+
+/* Number of buffer programs to use at once. */
+#define NUMBER_OF_PROGRAMS  8
+
+/*
+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line
+ * Space is also added for the 4 no-op instructions added on the end.
+ */
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE     \
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+	RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#endif
+
+/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE     \
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+	RISC_NOOP_INSTRUCTION_SIZE * 4)
+#endif
+
+/* Sizes of various instructions in bytes.  Used when adding instructions. */
+#define RISC_WRITE_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE  12
+#define RISC_SKIP_INSTRUCTION_SIZE  4
+#define RISC_SYNC_INSTRUCTION_SIZE  4
+#define RISC_WRITECR_INSTRUCTION_SIZE  16
+#define RISC_NOOP_INSTRUCTION_SIZE 4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE	\
+(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,788 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-audio-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
+			FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+					      struct sram_channel *ch,
+					      unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
+						 __le32 *rp,
+						 dma_addr_t databuf_phys_addr,
+						 unsigned int bpl,
+						 int fifo_enable)
+{
+	unsigned int line;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_audio_upstream_channel].sram_channels;
+	int offset = 0;
+
+	/* scan lines */
+	for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		/* Check if we need to enable the FIFO
+		 * after the first 3 lines.
+		 * For the upstream audio channel,
+		 * the risc engine will enable the FIFO */
+		if (fifo_enable && line == 2) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = sram_ch->fld_aud_fifo_en;
+			*(rp++) = 0x00000020;
+		}
+
+		offset += AUDIO_LINE_SIZE;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int frame = 0, i = 0;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int databuf_offset = 0;
+	int risc_flag = RISC_CNT_INC;
+	dma_addr_t risc_phys_jump_addr;
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_risc_virt_addr;
+
+	/* sync instruction */
+	*(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
+
+	for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (frame == 0) {
+			fifo_enable = 1;
+			risc_flag = RISC_CNT_RESET;
+		} else {
+			fifo_enable = 0;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Calculate physical jump address */
+		if ((frame + 1) == NUM_AUDIO_FRAMES) {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE;
+		} else {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE +
+			    AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
+		}
+
+		rp = cx25821_risc_field_upstream_audio(dev, rp,
+						       dev->
+						       _audiodata_buf_phys_addr
+						       + databuf_offset, bpl,
+						       fifo_enable);
+
+		if (USE_RISC_NOOP_AUDIO) {
+			for (i = 0; i < NUM_NO_OPS; i++)
+				*(rp++) = cpu_to_le32(RISC_NOOP);
+		}
+
+		/* Loop to (Nth)FrameRISC or to Start of Risc program &
+		 * generate IRQ */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+
+		/* Recalculate virtual address based on frame index */
+		rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
+		    (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+	}
+
+	return 0;
+}
+
+void cx25821_free_memory_audio(struct cx25821_dev *dev)
+{
+	if (dev->_risc_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiorisc_size,
+				    dev->_risc_virt_addr, dev->_risc_phys_addr);
+		dev->_risc_virt_addr = NULL;
+	}
+
+	if (dev->_audiodata_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
+				    dev->_audiodata_buf_virt_addr,
+				    dev->_audiodata_buf_phys_addr);
+		dev->_audiodata_buf_virt_addr = NULL;
+	}
+}
+
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_audio_is_running) {
+		printk(KERN_DEBUG
+		       pr_fmt("No audio file is currently running so return!\n"));
+		return;
+	}
+	/* Disable RISC interrupts */
+	cx_write(sram_ch->int_msk, 0);
+
+	/* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl,
+		 tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
+
+	/* Clear data buffer memory */
+	if (dev->_audiodata_buf_virt_addr)
+		memset(dev->_audiodata_buf_virt_addr, 0,
+		       dev->_audiodata_buf_size);
+
+	dev->_audio_is_running = 0;
+	dev->_is_first_audio_frame = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = END_OF_FILE;
+
+	kfree(dev->_irq_audio_queues);
+	dev->_irq_audio_queues = NULL;
+
+	kfree(dev->_audiofilename);
+}
+
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+{
+	if (dev->_audio_is_running)
+		cx25821_stop_upstream_audio(dev);
+
+	cx25821_free_memory_audio(dev);
+}
+
+int cx25821_get_audio_data(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_audioframe_index;
+	int i = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int frame_offset = frame_size * frame_index_temp;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset = dev->_audioframe_count * frame_size;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_audiofile_status == END_OF_FILE)
+		return 0;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_audio_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_audiodata_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_audiodata_buf_virt_addr +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_audioframe_count++;
+
+		dev->_audiofile_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_audioups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _audio_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel].
+			sram_channels);
+}
+
+int cx25821_openfile_audio(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
+			for (i = 0; i < dev->_audio_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_audiodata_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_audiodata_buf_virt_addr
+							+ offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_audioframe_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_audiofile_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
+						 struct sram_channel *sram_ch,
+						 int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	cx25821_free_memory_audio(dev);
+
+	dev->_risc_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size,
+				 &dma_addr);
+	dev->_risc_virt_start_addr = dev->_risc_virt_addr;
+	dev->_risc_phys_start_addr = dma_addr;
+	dev->_risc_phys_addr = dma_addr;
+	dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
+
+	if (!dev->_risc_virt_addr) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
+
+	/* For Audio Data buffer allocation */
+	dev->_audiodata_buf_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size,
+				 &data_dma_addr);
+	dev->_audiodata_buf_phys_addr = data_dma_addr;
+	dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
+
+	if (!dev->_audiodata_buf_virt_addr) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
+
+	ret = cx25821_openfile_audio(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret =
+	    cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+					       dev->_audio_lines_count);
+	if (ret < 0) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	int i = 0;
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_AUD_SRC_RISCI1) {
+		/* Get interrupt_index of the program that interrupted */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		cx_write(channel->int_msk, 0);
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+
+		spin_lock(&dev->slock);
+
+		while (prog_cnt != dev->_last_index_irq) {
+			/* Update _last_index_irq */
+			if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1))
+				dev->_last_index_irq++;
+			else
+				dev->_last_index_irq = 0;
+
+			dev->_audioframe_index = dev->_last_index_irq;
+
+			queue_work(dev->_irq_audio_queues,
+				   &dev->_audio_work_entry);
+		}
+
+		if (dev->_is_first_audio_frame) {
+			dev->_is_first_audio_frame = 0;
+
+			if (dev->_risc_virt_start_addr != NULL) {
+				risc_phys_jump_addr =
+				    dev->_risc_phys_start_addr +
+				    RISC_SYNC_INSTRUCTION_SIZE +
+				    AUDIO_RISC_DMA_BUF_SIZE;
+
+				rp = cx25821_risc_field_upstream_audio(dev,
+						dev->_risc_virt_start_addr + 1,
+						dev->_audiodata_buf_phys_addr,
+						AUDIO_LINE_SIZE, FIFO_DISABLE);
+
+				if (USE_RISC_NOOP_AUDIO) {
+					for (i = 0; i < NUM_NO_OPS; i++) {
+						*(rp++) =
+						    cpu_to_le32(RISC_NOOP);
+					}
+				}
+				/* Jump to 2nd Audio Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
+						RISC_CNT_RESET);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_AUD_SRC_OF)
+			pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_SYNC)
+			pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_OPC_ERR)
+			pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
+				__func__);
+
+		/* Read and write back the interrupt status register to clear
+		 * our bits */
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+	}
+
+	if (dev->_audiofile_status == END_OF_FILE) {
+		pr_warn("EOF Channel Audio Framecount = %d\n",
+			dev->_audioframe_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, audio_status;
+	int handled = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	audio_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (audio_status) {
+		handled = cx25821_audio_upstream_irq(dev,
+				dev->_audio_upstream_channel, audio_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_audio(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	int count = 0;
+	u32 tmp;
+
+	do {
+		/* Wait 10 microsecond before checking to see if the FIFO is
+		 * turned ON. */
+		udelay(10);
+
+		tmp = cx_read(sram_ch->dma_ctl);
+
+		/* 10 millisecond timeout */
+		if (count++ > 1000) {
+			pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
+			       __func__);
+			return;
+		}
+
+	} while (!(tmp & sram_ch->fld_aud_fifo_en));
+
+}
+
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the CMDS. */
+	cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Set the line length       (It looks like we do not need to set the
+	 * line length) */
+	cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(sram_ch->aud_cfg);
+	tmp |=
+	    FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+	    FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;
+	cx_write(sram_ch->aud_cfg, tmp);
+
+	/* Read and write back the interrupt status register to clear it */
+	tmp = cx_read(sram_ch->int_stat);
+	cx_write(sram_ch->int_stat, tmp);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
+
+	dev->_audio_is_running = 1;
+	dev->_is_first_audio_frame = 1;
+
+	/* The fifo_en bit turns on by the first Risc program */
+	cx25821_wait_fifo_enable(dev, sram_ch);
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
+{
+	struct sram_channel *sram_ch;
+	int retval = 0;
+	int err = 0;
+	int str_length = 0;
+
+	if (dev->_audio_is_running) {
+		pr_warn("Audio Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_audio_upstream_channel = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	/* Work queue */
+	INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
+	dev->_irq_audio_queues =
+	    create_singlethread_workqueue("cx25821_audioworkqueue");
+
+	if (!dev->_irq_audio_queues) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+		return -ENOMEM;
+	}
+
+	dev->_last_index_irq = 0;
+	dev->_audio_is_running = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = RESET_STATUS;
+	dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
+	_line_size = AUDIO_LINE_SIZE;
+
+	if (dev->input_audiofilename) {
+		str_length = strlen(dev->input_audiofilename);
+		dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+
+		memcpy(dev->_audiofilename, dev->input_audiofilename,
+		       str_length + 1);
+
+		/* Default if filename is empty string */
+		if (strcmp(dev->input_audiofilename, "") == 0)
+			dev->_audiofilename = "/root/audioGOOD.wav";
+	} else {
+		str_length = strlen(_defaultAudioName);
+		dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+
+		memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);
+	}
+
+	retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+							_line_size, 0);
+
+	dev->audio_upstream_riscbuf_size =
+	    AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+	    RISC_SYNC_INSTRUCTION_SIZE;
+	dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+							_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Audio upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+	/* Start RISC engine */
+	cx25821_start_audio_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-audio-upstream.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define NUM_AUDIO_PROGS       8
+#define NUM_AUDIO_FRAMES      8
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define NUM_NO_OPS            4
+
+#define RISC_READ_INSTRUCTION_SIZE      12
+#define RISC_JUMP_INSTRUCTION_SIZE      12
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define DWORD_SIZE                      4
+#define AUDIO_SYNC_LINE                 4
+
+#define LINES_PER_AUDIO_BUFFER      15
+#define AUDIO_LINE_SIZE             128
+#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
+
+#define USE_RISC_NOOP_AUDIO   1
+
+#ifdef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE +	\
+	 RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+static int _line_size;
+char *_defaultAudioName = "/root/audioGOOD.wav";
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-biffuncs.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-biffuncs.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-biffuncs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-biffuncs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit)  (1 << Bit)
+
+inline u8 getBit(u32 sample, u8 index)
+{
+	return (u8) ((sample >> index) & 1);
+}
+
+inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+	return value & ~(1 << bit);
+}
+
+inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+	sample |= (1 << bit);
+	return sample;
+
+}
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-cards.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-cards.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-cards.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+/* board config info */
+
+struct cx25821_board cx25821_boards[] = {
+	[UNKNOWN_BOARD] = {
+		.name = "UNKNOWN/GENERIC",
+		/* Ensure safe default for unknown boards */
+		.clk_freq = 0,
+	},
+
+	[CX25821_BOARD] = {
+		.name = "CX25821",
+		.portb = CX25821_RAW,
+		.portc = CX25821_264,
+		.input[0].type = CX25821_VMUX_COMPOSITE,
+	},
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[] = {
+	{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+		.card = CX25821_BOARD,
+	},
+};
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+	static u8 eeprom[256];
+
+	if (dev->i2c_bus[0].i2c_rc == 0) {
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+			      sizeof(eeprom));
+	}
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-core.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1517 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static unsigned int cx25821_devcount;
+
+DEFINE_MUTEX(cx25821_devlist_mutex);
+EXPORT_SYMBOL(cx25821_devlist_mutex);
+LIST_HEAD(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_devlist);
+
+struct sram_channel cx25821_sram_channels[] = {
+	[SRAM_CH00] = {
+		.i = SRAM_CH00,
+		.name = "VID A",
+		.cmds_start = VID_A_DOWN_CMDS,
+		.ctrl_start = VID_A_IQ,
+		.cdt = VID_A_CDT,
+		.fifo_start = VID_A_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA1_PTR1,
+		.ptr2_reg = DMA1_PTR2,
+		.cnt1_reg = DMA1_CNT1,
+		.cnt2_reg = DMA1_CNT2,
+		.int_msk = VID_A_INT_MSK,
+		.int_stat = VID_A_INT_STAT,
+		.int_mstat = VID_A_INT_MSTAT,
+		.dma_ctl = VID_DST_A_DMA_CTL,
+		.gpcnt_ctl = VID_DST_A_GPCNT_CTL,
+		.gpcnt = VID_DST_A_GPCNT,
+		.vip_ctl = VID_DST_A_VIP_CTL,
+		.pix_frmt = VID_DST_A_PIX_FRMT,
+	},
+
+	[SRAM_CH01] = {
+		.i = SRAM_CH01,
+		.name = "VID B",
+		.cmds_start = VID_B_DOWN_CMDS,
+		.ctrl_start = VID_B_IQ,
+		.cdt = VID_B_CDT,
+		.fifo_start = VID_B_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA2_PTR1,
+		.ptr2_reg = DMA2_PTR2,
+		.cnt1_reg = DMA2_CNT1,
+		.cnt2_reg = DMA2_CNT2,
+		.int_msk = VID_B_INT_MSK,
+		.int_stat = VID_B_INT_STAT,
+		.int_mstat = VID_B_INT_MSTAT,
+		.dma_ctl = VID_DST_B_DMA_CTL,
+		.gpcnt_ctl = VID_DST_B_GPCNT_CTL,
+		.gpcnt = VID_DST_B_GPCNT,
+		.vip_ctl = VID_DST_B_VIP_CTL,
+		.pix_frmt = VID_DST_B_PIX_FRMT,
+	},
+
+	[SRAM_CH02] = {
+		.i = SRAM_CH02,
+		.name = "VID C",
+		.cmds_start = VID_C_DOWN_CMDS,
+		.ctrl_start = VID_C_IQ,
+		.cdt = VID_C_CDT,
+		.fifo_start = VID_C_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA3_PTR1,
+		.ptr2_reg = DMA3_PTR2,
+		.cnt1_reg = DMA3_CNT1,
+		.cnt2_reg = DMA3_CNT2,
+		.int_msk = VID_C_INT_MSK,
+		.int_stat = VID_C_INT_STAT,
+		.int_mstat = VID_C_INT_MSTAT,
+		.dma_ctl = VID_DST_C_DMA_CTL,
+		.gpcnt_ctl = VID_DST_C_GPCNT_CTL,
+		.gpcnt = VID_DST_C_GPCNT,
+		.vip_ctl = VID_DST_C_VIP_CTL,
+		.pix_frmt = VID_DST_C_PIX_FRMT,
+	},
+
+	[SRAM_CH03] = {
+		.i = SRAM_CH03,
+		.name = "VID D",
+		.cmds_start = VID_D_DOWN_CMDS,
+		.ctrl_start = VID_D_IQ,
+		.cdt = VID_D_CDT,
+		.fifo_start = VID_D_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA4_PTR1,
+		.ptr2_reg = DMA4_PTR2,
+		.cnt1_reg = DMA4_CNT1,
+		.cnt2_reg = DMA4_CNT2,
+		.int_msk = VID_D_INT_MSK,
+		.int_stat = VID_D_INT_STAT,
+		.int_mstat = VID_D_INT_MSTAT,
+		.dma_ctl = VID_DST_D_DMA_CTL,
+		.gpcnt_ctl = VID_DST_D_GPCNT_CTL,
+		.gpcnt = VID_DST_D_GPCNT,
+		.vip_ctl = VID_DST_D_VIP_CTL,
+		.pix_frmt = VID_DST_D_PIX_FRMT,
+	},
+
+	[SRAM_CH04] = {
+		.i = SRAM_CH04,
+		.name = "VID E",
+		.cmds_start = VID_E_DOWN_CMDS,
+		.ctrl_start = VID_E_IQ,
+		.cdt = VID_E_CDT,
+		.fifo_start = VID_E_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA5_PTR1,
+		.ptr2_reg = DMA5_PTR2,
+		.cnt1_reg = DMA5_CNT1,
+		.cnt2_reg = DMA5_CNT2,
+		.int_msk = VID_E_INT_MSK,
+		.int_stat = VID_E_INT_STAT,
+		.int_mstat = VID_E_INT_MSTAT,
+		.dma_ctl = VID_DST_E_DMA_CTL,
+		.gpcnt_ctl = VID_DST_E_GPCNT_CTL,
+		.gpcnt = VID_DST_E_GPCNT,
+		.vip_ctl = VID_DST_E_VIP_CTL,
+		.pix_frmt = VID_DST_E_PIX_FRMT,
+	},
+
+	[SRAM_CH05] = {
+		.i = SRAM_CH05,
+		.name = "VID F",
+		.cmds_start = VID_F_DOWN_CMDS,
+		.ctrl_start = VID_F_IQ,
+		.cdt = VID_F_CDT,
+		.fifo_start = VID_F_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA6_PTR1,
+		.ptr2_reg = DMA6_PTR2,
+		.cnt1_reg = DMA6_CNT1,
+		.cnt2_reg = DMA6_CNT2,
+		.int_msk = VID_F_INT_MSK,
+		.int_stat = VID_F_INT_STAT,
+		.int_mstat = VID_F_INT_MSTAT,
+		.dma_ctl = VID_DST_F_DMA_CTL,
+		.gpcnt_ctl = VID_DST_F_GPCNT_CTL,
+		.gpcnt = VID_DST_F_GPCNT,
+		.vip_ctl = VID_DST_F_VIP_CTL,
+		.pix_frmt = VID_DST_F_PIX_FRMT,
+	},
+
+	[SRAM_CH06] = {
+		.i = SRAM_CH06,
+		.name = "VID G",
+		.cmds_start = VID_G_DOWN_CMDS,
+		.ctrl_start = VID_G_IQ,
+		.cdt = VID_G_CDT,
+		.fifo_start = VID_G_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA7_PTR1,
+		.ptr2_reg = DMA7_PTR2,
+		.cnt1_reg = DMA7_CNT1,
+		.cnt2_reg = DMA7_CNT2,
+		.int_msk = VID_G_INT_MSK,
+		.int_stat = VID_G_INT_STAT,
+		.int_mstat = VID_G_INT_MSTAT,
+		.dma_ctl = VID_DST_G_DMA_CTL,
+		.gpcnt_ctl = VID_DST_G_GPCNT_CTL,
+		.gpcnt = VID_DST_G_GPCNT,
+		.vip_ctl = VID_DST_G_VIP_CTL,
+		.pix_frmt = VID_DST_G_PIX_FRMT,
+	},
+
+	[SRAM_CH07] = {
+		.i = SRAM_CH07,
+		.name = "VID H",
+		.cmds_start = VID_H_DOWN_CMDS,
+		.ctrl_start = VID_H_IQ,
+		.cdt = VID_H_CDT,
+		.fifo_start = VID_H_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA8_PTR1,
+		.ptr2_reg = DMA8_PTR2,
+		.cnt1_reg = DMA8_CNT1,
+		.cnt2_reg = DMA8_CNT2,
+		.int_msk = VID_H_INT_MSK,
+		.int_stat = VID_H_INT_STAT,
+		.int_mstat = VID_H_INT_MSTAT,
+		.dma_ctl = VID_DST_H_DMA_CTL,
+		.gpcnt_ctl = VID_DST_H_GPCNT_CTL,
+		.gpcnt = VID_DST_H_GPCNT,
+		.vip_ctl = VID_DST_H_VIP_CTL,
+		.pix_frmt = VID_DST_H_PIX_FRMT,
+	},
+
+	[SRAM_CH08] = {
+		.name = "audio from",
+		.cmds_start = AUD_A_DOWN_CMDS,
+		.ctrl_start = AUD_A_IQ,
+		.cdt = AUD_A_CDT,
+		.fifo_start = AUD_A_DOWN_CLUSTER_1,
+		.fifo_size = AUDIO_CLUSTER_SIZE * 3,
+		.ptr1_reg = DMA17_PTR1,
+		.ptr2_reg = DMA17_PTR2,
+		.cnt1_reg = DMA17_CNT1,
+		.cnt2_reg = DMA17_CNT2,
+	},
+
+	[SRAM_CH09] = {
+		.i = SRAM_CH09,
+		.name = "VID Upstream I",
+		.cmds_start = VID_I_UP_CMDS,
+		.ctrl_start = VID_I_IQ,
+		.cdt = VID_I_CDT,
+		.fifo_start = VID_I_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA15_PTR1,
+		.ptr2_reg = DMA15_PTR2,
+		.cnt1_reg = DMA15_CNT1,
+		.cnt2_reg = DMA15_CNT2,
+		.int_msk = VID_I_INT_MSK,
+		.int_stat = VID_I_INT_STAT,
+		.int_mstat = VID_I_INT_MSTAT,
+		.dma_ctl = VID_SRC_I_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
+		.gpcnt = VID_SRC_I_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_I_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_I_CDT_SZ,
+		.irq_bit = 8,
+	},
+
+	[SRAM_CH10] = {
+		.i = SRAM_CH10,
+		.name = "VID Upstream J",
+		.cmds_start = VID_J_UP_CMDS,
+		.ctrl_start = VID_J_IQ,
+		.cdt = VID_J_CDT,
+		.fifo_start = VID_J_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA16_PTR1,
+		.ptr2_reg = DMA16_PTR2,
+		.cnt1_reg = DMA16_CNT1,
+		.cnt2_reg = DMA16_CNT2,
+		.int_msk = VID_J_INT_MSK,
+		.int_stat = VID_J_INT_STAT,
+		.int_mstat = VID_J_INT_MSTAT,
+		.dma_ctl = VID_SRC_J_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
+		.gpcnt = VID_SRC_J_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_J_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_J_CDT_SZ,
+		.irq_bit = 9,
+	},
+
+	[SRAM_CH11] = {
+		.i = SRAM_CH11,
+		.name = "Audio Upstream Channel B",
+		.cmds_start = AUD_B_UP_CMDS,
+		.ctrl_start = AUD_B_IQ,
+		.cdt = AUD_B_CDT,
+		.fifo_start = AUD_B_UP_CLUSTER_1,
+		.fifo_size = (AUDIO_CLUSTER_SIZE * 3),
+		.ptr1_reg = DMA22_PTR1,
+		.ptr2_reg = DMA22_PTR2,
+		.cnt1_reg = DMA22_CNT1,
+		.cnt2_reg = DMA22_CNT2,
+		.int_msk = AUD_B_INT_MSK,
+		.int_stat = AUD_B_INT_STAT,
+		.int_mstat = AUD_B_INT_MSTAT,
+		.dma_ctl = AUD_INT_DMA_CTL,
+		.gpcnt_ctl = AUD_B_GPCNT_CTL,
+		.gpcnt = AUD_B_GPCNT,
+		.aud_length = AUD_B_LNGTH,
+		.aud_cfg = AUD_B_CFG,
+		.fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
+		.fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
+		.irq_bit = 11,
+	},
+};
+EXPORT_SYMBOL(cx25821_sram_channels);
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+	static const char * const instr[16] = {
+		[RISC_SYNC >> 28] = "sync",
+		[RISC_WRITE >> 28] = "write",
+		[RISC_WRITEC >> 28] = "writec",
+		[RISC_READ >> 28] = "read",
+		[RISC_READC >> 28] = "readc",
+		[RISC_JUMP >> 28] = "jump",
+		[RISC_SKIP >> 28] = "skip",
+		[RISC_WRITERM >> 28] = "writerm",
+		[RISC_WRITECM >> 28] = "writecm",
+		[RISC_WRITECR >> 28] = "writecr",
+	};
+	static const int incr[16] = {
+		[RISC_WRITE >> 28] = 3,
+		[RISC_JUMP >> 28] = 3,
+		[RISC_SKIP >> 28] = 1,
+		[RISC_SYNC >> 28] = 1,
+		[RISC_WRITERM >> 28] = 3,
+		[RISC_WRITECM >> 28] = 3,
+		[RISC_WRITECR >> 28] = 4,
+	};
+	static const char * const bits[] = {
+		"12", "13", "14", "resync",
+		"cnt0", "cnt1", "18", "19",
+		"20", "21", "22", "23",
+		"irq1", "irq2", "eol", "sol",
+	};
+	int i;
+
+	pr_cont("0x%08x [ %s",
+		risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
+		if (risc & (1 << (i + 12)))
+			pr_cont(" %s", bits[i]);
+	}
+	pr_cont(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string)
+{
+	int tmp = 0;
+	u32 value = 0;
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp);
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+	u32 tmp;
+
+	/* enable RUN_RISC in Pecos */
+	cx_write(DEV_CNTRL2, 0x20);
+
+	/* Set the master PCI interrupt masks to enable video, audio, MBIF,
+	 * and GPIO interrupts
+	 * I2C interrupt masking is handled by the I2C objects themselves. */
+	cx_write(PCI_INT_MSK, 0x2001FFFF);
+
+	tmp = cx_read(RDR_TLCTL0);
+	tmp &= ~FLD_CFG_RCB_CK_EN;	/* Clear the RCB_CK_EN bit */
+	cx_write(RDR_TLCTL0, tmp);
+
+	/* PLL-A setting for the Audio Master Clock */
+	cx_write(PLL_A_INT_FRAC, 0x9807A58B);
+
+	/* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */
+	cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_A_INT_FRAC);
+	cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-B setting for Mobilygen Host Bus Interface */
+	cx_write(PLL_B_INT_FRAC, 0x9883A86F);
+
+	/* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_B_INT_FRAC);
+	cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-C setting for video upstream channel */
+	cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
+
+	/* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_C_INT_FRAC);
+	cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-D setting for audio upstream channel */
+	cx_write(PLL_D_INT_FRAC, 0x98757F5B);
+
+	/* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_D_INT_FRAC);
+	cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* This selects the PLL C clock source for the video upstream channel
+	 * I and J */
+	tmp = cx_read(VID_CH_CLK_SEL);
+	cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 * select 656/VIP DST for downstream Channel A - C */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	/* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	/* enables 656 port I and J as output */
+	tmp = cx_read(CLK_RST);
+	/* use external ALT_PLL_REF pin as its reference clock instead */
+	tmp |= FLD_USE_ALT_PLL_REF;
+	cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+	mdelay(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+			       struct sram_channel *ch,
+			       unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* init the first cdt buffer */
+	for (i = 0; i < 128; i++)
+		cx_write(ch->fifo_start + 4 * i, i);
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch,
+				     unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;	/* for AUDIO */
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	/* zero out */
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+	static char *name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+	u32 risc;
+	unsigned int i, j, n;
+
+	pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
+			i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch)
+{
+	static const char * const name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+
+	u32 risc, value, tmp;
+	unsigned int i, j, n;
+
+	pr_info("\n%s: %s - dma Audio channel status dump\n",
+		dev->name, ch->name);
+
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
+			dev->name, i * 4, name[i],
+			cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+
+	for (i = 0; i < 4; i++) {
+		risc = cx_read(ch->cmds_start + 56 + (i * 4));
+		pr_warn("instruction %d = 0x%x\n", i, risc);
+	}
+
+	/* read data from the first cdt buffer */
+	risc = cx_read(AUD_A_CDT);
+	pr_warn("\nread cdt loc=0x%x\n", risc);
+	for (i = 0; i < 8; i++) {
+		n = cx_read(risc + i * 4);
+		pr_cont("0x%x ", n);
+	}
+	pr_cont("\n\n");
+
+	value = cx_read(CLK_RST);
+	CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
+
+	value = cx_read(PLL_A_POST_STAT_BIST);
+	CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_A_INT_FRAC);
+	CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_B_POST_STAT_BIST);
+	CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_B_INT_FRAC);
+	CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_C_POST_STAT_BIST);
+	CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_C_INT_FRAC);
+	CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_D_POST_STAT_BIST);
+	CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_D_INT_FRAC);
+	CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value);
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+	int i;
+
+	/* disable RISC controller */
+	cx_write(DEV_CNTRL2, 0);
+
+	/* Disable Video A/B activity */
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	/* Disable Audio activity */
+	cx_write(AUD_INT_DMA_CTL, 0);
+
+	/* Disable Serial port */
+	cx_write(UART_CTL, 0);
+
+	/* Disable Interrupts */
+	cx_write(PCI_INT_MSK, 0);
+	cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
+			      u32 format)
+{
+	if (channel_select <= 7 && channel_select >= 0) {
+		cx_write(dev->channels[channel_select].
+			sram_channels->pix_frmt, format);
+		dev->channels[channel_select].pixel_formats = format;
+	}
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+				 struct sram_channel *ch)
+{
+	cx_write(ch->pix_frmt, PIXEL_FRMT_422);
+	cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+	int i;
+
+	dprintk(1, "%s()\n", __func__);
+
+	cx25821_shutdown(dev);
+	cx_write(PCI_INT_STAT, 0xffffffff);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+	cx_write(AUD_A_INT_STAT, 0xffffffff);
+	cx_write(AUD_B_INT_STAT, 0xffffffff);
+	cx_write(AUD_C_INT_STAT, 0xffffffff);
+	cx_write(AUD_D_INT_STAT, 0xffffffff);
+	cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+	cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+	cx_write(PAD_CTRL, 0x12);	/* for I2C */
+	cx25821_registers_init(dev);	/* init Pecos registers */
+	mdelay(100);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+		cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
+						1440, 0);
+		dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+		dev->channels[i].use_cif_resolution = FALSE;
+	}
+
+	/* Probably only affect Downstream */
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+	}
+
+	cx25821_sram_channel_setup_audio(dev,
+				dev->channels[SRAM_CH08].sram_channels,
+				128, 0);
+
+	cx25821_gpio_init(dev);
+}
+
+static int cx25821_get_resources(struct cx25821_dev *dev)
+{
+	if (request_mem_region
+	    (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
+	     dev->name))
+		return 0;
+
+	pr_err("%s: can't get MMIO memory @ 0x%llx\n",
+	       dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+	return -EBUSY;
+}
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+	dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
+
+	pr_info("%s(): Hardware revision = 0x%02x\n",
+		__func__, dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	/* Releasing IO memory */
+	if (dev->lmmio != NULL) {
+		CX25821_INFO("Releasing lmmio.\n");
+		iounmap(dev->lmmio);
+		dev->lmmio = NULL;
+	}
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+	int io_size = 0, i;
+
+	pr_info("\n***********************************\n");
+	pr_info("cx25821 set up\n");
+	pr_info("***********************************\n\n");
+
+	mutex_init(&dev->lock);
+
+	atomic_inc(&dev->refcount);
+
+	dev->nr = ++cx25821_devcount;
+	sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_add_tail(&dev->devlist, &cx25821_devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
+	strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
+
+	if (dev->pci->device != 0x8210) {
+		pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+			__func__, dev->pci->device);
+		return -1;
+	} else {
+		pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+	}
+
+	/* Apply a sensible clock frequency for the PCIe bridge */
+	dev->clk_freq = 28000000;
+	for (i = 0; i < MAX_VID_CHANNEL_NUM; i++)
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+
+	if (dev->nr > 1)
+		CX25821_INFO("dev->nr > 1!");
+
+	/* board config */
+	dev->board = 1;		/* card[dev->nr]; */
+	dev->_max_num_decoders = MAX_DECODERS;
+
+	dev->pci_bus = dev->pci->bus->number;
+	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+	dev->pci_irqmask = 0x001f00;
+
+	/* External Master 1 Bus */
+	dev->i2c_bus[0].nr = 0;
+	dev->i2c_bus[0].dev = dev;
+	dev->i2c_bus[0].reg_stat = I2C1_STAT;
+	dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
+	dev->i2c_bus[0].reg_addr = I2C1_ADDR;
+	dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+	dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+	dev->i2c_bus[0].i2c_period = (0x07 << 24);	/* 1.95MHz */
+
+	if (cx25821_get_resources(dev) < 0) {
+		pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
+		       dev->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device);
+
+		cx25821_devcount--;
+		return -EBUSY;
+	}
+
+	/* PCIe stuff */
+	dev->base_io_addr = pci_resource_start(dev->pci, 0);
+	io_size = pci_resource_len(dev->pci, 0);
+
+	if (!dev->base_io_addr) {
+		CX25821_ERR("No PCI Memory resources, exiting!\n");
+		return -ENODEV;
+	}
+
+	dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!dev->lmmio) {
+		CX25821_ERR
+		    ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+		cx25821_iounmap(dev);
+		return -ENOMEM;
+	}
+
+	dev->bmmio = (u8 __iomem *) dev->lmmio;
+
+	pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+		dev->name, dev->pci->subsystem_vendor,
+		dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+		dev->board, card[dev->nr] == dev->board ?
+		"insmod option" : "autodetected");
+
+	/* init hardware */
+	cx25821_initialize(dev);
+
+	cx25821_i2c_register(&dev->i2c_bus[0]);
+/*  cx25821_i2c_register(&dev->i2c_bus[1]);
+ *  cx25821_i2c_register(&dev->i2c_bus[2]); */
+
+	CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
+		     dev->i2c_bus[0].i2c_rc);
+
+	cx25821_card_setup(dev);
+
+	if (medusa_video_init(dev) < 0)
+		CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
+
+	cx25821_video_register(dev);
+
+	/* register IOCTL device */
+	dev->ioctl_dev =
+	   cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template,
+			      "video");
+
+	if (video_register_device
+	    (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
+		cx25821_videoioctl_unregister(dev);
+		pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
+		       __func__);
+	}
+
+	cx25821_dev_checkrevision(dev);
+	CX25821_INFO("setup done!\n");
+
+	return 0;
+}
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch1(dev, dev->channel_select,
+				     dev->pixel_format);
+}
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
+				     dev->pixel_format_ch2);
+}
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+				  struct upstream_user_struct *up_data)
+{
+	cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+	int i;
+
+	if (!dev->base_io_addr)
+		return;
+
+	cx25821_free_mem_upstream_ch1(dev);
+	cx25821_free_mem_upstream_ch2(dev);
+	cx25821_free_mem_upstream_audio(dev);
+
+	release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!atomic_dec_and_test(&dev->refcount))
+		return;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx25821_video_unregister(dev, i);
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+	     i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+		cx25821_video_unregister(dev, i);
+	}
+
+	cx25821_videoioctl_unregister(dev);
+
+	cx25821_i2c_unregister(&dev->i2c_bus[0]);
+	cx25821_iounmap(dev);
+}
+EXPORT_SYMBOL(cx25821_dev_unregister);
+
+static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
+				  unsigned int offset, u32 sync_line,
+				  unsigned int bpl, unsigned int padding,
+				  unsigned int lines)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | RISC_SOL |
+					(sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) =
+				    cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions;
+	u32 fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions =
+	    fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	if (UNSET != top_offset) {
+		rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
+					lines);
+	}
+
+	if (UNSET != bottom_offset) {
+		rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+					padding, lines);
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
+					unsigned int offset, u32 sync_line,
+					unsigned int bpl, unsigned int padding,
+					unsigned int lines, unsigned int lpi)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo, sol;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
+					      (sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) = cpu_to_le32(RISC_WRITE |
+						      sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+				  struct btcx_riscmem *risc,
+				  struct scatterlist *sglist,
+				  unsigned int bpl,
+				  unsigned int lines, unsigned int lpi)
+{
+	u32 instructions;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Here
+	   there is no padding and no sync.  First DMA region may be smaller
+	   than PAGE_SIZE */
+	/* Jump and write need an extra dword */
+	instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+	instructions += 1;
+
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+				      lines, lpi);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+			 u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	*(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+	return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 pci_status, pci_mask;
+	u32 vid_status;
+	int i, handled = 0;
+	u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+	pci_status = cx_read(PCI_INT_STAT);
+	pci_mask = cx_read(PCI_INT_MSK);
+
+	if (pci_status == 0)
+		goto out;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		if (pci_status & mask[i]) {
+			vid_status = cx_read(dev->channels[i].
+				sram_channels->int_stat);
+
+			if (vid_status)
+				handled +=
+				cx25821_video_irq(dev, i, vid_status);
+
+			cx_write(PCI_INT_STAT, mask[i]);
+		}
+	}
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+			   int len, u32 bits, u32 mask)
+{
+	unsigned int i;
+
+	printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
+
+	for (i = 0; i < len; i++) {
+		if (!(bits & (1 << i)))
+			continue;
+		if (strings[i])
+			pr_cont(" %s", strings[i]);
+		else
+			pr_cont(" %d", i);
+		if (!(mask & (1 << i)))
+			continue;
+		pr_cont("*");
+	}
+	pr_cont("\n");
+}
+EXPORT_SYMBOL(cx25821_print_irqbits);
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+	struct cx25821_dev *dev = pci_get_drvdata(pci);
+	return dev;
+}
+EXPORT_SYMBOL(cx25821_dev_get);
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
+				     const struct pci_device_id *pci_id)
+{
+	struct cx25821_dev *dev;
+	int err = 0;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (NULL == dev)
+		return -ENOMEM;
+
+	err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+	if (err < 0)
+		goto fail_free;
+
+	/* pci init */
+	dev->pci = pci_dev;
+	if (pci_enable_device(pci_dev)) {
+		err = -EIO;
+
+		pr_info("pci enable failed!\n");
+
+		goto fail_unregister_device;
+	}
+
+	pr_info("Athena pci enable !\n");
+
+	err = cx25821_dev_setup(dev);
+	if (err) {
+		if (err == -EBUSY)
+			goto fail_unregister_device;
+		else
+			goto fail_unregister_pci;
+	}
+
+	/* print pci info */
+	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+	pr_info("%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+		dev->pci_lat, (unsigned long long)dev->base_io_addr);
+
+	pci_set_master(pci_dev);
+	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		err = -EIO;
+		goto fail_irq;
+	}
+
+	err =
+	    request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED,
+			dev->name, dev);
+
+	if (err < 0) {
+		pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+		goto fail_irq;
+	}
+
+	return 0;
+
+fail_irq:
+	pr_info("cx25821_initdev() can't get IRQ !\n");
+	cx25821_dev_unregister(dev);
+
+fail_unregister_pci:
+	pci_disable_device(pci_dev);
+fail_unregister_device:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+fail_free:
+	kfree(dev);
+	return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx25821_dev *dev = get_cx25821(v4l2_dev);
+
+	cx25821_shutdown(dev);
+	pci_disable_device(pci_dev);
+
+	/* unregister stuff */
+	if (pci_dev->irq)
+		free_irq(pci_dev->irq, dev);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_del(&dev->devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	cx25821_dev_unregister(dev);
+	v4l2_device_unregister(v4l2_dev);
+	kfree(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = {
+	{
+		/* CX25821 Athena */
+		.vendor = 0x14f1,
+		.device = 0x8210,
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+	},
+	{
+		/* --- end of list --- */
+	}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = {
+	.name = "cx25821",
+	.id_table = cx25821_pci_tbl,
+	.probe = cx25821_initdev,
+	.remove = __devexit_p(cx25821_finidev),
+	/* TODO */
+	.suspend = NULL,
+	.resume = NULL,
+};
+
+static int __init cx25821_init(void)
+{
+	pr_info("driver version %d.%d.%d loaded\n",
+		(CX25821_VERSION_CODE >> 16) & 0xff,
+		(CX25821_VERSION_CODE >> 8) & 0xff,
+		CX25821_VERSION_CODE & 0xff);
+	return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void __exit cx25821_fini(void)
+{
+	pci_unregister_driver(&cx25821_pci_driver);
+}
+
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-gpio.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-gpio.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx25821.h"
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+				   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_oe_reg = GPIO_LO_OE;
+	u32 gpio_register = 0;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_oe_reg = GPIO_HI_OE;
+	}
+	/* Here we will make sure that the GPIOs 0 and 1 are output. keep the
+	 * rest as is */
+	gpio_register = cx_read(gpio_oe_reg);
+
+	if (pin_logic_value == 1)
+		value = gpio_register | Set_GPIO_Bit(bit);
+	else
+		value = gpio_register & Clear_GPIO_Bit(bit);
+
+	cx_write(gpio_oe_reg, value);
+}
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
+					   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_reg = GPIO_LO;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	/* change to output direction */
+	cx25821_set_gpiopin_direction(dev, pin_number, 0);
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_reg = GPIO_HI;
+	}
+
+	value = cx_read(gpio_reg);
+
+	if (pin_logic_value == 0)
+		value &= Clear_GPIO_Bit(bit);
+	else
+		value |= Set_GPIO_Bit(bit);
+
+	cx_write(gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	switch (dev->board) {
+	case CX25821_BOARD_CONEXANT_ATHENA10:
+	default:
+		/* set GPIO 5 to select the path for Medusa/Athena */
+		cx25821_set_gpiopin_logicvalue(dev, 5, 1);
+		mdelay(20);
+		break;
+	}
+
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,617 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE    1
+#define FALSE   0
+#define LINE_SIZE_D1    1440
+
+/* Number of decoders and encoders */
+#define MAX_DECODERS            8
+#define MAX_ENCODERS            2
+#define QUAD_DECODERS           4
+#define MAX_CAMERAS             16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT 8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0       1
+#define RESOURCE_VIDEO1       2
+#define RESOURCE_VIDEO2       4
+#define RESOURCE_VIDEO3       8
+#define RESOURCE_VIDEO4       16
+#define RESOURCE_VIDEO5       32
+#define RESOURCE_VIDEO6       64
+#define RESOURCE_VIDEO7       128
+#define RESOURCE_VIDEO8       256
+#define RESOURCE_VIDEO9       512
+#define RESOURCE_VIDEO10      1024
+#define RESOURCE_VIDEO11      2048
+#define RESOURCE_VIDEO_IOCTL  4096
+
+#define BUFFER_TIMEOUT     (HZ)	/* 0.5 seconds */
+
+#define UNKNOWN_BOARD       0
+#define CX25821_BOARD        1
+
+/* Currently supported by the driver */
+#define CX25821_NORMS (\
+	V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+	V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+	V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
+	V4L2_STD_PAL_Nc)
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM     12
+#define VID_CHANNEL_NUM 8
+#define CX25821_NR_INPUT 2
+
+struct cx25821_fmt {
+	char *name;
+	u32 fourcc;		/* v4l2 format id */
+	int depth;
+	int flags;
+	u32 cxformat;
+};
+
+struct cx25821_ctrl {
+	struct v4l2_queryctrl v;
+	u32 off;
+	u32 reg;
+	u32 mask;
+	u32 shift;
+};
+
+struct cx25821_tvnorm {
+	char *name;
+	v4l2_std_id id;
+	u32 cxiformat;
+	u32 cxoformat;
+};
+
+struct cx25821_fh {
+	struct cx25821_dev *dev;
+	enum v4l2_buf_type type;
+	int radio;
+	u32 resources;
+
+	enum v4l2_priority prio;
+
+	/* video overlay */
+	struct v4l2_window win;
+	struct v4l2_clip *clips;
+	unsigned int nclips;
+
+	/* video capture */
+	struct cx25821_fmt *fmt;
+	unsigned int width, height;
+	int channel_id;
+
+	/* vbi capture */
+	struct videobuf_queue vidq;
+	struct videobuf_queue vbiq;
+
+	/* H264 Encoder specifics ONLY */
+	struct videobuf_queue mpegq;
+	atomic_t v4l_reading;
+};
+
+enum cx25821_itype {
+	CX25821_VMUX_COMPOSITE = 1,
+	CX25821_VMUX_SVIDEO,
+	CX25821_VMUX_DEBUG,
+	CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+	CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+	CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	/* cx25821 specific */
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct cx25821_fmt *fmt;
+	u32 count;
+};
+
+struct cx25821_input {
+	enum cx25821_itype type;
+	unsigned int vmux;
+	u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+enum port {
+	CX25821_UNDEFINED = 0,
+	CX25821_RAW,
+	CX25821_264
+};
+
+struct cx25821_board {
+	char *name;
+	enum port porta;
+	enum port portb;
+	enum port portc;
+	unsigned int tuner_type;
+	unsigned int radio_type;
+	unsigned char tuner_addr;
+	unsigned char radio_addr;
+
+	u32 clk_freq;
+	struct cx25821_input input[CX25821_NR_INPUT];
+};
+
+struct cx25821_subid {
+	u16 subvendor;
+	u16 subdevice;
+	u32 card;
+};
+
+struct cx25821_i2c {
+	struct cx25821_dev *dev;
+
+	int nr;
+
+	/* i2c i/o */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algo_bit_data i2c_algo;
+	struct i2c_client i2c_client;
+	u32 i2c_rc;
+
+	/* cx25821 registers used for raw addess */
+	u32 i2c_period;
+	u32 reg_ctrl;
+	u32 reg_stat;
+	u32 reg_addr;
+	u32 reg_rdata;
+	u32 reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+	struct list_head active;
+	struct list_head queued;
+	struct timer_list timeout;
+	struct btcx_riscmem stopper;
+	u32 count;
+};
+
+struct cx25821_data {
+	struct cx25821_dev *dev;
+	struct sram_channel *channel;
+};
+
+struct cx25821_channel {
+	struct v4l2_prio_state prio;
+
+	int ctl_bright;
+	int ctl_contrast;
+	int ctl_hue;
+	int ctl_saturation;
+	struct cx25821_data timeout_data;
+
+	struct video_device *video_dev;
+	struct cx25821_dmaqueue vidq;
+
+	struct sram_channel *sram_channels;
+
+	struct mutex lock;
+	int resources;
+
+	int pixel_formats;
+	int use_cif_resolution;
+	int cif_width;
+};
+
+struct cx25821_dev {
+	struct list_head devlist;
+	atomic_t refcount;
+	struct v4l2_device v4l2_dev;
+
+	/* pci stuff */
+	struct pci_dev *pci;
+	unsigned char pci_rev, pci_lat;
+	int pci_bus, pci_slot;
+	u32 base_io_addr;
+	u32 __iomem *lmmio;
+	u8 __iomem *bmmio;
+	int pci_irqmask;
+	int hwrevision;
+
+	u32 clk_freq;
+
+	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+	struct cx25821_i2c i2c_bus[3];
+
+	int nr;
+	struct mutex lock;
+
+	struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
+
+	/* board details */
+	unsigned int board;
+	char name[32];
+
+	/* Analog video */
+	u32 resources;
+	unsigned int input;
+	u32 tvaudio;
+	v4l2_std_id tvnorm;
+	unsigned int tuner_type;
+	unsigned char tuner_addr;
+	unsigned int radio_type;
+	unsigned char radio_addr;
+	unsigned int has_radio;
+	unsigned int videc_type;
+	unsigned char videc_addr;
+	unsigned short _max_num_decoders;
+
+	/* Analog Audio Upstream */
+	int _audio_is_running;
+	int _audiopixel_format;
+	int _is_first_audio_frame;
+	int _audiofile_status;
+	int _audio_lines_count;
+	int _audioframe_count;
+	int _audio_upstream_channel;
+	int _last_index_irq;    /* The last interrupt index processed. */
+
+	__le32 *_risc_audio_jmp_addr;
+	__le32 *_risc_virt_start_addr;
+	__le32 *_risc_virt_addr;
+	dma_addr_t _risc_phys_addr;
+	dma_addr_t _risc_phys_start_addr;
+
+	unsigned int _audiorisc_size;
+	unsigned int _audiodata_buf_size;
+	__le32 *_audiodata_buf_virt_addr;
+	dma_addr_t _audiodata_buf_phys_addr;
+	char *_audiofilename;
+
+	/* V4l */
+	u32 freq;
+	struct video_device *vbi_dev;
+	struct video_device *radio_dev;
+	struct video_device *ioctl_dev;
+
+	spinlock_t slock;
+
+	/* Video Upstream */
+	int _line_size;
+	int _prog_cnt;
+	int _pixel_format;
+	int _is_first_frame;
+	int _is_running;
+	int _file_status;
+	int _lines_count;
+	int _frame_count;
+	int _channel_upstream_select;
+	unsigned int _risc_size;
+
+	__le32 *_dma_virt_start_addr;
+	__le32 *_dma_virt_addr;
+	dma_addr_t _dma_phys_addr;
+	dma_addr_t _dma_phys_start_addr;
+
+	unsigned int _data_buf_size;
+	__le32 *_data_buf_virt_addr;
+	dma_addr_t _data_buf_phys_addr;
+	char *_filename;
+	char *_defaultname;
+
+	int _line_size_ch2;
+	int _prog_cnt_ch2;
+	int _pixel_format_ch2;
+	int _is_first_frame_ch2;
+	int _is_running_ch2;
+	int _file_status_ch2;
+	int _lines_count_ch2;
+	int _frame_count_ch2;
+	int _channel2_upstream_select;
+	unsigned int _risc_size_ch2;
+
+	__le32 *_dma_virt_start_addr_ch2;
+	__le32 *_dma_virt_addr_ch2;
+	dma_addr_t _dma_phys_addr_ch2;
+	dma_addr_t _dma_phys_start_addr_ch2;
+
+	unsigned int _data_buf_size_ch2;
+	__le32 *_data_buf_virt_addr_ch2;
+	dma_addr_t _data_buf_phys_addr_ch2;
+	char *_filename_ch2;
+	char *_defaultname_ch2;
+
+	/* MPEG Encoder ONLY settings */
+	u32 cx23417_mailbox;
+	struct cx2341x_mpeg_params mpeg_params;
+	struct video_device *v4l_device;
+	atomic_t v4l_reader_count;
+	struct cx25821_tvnorm encodernorm;
+
+	u32 upstream_riscbuf_size;
+	u32 upstream_databuf_size;
+	u32 upstream_riscbuf_size_ch2;
+	u32 upstream_databuf_size_ch2;
+	u32 audio_upstream_riscbuf_size;
+	u32 audio_upstream_databuf_size;
+	int _isNTSC;
+	int _frame_index;
+	int _audioframe_index;
+	struct workqueue_struct *_irq_queues;
+	struct work_struct _irq_work_entry;
+	struct workqueue_struct *_irq_queues_ch2;
+	struct work_struct _irq_work_entry_ch2;
+	struct workqueue_struct *_irq_audio_queues;
+	struct work_struct _audio_work_entry;
+	char *input_filename;
+	char *input_filename_ch2;
+	int _frame_index_ch2;
+	int _isNTSC_ch2;
+	char *vid_stdname_ch2;
+	int pixel_format_ch2;
+	int channel_select_ch2;
+	int command_ch2;
+	char *input_audiofilename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+	int channel_opened;
+};
+
+struct upstream_user_struct {
+	char *input_filename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+};
+
+struct downstream_user_struct {
+	char *vid_stdname;
+	int pixel_format;
+	int cif_resolution_enable;
+	int cif_width;
+	int decoder_select;
+	int command;
+	int reg_address;
+	int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+	v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+extern struct list_head cx25821_devlist;
+extern struct mutex cx25821_devlist_mutex;
+
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00  0		/* Video A */
+#define SRAM_CH01  1		/* Video B */
+#define SRAM_CH02  2		/* Video C */
+#define SRAM_CH03  3		/* Video D */
+#define SRAM_CH04  4		/* Video E */
+#define SRAM_CH05  5		/* Video F */
+#define SRAM_CH06  6		/* Video G */
+#define SRAM_CH07  7		/* Video H */
+
+#define SRAM_CH08  8		/* Audio A */
+#define SRAM_CH09  9		/* Video Upstream I */
+#define SRAM_CH10  10		/* Video Upstream J */
+#define SRAM_CH11  11		/* Audio Upstream AUD_CHANNEL_B */
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
+#define VIDEO_IOCTL_CH  11
+
+struct sram_channel {
+	char *name;
+	u32 i;
+	u32 cmds_start;
+	u32 ctrl_start;
+	u32 cdt;
+	u32 fifo_start;
+	u32 fifo_size;
+	u32 ptr1_reg;
+	u32 ptr2_reg;
+	u32 cnt1_reg;
+	u32 cnt2_reg;
+	u32 int_msk;
+	u32 int_stat;
+	u32 int_mstat;
+	u32 dma_ctl;
+	u32 gpcnt_ctl;
+	u32 gpcnt;
+	u32 aud_length;
+	u32 aud_cfg;
+	u32 fld_aud_fifo_en;
+	u32 fld_aud_risc_en;
+
+	/* For Upstream Video */
+	u32 vid_fmt_ctl;
+	u32 vid_active_ctl1;
+	u32 vid_active_ctl2;
+	u32 vid_cdt_size;
+
+	u32 vip_ctl;
+	u32 pix_frmt;
+	u32 jumponly;
+	u32 irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS         0
+#define STATUS_UNSUCCESSFUL    -1
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+	writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+	((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit)                       (1 << Bit)
+#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...)			\
+	pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...)			\
+	pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...)			\
+	pr_info("(%d): " fmt, dev->board, ##args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int cx25821_ir_init(struct cx25821_dev *dev);
+extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+					  int pin_number, int pin_logic_value);
+
+extern int medusa_video_init(struct cx25821_dev *dev);
+extern int medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
+				  int decoder_select);
+extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
+				 int decoder);
+extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
+			       int decoder);
+extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
+				 int decoder);
+
+extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+				      struct sram_channel *ch, unsigned int bpl,
+				      u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			       struct scatterlist *sglist,
+			       unsigned int top_offset,
+			       unsigned int bottom_offset,
+			       unsigned int bpl,
+			       unsigned int padding, unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+					 struct btcx_riscmem *risc,
+					 struct scatterlist *sglist,
+					 unsigned int bpl,
+					 unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct videobuf_queue *q,
+				struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+				u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+				      struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch);
+
+extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
+				  int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch,
+					    unsigned int bpl, u32 risc);
+
+extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
+				       int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+					 struct upstream_user_struct *up_data);
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					       struct sram_channel *ch,
+					       unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+				     u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+					      struct pci_dev *pci,
+					      struct video_device *template,
+					      char *type);
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-i2c.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,425 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (i2c_debug >= level)						\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+	int count;
+
+	for (count = 0; count < I2C_WAIT_RETRY; count++) {
+		if (!i2c_is_busy(i2c_adap))
+			break;
+		udelay(I2C_WAIT_DELAY);
+	}
+
+	if (I2C_WAIT_RETRY == count)
+		return 0;
+
+	return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined_rlen)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 wdata, addr, ctrl;
+	int retval, cnt;
+
+	if (joined_rlen)
+		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+			msg->len, joined_rlen);
+	else
+		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	/* dev, reg + first byte */
+	addr = (msg->addr << 25) | msg->buf[0];
+	wdata = msg->buf[0];
+
+	ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+	if (msg->len > 1)
+		ctrl |= I2C_NOSTOP | I2C_EXTEND;
+	else if (joined_rlen)
+		ctrl |= I2C_NOSTOP;
+
+	cx_write(bus->reg_addr, addr);
+	cx_write(bus->reg_wdata, wdata);
+	cx_write(bus->reg_ctrl, ctrl);
+
+	retval = i2c_wait_done(i2c_adap);
+	if (retval < 0)
+		goto err;
+
+	if (retval == 0)
+		goto eio;
+
+	if (i2c_debug) {
+		if (!(ctrl & I2C_NOSTOP))
+			printk(" >\n");
+	}
+
+	for (cnt = 1; cnt < msg->len; cnt++) {
+		/* following bytes */
+		wdata = msg->buf[cnt];
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+		else if (joined_rlen)
+			ctrl |= I2C_NOSTOP;
+
+		cx_write(bus->reg_addr, addr);
+		cx_write(bus->reg_wdata, wdata);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+
+		if (retval == 0)
+			goto eio;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 ctrl, cnt;
+	int retval;
+
+	if (i2c_debug && !joined)
+		dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	if (i2c_debug) {
+		if (joined)
+			dprintk(1, " R");
+		else
+			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+	}
+
+	for (cnt = 0; cnt < msg->len; cnt++) {
+
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+		if (retval == 0)
+			goto eio;
+		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	int i, retval = 0;
+
+	dprintk(1, "%s(num = %d)\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+			__func__, num, msgs[i].addr, msgs[i].len);
+
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read */
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+			   msgs[i].addr == msgs[i + 1].addr) {
+			/* write then read from same address */
+			retval =
+			    i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
+
+			if (retval < 0)
+				goto err;
+			i++;
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+		} else {
+			/* write */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+		}
+
+		if (retval < 0)
+			goto err;
+	}
+	return num;
+
+err:
+	return retval;
+}
+
+
+static u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL |
+	    I2C_FUNC_I2C |
+	    I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+	.master_xfer = i2c_xfer,
+	.functionality = cx25821_functionality,
+#ifdef NEED_ALGO_CONTROL
+	.algo_control = dummy_algo_control,
+#endif
+};
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+	.name = "cx25821",
+	.owner = THIS_MODULE,
+	.algo = &cx25821_i2c_algo_template,
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+	.name = "cx25821 internal",
+};
+
+/* init + register i2c algo-bit adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+	struct cx25821_dev *dev = bus->dev;
+
+	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+	memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template,
+	       sizeof(bus->i2c_adap));
+	memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template,
+	       sizeof(bus->i2c_algo));
+	memcpy(&bus->i2c_client, &cx25821_i2c_client_template,
+	       sizeof(bus->i2c_client));
+
+	bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+	strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+	bus->i2c_algo.data = bus;
+	bus->i2c_adap.algo_data = bus;
+	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+	i2c_add_adapter(&bus->i2c_adap);
+
+	bus->i2c_client.adapter = &bus->i2c_adap;
+
+	/* set up the I2c */
+	bus->i2c_client.addr = (0x88 >> 1);
+
+	return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+	i2c_del_adapter(&bus->i2c_adap);
+	return 0;
+}
+
+void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+{
+	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+	char buffer[3];
+	struct i2c_msg msg;
+	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+	/* Register 0x144 */
+	buffer[0] = 0x01;
+	buffer[1] = 0x44;
+	if (enable == 1)
+		buffer[2] = 0x05;
+	else
+		buffer[2] = 0x00;
+
+	msg.addr = 0x44;
+	msg.flags = I2C_M_TEN;
+	msg.len = 3;
+	msg.buf = buffer;
+
+	i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
+}
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int retval = 0;
+	int v = 0;
+	u8 addr[2] = { 0, 0 };
+	u8 buf[4] = { 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 2,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 4,
+			.buf = buf,
+		}
+	};
+
+	addr[0] = (reg_addr >> 8);
+	addr[1] = (reg_addr & 0xff);
+	msgs[0].addr = 0x44;
+	msgs[1].addr = 0x44;
+
+	retval = i2c_xfer(client->adapter, msgs, 2);
+
+	v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+	*value = v;
+
+	return v;
+}
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int retval = 0;
+	u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[1] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 6,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg_addr >> 8;
+	buf[1] = reg_addr & 0xff;
+	buf[5] = (value >> 24) & 0xff;
+	buf[4] = (value >> 16) & 0xff;
+	buf[3] = (value >> 8) & 0xff;
+	buf[2] = value & 0xff;
+	client->flags = 0;
+	msgs[0].addr = 0x44;
+
+	retval = i2c_xfer(client->adapter, msgs, 1);
+
+	return retval;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-defines.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-defines.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-defines.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-defines.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+/* Video deocder that we supported */
+#define VDEC_A		0
+#define VDEC_B		1
+#define VDEC_C		2
+#define VDEC_D		3
+#define VDEC_E		4
+#define VDEC_F		5
+#define VDEC_G		6
+#define VDEC_H		7
+
+/* end of display sequence */
+#define END_OF_SEQ					0xF;
+
+/* registry string size */
+#define MAX_REGISTRY_SZ					40;
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-reg.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-reg.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+/* Serial Slave Registers */
+#define	HOST_REGISTER1				0x0000
+#define	HOST_REGISTER2				0x0001
+
+/* Chip Configuration Registers */
+#define	CHIP_CTRL					0x0100
+#define	AFE_AB_CTRL					0x0104
+#define	AFE_CD_CTRL					0x0108
+#define	AFE_EF_CTRL					0x010C
+#define	AFE_GH_CTRL					0x0110
+#define	DENC_AB_CTRL				0x0114
+#define	BYP_AB_CTRL					0x0118
+#define	MON_A_CTRL					0x011C
+#define	DISP_SEQ_A					0x0120
+#define	DISP_SEQ_B					0x0124
+#define	DISP_AB_CNT					0x0128
+#define	DISP_CD_CNT					0x012C
+#define	DISP_EF_CNT					0x0130
+#define	DISP_GH_CNT					0x0134
+#define	DISP_IJ_CNT					0x0138
+#define	PIN_OE_CTRL					0x013C
+#define	PIN_SPD_CTRL				0x0140
+#define	PIN_SPD_CTRL2				0x0144
+#define	IRQ_STAT_CTRL				0x0148
+#define	POWER_CTRL_AB				0x014C
+#define	POWER_CTRL_CD				0x0150
+#define	POWER_CTRL_EF				0x0154
+#define	POWER_CTRL_GH				0x0158
+#define	TUNE_CTRL					0x015C
+#define	BIAS_CTRL					0x0160
+#define	AFE_AB_DIAG_CTRL			0x0164
+#define	AFE_CD_DIAG_CTRL			0x0168
+#define	AFE_EF_DIAG_CTRL			0x016C
+#define	AFE_GH_DIAG_CTRL			0x0170
+#define	PLL_AB_DIAG_CTRL			0x0174
+#define	PLL_CD_DIAG_CTRL			0x0178
+#define	PLL_EF_DIAG_CTRL			0x017C
+#define	PLL_GH_DIAG_CTRL			0x0180
+#define	TEST_CTRL					0x0184
+#define	BIST_STAT					0x0188
+#define	BIST_STAT2					0x018C
+#define	BIST_VID_PLL_AB_STAT		0x0190
+#define	BIST_VID_PLL_CD_STAT		0x0194
+#define	BIST_VID_PLL_EF_STAT		0x0198
+#define	BIST_VID_PLL_GH_STAT		0x019C
+#define	DLL_DIAG_CTRL				0x01A0
+#define	DEV_CH_ID_CTRL				0x01A4
+#define	ABIST_CTRL_STATUS			0x01A8
+#define	ABIST_FREQ					0x01AC
+#define	ABIST_GOERT_SHIFT			0x01B0
+#define	ABIST_COEF12				0x01B4
+#define	ABIST_COEF34				0x01B8
+#define	ABIST_COEF56				0x01BC
+#define	ABIST_COEF7_SNR				0x01C0
+#define	ABIST_ADC_CAL				0x01C4
+#define	ABIST_BIN1_VGA0				0x01C8
+#define	ABIST_BIN2_VGA1				0x01CC
+#define	ABIST_BIN3_VGA2				0x01D0
+#define	ABIST_BIN4_VGA3				0x01D4
+#define	ABIST_BIN5_VGA4				0x01D8
+#define	ABIST_BIN6_VGA5				0x01DC
+#define	ABIST_BIN7_VGA6				0x0x1E0
+#define	ABIST_CLAMP_A				0x0x1E4
+#define	ABIST_CLAMP_B				0x0x1E8
+#define	ABIST_CLAMP_C				0x01EC
+#define	ABIST_CLAMP_D				0x01F0
+#define	ABIST_CLAMP_E				0x01F4
+#define	ABIST_CLAMP_F				0x01F8
+
+/*              Digital Video Encoder A Registers */
+#define	DENC_A_REG_1					0x0200
+#define	DENC_A_REG_2					0x0204
+#define	DENC_A_REG_3					0x0208
+#define	DENC_A_REG_4					0x020C
+#define	DENC_A_REG_5					0x0210
+#define	DENC_A_REG_6					0x0214
+#define	DENC_A_REG_7					0x0218
+#define	DENC_A_REG_8					0x021C
+
+/*      Digital Video Encoder B Registers */
+#define	DENC_B_REG_1					0x0300
+#define	DENC_B_REG_2					0x0304
+#define	DENC_B_REG_3					0x0308
+#define	DENC_B_REG_4					0x030C
+#define	DENC_B_REG_5					0x0310
+#define	DENC_B_REG_6					0x0314
+#define	DENC_B_REG_7					0x0318
+#define	DENC_B_REG_8					0x031C
+
+/*              Video Decoder A Registers */
+#define	MODE_CTRL						0x1000
+#define	OUT_CTRL1						0x1004
+#define	OUT_CTRL_NS						0x1008
+#define	GEN_STAT						0x100C
+#define	INT_STAT_MASK					0x1010
+#define	LUMA_CTRL						0x1014
+#define	CHROMA_CTRL						0x1018
+#define	CRUSH_CTRL						0x101C
+#define	HORIZ_TIM_CTRL					0x1020
+#define	VERT_TIM_CTRL					0x1024
+#define	MISC_TIM_CTRL					0x1028
+#define	FIELD_COUNT						0x102C
+#define	HSCALE_CTRL						0x1030
+#define	VSCALE_CTRL						0x1034
+#define	MAN_VGA_CTRL					0x1038
+#define	MAN_AGC_CTRL					0x103C
+#define	DFE_CTRL1						0x1040
+#define	DFE_CTRL2						0x1044
+#define	DFE_CTRL3						0x1048
+#define	PLL_CTRL						0x104C
+#define	PLL_CTRL_FAST					0x1050
+#define	HTL_CTRL						0x1054
+#define	SRC_CFG							0x1058
+#define	SC_STEP_SIZE					0x105C
+#define	SC_CONVERGE_CTRL				0x1060
+#define	SC_LOOP_CTRL					0x1064
+#define	COMB_2D_HFS_CFG					0x1068
+#define	COMB_2D_HFD_CFG					0x106C
+#define	COMB_2D_LF_CFG					0x1070
+#define	COMB_2D_BLEND					0x1074
+#define	COMB_MISC_CTRL					0x1078
+#define	COMB_FLAT_THRESH_CTRL			0x107C
+#define	COMB_TEST						0x1080
+#define	BP_MISC_CTRL					0x1084
+#define	VCR_DET_CTRL					0x1088
+#define	NOISE_DET_CTRL					0x108C
+#define	COMB_FLAT_NOISE_CTRL			0x1090
+#define	VERSION							0x11F8
+#define	SOFT_RST_CTRL					0x11FC
+
+/*      Video Decoder B Registers */
+#define	VDEC_B_MODE_CTRL				0x1200
+#define	VDEC_B_OUT_CTRL1				0x1204
+#define	VDEC_B_OUT_CTRL_NS				0x1208
+#define	VDEC_B_GEN_STAT					0x120C
+#define	VDEC_B_INT_STAT_MASK			0x1210
+#define	VDEC_B_LUMA_CTRL				0x1214
+#define	VDEC_B_CHROMA_CTRL				0x1218
+#define	VDEC_B_CRUSH_CTRL				0x121C
+#define	VDEC_B_HORIZ_TIM_CTRL			0x1220
+#define	VDEC_B_VERT_TIM_CTRL			0x1224
+#define	VDEC_B_MISC_TIM_CTRL			0x1228
+#define	VDEC_B_FIELD_COUNT				0x122C
+#define	VDEC_B_HSCALE_CTRL				0x1230
+#define	VDEC_B_VSCALE_CTRL				0x1234
+#define	VDEC_B_MAN_VGA_CTRL				0x1238
+#define	VDEC_B_MAN_AGC_CTRL				0x123C
+#define	VDEC_B_DFE_CTRL1				0x1240
+#define	VDEC_B_DFE_CTRL2				0x1244
+#define	VDEC_B_DFE_CTRL3				0x1248
+#define	VDEC_B_PLL_CTRL					0x124C
+#define	VDEC_B_PLL_CTRL_FAST			0x1250
+#define	VDEC_B_HTL_CTRL					0x1254
+#define	VDEC_B_SRC_CFG					0x1258
+#define	VDEC_B_SC_STEP_SIZE				0x125C
+#define	VDEC_B_SC_CONVERGE_CTRL			0x1260
+#define	VDEC_B_SC_LOOP_CTRL				0x1264
+#define	VDEC_B_COMB_2D_HFS_CFG			0x1268
+#define	VDEC_B_COMB_2D_HFD_CFG			0x126C
+#define	VDEC_B_COMB_2D_LF_CFG			0x1270
+#define	VDEC_B_COMB_2D_BLEND			0x1274
+#define	VDEC_B_COMB_MISC_CTRL			0x1278
+#define	VDEC_B_COMB_FLAT_THRESH_CTRL	0x127C
+#define	VDEC_B_COMB_TEST				0x1280
+#define	VDEC_B_BP_MISC_CTRL				0x1284
+#define	VDEC_B_VCR_DET_CTRL				0x1288
+#define	VDEC_B_NOISE_DET_CTRL			0x128C
+#define	VDEC_B_COMB_FLAT_NOISE_CTRL		0x1290
+#define	VDEC_B_VERSION					0x13F8
+#define	VDEC_B_SOFT_RST_CTRL			0x13FC
+
+/* Video Decoder C Registers */
+#define	VDEC_C_MODE_CTRL				0x1400
+#define	VDEC_C_OUT_CTRL1				0x1404
+#define	VDEC_C_OUT_CTRL_NS				0x1408
+#define	VDEC_C_GEN_STAT					0x140C
+#define	VDEC_C_INT_STAT_MASK			0x1410
+#define VDEC_C_LUMA_CTRL				0x1414
+#define VDEC_C_CHROMA_CTRL				0x1418
+#define	VDEC_C_CRUSH_CTRL				0x141C
+#define	VDEC_C_HORIZ_TIM_CTRL			0x1420
+#define	VDEC_C_VERT_TIM_CTRL			0x1424
+#define	VDEC_C_MISC_TIM_CTRL			0x1428
+#define	VDEC_C_FIELD_COUNT				0x142C
+#define	VDEC_C_HSCALE_CTRL				0x1430
+#define	VDEC_C_VSCALE_CTRL				0x1434
+#define	VDEC_C_MAN_VGA_CTRL				0x1438
+#define	VDEC_C_MAN_AGC_CTRL				0x143C
+#define	VDEC_C_DFE_CTRL1				0x1440
+#define	VDEC_C_DFE_CTRL2				0x1444
+#define	VDEC_C_DFE_CTRL3				0x1448
+#define	VDEC_C_PLL_CTRL					0x144C
+#define	VDEC_C_PLL_CTRL_FAST			0x1450
+#define	VDEC_C_HTL_CTRL					0x1454
+#define	VDEC_C_SRC_CFG					0x1458
+#define	VDEC_C_SC_STEP_SIZE				0x145C
+#define	VDEC_C_SC_CONVERGE_CTRL			0x1460
+#define	VDEC_C_SC_LOOP_CTRL				0x1464
+#define	VDEC_C_COMB_2D_HFS_CFG			0x1468
+#define	VDEC_C_COMB_2D_HFD_CFG			0x146C
+#define	VDEC_C_COMB_2D_LF_CFG			0x1470
+#define	VDEC_C_COMB_2D_BLEND			0x1474
+#define	VDEC_C_COMB_MISC_CTRL			0x1478
+#define	VDEC_C_COMB_FLAT_THRESH_CTRL	0x147C
+#define	VDEC_C_COMB_TEST				0x1480
+#define	VDEC_C_BP_MISC_CTRL				0x1484
+#define	VDEC_C_VCR_DET_CTRL				0x1488
+#define	VDEC_C_NOISE_DET_CTRL			0x148C
+#define	VDEC_C_COMB_FLAT_NOISE_CTRL		0x1490
+#define	VDEC_C_VERSION					0x15F8
+#define	VDEC_C_SOFT_RST_CTRL			0x15FC
+
+/* Video Decoder D Registers */
+#define VDEC_D_MODE_CTRL				0x1600
+#define VDEC_D_OUT_CTRL1				0x1604
+#define VDEC_D_OUT_CTRL_NS				0x1608
+#define VDEC_D_GEN_STAT					0x160C
+#define VDEC_D_INT_STAT_MASK			0x1610
+#define VDEC_D_LUMA_CTRL				0x1614
+#define VDEC_D_CHROMA_CTRL				0x1618
+#define VDEC_D_CRUSH_CTRL				0x161C
+#define VDEC_D_HORIZ_TIM_CTRL			0x1620
+#define VDEC_D_VERT_TIM_CTRL			0x1624
+#define VDEC_D_MISC_TIM_CTRL			0x1628
+#define VDEC_D_FIELD_COUNT				0x162C
+#define VDEC_D_HSCALE_CTRL				0x1630
+#define VDEC_D_VSCALE_CTRL				0x1634
+#define VDEC_D_MAN_VGA_CTRL				0x1638
+#define VDEC_D_MAN_AGC_CTRL				0x163C
+#define VDEC_D_DFE_CTRL1				0x1640
+#define VDEC_D_DFE_CTRL2				0x1644
+#define VDEC_D_DFE_CTRL3				0x1648
+#define VDEC_D_PLL_CTRL					0x164C
+#define VDEC_D_PLL_CTRL_FAST			0x1650
+#define VDEC_D_HTL_CTRL					0x1654
+#define VDEC_D_SRC_CFG					0x1658
+#define VDEC_D_SC_STEP_SIZE				0x165C
+#define VDEC_D_SC_CONVERGE_CTRL			0x1660
+#define VDEC_D_SC_LOOP_CTRL				0x1664
+#define VDEC_D_COMB_2D_HFS_CFG			0x1668
+#define VDEC_D_COMB_2D_HFD_CFG			0x166C
+#define VDEC_D_COMB_2D_LF_CFG			0x1670
+#define VDEC_D_COMB_2D_BLEND			0x1674
+#define VDEC_D_COMB_MISC_CTRL			0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL	0x167C
+#define VDEC_D_COMB_TEST				0x1680
+#define VDEC_D_BP_MISC_CTRL				0x1684
+#define VDEC_D_VCR_DET_CTRL				0x1688
+#define VDEC_D_NOISE_DET_CTRL			0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL		0x1690
+#define VDEC_D_VERSION					0x17F8
+#define VDEC_D_SOFT_RST_CTRL			0x17FC
+
+/* Video Decoder E Registers */
+#define	VDEC_E_MODE_CTRL				0x1800
+#define	VDEC_E_OUT_CTRL1				0x1804
+#define	VDEC_E_OUT_CTRL_NS				0x1808
+#define	VDEC_E_GEN_STAT					0x180C
+#define	VDEC_E_INT_STAT_MASK			0x1810
+#define	VDEC_E_LUMA_CTRL				0x1814
+#define	VDEC_E_CHROMA_CTRL				0x1818
+#define	VDEC_E_CRUSH_CTRL				0x181C
+#define	VDEC_E_HORIZ_TIM_CTRL			0x1820
+#define	VDEC_E_VERT_TIM_CTRL			0x1824
+#define	VDEC_E_MISC_TIM_CTRL			0x1828
+#define	VDEC_E_FIELD_COUNT				0x182C
+#define	VDEC_E_HSCALE_CTRL				0x1830
+#define	VDEC_E_VSCALE_CTRL				0x1834
+#define	VDEC_E_MAN_VGA_CTRL				0x1838
+#define	VDEC_E_MAN_AGC_CTRL				0x183C
+#define	VDEC_E_DFE_CTRL1				0x1840
+#define	VDEC_E_DFE_CTRL2				0x1844
+#define	VDEC_E_DFE_CTRL3				0x1848
+#define	VDEC_E_PLL_CTRL					0x184C
+#define	VDEC_E_PLL_CTRL_FAST			0x1850
+#define	VDEC_E_HTL_CTRL					0x1854
+#define	VDEC_E_SRC_CFG					0x1858
+#define	VDEC_E_SC_STEP_SIZE				0x185C
+#define	VDEC_E_SC_CONVERGE_CTRL			0x1860
+#define	VDEC_E_SC_LOOP_CTRL				0x1864
+#define	VDEC_E_COMB_2D_HFS_CFG			0x1868
+#define	VDEC_E_COMB_2D_HFD_CFG			0x186C
+#define	VDEC_E_COMB_2D_LF_CFG			0x1870
+#define	VDEC_E_COMB_2D_BLEND			0x1874
+#define	VDEC_E_COMB_MISC_CTRL			0x1878
+#define	VDEC_E_COMB_FLAT_THRESH_CTRL	0x187C
+#define	VDEC_E_COMB_TEST				0x1880
+#define	VDEC_E_BP_MISC_CTRL				0x1884
+#define	VDEC_E_VCR_DET_CTRL				0x1888
+#define	VDEC_E_NOISE_DET_CTRL			0x188C
+#define	VDEC_E_COMB_FLAT_NOISE_CTRL		0x1890
+#define	VDEC_E_VERSION					0x19F8
+#define	VDEC_E_SOFT_RST_CTRL			0x19FC
+
+/* Video Decoder F Registers */
+#define	VDEC_F_MODE_CTRL				0x1A00
+#define	VDEC_F_OUT_CTRL1				0x1A04
+#define	VDEC_F_OUT_CTRL_NS				0x1A08
+#define	VDEC_F_GEN_STAT					0x1A0C
+#define	VDEC_F_INT_STAT_MASK			0x1A10
+#define	VDEC_F_LUMA_CTRL				0x1A14
+#define	VDEC_F_CHROMA_CTRL				0x1A18
+#define	VDEC_F_CRUSH_CTRL				0x1A1C
+#define	VDEC_F_HORIZ_TIM_CTRL			0x1A20
+#define	VDEC_F_VERT_TIM_CTRL			0x1A24
+#define	VDEC_F_MISC_TIM_CTRL			0x1A28
+#define	VDEC_F_FIELD_COUNT				0x1A2C
+#define	VDEC_F_HSCALE_CTRL				0x1A30
+#define	VDEC_F_VSCALE_CTRL				0x1A34
+#define	VDEC_F_MAN_VGA_CTRL				0x1A38
+#define	VDEC_F_MAN_AGC_CTRL				0x1A3C
+#define	VDEC_F_DFE_CTRL1				0x1A40
+#define	VDEC_F_DFE_CTRL2				0x1A44
+#define	VDEC_F_DFE_CTRL3				0x1A48
+#define	VDEC_F_PLL_CTRL					0x1A4C
+#define	VDEC_F_PLL_CTRL_FAST			0x1A50
+#define	VDEC_F_HTL_CTRL					0x1A54
+#define	VDEC_F_SRC_CFG					0x1A58
+#define	VDEC_F_SC_STEP_SIZE				0x1A5C
+#define	VDEC_F_SC_CONVERGE_CTRL			0x1A60
+#define	VDEC_F_SC_LOOP_CTRL				0x1A64
+#define	VDEC_F_COMB_2D_HFS_CFG			0x1A68
+#define	VDEC_F_COMB_2D_HFD_CFG			0x1A6C
+#define	VDEC_F_COMB_2D_LF_CFG			0x1A70
+#define	VDEC_F_COMB_2D_BLEND			0x1A74
+#define	VDEC_F_COMB_MISC_CTRL			0x1A78
+#define	VDEC_F_COMB_FLAT_THRESH_CTRL	0x1A7C
+#define	VDEC_F_COMB_TEST				0x1A80
+#define	VDEC_F_BP_MISC_CTRL				0x1A84
+#define	VDEC_F_VCR_DET_CTRL				0x1A88
+#define	VDEC_F_NOISE_DET_CTRL			0x1A8C
+#define	VDEC_F_COMB_FLAT_NOISE_CTRL		0x1A90
+#define	VDEC_F_VERSION					0x1BF8
+#define	VDEC_F_SOFT_RST_CTRL			0x1BFC
+
+/* Video Decoder G Registers */
+#define	VDEC_G_MODE_CTRL				0x1C00
+#define	VDEC_G_OUT_CTRL1				0x1C04
+#define	VDEC_G_OUT_CTRL_NS				0x1C08
+#define	VDEC_G_GEN_STAT					0x1C0C
+#define	VDEC_G_INT_STAT_MASK			0x1C10
+#define	VDEC_G_LUMA_CTRL				0x1C14
+#define	VDEC_G_CHROMA_CTRL				0x1C18
+#define	VDEC_G_CRUSH_CTRL				0x1C1C
+#define	VDEC_G_HORIZ_TIM_CTRL			0x1C20
+#define	VDEC_G_VERT_TIM_CTRL			0x1C24
+#define	VDEC_G_MISC_TIM_CTRL			0x1C28
+#define	VDEC_G_FIELD_COUNT				0x1C2C
+#define	VDEC_G_HSCALE_CTRL				0x1C30
+#define	VDEC_G_VSCALE_CTRL				0x1C34
+#define	VDEC_G_MAN_VGA_CTRL				0x1C38
+#define	VDEC_G_MAN_AGC_CTRL				0x1C3C
+#define	VDEC_G_DFE_CTRL1				0x1C40
+#define	VDEC_G_DFE_CTRL2				0x1C44
+#define	VDEC_G_DFE_CTRL3				0x1C48
+#define	VDEC_G_PLL_CTRL					0x1C4C
+#define	VDEC_G_PLL_CTRL_FAST			0x1C50
+#define	VDEC_G_HTL_CTRL					0x1C54
+#define	VDEC_G_SRC_CFG					0x1C58
+#define	VDEC_G_SC_STEP_SIZE				0x1C5C
+#define	VDEC_G_SC_CONVERGE_CTRL			0x1C60
+#define	VDEC_G_SC_LOOP_CTRL				0x1C64
+#define	VDEC_G_COMB_2D_HFS_CFG			0x1C68
+#define	VDEC_G_COMB_2D_HFD_CFG			0x1C6C
+#define	VDEC_G_COMB_2D_LF_CFG			0x1C70
+#define	VDEC_G_COMB_2D_BLEND			0x1C74
+#define	VDEC_G_COMB_MISC_CTRL			0x1C78
+#define	VDEC_G_COMB_FLAT_THRESH_CTRL	0x1C7C
+#define	VDEC_G_COMB_TEST				0x1C80
+#define	VDEC_G_BP_MISC_CTRL				0x1C84
+#define	VDEC_G_VCR_DET_CTRL				0x1C88
+#define	VDEC_G_NOISE_DET_CTRL			0x1C8C
+#define	VDEC_G_COMB_FLAT_NOISE_CTRL		0x1C90
+#define	VDEC_G_VERSION					0x1DF8
+#define	VDEC_G_SOFT_RST_CTRL			0x1DFC
+
+/*              Video Decoder H Registers  */
+#define	VDEC_H_MODE_CTRL				0x1E00
+#define	VDEC_H_OUT_CTRL1				0x1E04
+#define	VDEC_H_OUT_CTRL_NS				0x1E08
+#define	VDEC_H_GEN_STAT					0x1E0C
+#define	VDEC_H_INT_STAT_MASK			0x1E1E
+#define	VDEC_H_LUMA_CTRL				0x1E14
+#define	VDEC_H_CHROMA_CTRL				0x1E18
+#define	VDEC_H_CRUSH_CTRL				0x1E1C
+#define	VDEC_H_HORIZ_TIM_CTRL			0x1E20
+#define	VDEC_H_VERT_TIM_CTRL			0x1E24
+#define	VDEC_H_MISC_TIM_CTRL			0x1E28
+#define	VDEC_H_FIELD_COUNT				0x1E2C
+#define	VDEC_H_HSCALE_CTRL				0x1E30
+#define	VDEC_H_VSCALE_CTRL				0x1E34
+#define	VDEC_H_MAN_VGA_CTRL				0x1E38
+#define	VDEC_H_MAN_AGC_CTRL				0x1E3C
+#define	VDEC_H_DFE_CTRL1				0x1E40
+#define	VDEC_H_DFE_CTRL2				0x1E44
+#define	VDEC_H_DFE_CTRL3				0x1E48
+#define	VDEC_H_PLL_CTRL					0x1E4C
+#define	VDEC_H_PLL_CTRL_FAST			0x1E50
+#define	VDEC_H_HTL_CTRL					0x1E54
+#define	VDEC_H_SRC_CFG					0x1E58
+#define	VDEC_H_SC_STEP_SIZE				0x1E5C
+#define	VDEC_H_SC_CONVERGE_CTRL			0x1E60
+#define	VDEC_H_SC_LOOP_CTRL				0x1E64
+#define	VDEC_H_COMB_2D_HFS_CFG			0x1E68
+#define	VDEC_H_COMB_2D_HFD_CFG			0x1E6C
+#define	VDEC_H_COMB_2D_LF_CFG			0x1E70
+#define	VDEC_H_COMB_2D_BLEND			0x1E74
+#define	VDEC_H_COMB_MISC_CTRL			0x1E78
+#define	VDEC_H_COMB_FLAT_THRESH_CTRL	0x1E7C
+#define	VDEC_H_COMB_TEST				0x1E80
+#define	VDEC_H_BP_MISC_CTRL				0x1E84
+#define	VDEC_H_VCR_DET_CTRL				0x1E88
+#define	VDEC_H_NOISE_DET_CTRL			0x1E8C
+#define	VDEC_H_COMB_FLAT_NOISE_CTRL		0x1E90
+#define	VDEC_H_VERSION					0x1FF8
+#define	VDEC_H_SOFT_RST_CTRL			0x1FFC
+
+/*****************************************************************************/
+/* LUMA_CTRL register fields */
+#define VDEC_A_BRITE_CTRL				0x1014
+#define VDEC_A_CNTRST_CTRL			0x1015
+#define VDEC_A_PEAK_SEL				0x1016
+
+/*****************************************************************************/
+/* CHROMA_CTRL register fields */
+#define VDEC_A_USAT_CTRL			0x1018
+#define VDEC_A_VSAT_CTRL			0x1019
+#define VDEC_A_HUE_CTRL				0x101A
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,872 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+/*
+ * medusa_enable_bluefield_output()
+ *
+ * Enable the generation of blue filed output if no video
+ *
+ */
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
+					   int enable)
+{
+	int ret_val = 1;
+	u32 value = 0;
+	u32 tmp = 0;
+	int out_ctrl = OUT_CTRL1;
+	int out_ctrl_ns = OUT_CTRL_NS;
+
+	switch (channel) {
+	default:
+	case VDEC_A:
+		break;
+	case VDEC_B:
+		out_ctrl = VDEC_B_OUT_CTRL1;
+		out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+		break;
+	case VDEC_C:
+		out_ctrl = VDEC_C_OUT_CTRL1;
+		out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+		break;
+	case VDEC_D:
+		out_ctrl = VDEC_D_OUT_CTRL1;
+		out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+		break;
+	case VDEC_E:
+		out_ctrl = VDEC_E_OUT_CTRL1;
+		out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+		return;
+	case VDEC_F:
+		out_ctrl = VDEC_F_OUT_CTRL1;
+		out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+		return;
+	case VDEC_G:
+		out_ctrl = VDEC_G_OUT_CTRL1;
+		out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+		return;
+	case VDEC_H:
+		out_ctrl = VDEC_H_OUT_CTRL1;
+		out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+		return;
+	}
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+	value &= 0xFFFFFF7F;	/* clear BLUE_FIELD_EN */
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+	value &= 0xFFFFFF7F;
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format NTSC-M */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10001;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				      value);
+
+		/* resolution NTSC 720x480 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x612D0074;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x1C1E001A;	/* vblank_cnt + 2 to get camera ID */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+
+		/* enable VIP optional active */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				      value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		*/
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				     &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				      value);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* NTSC hclock */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06B402D0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9054;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_2 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00EC00F0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x13020000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_4 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000E575;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+
+		/* Subcarrier Increment */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 480 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to NTSC 525 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00080200;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+	int ret_val = -1;
+	u32 value = 0, tmp = 0;
+
+	/* Setup for 2D threshold */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
+			      0x20002861);
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
+			      0x20002861);
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
+			      0x200A1023);
+
+	/* Setup flat chroma and luma thresholds */
+	value =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+	value &= 0x06230000;
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+
+	/* set comb 2D blend */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
+			      0x210F0F0F);
+
+	/* COMB MISC CONTROL */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
+			      0x41120A7F);
+
+	return ret_val;
+}
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format PAL-BDGHI */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10004;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				      value);
+
+		/* resolution PAL 720x576 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x632D007D;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		/* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x28240026;	/* vblank_cnt + 2 to get camera ID */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+
+		/* enable VIP optional active */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				      value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				     &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				      value);
+
+		medusa_PALCombInit(dev, i);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* PAL hclock */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06C002D0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9754;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_2 + (0x100 * i), value);
+
+		/* hblank and vactive */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00FC0120;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set PAL vblank, phase alternation, 0 IRE pedestal */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x14010000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_4 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000F078;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+
+		/* Subcarrier Increment */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 576 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to PAL 625 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value &= 0xFFF7FDFF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+	int status = STATUS_SUCCESS;
+	u32 value = 0, tmp = 0;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		status = medusa_initialize_pal(dev);
+	else
+		status = medusa_initialize_ntsc(dev);
+
+	/* Enable DENC_A output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+
+	/* Enable DENC_B output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+
+	return status;
+}
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width,
+			   int decoder_select)
+{
+	int decoder = 0;
+	int decoder_count = 0;
+	int ret_val = 0;
+	u32 hscale = 0x0;
+	u32 vscale = 0x0;
+	const int MAX_WIDTH = 720;
+
+	mutex_lock(&dev->lock);
+
+	/* validate the width - cannot be negative */
+	if (width > MAX_WIDTH) {
+		pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
+			__func__, width, MAX_WIDTH);
+		width = MAX_WIDTH;
+	}
+
+	if (decoder_select <= 7 && decoder_select >= 0) {
+		decoder = decoder_select;
+		decoder_count = decoder_select + 1;
+	} else {
+		decoder = 0;
+		decoder_count = _num_decoders;
+	}
+
+	switch (width) {
+	case 320:
+		hscale = 0x13E34B;
+		vscale = 0x0;
+		break;
+
+	case 352:
+		hscale = 0x10A273;
+		vscale = 0x0;
+		break;
+
+	case 176:
+		hscale = 0x3115B2;
+		vscale = 0x1E00;
+		break;
+
+	case 160:
+		hscale = 0x378D84;
+		vscale = 0x1E00;
+		break;
+
+	default:		/* 720 */
+		hscale = 0x0;
+		vscale = 0x0;
+		break;
+	}
+
+	for (; decoder < decoder_count; decoder++) {
+		/* write scaling values for each decoder */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HSCALE_CTRL + (0x200 * decoder), hscale);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VSCALE_CTRL + (0x200 * decoder), vscale);
+	}
+
+	mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+				       int duration)
+{
+	int ret_val = 0;
+	u32 fld_cnt = 0;
+	u32 tmp = 0;
+	u32 disp_cnt_reg = DISP_AB_CNT;
+
+	mutex_lock(&dev->lock);
+
+	/* no support */
+	if (decoder < VDEC_A && decoder > VDEC_H) {
+		mutex_unlock(&dev->lock);
+		return;
+	}
+
+	switch (decoder) {
+	default:
+		break;
+	case VDEC_C:
+	case VDEC_D:
+		disp_cnt_reg = DISP_CD_CNT;
+		break;
+	case VDEC_E:
+	case VDEC_F:
+		disp_cnt_reg = DISP_EF_CNT;
+		break;
+	case VDEC_G:
+	case VDEC_H:
+		disp_cnt_reg = DISP_GH_CNT;
+		break;
+	}
+
+	_display_field_cnt[decoder] = duration;
+
+	/* update hardware */
+	fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+
+	if (!(decoder % 2)) {	/* EVEN decoder */
+		fld_cnt &= 0xFFFF0000;
+		fld_cnt |= duration;
+	} else {
+		fld_cnt &= 0x0000FFFF;
+		fld_cnt |= ((u32) duration) << 16;
+	}
+
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+
+	mutex_unlock(&dev->lock);
+}
+
+/* Map to Medusa register setting */
+static int mapM(int srcMin,
+		int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
+{
+	int numerator;
+	int denominator;
+	int quotient;
+
+	if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
+		return -1;
+	/*
+	 * This is the overall expression used:
+	 * *dstVal =
+	 *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+	 * but we need to account for rounding so below we use the modulus
+	 * operator to find the remainder and increment if necessary.
+	 */
+	numerator = (srcVal - srcMin) * (dstMax - dstMin);
+	denominator = srcMax - srcMin;
+	quotient = numerator / denominator;
+
+	if (2 * (numerator % denominator) >= denominator)
+		quotient++;
+
+	*dstVal = quotient + dstMin;
+
+	return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+	unsigned char temp;
+
+	if (numeric >= 0)
+		return numeric;
+	else {
+		temp = ~(abs(numeric) & 0xFF);
+		temp += 1;
+		return temp;
+	}
+}
+
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+	if ((brightness > VIDEO_PROCAMP_MAX)
+	    || (brightness < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+		 SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+	value = convert_to_twos(value, 8);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_BRITE_CTRL + (0x200 * decoder),
+			      val | value);
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+		 UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_CNTRST_CTRL + (0x200 * decoder),
+			      val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
+		 SIGNED_BYTE_MAX, &value);
+
+	value = convert_to_twos(value, 8);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((saturation > VIDEO_PROCAMP_MAX)
+	    || (saturation < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+		 UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_USAT_CTRL + (0x200 * decoder),
+			      val | value);
+
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_VSAT_CTRL + (0x200 * decoder),
+			      val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+/* Program the display sequence and monitor output. */
+
+int medusa_video_init(struct cx25821_dev *dev)
+{
+	u32 value = 0, tmp = 0;
+	int ret_val = 0;
+	int i = 0;
+
+	mutex_lock(&dev->lock);
+
+	_num_decoders = dev->_max_num_decoders;
+
+	/* disable Auto source selection on all video decoders */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFF0FF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn off Master source switch enable */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFFFDF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	mutex_unlock(&dev->lock);
+
+	for (i = 0; i < _num_decoders; i++)
+		medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+
+	mutex_lock(&dev->lock);
+
+	/* Select monitor as DENC A input, power up the DAC */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+	value &= 0xFF70FF70;
+	value |= 0x00090008;	/* set en_active */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* enable input is VIP/656 */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00040100;	/* enable VIP */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* select AFE clock to output mode */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	value &= 0x83FFFFFF;
+	ret_val =
+	   cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+			     value | 0x10000000);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn on all of the data out and control output pins. */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+	value &= 0xFEF0FE00;
+	if (_num_decoders == MAX_DECODERS) {
+		/*
+		 * Note: The octal board does not support control pins(bit16-19)
+		 * These bits are ignored in the octal board.
+		 *
+		 * disable VDEC A-C port, default to Mobilygen Interface
+		 */
+		value |= 0x010001F8;
+	} else {
+		/* disable VDEC A-C port, default to Mobilygen Interface */
+		value |= 0x010F0108;
+	}
+
+	value |= 7;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+
+	mutex_unlock(&dev->lock);
+
+	ret_val = medusa_set_videostandard(dev);
+
+	return ret_val;
+
+error:
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-medusa-video.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#include "cx25821-medusa-defines.h"
+
+/* Color control constants */
+#define VIDEO_PROCAMP_MIN                 0
+#define VIDEO_PROCAMP_MAX                 10000
+#define UNSIGNED_BYTE_MIN                 0
+#define UNSIGNED_BYTE_MAX                 0xFF
+#define SIGNED_BYTE_MIN                   -128
+#define SIGNED_BYTE_MAX                   127
+
+/* Default video color settings */
+#define SHARPNESS_DEFAULT                 50
+#define SATURATION_DEFAULT              5000
+#define BRIGHTNESS_DEFAULT              6200
+#define CONTRAST_DEFAULT                5000
+#define HUE_DEFAULT                     5000
+
+unsigned short _num_decoders;
+unsigned short _num_cameras;
+
+unsigned int _video_standard;
+int _display_field_cnt[MAX_DECODERS];
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-reg.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-reg.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1592 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC	 0x00010000
+#define RISC_CNT_RESET	 0x00030000
+#define RISC_IRQ1		 0x01000000
+#define RISC_IRQ2		 0x02000000
+#define RISC_EOL		 0x04000000
+#define RISC_SOL		 0x08000000
+#define RISC_WRITE		 0x10000000
+#define RISC_SKIP		 0x20000000
+#define RISC_JUMP		 0x70000000
+#define RISC_SYNC		 0x80000000
+#define RISC_RESYNC		 0x80008000
+#define RISC_READ		 0x90000000
+#define RISC_WRITERM	 0xB0000000
+#define RISC_WRITECM	 0xC0000000
+#define RISC_WRITECR	 0xD0000000
+#define RISC_WRITEC		 0x50000000
+#define RISC_READC		 0xA0000000
+
+#define RISC_SYNC_ODD		 0x00000000
+#define RISC_SYNC_EVEN		 0x00000200
+#define RISC_SYNC_ODD_VBI	 0x00000006
+#define RISC_SYNC_EVEN_VBI	 0x00000207
+#define RISC_NOOP			 0xF0000000
+
+/*****************************************************************************
+* ASB SRAM
+ *****************************************************************************/
+#define  TX_SRAM                   0x000000	/* Transmit SRAM */
+
+/*****************************************************************************/
+#define  RX_RAM                    0x010000	/* Receive SRAM */
+
+/*****************************************************************************
+* Application Layer (AL)
+ *****************************************************************************/
+#define  DEV_CNTRL2                0x040000	/* Device control */
+#define  FLD_RUN_RISC              0x00000020
+
+/* ***************************************************************************** */
+#define  PCI_INT_MSK               0x040010	/* PCI interrupt mask */
+#define  PCI_INT_STAT              0x040014	/* PCI interrupt status */
+#define  PCI_INT_MSTAT             0x040018	/* PCI interrupt masked status */
+#define  FLD_HAMMERHEAD_INT        (1 << 27)
+#define  FLD_UART_INT              (1 << 26)
+#define  FLD_IRQN_INT              (1 << 25)
+#define  FLD_TM_INT                (1 << 28)
+#define  FLD_I2C_3_RACK            (1 << 27)
+#define  FLD_I2C_3_INT             (1 << 26)
+#define  FLD_I2C_2_RACK            (1 << 25)
+#define  FLD_I2C_2_INT             (1 << 24)
+#define  FLD_I2C_1_RACK            (1 << 23)
+#define  FLD_I2C_1_INT             (1 << 22)
+
+#define  FLD_APB_DMA_BERR_INT      (1 << 21)
+#define  FLD_AL_WR_BERR_INT        (1 << 20)
+#define  FLD_AL_RD_BERR_INT        (1 << 19)
+#define  FLD_RISC_WR_BERR_INT      (1 << 18)
+#define  FLD_RISC_RD_BERR_INT      (1 << 17)
+
+#define  FLD_VID_I_INT             (1 << 8)
+#define  FLD_VID_H_INT             (1 << 7)
+#define  FLD_VID_G_INT             (1 << 6)
+#define  FLD_VID_F_INT             (1 << 5)
+#define  FLD_VID_E_INT             (1 << 4)
+#define  FLD_VID_D_INT             (1 << 3)
+#define  FLD_VID_C_INT             (1 << 2)
+#define  FLD_VID_B_INT             (1 << 1)
+#define  FLD_VID_A_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  VID_A_INT_MSK             0x040020	/* Video A interrupt mask */
+#define  VID_A_INT_STAT            0x040024	/* Video A interrupt status */
+#define  VID_A_INT_MSTAT           0x040028	/* Video A interrupt masked status */
+#define  VID_A_INT_SSTAT           0x04002C	/* Video A interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_B_INT_MSK             0x040030	/* Video B interrupt mask */
+#define  VID_B_INT_STAT            0x040034	/* Video B interrupt status */
+#define  VID_B_INT_MSTAT           0x040038	/* Video B interrupt masked status */
+#define  VID_B_INT_SSTAT           0x04003C	/* Video B interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_C_INT_MSK             0x040040	/* Video C interrupt mask */
+#define  VID_C_INT_STAT            0x040044	/* Video C interrupt status */
+#define  VID_C_INT_MSTAT           0x040048	/* Video C interrupt masked status */
+#define  VID_C_INT_SSTAT           0x04004C	/* Video C interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_D_INT_MSK             0x040050	/* Video D interrupt mask */
+#define  VID_D_INT_STAT            0x040054	/* Video D interrupt status */
+#define  VID_D_INT_MSTAT           0x040058	/* Video D interrupt masked status */
+#define  VID_D_INT_SSTAT           0x04005C	/* Video D interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_E_INT_MSK             0x040060	/* Video E interrupt mask */
+#define  VID_E_INT_STAT            0x040064	/* Video E interrupt status */
+#define  VID_E_INT_MSTAT           0x040068	/* Video E interrupt masked status */
+#define  VID_E_INT_SSTAT           0x04006C	/* Video E interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_F_INT_MSK             0x040070	/* Video F interrupt mask */
+#define  VID_F_INT_STAT            0x040074	/* Video F interrupt status */
+#define  VID_F_INT_MSTAT           0x040078	/* Video F interrupt masked status */
+#define  VID_F_INT_SSTAT           0x04007C	/* Video F interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_G_INT_MSK             0x040080	/* Video G interrupt mask */
+#define  VID_G_INT_STAT            0x040084	/* Video G interrupt status */
+#define  VID_G_INT_MSTAT           0x040088	/* Video G interrupt masked status */
+#define  VID_G_INT_SSTAT           0x04008C	/* Video G interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_H_INT_MSK             0x040090	/* Video H interrupt mask */
+#define  VID_H_INT_STAT            0x040094	/* Video H interrupt status */
+#define  VID_H_INT_MSTAT           0x040098	/* Video H interrupt masked status */
+#define  VID_H_INT_SSTAT           0x04009C	/* Video H interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_I_INT_MSK             0x0400A0	/* Video I interrupt mask */
+#define  VID_I_INT_STAT            0x0400A4	/* Video I interrupt status */
+#define  VID_I_INT_MSTAT           0x0400A8	/* Video I interrupt masked status */
+#define  VID_I_INT_SSTAT           0x0400AC	/* Video I interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_J_INT_MSK             0x0400B0	/* Video J interrupt mask */
+#define  VID_J_INT_STAT            0x0400B4	/* Video J interrupt status */
+#define  VID_J_INT_MSTAT           0x0400B8	/* Video J interrupt masked status */
+#define  VID_J_INT_SSTAT           0x0400BC	/* Video J interrupt set status */
+
+#define  FLD_VID_SRC_OPC_ERR       0x00020000
+#define  FLD_VID_DST_OPC_ERR       0x00010000
+#define  FLD_VID_SRC_SYNC          0x00002000
+#define  FLD_VID_DST_SYNC          0x00001000
+#define  FLD_VID_SRC_UF            0x00000200
+#define  FLD_VID_DST_OF            0x00000100
+#define  FLD_VID_SRC_RISC2         0x00000020
+#define  FLD_VID_DST_RISC2         0x00000010
+#define  FLD_VID_SRC_RISC1         0x00000002
+#define  FLD_VID_DST_RISC1         0x00000001
+#define  FLD_VID_SRC_ERRORS		(FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
+#define  FLD_VID_DST_ERRORS		(FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
+
+/* ***************************************************************************** */
+#define  AUD_A_INT_MSK             0x0400C0	/* Audio Int interrupt mask */
+#define  AUD_A_INT_STAT            0x0400C4	/* Audio Int interrupt status */
+#define  AUD_A_INT_MSTAT           0x0400C8	/* Audio Int interrupt masked status */
+#define  AUD_A_INT_SSTAT           0x0400CC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_B_INT_MSK             0x0400D0	/* Audio Int interrupt mask */
+#define  AUD_B_INT_STAT            0x0400D4	/* Audio Int interrupt status */
+#define  AUD_B_INT_MSTAT           0x0400D8	/* Audio Int interrupt masked status */
+#define  AUD_B_INT_SSTAT           0x0400DC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_C_INT_MSK             0x0400E0	/* Audio Int interrupt mask */
+#define  AUD_C_INT_STAT            0x0400E4	/* Audio Int interrupt status */
+#define  AUD_C_INT_MSTAT           0x0400E8	/* Audio Int interrupt masked status */
+#define  AUD_C_INT_SSTAT           0x0400EC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_D_INT_MSK             0x0400F0	/* Audio Int interrupt mask */
+#define  AUD_D_INT_STAT            0x0400F4	/* Audio Int interrupt status */
+#define  AUD_D_INT_MSTAT           0x0400F8	/* Audio Int interrupt masked status */
+#define  AUD_D_INT_SSTAT           0x0400FC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_E_INT_MSK             0x040100	/* Audio Int interrupt mask */
+#define  AUD_E_INT_STAT            0x040104	/* Audio Int interrupt status */
+#define  AUD_E_INT_MSTAT           0x040108	/* Audio Int interrupt masked status */
+#define  AUD_E_INT_SSTAT           0x04010C	/* Audio Int interrupt set status */
+
+#define  FLD_AUD_SRC_OPC_ERR       0x00020000
+#define  FLD_AUD_DST_OPC_ERR       0x00010000
+#define  FLD_AUD_SRC_SYNC          0x00002000
+#define  FLD_AUD_DST_SYNC          0x00001000
+#define  FLD_AUD_SRC_OF            0x00000200
+#define  FLD_AUD_DST_OF            0x00000100
+#define  FLD_AUD_SRC_RISCI2        0x00000020
+#define  FLD_AUD_DST_RISCI2        0x00000010
+#define  FLD_AUD_SRC_RISCI1        0x00000002
+#define  FLD_AUD_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  MBIF_A_INT_MSK             0x040110	/* MBIF Int interrupt mask */
+#define  MBIF_A_INT_STAT            0x040114	/* MBIF Int interrupt status */
+#define  MBIF_A_INT_MSTAT           0x040118	/* MBIF Int interrupt masked status */
+#define  MBIF_A_INT_SSTAT           0x04011C	/* MBIF Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  MBIF_B_INT_MSK             0x040120	/* MBIF Int interrupt mask */
+#define  MBIF_B_INT_STAT            0x040124	/* MBIF Int interrupt status */
+#define  MBIF_B_INT_MSTAT           0x040128	/* MBIF Int interrupt masked status */
+#define  MBIF_B_INT_SSTAT           0x04012C	/* MBIF Int interrupt set status */
+
+#define  FLD_MBIF_DST_OPC_ERR       0x00010000
+#define  FLD_MBIF_DST_SYNC          0x00001000
+#define  FLD_MBIF_DST_OF            0x00000100
+#define  FLD_MBIF_DST_RISCI2        0x00000010
+#define  FLD_MBIF_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  AUD_EXT_INT_MSK           0x040060	/* Audio Ext interrupt mask */
+#define  AUD_EXT_INT_STAT          0x040064	/* Audio Ext interrupt status */
+#define  AUD_EXT_INT_MSTAT         0x040068	/* Audio Ext interrupt masked status */
+#define  AUD_EXT_INT_SSTAT         0x04006C	/* Audio Ext interrupt set status */
+#define  FLD_AUD_EXT_OPC_ERR       0x00010000
+#define  FLD_AUD_EXT_SYNC          0x00001000
+#define  FLD_AUD_EXT_OF            0x00000100
+#define  FLD_AUD_EXT_RISCI2        0x00000010
+#define  FLD_AUD_EXT_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  GPIO_LO                   0x110010	/* Lower  of GPIO pins [31:0] */
+#define  GPIO_HI                   0x110014	/* Upper WORD  of GPIO pins [47:31] */
+
+#define  GPIO_LO_OE                0x110018	/* Lower  of GPIO output enable [31:0] */
+#define  GPIO_HI_OE                0x11001C	/* Upper word  of GPIO output enable [47:32] */
+
+#define  GPIO_LO_INT_MSK           0x11003C	/* GPIO interrupt mask */
+#define  GPIO_LO_INT_STAT          0x110044	/* GPIO interrupt status */
+#define  GPIO_LO_INT_MSTAT         0x11004C	/* GPIO interrupt masked status */
+#define  GPIO_LO_ISM_SNS           0x110054	/* GPIO interrupt sensitivity */
+#define  GPIO_LO_ISM_POL           0x11005C	/* GPIO interrupt polarity */
+
+#define  GPIO_HI_INT_MSK           0x110040	/* GPIO interrupt mask */
+#define  GPIO_HI_INT_STAT          0x110048	/* GPIO interrupt status */
+#define  GPIO_HI_INT_MSTAT         0x110050	/* GPIO interrupt masked status */
+#define  GPIO_HI_ISM_SNS           0x110058	/* GPIO interrupt sensitivity */
+#define  GPIO_HI_ISM_POL           0x110060	/* GPIO interrupt polarity */
+
+#define  FLD_GPIO43_INT            (1 << 11)
+#define  FLD_GPIO42_INT            (1 << 10)
+#define  FLD_GPIO41_INT            (1 << 9)
+#define  FLD_GPIO40_INT            (1 << 8)
+
+#define  FLD_GPIO9_INT             (1 << 9)
+#define  FLD_GPIO8_INT             (1 << 8)
+#define  FLD_GPIO7_INT             (1 << 7)
+#define  FLD_GPIO6_INT             (1 << 6)
+#define  FLD_GPIO5_INT             (1 << 5)
+#define  FLD_GPIO4_INT             (1 << 4)
+#define  FLD_GPIO3_INT             (1 << 3)
+#define  FLD_GPIO2_INT             (1 << 2)
+#define  FLD_GPIO1_INT             (1 << 1)
+#define  FLD_GPIO0_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  TC_REQ                    0x040090	/* Rider PCI Express traFFic class request */
+
+/* ***************************************************************************** */
+#define  TC_REQ_SET                0x040094	/* Rider PCI Express traFFic class request set */
+
+/* ***************************************************************************** */
+/* Rider */
+/* ***************************************************************************** */
+
+/* PCI Compatible Header */
+/* ***************************************************************************** */
+#define  RDR_CFG0                  0x050000
+#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000
+
+/* ***************************************************************************** */
+#define  RDR_CFG1                  0x050004
+
+/* ***************************************************************************** */
+#define  RDR_CFG2                  0x050008
+
+/* ***************************************************************************** */
+#define  RDR_CFG3                  0x05000C
+
+/* ***************************************************************************** */
+#define  RDR_CFG4                  0x050010
+
+/* ***************************************************************************** */
+#define  RDR_CFG5                  0x050014
+
+/* ***************************************************************************** */
+#define  RDR_CFG6                  0x050018
+
+/* ***************************************************************************** */
+#define  RDR_CFG7                  0x05001C
+
+/* ***************************************************************************** */
+#define  RDR_CFG8                  0x050020
+
+/* ***************************************************************************** */
+#define  RDR_CFG9                  0x050024
+
+/* ***************************************************************************** */
+#define  RDR_CFGA                  0x050028
+
+/* ***************************************************************************** */
+#define  RDR_CFGB                  0x05002C
+#define  RDR_SUSSYSTEM_ID_CFG      0x05002C
+
+/* ***************************************************************************** */
+#define  RDR_CFGC                  0x050030
+
+/* ***************************************************************************** */
+#define  RDR_CFGD                  0x050034
+
+/* ***************************************************************************** */
+#define  RDR_CFGE                  0x050038
+
+/* ***************************************************************************** */
+#define  RDR_CFGF                  0x05003C
+
+/* ***************************************************************************** */
+/* PCI-Express Capabilities */
+/* ***************************************************************************** */
+#define  RDR_PECAP                 0x050040
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVCAP              0x050044
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVSC               0x050048
+
+/* ***************************************************************************** */
+#define  RDR_PELINKCAP             0x05004C
+
+/* ***************************************************************************** */
+#define  RDR_PELINKSC              0x050050
+
+/* ***************************************************************************** */
+#define  RDR_PMICAP                0x050080
+
+/* ***************************************************************************** */
+#define  RDR_PMCSR                 0x050084
+
+/* ***************************************************************************** */
+#define  RDR_VPDCAP                0x050090
+
+/* ***************************************************************************** */
+#define  RDR_VPDDATA               0x050094
+
+/* ***************************************************************************** */
+#define  RDR_MSICAP                0x0500A0
+
+/* ***************************************************************************** */
+#define  RDR_MSIARL                0x0500A4
+
+/* ***************************************************************************** */
+#define  RDR_MSIARU                0x0500A8
+
+/* ***************************************************************************** */
+#define  RDR_MSIDATA               0x0500AC
+
+/* ***************************************************************************** */
+/* PCI Express Extended Capabilities */
+/* ***************************************************************************** */
+#define  RDR_AERXCAP               0x050100
+
+/* ***************************************************************************** */
+#define  RDR_AERUESTA              0x050104
+
+/* ***************************************************************************** */
+#define  RDR_AERUEMSK              0x050108
+
+/* ***************************************************************************** */
+#define  RDR_AERUESEV              0x05010C
+
+/* ***************************************************************************** */
+#define  RDR_AERCESTA              0x050110
+
+/* ***************************************************************************** */
+#define  RDR_AERCEMSK              0x050114
+
+/* ***************************************************************************** */
+#define  RDR_AERCC                 0x050118
+
+/* ***************************************************************************** */
+#define  RDR_AERHL0                0x05011C
+
+/* ***************************************************************************** */
+#define  RDR_AERHL1                0x050120
+
+/* ***************************************************************************** */
+#define  RDR_AERHL2                0x050124
+
+/* ***************************************************************************** */
+#define  RDR_AERHL3                0x050128
+
+/* ***************************************************************************** */
+#define  RDR_VCXCAP                0x050200
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP1                0x050204
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP2                0x050208
+
+/* ***************************************************************************** */
+#define  RDR_VCSC                  0x05020C
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CAP              0x050210
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CTRL             0x050214
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_STAT             0x050218
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CAP              0x05021C
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CTRL             0x050220
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_STAT             0x050224
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CAP              0x050228
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CTRL             0x05022C
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_STAT             0x050230
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CAP              0x050234
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CTRL             0x050238
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_STAT             0x05023C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB0                0x050240
+
+/* ***************************************************************************** */
+#define  RDR_VCARB1                0x050244
+
+/* ***************************************************************************** */
+#define  RDR_VCARB2                0x050248
+
+/* ***************************************************************************** */
+#define  RDR_VCARB3                0x05024C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB4                0x050250
+
+/* ***************************************************************************** */
+#define  RDR_VCARB5                0x050254
+
+/* ***************************************************************************** */
+#define  RDR_VCARB6                0x050258
+
+/* ***************************************************************************** */
+#define  RDR_VCARB7                0x05025C
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT0              0x050300
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT1              0x050304
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL0               0x050308
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL1               0x05030C
+
+/* ***************************************************************************** */
+/* Transaction Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_TLSTAT0               0x050310
+
+/* ***************************************************************************** */
+#define  RDR_TLSTAT1               0x050314
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL0                0x050318
+#define  FLD_CFG_UR_CPL_MODE       0x00000040
+#define  FLD_CFG_CORR_ERR_QUITE    0x00000020
+#define  FLD_CFG_RCB_CK_EN         0x00000010
+#define  FLD_CFG_BNDRY_CK_EN       0x00000008
+#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004
+#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002
+#define  FLD_CFG_TAG_ORDER_EN      0x00000001
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL1                0x05031C
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAL               0x050320
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAU               0x050324
+
+/* ***************************************************************************** */
+#define  RDR_REQEPA                0x050328
+
+/* ***************************************************************************** */
+#define  RDR_REQCTRL               0x05032C
+
+/* ***************************************************************************** */
+#define  RDR_REQSTAT               0x050330
+
+/* ***************************************************************************** */
+#define  RDR_TL_TEST               0x050334
+
+/* ***************************************************************************** */
+#define  RDR_VCR01_CTL             0x050348
+
+/* ***************************************************************************** */
+#define  RDR_VCR23_CTL             0x05034C
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR0_FC            0x050350
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR1_FC            0x050354
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR2_FC            0x050358
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR3_FC            0x05035C
+
+/* ***************************************************************************** */
+/* Data Link Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_DLLSTAT               0x050360
+
+/* ***************************************************************************** */
+#define  RDR_DLLCTRL               0x050364
+
+/* ***************************************************************************** */
+#define  RDR_REPLAYTO              0x050368
+
+/* ***************************************************************************** */
+#define  RDR_ACKLATTO              0x05036C
+
+/* ***************************************************************************** */
+/* MAC Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_MACSTAT0              0x050380
+
+/* ***************************************************************************** */
+#define  RDR_MACSTAT1              0x050384
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL0              0x050388
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL1              0x05038C
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL2              0x050390
+
+/* ***************************************************************************** */
+#define  RDR_MAC_LB_DATA           0x050394
+
+/* ***************************************************************************** */
+#define  RDR_L0S_EXIT_LAT          0x050398
+
+/* ***************************************************************************** */
+/* DMAC */
+/* ***************************************************************************** */
+#define  DMA1_PTR1                 0x100000	/* DMA Current Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR1                 0x100004	/* DMA Current Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR1                 0x100008	/* DMA Current Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR1                 0x10000C	/* DMA Current Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR1                 0x100010	/* DMA Current Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR1                 0x100014	/* DMA Current Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR1                 0x100018	/* DMA Current Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR1                 0x10001C	/* DMA Current Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR1                 0x100020	/* DMA Current Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR1                0x100024	/* DMA Current Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR1                0x100028	/* DMA Current Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR1                0x10002C	/* DMA Current Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR1                0x100030	/* DMA Current Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR1                0x100034	/* DMA Current Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR1                0x100038	/* DMA Current Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR1                0x10003C	/* DMA Current Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR1                0x100040	/* DMA Current Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR1                0x100044	/* DMA Current Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR1                0x100048	/* DMA Current Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR1                0x10004C	/* DMA Current Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR1                0x100050	/* DMA Current Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR1                0x100054	/* DMA Current Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR1                0x100058	/* DMA Current Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR1                0x10005C	/* DMA Current Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR1                0x100060	/* DMA Current Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR1                0x100064	/* DMA Current Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_PTR2                 0x100080	/* DMA Tab Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR2                 0x100084	/* DMA Tab Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR2                 0x100088	/* DMA Tab Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR2                 0x10008C	/* DMA Tab Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR2                 0x100090	/* DMA Tab Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR2                 0x100094	/* DMA Tab Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR2                 0x100098	/* DMA Tab Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR2                 0x10009C	/* DMA Tab Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR2                 0x1000A0	/* DMA Tab Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR2                0x1000A4	/* DMA Tab Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR2                0x1000A8	/* DMA Tab Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR2                0x1000AC	/* DMA Tab Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR2                0x1000B0	/* DMA Tab Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR2                0x1000B4	/* DMA Tab Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR2                0x1000B8	/* DMA Tab Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR2                0x1000BC	/* DMA Tab Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR2                0x1000C0	/* DMA Tab Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR2                0x1000C4	/* DMA Tab Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR2                0x1000C8	/* DMA Tab Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR2                0x1000CC	/* DMA Tab Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR2                0x1000D0	/* DMA Tab Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR2                0x1000D4	/* DMA Tab Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR2                0x1000D8	/* DMA Tab Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR2                0x1000DC	/* DMA Tab Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR2                0x1000E0	/* DMA Tab Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR2                0x1000E4	/* DMA Tab Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT1                 0x100100	/* DMA BuFFer Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT1                 0x100104	/* DMA BuFFer Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT1                 0x100108	/* DMA BuFFer Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT1                 0x10010C	/* DMA BuFFer Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT1                 0x100110	/* DMA BuFFer Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT1                 0x100114	/* DMA BuFFer Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT1                 0x100118	/* DMA BuFFer Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT1                 0x10011C	/* DMA BuFFer Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT1                 0x100120	/* DMA BuFFer Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT1                0x100124	/* DMA BuFFer Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT1                0x100128	/* DMA BuFFer Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT1                0x10012C	/* DMA BuFFer Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT1                0x100130	/* DMA BuFFer Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT1                0x100134	/* DMA BuFFer Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT1                0x100138	/* DMA BuFFer Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT1                0x10013C	/* DMA BuFFer Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT1                0x100140	/* DMA BuFFer Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT1                0x100144	/* DMA BuFFer Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT1                0x100148	/* DMA BuFFer Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT1                0x10014C	/* DMA BuFFer Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT1                0x100150	/* DMA BuFFer Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT1                0x100154	/* DMA BuFFer Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT1                0x100158	/* DMA BuFFer Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT1                0x10015C	/* DMA BuFFer Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT1                0x100160	/* DMA BuFFer Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT1                0x100164	/* DMA BuFFer Size : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT2                 0x100180	/* DMA Table Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT2                 0x100184	/* DMA Table Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT2                 0x100188	/* DMA Table Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT2                 0x10018C	/* DMA Table Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT2                 0x100190	/* DMA Table Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT2                 0x100194	/* DMA Table Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT2                 0x100198	/* DMA Table Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT2                 0x10019C	/* DMA Table Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT2                 0x1001A0	/* DMA Table Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT2                0x1001A4	/* DMA Table Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT2                0x1001A8	/* DMA Table Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT2                0x1001AC	/* DMA Table Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT2                0x1001B0	/* DMA Table Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT2                0x1001B4	/* DMA Table Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT2                0x1001B8	/* DMA Table Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT2                0x1001BC	/* DMA Table Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT2                0x1001C0	/* DMA Table Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT2                0x1001C4	/* DMA Table Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT2                0x1001C8	/* DMA Table Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT2                0x1001CC	/* DMA Table Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT2                0x1001D0	/* DMA Table Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT2                0x1001D4	/* DMA Table Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT2                0x1001D8	/* DMA Table Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT2                0x1001DC	/* DMA Table Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT2                0x1001E0	/* DMA Table Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT2                0x1001E4	/* DMA Table Size : Ch#26 */
+
+/* ***************************************************************************** */
+ /* ITG */
+/* ***************************************************************************** */
+#define  TM_CNT_LDW                0x110000	/* Timer : Counter low */
+
+/* ***************************************************************************** */
+#define  TM_CNT_UW                 0x110004	/* Timer : Counter high word */
+
+/* ***************************************************************************** */
+#define  TM_LMT_LDW                0x110008	/* Timer : Limit low */
+
+/* ***************************************************************************** */
+#define  TM_LMT_UW                 0x11000C	/* Timer : Limit high word */
+
+/* ***************************************************************************** */
+#define  GP0_IO                    0x110010	/* GPIO output enables data I/O */
+#define  FLD_GP_OE                 0x00FF0000	/* GPIO: GP_OE output enable */
+#define  FLD_GP_IN                 0x0000FF00	/* GPIO: GP_IN status */
+#define  FLD_GP_OUT                0x000000FF	/* GPIO: GP_OUT control */
+
+/* ***************************************************************************** */
+#define  GPIO_ISM                  0x110014	/* GPIO interrupt sensitivity mode */
+#define  FLD_GP_ISM_SNS            0x00000070
+#define  FLD_GP_ISM_POL            0x00000007
+
+/* ***************************************************************************** */
+#define  SOFT_RESET                0x11001C	/* Output system reset reg */
+#define  FLD_PECOS_SOFT_RESET      0x00000001
+
+/* ***************************************************************************** */
+#define  MC416_RWD                 0x110020	/* MC416 GPIO[18:3] pin */
+#define  MC416_OEN                 0x110024	/* Output enable of GPIO[18:3] */
+#define  MC416_CTL                 0x110028
+
+/* ***************************************************************************** */
+#define  ALT_PIN_OUT_SEL           0x11002C	/* Alternate GPIO output select */
+
+#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000
+/* 0          Disabled <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+/* 8          ATT_IF */
+
+#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000
+/* 0          AUX_PLL_CLK<-- default */
+/* 1          GPIO[2] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_TX_ALT_SEL         0x00F00000
+/* 0          IR_TX <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_RX_ALT_SEL         0x000F0000
+/* 0          IR_RX <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO10_ALT_SEL        0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO2_ALT_SEL         0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO1_ALT_SEL         0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO0_ALT_SEL         0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  ALT_PIN_IN_SEL            0x110030	/* Alternate GPIO input select */
+
+#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+/* 5          GPIO[0] */
+/* 6          GPIO[1] */
+/* 7          GPIO[2] */
+
+#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL1             0x110040	/* Test bus control register #1 */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL2             0x110044	/* Test bus control register #2 */
+
+/* ***************************************************************************** */
+#define  CLK_DELAY                 0x110048	/* Clock delay */
+#define  FLD_MOE_CLK_DIS           0x80000000	/* Disable MoE clock */
+
+/* ***************************************************************************** */
+#define  PAD_CTRL                  0x110068	/* Pad drive strength control */
+
+/* ***************************************************************************** */
+#define  MBIST_CTRL                0x110050	/* SRAM memory built-in self test control */
+
+/* ***************************************************************************** */
+#define  MBIST_STAT                0x110054	/* SRAM memory built-in self test status */
+
+/* ***************************************************************************** */
+/* PLL registers */
+/* ***************************************************************************** */
+#define  PLL_A_INT_FRAC            0x110088
+#define  PLL_A_POST_STAT_BIST      0x11008C
+#define  PLL_B_INT_FRAC            0x110090
+#define  PLL_B_POST_STAT_BIST      0x110094
+#define  PLL_C_INT_FRAC            0x110098
+#define  PLL_C_POST_STAT_BIST      0x11009C
+#define  PLL_D_INT_FRAC            0x1100A0
+#define  PLL_D_POST_STAT_BIST      0x1100A4
+
+#define  CLK_RST                   0x11002C
+#define  FLD_VID_I_CLK_NOE         0x00001000
+#define  FLD_VID_J_CLK_NOE         0x00002000
+#define  FLD_USE_ALT_PLL_REF       0x00004000
+
+#define  VID_CH_MODE_SEL           0x110078
+#define  VID_CH_CLK_SEL            0x11007C
+
+/* ***************************************************************************** */
+#define  VBI_A_DMA                 0x130008	/* VBI A DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_A_VIP_CTL             0x130080	/* Video A VIP format control */
+#define  FLD_VIP_MODE              0x00000001
+
+/* ***************************************************************************** */
+#define  VID_A_PIXEL_FRMT          0x130084	/* Video A pixel format */
+#define  FLD_VID_A_GAMMA_DIS       0x00000008
+#define  FLD_VID_A_FORMAT          0x00000007
+#define  FLD_VID_A_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_A_VBI_CTL             0x130088	/* Video A VBI miscellaneous control */
+#define  FLD_VID_A_VIP_EXT         0x00000003
+
+/* ***************************************************************************** */
+#define  VID_B_DMA                 0x130100	/* Video B DMA data port */
+
+/* ***************************************************************************** */
+#define  VBI_B_DMA                 0x130108	/* VBI B DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_B_SRC_SEL             0x130144	/* Video B source select */
+#define  FLD_VID_B_SRC_SEL         0x00000000
+
+/* ***************************************************************************** */
+#define  VID_B_LNGTH               0x130150	/* Video B line length */
+#define  FLD_VID_B_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+#define  VID_B_VIP_CTL             0x130180	/* Video B VIP format control */
+
+/* ***************************************************************************** */
+#define  VID_B_PIXEL_FRMT          0x130184	/* Video B pixel format */
+#define  FLD_VID_B_GAMMA_DIS       0x00000008
+#define  FLD_VID_B_FORMAT          0x00000007
+#define  FLD_VID_B_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_C_DMA                 0x130200	/* Video C DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_C_LNGTH               0x130250	/* Video C line length */
+#define  FLD_VID_C_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+/* Video Destination Channels */
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT           0x130020	/* Video A general purpose counter */
+#define  VID_DST_B_GPCNT           0x130120	/* Video B general purpose counter */
+#define  VID_DST_C_GPCNT           0x130220	/* Video C general purpose counter */
+#define  VID_DST_D_GPCNT           0x130320	/* Video D general purpose counter */
+#define  VID_DST_E_GPCNT           0x130420	/* Video E general purpose counter */
+#define  VID_DST_F_GPCNT           0x130520	/* Video F general purpose counter */
+#define  VID_DST_G_GPCNT           0x130620	/* Video G general purpose counter */
+#define  VID_DST_H_GPCNT           0x130720	/* Video H general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT_CTL       0x130030	/* Video A general purpose control */
+#define  VID_DST_B_GPCNT_CTL       0x130130	/* Video B general purpose control */
+#define  VID_DST_C_GPCNT_CTL       0x130230	/* Video C general purpose control */
+#define  VID_DST_D_GPCNT_CTL       0x130330	/* Video D general purpose control */
+#define  VID_DST_E_GPCNT_CTL       0x130430	/* Video E general purpose control */
+#define  VID_DST_F_GPCNT_CTL       0x130530	/* Video F general purpose control */
+#define  VID_DST_G_GPCNT_CTL       0x130630	/* Video G general purpose control */
+#define  VID_DST_H_GPCNT_CTL       0x130730	/* Video H general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_DMA_CTL         0x130040	/* Video A DMA control */
+#define  VID_DST_B_DMA_CTL         0x130140	/* Video B DMA control */
+#define  VID_DST_C_DMA_CTL         0x130240	/* Video C DMA control */
+#define  VID_DST_D_DMA_CTL         0x130340	/* Video D DMA control */
+#define  VID_DST_E_DMA_CTL         0x130440	/* Video E DMA control */
+#define  VID_DST_F_DMA_CTL         0x130540	/* Video F DMA control */
+#define  VID_DST_G_DMA_CTL         0x130640	/* Video G DMA control */
+#define  VID_DST_H_DMA_CTL         0x130740	/* Video H DMA control */
+
+#define  FLD_VID_RISC_EN           0x00000010
+#define  FLD_VID_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_VIP_CTL         0x130080	/* Video A VIP control */
+#define  VID_DST_B_VIP_CTL         0x130180	/* Video B VIP control */
+#define  VID_DST_C_VIP_CTL         0x130280	/* Video C VIP control */
+#define  VID_DST_D_VIP_CTL         0x130380	/* Video D VIP control */
+#define  VID_DST_E_VIP_CTL         0x130480	/* Video E VIP control */
+#define  VID_DST_F_VIP_CTL         0x130580	/* Video F VIP control */
+#define  VID_DST_G_VIP_CTL         0x130680	/* Video G VIP control */
+#define  VID_DST_H_VIP_CTL         0x130780	/* Video H VIP control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_PIX_FRMT        0x130084	/* Video A Pixel format */
+#define  VID_DST_B_PIX_FRMT        0x130184	/* Video B Pixel format */
+#define  VID_DST_C_PIX_FRMT        0x130284	/* Video C Pixel format */
+#define  VID_DST_D_PIX_FRMT        0x130384	/* Video D Pixel format */
+#define  VID_DST_E_PIX_FRMT        0x130484	/* Video E Pixel format */
+#define  VID_DST_F_PIX_FRMT        0x130584	/* Video F Pixel format */
+#define  VID_DST_G_PIX_FRMT        0x130684	/* Video G Pixel format */
+#define  VID_DST_H_PIX_FRMT        0x130784	/* Video H Pixel format */
+
+/* ***************************************************************************** */
+/* Video Source Channels */
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT_CTL       0x130804	/* Video A general purpose control */
+#define  VID_SRC_B_GPCNT_CTL       0x130904	/* Video B general purpose control */
+#define  VID_SRC_C_GPCNT_CTL       0x130A04	/* Video C general purpose control */
+#define  VID_SRC_D_GPCNT_CTL       0x130B04	/* Video D general purpose control */
+#define  VID_SRC_E_GPCNT_CTL       0x130C04	/* Video E general purpose control */
+#define  VID_SRC_F_GPCNT_CTL       0x130D04	/* Video F general purpose control */
+#define  VID_SRC_I_GPCNT_CTL       0x130E04	/* Video I general purpose control */
+#define  VID_SRC_J_GPCNT_CTL       0x130F04	/* Video J general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT           0x130808	/* Video A general purpose counter */
+#define  VID_SRC_B_GPCNT           0x130908	/* Video B general purpose counter */
+#define  VID_SRC_C_GPCNT           0x130A08	/* Video C general purpose counter */
+#define  VID_SRC_D_GPCNT           0x130B08	/* Video D general purpose counter */
+#define  VID_SRC_E_GPCNT           0x130C08	/* Video E general purpose counter */
+#define  VID_SRC_F_GPCNT           0x130D08	/* Video F general purpose counter */
+#define  VID_SRC_I_GPCNT           0x130E08	/* Video I general purpose counter */
+#define  VID_SRC_J_GPCNT           0x130F08	/* Video J general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_DMA_CTL         0x13080C	/* Video A DMA control */
+#define  VID_SRC_B_DMA_CTL         0x13090C	/* Video B DMA control */
+#define  VID_SRC_C_DMA_CTL         0x130A0C	/* Video C DMA control */
+#define  VID_SRC_D_DMA_CTL         0x130B0C	/* Video D DMA control */
+#define  VID_SRC_E_DMA_CTL         0x130C0C	/* Video E DMA control */
+#define  VID_SRC_F_DMA_CTL         0x130D0C	/* Video F DMA control */
+#define  VID_SRC_I_DMA_CTL         0x130E0C	/* Video I DMA control */
+#define  VID_SRC_J_DMA_CTL         0x130F0C	/* Video J DMA control */
+
+#define  FLD_APB_RISC_EN           0x00000010
+#define  FLD_APB_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_FMT_CTL         0x130810	/* Video A format control */
+#define  VID_SRC_B_FMT_CTL         0x130910	/* Video B format control */
+#define  VID_SRC_C_FMT_CTL         0x130A10	/* Video C format control */
+#define  VID_SRC_D_FMT_CTL         0x130B10	/* Video D format control */
+#define  VID_SRC_E_FMT_CTL         0x130C10	/* Video E format control */
+#define  VID_SRC_F_FMT_CTL         0x130D10	/* Video F format control */
+#define  VID_SRC_I_FMT_CTL         0x130E10	/* Video I format control */
+#define  VID_SRC_J_FMT_CTL         0x130F10	/* Video J format control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL1     0x130814	/* Video A active control      1 */
+#define  VID_SRC_B_ACTIVE_CTL1     0x130914	/* Video B active control      1 */
+#define  VID_SRC_C_ACTIVE_CTL1     0x130A14	/* Video C active control      1 */
+#define  VID_SRC_D_ACTIVE_CTL1     0x130B14	/* Video D active control      1 */
+#define  VID_SRC_E_ACTIVE_CTL1     0x130C14	/* Video E active control      1 */
+#define  VID_SRC_F_ACTIVE_CTL1     0x130D14	/* Video F active control      1 */
+#define  VID_SRC_I_ACTIVE_CTL1     0x130E14	/* Video I active control      1 */
+#define  VID_SRC_J_ACTIVE_CTL1     0x130F14	/* Video J active control      1 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL2     0x130818	/* Video A active control      2 */
+#define  VID_SRC_B_ACTIVE_CTL2     0x130918	/* Video B active control      2 */
+#define  VID_SRC_C_ACTIVE_CTL2     0x130A18	/* Video C active control      2 */
+#define  VID_SRC_D_ACTIVE_CTL2     0x130B18	/* Video D active control      2 */
+#define  VID_SRC_E_ACTIVE_CTL2     0x130C18	/* Video E active control      2 */
+#define  VID_SRC_F_ACTIVE_CTL2     0x130D18	/* Video F active control      2 */
+#define  VID_SRC_I_ACTIVE_CTL2     0x130E18	/* Video I active control      2 */
+#define  VID_SRC_J_ACTIVE_CTL2     0x130F18	/* Video J active control      2 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_CDT_SZ          0x13081C	/* Video A CDT size */
+#define  VID_SRC_B_CDT_SZ          0x13091C	/* Video B CDT size */
+#define  VID_SRC_C_CDT_SZ          0x130A1C	/* Video C CDT size */
+#define  VID_SRC_D_CDT_SZ          0x130B1C	/* Video D CDT size */
+#define  VID_SRC_E_CDT_SZ          0x130C1C	/* Video E CDT size */
+#define  VID_SRC_F_CDT_SZ          0x130D1C	/* Video F CDT size */
+#define  VID_SRC_I_CDT_SZ          0x130E1C	/* Video I CDT size */
+#define  VID_SRC_J_CDT_SZ          0x130F1C	/* Video J CDT size */
+
+/* ***************************************************************************** */
+/* Audio I/F */
+/* ***************************************************************************** */
+#define  AUD_DST_A_DMA             0x140000	/* Audio Int A DMA data port */
+#define  AUD_SRC_A_DMA             0x140008	/* Audio Int A DMA data port */
+
+#define  AUD_A_GPCNT               0x140010	/* Audio Int A gp counter */
+#define  FLD_AUD_A_GP_CNT          0x0000FFFF
+
+#define  AUD_A_GPCNT_CTL           0x140014	/* Audio Int A gp control */
+
+#define  AUD_A_LNGTH               0x140018	/* Audio Int A line length */
+
+#define  AUD_A_CFG                 0x14001C	/* Audio Int A configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_B_DMA             0x140100	/* Audio Int B DMA data port */
+#define  AUD_SRC_B_DMA             0x140108	/* Audio Int B DMA data port */
+
+#define  AUD_B_GPCNT               0x140110	/* Audio Int B gp counter */
+#define  FLD_AUD_B_GP_CNT          0x0000FFFF
+
+#define  AUD_B_GPCNT_CTL           0x140114	/* Audio Int B gp control */
+
+#define  AUD_B_LNGTH               0x140118	/* Audio Int B line length */
+
+#define  AUD_B_CFG                 0x14011C	/* Audio Int B configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_C_DMA             0x140200	/* Audio Int C DMA data port */
+#define  AUD_SRC_C_DMA             0x140208	/* Audio Int C DMA data port */
+
+#define  AUD_C_GPCNT               0x140210	/* Audio Int C gp counter */
+#define  FLD_AUD_C_GP_CNT          0x0000FFFF
+
+#define  AUD_C_GPCNT_CTL           0x140214	/* Audio Int C gp control */
+
+#define  AUD_C_LNGTH               0x140218	/* Audio Int C line length */
+
+#define  AUD_C_CFG                 0x14021C	/* Audio Int C configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_D_DMA             0x140300	/* Audio Int D DMA data port */
+#define  AUD_SRC_D_DMA             0x140308	/* Audio Int D DMA data port */
+
+#define  AUD_D_GPCNT               0x140310	/* Audio Int D gp counter */
+#define  FLD_AUD_D_GP_CNT          0x0000FFFF
+
+#define  AUD_D_GPCNT_CTL           0x140314	/* Audio Int D gp control */
+
+#define  AUD_D_LNGTH               0x140318	/* Audio Int D line length */
+
+#define  AUD_D_CFG                 0x14031C	/* Audio Int D configuration */
+
+/* ***************************************************************************** */
+#define  AUD_SRC_E_DMA             0x140400	/* Audio Int E DMA data port */
+
+#define  AUD_E_GPCNT               0x140410	/* Audio Int E gp counter */
+#define  FLD_AUD_E_GP_CNT          0x0000FFFF
+
+#define  AUD_E_GPCNT_CTL           0x140414	/* Audio Int E gp control */
+
+#define  AUD_E_CFG                 0x14041C	/* Audio Int E configuration */
+
+/* ***************************************************************************** */
+
+#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF
+
+#define  FLD_AUD_DST_PK_MODE       0x00004000
+
+#define  FLD_AUD_CLK_ENABLE        0x00000200
+
+#define  FLD_AUD_MASTER_MODE       0x00000002
+
+#define  FLD_AUD_SONY_MODE         0x00000001
+
+#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800
+
+#define  FLD_AUD_DST_ENABLE        0x00020000
+
+#define  FLD_AUD_SRC_ENABLE        0x00010000
+
+/* ***************************************************************************** */
+#define  AUD_INT_DMA_CTL           0x140500	/* Audio Int DMA control */
+
+#define  FLD_AUD_SRC_E_RISC_EN     0x00008000
+#define  FLD_AUD_SRC_C_RISC_EN     0x00004000
+#define  FLD_AUD_SRC_B_RISC_EN     0x00002000
+#define  FLD_AUD_SRC_A_RISC_EN     0x00001000
+
+#define  FLD_AUD_DST_D_RISC_EN     0x00000800
+#define  FLD_AUD_DST_C_RISC_EN     0x00000400
+#define  FLD_AUD_DST_B_RISC_EN     0x00000200
+#define  FLD_AUD_DST_A_RISC_EN     0x00000100
+
+#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080
+#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040
+#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020
+#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010
+
+#define  FLD_AUD_DST_D_FIFO_EN     0x00000008
+#define  FLD_AUD_DST_C_FIFO_EN     0x00000004
+#define  FLD_AUD_DST_B_FIFO_EN     0x00000002
+#define  FLD_AUD_DST_A_FIFO_EN     0x00000001
+
+/* ***************************************************************************** */
+/*  */
+/* Mobilygen Interface Registers */
+/*  */
+/* ***************************************************************************** */
+/* Mobilygen Interface A */
+/* ***************************************************************************** */
+#define  MB_IF_A_DMA               0x150000	/* MBIF A DMA data port */
+#define  MB_IF_A_GPCN              0x150008	/* MBIF A GP counter */
+#define  MB_IF_A_GPCN_CTRL         0x15000C
+#define  MB_IF_A_DMA_CTRL          0x150010
+#define  MB_IF_A_LENGTH            0x150014
+#define  MB_IF_A_HDMA_XFER_SZ      0x150018
+#define  MB_IF_A_HCMD              0x15001C
+#define  MB_IF_A_HCONFIG           0x150020
+#define  MB_IF_A_DATA_STRUCT_0     0x150024
+#define  MB_IF_A_DATA_STRUCT_1     0x150028
+#define  MB_IF_A_DATA_STRUCT_2     0x15002C
+#define  MB_IF_A_DATA_STRUCT_3     0x150030
+#define  MB_IF_A_DATA_STRUCT_4     0x150034
+#define  MB_IF_A_DATA_STRUCT_5     0x150038
+#define  MB_IF_A_DATA_STRUCT_6     0x15003C
+#define  MB_IF_A_DATA_STRUCT_7     0x150040
+#define  MB_IF_A_DATA_STRUCT_8     0x150044
+#define  MB_IF_A_DATA_STRUCT_9     0x150048
+#define  MB_IF_A_DATA_STRUCT_A     0x15004C
+#define  MB_IF_A_DATA_STRUCT_B     0x150050
+#define  MB_IF_A_DATA_STRUCT_C     0x150054
+#define  MB_IF_A_DATA_STRUCT_D     0x150058
+#define  MB_IF_A_DATA_STRUCT_E     0x15005C
+#define  MB_IF_A_DATA_STRUCT_F     0x150060
+/* ***************************************************************************** */
+/* Mobilygen Interface B */
+/* ***************************************************************************** */
+#define  MB_IF_B_DMA               0x160000	/* MBIF A DMA data port */
+#define  MB_IF_B_GPCN              0x160008	/* MBIF A GP counter */
+#define  MB_IF_B_GPCN_CTRL         0x16000C
+#define  MB_IF_B_DMA_CTRL          0x160010
+#define  MB_IF_B_LENGTH            0x160014
+#define  MB_IF_B_HDMA_XFER_SZ      0x160018
+#define  MB_IF_B_HCMD              0x16001C
+#define  MB_IF_B_HCONFIG           0x160020
+#define  MB_IF_B_DATA_STRUCT_0     0x160024
+#define  MB_IF_B_DATA_STRUCT_1     0x160028
+#define  MB_IF_B_DATA_STRUCT_2     0x16002C
+#define  MB_IF_B_DATA_STRUCT_3     0x160030
+#define  MB_IF_B_DATA_STRUCT_4     0x160034
+#define  MB_IF_B_DATA_STRUCT_5     0x160038
+#define  MB_IF_B_DATA_STRUCT_6     0x16003C
+#define  MB_IF_B_DATA_STRUCT_7     0x160040
+#define  MB_IF_B_DATA_STRUCT_8     0x160044
+#define  MB_IF_B_DATA_STRUCT_9     0x160048
+#define  MB_IF_B_DATA_STRUCT_A     0x16004C
+#define  MB_IF_B_DATA_STRUCT_B     0x160050
+#define  MB_IF_B_DATA_STRUCT_C     0x160054
+#define  MB_IF_B_DATA_STRUCT_D     0x160058
+#define  MB_IF_B_DATA_STRUCT_E     0x16005C
+#define  MB_IF_B_DATA_STRUCT_F     0x160060
+
+/* MB_DMA_CTRL */
+#define  FLD_MB_IF_RISC_EN         0x00000010
+#define  FLD_MB_IF_FIFO_EN         0x00000001
+
+/* MB_LENGTH */
+#define  FLD_MB_IF_LN_LNGTH        0x00000FFF
+
+/* MB_HCMD register */
+#define  FLD_MB_HCMD_H_GO          0x80000000
+#define  FLD_MB_HCMD_H_BUSY        0x40000000
+#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000
+#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000
+#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000
+#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000
+#define  FLD_MB_HCMD_H_RW_N        0x01000000
+#define  FLD_MB_HCMD_H_ADDR        0x00FF0000
+#define  FLD_MB_HCMD_H_DATA        0x0000FFFF
+
+/* ***************************************************************************** */
+/* I2C #1 */
+/* ***************************************************************************** */
+#define  I2C1_ADDR                 0x180000	/* I2C #1 address */
+#define  FLD_I2C_DADDR             0xfe000000	/* RW [31:25] I2C Device Address */
+						 /* RO [24] reserved */
+/* ***************************************************************************** */
+#define  FLD_I2C_SADDR             0x00FFFFFF	/* RW [23:0]  I2C Sub-address */
+
+/* ***************************************************************************** */
+#define  I2C1_WDATA                0x180004	/* I2C #1 write data */
+#define  FLD_I2C_WDATA             0xFFFFFFFF	/* RW [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_CTRL                 0x180008	/* I2C #1 control */
+#define  FLD_I2C_PERIOD            0xFF000000	/* RW [31:24] */
+#define  FLD_I2C_SCL_IN            0x00200000	/* RW [21] */
+#define  FLD_I2C_SDA_IN            0x00100000	/* RW [20] */
+						 /* RO [19:18] reserved */
+#define  FLD_I2C_SCL_OUT           0x00020000	/* RW [17] */
+#define  FLD_I2C_SDA_OUT           0x00010000	/* RW [16] */
+						 /* RO [15] reserved */
+#define  FLD_I2C_DATA_LEN          0x00007000	/* RW [14:12] */
+#define  FLD_I2C_SADDR_INC         0x00000800	/* RW [11] */
+						 /* RO [10:9] reserved */
+#define  FLD_I2C_SADDR_LEN         0x00000300	/* RW [9:8] */
+						 /* RO [7:6] reserved */
+#define  FLD_I2C_SOFT              0x00000020	/* RW [5] */
+#define  FLD_I2C_NOSTOP            0x00000010	/* RW [4] */
+#define  FLD_I2C_EXTEND            0x00000008	/* RW [3] */
+#define  FLD_I2C_SYNC              0x00000004	/* RW [2] */
+#define  FLD_I2C_READ_SA           0x00000002	/* RW [1] */
+#define  FLD_I2C_READ_WRN          0x00000001	/* RW [0] */
+
+/* ***************************************************************************** */
+#define  I2C1_RDATA                0x18000C	/* I2C #1 read data */
+#define  FLD_I2C_RDATA             0xFFFFFFFF	/* RO [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_STAT                 0x180010	/* I2C #1 status */
+#define  FLD_I2C_XFER_IN_PROG      0x00000002	/* RO [1] */
+#define  FLD_I2C_RACK              0x00000001	/* RO [0] */
+
+/* ***************************************************************************** */
+/* I2C #2 */
+/* ***************************************************************************** */
+#define  I2C2_ADDR                 0x190000	/* I2C #2 address */
+
+/* ***************************************************************************** */
+#define  I2C2_WDATA                0x190004	/* I2C #2 write data */
+
+/* ***************************************************************************** */
+#define  I2C2_CTRL                 0x190008	/* I2C #2 control */
+
+/* ***************************************************************************** */
+#define  I2C2_RDATA                0x19000C	/* I2C #2 read data */
+
+/* ***************************************************************************** */
+#define  I2C2_STAT                 0x190010	/* I2C #2 status */
+
+/* ***************************************************************************** */
+/* I2C #3 */
+/* ***************************************************************************** */
+#define  I2C3_ADDR                 0x1A0000	/* I2C #3 address */
+
+/* ***************************************************************************** */
+#define  I2C3_WDATA                0x1A0004	/* I2C #3 write data */
+
+/* ***************************************************************************** */
+#define  I2C3_CTRL                 0x1A0008	/* I2C #3 control */
+
+/* ***************************************************************************** */
+#define  I2C3_RDATA                0x1A000C	/* I2C #3 read data */
+
+/* ***************************************************************************** */
+#define  I2C3_STAT                 0x1A0010	/* I2C #3 status */
+
+/* ***************************************************************************** */
+/* UART */
+/* ***************************************************************************** */
+#define  UART_CTL                  0x1B0000	/* UART Control Register */
+#define  FLD_LOOP_BACK_EN          (1 << 7)	/* RW field - default 0 */
+#define  FLD_RX_TRG_SZ             (3 << 2)	/* RW field - default 0 */
+#define  FLD_RX_EN                 (1 << 1)	/* RW field - default 0 */
+#define  FLD_TX_EN                 (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_BRD                  0x1B0004	/* UART Baud Rate Divisor */
+#define  FLD_BRD                   0x0000FFFF	/* RW field - default 0x197 */
+
+/* ***************************************************************************** */
+#define  UART_DBUF                 0x1B0008	/* UART Tx/Rx Data BuFFer */
+#define  FLD_DB                    0xFFFFFFFF	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_ISR                  0x1B000C	/* UART Interrupt Status */
+#define  FLD_RXD_TIMEOUT_EN        (1 << 7)	/* RW field - default 0 */
+#define  FLD_FRM_ERR_EN            (1 << 6)	/* RW field - default 0 */
+#define  FLD_RXD_RDY_EN            (1 << 5)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY_EN          (1 << 4)	/* RW field - default 0 */
+#define  FLD_RXD_OVERFLOW          (1 << 3)	/* RW field - default 0 */
+#define  FLD_FRM_ERR               (1 << 2)	/* RW field - default 0 */
+#define  FLD_RXD_RDY               (1 << 1)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY             (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_CNT                  0x1B0010	/* UART Tx/Rx FIFO Byte Count */
+#define  FLD_TXD_CNT               (0x1F << 8)	/* RW field - default 0 */
+#define  FLD_RXD_CNT               (0x1F << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+/* Motion Detection */
+#define  MD_CH0_GRID_BLOCK_YCNT    0x170014
+#define  MD_CH1_GRID_BLOCK_YCNT    0x170094
+#define  MD_CH2_GRID_BLOCK_YCNT    0x170114
+#define  MD_CH3_GRID_BLOCK_YCNT    0x170194
+#define  MD_CH4_GRID_BLOCK_YCNT    0x170214
+#define  MD_CH5_GRID_BLOCK_YCNT    0x170294
+#define  MD_CH6_GRID_BLOCK_YCNT    0x170314
+#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
+
+#define PIXEL_FRMT_422    4
+#define PIXEL_FRMT_411    5
+#define PIXEL_FRMT_Y8     6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif /* Athena_REGISTERS */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-sram.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-sram.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-sram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-sram.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,261 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+/* #define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM */
+#define VID_CMDS_SIZE             80	/* Video CMDS size in bytes */
+#define AUDIO_CMDS_SIZE           80	/* AUDIO CMDS size in bytes */
+#define MBIF_CMDS_SIZE            80	/* MBIF  CMDS size in bytes */
+
+/* #define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers */
+#define VID_IQ_SIZE               64	/* VID instruction queue size in bytes */
+#define MBIF_IQ_SIZE              64
+#define AUDIO_IQ_SIZE             64	/* AUD instruction queue size in bytes */
+
+#define VID_CDT_SIZE              64	/* VID cluster descriptor table size in bytes */
+#define MBIF_CDT_SIZE             64	/* MBIF/HBI cluster descriptor table size in bytes */
+#define AUDIO_CDT_SIZE            48	/* AUD cluster descriptor table size in bytes */
+
+/* #define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM */
+/* #define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM */
+
+/* #define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM */
+/* #define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora */
+
+#define VID_CLUSTER_SIZE          1440	/* VID cluster data line */
+#define AUDIO_CLUSTER_SIZE        128	/* AUDIO cluster data line */
+#define MBIF_CLUSTER_SIZE         1440	/* MBIF/HBI cluster data line */
+
+/* #define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM */
+/* #define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM */
+
+/* Receive SRAM */
+#define RX_SRAM_START             0x10000
+#define VID_A_DOWN_CMDS           0x10000
+#define VID_B_DOWN_CMDS           0x10050
+#define VID_C_DOWN_CMDS           0x100A0
+#define VID_D_DOWN_CMDS           0x100F0
+#define VID_E_DOWN_CMDS           0x10140
+#define VID_F_DOWN_CMDS           0x10190
+#define VID_G_DOWN_CMDS           0x101E0
+#define VID_H_DOWN_CMDS           0x10230
+#define VID_A_UP_CMDS             0x10280
+#define VID_B_UP_CMDS             0x102D0
+#define VID_C_UP_CMDS             0x10320
+#define VID_D_UP_CMDS             0x10370
+#define VID_E_UP_CMDS             0x103C0
+#define VID_F_UP_CMDS             0x10410
+#define VID_I_UP_CMDS             0x10460
+#define VID_J_UP_CMDS             0x104B0
+#define AUD_A_DOWN_CMDS           0x10500
+#define AUD_B_DOWN_CMDS           0x10550
+#define AUD_C_DOWN_CMDS           0x105A0
+#define AUD_D_DOWN_CMDS           0x105F0
+#define AUD_A_UP_CMDS             0x10640
+#define AUD_B_UP_CMDS             0x10690
+#define AUD_C_UP_CMDS             0x106E0
+#define AUD_E_UP_CMDS             0x10730
+#define MBIF_A_DOWN_CMDS          0x10780
+#define MBIF_B_DOWN_CMDS          0x107D0
+#define DMA_SCRATCH_PAD           0x10820	/* Scratch pad area from 0x10820 to 0x10B40 */
+
+/* #define RX_SRAM_POOL_START        = 0x105B0; */
+
+#define VID_A_IQ                  0x11000
+#define VID_B_IQ                  0x11040
+#define VID_C_IQ                  0x11080
+#define VID_D_IQ                  0x110C0
+#define VID_E_IQ                  0x11100
+#define VID_F_IQ                  0x11140
+#define VID_G_IQ                  0x11180
+#define VID_H_IQ                  0x111C0
+#define VID_I_IQ                  0x11200
+#define VID_J_IQ                  0x11240
+#define AUD_A_IQ                  0x11280
+#define AUD_B_IQ                  0x112C0
+#define AUD_C_IQ                  0x11300
+#define AUD_D_IQ                  0x11340
+#define AUD_E_IQ                  0x11380
+#define MBIF_A_IQ                 0x11000
+#define MBIF_B_IQ                 0x110C0
+
+#define VID_A_CDT                 0x10C00
+#define VID_B_CDT                 0x10C40
+#define VID_C_CDT                 0x10C80
+#define VID_D_CDT                 0x10CC0
+#define VID_E_CDT                 0x10D00
+#define VID_F_CDT                 0x10D40
+#define VID_G_CDT                 0x10D80
+#define VID_H_CDT                 0x10DC0
+#define VID_I_CDT                 0x10E00
+#define VID_J_CDT                 0x10E40
+#define AUD_A_CDT                 0x10E80
+#define AUD_B_CDT                 0x10EB0
+#define AUD_C_CDT                 0x10EE0
+#define AUD_D_CDT                 0x10F10
+#define AUD_E_CDT                 0x10F40
+#define MBIF_A_CDT                0x10C00
+#define MBIF_B_CDT                0x10CC0
+
+/* Cluster Buffer for RX */
+#define VID_A_UP_CLUSTER_1        0x11400
+#define VID_A_UP_CLUSTER_2        0x119A0
+#define VID_A_UP_CLUSTER_3        0x11F40
+#define VID_A_UP_CLUSTER_4        0x124E0
+
+#define VID_B_UP_CLUSTER_1        0x12A80
+#define VID_B_UP_CLUSTER_2        0x13020
+#define VID_B_UP_CLUSTER_3        0x135C0
+#define VID_B_UP_CLUSTER_4        0x13B60
+
+#define VID_C_UP_CLUSTER_1        0x14100
+#define VID_C_UP_CLUSTER_2        0x146A0
+#define VID_C_UP_CLUSTER_3        0x14C40
+#define VID_C_UP_CLUSTER_4        0x151E0
+
+#define VID_D_UP_CLUSTER_1        0x15780
+#define VID_D_UP_CLUSTER_2        0x15D20
+#define VID_D_UP_CLUSTER_3        0x162C0
+#define VID_D_UP_CLUSTER_4        0x16860
+
+#define VID_E_UP_CLUSTER_1        0x16E00
+#define VID_E_UP_CLUSTER_2        0x173A0
+#define VID_E_UP_CLUSTER_3        0x17940
+#define VID_E_UP_CLUSTER_4        0x17EE0
+
+#define VID_F_UP_CLUSTER_1        0x18480
+#define VID_F_UP_CLUSTER_2        0x18A20
+#define VID_F_UP_CLUSTER_3        0x18FC0
+#define VID_F_UP_CLUSTER_4        0x19560
+
+#define VID_I_UP_CLUSTER_1        0x19B00
+#define VID_I_UP_CLUSTER_2        0x1A0A0
+#define VID_I_UP_CLUSTER_3        0x1A640
+#define VID_I_UP_CLUSTER_4        0x1ABE0
+
+#define VID_J_UP_CLUSTER_1        0x1B180
+#define VID_J_UP_CLUSTER_2        0x1B720
+#define VID_J_UP_CLUSTER_3        0x1BCC0
+#define VID_J_UP_CLUSTER_4        0x1C260
+
+#define AUD_A_UP_CLUSTER_1        0x1C800
+#define AUD_A_UP_CLUSTER_2        0x1C880
+#define AUD_A_UP_CLUSTER_3        0x1C900
+
+#define AUD_B_UP_CLUSTER_1        0x1C980
+#define AUD_B_UP_CLUSTER_2        0x1CA00
+#define AUD_B_UP_CLUSTER_3        0x1CA80
+
+#define AUD_C_UP_CLUSTER_1        0x1CB00
+#define AUD_C_UP_CLUSTER_2        0x1CB80
+#define AUD_C_UP_CLUSTER_3        0x1CC00
+
+#define AUD_E_UP_CLUSTER_1        0x1CC80
+#define AUD_E_UP_CLUSTER_2        0x1CD00
+#define AUD_E_UP_CLUSTER_3        0x1CD80
+
+#define RX_SRAM_POOL_FREE         0x1CE00
+#define RX_SRAM_END               0x1D000
+
+/* Free Receive SRAM    144 Bytes */
+
+/* Transmit SRAM */
+#define TX_SRAM_POOL_START        0x00000
+
+#define VID_A_DOWN_CLUSTER_1      0x00040
+#define VID_A_DOWN_CLUSTER_2      0x005E0
+#define VID_A_DOWN_CLUSTER_3      0x00B80
+#define VID_A_DOWN_CLUSTER_4      0x01120
+
+#define VID_B_DOWN_CLUSTER_1      0x016C0
+#define VID_B_DOWN_CLUSTER_2      0x01C60
+#define VID_B_DOWN_CLUSTER_3      0x02200
+#define VID_B_DOWN_CLUSTER_4      0x027A0
+
+#define VID_C_DOWN_CLUSTER_1      0x02D40
+#define VID_C_DOWN_CLUSTER_2      0x032E0
+#define VID_C_DOWN_CLUSTER_3      0x03880
+#define VID_C_DOWN_CLUSTER_4      0x03E20
+
+#define VID_D_DOWN_CLUSTER_1      0x043C0
+#define VID_D_DOWN_CLUSTER_2      0x04960
+#define VID_D_DOWN_CLUSTER_3      0x04F00
+#define VID_D_DOWN_CLUSTER_4      0x054A0
+
+#define VID_E_DOWN_CLUSTER_1      0x05a40
+#define VID_E_DOWN_CLUSTER_2      0x05FE0
+#define VID_E_DOWN_CLUSTER_3      0x06580
+#define VID_E_DOWN_CLUSTER_4      0x06B20
+
+#define VID_F_DOWN_CLUSTER_1      0x070C0
+#define VID_F_DOWN_CLUSTER_2      0x07660
+#define VID_F_DOWN_CLUSTER_3      0x07C00
+#define VID_F_DOWN_CLUSTER_4      0x081A0
+
+#define VID_G_DOWN_CLUSTER_1      0x08740
+#define VID_G_DOWN_CLUSTER_2      0x08CE0
+#define VID_G_DOWN_CLUSTER_3      0x09280
+#define VID_G_DOWN_CLUSTER_4      0x09820
+
+#define VID_H_DOWN_CLUSTER_1      0x09DC0
+#define VID_H_DOWN_CLUSTER_2      0x0A360
+#define VID_H_DOWN_CLUSTER_3      0x0A900
+#define VID_H_DOWN_CLUSTER_4      0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1      0x0B500
+#define AUD_A_DOWN_CLUSTER_2      0x0B580
+#define AUD_A_DOWN_CLUSTER_3      0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1      0x0B680
+#define AUD_B_DOWN_CLUSTER_2      0x0B700
+#define AUD_B_DOWN_CLUSTER_3      0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1      0x0B800
+#define AUD_C_DOWN_CLUSTER_2      0x0B880
+#define AUD_C_DOWN_CLUSTER_3      0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1      0x0B980
+#define AUD_D_DOWN_CLUSTER_2      0x0BA00
+#define AUD_D_DOWN_CLUSTER_3      0x0BA80
+
+#define TX_SRAM_POOL_FREE         0x0BB00
+#define TX_SRAM_END               0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2012 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *  Parts adapted/taken from Eduardo Moscoso Rubino
+ *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug = VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num);
+
+static const struct v4l2_file_operations video_fops;
+static const struct v4l2_ioctl_ops video_ioctl_ops;
+
+#define FORMAT_FLAGS_PACKED       0x01
+
+struct cx25821_fmt formats[] = {
+	{
+		.name = "8 bpp, gray",
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.depth = 8,
+		.flags = FORMAT_FLAGS_PACKED,
+	 }, {
+		.name = "4:1:1, packed, Y41P",
+		.fourcc = V4L2_PIX_FMT_Y41P,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, YUYV",
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, UYVY",
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:0, YUV",
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	},
+};
+
+int cx25821_get_format_size(void)
+{
+	return ARRAY_SIZE(formats);
+}
+
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P)
+		return formats + 1;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].fourcc == fourcc)
+			return formats + i;
+
+	pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	return NULL;
+}
+
+void cx25821_dump_video_queue(struct cx25821_dev *dev,
+			      struct cx25821_dmaqueue *q)
+{
+	struct cx25821_buffer *buf;
+	struct list_head *item;
+	dprintk(1, "%s()\n", __func__);
+
+	if (!list_empty(&q->active)) {
+		list_for_each(item, &q->active)
+		    buf = list_entry(item, struct cx25821_buffer, vb.queue);
+	}
+
+	if (!list_empty(&q->queued)) {
+		list_for_each(item, &q->queued)
+		    buf = list_entry(item, struct cx25821_buffer, vb.queue);
+	}
+
+}
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
+			  u32 count)
+{
+	struct cx25821_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active)) {
+			dprintk(1, "bc=%d (=0: active empty)\n", bc);
+			break;
+		}
+
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+		/* count comes from the hw and it is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+
+		do_gettimeofday(&buf->vb.ts);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+
+	if (list_empty(&q->active))
+		del_timer(&q->timeout);
+	else
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+	if (bc != 1)
+		pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+		__func__, (unsigned int)norm, v4l2_norm_to_name(norm));
+
+	dev->tvnorm = norm;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, core, s_std, norm);
+
+	return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       struct video_device *template,
+				       char *type)
+{
+	struct video_device *vfd;
+	dprintk(1, "%s()\n", __func__);
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
+		 cx25821_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
+	return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].v.id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i].v;
+	return 0;
+}
+*/
+
+/* resource management */
+int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		    unsigned int bit)
+{
+	dprintk(1, "%s()\n", __func__);
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&dev->lock);
+	if (dev->channels[fh->channel_id].resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources |= bit;
+	dev->channels[fh->channel_id].resources |= bit;
+	dprintk(1, "res: get %d\n", bit);
+	mutex_unlock(&dev->lock);
+	return 1;
+}
+
+int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->resources & bit;
+}
+
+int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->dev->channels[fh->channel_id].resources & bit;
+}
+
+void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		      unsigned int bits)
+{
+	BUG_ON((fh->resources & bits) != bits);
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&dev->lock);
+	fh->resources &= ~bits;
+	dev->channels[fh->channel_id].resources &= ~bits;
+	dprintk(1, "res: put %d\n", bits);
+	mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+	struct v4l2_routing route;
+	memset(&route, 0, sizeof(route));
+
+	dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+		__func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
+		INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
+	dev->input = input;
+
+	route.input = INPUT(input)->vmux;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
+
+	return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+			    struct cx25821_dmaqueue *q,
+			    struct cx25821_buffer *buf,
+			    struct sram_channel *channel)
+{
+	int tmp = 0;
+
+	/* setup fifo + format */
+	cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+	/* reset counter */
+	cx_write(channel->gpcnt_ctl, 3);
+	q->count = 1;
+
+	/* enable irq */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
+	cx_set(channel->int_msk, 0x11);
+
+	/* start dma */
+	cx_write(channel->dma_ctl, 0x11);	/* FIFO and RISC enable */
+
+	/* make sure upstream setting if any is reversed */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	return 0;
+}
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev,
+				struct cx25821_dmaqueue *q,
+				struct sram_channel *channel)
+{
+	struct cx25821_buffer *buf, *prev;
+	struct list_head *item;
+
+	if (!list_empty(&q->active)) {
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+		cx25821_start_video_dma(dev, q, buf, channel);
+
+		list_for_each(item, &q->active) {
+			buf = list_entry(item, struct cx25821_buffer, vb.queue);
+			buf->count = q->count++;
+		}
+
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		return 0;
+	}
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+
+		buf =
+		    list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			cx25821_start_video_dma(dev, q, buf, channel);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		} else if (prev->vb.width == buf->vb.width &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+	struct cx25821_data *timeout_data = (struct cx25821_data *)data;
+	struct cx25821_dev *dev = timeout_data->dev;
+	struct sram_channel *channel = timeout_data->channel;
+	struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq;
+	struct cx25821_buffer *buf;
+	unsigned long flags;
+
+	/* cx25821_sram_channel_dump(dev, channel); */
+	cx_clear(channel->dma_ctl, 0x11);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+	}
+
+	cx25821_restart_video_queue(dev, q, channel);
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+	u32 count = 0;
+	int handled = 0;
+	u32 mask;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+
+	mask = cx_read(channel->int_msk);
+	if (0 == (status & mask))
+		return handled;
+
+	cx_write(channel->int_stat, status);
+
+	/* risc op code error */
+	if (status & (1 << 16)) {
+		pr_warn("%s, %s: video risc op code error\n",
+			dev->name, channel->name);
+		cx_clear(channel->dma_ctl, 0x11);
+		cx25821_sram_channel_dump(dev, channel);
+	}
+
+	/* risc1 y */
+	if (status & FLD_VID_DST_RISC1) {
+		spin_lock(&dev->slock);
+		count = cx_read(channel->gpcnt);
+		cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq,
+				count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		dprintk(2, "stopper video\n");
+		spin_lock(&dev->slock);
+		cx25821_restart_video_queue(dev,
+				&dev->channels[channel->i].vidq, channel);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+	return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+	if (dev->ioctl_dev) {
+		if (video_is_registered(dev->ioctl_dev))
+			video_unregister_device(dev->ioctl_dev);
+		else
+			video_device_release(dev->ioctl_dev);
+
+		dev->ioctl_dev = NULL;
+	}
+}
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+	cx_clear(PCI_INT_MSK, 1);
+
+	if (dev->channels[chan_num].video_dev) {
+		if (video_is_registered(dev->channels[chan_num].video_dev))
+			video_unregister_device(
+					dev->channels[chan_num].video_dev);
+		else
+			video_device_release(
+					dev->channels[chan_num].video_dev);
+
+		dev->channels[chan_num].video_dev = NULL;
+
+		btcx_riscmem_free(dev->pci,
+				&dev->channels[chan_num].vidq.stopper);
+
+		pr_warn("device %d released!\n", chan_num);
+	}
+
+}
+
+int cx25821_video_register(struct cx25821_dev *dev)
+{
+	int err;
+	int i;
+
+	struct video_device cx25821_video_device = {
+		.name = "cx25821-video",
+		.fops = &video_fops,
+		.minor = -1,
+		.ioctl_ops = &video_ioctl_ops,
+		.tvnorms = CX25821_NORMS,
+		.current_norm = V4L2_STD_NTSC_M,
+	};
+
+	spin_lock_init(&dev->slock);
+
+	for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+		cx25821_init_controls(dev, i);
+
+		cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
+				dev->channels[i].sram_channels->dma_ctl,
+				0x11, 0);
+
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+		dev->channels[i].video_dev = NULL;
+		dev->channels[i].resources = 0;
+
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+		INIT_LIST_HEAD(&dev->channels[i].vidq.active);
+		INIT_LIST_HEAD(&dev->channels[i].vidq.queued);
+
+		dev->channels[i].timeout_data.dev = dev;
+		dev->channels[i].timeout_data.channel =
+			&cx25821_sram_channels[i];
+		dev->channels[i].vidq.timeout.function =
+			cx25821_vid_timeout;
+		dev->channels[i].vidq.timeout.data =
+			(unsigned long)&dev->channels[i].timeout_data;
+		init_timer(&dev->channels[i].vidq.timeout);
+
+		/* register v4l devices */
+		dev->channels[i].video_dev = cx25821_vdev_init(dev,
+				dev->pci, &cx25821_video_device, "video");
+
+		err = video_register_device(dev->channels[i].video_dev,
+				VFL_TYPE_GRABBER, video_nr[dev->nr]);
+
+		if (err < 0)
+			goto fail_unreg;
+
+	}
+
+	/* set PCI interrupt */
+	cx_set(PCI_INT_MSK, 0xff);
+
+	/* initial device configuration */
+	mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+	dev->tvnorm = cx25821_video_device.current_norm;
+	cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+	mutex_unlock(&dev->lock);
+
+
+	return 0;
+
+fail_unreg:
+	cx25821_video_unregister(dev, i);
+	return err;
+}
+
+int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+		 unsigned int *size)
+{
+	struct cx25821_fh *fh = q->priv_data;
+
+	*size = fh->fmt->depth * fh->width * fh->height >> 3;
+
+	if (0 == *count)
+		*count = 32;
+
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
+
+	return 0;
+}
+
+int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+		   enum v4l2_field field)
+{
+	struct cx25821_fh *fh = q->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_buffer *buf =
+	    container_of(vb, struct cx25821_buffer, vb);
+	int rc, init_buffer = 0;
+	u32 line0_offset, line1_offset;
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+	int bpl_local = LINE_SIZE_D1;
+	int channel_opened = fh->channel_id;
+
+	BUG_ON(NULL == fh->fmt);
+	if (fh->width < 48 || fh->width > 720 ||
+	    fh->height < 32 || fh->height > 576)
+		return -EINVAL;
+
+	buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt != fh->fmt ||
+	    buf->vb.width != fh->width ||
+	    buf->vb.height != fh->height || buf->vb.field != field) {
+		buf->fmt = fh->fmt;
+		buf->vb.width = fh->width;
+		buf->vb.height = fh->height;
+		buf->vb.field = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc) {
+			printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
+			goto fail;
+		}
+	}
+
+	dprintk(1, "init_buffer=%d\n", init_buffer);
+
+	if (init_buffer) {
+
+		channel_opened = dev->channel_opened;
+		if (channel_opened < 0 || channel_opened > 7)
+			channel_opened = 7;
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411)
+			buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+		else
+			buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411) {
+			bpl_local = buf->bpl;
+		} else {
+			bpl_local = buf->bpl;   /* Default */
+
+			if (channel_opened >= 0 && channel_opened <= 7) {
+				if (dev->channels[channel_opened]
+						.use_cif_resolution) {
+					if (dev->tvnorm & V4L2_STD_PAL_BG
+					    || dev->tvnorm & V4L2_STD_PAL_DK)
+						bpl_local = 352 << 1;
+					else
+						bpl_local =
+						 dev->channels[channel_opened].
+						 cif_width <<
+						 1;
+				}
+			}
+		}
+
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, 0, UNSET,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, UNSET, 0,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			/* All other formats are top field first */
+			line0_offset = 0;
+			line1_offset = buf->bpl;
+			dprintk(1, "top field first\n");
+
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, line0_offset,
+					    bpl_local, bpl_local, bpl_local,
+					    buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    0, buf->bpl * (buf->vb.height >> 1),
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    buf->bpl * (buf->vb.height >> 1), 0,
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+		buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
+		fh->fmt->name, (unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+
+	return 0;
+
+fail:
+	cx25821_free_buffer(q, buf);
+	return rc;
+}
+
+void cx25821_buffer_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+	    container_of(vb, struct cx25821_buffer, vb);
+
+	cx25821_free_buffer(q, buf);
+}
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &fh->vidq;
+	default:
+		BUG();
+		return NULL;
+	}
+}
+
+int cx25821_get_resource(struct cx25821_fh *fh, int resource)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return resource;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+	   container_of(vb, struct cx25821_buffer, vb);
+	struct cx25821_buffer *prev;
+	struct cx25821_fh *fh = vq->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
+
+	dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue, &q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+				buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue, &q->active);
+		cx25821_start_video_dma(dev, q, buf,
+				dev->channels[fh->channel_id].sram_channels);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count = q->count++;
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+				buf, buf->vb.i, buf->count, q->count);
+	} else {
+		prev = list_entry(q->active.prev, struct cx25821_buffer,
+				vb.queue);
+		if (prev->vb.width == buf->vb.width
+		   && prev->vb.height == buf->vb.height
+		   && prev->fmt == buf->fmt) {
+			list_add_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+			/* 64 bit bits 63-32 */
+			prev->risc.jmp[2] = cpu_to_le32(0);
+			dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+					buf, buf->vb.i, buf->count);
+
+		} else {
+			list_add_tail(&buf->vb.queue, &q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+					buf->vb.i);
+		}
+	}
+
+	if (list_empty(&q->active))
+		dprintk(2, "active queue empty!\n");
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+	.buf_setup = cx25821_buffer_setup,
+	.buf_prepare = cx25821_buffer_prepare,
+	.buf_queue = buffer_queue,
+	.buf_release = cx25821_buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *h, *dev = video_drvdata(file);
+	struct cx25821_fh *fh;
+	struct list_head *list;
+	int minor = video_devdata(file)->minor;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	u32 pix_format;
+	int ch_id = 0;
+	int i;
+
+	dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev),
+			v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (NULL == fh)
+		return -ENOMEM;
+
+	mutex_lock(&cx25821_devlist_mutex);
+
+	list_for_each(list, &cx25821_devlist)
+	{
+		h = list_entry(list, struct cx25821_dev, devlist);
+
+		for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
+			if (h->channels[i].video_dev &&
+			   h->channels[i].video_dev->minor == minor) {
+				dev = h;
+				ch_id = i;
+				type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			}
+		}
+	}
+
+	if (NULL == dev) {
+		mutex_unlock(&cx25821_devlist_mutex);
+		kfree(fh);
+		return -ENODEV;
+	}
+
+	file->private_data = fh;
+	fh->dev = dev;
+	fh->type = type;
+	fh->width = 720;
+	fh->channel_id = ch_id;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		fh->height = 576;
+	else
+		fh->height = 480;
+
+	dev->channel_opened = fh->channel_id;
+	if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411)
+		pix_format = V4L2_PIX_FMT_Y41P;
+	else
+		pix_format = V4L2_PIX_FMT_YUYV;
+	fh->fmt = cx25821_format_by_fourcc(pix_format);
+
+	v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+			      &dev->pci->dev, &dev->slock,
+			      V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			      V4L2_FIELD_INTERLACED,
+			      sizeof(struct cx25821_buffer), fh, NULL);
+
+	dprintk(1, "post videobuf_queue_init()\n");
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+			 loff_t *ppos)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
+			return -EBUSY;
+
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					file->f_flags & O_NONBLOCK);
+
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static unsigned int video_poll(struct file *file,
+			      struct poll_table_struct *wait)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_buffer *buf;
+
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			return POLLERR;
+		buf = list_entry(fh->vidq.stream.next,
+				struct cx25821_buffer, vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+		if (NULL == buf)
+			return POLLERR;
+	}
+
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+		if (buf->vb.state == VIDEOBUF_DONE) {
+			struct cx25821_dev *dev = fh->dev;
+
+			if (dev && dev->channels[fh->channel_id]
+					.use_cif_resolution) {
+				u8 cam_id = *((char *)buf->vb.baddr + 3);
+				memcpy((char *)buf->vb.baddr,
+				      (char *)buf->vb.baddr + (fh->width * 2),
+				      (fh->width * 2));
+				*((char *)buf->vb.baddr + 3) = cam_id;
+			}
+		}
+
+		return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+
+	/* stop the risc engine and fifo */
+	cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+	/* stop video capture */
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		videobuf_queue_cancel(&fh->vidq);
+		cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
+	}
+
+	if (fh->vidq.read_buf) {
+		cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+
+	v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	if (unlikely(i != fh->type))
+		return -EINVAL;
+
+	if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh,
+						RESOURCE_VIDEO0))))
+		return -EBUSY;
+
+	return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+	int err, res;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
+	err = videobuf_streamoff(get_queue(fh));
+	if (err < 0)
+		return err;
+	cx25821_res_free(dev, fh, res);
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int err;
+	int pix_format = PIXEL_FRMT_422;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(2, "%s()\n", __func__);
+	err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
+
+	if (0 != err)
+		return err;
+
+	fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->vidq.field = f->fmt.pix.field;
+
+	/* check if width and height is valid based on set standard */
+	if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm))
+		fh->width = f->fmt.pix.width;
+
+	if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm))
+		fh->height = f->fmt.pix.height;
+
+	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+		pix_format = PIXEL_FRMT_411;
+	else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+		pix_format = PIXEL_FRMT_422;
+	else
+		return -EINVAL;
+
+	cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+	/* check if cif resolution */
+	if (fh->width == 320 || fh->width == 352)
+		dev->channels[fh->channel_id].use_cif_resolution = 1;
+	else
+		dev->channels[fh->channel_id].use_cif_resolution = 0;
+
+	dev->channels[fh->channel_id].cif_width = fh->width;
+	medusa_set_resolution(dev, fh->width, SRAM_CH00);
+
+	dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
+		fh->height, fh->vidq.field);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+	cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+
+	return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	int ret_val = 0;
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+	p->sequence = dev->channels[fh->channel_id].vidq.count;
+
+	return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	char name[32 + 2];
+
+	struct sram_channel *sram_ch = dev->channels[fh->channel_id]
+								.sram_channels;
+	u32 tmp = 0;
+
+	snprintf(name, sizeof(name), "%s/2", dev->name);
+	pr_info("%s/2: ============  START LOG STATUS  ============\n",
+		dev->name);
+	cx25821_call_all(dev, core, log_status);
+	tmp = cx_read(sram_ch->dma_ctl);
+	pr_info("Video input 0 is %s\n",
+		(tmp & 0x11) ? "streaming" : "stopped");
+	pr_info("%s/2: =============  END LOG STATUS  =============\n",
+		dev->name);
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+			struct v4l2_control *ctl)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	return cx25821_set_control(dev, ctl, fh->channel_id);
+}
+
+/* VIDEO IOCTLS */
+int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				 struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+
+	f->fmt.pix.width = fh->width;
+	f->fmt.pix.height = fh->height;
+	f->fmt.pix.field = fh->vidq.field;
+	f->fmt.pix.pixelformat = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct cx25821_fmt *fmt;
+	enum v4l2_field field;
+	unsigned int maxw, maxh;
+
+	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw = 720;
+	maxh = 576;
+
+	if (V4L2_FIELD_ANY == field) {
+		if (f->fmt.pix.height > maxh / 2)
+			field = V4L2_FIELD_INTERLACED;
+		else
+			field = V4L2_FIELD_TOP;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	if (f->fmt.pix.height < 32)
+		f->fmt.pix.height = 32;
+	if (f->fmt.pix.height > maxh)
+		f->fmt.pix.height = maxh;
+	if (f->fmt.pix.width < 48)
+		f->fmt.pix.width = 48;
+	if (f->fmt.pix.width > maxw)
+		f->fmt.pix.width = maxw;
+	f->fmt.pix.width &= ~0x03;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_querycap(struct file *file, void *priv,
+			    struct v4l2_capability *cap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	strcpy(cap->driver, "cx25821");
+	strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+	sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+	cap->version = CX25821_VERSION_CODE;
+	cap->capabilities =
+	    V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	if (UNSET != dev->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
+
+int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+			    struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+			   struct v4l2_requestbuffers *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int cx25821_vidioc_querybuf(struct file *file, void *priv,
+			    struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_querybuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_qbuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+	struct cx25821_fh *fh = f;
+
+	*p = v4l2_prio_max(&dev->channels[fh->channel_id].prio);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_priority(struct file *file, void *f,
+			      enum v4l2_priority prio)
+{
+	struct cx25821_fh *fh = f;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+	return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio,
+			prio);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (dev->tvnorm == *tvnorms)
+		return 0;
+
+	mutex_lock(&dev->lock);
+	cx25821_set_tvnorm(dev, *tvnorms);
+	mutex_unlock(&dev->lock);
+
+	medusa_set_videostandard(dev);
+
+	return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+	static const char * const iname[] = {
+		[CX25821_VMUX_COMPOSITE] = "Composite",
+		[CX25821_VMUX_SVIDEO] = "S-Video",
+		[CX25821_VMUX_DEBUG] = "for debug only",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name, iname[INPUT(n)->type]);
+
+	i->std = CX25821_NORMS;
+	return 0;
+}
+
+int cx25821_vidioc_enum_input(struct file *file, void *priv,
+			      struct v4l2_input *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+	return cx25821_enum_input(dev, i);
+}
+
+int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	*i = dev->input;
+	dprintk(1, "%s(): returns %d\n", __func__, *i);
+	return 0;
+}
+
+int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s(%d)\n", __func__, i);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (i >= CX25821_NR_INPUT) {
+		dprintk(1, "%s(): -EINVAL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->lock);
+	cx25821_video_mux(dev, i);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	f->frequency = dev->freq;
+
+	cx25821_call_all(dev, tuner, g_frequency, f);
+
+	return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+
+	cx25821_call_all(dev, tuner, s_frequency, f);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep(10);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev;
+	int err;
+
+	if (fh) {
+		dev = fh->dev;
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	} else {
+		pr_err("Invalid fh pointer!\n");
+		return -EINVAL;
+	}
+
+	return cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx25821_vidioc_g_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, g_register, reg);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, s_register, reg);
+
+	return 0;
+}
+
+#endif
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh = 0xffffffffUL;
+
+	t->signal = 0xffff;	/* LOCKED */
+	return 0;
+}
+
+int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(1, "%s()\n", __func__);
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	return 0;
+}
+
+#endif
+/*****************************************************************************/
+static const struct v4l2_queryctrl no_ctl = {
+	.name = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+	/* --- video --- */
+	{
+	 .id = V4L2_CID_BRIGHTNESS,
+	 .name = "Brightness",
+	 .minimum = 0,
+	 .maximum = 10000,
+	 .step = 1,
+	 .default_value = 6200,
+	 .type = V4L2_CTRL_TYPE_INTEGER,
+	 }, {
+	     .id = V4L2_CID_CONTRAST,
+	     .name = "Contrast",
+	     .minimum = 0,
+	     .maximum = 10000,
+	     .step = 1,
+	     .default_value = 5000,
+	     .type = V4L2_CTRL_TYPE_INTEGER,
+	     }, {
+		 .id = V4L2_CID_SATURATION,
+		 .name = "Saturation",
+		 .minimum = 0,
+		 .maximum = 10000,
+		 .step = 1,
+		 .default_value = 5000,
+		 .type = V4L2_CTRL_TYPE_INTEGER,
+		 }, {
+		     .id = V4L2_CID_HUE,
+		     .name = "Hue",
+		     .minimum = 0,
+		     .maximum = 10000,
+		     .step = 1,
+		     .default_value = 5000,
+		     .type = V4L2_CTRL_TYPE_INTEGER,
+		     }
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i];
+	return 0;
+}
+
+int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+		     struct v4l2_queryctrl *qctrl)
+{
+	return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+	unsigned int i;
+
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == id)
+			return cx25821_ctls + i;
+	return NULL;
+}
+
+int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+			  struct v4l2_control *ctl)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+
+	const struct v4l2_queryctrl *ctrl;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return -EINVAL;
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctl->value = dev->channels[fh->channel_id].ctl_bright;
+		break;
+	case V4L2_CID_HUE:
+		ctl->value = dev->channels[fh->channel_id].ctl_hue;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctl->value = dev->channels[fh->channel_id].ctl_contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctl->value = dev->channels[fh->channel_id].ctl_saturation;
+		break;
+	}
+	return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+			struct v4l2_control *ctl, int chan_num)
+{
+	int err;
+	const struct v4l2_queryctrl *ctrl;
+
+	err = -EINVAL;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return err;
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER:
+		if (ctl->value < ctrl->minimum)
+			ctl->value = ctrl->minimum;
+		if (ctl->value > ctrl->maximum)
+			ctl->value = ctrl->maximum;
+		break;
+	default:
+		/* nothing */ ;
+	}
+
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		dev->channels[chan_num].ctl_bright = ctl->value;
+		medusa_set_brightness(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_HUE:
+		dev->channels[chan_num].ctl_hue = ctl->value;
+		medusa_set_hue(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_CONTRAST:
+		dev->channels[chan_num].ctl_contrast = ctl->value;
+		medusa_set_contrast(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_SATURATION:
+		dev->channels[chan_num].ctl_saturation = ctl->value;
+		medusa_set_saturation(dev, ctl->value, chan_num);
+		break;
+	}
+
+	err = 0;
+
+	return err;
+}
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num)
+{
+	struct v4l2_control ctrl;
+	int i;
+	for (i = 0; i < CX25821_CTLS; i++) {
+		ctrl.id = cx25821_ctls[i].id;
+		ctrl.value = cx25821_ctls[i].default_value;
+
+		cx25821_set_control(dev, &ctrl, chan_num);
+	}
+}
+
+int cx25821_vidioc_cropcap(struct file *file, void *priv,
+			   struct v4l2_cropcap *cropcap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	cropcap->bounds.top = cropcap->bounds.left = 0;
+	cropcap->bounds.width = 720;
+	cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+	cropcap->pixelaspect.numerator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+	cropcap->pixelaspect.denominator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+	cropcap->defrect = cropcap->bounds;
+	return 0;
+}
+
+int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+	/* cx25821_vidioc_s_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	/* cx25821_vidioc_g_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
+{
+	/* medusa does not support video standard sensing of current input */
+	*norm = CX25821_NORMS;
+
+	return 0;
+}
+
+int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (width == 320 || width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (height == 576 || height == 288)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (height == 480 || height == 240)
+			return 1;
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch1(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch1(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename_ch2 = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname_ch2 = data_from_user->vid_stdname;
+	dev->pixel_format_ch2 = data_from_user->pixel_format;
+	dev->channel_select_ch2 = data_from_user->channel_select;
+	dev->command_ch2 = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch2(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch2(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_AUDIO:
+		cx25821_start_upstream_audio(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_AUDIO:
+		cx25821_stop_upstream_audio(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct downstream_user_struct *data_from_user;
+	int command;
+	int width = 720;
+	int selected_channel = 0, pix_format = 0, i = 0;
+	int cif_enable = 0, cif_width = 0;
+	u32 value = 0;
+
+	data_from_user = (struct downstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): User data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
+	   && command != ENABLE_CIF_RESOLUTION && command != REG_READ
+	   && command != REG_WRITE && command != MEDUSA_READ
+	   && command != MEDUSA_WRITE) {
+		return 0;
+	}
+
+	switch (command) {
+	case SET_VIDEO_STD:
+		if (!strcmp(data_from_user->vid_stdname, "PAL"))
+			dev->tvnorm = V4L2_STD_PAL_BG;
+		else
+			dev->tvnorm = V4L2_STD_NTSC_M;
+		medusa_set_videostandard(dev);
+		break;
+
+	case SET_PIXEL_FORMAT:
+		selected_channel = data_from_user->decoder_select;
+		pix_format = data_from_user->pixel_format;
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel >= 0)
+			cx25821_set_pixel_format(dev, selected_channel,
+						pix_format);
+
+		break;
+
+	case ENABLE_CIF_RESOLUTION:
+		selected_channel = data_from_user->decoder_select;
+		cif_enable = data_from_user->cif_resolution_enable;
+		cif_width = data_from_user->cif_width;
+
+		if (cif_enable) {
+			if (dev->tvnorm & V4L2_STD_PAL_BG
+			    || dev->tvnorm & V4L2_STD_PAL_DK) {
+				width = 352;
+			} else {
+				width = cif_width;
+				if (cif_width != 320 && cif_width != 352)
+					width = 320;
+			}
+		}
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel <= 7 && selected_channel >= 0) {
+			dev->channels[selected_channel].
+				use_cif_resolution = cif_enable;
+			dev->channels[selected_channel].cif_width = width;
+		} else {
+			for (i = 0; i < VID_CHANNEL_NUM; i++) {
+				dev->channels[i].use_cif_resolution =
+					cif_enable;
+				dev->channels[i].cif_width = width;
+			}
+		}
+
+		medusa_set_resolution(dev, width, selected_channel);
+		break;
+	case REG_READ:
+		data_from_user->reg_data = cx_read(data_from_user->reg_address);
+		break;
+	case REG_WRITE:
+		cx_write(data_from_user->reg_address, data_from_user->reg_data);
+		break;
+	case MEDUSA_READ:
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+					 (u16) data_from_user->reg_address,
+					 &data_from_user->reg_data);
+		break;
+	case MEDUSA_WRITE:
+		cx25821_i2c_write(&dev->i2c_bus[0],
+				  (u16) data_from_user->reg_address,
+				  data_from_user->reg_data);
+		break;
+	}
+
+	return 0;
+}
+
+static long cx25821_video_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	int  ret = 0;
+
+	struct cx25821_fh  *fh  = file->private_data;
+
+	/* check to see if it's the video upstream */
+	if (fh->channel_id == SRAM_CH09) {
+		ret = video_ioctl_upstream9(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH10) {
+		ret = video_ioctl_upstream10(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH11) {
+		ret = video_ioctl_upstream11(file, cmd, arg);
+		ret = video_ioctl_set(file, cmd, arg);
+		return ret;
+	}
+
+	return video_ioctl2(file, cmd, arg);
+}
+
+/* exported stuff */
+static const struct v4l2_file_operations video_fops = {
+	.owner = THIS_MODULE,
+	.open = video_open,
+	.release = video_release,
+	.read = video_read,
+	.poll = video_poll,
+	.mmap = cx25821_video_mmap,
+	.ioctl = cx25821_video_ioctl,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap = cx25821_vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs = cx25821_vidioc_reqbufs,
+	.vidioc_querybuf = cx25821_vidioc_querybuf,
+	.vidioc_qbuf = cx25821_vidioc_qbuf,
+	.vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+	.vidioc_s_std = cx25821_vidioc_s_std,
+	.vidioc_querystd = cx25821_vidioc_querystd,
+#endif
+	.vidioc_cropcap = cx25821_vidioc_cropcap,
+	.vidioc_s_crop = cx25821_vidioc_s_crop,
+	.vidioc_g_crop = cx25821_vidioc_g_crop,
+	.vidioc_enum_input = cx25821_vidioc_enum_input,
+	.vidioc_g_input = cx25821_vidioc_g_input,
+	.vidioc_s_input = cx25821_vidioc_s_input,
+	.vidioc_g_ctrl = cx25821_vidioc_g_ctrl,
+	.vidioc_s_ctrl = vidioc_s_ctrl,
+	.vidioc_queryctrl = cx25821_vidioc_queryctrl,
+	.vidioc_streamon = vidioc_streamon,
+	.vidioc_streamoff = vidioc_streamoff,
+	.vidioc_log_status = vidioc_log_status,
+	.vidioc_g_priority = cx25821_vidioc_g_priority,
+	.vidioc_s_priority = cx25821_vidioc_s_priority,
+#ifdef TUNER_FLAG
+	.vidioc_g_tuner = cx25821_vidioc_g_tuner,
+	.vidioc_s_tuner = cx25821_vidioc_s_tuner,
+	.vidioc_g_frequency = cx25821_vidioc_g_frequency,
+	.vidioc_s_frequency = cx25821_vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register = cx25821_vidioc_g_register,
+	.vidioc_s_register = cx25821_vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+	.name = "cx25821-videoioctl",
+	.fops = &video_fops,
+	.ioctl_ops = &video_ioctl_ops,
+	.tvnorms = CX25821_NORMS,
+	.current_norm = V4L2_STD_NTSC_M,
+};
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,188 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (VIDEO_DEBUG >= level)					\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+/* For IOCTL to identify running upstream */
+#define UPSTREAM_START_VIDEO        700
+#define UPSTREAM_STOP_VIDEO         701
+#define UPSTREAM_START_AUDIO        702
+#define UPSTREAM_STOP_AUDIO         703
+#define UPSTREAM_DUMP_REGISTERS     702
+#define SET_VIDEO_STD               800
+#define SET_PIXEL_FORMAT            1000
+#define ENABLE_CIF_RESOLUTION       1001
+
+#define REG_READ		    900
+#define REG_WRITE		    901
+#define MEDUSA_READ		    910
+#define MEDUSA_WRITE		    911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_videoioctl_template;
+/* extern const u32 *ctrl_classes[]; */
+
+extern unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED       0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void cx25821_dump_video_queue(struct cx25821_dev *dev,
+				     struct cx25821_dmaqueue *q);
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+				 struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			   unsigned int bit);
+extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit);
+extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			     unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+				   struct cx25821_dmaqueue *q,
+				   struct cx25821_buffer *buf,
+				   struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
+			     unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev);
+extern int cx25821_get_format_size(void);
+
+extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+				unsigned int *size);
+extern int cx25821_buffer_prepare(struct videobuf_queue *q,
+				  struct videobuf_buffer *vb,
+				  enum v4l2_field field);
+extern void cx25821_buffer_release(struct videobuf_queue *q,
+				   struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int cx25821_get_resource(struct cx25821_fh *fh, int resource);
+extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+					  struct v4l2_format *f);
+extern int cx25821_vidioc_querycap(struct file *file, void *priv,
+				   struct v4l2_capability *cap);
+extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+					   struct v4l2_fmtdesc *f);
+extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+				  struct v4l2_requestbuffers *p);
+extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
+				   struct v4l2_buffer *p);
+extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
+			       struct v4l2_buffer *p);
+extern int cx25821_vidioc_s_std(struct file *file, void *priv,
+				v4l2_std_id *tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
+				     struct v4l2_input *i);
+extern int cx25821_vidioc_g_input(struct file *file, void *priv,
+				  unsigned int *i);
+extern int cx25821_vidioc_s_input(struct file *file, void *priv,
+				  unsigned int i);
+extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+				 struct v4l2_control *ctl);
+extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f);
+extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_vidioc_g_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_s_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+
+extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int cx25821_vidioc_g_priority(struct file *file, void *f,
+				     enum v4l2_priority *p);
+extern int cx25821_vidioc_s_priority(struct file *file, void *f,
+				     enum v4l2_priority prio);
+
+extern int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+				    struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev,
+			       struct v4l2_control *ctrl, int chan_num);
+
+extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
+				  struct v4l2_cropcap *cropcap);
+extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+
+extern int cx25821_vidioc_querystd(struct file *file, void *priv,
+				   v4l2_std_id *norm);
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,885 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					struct sram_channel *ch,
+					unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
+					  __le32 *rp, unsigned int offset,
+					  unsigned int bpl, u32 sync_line,
+					  unsigned int lines, int fifo_enable,
+					  int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
+					   dma_addr_t databuf_phys_addr,
+					   unsigned int offset, u32 sync_line,
+					   unsigned int bpl, unsigned int lines,
+					   int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_channel_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
+			/* to skip the other field line */
+			offset += dist_betwn_starts;
+
+		/* check if we need to enable the FIFO after the first 4 lines
+		 * For the upstream video channel, the risc engine will enable
+		 * the FIFO. */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+				 struct pci_dev *pci,
+				 unsigned int top_offset,
+				 unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	/* get line count for single field */
+	int singlefield_lines = lines >> 1;
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		frame_size =
+		    (bpl ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		frame_size =
+		    (bpl ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream(dev, rp,
+							 dev->
+							 _data_buf_phys_addr +
+							 databuf_offset,
+							 top_offset, 0, bpl,
+							 odd_num_lines,
+							 fifo_enable,
+							 ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+		/* Even Field */
+		rp = cx25821_risc_field_upstream(dev, rp,
+						 dev->_data_buf_phys_addr +
+						 databuf_offset, bottom_offset,
+						 0x200, bpl, singlefield_lines,
+						 fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr =
+			    dev->_dma_phys_start_addr + risc_program_size;
+		} else {
+			risc_phys_jump_addr = dev->_dma_phys_start_addr;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Loop to 2ndFrameRISC or to Start of Risc
+		 * program & generate IRQ
+		 */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo enable */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr)
+		memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	dev->_is_running = 0;
+	dev->_is_first_frame = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = END_OF_FILE;
+
+	kfree(dev->_irq_queues);
+	dev->_irq_queues = NULL;
+
+	kfree(dev->_filename);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
+{
+	if (dev->_is_running)
+		cx25821_stop_upstream_video_ch1(dev);
+
+	if (dev->_dma_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_risc_size,
+				    dev->_dma_virt_addr, dev->_dma_phys_addr);
+		dev->_dma_virt_addr = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size,
+				    dev->_data_buf_virt_addr,
+				    dev->_data_buf_phys_addr);
+		dev->_data_buf_virt_addr = NULL;
+	}
+}
+
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index;
+	int i = 0;
+	int line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC) {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count * frame_size;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count++;
+
+		dev->_file_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _irq_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame(dev,
+			 dev->channels[dev->_channel_upstream_select].
+					       sram_channels);
+}
+
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_data_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr +
+							offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+				    struct sram_channel *sram_ch, int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
+				    dev->_dma_virt_addr, dev->_dma_phys_addr);
+	}
+
+	dev->_dma_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size,
+				 &dma_addr);
+	dev->_dma_virt_start_addr = dev->_dma_virt_addr;
+	dev->_dma_phys_start_addr = dma_addr;
+	dev->_dma_phys_addr = dma_addr;
+	dev->_risc_size = dev->upstream_riscbuf_size;
+
+	if (!dev->_dma_virt_addr) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_dma_virt_addr, 0, dev->_risc_size);
+
+	if (dev->_data_buf_virt_addr != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size,
+				    dev->_data_buf_virt_addr,
+				    dev->_data_buf_phys_addr);
+	}
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->upstream_databuf_size,
+				 &data_dma_addr);
+	dev->_data_buf_phys_addr = data_dma_addr;
+	dev->_data_buf_size = dev->upstream_databuf_size;
+
+	if (!dev->_data_buf_virt_addr) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	ret = cx25821_openfile(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Create RISC programs */
+	ret =
+	    cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+					 dev->_lines_count);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index = prog_cnt;
+
+		queue_work(dev->_irq_queues, &dev->_irq_work_entry);
+
+		if (dev->_is_first_frame) {
+			dev->_is_first_frame = 0;
+
+			if (dev->_isNTSC) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr != NULL) {
+				line_size_in_bytes =
+				    (dev->_pixel_format ==
+				     PIXEL_FRMT_411) ? Y411_LINE_SZ :
+				    Y422_LINE_SZ;
+				risc_phys_jump_addr =
+				    dev->_dma_phys_start_addr +
+				    odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram(dev,
+					dev->_dma_virt_start_addr, TOP_OFFSET,
+					line_size_in_bytes, 0x0,
+					singlefield_lines, FIFO_DISABLE,
+					ODD_FIELD);
+
+				/* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_VID_SRC_UF)
+			pr_err("%s(): Video Received Underflow Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_SYNC)
+			pr_err("%s(): Video Received Sync Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_OPC_ERR)
+			pr_err("%s(): Video Received OpCode Error Interrupt!\n",
+			       __func__);
+	}
+
+	if (dev->_file_status == END_OF_FILE) {
+		pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
+
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status) {
+		handled =
+		    cx25821_video_upstream_irq(dev, channel_num, vid_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch1(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
+			     int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = OUTPUT_FRMT_656;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/* set number of active pixels in each line.
+	 * Default is 720 pixels in both NTSC and PAL format */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running = 1;
+	dev->_is_first_frame = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
+	dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
+
+	if (!dev->_irq_queues) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size =
+	    dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename) {
+		str_length = strlen(dev->input_filename);
+		dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+
+		memcpy(dev->_filename, dev->input_filename, str_length + 1);
+	} else {
+		str_length = strlen(dev->_defaultname);
+		dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+
+		memcpy(dev->_filename, dev->_defaultname, str_length + 1);
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename, "") == 0) {
+		if (dev->_isNTSC) {
+			dev->_filename =
+			    (dev->_pixel_format ==
+			     PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+			    "/root/vidtest.yuv";
+		} else {
+			dev->_filename =
+			    (dev->_pixel_format ==
+			     PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+			    "/root/pal422.yuv";
+		}
+	}
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+
+	retval =
+	    cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size,
+						0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
+
+	dev->upstream_riscbuf_size = risc_buffer_size * 2;
+	dev->upstream_databuf_size = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,823 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream-ch2.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
+					      __le32 *rp, unsigned int offset,
+					      unsigned int bpl, u32 sync_line,
+					      unsigned int lines,
+					      int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1))
+		    || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
+					       __le32 *rp,
+					       dma_addr_t databuf_phys_addr,
+					       unsigned int offset,
+					       u32 sync_line, unsigned int bpl,
+					       unsigned int lines,
+					       int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_channel2_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1))
+		    || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+
+	       /*
+		 check if we need to enable the FIFO after the first 4 lines
+		  For the upstream video channel, the risc engine will enable
+		  the FIFO.
+	       */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+				     struct pci_dev *pci,
+				     unsigned int top_offset, unsigned int bpl,
+				     unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int singlefield_lines = lines >> 1; /*get line count for single field */
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC_ch2) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_NTSC_Y411;
+		else
+			frame_size = FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_PAL_Y411;
+		else
+			frame_size = FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr_ch2;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				top_offset, 0, bpl, odd_num_lines, fifo_enable,
+				ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+	       /* Even field */
+		rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				bottom_offset, 0x200, bpl, singlefield_lines,
+				fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 +
+					risc_program_size;
+		} else {
+			risc_flag = RISC_CNT_INC;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
+		}
+
+	       /*
+		  Loop to 2ndFrameRISC or to Start of
+		  Risc program & generate IRQ
+	       */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running_ch2) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr_ch2)
+		memset(dev->_data_buf_virt_addr_ch2, 0,
+		       dev->_data_buf_size_ch2);
+
+	dev->_is_running_ch2 = 0;
+	dev->_is_first_frame_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = END_OF_FILE;
+
+	kfree(dev->_irq_queues_ch2);
+	dev->_irq_queues_ch2 = NULL;
+
+	kfree(dev->_filename_ch2);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
+{
+	if (dev->_is_running_ch2)
+		cx25821_stop_upstream_video_ch2(dev);
+
+	if (dev->_dma_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_risc_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+		dev->_dma_virt_addr_ch2 = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+		dev->_data_buf_virt_addr_ch2 = NULL;
+	}
+}
+
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index_ch2;
+	int i = 0;
+	int line_size =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status_ch2 == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC_ch2) {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count_ch2 * frame_size;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count_ch2; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr_ch2 != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count_ch2++;
+
+		dev->_file_status_ch2 =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler_ch2(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame_ch2(dev,
+			     dev->channels[dev->
+			       _channel2_upstream_select].sram_channels);
+}
+
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count_ch2; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_data_buf_virt_addr_ch2 != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr_ch2
+							+ offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count_ch2++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status_ch2 =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
+					       struct sram_channel *sram_ch,
+					       int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+	}
+
+	dev->_dma_virt_addr_ch2 =
+	    pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+				 &dma_addr);
+	dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
+	dev->_dma_phys_start_addr_ch2 = dma_addr;
+	dev->_dma_phys_addr_ch2 = dma_addr;
+	dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
+
+	if (!dev->_dma_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Iniitize at this address until n bytes to 0 */
+	memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
+
+	if (dev->_data_buf_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+	}
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr_ch2 =
+	    pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+				 &data_dma_addr);
+	dev->_data_buf_phys_addr_ch2 = data_dma_addr;
+	dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
+
+	if (!dev->_data_buf_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize at this address until n bytes to 0 */
+	memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
+
+	ret = cx25821_openfile_ch2(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
+						dev->_lines_count_ch2);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
+				   u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/*
+		 *  Since we've identified our IRQ, clear our bits from the
+		 *  interrupt mask and interrupt status registers
+		 */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index_ch2 = prog_cnt;
+
+		queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
+
+		if (dev->_is_first_frame_ch2) {
+			dev->_is_first_frame_ch2 = 0;
+
+			if (dev->_isNTSC_ch2) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr_ch2 != NULL) {
+				if (dev->_pixel_format_ch2 == PIXEL_FRMT_411)
+					line_size_in_bytes = Y411_LINE_SZ;
+				else
+					line_size_in_bytes = Y422_LINE_SZ;
+				risc_phys_jump_addr =
+				    dev->_dma_phys_start_addr_ch2 +
+				    odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram_ch2(dev,
+						dev->_dma_virt_start_addr_ch2,
+						TOP_OFFSET, line_size_in_bytes,
+						0x0, singlefield_lines,
+						FIFO_DISABLE, ODD_FIELD);
+
+			       /* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	}
+
+	if (dev->_file_status_ch2 == END_OF_FILE) {
+		pr_info("EOF Channel 2 Framecount = %d\n",
+			dev->_frame_count_ch2);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status) {
+		handled =
+		    cx25821_video_upstream_irq_ch2(dev, channel_num,
+						   vid_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch2(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
+					struct sram_channel *ch, int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count_ch2;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = PIXEL_ENGINE_VIP1;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC_ch2 ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/*
+	 *  set number of active pixels in each line. Default is 720
+	 * pixels in both NTSC and PAL format
+	 */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC_ch2)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+					 struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/*
+	 *  656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface
+	 * for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/*
+	 *  Set the physical start address of the RISC program in the initial
+	 *  program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
+	cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running_ch2 = 1;
+	dev->_is_first_frame_ch2 = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running_ch2) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel2_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
+	dev->_irq_queues_ch2 =
+	    create_singlethread_workqueue("cx25821_workqueue2");
+
+	if (!dev->_irq_queues_ch2) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/*
+	 * 656/VIP SRC Upstream Channel I & J and 7 -
+	 * Host Bus Interface for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = RESET_STATUS;
+	dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
+	dev->_pixel_format_ch2 = pixel_format;
+	dev->_line_size_ch2 =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size =
+	    dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename_ch2) {
+		str_length = strlen(dev->input_filename_ch2);
+		dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+
+		memcpy(dev->_filename_ch2, dev->input_filename_ch2,
+		       str_length + 1);
+	} else {
+		str_length = strlen(dev->_defaultname_ch2);
+		dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+
+		memcpy(dev->_filename_ch2, dev->_defaultname_ch2,
+		       str_length + 1);
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename_ch2, "") == 0) {
+		if (dev->_isNTSC_ch2) {
+			dev->_filename_ch2 =
+			    (dev->_pixel_format_ch2 ==
+			     PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+			    "/root/vidtest.yuv";
+		} else {
+			dev->_filename_ch2 =
+			    (dev->_pixel_format_ch2 ==
+			     PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+			    "/root/pal422.yuv";
+		}
+	}
+
+	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+						dev->_line_size_ch2, 0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
+
+	dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
+	dev->upstream_databuf_size_ch2 = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+						dev->_line_size_ch2);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,138 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE))
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.h linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.h
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/cx25821-video-upstream.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OUTPUT_FRMT_656       0
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 JUMP_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE		(2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/Kconfig linux-libre-3.2-gnu1/drivers/media/video/cx25821/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+	tristate "Conexant cx25821 support"
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEO_TVEEPROM
+	depends on RC_CORE
+	select VIDEOBUF_DVB
+	select VIDEOBUF_DMA_SG
+	select VIDEO_CX25840
+	select VIDEO_CX2341X
+	---help---
+	  This is a video4linux driver for Conexant 25821 based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821
+
+config VIDEO_CX25821_ALSA
+	tristate "Conexant 25821 DMA audio support"
+	depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio on
+	  Conexant 25821 based capture cards using ALSA.
+
+	  It only works with boards with function 01 enabled.
+	  To check if your board supports, use lspci -n.
+	  If supported, you should see 14f1:8801 or 14f1:8811
+	  PCI device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821-alsa.
+
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25821/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx25821/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx25821/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25821/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
+		       cx25821-gpio.o cx25821-medusa-video.o \
+		       cx25821-video.o cx25821-video-upstream.o \
+		       cx25821-video-upstream-ch2.o \
+		       cx25821-audio-upstream.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-audio.c linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-audio.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -480,6 +480,7 @@ void cx25840_audio_set_path(struct i2c_c
 
 static void set_volume(struct i2c_client *client, int volume)
 {
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 	int vol;
 
 	/* Convert the volume to msp3400 values (0-127) */
@@ -495,7 +496,14 @@ static void set_volume(struct i2c_client
 	}
 
 	/* PATH1_VOLUME */
-	cx25840_write(client, 0x8d4, 228 - (vol * 2));
+	if (is_cx2388x(state)) {
+		/* for cx23885 volume doesn't work,
+		 * the calculation always results in
+		 * e4 regardless.
+		 */
+		cx25840_write(client, 0x8d4, volume);
+	} else
+		cx25840_write(client, 0x8d4, 228 - (vol * 2));
 }
 
 static void set_balance(struct i2c_client *client, int balance)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-core.c linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -702,6 +702,13 @@ static void cx231xx_initialize(struct i2
 
 	/* start microcontroller */
 	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+	/* CC raw enable */
+	cx25840_write(client, 0x404, 0x0b);
+
+	/* CC on */
+	cx25840_write(client, 0x42f, 0x66);
+	cx25840_write4(client, 0x474, 0x1e1e601a);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1067,6 +1074,18 @@ static int set_input(struct i2c_client *
 		cx25840_write(client, 0x919, 0x01);
 	}
 
+	if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) ||
+		(aud_input == CX25840_AUDIO6))) {
+		/* Configure audio from LR1 or LR2 input */
+		cx25840_write4(client, 0x910, 0);
+		cx25840_write4(client, 0x8d0, 0x63073);
+	} else
+	if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
+		/* Configure audio from tuner/sif input */
+		cx25840_write4(client, 0x910, 0x12b000c9);
+		cx25840_write4(client, 0x8d0, 0x1f063870);
+	}
+
 	return 0;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-ir.c linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-ir.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx25840/cx25840-ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25840/cx25840-ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 
 #include <linux/slab.h>
 #include <linux/kfifo.h>
+#include <linux/module.h>
 #include <media/cx25840.h>
 #include <media/rc-core.h>
 
@@ -668,7 +669,7 @@ static int cx25840_ir_rx_read(struct v4l
 	u16 divider;
 	unsigned int i, n;
 	union cx25840_ir_fifo_rec *p;
-	unsigned u, v;
+	unsigned u, v, w;
 
 	if (ir_state == NULL)
 		return -ENODEV;
@@ -694,11 +695,12 @@ static int cx25840_ir_rx_read(struct v4l
 		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
 			/* Assume RTO was because of no IR light input */
 			u = 0;
-			v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
+			w = 1;
 		} else {
 			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
 			if (invert)
 				u = u ? 0 : 1;
+			w = 0;
 		}
 
 		v = (unsigned) pulse_width_count_to_ns(
@@ -709,9 +711,12 @@ static int cx25840_ir_rx_read(struct v4l
 		init_ir_raw_event(&p->ir_core_data);
 		p->ir_core_data.pulse = u;
 		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
 
-		v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s\n",
-			 v, u ? "mark" : "space");
+		v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
 	}
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx25840/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx25840/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx25840/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx25840/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,4 @@ cx25840-objs    := cx25840-core.o cx2584
 
 obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx88/cx88-core.c linux-libre-3.2-gnu1/drivers/media/video/cx88/cx88-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx88/cx88-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx88/cx88-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -636,9 +636,6 @@ int cx88_reset(struct cx88_core *core)
 	cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
 	cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
 
-	/* set default notch filter */
-	cx_andor(MO_HTOTAL, 0x1800, (HLNotchFilter4xFsc << 11));
-
 	/* Reset on-board parts */
 	cx_write(MO_SRST_IO, 0);
 	msleep(10);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx88/cx88-video.c linux-libre-3.2-gnu1/drivers/media/video/cx88/cx88-video.c
--- linux-libre-3.1-gnu1/drivers/media/video/cx88/cx88-video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx88/cx88-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -266,7 +266,7 @@ static const struct cx88_ctrl cx8800_ctl
 			.id            = V4L2_CID_BAND_STOP_FILTER,
 			.name          = "Notch filter",
 			.minimum       = 0,
-			.maximum       = 3,
+			.maximum       = 1,
 			.step          = 1,
 			.default_value = 0x0,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/cx88/Makefile linux-libre-3.2-gnu1/drivers/media/video/cx88/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/cx88/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/cx88/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx
 obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/davinci/dm355_ccdc.c linux-libre-3.2-gnu1/drivers/media/video/davinci/dm355_ccdc.c
--- linux-libre-3.1-gnu1/drivers/media/video/davinci/dm355_ccdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/davinci/dm355_ccdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/videodev2.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <media/davinci/dm355_ccdc.h>
 #include <media/davinci/vpss.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/davinci/dm644x_ccdc.c linux-libre-3.2-gnu1/drivers/media/video/davinci/dm644x_ccdc.c
--- linux-libre-3.1-gnu1/drivers/media/video/davinci/dm644x_ccdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/davinci/dm644x_ccdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/gfp.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <media/davinci/dm644x_ccdc.h>
 #include <media/davinci/vpss.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/davinci/vpbe_display.c linux-libre-3.2-gnu1/drivers/media/video/davinci/vpbe_display.c
--- linux-libre-3.1-gnu1/drivers/media/video/davinci/vpbe_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/davinci/vpbe_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@
 
 static int debug;
 
-#define VPBE_DISPLAY_SD_BUF_SIZE (720*576*2)
 #define VPBE_DEFAULT_NUM_BUFS 3
 
 module_param(debug, int, 0644);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/davinci/vpbe_osd.c linux-libre-3.2-gnu1/drivers/media/video/davinci/vpbe_osd.c
--- linux-libre-3.1-gnu1/drivers/media/video/davinci/vpbe_osd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/davinci/vpbe_osd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1162,7 +1162,7 @@ static int osd_probe(struct platform_dev
 		goto free_mem;
 	}
 	osd->osd_base_phys = res->start;
-	osd->osd_size = res->end - res->start + 1;
+	osd->osd_size = resource_size(res);
 	if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
 				MODULE_NAME)) {
 		dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-cards.c linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-cards.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-cards.c	2013-05-01 23:42:04.000000000 -0400
@@ -60,7 +60,7 @@ static unsigned int card[]     = {[0 ...
 module_param_array(card,  int, NULL, 0444);
 MODULE_PARM_DESC(card,     "card type");
 
-/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
 static unsigned long em28xx_devused;
 
 struct em28xx_hash_table {
@@ -317,6 +317,25 @@ static struct em28xx_reg_seq terratec_h5
 };
 #endif
 
+/* 2013:024f PCTV DVB-S2 Stick 460e
+ * GPIO_0 - POWER_ON
+ * GPIO_1 - BOOST
+ * GPIO_2 - VUV_LNB (red LED)
+ * GPIO_3 - EXT_12V
+ * GPIO_4 - INT_DEM (DEMOD GPIO_0)
+ * GPIO_5 - INT_LNB
+ * GPIO_6 - RESET_DEM
+ * GPIO_7 - LED (green LED)
+ */
+static struct em28xx_reg_seq pctv_460e[] = {
+	{EM2874_R80_GPIO, 0x01, 0xff,  50},
+	{0x0d,            0xff, 0xff,  50},
+	{EM2874_R80_GPIO, 0x41, 0xff,  50}, /* GPIO_6=1 */
+	{0x0d,            0x42, 0xff,  50},
+	{EM2874_R80_GPIO, 0x61, 0xff,  50}, /* GPIO_5=1 */
+	{             -1,   -1,   -1,  -1},
+};
+
 /*
  *  Board definitions
  */
@@ -1810,6 +1829,17 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
 	},
+	/* 2013:024f PCTV DVB-S2 Stick 460e
+	 * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+	[EM28174_BOARD_PCTV_460E] = {
+		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+			EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+		.name          = "PCTV DVB-S2 Stick (460e)",
+		.tuner_type    = TUNER_ABSENT,
+		.tuner_gpio    = pctv_460e,
+		.has_dvb       = 1,
+		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+	},
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -1893,6 +1923,8 @@ struct usb_device_id em28xx_id_table[] =
 			.driver_info = EM2860_BOARD_TERRATEC_AV350 },
 	{ USB_DEVICE(0x0ccd, 0x0096),
 			.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+	{ USB_DEVICE(0x0ccd, 0x10AF),
+			.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
 	{ USB_DEVICE(0x0fd9, 0x0033),
 			.driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
 	{ USB_DEVICE(0x185b, 0x2870),
@@ -1941,6 +1973,8 @@ struct usb_device_id em28xx_id_table[] =
 			.driver_info = EM2870_BOARD_KWORLD_A340 },
 	{ USB_DEVICE(0x2013, 0x024f),
 			.driver_info = EM28174_BOARD_PCTV_290E },
+	{ USB_DEVICE(0x2013, 0x024c),
+			.driver_info = EM28174_BOARD_PCTV_460E },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2768,9 +2802,9 @@ static void flush_request_modules(struct
 #endif /* CONFIG_MODULES */
 
 /*
- * em28xx_realease_resources()
+ * em28xx_release_resources()
  * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
+ * called when the device gets disconnected or at module unload
 */
 void em28xx_release_resources(struct em28xx *dev)
 {
@@ -2784,8 +2818,6 @@ void em28xx_release_resources(struct em2
 
 	em28xx_release_analog_resources(dev);
 
-	em28xx_remove_from_devlist(dev);
-
 	em28xx_i2c_unregister(dev);
 
 	v4l2_device_unregister(&dev->v4l2_dev);
@@ -2793,7 +2825,7 @@ void em28xx_release_resources(struct em2
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
-	em28xx_devused &= ~(1 << dev->devno);
+	clear_bit(dev->devno, &em28xx_devused);
 };
 
 /*
@@ -2806,7 +2838,6 @@ static int em28xx_init_dev(struct em28xx
 {
 	struct em28xx *dev = *devhandle;
 	int retval;
-	int errCode;
 
 	dev->udev = udev;
 	mutex_init(&dev->ctrl_urb_lock);
@@ -2883,10 +2914,9 @@ static int em28xx_init_dev(struct em28xx
 	}
 
 	if (dev->is_audio_only) {
-		errCode = em28xx_audio_setup(dev);
-		if (errCode)
+		retval = em28xx_audio_setup(dev);
+		if (retval)
 			return -ENODEV;
-		em28xx_add_into_devlist(dev);
 		em28xx_init_extension(dev);
 
 		return 0;
@@ -2903,7 +2933,7 @@ static int em28xx_init_dev(struct em28xx
 		/* Resets I2C speed */
 		em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
 		if (retval < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req failed!"
+			em28xx_errdev("%s: em28xx_write_reg failed!"
 				      " retval [%d]\n",
 				      __func__, retval);
 			return retval;
@@ -2917,12 +2947,11 @@ static int em28xx_init_dev(struct em28xx
 	}
 
 	/* register i2c bus */
-	errCode = em28xx_i2c_register(dev);
-	if (errCode < 0) {
-		v4l2_device_unregister(&dev->v4l2_dev);
-		em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
-			__func__, errCode);
-		return errCode;
+	retval = em28xx_i2c_register(dev);
+	if (retval < 0) {
+		em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+			__func__, retval);
+		goto unregister_dev;
 	}
 
 	/*
@@ -2936,11 +2965,11 @@ static int em28xx_init_dev(struct em28xx
 	em28xx_card_setup(dev);
 
 	/* Configure audio */
-	errCode = em28xx_audio_setup(dev);
-	if (errCode < 0) {
-		v4l2_device_unregister(&dev->v4l2_dev);
-		em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
-			__func__, errCode);
+	retval = em28xx_audio_setup(dev);
+	if (retval < 0) {
+		em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
+			__func__, retval);
+		goto fail;
 	}
 
 	/* wake i2c devices */
@@ -2954,41 +2983,41 @@ static int em28xx_init_dev(struct em28xx
 
 	if (dev->board.has_msp34xx) {
 		/* Send a reset to other chips via gpio */
-		errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
-		if (errCode < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req - "
-				      "msp34xx(1) failed! errCode [%d]\n",
-				      __func__, errCode);
-			return errCode;
+		retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+		if (retval < 0) {
+			em28xx_errdev("%s: em28xx_write_reg - "
+				      "msp34xx(1) failed! error [%d]\n",
+				      __func__, retval);
+			goto fail;
 		}
 		msleep(3);
 
-		errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
-		if (errCode < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req - "
-				      "msp34xx(2) failed! errCode [%d]\n",
-				      __func__, errCode);
-			return errCode;
+		retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+		if (retval < 0) {
+			em28xx_errdev("%s: em28xx_write_reg - "
+				      "msp34xx(2) failed! error [%d]\n",
+				      __func__, retval);
+			goto fail;
 		}
 		msleep(3);
 	}
 
-	em28xx_add_into_devlist(dev);
-
 	retval = em28xx_register_analog_devices(dev);
 	if (retval < 0) {
-		em28xx_release_resources(dev);
-		goto fail_reg_devices;
+		goto fail;
 	}
 
-	em28xx_init_extension(dev);
-
 	/* Save some power by putting tuner to sleep */
 	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
 
 	return 0;
 
-fail_reg_devices:
+fail:
+	em28xx_i2c_unregister(dev);
+
+unregister_dev:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
 	return retval;
 }
 
@@ -3015,8 +3044,16 @@ static int em28xx_usb_probe(struct usb_i
 	udev = usb_get_dev(interface_to_usbdev(interface));
 
 	/* Check to see next free device and mark as used */
-	nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
-	em28xx_devused |= 1<<nr;
+	do {
+		nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+		if (nr >= EM28XX_MAXBOARDS) {
+			/* No free device slots */
+			printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+					EM28XX_MAXBOARDS);
+			retval = -ENOMEM;
+			goto err_no_slot;
+		}
+	} while (test_and_set_bit(nr, &em28xx_devused));
 
 	/* Don't register audio interfaces */
 	if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
@@ -3027,7 +3064,6 @@ static int em28xx_usb_probe(struct usb_i
 			ifnum,
 			interface->altsetting[0].desc.bInterfaceClass);
 
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENODEV;
 		goto err;
 	}
@@ -3076,7 +3112,6 @@ static int em28xx_usb_probe(struct usb_i
 				em28xx_err(DRIVER_NAME " This is an anciliary "
 					"interface not used by the driver\n");
 
-				em28xx_devused &= ~(1<<nr);
 				retval = -ENODEV;
 				goto err;
 			}
@@ -3132,29 +3167,19 @@ static int em28xx_usb_probe(struct usb_i
 		printk(DRIVER_NAME ": Device initialization failed.\n");
 		printk(DRIVER_NAME ": Device must be connected to a high-speed"
 		       " USB 2.0 port.\n");
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENODEV;
 		goto err;
 	}
 
-	if (nr >= EM28XX_MAXBOARDS) {
-		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
-				EM28XX_MAXBOARDS);
-		em28xx_devused &= ~(1<<nr);
-		retval = -ENOMEM;
-		goto err;
-	}
-
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		em28xx_err(DRIVER_NAME ": out of memory!\n");
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENOMEM;
 		goto err;
 	}
 
-	snprintf(dev->name, 29, "em28xx #%d", nr);
+	snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
 	dev->devno = nr;
 	dev->model = id->driver_info;
 	dev->alt   = -1;
@@ -3177,7 +3202,6 @@ static int em28xx_usb_probe(struct usb_i
 
 	if (dev->alt_max_pkt_size == NULL) {
 		em28xx_errdev("out of memory!\n");
-		em28xx_devused &= ~(1<<nr);
 		kfree(dev);
 		retval = -ENOMEM;
 		goto err;
@@ -3204,8 +3228,8 @@ static int em28xx_usb_probe(struct usb_i
 	mutex_lock(&dev->lock);
 	retval = em28xx_init_dev(&dev, udev, interface, nr);
 	if (retval) {
-		em28xx_devused &= ~(1<<dev->devno);
 		mutex_unlock(&dev->lock);
+		kfree(dev->alt_max_pkt_size);
 		kfree(dev);
 		goto err;
 	}
@@ -3217,15 +3241,26 @@ static int em28xx_usb_probe(struct usb_i
 	 */
 	mutex_unlock(&dev->lock);
 
+	/*
+	 * These extensions can be modules. If the modules are already
+	 * loaded then we can initialise the device now, otherwise we
+	 * will initialise it when the modules load instead.
+	 */
+	em28xx_init_extension(dev);
+
 	return 0;
 
 err:
+	clear_bit(nr, &em28xx_devused);
+
+err_no_slot:
+	usb_put_dev(udev);
 	return retval;
 }
 
 /*
  * em28xx_usb_disconnect()
- * called when the device gets diconencted
+ * called when the device gets disconnected
  * video device will be unregistered on v4l2_close in case it is still open
  */
 static void em28xx_usb_disconnect(struct usb_interface *interface)
@@ -3273,10 +3308,10 @@ static void em28xx_usb_disconnect(struct
 		em28xx_release_resources(dev);
 	}
 
-	em28xx_close_extension(dev);
-
 	mutex_unlock(&dev->lock);
 
+	em28xx_close_extension(dev);
+
 	if (!dev->users) {
 		kfree(dev->alt_max_pkt_size);
 		kfree(dev);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-core.c linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1184,25 +1184,6 @@ static LIST_HEAD(em28xx_devlist);
 static DEFINE_MUTEX(em28xx_devlist_mutex);
 
 /*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void em28xx_remove_from_devlist(struct em28xx *dev)
-{
-	mutex_lock(&em28xx_devlist_mutex);
-	list_del(&dev->devlist);
-	mutex_unlock(&em28xx_devlist_mutex);
-};
-
-void em28xx_add_into_devlist(struct em28xx *dev)
-{
-	mutex_lock(&em28xx_devlist_mutex);
-	list_add_tail(&dev->devlist, &em28xx_devlist);
-	mutex_unlock(&em28xx_devlist_mutex);
-};
-
-/*
  * Extension interface
  */
 
@@ -1217,8 +1198,8 @@ int em28xx_register_extension(struct em2
 	list_for_each_entry(dev, &em28xx_devlist, devlist) {
 		ops->init(dev);
 	}
-	printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
 	mutex_unlock(&em28xx_devlist_mutex);
+	printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
 	return 0;
 }
 EXPORT_SYMBOL(em28xx_register_extension);
@@ -1231,36 +1212,34 @@ void em28xx_unregister_extension(struct
 	list_for_each_entry(dev, &em28xx_devlist, devlist) {
 		ops->fini(dev);
 	}
-	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
 	list_del(&ops->next);
 	mutex_unlock(&em28xx_devlist_mutex);
+	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
 }
 EXPORT_SYMBOL(em28xx_unregister_extension);
 
 void em28xx_init_extension(struct em28xx *dev)
 {
-	struct em28xx_ops *ops = NULL;
+	const struct em28xx_ops *ops = NULL;
 
 	mutex_lock(&em28xx_devlist_mutex);
-	if (!list_empty(&em28xx_extension_devlist)) {
-		list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-			if (ops->init)
-				ops->init(dev);
-		}
+	list_add_tail(&dev->devlist, &em28xx_devlist);
+	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+		if (ops->init)
+			ops->init(dev);
 	}
 	mutex_unlock(&em28xx_devlist_mutex);
 }
 
 void em28xx_close_extension(struct em28xx *dev)
 {
-	struct em28xx_ops *ops = NULL;
+	const struct em28xx_ops *ops = NULL;
 
 	mutex_lock(&em28xx_devlist_mutex);
-	if (!list_empty(&em28xx_extension_devlist)) {
-		list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-			if (ops->fini)
-				ops->fini(dev);
-		}
+	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+		if (ops->fini)
+			ops->fini(dev);
 	}
+	list_del(&dev->devlist);
 	mutex_unlock(&em28xx_devlist_mutex);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-dvb.c linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-dvb.c
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-dvb.c	2013-05-02 01:36:04.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-dvb.c	2013-05-01 23:44:04.000000000 -0400
@@ -42,6 +42,8 @@
 #include "cxd2820r.h"
 #include "tda18271c2dd.h"
 #include "drxk.h"
+#include "tda10071.h"
+#include "a8293.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -122,7 +124,7 @@ static inline void print_err_status(stru
 	}
 }
 
-static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
 {
 	int i;
 
@@ -155,7 +157,7 @@ static inline int dvb_isoc_copy(struct e
 	return 0;
 }
 
-static int start_streaming(struct em28xx_dvb *dvb)
+static int em28xx_start_streaming(struct em28xx_dvb *dvb)
 {
 	int rc;
 	struct em28xx *dev = dvb->adapter.priv;
@@ -175,10 +177,10 @@ static int start_streaming(struct em28xx
 
 	return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
 				EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
-				dvb_isoc_copy);
+				em28xx_dvb_isoc_copy);
 }
 
-static int stop_streaming(struct em28xx_dvb *dvb)
+static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
 {
 	struct em28xx *dev = dvb->adapter.priv;
 
@@ -189,7 +191,7 @@ static int stop_streaming(struct em28xx_
 	return 0;
 }
 
-static int start_feed(struct dvb_demux_feed *feed)
+static int em28xx_start_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux  = feed->demux;
 	struct em28xx_dvb *dvb = demux->priv;
@@ -203,7 +205,7 @@ static int start_feed(struct dvb_demux_f
 	rc = dvb->nfeeds;
 
 	if (dvb->nfeeds == 1) {
-		ret = start_streaming(dvb);
+		ret = em28xx_start_streaming(dvb);
 		if (ret < 0)
 			rc = ret;
 	}
@@ -212,7 +214,7 @@ static int start_feed(struct dvb_demux_f
 	return rc;
 }
 
-static int stop_feed(struct dvb_demux_feed *feed)
+static int em28xx_stop_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux  = feed->demux;
 	struct em28xx_dvb *dvb = demux->priv;
@@ -222,7 +224,7 @@ static int stop_feed(struct dvb_demux_fe
 	dvb->nfeeds--;
 
 	if (0 == dvb->nfeeds)
-		err = stop_streaming(dvb);
+		err = em28xx_stop_streaming(dvb);
 
 	mutex_unlock(&dvb->lock);
 	return err;
@@ -380,7 +382,7 @@ static void terratec_h5_init(struct em28
 	em28xx_gpio_set(dev, terratec_h5_end);
 };
 
-static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
 {
 	/* Values extracted from a USB trace of the Terratec Windows driver */
 	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
@@ -412,7 +414,7 @@ static struct mt352_config terratec_xs_m
 	.demod_address = (0x1e >> 1),
 	.no_tuner = 1,
 	.if2 = 45600,
-	.demod_init = mt352_terratec_xs_init,
+	.demod_init = em28xx_mt352_terratec_xs_init,
 };
 
 static struct tda10023_config em28xx_tda10023_config = {
@@ -438,11 +440,25 @@ static struct cxd2820r_config em28xx_cxd
 
 static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
 	.output_opt = TDA18271_OUTPUT_LT_OFF,
+	.gate = TDA18271_GATE_DIGITAL,
+};
+
+static const struct tda10071_config em28xx_tda10071_config = {
+	.i2c_address = 0x55, /* (0xaa >> 1) */
+	.i2c_wr_max = 64,
+	.ts_mode = TDA10071_TS_SERIAL,
+	.spec_inv = 0,
+	.xtal = 40444000, /* 40.444 MHz */
+	.pll_multiplier = 20,
+};
+
+static const struct a8293_config em28xx_a8293_config = {
+	.i2c_addr = 0x08, /* (0x10 >> 1) */
 };
 
 /* ------------------------------------------------------------------ */
 
-static int attach_xc3028(u8 addr, struct em28xx *dev)
+static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
 {
 	struct dvb_frontend *fe;
 	struct xc2028_config cfg;
@@ -472,10 +488,8 @@ static int attach_xc3028(u8 addr, struct
 
 /* ------------------------------------------------------------------ */
 
-static int register_dvb(struct em28xx_dvb *dvb,
-		 struct module *module,
-		 struct em28xx *dev,
-		 struct device *device)
+static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
+			       struct em28xx *dev, struct device *device)
 {
 	int result;
 
@@ -522,8 +536,8 @@ static int register_dvb(struct em28xx_dv
 	dvb->demux.priv       = dvb;
 	dvb->demux.filternum  = 256;
 	dvb->demux.feednum    = 256;
-	dvb->demux.start_feed = start_feed;
-	dvb->demux.stop_feed  = stop_feed;
+	dvb->demux.start_feed = em28xx_start_feed;
+	dvb->demux.stop_feed  = em28xx_stop_feed;
 
 	result = dvb_dmx_init(&dvb->demux);
 	if (result < 0) {
@@ -591,7 +605,7 @@ fail_adapter:
 	return result;
 }
 
-static void unregister_dvb(struct em28xx_dvb *dvb)
+static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
 {
 	dvb_net_release(&dvb->net);
 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
@@ -607,9 +621,9 @@ static void unregister_dvb(struct em28xx
 	dvb_unregister_adapter(&dvb->adapter);
 }
 
-static int dvb_init(struct em28xx *dev)
+static int em28xx_dvb_init(struct em28xx *dev)
 {
-	int result = 0;
+	int result = 0, mfe_shared = 0;
 	struct em28xx_dvb *dvb;
 
 	if (!dev->board.has_dvb) {
@@ -648,7 +662,7 @@ static int dvb_init(struct em28xx *dev)
 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
 					   &em2880_lgdt3303_dev,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -657,7 +671,7 @@ static int dvb_init(struct em28xx *dev)
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_with_xc3028,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -668,7 +682,7 @@ static int dvb_init(struct em28xx *dev)
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_xc3028_no_i2c_gate,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -689,7 +703,7 @@ static int dvb_init(struct em28xx *dev)
 						   &dev->i2c_adap);
 		}
 
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -699,7 +713,7 @@ static int dvb_init(struct em28xx *dev)
 		dvb->fe[0] = dvb_attach(s5h1409_attach,
 					   &em28xx_s5h1409_with_xc3028,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -720,7 +734,7 @@ static int dvb_init(struct em28xx *dev)
 	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
 		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
 					   &dev->i2c_adap, &dev->udev->dev);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -753,11 +767,9 @@ static int dvb_init(struct em28xx *dev)
 		dvb->fe[0] = dvb_attach(cxd2820r_attach,
 			&em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
 		if (dvb->fe[0]) {
-			struct i2c_adapter *i2c_tuner;
-			i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]);
 			/* FE 0 attach tuner */
 			if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+				&dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
 				dvb_frontend_detach(dvb->fe[0]);
 				result = -EINVAL;
 				goto out_free;
@@ -768,10 +780,12 @@ static int dvb_init(struct em28xx *dev)
 			dvb->fe[1]->id = 1;
 			/* FE 1 attach tuner */
 			if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
-				i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+				&dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
 				dvb_frontend_detach(dvb->fe[1]);
 				/* leave FE 0 still active */
 			}
+
+			mfe_shared = 1;
 		}
 		break;
 	case EM2884_BOARD_TERRATEC_H5:
@@ -809,6 +823,16 @@ static int dvb_init(struct em28xx *dev)
 		       sizeof(dvb->fe[0]->ops.tuner_ops));
 
 		break;
+	case EM28174_BOARD_PCTV_460E:
+		/* attach demod */
+		dvb->fe[0] = dvb_attach(tda10071_attach,
+			&em28xx_tda10071_config, &dev->i2c_adap);
+
+		/* attach SEC */
+		if (dvb->fe[0])
+			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+				&em28xx_a8293_config);
+		break;
 	default:
 		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n");
@@ -823,11 +847,14 @@ static int dvb_init(struct em28xx *dev)
 	dvb->fe[0]->callback = em28xx_tuner_callback;
 
 	/* register everything */
-	result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 
 	if (result < 0)
 		goto out_free;
 
+	/* MFE lock */
+	dvb->adapter.mfe_shared = mfe_shared;
+
 	em28xx_info("Successfully loaded em28xx-dvb\n");
 ret:
 	em28xx_set_mode(dev, EM28XX_SUSPEND);
@@ -840,7 +867,14 @@ out_free:
 	goto ret;
 }
 
-static int dvb_fini(struct em28xx *dev)
+static inline void prevent_sleep(struct dvb_frontend_ops *ops)
+{
+	ops->set_voltage = NULL;
+	ops->sleep = NULL;
+	ops->tuner_ops.sleep = NULL;
+}
+
+static int em28xx_dvb_fini(struct em28xx *dev)
 {
 	if (!dev->board.has_dvb) {
 		/* This device does not support the extension */
@@ -848,8 +882,19 @@ static int dvb_fini(struct em28xx *dev)
 	}
 
 	if (dev->dvb) {
-		unregister_dvb(dev->dvb);
-		kfree(dev->dvb);
+		struct em28xx_dvb *dvb = dev->dvb;
+
+		if (dev->state & DEV_DISCONNECTED) {
+			/* We cannot tell the device to sleep
+			 * once it has been unplugged. */
+			if (dvb->fe[0])
+				prevent_sleep(&dvb->fe[0]->ops);
+			if (dvb->fe[1])
+				prevent_sleep(&dvb->fe[1]->ops);
+		}
+
+		em28xx_unregister_dvb(dvb);
+		kfree(dvb);
 		dev->dvb = NULL;
 	}
 
@@ -859,8 +904,8 @@ static int dvb_fini(struct em28xx *dev)
 static struct em28xx_ops dvb_ops = {
 	.id   = EM28XX_DVB,
 	.name = "Em28xx dvb Extension",
-	.init = dvb_init,
-	.fini = dvb_fini,
+	.init = em28xx_dvb_init,
+	.fini = em28xx_dvb_fini,
 };
 
 static int __init em28xx_dvb_register(void)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx.h linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx.h
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -120,6 +120,7 @@
 #define EM2874_BOARD_LEADERSHIP_ISDBT		  77
 #define EM28174_BOARD_PCTV_290E                   78
 #define EM2884_BOARD_TERRATEC_H5		  79
+#define EM28174_BOARD_PCTV_460E                   80
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -677,8 +678,6 @@ int em28xx_isoc_dvb_max_packetsize(struc
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
 int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);
-void em28xx_remove_from_devlist(struct em28xx *dev);
-void em28xx_add_into_devlist(struct em28xx *dev);
 int em28xx_register_extension(struct em28xx_ops *dev);
 void em28xx_unregister_extension(struct em28xx_ops *dev);
 void em28xx_init_extension(struct em28xx *dev);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-input.c linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-input.c
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -463,11 +463,11 @@ int em28xx_ir_fini(struct em28xx *dev)
 	if (!ir)
 		return 0;
 
-	em28xx_ir_stop(ir->rc);
-	rc_unregister_device(ir->rc);
-	kfree(ir);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	/* done */
+	kfree(ir);
 	dev->ir = NULL;
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-video.c linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-video.c
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/em28xx-video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/em28xx-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -1156,6 +1156,21 @@ static int vidioc_g_std(struct file *fil
 	return 0;
 }
 
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	struct em28xx_fh   *fh  = priv;
+	struct em28xx      *dev = fh->dev;
+	int                rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+
+	return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
 	struct em28xx_fh   *fh  = priv;
@@ -1787,6 +1802,45 @@ static int vidioc_enum_fmt_vid_cap(struc
 	return 0;
 }
 
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct em28xx_fh      *fh  = priv;
+	struct em28xx         *dev = fh->dev;
+	struct em28xx_fmt     *fmt;
+	unsigned int	      maxw = norm_maxw(dev);
+	unsigned int	      maxh = norm_maxh(dev);
+
+	fmt = format_by_fourcc(fsize->pixel_format);
+	if (!fmt) {
+		em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+				fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	if (dev->board.is_em2800) {
+		if (fsize->index > 1)
+			return -EINVAL;
+		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+		fsize->discrete.width = maxw / (1 + fsize->index);
+		fsize->discrete.height = maxh / (1 + fsize->index);
+		return 0;
+	}
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	/* Report a continuous range */
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = 48;
+	fsize->stepwise.min_height = 32;
+	fsize->stepwise.max_width = maxw;
+	fsize->stepwise.max_height = maxh;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.step_height = 1;
+	return 0;
+}
+
 /* Sliced VBI ioctls */
 static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
@@ -2200,6 +2254,7 @@ static int em28xx_v4l2_close(struct file
 		   free the remaining resources */
 		if (dev->state & DEV_DISCONNECTED) {
 			em28xx_release_resources(dev);
+			kfree(dev->alt_max_pkt_size);
 			kfree(dev);
 			return 0;
 		}
@@ -2340,10 +2395,10 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
 	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
 	.vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
+	.vidioc_enum_framesizes     = vidioc_enum_framesizes,
 	.vidioc_g_audio             = vidioc_g_audio,
 	.vidioc_s_audio             = vidioc_s_audio,
 	.vidioc_cropcap             = vidioc_cropcap,
-
 	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
 	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
 	.vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,
@@ -2353,6 +2408,7 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_qbuf                = vidioc_qbuf,
 	.vidioc_dqbuf               = vidioc_dqbuf,
 	.vidioc_g_std               = vidioc_g_std,
+	.vidioc_querystd            = vidioc_querystd,
 	.vidioc_s_std               = vidioc_s_std,
 	.vidioc_g_parm		    = vidioc_g_parm,
 	.vidioc_s_parm		    = vidioc_s_parm,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/Kconfig linux-libre-3.2-gnu1/drivers/media/video/em28xx/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@ config VIDEO_EM28XX_DVB
 	select DVB_CXD2820R if !DVB_FE_CUSTOMISE
 	select DVB_DRXK if !DVB_FE_CUSTOMISE
 	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+	select DVB_TDA10071 if !DVB_FE_CUSTOMISE
+	select DVB_A8293 if !DVB_FE_CUSTOMISE
 	select VIDEOBUF_DVB
 	---help---
 	  This adds support for DVB cards based on the
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/em28xx/Makefile linux-libre-3.2-gnu1/drivers/media/video/em28xx/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/em28xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/em28xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,8 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
 obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
 obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251_core.c linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251_core.c
--- linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251.h linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251.h
--- linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251.h	2012-01-04 18:55:44.000000000 -0500
@@ -165,45 +165,49 @@ et61x251_attach_sensor(struct et61x251_d
 #undef DBG
 #undef KDBG
 #ifdef ET61X251_DEBUG
-#	define DBG(level, fmt, args...)                                       \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1)                                             \
-			dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
-		else if ((level) == 2)                                        \
-			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
-		else if ((level) >= 3)                                        \
-			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-				 __FILE__, __func__, __LINE__ , ## args); \
-	}                                                                     \
+#define DBG(level, fmt, ...)						\
+do {									\
+	if (debug >= (level)) {						\
+		if ((level) == 1)					\
+			dev_err(&cam->usbdev->dev, fmt "\n",		\
+				##__VA_ARGS__);				\
+		else if ((level) == 2)					\
+			dev_info(&cam->usbdev->dev, fmt "\n",		\
+				 ##__VA_ARGS__);			\
+		else if ((level) >= 3)					\
+			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+				 __FILE__, __func__, __LINE__,		\
+				 ##__VA_ARGS__);			\
+	}								\
 } while (0)
-#	define KDBG(level, fmt, args...)                                      \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1 || (level) == 2)                             \
-			pr_info("et61x251: " fmt "\n", ## args);              \
-		else if ((level) == 3)                                        \
-			pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-				 __func__, __LINE__ , ## args);           \
-	}                                                                     \
+#define KDBG(level, fmt, ...)						\
+do {									\
+	if (debug >= (level)) {						\
+		if ((level) == 1 || (level) == 2)			\
+			pr_info(fmt "\n", ##__VA_ARGS__);		\
+		else if ((level) == 3)					\
+			pr_debug("[%s:%s:%d] " fmt "\n",		\
+				 __FILE__,  __func__, __LINE__,		\
+				 ##__VA_ARGS__);			\
+	}								\
 } while (0)
-#	define V4LDBG(level, name, cmd)                                       \
-do {                                                                          \
-	if (debug >= (level))                                                 \
-		v4l_print_ioctl(name, cmd);                                   \
+#define V4LDBG(level, name, cmd)					\
+do {									\
+	if (debug >= (level))						\
+		v4l_print_ioctl(name, cmd);				\
 } while (0)
 #else
-#	define DBG(level, fmt, args...) do {;} while(0)
-#	define KDBG(level, fmt, args...) do {;} while(0)
-#	define V4LDBG(level, name, cmd) do {;} while(0)
+#define DBG(level, fmt, ...) do {;} while(0)
+#define KDBG(level, fmt, ...) do {;} while(0)
+#define V4LDBG(level, name, cmd) do {;} while(0)
 #endif
 
 #undef PDBG
-#define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
-	 __LINE__ , ## args)
+#define PDBG(fmt, ...)							\
+	dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",		\
+		 __FILE__, __func__, __LINE__, ##__VA_ARGS__)
 
 #undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+#define PDBGG(fmt, args...) do {;} while (0) /* placeholder */
 
 #endif /* _ET61X251_H_ */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251_tas5130d1b.c linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251_tas5130d1b.c
--- linux-libre-3.1-gnu1/drivers/media/video/et61x251/et61x251_tas5130d1b.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/et61x251/et61x251_tas5130d1b.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "et61x251_sensor.h"
 
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/benq.c linux-libre-3.2-gnu1/drivers/media/video/gspca/benq.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/benq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/benq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "benq"
 
 #include "gspca.h"
@@ -62,7 +64,7 @@ static void reg_w(struct gspca_dev *gspc
 			0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -84,20 +86,6 @@ static int sd_init(struct gspca_dev *gsp
 	return 0;
 }
 
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-	int ret;
-
-	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
-		gspca_dev->nbalt - 1);
-	if (ret < 0) {
-		err("usb_set_interface failed");
-		return ret;
-	}
-/*	reg_w(gspca_dev, 0x0003, 0x0002); */
-	return 0;
-}
-
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
@@ -113,7 +101,7 @@ static int sd_start(struct gspca_dev *gs
 	for (n = 0; n < 4; n++) {
 		urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -123,7 +111,7 @@ static int sd_start(struct gspca_dev *gs
 						&urb->transfer_dma);
 
 		if (urb->transfer_buffer == NULL) {
-			err("usb_alloc_coherent failed");
+			pr_err("usb_alloc_coherent failed\n");
 			return -ENOMEM;
 		}
 		urb->dev = gspca_dev->dev;
@@ -181,7 +169,7 @@ static void sd_isoc_irq(struct urb *urb)
 		if (gspca_dev->frozen)
 			return;
 #endif
-		err("urb status: %d", urb->status);
+		pr_err("urb status: %d\n", urb->status);
 		return;
 	}
 
@@ -209,7 +197,7 @@ static void sd_isoc_irq(struct urb *urb)
 		if (st == 0)
 			st = urb->iso_frame_desc[i].status;
 		if (st) {
-			err("ISOC data error: [%d] status=%d",
+			pr_err("ISOC data error: [%d] status=%d\n",
 				i, st);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
@@ -256,10 +244,10 @@ static void sd_isoc_irq(struct urb *urb)
 	/* resubmit the URBs */
 	st = usb_submit_urb(urb0, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb(0) ret %d", st);
+		pr_err("usb_submit_urb(0) ret %d\n", st);
 	st = usb_submit_urb(urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb() ret %d", st);
+		pr_err("usb_submit_urb() ret %d\n", st);
 }
 
 /* sub-driver description */
@@ -269,7 +257,6 @@ static const struct sd_desc sd_desc = {
 	.nctrls = ARRAY_SIZE(sd_ctrls),
 	.config = sd_config,
 	.init = sd_init,
-	.isoc_init = sd_isoc_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.pkt_scan = sd_pkt_scan,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/conex.c linux-libre-3.2-gnu1/drivers/media/video/gspca/conex.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/conex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/conex.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "conex"
 
 #include "gspca.h"
@@ -129,7 +131,7 @@ static void reg_r(struct gspca_dev *gspc
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -169,7 +171,7 @@ static void reg_w(struct gspca_dev *gspc
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/cpia1.c linux-libre-3.2-gnu1/drivers/media/video/gspca/cpia1.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/cpia1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/cpia1.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "cpia1"
 
 #include <linux/input.h>
@@ -550,8 +552,7 @@ retry:
 			      gspca_dev->usb_buf, databytes, 1000);
 
 	if (ret < 0)
-		err("usb_control_msg %02x, error %d", command[1],
-		       ret);
+		pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
 
 	if (ret == -EPIPE && retries > 0) {
 		retries--;
@@ -1279,7 +1280,7 @@ static void monitor_exposure(struct gspc
 	cmd[7] = 0;
 	ret = cpia_usb_transferCmd(gspca_dev, cmd);
 	if (ret) {
-		err("ReadVPRegs(30,4,9,8) - failed: %d", ret);
+		pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
 		return;
 	}
 	exp_acc = gspca_dev->usb_buf[0];
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/etoms.c linux-libre-3.2-gnu1/drivers/media/video/gspca/etoms.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/etoms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/etoms.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "etoms"
 
 #include "gspca.h"
@@ -236,7 +238,7 @@ static void reg_r(struct gspca_dev *gspc
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -274,7 +276,7 @@ static void reg_w(struct gspca_dev *gspc
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/finepix.c linux-libre-3.2-gnu1/drivers/media/video/gspca/finepix.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/finepix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/finepix.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "finepix"
 
 #include "gspca.h"
@@ -182,7 +184,7 @@ static int sd_start(struct gspca_dev *gs
 	/* Init the device */
 	ret = command(gspca_dev, 0);
 	if (ret < 0) {
-		err("init failed %d", ret);
+		pr_err("init failed %d\n", ret);
 		return ret;
 	}
 
@@ -194,14 +196,14 @@ static int sd_start(struct gspca_dev *gs
 			FPIX_MAX_TRANSFER, &len,
 			FPIX_TIMEOUT);
 	if (ret < 0) {
-		err("usb_bulk_msg failed %d", ret);
+		pr_err("usb_bulk_msg failed %d\n", ret);
 		return ret;
 	}
 
 	/* Request a frame, but don't read it */
 	ret = command(gspca_dev, 1);
 	if (ret < 0) {
-		err("frame request failed %d", ret);
+		pr_err("frame request failed %d\n", ret);
 		return ret;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/gl860/gl860.c linux-libre-3.2-gnu1/drivers/media/video/gspca/gl860/gl860.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/gl860/gl860.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/gl860/gl860.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,9 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "gspca.h"
 #include "gl860.h"
 
@@ -572,9 +575,8 @@ int gl860_RTx(struct gspca_dev *gspca_de
 	}
 
 	if (r < 0)
-		err("ctrl transfer failed %4d "
-			"[p%02x r%d v%04x i%04x len%d]",
-			r, pref, req, val, index, len);
+		pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+		       r, pref, req, val, index, len);
 	else if (len > 1 && r < len)
 		PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/gl860/Makefile linux-libre-3.2-gnu1/drivers/media/video/gspca/gl860/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/gl860/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/gl860/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \
 		    gl860-ov9655.o \
 		    gl860-mi2020.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/gspca.c linux-libre-3.2-gnu1/drivers/media/video/gspca/gspca.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/gspca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/gspca.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,9 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define MODULE_NAME "gspca"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define GSPCA_VERSION	"2.14.0"
 
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -50,12 +52,10 @@
 #error "DEF_NURBS too big"
 #endif
 
-#define DRIVER_VERSION_NUMBER	"2.13.0"
-
 MODULE_AUTHOR("Jean-FranÃ§ois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION_NUMBER);
+MODULE_VERSION(GSPCA_VERSION);
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -148,7 +148,7 @@ static void int_irq(struct urb *urb)
 	if (ret == 0) {
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret < 0)
-			err("Resubmit URB failed with error %i", ret);
+			pr_err("Resubmit URB failed with error %i\n", ret);
 	}
 }
 
@@ -177,8 +177,8 @@ static int gspca_input_connect(struct gs
 
 		err = input_register_device(input_dev);
 		if (err) {
-			err("Input device registration failed with error %i",
-				err);
+			pr_err("Input device registration failed with error %i\n",
+			       err);
 			input_dev->dev.parent = NULL;
 			input_free_device(input_dev);
 		} else {
@@ -323,8 +323,8 @@ static void fill_frame(struct gspca_dev
 		/* check the packet status and length */
 		st = urb->iso_frame_desc[i].status;
 		if (st) {
-			err("ISOC data error: [%d] len=%d, status=%d",
-				i, len, st);
+			pr_err("ISOC data error: [%d] len=%d, status=%d\n",
+			       i, len, st);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
 		}
@@ -346,7 +346,7 @@ resubmit:
 	/* resubmit the URB */
 	st = usb_submit_urb(urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb() ret %d", st);
+		pr_err("usb_submit_urb() ret %d\n", st);
 }
 
 /*
@@ -400,7 +400,7 @@ resubmit:
 	if (gspca_dev->cam.bulk_nurbs != 0) {
 		st = usb_submit_urb(urb, GFP_ATOMIC);
 		if (st < 0)
-			err("usb_submit_urb() ret %d", st);
+			pr_err("usb_submit_urb() ret %d\n", st);
 	}
 }
 
@@ -464,7 +464,7 @@ void gspca_frame_add(struct gspca_dev *g
 		} else {
 /* !! image is NULL only when last pkt is LAST or DISCARD
 			if (gspca_dev->image == NULL) {
-				err("gspca_frame_add() image == NULL");
+				pr_err("gspca_frame_add() image == NULL\n");
 				return;
 			}
  */
@@ -497,19 +497,6 @@ void gspca_frame_add(struct gspca_dev *g
 }
 EXPORT_SYMBOL(gspca_frame_add);
 
-static int gspca_is_compressed(__u32 format)
-{
-	switch (format) {
-	case V4L2_PIX_FMT_MJPEG:
-	case V4L2_PIX_FMT_JPEG:
-	case V4L2_PIX_FMT_SPCA561:
-	case V4L2_PIX_FMT_PAC207:
-	case V4L2_PIX_FMT_MR97310A:
-		return 1;
-	}
-	return 0;
-}
-
 static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
 			enum v4l2_memory memory, unsigned int count)
 {
@@ -525,7 +512,7 @@ static int frame_alloc(struct gspca_dev
 		count = GSPCA_MAX_FRAMES - 1;
 	gspca_dev->frbuf = vmalloc_32(frsz * count);
 	if (!gspca_dev->frbuf) {
-		err("frame alloc failed");
+		pr_err("frame alloc failed\n");
 		return -ENOMEM;
 	}
 	gspca_dev->capt_file = file;
@@ -597,7 +584,7 @@ static int gspca_set_alt0(struct gspca_d
 		return 0;
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
 	if (ret < 0)
-		err("set alt 0 err %d", ret);
+		pr_err("set alt 0 err %d\n", ret);
 	return ret;
 }
 
@@ -640,53 +627,104 @@ static struct usb_host_endpoint *alt_xfe
 	return NULL;
 }
 
+/* compute the minimum bandwidth for the current transfer */
+static u32 which_bandwidth(struct gspca_dev *gspca_dev)
+{
+	u32 bandwidth;
+	int i;
+
+	i = gspca_dev->curr_mode;
+	bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+
+	/* if the image is compressed, estimate the mean image size */
+	if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+				gspca_dev->cam.cam_mode[i].height)
+		bandwidth /= 3;
+
+	/* estimate the frame rate */
+	if (gspca_dev->sd_desc->get_streamparm) {
+		struct v4l2_streamparm parm;
+
+		parm.parm.capture.timeperframe.denominator = 15;
+		gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
+		bandwidth *= parm.parm.capture.timeperframe.denominator;
+	} else {
+		bandwidth *= 15;		/* 15 fps */
+	}
+
+	PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
+	return bandwidth;
+}
+
+/* endpoint table */
+#define MAX_ALT 16
+struct ep_tb_s {
+	u32 alt;
+	u32 bandwidth;
+};
+
 /*
- * look for an input (isoc or bulk) endpoint
- *
- * The endpoint is defined by the subdriver.
- * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
- * This routine may be called many times when the bandwidth is too small
- * (the bandwidth is checked on urb submit).
+ * build the table of the endpoints
+ * and compute the minimum bandwidth for the image transfer
  */
-static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
+static int build_ep_tb(struct gspca_dev *gspca_dev,
+			struct usb_interface *intf,
+			int xfer,
+			struct ep_tb_s *ep_tb)
 {
-	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
-	int xfer, i, ret;
+	int i, j, nbalt, psize, found;
+	u32 bandwidth, last_bw;
 
-	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-	ep = NULL;
-	xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
-				   : USB_ENDPOINT_XFER_ISOC;
-	i = gspca_dev->alt;			/* previous alt setting */
-	if (gspca_dev->cam.reverse_alts) {
-		while (++i < gspca_dev->nbalt) {
-			ep = alt_xfer(&intf->altsetting[i], xfer);
-			if (ep)
-				break;
-		}
-	} else {
-		while (--i >= 0) {
-			ep = alt_xfer(&intf->altsetting[i], xfer);
-			if (ep)
-				break;
+	nbalt = intf->num_altsetting;
+	if (nbalt > MAX_ALT)
+		nbalt = MAX_ALT;	/* fixme: should warn */
+
+	/* build the endpoint table */
+	i = 0;
+	last_bw = 0;
+	for (;;) {
+		ep_tb->bandwidth = 2000 * 2000 * 120;
+		found = 0;
+		for (j = 0; j < nbalt; j++) {
+			ep = alt_xfer(&intf->altsetting[j], xfer);
+			if (ep == NULL)
+				continue;
+			psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+			if (!gspca_dev->cam.bulk)		/* isoc */
+				psize = (psize & 0x07ff) *
+						(1 + ((psize >> 11) & 3));
+			bandwidth = psize * ep->desc.bInterval * 1000;
+			if (gspca_dev->dev->speed == USB_SPEED_HIGH
+			 || gspca_dev->dev->speed == USB_SPEED_SUPER)
+				bandwidth *= 8;
+			if (bandwidth <= last_bw)
+				continue;
+			if (bandwidth < ep_tb->bandwidth) {
+				ep_tb->bandwidth = bandwidth;
+				ep_tb->alt = j;
+				found = 1;
+			}
 		}
+		if (!found)
+			break;
+		PDEBUG(D_STREAM, "alt %d bandwidth %d",
+				ep_tb->alt, ep_tb->bandwidth);
+		last_bw = ep_tb->bandwidth;
+		i++;
+		ep_tb++;
 	}
-	if (ep == NULL) {
-		err("no transfer endpoint found");
-		return NULL;
-	}
-	PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
-			i, ep->desc.bEndpointAddress);
-	gspca_dev->alt = i;		/* memorize the current alt setting */
-	if (gspca_dev->nbalt > 1) {
-		ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
-		if (ret < 0) {
-			err("set alt %d err %d", i, ret);
-			ep = NULL;
-		}
+
+	/* get the requested bandwidth and start at the highest atlsetting */
+	bandwidth = which_bandwidth(gspca_dev);
+	ep_tb--;
+	while (i > 1) {
+		ep_tb--;
+		if (ep_tb->bandwidth < bandwidth)
+			break;
+		i--;
 	}
-	return ep;
+	return i;
 }
 
 /*
@@ -731,7 +769,7 @@ static int create_urbs(struct gspca_dev
 	for (n = 0; n < nurbs; n++) {
 		urb = usb_alloc_urb(npkt, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -741,7 +779,7 @@ static int create_urbs(struct gspca_dev
 						&urb->transfer_dma);
 
 		if (urb->transfer_buffer == NULL) {
-			err("usb_alloc_coherent failed");
+			pr_err("usb_alloc_coherent failed\n");
 			return -ENOMEM;
 		}
 		urb->dev = gspca_dev->dev;
@@ -752,7 +790,10 @@ static int create_urbs(struct gspca_dev
 						    ep->desc.bEndpointAddress);
 			urb->transfer_flags = URB_ISO_ASAP
 					| URB_NO_TRANSFER_DMA_MAP;
-			urb->interval = ep->desc.bInterval;
+			if (gspca_dev->dev->speed == USB_SPEED_LOW)
+				urb->interval = ep->desc.bInterval;
+			else
+				urb->interval = 1 << (ep->desc.bInterval - 1);
 			urb->complete = isoc_irq;
 			urb->number_of_packets = npkt;
 			for (i = 0; i < npkt; i++) {
@@ -774,9 +815,11 @@ static int create_urbs(struct gspca_dev
  */
 static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
 	struct urb *urb;
-	int n, ret;
+	struct ep_tb_s ep_tb[MAX_ALT];
+	int n, ret, xfer, alt, alt_idx;
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
@@ -794,30 +837,65 @@ static int gspca_init_transfer(struct gs
 
 	gspca_dev->usb_err = 0;
 
-	/* set the higher alternate setting and
-	 * loop until urb submit succeeds */
-	if (gspca_dev->cam.reverse_alts)
-		gspca_dev->alt = 0;
-	else
-		gspca_dev->alt = gspca_dev->nbalt;
-
+	/* do the specific subdriver stuff before endpoint selection */
+	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+	gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
 	if (gspca_dev->sd_desc->isoc_init) {
 		ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
 		if (ret < 0)
 			goto unlock;
 	}
+	xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+				   : USB_ENDPOINT_XFER_ISOC;
 
-	gspca_input_destroy_urb(gspca_dev);
-	ep = get_ep(gspca_dev);
-	if (ep == NULL) {
-		ret = -EIO;
-		goto out;
+	/* if the subdriver forced an altsetting, get the endpoint */
+	if (gspca_dev->alt != 0) {
+		gspca_dev->alt--;	/* (previous version compatibility) */
+		ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+		if (ep == NULL) {
+			pr_err("bad altsetting %d\n", gspca_dev->alt);
+			ret = -EIO;
+			goto out;
+		}
+		ep_tb[0].alt = gspca_dev->alt;
+		alt_idx = 1;
+	} else {
+
+	/* else, compute the minimum bandwidth
+	 * and build the endpoint table */
+		alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+		if (alt_idx <= 0) {
+			pr_err("no transfer endpoint found\n");
+			ret = -EIO;
+			goto unlock;
+		}
 	}
+
+	/* set the highest alternate setting and
+	 * loop until urb submit succeeds */
+	gspca_input_destroy_urb(gspca_dev);
+
+	gspca_dev->alt = ep_tb[--alt_idx].alt;
+	alt = -1;
 	for (;;) {
+		if (alt != gspca_dev->alt) {
+			alt = gspca_dev->alt;
+			if (gspca_dev->nbalt > 1) {
+				ret = usb_set_interface(gspca_dev->dev,
+							gspca_dev->iface,
+							alt);
+				if (ret < 0) {
+					if (ret == -ENOSPC)
+						goto retry; /*fixme: ugly*/
+					pr_err("set alt %d err %d\n", alt, ret);
+					goto out;
+				}
+			}
+		}
 		if (!gspca_dev->cam.no_urb_create) {
-			PDEBUG(D_STREAM, "init transfer alt %d",
-				gspca_dev->alt);
-			ret = create_urbs(gspca_dev, ep);
+			PDEBUG(D_STREAM, "init transfer alt %d", alt);
+			ret = create_urbs(gspca_dev,
+				alt_xfer(&intf->altsetting[alt], xfer));
 			if (ret < 0) {
 				destroy_urbs(gspca_dev);
 				goto out;
@@ -851,29 +929,35 @@ static int gspca_init_transfer(struct gs
 				break;
 		}
 		if (ret >= 0)
-			break;
+			break;			/* transfer is started */
+
+		/* something when wrong
+		 * stop the webcam and free the transfer resources */
 		gspca_stream_off(gspca_dev);
 		if (ret != -ENOSPC) {
-			err("usb_submit_urb alt %d err %d",
-				gspca_dev->alt, ret);
+			pr_err("usb_submit_urb alt %d err %d\n",
+			       gspca_dev->alt, ret);
 			goto out;
 		}
 
 		/* the bandwidth is not wide enough
 		 * negotiate or try a lower alternate setting */
+retry:
 		PDEBUG(D_ERR|D_STREAM,
-			"bandwidth not wide enough - trying again");
+			"alt %d - bandwidth not wide enough - trying again",
+			alt);
 		msleep(20);	/* wait for kill complete */
 		if (gspca_dev->sd_desc->isoc_nego) {
 			ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
 			if (ret < 0)
 				goto out;
 		} else {
-			ep = get_ep(gspca_dev);
-			if (ep == NULL) {
+			if (alt_idx <= 0) {
+				pr_err("no transfer endpoint found\n");
 				ret = -EIO;
 				goto out;
 			}
+			gspca_dev->alt = ep_tb[--alt_idx].alt;
 		}
 	}
 out:
@@ -1044,7 +1128,9 @@ static int vidioc_enum_fmt_vid_cap(struc
 		return -EINVAL;		/* no more format */
 
 	fmtdesc->pixelformat = fmt_tb[index];
-	if (gspca_is_compressed(fmt_tb[index]))
+	if (gspca_dev->cam.cam_mode[i].sizeimage <
+			gspca_dev->cam.cam_mode[i].width *
+				gspca_dev->cam.cam_mode[i].height)
 		fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
 	fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
 	fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
@@ -2195,19 +2281,20 @@ int gspca_dev_probe2(struct usb_interfac
 	struct usb_device *dev = interface_to_usbdev(intf);
 	int ret;
 
-	PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
+	pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
+		sd_desc->name, id->idVendor, id->idProduct);
 
 	/* create the device */
 	if (dev_size < sizeof *gspca_dev)
 		dev_size = sizeof *gspca_dev;
 	gspca_dev = kzalloc(dev_size, GFP_KERNEL);
 	if (!gspca_dev) {
-		err("couldn't kzalloc gspca struct");
+		pr_err("couldn't kzalloc gspca struct\n");
 		return -ENOMEM;
 	}
 	gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
 	if (!gspca_dev->usb_buf) {
-		err("out of memory");
+		pr_err("out of memory\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -2264,7 +2351,7 @@ int gspca_dev_probe2(struct usb_interfac
 				  VFL_TYPE_GRABBER,
 				  -1);
 	if (ret < 0) {
-		err("video_register_device err %d", ret);
+		pr_err("video_register_device err %d\n", ret);
 		goto out;
 	}
 
@@ -2296,8 +2383,8 @@ int gspca_dev_probe(struct usb_interface
 
 	/* we don't handle multi-config cameras */
 	if (dev->descriptor.bNumConfigurations != 1) {
-		err("%04x:%04x too many config",
-				id->idVendor, id->idProduct);
+		pr_err("%04x:%04x too many config\n",
+		       id->idVendor, id->idProduct);
 		return -ENODEV;
 	}
 
@@ -2480,7 +2567,7 @@ EXPORT_SYMBOL(gspca_auto_gain_n_exposure
 /* -- module insert / remove -- */
 static int __init gspca_init(void)
 {
-	info("v" DRIVER_VERSION_NUMBER " registered");
+	pr_info("v" GSPCA_VERSION " registered\n");
 	return 0;
 }
 static void __exit gspca_exit(void)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/gspca.h linux-libre-3.2-gnu1/drivers/media/video/gspca/gspca.h
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/gspca.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/gspca.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,12 @@
 #ifdef GSPCA_DEBUG
 /* GSPCA our debug messages */
 extern int gspca_debug;
-#define PDEBUG(level, fmt, args...) \
-	do {\
-		if (gspca_debug & (level)) \
-			printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
-	} while (0)
+#define PDEBUG(level, fmt, ...)					\
+do {								\
+	if (gspca_debug & (level))				\
+		pr_info(fmt, ##__VA_ARGS__);			\
+} while (0)
+
 #define D_ERR  0x01
 #define D_PROBE 0x02
 #define D_CONF 0x04
@@ -29,17 +30,8 @@ extern int gspca_debug;
 #define D_USBO 0x00
 #define D_V4L2 0x0100
 #else
-#define PDEBUG(level, fmt, args...)
+#define PDEBUG(level, fmt, ...)
 #endif
-#undef err
-#define err(fmt, args...) \
-	printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
-#undef info
-#define info(fmt, args...) \
-	printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
-#undef warn
-#define warn(fmt, args...) \
-	printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
 
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
 /* image transfers */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/jeilinj.c linux-libre-3.2-gnu1/drivers/media/video/gspca/jeilinj.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/jeilinj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/jeilinj.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "jeilinj"
 
 #include <linux/slab.h>
@@ -113,8 +115,8 @@ static void jlj_write2(struct gspca_dev
 			usb_sndbulkpipe(gspca_dev->dev, 3),
 			gspca_dev->usb_buf, 2, NULL, 500);
 	if (retval < 0) {
-		err("command write [%02x] error %d",
-				gspca_dev->usb_buf[0], retval);
+		pr_err("command write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], retval);
 		gspca_dev->usb_err = retval;
 	}
 }
@@ -131,8 +133,8 @@ static void jlj_read1(struct gspca_dev *
 				gspca_dev->usb_buf, 1, NULL, 500);
 	response = gspca_dev->usb_buf[0];
 	if (retval < 0) {
-		err("read command [%02x] error %d",
-				gspca_dev->usb_buf[0], retval);
+		pr_err("read command [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], retval);
 		gspca_dev->usb_err = retval;
 	}
 }
@@ -403,13 +405,7 @@ static int sd_config(struct gspca_dev *g
 	dev->type = id->driver_info;
 	gspca_dev->cam.ctrls = dev->ctrls;
 	dev->quality = QUALITY_DEF;
-	dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
-	dev->ctrls[RED].def = RED_BALANCE_DEF;
-	dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;
-	dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;
-	PDEBUG(D_PROBE,
-		"JEILINJ camera detected"
-		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
 	cam->cam_mode = jlj_mode;
 	cam->nmodes = ARRAY_SIZE(jlj_mode);
 	cam->bulk = 1;
@@ -422,7 +418,7 @@ static void sd_stopN(struct gspca_dev *g
 {
 	int i;
 	u8 *buf;
-	u8 stop_commands[][2] = {
+	static u8 stop_commands[][2] = {
 		{0x71, 0x00},
 		{0x70, 0x09},
 		{0x71, 0x80},
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/Kconfig linux-libre-3.2-gnu1/drivers/media/video/gspca/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -356,6 +356,16 @@ config USB_GSPCA_T613
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_t613.
 
+config USB_GSPCA_TOPRO
+	tristate "TOPRO USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the
+	  TP6800 and TP6810 Topro chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_topro.
+
 config USB_GSPCA_TV8532
 	tristate "TV8532 USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/kinect.c linux-libre-3.2-gnu1/drivers/media/video/gspca/kinect.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/kinect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/kinect.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "kinect"
 
 #include "gspca.h"
@@ -34,11 +36,6 @@ MODULE_AUTHOR("Antonio Ospite <ospite@st
 MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
-	D_USBI | D_USBO | D_V4L2;
-#endif
-
 struct pkt_hdr {
 	uint8_t magic[2];
 	uint8_t pad;
@@ -141,7 +138,7 @@ static int send_cmd(struct gspca_dev *gs
 	struct cam_hdr *rhdr = (void *)ibuf;
 
 	if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
-		err("send_cmd: Invalid command length (0x%x)", cmd_len);
+		pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
 		return -1;
 	}
 
@@ -157,7 +154,7 @@ static int send_cmd(struct gspca_dev *gs
 	PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
 		sd->cam_tag, cmd_len, res);
 	if (res < 0) {
-		err("send_cmd: Output control transfer failed (%d)", res);
+		pr_err("send_cmd: Output control transfer failed (%d)\n", res);
 		return res;
 	}
 
@@ -166,33 +163,35 @@ static int send_cmd(struct gspca_dev *gs
 	} while (actual_len == 0);
 	PDEBUG(D_USBO, "Control reply: %d", res);
 	if (actual_len < sizeof(*rhdr)) {
-		err("send_cmd: Input control transfer failed (%d)", res);
+		pr_err("send_cmd: Input control transfer failed (%d)\n", res);
 		return res;
 	}
 	actual_len -= sizeof(*rhdr);
 
 	if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
-		err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
-			rhdr->magic[1]);
+		pr_err("send_cmd: Bad magic %02x %02x\n",
+		       rhdr->magic[0], rhdr->magic[1]);
 		return -1;
 	}
 	if (rhdr->cmd != chdr->cmd) {
-		err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
+		pr_err("send_cmd: Bad cmd %02x != %02x\n",
+		       rhdr->cmd, chdr->cmd);
 		return -1;
 	}
 	if (rhdr->tag != chdr->tag) {
-		err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
+		pr_err("send_cmd: Bad tag %04x != %04x\n",
+		       rhdr->tag, chdr->tag);
 		return -1;
 	}
 	if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
-		err("send_cmd: Bad len %04x != %04x",
-				cpu_to_le16(rhdr->len), (int)(actual_len/2));
+		pr_err("send_cmd: Bad len %04x != %04x\n",
+		       cpu_to_le16(rhdr->len), (int)(actual_len/2));
 		return -1;
 	}
 
 	if (actual_len > reply_len) {
-		warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
-				reply_len, actual_len);
+		pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
+			reply_len, actual_len);
 		memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
 	} else {
 		memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
@@ -218,8 +217,8 @@ static int write_register(struct gspca_d
 	if (res < 0)
 		return res;
 	if (res != 2) {
-		warn("send_cmd returned %d [%04x %04x], 0000 expected",
-				res, reply[0], reply[1]);
+		pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
+			res, reply[0], reply[1]);
 	}
 	return 0;
 }
@@ -353,8 +352,8 @@ static void sd_pkt_scan(struct gspca_dev
 		return;
 
 	if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
-		warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
-				hdr->magic[0], hdr->magic[1]);
+		pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
+			sd->stream_flag, hdr->magic[0], hdr->magic[1]);
 		return;
 	}
 
@@ -368,7 +367,7 @@ static void sd_pkt_scan(struct gspca_dev
 		gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
 
 	else
-		warn("Packet type not recognized...");
+		pr_warn("Packet type not recognized...\n");
 }
 
 /* sub-driver description */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/konica.c linux-libre-3.2-gnu1/drivers/media/video/gspca/konica.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/konica.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/konica.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "konica"
 
 #include <linux/input.h>
@@ -200,7 +202,7 @@ static void reg_w(struct gspca_dev *gspc
 			0,
 			1000);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -221,7 +223,7 @@ static void reg_r(struct gspca_dev *gspc
 			2,
 			1000);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -284,7 +286,7 @@ static int sd_start(struct gspca_dev *gs
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		return -EIO;
 	}
 
@@ -315,7 +317,7 @@ static int sd_start(struct gspca_dev *gs
 			le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
 		urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -324,7 +326,7 @@ static int sd_start(struct gspca_dev *gs
 						GFP_KERNEL,
 						&urb->transfer_dma);
 		if (urb->transfer_buffer == NULL) {
-			err("usb_buffer_alloc failed");
+			pr_err("usb_buffer_alloc failed\n");
 			return -ENOMEM;
 		}
 
@@ -386,7 +388,7 @@ static void sd_isoc_irq(struct urb *urb)
 		PDEBUG(D_ERR, "urb status: %d", urb->status);
 		st = usb_submit_urb(urb, GFP_ATOMIC);
 		if (st < 0)
-			err("resubmit urb error %d", st);
+			pr_err("resubmit urb error %d\n", st);
 		return;
 	}
 
@@ -477,7 +479,7 @@ resubmit:
 	}
 	st = usb_submit_urb(status_urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb(status_urb) ret %d", st);
+		pr_err("usb_submit_urb(status_urb) ret %d\n", st);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_core.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_core.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov9650.h"
 #include "m5602_ov7660.h"
 #include "m5602_mt9m111.h"
@@ -192,10 +194,9 @@ static void m5602_dump_bridge(struct sd
 	for (i = 0; i < 0x80; i++) {
 		unsigned char val = 0;
 		m5602_read_bridge(sd, i, &val);
-		info("ALi m5602 address 0x%x contains 0x%x", i, val);
+		pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
 	}
-	info("Warning: The ALi m5602 webcam probably won't work "
-		"until it's power cycled");
+	pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
 }
 
 static int m5602_probe_sensor(struct sd *sd)
@@ -231,7 +232,7 @@ static int m5602_probe_sensor(struct sd
 		return 0;
 
 	/* More sensor probe function goes here */
-	info("Failed to find a sensor");
+	pr_info("Failed to find a sensor\n");
 	sd->sensor = NULL;
 	return -ENODEV;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_mt9m111.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_mt9m111.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_mt9m111.h"
 
 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -163,7 +165,7 @@ int mt9m111_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == MT9M111_SENSOR) {
-			info("Forcing a %s sensor", mt9m111.name);
+			pr_info("Forcing a %s sensor\n", mt9m111.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -191,7 +193,7 @@ int mt9m111_probe(struct sd *sd)
 		return -ENODEV;
 
 	if ((data[0] == 0x14) && (data[1] == 0x3a)) {
-		info("Detected a mt9m111 sensor");
+		pr_info("Detected a mt9m111 sensor\n");
 		goto sensor_found;
 	}
 
@@ -612,34 +614,34 @@ static void mt9m111_dump_registers(struc
 {
 	u8 address, value[2] = {0x00, 0x00};
 
-	info("Dumping the mt9m111 register state");
+	pr_info("Dumping the mt9m111 register state\n");
 
-	info("Dumping the mt9m111 sensor core registers");
+	pr_info("Dumping the mt9m111 sensor core registers\n");
 	value[1] = MT9M111_SENSOR_CORE;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("Dumping the mt9m111 color pipeline registers");
+	pr_info("Dumping the mt9m111 color pipeline registers\n");
 	value[1] = MT9M111_COLORPIPE;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("Dumping the mt9m111 camera control registers");
+	pr_info("Dumping the mt9m111 camera control registers\n");
 	value[1] = MT9M111_CAMERA_CONTROL;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("mt9m111 register state dump complete");
+	pr_info("mt9m111 register state dump complete\n");
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_ov7660.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_ov7660.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_ov7660.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_ov7660.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov7660.h"
 
 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -149,7 +151,7 @@ int ov7660_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == OV7660_SENSOR) {
-			info("Forcing an %s sensor", ov7660.name);
+			pr_info("Forcing an %s sensor\n", ov7660.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor,
@@ -180,10 +182,10 @@ int ov7660_probe(struct sd *sd)
 	if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
 		return -ENODEV;
 
-	info("Sensor reported 0x%x%x", prod_id, ver_id);
+	pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
 
 	if ((prod_id == 0x76) && (ver_id == 0x60)) {
-		info("Detected a ov7660 sensor");
+		pr_info("Detected a ov7660 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -457,17 +459,16 @@ static int ov7660_set_vflip(struct gspca
 static void ov7660_dump_registers(struct sd *sd)
 {
 	int address;
-	info("Dumping the ov7660 register state");
+	pr_info("Dumping the ov7660 register state\n");
 	for (address = 0; address < 0xa9; address++) {
 		u8 value;
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("ov7660 register state dump complete");
+	pr_info("ov7660 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -477,9 +478,9 @@ static void ov7660_dump_registers(struct
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov9650.h"
 
 static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
@@ -299,7 +301,7 @@ int ov9650_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == OV9650_SENSOR) {
-			info("Forcing an %s sensor", ov9650.name);
+			pr_info("Forcing an %s sensor\n", ov9650.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor,
@@ -330,7 +332,7 @@ int ov9650_probe(struct sd *sd)
 		return -ENODEV;
 
 	if ((prod_id == 0x96) && (ver_id == 0x52)) {
-		info("Detected an ov9650 sensor");
+		pr_info("Detected an ov9650 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -850,17 +852,16 @@ static int ov9650_set_auto_gain(struct g
 static void ov9650_dump_registers(struct sd *sd)
 {
 	int address;
-	info("Dumping the ov9650 register state");
+	pr_info("Dumping the ov9650 register state\n");
 	for (address = 0; address < 0xa9; address++) {
 		u8 value;
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("ov9650 register state dump complete");
+	pr_info("ov9650 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -870,9 +871,9 @@ static void ov9650_dump_registers(struct
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_po1030.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_po1030.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_po1030.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_po1030.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_po1030.h"
 
 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -197,7 +199,7 @@ int po1030_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == PO1030_SENSOR) {
-			info("Forcing a %s sensor", po1030.name);
+			pr_info("Forcing a %s sensor\n", po1030.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -221,7 +223,7 @@ int po1030_probe(struct sd *sd)
 		return -ENODEV;
 
 	if (dev_id_h == 0x30) {
-		info("Detected a po1030 sensor");
+		pr_info("Detected a po1030 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -267,7 +269,7 @@ int po1030_init(struct sd *sd)
 			break;
 
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -733,16 +735,15 @@ static void po1030_dump_registers(struct
 	int address;
 	u8 value = 0;
 
-	info("Dumping the po1030 sensor core registers");
+	pr_info("Dumping the po1030 sensor core registers\n");
 	for (address = 0; address < 0x7f; address++) {
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("po1030 register state dump complete");
+	pr_info("po1030 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -752,9 +753,9 @@ static void po1030_dump_registers(struct
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_s5k4aa.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_s5k4aa.h"
 
 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -240,7 +242,7 @@ int s5k4aa_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == S5K4AA_SENSOR) {
-			info("Forcing a %s sensor", s5k4aa.name);
+			pr_info("Forcing a %s sensor\n", s5k4aa.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -276,7 +278,7 @@ int s5k4aa_probe(struct sd *sd)
 						  data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -292,7 +294,7 @@ int s5k4aa_probe(struct sd *sd)
 	if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
 		return -ENODEV;
 	else
-		info("Detected a s5k4aa sensor");
+		pr_info("Detected a s5k4aa sensor\n");
 
 sensor_found:
 	sensor_settings = kmalloc(
@@ -347,7 +349,7 @@ int s5k4aa_start(struct sd *sd)
 			break;
 
 			default:
-				err("Invalid stream command, exiting init");
+				pr_err("Invalid stream command, exiting init\n");
 				return -EINVAL;
 			}
 		}
@@ -383,7 +385,7 @@ int s5k4aa_start(struct sd *sd)
 			break;
 
 			default:
-				err("Invalid stream command, exiting init");
+				pr_err("Invalid stream command, exiting init\n");
 				return -EINVAL;
 			}
 		}
@@ -447,7 +449,7 @@ int s5k4aa_init(struct sd *sd)
 				init_s5k4aa[i][1], data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -686,20 +688,21 @@ static void s5k4aa_dump_registers(struct
 	m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-		info("Dumping the s5k4aa register state for page 0x%x", page);
+		pr_info("Dumping the s5k4aa register state for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 value = 0;
 			m5602_read_sensor(sd, address, &value, 1);
-			info("register 0x%x contains 0x%x",
-			     address, value);
+			pr_info("register 0x%x contains 0x%x\n",
+				address, value);
 		}
 	}
-	info("s5k4aa register state dump complete");
+	pr_info("s5k4aa register state dump complete\n");
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-		info("Probing for which registers that are "
-		     "read/write for page 0x%x", page);
+		pr_info("Probing for which registers that are read/write for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 old_value, ctrl_value, test_value = 0xff;
 
@@ -708,14 +711,16 @@ static void s5k4aa_dump_registers(struct
 			m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 			if (ctrl_value == test_value)
-				info("register 0x%x is writeable", address);
+				pr_info("register 0x%x is writeable\n",
+					address);
 			else
-				info("register 0x%x is read only", address);
+				pr_info("register 0x%x is read only\n",
+					address);
 
 			/* Restore original value */
 			m5602_write_sensor(sd, address, &old_value, 1);
 		}
 	}
-	info("Read/write register probing complete");
+	pr_info("Read/write register probing complete\n");
 	m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_s5k83a.c linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_s5k83a.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kthread.h>
 #include "m5602_s5k83a.h"
 
@@ -135,7 +137,7 @@ int s5k83a_probe(struct sd *sd)
 
 	if (force_sensor) {
 		if (force_sensor == S5K83A_SENSOR) {
-			info("Forcing a %s sensor", s5k83a.name);
+			pr_info("Forcing a %s sensor\n", s5k83a.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -168,7 +170,7 @@ int s5k83a_probe(struct sd *sd)
 	if ((prod_id == 0xff) || (ver_id == 0xff))
 		return -ENODEV;
 	else
-		info("Detected a s5k83a sensor");
+		pr_info("Detected a s5k83a sensor\n");
 
 sensor_found:
 	sens_priv = kmalloc(
@@ -227,7 +229,7 @@ int s5k83a_init(struct sd *sd)
 				init_s5k83a[i][1], data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -273,7 +275,7 @@ static int rotation_thread_function(void
 		s5k83a_get_rotation(sd, &reg);
 		if (previous_rotation != reg) {
 			previous_rotation = reg;
-			info("Camera was flipped");
+			pr_info("Camera was flipped\n");
 
 			s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
 			s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
@@ -566,20 +568,20 @@ static void s5k83a_dump_registers(struct
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Dumping the s5k83a register state for page 0x%x", page);
+		pr_info("Dumping the s5k83a register state for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 val = 0;
 			m5602_read_sensor(sd, address, &val, 1);
-			info("register 0x%x contains 0x%x",
-			     address, val);
+			pr_info("register 0x%x contains 0x%x\n", address, val);
 		}
 	}
-	info("s5k83a register state dump complete");
+	pr_info("s5k83a register state dump complete\n");
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Probing for which registers that are read/write "
-				"for page 0x%x", page);
+		pr_info("Probing for which registers that are read/write for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 old_val, ctrl_val, test_val = 0xff;
 
@@ -588,14 +590,16 @@ static void s5k83a_dump_registers(struct
 			m5602_read_sensor(sd, address, &ctrl_val, 1);
 
 			if (ctrl_val == test_val)
-				info("register 0x%x is writeable", address);
+				pr_info("register 0x%x is writeable\n",
+					address);
 			else
-				info("register 0x%x is read only", address);
+				pr_info("register 0x%x is read only\n",
+					address);
 
 			/* Restore original val */
 			m5602_write_sensor(sd, address, &old_val, 1);
 		}
 	}
-	info("Read/write register probing complete");
+	pr_info("Read/write register probing complete\n");
 	m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/Makefile linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/m5602/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/m5602/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \
 		    m5602_s5k83a.o \
 		    m5602_s5k4aa.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/Makefile linux-libre-3.2-gnu1/drivers/media/video/gspca/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_GSPCA_SUNPLUS)  += gspc
 obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.o
 obj-$(CONFIG_USB_GSPCA_STV0680)  += gspca_stv0680.o
 obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TOPRO)    += gspca_topro.o
 obj-$(CONFIG_USB_GSPCA_TV8532)   += gspca_tv8532.o
 obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
 obj-$(CONFIG_USB_GSPCA_VICAM)    += gspca_vicam.o
@@ -78,6 +79,7 @@ gspca_stk014-objs   := stk014.o
 gspca_stv0680-objs  := stv0680.o
 gspca_sunplus-objs  := sunplus.o
 gspca_t613-objs     := t613.o
+gspca_topro-objs    := topro.o
 gspca_tv8532-objs   := tv8532.o
 gspca_vc032x-objs   := vc032x.o
 gspca_vicam-objs    := vicam.o
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/mars.c linux-libre-3.2-gnu1/drivers/media/video/gspca/mars.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/mars.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/mars.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "mars"
 
 #include "gspca.h"
@@ -178,8 +180,8 @@ static void reg_w(struct gspca_dev *gspc
 			&alen,
 			500);	/* timeout in milliseconds */
 	if (ret < 0) {
-		err("reg write [%02x] error %d",
-			gspca_dev->usb_buf[0], ret);
+		pr_err("reg write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], ret);
 		gspca_dev->usb_err = ret;
 	}
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/mr97310a.c linux-libre-3.2-gnu1/drivers/media/video/gspca/mr97310a.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/mr97310a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/mr97310a.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "mr97310a"
 
 #include "gspca.h"
@@ -267,7 +269,7 @@ static int mr_write(struct gspca_dev *gs
 			  usb_sndbulkpipe(gspca_dev->dev, 4),
 			  gspca_dev->usb_buf, len, NULL, 500);
 	if (rc < 0)
-		err("reg write [%02x] error %d",
+		pr_err("reg write [%02x] error %d\n",
 		       gspca_dev->usb_buf[0], rc);
 	return rc;
 }
@@ -281,7 +283,7 @@ static int mr_read(struct gspca_dev *gsp
 			  usb_rcvbulkpipe(gspca_dev->dev, 3),
 			  gspca_dev->usb_buf, len, NULL, 500);
 	if (rc < 0)
-		err("reg read [%02x] error %d",
+		pr_err("reg read [%02x] error %d\n",
 		       gspca_dev->usb_buf[0], rc);
 	return rc;
 }
@@ -540,7 +542,7 @@ static int sd_config(struct gspca_dev *g
 			sd->sensor_type = 1;
 			break;
 		default:
-			err("Unknown CIF Sensor id : %02x",
+			pr_err("Unknown CIF Sensor id : %02x\n",
 			       gspca_dev->usb_buf[1]);
 			return -ENODEV;
 		}
@@ -575,10 +577,10 @@ static int sd_config(struct gspca_dev *g
 			sd->sensor_type = 2;
 		} else if ((gspca_dev->usb_buf[0] != 0x03) &&
 					(gspca_dev->usb_buf[0] != 0x04)) {
-			err("Unknown VGA Sensor id Byte 0: %02x",
-					gspca_dev->usb_buf[0]);
-			err("Defaults assumed, may not work");
-			err("Please report this");
+			pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
+			       gspca_dev->usb_buf[0]);
+			pr_err("Defaults assumed, may not work\n");
+			pr_err("Please report this\n");
 		}
 		/* Sakar Digital color needs to be adjusted. */
 		if ((gspca_dev->usb_buf[0] == 0x03) &&
@@ -595,10 +597,10 @@ static int sd_config(struct gspca_dev *g
 				/* Nothing to do here. */
 				break;
 			default:
-				err("Unknown VGA Sensor id Byte 1: %02x",
-					gspca_dev->usb_buf[1]);
-				err("Defaults assumed, may not work");
-				err("Please report this");
+				pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
+				       gspca_dev->usb_buf[1]);
+				pr_err("Defaults assumed, may not work\n");
+				pr_err("Please report this\n");
 			}
 		}
 		PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/nw80x.c linux-libre-3.2-gnu1/drivers/media/video/gspca/nw80x.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/nw80x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/nw80x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "nw80x"
 
 #include "gspca.h"
@@ -1571,7 +1573,7 @@ static void reg_w(struct gspca_dev *gspc
 			len,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1592,7 +1594,7 @@ static void reg_r(struct gspca_dev *gspc
 			0x00, index,
 			gspca_dev->usb_buf, len, 500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return;
 	}
@@ -1802,7 +1804,8 @@ static int sd_config(struct gspca_dev *g
 		}
 	}
 	if (webcam_chip[sd->webcam] != sd->bridge) {
-		err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
+		pr_err("Bad webcam type %d for NW80%d\n",
+		       sd->webcam, sd->bridge);
 		gspca_dev->usb_err = -ENODEV;
 		return gspca_dev->usb_err;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/ov519.c linux-libre-3.2-gnu1/drivers/media/video/gspca/ov519.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/ov519.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/ov519.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov519"
 
 #include <linux/input.h>
@@ -2171,7 +2174,7 @@ static void reg_w(struct sd *sd, u16 ind
 			sd->gspca_dev.usb_buf, 1, 500);
 leave:
 	if (ret < 0) {
-		err("reg_w %02x failed %d", index, ret);
+		pr_err("reg_w %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 		return;
 	}
@@ -2210,7 +2213,7 @@ static int reg_r(struct sd *sd, u16 inde
 		PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
 			req, index, ret);
 	} else {
-		err("reg_r %02x failed %d", index, ret);
+		pr_err("reg_r %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2235,7 +2238,7 @@ static int reg_r8(struct sd *sd,
 	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
 	} else {
-		err("reg_r8 %02x failed %d", index, ret);
+		pr_err("reg_r8 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2288,7 +2291,7 @@ static void ov518_reg_w32(struct sd *sd,
 			0, index,
 			sd->gspca_dev.usb_buf, n, 500);
 	if (ret < 0) {
-		err("reg_w32 %02x failed %d", index, ret);
+		pr_err("reg_w32 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -2457,7 +2460,7 @@ static void ovfx2_i2c_w(struct sd *sd, u
 			(u16) value, (u16) reg, NULL, 0, 500);
 
 	if (ret < 0) {
-		err("ovfx2_i2c_w %02x failed %d", reg, ret);
+		pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2481,7 +2484,7 @@ static int ovfx2_i2c_r(struct sd *sd, u8
 		ret = sd->gspca_dev.usb_buf[0];
 		PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
 	} else {
-		err("ovfx2_i2c_r %02x failed %d", reg, ret);
+		pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2727,7 +2730,7 @@ static void ov_hires_configure(struct sd
 	int high, low;
 
 	if (sd->bridge != BRIDGE_OVFX2) {
-		err("error hires sensors only supported with ovfx2");
+		pr_err("error hires sensors only supported with ovfx2\n");
 		return;
 	}
 
@@ -2762,7 +2765,7 @@ static void ov_hires_configure(struct sd
 		}
 		break;
 	}
-	err("Error unknown sensor type: %02x%02x", high, low);
+	pr_err("Error unknown sensor type: %02x%02x\n", high, low);
 }
 
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -2783,7 +2786,7 @@ static void ov8xx0_configure(struct sd *
 	if ((rc & 3) == 1)
 		sd->sensor = SEN_OV8610;
 	else
-		err("Unknown image sensor version: %d", rc & 3);
+		pr_err("Unknown image sensor version: %d\n", rc & 3);
 }
 
 /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
@@ -2840,8 +2843,8 @@ static void ov7xx0_configure(struct sd *
 		if (high == 0x76) {
 			switch (low) {
 			case 0x30:
-				err("Sensor is an OV7630/OV7635");
-				err("7630 is not supported by this driver");
+				pr_err("Sensor is an OV7630/OV7635\n");
+				pr_err("7630 is not supported by this driver\n");
 				return;
 			case 0x40:
 				PDEBUG(D_PROBE, "Sensor is an OV7645");
@@ -2868,7 +2871,7 @@ static void ov7xx0_configure(struct sd *
 			sd->sensor = SEN_OV7620;
 		}
 	} else {
-		err("Unknown image sensor version: %d", rc & 3);
+		pr_err("Unknown image sensor version: %d\n", rc & 3);
 	}
 }
 
@@ -2891,8 +2894,7 @@ static void ov6xx0_configure(struct sd *
 	switch (rc) {
 	case 0x00:
 		sd->sensor = SEN_OV6630;
-		warn("WARNING: Sensor is an OV66308. Your camera may have");
-		warn("been misdetected in previous driver versions.");
+		pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
 		break;
 	case 0x01:
 		sd->sensor = SEN_OV6620;
@@ -2908,11 +2910,10 @@ static void ov6xx0_configure(struct sd *
 		break;
 	case 0x90:
 		sd->sensor = SEN_OV6630;
-		warn("WARNING: Sensor is an OV66307. Your camera may have");
-		warn("been misdetected in previous driver versions.");
+		pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
 		break;
 	default:
-		err("FATAL: Unknown sensor version: 0x%02x", rc);
+		pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
 		return;
 	}
 
@@ -3405,7 +3406,7 @@ static int sd_init(struct gspca_dev *gsp
 	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
 		ov_hires_configure(sd);
 	} else {
-		err("Can't determine sensor slave IDs");
+		pr_err("Can't determine sensor slave IDs\n");
 		goto error;
 	}
 
@@ -3590,7 +3591,7 @@ static void ov511_mode_init_regs(struct
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
@@ -3713,7 +3714,7 @@ static void ov518_mode_init_regs(struct
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/ov534_9.c linux-libre-3.2-gnu1/drivers/media/video/gspca/ov534_9.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/ov534_9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/ov534_9.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * ov534-ov965x gspca driver
+ * ov534-ov9xxx gspca driver
  *
- * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
+ * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
  * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
  * Copyright (C) 2008 Jim Paris <jim@jtan.com>
  *
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov534_9"
 
 #include "gspca.h"
@@ -45,39 +47,44 @@ MODULE_AUTHOR("Jean-Francois Moine <moin
 MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	AUTOGAIN,
+	EXPOSURE,
+	SHARPNESS,
+	SATUR,
+	LIGHTFREQ,
+	NCTRLS		/* number of controls */
+};
+
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
+	struct gspca_ctrl ctrls[NCTRLS];
 	__u32 last_pts;
 	u8 last_fid;
 
-	u8 brightness;
-	u8 contrast;
-	u8 autogain;
-	u8 exposure;
-	s8 sharpness;
-	u8 satur;
-	u8 freq;
+	u8 sensor;
+};
+enum sensors {
+	SENSOR_OV965x,		/* ov9657 */
+	SENSOR_OV971x,		/* ov9712 */
+	NSENSORS
 };
 
 /* V4L2 controls supported by the driver */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void setsatur(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
 
-static const struct ctrl sd_ctrls[] = {
-    {							/* 0 */
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
 	{
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -85,13 +92,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 15,
 		.step    = 1,
-#define BRIGHTNESS_DEF 7
-		.default_value = BRIGHTNESS_DEF,
+		.default_value = 7
 	},
-	.set = sd_setbrightness,
-	.get = sd_getbrightness,
+	.set_control = setbrightness
     },
-    {							/* 1 */
+[CONTRAST] = {
 	{
 		.id      = V4L2_CID_CONTRAST,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -99,13 +104,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 15,
 		.step    = 1,
-#define CONTRAST_DEF 3
-		.default_value = CONTRAST_DEF,
+		.default_value = 3
 	},
-	.set = sd_setcontrast,
-	.get = sd_getcontrast,
+	.set_control = setcontrast
     },
-    {							/* 2 */
+[AUTOGAIN] = {
 	{
 		.id      = V4L2_CID_AUTOGAIN,
 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -116,11 +119,9 @@ static const struct ctrl sd_ctrls[] = {
 #define AUTOGAIN_DEF 1
 		.default_value = AUTOGAIN_DEF,
 	},
-	.set = sd_setautogain,
-	.get = sd_getautogain,
+	.set_control = setautogain
     },
-#define EXPO_IDX 3
-    {							/* 3 */
+[EXPOSURE] = {
 	{
 		.id      = V4L2_CID_EXPOSURE,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -128,13 +129,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 3,
 		.step    = 1,
-#define EXPO_DEF 0
-		.default_value = EXPO_DEF,
+		.default_value = 0
 	},
-	.set = sd_setexposure,
-	.get = sd_getexposure,
+	.set_control = setexposure
     },
-    {							/* 4 */
+[SHARPNESS] = {
 	{
 		.id      = V4L2_CID_SHARPNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -142,13 +141,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = -1,		/* -1 = auto */
 		.maximum = 4,
 		.step    = 1,
-#define SHARPNESS_DEF -1
-		.default_value = SHARPNESS_DEF,
+		.default_value = -1
 	},
-	.set = sd_setsharpness,
-	.get = sd_getsharpness,
+	.set_control = setsharpness
     },
-    {							/* 5 */
+[SATUR] = {
 	{
 		.id      = V4L2_CID_SATURATION,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -156,13 +153,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 4,
 		.step    = 1,
-#define SATUR_DEF 2
-		.default_value = SATUR_DEF,
+		.default_value = 2
 	},
-	.set = sd_setsatur,
-	.get = sd_getsatur,
+	.set_control = setsatur
     },
-    {
+[LIGHTFREQ] = {
 	{
 		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
 		.type    = V4L2_CTRL_TYPE_MENU,
@@ -170,11 +165,9 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
 		.step    = 1,
-#define FREQ_DEF 0
-		.default_value = FREQ_DEF,
+		.default_value = 0
 	},
-	.set = sd_setfreq,
-	.get = sd_getfreq,
+	.set_control = setlightfreq
     },
 };
 
@@ -206,6 +199,14 @@ static const struct v4l2_pix_format ov96
 		.colorspace = V4L2_COLORSPACE_JPEG},
 };
 
+static const struct v4l2_pix_format ov971x_mode[] = {
+	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB
+	}
+};
+
 static const u8 bridge_init[][2] = {
 	{0x88, 0xf8},
 	{0x89, 0xff},
@@ -240,7 +241,7 @@ static const u8 bridge_init[][2] = {
 	{0x94, 0x11},
 };
 
-static const u8 sensor_init[][2] = {
+static const u8 ov965x_init[][2] = {
 	{0x12, 0x80},	/* com7 - SSCB reset */
 	{0x00, 0x00},	/* gain */
 	{0x01, 0x80},	/* blue */
@@ -450,7 +451,7 @@ static const u8 bridge_init_2[][2] = {
 	{0x94, 0x11},
 };
 
-static const u8 sensor_init_2[][2] = {
+static const u8 ov965x_init_2[][2] = {
 	{0x3b, 0xc4},
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -492,7 +493,65 @@ static const u8 sensor_init_2[][2] = {
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
 };
 
-static const u8 sensor_start_1_vga[][2] = {	/* same for qvga */
+static const u8 ov971x_init[][2] = {
+	{0x12, 0x80},
+	{0x09, 0x10},
+	{0x1e, 0x07},
+	{0x5f, 0x18},
+	{0x69, 0x04},
+	{0x65, 0x2a},
+	{0x68, 0x0a},
+	{0x39, 0x28},
+	{0x4d, 0x90},
+	{0xc1, 0x80},
+	{0x0c, 0x30},
+	{0x6d, 0x02},
+	{0x96, 0xf1},
+	{0xbc, 0x68},
+	{0x12, 0x00},
+	{0x3b, 0x00},
+	{0x97, 0x80},
+	{0x17, 0x25},
+	{0x18, 0xa2},
+	{0x19, 0x01},
+	{0x1a, 0xca},
+	{0x03, 0x0a},
+	{0x32, 0x07},
+	{0x98, 0x40},	/*{0x98, 0x00},*/
+	{0x99, 0xA0},	/*{0x99, 0x00},*/
+	{0x9a, 0x01},	/*{0x9a, 0x00},*/
+	{0x57, 0x00},
+	{0x58, 0x78},	/*{0x58, 0xc8},*/
+	{0x59, 0x50},	/*{0x59, 0xa0},*/
+	{0x4c, 0x13},
+	{0x4b, 0x36},
+	{0x3d, 0x3c},
+	{0x3e, 0x03},
+	{0xbd, 0x50},	/*{0xbd, 0xa0},*/
+	{0xbe, 0x78},	/*{0xbe, 0xc8},*/
+	{0x4e, 0x55},
+	{0x4f, 0x55},
+	{0x50, 0x55},
+	{0x51, 0x55},
+	{0x24, 0x55},
+	{0x25, 0x40},
+	{0x26, 0xa1},
+	{0x5c, 0x59},
+	{0x5d, 0x00},
+	{0x11, 0x00},
+	{0x2a, 0x98},
+	{0x2b, 0x06},
+	{0x2d, 0x00},
+	{0x2e, 0x00},
+	{0x13, 0xa5},
+	{0x14, 0x40},
+	{0x4a, 0x00},
+	{0x49, 0xce},
+	{0x22, 0x03},
+	{0x09, 0x00}
+};
+
+static const u8 ov965x_start_1_vga[][2] = {	/* same for qvga */
 	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
 	{0x36, 0xfa},	/* aref3 */
 	{0x69, 0x0a},	/* hv */
@@ -515,7 +574,7 @@ static const u8 sensor_start_1_vga[][2]
 	{0xc0, 0xaa},
 };
 
-static const u8 sensor_start_1_svga[][2] = {
+static const u8 ov965x_start_1_svga[][2] = {
 	{0x12, 0x02},	/* com7 - YUYV - VGA 15 full resolution */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -537,7 +596,7 @@ static const u8 sensor_start_1_svga[][2]
 	{0xc0, 0xe2},
 };
 
-static const u8 sensor_start_1_xga[][2] = {
+static const u8 ov965x_start_1_xga[][2] = {
 	{0x12, 0x02},	/* com7 */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -560,7 +619,7 @@ static const u8 sensor_start_1_xga[][2]
 	{0xc0, 0xe2},
 };
 
-static const u8 sensor_start_1_sxga[][2] = {
+static const u8 ov965x_start_1_sxga[][2] = {
 	{0x12, 0x02},	/* com7 */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -709,7 +768,7 @@ static const u8 bridge_start_sxga[][2] =
 	{0x94, 0x11},
 };
 
-static const u8 sensor_start_2_qvga[][2] = {
+static const u8 ov965x_start_2_qvga[][2] = {
 	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -727,7 +786,7 @@ static const u8 sensor_start_2_qvga[][2]
 	{0x3a, 0x80},	/* tslb - yuyv */
 };
 
-static const u8 sensor_start_2_vga[][2] = {
+static const u8 ov965x_start_2_vga[][2] = {
 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -743,7 +802,7 @@ static const u8 sensor_start_2_vga[][2]
 	{0x2d, 0x00},	/* advfl */
 };
 
-static const u8 sensor_start_2_svga[][2] = {	/* same for xga */
+static const u8 ov965x_start_2_svga[][2] = {	/* same for xga */
 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -757,7 +816,7 @@ static const u8 sensor_start_2_svga[][2]
 	{0xa3, 0x41},	/* bd60 */
 };
 
-static const u8 sensor_start_2_sxga[][2] = {
+static const u8 ov965x_start_2_sxga[][2] = {
 	{0x13, 0xe0},	/* com8 */
 	{0x00, 0x00},
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
@@ -785,7 +844,7 @@ static void reg_w_i(struct gspca_dev *gs
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	if (ret < 0) {
-		err("reg_w failed %d", ret);
+		pr_err("reg_w failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -810,7 +869,7 @@ static u8 reg_r(struct gspca_dev *gspca_
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 	return gspca_dev->usb_buf[0];
@@ -848,7 +907,7 @@ static void sccb_write(struct gspca_dev
 	reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_write failed");
+		pr_err("sccb_write failed\n");
 }
 
 static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -856,11 +915,11 @@ static u8 sccb_read(struct gspca_dev *gs
 	reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_read failed 1");
+		pr_err("sccb_read failed 1\n");
 
 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_read failed 2");
+		pr_err("sccb_read failed 2\n");
 
 	return reg_r(gspca_dev, OV534_REG_READ);
 }
@@ -922,7 +981,9 @@ static void setbrightness(struct gspca_d
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
-	val = sd->brightness;
+	if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
+		return;
+	val = sd->ctrls[BRIGHTNESS].val;
 	if (val < 8)
 		val = 15 - val;		/* f .. 8 */
 	else
@@ -935,8 +996,10 @@ static void setcontrast(struct gspca_dev
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	if (gspca_dev->ctrl_dis & (1 << CONTRAST))
+		return;
 	sccb_write(gspca_dev, 0x56,	/* cnst1 - contrast 1 ctrl coeff */
-			sd->contrast << 4);
+			sd->ctrls[CONTRAST].val << 4);
 }
 
 static void setautogain(struct gspca_dev *gspca_dev)
@@ -944,10 +1007,12 @@ static void setautogain(struct gspca_dev
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
+	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+		return;
 /*fixme: should adjust agc/awb/aec by different controls */
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->autogain)
+	if (sd->ctrls[AUTOGAIN].val)
 		val |= 0x05;		/* agc & aec */
 	else
 		val &= 0xfa;
@@ -960,8 +1025,10 @@ static void setexposure(struct gspca_dev
 	u8 val;
 	static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
 
+	if (gspca_dev->ctrl_dis & (1 << EXPOSURE))
+		return;
 	sccb_write(gspca_dev, 0x10,			/* aec[9:2] */
-			expo[sd->exposure]);
+			expo[sd->ctrls[EXPOSURE].val]);
 
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
@@ -977,7 +1044,9 @@ static void setsharpness(struct gspca_de
 	struct sd *sd = (struct sd *) gspca_dev;
 	s8 val;
 
-	val = sd->sharpness;
+	if (gspca_dev->ctrl_dis & (1 << SHARPNESS))
+		return;
+	val = sd->ctrls[SHARPNESS].val;
 	if (val < 0) {				/* auto */
 		val = sccb_read(gspca_dev, 0x42);	/* com17 */
 		sccb_write(gspca_dev, 0xff, 0x00);
@@ -1006,8 +1075,10 @@ static void setsatur(struct gspca_dev *g
 		{0x48, 0x90}
 	};
 
-	val1 = matrix[sd->satur][0];
-	val2 = matrix[sd->satur][1];
+	if (gspca_dev->ctrl_dis & (1 << SATUR))
+		return;
+	val1 = matrix[sd->ctrls[SATUR].val][0];
+	val2 = matrix[sd->ctrls[SATUR].val][1];
 	val3 = val1 + val2;
 	sccb_write(gspca_dev, 0x4f, val3);	/* matrix coeff */
 	sccb_write(gspca_dev, 0x50, val3);
@@ -1022,14 +1093,16 @@ static void setsatur(struct gspca_dev *g
 	sccb_write(gspca_dev, 0x41, val1);
 }
 
-static void setfreq(struct gspca_dev *gspca_dev)
+static void setlightfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
+	if (gspca_dev->ctrl_dis & (1 << LIGHTFREQ))
+		return;
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->freq == 0) {
+	if (sd->ctrls[LIGHTFREQ].val == 0) {
 		sccb_write(gspca_dev, 0x13, val & 0xdf);
 		return;
 	}
@@ -1037,7 +1110,7 @@ static void setfreq(struct gspca_dev *gs
 
 	val = sccb_read(gspca_dev, 0x42);		/* com17 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->freq == 1)
+	if (sd->ctrls[LIGHTFREQ].val == 1)
 		val |= 0x01;
 	else
 		val &= 0xfe;
@@ -1049,34 +1122,19 @@ static int sd_config(struct gspca_dev *g
 		     const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam;
-
-	cam = &gspca_dev->cam;
 
-	cam->cam_mode = ov965x_mode;
-	cam->nmodes = ARRAY_SIZE(ov965x_mode);
+	gspca_dev->cam.ctrls = sd->ctrls;
 
-	sd->brightness = BRIGHTNESS_DEF;
-	sd->contrast = CONTRAST_DEF;
 #if AUTOGAIN_DEF != 0
-	sd->autogain = AUTOGAIN_DEF;
-	gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-#endif
-#if EXPO_DEF != 0
-	sd->exposure = EXPO_DEF;
-#endif
-#if SHARPNESS_DEF != 0
-	sd->sharpness = SHARPNESS_DEF;
+	gspca_dev->ctrl_inac |= (1 << EXPOSURE);
 #endif
-	sd->satur = SATUR_DEF;
-	sd->freq = FREQ_DEF;
-
 	return 0;
 }
 
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	u16 sensor_id;
 
 	/* reset bridge */
@@ -1099,68 +1157,117 @@ static int sd_init(struct gspca_dev *gsp
 	PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
 
 	/* initialize */
-	reg_w_array(gspca_dev, bridge_init,
-			ARRAY_SIZE(bridge_init));
-	sccb_w_array(gspca_dev, sensor_init,
-			ARRAY_SIZE(sensor_init));
-	reg_w_array(gspca_dev, bridge_init_2,
-			ARRAY_SIZE(bridge_init_2));
-	sccb_w_array(gspca_dev, sensor_init_2,
-			ARRAY_SIZE(sensor_init_2));
-	reg_w(gspca_dev, 0xe0, 0x00);
-	reg_w(gspca_dev, 0xe0, 0x01);
-	set_led(gspca_dev, 0);
-	reg_w(gspca_dev, 0xe0, 0x00);
+	if ((sensor_id & 0xfff0) == 0x9650) {
+		sd->sensor = SENSOR_OV965x;
+
+		gspca_dev->cam.cam_mode = ov965x_mode;
+		gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
+
+		reg_w_array(gspca_dev, bridge_init,
+				ARRAY_SIZE(bridge_init));
+		sccb_w_array(gspca_dev, ov965x_init,
+				ARRAY_SIZE(ov965x_init));
+		reg_w_array(gspca_dev, bridge_init_2,
+				ARRAY_SIZE(bridge_init_2));
+		sccb_w_array(gspca_dev, ov965x_init_2,
+				ARRAY_SIZE(ov965x_init_2));
+		reg_w(gspca_dev, 0xe0, 0x00);
+		reg_w(gspca_dev, 0xe0, 0x01);
+		set_led(gspca_dev, 0);
+		reg_w(gspca_dev, 0xe0, 0x00);
+	} else if ((sensor_id & 0xfff0) == 0x9710) {
+		const char *p;
+		int l;
+
+		sd->sensor = SENSOR_OV971x;
+
+		gspca_dev->cam.cam_mode = ov971x_mode;
+		gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
+
+		/* no control yet */
+		gspca_dev->ctrl_dis = (1 << NCTRLS) - 1;
+
+		gspca_dev->cam.bulk = 1;
+		gspca_dev->cam.bulk_size = 16384;
+		gspca_dev->cam.bulk_nurbs = 2;
+
+		sccb_w_array(gspca_dev, ov971x_init,
+				ARRAY_SIZE(ov971x_init));
+
+		/* set video format on bridge processor */
+		/* access bridge processor's video format registers at: 0x00 */
+		reg_w(gspca_dev, 0x1c, 0x00);
+		/*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
+		reg_w(gspca_dev, 0x1d, 0x00);
+
+		/* Will W. specific stuff
+		 * set VSYNC to
+		 *	output (0x1f) if first webcam
+		 *	input (0x17) if 2nd or 3rd webcam */
+		p = video_device_node_name(&gspca_dev->vdev);
+		l = strlen(p) - 1;
+		if (p[l] == '0')
+			reg_w(gspca_dev, 0x56, 0x1f);
+		else
+			reg_w(gspca_dev, 0x56, 0x17);
+	} else {
+		err("Unknown sensor %04x", sensor_id);
+		return -EINVAL;
+	}
 
 	return gspca_dev->usb_err;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_OV971x)
+		return gspca_dev->usb_err;
 	switch (gspca_dev->curr_mode) {
 	case QVGA_MODE:			/* 320x240 */
-		sccb_w_array(gspca_dev, sensor_start_1_vga,
-				ARRAY_SIZE(sensor_start_1_vga));
+		sccb_w_array(gspca_dev, ov965x_start_1_vga,
+				ARRAY_SIZE(ov965x_start_1_vga));
 		reg_w_array(gspca_dev, bridge_start_qvga,
 				ARRAY_SIZE(bridge_start_qvga));
-		sccb_w_array(gspca_dev, sensor_start_2_qvga,
-				ARRAY_SIZE(sensor_start_2_qvga));
+		sccb_w_array(gspca_dev, ov965x_start_2_qvga,
+				ARRAY_SIZE(ov965x_start_2_qvga));
 		break;
 	case VGA_MODE:			/* 640x480 */
-		sccb_w_array(gspca_dev, sensor_start_1_vga,
-				ARRAY_SIZE(sensor_start_1_vga));
+		sccb_w_array(gspca_dev, ov965x_start_1_vga,
+				ARRAY_SIZE(ov965x_start_1_vga));
 		reg_w_array(gspca_dev, bridge_start_vga,
 				ARRAY_SIZE(bridge_start_vga));
-		sccb_w_array(gspca_dev, sensor_start_2_vga,
-				ARRAY_SIZE(sensor_start_2_vga));
+		sccb_w_array(gspca_dev, ov965x_start_2_vga,
+				ARRAY_SIZE(ov965x_start_2_vga));
 		break;
 	case SVGA_MODE:			/* 800x600 */
-		sccb_w_array(gspca_dev, sensor_start_1_svga,
-				ARRAY_SIZE(sensor_start_1_svga));
+		sccb_w_array(gspca_dev, ov965x_start_1_svga,
+				ARRAY_SIZE(ov965x_start_1_svga));
 		reg_w_array(gspca_dev, bridge_start_svga,
 				ARRAY_SIZE(bridge_start_svga));
-		sccb_w_array(gspca_dev, sensor_start_2_svga,
-				ARRAY_SIZE(sensor_start_2_svga));
+		sccb_w_array(gspca_dev, ov965x_start_2_svga,
+				ARRAY_SIZE(ov965x_start_2_svga));
 		break;
 	case XGA_MODE:			/* 1024x768 */
-		sccb_w_array(gspca_dev, sensor_start_1_xga,
-				ARRAY_SIZE(sensor_start_1_xga));
+		sccb_w_array(gspca_dev, ov965x_start_1_xga,
+				ARRAY_SIZE(ov965x_start_1_xga));
 		reg_w_array(gspca_dev, bridge_start_xga,
 				ARRAY_SIZE(bridge_start_xga));
-		sccb_w_array(gspca_dev, sensor_start_2_svga,
-				ARRAY_SIZE(sensor_start_2_svga));
+		sccb_w_array(gspca_dev, ov965x_start_2_svga,
+				ARRAY_SIZE(ov965x_start_2_svga));
 		break;
 	default:
 /*	case SXGA_MODE:			 * 1280x1024 */
-		sccb_w_array(gspca_dev, sensor_start_1_sxga,
-				ARRAY_SIZE(sensor_start_1_sxga));
+		sccb_w_array(gspca_dev, ov965x_start_1_sxga,
+				ARRAY_SIZE(ov965x_start_1_sxga));
 		reg_w_array(gspca_dev, bridge_start_sxga,
 				ARRAY_SIZE(bridge_start_sxga));
-		sccb_w_array(gspca_dev, sensor_start_2_sxga,
-				ARRAY_SIZE(sensor_start_2_sxga));
+		sccb_w_array(gspca_dev, ov965x_start_2_sxga,
+				ARRAY_SIZE(ov965x_start_2_sxga));
 		break;
 	}
-	setfreq(gspca_dev);
+	setlightfreq(gspca_dev);
 	setautogain(gspca_dev);
 	setbrightness(gspca_dev);
 	setcontrast(gspca_dev);
@@ -1198,9 +1305,11 @@ static void sd_pkt_scan(struct gspca_dev
 	__u32 this_pts;
 	u8 this_fid;
 	int remaining_len = len;
+	int payload_len;
 
+	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
 	do {
-		len = min(remaining_len, 2040);
+		len = min(remaining_len, payload_len);
 
 		/* Payloads are prefixed with a UVC-style header.  We
 		   consider a frame to start when the FID toggles, or the PTS
@@ -1262,138 +1371,6 @@ scan_next:
 	} while (remaining_len > 0);
 }
 
-/* controls */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->brightness = val;
-	if (gspca_dev->streaming)
-		setbrightness(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->brightness;
-	return 0;
-}
-
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->contrast = val;
-	if (gspca_dev->streaming)
-		setcontrast(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->contrast;
-	return 0;
-}
-
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->autogain = val;
-
-	if (gspca_dev->streaming) {
-		if (val)
-			gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-		else
-			gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
-		setautogain(gspca_dev);
-	}
-	return gspca_dev->usb_err;
-}
-
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->autogain;
-	return 0;
-}
-
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->exposure = val;
-	if (gspca_dev->streaming)
-		setexposure(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->exposure;
-	return 0;
-}
-
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->sharpness = val;
-	if (gspca_dev->streaming)
-		setsharpness(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->sharpness;
-	return 0;
-}
-
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->satur = val;
-	if (gspca_dev->streaming)
-		setsatur(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->satur;
-	return 0;
-}
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->freq = val;
-	if (gspca_dev->streaming)
-		setfreq(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->freq;
-	return 0;
-}
-
 static int sd_querymenu(struct gspca_dev *gspca_dev,
 			struct v4l2_querymenu *menu)
 {
@@ -1419,7 +1396,7 @@ static int sd_querymenu(struct gspca_dev
 static const struct sd_desc sd_desc = {
 	.name     = MODULE_NAME,
 	.ctrls    = sd_ctrls,
-	.nctrls   = ARRAY_SIZE(sd_ctrls),
+	.nctrls   = NCTRLS,
 	.config   = sd_config,
 	.init     = sd_init,
 	.start    = sd_start,
@@ -1430,6 +1407,7 @@ static const struct sd_desc sd_desc = {
 
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x05a9, 0x8065)},
 	{USB_DEVICE(0x06f8, 0x3003)},
 	{}
 };
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/ov534.c linux-libre-3.2-gnu1/drivers/media/video/gspca/ov534.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/ov534.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/ov534.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov534"
 
 #include "gspca.h"
@@ -775,7 +777,7 @@ static void ov534_reg_write(struct gspca
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	if (ret < 0) {
-		err("write failed %d", ret);
+		pr_err("write failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -794,7 +796,7 @@ static u8 ov534_reg_read(struct gspca_de
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("read failed %d", ret);
+		pr_err("read failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 	return gspca_dev->usb_buf[0];
@@ -858,7 +860,7 @@ static void sccb_reg_write(struct gspca_
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 
 	if (!sccb_check_status(gspca_dev)) {
-		err("sccb_reg_write failed");
+		pr_err("sccb_reg_write failed\n");
 		gspca_dev->usb_err = -EIO;
 	}
 }
@@ -868,11 +870,11 @@ static u8 sccb_reg_read(struct gspca_dev
 	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_reg_read failed 1");
+		pr_err("sccb_reg_read failed 1\n");
 
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_reg_read failed 2");
+		pr_err("sccb_reg_read failed 2\n");
 
 	return ov534_reg_read(gspca_dev, OV534_REG_READ);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/pac207.c linux-libre-3.2-gnu1/drivers/media/video/gspca/pac207.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/pac207.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/pac207.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac207"
 
 #include <linux/input.h>
@@ -178,8 +180,8 @@ static int pac207_write_regs(struct gspc
 			0x00, index,
 			gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
 	if (err < 0)
-		err("Failed to write registers to index 0x%04X, error %d)",
-			index, err);
+		pr_err("Failed to write registers to index 0x%04X, error %d\n",
+		       index, err);
 
 	return err;
 }
@@ -194,8 +196,8 @@ static int pac207_write_reg(struct gspca
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
 	if (err)
-		err("Failed to write a register (index 0x%04X,"
-			" value 0x%02X, error %d)", index, value, err);
+		pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+		       index, value, err);
 
 	return err;
 }
@@ -210,8 +212,8 @@ static int pac207_read_reg(struct gspca_
 			0x00, index,
 			gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
 	if (res < 0) {
-		err("Failed to read a register (index 0x%04X, error %d)",
-			index, res);
+		pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+		       index, res);
 		return res;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/pac7302.c linux-libre-3.2-gnu1/drivers/media/video/gspca/pac7302.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/pac7302.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/pac7302.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,8 @@
     3   | 0x21       | sethvflip()
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac7302"
 
 #include <linux/input.h>
@@ -408,8 +410,8 @@ static void reg_w_buf(struct gspca_dev *
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w_buf failed index 0x%02x, error %d",
-			index, ret);
+		pr_err("reg_w_buf failed index 0x%02x, error %d\n",
+		       index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -431,8 +433,8 @@ static void reg_w(struct gspca_dev *gspc
 			0, index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
-			index, value, ret);
+		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+		       index, value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -466,9 +468,8 @@ static void reg_w_page(struct gspca_dev
 				0, index, gspca_dev->usb_buf, 1,
 				500);
 		if (ret < 0) {
-			err("reg_w_page() failed index 0x%02x, "
-			"value 0x%02x, error %d",
-				index, page[index], ret);
+			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+			       index, page[index], ret);
 			gspca_dev->usb_err = ret;
 			break;
 		}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/pac7311.c linux-libre-3.2-gnu1/drivers/media/video/gspca/pac7311.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/pac7311.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/pac7311.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,8 @@
 		for max gain, 0x14 for minimal gain.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac7311"
 
 #include <linux/input.h>
@@ -276,8 +278,8 @@ static void reg_w_buf(struct gspca_dev *
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w_buf() failed index 0x%02x, error %d",
-			index, ret);
+		pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
+		       index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -299,8 +301,8 @@ static void reg_w(struct gspca_dev *gspc
 			0, index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
-			index, value, ret);
+		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+		       index, value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -334,9 +336,8 @@ static void reg_w_page(struct gspca_dev
 				0, index, gspca_dev->usb_buf, 1,
 				500);
 		if (ret < 0) {
-			err("reg_w_page() failed index 0x%02x, "
-			"value 0x%02x, error %d",
-				index, page[index], ret);
+			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+			       index, page[index], ret);
 			gspca_dev->usb_err = ret;
 			break;
 		}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/se401.c linux-libre-3.2-gnu1/drivers/media/video/gspca/se401.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/se401.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/se401.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "se401"
 
 #define BULK_SIZE 4096
@@ -144,8 +146,8 @@ static void se401_write_req(struct gspca
 			      value, 0, NULL, 0, 1000);
 	if (err < 0) {
 		if (!silent)
-			err("write req failed req %#04x val %#04x error %d",
-			    req, value, err);
+			pr_err("write req failed req %#04x val %#04x error %d\n",
+			       req, value, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -158,7 +160,7 @@ static void se401_read_req(struct gspca_
 		return;
 
 	if (USB_BUF_SZ < READ_REQ_SIZE) {
-		err("USB_BUF_SZ too small!!");
+		pr_err("USB_BUF_SZ too small!!\n");
 		gspca_dev->usb_err = -ENOBUFS;
 		return;
 	}
@@ -169,7 +171,8 @@ static void se401_read_req(struct gspca_
 			      0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
 	if (err < 0) {
 		if (!silent)
-			err("read req failed req %#04x error %d", req, err);
+			pr_err("read req failed req %#04x error %d\n",
+			       req, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -188,8 +191,8 @@ static void se401_set_feature(struct gsp
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      param, selector, NULL, 0, 1000);
 	if (err < 0) {
-		err("set feature failed sel %#04x param %#04x error %d",
-		    selector, param, err);
+		pr_err("set feature failed sel %#04x param %#04x error %d\n",
+		       selector, param, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -202,7 +205,7 @@ static int se401_get_feature(struct gspc
 		return gspca_dev->usb_err;
 
 	if (USB_BUF_SZ < 2) {
-		err("USB_BUF_SZ too small!!");
+		pr_err("USB_BUF_SZ too small!!\n");
 		gspca_dev->usb_err = -ENOBUFS;
 		return gspca_dev->usb_err;
 	}
@@ -213,7 +216,8 @@ static int se401_get_feature(struct gspc
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0, selector, gspca_dev->usb_buf, 2, 1000);
 	if (err < 0) {
-		err("get feature failed sel %#04x error %d", selector, err);
+		pr_err("get feature failed sel %#04x error %d\n",
+		       selector, err);
 		gspca_dev->usb_err = err;
 		return err;
 	}
@@ -300,21 +304,21 @@ static int sd_config(struct gspca_dev *g
 		return gspca_dev->usb_err;
 
 	if (cd[1] != 0x41) {
-		err("Wrong descriptor type");
+		pr_err("Wrong descriptor type\n");
 		return -ENODEV;
 	}
 
 	if (!(cd[2] & SE401_FORMAT_BAYER)) {
-		err("Bayer format not supported!");
+		pr_err("Bayer format not supported!\n");
 		return -ENODEV;
 	}
 
 	if (cd[3])
-		info("ExtraFeatures: %d", cd[3]);
+		pr_info("ExtraFeatures: %d\n", cd[3]);
 
 	n = cd[4] | (cd[5] << 8);
 	if (n > MAX_MODES) {
-		err("Too many frame sizes");
+		pr_err("Too many frame sizes\n");
 		return -ENODEV;
 	}
 
@@ -353,15 +357,16 @@ static int sd_config(struct gspca_dev *g
 			sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
 			sd->fmts[i].bytesperline = widths[i];
 			sd->fmts[i].sizeimage = widths[i] * heights[i];
-			info("Frame size: %dx%d bayer", widths[i], heights[i]);
+			pr_info("Frame size: %dx%d bayer\n",
+				widths[i], heights[i]);
 		} else {
 			/* Found a match use janggu compression */
 			sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
 			sd->fmts[i].bytesperline = 0;
 			sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
-			info("Frame size: %dx%d 1/%dth janggu",
-			     widths[i], heights[i],
-			     sd->fmts[i].priv * sd->fmts[i].priv);
+			pr_info("Frame size: %dx%d 1/%dth janggu\n",
+				widths[i], heights[i],
+				sd->fmts[i].priv * sd->fmts[i].priv);
 		}
 	}
 
@@ -571,11 +576,12 @@ static void sd_pkt_scan_janggu(struct gs
 		plen   = ((bits + 47) >> 4) << 1;
 		/* Sanity checks */
 		if (plen > 1024) {
-			err("invalid packet len %d restarting stream", plen);
+			pr_err("invalid packet len %d restarting stream\n",
+			       plen);
 			goto error;
 		}
 		if (info == 3) {
-			err("unknown frame info value restarting stream");
+			pr_err("unknown frame info value restarting stream\n");
 			goto error;
 		}
 
@@ -599,8 +605,8 @@ static void sd_pkt_scan_janggu(struct gs
 			break;
 		case 1: /* EOF */
 			if (sd->pixels_read != imagesize) {
-				err("frame size %d expected %d",
-				    sd->pixels_read, imagesize);
+				pr_err("frame size %d expected %d\n",
+				       sd->pixels_read, imagesize);
 				goto error;
 			}
 			sd_complete_frame(gspca_dev, sd->packet, plen);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sn9c2028.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sn9c2028.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sn9c2028.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sn9c2028.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sn9c2028"
 
 #include "gspca.h"
@@ -75,8 +77,8 @@ static int sn9c2028_command(struct gspca
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			2, 0, gspca_dev->usb_buf, 6, 500);
 	if (rc < 0) {
-		err("command write [%02x] error %d",
-				gspca_dev->usb_buf[0], rc);
+		pr_err("command write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], rc);
 		return rc;
 	}
 
@@ -93,7 +95,7 @@ static int sn9c2028_read1(struct gspca_d
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			1, 0, gspca_dev->usb_buf, 1, 500);
 	if (rc != 1) {
-		err("read1 error %d", rc);
+		pr_err("read1 error %d\n", rc);
 		return (rc < 0) ? rc : -EIO;
 	}
 	PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
@@ -109,7 +111,7 @@ static int sn9c2028_read4(struct gspca_d
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			4, 0, gspca_dev->usb_buf, 4, 500);
 	if (rc != 4) {
-		err("read4 error %d", rc);
+		pr_err("read4 error %d\n", rc);
 		return (rc < 0) ? rc : -EIO;
 	}
 	memcpy(reading, gspca_dev->usb_buf, 4);
@@ -131,7 +133,7 @@ static int sn9c2028_long_command(struct
 	for (i = 0; i < 256 && status < 2; i++)
 		status = sn9c2028_read1(gspca_dev);
 	if (status != 2) {
-		err("long command status read error %d", status);
+		pr_err("long command status read error %d\n", status);
 		return (status < 0) ? status : -EIO;
 	}
 
@@ -638,7 +640,7 @@ static int sd_start(struct gspca_dev *gs
 		err_code = start_vivitar_cam(gspca_dev);
 		break;
 	default:
-		err("Starting unknown camera, please report this");
+		pr_err("Starting unknown camera, please report this\n");
 		return -ENXIO;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sn9c20x.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sn9c20x.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sn9c20x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sn9c20x.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/input.h>
 
 #include "gspca.h"
@@ -1123,7 +1125,7 @@ static int reg_r(struct gspca_dev *gspca
 			length,
 			500);
 	if (unlikely(result < 0 || result != length)) {
-		err("Read register failed 0x%02X", reg);
+		pr_err("Read register failed 0x%02X\n", reg);
 		return -EIO;
 	}
 	return 0;
@@ -1144,7 +1146,7 @@ static int reg_w(struct gspca_dev *gspca
 			length,
 			500);
 	if (unlikely(result < 0 || result != length)) {
-		err("Write register failed index 0x%02X", reg);
+		pr_err("Write register failed index 0x%02X\n", reg);
 		return -EIO;
 	}
 	return 0;
@@ -1275,14 +1277,14 @@ static int ov9650_init_sensor(struct gsp
 		return -EINVAL;
 
 	if (id != 0x7fa2) {
-		err("sensor id for ov9650 doesn't match (0x%04x)", id);
+		pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
 		return -ENODEV;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
 		if (i2c_w1(gspca_dev, ov9650_init[i].reg,
 				ov9650_init[i].val) < 0) {
-			err("OV9650 sensor initialization failed");
+			pr_err("OV9650 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1299,7 +1301,7 @@ static int ov9655_init_sensor(struct gsp
 	for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
 		if (i2c_w1(gspca_dev, ov9655_init[i].reg,
 				ov9655_init[i].val) < 0) {
-			err("OV9655 sensor initialization failed");
+			pr_err("OV9655 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1318,7 +1320,7 @@ static int soi968_init_sensor(struct gsp
 	for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
 		if (i2c_w1(gspca_dev, soi968_init[i].reg,
 				soi968_init[i].val) < 0) {
-			err("SOI968 sensor initialization failed");
+			pr_err("SOI968 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1338,7 +1340,7 @@ static int ov7660_init_sensor(struct gsp
 	for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
 		if (i2c_w1(gspca_dev, ov7660_init[i].reg,
 				ov7660_init[i].val) < 0) {
-			err("OV7660 sensor initialization failed");
+			pr_err("OV7660 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1355,7 +1357,7 @@ static int ov7670_init_sensor(struct gsp
 	for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
 		if (i2c_w1(gspca_dev, ov7670_init[i].reg,
 				ov7670_init[i].val) < 0) {
-			err("OV7670 sensor initialization failed");
+			pr_err("OV7670 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1379,14 +1381,14 @@ static int mt9v_init_sensor(struct gspca
 		for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
 					mt9v011_init[i].val) < 0) {
-				err("MT9V011 sensor initialization failed");
+				pr_err("MT9V011 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
 		sd->hstart = 2;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V011;
-		info("MT9V011 sensor detected");
+		pr_info("MT9V011 sensor detected\n");
 		return 0;
 	}
 
@@ -1397,7 +1399,7 @@ static int mt9v_init_sensor(struct gspca
 		for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
 					mt9v111_init[i].val) < 0) {
-				err("MT9V111 sensor initialization failed");
+				pr_err("MT9V111 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
@@ -1407,7 +1409,7 @@ static int mt9v_init_sensor(struct gspca
 		sd->hstart = 2;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V111;
-		info("MT9V111 sensor detected");
+		pr_info("MT9V111 sensor detected\n");
 		return 0;
 	}
 
@@ -1422,14 +1424,14 @@ static int mt9v_init_sensor(struct gspca
 		for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
 					mt9v112_init[i].val) < 0) {
-				err("MT9V112 sensor initialization failed");
+				pr_err("MT9V112 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
 		sd->hstart = 6;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V112;
-		info("MT9V112 sensor detected");
+		pr_info("MT9V112 sensor detected\n");
 		return 0;
 	}
 
@@ -1443,7 +1445,7 @@ static int mt9m112_init_sensor(struct gs
 	for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
 				mt9m112_init[i].val) < 0) {
-			err("MT9M112 sensor initialization failed");
+			pr_err("MT9M112 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1461,7 +1463,7 @@ static int mt9m111_init_sensor(struct gs
 	for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
 				mt9m111_init[i].val) < 0) {
-			err("MT9M111 sensor initialization failed");
+			pr_err("MT9M111 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1485,20 +1487,20 @@ static int mt9m001_init_sensor(struct gs
 	switch (id) {
 	case 0x8411:
 	case 0x8421:
-		info("MT9M001 color sensor detected");
+		pr_info("MT9M001 color sensor detected\n");
 		break;
 	case 0x8431:
-		info("MT9M001 mono sensor detected");
+		pr_info("MT9M001 mono sensor detected\n");
 		break;
 	default:
-		err("No MT9M001 chip detected, ID = %x\n", id);
+		pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
 		return -ENODEV;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
 				mt9m001_init[i].val) < 0) {
-			err("MT9M001 sensor initialization failed");
+			pr_err("MT9M001 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1517,7 +1519,7 @@ static int hv7131r_init_sensor(struct gs
 	for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
 		if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
 				hv7131r_init[i].val) < 0) {
-			err("HV7131R Sensor initialization failed");
+			pr_err("HV7131R Sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -2103,7 +2105,7 @@ static int sd_init(struct gspca_dev *gsp
 	for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
 		value = bridge_init[i][1];
 		if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
-			err("Device initialization failed");
+			pr_err("Device initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -2114,7 +2116,7 @@ static int sd_init(struct gspca_dev *gsp
 		reg_w1(gspca_dev, 0x1006, 0x20);
 
 	if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
-		err("Device initialization failed");
+		pr_err("Device initialization failed\n");
 		return -ENODEV;
 	}
 
@@ -2122,27 +2124,27 @@ static int sd_init(struct gspca_dev *gsp
 	case SENSOR_OV9650:
 		if (ov9650_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV9650 sensor detected");
+		pr_info("OV9650 sensor detected\n");
 		break;
 	case SENSOR_OV9655:
 		if (ov9655_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV9655 sensor detected");
+		pr_info("OV9655 sensor detected\n");
 		break;
 	case SENSOR_SOI968:
 		if (soi968_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("SOI968 sensor detected");
+		pr_info("SOI968 sensor detected\n");
 		break;
 	case SENSOR_OV7660:
 		if (ov7660_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV7660 sensor detected");
+		pr_info("OV7660 sensor detected\n");
 		break;
 	case SENSOR_OV7670:
 		if (ov7670_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV7670 sensor detected");
+		pr_info("OV7670 sensor detected\n");
 		break;
 	case SENSOR_MT9VPRB:
 		if (mt9v_init_sensor(gspca_dev) < 0)
@@ -2151,12 +2153,12 @@ static int sd_init(struct gspca_dev *gsp
 	case SENSOR_MT9M111:
 		if (mt9m111_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("MT9M111 sensor detected");
+		pr_info("MT9M111 sensor detected\n");
 		break;
 	case SENSOR_MT9M112:
 		if (mt9m112_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("MT9M112 sensor detected");
+		pr_info("MT9M112 sensor detected\n");
 		break;
 	case SENSOR_MT9M001:
 		if (mt9m001_init_sensor(gspca_dev) < 0)
@@ -2165,10 +2167,10 @@ static int sd_init(struct gspca_dev *gsp
 	case SENSOR_HV7131R:
 		if (hv7131r_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("HV7131R sensor detected");
+		pr_info("HV7131R sensor detected\n");
 		break;
 	default:
-		info("Unsupported Sensor");
+		pr_info("Unsupported Sensor\n");
 		return -ENODEV;
 	}
 
@@ -2263,19 +2265,19 @@ static int sd_start(struct gspca_dev *gs
 	switch (mode & SCALE_MASK) {
 	case SCALE_1280x1024:
 		scale = 0xc0;
-		info("Set 1280x1024");
+		pr_info("Set 1280x1024\n");
 		break;
 	case SCALE_640x480:
 		scale = 0x80;
-		info("Set 640x480");
+		pr_info("Set 640x480\n");
 		break;
 	case SCALE_320x240:
 		scale = 0x90;
-		info("Set 320x240");
+		pr_info("Set 320x240\n");
 		break;
 	case SCALE_160x120:
 		scale = 0xa0;
-		info("Set 160x120");
+		pr_info("Set 160x120\n");
 		break;
 	}
 
@@ -2513,7 +2515,7 @@ static const struct usb_device_id device
 	{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
 	{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
 	{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
-	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
 	{USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
 	{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
 	{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sonixj.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sonixj.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sonixj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sonixj.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
  *
- * Copyright (C) 2009-2010 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
  * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sonixj"
 
 #include <linux/input.h>
@@ -136,7 +138,7 @@ static void setillum(struct gspca_dev *g
 static void setfreq(struct gspca_dev *gspca_dev);
 
 static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] =  {
+[BRIGHTNESS] = {
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -157,7 +159,7 @@ static const struct ctrl sd_ctrls[NCTRLS
 #define CONTRAST_MAX 127
 		.maximum = CONTRAST_MAX,
 		.step    = 1,
-		.default_value = 63,
+		.default_value = 20,
 	    },
 	    .set_control = setcontrast
 	},
@@ -737,7 +739,7 @@ static const u8 mi0360_sensor_init[][8]
 	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
-	{0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
+	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
 	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
 	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
@@ -1277,7 +1279,7 @@ static const u8 soi768_sensor_param1[][8
 			/* global gain ? : 07 - change with 0x15 at the end */
 	{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
 	{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
-	{0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
+	{0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
 			/* exposure ? : 0200 - change with 0x1e at the end */
 	{}
 };
@@ -1395,7 +1397,7 @@ static void reg_r(struct gspca_dev *gspc
 		return;
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -1408,7 +1410,7 @@ static void reg_r(struct gspca_dev *gspc
 			500);
 	PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1432,7 +1434,7 @@ static void reg_w1(struct gspca_dev *gsp
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w1 err %d", ret);
+		pr_err("reg_w1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1449,7 +1451,7 @@ static void reg_w(struct gspca_dev *gspc
 		value, buffer[0], buffer[1]);
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 #endif
@@ -1462,7 +1464,7 @@ static void reg_w(struct gspca_dev *gspc
 			gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1502,7 +1504,7 @@ static void i2c_w1(struct gspca_dev *gsp
 			gspca_dev->usb_buf, 8,
 			500);
 	if (ret < 0) {
-		err("i2c_w1 err %d", ret);
+		pr_err("i2c_w1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1527,7 +1529,7 @@ static void i2c_w8(struct gspca_dev *gsp
 			500);
 	msleep(2);
 	if (ret < 0) {
-		err("i2c_w8 err %d", ret);
+		pr_err("i2c_w8 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1591,7 +1593,7 @@ static void hv7131r_probe(struct gspca_d
 		PDEBUG(D_PROBE, "Sensor HV7131R found");
 		return;
 	}
-	warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
+	pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
 		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
 		gspca_dev->usb_buf[2]);
 }
@@ -1710,7 +1712,7 @@ static void ov7648_probe(struct gspca_de
 		sd->sensor = SENSOR_PO1030;
 		return;
 	}
-	err("Unknown sensor %04x", val);
+	pr_err("Unknown sensor %04x\n", val);
 }
 
 /* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
@@ -1748,7 +1750,7 @@ static void po2030n_probe(struct gspca_d
 		PDEBUG(D_PROBE, "Sensor po2030n");
 /*		sd->sensor = SENSOR_PO2030N; */
 	} else {
-		err("Unknown sensor ID %04x", val);
+		pr_err("Unknown sensor ID %04x\n", val);
 	}
 }
 
@@ -2006,8 +2008,7 @@ static void setbrightness(struct gspca_d
 	case SENSOR_OM6802:
 		expo = brightness << 2;
 		sd->exposure = setexposure(gspca_dev, expo);
-		k2 = brightness >> 3;
-		break;
+		return;			/* Y offset already set */
 	}
 
 	reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
@@ -2019,13 +2020,13 @@ static void setcontrast(struct gspca_dev
 	u8 k2;
 	u8 contrast[6];
 
-	k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
-				+ 0x10;		/* 10..40 */
+	k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+				+ 37;		/* 37..73 */
 	contrast[0] = (k2 + 1) / 2;		/* red */
 	contrast[1] = 0;
 	contrast[2] = k2;			/* green */
 	contrast[3] = 0;
-	contrast[4] = (k2 + 1) / 5;		/* blue */
+	contrast[4] = k2 / 5;			/* blue */
 	contrast[5] = 0;
 	reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
 }
@@ -2507,9 +2508,7 @@ static int sd_start(struct gspca_dev *gs
 		break;
 	case SENSOR_HV7131R:
 	case SENSOR_MI0360:
-		if (mode)
-			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */
-		else
+		if (!mode)
 			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
 		reg17 &= ~MCK_SIZE_MASK;
 		reg17 |= 0x01;			/* clock / 1 */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca1528.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca1528.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca1528.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca1528.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * spca1528 subdriver
  *
- * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
  *
  * 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
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca1528"
 
 #include "gspca.h"
@@ -171,7 +173,7 @@ static void reg_r(struct gspca_dev *gspc
 	PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
 			 gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -193,7 +195,7 @@ static void reg_w(struct gspca_dev *gspc
 			value, index,
 			NULL, 0, 500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -217,21 +219,23 @@ static void reg_wb(struct gspca_dev *gsp
 			value, index,
 			gspca_dev->usb_buf, 1, 500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
 
 static void wait_status_0(struct gspca_dev *gspca_dev)
 {
-	int i;
+	int i, w;
 
-	i = 20;
+	i = 16;
+	w = 0;
 	do {
 		reg_r(gspca_dev, 0x21, 0x0000, 1);
 		if (gspca_dev->usb_buf[0] == 0)
 			return;
-		msleep(30);
+		w += 15;
+		msleep(w);
 	} while (--i > 0);
 	PDEBUG(D_ERR, "wait_status_0 timeout");
 	gspca_dev->usb_err = -ETIME;
@@ -307,8 +311,6 @@ static int sd_config(struct gspca_dev *g
 	sd->color = COLOR_DEF;
 	sd->sharpness = SHARPNESS_DEF;
 
-	gspca_dev->nbalt = 4;		/* use alternate setting 3 */
-
 	return 0;
 }
 
@@ -347,8 +349,12 @@ static int sd_isoc_init(struct gspca_dev
 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
 	reg_r(gspca_dev, 0x25, 0x0004, 1);
-	reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
+	reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);	/* 420 */
 	reg_r(gspca_dev, 0x27, 0x0000, 1);
+
+/* not useful..
+	gspca_dev->alt = 4;		* use alternate setting 3 */
+
 	return gspca_dev->usb_err;
 }
 
@@ -361,8 +367,8 @@ static int sd_start(struct gspca_dev *gs
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 
-	/* the JPEG quality seems to be 82% */
-	jpeg_set_qual(sd->jpeg_hdr, 82);
+	/* the JPEG quality shall be 85% */
+	jpeg_set_qual(sd->jpeg_hdr, 85);
 
 	/* set the controls */
 	setbrightness(gspca_dev);
@@ -377,7 +383,7 @@ static int sd_start(struct gspca_dev *gs
 
 	/* start the capture */
 	wait_status_0(gspca_dev);
-	reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
+	reg_w(gspca_dev, 0x31, 0x0000, 0x0004);	/* start request */
 	wait_status_1(gspca_dev);
 	wait_status_0(gspca_dev);
 	msleep(200);
@@ -390,7 +396,7 @@ static void sd_stopN(struct gspca_dev *g
 {
 	/* stop the capture */
 	wait_status_0(gspca_dev);
-	reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
+	reg_w(gspca_dev, 0x31, 0x0000, 0x0000);	/* stop request */
 	wait_status_1(gspca_dev);
 	wait_status_0(gspca_dev);
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca500.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca500.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca500.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca500"
 
 #include "gspca.h"
@@ -396,7 +398,7 @@ static int reg_w(struct gspca_dev *gspca
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -418,7 +420,7 @@ static int reg_r_12(struct gspca_dev *gs
 			gspca_dev->usb_buf, length,
 			500);		/* timeout */
 	if (ret < 0) {
-		err("reg_r_12 err %d", ret);
+		pr_err("reg_r_12 err %d\n", ret);
 		return ret;
 	}
 	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca501.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca501.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca501.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca501.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca501"
 
 #include "gspca.h"
@@ -1852,7 +1854,7 @@ static int reg_write(struct usb_device *
 	PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
 		req, index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca505.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca505.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca505.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca505.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca505"
 
 #include "gspca.h"
@@ -578,7 +580,7 @@ static int reg_write(struct usb_device *
 	PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
 		req, index, value, ret);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -685,8 +687,8 @@ static int sd_start(struct gspca_dev *gs
 		return ret;
 	}
 	if (ret != 0x0101) {
-		err("After vector read returns 0x%04x should be 0x0101",
-			ret);
+		pr_err("After vector read returns 0x%04x should be 0x0101\n",
+		       ret);
 	}
 
 	ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca508.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca508.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca508.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca508.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca508"
 
 #include "gspca.h"
@@ -1275,7 +1277,7 @@ static int reg_write(struct usb_device *
 	PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
 		index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -1297,7 +1299,7 @@ static int reg_read(struct gspca_dev *gs
 	PDEBUG(D_USBI, "reg read i:%04x --> %02x",
 		index, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_read err %d", ret);
+		pr_err("reg_read err %d\n", ret);
 		return ret;
 	}
 	return gspca_dev->usb_buf[0];
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/spca561.c linux-libre-3.2-gnu1/drivers/media/video/gspca/spca561.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/spca561.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/spca561.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca561"
 
 #include <linux/input.h>
@@ -315,7 +317,7 @@ static void reg_w_val(struct usb_device
 			      value, index, NULL, 0, 500);
 	PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 }
 
 static void write_vector(struct gspca_dev *gspca_dev,
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sq905.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sq905.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sq905.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sq905.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,8 @@
  * drivers.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq905"
 
 #include <linux/workqueue.h>
@@ -123,8 +125,7 @@ static int sq905_command(struct gspca_de
 			      SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -135,8 +136,7 @@ static int sq905_command(struct gspca_de
 			      SQ905_PING, 0, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed 2 (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -158,7 +158,7 @@ static int sq905_ack_frame(struct gspca_
 			      SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)", __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -186,7 +186,7 @@ sq905_read_data(struct gspca_dev *gspca_
 	if (need_lock)
 		mutex_unlock(&gspca_dev->usb_lock);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)", __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 	ret = usb_bulk_msg(gspca_dev->dev,
@@ -195,8 +195,7 @@ sq905_read_data(struct gspca_dev *gspca_
 
 	/* successful, it returns 0, otherwise  negative */
 	if (ret < 0 || act_len != size) {
-		err("bulk read fail (%d) len %d/%d",
-			ret, act_len, size);
+		pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
 		return -EIO;
 	}
 	return 0;
@@ -226,7 +225,7 @@ static void sq905_dostream(struct work_s
 
 	buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto quit_stream;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sq905c.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sq905c.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sq905c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sq905c.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * and may contain code fragments from it.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq905c"
 
 #include <linux/workqueue.h>
@@ -95,8 +97,7 @@ static int sq905c_command(struct gspca_d
 			      command, index, NULL, 0,
 			      SQ905C_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -115,8 +116,7 @@ static int sq905c_read(struct gspca_dev
 			      command, index, gspca_dev->usb_buf, size,
 			      SQ905C_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-		       __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -146,7 +146,7 @@ static void sq905c_dostream(struct work_
 
 	buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto quit_stream;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sq930x.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sq930x.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sq930x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sq930x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq930x"
 
 #include "gspca.h"
@@ -468,7 +470,7 @@ static void reg_r(struct gspca_dev *gspc
 			value, 0, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_r %04x failed %d", value, ret);
+		pr_err("reg_r %04x failed %d\n", value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -488,7 +490,7 @@ static void reg_w(struct gspca_dev *gspc
 			500);
 	msleep(30);
 	if (ret < 0) {
-		err("reg_w %04x %04x failed %d", value, index, ret);
+		pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -511,7 +513,7 @@ static void reg_wb(struct gspca_dev *gsp
 			1000);
 	msleep(30);
 	if (ret < 0) {
-		err("reg_wb %04x %04x failed %d", value, index, ret);
+		pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -556,7 +558,7 @@ static void i2c_write(struct sd *sd,
 			gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
 			500);
 	if (ret < 0) {
-		err("i2c_write failed %d", ret);
+		pr_err("i2c_write failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -575,7 +577,7 @@ static void ucbus_write(struct gspca_dev
 
 #ifdef GSPCA_DEBUG
 	if ((batchsize - 1) * 3 > USB_BUF_SZ) {
-		err("Bug: usb_buf overflow");
+		pr_err("Bug: usb_buf overflow\n");
 		gspca_dev->usb_err = -ENOMEM;
 		return;
 	}
@@ -612,7 +614,7 @@ static void ucbus_write(struct gspca_dev
 				gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
 				500);
 		if (ret < 0) {
-			err("ucbus_write failed %d", ret);
+			pr_err("ucbus_write failed %d\n", ret);
 			gspca_dev->usb_err = ret;
 			return;
 		}
@@ -688,7 +690,7 @@ static void cmos_probe(struct gspca_dev
 			break;
 	}
 	if (i >= ARRAY_SIZE(probe_order)) {
-		err("Unknown sensor");
+		pr_err("Unknown sensor\n");
 		gspca_dev->usb_err = -EINVAL;
 		return;
 	}
@@ -696,7 +698,8 @@ static void cmos_probe(struct gspca_dev
 	switch (sd->sensor) {
 	case SENSOR_OV7660:
 	case SENSOR_OV9630:
-		err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
+		pr_err("Sensor %s not yet treated\n",
+		       sensor_tb[sd->sensor].name);
 		gspca_dev->usb_err = -EINVAL;
 		break;
 	}
@@ -1091,7 +1094,7 @@ static void sd_dq_callback(struct gspca_
 	gspca_dev->cam.bulk_nurbs = 1;
 	ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
 	if (ret < 0)
-		err("sd_dq_callback() err %d", ret);
+		pr_err("sd_dq_callback() err %d\n", ret);
 
 	/* wait a little time, otherwise the webcam crashes */
 	msleep(100);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stk014.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stk014.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stk014.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stk014.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "stk014"
 
 #include "gspca.h"
@@ -137,7 +139,7 @@ static u8 reg_r(struct gspca_dev *gspca_
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return 0;
 	}
@@ -162,7 +164,7 @@ static void reg_w(struct gspca_dev *gspc
 			0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -192,7 +194,7 @@ static void rcv_val(struct gspca_dev *gs
 			&alen,
 			500);		/* timeout in milliseconds */
 	if (ret < 0) {
-		err("rcv_val err %d", ret);
+		pr_err("rcv_val err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -235,7 +237,7 @@ static void snd_val(struct gspca_dev *gs
 			&alen,
 			500);	/* timeout in milliseconds */
 	if (ret < 0) {
-		err("snd_val err %d", ret);
+		pr_err("snd_val err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	} else {
 		if (ads == 0x003f08) {
@@ -315,7 +317,7 @@ static int sd_init(struct gspca_dev *gsp
 	ret = reg_r(gspca_dev, 0x0740);
 	if (gspca_dev->usb_err >= 0) {
 		if (ret != 0xff) {
-			err("init reg: 0x%02x", ret);
+			pr_err("init reg: 0x%02x\n", ret);
 			gspca_dev->usb_err = -EIO;
 		}
 	}
@@ -349,8 +351,8 @@ static int sd_start(struct gspca_dev *gs
 					gspca_dev->iface,
 					gspca_dev->alt);
 	if (ret < 0) {
-		err("set intf %d %d failed",
-			gspca_dev->iface, gspca_dev->alt);
+		pr_err("set intf %d %d failed\n",
+		       gspca_dev->iface, gspca_dev->alt);
 		gspca_dev->usb_err = ret;
 		goto out;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv0680.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv0680.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv0680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv0680.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "stv0680"
 
 #include "gspca.h"
@@ -79,7 +81,7 @@ static int stv_sndctrl(struct gspca_dev
 			      val, 0, gspca_dev->usb_buf, size, 500);
 
 	if ((ret < 0) && (req != 0x0a))
-		err("usb_control_msg error %i, request = 0x%x, error = %i",
+		pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
 		       set, req, ret);
 
 	return ret;
@@ -236,7 +238,7 @@ static int sd_config(struct gspca_dev *g
 
 	if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
 	    gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
-		err("Could not get descriptor 0100.");
+		pr_err("Could not get descriptor 0100\n");
 		return stv0680_handle_error(gspca_dev, -EIO);
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/Makefile linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \
 		      stv06xx_pb0100.o \
 		      stv06xx_st6422.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/input.h>
 #include "stv06xx_sensor.h"
 
@@ -189,7 +191,7 @@ int stv06xx_read_sensor(struct sd *sd, c
 			      0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
 			      STV06XX_URB_MSG_TIMEOUT);
 	if (err < 0) {
-		err("I2C: Read error writing address: %d", err);
+		pr_err("I2C: Read error writing address: %d\n", err);
 		return err;
 	}
 
@@ -213,14 +215,14 @@ static void stv06xx_dump_bridge(struct s
 	int i;
 	u8 data, buf;
 
-	info("Dumping all stv06xx bridge registers");
+	pr_info("Dumping all stv06xx bridge registers\n");
 	for (i = 0x1400; i < 0x160f; i++) {
 		stv06xx_read_bridge(sd, i, &data);
 
-		info("Read 0x%x from address 0x%x", data, i);
+		pr_info("Read 0x%x from address 0x%x\n", data, i);
 	}
 
-	info("Testing stv06xx bridge registers for writability");
+	pr_info("Testing stv06xx bridge registers for writability\n");
 	for (i = 0x1400; i < 0x160f; i++) {
 		stv06xx_read_bridge(sd, i, &data);
 		buf = data;
@@ -228,12 +230,12 @@ static void stv06xx_dump_bridge(struct s
 		stv06xx_write_bridge(sd, i, 0xff);
 		stv06xx_read_bridge(sd, i, &data);
 		if (data == 0xff)
-			info("Register 0x%x is read/write", i);
+			pr_info("Register 0x%x is read/write\n", i);
 		else if (data != buf)
-			info("Register 0x%x is read/write,"
-			     " but only partially", i);
+			pr_info("Register 0x%x is read/write, but only partially\n",
+				i);
 		else
-			info("Register 0x%x is read-only", i);
+			pr_info("Register 0x%x is read-only\n", i);
 
 		stv06xx_write_bridge(sd, i, buf);
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.h linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.h
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,8 @@
 
 #define STV_ISOC_ENDPOINT_ADDR		0x81
 
+#define STV_R                           0x0509
+
 #define STV_REG23			0x0423
 
 /* Control registers of the STV0600 ASIC */
@@ -61,7 +63,9 @@
 
 /* Refers to the CIF 352x288 and QCIF 176x144 */
 /* 1: 288 lines, 2: 144 lines */
-#define STV_Y_CTRL			0x15c3
+#define STV_Y_CTRL		        0x15c3
+
+#define STV_RESET                       0x1620
 
 /* 0xa: 352 columns, 0x6: 176 columns */
 #define STV_X_CTRL			0x1680
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_hdcs.h"
 
 static const struct ctrl hdcs1x00_ctrl[] = {
@@ -428,7 +430,7 @@ static int hdcs_probe_1x00(struct sd *sd
 	if (ret < 0 || sensor != 0x08)
 		return -ENODEV;
 
-	info("HDCS-1000/1100 sensor detected");
+	pr_info("HDCS-1000/1100 sensor detected\n");
 
 	sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
@@ -487,7 +489,7 @@ static int hdcs_probe_1020(struct sd *sd
 	if (ret < 0 || sensor != 0x10)
 		return -ENODEV;
 
-	info("HDCS-1020 sensor detected");
+	pr_info("HDCS-1020 sensor detected\n");
 
 	sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
@@ -601,11 +603,11 @@ static int hdcs_dump(struct sd *sd)
 {
 	u16 reg, val;
 
-	info("Dumping sensor registers:");
+	pr_info("Dumping sensor registers:\n");
 
 	for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
 		stv06xx_read_sensor(sd, reg, &val);
-		info("reg 0x%02x = 0x%02x", reg, val);
+		pr_info("reg 0x%02x = 0x%02x\n", reg, val);
 	}
 	return 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,8 @@
  * PB_CFILLIN       = R5  = 0x0E (14 dec)     : Sets the frame rate
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_pb0100.h"
 
 static const struct ctrl pb0100_ctrl[] = {
@@ -190,7 +192,7 @@ static int pb0100_probe(struct sd *sd)
 		if (!sensor_settings)
 			return -ENOMEM;
 
-		info("Photobit pb0100 sensor detected");
+		pr_info("Photobit pb0100 sensor detected\n");
 
 		sd->gspca_dev.cam.cam_mode = pb0100_mode;
 		sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_st6422.h"
 
 /* controls */
@@ -136,7 +138,7 @@ static int st6422_probe(struct sd *sd)
 	if (sd->bridge != BRIDGE_ST6422)
 		return -ENODEV;
 
-	info("st6422 sensor detected");
+	pr_info("st6422 sensor detected\n");
 
 	sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
 	if (!sensor_settings)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_vv6410.h"
 
 static struct v4l2_pix_format vv6410_mode[] = {
@@ -112,7 +114,7 @@ static int vv6410_probe(struct sd *sd)
 		return -ENODEV;
 
 	if (data == 0x19) {
-		info("vv6410 sensor detected");
+		pr_info("vv6410 sensor detected\n");
 
 		sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
 					  GFP_KERNEL);
@@ -138,18 +140,7 @@ static int vv6410_init(struct sd *sd)
 	s32 *sensor_settings = sd->sensor_priv;
 
 	for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
-		/* if NULL then len contains single value */
-		if (stv_bridge_init[i].data == NULL) {
-			err = stv06xx_write_bridge(sd,
-				stv_bridge_init[i].start,
-				stv_bridge_init[i].len);
-		} else {
-			int j;
-			for (j = 0; j < stv_bridge_init[i].len; j++)
-				err = stv06xx_write_bridge(sd,
-					stv_bridge_init[i].start + j,
-					stv_bridge_init[i].data[j]);
-		}
+		stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
 	}
 
 	if (err < 0)
@@ -183,15 +174,6 @@ static int vv6410_start(struct sd *sd)
 	struct cam *cam = &sd->gspca_dev.cam;
 	u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
-	if (priv & VV6410_CROP_TO_QVGA) {
-		PDEBUG(D_CONF, "Cropping to QVGA");
-		stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
-		stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
-	} else {
-		stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
-		stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
-	}
-
 	if (priv & VV6410_SUBSAMPLE) {
 		PDEBUG(D_CONF, "Enabling subsampling");
 		stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
@@ -201,8 +183,8 @@ static int vv6410_start(struct sd *sd)
 	} else {
 		stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
 		stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+		stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
 
-		stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
 	}
 
 	/* Turn on LED */
@@ -242,11 +224,11 @@ static int vv6410_dump(struct sd *sd)
 	u8 i;
 	int err = 0;
 
-	info("Dumping all vv6410 sensor registers");
+	pr_info("Dumping all vv6410 sensor registers\n");
 	for (i = 0; i < 0xff && !err; i++) {
 		u16 data;
 		err = stv06xx_read_sensor(sd, i, &data);
-		info("Register 0x%x contained 0x%x", i, data);
+		pr_info("Register 0x%x contained 0x%x\n", i, data);
 	}
 	return (err < 0) ? err : 0;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -211,49 +211,49 @@ const struct stv06xx_sensor stv06xx_sens
 
 /* If NULL, only single value to write, stored in len */
 struct stv_init {
-	const u8 *data;
-	u16 start;
-	u8 len;
-};
-
-static const u8 x1500[] = {	/* 0x1500 - 0x150f */
-	0x0b, 0xa7, 0xb7, 0x00, 0x00
-};
-
-static const u8 x1536[] = {	/* 0x1536 - 0x153b */
-	0x02, 0x00, 0x60, 0x01, 0x20, 0x01
+	u16 addr;
+	u8 data;
 };
 
 static const struct stv_init stv_bridge_init[] = {
 	/* This reg is written twice. Some kind of reset? */
-	{NULL,  0x1620, 0x80},
-	{NULL,  0x1620, 0x00},
-	{NULL,  0x1443, 0x00},
-	{NULL,  0x1423, 0x04},
-	{x1500, 0x1500, ARRAY_SIZE(x1500)},
-	{x1536, 0x1536, ARRAY_SIZE(x1536)},
+	{STV_RESET, 0x80},
+	{STV_RESET, 0x00},
+	{STV_SCAN_RATE, 0x00},
+	{STV_I2C_FLUSH, 0x04},
+	{STV_REG00, 0x0b},
+	{STV_REG01, 0xa7},
+	{STV_REG02, 0xb7},
+	{STV_REG03, 0x00},
+	{STV_REG04, 0x00},
+	{0x1536, 0x02},
+	{0x1537, 0x00},
+	{0x1538, 0x60},
+	{0x1539, 0x01},
+	{0x153a, 0x20},
+	{0x153b, 0x01},
 };
 
 static const u8 vv6410_sensor_init[][2] = {
 	/* Setup registers */
-	{VV6410_SETUP0,		VV6410_SOFT_RESET},
-	{VV6410_SETUP0,		VV6410_LOW_POWER_MODE},
+	{VV6410_SETUP0,	VV6410_SOFT_RESET},
+	{VV6410_SETUP0,	VV6410_LOW_POWER_MODE},
 	/* Use shuffled read-out mode */
-	{VV6410_SETUP1,		BIT(6)},
-	/* All modes to 1 */
-	{VV6410_FGMODES,	BIT(6) | BIT(4) | BIT(2) | BIT(0)},
-	{VV6410_PINMAPPING,	0x00},
+	{VV6410_SETUP1,	BIT(6)},
+	/* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
+	{VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
+	{VV6410_PINMAPPING, 0x00},
 	/* Pre-clock generator divide off */
-	{VV6410_DATAFORMAT,	BIT(7) | BIT(0)},
+	{VV6410_DATAFORMAT, BIT(7) | BIT(0)},
 
-	{VV6410_CLKDIV,		VV6410_CLK_DIV_2},
+	{VV6410_CLKDIV,	VV6410_CLK_DIV_2},
 
 	/* System registers */
 	/* Enable voltage doubler */
-	{VV6410_AS0,		BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
-	{VV6410_AT0,		0x00},
+	{VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+	{VV6410_AT0, 0x00},
 	/* Power up audio, differential */
-	{VV6410_AT1,		BIT(4)|BIT(0)},
+	{VV6410_AT1, BIT(4) | BIT(0)},
 };
 
 #endif
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/sunplus.c linux-libre-3.2-gnu1/drivers/media/video/gspca/sunplus.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/sunplus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/sunplus.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sunplus"
 
 #include "gspca.h"
@@ -325,7 +327,7 @@ static void reg_r(struct gspca_dev *gspc
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -340,7 +342,7 @@ static void reg_r(struct gspca_dev *gspc
 			len ? gspca_dev->usb_buf : NULL, len,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -365,7 +367,7 @@ static void reg_w_1(struct gspca_dev *gs
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w_1 err %d", ret);
+		pr_err("reg_w_1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -385,7 +387,7 @@ static void reg_w_riv(struct gspca_dev *
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
 	if (ret < 0) {
-		err("reg_w_riv err %d", ret);
+		pr_err("reg_w_riv err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return;
 	}
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/t613.c linux-libre-3.2-gnu1/drivers/media/video/gspca/t613.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/t613.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/t613.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *			Costantino Leandro
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "t613"
 
 #include <linux/slab.h>
@@ -572,7 +574,7 @@ static void reg_w_buf(struct gspca_dev *
 
 		tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
 		if (!tmpbuf) {
-			err("Out of memory");
+			pr_err("Out of memory\n");
 			return;
 		}
 		usb_control_msg(gspca_dev->dev,
@@ -598,7 +600,7 @@ static void reg_w_ixbuf(struct gspca_dev
 	} else {
 		p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
 		if (!tmpbuf) {
-			err("Out of memory");
+			pr_err("Out of memory\n");
 			return;
 		}
 	}
@@ -652,7 +654,7 @@ static void om6802_sensor_init(struct gs
 	}
 	byte = reg_r(gspca_dev, 0x0063);
 	if (byte != 0x17) {
-		err("Bad sensor reset %02x", byte);
+		pr_err("Bad sensor reset %02x\n", byte);
 		/* continue? */
 	}
 
@@ -890,7 +892,7 @@ static int sd_init(struct gspca_dev *gsp
 		sd->sensor = SENSOR_OM6802;
 		break;
 	default:
-		err("unknown sensor %04x", sensor_id);
+		pr_err("unknown sensor %04x\n", sensor_id);
 		return -EINVAL;
 	}
 
@@ -905,7 +907,7 @@ static int sd_init(struct gspca_dev *gsp
 				break;		/* OK */
 		}
 		if (i < 0) {
-			err("Bad sensor reset %02x", test_byte);
+			pr_err("Bad sensor reset %02x\n", test_byte);
 			return -EIO;
 		}
 		reg_w_buf(gspca_dev, n2, sizeof n2);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/topro.c linux-libre-3.2-gnu1/drivers/media/video/gspca/topro.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/topro.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/topro.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4989 @@
+/*
+ * Topro TP6800/6810 webcam driver.
+ *
+ * Copyright (C) 2011 Jean-FranÃ§ois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
+ * Copyright (C) 2008 Thomas Champagne (lafeuil@gmail.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "gspca.h"
+
+MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+		"Anders Blomdell <anders.blomdell@control.lth.se>");
+MODULE_LICENSE("GPL");
+
+static int force_sensor = -1;
+
+/* JPEG header */
+static const u8 jpeg_head[] = {
+	0xff, 0xd8,			/* jpeg */
+
+/* quantization table quality 50% */
+	0xff, 0xdb, 0x00, 0x84,		/* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+	/* Define Huffman table (thanks to Thomas Kaiser) */
+	0xff, 0xc4, 0x01, 0x5e,
+	0x00, 0x00, 0x02, 0x03,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+	0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+	0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
+	0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
+	0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
+	0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
+	0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
+	0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
+	0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
+	0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
+	0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
+	0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
+	0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
+	0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
+	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
+	0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
+	0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+	0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
+	0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
+	0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+	0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
+	0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
+	0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
+	0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
+	0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
+	0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
+	0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
+	0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
+	0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
+	0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+	0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
+	0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
+	0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
+	0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+	0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xff, 0xc0, 0x00, 0x11,		/* SOF0 (start of frame 0 */
+	0x08,				/* data precision */
+#define JPEG_HEIGHT_OFFSET 493
+	0x01, 0xe0,			/* height */
+	0x02, 0x80,			/* width */
+	0x03,				/* component number */
+		0x01,
+			0x21,		/* samples Y = jpeg 422 */
+			0x00,		/* quant Y */
+		0x02, 0x11, 0x01,	/* samples CbCr - quant CbCr */
+		0x03, 0x11, 0x01,
+
+	0xff, 0xda, 0x00, 0x0c,		/* SOS (start of scan) */
+	0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 521
+};
+
+enum e_ctrl {
+	EXPOSURE,
+	QUALITY,
+	SHARPNESS,
+	RGAIN,
+	GAIN,
+	BGAIN,
+	GAMMA,
+	AUTOGAIN,
+	NCTRLS		/* number of controls */
+};
+
+#define AUTOGAIN_DEF 1
+
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	struct gspca_ctrl ctrls[NCTRLS];
+
+	u8 framerate;
+	u8 quality;		/* webcam current JPEG quality (0..16) */
+	s8 ag_cnt;		/* autogain / start counter for tp6810 */
+#define AG_CNT_START 13		/* check gain every N frames */
+
+	u8 bridge;
+	u8 sensor;
+
+	u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+enum bridges {
+	BRIDGE_TP6800,
+	BRIDGE_TP6810,
+};
+
+enum sensors {
+	SENSOR_CX0342,
+	SENSOR_SOI763A,		/* ~= ov7630 / ov7648 */
+	NSENSORS
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 4 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG}
+};
+
+/*
+ * JPEG quality
+ * index: webcam compression
+ * value: JPEG quality in %
+ */
+static const u8 jpeg_q[17] = {
+	88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
+};
+
+#define BULK_OUT_SIZE		0x20
+#if BULK_OUT_SIZE > USB_BUF_SZ
+#error "USB buffer too small"
+#endif
+
+static const u8 rates[] = {30, 20, 15, 10, 7, 5};
+static const struct framerates framerates[] = {
+	{
+		.rates = rates,
+		.nrates = ARRAY_SIZE(rates)
+	},
+	{
+		.rates = rates,
+		.nrates = ARRAY_SIZE(rates)
+	}
+};
+static const u8 rates_6810[] = {30, 15, 10, 7, 5};
+static const struct framerates framerates_6810[] = {
+	{
+		.rates = rates_6810,
+		.nrates = ARRAY_SIZE(rates_6810)
+	},
+	{
+		.rates = rates_6810,
+		.nrates = ARRAY_SIZE(rates_6810)
+	}
+};
+
+/*
+ * webcam quality in %
+ * the last value is the ultra fine quality
+ */
+
+/* TP6800 register offsets */
+#define TP6800_R10_SIF_TYPE		0x10
+#define TP6800_R11_SIF_CONTROL		0x11
+#define TP6800_R12_SIF_ADDR_S		0x12
+#define TP6800_R13_SIF_TX_DATA		0x13
+#define TP6800_R14_SIF_RX_DATA		0x14
+#define TP6800_R15_GPIO_PU		0x15
+#define TP6800_R16_GPIO_PD		0x16
+#define TP6800_R17_GPIO_IO		0x17
+#define TP6800_R18_GPIO_DATA		0x18
+#define TP6800_R19_SIF_ADDR_S2		0x19
+#define TP6800_R1A_SIF_TX_DATA2		0x1a
+#define TP6800_R1B_SIF_RX_DATA2		0x1b
+#define TP6800_R21_ENDP_1_CTL		0x21
+#define TP6800_R2F_TIMING_CFG		0x2f
+#define TP6800_R30_SENSOR_CFG		0x30
+#define TP6800_R31_PIXEL_START		0x31
+#define TP6800_R32_PIXEL_END_L		0x32
+#define TP6800_R33_PIXEL_END_H		0x33
+#define TP6800_R34_LINE_START		0x34
+#define TP6800_R35_LINE_END_L		0x35
+#define TP6800_R36_LINE_END_H		0x36
+#define TP6800_R37_FRONT_DARK_ST	0x37
+#define TP6800_R38_FRONT_DARK_END	0x38
+#define TP6800_R39_REAR_DARK_ST_L	0x39
+#define TP6800_R3A_REAR_DARK_ST_H	0x3a
+#define TP6800_R3B_REAR_DARK_END_L	0x3b
+#define TP6800_R3C_REAR_DARK_END_H	0x3c
+#define TP6800_R3D_HORIZ_DARK_LINE_L	0x3d
+#define TP6800_R3E_HORIZ_DARK_LINE_H	0x3e
+#define TP6800_R3F_FRAME_RATE		0x3f
+#define TP6800_R50			0x50
+#define TP6800_R51			0x51
+#define TP6800_R52			0x52
+#define TP6800_R53			0x53
+#define TP6800_R54_DARK_CFG		0x54
+#define TP6800_R55_GAMMA_R		0x55
+#define TP6800_R56_GAMMA_G		0x56
+#define TP6800_R57_GAMMA_B		0x57
+#define TP6800_R5C_EDGE_THRLD		0x5c
+#define TP6800_R5D_DEMOSAIC_CFG		0x5d
+#define TP6800_R78_FORMAT		0x78
+#define TP6800_R79_QUALITY		0x79
+#define TP6800_R7A_BLK_THRLD		0x7a
+
+/* CX0342 register offsets */
+
+#define CX0342_SENSOR_ID		0x00
+#define CX0342_VERSION_NO		0x01
+#define CX0342_ORG_X_L			0x02
+#define CX0342_ORG_X_H			0x03
+#define CX0342_ORG_Y_L			0x04
+#define CX0342_ORG_Y_H			0x05
+#define CX0342_STOP_X_L			0x06
+#define CX0342_STOP_X_H			0x07
+#define CX0342_STOP_Y_L			0x08
+#define CX0342_STOP_Y_H			0x09
+#define CX0342_FRAME_WIDTH_L		0x0a
+#define CX0342_FRAME_WIDTH_H		0x0b
+#define CX0342_FRAME_HEIGH_L		0x0c
+#define CX0342_FRAME_HEIGH_H		0x0d
+#define CX0342_EXPO_LINE_L		0x10
+#define CX0342_EXPO_LINE_H		0x11
+#define CX0342_EXPO_CLK_L		0x12
+#define CX0342_EXPO_CLK_H		0x13
+#define CX0342_RAW_GRGAIN_L		0x14
+#define CX0342_RAW_GRGAIN_H		0x15
+#define CX0342_RAW_GBGAIN_L		0x16
+#define CX0342_RAW_GBGAIN_H		0x17
+#define CX0342_RAW_RGAIN_L		0x18
+#define CX0342_RAW_RGAIN_H		0x19
+#define CX0342_RAW_BGAIN_L		0x1a
+#define CX0342_RAW_BGAIN_H		0x1b
+#define CX0342_GLOBAL_GAIN		0x1c
+#define CX0342_SYS_CTRL_0		0x20
+#define CX0342_SYS_CTRL_1		0x21
+#define CX0342_SYS_CTRL_2		0x22
+#define CX0342_BYPASS_MODE		0x23
+#define CX0342_SYS_CTRL_3		0x24
+#define CX0342_TIMING_EN		0x25
+#define CX0342_OUTPUT_CTRL		0x26
+#define CX0342_AUTO_ADC_CALIB		0x27
+#define CX0342_SYS_CTRL_4		0x28
+#define CX0342_ADCGN			0x30
+#define CX0342_SLPCR			0x31
+#define CX0342_SLPFN_LO			0x32
+#define CX0342_ADC_CTL			0x33
+#define CX0342_LVRST_BLBIAS		0x34
+#define CX0342_VTHSEL			0x35
+#define CX0342_RAMP_RIV			0x36
+#define CX0342_LDOSEL			0x37
+#define CX0342_CLOCK_GEN		0x40
+#define CX0342_SOFT_RESET		0x41
+#define CX0342_PLL			0x42
+#define CX0342_DR_ENH_PULSE_OFFSET_L	0x43
+#define CX0342_DR_ENH_PULSE_OFFSET_H	0x44
+#define CX0342_DR_ENH_PULSE_POS_L	0x45
+#define CX0342_DR_ENH_PULSE_POS_H	0x46
+#define CX0342_DR_ENH_PULSE_WIDTH	0x47
+#define CX0342_AS_CURRENT_CNT_L		0x48
+#define CX0342_AS_CURRENT_CNT_H		0x49
+#define CX0342_AS_PREVIOUS_CNT_L	0x4a
+#define CX0342_AS_PREVIOUS_CNT_H	0x4b
+#define CX0342_SPV_VALUE_L		0x4c
+#define CX0342_SPV_VALUE_H		0x4d
+#define CX0342_GPXLTHD_L		0x50
+#define CX0342_GPXLTHD_H		0x51
+#define CX0342_RBPXLTHD_L		0x52
+#define CX0342_RBPXLTHD_H		0x53
+#define CX0342_PLANETHD_L		0x54
+#define CX0342_PLANETHD_H		0x55
+#define CX0342_ROWDARK_TH		0x56
+#define CX0342_ROWDARK_TOL		0x57
+#define CX0342_RB_GAP_L			0x58
+#define CX0342_RB_GAP_H			0x59
+#define CX0342_G_GAP_L			0x5a
+#define CX0342_G_GAP_H			0x5b
+#define CX0342_AUTO_ROW_DARK		0x60
+#define CX0342_MANUAL_DARK_VALUE	0x61
+#define CX0342_GB_DARK_OFFSET		0x62
+#define CX0342_GR_DARK_OFFSET		0x63
+#define CX0342_RED_DARK_OFFSET		0x64
+#define CX0342_BLUE_DARK_OFFSET		0x65
+#define CX0342_DATA_SCALING_MULTI	0x66
+#define CX0342_AUTOD_Q_FRAME		0x67
+#define CX0342_AUTOD_ALLOW_VARI		0x68
+#define CX0342_AUTO_DARK_VALUE_L	0x69
+#define CX0342_AUTO_DARK_VALUE_H	0x6a
+#define CX0342_IO_CTRL_0		0x70
+#define CX0342_IO_CTRL_1		0x71
+#define CX0342_IO_CTRL_2		0x72
+#define CX0342_IDLE_CTRL		0x73
+#define CX0342_TEST_MODE		0x74
+#define CX0342_FRAME_FIX_DATA_TEST	0x75
+#define CX0342_FRAME_CNT_TEST		0x76
+#define CX0342_RST_OVERFLOW_L		0x80
+#define CX0342_RST_OVERFLOW_H		0x81
+#define CX0342_RST_UNDERFLOW_L		0x82
+#define CX0342_RST_UNDERFLOW_H		0x83
+#define CX0342_DATA_OVERFLOW_L		0x84
+#define CX0342_DATA_OVERFLOW_H		0x85
+#define CX0342_DATA_UNDERFLOW_L		0x86
+#define CX0342_DATA_UNDERFLOW_H		0x87
+#define CX0342_CHANNEL_0_0_L_irst	0x90
+#define CX0342_CHANNEL_0_0_H_irst	0x91
+#define CX0342_CHANNEL_0_1_L_irst	0x92
+#define CX0342_CHANNEL_0_1_H_irst	0x93
+#define CX0342_CHANNEL_0_2_L_irst	0x94
+#define CX0342_CHANNEL_0_2_H_irst	0x95
+#define CX0342_CHANNEL_0_3_L_irst	0x96
+#define CX0342_CHANNEL_0_3_H_irst	0x97
+#define CX0342_CHANNEL_0_4_L_irst	0x98
+#define CX0342_CHANNEL_0_4_H_irst	0x99
+#define CX0342_CHANNEL_0_5_L_irst	0x9a
+#define CX0342_CHANNEL_0_5_H_irst	0x9b
+#define CX0342_CHANNEL_0_6_L_irst	0x9c
+#define CX0342_CHANNEL_0_6_H_irst	0x9d
+#define CX0342_CHANNEL_0_7_L_irst	0x9e
+#define CX0342_CHANNEL_0_7_H_irst	0x9f
+#define CX0342_CHANNEL_1_0_L_itx	0xa0
+#define CX0342_CHANNEL_1_0_H_itx	0xa1
+#define CX0342_CHANNEL_1_1_L_itx	0xa2
+#define CX0342_CHANNEL_1_1_H_itx	0xa3
+#define CX0342_CHANNEL_1_2_L_itx	0xa4
+#define CX0342_CHANNEL_1_2_H_itx	0xa5
+#define CX0342_CHANNEL_1_3_L_itx	0xa6
+#define CX0342_CHANNEL_1_3_H_itx	0xa7
+#define CX0342_CHANNEL_1_4_L_itx	0xa8
+#define CX0342_CHANNEL_1_4_H_itx	0xa9
+#define CX0342_CHANNEL_1_5_L_itx	0xaa
+#define CX0342_CHANNEL_1_5_H_itx	0xab
+#define CX0342_CHANNEL_1_6_L_itx	0xac
+#define CX0342_CHANNEL_1_6_H_itx	0xad
+#define CX0342_CHANNEL_1_7_L_itx	0xae
+#define CX0342_CHANNEL_1_7_H_itx	0xaf
+#define CX0342_CHANNEL_2_0_L_iwl	0xb0
+#define CX0342_CHANNEL_2_0_H_iwl	0xb1
+#define CX0342_CHANNEL_2_1_L_iwl	0xb2
+#define CX0342_CHANNEL_2_1_H_iwl	0xb3
+#define CX0342_CHANNEL_2_2_L_iwl	0xb4
+#define CX0342_CHANNEL_2_2_H_iwl	0xb5
+#define CX0342_CHANNEL_2_3_L_iwl	0xb6
+#define CX0342_CHANNEL_2_3_H_iwl	0xb7
+#define CX0342_CHANNEL_2_4_L_iwl	0xb8
+#define CX0342_CHANNEL_2_4_H_iwl	0xb9
+#define CX0342_CHANNEL_2_5_L_iwl	0xba
+#define CX0342_CHANNEL_2_5_H_iwl	0xbb
+#define CX0342_CHANNEL_2_6_L_iwl	0xbc
+#define CX0342_CHANNEL_2_6_H_iwl	0xbd
+#define CX0342_CHANNEL_2_7_L_iwl	0xbe
+#define CX0342_CHANNEL_2_7_H_iwl	0xbf
+#define CX0342_CHANNEL_3_0_L_ensp	0xc0
+#define CX0342_CHANNEL_3_0_H_ensp	0xc1
+#define CX0342_CHANNEL_3_1_L_ensp	0xc2
+#define CX0342_CHANNEL_3_1_H_ensp	0xc3
+#define CX0342_CHANNEL_3_2_L_ensp	0xc4
+#define CX0342_CHANNEL_3_2_H_ensp	0xc5
+#define CX0342_CHANNEL_3_3_L_ensp	0xc6
+#define CX0342_CHANNEL_3_3_H_ensp	0xc7
+#define CX0342_CHANNEL_3_4_L_ensp	0xc8
+#define CX0342_CHANNEL_3_4_H_ensp	0xc9
+#define CX0342_CHANNEL_3_5_L_ensp	0xca
+#define CX0342_CHANNEL_3_5_H_ensp	0xcb
+#define CX0342_CHANNEL_3_6_L_ensp	0xcc
+#define CX0342_CHANNEL_3_6_H_ensp	0xcd
+#define CX0342_CHANNEL_3_7_L_ensp	0xce
+#define CX0342_CHANNEL_3_7_H_ensp	0xcf
+#define CX0342_CHANNEL_4_0_L_sela	0xd0
+#define CX0342_CHANNEL_4_0_H_sela	0xd1
+#define CX0342_CHANNEL_4_1_L_sela	0xd2
+#define CX0342_CHANNEL_4_1_H_sela	0xd3
+#define CX0342_CHANNEL_5_0_L_intla	0xe0
+#define CX0342_CHANNEL_5_0_H_intla	0xe1
+#define CX0342_CHANNEL_5_1_L_intla	0xe2
+#define CX0342_CHANNEL_5_1_H_intla	0xe3
+#define CX0342_CHANNEL_5_2_L_intla	0xe4
+#define CX0342_CHANNEL_5_2_H_intla	0xe5
+#define CX0342_CHANNEL_5_3_L_intla	0xe6
+#define CX0342_CHANNEL_5_3_H_intla	0xe7
+#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
+#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
+#define CX0342_CHANNEL_7_1_L_cds_pos	0xf2
+#define CX0342_CHANNEL_7_1_H_cds_pos	0xf3
+#define CX0342_SENSOR_HEIGHT_L		0xfb
+#define CX0342_SENSOR_HEIGHT_H		0xfc
+#define CX0342_SENSOR_WIDTH_L		0xfd
+#define CX0342_SENSOR_WIDTH_H		0xfe
+#define CX0342_VSYNC_HSYNC_READ		0xff
+
+struct cmd {
+	u8 reg;
+	u8 val;
+};
+
+static const u8 DQT[17][130] = {
+	/* Define quantization table (thanks to Thomas Kaiser) */
+	{			/* Quality 0 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x01,
+	 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
+	 0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 },
+	{			/* Quality 1 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x01,
+	 0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
+	 0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 },
+	{			/* Quality 2 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
+	 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x01,
+	 0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
+	 0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 },
+	{			/* Quality 3 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+	 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x01,
+	 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+	 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 },
+	{			/* Quality 4 */
+	 0x00,
+	 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
+	 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x01,
+	 0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
+	 0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 },
+	{			/* Quality 5 */
+	 0x00,
+	 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
+	 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x01,
+	 0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
+	 0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 },
+	{			/* Quality 6 */
+	 0x00,
+	 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+	 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
+	 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x01,
+	 0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
+	 0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 },
+	{			/* Quality 7 */
+	 0x00,
+	 0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
+	 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x01,
+	 0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+	 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 },
+	{			/* Quality 8 */
+	 0x00,
+	 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x01,
+	 0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
+	 0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 },
+	{			/* Quality 9 */
+	 0x00,
+	 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x01,
+	 0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+	 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 10 */
+	 0x00,
+	 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x01,
+	 0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
+	 0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 11 */
+	 0x00,
+	 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
+	 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x01,
+	 0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
+	 0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 12 */
+	 0x00,
+	 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
+	 0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x01,
+	 0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
+	 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 13 */
+	 0x00,
+	 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
+	 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x01,
+	 0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
+	 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 14 */
+	 0x00,
+	 0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x01,
+	 0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
+	 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 15 */
+	 0x00,
+	 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
+	 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x01,
+	 0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
+	 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 16-31 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x01,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 }
+};
+
+static const struct cmd tp6810_cx_init_common[] = {
+	{0x1c, 0x00},
+	{TP6800_R10_SIF_TYPE, 0x00},
+	{0x4e, 0x00},
+	{0x4f, 0x00},
+	{TP6800_R50, 0xff},
+	{TP6800_R51, 0x03},
+	{0x00, 0x07},
+	{TP6800_R79_QUALITY, 0x03},
+	{TP6800_R2F_TIMING_CFG, 0x37},
+	{TP6800_R30_SENSOR_CFG, 0x10},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{TP6800_R52, 0x40},
+	{TP6800_R53, 0x40},
+	{TP6800_R54_DARK_CFG, 0x40},
+	{TP6800_R30_SENSOR_CFG, 0x18},
+	{0x4b, 0x00},
+	{TP6800_R3F_FRAME_RATE, 0x83},
+	{TP6800_R79_QUALITY, 0x05},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{0x7c, 0x04},
+	{0x25, 0x14},
+	{0x26, 0x0f},
+	{0x7b, 0x10},
+};
+
+static const struct cmd tp6810_ov_init_common[] = {
+	{0x1c, 0x00},
+	{TP6800_R10_SIF_TYPE, 0x00},
+	{0x4e, 0x00},
+	{0x4f, 0x00},
+	{TP6800_R50, 0xff},
+	{TP6800_R51, 0x03},
+	{0x00, 0x07},
+	{TP6800_R52, 0x40},
+	{TP6800_R53, 0x40},
+	{TP6800_R54_DARK_CFG, 0x40},
+	{TP6800_R79_QUALITY, 0x03},
+	{TP6800_R2F_TIMING_CFG, 0x17},
+	{TP6800_R30_SENSOR_CFG, 0x18},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{TP6800_R3F_FRAME_RATE, 0x86},
+	{0x25, 0x18},
+	{0x26, 0x0f},
+	{0x7b, 0x90},
+};
+
+static const struct cmd tp6810_bridge_start[] = {
+	{0x59, 0x88},
+	{0x5a, 0x0f},
+	{0x5b, 0x4e},
+	{TP6800_R5C_EDGE_THRLD, 0x63},
+	{TP6800_R5D_DEMOSAIC_CFG, 0x00},
+	{0x03, 0x7f},
+	{0x04, 0x80},
+	{0x06, 0x00},
+	{0x00, 0x00},
+};
+
+static const struct cmd tp6810_late_start[] = {
+	{0x7d, 0x01},
+	{0xb0, 0x04},
+	{0xb1, 0x04},
+	{0xb2, 0x04},
+	{0xb3, 0x04},
+	{0xb4, 0x04},
+	{0xb5, 0x04},
+	{0xb6, 0x08},
+	{0xb7, 0x08},
+	{0xb8, 0x04},
+	{0xb9, 0x04},
+	{0xba, 0x04},
+	{0xbb, 0x04},
+	{0xbc, 0x04},
+	{0xbd, 0x08},
+	{0xbe, 0x08},
+	{0xbf, 0x08},
+	{0xc0, 0x04},
+	{0xc1, 0x04},
+	{0xc2, 0x08},
+	{0xc3, 0x08},
+	{0xc4, 0x08},
+	{0xc5, 0x08},
+	{0xc6, 0x08},
+	{0xc7, 0x13},
+	{0xc8, 0x04},
+	{0xc9, 0x08},
+	{0xca, 0x08},
+	{0xcb, 0x08},
+	{0xcc, 0x08},
+	{0xcd, 0x08},
+	{0xce, 0x13},
+	{0xcf, 0x13},
+	{0xd0, 0x08},
+	{0xd1, 0x08},
+	{0xd2, 0x08},
+	{0xd3, 0x08},
+	{0xd4, 0x08},
+	{0xd5, 0x13},
+	{0xd6, 0x13},
+	{0xd7, 0x13},
+	{0xd8, 0x08},
+	{0xd9, 0x08},
+	{0xda, 0x08},
+	{0xdb, 0x08},
+	{0xdc, 0x13},
+	{0xdd, 0x13},
+	{0xde, 0x13},
+	{0xdf, 0x13},
+	{0xe0, 0x08},
+	{0xe1, 0x08},
+	{0xe2, 0x08},
+	{0xe3, 0x13},
+	{0xe4, 0x13},
+	{0xe5, 0x13},
+	{0xe6, 0x13},
+	{0xe7, 0x13},
+	{0xe8, 0x08},
+	{0xe9, 0x08},
+	{0xea, 0x13},
+	{0xeb, 0x13},
+	{0xec, 0x13},
+	{0xed, 0x13},
+	{0xee, 0x13},
+	{0xef, 0x13},
+	{0x7d, 0x02},
+
+	/* later after isoc start */
+	{0x7d, 0x08},
+	{0x7d, 0x00},
+};
+
+static const struct cmd cx0342_timing_seq[] = {
+	{CX0342_CHANNEL_0_1_L_irst, 0x20},
+	{CX0342_CHANNEL_0_2_L_irst, 0x24},
+	{CX0342_CHANNEL_0_2_H_irst, 0x00},
+	{CX0342_CHANNEL_0_3_L_irst, 0x2f},
+	{CX0342_CHANNEL_0_3_H_irst, 0x00},
+	{CX0342_CHANNEL_1_0_L_itx, 0x02},
+	{CX0342_CHANNEL_1_0_H_itx, 0x00},
+	{CX0342_CHANNEL_1_1_L_itx, 0x20},
+	{CX0342_CHANNEL_1_1_H_itx, 0x00},
+	{CX0342_CHANNEL_1_2_L_itx, 0xe4},
+	{CX0342_CHANNEL_1_2_H_itx, 0x00},
+	{CX0342_CHANNEL_1_3_L_itx, 0xee},
+	{CX0342_CHANNEL_1_3_H_itx, 0x00},
+	{CX0342_CHANNEL_2_0_L_iwl, 0x30},
+	{CX0342_CHANNEL_2_0_H_iwl, 0x00},
+	{CX0342_CHANNEL_3_0_L_ensp, 0x34},
+	{CX0342_CHANNEL_3_1_L_ensp, 0xe2},
+	{CX0342_CHANNEL_3_1_H_ensp, 0x00},
+	{CX0342_CHANNEL_3_2_L_ensp, 0xf6},
+	{CX0342_CHANNEL_3_2_H_ensp, 0x00},
+	{CX0342_CHANNEL_3_3_L_ensp, 0xf4},
+	{CX0342_CHANNEL_3_3_H_ensp, 0x02},
+	{CX0342_CHANNEL_4_0_L_sela, 0x26},
+	{CX0342_CHANNEL_4_0_H_sela, 0x00},
+	{CX0342_CHANNEL_4_1_L_sela, 0xe2},
+	{CX0342_CHANNEL_4_1_H_sela, 0x00},
+	{CX0342_CHANNEL_5_0_L_intla, 0x26},
+	{CX0342_CHANNEL_5_1_L_intla, 0x29},
+	{CX0342_CHANNEL_5_2_L_intla, 0xf0},
+	{CX0342_CHANNEL_5_2_H_intla, 0x00},
+	{CX0342_CHANNEL_5_3_L_intla, 0xf3},
+	{CX0342_CHANNEL_5_3_H_intla, 0x00},
+	{CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
+	{CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
+	{CX0342_TIMING_EN, 0x01},
+};
+
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+			int height,
+			int width)
+{
+	memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
+}
+
+/* set the JPEG quality for sensor soi763a */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+			  int quality)
+{
+	int i, sc;
+
+	if (quality < 50)
+		sc = 5000 / quality;
+	else
+		sc = 200 - quality * 2;
+	for (i = 0; i < 64; i++) {
+		jpeg_hdr[JPEG_QT0_OFFSET + i] =
+			(jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+		jpeg_hdr[JPEG_QT1_OFFSET + i] =
+			(jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+	}
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x0e,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value, index, NULL, 0, 500);
+	if (ret < 0) {
+		pr_err("reg_w err %d\n", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+
+/* the returned value is in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev, u8 index)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			0x0d,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index, gspca_dev->usb_buf, 1, 500);
+	if (ret < 0) {
+		pr_err("reg_r err %d\n", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+			const struct cmd *p, int l)
+{
+	do {
+		reg_w(gspca_dev, p->reg, p->val);
+		p++;
+	} while (--l > 0);
+}
+
+static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+	reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
+	if (sd->bridge == BRIDGE_TP6800)
+		return 0;
+	msleep(5);
+	reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+	if (gspca_dev->usb_buf[0] == 0)
+		return 0;
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	return -1;				/* error */
+}
+
+static void i2c_w_buf(struct gspca_dev *gspca_dev,
+			const struct cmd *p, int l)
+{
+	do {
+		i2c_w(gspca_dev, p->reg, p->val);
+		p++;
+	} while (--l > 0);
+}
+
+static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int v;
+
+	reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
+	msleep(5);
+	reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
+	v = gspca_dev->usb_buf[0];
+	if (sd->bridge == BRIDGE_TP6800)
+		return v;
+	if (len > 1) {
+		reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
+		v |= (gspca_dev->usb_buf[0] << 8);
+	}
+	reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+	if (gspca_dev->usb_buf[0] == 0)
+		return v;
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	return -1;
+}
+
+static void bulk_w(struct gspca_dev *gspca_dev,
+		  u8 tag,
+		  const u8 *data,
+		  int length)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int count, actual_count, ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	for (;;) {
+		count = length > BULK_OUT_SIZE - 1
+				? BULK_OUT_SIZE - 1 : length;
+		gspca_dev->usb_buf[0] = tag;
+		memcpy(&gspca_dev->usb_buf[1], data, count);
+		ret = usb_bulk_msg(dev,
+				   usb_sndbulkpipe(dev, 3),
+				   gspca_dev->usb_buf, count + 1,
+				   &actual_count, 500);
+		if (ret < 0) {
+			pr_err("bulk write error %d tag=%02x\n",
+				ret, tag);
+			gspca_dev->usb_err = ret;
+			return;
+		}
+		length -= count;
+		if (length <= 0)
+			break;
+		data += count;
+	}
+}
+
+static int probe_6810(struct gspca_dev *gspca_dev)
+{
+	u8 gpio;
+	int ret;
+
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	gpio = gspca_dev->usb_buf[0];
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);	/* i2c 16 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);	/* ov??? */
+	reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
+	if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+		return SENSOR_SOI763A;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f);	/* (unknown i2c) */
+	if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+		return -2;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11);	/* tas??? / hv??? */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return -3;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e);	/* po??? */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return -4;
+
+	ret = i2c_r(gspca_dev, 0x01, 1);
+	if (ret > 0)
+		return -5;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);	/* i2c 16 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d);	/* mi/mt??? */
+	ret = i2c_r(gspca_dev, 0x00, 2);
+	if (ret > 0)
+		return -6;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c);	/* mi/mt??? */
+	ret = i2c_r(gspca_dev, 0x36, 2);
+	if (ret > 0)
+		return -7;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61);	/* (unknown i2c) */
+	reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
+	if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
+		return -8;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);	/* cx0342 */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return SENSOR_CX0342;
+	return -9;
+}
+
+static void cx0342_6810_init(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init_1[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{0x25, 0x02},
+		{TP6800_R21_ENDP_1_CTL, 0x00},
+		{TP6800_R3F_FRAME_RATE, 0x80},
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{TP6800_R18_GPIO_DATA, 0xc1},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{TP6800_R11_SIF_CONTROL, 0x00},
+	};
+	static const struct cmd reg_init_2[] = {
+		{TP6800_R78_FORMAT, 0x48},
+		{TP6800_R11_SIF_CONTROL, 0x00},
+	};
+	static const struct cmd sensor_init[] = {
+		{CX0342_OUTPUT_CTRL, 0x07},
+		{CX0342_BYPASS_MODE, 0x58},
+		{CX0342_GPXLTHD_L, 0x28},
+		{CX0342_RBPXLTHD_L, 0x28},
+		{CX0342_PLANETHD_L, 0x50},
+		{CX0342_PLANETHD_H, 0x03},
+		{CX0342_RB_GAP_L, 0xff},
+		{CX0342_RB_GAP_H, 0x07},
+		{CX0342_G_GAP_L, 0xff},
+		{CX0342_G_GAP_H, 0x07},
+		{CX0342_RST_OVERFLOW_L, 0x5c},
+		{CX0342_RST_OVERFLOW_H, 0x01},
+		{CX0342_DATA_OVERFLOW_L, 0xfc},
+		{CX0342_DATA_OVERFLOW_H, 0x03},
+		{CX0342_DATA_UNDERFLOW_L, 0x00},
+		{CX0342_DATA_UNDERFLOW_H, 0x00},
+		{CX0342_SYS_CTRL_0, 0x40},
+		{CX0342_GLOBAL_GAIN, 0x01},
+		{CX0342_CLOCK_GEN, 0x00},
+		{CX0342_SYS_CTRL_0, 0x02},
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_TIMING_EN, 0x01},
+	};
+
+	reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+	reg_w_buf(gspca_dev, tp6810_cx_init_common,
+			ARRAY_SIZE(tp6810_cx_init_common));
+	reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);	/* cx0342 I2C addr */
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+	i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+}
+
+static void soi763a_6810_init(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init_1[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{0x25, 0x02},
+		{TP6800_R21_ENDP_1_CTL, 0x00},
+		{TP6800_R3F_FRAME_RATE, 0x80},
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xc1},
+	};
+	static const struct cmd reg_init_2[] = {
+		{TP6800_R78_FORMAT, 0x54},
+	};
+	static const struct cmd sensor_init[] = {
+		{0x00, 0x00},
+		{0x01, 0x80},
+		{0x02, 0x80},
+		{0x03, 0x90},
+		{0x04, 0x20},
+		{0x05, 0x20},
+		{0x06, 0x80},
+		{0x07, 0x00},
+		{0x08, 0xff},
+		{0x09, 0xff},
+		{0x0a, 0x76},		/* 7630 = soi673a */
+		{0x0b, 0x30},
+		{0x0c, 0x20},
+		{0x0d, 0x20},
+		{0x0e, 0xff},
+		{0x0f, 0xff},
+		{0x10, 0x41},
+		{0x15, 0x14},
+		{0x11, 0x40},
+		{0x12, 0x48},
+		{0x13, 0x80},
+		{0x14, 0x80},
+		{0x16, 0x03},
+		{0x28, 0xb0},
+		{0x71, 0x20},
+		{0x75, 0x8e},
+		{0x17, 0x1b},
+		{0x18, 0xbd},
+		{0x19, 0x05},
+		{0x1a, 0xf6},
+		{0x1b, 0x04},
+		{0x1c, 0x7f},		/* omnivision */
+		{0x1d, 0xa2},
+		{0x1e, 0x00},
+		{0x1f, 0x00},
+		{0x20, 0x45},
+		{0x21, 0x80},
+		{0x22, 0x80},
+		{0x23, 0xee},
+		{0x24, 0x50},
+		{0x25, 0x7a},
+		{0x26, 0xa0},
+		{0x27, 0x9a},
+		{0x29, 0x30},
+		{0x2a, 0x80},
+		{0x2b, 0x00},
+		{0x2c, 0xac},
+		{0x2d, 0x05},
+		{0x2e, 0x80},
+		{0x2f, 0x3c},
+		{0x30, 0x22},
+		{0x31, 0x00},
+		{0x32, 0x86},
+		{0x33, 0x08},
+		{0x34, 0xff},
+		{0x35, 0xff},
+		{0x36, 0xff},
+		{0x37, 0xff},
+		{0x38, 0xff},
+		{0x39, 0xff},
+		{0x3a, 0xfe},
+		{0x3b, 0xfe},
+		{0x3c, 0xfe},
+		{0x3d, 0xfe},
+		{0x3e, 0xfe},
+		{0x3f, 0x71},
+		{0x40, 0xff},
+		{0x41, 0xff},
+		{0x42, 0xff},
+		{0x43, 0xff},
+		{0x44, 0xff},
+		{0x45, 0xff},
+		{0x46, 0xff},
+		{0x47, 0xff},
+		{0x48, 0xff},
+		{0x49, 0xff},
+		{0x4a, 0xfe},
+		{0x4b, 0xff},
+		{0x4c, 0x00},
+		{0x4d, 0x00},
+		{0x4e, 0xff},
+		{0x4f, 0xff},
+		{0x50, 0xff},
+		{0x51, 0xff},
+		{0x52, 0xff},
+		{0x53, 0xff},
+		{0x54, 0xff},
+		{0x55, 0xff},
+		{0x56, 0xff},
+		{0x57, 0xff},
+		{0x58, 0xff},
+		{0x59, 0xff},
+		{0x5a, 0xff},
+		{0x5b, 0xfe},
+		{0x5c, 0xff},
+		{0x5d, 0x8f},
+		{0x5e, 0xff},
+		{0x5f, 0x8f},
+		{0x60, 0xa2},
+		{0x61, 0x4a},
+		{0x62, 0xf3},
+		{0x63, 0x75},
+		{0x64, 0xf0},
+		{0x65, 0x00},
+		{0x66, 0x55},
+		{0x67, 0x92},
+		{0x68, 0xa0},
+		{0x69, 0x4a},
+		{0x6a, 0x22},
+		{0x6b, 0x00},
+		{0x6c, 0x33},
+		{0x6d, 0x44},
+		{0x6e, 0x22},
+		{0x6f, 0x84},
+		{0x70, 0x0b},
+		{0x72, 0x10},
+		{0x73, 0x50},
+		{0x74, 0x21},
+		{0x76, 0x00},
+		{0x77, 0xa5},
+		{0x78, 0x80},
+		{0x79, 0x80},
+		{0x7a, 0x80},
+		{0x7b, 0xe2},
+		{0x7c, 0x00},
+		{0x7d, 0xf7},
+		{0x7e, 0x00},
+		{0x7f, 0x00},
+	};
+
+	reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+	reg_w_buf(gspca_dev, tp6810_ov_init_common,
+			ARRAY_SIZE(tp6810_ov_init_common));
+	reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+	i2c_w(gspca_dev, 0x12, 0x80);		/* sensor reset */
+	msleep(10);
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+}
+
+/* set the gain and exposure */
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_CX0342) {
+		int expo;
+
+		expo = (sd->ctrls[EXPOSURE].val << 2) - 1;
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
+						sd->ctrls[GAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, sd->ctrls[GAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
+						sd->ctrls[GAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, sd->ctrls[GAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
+						sd->ctrls[BGAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
+						sd->ctrls[RGAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, sd->ctrls[RGAIN].val);
+		i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
+				sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
+		return;
+	}
+
+	/* soi763a */
+	i2c_w(gspca_dev, 0x10,		/* AEC_H (exposure time) */
+			 sd->ctrls[EXPOSURE].val);
+/*	i2c_w(gspca_dev, 0x76, 0x02);	 * AEC_L ([1:0] */
+	i2c_w(gspca_dev, 0x00,		/* gain */
+			 sd->ctrls[GAIN].val);
+}
+
+/* set the JPEG quantization tables */
+static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* update the jpeg quantization tables */
+	PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
+	sd->quality = q;
+	if (q > 16)
+		q = 16;
+	if (sd->sensor == SENSOR_SOI763A)
+		jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
+	else
+		memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
+			DQT[q], sizeof DQT[0]);
+}
+
+/* set the JPEG compression quality factor */
+static void setquality(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u16 q;
+
+	q = sd->ctrls[QUALITY].val;
+	if (q != 16)
+		q = 15 - q;
+
+	reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
+	reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
+	reg_w(gspca_dev, TP6800_R79_QUALITY, q);
+
+	/* auto quality */
+	if (q == 15 && sd->bridge == BRIDGE_TP6810) {
+		msleep(4);
+		reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
+	}
+}
+
+static const u8 color_null[18] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const u8 color_gain[NSENSORS][18] = {
+[SENSOR_CX0342] =
+	{0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00,	/* Y R/G/B (LE values) */
+	 0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00,	/* U R/G/B */
+	 0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03},	/* V R/G/B */
+[SENSOR_SOI763A] =
+	{0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00,	/* Y R/G/B (LE values) */
+	 0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00,	/* U R/G/B */
+	 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03},	/* V R/G/B */
+};
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int gamma;
+#define NGAMMA 6
+	static const u8 gamma_tb[NGAMMA][3][1024] = {
+	    {				/* gamma 0 - from tp6800 + soi763a */
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {				/* gamma 1 - from tp6810 + soi763a */
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
+		 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
+		 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
+		 0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
+		 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
+		 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
+		 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
+		 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
+		 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+		 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
+		 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+		 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
+		 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
+		 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
+		 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+		 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+		 0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
+		 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+		 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+		 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+		 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+		 0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
+		 0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
+		 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
+		 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
+		 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
+		 0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
+		 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
+		 0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
+		 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
+		 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
+		 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
+		 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+		 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
+		 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
+		 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
+		 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+		 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+		 0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
+		 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
+		 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
+		 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
+		 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+		 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
+		 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
+		 0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
+		 0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
+		 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
+		 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
+		 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
+		 0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
+		 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
+		 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
+		 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
+		 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
+		 0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
+		 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
+		 0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
+		 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+		 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
+		 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
+		 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
+		 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
+		 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+		 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
+		 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
+		 0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+		 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
+		 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
+		 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+		 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+		 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
+		 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
+		 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+		 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+		 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+		 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
+		 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+		 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
+		 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+	    },
+	    {							/* gamma 2 */
+		{0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
+		 0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
+		 0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+		 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
+		 0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
+		 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+		 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
+		 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
+		 0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
+		 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
+		 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
+		 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+		 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
+		 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
+		 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
+		 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
+		 0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+		 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
+		 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
+		 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
+		 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
+		 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
+		 0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
+		 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
+		 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
+		 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
+		 0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
+		 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
+		 0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
+		 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
+		 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
+		 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
+		 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
+		 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
+		 0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
+		 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
+		 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
+		 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
+		 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
+		 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
+		 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
+		 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
+		 0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
+		 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
+		 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
+		 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
+		 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
+		 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+		 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
+		 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
+		 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
+		 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
+		 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
+		 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+		 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+		 0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
+		 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {				/* gamma 3 - from tp6810 + cx0342 */
+		{0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
+		 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
+		 0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
+		 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
+		 0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
+		 0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
+		 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
+		 0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+		 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
+		 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
+		 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
+		 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
+		 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
+		 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
+		 0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
+		 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
+		 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
+		 0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
+		 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
+		 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
+		 0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+		 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
+		 0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
+		 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
+		 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
+		 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
+		 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+		 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
+		 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
+		 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
+		 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
+		 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
+		 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+		 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
+		 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+		 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
+		 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
+		 0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
+		 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
+		 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
+		 0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
+		 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
+		 0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
+		 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
+		 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
+		 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
+		 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
+		 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
+		 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
+		 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+		 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
+		 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
+		 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+		 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+	    },
+	    {				/* gamma 4 - from tp6800 + soi763a */
+		{0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
+		 0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
+		 0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
+		 0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
+		 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
+		 0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
+		 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
+		 0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
+		 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
+		 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
+		 0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
+		 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+		 0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
+		 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
+		 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
+		 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
+		 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
+		 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
+		 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
+		 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+		 0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
+		 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+		 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
+		 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+		 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
+		 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
+		 0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
+		 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
+		 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+		 0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
+		 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
+		 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
+		 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
+		 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
+		 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
+		 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+		 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
+		 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
+		 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+		 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
+		 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
+		 0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
+		 0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
+		 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
+		 0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
+		 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
+		 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
+		 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
+		 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+		 0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
+		 0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
+		 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {							/* gamma 5 */
+		{0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
+		 0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
+		 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
+		 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+		 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+		 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
+		 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
+		 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+		 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
+		 0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
+		 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
+		 0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
+		 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
+		 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
+		 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
+		 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
+		 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
+		 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
+		 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
+		 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
+		 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+		 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
+		 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
+		 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+		 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+		 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
+		 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
+		 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
+		 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
+		 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
+		 0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
+		 0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
+		 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
+		 0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
+		 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
+		 0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
+		 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
+		 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
+		 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
+		 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
+		 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
+		 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
+		 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
+		 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
+		 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
+		 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
+		 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
+		 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+		 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
+		 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+		 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
+		 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
+		 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+		 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+		 0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
+		 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
+		 0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
+		 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
+		 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
+		 0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
+		 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
+		 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
+		 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
+		 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
+		 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
+		 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+		 0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
+		 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
+		 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
+		 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
+		 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
+		 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
+		 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
+		 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
+		 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
+		 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
+		 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	    },
+	};
+
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+	if (sd->bridge == BRIDGE_TP6810)
+		reg_w(gspca_dev, 0x02, 0x28);
+/*	msleep(50); */
+	gamma = sd->ctrls[GAMMA].val;
+	bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
+	bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
+	bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
+	if (sd->bridge == BRIDGE_TP6810) {
+		int i;
+
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R55_GAMMA_R,
+				gamma_tb[gamma][0][i]);
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R56_GAMMA_G,
+				gamma_tb[gamma][1][i]);
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R57_GAMMA_B,
+				gamma_tb[gamma][2][i]);
+		reg_w(gspca_dev, 0x02, 0x28);
+	}
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+/*	msleep(50); */
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
+
+	if (sd->bridge == BRIDGE_TP6800) {
+		val = sd->ctrls[SHARPNESS].val
+				| 0x08;		/* grid compensation enable */
+		if (gspca_dev->width == 640)
+			reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+		else
+			val |= 0x04;		/* scaling down enable */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
+	} else {
+		val = (sd->ctrls[SHARPNESS].val << 5) | 0x08;
+		reg_w(gspca_dev, 0x59, val);
+	}
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+		return;
+	if (sd->ctrls[AUTOGAIN].val) {
+		sd->ag_cnt = AG_CNT_START;
+		gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+	} else {
+		sd->ag_cnt = -1;
+		gspca_dev->ctrl_inac &= ~((1 << EXPOSURE) | (1 << GAIN));
+	}
+}
+
+/* set the resolution for sensor cx0342 */
+static void set_resolution(struct gspca_dev *gspca_dev)
+{
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+	if (gspca_dev->width == 320) {
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
+		msleep(100);
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+		msleep(100);
+		reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
+	} else {
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
+		msleep(100);
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+		msleep(100);
+		reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+	}
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+				ARRAY_SIZE(color_gain[0]));
+	setgamma(gspca_dev);
+	setquality(gspca_dev);
+}
+
+/* convert the frame rate to a tp68x0 value */
+static int get_fr_idx(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+
+	if (sd->bridge == BRIDGE_TP6800) {
+		for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
+			if (sd->framerate >= rates[i])
+				break;
+		}
+		i = 6 - i;		/* 1 = 5fps .. 6 = 30fps */
+
+		/* 640x480 * 30 fps does not work */
+		if (i == 6			/* if 30 fps */
+		 && gspca_dev->width == 640)
+			i = 0x86;		/* 15 fps */
+	} else {
+		for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
+			if (sd->framerate >= rates_6810[i])
+				break;
+		}
+		i = 7 - i;		/* 3 = 5fps .. 7 = 30fps */
+
+		/* 640x480 * 30 fps does not work */
+		if (i == 7			/* if 30 fps */
+		 && gspca_dev->width == 640)
+			i = 6;			/* 15 fps */
+		i |= 0x80;			/* clock * 1 */
+	}
+	return i;
+}
+
+static void setframerate(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 fr_idx;
+
+	fr_idx = get_fr_idx(gspca_dev);
+
+	if (sd->bridge == BRIDGE_TP6810) {
+		reg_r(gspca_dev, 0x7b);
+		reg_w(gspca_dev, 0x7b,
+			sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
+		if (sd->ctrls[EXPOSURE].val >= 128)
+			fr_idx = 0xf0;		/* lower frame rate */
+	}
+
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
+
+	if (sd->sensor == SENSOR_CX0342)
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+}
+
+static void setrgain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int rgain;
+
+	rgain = sd->ctrls[RGAIN].val;
+	i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
+	i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_CX0342) {
+		sd->ctrls[BGAIN].val = sd->ctrls[BGAIN].val
+					* val / sd->ctrls[GAIN].val;
+		if (sd->ctrls[BGAIN].val > 4095)
+			sd->ctrls[BGAIN].val = 4095;
+		sd->ctrls[RGAIN].val = sd->ctrls[RGAIN].val
+					* val / sd->ctrls[GAIN].val;
+		if (sd->ctrls[RGAIN].val > 4095)
+			sd->ctrls[RGAIN].val = 4095;
+	}
+	sd->ctrls[GAIN].val = val;
+	if (gspca_dev->streaming)
+		setexposure(gspca_dev);
+	return gspca_dev->usb_err;
+}
+
+static void setbgain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int bgain;
+
+	bgain = sd->ctrls[BGAIN].val;
+	i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
+	i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+		     const struct usb_device_id *id)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->bridge = id->driver_info;
+
+	gspca_dev->cam.cam_mode = vga_mode;
+	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+	gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
+			framerates : framerates_6810;
+
+	sd->framerate = 30;		/* default: 30 fps */
+	gspca_dev->cam.ctrls = sd->ctrls;
+	return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	static const struct cmd tp6800_preinit[] = {
+		{TP6800_R10_SIF_TYPE, 0x01},	/* sif */
+		{TP6800_R11_SIF_CONTROL, 0x01},
+		{TP6800_R15_GPIO_PU, 0x9f},
+		{TP6800_R16_GPIO_PD, 0x9f},
+		{TP6800_R17_GPIO_IO, 0x80},
+		{TP6800_R18_GPIO_DATA, 0x40},	/* LED off */
+	};
+	static const struct cmd tp6810_preinit[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R15_GPIO_PU, 0x6f},
+		{TP6800_R16_GPIO_PD, 0x40},
+		{TP6800_R17_GPIO_IO, 0x9f},
+		{TP6800_R18_GPIO_DATA, 0xc1},	/* LED off */
+	};
+
+	if (sd->bridge == BRIDGE_TP6800)
+		reg_w_buf(gspca_dev, tp6800_preinit,
+				ARRAY_SIZE(tp6800_preinit));
+	else
+		reg_w_buf(gspca_dev, tp6810_preinit,
+				ARRAY_SIZE(tp6810_preinit));
+	msleep(15);
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
+/* values:
+ *	0x80: snapshot button
+ *	0x40: LED
+ *	0x20: (bridge / sensor) reset for tp6810 ?
+ *	0x07: sensor type ?
+ */
+
+	/* guess the sensor type */
+	if (force_sensor >= 0) {
+		sd->sensor = force_sensor;
+	} else {
+		if (sd->bridge == BRIDGE_TP6800) {
+/*fixme: not sure this is working*/
+			switch (gspca_dev->usb_buf[0] & 0x07) {
+			case 0:
+				sd->sensor = SENSOR_SOI763A;
+				break;
+			case 1:
+				sd->sensor = SENSOR_CX0342;
+				break;
+			}
+		} else {
+			int sensor;
+
+			sensor = probe_6810(gspca_dev);
+			if (sensor < 0) {
+				pr_warn("Unknown sensor %d - forced to soi763a\n",
+					-sensor);
+				sensor = SENSOR_SOI763A;
+			}
+			sd->sensor = sensor;
+		}
+	}
+	if (sd->sensor == SENSOR_SOI763A) {
+		pr_info("Sensor soi763a\n");
+		sd->ctrls[GAMMA].def = sd->bridge == BRIDGE_TP6800 ? 0 : 1;
+		sd->ctrls[GAIN].max = 15;
+		sd->ctrls[GAIN].def = 3;
+		gspca_dev->ctrl_dis = (1 << RGAIN) | (1 << BGAIN);
+		if (sd->bridge == BRIDGE_TP6810) {
+			soi763a_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+			gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+		} else {
+			gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+		}
+	} else {
+		pr_info("Sensor cx0342\n");
+		if (sd->bridge == BRIDGE_TP6810) {
+			cx0342_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+			gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+		} else {
+			gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+		}
+	}
+
+	if (sd->bridge == BRIDGE_TP6810)
+		sd->ctrls[QUALITY].def = 0;	/* auto quality */
+	set_dqt(gspca_dev, 0);
+	return 0;
+}
+
+/* This function is called before choosing the alt setting */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	static const struct cmd cx_sensor_init[] = {
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_EXPO_LINE_L, 0x37},
+		{CX0342_EXPO_LINE_H, 0x01},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd cx_bridge_init[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+	};
+	static const struct cmd ov_sensor_init[] = {
+		{0x10, 0x75},		/* exposure */
+		{0x76, 0x03},
+		{0x00, 0x00},		/* gain */
+	};
+	static const struct cmd ov_bridge_init[] = {
+		{0x7b, 0x90},
+		{TP6800_R3F_FRAME_RATE, 0x87},
+	};
+
+	if (sd->bridge == BRIDGE_TP6800)
+		return 0;
+	if (sd->sensor == SENSOR_CX0342) {
+		reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+		i2c_w_buf(gspca_dev, cx_sensor_init,
+				ARRAY_SIZE(cx_sensor_init));
+		reg_w_buf(gspca_dev, cx_bridge_init,
+				ARRAY_SIZE(cx_bridge_init));
+		bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+		reg_w(gspca_dev, 0x59, 0x40);
+	} else {
+		reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
+		i2c_w_buf(gspca_dev, ov_sensor_init,
+				ARRAY_SIZE(ov_sensor_init));
+		reg_r(gspca_dev, 0x7b);
+		reg_w_buf(gspca_dev, ov_bridge_init,
+				ARRAY_SIZE(ov_bridge_init));
+	}
+	reg_w(gspca_dev, TP6800_R78_FORMAT,
+			gspca_dev->curr_mode ? 0x00 : 0x01);
+	return gspca_dev->usb_err;
+}
+
+static void set_led(struct gspca_dev *gspca_dev, int on)
+{
+	u8 data;
+
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	data = gspca_dev->usb_buf[0];
+	if (on)
+		data &= ~0x40;
+	else
+		data |= 0x40;
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
+}
+
+static void cx0342_6800_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init[] = {
+/*fixme: is this usefull?*/
+		{TP6800_R17_GPIO_IO, 0x9f},
+		{TP6800_R16_GPIO_PD, 0x40},
+		{TP6800_R10_SIF_TYPE, 0x00},	/* i2c 8 bits */
+		{TP6800_R50, 0x00},
+		{TP6800_R51, 0x00},
+		{TP6800_R52, 0xff},
+		{TP6800_R53, 0x03},
+		{TP6800_R54_DARK_CFG, 0x07},
+		{TP6800_R5C_EDGE_THRLD, 0x40},
+		{TP6800_R7A_BLK_THRLD, 0x40},
+		{TP6800_R2F_TIMING_CFG, 0x17},
+		{TP6800_R30_SENSOR_CFG, 0x18},	/* G1B..RG0 */
+		{TP6800_R37_FRONT_DARK_ST, 0x00},
+		{TP6800_R38_FRONT_DARK_END, 0x00},
+		{TP6800_R39_REAR_DARK_ST_L, 0x00},
+		{TP6800_R3A_REAR_DARK_ST_H, 0x00},
+		{TP6800_R3B_REAR_DARK_END_L, 0x00},
+		{TP6800_R3C_REAR_DARK_END_H, 0x00},
+		{TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+		{TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+		{TP6800_R21_ENDP_1_CTL, 0x03},
+
+		{TP6800_R31_PIXEL_START, 0x0b},
+		{TP6800_R32_PIXEL_END_L, 0x8a},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0e},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+		{TP6800_R78_FORMAT, 0x00},
+		{TP6800_R12_SIF_ADDR_S, 0x20},	/* cx0342 i2c addr */
+	};
+	static const struct cmd sensor_init[] = {
+		{CX0342_OUTPUT_CTRL, 0x07},
+		{CX0342_BYPASS_MODE, 0x58},
+		{CX0342_GPXLTHD_L, 0x16},
+		{CX0342_RBPXLTHD_L, 0x16},
+		{CX0342_PLANETHD_L, 0xc0},
+		{CX0342_PLANETHD_H, 0x03},
+		{CX0342_RB_GAP_L, 0xff},
+		{CX0342_RB_GAP_H, 0x07},
+		{CX0342_G_GAP_L, 0xff},
+		{CX0342_G_GAP_H, 0x07},
+		{CX0342_RST_OVERFLOW_L, 0x5c},
+		{CX0342_RST_OVERFLOW_H, 0x01},
+		{CX0342_DATA_OVERFLOW_L, 0xfc},
+		{CX0342_DATA_OVERFLOW_H, 0x03},
+		{CX0342_DATA_UNDERFLOW_L, 0x00},
+		{CX0342_DATA_UNDERFLOW_H, 0x00},
+		{CX0342_SYS_CTRL_0, 0x40},
+		{CX0342_GLOBAL_GAIN, 0x01},
+		{CX0342_CLOCK_GEN, 0x00},
+		{CX0342_SYS_CTRL_0, 0x02},
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+	};
+
+	reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+	i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+	reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+	reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+	i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+	setexposure(gspca_dev);
+	set_led(gspca_dev, 1);
+	set_resolution(gspca_dev);
+}
+
+static void cx0342_6810_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd sensor_init_2[] = {
+		{CX0342_EXPO_LINE_L, 0x6f},
+		{CX0342_EXPO_LINE_H, 0x02},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd bridge_init_2[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+		{TP6800_R7A_BLK_THRLD, 0x00},
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+	};
+	static const struct cmd bridge_init_3[] = {
+		{TP6800_R31_PIXEL_START, 0x08},
+		{TP6800_R32_PIXEL_END_L, 0x87},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0e},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+	};
+	static const struct cmd sensor_init_3[] = {
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_EXPO_LINE_L, 0x6f},
+		{CX0342_EXPO_LINE_H, 0x02},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd bridge_init_5[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+	};
+	static const struct cmd sensor_init_4[] = {
+		{CX0342_EXPO_LINE_L, 0xd3},
+		{CX0342_EXPO_LINE_H, 0x01},
+/*fixme: gains, but 00..80 only*/
+		{CX0342_RAW_GRGAIN_L, 0x40},
+		{CX0342_RAW_GBGAIN_L, 0x40},
+		{CX0342_RAW_RGAIN_L, 0x40},
+		{CX0342_RAW_BGAIN_L, 0x40},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd sensor_init_5[] = {
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+	};
+
+	reg_w(gspca_dev, 0x22, gspca_dev->alt);
+	i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
+	reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+	reg_w_buf(gspca_dev, tp6810_cx_init_common,
+			ARRAY_SIZE(tp6810_cx_init_common));
+	reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4a, 0x7f);
+		reg_w(gspca_dev, 0x07, 0x05);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+	} else {
+		reg_w(gspca_dev, 0x4a, 0xff);
+		reg_w(gspca_dev, 0x07, 0x85);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+	}
+	setgamma(gspca_dev);
+	reg_w_buf(gspca_dev, tp6810_bridge_start,
+			ARRAY_SIZE(tp6810_bridge_start));
+	setsharpness(gspca_dev);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+				ARRAY_SIZE(color_gain[0]));
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+	i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
+	reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+	i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
+	reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+	i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
+
+	set_led(gspca_dev, 1);
+/*	setquality(gspca_dev); */
+}
+
+static void soi763a_6800_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init[] = {
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+		{TP6800_R10_SIF_TYPE, 0x00},	/* i2c 8 bits */
+
+		{TP6800_R50, 0x00},
+		{TP6800_R51, 0x00},
+		{TP6800_R52, 0xff},
+		{TP6800_R53, 0x03},
+		{TP6800_R54_DARK_CFG, 0x07},
+		{TP6800_R5C_EDGE_THRLD, 0x40},
+
+		{TP6800_R79_QUALITY, 0x03},
+		{TP6800_R7A_BLK_THRLD, 0x40},
+
+		{TP6800_R2F_TIMING_CFG, 0x46},
+		{TP6800_R30_SENSOR_CFG, 0x10},	/* BG1..G0R */
+		{TP6800_R37_FRONT_DARK_ST, 0x00},
+		{TP6800_R38_FRONT_DARK_END, 0x00},
+		{TP6800_R39_REAR_DARK_ST_L, 0x00},
+		{TP6800_R3A_REAR_DARK_ST_H, 0x00},
+		{TP6800_R3B_REAR_DARK_END_L, 0x00},
+		{TP6800_R3C_REAR_DARK_END_H, 0x00},
+		{TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+		{TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+		{TP6800_R21_ENDP_1_CTL, 0x03},
+
+		{TP6800_R3F_FRAME_RATE, 0x04},	/* 15 fps */
+		{TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
+
+		{TP6800_R31_PIXEL_START, 0x1b},
+		{TP6800_R32_PIXEL_END_L, 0x9a},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0f},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+		{TP6800_R78_FORMAT, 0x01},	/* qvga */
+		{TP6800_R12_SIF_ADDR_S, 0x21},	/* soi763a i2c addr */
+		{TP6800_R1A_SIF_TX_DATA2, 0x00},
+	};
+	static const struct cmd sensor_init[] = {
+		{0x12, 0x48},		/* mirror - RGB */
+		{0x13, 0xa0},		/* clock - no AGC nor AEC */
+		{0x03, 0xa4},		/* saturation */
+		{0x04, 0x30},		/* hue */
+		{0x05, 0x88},		/* contrast */
+		{0x06, 0x60},		/* brightness */
+		{0x10, 0x41},		/* AEC */
+		{0x11, 0x40},		/* clock rate */
+		{0x13, 0xa0},
+		{0x14, 0x00},		/* 640x480 */
+		{0x15, 0x14},
+		{0x1f, 0x41},
+		{0x20, 0x80},
+		{0x23, 0xee},
+		{0x24, 0x50},
+		{0x25, 0x7a},
+		{0x26, 0x00},
+		{0x27, 0xe2},
+		{0x28, 0xb0},
+		{0x2a, 0x00},
+		{0x2b, 0x00},
+		{0x2d, 0x81},
+		{0x2f, 0x9d},
+		{0x60, 0x80},
+		{0x61, 0x00},
+		{0x62, 0x88},
+		{0x63, 0x11},
+		{0x64, 0x89},
+		{0x65, 0x00},
+		{0x67, 0x94},
+		{0x68, 0x7a},
+		{0x69, 0x0f},
+		{0x6c, 0x80},
+		{0x6d, 0x80},
+		{0x6e, 0x80},
+		{0x6f, 0xff},
+		{0x71, 0x20},
+		{0x74, 0x20},
+		{0x75, 0x86},
+		{0x77, 0xb5},
+		{0x17, 0x18},		/* H href start */
+		{0x18, 0xbf},		/* H href end */
+		{0x19, 0x03},		/* V start */
+		{0x1a, 0xf8},		/* V end */
+		{0x01, 0x80},		/* blue gain */
+		{0x02, 0x80},		/* red gain */
+	};
+
+	reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+
+	i2c_w(gspca_dev, 0x12, 0x80);		/* sensor reset */
+	msleep(10);
+
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+
+	reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+	reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+
+	setsharpness(gspca_dev);
+
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+				ARRAY_SIZE(color_gain[0]));
+
+	set_led(gspca_dev, 1);
+	setexposure(gspca_dev);
+	setquality(gspca_dev);
+	setgamma(gspca_dev);
+}
+
+static void soi763a_6810_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd bridge_init_2[] = {
+		{TP6800_R7A_BLK_THRLD, 0x00},
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+	};
+	static const struct cmd bridge_init_3[] = {
+		{TP6800_R31_PIXEL_START, 0x20},
+		{TP6800_R32_PIXEL_END_L, 0x9f},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x13},
+		{TP6800_R35_LINE_END_L, 0xf8},
+		{TP6800_R36_LINE_END_H, 0x01},
+	};
+	static const struct cmd bridge_init_6[] = {
+		{0x08, 0xff},
+		{0x09, 0xff},
+		{0x0a, 0x5f},
+		{0x0b, 0x80},
+	};
+
+	reg_w(gspca_dev, 0x22, gspca_dev->alt);
+	bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+	reg_w(gspca_dev, 0x59, 0x40);
+	setexposure(gspca_dev);
+	reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+	reg_w_buf(gspca_dev, tp6810_ov_init_common,
+			ARRAY_SIZE(tp6810_ov_init_common));
+	reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4a, 0x7f);
+		reg_w(gspca_dev, 0x07, 0x05);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+	} else {
+		reg_w(gspca_dev, 0x4a, 0xff);
+		reg_w(gspca_dev, 0x07, 0x85);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+	}
+	setgamma(gspca_dev);
+	reg_w_buf(gspca_dev, tp6810_bridge_start,
+			ARRAY_SIZE(tp6810_bridge_start));
+
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4f, 0x00);
+		reg_w(gspca_dev, 0x4e, 0x7c);
+	}
+
+	reg_w(gspca_dev, 0x00, 0x00);
+
+	setsharpness(gspca_dev);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+				ARRAY_SIZE(color_gain[0]));
+	set_led(gspca_dev, 1);
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
+	setexposure(gspca_dev);
+	reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
+	set_dqt(gspca_dev, sd->quality);
+	if (sd->bridge == BRIDGE_TP6800) {
+		if (sd->sensor == SENSOR_CX0342)
+			cx0342_6800_start(gspca_dev);
+		else
+			soi763a_6800_start(gspca_dev);
+	} else {
+		if (sd->sensor == SENSOR_CX0342)
+			cx0342_6810_start(gspca_dev);
+		else
+			soi763a_6810_start(gspca_dev);
+		reg_w_buf(gspca_dev, tp6810_late_start,
+				ARRAY_SIZE(tp6810_late_start));
+		reg_w(gspca_dev, 0x80, 0x03);
+		reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
+
+		setexposure(gspca_dev);
+		setquality(gspca_dev);
+		setautogain(gspca_dev);
+	}
+
+	setframerate(gspca_dev);
+
+	return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->bridge == BRIDGE_TP6800)
+		reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
+	set_led(gspca_dev, 0);
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			u8 *data,
+			int len)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* the start of frame contains:
+	 *	ff d8
+	 *	ff fe
+	 *	width / 16
+	 *	height / 8
+	 *	quality
+	 */
+	if (sd->bridge == BRIDGE_TP6810) {
+		if (*data != 0x5a) {
+/*fixme: don't discard the whole frame..*/
+			if (*data == 0xaa || *data == 0x00)
+				return;
+			if (*data > 0xc0) {
+				PDEBUG(D_FRAM, "bad frame");
+				gspca_dev->last_packet_type = DISCARD_PACKET;
+				return;
+			}
+		}
+		data++;
+		len--;
+		if (*data == 0xff && data[1] == 0xd8) {
+/*fixme: there may be information in the 4 high bits*/
+			if ((data[6] & 0x0f) != sd->quality)
+				set_dqt(gspca_dev, data[6] & 0x0f);
+			gspca_frame_add(gspca_dev, FIRST_PACKET,
+					sd->jpeg_hdr, JPEG_HDR_SZ);
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data + 7, len - 7);
+		} else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+			gspca_frame_add(gspca_dev, LAST_PACKET,
+					data, len);
+		} else {
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data, len);
+		}
+		return;
+	}
+
+	switch (*data) {
+	case 0x55:
+		gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
+
+		if (len < 8
+		 || data[1] != 0xff || data[2] != 0xd8
+		 || data[3] != 0xff || data[4] != 0xfe) {
+
+			/* Have only seen this with corrupt frames */
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+			return;
+		}
+		if (data[7] != sd->quality)
+			set_dqt(gspca_dev, data[7]);
+		gspca_frame_add(gspca_dev, FIRST_PACKET,
+				sd->jpeg_hdr, JPEG_HDR_SZ);
+		gspca_frame_add(gspca_dev, INTER_PACKET,
+				data + 8, len - 8);
+		break;
+	case 0xaa:
+		gspca_dev->last_packet_type = DISCARD_PACKET;
+		break;
+	case 0xcc:
+		if (data[1] != 0xff || data[2] != 0xd8)
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data + 1, len - 1);
+		else
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+		break;
+	}
+}
+
+/* -- do autogain -- */
+/* gain setting is done in setexposure() for tp6810 */
+static void setgain(struct gspca_dev *gspca_dev) {}
+/* !! coarse_grained_expo_autogain is not used !! */
+#define exp_too_low_cnt bridge
+#define exp_too_high_cnt sensor
+
+#include "autogain_functions.h"
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int ret, alen;
+	int luma, expo;
+
+	if (sd->ag_cnt < 0)
+		return;
+	if (--sd->ag_cnt > 5)
+		return;
+	switch (sd->ag_cnt) {
+/*	case 5: */
+	default:
+		reg_w(gspca_dev, 0x7d, 0x00);
+		break;
+	case 4:
+		reg_w(gspca_dev, 0x27, 0xb0);
+		break;
+	case 3:
+		reg_w(gspca_dev, 0x0c, 0x01);
+		break;
+	case 2:
+		ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+				gspca_dev->usb_buf,
+				32,
+				&alen,
+				500);
+		if (ret < 0) {
+			pr_err("bulk err %d\n", ret);
+			break;
+		}
+		/* values not used (unknown) */
+		break;
+	case 1:
+		reg_w(gspca_dev, 0x27, 0xd0);
+		break;
+	case 0:
+		ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+				gspca_dev->usb_buf,
+				32,
+				&alen,
+				500);
+		if (ret < 0) {
+			pr_err("bulk err %d\n", ret);
+			break;
+		}
+		luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
+			(gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
+			(gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
+			(gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
+			(gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
+			(gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
+			(gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
+			(gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
+				/ 8;
+		if (gspca_dev->width == 640)
+			luma /= 4;
+		reg_w(gspca_dev, 0x7d, 0x00);
+
+		expo = sd->ctrls[EXPOSURE].val;
+		ret = auto_gain_n_exposure(gspca_dev, luma,
+				60,	/* desired luma */
+				6,	/* dead zone */
+				2,	/* gain knee */
+				70);	/* expo knee */
+		sd->ag_cnt = AG_CNT_START;
+		if (sd->bridge == BRIDGE_TP6810) {
+			if ((expo >= 128 && sd->ctrls[EXPOSURE].val < 128)
+			 || (expo < 128 && sd->ctrls[EXPOSURE].val >= 128))
+				setframerate(gspca_dev);
+		}
+		break;
+	}
+}
+
+/* get stream parameters (framerate) */
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
+			     struct v4l2_streamparm *parm)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_captureparm *cp = &parm->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	int fr, i;
+
+	cp->capability |= V4L2_CAP_TIMEPERFRAME;
+	tpf->numerator = 1;
+	i = get_fr_idx(gspca_dev);
+	if (i & 0x80) {
+		if (sd->bridge == BRIDGE_TP6800)
+			fr = rates[6 - (i & 0x07)];
+		else
+			fr = rates_6810[7 - (i & 0x07)];
+	} else {
+		fr = rates[6 - i];
+	}
+	tpf->denominator = fr;
+}
+
+/* set stream parameters (framerate) */
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
+			     struct v4l2_streamparm *parm)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_captureparm *cp = &parm->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	int fr, i;
+
+	sd->framerate = tpf->denominator / tpf->numerator;
+	if (gspca_dev->streaming)
+		setframerate(gspca_dev);
+
+	/* Return the actual framerate */
+	i = get_fr_idx(gspca_dev);
+	if (i & 0x80)
+		fr = rates_6810[7 - (i & 0x07)];
+	else
+		fr = rates[6 - i];
+	tpf->numerator = 1;
+	tpf->denominator = fr;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_SOI763A)
+		jpeg_set_qual(sd->jpeg_hdr, jcomp->quality);
+/*	else
+		fixme: TODO
+*/
+	return gspca_dev->usb_err;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = jpeg_q[sd->quality];
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
+static struct ctrl sd_ctrls[NCTRLS] = {
+[EXPOSURE] = {
+	    {
+		.id = V4L2_CID_EXPOSURE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Exposure",
+		.minimum = 0x01,
+		.maximum = 0xdc,
+		.step = 1,
+		.default_value = 0x4e,
+	    },
+	    .set_control = setexposure
+	},
+[QUALITY] = {
+	    {
+		.id = V4L2_CID_PRIVATE_BASE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Compression quality",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 13,
+	    },
+	    .set_control = setquality
+	},
+[RGAIN] = {
+	    {
+		.id = V4L2_CID_RED_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red balance",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set_control = setrgain
+	},
+[GAIN] = {
+	    {
+		.id = V4L2_CID_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gain",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set = sd_setgain
+	},
+[BGAIN] = {
+	    {
+		.id = V4L2_CID_BLUE_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue balance",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set_control = setbgain
+	},
+[SHARPNESS] = {
+	    {
+		.id	 = V4L2_CID_SHARPNESS,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Sharpness",
+		.minimum = 0,
+		.maximum = 3,
+		.step    = 1,
+		.default_value = 2,
+	    },
+	    .set_control = setsharpness
+	},
+[GAMMA] = {
+	    {
+		.id      = V4L2_CID_GAMMA,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gamma",
+		.minimum = 0,
+		.maximum = NGAMMA - 1,
+		.step    = 1,
+		.default_value = 1,
+	    },
+	    .set_control = setgamma
+	},
+[AUTOGAIN] = {
+	    {
+		.id      = V4L2_CID_AUTOGAIN,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Gain",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = AUTOGAIN_DEF
+	    },
+	    .set_control = setautogain
+	},
+};
+
+static const struct sd_desc sd_desc = {
+	.name = KBUILD_MODNAME,
+	.ctrls = sd_ctrls,
+	.nctrls = NCTRLS,
+	.config = sd_config,
+	.init = sd_init,
+	.isoc_init = sd_isoc_init,
+	.start = sd_start,
+	.stopN = sd_stopN,
+	.pkt_scan = sd_pkt_scan,
+	.dq_callback = sd_dq_callback,
+	.get_streamparm = sd_get_streamparm,
+	.set_streamparm = sd_set_streamparm,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
+};
+
+static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
+	{USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static int sd_probe(struct usb_interface *interface,
+		    const struct usb_device_id *id)
+{
+	return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
+			       THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+	.reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	return usb_register(&sd_driver);
+}
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
+
+module_param(force_sensor, int, 0644);
+MODULE_PARM_DESC(force_sensor,
+	"Force sensor. 0: cx0342, 1: soi763a");
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/vc032x.c linux-libre-3.2-gnu1/drivers/media/video/gspca/vc032x.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/vc032x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/vc032x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "vc032x"
 
 #include "gspca.h"
@@ -3169,7 +3171,7 @@ static void reg_r_i(struct gspca_dev *gs
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -3210,7 +3212,7 @@ static void reg_w_i(struct gspca_dev *gs
 			value, index, NULL, 0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -3235,8 +3237,7 @@ static u16 read_sensor_register(struct g
 
 	reg_r(gspca_dev, 0xa1, 0xb33f, 1);
 	if (!(gspca_dev->usb_buf[0] & 0x02)) {
-		err("I2c Bus Busy Wait %02x",
-			gspca_dev->usb_buf[0]);
+		pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
 		return 0;
 	}
 	reg_w(gspca_dev, 0xa0, address, 0xb33a);
@@ -3349,7 +3350,7 @@ static void i2c_write(struct gspca_dev *
 		msleep(20);
 	} while (--retry > 0);
 	if (retry <= 0)
-		err("i2c_write timeout");
+		pr_err("i2c_write timeout\n");
 }
 
 static void put_tab_to_reg(struct gspca_dev *gspca_dev,
@@ -3446,7 +3447,7 @@ static int sd_init(struct gspca_dev *gsp
 
 	switch (sensor) {
 	case -1:
-		err("Unknown sensor...");
+		pr_err("Unknown sensor...\n");
 		return -EINVAL;
 	case SENSOR_HV7131R:
 		PDEBUG(D_PROBE, "Find Sensor HV7131R");
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/vicam.c linux-libre-3.2-gnu1/drivers/media/video/gspca/vicam.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/vicam.c	2013-05-02 01:36:34.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/vicam.c	2013-05-01 23:44:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "vicam"
 #define HEADER_SIZE 64
 
@@ -117,7 +119,7 @@ static int vicam_control_msg(struct gspc
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      value, index, data, len, 1000);
 	if (ret < 0)
-		err("control msg req %02X error %d", request, ret);
+		pr_err("control msg req %02X error %d\n", request, ret);
 
 	return ret;
 }
@@ -189,8 +191,8 @@ static int vicam_read_frame(struct gspca
 			   data, size, &act_len, 10000);
 	/* successful, it returns 0, otherwise  negative */
 	if (ret < 0 || act_len != size) {
-		err("bulk read fail (%d) len %d/%d",
-			ret, act_len, size);
+		pr_err("bulk read fail (%d) len %d/%d\n",
+		       ret, act_len, size);
 		return -EIO;
 	}
 	return 0;
@@ -216,7 +218,7 @@ static void vicam_dostream(struct work_s
 		   HEADER_SIZE;
 	buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto exit;
 	}
 
@@ -269,7 +271,7 @@ static int sd_init(struct gspca_dev *gsp
 	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
 				    &gspca_dev->dev->dev);
 	if (ret) {
-		err("Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
+		pr_err("Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
 		return ret;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/w996Xcf.c linux-libre-3.2-gnu1/drivers/media/video/gspca/w996Xcf.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/w996Xcf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/w996Xcf.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
    the sensor drivers to v4l2 sub drivers, and properly split of this
    driver from ov519.c */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
 
 #define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
@@ -81,7 +83,7 @@ static void w9968cf_write_fsb(struct sd
 			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
 			      value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
 	if (ret < 0) {
-		err("Write FSB registers failed (%d)", ret);
+		pr_err("Write FSB registers failed (%d)\n", ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -108,7 +110,7 @@ static void w9968cf_write_sb(struct sd *
 	udelay(W9968CF_I2C_BUS_DELAY);
 
 	if (ret < 0) {
-		err("Write SB reg [01] %04x failed", value);
+		pr_err("Write SB reg [01] %04x failed\n", value);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -135,7 +137,7 @@ static int w9968cf_read_sb(struct sd *sd
 		ret = sd->gspca_dev.usb_buf[0] |
 		      (sd->gspca_dev.usb_buf[1] << 8);
 	} else {
-		err("Read SB reg [01] failed");
+		pr_err("Read SB reg [01] failed\n");
 		sd->gspca_dev.usb_err = ret;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/xirlink_cit.c linux-libre-3.2-gnu1/drivers/media/video/gspca/xirlink_cit.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/xirlink_cit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/xirlink_cit.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "xirlink-cit"
 
 #include <linux/input.h>
@@ -800,8 +802,8 @@ static int cit_write_reg(struct gspca_de
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			value, index, NULL, 0, 1000);
 	if (err < 0)
-		err("Failed to write a register (index 0x%04X,"
-			" value 0x%02X, error %d)", index, value, err);
+		pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+		       index, value, err);
 
 	return 0;
 }
@@ -816,8 +818,8 @@ static int cit_read_reg(struct gspca_dev
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			0x00, index, buf, 8, 1000);
 	if (res < 0) {
-		err("Failed to read a register (index 0x%04X, error %d)",
-			index, res);
+		pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+		       index, res);
 		return res;
 	}
 
@@ -1587,7 +1589,7 @@ static int cit_get_packet_size(struct gs
 	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
 	alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		return -EIO;
 	}
 
@@ -2824,7 +2826,7 @@ static int sd_isoc_nego(struct gspca_dev
 
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 	if (ret < 0)
-		err("set alt 1 err %d", ret);
+		pr_err("set alt 1 err %d\n", ret);
 
 	return ret;
 }
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/gspca/zc3xx.c linux-libre-3.2-gnu1/drivers/media/video/gspca/zc3xx.c
--- linux-libre-3.1-gnu1/drivers/media/video/gspca/zc3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/gspca/zc3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "zc3xx"
 
 #include <linux/input.h>
@@ -5666,7 +5668,7 @@ static u8 reg_r_i(struct gspca_dev *gspc
 			index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_r_i err %d", ret);
+		pr_err("reg_r_i err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return 0;
 	}
@@ -5698,7 +5700,7 @@ static void reg_w_i(struct gspca_dev *gs
 			value, index, NULL, 0,
 			500);
 	if (ret < 0) {
-		err("reg_w_i err %d", ret);
+		pr_err("reg_w_i err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -5724,7 +5726,7 @@ static u16 i2c_read(struct gspca_dev *gs
 	msleep(20);
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	if (retbyte != 0x00)
-		err("i2c_r status error %02x", retbyte);
+		pr_err("i2c_r status error %02x\n", retbyte);
 	retval = reg_r_i(gspca_dev, 0x0095);		/* read Lowbyte */
 	retval |= reg_r_i(gspca_dev, 0x0096) << 8;	/* read Hightbyte */
 	PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
@@ -5748,7 +5750,7 @@ static u8 i2c_write(struct gspca_dev *gs
 	msleep(1);
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	if (retbyte != 0x00)
-		err("i2c_w status error %02x", retbyte);
+		pr_err("i2c_w status error %02x\n", retbyte);
 	PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)",
 			reg, valH, valL, retbyte);
 	return retbyte;
@@ -6497,7 +6499,7 @@ static int sd_init(struct gspca_dev *gsp
 				PDEBUG(D_PROBE, "Sensor GC0303");
 				break;
 			default:
-				warn("Unknown sensor - set to TAS5130C");
+				pr_warn("Unknown sensor - set to TAS5130C\n");
 				sd->sensor = SENSOR_TAS5130C;
 			}
 			break;
@@ -6603,7 +6605,7 @@ static int sd_init(struct gspca_dev *gsp
 			sd->sensor = SENSOR_OV7620;	/* same sensor (?) */
 			break;
 		default:
-			err("Unknown sensor %04x", sensor);
+			pr_err("Unknown sensor %04x\n", sensor);
 			return -EINVAL;
 		}
 	}
@@ -6970,6 +6972,7 @@ static const struct sd_desc sd_desc = {
 };
 
 static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x03f0, 0x1b07)},
 	{USB_DEVICE(0x041e, 0x041e)},
 	{USB_DEVICE(0x041e, 0x4017)},
 	{USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c linux-libre-3.2-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c
--- linux-libre-3.1-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include "hdpvr.h"
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/hdpvr/Makefile linux-libre-3.2-gnu1/drivers/media/video/hdpvr/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/hdpvr/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/hdpvr/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,6 @@ hdpvr-objs	:= hdpvr-control.o hdpvr-core
 
 obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/hexium_gemini.c linux-libre-3.2-gnu1/drivers/media/video/hexium_gemini.c
--- linux-libre-3.1-gnu1/drivers/media/video/hexium_gemini.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/hexium_gemini.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,12 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DEBUG_VARIABLE debug
 
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 static int debug;
 module_param(debug, int, 0);
@@ -175,13 +178,14 @@ static int hexium_init_done(struct saa71
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D(("hexium_init_done called.\n"));
+	DEB_D("hexium_init_done called\n");
 
 	/* initialize the helper ics to useful values */
 	for (i = 0; i < sizeof(hexium_ks0127b); i++) {
 		data.byte = hexium_ks0127b[i];
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
+			pr_err("hexium_init_done() failed for address 0x%02x\n",
+			       i);
 		}
 	}
 
@@ -192,7 +196,7 @@ static int hexium_set_input(struct hexiu
 {
 	union i2c_smbus_data data;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	data.byte = hexium_input_select[input].byte;
 	if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
@@ -207,12 +211,13 @@ static int hexium_set_standard(struct he
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	while (vdec[i].adr != -1) {
 		data.byte = vdec[i].byte;
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
+			pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
+			       i);
 			return -1;
 		}
 		i++;
@@ -222,14 +227,14 @@ static int hexium_set_standard(struct he
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
 
 	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
 
-	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
 	return 0;
 }
 
@@ -240,7 +245,7 @@ static int vidioc_g_input(struct file *f
 
 	*input = hexium->cur_input;
 
-	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
 	return 0;
 }
 
@@ -249,7 +254,7 @@ static int vidioc_s_input(struct file *f
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+	DEB_EE("VIDIOC_S_INPUT %d\n", input);
 
 	if (input >= HEXIUM_INPUTS)
 		return -EINVAL;
@@ -270,7 +275,7 @@ static int vidioc_queryctrl(struct file
 	for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
 		if (hexium_controls[i].id == qc->id) {
 			*qc = hexium_controls[i];
-			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+			DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
 			return 0;
 		}
 	}
@@ -293,7 +298,7 @@ static int vidioc_g_ctrl(struct file *fi
 
 	if (vc->id == V4L2_CID_PRIVATE_BASE) {
 		vc->value = hexium->cur_bw;
-		DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
+		DEB_D("VIDIOC_G_CTRL BW:%d\n", vc->value);
 		return 0;
 	}
 	return -EINVAL;
@@ -316,7 +321,7 @@ static int vidioc_s_ctrl(struct file *fi
 	if (vc->id == V4L2_CID_PRIVATE_BASE)
 		hexium->cur_bw = vc->value;
 
-	DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
+	DEB_D("VIDIOC_S_CTRL BW:%d\n", hexium->cur_bw);
 
 	if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
 		hexium_set_standard(hexium, hexium_pal);
@@ -351,14 +356,14 @@ static struct saa7146_ext_vv vv_data;
 /* this function only gets called when the probing was successful */
 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
 {
-	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	struct hexium *hexium;
 	int ret;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
 	if (NULL == hexium) {
-		printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
+		pr_err("not enough kernel memory in hexium_attach()\n");
 		return -ENOMEM;
 	}
 	dev->ext_priv = hexium;
@@ -371,7 +376,7 @@ static int hexium_attach(struct saa7146_
 	};
 	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
-		DEB_S(("cannot register i2c-device. skipping.\n"));
+		DEB_S("cannot register i2c-device. skipping.\n");
 		kfree(hexium);
 		return -EFAULT;
 	}
@@ -402,11 +407,11 @@ static int hexium_attach(struct saa7146_
 	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
 	if (ret < 0) {
-		printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
+		pr_err("cannot register capture v4l2 device. skipping.\n");
 		return ret;
 	}
 
-	printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
+	pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
 	hexium_num++;
 
 	return 0;
@@ -416,7 +421,7 @@ static int hexium_detach(struct saa7146_
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_unregister_device(&hexium->video_dev, dev);
 	saa7146_vv_release(dev);
@@ -508,7 +513,7 @@ static struct saa7146_extension hexium_e
 static int __init hexium_init_module(void)
 {
 	if (0 != saa7146_register_extension(&hexium_extension)) {
-		DEB_S(("failed to register extension.\n"));
+		DEB_S("failed to register extension\n");
 		return -ENODEV;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/hexium_orion.c linux-libre-3.2-gnu1/drivers/media/video/hexium_orion.c
--- linux-libre-3.1-gnu1/drivers/media/video/hexium_orion.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/hexium_orion.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,12 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DEBUG_VARIABLE debug
 
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 static int debug;
 module_param(debug, int, 0);
@@ -209,7 +212,7 @@ static int hexium_probe(struct saa7146_d
 	union i2c_smbus_data data;
 	int err = 0;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	/* there are no hexium orion cards with revision 0 saa7146s */
 	if (0 == dev->revision) {
@@ -218,7 +221,7 @@ static int hexium_probe(struct saa7146_d
 
 	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
 	if (NULL == hexium) {
-		printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
+		pr_err("hexium_probe: not enough kernel memory\n");
 		return -ENOMEM;
 	}
 
@@ -234,7 +237,7 @@ static int hexium_probe(struct saa7146_d
 	};
 	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
-		DEB_S(("cannot register i2c-device. skipping.\n"));
+		DEB_S("cannot register i2c-device. skipping.\n");
 		kfree(hexium);
 		return -EFAULT;
 	}
@@ -248,7 +251,7 @@ static int hexium_probe(struct saa7146_d
 
 	/* detect newer Hexium Orion cards by subsystem ids */
 	if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
-		printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
+		pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_ORION_1SVHS_3BNC;
@@ -256,7 +259,7 @@ static int hexium_probe(struct saa7146_d
 	}
 
 	if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
-		printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
+		pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_ORION_4BNC;
@@ -266,7 +269,7 @@ static int hexium_probe(struct saa7146_d
 	/* check if this is an old hexium Orion card by looking at
 	   a saa7110 at address 0x4e */
 	if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
-		printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
+		pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_HV_PCI6_ORION;
@@ -288,13 +291,13 @@ static int hexium_init_done(struct saa71
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D(("hexium_init_done called.\n"));
+	DEB_D("hexium_init_done called\n");
 
 	/* initialize the helper ics to useful values */
 	for (i = 0; i < sizeof(hexium_saa7110); i++) {
 		data.byte = hexium_saa7110[i];
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_orion: failed for address 0x%02x\n", i);
+			pr_err("failed for address 0x%02x\n", i);
 		}
 	}
 
@@ -306,7 +309,7 @@ static int hexium_set_input(struct hexiu
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	for (i = 0; i < 8; i++) {
 		int adr = hexium_input_select[input].data[i].adr;
@@ -314,7 +317,7 @@ static int hexium_set_input(struct hexiu
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
 			return -1;
 		}
-		printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
+		pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
 	}
 
 	return 0;
@@ -322,14 +325,14 @@ static int hexium_set_input(struct hexiu
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
 
 	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
 
-	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
 	return 0;
 }
 
@@ -340,7 +343,7 @@ static int vidioc_g_input(struct file *f
 
 	*input = hexium->cur_input;
 
-	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
 	return 0;
 }
 
@@ -365,18 +368,18 @@ static int hexium_attach(struct saa7146_
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	saa7146_vv_init(dev, &vv_data);
 	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
 	vv_data.ops.vidioc_g_input = vidioc_g_input;
 	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
-		printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
+		pr_err("cannot register capture v4l2 device. skipping.\n");
 		return -1;
 	}
 
-	printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
+	pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
 	hexium_num++;
 
 	/* the rest */
@@ -390,7 +393,7 @@ static int hexium_detach(struct saa7146_
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_unregister_device(&hexium->video_dev, dev);
 	saa7146_vv_release(dev);
@@ -479,7 +482,7 @@ static struct saa7146_extension extensio
 static int __init hexium_init_module(void)
 {
 	if (0 != saa7146_register_extension(&extension)) {
-		DEB_S(("failed to register extension.\n"));
+		DEB_S("failed to register extension\n");
 		return -ENODEV;
 	}
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/imx074.c linux-libre-3.2-gnu1/drivers/media/video/imx074.c
--- linux-libre-3.1-gnu1/drivers/media/video/imx074.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/imx074.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
@@ -267,6 +268,17 @@ static int imx074_g_chip_ident(struct v4
 	return 0;
 }
 
+static int imx074_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	cfg->type = V4L2_MBUS_CSI2;
+	cfg->flags = V4L2_MBUS_CSI2_2_LANE |
+		V4L2_MBUS_CSI2_CHANNEL_0 |
+		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
 	.s_stream	= imx074_s_stream,
 	.s_mbus_fmt	= imx074_s_fmt,
@@ -275,6 +287,7 @@ static struct v4l2_subdev_video_ops imx0
 	.enum_mbus_fmt	= imx074_enum_fmt,
 	.g_crop		= imx074_g_crop,
 	.cropcap	= imx074_cropcap,
+	.g_mbus_config	= imx074_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
@@ -286,28 +299,7 @@ static struct v4l2_subdev_ops imx074_sub
 	.video	= &imx074_subdev_video_ops,
 };
 
-/*
- * We have to provide soc-camera operations, but we don't have anything to say
- * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
- */
-static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
-{
-	return 0;
-}
-
-static int imx074_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	return -EINVAL;
-}
-
-static struct soc_camera_ops imx074_ops = {
-	.query_bus_param	= imx074_query_bus_param,
-	.set_bus_param		= imx074_set_bus_param,
-};
-
-static int imx074_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int imx074_video_probe(struct i2c_client *client)
 {
 	int ret;
 	u16 id;
@@ -417,17 +409,10 @@ static int imx074_probe(struct i2c_clien
 			const struct i2c_device_id *did)
 {
 	struct imx074 *priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "IMX074: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "IMX074: missing platform data!\n");
 		return -EINVAL;
@@ -445,12 +430,10 @@ static int imx074_probe(struct i2c_clien
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
 
-	icd->ops	= &imx074_ops;
 	priv->fmt	= &imx074_colour_fmts[0];
 
-	ret = imx074_video_probe(icd, client);
+	ret = imx074_video_probe(client);
 	if (ret < 0) {
-		icd->ops = NULL;
 		kfree(priv);
 		return ret;
 	}
@@ -461,10 +444,8 @@ static int imx074_probe(struct i2c_clien
 static int imx074_remove(struct i2c_client *client)
 {
 	struct imx074 *priv = to_imx074(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
 	kfree(priv);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/ivtv/ivtv-driver.c linux-libre-3.2-gnu1/drivers/media/video/ivtv/ivtv-driver.c
--- linux-libre-3.1-gnu1/drivers/media/video/ivtv/ivtv-driver.c	2013-05-02 01:33:56.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/ivtv/ivtv-driver.c	2013-05-01 23:42:04.000000000 -0400
@@ -1180,6 +1180,8 @@ static int __devinit ivtv_probe(struct p
 		setup.addr = ADDR_UNSET;
 		setup.type = itv->options.tuner;
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (itv->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
 			ivtv_reset_tuner_gpio : NULL;
 		ivtv_call_all(itv, tuner, s_type_addr, &setup);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/ivtv/ivtv-ioctl.c linux-libre-3.2-gnu1/drivers/media/video/ivtv/ivtv-ioctl.c
--- linux-libre-3.1-gnu1/drivers/media/video/ivtv/ivtv-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/ivtv/ivtv-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1203,9 +1203,7 @@ static int ivtv_g_sliced_vbi_cap(struct
 					cap->service_lines[f][l] = set;
 			}
 		}
-		return 0;
-	}
-	if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+	} else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
 		if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
 			return -EINVAL;
 		if (itv->is_60hz) {
@@ -1215,9 +1213,16 @@ static int ivtv_g_sliced_vbi_cap(struct
 			cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
 			cap->service_lines[0][16] = V4L2_SLICED_VPS;
 		}
-		return 0;
+	} else {
+		return -EINVAL;
 	}
-	return -EINVAL;
+
+	set = 0;
+	for (f = 0; f < 2; f++)
+		for (l = 0; l < 24; l++)
+			set |= cap->service_lines[f][l];
+	cap->service_set = set;
+	return 0;
 }
 
 static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/ivtv/Makefile linux-libre-3.2-gnu1/drivers/media/video/ivtv/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/ivtv/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/ivtv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,8 +7,8 @@ ivtv-objs	:= ivtv-routing.o ivtv-cards.o
 obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
 obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/Kconfig linux-libre-3.2-gnu1/drivers/media/video/Kconfig
--- linux-libre-3.1-gnu1/drivers/media/video/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -467,6 +467,20 @@ config VIDEO_OV7670
 	  OV7670 VGA camera.  It currently only works with the M88ALP01
 	  controller.
 
+config VIDEO_MT9P031
+	tristate "Aptina MT9P031 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+	tristate "Aptina MT9T001 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt0t001 3 Mpixel camera.
+
 config VIDEO_MT9V011
 	tristate "Micron mt9v011 sensor support"
 	depends on I2C && VIDEO_V4L2
@@ -489,6 +503,27 @@ config VIDEO_TCM825X
 	  This is a driver for the Toshiba TCM825x VGA camera sensor.
 	  It is used for example in Nokia N800.
 
+config VIDEO_SR030PC30
+	tristate "Siliconfile SR030PC30 sensor support"
+	depends on I2C && VIDEO_V4L2
+	---help---
+	  This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+	tristate "Siliconfile NOON010PC30 sensor support"
+	depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/video/m5mols/Kconfig"
+
+config VIDEO_S5K6AA
+	tristate "Samsung S5K6AAFX sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+	  camera sensor with an embedded SoC image signal processor.
+
 comment "Flash devices"
 
 config VIDEO_ADP1653
@@ -708,6 +743,8 @@ source "drivers/media/video/cx88/Kconfig
 
 source "drivers/media/video/cx23885/Kconfig"
 
+source "drivers/media/video/cx25821/Kconfig"
+
 source "drivers/media/video/au0828/Kconfig"
 
 source "drivers/media/video/ivtv/Kconfig"
@@ -737,12 +774,6 @@ config VIDEO_M32R_AR_M64278
 	  To compile this driver as a module, choose M here: the
 	  module will be called arv.
 
-config VIDEO_SR030PC30
-	tristate "SR030PC30 VGA camera sensor support"
-	depends on I2C && VIDEO_V4L2
-	---help---
-	  This driver supports SR030PC30 VGA camera from Siliconfile
-
 config VIDEO_VIA_CAMERA
 	tristate "VIAFB camera controller support"
 	depends on FB_VIA
@@ -753,18 +784,9 @@ config VIDEO_VIA_CAMERA
 	   Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
 	   with ov7670 sensors.
 
-config VIDEO_NOON010PC30
-	tristate "NOON010PC30 CIF camera sensor support"
-	depends on I2C && VIDEO_V4L2
-	---help---
-	  This driver supports NOON010PC30 CIF camera from Siliconfile
-
-source "drivers/media/video/m5mols/Kconfig"
-
 config VIDEO_OMAP3
 	tristate "OMAP 3 Camera support (EXPERIMENTAL)"
-	select OMAP_IOMMU
-	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
+	depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
 	---help---
 	  Driver for an OMAP 3 camera controller.
 
@@ -949,8 +971,9 @@ config VIDEO_MX2
 	  Interface
 
 config  VIDEO_SAMSUNG_S5P_FIMC
-	tristate "Samsung S5P and EXYNOS4 camera host interface driver"
-	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+	tristate "Samsung S5P and EXYNOS4 camera interface driver (EXPERIMENTAL)"
+	depends on VIDEO_V4L2 && I2C && PLAT_S5P && PM_RUNTIME && \
+		VIDEO_V4L2_SUBDEV_API && EXPERIMENTAL
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	---help---
@@ -1004,6 +1027,8 @@ source "drivers/media/video/tlg2300/Kcon
 
 source "drivers/media/video/cx231xx/Kconfig"
 
+source "drivers/media/video/tm6000/Kconfig"
+
 source "drivers/media/video/usbvision/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/m5mols/m5mols_core.c linux-libre-3.2-gnu1/drivers/media/video/m5mols/m5mols_core.c
--- linux-libre-3.1-gnu1/drivers/media/video/m5mols/m5mols_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/m5mols/m5mols_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
@@ -333,7 +334,7 @@ int m5mols_mode(struct m5mols_info *info
 	int ret = -EINVAL;
 	u8 reg;
 
-	if (mode < REG_PARAMETER && mode > REG_CAPTURE)
+	if (mode < REG_PARAMETER || mode > REG_CAPTURE)
 		return ret;
 
 	ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
@@ -510,9 +511,6 @@ static int m5mols_get_fmt(struct v4l2_su
 	struct m5mols_info *info = to_m5mols(sd);
 	struct v4l2_mbus_framefmt *format;
 
-	if (fmt->pad != 0)
-		return -EINVAL;
-
 	format = __find_format(info, fh, fmt->which, info->res_type);
 	if (!format)
 		return -EINVAL;
@@ -531,9 +529,6 @@ static int m5mols_set_fmt(struct v4l2_su
 	u32 resolution = 0;
 	int ret;
 
-	if (fmt->pad != 0)
-		return -EINVAL;
-
 	ret = __find_resolution(sd, format, &type, &resolution);
 	if (ret < 0)
 		return ret;
@@ -542,13 +537,14 @@ static int m5mols_set_fmt(struct v4l2_su
 	if (!sfmt)
 		return 0;
 
-	*sfmt		= m5mols_default_ffmt[type];
-	sfmt->width	= format->width;
-	sfmt->height	= format->height;
+
+	format->code = m5mols_default_ffmt[type].code;
+	format->colorspace = V4L2_COLORSPACE_JPEG;
+	format->field = V4L2_FIELD_NONE;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		*sfmt = *format;
 		info->resolution = resolution;
-		info->code = format->code;
 		info->res_type = type;
 	}
 
@@ -625,13 +621,14 @@ static int m5mols_start_monitor(struct m
 static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct m5mols_info *info = to_m5mols(sd);
+	u32 code = info->ffmt[info->res_type].code;
 
 	if (enable) {
 		int ret = -EINVAL;
 
-		if (is_code(info->code, M5MOLS_RESTYPE_MONITOR))
+		if (is_code(code, M5MOLS_RESTYPE_MONITOR))
 			ret = m5mols_start_monitor(info);
-		if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE))
+		if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
 			ret = m5mols_start_capture(info);
 
 		return ret;
@@ -936,7 +933,7 @@ static int __devinit m5mols_probe(struct
 		return -EINVAL;
 	}
 
-	if (!pdata->irq) {
+	if (!client->irq) {
 		dev_err(&client->dev, "Interrupt not assigned\n");
 		return -EINVAL;
 	}
@@ -973,7 +970,7 @@ static int __devinit m5mols_probe(struct
 
 	init_waitqueue_head(&info->irq_waitq);
 	INIT_WORK(&info->work_irq, m5mols_irq_work);
-	ret = request_irq(pdata->irq, m5mols_irq_handler,
+	ret = request_irq(client->irq, m5mols_irq_handler,
 			  IRQF_TRIGGER_RISING, MODULE_NAME, sd);
 	if (ret) {
 		dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
@@ -998,7 +995,7 @@ static int __devexit m5mols_remove(struc
 	struct m5mols_info *info = to_m5mols(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	free_irq(info->pdata->irq, sd);
+	free_irq(client->irq, sd);
 
 	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
 	gpio_free(info->pdata->gpio_reset);
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/m5mols/m5mols.h linux-libre-3.2-gnu1/drivers/media/video/m5mols/m5mols.h
--- linux-libre-3.1-gnu1/drivers/media/video/m5mols/m5mols.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/m5mols/m5mols.h	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,6 @@ struct m5mols_version {
  * @pad: media pad
  * @ffmt: current fmt according to resolution type
  * @res_type: current resolution type
- * @code: current code
  * @irq_waitq: waitqueue for the capture
  * @work_irq: workqueue for the IRQ
  * @flags: state variable for the interrupt handler
@@ -192,7 +191,6 @@ struct m5mols_info {
 	struct media_pad pad;
 	struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
 	int res_type;
-	enum v4l2_mbus_pixelcode code;
 	wait_queue_head_t irq_waitq;
 	struct work_struct work_irq;
 	unsigned long flags;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/Makefile linux-libre-3.2-gnu1/drivers/media/video/Makefile
--- linux-libre-3.1-gnu1/drivers/media/video/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -65,11 +65,14 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083
 obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
 obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
 obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)	+= m5mols/
+obj-$(CONFIG_VIDEO_S5K6AA)	+= s5k6aa.o
 obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)		+= imx074.o
@@ -102,9 +105,11 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
 obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
@@ -190,6 +195,6 @@ obj-y	+= davinci/
 
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/marvell-ccic/mcam-core.c linux-libre-3.2-gnu1/drivers/media/video/marvell-ccic/mcam-core.c
--- linux-libre-3.1-gnu1/drivers/media/video/marvell-ccic/mcam-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/marvell-ccic/mcam-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -450,7 +450,7 @@ static void mcam_set_contig_buffer(struc
 		buf = cam->vb_bufs[frame ^ 0x1];
 		cam->vb_bufs[frame] = buf;
 		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-				vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
 		singles++;
 		return;
@@ -461,7 +461,7 @@ static void mcam_set_contig_buffer(struc
 	buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
 	list_del_init(&buf->queue);
 	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-			vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 	cam->vb_bufs[frame] = buf;
 	clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 }
@@ -883,8 +883,9 @@ static int mcam_read_setup(struct mcam_c
  * Videobuf2 interface code.
  */
 
-static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
-		unsigned int *num_planes, unsigned long sizes[],
+static int mcam_vb_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbufs,
+		unsigned int *num_planes, unsigned int sizes[],
 		void *alloc_ctxs[])
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
@@ -940,12 +941,14 @@ static void mcam_vb_wait_finish(struct v
 /*
  * These need to be called with the mutex held from vb2
  */
-static int mcam_vb_start_streaming(struct vb2_queue *vq)
+static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
 
-	if (cam->state != S_IDLE)
+	if (cam->state != S_IDLE) {
+		INIT_LIST_HEAD(&cam->buffers);
 		return -EINVAL;
+	}
 	cam->sequence = 0;
 	/*
 	 * Videobuf2 sneakily hoards all the buffers and won't
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/marvell-ccic/mmp-driver.c linux-libre-3.2-gnu1/drivers/media/video/marvell-ccic/mmp-driver.c
--- linux-libre-3.1-gnu1/drivers/media/video/marvell-ccic/mmp-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/marvell-ccic/mmp-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 
 #include "mcam-core.h"
 
+MODULE_ALIAS("platform:mmp-camera");
 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
 MODULE_LICENSE("GPL");
 
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/mem2mem_testdev.c linux-libre-3.2-gnu1/drivers/media/video/mem2mem_testdev.c
--- linux-libre-3.1-gnu1/drivers/media/video/mem2mem_testdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/mem2mem_testdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -738,9 +738,10 @@ static const struct v4l2_ioctl_ops m2mte
  * Queue operations
  */
 
-static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int m2mtest_queue_setup(struct vb2_queue *vq,
+				const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
 	struct m2mtest_q_data *q_data;
@@ -793,10 +794,24 @@ static void m2mtest_buf_queue(struct vb2
 	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 }
 
+static void m2mtest_wait_prepare(struct vb2_queue *q)
+{
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+	m2mtest_unlock(ctx);
+}
+
+static void m2mtest_wait_finish(struct vb2_queue *q)
+{
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+	m2mtest_lock(ctx);
+}
+
 static struct vb2_ops m2mtest_qops = {
 	.queue_setup	 = m2mtest_queue_setup,
 	.buf_prepare	 = m2mtest_buf_prepare,
 	.buf_queue	 = m2mtest_buf_queue,
+	.wait_prepare	 = m2mtest_wait_prepare,
+	.wait_finish	 = m2mtest_wait_finish,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/msp3400-driver.c linux-libre-3.2-gnu1/drivers/media/video/msp3400-driver.c
--- linux-libre-3.1-gnu1/drivers/media/video/msp3400-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/msp3400-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -426,6 +426,20 @@ static int msp_s_frequency(struct v4l2_s
 	return 0;
 }
 
+static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	*id &= state->detected_std;
+
+	v4l_dbg(2, msp_debug, client,
+		"detected standard: %s(0x%08Lx)\n",
+		msp_standard_std_name(state->std), state->detected_std);
+
+	return 0;
+}
+
 static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
 {
 	struct msp_state *state = to_state(sd);
@@ -616,6 +630,10 @@ static const struct v4l2_subdev_core_ops
 	.s_std = msp_s_std,
 };
 
+static const struct v4l2_subdev_video_ops msp_video_ops = {
+	.querystd = msp_querystd,
+};
+
 static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
 	.s_frequency = msp_s_frequency,
 	.g_tuner = msp_g_tuner,
@@ -630,6 +648,7 @@ static const struct v4l2_subdev_audio_op
 
 static const struct v4l2_subdev_ops msp_ops = {
 	.core = &msp_core_ops,
+	.video = &msp_video_ops,
 	.tuner = &msp_tuner_ops,
 	.audio = &msp_audio_ops,
 };
@@ -664,6 +683,7 @@ static int msp_probe(struct i2c_client *
 	v4l2_i2c_subdev_init(sd, client, &msp_ops);
 
 	state->v4l2_std = V4L2_STD_NTSC;
+	state->detected_std = V4L2_STD_ALL;
 	state->audmode = V4L2_TUNER_MODE_STEREO;
 	state->input = -1;
 	state->i2s_mode = 0;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/msp3400-driver.h linux-libre-3.2-gnu1/drivers/media/video/msp3400-driver.h
--- linux-libre-3.1-gnu1/drivers/media/video/msp3400-driver.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/msp3400-driver.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,7 +75,7 @@ struct msp_state {
 	int opmode;
 	int std;
 	int mode;
-	v4l2_std_id v4l2_std;
+	v4l2_std_id v4l2_std, detected_std;
 	int nicam_on;
 	int acb;
 	int in_scart;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/msp3400-kthreads.c linux-libre-3.2-gnu1/drivers/media/video/msp3400-kthreads.c
--- linux-libre-3.1-gnu1/drivers/media/video/msp3400-kthreads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/msp3400-kthreads.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,29 +37,49 @@ static struct {
 	int retval;
 	int main, second;
 	char *name;
+	v4l2_std_id std;
 } msp_stdlist[] = {
-	{ 0x0000, 0, 0, "could not detect sound standard" },
-	{ 0x0001, 0, 0, "autodetect start" },
-	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72  M Dual FM-Stereo" },
-	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74  B/G Dual FM-Stereo" },
-	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25  D/K1 Dual FM-Stereo" },
-	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74  D/K2 Dual FM-Stereo" },
-	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  D/K FM-Mono (HDEV3)" },
-	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74  D/K3 Dual FM-Stereo" },
-	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85  B/G NICAM FM" },
-	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  L NICAM AM" },
-	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55  I NICAM FM" },
-	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM" },
-	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV2)" },
-	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV3)" },
-	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Stereo" },
-	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Mono + SAP" },
-	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M EIA-J Japan Stereo" },
-	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7  FM-Stereo Radio" },
-	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  SAT-Mono" },
-	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20  SAT-Stereo" },
-	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2  SAT ADR" },
-	{     -1, 0, 0, NULL }, /* EOF */
+	{ 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
+	{ 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
+	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
+	  "4.5/4.72  M Dual FM-Stereo", V4L2_STD_MN },
+	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
+	  "5.5/5.74  B/G Dual FM-Stereo", V4L2_STD_BG },
+	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
+	  "6.5/6.25  D/K1 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
+	  "6.5/6.74  D/K2 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  D/K FM-Mono (HDEV3)", V4L2_STD_DK },
+	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
+	  "6.5/5.74  D/K3 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
+	  "5.5/5.85  B/G NICAM FM", V4L2_STD_BG },
+	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  L NICAM AM", V4L2_STD_L },
+	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
+	  "6.0/6.55  I NICAM FM", V4L2_STD_PAL_I },
+	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM", V4L2_STD_DK },
+	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV2)", V4L2_STD_DK },
+	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV3)", V4L2_STD_DK },
+	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Stereo", V4L2_STD_MTS },
+	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Mono + SAP", V4L2_STD_MTS },
+	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
+	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+	  "10.7  FM-Stereo Radio", V4L2_STD_ALL },
+	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  SAT-Mono", V4L2_STD_ALL },
+	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
+	  "7.02/7.20  SAT-Stereo", V4L2_STD_ALL },
+	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
+	  "7.2  SAT ADR", V4L2_STD_ALL },
+	{     -1, 0, 0, NULL, 0 }, /* EOF */
 };
 
 static struct msp3400c_init_data_dem {
@@ -156,6 +176,16 @@ const char *msp_standard_std_name(int st
 	return "unknown";
 }
 
+static v4l2_std_id msp_standard_std(int std)
+{
+	int i;
+
+	for (i = 0; msp_stdlist[i].name != NULL; i++)
+		if (msp_stdlist[i].retval == std)
+			return msp_stdlist[i].std;
+	return V4L2_STD_ALL;
+}
+
 static void msp_set_source(struct i2c_client *client, u16 src)
 {
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
@@ -479,6 +509,7 @@ int msp3400c_thread(void *data)
 	int count, max1, max2, val1, val2, val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
@@ -579,6 +610,7 @@ restart:
 		state->main = msp3400c_carrier_detect_main[max1].cdo;
 		switch (max1) {
 		case 1: /* 5.5 */
+			state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
 			if (max2 == 0) {
 				/* B/G FM-stereo */
 				state->second = msp3400c_carrier_detect_55[max2].cdo;
@@ -596,6 +628,7 @@ restart:
 			break;
 		case 2: /* 6.0 */
 			/* PAL I NICAM */
+			state->detected_std = V4L2_STD_PAL_I;
 			state->second = MSP_CARRIER(6.552);
 			msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
 			state->nicam_on = 1;
@@ -607,22 +640,26 @@ restart:
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
 			} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
 				/* L NICAM or AM-mono */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_L;
 			} else if (max2 == 0 && state->has_nicam) {
 				/* D/K NICAM */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
 				state->nicam_on = 1;
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
 			} else {
 				goto no_second;
 			}
 			break;
 		case 0: /* 4.5 */
+			state->detected_std = V4L2_STD_MN;
 		default:
 no_second:
 			state->second = msp3400c_carrier_detect_main[max1].cdo;
@@ -662,6 +699,7 @@ int msp3410d_thread(void *data)
 	int val, i, std, count;
 
 	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
@@ -743,6 +781,8 @@ restart:
 					msp_stdlist[8].name : "unknown", val);
 			state->std = val = 0x0009;
 			msp_write_dem(client, 0x20, val);
+		} else {
+			state->detected_std = msp_standard_std(state->std);
 		}
 
 		/* set stereo */
@@ -957,6 +997,7 @@ int msp34xxg_thread(void *data)
 	int val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
@@ -1013,6 +1054,7 @@ unmute:
 		v4l_dbg(1, msp_debug, client,
 			"detected standard: %s (0x%04x)\n",
 			msp_standard_std_name(state->std), state->std);
+		state->detected_std = msp_standard_std(state->std);
 
 		if (state->std == 9) {
 			/* AM NICAM mode */
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/mt9m001.c linux-libre-3.2-gnu1/drivers/media/video/mt9m001.c
--- linux-libre-3.1-gnu1/drivers/media/video/mt9m001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/mt9m001.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,13 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/log2.h>
+#include <linux/module.h>
 
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 /*
  * mt9m001 i2c address 0x5d
@@ -84,15 +87,19 @@ static const struct mt9m001_datafmt mt9m
 
 struct mt9m001 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
 	struct v4l2_rect rect;	/* Sensor window */
 	const struct mt9m001_datafmt *fmt;
 	const struct mt9m001_datafmt *fmts;
 	int num_fmts;
 	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
-	unsigned int gain;
-	unsigned int exposure;
+	unsigned int total_h;
 	unsigned short y_skip_top;	/* Lines to skip at the top */
-	unsigned char autoexposure;
 };
 
 static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
@@ -165,54 +172,13 @@ static int mt9m001_s_stream(struct v4l2_
 	return 0;
 }
 
-static int mt9m001_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
-
-	/* Only one width bit may be set */
-	if (!is_power_of_2(width_flag))
-		return -EINVAL;
-
-	if (icl->set_bus_param)
-		return icl->set_bus_param(icl, width_flag);
-
-	/*
-	 * Without board specific bus width settings we only support the
-	 * sensors native bus width
-	 */
-	if (width_flag == SOCAM_DATAWIDTH_10)
-		return 0;
-
-	return -EINVAL;
-}
-
-static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	/* MT9M001 has all capture_format parameters fixed */
-	unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER;
-
-	if (icl->query_bus_param)
-		flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
 	struct v4l2_rect rect = a->c;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	int ret;
 	const u16 hblank = 9, vblank = 25;
-	unsigned int total_h;
 
 	if (mt9m001->fmts == mt9m001_colour_fmts)
 		/*
@@ -231,7 +197,7 @@ static int mt9m001_s_crop(struct v4l2_su
 	soc_camera_limit_side(&rect.top, &rect.height,
 		     MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
 
-	total_h = rect.height + mt9m001->y_skip_top + vblank;
+	mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank;
 
 	/* Blanking and start values - default... */
 	ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
@@ -240,7 +206,7 @@ static int mt9m001_s_crop(struct v4l2_su
 
 	/*
 	 * The caller provides a supported format, as verified per
-	 * call to icd->try_fmt()
+	 * call to .try_mbus_fmt()
 	 */
 	if (!ret)
 		ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
@@ -251,17 +217,8 @@ static int mt9m001_s_crop(struct v4l2_su
 	if (!ret)
 		ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
 				rect.height + mt9m001->y_skip_top - 1);
-	if (!ret && mt9m001->autoexposure) {
-		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
-		if (!ret) {
-			const struct v4l2_queryctrl *qctrl =
-				soc_camera_find_qctrl(icd->ops,
-						      V4L2_CID_EXPOSURE);
-			mt9m001->exposure = (524 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				1048 + qctrl->minimum;
-		}
-	}
+	if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
+		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
 
 	if (!ret)
 		mt9m001->rect = rect;
@@ -421,107 +378,48 @@ static int mt9m001_s_register(struct v4l
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m001_controls[] = {
-	{
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Vertically",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 64,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 1,
-		.maximum	= 255,
-		.step		= 1,
-		.default_value	= 255,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9m001_ops = {
-	.set_bus_param		= mt9m001_set_bus_param,
-	.query_bus_param	= mt9m001_query_bus_param,
-	.controls		= mt9m001_controls,
-	.num_controls		= ARRAY_SIZE(mt9m001_controls),
-};
-
-static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	int data;
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	s32 min, max;
 
 	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		data = reg_read(client, MT9M001_READ_OPTIONS2);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x8000);
-		break;
 	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = mt9m001->autoexposure;
-		break;
-	case V4L2_CID_GAIN:
-		ctrl->value = mt9m001->gain;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = mt9m001->exposure;
+		min = mt9m001->exposure->minimum;
+		max = mt9m001->exposure->maximum;
+		mt9m001->exposure->val =
+			(524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min;
 		break;
 	}
 	return 0;
 }
 
-static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	struct v4l2_subdev *sd = &mt9m001->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	const struct v4l2_queryctrl *qctrl;
+	struct v4l2_ctrl *exp = mt9m001->exposure;
 	int data;
 
-	qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
-
-	if (!qctrl)
-		return -EINVAL;
-
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
 		else
 			data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
+
 	case V4L2_CID_GAIN:
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
 		/* See Datasheet Table 7, Gain settings. */
-		if (ctrl->value <= qctrl->default_value) {
+		if (ctrl->val <= ctrl->default_value) {
 			/* Pack it into 0..1 step 0.125, register values 0..8 */
-			unsigned long range = qctrl->default_value - qctrl->minimum;
-			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+			unsigned long range = ctrl->default_value - ctrl->minimum;
+			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&client->dev, "Setting gain %d\n", data);
 			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -530,8 +428,8 @@ static int mt9m001_s_ctrl(struct v4l2_su
 		} else {
 			/* Pack it into 1.125..15 variable step, register values 9..67 */
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
-			unsigned long range = qctrl->maximum - qctrl->default_value - 1;
-			unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
+			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
 					       111 + range / 2) / range + 9;
 
 			if (gain <= 32)
@@ -547,66 +445,44 @@ static int mt9m001_s_ctrl(struct v4l2_su
 			if (data < 0)
 				return -EIO;
 		}
+		return 0;
 
-		/* Success */
-		mt9m001->gain = ctrl->value;
-		break;
-	case V4L2_CID_EXPOSURE:
-		/* mt9m001 has maximum == default */
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else {
-			unsigned long range = qctrl->maximum - qctrl->minimum;
-			unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+			unsigned long range = exp->maximum - exp->minimum;
+			unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
 						 range / 2) / range + 1;
 
 			dev_dbg(&client->dev,
 				"Setting shutter width from %d to %lu\n",
-				reg_read(client, MT9M001_SHUTTER_WIDTH),
-				shutter);
+				reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
 			if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
 				return -EIO;
-			mt9m001->exposure = ctrl->value;
-			mt9m001->autoexposure = 0;
-		}
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		if (ctrl->value) {
+		} else {
 			const u16 vblank = 25;
-			unsigned int total_h = mt9m001->rect.height +
+
+			mt9m001->total_h = mt9m001->rect.height +
 				mt9m001->y_skip_top + vblank;
-			if (reg_write(client, MT9M001_SHUTTER_WIDTH,
-				      total_h) < 0)
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h) < 0)
 				return -EIO;
-			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
-			mt9m001->exposure = (524 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				1048 + qctrl->minimum;
-			mt9m001->autoexposure = 1;
-		} else
-			mt9m001->autoexposure = 0;
-		break;
+		}
+		return 0;
 	}
-	return 0;
+	return -EINVAL;
 }
 
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m001_video_probe(struct soc_camera_device *icd,
+static int mt9m001_video_probe(struct soc_camera_link *icl,
 			       struct i2c_client *client)
 {
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
 	s32 data;
 	unsigned long flags;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/* Enable the chip */
 	data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
 	dev_dbg(&client->dev, "write: %d\n", data);
@@ -661,18 +537,11 @@ static int mt9m001_video_probe(struct so
 		dev_err(&client->dev, "Failed to initialise the camera\n");
 
 	/* mt9m001_init() has reset the chip, returning registers to defaults */
-	mt9m001->gain = 64;
-	mt9m001->exposure = 255;
-
-	return ret;
+	return v4l2_ctrl_handler_setup(&mt9m001->hdl);
 }
 
-static void mt9m001_video_remove(struct soc_camera_device *icd)
+static void mt9m001_video_remove(struct soc_camera_link *icl)
 {
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	dev_dbg(icd->pdev, "Video removed: %p, %p\n",
-		icd->parent, icd->vdev);
 	if (icl->free_bus)
 		icl->free_bus(icl);
 }
@@ -687,9 +556,12 @@ static int mt9m001_g_skip_top_lines(stru
 	return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
+	.g_volatile_ctrl = mt9m001_g_volatile_ctrl,
+	.s_ctrl = mt9m001_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
-	.g_ctrl		= mt9m001_g_ctrl,
-	.s_ctrl		= mt9m001_s_ctrl,
 	.g_chip_ident	= mt9m001_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= mt9m001_g_register,
@@ -710,6 +582,40 @@ static int mt9m001_enum_fmt(struct v4l2_
 	return 0;
 }
 
+static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	/* MT9M001 has all capture_format parameters fixed */
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_MASTER;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	const struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	unsigned int bps = soc_mbus_get_fmtdesc(mt9m001->fmt->code)->bits_per_sample;
+
+	if (icl->set_bus_param)
+		return icl->set_bus_param(icl, 1 << (bps - 1));
+
+	/*
+	 * Without board specific bus width settings we only support the
+	 * sensors native bus width
+	 */
+	return bps == 10 ? 0 : -EINVAL;
+}
+
 static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
 	.s_stream	= mt9m001_s_stream,
 	.s_mbus_fmt	= mt9m001_s_fmt,
@@ -719,6 +625,8 @@ static struct v4l2_subdev_video_ops mt9m
 	.g_crop		= mt9m001_g_crop,
 	.cropcap	= mt9m001_cropcap,
 	.enum_mbus_fmt	= mt9m001_enum_fmt,
+	.g_mbus_config	= mt9m001_g_mbus_config,
+	.s_mbus_config	= mt9m001_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
@@ -735,17 +643,10 @@ static int mt9m001_probe(struct i2c_clie
 			 const struct i2c_device_id *did)
 {
 	struct mt9m001 *mt9m001;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "MT9M001 driver needs platform data\n");
 		return -EINVAL;
@@ -762,25 +663,40 @@ static int mt9m001_probe(struct i2c_clie
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m001->hdl, 4);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+	mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl,
+			&mt9m001_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m001->subdev.ctrl_handler = &mt9m001->hdl;
+	if (mt9m001->hdl.error) {
+		int err = mt9m001->hdl.error;
 
-	/* Second stage probe - when a capture adapter is there */
-	icd->ops		= &mt9m001_ops;
+		kfree(mt9m001);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure,
+					V4L2_EXPOSURE_MANUAL, true);
 
+	/* Second stage probe - when a capture adapter is there */
 	mt9m001->y_skip_top	= 0;
 	mt9m001->rect.left	= MT9M001_COLUMN_SKIP;
 	mt9m001->rect.top	= MT9M001_ROW_SKIP;
 	mt9m001->rect.width	= MT9M001_MAX_WIDTH;
 	mt9m001->rect.height	= MT9M001_MAX_HEIGHT;
 
-	/*
-	 * Simulated autoexposure. If enabled, we calculate shutter width
-	 * ourselves in the driver based on vertical blanking and frame width
-	 */
-	mt9m001->autoexposure = 1;
-
-	ret = mt9m001_video_probe(icd, client);
+	ret = mt9m001_video_probe(icl, client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9m001->hdl);
 		kfree(mt9m001);
 	}
 
@@ -790,10 +706,11 @@ static int mt9m001_probe(struct i2c_clie
 static int mt9m001_remove(struct i2c_client *client)
 {
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
-	mt9m001_video_remove(icd);
+	v4l2_device_unregister_subdev(&mt9m001->subdev);
+	v4l2_ctrl_handler_free(&mt9m001->hdl);
+	mt9m001_video_remove(icl);
 	kfree(mt9m001);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/mt9m111.c linux-libre-3.2-gnu1/drivers/media/video/mt9m111.c
--- linux-libre-3.1-gnu1/drivers/media/video/mt9m111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu1/drivers/media/video/mt9m111.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,10 +13,13 @@
 #include <linux/log2.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
 
+#include <media/soc_camera.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
 
 /*
  * MT9M111, MT9M112 and MT9M131:
@@ -177,6 +180,8 @@ enum mt9m111_context {
 
 struct mt9m111 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *gain;
 	int model;	/* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
 			 * from v4l2-chip-ident.h */
 	enum mt9m111_context context;
@@ -184,13 +189,9 @@ struct mt9m111 {
 	struct mutex power_lock; /* lock to protect power_count */
 	int power_count;
 	const struct mt9m111_datafmt *fmt;
-	unsigned int gain;
-	unsigned char autoexposure;
+	int lastpage;	/* PageMap cache value */
 	unsigned char datawidth;
 	unsigned int powered:1;
-	unsigned int hflip:1;
-	unsigned int vflip:1;
-	unsigned int autowhitebalance:1;
 };
 
 static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
@@ -202,17 +203,17 @@ static int reg_page_map_set(struct i2c_c
 {
 	int ret;
 	u16 page;
-	static int lastpage = -1;	/* PageMap cache value */
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
 
 	page = (reg >> 8);
-	if (page == lastpage)
+	if (page == mt9m111->lastpage)
 		return 0;
 	if (page > 2)
 		return -EINVAL;
 
 	ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
 	if (!ret)
-		lastpage = page;
+		mt9m111->lastpage = page;
 	return ret;
 }
 
@@ -362,21 +363,6 @@ static int mt9m111_reset(struct mt9m111
 	return ret;
 }
 
-static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
-{
-	return 0;
-}
-
 static int mt9m111_make_rect(struct mt9m111 *mt9m111,
 			     struct v4l2_rect *rect)
 {
@@ -659,50 +645,6 @@ static int mt9m111_s_register(struct v4l
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m111_controls[] = {
-	{
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Verticaly",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_HFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Horizontaly",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {	/* gain = 1/32*val (=>gain=1 if val==32) */
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 63 * 2 * 2,
-		.step		= 1,
-		.default_value	= 32,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Auto Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9m111_ops = {
-	.query_bus_param	= mt9m111_query_bus_param,
-	.set_bus_param		= mt9m111_set_bus_param,
-	.controls		= mt9m111_controls,
-	.num_controls		= ARRAY_SIZE(mt9m111_controls),
-};
-
 static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
@@ -743,7 +685,6 @@ static int mt9m111_set_global_gain(struc
 	if (gain > 63 * 2 * 2)
 		return -EINVAL;
 
-	mt9m111->gain = gain;
 	if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
 		val = (1 << 10) | (1 << 9) | (gain / 4);
 	else if ((gain >= 64) && (gain < 64 * 2))
@@ -757,118 +698,47 @@ static int mt9m111_set_global_gain(struc
 static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-	int ret;
 
 	if (on)
-		ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-	else
-		ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-
-	if (!ret)
-		mt9m111->autoexposure = on;
-
-	return ret;
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 }
 
 static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-	int ret;
 
 	if (on)
-		ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-	else
-		ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-
-	if (!ret)
-		mt9m111->autowhitebalance = on;
-
-	return ret;
-}
-
-static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-	int data;
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		if (mt9m111->context == HIGHPOWER)
-			data = reg_read(READ_MODE_B);
-		else
-			data = reg_read(READ_MODE_A);
-
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS);
-		break;
-	case V4L2_CID_HFLIP:
-		if (mt9m111->context == HIGHPOWER)
-			data = reg_read(READ_MODE_B);
-		else
-			data = reg_read(READ_MODE_A);
-
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
-		break;
-	case V4L2_CID_GAIN:
-		data = mt9m111_get_global_gain(mt9m111);
-		if (data < 0)
-			return data;
-		ctrl->value = data;
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = mt9m111->autoexposure;
-		break;
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ctrl->value = mt9m111->autowhitebalance;
-		break;
-	}
-	return 0;
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
 }
 
-static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-	const struct v4l2_queryctrl *qctrl;
-	int ret;
-
-	qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id);
-	if (!qctrl)
-		return -EINVAL;
+	struct mt9m111 *mt9m111 = container_of(ctrl->handler,
+					       struct mt9m111, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		mt9m111->vflip = ctrl->value;
-		ret = mt9m111_set_flip(mt9m111, ctrl->value,
+		return mt9m111_set_flip(mt9m111, ctrl->val,
 					MT9M111_RMB_MIRROR_ROWS);
-		break;
 	case V4L2_CID_HFLIP:
-		mt9m111->hflip = ctrl->value;
-		ret = mt9m111_set_flip(mt9m111, ctrl->value,
+		return mt9m111_set_flip(mt9m111, ctrl->val,
 					MT9M111_RMB_MIRROR_COLS);
-		break;
 	case V4L2_CID_GAIN:
-		ret = mt9m111_set_global_gain(mt9m111, ctrl->value);
-		break;
+		return mt9m111_set_global_gain(mt9m111, ctrl->val);
 	case V4L2_CID_EXPOSURE_AUTO:
-		ret =  mt9m111_set_autoexposure(mt9m111, ctrl->value);
-		break;
+		return mt9m111_set_autoexposure(mt9m111, ctrl->val);
 	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ret =  mt9m111_set_autowhitebalance(mt9m111, ctrl->value);
-		break;
-	default:
-		ret = -EINVAL;
+		return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int mt9m111_suspend(struct mt9m111 *mt9m111)
 {
-	mt9m111->gain = mt9m111_get_global_gain(mt9m111);
+	v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
 
 	return 0;
 }
@@ -878,11 +748,7 @@ static void mt9m111_restore_state(struct
 	mt9m111_set_context(mt9m111, mt9m111->context);
 	mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
 	mt9m111_setup_rect(mt9m111, &mt9m111->rect);
-	mt9m111_set_flip(mt9m111, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
-	mt9m111_set_flip(mt9m111, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
-	mt9m111_set_global_gain(mt9m111, mt9m111->gain);
-	mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
-	mt9m111_set_autowhitebalance(mt9m111, mt9m111->autowhitebalance);
+	v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_resume(struct mt9m111 *mt9m111)
@@ -910,8 +776,6 @@ static int mt9m111_init(struct mt9m111 *
 		ret = mt9m111_reset(mt9m111);
 	if (!ret)
 		ret = mt9m111_set_context(mt9m111, mt9m111->context);
-	if (!ret)
-		ret = mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
 	if (ret)
 		dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
 	return ret;
@@ -921,20 +785,12 @@ static int mt9m111_init(struct mt9m111 *
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m111_video_probe(struct soc_camera_device *icd,
-			       struct i2c_client *client)
+static int mt9m111_video_probe(struct i2c_client *client)
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
 	s32 data;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
-	mt9m111->autoexposure = 1;
-	mt9m111->autowhitebalance = 1;
-
 	data = reg_read(CHIP_VERSION);
 
 	switch (data) {
@@ -948,17 +804,16 @@ static int mt9m111_video_probe(struct so
 		dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
 		break;
 	default:
-		ret = -ENODEV;
 		dev_err(&client->dev,
 			"No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
 			data);
-		goto ei2c;
+		return -ENODEV;
 	}
 
 	ret = mt9m111_init(mt9m111);
-
-ei2c:
-	return ret;
+	if (ret)
+		return ret;
+	return v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
@@ -995,9 +850,11 @@ out:
 	return ret;
 }
 
+static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
+	.s_ctrl = mt9m111_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
-	.g_ctrl		= mt9m111_g_ctrl,
-	.s_ctrl		= mt9m111_s_ctrl,
 	.g_chip_ident	= mt9m111_g_chip_ident,
 	.s_power	= mt9m111_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1016,6 +873,21 @@ static int mt9m111_enum_fmt(struct v4l2_
 	return 0;
 }
 
+static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
 	.s_mbus_fmt	= mt9m111_s_fmt,
 	.g_mbus_fmt	= mt9m111_g_fmt,
@@ -1024,6 +896,7 @@ static struct v4l2_subdev_video_ops mt9m
 	.g_crop		= mt9m111_g_crop,
 	.cropcap	= mt9m111_cropcap,
 	.enum_mbus_fmt	= mt9m111_enum_fmt,
+	.g_mbus_config	= mt9m111_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops mt9m111_subdev_ops = {
@@ -1035,17 +908,10 @@ static int mt9m111_probe(struct i2c_clie
 			 const struct i2c_device_id *did)
 {
 	struct mt9m111 *mt9m111;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "mt9m111: soc-camera data missing!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "mt9m111: driver needs platform data\n");
 		return -EINVAL;
@@ -1062,19 +928,38 @@ static int mt9m111_probe(struct i2c_clie
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	mt9m111->gain = v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_GAIN, 0, 63 * 2 * 2, 1, 32);
+	v4l2_ctrl_new_std_menu(&mt9m111->hdl,
+			&mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
+	if (mt9m111->hdl.error) {
+		int err = mt9m111->hdl.error;
 
-	/* Second stage probe - when a capture adapter is there */
-	icd->ops		= &mt9m111_ops;
+		kfree(mt9m111);
+		return err;
+	}
 
+	/* Second stage probe - when a capture adapter is there */
 	mt9m111->rect.left	= MT9M111_MIN_DARK_COLS;
 	mt9m111->rect.top	= MT9M111_MIN_DARK_ROWS;
 	mt9m111->rect.width	= MT9M111_MAX_WIDTH;
 	mt9m111->rect.height	= MT9M111_MAX_HEIGHT;
 	mt9m111->fmt		= &mt9m111_colour_fmts[0];
+	mt9m111->lastpage	= -1;
+	mutex_init(&mt9m111->power_lock);
 
-	ret = mt9m111_video_probe(icd, client);
+	ret = mt9m111_video_probe(client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9m111->hdl);
 		kfree(mt9m111);
 	}
 
@@ -1084,9 +969,9 @@ static int mt9m111_probe(struct i2c_clie
 static int mt9m111_remove(struct i2c_client *client)
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
+	v4l2_device_unregister_subdev(&mt9m111->subdev);
+	v4l2_ctrl_handler_free(&mt9m111->hdl);
 	kfree(mt9m111);
 
 	return 0;
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/mt9p031.c linux-libre-3.2-gnu1/drivers/media/video/mt9p031.c
--- linux-libre-3.1-gnu1/drivers/media/video/mt9p031.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/mt9p031.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,964 @@
+/*
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
+ *
+ * Copyright (C) 2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on the MT9V032 driver and Bastian Hecht's code.
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <media/v4l2-subdev.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9p031.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9P031_PIXEL_ARRAY_WIDTH			2752
+#define MT9P031_PIXEL_ARRAY_HEIGHT			2004
+
+#define MT9P031_CHIP_VERSION				0x00
+#define		MT9P031_CHIP_VERSION_VALUE		0x1801
+#define MT9P031_ROW_START				0x01
+#define		MT9P031_ROW_START_MIN			0
+#define		MT9P031_ROW_START_MAX			2004
+#define		MT9P031_ROW_START_DEF			54
+#define MT9P031_COLUMN_START				0x02
+#define		MT9P031_COLUMN_START_MIN		0
+#define		MT9P031_COLUMN_START_MAX		2750
+#define		MT9P031_COLUMN_START_DEF		16
+#define MT9P031_WINDOW_HEIGHT				0x03
+#define		MT9P031_WINDOW_HEIGHT_MIN		2
+#define		MT9P031_WINDOW_HEIGHT_MAX		2006
+#define		MT9P031_WINDOW_HEIGHT_DEF		1944
+#define MT9P031_WINDOW_WIDTH				0x04
+#define		MT9P031_WINDOW_WIDTH_MIN		2
+#define		MT9P031_WINDOW_WIDTH_MAX		2752
+#define		MT9P031_WINDOW_WIDTH_DEF		2592
+#define MT9P031_HORIZONTAL_BLANK			0x05
+#define		MT9P031_HORIZONTAL_BLANK_MIN		0
+#define		MT9P031_HORIZONTAL_BLANK_MAX		4095
+#define MT9P031_VERTICAL_BLANK				0x06
+#define		MT9P031_VERTICAL_BLANK_MIN		0
+#define		MT9P031_VERTICAL_BLANK_MAX		4095
+#define		MT9P031_VERTICAL_BLANK_DEF		25
+#define MT9P031_OUTPUT_CONTROL				0x07
+#define		MT9P031_OUTPUT_CONTROL_CEN		2
+#define		MT9P031_OUTPUT_CONTROL_SYN		1
+#define		MT9P031_OUTPUT_CONTROL_DEF		0x1f82
+#define MT9P031_SHUTTER_WIDTH_UPPER			0x08
+#define MT9P031_SHUTTER_WIDTH_LOWER			0x09
+#define		MT9P031_SHUTTER_WIDTH_MIN		1
+#define		MT9P031_SHUTTER_WIDTH_MAX		1048575
+#define		MT9P031_SHUTTER_WIDTH_DEF		1943
+#define	MT9P031_PLL_CONTROL				0x10
+#define		MT9P031_PLL_CONTROL_PWROFF		0x0050
+#define		MT9P031_PLL_CONTROL_PWRON		0x0051
+#define		MT9P031_PLL_CONTROL_USEPLL		0x0052
+#define	MT9P031_PLL_CONFIG_1				0x11
+#define	MT9P031_PLL_CONFIG_2				0x12
+#define MT9P031_PIXEL_CLOCK_CONTROL			0x0a
+#define MT9P031_FRAME_RESTART				0x0b
+#define MT9P031_SHUTTER_DELAY				0x0c
+#define MT9P031_RST					0x0d
+#define		MT9P031_RST_ENABLE			1
+#define		MT9P031_RST_DISABLE			0
+#define MT9P031_READ_MODE_1				0x1e
+#define MT9P031_READ_MODE_2				0x20
+#define		MT9P031_READ_MODE_2_ROW_MIR		(1 << 15)
+#define		MT9P031_READ_MODE_2_COL_MIR		(1 << 14)
+#define		MT9P031_READ_MODE_2_ROW_BLC		(1 << 6)
+#define MT9P031_ROW_ADDRESS_MODE			0x22
+#define MT9P031_COLUMN_ADDRESS_MODE			0x23
+#define MT9P031_GLOBAL_GAIN				0x35
+#define		MT9P031_GLOBAL_GAIN_MIN			8
+#define		MT9P031_GLOBAL_GAIN_MAX			1024
+#define		MT9P031_GLOBAL_GAIN_DEF			8
+#define		MT9P031_GLOBAL_GAIN_MULT		(1 << 6)
+#define MT9P031_ROW_BLACK_DEF_OFFSET			0x4b
+#define MT9P031_TEST_PATTERN				0xa0
+#define		MT9P031_TEST_PATTERN_SHIFT		3
+#define		MT9P031_TEST_PATTERN_ENABLE		(1 << 0)
+#define		MT9P031_TEST_PATTERN_DISABLE		(0 << 0)
+#define MT9P031_TEST_PATTERN_GREEN			0xa1
+#define MT9P031_TEST_PATTERN_RED			0xa2
+#define MT9P031_TEST_PATTERN_BLUE			0xa3
+
+struct mt9p031_pll_divs {
+	u32 ext_freq;
+	u32 target_freq;
+	u8 m;
+	u8 n;
+	u8 p1;
+};
+
+struct mt9p031 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+	struct v4l2_rect crop;  /* Sensor window */
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_ctrl_handler ctrls;
+	struct mt9p031_platform_data *pdata;
+	struct mutex power_lock; /* lock to protect power_count */
+	int power_count;
+	u16 xskip;
+	u16 yskip;
+
+	const struct mt9p031_pll_divs *pll;
+
+	/* Registers cache */
+	u16 output_control;
+	u16 mode2;
+};
+
+static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9p031, subdev);
+}
+
+static int mt9p031_read(struct i2c_client *client, u8 reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+	return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->output_control & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->output_control = value;
+	return 0;
+}
+
+static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->mode2 & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_READ_MODE_2, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->mode2 = value;
+	return 0;
+}
+
+static int mt9p031_reset(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	/* Disable chip output, synchronous option update */
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN,
+					  0);
+}
+
+/*
+ * This static table uses ext_freq and vdd_io values to select suitable
+ * PLL dividers m, n and p1 which have been calculated as specifiec in p36
+ * of Aptina's mt9p031 datasheet. New values should be added here.
+ */
+static const struct mt9p031_pll_divs mt9p031_divs[] = {
+	/* ext_freq	target_freq	m	n	p1 */
+	{21000000,	48000000,	26,	2,	6}
+};
+
+static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) {
+		if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq &&
+		  mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) {
+			mt9p031->pll = &mt9p031_divs[i];
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, "
+		"target_freq = %d\n", mt9p031->pdata->ext_freq,
+		mt9p031->pdata->target_freq);
+	return -EINVAL;
+}
+
+static int mt9p031_pll_enable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1,
+			    (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1));
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON |
+			    MT9P031_PLL_CONTROL_USEPLL);
+	return ret;
+}
+
+static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+
+	return mt9p031_write(client, MT9P031_PLL_CONTROL,
+			     MT9P031_PLL_CONTROL_PWROFF);
+}
+
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
+{
+	/* Ensure RESET_BAR is low */
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 1);
+		usleep_range(1000, 2000);
+	}
+
+	/* Emable clock */
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev,
+					 mt9p031->pdata->ext_freq);
+
+	/* Now RESET_BAR must be high */
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 0);
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
+{
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 1);
+		usleep_range(1000, 2000);
+	}
+
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
+}
+
+static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	if (!on) {
+		mt9p031_power_off(mt9p031);
+		return 0;
+	}
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_reset(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to reset the camera\n");
+		return ret;
+	}
+
+	return v4l2_ctrl_handler_setup(&mt9p031->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static int mt9p031_set_params(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	struct v4l2_mbus_framefmt *format = &mt9p031->format;
+	const struct v4l2_rect *crop = &mt9p031->crop;
+	unsigned int hblank;
+	unsigned int vblank;
+	unsigned int xskip;
+	unsigned int yskip;
+	unsigned int xbin;
+	unsigned int ybin;
+	int ret;
+
+	/* Windows position and size.
+	 *
+	 * TODO: Make sure the start coordinates and window size match the
+	 * skipping, binning and mirroring (see description of registers 2 and 4
+	 * in table 13, and Binning section on page 41).
+	 */
+	ret = mt9p031_write(client, MT9P031_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Row and column binning and skipping. Use the maximum binning value
+	 * compatible with the skipping settings.
+	 */
+	xskip = DIV_ROUND_CLOSEST(crop->width, format->width);
+	yskip = DIV_ROUND_CLOSEST(crop->height, format->height);
+	xbin = 1 << (ffs(xskip) - 1);
+	ybin = 1 << (ffs(yskip) - 1);
+
+	ret = mt9p031_write(client, MT9P031_COLUMN_ADDRESS_MODE,
+			    ((xbin - 1) << 4) | (xskip - 1));
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_ADDRESS_MODE,
+			    ((ybin - 1) << 4) | (yskip - 1));
+	if (ret < 0)
+		return ret;
+
+	/* Blanking - use minimum value for horizontal blanking and default
+	 * value for vertical blanking.
+	 */
+	hblank = 346 * ybin + 64 + (80 >> max_t(unsigned int, xbin, 3));
+	vblank = MT9P031_VERTICAL_BLANK_DEF;
+
+	ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret;
+
+	if (!enable) {
+		/* Stop sensor readout */
+		ret = mt9p031_set_output_control(mt9p031,
+						 MT9P031_OUTPUT_CONTROL_CEN, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_pll_disable(mt9p031);
+	}
+
+	ret = mt9p031_set_params(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	ret = mt9p031_set_output_control(mt9p031, 0,
+					 MT9P031_OUTPUT_CONTROL_CEN);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_pll_enable(mt9p031);
+}
+
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (code->pad || code->index)
+		return -EINVAL;
+
+	code->code = mt9p031->format.code;
+	return 0;
+}
+
+static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (fse->index >= 8 || fse->code != mt9p031->format.code)
+		return -EINVAL;
+
+	fse->min_width = MT9P031_WINDOW_WIDTH_DEF
+		       / min_t(unsigned int, 7, fse->index + 1);
+	fse->max_width = fse->min_width;
+	fse->min_height = MT9P031_WINDOW_HEIGHT_DEF / (fse->index + 1);
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9p031_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	fmt->format = *__mt9p031_get_pad_format(mt9p031, fh, fmt->pad,
+						fmt->which);
+	return 0;
+}
+
+static int mt9p031_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 7, MT9P031_WINDOW_WIDTH_MIN),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			max(__crop->height / 8, MT9P031_WINDOW_HEIGHT_MIN),
+			__crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9p031_get_pad_format(mt9p031, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9p031_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9p031_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels to ensure a GRBG Bayer pattern.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
+			  MT9P031_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
+			 MT9P031_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9P031_WINDOW_WIDTH_MIN,
+			   MT9P031_WINDOW_WIDTH_MAX);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9P031_WINDOW_HEIGHT_MIN,
+			    MT9P031_WINDOW_HEIGHT_MAX);
+
+	rect.width = min(rect.width, MT9P031_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+
+static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9p031 *mt9p031 =
+			container_of(ctrl->handler, struct mt9p031, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 data;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		ret = mt9p031_write(client, MT9P031_SHUTTER_WIDTH_UPPER,
+				    (ctrl->val >> 16) & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_SHUTTER_WIDTH_LOWER,
+				     ctrl->val & 0xffff);
+
+	case V4L2_CID_GAIN:
+		/* Gain is controlled by 2 analog stages and a digital stage.
+		 * Valid values for the 3 stages are
+		 *
+		 * Stage                Min     Max     Step
+		 * ------------------------------------------
+		 * First analog stage   x1      x2      1
+		 * Second analog stage  x1      x4      0.125
+		 * Digital stage        x1      x16     0.125
+		 *
+		 * To minimize noise, the gain stages should be used in the
+		 * second analog stage, first analog stage, digital stage order.
+		 * Gain from a previous stage should be pushed to its maximum
+		 * value before the next stage is used.
+		 */
+		if (ctrl->val <= 32) {
+			data = ctrl->val;
+		} else if (ctrl->val <= 64) {
+			ctrl->val &= ~1;
+			data = (1 << 6) | (ctrl->val >> 1);
+		} else {
+			ctrl->val &= ~7;
+			data = ((ctrl->val - 64) << 5) | (1 << 6) | 32;
+		}
+
+		return mt9p031_write(client, MT9P031_GLOBAL_GAIN, data);
+
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_COL_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_COL_MIR, 0);
+
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_ROW_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_ROW_MIR, 0);
+
+	case V4L2_CID_TEST_PATTERN:
+		if (!ctrl->val) {
+			ret = mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_ROW_BLC);
+			if (ret < 0)
+				return ret;
+
+			return mt9p031_write(client, MT9P031_TEST_PATTERN,
+					     MT9P031_TEST_PATTERN_DISABLE);
+		}
+
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_RED, 0x0a50);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_BLUE, 0x0aa0);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC,
+					0);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_ROW_BLACK_DEF_OFFSET, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_TEST_PATTERN,
+				((ctrl->val - 1) << MT9P031_TEST_PATTERN_SHIFT)
+				| MT9P031_TEST_PATTERN_ENABLE);
+	}
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9p031_ctrl_ops = {
+	.s_ctrl = mt9p031_s_ctrl,
+};
+
+static const char * const mt9p031_test_pattern_menu[] = {
+	"Disabled",
+	"Color Field",
+	"Horizontal Gradient",
+	"Vertical Gradient",
+	"Diagonal Gradient",
+	"Classic Test Pattern",
+	"Walking 1s",
+	"Monochrome Horizontal Bars",
+	"Monochrome Vertical Bars",
+	"Vertical Color Bars",
+};
+
+static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
+	{
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Test Pattern",
+		.min		= 0,
+		.max		= ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.menu_skip_mask	= 0,
+		.qmenu		= mt9p031_test_pattern_menu,
+	}
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int mt9p031_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret = 0;
+
+	mutex_lock(&mt9p031->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (mt9p031->power_count == !on) {
+		ret = __mt9p031_set_power(mt9p031, !!on);
+		if (ret < 0)
+			goto out;
+	}
+
+	/* Update the power count. */
+	mt9p031->power_count += on ? 1 : -1;
+	WARN_ON(mt9p031->power_count < 0);
+
+out:
+	mutex_unlock(&mt9p031->power_lock);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9p031_registered(struct v4l2_subdev *subdev)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	s32 data;
+	int ret;
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "MT9P031 power up failed\n");
+		return ret;
+	}
+
+	/* Read out the chip version register */
+	data = mt9p031_read(client, MT9P031_CHIP_VERSION);
+	if (data != MT9P031_CHIP_VERSION_VALUE) {
+		dev_err(&client->dev, "MT9P031 not detected, wrong version "
+			"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	mt9p031_power_off(mt9p031);
+
+	dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
+		 client->addr);
+
+	return ret;
+}
+
+static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9P031_COLUMN_START_DEF;
+	crop->top = MT9P031_ROW_START_DEF;
+	crop->width = MT9P031_WINDOW_WIDTH_DEF;
+	crop->height = MT9P031_WINDOW_HEIGHT_DEF;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+
+	if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+		format->code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	format->width = MT9P031_WINDOW_WIDTH_DEF;
+	format->height = MT9P031_WINDOW_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	mt9p031->xskip = 1;
+	mt9p031->yskip = 1;
+	return mt9p031_set_power(subdev, 1);
+}
+
+static int mt9p031_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return mt9p031_set_power(subdev, 0);
+}
+
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
+	.s_power        = mt9p031_set_power,
+};
+
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
+	.s_stream       = mt9p031_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
+	.enum_mbus_code = mt9p031_enum_mbus_code,
+	.enum_frame_size = mt9p031_enum_frame_size,
+	.get_fmt = mt9p031_get_format,
+	.set_fmt = mt9p031_set_format,
+	.get_crop = mt9p031_get_crop,
+	.set_crop = mt9p031_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
+	.core   = &mt9p031_subdev_core_ops,
+	.video  = &mt9p031_subdev_video_ops,
+	.pad    = &mt9p031_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
+	.registered = mt9p031_registered,
+	.open = mt9p031_open,
+	.close = mt9p031_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9p031_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9p031_platform_data *pdata = client->dev.platform_data;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct mt9p031 *mt9p031;
+	unsigned int i;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->dev,
+			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9p031 = kzalloc(sizeof(*mt9p031), GFP_KERNEL);
+	if (mt9p031 == NULL)
+		return -ENOMEM;
+
+	mt9p031->pdata = pdata;
+	mt9p031->output_control	= MT9P031_OUTPUT_CONTROL_DEF;
+	mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
+
+	v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4);
+
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
+			  MT9P031_SHUTTER_WIDTH_MAX, 1,
+			  MT9P031_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_GAIN, MT9P031_GLOBAL_GAIN_MIN,
+			  MT9P031_GLOBAL_GAIN_MAX, 1, MT9P031_GLOBAL_GAIN_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
+
+	mt9p031->subdev.ctrl_handler = &mt9p031->ctrls;
+
+	if (mt9p031->ctrls.error)
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9p031->ctrls.error);
+
+	mutex_init(&mt9p031->power_lock);
+	v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
+	mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
+
+	mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
+	if (ret < 0)
+		goto done;
+
+	mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9p031->crop.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->crop.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->crop.left = MT9P031_COLUMN_START_DEF;
+	mt9p031->crop.top = MT9P031_ROW_START_DEF;
+
+	if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+		mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->format.field = V4L2_FIELD_NONE;
+	mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	ret = mt9p031_pll_get_divs(mt9p031);
+
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&mt9p031->ctrls);
+		media_entity_cleanup(&mt9p031->subdev.entity);
+		kfree(mt9p031);
+	}
+
+	return ret;
+}
+
+static int mt9p031_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	v4l2_ctrl_handler_free(&mt9p031->ctrls);
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	kfree(mt9p031);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9p031_id[] = {
+	{ "mt9p031", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
+
+static struct i2c_driver mt9p031_i2c_driver = {
+	.driver = {
+		.name = "mt9p031",
+	},
+	.probe          = mt9p031_probe,
+	.remove         = mt9p031_remove,
+	.id_table       = mt9p031_id,
+};
+
+static int __init mt9p031_mod_init(void)
+{
+	return i2c_add_driver(&mt9p031_i2c_driver);
+}
+
+static void __exit mt9p031_mod_exit(void)
+{
+	i2c_del_driver(&mt9p031_i2c_driver);
+}
+
+module_init(mt9p031_mod_init);
+module_exit(mt9p031_mod_exit);
+
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.1-gnu1/drivers/media/video/mt9t001.c linux-libre-3.2-gnu1/drivers/media/video/mt9t001.c
--- linux-libre-3.1-gnu1/drivers/media/video/mt9t001.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu1/drivers/media/video/mt9t001.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,836 @@
+/*
+ * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
+ *
+ * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on the MT9M001 driver,
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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/i2c.h>
+#include <linux/module.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/mt9t001.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9T001_PIXEL_ARRAY_HEIGHT			1568
+#define MT9T001_PIXEL_ARRAY_WIDTH			2112
+
+#define MT9T001_CHIP_VERSION				0x00
+#define		MT9T001_CHIP_ID				0x1621
+#define MT9T001_ROW_START				0x01
+#define		MT9T001_ROW_START_MIN			0
+#define		MT9T001_ROW_START_DEF			20
+#define		MT9T001_ROW_START_MAX			1534
+#define MT9T001_COLUMN_START				0x02
+#define		MT9T001_COLUMN_START_MIN		0
+#define		MT9T001_COLUMN_START_DEF		32
+#define		MT9T001_COLUMN_START_MAX		2046
+#define MT9T001_WINDOW_HEIGHT				0x03
+#define		MT9T001_WINDOW_HEIGHT_MIN		1
+#define		MT9T001_WINDOW_HEIGHT_DEF		1535
+#define		MT9T001_WINDOW_HEIGHT_MAX		1567
+#define MT9T001_WINDOW_WIDTH				0x04
+#define		MT9T001_WINDOW_WIDTH_MIN		1
+#define		MT9T001_WINDOW_WIDTH_DEF		2047
+#define		MT9T001_WINDOW_WIDTH_MAX		2111
+#define MT9T001_HORIZONTAL_BLANKING			0x05
+#define		MT9T001_HORIZONTAL_BLANKING_MIN		21
+#define		MT9T001_HORIZONTAL_BLANKING_MAX		1023
+#define MT9T001_VERTICAL_BLANKING			0x06
+#define		MT9T001_VERTICAL_BLANKING_MIN		3
+#define		MT9T001_VERTICAL_BLANKING_MAX		1023
+#define MT9T001_OUTPUT_CONTROL				0x07
+#define		MT9T001_OUTPUT_CONTROL_SYNC		(1 << 0)
+#define		MT9T001_OUTPUT_CONTROL_CHIP_ENABLE	(1 << 1)
+#define		MT9T001_OUTPUT_CONTROL_TEST_DATA	(1 << 6)
+#define MT9T001_SHUTTER_WIDTH_HIGH			0x08
+#define MT9T001_SHUTTER_WIDTH_LOW			0x09
+#define		MT9T001_SHUTTER_WIDTH_MIN		1
+#define		MT9T001_SHUTTER_WIDTH_DEF		1561
+#define		MT9T001_SHUTTER_WIDTH_MAX		(1024 * 1024)
+#define MT9T001_PIXEL_CLOCK				0x0a
+#define		MT9T001_PIXEL_CLOCK_INVERT		(1 << 15)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_MASK		(7 << 8)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_SHIFT		8
+#define		MT9T001_PIXEL_CLOCK_DIVIDE_MASK		(0x7f << 0)
+#define MT9T001_FRAME_RESTART				0x0b
+#define MT9T001_SHUTTER_DELAY				0x0c
+#define		MT9T001_SHUTTER_DELAY_MAX		2047
+#define MT9T001_RESET					0x0d
+#define MT9T001_READ_MODE1				0x1e
+#define		MT9T001_READ_MODE_SNAPSHOT		(1 << 8)
+#define		MT9T001_READ_MODE_STROBE_ENABLE		(1 << 9)
+#define		MT9T001_READ_MODE_STROBE_WIDTH		(1 << 10)
+#define		MT9T001_READ_MODE_STROBE_OVERRIDE	(1 << 11)
+#define MT9T001_READ_MODE2				0x20
+#define		MT9T001_READ_MODE_BAD_FRAMES		(1 << 0)
+#define		MT9T001_READ_MODE_LINE_VALID_CONTINUOUS	(1 << 9)
+#define		MT9T001_READ_MODE_LINE_VALID_FRAME	(1 << 10)
+#define MT9T001_READ_MODE3				0x21
+#define		MT9T001_READ_MODE_GLOBAL_RESET		(1 << 0)
+#define		MT9T001_READ_MODE_GHST_CTL		(1 << 1)
+#define MT9T001_ROW_ADDRESS_MODE			0x22
+#define		MT9T001_ROW_SKIP_MASK			(7 << 0)
+#define		MT9T001_ROW_BIN_MASK			(3 << 3)
+#define		MT9T001_ROW_BIN_SHIFT			3
+#define MT9T001_COLUMN_ADDRESS_MODE			0x23
+#define		MT9T001_COLUMN_SKIP_MASK		(7 << 0)
+#define		MT9T001_COLUMN_BIN_MASK			(3 << 3)
+#define		MT9T001_COLUMN_BIN_SHIFT		3
+#define MT9T001_GREEN1_GAIN				0x2b
+#define MT9T001_BLUE_GAIN				0x2c
+#define MT9T001_RED_GAIN				0x2d
+#define MT9T001_GREEN2_GAIN				0x2e
+#define MT9T001_TEST_DATA				0x32
+#define MT9T001_GLOBAL_GAIN				0x35
+#define		MT9T001_GLOBAL_GAIN_MIN			8
+#define		MT9T001_GLOBAL_GAIN_MAX			1024
+#define MT9T001_BLACK_LEVEL				0x49
+#define MT9T001_ROW_BLACK_DEFAULT_OFFSET		0x4b
+#define MT9T001_BLC_DELTA_THRESHOLDS			0x5d
+#define MT9T001_CAL_THRESHOLDS				0x5f
+#define MT9T001_GREEN1_OFFSET				0x60
+#define MT9T001_GREEN2_OFFSET				0x61
+#define MT9T001_BLACK_LEVEL_CALIBRATION			0x62
+#define		MT9T001_BLACK_LEVEL_OVERRIDE		(1 << 0)
+#define		MT9T001_BLACK_LEVEL_DISABLE_OFFSET	(1 << 1)
+#define		MT9T001_BLACK_LEVEL_RECALCULATE		(1 << 12)
+#define		MT9T001_BLACK_LEVEL_LOCK_RED_BLUE	(1 << 13)
+#define		MT9T001_BLACK_LEVEL_LOCK_GREEN		(1 << 14)
+#define MT9T001_RED_OFFSET				0x63
+#define MT9T001_BLUE_OFFSET				0x64
+
+struct mt9t001 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_rect crop;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *gains[4];
+
+	u16 output_control;
+	u16 black_level;
+};
+
+static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9t001, subdev);
+}
+
+static int mt9t001_read(struct i2c_client *client, u8 reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+	return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+	u16 value = (mt9t001->output_control & ~clear) | set;
+	int ret;
+
+	if (value == mt9t001->output_control)
+		return 0;
+
+	ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9t001->output_control = value;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+		       unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *format = &mt9t001->format;
+	struct v4l2_rect *crop = &mt9t001->crop;
+	unsigned int hratio;
+	unsigned int vratio;
+	int ret;
+
+	if (!enable)
+		return mt9t001_set_output_control(mt9t001, mode, 0);
+
+	/* Configure the window size and row/column bin */
+	hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
+	vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
+
+	ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	return mt9t001_set_output_control(mt9t001, 0, mode);
+}
+
+static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index > 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	return 0;
+}
+
+static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
+		return -EINVAL;
+
+	fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
+	fse->max_width = fse->min_width;
+	fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static int mt9t001_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	format->format = *__mt9t001_get_pad_format(mt9t001, fh, format->pad,
+						   format->which);
+	return 0;
+}
+
+static int mt9t001_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			 max(__crop->height / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			 __crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9t001_get_pad_format(mt9t001, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9t001_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9t001_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels